Author: ruiu Date: Wed Jan 16 15:46:28 2019 New Revision: 351401 URL: http://llvm.org/viewvc/llvm-project?rev=351401&view=rev Log: Merging r351396: ------------------------------------------------------------------------ r351396 | lekensteyn | 2019-01-16 15:28:51 -0800 (Wed, 16 Jan 2019) | 17 lines
[ELF][X86_64] Fix corrupted LD -> LE optimization for TLS without PLT The LD -> LE optimization for Thread-Local Storage without PLT requires an additional "66" prefix, otherwise the next instruction will be corrupted, causing runtime misbehavior (crashes) of the linked object. The other (GD -> IE/LD) optimizations are the same with or without PLT, but add tests for completeness. The instructions are copied from https://raw.githubusercontent.com/wiki/hjl-tools/x86-psABI/x86-64-psABI-1.0.pdf#subsection.11.1.2 This does not try to address ILP32 (x32) support. Fixes https://bugs.llvm.org/show_bug.cgi?id=37303 Reviewed By: ruiu Differential Revision: https://reviews.llvm.org/D56779 ------------------------------------------------------------------------ Added: lld/branches/release_80/test/ELF/tls-opt-x86_64-noplt.s Modified: lld/branches/release_80/ELF/Arch/X86_64.cpp Modified: lld/branches/release_80/ELF/Arch/X86_64.cpp URL: http://llvm.org/viewvc/llvm-project/lld/branches/release_80/ELF/Arch/X86_64.cpp?rev=351401&r1=351400&r2=351401&view=diff ============================================================================== --- lld/branches/release_80/ELF/Arch/X86_64.cpp (original) +++ lld/branches/release_80/ELF/Arch/X86_64.cpp Wed Jan 16 15:46:28 2019 @@ -264,15 +264,6 @@ void X86_64<ELFT>::relaxTlsIeToLe(uint8_ template <class ELFT> void X86_64<ELFT>::relaxTlsLdToLe(uint8_t *Loc, RelType Type, uint64_t Val) const { - // Convert - // leaq bar@tlsld(%rip), %rdi - // callq __tls_get_addr@PLT - // leaq bar@dtpoff(%rax), %rcx - // to - // .word 0x6666 - // .byte 0x66 - // mov %fs:0,%rax - // leaq bar@tpoff(%rax), %rcx if (Type == R_X86_64_DTPOFF64) { write64le(Loc, Val); return; @@ -287,7 +278,37 @@ void X86_64<ELFT>::relaxTlsLdToLe(uint8_ 0x66, // .byte 0x66 0x64, 0x48, 0x8b, 0x04, 0x25, 0x00, 0x00, 0x00, 0x00, // mov %fs:0,%rax }; - memcpy(Loc - 3, Inst, sizeof(Inst)); + + if (Loc[4] == 0xe8) { + // Convert + // leaq bar@tlsld(%rip), %rdi # 48 8d 3d <Loc> + // callq __tls_get_addr@PLT # e8 <disp32> + // leaq bar@dtpoff(%rax), %rcx + // to + // .word 0x6666 + // .byte 0x66 + // mov %fs:0,%rax + // leaq bar@tpoff(%rax), %rcx + memcpy(Loc - 3, Inst, sizeof(Inst)); + return; + } + + if (Loc[4] == 0xff && Loc[5] == 0x15) { + // Convert + // leaq x@tlsld(%rip),%rdi # 48 8d 3d <Loc> + // call *__tls_get_addr@GOTPCREL(%rip) # ff 15 <disp32> + // 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)); + return; + } + + error(getErrorLocation(Loc - 3) + + "expected R_X86_64_PLT32 or R_X86_64_GOTPCRELX after R_X86_64_TLSLD"); } template <class ELFT> Added: lld/branches/release_80/test/ELF/tls-opt-x86_64-noplt.s URL: http://llvm.org/viewvc/llvm-project/lld/branches/release_80/test/ELF/tls-opt-x86_64-noplt.s?rev=351401&view=auto ============================================================================== --- lld/branches/release_80/test/ELF/tls-opt-x86_64-noplt.s (added) +++ lld/branches/release_80/test/ELF/tls-opt-x86_64-noplt.s Wed Jan 16 15:46:28 2019 @@ -0,0 +1,88 @@ +// REQUIRES: x86 + +// Checks whether the TLS optimizations match the cases in Chapter 11 of +// https://raw.githubusercontent.com/wiki/hjl-tools/x86-psABI/x86-64-psABI-1.0.pdf + +// 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 %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 {{.*}} .rela.dyn { +// RELOC-NEXT: 0x2020C0 R_X86_64_TPOFF64 tlsshared0 0x0 +// RELOC-NEXT: 0x2020C8 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 b0 10 00 00 addq 4272(%rip), %rax +// DISASM-NEXT: 201010: 64 48 8b 04 25 00 00 00 00 movq %fs:0, %rax +// DISASM-NEXT: 201019: 48 03 05 a8 10 00 00 addq 4264(%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) _______________________________________________ llvm-branch-commits mailing list llvm-branch-commits@lists.llvm.org http://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-branch-commits