aboutsummaryrefslogtreecommitdiff
path: root/lib/xray/xray_init.cc
diff options
context:
space:
mode:
Diffstat (limited to 'lib/xray/xray_init.cc')
-rw-r--r--lib/xray/xray_init.cc35
1 files changed, 33 insertions, 2 deletions
diff --git a/lib/xray/xray_init.cc b/lib/xray/xray_init.cc
index aa660baa9920..11892cb8b7a3 100644
--- a/lib/xray/xray_init.cc
+++ b/lib/xray/xray_init.cc
@@ -44,12 +44,31 @@ __sanitizer::atomic_uint8_t XRayInitialized{0};
__sanitizer::SpinMutex XRayInstrMapMutex;
XRaySledMap XRayInstrMap;
+// Global flag to determine whether the flags have been initialized.
+__sanitizer::atomic_uint8_t XRayFlagsInitialized{0};
+
+// A mutex to allow only one thread to initialize the XRay data structures.
+__sanitizer::SpinMutex XRayInitMutex;
+
// __xray_init() will do the actual loading of the current process' memory map
// and then proceed to look for the .xray_instr_map section/segment.
void __xray_init() XRAY_NEVER_INSTRUMENT {
- initializeFlags();
+ __sanitizer::SpinMutexLock Guard(&XRayInitMutex);
+ // Short-circuit if we've already initialized XRay before.
+ if (__sanitizer::atomic_load(&XRayInitialized,
+ __sanitizer::memory_order_acquire))
+ return;
+
+ if (!__sanitizer::atomic_load(&XRayFlagsInitialized,
+ __sanitizer::memory_order_acquire)) {
+ initializeFlags();
+ __sanitizer::atomic_store(&XRayFlagsInitialized, true,
+ __sanitizer::memory_order_release);
+ }
+
if (__start_xray_instr_map == nullptr) {
- Report("XRay instrumentation map missing. Not initializing XRay.\n");
+ if (Verbosity())
+ Report("XRay instrumentation map missing. Not initializing XRay.\n");
return;
}
@@ -63,9 +82,21 @@ void __xray_init() XRAY_NEVER_INSTRUMENT {
__sanitizer::atomic_store(&XRayInitialized, true,
__sanitizer::memory_order_release);
+#ifndef XRAY_NO_PREINIT
if (flags()->patch_premain)
__xray_patch();
+#endif
}
+#if !defined(XRAY_NO_PREINIT) && SANITIZER_CAN_USE_PREINIT_ARRAY
+// Only add the preinit array initialization if the sanitizers can.
__attribute__((section(".preinit_array"),
used)) void (*__local_xray_preinit)(void) = __xray_init;
+#else
+// If we cannot use the .preinit_array section, we should instead use dynamic
+// initialisation.
+static bool UNUSED __local_xray_dyninit = [] {
+ __xray_init();
+ return true;
+}();
+#endif