Index: ELF/Arch/X86_64.cpp =================================================================== --- ELF/Arch/X86_64.cpp +++ ELF/Arch/X86_64.cpp @@ -265,8 +265,8 @@ void X86_64::relaxTlsLdToLe(uint8_t *Loc, RelType Type, uint64_t Val) const { // Convert - // leaq bar@tlsld(%rip), %rdi - // callq __tls_get_addr@PLT + // leaq bar@tlsld(%rip), %rdi # 48 8d 3d + // callq __tls_get_addr@PLT # e8 // leaq bar@dtpoff(%rax), %rcx // to // .word 0x6666 @@ -287,7 +287,24 @@ 0x66, // .byte 0x66 0x64, 0x48, 0x8b, 0x04, 0x25, 0x00, 0x00, 0x00, 0x00, // mov %fs:0,%rax }; - memcpy(Loc - 3, Inst, sizeof(Inst)); + const uint8_t NextOp = Loc[4]; + const uint8_t NextModRm = Loc[5]; + if (NextOp == 0xe8) + memcpy(Loc - 3, Inst, sizeof(Inst)); + else if (NextOp == 0xff && NextModRm == 0x15) { + // Convert + // leaq x@tlsld(%rip),%rdi # 48 8d 3d + // call *__tls_get_addr@GOTPCREL(%rip) # ff 15 + // to + // .long 0x66666666 + // movq %fs:0,%rax + // See "Table 11.9: LD -> LE Code Transition (LP64)" in + // https://raw.githubusercontent.com/wiki/hjl-tools/x86-psABI/x86-64-psABI-1.0.pdf + Loc[-3] = 0x66; + memcpy(Loc - 2, Inst, sizeof(Inst)); + } else + error(getErrorLocation(Loc - 3) + + "Expected R_X86_64_PLT32 or R_X86_64_GOTPCRELX after R_X86_64_TLSLD"); } template Index: test/ELF/tls-opt-x86_64-noplt.s =================================================================== --- /dev/null +++ test/ELF/tls-opt-x86_64-noplt.s @@ -0,0 +1,84 @@ +// REQUIRES: x86 +// RUN: llvm-mc -filetype=obj -triple=x86_64-unknown-linux %s -o %t.o +// RUN: llvm-mc -filetype=obj -triple=x86_64-unknown-linux %p/Inputs/tls-opt-gdie.s -o %tso.o +// RUN: ld.lld -shared %tso.o -o %t.so +// RUN: ld.lld --hash-style=sysv %t.o %t.so -o %t1 +// RUN: llvm-readobj -r %t1 | FileCheck --check-prefix=RELOC %s +// RUN: llvm-objdump -d %t1 | FileCheck --check-prefix=DISASM %s + +// RELOC: Relocations [ +// RELOC-NEXT: Section (4) .rela.dyn { +// RELOC-NEXT: 0x2020B0 R_X86_64_TPOFF64 tlsshared0 0x0 +// RELOC-NEXT: 0x2020B8 R_X86_64_TPOFF64 tlsshared1 0x0 +// RELOC-NEXT: } +// RELOC-NEXT: ] + +// DISASM: _start: + +// Table 11.5: GD -> IE Code Transition (LP64) +// DISASM-NEXT: 201000: 64 48 8b 04 25 00 00 00 00 movq %fs:0, %rax +// DISASM-NEXT: 201009: 48 03 05 a0 10 00 00 addq 4256(%rip), %rax +// DISASM-NEXT: 201010: 64 48 8b 04 25 00 00 00 00 movq %fs:0, %rax +// DISASM-NEXT: 201019: 48 03 05 98 10 00 00 addq 4248(%rip), %rax + +// Table 11.7: GD -> LE Code Transition (LP64) +// DISASM-NEXT: 201020: 64 48 8b 04 25 00 00 00 00 movq %fs:0, %rax +// DISASM-NEXT: 201029: 48 8d 80 f8 ff ff ff leaq -8(%rax), %rax +// DISASM-NEXT: 201030: 64 48 8b 04 25 00 00 00 00 movq %fs:0, %rax +// DISASM-NEXT: 201039: 48 8d 80 fc ff ff ff leaq -4(%rax), %rax + + +// Table 11.9: LD -> LE Code Transition (LP64) +// DISASM-NEXT: 201040: 66 66 66 66 64 48 8b 04 25 00 00 00 00 movq %fs:0, %rax +// DISASM-NEXT: 20104d: 66 66 66 66 64 48 8b 04 25 00 00 00 00 movq %fs:0, %rax + +.type tls0,@object +.section .tbss,"awT",@nobits +.globl tls0 +.align 4 +tls0: + .long 0 + .size tls0, 4 + +.type tls1,@object +.globl tls1 +.align 4 +tls1: + .long 0 + .size tls1, 4 + +.section .text +.globl _start +_start: + // Table 11.5: GD -> IE Code Transition (LP64) + .byte 0x66 + leaq tlsshared0@tlsgd(%rip),%rdi + .byte 0x66 + rex64 + call *__tls_get_addr@GOTPCREL(%rip) + + .byte 0x66 + leaq tlsshared1@tlsgd(%rip),%rdi + .byte 0x66 + rex64 + call *__tls_get_addr@GOTPCREL(%rip) + + // Table 11.7: GD -> LE Code Transition (LP64) + .byte 0x66 + leaq tls0@tlsgd(%rip),%rdi + .byte 0x66 + rex64 + call *__tls_get_addr@GOTPCREL(%rip) + + .byte 0x66 + leaq tls1@tlsgd(%rip),%rdi + .byte 0x66 + rex64 + call *__tls_get_addr@GOTPCREL(%rip) + + // Table 11.9: LD -> LE Code Transition (LP64) + leaq tls0@tlsld(%rip),%rdi + call *__tls_get_addr@GOTPCREL(%rip) + + leaq tls1@tlsld(%rip),%rdi + call *__tls_get_addr@GOTPCREL(%rip)