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 | /// If a given edge-kind is not supported on the target architecture then |
30 | /// Edge::Invalid should be used. |
31 | EHFrameEdgeFixer(StringRef EHFrameSectionName, unsigned PointerSize, |
32 | Edge::Kind Pointer32, Edge::Kind Pointer64, |
33 | Edge::Kind Delta32, Edge::Kind Delta64, |
34 | Edge::Kind NegDelta32); |
35 | Error operator()(LinkGraph &G); |
36 | |
37 | private: |
38 | |
39 | struct AugmentationInfo { |
40 | bool AugmentationDataPresent = false; |
41 | bool EHDataFieldPresent = false; |
42 | uint8_t Fields[4] = {0x0, 0x0, 0x0, 0x0}; |
43 | }; |
44 | |
45 | struct CIEInformation { |
46 | CIEInformation() = default; |
47 | CIEInformation(Symbol &CIESymbol) : CIESymbol(&CIESymbol) {} |
48 | Symbol *CIESymbol = nullptr; |
49 | bool AugmentationDataPresent = false; |
50 | bool LSDAPresent = false; |
51 | uint8_t LSDAEncoding = 0; |
52 | uint8_t AddressEncoding = 0; |
53 | }; |
54 | |
55 | struct EdgeTarget { |
56 | EdgeTarget() = default; |
57 | EdgeTarget(const Edge &E) : Target(&E.getTarget()), Addend(E.getAddend()) {} |
58 | |
59 | Symbol *Target = nullptr; |
60 | Edge::AddendT Addend = 0; |
61 | }; |
62 | |
63 | struct BlockEdgesInfo { |
64 | DenseMap<Edge::OffsetT, EdgeTarget> TargetMap; |
65 | DenseSet<Edge::OffsetT> Multiple; |
66 | }; |
67 | |
68 | using CIEInfosMap = DenseMap<orc::ExecutorAddr, CIEInformation>; |
69 | |
70 | struct ParseContext { |
71 | ParseContext(LinkGraph &G) : G(G) {} |
72 | |
73 | Expected<CIEInformation *> findCIEInfo(orc::ExecutorAddr Address) { |
74 | auto I = CIEInfos.find(Val: Address); |
75 | if (I == CIEInfos.end()) |
76 | return make_error<JITLinkError>(Args: "No CIE found at address " + |
77 | formatv(Fmt: "{0:x16}" , Vals&: Address)); |
78 | return &I->second; |
79 | } |
80 | |
81 | LinkGraph &G; |
82 | CIEInfosMap CIEInfos; |
83 | BlockAddressMap AddrToBlock; |
84 | DenseMap<orc::ExecutorAddr, Symbol *> AddrToSym; |
85 | }; |
86 | |
87 | Error processBlock(ParseContext &PC, Block &B); |
88 | Error processCIE(ParseContext &PC, Block &B, size_t CIEDeltaFieldOffset, |
89 | const BlockEdgesInfo &BlockEdges); |
90 | Error processFDE(ParseContext &PC, Block &B, size_t CIEDeltaFieldOffset, |
91 | uint32_t CIEDelta, const BlockEdgesInfo &BlockEdges); |
92 | |
93 | Expected<AugmentationInfo> |
94 | parseAugmentationString(BinaryStreamReader &RecordReader); |
95 | |
96 | Expected<uint8_t> readPointerEncoding(BinaryStreamReader &RecordReader, |
97 | Block &InBlock, const char *FieldName); |
98 | Error skipEncodedPointer(uint8_t PointerEncoding, |
99 | BinaryStreamReader &RecordReader); |
100 | Expected<Symbol *> getOrCreateEncodedPointerEdge( |
101 | ParseContext &PC, const BlockEdgesInfo &BlockEdges, |
102 | uint8_t PointerEncoding, BinaryStreamReader &RecordReader, |
103 | Block &BlockToFix, size_t PointerFieldOffset, const char *FieldName); |
104 | |
105 | Expected<Symbol &> getOrCreateSymbol(ParseContext &PC, |
106 | orc::ExecutorAddr Addr); |
107 | |
108 | StringRef EHFrameSectionName; |
109 | unsigned PointerSize; |
110 | Edge::Kind Pointer32; |
111 | Edge::Kind Pointer64; |
112 | Edge::Kind Delta32; |
113 | Edge::Kind Delta64; |
114 | Edge::Kind NegDelta32; |
115 | }; |
116 | |
117 | /// Add a 32-bit null-terminator to the end of the eh-frame section. |
118 | class { |
119 | public: |
120 | (StringRef EHFrameSectionName); |
121 | Error (LinkGraph &G); |
122 | |
123 | private: |
124 | static char []; |
125 | StringRef ; |
126 | }; |
127 | |
128 | } // end namespace jitlink |
129 | } // end namespace llvm |
130 | |
131 | #endif // LLVM_LIB_EXECUTIONENGINE_JITLINK_EHFRAMESUPPORTIMPL_H |
132 | |