This is the mail archive of the binutils@sources.redhat.com 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]

tls section alignment


This testcase fails to return the expected status on powerpc-linux,
depending on optimization level (really on where .tdata starts, but that
often changes depending on optimization).

__thread int a = 10;
__thread int b __attribute__ ((aligned (8)));

int main (void)
{
  return a;
}

What's happening is that the TLS segment, made up of .tdata and .tbss,
ends up with p_vaddr not a multiple of p_align.  Under these
circumstances glibc rounds down the TLS segment start address, which
affects targets that set their thread pointer from the start of a TLS
block.  In the powerpc-linux testcase, we end up accessing *(&a-1).

I started off fixing this just for powerpc and powerpc64, then decided
to teach ld how to ensure that the TLS segment p_vaddr is aligned.

bfd/ChangeLog
	* bfd-in.h (_bfd_elf_tls_setup): Declare.
	* bfd-in2.h: Regenerate.
	* elf-bfd.h (struct elf_link_tls_segment): Delete.
	(struct elf_link_hash_table): Add tls_sec and tls_size.
	* elf.c (_bfd_elf_link_hash_table_init): Init tls_sec and tls_size.
	* elflink.c (_bfd_elf_tls_setup): New function.
	* elflink.h (struct elf_final_link_info): Remove first_tls_sec.
	(elf_bfd_final_link): Don't set first_tls_sec here.  Update code
	saving tls segment info, round segment size up.
	(elf_link_output_extsym): Adjust code using tls segment info.
	(elf_link_input_bfd): Likewise.
	* elf32-i386.c (dtpoff_base, tpoff): Likewise.
	* elf32-s390.c (dtpoff_base, tpoff): Likewise.
	* elf32-sh.c (dtpoff_base, tpoff): Likewise.
	* elf32-sparc.c (dtpoff_base, tpoff): Likewise.
	* elf64-s390.c (dtpoff_base, tpoff): Likewise.
	* elf64-x86-64.c (dtpoff_base, tpoff): Likewise.
	* elfxx-ia64.c (elfNN_ia64_tprel_base): Likewise.
	(elfNN_ia64_dtprel_base): Likewise.
	* elf64-alpha.c (alpha_get_dtprel_base): Likewise.
	(alpha_get_tprel_base): Likewise.
	(struct alpha_relax_info): Remove tls_segment.
	(elf64_alpha_relax_got_load): Adjust invocation of
	alpha_get_dtprel_base and alpha_get_tprel_base.
	(elf64_alpha_relax_tls_get_addr): Likewise.
	(elf64_alpha_relax_section): Likewise.
	(elf64_alpha_relocate_section): Likewise.
	(elf64_alpha_relax_find_tls_segment): Delete.
	* elf32-ppc.c (struct ppc_elf_link_hash_table): Remove tls_sec.
	(ppc_elf_tls_setup): Call _bfd_elf_tls_setup.  Return section.
	(ppc_elf_relocate_section): Adjust to use elf.tls_sec.
	* elf32-ppc.h (ppc_elf_tls_setup): Update.
	* elf64-ppc.c (struct ppc_link_hash_table): Remove tls_sec.
	(ppc64_elf_tls_setup): Call _bfd_elf_tls_setup.  Return section.
	(ppc64_elf_tls_optimize): Adjust to use elf.tls_sec.
	(ppc64_elf_relocate_section): Likewise.
	* elf64-ppc.h (ppc64_elf_tls_setup): Update.

ld/ChangeLog
	* emultempl/elf32.em (gld${EMULATION_NAME}_before_allocation): Call
	_bfd_elf_tls_setup.

Index: bfd/bfd-in.h
===================================================================
RCS file: /cvs/src/src/bfd/bfd-in.h,v
retrieving revision 1.68
diff -u -p -r1.68 bfd-in.h
--- bfd/bfd-in.h	31 Oct 2003 05:32:45 -0000	1.68
+++ bfd/bfd-in.h	4 Nov 2003 05:33:50 -0000
@@ -677,6 +677,9 @@ extern int bfd_get_arch_size
 extern int bfd_get_sign_extend_vma
   (bfd *);
 
+extern struct bfd_section *_bfd_elf_tls_setup
+  (bfd *, struct bfd_link_info *);
+
 extern bfd_boolean bfd_m68k_elf32_create_embedded_relocs
   (bfd *, struct bfd_link_info *, struct bfd_section *, struct bfd_section *, char **);
 extern bfd_boolean bfd_mips_elf32_create_embedded_relocs
Index: bfd/elf-bfd.h
===================================================================
RCS file: /cvs/src/src/bfd/elf-bfd.h,v
retrieving revision 1.116
diff -u -p -r1.116 elf-bfd.h
--- bfd/elf-bfd.h	3 Nov 2003 15:17:38 -0000	1.116
+++ bfd/elf-bfd.h	4 Nov 2003 05:33:53 -0000
@@ -309,14 +309,6 @@ struct eh_frame_hdr_info
   bfd_boolean table;
 };
 
-/* Cached start, size and alignment of PT_TLS segment.  */
-struct elf_link_tls_segment
-{
-  bfd_vma start;
-  bfd_size_type size;
-  unsigned int align;
-};
-
 /* ELF linker hash table.  */
 
 struct elf_link_hash_table
@@ -377,8 +369,9 @@ struct elf_link_hash_table
      objects included in the link.  */
   struct bfd_link_needed_list *runpath;
 
-  /* Cached start, size and alignment of PT_TLS segment.  */
-  struct elf_link_tls_segment *tls_segment;
+  /* Cached first output tls section and size of PT_TLS segment.  */
+  asection *tls_sec;
+  bfd_size_type tls_size;
 
   /* A linked list of BFD's loaded in the link.  */
   struct elf_link_loaded_list *loaded;
Index: bfd/elf.c
===================================================================
RCS file: /cvs/src/src/bfd/elf.c,v
retrieving revision 1.205
diff -u -p -r1.205 elf.c
--- bfd/elf.c	31 Oct 2003 05:32:45 -0000	1.205
+++ bfd/elf.c	4 Nov 2003 05:34:00 -0000
@@ -1444,7 +1444,8 @@ _bfd_elf_link_hash_table_init
   memset (&table->eh_info, 0, sizeof (table->eh_info));
   table->dynlocal = NULL;
   table->runpath = NULL;
