Home | History | Annotate | Download | only in tests
      1 /* Test program for dwarf_getscopes.
      2    Copyright (C) 2005 Red Hat, Inc.
      3    This file is part of Red Hat elfutils.
      4 
      5    Red Hat elfutils is free software; you can redistribute it and/or modify
      6    it under the terms of the GNU General Public License as published by the
      7    Free Software Foundation; version 2 of the License.
      8 
      9    Red Hat elfutils is distributed in the hope that it will be useful, but
     10    WITHOUT ANY WARRANTY; without even the implied warranty of
     11    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
     12    General Public License for more details.
     13 
     14    You should have received a copy of the GNU General Public License along
     15    with Red Hat elfutils; if not, write to the Free Software Foundation,
     16    Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301 USA.
     17 
     18    Red Hat elfutils is an included package of the Open Invention Network.
     19    An included package of the Open Invention Network is a package for which
     20    Open Invention Network licensees cross-license their patents.  No patent
     21    license is granted, either expressly or impliedly, by designation as an
     22    included package.  Should you wish to participate in the Open Invention
     23    Network licensing program, please visit www.openinventionnetwork.com
     24    <http://www.openinventionnetwork.com>.  */
     25 
     26 #include <config.h>
     27 #include <assert.h>
     28 #include <inttypes.h>
     29 #include ELFUTILS_HEADER(dwfl)
     30 #include <dwarf.h>
     31 #include <argp.h>
     32 #include <stdio.h>
     33 #include <stdio_ext.h>
     34 #include <locale.h>
     35 #include <stdlib.h>
     36 #include <error.h>
     37 #include <string.h>
     38 
     39 
     40 static void
     41 paddr (const char *prefix, Dwarf_Addr addr, Dwfl_Line *line)
     42 {
     43   const char *src;
     44   int lineno, linecol;
     45   if (line != NULL
     46       && (src = dwfl_lineinfo (line, &addr, &lineno, &linecol,
     47 			       NULL, NULL)) != NULL)
     48     {
     49       if (linecol != 0)
     50 	printf ("%s%#" PRIx64 " (%s:%d:%d)",
     51 		prefix, addr, src, lineno, linecol);
     52       else
     53 	printf ("%s%#" PRIx64 " (%s:%d)",
     54 		prefix, addr, src, lineno);
     55     }
     56   else
     57     printf ("%s%#" PRIx64, prefix, addr);
     58 }
     59 
     60 static void
     61 print_vars (unsigned int indent, Dwarf_Die *die)
     62 {
     63   Dwarf_Die child;
     64   if (dwarf_child (die, &child) == 0)
     65     do
     66       switch (dwarf_tag (&child))
     67 	{
     68 	case DW_TAG_variable:
     69 	case DW_TAG_formal_parameter:
     70 	  printf ("%*s%-30s[%6" PRIx64 "]\n", indent, "",
     71 		  dwarf_diename (&child),
     72 		  (uint64_t) dwarf_dieoffset (&child));
     73 	  break;
     74 	default:
     75 	  break;
     76 	}
     77     while (dwarf_siblingof (&child, &child) == 0);
     78 
     79   Dwarf_Attribute attr_mem;
     80   Dwarf_Die origin;
     81   if (dwarf_hasattr (die, DW_AT_abstract_origin)
     82       && dwarf_formref_die (dwarf_attr (die, DW_AT_abstract_origin, &attr_mem),
     83 			    &origin) != NULL
     84       && dwarf_child (&origin, &child) == 0)
     85     do
     86       switch (dwarf_tag (&child))
     87 	{
     88 	case DW_TAG_variable:
     89 	case DW_TAG_formal_parameter:
     90 	  printf ("%*s%s (abstract)\n", indent, "",
     91 		  dwarf_diename (&child));
     92 	  break;
     93 	default:
     94 	  break;
     95 	}
     96     while (dwarf_siblingof (&child, &child) == 0);
     97 }
     98 
     99 
    100 #define INDENT 4
    101 
    102 static void
    103 handle_address (GElf_Addr pc, Dwfl *dwfl)
    104 {
    105   Dwarf_Addr cubias;
    106   Dwarf_Die *cudie = dwfl_addrdie (dwfl, pc, &cubias);
    107   if (cudie == NULL)
    108     error (EXIT_FAILURE, 0, "dwfl_addrdie: %s", dwfl_errmsg (-1));
    109 
    110   Dwarf_Die *scopes;
    111   int n = dwarf_getscopes (cudie, pc - cubias, &scopes);
    112   if (n < 0)
    113     error (EXIT_FAILURE, 0, "dwarf_getscopes: %s", dwarf_errmsg (-1));
    114   else if (n == 0)
    115     printf ("%#" PRIx64 ": not in any scope\n", pc);
    116   else
    117     {
    118       printf ("%#" PRIx64 ":\n", pc);
    119       unsigned int indent = 0;
    120       while (n-- > 0)
    121 	{
    122 	  Dwarf_Die *const die = &scopes[n];
    123 
    124 	  indent += INDENT;
    125 	  printf ("%*s%s (%#x)", indent, "",
    126 		  dwarf_diename (die) ?: "<unnamed>",
    127 		  dwarf_tag (die));
    128 
    129 	  Dwarf_Addr lowpc, highpc;
    130 	  if (dwarf_lowpc (die, &lowpc) == 0
    131 	      && dwarf_highpc (die, &highpc) == 0)
    132 	    {
    133 	      lowpc += cubias;
    134 	      highpc += cubias;
    135 	      Dwfl_Line *loline = dwfl_getsrc (dwfl, lowpc);
    136 	      Dwfl_Line *hiline = dwfl_getsrc (dwfl, highpc);
    137 	      paddr (": ", lowpc, loline);
    138 	      if (highpc != lowpc)
    139 		paddr (" .. ", lowpc, hiline == loline ? NULL : hiline);
    140 	    }
    141 	  puts ("");
    142 
    143 	  print_vars (indent + INDENT, die);
    144 	}
    145     }
    146 }
    147 
    148 int
    149 main (int argc, char *argv[])
    150 {
    151   int remaining;
    152 
    153   /* Set locale.  */
    154   (void) setlocale (LC_ALL, "");
    155 
    156   Dwfl *dwfl = NULL;
    157   (void) argp_parse (dwfl_standard_argp (), argc, argv, 0, &remaining, &dwfl);
    158   assert (dwfl != NULL);
    159 
    160   int result = 0;
    161 
    162   /* Now handle the addresses.  In case none are given on the command
    163      line, read from stdin.  */
    164   if (remaining == argc)
    165     {
    166       /* We use no threads here which can interfere with handling a stream.  */
    167       (void) __fsetlocking (stdin, FSETLOCKING_BYCALLER);
    168 
    169       char *buf = NULL;
    170       size_t len = 0;
    171       while (!feof_unlocked (stdin))
    172 	{
    173 	  if (getline (&buf, &len, stdin) < 0)
    174 	    break;
    175 
    176 	  char *endp;
    177 	  uintmax_t addr = strtoumax (buf, &endp, 0);
    178 	  if (endp != buf)
    179 	    handle_address (addr, dwfl);
    180 	  else
    181 	    result = 1;
    182 	}
    183 
    184       free (buf);
    185     }
    186   else
    187     {
    188       do
    189 	{
    190 	  char *endp;
    191 	  uintmax_t addr = strtoumax (argv[remaining], &endp, 0);
    192 	  if (endp != argv[remaining])
    193 	    handle_address (addr, dwfl);
    194 	  else
    195 	    result = 1;
    196 	}
    197       while (++remaining < argc);
    198     }
    199 
    200   dwfl_end (dwfl);
    201 
    202   return result;
    203 }
    204