Index: lib/asan/asan_globals.cc =================================================================== --- lib/asan/asan_globals.cc +++ lib/asan/asan_globals.cc @@ -332,6 +332,26 @@ *flag = 0; } +void __asan_register_elf_globals(uptr *flag, void *start, void *stop) { + if (*flag) return; + if (!start) return; + CHECK_EQ(0, ((uptr)stop - (uptr)start) % sizeof(__asan_global)); + __asan_global *globals_start = (__asan_global*)start; + __asan_global *globals_stop = (__asan_global*)stop; + __asan_register_globals(globals_start, globals_stop - globals_start); + *flag = 1; +} + +void __asan_unregister_elf_globals(uptr *flag, void *start, void *stop) { + if (!*flag) return; + if (!start) return; + CHECK_EQ(0, ((uptr)stop - (uptr)start) % sizeof(__asan_global)); + __asan_global *globals_start = (__asan_global*)start; + __asan_global *globals_stop = (__asan_global*)stop; + __asan_unregister_globals(globals_start, globals_stop - globals_start); + *flag = 0; +} + // Register an array of globals. void __asan_register_globals(__asan_global *globals, uptr n) { if (!flags()->report_globals) return; Index: lib/asan/asan_interface_internal.h =================================================================== --- lib/asan/asan_interface_internal.h +++ lib/asan/asan_interface_internal.h @@ -67,6 +67,11 @@ SANITIZER_INTERFACE_ATTRIBUTE void __asan_unregister_image_globals(uptr *flag); + SANITIZER_INTERFACE_ATTRIBUTE + void __asan_register_elf_globals(uptr *flag, void *start, void *stop); + SANITIZER_INTERFACE_ATTRIBUTE + void __asan_unregister_elf_globals(uptr *flag, void *start, void *stop); + // These two functions should be called by the instrumented code. // 'globals' is an array of structures describing 'n' globals. SANITIZER_INTERFACE_ATTRIBUTE Index: test/asan/TestCases/Linux/globals-gc-sections-lld.cc =================================================================== --- /dev/null +++ test/asan/TestCases/Linux/globals-gc-sections-lld.cc @@ -0,0 +1,16 @@ +// RUN: %clangxx_asan %s -o %t -Wl,--gc-sections -fuse-ld=lld -ffunction-sections -fdata-sections -mllvm -asan-globals=0 +// RUN: %clangxx_asan %s -o %t -Wl,--gc-sections -fuse-ld=lld -ffunction-sections -fdata-sections -mllvm -asan-globals=1 + +// https://code.google.com/p/address-sanitizer/issues/detail?id=260 + +// REQUIRES: lld + +int undefined(); + +// On i386 clang adds --export-dynamic when linking with ASan, which adds all +// non-hidden globals to GC roots. +__attribute__((visibility("hidden"))) int (*unused)() = undefined; + +int main() { + return 0; +} Index: test/asan/TestCases/Linux/globals-gc-sections.cc =================================================================== --- test/asan/TestCases/Linux/globals-gc-sections.cc +++ test/asan/TestCases/Linux/globals-gc-sections.cc @@ -1,12 +1,18 @@ -// RUN: %clangxx_asan %s -o %t -Wl,--gc-sections -ffunction-sections -mllvm -asan-globals=0 -// RUN: %clangxx_asan %s -o %t -Wl,--gc-sections -ffunction-sections -mllvm -asan-globals=1 +// RUN: %clangxx_asan %s -o %t -Wl,--gc-sections -fuse-ld=bfd -ffunction-sections -fdata-sections -mllvm -asan-globals=0 +// RUN: %clangxx_asan %s -o %t -Wl,--gc-sections -fuse-ld=bfd -ffunction-sections -fdata-sections -mllvm -asan-globals=1 // https://code.google.com/p/address-sanitizer/issues/detail?id=260 -// XFAIL: * int undefined(); -int (*unused)() = undefined; +// bug in ld.bfd: with multiple "asan_globals" sections, __start_asan_globals is +// treated as a strong GC reference to the first such section. As a result, the +// first (for some definition of the word) global is never gc-ed. +int first_unused = 42; + +// On i386 clang adds --export-dynamic when linking with ASan, which adds all +// non-hidden globals to GC roots. +__attribute__((visibility("hidden"))) int (*unused)() = undefined; int main() { return 0;