94f960faffda0b6cb0fa41d9502597de3495f9fb
[platform/upstream/elfutils.git] / tests / dwflmodtest.c
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
40 static bool show_inlines;
41
42 struct info
43 {
44   Dwarf_Die *cudie;
45   Dwarf_Addr dwbias;
46 };
47
48 static int
49 print_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
113 static void
114 print_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
120 static int
121 print_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
165 static int
166 list_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
184 static int
185 print_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
213 static bool show_functions;
214
215 /* gettext helper macro.  */
216 #undef  N_
217 #define N_(Str) Str
218
219 static 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
226 static error_t
227 parse_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
250 int
251 main (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 }