-
Notifications
You must be signed in to change notification settings - Fork 14.3k
[X86][LLD] Handle R_X86_64_CODE_4_GOTPC32_TLSDESC relocation type #116909
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
@llvm/pr-subscribers-lld Author: Feng Zou (fzou1) ChangesFor lea name@tlsdesc(%rip), %reg add R_X86_64_CODE_4_GOTPC32_TLSDESC = 45 in #116908. Linker can treat R_X86_64_CODE_4_GOTPC32_TLSDESC as R_X86_64_GOTPC32_TLSDESC or convert the instruction above to mov $name@tpoff, %reg if the first byte of the instruction at the relocation offset - 4 is 0xd5 (namely, encoded w/REX2 prefix) when possible. Binutils patch: bminor/binutils-gdb@a533c8d Full diff: https://github.com/llvm/llvm-project/pull/116909.diff 3 Files Affected:
diff --git a/lld/ELF/Arch/X86_64.cpp b/lld/ELF/Arch/X86_64.cpp
index e9267bd4128d18..194af96ea0321b 100644
--- a/lld/ELF/Arch/X86_64.cpp
+++ b/lld/ELF/Arch/X86_64.cpp
@@ -99,8 +99,11 @@ X86_64::X86_64(Ctx &ctx) : TargetInfo(ctx) {
int X86_64::getTlsGdRelaxSkip(RelType type) const {
// TLSDESC relocations are processed separately. See relaxTlsGdToLe below.
- return type == R_X86_64_GOTPC32_TLSDESC || type == R_X86_64_TLSDESC_CALL ? 1
- : 2;
+ return type == R_X86_64_GOTPC32_TLSDESC ||
+ type == R_X86_64_CODE_4_GOTPC32_TLSDESC ||
+ type == R_X86_64_TLSDESC_CALL
+ ? 1
+ : 2;
}
// Opcodes for the different X86_64 jmp instructions.
@@ -390,6 +393,7 @@ RelExpr X86_64::getRelExpr(RelType type, const Symbol &s,
case R_X86_64_GOT64:
return R_GOTPLT;
case R_X86_64_GOTPC32_TLSDESC:
+ case R_X86_64_CODE_4_GOTPC32_TLSDESC:
return R_TLSDESC_PC;
case R_X86_64_GOTPCREL:
case R_X86_64_GOTPCRELX:
@@ -486,18 +490,24 @@ void X86_64::relaxTlsGdToLe(uint8_t *loc, const Relocation &rel,
// The original code used a pc relative relocation and so we have to
// compensate for the -4 in had in the addend.
write32le(loc + 8, val + 4);
- } else if (rel.type == R_X86_64_GOTPC32_TLSDESC) {
+ } else if (rel.type == R_X86_64_GOTPC32_TLSDESC ||
+ rel.type == R_X86_64_CODE_4_GOTPC32_TLSDESC) {
// Convert leaq x@tlsdesc(%rip), %REG to movq $x@tpoff, %REG.
if ((loc[-3] & 0xfb) != 0x48 || loc[-2] != 0x8d ||
(loc[-1] & 0xc7) != 0x05) {
Err(ctx) << getErrorLoc(ctx, loc - 3)
- << "R_X86_64_GOTPC32_TLSDESC must be used "
- "in leaq x@tlsdesc(%rip), %REG";
+ << "R_X86_64_GOTPC32_TLSDESC/R_X86_64_CODE_4_GOTPC32_TLSDESC "
+ "must be used in leaq x@tlsdesc(%rip), %REG";
return;
}
- loc[-3] = 0x48 | ((loc[-3] >> 2) & 1);
+ if (rel.type == R_X86_64_GOTPC32_TLSDESC) {
+ loc[-3] = 0x48 | ((loc[-3] >> 2) & 1);
+ } else {
+ loc[-3] = (loc[-3] & ~0x44) | ((loc[-3] & 0x44) >> 2);
+ }
loc[-2] = 0xc7;
loc[-1] = 0xc0 | ((loc[-1] >> 3) & 7);
+
write32le(loc, val + 4);
} else {
// Convert call *x@tlsdesc(%REG) to xchg ax, ax.
@@ -527,14 +537,16 @@ void X86_64::relaxTlsGdToIe(uint8_t *loc, const Relocation &rel,
// Both code sequences are PC relatives, but since we are moving the
// constant forward by 8 bytes we have to subtract the value by 8.
write32le(loc + 8, val - 8);
- } else if (rel.type == R_X86_64_GOTPC32_TLSDESC) {
+ } else if (rel.type == R_X86_64_GOTPC32_TLSDESC ||
+ rel.type == R_X86_64_CODE_4_GOTPC32_TLSDESC) {
// Convert leaq x@tlsdesc(%rip), %REG to movq x@gottpoff(%rip), %REG.
- assert(rel.type == R_X86_64_GOTPC32_TLSDESC);
+ assert(rel.type == R_X86_64_GOTPC32_TLSDESC ||
+ rel.type == R_X86_64_CODE_4_GOTPC32_TLSDESC);
if ((loc[-3] & 0xfb) != 0x48 || loc[-2] != 0x8d ||
(loc[-1] & 0xc7) != 0x05) {
Err(ctx) << getErrorLoc(ctx, loc - 3)
- << "R_X86_64_GOTPC32_TLSDESC must be used "
- "in leaq x@tlsdesc(%rip), %REG";
+ << "R_X86_64_GOTPC32_TLSDESC/R_X86_64_CODE_4_GOTPC32_TLSDESC "
+ "must be used in leaq x@tlsdesc(%rip), %REG";
return;
}
loc[-2] = 0x8b;
@@ -830,6 +842,7 @@ void X86_64::relocate(uint8_t *loc, const Relocation &rel, uint64_t val) const {
}
break;
case R_X86_64_GOTPC32_TLSDESC:
+ case R_X86_64_CODE_4_GOTPC32_TLSDESC:
case R_X86_64_TLSDESC_CALL:
case R_X86_64_TLSGD:
if (rel.expr == R_RELAX_TLS_GD_TO_LE) {
diff --git a/lld/test/ELF/invalid/x86-64-tlsdesc-gd.s b/lld/test/ELF/invalid/x86-64-tlsdesc-gd.s
index a04087bb096a57..625248da144312 100644
--- a/lld/test/ELF/invalid/x86-64-tlsdesc-gd.s
+++ b/lld/test/ELF/invalid/x86-64-tlsdesc-gd.s
@@ -8,8 +8,13 @@
## GD to IE relaxation.
# RUN: not ld.lld %t.o %t1.so -o /dev/null 2>&1 | FileCheck -DINPUT=%t.o %s
-# CHECK: error: [[INPUT]]:(.text+0x0): R_X86_64_GOTPC32_TLSDESC must be used in leaq x@tlsdesc(%rip), %REG
+# CHECK: error: [[INPUT]]:(.text+0x0): R_X86_64_GOTPC32_TLSDESC/R_X86_64_CODE_4_GOTPC32_TLSDESC must be used in leaq x@tlsdesc(%rip), %REG
+# CHECK-NEXT: error: [[INPUT]]:(.text+0xd): R_X86_64_GOTPC32_TLSDESC/R_X86_64_CODE_4_GOTPC32_TLSDESC must be used in leaq x@tlsdesc(%rip), %REG
leaq a@tlsdesc(%rbx), %rdx
call *a@tlscall(%rdx)
movl %fs:(%rax), %eax
+
+leaq a@tlsdesc(%r16), %r20
+call *a@tlscall(%r20)
+movl %fs:(%rax), %eax
\ No newline at end of file
diff --git a/lld/test/ELF/x86-64-tlsdesc-gd.s b/lld/test/ELF/x86-64-tlsdesc-gd.s
index 64e9016925bb31..433c2b2723463b 100644
--- a/lld/test/ELF/x86-64-tlsdesc-gd.s
+++ b/lld/test/ELF/x86-64-tlsdesc-gd.s
@@ -19,42 +19,48 @@
# RUN: llvm-objdump --no-print-imm-hex -d --no-show-raw-insn %t | FileCheck --check-prefix=IE %s
# GD-RELA: .rela.dyn {
-# GD-RELA-NEXT: 0x23D0 R_X86_64_TLSDESC - 0xB
-# GD-RELA-NEXT: 0x23B0 R_X86_64_TLSDESC a 0x0
-# GD-RELA-NEXT: 0x23C0 R_X86_64_TLSDESC c 0x0
+# GD-RELA-NEXT: 0x23E0 R_X86_64_TLSDESC - 0xB
+# GD-RELA-NEXT: 0x23C0 R_X86_64_TLSDESC a 0x0
+# GD-RELA-NEXT: 0x23D0 R_X86_64_TLSDESC c 0x0
# GD-RELA-NEXT: }
# GD-RELA: Hex dump of section '.got':
-# GD-RELA-NEXT: 0x000023b0 00000000 00000000 00000000 00000000
# GD-RELA-NEXT: 0x000023c0 00000000 00000000 00000000 00000000
# GD-RELA-NEXT: 0x000023d0 00000000 00000000 00000000 00000000
+# GD-RELA-NEXT: 0x000023e0 00000000 00000000 00000000 00000000
# GD-REL: .rel.dyn {
-# GD-REL-NEXT: 0x23B8 R_X86_64_TLSDESC -
-# GD-REL-NEXT: 0x2398 R_X86_64_TLSDESC a
-# GD-REL-NEXT: 0x23A8 R_X86_64_TLSDESC c
+# GD-REL-NEXT: 0x23C8 R_X86_64_TLSDESC -
+# GD-REL-NEXT: 0x23A8 R_X86_64_TLSDESC a
+# GD-REL-NEXT: 0x23B8 R_X86_64_TLSDESC c
# GD-REL-NEXT: }
# GD-REL: Hex dump of section '.got':
-# GD-REL-NEXT: 0x00002398 00000000 00000000 00000000 00000000
# GD-REL-NEXT: 0x000023a8 00000000 00000000 00000000 00000000
-# GD-REL-NEXT: 0x000023b8 00000000 00000000 0b000000 00000000
+# GD-REL-NEXT: 0x000023b8 00000000 00000000 00000000 00000000
+# GD-REL-NEXT: 0x000023c8 00000000 00000000 0b000000 00000000
-## &.rela.dyn[a]-pc = 0x23B0-0x12e7 = 4297
-# GD: leaq 4297(%rip), %rax
+## &.rela.dyn[a]-pc = 0x23C0-0x12e7 = 4313
+# GD: leaq 4313(%rip), %rax
# GD-NEXT: 12e7: callq *(%rax)
# GD-NEXT: movl %fs:(%rax), %eax
-## &.rela.dyn[b]-pc = 0x23D0-0x12f3 = 4317
-# GD-NEXT: leaq 4317(%rip), %rcx
+## &.rela.dyn[b]-pc = 0x23E0-0x12f3 = 4333
+# GD-NEXT: leaq 4333(%rip), %rcx
# GD-NEXT: 12f3: movq %rcx, %rax
# GD-NEXT: callq *(%rax)
# GD-NEXT: movl %fs:(%rax), %eax
-## &.rela.dyn[c]-pc = 0x23C0-0x1302 = 4286
-# GD-NEXT: leaq 4286(%rip), %r15
+## &.rela.dyn[c]-pc = 0x23D0-0x1302 = 4302
+# GD-NEXT: leaq 4302(%rip), %r15
# GD-NEXT: 1302: movq %r15, %rax
# GD-NEXT: callq *(%rax)
# GD-NEXT: movl %fs:(%rax), %eax
+## &.rela.dyn[c]-pc = 0x23D0-0x1312 = 4286
+# GD-NEXT: leaq 4286(%rip), %r16
+# GD-NEXT: 1312: movq %r16, %rax
+# GD-NEXT: callq *(%rax)
+# GD-NEXT: movl %fs:(%rax), %eax
+
# NOREL: no relocations
## tpoff(a) = st_value(a) - tls_size = -8
@@ -71,9 +77,14 @@
# LE-NEXT: movq %r15, %rax
# LE-NEXT: nop
# LE-NEXT: movl %fs:(%rax), %eax
+## tpoff(c) = st_value(c) - tls_size = -4
+# LE: movq $-4, %r16
+# LE-NEXT: movq %r16, %rax
+# LE-NEXT: nop
+# LE-NEXT: movl %fs:(%rax), %eax
# IE-REL: .rela.dyn {
-# IE-REL-NEXT: 0x202378 R_X86_64_TPOFF64 c 0x0
+# IE-REL-NEXT: 0x202388 R_X86_64_TPOFF64 c 0x0
# IE-REL-NEXT: }
## a is relaxed to use LE.
@@ -84,11 +95,16 @@
# IE-NEXT: movq %rcx, %rax
# IE-NEXT: nop
# IE-NEXT: movl %fs:(%rax), %eax
-## &.rela.dyn[c]-pc = 0x202378 - 0x2012aa = 4302
-# IE-NEXT: movq 4302(%rip), %r15
+## &.rela.dyn[c]-pc = 0x202388 - 0x2012aa = 4318
+# IE-NEXT: movq 4318(%rip), %r15
# IE-NEXT: 2012aa: movq %r15, %rax
# IE-NEXT: nop
# IE-NEXT: movl %fs:(%rax), %eax
+## &.rela.dyn[c]-pc = 0x202388 - 0x2012ba = 4302
+# IE-NEXT: movq 4302(%rip), %r16
+# IE-NEXT: 2012ba: movq %r16, %rax
+# IE-NEXT: nop
+# IE-NEXT: movl %fs:(%rax), %eax
leaq a@tlsdesc(%rip), %rax
call *a@tlscall(%rax)
@@ -106,6 +122,11 @@ movq %r15, %rax
call *c@tlscall(%rax)
movl %fs:(%rax), %eax
+leaq c@tlsdesc(%rip), %r16
+movq %r16, %rax
+call *c@tlscall(%rax)
+movl %fs:(%rax), %eax
+
.section .tbss
.globl a
.zero 8
|
@llvm/pr-subscribers-lld-elf Author: Feng Zou (fzou1) ChangesFor lea name@tlsdesc(%rip), %reg add R_X86_64_CODE_4_GOTPC32_TLSDESC = 45 in #116908. Linker can treat R_X86_64_CODE_4_GOTPC32_TLSDESC as R_X86_64_GOTPC32_TLSDESC or convert the instruction above to mov $name@tpoff, %reg if the first byte of the instruction at the relocation offset - 4 is 0xd5 (namely, encoded w/REX2 prefix) when possible. Binutils patch: bminor/binutils-gdb@a533c8d Full diff: https://github.com/llvm/llvm-project/pull/116909.diff 3 Files Affected:
diff --git a/lld/ELF/Arch/X86_64.cpp b/lld/ELF/Arch/X86_64.cpp
index e9267bd4128d18..194af96ea0321b 100644
--- a/lld/ELF/Arch/X86_64.cpp
+++ b/lld/ELF/Arch/X86_64.cpp
@@ -99,8 +99,11 @@ X86_64::X86_64(Ctx &ctx) : TargetInfo(ctx) {
int X86_64::getTlsGdRelaxSkip(RelType type) const {
// TLSDESC relocations are processed separately. See relaxTlsGdToLe below.
- return type == R_X86_64_GOTPC32_TLSDESC || type == R_X86_64_TLSDESC_CALL ? 1
- : 2;
+ return type == R_X86_64_GOTPC32_TLSDESC ||
+ type == R_X86_64_CODE_4_GOTPC32_TLSDESC ||
+ type == R_X86_64_TLSDESC_CALL
+ ? 1
+ : 2;
}
// Opcodes for the different X86_64 jmp instructions.
@@ -390,6 +393,7 @@ RelExpr X86_64::getRelExpr(RelType type, const Symbol &s,
case R_X86_64_GOT64:
return R_GOTPLT;
case R_X86_64_GOTPC32_TLSDESC:
+ case R_X86_64_CODE_4_GOTPC32_TLSDESC:
return R_TLSDESC_PC;
case R_X86_64_GOTPCREL:
case R_X86_64_GOTPCRELX:
@@ -486,18 +490,24 @@ void X86_64::relaxTlsGdToLe(uint8_t *loc, const Relocation &rel,
// The original code used a pc relative relocation and so we have to
// compensate for the -4 in had in the addend.
write32le(loc + 8, val + 4);
- } else if (rel.type == R_X86_64_GOTPC32_TLSDESC) {
+ } else if (rel.type == R_X86_64_GOTPC32_TLSDESC ||
+ rel.type == R_X86_64_CODE_4_GOTPC32_TLSDESC) {
// Convert leaq x@tlsdesc(%rip), %REG to movq $x@tpoff, %REG.
if ((loc[-3] & 0xfb) != 0x48 || loc[-2] != 0x8d ||
(loc[-1] & 0xc7) != 0x05) {
Err(ctx) << getErrorLoc(ctx, loc - 3)
- << "R_X86_64_GOTPC32_TLSDESC must be used "
- "in leaq x@tlsdesc(%rip), %REG";
+ << "R_X86_64_GOTPC32_TLSDESC/R_X86_64_CODE_4_GOTPC32_TLSDESC "
+ "must be used in leaq x@tlsdesc(%rip), %REG";
return;
}
- loc[-3] = 0x48 | ((loc[-3] >> 2) & 1);
+ if (rel.type == R_X86_64_GOTPC32_TLSDESC) {
+ loc[-3] = 0x48 | ((loc[-3] >> 2) & 1);
+ } else {
+ loc[-3] = (loc[-3] & ~0x44) | ((loc[-3] & 0x44) >> 2);
+ }
loc[-2] = 0xc7;
loc[-1] = 0xc0 | ((loc[-1] >> 3) & 7);
+
write32le(loc, val + 4);
} else {
// Convert call *x@tlsdesc(%REG) to xchg ax, ax.
@@ -527,14 +537,16 @@ void X86_64::relaxTlsGdToIe(uint8_t *loc, const Relocation &rel,
// Both code sequences are PC relatives, but since we are moving the
// constant forward by 8 bytes we have to subtract the value by 8.
write32le(loc + 8, val - 8);
- } else if (rel.type == R_X86_64_GOTPC32_TLSDESC) {
+ } else if (rel.type == R_X86_64_GOTPC32_TLSDESC ||
+ rel.type == R_X86_64_CODE_4_GOTPC32_TLSDESC) {
// Convert leaq x@tlsdesc(%rip), %REG to movq x@gottpoff(%rip), %REG.
- assert(rel.type == R_X86_64_GOTPC32_TLSDESC);
+ assert(rel.type == R_X86_64_GOTPC32_TLSDESC ||
+ rel.type == R_X86_64_CODE_4_GOTPC32_TLSDESC);
if ((loc[-3] & 0xfb) != 0x48 || loc[-2] != 0x8d ||
(loc[-1] & 0xc7) != 0x05) {
Err(ctx) << getErrorLoc(ctx, loc - 3)
- << "R_X86_64_GOTPC32_TLSDESC must be used "
- "in leaq x@tlsdesc(%rip), %REG";
+ << "R_X86_64_GOTPC32_TLSDESC/R_X86_64_CODE_4_GOTPC32_TLSDESC "
+ "must be used in leaq x@tlsdesc(%rip), %REG";
return;
}
loc[-2] = 0x8b;
@@ -830,6 +842,7 @@ void X86_64::relocate(uint8_t *loc, const Relocation &rel, uint64_t val) const {
}
break;
case R_X86_64_GOTPC32_TLSDESC:
+ case R_X86_64_CODE_4_GOTPC32_TLSDESC:
case R_X86_64_TLSDESC_CALL:
case R_X86_64_TLSGD:
if (rel.expr == R_RELAX_TLS_GD_TO_LE) {
diff --git a/lld/test/ELF/invalid/x86-64-tlsdesc-gd.s b/lld/test/ELF/invalid/x86-64-tlsdesc-gd.s
index a04087bb096a57..625248da144312 100644
--- a/lld/test/ELF/invalid/x86-64-tlsdesc-gd.s
+++ b/lld/test/ELF/invalid/x86-64-tlsdesc-gd.s
@@ -8,8 +8,13 @@
## GD to IE relaxation.
# RUN: not ld.lld %t.o %t1.so -o /dev/null 2>&1 | FileCheck -DINPUT=%t.o %s
-# CHECK: error: [[INPUT]]:(.text+0x0): R_X86_64_GOTPC32_TLSDESC must be used in leaq x@tlsdesc(%rip), %REG
+# CHECK: error: [[INPUT]]:(.text+0x0): R_X86_64_GOTPC32_TLSDESC/R_X86_64_CODE_4_GOTPC32_TLSDESC must be used in leaq x@tlsdesc(%rip), %REG
+# CHECK-NEXT: error: [[INPUT]]:(.text+0xd): R_X86_64_GOTPC32_TLSDESC/R_X86_64_CODE_4_GOTPC32_TLSDESC must be used in leaq x@tlsdesc(%rip), %REG
leaq a@tlsdesc(%rbx), %rdx
call *a@tlscall(%rdx)
movl %fs:(%rax), %eax
+
+leaq a@tlsdesc(%r16), %r20
+call *a@tlscall(%r20)
+movl %fs:(%rax), %eax
\ No newline at end of file
diff --git a/lld/test/ELF/x86-64-tlsdesc-gd.s b/lld/test/ELF/x86-64-tlsdesc-gd.s
index 64e9016925bb31..433c2b2723463b 100644
--- a/lld/test/ELF/x86-64-tlsdesc-gd.s
+++ b/lld/test/ELF/x86-64-tlsdesc-gd.s
@@ -19,42 +19,48 @@
# RUN: llvm-objdump --no-print-imm-hex -d --no-show-raw-insn %t | FileCheck --check-prefix=IE %s
# GD-RELA: .rela.dyn {
-# GD-RELA-NEXT: 0x23D0 R_X86_64_TLSDESC - 0xB
-# GD-RELA-NEXT: 0x23B0 R_X86_64_TLSDESC a 0x0
-# GD-RELA-NEXT: 0x23C0 R_X86_64_TLSDESC c 0x0
+# GD-RELA-NEXT: 0x23E0 R_X86_64_TLSDESC - 0xB
+# GD-RELA-NEXT: 0x23C0 R_X86_64_TLSDESC a 0x0
+# GD-RELA-NEXT: 0x23D0 R_X86_64_TLSDESC c 0x0
# GD-RELA-NEXT: }
# GD-RELA: Hex dump of section '.got':
-# GD-RELA-NEXT: 0x000023b0 00000000 00000000 00000000 00000000
# GD-RELA-NEXT: 0x000023c0 00000000 00000000 00000000 00000000
# GD-RELA-NEXT: 0x000023d0 00000000 00000000 00000000 00000000
+# GD-RELA-NEXT: 0x000023e0 00000000 00000000 00000000 00000000
# GD-REL: .rel.dyn {
-# GD-REL-NEXT: 0x23B8 R_X86_64_TLSDESC -
-# GD-REL-NEXT: 0x2398 R_X86_64_TLSDESC a
-# GD-REL-NEXT: 0x23A8 R_X86_64_TLSDESC c
+# GD-REL-NEXT: 0x23C8 R_X86_64_TLSDESC -
+# GD-REL-NEXT: 0x23A8 R_X86_64_TLSDESC a
+# GD-REL-NEXT: 0x23B8 R_X86_64_TLSDESC c
# GD-REL-NEXT: }
# GD-REL: Hex dump of section '.got':
-# GD-REL-NEXT: 0x00002398 00000000 00000000 00000000 00000000
# GD-REL-NEXT: 0x000023a8 00000000 00000000 00000000 00000000
-# GD-REL-NEXT: 0x000023b8 00000000 00000000 0b000000 00000000
+# GD-REL-NEXT: 0x000023b8 00000000 00000000 00000000 00000000
+# GD-REL-NEXT: 0x000023c8 00000000 00000000 0b000000 00000000
-## &.rela.dyn[a]-pc = 0x23B0-0x12e7 = 4297
-# GD: leaq 4297(%rip), %rax
+## &.rela.dyn[a]-pc = 0x23C0-0x12e7 = 4313
+# GD: leaq 4313(%rip), %rax
# GD-NEXT: 12e7: callq *(%rax)
# GD-NEXT: movl %fs:(%rax), %eax
-## &.rela.dyn[b]-pc = 0x23D0-0x12f3 = 4317
-# GD-NEXT: leaq 4317(%rip), %rcx
+## &.rela.dyn[b]-pc = 0x23E0-0x12f3 = 4333
+# GD-NEXT: leaq 4333(%rip), %rcx
# GD-NEXT: 12f3: movq %rcx, %rax
# GD-NEXT: callq *(%rax)
# GD-NEXT: movl %fs:(%rax), %eax
-## &.rela.dyn[c]-pc = 0x23C0-0x1302 = 4286
-# GD-NEXT: leaq 4286(%rip), %r15
+## &.rela.dyn[c]-pc = 0x23D0-0x1302 = 4302
+# GD-NEXT: leaq 4302(%rip), %r15
# GD-NEXT: 1302: movq %r15, %rax
# GD-NEXT: callq *(%rax)
# GD-NEXT: movl %fs:(%rax), %eax
+## &.rela.dyn[c]-pc = 0x23D0-0x1312 = 4286
+# GD-NEXT: leaq 4286(%rip), %r16
+# GD-NEXT: 1312: movq %r16, %rax
+# GD-NEXT: callq *(%rax)
+# GD-NEXT: movl %fs:(%rax), %eax
+
# NOREL: no relocations
## tpoff(a) = st_value(a) - tls_size = -8
@@ -71,9 +77,14 @@
# LE-NEXT: movq %r15, %rax
# LE-NEXT: nop
# LE-NEXT: movl %fs:(%rax), %eax
+## tpoff(c) = st_value(c) - tls_size = -4
+# LE: movq $-4, %r16
+# LE-NEXT: movq %r16, %rax
+# LE-NEXT: nop
+# LE-NEXT: movl %fs:(%rax), %eax
# IE-REL: .rela.dyn {
-# IE-REL-NEXT: 0x202378 R_X86_64_TPOFF64 c 0x0
+# IE-REL-NEXT: 0x202388 R_X86_64_TPOFF64 c 0x0
# IE-REL-NEXT: }
## a is relaxed to use LE.
@@ -84,11 +95,16 @@
# IE-NEXT: movq %rcx, %rax
# IE-NEXT: nop
# IE-NEXT: movl %fs:(%rax), %eax
-## &.rela.dyn[c]-pc = 0x202378 - 0x2012aa = 4302
-# IE-NEXT: movq 4302(%rip), %r15
+## &.rela.dyn[c]-pc = 0x202388 - 0x2012aa = 4318
+# IE-NEXT: movq 4318(%rip), %r15
# IE-NEXT: 2012aa: movq %r15, %rax
# IE-NEXT: nop
# IE-NEXT: movl %fs:(%rax), %eax
+## &.rela.dyn[c]-pc = 0x202388 - 0x2012ba = 4302
+# IE-NEXT: movq 4302(%rip), %r16
+# IE-NEXT: 2012ba: movq %r16, %rax
+# IE-NEXT: nop
+# IE-NEXT: movl %fs:(%rax), %eax
leaq a@tlsdesc(%rip), %rax
call *a@tlscall(%rax)
@@ -106,6 +122,11 @@ movq %r15, %rax
call *c@tlscall(%rax)
movl %fs:(%rax), %eax
+leaq c@tlsdesc(%rip), %r16
+movq %r16, %rax
+call *c@tlscall(%rax)
+movl %fs:(%rax), %eax
+
.section .tbss
.globl a
.zero 8
|
For lea name@tlsdesc(%rip), %reg add R_X86_64_CODE_4_GOTPC32_TLSDESC = 45 in llvm#116908. Linker can treat R_X86_64_CODE_4_GOTPC32_TLSDESC as R_X86_64_GOTPC32_TLSDESC or convert the instruction above to mov $name@tpoff, %reg if the first byte of the instruction at the relocation offset - 4 is 0xd5 (namely, encoded w/REX2 prefix) when possible. Binutils patch: bminor/binutils-gdb@a533c8d Binutils mailthread: https://sourceware.org/pipermail/binutils/2023-December/131463.html ABI discussion: https://groups.google.com/g/x86-64-abi/c/ACwD-UQXVDs/m/vrgTenKyFwAJ Blog: https://kanrobert.github.io/rfc/All-about-APX-relocation
796fa80
to
2685e0e
Compare
@MaskRay / @KanRobert , could you please review this PR? Thanks. |
@@ -486,18 +490,26 @@ void X86_64::relaxTlsGdToLe(uint8_t *loc, const Relocation &rel, | |||
// The original code used a pc relative relocation and so we have to | |||
// compensate for the -4 in had in the addend. | |||
write32le(loc + 8, val + 4); | |||
} else if (rel.type == R_X86_64_GOTPC32_TLSDESC) { | |||
} else if (rel.type == R_X86_64_GOTPC32_TLSDESC || | |||
rel.type == R_X86_64_CODE_4_GOTPC32_TLSDESC) { | |||
// Convert leaq x@tlsdesc(%rip), %REG to movq $x@tpoff, %REG. | |||
if ((loc[-3] & 0xfb) != 0x48 || loc[-2] != 0x8d || |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It seems you're missing some tests. The (loc[-3] & 0xfb) != 0x48
is used to check the X and B bit for REX prefix, it would fail for REX2 prefix.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Never mind. I got something wrong. It works for REX2 too if we don't support
{rex2} leaq x@tlsdesc(%rip), %r8
for this relocation.
Currently, compiler won't emit such code.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM
@MaskRay , friendly ping. |
I'll commit first. Any further comments are welcome. |
This patch looks good. I delegated the review to Kan. Note, as a new contributor, it's important to avoid rushing through reviews. |
Sorry for that. Noted. Thanks. |
For
lea name@tlsdesc(%rip), %reg
add
R_X86_64_CODE_4_GOTPC32_TLSDESC = 45
in #116908.
Linker can treat R_X86_64_CODE_4_GOTPC32_TLSDESC as R_X86_64_GOTPC32_TLSDESC or convert the instruction above to
mov $name@tpoff, %reg
if the first byte of the instruction at the relocation offset - 4 is 0xd5 (namely, encoded w/REX2 prefix) when possible.
Binutils patch: bminor/binutils-gdb@a533c8d
Binutils mailthread: https://sourceware.org/pipermail/binutils/2023-December/131463.html
ABI discussion: https://groups.google.com/g/x86-64-abi/c/ACwD-UQXVDs/m/vrgTenKyFwAJ
Blog: https://kanrobert.github.io/rfc/All-about-APX-relocation