1 /* Test dwarf_cu_info properties.
2    Copyright (C) 2018 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 #ifdef HAVE_CONFIG_H
19 # include <config.h>
20 #endif
21 
22 #include <dwarf.h>
23 #include ELFUTILS_HEADER(dw)
24 #include <stdio.h>
25 #include <inttypes.h>
26 #include <sys/types.h>
27 #include <sys/stat.h>
28 #include <fcntl.h>
29 #include <unistd.h>
30 
31 /* Yeah, lazy, 16K CUs should be enough for everybody... */
32 #define MAX_UNITS 16384
33 struct info
34 {
35   int dietag;
36   int subtag;
37   Dwarf_Half version;
38   uint8_t unit_type;
39   uint64_t id;
40   uint8_t addr_size;
41   uint8_t off_size;
42 };
43 static struct info unit_info[MAX_UNITS];
44 
45 int
main(int argc,char * argv[])46 main (int argc, char *argv[])
47 {
48   for (int i = 1; i < argc; i++)
49     {
50       printf ("file: %s\n", argv[i]);
51       int fd = open (argv[i], O_RDONLY);
52       Dwarf *dbg = dwarf_begin (fd, DWARF_C_READ);
53       if (dbg == NULL)
54 	{
55 	  printf ("%s not usable: %s\n", argv[i], dwarf_errmsg (-1));
56 	  return -1;
57 	}
58 
59       Dwarf_CU *cu = NULL;
60       Dwarf_Half version;
61       Dwarf_Die cudie, subdie;
62       uint8_t unit_type;
63       size_t u, units;
64       u = units = 0;
65       printf ("Iterate getting all info, compare with dwarf_cu_info.\n");
66       while (dwarf_get_units (dbg, cu, &cu, &version,
67 			      &unit_type, &cudie, &subdie) == 0)
68 	{
69 	  int dietag = dwarf_tag (&cudie);
70 	  int subtag = dwarf_tag (&subdie);
71 
72 	  unit_info[u].dietag = dietag;
73 	  unit_info[u].subtag = subtag;
74 	  unit_info[u].version = version;
75 	  unit_info[u].unit_type = unit_type;
76 
77 	  printf ("%zu cu dietag: %x, subtag: %x, version %" PRIx32
78 		  ", unit_type %" PRIx8 "\n",
79 		  u, dietag, subtag, version, unit_type);
80 
81 	  uint64_t unit_id;
82 	  uint8_t addr_size, off_size;
83 	  if (dwarf_cu_info (cu,
84 			     &version, &unit_type, &cudie, &subdie,
85 			     &unit_id, &addr_size, &off_size) != 0)
86 	    {
87 	      printf ("Invalid dwarf_cu_info: %s\n", dwarf_errmsg (-1));
88 	      return -1;
89 	    }
90 
91 	  dietag = dwarf_tag (&cudie);
92 	  subtag = dwarf_tag (&subdie);
93 
94 	  if (unit_info[u].dietag != dietag)
95 	    {
96 	      printf("Unequal dietags\n");
97 	      return -1;
98 	    }
99 
100 	  if (unit_info[u].subtag != subtag)
101 	    {
102 	      printf("Unequal subtags\n");
103 	      return -1;
104 	    }
105 
106 	  if (unit_info[u].version != version)
107 	    {
108 	      printf("Unequal versions\n");
109 	      return -1;
110 	    }
111 
112 	  if (unit_info[u].unit_type != unit_type)
113 	    {
114 	      printf("Unequal unit_types\n");
115 	      return -1;
116 	    }
117 
118 	  unit_info[u].id = unit_id;
119 	  unit_info[u].addr_size = addr_size;
120 	  unit_info[u].off_size = off_size;
121 
122 	  if (unit_type == DW_UT_skeleton)
123 	    {
124 	      if (dwarf_cu_info (subdie.cu,
125 				 &version, &unit_type, &cudie, &subdie,
126 				 &unit_id, &addr_size, &off_size) != 0)
127 		{
128 		  printf ("Invalid subdie dwarf_cu_info: %s\n",
129 			  dwarf_errmsg (-1));
130 		  return -1;
131 		}
132 
133 	      dietag = dwarf_tag (&cudie);
134 	      subtag = dwarf_tag (&subdie);
135 
136 	      printf ("%zu subdietag: %x, subtag: %x, version %" PRIx32
137 		      ", unit_type %" PRIx8 "\n",
138 		      u, dietag, subtag, version, unit_type);
139 
140 	      /* subdie is now cudie.  */
141 	      if (unit_info[u].subtag != dietag)
142 	      {
143 		printf ("Inconsistent subdie tag\n");
144 		return -1;
145 	      }
146 
147 	      if (unit_info[u].id != unit_id)
148 		{
149 		  printf ("Unequal subdie ids\n");
150 		  return -1;
151 		}
152 
153 	      if (unit_info[u].addr_size != addr_size)
154 		{
155 		  printf ("Unequal subdie addr_size\n");
156 		  return -1;
157 		}
158 
159 	      if (unit_info[u].off_size != off_size)
160 		{
161 		  printf ("Unequal subdie off_size\n");
162 		  return -1;
163 		}
164 	    }
165 
166 	  if (u >= MAX_UNITS)
167 	    {
168 	      printf ("Oops, more than 16K units...\n");
169 	      return -1;
170 	    }
171 	  u = ++units;
172 	}
173 
174       dwarf_end (dbg);
175       close (fd);
176 
177       /* And again... */
178       printf ("rechecking: %s\n", argv[i]);
179       fd = open (argv[i], O_RDONLY);
180       dbg = dwarf_begin (fd, DWARF_C_READ);
181       if (dbg == NULL)
182 	{
183 	  printf ("%s not usable: %s\n", argv[i], dwarf_errmsg (-1));
184 	  return -1;
185 	}
186 
187       cu = NULL;
188       u = 0;
189       printf ("Iterate no info, compare recorded info with dwarf_cu_info.\n");
190       while (dwarf_get_units (dbg, cu, &cu, NULL, NULL, NULL, NULL) == 0)
191 	{
192 	  if (u > units)
193 	    {
194 	      printf ("Got too many units???\n");
195 	      return -1;
196 	    }
197 
198 	  uint64_t unit_id;
199 	  uint8_t addr_size, off_size;
200 	  if (dwarf_cu_info (cu,
201 			     &version, &unit_type, &cudie, &subdie,
202 			     &unit_id, &addr_size, &off_size) != 0)
203 	    {
204 	      printf ("Invalid dwarf_cu_info: %s\n", dwarf_errmsg (-1));
205 	      return -1;
206 	    }
207 
208 	  int dietag = dwarf_tag (&cudie);
209 	  int subtag = dwarf_tag (&subdie);
210 
211 	  printf ("%zu re dietag: %x, subtag: %x, version %" PRIx32
212 		  ", unit_type %" PRIx8 "\n",
213 		  u, dietag, subtag, version, unit_type);
214 
215 	  if (unit_info[u].dietag != dietag)
216 	    {
217 	      printf("Unequal dietags %x != %x\n", unit_info[u].dietag, dietag);
218 	      return -1;
219 	    }
220 
221 	  if (unit_info[u].subtag != subtag)
222 	    {
223 	      printf("Unequal subtags\n");
224 	      return -1;
225 	    }
226 
227 	  if (unit_info[u].version != version)
228 	    {
229 	      printf("Unequal versions\n");
230 	      return -1;
231 	    }
232 
233 	  if (unit_info[u].unit_type != unit_type)
234 	    {
235 	      printf("Unequal unit_types\n");
236 	      return -1;
237 	    }
238 
239 	  if (unit_info[u].id != unit_id)
240 	    {
241 	      printf ("Unequal subdie ids\n");
242 	      return -1;
243 	    }
244 
245 	  if (unit_info[u].addr_size != addr_size)
246 	    {
247 	      printf ("Unequal subdie addr_size\n");
248 	      return -1;
249 	    }
250 
251 	  if (unit_info[u].off_size != off_size)
252 	    {
253 	      printf ("Unequal subdie off_size\n");
254 	      return -1;
255 	    }
256 
257 	  if (unit_type == DW_UT_skeleton)
258 	    {
259 	      if (dwarf_cu_info (subdie.cu,
260 				 &version, &unit_type, &cudie, &subdie,
261 				 &unit_id, &addr_size, &off_size) != 0)
262 		{
263 		  printf ("Invalid subdie dwarf_cu_info: %s\n",
264 			  dwarf_errmsg (-1));
265 		  return -1;
266 		}
267 
268 	      dietag = dwarf_tag (&cudie);
269 	      subtag = dwarf_tag (&subdie);
270 
271 	      printf ("%zu subdietag: %x, subtag: %x, version %" PRIx32
272 		      ", unit_type %" PRIx8 "\n",
273 		      u, dietag, subtag, version, unit_type);
274 
275 	      /* subdie is now cudie.  */
276 	      subtag = dwarf_tag (&cudie);
277 	      if (unit_info[u].subtag != subtag)
278 	      {
279 		printf ("Inconsistent subdie tag\n");
280 		return -1;
281 	      }
282 
283 	      if (unit_info[u].id != unit_id)
284 		{
285 		  printf ("Unequal subdie ids\n");
286 		  return -1;
287 		}
288 
289 	      if (unit_info[u].addr_size != addr_size)
290 		{
291 		  printf ("Unequal subdie addr_size\n");
292 		  return -1;
293 		}
294 
295 	      if (unit_info[u].off_size != off_size)
296 		{
297 		  printf ("Unequal subdie off_size\n");
298 		  return -1;
299 		}
300 	    }
301 
302 	  if (u >= MAX_UNITS)
303 	    {
304 	      printf ("Oops, more than 16K units...\n");
305 	      return -1;
306 	    }
307 	  u++;
308 	}
309 
310       if (u != units)
311 	{
312 	  printf ("Got not enough units???\n");
313 	  return -1;
314 	}
315 
316       dwarf_end (dbg);
317       close (fd);
318 
319       printf ("\n");
320     }
321 
322   return 0;
323 }
324