amboar.github.io

Software development notes

View My GitHub Profile

26 June 2023

Managing the libpldm ABI Reference Dumps

by Andrew

A recent change to libpldm added three visibility classes to control its Application Binary Interface (ABI). The approach is fairly crude but also fairly effective. As outlined, the primary motivation is to allow us to fix (break) new Application Programmer Interfaces (APIs) without getting hung up on existing users. The testing ABI visibility class allows functions to exist in the library but remain out of reach for general use until we’re confident that their API is reasonable.

The existence of the stable visibility class implies that we shouldn’t break the existence or behaviour any of its functions. This promise is only as good as our ability to measure it. The ideal measurement is that any stable API and ABI breaks are detected by Continuous Integration (CI). To that end I integrated support for abi-compliance-checker into the build system.

However, this integration requires the existence of reference dumps against which CI will measure proposed patches. The existence of reference dumps implies we also need to maintain them as functions come and go across library releases. This post aims to outline exactly how and when we should go about updating these reference dumps.

We find the reference dumps under libpldm’s abi/ directory, namespaced by the host architecture1 and compiler:

$ git ls-files abi/
abi/aarch64/gcc.dump
abi/x86_64/gcc.dump
$

As we can see the dumps currently cover the library’s ABI as produced by GCC on aarch64 and x86_64. Support for aarch64 is required because that’s the architecture of my current laptop. The x86_64 reference dump is captured because the architecture is reasonably popular, but crucially, the dominant architecture used by the project’s CI.

Setting the reference dumps aside, each build also generates its own ABI dump if the abi-dumper and abi-compliance-checker tools are found2. These per-build dumps are currently written out as current.dump in the root of the build directory. The role of abi-compliance-checker is to test current.dump against the appropriate reference dump for the build.

A corollary of this is that the reference dumps can be updated by copying a build’s current.dump into the appropriate location under the abi/ directory. However, before you copy that file, several details must be checked:

  1. That the build is configured to expose only the deprecated and stable ABI3
  2. That the build’s host architecture (again, with respect to 1) is appropriate for the dump type, and
  3. That the compiler suite is appropriate for the dump type.

If you are unsure, these details are summarised in the meson output:

$ meson setup -Dabi=deprecated,stable builds/aarch64/stable
...
C compiler for the host machine: ccache cc (gcc 13.1.1 "cc (GCC) 13.1.1 20230614 (Red Hat 13.1.1-4)")
...
C++ compiler for the host machine: ccache c++ (gcc 13.1.1 "c++ (GCC) 13.1.1 20230614 (Red Hat 13.1.1-4)")
...
Host machine cpu family: aarch64
Host machine cpu: aarch64
...
  User defined options
    abi        : deprecated,stable
...

A critical issue is that any need to update a reference dump requires that all reference dumps be updated. Further, it may be the case that you do not have access to machines to cover all of the relevant host architectures. For Debian-derived distributions you can set yourself up with the multiarch instructions. Fedora is a bit more of a challenge, however I’ve covered one possible approach if it is your distro of choice. From there it’s a matter of choosing a build directory naming scheme such as builds/${arch}/${compiler} to keep your build configurations separate4:

$ meson setup -Dabi=deprecated,stable --cross-file=... builds/${arch}/${compiler}
$ meson compile -C builds/${arch}/${compiler}

And once the build completes:

$ cp builds/${arch}/${compiler}/current.dump abi/${arch}/${compiler}.dump

When should I update the reference ABI dumps?

Currently there are three circumstances:

  1. When tagging a new release of the library
  2. When stabilising a function5
  3. When deleting a function from the deprecated visibility class6

The ABI dumps capture the library version in their metadata. This drives the need to update the dumps whenever a new release tag is created.

Stabilising a function is the explicit promise not to break its API or ABI going forward. It is thus criticial that it be integrated into the reference dumps so this promise can be upheld by CI.

Finally, once a function is deleted there’s no need to continue carrying its description in the reference dumps.

And with that, hopefully the lifecycle of the reference dumps is now clear!

  1. In the sense of GCC’s configure terms  2

  2. Under Linux they can both be installed through the system’s package manager, e.g. with sudo dnf install abi-dumper abi-compliance-checker or sudo apt install abi-dumper abi-compliance-checker

  3. i.e. meson setup -Dabi=deprecated,stable ... 

  4. Again, for a short intro to meson’s cross-files see my post covering cross-architecture work on Fedora 

  5. That is, moving a function from the testing visibility class to the stable visibility class by changing its visibility annotation from LIBPLDM_ABI_TESTING to LIBPLDM_ABI_STABLE 

  6. Note that functions must never be deleted directly from the stable visibility class

tags: