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 /// Adds edges for implicit relocations on platforms where these are used 30 /// (e.g. MachO/x86-64). 31 /// 32 /// If a given edge-kind is not supported on the target architecture then 33 /// Edge::Invalid should be used. 34 EHFrameEdgeFixer(StringRef EHFrameSectionName, unsigned PointerSize, 35 Edge::Kind Pointer32, Edge::Kind Pointer64, 36 Edge::Kind Delta32, Edge::Kind Delta64, 37 Edge::Kind NegDelta32); 38 Error operator()(LinkGraph &G); 39 40 private: 41 42 struct AugmentationInfo { 43 bool AugmentationDataPresent = false; 44 bool EHDataFieldPresent = false; 45 uint8_t Fields[4] = {0x0, 0x0, 0x0, 0x0}; 46 }; 47 48 struct CIEInformation { 49 CIEInformation() = default; 50 CIEInformation(Symbol &CIESymbol) : CIESymbol(&CIESymbol) {} 51 Symbol *CIESymbol = nullptr; 52 bool AugmentationDataPresent = false; 53 bool LSDAPresent = false; 54 uint8_t LSDAEncoding = 0; 55 uint8_t AddressEncoding = 0; 56 }; 57 58 struct EdgeTarget { 59 EdgeTarget() = default; 60 EdgeTarget(const Edge &E) : Target(&E.getTarget()), Addend(E.getAddend()) {} 61 62 Symbol *Target = nullptr; 63 Edge::AddendT Addend = 0; 64 }; 65 66 struct BlockEdgesInfo { 67 DenseMap<Edge::OffsetT, EdgeTarget> TargetMap; 68 DenseSet<Edge::OffsetT> Multiple; 69 }; 70 71 using CIEInfosMap = DenseMap<orc::ExecutorAddr, CIEInformation>; 72 73 struct ParseContext { 74 ParseContext(LinkGraph &G) : G(G) {} 75 76 Expected<CIEInformation *> findCIEInfo(orc::ExecutorAddr 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 DenseMap<orc::ExecutorAddr, Symbol *> AddrToSym; 88 }; 89 90 Error processBlock(ParseContext &PC, Block &B); 91 Error processCIE(ParseContext &PC, Block &B, size_t CIEDeltaFieldOffset, 92 const BlockEdgesInfo &BlockEdges); 93 Error processFDE(ParseContext &PC, Block &B, size_t CIEDeltaFieldOffset, 94 uint32_t CIEDelta, const BlockEdgesInfo &BlockEdges); 95 96 Expected<AugmentationInfo> 97 parseAugmentationString(BinaryStreamReader &RecordReader); 98 99 Expected<uint8_t> readPointerEncoding(BinaryStreamReader &RecordReader, 100 Block &InBlock, const char *FieldName); 101 Error skipEncodedPointer(uint8_t PointerEncoding, 102 BinaryStreamReader &RecordReader); 103 Expected<Symbol *> getOrCreateEncodedPointerEdge( 104 ParseContext &PC, const BlockEdgesInfo &BlockEdges, 105 uint8_t PointerEncoding, BinaryStreamReader &RecordReader, 106 Block &BlockToFix, size_t PointerFieldOffset, const char *FieldName); 107 108 Expected<Symbol &> getOrCreateSymbol(ParseContext &PC, 109 orc::ExecutorAddr Addr); 110 111 StringRef EHFrameSectionName; 112 unsigned PointerSize; 113 Edge::Kind Pointer32; 114 Edge::Kind Pointer64; 115 Edge::Kind Delta32; 116 Edge::Kind Delta64; 117 Edge::Kind NegDelta32; 118 }; 119 120 /// Add a 32-bit null-terminator to the end of the eh-frame section. 121 class EHFrameNullTerminator { 122 public: 123 EHFrameNullTerminator(StringRef EHFrameSectionName); 124 Error operator()(LinkGraph &G); 125 126 private: 127 static char NullTerminatorBlockContent[]; 128 StringRef EHFrameSectionName; 129 }; 130 131 } // end namespace jitlink 132 } // end namespace llvm 133 134 #endif // LLVM_LIB_EXECUTIONENGINE_JITLINK_EHFRAMESUPPORTIMPL_H 135