1 | //===----- ELF_aarch64.cpp - JIT linker implementation for ELF/aarch64 ----===// |
---|---|
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 | // ELF/aarch64 jit-link implementation. |
10 | // |
11 | //===----------------------------------------------------------------------===// |
12 | |
13 | #include "llvm/ExecutionEngine/JITLink/ELF_aarch64.h" |
14 | #include "llvm/BinaryFormat/ELF.h" |
15 | #include "llvm/ExecutionEngine/JITLink/DWARFRecordSectionSplitter.h" |
16 | #include "llvm/ExecutionEngine/JITLink/aarch64.h" |
17 | #include "llvm/Object/ELFObjectFile.h" |
18 | #include "llvm/Support/Endian.h" |
19 | |
20 | #include "DefineExternalSectionStartAndEndSymbols.h" |
21 | #include "EHFrameSupportImpl.h" |
22 | #include "ELFLinkGraphBuilder.h" |
23 | #include "JITLinkGeneric.h" |
24 | |
25 | #define DEBUG_TYPE "jitlink" |
26 | |
27 | using namespace llvm; |
28 | using namespace llvm::jitlink; |
29 | |
30 | namespace { |
31 | |
32 | class ELFJITLinker_aarch64 : public JITLinker<ELFJITLinker_aarch64> { |
33 | friend class JITLinker<ELFJITLinker_aarch64>; |
34 | |
35 | public: |
36 | ELFJITLinker_aarch64(std::unique_ptr<JITLinkContext> Ctx, |
37 | std::unique_ptr<LinkGraph> G, |
38 | PassConfiguration PassConfig) |
39 | : JITLinker(std::move(Ctx), std::move(G), std::move(PassConfig)) {} |
40 | |
41 | private: |
42 | Error applyFixup(LinkGraph &G, Block &B, const Edge &E) const { |
43 | return aarch64::applyFixup(G, B, E); |
44 | } |
45 | }; |
46 | |
47 | template <typename ELFT> |
48 | class ELFLinkGraphBuilder_aarch64 : public ELFLinkGraphBuilder<ELFT> { |
49 | private: |
50 | enum ELFAArch64RelocationKind : Edge::Kind { |
51 | ELFCall26 = Edge::FirstRelocation, |
52 | ELFAdrLo21, |
53 | ELFAdrPage21, |
54 | ELFAddAbs12, |
55 | ELFLdSt8Abs12, |
56 | ELFLdSt16Abs12, |
57 | ELFLdSt32Abs12, |
58 | ELFLdSt64Abs12, |
59 | ELFLdSt128Abs12, |
60 | ELFMovwAbsG0, |
61 | ELFMovwAbsG1, |
62 | ELFMovwAbsG2, |
63 | ELFMovwAbsG3, |
64 | ELFTstBr14, |
65 | ELFCondBr19, |
66 | ELFAbs32, |
67 | ELFAbs64, |
68 | ELFPrel32, |
69 | ELFPrel64, |
70 | ELFAdrGOTPage21, |
71 | ELFLd64GOTLo12, |
72 | ELFTLSDescAdrPage21, |
73 | ELFTLSDescAddLo12, |
74 | ELFTLSDescLd64Lo12, |
75 | ELFTLSDescCall, |
76 | }; |
77 | |
78 | static Expected<ELFAArch64RelocationKind> |
79 | getRelocationKind(const uint32_t Type) { |
80 | using namespace aarch64; |
81 | switch (Type) { |
82 | case ELF::R_AARCH64_CALL26: |
83 | case ELF::R_AARCH64_JUMP26: |
84 | return ELFCall26; |
85 | case ELF::R_AARCH64_ADR_PREL_LO21: |
86 | return ELFAdrLo21; |
87 | case ELF::R_AARCH64_ADR_PREL_PG_HI21: |
88 | return ELFAdrPage21; |
89 | case ELF::R_AARCH64_ADD_ABS_LO12_NC: |
90 | return ELFAddAbs12; |
91 | case ELF::R_AARCH64_LDST8_ABS_LO12_NC: |
92 | return ELFLdSt8Abs12; |
93 | case ELF::R_AARCH64_LDST16_ABS_LO12_NC: |
94 | return ELFLdSt16Abs12; |
95 | case ELF::R_AARCH64_LDST32_ABS_LO12_NC: |
96 | return ELFLdSt32Abs12; |
97 | case ELF::R_AARCH64_LDST64_ABS_LO12_NC: |
98 | return ELFLdSt64Abs12; |
99 | case ELF::R_AARCH64_LDST128_ABS_LO12_NC: |
100 | return ELFLdSt128Abs12; |
101 | case ELF::R_AARCH64_MOVW_UABS_G0_NC: |
102 | return ELFMovwAbsG0; |
103 | case ELF::R_AARCH64_MOVW_UABS_G1_NC: |
104 | return ELFMovwAbsG1; |
105 | case ELF::R_AARCH64_MOVW_UABS_G2_NC: |
106 | return ELFMovwAbsG2; |
107 | case ELF::R_AARCH64_MOVW_UABS_G3: |
108 | return ELFMovwAbsG3; |
109 | case ELF::R_AARCH64_TSTBR14: |
110 | return ELFTstBr14; |
111 | case ELF::R_AARCH64_CONDBR19: |
112 | return ELFCondBr19; |
113 | case ELF::R_AARCH64_ABS32: |
114 | return ELFAbs32; |
115 | case ELF::R_AARCH64_ABS64: |
116 | return ELFAbs64; |
117 | case ELF::R_AARCH64_PREL32: |
118 | return ELFPrel32; |
119 | case ELF::R_AARCH64_PREL64: |
120 | return ELFPrel64; |
121 | case ELF::R_AARCH64_ADR_GOT_PAGE: |
122 | return ELFAdrGOTPage21; |
123 | case ELF::R_AARCH64_LD64_GOT_LO12_NC: |
124 | return ELFLd64GOTLo12; |
125 | case ELF::R_AARCH64_TLSDESC_ADR_PAGE21: |
126 | return ELFTLSDescAdrPage21; |
127 | case ELF::R_AARCH64_TLSDESC_ADD_LO12: |
128 | return ELFTLSDescAddLo12; |
129 | case ELF::R_AARCH64_TLSDESC_LD64_LO12: |
130 | return ELFTLSDescLd64Lo12; |
131 | case ELF::R_AARCH64_TLSDESC_CALL: |
132 | return ELFTLSDescCall; |
133 | } |
134 | |
135 | return make_error<JITLinkError>( |
136 | Args: "Unsupported aarch64 relocation:"+ formatv(Fmt: "{0:d}: ", Vals: Type) + |
137 | object::getELFRelocationTypeName(Machine: ELF::EM_AARCH64, Type)); |
138 | } |
139 | |
140 | Error addRelocations() override { |
141 | LLVM_DEBUG(dbgs() << "Processing relocations:\n"); |
142 | |
143 | using Base = ELFLinkGraphBuilder<ELFT>; |
144 | using Self = ELFLinkGraphBuilder_aarch64<ELFT>; |
145 | for (const auto &RelSect : Base::Sections) |
146 | if (Error Err = Base::forEachRelaRelocation(RelSect, this, |
147 | &Self::addSingleRelocation)) |
148 | return Err; |
149 | |
150 | return Error::success(); |
151 | } |
152 | |
153 | Error addSingleRelocation(const typename ELFT::Rela &Rel, |
154 | const typename ELFT::Shdr &FixupSect, |
155 | Block &BlockToFix) { |
156 | using support::ulittle32_t; |
157 | using Base = ELFLinkGraphBuilder<ELFT>; |
158 | |
159 | uint32_t SymbolIndex = Rel.getSymbol(false); |
160 | auto ObjSymbol = Base::Obj.getRelocationSymbol(Rel, Base::SymTabSec); |
161 | if (!ObjSymbol) |
162 | return ObjSymbol.takeError(); |
163 | |
164 | Symbol *GraphSymbol = Base::getGraphSymbol(SymbolIndex); |
165 | if (!GraphSymbol) |
166 | return make_error<StringError>( |
167 | formatv("Could not find symbol at given index, did you add it to " |
168 | "JITSymbolTable? index: {0}, shndx: {1} Size of table: {2}", |
169 | SymbolIndex, (*ObjSymbol)->st_shndx, |
170 | Base::GraphSymbols.size()), |
171 | inconvertibleErrorCode()); |
172 | |
173 | uint32_t Type = Rel.getType(false); |
174 | Expected<ELFAArch64RelocationKind> RelocKind = getRelocationKind(Type); |
175 | if (!RelocKind) |
176 | return RelocKind.takeError(); |
177 | |
178 | int64_t Addend = Rel.r_addend; |
179 | orc::ExecutorAddr FixupAddress = |
180 | orc::ExecutorAddr(FixupSect.sh_addr) + Rel.r_offset; |
181 | Edge::OffsetT Offset = FixupAddress - BlockToFix.getAddress(); |
182 | |
183 | // Get a pointer to the fixup content. |
184 | const void *FixupContent = BlockToFix.getContent().data() + |
185 | (FixupAddress - BlockToFix.getAddress()); |
186 | |
187 | Edge::Kind Kind = Edge::Invalid; |
188 | |
189 | switch (*RelocKind) { |
190 | case ELFCall26: { |
191 | Kind = aarch64::Branch26PCRel; |
192 | break; |
193 | } |
194 | case ELFAdrLo21: { |
195 | uint32_t Instr = *(const ulittle32_t *)FixupContent; |
196 | if (!aarch64::isADR(Instr)) |
197 | return make_error<JITLinkError>( |
198 | Args: "R_AARCH64_ADR_PREL_LO21 target is not an ADR instruction"); |
199 | |
200 | Kind = aarch64::ADRLiteral21; |
201 | break; |
202 | } |
203 | case ELFAdrPage21: { |
204 | Kind = aarch64::Page21; |
205 | break; |
206 | } |
207 | case ELFAddAbs12: { |
208 | Kind = aarch64::PageOffset12; |
209 | break; |
210 | } |
211 | case ELFLdSt8Abs12: { |
212 | uint32_t Instr = *(const ulittle32_t *)FixupContent; |
213 | if (!aarch64::isLoadStoreImm12(Instr) || |
214 | aarch64::getPageOffset12Shift(Instr) != 0) |
215 | return make_error<JITLinkError>( |
216 | Args: "R_AARCH64_LDST8_ABS_LO12_NC target is not a " |
217 | "LDRB/STRB (imm12) instruction"); |
218 | |
219 | Kind = aarch64::PageOffset12; |
220 | break; |
221 | } |
222 | case ELFLdSt16Abs12: { |
223 | uint32_t Instr = *(const ulittle32_t *)FixupContent; |
224 | if (!aarch64::isLoadStoreImm12(Instr) || |
225 | aarch64::getPageOffset12Shift(Instr) != 1) |
226 | return make_error<JITLinkError>( |
227 | Args: "R_AARCH64_LDST16_ABS_LO12_NC target is not a " |
228 | "LDRH/STRH (imm12) instruction"); |
229 | |
230 | Kind = aarch64::PageOffset12; |
231 | break; |
232 | } |
233 | case ELFLdSt32Abs12: { |
234 | uint32_t Instr = *(const ulittle32_t *)FixupContent; |
235 | if (!aarch64::isLoadStoreImm12(Instr) || |
236 | aarch64::getPageOffset12Shift(Instr) != 2) |
237 | return make_error<JITLinkError>( |
238 | Args: "R_AARCH64_LDST32_ABS_LO12_NC target is not a " |
239 | "LDR/STR (imm12, 32 bit) instruction"); |
240 | |
241 | Kind = aarch64::PageOffset12; |
242 | break; |
243 | } |
244 | case ELFLdSt64Abs12: { |
245 | uint32_t Instr = *(const ulittle32_t *)FixupContent; |
246 | if (!aarch64::isLoadStoreImm12(Instr) || |
247 | aarch64::getPageOffset12Shift(Instr) != 3) |
248 | return make_error<JITLinkError>( |
249 | Args: "R_AARCH64_LDST64_ABS_LO12_NC target is not a " |
250 | "LDR/STR (imm12, 64 bit) instruction"); |
251 | |
252 | Kind = aarch64::PageOffset12; |
253 | break; |
254 | } |
255 | case ELFLdSt128Abs12: { |
256 | uint32_t Instr = *(const ulittle32_t *)FixupContent; |
257 | if (!aarch64::isLoadStoreImm12(Instr) || |
258 | aarch64::getPageOffset12Shift(Instr) != 4) |
259 | return make_error<JITLinkError>( |
260 | Args: "R_AARCH64_LDST128_ABS_LO12_NC target is not a " |
261 | "LDR/STR (imm12, 128 bit) instruction"); |
262 | |
263 | Kind = aarch64::PageOffset12; |
264 | break; |
265 | } |
266 | case ELFMovwAbsG0: { |
267 | uint32_t Instr = *(const ulittle32_t *)FixupContent; |
268 | if (!aarch64::isMoveWideImm16(Instr) || |
269 | aarch64::getMoveWide16Shift(Instr) != 0) |
270 | return make_error<JITLinkError>( |
271 | Args: "R_AARCH64_MOVW_UABS_G0_NC target is not a " |
272 | "MOVK/MOVZ (imm16, LSL #0) instruction"); |
273 | |
274 | Kind = aarch64::MoveWide16; |
275 | break; |
276 | } |
277 | case ELFMovwAbsG1: { |
278 | uint32_t Instr = *(const ulittle32_t *)FixupContent; |
279 | if (!aarch64::isMoveWideImm16(Instr) || |
280 | aarch64::getMoveWide16Shift(Instr) != 16) |
281 | return make_error<JITLinkError>( |
282 | Args: "R_AARCH64_MOVW_UABS_G1_NC target is not a " |
283 | "MOVK/MOVZ (imm16, LSL #16) instruction"); |
284 | |
285 | Kind = aarch64::MoveWide16; |
286 | break; |
287 | } |
288 | case ELFMovwAbsG2: { |
289 | uint32_t Instr = *(const ulittle32_t *)FixupContent; |
290 | if (!aarch64::isMoveWideImm16(Instr) || |
291 | aarch64::getMoveWide16Shift(Instr) != 32) |
292 | return make_error<JITLinkError>( |
293 | Args: "R_AARCH64_MOVW_UABS_G2_NC target is not a " |
294 | "MOVK/MOVZ (imm16, LSL #32) instruction"); |
295 | |
296 | Kind = aarch64::MoveWide16; |
297 | break; |
298 | } |
299 | case ELFMovwAbsG3: { |
300 | uint32_t Instr = *(const ulittle32_t *)FixupContent; |
301 | if (!aarch64::isMoveWideImm16(Instr) || |
302 | aarch64::getMoveWide16Shift(Instr) != 48) |
303 | return make_error<JITLinkError>( |
304 | Args: "R_AARCH64_MOVW_UABS_G3 target is not a " |
305 | "MOVK/MOVZ (imm16, LSL #48) instruction"); |
306 | |
307 | Kind = aarch64::MoveWide16; |
308 | break; |
309 | } |
310 | case ELFTstBr14: { |
311 | uint32_t Instr = *(const ulittle32_t *)FixupContent; |
312 | if (!aarch64::isTestAndBranchImm14(Instr)) |
313 | return make_error<JITLinkError>(Args: "R_AARCH64_TSTBR14 target is not a " |
314 | "test and branch instruction"); |
315 | |
316 | Kind = aarch64::TestAndBranch14PCRel; |
317 | break; |
318 | } |
319 | case ELFCondBr19: { |
320 | uint32_t Instr = *(const ulittle32_t *)FixupContent; |
321 | if (!aarch64::isCondBranchImm19(Instr) && |
322 | !aarch64::isCompAndBranchImm19(Instr)) |
323 | return make_error<JITLinkError>(Args: "R_AARCH64_CONDBR19 target is not a " |
324 | "conditional branch instruction"); |
325 | |
326 | Kind = aarch64::CondBranch19PCRel; |
327 | break; |
328 | } |
329 | case ELFAbs32: { |
330 | Kind = aarch64::Pointer32; |
331 | break; |
332 | } |
333 | case ELFAbs64: { |
334 | Kind = aarch64::Pointer64; |
335 | break; |
336 | } |
337 | case ELFPrel32: { |
338 | Kind = aarch64::Delta32; |
339 | break; |
340 | } |
341 | case ELFPrel64: { |
342 | Kind = aarch64::Delta64; |
343 | break; |
344 | } |
345 | case ELFAdrGOTPage21: { |
346 | Kind = aarch64::RequestGOTAndTransformToPage21; |
347 | break; |
348 | } |
349 | case ELFLd64GOTLo12: { |
350 | Kind = aarch64::RequestGOTAndTransformToPageOffset12; |
351 | break; |
352 | } |
353 | case ELFTLSDescAdrPage21: { |
354 | Kind = aarch64::RequestTLSDescEntryAndTransformToPage21; |
355 | break; |
356 | } |
357 | case ELFTLSDescAddLo12: |
358 | case ELFTLSDescLd64Lo12: { |
359 | Kind = aarch64::RequestTLSDescEntryAndTransformToPageOffset12; |
360 | break; |
361 | } |
362 | case ELFTLSDescCall: { |
363 | return Error::success(); |
364 | } |
365 | }; |
366 | |
367 | Edge GE(Kind, Offset, *GraphSymbol, Addend); |
368 | LLVM_DEBUG({ |
369 | dbgs() << " "; |
370 | printEdge(dbgs(), BlockToFix, GE, aarch64::getEdgeKindName(Kind)); |
371 | dbgs() << "\n"; |
372 | }); |
373 | |
374 | BlockToFix.addEdge(E: std::move(GE)); |
375 | |
376 | return Error::success(); |
377 | } |
378 | |
379 | /// Return the string name of the given ELF aarch64 edge kind. |
380 | const char *getELFAArch64RelocationKindName(Edge::Kind R) { |
381 | switch (R) { |
382 | case ELFCall26: |
383 | return "ELFCall26"; |
384 | case ELFAdrPage21: |
385 | return "ELFAdrPage21"; |
386 | case ELFAddAbs12: |
387 | return "ELFAddAbs12"; |
388 | case ELFLdSt8Abs12: |
389 | return "ELFLdSt8Abs12"; |
390 | case ELFLdSt16Abs12: |
391 | return "ELFLdSt16Abs12"; |
392 | case ELFLdSt32Abs12: |
393 | return "ELFLdSt32Abs12"; |
394 | case ELFLdSt64Abs12: |
395 | return "ELFLdSt64Abs12"; |
396 | case ELFLdSt128Abs12: |
397 | return "ELFLdSt128Abs12"; |
398 | case ELFMovwAbsG0: |
399 | return "ELFMovwAbsG0"; |
400 | case ELFMovwAbsG1: |
401 | return "ELFMovwAbsG1"; |
402 | case ELFMovwAbsG2: |
403 | return "ELFMovwAbsG2"; |
404 | case ELFMovwAbsG3: |
405 | return "ELFMovwAbsG3"; |
406 | case ELFAbs32: |
407 | return "ELFAbs32"; |
408 | case ELFAbs64: |
409 | return "ELFAbs64"; |
410 | case ELFPrel32: |
411 | return "ELFPrel32"; |
412 | case ELFPrel64: |
413 | return "ELFPrel64"; |
414 | case ELFAdrGOTPage21: |
415 | return "ELFAdrGOTPage21"; |
416 | case ELFLd64GOTLo12: |
417 | return "ELFLd64GOTLo12"; |
418 | case ELFTLSDescAdrPage21: |
419 | return "ELFTLSDescAdrPage21"; |
420 | case ELFTLSDescAddLo12: |
421 | return "ELFTLSDescAddLo12"; |
422 | case ELFTLSDescLd64Lo12: |
423 | return "ELFTLSDescLd64Lo12"; |
424 | case ELFTLSDescCall: |
425 | return "ELFTLSDescCall"; |
426 | default: |
427 | return getGenericEdgeKindName(K: static_cast<Edge::Kind>(R)); |
428 | } |
429 | } |
430 | |
431 | public: |
432 | ELFLinkGraphBuilder_aarch64(StringRef FileName, |
433 | const object::ELFFile<ELFT> &Obj, Triple TT, |
434 | SubtargetFeatures Features) |
435 | : ELFLinkGraphBuilder<ELFT>(Obj, std::move(TT), std::move(Features), |
436 | FileName, aarch64::getEdgeKindName) {} |
437 | }; |
438 | |
439 | // TLS Info Builder. |
440 | class TLSInfoTableManager_ELF_aarch64 |
441 | : public TableManager<TLSInfoTableManager_ELF_aarch64> { |
442 | public: |
443 | static StringRef getSectionName() { return "$__TLSINFO"; } |
444 | |
445 | static const uint8_t TLSInfoEntryContent[16]; |
446 | |
447 | bool visitEdge(LinkGraph &G, Block *B, Edge &E) { return false; } |
448 | |
449 | Symbol &createEntry(LinkGraph &G, Symbol &Target) { |
450 | // the TLS Info entry's key value will be written by the fixTLVSectionByName |
451 | // pass, so create mutable content. |
452 | auto &TLSInfoEntry = G.createMutableContentBlock( |
453 | Parent&: getTLSInfoSection(G), MutableContent: G.allocateContent(Source: getTLSInfoEntryContent()), |
454 | Address: orc::ExecutorAddr(), Alignment: 8, AlignmentOffset: 0); |
455 | TLSInfoEntry.addEdge(K: aarch64::Pointer64, Offset: 8, Target, Addend: 0); |
456 | return G.addAnonymousSymbol(Content&: TLSInfoEntry, Offset: 0, Size: 16, IsCallable: false, IsLive: false); |
457 | } |
458 | |
459 | private: |
460 | Section &getTLSInfoSection(LinkGraph &G) { |
461 | if (!TLSInfoTable) |
462 | TLSInfoTable = &G.createSection(Name: getSectionName(), Prot: orc::MemProt::Read); |
463 | return *TLSInfoTable; |
464 | } |
465 | |
466 | ArrayRef<char> getTLSInfoEntryContent() const { |
467 | return {reinterpret_cast<const char *>(TLSInfoEntryContent), |
468 | sizeof(TLSInfoEntryContent)}; |
469 | } |
470 | |
471 | Section *TLSInfoTable = nullptr; |
472 | }; |
473 | |
474 | const uint8_t TLSInfoTableManager_ELF_aarch64::TLSInfoEntryContent[16] = { |
475 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /*pthread key */ |
476 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 /*data address*/ |
477 | }; |
478 | |
479 | // TLS Descriptor Builder. |
480 | class TLSDescTableManager_ELF_aarch64 |
481 | : public TableManager<TLSDescTableManager_ELF_aarch64> { |
482 | public: |
483 | TLSDescTableManager_ELF_aarch64( |
484 | TLSInfoTableManager_ELF_aarch64 &TLSInfoTableManager) |
485 | : TLSInfoTableManager(TLSInfoTableManager) {} |
486 | |
487 | static StringRef getSectionName() { return "$__TLSDESC"; } |
488 | |
489 | static const uint8_t TLSDescEntryContent[16]; |
490 | |
491 | bool visitEdge(LinkGraph &G, Block *B, Edge &E) { |
492 | Edge::Kind KindToSet = Edge::Invalid; |
493 | switch (E.getKind()) { |
494 | case aarch64::RequestTLSDescEntryAndTransformToPage21: { |
495 | KindToSet = aarch64::Page21; |
496 | break; |
497 | } |
498 | case aarch64::RequestTLSDescEntryAndTransformToPageOffset12: { |
499 | KindToSet = aarch64::PageOffset12; |
500 | break; |
501 | } |
502 | default: |
503 | return false; |
504 | } |
505 | assert(KindToSet != Edge::Invalid && |
506 | "Fell through switch, but no new kind to set"); |
507 | DEBUG_WITH_TYPE("jitlink", { |
508 | dbgs() << " Fixing "<< G.getEdgeKindName(E.getKind()) << " edge at " |
509 | << B->getFixupAddress(E) << " ("<< B->getAddress() << " + " |
510 | << formatv("{0:x}", E.getOffset()) << ")\n"; |
511 | }); |
512 | E.setKind(KindToSet); |
513 | E.setTarget(getEntryForTarget(G, Target&: E.getTarget())); |
514 | return true; |
515 | } |
516 | |
517 | Symbol &createEntry(LinkGraph &G, Symbol &Target) { |
518 | auto &EntryBlock = |
519 | G.createContentBlock(Parent&: getTLSDescSection(G), Content: getTLSDescBlockContent(), |
520 | Address: orc::ExecutorAddr(), Alignment: 8, AlignmentOffset: 0); |
521 | EntryBlock.addEdge(K: aarch64::Pointer64, Offset: 0, Target&: getTLSDescResolver(G), Addend: 0); |
522 | EntryBlock.addEdge(K: aarch64::Pointer64, Offset: 8, |
523 | Target&: TLSInfoTableManager.getEntryForTarget(G, Target), Addend: 0); |
524 | return G.addAnonymousSymbol(Content&: EntryBlock, Offset: 0, Size: 8, IsCallable: false, IsLive: false); |
525 | } |
526 | |
527 | private: |
528 | Section &getTLSDescSection(LinkGraph &G) { |
529 | if (!GOTSection) |
530 | GOTSection = &G.createSection(Name: getSectionName(), Prot: orc::MemProt::Read); |
531 | return *GOTSection; |
532 | } |
533 | |
534 | Symbol &getTLSDescResolver(LinkGraph &G) { |
535 | if (!TLSDescResolver) |
536 | TLSDescResolver = &G.addExternalSymbol(Name: "__tlsdesc_resolver", Size: 8, IsWeaklyReferenced: false); |
537 | return *TLSDescResolver; |
538 | } |
539 | |
540 | ArrayRef<char> getTLSDescBlockContent() { |
541 | return {reinterpret_cast<const char *>(TLSDescEntryContent), |
542 | sizeof(TLSDescEntryContent)}; |
543 | } |
544 | |
545 | Section *GOTSection = nullptr; |
546 | Symbol *TLSDescResolver = nullptr; |
547 | TLSInfoTableManager_ELF_aarch64 &TLSInfoTableManager; |
548 | }; |
549 | |
550 | const uint8_t TLSDescTableManager_ELF_aarch64::TLSDescEntryContent[16] = { |
551 | 0x00, 0x00, 0x00, 0x00, |
552 | 0x00, 0x00, 0x00, 0x00, /*resolver function pointer*/ |
553 | 0x00, 0x00, 0x00, 0x00, |
554 | 0x00, 0x00, 0x00, 0x00 /*pointer to tls info*/ |
555 | }; |
556 | |
557 | Error buildTables_ELF_aarch64(LinkGraph &G) { |
558 | LLVM_DEBUG(dbgs() << "Visiting edges in graph:\n"); |
559 | |
560 | aarch64::GOTTableManager GOT; |
561 | aarch64::PLTTableManager PLT(GOT); |
562 | TLSInfoTableManager_ELF_aarch64 TLSInfo; |
563 | TLSDescTableManager_ELF_aarch64 TLSDesc(TLSInfo); |
564 | visitExistingEdges(G, Vs&: GOT, Vs&: PLT, Vs&: TLSDesc, Vs&: TLSInfo); |
565 | return Error::success(); |
566 | } |
567 | |
568 | } // namespace |
569 | |
570 | namespace llvm { |
571 | namespace jitlink { |
572 | |
573 | Expected<std::unique_ptr<LinkGraph>> |
574 | createLinkGraphFromELFObject_aarch64(MemoryBufferRef ObjectBuffer) { |
575 | LLVM_DEBUG({ |
576 | dbgs() << "Building jitlink graph for new input " |
577 | << ObjectBuffer.getBufferIdentifier() << "...\n"; |
578 | }); |
579 | |
580 | auto ELFObj = object::ObjectFile::createELFObjectFile(Object: ObjectBuffer); |
581 | if (!ELFObj) |
582 | return ELFObj.takeError(); |
583 | |
584 | auto Features = (*ELFObj)->getFeatures(); |
585 | if (!Features) |
586 | return Features.takeError(); |
587 | |
588 | assert((*ELFObj)->getArch() == Triple::aarch64 && |
589 | "Only AArch64 (little endian) is supported for now"); |
590 | |
591 | auto &ELFObjFile = cast<object::ELFObjectFile<object::ELF64LE>>(Val&: **ELFObj); |
592 | return ELFLinkGraphBuilder_aarch64<object::ELF64LE>( |
593 | (*ELFObj)->getFileName(), ELFObjFile.getELFFile(), |
594 | (*ELFObj)->makeTriple(), std::move(*Features)) |
595 | .buildGraph(); |
596 | } |
597 | |
598 | void link_ELF_aarch64(std::unique_ptr<LinkGraph> G, |
599 | std::unique_ptr<JITLinkContext> Ctx) { |
600 | PassConfiguration Config; |
601 | const Triple &TT = G->getTargetTriple(); |
602 | if (Ctx->shouldAddDefaultTargetPasses(TT)) { |
603 | // Add eh-frame passes. |
604 | Config.PrePrunePasses.push_back(x: DWARFRecordSectionSplitter(".eh_frame")); |
605 | Config.PrePrunePasses.push_back(x: EHFrameEdgeFixer( |
606 | ".eh_frame", 8, aarch64::Pointer32, aarch64::Pointer64, |
607 | aarch64::Delta32, aarch64::Delta64, aarch64::NegDelta32)); |
608 | Config.PrePrunePasses.push_back(x: EHFrameNullTerminator(".eh_frame")); |
609 | |
610 | // Add a mark-live pass. |
611 | if (auto MarkLive = Ctx->getMarkLivePass(TT)) |
612 | Config.PrePrunePasses.push_back(x: std::move(MarkLive)); |
613 | else |
614 | Config.PrePrunePasses.push_back(x: markAllSymbolsLive); |
615 | |
616 | // Resolve any external section start / end symbols. |
617 | Config.PostAllocationPasses.push_back( |
618 | x: createDefineExternalSectionStartAndEndSymbolsPass( |
619 | F&: identifyELFSectionStartAndEndSymbols)); |
620 | |
621 | // Add an in-place GOT/TLS/Stubs build pass. |
622 | Config.PostPrunePasses.push_back(x: buildTables_ELF_aarch64); |
623 | } |
624 | |
625 | if (auto Err = Ctx->modifyPassConfig(G&: *G, Config)) |
626 | return Ctx->notifyFailed(Err: std::move(Err)); |
627 | |
628 | ELFJITLinker_aarch64::link(Args: std::move(Ctx), Args: std::move(G), Args: std::move(Config)); |
629 | } |
630 | |
631 | } // namespace jitlink |
632 | } // namespace llvm |
633 |
Definitions
- ELFJITLinker_aarch64
- ELFJITLinker_aarch64
- applyFixup
- ELFLinkGraphBuilder_aarch64
- ELFAArch64RelocationKind
- getRelocationKind
- addRelocations
- addSingleRelocation
- getELFAArch64RelocationKindName
- ELFLinkGraphBuilder_aarch64
- TLSInfoTableManager_ELF_aarch64
- getSectionName
- visitEdge
- createEntry
- getTLSInfoSection
- getTLSInfoEntryContent
- TLSInfoEntryContent
- TLSDescTableManager_ELF_aarch64
- TLSDescTableManager_ELF_aarch64
- getSectionName
- visitEdge
- createEntry
- getTLSDescSection
- getTLSDescResolver
- getTLSDescBlockContent
- TLSDescEntryContent
- buildTables_ELF_aarch64
- createLinkGraphFromELFObject_aarch64
Update your C++ knowledge – Modern C++11/14/17 Training
Find out more