1 //===- MemoryTaggingSupport.h - helpers for memory tagging implementations ===// 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-exception 5 // 6 //===----------------------------------------------------------------------===// 7 // 8 // This file declares common infrastructure for HWAddressSanitizer and 9 // Aarch64StackTagging. 10 // 11 //===----------------------------------------------------------------------===// 12 #ifndef LLVM_TRANSFORMS_UTILS_MEMORYTAGGINGSUPPORT_H 13 #define LLVM_TRANSFORMS_UTILS_MEMORYTAGGINGSUPPORT_H 14 15 #include "llvm/ADT/MapVector.h" 16 #include "llvm/ADT/STLFunctionalExtras.h" 17 #include "llvm/ADT/SmallVector.h" 18 #include "llvm/Analysis/LoopInfo.h" 19 #include "llvm/Analysis/OptimizationRemarkEmitter.h" 20 #include "llvm/Analysis/StackSafetyAnalysis.h" 21 #include "llvm/IR/IRBuilder.h" 22 #include "llvm/Support/Alignment.h" 23 24 namespace llvm { 25 class DominatorTree; 26 class DbgVariableIntrinsic; 27 class IntrinsicInst; 28 class PostDominatorTree; 29 class AllocaInst; 30 class Instruction; 31 namespace memtag { 32 // For an alloca valid between lifetime markers Start and Ends, call the 33 // Callback for all possible exits out of the lifetime in the containing 34 // function, which can return from the instructions in RetVec. 35 // 36 // Returns whether Ends covered all possible exits. If they did not, 37 // the caller should remove Ends to ensure that work done at the other 38 // exits does not happen outside of the lifetime. 39 bool forAllReachableExits(const DominatorTree &DT, const PostDominatorTree &PDT, 40 const LoopInfo &LI, const Instruction *Start, 41 const SmallVectorImpl<IntrinsicInst *> &Ends, 42 const SmallVectorImpl<Instruction *> &RetVec, 43 llvm::function_ref<void(Instruction *)> Callback); 44 45 bool isStandardLifetime(const SmallVectorImpl<IntrinsicInst *> &LifetimeStart, 46 const SmallVectorImpl<IntrinsicInst *> &LifetimeEnd, 47 const DominatorTree *DT, const LoopInfo *LI, 48 size_t MaxLifetimes); 49 50 Instruction *getUntagLocationIfFunctionExit(Instruction &Inst); 51 52 struct AllocaInfo { 53 AllocaInst *AI; 54 SmallVector<IntrinsicInst *, 2> LifetimeStart; 55 SmallVector<IntrinsicInst *, 2> LifetimeEnd; 56 SmallVector<DbgVariableIntrinsic *, 2> DbgVariableIntrinsics; 57 // Non-intrinsic records of variable locations. 58 SmallVector<DbgVariableRecord *, 2> DbgVariableRecords; 59 }; 60 61 struct StackInfo { 62 MapVector<AllocaInst *, AllocaInfo> AllocasToInstrument; 63 SmallVector<Instruction *, 4> UnrecognizedLifetimes; 64 SmallVector<Instruction *, 8> RetVec; 65 bool CallsReturnTwice = false; 66 }; 67 68 enum class AllocaInterestingness { 69 // Uninteresting because of the nature of the alloca. 70 kUninteresting, 71 // Uninteresting because proven safe. 72 kSafe, 73 // Interesting. 74 kInteresting 75 }; 76 77 class StackInfoBuilder { 78 public: 79 StackInfoBuilder(const StackSafetyGlobalInfo *SSI, const char *DebugType) 80 : SSI(SSI), DebugType(DebugType) {} 81 82 void visit(OptimizationRemarkEmitter &ORE, Instruction &Inst); 83 AllocaInterestingness getAllocaInterestingness(const AllocaInst &AI); 84 StackInfo &get() { return Info; }; 85 86 private: 87 StackInfo Info; 88 const StackSafetyGlobalInfo *SSI; 89 const char *DebugType; 90 }; 91 92 uint64_t getAllocaSizeInBytes(const AllocaInst &AI); 93 void alignAndPadAlloca(memtag::AllocaInfo &Info, llvm::Align Align); 94 bool isLifetimeIntrinsic(Value *V); 95 96 Value *readRegister(IRBuilder<> &IRB, StringRef Name); 97 Value *getFP(IRBuilder<> &IRB); 98 Value *getPC(const Triple &TargetTriple, IRBuilder<> &IRB); 99 Value *getAndroidSlotPtr(IRBuilder<> &IRB, int Slot); 100 101 void annotateDebugRecords(AllocaInfo &Info, unsigned int Tag); 102 Value *incrementThreadLong(IRBuilder<> &IRB, Value *ThreadLong, 103 unsigned int Inc); 104 105 } // namespace memtag 106 } // namespace llvm 107 108 #endif 109