Skip to content

Commit 77cb964

Browse files
[XRay] Add DSO support for XRay instrumentation on X86_64
1 parent 61a456b commit 77cb964

22 files changed

+1215
-144
lines changed

clang/include/clang/Basic/CodeGenOptions.def

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -136,6 +136,8 @@ CODEGENOPT(XRayIgnoreLoops , 1, 0)
136136
///< Emit the XRay function index section.
137137
CODEGENOPT(XRayFunctionIndex , 1, 1)
138138

139+
///< Set when -fxray-shared is enabled
140+
CODEGENOPT(XRayShared , 1, 0)
139141

140142
///< Set the minimum number of instructions in a function to determine selective
141143
///< XRay instrumentation.

clang/include/clang/Driver/Options.td

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2948,6 +2948,11 @@ def fxray_selected_function_group :
29482948
HelpText<"When using -fxray-function-groups, select which group of functions to instrument. Valid range is 0 to fxray-function-groups - 1">,
29492949
MarshallingInfoInt<CodeGenOpts<"XRaySelectedFunctionGroup">, "0">;
29502950

2951+
defm xray_shared : BoolFOption<"xray-shared",
2952+
CodeGenOpts<"XRayShared">, DefaultFalse,
2953+
PosFlag<SetTrue, [], [ClangOption, CC1Option],
2954+
"Enable shared library instrumentation with XRay">,
2955+
NegFlag<SetFalse>>;
29512956

29522957
defm fine_grained_bitfield_accesses : BoolOption<"f", "fine-grained-bitfield-accesses",
29532958
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 XRayShared = 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 && XRayShared;
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
@@ -1623,10 +1623,14 @@ bool tools::addSanitizerRuntimes(const ToolChain &TC, const ArgList &Args,
16231623
}
16241624

