xenial (7) libabigail.7.gz

Provided by: abigail-doc_1.0~rc3-1_all bug

NAME

       libabigail - Library to analyze and compare ELF ABIs

OVERVIEW OF LIBABIGAIL

       Libabigail stands for the Application Binary Interface Generic Analysis and Instrumentation Library.

       It  aims  at  helping developers and software distributors to spot some ABI-related issues like interface
       incompatibility in ELF shared libraries.

       The type of interface incompatibilities that libabigail focuses on is related to changes on the  exported
       ELF  functions  and  variables symbols, as well as layout and size changes of data types of the functions
       and variables exported by shared libraries.

       In other words, if the return type of a function exported by a shared library changes in an  incompatible
       way from one version of a given shared library to another, we want libabigail to help people catch that.

       In  more  concrete  terms,  libabigail  can  parse  a  shared library in ELF format, accompanied with its
       associated debug information in DWARF format, build an internal representation of all the  functions  and
       variables  it  exports,  along  with  their  types.  It also builds an internal representation of the ELF
       symbols of these functions and variables.  That information about these exported functions and  variables
       is roughly what we consider as being the ABI of the shared library, at least, in the scope of Libabigail.

       Aside  of this internal representation, libabigail provides facilities to perform deep comparisons of two
       ABIs.  That is, it can compare the types of two sets of functions or variables and represents the  result
       in a way that allows it to emit textual reports about the differences.

       This allows us to write tools like abidiff that can compare the ABI of two shared libraries and represent
       the result in a meaningful enough way to help us spot ABI incompatibilities.

TOOLS

   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.

       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>

   Options--help | -h

            Display a short help about the command and exit.

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

            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.

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

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

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

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

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

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

       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>

   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.

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

          • --dso-only

            Compare ELF files that are shared libraries, only.  Do not compare executable files, for instance.

          • --redundant
              In  the  diff reports, do display redundant changes.  A redundant change is a change that has been
              displayed elsewhere in a given report.

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

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

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

   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.

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

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

                  $

   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.

   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.

            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.

          • --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
              Do not show information about where in the second shared library the respective type was changed.

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

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

   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.

          • --stdin | --

            Read the input content from standard input.

          • --tu

            Expect the input XML to represent a single translation unit.

