Index: compiler-rt/lib/cfi/cfi.cc =================================================================== --- compiler-rt/lib/cfi/cfi.cc +++ compiler-rt/lib/cfi/cfi.cc @@ -367,14 +367,26 @@ using namespace __cfi; +static bool cfi_inited; +extern "C" void __cfi_init(); + +#define ENSURE_CFI_INITED() \ + do { \ + if (UNLIKELY(!cfi_inited)) { \ + __cfi_init(); \ + } \ + } while (0) + extern "C" SANITIZER_INTERFACE_ATTRIBUTE void __cfi_slowpath(u64 CallSiteTypeId, void *Ptr) { + ENSURE_CFI_INITED(); CfiSlowPathCommon(CallSiteTypeId, Ptr, nullptr); } #ifdef CFI_ENABLE_DIAG extern "C" SANITIZER_INTERFACE_ATTRIBUTE void __cfi_slowpath_diag(u64 CallSiteTypeId, void *Ptr, void *DiagData) { + ENSURE_CFI_INITED(); CfiSlowPathCommon(CallSiteTypeId, Ptr, DiagData); } #endif @@ -388,6 +400,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) { + ENSURE_CFI_INITED(); EnterLoader(); void *handle = REAL(dlopen)(filename, flag); ExitLoader(); @@ -395,18 +408,25 @@ } INTERCEPTOR(int, dlclose, void *handle) { + ENSURE_CFI_INITED(); EnterLoader(); int res = REAL(dlclose)(handle); ExitLoader(); return res; } +static BlockingMutex cfi_init_lock(LINKER_INITIALIZED); + extern "C" SANITIZER_INTERFACE_ATTRIBUTE #if !SANITIZER_CAN_USE_PREINIT_ARRAY // On ELF platforms, the constructor is invoked using .preinit_array (see below) __attribute__((constructor(0))) #endif void __cfi_init() { + BlockingMutexLock lock(&cfi_init_lock); + if (cfi_inited) + return; + cfi_inited = true; SanitizerToolName = "CFI"; InitializeFlags(); InitShadow();