1 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
2 // -*- Mode: C++ -*-
3 //
4 // Copyright (C) 2013-2022 Red Hat, Inc.
5 //
6 // Author: Dodji Seketeli
7
8 /// @file read ELF binaries containing DWARF, save them in XML corpus
9 /// files and diff the corpus files against reference XML corpus
10 /// files.
11
12 #include <cstdlib>
13 #include <fstream>
14 #include <iostream>
15 #include <memory>
16 #include <string>
17 #include <vector>
18 #include "test-read-common.h"
19 #include "abg-dwarf-reader.h"
20
21 using std::vector;
22 using std::string;
23 using std::cerr;
24
25 using abigail::tests::read_common::InOutSpec;
26 using abigail::tests::read_common::test_task;
27 using abigail::tests::read_common::display_usage;
28 using abigail::tests::read_common::options;
29 using abigail::tests::get_build_dir;
30
31 using abigail::xml_writer::SEQUENCE_TYPE_ID_STYLE;
32 using abigail::xml_writer::HASH_TYPE_ID_STYLE;
33 using abigail::xml_writer::type_id_style_kind;
34 using abigail::tools_utils::emit_prefix;
35
36 using namespace abigail;
37
38 static InOutSpec in_out_specs[] =
39 {
40 {
41 "data/test-read-dwarf/test0",
42 "",
43 "",
44 SEQUENCE_TYPE_ID_STYLE,
45 "data/test-read-dwarf/test0.abi",
46 "output/test-read-dwarf/test0.abi",
47 NULL,
48 },
49 {
50 "data/test-read-dwarf/test0",
51 "",
52 "",
53 HASH_TYPE_ID_STYLE,
54 "data/test-read-dwarf/test0.hash.abi",
55 "output/test-read-dwarf/test0.hash.abi",
56 NULL,
57 },
58 {
59 "data/test-read-dwarf/test1",
60 "",
61 "",
62 SEQUENCE_TYPE_ID_STYLE,
63 "data/test-read-dwarf/test1.abi",
64 "output/test-read-dwarf/test1.abi",
65 NULL,
66 },
67 {
68 "data/test-read-dwarf/test1",
69 "",
70 "",
71 HASH_TYPE_ID_STYLE,
72 "data/test-read-dwarf/test1.hash.abi",
73 "output/test-read-dwarf/test1.hash.abi",
74 NULL,
75 },
76 {
77 "data/test-read-dwarf/test2.so",
78 "",
79 "",
80 SEQUENCE_TYPE_ID_STYLE,
81 "data/test-read-dwarf/test2.so.abi",
82 "output/test-read-dwarf/test2.so.abi",
83 NULL,
84 },
85 {
86 "data/test-read-dwarf/test2.so",
87 "",
88 "",
89 HASH_TYPE_ID_STYLE,
90 "data/test-read-dwarf/test2.so.hash.abi",
91 "output/test-read-dwarf/test2.so.hash.abi",
92 NULL,
93 },
94 {
95 "data/test-read-common/test3.so",
96 "",
97 "",
98 SEQUENCE_TYPE_ID_STYLE,
99 "data/test-read-dwarf/test3.so.abi",
100 "output/test-read-dwarf/test3.so.abi",
101 NULL,
102 },
103 {
104 "data/test-read-common/test3.so",
105 "",
106 "",
107 HASH_TYPE_ID_STYLE,
108 "data/test-read-dwarf/test3.so.hash.abi",
109 "output/test-read-dwarf/test3.so.hash.abi",
110 NULL,
111 },
112 // suppress all except the main symbol of a group of aliases
113 {
114 "data/test-read-common/test3.so",
115 "data/test-read-common/test3-alias-1.suppr",
116 "",
117 HASH_TYPE_ID_STYLE,
118 "data/test-read-dwarf/test3-alias-1.so.hash.abi",
119 "output/test-read-dwarf/test3-alias-1.so.hash.abi",
120 NULL,
121 },
122 // suppress the main symbol of a group of aliases
123 {
124 "data/test-read-common/test3.so",
125 "data/test-read-common/test3-alias-2.suppr",
126 "",
127 HASH_TYPE_ID_STYLE,
128 "data/test-read-dwarf/test3-alias-2.so.hash.abi",
129 "output/test-read-dwarf/test3-alias-2.so.hash.abi",
130 NULL,
131 },
132 // suppress all except one non main symbol of a group of aliases
133 {
134 "data/test-read-common/test3.so",
135 "data/test-read-common/test3-alias-3.suppr",
136 "",
137 HASH_TYPE_ID_STYLE,
138 "data/test-read-dwarf/test3-alias-3.so.hash.abi",
139 "output/test-read-dwarf/test3-alias-3.so.hash.abi",
140 NULL,
141 },
142 // suppress all symbols of a group of aliases
143 {
144 "data/test-read-common/test3.so",
145 "data/test-read-common/test3-alias-4.suppr",
146 "",
147 HASH_TYPE_ID_STYLE,
148 "data/test-read-dwarf/test3-alias-4.so.hash.abi",
149 "output/test-read-dwarf/test3-alias-4.so.hash.abi",
150 NULL,
151 },
152 // suppress the main symbols with alias (function+variable) in .o file
153 {
154 "data/test-read-dwarf/test-suppressed-alias.o",
155 "data/test-read-dwarf/test-suppressed-alias.suppr",
156 "",
157 HASH_TYPE_ID_STYLE,
158 "data/test-read-dwarf/test-suppressed-alias.o.abi",
159 "output/test-read-dwarf/test-suppressed-alias.o.abi",
160 NULL,
161 },
162 {
163 "data/test-read-common/test4.so",
164 "",
165 "",
166 SEQUENCE_TYPE_ID_STYLE,
167 "data/test-read-dwarf/test4.so.abi",
168 "output/test-read-dwarf/test4.so.abi",
169 NULL,
170 },
171 {
172 "data/test-read-common/test4.so",
173 "",
174 "",
175 HASH_TYPE_ID_STYLE,
176 "data/test-read-dwarf/test4.so.hash.abi",
177 "output/test-read-dwarf/test4.so.hash.abi",
178 NULL,
179 },
180 {
181 "data/test-read-dwarf/test5.o",
182 "",
183 "",
184 SEQUENCE_TYPE_ID_STYLE,
185 "data/test-read-dwarf/test5.o.abi",
186 "output/test-read-dwarf/test5.o.abi",
187 NULL,
188 },
189 {
190 "data/test-read-dwarf/test5.o",
191 "",
192 "",
193 HASH_TYPE_ID_STYLE,
194 "data/test-read-dwarf/test5.o.hash.abi",
195 "output/test-read-dwarf/test5.o.hash.abi",
196 NULL,
197 },
198 {
199 "data/test-read-dwarf/test6.so",
200 "",
201 "",
202 SEQUENCE_TYPE_ID_STYLE,
203 "data/test-read-dwarf/test6.so.abi",
204 "output/test-read-dwarf/test6.so.abi",
205 NULL,
206 },
207 {
208 "data/test-read-dwarf/test6.so",
209 "",
210 "",
211 HASH_TYPE_ID_STYLE,
212 "data/test-read-dwarf/test6.so.hash.abi",
213 "output/test-read-dwarf/test6.so.hash.abi",
214 NULL,
215 },
216 {
217 "data/test-read-dwarf/test7.so",
218 "",
219 "",
220 SEQUENCE_TYPE_ID_STYLE,
221 "data/test-read-dwarf/test7.so.abi",
222 "output/test-read-dwarf/test7.so.abi",
223 NULL,
224 },
225 {
226 "data/test-read-dwarf/test7.so",
227 "",
228 "",
229 HASH_TYPE_ID_STYLE,
230 "data/test-read-dwarf/test7.so.hash.abi",
231 "output/test-read-dwarf/test7.so.hash.abi",
232 NULL,
233 },
234 {
235 "data/test-read-dwarf/test8-qualified-this-pointer.so",
236 "",
237 "",
238 SEQUENCE_TYPE_ID_STYLE,
239 "data/test-read-dwarf/test8-qualified-this-pointer.so.abi",
240 "output/test-read-dwarf/test8-qualified-this-pointer.so.abi",
241 NULL,
242 },
243 {
244 "data/test-read-dwarf/test8-qualified-this-pointer.so",
245 "",
246 "",
247 HASH_TYPE_ID_STYLE,
248 "data/test-read-dwarf/test8-qualified-this-pointer.so.hash.abi",
249 "output/test-read-dwarf/test8-qualified-this-pointer.so.hash.abi",
250 NULL,
251 },
252 {
253 "data/test-read-dwarf/test9-pr18818-clang.so",
254 "",
255 "",
256 SEQUENCE_TYPE_ID_STYLE,
257 "data/test-read-dwarf/test9-pr18818-clang.so.abi",
258 "output/test-read-dwarf/test9-pr18818-clang.so.abi",
259 NULL,
260 },
261 {
262 "data/test-read-dwarf/test10-pr18818-gcc.so",
263 "",
264 "",
265 SEQUENCE_TYPE_ID_STYLE,
266 "data/test-read-dwarf/test10-pr18818-gcc.so.abi",
267 "output/test-read-dwarf/test10-pr18818-gcc.so.abi",
268 NULL,
269 },
270 {
271 "data/test-read-dwarf/test11-pr18828.so",
272 "",
273 "",
274 SEQUENCE_TYPE_ID_STYLE,
275 "data/test-read-dwarf/test11-pr18828.so.abi",
276 "output/test-read-dwarf/test11-pr18828.so.abi",
277 NULL,
278 },
279 {
280 "data/test-read-dwarf/test12-pr18844.so",
281 "",
282 "",
283 SEQUENCE_TYPE_ID_STYLE,
284 "data/test-read-dwarf/test12-pr18844.so.abi",
285 "output/test-read-dwarf/test12-pr18844.so.abi",
286 NULL,
287 },
288 {
289 "data/test-read-dwarf/test13-pr18894.so",
290 "",
291 "",
292 SEQUENCE_TYPE_ID_STYLE,
293 "data/test-read-dwarf/test13-pr18894.so.abi",
294 "output/test-read-dwarf/test13-pr18894.so.abi",
295 NULL,
296 },
297 {
298 "data/test-read-dwarf/test14-pr18893.so",
299 "",
300 "",
301 SEQUENCE_TYPE_ID_STYLE,
302 "data/test-read-dwarf/test14-pr18893.so.abi",
303 "output/test-read-dwarf/test14-pr18893.so.abi",
304 NULL,
305 },
306 {
307 "data/test-read-dwarf/test15-pr18892.so",
308 "",
309 "",
310 SEQUENCE_TYPE_ID_STYLE,
311 "data/test-read-dwarf/test15-pr18892.so.abi",
312 "output/test-read-dwarf/test15-pr18892.so.abi",
313 NULL,
314 },
315 {
316 "data/test-read-dwarf/test16-pr18904.so",
317 "",
318 "",
319 SEQUENCE_TYPE_ID_STYLE,
320 "data/test-read-dwarf/test16-pr18904.so.abi",
321 "output/test-read-dwarf/test16-pr18904.so.abi",
322 NULL,
323 },
324 {
325 "data/test-read-dwarf/test17-pr19027.so",
326 "",
327 "",
328 SEQUENCE_TYPE_ID_STYLE,
329 "data/test-read-dwarf/test17-pr19027.so.abi",
330 "output/test-read-dwarf/test17-pr19027.so.abi",
331 NULL,
332 },
333 {
334 "data/test-read-dwarf/test18-pr19037-libvtkRenderingLIC-6.1.so",
335 "",
336 "",
337 SEQUENCE_TYPE_ID_STYLE,
338 "data/test-read-dwarf/test18-pr19037-libvtkRenderingLIC-6.1.so.abi",
339 "output/test-read-dwarf/test18-pr19037-libvtkRenderingLIC-6.1.so.abi",
340 NULL,
341 },
342 {
343 "data/test-read-dwarf/test19-pr19023-libtcmalloc_and_profiler.so",
344 "",
345 "",
346 SEQUENCE_TYPE_ID_STYLE,
347 "data/test-read-dwarf/test19-pr19023-libtcmalloc_and_profiler.so.abi",
348 "output/test-read-dwarf/test19-pr19023-libtcmalloc_and_profiler.so.abi",
349 NULL,
350 },
351 {
352 "data/test-read-dwarf/test20-pr19025-libvtkParallelCore-6.1.so",
353 "",
354 "",
355 SEQUENCE_TYPE_ID_STYLE,
356 "data/test-read-dwarf/test20-pr19025-libvtkParallelCore-6.1.so.abi",
357 "output/test-read-dwarf/test20-pr19025-libvtkParallelCore-6.1.so.abi",
358 NULL,
359 },
360 {
361 "data/test-read-dwarf/test21-pr19092.so",
362 "",
363 "",
364 SEQUENCE_TYPE_ID_STYLE,
365 "data/test-read-dwarf/test21-pr19092.so.abi",
366 "output/test-read-dwarf/test21-pr19092.so.abi",
367 NULL,
368 },
369 {
370 "data/test-read-dwarf/test22-pr19097-libstdc++.so.6.0.17.so",
371 "",
372 "",
373 SEQUENCE_TYPE_ID_STYLE,
374 "data/test-read-dwarf/test22-pr19097-libstdc++.so.6.0.17.so.abi",
375 "output/test-read-dwarf/test22-pr19097-libstdc++.so.6.0.17.so.abi",
376 NULL,
377 },
378 {
379 "data/test-read-dwarf/libtest23.so",
380 "",
381 "",
382 SEQUENCE_TYPE_ID_STYLE,
383 "data/test-read-dwarf/libtest23.so.abi",
384 "output/test-read-dwarf/libtest23.so.abi",
385 NULL,
386 },
387 {
388 "data/test-read-dwarf/libtest24-drop-fns.so",
389 "data/test-read-dwarf/test24-drop-fns-0.suppr",
390 "",
391 SEQUENCE_TYPE_ID_STYLE,
392 "data/test-read-dwarf/libtest24-drop-fns.so.abi",
393 "output/test-read-dwarf/libtest24-drop-fns.so.abi",
394 NULL,
395 },
396 {
397 "data/test-read-dwarf/libtest24-drop-fns.so",
398 "",
399 "",
400 SEQUENCE_TYPE_ID_STYLE,
401 "data/test-read-dwarf/libtest24-drop-fns-2.so.abi",
402 "output/test-read-dwarf/libtest24-drop-fns-2.so.abi",
403 NULL,
404 },
405 {
406 "data/test-read-dwarf/PR22015-libboost_iostreams.so",
407 "",
408 "",
409 SEQUENCE_TYPE_ID_STYLE,
410 "data/test-read-dwarf/PR22015-libboost_iostreams.so.abi",
411 "output/test-read-dwarf/PR22015-libboost_iostreams.so.abi",
412 NULL,
413 },
414 {
415 "data/test-read-dwarf/PR22122-libftdc.so",
416 "",
417 "",
418 SEQUENCE_TYPE_ID_STYLE,
419 "data/test-read-dwarf/PR22122-libftdc.so.abi",
420 "output/test-read-dwarf/PR22122-libftdc.so.abi",
421 NULL,
422 },
423 {
424 "data/test-read-dwarf/PR24378-fn-is-not-scope.o",
425 "",
426 "",
427 SEQUENCE_TYPE_ID_STYLE,
428 "data/test-read-dwarf/PR24378-fn-is-not-scope.abi",
429 "output/test-read-dwarf/PR24378-fn-is-not-scope.abi",
430 NULL,
431 },
432 #if defined(HAVE_R_AARCH64_ABS64_MACRO) && defined(HAVE_R_AARCH64_PREL32_MACRO)
433 {
434 "data/test-read-dwarf/PR25007-sdhci.ko",
435 "",
436 "",
437 SEQUENCE_TYPE_ID_STYLE,
438 "data/test-read-dwarf/PR25007-sdhci.ko.abi",
439 "output/test-read-dwarf/PR25007-sdhci.ko.abi",
440 NULL,
441 },
442 #endif
443 #if defined HAVE_DW_FORM_strx
444 {
445 "data/test-read-dwarf/PR25042-libgdbm-clang-dwarf5.so.6.0.0",
446 "",
447 "",
448 SEQUENCE_TYPE_ID_STYLE,
449 "data/test-read-dwarf/PR25042-libgdbm-clang-dwarf5.so.6.0.0.abi",
450 "output/test-read-dwarf/PR25042-libgdbm-clang-dwarf5.so.6.0.0.abi",
451 NULL,
452 },
453 #endif
454 {
455 "data/test-read-dwarf/test25-bogus-binary.elf",
456 "",
457 "",
458 SEQUENCE_TYPE_ID_STYLE,
459 NULL,
460 NULL,
461 NULL,
462 },
463 {
464 "data/test-read-dwarf/test26-bogus-binary.elf",
465 "",
466 "",
467 SEQUENCE_TYPE_ID_STYLE,
468 NULL,
469 NULL,
470 NULL,
471 },
472 {
473 "data/test-read-dwarf/test27-bogus-binary.elf",
474 "",
475 "",
476 SEQUENCE_TYPE_ID_STYLE,
477 NULL,
478 NULL,
479 NULL,
480 },
481 {
482 "data/test-read-common/PR26261/PR26261-exe",
483 "",
484 "",
485 SEQUENCE_TYPE_ID_STYLE,
486 "data/test-read-dwarf/PR26261/PR26261-exe.abi",
487 "output/test-read-dwarf/PR26261/PR26261-exe.abi",
488 NULL,
489 },
490 {
491 "data/test-read-common/test-PR26568-1.o",
492 "",
493 "",
494 SEQUENCE_TYPE_ID_STYLE,
495 "data/test-read-dwarf/test-PR26568-1.o.abi",
496 "output/test-read-dwarf/test-PR26568-1.o.abi",
497 NULL,
498 },
499 {
500 "data/test-read-common/test-PR26568-2.o",
501 "",
502 "",
503 SEQUENCE_TYPE_ID_STYLE,
504 "data/test-read-dwarf/test-PR26568-2.o.abi",
505 "output/test-read-dwarf/test-PR26568-2.o.abi",
506 NULL,
507 },
508 {
509 "data/test-read-dwarf/test-libandroid.so",
510 "",
511 "",
512 HASH_TYPE_ID_STYLE,
513 "data/test-read-dwarf/test-libandroid.so.abi",
514 "output/test-read-dwarf/test-libandroid.so.abi",
515 NULL,
516 },
517 {
518 "data/test-read-common/PR27700/test-PR27700.o",
519 "",
520 "data/test-read-common/PR27700/pub-incdir",
521 HASH_TYPE_ID_STYLE,
522 "data/test-read-dwarf/PR27700/test-PR27700.abi",
523 "output/test-read-dwarf/PR27700/test-PR27700.abi",
524 NULL,
525 },
526 {
527 "data/test-read-dwarf/test-libaaudio.so",
528 "",
529 "",
530 HASH_TYPE_ID_STYLE,
531 "data/test-read-dwarf/test-libaaudio.so.abi",
532 "output/test-read-dwarf/test-libaaudio.so.abi",
533 NULL,
534 },
535 {
536 "data/test-read-dwarf/PR28584/PR28584-smv.clang.o",
537 "",
538 "",
539 SEQUENCE_TYPE_ID_STYLE,
540 "data/test-read-dwarf/PR28584/PR28584-smv.clang.o.abi",
541 "output/test-read-dwarf/PR28584/PR28584-smv.clang.o.abi",
542 NULL,
543 },
544 {
545 "data/test-read-dwarf/PR29443-missing-xx.o",
546 "",
547 "",
548 SEQUENCE_TYPE_ID_STYLE,
549 "data/test-read-dwarf/PR29443-missing-xx.o.abi",
550 "output/test-read-dwarf/PR29443-missing-xx.o.abi",
551 NULL,
552 },
553 // DWARF fallback feature.
554 {
555 "data/test-read-dwarf/test-fallback.o",
556 "",
557 "",
558 SEQUENCE_TYPE_ID_STYLE,
559 "data/test-read-dwarf/test-fallback.abi",
560 "output/test-read-dwarf/test-fallback.abi",
561 #ifdef WITH_CTF
562 "--ctf",
563 #else
564 NULL,
565 #endif
566 },
567
568 // This should be the last entry.
569 {NULL, NULL, NULL, SEQUENCE_TYPE_ID_STYLE, NULL, NULL, NULL}
570 };
571
572 using abigail::suppr::suppression_sptr;
573 using abigail::suppr::suppressions_type;
574 using abigail::suppr::read_suppressions;
575
576 /// Task specialization to perform DWARF tests.
577 struct test_task_dwarf : public test_task
578 {
579 test_task_dwarf(const InOutSpec &s,
580 string& a_out_abi_base,
581 string& a_in_elf_base,
582 string& a_in_abi_base);
583 virtual void
584 perform();
585
586 virtual
~test_task_dwarftest_task_dwarf587 ~test_task_dwarf()
588 {}
589 }; // end struct test_task_dwarf
590
591 /// Constructor.
592 ///
593 /// Task to be executed for each DWARF test entry in @ref
594 /// abigail::tests::read_common::InOutSpec.
595 ///
596 /// @param InOutSpec the array containing set of tests.
597 ///
598 /// @param a_out_abi_base the output base directory for abixml files.
599 ///
600 /// @param a_in_elf_base the input base directory for object files.
601 ///
602 /// @param a_in_elf_base the input base directory for expected
603 /// abixml files.
test_task_dwarf(const InOutSpec & s,string & a_out_abi_base,string & a_in_elf_base,string & a_in_abi_base)604 test_task_dwarf::test_task_dwarf(const InOutSpec &s,
605 string& a_out_abi_base,
606 string& a_in_elf_base,
607 string& a_in_abi_base)
608 : test_task(s, a_out_abi_base, a_in_elf_base, a_in_abi_base)
609 {}
610
611 /// The thread function to execute each DWARF test entry in @ref
612 /// abigail::tests::read_common::InOutSpec.
613 ///
614 /// This reads the corpus into memory, saves it to disk, loads it
615 /// again and compares the new in-memory representation against the
616 void
perform()617 test_task_dwarf::perform()
618 {
619 set_in_elf_path();
620 set_in_suppr_spec_path();
621 set_in_public_headers_path();
622
623 if (!set_out_abi_path()
624 || in_elf_path.empty())
625 return;
626
627 string abidw = string(get_build_dir()) + "/tools/abidw";
628 string drop_private_types;
629 if (!in_public_headers_path.empty())
630 drop_private_types += "--headers-dir " + in_public_headers_path +
631 " --drop-private-types";
632 string type_id_style = "sequence";
633 if (spec.type_id_style == HASH_TYPE_ID_STYLE)
634 type_id_style = "hash";
635
636 string cmd = abidw + " --no-architecture "
637 + " --type-id-style " + type_id_style
638 + " --no-corpus-path "
639 + drop_private_types + " " + in_elf_path
640 +" > " + out_abi_path;
641
642 if (system(cmd.c_str()))
643 {
644 error_message = string("abidw failed:\n")
645 + "command was: '" + cmd + "'\n";
646 return;
647 }
648
649 if (!(is_ok = run_abidw()))
650 return;
651
652 if (!(is_ok = run_diff()))
653 return;
654 }
655
656 /// Create a new DWARF instance for task to be execute by the testsuite.
657 ///
658 /// @param s the @ref abigail::tests::read_common::InOutSpec
659 /// tests container.
660 ///
661 /// @param a_out_abi_base the output base directory for abixml files.
662 ///
663 /// @param a_in_elf_base the input base directory for object files.
664 ///
665 /// @param a_in_abi_base the input base directory for abixml files.
666 ///
667 /// @return abigail::tests::read_common::test_task instance.
668 static test_task*
new_task(const InOutSpec * s,string & a_out_abi_base,string & a_in_elf_base,string & a_in_abi_base)669 new_task(const InOutSpec* s, string& a_out_abi_base,
670 string& a_in_elf_base, string& a_in_abi_base)
671 {
672 return new test_task_dwarf(*s, a_out_abi_base,
673 a_in_elf_base, a_in_abi_base);
674 }
675
676 int
main(int argc,char * argv[])677 main(int argc, char *argv[])
678 {
679 options opts;
680 if (!parse_command_line(argc, argv, opts))
681 {
682 if (!opts.wrong_option.empty())
683 emit_prefix(argv[0], cerr)
684 << "unrecognized option: " << opts.wrong_option << "\n";
685 display_usage(argv[0], cerr);
686 return 1;
687 }
688
689 // compute number of tests to be executed.
690 const size_t num_tests = sizeof(in_out_specs) / sizeof(InOutSpec) - 1;
691
692 return run_tests(num_tests, in_out_specs, opts, new_task);
693 }
694