1 //===- Target.cpp ---------------------------------------------------------===// 2 // 3 // The LLVM Linker 4 // 5 // This file is distributed under the University of Illinois Open Source 6 // License. See LICENSE.TXT for details. 7 // 8 //===----------------------------------------------------------------------===// 9 // 10 // Machine-specific things, such as applying relocations, creation of 11 // GOT or PLT entries, etc., are handled in this file. 12 // 13 // Refer the ELF spec for the single letter varaibles, S, A or P, used 14 // in this file. SA is S+A. 15 // 16 //===----------------------------------------------------------------------===// 17 18 #include "Target.h" 19 #include "Error.h" 20 #include "OutputSections.h" 21 #include "Symbols.h" 22 23 #include "llvm/ADT/ArrayRef.h" 24 #include "llvm/Object/ELF.h" 25 #include "llvm/Support/Endian.h" 26 #include "llvm/Support/ELF.h" 27 28 using namespace llvm; 29 using namespace llvm::object; 30 using namespace llvm::support::endian; 31 using namespace llvm::ELF; 32 33 namespace lld { 34 namespace elf2 { 35 36 std::unique_ptr<TargetInfo> Target; 37 38 template <endianness E> static void add32(void *P, int32_t V) { 39 write32<E>(P, read32<E>(P) + V); 40 } 41 42 static void add32le(uint8_t *P, int32_t V) { add32<support::little>(P, V); } 43 static void or32le(uint8_t *P, int32_t V) { write32le(P, read32le(P) | V); } 44 45 template <unsigned N> static void checkInt(int64_t V, uint32_t Type) { 46 if (isInt<N>(V)) 47 return; 48 StringRef S = getELFRelocationTypeName(Config->EMachine, Type); 49 error("Relocation " + S + " out of range"); 50 } 51 52 template <unsigned N> static void checkUInt(uint64_t V, uint32_t Type) { 53 if (isUInt<N>(V)) 54 return; 55 StringRef S = getELFRelocationTypeName(Config->EMachine, Type); 56 error("Relocation " + S + " out of range"); 57 } 58 59 template <unsigned N> static void checkIntUInt(uint64_t V, uint32_t Type) { 60 if (isInt<N>(V) || isUInt<N>(V)) 61 return; 62 StringRef S = getELFRelocationTypeName(Config->EMachine, Type); 63 error("Relocation " + S + " out of range"); 64 } 65 66 template <unsigned N> static void checkAlignment(uint64_t V, uint32_t Type) { 67 if ((V & (N - 1)) == 0) 68 return; 69 StringRef S = getELFRelocationTypeName(Config->EMachine, Type); 70 error("Improper alignment for relocation " + S); 71 } 72 73 namespace { 74 class X86TargetInfo final : public TargetInfo { 75 public: 76 X86TargetInfo(); 77 void writeGotPltHeaderEntries(uint8_t *Buf) const override; 78 unsigned getDynReloc(unsigned Type) const override; 79 bool isTlsDynReloc(unsigned Type) const override; 80 void writeGotPltEntry(uint8_t *Buf, uint64_t Plt) const override; 81 void writePltZeroEntry(uint8_t *Buf, uint64_t GotEntryAddr, 82 uint64_t PltEntryAddr) const override; 83 void writePltEntry(uint8_t *Buf, uint64_t GotAddr, uint64_t GotEntryAddr, 84 uint64_t PltEntryAddr, int32_t Index, 85 unsigned RelOff) const override; 86 bool relocNeedsCopy(uint32_t Type, const SymbolBody &S) const override; 87 bool relocNeedsGot(uint32_t Type, const SymbolBody &S) const override; 88 bool relocNeedsPlt(uint32_t Type, const SymbolBody &S) const override; 89 void relocateOne(uint8_t *Loc, uint8_t *BufEnd, uint32_t Type, uint64_t P, 90 uint64_t SA, uint8_t *PairedLoc = nullptr) const override; 91 }; 92 93 class X86_64TargetInfo final : public TargetInfo { 94 public: 95 X86_64TargetInfo(); 96 unsigned getPltRefReloc(unsigned Type) const override; 97 bool isTlsDynReloc(unsigned Type) const override; 98 void writeGotPltHeaderEntries(uint8_t *Buf) const override; 99 void writeGotPltEntry(uint8_t *Buf, uint64_t Plt) const override; 100 void writePltZeroEntry(uint8_t *Buf, uint64_t GotEntryAddr, 101 uint64_t PltEntryAddr) const override; 102 void writePltEntry(uint8_t *Buf, uint64_t GotAddr, uint64_t GotEntryAddr, 103 uint64_t PltEntryAddr, int32_t Index, 104 unsigned RelOff) const override; 105 bool relocNeedsCopy(uint32_t Type, const SymbolBody &S) const override; 106 bool relocNeedsGot(uint32_t Type, const SymbolBody &S) const override; 107 bool relocNeedsPlt(uint32_t Type, const SymbolBody &S) const override; 108 void relocateOne(uint8_t *Loc, uint8_t *BufEnd, uint32_t Type, uint64_t P, 109 uint64_t SA, uint8_t *PairedLoc = nullptr) const override; 110 bool isRelRelative(uint32_t Type) const override; 111 bool isTlsOptimized(unsigned Type, const SymbolBody *S) const override; 112 unsigned relocateTlsOptimize(uint8_t *Loc, uint8_t *BufEnd, uint32_t Type, 113 uint64_t P, uint64_t SA, 114 const SymbolBody &S) const override; 115 116 private: 117 void relocateTlsLdToLe(uint8_t *Loc, uint8_t *BufEnd, uint64_t P, 118 uint64_t SA) const; 119 void relocateTlsGdToLe(uint8_t *Loc, uint8_t *BufEnd, uint64_t P, 120 uint64_t SA) const; 121 void relocateTlsGdToIe(uint8_t *Loc, uint8_t *BufEnd, uint64_t P, 122 uint64_t SA) const; 123 void relocateTlsIeToLe(uint8_t *Loc, uint8_t *BufEnd, uint64_t P, 124 uint64_t SA) const; 125 }; 126 127 class PPC64TargetInfo final : public TargetInfo { 128 public: 129 PPC64TargetInfo(); 130 void writeGotPltEntry(uint8_t *Buf, uint64_t Plt) const override; 131 void writePltZeroEntry(uint8_t *Buf, uint64_t GotEntryAddr, 132 uint64_t PltEntryAddr) const override; 133 void writePltEntry(uint8_t *Buf, uint64_t GotAddr, uint64_t GotEntryAddr, 134 uint64_t PltEntryAddr, int32_t Index, 135 unsigned RelOff) const override; 136 bool relocNeedsGot(uint32_t Type, const SymbolBody &S) const override; 137 bool relocNeedsPlt(uint32_t Type, const SymbolBody &S) const override; 138 void relocateOne(uint8_t *Loc, uint8_t *BufEnd, uint32_t Type, uint64_t P, 139 uint64_t SA, uint8_t *PairedLoc = nullptr) const override; 140 bool isRelRelative(uint32_t Type) const override; 141 }; 142 143 class AArch64TargetInfo final : public TargetInfo { 144 public: 145 AArch64TargetInfo(); 146 unsigned getPltRefReloc(unsigned Type) const override; 147 void writeGotPltEntry(uint8_t *Buf, uint64_t Plt) const override; 148 void writePltZeroEntry(uint8_t *Buf, uint64_t GotEntryAddr, 149 uint64_t PltEntryAddr) const override; 150 void writePltEntry(uint8_t *Buf, uint64_t GotAddr, uint64_t GotEntryAddr, 151 uint64_t PltEntryAddr, int32_t Index, 152 unsigned RelOff) const override; 153 bool relocNeedsCopy(uint32_t Type, const SymbolBody &S) const override; 154 bool relocNeedsGot(uint32_t Type, const SymbolBody &S) const override; 155 bool relocNeedsPlt(uint32_t Type, const SymbolBody &S) const override; 156 void relocateOne(uint8_t *Loc, uint8_t *BufEnd, uint32_t Type, uint64_t P, 157 uint64_t SA, uint8_t *PairedLoc = nullptr) const override; 158 }; 159 160 template <class ELFT> class MipsTargetInfo final : public TargetInfo { 161 public: 162 MipsTargetInfo(); 163 void writeGotHeaderEntries(uint8_t *Buf) const override; 164 void writeGotPltEntry(uint8_t *Buf, uint64_t Plt) const override; 165 void writePltZeroEntry(uint8_t *Buf, uint64_t GotEntryAddr, 166 uint64_t PltEntryAddr) const override; 167 void writePltEntry(uint8_t *Buf, uint64_t GotAddr, uint64_t GotEntryAddr, 168 uint64_t PltEntryAddr, int32_t Index, 169 unsigned RelOff) const override; 170 bool relocNeedsGot(uint32_t Type, const SymbolBody &S) const override; 171 bool relocNeedsPlt(uint32_t Type, const SymbolBody &S) const override; 172 void relocateOne(uint8_t *Loc, uint8_t *BufEnd, uint32_t Type, uint64_t P, 173 uint64_t SA, uint8_t *PairedLoc = nullptr) const override; 174 }; 175 } // anonymous namespace 176 177 TargetInfo *createTarget() { 178 switch (Config->EMachine) { 179 case EM_386: 180 return new X86TargetInfo(); 181 case EM_AARCH64: 182 return new AArch64TargetInfo(); 183 case EM_MIPS: 184 switch (Config->EKind) { 185 case ELF32LEKind: 186 return new MipsTargetInfo<ELF32LE>(); 187 case ELF32BEKind: 188 return new MipsTargetInfo<ELF32BE>(); 189 default: 190 error("Unsupported MIPS target"); 191 } 192 case EM_PPC64: 193 return new PPC64TargetInfo(); 194 case EM_X86_64: 195 return new X86_64TargetInfo(); 196 } 197 error("Unknown target machine"); 198 } 199 200 TargetInfo::~TargetInfo() {} 201 202 bool TargetInfo::isTlsOptimized(unsigned Type, const SymbolBody *S) const { 203 return false; 204 } 205 206 uint64_t TargetInfo::getVAStart() const { return Config->Shared ? 0 : VAStart; } 207 208 bool TargetInfo::relocNeedsCopy(uint32_t Type, const SymbolBody &S) const { 209 return false; 210 } 211 212 unsigned TargetInfo::getPltRefReloc(unsigned Type) const { return PCRelReloc; } 213 214 bool TargetInfo::isRelRelative(uint32_t Type) const { return true; } 215 216 unsigned TargetInfo::relocateTlsOptimize(uint8_t *Loc, uint8_t *BufEnd, 217 uint32_t Type, uint64_t P, uint64_t SA, 218 const SymbolBody &S) const { 219 return 0; 220 } 221 222 void TargetInfo::writeGotHeaderEntries(uint8_t *Buf) const {} 223 224 void TargetInfo::writeGotPltHeaderEntries(uint8_t *Buf) const {} 225 226 X86TargetInfo::X86TargetInfo() { 227 CopyReloc = R_386_COPY; 228 PCRelReloc = R_386_PC32; 229 GotReloc = R_386_GLOB_DAT; 230 PltReloc = R_386_JUMP_SLOT; 231 TlsGotReloc = R_386_TLS_TPOFF; 232 TlsGlobalDynamicReloc = R_386_TLS_GD; 233 TlsLocalDynamicReloc = R_386_TLS_LDM; 234 TlsModuleIndexReloc = R_386_TLS_DTPMOD32; 235 TlsOffsetReloc = R_386_TLS_DTPOFF32; 236 LazyRelocations = true; 237 PltEntrySize = 16; 238 PltZeroEntrySize = 16; 239 } 240 241 void X86TargetInfo::writeGotPltHeaderEntries(uint8_t *Buf) const { 242 write32le(Buf, Out<ELF32LE>::Dynamic->getVA()); 243 } 244 245 void X86TargetInfo::writeGotPltEntry(uint8_t *Buf, uint64_t Plt) const { 246 // Skip 6 bytes of "pushl (GOT+4)" 247 write32le(Buf, Plt + 6); 248 } 249 250 unsigned X86TargetInfo::getDynReloc(unsigned Type) const { 251 if (Type == R_386_TLS_LE) 252 return R_386_TLS_TPOFF; 253 if (Type == R_386_TLS_LE_32) 254 return R_386_TLS_TPOFF32; 255 return Type; 256 } 257 258 bool X86TargetInfo::isTlsDynReloc(unsigned Type) const { 259 if (Type == R_386_TLS_LE || Type == R_386_TLS_LE_32 || 260 Type == R_386_TLS_GOTIE) 261 return Config->Shared; 262 return false; 263 } 264 265 void X86TargetInfo::writePltZeroEntry(uint8_t *Buf, uint64_t GotEntryAddr, 266 uint64_t PltEntryAddr) const { 267 // Executable files and shared object files have 268 // separate procedure linkage tables. 269 if (Config->Shared) { 270 const uint8_t V[] = { 271 0xff, 0xb3, 0x04, 0x00, 0x00, 0x00, // pushl 4(%ebx 272 0xff, 0xa3, 0x08, 0x00, 0x00, 0x00, // jmp *8(%ebx) 273 0x90, 0x90, 0x90, 0x90 // nop;nop;nop;nop 274 }; 275 memcpy(Buf, V, sizeof(V)); 276 return; 277 } 278 279 const uint8_t PltData[] = { 280 0xff, 0x35, 0x00, 0x00, 0x00, 0x00, // pushl (GOT+4) 281 0xff, 0x25, 0x00, 0x00, 0x00, 0x00, // jmp *(GOT+8) 282 0x90, 0x90, 0x90, 0x90 // nop;nop;nop;nop 283 }; 284 memcpy(Buf, PltData, sizeof(PltData)); 285 write32le(Buf + 2, GotEntryAddr + 4); // GOT+4 286 write32le(Buf + 8, GotEntryAddr + 8); // GOT+8 287 } 288 289 void X86TargetInfo::writePltEntry(uint8_t *Buf, uint64_t GotAddr, 290 uint64_t GotEntryAddr, uint64_t PltEntryAddr, 291 int32_t Index, unsigned RelOff) const { 292 const uint8_t Inst[] = { 293 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, // jmp *foo_in_GOT|*foo@GOT(%ebx) 294 0x68, 0x00, 0x00, 0x00, 0x00, // pushl $reloc_offset 295 0xe9, 0x00, 0x00, 0x00, 0x00 // jmp .PLT0@PC 296 }; 297 memcpy(Buf, Inst, sizeof(Inst)); 298 // jmp *foo@GOT(%ebx) or jmp *foo_in_GOT 299 Buf[1] = Config->Shared ? 0xa3 : 0x25; 300 write32le(Buf + 2, Config->Shared ? (GotEntryAddr - GotAddr) : GotEntryAddr); 301 write32le(Buf + 7, RelOff); 302 write32le(Buf + 12, -Index * PltEntrySize - PltZeroEntrySize - 16); 303 } 304 305 bool X86TargetInfo::relocNeedsCopy(uint32_t Type, const SymbolBody &S) const { 306 if (Type == R_386_32 || Type == R_386_16 || Type == R_386_8) 307 if (auto *SS = dyn_cast<SharedSymbol<ELF32LE>>(&S)) 308 return SS->Sym.getType() == STT_OBJECT; 309 return false; 310 } 311 312 bool X86TargetInfo::relocNeedsGot(uint32_t Type, const SymbolBody &S) const { 313 return Type == R_386_TLS_GOTIE || Type == R_386_GOT32 || 314 relocNeedsPlt(Type, S); 315 } 316 317 bool X86TargetInfo::relocNeedsPlt(uint32_t Type, const SymbolBody &S) const { 318 return Type == R_386_PLT32 || (Type == R_386_PC32 && S.isShared()); 319 } 320 321 void X86TargetInfo::relocateOne(uint8_t *Loc, uint8_t *BufEnd, uint32_t Type, 322 uint64_t P, uint64_t SA, 323 uint8_t *PairedLoc) const { 324 switch (Type) { 325 case R_386_32: 326 add32le(Loc, SA); 327 break; 328 case R_386_GOT32: 329 add32le(Loc, SA - Out<ELF32LE>::Got->getVA()); 330 break; 331 case R_386_GOTPC: 332 add32le(Loc, SA + Out<ELF32LE>::Got->getVA() - P); 333 break; 334 case R_386_PC32: 335 add32le(Loc, SA - P); 336 break; 337 case R_386_TLS_GD: 338 case R_386_TLS_LDM: 339 case R_386_TLS_TPOFF: { 340 uint64_t V = SA - Out<ELF32LE>::Got->getVA() - 341 Out<ELF32LE>::Got->getNumEntries() * 4; 342 checkInt<32>(V, Type); 343 write32le(Loc, V); 344 break; 345 } 346 case R_386_TLS_LDO_32: 347 write32le(Loc, SA); 348 break; 349 case R_386_TLS_LE: 350 write32le(Loc, SA - Out<ELF32LE>::TlsPhdr->p_memsz); 351 break; 352 case R_386_TLS_LE_32: 353 write32le(Loc, Out<ELF32LE>::TlsPhdr->p_memsz - SA); 354 break; 355 default: 356 error("unrecognized reloc " + Twine(Type)); 357 } 358 } 359 360 X86_64TargetInfo::X86_64TargetInfo() { 361 CopyReloc = R_X86_64_COPY; 362 PCRelReloc = R_X86_64_PC32; 363 GotReloc = R_X86_64_GLOB_DAT; 364 PltReloc = R_X86_64_JUMP_SLOT; 365 RelativeReloc = R_X86_64_RELATIVE; 366 TlsGotReloc = R_X86_64_TPOFF64; 367 TlsLocalDynamicReloc = R_X86_64_TLSLD; 368 TlsGlobalDynamicReloc = R_X86_64_TLSGD; 369 TlsModuleIndexReloc = R_X86_64_DTPMOD64; 370 TlsOffsetReloc = R_X86_64_DTPOFF64; 371 LazyRelocations = true; 372 PltEntrySize = 16; 373 PltZeroEntrySize = 16; 374 } 375 376 void X86_64TargetInfo::writeGotPltHeaderEntries(uint8_t *Buf) const { 377 write64le(Buf, Out<ELF64LE>::Dynamic->getVA()); 378 } 379 380 void X86_64TargetInfo::writeGotPltEntry(uint8_t *Buf, uint64_t Plt) const { 381 // Skip 6 bytes of "jmpq *got(%rip)" 382 write32le(Buf, Plt + 6); 383 } 384 385 void X86_64TargetInfo::writePltZeroEntry(uint8_t *Buf, uint64_t GotEntryAddr, 386 uint64_t PltEntryAddr) const { 387 const uint8_t PltData[] = { 388 0xff, 0x35, 0x00, 0x00, 0x00, 0x00, // pushq GOT+8(%rip) 389 0xff, 0x25, 0x00, 0x00, 0x00, 0x00, // jmp *GOT+16(%rip) 390 0x0f, 0x1f, 0x40, 0x00 // nopl 0x0(rax) 391 }; 392 memcpy(Buf, PltData, sizeof(PltData)); 393 write32le(Buf + 2, GotEntryAddr - PltEntryAddr + 2); // GOT+8 394 write32le(Buf + 8, GotEntryAddr - PltEntryAddr + 4); // GOT+16 395 } 396 397 void X86_64TargetInfo::writePltEntry(uint8_t *Buf, uint64_t GotAddr, 398 uint64_t GotEntryAddr, 399 uint64_t PltEntryAddr, int32_t Index, 400 unsigned RelOff) const { 401 const uint8_t Inst[] = { 402 0xff, 0x25, 0x00, 0x00, 0x00, 0x00, // jmpq *got(%rip) 403 0x68, 0x00, 0x00, 0x00, 0x00, // pushq <relocation index> 404 0xe9, 0x00, 0x00, 0x00, 0x00 // jmpq plt[0] 405 }; 406 memcpy(Buf, Inst, sizeof(Inst)); 407 408 write32le(Buf + 2, GotEntryAddr - PltEntryAddr - 6); 409 write32le(Buf + 7, Index); 410 write32le(Buf + 12, -Index * PltEntrySize - PltZeroEntrySize - 16); 411 } 412 413 bool X86_64TargetInfo::relocNeedsCopy(uint32_t Type, 414 const SymbolBody &S) const { 415 if (Type == R_X86_64_32S || Type == R_X86_64_32 || Type == R_X86_64_PC32 || 416 Type == R_X86_64_64) 417 if (auto *SS = dyn_cast<SharedSymbol<ELF64LE>>(&S)) 418 return SS->Sym.getType() == STT_OBJECT; 419 return false; 420 } 421 422 bool X86_64TargetInfo::relocNeedsGot(uint32_t Type, const SymbolBody &S) const { 423 if (Type == R_X86_64_TLSGD) 424 return Target->isTlsOptimized(Type, &S) && canBePreempted(&S, true); 425 if (Type == R_X86_64_GOTTPOFF) 426 return !isTlsOptimized(Type, &S); 427 return Type == R_X86_64_GOTPCREL || relocNeedsPlt(Type, S); 428 } 429 430 bool X86_64TargetInfo::isTlsDynReloc(unsigned Type) const { 431 return Type == R_X86_64_GOTTPOFF || Type == R_X86_64_TLSGD; 432 } 433 434 unsigned X86_64TargetInfo::getPltRefReloc(unsigned Type) const { 435 if (Type == R_X86_64_PLT32) 436 return R_X86_64_PC32; 437 return Type; 438 } 439 440 bool X86_64TargetInfo::relocNeedsPlt(uint32_t Type, const SymbolBody &S) const { 441 if (relocNeedsCopy(Type, S)) 442 return false; 443 444 switch (Type) { 445 default: 446 return false; 447 case R_X86_64_32: 448 case R_X86_64_64: 449 case R_X86_64_PC32: 450 // This relocation is defined to have a value of (S + A - P). 451 // The problems start when a non PIC program calls a function in a shared 452 // library. 453 // In an ideal world, we could just report an error saying the relocation 454 // can overflow at runtime. 455 // In the real world with glibc, crt1.o has a R_X86_64_PC32 pointing to 456 // libc.so. 457 // 458 // The general idea on how to handle such cases is to create a PLT entry 459 // and use that as the function value. 460 // 461 // For the static linking part, we just return true and everything else 462 // will use the the PLT entry as the address. 463 // 464 // The remaining (unimplemented) problem is making sure pointer equality 465 // still works. We need the help of the dynamic linker for that. We 466 // let it know that we have a direct reference to a so symbol by creating 467 // an undefined symbol with a non zero st_value. Seeing that, the 468 // dynamic linker resolves the symbol to the value of the symbol we created. 469 // This is true even for got entries, so pointer equality is maintained. 470 // To avoid an infinite loop, the only entry that points to the 471 // real function is a dedicated got entry used by the plt. That is 472 // identified by special relocation types (R_X86_64_JUMP_SLOT, 473 // R_386_JMP_SLOT, etc). 474 return S.isShared(); 475 case R_X86_64_PLT32: 476 return canBePreempted(&S, true); 477 } 478 } 479 480 bool X86_64TargetInfo::isRelRelative(uint32_t Type) const { 481 switch (Type) { 482 default: 483 return false; 484 case R_X86_64_DTPOFF32: 485 case R_X86_64_DTPOFF64: 486 case R_X86_64_PC8: 487 case R_X86_64_PC16: 488 case R_X86_64_PC32: 489 case R_X86_64_PC64: 490 case R_X86_64_PLT32: 491 return true; 492 } 493 } 494 495 bool X86_64TargetInfo::isTlsOptimized(unsigned Type, 496 const SymbolBody *S) const { 497 if (Config->Shared || (S && !S->isTLS())) 498 return false; 499 return Type == R_X86_64_TLSGD || Type == R_X86_64_TLSLD || 500 Type == R_X86_64_DTPOFF32 || 501 (Type == R_X86_64_GOTTPOFF && !canBePreempted(S, true)); 502 } 503 504 // "Ulrich Drepper, ELF Handling For Thread-Local Storage" (5.5 505 // x86-x64 linker optimizations, http://www.akkadia.org/drepper/tls.pdf) shows 506 // how LD can be optimized to LE: 507 // leaq bar@tlsld(%rip), %rdi 508 // callq __tls_get_addr@PLT 509 // leaq bar@dtpoff(%rax), %rcx 510 // Is converted to: 511 // .word 0x6666 512 // .byte 0x66 513 // mov %fs:0,%rax 514 // leaq bar@tpoff(%rax), %rcx 515 void X86_64TargetInfo::relocateTlsLdToLe(uint8_t *Loc, uint8_t *BufEnd, 516 uint64_t P, uint64_t SA) const { 517 const uint8_t Inst[] = { 518 0x66, 0x66, //.word 0x6666 519 0x66, //.byte 0x66 520 0x64, 0x48, 0x8b, 0x04, 0x25, 0x00, 0x00, 0x00, 0x00 // mov %fs:0,%rax 521 }; 522 memcpy(Loc - 3, Inst, sizeof(Inst)); 523 } 524 525 // "Ulrich Drepper, ELF Handling For Thread-Local Storage" (5.5 526 // x86-x64 linker optimizations, http://www.akkadia.org/drepper/tls.pdf) shows 527 // how GD can be optimized to LE: 528 // .byte 0x66 529 // leaq x@tlsgd(%rip), %rdi 530 // .word 0x6666 531 // rex64 532 // call __tls_get_addr@plt 533 // Is converted to: 534 // mov %fs:0x0,%rax 535 // lea x@tpoff,%rax 536 void X86_64TargetInfo::relocateTlsGdToLe(uint8_t *Loc, uint8_t *BufEnd, 537 uint64_t P, uint64_t SA) const { 538 const uint8_t Inst[] = { 539 0x64, 0x48, 0x8b, 0x04, 0x25, 0x00, 0x00, 0x00, 0x00, // mov %fs:0x0,%rax 540 0x48, 0x8d, 0x80, 0x00, 0x00, 0x00, 0x00 // lea x@tpoff,%rax 541 }; 542 memcpy(Loc - 4, Inst, sizeof(Inst)); 543 relocateOne(Loc + 8, BufEnd, R_X86_64_TPOFF32, P, SA); 544 } 545 546 // "Ulrich Drepper, ELF Handling For Thread-Local Storage" (5.5 547 // x86-x64 linker optimizations, http://www.akkadia.org/drepper/tls.pdf) shows 548 // how GD can be optimized to IE: 549 // .byte 0x66 550 // leaq x@tlsgd(%rip), %rdi 551 // .word 0x6666 552 // rex64 553 // call __tls_get_addr@plt 554 // Is converted to: 555 // mov %fs:0x0,%rax 556 // addq x@tpoff,%rax 557 void X86_64TargetInfo::relocateTlsGdToIe(uint8_t *Loc, uint8_t *BufEnd, 558 uint64_t P, uint64_t SA) const { 559 const uint8_t Inst[] = { 560 0x64, 0x48, 0x8b, 0x04, 0x25, 0x00, 0x00, 0x00, 0x00, // mov %fs:0x0,%rax 561 0x48, 0x03, 0x05, 0x00, 0x00, 0x00, 0x00 // addq x@tpoff,%rax 562 }; 563 memcpy(Loc - 4, Inst, sizeof(Inst)); 564 relocateOne(Loc + 8, BufEnd, R_X86_64_TPOFF64, P + 12, SA); 565 } 566 567 // In some conditions, R_X86_64_GOTTPOFF relocation can be optimized to 568 // R_X86_64_TPOFF32 so that R_X86_64_TPOFF32 so that it does not use GOT. 569 // This function does that. Read "ELF Handling For Thread-Local Storage, 570 // 5.5 x86-x64 linker optimizations" (http://www.akkadia.org/drepper/tls.pdf) 571 // by Ulrich Drepper for details. 572 void X86_64TargetInfo::relocateTlsIeToLe(uint8_t *Loc, uint8_t *BufEnd, 573 uint64_t P, uint64_t SA) const { 574 // Ulrich's document section 6.5 says that @gottpoff(%rip) must be 575 // used in MOVQ or ADDQ instructions only. 576 // "MOVQ foo@GOTTPOFF(%RIP), %REG" is transformed to "MOVQ $foo, %REG". 577 // "ADDQ foo@GOTTPOFF(%RIP), %REG" is transformed to "LEAQ foo(%REG), %REG" 578 // (if the register is not RSP/R12) or "ADDQ $foo, %RSP". 579 // Opcodes info can be found at http://ref.x86asm.net/coder64.html#x48. 580 uint8_t *Prefix = Loc - 3; 581 uint8_t *Inst = Loc - 2; 582 uint8_t *RegSlot = Loc - 1; 583 uint8_t Reg = Loc[-1] >> 3; 584 bool IsMov = *Inst == 0x8b; 585 bool RspAdd = !IsMov && Reg == 4; 586 // r12 and rsp registers requires special handling. 587 // Problem is that for other registers, for example leaq 0xXXXXXXXX(%r11),%r11 588 // result out is 7 bytes: 4d 8d 9b XX XX XX XX, 589 // but leaq 0xXXXXXXXX(%r12),%r12 is 8 bytes: 4d 8d a4 24 XX XX XX XX. 590 // The same true for rsp. So we convert to addq for them, saving 1 byte that 591 // we dont have. 592 if (RspAdd) 593 *Inst = 0x81; 594 else 595 *Inst = IsMov ? 0xc7 : 0x8d; 596 if (*Prefix == 0x4c) 597 *Prefix = (IsMov || RspAdd) ? 0x49 : 0x4d; 598 *RegSlot = (IsMov || RspAdd) ? (0xc0 | Reg) : (0x80 | Reg | (Reg << 3)); 599 relocateOne(Loc, BufEnd, R_X86_64_TPOFF32, P, SA); 600 } 601 602 // This function applies a TLS relocation with an optimization as described 603 // in the Ulrich's document. As a result of rewriting instructions at the 604 // relocation target, relocations immediately follow the TLS relocation (which 605 // would be applied to rewritten instructions) may have to be skipped. 606 // This function returns a number of relocations that need to be skipped. 607 unsigned X86_64TargetInfo::relocateTlsOptimize(uint8_t *Loc, uint8_t *BufEnd, 608 uint32_t Type, uint64_t P, 609 uint64_t SA, 610 const SymbolBody &S) const { 611 switch (Type) { 612 case R_X86_64_DTPOFF32: 613 relocateOne(Loc, BufEnd, R_X86_64_TPOFF32, P, SA); 614 return 0; 615 case R_X86_64_GOTTPOFF: 616 relocateTlsIeToLe(Loc, BufEnd, P, SA); 617 return 0; 618 case R_X86_64_TLSGD: { 619 if (canBePreempted(&S, true)) 620 relocateTlsGdToIe(Loc, BufEnd, P, SA); 621 else 622 relocateTlsGdToLe(Loc, BufEnd, P, SA); 623 // The next relocation should be against __tls_get_addr, so skip it 624 return 1; 625 } 626 case R_X86_64_TLSLD: 627 relocateTlsLdToLe(Loc, BufEnd, P, SA); 628 // The next relocation should be against __tls_get_addr, so skip it 629 return 1; 630 } 631 llvm_unreachable("Unknown TLS optimization"); 632 } 633 634 void X86_64TargetInfo::relocateOne(uint8_t *Loc, uint8_t *BufEnd, uint32_t Type, 635 uint64_t P, uint64_t SA, 636 uint8_t *PairedLoc) const { 637 switch (Type) { 638 case R_X86_64_32: 639 checkUInt<32>(SA, Type); 640 write32le(Loc, SA); 641 break; 642 case R_X86_64_32S: 643 checkInt<32>(SA, Type); 644 write32le(Loc, SA); 645 break; 646 case R_X86_64_64: 647 write64le(Loc, SA); 648 break; 649 case R_X86_64_DTPOFF32: 650 write32le(Loc, SA); 651 break; 652 case R_X86_64_DTPOFF64: 653 write64le(Loc, SA); 654 break; 655 case R_X86_64_GOTPCREL: 656 case R_X86_64_PC32: 657 case R_X86_64_PLT32: 658 case R_X86_64_TLSGD: 659 case R_X86_64_TLSLD: 660 write32le(Loc, SA - P); 661 break; 662 case R_X86_64_TPOFF32: { 663 uint64_t Val = SA - Out<ELF64LE>::TlsPhdr->p_memsz; 664 checkInt<32>(Val, Type); 665 write32le(Loc, Val); 666 break; 667 } 668 case R_X86_64_TPOFF64: 669 write32le(Loc, SA - P); 670 break; 671 default: 672 error("unrecognized reloc " + Twine(Type)); 673 } 674 } 675 676 // Relocation masks following the #lo(value), #hi(value), #ha(value), 677 // #higher(value), #highera(value), #highest(value), and #highesta(value) 678 // macros defined in section 4.5.1. Relocation Types of the PPC-elf64abi 679 // document. 680 static uint16_t applyPPCLo(uint64_t V) { return V; } 681 static uint16_t applyPPCHi(uint64_t V) { return V >> 16; } 682 static uint16_t applyPPCHa(uint64_t V) { return (V + 0x8000) >> 16; } 683 static uint16_t applyPPCHigher(uint64_t V) { return V >> 32; } 684 static uint16_t applyPPCHighera(uint64_t V) { return (V + 0x8000) >> 32; } 685 static uint16_t applyPPCHighest(uint64_t V) { return V >> 48; } 686 static uint16_t applyPPCHighesta(uint64_t V) { return (V + 0x8000) >> 48; } 687 688 PPC64TargetInfo::PPC64TargetInfo() { 689 PCRelReloc = R_PPC64_REL24; 690 GotReloc = R_PPC64_GLOB_DAT; 691 RelativeReloc = R_PPC64_RELATIVE; 692 PltEntrySize = 32; 693 694 // We need 64K pages (at least under glibc/Linux, the loader won't 695 // set different permissions on a finer granularity than that). 696 PageSize = 65536; 697 698 // The PPC64 ELF ABI v1 spec, says: 699 // 700 // It is normally desirable to put segments with different characteristics 701 // in separate 256 Mbyte portions of the address space, to give the 702 // operating system full paging flexibility in the 64-bit address space. 703 // 704 // And because the lowest non-zero 256M boundary is 0x10000000, PPC64 linkers 705 // use 0x10000000 as the starting address. 706 VAStart = 0x10000000; 707 } 708 709 uint64_t getPPC64TocBase() { 710 // The TOC consists of sections .got, .toc, .tocbss, .plt in that 711 // order. The TOC starts where the first of these sections starts. 712 713 // FIXME: This obviously does not do the right thing when there is no .got 714 // section, but there is a .toc or .tocbss section. 715 uint64_t TocVA = Out<ELF64BE>::Got->getVA(); 716 if (!TocVA) 717 TocVA = Out<ELF64BE>::Plt->getVA(); 718 719 // Per the ppc64-elf-linux ABI, The TOC base is TOC value plus 0x8000 720 // thus permitting a full 64 Kbytes segment. Note that the glibc startup 721 // code (crt1.o) assumes that you can get from the TOC base to the 722 // start of the .toc section with only a single (signed) 16-bit relocation. 723 return TocVA + 0x8000; 724 } 725 726 void PPC64TargetInfo::writeGotPltEntry(uint8_t *Buf, uint64_t Plt) const {} 727 void PPC64TargetInfo::writePltZeroEntry(uint8_t *Buf, uint64_t GotEntryAddr, 728 uint64_t PltEntryAddr) const {} 729 void PPC64TargetInfo::writePltEntry(uint8_t *Buf, uint64_t GotAddr, 730 uint64_t GotEntryAddr, 731 uint64_t PltEntryAddr, int32_t Index, 732 unsigned RelOff) const { 733 uint64_t Off = GotEntryAddr - getPPC64TocBase(); 734 735 // FIXME: What we should do, in theory, is get the offset of the function 736 // descriptor in the .opd section, and use that as the offset from %r2 (the 737 // TOC-base pointer). Instead, we have the GOT-entry offset, and that will 738 // be a pointer to the function descriptor in the .opd section. Using 739 // this scheme is simpler, but requires an extra indirection per PLT dispatch. 740 741 write32be(Buf, 0xf8410028); // std %r2, 40(%r1) 742 write32be(Buf + 4, 0x3d620000 | applyPPCHa(Off)); // addis %r11, %r2, X@ha 743 write32be(Buf + 8, 0xe98b0000 | applyPPCLo(Off)); // ld %r12, X@l(%r11) 744 write32be(Buf + 12, 0xe96c0000); // ld %r11,0(%r12) 745 write32be(Buf + 16, 0x7d6903a6); // mtctr %r11 746 write32be(Buf + 20, 0xe84c0008); // ld %r2,8(%r12) 747 write32be(Buf + 24, 0xe96c0010); // ld %r11,16(%r12) 748 write32be(Buf + 28, 0x4e800420); // bctr 749 } 750 751 bool PPC64TargetInfo::relocNeedsGot(uint32_t Type, const SymbolBody &S) const { 752 if (relocNeedsPlt(Type, S)) 753 return true; 754 755 switch (Type) { 756 default: return false; 757 case R_PPC64_GOT16: 758 case R_PPC64_GOT16_DS: 759 case R_PPC64_GOT16_HA: 760 case R_PPC64_GOT16_HI: 761 case R_PPC64_GOT16_LO: 762 case R_PPC64_GOT16_LO_DS: 763 return true; 764 } 765 } 766 767 bool PPC64TargetInfo::relocNeedsPlt(uint32_t Type, const SymbolBody &S) const { 768 // These are function calls that need to be redirected through a PLT stub. 769 return Type == R_PPC64_REL24 && canBePreempted(&S, false); 770 } 771 772 bool PPC64TargetInfo::isRelRelative(uint32_t Type) const { 773 switch (Type) { 774 default: 775 return true; 776 case R_PPC64_ADDR64: 777 case R_PPC64_TOC: 778 return false; 779 } 780 } 781 782 void PPC64TargetInfo::relocateOne(uint8_t *Loc, uint8_t *BufEnd, uint32_t Type, 783 uint64_t P, uint64_t SA, 784 uint8_t *PairedLoc) const { 785 uint64_t TB = getPPC64TocBase(); 786 787 // For a TOC-relative relocation, adjust the addend and proceed in terms of 788 // the corresponding ADDR16 relocation type. 789 switch (Type) { 790 case R_PPC64_TOC16: Type = R_PPC64_ADDR16; SA -= TB; break; 791 case R_PPC64_TOC16_DS: Type = R_PPC64_ADDR16_DS; SA -= TB; break; 792 case R_PPC64_TOC16_HA: Type = R_PPC64_ADDR16_HA; SA -= TB; break; 793 case R_PPC64_TOC16_HI: Type = R_PPC64_ADDR16_HI; SA -= TB; break; 794 case R_PPC64_TOC16_LO: Type = R_PPC64_ADDR16_LO; SA -= TB; break; 795 case R_PPC64_TOC16_LO_DS: Type = R_PPC64_ADDR16_LO_DS; SA -= TB; break; 796 default: break; 797 } 798 799 switch (Type) { 800 case R_PPC64_ADDR14: { 801 checkAlignment<4>(SA, Type); 802 // Preserve the AA/LK bits in the branch instruction 803 uint8_t AALK = Loc[3]; 804 write16be(Loc + 2, (AALK & 3) | (SA & 0xfffc)); 805 break; 806 } 807 case R_PPC64_ADDR16: 808 checkInt<16>(SA, Type); 809 write16be(Loc, SA); 810 break; 811 case R_PPC64_ADDR16_DS: 812 checkInt<16>(SA, Type); 813 write16be(Loc, (read16be(Loc) & 3) | (SA & ~3)); 814 break; 815 case R_PPC64_ADDR16_HA: 816 write16be(Loc, applyPPCHa(SA)); 817 break; 818 case R_PPC64_ADDR16_HI: 819 write16be(Loc, applyPPCHi(SA)); 820 break; 821 case R_PPC64_ADDR16_HIGHER: 822 write16be(Loc, applyPPCHigher(SA)); 823 break; 824 case R_PPC64_ADDR16_HIGHERA: 825 write16be(Loc, applyPPCHighera(SA)); 826 break; 827 case R_PPC64_ADDR16_HIGHEST: 828 write16be(Loc, applyPPCHighest(SA)); 829 break; 830 case R_PPC64_ADDR16_HIGHESTA: 831 write16be(Loc, applyPPCHighesta(SA)); 832 break; 833 case R_PPC64_ADDR16_LO: 834 write16be(Loc, applyPPCLo(SA)); 835 break; 836 case R_PPC64_ADDR16_LO_DS: 837 write16be(Loc, (read16be(Loc) & 3) | (applyPPCLo(SA) & ~3)); 838 break; 839 case R_PPC64_ADDR32: 840 checkInt<32>(SA, Type); 841 write32be(Loc, SA); 842 break; 843 case R_PPC64_ADDR64: 844 write64be(Loc, SA); 845 break; 846 case R_PPC64_REL16_HA: 847 write16be(Loc, applyPPCHa(SA - P)); 848 break; 849 case R_PPC64_REL16_HI: 850 write16be(Loc, applyPPCHi(SA - P)); 851 break; 852 case R_PPC64_REL16_LO: 853 write16be(Loc, applyPPCLo(SA - P)); 854 break; 855 case R_PPC64_REL24: { 856 // If we have an undefined weak symbol, we might get here with a symbol 857 // address of zero. That could overflow, but the code must be unreachable, 858 // so don't bother doing anything at all. 859 if (!SA) 860 break; 861 862 uint64_t PltStart = Out<ELF64BE>::Plt->getVA(); 863 uint64_t PltEnd = PltStart + Out<ELF64BE>::Plt->getSize(); 864 bool InPlt = PltStart <= SA && SA < PltEnd; 865 866 if (!InPlt && Out<ELF64BE>::Opd) { 867 // If this is a local call, and we currently have the address of a 868 // function-descriptor, get the underlying code address instead. 869 uint64_t OpdStart = Out<ELF64BE>::Opd->getVA(); 870 uint64_t OpdEnd = OpdStart + Out<ELF64BE>::Opd->getSize(); 871 bool InOpd = OpdStart <= SA && SA < OpdEnd; 872 873 if (InOpd) 874 SA = read64be(&Out<ELF64BE>::OpdBuf[SA - OpdStart]); 875 } 876 877 uint32_t Mask = 0x03FFFFFC; 878 checkInt<24>(SA - P, Type); 879 write32be(Loc, (read32be(Loc) & ~Mask) | ((SA - P) & Mask)); 880 881 uint32_t Nop = 0x60000000; 882 if (InPlt && Loc + 8 <= BufEnd && read32be(Loc + 4) == Nop) 883 write32be(Loc + 4, 0xe8410028); // ld %r2, 40(%r1) 884 break; 885 } 886 case R_PPC64_REL32: 887 checkInt<32>(SA - P, Type); 888 write32be(Loc, SA - P); 889 break; 890 case R_PPC64_REL64: 891 write64be(Loc, SA - P); 892 break; 893 case R_PPC64_TOC: 894 write64be(Loc, SA); 895 break; 896 default: 897 error("unrecognized reloc " + Twine(Type)); 898 } 899 } 900 901 AArch64TargetInfo::AArch64TargetInfo() { 902 CopyReloc = R_AARCH64_COPY; 903 GotReloc = R_AARCH64_GLOB_DAT; 904 PltReloc = R_AARCH64_JUMP_SLOT; 905 LazyRelocations = true; 906 PltEntrySize = 16; 907 PltZeroEntrySize = 32; 908 } 909 910 unsigned AArch64TargetInfo::getPltRefReloc(unsigned Type) const { return Type; } 911 912 void AArch64TargetInfo::writeGotPltEntry(uint8_t *Buf, uint64_t Plt) const { 913 write64le(Buf, Out<ELF64LE>::Plt->getVA()); 914 } 915 916 void AArch64TargetInfo::writePltZeroEntry(uint8_t *Buf, uint64_t GotEntryAddr, 917 uint64_t PltEntryAddr) const { 918 const uint8_t PltData[] = { 919 0xf0, 0x7b, 0xbf, 0xa9, // stp x16, x30, [sp,#-16]! 920 0x10, 0x00, 0x00, 0x90, // adrp x16, Page(&(.plt.got[2])) 921 0x11, 0x02, 0x40, 0xf9, // ldr x17, [x16, Offset(&(.plt.got[2]))] 922 0x10, 0x02, 0x00, 0x91, // add x16, x16, Offset(&(.plt.got[2])) 923 0x20, 0x02, 0x1f, 0xd6, // br x17 924 0x1f, 0x20, 0x03, 0xd5, // nop 925 0x1f, 0x20, 0x03, 0xd5, // nop 926 0x1f, 0x20, 0x03, 0xd5 // nop 927 }; 928 memcpy(Buf, PltData, sizeof(PltData)); 929 930 relocateOne(Buf + 4, Buf + 8, R_AARCH64_ADR_PREL_PG_HI21, PltEntryAddr + 4, 931 GotEntryAddr + 16); 932 relocateOne(Buf + 8, Buf + 12, R_AARCH64_LDST64_ABS_LO12_NC, PltEntryAddr + 8, 933 GotEntryAddr + 16); 934 relocateOne(Buf + 12, Buf + 16, R_AARCH64_ADD_ABS_LO12_NC, PltEntryAddr + 12, 935 GotEntryAddr + 16); 936 } 937 938 void AArch64TargetInfo::writePltEntry(uint8_t *Buf, uint64_t GotAddr, 939 uint64_t GotEntryAddr, 940 uint64_t PltEntryAddr, int32_t Index, 941 unsigned RelOff) const { 942 const uint8_t Inst[] = { 943 0x10, 0x00, 0x00, 0x90, // adrp x16, Page(&(.plt.got[n])) 944 0x11, 0x02, 0x40, 0xf9, // ldr x17, [x16, Offset(&(.plt.got[n]))] 945 0x10, 0x02, 0x00, 0x91, // add x16, x16, Offset(&(.plt.got[n])) 946 0x20, 0x02, 0x1f, 0xd6 // br x17 947 }; 948 memcpy(Buf, Inst, sizeof(Inst)); 949 950 relocateOne(Buf, Buf + 4, R_AARCH64_ADR_PREL_PG_HI21, PltEntryAddr, 951 GotEntryAddr); 952 relocateOne(Buf + 4, Buf + 8, R_AARCH64_LDST64_ABS_LO12_NC, PltEntryAddr + 4, 953 GotEntryAddr); 954 relocateOne(Buf + 8, Buf + 12, R_AARCH64_ADD_ABS_LO12_NC, PltEntryAddr + 8, 955 GotEntryAddr); 956 } 957 958 bool AArch64TargetInfo::relocNeedsCopy(uint32_t Type, 959 const SymbolBody &S) const { 960 if (Config->Shared) 961 return false; 962 switch (Type) { 963 default: 964 return false; 965 case R_AARCH64_ABS16: 966 case R_AARCH64_ABS32: 967 case R_AARCH64_ABS64: 968 case R_AARCH64_ADD_ABS_LO12_NC: 969 case R_AARCH64_ADR_PREL_LO21: 970 case R_AARCH64_ADR_PREL_PG_HI21: 971 case R_AARCH64_LDST8_ABS_LO12_NC: 972 case R_AARCH64_LDST32_ABS_LO12_NC: 973 case R_AARCH64_LDST64_ABS_LO12_NC: 974 if (auto *SS = dyn_cast<SharedSymbol<ELF64LE>>(&S)) 975 return SS->Sym.getType() == STT_OBJECT; 976 return false; 977 } 978 } 979 980 bool AArch64TargetInfo::relocNeedsGot(uint32_t Type, 981 const SymbolBody &S) const { 982 return Type == R_AARCH64_ADR_GOT_PAGE || Type == R_AARCH64_LD64_GOT_LO12_NC || 983 relocNeedsPlt(Type, S); 984 } 985 986 bool AArch64TargetInfo::relocNeedsPlt(uint32_t Type, 987 const SymbolBody &S) const { 988 switch (Type) { 989 default: 990 return false; 991 case R_AARCH64_CALL26: 992 case R_AARCH64_JUMP26: 993 return canBePreempted(&S, true); 994 } 995 } 996 997 static void updateAArch64Adr(uint8_t *L, uint64_t Imm) { 998 uint32_t ImmLo = (Imm & 0x3) << 29; 999 uint32_t ImmHi = ((Imm & 0x1FFFFC) >> 2) << 5; 1000 uint64_t Mask = (0x3 << 29) | (0x7FFFF << 5); 1001 write32le(L, (read32le(L) & ~Mask) | ImmLo | ImmHi); 1002 } 1003 1004 // Page(Expr) is the page address of the expression Expr, defined 1005 // as (Expr & ~0xFFF). (This applies even if the machine page size 1006 // supported by the platform has a different value.) 1007 static uint64_t getAArch64Page(uint64_t Expr) { 1008 return Expr & (~static_cast<uint64_t>(0xFFF)); 1009 } 1010 1011 void AArch64TargetInfo::relocateOne(uint8_t *Loc, uint8_t *BufEnd, 1012 uint32_t Type, uint64_t P, uint64_t SA, 1013 uint8_t *PairedLoc) const { 1014 switch (Type) { 1015 case R_AARCH64_ABS16: 1016 checkIntUInt<16>(SA, Type); 1017 write16le(Loc, SA); 1018 break; 1019 case R_AARCH64_ABS32: 1020 checkIntUInt<32>(SA, Type); 1021 write32le(Loc, SA); 1022 break; 1023 case R_AARCH64_ABS64: 1024 write64le(Loc, SA); 1025 break; 1026 case R_AARCH64_ADD_ABS_LO12_NC: 1027 // This relocation stores 12 bits and there's no instruction 1028 // to do it. Instead, we do a 32 bits store of the value 1029 // of r_addend bitwise-or'ed Loc. This assumes that the addend 1030 // bits in Loc are zero. 1031 or32le(Loc, (SA & 0xFFF) << 10); 1032 break; 1033 case R_AARCH64_ADR_GOT_PAGE: { 1034 uint64_t X = getAArch64Page(SA) - getAArch64Page(P); 1035 checkInt<33>(X, Type); 1036 updateAArch64Adr(Loc, (X >> 12) & 0x1FFFFF); // X[32:12] 1037 break; 1038 } 1039 case R_AARCH64_ADR_PREL_LO21: { 1040 uint64_t X = SA - P; 1041 checkInt<21>(X, Type); 1042 updateAArch64Adr(Loc, X & 0x1FFFFF); 1043 break; 1044 } 1045 case R_AARCH64_ADR_PREL_PG_HI21: { 1046 uint64_t X = getAArch64Page(SA) - getAArch64Page(P); 1047 checkInt<33>(X, Type); 1048 updateAArch64Adr(Loc, (X >> 12) & 0x1FFFFF); // X[32:12] 1049 break; 1050 } 1051 case R_AARCH64_CALL26: 1052 case R_AARCH64_JUMP26: { 1053 uint64_t X = SA - P; 1054 checkInt<28>(X, Type); 1055 or32le(Loc, (X & 0x0FFFFFFC) >> 2); 1056 break; 1057 } 1058 case R_AARCH64_LD64_GOT_LO12_NC: 1059 checkAlignment<8>(SA, Type); 1060 or32le(Loc, (SA & 0xFF8) << 7); 1061 break; 1062 case R_AARCH64_LDST8_ABS_LO12_NC: 1063 or32le(Loc, (SA & 0xFFF) << 10); 1064 break; 1065 case R_AARCH64_LDST32_ABS_LO12_NC: 1066 or32le(Loc, (SA & 0xFFC) << 8); 1067 break; 1068 case R_AARCH64_LDST64_ABS_LO12_NC: 1069 or32le(Loc, (SA & 0xFF8) << 7); 1070 break; 1071 case R_AARCH64_PREL16: 1072 checkIntUInt<16>(SA - P, Type); 1073 write16le(Loc, SA - P); 1074 break; 1075 case R_AARCH64_PREL32: 1076 checkIntUInt<32>(SA - P, Type); 1077 write32le(Loc, SA - P); 1078 break; 1079 case R_AARCH64_PREL64: 1080 write64le(Loc, SA - P); 1081 break; 1082 default: 1083 error("unrecognized reloc " + Twine(Type)); 1084 } 1085 } 1086 1087 template <class ELFT> MipsTargetInfo<ELFT>::MipsTargetInfo() { 1088 PageSize = 65536; 1089 GotHeaderEntriesNum = 2; 1090 } 1091 1092 template <class ELFT> 1093 void MipsTargetInfo<ELFT>::writeGotHeaderEntries(uint8_t *Buf) const { 1094 typedef typename ELFFile<ELFT>::Elf_Off Elf_Off; 1095 auto *P = reinterpret_cast<Elf_Off *>(Buf); 1096 // Module pointer 1097 P[1] = ELFT::Is64Bits ? 0x8000000000000000 : 0x80000000; 1098 } 1099 1100 template <class ELFT> 1101 void MipsTargetInfo<ELFT>::writeGotPltEntry(uint8_t *Buf, uint64_t Plt) const {} 1102 template <class ELFT> 1103 void MipsTargetInfo<ELFT>::writePltZeroEntry(uint8_t *Buf, uint64_t GotEntryAddr, 1104 uint64_t PltEntryAddr) const {} 1105 template <class ELFT> 1106 void MipsTargetInfo<ELFT>::writePltEntry(uint8_t *Buf, uint64_t GotAddr, 1107 uint64_t GotEntryAddr, 1108 uint64_t PltEntryAddr, int32_t Index, 1109 unsigned RelOff) const {} 1110 1111 template <class ELFT> 1112 bool MipsTargetInfo<ELFT>::relocNeedsGot(uint32_t Type, 1113 const SymbolBody &S) const { 1114 return Type == R_MIPS_GOT16 || Type == R_MIPS_CALL16; 1115 } 1116 1117 template <class ELFT> 1118 bool MipsTargetInfo<ELFT>::relocNeedsPlt(uint32_t Type, 1119 const SymbolBody &S) const { 1120 return false; 1121 } 1122 1123 template <class ELFT> 1124 void MipsTargetInfo<ELFT>::relocateOne(uint8_t *Loc, uint8_t *BufEnd, 1125 uint32_t Type, uint64_t P, uint64_t SA, 1126 uint8_t *PairedLoc) const { 1127 const endianness E = ELFT::TargetEndianness; 1128 switch (Type) { 1129 case R_MIPS_32: 1130 add32<E>(Loc, SA); 1131 break; 1132 case R_MIPS_CALL16: 1133 case R_MIPS_GOT16: { 1134 int64_t V = SA - getMipsGpAddr<ELFT>(); 1135 if (Type == R_MIPS_GOT16) 1136 checkInt<16>(V, Type); 1137 write32<E>(Loc, (read32<E>(Loc) & 0xffff0000) | (V & 0xffff)); 1138 break; 1139 } 1140 case R_MIPS_HI16: { 1141 uint32_t Instr = read32<E>(Loc); 1142 if (PairedLoc) { 1143 uint64_t AHL = ((Instr & 0xffff) << 16) + 1144 SignExtend64<16>(read32<E>(PairedLoc) & 0xffff); 1145 write32<E>(Loc, (Instr & 0xffff0000) | (((SA + AHL) >> 16) & 0xffff)); 1146 } else { 1147 warning("Can't find matching R_MIPS_LO16 relocation for R_MIPS_HI16"); 1148 write32<E>(Loc, (Instr & 0xffff0000) | ((SA >> 16) & 0xffff)); 1149 } 1150 break; 1151 } 1152 case R_MIPS_LO16: { 1153 uint32_t Instr = read32<E>(Loc); 1154 int64_t AHL = SignExtend64<16>(Instr & 0xffff); 1155 write32<E>(Loc, (Instr & 0xffff0000) | ((SA + AHL) & 0xffff)); 1156 break; 1157 } 1158 default: 1159 error("unrecognized reloc " + Twine(Type)); 1160 } 1161 } 1162 1163 template <class ELFT> typename ELFFile<ELFT>::uintX_t getMipsGpAddr() { 1164 const unsigned GPOffset = 0x7ff0; 1165 return Out<ELFT>::Got->getVA() ? (Out<ELFT>::Got->getVA() + GPOffset) : 0; 1166 } 1167 1168 template uint32_t getMipsGpAddr<ELF32LE>(); 1169 template uint32_t getMipsGpAddr<ELF32BE>(); 1170 template uint64_t getMipsGpAddr<ELF64LE>(); 1171 template uint64_t getMipsGpAddr<ELF64BE>(); 1172 } 1173 } 1174