Run clang 15 executable on legacy device

1 minute read

For a suspected memory leak issue on a legacy device running OpenWrt build with gcc-8, I need a toolchain with leak sanitizer support, so I try to generate one with buildroot-2024.02, when I execute this app linked with -fsanitize=address, the following issue occurred:

./leak 
./leak: /lib/libc.so.6: version `GLIBC_2.32' not found (required by ./leak)
./leak: /lib/libc.so.6: version `GLIBC_2.34' not found (required by ./leak)

The solution is build toolchain with BR2_PACKAGE_GLIBC_KERNEL_COMPAT=y and push libc.so.6 and ld-linux-armhf.so.3 to system, a quick verification as follows:

adb push arm-buildroot-linux-gnueabihf/sysroot/lib/ld-linux-armhf.so.3 /usr/local/lib/
adb push arm-buildroot-linux-gnueabihf/sysroot/lib/libc.so.6 /usr/local/lib/
export LD_LIBRARY_PATH=/usr/local/lib/:$LD_LIBRARY_PATH
/usr/local/lib/ld-linux-armhf.so.3 ./leak

=================================================================
==2625==ERROR: LeakSanitizer: detected memory leaks

Direct leak of 7 byte(s) in 1 object(s) allocated from:
    #0 0xb66a3a78  (/usr/local/lib/ld-linux-armhf.so.3+0xcfa78)
    #1 0xb66ec930  (/usr/local/lib/ld-linux-armhf.so.3+0x118930)
    #2 0xb63a98b0  (/usr/local/lib/libc.so.6+0x228b0)
    #3 0xb63a999c  (/usr/local/lib/libc.so.6+0x2299c)

SUMMARY: AddressSanitizer: 7 byte(s) leaked in 1 allocation(s).

The linker and search path can also specified in compile process:

clang -fsanitize=address -Wl,--rpath=/usr/local/lib/ -Wl,--dynamic-linker=/usr/local/lib/ld-linux-armhf.so.3 leak.c -o leak 

Let’s take a look at the config option in buildroot, BR2_PACKAGE_GLIBC_KERNEL_COMPAT was defined in package/glibc/Config.in:

config BR2_PACKAGE_GLIBC_KERNEL_COMPAT
	bool "Enable compatibility shims to run on older kernels"
	help
	  Say 'y' here if you plan on running your system on a kernel
	  older than the version used for the toolchain headers.

	  Enabling those compatibility shims may generate a slightly
	  bigger and slightly slower glibc library.

	  The oldest supported kernel version depends on the
	  architecture.

With above option enabled, buildroot will add --enable-kernel to glibc config options, as defined in package/glibc/glibc.mk:

ifeq ($(BR2_PACKAGE_GLIBC_KERNEL_COMPAT),)
GLIBC_CONF_OPTS += --enable-kernel=$(call qstrip,$(BR2_TOOLCHAIN_HEADERS_AT_LEAST))
endif

For detailed description about --enable-kernel, head to C.1 Configuring and compiling the GNU C Library.

‘–enable-kernel=version’
This option is currently only useful on GNU/Linux systems. The version parameter should have the form X.Y.Z and describes the smallest version of the Linux kernel the generated library is expected to support. The higher the version number is, the less compatibility code is added, and the faster the code gets.