[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