1 /* Locate source files and line information for given addresses
2 Copyright (C) 2005-2010, 2012 Red Hat, Inc.
3 This file is part of elfutils.
4 Written by Ulrich Drepper <drepper@redhat.com>, 2005.
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.
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.
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/>. */
36 #include <stdio_ext.h>
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;
48 /* Bug report address. */
49 ARGP_PROGRAM_BUG_ADDRESS_DEF = PACKAGE_BUGREPORT;
52 /* Values for the parameters which have no short form. */
53 #define OPT_DEMANGLER 0x100
55 /* Definitions of arguments for argp functions. */
56 static const struct argp_option options[] =
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 { "flags", 'F', NULL, 0, N_("Also show line table flags"), 0 },
65 { "section", 'j', "NAME", 0,
66 N_("Treat addresses as offsets relative to NAME section."), 0 },
68 { NULL, 0, NULL, 0, N_("Miscellaneous:"), 0 },
69 /* Unsupported options. */
70 { "target", 'b', "ARG", OPTION_HIDDEN, NULL, 0 },
71 { "demangle", 'C', "ARG", OPTION_HIDDEN | OPTION_ARG_OPTIONAL, NULL, 0 },
72 { "demangler", OPT_DEMANGLER, "ARG", OPTION_HIDDEN, NULL, 0 },
73 { NULL, 0, NULL, 0, NULL, 0 }
76 /* Short description of program. */
77 static const char doc[] = N_("\
78 Locate source files and line information for ADDRs (in a.out by default).");
80 /* Strings for arguments in help texts. */
81 static const char args_doc[] = N_("[ADDR...]");
83 /* Prototype for option handler. */
84 static error_t parse_opt (int key, char *arg, struct argp_state *state);
86 static struct argp_child argp_children[2]; /* [0] is set in main. */
88 /* Data structure to communicate with argp functions. */
89 static const struct argp argp =
91 options, parse_opt, args_doc, doc, argp_children, NULL, NULL
96 static int handle_address (const char *addr, Dwfl *dwfl);
99 /* True if only base names of files should be shown. */
100 static bool only_basenames;
102 /* True if absolute file names based on DW_AT_comp_dir should be shown. */
103 static bool use_comp_dir;
105 /* True if line flags should be shown. */
106 static bool show_flags;
108 /* True if function names should be shown. */
109 static bool show_functions;
111 /* True if ELF symbol or section info should be shown. */
112 static bool show_symbols;
114 /* If non-null, take address parameters as relative to named section. */
115 static const char *just_section;
119 main (int argc, char *argv[])
124 /* Make memory leak detection possible. */
127 /* We use no threads here which can interfere with handling a stream. */
128 (void) __fsetlocking (stdout, FSETLOCKING_BYCALLER);
131 (void) setlocale (LC_ALL, "");
133 /* Make sure the message catalog can be found. */
134 (void) bindtextdomain (PACKAGE_TARNAME, LOCALEDIR);
136 /* Initialize the message catalog. */
137 (void) textdomain (PACKAGE_TARNAME);
139 /* Parse and process arguments. This includes opening the modules. */
140 argp_children[0].argp = dwfl_standard_argp ();
141 argp_children[0].group = 1;
143 (void) argp_parse (&argp, argc, argv, 0, &remaining, &dwfl);
144 assert (dwfl != NULL);
146 /* Now handle the addresses. In case none are given on the command
147 line, read from stdin. */
148 if (remaining == argc)
150 /* We use no threads here which can interfere with handling a stream. */
151 (void) __fsetlocking (stdin, FSETLOCKING_BYCALLER);
155 while (!feof_unlocked (stdin))
157 if (getline (&buf, &len, stdin) < 0)
160 result = handle_address (buf, dwfl);
168 result = handle_address (argv[remaining], dwfl);
169 while (++remaining < argc);
176 /* Print the version information. */
178 print_version (FILE *stream, struct argp_state *state __attribute__ ((unused)))
180 fprintf (stream, "addr2line (%s) %s\n", PACKAGE_NAME, PACKAGE_VERSION);
181 fprintf (stream, gettext ("\
182 Copyright (C) %s Red Hat, Inc.\n\
183 This is free software; see the source for copying conditions. There is NO\n\
184 warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.\n\
186 fprintf (stream, gettext ("Written by %s.\n"), "Ulrich Drepper");
190 /* Handle program arguments. */
192 parse_opt (int key, char *arg, struct argp_state *state)
197 state->child_inputs[0] = state->input;
203 /* Ignored for compatibility. */
207 only_basenames = true;
215 show_functions = true;
231 return ARGP_ERR_UNKNOWN;
238 print_dwarf_function (Dwfl_Module *mod, Dwarf_Addr addr)
241 Dwarf_Die *cudie = dwfl_module_addrdie (mod, addr, &bias);
244 int nscopes = dwarf_getscopes (cudie, addr - bias, &scopes);
248 for (int i = 0; i < nscopes; ++i)
249 switch (dwarf_tag (&scopes[i]))
251 case DW_TAG_subprogram:
253 const char *name = dwarf_diename (&scopes[i]);
260 case DW_TAG_inlined_subroutine:
262 const char *name = dwarf_diename (&scopes[i]);
265 printf ("%s inlined", name);
268 if (dwarf_getsrcfiles (cudie, &files, NULL) == 0)
270 Dwarf_Attribute attr_mem;
272 if (dwarf_formudata (dwarf_attr (&scopes[i],
274 &attr_mem), &val) == 0)
276 const char *file = dwarf_filesrc (files, val, NULL, NULL);
277 unsigned int lineno = 0;
278 unsigned int colno = 0;
279 if (dwarf_formudata (dwarf_attr (&scopes[i],
281 &attr_mem), &val) == 0)
283 if (dwarf_formudata (dwarf_attr (&scopes[i],
285 &attr_mem), &val) == 0)
288 const char *comp_dir = "";
289 const char *comp_dir_sep = "";
293 else if (only_basenames)
294 file = basename (file);
295 else if (use_comp_dir && file[0] != '/')
297 const char *const *dirs;
299 if (dwarf_getsrcdirs (files, &dirs, &ndirs) == 0
308 printf (" from %s%s%s",
309 comp_dir, comp_dir_sep, file);
311 printf (" at %s%s%s:%u",
312 comp_dir, comp_dir_sep, file, lineno);
314 printf (" at %s%s%s:%u:%u",
315 comp_dir, comp_dir_sep, file, lineno, colno);
327 print_addrsym (Dwfl_Module *mod, GElf_Addr addr)
331 const char *name = dwfl_module_addrsym (mod, addr, &s, &shndx);
334 /* No symbol name. Get a section name instead. */
335 int i = dwfl_module_relocate_address (mod, &addr);
337 name = dwfl_module_relocation_info (mod, i, NULL);
341 printf ("(%s)+%#" PRIx64 "\n", name, addr);
343 else if (addr == s.st_value)
346 printf ("%s+%#" PRIx64 "\n", name, addr - s.st_value);
350 see_one_module (Dwfl_Module *mod,
351 void **userdata __attribute__ ((unused)),
352 const char *name __attribute__ ((unused)),
353 Dwarf_Addr start __attribute__ ((unused)),
356 Dwfl_Module **result = arg;
358 return DWARF_CB_ABORT;
364 find_symbol (Dwfl_Module *mod,
365 void **userdata __attribute__ ((unused)),
366 const char *name __attribute__ ((unused)),
367 Dwarf_Addr start __attribute__ ((unused)),
370 const char *looking_for = ((void **) arg)[0];
371 GElf_Sym *symbol = ((void **) arg)[1];
373 int n = dwfl_module_getsymtab (mod);
374 for (int i = 1; i < n; ++i)
376 const char *symbol_name = dwfl_module_getsym (mod, i, symbol, NULL);
377 if (symbol_name == NULL || symbol_name[0] == '\0')
379 switch (GELF_ST_TYPE (symbol->st_info))
386 if (!strcmp (symbol_name, looking_for))
388 ((void **) arg)[0] = NULL;
389 return DWARF_CB_ABORT;
398 adjust_to_section (const char *name, uintmax_t *addr, Dwfl *dwfl)
400 /* It was (section)+offset. This makes sense if there is
401 only one module to look in for a section. */
402 Dwfl_Module *mod = NULL;
403 if (dwfl_getmodules (dwfl, &see_one_module, &mod, 0) != 0
405 error (EXIT_FAILURE, 0, gettext ("Section syntax requires"
406 " exactly one module"));
408 int nscn = dwfl_module_relocations (mod);
409 for (int i = 0; i < nscn; ++i)
412 const char *scn = dwfl_module_relocation_info (mod, i, &shndx);
413 if (unlikely (scn == NULL))
415 if (!strcmp (scn, name))
417 /* Found the section. */
420 GElf_Shdr *shdr = gelf_getshdr
421 (elf_getscn (dwfl_module_getelf (mod, &shdr_bias), shndx),
423 if (unlikely (shdr == NULL))
426 if (*addr >= shdr->sh_size)
428 gettext ("offset %#" PRIxMAX " lies outside"
432 *addr += shdr->sh_addr + shdr_bias;
441 handle_address (const char *string, Dwfl *dwfl)
444 uintmax_t addr = strtoumax (string, &endp, 0);
450 if (sscanf (string, "(%m[^)])%" PRIiMAX "%n", &name, &addr, &i) == 2
451 && string[i] == '\0')
452 parsed = adjust_to_section (name, &addr, dwfl);
453 switch (sscanf (string, "%m[^-+]%n%" PRIiMAX "%n", &name, &i, &addr, &j))
461 if (string[j] != '\0')
464 /* It was symbol[+offset]. */
466 void *arg[2] = { name, &sym };
467 (void) dwfl_getmodules (dwfl, &find_symbol, arg, 0);
469 error (0, 0, gettext ("cannot find symbol '%s'"), name);
472 if (sym.st_size != 0 && addr >= sym.st_size)
474 gettext ("offset %#" PRIxMAX " lies outside"
475 " contents of '%s'"),
477 addr += sym.st_value;
487 else if (just_section != NULL
488 && !adjust_to_section (just_section, &addr, dwfl))
491 Dwfl_Module *mod = dwfl_addrmodule (dwfl, addr);
495 /* First determine the function name. Use the DWARF information if
497 if (! print_dwarf_function (mod, addr) && !show_symbols)
498 puts (dwfl_module_addrname (mod, addr) ?: "??");
502 print_addrsym (mod, addr);
504 Dwfl_Line *line = dwfl_module_getsrc (mod, addr);
508 if (line != NULL && (src = dwfl_lineinfo (line, &addr, &lineno, &linecol,
509 NULL, NULL)) != NULL)
511 const char *comp_dir = "";
512 const char *comp_dir_sep = "";
515 src = basename (src);
516 else if (use_comp_dir && src[0] != '/')
518 comp_dir = dwfl_line_comp_dir (line);
519 if (comp_dir != NULL)
524 printf ("%s%s%s:%d:%d",
525 comp_dir, comp_dir_sep, src, lineno, linecol);
528 comp_dir, comp_dir_sep, src, lineno);
533 Dwarf_Line *info = dwfl_dwarf_line (line, &bias);
534 assert (info != NULL);
536 inline void show (int (*get) (Dwarf_Line *, bool *),
540 if ((*get) (info, &flag) == 0 && flag)
541 fputs (note, stdout);
543 inline void show_int (int (*get) (Dwarf_Line *, unsigned int *),
547 if ((*get) (info, &val) == 0 && val != 0)
548 printf (" (%s %u)", name, val);
551 show (&dwarf_linebeginstatement, " (is_stmt)");
552 show (&dwarf_lineblock, " (basic_block)");
553 show (&dwarf_lineprologueend, " (prologue_end)");
554 show (&dwarf_lineepiloguebegin, " (epilogue_begin)");
555 show_int (&dwarf_lineisa, "isa");
556 show_int (&dwarf_linediscriminator, "discriminator");
567 #include "debugpred.h"