LCOV - code coverage report
Current view: top level - src - addr2line.c (source / functions) Hit Total Coverage
Test: elfutils-0.173 Lines: 222 290 76.6 %
Date: 2018-06-29 23:49:12 Functions: 10 14 71.4 %
Legend: Lines: hit not hit

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

Generated by: LCOV version 1.13