You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
316 lines
8.9 KiB
316 lines
8.9 KiB
.. _abicompat_label:
|
|
|
|
=========
|
|
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.
|
|
|
|
.. _abicompat_invocation_label:
|
|
|
|
Invocation
|
|
==========
|
|
|
|
::
|
|
|
|
abicompat [options] [<application> <shared-library-first-version> <shared-library-second-version>]
|
|
|
|
.. _abicompat_options_label:
|
|
|
|
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 :ref:`suppression specification <suppr_spec_label>` 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.
|
|
|
|
.. _abicompat_return_value_label:
|
|
|
|
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.
|
|
|
|
.. _abicompat_usage_example_label:
|
|
|
|
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)
|
|
|
|
$
|