aboutsummaryrefslogtreecommitdiff
path: root/compiler-rt/lib/xray/xray_interface.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'compiler-rt/lib/xray/xray_interface.cpp')
-rw-r--r--compiler-rt/lib/xray/xray_interface.cpp84
1 files changed, 61 insertions, 23 deletions
diff --git a/compiler-rt/lib/xray/xray_interface.cpp b/compiler-rt/lib/xray/xray_interface.cpp
index 0d22893eb30f..7669b9ab82be 100644
--- a/compiler-rt/lib/xray/xray_interface.cpp
+++ b/compiler-rt/lib/xray/xray_interface.cpp
@@ -175,6 +175,33 @@ bool patchSled(const XRaySledEntry &Sled, bool Enable,
return Success;
}
+const XRayFunctionSledIndex
+findFunctionSleds(int32_t FuncId,
+ const XRaySledMap &InstrMap) XRAY_NEVER_INSTRUMENT {
+ int32_t CurFn = 0;
+ uint64_t LastFnAddr = 0;
+ XRayFunctionSledIndex Index = {nullptr, nullptr};
+
+ for (std::size_t I = 0; I < InstrMap.Entries && CurFn <= FuncId; I++) {
+ const auto &Sled = InstrMap.Sleds[I];
+ const auto Function = Sled.function();
+ if (Function != LastFnAddr) {
+ CurFn++;
+ LastFnAddr = Function;
+ }
+
+ if (CurFn == FuncId) {
+ if (Index.Begin == nullptr)
+ Index.Begin = &Sled;
+ Index.End = &Sled;
+ }
+ }
+
+ Index.End += 1;
+
+ return Index;
+}
+
XRayPatchingStatus patchFunction(int32_t FuncId,
bool Enable) XRAY_NEVER_INSTRUMENT {
if (!atomic_load(&XRayInitialized,
@@ -205,10 +232,10 @@ XRayPatchingStatus patchFunction(int32_t FuncId,
}
// Now we patch ths sleds for this specific function.
- auto SledRange = InstrMap.SledsIndex[FuncId - 1];
+ auto SledRange = InstrMap.SledsIndex ? InstrMap.SledsIndex[FuncId - 1]
+ : findFunctionSleds(FuncId, InstrMap);
auto *f = SledRange.Begin;
auto *e = SledRange.End;
-
bool SucceedOnce = false;
while (f != e)
SucceedOnce |= patchSled(*f++, Enable, FuncId);
@@ -264,14 +291,14 @@ XRayPatchingStatus controlPatching(bool Enable) XRAY_NEVER_INSTRUMENT {
// now we're assuming we can mprotect the whole section of text between the
// minimum sled address and the maximum sled address (+ the largest sled
// size).
- auto MinSled = InstrMap.Sleds[0];
- auto MaxSled = InstrMap.Sleds[InstrMap.Entries - 1];
+ auto *MinSled = &InstrMap.Sleds[0];
+ auto *MaxSled = &InstrMap.Sleds[InstrMap.Entries - 1];
for (std::size_t I = 0; I < InstrMap.Entries; I++) {
const auto &Sled = InstrMap.Sleds[I];
- if (Sled.Address < MinSled.Address)
- MinSled = Sled;
- if (Sled.Address > MaxSled.Address)
- MaxSled = Sled;
+ if (Sled.address() < MinSled->address())
+ MinSled = &Sled;
+ if (Sled.address() > MaxSled->address())
+ MaxSled = &Sled;
}
const size_t PageSize = flags()->xray_page_size_override > 0
@@ -283,9 +310,10 @@ XRayPatchingStatus controlPatching(bool Enable) XRAY_NEVER_INSTRUMENT {
}
void *PageAlignedAddr =
- reinterpret_cast<void *>(MinSled.Address & ~(PageSize - 1));
+ reinterpret_cast<void *>(MinSled->address() & ~(PageSize - 1));
size_t MProtectLen =
- (MaxSled.Address - reinterpret_cast<uptr>(PageAlignedAddr)) + cSledLength;
+ (MaxSled->address() - reinterpret_cast<uptr>(PageAlignedAddr)) +
+ cSledLength;
MProtectHelper Protector(PageAlignedAddr, MProtectLen, PageSize);
if (Protector.MakeWriteable() == -1) {
Report("Failed mprotect: %d\n", errno);
@@ -294,7 +322,7 @@ XRayPatchingStatus controlPatching(bool Enable) XRAY_NEVER_INSTRUMENT {
for (std::size_t I = 0; I < InstrMap.Entries; ++I) {
auto &Sled = InstrMap.Sleds[I];
- auto F = Sled.Function;
+ auto F = Sled.function();
if (CurFun == 0)
CurFun = F;
if (F != CurFun) {
@@ -334,23 +362,25 @@ XRayPatchingStatus mprotectAndPatchFunction(int32_t FuncId,
// Here we compute the minumum sled and maximum sled associated with a
// particular function ID.
- auto SledRange = InstrMap.SledsIndex[FuncId - 1];
+ auto SledRange = InstrMap.SledsIndex ? InstrMap.SledsIndex[FuncId - 1]
+ : findFunctionSleds(FuncId, InstrMap);
auto *f = SledRange.Begin;
auto *e = SledRange.End;
- auto MinSled = *f;
- auto MaxSled = *(SledRange.End - 1);
+ auto *MinSled = f;
+ auto *MaxSled = (SledRange.End - 1);
while (f != e) {
- if (f->Address < MinSled.Address)
- MinSled = *f;
- if (f->Address > MaxSled.Address)
- MaxSled = *f;
+ if (f->address() < MinSled->address())
+ MinSled = f;
+ if (f->address() > MaxSled->address())
+ MaxSled = f;
++f;
}
void *PageAlignedAddr =
- reinterpret_cast<void *>(MinSled.Address & ~(PageSize - 1));
+ reinterpret_cast<void *>(MinSled->address() & ~(PageSize - 1));
size_t MProtectLen =
- (MaxSled.Address - reinterpret_cast<uptr>(PageAlignedAddr)) + cSledLength;
+ (MaxSled->address() - reinterpret_cast<uptr>(PageAlignedAddr)) +
+ cSledLength;
MProtectHelper Protector(PageAlignedAddr, MProtectLen, PageSize);
if (Protector.MakeWriteable() == -1) {
Report("Failed mprotect: %d\n", errno);
@@ -461,10 +491,18 @@ int __xray_set_handler_arg1(void (*entry)(int32_t, XRayEntryType, uint64_t)) {
int __xray_remove_handler_arg1() { return __xray_set_handler_arg1(nullptr); }
uintptr_t __xray_function_address(int32_t FuncId) XRAY_NEVER_INSTRUMENT {
- SpinMutexLock Guard(&XRayInstrMapMutex);
- if (FuncId <= 0 || static_cast<size_t>(FuncId) > XRayInstrMap.Functions)
+ XRaySledMap InstrMap;
+ {
+ SpinMutexLock Guard(&XRayInstrMapMutex);
+ InstrMap = XRayInstrMap;
+ }
+
+ if (FuncId <= 0 || static_cast<size_t>(FuncId) > InstrMap.Functions)
return 0;
- return XRayInstrMap.SledsIndex[FuncId - 1].Begin->Function
+ const XRaySledEntry *Sled = InstrMap.SledsIndex
+ ? InstrMap.SledsIndex[FuncId - 1].Begin
+ : findFunctionSleds(FuncId, InstrMap).Begin;
+ return Sled->function()
// On PPC, function entries are always aligned to 16 bytes. The beginning of a
// sled might be a local entry, which is always +8 based on the global entry.
// Always return the global entry.