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