Properly align static TLS segments on Solaris 2

Rainer Orth ro@CeBiTec.Uni-Bielefeld.DE
Mon Oct 18 19:10:00 GMT 2010


Alan Modra <amodra@gmail.com> writes:

> Rainer, my guess is that you could fix this problem by writing an
> elf_backend_modify_program_headers function for your solaris targets
> that sets the PT_TLS p_memsz from elf_hash_table(info)->tls_size.

Unfortunately, this doesn't work: tls_size is set in elflink.c
(bfd_elf_final_link), but elf_backend_modify_program_headers is invoked
before that point (from _bfd_elf_compute_section_file_positions ->
assign_file_positions_except_relocs).  Even so, the p_memsz for the
PT_TLS segments is already computed correctly.

> I say this because tls_size isn't the "size of PT_TLS segment" as the
> comment in elf-bfd.h says (ie. p_memsz), but the size allocated by
> glibc's ld.so, which may be larger due to alignment requirements.
> Apparently this allows ld.so to make use of the gap for another tls
> block if one happens to fit.  I'm guessing that the Solaris ld.so does
> something a little different so the thread pointer isn't where ld
> expects it to be, but you should be able to force the location by
> making p_memsz the same as tls_size.  This assumes that at least one
> input section is sufficiently aligned that your ld.so won't further
> increase the TLS segment size.  If that isn't the case, then you'll
> need to also write a ld before_allocation function that calls
> _bfd_elf_tls_setup, tweaking the alignment of the returned section (if
> any), then calls the elf32.em before_allocation function.

This doesn't help either: all the tpoff calculations happen from
bfd_elf_final_link, which runs after all the linker's hook functions
(incl. ldemul_finish) have run.

I've now come up with the following patch, which does what I need and
shouldn't affect other targets in any way.  It is supported by the
following doc snippet which will be added the Solaris Linker and
Libraries Guide:

   The address of a static TLS item is encoded as a negative offset
   from the end of the static TLS arena.  The arena size is rounded
   to the nearest 8-byte boundary in a 32-bit object, and to the
   nearest 16-byte boundary in a 64-bit object.  This rounding ensures
   that the static TLS arena is suitably aligned for any use,

elfxx-sparc.c will need a similar change, but this will only take effect
once I introduce new Solaris-specific BFD target vectors, which is
already the case for Solaris/x86, but could be avoided so far for
Solaris/SPARC.

Once the general approach is accepted, I'll develop and test the SPARC
side as well.

The patch has been tested on i386-pc-solaris2.11 with a mainline GCC
bootstrap.  Unfortunately, compared to my last attempt, which was just a
hack, but had exactly the same effect, many C++ tests fail now since g++
crashes.  I could reproduce this with an unmodified gld, so this isn't
caused by this patch, but I still have to determine the root cause of the
problem.  On the other hand, all other languages are unaffected (no
GCC testsuite regressions), and the previously failing tls tests pass
now.

Ok for mainline?

	Rainer


2010-10-04  Rainer Orth  <ro@CeBiTec.Uni-Bielefeld.DE>

	* elf-bfd.h (struct elf_backend_data): New member
	static_tls_alignment.
	* elfxx-target.h (elf_backend_static_tls_alignment): Provide
	default.
	(elfNN_bed): Initialize static_tls_alignment.
	* elflink.c (bfd_elf_final_link): Don't round end of TLS section
	if static TLS has special alignment requirements.
	* elf32-i386.c (elf_i386_tpoff): Define bed, static_tls_size.
	Consider static_tls_alignment.
	(elf_backend_static_tls_alignment): Redefine for Solaris 2.
	Undef again for VxWorks.
	* elf64-x86-64.c (elf64_x86_64_tpoff):  Define bed,
	static_tls_size.
	Consider static_tls_alignment.
	(elf_backend_static_tls_alignment): Redefine for Solaris 2.
	Undef again for Intel L1OM.

