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