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 p, 1320 uint64_t gotPltVA, const InputFile *file, 1321 std::optional<int64_t> addend) { 1322 if (!ctx.arg.isPic) { 1323 write32(ctx, buf + 0, 0x3d600000 | (gotPltVA + 0x8000) >> 16); // lis r11,ha 1324 write32(ctx, buf + 4, 0x816b0000 | (uint16_t)gotPltVA); // lwz r11,l(r11) 1325 write32(ctx, buf + 8, 0x7d6903a6); // mtctr r11 1326 write32(ctx, buf + 12, 0x4e800420); // bctr 1327 return; 1328 } 1329 uint32_t offset; 1330 uint32_t reg; 1331 uint64_t written = 0; 1332 if (!addend) { 1333 // We're a (position-independent) IPLT entry, so cannot assume anything 1334 // about what value the caller left in r30 as this could be an indirect 1335 // call. 1336 write32(ctx, buf + 0, 0x7c0802a6); // mflr r0 1337 write32(ctx, buf + 4, 0x429f0005); // bcl 20, 31, 1f 1338 write32(ctx, buf + 8, 0x7d6802a6); // 1: mflr r11 1339 write32(ctx, buf + 12, 0x7c0803a6); // mtlr r0 1340 offset = gotPltVA - p - 8; 1341 reg = 11; 1342 written = 16; 1343 } else if (*addend >= 0x8000) { 1344 // The stub loads an address relative to r30 (.got2+Addend). Addend is 1345 // almost always 0x8000. The address of .got2 is different in another object 1346 // file, so a stub cannot be shared. 1347 reg = 30; 1348 offset = gotPltVA - 1349 (ctx.in.ppc32Got2->getParent()->getVA() + 1350 (file->ppc32Got2 ? file->ppc32Got2->outSecOff : 0) + *addend); 1351 } else { 1352 // The stub loads an address relative to _GLOBAL_OFFSET_TABLE_ (which is 1353 // currently the address of .got). 1354 reg = 30; 1355 offset = gotPltVA - ctx.in.got->getVA(); 1356 } 1357 uint16_t ha = (offset + 0x8000) >> 16, l = (uint16_t)offset; 1358 if (ha == 0) { 1359 write32(ctx, buf + written + 0, 1360 0x81600000 | (reg << 16) | l); // lwz r11,l(r[11|30]) 1361 write32(ctx, buf + written + 4, 0x7d6903a6); // mtctr r11 1362 write32(ctx, buf + written + 8, 0x4e800420); // bctr 1363 write32(ctx, buf + written + 12, 0x60000000); // nop 1364 } else { 1365 write32(ctx, buf + written + 0, 1366 0x3d600000 | (reg << 16) | ha); // addis r11,r[11|30],ha 1367 write32(ctx, buf + written + 4, 0x816b0000 | l); // lwz r11,l(r11) 1368 write32(ctx, buf + written + 8, 0x7d6903a6); // mtctr r11 1369 write32(ctx, buf + written + 12, 0x4e800420); // bctr 1370 } 1371 } 1372 1373 void PPC32PltCallStub::writeTo(uint8_t *buf) { 1374 writePPC32PltCallStub(ctx, buf, getThunkTargetSym()->getVA(ctx), 1375 destination.getGotPltVA(ctx), file, addend); 1376 } 1377 1378 void PPC32PltCallStub::addSymbols(ThunkSection &isec) { 1379 std::string buf; 1380 raw_string_ostream os(buf); 1381 os << format_hex_no_prefix(addend, 8); 1382 if (!ctx.arg.isPic) 1383 os << ".plt_call32."; 1384 else if (addend >= 0x8000) 1385 os << ".got2.plt_pic32."; 1386 else 1387 os << ".plt_pic32."; 1388 os << destination.getName(); 1389 addSymbol(ctx.saver.save(buf), STT_FUNC, 0, isec); 1390 } 1391 1392 bool PPC32PltCallStub::isCompatibleWith(const InputSection &isec, 1393 const Relocation &rel) const { 1394 return !ctx.arg.isPic || (isec.file == file && rel.addend == addend); 1395 } 1396 1397 void PPC32LongThunk::addSymbols(ThunkSection &isec) { 1398 addSymbol(ctx.saver.save("__LongThunk_" + destination.getName()), STT_FUNC, 0, 1399 isec); 1400 } 1401 1402 void PPC32LongThunk::writeTo(uint8_t *buf) { 1403 auto ha = [](uint32_t v) -> uint16_t { return (v + 0x8000) >> 16; }; 1404 auto lo = [](uint32_t v) -> uint16_t { return v; }; 1405 uint32_t d = destination.getVA(ctx, addend); 1406 if (ctx.arg.isPic) { 1407 uint32_t off = d - (getThunkTargetSym()->getVA(ctx) + 8); 1408 write32(ctx, buf + 0, 0x7c0802a6); // mflr r12,0 1409 write32(ctx, buf + 4, 0x429f0005); // bcl r20,r31,.+4 1410 write32(ctx, buf + 8, 0x7d8802a6); // mtctr r12 1411 write32(ctx, buf + 12, 0x3d8c0000 | ha(off)); // addis r12,r12,off@ha 1412 write32(ctx, buf + 16, 0x398c0000 | lo(off)); // addi r12,r12,off@l 1413 write32(ctx, buf + 20, 0x7c0803a6); // mtlr r0 1414 buf += 24; 1415 } else { 1416 write32(ctx, buf + 0, 0x3d800000 | ha(d)); // lis r12,d@ha 1417 write32(ctx, buf + 4, 0x398c0000 | lo(d)); // addi r12,r12,d@l 1418 buf += 8; 1419 } 1420 write32(ctx, buf + 0, 0x7d8903a6); // mtctr r12 1421 write32(ctx, buf + 4, 0x4e800420); // bctr 1422 } 1423 1424 void elf::writePPC64LoadAndBranch(Ctx &ctx, uint8_t *buf, uint64_t p, 1425 uint64_t addr, bool toc) { 1426 uint64_t offset; 1427 uint32_t reg; 1428 if (toc) { 1429 offset = addr - getPPC64TocBase(ctx); 1430 reg = 2; 1431 } else { 1432 offset = addr - p; 1433 reg = 12; 1434 } 1435 uint16_t offHa = (offset + 0x8000) >> 16; 1436 uint16_t offLo = offset & 0xffff; 1437 1438 write32(ctx, buf + 0, 1439 0x3d800000 | (reg << 16) | offHa); // addis r12, r[2|12], OffHa 1440 write32(ctx, buf + 4, 0xe98c0000 | offLo); // ld r12, OffLo(r12) 1441 write32(ctx, buf + 8, 0x7d8903a6); // mtctr r12 1442 write32(ctx, buf + 12, 0x4e800420); // bctr 1443 } 1444 1445 void PPC64PltCallStub::writeTo(uint8_t *buf) { 1446 // Save the TOC pointer to the save-slot reserved in the call frame. 1447 write32(ctx, buf + 0, 0xf8410018); // std r2,24(r1) 1448 writePPC64LoadAndBranch(ctx, buf + 4, getThunkTargetSym()->getVA(ctx) + 4, 1449 destination.getGotPltVA(ctx)); 1450 } 1451 1452 void PPC64PltCallStub::addSymbols(ThunkSection &isec) { 1453 Defined *s = addSymbol(ctx.saver.save("__plt_" + destination.getName()), 1454 STT_FUNC, 0, isec); 1455 s->setNeedsTocRestore(true); 1456 s->file = destination.file; 1457 } 1458 1459 bool PPC64PltCallStub::isCompatibleWith(const InputSection &isec, 1460 const Relocation &rel) const { 1461 return rel.type == R_PPC64_REL24 || rel.type == R_PPC64_REL14; 1462 } 1463 1464 void PPC64R2SaveStub::writeTo(uint8_t *buf) { 1465 const int64_t offset = computeOffset(); 1466 write32(ctx, buf + 0, 0xf8410018); // std r2,24(r1) 1467 // The branch offset needs to fit in 26 bits. 1468 if (getMayUseShortThunk()) { 1469 write32(ctx, buf + 4, 0x48000000 | (offset & 0x03fffffc)); // b <offset> 1470 } else if (isInt<34>(offset)) { 1471 int nextInstOffset; 1472 uint64_t tocOffset = destination.getVA(ctx) - getPPC64TocBase(ctx); 1473 if (tocOffset >> 16 > 0) { 1474 const uint64_t addi = ADDI_R12_TO_R12_NO_DISP | (tocOffset & 0xffff); 1475 const uint64_t addis = 1476 ADDIS_R12_TO_R2_NO_DISP | ((tocOffset >> 16) & 0xffff); 1477 write32(ctx, buf + 4, addis); // addis r12, r2 , top of offset 1478 write32(ctx, buf + 8, addi); // addi r12, r12, bottom of offset 1479 nextInstOffset = 12; 1480 } else { 1481 const uint64_t addi = ADDI_R12_TO_R2_NO_DISP | (tocOffset & 0xffff); 1482 write32(ctx, buf + 4, addi); // addi r12, r2, offset 1483 nextInstOffset = 8; 1484 } 1485 write32(ctx, buf + nextInstOffset, MTCTR_R12); // mtctr r12 1486 write32(ctx, buf + nextInstOffset + 4, BCTR); // bctr 1487 } else { 1488 ctx.in.ppc64LongBranchTarget->addEntry(&destination, addend); 1489 const uint64_t addr = 1490 ctx.in.ppc64LongBranchTarget->getEntryVA(&destination, addend); 1491 writePPC64LoadAndBranch(ctx, buf + 4, getThunkTargetSym()->getVA(ctx) + 4, 1492 addr); 1493 } 1494 } 1495 1496 void PPC64R2SaveStub::addSymbols(ThunkSection &isec) { 1497 Defined *s = addSymbol(ctx.saver.save("__toc_save_" + destination.getName()), 1498 STT_FUNC, 0, isec); 1499 s->setNeedsTocRestore(true); 1500 } 1501 1502 bool PPC64R2SaveStub::isCompatibleWith(const InputSection &isec, 1503 const Relocation &rel) const { 1504 return rel.type == R_PPC64_REL24 || rel.type == R_PPC64_REL14; 1505 } 1506 1507 void PPC64R12SetupStub::writeTo(uint8_t *buf) { 1508 int64_t offset = 1509 (gotPlt ? destination.getGotPltVA(ctx) : destination.getVA(ctx)) - 1510 getThunkTargetSym()->getVA(ctx); 1511 if (!isInt<34>(offset)) 1512 reportRangeError(ctx, buf, offset, 34, destination, 1513 "R12 setup stub offset"); 1514 1515 int nextInstOffset; 1516 if (ctx.arg.power10Stubs) { 1517 const uint64_t imm = (((offset >> 16) & 0x3ffff) << 32) | (offset & 0xffff); 1518 // pld 12, func@plt@pcrel or paddi r12, 0, func@pcrel 1519 writePrefixedInst(ctx, buf, 1520 (gotPlt ? PLD_R12_NO_DISP : PADDI_R12_NO_DISP) | imm); 1521 nextInstOffset = 8; 1522 } else { 1523 uint32_t off = offset - 8; 1524 write32(ctx, buf + 0, 0x7d8802a6); // mflr 12 1525 write32(ctx, buf + 4, 0x429f0005); // bcl 20,31,.+4 1526 write32(ctx, buf + 8, 0x7d6802a6); // mflr 11 1527 write32(ctx, buf + 12, 0x7d8803a6); // mtlr 12 1528 write32(ctx, buf + 16, 1529 0x3d8b0000 | ((off + 0x8000) >> 16)); // addis 12,11,off@ha 1530 if (gotPlt) 1531 write32(ctx, buf + 20, 0xe98c0000 | (off & 0xffff)); // ld 12, off@l(12) 1532 else 1533 write32(ctx, buf + 20, 0x398c0000 | (off & 0xffff)); // addi 12,12,off@l 1534 nextInstOffset = 24; 1535 } 1536 write32(ctx, buf + nextInstOffset, MTCTR_R12); // mtctr r12 1537 write32(ctx, buf + nextInstOffset + 4, BCTR); // bctr 1538 } 1539 1540 void PPC64R12SetupStub::addSymbols(ThunkSection &isec) { 1541 addSymbol(ctx.saver.save((gotPlt ? "__plt_pcrel_" : "__gep_setup_") + 1542 destination.getName()), 1543 STT_FUNC, 0, isec); 1544 } 1545 1546 bool PPC64R12SetupStub::isCompatibleWith(const InputSection &isec, 1547 const Relocation &rel) const { 1548 return rel.type == R_PPC64_REL24_NOTOC; 1549 } 1550 1551 void PPC64LongBranchThunk::writeTo(uint8_t *buf) { 1552 uint64_t addr = 1553 ctx.in.ppc64LongBranchTarget->getEntryVA(&destination, addend); 1554 writePPC64LoadAndBranch(ctx, buf, getThunkTargetSym()->getVA(ctx), addr); 1555 } 1556 1557 void PPC64LongBranchThunk::addSymbols(ThunkSection &isec) { 1558 addSymbol(ctx.saver.save("__long_branch_" + destination.getName()), STT_FUNC, 1559 0, isec); 1560 } 1561 1562 bool PPC64LongBranchThunk::isCompatibleWith(const InputSection &isec, 1563 const Relocation &rel) const { 1564 return rel.type == R_PPC64_REL24 || rel.type == R_PPC64_REL14; 1565 } 1566 1567 // Hexagon Target Thunks 1568 static uint64_t getHexagonThunkDestVA(Ctx &ctx, const Symbol &s, int64_t a) { 1569 uint64_t v = s.isInPlt(ctx) ? s.getPltVA(ctx) : s.getVA(ctx, a); 1570 return SignExtend64<32>(v); 1571 } 1572 1573 void HexagonThunk::writeTo(uint8_t *buf) { 1574 uint64_t s = getHexagonThunkDestVA(ctx, destination, addend); 1575 uint64_t p = getThunkTargetSym()->getVA(ctx); 1576 1577 if (ctx.arg.isPic) { 1578 write32(ctx, buf + 0, 0x00004000); // { immext(#0) 1579 ctx.target->relocateNoSym(buf, R_HEX_B32_PCREL_X, s - p); 1580 write32(ctx, buf + 4, 0x6a49c00e); // r14 = add(pc,##0) } 1581 ctx.target->relocateNoSym(buf + 4, R_HEX_6_PCREL_X, s - p); 1582 1583 write32(ctx, buf + 8, 0x528ec000); // { jumpr r14 } 1584 } else { 1585 write32(ctx, buf + 0, 0x00004000); // { immext 1586 ctx.target->relocateNoSym(buf, R_HEX_B32_PCREL_X, s - p); 1587 write32(ctx, buf + 4, 0x5800c000); // jump <> } 1588 ctx.target->relocateNoSym(buf + 4, R_HEX_B22_PCREL_X, s - p); 1589 } 1590 } 1591 void HexagonThunk::addSymbols(ThunkSection &isec) { 1592 Symbol *enclosing = isec.getEnclosingSymbol(relOffset); 1593 StringRef src = enclosing ? enclosing->getName() : isec.name; 1594 1595 addSymbol( 1596 saver().save("__hexagon_thunk_" + destination.getName() + "_from_" + src), 1597 STT_FUNC, 0, isec); 1598 } 1599 1600 Thunk::Thunk(Ctx &ctx, Symbol &d, int64_t a) 1601 : ctx(ctx), destination(d), addend(a), offset(0) { 1602 destination.thunkAccessed = true; 1603 } 1604 1605 Thunk::~Thunk() = default; 1606 1607 static std::unique_ptr<Thunk> addThunkAArch64(Ctx &ctx, const InputSection &sec, 1608 RelType type, Symbol &s, 1609 int64_t a) { 1610 assert(is_contained({R_AARCH64_CALL26, R_AARCH64_JUMP26, R_AARCH64_PLT32}, 1611 type)); 1612 bool mayNeedLandingPad = 1613 (ctx.arg.andFeatures & GNU_PROPERTY_AARCH64_FEATURE_1_BTI) && 1614 !isAArch64BTILandingPad(ctx, s, a); 1615 if (ctx.arg.picThunk) 1616 return std::make_unique<AArch64ADRPThunk>(ctx, s, a, mayNeedLandingPad); 1617 if (sec.getParent()->flags & SHF_AARCH64_PURECODE) 1618 return std::make_unique<AArch64ABSXOLongThunk>(ctx, s, a, 1619 mayNeedLandingPad); 1620 return std::make_unique<AArch64ABSLongThunk>(ctx, s, a, mayNeedLandingPad); 1621 } 1622 1623 // Creates a thunk for long branches or Thumb-ARM interworking. 1624 // Arm Architectures v4t does not support Thumb2 technology, and does not 1625 // support BLX or LDR Arm/Thumb state switching. This means that 1626 // - MOVT and MOVW instructions cannot be used. 1627 // - We can't rewrite BL in place to BLX. We will need thunks. 1628 // 1629 // TODO: use B for short Thumb->Arm thunks instead of LDR (this doesn't work for 1630 // Arm->Thumb, as in Arm state no BX PC trick; it doesn't switch state). 1631 static std::unique_ptr<Thunk> addThunkArmv4(Ctx &ctx, RelType reloc, Symbol &s, 1632 int64_t a) { 1633 bool thumb_target = s.getVA(ctx, a) & 1; 1634 1635 switch (reloc) { 1636 case R_ARM_PC24: 1637 case R_ARM_PLT32: 1638 case R_ARM_JUMP24: 1639 case R_ARM_CALL: 1640 if (ctx.arg.picThunk) { 1641 if (thumb_target) 1642 return std::make_unique<ARMV4PILongBXThunk>(ctx, s, a); 1643 return std::make_unique<ARMV4PILongThunk>(ctx, s, a); 1644 } 1645 if (thumb_target) 1646 return std::make_unique<ARMV4ABSLongBXThunk>(ctx, s, a); 1647 return std::make_unique<ARMV5LongLdrPcThunk>(ctx, s, a); 1648 case R_ARM_THM_CALL: 1649 if (ctx.arg.picThunk) { 1650 if (thumb_target) 1651 return std::make_unique<ThumbV4PILongThunk>(ctx, s, a); 1652 return std::make_unique<ThumbV4PILongBXThunk>(ctx, s, a); 1653 } 1654 if (thumb_target) 1655 return std::make_unique<ThumbV4ABSLongThunk>(ctx, s, a); 1656 return std::make_unique<ThumbV4ABSLongBXThunk>(ctx, s, a); 1657 } 1658 Fatal(ctx) << "relocation " << reloc << " to " << &s 1659 << " not supported for Armv4 or Armv4T target"; 1660 llvm_unreachable(""); 1661 } 1662 1663 // Creates a thunk for Thumb-ARM interworking compatible with Armv5 and Armv6. 1664 // Arm Architectures v5 and v6 do not support Thumb2 technology. This means that 1665 // - MOVT and MOVW instructions cannot be used 1666 // - Only Thumb relocation that can generate a Thunk is a BL, this can always 1667 // be transformed into a BLX 1668 static std::unique_ptr<Thunk> addThunkArmv5v6(Ctx &ctx, RelType reloc, 1669 Symbol &s, int64_t a) { 1670 switch (reloc) { 1671 case R_ARM_PC24: 1672 case R_ARM_PLT32: 1673 case R_ARM_JUMP24: 1674 case R_ARM_CALL: 1675 case R_ARM_THM_CALL: 1676 if (ctx.arg.picThunk) 1677 return std::make_unique<ARMV4PILongBXThunk>(ctx, s, a); 1678 return std::make_unique<ARMV5LongLdrPcThunk>(ctx, s, a); 1679 } 1680 Fatal(ctx) << "relocation " << reloc << " to " << &s 1681 << " not supported for Armv5 or Armv6 targets"; 1682 llvm_unreachable(""); 1683 } 1684 1685 // Create a thunk for Thumb long branch on V6-M. 1686 // Arm Architecture v6-M only supports Thumb instructions. This means 1687 // - MOVT and MOVW instructions cannot be used. 1688 // - Only a limited number of instructions can access registers r8 and above 1689 // - No interworking support is needed (all Thumb). 1690 static std::unique_ptr<Thunk> addThunkV6M(Ctx &ctx, const InputSection &isec, 1691 RelType reloc, Symbol &s, int64_t a) { 1692 const bool isPureCode = isec.getParent()->flags & SHF_ARM_PURECODE; 1693 switch (reloc) { 1694 case R_ARM_THM_JUMP19: 1695 case R_ARM_THM_JUMP24: 1696 case R_ARM_THM_CALL: 1697 if (ctx.arg.isPic) { 1698 if (!isPureCode) 1699 return std::make_unique<ThumbV6MPILongThunk>(ctx, s, a); 1700 1701 Fatal(ctx) 1702 << "relocation " << reloc << " to " << &s 1703 << " not supported for Armv6-M targets for position independent" 1704 " and execute only code"; 1705 llvm_unreachable(""); 1706 } 1707 if (isPureCode) 1708 return std::make_unique<ThumbV6MABSXOLongThunk>(ctx, s, a); 1709 return std::make_unique<ThumbV6MABSLongThunk>(ctx, s, a); 1710 } 1711 Fatal(ctx) << "relocation " << reloc << " to " << &s 1712 << " not supported for Armv6-M targets"; 1713 llvm_unreachable(""); 1714 } 1715 1716 // Creates a thunk for Thumb-ARM interworking or branch range extension. 1717 static std::unique_ptr<Thunk> addThunkArm(Ctx &ctx, const InputSection &isec, 1718 RelType reloc, Symbol &s, int64_t a) { 1719 // Decide which Thunk is needed based on: 1720 // Available instruction set 1721 // - An Arm Thunk can only be used if Arm state is available. 1722 // - A Thumb Thunk can only be used if Thumb state is available. 1723 // - Can only use a Thunk if it uses instructions that the Target supports. 1724 // Relocation is branch or branch and link 1725 // - Branch instructions cannot change state, can only select Thunk that 1726 // starts in the same state as the caller. 1727 // - Branch and link relocations can change state, can select Thunks from 1728 // either Arm or Thumb. 1729 // Position independent Thunks if we require position independent code. 1730 // Execute Only Thunks if the output section is execute only code. 1731 1732 // Handle architectures that have restrictions on the instructions that they 1733 // can use in Thunks. The flags below are set by reading the BuildAttributes 1734 // of the input objects. InputFiles.cpp contains the mapping from ARM 1735 // architecture to flag. 1736 if (!ctx.arg.armHasMovtMovw) { 1737 if (ctx.arg.armJ1J2BranchEncoding) 1738 return addThunkV6M(ctx, isec, reloc, s, a); 1739 if (ctx.arg.armHasBlx) 1740 return addThunkArmv5v6(ctx, reloc, s, a); 1741 return addThunkArmv4(ctx, reloc, s, a); 1742 } 1743 1744 switch (reloc) { 1745 case R_ARM_PC24: 1746 case R_ARM_PLT32: 1747 case R_ARM_JUMP24: 1748 case R_ARM_CALL: 1749 if (ctx.arg.picThunk) 1750 return std::make_unique<ARMV7PILongThunk>(ctx, s, a); 1751 return std::make_unique<ARMV7ABSLongThunk>(ctx, s, a); 1752 case R_ARM_THM_JUMP19: 1753 case R_ARM_THM_JUMP24: 1754 case R_ARM_THM_CALL: 1755 if (ctx.arg.picThunk) 1756 return std::make_unique<ThumbV7PILongThunk>(ctx, s, a); 1757 return std::make_unique<ThumbV7ABSLongThunk>(ctx, s, a); 1758 } 1759 llvm_unreachable(""); 1760 } 1761 1762 static std::unique_ptr<Thunk> addThunkAVR(Ctx &ctx, RelType type, Symbol &s, 1763 int64_t a) { 1764 switch (type) { 1765 case R_AVR_LO8_LDI_GS: 1766 case R_AVR_HI8_LDI_GS: 1767 return std::make_unique<AVRThunk>(ctx, s, a); 1768 default: 1769 llvm_unreachable(""); 1770 } 1771 } 1772 1773 static std::unique_ptr<Thunk> addThunkHexagon(Ctx &ctx, 1774 const InputSection &isec, 1775 Relocation &rel, Symbol &s) { 1776 switch (rel.type) { 1777 case R_HEX_B9_PCREL: 1778 case R_HEX_B13_PCREL: 1779 case R_HEX_B15_PCREL: 1780 case R_HEX_B22_PCREL: 1781 case R_HEX_PLT_B22_PCREL: 1782 case R_HEX_GD_PLT_B22_PCREL: 1783 return std::make_unique<HexagonThunk>(ctx, isec, rel, s); 1784 default: 1785 Fatal(ctx) << "unrecognized relocation " << rel.type << " to " << &s 1786 << " for hexagon target"; 1787 llvm_unreachable(""); 1788 } 1789 } 1790 1791 static std::unique_ptr<Thunk> addThunkMips(Ctx &ctx, RelType type, Symbol &s) { 1792 if ((s.stOther & STO_MIPS_MICROMIPS) && isMipsR6(ctx)) 1793 return std::make_unique<MicroMipsR6Thunk>(ctx, s); 1794 if (s.stOther & STO_MIPS_MICROMIPS) 1795 return std::make_unique<MicroMipsThunk>(ctx, s); 1796 return std::make_unique<MipsThunk>(ctx, s); 1797 } 1798 1799 static std::unique_ptr<Thunk> addThunkPPC32(Ctx &ctx, const InputSection &isec, 1800 const Relocation &rel, Symbol &s) { 1801 assert((rel.type == R_PPC_LOCAL24PC || rel.type == R_PPC_REL24 || 1802 rel.type == R_PPC_PLTREL24) && 1803 "unexpected relocation type for thunk"); 1804 if (s.isInPlt(ctx)) 1805 return std::make_unique<PPC32PltCallStub>(ctx, isec, rel, s); 1806 return std::make_unique<PPC32LongThunk>(ctx, s, rel.addend); 1807 } 1808 1809 static std::unique_ptr<Thunk> addThunkPPC64(Ctx &ctx, RelType type, Symbol &s, 1810 int64_t a) { 1811 assert((type == R_PPC64_REL14 || type == R_PPC64_REL24 || 1812 type == R_PPC64_REL24_NOTOC) && 1813 "unexpected relocation type for thunk"); 1814 1815 // If we are emitting stubs for NOTOC relocations, we need to tell 1816 // the PLT resolver that there can be multiple TOCs. 1817 if (type == R_PPC64_REL24_NOTOC) 1818 ctx.target->ppc64DynamicSectionOpt = 0x2; 1819 1820 if (s.isInPlt(ctx)) { 1821 if (type == R_PPC64_REL24_NOTOC) 1822 return std::make_unique<PPC64R12SetupStub>(ctx, s, 1823 /*gotPlt=*/true); 1824 return std::make_unique<PPC64PltCallStub>(ctx, s); 1825 } 1826 1827 // This check looks at the st_other bits of the callee. If the value is 1 1828 // then the callee clobbers the TOC and we need an R2 save stub when RelType 1829 // is R_PPC64_REL14 or R_PPC64_REL24. 1830 if ((type == R_PPC64_REL14 || type == R_PPC64_REL24) && (s.stOther >> 5) == 1) 1831 return std::make_unique<PPC64R2SaveStub>(ctx, s, a); 1832 1833 if (type == R_PPC64_REL24_NOTOC) 1834 return std::make_unique<PPC64R12SetupStub>(ctx, s, /*gotPlt=*/false); 1835 1836 if (ctx.arg.picThunk) 1837 return std::make_unique<PPC64PILongBranchThunk>(ctx, s, a); 1838 1839 return std::make_unique<PPC64PDLongBranchThunk>(ctx, s, a); 1840 } 1841 1842 std::unique_ptr<Thunk> elf::addThunk(Ctx &ctx, const InputSection &isec, 1843 Relocation &rel) { 1844 Symbol &s = *rel.sym; 1845 int64_t a = rel.addend; 1846 1847 switch (ctx.arg.emachine) { 1848 case EM_AARCH64: 1849 return addThunkAArch64(ctx, isec, rel.type, s, a); 1850 case EM_ARM: 1851 return addThunkArm(ctx, isec, rel.type, s, a); 1852 case EM_AVR: 1853 return addThunkAVR(ctx, rel.type, s, a); 1854 case EM_MIPS: 1855 return addThunkMips(ctx, rel.type, s); 1856 case EM_PPC: 1857 return addThunkPPC32(ctx, isec, rel, s); 1858 case EM_PPC64: 1859 return addThunkPPC64(ctx, rel.type, s, a); 1860 case EM_HEXAGON: 1861 return addThunkHexagon(ctx, isec, rel, s); 1862 default: 1863 llvm_unreachable( 1864 "add Thunk only supported for ARM, AVR, Hexagon, Mips and PowerPC"); 1865 } 1866 } 1867 1868 std::unique_ptr<Thunk> elf::addLandingPadThunk(Ctx &ctx, Symbol &s, int64_t a) { 1869 switch (ctx.arg.emachine) { 1870 case EM_AARCH64: 1871 return std::make_unique<AArch64BTILandingPadThunk>(ctx, s, a); 1872 default: 1873 llvm_unreachable("add landing pad only supported for AArch64"); 1874 } 1875 } 1876