1/* Locate source files and line information for given addresses
2   Copyright (C) 2005-2010, 2012, 2013 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.  */
45static void print_version (FILE *stream, struct argp_state *state);
46ARGP_PROGRAM_VERSION_HOOK_DEF = print_version;
47
48/* Bug report address.  */
49ARGP_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.  */
56static 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  { "symbols-sections", 'x', NULL, 0, N_("Also show symbol and the section names"), 0 },
65  { "flags", 'F', NULL, 0, N_("Also show line table flags"), 0 },
66  { "section", 'j', "NAME", 0,
67    N_("Treat addresses as offsets relative to NAME section."), 0 },
68  { "inlines", 'i', NULL, 0,
69    N_("Show all source locations that caused inline expansion of subroutines at the address."),
70    0 },
71
72  { NULL, 0, NULL, 0, N_("Miscellaneous:"), 0 },
73  /* Unsupported options.  */
74  { "target", 'b', "ARG", OPTION_HIDDEN, NULL, 0 },
75  { "demangle", 'C', "ARG", OPTION_HIDDEN | OPTION_ARG_OPTIONAL, NULL, 0 },
76  { "demangler", OPT_DEMANGLER, "ARG", OPTION_HIDDEN, NULL, 0 },
77  { NULL, 0, NULL, 0, NULL, 0 }
78};
79
80/* Short description of program.  */
81static const char doc[] = N_("\
82Locate source files and line information for ADDRs (in a.out by default).");
83
84/* Strings for arguments in help texts.  */
85static const char args_doc[] = N_("[ADDR...]");
86
87/* Prototype for option handler.  */
88static error_t parse_opt (int key, char *arg, struct argp_state *state);
89
90static struct argp_child argp_children[2]; /* [0] is set in main.  */
91
92/* Data structure to communicate with argp functions.  */
93static const struct argp argp =
94{
95  options, parse_opt, args_doc, doc, argp_children, NULL, NULL
96};
97
98
99/* Handle ADDR.  */
100static int handle_address (const char *addr, Dwfl *dwfl);
101
102
103/* True if only base names of files should be shown.  */
104static bool only_basenames;
105
106/* True if absolute file names based on DW_AT_comp_dir should be shown.  */
107static bool use_comp_dir;
108
109/* True if line flags should be shown.  */
110static bool show_flags;
111
112/* True if function names should be shown.  */
113static bool show_functions;
114
115/* True if ELF symbol or section info should be shown.  */
116static bool show_symbols;
117
118/* True if section associated with a symbol address should be shown.  */
119static bool show_symbol_sections;
120
121/* If non-null, take address parameters as relative to named section.  */
122static const char *just_section;
123
124/* True if all inlined subroutines of the current address should be shown.  */
125static bool show_inlines;
126
127
128int
129main (int argc, char *argv[])
130{
131  int remaining;
132  int result = 0;
133
134  /* Make memory leak detection possible.  */
135  mtrace ();
136
137  /* We use no threads here which can interfere with handling a stream.  */
138  (void) __fsetlocking (stdout, FSETLOCKING_BYCALLER);
139
140  /* Set locale.  */
141  (void) setlocale (LC_ALL, "");
142
143  /* Make sure the message catalog can be found.  */
144  (void) bindtextdomain (PACKAGE_TARNAME, LOCALEDIR);
145
146  /* Initialize the message catalog.  */
147  (void) textdomain (PACKAGE_TARNAME);
148
149  /* Parse and process arguments.  This includes opening the modules.  */
150  argp_children[0].argp = dwfl_standard_argp ();
151  argp_children[0].group = 1;
152  Dwfl *dwfl = NULL;
153  (void) argp_parse (&argp, argc, argv, 0, &remaining, &dwfl);
154  assert (dwfl != NULL);
155
156  /* Now handle the addresses.  In case none are given on the command
157     line, read from stdin.  */
158  if (remaining == argc)
159    {
160      /* We use no threads here which can interfere with handling a stream.  */
161      (void) __fsetlocking (stdin, FSETLOCKING_BYCALLER);
162
163      char *buf = NULL;
164      size_t len = 0;
165      ssize_t chars;
166      while (!feof_unlocked (stdin))
167	{
168	  if ((chars = getline (&buf, &len, stdin)) < 0)
169	    break;
170
171	  if (buf[chars - 1] == '\n')
172	    buf[chars - 1] = '\0';
173
174	  result = handle_address (buf, dwfl);
175	}
176
177      free (buf);
178    }
179  else
180    {
181      do
182	result = handle_address (argv[remaining], dwfl);
183      while (++remaining < argc);
184    }
185
186  dwfl_end (dwfl);
187  return result;
188}
189
190
191/* Print the version information.  */
192static void
193print_version (FILE *stream, struct argp_state *state __attribute__ ((unused)))
194{
195  fprintf (stream, "addr2line (%s) %s\n", PACKAGE_NAME, PACKAGE_VERSION);
196  fprintf (stream, gettext ("\
197Copyright (C) %s Red Hat, Inc.\n\
198This is free software; see the source for copying conditions.  There is NO\n\
199warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.\n\
200"), "2012");
201  fprintf (stream, gettext ("Written by %s.\n"), "Ulrich Drepper");
202}
203
204
205/* Handle program arguments.  */
206static error_t
207parse_opt (int key, char *arg, struct argp_state *state)
208{
209  switch (key)
210    {
211    case ARGP_KEY_INIT:
212      state->child_inputs[0] = state->input;
213      break;
214
215    case 'b':
216    case 'C':
217    case OPT_DEMANGLER:
218      /* Ignored for compatibility.  */
219      break;
220
221    case 's':
222      only_basenames = true;
223      break;
224
225    case 'A':
226      use_comp_dir = true;
227      break;
228
229    case 'f':
230      show_functions = true;
231      break;
232
233    case 'F':
234      show_flags = true;
235      break;
236
237    case 'S':
238      show_symbols = true;
239      break;
240
241    case 'x':
242      show_symbols = true;
243      show_symbol_sections = true;
244      break;
245
246    case 'j':
247      just_section = arg;
248      break;
249
250    case 'i':
251      show_inlines = true;
252      break;
253
254    default:
255      return ARGP_ERR_UNKNOWN;
256    }
257  return 0;
258}
259
260
261static const char *
262get_diename (Dwarf_Die *die)
263{
264  Dwarf_Attribute attr;
265  const char *name;
266
267  name = dwarf_formstring (dwarf_attr_integrate (die, DW_AT_MIPS_linkage_name,
268						 &attr)
269			   ?: dwarf_attr_integrate (die, DW_AT_linkage_name,
270						    &attr));
271
272  if (name == NULL)
273    name = dwarf_diename (die) ?: "??";
274
275  return name;
276}
277
278static bool
279print_dwarf_function (Dwfl_Module *mod, Dwarf_Addr addr)
280{
281  Dwarf_Addr bias = 0;
282  Dwarf_Die *cudie = dwfl_module_addrdie (mod, addr, &bias);
283
284  Dwarf_Die *scopes;
285  int nscopes = dwarf_getscopes (cudie, addr - bias, &scopes);
286  if (nscopes <= 0)
287    return false;
288
289  for (int i = 0; i < nscopes; ++i)
290    switch (dwarf_tag (&scopes[i]))
291      {
292      case DW_TAG_subprogram:
293	{
294	  const char *name = get_diename (&scopes[i]);
295	  if (name == NULL)
296	    return false;
297	  puts (name);
298	  return true;
299	}
300
301      case DW_TAG_inlined_subroutine:
302	{
303	  const char *name = get_diename (&scopes[i]);
304	  if (name == NULL)
305	    return false;
306	  printf ("%s inlined", name);
307
308	  Dwarf_Files *files;
309	  if (dwarf_getsrcfiles (cudie, &files, NULL) == 0)
310	    {
311	      Dwarf_Attribute attr_mem;
312	      Dwarf_Word val;
313	      if (dwarf_formudata (dwarf_attr (&scopes[i],
314					       DW_AT_call_file,
315					       &attr_mem), &val) == 0)
316		{
317		  const char *file = dwarf_filesrc (files, val, NULL, NULL);
318		  unsigned int lineno = 0;
319		  unsigned int colno = 0;
320		  if (dwarf_formudata (dwarf_attr (&scopes[i],
321						   DW_AT_call_line,
322						   &attr_mem), &val) == 0)
323		    lineno = val;
324		  if (dwarf_formudata (dwarf_attr (&scopes[i],
325						   DW_AT_call_column,
326						   &attr_mem), &val) == 0)
327		    colno = val;
328
329		  const char *comp_dir = "";
330		  const char *comp_dir_sep = "";
331
332		  if (file == NULL)
333		    file = "???";
334		  else if (only_basenames)
335		    file = basename (file);
336		  else if (use_comp_dir && file[0] != '/')
337		    {
338		      const char *const *dirs;
339		      size_t ndirs;
340		      if (dwarf_getsrcdirs (files, &dirs, &ndirs) == 0
341			  && dirs[0] != NULL)
342			{
343			  comp_dir = dirs[0];
344			  comp_dir_sep = "/";
345			}
346		    }
347
348		  if (lineno == 0)
349		    printf (" from %s%s%s",
350			    comp_dir, comp_dir_sep, file);
351		  else if (colno == 0)
352		    printf (" at %s%s%s:%u",
353			    comp_dir, comp_dir_sep, file, lineno);
354		  else
355		    printf (" at %s%s%s:%u:%u",
356			    comp_dir, comp_dir_sep, file, lineno, colno);
357		}
358	    }
359	  printf (" in ");
360	  continue;
361	}
362      }
363
364  return false;
365}
366
367static void
368print_addrsym (Dwfl_Module *mod, GElf_Addr addr)
369{
370  GElf_Sym s;
371  GElf_Off off;
372  const char *name = dwfl_module_addrinfo (mod, addr, &off, &s,
373					   NULL, NULL, NULL);
374  if (name == NULL)
375    {
376      /* No symbol name.  Get a section name instead.  */
377      int i = dwfl_module_relocate_address (mod, &addr);
378      if (i >= 0)
379	name = dwfl_module_relocation_info (mod, i, NULL);
380      if (name == NULL)
381	puts ("??");
382      else
383	printf ("(%s)+%#" PRIx64 "\n", name, addr);
384    }
385  else
386    {
387      if (off == 0)
388	printf ("%s", name);
389      else
390	printf ("%s+%#" PRIx64 "", name, off);
391
392      // Also show section name for address.
393      if (show_symbol_sections)
394	{
395	  Dwarf_Addr ebias;
396	  Elf_Scn *scn = dwfl_module_address_section (mod, &addr, &ebias);
397	  if (scn != NULL)
398	    {
399	      GElf_Shdr shdr_mem;
400	      GElf_Shdr *shdr = gelf_getshdr (scn, &shdr_mem);
401	      if (shdr != NULL)
402		{
403		  Elf *elf = dwfl_module_getelf (mod, &ebias);
404		  GElf_Ehdr ehdr;
405		  if (gelf_getehdr (elf, &ehdr) != NULL)
406		    printf (" (%s)", elf_strptr (elf, ehdr.e_shstrndx,
407						 shdr->sh_name));
408		}
409	    }
410	}
411      puts ("");
412    }
413}
414
415static int
416see_one_module (Dwfl_Module *mod,
417		void **userdata __attribute__ ((unused)),
418		const char *name __attribute__ ((unused)),
419		Dwarf_Addr start __attribute__ ((unused)),
420		void *arg)
421{
422  Dwfl_Module **result = arg;
423  if (*result != NULL)
424    return DWARF_CB_ABORT;
425  *result = mod;
426  return DWARF_CB_OK;
427}
428
429static int
430find_symbol (Dwfl_Module *mod,
431	     void **userdata __attribute__ ((unused)),
432	     const char *name __attribute__ ((unused)),
433	     Dwarf_Addr start __attribute__ ((unused)),
434	     void *arg)
435{
436  const char *looking_for = ((void **) arg)[0];
437  GElf_Sym *symbol = ((void **) arg)[1];
438  GElf_Addr *value = ((void **) arg)[2];
439
440  int n = dwfl_module_getsymtab (mod);
441  for (int i = 1; i < n; ++i)
442    {
443      const char *symbol_name = dwfl_module_getsym_info (mod, i, symbol,
444							 value, NULL, NULL,
445							 NULL);
446      if (symbol_name == NULL || symbol_name[0] == '\0')
447	continue;
448      switch (GELF_ST_TYPE (symbol->st_info))
449	{
450	case STT_SECTION:
451	case STT_FILE:
452	case STT_TLS:
453	  break;
454	default:
455	  if (!strcmp (symbol_name, looking_for))
456	    {
457	      ((void **) arg)[0] = NULL;
458	      return DWARF_CB_ABORT;
459	    }
460	}
461    }
462
463  return DWARF_CB_OK;
464}
465
466static bool
467adjust_to_section (const char *name, uintmax_t *addr, Dwfl *dwfl)
468{
469  /* It was (section)+offset.  This makes sense if there is
470     only one module to look in for a section.  */
471  Dwfl_Module *mod = NULL;
472  if (dwfl_getmodules (dwfl, &see_one_module, &mod, 0) != 0
473      || mod == NULL)
474    error (EXIT_FAILURE, 0, gettext ("Section syntax requires"
475				     " exactly one module"));
476
477  int nscn = dwfl_module_relocations (mod);
478  for (int i = 0; i < nscn; ++i)
479    {
480      GElf_Word shndx;
481      const char *scn = dwfl_module_relocation_info (mod, i, &shndx);
482      if (unlikely (scn == NULL))
483	break;
484      if (!strcmp (scn, name))
485	{
486	  /* Found the section.  */
487	  GElf_Shdr shdr_mem;
488	  GElf_Addr shdr_bias;
489	  GElf_Shdr *shdr = gelf_getshdr
490	    (elf_getscn (dwfl_module_getelf (mod, &shdr_bias), shndx),
491	     &shdr_mem);
492	  if (unlikely (shdr == NULL))
493	    break;
494
495	  if (*addr >= shdr->sh_size)
496	    error (0, 0,
497		   gettext ("offset %#" PRIxMAX " lies outside"
498			    " section '%s'"),
499		   *addr, scn);
500
501	  *addr += shdr->sh_addr + shdr_bias;
502	  return true;
503	}
504    }
505
506  return false;
507}
508
509static void
510print_src (const char *src, int lineno, int linecol, Dwarf_Die *cu)
511{
512  const char *comp_dir = "";
513  const char *comp_dir_sep = "";
514
515  if (only_basenames)
516    src = basename (src);
517  else if (use_comp_dir && src[0] != '/')
518    {
519      Dwarf_Attribute attr;
520      comp_dir = dwarf_formstring (dwarf_attr (cu, DW_AT_comp_dir, &attr));
521      if (comp_dir != NULL)
522	comp_dir_sep = "/";
523    }
524
525  if (linecol != 0)
526    printf ("%s%s%s:%d:%d",
527	    comp_dir, comp_dir_sep, src, lineno, linecol);
528  else
529    printf ("%s%s%s:%d",
530	    comp_dir, comp_dir_sep, src, lineno);
531}
532
533static int
534handle_address (const char *string, Dwfl *dwfl)
535{
536  char *endp;
537  uintmax_t addr = strtoumax (string, &endp, 0);
538  if (endp == string)
539    {
540      bool parsed = false;
541      int i, j;
542      char *name = NULL;
543      if (sscanf (string, "(%m[^)])%" PRIiMAX "%n", &name, &addr, &i) == 2
544	  && string[i] == '\0')
545	parsed = adjust_to_section (name, &addr, dwfl);
546      switch (sscanf (string, "%m[^-+]%n%" PRIiMAX "%n", &name, &i, &addr, &j))
547	{
548	default:
549	  break;
550	case 1:
551	  addr = 0;
552	  j = i;
553	case 2:
554	  if (string[j] != '\0')
555	    break;
556
557	  /* It was symbol[+offset].  */
558	  GElf_Sym sym;
559	  GElf_Addr value = 0;
560	  void *arg[3] = { name, &sym, &value };
561	  (void) dwfl_getmodules (dwfl, &find_symbol, arg, 0);
562	  if (arg[0] != NULL)
563	    error (0, 0, gettext ("cannot find symbol '%s'"), name);
564	  else
565	    {
566	      if (sym.st_size != 0 && addr >= sym.st_size)
567		error (0, 0,
568		       gettext ("offset %#" PRIxMAX " lies outside"
569				" contents of '%s'"),
570		       addr, name);
571	      addr += value;
572	      parsed = true;
573	    }
574	  break;
575	}
576
577      free (name);
578      if (!parsed)
579	return 1;
580    }
581  else if (just_section != NULL
582	   && !adjust_to_section (just_section, &addr, dwfl))
583    return 1;
584
585  Dwfl_Module *mod = dwfl_addrmodule (dwfl, addr);
586
587  if (show_functions)
588    {
589      /* First determine the function name.  Use the DWARF information if
590	 possible.  */
591      if (! print_dwarf_function (mod, addr) && !show_symbols)
592	puts (dwfl_module_addrname (mod, addr) ?: "??");
593    }
594
595  if (show_symbols)
596    print_addrsym (mod, addr);
597
598  Dwfl_Line *line = dwfl_module_getsrc (mod, addr);
599
600  const char *src;
601  int lineno, linecol;
602
603  if (line != NULL && (src = dwfl_lineinfo (line, &addr, &lineno, &linecol,
604					    NULL, NULL)) != NULL)
605    {
606      print_src (src, lineno, linecol, dwfl_linecu (line));
607      if (show_flags)
608	{
609	  Dwarf_Addr bias;
610	  Dwarf_Line *info = dwfl_dwarf_line (line, &bias);
611	  assert (info != NULL);
612
613	  inline void show (int (*get) (Dwarf_Line *, bool *),
614			    const char *note)
615	  {
616	    bool flag;
617	    if ((*get) (info, &flag) == 0 && flag)
618	      fputs (note, stdout);
619	  }
620	  inline void show_int (int (*get) (Dwarf_Line *, unsigned int *),
621				const char *name)
622	  {
623	    unsigned int val;
624	    if ((*get) (info, &val) == 0 && val != 0)
625	      printf (" (%s %u)", name, val);
626	  }
627
628	  show (&dwarf_linebeginstatement, " (is_stmt)");
629	  show (&dwarf_lineblock, " (basic_block)");
630	  show (&dwarf_lineprologueend, " (prologue_end)");
631	  show (&dwarf_lineepiloguebegin, " (epilogue_begin)");
632	  show_int (&dwarf_lineisa, "isa");
633	  show_int (&dwarf_linediscriminator, "discriminator");
634	}
635      putchar ('\n');
636    }
637  else
638    puts ("??:0");
639
640  if (show_inlines)
641    {
642      Dwarf_Addr bias = 0;
643      Dwarf_Die *cudie = dwfl_module_addrdie (mod, addr, &bias);
644
645      Dwarf_Die *scopes = NULL;
646      int nscopes = dwarf_getscopes (cudie, addr - bias, &scopes);
647      if (nscopes < 0)
648	return 1;
649
650      if (nscopes > 0)
651	{
652	  Dwarf_Die subroutine;
653	  Dwarf_Off dieoff = dwarf_dieoffset (&scopes[0]);
654	  dwarf_offdie (dwfl_module_getdwarf (mod, &bias),
655			dieoff, &subroutine);
656	  free (scopes);
657
658	  nscopes = dwarf_getscopes_die (&subroutine, &scopes);
659	  if (nscopes > 1)
660	    {
661	      Dwarf_Die cu;
662	      Dwarf_Files *files;
663	      if (dwarf_diecu (&scopes[0], &cu, NULL, NULL) != NULL
664		  && dwarf_getsrcfiles (cudie, &files, NULL) == 0)
665		{
666		  for (int i = 0; i < nscopes - 1; i++)
667		    {
668		      Dwarf_Word val;
669		      Dwarf_Attribute attr;
670		      Dwarf_Die *die = &scopes[i];
671		      if (dwarf_tag (die) != DW_TAG_inlined_subroutine)
672			continue;
673
674		      if (show_functions)
675			{
676			  /* Search for the parent inline or function.  It
677			     might not be directly above this inline -- e.g.
678			     there could be a lexical_block in between.  */
679			  for (int j = i + 1; j < nscopes; j++)
680			    {
681			      Dwarf_Die *parent = &scopes[j];
682			      int tag = dwarf_tag (parent);
683			      if (tag == DW_TAG_inlined_subroutine
684				  || tag == DW_TAG_entry_point
685				  || tag == DW_TAG_subprogram)
686				{
687				  puts (get_diename (parent));
688				  break;
689				}
690			    }
691			}
692
693		      src = NULL;
694		      lineno = 0;
695		      linecol = 0;
696		      if (dwarf_formudata (dwarf_attr (die, DW_AT_call_file,
697						       &attr), &val) == 0)
698			src = dwarf_filesrc (files, val, NULL, NULL);
699
700		      if (dwarf_formudata (dwarf_attr (die, DW_AT_call_line,
701						       &attr), &val) == 0)
702			lineno = val;
703
704		      if (dwarf_formudata (dwarf_attr (die, DW_AT_call_column,
705						       &attr), &val) == 0)
706			linecol = val;
707
708		      if (src != NULL)
709			{
710			  print_src (src, lineno, linecol, &cu);
711			  putchar ('\n');
712			}
713		      else
714			puts ("??:0");
715		    }
716		}
717	    }
718	}
719      free (scopes);
720    }
721
722  return 0;
723}
724
725
726#include "debugpred.h"
727