Index: cmake/builtin-config-ix.cmake =================================================================== --- cmake/builtin-config-ix.cmake +++ cmake/builtin-config-ix.cmake @@ -11,6 +11,7 @@ builtin_check_c_compiler_flag(-fvisibility=hidden COMPILER_RT_HAS_VISIBILITY_HIDDEN_FLAG) builtin_check_c_compiler_flag(-fomit-frame-pointer COMPILER_RT_HAS_OMIT_FRAME_POINTER_FLAG) builtin_check_c_compiler_flag(-ffreestanding COMPILER_RT_HAS_FREESTANDING_FLAG) +builtin_check_c_compiler_flag(-fxray-instrument COMPILER_RT_HAS_XRAY_COMPILER_FLAG) builtin_check_c_compiler_source(COMPILER_RT_HAS_ATOMIC_KEYWORD " Index: lib/xray/CMakeLists.txt =================================================================== --- lib/xray/CMakeLists.txt +++ 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 @@ 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_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() Index: lib/xray/xray_arm.cc =================================================================== --- lib/xray/xray_arm.cc +++ lib/xray/xray_arm.cc @@ -28,20 +28,21 @@ }; // 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, # // MOVT R, # -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 @@ // Writes the following instructions: // MOVW r0, # // MOVT r0, # -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, # // MOVT ip, # -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 @@ } 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); Index: lib/xray/xray_defs.h =================================================================== --- /dev/null +++ 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 + +#ifndef XRAY_SUPPORTED +#define XRAY_NEVER_INSTRUMENT +#else +#define XRAY_NEVER_INSTRUMENT __attribute__((xray_never_instrument)) +#endif + +#endif // XRAY_XRAY_DEFS_H Index: lib/xray/xray_flags.cc =================================================================== --- lib/xray/xray_flags.cc +++ 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 @@ 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(); Index: lib/xray/xray_init.cc =================================================================== --- lib/xray/xray_init.cc +++ lib/xray/xray_init.cc @@ -18,6 +18,7 @@ #include #include "sanitizer_common/sanitizer_common.h" +#include "xray_defs.h" #include "xray_flags.h" #include "xray_interface_internal.h" @@ -44,7 +45,7 @@ // __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"); Index: lib/xray/xray_inmemory_log.cc =================================================================== --- lib/xray/xray_inmemory_log.cc +++ lib/xray/xray_inmemory_log.cc @@ -35,6 +35,7 @@ #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 @@ // 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 @@ } #if defined(__x86_64__) -static std::pair retryingReadSome(int Fd, char *Begin, - char *End) { +static std::pair +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 @@ 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 @@ 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 L(LogMutex); if (Fd > 0 && Start != nullptr) { retryingWriteAll(Fd, reinterpret_cast(Start), @@ -140,9 +147,12 @@ 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::type; static constexpr size_t BuffLen = 1024; Index: lib/xray/xray_interface.cc =================================================================== --- lib/xray/xray_interface.cc +++ lib/xray/xray_interface.cc @@ -23,6 +23,7 @@ #include #include "sanitizer_common/sanitizer_common.h" +#include "xray_defs.h" namespace __xray { @@ -53,11 +54,13 @@ 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 @@ return R; } - ~MProtectHelper() { + ~MProtectHelper() XRAY_NEVER_INSTRUMENT { if (MustCleanup) { mprotect(PageAlignedAddr, MProtectLen, PROT_READ | PROT_EXEC); } @@ -77,7 +80,8 @@ extern std::atomic 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 @@ 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 XRayPatching{false}; @@ -97,22 +103,24 @@ 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 CleanupInvoker ScopeCleanup(Function Fn) { +template +CleanupInvoker ScopeCleanup(Function Fn) XRAY_NEVER_INSTRUMENT { return CleanupInvoker{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 @@ 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); +} Index: lib/xray/xray_x86_64.cc =================================================================== --- lib/xray/xray_x86_64.cc +++ 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 #include @@ -16,7 +17,7 @@ static constexpr int64_t MaxOffset{std::numeric_limits::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 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 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 =