1/* Copyright (C) 1998-2002, 2004, 2006, 2012, 2015 Red Hat, Inc.
2   This file is part of elfutils.
3   Written by Ulrich Drepper <drepper@redhat.com>, 1998.
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
20#include <dwarf.h>
21#include <inttypes.h>
22#include <libelf.h>
23#include ELFUTILS_HEADER(dw)
24#include <fcntl.h>
25#include <stdio.h>
26#include <string.h>
27#include <unistd.h>
28
29#include "../libdw/known-dwarf.h"
30
31static const char *
32dwarf_tag_string (unsigned int tag)
33{
34  switch (tag)
35    {
36#define DWARF_ONE_KNOWN_DW_TAG(NAME, CODE) case CODE: return #NAME;
37      DWARF_ALL_KNOWN_DW_TAG
38#undef DWARF_ONE_KNOWN_DW_TAG
39    default:
40      return NULL;
41    }
42}
43
44static const char *
45dwarf_attr_string (unsigned int attrnum)
46{
47  switch (attrnum)
48    {
49#define DWARF_ONE_KNOWN_DW_AT(NAME, CODE) case CODE: return #NAME;
50      DWARF_ALL_KNOWN_DW_AT
51#undef DWARF_ONE_KNOWN_DW_AT
52    default:
53      return NULL;
54    }
55}
56
57
58void
59handle (Dwarf *dbg, Dwarf_Die *die, int n)
60{
61  Dwarf_Die child;
62  unsigned int tag;
63  const char *str;
64  char buf[30];
65  const char *name;
66  Dwarf_Off off;
67  Dwarf_Off cuoff;
68  size_t cnt;
69  Dwarf_Addr addr;
70  int i;
71
72  tag = dwarf_tag (die);
73  if (tag != DW_TAG_invalid)
74    {
75      str = dwarf_tag_string (tag);
76      if (str == NULL)
77	{
78	  snprintf (buf, sizeof buf, "%#x", tag);
79	  str = buf;
80	}
81    }
82  else
83    str = "* NO TAG *";
84
85  name = dwarf_diename (die);
86  if (name == 0)
87    name = "* NO NAME *";
88
89  off = dwarf_dieoffset (die);
90  cuoff = dwarf_cuoffset (die);
91
92  printf ("%*sDW_TAG_%s\n", n * 5, "", str);
93  printf ("%*s Name      : %s\n", n * 5, "", name);
94  printf ("%*s Offset    : %lld\n", n * 5, "", (long long int) off);
95  printf ("%*s CU offset : %lld\n", n * 5, "", (long long int) cuoff);
96
97  printf ("%*s Attrs     :", n * 5, "");
98  for (cnt = 0; cnt < 0xffff; ++cnt)
99    if (dwarf_hasattr (die, cnt))
100      printf (" %s", dwarf_attr_string (cnt));
101  puts ("");
102
103  if (dwarf_hasattr (die, DW_AT_low_pc) && dwarf_lowpc (die, &addr) == 0)
104    {
105      Dwarf_Attribute attr;
106      Dwarf_Addr addr2;
107      printf ("%*s low PC    : %#llx\n",
108	      n * 5, "", (unsigned long long int) addr);
109
110      if (dwarf_attr (die, DW_AT_low_pc, &attr) == NULL
111	  || dwarf_formaddr (&attr, &addr2) != 0
112	  || addr != addr2)
113	puts ("************* DW_AT_low_pc verify failed ************");
114      else if (! dwarf_hasform (&attr, DW_FORM_addr))
115	puts ("************* DW_AT_low_pc form failed ************");
116      else if (dwarf_whatform (&attr) != DW_FORM_addr)
117	puts ("************* DW_AT_low_pc form (2) failed ************");
118      else if (dwarf_whatattr (&attr) != DW_AT_low_pc)
119	puts ("************* DW_AT_low_pc attr failed ************");
120    }
121  if (dwarf_hasattr (die, DW_AT_high_pc) && dwarf_highpc (die, &addr) == 0)
122    {
123      Dwarf_Attribute attr;
124      Dwarf_Addr addr2;
125      printf ("%*s high PC   : %#llx\n",
126	      n * 5, "", (unsigned long long int) addr);
127      if (dwarf_attr (die, DW_AT_high_pc, &attr) == NULL
128	  || dwarf_formaddr (&attr, &addr2) != 0
129	  || addr != addr2)
130	puts ("************* DW_AT_high_pc verify failed ************");
131      else if (! dwarf_hasform (&attr, DW_FORM_addr))
132	puts ("************* DW_AT_high_pc form failed ************");
133      else if (dwarf_whatform (&attr) != DW_FORM_addr)
134	puts ("************* DW_AT_high_pc form (2) failed ************");
135      else if (dwarf_whatattr (&attr) != DW_AT_high_pc)
136	puts ("************* DW_AT_high_pc attr failed ************");
137    }
138
139  if (dwarf_hasattr (die, DW_AT_byte_size) && (i = dwarf_bytesize (die)) != -1)
140    {
141      Dwarf_Attribute attr;
142      Dwarf_Word u2;
143      unsigned int u;
144      printf ("%*s byte size : %d\n", n * 5, "", i);
145      if (dwarf_attr (die, DW_AT_byte_size, &attr) == NULL
146	  || dwarf_formudata (&attr, &u2) != 0
147	  || i != (int) u2)
148	puts ("************* DW_AT_byte_size verify failed ************");
149      else if (! dwarf_hasform (&attr, DW_FORM_data1)
150	       && ! dwarf_hasform (&attr, DW_FORM_data2)
151	       && ! dwarf_hasform (&attr, DW_FORM_data4)
152	       && ! dwarf_hasform (&attr, DW_FORM_data8)
153	       && ! dwarf_hasform (&attr, DW_FORM_sdata)
154	       && ! dwarf_hasform (&attr, DW_FORM_udata))
155	puts ("************* DW_AT_byte_size form failed ************");
156      else if ((u = dwarf_whatform (&attr)) == 0
157	       || (u != DW_FORM_data1
158		   && u != DW_FORM_data2
159		   && u != DW_FORM_data4
160		   && u != DW_FORM_data8
161		   && u != DW_FORM_sdata
162		   && u != DW_FORM_udata))
163	puts ("************* DW_AT_byte_size form (2) failed ************");
164      else if (dwarf_whatattr (&attr) != DW_AT_byte_size)
165	puts ("************* DW_AT_byte_size attr failed ************");
166    }
167  if (dwarf_hasattr (die, DW_AT_bit_size) && (i = dwarf_bitsize (die)) != -1)
168    {
169      Dwarf_Attribute attr;
170      Dwarf_Word u2;
171      unsigned int u;
172      printf ("%*s bit size  : %d\n", n * 5, "", i);
173      if (dwarf_attr (die, DW_AT_bit_size, &attr) == NULL
174	  || dwarf_formudata (&attr, &u2) != 0
175	  || i != (int) u2)
176	puts ("************* DW_AT_bit_size test failed ************");
177      else if (! dwarf_hasform (&attr, DW_FORM_data1)
178	       && ! dwarf_hasform (&attr, DW_FORM_data2)
179	       && ! dwarf_hasform (&attr, DW_FORM_data4)
180	       && ! dwarf_hasform (&attr, DW_FORM_data8)
181	       && ! dwarf_hasform (&attr, DW_FORM_sdata)
182	       && ! dwarf_hasform (&attr, DW_FORM_udata))
183	puts ("************* DW_AT_bit_size form failed ************");
184      else if ((u = dwarf_whatform (&attr)) == 0
185	       || (u != DW_FORM_data1
186		   && u != DW_FORM_data2
187		   && u != DW_FORM_data4
188		   && u != DW_FORM_data8
189		   && u != DW_FORM_sdata
190		   && u != DW_FORM_udata))
191	puts ("************* DW_AT_bit_size form (2) failed ************");
192      else if (dwarf_whatattr (&attr) != DW_AT_bit_size)
193	puts ("************* DW_AT_bit_size attr failed ************");
194    }
195  if (dwarf_hasattr (die, DW_AT_bit_offset)
196      && (i = dwarf_bitoffset (die)) != -1)
197    {
198      Dwarf_Attribute attr;
199      Dwarf_Word u2;
200      unsigned int u;
201      printf ("%*s bit offset: %d\n", n * 5, "", i);
202      if (dwarf_attr (die, DW_AT_bit_offset, &attr) == NULL
203	  || dwarf_formudata (&attr, &u2) != 0
204	  || i != (int) u2)
205	puts ("************* DW_AT_bit_offset test failed ************");
206      else if (! dwarf_hasform (&attr, DW_FORM_data1)
207	       && ! dwarf_hasform (&attr, DW_FORM_data2)
208	       && ! dwarf_hasform (&attr, DW_FORM_data4)
209	       && ! dwarf_hasform (&attr, DW_FORM_data8)
210	       && ! dwarf_hasform (&attr, DW_FORM_sdata)
211	       && ! dwarf_hasform (&attr, DW_FORM_udata))
212	puts ("************* DW_AT_bit_offset form failed ************");
213      else if ((u = dwarf_whatform (&attr)) == 0
214	       || (u != DW_FORM_data1
215		   && u != DW_FORM_data2
216		   && u != DW_FORM_data4
217		   && u != DW_FORM_data8
218		   && u != DW_FORM_sdata
219		   && u != DW_FORM_udata))
220	puts ("************* DW_AT_bit_offset form (2) failed ************");
221      else if (dwarf_whatattr (&attr) != DW_AT_bit_offset)
222	puts ("************* DW_AT_bit_offset attr failed ************");
223    }
224
225  if (dwarf_hasattr (die, DW_AT_language) && (i = dwarf_srclang (die)) != -1)
226    {
227      Dwarf_Attribute attr;
228      Dwarf_Word u2;
229      unsigned int u;
230      printf ("%*s language  : %d\n", n * 5, "", i);
231      if (dwarf_attr (die, DW_AT_language, &attr) == NULL
232	  || dwarf_formudata (&attr, &u2) != 0
233	  || i != (int) u2)
234	puts ("************* DW_AT_language test failed ************");
235      else if (! dwarf_hasform (&attr, DW_FORM_data1)
236	       && ! dwarf_hasform (&attr, DW_FORM_data2)
237	       && ! dwarf_hasform (&attr, DW_FORM_data4)
238	       && ! dwarf_hasform (&attr, DW_FORM_data8)
239	       && ! dwarf_hasform (&attr, DW_FORM_sdata)
240	       && ! dwarf_hasform (&attr, DW_FORM_udata))
241	puts ("************* DW_AT_language form failed ************");
242      else if ((u = dwarf_whatform (&attr)) == 0
243	       || (u != DW_FORM_data1
244		   && u != DW_FORM_data2
245		   && u != DW_FORM_data4
246		   && u != DW_FORM_data8
247		   && u != DW_FORM_sdata
248		   && u != DW_FORM_udata))
249	puts ("************* DW_AT_language form (2) failed ************");
250      else if (dwarf_whatattr (&attr) != DW_AT_language)
251	puts ("************* DW_AT_language attr failed ************");
252    }
253
254  if (dwarf_hasattr (die, DW_AT_ordering)
255      && (i = dwarf_arrayorder (die)) != -1)
256    {
257      Dwarf_Attribute attr;
258      Dwarf_Word u2;
259      unsigned int u;
260      printf ("%*s ordering  : %d\n", n * 5, "", i);
261      if (dwarf_attr (die, DW_AT_ordering, &attr) == NULL
262	  || dwarf_formudata (&attr, &u2) != 0
263	  || i != (int) u2)
264	puts ("************* DW_AT_ordering test failed ************");
265      else if (! dwarf_hasform (&attr, DW_FORM_data1)
266	       && ! dwarf_hasform (&attr, DW_FORM_data2)
267	       && ! dwarf_hasform (&attr, DW_FORM_data4)
268	       && ! dwarf_hasform (&attr, DW_FORM_data8)
269	       && ! dwarf_hasform (&attr, DW_FORM_sdata)
270	       && ! dwarf_hasform (&attr, DW_FORM_udata))
271	puts ("************* DW_AT_ordering failed ************");
272      else if ((u = dwarf_whatform (&attr)) == 0
273	       || (u != DW_FORM_data1
274		   && u != DW_FORM_data2
275		   && u != DW_FORM_data4
276		   && u != DW_FORM_data8
277		   && u != DW_FORM_sdata
278		   && u != DW_FORM_udata))
279	puts ("************* DW_AT_ordering form (2) failed ************");
280      else if (dwarf_whatattr (&attr) != DW_AT_ordering)
281	puts ("************* DW_AT_ordering attr failed ************");
282    }
283
284  if (dwarf_hasattr (die, DW_AT_comp_dir))
285    {
286      Dwarf_Attribute attr;
287      if (dwarf_attr (die, DW_AT_comp_dir, &attr) == NULL
288	  || (name = dwarf_formstring (&attr)) == NULL)
289	puts ("************* DW_AT_comp_dir attr failed ************");
290      else
291	printf ("%*s directory : %s\n", n * 5, "", name);
292    }
293
294  if (dwarf_hasattr (die, DW_AT_producer))
295    {
296      Dwarf_Attribute attr;
297      if (dwarf_attr (die, DW_AT_producer, &attr) == NULL
298	  || (name = dwarf_formstring (&attr)) == NULL)
299	puts ("************* DW_AT_comp_dir attr failed ************");
300      else
301	printf ("%*s producer  : %s\n", n * 5, "", name);
302    }
303
304  if (dwarf_haschildren (die) != 0 && dwarf_child (die, &child) == 0)
305    handle (dbg, &child, n + 1);
306  if (dwarf_siblingof (die, die) == 0)
307    handle (dbg, die, n);
308}
309
310
311int
312main (int argc, char *argv[])
313{
314 int cnt;
315
316  for (cnt = 1; cnt < argc; ++cnt)
317    {
318      int fd = open (argv[cnt], O_RDONLY);
319      Dwarf *dbg;
320
321      printf ("file: %s\n", basename (argv[cnt]));
322
323      dbg = dwarf_begin (fd, DWARF_C_READ);
324      if (dbg == NULL)
325	{
326	  printf ("%s not usable\n", argv[cnt]);
327	  close (fd);
328	  continue;
329	}
330
331      Dwarf_Off off = 0;
332      Dwarf_Off old_off = 0;
333      size_t hsize;
334      Dwarf_Off abbrev;
335      uint8_t addresssize;
336      uint8_t offsetsize;
337      while (dwarf_nextcu (dbg, off, &off, &hsize, &abbrev, &addresssize,
338			   &offsetsize) == 0)
339	{
340	  printf ("New CU: off = %llu, hsize = %zu, ab = %llu, as = %" PRIu8
341		  ", os = %" PRIu8 "\n",
342		  (unsigned long long int) old_off, hsize,
343		  (unsigned long long int) abbrev, addresssize,
344		  offsetsize);
345
346	  Dwarf_Die die;
347	  if (dwarf_offdie (dbg, old_off + hsize, &die) != NULL)
348	    handle (dbg, &die, 1);
349
350	  old_off = off;
351	}
352
353      dwarf_end (dbg);
354      close (fd);
355    }
356
357  return 0;
358}
359