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 "InputSection.h"
26 #include "OutputSections.h"
27 #include "Symbols.h"
28 #include "SyntheticSections.h"
29 #include "Target.h"
30 #include "lld/Common/ErrorHandler.h"
31 #include "lld/Common/Memory.h"
32 #include "llvm/BinaryFormat/ELF.h"
33 #include "llvm/Support/Casting.h"
34 #include "llvm/Support/Endian.h"
35 #include "llvm/Support/ErrorHandling.h"
36 #include "llvm/Support/MathExtras.h"
37 #include <cstdint>
38 #include <cstring>
39 
40 using namespace llvm;
41 using namespace llvm::object;
42 using namespace llvm::ELF;
43 
44 namespace lld {
45 namespace elf {
46 
47 namespace {
48 
49 // AArch64 long range Thunks
50 class AArch64ABSLongThunk final : public Thunk {
51 public:
52   AArch64ABSLongThunk(Symbol &dest, int64_t addend) : Thunk(dest, addend) {}
53   uint32_t size() override { return 16; }
54   void writeTo(uint8_t *buf) override;
55   void addSymbols(ThunkSection &isec) override;
56 };
57 
58 class AArch64ADRPThunk final : public Thunk {
59 public:
60   AArch64ADRPThunk(Symbol &dest, int64_t addend) : Thunk(dest, addend) {}
61   uint32_t size() override { return 12; }
62   void writeTo(uint8_t *buf) override;
63   void addSymbols(ThunkSection &isec) override;
64 };
65 
66 // Base class for ARM thunks.
67 //
68 // An ARM thunk may be either short or long. A short thunk is simply a branch
69 // (B) instruction, and it may be used to call ARM functions when the distance
70 // from the thunk to the target is less than 32MB. Long thunks can branch to any
71 // virtual address and can switch between ARM and Thumb, and they are
72 // implemented in the derived classes. This class tries to create a short thunk
73 // if the target is in range, otherwise it creates a long thunk.
74 class ARMThunk : public Thunk {
75 public:
76   ARMThunk(Symbol &dest) : Thunk(dest, 0) {}
77 
78   bool getMayUseShortThunk();
79   uint32_t size() override { return getMayUseShortThunk() ? 4 : sizeLong(); }
80   void writeTo(uint8_t *buf) override;
81   bool isCompatibleWith(const InputSection &isec,
82                         const Relocation &rel) const override;
83 
84   // Returns the size of a long thunk.
85   virtual uint32_t sizeLong() = 0;
86 
87   // Writes a long thunk to Buf.
88   virtual void writeLong(uint8_t *buf) = 0;
89 
90 private:
91   // This field tracks whether all previously considered layouts would allow
92   // this thunk to be short. If we have ever needed a long thunk, we always
93   // create a long thunk, even if the thunk may be short given the current
94   // distance to the target. We do this because transitioning from long to short
95   // can create layout oscillations in certain corner cases which would prevent
96   // the layout from converging.
97   bool mayUseShortThunk = true;
98 };
99 
100 // Base class for Thumb-2 thunks.
101 //
102 // This class is similar to ARMThunk, but it uses the Thumb-2 B.W instruction
103 // which has a range of 16MB.
104 class ThumbThunk : public Thunk {
105 public:
106   ThumbThunk(Symbol &dest) : Thunk(dest, 0) { alignment = 2; }
107 
108   bool getMayUseShortThunk();
109   uint32_t size() override { return getMayUseShortThunk() ? 4 : sizeLong(); }
110   void writeTo(uint8_t *buf) override;
111   bool isCompatibleWith(const InputSection &isec,
112                         const Relocation &rel) const override;
113 
114   // Returns the size of a long thunk.
115   virtual uint32_t sizeLong() = 0;
116 
117   // Writes a long thunk to Buf.
118   virtual void writeLong(uint8_t *buf) = 0;
119 
120 private:
121   // See comment in ARMThunk above.
122   bool mayUseShortThunk = true;
123 };
124 
125 // Specific ARM Thunk implementations. The naming convention is:
126 // Source State, TargetState, Target Requirement, ABS or PI, Range
127 class ARMV7ABSLongThunk final : public ARMThunk {
128 public:
129   ARMV7ABSLongThunk(Symbol &dest) : ARMThunk(dest) {}
130 
131   uint32_t sizeLong() override { return 12; }
132   void writeLong(uint8_t *buf) override;
133   void addSymbols(ThunkSection &isec) override;
134 };
135 
136 class ARMV7PILongThunk final : public ARMThunk {
137 public:
138   ARMV7PILongThunk(Symbol &dest) : ARMThunk(dest) {}
139 
140   uint32_t sizeLong() override { return 16; }
141   void writeLong(uint8_t *buf) override;
142   void addSymbols(ThunkSection &isec) override;
143 };
144 
145 class ThumbV7ABSLongThunk final : public ThumbThunk {
146 public:
147   ThumbV7ABSLongThunk(Symbol &dest) : ThumbThunk(dest) {}
148 
149   uint32_t sizeLong() override { return 10; }
150   void writeLong(uint8_t *buf) override;
151   void addSymbols(ThunkSection &isec) override;
152 };
153 
154 class ThumbV7PILongThunk final : public ThumbThunk {
155 public:
156   ThumbV7PILongThunk(Symbol &dest) : ThumbThunk(dest) {}
157 
158   uint32_t sizeLong() override { return 12; }
159   void writeLong(uint8_t *buf) override;
160   void addSymbols(ThunkSection &isec) override;
161 };
162 
163 // Implementations of Thunks for older Arm architectures that do not support
164 // the movt/movw instructions. These thunks require at least Architecture v5
165 // as used on processors such as the Arm926ej-s. There are no Thumb entry
166 // points as there is no Thumb branch instruction on these architecture that
167 // can result in a thunk
168 class ARMV5ABSLongThunk final : public ARMThunk {
169 public:
170   ARMV5ABSLongThunk(Symbol &dest) : ARMThunk(dest) {}
171 
172   uint32_t sizeLong() override { return 8; }
173   void writeLong(uint8_t *buf) override;
174   void addSymbols(ThunkSection &isec) override;
175   bool isCompatibleWith(const InputSection &isec,
176                         const Relocation &rel) const override;
177 };
178 
179 class ARMV5PILongThunk final : public ARMThunk {
180 public:
181   ARMV5PILongThunk(Symbol &dest) : ARMThunk(dest) {}
182 
183   uint32_t sizeLong() override { return 16; }
184   void writeLong(uint8_t *buf) override;
185   void addSymbols(ThunkSection &isec) override;
186   bool isCompatibleWith(const InputSection &isec,
187                         const Relocation &rel) const override;
188 };
189 
190 // Implementations of Thunks for Arm v6-M. Only Thumb instructions are permitted
191 class ThumbV6MABSLongThunk final : public ThumbThunk {
192 public:
193   ThumbV6MABSLongThunk(Symbol &dest) : ThumbThunk(dest) {}
194 
195   uint32_t sizeLong() override { return 12; }
196   void writeLong(uint8_t *buf) override;
197   void addSymbols(ThunkSection &isec) override;
198 };
199 
200 class ThumbV6MPILongThunk final : public ThumbThunk {
201 public:
202   ThumbV6MPILongThunk(Symbol &dest) : ThumbThunk(dest) {}
203 
204   uint32_t sizeLong() override { return 16; }
205   void writeLong(uint8_t *buf) override;
206   void addSymbols(ThunkSection &isec) override;
207 };
208 
209 // MIPS LA25 thunk
210 class MipsThunk final : public Thunk {
211 public:
212   MipsThunk(Symbol &dest) : Thunk(dest, 0) {}
213 
214   uint32_t size() override { return 16; }
215   void writeTo(uint8_t *buf) override;
216   void addSymbols(ThunkSection &isec) override;
217   InputSection *getTargetInputSection() const override;
218 };
219 
220 // microMIPS R2-R5 LA25 thunk
221 class MicroMipsThunk final : public Thunk {
222 public:
223   MicroMipsThunk(Symbol &dest) : Thunk(dest, 0) {}
224 
225   uint32_t size() override { return 14; }
226   void writeTo(uint8_t *buf) override;
227   void addSymbols(ThunkSection &isec) override;
228   InputSection *getTargetInputSection() const override;
229 };
230 
231 // microMIPS R6 LA25 thunk
232 class MicroMipsR6Thunk final : public Thunk {
233 public:
234   MicroMipsR6Thunk(Symbol &dest) : Thunk(dest, 0) {}
235 
236   uint32_t size() override { return 12; }
237   void writeTo(uint8_t *buf) override;
238   void addSymbols(ThunkSection &isec) override;
239   InputSection *getTargetInputSection() const override;
240 };
241 
242 class PPC32PltCallStub final : public Thunk {
243 public:
244   // For R_PPC_PLTREL24, Thunk::addend records the addend which will be used to
245   // decide the offsets in the call stub.
246   PPC32PltCallStub(const InputSection &isec, const Relocation &rel,
247                    Symbol &dest)
248       : Thunk(dest, rel.addend), file(isec.file) {}
249   uint32_t size() override { return 16; }
250   void writeTo(uint8_t *buf) override;
251   void addSymbols(ThunkSection &isec) override;
252   bool isCompatibleWith(const InputSection &isec, const Relocation &rel) const override;
253 
254 private:
255   // Records the call site of the call stub.
256   const InputFile *file;
257 };
258 
259 class PPC32LongThunk final : public Thunk {
260 public:
261   PPC32LongThunk(Symbol &dest, int64_t addend) : Thunk(dest, addend) {}
262   uint32_t size() override { return config->isPic ? 32 : 16; }
263   void writeTo(uint8_t *buf) override;
264   void addSymbols(ThunkSection &isec) override;
265 };
266 
267 // PPC64 Plt call stubs.
268 // Any call site that needs to call through a plt entry needs a call stub in
269 // the .text section. The call stub is responsible for:
270 // 1) Saving the toc-pointer to the stack.
271 // 2) Loading the target functions address from the procedure linkage table into
272 //    r12 for use by the target functions global entry point, and into the count
273 //    register.
274 // 3) Transferring control to the target function through an indirect branch.
275 class PPC64PltCallStub final : public Thunk {
276 public:
277   PPC64PltCallStub(Symbol &dest) : Thunk(dest, 0) {}
278   uint32_t size() override { return 20; }
279   void writeTo(uint8_t *buf) override;
280   void addSymbols(ThunkSection &isec) override;
281 };
282 
283 // A bl instruction uses a signed 24 bit offset, with an implicit 4 byte
284 // alignment. This gives a possible 26 bits of 'reach'. If the call offset is
285 // larger then that we need to emit a long-branch thunk. The target address
286 // of the callee is stored in a table to be accessed TOC-relative. Since the
287 // call must be local (a non-local call will have a PltCallStub instead) the
288 // table stores the address of the callee's local entry point. For
289 // position-independent code a corresponding relative dynamic relocation is
290 // used.
291 class PPC64LongBranchThunk : public Thunk {
292 public:
293   uint32_t size() override { return 16; }
294   void writeTo(uint8_t *buf) override;
295   void addSymbols(ThunkSection &isec) override;
296 
297 protected:
298   PPC64LongBranchThunk(Symbol &dest, int64_t addend) : Thunk(dest, addend) {}
299 };
300 
301 class PPC64PILongBranchThunk final : public PPC64LongBranchThunk {
302 public:
303   PPC64PILongBranchThunk(Symbol &dest, int64_t addend)
304       : PPC64LongBranchThunk(dest, addend) {
305     assert(!dest.isPreemptible);
306     if (Optional<uint32_t> index =
307             in.ppc64LongBranchTarget->addEntry(&dest, addend)) {
308       mainPart->relaDyn->addReloc(
309           {target->relativeRel, in.ppc64LongBranchTarget, *index * UINT64_C(8),
310            true, &dest,
311            addend + getPPC64GlobalEntryToLocalEntryOffset(dest.stOther)});
312     }
313   }
314 };
315 
316 class PPC64PDLongBranchThunk final : public PPC64LongBranchThunk {
317 public:
318   PPC64PDLongBranchThunk(Symbol &dest, int64_t addend)
319       : PPC64LongBranchThunk(dest, addend) {
320     in.ppc64LongBranchTarget->addEntry(&dest, addend);
321   }
322 };
323 
324 } // end anonymous namespace
325 
326 Defined *Thunk::addSymbol(StringRef name, uint8_t type, uint64_t value,
327                           InputSectionBase &section) {
328   Defined *d = addSyntheticLocal(name, type, value, /*size=*/0, section);
329   syms.push_back(d);
330   return d;
331 }
332 
333 void Thunk::setOffset(uint64_t newOffset) {
334   for (Defined *d : syms)
335     d->value = d->value - offset + newOffset;
336   offset = newOffset;
337 }
338 
339 // AArch64 long range Thunks
340 
341 static uint64_t getAArch64ThunkDestVA(const Symbol &s, int64_t a) {
342   uint64_t v = s.isInPlt() ? s.getPltVA() : s.getVA(a);
343   return v;
344 }
345 
346 void AArch64ABSLongThunk::writeTo(uint8_t *buf) {
347   const uint8_t data[] = {
348     0x50, 0x00, 0x00, 0x58, //     ldr x16, L0
349     0x00, 0x02, 0x1f, 0xd6, //     br  x16
350     0x00, 0x00, 0x00, 0x00, // L0: .xword S
351     0x00, 0x00, 0x00, 0x00,
352   };
353   uint64_t s = getAArch64ThunkDestVA(destination, addend);
354   memcpy(buf, data, sizeof(data));
355   target->relocateOne(buf + 8, R_AARCH64_ABS64, s);
356 }
357 
358 void AArch64ABSLongThunk::addSymbols(ThunkSection &isec) {
359   addSymbol(saver.save("__AArch64AbsLongThunk_" + destination.getName()),
360             STT_FUNC, 0, isec);
361   addSymbol("$x", STT_NOTYPE, 0, isec);
362   addSymbol("$d", STT_NOTYPE, 8, isec);
363 }
364 
365 // This Thunk has a maximum range of 4Gb, this is sufficient for all programs
366 // using the small code model, including pc-relative ones. At time of writing
367 // clang and gcc do not support the large code model for position independent
368 // code so it is safe to use this for position independent thunks without
369 // worrying about the destination being more than 4Gb away.
370 void AArch64ADRPThunk::writeTo(uint8_t *buf) {
371   const uint8_t data[] = {
372       0x10, 0x00, 0x00, 0x90, // adrp x16, Dest R_AARCH64_ADR_PREL_PG_HI21(Dest)
373       0x10, 0x02, 0x00, 0x91, // add  x16, x16, R_AARCH64_ADD_ABS_LO12_NC(Dest)
374       0x00, 0x02, 0x1f, 0xd6, // br   x16
375   };
376   uint64_t s = getAArch64ThunkDestVA(destination, addend);
377   uint64_t p = getThunkTargetSym()->getVA();
378   memcpy(buf, data, sizeof(data));
379   target->relocateOne(buf, R_AARCH64_ADR_PREL_PG_HI21,
380                       getAArch64Page(s) - getAArch64Page(p));
381   target->relocateOne(buf + 4, R_AARCH64_ADD_ABS_LO12_NC, s);
382 }
383 
384 void AArch64ADRPThunk::addSymbols(ThunkSection &isec) {
385   addSymbol(saver.save("__AArch64ADRPThunk_" + destination.getName()), STT_FUNC,
386             0, isec);
387   addSymbol("$x", STT_NOTYPE, 0, isec);
388 }
389 
390 // ARM Target Thunks
391 static uint64_t getARMThunkDestVA(const Symbol &s) {
392   uint64_t v = s.isInPlt() ? s.getPltVA() : s.getVA();
393   return SignExtend64<32>(v);
394 }
395 
396 // This function returns true if the target is not Thumb and is within 2^26, and
397 // it has not previously returned false (see comment for mayUseShortThunk).
398 bool ARMThunk::getMayUseShortThunk() {
399   if (!mayUseShortThunk)
400     return false;
401   uint64_t s = getARMThunkDestVA(destination);
402   if (s & 1) {
403     mayUseShortThunk = false;
404     return false;
405   }
406   uint64_t p = getThunkTargetSym()->getVA();
407   int64_t offset = s - p - 8;
408   mayUseShortThunk = llvm::isInt<26>(offset);
409   return mayUseShortThunk;
410 }
411 
412 void ARMThunk::writeTo(uint8_t *buf) {
413   if (!getMayUseShortThunk()) {
414     writeLong(buf);
415     return;
416   }
417 
418   uint64_t s = getARMThunkDestVA(destination);
419   uint64_t p = getThunkTargetSym()->getVA();
420   int64_t offset = s - p - 8;
421   const uint8_t data[] = {
422     0x00, 0x00, 0x00, 0xea, // b S
423   };
424   memcpy(buf, data, sizeof(data));
425   target->relocateOne(buf, R_ARM_JUMP24, offset);
426 }
427 
428 bool ARMThunk::isCompatibleWith(const InputSection &isec,
429                                 const Relocation &rel) const {
430   // Thumb branch relocations can't use BLX
431   return rel.type != R_ARM_THM_JUMP19 && rel.type != R_ARM_THM_JUMP24;
432 }
433 
434 // This function returns true if the target is Thumb and is within 2^25, and
435 // it has not previously returned false (see comment for mayUseShortThunk).
436 bool ThumbThunk::getMayUseShortThunk() {
437   if (!mayUseShortThunk)
438     return false;
439   uint64_t s = getARMThunkDestVA(destination);
440   if ((s & 1) == 0) {
441     mayUseShortThunk = false;
442     return false;
443   }
444   uint64_t p = getThunkTargetSym()->getVA() & ~1;
445   int64_t offset = s - p - 4;
446   mayUseShortThunk = llvm::isInt<25>(offset);
447   return mayUseShortThunk;
448 }
449 
450 void ThumbThunk::writeTo(uint8_t *buf) {
451   if (!getMayUseShortThunk()) {
452     writeLong(buf);
453     return;
454   }
455 
456   uint64_t s = getARMThunkDestVA(destination);
457   uint64_t p = getThunkTargetSym()->getVA();
458   int64_t offset = s - p - 4;
459   const uint8_t data[] = {
460       0x00, 0xf0, 0x00, 0xb0, // b.w S
461   };
462   memcpy(buf, data, sizeof(data));
463   target->relocateOne(buf, R_ARM_THM_JUMP24, offset);
464 }
465 
466 bool ThumbThunk::isCompatibleWith(const InputSection &isec,
467                                   const Relocation &rel) const {
468   // ARM branch relocations can't use BLX
469   return rel.type != R_ARM_JUMP24 && rel.type != R_ARM_PC24 && rel.type != R_ARM_PLT32;
470 }
471 
472 void ARMV7ABSLongThunk::writeLong(uint8_t *buf) {
473   const uint8_t data[] = {
474       0x00, 0xc0, 0x00, 0xe3, // movw         ip,:lower16:S
475       0x00, 0xc0, 0x40, 0xe3, // movt         ip,:upper16:S
476       0x1c, 0xff, 0x2f, 0xe1, // bx   ip
477   };
478   uint64_t s = getARMThunkDestVA(destination);
479   memcpy(buf, data, sizeof(data));
480   target->relocateOne(buf, R_ARM_MOVW_ABS_NC, s);
481   target->relocateOne(buf + 4, R_ARM_MOVT_ABS, s);
482 }
483 
484 void ARMV7ABSLongThunk::addSymbols(ThunkSection &isec) {
485   addSymbol(saver.save("__ARMv7ABSLongThunk_" + destination.getName()),
486             STT_FUNC, 0, isec);
487   addSymbol("$a", STT_NOTYPE, 0, isec);
488 }
489 
490 void ThumbV7ABSLongThunk::writeLong(uint8_t *buf) {
491   const uint8_t data[] = {
492       0x40, 0xf2, 0x00, 0x0c, // movw         ip, :lower16:S
493       0xc0, 0xf2, 0x00, 0x0c, // movt         ip, :upper16:S
494       0x60, 0x47,             // bx   ip
495   };
496   uint64_t s = getARMThunkDestVA(destination);
497   memcpy(buf, data, sizeof(data));
498   target->relocateOne(buf, R_ARM_THM_MOVW_ABS_NC, s);
499   target->relocateOne(buf + 4, R_ARM_THM_MOVT_ABS, s);
500 }
501 
502 void ThumbV7ABSLongThunk::addSymbols(ThunkSection &isec) {
503   addSymbol(saver.save("__Thumbv7ABSLongThunk_" + destination.getName()),
504             STT_FUNC, 1, isec);
505   addSymbol("$t", STT_NOTYPE, 0, isec);
506 }
507 
508 void ARMV7PILongThunk::writeLong(uint8_t *buf) {
509   const uint8_t data[] = {
510       0xf0, 0xcf, 0x0f, 0xe3, // P:  movw ip,:lower16:S - (P + (L1-P) + 8)
511       0x00, 0xc0, 0x40, 0xe3, //     movt ip,:upper16:S - (P + (L1-P) + 8)
512       0x0f, 0xc0, 0x8c, 0xe0, // L1: add  ip, ip, pc
513       0x1c, 0xff, 0x2f, 0xe1, //     bx   ip
514   };
515   uint64_t s = getARMThunkDestVA(destination);
516   uint64_t p = getThunkTargetSym()->getVA();
517   int64_t offset = s - p - 16;
518   memcpy(buf, data, sizeof(data));
519   target->relocateOne(buf, R_ARM_MOVW_PREL_NC, offset);
520   target->relocateOne(buf + 4, R_ARM_MOVT_PREL, offset);
521 }
522 
523 void ARMV7PILongThunk::addSymbols(ThunkSection &isec) {
524   addSymbol(saver.save("__ARMV7PILongThunk_" + destination.getName()), STT_FUNC,
525             0, isec);
526   addSymbol("$a", STT_NOTYPE, 0, isec);
527 }
528 
529 void ThumbV7PILongThunk::writeLong(uint8_t *buf) {
530   const uint8_t data[] = {
531       0x4f, 0xf6, 0xf4, 0x7c, // P:  movw ip,:lower16:S - (P + (L1-P) + 4)
532       0xc0, 0xf2, 0x00, 0x0c, //     movt ip,:upper16:S - (P + (L1-P) + 4)
533       0xfc, 0x44,             // L1: add  ip, pc
534       0x60, 0x47,             //     bx   ip
535   };
536   uint64_t s = getARMThunkDestVA(destination);
537   uint64_t p = getThunkTargetSym()->getVA() & ~0x1;
538   int64_t offset = s - p - 12;
539   memcpy(buf, data, sizeof(data));
540   target->relocateOne(buf, R_ARM_THM_MOVW_PREL_NC, offset);
541   target->relocateOne(buf + 4, R_ARM_THM_MOVT_PREL, offset);
542 }
543 
544 void ThumbV7PILongThunk::addSymbols(ThunkSection &isec) {
545   addSymbol(saver.save("__ThumbV7PILongThunk_" + destination.getName()),
546             STT_FUNC, 1, isec);
547   addSymbol("$t", STT_NOTYPE, 0, isec);
548 }
549 
550 void ARMV5ABSLongThunk::writeLong(uint8_t *buf) {
551   const uint8_t data[] = {
552       0x04, 0xf0, 0x1f, 0xe5, //     ldr pc, [pc,#-4] ; L1
553       0x00, 0x00, 0x00, 0x00, // L1: .word S
554   };
555   memcpy(buf, data, sizeof(data));
556   target->relocateOne(buf + 4, R_ARM_ABS32, getARMThunkDestVA(destination));
557 }
558 
559 void ARMV5ABSLongThunk::addSymbols(ThunkSection &isec) {
560   addSymbol(saver.save("__ARMv5ABSLongThunk_" + destination.getName()),
561             STT_FUNC, 0, isec);
562   addSymbol("$a", STT_NOTYPE, 0, isec);
563   addSymbol("$d", STT_NOTYPE, 4, isec);
564 }
565 
566 bool ARMV5ABSLongThunk::isCompatibleWith(const InputSection &isec,
567                                          const Relocation &rel) const {
568   // Thumb branch relocations can't use BLX
569   return rel.type != R_ARM_THM_JUMP19 && rel.type != R_ARM_THM_JUMP24;
570 }
571 
572 void ARMV5PILongThunk::writeLong(uint8_t *buf) {
573   const uint8_t data[] = {
574       0x04, 0xc0, 0x9f, 0xe5, // P:  ldr ip, [pc,#4] ; L2
575       0x0c, 0xc0, 0x8f, 0xe0, // L1: add ip, pc, ip
576       0x1c, 0xff, 0x2f, 0xe1, //     bx ip
577       0x00, 0x00, 0x00, 0x00, // L2: .word S - (P + (L1 - P) + 8)
578   };
579   uint64_t s = getARMThunkDestVA(destination);
580   uint64_t p = getThunkTargetSym()->getVA() & ~0x1;
581   memcpy(buf, data, sizeof(data));
582   target->relocateOne(buf + 12, R_ARM_REL32, s - p - 12);
583 }
584 
585 void ARMV5PILongThunk::addSymbols(ThunkSection &isec) {
586   addSymbol(saver.save("__ARMV5PILongThunk_" + destination.getName()), STT_FUNC,
587             0, isec);
588   addSymbol("$a", STT_NOTYPE, 0, isec);
589   addSymbol("$d", STT_NOTYPE, 12, isec);
590 }
591 
592 bool ARMV5PILongThunk::isCompatibleWith(const InputSection &isec,
593                                         const Relocation &rel) const {
594   // Thumb branch relocations can't use BLX
595   return rel.type != R_ARM_THM_JUMP19 && rel.type != R_ARM_THM_JUMP24;
596 }
597 
598 void ThumbV6MABSLongThunk::writeLong(uint8_t *buf) {
599   // Most Thumb instructions cannot access the high registers r8 - r15. As the
600   // only register we can corrupt is r12 we must instead spill a low register
601   // to the stack to use as a scratch register. We push r1 even though we
602   // don't need to get some space to use for the return address.
603   const uint8_t data[] = {
604       0x03, 0xb4,            // push {r0, r1} ; Obtain scratch registers
605       0x01, 0x48,            // ldr r0, [pc, #4] ; L1
606       0x01, 0x90,            // str r0, [sp, #4] ; SP + 4 = S
607       0x01, 0xbd,            // pop {r0, pc} ; restore r0 and branch to dest
608       0x00, 0x00, 0x00, 0x00 // L1: .word S
609   };
610   uint64_t s = getARMThunkDestVA(destination);
611   memcpy(buf, data, sizeof(data));
612   target->relocateOne(buf + 8, R_ARM_ABS32, s);
613 }
614 
615 void ThumbV6MABSLongThunk::addSymbols(ThunkSection &isec) {
616   addSymbol(saver.save("__Thumbv6MABSLongThunk_" + destination.getName()),
617             STT_FUNC, 1, isec);
618   addSymbol("$t", STT_NOTYPE, 0, isec);
619   addSymbol("$d", STT_NOTYPE, 8, isec);
620 }
621 
622 void ThumbV6MPILongThunk::writeLong(uint8_t *buf) {
623   // Most Thumb instructions cannot access the high registers r8 - r15. As the
624   // only register we can corrupt is ip (r12) we must instead spill a low
625   // register to the stack to use as a scratch register.
626   const uint8_t data[] = {
627       0x01, 0xb4,             // P:  push {r0}        ; Obtain scratch register
628       0x02, 0x48,             //     ldr r0, [pc, #8] ; L2
629       0x84, 0x46,             //     mov ip, r0       ; high to low register
630       0x01, 0xbc,             //     pop {r0}         ; restore scratch register
631       0xe7, 0x44,             // L1: add pc, ip       ; transfer control
632       0xc0, 0x46,             //     nop              ; pad to 4-byte boundary
633       0x00, 0x00, 0x00, 0x00, // L2: .word S - (P + (L1 - P) + 4)
634   };
635   uint64_t s = getARMThunkDestVA(destination);
636   uint64_t p = getThunkTargetSym()->getVA() & ~0x1;
637   memcpy(buf, data, sizeof(data));
638   target->relocateOne(buf + 12, R_ARM_REL32, s - p - 12);
639 }
640 
641 void ThumbV6MPILongThunk::addSymbols(ThunkSection &isec) {
642   addSymbol(saver.save("__Thumbv6MPILongThunk_" + destination.getName()),
643             STT_FUNC, 1, isec);
644   addSymbol("$t", STT_NOTYPE, 0, isec);
645   addSymbol("$d", STT_NOTYPE, 12, isec);
646 }
647 
648 // Write MIPS LA25 thunk code to call PIC function from the non-PIC one.
649 void MipsThunk::writeTo(uint8_t *buf) {
650   uint64_t s = destination.getVA();
651   write32(buf, 0x3c190000); // lui   $25, %hi(func)
652   write32(buf + 4, 0x08000000 | (s >> 2)); // j     func
653   write32(buf + 8, 0x27390000); // addiu $25, $25, %lo(func)
654   write32(buf + 12, 0x00000000); // nop
655   target->relocateOne(buf, R_MIPS_HI16, s);
656   target->relocateOne(buf + 8, R_MIPS_LO16, s);
657 }
658 
659 void MipsThunk::addSymbols(ThunkSection &isec) {
660   addSymbol(saver.save("__LA25Thunk_" + destination.getName()), STT_FUNC, 0,
661             isec);
662 }
663 
664 InputSection *MipsThunk::getTargetInputSection() const {
665   auto &dr = cast<Defined>(destination);
666   return dyn_cast<InputSection>(dr.section);
667 }
668 
669 // Write microMIPS R2-R5 LA25 thunk code
670 // to call PIC function from the non-PIC one.
671 void MicroMipsThunk::writeTo(uint8_t *buf) {
672   uint64_t s = destination.getVA();
673   write16(buf, 0x41b9);       // lui   $25, %hi(func)
674   write16(buf + 4, 0xd400);   // j     func
675   write16(buf + 8, 0x3339);   // addiu $25, $25, %lo(func)
676   write16(buf + 12, 0x0c00);  // nop
677   target->relocateOne(buf, R_MICROMIPS_HI16, s);
678   target->relocateOne(buf + 4, R_MICROMIPS_26_S1, s);
679   target->relocateOne(buf + 8, R_MICROMIPS_LO16, s);
680 }
681 
682 void MicroMipsThunk::addSymbols(ThunkSection &isec) {
683   Defined *d = addSymbol(
684       saver.save("__microLA25Thunk_" + destination.getName()), STT_FUNC, 0, isec);
685   d->stOther |= STO_MIPS_MICROMIPS;
686 }
687 
688 InputSection *MicroMipsThunk::getTargetInputSection() const {
689   auto &dr = cast<Defined>(destination);
690   return dyn_cast<InputSection>(dr.section);
691 }
692 
693 // Write microMIPS R6 LA25 thunk code
694 // to call PIC function from the non-PIC one.
695 void MicroMipsR6Thunk::writeTo(uint8_t *buf) {
696   uint64_t s = destination.getVA();
697   uint64_t p = getThunkTargetSym()->getVA();
698   write16(buf, 0x1320);       // lui   $25, %hi(func)
699   write16(buf + 4, 0x3339);   // addiu $25, $25, %lo(func)
700   write16(buf + 8, 0x9400);   // bc    func
701   target->relocateOne(buf, R_MICROMIPS_HI16, s);
702   target->relocateOne(buf + 4, R_MICROMIPS_LO16, s);
703   target->relocateOne(buf + 8, R_MICROMIPS_PC26_S1, s - p - 12);
704 }
705 
706 void MicroMipsR6Thunk::addSymbols(ThunkSection &isec) {
707   Defined *d = addSymbol(
708       saver.save("__microLA25Thunk_" + destination.getName()), STT_FUNC, 0, isec);
709   d->stOther |= STO_MIPS_MICROMIPS;
710 }
711 
712 InputSection *MicroMipsR6Thunk::getTargetInputSection() const {
713   auto &dr = cast<Defined>(destination);
714   return dyn_cast<InputSection>(dr.section);
715 }
716 
717 void writePPC32PltCallStub(uint8_t *buf, uint64_t gotPltVA,
718                            const InputFile *file, int64_t addend) {
719   if (!config->isPic) {
720     write32(buf + 0, 0x3d600000 | (gotPltVA + 0x8000) >> 16); // lis r11,ha
721     write32(buf + 4, 0x816b0000 | (uint16_t)gotPltVA);        // lwz r11,l(r11)
722     write32(buf + 8, 0x7d6903a6);                             // mtctr r11
723     write32(buf + 12, 0x4e800420);                            // bctr
724     return;
725   }
726   uint32_t offset;
727   if (addend >= 0x8000) {
728     // The stub loads an address relative to r30 (.got2+Addend). Addend is
729     // almost always 0x8000. The address of .got2 is different in another object
730     // file, so a stub cannot be shared.
731     offset = gotPltVA - (in.ppc32Got2->getParent()->getVA() +
732                          file->ppc32Got2OutSecOff + addend);
733   } else {
734     // The stub loads an address relative to _GLOBAL_OFFSET_TABLE_ (which is
735     // currently the address of .got).
736     offset = gotPltVA - in.got->getVA();
737   }
738   uint16_t ha = (offset + 0x8000) >> 16, l = (uint16_t)offset;
739   if (ha == 0) {
740     write32(buf + 0, 0x817e0000 | l); // lwz r11,l(r30)
741     write32(buf + 4, 0x7d6903a6);     // mtctr r11
742     write32(buf + 8, 0x4e800420);     // bctr
743     write32(buf + 12, 0x60000000);    // nop
744   } else {
745     write32(buf + 0, 0x3d7e0000 | ha); // addis r11,r30,ha
746     write32(buf + 4, 0x816b0000 | l);  // lwz r11,l(r11)
747     write32(buf + 8, 0x7d6903a6);      // mtctr r11
748     write32(buf + 12, 0x4e800420);     // bctr
749   }
750 }
751 
752 void PPC32PltCallStub::writeTo(uint8_t *buf) {
753   writePPC32PltCallStub(buf, destination.getGotPltVA(), file, addend);
754 }
755 
756 void PPC32PltCallStub::addSymbols(ThunkSection &isec) {
757   std::string buf;
758   raw_string_ostream os(buf);
759   os << format_hex_no_prefix(addend, 8);
760   if (!config->isPic)
761     os << ".plt_call32.";
762   else if (addend >= 0x8000)
763     os << ".got2.plt_pic32.";
764   else
765     os << ".plt_pic32.";
766   os << destination.getName();
767   addSymbol(saver.save(os.str()), STT_FUNC, 0, isec);
768 }
769 
770 bool PPC32PltCallStub::isCompatibleWith(const InputSection &isec,
771                                         const Relocation &rel) const {
772   return !config->isPic || (isec.file == file && rel.addend == addend);
773 }
774 
775 void PPC32LongThunk::addSymbols(ThunkSection &isec) {
776   addSymbol(saver.save("__LongThunk_" + destination.getName()), STT_FUNC, 0,
777             isec);
778 }
779 
780 void PPC32LongThunk::writeTo(uint8_t *buf) {
781   auto ha = [](uint32_t v) -> uint16_t { return (v + 0x8000) >> 16; };
782   auto lo = [](uint32_t v) -> uint16_t { return v; };
783   uint32_t d = destination.getVA(addend);
784   if (config->isPic) {
785     uint32_t off = d - (getThunkTargetSym()->getVA() + 8);
786     write32(buf + 0, 0x7c0802a6);            // mflr r12,0
787     write32(buf + 4, 0x429f0005);            // bcl r20,r31,.+4
788     write32(buf + 8, 0x7d8802a6);            // mtctr r12
789     write32(buf + 12, 0x3d8c0000 | ha(off)); // addis r12,r12,off@ha
790     write32(buf + 16, 0x398c0000 | lo(off)); // addi r12,r12,off@l
791     write32(buf + 20, 0x7c0803a6);           // mtlr r0
792     buf += 24;
793   } else {
794     write32(buf + 0, 0x3d800000 | ha(d));    // lis r12,d@ha
795     write32(buf + 4, 0x398c0000 | lo(d));    // addi r12,r12,d@l
796     buf += 8;
797   }
798   write32(buf + 0, 0x7d8903a6);              // mtctr r12
799   write32(buf + 4, 0x4e800420);              // bctr
800 }
801 
802 void writePPC64LoadAndBranch(uint8_t *buf, int64_t offset) {
803   uint16_t offHa = (offset + 0x8000) >> 16;
804   uint16_t offLo = offset & 0xffff;
805 
806   write32(buf + 0, 0x3d820000 | offHa); // addis r12, r2, OffHa
807   write32(buf + 4, 0xe98c0000 | offLo); // ld    r12, OffLo(r12)
808   write32(buf + 8, 0x7d8903a6);         // mtctr r12
809   write32(buf + 12, 0x4e800420);        // bctr
810 }
811 
812 void PPC64PltCallStub::writeTo(uint8_t *buf) {
813   int64_t offset = destination.getGotPltVA() - getPPC64TocBase();
814   // Save the TOC pointer to the save-slot reserved in the call frame.
815   write32(buf + 0, 0xf8410018); // std     r2,24(r1)
816   writePPC64LoadAndBranch(buf + 4, offset);
817 }
818 
819 void PPC64PltCallStub::addSymbols(ThunkSection &isec) {
820   Defined *s = addSymbol(saver.save("__plt_" + destination.getName()), STT_FUNC,
821                          0, isec);
822   s->needsTocRestore = true;
823   s->file = destination.file;
824 }
825 
826 void PPC64LongBranchThunk::writeTo(uint8_t *buf) {
827   int64_t offset = in.ppc64LongBranchTarget->getEntryVA(&destination, addend) -
828                    getPPC64TocBase();
829   writePPC64LoadAndBranch(buf, offset);
830 }
831 
832 void PPC64LongBranchThunk::addSymbols(ThunkSection &isec) {
833   addSymbol(saver.save("__long_branch_" + destination.getName()), STT_FUNC, 0,
834             isec);
835 }
836 
837 Thunk::Thunk(Symbol &d, int64_t a) : destination(d), addend(a), offset(0) {}
838 
839 Thunk::~Thunk() = default;
840 
841 static Thunk *addThunkAArch64(RelType type, Symbol &s, int64_t a) {
842   if (type != R_AARCH64_CALL26 && type != R_AARCH64_JUMP26)
843     fatal("unrecognized relocation type");
844   if (config->picThunk)
845     return make<AArch64ADRPThunk>(s, a);
846   return make<AArch64ABSLongThunk>(s, a);
847 }
848 
849 // Creates a thunk for Thumb-ARM interworking.
850 // Arm Architectures v5 and v6 do not support Thumb2 technology. This means
851 // - MOVT and MOVW instructions cannot be used
852 // - Only Thumb relocation that can generate a Thunk is a BL, this can always
853 //   be transformed into a BLX
854 static Thunk *addThunkPreArmv7(RelType reloc, Symbol &s) {
855   switch (reloc) {
856   case R_ARM_PC24:
857   case R_ARM_PLT32:
858   case R_ARM_JUMP24:
859   case R_ARM_CALL:
860   case R_ARM_THM_CALL:
861     if (config->picThunk)
862       return make<ARMV5PILongThunk>(s);
863     return make<ARMV5ABSLongThunk>(s);
864   }
865   fatal("relocation " + toString(reloc) + " to " + toString(s) +
866         " not supported for Armv5 or Armv6 targets");
867 }
868 
869 // Create a thunk for Thumb long branch on V6-M.
870 // Arm Architecture v6-M only supports Thumb instructions. This means
871 // - MOVT and MOVW instructions cannot be used.
872 // - Only a limited number of instructions can access registers r8 and above
873 // - No interworking support is needed (all Thumb).
874 static Thunk *addThunkV6M(RelType reloc, Symbol &s) {
875   switch (reloc) {
876   case R_ARM_THM_JUMP19:
877   case R_ARM_THM_JUMP24:
878   case R_ARM_THM_CALL:
879     if (config->isPic)
880       return make<ThumbV6MPILongThunk>(s);
881     return make<ThumbV6MABSLongThunk>(s);
882   }
883   fatal("relocation " + toString(reloc) + " to " + toString(s) +
884         " not supported for Armv6-M targets");
885 }
886 
887 // Creates a thunk for Thumb-ARM interworking or branch range extension.
888 static Thunk *addThunkArm(RelType reloc, Symbol &s) {
889   // Decide which Thunk is needed based on:
890   // Available instruction set
891   // - An Arm Thunk can only be used if Arm state is available.
892   // - A Thumb Thunk can only be used if Thumb state is available.
893   // - Can only use a Thunk if it uses instructions that the Target supports.
894   // Relocation is branch or branch and link
895   // - Branch instructions cannot change state, can only select Thunk that
896   //   starts in the same state as the caller.
897   // - Branch and link relocations can change state, can select Thunks from
898   //   either Arm or Thumb.
899   // Position independent Thunks if we require position independent code.
900 
901   // Handle architectures that have restrictions on the instructions that they
902   // can use in Thunks. The flags below are set by reading the BuildAttributes
903   // of the input objects. InputFiles.cpp contains the mapping from ARM
904   // architecture to flag.
905   if (!config->armHasMovtMovw) {
906     if (!config->armJ1J2BranchEncoding)
907       return addThunkPreArmv7(reloc, s);
908     return addThunkV6M(reloc, s);
909   }
910 
911   switch (reloc) {
912   case R_ARM_PC24:
913   case R_ARM_PLT32:
914   case R_ARM_JUMP24:
915   case R_ARM_CALL:
916     if (config->picThunk)
917       return make<ARMV7PILongThunk>(s);
918     return make<ARMV7ABSLongThunk>(s);
919   case R_ARM_THM_JUMP19:
920   case R_ARM_THM_JUMP24:
921   case R_ARM_THM_CALL:
922     if (config->picThunk)
923       return make<ThumbV7PILongThunk>(s);
924     return make<ThumbV7ABSLongThunk>(s);
925   }
926   fatal("unrecognized relocation type");
927 }
928 
929 static Thunk *addThunkMips(RelType type, Symbol &s) {
930   if ((s.stOther & STO_MIPS_MICROMIPS) && isMipsR6())
931     return make<MicroMipsR6Thunk>(s);
932   if (s.stOther & STO_MIPS_MICROMIPS)
933     return make<MicroMipsThunk>(s);
934   return make<MipsThunk>(s);
935 }
936 
937 static Thunk *addThunkPPC32(const InputSection &isec, const Relocation &rel,
938                             Symbol &s) {
939   assert((rel.type == R_PPC_LOCAL24PC || rel.type == R_PPC_REL24 ||
940           rel.type == R_PPC_PLTREL24) &&
941          "unexpected relocation type for thunk");
942   if (s.isInPlt())
943     return make<PPC32PltCallStub>(isec, rel, s);
944   return make<PPC32LongThunk>(s, rel.addend);
945 }
946 
947 static Thunk *addThunkPPC64(RelType type, Symbol &s, int64_t a) {
948   assert(type == R_PPC64_REL24 && "unexpected relocation type for thunk");
949   if (s.isInPlt())
950     return make<PPC64PltCallStub>(s);
951 
952   if (config->picThunk)
953     return make<PPC64PILongBranchThunk>(s, a);
954 
955   return make<PPC64PDLongBranchThunk>(s, a);
956 }
957 
958 Thunk *addThunk(const InputSection &isec, Relocation &rel) {
959   Symbol &s = *rel.sym;
960   int64_t a = rel.addend;
961 
962   if (config->emachine == EM_AARCH64)
963     return addThunkAArch64(rel.type, s, a);
964 
965   if (config->emachine == EM_ARM)
966     return addThunkArm(rel.type, s);
967 
968   if (config->emachine == EM_MIPS)
969     return addThunkMips(rel.type, s);
970 
971   if (config->emachine == EM_PPC)
972     return addThunkPPC32(isec, rel, s);
973 
974   if (config->emachine == EM_PPC64)
975     return addThunkPPC64(rel.type, s, a);
976 
977   llvm_unreachable("add Thunk only supported for ARM, Mips and PowerPC");
978 }
979 
980 } // end namespace elf
981 } // end namespace lld
982