//===------- EHFrameSupportImpl.h - JITLink eh-frame utils ------*- C++ -*-===// // // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. // See https://llvm.org/LICENSE.txt for license information. // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception // //===----------------------------------------------------------------------===// // // EHFrame registration support for JITLink. // //===----------------------------------------------------------------------===// #ifndef LLVM_LIB_EXECUTIONENGINE_JITLINK_EHFRAMESUPPORTIMPL_H #define LLVM_LIB_EXECUTIONENGINE_JITLINK_EHFRAMESUPPORTIMPL_H #include "llvm/ExecutionEngine/JITLink/EHFrameSupport.h" #include "llvm/ExecutionEngine/JITLink/JITLink.h" #include "llvm/Support/BinaryStreamReader.h" namespace llvm { namespace jitlink { /// A LinkGraph pass that splits blocks in an eh-frame section into sub-blocks /// representing individual eh-frames. /// EHFrameSplitter should not be run without EHFrameEdgeFixer, which is /// responsible for adding FDE-to-CIE edges. class EHFrameSplitter { public: EHFrameSplitter(StringRef EHFrameSectionName); Error operator()(LinkGraph &G); private: Error processBlock(LinkGraph &G, Block &B, LinkGraph::SplitBlockCache &Cache); StringRef EHFrameSectionName; }; /// A LinkGraph pass that adds missing FDE-to-CIE, FDE-to-PC and FDE-to-LSDA /// edges. class EHFrameEdgeFixer { public: EHFrameEdgeFixer(StringRef EHFrameSectionName, Edge::Kind FDEToCIE, Edge::Kind FDEToPCBegin, Edge::Kind FDEToLSDA); Error operator()(LinkGraph &G); private: struct AugmentationInfo { bool AugmentationDataPresent = false; bool EHDataFieldPresent = false; uint8_t Fields[4] = {0x0, 0x0, 0x0, 0x0}; }; struct CIEInformation { CIEInformation() = default; CIEInformation(Symbol &CIESymbol) : CIESymbol(&CIESymbol) {} Symbol *CIESymbol = nullptr; bool FDEsHaveLSDAField = false; }; struct EdgeTarget { EdgeTarget() = default; EdgeTarget(const Edge &E) : Target(&E.getTarget()), Addend(E.getAddend()) {} Symbol *Target = nullptr; Edge::AddendT Addend = 0; }; using BlockEdgeMap = DenseMap; using CIEInfosMap = DenseMap; struct ParseContext { ParseContext(LinkGraph &G) : G(G) {} Expected findCIEInfo(JITTargetAddress Address) { auto I = CIEInfos.find(Address); if (I == CIEInfos.end()) return make_error("No CIE found at address " + formatv("{0:x16}", Address)); return &I->second; } LinkGraph &G; CIEInfosMap CIEInfos; BlockAddressMap AddrToBlock; SymbolAddressMap AddrToSyms; }; Error processBlock(ParseContext &PC, Block &B); Error processCIE(ParseContext &PC, Block &B, size_t RecordOffset, size_t RecordLength, size_t CIEDeltaFieldOffset); Error processFDE(ParseContext &PC, Block &B, size_t RecordOffset, size_t RecordLength, size_t CIEDeltaFieldOffset, uint32_t CIEDelta, BlockEdgeMap &BlockEdges); Expected parseAugmentationString(BinaryStreamReader &RecordReader); Expected readAbsolutePointer(LinkGraph &G, BinaryStreamReader &RecordReader); Expected getOrCreateSymbol(ParseContext &PC, JITTargetAddress Addr); StringRef EHFrameSectionName; Edge::Kind FDEToCIE; Edge::Kind FDEToPCBegin; Edge::Kind FDEToLSDA; }; } // end namespace jitlink } // end namespace llvm #endif // LLVM_LIB_EXECUTIONENGINE_JITLINK_EHFRAMESUPPORTIMPL_H