From Fedora Project Wiki

Line 1: Line 1:
 
== Introduction ==
 
== Introduction ==
  
Checking for changes in [http://en.wikipedia.org/wiki/Application_binary_interface Application Binary Interface], or ABI, may be a good idea for a couple of reasons:
+
When a new version of an ELF shared library (that we shall name L) is installed on the system, it's critically important that its [http://en.wikipedia.org/wiki/Application_binary_interface Application Binary Interface] (a.k.a ABI) stays compatible with the ABI of its previous version.  That compatibility ensures that ELF binaries, that [https://en.wikipedia.org/wiki/Linker_%28computing%29 dynamically links] with *L*, keep seeing the ABI they expect from that library L.  Otherwise, if the ABI of the new version of L is incompatible of with the ABI expected by the binaries that link with it, subtle and sometimes hard to debug runtime errors follow.
  
* Upstream does not maintain a soname with version.
+
As maintainers of a package that contains the shared library L, its our duty to ensure that the ABI of the new version L stays compatible with the ABI of the former version L.
* Upstream is not good about maintaining proper ABI compatibility.
 
  
It's important to note that a library's ABI can change even if the [http://en.wikipedia.org/wiki/Application_programming_interface API] does not. This can happen with internal changes to the compiler and/or compiler flags.
+
Thus, comparing the ABI of the new version of a package against its previous version is critical to detect possible incompatibilities, review them and file relevant bugs upstream, should the need arise. That comparison should be part of the normal update process followed by maintainers of packages that contain ELF libraries.
  
== Requirements ==
+
== Hands on ==
  
It is assumed that you already have a [[How_to_create_an_RPM_package#Preparing_your_system|development environment]] setup which can build packages. Other than that all that is required is the tool [https://apps.fedoraproject.org/packages/abi-compliance-checker abi-compliance-checker].
+
There are two main tools tailored for comparing the ABIs of packages: [https://sourceware.org/libabigail/manual/abipkgdiff.html abipkgdiff] and [http://ispras.linuxbase.org/index.php/ABI_compliance_checker abi-compliance-checker]
  
<pre>
+
* [[How_to_check_for_ABI_changes_with_abipkgdiff|Using abipkgdiff]]
$ sudo yum install abi-compliance-checker
+
* [[How_to_check_for_ABI_changes_with_abi_compliance_checker|Using abi-compliance-checker]]
(or as root)
 
# yum install abi-compliance-checker
 
</pre>
 
 
 
== Procedure ==
 
 
 
<code>abi-compliance-checker</code> has a lot of options and while it's not difficult to use it's not necessarily intuitive either. This example is one way to use the tool and should be considered the best practice.
 
 
 
=== Step 1: Preparing ===
 
 
 
First you need to unpack the packages to a location. You can use the these commands directly or add these to a shell script which will be called <code>rpmunpack</code>:
 
<pre>
 
#!/bin/bash
 
 
 
if [ ! -n "$1" ]
 
then
 
  echo "Unpacks an RPM into the current directory."
 
  echo ""
 
  echo "Usage: `basename $0` <package1> [package2]..."
 
fi
 
 
 
for file in $*; do
 
rpm2cpio $file | cpio -idmv
 
done
 
</pre>
 
 
 
Now create a directory structure and unpack the packages:
 
<pre>
 
$ mkdir -p <package>/<version_old>
 
$ mkdir -p <package>/<version_new>
 
$ cd <package>/<version_old>
 
$ rpmunpack <package>-<version_old> <package>-<version_old>-devel
 
$ cd ../<package>/<version_new>
 
$ rpmunpack <package>-<version_new> <package>-<version_new>-devel
 
$ cd ..
 
</pre>
 
 
 
=== Step 2: Dump the ABIs to a file ===
 
 
 
By default <code>abi-compliance-checker</code> will assign the version based on the directories created previously. If it doesn't get it right use the <code>-vnum</code> option to override it.
 
 
 
Execute the following command for both packages:
 
 
 
<pre>
 
$ abi-compliance-checker -l <package> -dump <path to unpacked RPM>
 
</pre>
 
 
 
The <code>-l</code> option needs to stay the same for all operations and is the name used in the resultant html report.
 
 
 
=== Step 3: Compare the to ABI dumps ===
 
 
 
The ABI dumps will be created in a sub-directory of where <code>abi-compliance-checker</code> was run, <code>abi_dumps/<package></code>. To compare the to ABI dumps:
 
 
 
<pre>
 
$ abi-compliance-checker -l <package> -old abi_dumps/<package>/<package>_<version_old>.abi.tar.gz -new abi_dumps/<package>/<package>_<version_old>.abi.tar.gz
 
</pre>
 
 
 
The html report will be created in a directory under <code>compat_reports/<package>/<version_old>_to_<version_new></code>.
 
 
 
== Tips & Tricks ==
 
 
 
{{admon/important|False Positives|<code>abi-compliance-checker</code> is just a tool and doesn't always get it right. The results need to be reviewed as false positives are common. This happens frequently if the old package was compiled with a different version of the compiler or different flags were used. To minimize this, it can be beneficial to rebuild the older package using the same environment as the new package.}}
 
 
 
=== ABI dumps error out ===
 
 
 
This often happens when upstream installs headers for other platforms. Adding the <code>-tolerant</code> option can often work around this problem. As a last resort, simply look through the log and remove the offending header.
 
 
 
== External links ==
 
 
 
[http://upstream-tracker.org/ API/ABI changes analysis for C/C++ libraries].
 
 
 
[http://upstream.rosalinux.ru/java/ API/ABI changes analysis for Java libraries].
 
 
 
[http://upstream.rosalinux.ru/kernel/ API/ABI changes in Linux kernel].
 
 
 
[http://ispras.linuxbase.org/index.php/ABI_compliance_checker ABI compliance checker], tool for checking backward binary and source-level compatibility of a C/C++ library.
 

Revision as of 10:06, 18 November 2015

Introduction

When a new version of an ELF shared library (that we shall name L) is installed on the system, it's critically important that its Application Binary Interface (a.k.a ABI) stays compatible with the ABI of its previous version. That compatibility ensures that ELF binaries, that dynamically links with *L*, keep seeing the ABI they expect from that library L. Otherwise, if the ABI of the new version of L is incompatible of with the ABI expected by the binaries that link with it, subtle and sometimes hard to debug runtime errors follow.

As maintainers of a package that contains the shared library L, its our duty to ensure that the ABI of the new version L stays compatible with the ABI of the former version L.

Thus, comparing the ABI of the new version of a package against its previous version is critical to detect possible incompatibilities, review them and file relevant bugs upstream, should the need arise. That comparison should be part of the normal update process followed by maintainers of packages that contain ELF libraries.

Hands on

There are two main tools tailored for comparing the ABIs of packages: abipkgdiff and abi-compliance-checker