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 /// Create an eh-frame edge fixer. 29 /// If a given edge-kind is not supported on the target architecture then 30 /// Edge::Invalid should be used. 31 EHFrameEdgeFixer(StringRef EHFrameSectionName, unsigned PointerSize, 32 Edge::Kind Pointer32, Edge::Kind Pointer64, 33 Edge::Kind Delta32, Edge::Kind Delta64, 34 Edge::Kind NegDelta32); 35 Error operator()(LinkGraph &G); 36 37 private: 38 39 struct AugmentationInfo { 40 bool AugmentationDataPresent = false; 41 bool EHDataFieldPresent = false; 42 uint8_t Fields[4] = {0x0, 0x0, 0x0, 0x0}; 43 }; 44 45 struct CIEInformation { 46 CIEInformation() = default; 47 CIEInformation(Symbol &CIESymbol) : CIESymbol(&CIESymbol) {} 48 Symbol *CIESymbol = nullptr; 49 bool AugmentationDataPresent = false; 50 bool LSDAPresent = false; 51 uint8_t LSDAEncoding = 0; 52 uint8_t AddressEncoding = 0; 53 }; 54 55 struct EdgeTarget { 56 EdgeTarget() = default; 57 EdgeTarget(const Edge &E) : Target(&E.getTarget()), Addend(E.getAddend()) {} 58 59 Symbol *Target = nullptr; 60 Edge::AddendT Addend = 0; 61 }; 62 63 using BlockEdgeMap = DenseMap<Edge::OffsetT, EdgeTarget>; 64 using CIEInfosMap = DenseMap<orc::ExecutorAddr, CIEInformation>; 65 66 struct ParseContext { 67 ParseContext(LinkGraph &G) : G(G) {} 68 69 Expected<CIEInformation *> findCIEInfo(orc::ExecutorAddr Address) { 70 auto I = CIEInfos.find(Address); 71 if (I == CIEInfos.end()) 72 return make_error<JITLinkError>("No CIE found at address " + 73 formatv("{0:x16}", Address)); 74 return &I->second; 75 } 76 77 LinkGraph &G; 78 CIEInfosMap CIEInfos; 79 BlockAddressMap AddrToBlock; 80 DenseMap<orc::ExecutorAddr, Symbol *> AddrToSym; 81 }; 82 83 Error processBlock(ParseContext &PC, Block &B); 84 Error processCIE(ParseContext &PC, Block &B, size_t RecordOffset, 85 size_t RecordLength, size_t CIEDeltaFieldOffset, 86 const BlockEdgeMap &BlockEdges); 87 Error processFDE(ParseContext &PC, Block &B, size_t RecordOffset, 88 size_t RecordLength, size_t CIEDeltaFieldOffset, 89 uint32_t CIEDelta, const BlockEdgeMap &BlockEdges); 90 91 Expected<AugmentationInfo> 92 parseAugmentationString(BinaryStreamReader &RecordReader); 93 94 Expected<uint8_t> readPointerEncoding(BinaryStreamReader &RecordReader, 95 Block &InBlock, const char *FieldName); 96 Error skipEncodedPointer(uint8_t PointerEncoding, 97 BinaryStreamReader &RecordReader); 98 Expected<Symbol *> getOrCreateEncodedPointerEdge( 99 ParseContext &PC, const BlockEdgeMap &BlockEdges, uint8_t PointerEncoding, 100 BinaryStreamReader &RecordReader, Block &BlockToFix, 101 size_t PointerFieldOffset, const char *FieldName); 102 103 Expected<Symbol &> getOrCreateSymbol(ParseContext &PC, 104 orc::ExecutorAddr Addr); 105 106 StringRef EHFrameSectionName; 107 unsigned PointerSize; 108 Edge::Kind Pointer32; 109 Edge::Kind Pointer64; 110 Edge::Kind Delta32; 111 Edge::Kind Delta64; 112 Edge::Kind NegDelta32; 113 }; 114 115 /// Add a 32-bit null-terminator to the end of the eh-frame section. 116 class EHFrameNullTerminator { 117 public: 118 EHFrameNullTerminator(StringRef EHFrameSectionName); 119 Error operator()(LinkGraph &G); 120 121 private: 122 static char NullTerminatorBlockContent[]; 123 StringRef EHFrameSectionName; 124 }; 125 126 } // end namespace jitlink 127 } // end namespace llvm 128 129 #endif // LLVM_LIB_EXECUTIONENGINE_JITLINK_EHFRAMESUPPORTIMPL_H 130