Description
Disclaimer: I tried to create a testcase from scratch, but for some reason I wasn't able to find a way to trigger the use of __asan_register_elf_globals
instead of __asan_globals_register
.
STR:
- Clone https://github.com/glandium/nss-builtins
cd nss-builtins
RUSTFLAGS="-Zsanitizer=address" CARGO_PROFILE_RELEASE_LTO=true cargo +nightly build --release
objdump -t target/release/libbuiltins_static.a | grep asan_globals_registered
Actual output:
0000000000000000 l O .bss.___asan_globals_registered 0000000000000008 ___asan_globals_registered
0000000000000000 l d .bss.___asan_globals_registered 0000000000000000 .bss.___asan_globals_registered
Expected output:
Something like:
0000000000000008 O *COM* 0000000000000008 .hidden ___asan_globals_registered
This doesn't happen without LTO.
The unfortunate consequence is that when the resulting static library is linked with C or C++ code compiled with clang with -fsanitize=address -fsanitize-address-globals-dead-stripping
(that latter flag is now default in clang trunk), which also uses __asan_register_elf_globals
/__asan_globals_registered
, ODR violation detection kick in complaining about globals defined multiple times, because both the clang-side asan constructor and the rust asan constructor register all the globals. Normally, what happens is that they both use the same __asan_globals_registered
(thus it normally being *COM*
), and set its value, so that only one constructor registers the globals. With the LTOed staticlib, what happens is that there are two distinct __asan_globals_registered
, so both constructors go through.
rustc +nightly --version --verbose
:
rustc 1.72.0-nightly (d9c13cd45 2023-07-05)
binary: rustc
commit-hash: d9c13cd4531649c2028a8384cb4d4e54f985380e
commit-date: 2023-07-05
host: x86_64-unknown-linux-gnu
release: 1.72.0-nightly
LLVM version: 16.0.5
(Edit: fixed typos, changed the peculiar setup with -Clto
and -Cembed-bitcode=yes
to the more normal LTO, which shows the problem too)