Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
freebsd
GitHub Repository: freebsd/freebsd-src
Path: blob/main/contrib/llvm-project/llvm/lib/Transforms/Instrumentation/RealtimeSanitizer.cpp
213799 views
1
//===- RealtimeSanitizer.cpp - RealtimeSanitizer instrumentation *- C++ -*-===//
2
//
3
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4
// See https://llvm.org/LICENSE.txt for license information.
5
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6
//
7
//===----------------------------------------------------------------------===//
8
//
9
// This file is a part of the RealtimeSanitizer, an LLVM transformation for
10
// detecting and reporting realtime safety violations.
11
//
12
// See also: llvm-project/compiler-rt/lib/rtsan/
13
//
14
//===----------------------------------------------------------------------===//
15
16
#include "llvm/IR/Analysis.h"
17
#include "llvm/IR/IRBuilder.h"
18
#include "llvm/IR/InstIterator.h"
19
#include "llvm/IR/Module.h"
20
#include "llvm/Transforms/Utils/ModuleUtils.h"
21
22
#include "llvm/Demangle/Demangle.h"
23
#include "llvm/Transforms/Instrumentation/RealtimeSanitizer.h"
24
25
using namespace llvm;
26
27
const char kRtsanModuleCtorName[] = "rtsan.module_ctor";
28
const char kRtsanInitName[] = "__rtsan_ensure_initialized";
29
30
static SmallVector<Type *> getArgTypes(ArrayRef<Value *> FunctionArgs) {
31
SmallVector<Type *> Types;
32
for (Value *Arg : FunctionArgs)
33
Types.push_back(Arg->getType());
34
return Types;
35
}
36
37
static void insertCallBeforeInstruction(Function &Fn, Instruction &Instruction,
38
const char *FunctionName,
39
ArrayRef<Value *> FunctionArgs) {
40
LLVMContext &Context = Fn.getContext();
41
FunctionType *FuncType = FunctionType::get(Type::getVoidTy(Context),
42
getArgTypes(FunctionArgs), false);
43
FunctionCallee Func =
44
Fn.getParent()->getOrInsertFunction(FunctionName, FuncType);
45
IRBuilder<> Builder{&Instruction};
46
Builder.CreateCall(Func, FunctionArgs);
47
}
48
49
static void insertCallAtFunctionEntryPoint(Function &Fn,
50
const char *InsertFnName,
51
ArrayRef<Value *> FunctionArgs) {
52
insertCallBeforeInstruction(Fn, Fn.front().front(), InsertFnName,
53
FunctionArgs);
54
}
55
56
static void insertCallAtAllFunctionExitPoints(Function &Fn,
57
const char *InsertFnName,
58
ArrayRef<Value *> FunctionArgs) {
59
for (auto &I : instructions(Fn))
60
if (isa<ReturnInst>(&I))
61
insertCallBeforeInstruction(Fn, I, InsertFnName, FunctionArgs);
62
}
63
64
static PreservedAnalyses rtsanPreservedCFGAnalyses() {
65
PreservedAnalyses PA;
66
PA.preserveSet<CFGAnalyses>();
67
return PA;
68
}
69
70
static PreservedAnalyses runSanitizeRealtime(Function &Fn) {
71
insertCallAtFunctionEntryPoint(Fn, "__rtsan_realtime_enter", {});
72
insertCallAtAllFunctionExitPoints(Fn, "__rtsan_realtime_exit", {});
73
return rtsanPreservedCFGAnalyses();
74
}
75
76
static PreservedAnalyses runSanitizeRealtimeBlocking(Function &Fn) {
77
IRBuilder<> Builder(&Fn.front().front());
78
Value *Name = Builder.CreateGlobalString(demangle(Fn.getName()));
79
insertCallAtFunctionEntryPoint(Fn, "__rtsan_notify_blocking_call", {Name});
80
return rtsanPreservedCFGAnalyses();
81
}
82
83
PreservedAnalyses RealtimeSanitizerPass::run(Module &M,
84
ModuleAnalysisManager &MAM) {
85
getOrCreateSanitizerCtorAndInitFunctions(
86
M, kRtsanModuleCtorName, kRtsanInitName, /*InitArgTypes=*/{},
87
/*InitArgs=*/{},
88
// This callback is invoked when the functions are created the first
89
// time. Hook them into the global ctors list in that case:
90
[&](Function *Ctor, FunctionCallee) { appendToGlobalCtors(M, Ctor, 0); });
91
92
for (Function &F : M) {
93
if (F.empty())
94
continue;
95
96
if (F.hasFnAttribute(Attribute::SanitizeRealtime))
97
runSanitizeRealtime(F);
98
99
if (F.hasFnAttribute(Attribute::SanitizeRealtimeBlocking))
100
runSanitizeRealtimeBlocking(F);
101
}
102
103
return PreservedAnalyses::none();
104
}
105
106