Skip to content

Commit b9cfa55

Browse files
committed
[X86][LLD] Handle R_X86_64_CODE_6_GOTTPOFF relocation type
For add %reg1, name@GOTTPOFF(%rip), %reg2 add name@GOTTPOFF(%rip), %reg1, %reg2 {nf} add %reg1, name@GOTTPOFF(%rip), %reg2 {nf} add name@GOTTPOFF(%rip), %reg1, %reg2 {nf} add name@GOTTPOFF(%rip), %reg add R_X86_64_CODE_6_GOTTPOFF = 50 in llvm#117277. Linker can treat R_X86_64_CODE_6_GOTTPOFF as R_X86_64_GOTTPOFF or convert the instructions above to add $name@tpoff, %reg1, %reg2 add $name@tpoff, %reg1, %reg2 {nf} add $name@tpoff, %reg1, %reg2 {nf} add $name@tpoff, %reg1, %reg2 {nf} add $name@tpoff, %reg if the first byte of the instruction at the relocation offset - 6 is 0x62 (namely, encoded w/EVEX prefix) when possible. Binutils patch: bminor/binutils-gdb@5bc71c2 Binutils mailthread: https://sourceware.org/pipermail/binutils/2024-February/132351.html ABI discussion: https://groups.google.com/g/x86-64-abi/c/FhEZjCtDLFw/m/VHDjN4orAgAJ Blog: https://kanrobert.github.io/rfc/All-about-APX-relocation
1 parent fad5ed6 commit b9cfa55

File tree

2 files changed

+43
-2
lines changed

2 files changed

+43
-2
lines changed

lld/ELF/Arch/X86_64.cpp

Lines changed: 26 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -401,6 +401,7 @@ RelExpr X86_64::getRelExpr(RelType type, const Symbol &s,
401401
case R_X86_64_CODE_4_GOTPCRELX:
402402
case R_X86_64_GOTTPOFF:
403403
case R_X86_64_CODE_4_GOTTPOFF:
404+
case R_X86_64_CODE_6_GOTTPOFF:
404405
return R_GOT_PC;
405406
case R_X86_64_GOTOFF64:
406407
return R_GOTPLTREL;
@@ -562,8 +563,9 @@ void X86_64::relaxTlsGdToIe(uint8_t *loc, const Relocation &rel,
562563
}
563564
}
564565

565-
// In some conditions, R_X86_64_GOTTPOFF/R_X86_64_CODE_4_GOTTPOFF relocation can
566-
// be optimized to R_X86_64_TPOFF32 so that it does not use GOT.
566+
// In some conditions,
567+
// R_X86_64_GOTTPOFF/R_X86_64_CODE_4_GOTTPOFF/R_X86_64_CODE_6_GOTTPOFF
568+
// relocation can be optimized to R_X86_64_TPOFF32 so that it does not use GOT.
567569
void X86_64::relaxTlsIeToLe(uint8_t *loc, const Relocation &rel,
568570
uint64_t val) const {
569571
uint8_t *inst = loc - 3;
@@ -623,6 +625,26 @@ void X86_64::relaxTlsIeToLe(uint8_t *loc, const Relocation &rel,
623625
<< "R_X86_64_CODE_4_GOTTPOFF must be used in MOVQ or ADDQ "
624626
"instructions only";
625627
}
628+
} else if (rel.type == R_X86_64_CODE_6_GOTTPOFF) {
629+
if (loc[-6] != 0x62) {
630+
Err(ctx) << getErrorLoc(ctx, loc - 6)
631+
<< "Invalid prefix with R_X86_64_CODE_6_GOTTPOFF!";
632+
return;
633+
}
634+
if (loc[-2] == 0x3 || loc[-2] == 0x1) {
635+
// "addq foo@gottpoff(%rip), %reg1, %reg2" -> "addq $foo, %reg1, %reg2"
636+
loc[-2] = 0x81;
637+
// Move R bits to B bits in EVEX payloads and ModRM byte.
638+
if ((loc[-5] & (1 << 7)) == 0)
639+
loc[-5] = (loc[-5] | (1 << 7)) & ~(1 << 5);
640+
if ((loc[-5] & (1 << 4)) == 0)
641+
loc[-5] = loc[-5] | (1 << 4) | (1 << 3);
642+
*regSlot = 0xc0 | reg;
643+
} else {
644+
Err(ctx)
645+
<< getErrorLoc(ctx, loc - 6)
646+
<< "R_X86_64_CODE_6_GOTTPOFF must be used in ADDQ instructions only";
647+
}
626648
} else {
627649
llvm_unreachable("Unsupported relocation type!");
628650
}
@@ -782,6 +804,7 @@ int64_t X86_64::getImplicitAddend(const uint8_t *buf, RelType type) const {
782804
case R_X86_64_PC32:
783805
case R_X86_64_GOTTPOFF:
784806
case R_X86_64_CODE_4_GOTTPOFF:
807+
case R_X86_64_CODE_6_GOTTPOFF:
785808
case R_X86_64_PLT32:
786809
case R_X86_64_TLSGD:
787810
case R_X86_64_TLSLD:
@@ -893,6 +916,7 @@ void X86_64::relocate(uint8_t *loc, const Relocation &rel, uint64_t val) const {
893916
break;
894917
case R_X86_64_GOTTPOFF:
895918
case R_X86_64_CODE_4_GOTTPOFF:
919+
case R_X86_64_CODE_6_GOTTPOFF:
896920
if (rel.expr == R_RELAX_TLS_IE_TO_LE) {
897921
relaxTlsIeToLe(loc, rel, val);
898922
} else {

lld/test/ELF/tls-opt.s

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,14 @@
2626
// DISASM-NEXT: addq $-8, %r16
2727
// DISASM-NEXT: addq $-8, %r28
2828
// DISASM-NEXT: addq $-4, %r16
29+
// DISASM-NEXT: addq $-10, %r16, %r16
30+
// DISASM-NEXT: addq $-10, %r16, %r20
31+
// DISASM-NEXT: addq $-10, %r16, %rax
32+
// DISASM-NEXT: addq $-10, %rax, %r16
33+
// DISASM-NEXT: addq $-10, %r8, %r16
34+
// DISASM-NEXT: addq $-10, %rax, %r12
35+
// DISASM-NEXT: {nf} addq $-10, %r8, %r16
36+
// DISASM-NEXT: {nf} addq $-10, %rax, %r12
2937

3038
// LD to LE:
3139
// DISASM-NEXT: movq %fs:0, %rax
@@ -82,6 +90,15 @@ _start:
8290
addq tls0@GOTTPOFF(%rip), %r16
8391
addq tls0@GOTTPOFF(%rip), %r28
8492
addq tls1@GOTTPOFF(%rip), %r16
93+
# NDD
94+
addq tls0@GOTTPOFF(%rip), %r16, %r16
95+
addq tls0@GOTTPOFF(%rip), %r16, %r20
96+
addq tls0@GOTTPOFF(%rip), %r16, %rax
97+
addq tls0@GOTTPOFF(%rip), %rax, %r16
98+
addq %r8, tls0@GOTTPOFF(%rip), %r16
99+
addq tls0@GOTTPOFF(%rip), %rax, %r12
100+
{nf} addq %r8, tls0@GOTTPOFF(%rip), %r16
101+
{nf} addq tls0@GOTTPOFF(%rip), %rax, %r12
85102

86103
// LD to LE
87104
leaq tls0@tlsld(%rip), %rdi

0 commit comments

Comments
 (0)