Skip to content

Commit 5143ef4

Browse files
[XRay] Add DSO support for XRay instrumentation on X86_64
1 parent 0e7590a commit 5143ef4

19 files changed

+912
-118
lines changed

clang/include/clang/Driver/Options.td

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2887,6 +2887,10 @@ def fxray_selected_function_group :
28872887
HelpText<"When using -fxray-function-groups, select which group of functions to instrument. Valid range is 0 to fxray-function-groups - 1">,
28882888
MarshallingInfoInt<CodeGenOpts<"XRaySelectedFunctionGroup">, "0">;
28892889

2890+
def fxray_enable_shared : Flag<["-"], "fxray-enable-shared">, Group<f_Group>, Visibility<[ClangOption, CC1Option]>,
2891+
HelpText<"Enable shared library instrumentation.">;
2892+
def fno_xray_enable_shared : Flag<["-"], "fno-xray-enable-shared">, Group<f_Group>,
2893+
Visibility<[ClangOption, CC1Option]>;
28902894

28912895
defm fine_grained_bitfield_accesses : BoolOption<"f", "fine-grained-bitfield-accesses",
28922896
CodeGenOpts<"FineGrainedBitfieldAccesses">, DefaultFalse,

clang/include/clang/Driver/XRayArgs.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@ class XRayArgs {
2727
XRayInstrSet InstrumentationBundle;
2828
llvm::opt::Arg *XRayInstrument = nullptr;
2929
bool XRayRT = true;
30+
bool XRayEnableShared = false;
3031

3132
public:
3233
/// Parses the XRay arguments from an argument list.
@@ -35,6 +36,9 @@ class XRayArgs {
3536
llvm::opt::ArgStringList &CmdArgs, types::ID InputType) const;
3637

3738
bool needsXRayRt() const { return XRayInstrument && XRayRT; }
39+
bool needsXRayDSORt() const {
40+
return XRayInstrument && XRayRT && XRayEnableShared;
41+
}
3842
llvm::ArrayRef<std::string> modeList() const { return Modes; }
3943
XRayInstrSet instrumentationBundle() const { return InstrumentationBundle; }
4044
};

clang/lib/Driver/ToolChains/CommonArgs.cpp

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1593,10 +1593,14 @@ bool tools::addSanitizerRuntimes(const ToolChain &TC, const ArgList &Args,
15931593
}
15941594

