diff options
author | Dean Michael Berris <dberris@google.com> | 2016-11-16 01:01:13 +0000 |
---|---|---|
committer | Dean Michael Berris <dberris@google.com> | 2016-11-16 01:01:13 +0000 |
commit | a1df33d42314dc8c52e3eb5254f0f216397e60fc (patch) | |
tree | 3170b1ed69ea95bca55af2ddfebef5da3fdf08a2 /lib | |
parent | ec301129e76d82fbdf59168f7478b343cff71294 (diff) |
[XRay][compiler-rt] Disable XRay instrumentation of the XRay runtime.
Summary:
Adds a CMake check for whether the compiler used to build the XRay
library supports XRay-instrumentation. If the compiler we're using does
support the `-fxray-instrument` flag (i.e. recently-built Clang), we
define the XRAY_NEVER_INSTRUMENT macro that then makes sure that the
XRay runtime functions never get XRay-instrumented.
This prevents potential weirdness involved with building the XRay
library with a Clang that supports XRay-instrumentation, and is
attempting to XRay-instrument the build of compiler-rt.
Reviewers: majnemer, rSerge, echristo
Subscribers: mehdi_amini, llvm-commits, mgorny
Differential Revision: https://reviews.llvm.org/D26597
git-svn-id: https://llvm.org/svn/llvm-project/compiler-rt/trunk@287068 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'lib')
-rw-r--r-- | lib/xray/CMakeLists.txt | 42 | ||||
-rw-r--r-- | lib/xray/xray_arm.cc | 28 | ||||
-rw-r--r-- | lib/xray/xray_defs.h | 22 | ||||
-rw-r--r-- | lib/xray/xray_flags.cc | 7 | ||||
-rw-r--r-- | lib/xray/xray_init.cc | 3 | ||||
-rw-r--r-- | lib/xray/xray_inmemory_log.cc | 30 | ||||
-rw-r--r-- | lib/xray/xray_interface.cc | 44 | ||||
-rw-r--r-- | lib/xray/xray_x86_64.cc | 7 |
8 files changed, 118 insertions, 65 deletions
diff --git a/lib/xray/CMakeLists.txt b/lib/xray/CMakeLists.txt index 12d9b7a53..c9f5105eb 100644 --- a/lib/xray/CMakeLists.txt +++ b/lib/xray/CMakeLists.txt @@ -2,20 +2,20 @@ set(XRAY_SOURCES xray_init.cc - xray_interface.cc - xray_flags.cc + xray_interface.cc + xray_flags.cc xray_inmemory_log.cc ) set(x86_64_SOURCES - xray_x86_64.cc - xray_trampoline_x86_64.S - ${XRAY_SOURCES}) + xray_x86_64.cc + xray_trampoline_x86_64.S + ${XRAY_SOURCES}) set(arm_SOURCES - xray_arm.cc - xray_trampoline_arm.S - ${XRAY_SOURCES}) + xray_arm.cc + xray_trampoline_arm.S + ${XRAY_SOURCES}) set(armhf_SOURCES ${arm_SOURCES}) @@ -25,6 +25,8 @@ include_directories(../../include) set(XRAY_CFLAGS ${SANITIZER_COMMON_CFLAGS}) set(XRAY_COMMON_DEFINITIONS XRAY_HAS_EXCEPTIONS=1) +append_list_if( + COMPILER_RT_HAS_XRAY_COMPILER_FLAG XRAY_SUPPORTED=1 XRAY_COMMON_DEFINITIONS) add_compiler_rt_object_libraries(RTXray ARCHS ${XRAY_SUPPORTED_ARCH} @@ -34,18 +36,18 @@ add_compiler_rt_object_libraries(RTXray add_compiler_rt_component(xray) set(XRAY_COMMON_RUNTIME_OBJECT_LIBS - RTSanitizerCommon - RTSanitizerCommonLibc) + 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 () + 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() diff --git a/lib/xray/xray_arm.cc b/lib/xray/xray_arm.cc index 4c1980364..53e26f8d8 100644 --- a/lib/xray/xray_arm.cc +++ b/lib/xray/xray_arm.cc @@ -28,20 +28,21 @@ enum class PatchOpcodes : uint32_t { }; // 0xUUUUWXYZ -> 0x000W0XYZ -inline static uint32_t getMovwMask(const uint32_t Value) { +inline static uint32_t getMovwMask(const uint32_t Value) XRAY_NEVER_INSTRUMENT { return (Value & 0xfff) | ((Value & 0xf000) << 4); } // 0xWXYZUUUU -> 0x000W0XYZ -inline static uint32_t getMovtMask(const uint32_t Value) { +inline static uint32_t getMovtMask(const uint32_t Value) XRAY_NEVER_INSTRUMENT { return getMovwMask(Value >> 16); } // Writes the following instructions: // MOVW R<regNo>, #<lower 16 bits of the |Value|> // MOVT R<regNo>, #<higher 16 bits of the |Value|> -inline static uint32_t *write32bitLoadReg(uint8_t regNo, uint32_t *Address, - const uint32_t Value) { +inline static uint32_t * +write32bitLoadReg(uint8_t regNo, uint32_t *Address, + const uint32_t Value) XRAY_NEVER_INSTRUMENT { // This is a fatal error: we cannot just report it and continue execution. assert(regNo <= 15 && "Register number must be 0 to 15."); // MOVW R, #0xWXYZ in machine code is 0xE30WRXYZ @@ -55,21 +56,24 @@ inline static uint32_t *write32bitLoadReg(uint8_t regNo, uint32_t *Address, // Writes the following instructions: // MOVW r0, #<lower 16 bits of the |Value|> // MOVT r0, #<higher 16 bits of the |Value|> -inline static uint32_t *Write32bitLoadR0(uint32_t *Address, - const uint32_t Value) { +inline static uint32_t * +Write32bitLoadR0(uint32_t *Address, + const uint32_t Value) XRAY_NEVER_INSTRUMENT { return write32bitLoadReg(0, Address, Value); } // Writes the following instructions: // MOVW ip, #<lower 16 bits of the |Value|> // MOVT ip, #<higher 16 bits of the |Value|> -inline static uint32_t *Write32bitLoadIP(uint32_t *Address, - const uint32_t Value) { +inline static uint32_t * +Write32bitLoadIP(uint32_t *Address, + const uint32_t Value) XRAY_NEVER_INSTRUMENT { return write32bitLoadReg(12, Address, Value); } inline static bool patchSled(const bool Enable, const uint32_t FuncId, - const XRaySledEntry &Sled, void (*TracingHook)()) { + const XRaySledEntry &Sled, + void (*TracingHook)()) XRAY_NEVER_INSTRUMENT { // When |Enable| == true, // We replace the following compile-time stub (sled): // @@ -118,17 +122,17 @@ inline static bool patchSled(const bool Enable, const uint32_t FuncId, } bool patchFunctionEntry(const bool Enable, const uint32_t FuncId, - const XRaySledEntry &Sled) { + const XRaySledEntry &Sled) XRAY_NEVER_INSTRUMENT { return patchSled(Enable, FuncId, Sled, __xray_FunctionEntry); } bool patchFunctionExit(const bool Enable, const uint32_t FuncId, - const XRaySledEntry &Sled) { + const XRaySledEntry &Sled) XRAY_NEVER_INSTRUMENT { return patchSled(Enable, FuncId, Sled, __xray_FunctionExit); } bool patchFunctionTailExit(const bool Enable, const uint32_t FuncId, - const XRaySledEntry &Sled) { + const XRaySledEntry &Sled) XRAY_NEVER_INSTRUMENT { // FIXME: In the future we'd need to distinguish between non-tail exits and // tail exits for better information preservation. return patchSled(Enable, FuncId, Sled, __xray_FunctionExit); diff --git a/lib/xray/xray_defs.h b/lib/xray/xray_defs.h new file mode 100644 index 000000000..e5c37c066 --- /dev/null +++ b/lib/xray/xray_defs.h @@ -0,0 +1,22 @@ +//===-- xray_defs.h ---------------------------------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// Common definitions useful for XRay sources. +// +//===----------------------------------------------------------------------===// +#ifndef XRAY_XRAY_DEFS_H +#define XRAY_XRAY_DEFS_H + +#if XRAY_SUPPORTED +#define XRAY_NEVER_INSTRUMENT __attribute__((xray_never_instrument)) +#else +#define XRAY_NEVER_INSTRUMENT +#endif + +#endif // XRAY_XRAY_DEFS_H diff --git a/lib/xray/xray_flags.cc b/lib/xray/xray_flags.cc index 6f829128c..338c2378b 100644 --- a/lib/xray/xray_flags.cc +++ b/lib/xray/xray_flags.cc @@ -16,6 +16,7 @@ #include "sanitizer_common/sanitizer_common.h" #include "sanitizer_common/sanitizer_flag_parser.h" #include "sanitizer_common/sanitizer_libc.h" +#include "xray_defs.h" using namespace __sanitizer; @@ -23,20 +24,20 @@ namespace __xray { Flags xray_flags_dont_use_directly; // use via flags(). -void Flags::SetDefaults() { +void Flags::SetDefaults() XRAY_NEVER_INSTRUMENT { #define XRAY_FLAG(Type, Name, DefaultValue, Description) Name = DefaultValue; #include "xray_flags.inc" #undef XRAY_FLAG } -static void RegisterXRayFlags(FlagParser *P, Flags *F) { +static void RegisterXRayFlags(FlagParser *P, Flags *F) XRAY_NEVER_INSTRUMENT { #define XRAY_FLAG(Type, Name, DefaultValue, Description) \ RegisterFlag(P, #Name, Description, &F->Name); #include "xray_flags.inc" #undef XRAY_FLAG } -void InitializeFlags() { +void InitializeFlags() XRAY_NEVER_INSTRUMENT { SetCommonFlagsDefaults(); auto *F = flags(); F->SetDefaults(); diff --git a/lib/xray/xray_init.cc b/lib/xray/xray_init.cc index f99903091..eb8618291 100644 --- a/lib/xray/xray_init.cc +++ b/lib/xray/xray_init.cc @@ -18,6 +18,7 @@ #include <unistd.h> #include "sanitizer_common/sanitizer_common.h" +#include "xray_defs.h" #include "xray_flags.h" #include "xray_interface_internal.h" @@ -44,7 +45,7 @@ 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() { +void __xray_init() XRAY_NEVER_INSTRUMENT { InitializeFlags(); if (__start_xray_instr_map == nullptr) { Report("XRay instrumentation map missing. Not initializing XRay.\n"); diff --git a/lib/xray/xray_inmemory_log.cc b/lib/xray/xray_inmemory_log.cc index 84958928e..17275ccf9 100644 --- a/lib/xray/xray_inmemory_log.cc +++ b/lib/xray/xray_inmemory_log.cc @@ -35,6 +35,7 @@ static const int64_t NanosecondsPerSecond = 1000LL * 1000 * 1000; #include "sanitizer_common/sanitizer_libc.h" #include "xray/xray_records.h" +#include "xray_defs.h" #include "xray_flags.h" #include "xray_interface_internal.h" @@ -43,14 +44,16 @@ static const int64_t NanosecondsPerSecond = 1000LL * 1000 * 1000; // events. We store simple fixed-sized entries in the log for external analysis. extern "C" { -void __xray_InMemoryRawLog(int32_t FuncId, XRayEntryType Type); +void __xray_InMemoryRawLog(int32_t FuncId, + XRayEntryType Type) XRAY_NEVER_INSTRUMENT; } namespace __xray { std::mutex LogMutex; -static void retryingWriteAll(int Fd, char *Begin, char *End) { +static void retryingWriteAll(int Fd, char *Begin, + char *End) XRAY_NEVER_INSTRUMENT { if (Begin == End) return; auto TotalBytes = std::distance(Begin, End); @@ -69,8 +72,8 @@ static void retryingWriteAll(int Fd, char *Begin, char *End) { } #if defined(__x86_64__) -static std::pair<ssize_t, bool> retryingReadSome(int Fd, char *Begin, - char *End) { +static std::pair<ssize_t, bool> +retryingReadSome(int Fd, char *Begin, char *End) XRAY_NEVER_INSTRUMENT { auto BytesToRead = std::distance(Begin, End); ssize_t BytesRead; ssize_t TotalBytesRead = 0; @@ -89,7 +92,8 @@ static std::pair<ssize_t, bool> retryingReadSome(int Fd, char *Begin, return std::make_pair(TotalBytesRead, true); } -static bool readValueFromFile(const char *Filename, long long *Value) { +static bool readValueFromFile(const char *Filename, + long long *Value) XRAY_NEVER_INSTRUMENT { int Fd = open(Filename, O_RDONLY | O_CLOEXEC); if (Fd == -1) return false; @@ -119,10 +123,13 @@ class ThreadExitFlusher { size_t &Offset; public: - explicit ThreadExitFlusher(int Fd, XRayRecord *Start, size_t &Offset) - : Fd(Fd), Start(Start), Offset(Offset) {} + explicit ThreadExitFlusher(int Fd, XRayRecord *Start, + size_t &Offset) XRAY_NEVER_INSTRUMENT + : Fd(Fd), + Start(Start), + Offset(Offset) {} - ~ThreadExitFlusher() { + ~ThreadExitFlusher() XRAY_NEVER_INSTRUMENT { std::lock_guard<std::mutex> L(LogMutex); if (Fd > 0 && Start != nullptr) { retryingWriteAll(Fd, reinterpret_cast<char *>(Start), @@ -140,9 +147,12 @@ public: using namespace __xray; -void PrintToStdErr(const char *Buffer) { fprintf(stderr, "%s", Buffer); } +void PrintToStdErr(const char *Buffer) XRAY_NEVER_INSTRUMENT { + fprintf(stderr, "%s", Buffer); +} -void __xray_InMemoryRawLog(int32_t FuncId, XRayEntryType Type) { +void __xray_InMemoryRawLog(int32_t FuncId, + XRayEntryType Type) XRAY_NEVER_INSTRUMENT { using Buffer = std::aligned_storage<sizeof(XRayRecord), alignof(XRayRecord)>::type; static constexpr size_t BuffLen = 1024; diff --git a/lib/xray/xray_interface.cc b/lib/xray/xray_interface.cc index fb49ff3a8..bfee1b8bc 100644 --- a/lib/xray/xray_interface.cc +++ b/lib/xray/xray_interface.cc @@ -23,6 +23,7 @@ #include <sys/mman.h> #include "sanitizer_common/sanitizer_common.h" +#include "xray_defs.h" namespace __xray { @@ -53,11 +54,13 @@ class MProtectHelper { bool MustCleanup; public: - explicit MProtectHelper(void *PageAlignedAddr, std::size_t MProtectLen) - : PageAlignedAddr(PageAlignedAddr), MProtectLen(MProtectLen), + explicit MProtectHelper(void *PageAlignedAddr, + std::size_t MProtectLen) XRAY_NEVER_INSTRUMENT + : PageAlignedAddr(PageAlignedAddr), + MProtectLen(MProtectLen), MustCleanup(false) {} - int MakeWriteable() { + int MakeWriteable() XRAY_NEVER_INSTRUMENT { auto R = mprotect(PageAlignedAddr, MProtectLen, PROT_READ | PROT_WRITE | PROT_EXEC); if (R != -1) @@ -65,7 +68,7 @@ public: return R; } - ~MProtectHelper() { + ~MProtectHelper() XRAY_NEVER_INSTRUMENT { if (MustCleanup) { mprotect(PageAlignedAddr, MProtectLen, PROT_READ | PROT_EXEC); } @@ -77,7 +80,8 @@ public: extern std::atomic<bool> XRayInitialized; extern std::atomic<__xray::XRaySledMap> XRayInstrMap; -int __xray_set_handler(void (*entry)(int32_t, XRayEntryType)) { +int __xray_set_handler(void (*entry)(int32_t, + XRayEntryType)) XRAY_NEVER_INSTRUMENT { if (XRayInitialized.load(std::memory_order_acquire)) { __xray::XRayPatchedFunction.store(entry, std::memory_order_release); return 1; @@ -85,7 +89,9 @@ int __xray_set_handler(void (*entry)(int32_t, XRayEntryType)) { return 0; } -int __xray_remove_handler() { return __xray_set_handler(nullptr); } +int __xray_remove_handler() XRAY_NEVER_INSTRUMENT { + return __xray_set_handler(nullptr); +} std::atomic<bool> XRayPatching{false}; @@ -97,22 +103,24 @@ template <class Function> class CleanupInvoker { Function Fn; public: - explicit CleanupInvoker(Function Fn) : Fn(Fn) {} - CleanupInvoker(const CleanupInvoker &) = default; - CleanupInvoker(CleanupInvoker &&) = default; - CleanupInvoker &operator=(const CleanupInvoker &) = delete; - CleanupInvoker &operator=(CleanupInvoker &&) = delete; - ~CleanupInvoker() { Fn(); } + explicit CleanupInvoker(Function Fn) XRAY_NEVER_INSTRUMENT : Fn(Fn) {} + CleanupInvoker(const CleanupInvoker &) XRAY_NEVER_INSTRUMENT = default; + CleanupInvoker(CleanupInvoker &&) XRAY_NEVER_INSTRUMENT = default; + CleanupInvoker & + operator=(const CleanupInvoker &) XRAY_NEVER_INSTRUMENT = delete; + CleanupInvoker &operator=(CleanupInvoker &&) XRAY_NEVER_INSTRUMENT = delete; + ~CleanupInvoker() XRAY_NEVER_INSTRUMENT { Fn(); } }; -template <class Function> CleanupInvoker<Function> ScopeCleanup(Function Fn) { +template <class Function> +CleanupInvoker<Function> ScopeCleanup(Function Fn) XRAY_NEVER_INSTRUMENT { return CleanupInvoker<Function>{Fn}; } // 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) { +XRayPatchingStatus ControlPatching(bool Enable) XRAY_NEVER_INSTRUMENT { if (!XRayInitialized.load(std::memory_order_acquire)) return XRayPatchingStatus::NOT_INITIALIZED; // Not initialized. @@ -188,6 +196,10 @@ XRayPatchingStatus ControlPatching(bool Enable) { return XRayPatchingStatus::SUCCESS; } -XRayPatchingStatus __xray_patch() { return ControlPatching(true); } +XRayPatchingStatus __xray_patch() XRAY_NEVER_INSTRUMENT { + return ControlPatching(true); +} -XRayPatchingStatus __xray_unpatch() { return ControlPatching(false); } +XRayPatchingStatus __xray_unpatch() XRAY_NEVER_INSTRUMENT { + return ControlPatching(false); +} diff --git a/lib/xray/xray_x86_64.cc b/lib/xray/xray_x86_64.cc index 11787a6bc..092e06db9 100644 --- a/lib/xray/xray_x86_64.cc +++ b/lib/xray/xray_x86_64.cc @@ -1,4 +1,5 @@ #include "sanitizer_common/sanitizer_common.h" +#include "xray_defs.h" #include "xray_interface_internal.h" #include <atomic> #include <cstdint> @@ -16,7 +17,7 @@ static constexpr int64_t MinOffset{std::numeric_limits<int32_t>::min()}; static constexpr int64_t MaxOffset{std::numeric_limits<int32_t>::max()}; bool patchFunctionEntry(const bool Enable, const uint32_t FuncId, - const XRaySledEntry &Sled) { + const XRaySledEntry &Sled) XRAY_NEVER_INSTRUMENT { // Here we do the dance of replacing the following sled: // // xray_sled_n: @@ -65,7 +66,7 @@ bool patchFunctionEntry(const bool Enable, const uint32_t FuncId, } bool patchFunctionExit(const bool Enable, const uint32_t FuncId, - const XRaySledEntry &Sled) { + const XRaySledEntry &Sled) XRAY_NEVER_INSTRUMENT { // Here we do the dance of replacing the following sled: // // xray_sled_n: @@ -112,7 +113,7 @@ bool patchFunctionExit(const bool Enable, const uint32_t FuncId, } bool patchFunctionTailExit(const bool Enable, const uint32_t FuncId, - const XRaySledEntry &Sled) { + const XRaySledEntry &Sled) XRAY_NEVER_INSTRUMENT { // Here we do the dance of replacing the tail call sled with a similar // sequence as the entry sled, but calls the tail exit sled instead. int64_t TrampolineOffset = |