• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /* Test program for libdwfl basic module tracking, relocation.
2    Copyright (C) 2005, 2007 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 <sys/types.h>
30 #include <stdio.h>
31 #include <stdio_ext.h>
32 #include <stdlib.h>
33 #include <string.h>
34 #include <error.h>
35 #include <locale.h>
36 #include <argp.h>
37 #include ELFUTILS_HEADER(dwfl)
38 #include <dwarf.h>
39 
40 static bool show_inlines;
41 
42 struct info
43 {
44   Dwarf_Die *cudie;
45   Dwarf_Addr dwbias;
46 };
47 
48 static int
print_instance(Dwarf_Die * instance,void * arg)49 print_instance (Dwarf_Die *instance, void *arg)
50 {
51   const struct info *info = arg;
52 
53   printf ("    inlined");
54 
55   Dwarf_Files *files;
56   if (dwarf_getsrcfiles (info->cudie, &files, NULL) == 0)
57     {
58       Dwarf_Attribute attr_mem;
59       Dwarf_Word val;
60       if (dwarf_formudata (dwarf_attr (instance, DW_AT_call_file,
61 				       &attr_mem), &val) == 0)
62 	{
63 	  const char *file = dwarf_filesrc (files, val, NULL, NULL);
64 	  int lineno = 0, colno = 0;
65 	  if (dwarf_formudata (dwarf_attr (instance, DW_AT_call_line,
66 					   &attr_mem), &val) == 0)
67 	    lineno = val;
68 	  if (dwarf_formudata (dwarf_attr (instance, DW_AT_call_column,
69 					   &attr_mem), &val) == 0)
70 	    colno = val;
71 	  if (lineno == 0)
72 	    {
73 	      if (file != NULL)
74 		printf (" from %s", file);
75 	    }
76 	  else if (colno == 0)
77 	    printf (" at %s:%u", file, lineno);
78 	  else
79 	    printf (" at %s:%u:%u", file, lineno, colno);
80 	}
81     }
82 
83   Dwarf_Addr lo = -1, hi = -1, entry = -1;
84   if (dwarf_lowpc (instance, &lo) == 0)
85     lo += info->dwbias;
86   else
87     printf (" (lowpc => %s)", dwarf_errmsg (-1));
88   if (dwarf_highpc (instance, &hi) == 0)
89     hi += info->dwbias;
90   else
91     printf (" (highpc => %s)", dwarf_errmsg (-1));
92 
93   Dwarf_Attribute attr_mem;
94   Dwarf_Attribute *attr = dwarf_attr (instance, DW_AT_entry_pc, &attr_mem);
95   if (attr != NULL)
96     {
97       if (dwarf_formaddr (attr, &entry) == 0)
98 	entry += info->dwbias;
99       else
100 	printf (" (entrypc => %s)", dwarf_errmsg (-1));
101     }
102 
103   if (lo != (Dwarf_Addr) -1 || hi != (Dwarf_Addr) -1)
104     printf (" %#" PRIx64 "..%#" PRIx64, lo, hi);
105   if (entry != (Dwarf_Addr) -1)
106     printf (" => %#" PRIx64 "\n", entry);
107   else
108     puts ("");
109 
110   return DWARF_CB_OK;
111 }
112 
113 static void
print_inline(Dwarf_Die * func,void * arg)114 print_inline (Dwarf_Die *func, void *arg)
115 {
116   if (dwarf_func_inline_instances (func, &print_instance, arg) != 0)
117     printf ("  error finding instances: %s\n", dwarf_errmsg (-1));
118 }
119 
120 static int
print_func(Dwarf_Die * func,void * arg)121 print_func (Dwarf_Die *func, void *arg)
122 {
123   const struct info *info = arg;
124 
125   const char *file = dwarf_decl_file (func);
126   int line = -1;
127   dwarf_decl_line (func, &line);
128   const char *fct = dwarf_diename (func);
129 
130   printf ("  %s:%d: %s:", file, line, fct);
131 
132   if (dwarf_func_inline (func))
133     {
134       puts (" inline function");
135       if (show_inlines)
136 	print_inline (func, arg);
137     }
138   else
139     {
140       Dwarf_Addr lo = -1, hi = -1, entry = -1;
141       if (dwarf_lowpc (func, &lo) == 0)
142 	lo += info->dwbias;
143       else
144 	printf (" (lowpc => %s)", dwarf_errmsg (-1));
145       if (dwarf_highpc (func, &hi) == 0)
146 	hi += info->dwbias;
147       else
148 	printf (" (highpc => %s)", dwarf_errmsg (-1));
149       if (dwarf_entrypc (func, &entry) == 0)
150 	entry += info->dwbias;
151       else
152 	printf (" (entrypc => %s)", dwarf_errmsg (-1));
153 
154       if (lo != (Dwarf_Addr) -1 || hi != (Dwarf_Addr) -1
155 	  || entry != (Dwarf_Addr) -1)
156 	printf (" %#" PRIx64 "..%#" PRIx64 " => %#" PRIx64 "\n",
157 		lo, hi, entry);
158       else
159 	puts ("");
160     }
161 
162   return DWARF_CB_OK;
163 }
164 
165 static int
list_module(Dwfl_Module * mod,void ** userdata,const char * name,Dwarf_Addr base,void * arg)166 list_module (Dwfl_Module *mod __attribute__ ((unused)),
167 	     void **userdata __attribute__ ((unused)),
168 	     const char *name, Dwarf_Addr base,
169 	     void *arg __attribute__ ((unused)))
170 {
171   Dwarf_Addr start;
172   Dwarf_Addr end;
173   const char *file;
174   const char *debug;
175   if (dwfl_module_info (mod, NULL, &start, &end,
176 			NULL, NULL, &file, &debug) != name
177       || start != base)
178     abort ();
179   printf ("module: %30s %08" PRIx64 "..%08" PRIx64 " %s %s\n",
180 	  name, start, end, file, debug);
181   return DWARF_CB_OK;
182 }
183 
184 static int
print_module(Dwfl_Module * mod,void ** userdata,const char * name,Dwarf_Addr base,Dwarf * dw,Dwarf_Addr bias,void * arg)185 print_module (Dwfl_Module *mod __attribute__ ((unused)),
186 	      void **userdata __attribute__ ((unused)),
187 	      const char *name, Dwarf_Addr base,
188 	      Dwarf *dw, Dwarf_Addr bias,
189 	      void *arg)
190 {
191   printf ("module: %30s %08" PRIx64 " %s %" PRIx64 " (%s)\n",
192 	  name, base, dw == NULL ? "no" : "DWARF", bias, dwfl_errmsg (-1));
193 
194   if (dw != NULL && *(const bool *) arg)
195     {
196       Dwarf_Off off = 0;
197       size_t cuhl;
198       Dwarf_Off noff;
199 
200       while (dwarf_nextcu (dw, off, &noff, &cuhl, NULL, NULL, NULL) == 0)
201 	{
202 	  Dwarf_Die die_mem;
203 	  struct info info = { dwarf_offdie (dw, off + cuhl, &die_mem), bias };
204 	  (void) dwarf_getfuncs (info.cudie, print_func, &info, 0);
205 
206 	  off = noff;
207 	}
208     }
209 
210   return DWARF_CB_OK;
211 }
212 
213 static bool show_functions;
214 
215 /* gettext helper macro.  */
216 #undef	N_
217 #define N_(Str) Str
218 
219 static const struct argp_option options[] =
220   {
221     { "functions", 'f', NULL, 0, N_("Additionally show function names"), 0 },
222     { "inlines", 'i', NULL, 0, N_("Show instances of inlined functions"), 0 },
223     { NULL, 0, NULL, 0, NULL, 0 }
224   };
225 
226 static error_t
parse_opt(int key,char * arg,struct argp_state * state)227 parse_opt (int key, char *arg __attribute__ ((unused)),
228 	   struct argp_state *state __attribute__ ((unused)))
229 {
230   switch (key)
231     {
232     case ARGP_KEY_INIT:
233       state->child_inputs[0] = state->input;
234       break;
235 
236     case 'f':
237       show_functions = true;
238       break;
239 
240     case 'i':
241       show_inlines = show_functions = true;
242       break;
243 
244     default:
245       return ARGP_ERR_UNKNOWN;
246     }
247   return 0;
248 }
249 
250 int
main(int argc,char ** argv)251 main (int argc, char **argv)
252 {
253   /* We use no threads here which can interfere with handling a stream.  */
254   (void) __fsetlocking (stdout, FSETLOCKING_BYCALLER);
255 
256   /* Set locale.  */
257   (void) setlocale (LC_ALL, "");
258 
259   Dwfl *dwfl = NULL;
260   const struct argp_child argp_children[] =
261     {
262       { .argp = dwfl_standard_argp () },
263       { .argp = NULL }
264     };
265   const struct argp argp =
266     {
267       options, parse_opt, NULL, NULL, argp_children, NULL, NULL
268     };
269   (void) argp_parse (&argp, argc, argv, 0, NULL, &dwfl);
270   assert (dwfl != NULL);
271 
272   ptrdiff_t p = 0;
273   do
274     p = dwfl_getmodules (dwfl, &list_module, NULL, p);
275   while (p > 0);
276   if (p < 0)
277     error (2, 0, "dwfl_getmodules: %s", dwfl_errmsg (-1));
278 
279   do
280     p = dwfl_getdwarf (dwfl, &print_module, &show_functions, p);
281   while (p > 0);
282   if (p < 0)
283     error (2, 0, "dwfl_getdwarf: %s", dwfl_errmsg (-1));
284 
285   p = 0;
286   do
287     p = dwfl_getmodules (dwfl, &list_module, NULL, p);
288   while (p > 0);
289   if (p < 0)
290     error (2, 0, "dwfl_getmodules: %s", dwfl_errmsg (-1));
291 
292   dwfl_end (dwfl);
293 
294   return 0;
295 }
296