Bug 25416 - TLSDESC relaxation doesn't work for x32
Summary: TLSDESC relaxation doesn't work for x32
Status: RESOLVED FIXED
Alias: None
Product: binutils
Classification: Unclassified
Component: ld (show other bugs)
Version: 2.34
: P2 normal
Target Milestone: 2.35
Assignee: Not yet assigned to anyone
URL:
Keywords:
Depends on:
Blocks:
 
Reported: 2020-01-18 21:13 UTC by H.J. Lu
Modified: 2020-01-22 14:26 UTC (History)
0 users

See Also:
Host:
Target: x86-64
Build:
Last reconfirmed:


Attachments

Note You need to log in before you can comment on or make changes to this bug.
Description H.J. Lu 2020-01-18 21:13:13 UTC

    
Comment 1 H.J. Lu 2020-01-18 21:17:38 UTC
For X32, TLSDESC generates

1. -maddress-mode=short

	lea	foo@TLSDESC(%rip), %eax
	call	*foo@TLSCALL(%eax)

2. -maddress-mode=long

	lea	foo@TLSDESC(%rip), %rax
	call	*foo@TLSCALL(%rax)

Currently, I got

[hjl@gnu-cfl-2 tls-x32]$ cat main.c
#include <stdlib.h>
#include <stdio.h>

__thread int bar = 301;

extern int *test1 (int);
extern int *test2 (int);

int
main ()
{
  int *p;
  p = test1 (30);
  if (*p != 30)
    abort ();
  *p = 40;
  test1 (40);
  p = test2 (301);
  if (*p != 301)
    abort ();
  if (p != &bar)
    abort ();
  *p = 40;
  test2 (40);
  puts ("PASS");
  return 0;
}
[hjl@gnu-cfl-2 tls-x32]$ cat tlsdes.S
	.text
	.p2align 4
	.globl	test1
	.type	test1, @function
test1:
	.cfi_startproc
	subl	$8, %esp
	.cfi_def_cfa_offset 16
	lea	foo@TLSDESC(%rip), %eax
	call	*foo@TLSCALL(%eax)
	addl	%fs:0, %eax
	cmpl	%edi, (%eax)
	jne	.L5
	addl	$8, %esp
	.cfi_remember_state
	.cfi_def_cfa_offset 8
	ret
.L5:
	.cfi_restore_state
	call	abort@PLT
	.cfi_endproc
	.size	test1, .-test1
	.p2align 4
	.globl	test2
	.type	test2, @function
test2:
	.cfi_startproc
	subl	$8, %esp
	.cfi_def_cfa_offset 16
	lea	bar@TLSDESC(%rip), %eax
	call	*bar@TLSCALL(%eax)
	addl	%fs:0, %eax
	cmpl	%edi, (%eax)
	jne	.L9
	addl	$8, %esp
	.cfi_remember_state
	.cfi_def_cfa_offset 8
	ret
.L9:
	.cfi_restore_state
	call	abort@PLT
	.cfi_endproc
	.size	test2, .-test2
	.section	.tdata,"awT",@progbits
	.align 4
	.type	foo, @object
	.size	foo, 4
foo:
	.long	30
	.section	.note.GNU-stack,"",@progbits
[hjl@gnu-cfl-2 tls-x32]$ gcc -mx32 tlsdes.S main.c
/usr/local/bin/ld: /tmp/ccdQjj3W.o: TLS transition from R_X86_64_GOTPC32_TLSDESC to R_X86_64_TPOFF32 against `foo' at 0x5 in section `.text' failed
collect2: error: ld returned 1 exit status
[hjl@gnu-cfl-2 tls-x32]$
Comment 2 H.J. Lu 2020-01-19 01:46:25 UTC
For x32, we must encode "lea x@TLSDESC(%rip), %eax" with a REX prefix
even if it isn't required.  Otherwise linker can’t safely perform
GDesc -> LE optimization.
Comment 3 Sourceware Commits 2020-01-20 15:04:53 UTC
The master branch has been updated by H.J. Lu <hjl@sourceware.org>:

https://sourceware.org/git/gitweb.cgi?p=binutils-gdb.git;h=14470f0755dbc942aa684ed647df978ddfc7cff2

