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