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