commit 14470f0755dbc942aa684ed647df978ddfc7cff2
Author: H.J. Lu <hjl.tools@gmail.com>
Date:   Mon Jan 20 06:58:51 2020 -0800

    x86-64: Fix TLSDESC relaxation for x32
    
    For x32, we must encode "lea x@TLSDESC(%rip), %reg" with a REX prefix
    even if it isn't required.  Otherwise linker can’t safely perform
    GDesc -> IE/LE optimization.  X32 TLSDESC sequences can be:
    
    40 8d 05 00 00 00 00	rex lea	x@TLSDESC(%rip), %reg
    ...
    67 ff 10		call	*x@TLSCALL(%eax)
    
    or the same sequence as LP64:
    
    48 8d 05 00 00 00 00	lea	foo@TLSDESC(%rip), %reg
    ...
    ff 10			call	*foo@TLSCALL(%rax)
    
    We need to support both sequences for x32.  For both GDesc -> IE/LE
    transitions,
    
    67 ff 10		call	*x@TLSCALL(%eax)
    
    should relaxed to
    
    0f 1f 00		nopl	(%rax)
    
    For GDesc -> LE transition,
    
    40 8d 05 00 00 00 00	rex lea	x@TLSDESC(%rip), %reg
    
    should relaxed to
    
    40 c7 c0 fc ff ff ff	rex movl $x@tpoff, %reg
    
    For GDesc -> IE transition,
    
    40 8d 05 00 00 00 00	rex lea	x@TLSDESC(%rip), %reg
    
    should relaxed to
    
    40 8b 05 00 00 00 00	rex movl x@gottpoff(%rip), %eax
    
    bfd/
    
    	PR ld/25416
    	* elf64-x86-64.c (elf_x86_64_check_tls_transition): Support
    	"rex leal x@tlsdesc(%rip), %reg" and "call *x@tlsdesc(%eax)" in
    	X32 mode.
    	(elf_x86_64_relocate_section): In x32 mode, for GDesc -> LE
    	transition, relax "rex leal x@tlsdesc(%rip), %reg" to
    	"rex movl $x@tpoff, %reg", for GDesc -> IE transition, relax
    	"rex leal x@tlsdesc(%rip), %reg" to
    	"rex movl x@gottpoff(%rip), %eax".  For both transitions, relax
    	"call *(%eax)" to "nopl (%rax)".
    
    gas/
    
    	PR ld/25416
    	* config/tc-i386.c (output_insn): Add a dummy REX_OPCODE prefix
    	for lea with R_X86_64_GOTPC32_TLSDESC relocation when generating
    	x32 object.
    	* testsuite/gas/i386/ilp32/x32-tls.d: Updated.
    	* testsuite/gas/i386/ilp32/x32-tls.s: Add tests for lea with
    	R_X86_64_GOTPC32_TLSDESC relocation.
    
    ld/
    
    	PR ld/25416
    	* testsuite/ld-x86-64/pr25416-1.s: New file
    	* testsuite/ld-x86-64/pr25416-1a.d: Likewise.
    	* testsuite/ld-x86-64/pr25416-1b.d: Likewise.
    	* testsuite/ld-x86-64/pr25416-1.s: Likewise.
    	* testsuite/ld-x86-64/pr25416-2.s: Likewise.
    	* testsuite/ld-x86-64/pr25416-2a.d: Likewise.
    	* testsuite/ld-x86-64/pr25416-2b.d: Likewise.
    	* testsuite/ld-x86-64/pr25416-3.d: Likewise.
    	* testsuite/ld-x86-64/pr25416-3.s: Likewise.
    	* testsuite/ld-x86-64/pr25416-4.d: Likewise.
    	* testsuite/ld-x86-64/pr25416-4.s: Likewise.
    	* testsuite/ld-x86-64/pr25416-5a.c: Likewise.
    	* testsuite/ld-x86-64/pr25416-5b.s: Likewise.
    	* testsuite/ld-x86-64/pr25416-5c.s: Likewise.
    	* testsuite/ld-x86-64/pr25416-5d.s: Likewise.
    	* testsuite/ld-x86-64/pr25416-5e.s: Likewise.
    	* testsuite/ld-x86-64/x86-64.exp: Run PR ld/25416 tests.
Comment 4 H.J. Lu 2020-01-20 15:15:23 UTC
Fixed for 2.35.
Comment 5 Sourceware Commits 2020-01-22 14:26:05 UTC
The master branch has been updated by H.J. Lu <hjl@sourceware.org>:

https://sourceware.org/git/gitweb.cgi?p=binutils-gdb.git;h=6a462ad49ec13bec4659f2a8fb2301cac9742da9

commit 6a462ad49ec13bec4659f2a8fb2301cac9742da9
Author: H.J. Lu <hjl.tools@gmail.com>
Date:   Wed Jan 22 06:22:41 2020 -0800

    x86-64: Skip GNU2 TLS tests only without compiler support
    
    After fixing:
    
    https://gcc.gnu.org/bugzilla/show_bug.cgi?id=93319
    https://sourceware.org/bugzilla/show_bug.cgi?id=25416
    
    -mtls-dialect=gnu2 is working for x32 with GCC 10.  Skip GNU2 TLS tests
    only if compiler doesn't support it.
    
    	PR ld/25416
    	* testsuite/ld-x86-64/tls.exp: Skip GNU2 TLS tests only without
    	compiler support.