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