brintos

brintos / llvm-project-archived public Read only

0
0
Text · 3.9 KiB · 667fdb7 Raw
105 lines · cpp
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-exception6//7//===----------------------------------------------------------------------===//8//9// This file is a part of the RealtimeSanitizer, an LLVM transformation for10// 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 25using namespace llvm;26 27const char kRtsanModuleCtorName[] = "rtsan.module_ctor";28const char kRtsanInitName[] = "__rtsan_ensure_initialized";29 30static 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 37static 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 49static void insertCallAtFunctionEntryPoint(Function &Fn,50                                           const char *InsertFnName,51                                           ArrayRef<Value *> FunctionArgs) {52  insertCallBeforeInstruction(Fn, Fn.front().front(), InsertFnName,53                              FunctionArgs);54}55 56static 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 64static PreservedAnalyses rtsanPreservedCFGAnalyses() {65  PreservedAnalyses PA;66  PA.preserveSet<CFGAnalyses>();67  return PA;68}69 70static PreservedAnalyses runSanitizeRealtime(Function &Fn) {71  insertCallAtFunctionEntryPoint(Fn, "__rtsan_realtime_enter", {});72  insertCallAtAllFunctionExitPoints(Fn, "__rtsan_realtime_exit", {});73  return rtsanPreservedCFGAnalyses();74}75 76static 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 83PreservedAnalyses 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 first89      // 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