1 //===- Thunks.cpp --------------------------------------------------------===//
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
7 //===---------------------------------------------------------------------===//
9 // This file contains Thunk subclasses.
11 // A thunk is a small piece of code written after an input section
12 // which is used to jump between "incompatible" functions
13 // such as MIPS PIC and non-PIC or ARM non-Thumb and Thumb functions.
15 // If a jump target is too far and its address doesn't fit to a
16 // short jump instruction, we need to create a thunk too, but we
17 // haven't supported it yet.
19 // i386 and x86-64 don't need thunks.
21 //===---------------------------------------------------------------------===//
25 #include "InputFiles.h"
26 #include "InputSection.h"
27 #include "OutputSections.h"
29 #include "SyntheticSections.h"
31 #include "lld/Common/CommonLinkerContext.h"
32 #include "llvm/BinaryFormat/ELF.h"
33 #include "llvm/Support/Casting.h"
34 #include "llvm/Support/ErrorHandling.h"
35 #include "llvm/Support/MathExtras.h"
40 using namespace llvm::object
;
41 using namespace llvm::ELF
;
43 using namespace lld::elf
;
47 // Base class for AArch64 thunks.
49 // An AArch64 thunk may be either short or long. A short thunk is simply a
50 // branch (B) instruction, and it may be used to call AArch64 functions when the
51 // distance from the thunk to the target is less than 128MB. Long thunks can
52 // branch to any virtual address and they are implemented in the derived
53 // classes. This class tries to create a short thunk if the target is in range,
54 // otherwise it creates a long thunk. When BTI is enabled indirect branches
55 // must land on a BTI instruction. If the destination does not have a BTI
56 // instruction mayNeedLandingPad is set to true and Thunk::landingPad points
57 // to an alternative entry point with a BTI.
58 class AArch64Thunk
: public Thunk
{
60 AArch64Thunk(Ctx
&ctx
, Symbol
&dest
, int64_t addend
, bool mayNeedLandingPad
)
61 : Thunk(ctx
, dest
, addend
), mayNeedLandingPad(mayNeedLandingPad
) {}
62 bool getMayUseShortThunk();
63 void writeTo(uint8_t *buf
) override
;
64 bool needsSyntheticLandingPad() override
;
67 bool mayNeedLandingPad
;
70 bool mayUseShortThunk
= true;
71 virtual void writeLong(uint8_t *buf
) = 0;
74 // AArch64 long range Thunks.
75 class AArch64ABSLongThunk final
: public AArch64Thunk
{
77 AArch64ABSLongThunk(Ctx
&ctx
, Symbol
&dest
, int64_t addend
,
78 bool mayNeedLandingPad
)
79 : AArch64Thunk(ctx
, dest
, addend
, mayNeedLandingPad
) {}
80 uint32_t size() override
{ return getMayUseShortThunk() ? 4 : 16; }
81 void addSymbols(ThunkSection
&isec
) override
;
84 void writeLong(uint8_t *buf
) override
;
87 class AArch64ADRPThunk final
: public AArch64Thunk
{
89 AArch64ADRPThunk(Ctx
&ctx
, Symbol
&dest
, int64_t addend
,
90 bool mayNeedLandingPad
)
91 : AArch64Thunk(ctx
, dest
, addend
, mayNeedLandingPad
) {}
92 uint32_t size() override
{ return getMayUseShortThunk() ? 4 : 12; }
93 void addSymbols(ThunkSection
&isec
) override
;
96 void writeLong(uint8_t *buf
) override
;
99 // AArch64 BTI Landing Pad
100 // When BTI is enabled indirect branches must land on a BTI
101 // compatible instruction. When the destination does not have a
102 // BTI compatible instruction a Thunk doing an indirect branch
103 // targets a Landing Pad Thunk that direct branches to the target.
104 class AArch64BTILandingPadThunk final
: public Thunk
{
106 AArch64BTILandingPadThunk(Ctx
&ctx
, Symbol
&dest
, int64_t addend
)
107 : Thunk(ctx
, dest
, addend
) {}
109 uint32_t size() override
{ return getMayUseShortThunk() ? 4 : 8; }
110 void addSymbols(ThunkSection
&isec
) override
;
111 void writeTo(uint8_t *buf
) override
;
114 bool getMayUseShortThunk();
115 void writeLong(uint8_t *buf
);
116 bool mayUseShortThunk
= true;
119 // Base class for ARM thunks.
121 // An ARM thunk may be either short or long. A short thunk is simply a branch
122 // (B) instruction, and it may be used to call ARM functions when the distance
123 // from the thunk to the target is less than 32MB. Long thunks can branch to any
124 // virtual address and can switch between ARM and Thumb, and they are
125 // implemented in the derived classes. This class tries to create a short thunk
126 // if the target is in range, otherwise it creates a long thunk.
127 class ARMThunk
: public Thunk
{
129 ARMThunk(Ctx
&ctx
, Symbol
&dest
, int64_t addend
) : Thunk(ctx
, dest
, addend
) {}
131 bool getMayUseShortThunk();
132 uint32_t size() override
{ return getMayUseShortThunk() ? 4 : sizeLong(); }
133 void writeTo(uint8_t *buf
) override
;
134 bool isCompatibleWith(const InputSection
&isec
,
135 const Relocation
&rel
) const override
;
137 // Returns the size of a long thunk.
138 virtual uint32_t sizeLong() = 0;
140 // Writes a long thunk to Buf.
141 virtual void writeLong(uint8_t *buf
) = 0;
144 // This field tracks whether all previously considered layouts would allow
145 // this thunk to be short. If we have ever needed a long thunk, we always
146 // create a long thunk, even if the thunk may be short given the current
147 // distance to the target. We do this because transitioning from long to short
148 // can create layout oscillations in certain corner cases which would prevent
149 // the layout from converging.
150 bool mayUseShortThunk
= true;
153 // Base class for Thumb-2 thunks.
155 // This class is similar to ARMThunk, but it uses the Thumb-2 B.W instruction
156 // which has a range of 16MB.
157 class ThumbThunk
: public Thunk
{
159 ThumbThunk(Ctx
&ctx
, Symbol
&dest
, int64_t addend
)
160 : Thunk(ctx
, dest
, addend
) {
164 bool getMayUseShortThunk();
165 uint32_t size() override
{ return getMayUseShortThunk() ? 4 : sizeLong(); }
166 void writeTo(uint8_t *buf
) override
;
167 bool isCompatibleWith(const InputSection
&isec
,
168 const Relocation
&rel
) const override
;
170 // Returns the size of a long thunk.
171 virtual uint32_t sizeLong() = 0;
173 // Writes a long thunk to Buf.
174 virtual void writeLong(uint8_t *buf
) = 0;
177 // See comment in ARMThunk above.
178 bool mayUseShortThunk
= true;
181 // Specific ARM Thunk implementations. The naming convention is:
182 // Source State, TargetState, Target Requirement, ABS or PI, Range
183 class ARMV7ABSLongThunk final
: public ARMThunk
{
185 ARMV7ABSLongThunk(Ctx
&ctx
, Symbol
&dest
, int64_t addend
)
186 : ARMThunk(ctx
, dest
, addend
) {}
188 uint32_t sizeLong() override
{ return 12; }
189 void writeLong(uint8_t *buf
) override
;
190 void addSymbols(ThunkSection
&isec
) override
;
193 class ARMV7PILongThunk final
: public ARMThunk
{
195 ARMV7PILongThunk(Ctx
&ctx
, Symbol
&dest
, int64_t addend
)
196 : ARMThunk(ctx
, dest
, addend
) {}
198 uint32_t sizeLong() override
{ return 16; }
199 void writeLong(uint8_t *buf
) override
;
200 void addSymbols(ThunkSection
&isec
) override
;
203 class ThumbV7ABSLongThunk final
: public ThumbThunk
{
205 ThumbV7ABSLongThunk(Ctx
&ctx
, Symbol
&dest
, int64_t addend
)
206 : ThumbThunk(ctx
, dest
, addend
) {}
208 uint32_t sizeLong() override
{ return 10; }
209 void writeLong(uint8_t *buf
) override
;
210 void addSymbols(ThunkSection
&isec
) override
;
213 class ThumbV7PILongThunk final
: public ThumbThunk
{
215 ThumbV7PILongThunk(Ctx
&ctx
, Symbol
&dest
, int64_t addend
)
216 : ThumbThunk(ctx
, dest
, addend
) {}
218 uint32_t sizeLong() override
{ return 12; }
219 void writeLong(uint8_t *buf
) override
;
220 void addSymbols(ThunkSection
&isec
) override
;
223 // Implementations of Thunks for Arm v6-M. Only Thumb instructions are permitted
224 class ThumbV6MABSLongThunk final
: public ThumbThunk
{
226 ThumbV6MABSLongThunk(Ctx
&ctx
, Symbol
&dest
, int64_t addend
)
227 : ThumbThunk(ctx
, dest
, addend
) {}
229 uint32_t sizeLong() override
{ return 12; }
230 void writeLong(uint8_t *buf
) override
;
231 void addSymbols(ThunkSection
&isec
) override
;
234 class ThumbV6MABSXOLongThunk final
: public ThumbThunk
{
236 ThumbV6MABSXOLongThunk(Ctx
&ctx
, Symbol
&dest
, int64_t addend
)
237 : ThumbThunk(ctx
, dest
, addend
) {}
239 uint32_t sizeLong() override
{ return 20; }
240 void writeLong(uint8_t *buf
) override
;
241 void addSymbols(ThunkSection
&isec
) override
;
244 class ThumbV6MPILongThunk final
: public ThumbThunk
{
246 ThumbV6MPILongThunk(Ctx
&ctx
, Symbol
&dest
, int64_t addend
)
247 : ThumbThunk(ctx
, dest
, addend
) {}
249 uint32_t sizeLong() override
{ return 16; }
250 void writeLong(uint8_t *buf
) override
;
251 void addSymbols(ThunkSection
&isec
) override
;
254 // Architectures v4, v5 and v6 do not support the movt/movw instructions. v5 and
255 // v6 support BLX to which BL instructions can be rewritten inline. There are no
256 // Thumb entrypoints for v5 and v6 as there is no Thumb branch instruction on
257 // these architecture that can result in a thunk.
259 // LDR on v5 and v6 can switch processor state, so for v5 and v6,
260 // ARMV5LongLdrPcThunk can be used for both Arm->Arm and Arm->Thumb calls. v4
261 // can also use this thunk, but only for Arm->Arm calls.
262 class ARMV5LongLdrPcThunk final
: public ARMThunk
{
264 ARMV5LongLdrPcThunk(Ctx
&ctx
, Symbol
&dest
, int64_t addend
)
265 : ARMThunk(ctx
, dest
, addend
) {}
267 uint32_t sizeLong() override
{ return 8; }
268 void writeLong(uint8_t *buf
) override
;
269 void addSymbols(ThunkSection
&isec
) override
;
272 // Implementations of Thunks for v4. BLX is not supported, and loads
273 // will not invoke Arm/Thumb state changes.
274 class ARMV4PILongBXThunk final
: public ARMThunk
{
276 ARMV4PILongBXThunk(Ctx
&ctx
, Symbol
&dest
, int64_t addend
)
277 : ARMThunk(ctx
, dest
, addend
) {}
279 uint32_t sizeLong() override
{ return 16; }
280 void writeLong(uint8_t *buf
) override
;
281 void addSymbols(ThunkSection
&isec
) override
;
284 class ARMV4PILongThunk final
: public ARMThunk
{
286 ARMV4PILongThunk(Ctx
&ctx
, Symbol
&dest
, int64_t addend
)
287 : ARMThunk(ctx
, dest
, addend
) {}
289 uint32_t sizeLong() override
{ return 12; }
290 void writeLong(uint8_t *buf
) override
;
291 void addSymbols(ThunkSection
&isec
) override
;
294 class ThumbV4PILongBXThunk final
: public ThumbThunk
{
296 ThumbV4PILongBXThunk(Ctx
&ctx
, Symbol
&dest
, int64_t addend
)
297 : ThumbThunk(ctx
, dest
, addend
) {}
299 uint32_t sizeLong() override
{ return 16; }
300 void writeLong(uint8_t *buf
) override
;
301 void addSymbols(ThunkSection
&isec
) override
;
304 class ThumbV4PILongThunk final
: public ThumbThunk
{
306 ThumbV4PILongThunk(Ctx
&ctx
, Symbol
&dest
, int64_t addend
)
307 : ThumbThunk(ctx
, dest
, addend
) {}
309 uint32_t sizeLong() override
{ return 20; }
310 void writeLong(uint8_t *buf
) override
;
311 void addSymbols(ThunkSection
&isec
) override
;
314 class ARMV4ABSLongBXThunk final
: public ARMThunk
{
316 ARMV4ABSLongBXThunk(Ctx
&ctx
, Symbol
&dest
, int64_t addend
)
317 : ARMThunk(ctx
, dest
, addend
) {}
319 uint32_t sizeLong() override
{ return 12; }
320 void writeLong(uint8_t *buf
) override
;
321 void addSymbols(ThunkSection
&isec
) override
;
324 class ThumbV4ABSLongBXThunk final
: public ThumbThunk
{
326 ThumbV4ABSLongBXThunk(Ctx
&ctx
, Symbol
&dest
, int64_t addend
)
327 : ThumbThunk(ctx
, dest
, addend
) {}
329 uint32_t sizeLong() override
{ return 12; }
330 void writeLong(uint8_t *buf
) override
;
331 void addSymbols(ThunkSection
&isec
) override
;
334 class ThumbV4ABSLongThunk final
: public ThumbThunk
{
336 ThumbV4ABSLongThunk(Ctx
&ctx
, Symbol
&dest
, int64_t addend
)
337 : ThumbThunk(ctx
, dest
, addend
) {}
339 uint32_t sizeLong() override
{ return 16; }
340 void writeLong(uint8_t *buf
) override
;
341 void addSymbols(ThunkSection
&isec
) override
;
344 // The AVR devices need thunks for R_AVR_LO8_LDI_GS/R_AVR_HI8_LDI_GS
345 // when their destination is out of range [0, 0x1ffff].
346 class AVRThunk
: public Thunk
{
348 AVRThunk(Ctx
&ctx
, Symbol
&dest
, int64_t addend
) : Thunk(ctx
, dest
, addend
) {}
349 uint32_t size() override
{ return 4; }
350 void writeTo(uint8_t *buf
) override
;
351 void addSymbols(ThunkSection
&isec
) override
;
355 class MipsThunk final
: public Thunk
{
357 MipsThunk(Ctx
&ctx
, Symbol
&dest
) : Thunk(ctx
, dest
, 0) {}
359 uint32_t size() override
{ return 16; }
360 void writeTo(uint8_t *buf
) override
;
361 void addSymbols(ThunkSection
&isec
) override
;
362 InputSection
*getTargetInputSection() const override
;
365 // microMIPS R2-R5 LA25 thunk
366 class MicroMipsThunk final
: public Thunk
{
368 MicroMipsThunk(Ctx
&ctx
, Symbol
&dest
) : Thunk(ctx
, dest
, 0) {}
370 uint32_t size() override
{ return 14; }
371 void writeTo(uint8_t *buf
) override
;
372 void addSymbols(ThunkSection
&isec
) override
;
373 InputSection
*getTargetInputSection() const override
;
376 // microMIPS R6 LA25 thunk
377 class MicroMipsR6Thunk final
: public Thunk
{
379 MicroMipsR6Thunk(Ctx
&ctx
, Symbol
&dest
) : Thunk(ctx
, dest
, 0) {}
381 uint32_t size() override
{ return 12; }
382 void writeTo(uint8_t *buf
) override
;
383 void addSymbols(ThunkSection
&isec
) override
;
384 InputSection
*getTargetInputSection() const override
;
387 class PPC32PltCallStub final
: public Thunk
{
389 // For R_PPC_PLTREL24, Thunk::addend records the addend which will be used to
390 // decide the offsets in the call stub.
391 PPC32PltCallStub(Ctx
&ctx
, const InputSection
&isec
, const Relocation
&rel
,
393 : Thunk(ctx
, dest
, rel
.addend
), file(isec
.file
) {}
394 uint32_t size() override
{ return 16; }
395 void writeTo(uint8_t *buf
) override
;
396 void addSymbols(ThunkSection
&isec
) override
;
397 bool isCompatibleWith(const InputSection
&isec
, const Relocation
&rel
) const override
;
400 // Records the call site of the call stub.
401 const InputFile
*file
;
404 class PPC32LongThunk final
: public Thunk
{
406 PPC32LongThunk(Ctx
&ctx
, Symbol
&dest
, int64_t addend
)
407 : Thunk(ctx
, dest
, addend
) {}
408 uint32_t size() override
{ return ctx
.arg
.isPic
? 32 : 16; }
409 void writeTo(uint8_t *buf
) override
;
410 void addSymbols(ThunkSection
&isec
) override
;
413 // PPC64 Plt call stubs.
414 // Any call site that needs to call through a plt entry needs a call stub in
415 // the .text section. The call stub is responsible for:
416 // 1) Saving the toc-pointer to the stack.
417 // 2) Loading the target functions address from the procedure linkage table into
418 // r12 for use by the target functions global entry point, and into the count
420 // 3) Transferring control to the target function through an indirect branch.
421 class PPC64PltCallStub final
: public Thunk
{
423 PPC64PltCallStub(Ctx
&ctx
, Symbol
&dest
) : Thunk(ctx
, dest
, 0) {}
424 uint32_t size() override
{ return 20; }
425 void writeTo(uint8_t *buf
) override
;
426 void addSymbols(ThunkSection
&isec
) override
;
427 bool isCompatibleWith(const InputSection
&isec
,
428 const Relocation
&rel
) const override
;
431 // PPC64 R2 Save Stub
432 // When the caller requires a valid R2 TOC pointer but the callee does not
433 // require a TOC pointer and the callee cannot guarantee that it doesn't
434 // clobber R2 then we need to save R2. This stub:
435 // 1) Saves the TOC pointer to the stack.
436 // 2) Tail calls the callee.
437 class PPC64R2SaveStub final
: public Thunk
{
439 PPC64R2SaveStub(Ctx
&ctx
, Symbol
&dest
, int64_t addend
)
440 : Thunk(ctx
, dest
, addend
) {
444 // To prevent oscillations in layout when moving from short to long thunks
445 // we make sure that once a thunk has been set to long it cannot go back.
446 bool getMayUseShortThunk() {
447 if (!mayUseShortThunk
)
449 if (!isInt
<26>(computeOffset())) {
450 mayUseShortThunk
= false;
455 uint32_t size() override
{ return getMayUseShortThunk() ? 8 : 32; }
456 void writeTo(uint8_t *buf
) override
;
457 void addSymbols(ThunkSection
&isec
) override
;
458 bool isCompatibleWith(const InputSection
&isec
,
459 const Relocation
&rel
) const override
;
462 // Transitioning from long to short can create layout oscillations in
463 // certain corner cases which would prevent the layout from converging.
464 // This is similar to the handling for ARMThunk.
465 bool mayUseShortThunk
= true;
466 int64_t computeOffset() const {
467 return destination
.getVA(ctx
) - (getThunkTargetSym()->getVA(ctx
) + 4);
471 // PPC64 R12 Setup Stub
472 // When a caller that does not maintain TOC calls a target which may possibly
473 // use TOC (either non-preemptible with localentry>1 or preemptible), we need to
474 // set r12 to satisfy the requirement of the global entry point.
475 class PPC64R12SetupStub final
: public Thunk
{
477 PPC64R12SetupStub(Ctx
&ctx
, Symbol
&dest
, bool gotPlt
)
478 : Thunk(ctx
, dest
, 0), gotPlt(gotPlt
) {
481 uint32_t size() override
{ return 32; }
482 void writeTo(uint8_t *buf
) override
;
483 void addSymbols(ThunkSection
&isec
) override
;
484 bool isCompatibleWith(const InputSection
&isec
,
485 const Relocation
&rel
) const override
;
491 // A bl instruction uses a signed 24 bit offset, with an implicit 4 byte
492 // alignment. This gives a possible 26 bits of 'reach'. If the call offset is
493 // larger than that we need to emit a long-branch thunk. The target address
494 // of the callee is stored in a table to be accessed TOC-relative. Since the
495 // call must be local (a non-local call will have a PltCallStub instead) the
496 // table stores the address of the callee's local entry point. For
497 // position-independent code a corresponding relative dynamic relocation is
499 class PPC64LongBranchThunk
: public Thunk
{
501 uint32_t size() override
{ return 32; }
502 void writeTo(uint8_t *buf
) override
;
503 void addSymbols(ThunkSection
&isec
) override
;
504 bool isCompatibleWith(const InputSection
&isec
,
505 const Relocation
&rel
) const override
;
508 PPC64LongBranchThunk(Ctx
&ctx
, Symbol
&dest
, int64_t addend
)
509 : Thunk(ctx
, dest
, addend
) {}
512 class PPC64PILongBranchThunk final
: public PPC64LongBranchThunk
{
514 PPC64PILongBranchThunk(Ctx
&ctx
, Symbol
&dest
, int64_t addend
)
515 : PPC64LongBranchThunk(ctx
, dest
, addend
) {
516 assert(!dest
.isPreemptible
);
517 if (std::optional
<uint32_t> index
=
518 ctx
.in
.ppc64LongBranchTarget
->addEntry(&dest
, addend
)) {
519 ctx
.mainPart
->relaDyn
->addRelativeReloc(
520 ctx
.target
->relativeRel
, *ctx
.in
.ppc64LongBranchTarget
,
521 *index
* UINT64_C(8), dest
,
522 addend
+ getPPC64GlobalEntryToLocalEntryOffset(ctx
, dest
.stOther
),
523 ctx
.target
->symbolicRel
, R_ABS
);
528 class PPC64PDLongBranchThunk final
: public PPC64LongBranchThunk
{
530 PPC64PDLongBranchThunk(Ctx
&ctx
, Symbol
&dest
, int64_t addend
)
531 : PPC64LongBranchThunk(ctx
, dest
, addend
) {
532 ctx
.in
.ppc64LongBranchTarget
->addEntry(&dest
, addend
);
536 } // end anonymous namespace
538 Defined
*Thunk::addSymbol(StringRef name
, uint8_t type
, uint64_t value
,
539 InputSectionBase
§ion
) {
540 Defined
*d
= addSyntheticLocal(ctx
, name
, type
, value
, /*size=*/0, section
);
545 void Thunk::setOffset(uint64_t newOffset
) {
546 for (Defined
*d
: syms
)
547 d
->value
= d
->value
- offset
+ newOffset
;
551 // AArch64 Thunk base class.
552 static uint64_t getAArch64ThunkDestVA(Ctx
&ctx
, const Symbol
&s
, int64_t a
) {
553 uint64_t v
= s
.isInPlt(ctx
) ? s
.getPltVA(ctx
) : s
.getVA(ctx
, a
);
557 bool AArch64Thunk::getMayUseShortThunk() {
558 if (!mayUseShortThunk
)
560 uint64_t s
= getAArch64ThunkDestVA(ctx
, destination
, addend
);
561 uint64_t p
= getThunkTargetSym()->getVA(ctx
);
562 mayUseShortThunk
= llvm::isInt
<28>(s
- p
);
563 return mayUseShortThunk
;
566 void AArch64Thunk::writeTo(uint8_t *buf
) {
567 if (!getMayUseShortThunk()) {
571 uint64_t s
= getAArch64ThunkDestVA(ctx
, destination
, addend
);
572 uint64_t p
= getThunkTargetSym()->getVA(ctx
);
573 write32(ctx
, buf
, 0x14000000); // b S
574 ctx
.target
->relocateNoSym(buf
, R_AARCH64_CALL26
, s
- p
);
577 bool AArch64Thunk::needsSyntheticLandingPad() {
578 // Short Thunks use a direct branch, no synthetic landing pad
580 return mayNeedLandingPad
&& !getMayUseShortThunk();
583 // AArch64 long range Thunks.
584 void AArch64ABSLongThunk::writeLong(uint8_t *buf
) {
585 const uint8_t data
[] = {
586 0x50, 0x00, 0x00, 0x58, // ldr x16, L0
587 0x00, 0x02, 0x1f, 0xd6, // br x16
588 0x00, 0x00, 0x00, 0x00, // L0: .xword S
589 0x00, 0x00, 0x00, 0x00,
591 // If mayNeedLandingPad is true then destination is an
592 // AArch64BTILandingPadThunk that defines landingPad.
593 assert(!mayNeedLandingPad
|| landingPad
!= nullptr);
594 uint64_t s
= mayNeedLandingPad
595 ? landingPad
->getVA(ctx
, 0)
596 : getAArch64ThunkDestVA(ctx
, destination
, addend
);
597 memcpy(buf
, data
, sizeof(data
));
598 ctx
.target
->relocateNoSym(buf
+ 8, R_AARCH64_ABS64
, s
);
601 void AArch64ABSLongThunk::addSymbols(ThunkSection
&isec
) {
602 addSymbol(ctx
.saver
.save("__AArch64AbsLongThunk_" + destination
.getName()),
604 addSymbol("$x", STT_NOTYPE
, 0, isec
);
605 if (!getMayUseShortThunk())
606 addSymbol("$d", STT_NOTYPE
, 8, isec
);
609 // This Thunk has a maximum range of 4Gb, this is sufficient for all programs
610 // using the small code model, including pc-relative ones. At time of writing
611 // clang and gcc do not support the large code model for position independent
612 // code so it is safe to use this for position independent thunks without
613 // worrying about the destination being more than 4Gb away.
614 void AArch64ADRPThunk::writeLong(uint8_t *buf
) {
615 const uint8_t data
[] = {
616 0x10, 0x00, 0x00, 0x90, // adrp x16, Dest R_AARCH64_ADR_PREL_PG_HI21(Dest)
617 0x10, 0x02, 0x00, 0x91, // add x16, x16, R_AARCH64_ADD_ABS_LO12_NC(Dest)
618 0x00, 0x02, 0x1f, 0xd6, // br x16
620 // if mayNeedLandingPad is true then destination is an
621 // AArch64BTILandingPadThunk that defines landingPad.
622 assert(!mayNeedLandingPad
|| landingPad
!= nullptr);
623 uint64_t s
= mayNeedLandingPad
624 ? landingPad
->getVA(ctx
, 0)
625 : getAArch64ThunkDestVA(ctx
, destination
, addend
);
626 uint64_t p
= getThunkTargetSym()->getVA(ctx
);
627 memcpy(buf
, data
, sizeof(data
));
628 ctx
.target
->relocateNoSym(buf
, R_AARCH64_ADR_PREL_PG_HI21
,
629 getAArch64Page(s
) - getAArch64Page(p
));
630 ctx
.target
->relocateNoSym(buf
+ 4, R_AARCH64_ADD_ABS_LO12_NC
, s
);
633 void AArch64ADRPThunk::addSymbols(ThunkSection
&isec
) {
634 addSymbol(ctx
.saver
.save("__AArch64ADRPThunk_" + destination
.getName()),
636 addSymbol("$x", STT_NOTYPE
, 0, isec
);
639 void AArch64BTILandingPadThunk::addSymbols(ThunkSection
&isec
) {
640 addSymbol(ctx
.saver
.save("__AArch64BTIThunk_" + destination
.getName()),
642 addSymbol("$x", STT_NOTYPE
, 0, isec
);
645 void AArch64BTILandingPadThunk::writeTo(uint8_t *buf
) {
646 if (!getMayUseShortThunk()) {
650 write32(ctx
, buf
, 0xd503245f); // BTI c
651 // Control falls through to target in following section.
654 bool AArch64BTILandingPadThunk::getMayUseShortThunk() {
655 if (!mayUseShortThunk
)
657 // If the target is the following instruction then we can fall
658 // through without the indirect branch.
659 uint64_t s
= destination
.getVA(ctx
, addend
);
660 uint64_t p
= getThunkTargetSym()->getVA(ctx
);
661 // This function is called before addresses are stable. We need to
662 // work out the range from the thunk to the next section but the
663 // address of the start of the next section depends on the size of
664 // the thunks in the previous pass. s - p + offset == 0 represents
665 // the first pass where the Thunk and following section are assigned
666 // the same offset. s - p <= 4 is the last Thunk in the Thunk
668 mayUseShortThunk
= (s
- p
+ offset
== 0 || s
- p
<= 4);
669 return mayUseShortThunk
;
672 void AArch64BTILandingPadThunk::writeLong(uint8_t *buf
) {
673 uint64_t s
= destination
.getVA(ctx
, addend
);
674 uint64_t p
= getThunkTargetSym()->getVA(ctx
) + 4;
675 write32(ctx
, buf
, 0xd503245f); // BTI c
676 write32(ctx
, buf
+ 4, 0x14000000); // B S
677 ctx
.target
->relocateNoSym(buf
+ 4, R_AARCH64_CALL26
, s
- p
);
681 static uint64_t getARMThunkDestVA(Ctx
&ctx
, const Symbol
&s
) {
682 uint64_t v
= s
.isInPlt(ctx
) ? s
.getPltVA(ctx
) : s
.getVA(ctx
);
683 return SignExtend64
<32>(v
);
686 // This function returns true if the target is not Thumb and is within 2^26, and
687 // it has not previously returned false (see comment for mayUseShortThunk).
688 bool ARMThunk::getMayUseShortThunk() {
689 if (!mayUseShortThunk
)
691 uint64_t s
= getARMThunkDestVA(ctx
, destination
);
693 mayUseShortThunk
= false;
696 uint64_t p
= getThunkTargetSym()->getVA(ctx
);
697 int64_t offset
= s
- p
- 8;
698 mayUseShortThunk
= llvm::isInt
<26>(offset
);
699 return mayUseShortThunk
;
702 void ARMThunk::writeTo(uint8_t *buf
) {
703 if (!getMayUseShortThunk()) {
708 uint64_t s
= getARMThunkDestVA(ctx
, destination
);
709 uint64_t p
= getThunkTargetSym()->getVA(ctx
);
710 int64_t offset
= s
- p
- 8;
711 write32(ctx
, buf
, 0xea000000); // b S
712 ctx
.target
->relocateNoSym(buf
, R_ARM_JUMP24
, offset
);
715 bool ARMThunk::isCompatibleWith(const InputSection
&isec
,
716 const Relocation
&rel
) const {
717 // v4T does not have BLX, so also deny R_ARM_THM_CALL
718 if (!ctx
.arg
.armHasBlx
&& rel
.type
== R_ARM_THM_CALL
)
721 // Thumb branch relocations can't use BLX
722 return rel
.type
!= R_ARM_THM_JUMP19
&& rel
.type
!= R_ARM_THM_JUMP24
;
725 // This function returns true if:
726 // the target is Thumb
727 // && is within branch range
728 // && this function has not previously returned false
729 // (see comment for mayUseShortThunk)
730 // && the arch supports Thumb branch range extension.
731 bool ThumbThunk::getMayUseShortThunk() {
732 if (!mayUseShortThunk
|| !ctx
.arg
.armJ1J2BranchEncoding
)
734 uint64_t s
= getARMThunkDestVA(ctx
, destination
);
736 mayUseShortThunk
= false;
739 uint64_t p
= getThunkTargetSym()->getVA(ctx
) & ~1;
740 int64_t offset
= s
- p
- 4;
741 mayUseShortThunk
= llvm::isInt
<25>(offset
);
742 return mayUseShortThunk
;
745 void ThumbThunk::writeTo(uint8_t *buf
) {
746 if (!getMayUseShortThunk()) {
751 uint64_t s
= getARMThunkDestVA(ctx
, destination
);
752 uint64_t p
= getThunkTargetSym()->getVA(ctx
);
753 int64_t offset
= s
- p
- 4;
754 write16(ctx
, buf
+ 0, 0xf000); // b.w S
755 write16(ctx
, buf
+ 2, 0xb000);
756 ctx
.target
->relocateNoSym(buf
, R_ARM_THM_JUMP24
, offset
);
759 bool ThumbThunk::isCompatibleWith(const InputSection
&isec
,
760 const Relocation
&rel
) const {
761 // v4T does not have BLX, so also deny R_ARM_CALL
762 if (!ctx
.arg
.armHasBlx
&& rel
.type
== R_ARM_CALL
)
765 // ARM branch relocations can't use BLX
766 return rel
.type
!= R_ARM_JUMP24
&& rel
.type
!= R_ARM_PC24
&& rel
.type
!= R_ARM_PLT32
;
769 void ARMV7ABSLongThunk::writeLong(uint8_t *buf
) {
770 write32(ctx
, buf
+ 0, 0xe300c000); // movw ip,:lower16:S
771 write32(ctx
, buf
+ 4, 0xe340c000); // movt ip,:upper16:S
772 write32(ctx
, buf
+ 8, 0xe12fff1c); // bx ip
773 uint64_t s
= getARMThunkDestVA(ctx
, destination
);
774 ctx
.target
->relocateNoSym(buf
, R_ARM_MOVW_ABS_NC
, s
);
775 ctx
.target
->relocateNoSym(buf
+ 4, R_ARM_MOVT_ABS
, s
);
778 void ARMV7ABSLongThunk::addSymbols(ThunkSection
&isec
) {
779 addSymbol(ctx
.saver
.save("__ARMv7ABSLongThunk_" + destination
.getName()),
781 addSymbol("$a", STT_NOTYPE
, 0, isec
);
784 void ThumbV7ABSLongThunk::writeLong(uint8_t *buf
) {
785 write16(ctx
, buf
+ 0, 0xf240); // movw ip, :lower16:S
786 write16(ctx
, buf
+ 2, 0x0c00);
787 write16(ctx
, buf
+ 4, 0xf2c0); // movt ip, :upper16:S
788 write16(ctx
, buf
+ 6, 0x0c00);
789 write16(ctx
, buf
+ 8, 0x4760); // bx ip
790 uint64_t s
= getARMThunkDestVA(ctx
, destination
);
791 ctx
.target
->relocateNoSym(buf
, R_ARM_THM_MOVW_ABS_NC
, s
);
792 ctx
.target
->relocateNoSym(buf
+ 4, R_ARM_THM_MOVT_ABS
, s
);
795 void ThumbV7ABSLongThunk::addSymbols(ThunkSection
&isec
) {
796 addSymbol(ctx
.saver
.save("__Thumbv7ABSLongThunk_" + destination
.getName()),
798 addSymbol("$t", STT_NOTYPE
, 0, isec
);
801 void ARMV7PILongThunk::writeLong(uint8_t *buf
) {
802 write32(ctx
, buf
+ 0,
803 0xe30fcff0); // P: movw ip,:lower16:S - (P + (L1-P) + 8)
804 write32(ctx
, buf
+ 4,
805 0xe340c000); // movt ip,:upper16:S - (P + (L1-P) + 8)
806 write32(ctx
, buf
+ 8, 0xe08cc00f); // L1: add ip, ip, pc
807 write32(ctx
, buf
+ 12, 0xe12fff1c); // bx ip
808 uint64_t s
= getARMThunkDestVA(ctx
, destination
);
809 uint64_t p
= getThunkTargetSym()->getVA(ctx
);
810 int64_t offset
= s
- p
- 16;
811 ctx
.target
->relocateNoSym(buf
, R_ARM_MOVW_PREL_NC
, offset
);
812 ctx
.target
->relocateNoSym(buf
+ 4, R_ARM_MOVT_PREL
, offset
);
815 void ARMV7PILongThunk::addSymbols(ThunkSection
&isec
) {
816 addSymbol(ctx
.saver
.save("__ARMV7PILongThunk_" + destination
.getName()),
818 addSymbol("$a", STT_NOTYPE
, 0, isec
);
821 void ThumbV7PILongThunk::writeLong(uint8_t *buf
) {
822 write16(ctx
, buf
+ 0, 0xf64f); // P: movw ip,:lower16:S - (P + (L1-P) + 4)
823 write16(ctx
, buf
+ 2, 0x7cf4);
824 write16(ctx
, buf
+ 4, 0xf2c0); // movt ip,:upper16:S - (P + (L1-P) + 4)
825 write16(ctx
, buf
+ 6, 0x0c00);
826 write16(ctx
, buf
+ 8, 0x44fc); // L1: add ip, pc
827 write16(ctx
, buf
+ 10, 0x4760); // bx ip
828 uint64_t s
= getARMThunkDestVA(ctx
, destination
);
829 uint64_t p
= getThunkTargetSym()->getVA(ctx
) & ~0x1;
830 int64_t offset
= s
- p
- 12;
831 ctx
.target
->relocateNoSym(buf
, R_ARM_THM_MOVW_PREL_NC
, offset
);
832 ctx
.target
->relocateNoSym(buf
+ 4, R_ARM_THM_MOVT_PREL
, offset
);
835 void ThumbV7PILongThunk::addSymbols(ThunkSection
&isec
) {
836 addSymbol(ctx
.saver
.save("__ThumbV7PILongThunk_" + destination
.getName()),
838 addSymbol("$t", STT_NOTYPE
, 0, isec
);
841 void ThumbV6MABSLongThunk::writeLong(uint8_t *buf
) {
842 // Most Thumb instructions cannot access the high registers r8 - r15. As the
843 // only register we can corrupt is r12 we must instead spill a low register
844 // to the stack to use as a scratch register. We push r1 even though we
845 // don't need to get some space to use for the return address.
846 write16(ctx
, buf
+ 0, 0xb403); // push {r0, r1} ; Obtain scratch registers
847 write16(ctx
, buf
+ 2, 0x4801); // ldr r0, [pc, #4] ; L1
848 write16(ctx
, buf
+ 4, 0x9001); // str r0, [sp, #4] ; SP + 4 = S
849 write16(ctx
, buf
+ 6, 0xbd01); // pop {r0, pc} ; restore r0 and branch to dest
850 write32(ctx
, buf
+ 8, 0x00000000); // L1: .word S
851 uint64_t s
= getARMThunkDestVA(ctx
, destination
);
852 ctx
.target
->relocateNoSym(buf
+ 8, R_ARM_ABS32
, s
);
855 void ThumbV6MABSLongThunk::addSymbols(ThunkSection
&isec
) {
856 addSymbol(ctx
.saver
.save("__Thumbv6MABSLongThunk_" + destination
.getName()),
858 addSymbol("$t", STT_NOTYPE
, 0, isec
);
859 if (!getMayUseShortThunk())
860 addSymbol("$d", STT_NOTYPE
, 8, isec
);
863 void ThumbV6MABSXOLongThunk::writeLong(uint8_t *buf
) {
864 // Most Thumb instructions cannot access the high registers r8 - r15. As the
865 // only register we can corrupt is r12 we must instead spill a low register
866 // to the stack to use as a scratch register. We push r1 even though we
867 // don't need to get some space to use for the return address.
868 write16(ctx
, buf
+ 0, 0xb403); // push {r0, r1} ; Obtain scratch registers
869 write16(ctx
, buf
+ 2, 0x2000); // movs r0, :upper8_15:S
870 write16(ctx
, buf
+ 4, 0x0200); // lsls r0, r0, #8
871 write16(ctx
, buf
+ 6, 0x3000); // adds r0, :upper0_7:S
872 write16(ctx
, buf
+ 8, 0x0200); // lsls r0, r0, #8
873 write16(ctx
, buf
+ 10, 0x3000); // adds r0, :lower8_15:S
874 write16(ctx
, buf
+ 12, 0x0200); // lsls r0, r0, #8
875 write16(ctx
, buf
+ 14, 0x3000); // adds r0, :lower0_7:S
876 write16(ctx
, buf
+ 16, 0x9001); // str r0, [sp, #4] ; SP + 4 = S
877 write16(ctx
, buf
+ 18,
878 0xbd01); // pop {r0, pc} ; restore r0 and branch to dest
879 uint64_t s
= getARMThunkDestVA(ctx
, destination
);
880 ctx
.target
->relocateNoSym(buf
+ 2, R_ARM_THM_ALU_ABS_G3
, s
);
881 ctx
.target
->relocateNoSym(buf
+ 6, R_ARM_THM_ALU_ABS_G2_NC
, s
);
882 ctx
.target
->relocateNoSym(buf
+ 10, R_ARM_THM_ALU_ABS_G1_NC
, s
);
883 ctx
.target
->relocateNoSym(buf
+ 14, R_ARM_THM_ALU_ABS_G0_NC
, s
);
886 void ThumbV6MABSXOLongThunk::addSymbols(ThunkSection
&isec
) {
887 addSymbol(ctx
.saver
.save("__Thumbv6MABSXOLongThunk_" + destination
.getName()),
889 addSymbol("$t", STT_NOTYPE
, 0, isec
);
892 void ThumbV6MPILongThunk::writeLong(uint8_t *buf
) {
893 // Most Thumb instructions cannot access the high registers r8 - r15. As the
894 // only register we can corrupt is ip (r12) we must instead spill a low
895 // register to the stack to use as a scratch register.
896 write16(ctx
, buf
+ 0,
897 0xb401); // P: push {r0} ; Obtain scratch register
898 write16(ctx
, buf
+ 2, 0x4802); // ldr r0, [pc, #8] ; L2
899 write16(ctx
, buf
+ 4, 0x4684); // mov ip, r0 ; high to low register
900 write16(ctx
, buf
+ 6,
901 0xbc01); // pop {r0} ; restore scratch register
902 write16(ctx
, buf
+ 8, 0x44e7); // L1: add pc, ip ; transfer control
903 write16(ctx
, buf
+ 10,
904 0x46c0); // nop ; pad to 4-byte boundary
905 write32(ctx
, buf
+ 12, 0x00000000); // L2: .word S - (P + (L1 - P) + 4)
906 uint64_t s
= getARMThunkDestVA(ctx
, destination
);
907 uint64_t p
= getThunkTargetSym()->getVA(ctx
) & ~0x1;
908 ctx
.target
->relocateNoSym(buf
+ 12, R_ARM_REL32
, s
- p
- 12);
911 void ThumbV6MPILongThunk::addSymbols(ThunkSection
&isec
) {
912 addSymbol(ctx
.saver
.save("__Thumbv6MPILongThunk_" + destination
.getName()),
914 addSymbol("$t", STT_NOTYPE
, 0, isec
);
915 if (!getMayUseShortThunk())
916 addSymbol("$d", STT_NOTYPE
, 12, isec
);
919 void ARMV5LongLdrPcThunk::writeLong(uint8_t *buf
) {
920 write32(ctx
, buf
+ 0, 0xe51ff004); // ldr pc, [pc,#-4] ; L1
921 write32(ctx
, buf
+ 4, 0x00000000); // L1: .word S
922 ctx
.target
->relocateNoSym(buf
+ 4, R_ARM_ABS32
,
923 getARMThunkDestVA(ctx
, destination
));
926 void ARMV5LongLdrPcThunk::addSymbols(ThunkSection
&isec
) {
927 addSymbol(ctx
.saver
.save("__ARMv5LongLdrPcThunk_" + destination
.getName()),
929 addSymbol("$a", STT_NOTYPE
, 0, isec
);
930 if (!getMayUseShortThunk())
931 addSymbol("$d", STT_NOTYPE
, 4, isec
);
934 void ARMV4ABSLongBXThunk::writeLong(uint8_t *buf
) {
935 write32(ctx
, buf
+ 0, 0xe59fc000); // ldr r12, [pc] ; L1
936 write32(ctx
, buf
+ 4, 0xe12fff1c); // bx r12
937 write32(ctx
, buf
+ 8, 0x00000000); // L1: .word S
938 ctx
.target
->relocateNoSym(buf
+ 8, R_ARM_ABS32
,
939 getARMThunkDestVA(ctx
, destination
));
942 void ARMV4ABSLongBXThunk::addSymbols(ThunkSection
&isec
) {
943 addSymbol(ctx
.saver
.save("__ARMv4ABSLongBXThunk_" + destination
.getName()),
945 addSymbol("$a", STT_NOTYPE
, 0, isec
);
946 if (!getMayUseShortThunk())
947 addSymbol("$d", STT_NOTYPE
, 8, isec
);
950 void ThumbV4ABSLongBXThunk::writeLong(uint8_t *buf
) {
951 write16(ctx
, buf
+ 0, 0x4778); // bx pc
952 write16(ctx
, buf
+ 2,
953 0xe7fd); // b #-6 ; Arm recommended sequence to follow bx pc
954 write32(ctx
, buf
+ 4, 0xe51ff004); // ldr pc, [pc, #-4] ; L1
955 write32(ctx
, buf
+ 8, 0x00000000); // L1: .word S
956 ctx
.target
->relocateNoSym(buf
+ 8, R_ARM_ABS32
,
957 getARMThunkDestVA(ctx
, destination
));
960 void ThumbV4ABSLongBXThunk::addSymbols(ThunkSection
&isec
) {
961 addSymbol(ctx
.saver
.save("__Thumbv4ABSLongBXThunk_" + destination
.getName()),
963 addSymbol("$t", STT_NOTYPE
, 0, isec
);
964 addSymbol("$a", STT_NOTYPE
, 4, isec
);
965 if (!getMayUseShortThunk())
966 addSymbol("$d", STT_NOTYPE
, 8, isec
);
969 void ThumbV4ABSLongThunk::writeLong(uint8_t *buf
) {
970 write16(ctx
, buf
+ 0, 0x4778); // bx pc
971 write16(ctx
, buf
+ 2,
972 0xe7fd); // b #-6 ; Arm recommended sequence to follow bx pc
973 write32(ctx
, buf
+ 4, 0xe59fc000); // ldr r12, [pc] ; L1
974 write32(ctx
, buf
+ 8, 0xe12fff1c); // bx r12
975 write32(ctx
, buf
+ 12, 0x00000000); // L1: .word S
976 ctx
.target
->relocateNoSym(buf
+ 12, R_ARM_ABS32
,
977 getARMThunkDestVA(ctx
, destination
));
980 void ThumbV4ABSLongThunk::addSymbols(ThunkSection
&isec
) {
981 addSymbol(ctx
.saver
.save("__Thumbv4ABSLongThunk_" + destination
.getName()),
983 addSymbol("$t", STT_NOTYPE
, 0, isec
);
984 addSymbol("$a", STT_NOTYPE
, 4, isec
);
985 if (!getMayUseShortThunk())
986 addSymbol("$d", STT_NOTYPE
, 12, isec
);
989 void ARMV4PILongBXThunk::writeLong(uint8_t *buf
) {
990 write32(ctx
, buf
+ 0, 0xe59fc004); // P: ldr ip, [pc,#4] ; L2
991 write32(ctx
, buf
+ 4, 0xe08fc00c); // L1: add ip, pc, ip
992 write32(ctx
, buf
+ 8, 0xe12fff1c); // bx ip
993 write32(ctx
, buf
+ 12, 0x00000000); // L2: .word S - (P + (L1 - P) + 8)
994 uint64_t s
= getARMThunkDestVA(ctx
, destination
);
995 uint64_t p
= getThunkTargetSym()->getVA(ctx
) & ~0x1;
996 ctx
.target
->relocateNoSym(buf
+ 12, R_ARM_REL32
, s
- p
- 12);
999 void ARMV4PILongBXThunk::addSymbols(ThunkSection
&isec
) {
1000 addSymbol(ctx
.saver
.save("__ARMv4PILongBXThunk_" + destination
.getName()),
1002 addSymbol("$a", STT_NOTYPE
, 0, isec
);
1003 if (!getMayUseShortThunk())
1004 addSymbol("$d", STT_NOTYPE
, 12, isec
);
1007 void ARMV4PILongThunk::writeLong(uint8_t *buf
) {
1008 write32(ctx
, buf
+ 0, 0xe59fc000); // P: ldr ip, [pc] ; L2
1009 write32(ctx
, buf
+ 4, 0xe08ff00c); // L1: add pc, pc, r12
1010 write32(ctx
, buf
+ 8, 0x00000000); // L2: .word S - (P + (L1 - P) + 8)
1011 uint64_t s
= getARMThunkDestVA(ctx
, destination
);
1012 uint64_t p
= getThunkTargetSym()->getVA(ctx
) & ~0x1;
1013 ctx
.target
->relocateNoSym(buf
+ 8, R_ARM_REL32
, s
- p
- 12);
1016 void ARMV4PILongThunk::addSymbols(ThunkSection
&isec
) {
1017 addSymbol(ctx
.saver
.save("__ARMv4PILongThunk_" + destination
.getName()),
1019 addSymbol("$a", STT_NOTYPE
, 0, isec
);
1020 if (!getMayUseShortThunk())
1021 addSymbol("$d", STT_NOTYPE
, 8, isec
);
1024 void ThumbV4PILongBXThunk::writeLong(uint8_t *buf
) {
1025 write16(ctx
, buf
+ 0, 0x4778); // P: bx pc
1026 write16(ctx
, buf
+ 2,
1027 0xe7fd); // b #-6 ; Arm recommended sequence to follow bx pc
1028 write32(ctx
, buf
+ 4, 0xe59fc000); // ldr r12, [pc] ; L2
1029 write32(ctx
, buf
+ 8, 0xe08cf00f); // L1: add pc, r12, pc
1030 write32(ctx
, buf
+ 12, 0x00000000); // L2: .word S - (P + (L1 - P) + 8)
1031 uint64_t s
= getARMThunkDestVA(ctx
, destination
);
1032 uint64_t p
= getThunkTargetSym()->getVA(ctx
) & ~0x1;
1033 ctx
.target
->relocateNoSym(buf
+ 12, R_ARM_REL32
, s
- p
- 16);
1036 void ThumbV4PILongBXThunk::addSymbols(ThunkSection
&isec
) {
1037 addSymbol(ctx
.saver
.save("__Thumbv4PILongBXThunk_" + destination
.getName()),
1039 addSymbol("$t", STT_NOTYPE
, 0, isec
);
1040 addSymbol("$a", STT_NOTYPE
, 4, isec
);
1041 if (!getMayUseShortThunk())
1042 addSymbol("$d", STT_NOTYPE
, 12, isec
);
1045 void ThumbV4PILongThunk::writeLong(uint8_t *buf
) {
1046 write16(ctx
, buf
+ 0, 0x4778); // P: bx pc
1047 write16(ctx
, buf
+ 2,
1048 0xe7fd); // b #-6 ; Arm recommended sequence to follow bx pc
1049 write32(ctx
, buf
+ 4, 0xe59fc004); // ldr ip, [pc,#4] ; L2
1050 write32(ctx
, buf
+ 8, 0xe08fc00c); // L1: add ip, pc, ip
1051 write32(ctx
, buf
+ 12, 0xe12fff1c); // bx ip
1052 write32(ctx
, buf
+ 16, 0x00000000); // L2: .word S - (P + (L1 - P) + 8)
1053 uint64_t s
= getARMThunkDestVA(ctx
, destination
);
1054 uint64_t p
= getThunkTargetSym()->getVA(ctx
) & ~0x1;
1055 ctx
.target
->relocateNoSym(buf
+ 16, R_ARM_REL32
, s
- p
- 16);
1058 void ThumbV4PILongThunk::addSymbols(ThunkSection
&isec
) {
1059 addSymbol(ctx
.saver
.save("__Thumbv4PILongThunk_" + destination
.getName()),
1061 addSymbol("$t", STT_NOTYPE
, 0, isec
);
1062 addSymbol("$a", STT_NOTYPE
, 4, isec
);
1063 if (!getMayUseShortThunk())
1064 addSymbol("$d", STT_NOTYPE
, 16, isec
);
1067 // Use the long jump which covers a range up to 8MiB.
1068 void AVRThunk::writeTo(uint8_t *buf
) {
1069 write32(ctx
, buf
, 0x940c); // jmp func
1070 ctx
.target
->relocateNoSym(buf
, R_AVR_CALL
, destination
.getVA(ctx
));
1073 void AVRThunk::addSymbols(ThunkSection
&isec
) {
1074 addSymbol(ctx
.saver
.save("__AVRThunk_" + destination
.getName()), STT_FUNC
, 0,
1078 // Write MIPS LA25 thunk code to call PIC function from the non-PIC one.
1079 void MipsThunk::writeTo(uint8_t *buf
) {
1080 uint64_t s
= destination
.getVA(ctx
);
1081 write32(ctx
, buf
, 0x3c190000); // lui $25, %hi(func)
1082 write32(ctx
, buf
+ 4, 0x08000000 | (s
>> 2)); // j func
1083 write32(ctx
, buf
+ 8, 0x27390000); // addiu $25, $25, %lo(func)
1084 write32(ctx
, buf
+ 12, 0x00000000); // nop
1085 ctx
.target
->relocateNoSym(buf
, R_MIPS_HI16
, s
);
1086 ctx
.target
->relocateNoSym(buf
+ 8, R_MIPS_LO16
, s
);
1089 void MipsThunk::addSymbols(ThunkSection
&isec
) {
1090 addSymbol(ctx
.saver
.save("__LA25Thunk_" + destination
.getName()), STT_FUNC
, 0,
1094 InputSection
*MipsThunk::getTargetInputSection() const {
1095 auto &dr
= cast
<Defined
>(destination
);
1096 return dyn_cast
<InputSection
>(dr
.section
);
1099 // Write microMIPS R2-R5 LA25 thunk code
1100 // to call PIC function from the non-PIC one.
1101 void MicroMipsThunk::writeTo(uint8_t *buf
) {
1102 uint64_t s
= destination
.getVA(ctx
);
1103 write16(ctx
, buf
, 0x41b9); // lui $25, %hi(func)
1104 write16(ctx
, buf
+ 4, 0xd400); // j func
1105 write16(ctx
, buf
+ 8, 0x3339); // addiu $25, $25, %lo(func)
1106 write16(ctx
, buf
+ 12, 0x0c00); // nop
1107 ctx
.target
->relocateNoSym(buf
, R_MICROMIPS_HI16
, s
);
1108 ctx
.target
->relocateNoSym(buf
+ 4, R_MICROMIPS_26_S1
, s
);
1109 ctx
.target
->relocateNoSym(buf
+ 8, R_MICROMIPS_LO16
, s
);
1112 void MicroMipsThunk::addSymbols(ThunkSection
&isec
) {
1114 addSymbol(ctx
.saver
.save("__microLA25Thunk_" + destination
.getName()),
1116 d
->stOther
|= STO_MIPS_MICROMIPS
;
1119 InputSection
*MicroMipsThunk::getTargetInputSection() const {
1120 auto &dr
= cast
<Defined
>(destination
);
1121 return dyn_cast
<InputSection
>(dr
.section
);
1124 // Write microMIPS R6 LA25 thunk code
1125 // to call PIC function from the non-PIC one.
1126 void MicroMipsR6Thunk::writeTo(uint8_t *buf
) {
1127 uint64_t s
= destination
.getVA(ctx
);
1128 uint64_t p
= getThunkTargetSym()->getVA(ctx
);
1129 write16(ctx
, buf
, 0x1320); // lui $25, %hi(func)
1130 write16(ctx
, buf
+ 4, 0x3339); // addiu $25, $25, %lo(func)
1131 write16(ctx
, buf
+ 8, 0x9400); // bc func
1132 ctx
.target
->relocateNoSym(buf
, R_MICROMIPS_HI16
, s
);
1133 ctx
.target
->relocateNoSym(buf
+ 4, R_MICROMIPS_LO16
, s
);
1134 ctx
.target
->relocateNoSym(buf
+ 8, R_MICROMIPS_PC26_S1
, s
- p
- 12);
1137 void MicroMipsR6Thunk::addSymbols(ThunkSection
&isec
) {
1139 addSymbol(ctx
.saver
.save("__microLA25Thunk_" + destination
.getName()),
1141 d
->stOther
|= STO_MIPS_MICROMIPS
;
1144 InputSection
*MicroMipsR6Thunk::getTargetInputSection() const {
1145 auto &dr
= cast
<Defined
>(destination
);
1146 return dyn_cast
<InputSection
>(dr
.section
);
1149 void elf::writePPC32PltCallStub(Ctx
&ctx
, uint8_t *buf
, uint64_t gotPltVA
,
1150 const InputFile
*file
, int64_t addend
) {
1151 if (!ctx
.arg
.isPic
) {
1152 write32(ctx
, buf
+ 0, 0x3d600000 | (gotPltVA
+ 0x8000) >> 16); // lis r11,ha
1153 write32(ctx
, buf
+ 4, 0x816b0000 | (uint16_t)gotPltVA
); // lwz r11,l(r11)
1154 write32(ctx
, buf
+ 8, 0x7d6903a6); // mtctr r11
1155 write32(ctx
, buf
+ 12, 0x4e800420); // bctr
1159 if (addend
>= 0x8000) {
1160 // The stub loads an address relative to r30 (.got2+Addend). Addend is
1161 // almost always 0x8000. The address of .got2 is different in another object
1162 // file, so a stub cannot be shared.
1164 (ctx
.in
.ppc32Got2
->getParent()->getVA() +
1165 (file
->ppc32Got2
? file
->ppc32Got2
->outSecOff
: 0) + addend
);
1167 // The stub loads an address relative to _GLOBAL_OFFSET_TABLE_ (which is
1168 // currently the address of .got).
1169 offset
= gotPltVA
- ctx
.in
.got
->getVA();
1171 uint16_t ha
= (offset
+ 0x8000) >> 16, l
= (uint16_t)offset
;
1173 write32(ctx
, buf
+ 0, 0x817e0000 | l
); // lwz r11,l(r30)
1174 write32(ctx
, buf
+ 4, 0x7d6903a6); // mtctr r11
1175 write32(ctx
, buf
+ 8, 0x4e800420); // bctr
1176 write32(ctx
, buf
+ 12, 0x60000000); // nop
1178 write32(ctx
, buf
+ 0, 0x3d7e0000 | ha
); // addis r11,r30,ha
1179 write32(ctx
, buf
+ 4, 0x816b0000 | l
); // lwz r11,l(r11)
1180 write32(ctx
, buf
+ 8, 0x7d6903a6); // mtctr r11
1181 write32(ctx
, buf
+ 12, 0x4e800420); // bctr
1185 void PPC32PltCallStub::writeTo(uint8_t *buf
) {
1186 writePPC32PltCallStub(ctx
, buf
, destination
.getGotPltVA(ctx
), file
, addend
);
1189 void PPC32PltCallStub::addSymbols(ThunkSection
&isec
) {
1191 raw_string_ostream
os(buf
);
1192 os
<< format_hex_no_prefix(addend
, 8);
1194 os
<< ".plt_call32.";
1195 else if (addend
>= 0x8000)
1196 os
<< ".got2.plt_pic32.";
1198 os
<< ".plt_pic32.";
1199 os
<< destination
.getName();
1200 addSymbol(ctx
.saver
.save(buf
), STT_FUNC
, 0, isec
);
1203 bool PPC32PltCallStub::isCompatibleWith(const InputSection
&isec
,
1204 const Relocation
&rel
) const {
1205 return !ctx
.arg
.isPic
|| (isec
.file
== file
&& rel
.addend
== addend
);
1208 void PPC32LongThunk::addSymbols(ThunkSection
&isec
) {
1209 addSymbol(ctx
.saver
.save("__LongThunk_" + destination
.getName()), STT_FUNC
, 0,
1213 void PPC32LongThunk::writeTo(uint8_t *buf
) {
1214 auto ha
= [](uint32_t v
) -> uint16_t { return (v
+ 0x8000) >> 16; };
1215 auto lo
= [](uint32_t v
) -> uint16_t { return v
; };
1216 uint32_t d
= destination
.getVA(ctx
, addend
);
1217 if (ctx
.arg
.isPic
) {
1218 uint32_t off
= d
- (getThunkTargetSym()->getVA(ctx
) + 8);
1219 write32(ctx
, buf
+ 0, 0x7c0802a6); // mflr r12,0
1220 write32(ctx
, buf
+ 4, 0x429f0005); // bcl r20,r31,.+4
1221 write32(ctx
, buf
+ 8, 0x7d8802a6); // mtctr r12
1222 write32(ctx
, buf
+ 12, 0x3d8c0000 | ha(off
)); // addis r12,r12,off@ha
1223 write32(ctx
, buf
+ 16, 0x398c0000 | lo(off
)); // addi r12,r12,off@l
1224 write32(ctx
, buf
+ 20, 0x7c0803a6); // mtlr r0
1227 write32(ctx
, buf
+ 0, 0x3d800000 | ha(d
)); // lis r12,d@ha
1228 write32(ctx
, buf
+ 4, 0x398c0000 | lo(d
)); // addi r12,r12,d@l
1231 write32(ctx
, buf
+ 0, 0x7d8903a6); // mtctr r12
1232 write32(ctx
, buf
+ 4, 0x4e800420); // bctr
1235 void elf::writePPC64LoadAndBranch(Ctx
&ctx
, uint8_t *buf
, int64_t offset
) {
1236 uint16_t offHa
= (offset
+ 0x8000) >> 16;
1237 uint16_t offLo
= offset
& 0xffff;
1239 write32(ctx
, buf
+ 0, 0x3d820000 | offHa
); // addis r12, r2, OffHa
1240 write32(ctx
, buf
+ 4, 0xe98c0000 | offLo
); // ld r12, OffLo(r12)
1241 write32(ctx
, buf
+ 8, 0x7d8903a6); // mtctr r12
1242 write32(ctx
, buf
+ 12, 0x4e800420); // bctr
1245 void PPC64PltCallStub::writeTo(uint8_t *buf
) {
1246 int64_t offset
= destination
.getGotPltVA(ctx
) - getPPC64TocBase(ctx
);
1247 // Save the TOC pointer to the save-slot reserved in the call frame.
1248 write32(ctx
, buf
+ 0, 0xf8410018); // std r2,24(r1)
1249 writePPC64LoadAndBranch(ctx
, buf
+ 4, offset
);
1252 void PPC64PltCallStub::addSymbols(ThunkSection
&isec
) {
1253 Defined
*s
= addSymbol(ctx
.saver
.save("__plt_" + destination
.getName()),
1255 s
->setNeedsTocRestore(true);
1256 s
->file
= destination
.file
;
1259 bool PPC64PltCallStub::isCompatibleWith(const InputSection
&isec
,
1260 const Relocation
&rel
) const {
1261 return rel
.type
== R_PPC64_REL24
|| rel
.type
== R_PPC64_REL14
;
1264 void PPC64R2SaveStub::writeTo(uint8_t *buf
) {
1265 const int64_t offset
= computeOffset();
1266 write32(ctx
, buf
+ 0, 0xf8410018); // std r2,24(r1)
1267 // The branch offset needs to fit in 26 bits.
1268 if (getMayUseShortThunk()) {
1269 write32(ctx
, buf
+ 4, 0x48000000 | (offset
& 0x03fffffc)); // b <offset>
1270 } else if (isInt
<34>(offset
)) {
1272 uint64_t tocOffset
= destination
.getVA(ctx
) - getPPC64TocBase(ctx
);
1273 if (tocOffset
>> 16 > 0) {
1274 const uint64_t addi
= ADDI_R12_TO_R12_NO_DISP
| (tocOffset
& 0xffff);
1275 const uint64_t addis
=
1276 ADDIS_R12_TO_R2_NO_DISP
| ((tocOffset
>> 16) & 0xffff);
1277 write32(ctx
, buf
+ 4, addis
); // addis r12, r2 , top of offset
1278 write32(ctx
, buf
+ 8, addi
); // addi r12, r12, bottom of offset
1279 nextInstOffset
= 12;
1281 const uint64_t addi
= ADDI_R12_TO_R2_NO_DISP
| (tocOffset
& 0xffff);
1282 write32(ctx
, buf
+ 4, addi
); // addi r12, r2, offset
1285 write32(ctx
, buf
+ nextInstOffset
, MTCTR_R12
); // mtctr r12
1286 write32(ctx
, buf
+ nextInstOffset
+ 4, BCTR
); // bctr
1288 ctx
.in
.ppc64LongBranchTarget
->addEntry(&destination
, addend
);
1289 const int64_t offsetFromTOC
=
1290 ctx
.in
.ppc64LongBranchTarget
->getEntryVA(&destination
, addend
) -
1291 getPPC64TocBase(ctx
);
1292 writePPC64LoadAndBranch(ctx
, buf
+ 4, offsetFromTOC
);
1296 void PPC64R2SaveStub::addSymbols(ThunkSection
&isec
) {
1297 Defined
*s
= addSymbol(ctx
.saver
.save("__toc_save_" + destination
.getName()),
1299 s
->setNeedsTocRestore(true);
1302 bool PPC64R2SaveStub::isCompatibleWith(const InputSection
&isec
,
1303 const Relocation
&rel
) const {
1304 return rel
.type
== R_PPC64_REL24
|| rel
.type
== R_PPC64_REL14
;
1307 void PPC64R12SetupStub::writeTo(uint8_t *buf
) {
1309 (gotPlt
? destination
.getGotPltVA(ctx
) : destination
.getVA(ctx
)) -
1310 getThunkTargetSym()->getVA(ctx
);
1311 if (!isInt
<34>(offset
))
1312 reportRangeError(ctx
, buf
, offset
, 34, destination
,
1313 "R12 setup stub offset");
1316 if (ctx
.arg
.power10Stubs
) {
1317 const uint64_t imm
= (((offset
>> 16) & 0x3ffff) << 32) | (offset
& 0xffff);
1318 // pld 12, func@plt@pcrel or paddi r12, 0, func@pcrel
1319 writePrefixedInst(ctx
, buf
,
1320 (gotPlt
? PLD_R12_NO_DISP
: PADDI_R12_NO_DISP
) | imm
);
1323 uint32_t off
= offset
- 8;
1324 write32(ctx
, buf
+ 0, 0x7d8802a6); // mflr 12
1325 write32(ctx
, buf
+ 4, 0x429f0005); // bcl 20,31,.+4
1326 write32(ctx
, buf
+ 8, 0x7d6802a6); // mflr 11
1327 write32(ctx
, buf
+ 12, 0x7d8803a6); // mtlr 12
1328 write32(ctx
, buf
+ 16,
1329 0x3d8b0000 | ((off
+ 0x8000) >> 16)); // addis 12,11,off@ha
1331 write32(ctx
, buf
+ 20, 0xe98c0000 | (off
& 0xffff)); // ld 12, off@l(12)
1333 write32(ctx
, buf
+ 20, 0x398c0000 | (off
& 0xffff)); // addi 12,12,off@l
1334 nextInstOffset
= 24;
1336 write32(ctx
, buf
+ nextInstOffset
, MTCTR_R12
); // mtctr r12
1337 write32(ctx
, buf
+ nextInstOffset
+ 4, BCTR
); // bctr
1340 void PPC64R12SetupStub::addSymbols(ThunkSection
&isec
) {
1341 addSymbol(ctx
.saver
.save((gotPlt
? "__plt_pcrel_" : "__gep_setup_") +
1342 destination
.getName()),
1346 bool PPC64R12SetupStub::isCompatibleWith(const InputSection
&isec
,
1347 const Relocation
&rel
) const {
1348 return rel
.type
== R_PPC64_REL24_NOTOC
;
1351 void PPC64LongBranchThunk::writeTo(uint8_t *buf
) {
1353 ctx
.in
.ppc64LongBranchTarget
->getEntryVA(&destination
, addend
) -
1354 getPPC64TocBase(ctx
);
1355 writePPC64LoadAndBranch(ctx
, buf
, offset
);
1358 void PPC64LongBranchThunk::addSymbols(ThunkSection
&isec
) {
1359 addSymbol(ctx
.saver
.save("__long_branch_" + destination
.getName()), STT_FUNC
,
1363 bool PPC64LongBranchThunk::isCompatibleWith(const InputSection
&isec
,
1364 const Relocation
&rel
) const {
1365 return rel
.type
== R_PPC64_REL24
|| rel
.type
== R_PPC64_REL14
;
1368 Thunk::Thunk(Ctx
&ctx
, Symbol
&d
, int64_t a
)
1369 : ctx(ctx
), destination(d
), addend(a
), offset(0) {
1370 destination
.thunkAccessed
= true;
1373 Thunk::~Thunk() = default;
1375 static std::unique_ptr
<Thunk
> addThunkAArch64(Ctx
&ctx
, RelType type
, Symbol
&s
,
1377 assert(is_contained({R_AARCH64_CALL26
, R_AARCH64_JUMP26
, R_AARCH64_PLT32
},
1379 bool mayNeedLandingPad
=
1380 (ctx
.arg
.andFeatures
& GNU_PROPERTY_AARCH64_FEATURE_1_BTI
) &&
1381 !isAArch64BTILandingPad(ctx
, s
, a
);
1382 if (ctx
.arg
.picThunk
)
1383 return std::make_unique
<AArch64ADRPThunk
>(ctx
, s
, a
, mayNeedLandingPad
);
1384 return std::make_unique
<AArch64ABSLongThunk
>(ctx
, s
, a
, mayNeedLandingPad
);
1387 // Creates a thunk for long branches or Thumb-ARM interworking.
1388 // Arm Architectures v4t does not support Thumb2 technology, and does not
1389 // support BLX or LDR Arm/Thumb state switching. This means that
1390 // - MOVT and MOVW instructions cannot be used.
1391 // - We can't rewrite BL in place to BLX. We will need thunks.
1393 // TODO: use B for short Thumb->Arm thunks instead of LDR (this doesn't work for
1394 // Arm->Thumb, as in Arm state no BX PC trick; it doesn't switch state).
1395 static std::unique_ptr
<Thunk
> addThunkArmv4(Ctx
&ctx
, RelType reloc
, Symbol
&s
,
1397 bool thumb_target
= s
.getVA(ctx
, a
) & 1;
1404 if (ctx
.arg
.picThunk
) {
1406 return std::make_unique
<ARMV4PILongBXThunk
>(ctx
, s
, a
);
1407 return std::make_unique
<ARMV4PILongThunk
>(ctx
, s
, a
);
1410 return std::make_unique
<ARMV4ABSLongBXThunk
>(ctx
, s
, a
);
1411 return std::make_unique
<ARMV5LongLdrPcThunk
>(ctx
, s
, a
);
1412 case R_ARM_THM_CALL
:
1413 if (ctx
.arg
.picThunk
) {
1415 return std::make_unique
<ThumbV4PILongThunk
>(ctx
, s
, a
);
1416 return std::make_unique
<ThumbV4PILongBXThunk
>(ctx
, s
, a
);
1419 return std::make_unique
<ThumbV4ABSLongThunk
>(ctx
, s
, a
);
1420 return std::make_unique
<ThumbV4ABSLongBXThunk
>(ctx
, s
, a
);
1422 Fatal(ctx
) << "relocation " << reloc
<< " to " << &s
1423 << " not supported for Armv4 or Armv4T target";
1424 llvm_unreachable("");
1427 // Creates a thunk for Thumb-ARM interworking compatible with Armv5 and Armv6.
1428 // Arm Architectures v5 and v6 do not support Thumb2 technology. This means that
1429 // - MOVT and MOVW instructions cannot be used
1430 // - Only Thumb relocation that can generate a Thunk is a BL, this can always
1431 // be transformed into a BLX
1432 static std::unique_ptr
<Thunk
> addThunkArmv5v6(Ctx
&ctx
, RelType reloc
,
1433 Symbol
&s
, int64_t a
) {
1439 case R_ARM_THM_CALL
:
1440 if (ctx
.arg
.picThunk
)
1441 return std::make_unique
<ARMV4PILongBXThunk
>(ctx
, s
, a
);
1442 return std::make_unique
<ARMV5LongLdrPcThunk
>(ctx
, s
, a
);
1444 Fatal(ctx
) << "relocation " << reloc
<< " to " << &s
1445 << " not supported for Armv5 or Armv6 targets";
1446 llvm_unreachable("");
1449 // Create a thunk for Thumb long branch on V6-M.
1450 // Arm Architecture v6-M only supports Thumb instructions. This means
1451 // - MOVT and MOVW instructions cannot be used.
1452 // - Only a limited number of instructions can access registers r8 and above
1453 // - No interworking support is needed (all Thumb).
1454 static std::unique_ptr
<Thunk
> addThunkV6M(Ctx
&ctx
, const InputSection
&isec
,
1455 RelType reloc
, Symbol
&s
, int64_t a
) {
1456 const bool isPureCode
= isec
.getParent()->flags
& SHF_ARM_PURECODE
;
1458 case R_ARM_THM_JUMP19
:
1459 case R_ARM_THM_JUMP24
:
1460 case R_ARM_THM_CALL
:
1461 if (ctx
.arg
.isPic
) {
1463 return std::make_unique
<ThumbV6MPILongThunk
>(ctx
, s
, a
);
1466 << "relocation " << reloc
<< " to " << &s
1467 << " not supported for Armv6-M targets for position independent"
1468 " and execute only code";
1469 llvm_unreachable("");
1472 return std::make_unique
<ThumbV6MABSXOLongThunk
>(ctx
, s
, a
);
1473 return std::make_unique
<ThumbV6MABSLongThunk
>(ctx
, s
, a
);
1475 Fatal(ctx
) << "relocation " << reloc
<< " to " << &s
1476 << " not supported for Armv6-M targets";
1477 llvm_unreachable("");
1480 // Creates a thunk for Thumb-ARM interworking or branch range extension.
1481 static std::unique_ptr
<Thunk
> addThunkArm(Ctx
&ctx
, const InputSection
&isec
,
1482 RelType reloc
, Symbol
&s
, int64_t a
) {
1483 // Decide which Thunk is needed based on:
1484 // Available instruction set
1485 // - An Arm Thunk can only be used if Arm state is available.
1486 // - A Thumb Thunk can only be used if Thumb state is available.
1487 // - Can only use a Thunk if it uses instructions that the Target supports.
1488 // Relocation is branch or branch and link
1489 // - Branch instructions cannot change state, can only select Thunk that
1490 // starts in the same state as the caller.
1491 // - Branch and link relocations can change state, can select Thunks from
1492 // either Arm or Thumb.
1493 // Position independent Thunks if we require position independent code.
1494 // Execute Only Thunks if the output section is execute only code.
1496 // Handle architectures that have restrictions on the instructions that they
1497 // can use in Thunks. The flags below are set by reading the BuildAttributes
1498 // of the input objects. InputFiles.cpp contains the mapping from ARM
1499 // architecture to flag.
1500 if (!ctx
.arg
.armHasMovtMovw
) {
1501 if (ctx
.arg
.armJ1J2BranchEncoding
)
1502 return addThunkV6M(ctx
, isec
, reloc
, s
, a
);
1503 if (ctx
.arg
.armHasBlx
)
1504 return addThunkArmv5v6(ctx
, reloc
, s
, a
);
1505 return addThunkArmv4(ctx
, reloc
, s
, a
);
1513 if (ctx
.arg
.picThunk
)
1514 return std::make_unique
<ARMV7PILongThunk
>(ctx
, s
, a
);
1515 return std::make_unique
<ARMV7ABSLongThunk
>(ctx
, s
, a
);
1516 case R_ARM_THM_JUMP19
:
1517 case R_ARM_THM_JUMP24
:
1518 case R_ARM_THM_CALL
:
1519 if (ctx
.arg
.picThunk
)
1520 return std::make_unique
<ThumbV7PILongThunk
>(ctx
, s
, a
);
1521 return std::make_unique
<ThumbV7ABSLongThunk
>(ctx
, s
, a
);
1523 llvm_unreachable("");
1526 static std::unique_ptr
<Thunk
> addThunkAVR(Ctx
&ctx
, RelType type
, Symbol
&s
,
1529 case R_AVR_LO8_LDI_GS
:
1530 case R_AVR_HI8_LDI_GS
:
1531 return std::make_unique
<AVRThunk
>(ctx
, s
, a
);
1533 llvm_unreachable("");
1537 static std::unique_ptr
<Thunk
> addThunkMips(Ctx
&ctx
, RelType type
, Symbol
&s
) {
1538 if ((s
.stOther
& STO_MIPS_MICROMIPS
) && isMipsR6(ctx
))
1539 return std::make_unique
<MicroMipsR6Thunk
>(ctx
, s
);
1540 if (s
.stOther
& STO_MIPS_MICROMIPS
)
1541 return std::make_unique
<MicroMipsThunk
>(ctx
, s
);
1542 return std::make_unique
<MipsThunk
>(ctx
, s
);
1545 static std::unique_ptr
<Thunk
> addThunkPPC32(Ctx
&ctx
, const InputSection
&isec
,
1546 const Relocation
&rel
, Symbol
&s
) {
1547 assert((rel
.type
== R_PPC_LOCAL24PC
|| rel
.type
== R_PPC_REL24
||
1548 rel
.type
== R_PPC_PLTREL24
) &&
1549 "unexpected relocation type for thunk");
1551 return std::make_unique
<PPC32PltCallStub
>(ctx
, isec
, rel
, s
);
1552 return std::make_unique
<PPC32LongThunk
>(ctx
, s
, rel
.addend
);
1555 static std::unique_ptr
<Thunk
> addThunkPPC64(Ctx
&ctx
, RelType type
, Symbol
&s
,
1557 assert((type
== R_PPC64_REL14
|| type
== R_PPC64_REL24
||
1558 type
== R_PPC64_REL24_NOTOC
) &&
1559 "unexpected relocation type for thunk");
1561 // If we are emitting stubs for NOTOC relocations, we need to tell
1562 // the PLT resolver that there can be multiple TOCs.
1563 if (type
== R_PPC64_REL24_NOTOC
)
1564 ctx
.target
->ppc64DynamicSectionOpt
= 0x2;
1566 if (s
.isInPlt(ctx
)) {
1567 if (type
== R_PPC64_REL24_NOTOC
)
1568 return std::make_unique
<PPC64R12SetupStub
>(ctx
, s
,
1570 return std::make_unique
<PPC64PltCallStub
>(ctx
, s
);
1573 // This check looks at the st_other bits of the callee. If the value is 1
1574 // then the callee clobbers the TOC and we need an R2 save stub when RelType
1575 // is R_PPC64_REL14 or R_PPC64_REL24.
1576 if ((type
== R_PPC64_REL14
|| type
== R_PPC64_REL24
) && (s
.stOther
>> 5) == 1)
1577 return std::make_unique
<PPC64R2SaveStub
>(ctx
, s
, a
);
1579 if (type
== R_PPC64_REL24_NOTOC
)
1580 return std::make_unique
<PPC64R12SetupStub
>(ctx
, s
, /*gotPlt=*/false);
1582 if (ctx
.arg
.picThunk
)
1583 return std::make_unique
<PPC64PILongBranchThunk
>(ctx
, s
, a
);
1585 return std::make_unique
<PPC64PDLongBranchThunk
>(ctx
, s
, a
);
1588 std::unique_ptr
<Thunk
> elf::addThunk(Ctx
&ctx
, const InputSection
&isec
,
1590 Symbol
&s
= *rel
.sym
;
1591 int64_t a
= rel
.addend
;
1593 switch (ctx
.arg
.emachine
) {
1595 return addThunkAArch64(ctx
, rel
.type
, s
, a
);
1597 return addThunkArm(ctx
, isec
, rel
.type
, s
, a
);
1599 return addThunkAVR(ctx
, rel
.type
, s
, a
);
1601 return addThunkMips(ctx
, rel
.type
, s
);
1603 return addThunkPPC32(ctx
, isec
, rel
, s
);
1605 return addThunkPPC64(ctx
, rel
.type
, s
, a
);
1607 llvm_unreachable("add Thunk only supported for ARM, AVR, Mips and PowerPC");
1611 std::unique_ptr
<Thunk
> elf::addLandingPadThunk(Ctx
&ctx
, Symbol
&s
, int64_t a
) {
1612 switch (ctx
.arg
.emachine
) {
1614 return std::make_unique
<AArch64BTILandingPadThunk
>(ctx
, s
, a
);
1616 llvm_unreachable("add landing pad only supported for AArch64");