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
print_instance(Dwarf_Die * instance,void * arg)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
print_inline(Dwarf_Die * func,void * arg)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
print_func(Dwarf_Die * func,void * arg)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
list_module(Dwfl_Module * mod,void ** userdata,const char * name,Dwarf_Addr base,void * arg)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
print_module(Dwfl_Module * mod,void ** userdata,const char * name,Dwarf_Addr base,Dwarf * dw,Dwarf_Addr bias,void * arg)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
parse_opt(int key,char * arg,struct argp_state * state)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
main(int argc,char ** argv)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 }
296