linker: Add library load and unload hooks for HWASan.
These hooks notify the HWASan runtime library whenever a library is loaded
or unloaded so that it can update its shadow memory.
Bug: 138159093
Test: walleye_hwasan-userdebug boots with+without https://reviews.llvm.org/D65770
Change-Id: I6caf2a6540ed2c0d94db444e806a3c7ba504cabb
diff --git a/libc/bionic/libc_init_dynamic.cpp b/libc/bionic/libc_init_dynamic.cpp
index 4f3b4f7..d6d5552 100644
--- a/libc/bionic/libc_init_dynamic.cpp
+++ b/libc/bionic/libc_init_dynamic.cpp
@@ -69,6 +69,13 @@
__LIBC_HIDDEN__ void* __libc_sysinfo = reinterpret_cast<void*>(__libc_int0x80);
#endif
+extern "C" __attribute__((weak)) void __hwasan_library_loaded(ElfW(Addr) base,
+ const ElfW(Phdr)* phdr,
+ ElfW(Half) phnum);
+extern "C" __attribute__((weak)) void __hwasan_library_unloaded(ElfW(Addr) base,
+ const ElfW(Phdr)* phdr,
+ ElfW(Half) phnum);
+
// We need a helper function for __libc_preinit because compiling with LTO may
// inline functions requiring a stack protector check, but __stack_chk_guard is
// not initialized at the start of __libc_preinit. __libc_preinit_impl will run
@@ -91,6 +98,14 @@
// Hooks for various libraries to let them know that we're starting up.
__libc_globals.mutate(__libc_init_malloc);
+
+#if __has_feature(hwaddress_sanitizer)
+ // Notify the HWASan runtime library whenever a library is loaded or unloaded
+ // so that it can update its shadow memory.
+ __libc_shared_globals()->load_hook = __hwasan_library_loaded;
+ __libc_shared_globals()->unload_hook = __hwasan_library_unloaded;
+#endif
+
netdClientInit();
}
diff --git a/libc/private/bionic_globals.h b/libc/private/bionic_globals.h
index d73079e..ef735ba 100644
--- a/libc/private/bionic_globals.h
+++ b/libc/private/bionic_globals.h
@@ -88,6 +88,10 @@
TlsModules tls_modules;
BionicAllocator tls_allocator;
+ // Values passed from the HWASan runtime (via libc.so) to the loader.
+ void (*load_hook)(ElfW(Addr) base, const ElfW(Phdr)* phdr, ElfW(Half) phnum) = nullptr;
+ void (*unload_hook)(ElfW(Addr) base, const ElfW(Phdr)* phdr, ElfW(Half) phnum) = nullptr;
+
// Values passed from the linker to libc.so.
const char* init_progname = nullptr;
char** init_environ = nullptr;
diff --git a/linker/linker.cpp b/linker/linker.cpp
index df7dd40..0361a8a 100644
--- a/linker/linker.cpp
+++ b/linker/linker.cpp
@@ -1905,6 +1905,9 @@
!get_cfi_shadow()->AfterLoad(si, solist_get_head())) {
return false;
}
+ if (__libc_shared_globals()->load_hook) {
+ __libc_shared_globals()->load_hook(si->load_bias, si->phdr, si->phnum);
+ }
}
return true;
@@ -2039,6 +2042,9 @@
si);
notify_gdb_of_unload(si);
unregister_soinfo_tls(si);
+ if (__libc_shared_globals()->unload_hook) {
+ __libc_shared_globals()->unload_hook(si->load_bias, si->phdr, si->phnum);
+ }
get_cfi_shadow()->BeforeUnload(si);
soinfo_free(si);
}