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

COPYRIGHT

       2014, Red Hat, Inc.

                                          March 10, 2016                            LIBABIGAIL(7)