summaryrefslogtreecommitdiff
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.cc54
1 files changed, 39 insertions, 15 deletions
diff --git a/lib/xray/xray_init.cc b/lib/xray/xray_init.cc
index 9d012e9a6..07f692431 100644
--- a/lib/xray/xray_init.cc
+++ b/lib/xray/xray_init.cc
@@ -12,7 +12,6 @@
// XRay initialisation logic.
//===----------------------------------------------------------------------===//
-#include <atomic>
#include <fcntl.h>
#include <strings.h>
#include <unistd.h>
@@ -26,9 +25,10 @@ extern "C" {
void __xray_init();
extern const XRaySledEntry __start_xray_instr_map[] __attribute__((weak));
extern const XRaySledEntry __stop_xray_instr_map[] __attribute__((weak));
+extern const XRayFunctionSledIndex __start_xray_fn_idx[] __attribute__((weak));
+extern const XRayFunctionSledIndex __stop_xray_fn_idx[] __attribute__((weak));
}
-using namespace __sanitizer;
using namespace __xray;
// When set to 'true' this means the XRay runtime has been initialised. We use
@@ -38,33 +38,57 @@ using namespace __xray;
//
// FIXME: Support DSO instrumentation maps too. The current solution only works
// for statically linked executables.
-std::atomic<bool> XRayInitialized{false};
+__sanitizer::atomic_uint8_t XRayInitialized{0};
// This should always be updated before XRayInitialized is updated.
-std::atomic<__xray::XRaySledMap> XRayInstrMap{};
+__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;
}
- // Now initialize the XRayInstrMap global struct with the address of the
- // entries, reinterpreted as an array of XRaySledEntry objects. We use the
- // virtual pointer we have from the section to provide us the correct
- // information.
- __xray::XRaySledMap SledMap{};
- SledMap.Sleds = __start_xray_instr_map;
- SledMap.Entries = __stop_xray_instr_map - __start_xray_instr_map;
- XRayInstrMap.store(SledMap, std::memory_order_release);
- XRayInitialized.store(true, std::memory_order_release);
+ {
+ __sanitizer::SpinMutexLock Guard(&XRayInstrMapMutex);
+ XRayInstrMap.Sleds = __start_xray_instr_map;
+ XRayInstrMap.Entries = __stop_xray_instr_map - __start_xray_instr_map;
+ XRayInstrMap.SledsIndex = __start_xray_fn_idx;
+ XRayInstrMap.Functions = __stop_xray_fn_idx - __start_xray_fn_idx;
+ }
+ __sanitizer::atomic_store(&XRayInitialized, true,
+ __sanitizer::memory_order_release);
+#ifndef XRAY_NO_PREINIT
if (flags()->patch_premain)
__xray_patch();
+#endif
}
+#ifndef XRAY_NO_PREINIT
__attribute__((section(".preinit_array"),
used)) void (*__local_xray_preinit)(void) = __xray_init;
+#endif