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, Edge::Kind FDEToCIE,
44                    Edge::Kind FDEToPCBegin, Edge::Kind FDEToLSDA);
45   Error operator()(LinkGraph &G);
46 
47 private:
48 
49   struct AugmentationInfo {
50     bool AugmentationDataPresent = false;
51     bool EHDataFieldPresent = false;
52     uint8_t Fields[4] = {0x0, 0x0, 0x0, 0x0};
53   };
54 
55   struct CIEInformation {
56     CIEInformation() = default;
57     CIEInformation(Symbol &CIESymbol) : CIESymbol(&CIESymbol) {}
58     Symbol *CIESymbol = nullptr;
59     bool FDEsHaveLSDAField = false;
60   };
61 
62   struct EdgeTarget {
63     EdgeTarget() = default;
64     EdgeTarget(const Edge &E) : Target(&E.getTarget()), Addend(E.getAddend()) {}
65 
66     Symbol *Target = nullptr;
67     Edge::AddendT Addend = 0;
68   };
69 
70   using BlockEdgeMap = DenseMap<Edge::OffsetT, EdgeTarget>;
71   using CIEInfosMap = DenseMap<JITTargetAddress, CIEInformation>;
72 
73   struct ParseContext {
74     ParseContext(LinkGraph &G) : G(G) {}
75 
76     Expected<CIEInformation *> findCIEInfo(JITTargetAddress Address) {
77       auto I = CIEInfos.find(Address);
78       if (I == CIEInfos.end())
79         return make_error<JITLinkError>("No CIE found at address " +
80                                         formatv("{0:x16}", Address));
81       return &I->second;
82     }
83 
84     LinkGraph &G;
85     CIEInfosMap CIEInfos;
86     BlockAddressMap AddrToBlock;
87     SymbolAddressMap AddrToSyms;
88   };
89 
90   Error processBlock(ParseContext &PC, Block &B);
91   Error processCIE(ParseContext &PC, Block &B, size_t RecordOffset,
92                    size_t RecordLength, size_t CIEDeltaFieldOffset);
93   Error processFDE(ParseContext &PC, Block &B, size_t RecordOffset,
94                    size_t RecordLength, size_t CIEDeltaFieldOffset,
95                    uint32_t CIEDelta, BlockEdgeMap &BlockEdges);
96 
97   Expected<AugmentationInfo>
98   parseAugmentationString(BinaryStreamReader &RecordReader);
99   Expected<JITTargetAddress>
100   readAbsolutePointer(LinkGraph &G, BinaryStreamReader &RecordReader);
101   Expected<Symbol &> getOrCreateSymbol(ParseContext &PC, JITTargetAddress Addr);
102 
103   StringRef EHFrameSectionName;
104   Edge::Kind FDEToCIE;
105   Edge::Kind FDEToPCBegin;
106   Edge::Kind FDEToLSDA;
107 };
108 
109 } // end namespace jitlink
110 } // end namespace llvm
111 
112 #endif // LLVM_LIB_EXECUTIONENGINE_JITLINK_EHFRAMESUPPORTIMPL_H
113