15951595
bool tools::addXRayRuntime(const ToolChain&TC, const ArgList &Args, ArgStringList &CmdArgs) {
1596-
if (Args.hasArg(options::OPT_shared))
1597-
return false;
1598-
1599-
if (TC.getXRayArgs().needsXRayRt()) {
1596+
if (Args.hasArg(options::OPT_shared)) {
1597+
if (TC.getXRayArgs().needsXRayDSORt()) {
1598+
CmdArgs.push_back("-whole-archive");
1599+
CmdArgs.push_back(TC.getCompilerRTArgString(Args, "xray-dso"));
1600+
CmdArgs.push_back("-no-whole-archive");
1601+
return true;
1602+
}
1603+
} else if (TC.getXRayArgs().needsXRayRt()) {
16001604
CmdArgs.push_back("--whole-archive");
16011605
CmdArgs.push_back(TC.getCompilerRTArgString(Args, "xray"));
16021606
for (const auto &Mode : TC.getXRayArgs().modeList())

clang/lib/Driver/XRayArgs.cpp

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -63,6 +63,10 @@ XRayArgs::XRayArgs(const ToolChain &TC, const ArgList &Args) {
6363
<< XRayInstrument->getSpelling() << Triple.str();
6464
}
6565

66+
if (Args.hasFlag(options::OPT_fxray_enable_shared,
67+
options::OPT_fno_xray_enable_shared, false))
68+
XRayEnableShared = true;
69+
6670
// Both XRay and -fpatchable-function-entry use
6771
// TargetOpcode::PATCHABLE_FUNCTION_ENTER.
6872
if (Arg *A = Args.getLastArg(options::OPT_fpatchable_function_entry_EQ))
@@ -177,6 +181,9 @@ void XRayArgs::addArgs(const ToolChain &TC, const ArgList &Args,
177181
Args.addOptOutFlag(CmdArgs, options::OPT_fxray_function_index,
178182
options::OPT_fno_xray_function_index);
179183

184+
if (XRayEnableShared)
185+
CmdArgs.push_back("-fxray-enable-shared");
186+
180187
if (const Arg *A =
181188
Args.getLastArg(options::OPT_fxray_instruction_threshold_EQ)) {
182189
int Value;

compiler-rt/cmake/Modules/AllSupportedArchDefs.cmake

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -88,6 +88,7 @@ else()
8888
set(ALL_XRAY_SUPPORTED_ARCH ${X86_64} ${ARM32} ${ARM64} ${MIPS32} ${MIPS64}
8989
powerpc64le ${HEXAGON} ${LOONGARCH64})
9090
endif()
91+
set(ALL_XRAY_DSO_SUPPORTED_ARCH ${X86_64})
9192
set(ALL_SHADOWCALLSTACK_SUPPORTED_ARCH ${ARM64})
9293

9394
if (UNIX)

compiler-rt/cmake/config-ix.cmake

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -648,6 +648,9 @@ if(APPLE)
648648
list_intersect(XRAY_SUPPORTED_ARCH
649649
ALL_XRAY_SUPPORTED_ARCH
650650
SANITIZER_COMMON_SUPPORTED_ARCH)
651+
list_intersect(XRAY_DSO_SUPPORTED_ARCH
652+
ALL_XRAY_DSO_SUPPORTED_ARCH
653+
SANITIZER_COMMON_SUPPORTED_ARCH)
651654
list_intersect(SHADOWCALLSTACK_SUPPORTED_ARCH
652655
ALL_SHADOWCALLSTACK_SUPPORTED_ARCH
653656
SANITIZER_COMMON_SUPPORTED_ARCH)
@@ -682,6 +685,7 @@ else()
682685
filter_available_targets(CFI_SUPPORTED_ARCH ${ALL_CFI_SUPPORTED_ARCH})
683686
filter_available_targets(SCUDO_STANDALONE_SUPPORTED_ARCH ${ALL_SCUDO_STANDALONE_SUPPORTED_ARCH})
684687
filter_available_targets(XRAY_SUPPORTED_ARCH ${ALL_XRAY_SUPPORTED_ARCH})
688+
filter_available_targets(XRAY_DSO_SUPPORTED_ARCH ${ALL_XRAY_DSO_SUPPORTED_ARCH})
685689
filter_available_targets(SHADOWCALLSTACK_SUPPORTED_ARCH
686690
${ALL_SHADOWCALLSTACK_SUPPORTED_ARCH})
687691
filter_available_targets(GWP_ASAN_SUPPORTED_ARCH ${ALL_GWP_ASAN_SUPPORTED_ARCH})

compiler-rt/include/xray/xray_interface.h

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -97,27 +97,50 @@ enum XRayPatchingStatus {
9797
/// for possible result values.
9898
extern XRayPatchingStatus __xray_patch();
9999

100+
extern XRayPatchingStatus __xray_patch_object(int32_t ObjId);
101+
100102
/// Reverses the effect of __xray_patch(). See XRayPatchingStatus for possible
101103
/// result values.
102104
extern XRayPatchingStatus __xray_unpatch();
103105

106+
extern XRayPatchingStatus __xray_unpatch_object(int32_t ObjId);
107+
104108
/// This patches a specific function id. See XRayPatchingStatus for possible
105109
/// result values.
106110
extern XRayPatchingStatus __xray_patch_function(int32_t FuncId);
107111

112+
extern XRayPatchingStatus __xray_patch_function_in_object(int32_t FuncId,
113+
int32_t ObjId);
114+
108115
/// This unpatches a specific function id. See XRayPatchingStatus for possible
109116
/// result values.
110117
extern XRayPatchingStatus __xray_unpatch_function(int32_t FuncId);
111118

119+
extern XRayPatchingStatus __xray_unpatch_function_in_object(int32_t FuncId,
120+
int32_t ObjId);
121+
112122
/// This function returns the address of the function provided a valid function
113123
/// id. We return 0 if we encounter any error, even if 0 may be a valid function
114124
/// address.
115125
extern uintptr_t __xray_function_address(int32_t FuncId);
116126

127+
extern uintptr_t __xray_function_address_in_object(int32_t FuncId,
128+
int32_t ObjId);
129+
117130
/// This function returns the maximum valid function id. Returns 0 if we
118131
/// encounter errors (when there are no instrumented functions, etc.).
119132
extern size_t __xray_max_function_id();
120133

134+
extern size_t __xray_max_function_id_in_object(int32_t ObjId);
135+
136+
extern size_t __xray_num_objects();
137+
138+
extern int32_t __xray_unpack_function_id(int32_t PackedId);
139+
140+
extern int32_t __xray_unpack_object_id(int32_t PackedId);
141+
142+
extern int32_t __xray_pack_id(int32_t FuncId, int32_t ObjId);
143+
121144
/// Initialize the required XRay data structures. This is useful in cases where
122145
/// users want to control precisely when the XRay instrumentation data
123146
/// structures are initialized, for example when the XRay library is built with

compiler-rt/lib/xray/CMakeLists.txt

Lines changed: 70 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,10 @@ set(XRAY_SOURCES
1010
xray_utils.cpp
1111
)
1212

13+
set(XRAY_DSO_SOURCES
14+
xray_dso_init.cpp
15+
)
16+
1317
# Implementation files for all XRay modes.
1418
set(XRAY_FDR_MODE_SOURCES
1519
xray_fdr_flags.cpp
@@ -33,6 +37,11 @@ set(x86_64_SOURCES
3337
xray_trampoline_x86_64.S
3438
)
3539

40+
set(x86_64_DSO_SOURCES
41+
xray_trampoline_x86_64.S
42+
)
43+
44+
3645
set(arm_SOURCES
3746
xray_arm.cpp
3847
xray_trampoline_arm.S
@@ -128,10 +137,12 @@ set(XRAY_IMPL_HEADERS
128137
# consumption by tests.
129138
set(XRAY_ALL_SOURCE_FILES
130139
${XRAY_SOURCES}
140+
${XRAY_DSO_SOURCES}
131141
${XRAY_FDR_MODE_SOURCES}
132142
${XRAY_BASIC_MODE_SOURCES}
133143
${XRAY_PROFILING_MODE_SOURCES}
134144
${x86_64_SOURCES}
145+
${x86_64_DSO_SOURCES}
135146
${arm_SOURCES}
136147
${armhf_SOURCES}
137148
${hexagon_SOURCES}
@@ -162,6 +173,9 @@ set(XRAY_CFLAGS
162173
${COMPILER_RT_CXX_CFLAGS})
163174
set(XRAY_COMMON_DEFINITIONS SANITIZER_COMMON_NO_REDEFINE_BUILTINS XRAY_HAS_EXCEPTIONS=1)
164175

176+
# DSO trampolines need to be compiled with GOT addressing
177+
set(XRAY_COMMON_DEFINITIONS_DSO ${XRAY_COMMON_DEFINITIONS} XRAY_PIC)
178+
165179
# Too many existing bugs, needs cleanup.
166180
append_list_if(COMPILER_RT_HAS_WNO_FORMAT -Wno-format XRAY_CFLAGS)
167181

@@ -201,7 +215,16 @@ if (APPLE)
201215
CFLAGS ${XRAY_CFLAGS}
202216
DEFS ${XRAY_COMMON_DEFINITIONS}
203217
DEPS ${XRAY_DEPS})
218+
add_compiler_rt_object_libraries(RTXrayDSO
219+
OS ${XRAY_SUPPORTED_OS}
220+
ARCHS ${XRAY_DSO_SUPPORTED_ARCH}
221+
SOURCES ${XRAY_DSO_SOURCES}
222+
ADDITIONAL_HEADERS ${XRAY_IMPL_HEADERS}
223+
CFLAGS ${XRAY_CFLAGS}
224+
DEFS ${XRAY_COMMON_DEFINITIONS_DSO}
225+
DEPS ${XRAY_DEPS})
204226
set(XRAY_RTXRAY_ARCH_LIBS "")
227+
set(XRAY_DSO_RTXRAY_ARCH_LIBS "")
205228
foreach(arch ${XRAY_SUPPORTED_ARCH})
206229
if(NOT ${arch} IN_LIST XRAY_SOURCE_ARCHS)
207230
continue()
@@ -215,6 +238,17 @@ if (APPLE)
215238
DEFS ${XRAY_COMMON_DEFINITIONS}
216239
DEPS ${XRAY_DEPS})
217240
list(APPEND XRAY_RTXRAY_ARCH_LIBS RTXray_${arch})
241+
if (${arch} IN_LIST XRAY_DSO_SUPPORTED_ARCH)
242+
add_compiler_rt_object_libraries(RTXrayDSO_${arch}
243+
OS ${XRAY_SUPPORTED_OS}
244+
ARCHS ${XRAY_DSO_SUPPORTED_ARCH}
245+
SOURCES ${${arch}_DSO_SOURCES}
246+
ADDITIONAL_HEADERS ${XRAY_IMPL_HEADERS}
247+
CFLAGS ${XRAY_CFLAGS}
248+
DEFS ${XRAY_COMMON_DEFINITIONS_DSO}
249+
DEPS ${XRAY_DEPS})
250+
list(APPEND XRAY_DSO_RTXRAY_ARCH_LIBS RTXrayDSO_${arch})
251+
endif()
218252
endforeach()
219253
add_compiler_rt_object_libraries(RTXrayFDR
220254
OS ${XRAY_SUPPORTED_OS}
@@ -252,6 +286,17 @@ if (APPLE)
252286
LINK_FLAGS ${XRAY_LINK_FLAGS} ${WEAK_SYMBOL_LINK_FLAGS}
253287
LINK_LIBS ${XRAY_LINK_LIBS}
254288
PARENT_TARGET xray)
289+
add_compiler_rt_runtime(clang_rt.xray-dso
290+
STATIC
291+
OS ${XRAY_SUPPORTED_OS}
292+
ARCHS ${XRAY_DSO_SUPPORTED_ARCH}
293+
OBJECT_LIBS RTXrayDSO ${XRAY_DSO_RTXRAY_ARCH_LIBS}
294+
CFLAGS ${XRAY_CFLAGS}
295+
DEFS ${XRAY_COMMON_DEFINITIONS}
296+
LINK_FLAGS ${XRAY_LINK_FLAGS} ${WEAK_SYMBOL_LINK_FLAGS}
297+
LINK_LIBS ${XRAY_LINK_LIBS}
298+
PARENT_TARGET xray)
299+
255300
add_compiler_rt_runtime(clang_rt.xray-fdr
256301
STATIC
257302
OS ${XRAY_SUPPORTED_OS}
@@ -283,6 +328,7 @@ if (APPLE)
283328
LINK_LIBS ${XRAY_LINK_LIBS}
284329
PARENT_TARGET xray)
285330
else() # not Apple
331+
message("DSO Supported Archs: ${XRAY_DSO_SUPPORTED_ARCH}")
286332
foreach(arch ${XRAY_SUPPORTED_ARCH})
287333
if(NOT CAN_TARGET_${arch})
288334
continue()
@@ -325,7 +371,7 @@ else() # not Apple
325371
LINK_LIBS ${XRAY_LINK_LIBS}
326372
DEFS ${XRAY_COMMON_DEFINITIONS}
327373
OBJECT_LIBS ${XRAY_COMMON_RUNTIME_OBJECT_LIBS} RTXray
328-
PARENT_TARGET xray)
374+
PARENT_TARGET xray)
329375
# FDR mode runtime archive (addon for clang_rt.xray)
330376
add_compiler_rt_runtime(clang_rt.xray-fdr
331377
STATIC
@@ -346,8 +392,8 @@ else() # not Apple
346392
DEFS ${XRAY_COMMON_DEFINITIONS}
347393
OBJECT_LIBS RTXrayBASIC
348394
PARENT_TARGET xray)
349-
# Profiler Mode runtime
350-
add_compiler_rt_runtime(clang_rt.xray-profiling
395+
# Profiler Mode runtime
396+
add_compiler_rt_runtime(clang_rt.xray-profiling
351397
STATIC
352398
ARCHS ${arch}
353399
CFLAGS ${XRAY_CFLAGS}
@@ -356,6 +402,27 @@ else() # not Apple
356402
DEFS ${XRAY_COMMON_DEFINITIONS}
357403
OBJECT_LIBS RTXrayPROFILING
358404
PARENT_TARGET xray)
405+
406+
if (${arch} IN_LIST XRAY_DSO_SUPPORTED_ARCH)
407+
# TODO: Only implemented for X86 at the moment
408+
add_compiler_rt_object_libraries(RTXrayDSO
409+
ARCHS ${arch}
410+
SOURCES ${XRAY_DSO_SOURCES} ${${arch}_DSO_SOURCES}
411+
ADDITIONAL_HEADERS ${XRAY_IMPL_HEADERS}
412+
CFLAGS ${XRAY_CFLAGS}
413+
DEFS ${XRAY_COMMON_DEFINITIONS_DSO}
414+
DEPS ${XRAY_DEPS})
415+
# DSO runtime archive
416+
add_compiler_rt_runtime(clang_rt.xray-dso
417+
STATIC
418+
ARCHS ${arch}
419+
CFLAGS ${XRAY_CFLAGS}
420+
LINK_FLAGS ${XRAY_LINK_FLAGS}
421+
LINK_LIBS ${XRAY_LINK_LIBS}
422+
DEFS ${XRAY_COMMON_DEFINITIONS}
423+
OBJECT_LIBS RTXrayDSO
424+
PARENT_TARGET xray)
425+
endif()
359426
endforeach()
360427
endif() # not Apple
361428

Lines changed: 62 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,62 @@
1+
//===-- xray_init.cpp -------------------------------------------*- C++ -*-===//
2+
//
3+
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4+
// See https://llvm.org/LICENSE.txt for license information.
5+
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6+
//
7+
//===----------------------------------------------------------------------===//
8+
//
9+
// This file is a part of XRay, a dynamic runtime instrumentation system.
10+
//
11+
// XRay initialisation logic for DSOs.
12+
//===----------------------------------------------------------------------===//
13+
14+
#include "sanitizer_common/sanitizer_atomic.h"
15+
#include "xray_defs.h"
16+
#include "xray_flags.h"
17+
#include "xray_interface_internal.h"
18+
19+
using namespace __sanitizer;
20+
21+
extern "C" {
22+
extern const XRaySledEntry __start_xray_instr_map[] __attribute__((weak))
23+
__attribute__((visibility("hidden")));
24+
extern const XRaySledEntry __stop_xray_instr_map[] __attribute__((weak))
25+
__attribute__((visibility("hidden")));
26+
extern const XRayFunctionSledIndex __start_xray_fn_idx[] __attribute__((weak))
27+
__attribute__((visibility("hidden")));
28+
extern const XRayFunctionSledIndex __stop_xray_fn_idx[] __attribute__((weak))
29+
__attribute__((visibility("hidden")));
30+
31+
#if SANITIZER_MAC
32+
// HACK: This is a temporary workaround to make XRay build on
33+
// Darwin, but it will probably not work at runtime.
34+
extern const XRaySledEntry __start_xray_instr_map[] = {};
35+
extern const XRaySledEntry __stop_xray_instr_map[] = {};
36+
extern const XRayFunctionSledIndex __start_xray_fn_idx[] = {};
37+
extern const XRayFunctionSledIndex __stop_xray_fn_idx[] = {};
38+
#endif
39+
}
40+
41+
// Handler functions to call in the patched entry/exit sled.
42+
extern atomic_uintptr_t XRayPatchedFunction;
43+
extern atomic_uintptr_t XRayArgLogger;
44+
extern atomic_uintptr_t XRayPatchedCustomEvent;
45+
extern atomic_uintptr_t XRayPatchedTypedEvent;
46+
47+
static int __xray_object_id{-1};
48+
49+
// Note: .preinit_array initialization does not work for DSOs
50+
__attribute__((constructor(0))) static void
51+
__xray_init_dso() XRAY_NEVER_INSTRUMENT {
52+
// Register sleds in main XRay runtime.
53+
__xray_object_id =
54+
__xray_register_dso(__start_xray_instr_map, __stop_xray_instr_map,
55+
__start_xray_fn_idx, __stop_xray_fn_idx, {});
56+
}
57+
58+
__attribute__((destructor(0))) static void
59+
__xray_finalize_dso() XRAY_NEVER_INSTRUMENT {
60+
// Inform the main runtime that this DSO is no longer used.
61+
__xray_deregister_dso(__xray_object_id);
62+
}

0 commit comments

Comments
 (0)