dwflmodtest.c revision cc6695e2684ce93cdf8bd2da63d55d2cf49ff076
1/* Test program for libdwfl basic module tracking, relocation.
2   Copyright (C) 2005, 2007 Red Hat, Inc.
3   This file is part of Red Hat elfutils.
4
5   Red Hat elfutils is free software; you can redistribute it and/or modify
6   it under the terms of the GNU General Public License as published by the
7   Free Software Foundation; version 2 of the License.
8
9   Red Hat elfutils is distributed in the hope that it will be useful, but
10   WITHOUT ANY WARRANTY; without even the implied warranty of
11   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
12   General Public License for more details.
13
14   You should have received a copy of the GNU General Public License along
15   with Red Hat elfutils; if not, write to the Free Software Foundation,
16   Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301 USA.
17
18   Red Hat elfutils is an included package of the Open Invention Network.
19   An included package of the Open Invention Network is a package for which
20   Open Invention Network licensees cross-license their patents.  No patent
21   license is granted, either expressly or impliedly, by designation as an
22   included package.  Should you wish to participate in the Open Invention
23   Network licensing program, please visit www.openinventionnetwork.com
24   <http://www.openinventionnetwork.com>.  */
25
26#include <config.h>
27#include <assert.h>
28#include <inttypes.h>
29#include <sys/types.h>
30#include <stdio.h>
31#include <stdio_ext.h>
32#include <stdlib.h>
33#include <string.h>
34#include <error.h>
35#include <locale.h>
36#include <argp.h>
37#include ELFUTILS_HEADER(dwfl)
38#include <dwarf.h>
39
40static bool show_inlines;
41
42struct info
43{
44  Dwarf_Die *cudie;
45  Dwarf_Addr dwbias;
46};
47
48static int
49print_instance (Dwarf_Die *instance, void *arg)
50{
51  const struct info *info = arg;
52
53  printf ("    inlined");
54
55  Dwarf_Files *files;
56  if (dwarf_getsrcfiles (info->cudie, &files, NULL) == 0)
57    {
58      Dwarf_Attribute attr_mem;
59      Dwarf_Word val;
60      if (dwarf_formudata (dwarf_attr (instance, DW_AT_call_file,
61				       &attr_mem), &val) == 0)
62	{
63	  const char *file = dwarf_filesrc (files, val, NULL, NULL);
64	  int lineno = 0, colno = 0;
65	  if (dwarf_formudata (dwarf_attr (instance, DW_AT_call_line,
66					   &attr_mem), &val) == 0)
67	    lineno = val;
68	  if (dwarf_formudata (dwarf_attr (instance, DW_AT_call_column,
69					   &attr_mem), &val) == 0)
70	    colno = val;
71	  if (lineno == 0)
72	    {
73	      if (file != NULL)
74		printf (" from %s", file);
75	    }
76	  else if (colno == 0)
77	    printf (" at %s:%u", file, lineno);
78	  else
79	    printf (" at %s:%u:%u", file, lineno, colno);
80	}
81    }
82
83  Dwarf_Addr lo = -1, hi = -1, entry = -1;
84  if (dwarf_lowpc (instance, &lo) == 0)
85    lo += info->dwbias;
86  else
87    printf (" (lowpc => %s)", dwarf_errmsg (-1));
88  if (dwarf_highpc (instance, &hi) == 0)
89    hi += info->dwbias;
90  else
91    printf (" (highpc => %s)", dwarf_errmsg (-1));
92
93  Dwarf_Attribute attr_mem;
94  Dwarf_Attribute *attr = dwarf_attr (instance, DW_AT_entry_pc, &attr_mem);
95  if (attr != NULL)
96    {
97      if (dwarf_formaddr (attr, &entry) == 0)
98	entry += info->dwbias;
99      else
100	printf (" (entrypc => %s)", dwarf_errmsg (-1));
101    }
102
103  if (lo != (Dwarf_Addr) -1 || hi != (Dwarf_Addr) -1)
104    printf (" %#" PRIx64 "..%#" PRIx64, lo, hi);
105  if (entry != (Dwarf_Addr) -1)
106    printf (" => %#" PRIx64 "\n", entry);
107  else
108    puts ("");
109
110  return DWARF_CB_OK;
111}
112
113static void
114print_inline (Dwarf_Die *func, void *arg)
115{
116  if (dwarf_func_inline_instances (func, &print_instance, arg) != 0)
117    printf ("  error finding instances: %s\n", dwarf_errmsg (-1));
118}
119
120static int
121print_func (Dwarf_Die *func, void *arg)
122{
123  const struct info *info = arg;
124
125  const char *file = dwarf_decl_file (func);
126  int line = -1;
127  dwarf_decl_line (func, &line);
128  const char *fct = dwarf_diename (func);
129
130  printf ("  %s:%d: %s:", file, line, fct);
131
132  if (dwarf_func_inline (func))
133    {
134      puts (" inline function");
135      if (show_inlines)
136	print_inline (func, arg);
137    }
138  else
139    {
140      Dwarf_Addr lo = -1, hi = -1, entry = -1;
141      if (dwarf_lowpc (func, &lo) == 0)
142	lo += info->dwbias;
143      else
144	printf (" (lowpc => %s)", dwarf_errmsg (-1));
145      if (dwarf_highpc (func, &hi) == 0)
146	hi += info->dwbias;
147      else
148	printf (" (highpc => %s)", dwarf_errmsg (-1));
149      if (dwarf_entrypc (func, &entry) == 0)
150	entry += info->dwbias;
151      else
152	printf (" (entrypc => %s)", dwarf_errmsg (-1));
153
154      if (lo != (Dwarf_Addr) -1 || hi != (Dwarf_Addr) -1
155	  || entry != (Dwarf_Addr) -1)
156	printf (" %#" PRIx64 "..%#" PRIx64 " => %#" PRIx64 "\n",
157		lo, hi, entry);
158      else
159	puts ("");
160    }
161
162  return DWARF_CB_OK;
163}
164
165static int
166list_module (Dwfl_Module *mod __attribute__ ((unused)),
167	     void **userdata __attribute__ ((unused)),
168	     const char *name, Dwarf_Addr base,
169	     void *arg __attribute__ ((unused)))
170{
171  Dwarf_Addr start;
172  Dwarf_Addr end;
173  const char *file;
174  const char *debug;
175  if (dwfl_module_info (mod, NULL, &start, &end,
176			NULL, NULL, &file, &debug) != name
177      || start != base)
178    abort ();
179  printf ("module: %30s %08" PRIx64 "..%08" PRIx64 " %s %s\n",
180	  name, start, end, file, debug);
181  return DWARF_CB_OK;
182}
183
184static int
185print_module (Dwfl_Module *mod __attribute__ ((unused)),
186	      void **userdata __attribute__ ((unused)),
187	      const char *name, Dwarf_Addr base,
188	      Dwarf *dw, Dwarf_Addr bias,
189	      void *arg)
190{
191  printf ("module: %30s %08" PRIx64 " %s %" PRIx64 " (%s)\n",
192	  name, base, dw == NULL ? "no" : "DWARF", bias, dwfl_errmsg (-1));
193
194  if (dw != NULL && *(const bool *) arg)
195    {
196      Dwarf_Off off = 0;
197      size_t cuhl;
198      Dwarf_Off noff;
199
200      while (dwarf_nextcu (dw, off, &noff, &cuhl, NULL, NULL, NULL) == 0)
201	{
202	  Dwarf_Die die_mem;
203	  struct info info = { dwarf_offdie (dw, off + cuhl, &die_mem), bias };
204	  (void) dwarf_getfuncs (info.cudie, print_func, &info, 0);
205
206	  off = noff;
207	}
208    }
209
210  return DWARF_CB_OK;
211}
212
213static bool show_functions;
214
215/* gettext helper macro.  */
216#undef	N_
217#define N_(Str) Str
218
219static const struct argp_option options[] =
220  {
221    { "functions", 'f', NULL, 0, N_("Additionally show function names"), 0 },
222    { "inlines", 'i', NULL, 0, N_("Show instances of inlined functions"), 0 },
223    { NULL, 0, NULL, 0, NULL, 0 }
224  };
225
226static error_t
227parse_opt (int key, char *arg __attribute__ ((unused)),
228	   struct argp_state *state __attribute__ ((unused)))
229{
230  switch (key)
231    {
232    case ARGP_KEY_INIT:
233      state->child_inputs[0] = state->input;
234      break;
235
236    case 'f':
237      show_functions = true;
238      break;
239
240    case 'i':
241      show_inlines = show_functions = true;
242      break;
243
244    default:
245      return ARGP_ERR_UNKNOWN;
246    }
247  return 0;
248}
249
250int
251main (int argc, char **argv)
252{
253  /* We use no threads here which can interfere with handling a stream.  */
254  (void) __fsetlocking (stdout, FSETLOCKING_BYCALLER);
255
256  /* Set locale.  */
257  (void) setlocale (LC_ALL, "");
258
259  Dwfl *dwfl = NULL;
260  const struct argp_child argp_children[] =
261    {
262      { .argp = dwfl_standard_argp () },
263      { .argp = NULL }
264    };
265  const struct argp argp =
266    {
267      options, parse_opt, NULL, NULL, argp_children, NULL, NULL
268    };
269  (void) argp_parse (&argp, argc, argv, 0, NULL, &dwfl);
270  assert (dwfl != NULL);
271
272  ptrdiff_t p = 0;
273  do
274    p = dwfl_getmodules (dwfl, &list_module, NULL, p);
275  while (p > 0);
276  if (p < 0)
277    error (2, 0, "dwfl_getmodules: %s", dwfl_errmsg (-1));
278
279  do
280    p = dwfl_getdwarf (dwfl, &print_module, &show_functions, p);
281  while (p > 0);
282  if (p < 0)
283    error (2, 0, "dwfl_getdwarf: %s", dwfl_errmsg (-1));
284
285  p = 0;
286  do
287    p = dwfl_getmodules (dwfl, &list_module, NULL, p);
288  while (p > 0);
289  if (p < 0)
290    error (2, 0, "dwfl_getmodules: %s", dwfl_errmsg (-1));
291
292  dwfl_end (dwfl);
293
294  return 0;
295}
296