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