[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