xref: /freebsd/contrib/llvm-project/lld/ELF/Thunks.cpp (revision e64bea71c21eb42e97aa615188ba91f6cce0d36d)
1 //===- Thunks.cpp --------------------------------------------------------===//
2 //
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6 //
7 //===---------------------------------------------------------------------===//
8 //
9 // This file contains Thunk subclasses.
10 //
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.
14 //
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.
18 //
19 // i386 and x86-64 don't need thunks.
20 //
21 //===---------------------------------------------------------------------===//
22 
23 #include "Thunks.h"
24 #include "Config.h"
25 #include "InputFiles.h"
26 #include "InputSection.h"
27 #include "OutputSections.h"
28 #include "Symbols.h"
29 #include "SyntheticSections.h"
30 #include "Target.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"
36 #include <cstdint>
37 #include <cstring>
38 
39 using namespace llvm;
40 using namespace llvm::object;
41 using namespace llvm::ELF;
42 using namespace lld;
43 using namespace lld::elf;
44 
45 namespace {
46 
47 // Base class for AArch64 thunks.
48 //
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 {
59 public:
AArch64Thunk(Ctx & ctx,Symbol & dest,int64_t addend,bool mayNeedLandingPad)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;
65 
66 protected:
67   bool mayNeedLandingPad;
68 
69 private:
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.
addLongMapSyms()76   virtual void addLongMapSyms() {}
77 };
78 
79 // AArch64 long range Thunks.
80 class AArch64ABSLongThunk final : public AArch64Thunk {
81 public:
AArch64ABSLongThunk(Ctx & ctx,Symbol & dest,int64_t addend,bool mayNeedLandingPad)82   AArch64ABSLongThunk(Ctx &ctx, Symbol &dest, int64_t addend,
83                       bool mayNeedLandingPad)
84       : AArch64Thunk(ctx, dest, addend, mayNeedLandingPad) {}
size()85   uint32_t size() override { return getMayUseShortThunk() ? 4 : 16; }
86   void addSymbols(ThunkSection &isec) override;
87 
88 private:
89   void writeLong(uint8_t *buf) override;
90   void addLongMapSyms() override;
91   ThunkSection *tsec = nullptr;
92 };
93 
94 // AArch64 long range Thunks compatible with execute-only code.
95 class AArch64ABSXOLongThunk final : public AArch64Thunk {
96 public:
AArch64ABSXOLongThunk(Ctx & ctx,Symbol & dest,int64_t addend,bool mayNeedLandingPad)97   AArch64ABSXOLongThunk(Ctx &ctx, Symbol &dest, int64_t addend,
98                         bool mayNeedLandingPad)
99       : AArch64Thunk(ctx, dest, addend, mayNeedLandingPad) {}
size()100   uint32_t size() override { return getMayUseShortThunk() ? 4 : 20; }
101   void addSymbols(ThunkSection &sec) override;
102 
103 private:
104   void writeLong(uint8_t *buf) override;
105 };
106 
107 class AArch64ADRPThunk final : public AArch64Thunk {
108 public:
AArch64ADRPThunk(Ctx & ctx,Symbol & dest,int64_t addend,bool mayNeedLandingPad)109   AArch64ADRPThunk(Ctx &ctx, Symbol &dest, int64_t addend,
110                    bool mayNeedLandingPad)
111       : AArch64Thunk(ctx, dest, addend, mayNeedLandingPad) {}
size()112   uint32_t size() override { return getMayUseShortThunk() ? 4 : 12; }
113   void addSymbols(ThunkSection &isec) override;
114 
115 private:
116   void writeLong(uint8_t *buf) override;
117 };
118 
119 // AArch64 BTI Landing Pad
120 // When BTI is enabled indirect branches must land on a BTI
121 // compatible instruction. When the destination does not have a
122 // BTI compatible instruction a Thunk doing an indirect branch
123 // targets a Landing Pad Thunk that direct branches to the target.
124 class AArch64BTILandingPadThunk final : public Thunk {
125 public:
AArch64BTILandingPadThunk(Ctx & ctx,Symbol & dest,int64_t addend)126   AArch64BTILandingPadThunk(Ctx &ctx, Symbol &dest, int64_t addend)
127       : Thunk(ctx, dest, addend) {}
128 
size()129   uint32_t size() override { return getMayUseShortThunk() ? 4 : 8; }
130   void addSymbols(ThunkSection &isec) override;
131   void writeTo(uint8_t *buf) override;
132 
133 private:
134   bool getMayUseShortThunk();
135   void writeLong(uint8_t *buf);
136   bool mayUseShortThunk = true;
137 };
138 
139 // Base class for ARM thunks.
140 //
141 // An ARM thunk may be either short or long. A short thunk is simply a branch
142 // (B) instruction, and it may be used to call ARM functions when the distance
143 // from the thunk to the target is less than 32MB. Long thunks can branch to any
144 // virtual address and can switch between ARM and Thumb, and they are
145 // implemented in the derived classes. This class tries to create a short thunk
146 // if the target is in range, otherwise it creates a long thunk.
147 class ARMThunk : public Thunk {
148 public:
ARMThunk(Ctx & ctx,Symbol & dest,int64_t addend)149   ARMThunk(Ctx &ctx, Symbol &dest, int64_t addend) : Thunk(ctx, dest, addend) {}
150 
151   bool getMayUseShortThunk();
size()152   uint32_t size() override { return getMayUseShortThunk() ? 4 : sizeLong(); }
153   void writeTo(uint8_t *buf) override;
154   bool isCompatibleWith(const InputSection &isec,
155                         const Relocation &rel) const override;
156 
157   // Returns the size of a long thunk.
158   virtual uint32_t sizeLong() = 0;
159 
160   // Writes a long thunk to Buf.
161   virtual void writeLong(uint8_t *buf) = 0;
162 
163 private:
164   // This field tracks whether all previously considered layouts would allow
165   // this thunk to be short. If we have ever needed a long thunk, we always
166   // create a long thunk, even if the thunk may be short given the current
167   // distance to the target. We do this because transitioning from long to short
168   // can create layout oscillations in certain corner cases which would prevent
169   // the layout from converging.
170   bool mayUseShortThunk = true;
171   // See comment in AArch64Thunk.
addLongMapSyms()172   virtual void addLongMapSyms() {}
173 };
174 
175 // Base class for Thumb-2 thunks.
176 //
177 // This class is similar to ARMThunk, but it uses the Thumb-2 B.W instruction
178 // which has a range of 16MB.
179 class ThumbThunk : public Thunk {
180 public:
ThumbThunk(Ctx & ctx,Symbol & dest,int64_t addend)181   ThumbThunk(Ctx &ctx, Symbol &dest, int64_t addend)
182       : Thunk(ctx, dest, addend) {
183     alignment = 2;
184   }
185 
186   bool getMayUseShortThunk();
size()187   uint32_t size() override { return getMayUseShortThunk() ? 4 : sizeLong(); }
188   void writeTo(uint8_t *buf) override;
189   bool isCompatibleWith(const InputSection &isec,
190                         const Relocation &rel) const override;
191 
192   // Returns the size of a long thunk.
193   virtual uint32_t sizeLong() = 0;
194 
195   // Writes a long thunk to Buf.
196   virtual void writeLong(uint8_t *buf) = 0;
197 
198 private:
199   // See comment in ARMThunk above.
200   bool mayUseShortThunk = true;
201   // See comment in AArch64Thunk.
addLongMapSyms()202   virtual void addLongMapSyms() {}
203 };
204 
205 // Specific ARM Thunk implementations. The naming convention is:
206 // Source State, TargetState, Target Requirement, ABS or PI, Range
207 class ARMV7ABSLongThunk final : public ARMThunk {
208 public:
ARMV7ABSLongThunk(Ctx & ctx,Symbol & dest,int64_t addend)209   ARMV7ABSLongThunk(Ctx &ctx, Symbol &dest, int64_t addend)
210       : ARMThunk(ctx, dest, addend) {}
211 
sizeLong()212   uint32_t sizeLong() override { return 12; }
213   void writeLong(uint8_t *buf) override;
214   void addSymbols(ThunkSection &isec) override;
215 };
216 
217 class ARMV7PILongThunk final : public ARMThunk {
218 public:
ARMV7PILongThunk(Ctx & ctx,Symbol & dest,int64_t addend)219   ARMV7PILongThunk(Ctx &ctx, Symbol &dest, int64_t addend)
220       : ARMThunk(ctx, dest, addend) {}
221 
sizeLong()222   uint32_t sizeLong() override { return 16; }
223   void writeLong(uint8_t *buf) override;
224   void addSymbols(ThunkSection &isec) override;
225 };
226 
227 class ThumbV7ABSLongThunk final : public ThumbThunk {
228 public:
ThumbV7ABSLongThunk(Ctx & ctx,Symbol & dest,int64_t addend)229   ThumbV7ABSLongThunk(Ctx &ctx, Symbol &dest, int64_t addend)
230       : ThumbThunk(ctx, dest, addend) {}
231 
sizeLong()232   uint32_t sizeLong() override { return 10; }
233   void writeLong(uint8_t *buf) override;
234   void addSymbols(ThunkSection &isec) override;
235 };
236 
237 class ThumbV7PILongThunk final : public ThumbThunk {
238 public:
ThumbV7PILongThunk(Ctx & ctx,Symbol & dest,int64_t addend)239   ThumbV7PILongThunk(Ctx &ctx, Symbol &dest, int64_t addend)
240       : ThumbThunk(ctx, dest, addend) {}
241 
sizeLong()242   uint32_t sizeLong() override { return 12; }
243   void writeLong(uint8_t *buf) override;
244   void addSymbols(ThunkSection &isec) override;
245 };
246 
247 // Implementations of Thunks for Arm v6-M. Only Thumb instructions are permitted
248 class ThumbV6MABSLongThunk final : public ThumbThunk {
249 public:
ThumbV6MABSLongThunk(Ctx & ctx,Symbol & dest,int64_t addend)250   ThumbV6MABSLongThunk(Ctx &ctx, Symbol &dest, int64_t addend)
251       : ThumbThunk(ctx, dest, addend) {}
252 
sizeLong()253   uint32_t sizeLong() override { return 12; }
254   void writeLong(uint8_t *buf) override;
255   void addSymbols(ThunkSection &isec) override;
256 
257 private:
258   void addLongMapSyms() override;
259   ThunkSection *tsec = nullptr;
260 };
261 
262 class ThumbV6MABSXOLongThunk final : public ThumbThunk {
263 public:
ThumbV6MABSXOLongThunk(Ctx & ctx,Symbol & dest,int64_t addend)264   ThumbV6MABSXOLongThunk(Ctx &ctx, Symbol &dest, int64_t addend)
265       : ThumbThunk(ctx, dest, addend) {}
266 
sizeLong()267   uint32_t sizeLong() override { return 20; }
268   void writeLong(uint8_t *buf) override;
269   void addSymbols(ThunkSection &isec) override;
270 };
271 
272 class ThumbV6MPILongThunk final : public ThumbThunk {
273 public:
ThumbV6MPILongThunk(Ctx & ctx,Symbol & dest,int64_t addend)274   ThumbV6MPILongThunk(Ctx &ctx, Symbol &dest, int64_t addend)
275       : ThumbThunk(ctx, dest, addend) {}
276 
sizeLong()277   uint32_t sizeLong() override { return 16; }
278   void writeLong(uint8_t *buf) override;
279   void addSymbols(ThunkSection &isec) override;
280 
281 private:
282   void addLongMapSyms() override;
283   ThunkSection *tsec = nullptr;
284 };
285 
286 // Architectures v4, v5 and v6 do not support the movt/movw instructions. v5 and
287 // v6 support BLX to which BL instructions can be rewritten inline. There are no
288 // Thumb entrypoints for v5 and v6 as there is no Thumb branch instruction on
289 // these architecture that can result in a thunk.
290 
291 // LDR on v5 and v6 can switch processor state, so for v5 and v6,
292 // ARMV5LongLdrPcThunk can be used for both Arm->Arm and Arm->Thumb calls. v4
293 // can also use this thunk, but only for Arm->Arm calls.
294 class ARMV5LongLdrPcThunk final : public ARMThunk {
295 public:
ARMV5LongLdrPcThunk(Ctx & ctx,Symbol & dest,int64_t addend)296   ARMV5LongLdrPcThunk(Ctx &ctx, Symbol &dest, int64_t addend)
297       : ARMThunk(ctx, dest, addend) {}
298 
sizeLong()299   uint32_t sizeLong() override { return 8; }
300   void writeLong(uint8_t *buf) override;
301   void addSymbols(ThunkSection &isec) override;
302 
303 private:
304   void addLongMapSyms() override;
305   ThunkSection *tsec = nullptr;
306 };
307 
308 // Implementations of Thunks for v4. BLX is not supported, and loads
309 // will not invoke Arm/Thumb state changes.
310 class ARMV4PILongBXThunk final : public ARMThunk {
311 public:
ARMV4PILongBXThunk(Ctx & ctx,Symbol & dest,int64_t addend)312   ARMV4PILongBXThunk(Ctx &ctx, Symbol &dest, int64_t addend)
313       : ARMThunk(ctx, dest, addend) {}
314 
sizeLong()315   uint32_t sizeLong() override { return 16; }
316   void writeLong(uint8_t *buf) override;
317   void addSymbols(ThunkSection &isec) override;
318 
319 private:
320   void addLongMapSyms() override;
321   ThunkSection *tsec = nullptr;
322 };
323 
324 class ARMV4PILongThunk final : public ARMThunk {
325 public:
ARMV4PILongThunk(Ctx & ctx,Symbol & dest,int64_t addend)326   ARMV4PILongThunk(Ctx &ctx, Symbol &dest, int64_t addend)
327       : ARMThunk(ctx, dest, addend) {}
328 
sizeLong()329   uint32_t sizeLong() override { return 12; }
330   void writeLong(uint8_t *buf) override;
331   void addSymbols(ThunkSection &isec) override;
332 
333 private:
334   void addLongMapSyms() override;
335   ThunkSection *tsec = nullptr;
336 };
337 
338 class ThumbV4PILongBXThunk final : public ThumbThunk {
339 public:
ThumbV4PILongBXThunk(Ctx & ctx,Symbol & dest,int64_t addend)340   ThumbV4PILongBXThunk(Ctx &ctx, Symbol &dest, int64_t addend)
341       : ThumbThunk(ctx, dest, addend) {}
342 
sizeLong()343   uint32_t sizeLong() override { return 16; }
344   void writeLong(uint8_t *buf) override;
345   void addSymbols(ThunkSection &isec) override;
346 
347 private:
348   void addLongMapSyms() override;
349   ThunkSection *tsec = nullptr;
350 };
351 
352 class ThumbV4PILongThunk final : public ThumbThunk {
353 public:
ThumbV4PILongThunk(Ctx & ctx,Symbol & dest,int64_t addend)354   ThumbV4PILongThunk(Ctx &ctx, Symbol &dest, int64_t addend)
355       : ThumbThunk(ctx, dest, addend) {}
356 
sizeLong()357   uint32_t sizeLong() override { return 20; }
358   void writeLong(uint8_t *buf) override;
359   void addSymbols(ThunkSection &isec) override;
360 
361 private:
362   void addLongMapSyms() override;
363   ThunkSection *tsec = nullptr;
364 };
365 
366 class ARMV4ABSLongBXThunk final : public ARMThunk {
367 public:
ARMV4ABSLongBXThunk(Ctx & ctx,Symbol & dest,int64_t addend)368   ARMV4ABSLongBXThunk(Ctx &ctx, Symbol &dest, int64_t addend)
369       : ARMThunk(ctx, dest, addend) {}
370 
sizeLong()371   uint32_t sizeLong() override { return 12; }
372   void writeLong(uint8_t *buf) override;
373   void addSymbols(ThunkSection &isec) override;
374 
375 private:
376   void addLongMapSyms() override;
377   ThunkSection *tsec = nullptr;
378 };
379 
380 class ThumbV4ABSLongBXThunk final : public ThumbThunk {
381 public:
ThumbV4ABSLongBXThunk(Ctx & ctx,Symbol & dest,int64_t addend)382   ThumbV4ABSLongBXThunk(Ctx &ctx, Symbol &dest, int64_t addend)
383       : ThumbThunk(ctx, dest, addend) {}
384 
sizeLong()385   uint32_t sizeLong() override { return 12; }
386   void writeLong(uint8_t *buf) override;
387   void addSymbols(ThunkSection &isec) override;
388 
389 private:
390   void addLongMapSyms() override;
391   ThunkSection *tsec = nullptr;
392 };
393 
394 class ThumbV4ABSLongThunk final : public ThumbThunk {
395 public:
ThumbV4ABSLongThunk(Ctx & ctx,Symbol & dest,int64_t addend)396   ThumbV4ABSLongThunk(Ctx &ctx, Symbol &dest, int64_t addend)
397       : ThumbThunk(ctx, dest, addend) {}
398 
sizeLong()399   uint32_t sizeLong() override { return 16; }
400   void writeLong(uint8_t *buf) override;
401   void addSymbols(ThunkSection &isec) override;
402 
403 private:
404   void addLongMapSyms() override;
405   ThunkSection *tsec = nullptr;
406 };
407 
408 // The AVR devices need thunks for R_AVR_LO8_LDI_GS/R_AVR_HI8_LDI_GS
409 // when their destination is out of range [0, 0x1ffff].
410 class AVRThunk : public Thunk {
411 public:
AVRThunk(Ctx & ctx,Symbol & dest,int64_t addend)412   AVRThunk(Ctx &ctx, Symbol &dest, int64_t addend) : Thunk(ctx, dest, addend) {}
size()413   uint32_t size() override { return 4; }
414   void writeTo(uint8_t *buf) override;
415   void addSymbols(ThunkSection &isec) override;
416 };
417 
418 // Hexagon CPUs need thunks for R_HEX_B{9,1{3,5},22}_PCREL,
419 // R_HEX_{,GD_}PLT_B22_PCREL when their destination is out of
420 // range.
421 class HexagonThunk : public Thunk {
422 public:
HexagonThunk(Ctx & ctx,const InputSection & isec,Relocation & rel,Symbol & dest)423   HexagonThunk(Ctx &ctx, const InputSection &isec, Relocation &rel,
424                Symbol &dest)
425       : Thunk(ctx, dest, 0), relOffset(rel.offset) {
426     alignment = 4;
427   }
428   uint32_t relOffset;
size()429   uint32_t size() override { return ctx.arg.isPic ? 12 : 8; }
430   void writeTo(uint8_t *buf) override;
431   void addSymbols(ThunkSection &isec) override;
432 };
433 
434 // MIPS LA25 thunk
435 class MipsThunk final : public Thunk {
436 public:
MipsThunk(Ctx & ctx,Symbol & dest)437   MipsThunk(Ctx &ctx, Symbol &dest) : Thunk(ctx, dest, 0) {}
438 
size()439   uint32_t size() override { return 16; }
440   void writeTo(uint8_t *buf) override;
441   void addSymbols(ThunkSection &isec) override;
442   InputSection *getTargetInputSection() const override;
443 };
444 
445 // microMIPS R2-R5 LA25 thunk
446 class MicroMipsThunk final : public Thunk {
447 public:
MicroMipsThunk(Ctx & ctx,Symbol & dest)448   MicroMipsThunk(Ctx &ctx, Symbol &dest) : Thunk(ctx, dest, 0) {}
449 
size()450   uint32_t size() override { return 14; }
451   void writeTo(uint8_t *buf) override;
452   void addSymbols(ThunkSection &isec) override;
453   InputSection *getTargetInputSection() const override;
454 };
455 
456 // microMIPS R6 LA25 thunk
457 class MicroMipsR6Thunk final : public Thunk {
458 public:
MicroMipsR6Thunk(Ctx & ctx,Symbol & dest)459   MicroMipsR6Thunk(Ctx &ctx, Symbol &dest) : Thunk(ctx, dest, 0) {}
460 
size()461   uint32_t size() override { return 12; }
462   void writeTo(uint8_t *buf) override;
463   void addSymbols(ThunkSection &isec) override;
464   InputSection *getTargetInputSection() const override;
465 };
466 
467 class PPC32PltCallStub final : public Thunk {
468 public:
469   // For R_PPC_PLTREL24, Thunk::addend records the addend which will be used to
470   // decide the offsets in the call stub.
PPC32PltCallStub(Ctx & ctx,const InputSection & isec,const Relocation & rel,Symbol & dest)471   PPC32PltCallStub(Ctx &ctx, const InputSection &isec, const Relocation &rel,
472                    Symbol &dest)
473       : Thunk(ctx, dest, rel.addend), file(isec.file) {}
size()474   uint32_t size() override { return 16; }
475   void writeTo(uint8_t *buf) override;
476   void addSymbols(ThunkSection &isec) override;
477   bool isCompatibleWith(const InputSection &isec, const Relocation &rel) const override;
478 
479 private:
480   // Records the call site of the call stub.
481   const InputFile *file;
482 };
483 
484 class PPC32LongThunk final : public Thunk {
485 public:
PPC32LongThunk(Ctx & ctx,Symbol & dest,int64_t addend)486   PPC32LongThunk(Ctx &ctx, Symbol &dest, int64_t addend)
487       : Thunk(ctx, dest, addend) {}
size()488   uint32_t size() override { return ctx.arg.isPic ? 32 : 16; }
489   void writeTo(uint8_t *buf) override;
490   void addSymbols(ThunkSection &isec) override;
491 };
492 
493 // PPC64 Plt call stubs.
494 // Any call site that needs to call through a plt entry needs a call stub in
495 // the .text section. The call stub is responsible for:
496 // 1) Saving the toc-pointer to the stack.
497 // 2) Loading the target functions address from the procedure linkage table into
498 //    r12 for use by the target functions global entry point, and into the count
499 //    register.
500 // 3) Transferring control to the target function through an indirect branch.
501 class PPC64PltCallStub final : public Thunk {
502 public:
PPC64PltCallStub(Ctx & ctx,Symbol & dest)503   PPC64PltCallStub(Ctx &ctx, Symbol &dest) : Thunk(ctx, dest, 0) {}
size()504   uint32_t size() override { return 20; }
505   void writeTo(uint8_t *buf) override;
506   void addSymbols(ThunkSection &isec) override;
507   bool isCompatibleWith(const InputSection &isec,
508                         const Relocation &rel) const override;
509 };
510 
511 // PPC64 R2 Save Stub
512 // When the caller requires a valid R2 TOC pointer but the callee does not
513 // require a TOC pointer and the callee cannot guarantee that it doesn't
514 // clobber R2 then we need to save R2. This stub:
515 // 1) Saves the TOC pointer to the stack.
516 // 2) Tail calls the callee.
517 class PPC64R2SaveStub final : public Thunk {
518 public:
PPC64R2SaveStub(Ctx & ctx,Symbol & dest,int64_t addend)519   PPC64R2SaveStub(Ctx &ctx, Symbol &dest, int64_t addend)
520       : Thunk(ctx, dest, addend) {
521     alignment = 16;
522   }
523 
524   // To prevent oscillations in layout when moving from short to long thunks
525   // we make sure that once a thunk has been set to long it cannot go back.
getMayUseShortThunk()526   bool getMayUseShortThunk() {
527     if (!mayUseShortThunk)
528       return false;
529     if (!isInt<26>(computeOffset())) {
530       mayUseShortThunk = false;
531       return false;
532     }
533     return true;
534   }
size()535   uint32_t size() override { return getMayUseShortThunk() ? 8 : 32; }
536   void writeTo(uint8_t *buf) override;
537   void addSymbols(ThunkSection &isec) override;
538   bool isCompatibleWith(const InputSection &isec,
539                         const Relocation &rel) const override;
540 
541 private:
542   // Transitioning from long to short can create layout oscillations in
543   // certain corner cases which would prevent the layout from converging.
544   // This is similar to the handling for ARMThunk.
545   bool mayUseShortThunk = true;
computeOffset() const546   int64_t computeOffset() const {
547     return destination.getVA(ctx) - (getThunkTargetSym()->getVA(ctx) + 4);
548   }
549 };
550 
551 // PPC64 R12 Setup Stub
552 // When a caller that does not maintain TOC calls a target which may possibly
553 // use TOC (either non-preemptible with localentry>1 or preemptible), we need to
554 // set r12 to satisfy the requirement of the global entry point.
555 class PPC64R12SetupStub final : public Thunk {
556 public:
PPC64R12SetupStub(Ctx & ctx,Symbol & dest,bool gotPlt)557   PPC64R12SetupStub(Ctx &ctx, Symbol &dest, bool gotPlt)
558       : Thunk(ctx, dest, 0), gotPlt(gotPlt) {
559     alignment = 16;
560   }
size()561   uint32_t size() override { return 32; }
562   void writeTo(uint8_t *buf) override;
563   void addSymbols(ThunkSection &isec) override;
564   bool isCompatibleWith(const InputSection &isec,
565                         const Relocation &rel) const override;
566 
567 private:
568   bool gotPlt;
569 };
570 
571 // A bl instruction uses a signed 24 bit offset, with an implicit 4 byte
572 // alignment. This gives a possible 26 bits of 'reach'. If the call offset is
573 // larger than that we need to emit a long-branch thunk. The target address
574 // of the callee is stored in a table to be accessed TOC-relative. Since the
575 // call must be local (a non-local call will have a PltCallStub instead) the
576 // table stores the address of the callee's local entry point. For
577 // position-independent code a corresponding relative dynamic relocation is
578 // used.
579 class PPC64LongBranchThunk : public Thunk {
580 public:
size()581   uint32_t size() override { return 32; }
582   void writeTo(uint8_t *buf) override;
583   void addSymbols(ThunkSection &isec) override;
584   bool isCompatibleWith(const InputSection &isec,
585                         const Relocation &rel) const override;
586 
587 protected:
PPC64LongBranchThunk(Ctx & ctx,Symbol & dest,int64_t addend)588   PPC64LongBranchThunk(Ctx &ctx, Symbol &dest, int64_t addend)
589       : Thunk(ctx, dest, addend) {}
590 };
591 
592 class PPC64PILongBranchThunk final : public PPC64LongBranchThunk {
593 public:
PPC64PILongBranchThunk(Ctx & ctx,Symbol & dest,int64_t addend)594   PPC64PILongBranchThunk(Ctx &ctx, Symbol &dest, int64_t addend)
595       : PPC64LongBranchThunk(ctx, dest, addend) {
596     assert(!dest.isPreemptible);
597     if (std::optional<uint32_t> index =
598             ctx.in.ppc64LongBranchTarget->addEntry(&dest, addend)) {
599       ctx.mainPart->relaDyn->addRelativeReloc(
600           ctx.target->relativeRel, *ctx.in.ppc64LongBranchTarget,
601           *index * UINT64_C(8), dest,
602           addend + getPPC64GlobalEntryToLocalEntryOffset(ctx, dest.stOther),
603           ctx.target->symbolicRel, R_ABS);
604     }
605   }
606 };
607 
608 class PPC64PDLongBranchThunk final : public PPC64LongBranchThunk {
609 public:
PPC64PDLongBranchThunk(Ctx & ctx,Symbol & dest,int64_t addend)610   PPC64PDLongBranchThunk(Ctx &ctx, Symbol &dest, int64_t addend)
611       : PPC64LongBranchThunk(ctx, dest, addend) {
612     ctx.in.ppc64LongBranchTarget->addEntry(&dest, addend);
613   }
614 };
615 
616 } // end anonymous namespace
617 
addSymbol(StringRef name,uint8_t type,uint64_t value,InputSectionBase & section)618 Defined *Thunk::addSymbol(StringRef name, uint8_t type, uint64_t value,
619                           InputSectionBase &section) {
620   Defined *d =
621       addSyntheticLocal(ctx, name, type, value + offset, /*size=*/0, section);
622   syms.push_back(d);
623   return d;
624 }
625 
setOffset(uint64_t newOffset)626 void Thunk::setOffset(uint64_t newOffset) {
627   for (Defined *d : syms)
628     d->value = d->value - offset + newOffset;
629   offset = newOffset;
630 }
631 
632 // AArch64 Thunk base class.
getAArch64ThunkDestVA(Ctx & ctx,const Symbol & s,int64_t a)633 static uint64_t getAArch64ThunkDestVA(Ctx &ctx, const Symbol &s, int64_t a) {
634   uint64_t v = s.isInPlt(ctx) ? s.getPltVA(ctx) : s.getVA(ctx, a);
635   return v;
636 }
637 
getMayUseShortThunk()638 bool AArch64Thunk::getMayUseShortThunk() {
639   if (!mayUseShortThunk)
640     return false;
641   uint64_t s = getAArch64ThunkDestVA(ctx, destination, addend);
642   uint64_t p = getThunkTargetSym()->getVA(ctx);
643   mayUseShortThunk = llvm::isInt<28>(s - p);
644   if (!mayUseShortThunk)
645     addLongMapSyms();
646   return mayUseShortThunk;
647 }
648 
writeTo(uint8_t * buf)649 void AArch64Thunk::writeTo(uint8_t *buf) {
650   if (!getMayUseShortThunk()) {
651     writeLong(buf);
652     return;
653   }
654   uint64_t s = getAArch64ThunkDestVA(ctx, destination, addend);
655   uint64_t p = getThunkTargetSym()->getVA(ctx);
656   write32(ctx, buf, 0x14000000); // b S
657   ctx.target->relocateNoSym(buf, R_AARCH64_CALL26, s - p);
658 }
659 
needsSyntheticLandingPad()660 bool AArch64Thunk::needsSyntheticLandingPad() {
661   // Short Thunks use a direct branch, no synthetic landing pad
662   // required.
663   return mayNeedLandingPad && !getMayUseShortThunk();
664 }
665 
666 // AArch64 long range Thunks.
writeLong(uint8_t * buf)667 void AArch64ABSLongThunk::writeLong(uint8_t *buf) {
668   const uint8_t data[] = {
669     0x50, 0x00, 0x00, 0x58, //     ldr x16, L0
670     0x00, 0x02, 0x1f, 0xd6, //     br  x16
671     0x00, 0x00, 0x00, 0x00, // L0: .xword S
672     0x00, 0x00, 0x00, 0x00,
673   };
674   // If mayNeedLandingPad is true then destination is an
675   // AArch64BTILandingPadThunk that defines landingPad.
676   assert(!mayNeedLandingPad || landingPad != nullptr);
677   uint64_t s = mayNeedLandingPad
678                    ? landingPad->getVA(ctx, 0)
679                    : getAArch64ThunkDestVA(ctx, destination, addend);
680   memcpy(buf, data, sizeof(data));
681   ctx.target->relocateNoSym(buf + 8, R_AARCH64_ABS64, s);
682 }
683 
addSymbols(ThunkSection & isec)684 void AArch64ABSLongThunk::addSymbols(ThunkSection &isec) {
685   addSymbol(ctx.saver.save("__AArch64AbsLongThunk_" + destination.getName()),
686             STT_FUNC, 0, isec);
687   addSymbol("$x", STT_NOTYPE, 0, isec);
688   tsec = &isec;
689   (void)getMayUseShortThunk();
690 }
691 
addLongMapSyms()692 void AArch64ABSLongThunk::addLongMapSyms() {
693   addSymbol("$d", STT_NOTYPE, 8, *tsec);
694   // The ldr in the long Thunk requires 8-byte alignment when
695   // unaligned accesses are disabled.
696   alignment = 8;
697 }
698 
writeLong(uint8_t * buf)699 void AArch64ABSXOLongThunk::writeLong(uint8_t *buf) {
700   const uint8_t data[] = {
701       0x10, 0x00, 0x80, 0xd2, // movz x16, :abs_g0_nc:S, lsl #0
702       0x10, 0x00, 0xa0, 0xf2, // movk x16, :abs_g1_nc:S, lsl #16
703       0x10, 0x00, 0xc0, 0xf2, // movk x16, :abs_g2_nc:S, lsl #32
704       0x10, 0x00, 0xe0, 0xf2, // movk x16, :abs_g3:S,    lsl #48
705       0x00, 0x02, 0x1f, 0xd6, // br   x16
706   };
707   // If mayNeedLandingPad is true then destination is an
708   // AArch64BTILandingPadThunk that defines landingPad.
709   assert(!mayNeedLandingPad || landingPad != nullptr);
710   uint64_t s = mayNeedLandingPad
711                    ? landingPad->getVA(ctx, 0)
712                    : getAArch64ThunkDestVA(ctx, destination, addend);
713   memcpy(buf, data, sizeof(data));
714   ctx.target->relocateNoSym(buf + 0, R_AARCH64_MOVW_UABS_G0_NC, s);
715   ctx.target->relocateNoSym(buf + 4, R_AARCH64_MOVW_UABS_G1_NC, s);
716   ctx.target->relocateNoSym(buf + 8, R_AARCH64_MOVW_UABS_G2_NC, s);
717   ctx.target->relocateNoSym(buf + 12, R_AARCH64_MOVW_UABS_G3, s);
718 }
719 
addSymbols(ThunkSection & sec)720 void AArch64ABSXOLongThunk::addSymbols(ThunkSection &sec) {
721   addSymbol(ctx.saver.save("__AArch64AbsXOLongThunk_" + destination.getName()),
722             STT_FUNC, 0, sec);
723   addSymbol("$x", STT_NOTYPE, 0, sec);
724 }
725 
726 // This Thunk has a maximum range of 4Gb, this is sufficient for all programs
727 // using the small code model, including pc-relative ones. At time of writing
728 // clang and gcc do not support the large code model for position independent
729 // code so it is safe to use this for position independent thunks without
730 // worrying about the destination being more than 4Gb away.
writeLong(uint8_t * buf)731 void AArch64ADRPThunk::writeLong(uint8_t *buf) {
732   const uint8_t data[] = {
733       0x10, 0x00, 0x00, 0x90, // adrp x16, Dest R_AARCH64_ADR_PREL_PG_HI21(Dest)
734       0x10, 0x02, 0x00, 0x91, // add  x16, x16, R_AARCH64_ADD_ABS_LO12_NC(Dest)
735       0x00, 0x02, 0x1f, 0xd6, // br   x16
736   };
737   // if mayNeedLandingPad is true then destination is an
738   // AArch64BTILandingPadThunk that defines landingPad.
739   assert(!mayNeedLandingPad || landingPad != nullptr);
740   uint64_t s = mayNeedLandingPad
741                    ? landingPad->getVA(ctx, 0)
742                    : getAArch64ThunkDestVA(ctx, destination, addend);
743   uint64_t p = getThunkTargetSym()->getVA(ctx);
744   memcpy(buf, data, sizeof(data));
745   ctx.target->relocateNoSym(buf, R_AARCH64_ADR_PREL_PG_HI21,
746                             getAArch64Page(s) - getAArch64Page(p));
747   ctx.target->relocateNoSym(buf + 4, R_AARCH64_ADD_ABS_LO12_NC, s);
748 }
749 
addSymbols(ThunkSection & isec)750 void AArch64ADRPThunk::addSymbols(ThunkSection &isec) {
751   addSymbol(ctx.saver.save("__AArch64ADRPThunk_" + destination.getName()),
752             STT_FUNC, 0, isec);
753   addSymbol("$x", STT_NOTYPE, 0, isec);
754 }
755 
addSymbols(ThunkSection & isec)756 void AArch64BTILandingPadThunk::addSymbols(ThunkSection &isec) {
757   addSymbol(ctx.saver.save("__AArch64BTIThunk_" + destination.getName()),
758             STT_FUNC, 0, isec);
759   addSymbol("$x", STT_NOTYPE, 0, isec);
760 }
761 
writeTo(uint8_t * buf)762 void AArch64BTILandingPadThunk::writeTo(uint8_t *buf) {
763   if (!getMayUseShortThunk()) {
764     writeLong(buf);
765     return;
766   }
767   write32(ctx, buf, 0xd503245f); // BTI c
768   // Control falls through to target in following section.
769 }
770 
getMayUseShortThunk()771 bool AArch64BTILandingPadThunk::getMayUseShortThunk() {
772   if (!mayUseShortThunk)
773     return false;
774   // If the target is the following instruction then we can fall
775   // through without the indirect branch.
776   uint64_t s = destination.getVA(ctx, addend);
777   uint64_t p = getThunkTargetSym()->getVA(ctx);
778   // This function is called before addresses are stable.  We need to
779   // work out the range from the thunk to the next section but the
780   // address of the start of the next section depends on the size of
781   // the thunks in the previous pass.  s - p + offset == 0 represents
782   // the first pass where the Thunk and following section are assigned
783   // the same offset.  s - p <= 4 is the last Thunk in the Thunk
784   // Section.
785   mayUseShortThunk = (s - p + offset == 0 || s - p <= 4);
786   return mayUseShortThunk;
787 }
788 
writeLong(uint8_t * buf)789 void AArch64BTILandingPadThunk::writeLong(uint8_t *buf) {
790   uint64_t s = destination.getVA(ctx, addend);
791   uint64_t p = getThunkTargetSym()->getVA(ctx) + 4;
792   write32(ctx, buf, 0xd503245f);     // BTI c
793   write32(ctx, buf + 4, 0x14000000); // B S
794   ctx.target->relocateNoSym(buf + 4, R_AARCH64_CALL26, s - p);
795 }
796 
797 // ARM Target Thunks
getARMThunkDestVA(Ctx & ctx,const Symbol & s)798 static uint64_t getARMThunkDestVA(Ctx &ctx, const Symbol &s) {
799   uint64_t v = s.isInPlt(ctx) ? s.getPltVA(ctx) : s.getVA(ctx);
800   return SignExtend64<32>(v);
801 }
802 
803 // This function returns true if the target is not Thumb and is within 2^26, and
804 // it has not previously returned false (see comment for mayUseShortThunk).
getMayUseShortThunk()805 bool ARMThunk::getMayUseShortThunk() {
806   if (!mayUseShortThunk)
807     return false;
808   uint64_t s = getARMThunkDestVA(ctx, destination);
809   if (s & 1) {
810     mayUseShortThunk = false;
811     addLongMapSyms();
812     return false;
813   }
814   uint64_t p = getThunkTargetSym()->getVA(ctx);
815   int64_t offset = s - p - 8;
816   mayUseShortThunk = llvm::isInt<26>(offset);
817   if (!mayUseShortThunk)
818     addLongMapSyms();
819   return mayUseShortThunk;
820 }
821 
writeTo(uint8_t * buf)822 void ARMThunk::writeTo(uint8_t *buf) {
823   if (!getMayUseShortThunk()) {
824     writeLong(buf);
825     return;
826   }
827 
828   uint64_t s = getARMThunkDestVA(ctx, destination);
829   uint64_t p = getThunkTargetSym()->getVA(ctx);
830   int64_t offset = s - p - 8;
831   write32(ctx, buf, 0xea000000); // b S
832   ctx.target->relocateNoSym(buf, R_ARM_JUMP24, offset);
833 }
834 
isCompatibleWith(const InputSection & isec,const Relocation & rel) const835 bool ARMThunk::isCompatibleWith(const InputSection &isec,
836                                 const Relocation &rel) const {
837   // v4T does not have BLX, so also deny R_ARM_THM_CALL
838   if (!ctx.arg.armHasBlx && rel.type == R_ARM_THM_CALL)
839     return false;
840 
841   // Thumb branch relocations can't use BLX
842   return rel.type != R_ARM_THM_JUMP19 && rel.type != R_ARM_THM_JUMP24;
843 }
844 
845 // This function returns true if:
846 // the target is Thumb
847 // && is within branch range
848 // && this function has not previously returned false
849 //    (see comment for mayUseShortThunk)
850 // && the arch supports Thumb branch range extension.
getMayUseShortThunk()851 bool ThumbThunk::getMayUseShortThunk() {
852   if (!mayUseShortThunk)
853     return false;
854   uint64_t s = getARMThunkDestVA(ctx, destination);
855   // To use a short thunk the destination must be Thumb and the target must
856   // have the wide branch instruction B.w. This instruction is included when
857   // Thumb 2 is present, or in v8-M (and above) baseline architectures.
858   // armJ1J2BranchEncoding is available in all architectures with a profile and
859   // the one v6 CPU that implements Thumb 2 (Arm1156t2-s).
860   // Movt and Movw instructions require Thumb 2 or v8-M baseline.
861   if ((s & 1) == 0 || !ctx.arg.armJ1J2BranchEncoding ||
862       !ctx.arg.armHasMovtMovw) {
863     mayUseShortThunk = false;
864     addLongMapSyms();
865     return false;
866   }
867   uint64_t p = getThunkTargetSym()->getVA(ctx) & ~1;
868   int64_t offset = s - p - 4;
869   mayUseShortThunk = llvm::isInt<25>(offset);
870   if (!mayUseShortThunk)
871     addLongMapSyms();
872   return mayUseShortThunk;
873 }
874 
writeTo(uint8_t * buf)875 void ThumbThunk::writeTo(uint8_t *buf) {
876   if (!getMayUseShortThunk()) {
877     writeLong(buf);
878     return;
879   }
880 
881   uint64_t s = getARMThunkDestVA(ctx, destination);
882   uint64_t p = getThunkTargetSym()->getVA(ctx);
883   int64_t offset = s - p - 4;
884   write16(ctx, buf + 0, 0xf000); // b.w S
885   write16(ctx, buf + 2, 0xb000);
886   ctx.target->relocateNoSym(buf, R_ARM_THM_JUMP24, offset);
887 }
888 
isCompatibleWith(const InputSection & isec,const Relocation & rel) const889 bool ThumbThunk::isCompatibleWith(const InputSection &isec,
890                                   const Relocation &rel) const {
891   // v4T does not have BLX, so also deny R_ARM_CALL
892   if (!ctx.arg.armHasBlx && rel.type == R_ARM_CALL)
893     return false;
894 
895   // ARM branch relocations can't use BLX
896   return rel.type != R_ARM_JUMP24 && rel.type != R_ARM_PC24 && rel.type != R_ARM_PLT32;
897 }
898 
writeLong(uint8_t * buf)899 void ARMV7ABSLongThunk::writeLong(uint8_t *buf) {
900   write32(ctx, buf + 0, 0xe300c000); // movw ip,:lower16:S
901   write32(ctx, buf + 4, 0xe340c000); // movt ip,:upper16:S
902   write32(ctx, buf + 8, 0xe12fff1c); // bx   ip
903   uint64_t s = getARMThunkDestVA(ctx, destination);
904   ctx.target->relocateNoSym(buf, R_ARM_MOVW_ABS_NC, s);
905   ctx.target->relocateNoSym(buf + 4, R_ARM_MOVT_ABS, s);
906 }
907 
addSymbols(ThunkSection & isec)908 void ARMV7ABSLongThunk::addSymbols(ThunkSection &isec) {
909   addSymbol(ctx.saver.save("__ARMv7ABSLongThunk_" + destination.getName()),
910             STT_FUNC, 0, isec);
911   addSymbol("$a", STT_NOTYPE, 0, isec);
912 }
913 
writeLong(uint8_t * buf)914 void ThumbV7ABSLongThunk::writeLong(uint8_t *buf) {
915   write16(ctx, buf + 0, 0xf240); // movw ip, :lower16:S
916   write16(ctx, buf + 2, 0x0c00);
917   write16(ctx, buf + 4, 0xf2c0); // movt ip, :upper16:S
918   write16(ctx, buf + 6, 0x0c00);
919   write16(ctx, buf + 8, 0x4760); // bx   ip
920   uint64_t s = getARMThunkDestVA(ctx, destination);
921   ctx.target->relocateNoSym(buf, R_ARM_THM_MOVW_ABS_NC, s);
922   ctx.target->relocateNoSym(buf + 4, R_ARM_THM_MOVT_ABS, s);
923 }
924 
addSymbols(ThunkSection & isec)925 void ThumbV7ABSLongThunk::addSymbols(ThunkSection &isec) {
926   addSymbol(ctx.saver.save("__Thumbv7ABSLongThunk_" + destination.getName()),
927             STT_FUNC, 1, isec);
928   addSymbol("$t", STT_NOTYPE, 0, isec);
929 }
930 
writeLong(uint8_t * buf)931 void ARMV7PILongThunk::writeLong(uint8_t *buf) {
932   write32(ctx, buf + 0,
933           0xe30fcff0); // P:  movw ip,:lower16:S - (P + (L1-P) + 8)
934   write32(ctx, buf + 4,
935           0xe340c000); //     movt ip,:upper16:S - (P + (L1-P) + 8)
936   write32(ctx, buf + 8, 0xe08cc00f);  // L1: add  ip, ip, pc
937   write32(ctx, buf + 12, 0xe12fff1c); //     bx   ip
938   uint64_t s = getARMThunkDestVA(ctx, destination);
939   uint64_t p = getThunkTargetSym()->getVA(ctx);
940   int64_t offset = s - p - 16;
941   ctx.target->relocateNoSym(buf, R_ARM_MOVW_PREL_NC, offset);
942   ctx.target->relocateNoSym(buf + 4, R_ARM_MOVT_PREL, offset);
943 }
944 
addSymbols(ThunkSection & isec)945 void ARMV7PILongThunk::addSymbols(ThunkSection &isec) {
946   addSymbol(ctx.saver.save("__ARMV7PILongThunk_" + destination.getName()),
947             STT_FUNC, 0, isec);
948   addSymbol("$a", STT_NOTYPE, 0, isec);
949 }
950 
writeLong(uint8_t * buf)951 void ThumbV7PILongThunk::writeLong(uint8_t *buf) {
952   write16(ctx, buf + 0, 0xf64f); // P:  movw ip,:lower16:S - (P + (L1-P) + 4)
953   write16(ctx, buf + 2, 0x7cf4);
954   write16(ctx, buf + 4, 0xf2c0); //     movt ip,:upper16:S - (P + (L1-P) + 4)
955   write16(ctx, buf + 6, 0x0c00);
956   write16(ctx, buf + 8, 0x44fc);  // L1: add  ip, pc
957   write16(ctx, buf + 10, 0x4760); //     bx   ip
958   uint64_t s = getARMThunkDestVA(ctx, destination);
959   uint64_t p = getThunkTargetSym()->getVA(ctx) & ~0x1;
960   int64_t offset = s - p - 12;
961   ctx.target->relocateNoSym(buf, R_ARM_THM_MOVW_PREL_NC, offset);
962   ctx.target->relocateNoSym(buf + 4, R_ARM_THM_MOVT_PREL, offset);
963 }
964 
addSymbols(ThunkSection & isec)965 void ThumbV7PILongThunk::addSymbols(ThunkSection &isec) {
966   addSymbol(ctx.saver.save("__ThumbV7PILongThunk_" + destination.getName()),
967             STT_FUNC, 1, isec);
968   addSymbol("$t", STT_NOTYPE, 0, isec);
969 }
970 
writeLong(uint8_t * buf)971 void ThumbV6MABSLongThunk::writeLong(uint8_t *buf) {
972   // Most Thumb instructions cannot access the high registers r8 - r15. As the
973   // only register we can corrupt is r12 we must instead spill a low register
974   // to the stack to use as a scratch register. We push r1 even though we
975   // don't need to get some space to use for the return address.
976   write16(ctx, buf + 0, 0xb403); // push {r0, r1} ; Obtain scratch registers
977   write16(ctx, buf + 2, 0x4801); // ldr r0, [pc, #4] ; L1
978   write16(ctx, buf + 4, 0x9001); // str r0, [sp, #4] ; SP + 4 = S
979   write16(ctx, buf + 6, 0xbd01); // pop {r0, pc} ; restore r0 and branch to dest
980   write32(ctx, buf + 8, 0x00000000); // L1: .word S
981   uint64_t s = getARMThunkDestVA(ctx, destination);
982   ctx.target->relocateNoSym(buf + 8, R_ARM_ABS32, s);
983 }
984 
addSymbols(ThunkSection & isec)985 void ThumbV6MABSLongThunk::addSymbols(ThunkSection &isec) {
986   addSymbol(ctx.saver.save("__Thumbv6MABSLongThunk_" + destination.getName()),
987             STT_FUNC, 1, isec);
988   addSymbol("$t", STT_NOTYPE, 0, isec);
989   tsec = &isec;
990   (void)getMayUseShortThunk();
991 }
992 
addLongMapSyms()993 void ThumbV6MABSLongThunk::addLongMapSyms() {
994   addSymbol("$d", STT_NOTYPE, 8, *tsec);
995 }
996 
writeLong(uint8_t * buf)997 void ThumbV6MABSXOLongThunk::writeLong(uint8_t *buf) {
998   // Most Thumb instructions cannot access the high registers r8 - r15. As the
999   // only register we can corrupt is r12 we must instead spill a low register
1000   // to the stack to use as a scratch register. We push r1 even though we
1001   // don't need to get some space to use for the return address.
1002   write16(ctx, buf + 0, 0xb403);  // push {r0, r1} ; Obtain scratch registers
1003   write16(ctx, buf + 2, 0x2000);  // movs r0, :upper8_15:S
1004   write16(ctx, buf + 4, 0x0200);  // lsls r0, r0, #8
1005   write16(ctx, buf + 6, 0x3000);  // adds r0, :upper0_7:S
1006   write16(ctx, buf + 8, 0x0200);  // lsls r0, r0, #8
1007   write16(ctx, buf + 10, 0x3000); // adds r0, :lower8_15:S
1008   write16(ctx, buf + 12, 0x0200); // lsls r0, r0, #8
1009   write16(ctx, buf + 14, 0x3000); // adds r0, :lower0_7:S
1010   write16(ctx, buf + 16, 0x9001); // str r0, [sp, #4] ; SP + 4 = S
1011   write16(ctx, buf + 18,
1012           0xbd01); // pop {r0, pc} ; restore r0 and branch to dest
1013   uint64_t s = getARMThunkDestVA(ctx, destination);
1014   ctx.target->relocateNoSym(buf + 2, R_ARM_THM_ALU_ABS_G3, s);
1015   ctx.target->relocateNoSym(buf + 6, R_ARM_THM_ALU_ABS_G2_NC, s);
1016   ctx.target->relocateNoSym(buf + 10, R_ARM_THM_ALU_ABS_G1_NC, s);
1017   ctx.target->relocateNoSym(buf + 14, R_ARM_THM_ALU_ABS_G0_NC, s);
1018 }
1019 
addSymbols(ThunkSection & isec)1020 void ThumbV6MABSXOLongThunk::addSymbols(ThunkSection &isec) {
1021   addSymbol(ctx.saver.save("__Thumbv6MABSXOLongThunk_" + destination.getName()),
1022             STT_FUNC, 1, isec);
1023   addSymbol("$t", STT_NOTYPE, 0, isec);
1024 }
1025 
writeLong(uint8_t * buf)1026 void ThumbV6MPILongThunk::writeLong(uint8_t *buf) {
1027   // Most Thumb instructions cannot access the high registers r8 - r15. As the
1028   // only register we can corrupt is ip (r12) we must instead spill a low
1029   // register to the stack to use as a scratch register.
1030   write16(ctx, buf + 0,
1031           0xb401); // P:  push {r0}        ; Obtain scratch register
1032   write16(ctx, buf + 2, 0x4802); //     ldr r0, [pc, #8] ; L2
1033   write16(ctx, buf + 4, 0x4684); //     mov ip, r0       ; high to low register
1034   write16(ctx, buf + 6,
1035           0xbc01); //     pop {r0}         ; restore scratch register
1036   write16(ctx, buf + 8, 0x44e7); // L1: add pc, ip       ; transfer control
1037   write16(ctx, buf + 10,
1038           0x46c0); //     nop              ; pad to 4-byte boundary
1039   write32(ctx, buf + 12, 0x00000000); // L2: .word S - (P + (L1 - P) + 4)
1040   uint64_t s = getARMThunkDestVA(ctx, destination);
1041   uint64_t p = getThunkTargetSym()->getVA(ctx) & ~0x1;
1042   ctx.target->relocateNoSym(buf + 12, R_ARM_REL32, s - p - 12);
1043 }
1044 
addSymbols(ThunkSection & isec)1045 void ThumbV6MPILongThunk::addSymbols(ThunkSection &isec) {
1046   addSymbol(ctx.saver.save("__Thumbv6MPILongThunk_" + destination.getName()),
1047             STT_FUNC, 1, isec);
1048   addSymbol("$t", STT_NOTYPE, 0, isec);
1049   tsec = &isec;
1050   (void)getMayUseShortThunk();
1051 }
1052 
addLongMapSyms()1053 void ThumbV6MPILongThunk::addLongMapSyms() {
1054   addSymbol("$d", STT_NOTYPE, 12, *tsec);
1055 }
1056 
writeLong(uint8_t * buf)1057 void ARMV5LongLdrPcThunk::writeLong(uint8_t *buf) {
1058   write32(ctx, buf + 0, 0xe51ff004); // ldr pc, [pc,#-4] ; L1
1059   write32(ctx, buf + 4, 0x00000000); // L1: .word S
1060   ctx.target->relocateNoSym(buf + 4, R_ARM_ABS32,
1061                             getARMThunkDestVA(ctx, destination));
1062 }
1063 
addSymbols(ThunkSection & isec)1064 void ARMV5LongLdrPcThunk::addSymbols(ThunkSection &isec) {
1065   addSymbol(ctx.saver.save("__ARMv5LongLdrPcThunk_" + destination.getName()),
1066             STT_FUNC, 0, isec);
1067   addSymbol("$a", STT_NOTYPE, 0, isec);
1068   tsec = &isec;
1069   (void)getMayUseShortThunk();
1070 }
1071 
addLongMapSyms()1072 void ARMV5LongLdrPcThunk::addLongMapSyms() {
1073   addSymbol("$d", STT_NOTYPE, 4, *tsec);
1074 }
1075 
writeLong(uint8_t * buf)1076 void ARMV4ABSLongBXThunk::writeLong(uint8_t *buf) {
1077   write32(ctx, buf + 0, 0xe59fc000); // ldr r12, [pc] ; L1
1078   write32(ctx, buf + 4, 0xe12fff1c); // bx r12
1079   write32(ctx, buf + 8, 0x00000000); // L1: .word S
1080   ctx.target->relocateNoSym(buf + 8, R_ARM_ABS32,
1081                             getARMThunkDestVA(ctx, destination));
1082 }
1083 
addSymbols(ThunkSection & isec)1084 void ARMV4ABSLongBXThunk::addSymbols(ThunkSection &isec) {
1085   addSymbol(ctx.saver.save("__ARMv4ABSLongBXThunk_" + destination.getName()),
1086             STT_FUNC, 0, isec);
1087   addSymbol("$a", STT_NOTYPE, 0, isec);
1088   tsec = &isec;
1089   (void)getMayUseShortThunk();
1090 }
1091 
addLongMapSyms()1092 void ARMV4ABSLongBXThunk::addLongMapSyms() {
1093   addSymbol("$d", STT_NOTYPE, 8, *tsec);
1094 }
1095 
writeLong(uint8_t * buf)1096 void ThumbV4ABSLongBXThunk::writeLong(uint8_t *buf) {
1097   write16(ctx, buf + 0, 0x4778); // bx pc
1098   write16(ctx, buf + 2,
1099           0xe7fd); // b #-6 ; Arm recommended sequence to follow bx pc
1100   write32(ctx, buf + 4, 0xe51ff004); // ldr pc, [pc, #-4] ; L1
1101   write32(ctx, buf + 8, 0x00000000); // L1: .word S
1102   ctx.target->relocateNoSym(buf + 8, R_ARM_ABS32,
1103                             getARMThunkDestVA(ctx, destination));
1104 }
1105 
addSymbols(ThunkSection & isec)1106 void ThumbV4ABSLongBXThunk::addSymbols(ThunkSection &isec) {
1107   addSymbol(ctx.saver.save("__Thumbv4ABSLongBXThunk_" + destination.getName()),
1108             STT_FUNC, 1, isec);
1109   addSymbol("$t", STT_NOTYPE, 0, isec);
1110   tsec = &isec;
1111   (void)getMayUseShortThunk();
1112 }
1113 
addLongMapSyms()1114 void ThumbV4ABSLongBXThunk::addLongMapSyms() {
1115   addSymbol("$a", STT_NOTYPE, 4, *tsec);
1116   addSymbol("$d", STT_NOTYPE, 8, *tsec);
1117 }
1118 
writeLong(uint8_t * buf)1119 void ThumbV4ABSLongThunk::writeLong(uint8_t *buf) {
1120   write16(ctx, buf + 0, 0x4778); // bx pc
1121   write16(ctx, buf + 2,
1122           0xe7fd); // b #-6 ; Arm recommended sequence to follow bx pc
1123   write32(ctx, buf + 4, 0xe59fc000);  // ldr r12, [pc] ; L1
1124   write32(ctx, buf + 8, 0xe12fff1c);  // bx r12
1125   write32(ctx, buf + 12, 0x00000000); // L1: .word S
1126   ctx.target->relocateNoSym(buf + 12, R_ARM_ABS32,
1127                             getARMThunkDestVA(ctx, destination));
1128 }
1129 
addSymbols(ThunkSection & isec)1130 void ThumbV4ABSLongThunk::addSymbols(ThunkSection &isec) {
1131   addSymbol(ctx.saver.save("__Thumbv4ABSLongThunk_" + destination.getName()),
1132             STT_FUNC, 1, isec);
1133   addSymbol("$t", STT_NOTYPE, 0, isec);
1134   tsec = &isec;
1135   (void)getMayUseShortThunk();
1136 }
1137 
addLongMapSyms()1138 void ThumbV4ABSLongThunk::addLongMapSyms() {
1139   addSymbol("$a", STT_NOTYPE, 4, *tsec);
1140   addSymbol("$d", STT_NOTYPE, 12, *tsec);
1141 }
1142 
writeLong(uint8_t * buf)1143 void ARMV4PILongBXThunk::writeLong(uint8_t *buf) {
1144   write32(ctx, buf + 0, 0xe59fc004);  // P:  ldr ip, [pc,#4] ; L2
1145   write32(ctx, buf + 4, 0xe08fc00c);  // L1: add ip, pc, ip
1146   write32(ctx, buf + 8, 0xe12fff1c);  //     bx ip
1147   write32(ctx, buf + 12, 0x00000000); // L2: .word S - (P + (L1 - P) + 8)
1148   uint64_t s = getARMThunkDestVA(ctx, destination);
1149   uint64_t p = getThunkTargetSym()->getVA(ctx) & ~0x1;
1150   ctx.target->relocateNoSym(buf + 12, R_ARM_REL32, s - p - 12);
1151 }
1152 
addSymbols(ThunkSection & isec)1153 void ARMV4PILongBXThunk::addSymbols(ThunkSection &isec) {
1154   addSymbol(ctx.saver.save("__ARMv4PILongBXThunk_" + destination.getName()),
1155             STT_FUNC, 0, isec);
1156   addSymbol("$a", STT_NOTYPE, 0, isec);
1157   tsec = &isec;
1158   (void)getMayUseShortThunk();
1159 }
1160 
addLongMapSyms()1161 void ARMV4PILongBXThunk::addLongMapSyms() {
1162   addSymbol("$d", STT_NOTYPE, 12, *tsec);
1163 }
1164 
writeLong(uint8_t * buf)1165 void ARMV4PILongThunk::writeLong(uint8_t *buf) {
1166   write32(ctx, buf + 0, 0xe59fc000); // P:  ldr ip, [pc] ; L2
1167   write32(ctx, buf + 4, 0xe08ff00c); // L1: add pc, pc, r12
1168   write32(ctx, buf + 8, 0x00000000); // L2: .word S - (P + (L1 - P) + 8)
1169   uint64_t s = getARMThunkDestVA(ctx, destination);
1170   uint64_t p = getThunkTargetSym()->getVA(ctx) & ~0x1;
1171   ctx.target->relocateNoSym(buf + 8, R_ARM_REL32, s - p - 12);
1172 }
1173 
addSymbols(ThunkSection & isec)1174 void ARMV4PILongThunk::addSymbols(ThunkSection &isec) {
1175   addSymbol(ctx.saver.save("__ARMv4PILongThunk_" + destination.getName()),
1176             STT_FUNC, 0, isec);
1177   addSymbol("$a", STT_NOTYPE, 0, isec);
1178   tsec = &isec;
1179   (void)getMayUseShortThunk();
1180 }
1181 
addLongMapSyms()1182 void ARMV4PILongThunk::addLongMapSyms() {
1183   addSymbol("$d", STT_NOTYPE, 8, *tsec);
1184 }
1185 
writeLong(uint8_t * buf)1186 void ThumbV4PILongBXThunk::writeLong(uint8_t *buf) {
1187   write16(ctx, buf + 0, 0x4778); // P:  bx pc
1188   write16(ctx, buf + 2,
1189           0xe7fd); //     b #-6 ; Arm recommended sequence to follow bx pc
1190   write32(ctx, buf + 4, 0xe59fc000);  //     ldr r12, [pc] ; L2
1191   write32(ctx, buf + 8, 0xe08cf00f);  // L1: add pc, r12, pc
1192   write32(ctx, buf + 12, 0x00000000); // L2: .word S - (P + (L1 - P) + 8)
1193   uint64_t s = getARMThunkDestVA(ctx, destination);
1194   uint64_t p = getThunkTargetSym()->getVA(ctx) & ~0x1;
1195   ctx.target->relocateNoSym(buf + 12, R_ARM_REL32, s - p - 16);
1196 }
1197 
addSymbols(ThunkSection & isec)1198 void ThumbV4PILongBXThunk::addSymbols(ThunkSection &isec) {
1199   addSymbol(ctx.saver.save("__Thumbv4PILongBXThunk_" + destination.getName()),
1200             STT_FUNC, 1, isec);
1201   addSymbol("$t", STT_NOTYPE, 0, isec);
1202   tsec = &isec;
1203   (void)getMayUseShortThunk();
1204 }
1205 
addLongMapSyms()1206 void ThumbV4PILongBXThunk::addLongMapSyms() {
1207   addSymbol("$a", STT_NOTYPE, 4, *tsec);
1208   addSymbol("$d", STT_NOTYPE, 12, *tsec);
1209 }
1210 
writeLong(uint8_t * buf)1211 void ThumbV4PILongThunk::writeLong(uint8_t *buf) {
1212   write16(ctx, buf + 0, 0x4778); // P:  bx pc
1213   write16(ctx, buf + 2,
1214           0xe7fd); //     b #-6 ; Arm recommended sequence to follow bx pc
1215   write32(ctx, buf + 4, 0xe59fc004);  //     ldr ip, [pc,#4] ; L2
1216   write32(ctx, buf + 8, 0xe08fc00c);  // L1: add ip, pc, ip
1217   write32(ctx, buf + 12, 0xe12fff1c); //     bx ip
1218   write32(ctx, buf + 16, 0x00000000); // L2: .word S - (P + (L1 - P) + 8)
1219   uint64_t s = getARMThunkDestVA(ctx, destination);
1220   uint64_t p = getThunkTargetSym()->getVA(ctx) & ~0x1;
1221   ctx.target->relocateNoSym(buf + 16, R_ARM_REL32, s - p - 16);
1222 }
1223 
addSymbols(ThunkSection & isec)1224 void ThumbV4PILongThunk::addSymbols(ThunkSection &isec) {
1225   addSymbol(ctx.saver.save("__Thumbv4PILongThunk_" + destination.getName()),
1226             STT_FUNC, 1, isec);
1227   addSymbol("$t", STT_NOTYPE, 0, isec);
1228   tsec = &isec;
1229   (void)getMayUseShortThunk();
1230 }
1231 
addLongMapSyms()1232 void ThumbV4PILongThunk::addLongMapSyms() {
1233   addSymbol("$a", STT_NOTYPE, 4, *tsec);
1234   addSymbol("$d", STT_NOTYPE, 16, *tsec);
1235 }
1236 
1237 // Use the long jump which covers a range up to 8MiB.
writeTo(uint8_t * buf)1238 void AVRThunk::writeTo(uint8_t *buf) {
1239   write32(ctx, buf, 0x940c); // jmp func
1240   ctx.target->relocateNoSym(buf, R_AVR_CALL, destination.getVA(ctx));
1241 }
1242 
addSymbols(ThunkSection & isec)1243 void AVRThunk::addSymbols(ThunkSection &isec) {
1244   addSymbol(ctx.saver.save("__AVRThunk_" + destination.getName()), STT_FUNC, 0,
1245             isec);
1246 }
1247 
1248 // Write MIPS LA25 thunk code to call PIC function from the non-PIC one.
writeTo(uint8_t * buf)1249 void MipsThunk::writeTo(uint8_t *buf) {
1250   uint64_t s = destination.getVA(ctx);
1251   write32(ctx, buf, 0x3c190000);                // lui   $25, %hi(func)
1252   write32(ctx, buf + 4, 0x08000000 | (s >> 2)); // j     func
1253   write32(ctx, buf + 8, 0x27390000);            // addiu $25, $25, %lo(func)
1254   write32(ctx, buf + 12, 0x00000000);           // nop
1255   ctx.target->relocateNoSym(buf, R_MIPS_HI16, s);
1256   ctx.target->relocateNoSym(buf + 8, R_MIPS_LO16, s);
1257 }
1258 
addSymbols(ThunkSection & isec)1259 void MipsThunk::addSymbols(ThunkSection &isec) {
1260   addSymbol(ctx.saver.save("__LA25Thunk_" + destination.getName()), STT_FUNC, 0,
1261             isec);
1262 }
1263 
getTargetInputSection() const1264 InputSection *MipsThunk::getTargetInputSection() const {
1265   auto &dr = cast<Defined>(destination);
1266   return dyn_cast<InputSection>(dr.section);
1267 }
1268 
1269 // Write microMIPS R2-R5 LA25 thunk code
1270 // to call PIC function from the non-PIC one.
writeTo(uint8_t * buf)1271 void MicroMipsThunk::writeTo(uint8_t *buf) {
1272   uint64_t s = destination.getVA(ctx);
1273   write16(ctx, buf, 0x41b9);      // lui   $25, %hi(func)
1274   write16(ctx, buf + 4, 0xd400);  // j     func
1275   write16(ctx, buf + 8, 0x3339);  // addiu $25, $25, %lo(func)
1276   write16(ctx, buf + 12, 0x0c00); // nop
1277   ctx.target->relocateNoSym(buf, R_MICROMIPS_HI16, s);
1278   ctx.target->relocateNoSym(buf + 4, R_MICROMIPS_26_S1, s);
1279   ctx.target->relocateNoSym(buf + 8, R_MICROMIPS_LO16, s);
1280 }
1281 
addSymbols(ThunkSection & isec)1282 void MicroMipsThunk::addSymbols(ThunkSection &isec) {
1283   Defined *d =
1284       addSymbol(ctx.saver.save("__microLA25Thunk_" + destination.getName()),
1285                 STT_FUNC, 0, isec);
1286   d->stOther |= STO_MIPS_MICROMIPS;
1287 }
1288 
getTargetInputSection() const1289 InputSection *MicroMipsThunk::getTargetInputSection() const {
1290   auto &dr = cast<Defined>(destination);
1291   return dyn_cast<InputSection>(dr.section);
1292 }
1293 
1294 // Write microMIPS R6 LA25 thunk code
1295 // to call PIC function from the non-PIC one.
writeTo(uint8_t * buf)1296 void MicroMipsR6Thunk::writeTo(uint8_t *buf) {
1297   uint64_t s = destination.getVA(ctx);
1298   uint64_t p = getThunkTargetSym()->getVA(ctx);
1299   write16(ctx, buf, 0x1320);     // lui   $25, %hi(func)
1300   write16(ctx, buf + 4, 0x3339); // addiu $25, $25, %lo(func)
1301   write16(ctx, buf + 8, 0x9400); // bc    func
1302   ctx.target->relocateNoSym(buf, R_MICROMIPS_HI16, s);
1303   ctx.target->relocateNoSym(buf + 4, R_MICROMIPS_LO16, s);
1304   ctx.target->relocateNoSym(buf + 8, R_MICROMIPS_PC26_S1, s - p - 12);
1305 }
1306 
addSymbols(ThunkSection & isec)1307 void MicroMipsR6Thunk::addSymbols(ThunkSection &isec) {
1308   Defined *d =
1309       addSymbol(ctx.saver.save("__microLA25Thunk_" + destination.getName()),
1310                 STT_FUNC, 0, isec);
1311   d->stOther |= STO_MIPS_MICROMIPS;
1312 }
1313 
getTargetInputSection() const1314 InputSection *MicroMipsR6Thunk::getTargetInputSection() const {
1315   auto &dr = cast<Defined>(destination);
1316   return dyn_cast<InputSection>(dr.section);
1317 }
1318 
writePPC32PltCallStub(Ctx & ctx,uint8_t * buf,uint64_t gotPltVA,const InputFile * file,int64_t addend)1319 void elf::writePPC32PltCallStub(Ctx &ctx, uint8_t *buf, uint64_t gotPltVA,
1320                                 const InputFile *file, int64_t addend) {
1321   if (!ctx.arg.isPic) {
1322     write32(ctx, buf + 0, 0x3d600000 | (gotPltVA + 0x8000) >> 16); // lis r11,ha
1323     write32(ctx, buf + 4, 0x816b0000 | (uint16_t)gotPltVA); // lwz r11,l(r11)
1324     write32(ctx, buf + 8, 0x7d6903a6);                      // mtctr r11
1325     write32(ctx, buf + 12, 0x4e800420);                     // bctr
1326     return;
1327   }
1328   uint32_t offset;
1329   if (addend >= 0x8000) {
1330     // The stub loads an address relative to r30 (.got2+Addend). Addend is
1331     // almost always 0x8000. The address of .got2 is different in another object
1332     // file, so a stub cannot be shared.
1333     offset = gotPltVA -
1334              (ctx.in.ppc32Got2->getParent()->getVA() +
1335               (file->ppc32Got2 ? file->ppc32Got2->outSecOff : 0) + addend);
1336   } else {
1337     // The stub loads an address relative to _GLOBAL_OFFSET_TABLE_ (which is
1338     // currently the address of .got).
1339     offset = gotPltVA - ctx.in.got->getVA();
1340   }
1341   uint16_t ha = (offset + 0x8000) >> 16, l = (uint16_t)offset;
1342   if (ha == 0) {
1343     write32(ctx, buf + 0, 0x817e0000 | l); // lwz r11,l(r30)
1344     write32(ctx, buf + 4, 0x7d6903a6);     // mtctr r11
1345     write32(ctx, buf + 8, 0x4e800420);     // bctr
1346     write32(ctx, buf + 12, 0x60000000);    // nop
1347   } else {
1348     write32(ctx, buf + 0, 0x3d7e0000 | ha); // addis r11,r30,ha
1349     write32(ctx, buf + 4, 0x816b0000 | l);  // lwz r11,l(r11)
1350     write32(ctx, buf + 8, 0x7d6903a6);      // mtctr r11
1351     write32(ctx, buf + 12, 0x4e800420);     // bctr
1352   }
1353 }
1354 
writeTo(uint8_t * buf)1355 void PPC32PltCallStub::writeTo(uint8_t *buf) {
1356   writePPC32PltCallStub(ctx, buf, destination.getGotPltVA(ctx), file, addend);
1357 }
1358 
addSymbols(ThunkSection & isec)1359 void PPC32PltCallStub::addSymbols(ThunkSection &isec) {
1360   std::string buf;
1361   raw_string_ostream os(buf);
1362   os << format_hex_no_prefix(addend, 8);
1363   if (!ctx.arg.isPic)
1364     os << ".plt_call32.";
1365   else if (addend >= 0x8000)
1366     os << ".got2.plt_pic32.";
1367   else
1368     os << ".plt_pic32.";
1369   os << destination.getName();
1370   addSymbol(ctx.saver.save(buf), STT_FUNC, 0, isec);
1371 }
1372 
isCompatibleWith(const InputSection & isec,const Relocation & rel) const1373 bool PPC32PltCallStub::isCompatibleWith(const InputSection &isec,
1374                                         const Relocation &rel) const {
1375   return !ctx.arg.isPic || (isec.file == file && rel.addend == addend);
1376 }
1377 
addSymbols(ThunkSection & isec)1378 void PPC32LongThunk::addSymbols(ThunkSection &isec) {
1379   addSymbol(ctx.saver.save("__LongThunk_" + destination.getName()), STT_FUNC, 0,
1380             isec);
1381 }
1382 
writeTo(uint8_t * buf)1383 void PPC32LongThunk::writeTo(uint8_t *buf) {
1384   auto ha = [](uint32_t v) -> uint16_t { return (v + 0x8000) >> 16; };
1385   auto lo = [](uint32_t v) -> uint16_t { return v; };
1386   uint32_t d = destination.getVA(ctx, addend);
1387   if (ctx.arg.isPic) {
1388     uint32_t off = d - (getThunkTargetSym()->getVA(ctx) + 8);
1389     write32(ctx, buf + 0, 0x7c0802a6);            // mflr r12,0
1390     write32(ctx, buf + 4, 0x429f0005);            // bcl r20,r31,.+4
1391     write32(ctx, buf + 8, 0x7d8802a6);            // mtctr r12
1392     write32(ctx, buf + 12, 0x3d8c0000 | ha(off)); // addis r12,r12,off@ha
1393     write32(ctx, buf + 16, 0x398c0000 | lo(off)); // addi r12,r12,off@l
1394     write32(ctx, buf + 20, 0x7c0803a6);           // mtlr r0
1395     buf += 24;
1396   } else {
1397     write32(ctx, buf + 0, 0x3d800000 | ha(d)); // lis r12,d@ha
1398     write32(ctx, buf + 4, 0x398c0000 | lo(d)); // addi r12,r12,d@l
1399     buf += 8;
1400   }
1401   write32(ctx, buf + 0, 0x7d8903a6); // mtctr r12
1402   write32(ctx, buf + 4, 0x4e800420); // bctr
1403 }
1404 
writePPC64LoadAndBranch(Ctx & ctx,uint8_t * buf,int64_t offset)1405 void elf::writePPC64LoadAndBranch(Ctx &ctx, uint8_t *buf, int64_t offset) {
1406   uint16_t offHa = (offset + 0x8000) >> 16;
1407   uint16_t offLo = offset & 0xffff;
1408 
1409   write32(ctx, buf + 0, 0x3d820000 | offHa); // addis r12, r2, OffHa
1410   write32(ctx, buf + 4, 0xe98c0000 | offLo); // ld    r12, OffLo(r12)
1411   write32(ctx, buf + 8, 0x7d8903a6);         // mtctr r12
1412   write32(ctx, buf + 12, 0x4e800420);        // bctr
1413 }
1414 
writeTo(uint8_t * buf)1415 void PPC64PltCallStub::writeTo(uint8_t *buf) {
1416   int64_t offset = destination.getGotPltVA(ctx) - getPPC64TocBase(ctx);
1417   // Save the TOC pointer to the save-slot reserved in the call frame.
1418   write32(ctx, buf + 0, 0xf8410018); // std     r2,24(r1)
1419   writePPC64LoadAndBranch(ctx, buf + 4, offset);
1420 }
1421 
addSymbols(ThunkSection & isec)1422 void PPC64PltCallStub::addSymbols(ThunkSection &isec) {
1423   Defined *s = addSymbol(ctx.saver.save("__plt_" + destination.getName()),
1424                          STT_FUNC, 0, isec);
1425   s->setNeedsTocRestore(true);
1426   s->file = destination.file;
1427 }
1428 
isCompatibleWith(const InputSection & isec,const Relocation & rel) const1429 bool PPC64PltCallStub::isCompatibleWith(const InputSection &isec,
1430                                         const Relocation &rel) const {
1431   return rel.type == R_PPC64_REL24 || rel.type == R_PPC64_REL14;
1432 }
1433 
writeTo(uint8_t * buf)1434 void PPC64R2SaveStub::writeTo(uint8_t *buf) {
1435   const int64_t offset = computeOffset();
1436   write32(ctx, buf + 0, 0xf8410018); // std  r2,24(r1)
1437   // The branch offset needs to fit in 26 bits.
1438   if (getMayUseShortThunk()) {
1439     write32(ctx, buf + 4, 0x48000000 | (offset & 0x03fffffc)); // b    <offset>
1440   } else if (isInt<34>(offset)) {
1441     int nextInstOffset;
1442     uint64_t tocOffset = destination.getVA(ctx) - getPPC64TocBase(ctx);
1443     if (tocOffset >> 16 > 0) {
1444       const uint64_t addi = ADDI_R12_TO_R12_NO_DISP | (tocOffset & 0xffff);
1445       const uint64_t addis =
1446           ADDIS_R12_TO_R2_NO_DISP | ((tocOffset >> 16) & 0xffff);
1447       write32(ctx, buf + 4, addis); // addis r12, r2 , top of offset
1448       write32(ctx, buf + 8, addi);  // addi  r12, r12, bottom of offset
1449       nextInstOffset = 12;
1450     } else {
1451       const uint64_t addi = ADDI_R12_TO_R2_NO_DISP | (tocOffset & 0xffff);
1452       write32(ctx, buf + 4, addi); // addi r12, r2, offset
1453       nextInstOffset = 8;
1454     }
1455     write32(ctx, buf + nextInstOffset, MTCTR_R12); // mtctr r12
1456     write32(ctx, buf + nextInstOffset + 4, BCTR);  // bctr
1457   } else {
1458     ctx.in.ppc64LongBranchTarget->addEntry(&destination, addend);
1459     const int64_t offsetFromTOC =
1460         ctx.in.ppc64LongBranchTarget->getEntryVA(&destination, addend) -
1461         getPPC64TocBase(ctx);
1462     writePPC64LoadAndBranch(ctx, buf + 4, offsetFromTOC);
1463   }
1464 }
1465 
addSymbols(ThunkSection & isec)1466 void PPC64R2SaveStub::addSymbols(ThunkSection &isec) {
1467   Defined *s = addSymbol(ctx.saver.save("__toc_save_" + destination.getName()),
1468                          STT_FUNC, 0, isec);
1469   s->setNeedsTocRestore(true);
1470 }
1471 
isCompatibleWith(const InputSection & isec,const Relocation & rel) const1472 bool PPC64R2SaveStub::isCompatibleWith(const InputSection &isec,
1473                                        const Relocation &rel) const {
1474   return rel.type == R_PPC64_REL24 || rel.type == R_PPC64_REL14;
1475 }
1476 
writeTo(uint8_t * buf)1477 void PPC64R12SetupStub::writeTo(uint8_t *buf) {
1478   int64_t offset =
1479       (gotPlt ? destination.getGotPltVA(ctx) : destination.getVA(ctx)) -
1480       getThunkTargetSym()->getVA(ctx);
1481   if (!isInt<34>(offset))
1482     reportRangeError(ctx, buf, offset, 34, destination,
1483                      "R12 setup stub offset");
1484 
1485   int nextInstOffset;
1486   if (ctx.arg.power10Stubs) {
1487     const uint64_t imm = (((offset >> 16) & 0x3ffff) << 32) | (offset & 0xffff);
1488     // pld 12, func@plt@pcrel or  paddi r12, 0, func@pcrel
1489     writePrefixedInst(ctx, buf,
1490                       (gotPlt ? PLD_R12_NO_DISP : PADDI_R12_NO_DISP) | imm);
1491     nextInstOffset = 8;
1492   } else {
1493     uint32_t off = offset - 8;
1494     write32(ctx, buf + 0, 0x7d8802a6);  // mflr 12
1495     write32(ctx, buf + 4, 0x429f0005);  // bcl 20,31,.+4
1496     write32(ctx, buf + 8, 0x7d6802a6);  // mflr 11
1497     write32(ctx, buf + 12, 0x7d8803a6); // mtlr 12
1498     write32(ctx, buf + 16,
1499             0x3d8b0000 | ((off + 0x8000) >> 16)); // addis 12,11,off@ha
1500     if (gotPlt)
1501       write32(ctx, buf + 20, 0xe98c0000 | (off & 0xffff)); // ld 12, off@l(12)
1502     else
1503       write32(ctx, buf + 20, 0x398c0000 | (off & 0xffff)); // addi 12,12,off@l
1504     nextInstOffset = 24;
1505   }
1506   write32(ctx, buf + nextInstOffset, MTCTR_R12); // mtctr r12
1507   write32(ctx, buf + nextInstOffset + 4, BCTR);  // bctr
1508 }
1509 
addSymbols(ThunkSection & isec)1510 void PPC64R12SetupStub::addSymbols(ThunkSection &isec) {
1511   addSymbol(ctx.saver.save((gotPlt ? "__plt_pcrel_" : "__gep_setup_") +
1512                            destination.getName()),
1513             STT_FUNC, 0, isec);
1514 }
1515 
isCompatibleWith(const InputSection & isec,const Relocation & rel) const1516 bool PPC64R12SetupStub::isCompatibleWith(const InputSection &isec,
1517                                          const Relocation &rel) const {
1518   return rel.type == R_PPC64_REL24_NOTOC;
1519 }
1520 
writeTo(uint8_t * buf)1521 void PPC64LongBranchThunk::writeTo(uint8_t *buf) {
1522   int64_t offset =
1523       ctx.in.ppc64LongBranchTarget->getEntryVA(&destination, addend) -
1524       getPPC64TocBase(ctx);
1525   writePPC64LoadAndBranch(ctx, buf, offset);
1526 }
1527 
addSymbols(ThunkSection & isec)1528 void PPC64LongBranchThunk::addSymbols(ThunkSection &isec) {
1529   addSymbol(ctx.saver.save("__long_branch_" + destination.getName()), STT_FUNC,
1530             0, isec);
1531 }
1532 
isCompatibleWith(const InputSection & isec,const Relocation & rel) const1533 bool PPC64LongBranchThunk::isCompatibleWith(const InputSection &isec,
1534                                             const Relocation &rel) const {
1535   return rel.type == R_PPC64_REL24 || rel.type == R_PPC64_REL14;
1536 }
1537 
1538 // Hexagon Target Thunks
getHexagonThunkDestVA(Ctx & ctx,const Symbol & s,int64_t a)1539 static uint64_t getHexagonThunkDestVA(Ctx &ctx, const Symbol &s, int64_t a) {
1540   uint64_t v = s.isInPlt(ctx) ? s.getPltVA(ctx) : s.getVA(ctx, a);
1541   return SignExtend64<32>(v);
1542 }
1543 
writeTo(uint8_t * buf)1544 void HexagonThunk::writeTo(uint8_t *buf) {
1545   uint64_t s = getHexagonThunkDestVA(ctx, destination, addend);
1546   uint64_t p = getThunkTargetSym()->getVA(ctx);
1547 
1548   if (ctx.arg.isPic) {
1549     write32(ctx, buf + 0, 0x00004000); // {  immext(#0)
1550     ctx.target->relocateNoSym(buf, R_HEX_B32_PCREL_X, s - p);
1551     write32(ctx, buf + 4, 0x6a49c00e); //    r14 = add(pc,##0) }
1552     ctx.target->relocateNoSym(buf + 4, R_HEX_6_PCREL_X, s - p);
1553 
1554     write32(ctx, buf + 8, 0x528ec000); // {  jumpr r14 }
1555   } else {
1556     write32(ctx, buf + 0, 0x00004000); //  { immext
1557     ctx.target->relocateNoSym(buf, R_HEX_B32_PCREL_X, s - p);
1558     write32(ctx, buf + 4, 0x5800c000); //    jump <> }
1559     ctx.target->relocateNoSym(buf + 4, R_HEX_B22_PCREL_X, s - p);
1560   }
1561 }
addSymbols(ThunkSection & isec)1562 void HexagonThunk::addSymbols(ThunkSection &isec) {
1563   Symbol *enclosing = isec.getEnclosingSymbol(relOffset);
1564   StringRef src = enclosing ? enclosing->getName() : isec.name;
1565 
1566   addSymbol(
1567       saver().save("__hexagon_thunk_" + destination.getName() + "_from_" + src),
1568       STT_FUNC, 0, isec);
1569 }
1570 
Thunk(Ctx & ctx,Symbol & d,int64_t a)1571 Thunk::Thunk(Ctx &ctx, Symbol &d, int64_t a)
1572     : ctx(ctx), destination(d), addend(a), offset(0) {
1573   destination.thunkAccessed = true;
1574 }
1575 
1576 Thunk::~Thunk() = default;
1577 
addThunkAArch64(Ctx & ctx,const InputSection & sec,RelType type,Symbol & s,int64_t a)1578 static std::unique_ptr<Thunk> addThunkAArch64(Ctx &ctx, const InputSection &sec,
1579                                               RelType type, Symbol &s,
1580                                               int64_t a) {
1581   assert(is_contained({R_AARCH64_CALL26, R_AARCH64_JUMP26, R_AARCH64_PLT32},
1582                       type));
1583   bool mayNeedLandingPad =
1584       (ctx.arg.andFeatures & GNU_PROPERTY_AARCH64_FEATURE_1_BTI) &&
1585       !isAArch64BTILandingPad(ctx, s, a);
1586   if (ctx.arg.picThunk)
1587     return std::make_unique<AArch64ADRPThunk>(ctx, s, a, mayNeedLandingPad);
1588   if (sec.getParent()->flags & SHF_AARCH64_PURECODE)
1589     return std::make_unique<AArch64ABSXOLongThunk>(ctx, s, a,
1590                                                    mayNeedLandingPad);
1591   return std::make_unique<AArch64ABSLongThunk>(ctx, s, a, mayNeedLandingPad);
1592 }
1593 
1594 // Creates a thunk for long branches or Thumb-ARM interworking.
1595 // Arm Architectures v4t does not support Thumb2 technology, and does not
1596 // support BLX or LDR Arm/Thumb state switching. This means that
1597 // - MOVT and MOVW instructions cannot be used.
1598 // - We can't rewrite BL in place to BLX. We will need thunks.
1599 //
1600 // TODO: use B for short Thumb->Arm thunks instead of LDR (this doesn't work for
1601 //       Arm->Thumb, as in Arm state no BX PC trick; it doesn't switch state).
addThunkArmv4(Ctx & ctx,RelType reloc,Symbol & s,int64_t a)1602 static std::unique_ptr<Thunk> addThunkArmv4(Ctx &ctx, RelType reloc, Symbol &s,
1603                                             int64_t a) {
1604   bool thumb_target = s.getVA(ctx, a) & 1;
1605 
1606   switch (reloc) {
1607   case R_ARM_PC24:
1608   case R_ARM_PLT32:
1609   case R_ARM_JUMP24:
1610   case R_ARM_CALL:
1611     if (ctx.arg.picThunk) {
1612       if (thumb_target)
1613         return std::make_unique<ARMV4PILongBXThunk>(ctx, s, a);
1614       return std::make_unique<ARMV4PILongThunk>(ctx, s, a);
1615     }
1616     if (thumb_target)
1617       return std::make_unique<ARMV4ABSLongBXThunk>(ctx, s, a);
1618     return std::make_unique<ARMV5LongLdrPcThunk>(ctx, s, a);
1619   case R_ARM_THM_CALL:
1620     if (ctx.arg.picThunk) {
1621       if (thumb_target)
1622         return std::make_unique<ThumbV4PILongThunk>(ctx, s, a);
1623       return std::make_unique<ThumbV4PILongBXThunk>(ctx, s, a);
1624     }
1625     if (thumb_target)
1626       return std::make_unique<ThumbV4ABSLongThunk>(ctx, s, a);
1627     return std::make_unique<ThumbV4ABSLongBXThunk>(ctx, s, a);
1628   }
1629   Fatal(ctx) << "relocation " << reloc << " to " << &s
1630              << " not supported for Armv4 or Armv4T target";
1631   llvm_unreachable("");
1632 }
1633 
1634 // Creates a thunk for Thumb-ARM interworking compatible with Armv5 and Armv6.
1635 // Arm Architectures v5 and v6 do not support Thumb2 technology. This means that
1636 // - MOVT and MOVW instructions cannot be used
1637 // - Only Thumb relocation that can generate a Thunk is a BL, this can always
1638 //   be transformed into a BLX
addThunkArmv5v6(Ctx & ctx,RelType reloc,Symbol & s,int64_t a)1639 static std::unique_ptr<Thunk> addThunkArmv5v6(Ctx &ctx, RelType reloc,
1640                                               Symbol &s, int64_t a) {
1641   switch (reloc) {
1642   case R_ARM_PC24:
1643   case R_ARM_PLT32:
1644   case R_ARM_JUMP24:
1645   case R_ARM_CALL:
1646   case R_ARM_THM_CALL:
1647     if (ctx.arg.picThunk)
1648       return std::make_unique<ARMV4PILongBXThunk>(ctx, s, a);
1649     return std::make_unique<ARMV5LongLdrPcThunk>(ctx, s, a);
1650   }
1651   Fatal(ctx) << "relocation " << reloc << " to " << &s
1652              << " not supported for Armv5 or Armv6 targets";
1653   llvm_unreachable("");
1654 }
1655 
1656 // Create a thunk for Thumb long branch on V6-M.
1657 // Arm Architecture v6-M only supports Thumb instructions. This means
1658 // - MOVT and MOVW instructions cannot be used.
1659 // - Only a limited number of instructions can access registers r8 and above
1660 // - No interworking support is needed (all Thumb).
addThunkV6M(Ctx & ctx,const InputSection & isec,RelType reloc,Symbol & s,int64_t a)1661 static std::unique_ptr<Thunk> addThunkV6M(Ctx &ctx, const InputSection &isec,
1662                                           RelType reloc, Symbol &s, int64_t a) {
1663   const bool isPureCode = isec.getParent()->flags & SHF_ARM_PURECODE;
1664   switch (reloc) {
1665   case R_ARM_THM_JUMP19:
1666   case R_ARM_THM_JUMP24:
1667   case R_ARM_THM_CALL:
1668     if (ctx.arg.isPic) {
1669       if (!isPureCode)
1670         return std::make_unique<ThumbV6MPILongThunk>(ctx, s, a);
1671 
1672       Fatal(ctx)
1673           << "relocation " << reloc << " to " << &s
1674           << " not supported for Armv6-M targets for position independent"
1675              " and execute only code";
1676       llvm_unreachable("");
1677     }
1678     if (isPureCode)
1679       return std::make_unique<ThumbV6MABSXOLongThunk>(ctx, s, a);
1680     return std::make_unique<ThumbV6MABSLongThunk>(ctx, s, a);
1681   }
1682   Fatal(ctx) << "relocation " << reloc << " to " << &s
1683              << " not supported for Armv6-M targets";
1684   llvm_unreachable("");
1685 }
1686 
1687 // Creates a thunk for Thumb-ARM interworking or branch range extension.
addThunkArm(Ctx & ctx,const InputSection & isec,RelType reloc,Symbol & s,int64_t a)1688 static std::unique_ptr<Thunk> addThunkArm(Ctx &ctx, const InputSection &isec,
1689                                           RelType reloc, Symbol &s, int64_t a) {
1690   // Decide which Thunk is needed based on:
1691   // Available instruction set
1692   // - An Arm Thunk can only be used if Arm state is available.
1693   // - A Thumb Thunk can only be used if Thumb state is available.
1694   // - Can only use a Thunk if it uses instructions that the Target supports.
1695   // Relocation is branch or branch and link
1696   // - Branch instructions cannot change state, can only select Thunk that
1697   //   starts in the same state as the caller.
1698   // - Branch and link relocations can change state, can select Thunks from
1699   //   either Arm or Thumb.
1700   // Position independent Thunks if we require position independent code.
1701   // Execute Only Thunks if the output section is execute only code.
1702 
1703   // Handle architectures that have restrictions on the instructions that they
1704   // can use in Thunks. The flags below are set by reading the BuildAttributes
1705   // of the input objects. InputFiles.cpp contains the mapping from ARM
1706   // architecture to flag.
1707   if (!ctx.arg.armHasMovtMovw) {
1708     if (ctx.arg.armJ1J2BranchEncoding)
1709       return addThunkV6M(ctx, isec, reloc, s, a);
1710     if (ctx.arg.armHasBlx)
1711       return addThunkArmv5v6(ctx, reloc, s, a);
1712     return addThunkArmv4(ctx, reloc, s, a);
1713   }
1714 
1715   switch (reloc) {
1716   case R_ARM_PC24:
1717   case R_ARM_PLT32:
1718   case R_ARM_JUMP24:
1719   case R_ARM_CALL:
1720     if (ctx.arg.picThunk)
1721       return std::make_unique<ARMV7PILongThunk>(ctx, s, a);
1722     return std::make_unique<ARMV7ABSLongThunk>(ctx, s, a);
1723   case R_ARM_THM_JUMP19:
1724   case R_ARM_THM_JUMP24:
1725   case R_ARM_THM_CALL:
1726     if (ctx.arg.picThunk)
1727       return std::make_unique<ThumbV7PILongThunk>(ctx, s, a);
1728     return std::make_unique<ThumbV7ABSLongThunk>(ctx, s, a);
1729   }
1730   llvm_unreachable("");
1731 }
1732 
addThunkAVR(Ctx & ctx,RelType type,Symbol & s,int64_t a)1733 static std::unique_ptr<Thunk> addThunkAVR(Ctx &ctx, RelType type, Symbol &s,
1734                                           int64_t a) {
1735   switch (type) {
1736   case R_AVR_LO8_LDI_GS:
1737   case R_AVR_HI8_LDI_GS:
1738     return std::make_unique<AVRThunk>(ctx, s, a);
1739   default:
1740     llvm_unreachable("");
1741   }
1742 }
1743 
addThunkHexagon(Ctx & ctx,const InputSection & isec,Relocation & rel,Symbol & s)1744 static std::unique_ptr<Thunk> addThunkHexagon(Ctx &ctx,
1745                                               const InputSection &isec,
1746                                               Relocation &rel, Symbol &s) {
1747   switch (rel.type) {
1748   case R_HEX_B9_PCREL:
1749   case R_HEX_B13_PCREL:
1750   case R_HEX_B15_PCREL:
1751   case R_HEX_B22_PCREL:
1752   case R_HEX_PLT_B22_PCREL:
1753   case R_HEX_GD_PLT_B22_PCREL:
1754     return std::make_unique<HexagonThunk>(ctx, isec, rel, s);
1755   default:
1756     Fatal(ctx) << "unrecognized relocation " << rel.type << " to " << &s
1757                << " for hexagon target";
1758     llvm_unreachable("");
1759   }
1760 }
1761 
addThunkMips(Ctx & ctx,RelType type,Symbol & s)1762 static std::unique_ptr<Thunk> addThunkMips(Ctx &ctx, RelType type, Symbol &s) {
1763   if ((s.stOther & STO_MIPS_MICROMIPS) && isMipsR6(ctx))
1764     return std::make_unique<MicroMipsR6Thunk>(ctx, s);
1765   if (s.stOther & STO_MIPS_MICROMIPS)
1766     return std::make_unique<MicroMipsThunk>(ctx, s);
1767   return std::make_unique<MipsThunk>(ctx, s);
1768 }
1769 
addThunkPPC32(Ctx & ctx,const InputSection & isec,const Relocation & rel,Symbol & s)1770 static std::unique_ptr<Thunk> addThunkPPC32(Ctx &ctx, const InputSection &isec,
1771                                             const Relocation &rel, Symbol &s) {
1772   assert((rel.type == R_PPC_LOCAL24PC || rel.type == R_PPC_REL24 ||
1773           rel.type == R_PPC_PLTREL24) &&
1774          "unexpected relocation type for thunk");
1775   if (s.isInPlt(ctx))
1776     return std::make_unique<PPC32PltCallStub>(ctx, isec, rel, s);
1777   return std::make_unique<PPC32LongThunk>(ctx, s, rel.addend);
1778 }
1779 
addThunkPPC64(Ctx & ctx,RelType type,Symbol & s,int64_t a)1780 static std::unique_ptr<Thunk> addThunkPPC64(Ctx &ctx, RelType type, Symbol &s,
1781                                             int64_t a) {
1782   assert((type == R_PPC64_REL14 || type == R_PPC64_REL24 ||
1783           type == R_PPC64_REL24_NOTOC) &&
1784          "unexpected relocation type for thunk");
1785 
1786   // If we are emitting stubs for NOTOC relocations, we need to tell
1787   // the PLT resolver that there can be multiple TOCs.
1788   if (type == R_PPC64_REL24_NOTOC)
1789     ctx.target->ppc64DynamicSectionOpt = 0x2;
1790 
1791   if (s.isInPlt(ctx)) {
1792     if (type == R_PPC64_REL24_NOTOC)
1793       return std::make_unique<PPC64R12SetupStub>(ctx, s,
1794                                                  /*gotPlt=*/true);
1795     return std::make_unique<PPC64PltCallStub>(ctx, s);
1796   }
1797 
1798   // This check looks at the st_other bits of the callee. If the value is 1
1799   // then the callee clobbers the TOC and we need an R2 save stub when RelType
1800   // is R_PPC64_REL14 or R_PPC64_REL24.
1801   if ((type == R_PPC64_REL14 || type == R_PPC64_REL24) && (s.stOther >> 5) == 1)
1802     return std::make_unique<PPC64R2SaveStub>(ctx, s, a);
1803 
1804   if (type == R_PPC64_REL24_NOTOC)
1805     return std::make_unique<PPC64R12SetupStub>(ctx, s, /*gotPlt=*/false);
1806 
1807   if (ctx.arg.picThunk)
1808     return std::make_unique<PPC64PILongBranchThunk>(ctx, s, a);
1809 
1810   return std::make_unique<PPC64PDLongBranchThunk>(ctx, s, a);
1811 }
1812 
addThunk(Ctx & ctx,const InputSection & isec,Relocation & rel)1813 std::unique_ptr<Thunk> elf::addThunk(Ctx &ctx, const InputSection &isec,
1814                                      Relocation &rel) {
1815   Symbol &s = *rel.sym;
1816   int64_t a = rel.addend;
1817 
1818   switch (ctx.arg.emachine) {
1819   case EM_AARCH64:
1820     return addThunkAArch64(ctx, isec, rel.type, s, a);
1821   case EM_ARM:
1822     return addThunkArm(ctx, isec, rel.type, s, a);
1823   case EM_AVR:
1824     return addThunkAVR(ctx, rel.type, s, a);
1825   case EM_MIPS:
1826     return addThunkMips(ctx, rel.type, s);
1827   case EM_PPC:
1828     return addThunkPPC32(ctx, isec, rel, s);
1829   case EM_PPC64:
1830     return addThunkPPC64(ctx, rel.type, s, a);
1831   case EM_HEXAGON:
1832     return addThunkHexagon(ctx, isec, rel, s);
1833   default:
1834     llvm_unreachable(
1835         "add Thunk only supported for ARM, AVR, Hexagon, Mips and PowerPC");
1836   }
1837 }
1838 
addLandingPadThunk(Ctx & ctx,Symbol & s,int64_t a)1839 std::unique_ptr<Thunk> elf::addLandingPadThunk(Ctx &ctx, Symbol &s, int64_t a) {
1840   switch (ctx.arg.emachine) {
1841   case EM_AARCH64:
1842     return std::make_unique<AArch64BTILandingPadThunk>(ctx, s, a);
1843   default:
1844     llvm_unreachable("add landing pad only supported for AArch64");
1845   }
1846 }
1847