From 22f6aeecb2122630e4b27e7018c9fb47d17edda5 Mon Sep 17 00:00:00 2001 From: Dean Michael Berris Date: Tue, 28 Nov 2017 11:49:22 +0000 Subject: [XRay][compiler-rt][Darwin] Minimal XRay build support in Darwin This change is the first in a series of changes to get the XRay runtime building on macOS. This first allows us to build the minimal parts of XRay to get us started on supporting macOS development. These include: - CMake changes to allow targeting x86_64 initially. - Allowing for building the initialisation routines without `.preinit_array` support. - Use __sanitizer::SleepForMillis() to work around the lack of clock_nanosleep on macOS. - Deprecate the xray_fdr_log_grace_period_us flag, and introduce the xray_fdr_log_grace_period_ms flag instead, to use milliseconds across platforms. Reviewers: kubamracek Subscribers: llvm-commits, krytarowski, nglevin, mgorny Differential Review: https://reviews.llvm.org/D39114 git-svn-id: https://llvm.org/svn/llvm-project/compiler-rt/trunk@319165 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/xray/CMakeLists.txt | 45 ++++++++++++++++-- lib/xray/weak_symbols.txt | 4 ++ lib/xray/xray_fdr_logging.cc | 14 ++---- lib/xray/xray_flags.inc | 4 +- lib/xray/xray_init.cc | 3 +- lib/xray/xray_trampoline_x86_64.S | 96 +++++++++++++++++++-------------------- 6 files changed, 100 insertions(+), 66 deletions(-) create mode 100644 lib/xray/weak_symbols.txt (limited to 'lib') diff --git a/lib/xray/CMakeLists.txt b/lib/xray/CMakeLists.txt index 6d24ba8bf..101be97d2 100644 --- a/lib/xray/CMakeLists.txt +++ b/lib/xray/CMakeLists.txt @@ -65,19 +65,53 @@ append_list_if( append_list_if( COMPILER_RT_BUILD_XRAY_NO_PREINIT XRAY_NO_PREINIT XRAY_COMMON_DEFINITIONS) -add_compiler_rt_object_libraries(RTXray - ARCHS ${XRAY_SUPPORTED_ARCH} - SOURCES ${XRAY_SOURCES} CFLAGS ${XRAY_CFLAGS} - DEFS ${XRAY_COMMON_DEFINITIONS}) - add_compiler_rt_component(xray) set(XRAY_COMMON_RUNTIME_OBJECT_LIBS + RTXray RTSanitizerCommon RTSanitizerCommonLibc) +if (APPLE) + set(XRAY_LINK_LIBS ${SANITIZER_COMMON_LINK_LIBS}) + set(XRAY_ASM_SOURCES xray_trampoline_x86_64.S) + + if (${CMAKE_GENERATOR} STREQUAL "Xcode") + enable_language(ASM) + else() + set_source_files_properties(${XRAY_ASM_SOURCES} PROPERTIES LANGUAGE C) + endif() + + add_weak_symbols("sanitizer_common" WEAK_SYMBOL_LINK_FLAGS) + add_weak_symbols("xray" WEAK_SYMBOL_LINK_FLAGS) + + add_compiler_rt_object_libraries(RTXray + OS ${XRAY_SUPPORTED_OS} + ARCHS ${XRAY_SUPPORTED_ARCH} + SOURCES ${x86_64_SOURCES} + CFLAGS ${XRAY_CFLAGS} + DEFS ${XRAY_COMMON_DEFINITIONS}) + + # We only support running on osx for now. + add_compiler_rt_runtime(clang_rt.xray + STATIC + OS ${XRAY_SUPPORTED_OS} + ARCHS ${XRAY_SUPPORTED_ARCH} + OBJECT_LIBS RTXray + RTSanitizerCommon + RTSanitizerCommonLibc + CFLAGS ${XRAY_CFLAGS} + DEFS ${XRAY_COMMON_DEFINITIONS} + LINK_FLAGS ${SANITIZER_COMMON_LINK_FLAGS} ${WEAK_SYMBOL_LINK_FLAGS} + LINK_LIBS ${XRAY_LINK_LIBS} + PARENT_TARGET xray) +else() foreach(arch ${XRAY_SUPPORTED_ARCH}) if(CAN_TARGET_${arch}) + add_compiler_rt_object_libraries(RTXray + ARCHS ${XRAY_SUPPORTED_ARCH} + SOURCES ${XRAY_SOURCES} CFLAGS ${XRAY_CFLAGS} + DEFS ${XRAY_COMMON_DEFINITIONS}) add_compiler_rt_runtime(clang_rt.xray STATIC ARCHS ${arch} @@ -88,6 +122,7 @@ foreach(arch ${XRAY_SUPPORTED_ARCH}) PARENT_TARGET xray) endif() endforeach() +endif() if(COMPILER_RT_INCLUDE_TESTS) add_subdirectory(tests) diff --git a/lib/xray/weak_symbols.txt b/lib/xray/weak_symbols.txt new file mode 100644 index 000000000..963fff2d6 --- /dev/null +++ b/lib/xray/weak_symbols.txt @@ -0,0 +1,4 @@ +___start_xray_fn_idx +___start_xray_instr_map +___stop_xray_fn_idx +___stop_xray_instr_map diff --git a/lib/xray/xray_fdr_logging.cc b/lib/xray/xray_fdr_logging.cc index 035fc4061..ca764022f 100644 --- a/lib/xray/xray_fdr_logging.cc +++ b/lib/xray/xray_fdr_logging.cc @@ -70,15 +70,9 @@ XRayLogFlushStatus fdrLoggingFlush() XRAY_NEVER_INSTRUMENT { return XRayLogFlushStatus::XRAY_LOG_NOT_FLUSHING; } - // We wait a number of microseconds to allow threads to see that we've + // We wait a number of milliseconds to allow threads to see that we've // finalised before attempting to flush the log. - struct timespec TS; - TS.tv_sec = flags()->xray_fdr_log_grace_period_us / 1000000; - TS.tv_nsec = (flags()->xray_fdr_log_grace_period_us % 1000000) * 1000; - struct timespec Rem; - while (clock_nanosleep(CLOCK_REALTIME, 0, &TS, &Rem) && - (Rem.tv_sec != 0 || Rem.tv_nsec != 0)) - TS = Rem; + __sanitizer::SleepForMillis(flags()->xray_fdr_log_grace_period_ms); // We write out the file in the following format: // @@ -374,9 +368,7 @@ static auto UNUSED Unused = [] { using namespace __xray; if (flags()->xray_fdr_log) { XRayLogImpl Impl{ - fdrLoggingInit, - fdrLoggingFinalize, - fdrLoggingHandleArg0, + fdrLoggingInit, fdrLoggingFinalize, fdrLoggingHandleArg0, fdrLoggingFlush, }; __xray_set_log_impl(Impl); diff --git a/lib/xray/xray_flags.inc b/lib/xray/xray_flags.inc index 470db45d7..c4238ff88 100644 --- a/lib/xray/xray_flags.inc +++ b/lib/xray/xray_flags.inc @@ -37,7 +37,9 @@ XRAY_FLAG(bool, xray_fdr_log, false, XRAY_FLAG(int, xray_fdr_log_func_duration_threshold_us, 5, "FDR logging will try to skip functions that execute for fewer " "microseconds than this threshold.") -XRAY_FLAG(int, xray_fdr_log_grace_period_us, 100000, +XRAY_FLAG(int, xray_fdr_log_grace_period_us, 0, + "DEPRECATED: use xray_fdr_log_grace_period_ms instead.") +XRAY_FLAG(int, xray_fdr_log_grace_period_ms, 100, "FDR logging will wait this much time in microseconds before " "actually flushing the log; this gives a chance for threads to " "notice that the log has been finalized and clean up.") diff --git a/lib/xray/xray_init.cc b/lib/xray/xray_init.cc index 07f692431..864e77944 100644 --- a/lib/xray/xray_init.cc +++ b/lib/xray/xray_init.cc @@ -88,7 +88,8 @@ void __xray_init() XRAY_NEVER_INSTRUMENT { #endif } -#ifndef XRAY_NO_PREINIT +// Only add the preinit array initialization if the sanitizers can. +#if !defined(XRAY_NO_PREINIT) && SANITIZER_CAN_USE_PREINIT_ARRAY __attribute__((section(".preinit_array"), used)) void (*__local_xray_preinit)(void) = __xray_init; #endif diff --git a/lib/xray/xray_trampoline_x86_64.S b/lib/xray/xray_trampoline_x86_64.S index 33fa0e79d..0ae85c78a 100644 --- a/lib/xray/xray_trampoline_x86_64.S +++ b/lib/xray/xray_trampoline_x86_64.S @@ -14,10 +14,13 @@ //===----------------------------------------------------------------------===// #include "../builtins/assembly.h" +#include "../sanitizer_common/sanitizer_asm.h" + + .macro SAVE_REGISTERS subq $192, %rsp - .cfi_def_cfa_offset 200 + CFI_DEF_CFA_OFFSET(200) // At this point, the stack pointer should be aligned to an 8-byte boundary, // because any call instructions that come after this will add another 8 // bytes and therefore align it to 16-bytes. @@ -57,7 +60,7 @@ movq 8(%rsp), %r8 movq 0(%rsp), %r9 addq $192, %rsp - .cfi_def_cfa_offset 8 + CFI_DEF_CFA_OFFSET(8) .endm .macro ALIGNED_CALL_RAX @@ -75,21 +78,25 @@ .endm .text +#if !defined(__APPLE__) + .section .text +#else + .section __TEXT,__text +#endif .file "xray_trampoline_x86.S" //===----------------------------------------------------------------------===// - .globl __xray_FunctionEntry + .globl ASM_TSAN_SYMBOL(__xray_FunctionEntry) .align 16, 0x90 - .type __xray_FunctionEntry,@function - -__xray_FunctionEntry: - .cfi_startproc + ASM_TYPE_FUNCTION(__xray_FunctionEntry) +ASM_TSAN_SYMBOL(__xray_FunctionEntry): + CFI_STARTPROC SAVE_REGISTERS // This load has to be atomic, it's concurrent with __xray_patch(). // On x86/amd64, a simple (type-aligned) MOV instruction is enough. - movq _ZN6__xray19XRayPatchedFunctionE(%rip), %rax + movq ASM_TSAN_SYMBOL(_ZN6__xray19XRayPatchedFunctionE)(%rip), %rax testq %rax, %rax je .Ltmp0 @@ -101,28 +108,27 @@ __xray_FunctionEntry: .Ltmp0: RESTORE_REGISTERS retq -.Ltmp1: - .size __xray_FunctionEntry, .Ltmp1-__xray_FunctionEntry - .cfi_endproc + ASM_SIZE(__xray_FunctionEntry) + CFI_ENDPROC //===----------------------------------------------------------------------===// - .globl __xray_FunctionExit + .globl ASM_TSAN_SYMBOL(__xray_FunctionExit) .align 16, 0x90 - .type __xray_FunctionExit,@function -__xray_FunctionExit: - .cfi_startproc + ASM_TYPE_FUNCTION(__xray_FunctionExit) +ASM_TSAN_SYMBOL(__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. subq $56, %rsp - .cfi_def_cfa_offset 64 + CFI_DEF_CFA_OFFSET(64) movq %rbp, 48(%rsp) movupd %xmm0, 32(%rsp) movupd %xmm1, 16(%rsp) movq %rax, 8(%rsp) movq %rdx, 0(%rsp) - movq _ZN6__xray19XRayPatchedFunctionE(%rip), %rax + movq ASM_TSAN_SYMBOL(_ZN6__xray19XRayPatchedFunctionE)(%rip), %rax testq %rax,%rax je .Ltmp2 @@ -138,22 +144,21 @@ __xray_FunctionExit: movq 8(%rsp), %rax movq 0(%rsp), %rdx addq $56, %rsp - .cfi_def_cfa_offset 8 + CFI_DEF_CFA_OFFSET(8) retq -.Ltmp3: - .size __xray_FunctionExit, .Ltmp3-__xray_FunctionExit - .cfi_endproc + ASM_SIZE(__xray_FunctionExit) + CFI_ENDPROC //===----------------------------------------------------------------------===// - .global __xray_FunctionTailExit + .globl ASM_TSAN_SYMBOL(__xray_FunctionTailExit) .align 16, 0x90 - .type __xray_FunctionTailExit,@function -__xray_FunctionTailExit: - .cfi_startproc + ASM_TYPE_FUNCTION(__xray_FunctionTailExit) +ASM_TSAN_SYMBOL(__xray_FunctionTailExit): + CFI_STARTPROC SAVE_REGISTERS - movq _ZN6__xray19XRayPatchedFunctionE(%rip), %rax + movq ASM_TSAN_SYMBOL(_ZN6__xray19XRayPatchedFunctionE)(%rip), %rax testq %rax,%rax je .Ltmp4 @@ -165,26 +170,25 @@ __xray_FunctionTailExit: .Ltmp4: RESTORE_REGISTERS retq -.Ltmp5: - .size __xray_FunctionTailExit, .Ltmp5-__xray_FunctionTailExit - .cfi_endproc + ASM_SIZE(__xray_FunctionTailExit) + CFI_ENDPROC //===----------------------------------------------------------------------===// - .globl __xray_ArgLoggerEntry + .globl ASM_TSAN_SYMBOL(__xray_ArgLoggerEntry) .align 16, 0x90 - .type __xray_ArgLoggerEntry,@function -__xray_ArgLoggerEntry: - .cfi_startproc + ASM_TYPE_FUNCTION(__xray_ArgLoggerEntry) +ASM_TSAN_SYMBOL(__xray_ArgLoggerEntry): + CFI_STARTPROC SAVE_REGISTERS // Again, these function pointer loads must be atomic; MOV is fine. - movq _ZN6__xray13XRayArgLoggerE(%rip), %rax + movq ASM_TSAN_SYMBOL(_ZN6__xray13XRayArgLoggerE)(%rip), %rax testq %rax, %rax jne .Larg1entryLog // If [arg1 logging handler] not set, defer to no-arg logging. - movq _ZN6__xray19XRayPatchedFunctionE(%rip), %rax + movq ASM_TSAN_SYMBOL(_ZN6__xray19XRayPatchedFunctionE)(%rip), %rax testq %rax, %rax je .Larg1entryFail @@ -203,24 +207,22 @@ __xray_ArgLoggerEntry: .Larg1entryFail: RESTORE_REGISTERS retq - -.Larg1entryEnd: - .size __xray_ArgLoggerEntry, .Larg1entryEnd-__xray_ArgLoggerEntry - .cfi_endproc + ASM_SIZE(__xray_ArgLoggerEntry) + CFI_ENDPROC //===----------------------------------------------------------------------===// - .global __xray_CustomEvent + .global ASM_TSAN_SYMBOL(__xray_CustomEvent) .align 16, 0x90 - .type __xray_CustomEvent,@function -__xray_CustomEvent: - .cfi_startproc + ASM_TYPE_FUNCTION(__xray_CustomEvent) +ASM_TSAN_SYMBOL(__xray_CustomEvent): + CFI_STARTPROC SAVE_REGISTERS // We take two arguments to this trampoline, which should be in rdi and rsi // already. We also make sure that we stash %rax because we use that register // to call the logging handler. - movq _ZN6__xray22XRayPatchedCustomEventE(%rip), %rax + movq ASM_TSAN_SYMBOL(_ZN6__xray22XRayPatchedCustomEventE)(%rip), %rax testq %rax,%rax je .LcustomEventCleanup @@ -229,9 +231,7 @@ __xray_CustomEvent: .LcustomEventCleanup: RESTORE_REGISTERS retq - -.Ltmp8: - .size __xray_CustomEvent, .Ltmp8-__xray_CustomEvent - .cfi_endproc + ASM_SIZE(__xray_CustomEvent) + CFI_ENDPROC NO_EXEC_STACK_DIRECTIVE -- cgit v1.2.3