Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
freebsd
GitHub Repository: freebsd/freebsd-src
Path: blob/main/contrib/llvm-project/llvm/lib/ExecutionEngine/JITLink/COFFLinkGraphBuilder.h
35271 views
1
//===----- COFFLinkGraphBuilder.h - COFF LinkGraph builder ----*- 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
// Generic COFF LinkGraph building code.
10
//
11
//===----------------------------------------------------------------------===//
12
13
#ifndef LIB_EXECUTIONENGINE_JITLINK_COFFLINKGRAPHBUILDER_H
14
#define LIB_EXECUTIONENGINE_JITLINK_COFFLINKGRAPHBUILDER_H
15
16
#include "llvm/ADT/DenseMap.h"
17
#include "llvm/ExecutionEngine/JITLink/JITLink.h"
18
#include "llvm/Object/COFF.h"
19
20
#include "COFFDirectiveParser.h"
21
#include "EHFrameSupportImpl.h"
22
#include "JITLinkGeneric.h"
23
24
#define DEBUG_TYPE "jitlink"
25
26
#include <list>
27
28
namespace llvm {
29
namespace jitlink {
30
31
class COFFLinkGraphBuilder {
32
public:
33
virtual ~COFFLinkGraphBuilder();
34
Expected<std::unique_ptr<LinkGraph>> buildGraph();
35
36
protected:
37
using COFFSectionIndex = int32_t;
38
using COFFSymbolIndex = int32_t;
39
40
COFFLinkGraphBuilder(const object::COFFObjectFile &Obj, Triple TT,
41
SubtargetFeatures Features,
42
LinkGraph::GetEdgeKindNameFunction GetEdgeKindName);
43
44
LinkGraph &getGraph() const { return *G; }
45
46
const object::COFFObjectFile &getObject() const { return Obj; }
47
48
virtual Error addRelocations() = 0;
49
50
Error graphifySections();
51
Error graphifySymbols();
52
53
void setGraphSymbol(COFFSectionIndex SecIndex, COFFSymbolIndex SymIndex,
54
Symbol &Sym) {
55
assert(!GraphSymbols[SymIndex] && "Duplicate symbol at index");
56
GraphSymbols[SymIndex] = &Sym;
57
if (!COFF::isReservedSectionNumber(SecIndex))
58
SymbolSets[SecIndex].insert({Sym.getOffset(), &Sym});
59
}
60
61
Symbol *getGraphSymbol(COFFSymbolIndex SymIndex) const {
62
if (SymIndex < 0 ||
63
SymIndex >= static_cast<COFFSymbolIndex>(GraphSymbols.size()))
64
return nullptr;
65
return GraphSymbols[SymIndex];
66
}
67
68
void setGraphBlock(COFFSectionIndex SecIndex, Block *B) {
69
assert(!GraphBlocks[SecIndex] && "Duplicate section at index");
70
assert(!COFF::isReservedSectionNumber(SecIndex) && "Invalid section index");
71
GraphBlocks[SecIndex] = B;
72
}
73
74
Block *getGraphBlock(COFFSectionIndex SecIndex) const {
75
if (SecIndex <= 0 ||
76
SecIndex >= static_cast<COFFSectionIndex>(GraphSymbols.size()))
77
return nullptr;
78
return GraphBlocks[SecIndex];
79
}
80
81
object::COFFObjectFile::section_iterator_range sections() const {
82
return Obj.sections();
83
}
84
85
/// Traverse all matching relocation records in the given section. The handler
86
/// function Func should be callable with this signature:
87
/// Error(const object::RelocationRef&,
88
/// const object::SectionRef&, Section &)
89
///
90
template <typename RelocHandlerFunction>
91
Error forEachRelocation(const object::SectionRef &RelSec,
92
RelocHandlerFunction &&Func,
93
bool ProcessDebugSections = false);
94
95
/// Traverse all matching relocation records in the given section. Convenience
96
/// wrapper to allow passing a member function for the handler.
97
///
98
template <typename ClassT, typename RelocHandlerMethod>
99
Error forEachRelocation(const object::SectionRef &RelSec, ClassT *Instance,
100
RelocHandlerMethod &&Method,
101
bool ProcessDebugSections = false) {
102
return forEachRelocation(
103
RelSec,
104
[Instance, Method](const auto &Rel, const auto &Target, auto &GS) {
105
return (Instance->*Method)(Rel, Target, GS);
106
},
107
ProcessDebugSections);
108
}
109
110
private:
111
// Pending comdat symbol export that is initiated by the first symbol of
112
// COMDAT sequence.
113
struct ComdatExportRequest {
114
COFFSymbolIndex SymbolIndex;
115
jitlink::Linkage Linkage;
116
orc::ExecutorAddrDiff Size;
117
};
118
std::vector<std::optional<ComdatExportRequest>> PendingComdatExports;
119
120
// This represents a pending request to create a weak external symbol with a
121
// name.
122
struct WeakExternalRequest {
123
COFFSymbolIndex Alias;
124
COFFSymbolIndex Target;
125
uint32_t Characteristics;
126
StringRef SymbolName;
127
};
128
std::vector<WeakExternalRequest> WeakExternalRequests;
129
130
// Per COFF section jitlink symbol set sorted by offset.
131
// Used for calculating implicit size of defined symbols.
132
using SymbolSet = std::set<std::pair<orc::ExecutorAddrDiff, Symbol *>>;
133
std::vector<SymbolSet> SymbolSets;
134
135
Section &getCommonSection();
136
137
Symbol *createExternalSymbol(COFFSymbolIndex SymIndex, StringRef SymbolName,
138
object::COFFSymbolRef Symbol,
139
const object::coff_section *Section);
140
Expected<Symbol *> createAliasSymbol(StringRef SymbolName, Linkage L, Scope S,
141
Symbol &Target);
142
Expected<Symbol *> createDefinedSymbol(COFFSymbolIndex SymIndex,
143
StringRef SymbolName,
144
object::COFFSymbolRef Symbol,
145
const object::coff_section *Section);
146
Expected<Symbol *> createCOMDATExportRequest(
147
COFFSymbolIndex SymIndex, object::COFFSymbolRef Symbol,
148
const object::coff_aux_section_definition *Definition);
149
Expected<Symbol *> exportCOMDATSymbol(COFFSymbolIndex SymIndex,
150
StringRef SymbolName,
151
object::COFFSymbolRef Symbol);
152
153
Error handleDirectiveSection(StringRef Str);
154
Error flushWeakAliasRequests();
155
Error handleAlternateNames();
156
Error calculateImplicitSizeOfSymbols();
157
158
static uint64_t getSectionAddress(const object::COFFObjectFile &Obj,
159
const object::coff_section *Section);
160
static uint64_t getSectionSize(const object::COFFObjectFile &Obj,
161
const object::coff_section *Section);
162
static bool isComdatSection(const object::coff_section *Section);
163
static unsigned getPointerSize(const object::COFFObjectFile &Obj);
164
static llvm::endianness getEndianness(const object::COFFObjectFile &Obj);
165
static StringRef getDLLImportStubPrefix() { return "__imp_"; }
166
static StringRef getDirectiveSectionName() { return ".drectve"; }
167
StringRef getCOFFSectionName(COFFSectionIndex SectionIndex,
168
const object::coff_section *Sec,
169
object::COFFSymbolRef Sym);
170
171
const object::COFFObjectFile &Obj;
172
std::unique_ptr<LinkGraph> G;
173
COFFDirectiveParser DirectiveParser;
174
175
Section *CommonSection = nullptr;
176
std::vector<Block *> GraphBlocks;
177
std::vector<Symbol *> GraphSymbols;
178
179
DenseMap<StringRef, StringRef> AlternateNames;
180
DenseMap<StringRef, Symbol *> ExternalSymbols;
181
DenseMap<StringRef, Symbol *> DefinedSymbols;
182
};
183
184
template <typename RelocHandlerFunction>
185
Error COFFLinkGraphBuilder::forEachRelocation(const object::SectionRef &RelSec,
186
RelocHandlerFunction &&Func,
187
bool ProcessDebugSections) {
188
189
auto COFFRelSect = Obj.getCOFFSection(RelSec);
190
191
// Target sections have names in valid COFF object files.
192
Expected<StringRef> Name = Obj.getSectionName(COFFRelSect);
193
if (!Name)
194
return Name.takeError();
195
196
// Skip the unhandled metadata sections.
197
if (*Name == ".voltbl")
198
return Error::success();
199
LLVM_DEBUG(dbgs() << " " << *Name << ":\n");
200
201
// Lookup the link-graph node corresponding to the target section name.
202
auto *BlockToFix = getGraphBlock(RelSec.getIndex() + 1);
203
if (!BlockToFix)
204
return make_error<StringError>(
205
"Referencing a section that wasn't added to the graph: " + *Name,
206
inconvertibleErrorCode());
207
208
// Let the callee process relocation entries one by one.
209
for (const auto &R : RelSec.relocations())
210
if (Error Err = Func(R, RelSec, *BlockToFix))
211
return Err;
212
213
LLVM_DEBUG(dbgs() << "\n");
214
return Error::success();
215
}
216
217
} // end namespace jitlink
218
} // end namespace llvm
219
220
#endif // LIB_EXECUTIONENGINE_JITLINK_COFFLINKGRAPHBUILDER_H
221
222