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 #include <fnmatch.h>
     39 
     40 
     41 static void
     42 paddr (const char *prefix, Dwarf_Addr addr, Dwfl_Line *line)
     43 {
     44   const char *src;
     45   int lineno, linecol;
     46   if (line != NULL
     47       && (src = dwfl_lineinfo (line, &addr, &lineno, &linecol,
     48 			       NULL, NULL)) != NULL)
     49     {
     50       if (linecol != 0)
     51 	printf ("%s%#" PRIx64 " (%s:%d:%d)",
     52 		prefix, addr, src, lineno, linecol);
     53       else
     54 	printf ("%s%#" PRIx64 " (%s:%d)",
     55 		prefix, addr, src, lineno);
     56     }
     57   else
     58     printf ("%s%#" PRIx64, prefix, addr);
     59 }
     60 
     61 
     62 static void
     63 print_vars (unsigned int indent, Dwarf_Die *die)
     64 {
     65   Dwarf_Die child;
     66   if (dwarf_child (die, &child) == 0)
     67     do
     68       switch (dwarf_tag (&child))
     69 	{
     70 	case DW_TAG_variable:
     71 	case DW_TAG_formal_parameter:
     72 	  printf ("%*s%-30s[%6" PRIx64 "]\n", indent, "",
     73 		  dwarf_diename (&child),
     74 		  (uint64_t) dwarf_dieoffset (&child));
     75 	  break;
     76 	default:
     77 	  break;
     78 	}
     79     while (dwarf_siblingof (&child, &child) == 0);
     80 
     81   Dwarf_Attribute attr_mem;
     82   Dwarf_Die origin;
     83   if (dwarf_hasattr (die, DW_AT_abstract_origin)
     84       && dwarf_formref_die (dwarf_attr (die, DW_AT_abstract_origin, &attr_mem),
     85 			    &origin) != NULL
     86       && dwarf_child (&origin, &child) == 0)
     87     do
     88       switch (dwarf_tag (&child))
     89 	{
     90 	case DW_TAG_variable:
     91 	case DW_TAG_formal_parameter:
     92 	  printf ("%*s%s (abstract)\n", indent, "",
     93 		  dwarf_diename (&child));
     94 	  break;
     95 	default:
     96 	  break;
     97 	}
     98     while (dwarf_siblingof (&child, &child) == 0);
     99 }
    100 
    101 
    102 #define INDENT 4
    103 
    104 struct args
    105 {
    106   Dwfl *dwfl;
    107   Dwarf_Die *cu;
    108   Dwarf_Addr dwbias;
    109   char **argv;
    110 };
    111 
    112 static int
    113 handle_function (Dwarf_Die *funcdie, void *arg)
    114 {
    115   struct args *a = arg;
    116 
    117   const char *name = dwarf_diename (funcdie);
    118   char **argv = a->argv;
    119   if (argv[0] != NULL)
    120     {
    121       bool match;
    122       do
    123 	match = fnmatch (*argv, name, 0) == 0;
    124       while (!match && *++argv);
    125       if (!match)
    126 	return 0;
    127     }
    128 
    129   Dwarf_Die *scopes;
    130   int n = dwarf_getscopes_die (funcdie, &scopes);
    131   if (n <= 0)
    132     error (EXIT_FAILURE, 0, "dwarf_getscopes_die: %s", dwarf_errmsg (-1));
    133   else
    134     {
    135       Dwarf_Addr start, end;
    136       const char *fname;
    137       const char *modname = dwfl_module_info (dwfl_cumodule (a->cu), NULL,
    138 					      &start, &end,
    139 					      NULL, NULL,
    140 					      &fname, NULL);
    141       if (modname == NULL)
    142 	error (EXIT_FAILURE, 0, "dwfl_module_info: %s", dwarf_errmsg (-1));
    143       if (modname[0] == '\0')
    144 	modname = fname;
    145       printf ("%s: %#" PRIx64 " .. %#" PRIx64 "\n", modname, start, end);
    146 
    147       unsigned int indent = 0;
    148       while (n-- > 0)
    149 	{
    150 	  Dwarf_Die *const die = &scopes[n];
    151 
    152 	  indent += INDENT;
    153 	  printf ("%*s%s (%#x)", indent, "",
    154 		  dwarf_diename (die) ?: "<unnamed>",
    155 		  dwarf_tag (die));
    156 
    157 	  Dwarf_Addr lowpc, highpc;
    158 	  if (dwarf_lowpc (die, &lowpc) == 0
    159 	      && dwarf_highpc (die, &highpc) == 0)
    160 	    {
    161 	      lowpc += a->dwbias;
    162 	      highpc += a->dwbias;
    163 	      Dwfl_Line *loline = dwfl_getsrc (a->dwfl, lowpc);
    164 	      Dwfl_Line *hiline = dwfl_getsrc (a->dwfl, highpc);
    165 	      paddr (": ", lowpc, loline);
    166 	      if (highpc != lowpc)
    167 		paddr (" .. ", lowpc, hiline == loline ? NULL : hiline);
    168 	    }
    169 	  puts ("");
    170 
    171 	  print_vars (indent + INDENT, die);
    172 	}
    173     }
    174 
    175   return 0;
    176 }
    177 
    178 
    179 int
    180 main (int argc, char *argv[])
    181 {
    182   int remaining;
    183 
    184   /* Set locale.  */
    185   (void) setlocale (LC_ALL, "");
    186 
    187   struct args a = { .dwfl = NULL, .cu = NULL };
    188 
    189   (void) argp_parse (dwfl_standard_argp (), argc, argv, 0, &remaining,
    190 		     &a.dwfl);
    191   assert (a.dwfl != NULL);
    192   a.argv = &argv[remaining];
    193 
    194   int result = 0;
    195 
    196   while ((a.cu = dwfl_nextcu (a.dwfl, a.cu, &a.dwbias)) != NULL)
    197     dwarf_getfuncs (a.cu, &handle_function, &a, 0);
    198 
    199   dwfl_end (a.dwfl);
    200 
    201   return result;
    202 }
    203