Home | History | Annotate | Download | only in tests
      1 /* Test program for dwarf_getscopes.
      2    Copyright (C) 2005, 2014 Red Hat, Inc.
      3    This file is part of elfutils.
      4 
      5    This file is free software; you can redistribute it and/or modify
      6    it under the terms of the GNU General Public License as published by
      7    the Free Software Foundation; either version 3 of the License, or
      8    (at your option) any later version.
      9 
     10    elfutils is distributed in the hope that it will be useful, but
     11    WITHOUT ANY WARRANTY; without even the implied warranty of
     12    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
     13    GNU General Public License for more details.
     14 
     15    You should have received a copy of the GNU General Public License
     16    along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
     17 
     18 #include <config.h>
     19 #include <assert.h>
     20 #include <inttypes.h>
     21 #include ELFUTILS_HEADER(dwfl)
     22 #include <dwarf.h>
     23 #include <argp.h>
     24 #include <stdio.h>
     25 #include <stdio_ext.h>
     26 #include <locale.h>
     27 #include <stdlib.h>
     28 #include <error.h>
     29 #include <string.h>
     30 #include <fnmatch.h>
     31 
     32 
     33 static void
     34 paddr (const char *prefix, Dwarf_Addr addr, Dwfl_Line *line)
     35 {
     36   const char *src;
     37   int lineno, linecol;
     38   if (line != NULL
     39       && (src = dwfl_lineinfo (line, &addr, &lineno, &linecol,
     40 			       NULL, NULL)) != NULL)
     41     {
     42       if (linecol != 0)
     43 	printf ("%s%#" PRIx64 " (%s:%d:%d)",
     44 		prefix, addr, src, lineno, linecol);
     45       else
     46 	printf ("%s%#" PRIx64 " (%s:%d)",
     47 		prefix, addr, src, lineno);
     48     }
     49   else
     50     printf ("%s%#" PRIx64, prefix, addr);
     51 }
     52 
     53 
     54 static void
     55 print_vars (unsigned int indent, Dwarf_Die *die)
     56 {
     57   Dwarf_Die child;
     58   if (dwarf_child (die, &child) == 0)
     59     do
     60       switch (dwarf_tag (&child))
     61 	{
     62 	case DW_TAG_variable:
     63 	case DW_TAG_formal_parameter:
     64 	  printf ("%*s%-30s[%6" PRIx64 "]\n", indent, "",
     65 		  dwarf_diename (&child),
     66 		  (uint64_t) dwarf_dieoffset (&child));
     67 	  break;
     68 	default:
     69 	  break;
     70 	}
     71     while (dwarf_siblingof (&child, &child) == 0);
     72 
     73   Dwarf_Attribute attr_mem;
     74   Dwarf_Die origin;
     75   if (dwarf_hasattr (die, DW_AT_abstract_origin)
     76       && dwarf_formref_die (dwarf_attr (die, DW_AT_abstract_origin, &attr_mem),
     77 			    &origin) != NULL
     78       && dwarf_child (&origin, &child) == 0)
     79     do
     80       switch (dwarf_tag (&child))
     81 	{
     82 	case DW_TAG_variable:
     83 	case DW_TAG_formal_parameter:
     84 	  printf ("%*s%s (abstract)\n", indent, "",
     85 		  dwarf_diename (&child));
     86 	  break;
     87 	default:
     88 	  break;
     89 	}
     90     while (dwarf_siblingof (&child, &child) == 0);
     91 }
     92 
     93 
     94 #define INDENT 4
     95 
     96 struct args
     97 {
     98   Dwfl *dwfl;
     99   Dwarf_Die *cu;
    100   Dwarf_Addr dwbias;
    101   char **argv;
    102 };
    103 
    104 static int
    105 handle_function (Dwarf_Die *funcdie, void *arg)
    106 {
    107   struct args *a = arg;
    108 
    109   const char *name = dwarf_diename (funcdie);
    110   char **argv = a->argv;
    111   if (argv[0] != NULL)
    112     {
    113       bool match;
    114       do
    115 	match = fnmatch (*argv, name, 0) == 0;
    116       while (!match && *++argv);
    117       if (!match)
    118 	return 0;
    119     }
    120 
    121   Dwarf_Die *scopes;
    122   int n = dwarf_getscopes_die (funcdie, &scopes);
    123   if (n <= 0)
    124     error (EXIT_FAILURE, 0, "dwarf_getscopes_die: %s", dwarf_errmsg (-1));
    125   else
    126     {
    127       Dwarf_Addr start, end;
    128       const char *fname;
    129       const char *modname = dwfl_module_info (dwfl_cumodule (a->cu), NULL,
    130 					      &start, &end,
    131 					      NULL, NULL,
    132 					      &fname, NULL);
    133       if (modname == NULL)
    134 	error (EXIT_FAILURE, 0, "dwfl_module_info: %s", dwarf_errmsg (-1));
    135       if (modname[0] == '\0')
    136 	modname = fname;
    137       printf ("%s: %#" PRIx64 " .. %#" PRIx64 "\n", modname, start, end);
    138 
    139       unsigned int indent = 0;
    140       while (n-- > 0)
    141 	{
    142 	  Dwarf_Die *const die = &scopes[n];
    143 
    144 	  indent += INDENT;
    145 	  printf ("%*s%s (%#x)", indent, "",
    146 		  dwarf_diename (die) ?: "<unnamed>",
    147 		  dwarf_tag (die));
    148 
    149 	  Dwarf_Addr lowpc, highpc;
    150 	  if (dwarf_lowpc (die, &lowpc) == 0
    151 	      && dwarf_highpc (die, &highpc) == 0)
    152 	    {
    153 	      lowpc += a->dwbias;
    154 	      highpc += a->dwbias;
    155 	      Dwfl_Line *loline = dwfl_getsrc (a->dwfl, lowpc);
    156 	      Dwfl_Line *hiline = dwfl_getsrc (a->dwfl, highpc - 1);
    157 	      paddr (": ", lowpc, loline);
    158 	      if (highpc != lowpc)
    159 		paddr (" .. ", highpc - 1, hiline == loline ? NULL : hiline);
    160 	    }
    161 	  puts ("");
    162 
    163 	  print_vars (indent + INDENT, die);
    164 	}
    165       free (scopes);
    166     }
    167 
    168   return 0;
    169 }
    170 
    171 
    172 int
    173 main (int argc, char *argv[])
    174 {
    175   int remaining;
    176 
    177   /* Set locale.  */
    178   (void) setlocale (LC_ALL, "");
    179 
    180   struct args a = { .dwfl = NULL, .cu = NULL };
    181 
    182   (void) argp_parse (dwfl_standard_argp (), argc, argv, 0, &remaining,
    183 		     &a.dwfl);
    184   assert (a.dwfl != NULL);
    185   a.argv = &argv[remaining];
    186 
    187   int result = 0;
    188 
    189   while ((a.cu = dwfl_nextcu (a.dwfl, a.cu, &a.dwbias)) != NULL)
    190     dwarf_getfuncs (a.cu, &handle_function, &a, 0);
    191 
    192   dwfl_end (a.dwfl);
    193 
    194   return result;
    195 }
    196