10b57cec5SDimitry Andric //===------- EHFrameSupportImpl.h - JITLink eh-frame utils ------*- C++ -*-===// 20b57cec5SDimitry Andric // 30b57cec5SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 40b57cec5SDimitry Andric // See https://llvm.org/LICENSE.txt for license information. 50b57cec5SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 60b57cec5SDimitry Andric // 70b57cec5SDimitry Andric //===----------------------------------------------------------------------===// 80b57cec5SDimitry Andric // 90b57cec5SDimitry Andric // EHFrame registration support for JITLink. 100b57cec5SDimitry Andric // 110b57cec5SDimitry Andric //===----------------------------------------------------------------------===// 120b57cec5SDimitry Andric 130b57cec5SDimitry Andric #ifndef LLVM_LIB_EXECUTIONENGINE_JITLINK_EHFRAMESUPPORTIMPL_H 140b57cec5SDimitry Andric #define LLVM_LIB_EXECUTIONENGINE_JITLINK_EHFRAMESUPPORTIMPL_H 150b57cec5SDimitry Andric 160b57cec5SDimitry Andric #include "llvm/ExecutionEngine/JITLink/EHFrameSupport.h" 170b57cec5SDimitry Andric 180b57cec5SDimitry Andric #include "llvm/ExecutionEngine/JITLink/JITLink.h" 190b57cec5SDimitry Andric #include "llvm/Support/BinaryStreamReader.h" 200b57cec5SDimitry Andric 210b57cec5SDimitry Andric namespace llvm { 220b57cec5SDimitry Andric namespace jitlink { 230b57cec5SDimitry Andric 24480093f4SDimitry Andric /// A LinkGraph pass that adds missing FDE-to-CIE, FDE-to-PC and FDE-to-LSDA 25480093f4SDimitry Andric /// edges. 26480093f4SDimitry Andric class EHFrameEdgeFixer { 27480093f4SDimitry Andric public: 2881ad6265SDimitry Andric /// Create an eh-frame edge fixer. 2981ad6265SDimitry Andric /// If a given edge-kind is not supported on the target architecture then 3081ad6265SDimitry Andric /// Edge::Invalid should be used. 31e8d8bef9SDimitry Andric EHFrameEdgeFixer(StringRef EHFrameSectionName, unsigned PointerSize, 3281ad6265SDimitry Andric Edge::Kind Pointer32, Edge::Kind Pointer64, 3381ad6265SDimitry Andric Edge::Kind Delta32, Edge::Kind Delta64, 34e8d8bef9SDimitry Andric Edge::Kind NegDelta32); 35480093f4SDimitry Andric Error operator()(LinkGraph &G); 36480093f4SDimitry Andric 37480093f4SDimitry Andric private: 388bcb0991SDimitry Andric 390b57cec5SDimitry Andric struct AugmentationInfo { 400b57cec5SDimitry Andric bool AugmentationDataPresent = false; 410b57cec5SDimitry Andric bool EHDataFieldPresent = false; 420b57cec5SDimitry Andric uint8_t Fields[4] = {0x0, 0x0, 0x0, 0x0}; 430b57cec5SDimitry Andric }; 440b57cec5SDimitry Andric 450b57cec5SDimitry Andric struct CIEInformation { 460b57cec5SDimitry Andric CIEInformation() = default; 478bcb0991SDimitry Andric CIEInformation(Symbol &CIESymbol) : CIESymbol(&CIESymbol) {} 488bcb0991SDimitry Andric Symbol *CIESymbol = nullptr; 4981ad6265SDimitry Andric bool AugmentationDataPresent = false; 5081ad6265SDimitry Andric bool LSDAPresent = false; 5181ad6265SDimitry Andric uint8_t LSDAEncoding = 0; 5281ad6265SDimitry Andric uint8_t AddressEncoding = 0; 530b57cec5SDimitry Andric }; 540b57cec5SDimitry Andric 55480093f4SDimitry Andric struct EdgeTarget { 56480093f4SDimitry Andric EdgeTarget() = default; 57480093f4SDimitry Andric EdgeTarget(const Edge &E) : Target(&E.getTarget()), Addend(E.getAddend()) {} 58480093f4SDimitry Andric 59480093f4SDimitry Andric Symbol *Target = nullptr; 60480093f4SDimitry Andric Edge::AddendT Addend = 0; 61480093f4SDimitry Andric }; 62480093f4SDimitry Andric 63*5f757f3fSDimitry Andric struct BlockEdgesInfo { 64*5f757f3fSDimitry Andric DenseMap<Edge::OffsetT, EdgeTarget> TargetMap; 65*5f757f3fSDimitry Andric DenseSet<Edge::OffsetT> Multiple; 66*5f757f3fSDimitry Andric }; 67*5f757f3fSDimitry Andric 6804eeddc0SDimitry Andric using CIEInfosMap = DenseMap<orc::ExecutorAddr, CIEInformation>; 69480093f4SDimitry Andric 70480093f4SDimitry Andric struct ParseContext { 71480093f4SDimitry Andric ParseContext(LinkGraph &G) : G(G) {} 72480093f4SDimitry Andric 7304eeddc0SDimitry Andric Expected<CIEInformation *> findCIEInfo(orc::ExecutorAddr Address) { 74480093f4SDimitry Andric auto I = CIEInfos.find(Address); 75480093f4SDimitry Andric if (I == CIEInfos.end()) 76480093f4SDimitry Andric return make_error<JITLinkError>("No CIE found at address " + 77480093f4SDimitry Andric formatv("{0:x16}", Address)); 78480093f4SDimitry Andric return &I->second; 79480093f4SDimitry Andric } 80480093f4SDimitry Andric 81480093f4SDimitry Andric LinkGraph &G; 82480093f4SDimitry Andric CIEInfosMap CIEInfos; 83480093f4SDimitry Andric BlockAddressMap AddrToBlock; 8481ad6265SDimitry Andric DenseMap<orc::ExecutorAddr, Symbol *> AddrToSym; 85480093f4SDimitry Andric }; 86480093f4SDimitry Andric 87480093f4SDimitry Andric Error processBlock(ParseContext &PC, Block &B); 88*5f757f3fSDimitry Andric Error processCIE(ParseContext &PC, Block &B, size_t CIEDeltaFieldOffset, 89*5f757f3fSDimitry Andric const BlockEdgesInfo &BlockEdges); 90*5f757f3fSDimitry Andric Error processFDE(ParseContext &PC, Block &B, size_t CIEDeltaFieldOffset, 91*5f757f3fSDimitry Andric uint32_t CIEDelta, const BlockEdgesInfo &BlockEdges); 92480093f4SDimitry Andric 93480093f4SDimitry Andric Expected<AugmentationInfo> 94480093f4SDimitry Andric parseAugmentationString(BinaryStreamReader &RecordReader); 95e8d8bef9SDimitry Andric 9681ad6265SDimitry Andric Expected<uint8_t> readPointerEncoding(BinaryStreamReader &RecordReader, 9781ad6265SDimitry Andric Block &InBlock, const char *FieldName); 9881ad6265SDimitry Andric Error skipEncodedPointer(uint8_t PointerEncoding, 99e8d8bef9SDimitry Andric BinaryStreamReader &RecordReader); 10081ad6265SDimitry Andric Expected<Symbol *> getOrCreateEncodedPointerEdge( 101*5f757f3fSDimitry Andric ParseContext &PC, const BlockEdgesInfo &BlockEdges, 102*5f757f3fSDimitry Andric uint8_t PointerEncoding, BinaryStreamReader &RecordReader, 103*5f757f3fSDimitry Andric Block &BlockToFix, size_t PointerFieldOffset, const char *FieldName); 104e8d8bef9SDimitry Andric 10504eeddc0SDimitry Andric Expected<Symbol &> getOrCreateSymbol(ParseContext &PC, 10604eeddc0SDimitry Andric orc::ExecutorAddr Addr); 107480093f4SDimitry Andric 108480093f4SDimitry Andric StringRef EHFrameSectionName; 109e8d8bef9SDimitry Andric unsigned PointerSize; 11081ad6265SDimitry Andric Edge::Kind Pointer32; 11181ad6265SDimitry Andric Edge::Kind Pointer64; 112e8d8bef9SDimitry Andric Edge::Kind Delta32; 11381ad6265SDimitry Andric Edge::Kind Delta64; 114e8d8bef9SDimitry Andric Edge::Kind NegDelta32; 1150b57cec5SDimitry Andric }; 1160b57cec5SDimitry Andric 117fe6060f1SDimitry Andric /// Add a 32-bit null-terminator to the end of the eh-frame section. 118fe6060f1SDimitry Andric class EHFrameNullTerminator { 119fe6060f1SDimitry Andric public: 120fe6060f1SDimitry Andric EHFrameNullTerminator(StringRef EHFrameSectionName); 121fe6060f1SDimitry Andric Error operator()(LinkGraph &G); 122fe6060f1SDimitry Andric 123fe6060f1SDimitry Andric private: 124fe6060f1SDimitry Andric static char NullTerminatorBlockContent[]; 125fe6060f1SDimitry Andric StringRef EHFrameSectionName; 126fe6060f1SDimitry Andric }; 127fe6060f1SDimitry Andric 1280b57cec5SDimitry Andric } // end namespace jitlink 1290b57cec5SDimitry Andric } // end namespace llvm 1300b57cec5SDimitry Andric 1310b57cec5SDimitry Andric #endif // LLVM_LIB_EXECUTIONENGINE_JITLINK_EHFRAMESUPPORTIMPL_H 132