# abicompat

## NAME



           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



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



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


* * *