1 /* addr2line.c -- convert addresses to line number and function name
2    Copyright (C) 1997-2024 Free Software Foundation, Inc.
3    Contributed by Ulrich Lauther <Ulrich.Lauther@mchp.siemens.de>
4 
5    This file is part of GNU Binutils.
6 
7    This program is free software; you can redistribute it and/or modify
8    it under the terms of the GNU General Public License as published by
9    the Free Software Foundation; either version 3, or (at your option)
10    any later version.
11 
12    This program is distributed in the hope that it will be useful,
13    but WITHOUT ANY WARRANTY; without even the implied warranty of
14    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15    GNU General Public License for more details.
16 
17    You should have received a copy of the GNU General Public License
18    along with this program; if not, write to the Free Software
19    Foundation, 51 Franklin Street - Fifth Floor, Boston,
20    MA 02110-1301, USA.  */
21 
22 
23 /* Derived from objdump.c and nm.c by Ulrich.Lauther@mchp.siemens.de
24 
25    Usage:
26    addr2line [options] addr addr ...
27    or
28    addr2line [options]
29 
30    both forms write results to stdout, the second form reads addresses
31    to be converted from stdin.  */
32 
33 #include "sysdep.h"
34 #include "bfd.h"
35 #include "getopt.h"
36 #include "libiberty.h"
37 #include "demangle.h"
38 #include "bucomm.h"
39 #include "elf-bfd.h"
40 #include "safe-ctype.h"
41 
42 static bool unwind_inlines;   /* -i, unwind inlined functions. */
43 static bool with_addresses;   /* -a, show addresses.  */
44 static bool with_functions;   /* -f, show function names.  */
45 static bool do_demangle;      /* -C, demangle names.  */
46 static bool pretty_print;     /* -p, print on one line.  */
47 static bool base_names;                 /* -s, strip directory names.  */
48 
49 /* Flags passed to the name demangler.  */
50 static int demangle_flags = DMGL_PARAMS | DMGL_ANSI;
51 
52 static int naddr;             /* Number of addresses to process.  */
53 static char **addr;           /* Hex addresses to process.  */
54 
55 static long symcount;
56 static asymbol **syms;                  /* Symbol table.  */
57 
58 static struct option long_options[] =
59 {
60   {"addresses", no_argument, NULL, 'a'},
61   {"basenames", no_argument, NULL, 's'},
62   {"demangle", optional_argument, NULL, 'C'},
63   {"exe", required_argument, NULL, 'e'},
64   {"functions", no_argument, NULL, 'f'},
65   {"inlines", no_argument, NULL, 'i'},
66   {"pretty-print", no_argument, NULL, 'p'},
67   {"recurse-limit", no_argument, NULL, 'R'},
68   {"recursion-limit", no_argument, NULL, 'R'},
69   {"no-recurse-limit", no_argument, NULL, 'r'},
70   {"no-recursion-limit", no_argument, NULL, 'r'},
71   {"section", required_argument, NULL, 'j'},
72   {"target", required_argument, NULL, 'b'},
73   {"help", no_argument, NULL, 'H'},
74   {"version", no_argument, NULL, 'V'},
75   {0, no_argument, 0, 0}
76 };
77 
78 static void usage (FILE *, int);
79 static void slurp_symtab (bfd *);
80 static void find_address_in_section (bfd *, asection *, void *);
81 static void find_offset_in_section (bfd *, asection *);
82 static void translate_addresses (bfd *, asection *);
83 
84 /* Print a usage message to STREAM and exit with STATUS.  */
85 
86 static void
usage(FILE * stream,int status)87 usage (FILE *stream, int status)
88 {
89   fprintf (stream, _("Usage: %s [option(s)] [addr(s)]\n"), program_name);
90   fprintf (stream, _(" Convert addresses into line number/file name pairs.\n"));
91   fprintf (stream, _(" If no addresses are specified on the command line, they will be read from stdin\n"));
92   fprintf (stream, _(" The options are:\n\
93   @<file>                Read options from <file>\n\
94   -a --addresses         Show addresses\n\
95   -b --target=<bfdname>  Set the binary file format\n\
96   -e --exe=<executable>  Set the input file name (default is a.out)\n\
97   -i --inlines           Unwind inlined functions\n\
98   -j --section=<name>    Read section-relative offsets instead of addresses\n\
99   -p --pretty-print      Make the output easier to read for humans\n\
100   -s --basenames         Strip directory names\n\
101   -f --functions         Show function names\n\
102   -C --demangle[=style]  Demangle function names\n\
103   -R --recurse-limit     Enable a limit on recursion whilst demangling.  [Default]\n\
104   -r --no-recurse-limit  Disable a limit on recursion whilst demangling\n\
105   -h --help              Display this information\n\
106   -v --version           Display the program's version\n\
107 \n"));
108 
109   list_supported_targets (program_name, stream);
110   if (REPORT_BUGS_TO[0] && status == 0)
111     fprintf (stream, _("Report bugs to %s\n"), REPORT_BUGS_TO);
112   exit (status);
113 }
114 
115 /* Read in the symbol table.  */
116 
117 static void
slurp_symtab(bfd * abfd)118 slurp_symtab (bfd *abfd)
119 {
120   long storage;
121   bool dynamic = false;
122 
123   if ((bfd_get_file_flags (abfd) & HAS_SYMS) == 0)
124     return;
125 
126   storage = bfd_get_symtab_upper_bound (abfd);
127   if (storage == 0)
128     {
129       storage = bfd_get_dynamic_symtab_upper_bound (abfd);
130       dynamic = true;
131     }
132   if (storage < 0)
133     {
134       bfd_nonfatal (bfd_get_filename (abfd));
135       return;
136     }
137 
138   syms = (asymbol **) xmalloc (storage);
139   if (dynamic)
140     symcount = bfd_canonicalize_dynamic_symtab (abfd, syms);
141   else
142     symcount = bfd_canonicalize_symtab (abfd, syms);
143   if (symcount < 0)
144     bfd_nonfatal (bfd_get_filename (abfd));
145 
146   /* If there are no symbols left after canonicalization and
147      we have not tried the dynamic symbols then give them a go.  */
148   if (symcount == 0
149       && ! dynamic
150       && (storage = bfd_get_dynamic_symtab_upper_bound (abfd)) > 0)
151     {
152       free (syms);
153       syms = xmalloc (storage);
154       symcount = bfd_canonicalize_dynamic_symtab (abfd, syms);
155     }
156 
157   /* PR 17512: file: 2a1d3b5b.
158      Do not pretend that we have some symbols when we don't.  */
159   if (symcount <= 0)
160     {
161       free (syms);
162       syms = NULL;
163     }
164 }
165 
166 /* These global variables are used to pass information between
167    translate_addresses and find_address_in_section.  */
168 
169 static bfd_vma pc;
170 static const char *filename;
171 static const char *functionname;
172 static unsigned int line;
173 static unsigned int discriminator;
174 static bool found;
175 
176 /* Look for an address in a section.  This is called via
177    bfd_map_over_sections.  */
178 
179 static void
find_address_in_section(bfd * abfd,asection * section,void * data ATTRIBUTE_UNUSED)180 find_address_in_section (bfd *abfd, asection *section,
181                                void *data ATTRIBUTE_UNUSED)
182 {
183   bfd_vma vma;
184   bfd_size_type size;
185 
186   if (found)
187     return;
188 
189   if ((bfd_section_flags (section) & SEC_ALLOC) == 0)
190     return;
191 
192   vma = bfd_section_vma (section);
193   if (pc < vma)
194     return;
195 
196   size = bfd_section_size (section);
197   if (pc >= vma + size)
198     return;
199 
200   found = bfd_find_nearest_line_discriminator (abfd, section, syms, pc - vma,
201                                                &filename, &functionname,
202                                                &line, &discriminator);
203 }
204 
205 /* Look for an offset in a section.  This is directly called.  */
206 
207 static void
find_offset_in_section(bfd * abfd,asection * section)208 find_offset_in_section (bfd *abfd, asection *section)
209 {
210   bfd_size_type size;
211 
212   if (found)
213     return;
214 
215   if ((bfd_section_flags (section) & SEC_ALLOC) == 0)
216     return;
217 
218   size = bfd_section_size (section);
219   if (pc >= size)
220     return;
221 
222   found = bfd_find_nearest_line_discriminator (abfd, section, syms, pc,
223                                                &filename, &functionname,
224                                                &line, &discriminator);
225 }
226 
227 /* Lookup a symbol with offset in symbol table.  */
228 
229 static bfd_vma
lookup_symbol(bfd * abfd,char * sym,size_t offset)230 lookup_symbol (bfd *abfd, char *sym, size_t offset)
231 {
232   long i;
233 
234   for (i = 0; i < symcount; i++)
235     {
236       if (!strcmp (syms[i]->name, sym))
237           return syms[i]->value + offset + bfd_asymbol_section (syms[i])->vma;
238     }
239   /* Try again mangled */
240   for (i = 0; i < symcount; i++)
241     {
242       char *d = bfd_demangle (abfd, syms[i]->name, demangle_flags);
243       bool match = d && !strcmp (d, sym);
244       free (d);
245 
246       if (match)
247           return syms[i]->value + offset + bfd_asymbol_section (syms[i])->vma;
248     }
249   return 0;
250 }
251 
252 /* Split an symbol+offset expression. adr is modified.  */
253 
254 static bool
is_symbol(char * adr,char ** symp,size_t * offset)255 is_symbol (char *adr, char **symp, size_t *offset)
256 {
257   char *end;
258 
259   while (ISSPACE (*adr))
260     adr++;
261   if (ISDIGIT (*adr) || *adr == 0)
262     return false;
263   /* Could be either symbol or hex number. Check if it has +.  */
264   if (TOUPPER(*adr) >= 'A' && TOUPPER(*adr) <= 'F' && !strchr (adr, '+'))
265     return false;
266 
267   *symp = adr;
268   while (*adr && !ISSPACE (*adr) && *adr != '+')
269     adr++;
270   end = adr;
271   while (ISSPACE (*adr))
272     adr++;
273   *offset = 0;
274   if (*adr == '+')
275     {
276       adr++;
277       *offset = strtoul(adr, NULL, 0);
278     }
279   *end = 0;
280   return true;
281 }
282 
283 /* Read hexadecimal or symbolic with offset addresses from stdin, translate into
284    file_name:line_number and optionally function name.  */
285 
286 static void
translate_addresses(bfd * abfd,asection * section)287 translate_addresses (bfd *abfd, asection *section)
288 {
289   int read_stdin = (naddr == 0);
290   char *adr;
291   char addr_hex[100];
292   char *symp;
293   size_t offset;
294 
295   for (;;)
296     {
297       if (read_stdin)
298           {
299             if (fgets (addr_hex, sizeof addr_hex, stdin) == NULL)
300               break;
301             adr = addr_hex;
302           }
303       else
304           {
305             if (naddr <= 0)
306               break;
307             --naddr;
308             adr = *addr++;
309           }
310 
311       if (is_symbol (adr, &symp, &offset))
312         pc = lookup_symbol (abfd, symp, offset);
313       else
314         pc = bfd_scan_vma (adr, NULL, 16);
315       if (bfd_get_flavour (abfd) == bfd_target_elf_flavour)
316           {
317             const struct elf_backend_data *bed = get_elf_backend_data (abfd);
318             bfd_vma sign = (bfd_vma) 1 << (bed->s->arch_size - 1);
319 
320             pc &= (sign << 1) - 1;
321             if (bed->sign_extend_vma)
322               pc = (pc ^ sign) - sign;
323           }
324 
325       if (with_addresses)
326         {
327           printf ("0x");
328           bfd_printf_vma (abfd, pc);
329 
330           if (pretty_print)
331             printf (": ");
332           else
333             printf ("\n");
334         }
335 
336       found = false;
337       if (section)
338           find_offset_in_section (abfd, section);
339       else
340           bfd_map_over_sections (abfd, find_address_in_section, NULL);
341 
342       if (! found)
343           {
344             if (with_functions)
345               {
346                 if (pretty_print)
347                     printf ("?? ");
348                 else
349                     printf ("??\n");
350               }
351             printf ("??:0\n");
352           }
353       else
354           {
355             while (1)
356             {
357               if (with_functions)
358                 {
359                   const char *name;
360                   char *alloc = NULL;
361 
362                   name = functionname;
363                   if (name == NULL || *name == '\0')
364                     name = "??";
365                   else if (do_demangle)
366                     {
367                       alloc = bfd_demangle (abfd, name, demangle_flags);
368                       if (alloc != NULL)
369                         name = alloc;
370                     }
371 
372                   printf ("%s", name);
373                   if (pretty_print)
374                         /* Note for translators:  This printf is used to join the
375                            function name just printed above to the line number/
376                            file name pair that is about to be printed below.  Eg:
377 
378                              foo at 123:bar.c  */
379                     printf (_(" at "));
380                   else
381                     printf ("\n");
382 
383                       free (alloc);
384                 }
385 
386               if (base_names && filename != NULL)
387                 {
388                   char *h;
389 
390                   h = strrchr (filename, '/');
391                   if (h != NULL)
392                     filename = h + 1;
393                 }
394 
395               printf ("%s:", filename ? filename : "??");
396                 if (line != 0)
397                 {
398                   if (discriminator != 0)
399                     printf ("%u (discriminator %u)\n", line, discriminator);
400                   else
401                     printf ("%u\n", line);
402                 }
403                 else
404                     printf ("?\n");
405               if (!unwind_inlines)
406                 found = false;
407               else
408                 found = bfd_find_inliner_info (abfd, &filename, &functionname,
409                                                          &line);
410               if (! found)
411                 break;
412               if (pretty_print)
413                     /* Note for translators: This printf is used to join the
414                        line number/file name pair that has just been printed with
415                        the line number/file name pair that is going to be printed
416                        by the next iteration of the while loop.  Eg:
417 
418                          123:bar.c (inlined by) 456:main.c  */
419                 printf (_(" (inlined by) "));
420             }
421           }
422 
423       /* fflush() is essential for using this command as a server
424          child process that reads addresses from a pipe and responds
425          with line number information, processing one address at a
426          time.  */
427       fflush (stdout);
428     }
429 }
430 
431 /* Process a file.  Returns an exit value for main().  */
432 
433 static int
process_file(const char * file_name,const char * section_name,const char * target)434 process_file (const char *file_name, const char *section_name,
435                 const char *target)
436 {
437   bfd *abfd;
438   asection *section;
439   char **matching;
440 
441   if (get_file_size (file_name) < 1)
442     return 1;
443 
444   abfd = bfd_openr (file_name, target);
445   if (abfd == NULL)
446     bfd_fatal (file_name);
447 
448   /* Decompress sections.  */
449   abfd->flags |= BFD_DECOMPRESS;
450 
451   if (bfd_check_format (abfd, bfd_archive))
452     {
453       non_fatal (_("%s: cannot get addresses from archive"), file_name);
454       bfd_close (abfd);
455       return 1;
456     }
457 
458   if (! bfd_check_format_matches (abfd, bfd_object, &matching))
459     {
460       bfd_nonfatal (bfd_get_filename (abfd));
461       if (bfd_get_error () == bfd_error_file_ambiguously_recognized)
462           list_matching_formats (matching);
463       bfd_close (abfd);
464       return 1;
465     }
466 
467   if (section_name != NULL)
468     {
469       section = bfd_get_section_by_name (abfd, section_name);
470       if (section == NULL)
471           {
472             non_fatal (_("%s: cannot find section %s"), file_name, section_name);
473             bfd_close (abfd);
474             return 1;
475           }
476     }
477   else
478     section = NULL;
479 
480   slurp_symtab (abfd);
481 
482   translate_addresses (abfd, section);
483 
484   free (syms);
485   syms = NULL;
486 
487   bfd_close (abfd);
488 
489   return 0;
490 }
491 
492 int
main(int argc,char ** argv)493 main (int argc, char **argv)
494 {
495   const char *file_name;
496   const char *section_name;
497   char *target;
498   int c;
499 
500 #ifdef HAVE_LC_MESSAGES
501   setlocale (LC_MESSAGES, "");
502 #endif
503   setlocale (LC_CTYPE, "");
504   bindtextdomain (PACKAGE, LOCALEDIR);
505   textdomain (PACKAGE);
506 
507   program_name = *argv;
508   xmalloc_set_program_name (program_name);
509   bfd_set_error_program_name (program_name);
510 
511   expandargv (&argc, &argv);
512 
513   if (bfd_init () != BFD_INIT_MAGIC)
514     fatal (_("fatal error: libbfd ABI mismatch"));
515   set_default_bfd_target ();
516 
517   file_name = NULL;
518   section_name = NULL;
519   target = NULL;
520   while ((c = getopt_long (argc, argv, "ab:Ce:rRsfHhij:pVv", long_options, (int *) 0))
521            != EOF)
522     {
523       switch (c)
524           {
525           case 0:
526             break;            /* We've been given a long option.  */
527           case 'a':
528             with_addresses = true;
529             break;
530           case 'b':
531             target = optarg;
532             break;
533           case 'C':
534             do_demangle = true;
535             if (optarg != NULL)
536               {
537                 enum demangling_styles style;
538 
539                 style = cplus_demangle_name_to_style (optarg);
540                 if (style == unknown_demangling)
541                     fatal (_("unknown demangling style `%s'"),
542                            optarg);
543 
544                 cplus_demangle_set_style (style);
545               }
546             break;
547           case 'r':
548             demangle_flags |= DMGL_NO_RECURSE_LIMIT;
549             break;
550           case 'R':
551             demangle_flags &= ~ DMGL_NO_RECURSE_LIMIT;
552             break;
553           case 'e':
554             file_name = optarg;
555             break;
556           case 's':
557             base_names = true;
558             break;
559           case 'f':
560             with_functions = true;
561             break;
562         case 'p':
563           pretty_print = true;
564           break;
565           case 'v':
566           case 'V':
567             print_version ("addr2line");
568             break;
569           case 'h':
570           case 'H':
571             usage (stdout, 0);
572             break;
573           case 'i':
574             unwind_inlines = true;
575             break;
576           case 'j':
577             section_name = optarg;
578             break;
579           default:
580             usage (stderr, 1);
581             break;
582           }
583     }
584 
585   if (file_name == NULL)
586     file_name = "a.out";
587 
588   addr = argv + optind;
589   naddr = argc - optind;
590 
591   return process_file (file_name, section_name, target);
592 }
593