Index: bfd/elf-bfd.h
===================================================================
RCS file: /vol/gnu/src/binutils/src-cvs/src/bfd/elf-bfd.h,v
retrieving revision 1.310
diff -u -p -r1.310 elf-bfd.h
--- bfd/elf-bfd.h	4 Oct 2010 14:13:08 -0000	1.310
+++ bfd/elf-bfd.h	17 Oct 2010 10:32:03 -0000
@@ -1256,6 +1256,9 @@ struct elf_backend_data
      actual tag number to place in the input position.  */
   int (*obj_attrs_order) (int);
 
+  /* This is non-zero if static TLS segments require a special alignment.  */
+  unsigned static_tls_alignment;
+
   /* This is TRUE if the linker should act like collect and gather
      global constructors and destructors by name.  This is TRUE for
      MIPS ELF because the Irix 5 tools can not handle the .init
Index: bfd/elf32-i386.c
===================================================================
RCS file: /vol/gnu/src/binutils/src-cvs/src/bfd/elf32-i386.c,v
retrieving revision 1.240
diff -u -p -r1.240 elf32-i386.c
--- bfd/elf32-i386.c	1 Oct 2010 04:28:03 -0000	1.240
+++ bfd/elf32-i386.c	17 Oct 2010 10:42:15 -0000
@@ -2828,11 +2828,16 @@ static bfd_vma
 elf_i386_tpoff (struct bfd_link_info *info, bfd_vma address)
 {
   struct elf_link_hash_table *htab = elf_hash_table (info);
+  const struct elf_backend_data *bed = get_elf_backend_data (info->output_bfd);
+  bfd_vma static_tls_size;
 
   /* If tls_sec is NULL, we should have signalled an error already.  */
   if (htab->tls_sec == NULL)
     return 0;
-  return htab->tls_size + htab->tls_sec->vma - address;
+
+  /* Consider special static TLS alignment requirements.  */
+  static_tls_size = BFD_ALIGN (htab->tls_size, bed->static_tls_alignment);
+  return static_tls_size + htab->tls_sec->vma - address;
 }
 
 /* Relocate an i386 ELF section.  */
