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