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 Red Hat elfutils.
4 Written by Ulrich Drepper <drepper@redhat.com>, 2005.
6 Red Hat elfutils is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by the
8 Free Software Foundation; version 2 of the License.
10 Red Hat elfutils is distributed in the hope that it will be useful, but
11 WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 General Public License for more details.
15 You should have received a copy of the GNU General Public License along
16 with Red Hat elfutils; if not, write to the Free Software Foundation,
17 Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301 USA.
19 Red Hat elfutils is an included package of the Open Invention Network.
20 An included package of the Open Invention Network is a package for which
21 Open Invention Network licensees cross-license their patents. No patent
22 license is granted, either expressly or impliedly, by designation as an
23 included package. Should you wish to participate in the Open Invention
24 Network licensing program, please visit www.openinventionnetwork.com
25 <http://www.openinventionnetwork.com>. */
44 #include <stdio_ext.h>
52 /* Name and version of program. */
53 static void print_version (FILE *stream, struct argp_state *state);
54 ARGP_PROGRAM_VERSION_HOOK_DEF = print_version;
56 /* Bug report address. */
57 ARGP_PROGRAM_BUG_ADDRESS_DEF = PACKAGE_BUGREPORT;
60 /* Values for the parameters which have no short form. */
61 #define OPT_DEMANGLER 0x100
63 /* Definitions of arguments for argp functions. */
64 static const struct argp_option options[] =
66 { NULL, 0, NULL, 0, N_("Output selection options:"), 2 },
67 { "basenames", 's', NULL, 0, N_("Show only base names of source files"), 0 },
68 { "absolute", 'A', NULL, 0,
69 N_("Show absolute file names using compilation directory"), 0 },
70 { "functions", 'f', NULL, 0, N_("Also show function names"), 0 },
71 { "symbols", 'S', NULL, 0, N_("Also show symbol or section names"), 0 },
72 { "flags", 'F', NULL, 0, N_("Also show line table flags"), 0 },
73 { "section", 'j', "NAME", 0,
74 N_("Treat addresses as offsets relative to NAME section."), 0 },
76 { NULL, 0, NULL, 0, N_("Miscellaneous:"), 0 },
77 /* Unsupported options. */
78 { "target", 'b', "ARG", OPTION_HIDDEN, NULL, 0 },
79 { "demangle", 'C', "ARG", OPTION_HIDDEN | OPTION_ARG_OPTIONAL, NULL, 0 },
80 { "demangler", OPT_DEMANGLER, "ARG", OPTION_HIDDEN, NULL, 0 },
81 { NULL, 0, NULL, 0, NULL, 0 }
84 /* Short description of program. */
85 static const char doc[] = N_("\
86 Locate source files and line information for ADDRs (in a.out by default).");
88 /* Strings for arguments in help texts. */
89 static const char args_doc[] = N_("[ADDR...]");
91 /* Prototype for option handler. */
92 static error_t parse_opt (int key, char *arg, struct argp_state *state);
94 static struct argp_child argp_children[2]; /* [0] is set in main. */
96 /* Data structure to communicate with argp functions. */
97 static const struct argp argp =
99 options, parse_opt, args_doc, doc, argp_children, NULL, NULL
104 static int handle_address (const char *addr, Dwfl *dwfl);
107 /* True if only base names of files should be shown. */
108 static bool only_basenames;
110 /* True if absolute file names based on DW_AT_comp_dir should be shown. */
111 static bool use_comp_dir;
113 /* True if line flags should be shown. */
114 static bool show_flags;
116 /* True if function names should be shown. */
117 static bool show_functions;
119 /* True if ELF symbol or section info should be shown. */
120 static bool show_symbols;
122 /* If non-null, take address parameters as relative to named section. */
123 static const char *just_section;
127 main (int argc, char *argv[])
132 /* Make memory leak detection possible. */
135 /* We use no threads here which can interfere with handling a stream. */
136 (void) __fsetlocking (stdout, FSETLOCKING_BYCALLER);
139 (void) setlocale (LC_ALL, "");
141 /* Make sure the message catalog can be found. */
142 (void) bindtextdomain (PACKAGE_TARNAME, LOCALEDIR);
144 /* Initialize the message catalog. */
145 (void) textdomain (PACKAGE_TARNAME);
147 /* Parse and process arguments. This includes opening the modules. */
148 argp_children[0].argp = dwfl_standard_argp ();
149 argp_children[0].group = 1;
151 (void) argp_parse (&argp, argc, argv, 0, &remaining, &dwfl);
152 assert (dwfl != NULL);
154 /* Now handle the addresses. In case none are given on the command
155 line, read from stdin. */
156 if (remaining == argc)
158 /* We use no threads here which can interfere with handling a stream. */
159 (void) __fsetlocking (stdin, FSETLOCKING_BYCALLER);
163 while (!feof_unlocked (stdin))
165 if (getline (&buf, &len, stdin) < 0)
168 result = handle_address (buf, dwfl);
176 result = handle_address (argv[remaining], dwfl);
177 while (++remaining < argc);
184 /* Print the version information. */
186 print_version (FILE *stream, struct argp_state *state __attribute__ ((unused)))
188 fprintf (stream, "addr2line (%s) %s\n", PACKAGE_NAME, PACKAGE_VERSION);
189 fprintf (stream, gettext ("\
190 Copyright (C) %s Red Hat, Inc.\n\
191 This is free software; see the source for copying conditions. There is NO\n\
192 warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.\n\
194 fprintf (stream, gettext ("Written by %s.\n"), "Ulrich Drepper");
198 /* Handle program arguments. */
200 parse_opt (int key, char *arg, struct argp_state *state)
205 state->child_inputs[0] = state->input;
211 /* Ignored for compatibility. */
215 only_basenames = true;
223 show_functions = true;
239 return ARGP_ERR_UNKNOWN;
246 print_dwarf_function (Dwfl_Module *mod, Dwarf_Addr addr)
249 Dwarf_Die *cudie = dwfl_module_addrdie (mod, addr, &bias);
252 int nscopes = dwarf_getscopes (cudie, addr - bias, &scopes);
256 for (int i = 0; i < nscopes; ++i)
257 switch (dwarf_tag (&scopes[i]))
259 case DW_TAG_subprogram:
261 const char *name = dwarf_diename (&scopes[i]);
268 case DW_TAG_inlined_subroutine:
270 const char *name = dwarf_diename (&scopes[i]);
273 printf ("%s inlined", name);
276 if (dwarf_getsrcfiles (cudie, &files, NULL) == 0)
278 Dwarf_Attribute attr_mem;
280 if (dwarf_formudata (dwarf_attr (&scopes[i],
282 &attr_mem), &val) == 0)
284 const char *file = dwarf_filesrc (files, val, NULL, NULL);
285 unsigned int lineno = 0;
286 unsigned int colno = 0;
287 if (dwarf_formudata (dwarf_attr (&scopes[i],
289 &attr_mem), &val) == 0)
291 if (dwarf_formudata (dwarf_attr (&scopes[i],
293 &attr_mem), &val) == 0)
296 const char *comp_dir = "";
297 const char *comp_dir_sep = "";
301 else if (only_basenames)
302 file = basename (file);
303 else if (use_comp_dir && file[0] != '/')
305 const char *const *dirs;
307 if (dwarf_getsrcdirs (files, &dirs, &ndirs) == 0
316 printf (" from %s%s%s",
317 comp_dir, comp_dir_sep, file);
319 printf (" at %s%s%s:%u",
320 comp_dir, comp_dir_sep, file, lineno);
322 printf (" at %s%s%s:%u:%u",
323 comp_dir, comp_dir_sep, file, lineno, colno);
335 print_addrsym (Dwfl_Module *mod, GElf_Addr addr)
339 const char *name = dwfl_module_addrsym (mod, addr, &s, &shndx);
342 /* No symbol name. Get a section name instead. */
343 int i = dwfl_module_relocate_address (mod, &addr);
345 name = dwfl_module_relocation_info (mod, i, NULL);
349 printf ("(%s)+%#" PRIx64 "\n", name, addr);
351 else if (addr == s.st_value)
354 printf ("%s+%#" PRIx64 "\n", name, addr - s.st_value);
358 see_one_module (Dwfl_Module *mod,
359 void **userdata __attribute__ ((unused)),
360 const char *name __attribute__ ((unused)),
361 Dwarf_Addr start __attribute__ ((unused)),
364 Dwfl_Module **result = arg;
366 return DWARF_CB_ABORT;
372 find_symbol (Dwfl_Module *mod,
373 void **userdata __attribute__ ((unused)),
374 const char *name __attribute__ ((unused)),
375 Dwarf_Addr start __attribute__ ((unused)),
378 const char *looking_for = ((void **) arg)[0];
379 GElf_Sym *symbol = ((void **) arg)[1];
381 int n = dwfl_module_getsymtab (mod);
382 for (int i = 1; i < n; ++i)
384 const char *symbol_name = dwfl_module_getsym (mod, i, symbol, NULL);
385 if (symbol_name == NULL || symbol_name[0] == '\0')
387 switch (GELF_ST_TYPE (symbol->st_info))
394 if (!strcmp (symbol_name, looking_for))
396 ((void **) arg)[0] = NULL;
397 return DWARF_CB_ABORT;
406 adjust_to_section (const char *name, uintmax_t *addr, Dwfl *dwfl)
408 /* It was (section)+offset. This makes sense if there is
409 only one module to look in for a section. */
410 Dwfl_Module *mod = NULL;
411 if (dwfl_getmodules (dwfl, &see_one_module, &mod, 0) != 0
413 error (EXIT_FAILURE, 0, gettext ("Section syntax requires"
414 " exactly one module"));
416 int nscn = dwfl_module_relocations (mod);
417 for (int i = 0; i < nscn; ++i)
420 const char *scn = dwfl_module_relocation_info (mod, i, &shndx);
421 if (unlikely (scn == NULL))
423 if (!strcmp (scn, name))
425 /* Found the section. */
428 GElf_Shdr *shdr = gelf_getshdr
429 (elf_getscn (dwfl_module_getelf (mod, &shdr_bias), shndx),
431 if (unlikely (shdr == NULL))
434 if (*addr >= shdr->sh_size)
436 gettext ("offset %#" PRIxMAX " lies outside"
440 *addr += shdr->sh_addr + shdr_bias;
449 handle_address (const char *string, Dwfl *dwfl)
452 uintmax_t addr = strtoumax (string, &endp, 0);
458 if (sscanf (string, "(%m[^)])%" PRIiMAX "%n", &name, &addr, &i) == 2
459 && string[i] == '\0')
460 parsed = adjust_to_section (name, &addr, dwfl);
461 switch (sscanf (string, "%m[^-+]%n%" PRIiMAX "%n", &name, &i, &addr, &j))
469 if (string[j] != '\0')
472 /* It was symbol[+offset]. */
474 void *arg[2] = { name, &sym };
475 (void) dwfl_getmodules (dwfl, &find_symbol, arg, 0);
477 error (0, 0, gettext ("cannot find symbol '%s'"), name);
480 if (sym.st_size != 0 && addr >= sym.st_size)
482 gettext ("offset %#" PRIxMAX " lies outside"
483 " contents of '%s'"),
485 addr += sym.st_value;
495 else if (just_section != NULL
496 && !adjust_to_section (just_section, &addr, dwfl))
499 Dwfl_Module *mod = dwfl_addrmodule (dwfl, addr);
503 /* First determine the function name. Use the DWARF information if
505 if (! print_dwarf_function (mod, addr) && !show_symbols)
506 puts (dwfl_module_addrname (mod, addr) ?: "??");
510 print_addrsym (mod, addr);
512 Dwfl_Line *line = dwfl_module_getsrc (mod, addr);
516 if (line != NULL && (src = dwfl_lineinfo (line, &addr, &lineno, &linecol,
517 NULL, NULL)) != NULL)
519 const char *comp_dir = "";
520 const char *comp_dir_sep = "";
523 src = basename (src);
524 else if (use_comp_dir && src[0] != '/')
526 comp_dir = dwfl_line_comp_dir (line);
527 if (comp_dir != NULL)
532 printf ("%s%s%s:%d:%d",
533 comp_dir, comp_dir_sep, src, lineno, linecol);
536 comp_dir, comp_dir_sep, src, lineno);
541 Dwarf_Line *info = dwfl_dwarf_line (line, &bias);
542 assert (info != NULL);
544 inline void show (int (*get) (Dwarf_Line *, bool *),
548 if ((*get) (info, &flag) == 0 && flag)
549 fputs (note, stdout);
551 inline void show_int (int (*get) (Dwarf_Line *, unsigned int *),
555 if ((*get) (info, &val) == 0 && val != 0)
556 printf (" (%s %u)", name, val);
559 show (&dwarf_linebeginstatement, " (is_stmt)");
560 show (&dwarf_lineblock, " (basic_block)");
561 show (&dwarf_lineprologueend, " (prologue_end)");
562 show (&dwarf_lineepiloguebegin, " (epilogue_begin)");
563 show_int (&dwarf_lineisa, "isa");
564 show_int (&dwarf_linediscriminator, "discriminator");
575 #include "debugpred.h"