@@ -4795,6 +4800,11 @@ elf_i386_fbsd_post_process_headers (bfd 
 #undef	elf32_bed
 #define	elf32_bed			elf32_i386_sol2_bed
 
+/* The 32-bit static TLS arena size is rounded to the nearest 8-byte
+   boundary.  */
+#undef elf_backend_static_tls_alignment
+#define elf_backend_static_tls_alignment 8
+
 /* The Solaris 2 ABI requires a plt symbol on all platforms.
 
    Cf. Linker and Libraries Guide, Ch. 2, Link-Editor, Generating the Output
@@ -4848,6 +4858,7 @@ elf_i386_vxworks_link_hash_table_create 
 #undef elf_backend_final_write_processing
 #define elf_backend_final_write_processing \
   elf_vxworks_final_write_processing
+#undef elf_backend_static_tls_alignment
 
 /* On VxWorks, we emit relocations against _PROCEDURE_LINKAGE_TABLE_, so
    define it.  */
Index: bfd/elf64-x86-64.c
===================================================================
RCS file: /vol/gnu/src/binutils/src-cvs/src/bfd/elf64-x86-64.c,v
retrieving revision 1.201
diff -u -p -r1.201 elf64-x86-64.c
--- bfd/elf64-x86-64.c	1 Oct 2010 04:28:04 -0000	1.201
+++ bfd/elf64-x86-64.c	17 Oct 2010 10:50:14 -0000
@@ -2607,11 +2607,16 @@ static bfd_vma
 elf64_x86_64_tpoff (struct bfd_link_info *info, bfd_vma address)
 {
   struct elf_link_hash_table *htab = elf_hash_table (info);
+  const struct elf_backend_data *bed = get_elf_backend_data (info->output_bfd);
+  bfd_vma static_tls_size;
 
   /* If tls_segment is NULL, we should have signalled an error already.  */
   if (htab->tls_sec == NULL)
     return 0;
-  return address - htab->tls_size - htab->tls_sec->vma;
+
+  /* Consider special static TLS alignment requirements.  */
+  static_tls_size = BFD_ALIGN (htab->tls_size, bed->static_tls_alignment);
+  return address - static_tls_size - htab->tls_sec->vma;
 }
 
 /* Is the instruction before OFFSET in CONTENTS a 32bit relative
@@ -4565,6 +4570,11 @@ static const struct bfd_elf_special_sect
 #undef  elf64_bed
 #define elf64_bed			    elf64_x86_64_sol2_bed
 
+/* The 64-bit static TLS arena size is rounded to the nearest 16-byte
+   boundary.  */
+#undef elf_backend_static_tls_alignment
+#define elf_backend_static_tls_alignment    16
+
 /* The Solaris 2 ABI requires a plt symbol on all platforms.
 
    Cf. Linker and Libraries Guide, Ch. 2, Link-Editor, Generating the Output
@@ -4603,6 +4613,7 @@ elf64_l1om_elf_object_p (bfd *abfd)
 #define elf_backend_object_p		    elf64_l1om_elf_object_p
 
 #undef  elf_backend_post_process_headers
+#undef  elf_backend_static_tls_alignment
 
 #include "elf64-target.h"
 
Index: bfd/elflink.c
===================================================================
RCS file: /vol/gnu/src/binutils/src-cvs/src/bfd/elflink.c,v
retrieving revision 1.386
diff -u -p -r1.386 elflink.c
--- bfd/elflink.c	14 Oct 2010 01:31:27 -0000	1.386
+++ bfd/elflink.c	17 Oct 2010 10:27:25 -0000
@@ -10624,7 +10624,11 @@ bfd_elf_final_link (bfd *abfd, struct bf
 	  end = sec->vma + size;
 	}
       base = elf_hash_table (info)->tls_sec->vma;
-      end = align_power (end, elf_hash_table (info)->tls_sec->alignment_power);
+      /* Only align end of TLS section if static TLS doesn't have special
+	 alignment requirements.  */
+      if (bed->static_tls_alignment == 0)
+	end = align_power (end,
+			   elf_hash_table (info)->tls_sec->alignment_power);
       elf_hash_table (info)->tls_size = end - base;
     }
 
Index: bfd/elfxx-target.h
===================================================================
RCS file: /vol/gnu/src/binutils/src-cvs/src/bfd/elfxx-target.h,v
retrieving revision 1.121
diff -u -p -r1.121 elfxx-target.h
--- bfd/elfxx-target.h	25 Aug 2010 14:53:45 -0000	1.121
+++ bfd/elfxx-target.h	17 Oct 2010 10:30:04 -0000
@@ -1,6 +1,6 @@
 /* Target definitions for NN-bit ELF
    Copyright 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002,
-   2003, 2004, 2005, 2006, 2007, 2008, 2009 Free Software Foundation, Inc.
+   2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010 Free Software Foundation, Inc.
 
    This file is part of BFD, the Binary File Descriptor library.
 
@@ -477,6 +477,9 @@
 #ifndef elf_backend_obj_attrs_order
 #define elf_backend_obj_attrs_order		NULL
 #endif
+#ifndef elf_backend_static_tls_alignment
+#define elf_backend_static_tls_alignment	0
+#endif
 #ifndef elf_backend_post_process_headers
 #define elf_backend_post_process_headers	NULL
 #endif
@@ -738,6 +741,7 @@ static struct elf_backend_data elfNN_bed
   elf_backend_obj_attrs_arg_type,
   elf_backend_obj_attrs_section_type,
   elf_backend_obj_attrs_order,
+  elf_backend_static_tls_alignment,
   elf_backend_collect,
   elf_backend_type_change_ok,
   elf_backend_may_use_rel_p,


-- 
-----------------------------------------------------------------------------
Rainer Orth, Center for Biotechnology, Bielefeld University



More information about the Binutils mailing list