CONCEPTS

   ABI artifacts
       An  ABI artifact is a relevant part of the ABI of a shared library or program.  Examples of ABI artifacts
       are exported types, variables, functions, or ELF symbols exported by a shared library.

   Harmful changes
       A change in the diff report is considered harmful if it might cause ABI compatibility issues.   That  is,
       it  might  prevent an application dynamically linked against a given version of a library to keep working
       with the changed subsequent versions of the same library.

   Harmless changes
       A change in the diff report is considered harmless if it will not  cause  any  ABI  compatibility  issue.
       That is, it will not prevent an application dynamically linked against given version of a library to keep
       working with the changed subsequent versions of the same library.

       By default, abidiff filters harmless changes from the diff report.

   Suppression specifications
   Definition
       A suppression specification file is a way for a user to instruct abidiff to avoid  emitting  reports  for
       changes involving certain ABI artifacts.

       It  contains  directives  (or  specifications)  that  describe the set of ABI artifacts to avoid emitting
       change reports about.

   Introductory examples
       Its syntax is based on a simplified and customized form of Ini File Syntax.   For  instance,  to  specify
       that change reports on a type named FooPrivateType should be suppressed, one could write this suppression
       specification:

          [suppress_type]
            name = FooPrivateType

       If we want to ensure that only change reports about structures named FooPrivateType should be suppressed,
       we could write:

          [suppress_type]
            type_kind = struct
            name = FooPrivateType

       But  we  could also want to suppress change reports avoid typedefs named FooPrivateType.  In that case we
       would write:

          [suppress_type]
            type_kind = typedef
            name = FooPrivateType

       Or, we could want to  suppress  change  reports  about  all  struct  which  names  end  with  the  string
       "PrivateType":

          [suppress_type]
            type_kind = struct
            name_regexp = ^.*PrivateType

       Let's now look at the generic syntax of suppression specification files.

   Syntax
   Properties
       More  generally,  the  format  of  suppression  lists is organized around the concept of property.  Every
       property has a name and a value, delimited by the = sign.  E.g:

          name = value

       Leading and trailing white spaces are ignored around property names and values.

   Regular expressions
       The value of some properties might be a regular expression.  In that case,  they  must  comply  with  the
       syntax of extended POSIX regular expressions.  Note that Libabigail uses the regular expression engine of
       the GNU C Library.

   Escaping a character in a regular expression
       When trying to match a string that contains a * character, like in the pointer type  int*,  one  must  be
       careful  to  notice  that the character * is a special character in the extended POSIX regular expression
       syntax.  And that character must be  escaped  for  the  regular  expression  engine.   Thus  the  regular
       expression that would match the string int* in a suppression file should be

          int\\*

       Wait; but then why the two \ characters?  Well, because the \ character is a special character in the Ini
       File Syntax used for specifying suppressions.  So it must be escaped as well, so that the Ini File parser
       leaves  a  \  character intact in the data stream that is handed to the regular expression engine.  Hence
       the \\ targeted at the Ini File parser.

       So, in short, to escape a character in a regular expression, always prefix  the  character  with  the  \\
       sequence.

   Sections
       Properties  are  then  grouped into arbitrarily named sections that shall not be nested.  The name of the
       section is on a line by itself and is surrounded by square brackets, i.e:

          [section_name]
          property1_name = property1_value
          property2_name = property2_value

       A section might or might not have properties.  Sections that expect to  have  properties  and  which  are
       found  nonetheless  empty are just ignored.  Properties that are not recognized by the reader are ignored
       as well.

   Section names
       Each different section can be thought of as being a directive to suppress diff reports for  a  particular
       kind of ABI artifact.

   [suppress_type]
       This directive suppresses report messages about a type change.

       Note  that  for  the  [suppress_type] directive to work, at least one of the following properties must be
       provided:
          name, name_regexp, type_kind, source_location_not_in, source_location_not_regexp.

       If none of the following properties  are  provided,  then  the  [suppression_type]  directive  is  simply
       ignored.

       The potential properties of this sections are listed below:

       • file_name_regexp

         Usage:

         file_name_regexp = <regular-expression>

         Suppresses  change reports about ABI artifacts that are defined in a binary file which name matches the
         regular expression specified as value of this property.

       • soname_regexp

         Usage:

         soname_regexp = <regular-expression>

         Suppresses change reports about ABI artifact that are defined in a shared library which SONAME  matches
         the regular expression specified as value of this property.

       • name_regexp
          Usage:

          name_regexp = <regular-expression>

          Suppresses change reports involving types whose name matches the regular expression specified as value
          of this property.

       • name
          Usage:

          name = <a-value>

          Suppresses change reports involving types whose name equals the value of this property.

       • type_kind
          Usage:

              type_kind = class | struct | union | enum |
                     array | typedef | builtin

          Suppresses change reports involving a certain kind of type.  The  kind  of  type  to  suppress  change
          reports for is specified by the possible values listed above:

              •

                class: suppress change reports for class types. Note that
                       even  if  class  types  don't  exist  for C, this value still triggers the suppression of
                       change reports for struct types, in C.  In C++ however, it should do what it suggests.

              •

                struct: suppress change reports for struct types in C or C++.
                       Note that the value class above is a super-set of this one.

              • union: suppress change reports for union types.

              • enum: suppress change reports for enum types.

              • array: suppress change reports for array types.

              • typedef: suppress change reports for typedef types.

              • builtin: suppress change reports for built-in (or native) types.  Example of built-in types  are
                char, int, unsigned int, etc.

       • source_location_not_in
          Usage:
              source_location_not_in = <list-of-file-paths>

          Suppresses  change reports involving a type which is defined in a file which path is NOT listed in the
          value list-of-file-paths.  Note that the value is a comma-separated  list  of  file  paths  e.g,  this
          property

              source_location_not_in = libabigail/abg-ir.h, libabigail/abg-dwarf-reader.h

          suppresses  change  reports about all the types that are NOT defined in header files whose path end up
          with the strings libabigail/abg-ir.h or libabigail/abg-dwarf-reader.h.

       • source_location_not_regexp
          Usage:
              source_location_not_regexp = <regular-expression>

          Suppresses change reports involving a type which is defined in a file which path does  NOT  match  the
          regular expression provided as value of the property. E.g, this property

              source_location_not_regexp = libabigail/abg-.*\\.h

          suppresses  change  reports  involving  all  the types that are NOT defined in header files whose path
          match the regular expression provided a value of the property.

       • has_data_member_inserted_at
          Usage:
              has_data_member_inserted_at = <offset-in-bit>

          Suppresses change reports involving a type which has at least one data member inserted  at  an  offset
          specified by the property value offset-in-bit.  The value offset-in-bit is either:

                 • an  integer  value, expressed in bits, which denotes the offset of the insertion point of the
                   data member, starting from the beginning of the relevant structure or class.

                 • the keyword end which is a named constant which value equals the offset of the end of the  of
                   the structure or class.

                 • the  function  call expression offset_of(data-member-name) where data-member-name is the name
                   of a given data member of the relevant structure or class.  The value of this  function  call
                   expression  is  an  integer  that  represents  the  offset  of  the  data  member  denoted by
                   data-member-name.

                 • the function call expression offset_after(data-member-name)  where  data-member-name  is  the
                   name  of  a given data member of the relevant structure or class.  The value of this function
                   call expression is an integer that represents the offset of the point that comes right  after
                   the region occupied by the data member denoted by data-member-name.

       • has_data_member_inserted_between
          Usage:
              has_data_member_inserted_between = {<range-begin>, <range-end>}

          Suppresses change reports involving a type which has at least one data mber inserted at an offset that
          is comprised in the range between range-begin`` and range-end.  Please note  that  each  of  the  lues
          range-begin and range-end can be of the same form as the has_data_member_inserted_at property above.

          Usage examples of this properties are:

              has_data_member_inserted_between = {8, 64}

          or:

              has_data_member_inserted_between = {16, end}

          or:

              has_data_member_inserted_between = {offset_after(member1), end}

       • has_data_members_inserted_between
          Usage:
              has_data_members_inserted_between = {<sequence-of-ranges>}

          Suppresses  change  reports involving a type which has multiple data member inserted in various offset
          ranges.  A usage example of this property is, for instance:

              has_data_members_inserted_between = {{8, 31}, {72, 95}}

          This usage example suppresses change reports involving a type which has data members inserted  in  bit
          offset   ranges   [8   31]   and   [72   95].    The   length  of  the  sequence  of  ranges  or  this
          has_data_members_inserted_between is not bounded; it can be as long as the system can cope with.   The
          values  of  the  boundaries  of the ranges are of the same kind as for the has_data_member_inserted_at
          property above.

          Another usage example of this property is thus:

              has_data_members_inserted_between =
                {
                     {offset_after(member0), offset_of(member1)},
                     {72, end}
                }

       • accessed_through
          Usage:
              accessed_through = <some-predefined-values>

          Suppress change reports involving a type which is referred to either directly or through a pointer  or
          a reference.  The potential values of this property are the predefined keywords below:

              • direct

                So if the [suppress_type] contains the property description:

                   accessed_through = direct

                then  changes  about  a  type  that  is  referred-to  directly  (i.e, not through a pointer or a
                reference) are going to be suppressed.

              • pointer

                If the accessed_through property is set to the value pointer then changes about a type  that  is
                referred-to through a pointer are going to be suppressed.

              • reference

                If the accessed_through property is set to the value reference then changes about a type that is
                referred-to through a reference are going to be suppressed.

              • reference-or-pointer

                If the accessed_through property is set to the value reference-or-pointer then changes  about  a
                type that is referred-to through either a reference or a pointer are going to be suppressed.

          For  an  extensive  example  of  how  to  use  this property, please check out the example below about
          suppressing change reports about types accessed either directly or through pointers.

       • label
          Usage:
              label = <some-value>

          Define a label for the section.  A label is just an informative string that might be used  by  abidiff
          to refer to a type suppression in error messages.

   [suppress_function]
       This directive suppresses report messages about changes on a set of functions.

       Note that for the [suppress_function] directive to work, at least one of the following properties must be
       provided:
          label,   name,   name_regexp,   parameter,    return_type_name,    symbol_name,    symbol_name_regexp,
          symbol_version, symbol_version_regexp.

       If  none  of  the  following properties are provided, then the [suppression_function] directive is simply
       ignored.

       The potential properties of this sections are:

       • label
          Usage:
              label = <some-value>

          This property is the same as the label property defined above.

       • name
          Usage:
              name = <some-value>

          Suppresses change reports involving functions whose name equals the value of this property.

       • name_regexp
          Usage:
              name_regexp = <regular-expression>

          Suppresses change reports involving functions whose name matches the regular expression  specified  as
          value of this property.

          Let's consider the case of functions that have several symbol names.  This happens when the underlying
          symbol for the function has aliases.  Each symbol name is actually one alias name.

          In this case, if the regular expression matches the name of at least one of the aliases names, then it
          must  match the names of all of the aliases of the function for the directive to actually suppress the
          diff reports for said function.

       • change_kind
          Usage:
              change_kind = <predefined-possible-values>

          Specifies the kind of changes this suppression specification should apply to.  The possible values  of
          this property as well as their meaning are listed below:

              • function-subtype-change

                This  suppression  specification applies to functions that which have at least one sub-type that
                has changed.

              • added-function

                This suppression specification applies to functions that have been added to the binary.

              • deleted-function

                This suppression specification applies to functions that have been removed from the binary.

              • all

                This suppression specification applies to functions that have all of the  changes  above.   Note
                that not providing the change_kind property at all is equivalent to setting it to the value all.

       • parameter
          Usage:

          parameter = <function-parameter-specification>

          Suppresses  change  reports  involving  functions  whose  parameters match the parameter specification
          indicated as value of this property.

          The format of the function parameter specification is:

          ' <parameter-index> <space> <type-name-or-regular-expression>

          That is, an apostrophe followed by a number that is the index of the parameter,  followed  by  one  of
          several  spaces,  followed  by  either  the name of the type of the parameter, or a regular expression
          describing a family of parameter type names.

          If the parameter type name is designated by a regular expression, then said regular expression must be
          enclosed between two slashes; like /some-regular-expression/.

          The  index of the first parameter of the function is zero.  Note that for member functions (methods of
          classes), the this is the first parameter that comes after the implicit "this" pointer parameter.

          Examples of function parameter specifications are:

              '0 int

          Which means, the parameter at index 0, whose type name is int.

              '4 unsigned char*

          Which means, the parameter at index 4, whose type name is unsigned char*.

              '2 /^foo.*&/

          Which means, the parameter at index 2, whose type name starts with the string "foo" and ends  with  an
          '&'.   In other words, this is the third parameter and it's a reference on a type that starts with the
          string "foo".

       • return_type_name
          Usage:
              return_type_name = <some-value>

          Suppresses change reports involving functions  whose  return  type  name  equals  the  value  of  this
          property.

       • return_type_regexp
          Usage:
              return_type_regexp = <regular-expression>

          Suppresses  change  reports  involving functions whose return type name matches the regular expression
          specified as value of this property.

       • symbol_name
          Usage:
              symbol_name = <some-value>

          Suppresses change reports involving functions whose symbol name equals the value of this property.

       • symbol_name_regexp
          Usage:

          symbol_name_regexp = <regular-expression>

          Suppresses change reports involving  functions  whose  symbol  name  matches  the  regular  expression
          specified as value of this property.

          Let's consider the case of functions that have several symbol names.  This happens when the underlying
          symbol for the function has aliases.  Each symbol name is actually one alias name.

          In this case, the regular expression must match the names of all of the aliases of  the  function  for
          the directive to actually suppress the diff reports for said function.

       • symbol_version
          Usage:
              symbol_version = <some-value>

          Suppresses change reports involving functions whose symbol version equals the value of this property.

       • symbol_version_regexp
          Usage:
              symbol_version_regexp = <regular-expression>

          Suppresses  change  reports  involving  functions  whose symbol version matches the regular expression
          specified as value of this property.

   [suppress_variable]
       This directive suppresses report messages about changes on a set of variables.

       Note that for the [suppress_variable] directive to work, at least one of the following properties must be
       provided:
          label, name, name_regexp, symbol_name, symbol_name_regexp, symbol_version, symbol_version_regexp.

       If  none  of  the  following  properties  are  provided,  then the [suppres_variable] directive is simply
       ignored.

       The potential properties of this sections are:

       • label
          Usage:
              label = <some-value>

          This property is the same as the label property defined above.

       • name
          Usage:
              name = <some-value>

          Suppresses change reports involving variables whose name equals the value of this property.

       • name_regexp
          Usage:
              name_regexp = <regular-expression>

          Suppresses change reports involving variables whose name matches the regular expression  specified  as
          value of this property.

       • change_kind
          Usage:
              change_kind = <predefined-possible-values>

          Specifies  the kind of changes this suppression specification should apply to.  The possible values of
          this property as well as their meaning are the same as  when  it's  used  in  the  [suppress_function]
          section.

       • symbol_name
          Usage:
              symbol_name = <some-value>

          Suppresses change reports involving variables whose symbol name equals the value of this property.

       • symbol_name_regexp
          Usage:
              symbol_name_regexp = <regular-expression>

          Suppresses  change  reports  involving  variables  whose  symbol  name  matches the regular expression
          specified as value of this property.

       • symbol_version
          Usage:
              symbol_version = <some-value>

          Suppresses change reports involving variables whose symbol version equals the value of this property.

       • symbol_version_regexp
          Usage:
              symbol_version_regexp = <regular-expression>

          Suppresses change reports involving variables whose symbol  version  matches  the  regular  expression
          specified as value of this property.

       • type_name
          Usage:
              type_name = <some-value>

          Suppresses change reports involving variables whose type name equals the value of this property.

       • type_name_regexp
          Usage:
              type_name_regexp = <regular-expression>

          Suppresses change reports involving variables whose type name matches the regular expression specified
          as value of this property.

   Comments
       ; or # ASCII character at the beginning of a line indicates a comment.  Comment lines are ignored.

   Code examples
       1. Suppressing change reports about types.

          Suppose we have a library named libtest1-v0.so which contains this very useful code:

             $ cat -n test1-v0.cc
                  1  // A forward declaration for a type considered to be opaque to
                  2  // function foo() below.
                  3  struct opaque_type;
                  4
                  5  // This function cannot touch any member of opaque_type.  Hence,
                  6  // changes to members of opaque_type should not impact foo, as far as
                  7  // ABI is concerned.
                  8  void
                  9  foo(opaque_type*)
                 10  {
                 11  }
                 12
                 13  struct opaque_type
                 14  {
                 15    int member0;
                 16    char member1;
                 17  };
             $

       Let's change the layout of struct opaque_type by inserting a data member around line 15, leading to a new
       version of the library, that we shall name libtest1-v1.so:

          $ cat -n test1-v1.cc
               1  // A forward declaration for a type considered to be opaque to
               2  // function foo() below.
               3  struct opaque_type;
               4
               5  // This function cannot touch any member of opaque_type;  Hence,
               6  // changes to members of opaque_type should not impact foo, as far as
               7  // ABI is concerned.
               8  void
               9  foo(opaque_type*)
              10  {
              11  }
              12
              13  struct opaque_type
              14  {
              15    char added_member; // <-- a new member got added here now.
              16    int member0;
              17    char member1;
              18  };
          $

       Let's  compile  both  examples.   We  shall  not forget to compile them with debug information generation
       turned on:

          $ g++ -shared -g -Wall -o libtest1-v0.so test1-v0.cc
          $ g++ -shared -g -Wall -o libtest1-v1.so test1-v1.cc

       Let's ask abidiff which ABI differences it sees between libtest1-v0.so and libtest1-v1.so:

          $ abidiff libtest1-v0.so libtest1-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(opaque_type*)' has some indirect sub-type changes:
              parameter 0 of type 'opaque_type*' has sub-type changes:
                in pointed to type 'struct opaque_type':
                  size changed from 64 to 96 bits
                  1 data member insertion:
                    'char opaque_type::added_member', at offset 0 (in bits)
                  2 data member changes:
                   'int opaque_type::member0' offset changed from 0 to 32
                   'char opaque_type::member1' offset changed from 32 to 64

       So abidiff reports that the opaque_type's layout has  changed  in  a  significant  way,  as  far  as  ABI
       implications  are  concerned,  in  theory.   After  all,  a  sub-type (struct opaque_type) of an exported
       function (foo()) has seen its layout change.  This might have non negligible ABI  implications.   But  in
       practice  here,  the  programmer  of the litest1-v1.so library knows that the "soft" contract between the
       function foo() and the type struct opaque_type is to stay away from the data members  of  the  type.   So
       layout changes of struct opaque_type should not impact foo().

       Now  to teach abidiff about this soft contract and have it avoid emitting what amounts to false positives
       in this case, we write the suppression specification file below:

          $ cat test1.suppr
          [suppress_type]
            type_kind = struct
            name = opaque_type

       Translated in plain English, this suppression specification would read: "Do not emit change reports about
       a struct which name is opaque_type".

       Let's  now  invoke  abidiff  on the two versions of the library again, but this time with the suppression
       specification:

          $ abidiff --suppressions test1.suppr libtest1-v0.so libtest1-v1.so
          Functions changes summary: 0 Removed, 0 Changed (1 filtered out), 0 Added function
          Variables changes summary: 0 Removed, 0 Changed, 0 Added variable

       As you can see, abidiff does not report the change anymore; it tells us that it was filtered out instead.

       Suppressing change reports about types with data member insertions

       Suppose the first version of a library named libtest3-v0.so has this source code:

          /* Compile this with:
               gcc -g -Wall -shared -o libtest3-v0.so test3-v0.c
           */

          struct S
          {
            char member0;
            int member1; /*
                            between member1 and member2, there is some padding,
                            at least on some popular platforms.  On
                            these platforms, adding a small enough data
                            member into that padding shouldn't change
                            the offset of member1.  Right?
                          */
          };

          int
          foo(struct S* s)
          {
            return s->member0 + s->member1;
          }

       Now, suppose the second version of the library named libtest3-v1.so has this source code in which a  data
       member has been added in the padding space of struct S and another data member has been added at its end:

          /* Compile this with:
               gcc -g -Wall -shared -o libtest3-v1.so test3-v1.c
           */

          struct S
          {
            char member0;
            char inserted1; /* <---- A data member has been added here...  */
            int member1;
            char inserted2; /* <---- ... and another one has been added here.  */
          };

          int
          foo(struct S* s)
          {
            return s->member0 + s->member1;
          }

       In  libtest3-v1.so,  adding  char  data  members S::inserted1 and S::inserted2 can be considered harmless
       (from an ABI compatibility perspective), at least on the x86 platform, because that  doesn't  change  the
       offsets of the data members S::member0 and S::member1.  But then running abidiff on these two versions of
       library yields:

          $ abidiff libtest3-v0.so libtest3-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 int foo(S*)' has some indirect sub-type changes:
              parameter 0 of type 'S*' has sub-type changes:
                in pointed to type 'struct S':
                  type size changed from 64 to 96 bits
                  2 data member insertions:
                    'char S::inserted1', at offset 8 (in bits)
                    'char S::inserted2', at offset 64 (in bits)
          $

       That is, abidiff shows us the two changes, even though we (the developers of that very involved  library)
       know that these changes are harmless in this particular context.

       Luckily,  we  can  devise a suppression specification that essentially tells abidiff to filter out change
       reports about adding a data member between S::member0 and S::member1, and adding a data member at the end
       of  struct  S.   We  have  written such a suppression specification in a file called test3-1.suppr and it
       unsurprisingly looks like:

          [suppress_type]
            name = S
            has_data_member_inserted_between = {offset_after(member0), offset_of(member1)}
            has_data_member_inserted_at = end

       Now running abidiff with this suppression specification yields:

          $ ../build/tools/abidiff --suppressions test3-1.suppr libtest3-v0.so libtest3-v1.so
          Functions changes summary: 0 Removed, 0 Changed (1 filtered out), 0 Added function
          Variables changes summary: 0 Removed, 0 Changed, 0 Added variable

          $

       Hooora! \o/ (I guess)

       Suppressing change reports about types accessed either directly or through pointers

       Suppose we have a first version of an object file which source code is the file widget-v0.cc below:

          // Compile with: g++ -g -c widget-v0.cc

          struct widget
          {
            int x;
            int y;

            widget()
              :x(), y()
            {}
          };

          void
          fun0(widget*)
          {
            // .. do stuff here.
          }

          void
          fun1(widget&)
          {
            // .. do stuff here ..
          }

          void
          fun2(widget w)
          {
            // ... do other stuff here ...
          }

       Now suppose in the second version of that file, named widget-v1.cc, we have added some  data  members  at
       the end of the type struct widget; here is what the content of that file would look like:

          // Compile with: g++ -g -c widget-v1.cc

          struct widget
          {
            int x;
            int y;
            int w; // We have added these two new data members here ..
            int h; // ... and here.

            widget()
              : x(), y(), w(), h()
            {}
          };

          void
          fun0(widget*)
          {
            // .. do stuff here.
          }

          void
          fun1(widget&)
          {
            // .. do stuff here ..
          }

          void
          fun2(widget w)
          {
            // ... do other stuff here ...
          }

       When  we invoke abidiff on the object files resulting from the compilation of the two file above, here is
       what we get:

           $ abidiff widget-v0.o widget-v1.o
           Functions changes summary: 0 Removed, 2 Changed (1 filtered out), 0 Added functions
           Variables changes summary: 0 Removed, 0 Changed, 0 Added variable

           2 functions with some indirect sub-type change:

             [C]'function void fun0(widget*)' has some indirect sub-type changes:
               parameter 1 of type 'widget*' has sub-type changes:
                 in pointed to type 'struct widget':
                   type size changed from 64 to 128 bits
                   2 data member insertions:
                     'int widget::w', at offset 64 (in bits)
                     'int widget::h', at offset 96 (in bits)

             [C]'function void fun2(widget)' has some indirect sub-type changes:
               parameter 1 of type 'struct widget' has sub-type changes:
                 details were reported earlier
          $

       I guess a little bit of explaining is due here.  abidiff detects that two data member got  added  at  the
       end  of  struct widget.  it also tells us that the type change impacts the exported function fun0() which
       uses the type struct widget through a pointer, in its signature.

       Careful readers will notice that the change to struct widget also impacts the exported  function  fun1(),
       that  uses  type struct widget through a reference.  But then abidiff doesn't tell us about the impact on
       that function fun1() because it has evaluated that change as being redundant with the change it  reported
       on fun0().  It has thus filtered it out, to avoid cluttering the output with noise.

       Redundancy  detection  and  filtering is fine and helpful to avoid burying the important information in a
       sea of noise.  However, it must be treated with care, by fear of mistakenly filtering  out  relevant  and
       important information.

       That  is  why  abidiff tells us about the impact that the change to struct widget has on function fun2().
       In this case, that function uses the type struct widget directly (in its signature).  It does not use  it
       via a pointer or a reference.  In this case, the direct use of this type causes fun2() to be exposed to a
       potentially harmful ABI change.  Hence, the report about fun2() is not filtered  out,  even  though  it's
       about that same change on struct widget.

       To  go further in suppressing reports about changes that are harmless and keeping only those that we know
       are harmful, we would like to go tell abidiff to suppress reports about  this  particular  struct  widget
       change  when  it  impacts uses of struct widget through a pointer or reference.  In other words, suppress
       the change reports about fun0() and fun1().  We would then write this suppression specification, in  file
       widget.suppr:

          [suppress_type]
            name = widget
            type_kind = struct
            has_data_member_inserted_at = end
            accessed_through = reference-or-pointer

            # So this suppression specification says to suppress reports about
            # the type 'struct widget', if this type was added some data member
            # at its end, and if the change impacts uses of the type through a
            # reference or a pointer.

       Invoking abidiff on widget-v0.o and widget-v1.o with this suppression specification yields:

          $ abidiff --suppressions widget.suppr widget-v0.o widget-v1.o
          Functions changes summary: 0 Removed, 1 Changed (2 filtered out), 0 Added function
          Variables changes summary: 0 Removed, 0 Changed, 0 Added variable

          1 function with some indirect sub-type change:

            [C]'function void fun2(widget)' has some indirect sub-type changes:
              parameter 1 of type 'struct widget' has sub-type changes:
                type size changed from 64 to 128 bits
                2 data member insertions:
                  'int widget::w', at offset 64 (in bits)
                  'int widget::h', at offset 96 (in bits)
          $

       As expected, I guess.

       Suppressing change reports about functions.

       Suppose we have a first version a library named libtest2-v0.so whose source code is:

           $ cat -n test2-v0.cc

            1     struct S1
            2     {
            3       int m0;
            4
            5       S1()
            6         : m0()
            7       {}
            8     };
            9
           10     struct S2
           11     {
           12       int m0;
           13
           14       S2()
           15         : m0()
           16       {}
           17     };
           18
           19     struct S3
           20     {
           21       int m0;
           22
           23       S3()
           24         : m0()
           25       {}
           26     };
           27
           28     int
           29     func(S1&)
           30     {
           31       // suppose the code does something with the argument.
           32       return 0;
           33
           34     }
           35
           36     char
           37     func(S2*)
           38     {
           39       // suppose the code does something with the argument.
           40       return 0;
           41     }
           42
           43     unsigned
           44     func(S3)
           45     {
           46       // suppose the code does something with the argument.
           47       return 0;
           48     }
          $

       And  then we come up with a second version libtest2-v1.so of that library; the source code is modified by
       making the structures S1, S2, S3 inherit another struct:

          $ cat -n test2-v1.cc
                1 struct base_type
                2 {
                3   int m_inserted;
                4 };
                5
                6 struct S1 : public base_type // <--- S1 now has base_type as its base
                7                              // type.
                8 {
                9   int m0;
               10
               11   S1()
               12     : m0()
               13   {}
               14 };
               15
               16 struct S2 : public base_type // <--- S2 now has base_type as its base
               17                              // type.
               18 {
               19   int m0;
               20
               21   S2()
               22     : m0()
               23   {}
               24 };
               25
               26 struct S3 : public base_type // <--- S3 now has base_type as its base
               27                              // type.
               28 {
               29   int m0;
               30
               31   S3()
               32     : m0()
               33   {}
               34 };
               35
               36 int
               37 func(S1&)
               38 {
               39   // suppose the code does something with the argument.
               40   return 0;
               41
               42 }
               43
               44 char
               45 func(S2*)
               46 {
               47   // suppose the code does something with the argument.
               48   return 0;
               49 }
               50
               51 unsigned
               52 func(S3)
               53 {
               54   // suppose the code does something with the argument.
               55   return 0;
               56 }
           $

       Now let's build the two libraries:

          g++ -Wall -g -shared -o libtest2-v0.so test2-v0.cc
          g++ -Wall -g -shared -o libtest2-v0.so test2-v0.cc

       Let's look at the output of abidiff:

          $ abidiff libtest2-v0.so libtest2-v1.so
          Functions changes summary: 0 Removed, 3 Changed, 0 Added functions
          Variables changes summary: 0 Removed, 0 Changed, 0 Added variable

          3 functions with some indirect sub-type change:

            [C]'function unsigned int func(S3)' has some indirect sub-type changes:
              parameter 0 of type 'struct S3' has sub-type changes:
                size changed from 32 to 64 bits
                1 base class insertion:
                  struct base_type
                1 data member change:
                 'int S3::m0' offset changed from 0 to 32

            [C]'function char func(S2*)' has some indirect sub-type changes:
              parameter 0 of type 'S2*' has sub-type changes:
                in pointed to type 'struct S2':
                  size changed from 32 to 64 bits
                  1 base class insertion:
                    struct base_type
                  1 data member change:
                   'int S2::m0' offset changed from 0 to 32

            [C]'function int func(S1&)' has some indirect sub-type changes:
              parameter 0 of type 'S1&' has sub-type changes:
                in referenced type 'struct S1':
                  size changed from 32 to 64 bits
                  1 base class insertion:
                    struct base_type
                  1 data member change:
                   'int S1::m0' offset changed from 0 to 32
          $

       Let's tell abidiff to avoid showing us the differences on the overloads  of  func  that  takes  either  a
       pointer or a reference.  For that, we author this simple suppression specification:

          $ cat -n libtest2.suppr
               1 [suppress_function]
               2   name = func
               3   parameter = '0 S1&
               4
               5 [suppress_function]
               6   name = func
               7   parameter = '0 S2*
          $

       And then let's invoke abidiff with the suppression specification:

          $ ../build/tools/abidiff --suppressions libtest2.suppr libtest2-v0.so libtest2-v1.so
          Functions changes summary: 0 Removed, 1 Changed (2 filtered out), 0 Added function
          Variables changes summary: 0 Removed, 0 Changed, 0 Added variable

          1 function with some indirect sub-type change:

                 [C]'function unsigned int func(S3)' has some indirect sub-type changes:
                   parameter 0 of type 'struct S3' has sub-type changes:
                     size changed from 32 to 64 bits
                     1 base class insertion:
                       struct base_type
                     1 data member change:
                      'int S3::m0' offset changed from 0 to 32

       The suppression specification could be reduced using regular expressions:

          $ cat -n libtest2-1.suppr
                    1   [suppress_function]
                    2     name = func
                    3     parameter = '0 /^S.(&|\\*)/
          $

          $ ../build/tools/abidiff --suppressions libtest2-1.suppr libtest2-v0.so libtest2-v1.so
          Functions changes summary: 0 Removed, 1 Changed (2 filtered out), 0 Added function
          Variables changes summary: 0 Removed, 0 Changed, 0 Added variable

          1 function with some indirect sub-type change:

                 [C]'function unsigned int func(S3)' has some indirect sub-type changes:
                   parameter 0 of type 'struct S3' has sub-type changes:
                     size changed from 32 to 64 bits
                     1 base class insertion:
                       struct base_type
                     1 data member change:
                      'int S3::m0' offset changed from 0 to 32

          $

AUTHOR

       Dodji Seketeli

       2014, Red Hat, Inc.

                                                 March 10, 2016                                    LIBABIGAIL(7)