RFC + committed: fix CRIS initial-exec relocation for tcomm TLS offset in GOT

Hans-Peter Nilsson hans-peter.nilsson@axis.com
Sun Jun 17 07:32:00 GMT 2012


It seems only the glibc testsuite is using the .tls_common
construct; I can't get gcc to emit anything else than
placeholder data in .tbss (-fcommon doesn't help).  Anyway, the
data emitted into .got was wrong for .tls_common references from
a non-DSO.  A corresponding test-case for DSO seemed due (but
didn't fail (info->shared being true); only tls-e-tpiecomm1
failed.

The code supposed to emit the reloc for the case of an unknown
symbol (which is what common symbols look like without the
ELF_COMMON_DEF_P check) had a suspicious-looking conditional and
a comment stating that the false case could only happen if there
were linker errors.  The common-bug being a bug and not a
suboptimization, is because that reloc wasn't emitted and yet
there wasn't an error.  (It wasn't emitted because it had
already been decided that there was no need for dynamic
sections.)

I'd really like to BFD_ASSERT those brittle "NULL if we had an
error" statements, for example as:

Index: elf32-cris.c
===================================================================
RCS file: /cvs/src/src/bfd/elf32-cris.c,v
retrieving revision 1.121
diff -p -u -r1.121 elf32-cris.c
--- elf32-cris.c	7 May 2012 03:27:49 -0000	1.121
+++ elf32-cris.c	17 Jun 2012 06:27:47 -0000
@@ -1832,6 +1832,8 @@ cris_elf_relocate_section (bfd *output_b
 		  /* NULL if we had an error.  */
 		  if (srelgot->contents != NULL)
 		    bfd_elf32_swap_reloca_out (output_bfd, &outrel, loc);
+		  else
+		    BFD_ASSERT (bfd_get_error () != bfd_error_no_error);
 		}
 	      else
 		off &= ~3;

(which already has coverage in the test-suite when there
actually is a linker error.)

But that assertion would have been false security, because
bfd_get_error yields a (false) error here; *always* being set.
Apparently so because all sections in the linker script are
dragged through _bfd_elf_section_from_bfd_section, which sets
bfd_error_nonrepresentable_section when it sees anything that
isn't the absolute, common, or "undefined" section (unless
elf_backend_section_from_bfd_section comes to the rescue).
That's just temporary; there is no actual error, still bfd_error
is bfd_error_nonrepresentable_section at the time
cris_elf_relocate_section is called.

What's best to do to fix thathere: call bfd_set_error
(bfd_error_no_error) in elf_fixup_link_order after the loop?  Or
give up on trying to have bfd_error == bfd_error_no_error?  I'll
hold the asserts until that's resolved.

In the meantime, committed:

ld/testsuite:
	* ld-cris/tls-e-tpiecomm1.d, ld-cris/tls-e-tpiecomm1.s: New test.
	* ld-cris/tls-dso-tpoffgotcomm1.d,
	ld-cris/tls-dso-tpoffgotcomm1.s: Ditto.

bfd:
	* elf32-cris.c (cris_elf_relocate_section): <R_CRIS_32_IE>
	<R_CRIS_32_GOT_TPREL, R_CRIS_16_GOT_TPREL>: Handle references to
	thread common symbols.

Index: elf32-cris.c
===================================================================
RCS file: /cvs/src/src/bfd/elf32-cris.c,v
retrieving revision 1.121
diff -p -u -r1.121 elf32-cris.c
--- elf32-cris.c	7 May 2012 03:27:49 -0000	1.121
+++ elf32-cris.c	17 Jun 2012 07:14:26 -0000
@@ -1877,7 +1877,8 @@ cris_elf_relocate_section (bfd *output_b
 	      return FALSE;
 	    }
 
-	  if (!info->shared && (h == NULL || h->def_regular))
+	  if (!info->shared
+	      && (h == NULL || h->def_regular || ELF_COMMON_DEF_P (h)))
 	    {
 	      /* Known contents of the GOT.  */
 	      bfd_vma off;

--- /dev/null	2012-04-03 01:25:46.382002352 +0200
+++ ld-cris/tls-e-tpiecomm1.d	2012-06-16 04:31:09.000000000 +0200
@@ -0,0 +1,47 @@
+#source: start1.s
+#source: tls-e-tpiecomm1.s
+#as: --no-underscore --em=criself -I$srcdir/$subdir
+#ld: -m crislinux
+#objdump: -d -s -h -t -r -p
+
+# Make sure we can link a file with IE relocs against common
+# symbols and that the values entered in the GOT are right.
+
+.*:     file format elf32-cris
+
+Program Header:
+    LOAD off    0x0+ vaddr 0x0+80000 paddr 0x0+80000 align 2\*\*13
+         filesz 0x0+a4 memsz 0x0+a4 flags r-x
+    LOAD off    0x0+a4 vaddr 0x0+820a4 paddr 0x0+820a4 align 2\*\*13
+         filesz 0x0+14 memsz 0x0+14 flags rw-
+     TLS off    0x0+a4 vaddr 0x0+820a4 paddr 0x0+820a4 align 2\*\*2
+         filesz 0x0+ memsz 0x0+8 flags r--
+private flags = 0:
+
+Sections:
+Idx Name          Size      VMA       LMA       File off  Algn
+  0 \.text         0+10  0+80094  0+80094  0+94  2\*\*1
+                  CONTENTS, ALLOC, LOAD, READONLY, CODE
+  1 \.tbss         0+8  0+820a4  0+820a4  0+a4  2\*\*2
+                  ALLOC, THREAD_LOCAL
+  2 \.got          0+14  0+820a4  0+820a4  0+a4  2\*\*2
+                  CONTENTS, ALLOC, LOAD, DATA
+SYMBOL TABLE:
+#...
+0+ g       .tbss	0+4 foo
+#...
+0+4 g       .tbss	0+4 bar
+#...
+Contents of section \.got:
+ 820a4 00000000 00000000 00000000 f8ffffff  .*
+ 820b4 fcffffff                             .*
+
+Disassembly of section \.text:
+
+0+80094 <_start>:
+   80094:	41b2                	moveq 1,\$r11
+	\.\.\.
+
+0+80098 <do_test>:
+   80098:	6f0e b020 0800      	move\.d 820b0 <_GLOBAL_OFFSET_TABLE_\+0xc>,\$r0
+   8009e:	2f1e b420 0800      	add\.d 820b4 <_GLOBAL_OFFSET_TABLE_\+0x10>,\$r1
--- /dev/null	2012-04-03 01:25:46.382002352 +0200
+++ ld-cris/tls-e-tpiecomm1.s	2012-06-16 02:04:15.000000000 +0200
@@ -0,0 +1,9 @@
+	.tls_common foo,4,4
+	.tls_common bar,4,4
+	.text
+	.align 1
+	.type	do_test, @function
+do_test:
+	move.d foo:IE,$r0
+	add.d bar:IE,$r1
+	.size	do_test, .-do_test
--- /dev/null	2012-04-03 01:25:46.382002352 +0200
+++ ld-cris/tls-dso-tpoffgotcomm1.d	2012-06-16 03:23:15.000000000 +0200
@@ -0,0 +1,46 @@
+#source: start1.s
+#source: tls-dso-tpoffgotcomm1.s
+#as: --no-underscore --pic --em=criself -I$srcdir/$subdir
+#ld: -m crislinux -shared
+#objdump: -d -h -s -t -r -R -p
+
+# Make sure we can link a file with TPOFFGOT relocs against common
+# symbols.
+
+.*:     file format elf32-cris
+
+Program Header:
+    LOAD off    0x0+ vaddr 0x0+ paddr 0x0+ align 2\*\*13
+         filesz 0x0+1c8 memsz 0x0+1c8 flags r-x
+    LOAD off .*
+         filesz .*
+ DYNAMIC off .*
+         filesz .*
+     TLS off    .* vaddr .* paddr .* align 2\*\*2
+         filesz 0x0+ memsz 0x0+8 flags r--
+#...
+Sections:
+#...
+  7 .got          0+14  0+2240  0+2240  0+240  2\*\*2
+                  CONTENTS, ALLOC, LOAD, DATA
+SYMBOL TABLE:
+#...
+0+ g       \.tbss	0+4 foo
+#...
+0+4 g       \.tbss	0+4 bar
+
+#...
+Contents of section .got:
+ 2240 c8210000 00000000 00000000 00000000  .*
+ 2250 00000000                             .*
+
+Disassembly of section \.text:
+
+0+1b8 <_start>:
+ 1b8:	41b2                	moveq 1,\$r11
+	\.\.\.
+
+0+1bc <do_test>:
+ 1bc:	2f0e 0c00 0000      	add\.d c <bar\+0x8>,\$r0
+ 1c2:	1f1e 1000           	add\.w 0x10,\$r1
+	\.\.\.
--- /dev/null	2012-04-03 01:25:46.382002352 +0200
+++ ld-cris/tls-dso-tpoffgotcomm1.s	2012-06-16 02:19:39.000000000 +0200
@@ -0,0 +1,9 @@
+	.tls_common foo,4,4
+	.tls_common bar,4,4
+	.text
+	.align 1
+	.type	do_test, @function
+do_test:
+	add.d foo:TPOFFGOT,$r0
+	add.w bar:TPOFFGOT16,$r1
+	.size	do_test, .-do_test



More information about the Binutils mailing list