[compiler-rt] r276117 - [compiler-rt] [XRay] Basic initialization and flag definition for XRay runtime

Dean Michael Berris via llvm-commits llvm-commits at lists.llvm.org
Wed Jul 20 07:14:51 PDT 2016


Author: dberris
Date: Wed Jul 20 09:14:50 2016
New Revision: 276117

URL: http://llvm.org/viewvc/llvm-project?rev=276117&view=rev
Log:
[compiler-rt] [XRay] Basic initialization and flag definition for XRay runtime

Summary:
This patch implements the initialisation and patching routines for the XRay runtime, along with the necessary trampolines for function entry/exit handling. For now we only define the basic hooks for allowing an implementation to define a handler that gets run on function entry/exit. We expose a minimal API for controlling the behaviour of the runtime (patching, cleanup, and setting the handler to invoke when instrumenting).

Depends on D19904

Reviewers: echristo, kcc, rnk

Subscribers: rnk, mehdi_amini, llvm-commits

Differential Revision: https://reviews.llvm.org/D21612

Added:
    compiler-rt/trunk/include/xray/
    compiler-rt/trunk/include/xray/xray_interface.h
    compiler-rt/trunk/lib/xray/
    compiler-rt/trunk/lib/xray/CMakeLists.txt
    compiler-rt/trunk/lib/xray/xray_flags.cc
    compiler-rt/trunk/lib/xray/xray_flags.h
    compiler-rt/trunk/lib/xray/xray_flags.inc
    compiler-rt/trunk/lib/xray/xray_init.cc
    compiler-rt/trunk/lib/xray/xray_interface.cc
    compiler-rt/trunk/lib/xray/xray_interface_internal.h
    compiler-rt/trunk/lib/xray/xray_trampoline_x86.S
Modified:
    compiler-rt/trunk/CMakeLists.txt
    compiler-rt/trunk/cmake/config-ix.cmake
    compiler-rt/trunk/include/CMakeLists.txt
    compiler-rt/trunk/lib/CMakeLists.txt

