From Fedora Project Wiki

 
(12 intermediate revisions by 3 users not shown)
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 (let's call it FOO) 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 link] with FOO, keep seeing the ABI they expect from that library FOO.  Otherwise, if the ABI of the new version of FOO 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 a shared library FOO, it's our duty to ensure that the ABI of new versions of FOO stays compatible with the ABI of its former versions.
* 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].
+
=== Reviewing ABI changes in a given ''ELF binary'' ===
  
<pre>
+
There are essentially two tools to review the ABI differences between two versions of a given '''ELF binary''':
$ sudo yum install abi-compliance-checker
 
(or as root)
 
# yum install abi-compliance-checker
 
</pre>
 
  
== Procedure ==
+
* [[How_to_check_for_ABI_changes_with_abidiff|abidiff]]
 +
* [[How_to_check_for_ABI_changes_with_abi_compliance_checker#procedure_for_comparing_the_ABIs_of_two_Elf_binaries|abi-compliance-checker]]
  
<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.
+
=== Reviewing ABI changes in a given ''RPM package'' ===
  
=== Step 1: Preparing ===
+
There are two main tools tailored for comparing the ABIs of '''packages''': [https://sourceware.org/libabigail/manual/abipkgdiff.html abipkgdiff] and [http://lvc.github.io/abi-compliance-checker/ abi-compliance-checker]
  
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>:
+
* [[How_to_check_for_ABI_changes_with_abipkgdiff|Using abipkgdiff]]
<pre>
+
* [[How_to_check_for_ABI_changes_with_abi_compliance_checker|Using abi-compliance-checker]]
#!/bin/bash
 
  
if [ ! -n "$1" ]
+
== External links ==
then
 
  echo "Unpacks an RPM into the current directory."
 
  echo ""
 
  echo "Usage: `basename $0` <package1> [package2]..."
 
fi
 
  
for file in $*; do
+
* [https://sourceware.org/libabigail/ The ABI Generic Analysis and Instrumentation Library]
rpm2cpio $file | cpio -idmv
 
done
 
</pre>
 
  
Now create a directory structure and unpack the packages:
+
[[Category:ABI]]
<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.
 

Latest revision as of 11:25, 15 August 2017

Introduction

When a new version of an ELF shared library (let's call it FOO) 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 link with FOO, keep seeing the ABI they expect from that library FOO. Otherwise, if the ABI of the new version of FOO 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 a shared library FOO, it's our duty to ensure that the ABI of new versions of FOO stays compatible with the ABI of its former versions.

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

Reviewing ABI changes in a given ELF binary

There are essentially two tools to review the ABI differences between two versions of a given ELF binary:

Reviewing ABI changes in a given RPM package

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

External links