[clang] ca3180a - [LLVM][rtsan] Add module pass to initialize rtsan (#118989)
via cfe-commits
cfe-commits at lists.llvm.org
Fri Dec 6 11:29:16 PST 2024
Author: Chris Apple
Date: 2024-12-06T11:29:11-08:00
New Revision: ca3180ad6e39304177deac112bd78739d85fe32b
URL: https://github.com/llvm/llvm-project/commit/ca3180ad6e39304177deac112bd78739d85fe32b
DIFF: https://github.com/llvm/llvm-project/commit/ca3180ad6e39304177deac112bd78739d85fe32b.diff
LOG: [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
Added:
Modified:
clang/lib/CodeGen/BackendUtil.cpp
llvm/include/llvm/Transforms/Instrumentation/RealtimeSanitizer.h
llvm/lib/Passes/PassRegistry.def
llvm/lib/Transforms/Instrumentation/RealtimeSanitizer.cpp
llvm/test/Instrumentation/RealtimeSanitizer/rtsan.ll
Removed:
################################################################################
diff --git a/clang/lib/CodeGen/BackendUtil.cpp b/clang/lib/CodeGen/BackendUtil.cpp
index bf9b04f02e9f44..fbb3fb6e5ea423 100644
--- a/clang/lib/CodeGen/BackendUtil.cpp
+++ b/clang/lib/CodeGen/BackendUtil.cpp
@@ -1024,12 +1024,14 @@ void EmitAssemblyHelper::RunOptimizationPipeline(
FPM.addPass(BoundsCheckingPass());
});
- if (LangOpts.Sanitize.has(SanitizerKind::Realtime))
+ if (LangOpts.Sanitize.has(SanitizerKind::Realtime)) {
PB.registerScalarOptimizerLateEPCallback(
[](FunctionPassManager &FPM, OptimizationLevel Level) {
RealtimeSanitizerOptions Opts;
FPM.addPass(RealtimeSanitizerPass(Opts));
});
+ MPM.addPass(ModuleRealtimeSanitizerPass());
+ }
// Don't add sanitizers if we are here from ThinLTO PostLink. That already
// done on PreLink stage.
diff --git a/llvm/include/llvm/Transforms/Instrumentation/RealtimeSanitizer.h b/llvm/include/llvm/Transforms/Instrumentation/RealtimeSanitizer.h
index f2ce1636551ce2..151e70e87b294d 100644
--- a/llvm/include/llvm/Transforms/Instrumentation/RealtimeSanitizer.h
+++ b/llvm/include/llvm/Transforms/Instrumentation/RealtimeSanitizer.h
@@ -33,6 +33,13 @@ class RealtimeSanitizerPass : public PassInfoMixin<RealtimeSanitizerPass> {
static bool isRequired() { return true; }
};
+/// Create ctor and init functions.
+struct ModuleRealtimeSanitizerPass
+ : public PassInfoMixin<ModuleRealtimeSanitizerPass> {
+ PreservedAnalyses run(Module &M, ModuleAnalysisManager &AM);
+ static bool isRequired() { return true; }
+};
+
} // namespace llvm
#endif // LLVM_TRANSFORMS_INSTRUMENTATION_REALTIMESANITIZER_H
diff --git a/llvm/lib/Passes/PassRegistry.def b/llvm/lib/Passes/PassRegistry.def
index 772ec5fd10e633..2ddebb07017c2a 100644
--- a/llvm/lib/Passes/PassRegistry.def
+++ b/llvm/lib/Passes/PassRegistry.def
@@ -138,6 +138,7 @@ MODULE_PASS("rel-lookup-table-converter", RelLookupTableConverterPass())
MODULE_PASS("rewrite-statepoints-for-gc", RewriteStatepointsForGC())
MODULE_PASS("rewrite-symbols", RewriteSymbolPass())
MODULE_PASS("rpo-function-attrs", ReversePostOrderFunctionAttrsPass())
+MODULE_PASS("rtsan-module", ModuleRealtimeSanitizerPass())
MODULE_PASS("sample-profile", SampleProfileLoaderPass())
MODULE_PASS("sancov-module", SanitizerCoveragePass())
MODULE_PASS("sanmd-module", SanitizerBinaryMetadataPass())
diff --git a/llvm/lib/Transforms/Instrumentation/RealtimeSanitizer.cpp b/llvm/lib/Transforms/Instrumentation/RealtimeSanitizer.cpp
index 88cb04695217d5..890c79ae96718a 100644
--- a/llvm/lib/Transforms/Instrumentation/RealtimeSanitizer.cpp
+++ b/llvm/lib/Transforms/Instrumentation/RealtimeSanitizer.cpp
@@ -17,12 +17,16 @@
#include "llvm/IR/IRBuilder.h"
#include "llvm/IR/InstIterator.h"
#include "llvm/IR/Module.h"
+#include "llvm/Transforms/Utils/ModuleUtils.h"
#include "llvm/Demangle/Demangle.h"
#include "llvm/Transforms/Instrumentation/RealtimeSanitizer.h"
using namespace llvm;
+const char kRtsanModuleCtorName[] = "rtsan.module_ctor";
+const char kRtsanInitName[] = "__rtsan_ensure_initialized";
+
static SmallVector<Type *> getArgTypes(ArrayRef<Value *> FunctionArgs) {
SmallVector<Type *> Types;
for (Value *Arg : FunctionArgs)
@@ -89,3 +93,14 @@ PreservedAnalyses RealtimeSanitizerPass::run(Function &Fn,
return PreservedAnalyses::all();
}
+
+PreservedAnalyses ModuleRealtimeSanitizerPass::run(Module &M,
+ ModuleAnalysisManager &MAM) {
+ getOrCreateSanitizerCtorAndInitFunctions(
+ M, kRtsanModuleCtorName, kRtsanInitName, /*InitArgTypes=*/{},
+ /*InitArgs=*/{},
+ // This callback is invoked when the functions are created the first
+ // time. Hook them into the global ctors list in that case:
+ [&](Function *Ctor, FunctionCallee) { appendToGlobalCtors(M, Ctor, 0); });
+ return PreservedAnalyses::none();
+}
diff --git a/llvm/test/Instrumentation/RealtimeSanitizer/rtsan.ll b/llvm/test/Instrumentation/RealtimeSanitizer/rtsan.ll
index a0bc4aef2cc319..c245a85a9a4856 100644
--- a/llvm/test/Instrumentation/RealtimeSanitizer/rtsan.ll
+++ b/llvm/test/Instrumentation/RealtimeSanitizer/rtsan.ll
@@ -1,4 +1,4 @@
-; RUN: opt < %s -passes=rtsan -S | FileCheck %s
+; RUN: opt < %s -passes='function(rtsan),module(rtsan-module)' -S | FileCheck %s
define void @violation() #0 {
%1 = alloca ptr, align 8
@@ -18,6 +18,10 @@ define noundef i32 @main() #2 {
attributes #0 = { mustprogress noinline sanitize_realtime optnone ssp uwtable(sync) }
+; RealtimeSanitizer pass should insert call to initialize the runtime
+; CHECK: @llvm.used = appending global [1 x ptr] [ptr @rtsan.module_ctor]
+; CHECK: @llvm.global_ctors = {{.*}}@rtsan.module_ctor
+
; RealtimeSanitizer pass should insert __rtsan_realtime_enter right after function definition
; CHECK-LABEL: @violation()
; CHECK-NEXT: call{{.*}}@__rtsan_realtime_enter
@@ -25,3 +29,6 @@ attributes #0 = { mustprogress noinline sanitize_realtime optnone ssp uwtable(sy
; RealtimeSanitizer pass should insert __rtsan_realtime_exit right before function return
; CHECK: call{{.*}}@__rtsan_realtime_exit
; CHECK-NEXT: ret{{.*}}void
+
+; CHECK-LABEL: define internal void @rtsan.module_ctor()
+; CHECK-NEXT: call void @__rtsan_ensure_initialized()
More information about the cfe-commits
mailing list