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

Generated by: LCOV version 1.13