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