Branch data Line data Source code
1 : : /* Locate source files and line information for given addresses
2 : : Copyright (C) 2005-2010, 2012, 2013, 2015 Red Hat, Inc.
3 : : This file is part of elfutils.
4 : : Written by Ulrich Drepper <drepper@redhat.com>, 2005.
5 : :
6 : : This file is free software; you can redistribute it and/or modify
7 : : it under the terms of the GNU General Public License as published by
8 : : the Free Software Foundation; either version 3 of the License, or
9 : : (at your option) any later version.
10 : :
11 : : elfutils is distributed in the hope that it will be useful, but
12 : : WITHOUT ANY WARRANTY; without even the implied warranty of
13 : : MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 : : GNU General Public License for more details.
15 : :
16 : : You should have received a copy of the GNU General Public License
17 : : along with this program. If not, see <http://www.gnu.org/licenses/>. */
18 : :
19 : : #ifdef HAVE_CONFIG_H
20 : : # include <config.h>
21 : : #endif
22 : :
23 : : #include <argp.h>
24 : : #include <assert.h>
25 : : #include <errno.h>
26 : : #include <fcntl.h>
27 : : #include <inttypes.h>
28 : : #include <libdwfl.h>
29 : : #include <dwarf.h>
30 : : #include <libintl.h>
31 : : #include <locale.h>
32 : : #include <stdbool.h>
33 : : #include <stdio.h>
34 : : #include <stdio_ext.h>
35 : : #include <stdlib.h>
36 : : #include <string.h>
37 : : #include <unistd.h>
38 : :
39 : : #include <system.h>
40 : : #include <printversion.h>
41 : :
42 : :
43 : : /* Name and version of program. */
44 : : ARGP_PROGRAM_VERSION_HOOK_DEF = print_version;
45 : :
46 : : /* Bug report address. */
47 : : ARGP_PROGRAM_BUG_ADDRESS_DEF = PACKAGE_BUGREPORT;
48 : :
49 : :
50 : : /* Values for the parameters which have no short form. */
51 : : #define OPT_DEMANGLER 0x100
52 : : #define OPT_PRETTY 0x101 /* 'p' is already used to select the process. */
53 : :
54 : : /* Definitions of arguments for argp functions. */
55 : : static const struct argp_option options[] =
56 : : {
57 : : { NULL, 0, NULL, 0, N_("Input format options:"), 2 },
58 : : { "section", 'j', "NAME", 0,
59 : : N_("Treat addresses as offsets relative to NAME section."), 0 },
60 : :
61 : : { NULL, 0, NULL, 0, N_("Output format options:"), 3 },
62 : : { "addresses", 'a', NULL, 0, N_("Print address before each entry"), 0 },
63 : : { "basenames", 's', NULL, 0, N_("Show only base names of source files"), 0 },
64 : : { "absolute", 'A', NULL, 0,
65 : : N_("Show absolute file names using compilation directory"), 0 },
66 : : { "functions", 'f', NULL, 0, N_("Also show function names"), 0 },
67 : : { "symbols", 'S', NULL, 0, N_("Also show symbol or section names"), 0 },
68 : : { "symbols-sections", 'x', NULL, 0, N_("Also show symbol and the section names"), 0 },
69 : : { "flags", 'F', NULL, 0, N_("Also show line table flags"), 0 },
70 : : { "inlines", 'i', NULL, 0,
71 : : N_("Show all source locations that caused inline expansion of subroutines at the address."),
72 : : 0 },
73 : : { "demangle", 'C', "ARG", OPTION_ARG_OPTIONAL,
74 : : N_("Show demangled symbols (ARG is always ignored)"), 0 },
75 : : { "pretty-print", OPT_PRETTY, NULL, 0,
76 : : N_("Print all information on one line, and indent inlines"), 0 },
77 : :
78 : : { NULL, 0, NULL, 0, N_("Miscellaneous:"), 0 },
79 : : /* Unsupported options. */
80 : : { "target", 'b', "ARG", OPTION_HIDDEN, NULL, 0 },
81 : : { "demangler", OPT_DEMANGLER, "ARG", OPTION_HIDDEN, NULL, 0 },
82 : : { NULL, 0, NULL, 0, NULL, 0 }
83 : : };
84 : :
85 : : /* Short description of program. */
86 : : static const char doc[] = N_("\
87 : : Locate source files and line information for ADDRs (in a.out by default).");
88 : :
89 : : /* Strings for arguments in help texts. */
90 : : static const char args_doc[] = N_("[ADDR...]");
91 : :
92 : : /* Prototype for option handler. */
93 : : static error_t parse_opt (int key, char *arg, struct argp_state *state);
94 : :
95 : : static struct argp_child argp_children[2]; /* [0] is set in main. */
96 : :
97 : : /* Data structure to communicate with argp functions. */
98 : : static const struct argp argp =
99 : : {
100 : : options, parse_opt, args_doc, doc, argp_children, NULL, NULL
101 : : };
102 : :
103 : :
104 : : /* Handle ADDR. */
105 : : static int handle_address (const char *addr, Dwfl *dwfl);
106 : :
107 : : /* True when we should print the address for each entry. */
108 : : static bool print_addresses;
109 : :
110 : : /* True if only base names of files should be shown. */
111 : : static bool only_basenames;
112 : :
113 : : /* True if absolute file names based on DW_AT_comp_dir should be shown. */
114 : : static bool use_comp_dir;
115 : :
116 : : /* True if line flags should be shown. */
117 : : static bool show_flags;
118 : :
119 : : /* True if function names should be shown. */
120 : : static bool show_functions;
121 : :
122 : : /* True if ELF symbol or section info should be shown. */
123 : : static bool show_symbols;
124 : :
125 : : /* True if section associated with a symbol address should be shown. */
126 : : static bool show_symbol_sections;
127 : :
128 : : /* If non-null, take address parameters as relative to named section. */
129 : : static const char *just_section;
130 : :
131 : : /* True if all inlined subroutines of the current address should be shown. */
132 : : static bool show_inlines;
133 : :
134 : : /* True if all names need to be demangled. */
135 : : static bool demangle;
136 : :
137 : : /* True if all information should be printed on one line. */
138 : : static bool pretty;
139 : :
140 : : #ifdef USE_DEMANGLE
141 : : static size_t demangle_buffer_len = 0;
142 : : static char *demangle_buffer = NULL;
143 : : #endif
144 : :
145 : : int
146 : 52 : main (int argc, char *argv[])
147 : : {
148 : 52 : int remaining;
149 : 52 : int result = 0;
150 : :
151 : : /* We use no threads here which can interfere with handling a stream. */
152 : 52 : (void) __fsetlocking (stdout, FSETLOCKING_BYCALLER);
153 : :
154 : : /* Set locale. */
155 : 52 : (void) setlocale (LC_ALL, "");
156 : :
157 : : /* Make sure the message catalog can be found. */
158 : 52 : (void) bindtextdomain (PACKAGE_TARNAME, LOCALEDIR);
159 : :
160 : : /* Initialize the message catalog. */
161 : 52 : (void) textdomain (PACKAGE_TARNAME);
162 : :
163 : : /* Parse and process arguments. This includes opening the modules. */
164 : 52 : argp_children[0].argp = dwfl_standard_argp ();
165 : 52 : argp_children[0].group = 1;
166 : 52 : Dwfl *dwfl = NULL;
167 : 52 : (void) argp_parse (&argp, argc, argv, 0, &remaining, &dwfl);
168 [ - + ]: 52 : assert (dwfl != NULL);
169 : :
170 : : /* Now handle the addresses. In case none are given on the command
171 : : line, read from stdin. */
172 [ + + ]: 52 : if (remaining == argc)
173 : : {
174 : : /* We use no threads here which can interfere with handling a stream. */
175 : 4 : (void) __fsetlocking (stdin, FSETLOCKING_BYCALLER);
176 : :
177 : 4 : char *buf = NULL;
178 : 4 : size_t len = 0;
179 : 4 : ssize_t chars;
180 [ + + ][ + + ]: 40 : while (!feof_unlocked (stdin))
181 : : {
182 [ + + ]: 20 : if ((chars = getline (&buf, &len, stdin)) < 0)
183 : : break;
184 : :
185 [ + + ]: 18 : if (buf[chars - 1] == '\n')
186 : 16 : buf[chars - 1] = '\0';
187 : :
188 : 18 : result = handle_address (buf, dwfl);
189 : 18 : fflush (stdout);
190 : : }
191 : :
192 : 4 : free (buf);
193 : : }
194 : : else
195 : : {
196 : 193 : do
197 : 193 : result = handle_address (argv[remaining], dwfl);
198 [ + + ]: 193 : while (++remaining < argc);
199 : : }
200 : :
201 : 52 : dwfl_end (dwfl);
202 : :
203 : : #ifdef USE_DEMANGLE
204 : 52 : free (demangle_buffer);
205 : : #endif
206 : :
207 : 52 : return result;
208 : : }
209 : :
210 : :
211 : : /* Handle program arguments. */
212 : : static error_t
213 : 328 : parse_opt (int key, char *arg, struct argp_state *state)
214 : : {
215 [ + + + - : 328 : switch (key)
- + - + +
- + + + ]
216 : : {
217 : 52 : case ARGP_KEY_INIT:
218 : 52 : state->child_inputs[0] = state->input;
219 : 52 : break;
220 : :
221 : 6 : case 'a':
222 : 6 : print_addresses = true;
223 : 6 : break;
224 : :
225 : 1 : case 'b':
226 : : case 'C':
227 : : case OPT_DEMANGLER:
228 : 1 : demangle = true;
229 : 1 : break;
230 : :
231 : 0 : case 's':
232 : 0 : only_basenames = true;
233 : 0 : break;
234 : :
235 : 0 : case 'A':
236 : 0 : use_comp_dir = true;
237 : 0 : break;
238 : :
239 : 14 : case 'f':
240 : 14 : show_functions = true;
241 : 14 : break;
242 : :
243 : 0 : case 'F':
244 : 0 : show_flags = true;
245 : 0 : break;
246 : :
247 : 22 : case 'S':
248 : 22 : show_symbols = true;
249 : 22 : break;
250 : :
251 : 2 : case 'x':
252 : 2 : show_symbols = true;
253 : 2 : show_symbol_sections = true;
254 : 2 : break;
255 : :
256 : 0 : case 'j':
257 : 0 : just_section = arg;
258 : 0 : break;
259 : :
260 : 20 : case 'i':
261 : 20 : show_inlines = true;
262 : 20 : break;
263 : :
264 : 3 : case OPT_PRETTY:
265 : 3 : pretty = true;
266 : 3 : break;
267 : :
268 : : default:
269 : : return ARGP_ERR_UNKNOWN;
270 : : }
271 : : return 0;
272 : : }
273 : :
274 : : static const char *
275 : 249 : symname (const char *name)
276 : : {
277 : : #ifdef USE_DEMANGLE
278 : : // Require GNU v3 ABI by the "_Z" prefix.
279 [ + + ][ + + ]: 249 : if (demangle && name[0] == '_' && name[1] == 'Z')
[ + - ]
280 : : {
281 : 11 : int status = -1;
282 : 11 : char *dsymname = __cxa_demangle (name, demangle_buffer,
283 : : &demangle_buffer_len, &status);
284 [ + - ]: 11 : if (status == 0)
285 : 11 : name = demangle_buffer = dsymname;
286 : : }
287 : : #endif
288 : 249 : return name;
289 : : }
290 : :
291 : : static const char *
292 : 137 : get_diename (Dwarf_Die *die)
293 : : {
294 : 137 : Dwarf_Attribute attr;
295 : 137 : const char *name;
296 : :
297 [ + + ]: 249 : name = dwarf_formstring (dwarf_attr_integrate (die, DW_AT_MIPS_linkage_name,
298 : : &attr)
299 : 112 : ?: dwarf_attr_integrate (die, DW_AT_linkage_name,
300 : : &attr));
301 : :
302 [ + + ]: 137 : if (name == NULL)
303 [ - + ]: 108 : name = dwarf_diename (die) ?: "??";
304 : :
305 : 137 : return name;
306 : : }
307 : :
308 : : static bool
309 : 101 : print_dwarf_function (Dwfl_Module *mod, Dwarf_Addr addr)
310 : : {
311 : 101 : Dwarf_Addr bias = 0;
312 : 101 : Dwarf_Die *cudie = dwfl_module_addrdie (mod, addr, &bias);
313 : :
314 : 101 : Dwarf_Die *scopes;
315 : 101 : int nscopes = dwarf_getscopes (cudie, addr - bias, &scopes);
316 [ + + ]: 101 : if (nscopes <= 0)
317 : : return false;
318 : :
319 : : bool res = false;
320 [ + + ]: 135 : for (int i = 0; i < nscopes; ++i)
321 [ + + + ]: 115 : switch (dwarf_tag (&scopes[i]))
322 : : {
323 : 63 : case DW_TAG_subprogram:
324 : : {
325 : 63 : const char *name = get_diename (&scopes[i]);
326 [ + - ]: 63 : if (name == NULL)
327 : : goto done;
328 [ + + ]: 114 : printf ("%s%c", symname (name), pretty ? ' ' : '\n');
329 : 63 : res = true;
330 : 63 : goto done;
331 : : }
332 : :
333 : 32 : case DW_TAG_inlined_subroutine:
334 : : {
335 : 32 : const char *name = get_diename (&scopes[i]);
336 [ + - ]: 32 : if (name == NULL)
337 : 12 : goto done;
338 : :
339 : : /* When using --pretty-print we only show inlines on their
340 : : own line. Just print the first subroutine name. */
341 [ + + ]: 32 : if (pretty)
342 : : {
343 : 12 : printf ("%s ", symname (name));
344 : 12 : res = true;
345 : 12 : goto done;
346 : : }
347 : : else
348 : 20 : printf ("%s inlined", symname (name));
349 : :
350 : 20 : Dwarf_Files *files;
351 [ + - ]: 20 : if (dwarf_getsrcfiles (cudie, &files, NULL) == 0)
352 : : {
353 : 20 : Dwarf_Attribute attr_mem;
354 : 20 : Dwarf_Word val;
355 [ + - ]: 20 : if (dwarf_formudata (dwarf_attr (&scopes[i],
356 : : DW_AT_call_file,
357 : : &attr_mem), &val) == 0)
358 : : {
359 : 20 : const char *file = dwarf_filesrc (files, val, NULL, NULL);
360 : 20 : unsigned int lineno = 0;
361 : 20 : unsigned int colno = 0;
362 [ + - ]: 20 : if (dwarf_formudata (dwarf_attr (&scopes[i],
363 : : DW_AT_call_line,
364 : : &attr_mem), &val) == 0)
365 : 20 : lineno = val;
366 [ - + ]: 20 : if (dwarf_formudata (dwarf_attr (&scopes[i],
367 : : DW_AT_call_column,
368 : : &attr_mem), &val) == 0)
369 : 0 : colno = val;
370 : :
371 : 20 : const char *comp_dir = "";
372 : 20 : const char *comp_dir_sep = "";
373 : :
374 [ + - ]: 20 : if (file == NULL)
375 : : file = "???";
376 [ - + ]: 20 : else if (only_basenames)
377 : 0 : file = basename (file);
378 [ - + # # ]: 20 : else if (use_comp_dir && file[0] != '/')
379 : : {
380 : 0 : const char *const *dirs;
381 : 0 : size_t ndirs;
382 [ # # ]: 0 : if (dwarf_getsrcdirs (files, &dirs, &ndirs) == 0
383 [ # # ]: 0 : && dirs[0] != NULL)
384 : : {
385 : 0 : comp_dir = dirs[0];
386 : 0 : comp_dir_sep = "/";
387 : : }
388 : : }
389 : :
390 [ - + ]: 20 : if (lineno == 0)
391 : 0 : printf (" from %s%s%s",
392 : : comp_dir, comp_dir_sep, file);
393 [ + - ]: 20 : else if (colno == 0)
394 : 20 : printf (" at %s%s%s:%u",
395 : : comp_dir, comp_dir_sep, file, lineno);
396 : : else
397 : 0 : printf (" at %s%s%s:%u:%u",
398 : : comp_dir, comp_dir_sep, file, lineno, colno);
399 : : }
400 : : }
401 : 20 : printf (" in ");
402 : 20 : continue;
403 : : }
404 : : }
405 : :
406 : 20 : done:
407 : 95 : free (scopes);
408 : 95 : return res;
409 : : }
410 : :
411 : : static void
412 : 96 : print_addrsym (Dwfl_Module *mod, GElf_Addr addr)
413 : : {
414 : 96 : GElf_Sym s;
415 : 96 : GElf_Off off;
416 : 96 : const char *name = dwfl_module_addrinfo (mod, addr, &off, &s,
417 : : NULL, NULL, NULL);
418 [ + + ]: 96 : if (name == NULL)
419 : : {
420 : : /* No symbol name. Get a section name instead. */
421 : 9 : int i = dwfl_module_relocate_address (mod, &addr);
422 [ + - ]: 9 : if (i >= 0)
423 : 9 : name = dwfl_module_relocation_info (mod, i, NULL);
424 [ - + ]: 9 : if (name == NULL)
425 [ # # ]: 0 : printf ("??%c", pretty ? ' ': '\n');
426 : : else
427 [ + - ]: 18 : printf ("(%s)+%#" PRIx64 "%c", name, addr, pretty ? ' ' : '\n');
428 : : }
429 : : else
430 : : {
431 : 87 : name = symname (name);
432 [ + + ]: 87 : if (off == 0)
433 : 31 : printf ("%s", name);
434 : : else
435 : 56 : printf ("%s+%#" PRIx64 "", name, off);
436 : :
437 : : // Also show section name for address.
438 [ + + ]: 87 : if (show_symbol_sections)
439 : : {
440 : 8 : Dwarf_Addr ebias;
441 : 8 : Elf_Scn *scn = dwfl_module_address_section (mod, &addr, &ebias);
442 [ + - ]: 8 : if (scn != NULL)
443 : : {
444 : 8 : GElf_Shdr shdr_mem;
445 : 8 : GElf_Shdr *shdr = gelf_getshdr (scn, &shdr_mem);
446 [ + - ]: 8 : if (shdr != NULL)
447 : : {
448 : 8 : Elf *elf = dwfl_module_getelf (mod, &ebias);
449 : 8 : size_t shstrndx;
450 [ + - ]: 8 : if (elf_getshdrstrndx (elf, &shstrndx) >= 0)
451 : 8 : printf (" (%s)", elf_strptr (elf, shstrndx,
452 : 8 : shdr->sh_name));
453 : : }
454 : : }
455 : : }
456 [ + - ]: 174 : printf ("%c", pretty ? ' ' : '\n');
457 : : }
458 : 96 : }
459 : :
460 : : static int
461 : 0 : see_one_module (Dwfl_Module *mod,
462 : : void **userdata __attribute__ ((unused)),
463 : : const char *name __attribute__ ((unused)),
464 : : Dwarf_Addr start __attribute__ ((unused)),
465 : : void *arg)
466 : : {
467 : 0 : Dwfl_Module **result = arg;
468 [ # # ]: 0 : if (*result != NULL)
469 : : return DWARF_CB_ABORT;
470 : 0 : *result = mod;
471 : 0 : return DWARF_CB_OK;
472 : : }
473 : :
474 : : static int
475 : 29 : find_symbol (Dwfl_Module *mod,
476 : : void **userdata __attribute__ ((unused)),
477 : : const char *name __attribute__ ((unused)),
478 : : Dwarf_Addr start __attribute__ ((unused)),
479 : : void *arg)
480 : : {
481 : 29 : const char *looking_for = ((void **) arg)[0];
482 : 29 : GElf_Sym *symbol = ((void **) arg)[1];
483 : 29 : GElf_Addr *value = ((void **) arg)[2];
484 : :
485 : 29 : int n = dwfl_module_getsymtab (mod);
486 [ + + ]: 2124 : for (int i = 1; i < n; ++i)
487 : : {
488 : 2122 : const char *symbol_name = dwfl_module_getsym_info (mod, i, symbol,
489 : : value, NULL, NULL,
490 : : NULL);
491 [ + - ][ + + ]: 2122 : if (symbol_name == NULL || symbol_name[0] == '\0')
492 : : continue;
493 [ + - ]: 1249 : switch (GELF_ST_TYPE (symbol->st_info))
494 : : {
495 : : case STT_SECTION:
496 : : case STT_FILE:
497 : : case STT_TLS:
498 : : break;
499 : 1049 : default:
500 [ + + ]: 1049 : if (!strcmp (symbol_name, looking_for))
501 : : {
502 : 27 : ((void **) arg)[0] = NULL;
503 : 27 : return DWARF_CB_ABORT;
504 : : }
505 : : }
506 : : }
507 : :
508 : : return DWARF_CB_OK;
509 : : }
510 : :
511 : : static bool
512 : 0 : adjust_to_section (const char *name, uintmax_t *addr, Dwfl *dwfl)
513 : : {
514 : : /* It was (section)+offset. This makes sense if there is
515 : : only one module to look in for a section. */
516 : 0 : Dwfl_Module *mod = NULL;
517 [ # # ]: 0 : if (dwfl_getmodules (dwfl, &see_one_module, &mod, 0) != 0
518 [ # # ]: 0 : || mod == NULL)
519 : 0 : error (EXIT_FAILURE, 0, _("Section syntax requires"
520 : : " exactly one module"));
521 : :
522 : 0 : int nscn = dwfl_module_relocations (mod);
523 [ # # ]: 0 : for (int i = 0; i < nscn; ++i)
524 : : {
525 : 0 : GElf_Word shndx;
526 : 0 : const char *scn = dwfl_module_relocation_info (mod, i, &shndx);
527 [ # # ]: 0 : if (unlikely (scn == NULL))
528 : : break;
529 [ # # ]: 0 : if (!strcmp (scn, name))
530 : : {
531 : : /* Found the section. */
532 : 0 : GElf_Shdr shdr_mem;
533 : 0 : GElf_Addr shdr_bias;
534 : 0 : GElf_Shdr *shdr = gelf_getshdr
535 : : (elf_getscn (dwfl_module_getelf (mod, &shdr_bias), shndx),
536 : : &shdr_mem);
537 [ # # ]: 0 : if (unlikely (shdr == NULL))
538 : : break;
539 : :
540 [ # # ]: 0 : if (*addr >= shdr->sh_size)
541 : 0 : error (0, 0,
542 : 0 : _("offset %#" PRIxMAX " lies outside"
543 : : " section '%s'"),
544 : : *addr, scn);
545 : :
546 : 0 : *addr += shdr->sh_addr + shdr_bias;
547 : 0 : return true;
548 : : }
549 : : }
550 : :
551 : : return false;
552 : : }
553 : :
554 : : static void
555 : 185 : print_src (const char *src, int lineno, int linecol, Dwarf_Die *cu)
556 : : {
557 : 185 : const char *comp_dir = "";
558 : 185 : const char *comp_dir_sep = "";
559 : :
560 [ - + ]: 185 : if (only_basenames)
561 : 0 : src = basename (src);
562 [ - + # # ]: 185 : else if (use_comp_dir && src[0] != '/')
563 : : {
564 : 0 : Dwarf_Attribute attr;
565 : 0 : comp_dir = dwarf_formstring (dwarf_attr (cu, DW_AT_comp_dir, &attr));
566 [ # # ]: 0 : if (comp_dir != NULL)
567 : 0 : comp_dir_sep = "/";
568 : : }
569 : :
570 [ - + ]: 185 : if (linecol != 0)
571 : 0 : printf ("%s%s%s:%d:%d",
572 : : comp_dir, comp_dir_sep, src, lineno, linecol);
573 : : else
574 : 185 : printf ("%s%s%s:%d",
575 : : comp_dir, comp_dir_sep, src, lineno);
576 : 185 : }
577 : :
578 : : static int
579 : 51 : get_addr_width (Dwfl_Module *mod)
580 : : {
581 : : // Try to find the address width if possible.
582 : 51 : static int width = 0;
583 [ + + ][ + - ]: 51 : if (width == 0 && mod != NULL)
584 : : {
585 : 6 : Dwarf_Addr bias;
586 : 6 : Elf *elf = dwfl_module_getelf (mod, &bias);
587 [ + - ]: 6 : if (elf != NULL)
588 : : {
589 : 6 : GElf_Ehdr ehdr_mem;
590 : 6 : GElf_Ehdr *ehdr = gelf_getehdr (elf, &ehdr_mem);
591 [ + - ]: 6 : if (ehdr != NULL)
592 [ + + ]: 9 : width = ehdr->e_ident[EI_CLASS] == ELFCLASS32 ? 8 : 16;
593 : : }
594 : : }
595 [ - + ]: 51 : if (width == 0)
596 : 0 : width = 16;
597 : :
598 : 51 : return width;
599 : : }
600 : :
601 : : static inline void
602 : 0 : show_note (int (*get) (Dwarf_Line *, bool *),
603 : : Dwarf_Line *info,
604 : : const char *note)
605 : : {
606 : 0 : bool flag;
607 [ # # # # ]: 0 : if ((*get) (info, &flag) == 0 && flag)
608 : 0 : fputs (note, stdout);
609 : 0 : }
610 : :
611 : : static inline void
612 : 0 : show_int (int (*get) (Dwarf_Line *, unsigned int *),
613 : : Dwarf_Line *info,
614 : : const char *name)
615 : : {
616 : 0 : unsigned int val;
617 [ # # # # ]: 0 : if ((*get) (info, &val) == 0 && val != 0)
618 : 0 : printf (" (%s %u)", name, val);
619 : 0 : }
620 : :
621 : : static int
622 : 211 : handle_address (const char *string, Dwfl *dwfl)
623 : : {
624 : 211 : char *endp;
625 : 211 : uintmax_t addr = strtoumax (string, &endp, 16);
626 [ + + ][ + + ]: 211 : if (endp == string || *endp != '\0')
627 : 27 : {
628 : 27 : bool parsed = false;
629 : 27 : int i, j;
630 : 27 : char *name = NULL;
631 [ - + ]: 27 : if (sscanf (string, "(%m[^)])%" PRIiMAX "%n", &name, &addr, &i) == 2
632 [ # # ]: 0 : && string[i] == '\0')
633 : 0 : parsed = adjust_to_section (name, &addr, dwfl);
634 [ + + - ]: 27 : switch (sscanf (string, "%m[^-+]%n%" PRIiMAX "%n", &name, &i, &addr, &j))
635 : : {
636 : : default:
637 : : break;
638 : 11 : case 1:
639 : 11 : addr = 0;
640 : 11 : j = i;
641 : 27 : FALLTHROUGH;
642 : 27 : case 2:
643 [ + - ]: 27 : if (string[j] != '\0')
644 : : break;
645 : :
646 : : /* It was symbol[+offset]. */
647 : 27 : GElf_Sym sym;
648 : 27 : GElf_Addr value = 0;
649 : 27 : void *arg[3] = { name, &sym, &value };
650 : 27 : (void) dwfl_getmodules (dwfl, &find_symbol, arg, 0);
651 [ - + ]: 27 : if (arg[0] != NULL)
652 : 0 : error (0, 0, _("cannot find symbol '%s'"), name);
653 : : else
654 : : {
655 [ + - ][ - + ]: 27 : if (sym.st_size != 0 && addr >= sym.st_size)
656 : 0 : error (0, 0,
657 : 0 : _("offset %#" PRIxMAX " lies outside"
658 : : " contents of '%s'"),
659 : : addr, name);
660 : 27 : addr += value;
661 : 27 : parsed = true;
662 : : }
663 : : break;
664 : : }
665 : :
666 : 27 : free (name);
667 [ - + ]: 27 : if (!parsed)
668 : 0 : return 1;
669 : : }
670 [ - + ]: 184 : else if (just_section != NULL
671 [ # # ]: 0 : && !adjust_to_section (just_section, &addr, dwfl))
672 : : return 1;
673 : :
674 : 211 : Dwfl_Module *mod = dwfl_addrmodule (dwfl, addr);
675 : :
676 [ + + ]: 211 : if (print_addresses)
677 : : {
678 : 51 : int width = get_addr_width (mod);
679 [ + + ]: 78 : printf ("0x%.*" PRIx64 "%s", width, addr, pretty ? ": " : "\n");
680 : : }
681 : :
682 [ + + ]: 211 : if (show_functions)
683 : : {
684 : : /* First determine the function name. Use the DWARF information if
685 : : possible. */
686 [ + + ][ + - ]: 101 : if (! print_dwarf_function (mod, addr) && !show_symbols)
687 : : {
688 : 26 : const char *name = dwfl_module_addrname (mod, addr);
689 [ + + ]: 26 : name = name != NULL ? symname (name) : "??";
690 [ + - ]: 52 : printf ("%s%c", name, pretty ? ' ' : '\n');
691 : : }
692 : : }
693 : :
694 [ + + ]: 211 : if (show_symbols)
695 : 96 : print_addrsym (mod, addr);
696 : :
697 [ + + ][ + + ]: 211 : if ((show_functions || show_symbols) && pretty)
[ + + ]
698 : 24 : printf ("at ");
699 : :
700 : 211 : Dwfl_Line *line = dwfl_module_getsrc (mod, addr);
701 : :
702 : 211 : const char *src;
703 : 211 : int lineno, linecol;
704 : :
705 [ + + ][ + - ]: 211 : if (line != NULL && (src = dwfl_lineinfo (line, &addr, &lineno, &linecol,
706 : : NULL, NULL)) != NULL)
707 : : {
708 : 133 : print_src (src, lineno, linecol, dwfl_linecu (line));
709 [ - + ]: 133 : if (show_flags)
710 : : {
711 : 0 : Dwarf_Addr bias;
712 : 0 : Dwarf_Line *info = dwfl_dwarf_line (line, &bias);
713 [ # # ]: 0 : assert (info != NULL);
714 : :
715 : 0 : show_note (&dwarf_linebeginstatement, info, " (is_stmt)");
716 : 0 : show_note (&dwarf_lineblock, info, " (basic_block)");
717 : 0 : show_note (&dwarf_lineprologueend, info, " (prologue_end)");
718 : 0 : show_note (&dwarf_lineepiloguebegin, info, " (epilogue_begin)");
719 : 0 : show_int (&dwarf_lineisa, info, "isa");
720 : 0 : show_int (&dwarf_linediscriminator, info, "discriminator");
721 : : }
722 : 133 : putchar ('\n');
723 : : }
724 : : else
725 : 78 : puts ("??:0");
726 : :
727 [ + + ]: 211 : if (show_inlines)
728 : : {
729 : 73 : Dwarf_Addr bias = 0;
730 : 73 : Dwarf_Die *cudie = dwfl_module_addrdie (mod, addr, &bias);
731 : :
732 : 73 : Dwarf_Die *scopes = NULL;
733 : 73 : int nscopes = dwarf_getscopes (cudie, addr - bias, &scopes);
734 [ - + ]: 73 : if (nscopes < 0)
735 : 0 : return 1;
736 : :
737 [ + - ]: 73 : if (nscopes > 0)
738 : : {
739 : 73 : Dwarf_Die subroutine;
740 : 73 : Dwarf_Off dieoff = dwarf_dieoffset (&scopes[0]);
741 : 73 : dwarf_offdie (dwfl_module_getdwarf (mod, &bias),
742 : : dieoff, &subroutine);
743 : 73 : free (scopes);
744 : 73 : scopes = NULL;
745 : :
746 : 73 : nscopes = dwarf_getscopes_die (&subroutine, &scopes);
747 [ + - ]: 73 : if (nscopes > 1)
748 : : {
749 : 73 : Dwarf_Die cu;
750 : 73 : Dwarf_Files *files;
751 [ + - ]: 73 : if (dwarf_diecu (&scopes[0], &cu, NULL, NULL) != NULL
752 [ + - ]: 73 : && dwarf_getsrcfiles (cudie, &files, NULL) == 0)
753 : : {
754 [ + + ]: 202 : for (int i = 0; i < nscopes - 1; i++)
755 : : {
756 : 129 : Dwarf_Word val;
757 : 129 : Dwarf_Attribute attr;
758 : 129 : Dwarf_Die *die = &scopes[i];
759 [ + + ]: 129 : if (dwarf_tag (die) != DW_TAG_inlined_subroutine)
760 : 77 : continue;
761 : :
762 [ + + ]: 52 : if (pretty)
763 : 16 : printf (" (inlined by) ");
764 : :
765 [ + + ]: 52 : if (show_functions)
766 : : {
767 : : /* Search for the parent inline or function. It
768 : : might not be directly above this inline -- e.g.
769 : : there could be a lexical_block in between. */
770 [ + - ]: 44 : for (int j = i + 1; j < nscopes; j++)
771 : : {
772 : 44 : Dwarf_Die *parent = &scopes[j];
773 : 44 : int tag = dwarf_tag (parent);
774 : 88 : if (tag == DW_TAG_inlined_subroutine
775 [ + + ]: 44 : || tag == DW_TAG_entry_point
776 [ + + ]: 34 : || tag == DW_TAG_subprogram)
777 : : {
778 : 42 : printf ("%s%s",
779 : : symname (get_diename (parent)),
780 [ + + ]: 42 : pretty ? " at " : "\n");
781 : : break;
782 : : }
783 : : }
784 : : }
785 : :
786 : 52 : src = NULL;
787 : 52 : lineno = 0;
788 : 52 : linecol = 0;
789 [ + - ]: 52 : if (dwarf_formudata (dwarf_attr (die, DW_AT_call_file,
790 : : &attr), &val) == 0)
791 : 52 : src = dwarf_filesrc (files, val, NULL, NULL);
792 : :
793 [ + - ]: 52 : if (dwarf_formudata (dwarf_attr (die, DW_AT_call_line,
794 : : &attr), &val) == 0)
795 : 52 : lineno = val;
796 : :
797 [ - + ]: 52 : if (dwarf_formudata (dwarf_attr (die, DW_AT_call_column,
798 : : &attr), &val) == 0)
799 : 0 : linecol = val;
800 : :
801 [ + - ]: 52 : if (src != NULL)
802 : : {
803 : 52 : print_src (src, lineno, linecol, &cu);
804 : 52 : putchar ('\n');
805 : : }
806 : : else
807 : 0 : puts ("??:0");
808 : : }
809 : : }
810 : : }
811 : : }
812 : 73 : free (scopes);
813 : : }
814 : :
815 : : return 0;
816 : : }
817 : :
818 : :
819 : : #include "debugpred.h"
|