Modified: compiler-rt/trunk/CMakeLists.txt
URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/CMakeLists.txt?rev=276117&r1=276116&r2=276117&view=diff
==============================================================================
--- compiler-rt/trunk/CMakeLists.txt (original)
+++ compiler-rt/trunk/CMakeLists.txt Wed Jul 20 09:14:50 2016
@@ -37,6 +37,8 @@ option(COMPILER_RT_BUILD_BUILTINS "Build
 mark_as_advanced(COMPILER_RT_BUILD_BUILTINS)
 option(COMPILER_RT_BUILD_SANITIZERS "Build sanitizers" ON)
 mark_as_advanced(COMPILER_RT_BUILD_SANITIZERS)
+option(COMPILER_RT_BUILD_XRAY "Build xray" ON)
+mark_as_advanced(COMPILER_RT_BUILD_XRAY)
 
 if (COMPILER_RT_STANDALONE_BUILD)
   if (NOT LLVM_CONFIG_PATH)

Modified: compiler-rt/trunk/cmake/config-ix.cmake
URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/cmake/config-ix.cmake?rev=276117&r1=276116&r2=276117&view=diff
==============================================================================
--- compiler-rt/trunk/cmake/config-ix.cmake (original)
+++ compiler-rt/trunk/cmake/config-ix.cmake Wed Jul 20 09:14:50 2016
@@ -161,6 +161,7 @@ set(ALL_SAFESTACK_SUPPORTED_ARCH ${X86}
 set(ALL_CFI_SUPPORTED_ARCH ${X86} ${X86_64} ${MIPS64})
 set(ALL_ESAN_SUPPORTED_ARCH ${X86_64})
 set(ALL_SCUDO_SUPPORTED_ARCH ${X86_64})
+set(ALL_XRAY_SUPPORTED_ARCH ${X86_64})
 
 if(APPLE)
   include(CompilerRTDarwinUtils)
@@ -350,6 +351,9 @@ if(APPLE)
   list_intersect(SCUDO_SUPPORTED_ARCH
     ALL_SCUDO_SUPPORTED_ARCH
     SANITIZER_COMMON_SUPPORTED_ARCH)
+  list_intersect(XRAY_SUPPORTED_ARCH
+    ALL_XRAY_SUPPORTED_ARCH
+    SANITIZER_COMMON_SUPPORTED_ARCH)
 else()
   # Architectures supported by compiler-rt libraries.
   filter_available_targets(SANITIZER_COMMON_SUPPORTED_ARCH
@@ -373,6 +377,7 @@ else()
   filter_available_targets(ESAN_SUPPORTED_ARCH ${ALL_ESAN_SUPPORTED_ARCH})
   filter_available_targets(SCUDO_SUPPORTED_ARCH
     ${ALL_SCUDO_SUPPORTED_ARCH})
+  filter_available_targets(XRAY_SUPPORTED_ARCH ${ALL_XRAY_SUPPORTED_ARCH})
 endif()
 
 if (MSVC)

Modified: compiler-rt/trunk/include/CMakeLists.txt
URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/include/CMakeLists.txt?rev=276117&r1=276116&r2=276117&view=diff
==============================================================================
--- compiler-rt/trunk/include/CMakeLists.txt (original)
+++ compiler-rt/trunk/include/CMakeLists.txt Wed Jul 20 09:14:50 2016
@@ -10,11 +10,18 @@ set(SANITIZER_HEADERS
   sanitizer/msan_interface.h
   sanitizer/tsan_interface_atomic.h)
 
+set(XRAY_HEADERS
+  xray/xray_interface.h)
+
+set(COMPILER_RT_HEADERS
+  ${SANITIZER_HEADERS}
+	${XRAY_HEADERS})
+
 set(output_dir ${COMPILER_RT_OUTPUT_DIR}/include)
 
 # Copy compiler-rt headers to the build tree.
 set(out_files)
-foreach( f ${SANITIZER_HEADERS} )
+foreach( f ${COMPILER_RT_HEADERS} )
   set( src ${CMAKE_CURRENT_SOURCE_DIR}/${f} )
   set( dst ${output_dir}/${f} )
   add_custom_command(OUTPUT ${dst}
@@ -32,3 +39,7 @@ set_target_properties(compiler-rt-header
 install(FILES ${SANITIZER_HEADERS}
   PERMISSIONS OWNER_READ OWNER_WRITE GROUP_READ WORLD_READ
   DESTINATION ${COMPILER_RT_INSTALL_PATH}/include/sanitizer)
+# Install xray headers.
+install(FILES ${XRAY_HEADERS}
+  PERMISSIONS OWNER_READ OWNER_WRITE GROUP_READ WORLD_READ
+  DESTINATION ${COMPILER_RT_INSTALL_PATH}/include/xray)

Added: compiler-rt/trunk/include/xray/xray_interface.h
URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/include/xray/xray_interface.h?rev=276117&view=auto
==============================================================================
--- compiler-rt/trunk/include/xray/xray_interface.h (added)
+++ compiler-rt/trunk/include/xray/xray_interface.h Wed Jul 20 09:14:50 2016
@@ -0,0 +1,66 @@
+//===-- xray_interface.h ----------------------------------------*- C++ -*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file is a part of XRay, a dynamic runtime instrumentation system.
+//
+// APIs for controlling XRay functionality explicitly.
+//===----------------------------------------------------------------------===//
+#ifndef XRAY_XRAY_INTERFACE_H
+#define XRAY_XRAY_INTERFACE_H
+
+#include <cstdint>
+
+extern "C" {
+
+enum XRayEntryType { ENTRY = 0, EXIT = 1 };
+
+// Provide a function to invoke for when instrumentation points are hit. This is
+// a user-visible control surface that overrides the default implementation. The
+// function provided should take the following arguments:
+//
+//   - function id: an identifier that indicates the id of a function; this id
+//                  is generated by xray; the mapping between the function id
+//                  and the actual function pointer is available through
+//                  __xray_table.
+//   - entry type: identifies what kind of instrumentation point was encountered
+//                 (function entry, function exit, etc.). See the enum
+//                 XRayEntryType for more details.
+//
+// Returns 1 on success, 0 on error.
+extern int __xray_set_handler(void (*entry)(int32_t, XRayEntryType));
+
+// This removes whatever the currently provided handler is. Returns 1 on
+// success, 0 on error.
+extern int __xray_remove_handler();
+
+enum XRayPatchingStatus {
+  NOT_INITIALIZED = 0,
+  NOTIFIED = 1,
+  ONGOING = 2,
+  FAILED = 3
+};
+
+// This tells XRay to patch the instrumentation points. This is an asynchronous
+// process, and returns the following status in specific cases:
+//
+//   - 0 : XRay is not initialized.
+//   - 1 : We've done the notification.
+//   - 2 : Patching / un-patching is on-going.
+extern XRayPatchingStatus __xray_patch();
+
+// Reverses the effect of __xray_patch(). This is an asynchronous process, and
+// returns the following status in specific cases.
+//
+//   - 0 : XRay is not initialized.
+//   - 1 : We've done the notification.
+//   - 2 : Patching / un-patching is on-going.
+extern int __xray_unpatch();
+}
+
+#endif

Modified: compiler-rt/trunk/lib/CMakeLists.txt
URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/CMakeLists.txt?rev=276117&r1=276116&r2=276117&view=diff
==============================================================================
--- compiler-rt/trunk/lib/CMakeLists.txt (original)
+++ compiler-rt/trunk/lib/CMakeLists.txt Wed Jul 20 09:14:50 2016
@@ -57,3 +57,7 @@ if(COMPILER_RT_BUILD_SANITIZERS)
     add_subdirectory(scudo)
   endif()
 endif()
+
+if(COMPILER_RT_BUILD_XRAY)
+  add_subdirectory(xray)
+endif()

Added: compiler-rt/trunk/lib/xray/CMakeLists.txt
URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/xray/CMakeLists.txt?rev=276117&view=auto
==============================================================================
--- compiler-rt/trunk/lib/xray/CMakeLists.txt (added)
+++ compiler-rt/trunk/lib/xray/CMakeLists.txt Wed Jul 20 09:14:50 2016
@@ -0,0 +1,47 @@
+# Build for the XRay runtime support library.
+
+set(XRAY_SOURCES
+  xray_init.cc
+	xray_interface.cc
+	xray_flags.cc
+)
+
+set(x86_64_SOURCES
+		xray_trampoline_x86.S
+		${XRAY_SOURCES})
+
+include_directories(..)
+include_directories(../../include)
+
+set(XRAY_CFLAGS ${SANITIZER_COMMON_CFLAGS})
+
+set(XRAY_COMMON_DEFINITIONS XRAY_HAS_EXCEPTIONS=1)
+
+add_compiler_rt_object_libraries(RTXray
+		ARCHS ${XRAY_SUPPORTED_ARCH}
+		SOURCES ${XRAY_SOURCES} CFLAGS ${XRAY_CFLAGS}
+		DEFS ${XRAY_COMMON_DEFINITIONS})
+
+add_custom_target(xray)
+set(XRAY_COMMON_RUNTIME_OBJECT_LIBS
+		RTSanitizerCommon
+		RTSanitizerCommonLibc)
+
+foreach (arch ${XRAY_SUPPORTED_ARCH})
+		if (CAN_TARGET_${arch})
+				add_compiler_rt_runtime(clang_rt.xray
+						STATIC
+						ARCHS ${arch}
+						SOURCES ${${arch}_SOURCES}
+						CFLAGS ${XRAY_CFLAGS}
+						DEFS ${XRAY_COMMON_DEFINITIONS}
+						OBJECT_LIBS ${XRAY_COMMON_RUNTIME_OBJECT_LIBS}
+						PARENT_TARGET xray)
+		endif ()
+endforeach()
+
+add_dependencies(compiler-rt xray)
+
+# if(COMPILER_RT_INCLUDE_TESTS)
+#   add_subdirectory(tests)
+# endif()

Added: compiler-rt/trunk/lib/xray/xray_flags.cc
URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/xray/xray_flags.cc?rev=276117&view=auto
==============================================================================
--- compiler-rt/trunk/lib/xray/xray_flags.cc (added)
+++ compiler-rt/trunk/lib/xray/xray_flags.cc Wed Jul 20 09:14:50 2016
@@ -0,0 +1,61 @@
+//===-- xray_flags.cc -------------------------------------------*- C++ -*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file is a part of XRay, a dynamic runtime instrumentation system.
+//
+// XRay flag parsing logic.
+//===----------------------------------------------------------------------===//
+
+#include "xray_flags.h"
+#include "sanitizer_common/sanitizer_common.h"
+#include "sanitizer_common/sanitizer_flag_parser.h"
+#include "sanitizer_common/sanitizer_libc.h"
+
+using namespace __sanitizer;
+
+namespace __xray {
+
+Flags xray_flags_dont_use_directly; // use via flags().
+
+void Flags::SetDefaults() {
+#define XRAY_FLAG(Type, Name, DefaultValue, Description) Name = DefaultValue;
+#include "xray_flags.inc"
+#undef XRAY_FLAG
+}
+
+static void RegisterXRayFlags(FlagParser *P, Flags *F) {
+#define XRAY_FLAG(Type, Name, DefaultValue, Description)                       \
+  RegisterFlag(P, #Name, Description, &F->Name);
+#include "xray_flags.inc"
+#undef XRAY_FLAG
+}
+
+void InitializeFlags() {
+  SetCommonFlagsDefaults();
+  auto *F = flags();
+  F->SetDefaults();
+
+  FlagParser XRayParser;
+  RegisterXRayFlags(&XRayParser, F);
+  RegisterCommonFlags(&XRayParser);
+
+  // Override from command line.
+  XRayParser.ParseString(GetEnv("XRAY_OPTIONS"));
+
+  InitializeCommonFlags();
+
+  if (Verbosity())
+    ReportUnrecognizedFlags();
+
+  if (common_flags()->help) {
+    XRayParser.PrintFlagDescriptions();
+  }
+}
+
+} // namespace __xray

Added: compiler-rt/trunk/lib/xray/xray_flags.h
URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/xray/xray_flags.h?rev=276117&view=auto
==============================================================================
--- compiler-rt/trunk/lib/xray/xray_flags.h (added)
+++ compiler-rt/trunk/lib/xray/xray_flags.h Wed Jul 20 09:14:50 2016
@@ -0,0 +1,37 @@
+//===-- xray_flags.h -------------------------------------------*- C++ -*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file is a part of XRay, a dynamic runtime instruementation system.
+//
+// XRay runtime flags.
+//===----------------------------------------------------------------------===//
+
+#ifndef XRAY_FLAGS_H
+#define XRAY_FLAGS_H
+
+#include "sanitizer_common/sanitizer_flag_parser.h"
+
+namespace __xray {
+
+struct Flags {
+#define XRAY_FLAG(Type, Name, DefaultValue, Description) Type Name;
+#include "xray_flags.inc"
+#undef XRAY_FLAG
+
+  void SetDefaults();
+};
+
+extern Flags xray_flags_dont_use_directly;
+inline Flags *flags() { return &xray_flags_dont_use_directly; }
+
+void InitializeFlags();
+
+} // namespace __xray
+
+#endif // XRAY_FLAGS_H

Added: compiler-rt/trunk/lib/xray/xray_flags.inc
URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/xray/xray_flags.inc?rev=276117&view=auto
==============================================================================
--- compiler-rt/trunk/lib/xray/xray_flags.inc (added)
+++ compiler-rt/trunk/lib/xray/xray_flags.inc Wed Jul 20 09:14:50 2016
@@ -0,0 +1,18 @@
+//===-- xray_flags.inc ------------------------------------------*- C++ -*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// XRay runtime flags.
+//
+//===----------------------------------------------------------------------===//
+#ifndef XRAY_FLAG
+#error "Define XRAY_FLAG prior to including this file!"
+#endif
+
+XRAY_FLAG(bool, patch_premain, true,
+          "Whether to patch instrumentation points before main.")

Added: compiler-rt/trunk/lib/xray/xray_init.cc
URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/xray/xray_init.cc?rev=276117&view=auto
==============================================================================
--- compiler-rt/trunk/lib/xray/xray_init.cc (added)
+++ compiler-rt/trunk/lib/xray/xray_init.cc Wed Jul 20 09:14:50 2016
@@ -0,0 +1,68 @@
+//===-- xray_init.cc --------------------------------------------*- C++ -*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file is a part of XRay, a dynamic runtime instrumentation system.
+//
+// XRay initialisation logic.
+//===----------------------------------------------------------------------===//
+
+#include <atomic>
+#include <fcntl.h>
+#include <strings.h>
+#include <unistd.h>
+
+#include "sanitizer_common/sanitizer_common.h"
+#include "xray_flags.h"
+#include "xray_interface_internal.h"
+#include "llvm/Support/ELF.h"
+
+extern "C" {
+extern void __xray_init();
+extern const XRaySledEntry __start_xray_instr_map[] __attribute__((weak));
+extern const XRaySledEntry __stop_xray_instr_map[] __attribute__((weak));
+}
+
+using namespace __xray;
+
+// We initialize some global variables that pertain to specific sections of XRay
+// data structures in the binary. We do this for the current process using
+// /proc/curproc/map and make sure that we're able to get it. We signal failure
+// via a global atomic boolean to indicate whether we've initialized properly.
+//
+std::atomic<bool> XRayInitialized{false};
+
+// This should always be updated before XRayInitialized is updated.
+std::atomic<__xray::XRaySledMap> XRayInstrMap{};
+
+// __xray_init() will do the actual loading of the current process' memory map
+// and then proceed to look for the .xray_instr_map section/segment.
+void __xray_init() {
+  InitializeFlags();
+  if (__start_xray_instr_map == nullptr) {
+    Report("XRay instrumentation map missing. Not initializing XRay.\n");
+    return;
+  }
+
+  // Now initialize the XRayInstrMap global struct with the address of the
+  // entries, reinterpreted as an array of XRaySledEntry objects. We use the
+  // virtual pointer we have from the section to provide us the correct
+  // information.
+  __xray::XRaySledMap SledMap{};
+  SledMap.Sleds = __start_xray_instr_map;
+  SledMap.Entries = __stop_xray_instr_map - __start_xray_instr_map;
+  XRayInstrMap.store(SledMap, std::memory_order_release);
+  XRayInitialized.store(true, std::memory_order_release);
+
+  // FIXME: Check the flag/environment before patching.
+  if (flags()->patch_premain)
+    __xray_patch();
+}
+
+__attribute__((section(".preinit_array"),
+               used)) void (*__local_xray_preinit)(void) = __xray_init;

Added: compiler-rt/trunk/lib/xray/xray_interface.cc
URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/xray/xray_interface.cc?rev=276117&view=auto
==============================================================================
--- compiler-rt/trunk/lib/xray/xray_interface.cc (added)
+++ compiler-rt/trunk/lib/xray/xray_interface.cc Wed Jul 20 09:14:50 2016
@@ -0,0 +1,179 @@
+//===-- xray_interface.cpp --------------------------------------*- C++ -*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file is a part of XRay, a dynamic runtime instrumentation system.
+//
+// Implementation of the API functions.
+//
+//===----------------------------------------------------------------------===//
+
+#include "xray_interface_internal.h"
+#include <atomic>
+#include <cstdint>
+#include <cstdio>
+#include <errno.h>
+#include <limits>
+#include <sys/mman.h>
+
+namespace __xray {
+
+// This is the function to call when we encounter the entry or exit sleds.
+std::atomic<void (*)(int32_t, XRayEntryType)> XRayPatchedFunction{nullptr};
+
+} // namespace __xray
+
+extern "C" {
+// The following functions have to be defined in assembler, on a per-platform
+// basis. See xray_trampoline_*.s files for implementations.
+extern void __xray_FunctionEntry();
+extern void __xray_FunctionExit();
+}
+
+extern std::atomic<bool> XRayInitialized;
+extern std::atomic<__xray::XRaySledMap> XRayInstrMap;
+
+int __xray_set_handler(void (*entry)(int32_t, XRayEntryType)) {
+  if (XRayInitialized.load(std::memory_order_acquire)) {
+    __xray::XRayPatchedFunction.store(entry, std::memory_order_release);
+    return 1;
+  }
+  return 0;
+}
+
+std::atomic<bool> XRayPatching{false};
+
+XRayPatchingStatus __xray_patch() {
+  // FIXME: Make this happen asynchronously. For now just do this sequentially.
+  if (!XRayInitialized.load(std::memory_order_acquire))
+    return XRayPatchingStatus::NOT_INITIALIZED; // Not initialized.
+
+  static bool NotPatching = false;
+  if (!XRayPatching.compare_exchange_strong(NotPatching, true,
+                                            std::memory_order_acq_rel,
+                                            std::memory_order_acquire)) {
+    return XRayPatchingStatus::ONGOING; // Already patching.
+  }
+
+  // Step 1: Compute the function id, as a unique identifier per function in the
+  // instrumentation map.
+  __xray::XRaySledMap InstrMap = XRayInstrMap.load(std::memory_order_acquire);
+  if (InstrMap.Entries == 0)
+    return XRayPatchingStatus::NOT_INITIALIZED;
+
+  int32_t FuncId = 1;
+  static constexpr uint8_t CallOpCode = 0xe8;
+  static constexpr uint16_t MovR10Seq = 0xba41;
+  static constexpr uint8_t JmpOpCode = 0xe9;
+  uint64_t CurFun = 0;
+  for (std::size_t I = 0; I < InstrMap.Entries; I++) {
+    auto Sled = InstrMap.Sleds[I];
+    auto F = Sled.Function;
+    if (CurFun == 0)
+      CurFun = F;
+    if (F != CurFun) {
+      ++FuncId;
+      CurFun = F;
+    }
+
+    // While we're here, we should patch the nop sled. To do that we mprotect
+    // the page containing the function to be writeable.
+    void *PageAlignedAddr =
+        reinterpret_cast<void *>(Sled.Address & ~((2 << 16) - 1));
+    std::size_t MProtectLen =
+        (Sled.Address + 12) - reinterpret_cast<uint64_t>(PageAlignedAddr);
+    if (mprotect(PageAlignedAddr, MProtectLen,
+                 PROT_READ | PROT_WRITE | PROT_EXEC) == -1) {
+      printf("Failed mprotect: %d\n", errno);
+      return XRayPatchingStatus::FAILED;
+    }
+
+    static constexpr int64_t MinOffset{std::numeric_limits<int32_t>::min()};
+    static constexpr int64_t MaxOffset{std::numeric_limits<int32_t>::max()};
+    if (Sled.Kind == XRayEntryType::ENTRY) {
+      // Here we do the dance of replacing the following sled:
+      //
+      // xray_sled_n:
+      //   jmp +9
+      //   <9 byte nop>
+      //
+      // With the following:
+      //
+      //   mov r10d, <function id>
+      //   call <relative 32bit offset to entry trampoline>
+      //
+      // We need to do this in the following order:
+      //
+      // 1. Put the function id first, 2 bytes from the start of the sled (just
+      // after the 2-byte jmp instruction).
+      // 2. Put the call opcode 6 bytes from the start of the sled.
+      // 3. Put the relative offset 7 bytes from the start of the sled.
+      // 4. Do an atomic write over the jmp instruction for the "mov r10d"
+      // opcode and first operand.
+      //
+      // Prerequisite is to compute the relative offset to the
+      // __xray_FunctionEntry function's address.
+      int64_t TrampolineOffset =
+          reinterpret_cast<int64_t>(__xray_FunctionEntry) -
+          (static_cast<int64_t>(Sled.Address) + 11);
+      if (TrampolineOffset < MinOffset || TrampolineOffset > MaxOffset) {
+        // FIXME: Print out an error here.
+        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 (Sled.Kind == XRayEntryType::EXIT) {
+      // Here we do the dance of replacing the following sled:
+      //
+      // xray_sled_n:
+      //   ret
+      //   <10 byte nop>
+      //
+      // With the following:
+      //
+      //   mov r10d, <function id>
+      //   jmp <relative 32bit offset to exit trampoline>
+      //
+      // 1. Put the function id first, 2 bytes from the start of the sled (just
+      // after the 1-byte ret instruction).
+      // 2. Put the jmp opcode 6 bytes from the start of the sled.
+      // 3. Put the relative offset 7 bytes from the start of the sled.
+      // 4. Do an atomic write over the jmp instruction for the "mov r10d"
+      // opcode and first operand.
+      //
+      // Prerequisite is to compute the relative offset fo the
+      // __xray_FunctionExit function's address.
+      int64_t TrampolineOffset =
+          reinterpret_cast<int64_t>(__xray_FunctionExit) -
+          (static_cast<int64_t>(Sled.Address) + 11);
+      if (TrampolineOffset < MinOffset || TrampolineOffset > MaxOffset) {
+        // FIXME: Print out an error here.
+        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 (mprotect(PageAlignedAddr, MProtectLen, PROT_READ | PROT_EXEC) == -1) {
+      printf("Failed mprotect: %d\n", errno);
+      return XRayPatchingStatus::FAILED;
+    }
+  }
+  XRayPatching.store(false, std::memory_order_release);
+  return XRayPatchingStatus::NOTIFIED;
+}

Added: compiler-rt/trunk/lib/xray/xray_interface_internal.h
URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/xray/xray_interface_internal.h?rev=276117&view=auto
==============================================================================
--- compiler-rt/trunk/lib/xray/xray_interface_internal.h (added)
+++ compiler-rt/trunk/lib/xray/xray_interface_internal.h Wed Jul 20 09:14:50 2016
@@ -0,0 +1,40 @@
+//===-- xray_interface_internal.h -------------------------------*- C++ -*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file is a part of XRay, a dynamic runtime instrumentation system.
+//
+// Implementation of the API functions. See also include/xray/xray_interface.h.
+//
+//===----------------------------------------------------------------------===//
+#ifndef XRAY_INTERFACE_INTERNAL_H
+#define XRAY_INTERFACE_INTERNAL_H
+
+#include "xray/xray_interface.h"
+#include <cstdint>
+
+extern "C" {
+
+struct XRaySledEntry {
+  uint64_t Address;
+  uint64_t Function;
+  unsigned char Kind;
+  unsigned char AlwaysInstrument;
+  unsigned char Padding[14]; // Need 32 bytes
+};
+}
+
+namespace __xray {
+
+struct XRaySledMap {
+  const XRaySledEntry *Sleds;
+  std::size_t Entries;
+};
+}
+
+#endif

Added: compiler-rt/trunk/lib/xray/xray_trampoline_x86.S
URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/xray/xray_trampoline_x86.S?rev=276117&view=auto
==============================================================================
--- compiler-rt/trunk/lib/xray/xray_trampoline_x86.S (added)
+++ compiler-rt/trunk/lib/xray/xray_trampoline_x86.S Wed Jul 20 09:14:50 2016
@@ -0,0 +1,93 @@
+//===-- xray_trampoline_x86.s -----------------------------------*- ASM -*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file is a part of XRay, a dynamic runtime instrumentation system.
+//
+// This implements the X86-specific assembler for the trampolines.
+//
+//===----------------------------------------------------------------------===//
+
+	.text
+	.file "xray_trampoline_x86.S"
+	.globl __xray_FunctionEntry
+	.align 16, 0x90
+	.type __xray_FunctionEntry, at function
+
+__xray_FunctionEntry:
+  .cfi_startproc
+  // Save caller provided registers before doing any actual work.
+	pushq %rbp
+	.cfi_def_cfa_offset 16
+	subq $72, %rsp
+	movq	%rdi, 64(%rsp)
+	movq  %rax, 56(%rsp)
+	movq  %rdx, 48(%rsp)
+	movq	%rsi, 40(%rsp)
+	movq	%rcx, 32(%rsp)
+	movq	%r8, 24(%rsp)
+	movq	%r9, 16(%rsp)
+
+	// de-mangled, that's __xray::XRayPatchedFunction, and we're doing an acquire
+	// load (on x86 is a normal mov instruction).
+	movq	_ZN6__xray19XRayPatchedFunctionE(%rip), %rax
+	testq	%rax, %rax
+	je	.Ltmp0
+
+	// assume that %r10d has the function id.
+	movl	%r10d, %edi
+	xor	%esi,%esi
+	callq	*%rax
+.Ltmp0:
+  // restore the registers
+	movq	64(%rsp), %rdi
+	movq  56(%rsp), %rax
+	movq  48(%rsp), %rdx
+	movq	40(%rsp), %rsi
+	movq	32(%rsp), %rcx
+	movq	24(%rsp), %r8
+	movq	16(%rsp), %r9
+	addq	$72, %rsp
+	popq	%rbp
+	retq
+.Ltmp1:
+	.size __xray_FunctionEntry, .Ltmp1-__xray_FunctionEntry
+	.cfi_endproc
+
+	.globl __xray_FunctionExit
+	.align 16, 0x90
+	.type __xray_FunctionExit, at function
+__xray_FunctionExit:
+	.cfi_startproc
+	// Save the important registers first. Since we're assuming that this
+	// function is only jumped into, we only preserve the registers for
+	// returning.
+	// FIXME: Figure out whether this is sufficient.
+	pushq	%rbp
+	.cfi_def_cfa_offset 16
+	subq	$24, %rsp
+	.cfi_def_cfa_offset 32
+	movq	%rax, 16(%rsp)
+	movq	%rdx, 8(%rsp)
+	movq	_ZN6__xray19XRayPatchedFunctionE(%rip), %rax
+	testq %rax,%rax
+	je	.Ltmp2
+
+	movl	%r10d, %edi
+	movl	$1, %esi
+	callq	*%rax
+.Ltmp2:
+  // Restore the important registers.
+	movq	16(%rsp), %rax
+	movq	8(%rsp), %rdx
+	addq	$24, %rsp
+	popq	%rbp
+	retq
+.Ltmp3:
+	.size __xray_FunctionExit, .Ltmp3-__xray_FunctionExit
+	.cfi_endproc




More information about the llvm-commits mailing list