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
9 ///
10 /// This program runs a diff between input dwarf files and compares
11 /// the resulting report with a reference report. If the resulting
12 /// report is different from the reference report, the test has
13 /// failed. Note that the comparison is done using the libabigail
14 /// library directly.
15 ///
16 /// The set of input files and reference reports to consider should be
17 /// present in the source distribution.
18
19 #include <string>
20 #include <fstream>
21 #include <iostream>
22 #include <cstdlib>
23 #include "abg-tools-utils.h"
24 #include "test-utils.h"
25 #include "abg-dwarf-reader.h"
26 #include "abg-comparison.h"
27
28 using std::string;
29 using std::ofstream;
30 using std::cerr;
31
32 /// This is an aggregate that specifies where a test shall get its
33 /// input from and where it shall write its ouput to.
34 struct InOutSpec
35 {
36 const char* in_elfv0_path;
37 const char* in_elfv1_path;
38 const char* in_report_path;
39 const char* out_report_path;
40 };// end struct InOutSpec
41
42 InOutSpec in_out_specs[] =
43 {
44 {
45 "data/test-diff-dwarf/test0-v0.o",
46 "data/test-diff-dwarf/test0-v1.o",
47 "data/test-diff-dwarf/test0-report.txt",
48 "output/test-diff-dwarf/test0-report.txt"
49 },
50 {
51 "data/test-diff-dwarf/test1-v0.o",
52 "data/test-diff-dwarf/test1-v1.o",
53 "data/test-diff-dwarf/test1-report.txt",
54 "output/test-diff-dwarf/test1-report.txt"
55 },
56 {
57 "data/test-diff-dwarf/test2-v0.o",
58 "data/test-diff-dwarf/test2-v1.o",
59 "data/test-diff-dwarf/test2-report.txt",
60 "output/test-diff-dwarf/test2-report.txt"
61 },
62 {
63 "data/test-diff-dwarf/test3-v0.o",
64 "data/test-diff-dwarf/test3-v1.o",
65 "data/test-diff-dwarf/test3-report.txt",
66 "output/test-diff-dwarf/test3-report.txt"
67 },
68 {
69 "data/test-diff-dwarf/test3-v0.o",
70 "data/test-diff-dwarf/test3-v1.o",
71 "data/test-diff-dwarf/test3-report.txt",
72 "output/test-diff-dwarf/test3-report.txt"
73 },
74 {
75 "data/test-diff-dwarf/test4-v0.o",
76 "data/test-diff-dwarf/test4-v1.o",
77 "data/test-diff-dwarf/test4-report.txt",
78 "output/test-diff-dwarf/test4-report.txt"
79 },
80 {
81 "data/test-diff-dwarf/test5-v0.o",
82 "data/test-diff-dwarf/test5-v1.o",
83 "data/test-diff-dwarf/test5-report.txt",
84 "output/test-diff-dwarf/test5-report.txt"
85 },
86 {
87 "data/test-diff-dwarf/test6-v0.o",
88 "data/test-diff-dwarf/test6-v1.o",
89 "data/test-diff-dwarf/test6-report.txt",
90 "output/test-diff-dwarf/test6-report.txt"
91 },
92 {
93 "data/test-diff-dwarf/test7-v0.o",
94 "data/test-diff-dwarf/test7-v1.o",
95 "data/test-diff-dwarf/test7-report.txt",
96 "output/test-diff-dwarf/test7-report.txt"
97 },
98 {
99 "data/test-diff-dwarf/test8-v0.o",
100 "data/test-diff-dwarf/test8-v1.o",
101 "data/test-diff-dwarf/test8-report.txt",
102 "output/test-diff-dwarf/test8-report.txt"
103 },
104 {
105 "data/test-diff-dwarf/libtest9-v0.so",
106 "data/test-diff-dwarf/libtest9-v1.so",
107 "data/test-diff-dwarf/test9-report.txt",
108 "output/test-diff-dwarf/test9-report.txt"
109 },
110 {
111 "data/test-diff-dwarf/test10-v0.o",
112 "data/test-diff-dwarf/test10-v1.o",
113 "data/test-diff-dwarf/test10-report.txt",
114 "output/test-diff-dwarf/test10-report.txt"
115 },
116 {
117 "data/test-diff-dwarf/test11-v0.o",
118 "data/test-diff-dwarf/test11-v1.o",
119 "data/test-diff-dwarf/test11-report.txt",
120 "output/test-diff-dwarf/test11-report.txt"
121 },
122 {
123 "data/test-diff-dwarf/libtest12-v0.so",
124 "data/test-diff-dwarf/libtest12-v1.so",
125 "data/test-diff-dwarf/test12-report.txt",
126 "output/test-diff-dwarf/test12-report.txt"
127 },
128 {
129 "data/test-diff-dwarf/test13-v0.o",
130 "data/test-diff-dwarf/test13-v1.o",
131 "data/test-diff-dwarf/test13-report.txt",
132 "output/test-diff-dwarf/test13-report.txt"
133 },
134 {
135 "data/test-diff-dwarf/test14-inline-v0.o",
136 "data/test-diff-dwarf/test14-inline-v1.o",
137 "data/test-diff-dwarf/test14-inline-report.txt",
138 "output/test-diff-dwarf/test14-inline-report.txt"
139 },
140 {
141 "data/test-diff-dwarf/test15-enum-v0.o",
142 "data/test-diff-dwarf/test15-enum-v1.o",
143 "data/test-diff-dwarf/test15-enum-report.txt",
144 "output/test-diff-dwarf/test15-enum-report.txt"
145 },
146 {
147 "data/test-diff-dwarf/test16-syms-only-v0.o",
148 "data/test-diff-dwarf/test16-syms-only-v1.o",
149 "data/test-diff-dwarf/test16-syms-only-report.txt",
150 "output/test-diff-dwarf/test16-syms-only-report.txt"
151 },
152 {
153 "data/test-diff-dwarf/test17-non-refed-syms-v0.o",
154 "data/test-diff-dwarf/test17-non-refed-syms-v1.o",
155 "data/test-diff-dwarf/test17-non-refed-syms-report-0.txt",
156 "output/test-diff-dwarf/test17-non-refed-syms-report-0.txt"
157 },
158 {
159 "data/test-diff-dwarf/libtest18-alias-sym-v0.so",
160 "data/test-diff-dwarf/libtest18-alias-sym-v1.so",
161 "data/test-diff-dwarf/test18-alias-sym-report-0.txt",
162 "output/test-diff-dwarf/test18-alias-sym-report-0.txt"
163 },
164 {
165 "data/test-diff-dwarf/libtest19-soname-v0.so",
166 "data/test-diff-dwarf/libtest19-soname-v1.so",
167 "data/test-diff-dwarf/test19-soname-report-0.txt",
168 "output/test-diff-dwarf/test19-soname-report-0.txt"
169 },
170 {
171 "data/test-diff-dwarf/libtest20-add-fn-parm-v0.so",
172 "data/test-diff-dwarf/libtest20-add-fn-parm-v1.so",
173 "data/test-diff-dwarf/test20-add-fn-parm-report-0.txt",
174 "output/test-diff-dwarf/test20-add-fn-parm-report-0.txt"
175 },
176 {
177 "data/test-diff-dwarf/libtest21-redundant-fn-v0.so",
178 "data/test-diff-dwarf/libtest21-redundant-fn-v1.so",
179 "data/test-diff-dwarf/test21-redundant-fn-report-0.txt",
180 "output/test-diff-dwarf/test21-redundant-fn-report-0.txt"
181 },
182 {
183 "data/test-diff-dwarf/libtest22-changed-parm-c-v0.so",
184 "data/test-diff-dwarf/libtest22-changed-parm-c-v1.so",
185 "data/test-diff-dwarf/test22-changed-parm-c-report-0.txt",
186 "output/test-diff-dwarf/test22-changed-parm-c-report-0.txt"
187 },
188 {
189 "data/test-diff-dwarf/libtest-23-diff-arch-v0-32.so",
190 "data/test-diff-dwarf/libtest-23-diff-arch-v0-64.so",
191 "data/test-diff-dwarf/test-23-diff-arch-report-0.txt",
192 "output/test-diff-dwarf/test-23-diff-arch-report-0.txt"
193 },
194 {
195 "data/test-diff-dwarf/libtest24-added-fn-parms-v0.so",
196 "data/test-diff-dwarf/libtest24-added-fn-parms-v1.so",
197 "data/test-diff-dwarf/test24-added-fn-parms-report-0.txt",
198 "output/test-diff-dwarf/test24-added-fn-parms-report-0.txt"
199 },
200 {
201 "data/test-diff-dwarf/libtest25-removed-fn-parms-v0.so",
202 "data/test-diff-dwarf/libtest25-removed-fn-parms-v1.so",
203 "data/test-diff-dwarf/test25-removed-fn-parms-report-0.txt",
204 "output/test-diff-dwarf/test25-removed-fn-parms-report-0.txt"
205 },
206 {
207 "data/test-diff-dwarf/libtest26-added-parms-before-variadic-v0.so",
208 "data/test-diff-dwarf/libtest26-added-parms-before-variadic-v1.so",
209 "data/test-diff-dwarf/test26-added-parms-before-variadic-report.txt",
210 "output/test-diff-dwarf/test26-added-parms-before-variadic-report.txt"
211 },
212 {
213 "data/test-diff-dwarf/test27-local-base-diff-v0.o",
214 "data/test-diff-dwarf/test27-local-base-diff-v1.o",
215 "data/test-diff-dwarf/test27-local-base-diff-report.txt",
216 "output/test-diff-dwarf/test27-local-base-diff-report.txt"
217 },
218 {
219 "data/test-diff-dwarf/test28-vtable-changes-v0.o",
220 "data/test-diff-dwarf/test28-vtable-changes-v1.o",
221 "data/test-diff-dwarf/test28-vtable-changes-report-0.txt",
222 "output/test-diff-dwarf/test28-vtable-changes-report-0.txt"
223 },
224 {
225 "data/test-diff-dwarf/test29-vtable-changes-v0.o",
226 "data/test-diff-dwarf/test29-vtable-changes-v1.o",
227 "data/test-diff-dwarf/test29-vtable-changes-report-0.txt",
228 "output/test-diff-dwarf/test29-vtable-changes-report-0.txt"
229 },
230 {
231 "data/test-diff-dwarf/test30-vtable-changes-v0.o",
232 "data/test-diff-dwarf/test30-vtable-changes-v1.o",
233 "data/test-diff-dwarf/test30-vtable-changes-report-0.txt",
234 "output/test-diff-dwarf/test30-vtable-changes-report-0.txt"
235 },
236 {
237 "data/test-diff-dwarf/test31-vtable-changes-v0.o",
238 "data/test-diff-dwarf/test31-vtable-changes-v1.o",
239 "data/test-diff-dwarf/test31-vtable-changes-report-0.txt",
240 "output/test-diff-dwarf/test31-vtable-changes-report-0.txt"
241 },
242 {
243 "data/test-diff-dwarf/test32-fnptr-changes-v0.o",
244 "data/test-diff-dwarf/test32-fnptr-changes-v1.o",
245 "data/test-diff-dwarf/test32-fnptr-changes-report-0.txt",
246 "output/test-diff-dwarf/test32-fnptr-changes-report-0.txt"
247 },
248 {
249 "data/test-diff-dwarf/test33-fnref-changes-v0.o",
250 "data/test-diff-dwarf/test33-fnref-changes-v1.o",
251 "data/test-diff-dwarf/test33-fnref-changes-report-0.txt",
252 "output/test-diff-dwarf/test33-fnref-changes-report-0.txt"
253 },
254 {
255 "data/test-diff-dwarf/test34-pr19173-libfoo.so",
256 "data/test-diff-dwarf/test34-pr19173-libfoo2.so",
257 "data/test-diff-dwarf/test34-pr19173-libfoo-report-0.txt",
258 "output/test-diff-dwarf/test34-pr19173-libfoo-report-0.txt"
259 },
260 {
261 "data/test-diff-dwarf/test35-pr19173-libfoo-long-gcc.so",
262 "data/test-diff-dwarf/test35-pr19173-libfoo-long-gcc2.so",
263 "data/test-diff-dwarf/test35-pr19173-libfoo-long-gcc-report-0.txt",
264 "output/test-diff-dwarf/test35-pr19173-libfoo-long-gcc-report-0.txt"
265 },
266 {
267 "data/test-diff-dwarf/test35-pr19173-libfoo-long-clang.so",
268 "data/test-diff-dwarf/test35-pr19173-libfoo-long-clang2.so",
269 "data/test-diff-dwarf/test35-pr19173-libfoo-long-clang-report-0.txt",
270 "output/test-diff-dwarf/test35-pr19173-libfoo-long-clang-report-0.txt"
271 },
272 {
273 "data/test-diff-dwarf/libtest36-ppc64-aliases-v0.so",
274 "data/test-diff-dwarf/libtest36-ppc64-aliases-v1.so",
275 "data/test-diff-dwarf/test36-ppc64-aliases-report-0.txt",
276 "output/test-diff-dwarf/test36-ppc64-aliases-report-0.txt"
277 },
278 {
279 "data/test-diff-dwarf/libtest37-union-v0.so",
280 "data/test-diff-dwarf/libtest37-union-v1.so",
281 "data/test-diff-dwarf/test37-union-report-0.txt",
282 "output/test-diff-dwarf/test37-union-report-0.txt"
283 },
284 {
285 "data/test-diff-dwarf/libtest38-union-v0.so",
286 "data/test-diff-dwarf/libtest38-union-v1.so",
287 "data/test-diff-dwarf/test38-union-report-0.txt",
288 "output/test-diff-dwarf/test38-union-report-0.txt"
289 },
290 {
291 "data/test-diff-dwarf/libtest39-union-v0.so",
292 "data/test-diff-dwarf/libtest39-union-v1.so",
293 "data/test-diff-dwarf/test39-union-report-0.txt",
294 "output/test-diff-dwarf/test39-union-report-0.txt"
295 },
296 {
297 "data/test-diff-dwarf/libtest40-v0.so",
298 "data/test-diff-dwarf/libtest40-v1.so",
299 "data/test-diff-dwarf/test40-report-0.txt",
300 "output/test-diff-dwarf/test40-report-0.txt"
301 },
302 {
303 "data/test-diff-dwarf/libtest41-PR20476-hidden-old.so",
304 "data/test-diff-dwarf/libtest41-PR20476-hidden-new.so",
305 "data/test-diff-dwarf/test41-PR20476-hidden-report-0.txt",
306 "output/test-diff-dwarf/test41-PR20476-hidden-report-0.txt"
307 },
308 {
309 "data/test-diff-dwarf/test42-PR21296-libgcc.so",
310 "data/test-diff-dwarf/test42-PR21296-libclang.so",
311 "data/test-diff-dwarf/test42-PR21296-clanggcc-report0.txt",
312 "output/test-diff-dwarf/test42-PR21296-clanggcc-report0.txt"
313 },
314 {
315 "data/test-diff-dwarf/libtest43-PR22913-v0.so",
316 "data/test-diff-dwarf/libtest43-PR22913-v1.so",
317 "data/test-diff-dwarf/test43-PR22913-report-0.txt",
318 "output/test-diff-dwarf/test43-PR22913-report-0.txt"
319 },
320 {
321 "data/test-diff-dwarf/test44-anon-struct-union-v0.o",
322 "data/test-diff-dwarf/test44-anon-struct-union-v1.o",
323 "data/test-diff-dwarf/test44-anon-struct-union-report-0.txt",
324 "output/test-diff-dwarf/test44-anon-struct-union-report-0.txt"
325 },
326 {
327 "data/test-diff-dwarf/test45-anon-dm-change-v0.o",
328 "data/test-diff-dwarf/test45-anon-dm-change-v1.o",
329 "data/test-diff-dwarf/test45-anon-dm-change-report-0.txt",
330 "output/test-diff-dwarf/test45-anon-dm-change-report-0.txt"
331 },
332 #ifdef HAVE_DW_LANG_Rust_enumerator
333 {
334 "data/test-diff-dwarf/test46-rust-libone.so",
335 "data/test-diff-dwarf/test46-rust-libtwo.so",
336 "data/test-diff-dwarf/test46-rust-report-0.txt",
337 "output/test-diff-dwarf/test46-rust-report-0.txt"
338 },
339 #endif
340 {
341 "data/test-diff-dwarf/PR25058-liblttng-ctl2.10.so",
342 "data/test-diff-dwarf/PR25058-liblttng-ctl.so",
343 "data/test-diff-dwarf/PR25058-liblttng-ctl-report-1.txt",
344 "output/test-diff-dwarf/PR25058-liblttng-ctl-report-1.txt"
345 },
346 // This should be the last entry
347 {NULL, NULL, NULL, NULL}
348 };
349
350 int
main()351 main()
352 {
353 using abigail::tests::get_src_dir;
354 using abigail::tests::get_build_dir;
355 using abigail::tools_utils::ensure_parent_dir_created;
356 using abigail::comparison::compute_diff;
357 using abigail::comparison::corpus_diff_sptr;
358 using abigail::ir::environment;
359 using abigail::ir::environment_sptr;
360 using abigail::comparison::diff_context_sptr;
361 using abigail::comparison::diff_context;
362
363 using namespace abigail;
364
365 bool is_ok = true;
366 string in_elfv0_path, in_elfv1_path,
367 ref_diff_report_path, out_diff_report_path;
368
369 for (InOutSpec* s = in_out_specs; s->in_elfv0_path; ++s)
370 {
371 in_elfv0_path = string(get_src_dir()) + "/tests/" + s->in_elfv0_path;
372 in_elfv1_path = string(get_src_dir()) + "/tests/" + s->in_elfv1_path;
373 out_diff_report_path =
374 string(get_build_dir()) + "/tests/" + s->out_report_path;
375
376 if (!ensure_parent_dir_created(out_diff_report_path))
377 {
378 cerr << "could not create parent directory for "
379 << out_diff_report_path;
380 is_ok = false;
381 continue;
382 }
383
384 abigail::fe_iface::status status =
385 abigail::fe_iface::STATUS_UNKNOWN;
386
387 environment env;
388 std::vector<char**> di_roots;
389 abigail::corpus_sptr corp0 =
390 dwarf::read_corpus_from_elf(in_elfv0_path,
391 /*debug_info_root_path=*/di_roots,
392 env, /*load_all_types=*/false, status);
393
394 abigail::corpus_sptr corp1 =
395 dwarf::read_corpus_from_elf(in_elfv1_path,
396 /*debug_info_root_path=*/di_roots,
397 env, /*load_all_types=*/false, status);
398
399 if (!corp0)
400 {
401 cerr << "failed to read " << in_elfv0_path << "\n";
402 is_ok = false;
403 continue;
404 }
405
406 if (!corp1)
407 {
408 cerr << "failed to read " << in_elfv1_path << "\n";
409 is_ok = false;
410 continue;
411 }
412
413 corp0->set_path(s->in_elfv0_path);
414 corp1->set_path(s->in_elfv1_path);
415
416 diff_context_sptr ctxt(new diff_context);
417 ctxt->show_locs(false);
418
419 corpus_diff_sptr d = compute_diff(corp0, corp1, ctxt);
420 if (!d)
421 {
422 cerr << "failed to compute diff\n";
423 is_ok = false;
424 continue;
425 }
426
427 ref_diff_report_path =
428 string(get_src_dir()) + "/tests/" + s->in_report_path;
429 out_diff_report_path =
430 string(get_build_dir()) + "/tests/" + s->out_report_path;
431
432 ofstream of(out_diff_report_path.c_str(), std::ios_base::trunc);
433 if (!of.is_open())
434 {
435 cerr << "failed to read " << out_diff_report_path << "\n";
436 is_ok = false;
437 continue;
438 }
439
440 if (d->has_changes())
441 d->report(of);
442 of.close();
443
444 string cmd =
445 "diff -u " + ref_diff_report_path + " " + out_diff_report_path;
446 if (system(cmd.c_str()))
447 is_ok = false;
448 }
449
450 return !is_ok;
451 }
452