[compiler-rt] r277971 - [compiler-rt][XRay] Implement __xray_unpatch() and __xray_remove_handler()
Dean Michael Berris via llvm-commits
llvm-commits at lists.llvm.org
Sun Aug 7 20:10:23 PDT 2016
Author: dberris
Date: Sun Aug 7 22:10:22 2016
New Revision: 277971
URL: http://llvm.org/viewvc/llvm-project?rev=277971&view=rev
Log:
[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
Added:
compiler-rt/trunk/test/xray/
compiler-rt/trunk/test/xray/CMakeLists.txt
compiler-rt/trunk/test/xray/TestCases/
compiler-rt/trunk/test/xray/TestCases/Linux/
compiler-rt/trunk/test/xray/TestCases/Linux/patching-unpatching.cc
compiler-rt/trunk/test/xray/lit.cfg
compiler-rt/trunk/test/xray/lit.site.cfg.in
Modified:
compiler-rt/trunk/lib/xray/xray_interface.cc
compiler-rt/trunk/test/CMakeLists.txt
Modified: compiler-rt/trunk/lib/xray/xray_interface.cc
URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/xray/xray_interface.cc?rev=277971&r1=277970&r2=277971&view=diff
==============================================================================
--- compiler-rt/trunk/lib/xray/xray_interface.cc (original)
+++ compiler-rt/trunk/lib/xray/xray_interface.cc Sun Aug 7 22:10:22 2016
@@ -82,6 +82,8 @@ int __xray_set_handler(void (*entry)(int
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
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); }
Modified: compiler-rt/trunk/test/CMakeLists.txt
URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/test/CMakeLists.txt?rev=277971&r1=277970&r2=277971&view=diff
==============================================================================
--- compiler-rt/trunk/test/CMakeLists.txt (original)
+++ compiler-rt/trunk/test/CMakeLists.txt Sun Aug 7 22:10:22 2016
@@ -79,6 +79,9 @@ if(COMPILER_RT_CAN_EXECUTE_TESTS)
if(COMPILER_RT_HAS_SCUDO)
add_subdirectory(scudo)
endif()
+ if(COMPILER_RT_HAS_XRAY)
+ add_subdirectory(xray)
+ endif()
endif()
if(COMPILER_RT_STANDALONE_BUILD)
Added: compiler-rt/trunk/test/xray/CMakeLists.txt
URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/test/xray/CMakeLists.txt?rev=277971&view=auto
==============================================================================
--- compiler-rt/trunk/test/xray/CMakeLists.txt (added)
+++ compiler-rt/trunk/test/xray/CMakeLists.txt Sun Aug 7 22:10:22 2016
@@ -0,0 +1,37 @@
+set(XRAY_LIT_SOURCE_DIR ${CMAKE_CURRENT_SOURCE_DIR})
+
+set(XRAY_TESTSUITES)
+
+set(XRAY_TEST_DEPS ${SANITIZER_COMMON_LIT_TEST_DEPS})
+if(NOT COMPILER_RT_STANDALONE_BUILD)
+ list(APPEND XRAY_TEST_DEPS xray)
+endif()
+
+set(XRAY_TEST_ARCH ${XRAY_SUPPORTED_ARCH})
+foreach(arch ${XRAY_TEST_ARCH})
+ set(XRAY_TEST_TARGET_ARCH ${arch})
+ string(TOLOWER "-${arch}-${OS_NAME}" XRAY_TEST_CONFIG_SUFFIX)
+
+ if(ANDROID OR ${arch} MATCHES "arm|aarch64")
+ # This is only true if we are cross-compiling.
+ # Build all tests with host compiler and use host tools.
+ set(XRAY_TEST_TARGET_CC ${COMPILER_RT_TEST_COMPILER})
+ set(XRAY_TEST_TARGET_CFLAGS ${COMPILER_RT_TEST_COMPILER_CFLAGS})
+ else()
+ get_target_flags_for_arch(${arch} XRAY_TEST_TARGET_CFLAGS)
+ string(REPLACE ";" " " XRAY_TEST_TARGET_CFLAGS "${XRAY_TEST_TARGET_CFLAGS}")
+ endif()
+
+ string(TOUPPER ${arch} ARCH_UPPER_CASE)
+ set(CONFIG_NAME ${ARCH_UPPER_CASE}${OS_NAME}Config)
+
+ configure_lit_site_cfg(
+ ${CMAKE_CURRENT_SOURCE_DIR}/lit.site.cfg.in
+ ${CMAKE_CURRENT_BINARY_DIR}/${CONFIG_NAME}/lit.site.cfg)
+ list(APPEND XRAY_TESTSUITES ${CMAKE_CURRENT_BINARY_DIR}/${CONFIG_NAME})
+endforeach()
+
+add_lit_testsuite(check-xray "Running the XRay tests"
+ ${XRAY_TESTSUITES}
+ DEPENDS ${XRAY_TEST_DEPS})
+set_target_properties(check-xray PROPERTIES FOLDER "Compiler-RT Misc")
Added: compiler-rt/trunk/test/xray/TestCases/Linux/patching-unpatching.cc
URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/test/xray/TestCases/Linux/patching-unpatching.cc?rev=277971&view=auto
==============================================================================
--- compiler-rt/trunk/test/xray/TestCases/Linux/patching-unpatching.cc (added)
+++ compiler-rt/trunk/test/xray/TestCases/Linux/patching-unpatching.cc Sun Aug 7 22:10:22 2016
@@ -0,0 +1,47 @@
+// Check that we can patch and un-patch on demand, and that logging gets invoked
+// appropriately.
+//
+// RUN: %clangxx_xray -fxray-instrument -std=c++11 %s -o %t
+// RUN: XRAY_OPTIONS="patch_premain=false" %run %t 2>&1 | FileCheck %s
+
+#include "xray/xray_interface.h"
+
+#include <cstdio>
+
+bool called = false;
+
+void test_handler(int32_t fid, XRayEntryType type) {
+ printf("called: %d, type=%d\n", fid, static_cast<int32_t>(type));
+ called = true;
+}
+
+[[clang::xray_always_instrument]] void always_instrument() {
+ printf("always instrumented called\n");
+}
+
+int main() {
+ __xray_set_handler(test_handler);
+ always_instrument();
+ // CHECK: always instrumented called
+ auto status = __xray_patch();
+ printf("patching status: %d\n", static_cast<int32_t>(status));
+ // CHECK-NEXT: patching status: 1
+ always_instrument();
+ // CHECK-NEXT: called: {{.*}}, type=0
+ // CHECK-NEXT: always instrumented called
+ // CHECK-NEXT: called: {{.*}}, type=1
+ status = __xray_unpatch();
+ printf("patching status: %d\n", static_cast<int32_t>(status));
+ // CHECK-NEXT: patching status: 1
+ always_instrument();
+ // CHECK-NEXT: always instrumented called
+ status = __xray_patch();
+ printf("patching status: %d\n", static_cast<int32_t>(status));
+ // CHECK-NEXT: patching status: 1
+ __xray_remove_handler();
+ always_instrument();
+ // CHECK-NEXT: always instrumented called
+ status = __xray_unpatch();
+ printf("patching status: %d\n", static_cast<int32_t>(status));
+ // CHECK-NEXT: patching status: 1
+}
Added: compiler-rt/trunk/test/xray/lit.cfg
URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/test/xray/lit.cfg?rev=277971&view=auto
==============================================================================
--- compiler-rt/trunk/test/xray/lit.cfg (added)
+++ compiler-rt/trunk/test/xray/lit.cfg Sun Aug 7 22:10:22 2016
@@ -0,0 +1,34 @@
+# -*- Python -*-
+
+import os
+
+# Setup config name.
+config.name = 'XRay' + config.name_suffix
+
+# Setup source root.
+config.test_source_root = os.path.dirname(__file__)
+
+# Setup default compiler flags use with -fxray-instrument option.
+clang_xray_cflags = (['-fxray-instrument', config.target_cflags])
+clang_xray_cxxflags = config.cxx_mode_flags + clang_xray_cflags
+
+
+def build_invocation(compile_flags):
+ return ' ' + ' '.join([config.clang] + compile_flags) + ' '
+
+# Setup substitutions.
+config.substitutions.append(
+ ('%clang ', build_invocation([config.target_cflags])))
+config.substitutions.append(
+ ('%clangxx ',
+ build_invocation(config.cxx_mode_flags + [config.target_cflags])))
+config.substitutions.append(
+ ('%clang_xray ', build_invocation(clang_xray_cflags)))
+config.substitutions.append(
+ ('%clangxx_xray', build_invocation(clang_xray_cxxflags)))
+
+# Default test suffixes.
+config.suffixes = ['.c', '.cc', '.cpp']
+
+if config.host_os not in ['Linux'] or config.host_arch.find('64') == -1:
+ config.unsupported = True
Added: compiler-rt/trunk/test/xray/lit.site.cfg.in
URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/test/xray/lit.site.cfg.in?rev=277971&view=auto
==============================================================================
--- compiler-rt/trunk/test/xray/lit.site.cfg.in (added)
+++ compiler-rt/trunk/test/xray/lit.site.cfg.in Sun Aug 7 22:10:22 2016
@@ -0,0 +1,13 @@
+ at LIT_SITE_CFG_IN_HEADER@
+
+# Tool-specific config options.
+config.name_suffix = "@XRAY_TEST_CONFIG_SUFFIX@"
+config.xray_lit_source_dir = "@XRAY_LIT_SOURCE_DIR@"
+config.target_cflags = "@XRAY_TEST_TARGET_CFLAGS@"
+config.target_arch = "@XRAY_TEST_TARGET_ARCH@"
+
+# Load common config for all compiler-rt lit tests
+lit_config.load_config(config, "@COMPILER_RT_BINARY_DIR@/test/lit.common.configured")
+
+# Load tool-specific config that would do the real work.
+lit_config.load_config(config, "@XRAY_LIT_SOURCE_DIR@/lit.cfg")
More information about the llvm-commits
mailing list