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