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() _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits