Created attachment 5818 [details] Assembly code that fails with enabled linker relaxations This is a followup from gcc PR 49515 [1]. Attached testcase fails with linker relaxations on alphaev68-pc-linux-gnu: uros@monolith ~ $ gcc thr-init-2.s uros@monolith ~ $ ./a.out a=2 fstat=33554434 Aborted uros@monolith ~ $ gcc -Wl,--no-relax thr-init-2.s uros@monolith ~ $ ./a.out uros@monolith ~ $ ld --version GNU ld (GNU Binutils) 2.21 Copyright 2010 Free Software Foundation, Inc. ... But the bug also exists in latest snapshot: GNU ld (GNU Binutils) 2.21.52.20110623 The c source: --cut here-- /* { dg-do run } */ /* { dg-require-effective-target tls_runtime } */ /* { dg-add-options tls } */ extern int printf (char *,...); extern void abort() ; static __thread int fstat ; static __thread int fstat = 1; static __thread int fstat ; int test_code(int b) { fstat += b ; return fstat; } int main (int ac, char *av[]) { int a = test_code(1); if ( a != 2 || fstat != 2 ) { printf ("a=%d fstat=%d\n", a, fstat) ; abort (); } return 0; } --cut here-- compiled with -O2 -fpic to produce attached assembly code. [1] http://gcc.gnu.org/bugzilla/show_bug.cgi?id=49515
The difference to working code (test_code function) from gcc-4.4.5 is: @@ -26,17 +26,18 @@ ldah $1,fstat($0) !dtprelhi ldq $26,0($30) lda $29,0($29) !gpdisp!3 - ldl $0,fstat($1) !dtprello - addl $0,$9,$0 + ldl $16,fstat($1) !dtprello + addl $16,$9,$16 ldq $9,8($30) - stl $0,fstat($1) !dtprello + addl $31,$16,$0 + stl $16,fstat($1) !dtprello lda $30,16($30) ret $31,($26),1 Please note that $0 is used instead (extra addl is just a move from $16 to $0).
I think that I got the problem, but the wrong relaxation is in main. in an object, we have following part of test_code: 10: 00 00 5e b7 stq ra,0(sp) 14: 08 00 3e b5 stq s0,8(sp) 18: 09 04 f0 47 mov a0,s0 1c: 00 00 1d 22 lda a0,0(gp) 1c: TLSLDM fstat 20: 00 40 5b 6b jsr ra,(t12),24 <test_code+0x24> 20: LITUSE .text+0x5 20: HINT __tls_get_addr 24: 00 00 ba 27 ldah gp,0(ra) 24: GPDISP .text+0xc 28: 00 00 20 24 ldah t0,0(v0) 28: DTPRELHI fstat 2c: 00 00 5e a7 ldq ra,0(sp) this links in the final link to: 1200007b0: 00 00 5e b7 stq ra,0(sp) 1200007b4: 08 00 3e b5 stq s0,8(sp) 1200007b8: 09 04 f0 47 mov a0,s0 => 1200007bc: 10 00 1f 22 lda a0,16 1200007c0: 9e 00 00 00 rduniq -> 1200007c4: 00 04 00 42 addq a0,v0,v0 1200007c8: 00 00 20 24 ldah t0,0(v0) 1200007cc: 00 00 5e a7 ldq ra,0(sp) Please note the load of constant 16 (0x10) to a0. a0 is later added to v0. However, in main, we have: 1c: 00 40 5b 6b jsr ra,(t12),20 <main+0x20> 1c: LITUSE .text.startup+0x3 1c: HINT test_code 20: 00 00 ba 27 ldah gp,0(ra) 20: GPDISP .text.startup+0x8 24: a1 55 00 40 cmpeq v0,0x2,t0 28: 00 00 bd 23 lda gp,0(gp) 2c: 09 04 e0 47 mov v0,s0 30: 0e 00 20 e4 beq t0,6c <main+0x6c> 34: 00 00 7d a7 ldq t12,0(gp) 34: ELF_LITERAL __tls_get_addr 38: 00 00 1d 22 lda a0,0(gp) 38: TLSLDM fstat 3c: 00 40 5b 6b jsr ra,(t12),40 <main+0x40> 3c: LITUSE .text.startup+0x5 3c: HINT __tls_get_addr 40: 00 00 ba 27 ldah gp,0(ra) 40: GPDISP .text.startup+0x8 44: 00 00 00 24 ldah v0,0(v0) 44: DTPRELHI fstat 48: 00 00 bd 23 lda gp,0(gp) 4c: 00 00 20 a0 ldl t0,0(v0) 4c: DTPRELLO fstat this links in the final link to: 1200005dc: 72 00 40 d3 bsr ra,1200007a8 <test_code+0x8> 1200005e0: 00 00 fe 2f unop 1200005e4: a1 55 00 40 cmpeq v0,0x2,t0 1200005e8: 00 00 fe 2f unop 1200005ec: 09 04 e0 47 mov v0,s0 1200005f0: 0e 00 20 e4 beq t0,12000062c <main+0x6c> => 1200005f4: 10 00 7f 23 lda t12,16 1200005f8: 00 00 fe 2f unop 1200005fc: 9e 00 00 00 rduniq -> 120000600: 00 04 00 42 addq a0,v0,v0 120000604: 00 00 00 24 ldah v0,0(v0) 120000608: 00 00 fe 2f unop 12000060c: 00 00 20 a0 ldl t0,0(v0) Huh? Instead of loading a0 with 0x10, we load t12 instead, but a couple of insns down the insn stream, we still add a0 to v0. This also explains what happened when test_code clobbered a0. If the constant value in a0, generated in test_code lived up to addq after the rduniq call in main, everything worked ok, but by pure luck. The linker should eventually update both instructions.
Confirmed.
CVSROOT: /cvs/src Module name: src Changes by: rth@sourceware.org 2011-06-24 17:38:17 Modified files: bfd : ChangeLog elf64-alpha.c Log message: PR ld/12928 * elf64-alpha.c (elf64_alpha_relax_tls_get_addr): Recover the tlsgd insn before swapping adjacent insns. Patches: http://sourceware.org/cgi-bin/cvsweb.cgi/src/bfd/ChangeLog.diff?cvsroot=src&r1=1.5401&r2=1.5402 http://sourceware.org/cgi-bin/cvsweb.cgi/src/bfd/elf64-alpha.c.diff?cvsroot=src&r1=1.179&r2=1.180
Fixed.
*** Bug 12608 has been marked as a duplicate of this bug. ***