Skip to content

Commit 4547d60

Browse files
[llvm][rtsan] Add transform pass for sanitize_realtime_unsafe (#109543)
1 parent e813750 commit 4547d60

File tree

2 files changed

+79
-20
lines changed

2 files changed

+79
-20
lines changed

llvm/lib/Transforms/Instrumentation/RealtimeSanitizer.cpp

Lines changed: 48 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -15,49 +15,77 @@
1515

1616
#include "llvm/IR/Analysis.h"
1717
#include "llvm/IR/IRBuilder.h"
18+
#include "llvm/IR/InstIterator.h"
1819
#include "llvm/IR/Module.h"
1920

21+
#include "llvm/Demangle/Demangle.h"
2022
#include "llvm/Transforms/Instrumentation/RealtimeSanitizer.h"
2123

2224
using namespace llvm;
2325

26+
static SmallVector<Type *> getArgTypes(ArrayRef<Value *> FunctionArgs) {
27+
SmallVector<Type *> Types;
28+
for (Value *Arg : FunctionArgs)
29+
Types.push_back(Arg->getType());
30+
return Types;
31+
}
32+
2433
static void insertCallBeforeInstruction(Function &Fn, Instruction &Instruction,
25-
const char *FunctionName) {
34+
const char *FunctionName,
35+
ArrayRef<Value *> FunctionArgs) {
2636
LLVMContext &Context = Fn.getContext();
27-
FunctionType *FuncType = FunctionType::get(Type::getVoidTy(Context), false);
37+
FunctionType *FuncType = FunctionType::get(Type::getVoidTy(Context),
38+
getArgTypes(FunctionArgs), false);
2839
FunctionCallee Func =
2940
Fn.getParent()->getOrInsertFunction(FunctionName, FuncType);
3041
IRBuilder<> Builder{&Instruction};
31-
Builder.CreateCall(Func, {});
42+
Builder.CreateCall(Func, FunctionArgs);
3243
}
3344

3445
static void insertCallAtFunctionEntryPoint(Function &Fn,
35-
const char *InsertFnName) {
36-
37-
insertCallBeforeInstruction(Fn, Fn.front().front(), InsertFnName);
46+
const char *InsertFnName,
47+
ArrayRef<Value *> FunctionArgs) {
48+
insertCallBeforeInstruction(Fn, Fn.front().front(), InsertFnName,
49+
FunctionArgs);
3850
}
3951

4052
static void insertCallAtAllFunctionExitPoints(Function &Fn,
41-
const char *InsertFnName) {
42-
for (auto &BB : Fn)
43-
for (auto &I : BB)
44-
if (isa<ReturnInst>(&I))
45-
insertCallBeforeInstruction(Fn, I, InsertFnName);
53+
const char *InsertFnName,
54+
ArrayRef<Value *> FunctionArgs) {
55+
for (auto &I : instructions(Fn))
56+
if (isa<ReturnInst>(&I))
57+
insertCallBeforeInstruction(Fn, I, InsertFnName, FunctionArgs);
58+
}
59+
60+
static PreservedAnalyses rtsanPreservedCFGAnalyses() {
61+
PreservedAnalyses PA;
62+
PA.preserveSet<CFGAnalyses>();
63+
return PA;
64+
}
65+
66+
static PreservedAnalyses runSanitizeRealtime(Function &Fn) {
67+
insertCallAtFunctionEntryPoint(Fn, "__rtsan_realtime_enter", {});
68+
insertCallAtAllFunctionExitPoints(Fn, "__rtsan_realtime_exit", {});
69+
return rtsanPreservedCFGAnalyses();
70+
}
71+
72+
static PreservedAnalyses runSanitizeRealtimeUnsafe(Function &Fn) {
73+
IRBuilder<> Builder(&Fn.front().front());
74+
Value *Name = Builder.CreateGlobalString(demangle(Fn.getName()));
75+
insertCallAtFunctionEntryPoint(Fn, "__rtsan_notify_blocking_call", {Name});
76+
return rtsanPreservedCFGAnalyses();
4677
}
4778

4879
RealtimeSanitizerPass::RealtimeSanitizerPass(
4980
const RealtimeSanitizerOptions &Options) {}
5081

51-
PreservedAnalyses RealtimeSanitizerPass::run(Function &F,
82+
PreservedAnalyses RealtimeSanitizerPass::run(Function &Fn,
5283
AnalysisManager<Function> &AM) {
53-
if (F.hasFnAttribute(Attribute::SanitizeRealtime)) {
54-
insertCallAtFunctionEntryPoint(F, "__rtsan_realtime_enter");
55-
insertCallAtAllFunctionExitPoints(F, "__rtsan_realtime_exit");
56-
57-
PreservedAnalyses PA;
58-
PA.preserveSet<CFGAnalyses>();
59-
return PA;
60-
}
84+
if (Fn.hasFnAttribute(Attribute::SanitizeRealtime))
85+
return runSanitizeRealtime(Fn);
86+
87+
if (Fn.hasFnAttribute(Attribute::SanitizeRealtimeUnsafe))
88+
return runSanitizeRealtimeUnsafe(Fn);
6189

6290
return PreservedAnalyses::all();
6391
}
Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --check-globals all --version 5
2+
; RUN: opt < %s -passes=rtsan -S | FileCheck %s
3+
4+
; RealtimeSanitizer pass should create the demangled function name as a global string and,
5+
; at the function entrypoint, pass it as an argument to the rtsan notify method
6+
7+
;.
8+
; CHECK: @[[GLOB0:[0-9]+]] = private unnamed_addr constant [20 x i8] c"blocking_function()\00", align 1
9+
;.
10+
define void @_Z17blocking_functionv() #0 {
11+
; CHECK-LABEL: define void @_Z17blocking_functionv(
12+
; CHECK-SAME: ) #[[ATTR0:[0-9]+]] {
13+
; CHECK-NEXT: call void @__rtsan_notify_blocking_call(ptr @[[GLOB0]])
14+
; CHECK-NEXT: ret void
15+
;
16+
ret void
17+
}
18+
19+
define noundef i32 @main() #2 {
20+
; CHECK-LABEL: define noundef i32 @main() {
21+
; CHECK-NEXT: call void @_Z17blocking_functionv()
22+
; CHECK-NEXT: ret i32 0
23+
;
24+
call void @_Z17blocking_functionv() #4
25+
ret i32 0
26+
}
27+
28+
attributes #0 = { mustprogress noinline sanitize_realtime_unsafe optnone ssp uwtable(sync) }
29+
;.
30+
; CHECK: attributes #[[ATTR0]] = { mustprogress noinline optnone sanitize_realtime_unsafe ssp uwtable(sync) }
31+
;.

0 commit comments

Comments
 (0)