Overview
The upstream code repository of Libabigail contains several tools
written using the library. They are maintained and released as
part of the project. All tools come with a bash-completion
script.
Tools manuals
abidiff
abidiff compares the Application Binary Interfaces (ABI) of two
shared libraries in ELF format. It emits a meaningful report
describing the differences between the two ABIs.
This tool can also compare the textual representations of the ABI
of two ELF binaries (as emitted by abidw
) or an ELF binary
against a textual representation of another ELF binary.
For a comprehensive ABI change report that includes changes about
function and variable sub-types, the two input shared libraries
must be accompanied with their debug information in DWARF format.
Otherwise, only ELF symbols that were added or removed are
reported.
Invocation
abidiff [options] <first-shared-library> <second-shared-library>
Environment
abidiff loads two default suppression specifications files,
merges their content and use it to filter out ABI change reports
that might be considered as false positives to users.
• Default system-wide suppression specification file
It's located by the optional environment variable
LIBABIGAIL_DEFAULT_SYSTEM_SUPPRESSION_FILE. If that
environment variable is not set, then abidiff tries to load the
suppression file
$libdir/libabigail/libabigail-default.abignore. If that file
is not present, then no default system-wide suppression
specification file is loaded.
• Default user suppression specification file.
It's located by the optional environment
LIBABIGAIL_DEFAULT_USER_SUPPRESSION_FILE. If that environment
variable is not set, then abidiff tries to load the suppression
file $HOME/.abignore. If that file is not present, then no
default user suppression specification is loaded.
Options
• --help | -h
Display a short help about the command and exit.
• --debug
In this mode, error messages are emitted for types which
fail type canonicalization.
This is an optional ebugging and sanity check option. To
enable it the libabigail package needs to be configured with
the --enable-debug-self-comparison option.
• --version | -v
Display the version of the program and exit.
• --debug-info-dir1 | --d1
<di-path1>
For cases where the debug information for
first-shared-library is split out into a separate file,
tells abidiff
where to find that separate debug information
file.
Note that di-path must point to the root directory under
which the debug information is arranged in a tree-like
manner. Under Red Hat based systems, that directory is
usually <root>/usr/lib/debug
.
This option can be provided several times with different
root directories. In that case, abidiff
will potentially
look into all those root directories to find the split debug
info for first-shared-library.
Note also that this option is not mandatory for split debug
information installed by your system's package manager
because then abidiff
knows where to find it.
• --debug-info-dir2 | --d2
<di-path2>
Like --debug-info-dir1
, this options tells abidiff
where to
find the split debug information for the
second-shared-library file.
This option can be provided several times with different
root directories. In that case, abidiff
will potentially
look into all those root directories to find the split debug
info for second-shared-library.
• --headers-dir1 | --hd1
<headers-directory-path-1>
Specifies where to find the public headers of the first
shared library (or binary in general) that the tool has to
consider. The tool will thus filter out ABI changes on
types that are not defined in public headers.
Note that several public header directories can be specified
for the first shared library. In that case the
--headers-dir1
option should be present several times on the
command line, like in the following example:
$ abidiff --headers-dir1 /some/path \
--headers-dir1 /some/other/path \
binary-version-1 binary-version-2
• --header-file1 | --hf1
<header-file-path-1>
Specifies where to find one public header of the first
shared library that the tool has to consider. The tool will
thus filter out ABI changes on types that are not defined in
public headers.
• --headers-dir2 | --hd2
<headers-directory-path-1>
Specifies where to find the public headers of the second
shared library that the tool has to consider. The tool will
thus filter out ABI changes on types that are not defined in
public headers.
Note that several public header directories can be specified
for the second shared library. In that case the
--headers-dir2
option should be present several times like
in the following example:
$ abidiff --headers-dir2 /some/path \
--headers-dir2 /some/other/path \
binary-version-1 binary-version-2
• --header-file2 | --hf2
<header-file-path-2>
Specifies where to find one public header of the second
shared library that the tool has to consider. The tool will
thus filter out ABI changes on types that are not defined in
public headers.
• --no-linux-kernel-mode
Without this option, if abidiff detects that the binaries it
is looking at are Linux Kernel binaries (either vmlinux or
modules) then it only considers functions and variables
which ELF symbols are listed in the __ksymtab and
__ksymtab_gpl sections.
With this option, abidiff considers the binary as a
non-special ELF binary. It thus considers functions and
variables which are defined and exported in the ELF sense.
• --kmi-whitelist | -kaw
<path-to-whitelist>
When analyzing a Linux kernel binary, this option points to
the white list of names of ELF symbols of functions and
variables which ABI must be considered. That white list is
called a "Kernel Module Interface white list". This is
because for the Kernel, we don't talk about ABI
; we rather
talk about the interface between the Kernel and its module.
Hence the term KMI
rather than ABI
.
Any other function or variable which ELF symbol are not
present in that white list will not be considered by this
tool.
If this option is not provided -- thus if no white list is
provided -- then the entire KMI, that is, the set of all
publicly defined and exported functions and global variables
by the Linux Kernel binaries, is considered.
• --drop-private-types
This option is to be used with the --headers-dir1
,
header-file1
, header-file2
and --headers-dir2
options. With
this option, types that are NOT defined in the headers are
entirely dropped from the internal representation build by
Libabigail to represent the ABI. They thus don't have to be
filtered out from the final ABI change report because they
are not even present in Libabigail's representation.
Without this option however, those private types are kept in
the internal representation and later filtered out from the
report.
This options thus potentially makes Libabigail consume less
memory. It's meant to be mainly used to optimize the memory
consumption of the tool on binaries with a lot of publicly
defined and exported types.
• --stat
Rather than displaying the detailed ABI differences between
first-shared-library and second-shared-library, just display
some summary statistics about these differences.
• --symtabs
Only display the symbol tables of the first-shared-library
and second-shared-library.
• --deleted-fns
In the resulting report about the differences between
first-shared-library and second-shared-library, only display
the globally defined functions that got deleted from
first-shared-library.
• --changed-fns
In the resulting report about the differences between
first-shared-library and second-shared-library, only display
the changes in sub-types of the global functions defined in
first-shared-library.
• --added-fns
In the resulting report about the differences between
first-shared-library and second-shared-library, only display
the globally defined functions that were added to
second-shared-library.
• --deleted-vars
In the resulting report about the differences between
first-shared-library and second-shared-library, only display
the globally defined variables that were deleted from
first-shared-library.
• --changed-vars
In the resulting report about the differences between
first-shared-library and second-shared-library, only display
the changes in the sub-types of the global variables defined
in first-shared-library
• --added-vars
In the resulting report about the differences between
first-shared-library and second-shared-library, only display
the global variables that were added (defined) to
second-shared-library.
• --non-reachable-types|-t
Analyze and emit change reports for all the types of the
binary, including those that are not reachable from global
functions and variables.
This option might incur some serious performance degradation
as the number of types analyzed can be huge. However, if
paired with the --headers-dir{1,2}
and/or header-file{1,2}
options, the additional non-reachable types analyzed are
restricted to those defined in public headers files, thus
hopefully making the performance hit acceptable.
Also, using this option alongside suppression specifications
(by also using the --suppressions
option) might help keep
the number of analyzed types (and the potential performance
degradation) in control.
Note that without this option, only types that are reachable
from global functions and variables are analyzed, so the
tool detects and reports changes on these reachable types
only.
• --no-added-syms
In the resulting report about the differences between
first-shared-library and second-shared-library, do not
display added functions or variables. Do not display added
functions or variables ELF symbols either. All other kinds
of changes are displayed unless they are explicitely
forbidden by other options on the command line.
• --no-linkage-name
In the resulting report, do not display the linkage names of
the added, removed, or changed functions or variables.
• --no-show-locs
Do not show information about where in the second shared
library the respective type was changed.
• --show-bytes
Show sizes and offsets in bytes, not bits. By default,
sizes and offsets are shown in bits.
• --show-bits
Show sizes and offsets in bits, not bytes. This option is
activated by default.
• --show-hex
Show sizes and offsets in hexadecimal base.
• --show-dec
Show sizes and offsets in decimal base. This option is
activated by default.
• --no-show-relative-offset-changes
Without this option, when the offset of a data member
changes, the change report not only mentions the older and
newer offset, but it also mentions by how many bits the data
member changes. With this option, the latter is not shown.
• --no-unreferenced-symbols
In the resulting report, do not display change information
about function and variable symbols that are not referenced
by any debug information. Note that for these symbols not
referenced by any debug information, the change information
displayed is either added or removed symbols.
• --no-default-suppression
Do not load the default suppression specification files.
• --suppressions | --suppr
<path-to-suppressions>
Use a suppression specification file located at
path-to-suppressions. Note that this option can appear
multiple times on the command line. In that case, all of
the provided suppression specification files are taken into
account.
Please note that, by default, if this option is not
provided, then the default suppression specification files
are loaded .
• --drop
<regex>
When reading the first-shared-library and
second-shared-library ELF input files, drop the globally
defined functions and variables which name match the regular
expression regex. As a result, no change involving these
functions or variables will be emitted in the diff report.
• --drop-fn
<regex>
When reading the first-shared-library and
second-shared-library ELF input files, drop the globally
defined functions which name match the regular expression
regex. As a result, no change involving these functions
will be emitted in the diff report.
• --drop-var
<regex>
When reading the first-shared-library and
second-shared-library ELF input files, drop the globally
defined variables matching a the regular expression regex.
• --keep
<regex>
When reading the first-shared-library and
second-shared-library ELF input files, keep the globally
defined functions and variables which names match the
regular expression regex. All other functions and variables
are dropped on the floor and will thus not appear in the
resulting diff report.
• --keep-fn
<regex>
When reading the first-shared-library and
second-shared-library ELF input files, keep the globally
defined functions which name match the regular expression
regex. All other functions are dropped on the floor and
will thus not appear in the resulting diff report.
• --keep-var
<regex>
When reading the first-shared-library and
second-shared-library ELF input files, keep the globally
defined which names match the regular expression regex. All
other variables are dropped on the floor and will thus not
appear in the resulting diff report.
• --harmless
In the diff report, display only the harmless changes. By
default, the harmless changes are filtered out of the diff
report keep the clutter to a minimum and have a greater
chance to spot real ABI issues.
• --no-harmful
In the diff report, do not display the harmful changes. By
default, only the harmful changes are displayed in diff
report.
• --redundant
In the diff report, do display redundant changes. A
redundant change is a change that has been displayed
elsewhere in the report.
• --no-redundant
In the diff report, do NOT display redundant changes. A
redundant change is a change that has been displayed
elsewhere in the report. This option is switched on by
default.
• --no-architecture
Do not take architecture in account when comparing ABIs.
• --no-corpus-path
Do not emit the path attribute for the ABI corpus.
• --fail-no-debug-info
If no debug info was found, then this option makes the
program to fail. Otherwise, without this option, the
program will attempt to compare properties of the binaries
that are not related to debug info, like pure ELF
properties.
• --leaf-changes-only|-l
only show leaf changes, so don't show
impact analysis report. This option implies --redundant
.
The typical output of abidiff when comparing two binaries
looks like this
$ abidiff libtest-v0.so libtest-v1.so
Functions changes summary: 0 Removed, 1 Changed, 0 Added function
Variables changes summary: 0 Removed, 0 Changed, 0 Added variable
1 function with some indirect sub-type change:
[C]'function void fn(C&)' at test-v1.cc:13:1 has some indirect sub-type changes:
parameter 1 of type 'C&' has sub-type changes:
in referenced type 'struct C' at test-v1.cc:7:1:
type size hasn't changed
1 data member change:
type of 'leaf* C::m0' changed:
in pointed to type 'struct leaf' at test-v1.cc:1:1:
type size changed from 32 to 64 bits
1 data member insertion:
'char leaf::m1', at offset 32 (in bits) at test-v1.cc:4:1
$
So in that example the report emits information about how
the data member insertion change of "struct leaf" is
reachable from function "void fn(C&)". In other words, the
report not only shows the data member change on "struct
leaf", but it also shows the impact of that change on the
function "void fn(C&)".
In abidiff parlance, the change on "struct leaf" is called a
leaf change. So the --leaf-changes-only
--impacted-interfaces
options show, well, only the leaf
change. And it goes like this:
$ abidiff -l libtest-v0.so libtest-v1.so
'struct leaf' changed:
type size changed from 32 to 64 bits
1 data member insertion:
'char leaf::m1', at offset 32 (in bits) at test-v1.cc:4:1
one impacted interface:
function void fn(C&)
$
Note how the report ends by showing the list of interfaces
impacted by the leaf change.
Now if you don't want to see that list of impacted
interfaces, then you can just avoid using the
--impacted-interface
option. You can learn about that
option below, in any case.
• --impacted-interfaces
When showing leaf changes, this option instructs abidiff to
show the list of impacted interfaces. This option is thus
to be used in addition the --leaf-changes-only
option,
otherwise, it's ignored.
• --dump-diff-tree
After the diff report, emit a textual representation of
the diff nodes tree used by the comparison engine to
represent the changed functions and variables. That
representation is emitted to the error output for
debugging purposes. Note that this diff tree is relevant
only to functions and variables that have some sub-type
changes. Added or removed functions and variables do not
have any diff nodes tree associated to them.
• --stats
Emit statistics about various internal things.
• --verbose
Emit verbose logs about the progress of miscellaneous
internal things.
Return values
The exit code of the abidiff
command is either 0 if the ABI of
the binaries being compared are equal, or non-zero if they differ
or if the tool encountered an error.
In the later case, the exit code is a 8-bits-wide bit field in
which each bit has a specific meaning.
The first bit, of value 1, named ABIDIFF_ERROR
means there was an
error.
The second bit, of value 2, named ABIDIFF_USAGE_ERROR
means there
was an error in the way the user invoked the tool. It might be
set, for instance, if the user invoked the tool with an unknown
command line switch, with a wrong number or argument, etc. If
this bit is set, then the ABIDIFF_ERROR
bit must be set as well.
The third bit, of value 4, named ABIDIFF_ABI_CHANGE
means the ABI
of the binaries being compared are different.
The fourth bit, of value 8, named ABIDIFF_ABI_INCOMPATIBLE_CHANGE
means the ABI of the binaries compared are different in an
incompatible way. If this bit is set, then the
ABIDIFF_ABI_CHANGE
bit must be set as well. If the
ABIDIFF_ABI_CHANGE
is set and the ABIDIFF_INCOMPATIBLE_CHANGE
is
NOT set, then it means that the ABIs being compared might or
might not be compatible. In that case, a human being needs to
review the ABI changes to decide if they are compatible or not.
Note that, at the moment, there are only a few kinds of ABI
changes that would result in setting the flag
ABIDIFF_ABI_INCOMPATIBLE_CHANGE
. Those ABI changes are either:
• the removal of the symbol of a function or variable that has
been defined and exported.
• the modification of the index of a member of a virtual
function table (for C++ programs and libraries).
With time, when more ABI change patterns are found to always
constitute incompatible ABI changes, we will adapt the code to
recognize those cases and set the ABIDIFF_ABI_INCOMPATIBLE_CHANGE
accordingly. So, if you find such patterns, please let us know.
The remaining bits are not used for the moment.
Usage examples
1. Detecting a change in a sub-type of a function:
$ cat -n test-v0.cc
1 // Compile this with:
2 // g++ -g -Wall -shared -o libtest-v0.so test-v0.cc
3
4 struct S0
5 {
6 int m0;
7 };
8
9 void
10 foo(S0* /*parameter_name*/)
11 {
12 // do something with parameter_name.
13 }
$
$ cat -n test-v1.cc
1 // Compile this with:
2 // g++ -g -Wall -shared -o libtest-v1.so test-v1.cc
3
4 struct type_base
5 {
6 int inserted;
7 };
8
9 struct S0 : public type_base
10 {
11 int m0;
12 };
13
14 void
15 foo(S0* /*parameter_name*/)
16 {
17 // do something with parameter_name.
18 }
$
$ g++ -g -Wall -shared -o libtest-v0.so test-v0.cc
$ g++ -g -Wall -shared -o libtest-v1.so test-v1.cc
$
$ ../build/tools/abidiff libtest-v0.so libtest-v1.so
Functions changes summary: 0 Removed, 1 Changed, 0 Added function
Variables changes summary: 0 Removed, 0 Changed, 0 Added variable
1 function with some indirect sub-type change:
[C]'function void foo(S0*)' has some indirect sub-type changes:
parameter 0 of type 'S0*' has sub-type changes:
in pointed to type 'struct S0':
size changed from 32 to 64 bits
1 base class insertion:
struct type_base
1 data member change:
'int S0::m0' offset changed from 0 to 32
$
2. Detecting another change in a sub-type of a function:
$ cat -n test-v0.cc
1 // Compile this with:
2 // g++ -g -Wall -shared -o libtest-v0.so test-v0.cc
3
4 struct S0
5 {
6 int m0;
7 };
8
9 void
10 foo(S0& /*parameter_name*/)
11 {
12 // do something with parameter_name.
13 }
$
$ cat -n test-v1.cc
1 // Compile this with:
2 // g++ -g -Wall -shared -o libtest-v1.so test-v1.cc
3
4 struct S0
5 {
6 char inserted_member;
7 int m0;
8 };
9
10 void
11 foo(S0& /*parameter_name*/)
12 {
13 // do something with parameter_name.
14 }
$
$ g++ -g -Wall -shared -o libtest-v0.so test-v0.cc
$ g++ -g -Wall -shared -o libtest-v1.so test-v1.cc
$
$ ../build/tools/abidiff libtest-v0.so libtest-v1.so
Functions changes summary: 0 Removed, 1 Changed, 0 Added function
Variables changes summary: 0 Removed, 0 Changed, 0 Added variable
1 function with some indirect sub-type change:
[C]'function void foo(S0&)' has some indirect sub-type changes:
parameter 0 of type 'S0&' has sub-type changes:
in referenced type 'struct S0':
size changed from 32 to 64 bits
1 data member insertion:
'char S0::inserted_member', at offset 0 (in bits)
1 data member change:
'int S0::m0' offset changed from 0 to 32
$
3. Detecting that functions got removed or added to a library:
$ cat -n test-v0.cc
1 // Compile this with:
2 // g++ -g -Wall -shared -o libtest-v0.so test-v0.cc
3
4 struct S0
5 {
6 int m0;
7 };
8
9 void
10 foo(S0& /*parameter_name*/)
11 {
12 // do something with parameter_name.
13 }
$
$ cat -n test-v1.cc
1 // Compile this with:
2 // g++ -g -Wall -shared -o libtest-v1.so test-v1.cc
3
4 struct S0
5 {
6 char inserted_member;
7 int m0;
8 };
9
10 void
11 bar(S0& /*parameter_name*/)
12 {
13 // do something with parameter_name.
14 }
$
$ g++ -g -Wall -shared -o libtest-v0.so test-v0.cc
$ g++ -g -Wall -shared -o libtest-v1.so test-v1.cc
$
$ ../build/tools/abidiff libtest-v0.so libtest-v1.so
Functions changes summary: 1 Removed, 0 Changed, 1 Added functions
Variables changes summary: 0 Removed, 0 Changed, 0 Added variable
1 Removed function:
'function void foo(S0&)' {_Z3fooR2S0}
1 Added function:
'function void bar(S0&)' {_Z3barR2S0}
$
abipkgdiff
abipkgdiff
compares the Application Binary Interfaces (ABI) of
the ELF binaries contained in two software packages. The
software package formats currently supported are Deb, RPM, tar
archives (either compressed or not) and plain directories that
contain binaries.
For a comprehensive ABI change report that includes changes about
function and variable sub-types, the two input packages must be
accompanied with their debug information packages that contain
debug information in DWARF format.
Invocation
abipkgdiff [option] <package1> <package2>
package1
and package2
are the packages that contain the binaries
to be compared.
Environment
abipkgdiff loads two default suppression specifications files,
merges their content and use it to filter out ABI change reports
that might be considered as false positives to users.
• Default system-wide suppression specification file
It's located by the optional environment variable
LIBABIGAIL_DEFAULT_SYSTEM_SUPPRESSION_FILE. If that
environment variable is not set, then abipkgdiff tries to load
the suppression file
$libdir/libabigail/libabigail-default.abignore. If that file
is not present, then no default system-wide suppression
specification file is loaded.
• Default user suppression specification file.
It's located by the optional environment
LIBABIGAIL_DEFAULT_USER_SUPPRESSION_FILE. If that environment
variable is not set, then abipkgdiff tries to load the
suppression file $HOME/.abignore. If that file is not present,
then no default user suppression specification is loaded.
In addition to those default suppression specification files,
abipkgdiff will also look inside the packages being compared and
if it sees a file that ends with the extension .abignore
, then it
will consider it as a suppression specification and it will
combine it to the default suppression specification that might be
already loaded.
The user might as well use the --suppressions
option (that is
documented further below) to provide a suppression specification.
Options
• --help | -h
Display a short help about the command and exit.
• --version | -v
Display the version of the program and exit.
• --debug-info-pkg1 | --d1
<path>
For cases where the debug information for package1 is split
out into a separate file, tells abipkgdiff
where to find
that separate debug information package.
Note that the debug info for package1 can have been split
into several different debug info packages. In that case,
several instances of this options can be provided, along
with those several different debug info packages.
• --debug-info-pkg2 | --d2
<path>
For cases where the debug information for package2 is split
out into a separate file, tells abipkgdiff
where to find
that separate debug information package.
Note that the debug info for package2 can have been split
into several different debug info packages. In that case,
several instances of this options can be provided, along
with those several different debug info packages.
• --devel-pkg1 | --devel1
<path>
Specifies where to find the Development Package associated
with the first package to be compared. That Development
Package at path
should at least contain header files in
which public types exposed by the libraries (of the first
package to be compared) are defined. When this option is
provided, the tool filters out reports about ABI changes to
types that are NOT defined in these header files.
• --devel-pkg2 | --devel2
<path>
Specifies where to find the Development Package associated
with the second package to be compared. That Development
Package at path
should at least contains header files in
which public types exposed by the libraries (of the second
package to be compared) are defined. When this option is
provided, the tool filters out reports about ABI changes to
types that are NOT defined in these header files.
• --drop-private-types
This option is to be used with the --devel-pkg1
and
--devel-pkg2
options. With this option, types that are NOT
defined in the headers are entirely dropped from the
internal representation build by Libabigail to represent the
ABI. They thus don't have to be filtered out from the final
ABI change report because they are not even present in
Libabigail's representation.
Without this option however, those private types are kept in
the internal representation and later filtered out from the
report.
This options thus potentially makes Libabigail consume less
memory. It's meant to be mainly used to optimize the memory
consumption of the tool on binaries with a lot of publicly
defined and exported types.
• --dso-only
Compare ELF files that are shared libraries, only. Do not
compare executable files, for instance.
• --private-dso
By default, abipkgdiff
does not compare DSOs that are
private to the RPM package. A private DSO is a DSO which
SONAME is NOT advertised in the "provides" property of the
RPM.
This option instructs abipkgdiff
to also compare DSOs that
are NOT advertised in the "provides" property of the RPM.
Please note that the fact that (by default) abipkgdiff
skips
private DSO is a feature that is available only for RPMs, at
the moment. We would happily accept patches adding that
feature for other package formats.
• --leaf-changes-only|-l
only show leaf changes, so don't show
impact analysis report. This option implies --redundant
The typical output of abipkgdiff
and abidiff
when comparing
two binaries, that we shall call full impact report
, looks
like this
$ abidiff libtest-v0.so libtest-v1.so
Functions changes summary: 0 Removed, 1 Changed, 0 Added function
Variables changes summary: 0 Removed, 0 Changed, 0 Added variable
1 function with some indirect sub-type change:
[C]'function void fn(C&)' at test-v1.cc:13:1 has some indirect sub-type changes:
parameter 1 of type 'C&' has sub-type changes:
in referenced type 'struct C' at test-v1.cc:7:1:
type size hasn't changed
1 data member change:
type of 'leaf* C::m0' changed:
in pointed to type 'struct leaf' at test-v1.cc:1:1:
type size changed from 32 to 64 bits
1 data member insertion:
'char leaf::m1', at offset 32 (in bits) at test-v1.cc:4:1
$
So in that example the report emits information about how
the data member insertion change of "struct leaf" is
reachable from function "void fn(C&)". In other words, the
report not only shows the data member change on "struct
leaf", but it also shows the impact of that change on the
function "void fn(C&)".
In abidiff (and abipkgdiff) parlance, the change on "struct
leaf" is called a leaf change. So the --leaf-changes-only
--impacted-interfaces
options show, well, only the leaf
change. And it goes like this:
$ abidiff -l libtest-v0.so libtest-v1.so
'struct leaf' changed:
type size changed from 32 to 64 bits
1 data member insertion:
'char leaf::m1', at offset 32 (in bits) at test-v1.cc:4:1
one impacted interface:
function void fn(C&)
$
Note how the report ends up by showing the list of
interfaces impacted by the leaf change. That's the effect
of the additional --impacted-interfaces
option.
Now if you don't want to see that list of impacted
interfaces, then you can just avoid using the
--impacted-interface
option. You can learn about that
option below, in any case.
Please note that when comparing two Linux Kernel packages,
it's this leaf changes report
that is emitted, by default.
The normal so-called full impact report
can be emitted with
the option --full-impact
which is documented later below.
• --impacted-interfaces
When showing leaf changes, this option instructs abipkgdiff
to show the list of impacted interfaces. This option is
thus to be used in addition to the --leaf-changes-only
option, or, when comparing two Linux Kernel packages.
Otherwise, it's simply ignored.
• --full-impact|-f
When comparing two Linux Kernel packages, this function
instructs abipkgdiff
to emit the so-called full impact
report
, which is the default report kind emitted by the
abidiff
tool:
$ abidiff libtest-v0.so libtest-v1.so
Functions changes summary: 0 Removed, 1 Changed, 0 Added function
Variables changes summary: 0 Removed, 0 Changed, 0 Added variable
1 function with some indirect sub-type change:
[C]'function void fn(C&)' at test-v1.cc:13:1 has some indirect sub-type changes:
parameter 1 of type 'C&' has sub-type changes:
in referenced type 'struct C' at test-v1.cc:7:1:
type size hasn't changed
1 data member change:
type of 'leaf* C::m0' changed:
in pointed to type 'struct leaf' at test-v1.cc:1:1:
type size changed from 32 to 64 bits
1 data member insertion:
'char leaf::m1', at offset 32 (in bits) at test-v1.cc:4:1
$
• --non-reachable-types|-t
Analyze and emit change reports for all the types of the
binary, including those that are not reachable from global
functions and variables.
This option might incur some serious performance degradation
as the number of types analyzed can be huge. However, if
paired with the --devel-pkg{1,2}
options, the additional
non-reachable types analyzed are restricted to those defined
in the public headers files carried by the referenced
development packages, thus hopefully making the performance
hit acceptable.
Also, using this option alongside suppression specifications
(by also using the --suppressions
option) might help keep
the number of analyzed types (and the potential performance
degradation) in control.
Note that without this option, only types that are reachable
from global functions and variables are analyzed, so the
tool detects and reports changes on these reachable types
only.
• --redundant
In the diff reports, do display redundant changes. A
redundant change is a change that has been displayed
elsewhere in a given report.
• --harmless
In the diff report, display only the harmless changes. By
default, the harmless changes are filtered out of the diff
report keep the clutter to a minimum and have a greater
chance to spot real ABI issues.
• --no-linkage-name
In the resulting report, do not display the linkage names of
the added, removed, or changed functions or variables.
• --no-added-syms
Do not show the list of functions, variables, or any symbol
that was added.
• --no-added-binaries
Do not show the list of binaries that got added to the
second package.
Please note that the presence of such added binaries is not
considered like an ABI change by this tool; as such, it
doesn't have any impact on the exit code of the tool. It
does only have an informational value. Removed binaries
are, however, considered as an ABI change.
• --no-abignore
Do not search the package for the presence of suppression
files.
• --no-parallel
By default, abipkgdiff
will use all the processors it has
available to execute concurrently. This option tells it not
to extract packages or run comparisons in parallel.
• --no-default-suppression
Do not load the default suppression specification files.
• --suppressions | --suppr
<path-to-suppressions>
Use a suppression specification file located at
path-to-suppressions. Note that this option can appear
multiple times on the command line. In that case, all of
the suppression specification files are taken into account.
Please note that, by default, if this option is not
provided, then the default suppression specification files
are loaded .
• --linux-kernel-abi-whitelist | -w
<path-to-whitelist>
When comparing two Linux kernel RPM packages, this option
points to the white list of names of ELF symbols of
functions and variables that must be compared for ABI
changes. That white list is called a "Linux kernel ABI
white list".
Any other function or variable which ELF symbol are not
present in that white list will not be considered by the ABI
comparison process.
If this option is not provided -- thus if no white list is
provided -- then the ABI of all publicly defined and
exported functions and global variables by the Linux Kernel
binaries are compared.
Please note that if a white list package is given in
parameter, this option handles it just fine, like if the
--wp option was used.
• --wp
<path-to-whitelist-package>
When comparing two Linux kernel RPM packages, this option
points an RPM package containining several white lists of
names of ELF symbols of functions and variables that must be
compared for ABI changes. Those white lists are called
"Linux kernel ABI white lists".
From the content of that white list package, this program
then chooses the appropriate Linux kernel ABI white list to
consider when comparing the ABI of Linux kernel binaries
contained in the Linux kernel packages provided on the
command line.
That choosen Linux kernel ABI white list contains the list
of names of ELF symbols of functions and variables that must
be compared for ABI changes.
Any other function or variable which ELF symbol are not
present in that white list will not be considered by the ABI
comparison process.
Note that this option can be provided twice (not mor than
twice), specifying one white list package for each Linux
Kernel package that is provided on the command line.
If this option is not provided -- thus if no white list is
provided -- then the ABI of all publicly defined and
exported functions and global variables by the Linux Kernel
binaries are compared.
• --no-unreferenced-symbols
In the resulting report, do not display change information
about function and variable symbols that are not referenced
by any debug information. Note that for these symbols not
referenced by any debug information, the change information
displayed is either added or removed symbols.
• --no-show-locs
Do not show information about where in the second shared
library the respective type was changed.
• --show-bytes
Show sizes and offsets in bytes, not bits. By default,
sizes and offsets are shown in bits.
• --show-bits
Show sizes and offsets in bits, not bytes. This option is
activated by default.
• --show-hex
Show sizes and offsets in hexadecimal base.
• --show-dec
Show sizes and offsets in decimal base. This option is
activated by default.
• --no-show-relative-offset-changes
Without this option, when the offset of a data member
changes, the change report not only mentions the older and
newer offset, but it also mentions by how many bits the data
member changes. With this option, the latter is not shown.
• --show-identical-binaries
Show the names of the all binaries compared, including the
binaries whose ABI compare equal. By default, when this
option is not provided, only binaries with ABI changes are
mentionned in the output.
• --fail-no-dbg
Make the program fail and return a non-zero exit code if
couldn't read any of the debug information that comes from
the debug info packages that were given on the command line.
If no debug info package were provided on the command line
then this option is not active.
Note that the non-zero exit code returned by the program as
a result of this option is the constant ABIDIFF_ERROR
. To
know the numerical value of that constant, please refer to
the exit code documentation.
• --keep-tmp-files
Do not erase the temporary directory files that are created
during the execution of the tool.
• --verbose
Emit verbose progress messages.
• self-check
This is used to test the underlying Libabigail library.
When in used, the command expects only on input package,
along with its associated debug info packages. The command
then compares each binary inside the package against its own
ABIXML representation. The result of the comparison should
yield the empty set if Libabigail behaves correctly.
Otherwise, it means there is an issue that ought to be
fixed. This option is used by people interested in
Libabigail development for regression testing purposes.
Here is an example of the use of this option:
$ abipkgdiff --self-check --d1 mesa-libGLU-debuginfo-9.0.1-3.fc33.x86_64.rpm mesa-libGLU-9.0.1-3.fc33.x86_64.rpm
==== SELF CHECK SUCCEEDED for 'libGLU.so.1.3.1' ====
$
Return value
The exit code of the abipkgdiff
command is either 0 if the ABI of
the binaries compared are equal, or non-zero if they differ or if
the tool encountered an error.
In the later case, the value of the exit code is the same as for
the abidiff tool.
kmidiff
kmidiff
compares the binary Kernel Module Interfaces of two Linux
Kernel trees. The binary KMI is the interface that the Linux
Kernel exposes to its modules. The trees we are interested in
here are the result of the build of the Linux Kernel source tree.
General approach
And example of how to build your kernel if you want to compare it
to another one using kmidiff is:
git clone -b v4.5 git://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git linux/v4.5
cd linux/v4.5
make allyesconfig all
Then install the modules into a directory, for instance, the
build/modules sub-directory of the your kernel source tree:
mkdir build/modules
make modules_install INSTALL_MOD_DIR=build/modules
Then construct a list of interfaces exported by the kernel, that
you want to compare:
cat > kmi-whitelist << EOF
[kernel_4.5_kmi_whitelist]
init_task
schedule
dev_queue_xmit
__kmalloc
printk
EOF
Suppose you've done something similar for the v4.6 branch of the
Linux kernel, you now have these two directories: linux/v4.5
and
linux/v4.6
. Their modules are present under the directories
linux/v4.5/build/modules
and linux/v4.6/build/modules
.
To Comparing their KMI kmidiff
needs to know where to find the
vmlinux binaries and their associated modules. Here would be
what the command line looks like:
kmidiff \
--kmi-whitelist linux/v4.6/kmi-whitelist \
--vmlinux1 linux/v4.5/vmlinux \
--vmlinux2 linux/v4.6/vmlinux \
linux/v4.5/build/modules \
linux/v4.6/build/modules
Invocation
More generally, kmidiff
is invoked under the form:
kmidiff [options] <first-modules-dir> <second-modules-dir>
Environment
By default, kmidiff
compares all the interfaces (exported
functions and variables) between the Kernel and its modules. In
practice, though, users want to compare a subset of the those
interfaces.
Users can then define a "white list" of the interfaces to
compare. Such a white list is a just a file in the "INI" format
that looks like:
[kernel_version_x86_64_whitelist]
function1_name
function2_name
global_variable1_name
....
Note that the name of the section (the name that is between the
two brackets) of that INI file just has to end with the string
"whitelist". So you can define the name you want, for instance
[kernel_46_x86_64_whitelist]
.
Then each line of that whitelist file is the name of an exported
function or variable. Only those interfaces along with the types
reachable from their signatures are going to be compared by
kmidiff
recursively.
Note that kmidiff compares the interfaces exported by the vmlinux
binary and by the all of the compiled modules.
Options
• --help | -h
Display a short help about the command and exit.
• --version | -v
Display the version of the program and exit.
• --verbose
Display some verbose messages while executing.
• --debug-info-dir1 | --d1
<di-path1>
For cases where the debug information for the binaries of
the first Linux kernel is split out into separate files,
tells kmidiff
where to find those separate debug information
files.
Note that di-path must point to the root directory under
which the debug information is arranged in a tree-like
manner. Under Red Hat based systems, that directory is
usually <root>/usr/lib/debug
.
• --debug-info-dir2 | --d2
<di-path2>
Like --debug-info-dir1
, this options tells kmidiff
where to
find the split debug information for the binaries of the
second Linux kernel.
• --vmlinux1 | --l1
<path-to-first-vmlinux>
Sets the path to the first vmlinux
binary to consider. This
has to be the uncompressed vmlinux binary compiled with
debug info.
• --vmlinux2 | --l2
<path-to-first-vmlinux>
Sets the path to the second vmlinux
binary to consider.
This has to be the uncompressed vmlinux binary compiled with
debug info.
• --kmi-whitelist | -w
<path-to-interface-whitelist>
Set the path to the white list of interfaces to compare
while comparing the Kernel Module Interface of the first
kernel against the one of the second kernel.
If this option is not provided, all the exported interfaces
of the two kernels are compared. That takes a lot of times
and is not necessarily meaningful because many interface are
probably meant to see their reachable types change.
So please, make sure you always use this option unless you
really know what you are doing.
• --suppressions | --suppr
<path-to-suppressions>
Use a suppression specification file located at
path-to-suppressions. Note that this option can appear
multiple times on the command line. In that case, all of
the provided suppression specification files are taken into
account.
Please note that, by default, if this option is not
provided, then the default suppression specification files
are loaded .
• --impacted-interfaces | -i
Tell what interfaces got impacted by each individual ABI
change.
• --full-impact | -f
Emit a change report that shows the full impact of each
change on exported interfaces. This is the default kind of
report emitted by tools like abidiff
or abipkgdiff
.
• --show-bytes
Show sizes and offsets in bytes, not bits. This option is
activated by default.
• --show-bits
Show sizes and offsets in bits, not bytes. By default,
sizes and offsets are shown in bytes.
• --show-hex
Show sizes and offsets in hexadecimal base. This option is
activated by default.
• --show-dec
Show sizes and offsets in decimal base.
abidw
abidw reads a shared library in ELF format and emits an XML
representation of its ABI to standard output. The emitted
representation includes all the globally defined functions and
variables, along with a complete representation of their types.
It also includes a representation of the globally defined ELF
symbols of the file. The input shared library must contain
associated debug information in DWARF format.
When given the --linux-tree
option, this program can also handle
a Linux kernel tree. That is, a directory tree that contains
both the vmlinux binary and Linux kernel modules. It analyses
those Linux kernel binaries and emits an XML representation of
the interface between the kernel and its module, to standard
output. In this case, we don't call it an ABI, but a KMI (Kernel
Module Interface). The emitted KMI includes all the globally
defined functions and variables, along with a complete
representation of their types. The input binaries must contain
associated debug information in DWARF format.
Invocation
abidw [options] [<path-to-elf-file>]
Options
• --help | -h
Display a short help about the command and exit.
• --version | -v
Display the version of the program and exit.
• --debug-info-dir | -d
<dir-path>
In cases where the debug info for path-to-elf-file is in a
separate file that is located in a non-standard place, this
tells abidw
where to look for that debug info file.
Note that dir-path must point to the root directory under
which the debug information is arranged in a tree-like
manner. Under Red Hat based systems, that directory is
usually <root>/usr/lib/debug
.
This option can be provided several times with different
root directories. In that case, abidw
will potentially look
into all those root directories to find the split debug info
for the elf file.
Note that this option is not mandatory for split debug
information installed by your system's package manager
because then abidw
knows where to find it.
• --out-file
<file-path>
This option instructs abidw
to emit the XML representation
of path-to-elf-file into the file file-path, rather than
emitting it to its standard output.
• --noout
This option instructs abidw
to not emit the XML
representation of the ABI. So it only reads the ELF and
debug information, builds the internal representation of the
ABI and exits. This option is usually useful for debugging
purposes.
• --no-corpus-path
Do not emit the path attribute for the ABI corpus.
• --suppressions | suppr
<path-to-suppression-specifications-file>
Use a suppression specification file located at
path-to-suppression-specifications-file. Note that this
option can appear multiple times on the command line. In
that case, all of the provided suppression specification
files are taken into account. ABI artifacts matched by the
suppression specifications are suppressed from the output of
this tool.
• --kmi-whitelist | -kaw
<path-to-whitelist>
When analyzing a Linux kernel binary, this option points to
the white list of names of ELF symbols of functions and
variables which ABI must be written out. That white list is
called a " Kernel Module Interface white list". This is
because for the Kernel, we don't talk about the ABI; we
rather talk about the interface between the Kernel and its
module. Hence the term KMI
rather than ABI
Any other function or variable which ELF symbol are not
present in that white list will not be considered by the KMI
writing process.
If this option is not provided -- thus if no white list is
provided -- then the entire KMI, that is, all publicly
defined and exported functions and global variables by the
Linux Kernel binaries is emitted.
• --linux-tree | --lt
Make abidw
to consider the input path as a path to a
directory containing the vmlinux binary as several kernel
modules binaries. In that case, this program emits the
representation of the Kernel Module Interface (KMI) on the
standard output.
Below is an example of usage of abidw
on a Linux Kernel
tree.
First, checkout a Linux kernel source tree and build it.
Then install the kernel modules in a directory somewhere.
Copy the vmlinux binary into that directory too. And then
serialize the KMI of that kernel to disk, using abidw
:
$ git clone git://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
$ cd linux && git checkout v4.5
$ make allyesconfig all
$ mkdir build-output
$ make INSTALL_MOD_PATH=./build-output modules_install
$ cp vmlinux build-output/modules/4.5.0
$ abidw --linux-tree build-output/modules/4.5.0 > build-output/linux-4.5.0.kmi
• --headers-dir | --hd
<headers-directory-path-1>
Specifies where to find the public headers of the binary
that the tool has to consider. The tool will thus filter
out types that are not defined in public headers.
Note that several public header directories can be specified
for the binary to consider. In that case the --header-dir
option should be present several times on the command line,
like in the following example:
$ abidw --header-dir /some/path \
--header-dir /some/other/path \
binary > binary.abi
• --header-file | --hf
<header-file-path>
Specifies where to find one of the public headers of the abi
file that the tool has to consider. The tool will thus
filter out types that are not defined in public headers.
• --drop-private-types
This option is to be used with the --headers-dir
and/or
header-file
options. With this option, types that are NOT
defined in the headers are entirely dropped from the
internal representation build by Libabigail to represent the
ABI and will not end up in the abi XML file.
• --no-elf-needed
Do not include the list of DT_NEEDED dependency names in the
corpus.
• --drop-undefined-syms
With this option functions or variables for which the
(exported) ELF symbol is undefined are dropped from the
internal representation build by Libabigail to represent the
ABI and will not end up in the abi XML file.
• --no-linux-kernel-mode
Without this option, if abipkgiff detects that the binaries
it is looking at are Linux Kernel binaries (either vmlinux
or modules) then it only considers functions and variables
which ELF symbols are listed in the __ksymtab and
__ksymtab_gpl sections.
With this option, abipkgdiff considers the binary as a
non-special ELF binary. It thus considers functions and
variables which are defined and exported in the ELF sense.
• --check-alternate-debug-info
<elf-path>
If the debug info for the file elf-path contains a reference
to an alternate debug info file, abidw
checks that it can
find that alternate debug info file. In that case, it emits
a meaningful success message mentioning the full path to the
alternate debug info file found. Otherwise, it emits an
error code.
• --no-show-locs
In the emitted ABI representation, do not show file, line
or column where ABI artifacts are defined.
• --no-parameter-names
In the emitted ABI representation, do not show names of
function parameters, just the types.
• --no-write-default-sizes
In the XML ABI representation, do not write the size-in-bits
for pointer type definitions, reference type definitions,
function declarations and function types when they are equal
to the default address size of the translation unit. Note
that libabigail before 1.8 will not set the default size and
will interpret types without a size-in-bits attribute as
zero sized.
• --type-id-style
<sequence``|``hash
>
This option controls how types are idenfied in the generated
XML files. The default sequence
style just numbers (with
type-id-
as prefix) the types in the order they are
encountered. The hash
style uses a (stable, portable) hash
of libabigail's internal type names and is intended to make
the XML files easier to diff.
• --check-alternate-debug-info-base-name
<elf-path>
Like --check-alternate-debug-info
, but in the success
message, only mention the base name of the debug info file;
not its full path.
• --load-all-types
By default, libabigail
(and thus abidw
) only loads types
that are reachable from functions and variables declarations
that are publicly defined and exported by the binary. So
only those types are present in the output of abidw
. This
option however makes abidw
load all the types defined in the
binaries, even those that are not reachable from public
declarations.
• --abidiff
Load the ABI of the ELF binary given in argument, save it
in libabigail's XML format in a temporary file; read the
ABI from the temporary XML file and compare the ABI that
has been read back against the ABI of the ELF binary given
in argument. The ABIs should compare equal. If they
don't, the program emits a diagnostic and exits with a
non-zero code.
This is a debugging and sanity check option.
• --debug-abidiff
Same as --abidiff
but in debug mode. In this mode, error
messages are emitted for types which fail type
canonicalization.
This is an optional debugging and sanity check option. To
enable it the libabigail package needs to be configured
with the --enable-debug-self-comparison option.
• --annotate
Annotate the ABIXML output with comments above most
elements. The comments are made of the pretty-printed
form types, declaration or even ELF symbols. The purpose
is to make the ABIXML output more human-readable for
debugging or documenting purposes.
• --stats
Emit statistics about various internal things.
• --verbose
Emit verbose logs about the progress of miscellaneous
internal things.
Notes
Alternate debug info files
As of the version 4 of the DWARF specification, Alternate debug
information is a GNU extension to the DWARF specification. It
has however been proposed for inclusion into the upcoming version
5 of the DWARF standard. You can read more about the GNU
extensions to the DWARF standard here.
abicompat
abicompat checks that an application that links against a given
shared library is still ABI compatible with a subsequent version
of that library. If the new version of the library introduces an
ABI incompatibility, then abicompat hints the user at what
exactly that incompatibility is.
Invocation
abicompat [options] [<application> <shared-library-first-version> <shared-library-second-version>]
Options
• --help
Display a short help about the command and exit.
• --version | -v
Display the version of the program and exit.
• --list-undefined-symbols | -u
Display the list of undefined symbols of the application and
exit.
• --show-base-names | -b
In the resulting report emitted by the tool, this option
makes the application and libraries be referred to by their
base names only; not by a full absolute name. This can be
useful for use in scripts that wants to compare names of the
application and libraries independently of what their
directory names are.
• --app-debug-info-dir | --appd
<path-to-app-debug-info-directory>
Set the path to the directory under which the debug
information of the application is supposed to be laid out.
This is useful for application binaries for which the debug
info is in a separate set of files.
• --lib-debug-info-dir1 | --libd1
<path-to-lib1-debug-info>
Set the path to the directory under which the debug
information of the first version of the shared library is
supposed to be laid out. This is useful for shared library
binaries for which the debug info is in a separate set of
files.
• --lib-debug-info-dir2 | --libd2
<path-to-lib1-debug-info>
Set the path to the directory under which the debug
information of the second version of the shared library is
supposed to be laid out. This is useful for shared library
binaries for which the debug info is in a separate set of
files.
• --suppressions | --suppr
<path-to-suppressions>
Use a suppression specification file located at
path-to-suppressions. Note that this option can appear
multiple times on the command line; all the suppression
specification files are then taken into account.
• --no-show-locs
Do not show information about where in the second shared
library the respective type was changed.
• --weak-mode
This triggers the weak mode of abicompat
. In this mode,
only one version of the library is required. That is,
abicompat is invoked like this:
abicompat --weak-mode <the-application> <the-library>
Note that the --weak-mode
option can even be omitted if only
one version of the library is given, along with the
application; in that case, abicompat
automatically switches
to operate in weak mode:
abicompat <the-application> <the-library>
In this weak mode, the types of functions and variables
exported by the library and consumed by the application (as
in, the symbols of the these functions and variables are
undefined in the application and are defined and exported by
the library) are compared to the version of these types as
expected by the application. And if these two versions of
types are different, abicompat
tells the user what the
differences are.
In other words, in this mode, abicompat
checks that the
types of the functions and variables exported by the library
mean the same thing as what the application expects, as far
as the ABI is concerned.
Note that in this mode, abicompat doesn't detect exported
functions or variables (symbols) that are expected by the
application but that are removed from the library. That is
why it is called weak
mode.
Return values
The exit code of the abicompat
command is either 0 if the ABI of
the binaries being compared are equal, or non-zero if they differ
or if the tool encountered an error.
In the later case, the exit code is a 8-bits-wide bit field in
which each bit has a specific meaning.
The first bit, of value 1, named ABIDIFF_ERROR
means there was an
error.
The second bit, of value 2, named ABIDIFF_USAGE_ERROR
means there
was an error in the way the user invoked the tool. It might be
set, for instance, if the user invoked the tool with an unknown
command line switch, with a wrong number or argument, etc. If
this bit is set, then the ABIDIFF_ERROR
bit must be set as well.
The third bit, of value 4, named ABIDIFF_ABI_CHANGE
means the ABI
of the binaries being compared are different.
The fourth bit, of value 8, named ABIDIFF_ABI_INCOMPATIBLE_CHANGE
means the ABI of the binaries compared are different in an
incompatible way. If this bit is set, then the
ABIDIFF_ABI_CHANGE
bit must be set as well. If the
ABIDIFF_ABI_CHANGE
is set and the ABIDIFF_INCOMPATIBLE_CHANGE
is
NOT set, then it means that the ABIs being compared might or
might not be compatible. In that case, a human being needs to
review the ABI changes to decide if they are compatible or not.
The remaining bits are not used for the moment.
Usage examples
• Detecting a possible ABI incompatibility in a new shared
library version:
$ cat -n test0.h
1 struct foo
2 {
3 int m0;
4
5 foo()
6 : m0()
7 {}
8 };
9
10 foo*
11 first_func();
12
13 void
14 second_func(foo&);
15
16 void
17 third_func();
$
$ cat -n test-app.cc
1 // Compile with:
2 // g++ -g -Wall -o test-app -L. -ltest-0 test-app.cc
3
4 #include "test0.h"
5
6 int
7 main()
8 {
9 foo* f = first_func();
10 second_func(*f);
11 return 0;
12 }
$
$ cat -n test0.cc
1 // Compile this with:
2 // g++ -g -Wall -shared -o libtest-0.so test0.cc
3
4 #include "test0.h"
5
6 foo*
7 first_func()
8 {
9 foo* f = new foo();
10 return f;
11 }
12
13 void
14 second_func(foo&)
15 {
16 }
17
18 void
19 third_func()
20 {
21 }
$
$ cat -n test1.h
1 struct foo
2 {
3 int m0;
4 char m1; /* <-- a new member got added here! */
5
6 foo()
7 : m0(),
8 m1()
9 {}
10 };
11
12 foo*
13 first_func();
14
15 void
16 second_func(foo&);
17
18 void
19 third_func();
$
$ cat -n test1.cc
1 // Compile this with:
2 // g++ -g -Wall -shared -o libtest-1.so test1.cc
3
4 #include "test1.h"
5
6 foo*
7 first_func()
8 {
9 foo* f = new foo();
10 return f;
11 }
12
13 void
14 second_func(foo&)
15 {
16 }
17
18 /* Let's comment out the definition of third_func()
19 void
20 third_func()
21 {
22 }
23 */
$
• Compile the first and second versions of the libraries:
libtest-0.so
and libtest-1.so
:
$ g++ -g -Wall -shared -o libtest-0.so test0.cc
$ g++ -g -Wall -shared -o libtest-1.so test1.cc
• Compile the application and link it against the first
version of the library, creating the test-app
binary:
$ g++ -g -Wall -o test-app -L. -ltest-0.so test-app.cc
• Now, use abicompat
to see if libtest-1.so is ABI
compatible with app, with respect to the ABI of
libtest-0.so:
$ abicompat test-app libtest-0.so libtest-1.so
ELF file 'test-app' might not be ABI compatible with 'libtest-1.so' due to differences with 'libtest-0.so' below:
Functions changes summary: 0 Removed, 2 Changed, 0 Added functions
Variables changes summary: 0 Removed, 0 Changed, 0 Added variable
2 functions with some indirect sub-type change:
[C]'function foo* first_func()' has some indirect sub-type changes:
return type changed:
in pointed to type 'struct foo':
size changed from 32 to 64 bits
1 data member insertion:
'char foo::m1', at offset 32 (in bits)
[C]'function void second_func(foo&)' has some indirect sub-type changes:
parameter 0 of type 'foo&' has sub-type changes:
referenced type 'struct foo' changed, as reported earlier
$
• Now use the weak mode of abicompat, that is, providing
just the application and the new version of the library:
$ abicompat --weak-mode test-app libtest-1.so
functions defined in library
'libtest-1.so'
have sub-types that are different from what application
'test-app'
expects:
function foo* first_func():
return type changed:
in pointed to type 'struct foo':
size changed from 32 to 64 bits
1 data member insertion:
'char foo::m1', at offset 32 (in bits)
$
abilint
abilint parses the native XML representation of an ABI as emitted
by abidw. Once it has parsed the XML representation of the ABI,
abilint
builds and in-memory model from it. It then tries to
save it back to an XML form, to standard output. If that
read-write operation succeeds chances are the input XML ABI
representation is meaningful.
Note that the main intent of this tool to help debugging issues
in the underlying Libabigail library.
Note also that abilint
can also read an ELF input file, build the
in-memory model for its ABI, and serialize that model back into
XML to standard output. In that case, the ELF input file must be
accompanied with its debug information in the DWARF format.
Invocation
abilint [options] [<abi-file1>]
Options
• --help
Display a short help message and exits.
• --version | -v
Display the version of the program and exit.
• --debug-info-dir
<path>
When reading an ELF input file which debug information is
split out into a separate file, this options tells abilint
where to find that separate debug information file.
Note that path must point to the root directory under which
the debug information is arranged in a tree-like manner.
Under Red Hat based systems, that directory is usually
<root>/usr/lib/debug
.
Note also that this option is not mandatory for split debug
information installed by your system's package manager
because then abidiff
knows where to find it.
• --diff
For XML inputs, perform a text diff between the input and
the memory model saved back to disk. This can help to spot
issues in the handling of the XML format by the underlying
Libabigail library.
• --noout
Do not display anything on standard output. The return code
of the command is the only way to know if the command
succeeded.
• --suppressions | suppr
<path-to-suppression-specifications-file>
Use a suppression specification file located at
path-to-suppression-specifications-file. Note that this
option can appear multiple times on the command line. In
that case, all of the provided suppression specification
files are taken into account. ABI artifacts matched by the
suppression specifications are suppressed from the output of
this tool.
• --headers-dir | --hd
<headers-directory-path-1>
Specifies where to find the public headers of the first
shared library that the tool has to consider. The tool will
thus filter out types that are not defined in public
headers.
• --header-file | --hf
<header-file-path>
Specifies where to find one of the public headers of the abi
file that the tool has to consider. The tool will thus
filter out types that are not defined in public headers.
• --stdin | --
Read the input content from standard input.
• --tu
Expect the input XML to represent a single translation unit.
fedabipkgdiff
fedabipkgdiff
compares the ABI of shared libraries in Fedora
packages. It's a convenient way to do so without having to
manually download packages from the Fedora Build System.
fedabipkgdiff
knows how to talk with the Fedora Build System to
find the right packages versions, their associated debug
information and development packages, download them, compare
their ABI locally, and report about the possible ABI changes.
Note that by default, this tool reports ABI changes about types
that are defined in public header files found in the development
packages associated with the packages being compared. It also
reports ABI changes about functions and global variables whose
symbols are defined and exported in the ELF binaries found in the
packages being compared.
Invocation
fedabipkgdiff [option] <NVR> ...
Environment
fedabipkgdiff loads two default suppression specifications files,
merges their content and use it to filter out ABI change reports
that might be considered as false positives to users.
• Default system-wide suppression specification file
It's located by the optional environment variable
LIBABIGAIL_DEFAULT_SYSTEM_SUPPRESSION_FILE. If that
environment variable is not set, then fedabipkgdiff tries to
load the suppression file
$libdir/libabigail/libabigail-default.abignore. If that file
is not present, then no default system-wide suppression
specification file is loaded.
• Default user suppression specification file.
It's located by the optional environment
LIBABIGAIL_DEFAULT_USER_SUPPRESSION_FILE. If that environment
variable is not set, then fedabipkgdiff tries to load the
suppression file $HOME/.abignore. If that file is not present,
then no default user suppression specification is loaded.
Options
• --help | -h
Display a short help about the command and exit.
• --dry-run
Don't actually perform the ABI comparison. Details about
what is going to be done are emitted on standard output.
• --debug
Emit debugging messages about the execution of the program.
Details about each method invocation, including input
parameters and returned values, are emitted.
• --traceback
Show traceback when an exception raised. This is useful for
developers of the tool itself to know more exceptional
errors.
• --server
<URL>
Specifies the URL of the Koji XMLRPC service the tool talks
to. The default value of this option is
http://koji.fedoraproject.org/kojihub .
• --topurl
<URL>
Specifies the URL of the package store the tool downloads
RPMs from. The default value of this option is
https://kojipkgs.fedoraproject.org .
• --from
<distro>
Specifies the name of the baseline Fedora distribution in
which to find the first build that is used for comparison.
The distro
value can be any valid value of the RPM macro
%{?dist}
for Fedora, for example, fc4
, fc23
, fc25
.
• --to
<distro>
Specifies the name of the Fedora distribution in which to
find the build that is compared against the baseline
specified by option --from
. The distro
value could be any
valid value of the RPM macro %{?dist}
for Fedora, for
example, fc4
, fc23
.
• --all-subpackages
Instructs the tool to also compare the ABI of the binaries
in the sub-packages of the packages specified.
• --dso-only
Compares the ABI of shared libraries only. If this option
is not provided, the tool compares the ABI of all ELF
binaries found in the packages.
• --suppressions
<path-to-suppresions>
Use a suppression specification file located at
path-to-suppressions.
• --no-default-suppression
Do not load the default suppression specification files.
• --no-devel-pkg
Do not take associated development packages into account
when performing the ABI comparison. This makes the tool
report ABI changes about all types that are reachable from
functions and global variables which symbols are defined and
publicly exported in the binaries being compared, even if
those types are not defined in public header files available
from the packages being compared.
• --show-identical-binaries
Show the names of the all binaries compared, including the
binaries whose ABI compare equal. By default, when this
option is not provided, only binaries with ABI changes are
mentionned in the output.
• --abipkgdiff
<path/to/abipkgdiff>
Specify an alternative abipkgdiff instead of the one
installed in system.
• --clean-cache-before
Clean cache before ABI comparison.
• --clean-cache-after
Clean cache after ABI comparison.
• --clean-cache
If you want to clean cache both before and after ABI
comparison, --clean-cache
is the convenient way for you to
save typing of two options at same time.
Note that a build is a specific version and release of an RPM
package. It's specified by its the package name, version and
release. These are specified by the Fedora Naming Guidelines
Return value
The exit code of the abipkgdiff
command is either 0 if the ABI of
the binaries compared are equivalent, or non-zero if they differ
or if the tool encountered an error.
In the later case, the value of the exit code is the same as for
the abidiff tool.
Use cases
Below are some usage examples currently supported by
fedabipkgdiff
.
1. Compare the ABI of binaries in a local package against the
ABI of the latest stable package in Fedora 23.
Suppose you have built just built the httpd
package and you
want to compare the ABI of the binaries in this locally
built package against the ABI of the binaries in the latest
http
build from Fedora 23. The command line invocation
would be:
$ fedabipkgdiff --from fc23 ./httpd-2.4.18-2.fc24.x86_64.rpm
2. Compare the ABI of binaries in two local packages.
Suppose you have built two versions of package httpd, and
you want to see what ABI differences between these two
versions of RPM files. The command line invocation would
be:
$ fedabipkgdiff path/to/httpd-2.4.23-3.fc23.x86_64.rpm another/path/to/httpd-2.4.23-4.fc24.x86_64.rpm
All what fedabipkgdiff does happens on local machine
without the need of querying or downloading RPMs from Koji.
3. Compare the ABI of binaries in the latest build of the
httpd
package in Fedora 23
against the ABI of the binaries
in the latest build of the same package in 24.
In this case, note that neither of the two packages are
available locally. The tool is going to talk with the
Fedora Build System, determine what the versions and
releases of the latest packages are, download them and
perform the comparison locally. The command line
invocation would be:
$ fedabipkgdiff --from fc23 --to fc24 httpd
4. Compare the ABI of binaries of two builds of the httpd
package, designated their versions and releases.
If we want to do perform the ABI comparison for all the
processor architectures supported by Fedora the command
line invocation would be:
$ fedabipkgdiff httpd-2.8.14.fc23 httpd-2.8.14.fc24
But if we want to perform the ABI comparison for a specific
architecture, say, x86_64, then the command line invocation
would be:
$ fedabipkgdiff httpd-2.8.14.fc23.x86_64 httpd-2.8.14.fc24.x86_64
5. If the use wants to also compare the sub-packages of a
given package, she can use the --all-subpackages option.
The first command of the previous example would thus look
like:
$ fedabipkgdiff --all-subpackages httpd-2.8.14.fc23 httpd-2.8.14.fc24