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