diff options
author | Dean Michael Berris <dberris@google.com> | 2016-08-08 03:10:22 +0000 |
---|---|---|
committer | Dean Michael Berris <dberris@google.com> | 2016-08-08 03:10:22 +0000 |
commit | 585545f941de14c15784e9638a00da2ac4df5ed7 (patch) | |
tree | c4a03742fc09b9b3d3ecf05b6e5c5d2a483a790f /lib/xray | |
parent | 790fa40271e6c8b4e4c5994ad4b0303201639dab (diff) |
[compiler-rt][XRay] Implement __xray_unpatch() and __xray_remove_handler()
Summary:
We also add one test (and the XRay testing infrastructure) to exercise
the patching and unpatching code. This uses the XRay API exported
through the headers as well, installing a custom log handler.
Depends on D23101 for the updated emitted code alignment for the
return/entry sleds.
Reviewers: rSerge, echristo, rnk
Subscribers: tberghammer, danalbert, srhines, mehdi_amini, llvm-commits
Differential Revision: https://reviews.llvm.org/D23154
git-svn-id: https://llvm.org/svn/llvm-project/compiler-rt/trunk@277971 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'lib/xray')
-rw-r--r-- | lib/xray/xray_interface.cc | 51 |
1 files changed, 38 insertions, 13 deletions
diff --git a/lib/xray/xray_interface.cc b/lib/xray/xray_interface.cc index ccbe7e2f2..5ef3fc7aa 100644 --- a/lib/xray/xray_interface.cc +++ b/lib/xray/xray_interface.cc @@ -82,6 +82,8 @@ int __xray_set_handler(void (*entry)(int32_t, XRayEntryType)) { return 0; } +int __xray_remove_handler() { return __xray_set_handler(nullptr); } + std::atomic<bool> XRayPatching{false}; using namespace __xray; @@ -104,7 +106,10 @@ template <class Function> CleanupInvoker<Function> ScopeCleanup(Function Fn) { return CleanupInvoker<Function>{Fn}; } -XRayPatchingStatus __xray_patch() { +// ControlPatching implements the common internals of the patching/unpatching +// implementation. |Enable| defines whether we're enabling or disabling the +// runtime XRay instrumentation. +XRayPatchingStatus ControlPatching(bool Enable) { if (!XRayInitialized.load(std::memory_order_acquire)) return XRayPatchingStatus::NOT_INITIALIZED; // Not initialized. @@ -131,7 +136,9 @@ XRayPatchingStatus __xray_patch() { int32_t FuncId = 1; static constexpr uint8_t CallOpCode = 0xe8; static constexpr uint16_t MovR10Seq = 0xba41; + static constexpr uint16_t Jmp9Seq = 0x09eb; static constexpr uint8_t JmpOpCode = 0xe9; + static constexpr uint8_t RetOpCode = 0xc3; uint64_t CurFun = 0; for (std::size_t I = 0; I < InstrMap.Entries; I++) { auto Sled = InstrMap.Sleds[I]; @@ -191,12 +198,19 @@ XRayPatchingStatus __xray_patch() { TrampolineOffset); continue; } - *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); + 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? + } } if (Sled.Kind == XRayEntryType::EXIT) { @@ -231,15 +245,26 @@ XRayPatchingStatus __xray_patch() { TrampolineOffset); continue; } - *reinterpret_cast<uint32_t *>(Sled.Address + 2) = FuncId; - *reinterpret_cast<uint8_t *>(Sled.Address + 6) = JmpOpCode; - *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); + if (Enable) { + *reinterpret_cast<uint32_t *>(Sled.Address + 2) = FuncId; + *reinterpret_cast<uint8_t *>(Sled.Address + 6) = JmpOpCode; + *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<uint8_t> *>(Sled.Address), RetOpCode, + std::memory_order_release); + // FIXME: Write out the nops still? + } } } XRayPatching.store(false, std::memory_order_release); PatchingSuccess = true; return XRayPatchingStatus::SUCCESS; } + +XRayPatchingStatus __xray_patch() { return ControlPatching(true); } + +XRayPatchingStatus __xray_unpatch() { return ControlPatching(false); } |