#5548·bcc

RFC: Support fully static libbpf-tools builds for Android/AArch64 deployment

Author: lipengfei28Created Aug 28, 2026Updated Aug 28, 2026

Summary

BCC's libbpf-tools currently links libbpf statically, but normally leaves system libraries such as libc, libelf, and zlib dynamically linked. This works well on conventional Linux distributions, but it is not directly suitable for Android devices, where the expected GNU/Linux shared libraries are generally unavailable or incompatible.

This RFC proposes an optional AArch64 cross-build environment that builds the required user-space libraries from source and produces fully static libbpf-tools executables for deployment on Android devices.

The proposal is limited to the build and deployment workflow. It does not require changes to the functional source code of individual libbpf tools or their BPF programs.

Motivation

Android devices do not normally provide compatible versions of libraries such as libelf.so.1, libz.so, or other GNU/Linux user-space dependencies needed by dynamically linked libbpf-tools binaries. Packaging those shared libraries with every tool also requires target-side library-path management and introduces additional compatibility problems.

Fully static executables avoid those runtime shared-library dependencies. A tool can be copied to the device with adb push and executed directly, subject to the device's kernel configuration, BTF availability, SELinux policy, and privileges.

Proposed build support

The proposed build environment would:

  1. use an AArch64 GNU/Linux cross compiler;
  2. build all required user-space dependencies from pinned source revisions;
  3. link libc, libelf, zlib, libzstd, liblzma, and libbpf statically as needed;
  4. preserve the existing native and partially static build as the default;
  5. provide an explicit, opt-in target or build script for fully static tools;
  6. use -j3 for all compilation stages;
  7. audit generated ELF files to ensure that they contain no dynamic section, interpreter, or DT_NEEDED entries; and
  8. optionally stage the binaries for deployment with adb push.

The intended interface could be a dedicated make target or a wrapper script, for example:

bash
./scripts/build-static-aarch64.sh -j3

The exact interface can be adjusted to match BCC project conventions.

Source-code impact

The prototype does not require modifications to the C source code of existing libbpf-tools or to their BPF programs. Cross-build-specific behavior is kept in external build scripts, Makefile options, dependency configuration, ELF auditing, and deployment helpers.

The normal build remains unchanged. Fully static AArch64 output is enabled only when explicitly requested.

All required libraries are built from source. In particular, libelf.a is linked into the resulting executables, so the Android device does not need libelf.so.1.

Prototype and Android validation

The approach has been prototyped successfully. Multiple AArch64 libbpf-tools, including biosnoop, capable, and execsnoop, were built as fully static executables and tested on an Android AArch64 device through adb shell.

Example deployment:

bash
adb push biosnoop /data/local/tmp/biosnoop
adb shell chmod 755 /data/local/tmp/biosnoop
adb shell /data/local/tmp/biosnoop

TIME(s)     COMM           PID     DISK    T    SECTOR     BYTES   LAT(ms)
0.000000    POSIX timer 0  1206    sda     WS   115717800  4096      0.153
0.000237    POSIX timer 0  1206    sda     WS   144686432  4096      0.024
0.055405    kworker/0:3    1667    sda     N    -1         0         0.408
0.255093    dbthread       8623    sda     WS   115718616  4096      0.130
0.255182    dbthread       8623    sda     WS   115718624  4096      0.203
0.255192    dbthread       8623    sda     WS   115718632  8192      0.207
0.255626    dbthread       8623    sda     WS   144686440  4096      0.024
0.255913    ?              0       sda     FF   -1         0         0.119
0.256035    dbthread       8623    sda     WS   144686448  4096      0.044
0.256207    ?              0       sda     FF   -1         0         0.105
0.317385    kworker/0:3    1667    sda     N    -1         0         0.417
0.474849    SettingsProvid 3532    sda     WS   115718648  81920     0.216
0.475058    SettingsProvid 3532    sda     WS   144686456  4096      0.027
0.535385    kworker/0:3    1667    sda     N    -1         0         0.410
0.770098    touch-main-loo 2349    sda     R    8517944    4096      0.198
0.770364    touch-main-loo 2349    sda     RA   8431168    4096      0.075
0.770469    touch-main-loo 2349    sda     RA   8431176    8192      0.083

The ELF audit produces:

bash
$ readelf -d biosnoop

There is no dynamic section in this file.

Therefore, the deployed tool does not require libelf.so.1, libz.so, or other build-specific shared libraries on the device.

Platform scope

The current prototype uses an AArch64 GNU/Linux/glibc cross toolchain and runs the resulting fully static binaries on Android. This is an Android deployment workflow, not a native Android NDK/bionic build.

AArch64 GNU/Linux/glibc and Android NDK/bionic are different targets and should not be treated as interchangeable. Native NDK/bionic support, if desired, should be considered separately.

Successful execution also depends on target-specific conditions, including:

  • a kernel with the required eBPF features;
  • suitable BTF data for CO-RE relocation;
  • root or the required Linux capabilities;
  • compatible SELinux policy; and
  • tracepoints, kprobes, and kernel symbols required by each tool.

Questions

  1. Is an optional fully static AArch64 build mode appropriate for BCC libbpf-tools?
  2. Should the implementation be integrated into the existing Makefile or kept in a separate build script?
  3. Should the project validate fully static output in CI by checking for PT_INTERP, DT_NEEDED, and dynamic sections?
  4. Should Android deployment documentation explicitly distinguish this GNU/Linux/glibc approach from native Android NDK/bionic support?

The prototype demonstrates that fully static libbpf-tools provide a simple and practical deployment path for Android AArch64 devices without changing the tools' functional source code.