• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
2 // -*- Mode: C++ -*-
3 //
4 // Copyright (C) 2021-2022 Oracle, Inc.
5 //
6 // Author: Guillermo E. Martinez
7 
8 /// @file
9 ///
10 /// This file implement the CTF testsuite. It reads ELF binaries
11 /// containing CTF, save them in XML corpus files and diff the
12 /// corpus files against reference XML corpus files.
13 
14 #include <cstdlib>
15 #include <fstream>
16 #include <iostream>
17 #include <memory>
18 #include <string>
19 #include <vector>
20 #include "abg-ctf-reader.h"
21 #include "test-read-common.h"
22 
23 using std::string;
24 using std::cerr;
25 using std::vector;
26 
27 using abigail::tests::read_common::InOutSpec;
28 using abigail::tests::read_common::test_task;
29 using abigail::tests::read_common::display_usage;
30 using abigail::tests::read_common::options;
31 
32 using abigail::xml_writer::SEQUENCE_TYPE_ID_STYLE;
33 using abigail::xml_writer::HASH_TYPE_ID_STYLE;
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-ctf/test0",
42     "",
43     "",
44     SEQUENCE_TYPE_ID_STYLE,
45     "data/test-read-ctf/test0.abi",
46     "output/test-read-ctf/test0.abi",
47     "--ctf"
48   },
49   {
50     "data/test-read-ctf/test0",
51     "",
52     "",
53     HASH_TYPE_ID_STYLE,
54     "data/test-read-ctf/test0.hash.abi",
55     "output/test-read-ctf/test0.hash.abi",
56     "--ctf"
57   },
58   {
59     "data/test-read-ctf/test1.so",
60     "",
61     "",
62     SEQUENCE_TYPE_ID_STYLE,
63     "data/test-read-ctf/test1.so.abi",
64     "output/test-read-ctf/test1.so.abi",
65     "--ctf"
66   },
67   {
68     "data/test-read-ctf/test1.so",
69     "",
70     "",
71     HASH_TYPE_ID_STYLE,
72     "data/test-read-ctf/test1.so.hash.abi",
73     "output/test-read-ctf/test1.so.hash.abi",
74     "--ctf"
75   },
76   {
77     "data/test-read-ctf/test2.so",
78     "",
79     "",
80     SEQUENCE_TYPE_ID_STYLE,
81     "data/test-read-ctf/test2.so.abi",
82     "output/test-read-ctf/test2.so.abi",
83     "--ctf"
84   },
85   {
86     "data/test-read-ctf/test2.so",
87     "",
88     "",
89     HASH_TYPE_ID_STYLE,
90     "data/test-read-ctf/test2.so.hash.abi",
91     "output/test-read-ctf/test2.so.hash.abi",
92     "--ctf"
93   },
94   {
95     "data/test-read-common/test3.so",
96     "",
97     "",
98     SEQUENCE_TYPE_ID_STYLE,
99     "data/test-read-ctf/test3.so.abi",
100     "output/test-read-ctf/test3.so.abi",
101     "--ctf"
102   },
103   {
104     "data/test-read-common/test3.so",
105     "",
106     "",
107     HASH_TYPE_ID_STYLE,
108     "data/test-read-ctf/test3.so.hash.abi",
109     "output/test-read-ctf/test3.so.hash.abi",
110     "--ctf"
111   },
112   {
113     "data/test-read-ctf/test-enum-many.o",
114     "",
115     "",
116     HASH_TYPE_ID_STYLE,
117     "data/test-read-ctf/test-enum-many.o.hash.abi",
118     "output/test-read-ctf/test-enum-many.o.hash.abi",
119     "--ctf"
120   },
121   {
122     "data/test-read-ctf/test-ambiguous-struct-A.o",
123     "",
124     "",
125     HASH_TYPE_ID_STYLE,
126     "data/test-read-ctf/test-ambiguous-struct-A.o.hash.abi",
127     "output/test-read-ctf/test-ambiguous-struct-A.o.hash.abi",
128     "--ctf"
129   },
130   {
131     "data/test-read-ctf/test-ambiguous-struct-B.o",
132     "",
133     "",
134     HASH_TYPE_ID_STYLE,
135     "data/test-read-ctf/test-ambiguous-struct-B.o.hash.abi",
136     "output/test-read-ctf/test-ambiguous-struct-B.o.hash.abi",
137     "--ctf"
138   },
139   {
140     "data/test-read-ctf/test-conflicting-type-syms-a.o",
141     "",
142     "",
143     HASH_TYPE_ID_STYLE,
144     "data/test-read-ctf/test-conflicting-type-syms-a.o.hash.abi",
145     "output/test-read-ctf/test-conflicting-type-syms-a.o.hash.abi",
146     "--ctf"
147   },
148   {
149     "data/test-read-ctf/test-conflicting-type-syms-b.o",
150     "",
151     "",
152     HASH_TYPE_ID_STYLE,
153     "data/test-read-ctf/test-conflicting-type-syms-b.o.hash.abi",
154     "output/test-read-ctf/test-conflicting-type-syms-b.o.hash.abi",
155     "--ctf"
156   },
157   {
158     "data/test-read-common/test4.so",
159     "",
160     "",
161     SEQUENCE_TYPE_ID_STYLE,
162     "data/test-read-ctf/test4.so.abi",
163     "output/test-read-ctf/test4.so.abi",
164     "--ctf"
165   },
166   {
167     "data/test-read-common/test4.so",
168     "",
169     "",
170     HASH_TYPE_ID_STYLE,
171     "data/test-read-ctf/test4.so.hash.abi",
172     "output/test-read-ctf/test4.so.hash.abi",
173     "--ctf"
174   },
175   {
176     "data/test-read-ctf/test5.o",
177     "",
178     "",
179     SEQUENCE_TYPE_ID_STYLE,
180     "data/test-read-ctf/test5.o.abi",
181     "output/test-read-ctf/test5.o.abi",
182     "--ctf"
183   },
184   {
185     "data/test-read-ctf/test7.o",
186     "",
187     "",
188     SEQUENCE_TYPE_ID_STYLE,
189     "data/test-read-ctf/test7.o.abi",
190     "output/test-read-ctf/test7.o.abi",
191     "--ctf"
192   },
193   {
194     "data/test-read-ctf/test8.o",
195     "",
196     "",
197     SEQUENCE_TYPE_ID_STYLE,
198     "data/test-read-ctf/test8.o.abi",
199     "output/test-read-ctf/test8.o.abi",
200     "--ctf"
201   },
202   {
203     "data/test-read-ctf/test9.o",
204     "",
205     "",
206     SEQUENCE_TYPE_ID_STYLE,
207     "data/test-read-ctf/test9.o.abi",
208     "output/test-read-ctf/test9.o.abi",
209     "--ctf"
210   },
211   {
212     "data/test-read-ctf/test-enum.o",
213     "",
214     "",
215     SEQUENCE_TYPE_ID_STYLE,
216     "data/test-read-ctf/test-enum.o.abi",
217     "output/test-read-ctf/test-enum.o.abi",
218     "--ctf"
219   },
220   {
221     "data/test-read-ctf/test-enum-symbol.o",
222     "",
223     "",
224     HASH_TYPE_ID_STYLE,
225     "data/test-read-ctf/test-enum-symbol.o.hash.abi",
226     "output/test-read-ctf/test-enum-symbol.o.hash.abi",
227     "--ctf"
228   },
229   {
230     "data/test-read-ctf/test-dynamic-array.o",
231     "",
232     "",
233     SEQUENCE_TYPE_ID_STYLE,
234     "data/test-read-ctf/test-dynamic-array.o.abi",
235     "output/test-read-ctf/test-dynamic-array.o.abi",
236     "--ctf"
237   },
238   {
239     "data/test-read-ctf/test-anonymous-fields.o",
240     "",
241     "",
242     SEQUENCE_TYPE_ID_STYLE,
243     "data/test-read-ctf/test-anonymous-fields.o.abi",
244     "output/test-read-ctf/test-anonymous-fields.o.abi",
245     "--ctf"
246   },
247   {
248     "data/test-read-common/PR27700/test-PR27700.o",
249     "",
250     "data/test-read-common/PR27700/pub-incdir",
251     HASH_TYPE_ID_STYLE,
252     "data/test-read-ctf/PR27700/test-PR27700.abi",
253     "output/test-read-ctf/PR27700/test-PR27700.abi",
254     "--ctf"
255   },
256   {
257     "data/test-read-ctf/test-callback.o",
258     "",
259     "",
260     SEQUENCE_TYPE_ID_STYLE,
261     "data/test-read-ctf/test-callback.abi",
262     "output/test-read-ctf/test-callback.abi",
263     "--ctf"
264   },
265   {
266     "data/test-read-ctf/test-array-of-pointers.o",
267     "",
268     "",
269     SEQUENCE_TYPE_ID_STYLE,
270     "data/test-read-ctf/test-array-of-pointers.abi",
271     "output/test-read-ctf/test-array-of-pointers.abi",
272     "--ctf"
273   },
274   {
275     "data/test-read-ctf/test-functions-declaration.o",
276     "",
277     "",
278     SEQUENCE_TYPE_ID_STYLE,
279     "data/test-read-ctf/test-functions-declaration.abi",
280     "output/test-read-ctf/test-functions-declaration.abi",
281     "--ctf"
282   },
283   {
284     "data/test-read-ctf/test-forward-type-decl.o",
285     "",
286     "",
287     SEQUENCE_TYPE_ID_STYLE,
288     "data/test-read-ctf/test-forward-type-decl.abi",
289     "output/test-read-ctf/test-forward-type-decl.abi",
290     "--ctf"
291   },
292   {
293     "data/test-read-ctf/test-list-struct.o",
294     "",
295     "",
296     SEQUENCE_TYPE_ID_STYLE,
297     "data/test-read-ctf/test-list-struct.abi",
298     "output/test-read-ctf/test-list-struct.abi",
299     "--ctf"
300   },
301   {
302     "data/test-read-common/test-PR26568-1.o",
303     "",
304     "",
305     SEQUENCE_TYPE_ID_STYLE,
306     "data/test-read-ctf/test-PR26568-1.o.abi",
307     "output/test-read-ctf/test-PR26568-1.o.abi",
308     "--ctf"
309   },
310   {
311     "data/test-read-common/test-PR26568-2.o",
312     "",
313     "",
314     SEQUENCE_TYPE_ID_STYLE,
315     "data/test-read-ctf/test-PR26568-2.o.abi",
316     "output/test-read-ctf/test-PR26568-2.o.abi",
317     "--ctf"
318   },
319   {
320     "data/test-read-ctf/test-callback2.o",
321     "",
322     "",
323     SEQUENCE_TYPE_ID_STYLE,
324     "data/test-read-ctf/test-callback2.abi",
325     "output/test-read-ctf/test-callback2.abi",
326     "--ctf"
327   },
328   // out-of-tree kernel module.
329   {
330     "data/test-read-ctf/test-linux-module.ko",
331     "",
332     "",
333     SEQUENCE_TYPE_ID_STYLE,
334     "data/test-read-ctf/test-linux-module.abi",
335     "output/test-read-ctf/test-linux-module.abi",
336     "--ctf"
337   },
338   // CTF fallback feature.
339   {
340     "data/test-read-ctf/test-fallback.o",
341     "",
342     "",
343     SEQUENCE_TYPE_ID_STYLE,
344     "data/test-read-ctf/test-fallback.abi",
345     "output/test-read-ctf/test-fallback.abi",
346     NULL,
347   },
348   {
349     "data/test-read-ctf/test-bitfield.o",
350     "",
351     "",
352     SEQUENCE_TYPE_ID_STYLE,
353     "data/test-read-ctf/test-bitfield.abi",
354     "output/test-read-ctf/test-bitfield.abi",
355     "--ctf",
356   },
357   {
358     "data/test-read-ctf/test-bitfield-enum.o",
359     "",
360     "",
361     SEQUENCE_TYPE_ID_STYLE,
362     "data/test-read-ctf/test-bitfield-enum.abi",
363     "output/test-read-ctf/test-bitfield-enum.abi",
364     "--ctf",
365   },
366   {
367     "data/test-read-ctf/test-const-array.o",
368     "",
369     "",
370     SEQUENCE_TYPE_ID_STYLE,
371     "data/test-read-ctf/test-const-array.abi",
372     "output/test-read-ctf/test-const-array.abi",
373     "--ctf",
374   },
375   {
376     "data/test-read-ctf/test-array-mdimension.o",
377     "",
378     "",
379     SEQUENCE_TYPE_ID_STYLE,
380     "data/test-read-ctf/test-array-mdimension.abi",
381     "output/test-read-ctf/test-array-mdimension.abi",
382     "--ctf",
383   },
384   {
385     "data/test-read-ctf/test-array-size.o",
386     "",
387     "",
388     SEQUENCE_TYPE_ID_STYLE,
389     "data/test-read-ctf/test-array-size.abi",
390     "output/test-read-ctf/test-array-size.abi",
391     "--ctf",
392   },
393   // This should be the last entry.
394   {NULL, NULL, NULL, SEQUENCE_TYPE_ID_STYLE, NULL, NULL, NULL}
395 };
396 
397 /// Task specialization to perform CTF tests.
398 struct test_task_ctf : public test_task
399 {
400   test_task_ctf(const InOutSpec &s,
401                 string& a_out_abi_base,
402                 string& a_in_elf_base,
403                 string& a_in_abi_base);
404   virtual void
405   perform();
406 
407   virtual
~test_task_ctftest_task_ctf408   ~test_task_ctf()
409   {}
410 }; // end struct test_task_ctf
411 
412 /// Constructor.
413 ///
414 /// Task to be executed for each CTF test entry in @ref
415 /// abigail::tests::read_common::InOutSpec.
416 /// @param InOutSpec the array containing set of tests.
417 ///
418 /// @param a_out_abi_base the output base directory for abixml files.
419 ///
420 /// @param a_in_elf_base the input base directory for object files.
421 ///
422 /// @param a_in_elf_base the input base directory for expected
423 /// abixml files.
test_task_ctf(const InOutSpec & s,string & a_out_abi_base,string & a_in_elf_base,string & a_in_abi_base)424 test_task_ctf::test_task_ctf(const InOutSpec &s,
425                              string& a_out_abi_base,
426                              string& a_in_elf_base,
427                              string& a_in_abi_base)
428         : test_task(s, a_out_abi_base, a_in_elf_base, a_in_abi_base)
429   {}
430 
431 /// The thread function to execute each CTF test entry in @ref
432 /// abigail::tests::read_common::InOutSpec.
433 ///
434 /// This reads the corpus into memory, saves it to disk, loads it
435 /// again and compares the new in-memory representation against the
436 void
perform()437 test_task_ctf::perform()
438 {
439   abigail::ir::environment env;
440 
441   set_in_elf_path();
442   set_in_suppr_spec_path();
443 
444   abigail::fe_iface::status status =
445     abigail::fe_iface::STATUS_UNKNOWN;
446   vector<char**> di_roots;
447   ABG_ASSERT(abigail::tools_utils::file_exists(in_elf_path));
448 
449   abigail::elf_based_reader_sptr rdr = ctf::create_reader(in_elf_path,
450 							  di_roots, env);
451   ABG_ASSERT(rdr);
452 
453   corpus_sptr corp = rdr->read_corpus(status);
454 
455   // if there is no output and no input, assume that we do not care about the
456   // actual read result, just that it succeeded.
457   if (!spec.in_abi_path && !spec.out_abi_path)
458     {
459         // Phew! we made it here and we did not crash! yay!
460         return;
461     }
462   if (!corp)
463     {
464         error_message = string("failed to read ") + in_elf_path  + "\n";
465         is_ok = false;
466         return;
467     }
468   corp->set_path(spec.in_elf_path);
469   // Do not take architecture names in comparison so that these
470   // test input binaries can come from whatever arch the
471   // programmer likes.
472   corp->set_architecture_name("");
473 
474   if (!(is_ok = set_out_abi_path()))
475       return;
476 
477   if (!(is_ok = serialize_corpus(out_abi_path, corp)))
478        return;
479 
480   if (!(is_ok = run_abidw()))
481     return;
482 
483   if (!(is_ok = run_diff()))
484       return;
485 }
486 
487 /// Create a new CTF instance for task to be execute by the testsuite.
488 ///
489 /// @param s the @ref abigail::tests::read_common::InOutSpec
490 /// tests container.
491 ///
492 /// @param a_out_abi_base the output base directory for abixml files.
493 ///
494 /// @param a_in_elf_base the input base directory for object files.
495 ///
496 /// @param a_in_abi_base the input base directory for abixml files.
497 ///
498 /// @return abigail::tests::read_common::test_task instance.
499 static test_task*
new_task(const InOutSpec * s,string & a_out_abi_base,string & a_in_elf_base,string & a_in_abi_base)500 new_task(const InOutSpec* s, string& a_out_abi_base,
501          string& a_in_elf_base, string& a_in_abi_base)
502 {
503   return new test_task_ctf(*s, a_out_abi_base,
504                            a_in_elf_base, a_in_abi_base);
505 }
506 
507 int
main(int argc,char * argv[])508 main(int argc, char *argv[])
509 {
510   options opts;
511   if (!parse_command_line(argc, argv, opts))
512     {
513       if (!opts.wrong_option.empty())
514         emit_prefix(argv[0], cerr)
515           << "unrecognized option: " << opts.wrong_option << "\n";
516       display_usage(argv[0], cerr);
517       return 1;
518     }
519 
520   // compute number of tests to be executed.
521   const size_t num_tests = sizeof(in_out_specs) / sizeof(InOutSpec) - 1;
522 
523   return run_tests(num_tests, in_out_specs, opts, new_task);
524 }
525