-  table->tls_segment = NULL;
+  table->tls_sec = NULL;
+  table->tls_size = 0;
   table->loaded = NULL;
 
   ret = _bfd_link_hash_table_init (&table->root, abfd, newfunc);
Index: bfd/elflink.c
===================================================================
RCS file: /cvs/src/src/bfd/elflink.c,v
retrieving revision 1.48
diff -u -p -r1.48 elflink.c
--- bfd/elflink.c	30 Oct 2003 14:13:50 -0000	1.48
+++ bfd/elflink.c	4 Nov 2003 05:34:00 -0000
@@ -2519,3 +2519,31 @@ _bfd_elf_symbol_refs_local_p (struct elf
      dynamic linker will resolve them locally.  */
   return local_protected;
 }
+
+/* Caches some TLS segment info, and ensures that the TLS segment vma is
+   aligned.  Returns the first TLS output section.  */
+
+struct bfd_section *
+_bfd_elf_tls_setup (bfd *obfd, struct bfd_link_info *info)
+{
+  struct bfd_section *sec, *tls;
+  unsigned int align = 0;
+
+  for (sec = obfd->sections; sec != NULL; sec = sec->next)
+    if ((sec->flags & SEC_THREAD_LOCAL) != 0)
+      break;
+  tls = sec;
+
+  for (; sec != NULL && (sec->flags & SEC_THREAD_LOCAL) != 0; sec = sec->next)
+    if (sec->alignment_power > align)
+      align = sec->alignment_power;
+
+  elf_hash_table (info)->tls_sec = tls;
+
+  /* Ensure the alignment of the first section is the largest alignment,
+     so that the tls segment starts aligned.  */
+  if (tls != NULL)
+    tls->alignment_power = align;
+
+  return tls;
+}
Index: bfd/elflink.h
===================================================================
RCS file: /cvs/src/src/bfd/elflink.h,v
retrieving revision 1.245
diff -u -p -r1.245 elflink.h
--- bfd/elflink.h	24 Oct 2003 14:55:14 -0000	1.245
+++ bfd/elflink.h	4 Nov 2003 05:34:02 -0000
@@ -2804,8 +2804,6 @@ struct elf_final_link_info
   asection *hash_sec;
   /* symbol version section (.gnu.version).  */
   asection *symver_sec;
-  /* first SHF_TLS section (if any).  */
-  asection *first_tls_sec;
   /* Buffer large enough to hold contents of any section.  */
   bfd_byte *contents;
   /* Buffer large enough to hold external relocs of any section.  */
@@ -3160,14 +3158,6 @@ elf_bfd_final_link (bfd *abfd, struct bf
   finfo.symshndxbuf = NULL;
   finfo.symbuf_count = 0;
   finfo.shndxbuf_size = 0;
-  finfo.first_tls_sec = NULL;
-  for (o = abfd->sections; o != NULL; o = o->next)
-    if ((o->flags & SEC_THREAD_LOCAL) != 0
-	&& (o->flags & SEC_LOAD) != 0)
-      {
-	finfo.first_tls_sec = o;
-	break;
-      }
 
   /* Count up the number of relocations we will output for each output
      section, so that we know the sizes of the reloc sections.  We
@@ -3525,38 +3515,30 @@ elf_bfd_final_link (bfd *abfd, struct bf
 	goto error_return;
     }
 
-  if (finfo.first_tls_sec)
+  if (elf_hash_table (info)->tls_sec)
     {
-      unsigned int align = 0;
-      bfd_vma base = finfo.first_tls_sec->vma, end = 0;
+      bfd_vma base, end = 0;
       asection *sec;
 
-      for (sec = finfo.first_tls_sec;
+      for (sec = elf_hash_table (info)->tls_sec;
 	   sec && (sec->flags & SEC_THREAD_LOCAL);
 	   sec = sec->next)
 	{
 	  bfd_vma size = sec->_raw_size;
 
-	  if (bfd_get_section_alignment (abfd, sec) > align)
-	    align = bfd_get_section_alignment (abfd, sec);
-	  if (sec->_raw_size == 0 && (sec->flags & SEC_HAS_CONTENTS) == 0)
+	  if (size == 0 && (sec->flags & SEC_HAS_CONTENTS) == 0)
 	    {
 	      struct bfd_link_order *o;
 
-	      size = 0;
 	      for (o = sec->link_order_head; o != NULL; o = o->next)
 		if (size < o->offset + o->size)
 		  size = o->offset + o->size;
 	    }
 	  end = sec->vma + size;
 	}
-      elf_hash_table (info)->tls_segment
-	= bfd_zalloc (abfd, sizeof (struct elf_link_tls_segment));
-      if (elf_hash_table (info)->tls_segment == NULL)
-	goto error_return;
-      elf_hash_table (info)->tls_segment->start = base;
-      elf_hash_table (info)->tls_segment->size = end - base;
-      elf_hash_table (info)->tls_segment->align = align;
+      base = elf_hash_table (info)->tls_sec->vma;
+      end = align_power (end, elf_hash_table (info)->tls_sec->alignment_power);
+      elf_hash_table (info)->tls_size = end - base;
     }
 
   /* Since ELF permits relocations to be against local symbols, we
@@ -4503,8 +4485,8 @@ elf_link_output_extsym (struct elf_link_
 		  {
 		    /* STT_TLS symbols are relative to PT_TLS segment
 		       base.  */
-		    BFD_ASSERT (finfo->first_tls_sec != NULL);
-		    sym.st_value -= finfo->first_tls_sec->vma;
+		    BFD_ASSERT (elf_hash_table (finfo->info)->tls_sec != NULL);
+		    sym.st_value -= elf_hash_table (finfo->info)->tls_sec->vma;
 		  }
 	      }
 	  }
@@ -4862,8 +4844,8 @@ elf_link_input_bfd (struct elf_final_lin
 	  if (ELF_ST_TYPE (osym.st_info) == STT_TLS)
 	    {
 	      /* STT_TLS symbols are relative to PT_TLS segment base.  */
-	      BFD_ASSERT (finfo->first_tls_sec != NULL);
-	      osym.st_value -= finfo->first_tls_sec->vma;
+	      BFD_ASSERT (elf_hash_table (finfo->info)->tls_sec != NULL);
+	      osym.st_value -= elf_hash_table (finfo->info)->tls_sec->vma;
 	    }
 	}
 
