• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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
paddr(const char * prefix,Dwarf_Addr addr,Dwfl_Line * line)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
print_vars(unsigned int indent,Dwarf_Die * die)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
handle_function(Dwarf_Die * funcdie,void * arg)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
main(int argc,char * argv[])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