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 adds missing FDE-to-CIE, FDE-to-PC and FDE-to-LSDA 25 /// edges. 26 class EHFrameEdgeFixer { 27 public: 28 EHFrameEdgeFixer(StringRef EHFrameSectionName, unsigned PointerSize, 29 Edge::Kind Delta64, Edge::Kind Delta32, 30 Edge::Kind NegDelta32); 31 Error operator()(LinkGraph &G); 32 33 private: 34 35 struct AugmentationInfo { 36 bool AugmentationDataPresent = false; 37 bool EHDataFieldPresent = false; 38 uint8_t Fields[4] = {0x0, 0x0, 0x0, 0x0}; 39 }; 40 41 struct CIEInformation { 42 CIEInformation() = default; 43 CIEInformation(Symbol &CIESymbol) : CIESymbol(&CIESymbol) {} 44 Symbol *CIESymbol = nullptr; 45 bool FDEsHaveLSDAField = false; 46 uint8_t FDEPointerEncoding = 0; 47 uint8_t LSDAPointerEncoding = 0; 48 }; 49 50 struct EdgeTarget { 51 EdgeTarget() = default; 52 EdgeTarget(const Edge &E) : Target(&E.getTarget()), Addend(E.getAddend()) {} 53 54 Symbol *Target = nullptr; 55 Edge::AddendT Addend = 0; 56 }; 57 58 using BlockEdgeMap = DenseMap<Edge::OffsetT, EdgeTarget>; 59 using CIEInfosMap = DenseMap<orc::ExecutorAddr, CIEInformation>; 60 61 struct ParseContext { 62 ParseContext(LinkGraph &G) : G(G) {} 63 64 Expected<CIEInformation *> findCIEInfo(orc::ExecutorAddr Address) { 65 auto I = CIEInfos.find(Address); 66 if (I == CIEInfos.end()) 67 return make_error<JITLinkError>("No CIE found at address " + 68 formatv("{0:x16}", Address)); 69 return &I->second; 70 } 71 72 LinkGraph &G; 73 CIEInfosMap CIEInfos; 74 BlockAddressMap AddrToBlock; 75 SymbolAddressMap AddrToSyms; 76 }; 77 78 Error processBlock(ParseContext &PC, Block &B); 79 Error processCIE(ParseContext &PC, Block &B, size_t RecordOffset, 80 size_t RecordLength, size_t CIEDeltaFieldOffset); 81 Error processFDE(ParseContext &PC, Block &B, size_t RecordOffset, 82 size_t RecordLength, size_t CIEDeltaFieldOffset, 83 uint32_t CIEDelta, BlockEdgeMap &BlockEdges); 84 85 Expected<AugmentationInfo> 86 parseAugmentationString(BinaryStreamReader &RecordReader); 87 88 static bool isSupportedPointerEncoding(uint8_t PointerEncoding); 89 unsigned getPointerEncodingDataSize(uint8_t PointerEncoding); 90 Expected<std::pair<orc::ExecutorAddr, Edge::Kind>> 91 readEncodedPointer(uint8_t PointerEncoding, 92 orc::ExecutorAddr PointerFieldAddress, 93 BinaryStreamReader &RecordReader); 94 95 Expected<Symbol &> getOrCreateSymbol(ParseContext &PC, 96 orc::ExecutorAddr Addr); 97 98 StringRef EHFrameSectionName; 99 unsigned PointerSize; 100 Edge::Kind Delta64; 101 Edge::Kind Delta32; 102 Edge::Kind NegDelta32; 103 }; 104 105 /// Add a 32-bit null-terminator to the end of the eh-frame section. 106 class EHFrameNullTerminator { 107 public: 108 EHFrameNullTerminator(StringRef EHFrameSectionName); 109 Error operator()(LinkGraph &G); 110 111 private: 112 static char NullTerminatorBlockContent[]; 113 StringRef EHFrameSectionName; 114 }; 115 116 } // end namespace jitlink 117 } // end namespace llvm 118 119 #endif // LLVM_LIB_EXECUTIONENGINE_JITLINK_EHFRAMESUPPORTIMPL_H 120