[llvm] 8acf885 - [LLVM][rtsan] Add RealtimeSanitizer transform pass (#101232)
via llvm-commits
llvm-commits at lists.llvm.org
Thu Aug 8 16:32:57 PDT 2024
Author: Chris Apple
Date: 2024-08-08T16:32:54-07:00
New Revision: 8acf8852e9d4044456a782ff0089a4becfa2df86
URL: https://github.com/llvm/llvm-project/commit/8acf8852e9d4044456a782ff0089a4becfa2df86
DIFF: https://github.com/llvm/llvm-project/commit/8acf8852e9d4044456a782ff0089a4becfa2df86.diff
LOG: [LLVM][rtsan] Add RealtimeSanitizer transform pass (#101232)
Split from #100596.
Introduce the RealtimeSanitizer transform, which inserts the
rtsan_enter/exit functions at the appropriate places in an instrumented
function.
Added:
llvm/include/llvm/Transforms/Instrumentation/RealtimeSanitizer.h
llvm/lib/Transforms/Instrumentation/RealtimeSanitizer.cpp
llvm/test/Instrumentation/RealtimeSanitizer/rtsan.ll
llvm/test/Instrumentation/RealtimeSanitizer/rtsan_multi_return.ll
Modified:
llvm/lib/Passes/PassBuilder.cpp
llvm/lib/Passes/PassRegistry.def
llvm/lib/Transforms/Instrumentation/CMakeLists.txt
Removed:
################################################################################
diff --git a/llvm/include/llvm/Transforms/Instrumentation/RealtimeSanitizer.h b/llvm/include/llvm/Transforms/Instrumentation/RealtimeSanitizer.h
new file mode 100644
index 00000000000000..b141ad27996b7b
--- /dev/null
+++ b/llvm/include/llvm/Transforms/Instrumentation/RealtimeSanitizer.h
@@ -0,0 +1,41 @@
+//===- RealtimeSanitizer.h - RealtimeSanitizer instrumentation --*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+//
+// This file is a part of the RealtimeSanitizer, an LLVM transformation for
+// detecting and reporting realtime safety violations.
+//
+// The instrumentation pass inserts calls to __rtsan_realtime_enter and
+// __rtsan_realtime_exit at the entry and exit points of functions that are
+// marked with the appropriate attribute.
+//
+// See also: llvm-project/compiler-rt/lib/rtsan/
+//
+//===----------------------------------------------------------------------===//
+#ifndef LLVM_TRANSFORMS_INSTRUMENTATION_REALTIMESANITIZER_H
+#define LLVM_TRANSFORMS_INSTRUMENTATION_REALTIMESANITIZER_H
+
+#include "llvm/IR/PassManager.h"
+
+namespace llvm {
+
+struct RealtimeSanitizerOptions {};
+
+class RealtimeSanitizerPass : public PassInfoMixin<RealtimeSanitizerPass> {
+public:
+ RealtimeSanitizerPass(const RealtimeSanitizerOptions &Options);
+ PreservedAnalyses run(Function &F, AnalysisManager<Function> &AM);
+
+ static bool isRequired() { return true; }
+
+private:
+ RealtimeSanitizerOptions Options{};
+};
+
+} // namespace llvm
+
+#endif // LLVM_TRANSFORMS_INSTRUMENTATION_REALTIMESANITIZER_H
diff --git a/llvm/lib/Passes/PassBuilder.cpp b/llvm/lib/Passes/PassBuilder.cpp
index bcc69d5ac3db67..7bc1c870ce5191 100644
--- a/llvm/lib/Passes/PassBuilder.cpp
+++ b/llvm/lib/Passes/PassBuilder.cpp
@@ -199,6 +199,7 @@
#include "llvm/Transforms/Instrumentation/PGOForceFunctionAttrs.h"
#include "llvm/Transforms/Instrumentation/PGOInstrumentation.h"
#include "llvm/Transforms/Instrumentation/PoisonChecking.h"
+#include "llvm/Transforms/Instrumentation/RealtimeSanitizer.h"
#include "llvm/Transforms/Instrumentation/SanitizerBinaryMetadata.h"
#include "llvm/Transforms/Instrumentation/SanitizerCoverage.h"
#include "llvm/Transforms/Instrumentation/ThreadSanitizer.h"
@@ -1210,6 +1211,11 @@ parseRegAllocFastPassOptions(PassBuilder &PB, StringRef Params) {
return Opts;
}
+Expected<RealtimeSanitizerOptions> parseRtSanPassOptions(StringRef Params) {
+ RealtimeSanitizerOptions Result;
+ return Result;
+}
+
} // namespace
/// Tests whether a pass name starts with a valid prefix for a default pipeline
diff --git a/llvm/lib/Passes/PassRegistry.def b/llvm/lib/Passes/PassRegistry.def
index 61a5bab92927fe..95842d15a35bf6 100644
--- a/llvm/lib/Passes/PassRegistry.def
+++ b/llvm/lib/Passes/PassRegistry.def
@@ -592,6 +592,10 @@ FUNCTION_PASS_WITH_PARAMS(
return WinEHPreparePass(DemoteCatchSwitchPHIOnly);
},
parseWinEHPrepareOptions, "demote-catchswitch-only")
+FUNCTION_PASS_WITH_PARAMS(
+ "rtsan", "RealtimeSanitizerPass",
+ [](RealtimeSanitizerOptions Opts) { return RealtimeSanitizerPass(Opts); },
+ parseRtSanPassOptions, "")
#undef FUNCTION_PASS_WITH_PARAMS
#ifndef LOOPNEST_PASS
diff --git a/llvm/lib/Transforms/Instrumentation/CMakeLists.txt b/llvm/lib/Transforms/Instrumentation/CMakeLists.txt
index 4e3f9e27e0c344..deab37801ff1df 100644
--- a/llvm/lib/Transforms/Instrumentation/CMakeLists.txt
+++ b/llvm/lib/Transforms/Instrumentation/CMakeLists.txt
@@ -25,6 +25,7 @@ add_llvm_component_library(LLVMInstrumentation
ValueProfileCollector.cpp
ThreadSanitizer.cpp
HWAddressSanitizer.cpp
+ RealtimeSanitizer.cpp
ADDITIONAL_HEADER_DIRS
${LLVM_MAIN_INCLUDE_DIR}/llvm/Transforms
diff --git a/llvm/lib/Transforms/Instrumentation/RealtimeSanitizer.cpp b/llvm/lib/Transforms/Instrumentation/RealtimeSanitizer.cpp
new file mode 100644
index 00000000000000..d3028ee97c3eb8
--- /dev/null
+++ b/llvm/lib/Transforms/Instrumentation/RealtimeSanitizer.cpp
@@ -0,0 +1,61 @@
+//===- RealtimeSanitizer.cpp - RealtimeSanitizer instrumentation *- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+//
+// This file is a part of the RealtimeSanitizer, an LLVM transformation for
+// detecting and reporting realtime safety violations.
+//
+// See also: llvm-project/compiler-rt/lib/rtsan/
+//
+//===----------------------------------------------------------------------===//
+
+#include "llvm/IR/Analysis.h"
+#include "llvm/IR/IRBuilder.h"
+#include "llvm/IR/Module.h"
+
+#include "llvm/Transforms/Instrumentation/RealtimeSanitizer.h"
+
+using namespace llvm;
+
+static void insertCallBeforeInstruction(Function &Fn, Instruction &Instruction,
+ const char *FunctionName) {
+ LLVMContext &Context = Fn.getContext();
+ FunctionType *FuncType = FunctionType::get(Type::getVoidTy(Context), false);
+ FunctionCallee Func =
+ Fn.getParent()->getOrInsertFunction(FunctionName, FuncType);
+ IRBuilder<> Builder{&Instruction};
+ Builder.CreateCall(Func, {});
+}
+
+static void insertCallAtFunctionEntryPoint(Function &Fn,
+ const char *InsertFnName) {
+
+ insertCallBeforeInstruction(Fn, Fn.front().front(), InsertFnName);
+}
+
+static void insertCallAtAllFunctionExitPoints(Function &Fn,
+ const char *InsertFnName) {
+ for (auto &BB : Fn)
+ for (auto &I : BB)
+ if (auto *RI = dyn_cast<ReturnInst>(&I))
+ insertCallBeforeInstruction(Fn, I, InsertFnName);
+}
+
+RealtimeSanitizerPass::RealtimeSanitizerPass(
+ const RealtimeSanitizerOptions &Options)
+ : Options{Options} {}
+
+PreservedAnalyses RealtimeSanitizerPass::run(Function &F,
+ AnalysisManager<Function> &AM) {
+ if (F.hasFnAttribute(Attribute::SanitizeRealtime)) {
+ insertCallAtFunctionEntryPoint(F, "__rtsan_realtime_enter");
+ insertCallAtAllFunctionExitPoints(F, "__rtsan_realtime_exit");
+ return PreservedAnalyses::none();
+ }
+
+ return PreservedAnalyses::all();
+}
diff --git a/llvm/test/Instrumentation/RealtimeSanitizer/rtsan.ll b/llvm/test/Instrumentation/RealtimeSanitizer/rtsan.ll
new file mode 100644
index 00000000000000..a0bc4aef2cc319
--- /dev/null
+++ b/llvm/test/Instrumentation/RealtimeSanitizer/rtsan.ll
@@ -0,0 +1,27 @@
+; RUN: opt < %s -passes=rtsan -S | FileCheck %s
+
+define void @violation() #0 {
+ %1 = alloca ptr, align 8
+ %2 = call ptr @malloc(i64 noundef 2) #3
+ store ptr %2, ptr %1, align 8
+ ret void
+}
+
+declare ptr @malloc(i64 noundef) #1
+
+define noundef i32 @main() #2 {
+ %1 = alloca i32, align 4
+ store i32 0, ptr %1, align 4
+ call void @violation() #4
+ ret i32 0
+}
+
+attributes #0 = { mustprogress noinline sanitize_realtime optnone ssp uwtable(sync) }
+
+; RealtimeSanitizer pass should insert __rtsan_realtime_enter right after function definition
+; CHECK-LABEL: @violation()
+; CHECK-NEXT: call{{.*}}@__rtsan_realtime_enter
+
+; RealtimeSanitizer pass should insert __rtsan_realtime_exit right before function return
+; CHECK: call{{.*}}@__rtsan_realtime_exit
+; CHECK-NEXT: ret{{.*}}void
diff --git a/llvm/test/Instrumentation/RealtimeSanitizer/rtsan_multi_return.ll b/llvm/test/Instrumentation/RealtimeSanitizer/rtsan_multi_return.ll
new file mode 100644
index 00000000000000..39a1ff0b7c442a
--- /dev/null
+++ b/llvm/test/Instrumentation/RealtimeSanitizer/rtsan_multi_return.ll
@@ -0,0 +1,30 @@
+; RUN: opt < %s -passes=rtsan -S | FileCheck %s
+
+define i32 @example(i32 %x) #0 {
+entry:
+ %retval = alloca i32
+ %cmp = icmp sgt i32 %x, 10
+ br i1 %cmp, label %then, label %else
+
+then:
+ ret i32 1
+
+else:
+ ret i32 0
+}
+
+attributes #0 = { mustprogress noinline sanitize_realtime optnone ssp uwtable(sync) }
+
+; RealtimeSanitizer pass should insert __rtsan_realtime_enter right after function definition
+; CHECK-LABEL: @example(
+; CHECK-NEXT: entry:
+; CHECK-NEXT: call{{.*}}@__rtsan_realtime_enter
+
+; RealtimeSanitizer pass should insert the call at both function returns
+; CHECK-LABEL: then:
+; CHECK-NEXT: call{{.*}}@__rtsan_realtime_exit
+; CHECK-NEXT: ret i32 1
+
+; CHECK-LABEL: else:
+; CHECK-NEXT: call{{.*}}@__rtsan_realtime_exit
+; CHECK-NEXT: ret i32 0
More information about the llvm-commits
mailing list