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(Val: Address); |
78 | if (I == CIEInfos.end()) |
79 | return make_error<JITLinkError>(Args: "No CIE found at address " + |
80 | formatv(Fmt: "{0:x16}" , Vals&: 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 { |
122 | public: |
123 | (StringRef EHFrameSectionName); |
124 | Error (LinkGraph &G); |
125 | |
126 | private: |
127 | static char []; |
128 | StringRef ; |
129 | }; |
130 | |
131 | } // end namespace jitlink |
132 | } // end namespace llvm |
133 | |
134 | #endif // LLVM_LIB_EXECUTIONENGINE_JITLINK_EHFRAMESUPPORTIMPL_H |
135 | |