1 //===- X86_64.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 #include "InputFiles.h" 11 #include "Symbols.h" 12 #include "SyntheticSections.h" 13 #include "Target.h" 14 #include "lld/Common/ErrorHandler.h" 15 #include "llvm/Object/ELF.h" 16 #include "llvm/Support/Endian.h" 17 18 using namespace llvm; 19 using namespace llvm::object; 20 using namespace llvm::support::endian; 21 using namespace llvm::ELF; 22 using namespace lld; 23 using namespace lld::elf; 24 25 namespace { 26 template <class ELFT> class X86_64 : public TargetInfo { 27 public: 28 X86_64(); 29 RelExpr getRelExpr(RelType Type, const Symbol &S, 30 const uint8_t *Loc) const override; 31 RelType getDynRel(RelType Type) const override; 32 void writeGotPltHeader(uint8_t *Buf) const override; 33 void writeGotPlt(uint8_t *Buf, const Symbol &S) const override; 34 void writePltHeader(uint8_t *Buf) const override; 35 void writePlt(uint8_t *Buf, uint64_t GotPltEntryAddr, uint64_t PltEntryAddr, 36 int32_t Index, unsigned RelOff) const override; 37 void relocateOne(uint8_t *Loc, RelType Type, uint64_t Val) const override; 38 39 RelExpr adjustRelaxExpr(RelType Type, const uint8_t *Data, 40 RelExpr Expr) const override; 41 void relaxGot(uint8_t *Loc, uint64_t Val) const override; 42 void relaxTlsGdToIe(uint8_t *Loc, RelType Type, uint64_t Val) const override; 43 void relaxTlsGdToLe(uint8_t *Loc, RelType Type, uint64_t Val) const override; 44 void relaxTlsIeToLe(uint8_t *Loc, RelType Type, uint64_t Val) const override; 45 void relaxTlsLdToLe(uint8_t *Loc, RelType Type, uint64_t Val) const override; 46 bool adjustPrologueForCrossSplitStack(uint8_t *Loc, uint8_t *End, 47 uint8_t StOther) const override; 48 49 private: 50 void relaxGotNoPic(uint8_t *Loc, uint64_t Val, uint8_t Op, 51 uint8_t ModRm) const; 52 }; 53 } // namespace 54 55 template <class ELFT> X86_64<ELFT>::X86_64() { 56 CopyRel = R_X86_64_COPY; 57 GotRel = R_X86_64_GLOB_DAT; 58 NoneRel = R_X86_64_NONE; 59 PltRel = R_X86_64_JUMP_SLOT; 60 RelativeRel = R_X86_64_RELATIVE; 61 IRelativeRel = R_X86_64_IRELATIVE; 62 TlsGotRel = R_X86_64_TPOFF64; 63 TlsModuleIndexRel = R_X86_64_DTPMOD64; 64 TlsOffsetRel = R_X86_64_DTPOFF64; 65 GotEntrySize = 8; 66 GotPltEntrySize = 8; 67 PltEntrySize = 16; 68 PltHeaderSize = 16; 69 TlsGdRelaxSkip = 2; 70 TrapInstr = 0xcccccccc; // 0xcc = INT3 71 72 // Align to the large page size (known as a superpage or huge page). 73 // FreeBSD automatically promotes large, superpage-aligned allocations. 74 DefaultImageBase = 0x200000; 75 } 76 77 template <class ELFT> 78 RelExpr X86_64<ELFT>::getRelExpr(RelType Type, const Symbol &S, 79 const uint8_t *Loc) const { 80 switch (Type) { 81 case R_X86_64_8: 82 case R_X86_64_16: 83 case R_X86_64_32: 84 case R_X86_64_32S: 85 case R_X86_64_64: 86 case R_X86_64_DTPOFF32: 87 case R_X86_64_DTPOFF64: 88 return R_ABS; 89 case R_X86_64_TPOFF32: 90 return R_TLS; 91 case R_X86_64_TLSLD: 92 return R_TLSLD_PC; 93 case R_X86_64_TLSGD: 94 return R_TLSGD_PC; 95 case R_X86_64_SIZE32: 96 case R_X86_64_SIZE64: 97 return R_SIZE; 98 case R_X86_64_PLT32: 99 return R_PLT_PC; 100 case R_X86_64_PC32: 101 case R_X86_64_PC64: 102 return R_PC; 103 case R_X86_64_GOT32: 104 case R_X86_64_GOT64: 105 return R_GOT_FROM_END; 106 case R_X86_64_GOTPCREL: 107 case R_X86_64_GOTPCRELX: 108 case R_X86_64_REX_GOTPCRELX: 109 case R_X86_64_GOTTPOFF: 110 return R_GOT_PC; 111 case R_X86_64_GOTOFF64: 112 return R_GOTREL_FROM_END; 113 case R_X86_64_GOTPC32: 114 case R_X86_64_GOTPC64: 115 return R_GOTONLY_PC_FROM_END; 116 case R_X86_64_NONE: 117 return R_NONE; 118 default: 119 return R_INVALID; 120 } 121 } 122 123 template <class ELFT> void X86_64<ELFT>::writeGotPltHeader(uint8_t *Buf) const { 124 // The first entry holds the value of _DYNAMIC. It is not clear why that is 125 // required, but it is documented in the psabi and the glibc dynamic linker 126 // seems to use it (note that this is relevant for linking ld.so, not any 127 // other program). 128 write64le(Buf, In.Dynamic->getVA()); 129 } 130 131 template <class ELFT> 132 void X86_64<ELFT>::writeGotPlt(uint8_t *Buf, const Symbol &S) const { 133 // See comments in X86::writeGotPlt. 134 write64le(Buf, S.getPltVA() + 6); 135 } 136 137 template <class ELFT> void X86_64<ELFT>::writePltHeader(uint8_t *Buf) const { 138 const uint8_t PltData[] = { 139 0xff, 0x35, 0, 0, 0, 0, // pushq GOTPLT+8(%rip) 140 0xff, 0x25, 0, 0, 0, 0, // jmp *GOTPLT+16(%rip) 141 0x0f, 0x1f, 0x40, 0x00, // nop 142 }; 143 memcpy(Buf, PltData, sizeof(PltData)); 144 uint64_t GotPlt = In.GotPlt->getVA(); 145 uint64_t Plt = In.Plt->getVA(); 146 write32le(Buf + 2, GotPlt - Plt + 2); // GOTPLT+8 147 write32le(Buf + 8, GotPlt - Plt + 4); // GOTPLT+16 148 } 149 150 template <class ELFT> 151 void X86_64<ELFT>::writePlt(uint8_t *Buf, uint64_t GotPltEntryAddr, 152 uint64_t PltEntryAddr, int32_t Index, 153 unsigned RelOff) const { 154 const uint8_t Inst[] = { 155 0xff, 0x25, 0, 0, 0, 0, // jmpq *got(%rip) 156 0x68, 0, 0, 0, 0, // pushq <relocation index> 157 0xe9, 0, 0, 0, 0, // jmpq plt[0] 158 }; 159 memcpy(Buf, Inst, sizeof(Inst)); 160 161 write32le(Buf + 2, GotPltEntryAddr - PltEntryAddr - 6); 162 write32le(Buf + 7, Index); 163 write32le(Buf + 12, -getPltEntryOffset(Index) - 16); 164 } 165 166 template <class ELFT> RelType X86_64<ELFT>::getDynRel(RelType Type) const { 167 if (Type == R_X86_64_64 || Type == R_X86_64_PC64 || Type == R_X86_64_SIZE32 || 168 Type == R_X86_64_SIZE64) 169 return Type; 170 return R_X86_64_NONE; 171 } 172 173 template <class ELFT> 174 void X86_64<ELFT>::relaxTlsGdToLe(uint8_t *Loc, RelType Type, 175 uint64_t Val) const { 176 // Convert 177 // .byte 0x66 178 // leaq x@tlsgd(%rip), %rdi 179 // .word 0x6666 180 // rex64 181 // call __tls_get_addr@plt 182 // to 183 // mov %fs:0x0,%rax 184 // lea x@tpoff,%rax 185 const uint8_t Inst[] = { 186 0x64, 0x48, 0x8b, 0x04, 0x25, 0x00, 0x00, 0x00, 0x00, // mov %fs:0x0,%rax 187 0x48, 0x8d, 0x80, 0, 0, 0, 0, // lea x@tpoff,%rax 188 }; 189 memcpy(Loc - 4, Inst, sizeof(Inst)); 190 191 // The original code used a pc relative relocation and so we have to 192 // compensate for the -4 in had in the addend. 193 write32le(Loc + 8, Val + 4); 194 } 195 196 template <class ELFT> 197 void X86_64<ELFT>::relaxTlsGdToIe(uint8_t *Loc, RelType Type, 198 uint64_t Val) const { 199 // Convert 200 // .byte 0x66 201 // leaq x@tlsgd(%rip), %rdi 202 // .word 0x6666 203 // rex64 204 // call __tls_get_addr@plt 205 // to 206 // mov %fs:0x0,%rax 207 // addq x@tpoff,%rax 208 const uint8_t Inst[] = { 209 0x64, 0x48, 0x8b, 0x04, 0x25, 0x00, 0x00, 0x00, 0x00, // mov %fs:0x0,%rax 210 0x48, 0x03, 0x05, 0, 0, 0, 0, // addq x@tpoff,%rax 211 }; 212 memcpy(Loc - 4, Inst, sizeof(Inst)); 213 214 // Both code sequences are PC relatives, but since we are moving the constant 215 // forward by 8 bytes we have to subtract the value by 8. 216 write32le(Loc + 8, Val - 8); 217 } 218 219 // In some conditions, R_X86_64_GOTTPOFF relocation can be optimized to 220 // R_X86_64_TPOFF32 so that it does not use GOT. 221 template <class ELFT> 222 void X86_64<ELFT>::relaxTlsIeToLe(uint8_t *Loc, RelType Type, 223 uint64_t Val) const { 224 uint8_t *Inst = Loc - 3; 225 uint8_t Reg = Loc[-1] >> 3; 226 uint8_t *RegSlot = Loc - 1; 227 228 // Note that ADD with RSP or R12 is converted to ADD instead of LEA 229 // because LEA with these registers needs 4 bytes to encode and thus 230 // wouldn't fit the space. 231 232 if (memcmp(Inst, "\x48\x03\x25", 3) == 0) { 233 // "addq foo@gottpoff(%rip),%rsp" -> "addq $foo,%rsp" 234 memcpy(Inst, "\x48\x81\xc4", 3); 235 } else if (memcmp(Inst, "\x4c\x03\x25", 3) == 0) { 236 // "addq foo@gottpoff(%rip),%r12" -> "addq $foo,%r12" 237 memcpy(Inst, "\x49\x81\xc4", 3); 238 } else if (memcmp(Inst, "\x4c\x03", 2) == 0) { 239 // "addq foo@gottpoff(%rip),%r[8-15]" -> "leaq foo(%r[8-15]),%r[8-15]" 240 memcpy(Inst, "\x4d\x8d", 2); 241 *RegSlot = 0x80 | (Reg << 3) | Reg; 242 } else if (memcmp(Inst, "\x48\x03", 2) == 0) { 243 // "addq foo@gottpoff(%rip),%reg -> "leaq foo(%reg),%reg" 244 memcpy(Inst, "\x48\x8d", 2); 245 *RegSlot = 0x80 | (Reg << 3) | Reg; 246 } else if (memcmp(Inst, "\x4c\x8b", 2) == 0) { 247 // "movq foo@gottpoff(%rip),%r[8-15]" -> "movq $foo,%r[8-15]" 248 memcpy(Inst, "\x49\xc7", 2); 249 *RegSlot = 0xc0 | Reg; 250 } else if (memcmp(Inst, "\x48\x8b", 2) == 0) { 251 // "movq foo@gottpoff(%rip),%reg" -> "movq $foo,%reg" 252 memcpy(Inst, "\x48\xc7", 2); 253 *RegSlot = 0xc0 | Reg; 254 } else { 255 error(getErrorLocation(Loc - 3) + 256 "R_X86_64_GOTTPOFF must be used in MOVQ or ADDQ instructions only"); 257 } 258 259 // The original code used a PC relative relocation. 260 // Need to compensate for the -4 it had in the addend. 261 write32le(Loc, Val + 4); 262 } 263 264 template <class ELFT> 265 void X86_64<ELFT>::relaxTlsLdToLe(uint8_t *Loc, RelType Type, 266 uint64_t Val) const { 267 // Convert 268 // leaq bar@tlsld(%rip), %rdi 269 // callq __tls_get_addr@PLT 270 // leaq bar@dtpoff(%rax), %rcx 271 // to 272 // .word 0x6666 273 // .byte 0x66 274 // mov %fs:0,%rax 275 // leaq bar@tpoff(%rax), %rcx 276 if (Type == R_X86_64_DTPOFF64) { 277 write64le(Loc, Val); 278 return; 279 } 280 if (Type == R_X86_64_DTPOFF32) { 281 write32le(Loc, Val); 282 return; 283 } 284 285 const uint8_t Inst[] = { 286 0x66, 0x66, // .word 0x6666 287 0x66, // .byte 0x66 288 0x64, 0x48, 0x8b, 0x04, 0x25, 0x00, 0x00, 0x00, 0x00, // mov %fs:0,%rax 289 }; 290 memcpy(Loc - 3, Inst, sizeof(Inst)); 291 } 292 293 template <class ELFT> 294 void X86_64<ELFT>::relocateOne(uint8_t *Loc, RelType Type, uint64_t Val) const { 295 switch (Type) { 296 case R_X86_64_8: 297 checkUInt(Loc, Val, 8, Type); 298 *Loc = Val; 299 break; 300 case R_X86_64_16: 301 checkUInt(Loc, Val, 16, Type); 302 write16le(Loc, Val); 303 break; 304 case R_X86_64_32: 305 checkUInt(Loc, Val, 32, Type); 306 write32le(Loc, Val); 307 break; 308 case R_X86_64_32S: 309 case R_X86_64_TPOFF32: 310 case R_X86_64_GOT32: 311 case R_X86_64_GOTPC32: 312 case R_X86_64_GOTPCREL: 313 case R_X86_64_GOTPCRELX: 314 case R_X86_64_REX_GOTPCRELX: 315 case R_X86_64_PC32: 316 case R_X86_64_GOTTPOFF: 317 case R_X86_64_PLT32: 318 case R_X86_64_TLSGD: 319 case R_X86_64_TLSLD: 320 case R_X86_64_DTPOFF32: 321 case R_X86_64_SIZE32: 322 checkInt(Loc, Val, 32, Type); 323 write32le(Loc, Val); 324 break; 325 case R_X86_64_64: 326 case R_X86_64_DTPOFF64: 327 case R_X86_64_GLOB_DAT: 328 case R_X86_64_PC64: 329 case R_X86_64_SIZE64: 330 case R_X86_64_GOT64: 331 case R_X86_64_GOTOFF64: 332 case R_X86_64_GOTPC64: 333 write64le(Loc, Val); 334 break; 335 default: 336 error(getErrorLocation(Loc) + "unrecognized reloc " + Twine(Type)); 337 } 338 } 339 340 template <class ELFT> 341 RelExpr X86_64<ELFT>::adjustRelaxExpr(RelType Type, const uint8_t *Data, 342 RelExpr RelExpr) const { 343 if (Type != R_X86_64_GOTPCRELX && Type != R_X86_64_REX_GOTPCRELX) 344 return RelExpr; 345 const uint8_t Op = Data[-2]; 346 const uint8_t ModRm = Data[-1]; 347 348 // FIXME: When PIC is disabled and foo is defined locally in the 349 // lower 32 bit address space, memory operand in mov can be converted into 350 // immediate operand. Otherwise, mov must be changed to lea. We support only 351 // latter relaxation at this moment. 352 if (Op == 0x8b) 353 return R_RELAX_GOT_PC; 354 355 // Relax call and jmp. 356 if (Op == 0xff && (ModRm == 0x15 || ModRm == 0x25)) 357 return R_RELAX_GOT_PC; 358 359 // Relaxation of test, adc, add, and, cmp, or, sbb, sub, xor. 360 // If PIC then no relaxation is available. 361 // We also don't relax test/binop instructions without REX byte, 362 // they are 32bit operations and not common to have. 363 assert(Type == R_X86_64_REX_GOTPCRELX); 364 return Config->Pic ? RelExpr : R_RELAX_GOT_PC_NOPIC; 365 } 366 367 // A subset of relaxations can only be applied for no-PIC. This method 368 // handles such relaxations. Instructions encoding information was taken from: 369 // "Intel 64 and IA-32 Architectures Software Developer's Manual V2" 370 // (http://www.intel.com/content/dam/www/public/us/en/documents/manuals/ 371 // 64-ia-32-architectures-software-developer-instruction-set-reference-manual-325383.pdf) 372 template <class ELFT> 373 void X86_64<ELFT>::relaxGotNoPic(uint8_t *Loc, uint64_t Val, uint8_t Op, 374 uint8_t ModRm) const { 375 const uint8_t Rex = Loc[-3]; 376 // Convert "test %reg, foo@GOTPCREL(%rip)" to "test $foo, %reg". 377 if (Op == 0x85) { 378 // See "TEST-Logical Compare" (4-428 Vol. 2B), 379 // TEST r/m64, r64 uses "full" ModR / M byte (no opcode extension). 380 381 // ModR/M byte has form XX YYY ZZZ, where 382 // YYY is MODRM.reg(register 2), ZZZ is MODRM.rm(register 1). 383 // XX has different meanings: 384 // 00: The operand's memory address is in reg1. 385 // 01: The operand's memory address is reg1 + a byte-sized displacement. 386 // 10: The operand's memory address is reg1 + a word-sized displacement. 387 // 11: The operand is reg1 itself. 388 // If an instruction requires only one operand, the unused reg2 field 389 // holds extra opcode bits rather than a register code 390 // 0xC0 == 11 000 000 binary. 391 // 0x38 == 00 111 000 binary. 392 // We transfer reg2 to reg1 here as operand. 393 // See "2.1.3 ModR/M and SIB Bytes" (Vol. 2A 2-3). 394 Loc[-1] = 0xc0 | (ModRm & 0x38) >> 3; // ModR/M byte. 395 396 // Change opcode from TEST r/m64, r64 to TEST r/m64, imm32 397 // See "TEST-Logical Compare" (4-428 Vol. 2B). 398 Loc[-2] = 0xf7; 399 400 // Move R bit to the B bit in REX byte. 401 // REX byte is encoded as 0100WRXB, where 402 // 0100 is 4bit fixed pattern. 403 // REX.W When 1, a 64-bit operand size is used. Otherwise, when 0, the 404 // default operand size is used (which is 32-bit for most but not all 405 // instructions). 406 // REX.R This 1-bit value is an extension to the MODRM.reg field. 407 // REX.X This 1-bit value is an extension to the SIB.index field. 408 // REX.B This 1-bit value is an extension to the MODRM.rm field or the 409 // SIB.base field. 410 // See "2.2.1.2 More on REX Prefix Fields " (2-8 Vol. 2A). 411 Loc[-3] = (Rex & ~0x4) | (Rex & 0x4) >> 2; 412 write32le(Loc, Val); 413 return; 414 } 415 416 // If we are here then we need to relax the adc, add, and, cmp, or, sbb, sub 417 // or xor operations. 418 419 // Convert "binop foo@GOTPCREL(%rip), %reg" to "binop $foo, %reg". 420 // Logic is close to one for test instruction above, but we also 421 // write opcode extension here, see below for details. 422 Loc[-1] = 0xc0 | (ModRm & 0x38) >> 3 | (Op & 0x3c); // ModR/M byte. 423 424 // Primary opcode is 0x81, opcode extension is one of: 425 // 000b = ADD, 001b is OR, 010b is ADC, 011b is SBB, 426 // 100b is AND, 101b is SUB, 110b is XOR, 111b is CMP. 427 // This value was wrote to MODRM.reg in a line above. 428 // See "3.2 INSTRUCTIONS (A-M)" (Vol. 2A 3-15), 429 // "INSTRUCTION SET REFERENCE, N-Z" (Vol. 2B 4-1) for 430 // descriptions about each operation. 431 Loc[-2] = 0x81; 432 Loc[-3] = (Rex & ~0x4) | (Rex & 0x4) >> 2; 433 write32le(Loc, Val); 434 } 435 436 template <class ELFT> 437 void X86_64<ELFT>::relaxGot(uint8_t *Loc, uint64_t Val) const { 438 const uint8_t Op = Loc[-2]; 439 const uint8_t ModRm = Loc[-1]; 440 441 // Convert "mov foo@GOTPCREL(%rip),%reg" to "lea foo(%rip),%reg". 442 if (Op == 0x8b) { 443 Loc[-2] = 0x8d; 444 write32le(Loc, Val); 445 return; 446 } 447 448 if (Op != 0xff) { 449 // We are relaxing a rip relative to an absolute, so compensate 450 // for the old -4 addend. 451 assert(!Config->Pic); 452 relaxGotNoPic(Loc, Val + 4, Op, ModRm); 453 return; 454 } 455 456 // Convert call/jmp instructions. 457 if (ModRm == 0x15) { 458 // ABI says we can convert "call *foo@GOTPCREL(%rip)" to "nop; call foo". 459 // Instead we convert to "addr32 call foo" where addr32 is an instruction 460 // prefix. That makes result expression to be a single instruction. 461 Loc[-2] = 0x67; // addr32 prefix 462 Loc[-1] = 0xe8; // call 463 write32le(Loc, Val); 464 return; 465 } 466 467 // Convert "jmp *foo@GOTPCREL(%rip)" to "jmp foo; nop". 468 // jmp doesn't return, so it is fine to use nop here, it is just a stub. 469 assert(ModRm == 0x25); 470 Loc[-2] = 0xe9; // jmp 471 Loc[3] = 0x90; // nop 472 write32le(Loc - 1, Val + 1); 473 } 474 475 // This anonymous namespace works around a warning bug in 476 // old versions of gcc. See https://gcc.gnu.org/bugzilla/show_bug.cgi?id=56480 477 namespace { 478 479 // A split-stack prologue starts by checking the amount of stack remaining 480 // in one of two ways: 481 // A) Comparing of the stack pointer to a field in the tcb. 482 // B) Or a load of a stack pointer offset with an lea to r10 or r11. 483 template <> 484 bool X86_64<ELF64LE>::adjustPrologueForCrossSplitStack(uint8_t *Loc, 485 uint8_t *End, 486 uint8_t StOther) const { 487 if (Loc + 8 >= End) 488 return false; 489 490 // Replace "cmp %fs:0x70,%rsp" and subsequent branch 491 // with "stc, nopl 0x0(%rax,%rax,1)" 492 if (memcmp(Loc, "\x64\x48\x3b\x24\x25", 5) == 0) { 493 memcpy(Loc, "\xf9\x0f\x1f\x84\x00\x00\x00\x00", 8); 494 return true; 495 } 496 497 // Adjust "lea X(%rsp),%rYY" to lea "(X - 0x4000)(%rsp),%rYY" where rYY could 498 // be r10 or r11. The lea instruction feeds a subsequent compare which checks 499 // if there is X available stack space. Making X larger effectively reserves 500 // that much additional space. The stack grows downward so subtract the value. 501 if (memcmp(Loc, "\x4c\x8d\x94\x24", 4) == 0 || 502 memcmp(Loc, "\x4c\x8d\x9c\x24", 4) == 0) { 503 // The offset bytes are encoded four bytes after the start of the 504 // instruction. 505 write32le(Loc + 4, read32le(Loc + 4) - 0x4000); 506 return true; 507 } 508 return false; 509 } 510 511 template <> 512 bool X86_64<ELF32LE>::adjustPrologueForCrossSplitStack(uint8_t *Loc, 513 uint8_t *End, 514 uint8_t StOther) const { 515 llvm_unreachable("Target doesn't support split stacks."); 516 } 517 518 } // namespace 519 520 // These nonstandard PLT entries are to migtigate Spectre v2 security 521 // vulnerability. In order to mitigate Spectre v2, we want to avoid indirect 522 // branch instructions such as `jmp *GOTPLT(%rip)`. So, in the following PLT 523 // entries, we use a CALL followed by MOV and RET to do the same thing as an 524 // indirect jump. That instruction sequence is so-called "retpoline". 525 // 526 // We have two types of retpoline PLTs as a size optimization. If `-z now` 527 // is specified, all dynamic symbols are resolved at load-time. Thus, when 528 // that option is given, we can omit code for symbol lazy resolution. 529 namespace { 530 template <class ELFT> class Retpoline : public X86_64<ELFT> { 531 public: 532 Retpoline(); 533 void writeGotPlt(uint8_t *Buf, const Symbol &S) const override; 534 void writePltHeader(uint8_t *Buf) const override; 535 void writePlt(uint8_t *Buf, uint64_t GotPltEntryAddr, uint64_t PltEntryAddr, 536 int32_t Index, unsigned RelOff) const override; 537 }; 538 539 template <class ELFT> class RetpolineZNow : public X86_64<ELFT> { 540 public: 541 RetpolineZNow(); 542 void writeGotPlt(uint8_t *Buf, const Symbol &S) const override {} 543 void writePltHeader(uint8_t *Buf) const override; 544 void writePlt(uint8_t *Buf, uint64_t GotPltEntryAddr, uint64_t PltEntryAddr, 545 int32_t Index, unsigned RelOff) const override; 546 }; 547 } // namespace 548 549 template <class ELFT> Retpoline<ELFT>::Retpoline() { 550 TargetInfo::PltHeaderSize = 48; 551 TargetInfo::PltEntrySize = 32; 552 } 553 554 template <class ELFT> 555 void Retpoline<ELFT>::writeGotPlt(uint8_t *Buf, const Symbol &S) const { 556 write64le(Buf, S.getPltVA() + 17); 557 } 558 559 template <class ELFT> void Retpoline<ELFT>::writePltHeader(uint8_t *Buf) const { 560 const uint8_t Insn[] = { 561 0xff, 0x35, 0, 0, 0, 0, // 0: pushq GOTPLT+8(%rip) 562 0x4c, 0x8b, 0x1d, 0, 0, 0, 0, // 6: mov GOTPLT+16(%rip), %r11 563 0xe8, 0x0e, 0x00, 0x00, 0x00, // d: callq next 564 0xf3, 0x90, // 12: loop: pause 565 0x0f, 0xae, 0xe8, // 14: lfence 566 0xeb, 0xf9, // 17: jmp loop 567 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, // 19: int3; .align 16 568 0x4c, 0x89, 0x1c, 0x24, // 20: next: mov %r11, (%rsp) 569 0xc3, // 24: ret 570 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, // 25: int3; padding 571 0xcc, 0xcc, 0xcc, 0xcc, // 2c: int3; padding 572 }; 573 memcpy(Buf, Insn, sizeof(Insn)); 574 575 uint64_t GotPlt = In.GotPlt->getVA(); 576 uint64_t Plt = In.Plt->getVA(); 577 write32le(Buf + 2, GotPlt - Plt - 6 + 8); 578 write32le(Buf + 9, GotPlt - Plt - 13 + 16); 579 } 580 581 template <class ELFT> 582 void Retpoline<ELFT>::writePlt(uint8_t *Buf, uint64_t GotPltEntryAddr, 583 uint64_t PltEntryAddr, int32_t Index, 584 unsigned RelOff) const { 585 const uint8_t Insn[] = { 586 0x4c, 0x8b, 0x1d, 0, 0, 0, 0, // 0: mov foo@GOTPLT(%rip), %r11 587 0xe8, 0, 0, 0, 0, // 7: callq plt+0x20 588 0xe9, 0, 0, 0, 0, // c: jmp plt+0x12 589 0x68, 0, 0, 0, 0, // 11: pushq <relocation index> 590 0xe9, 0, 0, 0, 0, // 16: jmp plt+0 591 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, // 1b: int3; padding 592 }; 593 memcpy(Buf, Insn, sizeof(Insn)); 594 595 uint64_t Off = TargetInfo::getPltEntryOffset(Index); 596 597 write32le(Buf + 3, GotPltEntryAddr - PltEntryAddr - 7); 598 write32le(Buf + 8, -Off - 12 + 32); 599 write32le(Buf + 13, -Off - 17 + 18); 600 write32le(Buf + 18, Index); 601 write32le(Buf + 23, -Off - 27); 602 } 603 604 template <class ELFT> RetpolineZNow<ELFT>::RetpolineZNow() { 605 TargetInfo::PltHeaderSize = 32; 606 TargetInfo::PltEntrySize = 16; 607 } 608 609 template <class ELFT> 610 void RetpolineZNow<ELFT>::writePltHeader(uint8_t *Buf) const { 611 const uint8_t Insn[] = { 612 0xe8, 0x0b, 0x00, 0x00, 0x00, // 0: call next 613 0xf3, 0x90, // 5: loop: pause 614 0x0f, 0xae, 0xe8, // 7: lfence 615 0xeb, 0xf9, // a: jmp loop 616 0xcc, 0xcc, 0xcc, 0xcc, // c: int3; .align 16 617 0x4c, 0x89, 0x1c, 0x24, // 10: next: mov %r11, (%rsp) 618 0xc3, // 14: ret 619 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, // 15: int3; padding 620 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, // 1a: int3; padding 621 0xcc, // 1f: int3; padding 622 }; 623 memcpy(Buf, Insn, sizeof(Insn)); 624 } 625 626 template <class ELFT> 627 void RetpolineZNow<ELFT>::writePlt(uint8_t *Buf, uint64_t GotPltEntryAddr, 628 uint64_t PltEntryAddr, int32_t Index, 629 unsigned RelOff) const { 630 const uint8_t Insn[] = { 631 0x4c, 0x8b, 0x1d, 0, 0, 0, 0, // mov foo@GOTPLT(%rip), %r11 632 0xe9, 0, 0, 0, 0, // jmp plt+0 633 0xcc, 0xcc, 0xcc, 0xcc, // int3; padding 634 }; 635 memcpy(Buf, Insn, sizeof(Insn)); 636 637 write32le(Buf + 3, GotPltEntryAddr - PltEntryAddr - 7); 638 write32le(Buf + 8, -TargetInfo::getPltEntryOffset(Index) - 12); 639 } 640 641 template <class ELFT> static TargetInfo *getTargetInfo() { 642 if (Config->ZRetpolineplt) { 643 if (Config->ZNow) { 644 static RetpolineZNow<ELFT> T; 645 return &T; 646 } 647 static Retpoline<ELFT> T; 648 return &T; 649 } 650 651 static X86_64<ELFT> T; 652 return &T; 653 } 654 655 TargetInfo *elf::getX32TargetInfo() { return getTargetInfo<ELF32LE>(); } 656 TargetInfo *elf::getX86_64TargetInfo() { return getTargetInfo<ELF64LE>(); } 657