@@ -5219,8 +5201,10 @@ elf_link_input_bfd (struct elf_final_lin
 				{
 				  /* STT_TLS symbols are relative to PT_TLS
 				     segment base.  */
-				  BFD_ASSERT (finfo->first_tls_sec != NULL);
-				  sym.st_value -= finfo->first_tls_sec->vma;
+				  BFD_ASSERT (elf_hash_table (finfo->info)
+					      ->tls_sec != NULL);
+				  sym.st_value -= (elf_hash_table (finfo->info)
+						   ->tls_sec->vma);
 				}
 			    }
 
Index: bfd/elf32-i386.c
===================================================================
RCS file: /cvs/src/src/bfd/elf32-i386.c,v
retrieving revision 1.112
diff -u -p -r1.112 elf32-i386.c
--- bfd/elf32-i386.c	3 Nov 2003 15:17:38 -0000	1.112
+++ bfd/elf32-i386.c	4 Nov 2003 05:34:04 -0000
@@ -1953,10 +1953,10 @@ elf_i386_fake_sections (bfd *abfd ATTRIB
 static bfd_vma
 dtpoff_base (struct bfd_link_info *info)
 {
-  /* If tls_segment is NULL, we should have signalled an error already.  */
-  if (elf_hash_table (info)->tls_segment == NULL)
+  /* If tls_sec is NULL, we should have signalled an error already.  */
+  if (elf_hash_table (info)->tls_sec == NULL)
     return 0;
-  return elf_hash_table (info)->tls_segment->start;
+  return elf_hash_table (info)->tls_sec->vma;
 }
 
 /* Return the relocation value for @tpoff relocation
@@ -1965,14 +1965,12 @@ dtpoff_base (struct bfd_link_info *info)
 static bfd_vma
 tpoff (struct bfd_link_info *info, bfd_vma address)
 {
-  struct elf_link_tls_segment *tls_segment
-    = elf_hash_table (info)->tls_segment;
+  struct elf_link_hash_table *htab = elf_hash_table (info);
 
-  /* If tls_segment is NULL, we should have signalled an error already.  */
-  if (tls_segment == NULL)
+  /* If tls_sec is NULL, we should have signalled an error already.  */
+  if (htab->tls_sec == NULL)
     return 0;
-  return (align_power (tls_segment->size, tls_segment->align)
-	  + tls_segment->start - address);
+  return htab->tls_size + htab->tls_sec->vma - address;
 }
 
 /* Relocate an i386 ELF section.  */
Index: bfd/elf32-s390.c
===================================================================
RCS file: /cvs/src/src/bfd/elf32-s390.c,v
retrieving revision 1.49
diff -u -p -r1.49 elf32-s390.c
--- bfd/elf32-s390.c	3 Nov 2003 15:17:39 -0000	1.49
+++ bfd/elf32-s390.c	4 Nov 2003 05:34:06 -0000
@@ -2216,10 +2216,10 @@ static bfd_vma
 dtpoff_base (info)
      struct bfd_link_info *info;
 {
-  /* If tls_segment is NULL, we should have signalled an error already.  */
-  if (elf_hash_table (info)->tls_segment == NULL)
+  /* If tls_sec is NULL, we should have signalled an error already.  */
+  if (elf_hash_table (info)->tls_sec == NULL)
     return 0;
-  return elf_hash_table (info)->tls_segment->start;
+  return elf_hash_table (info)->tls_sec->vma;
 }
 
 /* Return the relocation value for @tpoff relocation
@@ -2230,14 +2230,12 @@ tpoff (info, address)
      struct bfd_link_info *info;
      bfd_vma address;
 {
-  struct elf_link_tls_segment *tls_segment
-    = elf_hash_table (info)->tls_segment;
+  struct elf_link_hash_table *htab = elf_hash_table (info);
 
-  /* If tls_segment is NULL, we should have signalled an error already.  */
-  if (tls_segment == NULL)
+  /* If tls_sec is NULL, we should have signalled an error already.  */
+  if (htab->tls_sec == NULL)
     return 0;
-  return (align_power (tls_segment->size, tls_segment->align)
-	  + tls_segment->start - address);
+  return htab->tls_size + htab->tls_sec->vma - address;
 }
 
 /* Complain if TLS instruction relocation is against an invalid
Index: bfd/elf32-sh.c
===================================================================
RCS file: /cvs/src/src/bfd/elf32-sh.c,v
retrieving revision 1.95
diff -u -p -r1.95 elf32-sh.c
--- bfd/elf32-sh.c	3 Nov 2003 15:17:39 -0000	1.95
+++ bfd/elf32-sh.c	4 Nov 2003 05:34:10 -0000
@@ -6021,10 +6021,10 @@ sh_elf_get_relocated_section_contents (b
 static bfd_vma
 dtpoff_base (struct bfd_link_info *info)
 {
-  /* If tls_segment is NULL, we should have signalled an error already.  */
-  if (elf_hash_table (info)->tls_segment == NULL)
+  /* If tls_sec is NULL, we should have signalled an error already.  */
+  if (elf_hash_table (info)->tls_sec == NULL)
     return 0;
-  return elf_hash_table (info)->tls_segment->start;
+  return elf_hash_table (info)->tls_sec->vma;
 }
 
 /* Return the relocation value for R_SH_TLS_TPOFF32..  */
@@ -6032,12 +6032,12 @@ dtpoff_base (struct bfd_link_info *info)
 static bfd_vma
 tpoff (struct bfd_link_info *info, bfd_vma address)
 {
-  /* If tls_segment is NULL, we should have signalled an error already.  */
-  if (elf_hash_table (info)->tls_segment == NULL)
+  /* If tls_sec is NULL, we should have signalled an error already.  */
+  if (elf_hash_table (info)->tls_sec == NULL)
     return 0;
   /* SH TLS ABI is variant I and static TLS block start just after tcbhead
      structure which has 2 pointer fields.  */
-  return (address - dtpoff_base (info) + 8);
+  return address - elf_hash_table (info)->tls_sec->vma + 8;
 }
 
 static asection *
