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