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;
72 // A thunk may be written out as a short or long, and we may not know which
73 // type at thunk creation time. In some thunk implementations the long thunk
74 // has additional mapping symbols. Thus function can be overridden to add
75 // these additional mapping symbols.
76 virtual void addLongMapSyms() {}
79 // AArch64 long range Thunks.
80 class AArch64ABSLongThunk final
: public AArch64Thunk
{
82 AArch64ABSLongThunk(Ctx
&ctx
, Symbol
&dest
, int64_t addend
,
83 bool mayNeedLandingPad
)
84 : AArch64Thunk(ctx
, dest
, addend
, mayNeedLandingPad
) {}
85 uint32_t size() override
{ return getMayUseShortThunk() ? 4 : 16; }
86 void addSymbols(ThunkSection
&isec
) override
;
89 void writeLong(uint8_t *buf
) override
;
90 void addLongMapSyms() override
;
91 ThunkSection
*tsec
= nullptr;
94 class AArch64ADRPThunk final
: public AArch64Thunk
{
96 AArch64ADRPThunk(Ctx
&ctx
, Symbol
&dest
, int64_t addend
,
97 bool mayNeedLandingPad
)
98 : AArch64Thunk(ctx
, dest
, addend
, mayNeedLandingPad
) {}
99 uint32_t size() override
{ return getMayUseShortThunk() ? 4 : 12; }
100 void addSymbols(ThunkSection
&isec
) override
;
103 void writeLong(uint8_t *buf
) override
;
106 // AArch64 BTI Landing Pad
107 // When BTI is enabled indirect branches must land on a BTI
108 // compatible instruction. When the destination does not have a
109 // BTI compatible instruction a Thunk doing an indirect branch
110 // targets a Landing Pad Thunk that direct branches to the target.
111 class AArch64BTILandingPadThunk final
: public Thunk
{
113 AArch64BTILandingPadThunk(Ctx
&ctx
, Symbol
&dest
, int64_t addend
)
114 : Thunk(ctx
, dest
, addend
) {}
116 uint32_t size() override
{ return getMayUseShortThunk() ? 4 : 8; }
117 void addSymbols(ThunkSection
&isec
) override
;
118 void writeTo(uint8_t *buf
) override
;
121 bool getMayUseShortThunk();
122 void writeLong(uint8_t *buf
);
123 bool mayUseShortThunk
= true;
126 // Base class for ARM thunks.
128 // An ARM thunk may be either short or long. A short thunk is simply a branch
129 // (B) instruction, and it may be used to call ARM functions when the distance
130 // from the thunk to the target is less than 32MB. Long thunks can branch to any
131 // virtual address and can switch between ARM and Thumb, and they are
132 // implemented in the derived classes. This class tries to create a short thunk
133 // if the target is in range, otherwise it creates a long thunk.
134 class ARMThunk
: public Thunk
{
136 ARMThunk(Ctx
&ctx
, Symbol
&dest
, int64_t addend
) : Thunk(ctx
, dest
, addend
) {}
138 bool getMayUseShortThunk();
139 uint32_t size() override
{ return getMayUseShortThunk() ? 4 : sizeLong(); }
140 void writeTo(uint8_t *buf
) override
;
141 bool isCompatibleWith(const InputSection
&isec
,
142 const Relocation
&rel
) const override
;
144 // Returns the size of a long thunk.
145 virtual uint32_t sizeLong() = 0;
147 // Writes a long thunk to Buf.
148 virtual void writeLong(uint8_t *buf
) = 0;
151 // This field tracks whether all previously considered layouts would allow
152 // this thunk to be short. If we have ever needed a long thunk, we always
153 // create a long thunk, even if the thunk may be short given the current
154 // distance to the target. We do this because transitioning from long to short
155 // can create layout oscillations in certain corner cases which would prevent
156 // the layout from converging.
157 bool mayUseShortThunk
= true;
158 // See comment in AArch64Thunk.
159 virtual void addLongMapSyms() {}
162 // Base class for Thumb-2 thunks.
164 // This class is similar to ARMThunk, but it uses the Thumb-2 B.W instruction
165 // which has a range of 16MB.
166 class ThumbThunk
: public Thunk
{
168 ThumbThunk(Ctx
&ctx
, Symbol
&dest
, int64_t addend
)
169 : Thunk(ctx
, dest
, addend
) {
173 bool getMayUseShortThunk();
174 uint32_t size() override
{ return getMayUseShortThunk() ? 4 : sizeLong(); }
175 void writeTo(uint8_t *buf
) override
;
176 bool isCompatibleWith(const InputSection
&isec
,
177 const Relocation
&rel
) const override
;
179 // Returns the size of a long thunk.
180 virtual uint32_t sizeLong() = 0;
182 // Writes a long thunk to Buf.
183 virtual void writeLong(uint8_t *buf
) = 0;
186 // See comment in ARMThunk above.
187 bool mayUseShortThunk
= true;
188 // See comment in AArch64Thunk.
189 virtual void addLongMapSyms() {}
192 // Specific ARM Thunk implementations. The naming convention is:
193 // Source State, TargetState, Target Requirement, ABS or PI, Range
194 class ARMV7ABSLongThunk final
: public ARMThunk
{
196 ARMV7ABSLongThunk(Ctx
&ctx
, Symbol
&dest
, int64_t addend
)
197 : ARMThunk(ctx
, dest
, addend
) {}
199 uint32_t sizeLong() override
{ return 12; }
200 void writeLong(uint8_t *buf
) override
;
201 void addSymbols(ThunkSection
&isec
) override
;
204 class ARMV7PILongThunk final
: public ARMThunk
{
206 ARMV7PILongThunk(Ctx
&ctx
, Symbol
&dest
, int64_t addend
)
207 : ARMThunk(ctx
, dest
, addend
) {}
209 uint32_t sizeLong() override
{ return 16; }
210 void writeLong(uint8_t *buf
) override
;
211 void addSymbols(ThunkSection
&isec
) override
;
214 class ThumbV7ABSLongThunk final
: public ThumbThunk
{
216 ThumbV7ABSLongThunk(Ctx
&ctx
, Symbol
&dest
, int64_t addend
)
217 : ThumbThunk(ctx
, dest
, addend
) {}
219 uint32_t sizeLong() override
{ return 10; }
220 void writeLong(uint8_t *buf
) override
;
221 void addSymbols(ThunkSection
&isec
) override
;
224 class ThumbV7PILongThunk final
: public ThumbThunk
{
226 ThumbV7PILongThunk(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 // Implementations of Thunks for Arm v6-M. Only Thumb instructions are permitted
235 class ThumbV6MABSLongThunk final
: public ThumbThunk
{
237 ThumbV6MABSLongThunk(Ctx
&ctx
, Symbol
&dest
, int64_t addend
)
238 : ThumbThunk(ctx
, dest
, addend
) {}
240 uint32_t sizeLong() override
{ return 12; }
241 void writeLong(uint8_t *buf
) override
;
242 void addSymbols(ThunkSection
&isec
) override
;
245 void addLongMapSyms() override
;
246 ThunkSection
*tsec
= nullptr;
249 class ThumbV6MABSXOLongThunk final
: public ThumbThunk
{
251 ThumbV6MABSXOLongThunk(Ctx
&ctx
, Symbol
&dest
, int64_t addend
)
252 : ThumbThunk(ctx
, dest
, addend
) {}
254 uint32_t sizeLong() override
{ return 20; }
255 void writeLong(uint8_t *buf
) override
;
256 void addSymbols(ThunkSection
&isec
) override
;
259 class ThumbV6MPILongThunk final
: public ThumbThunk
{
261 ThumbV6MPILongThunk(Ctx
&ctx
, Symbol
&dest
, int64_t addend
)
262 : ThumbThunk(ctx
, dest
, addend
) {}
264 uint32_t sizeLong() override
{ return 16; }
265 void writeLong(uint8_t *buf
) override
;
266 void addSymbols(ThunkSection
&isec
) override
;
269 void addLongMapSyms() override
;
270 ThunkSection
*tsec
= nullptr;
273 // Architectures v4, v5 and v6 do not support the movt/movw instructions. v5 and
274 // v6 support BLX to which BL instructions can be rewritten inline. There are no
275 // Thumb entrypoints for v5 and v6 as there is no Thumb branch instruction on
276 // these architecture that can result in a thunk.
278 // LDR on v5 and v6 can switch processor state, so for v5 and v6,
279 // ARMV5LongLdrPcThunk can be used for both Arm->Arm and Arm->Thumb calls. v4
280 // can also use this thunk, but only for Arm->Arm calls.
281 class ARMV5LongLdrPcThunk final
: public ARMThunk
{
283 ARMV5LongLdrPcThunk(Ctx
&ctx
, Symbol
&dest
, int64_t addend
)
284 : ARMThunk(ctx
, dest
, addend
) {}
286 uint32_t sizeLong() override
{ return 8; }
287 void writeLong(uint8_t *buf
) override
;
288 void addSymbols(ThunkSection
&isec
) override
;
291 void addLongMapSyms() override
;
292 ThunkSection
*tsec
= nullptr;
295 // Implementations of Thunks for v4. BLX is not supported, and loads
296 // will not invoke Arm/Thumb state changes.
297 class ARMV4PILongBXThunk final
: public ARMThunk
{
299 ARMV4PILongBXThunk(Ctx
&ctx
, Symbol
&dest
, int64_t addend
)
300 : ARMThunk(ctx
, dest
, addend
) {}
302 uint32_t sizeLong() override
{ return 16; }
303 void writeLong(uint8_t *buf
) override
;
304 void addSymbols(ThunkSection
&isec
) override
;
307 void addLongMapSyms() override
;
308 ThunkSection
*tsec
= nullptr;
311 class ARMV4PILongThunk final
: public ARMThunk
{
313 ARMV4PILongThunk(Ctx
&ctx
, Symbol
&dest
, int64_t addend
)
314 : ARMThunk(ctx
, dest
, addend
) {}
316 uint32_t sizeLong() override
{ return 12; }
317 void writeLong(uint8_t *buf
) override
;
318 void addSymbols(ThunkSection
&isec
) override
;
321 void addLongMapSyms() override
;
322 ThunkSection
*tsec
= nullptr;
325 class ThumbV4PILongBXThunk final
: public ThumbThunk
{
327 ThumbV4PILongBXThunk(Ctx
&ctx
, Symbol
&dest
, int64_t addend
)
328 : ThumbThunk(ctx
, dest
, addend
) {}
330 uint32_t sizeLong() override
{ return 16; }
331 void writeLong(uint8_t *buf
) override
;
332 void addSymbols(ThunkSection
&isec
) override
;
335 void addLongMapSyms() override
;
336 ThunkSection
*tsec
= nullptr;
339 class ThumbV4PILongThunk final
: public ThumbThunk
{
341 ThumbV4PILongThunk(Ctx
&ctx
, Symbol
&dest
, int64_t addend
)
342 : ThumbThunk(ctx
, dest
, addend
) {}
344 uint32_t sizeLong() override
{ return 20; }
345 void writeLong(uint8_t *buf
) override
;
346 void addSymbols(ThunkSection
&isec
) override
;
349 void addLongMapSyms() override
;
350 ThunkSection
*tsec
= nullptr;
353 class ARMV4ABSLongBXThunk final
: public ARMThunk
{
355 ARMV4ABSLongBXThunk(Ctx
&ctx
, Symbol
&dest
, int64_t addend
)
356 : ARMThunk(ctx
, dest
, addend
) {}
358 uint32_t sizeLong() override
{ return 12; }
359 void writeLong(uint8_t *buf
) override
;
360 void addSymbols(ThunkSection
&isec
) override
;
363 void addLongMapSyms() override
;
364 ThunkSection
*tsec
= nullptr;
367 class ThumbV4ABSLongBXThunk final
: public ThumbThunk
{
369 ThumbV4ABSLongBXThunk(Ctx
&ctx
, Symbol
&dest
, int64_t addend
)
370 : ThumbThunk(ctx
, dest
, addend
) {}
372 uint32_t sizeLong() override
{ return 12; }
373 void writeLong(uint8_t *buf
) override
;
374 void addSymbols(ThunkSection
&isec
) override
;
377 void addLongMapSyms() override
;
378 ThunkSection
*tsec
= nullptr;
381 class ThumbV4ABSLongThunk final
: public ThumbThunk
{
383 ThumbV4ABSLongThunk(Ctx
&ctx
, Symbol
&dest
, int64_t addend
)
384 : ThumbThunk(ctx
, dest
, addend
) {}
386 uint32_t sizeLong() override
{ return 16; }
387 void writeLong(uint8_t *buf
) override
;
388 void addSymbols(ThunkSection
&isec
) override
;
391 void addLongMapSyms() override
;
392 ThunkSection
*tsec
= nullptr;
395 // The AVR devices need thunks for R_AVR_LO8_LDI_GS/R_AVR_HI8_LDI_GS
396 // when their destination is out of range [0, 0x1ffff].
397 class AVRThunk
: public Thunk
{
399 AVRThunk(Ctx
&ctx
, Symbol
&dest
, int64_t addend
) : Thunk(ctx
, dest
, addend
) {}
400 uint32_t size() override
{ return 4; }
401 void writeTo(uint8_t *buf
) override
;
402 void addSymbols(ThunkSection
&isec
) override
;
406 class MipsThunk final
: public Thunk
{
408 MipsThunk(Ctx
&ctx
, Symbol
&dest
) : Thunk(ctx
, dest
, 0) {}
410 uint32_t size() override
{ return 16; }
411 void writeTo(uint8_t *buf
) override
;
412 void addSymbols(ThunkSection
&isec
) override
;
413 InputSection
*getTargetInputSection() const override
;
416 // microMIPS R2-R5 LA25 thunk
417 class MicroMipsThunk final
: public Thunk
{
419 MicroMipsThunk(Ctx
&ctx
, Symbol
&dest
) : Thunk(ctx
, dest
, 0) {}
421 uint32_t size() override
{ return 14; }
422 void writeTo(uint8_t *buf
) override
;
423 void addSymbols(ThunkSection
&isec
) override
;
424 InputSection
*getTargetInputSection() const override
;
427 // microMIPS R6 LA25 thunk
428 class MicroMipsR6Thunk final
: public Thunk
{
430 MicroMipsR6Thunk(Ctx
&ctx
, Symbol
&dest
) : Thunk(ctx
, dest
, 0) {}
432 uint32_t size() override
{ return 12; }
433 void writeTo(uint8_t *buf
) override
;
434 void addSymbols(ThunkSection
&isec
) override
;
435 InputSection
*getTargetInputSection() const override
;
438 class PPC32PltCallStub final
: public Thunk
{
440 // For R_PPC_PLTREL24, Thunk::addend records the addend which will be used to
441 // decide the offsets in the call stub.
442 PPC32PltCallStub(Ctx
&ctx
, const InputSection
&isec
, const Relocation
&rel
,
444 : Thunk(ctx
, dest
, rel
.addend
), file(isec
.file
) {}
445 uint32_t size() override
{ return 16; }
446 void writeTo(uint8_t *buf
) override
;
447 void addSymbols(ThunkSection
&isec
) override
;
448 bool isCompatibleWith(const InputSection
&isec
, const Relocation
&rel
) const override
;
451 // Records the call site of the call stub.
452 const InputFile
*file
;
455 class PPC32LongThunk final
: public Thunk
{
457 PPC32LongThunk(Ctx
&ctx
, Symbol
&dest
, int64_t addend
)
458 : Thunk(ctx
, dest
, addend
) {}
459 uint32_t size() override
{ return ctx
.arg
.isPic
? 32 : 16; }
460 void writeTo(uint8_t *buf
) override
;
461 void addSymbols(ThunkSection
&isec
) override
;
464 // PPC64 Plt call stubs.
465 // Any call site that needs to call through a plt entry needs a call stub in
466 // the .text section. The call stub is responsible for:
467 // 1) Saving the toc-pointer to the stack.
468 // 2) Loading the target functions address from the procedure linkage table into
469 // r12 for use by the target functions global entry point, and into the count
471 // 3) Transferring control to the target function through an indirect branch.
472 class PPC64PltCallStub final
: public Thunk
{
474 PPC64PltCallStub(Ctx
&ctx
, Symbol
&dest
) : Thunk(ctx
, dest
, 0) {}
475 uint32_t size() override
{ return 20; }
476 void writeTo(uint8_t *buf
) override
;
477 void addSymbols(ThunkSection
&isec
) override
;
478 bool isCompatibleWith(const InputSection
&isec
,
479 const Relocation
&rel
) const override
;
482 // PPC64 R2 Save Stub
483 // When the caller requires a valid R2 TOC pointer but the callee does not
484 // require a TOC pointer and the callee cannot guarantee that it doesn't
485 // clobber R2 then we need to save R2. This stub:
486 // 1) Saves the TOC pointer to the stack.
487 // 2) Tail calls the callee.
488 class PPC64R2SaveStub final
: public Thunk
{
490 PPC64R2SaveStub(Ctx
&ctx
, Symbol
&dest
, int64_t addend
)
491 : Thunk(ctx
, dest
, addend
) {
495 // To prevent oscillations in layout when moving from short to long thunks
496 // we make sure that once a thunk has been set to long it cannot go back.
497 bool getMayUseShortThunk() {
498 if (!mayUseShortThunk
)
500 if (!isInt
<26>(computeOffset())) {
501 mayUseShortThunk
= false;
506 uint32_t size() override
{ return getMayUseShortThunk() ? 8 : 32; }
507 void writeTo(uint8_t *buf
) override
;
508 void addSymbols(ThunkSection
&isec
) override
;
509 bool isCompatibleWith(const InputSection
&isec
,
510 const Relocation
&rel
) const override
;
513 // Transitioning from long to short can create layout oscillations in
514 // certain corner cases which would prevent the layout from converging.
515 // This is similar to the handling for ARMThunk.
516 bool mayUseShortThunk
= true;
517 int64_t computeOffset() const {
518 return destination
.getVA(ctx
) - (getThunkTargetSym()->getVA(ctx
) + 4);
522 // PPC64 R12 Setup Stub
523 // When a caller that does not maintain TOC calls a target which may possibly
524 // use TOC (either non-preemptible with localentry>1 or preemptible), we need to
525 // set r12 to satisfy the requirement of the global entry point.
526 class PPC64R12SetupStub final
: public Thunk
{
528 PPC64R12SetupStub(Ctx
&ctx
, Symbol
&dest
, bool gotPlt
)
529 : Thunk(ctx
, dest
, 0), gotPlt(gotPlt
) {
532 uint32_t size() override
{ return 32; }
533 void writeTo(uint8_t *buf
) override
;
534 void addSymbols(ThunkSection
&isec
) override
;
535 bool isCompatibleWith(const InputSection
&isec
,
536 const Relocation
&rel
) const override
;
542 // A bl instruction uses a signed 24 bit offset, with an implicit 4 byte
543 // alignment. This gives a possible 26 bits of 'reach'. If the call offset is
544 // larger than that we need to emit a long-branch thunk. The target address
545 // of the callee is stored in a table to be accessed TOC-relative. Since the
546 // call must be local (a non-local call will have a PltCallStub instead) the
547 // table stores the address of the callee's local entry point. For
548 // position-independent code a corresponding relative dynamic relocation is
550 class PPC64LongBranchThunk
: public Thunk
{
552 uint32_t size() override
{ return 32; }
553 void writeTo(uint8_t *buf
) override
;
554 void addSymbols(ThunkSection
&isec
) override
;
555 bool isCompatibleWith(const InputSection
&isec
,
556 const Relocation
&rel
) const override
;
559 PPC64LongBranchThunk(Ctx
&ctx
, Symbol
&dest
, int64_t addend
)
560 : Thunk(ctx
, dest
, addend
) {}
563 class PPC64PILongBranchThunk final
: public PPC64LongBranchThunk
{
565 PPC64PILongBranchThunk(Ctx
&ctx
, Symbol
&dest
, int64_t addend
)
566 : PPC64LongBranchThunk(ctx
, dest
, addend
) {
567 assert(!dest
.isPreemptible
);
568 if (std::optional
<uint32_t> index
=
569 ctx
.in
.ppc64LongBranchTarget
->addEntry(&dest
, addend
)) {
570 ctx
.mainPart
->relaDyn
->addRelativeReloc(
571 ctx
.target
->relativeRel
, *ctx
.in
.ppc64LongBranchTarget
,
572 *index
* UINT64_C(8), dest
,
573 addend
+ getPPC64GlobalEntryToLocalEntryOffset(ctx
, dest
.stOther
),
574 ctx
.target
->symbolicRel
, R_ABS
);
579 class PPC64PDLongBranchThunk final
: public PPC64LongBranchThunk
{
581 PPC64PDLongBranchThunk(Ctx
&ctx
, Symbol
&dest
, int64_t addend
)
582 : PPC64LongBranchThunk(ctx
, dest
, addend
) {
583 ctx
.in
.ppc64LongBranchTarget
->addEntry(&dest
, addend
);
587 } // end anonymous namespace
589 Defined
*Thunk::addSymbol(StringRef name
, uint8_t type
, uint64_t value
,
590 InputSectionBase
§ion
) {
591 Defined
*d
= addSyntheticLocal(ctx
, name
, type
, value
, /*size=*/0, section
);
596 void Thunk::setOffset(uint64_t newOffset
) {
597 for (Defined
*d
: syms
)
598 d
->value
= d
->value
- offset
+ newOffset
;
602 // AArch64 Thunk base class.
603 static uint64_t getAArch64ThunkDestVA(Ctx
&ctx
, const Symbol
&s
, int64_t a
) {
604 uint64_t v
= s
.isInPlt(ctx
) ? s
.getPltVA(ctx
) : s
.getVA(ctx
, a
);
608 bool AArch64Thunk::getMayUseShortThunk() {
609 if (!mayUseShortThunk
)
611 uint64_t s
= getAArch64ThunkDestVA(ctx
, destination
, addend
);
612 uint64_t p
= getThunkTargetSym()->getVA(ctx
);
613 mayUseShortThunk
= llvm::isInt
<28>(s
- p
);
614 if (!mayUseShortThunk
)
616 return mayUseShortThunk
;
619 void AArch64Thunk::writeTo(uint8_t *buf
) {
620 if (!getMayUseShortThunk()) {
624 uint64_t s
= getAArch64ThunkDestVA(ctx
, destination
, addend
);
625 uint64_t p
= getThunkTargetSym()->getVA(ctx
);
626 write32(ctx
, buf
, 0x14000000); // b S
627 ctx
.target
->relocateNoSym(buf
, R_AARCH64_CALL26
, s
- p
);
630 bool AArch64Thunk::needsSyntheticLandingPad() {
631 // Short Thunks use a direct branch, no synthetic landing pad
633 return mayNeedLandingPad
&& !getMayUseShortThunk();
636 // AArch64 long range Thunks.
637 void AArch64ABSLongThunk::writeLong(uint8_t *buf
) {
638 const uint8_t data
[] = {
639 0x50, 0x00, 0x00, 0x58, // ldr x16, L0
640 0x00, 0x02, 0x1f, 0xd6, // br x16
641 0x00, 0x00, 0x00, 0x00, // L0: .xword S
642 0x00, 0x00, 0x00, 0x00,
644 // If mayNeedLandingPad is true then destination is an
645 // AArch64BTILandingPadThunk that defines landingPad.
646 assert(!mayNeedLandingPad
|| landingPad
!= nullptr);
647 uint64_t s
= mayNeedLandingPad
648 ? landingPad
->getVA(ctx
, 0)
649 : getAArch64ThunkDestVA(ctx
, destination
, addend
);
650 memcpy(buf
, data
, sizeof(data
));
651 ctx
.target
->relocateNoSym(buf
+ 8, R_AARCH64_ABS64
, s
);
654 void AArch64ABSLongThunk::addSymbols(ThunkSection
&isec
) {
655 addSymbol(ctx
.saver
.save("__AArch64AbsLongThunk_" + destination
.getName()),
657 addSymbol("$x", STT_NOTYPE
, 0, isec
);
659 (void)getMayUseShortThunk();
662 void AArch64ABSLongThunk::addLongMapSyms() {
663 addSymbol("$d", STT_NOTYPE
, 8, *tsec
);
666 // This Thunk has a maximum range of 4Gb, this is sufficient for all programs
667 // using the small code model, including pc-relative ones. At time of writing
668 // clang and gcc do not support the large code model for position independent
669 // code so it is safe to use this for position independent thunks without
670 // worrying about the destination being more than 4Gb away.
671 void AArch64ADRPThunk::writeLong(uint8_t *buf
) {
672 const uint8_t data
[] = {
673 0x10, 0x00, 0x00, 0x90, // adrp x16, Dest R_AARCH64_ADR_PREL_PG_HI21(Dest)
674 0x10, 0x02, 0x00, 0x91, // add x16, x16, R_AARCH64_ADD_ABS_LO12_NC(Dest)
675 0x00, 0x02, 0x1f, 0xd6, // br x16
677 // if mayNeedLandingPad is true then destination is an
678 // AArch64BTILandingPadThunk that defines landingPad.
679 assert(!mayNeedLandingPad
|| landingPad
!= nullptr);
680 uint64_t s
= mayNeedLandingPad
681 ? landingPad
->getVA(ctx
, 0)
682 : getAArch64ThunkDestVA(ctx
, destination
, addend
);
683 uint64_t p
= getThunkTargetSym()->getVA(ctx
);
684 memcpy(buf
, data
, sizeof(data
));
685 ctx
.target
->relocateNoSym(buf
, R_AARCH64_ADR_PREL_PG_HI21
,
686 getAArch64Page(s
) - getAArch64Page(p
));
687 ctx
.target
->relocateNoSym(buf
+ 4, R_AARCH64_ADD_ABS_LO12_NC
, s
);
690 void AArch64ADRPThunk::addSymbols(ThunkSection
&isec
) {
691 addSymbol(ctx
.saver
.save("__AArch64ADRPThunk_" + destination
.getName()),
693 addSymbol("$x", STT_NOTYPE
, 0, isec
);
696 void AArch64BTILandingPadThunk::addSymbols(ThunkSection
&isec
) {
697 addSymbol(ctx
.saver
.save("__AArch64BTIThunk_" + destination
.getName()),
699 addSymbol("$x", STT_NOTYPE
, 0, isec
);
702 void AArch64BTILandingPadThunk::writeTo(uint8_t *buf
) {
703 if (!getMayUseShortThunk()) {
707 write32(ctx
, buf
, 0xd503245f); // BTI c
708 // Control falls through to target in following section.
711 bool AArch64BTILandingPadThunk::getMayUseShortThunk() {
712 if (!mayUseShortThunk
)
714 // If the target is the following instruction then we can fall
715 // through without the indirect branch.
716 uint64_t s
= destination
.getVA(ctx
, addend
);
717 uint64_t p
= getThunkTargetSym()->getVA(ctx
);
718 // This function is called before addresses are stable. We need to
719 // work out the range from the thunk to the next section but the
720 // address of the start of the next section depends on the size of
721 // the thunks in the previous pass. s - p + offset == 0 represents
722 // the first pass where the Thunk and following section are assigned
723 // the same offset. s - p <= 4 is the last Thunk in the Thunk
725 mayUseShortThunk
= (s
- p
+ offset
== 0 || s
- p
<= 4);
726 return mayUseShortThunk
;
729 void AArch64BTILandingPadThunk::writeLong(uint8_t *buf
) {
730 uint64_t s
= destination
.getVA(ctx
, addend
);
731 uint64_t p
= getThunkTargetSym()->getVA(ctx
) + 4;
732 write32(ctx
, buf
, 0xd503245f); // BTI c
733 write32(ctx
, buf
+ 4, 0x14000000); // B S
734 ctx
.target
->relocateNoSym(buf
+ 4, R_AARCH64_CALL26
, s
- p
);
738 static uint64_t getARMThunkDestVA(Ctx
&ctx
, const Symbol
&s
) {
739 uint64_t v
= s
.isInPlt(ctx
) ? s
.getPltVA(ctx
) : s
.getVA(ctx
);
740 return SignExtend64
<32>(v
);
743 // This function returns true if the target is not Thumb and is within 2^26, and
744 // it has not previously returned false (see comment for mayUseShortThunk).
745 bool ARMThunk::getMayUseShortThunk() {
746 if (!mayUseShortThunk
)
748 uint64_t s
= getARMThunkDestVA(ctx
, destination
);
750 mayUseShortThunk
= false;
754 uint64_t p
= getThunkTargetSym()->getVA(ctx
);
755 int64_t offset
= s
- p
- 8;
756 mayUseShortThunk
= llvm::isInt
<26>(offset
);
757 if (!mayUseShortThunk
)
759 return mayUseShortThunk
;
762 void ARMThunk::writeTo(uint8_t *buf
) {
763 if (!getMayUseShortThunk()) {
768 uint64_t s
= getARMThunkDestVA(ctx
, destination
);
769 uint64_t p
= getThunkTargetSym()->getVA(ctx
);
770 int64_t offset
= s
- p
- 8;
771 write32(ctx
, buf
, 0xea000000); // b S
772 ctx
.target
->relocateNoSym(buf
, R_ARM_JUMP24
, offset
);
775 bool ARMThunk::isCompatibleWith(const InputSection
&isec
,
776 const Relocation
&rel
) const {
777 // v4T does not have BLX, so also deny R_ARM_THM_CALL
778 if (!ctx
.arg
.armHasBlx
&& rel
.type
== R_ARM_THM_CALL
)
781 // Thumb branch relocations can't use BLX
782 return rel
.type
!= R_ARM_THM_JUMP19
&& rel
.type
!= R_ARM_THM_JUMP24
;
785 // This function returns true if:
786 // the target is Thumb
787 // && is within branch range
788 // && this function has not previously returned false
789 // (see comment for mayUseShortThunk)
790 // && the arch supports Thumb branch range extension.
791 bool ThumbThunk::getMayUseShortThunk() {
792 if (!mayUseShortThunk
)
794 uint64_t s
= getARMThunkDestVA(ctx
, destination
);
795 // To use a short thunk the destination must be Thumb and the target must
796 // have the wide branch instruction B.w. This instruction is included when
797 // Thumb 2 is present, or in v8-M (and above) baseline architectures.
798 // armJ1J2BranchEncoding is available in all architectures with a profile and
799 // the one v6 CPU that implements Thumb 2 (Arm1156t2-s).
800 // Movt and Movw instructions require Thumb 2 or v8-M baseline.
801 if ((s
& 1) == 0 || !ctx
.arg
.armJ1J2BranchEncoding
||
802 !ctx
.arg
.armHasMovtMovw
) {
803 mayUseShortThunk
= false;
807 uint64_t p
= getThunkTargetSym()->getVA(ctx
) & ~1;
808 int64_t offset
= s
- p
- 4;
809 mayUseShortThunk
= llvm::isInt
<25>(offset
);
810 if (!mayUseShortThunk
)
812 return mayUseShortThunk
;
815 void ThumbThunk::writeTo(uint8_t *buf
) {
816 if (!getMayUseShortThunk()) {
821 uint64_t s
= getARMThunkDestVA(ctx
, destination
);
822 uint64_t p
= getThunkTargetSym()->getVA(ctx
);
823 int64_t offset
= s
- p
- 4;
824 write16(ctx
, buf
+ 0, 0xf000); // b.w S
825 write16(ctx
, buf
+ 2, 0xb000);
826 ctx
.target
->relocateNoSym(buf
, R_ARM_THM_JUMP24
, offset
);
829 bool ThumbThunk::isCompatibleWith(const InputSection
&isec
,
830 const Relocation
&rel
) const {
831 // v4T does not have BLX, so also deny R_ARM_CALL
832 if (!ctx
.arg
.armHasBlx
&& rel
.type
== R_ARM_CALL
)
835 // ARM branch relocations can't use BLX
836 return rel
.type
!= R_ARM_JUMP24
&& rel
.type
!= R_ARM_PC24
&& rel
.type
!= R_ARM_PLT32
;
839 void ARMV7ABSLongThunk::writeLong(uint8_t *buf
) {
840 write32(ctx
, buf
+ 0, 0xe300c000); // movw ip,:lower16:S
841 write32(ctx
, buf
+ 4, 0xe340c000); // movt ip,:upper16:S
842 write32(ctx
, buf
+ 8, 0xe12fff1c); // bx ip
843 uint64_t s
= getARMThunkDestVA(ctx
, destination
);
844 ctx
.target
->relocateNoSym(buf
, R_ARM_MOVW_ABS_NC
, s
);
845 ctx
.target
->relocateNoSym(buf
+ 4, R_ARM_MOVT_ABS
, s
);
848 void ARMV7ABSLongThunk::addSymbols(ThunkSection
&isec
) {
849 addSymbol(ctx
.saver
.save("__ARMv7ABSLongThunk_" + destination
.getName()),
851 addSymbol("$a", STT_NOTYPE
, 0, isec
);
854 void ThumbV7ABSLongThunk::writeLong(uint8_t *buf
) {
855 write16(ctx
, buf
+ 0, 0xf240); // movw ip, :lower16:S
856 write16(ctx
, buf
+ 2, 0x0c00);
857 write16(ctx
, buf
+ 4, 0xf2c0); // movt ip, :upper16:S
858 write16(ctx
, buf
+ 6, 0x0c00);
859 write16(ctx
, buf
+ 8, 0x4760); // bx ip
860 uint64_t s
= getARMThunkDestVA(ctx
, destination
);
861 ctx
.target
->relocateNoSym(buf
, R_ARM_THM_MOVW_ABS_NC
, s
);
862 ctx
.target
->relocateNoSym(buf
+ 4, R_ARM_THM_MOVT_ABS
, s
);
865 void ThumbV7ABSLongThunk::addSymbols(ThunkSection
&isec
) {
866 addSymbol(ctx
.saver
.save("__Thumbv7ABSLongThunk_" + destination
.getName()),
868 addSymbol("$t", STT_NOTYPE
, 0, isec
);
871 void ARMV7PILongThunk::writeLong(uint8_t *buf
) {
872 write32(ctx
, buf
+ 0,
873 0xe30fcff0); // P: movw ip,:lower16:S - (P + (L1-P) + 8)
874 write32(ctx
, buf
+ 4,
875 0xe340c000); // movt ip,:upper16:S - (P + (L1-P) + 8)
876 write32(ctx
, buf
+ 8, 0xe08cc00f); // L1: add ip, ip, pc
877 write32(ctx
, buf
+ 12, 0xe12fff1c); // bx ip
878 uint64_t s
= getARMThunkDestVA(ctx
, destination
);
879 uint64_t p
= getThunkTargetSym()->getVA(ctx
);
880 int64_t offset
= s
- p
- 16;
881 ctx
.target
->relocateNoSym(buf
, R_ARM_MOVW_PREL_NC
, offset
);
882 ctx
.target
->relocateNoSym(buf
+ 4, R_ARM_MOVT_PREL
, offset
);
885 void ARMV7PILongThunk::addSymbols(ThunkSection
&isec
) {
886 addSymbol(ctx
.saver
.save("__ARMV7PILongThunk_" + destination
.getName()),
888 addSymbol("$a", STT_NOTYPE
, 0, isec
);
891 void ThumbV7PILongThunk::writeLong(uint8_t *buf
) {
892 write16(ctx
, buf
+ 0, 0xf64f); // P: movw ip,:lower16:S - (P + (L1-P) + 4)
893 write16(ctx
, buf
+ 2, 0x7cf4);
894 write16(ctx
, buf
+ 4, 0xf2c0); // movt ip,:upper16:S - (P + (L1-P) + 4)
895 write16(ctx
, buf
+ 6, 0x0c00);
896 write16(ctx
, buf
+ 8, 0x44fc); // L1: add ip, pc
897 write16(ctx
, buf
+ 10, 0x4760); // bx ip
898 uint64_t s
= getARMThunkDestVA(ctx
, destination
);
899 uint64_t p
= getThunkTargetSym()->getVA(ctx
) & ~0x1;
900 int64_t offset
= s
- p
- 12;
901 ctx
.target
->relocateNoSym(buf
, R_ARM_THM_MOVW_PREL_NC
, offset
);
902 ctx
.target
->relocateNoSym(buf
+ 4, R_ARM_THM_MOVT_PREL
, offset
);
905 void ThumbV7PILongThunk::addSymbols(ThunkSection
&isec
) {
906 addSymbol(ctx
.saver
.save("__ThumbV7PILongThunk_" + destination
.getName()),
908 addSymbol("$t", STT_NOTYPE
, 0, isec
);
911 void ThumbV6MABSLongThunk::writeLong(uint8_t *buf
) {
912 // Most Thumb instructions cannot access the high registers r8 - r15. As the
913 // only register we can corrupt is r12 we must instead spill a low register
914 // to the stack to use as a scratch register. We push r1 even though we
915 // don't need to get some space to use for the return address.
916 write16(ctx
, buf
+ 0, 0xb403); // push {r0, r1} ; Obtain scratch registers
917 write16(ctx
, buf
+ 2, 0x4801); // ldr r0, [pc, #4] ; L1
918 write16(ctx
, buf
+ 4, 0x9001); // str r0, [sp, #4] ; SP + 4 = S
919 write16(ctx
, buf
+ 6, 0xbd01); // pop {r0, pc} ; restore r0 and branch to dest
920 write32(ctx
, buf
+ 8, 0x00000000); // L1: .word S
921 uint64_t s
= getARMThunkDestVA(ctx
, destination
);
922 ctx
.target
->relocateNoSym(buf
+ 8, R_ARM_ABS32
, s
);
925 void ThumbV6MABSLongThunk::addSymbols(ThunkSection
&isec
) {
926 addSymbol(ctx
.saver
.save("__Thumbv6MABSLongThunk_" + destination
.getName()),
928 addSymbol("$t", STT_NOTYPE
, 0, isec
);
930 (void)getMayUseShortThunk();
933 void ThumbV6MABSLongThunk::addLongMapSyms() {
934 addSymbol("$d", STT_NOTYPE
, 8, *tsec
);
937 void ThumbV6MABSXOLongThunk::writeLong(uint8_t *buf
) {
938 // Most Thumb instructions cannot access the high registers r8 - r15. As the
939 // only register we can corrupt is r12 we must instead spill a low register
940 // to the stack to use as a scratch register. We push r1 even though we
941 // don't need to get some space to use for the return address.
942 write16(ctx
, buf
+ 0, 0xb403); // push {r0, r1} ; Obtain scratch registers
943 write16(ctx
, buf
+ 2, 0x2000); // movs r0, :upper8_15:S
944 write16(ctx
, buf
+ 4, 0x0200); // lsls r0, r0, #8
945 write16(ctx
, buf
+ 6, 0x3000); // adds r0, :upper0_7:S
946 write16(ctx
, buf
+ 8, 0x0200); // lsls r0, r0, #8
947 write16(ctx
, buf
+ 10, 0x3000); // adds r0, :lower8_15:S
948 write16(ctx
, buf
+ 12, 0x0200); // lsls r0, r0, #8
949 write16(ctx
, buf
+ 14, 0x3000); // adds r0, :lower0_7:S
950 write16(ctx
, buf
+ 16, 0x9001); // str r0, [sp, #4] ; SP + 4 = S
951 write16(ctx
, buf
+ 18,
952 0xbd01); // pop {r0, pc} ; restore r0 and branch to dest
953 uint64_t s
= getARMThunkDestVA(ctx
, destination
);
954 ctx
.target
->relocateNoSym(buf
+ 2, R_ARM_THM_ALU_ABS_G3
, s
);
955 ctx
.target
->relocateNoSym(buf
+ 6, R_ARM_THM_ALU_ABS_G2_NC
, s
);
956 ctx
.target
->relocateNoSym(buf
+ 10, R_ARM_THM_ALU_ABS_G1_NC
, s
);
957 ctx
.target
->relocateNoSym(buf
+ 14, R_ARM_THM_ALU_ABS_G0_NC
, s
);
960 void ThumbV6MABSXOLongThunk::addSymbols(ThunkSection
&isec
) {
961 addSymbol(ctx
.saver
.save("__Thumbv6MABSXOLongThunk_" + destination
.getName()),
963 addSymbol("$t", STT_NOTYPE
, 0, isec
);
966 void ThumbV6MPILongThunk::writeLong(uint8_t *buf
) {
967 // Most Thumb instructions cannot access the high registers r8 - r15. As the
968 // only register we can corrupt is ip (r12) we must instead spill a low
969 // register to the stack to use as a scratch register.
970 write16(ctx
, buf
+ 0,
971 0xb401); // P: push {r0} ; Obtain scratch register
972 write16(ctx
, buf
+ 2, 0x4802); // ldr r0, [pc, #8] ; L2
973 write16(ctx
, buf
+ 4, 0x4684); // mov ip, r0 ; high to low register
974 write16(ctx
, buf
+ 6,
975 0xbc01); // pop {r0} ; restore scratch register
976 write16(ctx
, buf
+ 8, 0x44e7); // L1: add pc, ip ; transfer control
977 write16(ctx
, buf
+ 10,
978 0x46c0); // nop ; pad to 4-byte boundary
979 write32(ctx
, buf
+ 12, 0x00000000); // L2: .word S - (P + (L1 - P) + 4)
980 uint64_t s
= getARMThunkDestVA(ctx
, destination
);
981 uint64_t p
= getThunkTargetSym()->getVA(ctx
) & ~0x1;
982 ctx
.target
->relocateNoSym(buf
+ 12, R_ARM_REL32
, s
- p
- 12);
985 void ThumbV6MPILongThunk::addSymbols(ThunkSection
&isec
) {
986 addSymbol(ctx
.saver
.save("__Thumbv6MPILongThunk_" + destination
.getName()),
988 addSymbol("$t", STT_NOTYPE
, 0, isec
);
990 (void)getMayUseShortThunk();
993 void ThumbV6MPILongThunk::addLongMapSyms() {
994 addSymbol("$d", STT_NOTYPE
, 12, *tsec
);
997 void ARMV5LongLdrPcThunk::writeLong(uint8_t *buf
) {
998 write32(ctx
, buf
+ 0, 0xe51ff004); // ldr pc, [pc,#-4] ; L1
999 write32(ctx
, buf
+ 4, 0x00000000); // L1: .word S
1000 ctx
.target
->relocateNoSym(buf
+ 4, R_ARM_ABS32
,
1001 getARMThunkDestVA(ctx
, destination
));
1004 void ARMV5LongLdrPcThunk::addSymbols(ThunkSection
&isec
) {
1005 addSymbol(ctx
.saver
.save("__ARMv5LongLdrPcThunk_" + destination
.getName()),
1007 addSymbol("$a", STT_NOTYPE
, 0, isec
);
1009 (void)getMayUseShortThunk();
1012 void ARMV5LongLdrPcThunk::addLongMapSyms() {
1013 addSymbol("$d", STT_NOTYPE
, 4, *tsec
);
1016 void ARMV4ABSLongBXThunk::writeLong(uint8_t *buf
) {
1017 write32(ctx
, buf
+ 0, 0xe59fc000); // ldr r12, [pc] ; L1
1018 write32(ctx
, buf
+ 4, 0xe12fff1c); // bx r12
1019 write32(ctx
, buf
+ 8, 0x00000000); // L1: .word S
1020 ctx
.target
->relocateNoSym(buf
+ 8, R_ARM_ABS32
,
1021 getARMThunkDestVA(ctx
, destination
));
1024 void ARMV4ABSLongBXThunk::addSymbols(ThunkSection
&isec
) {
1025 addSymbol(ctx
.saver
.save("__ARMv4ABSLongBXThunk_" + destination
.getName()),
1027 addSymbol("$a", STT_NOTYPE
, 0, isec
);
1029 (void)getMayUseShortThunk();
1032 void ARMV4ABSLongBXThunk::addLongMapSyms() {
1033 addSymbol("$d", STT_NOTYPE
, 8, *tsec
);
1036 void ThumbV4ABSLongBXThunk::writeLong(uint8_t *buf
) {
1037 write16(ctx
, buf
+ 0, 0x4778); // bx pc
1038 write16(ctx
, buf
+ 2,
1039 0xe7fd); // b #-6 ; Arm recommended sequence to follow bx pc
1040 write32(ctx
, buf
+ 4, 0xe51ff004); // ldr pc, [pc, #-4] ; L1
1041 write32(ctx
, buf
+ 8, 0x00000000); // L1: .word S
1042 ctx
.target
->relocateNoSym(buf
+ 8, R_ARM_ABS32
,
1043 getARMThunkDestVA(ctx
, destination
));
1046 void ThumbV4ABSLongBXThunk::addSymbols(ThunkSection
&isec
) {
1047 addSymbol(ctx
.saver
.save("__Thumbv4ABSLongBXThunk_" + destination
.getName()),
1049 addSymbol("$t", STT_NOTYPE
, 0, isec
);
1051 (void)getMayUseShortThunk();
1054 void ThumbV4ABSLongBXThunk::addLongMapSyms() {
1055 addSymbol("$a", STT_NOTYPE
, 4, *tsec
);
1056 addSymbol("$d", STT_NOTYPE
, 8, *tsec
);
1059 void ThumbV4ABSLongThunk::writeLong(uint8_t *buf
) {
1060 write16(ctx
, buf
+ 0, 0x4778); // bx pc
1061 write16(ctx
, buf
+ 2,
1062 0xe7fd); // b #-6 ; Arm recommended sequence to follow bx pc
1063 write32(ctx
, buf
+ 4, 0xe59fc000); // ldr r12, [pc] ; L1
1064 write32(ctx
, buf
+ 8, 0xe12fff1c); // bx r12
1065 write32(ctx
, buf
+ 12, 0x00000000); // L1: .word S
1066 ctx
.target
->relocateNoSym(buf
+ 12, R_ARM_ABS32
,
1067 getARMThunkDestVA(ctx
, destination
));
1070 void ThumbV4ABSLongThunk::addSymbols(ThunkSection
&isec
) {
1071 addSymbol(ctx
.saver
.save("__Thumbv4ABSLongThunk_" + destination
.getName()),
1073 addSymbol("$t", STT_NOTYPE
, 0, isec
);
1075 (void)getMayUseShortThunk();
1078 void ThumbV4ABSLongThunk::addLongMapSyms() {
1079 addSymbol("$a", STT_NOTYPE
, 4, *tsec
);
1080 addSymbol("$d", STT_NOTYPE
, 12, *tsec
);
1083 void ARMV4PILongBXThunk::writeLong(uint8_t *buf
) {
1084 write32(ctx
, buf
+ 0, 0xe59fc004); // P: ldr ip, [pc,#4] ; L2
1085 write32(ctx
, buf
+ 4, 0xe08fc00c); // L1: add ip, pc, ip
1086 write32(ctx
, buf
+ 8, 0xe12fff1c); // bx ip
1087 write32(ctx
, buf
+ 12, 0x00000000); // L2: .word S - (P + (L1 - P) + 8)
1088 uint64_t s
= getARMThunkDestVA(ctx
, destination
);
1089 uint64_t p
= getThunkTargetSym()->getVA(ctx
) & ~0x1;
1090 ctx
.target
->relocateNoSym(buf
+ 12, R_ARM_REL32
, s
- p
- 12);
1093 void ARMV4PILongBXThunk::addSymbols(ThunkSection
&isec
) {
1094 addSymbol(ctx
.saver
.save("__ARMv4PILongBXThunk_" + destination
.getName()),
1096 addSymbol("$a", STT_NOTYPE
, 0, isec
);
1098 (void)getMayUseShortThunk();
1101 void ARMV4PILongBXThunk::addLongMapSyms() {
1102 addSymbol("$d", STT_NOTYPE
, 12, *tsec
);
1105 void ARMV4PILongThunk::writeLong(uint8_t *buf
) {
1106 write32(ctx
, buf
+ 0, 0xe59fc000); // P: ldr ip, [pc] ; L2
1107 write32(ctx
, buf
+ 4, 0xe08ff00c); // L1: add pc, pc, r12
1108 write32(ctx
, buf
+ 8, 0x00000000); // L2: .word S - (P + (L1 - P) + 8)
1109 uint64_t s
= getARMThunkDestVA(ctx
, destination
);
1110 uint64_t p
= getThunkTargetSym()->getVA(ctx
) & ~0x1;
1111 ctx
.target
->relocateNoSym(buf
+ 8, R_ARM_REL32
, s
- p
- 12);
1114 void ARMV4PILongThunk::addSymbols(ThunkSection
&isec
) {
1115 addSymbol(ctx
.saver
.save("__ARMv4PILongThunk_" + destination
.getName()),
1117 addSymbol("$a", STT_NOTYPE
, 0, isec
);
1119 (void)getMayUseShortThunk();
1122 void ARMV4PILongThunk::addLongMapSyms() {
1123 addSymbol("$d", STT_NOTYPE
, 8, *tsec
);
1126 void ThumbV4PILongBXThunk::writeLong(uint8_t *buf
) {
1127 write16(ctx
, buf
+ 0, 0x4778); // P: bx pc
1128 write16(ctx
, buf
+ 2,
1129 0xe7fd); // b #-6 ; Arm recommended sequence to follow bx pc
1130 write32(ctx
, buf
+ 4, 0xe59fc000); // ldr r12, [pc] ; L2
1131 write32(ctx
, buf
+ 8, 0xe08cf00f); // L1: add pc, r12, pc
1132 write32(ctx
, buf
+ 12, 0x00000000); // L2: .word S - (P + (L1 - P) + 8)
1133 uint64_t s
= getARMThunkDestVA(ctx
, destination
);
1134 uint64_t p
= getThunkTargetSym()->getVA(ctx
) & ~0x1;
1135 ctx
.target
->relocateNoSym(buf
+ 12, R_ARM_REL32
, s
- p
- 16);
1138 void ThumbV4PILongBXThunk::addSymbols(ThunkSection
&isec
) {
1139 addSymbol(ctx
.saver
.save("__Thumbv4PILongBXThunk_" + destination
.getName()),
1141 addSymbol("$t", STT_NOTYPE
, 0, isec
);
1143 (void)getMayUseShortThunk();
1146 void ThumbV4PILongBXThunk::addLongMapSyms() {
1147 addSymbol("$a", STT_NOTYPE
, 4, *tsec
);
1148 addSymbol("$d", STT_NOTYPE
, 12, *tsec
);
1151 void ThumbV4PILongThunk::writeLong(uint8_t *buf
) {
1152 write16(ctx
, buf
+ 0, 0x4778); // P: bx pc
1153 write16(ctx
, buf
+ 2,
1154 0xe7fd); // b #-6 ; Arm recommended sequence to follow bx pc
1155 write32(ctx
, buf
+ 4, 0xe59fc004); // ldr ip, [pc,#4] ; L2
1156 write32(ctx
, buf
+ 8, 0xe08fc00c); // L1: add ip, pc, ip
1157 write32(ctx
, buf
+ 12, 0xe12fff1c); // bx ip
1158 write32(ctx
, buf
+ 16, 0x00000000); // L2: .word S - (P + (L1 - P) + 8)
1159 uint64_t s
= getARMThunkDestVA(ctx
, destination
);
1160 uint64_t p
= getThunkTargetSym()->getVA(ctx
) & ~0x1;
1161 ctx
.target
->relocateNoSym(buf
+ 16, R_ARM_REL32
, s
- p
- 16);
1164 void ThumbV4PILongThunk::addSymbols(ThunkSection
&isec
) {
1165 addSymbol(ctx
.saver
.save("__Thumbv4PILongThunk_" + destination
.getName()),
1167 addSymbol("$t", STT_NOTYPE
, 0, isec
);
1169 (void)getMayUseShortThunk();
1172 void ThumbV4PILongThunk::addLongMapSyms() {
1173 addSymbol("$a", STT_NOTYPE
, 4, *tsec
);
1174 addSymbol("$d", STT_NOTYPE
, 16, *tsec
);
1177 // Use the long jump which covers a range up to 8MiB.
1178 void AVRThunk::writeTo(uint8_t *buf
) {
1179 write32(ctx
, buf
, 0x940c); // jmp func
1180 ctx
.target
->relocateNoSym(buf
, R_AVR_CALL
, destination
.getVA(ctx
));
1183 void AVRThunk::addSymbols(ThunkSection
&isec
) {
1184 addSymbol(ctx
.saver
.save("__AVRThunk_" + destination
.getName()), STT_FUNC
, 0,
1188 // Write MIPS LA25 thunk code to call PIC function from the non-PIC one.
1189 void MipsThunk::writeTo(uint8_t *buf
) {
1190 uint64_t s
= destination
.getVA(ctx
);
1191 write32(ctx
, buf
, 0x3c190000); // lui $25, %hi(func)
1192 write32(ctx
, buf
+ 4, 0x08000000 | (s
>> 2)); // j func
1193 write32(ctx
, buf
+ 8, 0x27390000); // addiu $25, $25, %lo(func)
1194 write32(ctx
, buf
+ 12, 0x00000000); // nop
1195 ctx
.target
->relocateNoSym(buf
, R_MIPS_HI16
, s
);
1196 ctx
.target
->relocateNoSym(buf
+ 8, R_MIPS_LO16
, s
);
1199 void MipsThunk::addSymbols(ThunkSection
&isec
) {
1200 addSymbol(ctx
.saver
.save("__LA25Thunk_" + destination
.getName()), STT_FUNC
, 0,
1204 InputSection
*MipsThunk::getTargetInputSection() const {
1205 auto &dr
= cast
<Defined
>(destination
);
1206 return dyn_cast
<InputSection
>(dr
.section
);
1209 // Write microMIPS R2-R5 LA25 thunk code
1210 // to call PIC function from the non-PIC one.
1211 void MicroMipsThunk::writeTo(uint8_t *buf
) {
1212 uint64_t s
= destination
.getVA(ctx
);
1213 write16(ctx
, buf
, 0x41b9); // lui $25, %hi(func)
1214 write16(ctx
, buf
+ 4, 0xd400); // j func
1215 write16(ctx
, buf
+ 8, 0x3339); // addiu $25, $25, %lo(func)
1216 write16(ctx
, buf
+ 12, 0x0c00); // nop
1217 ctx
.target
->relocateNoSym(buf
, R_MICROMIPS_HI16
, s
);
1218 ctx
.target
->relocateNoSym(buf
+ 4, R_MICROMIPS_26_S1
, s
);
1219 ctx
.target
->relocateNoSym(buf
+ 8, R_MICROMIPS_LO16
, s
);
1222 void MicroMipsThunk::addSymbols(ThunkSection
&isec
) {
1224 addSymbol(ctx
.saver
.save("__microLA25Thunk_" + destination
.getName()),
1226 d
->stOther
|= STO_MIPS_MICROMIPS
;
1229 InputSection
*MicroMipsThunk::getTargetInputSection() const {
1230 auto &dr
= cast
<Defined
>(destination
);
1231 return dyn_cast
<InputSection
>(dr
.section
);
1234 // Write microMIPS R6 LA25 thunk code
1235 // to call PIC function from the non-PIC one.
1236 void MicroMipsR6Thunk::writeTo(uint8_t *buf
) {
1237 uint64_t s
= destination
.getVA(ctx
);
1238 uint64_t p
= getThunkTargetSym()->getVA(ctx
);
1239 write16(ctx
, buf
, 0x1320); // lui $25, %hi(func)
1240 write16(ctx
, buf
+ 4, 0x3339); // addiu $25, $25, %lo(func)
1241 write16(ctx
, buf
+ 8, 0x9400); // bc func
1242 ctx
.target
->relocateNoSym(buf
, R_MICROMIPS_HI16
, s
);
1243 ctx
.target
->relocateNoSym(buf
+ 4, R_MICROMIPS_LO16
, s
);
1244 ctx
.target
->relocateNoSym(buf
+ 8, R_MICROMIPS_PC26_S1
, s
- p
- 12);
1247 void MicroMipsR6Thunk::addSymbols(ThunkSection
&isec
) {
1249 addSymbol(ctx
.saver
.save("__microLA25Thunk_" + destination
.getName()),
1251 d
->stOther
|= STO_MIPS_MICROMIPS
;
1254 InputSection
*MicroMipsR6Thunk::getTargetInputSection() const {
1255 auto &dr
= cast
<Defined
>(destination
);
1256 return dyn_cast
<InputSection
>(dr
.section
);
1259 void elf::writePPC32PltCallStub(Ctx
&ctx
, uint8_t *buf
, uint64_t gotPltVA
,
1260 const InputFile
*file
, int64_t addend
) {
1261 if (!ctx
.arg
.isPic
) {
1262 write32(ctx
, buf
+ 0, 0x3d600000 | (gotPltVA
+ 0x8000) >> 16); // lis r11,ha
1263 write32(ctx
, buf
+ 4, 0x816b0000 | (uint16_t)gotPltVA
); // lwz r11,l(r11)
1264 write32(ctx
, buf
+ 8, 0x7d6903a6); // mtctr r11
1265 write32(ctx
, buf
+ 12, 0x4e800420); // bctr
1269 if (addend
>= 0x8000) {
1270 // The stub loads an address relative to r30 (.got2+Addend). Addend is
1271 // almost always 0x8000. The address of .got2 is different in another object
1272 // file, so a stub cannot be shared.
1274 (ctx
.in
.ppc32Got2
->getParent()->getVA() +
1275 (file
->ppc32Got2
? file
->ppc32Got2
->outSecOff
: 0) + addend
);
1277 // The stub loads an address relative to _GLOBAL_OFFSET_TABLE_ (which is
1278 // currently the address of .got).
1279 offset
= gotPltVA
- ctx
.in
.got
->getVA();
1281 uint16_t ha
= (offset
+ 0x8000) >> 16, l
= (uint16_t)offset
;
1283 write32(ctx
, buf
+ 0, 0x817e0000 | l
); // lwz r11,l(r30)
1284 write32(ctx
, buf
+ 4, 0x7d6903a6); // mtctr r11
1285 write32(ctx
, buf
+ 8, 0x4e800420); // bctr
1286 write32(ctx
, buf
+ 12, 0x60000000); // nop
1288 write32(ctx
, buf
+ 0, 0x3d7e0000 | ha
); // addis r11,r30,ha
1289 write32(ctx
, buf
+ 4, 0x816b0000 | l
); // lwz r11,l(r11)
1290 write32(ctx
, buf
+ 8, 0x7d6903a6); // mtctr r11
1291 write32(ctx
, buf
+ 12, 0x4e800420); // bctr
1295 void PPC32PltCallStub::writeTo(uint8_t *buf
) {
1296 writePPC32PltCallStub(ctx
, buf
, destination
.getGotPltVA(ctx
), file
, addend
);
1299 void PPC32PltCallStub::addSymbols(ThunkSection
&isec
) {
1301 raw_string_ostream
os(buf
);
1302 os
<< format_hex_no_prefix(addend
, 8);
1304 os
<< ".plt_call32.";
1305 else if (addend
>= 0x8000)
1306 os
<< ".got2.plt_pic32.";
1308 os
<< ".plt_pic32.";
1309 os
<< destination
.getName();
1310 addSymbol(ctx
.saver
.save(buf
), STT_FUNC
, 0, isec
);
1313 bool PPC32PltCallStub::isCompatibleWith(const InputSection
&isec
,
1314 const Relocation
&rel
) const {
1315 return !ctx
.arg
.isPic
|| (isec
.file
== file
&& rel
.addend
== addend
);
1318 void PPC32LongThunk::addSymbols(ThunkSection
&isec
) {
1319 addSymbol(ctx
.saver
.save("__LongThunk_" + destination
.getName()), STT_FUNC
, 0,
1323 void PPC32LongThunk::writeTo(uint8_t *buf
) {
1324 auto ha
= [](uint32_t v
) -> uint16_t { return (v
+ 0x8000) >> 16; };
1325 auto lo
= [](uint32_t v
) -> uint16_t { return v
; };
1326 uint32_t d
= destination
.getVA(ctx
, addend
);
1327 if (ctx
.arg
.isPic
) {
1328 uint32_t off
= d
- (getThunkTargetSym()->getVA(ctx
) + 8);
1329 write32(ctx
, buf
+ 0, 0x7c0802a6); // mflr r12,0
1330 write32(ctx
, buf
+ 4, 0x429f0005); // bcl r20,r31,.+4
1331 write32(ctx
, buf
+ 8, 0x7d8802a6); // mtctr r12
1332 write32(ctx
, buf
+ 12, 0x3d8c0000 | ha(off
)); // addis r12,r12,off@ha
1333 write32(ctx
, buf
+ 16, 0x398c0000 | lo(off
)); // addi r12,r12,off@l
1334 write32(ctx
, buf
+ 20, 0x7c0803a6); // mtlr r0
1337 write32(ctx
, buf
+ 0, 0x3d800000 | ha(d
)); // lis r12,d@ha
1338 write32(ctx
, buf
+ 4, 0x398c0000 | lo(d
)); // addi r12,r12,d@l
1341 write32(ctx
, buf
+ 0, 0x7d8903a6); // mtctr r12
1342 write32(ctx
, buf
+ 4, 0x4e800420); // bctr
1345 void elf::writePPC64LoadAndBranch(Ctx
&ctx
, uint8_t *buf
, int64_t offset
) {
1346 uint16_t offHa
= (offset
+ 0x8000) >> 16;
1347 uint16_t offLo
= offset
& 0xffff;
1349 write32(ctx
, buf
+ 0, 0x3d820000 | offHa
); // addis r12, r2, OffHa
1350 write32(ctx
, buf
+ 4, 0xe98c0000 | offLo
); // ld r12, OffLo(r12)
1351 write32(ctx
, buf
+ 8, 0x7d8903a6); // mtctr r12
1352 write32(ctx
, buf
+ 12, 0x4e800420); // bctr
1355 void PPC64PltCallStub::writeTo(uint8_t *buf
) {
1356 int64_t offset
= destination
.getGotPltVA(ctx
) - getPPC64TocBase(ctx
);
1357 // Save the TOC pointer to the save-slot reserved in the call frame.
1358 write32(ctx
, buf
+ 0, 0xf8410018); // std r2,24(r1)
1359 writePPC64LoadAndBranch(ctx
, buf
+ 4, offset
);
1362 void PPC64PltCallStub::addSymbols(ThunkSection
&isec
) {
1363 Defined
*s
= addSymbol(ctx
.saver
.save("__plt_" + destination
.getName()),
1365 s
->setNeedsTocRestore(true);
1366 s
->file
= destination
.file
;
1369 bool PPC64PltCallStub::isCompatibleWith(const InputSection
&isec
,
1370 const Relocation
&rel
) const {
1371 return rel
.type
== R_PPC64_REL24
|| rel
.type
== R_PPC64_REL14
;
1374 void PPC64R2SaveStub::writeTo(uint8_t *buf
) {
1375 const int64_t offset
= computeOffset();
1376 write32(ctx
, buf
+ 0, 0xf8410018); // std r2,24(r1)
1377 // The branch offset needs to fit in 26 bits.
1378 if (getMayUseShortThunk()) {
1379 write32(ctx
, buf
+ 4, 0x48000000 | (offset
& 0x03fffffc)); // b <offset>
1380 } else if (isInt
<34>(offset
)) {
1382 uint64_t tocOffset
= destination
.getVA(ctx
) - getPPC64TocBase(ctx
);
1383 if (tocOffset
>> 16 > 0) {
1384 const uint64_t addi
= ADDI_R12_TO_R12_NO_DISP
| (tocOffset
& 0xffff);
1385 const uint64_t addis
=
1386 ADDIS_R12_TO_R2_NO_DISP
| ((tocOffset
>> 16) & 0xffff);
1387 write32(ctx
, buf
+ 4, addis
); // addis r12, r2 , top of offset
1388 write32(ctx
, buf
+ 8, addi
); // addi r12, r12, bottom of offset
1389 nextInstOffset
= 12;
1391 const uint64_t addi
= ADDI_R12_TO_R2_NO_DISP
| (tocOffset
& 0xffff);
1392 write32(ctx
, buf
+ 4, addi
); // addi r12, r2, offset
1395 write32(ctx
, buf
+ nextInstOffset
, MTCTR_R12
); // mtctr r12
1396 write32(ctx
, buf
+ nextInstOffset
+ 4, BCTR
); // bctr
1398 ctx
.in
.ppc64LongBranchTarget
->addEntry(&destination
, addend
);
1399 const int64_t offsetFromTOC
=
1400 ctx
.in
.ppc64LongBranchTarget
->getEntryVA(&destination
, addend
) -
1401 getPPC64TocBase(ctx
);
1402 writePPC64LoadAndBranch(ctx
, buf
+ 4, offsetFromTOC
);
1406 void PPC64R2SaveStub::addSymbols(ThunkSection
&isec
) {
1407 Defined
*s
= addSymbol(ctx
.saver
.save("__toc_save_" + destination
.getName()),
1409 s
->setNeedsTocRestore(true);
1412 bool PPC64R2SaveStub::isCompatibleWith(const InputSection
&isec
,
1413 const Relocation
&rel
) const {
1414 return rel
.type
== R_PPC64_REL24
|| rel
.type
== R_PPC64_REL14
;
1417 void PPC64R12SetupStub::writeTo(uint8_t *buf
) {
1419 (gotPlt
? destination
.getGotPltVA(ctx
) : destination
.getVA(ctx
)) -
1420 getThunkTargetSym()->getVA(ctx
);
1421 if (!isInt
<34>(offset
))
1422 reportRangeError(ctx
, buf
, offset
, 34, destination
,
1423 "R12 setup stub offset");
1426 if (ctx
.arg
.power10Stubs
) {
1427 const uint64_t imm
= (((offset
>> 16) & 0x3ffff) << 32) | (offset
& 0xffff);
1428 // pld 12, func@plt@pcrel or paddi r12, 0, func@pcrel
1429 writePrefixedInst(ctx
, buf
,
1430 (gotPlt
? PLD_R12_NO_DISP
: PADDI_R12_NO_DISP
) | imm
);
1433 uint32_t off
= offset
- 8;
1434 write32(ctx
, buf
+ 0, 0x7d8802a6); // mflr 12
1435 write32(ctx
, buf
+ 4, 0x429f0005); // bcl 20,31,.+4
1436 write32(ctx
, buf
+ 8, 0x7d6802a6); // mflr 11
1437 write32(ctx
, buf
+ 12, 0x7d8803a6); // mtlr 12
1438 write32(ctx
, buf
+ 16,
1439 0x3d8b0000 | ((off
+ 0x8000) >> 16)); // addis 12,11,off@ha
1441 write32(ctx
, buf
+ 20, 0xe98c0000 | (off
& 0xffff)); // ld 12, off@l(12)
1443 write32(ctx
, buf
+ 20, 0x398c0000 | (off
& 0xffff)); // addi 12,12,off@l
1444 nextInstOffset
= 24;
1446 write32(ctx
, buf
+ nextInstOffset
, MTCTR_R12
); // mtctr r12
1447 write32(ctx
, buf
+ nextInstOffset
+ 4, BCTR
); // bctr
1450 void PPC64R12SetupStub::addSymbols(ThunkSection
&isec
) {
1451 addSymbol(ctx
.saver
.save((gotPlt
? "__plt_pcrel_" : "__gep_setup_") +
1452 destination
.getName()),
1456 bool PPC64R12SetupStub::isCompatibleWith(const InputSection
&isec
,
1457 const Relocation
&rel
) const {
1458 return rel
.type
== R_PPC64_REL24_NOTOC
;
1461 void PPC64LongBranchThunk::writeTo(uint8_t *buf
) {
1463 ctx
.in
.ppc64LongBranchTarget
->getEntryVA(&destination
, addend
) -
1464 getPPC64TocBase(ctx
);
1465 writePPC64LoadAndBranch(ctx
, buf
, offset
);
1468 void PPC64LongBranchThunk::addSymbols(ThunkSection
&isec
) {
1469 addSymbol(ctx
.saver
.save("__long_branch_" + destination
.getName()), STT_FUNC
,
1473 bool PPC64LongBranchThunk::isCompatibleWith(const InputSection
&isec
,
1474 const Relocation
&rel
) const {
1475 return rel
.type
== R_PPC64_REL24
|| rel
.type
== R_PPC64_REL14
;
1478 Thunk::Thunk(Ctx
&ctx
, Symbol
&d
, int64_t a
)
1479 : ctx(ctx
), destination(d
), addend(a
), offset(0) {
1480 destination
.thunkAccessed
= true;
1483 Thunk::~Thunk() = default;
1485 static std::unique_ptr
<Thunk
> addThunkAArch64(Ctx
&ctx
, RelType type
, Symbol
&s
,
1487 assert(is_contained({R_AARCH64_CALL26
, R_AARCH64_JUMP26
, R_AARCH64_PLT32
},
1489 bool mayNeedLandingPad
=
1490 (ctx
.arg
.andFeatures
& GNU_PROPERTY_AARCH64_FEATURE_1_BTI
) &&
1491 !isAArch64BTILandingPad(ctx
, s
, a
);
1492 if (ctx
.arg
.picThunk
)
1493 return std::make_unique
<AArch64ADRPThunk
>(ctx
, s
, a
, mayNeedLandingPad
);
1494 return std::make_unique
<AArch64ABSLongThunk
>(ctx
, s
, a
, mayNeedLandingPad
);
1497 // Creates a thunk for long branches or Thumb-ARM interworking.
1498 // Arm Architectures v4t does not support Thumb2 technology, and does not
1499 // support BLX or LDR Arm/Thumb state switching. This means that
1500 // - MOVT and MOVW instructions cannot be used.
1501 // - We can't rewrite BL in place to BLX. We will need thunks.
1503 // TODO: use B for short Thumb->Arm thunks instead of LDR (this doesn't work for
1504 // Arm->Thumb, as in Arm state no BX PC trick; it doesn't switch state).
1505 static std::unique_ptr
<Thunk
> addThunkArmv4(Ctx
&ctx
, RelType reloc
, Symbol
&s
,
1507 bool thumb_target
= s
.getVA(ctx
, a
) & 1;
1514 if (ctx
.arg
.picThunk
) {
1516 return std::make_unique
<ARMV4PILongBXThunk
>(ctx
, s
, a
);
1517 return std::make_unique
<ARMV4PILongThunk
>(ctx
, s
, a
);
1520 return std::make_unique
<ARMV4ABSLongBXThunk
>(ctx
, s
, a
);
1521 return std::make_unique
<ARMV5LongLdrPcThunk
>(ctx
, s
, a
);
1522 case R_ARM_THM_CALL
:
1523 if (ctx
.arg
.picThunk
) {
1525 return std::make_unique
<ThumbV4PILongThunk
>(ctx
, s
, a
);
1526 return std::make_unique
<ThumbV4PILongBXThunk
>(ctx
, s
, a
);
1529 return std::make_unique
<ThumbV4ABSLongThunk
>(ctx
, s
, a
);
1530 return std::make_unique
<ThumbV4ABSLongBXThunk
>(ctx
, s
, a
);
1532 Fatal(ctx
) << "relocation " << reloc
<< " to " << &s
1533 << " not supported for Armv4 or Armv4T target";
1534 llvm_unreachable("");
1537 // Creates a thunk for Thumb-ARM interworking compatible with Armv5 and Armv6.
1538 // Arm Architectures v5 and v6 do not support Thumb2 technology. This means that
1539 // - MOVT and MOVW instructions cannot be used
1540 // - Only Thumb relocation that can generate a Thunk is a BL, this can always
1541 // be transformed into a BLX
1542 static std::unique_ptr
<Thunk
> addThunkArmv5v6(Ctx
&ctx
, RelType reloc
,
1543 Symbol
&s
, int64_t a
) {
1549 case R_ARM_THM_CALL
:
1550 if (ctx
.arg
.picThunk
)
1551 return std::make_unique
<ARMV4PILongBXThunk
>(ctx
, s
, a
);
1552 return std::make_unique
<ARMV5LongLdrPcThunk
>(ctx
, s
, a
);
1554 Fatal(ctx
) << "relocation " << reloc
<< " to " << &s
1555 << " not supported for Armv5 or Armv6 targets";
1556 llvm_unreachable("");
1559 // Create a thunk for Thumb long branch on V6-M.
1560 // Arm Architecture v6-M only supports Thumb instructions. This means
1561 // - MOVT and MOVW instructions cannot be used.
1562 // - Only a limited number of instructions can access registers r8 and above
1563 // - No interworking support is needed (all Thumb).
1564 static std::unique_ptr
<Thunk
> addThunkV6M(Ctx
&ctx
, const InputSection
&isec
,
1565 RelType reloc
, Symbol
&s
, int64_t a
) {
1566 const bool isPureCode
= isec
.getParent()->flags
& SHF_ARM_PURECODE
;
1568 case R_ARM_THM_JUMP19
:
1569 case R_ARM_THM_JUMP24
:
1570 case R_ARM_THM_CALL
:
1571 if (ctx
.arg
.isPic
) {
1573 return std::make_unique
<ThumbV6MPILongThunk
>(ctx
, s
, a
);
1576 << "relocation " << reloc
<< " to " << &s
1577 << " not supported for Armv6-M targets for position independent"
1578 " and execute only code";
1579 llvm_unreachable("");
1582 return std::make_unique
<ThumbV6MABSXOLongThunk
>(ctx
, s
, a
);
1583 return std::make_unique
<ThumbV6MABSLongThunk
>(ctx
, s
, a
);
1585 Fatal(ctx
) << "relocation " << reloc
<< " to " << &s
1586 << " not supported for Armv6-M targets";
1587 llvm_unreachable("");
1590 // Creates a thunk for Thumb-ARM interworking or branch range extension.
1591 static std::unique_ptr
<Thunk
> addThunkArm(Ctx
&ctx
, const InputSection
&isec
,
1592 RelType reloc
, Symbol
&s
, int64_t a
) {
1593 // Decide which Thunk is needed based on:
1594 // Available instruction set
1595 // - An Arm Thunk can only be used if Arm state is available.
1596 // - A Thumb Thunk can only be used if Thumb state is available.
1597 // - Can only use a Thunk if it uses instructions that the Target supports.
1598 // Relocation is branch or branch and link
1599 // - Branch instructions cannot change state, can only select Thunk that
1600 // starts in the same state as the caller.
1601 // - Branch and link relocations can change state, can select Thunks from
1602 // either Arm or Thumb.
1603 // Position independent Thunks if we require position independent code.
1604 // Execute Only Thunks if the output section is execute only code.
1606 // Handle architectures that have restrictions on the instructions that they
1607 // can use in Thunks. The flags below are set by reading the BuildAttributes
1608 // of the input objects. InputFiles.cpp contains the mapping from ARM
1609 // architecture to flag.
1610 if (!ctx
.arg
.armHasMovtMovw
) {
1611 if (ctx
.arg
.armJ1J2BranchEncoding
)
1612 return addThunkV6M(ctx
, isec
, reloc
, s
, a
);
1613 if (ctx
.arg
.armHasBlx
)
1614 return addThunkArmv5v6(ctx
, reloc
, s
, a
);
1615 return addThunkArmv4(ctx
, reloc
, s
, a
);
1623 if (ctx
.arg
.picThunk
)
1624 return std::make_unique
<ARMV7PILongThunk
>(ctx
, s
, a
);
1625 return std::make_unique
<ARMV7ABSLongThunk
>(ctx
, s
, a
);
1626 case R_ARM_THM_JUMP19
:
1627 case R_ARM_THM_JUMP24
:
1628 case R_ARM_THM_CALL
:
1629 if (ctx
.arg
.picThunk
)
1630 return std::make_unique
<ThumbV7PILongThunk
>(ctx
, s
, a
);
1631 return std::make_unique
<ThumbV7ABSLongThunk
>(ctx
, s
, a
);
1633 llvm_unreachable("");
1636 static std::unique_ptr
<Thunk
> addThunkAVR(Ctx
&ctx
, RelType type
, Symbol
&s
,
1639 case R_AVR_LO8_LDI_GS
:
1640 case R_AVR_HI8_LDI_GS
:
1641 return std::make_unique
<AVRThunk
>(ctx
, s
, a
);
1643 llvm_unreachable("");
1647 static std::unique_ptr
<Thunk
> addThunkMips(Ctx
&ctx
, RelType type
, Symbol
&s
) {
1648 if ((s
.stOther
& STO_MIPS_MICROMIPS
) && isMipsR6(ctx
))
1649 return std::make_unique
<MicroMipsR6Thunk
>(ctx
, s
);
1650 if (s
.stOther
& STO_MIPS_MICROMIPS
)
1651 return std::make_unique
<MicroMipsThunk
>(ctx
, s
);
1652 return std::make_unique
<MipsThunk
>(ctx
, s
);
1655 static std::unique_ptr
<Thunk
> addThunkPPC32(Ctx
&ctx
, const InputSection
&isec
,
1656 const Relocation
&rel
, Symbol
&s
) {
1657 assert((rel
.type
== R_PPC_LOCAL24PC
|| rel
.type
== R_PPC_REL24
||
1658 rel
.type
== R_PPC_PLTREL24
) &&
1659 "unexpected relocation type for thunk");
1661 return std::make_unique
<PPC32PltCallStub
>(ctx
, isec
, rel
, s
);
1662 return std::make_unique
<PPC32LongThunk
>(ctx
, s
, rel
.addend
);
1665 static std::unique_ptr
<Thunk
> addThunkPPC64(Ctx
&ctx
, RelType type
, Symbol
&s
,
1667 assert((type
== R_PPC64_REL14
|| type
== R_PPC64_REL24
||
1668 type
== R_PPC64_REL24_NOTOC
) &&
1669 "unexpected relocation type for thunk");
1671 // If we are emitting stubs for NOTOC relocations, we need to tell
1672 // the PLT resolver that there can be multiple TOCs.
1673 if (type
== R_PPC64_REL24_NOTOC
)
1674 ctx
.target
->ppc64DynamicSectionOpt
= 0x2;
1676 if (s
.isInPlt(ctx
)) {
1677 if (type
== R_PPC64_REL24_NOTOC
)
1678 return std::make_unique
<PPC64R12SetupStub
>(ctx
, s
,
1680 return std::make_unique
<PPC64PltCallStub
>(ctx
, s
);
1683 // This check looks at the st_other bits of the callee. If the value is 1
1684 // then the callee clobbers the TOC and we need an R2 save stub when RelType
1685 // is R_PPC64_REL14 or R_PPC64_REL24.
1686 if ((type
== R_PPC64_REL14
|| type
== R_PPC64_REL24
) && (s
.stOther
>> 5) == 1)
1687 return std::make_unique
<PPC64R2SaveStub
>(ctx
, s
, a
);
1689 if (type
== R_PPC64_REL24_NOTOC
)
1690 return std::make_unique
<PPC64R12SetupStub
>(ctx
, s
, /*gotPlt=*/false);
1692 if (ctx
.arg
.picThunk
)
1693 return std::make_unique
<PPC64PILongBranchThunk
>(ctx
, s
, a
);
1695 return std::make_unique
<PPC64PDLongBranchThunk
>(ctx
, s
, a
);
1698 std::unique_ptr
<Thunk
> elf::addThunk(Ctx
&ctx
, const InputSection
&isec
,
1700 Symbol
&s
= *rel
.sym
;
1701 int64_t a
= rel
.addend
;
1703 switch (ctx
.arg
.emachine
) {
1705 return addThunkAArch64(ctx
, rel
.type
, s
, a
);
1707 return addThunkArm(ctx
, isec
, rel
.type
, s
, a
);
1709 return addThunkAVR(ctx
, rel
.type
, s
, a
);
1711 return addThunkMips(ctx
, rel
.type
, s
);
1713 return addThunkPPC32(ctx
, isec
, rel
, s
);
1715 return addThunkPPC64(ctx
, rel
.type
, s
, a
);
1717 llvm_unreachable("add Thunk only supported for ARM, AVR, Mips and PowerPC");
1721 std::unique_ptr
<Thunk
> elf::addLandingPadThunk(Ctx
&ctx
, Symbol
&s
, int64_t a
) {
1722 switch (ctx
.arg
.emachine
) {
1724 return std::make_unique
<AArch64BTILandingPadThunk
>(ctx
, s
, a
);
1726 llvm_unreachable("add landing pad only supported for AArch64");