summaryrefslogtreecommitdiffstats
path: root/compiler-rt/lib/xray/xray_x86_64.cc
diff options
context:
space:
mode:
Diffstat (limited to 'compiler-rt/lib/xray/xray_x86_64.cc')
-rw-r--r--compiler-rt/lib/xray/xray_x86_64.cc33
1 files changed, 33 insertions, 0 deletions
diff --git a/compiler-rt/lib/xray/xray_x86_64.cc b/compiler-rt/lib/xray/xray_x86_64.cc
index 0443c5eb6d5..c4fead97871 100644
--- a/compiler-rt/lib/xray/xray_x86_64.cc
+++ b/compiler-rt/lib/xray/xray_x86_64.cc
@@ -111,4 +111,37 @@ bool patchFunctionExit(const bool Enable, const uint32_t FuncId,
return true;
}
+bool patchFunctionTailExit(const bool Enable, const uint32_t FuncId,
+ const XRaySledEntry &Sled) {
+ // Here we do the dance of replacing the tail call sled with a similar
+ // sequence as the entry sled, but calls the exit sled instead, so we can
+ // treat tail call exits as if they were normal exits.
+ //
+ // FIXME: In the future we'd need to distinguish between non-tail exits and
+ // tail exits for better information preservation.
+ int64_t TrampolineOffset = reinterpret_cast<int64_t>(__xray_FunctionExit) -
+ (static_cast<int64_t>(Sled.Address) + 11);
+ if (TrampolineOffset < MinOffset || TrampolineOffset > MaxOffset) {
+ Report("XRay Exit trampoline (%p) too far from sled (%p); distance = "
+ "%ld\n",
+ __xray_FunctionExit, reinterpret_cast<void *>(Sled.Address),
+ TrampolineOffset);
+ return false;
+ }
+ if (Enable) {
+ *reinterpret_cast<uint32_t *>(Sled.Address + 2) = FuncId;
+ *reinterpret_cast<uint8_t *>(Sled.Address + 6) = CallOpCode;
+ *reinterpret_cast<uint32_t *>(Sled.Address + 7) = TrampolineOffset;
+ std::atomic_store_explicit(
+ reinterpret_cast<std::atomic<uint16_t> *>(Sled.Address), MovR10Seq,
+ std::memory_order_release);
+ } else {
+ std::atomic_store_explicit(
+ reinterpret_cast<std::atomic<uint16_t> *>(Sled.Address), Jmp9Seq,
+ std::memory_order_release);
+ // FIXME: Write out the nops still?
+ }
+ return true;
+}
+
} // namespace __xray
OpenPOWER on IntegriCloud