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 : 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 : ssize_t chars;
180 48 : while (!feof_unlocked (stdin))
181 : {
182 40 : 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 : 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 : 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 : Dwarf_Attribute attr;
295 : const char *name;
296 :
297 137 : name = dwarf_formstring (dwarf_attr_integrate (die, DW_AT_MIPS_linkage_name,
298 : &attr)
299 : ?: 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 : 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 40 : 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 126 : 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 : 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 24 : printf ("%s ", symname (name));
344 12 : res = true;
345 12 : goto done;
346 : }
347 : else
348 40 : printf ("%s inlined", symname (name));
349 :
350 : Dwarf_Files *files;
351 20 : if (dwarf_getsrcfiles (cudie, &files, NULL) == 0)
352 : {
353 : Dwarf_Attribute attr_mem;
354 : 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 : const char *const *dirs;
381 : 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 : printf (" from %s%s%s",
392 : comp_dir, comp_dir_sep, file);
393 20 : else if (colno == 0)
394 : printf (" at %s%s%s:%u",
395 : comp_dir, comp_dir_sep, file, lineno);
396 : else
397 : 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 : GElf_Sym s;
415 : 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 9 : printf ("(%s)+%#" PRIx64 "%c", name, addr, pretty ? ' ' : '\n');
428 : }
429 : else
430 : {
431 87 : name = symname (name);
432 87 : if (off == 0)
433 : 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 : Dwarf_Addr ebias;
441 8 : Elf_Scn *scn = dwfl_module_address_section (mod, &addr, &ebias);
442 8 : if (scn != NULL)
443 : {
444 : 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 : 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 87 : 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 873 : 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, gettext ("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 : 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 : GElf_Shdr shdr_mem;
533 : 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 : error (0, 0,
542 0 : gettext ("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 : 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 : printf ("%s%s%s:%d:%d",
572 : comp_dir, comp_dir_sep, src, lineno, linecol);
573 : else
574 : 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 : static int width = 0;
583 51 : if (width == 0 && mod != NULL)
584 : {
585 : Dwarf_Addr bias;
586 6 : Elf *elf = dwfl_module_getelf (mod, &bias);
587 6 : if (elf != NULL)
588 : {
589 : GElf_Ehdr ehdr_mem;
590 6 : GElf_Ehdr *ehdr = gelf_getehdr (elf, &ehdr_mem);
591 6 : if (ehdr != NULL)
592 6 : 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 int
602 211 : handle_address (const char *string, Dwfl *dwfl)
603 : {
604 : char *endp;
605 211 : uintmax_t addr = strtoumax (string, &endp, 16);
606 211 : if (endp == string || *endp != '\0')
607 27 : {
608 27 : bool parsed = false;
609 : int i, j;
610 27 : char *name = NULL;
611 27 : if (sscanf (string, "(%m[^)])%" PRIiMAX "%n", &name, &addr, &i) == 2
612 0 : && string[i] == '\0')
613 0 : parsed = adjust_to_section (name, &addr, dwfl);
614 27 : switch (sscanf (string, "%m[^-+]%n%" PRIiMAX "%n", &name, &i, &addr, &j))
615 : {
616 : default:
617 : break;
618 11 : case 1:
619 11 : addr = 0;
620 11 : j = i;
621 : FALLTHROUGH;
622 27 : case 2:
623 27 : if (string[j] != '\0')
624 : break;
625 :
626 : /* It was symbol[+offset]. */
627 : GElf_Sym sym;
628 27 : GElf_Addr value = 0;
629 27 : void *arg[3] = { name, &sym, &value };
630 27 : (void) dwfl_getmodules (dwfl, &find_symbol, arg, 0);
631 27 : if (arg[0] != NULL)
632 0 : error (0, 0, gettext ("cannot find symbol '%s'"), name);
633 : else
634 : {
635 27 : if (sym.st_size != 0 && addr >= sym.st_size)
636 0 : error (0, 0,
637 0 : gettext ("offset %#" PRIxMAX " lies outside"
638 : " contents of '%s'"),
639 : addr, name);
640 27 : addr += value;
641 27 : parsed = true;
642 : }
643 : break;
644 : }
645 :
646 27 : free (name);
647 27 : if (!parsed)
648 0 : return 1;
649 : }
650 184 : else if (just_section != NULL
651 0 : && !adjust_to_section (just_section, &addr, dwfl))
652 : return 1;
653 :
654 211 : Dwfl_Module *mod = dwfl_addrmodule (dwfl, addr);
655 :
656 211 : if (print_addresses)
657 : {
658 51 : int width = get_addr_width (mod);
659 51 : printf ("0x%.*" PRIx64 "%s", width, addr, pretty ? ": " : "\n");
660 : }
661 :
662 211 : if (show_functions)
663 : {
664 : /* First determine the function name. Use the DWARF information if
665 : possible. */
666 101 : if (! print_dwarf_function (mod, addr) && !show_symbols)
667 : {
668 26 : const char *name = dwfl_module_addrname (mod, addr);
669 26 : name = name != NULL ? symname (name) : "??";
670 26 : printf ("%s%c", name, pretty ? ' ' : '\n');
671 : }
672 : }
673 :
674 211 : if (show_symbols)
675 96 : print_addrsym (mod, addr);
676 :
677 211 : if ((show_functions || show_symbols) && pretty)
678 : printf ("at ");
679 :
680 211 : Dwfl_Line *line = dwfl_module_getsrc (mod, addr);
681 :
682 : const char *src;
683 : int lineno, linecol;
684 :
685 211 : if (line != NULL && (src = dwfl_lineinfo (line, &addr, &lineno, &linecol,
686 : NULL, NULL)) != NULL)
687 : {
688 133 : print_src (src, lineno, linecol, dwfl_linecu (line));
689 133 : if (show_flags)
690 : {
691 : Dwarf_Addr bias;
692 0 : Dwarf_Line *info = dwfl_dwarf_line (line, &bias);
693 0 : assert (info != NULL);
694 :
695 0 : inline void show (int (*get) (Dwarf_Line *, bool *),
696 : const char *note)
697 : {
698 : bool flag;
699 0 : if ((*get) (info, &flag) == 0 && flag)
700 0 : fputs (note, stdout);
701 0 : }
702 0 : inline void show_int (int (*get) (Dwarf_Line *, unsigned int *),
703 : const char *name)
704 : {
705 : unsigned int val;
706 0 : if ((*get) (info, &val) == 0 && val != 0)
707 0 : printf (" (%s %u)", name, val);
708 0 : }
709 :
710 0 : show (&dwarf_linebeginstatement, " (is_stmt)");
711 0 : show (&dwarf_lineblock, " (basic_block)");
712 0 : show (&dwarf_lineprologueend, " (prologue_end)");
713 0 : show (&dwarf_lineepiloguebegin, " (epilogue_begin)");
714 0 : show_int (&dwarf_lineisa, "isa");
715 0 : show_int (&dwarf_linediscriminator, "discriminator");
716 : }
717 : putchar ('\n');
718 : }
719 : else
720 78 : puts ("??:0");
721 :
722 211 : if (show_inlines)
723 : {
724 73 : Dwarf_Addr bias = 0;
725 73 : Dwarf_Die *cudie = dwfl_module_addrdie (mod, addr, &bias);
726 :
727 73 : Dwarf_Die *scopes = NULL;
728 73 : int nscopes = dwarf_getscopes (cudie, addr - bias, &scopes);
729 73 : if (nscopes < 0)
730 0 : return 1;
731 :
732 73 : if (nscopes > 0)
733 : {
734 : Dwarf_Die subroutine;
735 73 : Dwarf_Off dieoff = dwarf_dieoffset (&scopes[0]);
736 73 : dwarf_offdie (dwfl_module_getdwarf (mod, &bias),
737 : dieoff, &subroutine);
738 73 : free (scopes);
739 73 : scopes = NULL;
740 :
741 73 : nscopes = dwarf_getscopes_die (&subroutine, &scopes);
742 73 : if (nscopes > 1)
743 : {
744 : Dwarf_Die cu;
745 : Dwarf_Files *files;
746 73 : if (dwarf_diecu (&scopes[0], &cu, NULL, NULL) != NULL
747 73 : && dwarf_getsrcfiles (cudie, &files, NULL) == 0)
748 : {
749 129 : for (int i = 0; i < nscopes - 1; i++)
750 : {
751 : Dwarf_Word val;
752 : Dwarf_Attribute attr;
753 129 : Dwarf_Die *die = &scopes[i];
754 129 : if (dwarf_tag (die) != DW_TAG_inlined_subroutine)
755 77 : continue;
756 :
757 52 : if (pretty)
758 : printf (" (inlined by) ");
759 :
760 52 : if (show_functions)
761 : {
762 : /* Search for the parent inline or function. It
763 : might not be directly above this inline -- e.g.
764 : there could be a lexical_block in between. */
765 44 : for (int j = i + 1; j < nscopes; j++)
766 : {
767 44 : Dwarf_Die *parent = &scopes[j];
768 44 : int tag = dwarf_tag (parent);
769 88 : if (tag == DW_TAG_inlined_subroutine
770 44 : || tag == DW_TAG_entry_point
771 34 : || tag == DW_TAG_subprogram)
772 : {
773 42 : printf ("%s%s",
774 : symname (get_diename (parent)),
775 42 : pretty ? " at " : "\n");
776 : break;
777 : }
778 : }
779 : }
780 :
781 52 : src = NULL;
782 52 : lineno = 0;
783 52 : linecol = 0;
784 52 : if (dwarf_formudata (dwarf_attr (die, DW_AT_call_file,
785 : &attr), &val) == 0)
786 52 : src = dwarf_filesrc (files, val, NULL, NULL);
787 :
788 52 : if (dwarf_formudata (dwarf_attr (die, DW_AT_call_line,
789 : &attr), &val) == 0)
790 52 : lineno = val;
791 :
792 52 : if (dwarf_formudata (dwarf_attr (die, DW_AT_call_column,
793 : &attr), &val) == 0)
794 0 : linecol = val;
795 :
796 52 : if (src != NULL)
797 : {
798 52 : print_src (src, lineno, linecol, &cu);
799 : putchar ('\n');
800 : }
801 : else
802 0 : puts ("??:0");
803 : }
804 : }
805 : }
806 : }
807 73 : free (scopes);
808 : }
809 :
810 : return 0;
811 : }
812 :
813 :
814 : #include "debugpred.h"
|