Index: bfd/elf32-sparc.c
===================================================================
RCS file: /cvs/src/src/bfd/elf32-sparc.c,v
retrieving revision 1.57
diff -u -p -r1.57 elf32-sparc.c
--- bfd/elf32-sparc.c	3 Nov 2003 15:17:39 -0000	1.57
+++ bfd/elf32-sparc.c	4 Nov 2003 05:34:11 -0000
@@ -2082,10 +2082,10 @@ static bfd_vma
 dtpoff_base (info)
      struct bfd_link_info *info;
 {
-  /* If tls_segment is NULL, we should have signalled an error already.  */
-  if (elf_hash_table (info)->tls_segment == NULL)
+  /* If tls_sec is NULL, we should have signalled an error already.  */
+  if (elf_hash_table (info)->tls_sec == NULL)
     return 0;
-  return elf_hash_table (info)->tls_segment->start;
+  return elf_hash_table (info)->tls_sec->vma;
 }
 
 /* Return the relocation value for @tpoff relocation
@@ -2096,14 +2096,12 @@ tpoff (info, address)
      struct bfd_link_info *info;
      bfd_vma address;
 {
-  struct elf_link_tls_segment *tls_segment
-    = elf_hash_table (info)->tls_segment;
+  struct elf_link_hash_table *htab = elf_hash_table (info);
 
-  /* If tls_segment is NULL, we should have signalled an error already.  */
-  if (tls_segment == NULL)
+  /* If tls_sec is NULL, we should have signalled an error already.  */
+  if (htab->tls_sec == NULL)
     return 0;
-  return -(align_power (tls_segment->size, tls_segment->align)
-	   + tls_segment->start - address);
+  return address - htab->tls_size - htab->tls_sec->vma;
 }
 
 /* Relocate a SPARC ELF section.  */
Index: bfd/elf64-s390.c
===================================================================
RCS file: /cvs/src/src/bfd/elf64-s390.c,v
retrieving revision 1.50
diff -u -p -r1.50 elf64-s390.c
--- bfd/elf64-s390.c	3 Nov 2003 15:17:39 -0000	1.50
+++ bfd/elf64-s390.c	4 Nov 2003 05:34:13 -0000
@@ -2186,10 +2186,10 @@ static bfd_vma
 dtpoff_base (info)
      struct bfd_link_info *info;
 {
-  /* If tls_segment is NULL, we should have signalled an error already.  */
-  if (elf_hash_table (info)->tls_segment == NULL)
+  /* If tls_sec is NULL, we should have signalled an error already.  */
+  if (elf_hash_table (info)->tls_sec == NULL)
     return 0;
-  return elf_hash_table (info)->tls_segment->start;
+  return elf_hash_table (info)->tls_sec->vma;
 }
 
 /* Return the relocation value for @tpoff relocation
@@ -2200,14 +2200,12 @@ tpoff (info, address)
      struct bfd_link_info *info;
      bfd_vma address;
 {
-  struct elf_link_tls_segment *tls_segment
-    = elf_hash_table (info)->tls_segment;
+  struct elf_link_hash_table *htab = elf_hash_table (info);
 
-  /* If tls_segment is NULL, we should have signalled an error already.  */
-  if (tls_segment == NULL)
+  /* If tls_sec is NULL, we should have signalled an error already.  */
+  if (htab->tls_sec == NULL)
     return 0;
-  return (align_power (tls_segment->size, tls_segment->align)
-	  + tls_segment->start - address);
+  return htab->tls_size + htab->tls_sec->vma - address;
 }
 
 /* Complain if TLS instruction relocation is against an invalid
Index: bfd/elf64-x86-64.c
===================================================================
RCS file: /cvs/src/src/bfd/elf64-x86-64.c,v
retrieving revision 1.68
diff -u -p -r1.68 elf64-x86-64.c
--- bfd/elf64-x86-64.c	3 Nov 2003 15:17:39 -0000	1.68
+++ bfd/elf64-x86-64.c	4 Nov 2003 05:34:14 -0000
@@ -1739,10 +1739,10 @@ elf64_x86_64_size_dynamic_sections (bfd 
 static bfd_vma
 dtpoff_base (struct bfd_link_info *info)
 {
-  /* If tls_segment is NULL, we should have signalled an error already.  */
-  if (elf_hash_table (info)->tls_segment == NULL)
+  /* If tls_sec is NULL, we should have signalled an error already.  */
+  if (elf_hash_table (info)->tls_sec == NULL)
     return 0;
-  return elf_hash_table (info)->tls_segment->start;
+  return elf_hash_table (info)->tls_sec->vma;
 }
 
 /* Return the relocation value for @tpoff relocation
@@ -1751,14 +1751,12 @@ dtpoff_base (struct bfd_link_info *info)
 static bfd_vma
 tpoff (struct bfd_link_info *info, bfd_vma address)
 {
-  struct elf_link_tls_segment *tls_segment
-    = elf_hash_table (info)->tls_segment;
+  struct elf_link_hash_table *htab = elf_hash_table (info);
 
   /* If tls_segment is NULL, we should have signalled an error already.  */
-  if (tls_segment == NULL)
+  if (htab->tls_sec == NULL)
     return 0;
-  return address - align_power (tls_segment->size, tls_segment->align)
-	 - tls_segment->start;
+  return address - htab->tls_size - htab->tls_sec->vma;
 }
 
 /* Relocate an x86_64 ELF section.  */
