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
21namespace llvm {
22namespace jitlink {
23
24/// A LinkGraph pass that adds missing FDE-to-CIE, FDE-to-PC and FDE-to-LSDA
25/// edges.
26class EHFrameEdgeFixer {
27public:
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
40private:
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.
121class EHFrameNullTerminator {
122public:
123 EHFrameNullTerminator(StringRef EHFrameSectionName);
124 Error operator()(LinkGraph &G);
125
126private:
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