1 //===------- EHFrameSupportImpl.h - JITLink eh-frame utils ------*- 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 // EHFrame registration support for JITLink. 10 // 11 //===----------------------------------------------------------------------===// 12 13 #ifndef LLVM_LIB_EXECUTIONENGINE_JITLINK_EHFRAMESUPPORTIMPL_H 14 #define LLVM_LIB_EXECUTIONENGINE_JITLINK_EHFRAMESUPPORTIMPL_H 15 16 #include "llvm/ExecutionEngine/JITLink/EHFrameSupport.h" 17 18 #include "llvm/ExecutionEngine/JITLink/JITLink.h" 19 #include "llvm/Support/BinaryStreamReader.h" 20 21 namespace llvm { 22 namespace jitlink { 23 24 /// A LinkGraph pass that splits blocks in an eh-frame section into sub-blocks 25 /// representing individual eh-frames. 26 /// EHFrameSplitter should not be run without EHFrameEdgeFixer, which is 27 /// responsible for adding FDE-to-CIE edges. 28 class EHFrameSplitter { 29 public: 30 EHFrameSplitter(StringRef EHFrameSectionName); 31 Error operator()(LinkGraph &G); 32 33 private: 34 Error processBlock(LinkGraph &G, Block &B, LinkGraph::SplitBlockCache &Cache); 35 36 StringRef EHFrameSectionName; 37 }; 38 39 /// A LinkGraph pass that adds missing FDE-to-CIE, FDE-to-PC and FDE-to-LSDA 40 /// edges. 41 class EHFrameEdgeFixer { 42 public: 43 EHFrameEdgeFixer(StringRef EHFrameSectionName, Edge::Kind FDEToCIE, 44 Edge::Kind FDEToPCBegin, Edge::Kind FDEToLSDA); 45 Error operator()(LinkGraph &G); 46 47 private: 48 49 struct AugmentationInfo { 50 bool AugmentationDataPresent = false; 51 bool EHDataFieldPresent = false; 52 uint8_t Fields[4] = {0x0, 0x0, 0x0, 0x0}; 53 }; 54 55 struct CIEInformation { 56 CIEInformation() = default; 57 CIEInformation(Symbol &CIESymbol) : CIESymbol(&CIESymbol) {} 58 Symbol *CIESymbol = nullptr; 59 bool FDEsHaveLSDAField = false; 60 }; 61 62 struct EdgeTarget { 63 EdgeTarget() = default; 64 EdgeTarget(const Edge &E) : Target(&E.getTarget()), Addend(E.getAddend()) {} 65 66 Symbol *Target = nullptr; 67 Edge::AddendT Addend = 0; 68 }; 69 70 using BlockEdgeMap = DenseMap<Edge::OffsetT, EdgeTarget>; 71 using CIEInfosMap = DenseMap<JITTargetAddress, CIEInformation>; 72 73 struct ParseContext { 74 ParseContext(LinkGraph &G) : G(G) {} 75 76 Expected<CIEInformation *> findCIEInfo(JITTargetAddress Address) { 77 auto I = CIEInfos.find(Address); 78 if (I == CIEInfos.end()) 79 return make_error<JITLinkError>("No CIE found at address " + 80 formatv("{0:x16}", Address)); 81 return &I->second; 82 } 83 84 LinkGraph &G; 85 CIEInfosMap CIEInfos; 86 BlockAddressMap AddrToBlock; 87 SymbolAddressMap AddrToSyms; 88 }; 89 90 Error processBlock(ParseContext &PC, Block &B); 91 Error processCIE(ParseContext &PC, Block &B, size_t RecordOffset, 92 size_t RecordLength, size_t CIEDeltaFieldOffset); 93 Error processFDE(ParseContext &PC, Block &B, size_t RecordOffset, 94 size_t RecordLength, size_t CIEDeltaFieldOffset, 95 uint32_t CIEDelta, BlockEdgeMap &BlockEdges); 96 97 Expected<AugmentationInfo> 98 parseAugmentationString(BinaryStreamReader &RecordReader); 99 Expected<JITTargetAddress> 100 readAbsolutePointer(LinkGraph &G, BinaryStreamReader &RecordReader); 101 Expected<Symbol &> getOrCreateSymbol(ParseContext &PC, JITTargetAddress Addr); 102 103 StringRef EHFrameSectionName; 104 Edge::Kind FDEToCIE; 105 Edge::Kind FDEToPCBegin; 106 Edge::Kind FDEToLSDA; 107 }; 108 109 } // end namespace jitlink 110 } // end namespace llvm 111 112 #endif // LLVM_LIB_EXECUTIONENGINE_JITLINK_EHFRAMESUPPORTIMPL_H 113