1 #include <r_util.h>
2 #include "minunit.h"
3 #include <r_bin.h>
4 #include <r_bin_dwarf.h>
5 
6 #define MODE 2
7 
8 
9 #define check_attr_string(attr_idx, expect_string) \
10 	mu_assert_streq (cu.dies[i].attr_values[attr_idx].string.content, expect_string, "Wrong string attribute information")
11 
12 #define check_attr_name(attr_idx, expect_name) \
13 	mu_assert_eq (cu.dies[i].attr_values[attr_idx].attr_name, expect_name, "Wrong attribute name")
14 
15 #define check_attr_address(attr_idx, expect_addr) \
16 	mu_assert_eq (cu.dies[i].attr_values[attr_idx].address, expect_addr, "Wrong attribute name")
17 
18 #define check_attr_form(attr_idx, expect_form) \
19 	mu_assert_eq (cu.dies[i].attr_values[attr_idx].attr_form, expect_form, "Wrong attribute name")
20 
21 #define check_attr_data(attr_idx, expect_data) \
22 	mu_assert_eq (cu.dies[i].attr_values[attr_idx].uconstant, expect_data, "Wrong attribute data")
23 
24 #define check_attr_block_length(attr_idx, expect_len) \
25 	mu_assert_eq (cu.dies[i].attr_values[attr_idx].block.length, expect_len, "Wrong attribute block length")
26 
27 #define check_attr_block_data(attr_idx, data_idx, expect_data) \
28 	mu_assert_eq (cu.dies[i].attr_values[attr_idx].block.data[data_idx], expect_data, "Wrong attribute block data")
29 
30 #define check_attr_reference(attr_idx, expect_ref) \
31 	mu_assert_eq (cu.dies[i].attr_values[attr_idx].reference, expect_ref, "Wrong attribute reference")
32 
33 #define check_attr_flag(attr_idx, expect_flag) \
34 	mu_assert_eq (cu.dies[i].attr_values[attr_idx].flag, expect_flag, "Wrong attribute flag")
35 
36 #define check_die_abbr_code(expect_code) \
37 	mu_assert_eq (cu.dies[i].abbrev_code, expect_code, "Wrong abbrev code")
38 
39 #define check_die_length(len) \
40 	mu_assert_eq (cu.dies[i].count, len, "Wrong DIE length information")
41 
42 #define check_die_tag(tg) \
43 	mu_assert_eq (cu.dies[i].tag, tg, "Wrong DIE tag")
44 
45 #define check_basic_unit_header(vers, len, is64bit, addr_size, abbr_offset)                              \
46 	do {                                                                                             \
47 		mu_assert_eq (hdr.version, vers, "Wrong header version information");                    \
48 		mu_assert_eq (hdr.length, len, "Wrong header length information");                       \
49 		mu_assert_eq (hdr.is_64bit, is64bit, "Wrong header is_64bit information");               \
50 		mu_assert_eq (hdr.address_size, addr_size, "Wrong header address_size information");     \
51 		mu_assert_eq (hdr.abbrev_offset, abbr_offset, "Wrong header abbrev_offset information"); \
52 	} while (0)
53 
test_dwarf3_c(void)54 bool test_dwarf3_c(void) {
55 	RBin *bin = r_bin_new ();
56 	RIO *io = r_io_new ();
57 	r_io_bind (io, &bin->iob);
58 
59 	RBinOptions opt = { 0 };
60 	bool res = r_bin_open (bin, "bins/elf/dwarf3_c.elf", &opt);
61 	mu_assert ("dwarf3_c.elf binary could not be opened", res);
62 
63 	RBinDwarfDebugAbbrev *da = r_bin_dwarf_parse_abbrev (bin, MODE);
64 	mu_assert_eq (da->count, 7, "Incorrect number of abbreviation");
65 	RBinDwarfDebugInfo *info = r_bin_dwarf_parse_info (da, bin, MODE);
66 	mu_assert_eq (info->count, 1, "Incorrect number of info compilation units");
67 
68 	// check header
69 	RBinDwarfCompUnit cu = info->comp_units[0];
70 	RBinDwarfCompUnitHdr hdr = cu.hdr;
71 
72 	check_basic_unit_header (3, 0xa9, false, 8, 0x0);
73 
74 	mu_assert_eq (cu.count, 11, "Wrong attribute information");
75 	mu_assert_eq (cu.offset, 0x0, "Wrong attribute information");
76 	// check some of the attributes
77 	int i = 0;
78 	check_die_abbr_code (1);
79 
80 	check_die_length (7);
81 	check_die_tag (DW_TAG_compile_unit);
82 
83 	check_attr_name (0, DW_AT_producer);
84 	check_attr_string (2, "main.c");
85 	i++;
86 	check_die_abbr_code (2);
87 	i++;
88 	check_die_abbr_code (3);
89 	i++;
90 	check_die_abbr_code (4);
91 	i++;
92 	check_die_abbr_code (5);
93 	i++;
94 	check_die_abbr_code (0);
95 	i++;
96 	check_die_abbr_code (6);
97 	i++;
98 	check_die_abbr_code (7);
99 
100 	check_attr_string (0, "b");
101 	check_attr_data (3, 15);
102 
103 	i++;
104 	check_die_abbr_code (7);
105 	i++;
106 	check_die_abbr_code (0);
107 	i++;
108 	check_die_abbr_code (0);
109 
110 	r_bin_dwarf_free_debug_info (info);
111 	r_bin_dwarf_free_debug_abbrev (da);
112 	r_bin_free (bin);
113 	r_io_free (io);
114 	mu_end;
115 }
116 
test_dwarf4_cpp_multiple_modules(void)117 bool test_dwarf4_cpp_multiple_modules(void) {
118 	RBin *bin = r_bin_new ();
119 	RIO *io = r_io_new ();
120 	r_io_bind (io, &bin->iob);
121 
122 	RBinOptions opt = { 0 };
123 	bool res = r_bin_open (bin, "bins/elf/dwarf4_many_comp_units.elf", &opt);
124 	mu_assert ("dwarf4_many_comp_units.elf binary could not be opened", res);
125 
126 	RBinDwarfDebugAbbrev *da = r_bin_dwarf_parse_abbrev (bin, MODE);
127 	mu_assert_eq (da->count, 37, "Incorrect number of abbreviation");
128 	RBinDwarfDebugInfo *info = r_bin_dwarf_parse_info (da, bin, MODE);
129 	mu_assert_notnull (info, "Failed parsing of debug_info");
130 	mu_assert_eq (info->count, 2, "Incorrect number of info compilation units");
131 
132 	// check header
133 	RBinDwarfCompUnit cu = info->comp_units[0];
134 	RBinDwarfCompUnitHdr hdr = cu.hdr;
135 	check_basic_unit_header (4, 0x2c0, false, 8, 0x0);
136 
137 	// check some of the attributes
138 	mu_assert_eq (cu.count, 73, "Wrong attribute information");
139 	mu_assert_eq (cu.offset, 0x0, "Wrong attribute information");
140 
141 	int i = 0;
142 	check_die_abbr_code (1);
143 	check_die_length (7);
144 	check_die_tag (DW_TAG_compile_unit);
145 
146 	check_attr_name (0, DW_AT_producer);
147 	check_attr_string (2, "../main.cpp");
148 	check_attr_name (6, DW_AT_ranges);
149 	check_attr_reference (6, 0x0);
150 
151 	i++;
152 	check_die_abbr_code (2);
153 	i++;
154 	check_die_abbr_code (3);
155 	i++;
156 	check_die_abbr_code (3);
157 	i++;
158 	check_die_abbr_code (3);
159 	i++;
160 	check_die_abbr_code (0);
161 	i++;
162 	// i == 6
163 	check_die_abbr_code (4);
164 	check_attr_reference (0, 0x6e);
165 	check_attr_data (1, 4);
166 	check_attr_string (2, "Bird");
167 	check_attr_data (3, 8);
168 	check_attr_data (4, 1);
169 	check_attr_data (5, 9);
170 	i++;
171 	check_die_abbr_code (5);
172 	check_die_tag (DW_TAG_member);
173 	check_attr_string (0, "_vptr$Bird");
174 	check_attr_reference (1, 0xc5);
175 	check_attr_data (2, 0);
176 	check_attr_flag (3, true);
177 
178 	i++;
179 	check_die_abbr_code (6);
180 	i++;
181 	check_die_abbr_code (7);
182 	i++;
183 	check_die_abbr_code (0);
184 	i++;
185 	check_die_abbr_code (8);
186 	i++;
187 	check_die_abbr_code (7);
188 	i++;
189 	check_die_abbr_code (0);
190 	i++;
191 	check_die_abbr_code (9);
192 	check_die_tag (DW_TAG_subprogram);
193 	check_die_length (10);
194 	check_attr_string (0, "_ZN4Bird3flyEv");
195 	check_attr_string (1, "fly");
196 	check_attr_data (2, 1);
197 	check_attr_data (3, 12);
198 	check_attr_reference (4, 0xd8);
199 	check_attr_name (6, DW_AT_vtable_elem_location);
200 	check_attr_form (7, DW_FORM_flag_present);
201 	check_attr_flag (7, true);
202 	check_attr_name (8, DW_AT_external);
203 	check_attr_flag (8, true);
204 	check_attr_name (9, DW_AT_containing_type);
205 	check_attr_reference (9, 0x6e);
206 	i++;
207 	check_die_abbr_code (7);
208 	mu_assert_eq (cu.dies[i].abbrev_code, 7, "Wrong attribute information");
209 	i++;
210 	check_die_abbr_code (0);
211 	mu_assert_eq (cu.dies[i].abbrev_code, 0, "Wrong attribute information");
212 	i++;
213 	check_die_abbr_code (0);
214 	mu_assert_eq (cu.dies[i].abbrev_code, 0, "Wrong attribute information");
215 	i++;
216 	check_die_abbr_code (10);
217 	mu_assert_eq (cu.dies[i].abbrev_code, 10, "Wrong attribute information");
218 	i++;
219 	check_die_abbr_code (11);
220 	mu_assert_eq (cu.dies[i].abbrev_code, 11, "Wrong attribute information");
221 	i++;
222 	check_die_abbr_code (12);
223 	mu_assert_eq (cu.dies[i].abbrev_code, 12, "Wrong attribute information");
224 	i++;
225 	check_die_abbr_code (13);
226 	check_die_tag (DW_TAG_base_type);
227 	check_die_length (3);
228 	i++;
229 	check_die_abbr_code (10);
230 	i++;
231 	check_die_abbr_code (14);
232 	i++;
233 	check_die_abbr_code (15);
234 	i++;
235 	check_die_abbr_code (0);
236 	i++;
237 	check_die_abbr_code (4);
238 	i = 66;
239 	check_die_abbr_code (18);
240 	check_die_length (5);
241 	check_attr_reference (3, 0x2a7);
242 	i++;
243 	check_die_abbr_code (15);
244 	check_die_length (4);
245 	check_attr_block_length (0, 2);
246 	check_attr_block_data (0, 0, 0x91);
247 	check_attr_block_data (0, 1, 0x78);
248 	check_attr_string (1, "this");
249 	check_attr_reference (2, 0x2be);
250 	check_attr_flag (3, true);
251 	i++;
252 	check_die_abbr_code (0);
253 	i++;
254 	check_die_abbr_code (10);
255 	i++;
256 	check_die_abbr_code (10);
257 	check_die_tag (DW_TAG_pointer_type);
258 	i++;
259 	check_die_abbr_code (10);
260 	i++;
261 	check_die_abbr_code (0);
262 	i++;
263 
264 	cu = info->comp_units[1];
265 	hdr = cu.hdr;
266 	check_basic_unit_header (4, 0x192, false, 8, 0xfd);
267 
268 	// check some of the attributes
269 	mu_assert_eq (cu.count, 42, "Wrong attribute information");
270 	mu_assert_eq (cu.offset, 0x2c4, "Wrong attribute information");
271 
272 	i = 0;
273 	check_die_abbr_code (1);
274 	check_die_length (7);
275 	check_die_tag (DW_TAG_compile_unit);
276 	check_attr_name (0, DW_AT_producer);
277 	check_attr_string (0, "clang version 10.0.0-4ubuntu1 ");
278 	check_attr_data (1, 33);
279 	check_attr_string (2, "../mammal.cpp");
280 	check_attr_address (5, 0x0);
281 	check_attr_form (5, DW_FORM_addr);
282 	check_attr_name (6, DW_AT_ranges);
283 	check_attr_reference (6, 0xb0);
284 	i++;
285 	check_die_abbr_code (2);
286 	i++;
287 	check_die_abbr_code (3);
288 	i++;
289 	check_die_abbr_code (4);
290 	i++;
291 	check_die_abbr_code (5);
292 	i++;
293 	check_die_abbr_code (0);
294 	i++;
295 	check_die_abbr_code (6);
296 	i++;
297 	check_die_abbr_code (5);
298 	i++;
299 	check_die_abbr_code (0);
300 	i = 35;
301 	check_die_abbr_code (8);
302 	check_die_tag (DW_TAG_pointer_type);
303 	check_die_length (1);
304 	check_attr_form (0, DW_FORM_ref4);
305 	check_attr_reference (0, 0x407);
306 	i++;
307 	check_die_abbr_code (19);
308 	check_die_tag (DW_TAG_subprogram);
309 	check_die_length (5);
310 	check_attr_name (2, DW_AT_frame_base);
311 	check_attr_block_length (2, 1);
312 	check_attr_block_data (2, 0, 0x56);
313 	check_attr_reference (3, 0x442);
314 	check_attr_reference (4, 0x410);
315 	i=40;
316 	check_die_abbr_code (8);
317 	i++;
318 	check_die_abbr_code (0);
319 
320 	r_bin_dwarf_free_debug_info (info);
321 	r_bin_dwarf_free_debug_abbrev (da);
322 	r_bin_free (bin);
323 	r_io_free (io);
324 	mu_end;
325 }
326 
test_dwarf2_big_endian(void)327 bool test_dwarf2_big_endian(void) {
328 	RBin *bin = r_bin_new ();
329 	RIO *io = r_io_new ();
330 	r_io_bind (io, &bin->iob);
331 
332 	RBinOptions opt = { 0 };
333 	bool res = r_bin_open (bin, "bins/elf/ppc64_sudoku_dwarf", &opt);
334 	mu_assert ("dwarf4_many_comp_units.elf binary could not be opened", res);
335 
336 	RBinDwarfDebugAbbrev *da = r_bin_dwarf_parse_abbrev (bin, MODE);
337 	mu_assert_eq (da->count, 108, "Incorrect number of abbreviation");
338 	RBinDwarfDebugInfo *info = r_bin_dwarf_parse_info (da, bin, MODE);
339 	mu_assert_notnull (info, "Failed parsing of debug_info");
340 	mu_assert_eq (info->count, 1, "Incorrect number of info compilation units");
341 
342 	// check header
343 	RBinDwarfCompUnit cu = info->comp_units[0];
344 	RBinDwarfCompUnitHdr hdr = cu.hdr;
345 	check_basic_unit_header (2, 0x38b9, false, 8, 0x0);
346 
347 	int i = 0;
348 	check_die_abbr_code (1);
349 	check_die_length (7);
350 	check_die_tag (DW_TAG_compile_unit);
351 
352 	check_attr_name (0, DW_AT_producer);
353 	check_attr_string (0, "GNU C++14 9.3.0 -msecure-plt -mabi=elfv2 -mcpu=970 -gdwarf-2 -gstrict-dwarf -O1");
354 	check_attr_name (1, DW_AT_language);
355 	check_attr_data (1, DW_LANG_C_plus_plus);
356 
357 	check_attr_name (4, DW_AT_low_pc);
358 	check_attr_reference (4, 0x0000000010000ec4);
359 	check_attr_name (5, DW_AT_high_pc);
360 	check_attr_reference (5, 0x0000000010001c48);
361 	check_attr_name (6, DW_AT_stmt_list);
362 	check_attr_reference (6, 0x0);
363 
364 	i+=2;
365 	check_die_abbr_code (3);
366 	check_die_tag (DW_TAG_base_type);
367 
368 	check_attr_name (0, DW_AT_byte_size);
369 	check_attr_data (0, 0x08);
370 
371 	check_attr_name (1, DW_AT_encoding);
372 	check_attr_data (1, DW_ATE_unsigned);
373 
374 	check_attr_name (2, DW_AT_name);
375 	check_attr_string (2, "long unsigned int");
376 
377 	i++; check_die_abbr_code (4);
378 	i++; check_die_abbr_code (2);
379 	i++; check_die_abbr_code (3);
380 	i++; check_die_abbr_code (2);
381 	i++;
382 	// i == 7
383 	check_die_abbr_code (5);
384 	check_die_tag (DW_TAG_structure_type);
385 
386 	check_attr_name (0, DW_AT_name);
387 	check_attr_string (0, "_IO_FILE");
388 
389 	check_attr_name (1, DW_AT_byte_size);
390 	check_attr_data (1, 0x01);
391 
392 	check_attr_name (2, DW_AT_decl_file);
393 	check_attr_name (3, DW_AT_decl_line);
394 	check_attr_name (4, DW_AT_decl_column);
395 	check_attr_name (5, DW_AT_sibling);
396 
397 	i = 1668 - 4;
398 	check_die_abbr_code (108);
399 	check_die_tag (DW_TAG_subprogram);
400 
401 	check_attr_name (0, DW_AT_abstract_origin);
402 	check_attr_reference (0, 0x2f32);
403 
404 	check_attr_name (1, DW_AT_MIPS_linkage_name);
405 	check_attr_string (1, "_Z8isnumberc");
406 
407 	check_attr_name (2, DW_AT_low_pc);
408 	check_attr_reference (2, 0x0000000010001aa4);
409 
410 	check_attr_name (3, DW_AT_high_pc);
411 	check_attr_reference (3, 0x0000000010001ac8);
412 
413 	r_bin_dwarf_free_debug_info (info);
414 	r_bin_dwarf_free_debug_abbrev (da);
415 	r_bin_free (bin);
416 	r_io_free (io);
417 	mu_end;
418 }
419 
all_tests()420 bool all_tests() {
421 	mu_run_test (test_dwarf3_c);
422 	mu_run_test (test_dwarf4_cpp_multiple_modules);
423 	mu_run_test (test_dwarf2_big_endian);
424 	return tests_passed != tests_run;
425 }
426 
main(int argc,char ** argv)427 int main(int argc, char **argv) {
428 	return all_tests ();
429 }
430