Imported Upstream version 0.155
[platform/upstream/elfutils.git] / src / addr2line.c
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.
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   { "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 },
67
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 }
74 };
75
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).");
79
80 /* Strings for arguments in help texts.  */
81 static const char args_doc[] = N_("[ADDR...]");
82
83 /* Prototype for option handler.  */
84 static error_t parse_opt (int key, char *arg, struct argp_state *state);
85
86 static struct argp_child argp_children[2]; /* [0] is set in main.  */
87
88 /* Data structure to communicate with argp functions.  */
89 static const struct argp argp =
90 {
91   options, parse_opt, args_doc, doc, argp_children, NULL, NULL
92 };
93
94
95 /* Handle ADDR.  */
96 static int handle_address (const char *addr, Dwfl *dwfl);
97
98
99 /* True if only base names of files should be shown.  */
100 static bool only_basenames;
101
102 /* True if absolute file names based on DW_AT_comp_dir should be shown.  */
103 static bool use_comp_dir;
104
105 /* True if line flags should be shown.  */
106 static bool show_flags;
107
108 /* True if function names should be shown.  */
109 static bool show_functions;
110
111 /* True if ELF symbol or section info should be shown.  */
112 static bool show_symbols;
113
114 /* If non-null, take address parameters as relative to named section.  */
115 static const char *just_section;
116
117
118 int
119 main (int argc, char *argv[])
120 {
121   int remaining;
122   int result = 0;
123
124   /* Make memory leak detection possible.  */
125   mtrace ();
126
127   /* We use no threads here which can interfere with handling a stream.  */
128   (void) __fsetlocking (stdout, FSETLOCKING_BYCALLER);
129
130   /* Set locale.  */
131   (void) setlocale (LC_ALL, "");
132
133   /* Make sure the message catalog can be found.  */
134   (void) bindtextdomain (PACKAGE_TARNAME, LOCALEDIR);
135
136   /* Initialize the message catalog.  */
137   (void) textdomain (PACKAGE_TARNAME);
138
139   /* Parse and process arguments.  This includes opening the modules.  */
140   argp_children[0].argp = dwfl_standard_argp ();
141   argp_children[0].group = 1;
142   Dwfl *dwfl = NULL;
143   (void) argp_parse (&argp, argc, argv, 0, &remaining, &dwfl);
144   assert (dwfl != NULL);
145
146   /* Now handle the addresses.  In case none are given on the command
147      line, read from stdin.  */
148   if (remaining == argc)
149     {
150       /* We use no threads here which can interfere with handling a stream.  */
151       (void) __fsetlocking (stdin, FSETLOCKING_BYCALLER);
152
153       char *buf = NULL;
154       size_t len = 0;
155       while (!feof_unlocked (stdin))
156         {
157           if (getline (&buf, &len, stdin) < 0)
158             break;
159
160           result = handle_address (buf, dwfl);
161         }
162
163       free (buf);
164     }
165   else
166     {
167       do
168         result = handle_address (argv[remaining], dwfl);
169       while (++remaining < argc);
170     }
171
172   return result;
173 }
174
175
176 /* Print the version information.  */
177 static void
178 print_version (FILE *stream, struct argp_state *state __attribute__ ((unused)))
179 {
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\
185 "), "2012");
186   fprintf (stream, gettext ("Written by %s.\n"), "Ulrich Drepper");
187 }
188
189
190 /* Handle program arguments.  */
191 static error_t
192 parse_opt (int key, char *arg, struct argp_state *state)
193 {
194   switch (key)
195     {
196     case ARGP_KEY_INIT:
197       state->child_inputs[0] = state->input;
198       break;
199
200     case 'b':
201     case 'C':
202     case OPT_DEMANGLER:
203       /* Ignored for compatibility.  */
204       break;
205
206     case 's':
207       only_basenames = true;
208       break;
209
210     case 'A':
211       use_comp_dir = true;
212       break;
213
214     case 'f':
215       show_functions = true;
216       break;
217
218     case 'F':
219       show_flags = true;
220       break;
221
222     case 'S':
223       show_symbols = true;
224       break;
225
226     case 'j':
227       just_section = arg;
228       break;
229
230     default:
231       return ARGP_ERR_UNKNOWN;
232     }
233   return 0;
234 }
235
236
237 static bool
238 print_dwarf_function (Dwfl_Module *mod, Dwarf_Addr addr)
239 {
240   Dwarf_Addr bias = 0;
241   Dwarf_Die *cudie = dwfl_module_addrdie (mod, addr, &bias);
242
243   Dwarf_Die *scopes;
244   int nscopes = dwarf_getscopes (cudie, addr - bias, &scopes);
245   if (nscopes <= 0)
246     return false;
247
248   for (int i = 0; i < nscopes; ++i)
249     switch (dwarf_tag (&scopes[i]))
250       {
251       case DW_TAG_subprogram:
252         {
253           const char *name = dwarf_diename (&scopes[i]);
254           if (name == NULL)
255             return false;
256           puts (name);
257           return true;
258         }
259
260       case DW_TAG_inlined_subroutine:
261         {
262           const char *name = dwarf_diename (&scopes[i]);
263           if (name == NULL)
264             return false;
265           printf ("%s inlined", name);
266
267           Dwarf_Files *files;
268           if (dwarf_getsrcfiles (cudie, &files, NULL) == 0)
269             {
270               Dwarf_Attribute attr_mem;
271               Dwarf_Word val;
272               if (dwarf_formudata (dwarf_attr (&scopes[i],
273                                                DW_AT_call_file,
274                                                &attr_mem), &val) == 0)
275                 {
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],
280                                                    DW_AT_call_line,
281                                                    &attr_mem), &val) == 0)
282                     lineno = val;
283                   if (dwarf_formudata (dwarf_attr (&scopes[i],
284                                                    DW_AT_call_column,
285                                                    &attr_mem), &val) == 0)
286                     colno = val;
287
288                   const char *comp_dir = "";
289                   const char *comp_dir_sep = "";
290
291                   if (file == NULL)
292                     file = "???";
293                   else if (only_basenames)
294                     file = basename (file);
295                   else if (use_comp_dir && file[0] != '/')
296                     {
297                       const char *const *dirs;
298                       size_t ndirs;
299                       if (dwarf_getsrcdirs (files, &dirs, &ndirs) == 0
300                           && dirs[0] != NULL)
301                         {
302                           comp_dir = dirs[0];
303                           comp_dir_sep = "/";
304                         }
305                     }
306
307                   if (lineno == 0)
308                     printf (" from %s%s%s",
309                             comp_dir, comp_dir_sep, file);
310                   else if (colno == 0)
311                     printf (" at %s%s%s:%u",
312                             comp_dir, comp_dir_sep, file, lineno);
313                   else
314                     printf (" at %s%s%s:%u:%u",
315                             comp_dir, comp_dir_sep, file, lineno, colno);
316                 }
317             }
318           printf (" in ");
319           continue;
320         }
321       }
322
323   return false;
324 }
325
326 static void
327 print_addrsym (Dwfl_Module *mod, GElf_Addr addr)
328 {
329   GElf_Sym s;
330   GElf_Word shndx;
331   const char *name = dwfl_module_addrsym (mod, addr, &s, &shndx);
332   if (name == NULL)
333     {
334       /* No symbol name.  Get a section name instead.  */
335       int i = dwfl_module_relocate_address (mod, &addr);
336       if (i >= 0)
337         name = dwfl_module_relocation_info (mod, i, NULL);
338       if (name == NULL)
339         puts ("??");
340       else
341         printf ("(%s)+%#" PRIx64 "\n", name, addr);
342     }
343   else if (addr == s.st_value)
344     puts (name);
345   else
346     printf ("%s+%#" PRIx64 "\n", name, addr - s.st_value);
347 }
348
349 static int
350 see_one_module (Dwfl_Module *mod,
351                 void **userdata __attribute__ ((unused)),
352                 const char *name __attribute__ ((unused)),
353                 Dwarf_Addr start __attribute__ ((unused)),
354                 void *arg)
355 {
356   Dwfl_Module **result = arg;
357   if (*result != NULL)
358     return DWARF_CB_ABORT;
359   *result = mod;
360   return DWARF_CB_OK;
361 }
362
363 static int
364 find_symbol (Dwfl_Module *mod,
365              void **userdata __attribute__ ((unused)),
366              const char *name __attribute__ ((unused)),
367              Dwarf_Addr start __attribute__ ((unused)),
368              void *arg)
369 {
370   const char *looking_for = ((void **) arg)[0];
371   GElf_Sym *symbol = ((void **) arg)[1];
372
373   int n = dwfl_module_getsymtab (mod);
374   for (int i = 1; i < n; ++i)
375     {
376       const char *symbol_name = dwfl_module_getsym (mod, i, symbol, NULL);
377       if (symbol_name == NULL || symbol_name[0] == '\0')
378         continue;
379       switch (GELF_ST_TYPE (symbol->st_info))
380         {
381         case STT_SECTION:
382         case STT_FILE:
383         case STT_TLS:
384           break;
385         default:
386           if (!strcmp (symbol_name, looking_for))
387             {
388               ((void **) arg)[0] = NULL;
389               return DWARF_CB_ABORT;
390             }
391         }
392     }
393
394   return DWARF_CB_OK;
395 }
396
397 static bool
398 adjust_to_section (const char *name, uintmax_t *addr, Dwfl *dwfl)
399 {
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
404       || mod == NULL)
405     error (EXIT_FAILURE, 0, gettext ("Section syntax requires"
406                                      " exactly one module"));
407
408   int nscn = dwfl_module_relocations (mod);
409   for (int i = 0; i < nscn; ++i)
410     {
411       GElf_Word shndx;
412       const char *scn = dwfl_module_relocation_info (mod, i, &shndx);
413       if (unlikely (scn == NULL))
414         break;
415       if (!strcmp (scn, name))
416         {
417           /* Found the section.  */
418           GElf_Shdr shdr_mem;
419           GElf_Addr shdr_bias;
420           GElf_Shdr *shdr = gelf_getshdr
421             (elf_getscn (dwfl_module_getelf (mod, &shdr_bias), shndx),
422              &shdr_mem);
423           if (unlikely (shdr == NULL))
424             break;
425
426           if (*addr >= shdr->sh_size)
427             error (0, 0,
428                    gettext ("offset %#" PRIxMAX " lies outside"
429                             " section '%s'"),
430                    *addr, scn);
431
432           *addr += shdr->sh_addr + shdr_bias;
433           return true;
434         }
435     }
436
437   return false;
438 }
439
440 static int
441 handle_address (const char *string, Dwfl *dwfl)
442 {
443   char *endp;
444   uintmax_t addr = strtoumax (string, &endp, 0);
445   if (endp == string)
446     {
447       bool parsed = false;
448       int i, j;
449       char *name = NULL;
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))
454         {
455         default:
456           break;
457         case 1:
458           addr = 0;
459           j = i;
460         case 2:
461           if (string[j] != '\0')
462             break;
463
464           /* It was symbol[+offset].  */
465           GElf_Sym sym;
466           void *arg[2] = { name, &sym };
467           (void) dwfl_getmodules (dwfl, &find_symbol, arg, 0);
468           if (arg[0] != NULL)
469             error (0, 0, gettext ("cannot find symbol '%s'"), name);
470           else
471             {
472               if (sym.st_size != 0 && addr >= sym.st_size)
473                 error (0, 0,
474                        gettext ("offset %#" PRIxMAX " lies outside"
475                                 " contents of '%s'"),
476                        addr, name);
477               addr += sym.st_value;
478               parsed = true;
479             }
480           break;
481         }
482
483       free (name);
484       if (!parsed)
485         return 1;
486     }
487   else if (just_section != NULL
488            && !adjust_to_section (just_section, &addr, dwfl))
489     return 1;
490
491   Dwfl_Module *mod = dwfl_addrmodule (dwfl, addr);
492
493   if (show_functions)
494     {
495       /* First determine the function name.  Use the DWARF information if
496          possible.  */
497       if (! print_dwarf_function (mod, addr) && !show_symbols)
498         puts (dwfl_module_addrname (mod, addr) ?: "??");
499     }
500
501   if (show_symbols)
502     print_addrsym (mod, addr);
503
504   Dwfl_Line *line = dwfl_module_getsrc (mod, addr);
505
506   const char *src;
507   int lineno, linecol;
508   if (line != NULL && (src = dwfl_lineinfo (line, &addr, &lineno, &linecol,
509                                             NULL, NULL)) != NULL)
510     {
511       const char *comp_dir = "";
512       const char *comp_dir_sep = "";
513
514       if (only_basenames)
515         src = basename (src);
516       else if (use_comp_dir && src[0] != '/')
517         {
518           comp_dir = dwfl_line_comp_dir (line);
519           if (comp_dir != NULL)
520             comp_dir_sep = "/";
521         }
522
523       if (linecol != 0)
524         printf ("%s%s%s:%d:%d",
525                 comp_dir, comp_dir_sep, src, lineno, linecol);
526       else
527         printf ("%s%s%s:%d",
528                 comp_dir, comp_dir_sep, src, lineno);
529
530       if (show_flags)
531         {
532           Dwarf_Addr bias;
533           Dwarf_Line *info = dwfl_dwarf_line (line, &bias);
534           assert (info != NULL);
535
536           inline void show (int (*get) (Dwarf_Line *, bool *),
537                             const char *note)
538           {
539             bool flag;
540             if ((*get) (info, &flag) == 0 && flag)
541               fputs (note, stdout);
542           }
543           inline void show_int (int (*get) (Dwarf_Line *, unsigned int *),
544                                 const char *name)
545           {
546             unsigned int val;
547             if ((*get) (info, &val) == 0 && val != 0)
548               printf (" (%s %u)", name, val);
549           }
550
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");
557         }
558       putchar ('\n');
559     }
560   else
561     puts ("??:0");
562
563   return 0;
564 }
565
566
567 #include "debugpred.h"