Home | History | Annotate | Line # | Download | only in JITLink
      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 splits blocks in an eh-frame section into sub-blocks
     25 /// representing individual eh-frames.
     26 /// EHFrameSplitter should not be run without EHFrameEdgeFixer, which is
     27 /// responsible for adding FDE-to-CIE edges.
     28 class EHFrameSplitter {
     29 public:
     30   EHFrameSplitter(StringRef EHFrameSectionName);
     31   Error operator()(LinkGraph &G);
     32 
     33 private:
     34   Error processBlock(LinkGraph &G, Block &B, LinkGraph::SplitBlockCache &Cache);
     35 
     36   StringRef EHFrameSectionName;
     37 };
     38 
     39 /// A LinkGraph pass that adds missing FDE-to-CIE, FDE-to-PC and FDE-to-LSDA
     40 /// edges.
     41 class EHFrameEdgeFixer {
     42 public:
     43   EHFrameEdgeFixer(StringRef EHFrameSectionName, unsigned PointerSize,
     44                    Edge::Kind Delta64, Edge::Kind Delta32,
     45                    Edge::Kind NegDelta32);
     46   Error operator()(LinkGraph &G);
     47 
     48 private:
     49 
     50   struct AugmentationInfo {
     51     bool AugmentationDataPresent = false;
     52     bool EHDataFieldPresent = false;
     53     uint8_t Fields[4] = {0x0, 0x0, 0x0, 0x0};
     54   };
     55 
     56   struct CIEInformation {
     57     CIEInformation() = default;
     58     CIEInformation(Symbol &CIESymbol) : CIESymbol(&CIESymbol) {}
     59     Symbol *CIESymbol = nullptr;
     60     bool FDEsHaveLSDAField = false;
     61     uint8_t FDEPointerEncoding = 0;
     62     uint8_t LSDAPointerEncoding = 0;
     63   };
     64 
     65   struct EdgeTarget {
     66     EdgeTarget() = default;
     67     EdgeTarget(const Edge &E) : Target(&E.getTarget()), Addend(E.getAddend()) {}
     68 
     69     Symbol *Target = nullptr;
     70     Edge::AddendT Addend = 0;
     71   };
     72 
     73   using BlockEdgeMap = DenseMap<Edge::OffsetT, EdgeTarget>;
     74   using CIEInfosMap = DenseMap<JITTargetAddress, CIEInformation>;
     75 
     76   struct ParseContext {
     77     ParseContext(LinkGraph &G) : G(G) {}
     78 
     79     Expected<CIEInformation *> findCIEInfo(JITTargetAddress Address) {
     80       auto I = CIEInfos.find(Address);
     81       if (I == CIEInfos.end())
     82         return make_error<JITLinkError>("No CIE found at address " +
     83                                         formatv("{0:x16}", Address));
     84       return &I->second;
     85     }
     86 
     87     LinkGraph &G;
     88     CIEInfosMap CIEInfos;
     89     BlockAddressMap AddrToBlock;
     90     SymbolAddressMap AddrToSyms;
     91   };
     92 
     93   Error processBlock(ParseContext &PC, Block &B);
     94   Error processCIE(ParseContext &PC, Block &B, size_t RecordOffset,
     95                    size_t RecordLength, size_t CIEDeltaFieldOffset);
     96   Error processFDE(ParseContext &PC, Block &B, size_t RecordOffset,
     97                    size_t RecordLength, size_t CIEDeltaFieldOffset,
     98                    uint32_t CIEDelta, BlockEdgeMap &BlockEdges);
     99 
    100   Expected<AugmentationInfo>
    101   parseAugmentationString(BinaryStreamReader &RecordReader);
    102 
    103   static bool isSupportedPointerEncoding(uint8_t PointerEncoding);
    104   unsigned getPointerEncodingDataSize(uint8_t PointerEncoding);
    105   Expected<std::pair<JITTargetAddress, Edge::Kind>>
    106   readEncodedPointer(uint8_t PointerEncoding,
    107                      JITTargetAddress PointerFieldAddress,
    108                      BinaryStreamReader &RecordReader);
    109 
    110   Expected<Symbol &> getOrCreateSymbol(ParseContext &PC, JITTargetAddress Addr);
    111 
    112   StringRef EHFrameSectionName;
    113   unsigned PointerSize;
    114   Edge::Kind Delta64;
    115   Edge::Kind Delta32;
    116   Edge::Kind NegDelta32;
    117 };
    118 
    119 /// Add a 32-bit null-terminator to the end of the eh-frame section.
    120 class EHFrameNullTerminator {
    121 public:
    122   EHFrameNullTerminator(StringRef EHFrameSectionName);
    123   Error operator()(LinkGraph &G);
    124 
    125 private:
    126   static char NullTerminatorBlockContent[];
    127   StringRef EHFrameSectionName;
    128 };
    129 
    130 } // end namespace jitlink
    131 } // end namespace llvm
    132 
    133 #endif // LLVM_LIB_EXECUTIONENGINE_JITLINK_EHFRAMESUPPORTIMPL_H
    134