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