This is the mail archive of the binutils@sourceware.org mailing list for the binutils project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

Fix -q for x86 ELF after TLS descriptor changes


One of the quirks of VxWorks is that -q (aka --emit-relocs) is standard
for user-mode executables.  This showed up the fact that --emit-relocs
no longer works for x86 ELF targets after the recent TLS descriptor
changes.

The problem is that we use srelplt->reloc_count to track the index
of the next unused R_386_TLS_DESC entry in .rel.plt.  (At least
I think we do.  It took me quite a while to reach that conclusion.)
Thus code that reserves room for an R_386_JUMP_SLOT increases
both srelplt->size and srelplt->reloc_count:

          /* We also need to make an entry in the .rel.plt section.  */
          htab->srelplt->size += sizeof (Elf32_External_Rel);
          htab->srelplt->reloc_count++;

while code that reserves room for an R_386_TLS_DESC just increases
the size, e.g.:

      if (GOT_TLS_GDESC_P (tls_type))
        htab->srelplt->size += sizeof (Elf32_External_Rel);

So after allocate_dynrelocs, srelplt->size is the size needed for
both types of reloc, and srelplt->reloc_count is the number of
R_386_JUMP_SLOT entries (which always come first).  This information
needs to persist to elf_i386_relocate_section, which uses it to
calculate the offset of the next R_386_TLS_DESC:

                  sreloc = htab->srelplt;
                  loc = sreloc->contents;
                  loc += sreloc->reloc_count++
                    * sizeof (Elf32_External_Rel);

size_dynamic_sections therefore refuses to zero reloc_count:

          /* We use the reloc_count field as a counter if we need
             to copy relocs into the output file.  */
          if (s != htab->srelplt)
            s->reloc_count = 0;

But for --emit-relocs links, bfd_elf_final_link will interpret a
reloc_count of N as meaning that we need N relocations.  It therefore
thinks we need a .rel.rel.plt section and aborts when it realises that
sh_entsize isn't the value it was expecting.

This patch stores the information in the link_hash_table instead.
It fixes the VxWorks problem and the attached testcase.  Tested on
i686-pc-linux-gnu (--enable-targets=all --enable-64-bit-bfd).
OK to install?

Richard


bfd/
	* elf32-i386.c (elf_i386_link_hash_table): Add next_tls_desc_index.
	(elf_i386_link_hash_table_create): Initialize it.
	(elf_i386_compute_jump_table_size): Use it instead of
	srelplt->reloc_count.
	(allocate_dynrelocs): Likewise.
	(elf_i386_size_dynamic_sections): Likewise.
	(elf_i386_relocate_section): Likewise.
	
ld/testsuite/
	* ld-i386/emit-relocs.s, ld-i386/emit-relocs.d: New test.
	* ld-i386/i386.exp: Run it.

Index: bfd/elf32-i386.c
===================================================================
RCS file: /cvs/src/src/bfd/elf32-i386.c,v
retrieving revision 1.154
diff -u -p -r1.154 elf32-i386.c
--- bfd/elf32-i386.c	27 Feb 2006 08:48:28 -0000	1.154
+++ bfd/elf32-i386.c	27 Feb 2006 19:04:16 -0000
@@ -653,6 +653,9 @@ struct elf_i386_link_hash_table
   /* Value used to fill the last word of the first plt entry.  */
   bfd_byte plt0_pad_byte;
 
+  /* The index of the next unused R_386_TLS_DESC slot in .rel.plt.  */
+  bfd_vma next_tls_desc_index;
+
   union {
     bfd_signed_vma refcount;
     bfd_vma offset;
@@ -672,7 +675,7 @@ struct elf_i386_link_hash_table
   ((struct elf_i386_link_hash_table *) ((p)->hash))
 
 #define elf_i386_compute_jump_table_size(htab) \
-  ((htab)->srelplt->reloc_count * 4)
+  ((htab)->next_tls_desc_index * 4)
 
 /* Create an entry in an i386 ELF linker hash table.  */
 
@@ -732,6 +735,7 @@ elf_i386_link_hash_table_create (bfd *ab
   ret->sdynbss = NULL;
   ret->srelbss = NULL;
   ret->tls_ldm_got.refcount = 0;
+  ret->next_tls_desc_index = 0;
   ret->sgotplt_jump_table_size = 0;
   ret->sym_sec.abfd = NULL;
   ret->is_vxworks = 0;
@@ -1639,7 +1643,7 @@ allocate_dynrelocs (struct elf_link_hash
 
 	  /* We also need to make an entry in the .rel.plt section.  */
 	  htab->srelplt->size += sizeof (Elf32_External_Rel);
-	  htab->srelplt->reloc_count++;
+	  htab->next_tls_desc_index++;
 
 	  if (htab->is_vxworks && !info->shared)
 	    {
@@ -2021,7 +2025,7 @@ elf_i386_size_dynamic_sections (bfd *out
      for them, it suffices to multiply the reloc count by the jump
      slot size.  */
   if (htab->srelplt)
-    htab->sgotplt_jump_table_size = htab->srelplt->reloc_count * 4;
+    htab->sgotplt_jump_table_size = htab->next_tls_desc_index * 4;
 
   /* We now have determined the sizes of the various dynamic sections.
      Allocate memory for them.  */
@@ -2054,8 +2058,7 @@ elf_i386_size_dynamic_sections (bfd *out
 
 	  /* We use the reloc_count field as a counter if we need
 	     to copy relocs into the output file.  */
-	  if (s != htab->srelplt)
-	    s->reloc_count = 0;
+	  s->reloc_count = 0;
 	}
       else
 	{
@@ -2997,8 +3000,8 @@ elf_i386_relocate_section (bfd *output_b
 				     + htab->sgotplt_jump_table_size);
 		  sreloc = htab->srelplt;
 		  loc = sreloc->contents;
-		  loc += sreloc->reloc_count++
-		    * sizeof (Elf32_External_Rel);
+		  loc += (htab->next_tls_desc_index++
+			  * sizeof (Elf32_External_Rel));
 		  BFD_ASSERT (loc + sizeof (Elf32_External_Rel)
 			      <= sreloc->contents + sreloc->size);
 		  bfd_elf32_swap_reloc_out (output_bfd, &outrel, loc);
Index: ld/testsuite/ld-i386/i386.exp
===================================================================
RCS file: /cvs/src/src/ld/testsuite/ld-i386/i386.exp,v
retrieving revision 1.11
diff -u -p -r1.11 i386.exp
--- ld/testsuite/ld-i386/i386.exp	18 Jan 2006 21:07:49 -0000	1.11
+++ ld/testsuite/ld-i386/i386.exp	27 Feb 2006 19:04:16 -0000
@@ -75,6 +89,8 @@ set i386tests {
      {{objdump -drj.text tlsindntpoff.dd}} "tlsindntpoff"}
     {"Reloc section order" "-shared -melf_i386 -z nocombreloc" "--32"
      {reloc.s} {{objdump -hw reloc.d}} "reloc.so"}
+    {"Basic --emit-relocs support" "-shared -melf_i386 --emit-relocs" "--32"
+     {emit-relocs.s} {{readelf --relocs emit-relocs.d}} "emit-relocs.so"}
     {"-z combreloc relocation sections" "-shared -melf_i386 -z combreloc"
      "--32" {combreloc.s} {{readelf -r combreloc.d}} "combreloc.so"}
 }
Index: ld/testsuite/ld-i386/emit-relocs.d
===================================================================
RCS file: ld/testsuite/ld-i386/emit-relocs.d
diff -N ld/testsuite/ld-i386/emit-relocs.d
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ ld/testsuite/ld-i386/emit-relocs.d	27 Feb 2006 19:04:16 -0000
@@ -0,0 +1,8 @@
+
+Relocation section '\.rel\.plt' at offset .* contains 1 entries:
+ Offset     Info    Type            Sym\.Value  Sym\. Name
+.*  .*07 R_386_JUMP_SLOT   00000000   foo
+
+Relocation section '\.rel\.text' at offset .* contains 1 entries:
+ Offset     Info    Type            Sym\.Value  Sym\. Name
+.*  .*04 R_386_PLT32       00000000   foo
Index: ld/testsuite/ld-i386/emit-relocs.s
===================================================================
RCS file: ld/testsuite/ld-i386/emit-relocs.s
diff -N ld/testsuite/ld-i386/emit-relocs.s
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ ld/testsuite/ld-i386/emit-relocs.s	27 Feb 2006 19:04:16 -0000
@@ -0,0 +1 @@
+	call	foo@plt


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]