abicompat(1) — Linux manual page

NAME | INVOCATION | OPTIONS | RETURN VALUES | USAGE EXAMPLES | AUTHOR | COPYRIGHT | COLOPHON

ABICOMPAT(1)                   Libabigail                   ABICOMPAT(1)

NAME         top

       abicompat - check ABI compatibility

       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         top

          abicompat [options] [<application> <shared-library-first-version> <shared-library-second-version>]

OPTIONS         top

--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.

          • --btf

            When comparing binaries, extract ABI information from BTF
            debug information, if present.

          • --ctf

            When comparing binaries, extract ABI information from CTF
            debug information, if present.

          • --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.

          • --ignore-soname

            Ignore differences in the SONAME when doing a comparison

          • --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         top

       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         top

          • 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)

                  $

AUTHOR         top

       Dodji Seketeli

COPYRIGHT         top

       2014-2022, Red Hat, Inc.

COLOPHON         top

       This page is part of the libabigail (ABI Generic Analysis and
       Instrumentation Library) project.  Information about the project
       can be found at ⟨https://sourceware.org/libabigail/⟩.  If you
       have a bug report for this manual page, see
       ⟨http://sourceware.org/bugzilla/enter_bug.cgi?product=libabigail⟩.
       This page was obtained from the project's upstream Git repository
       ⟨git://sourceware.org/git/libabigail.git⟩ on 2024-06-14.  (At
       that time, the date of the most recent commit that was found in
       the repository was 2024-05-31.)  If you discover any rendering
       problems in this HTML version of the page, or you believe there
       is a better or more up-to-date source for the page, or you have
       corrections or improvements to the information in this COLOPHON
       (which is not part of the original manual page), send a mail to
       [email protected]

                              Jun 14, 2024                  ABICOMPAT(1)