109467b48Spatrick //===------- EHFrameSupportImpl.h - JITLink eh-frame utils ------*- C++ -*-===// 209467b48Spatrick // 309467b48Spatrick // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 409467b48Spatrick // See https://llvm.org/LICENSE.txt for license information. 509467b48Spatrick // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 609467b48Spatrick // 709467b48Spatrick //===----------------------------------------------------------------------===// 809467b48Spatrick // 909467b48Spatrick // EHFrame registration support for JITLink. 1009467b48Spatrick // 1109467b48Spatrick //===----------------------------------------------------------------------===// 1209467b48Spatrick 1309467b48Spatrick #ifndef LLVM_LIB_EXECUTIONENGINE_JITLINK_EHFRAMESUPPORTIMPL_H 1409467b48Spatrick #define LLVM_LIB_EXECUTIONENGINE_JITLINK_EHFRAMESUPPORTIMPL_H 1509467b48Spatrick 1609467b48Spatrick #include "llvm/ExecutionEngine/JITLink/EHFrameSupport.h" 1709467b48Spatrick 1809467b48Spatrick #include "llvm/ExecutionEngine/JITLink/JITLink.h" 1909467b48Spatrick #include "llvm/Support/BinaryStreamReader.h" 2009467b48Spatrick 2109467b48Spatrick namespace llvm { 2209467b48Spatrick namespace jitlink { 2309467b48Spatrick 2409467b48Spatrick /// A LinkGraph pass that adds missing FDE-to-CIE, FDE-to-PC and FDE-to-LSDA 2509467b48Spatrick /// edges. 2609467b48Spatrick class EHFrameEdgeFixer { 2709467b48Spatrick public: 28*d415bd75Srobert /// Create an eh-frame edge fixer. 29*d415bd75Srobert /// If a given edge-kind is not supported on the target architecture then 30*d415bd75Srobert /// Edge::Invalid should be used. 3173471bf0Spatrick EHFrameEdgeFixer(StringRef EHFrameSectionName, unsigned PointerSize, 32*d415bd75Srobert Edge::Kind Pointer32, Edge::Kind Pointer64, 33*d415bd75Srobert Edge::Kind Delta32, Edge::Kind Delta64, 3473471bf0Spatrick Edge::Kind NegDelta32); 3509467b48Spatrick Error operator()(LinkGraph &G); 3609467b48Spatrick 3709467b48Spatrick private: 3809467b48Spatrick 3909467b48Spatrick struct AugmentationInfo { 4009467b48Spatrick bool AugmentationDataPresent = false; 4109467b48Spatrick bool EHDataFieldPresent = false; 4209467b48Spatrick uint8_t Fields[4] = {0x0, 0x0, 0x0, 0x0}; 4309467b48Spatrick }; 4409467b48Spatrick 4509467b48Spatrick struct CIEInformation { 4609467b48Spatrick CIEInformation() = default; CIEInformationCIEInformation4709467b48Spatrick CIEInformation(Symbol &CIESymbol) : CIESymbol(&CIESymbol) {} 4809467b48Spatrick Symbol *CIESymbol = nullptr; 49*d415bd75Srobert bool AugmentationDataPresent = false; 50*d415bd75Srobert bool LSDAPresent = false; 51*d415bd75Srobert uint8_t LSDAEncoding = 0; 52*d415bd75Srobert uint8_t AddressEncoding = 0; 5309467b48Spatrick }; 5409467b48Spatrick 5509467b48Spatrick struct EdgeTarget { 5609467b48Spatrick EdgeTarget() = default; EdgeTargetEdgeTarget5709467b48Spatrick EdgeTarget(const Edge &E) : Target(&E.getTarget()), Addend(E.getAddend()) {} 5809467b48Spatrick 5909467b48Spatrick Symbol *Target = nullptr; 6009467b48Spatrick Edge::AddendT Addend = 0; 6109467b48Spatrick }; 6209467b48Spatrick 6309467b48Spatrick using BlockEdgeMap = DenseMap<Edge::OffsetT, EdgeTarget>; 64*d415bd75Srobert using CIEInfosMap = DenseMap<orc::ExecutorAddr, CIEInformation>; 6509467b48Spatrick 6609467b48Spatrick struct ParseContext { ParseContextParseContext6709467b48Spatrick ParseContext(LinkGraph &G) : G(G) {} 6809467b48Spatrick findCIEInfoParseContext69*d415bd75Srobert Expected<CIEInformation *> findCIEInfo(orc::ExecutorAddr Address) { 7009467b48Spatrick auto I = CIEInfos.find(Address); 7109467b48Spatrick if (I == CIEInfos.end()) 7209467b48Spatrick return make_error<JITLinkError>("No CIE found at address " + 7309467b48Spatrick formatv("{0:x16}", Address)); 7409467b48Spatrick return &I->second; 7509467b48Spatrick } 7609467b48Spatrick 7709467b48Spatrick LinkGraph &G; 7809467b48Spatrick CIEInfosMap CIEInfos; 7909467b48Spatrick BlockAddressMap AddrToBlock; 80*d415bd75Srobert DenseMap<orc::ExecutorAddr, Symbol *> AddrToSym; 8109467b48Spatrick }; 8209467b48Spatrick 8309467b48Spatrick Error processBlock(ParseContext &PC, Block &B); 8409467b48Spatrick Error processCIE(ParseContext &PC, Block &B, size_t RecordOffset, 85*d415bd75Srobert size_t RecordLength, size_t CIEDeltaFieldOffset, 86*d415bd75Srobert const BlockEdgeMap &BlockEdges); 8709467b48Spatrick Error processFDE(ParseContext &PC, Block &B, size_t RecordOffset, 8809467b48Spatrick size_t RecordLength, size_t CIEDeltaFieldOffset, 89*d415bd75Srobert uint32_t CIEDelta, const BlockEdgeMap &BlockEdges); 9009467b48Spatrick 9109467b48Spatrick Expected<AugmentationInfo> 9209467b48Spatrick parseAugmentationString(BinaryStreamReader &RecordReader); 9373471bf0Spatrick 94*d415bd75Srobert Expected<uint8_t> readPointerEncoding(BinaryStreamReader &RecordReader, 95*d415bd75Srobert Block &InBlock, const char *FieldName); 96*d415bd75Srobert Error skipEncodedPointer(uint8_t PointerEncoding, 9773471bf0Spatrick BinaryStreamReader &RecordReader); 98*d415bd75Srobert Expected<Symbol *> getOrCreateEncodedPointerEdge( 99*d415bd75Srobert ParseContext &PC, const BlockEdgeMap &BlockEdges, uint8_t PointerEncoding, 100*d415bd75Srobert BinaryStreamReader &RecordReader, Block &BlockToFix, 101*d415bd75Srobert size_t PointerFieldOffset, const char *FieldName); 10273471bf0Spatrick 103*d415bd75Srobert Expected<Symbol &> getOrCreateSymbol(ParseContext &PC, 104*d415bd75Srobert orc::ExecutorAddr Addr); 10509467b48Spatrick 10609467b48Spatrick StringRef EHFrameSectionName; 10773471bf0Spatrick unsigned PointerSize; 108*d415bd75Srobert Edge::Kind Pointer32; 109*d415bd75Srobert Edge::Kind Pointer64; 11073471bf0Spatrick Edge::Kind Delta32; 111*d415bd75Srobert Edge::Kind Delta64; 11273471bf0Spatrick Edge::Kind NegDelta32; 11373471bf0Spatrick }; 11473471bf0Spatrick 11573471bf0Spatrick /// Add a 32-bit null-terminator to the end of the eh-frame section. 11673471bf0Spatrick class EHFrameNullTerminator { 11773471bf0Spatrick public: 11873471bf0Spatrick EHFrameNullTerminator(StringRef EHFrameSectionName); 11973471bf0Spatrick Error operator()(LinkGraph &G); 12073471bf0Spatrick 12173471bf0Spatrick private: 12273471bf0Spatrick static char NullTerminatorBlockContent[]; 12373471bf0Spatrick StringRef EHFrameSectionName; 12409467b48Spatrick }; 12509467b48Spatrick 12609467b48Spatrick } // end namespace jitlink 12709467b48Spatrick } // end namespace llvm 12809467b48Spatrick 12909467b48Spatrick #endif // LLVM_LIB_EXECUTIONENGINE_JITLINK_EHFRAMESUPPORTIMPL_H 130