Author: Mikhail Goncharov Date: 2024-10-11T14:01:58+02:00 New Revision: 90627a5a190a99ae2991d524580d866484aaba16
URL: https://github.com/llvm/llvm-project/commit/90627a5a190a99ae2991d524580d866484aaba16 DIFF: https://github.com/llvm/llvm-project/commit/90627a5a190a99ae2991d524580d866484aaba16.diff LOG: Revert "[XRay] Add support for instrumentation of DSOs on x86_64 (#90959)" This reverts commit a4402039bffd788b9af82435fd5a2fb311fdc6e8 and 4451f9f812d458f6b53785b27869674caf01e67b Added: Modified: clang/include/clang/Basic/CodeGenOptions.def clang/include/clang/Driver/Options.td clang/include/clang/Driver/XRayArgs.h clang/lib/Driver/ToolChains/CommonArgs.cpp clang/lib/Driver/XRayArgs.cpp compiler-rt/cmake/Modules/AllSupportedArchDefs.cmake compiler-rt/cmake/config-ix.cmake compiler-rt/include/xray/xray_interface.h compiler-rt/lib/xray/CMakeLists.txt compiler-rt/lib/xray/xray_init.cpp compiler-rt/lib/xray/xray_interface.cpp compiler-rt/lib/xray/xray_interface_internal.h compiler-rt/lib/xray/xray_trampoline_x86_64.S compiler-rt/lib/xray/xray_x86_64.cpp Removed: clang/test/Driver/XRay/xray-shared.cpp compiler-rt/lib/xray/xray_dso_init.cpp compiler-rt/test/xray/TestCases/Posix/basic-mode-dso.cpp compiler-rt/test/xray/TestCases/Posix/clang-xray-shared.cpp compiler-rt/test/xray/TestCases/Posix/dlopen.cpp compiler-rt/test/xray/TestCases/Posix/dso-dep-chains.cpp compiler-rt/test/xray/TestCases/Posix/patch-premain-dso.cpp compiler-rt/test/xray/TestCases/Posix/patching-unpatching-dso.cpp ################################################################################ diff --git a/clang/include/clang/Basic/CodeGenOptions.def b/clang/include/clang/Basic/CodeGenOptions.def index e45370bde74a5d..eac831278ee20d 100644 --- a/clang/include/clang/Basic/CodeGenOptions.def +++ b/clang/include/clang/Basic/CodeGenOptions.def @@ -136,8 +136,6 @@ CODEGENOPT(XRayIgnoreLoops , 1, 0) ///< Emit the XRay function index section. CODEGENOPT(XRayFunctionIndex , 1, 1) -///< Set when -fxray-shared is enabled -CODEGENOPT(XRayShared , 1, 0) ///< Set the minimum number of instructions in a function to determine selective ///< XRay instrumentation. diff --git a/clang/include/clang/Driver/Options.td b/clang/include/clang/Driver/Options.td index 4ee16e213d0e13..d306c751505e98 100644 --- a/clang/include/clang/Driver/Options.td +++ b/clang/include/clang/Driver/Options.td @@ -2946,11 +2946,6 @@ def fxray_selected_function_group : HelpText<"When using -fxray-function-groups, select which group of functions to instrument. Valid range is 0 to fxray-function-groups - 1">, MarshallingInfoInt<CodeGenOpts<"XRaySelectedFunctionGroup">, "0">; -defm xray_shared : BoolFOption<"xray-shared", - CodeGenOpts<"XRayShared">, DefaultFalse, - PosFlag<SetTrue, [], [ClangOption, CC1Option], - "Enable shared library instrumentation with XRay">, - NegFlag<SetFalse>>; defm fine_grained_bitfield_accesses : BoolOption<"f", "fine-grained-bitfield-accesses", CodeGenOpts<"FineGrainedBitfieldAccesses">, DefaultFalse, diff --git a/clang/include/clang/Driver/XRayArgs.h b/clang/include/clang/Driver/XRayArgs.h index 1b5c4a4c42f12a..bdd3d979547eed 100644 --- a/clang/include/clang/Driver/XRayArgs.h +++ b/clang/include/clang/Driver/XRayArgs.h @@ -27,7 +27,6 @@ class XRayArgs { XRayInstrSet InstrumentationBundle; llvm::opt::Arg *XRayInstrument = nullptr; bool XRayRT = true; - bool XRayShared = false; public: /// Parses the XRay arguments from an argument list. @@ -36,7 +35,6 @@ class XRayArgs { llvm::opt::ArgStringList &CmdArgs, types::ID InputType) const; bool needsXRayRt() const { return XRayInstrument && XRayRT; } - bool needsXRayDSORt() const { return XRayInstrument && XRayRT && XRayShared; } llvm::ArrayRef<std::string> modeList() const { return Modes; } XRayInstrSet instrumentationBundle() const { return InstrumentationBundle; } }; diff --git a/clang/lib/Driver/ToolChains/CommonArgs.cpp b/clang/lib/Driver/ToolChains/CommonArgs.cpp index 0a1b7c209563e8..0c6a585c3acffd 100644 --- a/clang/lib/Driver/ToolChains/CommonArgs.cpp +++ b/clang/lib/Driver/ToolChains/CommonArgs.cpp @@ -1613,14 +1613,10 @@ bool tools::addSanitizerRuntimes(const ToolChain &TC, const ArgList &Args, } bool tools::addXRayRuntime(const ToolChain&TC, const ArgList &Args, ArgStringList &CmdArgs) { - if (Args.hasArg(options::OPT_shared)) { - if (TC.getXRayArgs().needsXRayDSORt()) { - CmdArgs.push_back("--whole-archive"); - CmdArgs.push_back(TC.getCompilerRTArgString(Args, "xray-dso")); - CmdArgs.push_back("--no-whole-archive"); - return true; - } - } else if (TC.getXRayArgs().needsXRayRt()) { + if (Args.hasArg(options::OPT_shared)) + return false; + + if (TC.getXRayArgs().needsXRayRt()) { CmdArgs.push_back("--whole-archive"); CmdArgs.push_back(TC.getCompilerRTArgString(Args, "xray")); for (const auto &Mode : TC.getXRayArgs().modeList()) diff --git a/clang/lib/Driver/XRayArgs.cpp b/clang/lib/Driver/XRayArgs.cpp index d0bb5d4887c184..8c5134e2501358 100644 --- a/clang/lib/Driver/XRayArgs.cpp +++ b/clang/lib/Driver/XRayArgs.cpp @@ -63,23 +63,6 @@ XRayArgs::XRayArgs(const ToolChain &TC, const ArgList &Args) { << XRayInstrument->getSpelling() << Triple.str(); } - if (Args.hasFlag(options::OPT_fxray_shared, options::OPT_fno_xray_shared, - false)) { - XRayShared = true; - - // DSO instrumentation is currently limited to x86_64 - if (Triple.getArch() != llvm::Triple::x86_64) { - D.Diag(diag::err_drv_unsupported_opt_for_target) - << "-fxray-shared" << Triple.str(); - } - - unsigned PICLvl = std::get<1>(tools::ParsePICArgs(TC, Args)); - if (!PICLvl) { - D.Diag(diag::err_opt_not_valid_without_opt) << "-fxray-shared" - << "-fPIC"; - } - } - // Both XRay and -fpatchable-function-entry use // TargetOpcode::PATCHABLE_FUNCTION_ENTER. if (Arg *A = Args.getLastArg(options::OPT_fpatchable_function_entry_EQ)) @@ -194,10 +177,6 @@ void XRayArgs::addArgs(const ToolChain &TC, const ArgList &Args, Args.addOptOutFlag(CmdArgs, options::OPT_fxray_function_index, options::OPT_fno_xray_function_index); - if (XRayShared) - Args.addOptInFlag(CmdArgs, options::OPT_fxray_shared, - options::OPT_fno_xray_shared); - if (const Arg *A = Args.getLastArg(options::OPT_fxray_instruction_threshold_EQ)) { int Value; diff --git a/clang/test/Driver/XRay/xray-shared.cpp b/clang/test/Driver/XRay/xray-shared.cpp deleted file mode 100644 index 215854e1fc7cef..00000000000000 --- a/clang/test/Driver/XRay/xray-shared.cpp +++ /dev/null @@ -1,17 +0,0 @@ -// RUN: %clang -### --target=x86_64-unknown-linux-gnu -fPIC -fxray-instrument -fxray-shared -c %s -o /dev/null 2>&1 | FileCheck %s -// RUN: %clang -### --target=x86_64-unknown-linux-gnu -fpic -fxray-instrument -fxray-shared -c %s -o /dev/null 2>&1 | FileCheck %s -// RUN: %clang -### --target=x86_64-unknown-linux-gnu -fxray-instrument -fxray-shared -c %s -o /dev/null 2>&1 | FileCheck %s -// RUN: not %clang -### --target=x86_64-unknown-linux-gnu -fno-PIC -fxray-instrument -fxray-shared -c %s -o /dev/null 2>&1 | FileCheck %s --check-prefix=ERR-PIC -// RUN: not %clang -### --target=x86_64-unknown-linux-gnu -fno-pic -fxray-instrument -fxray-shared -c %s -o /dev/null 2>&1 | FileCheck %s --check-prefix=ERR-PIC - -// On 64 bit darwin, PIC is always enabled -// RUN: %clang -### --target=x86_64-apple-darwin -fxray-instrument -fxray-shared -c %s -o /dev/null 2>&1 | FileCheck %s - -// Check unsupported targets -// RUN: not %clang -### --target=aarch64-pc-freebsd -fPIC -fxray-instrument -fxray-shared -c %s -o /dev/null 2>&1 | FileCheck %s --check-prefix=ERR-TARGET -// RUN: not %clang -### --target=arm64-apple-macos -fPIC -fxray-instrument -fxray-shared -c %s -o /dev/null 2>&1 | FileCheck %s --check-prefix=ERR-TARGET - -// CHECK: "-cc1" {{.*}}"-fxray-instrument" {{.*}}"-fxray-shared" -// ERR-TARGET: error: unsupported option '-fxray-shared' for target -// ERR-PIC: error: option '-fxray-shared' cannot be specified without '-fPIC' - diff --git a/compiler-rt/cmake/Modules/AllSupportedArchDefs.cmake b/compiler-rt/cmake/Modules/AllSupportedArchDefs.cmake index 50a4256b82fe4e..809e9277156912 100644 --- a/compiler-rt/cmake/Modules/AllSupportedArchDefs.cmake +++ b/compiler-rt/cmake/Modules/AllSupportedArchDefs.cmake @@ -104,7 +104,6 @@ else() set(ALL_XRAY_SUPPORTED_ARCH ${X86_64} ${ARM32} ${ARM64} ${MIPS32} ${MIPS64} powerpc64le ${HEXAGON} ${LOONGARCH64}) endif() -set(ALL_XRAY_DSO_SUPPORTED_ARCH ${X86_64}) set(ALL_SHADOWCALLSTACK_SUPPORTED_ARCH ${ARM64}) if (UNIX) diff --git a/compiler-rt/cmake/config-ix.cmake b/compiler-rt/cmake/config-ix.cmake index 6134c9876b38e9..a93a88a9205001 100644 --- a/compiler-rt/cmake/config-ix.cmake +++ b/compiler-rt/cmake/config-ix.cmake @@ -668,9 +668,6 @@ if(APPLE) list_intersect(XRAY_SUPPORTED_ARCH ALL_XRAY_SUPPORTED_ARCH SANITIZER_COMMON_SUPPORTED_ARCH) - list_intersect(XRAY_DSO_SUPPORTED_ARCH - ALL_XRAY_DSO_SUPPORTED_ARCH - SANITIZER_COMMON_SUPPORTED_ARCH) list_intersect(SHADOWCALLSTACK_SUPPORTED_ARCH ALL_SHADOWCALLSTACK_SUPPORTED_ARCH SANITIZER_COMMON_SUPPORTED_ARCH) @@ -705,7 +702,6 @@ else() filter_available_targets(CFI_SUPPORTED_ARCH ${ALL_CFI_SUPPORTED_ARCH}) filter_available_targets(SCUDO_STANDALONE_SUPPORTED_ARCH ${ALL_SCUDO_STANDALONE_SUPPORTED_ARCH}) filter_available_targets(XRAY_SUPPORTED_ARCH ${ALL_XRAY_SUPPORTED_ARCH}) - filter_available_targets(XRAY_DSO_SUPPORTED_ARCH ${ALL_XRAY_DSO_SUPPORTED_ARCH}) filter_available_targets(SHADOWCALLSTACK_SUPPORTED_ARCH ${ALL_SHADOWCALLSTACK_SUPPORTED_ARCH}) filter_available_targets(GWP_ASAN_SUPPORTED_ARCH ${ALL_GWP_ASAN_SUPPORTED_ARCH}) diff --git a/compiler-rt/include/xray/xray_interface.h b/compiler-rt/include/xray/xray_interface.h index 675ea0cbc48c83..727431c04e4f73 100644 --- a/compiler-rt/include/xray/xray_interface.h +++ b/compiler-rt/include/xray/xray_interface.h @@ -93,78 +93,31 @@ enum XRayPatchingStatus { FAILED = 3, }; -/// This tells XRay to patch the instrumentation points in all currently loaded -/// objects. See XRayPatchingStatus for possible result values. +/// This tells XRay to patch the instrumentation points. See XRayPatchingStatus +/// for possible result values. extern XRayPatchingStatus __xray_patch(); -/// This tells XRay to patch the instrumentation points in the given object. -/// See XRayPatchingStatus for possible result values. -extern XRayPatchingStatus __xray_patch_object(int32_t ObjId); - /// Reverses the effect of __xray_patch(). See XRayPatchingStatus for possible /// result values. extern XRayPatchingStatus __xray_unpatch(); -/// Reverses the effect of __xray_patch_object. See XRayPatchingStatus for -/// possible result values. -extern XRayPatchingStatus __xray_unpatch_object(int32_t ObjId); - -/// This unpacks the given (packed) function id and patches -/// the corresponding function. See XRayPatchingStatus for possible +/// This patches a specific function id. See XRayPatchingStatus for possible /// result values. extern XRayPatchingStatus __xray_patch_function(int32_t FuncId); -/// This patches a specific function in the given object. See XRayPatchingStatus -/// for possible result values. -extern XRayPatchingStatus __xray_patch_function_in_object(int32_t FuncId, - int32_t ObjId); - -/// This unpacks the given (packed) function id and unpatches -/// the corresponding function. See XRayPatchingStatus for possible +/// This unpatches a specific function id. See XRayPatchingStatus for possible /// result values. extern XRayPatchingStatus __xray_unpatch_function(int32_t FuncId); -/// This unpatches a specific function in the given object. -/// See XRayPatchingStatus for possible result values. -extern XRayPatchingStatus __xray_unpatch_function_in_object(int32_t FuncId, - int32_t ObjId); - -/// This function unpacks the given (packed) function id and returns the address -/// of the corresponding function. We return 0 if we encounter any error, even -/// if 0 may be a valid function address. +/// This function returns the address of the function provided a valid function +/// id. We return 0 if we encounter any error, even if 0 may be a valid function +/// address. extern uintptr_t __xray_function_address(int32_t FuncId); -/// This function returns the address of the function in the given object -/// provided valid function and object ids. We return 0 if we encounter any -/// error, even if 0 may be a valid function address. -extern uintptr_t __xray_function_address_in_object(int32_t FuncId, - int32_t ObjId); - -/// This function returns the maximum valid function id for the main executable -/// (object id = 0). Returns 0 if we encounter errors (when there are no -/// instrumented functions, etc.). +/// This function returns the maximum valid function id. Returns 0 if we +/// encounter errors (when there are no instrumented functions, etc.). extern size_t __xray_max_function_id(); -/// This function returns the maximum valid function id for the given object. -/// Returns 0 if we encounter errors (when there are no instrumented functions, -/// etc.). -extern size_t __xray_max_function_id_in_object(int32_t ObjId); - -/// This function returns the number of previously registered objects -/// (executable + loaded DSOs). Returns 0 if XRay has not been initialized. -extern size_t __xray_num_objects(); - -/// Unpacks the function id from the given packed id. -extern int32_t __xray_unpack_function_id(int32_t PackedId); - -/// Unpacks the object id from the given packed id. -extern int32_t __xray_unpack_object_id(int32_t PackedId); - -/// Creates and returns a packed id from the given function and object ids. -/// If the ids do not fit within the reserved number of bits for each part, the -/// high bits are truncated. -extern int32_t __xray_pack_id(int32_t FuncId, int32_t ObjId); - /// Initialize the required XRay data structures. This is useful in cases where /// users want to control precisely when the XRay instrumentation data /// structures are initialized, for example when the XRay library is built with diff --git a/compiler-rt/lib/xray/CMakeLists.txt b/compiler-rt/lib/xray/CMakeLists.txt index f38c07420c9abf..cf7b5062aae32d 100644 --- a/compiler-rt/lib/xray/CMakeLists.txt +++ b/compiler-rt/lib/xray/CMakeLists.txt @@ -10,10 +10,6 @@ set(XRAY_SOURCES xray_utils.cpp ) -set(XRAY_DSO_SOURCES - xray_dso_init.cpp - ) - # Implementation files for all XRay modes. set(XRAY_FDR_MODE_SOURCES xray_fdr_flags.cpp @@ -37,11 +33,6 @@ set(x86_64_SOURCES xray_trampoline_x86_64.S ) -set(x86_64_DSO_SOURCES - xray_trampoline_x86_64.S - ) - - set(arm_SOURCES xray_arm.cpp xray_trampoline_arm.S @@ -137,12 +128,10 @@ set(XRAY_IMPL_HEADERS # consumption by tests. set(XRAY_ALL_SOURCE_FILES ${XRAY_SOURCES} - ${XRAY_DSO_SOURCES} ${XRAY_FDR_MODE_SOURCES} ${XRAY_BASIC_MODE_SOURCES} ${XRAY_PROFILING_MODE_SOURCES} ${x86_64_SOURCES} - ${x86_64_DSO_SOURCES} ${arm_SOURCES} ${armhf_SOURCES} ${hexagon_SOURCES} @@ -173,9 +162,6 @@ set(XRAY_CFLAGS ${COMPILER_RT_CXX_CFLAGS}) set(XRAY_COMMON_DEFINITIONS SANITIZER_COMMON_NO_REDEFINE_BUILTINS XRAY_HAS_EXCEPTIONS=1) -# DSO trampolines need to be compiled with GOT addressing -set(XRAY_COMMON_DEFINITIONS_DSO ${XRAY_COMMON_DEFINITIONS} XRAY_PIC) - # Too many existing bugs, needs cleanup. append_list_if(COMPILER_RT_HAS_WNO_FORMAT -Wno-format XRAY_CFLAGS) @@ -215,16 +201,7 @@ if (APPLE) CFLAGS ${XRAY_CFLAGS} DEFS ${XRAY_COMMON_DEFINITIONS} DEPS ${XRAY_DEPS}) - add_compiler_rt_object_libraries(RTXrayDSO - OS ${XRAY_SUPPORTED_OS} - ARCHS ${XRAY_DSO_SUPPORTED_ARCH} - SOURCES ${XRAY_DSO_SOURCES} - ADDITIONAL_HEADERS ${XRAY_IMPL_HEADERS} - CFLAGS ${XRAY_CFLAGS} - DEFS ${XRAY_COMMON_DEFINITIONS_DSO} - DEPS ${XRAY_DEPS}) set(XRAY_RTXRAY_ARCH_LIBS "") - set(XRAY_DSO_RTXRAY_ARCH_LIBS "") foreach(arch ${XRAY_SUPPORTED_ARCH}) if(NOT ${arch} IN_LIST XRAY_SOURCE_ARCHS) continue() @@ -238,17 +215,6 @@ if (APPLE) DEFS ${XRAY_COMMON_DEFINITIONS} DEPS ${XRAY_DEPS}) list(APPEND XRAY_RTXRAY_ARCH_LIBS RTXray_${arch}) - if (${arch} IN_LIST XRAY_DSO_SUPPORTED_ARCH) - add_compiler_rt_object_libraries(RTXrayDSO_${arch} - OS ${XRAY_SUPPORTED_OS} - ARCHS ${XRAY_DSO_SUPPORTED_ARCH} - SOURCES ${${arch}_DSO_SOURCES} - ADDITIONAL_HEADERS ${XRAY_IMPL_HEADERS} - CFLAGS ${XRAY_CFLAGS} - DEFS ${XRAY_COMMON_DEFINITIONS_DSO} - DEPS ${XRAY_DEPS}) - list(APPEND XRAY_DSO_RTXRAY_ARCH_LIBS RTXrayDSO_${arch}) - endif() endforeach() add_compiler_rt_object_libraries(RTXrayFDR OS ${XRAY_SUPPORTED_OS} @@ -286,17 +252,6 @@ if (APPLE) LINK_FLAGS ${XRAY_LINK_FLAGS} ${WEAK_SYMBOL_LINK_FLAGS} LINK_LIBS ${XRAY_LINK_LIBS} PARENT_TARGET xray) - add_compiler_rt_runtime(clang_rt.xray-dso - STATIC - OS ${XRAY_SUPPORTED_OS} - ARCHS ${XRAY_DSO_SUPPORTED_ARCH} - OBJECT_LIBS RTXrayDSO ${XRAY_DSO_RTXRAY_ARCH_LIBS} - CFLAGS ${XRAY_CFLAGS} - DEFS ${XRAY_COMMON_DEFINITIONS} - LINK_FLAGS ${XRAY_LINK_FLAGS} ${WEAK_SYMBOL_LINK_FLAGS} - LINK_LIBS ${XRAY_LINK_LIBS} - PARENT_TARGET xray) - add_compiler_rt_runtime(clang_rt.xray-fdr STATIC OS ${XRAY_SUPPORTED_OS} @@ -391,37 +346,16 @@ else() # not Apple DEFS ${XRAY_COMMON_DEFINITIONS} OBJECT_LIBS RTXrayBASIC PARENT_TARGET xray) - # Profiler Mode runtime - add_compiler_rt_runtime(clang_rt.xray-profiling - STATIC - ARCHS ${arch} - CFLAGS ${XRAY_CFLAGS} - LINK_FLAGS ${XRAY_LINK_FLAGS} - LINK_LIBS ${XRAY_LINK_LIBS} - DEFS ${XRAY_COMMON_DEFINITIONS} - OBJECT_LIBS RTXrayPROFILING - PARENT_TARGET xray) - - if (${arch} IN_LIST XRAY_DSO_SUPPORTED_ARCH) - # TODO: Only implemented for X86 at the moment - add_compiler_rt_object_libraries(RTXrayDSO - ARCHS ${arch} - SOURCES ${XRAY_DSO_SOURCES} ${${arch}_DSO_SOURCES} - ADDITIONAL_HEADERS ${XRAY_IMPL_HEADERS} - CFLAGS ${XRAY_CFLAGS} - DEFS ${XRAY_COMMON_DEFINITIONS_DSO} - DEPS ${XRAY_DEPS}) - # DSO runtime archive - add_compiler_rt_runtime(clang_rt.xray-dso - STATIC - ARCHS ${arch} - CFLAGS ${XRAY_CFLAGS} - LINK_FLAGS ${XRAY_LINK_FLAGS} - LINK_LIBS ${XRAY_LINK_LIBS} - DEFS ${XRAY_COMMON_DEFINITIONS} - OBJECT_LIBS RTXrayDSO - PARENT_TARGET xray) - endif() + # Profiler Mode runtime + add_compiler_rt_runtime(clang_rt.xray-profiling + STATIC + ARCHS ${arch} + CFLAGS ${XRAY_CFLAGS} + LINK_FLAGS ${XRAY_LINK_FLAGS} + LINK_LIBS ${XRAY_LINK_LIBS} + DEFS ${XRAY_COMMON_DEFINITIONS} + OBJECT_LIBS RTXrayPROFILING + PARENT_TARGET xray) endforeach() endif() # not Apple diff --git a/compiler-rt/lib/xray/xray_dso_init.cpp b/compiler-rt/lib/xray/xray_dso_init.cpp deleted file mode 100644 index eb754db54c64fa..00000000000000 --- a/compiler-rt/lib/xray/xray_dso_init.cpp +++ /dev/null @@ -1,62 +0,0 @@ -//===-- xray_init.cpp -------------------------------------------*- C++ -*-===// -// -// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. -// See https://llvm.org/LICENSE.txt for license information. -// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -// -//===----------------------------------------------------------------------===// -// -// This file is a part of XRay, a dynamic runtime instrumentation system. -// -// XRay initialisation logic for DSOs. -//===----------------------------------------------------------------------===// - -#include "sanitizer_common/sanitizer_atomic.h" -#include "xray_defs.h" -#include "xray_flags.h" -#include "xray_interface_internal.h" - -using namespace __sanitizer; - -extern "C" { -extern const XRaySledEntry __start_xray_instr_map[] __attribute__((weak)) -__attribute__((visibility("hidden"))); -extern const XRaySledEntry __stop_xray_instr_map[] __attribute__((weak)) -__attribute__((visibility("hidden"))); -extern const XRayFunctionSledIndex __start_xray_fn_idx[] __attribute__((weak)) -__attribute__((visibility("hidden"))); -extern const XRayFunctionSledIndex __stop_xray_fn_idx[] __attribute__((weak)) -__attribute__((visibility("hidden"))); - -#if SANITIZER_APPLE -// HACK: This is a temporary workaround to make XRay build on -// Darwin, but it will probably not work at runtime. -extern const XRaySledEntry __start_xray_instr_map[] = {}; -extern const XRaySledEntry __stop_xray_instr_map[] = {}; -extern const XRayFunctionSledIndex __start_xray_fn_idx[] = {}; -extern const XRayFunctionSledIndex __stop_xray_fn_idx[] = {}; -#endif -} - -// Handler functions to call in the patched entry/exit sled. -extern atomic_uintptr_t XRayPatchedFunction; -extern atomic_uintptr_t XRayArgLogger; -extern atomic_uintptr_t XRayPatchedCustomEvent; -extern atomic_uintptr_t XRayPatchedTypedEvent; - -static int __xray_object_id{-1}; - -// Note: .preinit_array initialization does not work for DSOs -__attribute__((constructor(0))) static void -__xray_init_dso() XRAY_NEVER_INSTRUMENT { - // Register sleds in main XRay runtime. - __xray_object_id = - __xray_register_dso(__start_xray_instr_map, __stop_xray_instr_map, - __start_xray_fn_idx, __stop_xray_fn_idx, {}); -} - -__attribute__((destructor(0))) static void -__xray_finalize_dso() XRAY_NEVER_INSTRUMENT { - // Inform the main runtime that this DSO is no longer used. - __xray_deregister_dso(__xray_object_id); -} diff --git a/compiler-rt/lib/xray/xray_init.cpp b/compiler-rt/lib/xray/xray_init.cpp index 53c93be89cd148..f22a31b95686d0 100644 --- a/compiler-rt/lib/xray/xray_init.cpp +++ b/compiler-rt/lib/xray/xray_init.cpp @@ -16,8 +16,6 @@ #include <unistd.h> #include "sanitizer_common/sanitizer_common.h" -#include "xray/xray_interface.h" -#include "xray_allocator.h" #include "xray_defs.h" #include "xray_flags.h" #include "xray_interface_internal.h" @@ -30,7 +28,7 @@ extern const XRayFunctionSledIndex __start_xray_fn_idx[] __attribute__((weak)); extern const XRayFunctionSledIndex __stop_xray_fn_idx[] __attribute__((weak)); #if SANITIZER_APPLE -// HACK: This is a temporary workaround to make XRay build on +// HACK: This is a temporary workaround to make XRay build on // Darwin, but it will probably not work at runtime. const XRaySledEntry __start_xray_instr_map[] = {}; extern const XRaySledEntry __stop_xray_instr_map[] = {}; @@ -45,16 +43,14 @@ using namespace __xray; // the weak symbols defined above (__start_xray_inst_map and // __stop_xray_instr_map) to initialise the instrumentation map that XRay uses // for runtime patching/unpatching of instrumentation points. +// +// FIXME: Support DSO instrumentation maps too. The current solution only works +// for statically linked executables. atomic_uint8_t XRayInitialized{0}; // This should always be updated before XRayInitialized is updated. SpinMutex XRayInstrMapMutex; - -// Contains maps for the main executable as well as DSOs. -XRaySledMap *XRayInstrMaps; - -// Number of binary objects registered. -atomic_uint32_t XRayNumObjects{0}; +XRaySledMap XRayInstrMap; // Global flag to determine whether the flags have been initialized. atomic_uint8_t XRayFlagsInitialized{0}; @@ -62,63 +58,6 @@ atomic_uint8_t XRayFlagsInitialized{0}; // A mutex to allow only one thread to initialize the XRay data structures. SpinMutex XRayInitMutex; -// Registers XRay sleds and trampolines coming from the main executable or one -// of the linked DSOs. -// Returns the object ID if registration is successful, -1 otherwise. -int32_t -__xray_register_sleds(const XRaySledEntry *SledsBegin, - const XRaySledEntry *SledsEnd, - const XRayFunctionSledIndex *FnIndexBegin, - const XRayFunctionSledIndex *FnIndexEnd, bool FromDSO, - XRayTrampolines Trampolines) XRAY_NEVER_INSTRUMENT { - if (!SledsBegin || !SledsEnd) { - Report("Invalid XRay sleds.\n"); - return -1; - } - XRaySledMap SledMap; - SledMap.FromDSO = FromDSO; - SledMap.Loaded = true; - SledMap.Trampolines = Trampolines; - SledMap.Sleds = SledsBegin; - SledMap.Entries = SledsEnd - SledsBegin; - if (FnIndexBegin != nullptr) { - SledMap.SledsIndex = FnIndexBegin; - SledMap.Functions = FnIndexEnd - FnIndexBegin; - } else { - size_t CountFunctions = 0; - uint64_t LastFnAddr = 0; - - for (std::size_t I = 0; I < SledMap.Entries; I++) { - const auto &Sled = SledMap.Sleds[I]; - const auto Function = Sled.function(); - if (Function != LastFnAddr) { - CountFunctions++; - LastFnAddr = Function; - } - } - SledMap.SledsIndex = nullptr; - SledMap.Functions = CountFunctions; - } - if (SledMap.Functions >= XRayMaxFunctions) { - Report("Too many functions! Maximum is %ld\n", XRayMaxFunctions); - return -1; - } - - if (Verbosity()) - Report("Registering %d new functions!\n", SledMap.Functions); - - { - SpinMutexLock Guard(&XRayInstrMapMutex); - auto Idx = atomic_fetch_add(&XRayNumObjects, 1, memory_order_acq_rel); - if (Idx >= XRayMaxObjects) { - Report("Too many objects registered! Maximum is %ld\n", XRayMaxObjects); - return -1; - } - XRayInstrMaps[Idx] = std::move(SledMap); - return Idx; - } -} - // __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() XRAY_NEVER_INSTRUMENT { @@ -141,21 +80,29 @@ void __xray_init() XRAY_NEVER_INSTRUMENT { return; } - atomic_store(&XRayNumObjects, 0, memory_order_release); - - // Pre-allocation takes up approx. 5kB for XRayMaxObjects=64. - XRayInstrMaps = allocateBuffer<XRaySledMap>(XRayMaxObjects); - - int MainBinaryId = - __xray_register_sleds(__start_xray_instr_map, __stop_xray_instr_map, - __start_xray_fn_idx, __stop_xray_fn_idx, false, {}); + { + SpinMutexLock Guard(&XRayInstrMapMutex); + XRayInstrMap.Sleds = __start_xray_instr_map; + XRayInstrMap.Entries = __stop_xray_instr_map - __start_xray_instr_map; + if (__start_xray_fn_idx != nullptr) { + XRayInstrMap.SledsIndex = __start_xray_fn_idx; + XRayInstrMap.Functions = __stop_xray_fn_idx - __start_xray_fn_idx; + } else { + size_t CountFunctions = 0; + uint64_t LastFnAddr = 0; + + for (std::size_t I = 0; I < XRayInstrMap.Entries; I++) { + const auto &Sled = XRayInstrMap.Sleds[I]; + const auto Function = Sled.function(); + if (Function != LastFnAddr) { + CountFunctions++; + LastFnAddr = Function; + } + } - // The executable should always get ID 0. - if (MainBinaryId != 0) { - Report("Registering XRay sleds failed.\n"); - return; + XRayInstrMap.Functions = CountFunctions; + } } - atomic_store(&XRayInitialized, true, memory_order_release); #ifndef XRAY_NO_PREINIT @@ -164,84 +111,6 @@ void __xray_init() XRAY_NEVER_INSTRUMENT { #endif } -// Registers XRay sleds and trampolines of an instrumented DSO. -// Returns the object ID if registration is successful, -1 otherwise. -// -// Default visibility is hidden, so we have to explicitly make it visible to -// DSO. -SANITIZER_INTERFACE_ATTRIBUTE int32_t __xray_register_dso( - const XRaySledEntry *SledsBegin, const XRaySledEntry *SledsEnd, - const XRayFunctionSledIndex *FnIndexBegin, - const XRayFunctionSledIndex *FnIndexEnd, - XRayTrampolines Trampolines) XRAY_NEVER_INSTRUMENT { - // Make sure XRay has been initialized in the main executable. - __xray_init(); - - if (__xray_num_objects() == 0) { - if (Verbosity()) - Report("No XRay instrumentation map in main executable. Not initializing " - "XRay for DSO.\n"); - return -1; - } - - // Register sleds in global map. - int ObjId = __xray_register_sleds(SledsBegin, SledsEnd, FnIndexBegin, - FnIndexEnd, true, Trampolines); - -#ifndef XRAY_NO_PREINIT - if (ObjId >= 0 && flags()->patch_premain) - __xray_patch_object(ObjId); -#endif - - return ObjId; -} - -// Deregisters a DSO from the main XRay runtime. -// Called from the DSO-local runtime when the library is unloaded (e.g. if -// dlclose is called). -// Returns true if the object ID is valid and the DSO was successfully -// deregistered. -SANITIZER_INTERFACE_ATTRIBUTE bool -__xray_deregister_dso(int32_t ObjId) XRAY_NEVER_INSTRUMENT { - - if (!atomic_load(&XRayInitialized, memory_order_acquire)) { - if (Verbosity()) - Report("XRay has not been initialized. Cannot deregister DSO.\n"); - return false; - } - - if (ObjId <= 0 || ObjId >= __xray_num_objects()) { - if (Verbosity()) - Report("Can't deregister object with ID %d: ID is invalid.\n", ObjId); - return false; - } - - { - SpinMutexLock Guard(&XRayInstrMapMutex); - auto &Entry = XRayInstrMaps[ObjId]; - if (!Entry.FromDSO) { - if (Verbosity()) - Report("Can't deregister object with ID %d: object does not correspond " - "to a shared library.\n", - ObjId); - return false; - } - if (!Entry.Loaded) { - if (Verbosity()) - Report("Can't deregister object with ID %d: object is not loaded.\n", - ObjId); - return true; - } - // Mark DSO as unloaded. No need to unpatch. - Entry.Loaded = false; - } - - if (Verbosity()) - Report("Deregistered object with ID %d.\n", ObjId); - - return true; -} - // FIXME: Make check-xray tests work on FreeBSD without // SANITIZER_CAN_USE_PREINIT_ARRAY. // See sanitizer_internal_defs.h where the macro is defined. diff --git a/compiler-rt/lib/xray/xray_interface.cpp b/compiler-rt/lib/xray/xray_interface.cpp index 402fc3d07b4e2a..5839043fcb93a8 100644 --- a/compiler-rt/lib/xray/xray_interface.cpp +++ b/compiler-rt/lib/xray/xray_interface.cpp @@ -36,8 +36,7 @@ extern __sanitizer::SpinMutex XRayInstrMapMutex; extern __sanitizer::atomic_uint8_t XRayInitialized; -extern __xray::XRaySledMap *XRayInstrMaps; -extern __sanitizer::atomic_uint32_t XRayNumObjects; +extern __xray::XRaySledMap XRayInstrMap; namespace __xray { @@ -62,16 +61,16 @@ static const int16_t cSledLength = 20; #endif /* CPU architecture */ // This is the function to call when we encounter the entry or exit sleds. -atomic_uintptr_t XRayPatchedFunction SANITIZER_INTERFACE_ATTRIBUTE{0}; +atomic_uintptr_t XRayPatchedFunction{0}; // This is the function to call from the arg1-enabled sleds/trampolines. -atomic_uintptr_t XRayArgLogger SANITIZER_INTERFACE_ATTRIBUTE{0}; +atomic_uintptr_t XRayArgLogger{0}; // This is the function to call when we encounter a custom event log call. -atomic_uintptr_t XRayPatchedCustomEvent SANITIZER_INTERFACE_ATTRIBUTE{0}; +atomic_uintptr_t XRayPatchedCustomEvent{0}; // This is the function to call when we encounter a typed event log call. -atomic_uintptr_t XRayPatchedTypedEvent SANITIZER_INTERFACE_ATTRIBUTE{0}; +atomic_uintptr_t XRayPatchedTypedEvent{0}; // This is the global status to determine whether we are currently // patching/unpatching. @@ -151,42 +150,27 @@ class MProtectHelper { namespace { -bool isObjectLoaded(int32_t ObjId) { - SpinMutexLock Guard(&XRayInstrMapMutex); - if (ObjId < 0 || - ObjId >= atomic_load(&XRayNumObjects, memory_order_acquire)) { - return false; - } - return XRayInstrMaps[ObjId].Loaded; -} - -bool patchSled(const XRaySledEntry &Sled, bool Enable, int32_t FuncId, - const XRayTrampolines &Trampolines) XRAY_NEVER_INSTRUMENT { +bool patchSled(const XRaySledEntry &Sled, bool Enable, + int32_t FuncId) XRAY_NEVER_INSTRUMENT { bool Success = false; switch (Sled.Kind) { case XRayEntryType::ENTRY: - Success = - patchFunctionEntry(Enable, FuncId, Sled, Trampolines.EntryTrampoline); + Success = patchFunctionEntry(Enable, FuncId, Sled, __xray_FunctionEntry); break; case XRayEntryType::EXIT: - Success = - patchFunctionExit(Enable, FuncId, Sled, Trampolines.ExitTrampoline); + Success = patchFunctionExit(Enable, FuncId, Sled); break; case XRayEntryType::TAIL: - Success = patchFunctionTailExit(Enable, FuncId, Sled, - Trampolines.TailExitTrampoline); + Success = patchFunctionTailExit(Enable, FuncId, Sled); break; case XRayEntryType::LOG_ARGS_ENTRY: - Success = - patchFunctionEntry(Enable, FuncId, Sled, Trampolines.LogArgsTrampoline); + Success = patchFunctionEntry(Enable, FuncId, Sled, __xray_ArgLoggerEntry); break; case XRayEntryType::CUSTOM_EVENT: - Success = patchCustomEvent(Enable, FuncId, Sled, - Trampolines.CustomEventTrampoline); + Success = patchCustomEvent(Enable, FuncId, Sled); break; case XRayEntryType::TYPED_EVENT: - Success = - patchTypedEvent(Enable, FuncId, Sled, Trampolines.TypedEventTrampoline); + Success = patchTypedEvent(Enable, FuncId, Sled); break; default: Report("Unsupported sled kind '%" PRIu64 "' @%04x\n", Sled.Address, @@ -221,9 +205,10 @@ findFunctionSleds(int32_t FuncId, return Index; } -XRayPatchingStatus patchFunction(int32_t FuncId, int32_t ObjId, +XRayPatchingStatus patchFunction(int32_t FuncId, bool Enable) XRAY_NEVER_INSTRUMENT { - if (!atomic_load(&XRayInitialized, memory_order_acquire)) + if (!atomic_load(&XRayInitialized, + memory_order_acquire)) return XRayPatchingStatus::NOT_INITIALIZED; // Not initialized. uint8_t NotPatching = false; @@ -235,24 +220,13 @@ XRayPatchingStatus patchFunction(int32_t FuncId, int32_t ObjId, XRaySledMap InstrMap; { SpinMutexLock Guard(&XRayInstrMapMutex); - if (ObjId < 0 || - ObjId >= atomic_load(&XRayNumObjects, memory_order_acquire)) { - Report("Unable to patch function: invalid sled map index: %d", ObjId); - return XRayPatchingStatus::FAILED; - } - InstrMap = XRayInstrMaps[ObjId]; + InstrMap = XRayInstrMap; } // If we don't have an index, we can't patch individual functions. if (InstrMap.Functions == 0) return XRayPatchingStatus::NOT_INITIALIZED; - // Check if the corresponding DSO has been unloaded. - if (!InstrMap.Loaded) { - Report("Invalid function id provided: %d\n", FuncId); - return XRayPatchingStatus::NOT_INITIALIZED; - } - // FuncId must be a positive number, less than the number of functions // instrumented. if (FuncId <= 0 || static_cast<size_t>(FuncId) > InstrMap.Functions) { @@ -260,8 +234,6 @@ XRayPatchingStatus patchFunction(int32_t FuncId, int32_t ObjId, return XRayPatchingStatus::FAILED; } - auto PackedId = __xray::MakePackedId(FuncId, ObjId); - // Now we patch ths sleds for this specific function. XRayFunctionSledIndex SledRange; if (InstrMap.SledsIndex) { @@ -270,13 +242,13 @@ XRayPatchingStatus patchFunction(int32_t FuncId, int32_t ObjId, } else { SledRange = findFunctionSleds(FuncId, InstrMap); } - auto *f = SledRange.Begin; bool SucceedOnce = false; for (size_t i = 0; i != SledRange.Size; ++i) - SucceedOnce |= patchSled(f[i], Enable, PackedId, InstrMap.Trampolines); + SucceedOnce |= patchSled(f[i], Enable, FuncId); - atomic_store(&XRayPatching, false, memory_order_release); + atomic_store(&XRayPatching, false, + memory_order_release); if (!SucceedOnce) { Report("Failed patching any sled for function '%d'.", FuncId); @@ -289,31 +261,32 @@ XRayPatchingStatus patchFunction(int32_t FuncId, int32_t ObjId, // controlPatching implements the common internals of the patching/unpatching // implementation. |Enable| defines whether we're enabling or disabling the // runtime XRay instrumentation. -// This function should only be called after ensuring that XRay is initialized -// and no other thread is currently patching. -XRayPatchingStatus controlPatchingObjectUnchecked(bool Enable, int32_t ObjId) { +XRayPatchingStatus controlPatching(bool Enable) XRAY_NEVER_INSTRUMENT { + if (!atomic_load(&XRayInitialized, + memory_order_acquire)) + return XRayPatchingStatus::NOT_INITIALIZED; // Not initialized. + + uint8_t NotPatching = false; + if (!atomic_compare_exchange_strong( + &XRayPatching, &NotPatching, true, memory_order_acq_rel)) + return XRayPatchingStatus::ONGOING; // Already patching. + + uint8_t PatchingSuccess = false; + auto XRayPatchingStatusResetter = + at_scope_exit([&PatchingSuccess] { + if (!PatchingSuccess) + atomic_store(&XRayPatching, false, + memory_order_release); + }); + XRaySledMap InstrMap; { SpinMutexLock Guard(&XRayInstrMapMutex); - if (ObjId < 0 || - ObjId >= atomic_load(&XRayNumObjects, memory_order_acquire)) { - Report("Unable to patch functions: invalid sled map index: %d\n", ObjId); - return XRayPatchingStatus::FAILED; - } - InstrMap = XRayInstrMaps[ObjId]; + InstrMap = XRayInstrMap; } if (InstrMap.Entries == 0) return XRayPatchingStatus::NOT_INITIALIZED; - if (Verbosity()) - Report("Patching object %d with %d functions.\n", ObjId, InstrMap.Entries); - - // Check if the corresponding DSO has been unloaded. - if (!InstrMap.Loaded) { - Report("Object is not loaded at index: %d\n", ObjId); - return XRayPatchingStatus::FAILED; - } - uint32_t FuncId = 1; uint64_t CurFun = 0; @@ -363,96 +336,20 @@ XRayPatchingStatus controlPatchingObjectUnchecked(bool Enable, int32_t ObjId) { ++FuncId; CurFun = F; } - auto PackedId = __xray::MakePackedId(FuncId, ObjId); - patchSled(Sled, Enable, PackedId, InstrMap.Trampolines); + patchSled(Sled, Enable, FuncId); } - atomic_store(&XRayPatching, false, memory_order_release); + atomic_store(&XRayPatching, false, + memory_order_release); + PatchingSuccess = true; return XRayPatchingStatus::SUCCESS; } -// Controls patching for all registered objects. -// Returns: SUCCESS, if patching succeeds for all objects. -// NOT_INITIALIZED, if one or more objects returned NOT_INITIALIZED -// but none failed. -// FAILED, if patching of one or more objects failed. -XRayPatchingStatus controlPatching(bool Enable) XRAY_NEVER_INSTRUMENT { - if (!atomic_load(&XRayInitialized, memory_order_acquire)) - return XRayPatchingStatus::NOT_INITIALIZED; // Not initialized. - - uint8_t NotPatching = false; - if (!atomic_compare_exchange_strong(&XRayPatching, &NotPatching, true, - memory_order_acq_rel)) - return XRayPatchingStatus::ONGOING; // Already patching. - - auto XRayPatchingStatusResetter = at_scope_exit( - [] { atomic_store(&XRayPatching, false, memory_order_release); }); - - unsigned NumObjects = __xray_num_objects(); - - XRayPatchingStatus CombinedStatus{NOT_INITIALIZED}; - for (unsigned I = 0; I < NumObjects; ++I) { - if (!isObjectLoaded(I)) - continue; - auto LastStatus = controlPatchingObjectUnchecked(Enable, I); - switch (LastStatus) { - case SUCCESS: - if (CombinedStatus == NOT_INITIALIZED) - CombinedStatus = SUCCESS; - break; - case FAILED: - // Report failure, but try to patch the remaining objects - CombinedStatus = FAILED; - break; - case NOT_INITIALIZED: - // XRay has been initialized but there are no sleds available for this - // object. Try to patch remaining objects. - if (CombinedStatus != FAILED) - CombinedStatus = NOT_INITIALIZED; - break; - case ONGOING: - UNREACHABLE("Status ONGOING should not appear at this point"); - default: - UNREACHABLE("Unhandled patching status"); - } - } - return CombinedStatus; -} - -// Controls patching for one object. -XRayPatchingStatus controlPatching(bool Enable, - int32_t ObjId) XRAY_NEVER_INSTRUMENT { - - if (!atomic_load(&XRayInitialized, memory_order_acquire)) - return XRayPatchingStatus::NOT_INITIALIZED; // Not initialized. - - uint8_t NotPatching = false; - if (!atomic_compare_exchange_strong(&XRayPatching, &NotPatching, true, - memory_order_acq_rel)) - return XRayPatchingStatus::ONGOING; // Already patching. - - auto XRayPatchingStatusResetter = at_scope_exit( - [] { atomic_store(&XRayPatching, false, memory_order_release); }); - - return controlPatchingObjectUnchecked(Enable, ObjId); -} - -XRayPatchingStatus mprotectAndPatchFunction(int32_t FuncId, int32_t ObjId, +XRayPatchingStatus mprotectAndPatchFunction(int32_t FuncId, bool Enable) XRAY_NEVER_INSTRUMENT { XRaySledMap InstrMap; { SpinMutexLock Guard(&XRayInstrMapMutex); - if (ObjId < 0 || - ObjId >= atomic_load(&XRayNumObjects, memory_order_acquire)) { - Report("Unable to patch function: invalid sled map index: %d\n", ObjId); - return XRayPatchingStatus::FAILED; - } - InstrMap = XRayInstrMaps[ObjId]; - } - - // Check if the corresponding DSO has been unloaded. - if (!InstrMap.Loaded) { - Report("Object is not loaded at index: %d\n", ObjId); - return XRayPatchingStatus::FAILED; + InstrMap = XRayInstrMap; } // FuncId must be a positive number, less than the number of functions @@ -501,7 +398,7 @@ XRayPatchingStatus mprotectAndPatchFunction(int32_t FuncId, int32_t ObjId, Report("Failed mprotect: %d\n", errno); return XRayPatchingStatus::FAILED; } - return patchFunction(FuncId, ObjId, Enable); + return patchFunction(FuncId, Enable); } } // namespace @@ -515,10 +412,12 @@ using namespace __xray; int __xray_set_handler(void (*entry)(int32_t, XRayEntryType)) XRAY_NEVER_INSTRUMENT { - if (atomic_load(&XRayInitialized, memory_order_acquire)) { + if (atomic_load(&XRayInitialized, + memory_order_acquire)) { atomic_store(&__xray::XRayPatchedFunction, - reinterpret_cast<uintptr_t>(entry), memory_order_release); + reinterpret_cast<uintptr_t>(entry), + memory_order_release); return 1; } return 0; @@ -526,9 +425,11 @@ int __xray_set_handler(void (*entry)(int32_t, int __xray_set_customevent_handler(void (*entry)(void *, size_t)) XRAY_NEVER_INSTRUMENT { - if (atomic_load(&XRayInitialized, memory_order_acquire)) { + if (atomic_load(&XRayInitialized, + memory_order_acquire)) { atomic_store(&__xray::XRayPatchedCustomEvent, - reinterpret_cast<uintptr_t>(entry), memory_order_release); + reinterpret_cast<uintptr_t>(entry), + memory_order_release); return 1; } return 0; @@ -536,9 +437,11 @@ int __xray_set_customevent_handler(void (*entry)(void *, size_t)) int __xray_set_typedevent_handler(void (*entry)(size_t, const void *, size_t)) XRAY_NEVER_INSTRUMENT { - if (atomic_load(&XRayInitialized, memory_order_acquire)) { + if (atomic_load(&XRayInitialized, + memory_order_acquire)) { atomic_store(&__xray::XRayPatchedTypedEvent, - reinterpret_cast<uintptr_t>(entry), memory_order_release); + reinterpret_cast<uintptr_t>(entry), + memory_order_release); return 1; } return 0; @@ -571,78 +474,39 @@ XRayPatchingStatus __xray_patch() XRAY_NEVER_INSTRUMENT { return controlPatching(true); } -XRayPatchingStatus __xray_patch_object(int32_t ObjId) XRAY_NEVER_INSTRUMENT { - return controlPatching(true, ObjId); -} - XRayPatchingStatus __xray_unpatch() XRAY_NEVER_INSTRUMENT { return controlPatching(false); } -XRayPatchingStatus __xray_unpatch_object(int32_t ObjId) XRAY_NEVER_INSTRUMENT { - return controlPatching(false, ObjId); -} - XRayPatchingStatus __xray_patch_function(int32_t FuncId) XRAY_NEVER_INSTRUMENT { - auto Ids = __xray::UnpackId(FuncId); - auto ObjId = Ids.first; - auto FnId = Ids.second; - return mprotectAndPatchFunction(FnId, ObjId, true); -} - -XRayPatchingStatus -__xray_patch_function_in_object(int32_t FuncId, - int32_t ObjId) XRAY_NEVER_INSTRUMENT { - return mprotectAndPatchFunction(FuncId, ObjId, true); + return mprotectAndPatchFunction(FuncId, true); } XRayPatchingStatus __xray_unpatch_function(int32_t FuncId) XRAY_NEVER_INSTRUMENT { - auto Ids = __xray::UnpackId(FuncId); - auto ObjId = Ids.first; - auto FnId = Ids.second; - return mprotectAndPatchFunction(FnId, ObjId, false); -} - -XRayPatchingStatus -__xray_unpatch_function_in_object(int32_t FuncId, - int32_t ObjId) XRAY_NEVER_INSTRUMENT { - return mprotectAndPatchFunction(FuncId, ObjId, false); + return mprotectAndPatchFunction(FuncId, false); } int __xray_set_handler_arg1(void (*entry)(int32_t, XRayEntryType, uint64_t)) { - if (!atomic_load(&XRayInitialized, memory_order_acquire)) + if (!atomic_load(&XRayInitialized, + memory_order_acquire)) return 0; // A relaxed write might not be visible even if the current thread gets // scheduled on a diff erent CPU/NUMA node. We need to wait for everyone to // have this handler installed for consistency of collected data across CPUs. atomic_store(&XRayArgLogger, reinterpret_cast<uint64_t>(entry), - memory_order_release); + memory_order_release); return 1; } int __xray_remove_handler_arg1() { return __xray_set_handler_arg1(nullptr); } -uintptr_t -__xray_function_address(int32_t CombinedFuncId) XRAY_NEVER_INSTRUMENT { - auto Ids = __xray::UnpackId(CombinedFuncId); - return __xray_function_address_in_object(Ids.second, Ids.first); -} - -uintptr_t __xray_function_address_in_object(int32_t FuncId, int32_t ObjId) - XRAY_NEVER_INSTRUMENT { +uintptr_t __xray_function_address(int32_t FuncId) XRAY_NEVER_INSTRUMENT { XRaySledMap InstrMap; { SpinMutexLock Guard(&XRayInstrMapMutex); - auto count = atomic_load(&XRayNumObjects, memory_order_acquire); - if (ObjId < 0 || ObjId >= count) { - Report("Unable to determine function address: invalid sled map index %d " - "(size is %d)\n", - ObjId, (int)count); - return 0; - } - InstrMap = XRayInstrMaps[ObjId]; + InstrMap = XRayInstrMap; } if (FuncId <= 0 || static_cast<size_t>(FuncId) > InstrMap.Functions) @@ -661,29 +525,6 @@ uintptr_t __xray_function_address_in_object(int32_t FuncId, int32_t ObjId) } size_t __xray_max_function_id() XRAY_NEVER_INSTRUMENT { - return __xray_max_function_id_in_object(0); -} - -size_t __xray_max_function_id_in_object(int32_t ObjId) XRAY_NEVER_INSTRUMENT { - SpinMutexLock Guard(&XRayInstrMapMutex); - if (ObjId < 0 || ObjId >= atomic_load(&XRayNumObjects, memory_order_acquire)) - return 0; - return XRayInstrMaps[ObjId].Functions; -} - -size_t __xray_num_objects() XRAY_NEVER_INSTRUMENT { SpinMutexLock Guard(&XRayInstrMapMutex); - return atomic_load(&XRayNumObjects, memory_order_acquire); -} - -int32_t __xray_unpack_function_id(int32_t PackedId) { - return __xray::UnpackId(PackedId).second; -} - -int32_t __xray_unpack_object_id(int32_t PackedId) { - return __xray::UnpackId(PackedId).first; -} - -int32_t __xray_pack_id(int32_t FuncId, int32_t ObjId) { - return __xray::MakePackedId(FuncId, ObjId); + return XRayInstrMap.Functions; } diff --git a/compiler-rt/lib/xray/xray_interface_internal.h b/compiler-rt/lib/xray/xray_interface_internal.h index 5fbaa9c3f315b1..80c07c167f6461 100644 --- a/compiler-rt/lib/xray/xray_interface_internal.h +++ b/compiler-rt/lib/xray/xray_interface_internal.h @@ -18,18 +18,6 @@ #include "xray/xray_interface.h" #include <cstddef> #include <cstdint> -#include <utility> - -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 void __xray_FunctionTailExit(); -extern void __xray_ArgLoggerEntry(); -extern void __xray_CustomEvent(); -extern void __xray_TypedEvent(); -} extern "C" { @@ -79,77 +67,36 @@ struct XRayFunctionSledIndex { uintptr_t(Begin)); } }; - -struct XRayTrampolines { - void (*EntryTrampoline)(); - void (*ExitTrampoline)(); - void (*TailExitTrampoline)(); - void (*LogArgsTrampoline)(); - void (*CustomEventTrampoline)(); - void (*TypedEventTrampoline)(); - - XRayTrampolines() { - // These resolve to the definitions in the respective executable or DSO. - EntryTrampoline = __xray_FunctionEntry; - ExitTrampoline = __xray_FunctionExit; - TailExitTrampoline = __xray_FunctionTailExit; - LogArgsTrampoline = __xray_ArgLoggerEntry; - CustomEventTrampoline = __xray_CustomEvent; - TypedEventTrampoline = __xray_TypedEvent; - } -}; - -extern int32_t __xray_register_dso(const XRaySledEntry *SledsBegin, - const XRaySledEntry *SledsEnd, - const XRayFunctionSledIndex *FnIndexBegin, - const XRayFunctionSledIndex *FnIndexEnd, - XRayTrampolines Trampolines); - -extern bool __xray_deregister_dso(int32_t ObjId); } namespace __xray { -constexpr uint32_t XRayNFnBits = 24; -constexpr uint32_t XRayNObjBits = 8; - -constexpr uint32_t XRayFnBitMask = 0x00FFFFFF; -constexpr uint32_t XRayObjBitMask = 0xFF000000; - -constexpr size_t XRayMaxFunctions = 1 << XRayNFnBits; -constexpr size_t XRayMaxObjects = 1 << XRayNObjBits; - -inline int32_t MakePackedId(int32_t FnId, int32_t ObjId) { - return ((ObjId << XRayNFnBits) & XRayObjBitMask) | (FnId & XRayFnBitMask); -} - -inline std::pair<int32_t, int32_t> UnpackId(int32_t PackedId) { - uint32_t ObjId = (PackedId & XRayObjBitMask) >> XRayNFnBits; - uint32_t FnId = PackedId & XRayFnBitMask; - return {ObjId, FnId}; -} - struct XRaySledMap { const XRaySledEntry *Sleds; size_t Entries; const XRayFunctionSledIndex *SledsIndex; size_t Functions; - XRayTrampolines Trampolines; - bool FromDSO; - bool Loaded; }; bool patchFunctionEntry(bool Enable, uint32_t FuncId, const XRaySledEntry &Sled, void (*Trampoline)()); -bool patchFunctionExit(bool Enable, uint32_t FuncId, const XRaySledEntry &Sled, - void (*Trampoline)()); +bool patchFunctionExit(bool Enable, uint32_t FuncId, const XRaySledEntry &Sled); bool patchFunctionTailExit(bool Enable, uint32_t FuncId, - const XRaySledEntry &Sled, void (*Trampoline)()); -bool patchCustomEvent(bool Enable, uint32_t FuncId, const XRaySledEntry &Sled, - void (*Trampoline)()); -bool patchTypedEvent(bool Enable, uint32_t FuncId, const XRaySledEntry &Sled, - void (*Trampoline)()); + const XRaySledEntry &Sled); +bool patchCustomEvent(bool Enable, uint32_t FuncId, const XRaySledEntry &Sled); +bool patchTypedEvent(bool Enable, uint32_t FuncId, const XRaySledEntry &Sled); } // 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 void __xray_FunctionTailExit(); +extern void __xray_ArgLoggerEntry(); +extern void __xray_CustomEvent(); +extern void __xray_TypedEvent(); +} + #endif diff --git a/compiler-rt/lib/xray/xray_trampoline_x86_64.S b/compiler-rt/lib/xray/xray_trampoline_x86_64.S index 0f480547b52cc6..01098f60eeab8b 100644 --- a/compiler-rt/lib/xray/xray_trampoline_x86_64.S +++ b/compiler-rt/lib/xray/xray_trampoline_x86_64.S @@ -107,16 +107,6 @@ .section __TEXT,__text #endif -.macro LOAD_HANDLER_ADDR handler -#if !defined(XRAY_PIC) - movq ASM_SYMBOL(\handler)(%rip), %rax -#else - movq ASM_SYMBOL(\handler)@GOTPCREL(%rip), %rax - movq (%rax), %rax -#endif -.endm - - //===----------------------------------------------------------------------===// .globl ASM_SYMBOL(__xray_FunctionEntry) @@ -131,7 +121,7 @@ ASM_SYMBOL(__xray_FunctionEntry): // This load has to be atomic, it's concurrent with __xray_patch(). // On x86/amd64, a simple (type-aligned) MOV instruction is enough. - LOAD_HANDLER_ADDR _ZN6__xray19XRayPatchedFunctionE + movq ASM_SYMBOL(_ZN6__xray19XRayPatchedFunctionE)(%rip), %rax testq %rax, %rax je LOCAL_LABEL(tmp0) @@ -169,7 +159,7 @@ ASM_SYMBOL(__xray_FunctionExit): movupd %xmm1, 16(%rsp) movq %rax, 8(%rsp) movq %rdx, 0(%rsp) - LOAD_HANDLER_ADDR _ZN6__xray19XRayPatchedFunctionE + movq ASM_SYMBOL(_ZN6__xray19XRayPatchedFunctionE)(%rip), %rax testq %rax,%rax je LOCAL_LABEL(tmp2) @@ -205,7 +195,7 @@ ASM_SYMBOL(__xray_FunctionTailExit): SAVE_REGISTERS ALIGN_STACK_16B - LOAD_HANDLER_ADDR _ZN6__xray19XRayPatchedFunctionE + movq ASM_SYMBOL(_ZN6__xray19XRayPatchedFunctionE)(%rip), %rax testq %rax,%rax je LOCAL_LABEL(tmp4) @@ -234,12 +224,12 @@ ASM_SYMBOL(__xray_ArgLoggerEntry): ALIGN_STACK_16B // Again, these function pointer loads must be atomic; MOV is fine. - LOAD_HANDLER_ADDR _ZN6__xray13XRayArgLoggerE + movq ASM_SYMBOL(_ZN6__xray13XRayArgLoggerE)(%rip), %rax testq %rax, %rax jne LOCAL_LABEL(arg1entryLog) // If [arg1 logging handler] not set, defer to no-arg logging. - LOAD_HANDLER_ADDR _ZN6__xray19XRayPatchedFunctionE + movq ASM_SYMBOL(_ZN6__xray19XRayPatchedFunctionE)(%rip), %rax testq %rax, %rax je LOCAL_LABEL(arg1entryFail) @@ -278,7 +268,7 @@ ASM_SYMBOL(__xray_CustomEvent): // We take two arguments to this trampoline, which should be in rdi and rsi // already. - LOAD_HANDLER_ADDR _ZN6__xray22XRayPatchedCustomEventE + movq ASM_SYMBOL(_ZN6__xray22XRayPatchedCustomEventE)(%rip), %rax testq %rax,%rax je LOCAL_LABEL(customEventCleanup) @@ -303,7 +293,7 @@ ASM_SYMBOL(__xray_TypedEvent): // We pass three arguments to this trampoline, which should be in rdi, rsi // and rdx without our intervention. - LOAD_HANDLER_ADDR _ZN6__xray21XRayPatchedTypedEventE + movq ASM_SYMBOL(_ZN6__xray21XRayPatchedTypedEventE)(%rip), %rax testq %rax,%rax je LOCAL_LABEL(typedEventCleanup) diff --git a/compiler-rt/lib/xray/xray_x86_64.cpp b/compiler-rt/lib/xray/xray_x86_64.cpp index 663a51b2686614..b9666a40861d48 100644 --- a/compiler-rt/lib/xray/xray_x86_64.cpp +++ b/compiler-rt/lib/xray/xray_x86_64.cpp @@ -170,8 +170,7 @@ bool patchFunctionEntry(const bool Enable, const uint32_t FuncId, } bool patchFunctionExit(const bool Enable, const uint32_t FuncId, - const XRaySledEntry &Sled, - void (*Trampoline)()) XRAY_NEVER_INSTRUMENT { + const XRaySledEntry &Sled) XRAY_NEVER_INSTRUMENT { // Here we do the dance of replacing the following sled: // // xray_sled_n: @@ -193,11 +192,11 @@ bool patchFunctionExit(const bool Enable, const uint32_t FuncId, // Prerequisite is to compute the relative offset fo the // __xray_FunctionExit function's address. const uint64_t Address = Sled.address(); - int64_t TrampolineOffset = reinterpret_cast<int64_t>(Trampoline) - + int64_t TrampolineOffset = reinterpret_cast<int64_t>(__xray_FunctionExit) - (static_cast<int64_t>(Address) + 11); if (TrampolineOffset < MinOffset || TrampolineOffset > MaxOffset) { Report("XRay Exit trampoline (%p) too far from sled (%p)\n", - reinterpret_cast<void *>(Trampoline), + reinterpret_cast<void *>(__xray_FunctionExit), reinterpret_cast<void *>(Address)); return false; } @@ -218,16 +217,16 @@ bool patchFunctionExit(const bool Enable, const uint32_t FuncId, } bool patchFunctionTailExit(const bool Enable, const uint32_t FuncId, - const XRaySledEntry &Sled, - void (*Trampoline)()) XRAY_NEVER_INSTRUMENT { + 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. const uint64_t Address = Sled.address(); - int64_t TrampolineOffset = reinterpret_cast<int64_t>(Trampoline) - - (static_cast<int64_t>(Address) + 11); + int64_t TrampolineOffset = + reinterpret_cast<int64_t>(__xray_FunctionTailExit) - + (static_cast<int64_t>(Address) + 11); if (TrampolineOffset < MinOffset || TrampolineOffset > MaxOffset) { Report("XRay Tail Exit trampoline (%p) too far from sled (%p)\n", - reinterpret_cast<void *>(Trampoline), + reinterpret_cast<void *>(__xray_FunctionTailExit), reinterpret_cast<void *>(Address)); return false; } @@ -248,8 +247,7 @@ bool patchFunctionTailExit(const bool Enable, const uint32_t FuncId, } bool patchCustomEvent(const bool Enable, const uint32_t FuncId, - const XRaySledEntry &Sled, - void (*Trampoline)()) XRAY_NEVER_INSTRUMENT { + const XRaySledEntry &Sled) XRAY_NEVER_INSTRUMENT { // Here we do the dance of replacing the following sled: // // xray_sled_n: @@ -277,8 +275,7 @@ bool patchCustomEvent(const bool Enable, const uint32_t FuncId, } bool patchTypedEvent(const bool Enable, const uint32_t FuncId, - const XRaySledEntry &Sled, - void (*Trampoline)()) XRAY_NEVER_INSTRUMENT { + const XRaySledEntry &Sled) XRAY_NEVER_INSTRUMENT { // Here we do the dance of replacing the following sled: // // xray_sled_n: diff --git a/compiler-rt/test/xray/TestCases/Posix/basic-mode-dso.cpp b/compiler-rt/test/xray/TestCases/Posix/basic-mode-dso.cpp deleted file mode 100644 index 31c615bd1f81bf..00000000000000 --- a/compiler-rt/test/xray/TestCases/Posix/basic-mode-dso.cpp +++ /dev/null @@ -1,47 +0,0 @@ -// Testing shared library support in basic logging mode. - -// RUN: split-file %s %t -// RUN: %clangxx_xray -g -fPIC -fxray-instrument -fxray-shared -shared -std=c++11 %t/testlib.cpp -o %t/testlib.so -// RUN: %clangxx_xray -g -fPIC -fxray-instrument -fxray-shared -std=c++11 %t/main.cpp %t/testlib.so -Wl,-rpath,%t -o %t/main.o - -// RUN: XRAY_OPTIONS="patch_premain=false,xray_mode=xray-basic,xray_logfile_base=basic-mode-dso-,verbosity=1" XRAY_BASIC_OPTIONS="func_duration_threshold_us=0" %run %t/main.o 2>&1 | FileCheck %s -// RUN: %llvm_xray account --format=csv --sort=funcid "`ls basic-mode-dso-* | head -1`" | FileCheck --check-prefix=ACCOUNT %s -// RUN: rm basic-mode-dso-* - -// REQUIRES: target=x86_64{{.*}} - -//--- main.cpp - -#include "xray/xray_interface.h" - -#include <cstdio> -#include <unistd.h> - -[[clang::xray_always_instrument]] void instrumented_in_executable() { - printf("instrumented_in_executable called\n"); - sleep(1); -} - -extern void instrumented_in_dso(); - -int main() { - // Explicit patching to ensure the DSO has been loaded - __xray_patch(); - instrumented_in_executable(); - // CHECK: instrumented_in_executable called - instrumented_in_dso(); - // CHECK-NEXT: instrumented_in_dso called -} - -//--- testlib.cpp - -#include <cstdio> -#include <unistd.h> - -[[clang::xray_always_instrument]] void instrumented_in_dso() { - printf("instrumented_in_dso called\n"); -} - -// ACCOUNT: funcid,count,min,median,90%ile,99%ile,max,sum,debug,function -// ACCOUNT-NEXT: 1,1,{{.*}} -// ACCOUNT-NEXT: 16777217,1,{{.*}} diff --git a/compiler-rt/test/xray/TestCases/Posix/clang-xray-shared.cpp b/compiler-rt/test/xray/TestCases/Posix/clang-xray-shared.cpp deleted file mode 100644 index 92f3c29e970d42..00000000000000 --- a/compiler-rt/test/xray/TestCases/Posix/clang-xray-shared.cpp +++ /dev/null @@ -1,14 +0,0 @@ -// Test that the DSO-local runtime library has been linked if -fxray-shared is passed. -// -// RUN: %clangxx -fxray-instrument -fxray-shared %s -shared -o %t.so -// RUN: llvm-nm %t.so | FileCheck %s --check-prefix ENABLED - -// RUN: %clangxx -fxray-instrument %s -shared -o %t.so -// RUN: llvm-nm %t.so | FileCheck %s --check-prefix DISABLED -// -// REQUIRES: target=x86_64{{.*}} - -[[clang::xray_always_instrument]] int always_instrumented() { return 42; } - -// ENABLED: __start_xray_instr_map -// DISABLED-NOT: __start_xray_instr_map diff --git a/compiler-rt/test/xray/TestCases/Posix/dlopen.cpp b/compiler-rt/test/xray/TestCases/Posix/dlopen.cpp deleted file mode 100644 index 9db411d5ff1c6e..00000000000000 --- a/compiler-rt/test/xray/TestCases/Posix/dlopen.cpp +++ /dev/null @@ -1,107 +0,0 @@ -// Check that we can patch and un-patch DSOs loaded with dlopen. -// - -// RUN: split-file %s %t -// RUN: %clangxx_xray -g -fPIC -fxray-instrument -fxray-shared -shared -std=c++11 %t/testlib.cpp -o %t/testlib.so -// RUN: %clangxx_xray -g -fPIC -rdynamic -fxray-instrument -fxray-shared -std=c++11 %t/main.cpp -o %t/main.o -// -// RUN: XRAY_OPTIONS="patch_premain=true" %run %t/main.o %t/testlib.so 2>&1 | FileCheck %s - -// REQUIRES: target=x86_64{{.*}} - -//--- main.cpp - -#include "xray/xray_interface.h" - -#include <cstdio> -#include <dlfcn.h> - -void test_handler(int32_t fid, XRayEntryType type) { - printf("called: %d, type=%d\n", fid, static_cast<int32_t>(type)); -} - -[[clang::xray_always_instrument]] void instrumented_in_executable() { - printf("instrumented_in_executable called\n"); -} - -typedef void (*dso_func_type)(); - -int main(int argc, char **argv) { - if (argc < 2) { - printf("Shared library argument missing\n"); - // CHECK-NOT: Shared library argument missing - return 1; - } - - const char *dso_path = argv[1]; - - void *dso_handle = dlopen(dso_path, RTLD_LAZY); - if (!dso_handle) { - printf("Failed to load shared library\n"); - char *error = dlerror(); - if (error) { - fprintf(stderr, "%s\n", error); - return 1; - } - return 1; - } - - dso_func_type instrumented_in_dso = - (dso_func_type)dlsym(dso_handle, "_Z19instrumented_in_dsov"); - if (!instrumented_in_dso) { - printf("Failed to find symbol\n"); - char *error = dlerror(); - if (error) { - fprintf(stderr, "%s\n", error); - return 1; - } - return 1; - } - - __xray_set_handler(test_handler); - - instrumented_in_executable(); - // CHECK: called: {{.*}}, type=0 - // CHECK-NEXT: instrumented_in_executable called - // CHECK-NEXT: called: {{.*}}, type=1 - instrumented_in_dso(); - // CHECK-NEXT: called: {{.*}}, type=0 - // CHECK-NEXT: instrumented_in_dso called - // CHECK-NEXT: called: {{.*}}, type=1 - - auto status = __xray_unpatch(); - printf("unpatching status: %d\n", static_cast<int32_t>(status)); - // CHECK-NEXT: unpatching status: 1 - - instrumented_in_executable(); - // CHECK-NEXT: instrumented_in_executable called - instrumented_in_dso(); - // CHECK-NEXT: instrumented_in_dso called - - status = __xray_patch(); - printf("patching status: %d\n", static_cast<int32_t>(status)); - // CHECK-NEXT: patching status: 1 - - instrumented_in_executable(); - // CHECK-NEXT: called: {{.*}}, type=0 - // CHECK-NEXT: instrumented_in_executable called - // CHECK-NEXT: called: {{.*}}, type=1 - instrumented_in_dso(); - // CHECK-NEXT: called: {{.*}}, type=0 - // CHECK-NEXT: instrumented_in_dso called - // CHECK-NEXT: called: {{.*}}, type=1 - - dlclose(dso_handle); - - status = __xray_unpatch(); - printf("unpatching status: %d\n", static_cast<int32_t>(status)); - // CHECK-NEXT: unpatching status: 1 -} - -//--- testlib.cpp - -#include <cstdio> - -[[clang::xray_always_instrument]] void instrumented_in_dso() { - printf("instrumented_in_dso called\n"); -} diff --git a/compiler-rt/test/xray/TestCases/Posix/dso-dep-chains.cpp b/compiler-rt/test/xray/TestCases/Posix/dso-dep-chains.cpp deleted file mode 100644 index 89da2764c35cee..00000000000000 --- a/compiler-rt/test/xray/TestCases/Posix/dso-dep-chains.cpp +++ /dev/null @@ -1,197 +0,0 @@ -// Check that loading libraries with diff erent modes (RTLD_LOCAL/RTLD_GLOBAL) -// and dependencies on other DSOs work correctly. -// - -// RUN: split-file %s %t -// -// Build shared libs with dependencies b->c and e->f -// RUN: %clangxx_xray -g -fPIC -fxray-instrument -fxray-shared -shared -std=c++11 %t/testliba.cpp -o %t/testliba.so -// RUN: %clangxx_xray -g -fPIC -fxray-instrument -fxray-shared -shared -std=c++11 %t/testlibc.cpp -o %t/testlibc.so -// RUN: %clangxx_xray -g -fPIC -fxray-instrument -fxray-shared -shared -std=c++11 %t/testlibb.cpp %t/testlibc.so -o %t/testlibb.so -// RUN: %clangxx_xray -g -fPIC -fxray-instrument -fxray-shared -shared -std=c++11 %t/testlibd.cpp -o %t/testlibd.so -// RUN: %clangxx_xray -g -fPIC -fxray-instrument -fxray-shared -shared -std=c++11 %t/testlibf.cpp -o %t/testlibf.so -// RUN: %clangxx_xray -g -fPIC -fxray-instrument -fxray-shared -shared -std=c++11 %t/testlibe.cpp %t/testlibf.so -o %t/testlibe.so -// -// Executable links with a and b explicitly and loads d and e at runtime. -// RUN: %clangxx_xray -g -fPIC -rdynamic -fxray-instrument -fxray-shared -std=c++11 %t/main.cpp %t/testliba.so %t/testlibb.so -o %t/main.o -// -// RUN: XRAY_OPTIONS="patch_premain=true" %run %t/main.o %t/testlibd.so %t/testlibe.so 2>&1 | FileCheck %s - -// REQUIRES: target=x86_64{{.*}} - -//--- main.cpp - -#include "xray/xray_interface.h" - -#include <cstdio> -#include <dlfcn.h> - -[[clang::xray_never_instrument]] void test_handler(int32_t fid, - XRayEntryType type) { - printf("called: %d, object=%d, fn=%d, type=%d\n", fid, (fid >> 24) & 0xFF, - fid & 0x00FFFFFF, static_cast<int32_t>(type)); -} - -[[clang::xray_always_instrument]] void instrumented_in_executable() { - printf("instrumented_in_executable called\n"); -} - -typedef void (*dso_func_type)(); - -[[clang::xray_never_instrument]] void *load_dso(const char *path, int mode) { - void *dso_handle = dlopen(path, mode); - if (!dso_handle) { - printf("failed to load shared library\n"); - char *error = dlerror(); - if (error) { - fprintf(stderr, "%s\n", error); - } - return nullptr; - } - return dso_handle; -} - -[[clang::xray_never_instrument]] void find_and_call(void *dso_handle, - const char *fn) { - dso_func_type dso_fn = (dso_func_type)dlsym(dso_handle, fn); - if (!dso_fn) { - printf("failed to find symbol\n"); - char *error = dlerror(); - if (error) { - fprintf(stderr, "%s\n", error); - } - return; - } - dso_fn(); -} - -extern void a(); -extern void b(); - -int main(int argc, char **argv) { - - if (argc < 3) { - printf("Shared library arguments missing\n"); - // CHECK-NOT: Shared library arguments missing - return 1; - } - - const char *dso_path_d = argv[1]; - const char *dso_path_e = argv[2]; - - __xray_set_handler(test_handler); - - instrumented_in_executable(); - // CHECK: called: {{[0-9]+}}, object=0, fn={{[0-9]+}}, type=0 - // CHECK-NEXT: instrumented_in_executable called - // CHECK-NEXT: called: {{[0-9]+}}, object=0, fn={{[0-9]+}}, type=1 - - a(); - // CHECK-NEXT: called: {{[0-9]+}}, object=[[OBJ1:[0-9]+]], fn=1, type=0 - // CHECK-NEXT: a called - // CHECK-NEXT: called: {{[0-9]+}}, object=[[OBJ1]], fn=1, type=1 - - // Make sure this object ID does not appear again - // CHECK-NOT: called: {{[0-9]+}}, object=[[OBJ1]] - - b(); // b calls c - // CHECK-NEXT: called: {{[0-9]+}}, object=[[OBJ2:[0-9]+]], fn=1, type=0 - // CHECK-NEXT: b called - // CHECK-NEXT: called: {{[0-9]+}}, object=[[OBJ3:[0-9]+]], fn=1, type=0 - // CHECK-NEXT: c called - // CHECK-NEXT: called: {{[0-9]+}}, object=[[OBJ3]], fn=1, type=1 - // CHECK-NOT: called: {{[0-9]+}}, object=[[OBJ3]] - // CHECK-NEXT: called: {{[0-9]+}}, object=[[OBJ2]], fn=1, type=1 - // CHECK-NOT: called: {{[0-9]+}}, object=[[OBJ2]] - - // Now check explicit loading with RTLD_LOCAL - - void *dso_handle_d = load_dso(dso_path_d, RTLD_LAZY | RTLD_LOCAL); - void *dso_handle_e = load_dso(dso_path_e, RTLD_LAZY | RTLD_LOCAL); - // CHECK-NOT: failed to load shared library - - find_and_call(dso_handle_d, "_Z1dv"); - // CHECK-NEXT: called: {{[0-9]+}}, object=[[OBJ4:[0-9]+]], fn=1, type=0 - // CHECK-NEXT: d called - // CHECK-NEXT: called: {{[0-9]+}}, object=[[OBJ4]], fn=1, type=1 - // CHECK-NOT: called: {{[0-9]+}}, object=[[OBJ4]] - - find_and_call(dso_handle_e, "_Z1ev"); - // CHECK-NEXT: called: {{[0-9]+}}, object=[[OBJ5:[0-9]+]], fn=1, type=0 - // CHECK-NEXT: e called - // CHECK-NEXT: called: {{[0-9]+}}, object=[[OBJ6:[0-9]+]], fn=1, type=0 - // CHECK-NEXT: f called - // CHECK-NEXT: called: {{[0-9]+}}, object=[[OBJ6]], fn=1, type=1 - // CHECK-NOT: called: {{[0-9]+}}, object=[[OBJ6]] - // CHECK-NEXT: called: {{[0-9]+}}, object=[[OBJ5]], fn=1, type=1 - // CHECK-NOT: called: {{[0-9]+}}, object=[[OBJ5]] - - // Unload DSOs - dlclose(dso_handle_d); - dlclose(dso_handle_e); - - // Repeat test with RTLD_GLOBAL - dso_handle_d = load_dso(dso_path_d, RTLD_LAZY | RTLD_GLOBAL); - dso_handle_e = load_dso(dso_path_e, RTLD_LAZY | RTLD_GLOBAL); - // CHECK-NOT: failed to load shared library - - find_and_call(dso_handle_d, "_Z1dv"); - // CHECK-NEXT: called: {{[0-9]+}}, object=[[OBJ7:[0-9]+]], fn=1, type=0 - // CHECK-NEXT: d called - // CHECK-NEXT: called: {{[0-9]+}}, object=[[OBJ7]], fn=1, type=1 - // CHECK-NOT: called: {{[0-9]+}}, object=[[OBJ7]] - - find_and_call(dso_handle_e, "_Z1ev"); - // CHECK-NEXT: called: {{[0-9]+}}, object=[[OBJ8:[0-9]+]], fn=1, type=0 - // CHECK-NEXT: e called - // CHECK-NEXT: called: {{[0-9]+}}, object=[[OBJ9:[0-9]+]], fn=1, type=0 - // CHECK-NEXT: f called - // CHECK-NEXT: called: {{[0-9]+}}, object=[[OBJ9]], fn=1, type=1 - // CHECK-NOT: called: {{[0-9]+}}, object=[[OBJ9]] - // CHECK-NEXT: called: {{[0-9]+}}, object=[[OBJ8]], fn=1, type=1 - // CHECK-NOT: called: {{[0-9]+}}, object=[[OBJ8]] - - auto status = __xray_unpatch(); - printf("unpatching status: %d\n", static_cast<int32_t>(status)); - // CHECK-NEXT: unpatching status: 1 - - dlclose(dso_handle_d); - dlclose(dso_handle_e); -} - -//--- libgenmacro.inc -#include <cstdio> -// Helper macros to quickly generate libraries containing a single function. -#define GENERATE_LIB(NAME) \ - [[clang::xray_always_instrument]] void NAME() { printf(#NAME " called\n"); } - -#define GENERATE_LIB_WITH_CALL(NAME, FN) \ - extern void FN(); \ - [[clang::xray_always_instrument]] void NAME() { \ - printf(#NAME " called\n"); \ - FN(); \ - } - -//--- testliba.cpp -#include "libgenmacro.inc" -GENERATE_LIB(a) - -//--- testlibb.cpp -#include "libgenmacro.inc" -GENERATE_LIB_WITH_CALL(b, c) - -//--- testlibc.cpp -#include "libgenmacro.inc" -GENERATE_LIB(c) - -//--- testlibd.cpp -#include "libgenmacro.inc" -GENERATE_LIB(d) - -//--- testlibe.cpp -#include "libgenmacro.inc" -GENERATE_LIB_WITH_CALL(e, f) - -//--- testlibf.cpp -#include "libgenmacro.inc" -GENERATE_LIB(f) diff --git a/compiler-rt/test/xray/TestCases/Posix/patch-premain-dso.cpp b/compiler-rt/test/xray/TestCases/Posix/patch-premain-dso.cpp deleted file mode 100644 index 0708d0383439d0..00000000000000 --- a/compiler-rt/test/xray/TestCases/Posix/patch-premain-dso.cpp +++ /dev/null @@ -1,45 +0,0 @@ -// Checking that DSOs are automatically patched upon load, if patch_premain is passed. - -// RUN: split-file %s %t -// RUN: %clangxx_xray -g -fPIC -fxray-instrument -fxray-shared -shared -std=c++11 %t/testlib.cpp -o %t/testlib.so -// RUN: %clangxx_xray -g -fPIC -fxray-instrument -fxray-shared -std=c++11 %t/main.cpp %t/testlib.so -Wl,-rpath,%t -o %t/main.o - -// RUN: XRAY_OPTIONS="patch_premain=true,verbosity=1" %run %t/main.o 2>&1 | FileCheck %s - -// REQUIRES: target=x86_64{{.*}} - -//--- main.cpp - -#include "xray/xray_interface.h" - -#include <cstdio> - -void test_handler(int32_t fid, XRayEntryType type) { - printf("called: %d, type=%d\n", fid, static_cast<int32_t>(type)); -} - -[[clang::xray_always_instrument]] void instrumented_in_executable() { - printf("instrumented_in_executable called\n"); -} - -extern void instrumented_in_dso(); - -int main() { - __xray_set_handler(test_handler); - instrumented_in_executable(); - // CHECK: called: {{.*}}, type=0 - // CHECK-NEXT: instrumented_in_executable called - // CHECK-NEXT: called: {{.*}}, type=1 - instrumented_in_dso(); - // CHECK-NEXT: called: {{.*}}, type=0 - // CHECK-NEXT: instrumented_in_dso called - // CHECK-NEXT: called: {{.*}}, type=1 -} - -//--- testlib.cpp - -#include <cstdio> - -[[clang::xray_always_instrument]] void instrumented_in_dso() { - printf("instrumented_in_dso called\n"); -} diff --git a/compiler-rt/test/xray/TestCases/Posix/patching-unpatching-dso.cpp b/compiler-rt/test/xray/TestCases/Posix/patching-unpatching-dso.cpp deleted file mode 100644 index d3e992dd497725..00000000000000 --- a/compiler-rt/test/xray/TestCases/Posix/patching-unpatching-dso.cpp +++ /dev/null @@ -1,75 +0,0 @@ -// Check that we can patch and un-patch on demand, and that logging gets invoked -// appropriately. -// - -// RUN: split-file %s %t -// RUN: %clangxx_xray -g -fPIC -fxray-instrument -fxray-shared -shared -std=c++11 %t/testlib.cpp -o %t/testlib.so -// RUN: %clangxx_xray -g -fPIC -fxray-instrument -fxray-shared -std=c++11 %t/main.cpp %t/testlib.so -Wl,-rpath,%t -o %t/main.o - -// RUN: XRAY_OPTIONS="patch_premain=false" %run %t/main.o 2>&1 | FileCheck %s - -// REQUIRES: target=x86_64{{.*}} - -//--- main.cpp - -#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 instrumented_in_executable() { - printf("instrumented_in_executable called\n"); -} - -extern void instrumented_in_dso(); - -int main() { - __xray_set_handler(test_handler); - instrumented_in_executable(); - // CHECK: instrumented_in_executable called - instrumented_in_dso(); - // CHECK: instrumented_in_dso called - auto status = __xray_patch(); - printf("patching status: %d\n", static_cast<int32_t>(status)); - // CHECK-NEXT: patching status: 1 - instrumented_in_executable(); - // CHECK-NEXT: called: {{.*}}, type=0 - // CHECK-NEXT: instrumented_in_executable called - // CHECK-NEXT: called: {{.*}}, type=1 - instrumented_in_dso(); - // CHECK-NEXT: called: {{.*}}, type=0 - // CHECK-NEXT: instrumented_in_dso called - // CHECK-NEXT: called: {{.*}}, type=1 - status = __xray_unpatch(); - printf("patching status: %d\n", static_cast<int32_t>(status)); - // CHECK-NEXT: patching status: 1 - instrumented_in_executable(); - // CHECK-NEXT: instrumented_in_executable called - instrumented_in_dso(); - // CHECK-NEXT: instrumented_in_dso called - status = __xray_patch(); - printf("patching status: %d\n", static_cast<int32_t>(status)); - // CHECK-NEXT: patching status: 1 - __xray_remove_handler(); - instrumented_in_executable(); - // CHECK-NEXT: instrumented_in_executable called - instrumented_in_dso(); - // CHECK-NEXT: instrumented_in_dso called - status = __xray_unpatch(); - printf("patching status: %d\n", static_cast<int32_t>(status)); - // CHECK-NEXT: patching status: 1 -} - -//--- testlib.cpp - -#include <cstdio> - -[[clang::xray_always_instrument]] void instrumented_in_dso() { - printf("instrumented_in_dso called\n"); -} _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits