While working on #864, I noticed we emit the wrong output when the aforementioned relaxation is suppressed:
diff --git a/libwild/src/x86_64.rs b/libwild/src/x86_64.rs
index 349b8959..55ccf7e8 100644
--- a/libwild/src/x86_64.rs
+++ b/libwild/src/x86_64.rs
@@ -287,12 +287,14 @@ impl crate::arch::Relaxation for Relaxation {
if section_bytes.get(offset - 3..offset)? == [0x48, 0x8d, 0x3d] {
match section_bytes.get(offset + 4..offset + 6) {
// PC-relative direct call
+ /*
Some(&[0xe8, _]) => {
return create(
RelaxationKind::TlsLdToLocalExec,
object::elf::R_X86_64_NONE,
);
}
+ */
// TODO: Make a test for this. Also, the description of TlsLdToLocalExec64
// possibly doesn't match what we're actually checking here.
Some(&[0x48, 0xb8]) => {
❯ cat t.c
_Thread_local long foo = 42;
int main() {
__builtin_printf("%ld\n", foo);
return 0;
}
❯ gcc t.c -ftls-model=local-dynamic -fPIC -B ~/Programming/wild --save-temps && ./a.out
WARNING: wild: --plugin /usr/lib64/gcc/x86_64-suse-linux/14/liblto_plugin.so is not yet supported
0
❯ objdump -dr a-t.o
a-t.o: file format elf64-x86-64
Disassembly of section .text:
0000000000000000 <main>:
0: 55 push %rbp
1: 48 89 e5 mov %rsp,%rbp
4: 48 8d 3d 00 00 00 00 lea 0x0(%rip),%rdi # b <main+0xb>
7: R_X86_64_TLSLD foo-0x4
b: e8 00 00 00 00 call 10 <main+0x10>
c: R_X86_64_PLT32 __tls_get_addr-0x4
10: 48 05 00 00 00 00 add $0x0,%rax
12: R_X86_64_DTPOFF32 foo
16: 48 8b 00 mov (%rax),%rax
19: 48 89 c6 mov %rax,%rsi
...
Seems to me we emit a negative offset (as on x86_64 the $tp points to the end of TLS segment), for the TLS variable ($0xfffffffffffffff8):
0000000000402120 <main>:
402120: 55 push %rbp
402121: 48 89 e5 mov %rsp,%rbp
402124: 48 8d 3d 75 12 00 00 lea 0x1275(%rip),%rdi # 4033a0 <_GLOBAL_OFFSET_TABLE_>
40212b: e8 e0 fe ff ff call 402010 <__tls_get_addr@plt>
402130: 48 05 f8 ff ff ff add $0xfffffffffffffff8,%rax
402136: 48 8b 00 mov (%rax),%rax
Which is the situation we special case here:
https://github.com/davidlattimore/wild/blob/d392e9d87ffc74536b11133aed501f1a60268d3b/libwild/src/elf_writer.rs#L2020-L2027
If I change the logic (relative to layout.tls_start_address()), then it works:
0000000000402120 <main>:
402120: 55 push %rbp
402121: 48 89 e5 mov %rsp,%rbp
402124: 48 8d 3d 75 12 00 00 lea 0x1275(%rip),%rdi # 4033a0 <_GLOBAL_OFFSET_TABLE_>
40212b: e8 e0 fe ff ff call 402010 <__tls_get_addr@plt>
402130: 48 05 00 00 00 00 add $0x0,%rax
...
❯ ./a.out
42
While working on #864, I noticed we emit the wrong output when the aforementioned relaxation is suppressed:
Seems to me we emit a negative offset (as on x86_64 the $tp points to the end of TLS segment), for the TLS variable (
$0xfffffffffffffff8):Which is the situation we special case here:
https://github.com/davidlattimore/wild/blob/d392e9d87ffc74536b11133aed501f1a60268d3b/libwild/src/elf_writer.rs#L2020-L2027
If I change the logic (relative to
layout.tls_start_address()), then it works: