-
Notifications
You must be signed in to change notification settings - Fork 11.6k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Rtsan/blocking 2 llvm pass #109543
base: main
Are you sure you want to change the base?
Rtsan/blocking 2 llvm pass #109543
Conversation
@llvm/pr-subscribers-llvm-transforms @llvm/pr-subscribers-compiler-rt-sanitizer Author: None (davidtrevelyan) ChangesPass update for sanitize_realtime_unsafeFollows #106754 MotivationCalls to system library functions such as malloc are easy for RealtimeSanitizer to intercept. If such a call is made in a At the same time as introducing ImplementationWe recently merged the
Once the feature is switched on, RealtimeSanitizer will error if any calls to functions attributed with Integration RoadmapThe above functionality is currently split into three patches.
Full diff: https://github.com/llvm/llvm-project/pull/109543.diff 2 Files Affected:
diff --git a/llvm/lib/Transforms/Instrumentation/RealtimeSanitizer.cpp b/llvm/lib/Transforms/Instrumentation/RealtimeSanitizer.cpp
index 7854cf4f2c625f..f27cf83cd3cf3d 100644
--- a/llvm/lib/Transforms/Instrumentation/RealtimeSanitizer.cpp
+++ b/llvm/lib/Transforms/Instrumentation/RealtimeSanitizer.cpp
@@ -17,6 +17,7 @@
#include "llvm/IR/IRBuilder.h"
#include "llvm/IR/Module.h"
+#include "llvm/Demangle/Demangle.h"
#include "llvm/Transforms/Instrumentation/RealtimeSanitizer.h"
using namespace llvm;
@@ -45,6 +46,26 @@ static void insertCallAtAllFunctionExitPoints(Function &Fn,
insertCallBeforeInstruction(Fn, I, InsertFnName);
}
+static PreservedAnalyses rtsanPreservedCFGAnalyses() {
+ PreservedAnalyses PA;
+ PA.preserveSet<CFGAnalyses>();
+ return PA;
+}
+
+static void insertNotifyBlockingCallAtFunctionEntryPoint(Function &F) {
+ IRBuilder<> Builder(&F.front().front());
+ Value *NameArg = Builder.CreateGlobalString(demangle(F.getName()));
+
+ FunctionType *FuncType =
+ FunctionType::get(Type::getVoidTy(F.getContext()),
+ {PointerType::getUnqual(F.getContext())}, false);
+
+ FunctionCallee Func = F.getParent()->getOrInsertFunction(
+ "__rtsan_notify_blocking_call", FuncType);
+
+ Builder.CreateCall(Func, {NameArg});
+}
+
RealtimeSanitizerPass::RealtimeSanitizerPass(
const RealtimeSanitizerOptions &Options) {}
@@ -53,10 +74,12 @@ PreservedAnalyses RealtimeSanitizerPass::run(Function &F,
if (F.hasFnAttribute(Attribute::SanitizeRealtime)) {
insertCallAtFunctionEntryPoint(F, "__rtsan_realtime_enter");
insertCallAtAllFunctionExitPoints(F, "__rtsan_realtime_exit");
+ return rtsanPreservedCFGAnalyses();
+ }
- PreservedAnalyses PA;
- PA.preserveSet<CFGAnalyses>();
- return PA;
+ if (F.hasFnAttribute(Attribute::SanitizeRealtimeUnsafe)) {
+ insertNotifyBlockingCallAtFunctionEntryPoint(F);
+ return rtsanPreservedCFGAnalyses();
}
return PreservedAnalyses::all();
diff --git a/llvm/test/Instrumentation/RealtimeSanitizer/rtsan_unsafe.ll b/llvm/test/Instrumentation/RealtimeSanitizer/rtsan_unsafe.ll
new file mode 100644
index 00000000000000..fe9f13778e35af
--- /dev/null
+++ b/llvm/test/Instrumentation/RealtimeSanitizer/rtsan_unsafe.ll
@@ -0,0 +1,19 @@
+; RUN: opt < %s -passes=rtsan -S | FileCheck %s
+
+define void @_Z17blocking_functionv() #0 {
+ ret void
+}
+
+define noundef i32 @main() #2 {
+ call void @_Z17blocking_functionv() #4
+ ret i32 0
+}
+
+attributes #0 = { mustprogress noinline sanitize_realtime_unsafe optnone ssp uwtable(sync) }
+
+; RealtimeSanitizer pass should create the demangled function name as a global string, and
+; pass it as input to an inserted __rtsan_expect_not_realtime call at the function entrypoint
+; CHECK: [[GLOBAL_STR:@[a-zA-Z0-9\.]+]]
+; CHECK-SAME: c"blocking_function()\00"
+; CHECK-LABEL: @_Z17blocking_functionv()
+; CHECK-NEXT: call{{.*}}@__rtsan_notify_blocking_call(ptr{{.*}}[[GLOBAL_STR]])
|
@cjappl for review |
Pass update for sanitize_realtime_unsafe
Follows #106754
Motivation
Calls to system library functions such as malloc are easy for RealtimeSanitizer to intercept. If such a call is made in a
[[clang::nonblocking]]
function (a real-time context), RealtimeSanitizer will error. Real-time programmers also write their own blocking (real-time unsafe) functions that may or may not call intercepted functions. We wish to introduce a mechanism whereby RealtimeSanitizer can error on calls to these, too, if called within a real-time context.At the same time as introducing
[[clang::nonblocking]]
, the[[clang::blocking]]
attribute was also introduced. With the function effects warnings (as errors) activated, blocking functions cannot be called from non-blocking functions, and this is enforced at compile time. The purpose of this series of PRs is to introduce similar functionality into RealtimeSanitizer, so that it can make the equivalent check at run time.Implementation
We recently merged the
sanitize_realtime_unsafe
LLVM function attribute intomain
. Our next steps are to:sanitize_realtime_unsafe
is detected, update RealtimeSanitizer's LLVM pass to insert a call to__rtsan_notify_blocking_call
, andsanitize_realtime_unsafe
attribute to the IR for functions attributed with[[clang::blocking]]
.Once the feature is switched on, RealtimeSanitizer will error if any calls to functions attributed with
[[clang::blocking]]
are made from[[clang::nonblocking]]
functions.Integration Roadmap
The above functionality is currently split into three patches.
sanitize_realtime_unsafe
attribute to functions attributed with[[clang::blocking]]
(next PR)