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