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 // AArch64 long range Thunks compatible with execute-only code. 95 class AArch64ABSXOLongThunk final : public AArch64Thunk { 96 public: 97 AArch64ABSXOLongThunk(Ctx &ctx, Symbol &dest, int64_t addend, 98 bool mayNeedLandingPad) 99 : AArch64Thunk(ctx, dest, addend, mayNeedLandingPad) {} 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: 109 AArch64ADRPThunk(Ctx &ctx, Symbol &dest, int64_t addend, 110 bool mayNeedLandingPad) 111 : AArch64Thunk(ctx, dest, addend, mayNeedLandingPad) {} 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: 126 AArch64BTILandingPadThunk(Ctx &ctx, Symbol &dest, int64_t addend) 127 : Thunk(ctx, dest, addend) {} 128 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: 149 ARMThunk(Ctx &ctx, Symbol &dest, int64_t addend) : Thunk(ctx, dest, addend) {} 150 151 bool getMayUseShortThunk(); 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. 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: 181 ThumbThunk(Ctx &ctx, Symbol &dest, int64_t addend) 182 : Thunk(ctx, dest, addend) { 183 alignment = 2; 184 } 185 186 bool getMayUseShortThunk(); 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. 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: 209 ARMV7ABSLongThunk(Ctx &ctx, Symbol &dest, int64_t addend) 210 : ARMThunk(ctx, dest, addend) {} 211 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: 219 ARMV7PILongThunk(Ctx &ctx, Symbol &dest, int64_t addend) 220 : ARMThunk(ctx, dest, addend) {} 221 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: 229 ThumbV7ABSLongThunk(Ctx &ctx, Symbol &dest, int64_t addend) 230 : ThumbThunk(ctx, dest, addend) {} 231 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: 239 ThumbV7PILongThunk(Ctx &ctx, Symbol &dest, int64_t addend) 240 : ThumbThunk(ctx, dest, addend) {} 241 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: 250 ThumbV6MABSLongThunk(Ctx &ctx, Symbol &dest, int64_t addend) 251 : ThumbThunk(ctx, dest, addend) {} 252 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: 264 ThumbV6MABSXOLongThunk(Ctx &ctx, Symbol &dest, int64_t addend) 265 : ThumbThunk(ctx, dest, addend) {} 266 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: 274 ThumbV6MPILongThunk(Ctx &ctx, Symbol &dest, int64_t addend) 275 : ThumbThunk(ctx, dest, addend) {} 276 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: 296 ARMV5LongLdrPcThunk(Ctx &ctx, Symbol &dest, int64_t addend) 297 : ARMThunk(ctx, dest, addend) {} 298 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: 312 ARMV4PILongBXThunk(Ctx &ctx, Symbol &dest, int64_t addend) 313 : ARMThunk(ctx, dest, addend) {} 314 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: 326 ARMV4PILongThunk(Ctx &ctx, Symbol &dest, int64_t addend) 327 : ARMThunk(ctx, dest, addend) {} 328 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: 340 ThumbV4PILongBXThunk(Ctx &ctx, Symbol &dest, int64_t addend) 341 : ThumbThunk(ctx, dest, addend) {} 342 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: 354 ThumbV4PILongThunk(Ctx &ctx, Symbol &dest, int64_t addend) 355 : ThumbThunk(ctx, dest, addend) {} 356 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: 368 ARMV4ABSLongBXThunk(Ctx &ctx, Symbol &dest, int64_t addend) 369 : ARMThunk(ctx, dest, addend) {} 370 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: 382 ThumbV4ABSLongBXThunk(Ctx &ctx, Symbol &dest, int64_t addend) 383 : ThumbThunk(ctx, dest, addend) {} 384 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: 396 ThumbV4ABSLongThunk(Ctx &ctx, Symbol &dest, int64_t addend) 397 : ThumbThunk(ctx, dest, addend) {} 398 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: 412 AVRThunk(Ctx &ctx, Symbol &dest, int64_t addend) : Thunk(ctx, dest, addend) {} 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: 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; 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: 437 MipsThunk(Ctx &ctx, Symbol &dest) : Thunk(ctx, dest, 0) {} 438 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: 448 MicroMipsThunk(Ctx &ctx, Symbol &dest) : Thunk(ctx, dest, 0) {} 449 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: 459 MicroMipsR6Thunk(Ctx &ctx, Symbol &dest) : Thunk(ctx, dest, 0) {} 460 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. 471 PPC32PltCallStub(Ctx &ctx, const InputSection &isec, const Relocation &rel, 472 Symbol &dest) 473 : Thunk(ctx, dest, rel.addend), file(isec.file) {} 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: 486 PPC32LongThunk(Ctx &ctx, Symbol &dest, int64_t addend) 487 : Thunk(ctx, dest, addend) {} 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: 503 PPC64PltCallStub(Ctx &ctx, Symbol &dest) : Thunk(ctx, dest, 0) {} 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: 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. 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 } 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; 546 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: 557 PPC64R12SetupStub(Ctx &ctx, Symbol &dest, bool gotPlt) 558 : Thunk(ctx, dest, 0), gotPlt(gotPlt) { 559 alignment = 16; 560 } 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: 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: 588 PPC64LongBranchThunk(Ctx &ctx, Symbol &dest, int64_t addend) 589 : Thunk(ctx, dest, addend) {} 590 }; 591 592 class PPC64PILongBranchThunk final : public PPC64LongBranchThunk { 593 public: 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: 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 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 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. 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 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 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 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. 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 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 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 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 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. 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 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 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 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 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 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 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). 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 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 835 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. 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 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 889 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 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 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 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 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 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 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 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 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 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 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 993 void ThumbV6MABSLongThunk::addLongMapSyms() { 994 addSymbol("$d", STT_NOTYPE, 8, *tsec); 995 } 996 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 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 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 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 1053 void ThumbV6MPILongThunk::addLongMapSyms() { 1054 addSymbol("$d", STT_NOTYPE, 12, *tsec); 1055 } 1056 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 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 1072 void ARMV5LongLdrPcThunk::addLongMapSyms() { 1073 addSymbol("$d", STT_NOTYPE, 4, *tsec); 1074 } 1075 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 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 1092 void ARMV4ABSLongBXThunk::addLongMapSyms() { 1093 addSymbol("$d", STT_NOTYPE, 8, *tsec); 1094 } 1095 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 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 1114 void ThumbV4ABSLongBXThunk::addLongMapSyms() { 1115 addSymbol("$a", STT_NOTYPE, 4, *tsec); 1116 addSymbol("$d", STT_NOTYPE, 8, *tsec); 1117 } 1118 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 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 1138 void ThumbV4ABSLongThunk::addLongMapSyms() { 1139 addSymbol("$a", STT_NOTYPE, 4, *tsec); 1140 addSymbol("$d", STT_NOTYPE, 12, *tsec); 1141 } 1142 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 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 1161 void ARMV4PILongBXThunk::addLongMapSyms() { 1162 addSymbol("$d", STT_NOTYPE, 12, *tsec); 1163 } 1164 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 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 1182 void ARMV4PILongThunk::addLongMapSyms() { 1183 addSymbol("$d", STT_NOTYPE, 8, *tsec); 1184 } 1185 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 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 1206 void ThumbV4PILongBXThunk::addLongMapSyms() { 1207 addSymbol("$a", STT_NOTYPE, 4, *tsec); 1208 addSymbol("$d", STT_NOTYPE, 12, *tsec); 1209 } 1210 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 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 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. 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 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. 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 1259 void MipsThunk::addSymbols(ThunkSection &isec) { 1260 addSymbol(ctx.saver.save("__LA25Thunk_" + destination.getName()), STT_FUNC, 0, 1261 isec); 1262 } 1263 1264 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. 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 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 1289 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. 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 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 1314 InputSection *MicroMipsR6Thunk::getTargetInputSection() const { 1315 auto &dr = cast<Defined>(destination); 1316 return dyn_cast<InputSection>(dr.section); 1317 } 1318 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 1355 void PPC32PltCallStub::writeTo(uint8_t *buf) { 1356 writePPC32PltCallStub(ctx, buf, destination.getGotPltVA(ctx), file, addend); 1357 } 1358 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 1373 bool PPC32PltCallStub::isCompatibleWith(const InputSection &isec, 1374 const Relocation &rel) const { 1375 return !ctx.arg.isPic || (isec.file == file && rel.addend == addend); 1376 } 1377 1378 void PPC32LongThunk::addSymbols(ThunkSection &isec) { 1379 addSymbol(ctx.saver.save("__LongThunk_" + destination.getName()), STT_FUNC, 0, 1380 isec); 1381 } 1382 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 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 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 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 1429 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 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 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 1472 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 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 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 1516 bool PPC64R12SetupStub::isCompatibleWith(const InputSection &isec, 1517 const Relocation &rel) const { 1518 return rel.type == R_PPC64_REL24_NOTOC; 1519 } 1520 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 1528 void PPC64LongBranchThunk::addSymbols(ThunkSection &isec) { 1529 addSymbol(ctx.saver.save("__long_branch_" + destination.getName()), STT_FUNC, 1530 0, isec); 1531 } 1532 1533 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 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 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 } 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 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 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). 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 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). 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. 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 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 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 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 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 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 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 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