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 §ion) {
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