Index: bfd/elfxx-ia64.c
===================================================================
RCS file: /cvs/src/src/bfd/elfxx-ia64.c,v
retrieving revision 1.106
diff -u -p -r1.106 elfxx-ia64.c
--- bfd/elfxx-ia64.c	3 Nov 2003 15:17:40 -0000	1.106
+++ bfd/elfxx-ia64.c	4 Nov 2003 05:34:17 -0000
@@ -3544,12 +3544,10 @@ static bfd_vma
 elfNN_ia64_tprel_base (info)
      struct bfd_link_info *info;
 {
-  struct elf_link_tls_segment *tls_segment
-    = elf_hash_table (info)->tls_segment;
+  asection *tls_sec = elf_hash_table (info)->tls_sec;
 
-  BFD_ASSERT (tls_segment != NULL);
-  return (tls_segment->start
-	  - align_power ((bfd_vma) 16, tls_segment->align));
+  BFD_ASSERT (tls_sec != NULL);
+  return tls_sec->vma - align_power ((bfd_vma) 16, tls_sec->alignment_power);
 }
 
 /* Return the base VMA address which should be subtracted from real addresses
@@ -3560,8 +3558,8 @@ static bfd_vma
 elfNN_ia64_dtprel_base (info)
      struct bfd_link_info *info;
 {
-  BFD_ASSERT (elf_hash_table (info)->tls_segment != NULL);
-  return elf_hash_table (info)->tls_segment->start;
+  BFD_ASSERT (elf_hash_table (info)->tls_sec != NULL);
+  return elf_hash_table (info)->tls_sec->vma;
 }
 
 /* Called through qsort to sort the .IA_64.unwind section during a
Index: bfd/elf64-alpha.c
===================================================================
RCS file: /cvs/src/src/bfd/elf64-alpha.c,v
retrieving revision 1.108
diff -u -p -r1.108 elf64-alpha.c
--- bfd/elf64-alpha.c	3 Nov 2003 15:17:39 -0000	1.108
+++ bfd/elf64-alpha.c	4 Nov 2003 05:34:20 -0000
@@ -1158,13 +1158,15 @@ elf64_alpha_info_to_howto (abfd, cache_p
   (r_type == R_ALPHA_TLSGD || r_type == R_ALPHA_TLSLDM ? 16 : 8)
 
 /* This is PT_TLS segment p_vaddr.  */
-#define alpha_get_dtprel_base(tlss) \
-  ((tlss)->start)
+#define alpha_get_dtprel_base(info) \
+  (elf_hash_table (info)->tls_sec->vma)
 
 /* Main program TLS (whose template starts at PT_TLS p_vaddr)
    is assigned offset round(16, PT_TLS p_align).  */
-#define alpha_get_tprel_base(tlss) \
-  ((tlss)->start - align_power ((bfd_vma) 16, (tlss)->align))
+#define alpha_get_tprel_base(info) \
+  (elf_hash_table (info)->tls_sec->vma					\
+   - align_power ((bfd_vma) 16,						\
+		  elf_hash_table (info)->tls_sec->alignment_power))
 
 /* These functions do relaxation for Alpha ELF.
 
@@ -1198,7 +1200,6 @@ struct alpha_relax_info
   Elf_Internal_Shdr *symtab_hdr;
   Elf_Internal_Rela *relocs, *relend;
   struct bfd_link_info *link_info;
-  struct elf_link_tls_segment *tls_segment;
   bfd_vma gp;
   bfd *gotobj;
   asection *tsec;
@@ -1224,8 +1225,6 @@ static bfd_boolean elf64_alpha_relax_gpr
 static bfd_boolean elf64_alpha_relax_tls_get_addr
   PARAMS((struct alpha_relax_info *info, bfd_vma symval,
           Elf_Internal_Rela *irel, bfd_boolean));
-static struct elf_link_tls_segment *elf64_alpha_relax_find_tls_segment
-  PARAMS((struct alpha_relax_info *, struct elf_link_tls_segment *));
 static bfd_boolean elf64_alpha_relax_section
   PARAMS((bfd *abfd, asection *sec, struct bfd_link_info *link_info,
 	  bfd_boolean *again));
@@ -1598,9 +1597,9 @@ elf64_alpha_relax_got_load (info, symval
     {
       bfd_vma dtp_base, tp_base;
 
-      BFD_ASSERT (info->tls_segment != NULL);
-      dtp_base = alpha_get_dtprel_base (info->tls_segment);
-      tp_base = alpha_get_tprel_base (info->tls_segment);
+      BFD_ASSERT (elf_hash_table (info->link_info)->tls_sec != NULL);
+      dtp_base = alpha_get_dtprel_base (info->link_info);
+      tp_base = alpha_get_tprel_base (info->link_info);
       disp = symval - (r_type == R_ALPHA_GOTDTPREL ? dtp_base : tp_base);
     }
 
@@ -1845,8 +1844,8 @@ elf64_alpha_relax_tls_get_addr (info, sy
 	bfd_vma tp_base;
 	bfd_signed_vma disp;
 
-	BFD_ASSERT (info->tls_segment != NULL);
-	tp_base = alpha_get_tprel_base (info->tls_segment);
+	BFD_ASSERT (elf_hash_table (info->link_info)->tls_sec != NULL);
+	tp_base = alpha_get_tprel_base (info->link_info);
 	disp = symval - tp_base;
 
 	if (disp >= -0x8000 && disp < 0x8000)
@@ -1961,53 +1960,6 @@ elf64_alpha_relax_tls_get_addr (info, sy
   return TRUE;
 }
 
-static struct elf_link_tls_segment *
-elf64_alpha_relax_find_tls_segment (info, seg)
-     struct alpha_relax_info *info;
-     struct elf_link_tls_segment *seg;
-{
-  bfd *output_bfd = info->sec->output_section->owner;
-  asection *o;
-  unsigned int align;
-  bfd_vma base, end;
-
-  for (o = output_bfd->sections; o ; o = o->next)
-    if ((o->flags & SEC_THREAD_LOCAL) != 0
-        && (o->flags & SEC_LOAD) != 0)
-      break;
-  if (!o)
-    return NULL;
-
-  base = o->vma;
-  align = 0;
-
-  do
-    {
-      bfd_vma size;
-
-      if (bfd_get_section_alignment (output_bfd, o) > align)
-	align = bfd_get_section_alignment (output_bfd, o);
-
-      size = o->_raw_size;
-      if (size == 0 && (o->flags & SEC_HAS_CONTENTS) == 0)
-	{
-	  struct bfd_link_order *lo;
-	  for (lo = o->link_order_head; lo ; lo = lo->next)
-	    if (size < lo->offset + lo->size)
-	      size = lo->offset + lo->size;
-	}
-      end = o->vma + size;
-      o = o->next;
-    }
-  while (o && (o->flags & SEC_THREAD_LOCAL));
-
-  seg->start = base;
-  seg->size = end - base;
-  seg->align = align;
-
-  return seg;
-}
-
 static bfd_boolean
 elf64_alpha_relax_section (abfd, sec, link_info, again)
      bfd *abfd;
@@ -2021,7 +1973,6 @@ elf64_alpha_relax_section (abfd, sec, li
   Elf_Internal_Sym *isymbuf = NULL;
   struct alpha_elf_got_entry **local_got_entries;
   struct alpha_relax_info info;
-  struct elf_link_tls_segment tls_segment;
 
   /* We are not currently changing any sizes, so only one pass.  */
   *again = FALSE;