16251625
bool tools::addXRayRuntime(const ToolChain&TC, const ArgList &Args, ArgStringList &CmdArgs) {
1626-
if (Args.hasArg(options::OPT_shared))
1627-
return false;
1628-
1629-
if (TC.getXRayArgs().needsXRayRt()) {
1626+
if (Args.hasArg(options::OPT_shared)) {
1627+
if (TC.getXRayArgs().needsXRayDSORt()) {
1628+
CmdArgs.push_back("--whole-archive");
1629+
CmdArgs.push_back(TC.getCompilerRTArgString(Args, "xray-dso"));
1630+
CmdArgs.push_back("--no-whole-archive");
1631+
return true;
1632+
}
1633+
} else if (TC.getXRayArgs().needsXRayRt()) {
16301634
CmdArgs.push_back("--whole-archive");
16311635
CmdArgs.push_back(TC.getCompilerRTArgString(Args, "xray"));
16321636
for (const auto &Mode : TC.getXRayArgs().modeList())

clang/lib/Driver/XRayArgs.cpp

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

66+
if (Args.hasFlag(options::OPT_fxray_shared,
67+
options::OPT_fno_xray_shared, false)) {
68+
XRayShared = true;
69+
70+
// DSO instrumentation is currently limited to x86_64
71+
if (Triple.getArch() != llvm::Triple::x86_64) {
72+
D.Diag(diag::err_drv_unsupported_opt_for_target)
73+
<< "-fxray-shared" << Triple.str();
74+
}
75+
76+
unsigned PICLvl = std::get<1>(tools::ParsePICArgs(TC, Args));
77+
if (!PICLvl) {
78+
D.Diag(diag::err_opt_not_valid_without_opt)
79+
<< "-fxray-shared" << "-fPIC";
80+
}
81+
}
82+
6683
// Both XRay and -fpatchable-function-entry use
6784
// TargetOpcode::PATCHABLE_FUNCTION_ENTER.
6885
if (Arg *A = Args.getLastArg(options::OPT_fpatchable_function_entry_EQ))
@@ -177,6 +194,10 @@ void XRayArgs::addArgs(const ToolChain &TC, const ArgList &Args,
177194
Args.addOptOutFlag(CmdArgs, options::OPT_fxray_function_index,
178195
options::OPT_fno_xray_function_index);
179196

197+
if (XRayShared)
198+
Args.addOptInFlag(CmdArgs, options::OPT_fxray_shared,
199+
options::OPT_fno_xray_shared);
200+
180201
if (const Arg *A =
181202
Args.getLastArg(options::OPT_fxray_instruction_threshold_EQ)) {
182203
int Value;
Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
// RUN: %clang -### --target=x86_64-unknown-linux-gnu -fPIC -fxray-instrument -fxray-shared -c %s -o /dev/null 2>&1 | FileCheck %s
2+
// RUN: %clang -### --target=x86_64-unknown-linux-gnu -fpic -fxray-instrument -fxray-shared -c %s -o /dev/null 2>&1 | FileCheck %s
3+
// RUN: %clang -### --target=x86_64-unknown-linux-gnu -fxray-instrument -fxray-shared -c %s -o /dev/null 2>&1 | FileCheck %s
4+
// 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
5+
// 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
6+
7+
// On 64 bit darwin, PIC is always enabled
8+
// RUN: %clang -### --target=x86_64-apple-darwin -fxray-instrument -fxray-shared -c %s -o /dev/null 2>&1 | FileCheck %s
9+
10+
// Check unsupported targets
11+
// 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
12+
// 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
13+
14+
// CHECK: "-cc1" {{.*}}"-fxray-instrument" {{.*}}"-fxray-shared"
15+
// ERR-TARGET: error: unsupported option '-fxray-shared' for target
16+
// ERR-PIC: error: option '-fxray-shared' cannot be specified without '-fPIC'
17+

compiler-rt/cmake/Modules/AllSupportedArchDefs.cmake

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -104,6 +104,7 @@ else()
104104
set(ALL_XRAY_SUPPORTED_ARCH ${X86_64} ${ARM32} ${ARM64} ${MIPS32} ${MIPS64}
105105
powerpc64le ${HEXAGON} ${LOONGARCH64})
106106
endif()
107+
set(ALL_XRAY_DSO_SUPPORTED_ARCH ${X86_64})
107108
set(ALL_SHADOWCALLSTACK_SUPPORTED_ARCH ${ARM64})
108109

109110
if (UNIX)

compiler-rt/cmake/config-ix.cmake

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -668,6 +668,9 @@ if(APPLE)
668668
list_intersect(XRAY_SUPPORTED_ARCH
669669
ALL_XRAY_SUPPORTED_ARCH
670670
SANITIZER_COMMON_SUPPORTED_ARCH)
671+
list_intersect(XRAY_DSO_SUPPORTED_ARCH
672+
ALL_XRAY_DSO_SUPPORTED_ARCH
673+
SANITIZER_COMMON_SUPPORTED_ARCH)
671674
list_intersect(SHADOWCALLSTACK_SUPPORTED_ARCH
672675
ALL_SHADOWCALLSTACK_SUPPORTED_ARCH
673676
SANITIZER_COMMON_SUPPORTED_ARCH)
@@ -702,6 +705,7 @@ else()
702705
filter_available_targets(CFI_SUPPORTED_ARCH ${ALL_CFI_SUPPORTED_ARCH})
703706
filter_available_targets(SCUDO_STANDALONE_SUPPORTED_ARCH ${ALL_SCUDO_STANDALONE_SUPPORTED_ARCH})
704707
filter_available_targets(XRAY_SUPPORTED_ARCH ${ALL_XRAY_SUPPORTED_ARCH})
708+
filter_available_targets(XRAY_DSO_SUPPORTED_ARCH ${ALL_XRAY_DSO_SUPPORTED_ARCH})
705709
filter_available_targets(SHADOWCALLSTACK_SUPPORTED_ARCH
706710
${ALL_SHADOWCALLSTACK_SUPPORTED_ARCH})
707711
filter_available_targets(GWP_ASAN_SUPPORTED_ARCH ${ALL_GWP_ASAN_SUPPORTED_ARCH})

compiler-rt/include/xray/xray_interface.h

Lines changed: 49 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -93,31 +93,74 @@ enum XRayPatchingStatus {
9393
FAILED = 3,
9494
};
9595

96-
/// This tells XRay to patch the instrumentation points. See XRayPatchingStatus
96+
/// This tells XRay to patch the instrumentation points in all currently loaded objects. See XRayPatchingStatus
9797
/// for possible result values.
9898
extern XRayPatchingStatus __xray_patch();
9999

100+
/// This tells XRay to patch the instrumentation points in the given object.
101+
/// See XRayPatchingStatus for possible result values.
102+
extern XRayPatchingStatus __xray_patch_object(int32_t ObjId);
103+
100104
/// Reverses the effect of __xray_patch(). See XRayPatchingStatus for possible
101105
/// result values.
102106
extern XRayPatchingStatus __xray_unpatch();
103107

104-
/// This patches a specific function id. See XRayPatchingStatus for possible
108+
/// Reverses the effect of __xray_patch_object. See XRayPatchingStatus for possible
109+
/// result values.
110+
extern XRayPatchingStatus __xray_unpatch_object(int32_t ObjId);
111+
112+
/// This unpacks the given (packed) function id and patches
113+
/// the corresponding function. See XRayPatchingStatus for possible
105114
/// result values.
106115
extern XRayPatchingStatus __xray_patch_function(int32_t FuncId);
107116

108-
/// This unpatches a specific function id. See XRayPatchingStatus for possible
117+
/// This patches a specific function in the given object. See XRayPatchingStatus for possible
118+
/// result values.
119+
extern XRayPatchingStatus __xray_patch_function_in_object(int32_t FuncId,
120+
int32_t ObjId);
121+
122+
/// This unpacks the given (packed) function id and unpatches
123+
/// the corresponding function. See XRayPatchingStatus for possible
109124
/// result values.
110125
extern XRayPatchingStatus __xray_unpatch_function(int32_t FuncId);
111126

112-
/// This function returns the address of the function provided a valid function
113-
/// id. We return 0 if we encounter any error, even if 0 may be a valid function
127+
/// This unpatches a specific function in the given object.
128+
/// See XRayPatchingStatus for possible result values.
129+
extern XRayPatchingStatus __xray_unpatch_function_in_object(int32_t FuncId,
130+
int32_t ObjId);
131+
132+
/// 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
114133
/// address.
115134
extern uintptr_t __xray_function_address(int32_t FuncId);
116135

117-
/// This function returns the maximum valid function id. Returns 0 if we
136+
/// This function returns the address of the function in the given object provided valid function and object
137+
/// ids. We return 0 if we encounter any error, even if 0 may be a valid function
138+
/// address.
139+
extern uintptr_t __xray_function_address_in_object(int32_t FuncId,
140+
int32_t ObjId);
141+
142+
/// This function returns the maximum valid function id for the main executable (object id = 0). Returns 0 if we
118143
/// encounter errors (when there are no instrumented functions, etc.).
119144
extern size_t __xray_max_function_id();
120145

146+
/// This function returns the maximum valid function id for the given object. Returns 0 if we
147+
/// encounter errors (when there are no instrumented functions, etc.).
148+
extern size_t __xray_max_function_id_in_object(int32_t ObjId);
149+
150+
/// This function returns the number of previously registered objects (executable + loaded DSOs).
151+
/// Returns 0 if XRay has not been initialized.
152+
extern size_t __xray_num_objects();
153+
154+
/// Unpacks the function id from the given packed id.
155+
extern int32_t __xray_unpack_function_id(int32_t PackedId);
156+
157+
/// Unpacks the object id from the given packed id.
158+
extern int32_t __xray_unpack_object_id(int32_t PackedId);
159+
160+
/// Creates and returns a packed id from the given function and object ids.
161+
/// If the ids do not fit within the reserved number of bits for each part, the high bits are truncated.
162+
extern int32_t __xray_pack_id(int32_t FuncId, int32_t ObjId);
163+
121164
/// Initialize the required XRay data structures. This is useful in cases where
122165
/// users want to control precisely when the XRay instrumentation data
123166
/// structures are initialized, for example when the XRay library is built with

compiler-rt/lib/xray/CMakeLists.txt

Lines changed: 76 additions & 10 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}
@@ -346,16 +391,37 @@ else() # not Apple
346391
DEFS ${XRAY_COMMON_DEFINITIONS}
347392
OBJECT_LIBS RTXrayBASIC
348393
PARENT_TARGET xray)
349-
# Profiler Mode runtime
350-
add_compiler_rt_runtime(clang_rt.xray-profiling
351-
STATIC
352-
ARCHS ${arch}
353-
CFLAGS ${XRAY_CFLAGS}
354-
LINK_FLAGS ${XRAY_LINK_FLAGS}
355-
LINK_LIBS ${XRAY_LINK_LIBS}
356-
DEFS ${XRAY_COMMON_DEFINITIONS}
357-
OBJECT_LIBS RTXrayPROFILING
358-
PARENT_TARGET xray)
394+
# Profiler Mode runtime
395+
add_compiler_rt_runtime(clang_rt.xray-profiling
396+
STATIC
397+
ARCHS ${arch}
398+
CFLAGS ${XRAY_CFLAGS}
399+
LINK_FLAGS ${XRAY_LINK_FLAGS}
400+
LINK_LIBS ${XRAY_LINK_LIBS}
401+
DEFS ${XRAY_COMMON_DEFINITIONS}
402+
OBJECT_LIBS RTXrayPROFILING
403+
PARENT_TARGET xray)
404+
405+
if (${arch} IN_LIST XRAY_DSO_SUPPORTED_ARCH)
406+
# TODO: Only implemented for X86 at the moment
407+
add_compiler_rt_object_libraries(RTXrayDSO
408+
ARCHS ${arch}
409+
SOURCES ${XRAY_DSO_SOURCES} ${${arch}_DSO_SOURCES}
410+
ADDITIONAL_HEADERS ${XRAY_IMPL_HEADERS}
411+
CFLAGS ${XRAY_CFLAGS}
412+
DEFS ${XRAY_COMMON_DEFINITIONS_DSO}
413+
DEPS ${XRAY_DEPS})
414+
# DSO runtime archive
415+
add_compiler_rt_runtime(clang_rt.xray-dso
416+
STATIC
417+
ARCHS ${arch}
418+
CFLAGS ${XRAY_CFLAGS}
419+
LINK_FLAGS ${XRAY_LINK_FLAGS}
420+
LINK_LIBS ${XRAY_LINK_LIBS}
421+
DEFS ${XRAY_COMMON_DEFINITIONS}
422+
OBJECT_LIBS RTXrayDSO
423+
PARENT_TARGET xray)
424+
endif()
359425
endforeach()
360426
endif() # not Apple
361427

0 commit comments

Comments
 (0)