Index: compiler-rt/lib/cfi/cfi.cc =================================================================== --- compiler-rt/lib/cfi/cfi.cc +++ compiler-rt/lib/cfi/cfi.cc @@ -379,6 +379,8 @@ } #endif +static void EnsureInterceptorsInited(); + // Setup shadow for dlopen()ed libraries. // The actual shadow setup happens after dlopen() returns, which means that // a library can not be a target of any CFI checks while its constructors are @@ -388,6 +390,7 @@ // We could insert a high-priority constructor into the library, but that would // not help with the uninstrumented libraries. INTERCEPTOR(void*, dlopen, const char *filename, int flag) { + EnsureInterceptorsInited(); EnterLoader(); void *handle = REAL(dlopen)(filename, flag); ExitLoader(); @@ -395,12 +398,27 @@ } INTERCEPTOR(int, dlclose, void *handle) { + EnsureInterceptorsInited(); EnterLoader(); int res = REAL(dlclose)(handle); ExitLoader(); return res; } +static atomic_uint8_t interceptors_inited = {0}; + +static void EnsureInterceptorsInited() { + // This check allows redundant initializations. This is acceptable as + // INTERCEPT_FUNCTION is expected to save same value. + if (atomic_load(&interceptors_inited, memory_order_acquire)) + return; + + INTERCEPT_FUNCTION(dlopen); + INTERCEPT_FUNCTION(dlclose); + + atomic_store(&interceptors_inited, 1, memory_order_release); +} + extern "C" SANITIZER_INTERFACE_ATTRIBUTE #if !SANITIZER_CAN_USE_PREINIT_ARRAY // On ELF platforms, the constructor is invoked using .preinit_array (see below) @@ -411,9 +429,6 @@ InitializeFlags(); InitShadow(); - INTERCEPT_FUNCTION(dlopen); - INTERCEPT_FUNCTION(dlclose); - #ifdef CFI_ENABLE_DIAG __ubsan::InitAsPlugin(); #endif