Skip to content

Commit ca3180a

Browse files
authored
[LLVM][rtsan] Add module pass to initialize rtsan (#118989)
This allows shared libraries instrumented with RTSan to be initialized. This approach directly mirrors the approach in Tsan, Asan and many of the other sanitizers
1 parent 3c83054 commit ca3180a

File tree

5 files changed

+34
-2
lines changed

5 files changed

+34
-2
lines changed

clang/lib/CodeGen/BackendUtil.cpp

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1024,12 +1024,14 @@ void EmitAssemblyHelper::RunOptimizationPipeline(
10241024
FPM.addPass(BoundsCheckingPass());
10251025
});
10261026

1027-
if (LangOpts.Sanitize.has(SanitizerKind::Realtime))
1027+
if (LangOpts.Sanitize.has(SanitizerKind::Realtime)) {
10281028
PB.registerScalarOptimizerLateEPCallback(
10291029
[](FunctionPassManager &FPM, OptimizationLevel Level) {
10301030
RealtimeSanitizerOptions Opts;
10311031
FPM.addPass(RealtimeSanitizerPass(Opts));
10321032
});
1033+
MPM.addPass(ModuleRealtimeSanitizerPass());
1034+
}
10331035

10341036
// Don't add sanitizers if we are here from ThinLTO PostLink. That already
10351037
// done on PreLink stage.

llvm/include/llvm/Transforms/Instrumentation/RealtimeSanitizer.h

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,13 @@ class RealtimeSanitizerPass : public PassInfoMixin<RealtimeSanitizerPass> {
3333
static bool isRequired() { return true; }
3434
};
3535

36+
/// Create ctor and init functions.
37+
struct ModuleRealtimeSanitizerPass
38+
: public PassInfoMixin<ModuleRealtimeSanitizerPass> {
39+
PreservedAnalyses run(Module &M, ModuleAnalysisManager &AM);
40+
static bool isRequired() { return true; }
41+
};
42+
3643
} // namespace llvm
3744

3845
#endif // LLVM_TRANSFORMS_INSTRUMENTATION_REALTIMESANITIZER_H

llvm/lib/Passes/PassRegistry.def

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -138,6 +138,7 @@ MODULE_PASS("rel-lookup-table-converter", RelLookupTableConverterPass())
138138
MODULE_PASS("rewrite-statepoints-for-gc", RewriteStatepointsForGC())
139139
MODULE_PASS("rewrite-symbols", RewriteSymbolPass())
140140
MODULE_PASS("rpo-function-attrs", ReversePostOrderFunctionAttrsPass())
141+
MODULE_PASS("rtsan-module", ModuleRealtimeSanitizerPass())
141142
MODULE_PASS("sample-profile", SampleProfileLoaderPass())
142143
MODULE_PASS("sancov-module", SanitizerCoveragePass())
143144
MODULE_PASS("sanmd-module", SanitizerBinaryMetadataPass())

llvm/lib/Transforms/Instrumentation/RealtimeSanitizer.cpp

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,12 +17,16 @@
1717
#include "llvm/IR/IRBuilder.h"
1818
#include "llvm/IR/InstIterator.h"
1919
#include "llvm/IR/Module.h"
20+
#include "llvm/Transforms/Utils/ModuleUtils.h"
2021

2122
#include "llvm/Demangle/Demangle.h"
2223
#include "llvm/Transforms/Instrumentation/RealtimeSanitizer.h"
2324

2425
using namespace llvm;
2526

27+
const char kRtsanModuleCtorName[] = "rtsan.module_ctor";
28+
const char kRtsanInitName[] = "__rtsan_ensure_initialized";
29+
2630
static SmallVector<Type *> getArgTypes(ArrayRef<Value *> FunctionArgs) {
2731
SmallVector<Type *> Types;
2832
for (Value *Arg : FunctionArgs)
@@ -89,3 +93,14 @@ PreservedAnalyses RealtimeSanitizerPass::run(Function &Fn,
8993

9094
return PreservedAnalyses::all();
9195
}
96+
97+
PreservedAnalyses ModuleRealtimeSanitizerPass::run(Module &M,
98+
ModuleAnalysisManager &MAM) {
99+
getOrCreateSanitizerCtorAndInitFunctions(
100+
M, kRtsanModuleCtorName, kRtsanInitName, /*InitArgTypes=*/{},
101+
/*InitArgs=*/{},
102+
// This callback is invoked when the functions are created the first
103+
// time. Hook them into the global ctors list in that case:
104+
[&](Function *Ctor, FunctionCallee) { appendToGlobalCtors(M, Ctor, 0); });
105+
return PreservedAnalyses::none();
106+
}

llvm/test/Instrumentation/RealtimeSanitizer/rtsan.ll

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
; RUN: opt < %s -passes=rtsan -S | FileCheck %s
1+
; RUN: opt < %s -passes='function(rtsan),module(rtsan-module)' -S | FileCheck %s
22

33
define void @violation() #0 {
44
%1 = alloca ptr, align 8
@@ -18,10 +18,17 @@ define noundef i32 @main() #2 {
1818

1919
attributes #0 = { mustprogress noinline sanitize_realtime optnone ssp uwtable(sync) }
2020

21+
; RealtimeSanitizer pass should insert call to initialize the runtime
22+
; CHECK: @llvm.used = appending global [1 x ptr] [ptr @rtsan.module_ctor]
23+
; CHECK: @llvm.global_ctors = {{.*}}@rtsan.module_ctor
24+
2125
; RealtimeSanitizer pass should insert __rtsan_realtime_enter right after function definition
2226
; CHECK-LABEL: @violation()
2327
; CHECK-NEXT: call{{.*}}@__rtsan_realtime_enter
2428

2529
; RealtimeSanitizer pass should insert __rtsan_realtime_exit right before function return
2630
; CHECK: call{{.*}}@__rtsan_realtime_exit
2731
; CHECK-NEXT: ret{{.*}}void
32+
33+
; CHECK-LABEL: define internal void @rtsan.module_ctor()
34+
; CHECK-NEXT: call void @__rtsan_ensure_initialized()

0 commit comments

Comments
 (0)