* 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.

	* emultempl/elf32.em (gld${EMULATION_NAME}_before_allocation): Call
	_bfd_elf_tls_setup.
diff --git a/bfd/elf64-alpha.c b/bfd/elf64-alpha.c
index 1d1eea7..4933d28 100644
--- a/bfd/elf64-alpha.c
+++ b/bfd/elf64-alpha.c
@@ -1158,13 +1158,15 @@
   (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 @@
   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_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 @@
     {
       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 @@
 	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 @@
   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 @@
   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 @@
 	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 @@
 	  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 @@
   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 @@
 
   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 @@
 	      }
 	    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 @@
 		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 @@
                  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 @@
                  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 @@
 		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)