Prebuilt ABI usages checker

Android shared libraries evolve from time to time. Keeping prebuilt binaries up-to-date requires considerable effort. In Android 9 or earlier, the prebuilt binaries that depend on removed libraries or ABIs only fail to link at run-time. Developers have to trace the logs to find the outdated prebuilt binaries. In Android 10, a symbol-based ABI usages checker is introduced. The checker can detect outdated prebuilt binaries at build-time, so that shared library developers can know which prebuilt binaries might be broken by their change and which prebuilt binaries must be re-built.

Symbol-based ABI usages checker

The symbol-based ABI usages checker emulates the Android dynamic linker on host. The checker links the prebuilt binary with the dependencies of the prebuilt binary and checks whether all undefined symbols are resolved.

First, the checker checks the target architecture of the prebuilt binary. If the prebuilt binary does not target ARM, AArch64, x86, or x86-64 architecture, the checker skips the prebuilt binary.

Second, the dependencies of the prebuilt binary must be listed in LOCAL_SHARED_LIBRARIES or shared_libs. The build system resolves the module names to the matching variant (i.e. core vs. vendor) of the shared libraries.

Third, the checker compares the DT_NEEDED entries to LOCAL_SHARED_LIBRARIES or shared_libs. In particular, the checker extracts the DT_SONAME entry from each shared libraries and compares these DT_SONAME with the DT_NEEDED entries recorded in the prebuilt binary. If there is a mismatch, an error message is emitted.

Fourth, the checker resolves the undefined symbols in the prebuilt binary. Those undefined symbols must be defined in one of the dependencies and the symbol binding must be either GLOBAL or WEAK. If an undefined symbol cannot be resolved, an error message is emitted.

Prebuilts module properties

Dependencies of the prebuilt binary must be specified in one of the following:

  • Android.bp: shared_libs: ["libc", "libdl", "libm"],
  • Android.mk: LOCAL_SHARED_LIBRARIES := libc libdl libm

If the prebuilt binary is designed to have some unresolvable undefined symbols, specify one of the following:

  • Android.bp: allow_undefined_symbols: true,
  • Android.mk: LOCAL_ALLOW_UNDEFINED_SYMBOLS := true

To have the prebuilt binary skip the ELF file check, specify one of the following:

  • Android.bp: check_elf_files: false,
  • Android.mk: LOCAL_CHECK_ELF_FILES := false

Run the checker

The checker covers all ELF prebuilt modules during the Android build process.

To run the checker alone for faster turnaround times:

m check-elf-files

ABI error fixer

The automatic fixer can help resolve ABI check errors. Simply run the fixer with the Android.bp / Android.mk as input, and the fixer would print the suggested fix to stdout. Optionally, run the fixer with the --in-place option to directly update the Android.bp / Android.mk with the suggested fix.

For Android.bp,

m fix_android_bp_prebuilt
# Print the fixed Android.bp to stdout.
fix_android_bp_prebuilt <path-to-Android.bp>
# Update the Android.bp in place.
fix_android_bp_prebuilt --in-place <path-to-Android.bp>

For Android.mk,

m fix_android_mk_prebuilt
# Print the fixed Android.mk to stdout.
fix_android_mk_prebuilt <path-to-Android.mk>
# Update the Android.mk in place.
fix_android_mk_prebuilt --in-place <path-to-Android.mk>