Home | History | Annotate | Download | only in src
      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 (at) 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"
    576