xref: /llvm-project/llvm/lib/ExecutionEngine/JITLink/EHFrameSupportImpl.h (revision 9f48bb637eeb40e40bb9e2927ea97b58684ece3a)
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   /// Create an eh-frame edge fixer.
29   /// Adds edges for implicit relocations on platforms where these are used
30   /// (e.g. MachO/x86-64).
31   ///
32   /// If a given edge-kind is not supported on the target architecture then
33   /// Edge::Invalid should be used.
34   EHFrameEdgeFixer(StringRef EHFrameSectionName, unsigned PointerSize,
35                    Edge::Kind Pointer32, Edge::Kind Pointer64,
36                    Edge::Kind Delta32, Edge::Kind Delta64,
37                    Edge::Kind NegDelta32);
38   Error operator()(LinkGraph &G);
39 
40 private:
41 
42   struct AugmentationInfo {
43     bool AugmentationDataPresent = false;
44     bool EHDataFieldPresent = false;
45     uint8_t Fields[4] = {0x0, 0x0, 0x0, 0x0};
46   };
47 
48   struct CIEInformation {
49     CIEInformation() = default;
50     CIEInformation(Symbol &CIESymbol) : CIESymbol(&CIESymbol) {}
51     Symbol *CIESymbol = nullptr;
52     bool AugmentationDataPresent = false;
53     bool LSDAPresent = false;
54     uint8_t LSDAEncoding = 0;
55     uint8_t AddressEncoding = 0;
56   };
57 
58   struct EdgeTarget {
59     EdgeTarget() = default;
60     EdgeTarget(const Edge &E) : Target(&E.getTarget()), Addend(E.getAddend()) {}
61 
62     Symbol *Target = nullptr;
63     Edge::AddendT Addend = 0;
64   };
65 
66   struct BlockEdgesInfo {
67     DenseMap<Edge::OffsetT, EdgeTarget> TargetMap;
68     DenseSet<Edge::OffsetT> Multiple;
69   };
70 
71   using CIEInfosMap = DenseMap<orc::ExecutorAddr, CIEInformation>;
72 
73   struct ParseContext {
74     ParseContext(LinkGraph &G) : G(G) {}
75 
76     Expected<CIEInformation *> findCIEInfo(orc::ExecutorAddr 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     DenseMap<orc::ExecutorAddr, Symbol *> AddrToSym;
88   };
89 
90   Error processBlock(ParseContext &PC, Block &B);
91   Error processCIE(ParseContext &PC, Block &B, size_t CIEDeltaFieldOffset,
92                    const BlockEdgesInfo &BlockEdges);
93   Error processFDE(ParseContext &PC, Block &B, size_t CIEDeltaFieldOffset,
94                    uint32_t CIEDelta, const BlockEdgesInfo &BlockEdges);
95 
96   Expected<AugmentationInfo>
97   parseAugmentationString(BinaryStreamReader &RecordReader);
98 
99   Expected<uint8_t> readPointerEncoding(BinaryStreamReader &RecordReader,
100                                         Block &InBlock, const char *FieldName);
101   Error skipEncodedPointer(uint8_t PointerEncoding,
102                            BinaryStreamReader &RecordReader);
103   Expected<Symbol *> getOrCreateEncodedPointerEdge(
104       ParseContext &PC, const BlockEdgesInfo &BlockEdges,
105       uint8_t PointerEncoding, BinaryStreamReader &RecordReader,
106       Block &BlockToFix, size_t PointerFieldOffset, const char *FieldName);
107 
108   Expected<Symbol &> getOrCreateSymbol(ParseContext &PC,
109                                        orc::ExecutorAddr Addr);
110 
111   StringRef EHFrameSectionName;
112   unsigned PointerSize;
113   Edge::Kind Pointer32;
114   Edge::Kind Pointer64;
115   Edge::Kind Delta32;
116   Edge::Kind Delta64;
117   Edge::Kind NegDelta32;
118 };
119 
120 /// Add a 32-bit null-terminator to the end of the eh-frame section.
121 class EHFrameNullTerminator {
122 public:
123   EHFrameNullTerminator(StringRef EHFrameSectionName);
124   Error operator()(LinkGraph &G);
125 
126 private:
127   static char NullTerminatorBlockContent[];
128   StringRef EHFrameSectionName;
129 };
130 
131 } // end namespace jitlink
132 } // end namespace llvm
133 
134 #endif // LLVM_LIB_EXECUTIONENGINE_JITLINK_EHFRAMESUPPORTIMPL_H
135