1ABIDIFF(1) Libabigail ABIDIFF(1)
2
3
4
6 abidiff - compare ABIs of ELF files
7
8 abidiff compares the Application Binary Interfaces (ABI) of two shared
9 libraries in ELF format. It emits a meaningful report describing the
10 differences between the two ABIs.
11
12 This tool can also compare the textual representations of the ABI of
13 two ELF binaries (as emitted by abidw) or an ELF binary against a tex‐
14 tual representation of another ELF binary.
15
16 For a comprehensive ABI change report that includes changes about func‐
17 tion and variable sub-types, the two input shared libraries must be ac‐
18 companied with their debug information in DWARF format. Otherwise,
19 only ELF symbols that were added or removed are reported.
20
22 abidiff [options] <first-shared-library> <second-shared-library>
23
25 abidiff loads two default suppression specifications files, merges
26 their content and use it to filter out ABI change reports that might be
27 considered as false positives to users.
28
29 • Default system-wide suppression specification file
30
31 It’s located by the optional environment variable LIBABIGAIL_DE‐
32 FAULT_SYSTEM_SUPPRESSION_FILE. If that environment variable is not
33 set, then abidiff tries to load the suppression file $libdir/libabi‐
34 gail/libabigail-default.abignore. If that file is not present, then
35 no default system-wide suppression specification file is loaded.
36
37 • Default user suppression specification file.
38
39 It’s located by the optional environment LIBABIGAIL_DEFAULT_USER_SUP‐
40 PRESSION_FILE. If that environment variable is not set, then abidiff
41 tries to load the suppression file $HOME/.abignore. If that file is
42 not present, then no default user suppression specification is
43 loaded.
44
46 • --help | -h
47
48 Display a short help about the command and exit.
49
50 • --debug
51
52 In this mode, error messages are emitted for types which fail type
53 canonicalization.
54
55 This is an optional ebugging and sanity check option. To enable
56 it the libabigail package needs to be configured with the –en‐
57 able-debug-self-comparison option.
58
59 • --version | -v
60
61 Display the version of the program and exit.
62
63 • --debug-info-dir1 | --d1 <di-path1>
64
65 For cases where the debug information for first-shared-library is
66 split out into a separate file, tells abidiff where to find that
67 separate debug information file.
68
69 Note that di-path must point to the root directory under which the
70 debug information is arranged in a tree-like manner. Under Red
71 Hat based systems, that directory is usually <root>/usr/lib/debug.
72
73 This option can be provided several times with different root di‐
74 rectories. In that case, abidiff will potentially look into all
75 those root directories to find the split debug info for
76 first-shared-library.
77
78 Note also that this option is not mandatory for split debug infor‐
79 mation installed by your system’s package manager because then
80 abidiff knows where to find it.
81
82 • --debug-info-dir2 | --d2 <di-path2>
83
84 Like --debug-info-dir1, this options tells abidiff where to find
85 the split debug information for the second-shared-library file.
86
87 This option can be provided several times with different root di‐
88 rectories. In that case, abidiff will potentially look into all
89 those root directories to find the split debug info for sec‐
90 ond-shared-library.
91
92 • --headers-dir1 | --hd1 <headers-directory-path-1>
93
94 Specifies where to find the public headers of the first shared li‐
95 brary (or binary in general) that the tool has to consider. The
96 tool will thus filter out ABI changes on types that are not de‐
97 fined in public headers.
98
99 Note that several public header directories can be specified for
100 the first shared library. In that case the --headers-dir1 option
101 should be present several times on the command line, like in the
102 following example:
103
104 $ abidiff --headers-dir1 /some/path \
105 --headers-dir1 /some/other/path \
106 binary-version-1 binary-version-2
107
108 • --header-file1 | --hf1 <header-file-path-1>
109
110 Specifies where to find one public header of the first shared li‐
111 brary that the tool has to consider. The tool will thus filter
112 out ABI changes on types that are not defined in public headers.
113
114 • --headers-dir2 | --hd2 <headers-directory-path-1>
115
116 Specifies where to find the public headers of the second shared
117 library that the tool has to consider. The tool will thus filter
118 out ABI changes on types that are not defined in public headers.
119
120 Note that several public header directories can be specified for
121 the second shared library. In that case the --headers-dir2 option
122 should be present several times like in the following example:
123
124 $ abidiff --headers-dir2 /some/path \
125 --headers-dir2 /some/other/path \
126 binary-version-1 binary-version-2
127
128 • --header-file2 | --hf2 <header-file-path-2>
129
130 Specifies where to find one public header of the second shared li‐
131 brary that the tool has to consider. The tool will thus filter
132 out ABI changes on types that are not defined in public headers.
133
134 • --no-linux-kernel-mode
135
136 Without this option, if abidiff detects that the binaries it is
137 looking at are Linux Kernel binaries (either vmlinux or modules)
138 then it only considers functions and variables which ELF symbols
139 are listed in the __ksymtab and __ksymtab_gpl sections.
140
141 With this option, abidiff considers the binary as a non-special
142 ELF binary. It thus considers functions and variables which are
143 defined and exported in the ELF sense.
144
145 • --kmi-whitelist | -kaw <path-to-whitelist>
146
147 When analyzing a Linux kernel binary, this option points to the
148 white list of names of ELF symbols of functions and variables
149 which ABI must be considered. That white list is called a “Kernel
150 Module Interface white list”. This is because for the Kernel, we
151 don’t talk about ABI; we rather talk about the interface between
152 the Kernel and its module. Hence the term KMI rather than ABI.
153
154 Any other function or variable which ELF symbol are not present in
155 that white list will not be considered by this tool.
156
157 If this option is not provided – thus if no white list is provided
158 – then the entire KMI, that is, the set of all publicly defined
159 and exported functions and global variables by the Linux Kernel
160 binaries, is considered.
161
162 • --drop-private-types
163
164 This option is to be used with the --headers-dir1, header-file1,
165 header-file2 and --headers-dir2 options. With this option, types
166 that are NOT defined in the headers are entirely dropped from the
167 internal representation build by Libabigail to represent the ABI.
168 They thus don’t have to be filtered out from the final ABI change
169 report because they are not even present in Libabigail’s represen‐
170 tation.
171
172 Without this option however, those private types are kept in the
173 internal representation and later filtered out from the report.
174
175 This options thus potentially makes Libabigail consume less mem‐
176 ory. It’s meant to be mainly used to optimize the memory consump‐
177 tion of the tool on binaries with a lot of publicly defined and
178 exported types.
179
180 • --stat
181
182 Rather than displaying the detailed ABI differences between
183 first-shared-library and second-shared-library, just display some
184 summary statistics about these differences.
185
186 • --symtabs
187
188 Only display the symbol tables of the first-shared-library and
189 second-shared-library.
190
191 • --deleted-fns
192
193 In the resulting report about the differences between
194 first-shared-library and second-shared-library, only display the
195 globally defined functions that got deleted from first-shared-li‐
196 brary.
197
198 • --changed-fns
199
200 In the resulting report about the differences between
201 first-shared-library and second-shared-library, only display the
202 changes in sub-types of the global functions defined in
203 first-shared-library.
204
205 • --added-fns
206
207 In the resulting report about the differences between
208 first-shared-library and second-shared-library, only display the
209 globally defined functions that were added to second-shared-li‐
210 brary.
211
212 • --deleted-vars
213
214 In the resulting report about the differences between
215 first-shared-library and second-shared-library, only display the
216 globally defined variables that were deleted from first-shared-li‐
217 brary.
218
219 • --changed-vars
220
221 In the resulting report about the differences between
222 first-shared-library and second-shared-library, only display the
223 changes in the sub-types of the global variables defined in
224 first-shared-library
225
226 • --added-vars
227
228 In the resulting report about the differences between
229 first-shared-library and second-shared-library, only display the
230 global variables that were added (defined) to second-shared-li‐
231 brary.
232
233 • --non-reachable-types|-t
234
235 Analyze and emit change reports for all the types of the binary,
236 including those that are not reachable from global functions and
237 variables.
238
239 This option might incur some serious performance degradation as
240 the number of types analyzed can be huge. However, if paired with
241 the --headers-dir{1,2} and/or header-file{1,2} options, the addi‐
242 tional non-reachable types analyzed are restricted to those de‐
243 fined in public headers files, thus hopefully making the perfor‐
244 mance hit acceptable.
245
246 Also, using this option alongside suppression specifications (by
247 also using the --suppressions option) might help keep the number
248 of analyzed types (and the potential performance degradation) in
249 control.
250
251 Note that without this option, only types that are reachable from
252 global functions and variables are analyzed, so the tool detects
253 and reports changes on these reachable types only.
254
255 • --no-added-syms
256
257 In the resulting report about the differences between
258 first-shared-library and second-shared-library, do not display
259 added functions or variables. Do not display added functions or
260 variables ELF symbols either. All other kinds of changes are dis‐
261 played unless they are explicitely forbidden by other options on
262 the command line.
263
264 • --no-linkage-name
265
266 In the resulting report, do not display the linkage names of the
267 added, removed, or changed functions or variables.
268
269 • --no-show-locs
270 Do not show information about where in the second shared library
271 the respective type was changed.
272
273 • --show-bytes
274
275 Show sizes and offsets in bytes, not bits. By default, sizes and
276 offsets are shown in bits.
277
278 • --show-bits
279
280 Show sizes and offsets in bits, not bytes. This option is acti‐
281 vated by default.
282
283 • --show-hex
284
285 Show sizes and offsets in hexadecimal base.
286
287 • --show-dec
288
289 Show sizes and offsets in decimal base. This option is activated
290 by default.
291
292 • --no-show-relative-offset-changes
293
294 Without this option, when the offset of a data member changes, the
295 change report not only mentions the older and newer offset, but it
296 also mentions by how many bits the data member changes. With this
297 option, the latter is not shown.
298
299 • --no-unreferenced-symbols
300
301 In the resulting report, do not display change information about
302 function and variable symbols that are not referenced by any debug
303 information. Note that for these symbols not referenced by any
304 debug information, the change information displayed is either
305 added or removed symbols.
306
307 • --no-default-suppression
308
309 Do not load the default suppression specification files.
310
311 • --suppressions | --suppr <path-to-suppressions>
312
313 Use a suppression specification file located at path-to-suppres‐
314 sions. Note that this option can appear multiple times on the
315 command line. In that case, all of the provided suppression spec‐
316 ification files are taken into account.
317
318 Please note that, by default, if this option is not provided, then
319 the default suppression specification files are loaded .
320
321 • --drop <regex>
322
323 When reading the first-shared-library and second-shared-library
324 ELF input files, drop the globally defined functions and variables
325 which name match the regular expression regex. As a result, no
326 change involving these functions or variables will be emitted in
327 the diff report.
328
329 • --drop-fn <regex>
330
331 When reading the first-shared-library and second-shared-library
332 ELF input files, drop the globally defined functions which name
333 match the regular expression regex. As a result, no change in‐
334 volving these functions will be emitted in the diff report.
335
336 • --drop-var <regex>
337
338 When reading the first-shared-library and second-shared-library
339 ELF input files, drop the globally defined variables matching a
340 the regular expression regex.
341
342 • --keep <regex>
343
344 When reading the first-shared-library and second-shared-library
345 ELF input files, keep the globally defined functions and variables
346 which names match the regular expression regex. All other func‐
347 tions and variables are dropped on the floor and will thus not ap‐
348 pear in the resulting diff report.
349
350 • --keep-fn <regex>
351
352 When reading the first-shared-library and second-shared-library
353 ELF input files, keep the globally defined functions which name
354 match the regular expression regex. All other functions are
355 dropped on the floor and will thus not appear in the resulting
356 diff report.
357
358 • --keep-var <regex>
359
360 When reading the first-shared-library and second-shared-library
361 ELF input files, keep the globally defined which names match the
362 regular expression regex. All other variables are dropped on the
363 floor and will thus not appear in the resulting diff report.
364
365 • --harmless
366
367 In the diff report, display only the harmless changes. By de‐
368 fault, the harmless changes are filtered out of the diff report
369 keep the clutter to a minimum and have a greater chance to spot
370 real ABI issues.
371
372 • --no-harmful
373
374 In the diff report, do not display the harmful changes. By de‐
375 fault, only the harmful changes are displayed in diff report.
376
377 • --redundant
378
379 In the diff report, do display redundant changes. A redundant
380 change is a change that has been displayed elsewhere in the re‐
381 port.
382
383 • --no-redundant
384
385 In the diff report, do NOT display redundant changes. A redundant
386 change is a change that has been displayed elsewhere in the re‐
387 port. This option is switched on by default.
388
389 • --no-architecture
390
391 Do not take architecture in account when comparing ABIs.
392
393 • --no-corpus-path
394
395 Do not emit the path attribute for the ABI corpus.
396
397 • --fail-no-debug-info
398
399 If no debug info was found, then this option makes the program to
400 fail. Otherwise, without this option, the program will attempt to
401 compare properties of the binaries that are not related to debug
402 info, like pure ELF properties.
403
404 • --leaf-changes-only|-l only show leaf changes, so don’t show im‐
405 pact analysis report. This option implies --redundant.
406
407 The typical output of abidiff when comparing two binaries looks
408 like this
409
410 $ abidiff libtest-v0.so libtest-v1.so
411 Functions changes summary: 0 Removed, 1 Changed, 0 Added function
412 Variables changes summary: 0 Removed, 0 Changed, 0 Added variable
413
414 1 function with some indirect sub-type change:
415
416 [C]'function void fn(C&)' at test-v1.cc:13:1 has some indirect sub-type changes:
417 parameter 1 of type 'C&' has sub-type changes:
418 in referenced type 'struct C' at test-v1.cc:7:1:
419 type size hasn't changed
420 1 data member change:
421 type of 'leaf* C::m0' changed:
422 in pointed to type 'struct leaf' at test-v1.cc:1:1:
423 type size changed from 32 to 64 bits
424 1 data member insertion:
425 'char leaf::m1', at offset 32 (in bits) at test-v1.cc:4:1
426
427 $
428
429 So in that example the report emits information about how the data
430 member insertion change of “struct leaf” is reachable from func‐
431 tion “void fn(C&)”. In other words, the report not only shows the
432 data member change on “struct leaf”, but it also shows the impact
433 of that change on the function “void fn(C&)”.
434
435 In abidiff parlance, the change on “struct leaf” is called a leaf
436 change. So the --leaf-changes-only --impacted-interfaces options
437 show, well, only the leaf change. And it goes like this:
438
439 $ abidiff -l libtest-v0.so libtest-v1.so
440 'struct leaf' changed:
441 type size changed from 32 to 64 bits
442 1 data member insertion:
443 'char leaf::m1', at offset 32 (in bits) at test-v1.cc:4:1
444
445 one impacted interface:
446 function void fn(C&)
447 $
448
449 Note how the report ends by showing the list of interfaces im‐
450 pacted by the leaf change.
451
452 Now if you don’t want to see that list of impacted interfaces,
453 then you can just avoid using the --impacted-interface option.
454 You can learn about that option below, in any case.
455
456 • --impacted-interfaces
457
458 When showing leaf changes, this option instructs abidiff to show
459 the list of impacted interfaces. This option is thus to be used
460 in addition the --leaf-changes-only option, otherwise, it’s ig‐
461 nored.
462
463 • --dump-diff-tree
464 After the diff report, emit a textual representation of the diff
465 nodes tree used by the comparison engine to represent the
466 changed functions and variables. That representation is emitted
467 to the error output for debugging purposes. Note that this diff
468 tree is relevant only to functions and variables that have some
469 sub-type changes. Added or removed functions and variables do
470 not have any diff nodes tree associated to them.
471
472 • --stats
473
474 Emit statistics about various internal things.
475
476 • --verbose
477
478 Emit verbose logs about the progress of miscellaneous internal
479 things.
480
482 The exit code of the abidiff command is either 0 if the ABI of the bi‐
483 naries being compared are equal, or non-zero if they differ or if the
484 tool encountered an error.
485
486 In the later case, the exit code is a 8-bits-wide bit field in which
487 each bit has a specific meaning.
488
489 The first bit, of value 1, named ABIDIFF_ERROR means there was an er‐
490 ror.
491
492 The second bit, of value 2, named ABIDIFF_USAGE_ERROR means there was
493 an error in the way the user invoked the tool. It might be set, for
494 instance, if the user invoked the tool with an unknown command line
495 switch, with a wrong number or argument, etc. If this bit is set, then
496 the ABIDIFF_ERROR bit must be set as well.
497
498 The third bit, of value 4, named ABIDIFF_ABI_CHANGE means the ABI of
499 the binaries being compared are different.
500
501 The fourth bit, of value 8, named ABIDIFF_ABI_INCOMPATIBLE_CHANGE means
502 the ABI of the binaries compared are different in an incompatible way.
503 If this bit is set, then the ABIDIFF_ABI_CHANGE bit must be set as
504 well. If the ABIDIFF_ABI_CHANGE is set and the ABIDIFF_INCOMPATI‐
505 BLE_CHANGE is NOT set, then it means that the ABIs being compared might
506 or might not be compatible. In that case, a human being needs to re‐
507 view the ABI changes to decide if they are compatible or not.
508
509 Note that, at the moment, there are only a few kinds of ABI changes
510 that would result in setting the flag ABIDIFF_ABI_INCOMPATIBLE_CHANGE.
511 Those ABI changes are either:
512
513 • the removal of the symbol of a function or variable that has been
514 defined and exported.
515
516 • the modification of the index of a member of a virtual function
517 table (for C++ programs and libraries).
518
519 With time, when more ABI change patterns are found to always constitute
520 incompatible ABI changes, we will adapt the code to recognize those
521 cases and set the ABIDIFF_ABI_INCOMPATIBLE_CHANGE accordingly. So, if
522 you find such patterns, please let us know.
523
524 The remaining bits are not used for the moment.
525
527 1. Detecting a change in a sub-type of a function:
528
529 $ cat -n test-v0.cc
530 1 // Compile this with:
531 2 // g++ -g -Wall -shared -o libtest-v0.so test-v0.cc
532 3
533 4 struct S0
534 5 {
535 6 int m0;
536 7 };
537 8
538 9 void
539 10 foo(S0* /*parameter_name*/)
540 11 {
541 12 // do something with parameter_name.
542 13 }
543 $
544 $ cat -n test-v1.cc
545 1 // Compile this with:
546 2 // g++ -g -Wall -shared -o libtest-v1.so test-v1.cc
547 3
548 4 struct type_base
549 5 {
550 6 int inserted;
551 7 };
552 8
553 9 struct S0 : public type_base
554 10 {
555 11 int m0;
556 12 };
557 13
558 14 void
559 15 foo(S0* /*parameter_name*/)
560 16 {
561 17 // do something with parameter_name.
562 18 }
563 $
564 $ g++ -g -Wall -shared -o libtest-v0.so test-v0.cc
565 $ g++ -g -Wall -shared -o libtest-v1.so test-v1.cc
566 $
567 $ ../build/tools/abidiff libtest-v0.so libtest-v1.so
568 Functions changes summary: 0 Removed, 1 Changed, 0 Added function
569 Variables changes summary: 0 Removed, 0 Changed, 0 Added variable
570
571 1 function with some indirect sub-type change:
572
573 [C]'function void foo(S0*)' has some indirect sub-type changes:
574 parameter 0 of type 'S0*' has sub-type changes:
575 in pointed to type 'struct S0':
576 size changed from 32 to 64 bits
577 1 base class insertion:
578 struct type_base
579 1 data member change:
580 'int S0::m0' offset changed from 0 to 32
581 $
582
583 2. Detecting another change in a sub-type of a function:
584
585 $ cat -n test-v0.cc
586 1 // Compile this with:
587 2 // g++ -g -Wall -shared -o libtest-v0.so test-v0.cc
588 3
589 4 struct S0
590 5 {
591 6 int m0;
592 7 };
593 8
594 9 void
595 10 foo(S0& /*parameter_name*/)
596 11 {
597 12 // do something with parameter_name.
598 13 }
599 $
600 $ cat -n test-v1.cc
601 1 // Compile this with:
602 2 // g++ -g -Wall -shared -o libtest-v1.so test-v1.cc
603 3
604 4 struct S0
605 5 {
606 6 char inserted_member;
607 7 int m0;
608 8 };
609 9
610 10 void
611 11 foo(S0& /*parameter_name*/)
612 12 {
613 13 // do something with parameter_name.
614 14 }
615 $
616 $ g++ -g -Wall -shared -o libtest-v0.so test-v0.cc
617 $ g++ -g -Wall -shared -o libtest-v1.so test-v1.cc
618 $
619 $ ../build/tools/abidiff libtest-v0.so libtest-v1.so
620 Functions changes summary: 0 Removed, 1 Changed, 0 Added function
621 Variables changes summary: 0 Removed, 0 Changed, 0 Added variable
622
623 1 function with some indirect sub-type change:
624
625 [C]'function void foo(S0&)' has some indirect sub-type changes:
626 parameter 0 of type 'S0&' has sub-type changes:
627 in referenced type 'struct S0':
628 size changed from 32 to 64 bits
629 1 data member insertion:
630 'char S0::inserted_member', at offset 0 (in bits)
631 1 data member change:
632 'int S0::m0' offset changed from 0 to 32
633
634
635 $
636
637 3. Detecting that functions got removed or added to a library:
638
639 $ cat -n test-v0.cc
640 1 // Compile this with:
641 2 // g++ -g -Wall -shared -o libtest-v0.so test-v0.cc
642 3
643 4 struct S0
644 5 {
645 6 int m0;
646 7 };
647 8
648 9 void
649 10 foo(S0& /*parameter_name*/)
650 11 {
651 12 // do something with parameter_name.
652 13 }
653 $
654 $ cat -n test-v1.cc
655 1 // Compile this with:
656 2 // g++ -g -Wall -shared -o libtest-v1.so test-v1.cc
657 3
658 4 struct S0
659 5 {
660 6 char inserted_member;
661 7 int m0;
662 8 };
663 9
664 10 void
665 11 bar(S0& /*parameter_name*/)
666 12 {
667 13 // do something with parameter_name.
668 14 }
669 $
670 $ g++ -g -Wall -shared -o libtest-v0.so test-v0.cc
671 $ g++ -g -Wall -shared -o libtest-v1.so test-v1.cc
672 $
673 $ ../build/tools/abidiff libtest-v0.so libtest-v1.so
674 Functions changes summary: 1 Removed, 0 Changed, 1 Added functions
675 Variables changes summary: 0 Removed, 0 Changed, 0 Added variable
676
677 1 Removed function:
678 'function void foo(S0&)' {_Z3fooR2S0}
679
680 1 Added function:
681 'function void bar(S0&)' {_Z3barR2S0}
682
683 $
684
686 Dodji Seketeli
687
689 2014-2022, Red Hat, Inc.
690
691
692
693
694 Jan 20, 2022 ABIDIFF(1)