@@ -2079,11 +2030,6 @@ elf64_alpha_relax_section (abfd, sec, li
 	goto error_return;
     }
 
-  /* Compute the TLS segment information.  The version normally found in
-     elf_hash_table (link_info)->tls_segment isn't built until final_link.
-     ??? Probably should look into extracting this into a common function.  */
-  info.tls_segment = elf64_alpha_relax_find_tls_segment (&info, &tls_segment);
-
   for (irel = internal_relocs; irel < irelend; irel++)
     {
       bfd_vma symval;
@@ -2137,7 +2083,7 @@ elf64_alpha_relax_section (abfd, sec, li
 	  if (r_type == R_ALPHA_TLSLDM)
 	    {
 	      info.tsec = bfd_abs_section_ptr;
-	      symval = alpha_get_tprel_base (info.tls_segment);
+	      symval = alpha_get_tprel_base (info.link_info);
 	    }
 	  else
 	    {
@@ -4294,7 +4240,6 @@ elf64_alpha_relocate_section (output_bfd
   Elf_Internal_Shdr *symtab_hdr;
   Elf_Internal_Rela *rel;
   Elf_Internal_Rela *relend;
-  struct elf_link_tls_segment *tls_segment;
   asection *sgot, *srel, *srelgot;
   bfd *dynobj, *gotobj;
   bfd_vma gp, tp_base, dtp_base;
@@ -4348,11 +4293,10 @@ elf64_alpha_relocate_section (output_bfd
 
   local_got_entries = alpha_elf_tdata(input_bfd)->local_got_entries;
 
-  tls_segment = elf_hash_table (info)->tls_segment;
-  if (tls_segment)
+  if (elf_hash_table (info)->tls_sec != NULL)
     {
-      dtp_base = alpha_get_dtprel_base (tls_segment);
-      tp_base = alpha_get_tprel_base (tls_segment);
+      dtp_base = alpha_get_dtprel_base (info);
+      tp_base = alpha_get_tprel_base (info);
     }
   else
     dtp_base = tp_base = 0;
@@ -4674,13 +4618,13 @@ elf64_alpha_relocate_section (output_bfd
 	      }
 	    else if (r_type == R_ALPHA_DTPREL64)
 	      {
-		BFD_ASSERT(tls_segment != NULL);
+		BFD_ASSERT (elf_hash_table (info)->tls_sec != NULL);
 		value -= dtp_base;
 		goto default_reloc;
 	      }
 	    else if (r_type == R_ALPHA_TPREL64)
 	      {
-		BFD_ASSERT(tls_segment != NULL);
+		BFD_ASSERT (elf_hash_table (info)->tls_sec != NULL);
 		if (!info->shared)
 		  {
 		    value -= tp_base;
@@ -4760,7 +4704,7 @@ elf64_alpha_relocate_section (output_bfd
 		value = 0;
 	      else
 		{
-		  BFD_ASSERT(tls_segment != NULL);
+		  BFD_ASSERT (elf_hash_table (info)->tls_sec != NULL);
 	          value -= dtp_base;
 		}
 	      bfd_put_64 (output_bfd, value,
@@ -4783,7 +4727,7 @@ elf64_alpha_relocate_section (output_bfd
                  bfd_archive_filename (input_bfd), h->root.root.root.string);
               ret_val = FALSE;
             }
-	  BFD_ASSERT(tls_segment != NULL);
+	  BFD_ASSERT (elf_hash_table (info)->tls_sec != NULL);
 	  value -= dtp_base;
 	  if (r_type == R_ALPHA_DTPRELHI)
 	    value = ((bfd_signed_vma) value >> 16) + ((value >> 15) & 1);
@@ -4806,7 +4750,7 @@ elf64_alpha_relocate_section (output_bfd
                  bfd_archive_filename (input_bfd), h->root.root.root.string);
               ret_val = FALSE;
             }
-	  BFD_ASSERT(tls_segment != NULL);
+	  BFD_ASSERT (elf_hash_table (info)->tls_sec != NULL);
 	  value -= tp_base;
 	  if (r_type == R_ALPHA_TPRELHI)
 	    value = ((bfd_signed_vma) value >> 16) + ((value >> 15) & 1);
@@ -4827,7 +4771,7 @@ elf64_alpha_relocate_section (output_bfd
 		value = 0;
 	      else
 		{
-		  BFD_ASSERT(tls_segment != NULL);
+		  BFD_ASSERT (elf_hash_table (info)->tls_sec != NULL);
 		  if (r_type == R_ALPHA_GOTDTPREL)
 		    value -= dtp_base;
 		  else if (!info->shared)
Index: bfd/elf32-ppc.c
===================================================================
RCS file: /cvs/src/src/bfd/elf32-ppc.c,v
retrieving revision 1.102
diff -u -p -r1.102 elf32-ppc.c
--- bfd/elf32-ppc.c	3 Nov 2003 15:17:39 -0000	1.102
+++ bfd/elf32-ppc.c	4 Nov 2003 05:34:23 -0000
@@ -205,9 +205,6 @@ struct ppc_elf_link_hash_table
   elf_linker_section_t *sdata2;
   asection *sbss;
 
-  /* Short-cut to first output tls section.  */
-  asection *tls_sec;
-
   /* Shortcut to .__tls_get_addr.  */
   struct elf_link_hash_entry *tls_get_addr;
 
@@ -4184,25 +4181,18 @@ ppc_elf_gc_sweep_hook (bfd *abfd,
   return TRUE;
 }
 
-/* Set htab->tls_sec and htab->tls_get_addr.  */
+/* Set htab->tls_get_addr and call the generic ELF tls_setup function.  */
 
-bfd_boolean
+asection *
 ppc_elf_tls_setup (bfd *obfd, struct bfd_link_info *info)
 {
-  asection *tls;
   struct ppc_elf_link_hash_table *htab;
 
   htab = ppc_elf_hash_table (info);
   htab->tls_get_addr = elf_link_hash_lookup (&htab->elf, "__tls_get_addr",
 					     FALSE, FALSE, TRUE);
 
-  for (tls = obfd->sections; tls != NULL; tls = tls->next)
-    if ((tls->flags & (SEC_THREAD_LOCAL | SEC_LOAD))
-	== (SEC_THREAD_LOCAL | SEC_LOAD))
-      break;
-  htab->tls_sec = tls;
-
-  return tls != NULL;
+  return _bfd_elf_tls_setup (obfd, info);
 }
 
 /* Run through all the TLS relocs looking for optimization
@@ -4917,8 +4907,8 @@ ppc_elf_relocate_section (bfd *output_bf
 			{
 			  /* Was an LD reloc.  */
 			  r_symndx = 0;
-			  rel->r_addend = htab->tls_sec->vma + DTP_OFFSET;
-			  rel[1].r_addend = htab->tls_sec->vma + DTP_OFFSET;
+			  rel->r_addend = htab->elf.tls_sec->vma + DTP_OFFSET;
+			  rel[1].r_addend = htab->elf.tls_sec->vma + DTP_OFFSET;
 			}
 		      r_type = R_PPC_TPREL16_HA;
 		      rel->r_info = ELF32_R_INFO (r_symndx, r_type);
@@ -5156,7 +5146,7 @@ ppc_elf_relocate_section (bfd *output_bf
 			  {
 			    outrel.r_addend += relocation;
 			    if (tls_ty & (TLS_GD | TLS_DTPREL | TLS_TPREL))
-			      outrel.r_addend -= htab->tls_sec->vma;
+			      outrel.r_addend -= htab->elf.tls_sec->vma;
 			  }
 			loc = htab->relgot->contents;
 			loc += (htab->relgot->reloc_count++
@@ -5174,7 +5164,7 @@ ppc_elf_relocate_section (bfd *output_bf
 			  value = 1;
 			else if (tls_ty != 0)
 			  {
-			    value -= htab->tls_sec->vma + DTP_OFFSET;
+			    value -= htab->elf.tls_sec->vma + DTP_OFFSET;
 			    if (tls_ty == (TLS_TLS | TLS_TPREL))
 			      value += DTP_OFFSET - TP_OFFSET;
 
@@ -5262,7 +5252,7 @@ ppc_elf_relocate_section (bfd *output_bf
 	case R_PPC_DTPREL16_LO:
 	case R_PPC_DTPREL16_HI:
 	case R_PPC_DTPREL16_HA:
-	  addend -= htab->tls_sec->vma + DTP_OFFSET;
+	  addend -= htab->elf.tls_sec->vma + DTP_OFFSET;
 	  break;
 
 	  /* Relocations that may need to be propagated if this is a shared
@@ -5271,18 +5261,18 @@ ppc_elf_relocate_section (bfd *output_bf
 	case R_PPC_TPREL16_LO:
 	case R_PPC_TPREL16_HI:
 	case R_PPC_TPREL16_HA:
-	  addend -= htab->tls_sec->vma + TP_OFFSET;
+	  addend -= htab->elf.tls_sec->vma + TP_OFFSET;
 	  /* The TPREL16 relocs shouldn't really be used in shared
 	     libs as they will result in DT_TEXTREL being set, but
 	     support them anyway.  */
 	  goto dodyn;
 
 	case R_PPC_TPREL32:
-	  addend -= htab->tls_sec->vma + TP_OFFSET;
+	  addend -= htab->elf.tls_sec->vma + TP_OFFSET;
 	  goto dodyn;
 
 	case R_PPC_DTPREL32:
-	  addend -= htab->tls_sec->vma + DTP_OFFSET;
+	  addend -= htab->elf.tls_sec->vma + DTP_OFFSET;
 	  goto dodyn;
 
 	case R_PPC_DTPMOD32:
Index: bfd/elf32-ppc.h
===================================================================
RCS file: /cvs/src/src/bfd/elf32-ppc.h,v
retrieving revision 1.2
diff -u -p -r1.2 elf32-ppc.h
--- bfd/elf32-ppc.h	24 Jun 2003 14:03:53 -0000	1.2
+++ bfd/elf32-ppc.h	4 Nov 2003 05:34:23 -0000
@@ -17,5 +17,5 @@ You should have received a copy of the G
 along with this program; if not, write to the Free Software
 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.  */
 
-bfd_boolean ppc_elf_tls_setup (bfd *, struct bfd_link_info *);
+asection *ppc_elf_tls_setup (bfd *, struct bfd_link_info *);
 bfd_boolean ppc_elf_tls_optimize (bfd *, struct bfd_link_info *);
Index: bfd/elf64-ppc.c
===================================================================
RCS file: /cvs/src/src/bfd/elf64-ppc.c,v
retrieving revision 1.134
diff -u -p -r1.134 elf64-ppc.c
--- bfd/elf64-ppc.c	3 Nov 2003 15:17:39 -0000	1.134
+++ bfd/elf64-ppc.c	4 Nov 2003 05:34:27 -0000
@@ -2837,9 +2837,6 @@ struct ppc_link_hash_table
   asection *brlt;
   asection *relbrlt;
 
-  /* Short-cut to first output tls section.  */
-  asection *tls_sec;
-
   /* Shortcut to .__tls_get_addr.  */
   struct elf_link_hash_entry *tls_get_addr;
 
@@ -5172,22 +5169,14 @@ ppc64_elf_edit_opd (bfd *obfd, struct bf
   return TRUE;
 }
 
-/* Set htab->tls_sec.  */
+/* Set htab->tls_get_addr and call the generic ELF tls_setup function.  */
 
-bfd_boolean
+asection *
 ppc64_elf_tls_setup (bfd *obfd, struct bfd_link_info *info)
 {
-  asection *tls;
   struct ppc_link_hash_table *htab;
 
-  for (tls = obfd->sections; tls != NULL; tls = tls->next)
-    if ((tls->flags & (SEC_THREAD_LOCAL | SEC_LOAD))
-	== (SEC_THREAD_LOCAL | SEC_LOAD))
-      break;
-
   htab = ppc_hash_table (info);
-  htab->tls_sec = tls;
-
   if (htab->tls_get_addr != NULL)
     {
       struct elf_link_hash_entry *h = htab->tls_get_addr;
@@ -5199,7 +5188,7 @@ ppc64_elf_tls_setup (bfd *obfd, struct b
       htab->tls_get_addr = h;
     }
 
-  return tls != NULL;
+  return _bfd_elf_tls_setup (obfd, info);
 }
 
 /* Run through all the TLS relocs looking for optimization
@@ -5282,7 +5271,7 @@ ppc64_elf_tls_optimize (bfd *obfd ATTRIB
 		    is_local = TRUE;
 		    value += sym_sec->output_offset;
 		    value += sym_sec->output_section->vma;
-		    value -= htab->tls_sec->vma;
+		    value -= htab->elf.tls_sec->vma;
 		    ok_tprel = (value + TP_OFFSET + ((bfd_vma) 1 << 31)
 				< (bfd_vma) 1 << 32);
 		  }
@@ -7690,8 +7679,8 @@ ppc64_elf_relocate_section (bfd *output_
 			{
 			  /* Was an LD reloc.  */
 			  r_symndx = 0;
-			  rel->r_addend = htab->tls_sec->vma + DTP_OFFSET;
-			  rel[1].r_addend = htab->tls_sec->vma + DTP_OFFSET;
+			  rel->r_addend = htab->elf.tls_sec->vma + DTP_OFFSET;
+			  rel[1].r_addend = htab->elf.tls_sec->vma + DTP_OFFSET;
 			}
 		      else if (toc_symndx != 0)
 			r_symndx = toc_symndx;
@@ -8096,7 +8085,7 @@ ppc64_elf_relocate_section (bfd *output_
 		      {
 			outrel.r_addend += relocation;
 			if (tls_type & (TLS_GD | TLS_DTPREL | TLS_TPREL))
-			  outrel.r_addend -= htab->tls_sec->vma;
+			  outrel.r_addend -= htab->elf.tls_sec->vma;
 		      }
 		    loc = relgot->contents;
 		    loc += (relgot->reloc_count++
@@ -8113,7 +8102,7 @@ ppc64_elf_relocate_section (bfd *output_
 		      relocation = 1;
 		    else if (tls_type != 0)
 		      {
-			relocation -= htab->tls_sec->vma + DTP_OFFSET;
+			relocation -= htab->elf.tls_sec->vma + DTP_OFFSET;
 			if (tls_type == (TLS_TLS | TLS_TPREL))
 			  relocation += DTP_OFFSET - TP_OFFSET;
 
@@ -8223,7 +8212,7 @@ ppc64_elf_relocate_section (bfd *output_
 	case R_PPC64_TPREL16_HIGHERA:
 	case R_PPC64_TPREL16_HIGHEST:
 	case R_PPC64_TPREL16_HIGHESTA:
-	  addend -= htab->tls_sec->vma + TP_OFFSET;
+	  addend -= htab->elf.tls_sec->vma + TP_OFFSET;
 	  if (info->shared)
 	    /* The TPREL16 relocs shouldn't really be used in shared
 	       libs as they will result in DT_TEXTREL being set, but
@@ -8241,7 +8230,7 @@ ppc64_elf_relocate_section (bfd *output_
 	case R_PPC64_DTPREL16_HIGHERA:
 	case R_PPC64_DTPREL16_HIGHEST:
 	case R_PPC64_DTPREL16_HIGHESTA:
-	  addend -= htab->tls_sec->vma + DTP_OFFSET;
+	  addend -= htab->elf.tls_sec->vma + DTP_OFFSET;
 	  break;
 
 	case R_PPC64_DTPMOD64:
@@ -8250,11 +8239,11 @@ ppc64_elf_relocate_section (bfd *output_
 	  goto dodyn;
 
 	case R_PPC64_TPREL64:
-	  addend -= htab->tls_sec->vma + TP_OFFSET;
+	  addend -= htab->elf.tls_sec->vma + TP_OFFSET;
 	  goto dodyn;
 
 	case R_PPC64_DTPREL64:
-	  addend -= htab->tls_sec->vma + DTP_OFFSET;
+	  addend -= htab->elf.tls_sec->vma + DTP_OFFSET;
 	  /* Fall thru */
 
 	  /* Relocations that may need to be propagated if this is a
Index: bfd/elf64-ppc.h
===================================================================
RCS file: /cvs/src/src/bfd/elf64-ppc.h,v
retrieving revision 1.13
diff -u -p -r1.13 elf64-ppc.h
--- bfd/elf64-ppc.h	10 Jul 2003 00:37:26 -0000	1.13
+++ bfd/elf64-ppc.h	4 Nov 2003 05:34:27 -0000
@@ -23,7 +23,7 @@ bfd_boolean ppc64_elf_mark_entry_syms
   (struct bfd_link_info *);
 bfd_boolean ppc64_elf_edit_opd
   (bfd *, struct bfd_link_info *);
-bfd_boolean ppc64_elf_tls_setup
+asection *ppc64_elf_tls_setup
   (bfd *, struct bfd_link_info *);
 bfd_boolean ppc64_elf_tls_optimize
   (bfd *, struct bfd_link_info *);
Index: ld/emultempl/elf32.em
===================================================================
RCS file: /cvs/src/src/ld/emultempl/elf32.em,v
retrieving revision 1.104
diff -u -p -r1.104 elf32.em
--- ld/emultempl/elf32.em	20 Aug 2003 08:37:15 -0000	1.104
+++ ld/emultempl/elf32.em	4 Nov 2003 05:34:28 -0000
@@ -845,6 +845,9 @@ gld${EMULATION_NAME}_before_allocation (
   const char *rpath;
   asection *sinterp;
 
+  if (link_info.hash->creator->flavour == bfd_target_elf_flavour)
+    _bfd_elf_tls_setup (output_bfd, &link_info);
+
   /* If we are going to make any variable assignments, we need to let
      the ELF backend know about them in case the variables are
      referred to by dynamic objects.  */

-- 
Alan Modra
IBM OzLabs - Linux Technology Centre


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