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