Path: blob/main/contrib/llvm-project/llvm/lib/Transforms/Instrumentation/RealtimeSanitizer.cpp
213799 views
//===- RealtimeSanitizer.cpp - RealtimeSanitizer instrumentation *- C++ -*-===//1//2// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.3// See https://llvm.org/LICENSE.txt for license information.4// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception5//6//===----------------------------------------------------------------------===//7//8// This file is a part of the RealtimeSanitizer, an LLVM transformation for9// detecting and reporting realtime safety violations.10//11// See also: llvm-project/compiler-rt/lib/rtsan/12//13//===----------------------------------------------------------------------===//1415#include "llvm/IR/Analysis.h"16#include "llvm/IR/IRBuilder.h"17#include "llvm/IR/InstIterator.h"18#include "llvm/IR/Module.h"19#include "llvm/Transforms/Utils/ModuleUtils.h"2021#include "llvm/Demangle/Demangle.h"22#include "llvm/Transforms/Instrumentation/RealtimeSanitizer.h"2324using namespace llvm;2526const char kRtsanModuleCtorName[] = "rtsan.module_ctor";27const char kRtsanInitName[] = "__rtsan_ensure_initialized";2829static SmallVector<Type *> getArgTypes(ArrayRef<Value *> FunctionArgs) {30SmallVector<Type *> Types;31for (Value *Arg : FunctionArgs)32Types.push_back(Arg->getType());33return Types;34}3536static void insertCallBeforeInstruction(Function &Fn, Instruction &Instruction,37const char *FunctionName,38ArrayRef<Value *> FunctionArgs) {39LLVMContext &Context = Fn.getContext();40FunctionType *FuncType = FunctionType::get(Type::getVoidTy(Context),41getArgTypes(FunctionArgs), false);42FunctionCallee Func =43Fn.getParent()->getOrInsertFunction(FunctionName, FuncType);44IRBuilder<> Builder{&Instruction};45Builder.CreateCall(Func, FunctionArgs);46}4748static void insertCallAtFunctionEntryPoint(Function &Fn,49const char *InsertFnName,50ArrayRef<Value *> FunctionArgs) {51insertCallBeforeInstruction(Fn, Fn.front().front(), InsertFnName,52FunctionArgs);53}5455static void insertCallAtAllFunctionExitPoints(Function &Fn,56const char *InsertFnName,57ArrayRef<Value *> FunctionArgs) {58for (auto &I : instructions(Fn))59if (isa<ReturnInst>(&I))60insertCallBeforeInstruction(Fn, I, InsertFnName, FunctionArgs);61}6263static PreservedAnalyses rtsanPreservedCFGAnalyses() {64PreservedAnalyses PA;65PA.preserveSet<CFGAnalyses>();66return PA;67}6869static PreservedAnalyses runSanitizeRealtime(Function &Fn) {70insertCallAtFunctionEntryPoint(Fn, "__rtsan_realtime_enter", {});71insertCallAtAllFunctionExitPoints(Fn, "__rtsan_realtime_exit", {});72return rtsanPreservedCFGAnalyses();73}7475static PreservedAnalyses runSanitizeRealtimeBlocking(Function &Fn) {76IRBuilder<> Builder(&Fn.front().front());77Value *Name = Builder.CreateGlobalString(demangle(Fn.getName()));78insertCallAtFunctionEntryPoint(Fn, "__rtsan_notify_blocking_call", {Name});79return rtsanPreservedCFGAnalyses();80}8182PreservedAnalyses RealtimeSanitizerPass::run(Module &M,83ModuleAnalysisManager &MAM) {84getOrCreateSanitizerCtorAndInitFunctions(85M, kRtsanModuleCtorName, kRtsanInitName, /*InitArgTypes=*/{},86/*InitArgs=*/{},87// This callback is invoked when the functions are created the first88// time. Hook them into the global ctors list in that case:89[&](Function *Ctor, FunctionCallee) { appendToGlobalCtors(M, Ctor, 0); });9091for (Function &F : M) {92if (F.empty())93continue;9495if (F.hasFnAttribute(Attribute::SanitizeRealtime))96runSanitizeRealtime(F);9798if (F.hasFnAttribute(Attribute::SanitizeRealtimeBlocking))99runSanitizeRealtimeBlocking(F);100}101102return PreservedAnalyses::none();103}104105106