clang -cc1 -cc1 -triple amd64-unknown-openbsd7.0 -analyze -disable-free -disable-llvm-verifier -discard-value-names -main-file-name JITLink.cpp -analyzer-store=region -analyzer-opt-analyze-nested-blocks -analyzer-checker=core -analyzer-checker=apiModeling -analyzer-checker=unix -analyzer-checker=deadcode -analyzer-checker=cplusplus -analyzer-checker=security.insecureAPI.UncheckedReturn -analyzer-checker=security.insecureAPI.getpw -analyzer-checker=security.insecureAPI.gets -analyzer-checker=security.insecureAPI.mktemp -analyzer-checker=security.insecureAPI.mkstemp -analyzer-checker=security.insecureAPI.vfork -analyzer-checker=nullability.NullPassedToNonnull -analyzer-checker=nullability.NullReturnedFromNonnull -analyzer-output plist -w -setup-static-analyzer -mrelocation-model static -mframe-pointer=all -relaxed-aliasing -fno-rounding-math -mconstructor-aliases -munwind-tables -target-cpu x86-64 -tune-cpu generic -debugger-tuning=gdb -fcoverage-compilation-dir=/usr/src/gnu/usr.bin/clang/libLLVM/obj -resource-dir /usr/local/lib/clang/13.0.0 -I /usr/src/gnu/usr.bin/clang/libLLVM/../../../llvm/llvm/include/llvm/Transforms -I /usr/src/gnu/usr.bin/clang/libLLVM/obj/../include/llvm/AMDGPU -I /usr/src/gnu/usr.bin/clang/libLLVM/../../../llvm/llvm/lib/Target/AMDGPU -I /usr/src/gnu/usr.bin/clang/libLLVM/obj/../include/llvm/AMDGPU -I /usr/src/gnu/usr.bin/clang/libLLVM/../../../llvm/llvm/lib/Target/AMDGPU -I /usr/src/gnu/usr.bin/clang/libLLVM/obj/../include/llvm/AMDGPU -I /usr/src/gnu/usr.bin/clang/libLLVM/../../../llvm/llvm/lib/Target/AMDGPU -I /usr/src/gnu/usr.bin/clang/libLLVM/obj/../include/llvm/AMDGPU -I /usr/src/gnu/usr.bin/clang/libLLVM/../../../llvm/llvm/lib/Target/AMDGPU -I /usr/src/gnu/usr.bin/clang/libLLVM/obj/../include/llvm/AMDGPU -I /usr/src/gnu/usr.bin/clang/libLLVM/../../../llvm/llvm/lib/Target/AMDGPU -I /usr/src/gnu/usr.bin/clang/libLLVM/obj/../include/llvm/AMDGPU -I /usr/src/gnu/usr.bin/clang/libLLVM/../../../llvm/llvm/lib/Target/AMDGPU -I /usr/src/gnu/usr.bin/clang/libLLVM/../../../llvm/llvm/include/llvm/Analysis -I /usr/src/gnu/usr.bin/clang/libLLVM/../../../llvm/llvm/include/llvm/ASMParser -I /usr/src/gnu/usr.bin/clang/libLLVM/../../../llvm/llvm/include/llvm/BinaryFormat -I /usr/src/gnu/usr.bin/clang/libLLVM/../../../llvm/llvm/include/llvm/Bitcode -I /usr/src/gnu/usr.bin/clang/libLLVM/../../../llvm/llvm/include/llvm/Bitcode -I /usr/src/gnu/usr.bin/clang/libLLVM/../../../llvm/llvm/include/llvm/Bitstream -I /usr/src/gnu/usr.bin/clang/libLLVM/../../../llvm/llvm/include/llvm/Transforms -I /include/llvm/CodeGen -I /include/llvm/CodeGen/PBQP -I /usr/src/gnu/usr.bin/clang/libLLVM/obj/../include/llvm/IR -I /usr/src/gnu/usr.bin/clang/libLLVM/../../../llvm/llvm/include/llvm/IR -I /usr/src/gnu/usr.bin/clang/libLLVM/../../../llvm/llvm/include/llvm/Transforms -I /usr/src/gnu/usr.bin/clang/libLLVM/../../../llvm/llvm/include/llvm/Transforms/Coroutines -I /usr/src/gnu/usr.bin/clang/libLLVM/../../../llvm/llvm/include/llvm/ProfileData/Coverage -I /usr/src/gnu/usr.bin/clang/libLLVM/../../../llvm/llvm/include/llvm/DebugInfo/CodeView -I /usr/src/gnu/usr.bin/clang/libLLVM/../../../llvm/llvm/include/llvm/DebugInfo/DWARF -I /usr/src/gnu/usr.bin/clang/libLLVM/../../../llvm/llvm/include/llvm/DebugInfo -I /usr/src/gnu/usr.bin/clang/libLLVM/../../../llvm/llvm/include/llvm/DebugInfo/MSF -I /usr/src/gnu/usr.bin/clang/libLLVM/../../../llvm/llvm/include/llvm/DebugInfo/PDB -I /usr/src/gnu/usr.bin/clang/libLLVM/../../../llvm/llvm/include/llvm/Demangle -I /usr/src/gnu/usr.bin/clang/libLLVM/../../../llvm/llvm/include/llvm/ExecutionEngine -I /usr/src/gnu/usr.bin/clang/libLLVM/../../../llvm/llvm/include/llvm/ExecutionEngine/JITLink -I /usr/src/gnu/usr.bin/clang/libLLVM/../../../llvm/llvm/include/llvm/ExecutionEngine/Orc -I /usr/src/gnu/usr.bin/clang/libLLVM/../../../llvm/llvm/include/llvm/Frontend -I /usr/src/gnu/usr.bin/clang/libLLVM/../../../llvm/llvm/include/llvm/Frontend/OpenACC -I /usr/src/gnu/usr.bin/clang/libLLVM/../../../llvm/llvm/include/llvm/Frontend -I /usr/src/gnu/usr.bin/clang/libLLVM/../../../llvm/llvm/include/llvm/Frontend/OpenMP -I /include/llvm/CodeGen/GlobalISel -I /usr/src/gnu/usr.bin/clang/libLLVM/../../../llvm/llvm/include/llvm/IRReader -I /usr/src/gnu/usr.bin/clang/libLLVM/../../../llvm/llvm/include/llvm/Transforms -I /usr/src/gnu/usr.bin/clang/libLLVM/../../../llvm/llvm/include/llvm/Transforms/InstCombine -I /usr/src/gnu/usr.bin/clang/libLLVM/obj/../include/llvm/Transforms/InstCombine -I /usr/src/gnu/usr.bin/clang/libLLVM/../../../llvm/llvm/include/llvm/Transforms -I /usr/src/gnu/usr.bin/clang/libLLVM/../../../llvm/llvm/include/llvm/LTO -I /usr/src/gnu/usr.bin/clang/libLLVM/../../../llvm/llvm/include/llvm/Linker -I /usr/src/gnu/usr.bin/clang/libLLVM/../../../llvm/llvm/include/llvm/MC -I /usr/src/gnu/usr.bin/clang/libLLVM/../../../llvm/llvm/include/llvm/MC/MCParser -I /include/llvm/CodeGen/MIRParser -I /usr/src/gnu/usr.bin/clang/libLLVM/../../../llvm/llvm/include/llvm/Transforms -I /usr/src/gnu/usr.bin/clang/libLLVM/../../../llvm/llvm/include/llvm/Object -I /usr/src/gnu/usr.bin/clang/libLLVM/../../../llvm/llvm/include/llvm/Option -I /usr/src/gnu/usr.bin/clang/libLLVM/../../../llvm/llvm/include/llvm/Passes -I /usr/src/gnu/usr.bin/clang/libLLVM/../../../llvm/llvm/include/llvm/ -I /usr/src/gnu/usr.bin/clang/libLLVM/../../../llvm/llvm/include/llvm/ProfileData -I /usr/src/gnu/usr.bin/clang/libLLVM/../../../llvm/llvm/include/llvm/Transforms -I /usr/src/gnu/usr.bin/clang/libLLVM/../../../llvm/llvm/include/llvm/Transforms/Scalar -I /usr/src/gnu/usr.bin/clang/libLLVM/../../../llvm/llvm/include/llvm/ADT -I /usr/src/gnu/usr.bin/clang/libLLVM/../../../llvm/llvm/include/llvm/Support -I /usr/src/gnu/usr.bin/clang/libLLVM/../../../llvm/llvm/include/llvm/DebugInfo/Symbolize -I /usr/src/gnu/usr.bin/clang/libLLVM/../../../llvm/llvm/include/llvm/Target -I /usr/src/gnu/usr.bin/clang/libLLVM/../../../llvm/llvm/include/llvm/Transforms -I /usr/src/gnu/usr.bin/clang/libLLVM/../../../llvm/llvm/include/llvm/Transforms/Utils -I /usr/src/gnu/usr.bin/clang/libLLVM/../../../llvm/llvm/include/llvm/Transforms -I /usr/src/gnu/usr.bin/clang/libLLVM/../../../llvm/llvm/include/llvm/Transforms/Vectorize -I /usr/src/gnu/usr.bin/clang/libLLVM/obj/../include/llvm/X86 -I /usr/src/gnu/usr.bin/clang/libLLVM/../../../llvm/llvm/lib/Target/X86 -I /usr/src/gnu/usr.bin/clang/libLLVM/obj/../include/llvm/X86 -I /usr/src/gnu/usr.bin/clang/libLLVM/../../../llvm/llvm/lib/Target/X86 -I /usr/src/gnu/usr.bin/clang/libLLVM/obj/../include/llvm/X86 -I /usr/src/gnu/usr.bin/clang/libLLVM/../../../llvm/llvm/lib/Target/X86 -I /usr/src/gnu/usr.bin/clang/libLLVM/obj/../include/llvm/X86 -I /usr/src/gnu/usr.bin/clang/libLLVM/../../../llvm/llvm/lib/Target/X86 -I /usr/src/gnu/usr.bin/clang/libLLVM/obj/../include/llvm/X86 -I /usr/src/gnu/usr.bin/clang/libLLVM/../../../llvm/llvm/lib/Target/X86 -I /usr/src/gnu/usr.bin/clang/libLLVM/../../../llvm/llvm/include/llvm/Transforms -I /usr/src/gnu/usr.bin/clang/libLLVM/../../../llvm/llvm/include/llvm/Transforms/IPO -I /usr/src/gnu/usr.bin/clang/libLLVM/../../../llvm/llvm/include -I /usr/src/gnu/usr.bin/clang/libLLVM/../include -I /usr/src/gnu/usr.bin/clang/libLLVM/obj -I /usr/src/gnu/usr.bin/clang/libLLVM/obj/../include -D NDEBUG -D __STDC_LIMIT_MACROS -D __STDC_CONSTANT_MACROS -D __STDC_FORMAT_MACROS -D LLVM_PREFIX="/usr" -internal-isystem /usr/include/c++/v1 -internal-isystem /usr/local/lib/clang/13.0.0/include -internal-externc-isystem /usr/include -O2 -Wno-unused-parameter -Wwrite-strings -Wno-missing-field-initializers -Wno-long-long -Wno-comment -std=c++14 -fdeprecated-macro -fdebug-compilation-dir=/usr/src/gnu/usr.bin/clang/libLLVM/obj -ferror-limit 19 -fvisibility-inlines-hidden -fwrapv -stack-protector 2 -fno-rtti -fgnuc-version=4.2.1 -vectorize-loops -vectorize-slp -fno-builtin-malloc -fno-builtin-calloc -fno-builtin-realloc -fno-builtin-valloc -fno-builtin-free -fno-builtin-strdup -fno-builtin-strndup -analyzer-output=html -faddrsig -D__GCC_HAVE_DWARF2_CFI_ASM=1 -o /home/ben/Projects/vmm/scan-build/2022-01-12-194120-40624-1 -x c++ /usr/src/gnu/usr.bin/clang/libLLVM/../../../llvm/llvm/lib/ExecutionEngine/JITLink/JITLink.cpp
1 | |
2 | |
3 | |
4 | |
5 | |
6 | |
7 | |
8 | |
9 | |
10 | #include "llvm/ExecutionEngine/JITLink/JITLink.h" |
11 | |
12 | #include "llvm/BinaryFormat/Magic.h" |
13 | #include "llvm/ExecutionEngine/JITLink/ELF.h" |
14 | #include "llvm/ExecutionEngine/JITLink/MachO.h" |
15 | #include "llvm/Support/Format.h" |
16 | #include "llvm/Support/ManagedStatic.h" |
17 | #include "llvm/Support/MemoryBuffer.h" |
18 | #include "llvm/Support/raw_ostream.h" |
19 | |
20 | using namespace llvm; |
21 | using namespace llvm::object; |
22 | |
23 | #define DEBUG_TYPE "jitlink" |
24 | |
25 | namespace { |
26 | |
27 | enum JITLinkErrorCode { GenericJITLinkError = 1 }; |
28 | |
29 | |
30 | |
31 | |
32 | class JITLinkerErrorCategory : public std::error_category { |
33 | public: |
34 | const char *name() const noexcept override { return "runtimedyld"; } |
35 | |
36 | std::string message(int Condition) const override { |
37 | switch (static_cast<JITLinkErrorCode>(Condition)) { |
38 | case GenericJITLinkError: |
39 | return "Generic JITLink error"; |
40 | } |
41 | llvm_unreachable("Unrecognized JITLinkErrorCode"); |
42 | } |
43 | }; |
44 | |
45 | static ManagedStatic<JITLinkerErrorCategory> JITLinkerErrorCategory; |
46 | |
47 | } |
48 | |
49 | namespace llvm { |
50 | namespace jitlink { |
51 | |
52 | char JITLinkError::ID = 0; |
53 | |
54 | void JITLinkError::log(raw_ostream &OS) const { OS << ErrMsg; } |
55 | |
56 | std::error_code JITLinkError::convertToErrorCode() const { |
57 | return std::error_code(GenericJITLinkError, *JITLinkerErrorCategory); |
58 | } |
59 | |
60 | const char *getGenericEdgeKindName(Edge::Kind K) { |
61 | switch (K) { |
62 | case Edge::Invalid: |
63 | return "INVALID RELOCATION"; |
64 | case Edge::KeepAlive: |
65 | return "Keep-Alive"; |
66 | default: |
67 | return "<Unrecognized edge kind>"; |
68 | } |
69 | } |
70 | |
71 | const char *getLinkageName(Linkage L) { |
72 | switch (L) { |
73 | case Linkage::Strong: |
74 | return "strong"; |
75 | case Linkage::Weak: |
76 | return "weak"; |
77 | } |
78 | llvm_unreachable("Unrecognized llvm.jitlink.Linkage enum"); |
79 | } |
80 | |
81 | const char *getScopeName(Scope S) { |
82 | switch (S) { |
83 | case Scope::Default: |
84 | return "default"; |
85 | case Scope::Hidden: |
86 | return "hidden"; |
87 | case Scope::Local: |
88 | return "local"; |
89 | } |
90 | llvm_unreachable("Unrecognized llvm.jitlink.Scope enum"); |
91 | } |
92 | |
93 | raw_ostream &operator<<(raw_ostream &OS, const Block &B) { |
94 | return OS << formatv("{0:x16}", B.getAddress()) << " -- " |
95 | << formatv("{0:x8}", B.getAddress() + B.getSize()) << ": " |
96 | << "size = " << formatv("{0:x8}", B.getSize()) << ", " |
97 | << (B.isZeroFill() ? "zero-fill" : "content") |
98 | << ", align = " << B.getAlignment() |
99 | << ", align-ofs = " << B.getAlignmentOffset() |
100 | << ", section = " << B.getSection().getName(); |
101 | } |
102 | |
103 | raw_ostream &operator<<(raw_ostream &OS, const Symbol &Sym) { |
104 | OS << formatv("{0:x16}", Sym.getAddress()) << " (" |
105 | << (Sym.isDefined() ? "block" : "addressable") << " + " |
106 | << formatv("{0:x8}", Sym.getOffset()) |
107 | << "): size: " << formatv("{0:x8}", Sym.getSize()) |
108 | << ", linkage: " << formatv("{0:6}", getLinkageName(Sym.getLinkage())) |
109 | << ", scope: " << formatv("{0:8}", getScopeName(Sym.getScope())) << ", " |
110 | << (Sym.isLive() ? "live" : "dead") << " - " |
111 | << (Sym.hasName() ? Sym.getName() : "<anonymous symbol>"); |
112 | return OS; |
113 | } |
114 | |
115 | void printEdge(raw_ostream &OS, const Block &B, const Edge &E, |
116 | StringRef EdgeKindName) { |
117 | OS << "edge@" << formatv("{0:x16}", B.getAddress() + E.getOffset()) << ": " |
118 | << formatv("{0:x16}", B.getAddress()) << " + " |
119 | << formatv("{0:x}", E.getOffset()) << " -- " << EdgeKindName << " -> "; |
120 | |
121 | auto &TargetSym = E.getTarget(); |
122 | if (TargetSym.hasName()) |
123 | OS << TargetSym.getName(); |
124 | else { |
125 | auto &TargetBlock = TargetSym.getBlock(); |
126 | auto &TargetSec = TargetBlock.getSection(); |
127 | JITTargetAddress SecAddress = ~JITTargetAddress(0); |
128 | for (auto *B : TargetSec.blocks()) |
129 | if (B->getAddress() < SecAddress) |
130 | SecAddress = B->getAddress(); |
131 | |
132 | JITTargetAddress SecDelta = TargetSym.getAddress() - SecAddress; |
133 | OS << formatv("{0:x16}", TargetSym.getAddress()) << " (section " |
134 | << TargetSec.getName(); |
135 | if (SecDelta) |
136 | OS << " + " << formatv("{0:x}", SecDelta); |
137 | OS << " / block " << formatv("{0:x16}", TargetBlock.getAddress()); |
138 | if (TargetSym.getOffset()) |
139 | OS << " + " << formatv("{0:x}", TargetSym.getOffset()); |
140 | OS << ")"; |
141 | } |
142 | |
143 | if (E.getAddend() != 0) |
144 | OS << " + " << E.getAddend(); |
145 | } |
146 | |
147 | Section::~Section() { |
148 | for (auto *Sym : Symbols) |
149 | Sym->~Symbol(); |
150 | for (auto *B : Blocks) |
151 | B->~Block(); |
152 | } |
153 | |
154 | Block &LinkGraph::splitBlock(Block &B, size_t SplitIndex, |
155 | SplitBlockCache *Cache) { |
156 | |
157 | assert(SplitIndex > 0 && "splitBlock can not be called with SplitIndex == 0"); |
158 | |
159 | |
160 | if (SplitIndex == B.getSize()) |
| 1 | Assuming the condition is false | |
|
| |
161 | return B; |
162 | |
163 | assert(SplitIndex < B.getSize() && "SplitIndex out of range"); |
164 | |
165 | |
166 | auto &NewBlock = |
167 | B.isZeroFill() |
| |
168 | ? createZeroFillBlock(B.getSection(), SplitIndex, B.getAddress(), |
169 | B.getAlignment(), B.getAlignmentOffset()) |
170 | : createContentBlock( |
171 | B.getSection(), B.getContent().slice(0, SplitIndex), |
172 | B.getAddress(), B.getAlignment(), B.getAlignmentOffset()); |
173 | |
174 | |
175 | B.setAddress(B.getAddress() + SplitIndex); |
176 | B.setContent(B.getContent().slice(SplitIndex)); |
177 | B.setAlignmentOffset((B.getAlignmentOffset() + SplitIndex) % |
| |
178 | B.getAlignment()); |
| 4 | | Calling 'Block::getAlignment' | |
|
| 6 | | Returning from 'Block::getAlignment' | |
|
179 | |
180 | |
181 | { |
182 | |
183 | |
184 | std::vector<Block::edge_iterator> EdgesToRemove; |
185 | for (auto I = B.edges().begin(); I != B.edges().end();) { |
186 | if (I->getOffset() < SplitIndex) { |
187 | NewBlock.addEdge(*I); |
188 | I = B.removeEdge(I); |
189 | } else { |
190 | I->setOffset(I->getOffset() - SplitIndex); |
191 | ++I; |
192 | } |
193 | } |
194 | } |
195 | |
196 | |
197 | { |
198 | |
199 | SplitBlockCache LocalBlockSymbolsCache; |
200 | if (!Cache) |
201 | Cache = &LocalBlockSymbolsCache; |
202 | if (*Cache == None) { |
203 | *Cache = SplitBlockCache::value_type(); |
204 | for (auto *Sym : B.getSection().symbols()) |
205 | if (&Sym->getBlock() == &B) |
206 | (*Cache)->push_back(Sym); |
207 | |
208 | llvm::sort(**Cache, [](const Symbol *LHS, const Symbol *RHS) { |
209 | return LHS->getOffset() > RHS->getOffset(); |
210 | }); |
211 | } |
212 | auto &BlockSymbols = **Cache; |
213 | |
214 | |
215 | while (!BlockSymbols.empty() && |
216 | BlockSymbols.back()->getOffset() < SplitIndex) { |
217 | BlockSymbols.back()->setBlock(NewBlock); |
218 | BlockSymbols.pop_back(); |
219 | } |
220 | |
221 | |
222 | for (auto *Sym : BlockSymbols) |
223 | Sym->setOffset(Sym->getOffset() - SplitIndex); |
224 | } |
225 | |
226 | return NewBlock; |
227 | } |
228 | |
229 | void LinkGraph::dump(raw_ostream &OS) { |
230 | DenseMap<Block *, std::vector<Symbol *>> BlockSymbols; |
231 | |
232 | |
233 | for (auto *Sym : defined_symbols()) |
234 | BlockSymbols[&Sym->getBlock()].push_back(Sym); |
235 | |
236 | |
237 | |
238 | for (auto &KV : BlockSymbols) |
239 | llvm::sort(KV.second, [](const Symbol *LHS, const Symbol *RHS) { |
240 | if (LHS->getOffset() != RHS->getOffset()) |
241 | return LHS->getOffset() < RHS->getOffset(); |
242 | if (LHS->getLinkage() != RHS->getLinkage()) |
243 | return LHS->getLinkage() < RHS->getLinkage(); |
244 | if (LHS->getScope() != RHS->getScope()) |
245 | return LHS->getScope() < RHS->getScope(); |
246 | if (LHS->hasName()) { |
247 | if (!RHS->hasName()) |
248 | return true; |
249 | return LHS->getName() < RHS->getName(); |
250 | } |
251 | return false; |
252 | }); |
253 | |
254 | for (auto &Sec : sections()) { |
255 | OS << "section " << Sec.getName() << ":\n\n"; |
256 | |
257 | std::vector<Block *> SortedBlocks; |
258 | llvm::copy(Sec.blocks(), std::back_inserter(SortedBlocks)); |
259 | llvm::sort(SortedBlocks, [](const Block *LHS, const Block *RHS) { |
260 | return LHS->getAddress() < RHS->getAddress(); |
261 | }); |
262 | |
263 | for (auto *B : SortedBlocks) { |
264 | OS << " block " << formatv("{0:x16}", B->getAddress()) |
265 | << " size = " << formatv("{0:x8}", B->getSize()) |
266 | << ", align = " << B->getAlignment() |
267 | << ", alignment-offset = " << B->getAlignmentOffset(); |
268 | if (B->isZeroFill()) |
269 | OS << ", zero-fill"; |
270 | OS << "\n"; |
271 | |
272 | auto BlockSymsI = BlockSymbols.find(B); |
273 | if (BlockSymsI != BlockSymbols.end()) { |
274 | OS << " symbols:\n"; |
275 | auto &Syms = BlockSymsI->second; |
276 | for (auto *Sym : Syms) |
277 | OS << " " << *Sym << "\n"; |
278 | } else |
279 | OS << " no symbols\n"; |
280 | |
281 | if (!B->edges_empty()) { |
282 | OS << " edges:\n"; |
283 | std::vector<Edge> SortedEdges; |
284 | llvm::copy(B->edges(), std::back_inserter(SortedEdges)); |
285 | llvm::sort(SortedEdges, [](const Edge &LHS, const Edge &RHS) { |
286 | return LHS.getOffset() < RHS.getOffset(); |
287 | }); |
288 | for (auto &E : SortedEdges) { |
289 | OS << " " << formatv("{0:x16}", B->getFixupAddress(E)) |
290 | << " (block + " << formatv("{0:x8}", E.getOffset()) |
291 | << "), addend = "; |
292 | if (E.getAddend() >= 0) |
293 | OS << formatv("+{0:x8}", E.getAddend()); |
294 | else |
295 | OS << formatv("-{0:x8}", -E.getAddend()); |
296 | OS << ", kind = " << getEdgeKindName(E.getKind()) << ", target = "; |
297 | if (E.getTarget().hasName()) |
298 | OS << E.getTarget().getName(); |
299 | else |
300 | OS << "addressable@" |
301 | << formatv("{0:x16}", E.getTarget().getAddress()) << "+" |
302 | << formatv("{0:x8}", E.getTarget().getOffset()); |
303 | OS << "\n"; |
304 | } |
305 | } else |
306 | OS << " no edges\n"; |
307 | OS << "\n"; |
308 | } |
309 | } |
310 | |
311 | OS << "Absolute symbols:\n"; |
312 | if (!llvm::empty(absolute_symbols())) { |
313 | for (auto *Sym : absolute_symbols()) |
314 | OS << " " << format("0x%016" PRIx64, Sym->getAddress()) << ": " << *Sym |
315 | << "\n"; |
316 | } else |
317 | OS << " none\n"; |
318 | |
319 | OS << "\nExternal symbols:\n"; |
320 | if (!llvm::empty(external_symbols())) { |
321 | for (auto *Sym : external_symbols()) |
322 | OS << " " << format("0x%016" PRIx64, Sym->getAddress()) << ": " << *Sym |
323 | << "\n"; |
324 | } else |
325 | OS << " none\n"; |
326 | } |
327 | |
328 | raw_ostream &operator<<(raw_ostream &OS, const SymbolLookupFlags &LF) { |
329 | switch (LF) { |
330 | case SymbolLookupFlags::RequiredSymbol: |
331 | return OS << "RequiredSymbol"; |
332 | case SymbolLookupFlags::WeaklyReferencedSymbol: |
333 | return OS << "WeaklyReferencedSymbol"; |
334 | } |
335 | llvm_unreachable("Unrecognized lookup flags"); |
336 | } |
337 | |
338 | void JITLinkAsyncLookupContinuation::anchor() {} |
339 | |
340 | JITLinkContext::~JITLinkContext() {} |
341 | |
342 | bool JITLinkContext::shouldAddDefaultTargetPasses(const Triple &TT) const { |
343 | return true; |
344 | } |
345 | |
346 | LinkGraphPassFunction JITLinkContext::getMarkLivePass(const Triple &TT) const { |
347 | return LinkGraphPassFunction(); |
348 | } |
349 | |
350 | Error JITLinkContext::modifyPassConfig(LinkGraph &G, |
351 | PassConfiguration &Config) { |
352 | return Error::success(); |
353 | } |
354 | |
355 | Error markAllSymbolsLive(LinkGraph &G) { |
356 | for (auto *Sym : G.defined_symbols()) |
357 | Sym->setLive(true); |
358 | return Error::success(); |
359 | } |
360 | |
361 | Error makeTargetOutOfRangeError(const LinkGraph &G, const Block &B, |
362 | const Edge &E) { |
363 | std::string ErrMsg; |
364 | { |
365 | raw_string_ostream ErrStream(ErrMsg); |
366 | Section &Sec = B.getSection(); |
367 | ErrStream << "In graph " << G.getName() << ", section " << Sec.getName() |
368 | << ": relocation target "; |
369 | if (E.getTarget().hasName()) |
370 | ErrStream << "\"" << E.getTarget().getName() << "\" "; |
371 | ErrStream << "at address " << formatv("{0:x}", E.getTarget().getAddress()); |
372 | ErrStream << " is out of range of " << G.getEdgeKindName(E.getKind()) |
373 | << " fixup at " << formatv("{0:x}", B.getFixupAddress(E)) << " ("; |
374 | |
375 | Symbol *BestSymbolForBlock = nullptr; |
376 | for (auto *Sym : Sec.symbols()) |
377 | if (&Sym->getBlock() == &B && Sym->hasName() && Sym->getOffset() == 0 && |
378 | (!BestSymbolForBlock || |
379 | Sym->getScope() < BestSymbolForBlock->getScope() || |
380 | Sym->getLinkage() < BestSymbolForBlock->getLinkage())) |
381 | BestSymbolForBlock = Sym; |
382 | |
383 | if (BestSymbolForBlock) |
384 | ErrStream << BestSymbolForBlock->getName() << ", "; |
385 | else |
386 | ErrStream << "<anonymous block> @ "; |
387 | |
388 | ErrStream << formatv("{0:x}", B.getAddress()) << " + " |
389 | << formatv("{0:x}", E.getOffset()) << ")"; |
390 | } |
391 | return make_error<JITLinkError>(std::move(ErrMsg)); |
392 | } |
393 | |
394 | Expected<std::unique_ptr<LinkGraph>> |
395 | createLinkGraphFromObject(MemoryBufferRef ObjectBuffer) { |
396 | auto Magic = identify_magic(ObjectBuffer.getBuffer()); |
397 | switch (Magic) { |
398 | case file_magic::macho_object: |
399 | return createLinkGraphFromMachOObject(ObjectBuffer); |
400 | case file_magic::elf_relocatable: |
401 | return createLinkGraphFromELFObject(ObjectBuffer); |
402 | default: |
403 | return make_error<JITLinkError>("Unsupported file format"); |
404 | }; |
405 | } |
406 | |
407 | void link(std::unique_ptr<LinkGraph> G, std::unique_ptr<JITLinkContext> Ctx) { |
408 | switch (G->getTargetTriple().getObjectFormat()) { |
409 | case Triple::MachO: |
410 | return link_MachO(std::move(G), std::move(Ctx)); |
411 | case Triple::ELF: |
412 | return link_ELF(std::move(G), std::move(Ctx)); |
413 | default: |
414 | Ctx->notifyFailed(make_error<JITLinkError>("Unsupported object format")); |
415 | }; |
416 | } |
417 | |
418 | } |
419 | } |
1 | |
2 | |
3 | |
4 | |
5 | |
6 | |
7 | |
8 | |
9 | |
10 | |
11 | |
12 | |
13 | #ifndef LLVM_EXECUTIONENGINE_JITLINK_JITLINK_H |
14 | #define LLVM_EXECUTIONENGINE_JITLINK_JITLINK_H |
15 | |
16 | #include "JITLinkMemoryManager.h" |
17 | #include "llvm/ADT/DenseMap.h" |
18 | #include "llvm/ADT/DenseSet.h" |
19 | #include "llvm/ADT/Optional.h" |
20 | #include "llvm/ADT/STLExtras.h" |
21 | #include "llvm/ADT/Triple.h" |
22 | #include "llvm/ExecutionEngine/JITSymbol.h" |
23 | #include "llvm/Support/Allocator.h" |
24 | #include "llvm/Support/Endian.h" |
25 | #include "llvm/Support/Error.h" |
26 | #include "llvm/Support/FormatVariadic.h" |
27 | #include "llvm/Support/MathExtras.h" |
28 | #include "llvm/Support/Memory.h" |
29 | #include "llvm/Support/MemoryBuffer.h" |
30 | |
31 | #include <map> |
32 | #include <string> |
33 | #include <system_error> |
34 | |
35 | namespace llvm { |
36 | namespace jitlink { |
37 | |
38 | class LinkGraph; |
39 | class Symbol; |
40 | class Section; |
41 | |
42 | |
43 | |
44 | class JITLinkError : public ErrorInfo<JITLinkError> { |
45 | public: |
46 | static char ID; |
47 | |
48 | JITLinkError(Twine ErrMsg) : ErrMsg(ErrMsg.str()) {} |
49 | |
50 | void log(raw_ostream &OS) const override; |
51 | const std::string &getErrorMessage() const { return ErrMsg; } |
52 | std::error_code convertToErrorCode() const override; |
53 | |
54 | private: |
55 | std::string ErrMsg; |
56 | }; |
57 | |
58 | |
59 | class Edge { |
60 | public: |
61 | using Kind = uint8_t; |
62 | |
63 | enum GenericEdgeKind : Kind { |
64 | Invalid, |
65 | FirstKeepAlive, |
66 | KeepAlive = FirstKeepAlive, |
67 | FirstRelocation |
68 | }; |
69 | |
70 | using OffsetT = uint32_t; |
71 | using AddendT = int64_t; |
72 | |
73 | Edge(Kind K, OffsetT Offset, Symbol &Target, AddendT Addend) |
74 | : Target(&Target), Offset(Offset), Addend(Addend), K(K) {} |
75 | |
76 | OffsetT getOffset() const { return Offset; } |
77 | void setOffset(OffsetT Offset) { this->Offset = Offset; } |
78 | Kind getKind() const { return K; } |
79 | void setKind(Kind K) { this->K = K; } |
80 | bool isRelocation() const { return K >= FirstRelocation; } |
81 | Kind getRelocation() const { |
82 | assert(isRelocation() && "Not a relocation edge"); |
83 | return K - FirstRelocation; |
84 | } |
85 | bool isKeepAlive() const { return K >= FirstKeepAlive; } |
86 | Symbol &getTarget() const { return *Target; } |
87 | void setTarget(Symbol &Target) { this->Target = &Target; } |
88 | AddendT getAddend() const { return Addend; } |
89 | void setAddend(AddendT Addend) { this->Addend = Addend; } |
90 | |
91 | private: |
92 | Symbol *Target = nullptr; |
93 | OffsetT Offset = 0; |
94 | AddendT Addend = 0; |
95 | Kind K = 0; |
96 | }; |
97 | |
98 | |
99 | |
100 | const char *getGenericEdgeKindName(Edge::Kind K); |
101 | |
102 | |
103 | class Addressable { |
104 | friend class LinkGraph; |
105 | |
106 | protected: |
107 | Addressable(JITTargetAddress Address, bool IsDefined) |
108 | : Address(Address), IsDefined(IsDefined), IsAbsolute(false) {} |
109 | |
110 | Addressable(JITTargetAddress Address) |
111 | : Address(Address), IsDefined(false), IsAbsolute(true) { |
112 | assert(!(IsDefined && IsAbsolute) && |
113 | "Block cannot be both defined and absolute"); |
114 | } |
115 | |
116 | public: |
117 | Addressable(const Addressable &) = delete; |
118 | Addressable &operator=(const Addressable &) = default; |
119 | Addressable(Addressable &&) = delete; |
120 | Addressable &operator=(Addressable &&) = default; |
121 | |
122 | JITTargetAddress getAddress() const { return Address; } |
123 | void setAddress(JITTargetAddress Address) { this->Address = Address; } |
124 | |
125 | |
126 | |
127 | bool isDefined() const { return static_cast<bool>(IsDefined); } |
128 | bool isAbsolute() const { return static_cast<bool>(IsAbsolute); } |
129 | |
130 | private: |
131 | void setAbsolute(bool IsAbsolute) { |
132 | assert(!IsDefined && "Cannot change the Absolute flag on a defined block"); |
133 | this->IsAbsolute = IsAbsolute; |
134 | } |
135 | |
136 | JITTargetAddress Address = 0; |
137 | uint64_t IsDefined : 1; |
138 | uint64_t IsAbsolute : 1; |
139 | |
140 | protected: |
141 | |
142 | uint64_t ContentMutable : 1; |
143 | uint64_t P2Align : 5; |
144 | uint64_t AlignmentOffset : 56; |
145 | }; |
146 | |
147 | using SectionOrdinal = unsigned; |
148 | |
149 | |
150 | class Block : public Addressable { |
151 | friend class LinkGraph; |
152 | |
153 | private: |
154 | |
155 | Block(Section &Parent, JITTargetAddress Size, JITTargetAddress Address, |
156 | uint64_t Alignment, uint64_t AlignmentOffset) |
157 | : Addressable(Address, true), Parent(&Parent), Size(Size) { |
158 | assert(isPowerOf2_64(Alignment) && "Alignment must be power of 2"); |
159 | assert(AlignmentOffset < Alignment && |
160 | "Alignment offset cannot exceed alignment"); |
161 | assert(AlignmentOffset <= MaxAlignmentOffset && |
162 | "Alignment offset exceeds maximum"); |
163 | ContentMutable = false; |
164 | P2Align = Alignment ? countTrailingZeros(Alignment) : 0; |
165 | this->AlignmentOffset = AlignmentOffset; |
166 | } |
167 | |
168 | |
169 | |
170 | |
171 | Block(Section &Parent, ArrayRef<char> Content, JITTargetAddress Address, |
172 | uint64_t Alignment, uint64_t AlignmentOffset) |
173 | : Addressable(Address, true), Parent(&Parent), Data(Content.data()), |
174 | Size(Content.size()) { |
175 | assert(isPowerOf2_64(Alignment) && "Alignment must be power of 2"); |
176 | assert(AlignmentOffset < Alignment && |
177 | "Alignment offset cannot exceed alignment"); |
178 | assert(AlignmentOffset <= MaxAlignmentOffset && |
179 | "Alignment offset exceeds maximum"); |
180 | ContentMutable = false; |
181 | P2Align = Alignment ? countTrailingZeros(Alignment) : 0; |
182 | this->AlignmentOffset = AlignmentOffset; |
183 | } |
184 | |
185 | |
186 | |
187 | |
188 | |
189 | |
190 | Block(Section &Parent, MutableArrayRef<char> Content, |
191 | JITTargetAddress Address, uint64_t Alignment, uint64_t AlignmentOffset) |
192 | : Addressable(Address, true), Parent(&Parent), Data(Content.data()), |
193 | Size(Content.size()) { |
194 | assert(isPowerOf2_64(Alignment) && "Alignment must be power of 2"); |
195 | assert(AlignmentOffset < Alignment && |
196 | "Alignment offset cannot exceed alignment"); |
197 | assert(AlignmentOffset <= MaxAlignmentOffset && |
198 | "Alignment offset exceeds maximum"); |
199 | ContentMutable = true; |
200 | P2Align = Alignment ? countTrailingZeros(Alignment) : 0; |
201 | this->AlignmentOffset = AlignmentOffset; |
202 | } |
203 | |
204 | public: |
205 | using EdgeVector = std::vector<Edge>; |
206 | using edge_iterator = EdgeVector::iterator; |
207 | using const_edge_iterator = EdgeVector::const_iterator; |
208 | |
209 | Block(const Block &) = delete; |
210 | Block &operator=(const Block &) = delete; |
211 | Block(Block &&) = delete; |
212 | Block &operator=(Block &&) = delete; |
213 | |
214 | |
215 | Section &getSection() const { return *Parent; } |
216 | |
217 | |
218 | |
219 | |
220 | |
221 | bool isZeroFill() const { return !Data; } |
222 | |
223 | |
224 | size_t getSize() const { return Size; } |
225 | |
226 | |
227 | ArrayRef<char> getContent() const { |
228 | assert(Data && "Section does not contain content"); |
229 | return ArrayRef<char>(Data, Size); |
230 | } |
231 | |
232 | |
233 | |
234 | |
235 | void setContent(ArrayRef<char> Content) { |
236 | Data = Content.data(); |
237 | Size = Content.size(); |
238 | ContentMutable = false; |
239 | } |
240 | |
241 | |
242 | |
243 | |
244 | |
245 | |
246 | MutableArrayRef<char> getMutableContent(LinkGraph &G); |
247 | |
248 | |
249 | |
250 | |
251 | |
252 | |
253 | MutableArrayRef<char> getAlreadyMutableContent() { |
254 | assert(ContentMutable && "Content is not mutable"); |
255 | return MutableArrayRef<char>(const_cast<char *>(Data), Size); |
256 | } |
257 | |
258 | |
259 | |
260 | |
261 | |
262 | void setMutableContent(MutableArrayRef<char> MutableContent) { |
263 | Data = MutableContent.data(); |
264 | Size = MutableContent.size(); |
265 | ContentMutable = true; |
266 | } |
267 | |
268 | |
269 | |
270 | |
271 | |
272 | |
273 | |
274 | bool isContentMutable() const { return ContentMutable; } |
275 | |
276 | |
277 | uint64_t getAlignment() const { return 1ull << P2Align; } |
| |
278 | |
279 | |
280 | void setAlignment(uint64_t Alignment) { |
281 | assert(isPowerOf2_64(Alignment) && "Alignment must be a power of two"); |
282 | P2Align = Alignment ? countTrailingZeros(Alignment) : 0; |
283 | } |
284 | |
285 | |
286 | uint64_t getAlignmentOffset() const { return AlignmentOffset; } |
287 | |
288 | |
289 | void setAlignmentOffset(uint64_t AlignmentOffset) { |
290 | assert(AlignmentOffset < (1ull << P2Align) && |
291 | "Alignment offset can't exceed alignment"); |
292 | this->AlignmentOffset = AlignmentOffset; |
293 | } |
294 | |
295 | |
296 | void addEdge(Edge::Kind K, Edge::OffsetT Offset, Symbol &Target, |
297 | Edge::AddendT Addend) { |
298 | Edges.push_back(Edge(K, Offset, Target, Addend)); |
299 | } |
300 | |
301 | |
302 | |
303 | void addEdge(const Edge &E) { Edges.push_back(E); } |
304 | |
305 | |
306 | iterator_range<edge_iterator> edges() { |
307 | return make_range(Edges.begin(), Edges.end()); |
308 | } |
309 | |
310 | |
311 | iterator_range<const_edge_iterator> edges() const { |
312 | return make_range(Edges.begin(), Edges.end()); |
313 | } |
314 | |
315 | |
316 | size_t edges_size() const { return Edges.size(); } |
317 | |
318 | |
319 | bool edges_empty() const { return Edges.empty(); } |
320 | |
321 | |
322 | |
323 | edge_iterator removeEdge(edge_iterator I) { return Edges.erase(I); } |
324 | |
325 | |
326 | |
327 | JITTargetAddress getFixupAddress(const Edge &E) const { |
328 | return getAddress() + E.getOffset(); |
329 | } |
330 | |
331 | private: |
332 | static constexpr uint64_t MaxAlignmentOffset = (1ULL << 56) - 1; |
333 | |
334 | void setSection(Section &Parent) { this->Parent = &Parent; } |
335 | |
336 | Section *Parent; |
337 | const char *Data = nullptr; |
338 | size_t Size = 0; |
339 | std::vector<Edge> Edges; |
340 | }; |
341 | |
342 | |
343 | |
344 | enum class Linkage : uint8_t { |
345 | Strong, |
346 | Weak, |
347 | }; |
348 | |
349 | |
350 | const char *getLinkageName(Linkage L); |
351 | |
352 | |
353 | |
354 | |
355 | |
356 | enum class Scope : uint8_t { |
357 | Default, |
358 | Hidden, |
359 | Local |
360 | }; |
361 | |
362 | |
363 | const char *getScopeName(Scope S); |
364 | |
365 | raw_ostream &operator<<(raw_ostream &OS, const Block &B); |
366 | |
367 | |
368 | |
369 | |
370 | |
371 | |
372 | |
373 | |
374 | |
375 | |
376 | |
377 | |
378 | |
379 | |
380 | class Symbol { |
381 | friend class LinkGraph; |
382 | |
383 | private: |
384 | Symbol(Addressable &Base, JITTargetAddress Offset, StringRef Name, |
385 | JITTargetAddress Size, Linkage L, Scope S, bool IsLive, |
386 | bool IsCallable) |
387 | : Name(Name), Base(&Base), Offset(Offset), Size(Size) { |
388 | assert(Offset <= MaxOffset && "Offset out of range"); |
389 | setLinkage(L); |
390 | setScope(S); |
391 | setLive(IsLive); |
392 | setCallable(IsCallable); |
393 | } |
394 | |
395 | static Symbol &constructCommon(void *SymStorage, Block &Base, StringRef Name, |
396 | JITTargetAddress Size, Scope S, bool IsLive) { |
397 | assert(SymStorage && "Storage cannot be null"); |
398 | assert(!Name.empty() && "Common symbol name cannot be empty"); |
399 | assert(Base.isDefined() && |
400 | "Cannot create common symbol from undefined block"); |
401 | assert(static_cast<Block &>(Base).getSize() == Size && |
402 | "Common symbol size should match underlying block size"); |
403 | auto *Sym = reinterpret_cast<Symbol *>(SymStorage); |
404 | new (Sym) Symbol(Base, 0, Name, Size, Linkage::Weak, S, IsLive, false); |
405 | return *Sym; |
406 | } |
407 | |
408 | static Symbol &constructExternal(void *SymStorage, Addressable &Base, |
409 | StringRef Name, JITTargetAddress Size, |
410 | Linkage L) { |
411 | assert(SymStorage && "Storage cannot be null"); |
412 | assert(!Base.isDefined() && |
413 | "Cannot create external symbol from defined block"); |
414 | assert(!Name.empty() && "External symbol name cannot be empty"); |
415 | auto *Sym = reinterpret_cast<Symbol *>(SymStorage); |
416 | new (Sym) Symbol(Base, 0, Name, Size, L, Scope::Default, false, false); |
417 | return *Sym; |
418 | } |
419 | |
420 | static Symbol &constructAbsolute(void *SymStorage, Addressable &Base, |
421 | StringRef Name, JITTargetAddress Size, |
422 | Linkage L, Scope S, bool IsLive) { |
423 | assert(SymStorage && "Storage cannot be null"); |
424 | assert(!Base.isDefined() && |
425 | "Cannot create absolute symbol from a defined block"); |
426 | auto *Sym = reinterpret_cast<Symbol *>(SymStorage); |
427 | new (Sym) Symbol(Base, 0, Name, Size, L, S, IsLive, false); |
428 | return *Sym; |
429 | } |
430 | |
431 | static Symbol &constructAnonDef(void *SymStorage, Block &Base, |
432 | JITTargetAddress Offset, |
433 | JITTargetAddress Size, bool IsCallable, |
434 | bool IsLive) { |
435 | assert(SymStorage && "Storage cannot be null"); |
436 | assert((Offset + Size) <= Base.getSize() && |
437 | "Symbol extends past end of block"); |
438 | auto *Sym = reinterpret_cast<Symbol *>(SymStorage); |
439 | new (Sym) Symbol(Base, Offset, StringRef(), Size, Linkage::Strong, |
440 | Scope::Local, IsLive, IsCallable); |
441 | return *Sym; |
442 | } |
443 | |
444 | static Symbol &constructNamedDef(void *SymStorage, Block &Base, |
445 | JITTargetAddress Offset, StringRef Name, |
446 | JITTargetAddress Size, Linkage L, Scope S, |
447 | bool IsLive, bool IsCallable) { |
448 | assert(SymStorage && "Storage cannot be null"); |
449 | assert((Offset + Size) <= Base.getSize() && |
450 | "Symbol extends past end of block"); |
451 | assert(!Name.empty() && "Name cannot be empty"); |
452 | auto *Sym = reinterpret_cast<Symbol *>(SymStorage); |
453 | new (Sym) Symbol(Base, Offset, Name, Size, L, S, IsLive, IsCallable); |
454 | return *Sym; |
455 | } |
456 | |
457 | public: |
458 | |
459 | |
460 | |
461 | Symbol() = default; |
462 | |
463 | |
464 | Symbol(const Symbol &) = delete; |
465 | Symbol &operator=(const Symbol &) = delete; |
466 | Symbol(Symbol &&) = delete; |
467 | Symbol &operator=(Symbol &&) = delete; |
468 | |
469 | |
470 | bool hasName() const { return !Name.empty(); } |
471 | |
472 | |
473 | StringRef getName() const { |
474 | assert((!Name.empty() || getScope() == Scope::Local) && |
475 | "Anonymous symbol has non-local scope"); |
476 | return Name; |
477 | } |
478 | |
479 | |
480 | |
481 | void setName(StringRef Name) { this->Name = Name; } |
482 | |
483 | |
484 | |
485 | bool isDefined() const { |
486 | assert(Base && "Attempt to access null symbol"); |
487 | return Base->isDefined(); |
488 | } |
489 | |
490 | |
491 | |
492 | bool isLive() const { |
493 | assert(Base && "Attempting to access null symbol"); |
494 | return IsLive; |
495 | } |
496 | |
497 | |
498 | void setLive(bool IsLive) { this->IsLive = IsLive; } |
499 | |
500 | |
501 | bool isCallable() const { return IsCallable; } |
502 | |
503 | |
504 | void setCallable(bool IsCallable) { this->IsCallable = IsCallable; } |
505 | |
506 | |
507 | bool isExternal() const { |
508 | assert(Base && "Attempt to access null symbol"); |
509 | return !Base->isDefined() && !Base->isAbsolute(); |
510 | } |
511 | |
512 | |
513 | bool isAbsolute() const { |
514 | assert(Base && "Attempt to access null symbol"); |
515 | return Base->isAbsolute(); |
516 | } |
517 | |
518 | |
519 | Addressable &getAddressable() { |
520 | assert(Base && "Cannot get underlying addressable for null symbol"); |
521 | return *Base; |
522 | } |
523 | |
524 | |
525 | const Addressable &getAddressable() const { |
526 | assert(Base && "Cannot get underlying addressable for null symbol"); |
527 | return *Base; |
528 | } |
529 | |
530 | |
531 | Block &getBlock() { |
532 | assert(Base && "Cannot get block for null symbol"); |
533 | assert(Base->isDefined() && "Not a defined symbol"); |
534 | return static_cast<Block &>(*Base); |
535 | } |
536 | |
537 | |
538 | const Block &getBlock() const { |
539 | assert(Base && "Cannot get block for null symbol"); |
540 | assert(Base->isDefined() && "Not a defined symbol"); |
541 | return static_cast<const Block &>(*Base); |
542 | } |
543 | |
544 | |
545 | JITTargetAddress getOffset() const { return Offset; } |
546 | |
547 | |
548 | JITTargetAddress getAddress() const { return Base->getAddress() + Offset; } |
549 | |
550 | |
551 | JITTargetAddress getSize() const { return Size; } |
552 | |
553 | |
554 | void setSize(JITTargetAddress Size) { |
555 | assert(Base && "Cannot set size for null Symbol"); |
556 | assert((Size == 0 || Base->isDefined()) && |
557 | "Non-zero size can only be set for defined symbols"); |
558 | assert((Offset + Size <= static_cast<const Block &>(*Base).getSize()) && |
559 | "Symbol size cannot extend past the end of its containing block"); |
560 | this->Size = Size; |
561 | } |
562 | |
563 | |
564 | |
565 | bool isSymbolZeroFill() const { return getBlock().isZeroFill(); } |
566 | |
567 | |
568 | |
569 | ArrayRef<char> getSymbolContent() const { |
570 | return getBlock().getContent().slice(Offset, Size); |
571 | } |
572 | |
573 | |
574 | Linkage getLinkage() const { return static_cast<Linkage>(L); } |
575 | |
576 | |
577 | void setLinkage(Linkage L) { |
578 | assert((L == Linkage::Strong || (!Base->isAbsolute() && !Name.empty())) && |
579 | "Linkage can only be applied to defined named symbols"); |
580 | this->L = static_cast<uint8_t>(L); |
581 | } |
582 | |
583 | |
584 | Scope getScope() const { return static_cast<Scope>(S); } |
585 | |
586 | |
587 | void setScope(Scope S) { |
588 | assert((!Name.empty() || S == Scope::Local) && |
589 | "Can not set anonymous symbol to non-local scope"); |
590 | assert((S == Scope::Default || Base->isDefined() || Base->isAbsolute()) && |
591 | "Invalid visibility for symbol type"); |
592 | this->S = static_cast<uint8_t>(S); |
593 | } |
594 | |
595 | private: |
596 | void makeExternal(Addressable &A) { |
597 | assert(!A.isDefined() && !A.isAbsolute() && |
598 | "Attempting to make external with defined or absolute block"); |
599 | Base = &A; |
600 | Offset = 0; |
601 | setScope(Scope::Default); |
602 | IsLive = 0; |
603 | |
604 | } |
605 | |
606 | void makeAbsolute(Addressable &A) { |
607 | assert(!A.isDefined() && A.isAbsolute() && |
608 | "Attempting to make absolute with defined or external block"); |
609 | Base = &A; |
610 | Offset = 0; |
611 | } |
612 | |
613 | void setBlock(Block &B) { Base = &B; } |
614 | |
615 | void setOffset(uint64_t NewOffset) { |
616 | assert(NewOffset <= MaxOffset && "Offset out of range"); |
617 | Offset = NewOffset; |
618 | } |
619 | |
620 | static constexpr uint64_t MaxOffset = (1ULL << 59) - 1; |
621 | |
622 | |
623 | StringRef Name; |
624 | Addressable *Base = nullptr; |
625 | uint64_t Offset : 59; |
626 | uint64_t L : 1; |
627 | uint64_t S : 2; |
628 | uint64_t IsLive : 1; |
629 | uint64_t IsCallable : 1; |
630 | JITTargetAddress Size = 0; |
631 | }; |
632 | |
633 | raw_ostream &operator<<(raw_ostream &OS, const Symbol &A); |
634 | |
635 | void printEdge(raw_ostream &OS, const Block &B, const Edge &E, |
636 | StringRef EdgeKindName); |
637 | |
638 | |
639 | class Section { |
640 | friend class LinkGraph; |
641 | |
642 | private: |
643 | Section(StringRef Name, sys::Memory::ProtectionFlags Prot, |
644 | SectionOrdinal SecOrdinal) |
645 | : Name(Name), Prot(Prot), SecOrdinal(SecOrdinal) {} |
646 | |
647 | using SymbolSet = DenseSet<Symbol *>; |
648 | using BlockSet = DenseSet<Block *>; |
649 | |
650 | public: |
651 | using symbol_iterator = SymbolSet::iterator; |
652 | using const_symbol_iterator = SymbolSet::const_iterator; |
653 | |
654 | using block_iterator = BlockSet::iterator; |
655 | using const_block_iterator = BlockSet::const_iterator; |
656 | |
657 | ~Section(); |
658 | |
659 | |
660 | Section(const Section &) = delete; |
661 | Section &operator=(const Section &) = delete; |
662 | Section(Section &&) = delete; |
663 | Section &operator=(Section &&) = delete; |
664 | |
665 | |
666 | StringRef getName() const { return Name; } |
667 | |
668 | |
669 | sys::Memory::ProtectionFlags getProtectionFlags() const { return Prot; } |
670 | |
671 | |
672 | void setProtectionFlags(sys::Memory::ProtectionFlags Prot) { |
673 | this->Prot = Prot; |
674 | } |
675 | |
676 | |
677 | SectionOrdinal getOrdinal() const { return SecOrdinal; } |
678 | |
679 | |
680 | iterator_range<block_iterator> blocks() { |
681 | return make_range(Blocks.begin(), Blocks.end()); |
682 | } |
683 | |
684 | |
685 | iterator_range<const_block_iterator> blocks() const { |
686 | return make_range(Blocks.begin(), Blocks.end()); |
687 | } |
688 | |
689 | BlockSet::size_type blocks_size() const { return Blocks.size(); } |
690 | |
691 | |
692 | iterator_range<symbol_iterator> symbols() { |
693 | return make_range(Symbols.begin(), Symbols.end()); |
694 | } |
695 | |
696 | |
697 | iterator_range<const_symbol_iterator> symbols() const { |
698 | return make_range(Symbols.begin(), Symbols.end()); |
699 | } |
700 | |
701 | |
702 | SymbolSet::size_type symbols_size() const { return Symbols.size(); } |
703 | |
704 | private: |
705 | void addSymbol(Symbol &Sym) { |
706 | assert(!Symbols.count(&Sym) && "Symbol is already in this section"); |
707 | Symbols.insert(&Sym); |
708 | } |
709 | |
710 | void removeSymbol(Symbol &Sym) { |
711 | assert(Symbols.count(&Sym) && "symbol is not in this section"); |
712 | Symbols.erase(&Sym); |
713 | } |
714 | |
715 | void addBlock(Block &B) { |
716 | assert(!Blocks.count(&B) && "Block is already in this section"); |
717 | Blocks.insert(&B); |
718 | } |
719 | |
720 | void removeBlock(Block &B) { |
721 | assert(Blocks.count(&B) && "Block is not in this section"); |
722 | Blocks.erase(&B); |
723 | } |
724 | |
725 | void transferContentTo(Section &DstSection) { |
726 | if (&DstSection == this) |
727 | return; |
728 | for (auto *S : Symbols) |
729 | DstSection.addSymbol(*S); |
730 | for (auto *B : Blocks) |
731 | DstSection.addBlock(*B); |
732 | Symbols.clear(); |
733 | Blocks.clear(); |
734 | } |
735 | |
736 | StringRef Name; |
737 | sys::Memory::ProtectionFlags Prot; |
738 | SectionOrdinal SecOrdinal = 0; |
739 | BlockSet Blocks; |
740 | SymbolSet Symbols; |
741 | }; |
742 | |
743 | |
744 | |
745 | class SectionRange { |
746 | public: |
747 | SectionRange() = default; |
748 | SectionRange(const Section &Sec) { |
749 | if (llvm::empty(Sec.blocks())) |
750 | return; |
751 | First = Last = *Sec.blocks().begin(); |
752 | for (auto *B : Sec.blocks()) { |
753 | if (B->getAddress() < First->getAddress()) |
754 | First = B; |
755 | if (B->getAddress() > Last->getAddress()) |
756 | Last = B; |
757 | } |
758 | } |
759 | Block *getFirstBlock() const { |
760 | assert((!Last || First) && "First can not be null if end is non-null"); |
761 | return First; |
762 | } |
763 | Block *getLastBlock() const { |
764 | assert((First || !Last) && "Last can not be null if start is non-null"); |
765 | return Last; |
766 | } |
767 | bool empty() const { |
768 | assert((First || !Last) && "Last can not be null if start is non-null"); |
769 | return !First; |
770 | } |
771 | JITTargetAddress getStart() const { |
772 | return First ? First->getAddress() : 0; |
773 | } |
774 | JITTargetAddress getEnd() const { |
775 | return Last ? Last->getAddress() + Last->getSize() : 0; |
776 | } |
777 | uint64_t getSize() const { return getEnd() - getStart(); } |
778 | |
779 | private: |
780 | Block *First = nullptr; |
781 | Block *Last = nullptr; |
782 | }; |
783 | |
784 | class LinkGraph { |
785 | private: |
786 | using SectionList = std::vector<std::unique_ptr<Section>>; |
787 | using ExternalSymbolSet = DenseSet<Symbol *>; |
788 | using BlockSet = DenseSet<Block *>; |
789 | |
790 | template <typename... ArgTs> |
791 | Addressable &createAddressable(ArgTs &&... Args) { |
792 | Addressable *A = |
793 | reinterpret_cast<Addressable *>(Allocator.Allocate<Addressable>()); |
794 | new (A) Addressable(std::forward<ArgTs>(Args)...); |
795 | return *A; |
796 | } |
797 | |
798 | void destroyAddressable(Addressable &A) { |
799 | A.~Addressable(); |
800 | Allocator.Deallocate(&A); |
801 | } |
802 | |
803 | template <typename... ArgTs> Block &createBlock(ArgTs &&... Args) { |
804 | Block *B = reinterpret_cast<Block *>(Allocator.Allocate<Block>()); |
805 | new (B) Block(std::forward<ArgTs>(Args)...); |
806 | B->getSection().addBlock(*B); |
807 | return *B; |
808 | } |
809 | |
810 | void destroyBlock(Block &B) { |
811 | B.~Block(); |
812 | Allocator.Deallocate(&B); |
813 | } |
814 | |
815 | void destroySymbol(Symbol &S) { |
816 | S.~Symbol(); |
817 | Allocator.Deallocate(&S); |
818 | } |
819 | |
820 | static iterator_range<Section::block_iterator> getSectionBlocks(Section &S) { |
821 | return S.blocks(); |
822 | } |
823 | |
824 | static iterator_range<Section::const_block_iterator> |
825 | getSectionConstBlocks(Section &S) { |
826 | return S.blocks(); |
827 | } |
828 | |
829 | static iterator_range<Section::symbol_iterator> |
830 | getSectionSymbols(Section &S) { |
831 | return S.symbols(); |
832 | } |
833 | |
834 | static iterator_range<Section::const_symbol_iterator> |
835 | getSectionConstSymbols(Section &S) { |
836 | return S.symbols(); |
837 | } |
838 | |
839 | public: |
840 | using external_symbol_iterator = ExternalSymbolSet::iterator; |
841 | |
842 | using section_iterator = pointee_iterator<SectionList::iterator>; |
843 | using const_section_iterator = pointee_iterator<SectionList::const_iterator>; |
844 | |
845 | template <typename OuterItrT, typename InnerItrT, typename T, |
846 | iterator_range<InnerItrT> getInnerRange( |
847 | typename OuterItrT::reference)> |
848 | class nested_collection_iterator |
849 | : public iterator_facade_base< |
850 | nested_collection_iterator<OuterItrT, InnerItrT, T, getInnerRange>, |
851 | std::forward_iterator_tag, T> { |
852 | public: |
853 | nested_collection_iterator() = default; |
854 | |
855 | nested_collection_iterator(OuterItrT OuterI, OuterItrT OuterE) |
856 | : OuterI(OuterI), OuterE(OuterE), |
857 | InnerI(getInnerBegin(OuterI, OuterE)) { |
858 | moveToNonEmptyInnerOrEnd(); |
859 | } |
860 | |
861 | bool operator==(const nested_collection_iterator &RHS) const { |
862 | return (OuterI == RHS.OuterI) && (InnerI == RHS.InnerI); |
863 | } |
864 | |
865 | T operator*() const { |
866 | assert(InnerI != getInnerRange(*OuterI).end() && "Dereferencing end?"); |
867 | return *InnerI; |
868 | } |
869 | |
870 | nested_collection_iterator operator++() { |
871 | ++InnerI; |
872 | moveToNonEmptyInnerOrEnd(); |
873 | return *this; |
874 | } |
875 | |
876 | private: |
877 | static InnerItrT getInnerBegin(OuterItrT OuterI, OuterItrT OuterE) { |
878 | return OuterI != OuterE ? getInnerRange(*OuterI).begin() : InnerItrT(); |
879 | } |
880 | |
881 | void moveToNonEmptyInnerOrEnd() { |
882 | while (OuterI != OuterE && InnerI == getInnerRange(*OuterI).end()) { |
883 | ++OuterI; |
884 | InnerI = getInnerBegin(OuterI, OuterE); |
885 | } |
886 | } |
887 | |
888 | OuterItrT OuterI, OuterE; |
889 | InnerItrT InnerI; |
890 | }; |
891 | |
892 | using defined_symbol_iterator = |
893 | nested_collection_iterator<const_section_iterator, |
894 | Section::symbol_iterator, Symbol *, |
895 | getSectionSymbols>; |
896 | |
897 | using const_defined_symbol_iterator = |
898 | nested_collection_iterator<const_section_iterator, |
899 | Section::const_symbol_iterator, const Symbol *, |
900 | getSectionConstSymbols>; |
901 | |
902 | using block_iterator = nested_collection_iterator<const_section_iterator, |
903 | Section::block_iterator, |
904 | Block *, getSectionBlocks>; |
905 | |
906 | using const_block_iterator = |
907 | nested_collection_iterator<const_section_iterator, |
908 | Section::const_block_iterator, const Block *, |
909 | getSectionConstBlocks>; |
910 | |
911 | using GetEdgeKindNameFunction = const char *(*)(Edge::Kind); |
912 | |
913 | LinkGraph(std::string Name, const Triple &TT, unsigned PointerSize, |
914 | support::endianness Endianness, |
915 | GetEdgeKindNameFunction GetEdgeKindName) |
916 | : Name(std::move(Name)), TT(TT), PointerSize(PointerSize), |
917 | Endianness(Endianness), GetEdgeKindName(std::move(GetEdgeKindName)) {} |
918 | |
919 | |
920 | |
921 | const std::string &getName() const { return Name; } |
922 | |
923 | |
924 | const Triple &getTargetTriple() const { return TT; } |
925 | |
926 | |
927 | unsigned getPointerSize() const { return PointerSize; } |
928 | |
929 | |
930 | support::endianness getEndianness() const { return Endianness; } |
931 | |
932 | const char *getEdgeKindName(Edge::Kind K) const { return GetEdgeKindName(K); } |
933 | |
934 | |
935 | |
936 | MutableArrayRef<char> allocateBuffer(size_t Size) { |
937 | return {Allocator.Allocate<char>(Size), Size}; |
938 | } |
939 | |
940 | |
941 | |
942 | |
943 | MutableArrayRef<char> allocateContent(ArrayRef<char> Source) { |
944 | auto *AllocatedBuffer = Allocator.Allocate<char>(Source.size()); |
945 | llvm::copy(Source, AllocatedBuffer); |
946 | return MutableArrayRef<char>(AllocatedBuffer, Source.size()); |
947 | } |
948 | |
949 | |
950 | |
951 | |
952 | |
953 | |
954 | |
955 | |
956 | MutableArrayRef<char> allocateString(Twine Source) { |
957 | SmallString<256> TmpBuffer; |
958 | auto SourceStr = Source.toStringRef(TmpBuffer); |
959 | auto *AllocatedBuffer = Allocator.Allocate<char>(SourceStr.size()); |
960 | llvm::copy(SourceStr, AllocatedBuffer); |
961 | return MutableArrayRef<char>(AllocatedBuffer, SourceStr.size()); |
962 | } |
963 | |
964 | |
965 | Section &createSection(StringRef Name, sys::Memory::ProtectionFlags Prot) { |
966 | assert(llvm::find_if(Sections, |
967 | [&](std::unique_ptr<Section> &Sec) { |
968 | return Sec->getName() == Name; |
969 | }) == Sections.end() && |
970 | "Duplicate section name"); |
971 | std::unique_ptr<Section> Sec(new Section(Name, Prot, Sections.size())); |
972 | Sections.push_back(std::move(Sec)); |
973 | return *Sections.back(); |
974 | } |
975 | |
976 | |
977 | Block &createContentBlock(Section &Parent, ArrayRef<char> Content, |
978 | uint64_t Address, uint64_t Alignment, |
979 | uint64_t AlignmentOffset) { |
980 | return createBlock(Parent, Content, Address, Alignment, AlignmentOffset); |
981 | } |
982 | |
983 | |
984 | Block &createMutableContentBlock(Section &Parent, |
985 | MutableArrayRef<char> MutableContent, |
986 | uint64_t Address, uint64_t Alignment, |
987 | uint64_t AlignmentOffset) { |
988 | return createBlock(Parent, MutableContent, Address, Alignment, |
989 | AlignmentOffset); |
990 | } |
991 | |
992 | |
993 | Block &createZeroFillBlock(Section &Parent, uint64_t Size, uint64_t Address, |
994 | uint64_t Alignment, uint64_t AlignmentOffset) { |
995 | return createBlock(Parent, Size, Address, Alignment, AlignmentOffset); |
996 | } |
997 | |
998 | |
999 | using SplitBlockCache = Optional<SmallVector<Symbol *, 8>>; |
1000 | |
1001 | |
1002 | |
1003 | |
1004 | |
1005 | |
1006 | |
1007 | |
1008 | |
1009 | |
1010 | |
1011 | |
1012 | |
1013 | |
1014 | |
1015 | |
1016 | |
1017 | |
1018 | |
1019 | |
1020 | |
1021 | |
1022 | |
1023 | |
1024 | |
1025 | |
1026 | |
1027 | |
1028 | |
1029 | |
1030 | |
1031 | |
1032 | |
1033 | |
1034 | Block &splitBlock(Block &B, size_t SplitIndex, |
1035 | SplitBlockCache *Cache = nullptr); |
1036 | |
1037 | |
1038 | |
1039 | |
1040 | |
1041 | |
1042 | |
1043 | |
1044 | Symbol &addExternalSymbol(StringRef Name, uint64_t Size, Linkage L) { |
1045 | assert(llvm::count_if(ExternalSymbols, |
1046 | [&](const Symbol *Sym) { |
1047 | return Sym->getName() == Name; |
1048 | }) == 0 && |
1049 | "Duplicate external symbol"); |
1050 | auto &Sym = |
1051 | Symbol::constructExternal(Allocator.Allocate<Symbol>(), |
1052 | createAddressable(0, false), Name, Size, L); |
1053 | ExternalSymbols.insert(&Sym); |
1054 | return Sym; |
1055 | } |
1056 | |
1057 | |
1058 | Symbol &addAbsoluteSymbol(StringRef Name, JITTargetAddress Address, |
1059 | uint64_t Size, Linkage L, Scope S, bool IsLive) { |
1060 | assert(llvm::count_if(AbsoluteSymbols, |
1061 | [&](const Symbol *Sym) { |
1062 | return Sym->getName() == Name; |
1063 | }) == 0 && |
1064 | "Duplicate absolute symbol"); |
1065 | auto &Sym = Symbol::constructAbsolute(Allocator.Allocate<Symbol>(), |
1066 | createAddressable(Address), Name, |
1067 | Size, L, S, IsLive); |
1068 | AbsoluteSymbols.insert(&Sym); |
1069 | return Sym; |
1070 | } |
1071 | |
1072 | |
1073 | Symbol &addCommonSymbol(StringRef Name, Scope S, Section &Section, |
1074 | JITTargetAddress Address, uint64_t Size, |
1075 | uint64_t Alignment, bool IsLive) { |
1076 | assert(llvm::count_if(defined_symbols(), |
1077 | [&](const Symbol *Sym) { |
1078 | return Sym->getName() == Name; |
1079 | }) == 0 && |
1080 | "Duplicate defined symbol"); |
1081 | auto &Sym = Symbol::constructCommon( |
1082 | Allocator.Allocate<Symbol>(), |
1083 | createBlock(Section, Size, Address, Alignment, 0), Name, Size, S, |
1084 | IsLive); |
1085 | Section.addSymbol(Sym); |
1086 | return Sym; |
1087 | } |
1088 | |
1089 | |
1090 | Symbol &addAnonymousSymbol(Block &Content, JITTargetAddress Offset, |
1091 | JITTargetAddress Size, bool IsCallable, |
1092 | bool IsLive) { |
1093 | auto &Sym = Symbol::constructAnonDef(Allocator.Allocate<Symbol>(), Content, |
1094 | Offset, Size, IsCallable, IsLive); |
1095 | Content.getSection().addSymbol(Sym); |
1096 | return Sym; |
1097 | } |
1098 | |
1099 | |
1100 | Symbol &addDefinedSymbol(Block &Content, JITTargetAddress Offset, |
1101 | StringRef Name, JITTargetAddress Size, Linkage L, |
1102 | Scope S, bool IsCallable, bool IsLive) { |
1103 | assert(llvm::count_if(defined_symbols(), |
1104 | [&](const Symbol *Sym) { |
1105 | return Sym->getName() == Name; |
1106 | }) == 0 && |
1107 | "Duplicate defined symbol"); |
1108 | auto &Sym = |
1109 | Symbol::constructNamedDef(Allocator.Allocate<Symbol>(), Content, Offset, |
1110 | Name, Size, L, S, IsLive, IsCallable); |
1111 | Content.getSection().addSymbol(Sym); |
1112 | return Sym; |
1113 | } |
1114 | |
1115 | iterator_range<section_iterator> sections() { |
1116 | return make_range(section_iterator(Sections.begin()), |
1117 | section_iterator(Sections.end())); |
1118 | } |
1119 | |
1120 | SectionList::size_type sections_size() const { return Sections.size(); } |
1121 | |
1122 | |
1123 | |
1124 | Section *findSectionByName(StringRef Name) { |
1125 | for (auto &S : sections()) |
1126 | if (S.getName() == Name) |
1127 | return &S; |
1128 | return nullptr; |
1129 | } |
1130 | |
1131 | iterator_range<block_iterator> blocks() { |
1132 | return make_range(block_iterator(Sections.begin(), Sections.end()), |
1133 | block_iterator(Sections.end(), Sections.end())); |
1134 | } |
1135 | |
1136 | iterator_range<const_block_iterator> blocks() const { |
1137 | return make_range(const_block_iterator(Sections.begin(), Sections.end()), |
1138 | const_block_iterator(Sections.end(), Sections.end())); |
1139 | } |
1140 | |
1141 | iterator_range<external_symbol_iterator> external_symbols() { |
1142 | return make_range(ExternalSymbols.begin(), ExternalSymbols.end()); |
1143 | } |
1144 | |
1145 | iterator_range<external_symbol_iterator> absolute_symbols() { |
1146 | return make_range(AbsoluteSymbols.begin(), AbsoluteSymbols.end()); |
1147 | } |
1148 | |
1149 | iterator_range<defined_symbol_iterator> defined_symbols() { |
1150 | return make_range(defined_symbol_iterator(Sections.begin(), Sections.end()), |
1151 | defined_symbol_iterator(Sections.end(), Sections.end())); |
1152 | } |
1153 | |
1154 | iterator_range<const_defined_symbol_iterator> defined_symbols() const { |
1155 | return make_range( |
1156 | const_defined_symbol_iterator(Sections.begin(), Sections.end()), |
1157 | const_defined_symbol_iterator(Sections.end(), Sections.end())); |
1158 | } |
1159 | |
1160 | |
1161 | |
1162 | |
1163 | |
1164 | void makeExternal(Symbol &Sym) { |
1165 | assert(!Sym.isExternal() && "Symbol is already external"); |
1166 | if (Sym.isAbsolute()) { |
1167 | assert(AbsoluteSymbols.count(&Sym) && |
1168 | "Sym is not in the absolute symbols set"); |
1169 | assert(Sym.getOffset() == 0 && "Absolute not at offset 0"); |
1170 | AbsoluteSymbols.erase(&Sym); |
1171 | Sym.getAddressable().setAbsolute(false); |
1172 | } else { |
1173 | assert(Sym.isDefined() && "Sym is not a defined symbol"); |
1174 | Section &Sec = Sym.getBlock().getSection(); |
1175 | Sec.removeSymbol(Sym); |
1176 | Sym.makeExternal(createAddressable(0, false)); |
1177 | } |
1178 | ExternalSymbols.insert(&Sym); |
1179 | } |
1180 | |
1181 | |
1182 | |
1183 | |
1184 | |
1185 | |
1186 | void makeAbsolute(Symbol &Sym, JITTargetAddress Address) { |
1187 | assert(!Sym.isAbsolute() && "Symbol is already absolute"); |
1188 | if (Sym.isExternal()) { |
1189 | assert(ExternalSymbols.count(&Sym) && |
1190 | "Sym is not in the absolute symbols set"); |
1191 | assert(Sym.getOffset() == 0 && "External is not at offset 0"); |
1192 | ExternalSymbols.erase(&Sym); |
1193 | Sym.getAddressable().setAbsolute(true); |
1194 | } else { |
1195 | assert(Sym.isDefined() && "Sym is not a defined symbol"); |
1196 | Section &Sec = Sym.getBlock().getSection(); |
1197 | Sec.removeSymbol(Sym); |
1198 | Sym.makeAbsolute(createAddressable(Address)); |
1199 | } |
1200 | AbsoluteSymbols.insert(&Sym); |
1201 | } |
1202 | |
1203 | |
1204 | |
1205 | void makeDefined(Symbol &Sym, Block &Content, JITTargetAddress Offset, |
1206 | JITTargetAddress Size, Linkage L, Scope S, bool IsLive) { |
1207 | assert(!Sym.isDefined() && "Sym is already a defined symbol"); |
1208 | if (Sym.isAbsolute()) { |
1209 | assert(AbsoluteSymbols.count(&Sym) && |
1210 | "Symbol is not in the absolutes set"); |
1211 | AbsoluteSymbols.erase(&Sym); |
1212 | } else { |
1213 | assert(ExternalSymbols.count(&Sym) && |
1214 | "Symbol is not in the externals set"); |
1215 | ExternalSymbols.erase(&Sym); |
1216 | } |
1217 | Addressable &OldBase = *Sym.Base; |
1218 | Sym.setBlock(Content); |
1219 | Sym.setOffset(Offset); |
1220 | Sym.setSize(Size); |
1221 | Sym.setLinkage(L); |
1222 | Sym.setScope(S); |
1223 | Sym.setLive(IsLive); |
1224 | Content.getSection().addSymbol(Sym); |
1225 | destroyAddressable(OldBase); |
1226 | } |
1227 | |
1228 | |
1229 | |
1230 | |
1231 | |
1232 | |
1233 | |
1234 | |
1235 | |
1236 | |
1237 | void transferDefinedSymbol(Symbol &Sym, Block &DestBlock, |
1238 | JITTargetAddress NewOffset, |
1239 | Optional<JITTargetAddress> ExplicitNewSize) { |
1240 | Sym.setBlock(DestBlock); |
1241 | Sym.setOffset(NewOffset); |
1242 | if (ExplicitNewSize) |
1243 | Sym.setSize(*ExplicitNewSize); |
1244 | else { |
1245 | JITTargetAddress RemainingBlockSize = DestBlock.getSize() - NewOffset; |
1246 | if (Sym.getSize() > RemainingBlockSize) |
1247 | Sym.setSize(RemainingBlockSize); |
1248 | } |
1249 | } |
1250 | |
1251 | |
1252 | |
1253 | |
1254 | |
1255 | |
1256 | |
1257 | |
1258 | void transferBlock(Block &B, Section &NewSection) { |
1259 | auto &OldSection = B.getSection(); |
1260 | if (&OldSection == &NewSection) |
1261 | return; |
1262 | SmallVector<Symbol *> AttachedSymbols; |
1263 | for (auto *S : OldSection.symbols()) |
1264 | if (&S->getBlock() == &B) |
1265 | AttachedSymbols.push_back(S); |
1266 | for (auto *S : AttachedSymbols) { |
1267 | OldSection.removeSymbol(*S); |
1268 | NewSection.addSymbol(*S); |
1269 | } |
1270 | OldSection.removeBlock(B); |
1271 | NewSection.addBlock(B); |
1272 | } |
1273 | |
1274 | |
1275 | |
1276 | |
1277 | |
1278 | |
1279 | void mergeSections(Section &DstSection, Section &SrcSection, |
1280 | bool PreserveSrcSection = false) { |
1281 | if (&DstSection == &SrcSection) |
1282 | return; |
1283 | SrcSection.transferContentTo(DstSection); |
1284 | if (!PreserveSrcSection) |
1285 | removeSection(SrcSection); |
1286 | } |
1287 | |
1288 | |
1289 | void removeExternalSymbol(Symbol &Sym) { |
1290 | assert(!Sym.isDefined() && !Sym.isAbsolute() && |
1291 | "Sym is not an external symbol"); |
1292 | assert(ExternalSymbols.count(&Sym) && "Symbol is not in the externals set"); |
1293 | ExternalSymbols.erase(&Sym); |
1294 | Addressable &Base = *Sym.Base; |
1295 | assert(llvm::find_if(ExternalSymbols, |
1296 | [&](Symbol *AS) { return AS->Base == &Base; }) == |
1297 | ExternalSymbols.end() && |
1298 | "Base addressable still in use"); |
1299 | destroySymbol(Sym); |
1300 | destroyAddressable(Base); |
1301 | } |
1302 | |
1303 | |
1304 | void removeAbsoluteSymbol(Symbol &Sym) { |
1305 | assert(!Sym.isDefined() && Sym.isAbsolute() && |
1306 | "Sym is not an absolute symbol"); |
1307 | assert(AbsoluteSymbols.count(&Sym) && |
1308 | "Symbol is not in the absolute symbols set"); |
1309 | AbsoluteSymbols.erase(&Sym); |
1310 | Addressable &Base = *Sym.Base; |
1311 | assert(llvm::find_if(ExternalSymbols, |
1312 | [&](Symbol *AS) { return AS->Base == &Base; }) == |
1313 | ExternalSymbols.end() && |
1314 | "Base addressable still in use"); |
1315 | destroySymbol(Sym); |
1316 | destroyAddressable(Base); |
1317 | } |
1318 | |
1319 | |
1320 | void removeDefinedSymbol(Symbol &Sym) { |
1321 | assert(Sym.isDefined() && "Sym is not a defined symbol"); |
1322 | Sym.getBlock().getSection().removeSymbol(Sym); |
1323 | destroySymbol(Sym); |
1324 | } |
1325 | |
1326 | |
1327 | |
1328 | void removeBlock(Block &B) { |
1329 | assert(llvm::none_of(B.getSection().symbols(), |
1330 | [&](const Symbol *Sym) { |
1331 | return &Sym->getBlock() == &B; |
1332 | }) && |
1333 | "Block still has symbols attached"); |
1334 | B.getSection().removeBlock(B); |
1335 | destroyBlock(B); |
1336 | } |
1337 | |
1338 | |
1339 | |
1340 | void removeSection(Section &Sec) { |
1341 | auto I = llvm::find_if(Sections, [&Sec](const std::unique_ptr<Section> &S) { |
1342 | return S.get() == &Sec; |
1343 | }); |
1344 | assert(I != Sections.end() && "Section does not appear in this graph"); |
1345 | Sections.erase(I); |
1346 | } |
1347 | |
1348 | |
1349 | void dump(raw_ostream &OS); |
1350 | |
1351 | private: |
1352 | |
1353 | |
1354 | BumpPtrAllocator Allocator; |
1355 | |
1356 | std::string Name; |
1357 | Triple TT; |
1358 | unsigned PointerSize; |
1359 | support::endianness Endianness; |
1360 | GetEdgeKindNameFunction GetEdgeKindName = nullptr; |
1361 | SectionList Sections; |
1362 | ExternalSymbolSet ExternalSymbols; |
1363 | ExternalSymbolSet AbsoluteSymbols; |
1364 | }; |
1365 | |
1366 | inline MutableArrayRef<char> Block::getMutableContent(LinkGraph &G) { |
1367 | if (!ContentMutable) |
1368 | setMutableContent(G.allocateContent({Data, Size})); |
1369 | return MutableArrayRef<char>(const_cast<char *>(Data), Size); |
1370 | } |
1371 | |
1372 | |
1373 | class BlockAddressMap { |
1374 | public: |
1375 | using AddrToBlockMap = std::map<JITTargetAddress, Block *>; |
1376 | using const_iterator = AddrToBlockMap::const_iterator; |
1377 | |
1378 | |
1379 | static bool includeAllBlocks(const Block &B) { return true; } |
1380 | |
1381 | |
1382 | static bool includeNonNull(const Block &B) { return B.getAddress(); } |
1383 | |
1384 | BlockAddressMap() = default; |
1385 | |
1386 | |
1387 | |
1388 | template <typename PredFn = decltype(includeAllBlocks)> |
1389 | Error addBlock(Block &B, PredFn Pred = includeAllBlocks) { |
1390 | if (!Pred(B)) |
1391 | return Error::success(); |
1392 | |
1393 | auto I = AddrToBlock.upper_bound(B.getAddress()); |
1394 | |
1395 | |
1396 | |
1397 | if (I != AddrToBlock.end()) { |
1398 | if (B.getAddress() + B.getSize() > I->second->getAddress()) |
1399 | return overlapError(B, *I->second); |
1400 | } |
1401 | |
1402 | |
1403 | |
1404 | if (I != AddrToBlock.begin()) { |
1405 | auto &PrevBlock = *std::prev(I)->second; |
1406 | if (PrevBlock.getAddress() + PrevBlock.getSize() > B.getAddress()) |
1407 | return overlapError(B, PrevBlock); |
1408 | } |
1409 | |
1410 | AddrToBlock.insert(I, std::make_pair(B.getAddress(), &B)); |
1411 | return Error::success(); |
1412 | } |
1413 | |
1414 | |
1415 | |
1416 | |
1417 | void addBlockWithoutChecking(Block &B) { AddrToBlock[B.getAddress()] = &B; } |
1418 | |
1419 | |
1420 | |
1421 | |
1422 | template <typename BlockPtrRange, |
1423 | typename PredFn = decltype(includeAllBlocks)> |
1424 | Error addBlocks(BlockPtrRange &&Blocks, PredFn Pred = includeAllBlocks) { |
1425 | for (auto *B : Blocks) |
1426 | if (auto Err = addBlock(*B, Pred)) |
1427 | return Err; |
1428 | return Error::success(); |
1429 | } |
1430 | |
1431 | |
1432 | |
1433 | |
1434 | template <typename BlockPtrRange> |
1435 | void addBlocksWithoutChecking(BlockPtrRange &&Blocks) { |
1436 | for (auto *B : Blocks) |
1437 | addBlockWithoutChecking(*B); |
1438 | } |
1439 | |
1440 | |
1441 | const_iterator begin() const { return AddrToBlock.begin(); } |
1442 | const_iterator end() const { return AddrToBlock.end(); } |
1443 | |
1444 | |
1445 | |
1446 | Block *getBlockAt(JITTargetAddress Addr) const { |
1447 | auto I = AddrToBlock.find(Addr); |
1448 | if (I == AddrToBlock.end()) |
1449 | return nullptr; |
1450 | return I->second; |
1451 | } |
1452 | |
1453 | |
1454 | |
1455 | Block *getBlockCovering(JITTargetAddress Addr) const { |
1456 | auto I = AddrToBlock.upper_bound(Addr); |
1457 | if (I == AddrToBlock.begin()) |
1458 | return nullptr; |
1459 | auto *B = std::prev(I)->second; |
1460 | if (Addr < B->getAddress() + B->getSize()) |
1461 | return B; |
1462 | return nullptr; |
1463 | } |
1464 | |
1465 | private: |
1466 | Error overlapError(Block &NewBlock, Block &ExistingBlock) { |
1467 | auto NewBlockEnd = NewBlock.getAddress() + NewBlock.getSize(); |
1468 | auto ExistingBlockEnd = |
1469 | ExistingBlock.getAddress() + ExistingBlock.getSize(); |
1470 | return make_error<JITLinkError>( |
1471 | "Block at " + |
1472 | formatv("{0:x16} -- {1:x16}", NewBlock.getAddress(), NewBlockEnd) + |
1473 | " overlaps " + |
1474 | formatv("{0:x16} -- {1:x16}", ExistingBlock.getAddress(), |
1475 | ExistingBlockEnd)); |
1476 | } |
1477 | |
1478 | AddrToBlockMap AddrToBlock; |
1479 | }; |
1480 | |
1481 | |
1482 | class SymbolAddressMap { |
1483 | public: |
1484 | using SymbolVector = SmallVector<Symbol *, 1>; |
1485 | |
1486 | |
1487 | void addSymbol(Symbol &Sym) { |
1488 | AddrToSymbols[Sym.getAddress()].push_back(&Sym); |
1489 | } |
1490 | |
1491 | |
1492 | template <typename SymbolPtrCollection> |
1493 | void addSymbols(SymbolPtrCollection &&Symbols) { |
1494 | for (auto *Sym : Symbols) |
1495 | addSymbol(*Sym); |
1496 | } |
1497 | |
1498 | |
1499 | |
1500 | const SymbolVector *getSymbolsAt(JITTargetAddress Addr) const { |
1501 | auto I = AddrToSymbols.find(Addr); |
1502 | if (I == AddrToSymbols.end()) |
1503 | return nullptr; |
1504 | return &I->second; |
1505 | } |
1506 | |
1507 | private: |
1508 | std::map<JITTargetAddress, SymbolVector> AddrToSymbols; |
1509 | }; |
1510 | |
1511 | |
1512 | using LinkGraphPassFunction = std::function<Error(LinkGraph &)>; |
1513 | |
1514 | |
1515 | using LinkGraphPassList = std::vector<LinkGraphPassFunction>; |
1516 | |
1517 | |
1518 | |
1519 | struct PassConfiguration { |
1520 | |
1521 | |
1522 | |
1523 | |
1524 | |
1525 | |
1526 | |
1527 | LinkGraphPassList PrePrunePasses; |
1528 | |
1529 | |
1530 | |
1531 | |
1532 | |
1533 | |
1534 | |
1535 | LinkGraphPassList PostPrunePasses; |
1536 | |
1537 | |
1538 | |
1539 | |
1540 | |
1541 | |
1542 | |
1543 | |
1544 | |
1545 | |
1546 | |
1547 | |
1548 | |
1549 | |
1550 | LinkGraphPassList PostAllocationPasses; |
1551 | |
1552 | |
1553 | |
1554 | |
1555 | |
1556 | |
1557 | |
1558 | |
1559 | |
1560 | |
1561 | LinkGraphPassList PreFixupPasses; |
1562 | |
1563 | |
1564 | |
1565 | |
1566 | |
1567 | |
1568 | |
1569 | |
1570 | LinkGraphPassList PostFixupPasses; |
1571 | }; |
1572 | |
1573 | |
1574 | |
1575 | |
1576 | |
1577 | enum class SymbolLookupFlags { RequiredSymbol, WeaklyReferencedSymbol }; |
1578 | |
1579 | raw_ostream &operator<<(raw_ostream &OS, const SymbolLookupFlags &LF); |
1580 | |
1581 | |
1582 | using AsyncLookupResult = DenseMap<StringRef, JITEvaluatedSymbol>; |
1583 | |
1584 | |
1585 | |
1586 | class JITLinkAsyncLookupContinuation { |
1587 | public: |
1588 | virtual ~JITLinkAsyncLookupContinuation() {} |
1589 | virtual void run(Expected<AsyncLookupResult> LR) = 0; |
1590 | |
1591 | private: |
1592 | virtual void anchor(); |
1593 | }; |
1594 | |
1595 | |
1596 | template <typename Continuation> |
1597 | std::unique_ptr<JITLinkAsyncLookupContinuation> |
1598 | createLookupContinuation(Continuation Cont) { |
1599 | |
1600 | class Impl final : public JITLinkAsyncLookupContinuation { |
1601 | public: |
1602 | Impl(Continuation C) : C(std::move(C)) {} |
1603 | void run(Expected<AsyncLookupResult> LR) override { C(std::move(LR)); } |
1604 | |
1605 | private: |
1606 | Continuation C; |
1607 | }; |
1608 | |
1609 | return std::make_unique<Impl>(std::move(Cont)); |
1610 | } |
1611 | |
1612 | |
1613 | class JITLinkContext { |
1614 | public: |
1615 | using LookupMap = DenseMap<StringRef, SymbolLookupFlags>; |
1616 | |
1617 | |
1618 | JITLinkContext(const JITLinkDylib *JD) : JD(JD) {} |
1619 | |
1620 | |
1621 | virtual ~JITLinkContext(); |
1622 | |
1623 | |
1624 | const JITLinkDylib *getJITLinkDylib() const { return JD; } |
1625 | |
1626 | |
1627 | virtual JITLinkMemoryManager &getMemoryManager() = 0; |
1628 | |
1629 | |
1630 | |
1631 | virtual void notifyFailed(Error Err) = 0; |
1632 | |
1633 | |
1634 | |
1635 | |
1636 | virtual void lookup(const LookupMap &Symbols, |
1637 | std::unique_ptr<JITLinkAsyncLookupContinuation> LC) = 0; |
1638 | |
1639 | |
1640 | |
1641 | |
1642 | |
1643 | |
1644 | |
1645 | |
1646 | |
1647 | virtual Error notifyResolved(LinkGraph &G) = 0; |
1648 | |
1649 | |
1650 | |
1651 | |
1652 | |
1653 | virtual void |
1654 | notifyFinalized(std::unique_ptr<JITLinkMemoryManager::Allocation> A) = 0; |
1655 | |
1656 | |
1657 | |
1658 | |
1659 | |
1660 | virtual bool shouldAddDefaultTargetPasses(const Triple &TT) const; |
1661 | |
1662 | |
1663 | |
1664 | |
1665 | |
1666 | |
1667 | |
1668 | virtual LinkGraphPassFunction getMarkLivePass(const Triple &TT) const; |
1669 | |
1670 | |
1671 | |
1672 | virtual Error modifyPassConfig(LinkGraph &G, PassConfiguration &Config); |
1673 | |
1674 | private: |
1675 | const JITLinkDylib *JD = nullptr; |
1676 | }; |
1677 | |
1678 | |
1679 | |
1680 | Error markAllSymbolsLive(LinkGraph &G); |
1681 | |
1682 | |
1683 | Error makeTargetOutOfRangeError(const LinkGraph &G, const Block &B, |
1684 | const Edge &E); |
1685 | |
1686 | |
1687 | |
1688 | |
1689 | |
1690 | |
1691 | Expected<std::unique_ptr<LinkGraph>> |
1692 | createLinkGraphFromObject(MemoryBufferRef ObjectBuffer); |
1693 | |
1694 | |
1695 | void link(std::unique_ptr<LinkGraph> G, std::unique_ptr<JITLinkContext> Ctx); |
1696 | |
1697 | } |
1698 | } |
1699 | |
1700 | #endif // LLVM_EXECUTIONENGINE_JITLINK_JITLINK_H |