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]

Re: RFC: TLS improvements for IA32 and AMD64/EM64T


On Sep 16, 2005, Alexandre Oliva <aoliva@redhat.com> wrote:

> Over the past few months, I've been working on porting to IA32 and
> AMD64/EM64T the interesting bits of the TLS design I came up with for
> FR-V, achieving some impressive speedups along with slight code size
> reductions in the most common cases.

> Although the design is not set in stone yet, it's fully implemented
> and functional with patches I'm about to post for binutils, gcc and
> glibc mainline, as follow-ups to this message, except that the GCC
> patch will go to gcc-patches, as expected.

Here's the patch for binutils.

I'm not entirely happy with two aspects of the patch:

- the way I managed to emit the `call *(%[er]ax)' instruction from
  `call *variable@TLSCALL(%[er]ax)', dropping the offset from the
  instruction but still emitting the relocation, seems fragile to me,
  but there were not additional bits available to do something
  cleaner.  Any suggestions on a better approach?

- local_tlsdesc_gotent is probably too wasteful, since very few of all
  local symbols are going to require TLS descriptor entries.  I hope
  this is not too much of a problem, but I could introduce another
  data structure if people feel strongly about it.


Also note the several FIXMEs with decisions yet to be made on exact
instructions to be generated in several cases.  I'm yet to develop
some means to better evaluate the performance of each alternative, but
even then, I have limited hardware to test on.  I'd welcome feedback
from people more familiar with performance features of various
x86-compatible processors.  Anyone?  Thanks in advance,

Here's the patch.  Built and tested on x86_64-linux-gnu and
i686-pc-linux-gnu.  Ok to install?

Index: include/elf/ChangeLog
from  Alexandre Oliva  <aoliva@redhat.com>

	Introduce TLS descriptors for i386 and x86_64.
	* common.h (DT_TLSDESC_GOT, DT_TLSDESC_PLT): New.
	* i386.h (R_386_TLS_GOTDESC, R_386_TLS_DESC, R_386_TLS_DESC_CALL):
	New.
	* x86-64.h (R_X86_64_GOTPC32_TLSDESC, R_X86_64_TLSDESC,
	R_X86_64_TLSDESC_CALL): New.

Index: include/elf/common.h
===================================================================
RCS file: /cvs/uberbaum/./include/elf/common.h,v
retrieving revision 1.72
diff -u -p -r1.72 common.h
--- include/elf/common.h 14 Jul 2005 22:52:15 -0000 1.72
+++ include/elf/common.h 15 Sep 2005 22:39:19 -0000
@@ -581,6 +581,8 @@
 #define DT_SYMINFO	0x6ffffeff
 #define DT_ADDRRNGHI	0x6ffffeff
 
+#define DT_TLSDESC_GOT	0x6ffffff7
+#define DT_TLSDESC_PLT	0x6ffffff8
 #define DT_RELACOUNT	0x6ffffff9
 #define DT_RELCOUNT	0x6ffffffa
 #define DT_FLAGS_1	0x6ffffffb
Index: include/elf/i386.h
===================================================================
RCS file: /cvs/uberbaum/./include/elf/i386.h,v
retrieving revision 1.10
diff -u -p -r1.10 i386.h
--- include/elf/i386.h 10 May 2005 10:21:10 -0000 1.10
+++ include/elf/i386.h 15 Sep 2005 22:39:19 -0000
@@ -1,5 +1,5 @@
 /* ix86 ELF support for BFD.
-   Copyright 1998, 1999, 2000, 2002, 2004 Free Software Foundation, Inc.
+   Copyright 1998, 1999, 2000, 2002, 2004, 2005 Free Software Foundation, Inc.
 
    This file is part of BFD, the Binary File Descriptor library.
 
@@ -61,6 +61,9 @@ START_RELOC_NUMBERS (elf_i386_reloc_type
      RELOC_NUMBER (R_386_TLS_DTPMOD32, 35)
      RELOC_NUMBER (R_386_TLS_DTPOFF32, 36)
      RELOC_NUMBER (R_386_TLS_TPOFF32,  37)
+     RELOC_NUMBER (R_386_TLS_GOTDESC,  38)
+     RELOC_NUMBER (R_386_TLS_DESC,     39)
+     RELOC_NUMBER (R_386_TLS_DESC_CALL,40)
 
      /* Used by Intel.  */
      RELOC_NUMBER (R_386_USED_BY_INTEL_200, 200)
Index: include/elf/x86-64.h
===================================================================
RCS file: /cvs/uberbaum/./include/elf/x86-64.h,v
retrieving revision 1.8
diff -u -p -r1.8 x86-64.h
--- include/elf/x86-64.h 25 Jul 2005 15:41:07 -0000 1.8
+++ include/elf/x86-64.h 15 Sep 2005 22:39:19 -0000
@@ -1,5 +1,5 @@
 /* x86_64 ELF support for BFD.
-   Copyright (C) 2000, 2001, 2002, 2004 Free Software Foundation, Inc.
+   Copyright (C) 2000, 2001, 2002, 2004, 2005 Free Software Foundation, Inc.
    Contributed by Jan Hubicka <jh@suse.cz>
 
    This file is part of BFD, the Binary File Descriptor library.
@@ -53,6 +53,13 @@ START_RELOC_NUMBERS (elf_x86_64_reloc_ty
      RELOC_NUMBER (R_X86_64_GOTOFF64, 25)     /* 64 bit offset to GOT */
      RELOC_NUMBER (R_X86_64_GOTPC32,  26)     /* 32 bit signed pc relative
                                                  offset to GOT */
+     RELOC_NUMBER (R_X86_64_GOTPC32_TLSDESC, 27)
+					      /* 32 bit signed pc relative
+						 offset to TLS descriptor
+						 in the GOT.  */
+     RELOC_NUMBER (R_X86_64_TLSDESC, 28)      /* 2x64-bit TLS descriptor.  */
+     RELOC_NUMBER (R_X86_64_TLSDESC_CALL, 29) /* Relaxable call through TLS
+						 descriptor.  */
      RELOC_NUMBER (R_X86_64_GNU_VTINHERIT, 250)       /* GNU C++ hack  */
      RELOC_NUMBER (R_X86_64_GNU_VTENTRY, 251)         /* GNU C++ hack  */
 END_RELOC_NUMBERS (R_X86_64_max)
Index: bfd/ChangeLog
from  Alexandre Oliva  <aoliva@redhat.com>

	Introduce TLS descriptors for i386 and x86_64.
	* reloc.c (BFD_RELOC_386_TLS_GOTDESC, BFD_RELOC_386_TLS_DESC,
	BFD_RELOC_386_TLS_DESC_CALL, BFD_RELOC_X86_64_GOTPC32_TLSDESC,
	BFD_RELOC_X86_64_TLSDESC, BFD_RELOC_X86_64_TLSDESC_CALL): New.
	* libbfd.h, bfd-in2.h: Rebuilt.
	* elf32-i386.c (elf_howto_table): New relocations.
	(R_386_tls): Adjust.
	(elf_i386_reloc_type_lookup): Map new relocations.
	(GOT_TLS_GDESC, GOT_TLS_GD_BOTH_P): New macros.
	(GOT_TLS_GD_P, GOT_TLS_GDESC_P, GOT_TLS_GD_ANY_P): New macros.
	(struct elf_i386_link_hash_entry): Add tlsdesc_got field.
	(struct elf_i386_obj_tdata): Add local_tlsdesc_gotent field.
	(elf_i386_local_tlsdesc_gotent): New macro.
	(struct elf_i386_link_hash_table): Add sgotplt_jump_table_size.
	(elf_i386_compute_jump_table_size): New macro.
	(link_hash_newfunc): Initialize tlsdesc_got.
	(elf_i386_link_hash_table_create): Set sgotplt_jump_table_size.
	(elf_i386_tls_transition): Handle R_386_TLS_GOTDESC and
	R_386_TLS_DESC_CALL.
	(elf_i386_check_relocs): Likewise.  Allocate space for
	local_tlsdesc_gotent.
	(elf_i386_gc_sweep_hook): Handle R_386_TLS_GOTDESC and
	R_386_TLS_DESC_CALL.
	(allocate_dynrelocs): Count function PLT relocations.  Reserve
	space for TLS descriptors and relocations.
	(elf_i386_size_dynamic_sections): Reserve space for TLS
	descriptors and relocations.  Set up sgotplt_jump_table_size.
	Don't zero reloc_count in srelplt.
	(elf_i386_always_size_sections): New.  Set up _TLS_MODULE_BASE_.
	(elf_i386_relocate_section): Handle R_386_TLS_GOTDESC and
	R_386_TLS_DESC_CALL.
	(elf_i386_finish_dynamic_symbol): Use GOT_TLS_GD_ANY_P.
	(elf_backend_always_size_sections): Define.
	* elf64-x86-64.c (x86_64_elf_howto): Add R_X86_64_GOTPC32_TLSDESC,
	R_X86_64_TLSDESC, R_X86_64_TLSDESC_CALL.
	(R_X86_64_standard): Adjust.
	(x86_64_reloc_map): Map new relocs.
	(GOT_TLS_GDESC, GOT_TLS_GD_BOTH_P): New macros.
	(GOT_TLS_GD_P, GOT_TLS_GDESC_P, GOT_TLS_GD_ANY_P): New macros.
	(struct elf64_x86_64_link_hash_entry): Add tlsdesc_got field.
	(struct elf64_x86_64_obj_tdata): Add local_tlsdesc_gotent field.
	(elf64_x86_64_local_tlsdesc_gotent): New macro.
	(struct elf64_x86_64_link_hash_table): Add tlsdesc_plt,
	tlsdesc_got and sgotplt_jump_table_size fields.
	(elf64_x86_64_compute_jump_table_size): New macro.
	(link_hash_newfunc): Initialize tlsdesc_got.
	(elf64_x86_64_link_hash_table_create): Initialize new fields.
	(elf64_x86_64_tls_transition): Handle R_X86_64_GOTPC32_TLSDESC and
	R_X86_64_TLSDESC_CALL.
	(elf64_x86_64_check_relocs): Likewise.  Allocate space for
	local_tlsdesc_gotent.
	(elf64_x86_64_gc_sweep_hook): Handle R_X86_64_GOTPC32_TLSDESC and
	R_X86_64_TLSDESC_CALL.
	(allocate_dynrelocs): Count function PLT relocations.  Reserve
	space for TLS descriptors and relocations.
	(elf64_x86_64_size_dynamic_sections): Reserve space for TLS
	descriptors and relocations.  Set up sgotplt_jump_table_size,
	tlsdesc_plt and tlsdesc_got.  Make room for them.  Don't zero
	reloc_count in srelplt.  Add dynamic entries for DT_TLSDESC_PLT
	and DT_TLSDESC_GOT.
	(elf64_x86_64_always_size_sections): New.  Set up
	_TLS_MODULE_BASE_.
	(elf64_x86_64_relocate_section): Handle R_386_TLS_GOTDESC and
	R_386_TLS_DESC_CALL.
	(elf64_x86_64_finish_dynamic_symbol): Use GOT_TLS_GD_ANY_P.
	(elf64_x86_64_finish_dynamic_sections): Set DT_TLSDESC_PLT and
	DT_TLSDESC_GOT.  Set up TLS descriptor lazy resolver PLT entry.
	(elf_backend_always_size_sections): Define.

Index: bfd/bfd-in2.h
===================================================================
RCS file: /cvs/uberbaum/./bfd/bfd-in2.h,v
retrieving revision 1.366
diff -u -p -r1.366 bfd-in2.h
--- bfd/bfd-in2.h 8 Sep 2005 12:49:18 -0000 1.366
+++ bfd/bfd-in2.h 15 Sep 2005 22:38:15 -0000
@@ -2647,6 +2647,9 @@ in the instruction.  */
   BFD_RELOC_386_TLS_DTPMOD32,
   BFD_RELOC_386_TLS_DTPOFF32,
   BFD_RELOC_386_TLS_TPOFF32,
+  BFD_RELOC_386_TLS_GOTDESC,
+  BFD_RELOC_386_TLS_DESC,
+  BFD_RELOC_386_TLS_DESC_CALL,
 
 /* x86-64/elf relocations  */
   BFD_RELOC_X86_64_GOT32,
@@ -2667,6 +2670,9 @@ in the instruction.  */
   BFD_RELOC_X86_64_TPOFF32,
   BFD_RELOC_X86_64_GOTOFF64,
   BFD_RELOC_X86_64_GOTPC32,
+  BFD_RELOC_X86_64_GOTPC32_TLSDESC,
+  BFD_RELOC_X86_64_TLSDESC,
+  BFD_RELOC_X86_64_TLSDESC_CALL,
 
 /* ns32k relocations  */
   BFD_RELOC_NS32K_IMM_8,
Index: bfd/elf32-i386.c
===================================================================
RCS file: /cvs/uberbaum/./bfd/elf32-i386.c,v
retrieving revision 1.149
diff -u -p -r1.149 elf32-i386.c
--- bfd/elf32-i386.c 31 Aug 2005 23:45:45 -0000 1.149
+++ bfd/elf32-i386.c 15 Sep 2005 22:38:17 -0000
@@ -126,9 +126,18 @@ static reloc_howto_type elf_howto_table[
   HOWTO(R_386_TLS_TPOFF32, 0, 2, 32, FALSE, 0, complain_overflow_bitfield,
 	bfd_elf_generic_reloc, "R_386_TLS_TPOFF32",
 	TRUE, 0xffffffff, 0xffffffff, FALSE),
+  HOWTO(R_386_TLS_GOTDESC, 0, 2, 32, FALSE, 0, complain_overflow_bitfield,
+	bfd_elf_generic_reloc, "R_386_TLS_GOTDESC",
+	TRUE, 0xffffffff, 0xffffffff, FALSE),
+  HOWTO(R_386_TLS_DESC, 0, 2, 32, FALSE, 0, complain_overflow_bitfield,
+	bfd_elf_generic_reloc, "R_386_TLS_DESC",
+	TRUE, 0xffffffff, 0xffffffff, FALSE),
+  HOWTO(R_386_TLS_DESC_CALL, 0, 0, 0, FALSE, 0, complain_overflow_dont,
+	bfd_elf_generic_reloc, "R_386_TLS_DESC_CALL",
+	FALSE, 0, 0, FALSE),
 
   /* Another gap.  */
-#define R_386_tls (R_386_TLS_TPOFF32 + 1 - R_386_tls_offset)
+#define R_386_tls (R_386_TLS_DESC_CALL + 1 - R_386_tls_offset)
 #define R_386_vt_offset (R_386_GNU_VTINHERIT - R_386_tls)
 
 /* GNU extension to record C++ vtable hierarchy.  */
@@ -292,6 +301,18 @@ elf_i386_reloc_type_lookup (bfd *abfd AT
       TRACE ("BFD_RELOC_386_TLS_TPOFF32");
       return &elf_howto_table[R_386_TLS_TPOFF32 - R_386_tls_offset];
 
+    case BFD_RELOC_386_TLS_GOTDESC:
+      TRACE ("BFD_RELOC_386_TLS_GOTDESC");
+      return &elf_howto_table[R_386_TLS_GOTDESC - R_386_tls_offset];
+
+    case BFD_RELOC_386_TLS_DESC:
+      TRACE ("BFD_RELOC_386_TLS_DESC");
+      return &elf_howto_table[R_386_TLS_DESC - R_386_tls_offset];
+
+    case BFD_RELOC_386_TLS_DESC_CALL:
+      TRACE ("BFD_RELOC_386_TLS_DESC_CALL");
+      return &elf_howto_table[R_386_TLS_DESC_CALL - R_386_tls_offset];
+
     case BFD_RELOC_VTABLE_INHERIT:
       TRACE ("BFD_RELOC_VTABLE_INHERIT");
       return &elf_howto_table[R_386_GNU_VTINHERIT - R_386_vt_offset];
@@ -559,7 +580,20 @@ struct elf_i386_link_hash_entry
 #define GOT_TLS_IE_POS	5
 #define GOT_TLS_IE_NEG	6
 #define GOT_TLS_IE_BOTH 7
+#define GOT_TLS_GDESC	8
+#define GOT_TLS_GD_BOTH_P(type)						\
+  ((type) == (GOT_TLS_GD | GOT_TLS_GDESC))
+#define GOT_TLS_GD_P(type)						\
+  ((type) == GOT_TLS_GD || GOT_TLS_GD_BOTH_P (type))
+#define GOT_TLS_GDESC_P(type)						\
+  ((type) == GOT_TLS_GDESC || GOT_TLS_GD_BOTH_P (type))
+#define GOT_TLS_GD_ANY_P(type)						\
+  (GOT_TLS_GD_P (type) || GOT_TLS_GDESC_P (type))
   unsigned char tls_type;
+
+  /* Offset of the GOTPLT entry reserved for the TLS descriptor,
+     starting at the end of the jump table.  */
+  bfd_vma tlsdesc_got;
 };
 
 #define elf_i386_hash_entry(ent) ((struct elf_i386_link_hash_entry *)(ent))
@@ -570,6 +604,9 @@ struct elf_i386_obj_tdata
 
   /* tls_type for each local got entry.  */
   char *local_got_tls_type;
+
+  /* GOTPLT entries for TLS descriptors.  */
+  bfd_vma *local_tlsdesc_gotent;
 };
 
 #define elf_i386_tdata(abfd) \
@@ -578,6 +615,9 @@ struct elf_i386_obj_tdata
 #define elf_i386_local_got_tls_type(abfd) \
   (elf_i386_tdata (abfd)->local_got_tls_type)
 
+#define elf_i386_local_tlsdesc_gotent(abfd) \
+  (elf_i386_tdata (abfd)->local_tlsdesc_gotent)
+
 static bfd_boolean
 elf_i386_mkobject (bfd *abfd)
 {
@@ -620,6 +660,10 @@ struct elf_i386_link_hash_table
     bfd_vma offset;
   } tls_ldm_got;
 
+  /* The amount of space used by the reserved portion of the sgotplt
+     section, plus whatever space is used by the jump slots.  */
+  bfd_vma sgotplt_jump_table_size;
+
   /* Small local sym to section mapping cache.  */
   struct sym_sec_cache sym_sec;
 };
@@ -629,6 +673,9 @@ struct elf_i386_link_hash_table
 #define elf_i386_hash_table(p) \
   ((struct elf_i386_link_hash_table *) ((p)->hash))
 
+#define elf_i386_compute_jump_table_size(htab) \
+  ((htab)->srelplt->reloc_count * 4)
+
 /* Create an entry in an i386 ELF linker hash table.  */
 
 static struct bfd_hash_entry *
@@ -655,6 +702,7 @@ link_hash_newfunc (struct bfd_hash_entry
       eh = (struct elf_i386_link_hash_entry *) entry;
       eh->dyn_relocs = NULL;
       eh->tls_type = GOT_UNKNOWN;
+      eh->tlsdesc_got = (bfd_vma) -1;
     }
 
   return entry;
@@ -686,6 +734,7 @@ elf_i386_link_hash_table_create (bfd *ab
   ret->sdynbss = NULL;
   ret->srelbss = NULL;
   ret->tls_ldm_got.refcount = 0;
+  ret->sgotplt_jump_table_size = 0;
   ret->sym_sec.abfd = NULL;
   ret->is_vxworks = 0;
   ret->srelplt2 = NULL;
@@ -848,6 +897,8 @@ elf_i386_tls_transition (struct bfd_link
   switch (r_type)
     {
     case R_386_TLS_GD:
+    case R_386_TLS_GOTDESC:
+    case R_386_TLS_DESC_CALL:
     case R_386_TLS_IE_32:
       if (is_local)
 	return R_386_TLS_LE_32;
@@ -952,6 +1003,8 @@ elf_i386_check_relocs (bfd *abfd,
 
 	case R_386_GOT32:
 	case R_386_TLS_GD:
+	case R_386_TLS_GOTDESC:
+	case R_386_TLS_DESC_CALL:
 	  /* This symbol requires a global offset table entry.  */
 	  {
 	    int tls_type, old_tls_type;
@@ -961,6 +1014,9 @@ elf_i386_check_relocs (bfd *abfd,
 	      default:
 	      case R_386_GOT32: tls_type = GOT_NORMAL; break;
 	      case R_386_TLS_GD: tls_type = GOT_TLS_GD; break;
+	      case R_386_TLS_GOTDESC:
+	      case R_386_TLS_DESC_CALL:
+		tls_type = GOT_TLS_GDESC; break;
 	      case R_386_TLS_IE_32:
 		if (ELF32_R_TYPE (rel->r_info) == r_type)
 		  tls_type = GOT_TLS_IE_NEG;
@@ -990,13 +1046,16 @@ elf_i386_check_relocs (bfd *abfd,
 		    bfd_size_type size;
 
 		    size = symtab_hdr->sh_info;
-		    size *= (sizeof (bfd_signed_vma) + sizeof(char));
+		    size *= (sizeof (bfd_signed_vma)
+			     + sizeof (bfd_vma) + sizeof(char));
 		    local_got_refcounts = bfd_zalloc (abfd, size);
 		    if (local_got_refcounts == NULL)
 		      return FALSE;
 		    elf_local_got_refcounts (abfd) = local_got_refcounts;
+		    elf_i386_local_tlsdesc_gotent (abfd)
+		      = (bfd_vma *) (local_got_refcounts + symtab_hdr->sh_info);
 		    elf_i386_local_got_tls_type (abfd)
-		      = (char *) (local_got_refcounts + symtab_hdr->sh_info);
+		      = (char *) (local_got_refcounts + 2 * symtab_hdr->sh_info);
 		  }
 		local_got_refcounts[r_symndx] += 1;
 		old_tls_type = elf_i386_local_got_tls_type (abfd) [r_symndx];
@@ -1007,11 +1066,14 @@ elf_i386_check_relocs (bfd *abfd,
 	    /* If a TLS symbol is accessed using IE at least once,
 	       there is no point to use dynamic model for it.  */
 	    else if (old_tls_type != tls_type && old_tls_type != GOT_UNKNOWN
-		     && (old_tls_type != GOT_TLS_GD
+		     && (! GOT_TLS_GD_ANY_P (old_tls_type)
 			 || (tls_type & GOT_TLS_IE) == 0))
 	      {
-		if ((old_tls_type & GOT_TLS_IE) && tls_type == GOT_TLS_GD)
+		if ((old_tls_type & GOT_TLS_IE) && GOT_TLS_GD_ANY_P (tls_type))
 		  tls_type = old_tls_type;
+		else if (GOT_TLS_GD_ANY_P (old_tls_type)
+			 && GOT_TLS_GD_ANY_P (tls_type))
+		  tls_type |= old_tls_type;
 		else
 		  {
 		    (*_bfd_error_handler)
@@ -1319,6 +1381,8 @@ elf_i386_gc_sweep_hook (bfd *abfd,
 	  break;
 
 	case R_386_TLS_GD:
+	case R_386_TLS_GOTDESC:
+	case R_386_TLS_DESC_CALL:
 	case R_386_TLS_IE_32:
 	case R_386_TLS_IE:
 	case R_386_TLS_GOTIE:
@@ -1582,6 +1646,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++;
 
 	  if (htab->is_vxworks && !info->shared)
 	    {
@@ -1615,6 +1680,9 @@ allocate_dynrelocs (struct elf_link_hash
       h->needs_plt = 0;
     }
 
+  eh = (struct elf_i386_link_hash_entry *) h;
+  eh->tlsdesc_got = (bfd_vma) -1;
+
   /* If R_386_TLS_{IE_32,IE,GOTIE} symbol is now local to the binary,
      make it a R_386_TLS_LE_32 requiring no TLS entry.  */
   if (h->got.refcount > 0
@@ -1638,11 +1706,22 @@ allocate_dynrelocs (struct elf_link_hash
 	}
 
       s = htab->sgot;
-      h->got.offset = s->size;
-      s->size += 4;
-      /* R_386_TLS_GD needs 2 consecutive GOT slots.  */
-      if (tls_type == GOT_TLS_GD || tls_type == GOT_TLS_IE_BOTH)
-	s->size += 4;
+      if (GOT_TLS_GDESC_P (tls_type))
+	{
+	  eh->tlsdesc_got = htab->sgotplt->size
+	    - elf_i386_compute_jump_table_size (htab);
+	  htab->sgotplt->size += 8;
+	  h->got.offset = (bfd_vma) -2;
+	}
+      if (! GOT_TLS_GDESC_P (tls_type)
+	  || GOT_TLS_GD_P (tls_type))
+	{
+	  h->got.offset = s->size;
+	  s->size += 4;
+	  /* R_386_TLS_GD needs 2 consecutive GOT slots.  */
+	  if (GOT_TLS_GD_P (tls_type) || tls_type == GOT_TLS_IE_BOTH)
+	    s->size += 4;
+	}
       dyn = htab->elf.dynamic_sections_created;
       /* R_386_TLS_IE_32 needs one dynamic relocation,
 	 R_386_TLS_IE resp. R_386_TLS_GOTIE needs one dynamic relocation,
@@ -1651,21 +1730,23 @@ allocate_dynrelocs (struct elf_link_hash
 	 global.  */
       if (tls_type == GOT_TLS_IE_BOTH)
 	htab->srelgot->size += 2 * sizeof (Elf32_External_Rel);
-      else if ((tls_type == GOT_TLS_GD && h->dynindx == -1)
+      else if ((GOT_TLS_GD_P (tls_type) && h->dynindx == -1)
 	       || (tls_type & GOT_TLS_IE))
 	htab->srelgot->size += sizeof (Elf32_External_Rel);
-      else if (tls_type == GOT_TLS_GD)
+      else if (GOT_TLS_GD_P (tls_type))
 	htab->srelgot->size += 2 * sizeof (Elf32_External_Rel);
-      else if ((ELF_ST_VISIBILITY (h->other) == STV_DEFAULT
-		|| h->root.type != bfd_link_hash_undefweak)
+      else if (! GOT_TLS_GDESC_P (tls_type)
+	       && (ELF_ST_VISIBILITY (h->other) == STV_DEFAULT
+		   || h->root.type != bfd_link_hash_undefweak)
 	       && (info->shared
 		   || WILL_CALL_FINISH_DYNAMIC_SYMBOL (dyn, 0, h)))
 	htab->srelgot->size += sizeof (Elf32_External_Rel);
+      if (GOT_TLS_GDESC_P (tls_type))
+	htab->srelplt->size += sizeof (Elf32_External_Rel);
     }
   else
     h->got.offset = (bfd_vma) -1;
 
-  eh = (struct elf_i386_link_hash_entry *) h;
   if (eh->dyn_relocs == NULL)
     return TRUE;
 
@@ -1813,6 +1894,7 @@ elf_i386_size_dynamic_sections (bfd *out
       bfd_signed_vma *local_got;
       bfd_signed_vma *end_local_got;
       char *local_tls_type;
+      bfd_vma *local_tlsdesc_gotent;
       bfd_size_type locsymcount;
       Elf_Internal_Shdr *symtab_hdr;
       asection *srel;
@@ -1855,25 +1937,42 @@ elf_i386_size_dynamic_sections (bfd *out
       locsymcount = symtab_hdr->sh_info;
       end_local_got = local_got + locsymcount;
       local_tls_type = elf_i386_local_got_tls_type (ibfd);
+      local_tlsdesc_gotent = elf_i386_local_tlsdesc_gotent (ibfd);
       s = htab->sgot;
       srel = htab->srelgot;
-      for (; local_got < end_local_got; ++local_got, ++local_tls_type)
+      for (; local_got < end_local_got;
+	   ++local_got, ++local_tls_type, ++local_tlsdesc_gotent)
 	{
+	  *local_tlsdesc_gotent = (bfd_vma) -1;
 	  if (*local_got > 0)
 	    {
-	      *local_got = s->size;
-	      s->size += 4;
-	      if (*local_tls_type == GOT_TLS_GD
-		  || *local_tls_type == GOT_TLS_IE_BOTH)
-		s->size += 4;
+	      if (GOT_TLS_GDESC_P (*local_tls_type))
+		{
+		  *local_tlsdesc_gotent = htab->sgotplt->size
+		    - elf_i386_compute_jump_table_size (htab);
+		  htab->sgotplt->size += 8;
+		  *local_got = (bfd_vma) -2;
+		}
+	      if (! GOT_TLS_GDESC_P (*local_tls_type)
+		  || GOT_TLS_GD_P (*local_tls_type))
+		{
+		  *local_got = s->size;
+		  s->size += 4;
+		  if (GOT_TLS_GD_P (*local_tls_type)
+		      || *local_tls_type == GOT_TLS_IE_BOTH)
+		    s->size += 4;
+		}
 	      if (info->shared
-		  || *local_tls_type == GOT_TLS_GD
+		  || GOT_TLS_GD_ANY_P (*local_tls_type)
 		  || (*local_tls_type & GOT_TLS_IE))
 		{
 		  if (*local_tls_type == GOT_TLS_IE_BOTH)
 		    srel->size += 2 * sizeof (Elf32_External_Rel);
-		  else
+		  else if (GOT_TLS_GD_P (*local_tls_type)
+			   || ! GOT_TLS_GDESC_P (*local_tls_type))
 		    srel->size += sizeof (Elf32_External_Rel);
+		  if (GOT_TLS_GDESC_P (*local_tls_type))
+		    htab->srelplt->size += sizeof (Elf32_External_Rel);
 		}
 	    }
 	  else
@@ -1917,6 +2016,14 @@ elf_i386_size_dynamic_sections (bfd *out
      sym dynamic relocs.  */
   elf_link_hash_traverse (&htab->elf, allocate_dynrelocs, (PTR) info);
 
+  /* For every jump slot reserved in the sgotplt, reloc_count is
+     incremented.  However, when we reserve space for TLS descriptors,
+     it's not incremented, so in order to compute the space reserved
+     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;
+
   /* We now have determined the sizes of the various dynamic sections.
      Allocate memory for them.  */
   relocs = FALSE;
@@ -1948,7 +2055,8 @@ 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.  */
-	  s->reloc_count = 0;
+	  if (s != htab->srelplt)
+	    s->reloc_count = 0;
 	}
       else
 	{
@@ -2035,6 +2143,41 @@ elf_i386_size_dynamic_sections (bfd *out
   return TRUE;
 }
 
+static bfd_boolean
+elf_i386_always_size_sections (bfd *output_bfd,
+			       struct bfd_link_info *info)
+{
+  asection *tls_sec = elf_hash_table (info)->tls_sec;
+
+  if (tls_sec)
+    {
+      struct elf_link_hash_entry *tlsbase;
+
+      tlsbase = elf_link_hash_lookup (elf_hash_table (info),
+				      "_TLS_MODULE_BASE_",
+				      FALSE, FALSE, FALSE);
+
+      if (tlsbase && tlsbase->type == STT_TLS)
+	{
+	  struct bfd_link_hash_entry *bh = NULL;
+	  const struct elf_backend_data *bed
+	    = get_elf_backend_data (output_bfd);
+
+	  if (!(_bfd_generic_link_add_one_symbol
+		(info, output_bfd, "_TLS_MODULE_BASE_", BSF_LOCAL,
+		 tls_sec, 0, NULL, FALSE,
+		 bed->collect, &bh)))
+	    return FALSE;
+	  tlsbase = (struct elf_link_hash_entry *)bh;
+	  tlsbase->def_regular = 1;
+	  tlsbase->other = STV_HIDDEN;
+	  (*bed->elf_backend_hide_symbol) (info, tlsbase, TRUE);
+	}
+    }
+
+  return TRUE;
+}
+
 /* Set the correct type for an x86 ELF section.  We do this by the
    section name, which is a hack, but ought to work.  */
 
@@ -2112,6 +2255,7 @@ elf_i386_relocate_section (bfd *output_b
   Elf_Internal_Shdr *symtab_hdr;
   struct elf_link_hash_entry **sym_hashes;
   bfd_vma *local_got_offsets;
+  bfd_vma *local_tlsdesc_gotents;
   Elf_Internal_Rela *rel;
   Elf_Internal_Rela *relend;
 
@@ -2119,6 +2263,7 @@ elf_i386_relocate_section (bfd *output_b
   symtab_hdr = &elf_tdata (input_bfd)->symtab_hdr;
   sym_hashes = elf_sym_hashes (input_bfd);
   local_got_offsets = elf_local_got_offsets (input_bfd);
+  local_tlsdesc_gotents = elf_i386_local_tlsdesc_gotent (input_bfd);
 
   rel = relocs;
   relend = relocs + input_section->reloc_count;
@@ -2130,7 +2275,7 @@ elf_i386_relocate_section (bfd *output_b
       struct elf_link_hash_entry *h;
       Elf_Internal_Sym *sym;
       asection *sec;
-      bfd_vma off;
+      bfd_vma off, offplt;
       bfd_vma relocation;
       bfd_boolean unresolved_reloc;
       bfd_reloc_status_type r;
@@ -2552,6 +2697,8 @@ elf_i386_relocate_section (bfd *output_b
 	  /* Fall through */
 
 	case R_386_TLS_GD:
+	case R_386_TLS_GOTDESC:
+	case R_386_TLS_DESC_CALL:
 	case R_386_TLS_IE_32:
 	case R_386_TLS_GOTIE:
 	  r_type = elf_i386_tls_transition (info, r_type, h == NULL);
@@ -2566,7 +2713,9 @@ elf_i386_relocate_section (bfd *output_b
 	    }
 	  if (tls_type == GOT_TLS_IE)
 	    tls_type = GOT_TLS_IE_NEG;
-	  if (r_type == R_386_TLS_GD)
+	  if (r_type == R_386_TLS_GD
+	      || r_type == R_386_TLS_GOTDESC
+	      || r_type == R_386_TLS_DESC_CALL)
 	    {
 	      if (tls_type == GOT_TLS_IE_POS)
 		r_type = R_386_TLS_GOTIE;
@@ -2640,6 +2789,67 @@ elf_i386_relocate_section (bfd *output_b
 		  rel++;
 		  continue;
 		}
+	      else if (ELF32_R_TYPE (rel->r_info) == R_386_TLS_GOTDESC)
+		{
+		  /* GDesc -> LE transition.
+		     It's originally something like:
+		     leal x@tlsdesc(%ebx), %eax
+
+		     aoliva FIXME.  Decide whether to change it to:
+		     gs: .byte 0x65 ; movl $x@ntpoff, %eax
+		     or
+		     leal x@ntpoff, %eax
+		     
+		     Registers other than %eax may be set up here.  */
+		  
+		  unsigned int val, type;
+		  bfd_vma roff;
+
+		  /* First, make sure it's a leal adding ebx to a
+		     32-bit offset into any register, although it's
+		     probably almost always going to be eax.  */
+		  roff = rel->r_offset;
+		  BFD_ASSERT (roff >= 2);
+		  type = bfd_get_8 (input_bfd, contents + roff - 2);
+		  BFD_ASSERT (type == 0x8d);
+		  val = bfd_get_8 (input_bfd, contents + roff - 1);
+		  BFD_ASSERT ((val & 0xc7) == 0x83);
+		  BFD_ASSERT (roff + 4 <= input_section->size);
+
+		  /* Now modify the instruction as appropriate.  */
+		  bfd_put_8 (output_bfd, 0x65, contents + roff - 2);
+		  /* aoliva FIXME: remove the above and xor the byte
+		     below with 0x86.  */
+		  bfd_put_8 (output_bfd, 0xb8 | ((val >> 3) & 7),
+			     contents + roff - 1);
+		  bfd_put_32 (output_bfd, -tpoff (info, relocation),
+			      contents + roff);
+		  continue;
+		}
+	      else if (ELF32_R_TYPE (rel->r_info) == R_386_TLS_DESC_CALL)
+		{
+		  /* GDesc -> LE transition.
+		     It's originally:
+		     call *(%eax)
+		     Turn it into:
+		     movl %eax, %eax  */
+		  
+		  unsigned int val, type;
+		  bfd_vma roff;
+
+		  /* First, make sure it's a call *(%eax).  */
+		  roff = rel->r_offset;
+		  BFD_ASSERT (roff + 2 <= input_section->size);
+		  type = bfd_get_8 (input_bfd, contents + roff);
+		  BFD_ASSERT (type == 0xff);
+		  val = bfd_get_8 (input_bfd, contents + roff + 1);
+		  BFD_ASSERT (val == 0x10);
+
+		  /* Now modify the instruction as appropriate.  */
+		  bfd_put_8 (output_bfd, 0x89, contents + roff);
+		  bfd_put_8 (output_bfd, 0xc0, contents + roff + 1);
+		  continue;
+		}
 	      else if (ELF32_R_TYPE (rel->r_info) == R_386_TLS_IE)
 		{
 		  unsigned int val, type;
@@ -2754,13 +2964,17 @@ elf_i386_relocate_section (bfd *output_b
 	    abort ();
 
 	  if (h != NULL)
-	    off = h->got.offset;
+	    {
+	      off = h->got.offset;
+	      offplt = elf_i386_hash_entry (h)->tlsdesc_got;
+	    }
 	  else
 	    {
 	      if (local_got_offsets == NULL)
 		abort ();
 
 	      off = local_got_offsets[r_symndx];
+	      offplt = local_tlsdesc_gotents[r_symndx];
 	    }
 
 	  if ((off & 1) != 0)
@@ -2770,35 +2984,77 @@ elf_i386_relocate_section (bfd *output_b
 	      Elf_Internal_Rela outrel;
 	      bfd_byte *loc;
 	      int dr_type, indx;
+	      asection *sreloc;
 
 	      if (htab->srelgot == NULL)
 		abort ();
 
+	      indx = h && h->dynindx != -1 ? h->dynindx : 0;
+
+	      if (GOT_TLS_GDESC_P (tls_type))
+		{
+		  outrel.r_info = ELF32_R_INFO (indx, R_386_TLS_DESC);
+		  BFD_ASSERT (htab->sgotplt_jump_table_size + offplt + 8
+			      <= htab->sgotplt->size);
+		  outrel.r_offset = (htab->sgotplt->output_section->vma
+				     + htab->sgotplt->output_offset
+				     + offplt
+				     + htab->sgotplt_jump_table_size);
+		  sreloc = htab->srelplt;
+		  loc = sreloc->contents;
+		  loc += sreloc->reloc_count++
+		    * sizeof (Elf32_External_Rel);
+		  BFD_ASSERT (loc + sizeof (Elf32_External_Rel)
+			      <= sreloc->contents + sreloc->size);
+		  bfd_elf32_swap_reloc_out (output_bfd, &outrel, loc);
+		  if (indx == 0)
+		    {
+		      BFD_ASSERT (! unresolved_reloc);
+		      bfd_put_32 (output_bfd,
+				  relocation - dtpoff_base (info),
+				  htab->sgotplt->contents + offplt
+				  + htab->sgotplt_jump_table_size + 4);
+		    }
+		  else
+		    {
+		      bfd_put_32 (output_bfd, 0,
+				  htab->sgotplt->contents + offplt
+				  + htab->sgotplt_jump_table_size + 4);
+		    }
+		}
+
+	      sreloc = htab->srelgot;
+
 	      outrel.r_offset = (htab->sgot->output_section->vma
 				 + htab->sgot->output_offset + off);
 
-	      indx = h && h->dynindx != -1 ? h->dynindx : 0;
-	      if (r_type == R_386_TLS_GD)
+	      if (GOT_TLS_GD_P (tls_type))
 		dr_type = R_386_TLS_DTPMOD32;
+	      else if (GOT_TLS_GDESC_P (tls_type))
+		goto dr_done;
 	      else if (tls_type == GOT_TLS_IE_POS)
 		dr_type = R_386_TLS_TPOFF;
 	      else
 		dr_type = R_386_TLS_TPOFF32;
+
 	      if (dr_type == R_386_TLS_TPOFF && indx == 0)
 		bfd_put_32 (output_bfd, relocation - dtpoff_base (info),
 			    htab->sgot->contents + off);
 	      else if (dr_type == R_386_TLS_TPOFF32 && indx == 0)
 		bfd_put_32 (output_bfd, dtpoff_base (info) - relocation,
 			    htab->sgot->contents + off);
-	      else
+	      else if (dr_type != R_386_TLS_DESC)
 		bfd_put_32 (output_bfd, 0,
 			    htab->sgot->contents + off);
 	      outrel.r_info = ELF32_R_INFO (indx, dr_type);
-	      loc = htab->srelgot->contents;
-	      loc += htab->srelgot->reloc_count++ * sizeof (Elf32_External_Rel);
+
+	      loc = sreloc->contents;
+	      loc += sreloc->reloc_count++ * sizeof (Elf32_External_Rel);
+	      BFD_ASSERT (loc + sizeof (Elf32_External_Rel)
+			  <= sreloc->contents + sreloc->size);
 	      bfd_elf32_swap_reloc_out (output_bfd, &outrel, loc);
 
-	      if (r_type == R_386_TLS_GD)
+	      if (GOT_TLS_GD_P (tls_type))
 		{
 		  if (indx == 0)
 		    {
@@ -2814,8 +3070,10 @@ elf_i386_relocate_section (bfd *output_b
 		      outrel.r_info = ELF32_R_INFO (indx,
 						    R_386_TLS_DTPOFF32);
 		      outrel.r_offset += 4;
-		      htab->srelgot->reloc_count++;
+		      sreloc->reloc_count++;
 		      loc += sizeof (Elf32_External_Rel);
+		      BFD_ASSERT (loc + sizeof (Elf32_External_Rel)
+				  <= sreloc->contents + sreloc->size);
 		      bfd_elf32_swap_reloc_out (output_bfd, &outrel, loc);
 		    }
 		}
@@ -2826,25 +3084,33 @@ elf_i386_relocate_section (bfd *output_b
 			      htab->sgot->contents + off + 4);
 		  outrel.r_info = ELF32_R_INFO (indx, R_386_TLS_TPOFF);
 		  outrel.r_offset += 4;
-		  htab->srelgot->reloc_count++;
+		  sreloc->reloc_count++;
 		  loc += sizeof (Elf32_External_Rel);
 		  bfd_elf32_swap_reloc_out (output_bfd, &outrel, loc);
 		}
 
+	    dr_done:
 	      if (h != NULL)
 		h->got.offset |= 1;
 	      else
 		local_got_offsets[r_symndx] |= 1;
 	    }
 
-	  if (off >= (bfd_vma) -2)
+	  if (off >= (bfd_vma) -2
+	      && ! GOT_TLS_GDESC_P (tls_type))
 	    abort ();
-	  if (r_type == ELF32_R_TYPE (rel->r_info))
+	  if (r_type == R_386_TLS_GOTDESC
+	      || r_type == R_386_TLS_DESC_CALL)
+	    {
+	      relocation = htab->sgotplt_jump_table_size + offplt;
+	      unresolved_reloc = FALSE;
+	    }
+	  else if (r_type == ELF32_R_TYPE (rel->r_info))
 	    {
 	      bfd_vma g_o_t = htab->sgotplt->output_section->vma
 			      + htab->sgotplt->output_offset;
 	      relocation = htab->sgot->output_section->vma
-			   + htab->sgot->output_offset + off - g_o_t;
+		+ htab->sgot->output_offset + off - g_o_t;
 	      if ((r_type == R_386_TLS_IE || r_type == R_386_TLS_GOTIE)
 		  && tls_type == GOT_TLS_IE_BOTH)
 		relocation += 4;
@@ -2852,7 +3118,7 @@ elf_i386_relocate_section (bfd *output_b
 		relocation += g_o_t;
 	      unresolved_reloc = FALSE;
 	    }
-	  else
+	  else if (ELF32_R_TYPE (rel->r_info) == R_386_TLS_GD)
 	    {
 	      unsigned int val, type;
 	      bfd_vma roff;
@@ -2916,6 +3182,97 @@ elf_i386_relocate_section (bfd *output_b
 	      rel++;
 	      continue;
 	    }
+	  else if (ELF32_R_TYPE (rel->r_info) == R_386_TLS_GOTDESC)
+	    {
+	      /* GDesc -> IE transition.
+		 It's originally something like:
+		 leal x@tlsdesc(%ebx), %eax
+
+		 aoliva FIXME: decide whether to change it to:
+		 movl x@gotntpoff(%ebx), %eax # before movl %eax,%eax
+		 or
+		 leal x@gotntpoff(%ebx), %eax # before movl (%eax),%eax
+		 but the latter won't work if we need to negate the
+		 loaded value.
+		     
+		 Registers other than %eax may be set up here.  */
+		  
+	      unsigned int val, type;
+	      bfd_vma roff;
+
+	      /* First, make sure it's a leal adding ebx to a 32-bit
+		 offset into any register, although it's probably
+		 almost always going to be eax.  */
+	      roff = rel->r_offset;
+	      BFD_ASSERT (roff >= 2);
+	      type = bfd_get_8 (input_bfd, contents + roff - 2);
+	      BFD_ASSERT (type == 0x8d);
+	      val = bfd_get_8 (input_bfd, contents + roff - 1);
+	      BFD_ASSERT ((val & 0xc7) == 0x83);
+	      BFD_ASSERT (roff + 4 <= input_section->size);
+
+	      /* Now modify the instruction as appropriate.  */
+	      /* To turn a leal into a movl in the form we use it, it
+		 suffices to change the first byte from 0x8d to 0x8b.
+		 aoliva FIXME: should we decide to keep the leal, all
+		 we have to do is remove the statement below, and
+		 adjust the relaxation of R_386_TLS_DESC_CALL.  */
+	      bfd_put_8 (output_bfd, 0x8b, contents + roff - 2);
+
+	      if (tls_type == GOT_TLS_IE_BOTH)
+		off += 4;
+
+	      bfd_put_32 (output_bfd,
+			  htab->sgot->output_section->vma
+			  + htab->sgot->output_offset + off
+			  - htab->sgotplt->output_section->vma
+			  - htab->sgotplt->output_offset,
+			  contents + roff);
+	      continue;
+	    }
+	  else if (ELF32_R_TYPE (rel->r_info) == R_386_TLS_DESC_CALL)
+	    {
+	      /* GDesc -> IE transition.
+		 It's originally:
+		 calll *(%eax)
+
+		 aoliva FIXME: decide whether to change it to:
+		 movl %eax,%eax # after movl x@gotntpoff(%ebx), %eax
+		 or
+		 movl (%eax),%eax # after leal x@gotntpoff(%ebx), %eax
+
+	         Either one works unless we have to negate the
+	         offset.  */
+		  
+	      unsigned int val, type;
+	      bfd_vma roff;
+
+	      /* First, make sure it's a call *(%eax).  */
+	      roff = rel->r_offset;
+	      BFD_ASSERT (roff + 2 <= input_section->size);
+	      type = bfd_get_8 (input_bfd, contents + roff);
+	      BFD_ASSERT (type == 0xff);
+	      val = bfd_get_8 (input_bfd, contents + roff + 1);
+	      BFD_ASSERT (val == 0x10);
+
+	      /* Now modify the instruction as appropriate.  */
+	      if (tls_type != GOT_TLS_IE_NEG)
+		{
+		  /* movl %eax,%eax */
+		  bfd_put_8 (output_bfd, 0x89, contents + roff);
+		  bfd_put_8 (output_bfd, 0xc0, contents + roff + 1);
+		}
+	      else
+		{
+		  /* negl %eax */
+		  bfd_put_8 (output_bfd, 0xf7, contents + roff);
+		  bfd_put_8 (output_bfd, 0xd8, contents + roff + 1);
+		}
+
+	      continue;
+	    }
+	  else
+	    BFD_ASSERT (FALSE);
 	  break;
 
 	case R_386_TLS_LDM:
@@ -3223,7 +3580,7 @@ elf_i386_finish_dynamic_symbol (bfd *out
     }
 
   if (h->got.offset != (bfd_vma) -1
-      && elf_i386_hash_entry(h)->tls_type != GOT_TLS_GD
+      && ! GOT_TLS_GD_ANY_P (elf_i386_hash_entry(h)->tls_type)
       && (elf_i386_hash_entry(h)->tls_type & GOT_TLS_IE) == 0)
     {
       Elf_Internal_Rela rel;
@@ -3558,6 +3915,7 @@ elf_i386_plt_sym_val (bfd_vma i, const a
 #define elf_backend_reloc_type_class	      elf_i386_reloc_type_class
 #define elf_backend_relocate_section	      elf_i386_relocate_section
 #define elf_backend_size_dynamic_sections     elf_i386_size_dynamic_sections
+#define elf_backend_always_size_sections      elf_i386_always_size_sections
 #define elf_backend_plt_sym_val		      elf_i386_plt_sym_val
 
 #include "elf32-target.h"
Index: bfd/elf64-x86-64.c
===================================================================
RCS file: /cvs/uberbaum/./bfd/elf64-x86-64.c,v
retrieving revision 1.107
diff -u -p -r1.107 elf64-x86-64.c
--- bfd/elf64-x86-64.c 31 Aug 2005 23:45:46 -0000 1.107
+++ bfd/elf64-x86-64.c 15 Sep 2005 22:38:19 -0000
@@ -112,12 +112,24 @@ static reloc_howto_type x86_64_elf_howto
   HOWTO(R_X86_64_GOTPC32, 0, 2, 32, TRUE, 0, complain_overflow_signed,
 	bfd_elf_generic_reloc, "R_X86_64_GOTPC32",
 	FALSE, 0xffffffff, 0xffffffff, TRUE),
+  HOWTO(R_X86_64_GOTPC32_TLSDESC, 0, 2, 32, TRUE, 0,
+	complain_overflow_bitfield, bfd_elf_generic_reloc,
+	"R_X86_64_GOTPC32_TLSDESC",
+	FALSE, 0xffffffff, 0xffffffff, TRUE),
+  HOWTO(R_X86_64_TLSDESC, 0, 4, 64, FALSE, 0,
+	complain_overflow_bitfield, bfd_elf_generic_reloc,
+	"R_X86_64_TLSDESC",
+	FALSE, MINUS_ONE, MINUS_ONE, FALSE),
+  HOWTO(R_X86_64_TLSDESC_CALL, 0, 0, 0, FALSE, 0,
+	complain_overflow_dont, bfd_elf_generic_reloc,
+	"R_X86_64_TLSDESC_CALL", 
+	FALSE, 0, 0, FALSE),
 
   /* We have a gap in the reloc numbers here.
      R_X86_64_standard counts the number up to this point, and
      R_X86_64_vt_offset is the value to subtract from a reloc type of
      R_X86_64_GNU_VT* to form an index into this table.  */
-#define R_X86_64_standard (R_X86_64_GOTPC32 + 1)
+#define R_X86_64_standard (R_X86_64_TLSDESC_CALL + 1)
 #define R_X86_64_vt_offset (R_X86_64_GNU_VTINHERIT - R_X86_64_standard)
 
 /* GNU extension to record C++ vtable hierarchy.  */
@@ -166,6 +178,9 @@ static const struct elf_reloc_map x86_64
   { BFD_RELOC_64_PCREL,		R_X86_64_PC64, },
   { BFD_RELOC_X86_64_GOTOFF64,	R_X86_64_GOTOFF64, },
   { BFD_RELOC_X86_64_GOTPC32,	R_X86_64_GOTPC32, },
+  { BFD_RELOC_X86_64_GOTPC32_TLSDESC, R_X86_64_GOTPC32_TLSDESC, },
+  { BFD_RELOC_X86_64_TLSDESC,	R_X86_64_TLSDESC, },
+  { BFD_RELOC_X86_64_TLSDESC_CALL, R_X86_64_TLSDESC_CALL, },
   { BFD_RELOC_VTABLE_INHERIT,	R_X86_64_GNU_VTINHERIT, },
   { BFD_RELOC_VTABLE_ENTRY,	R_X86_64_GNU_VTENTRY, },
 };
@@ -353,7 +368,20 @@ struct elf64_x86_64_link_hash_entry
 #define GOT_NORMAL	1
 #define GOT_TLS_GD	2
 #define GOT_TLS_IE	3
+#define GOT_TLS_GDESC	4
+#define GOT_TLS_GD_BOTH_P(type) \
+  ((type) == (GOT_TLS_GD | GOT_TLS_GDESC))
+#define GOT_TLS_GD_P(type) \
+  ((type) == GOT_TLS_GD || GOT_TLS_GD_BOTH_P (type))
+#define GOT_TLS_GDESC_P(type) \
+  ((type) == GOT_TLS_GDESC || GOT_TLS_GD_BOTH_P (type))
+#define GOT_TLS_GD_ANY_P(type) \
+  (GOT_TLS_GD_P (type) || GOT_TLS_GDESC_P (type))
   unsigned char tls_type;
+
+  /* Offset of the GOTPLT entry reserved for the TLS descriptor,
+     starting at the end of the jump table.  */
+  bfd_vma tlsdesc_got;
 };
 
 #define elf64_x86_64_hash_entry(ent) \
@@ -365,6 +393,9 @@ struct elf64_x86_64_obj_tdata
 
   /* tls_type for each local got entry.  */
   char *local_got_tls_type;
+
+  /* GOTPLT entries for TLS descriptors.  */
+  bfd_vma *local_tlsdesc_gotent;
 };
 
 #define elf64_x86_64_tdata(abfd) \
@@ -373,6 +404,8 @@ struct elf64_x86_64_obj_tdata
 #define elf64_x86_64_local_got_tls_type(abfd) \
   (elf64_x86_64_tdata (abfd)->local_got_tls_type)
 
+#define elf64_x86_64_local_tlsdesc_gotent(abfd) \
+  (elf64_x86_64_tdata (abfd)->local_tlsdesc_gotent)
 
 /* x86-64 ELF linker hash table.  */
 
@@ -389,11 +422,23 @@ struct elf64_x86_64_link_hash_table
   asection *sdynbss;
   asection *srelbss;
 
+  /* The offset into splt of the PLT entry for the TLS descriptor
+     resolver.  Special values are 0, if not necessary (or not found
+     to be necessary yet), and -1 if needed but not determined
+     yet.  */
+  bfd_vma tlsdesc_plt;
+  /* The offset into sgot of the GOT entry used by the PLT entry
+     above.  */
+  bfd_vma tlsdesc_got;
+
   union {
     bfd_signed_vma refcount;
     bfd_vma offset;
   } tls_ld_got;
 
+  /* The amount of space used by the jump slots in the GOT.  */
+  bfd_vma sgotplt_jump_table_size;
+
   /* Small local sym to section mapping cache.  */
   struct sym_sec_cache sym_sec;
 };
@@ -403,6 +448,9 @@ struct elf64_x86_64_link_hash_table
 #define elf64_x86_64_hash_table(p) \
   ((struct elf64_x86_64_link_hash_table *) ((p)->hash))
 
+#define elf64_x86_64_compute_jump_table_size(htab) \
+  ((htab)->srelplt->reloc_count * GOT_ENTRY_SIZE)
+
 /* Create an entry in an x86-64 ELF linker hash table.	*/
 
 static struct bfd_hash_entry *
@@ -428,6 +476,7 @@ link_hash_newfunc (struct bfd_hash_entry
       eh = (struct elf64_x86_64_link_hash_entry *) entry;
       eh->dyn_relocs = NULL;
       eh->tls_type = GOT_UNKNOWN;
+      eh->tlsdesc_got = (bfd_vma) -1;
     }
 
   return entry;
@@ -459,7 +508,10 @@ elf64_x86_64_link_hash_table_create (bfd
   ret->sdynbss = NULL;
   ret->srelbss = NULL;
   ret->sym_sec.abfd = NULL;
+  ret->tlsdesc_plt = 0;
+  ret->tlsdesc_got = 0;
   ret->tls_ld_got.refcount = 0;
+  ret->sgotplt_jump_table_size = 0;
 
   return &ret->elf.root;
 }
@@ -619,6 +671,8 @@ elf64_x86_64_tls_transition (struct bfd_
   switch (r_type)
     {
     case R_X86_64_TLSGD:
+    case R_X86_64_GOTPC32_TLSDESC:
+    case R_X86_64_TLSDESC_CALL:
     case R_X86_64_GOTTPOFF:
       if (is_local)
 	return R_X86_64_TPOFF32;
@@ -709,6 +763,8 @@ elf64_x86_64_check_relocs (bfd *abfd, st
 	case R_X86_64_GOT32:
 	case R_X86_64_GOTPCREL:
 	case R_X86_64_TLSGD:
+	case R_X86_64_GOTPC32_TLSDESC:
+	case R_X86_64_TLSDESC_CALL:
 	  /* This symbol requires a global offset table entry.	*/
 	  {
 	    int tls_type, old_tls_type;
@@ -718,6 +774,9 @@ elf64_x86_64_check_relocs (bfd *abfd, st
 	      default: tls_type = GOT_NORMAL; break;
 	      case R_X86_64_TLSGD: tls_type = GOT_TLS_GD; break;
 	      case R_X86_64_GOTTPOFF: tls_type = GOT_TLS_IE; break;
+	      case R_X86_64_GOTPC32_TLSDESC:
+	      case R_X86_64_TLSDESC_CALL:
+		tls_type = GOT_TLS_GDESC; break;
 	      }
 
 	    if (h != NULL)
@@ -736,14 +795,17 @@ elf64_x86_64_check_relocs (bfd *abfd, st
 		    bfd_size_type size;
 
 		    size = symtab_hdr->sh_info;
-		    size *= sizeof (bfd_signed_vma) + sizeof (char);
+		    size *= sizeof (bfd_signed_vma)
+		      + sizeof (bfd_vma) + sizeof (char);
 		    local_got_refcounts = ((bfd_signed_vma *)
 					   bfd_zalloc (abfd, size));
 		    if (local_got_refcounts == NULL)
 		      return FALSE;
 		    elf_local_got_refcounts (abfd) = local_got_refcounts;
+		    elf64_x86_64_local_tlsdesc_gotent (abfd)
+		      = (bfd_vma *) (local_got_refcounts + symtab_hdr->sh_info);
 		    elf64_x86_64_local_got_tls_type (abfd)
-		      = (char *) (local_got_refcounts + symtab_hdr->sh_info);
+		      = (char *) (local_got_refcounts + 2 * symtab_hdr->sh_info);
 		  }
 		local_got_refcounts[r_symndx] += 1;
 		old_tls_type
@@ -753,10 +815,14 @@ elf64_x86_64_check_relocs (bfd *abfd, st
 	    /* If a TLS symbol is accessed using IE at least once,
 	       there is no point to use dynamic model for it.  */
 	    if (old_tls_type != tls_type && old_tls_type != GOT_UNKNOWN
-		&& (old_tls_type != GOT_TLS_GD || tls_type != GOT_TLS_IE))
+		&& (! GOT_TLS_GD_ANY_P (old_tls_type)
+		    || tls_type != GOT_TLS_IE))
 	      {
-		if (old_tls_type == GOT_TLS_IE && tls_type == GOT_TLS_GD)
+		if (old_tls_type == GOT_TLS_IE && GOT_TLS_GD_ANY_P (tls_type))
 		  tls_type = old_tls_type;
+		else if (GOT_TLS_GD_ANY_P (old_tls_type)
+			 && GOT_TLS_GD_ANY_P (tls_type))
+		  tls_type |= old_tls_type;
 		else
 		  {
 		    (*_bfd_error_handler)
@@ -1104,6 +1170,8 @@ elf64_x86_64_gc_sweep_hook (bfd *abfd, s
 	  break;
 
 	case R_X86_64_TLSGD:
+	case R_X86_64_GOTPC32_TLSDESC:
+	case R_X86_64_TLSDESC_CALL:
 	case R_X86_64_GOTTPOFF:
 	case R_X86_64_GOT32:
 	case R_X86_64_GOTPCREL:
@@ -1371,6 +1439,7 @@ allocate_dynrelocs (struct elf_link_hash
 
 	  /* We also need to make an entry in the .rela.plt section.  */
 	  htab->srelplt->size += sizeof (Elf64_External_Rela);
+	  htab->srelplt->reloc_count++;
 	}
       else
 	{
@@ -1384,6 +1453,9 @@ allocate_dynrelocs (struct elf_link_hash
       h->needs_plt = 0;
     }
 
+  eh = (struct elf64_x86_64_link_hash_entry *) h;
+  eh->tlsdesc_got = (bfd_vma) -1;
+  
   /* If R_X86_64_GOTTPOFF symbol is now local to the binary,
      make it a R_X86_64_TPOFF32 requiring no GOT entry.  */
   if (h->got.refcount > 0
@@ -1406,31 +1478,46 @@ allocate_dynrelocs (struct elf_link_hash
 	    return FALSE;
 	}
 
-      s = htab->sgot;
-      h->got.offset = s->size;
-      s->size += GOT_ENTRY_SIZE;
-      /* R_X86_64_TLSGD needs 2 consecutive GOT slots.  */
-      if (tls_type == GOT_TLS_GD)
-	s->size += GOT_ENTRY_SIZE;
+      if (GOT_TLS_GDESC_P (tls_type))
+	{
+	  eh->tlsdesc_got = htab->sgotplt->size
+	    - elf64_x86_64_compute_jump_table_size (htab);
+	  htab->sgotplt->size += 2 * GOT_ENTRY_SIZE;
+	  h->got.offset = (bfd_vma) -2;
+	}
+      if (! GOT_TLS_GDESC_P (tls_type)
+	  || GOT_TLS_GD_P (tls_type))
+	{
+	  s = htab->sgot;
+	  h->got.offset = s->size;
+	  s->size += GOT_ENTRY_SIZE;
+	  if (GOT_TLS_GD_P (tls_type))
+	    s->size += GOT_ENTRY_SIZE;
+	}
       dyn = htab->elf.dynamic_sections_created;
       /* R_X86_64_TLSGD needs one dynamic relocation if local symbol
 	 and two if global.
 	 R_X86_64_GOTTPOFF needs one dynamic relocation.  */
-      if ((tls_type == GOT_TLS_GD && h->dynindx == -1)
+      if ((GOT_TLS_GD_P (tls_type) && h->dynindx == -1)
 	  || tls_type == GOT_TLS_IE)
 	htab->srelgot->size += sizeof (Elf64_External_Rela);
-      else if (tls_type == GOT_TLS_GD)
+      else if (GOT_TLS_GD_P (tls_type))
 	htab->srelgot->size += 2 * sizeof (Elf64_External_Rela);
-      else if ((ELF_ST_VISIBILITY (h->other) == STV_DEFAULT
-		|| h->root.type != bfd_link_hash_undefweak)
+      else if (! GOT_TLS_GDESC_P (tls_type)
+	       && (ELF_ST_VISIBILITY (h->other) == STV_DEFAULT
+		   || h->root.type != bfd_link_hash_undefweak)
 	       && (info->shared
 		   || WILL_CALL_FINISH_DYNAMIC_SYMBOL (dyn, 0, h)))
 	htab->srelgot->size += sizeof (Elf64_External_Rela);
+      if (GOT_TLS_GDESC_P (tls_type))
+	{
+	  htab->srelplt->size += sizeof (Elf64_External_Rela);
+	  htab->tlsdesc_plt = (bfd_vma) -1;
+	}
     }
   else
     h->got.offset = (bfd_vma) -1;
 
-  eh = (struct elf64_x86_64_link_hash_entry *) h;
   if (eh->dyn_relocs == NULL)
     return TRUE;
 
@@ -1578,6 +1665,7 @@ elf64_x86_64_size_dynamic_sections (bfd 
       bfd_signed_vma *local_got;
       bfd_signed_vma *end_local_got;
       char *local_tls_type;
+      bfd_vma *local_tlsdesc_gotent;
       bfd_size_type locsymcount;
       Elf_Internal_Shdr *symtab_hdr;
       asection *srel;
@@ -1621,20 +1709,43 @@ elf64_x86_64_size_dynamic_sections (bfd 
       locsymcount = symtab_hdr->sh_info;
       end_local_got = local_got + locsymcount;
       local_tls_type = elf64_x86_64_local_got_tls_type (ibfd);
+      local_tlsdesc_gotent = elf64_x86_64_local_tlsdesc_gotent (ibfd);
       s = htab->sgot;
       srel = htab->srelgot;
-      for (; local_got < end_local_got; ++local_got, ++local_tls_type)
+      for (; local_got < end_local_got;
+	   ++local_got, ++local_tls_type, ++local_tlsdesc_gotent)
 	{
+	  *local_tlsdesc_gotent = (bfd_vma) -1;
 	  if (*local_got > 0)
 	    {
-	      *local_got = s->size;
-	      s->size += GOT_ENTRY_SIZE;
-	      if (*local_tls_type == GOT_TLS_GD)
-		s->size += GOT_ENTRY_SIZE;
+	      if (GOT_TLS_GDESC_P (*local_tls_type))
+		{
+		  *local_tlsdesc_gotent = htab->sgotplt->size
+		    - elf64_x86_64_compute_jump_table_size (htab);
+		  htab->sgotplt->size += 2 * GOT_ENTRY_SIZE;
+		  *local_got = (bfd_vma) -2;
+		}
+	      if (! GOT_TLS_GDESC_P (*local_tls_type)
+		  || GOT_TLS_GD_P (*local_tls_type))
+		{
+		  *local_got = s->size;
+		  s->size += GOT_ENTRY_SIZE;
+		  if (GOT_TLS_GD_P (*local_tls_type))
+		    s->size += GOT_ENTRY_SIZE;
+		}
 	      if (info->shared
-		  || *local_tls_type == GOT_TLS_GD
+		  || GOT_TLS_GD_ANY_P (*local_tls_type)
 		  || *local_tls_type == GOT_TLS_IE)
-		srel->size += sizeof (Elf64_External_Rela);
+		{
+		  if (GOT_TLS_GDESC_P (*local_tls_type))
+		    {
+		      htab->srelplt->size += sizeof (Elf64_External_Rela);
+		      htab->tlsdesc_plt = (bfd_vma) -1;
+		    }
+		  if (! GOT_TLS_GDESC_P (*local_tls_type)
+		      || GOT_TLS_GD_P (*local_tls_type))
+		    srel->size += sizeof (Elf64_External_Rela);
+		}
 	    }
 	  else
 	    *local_got = (bfd_vma) -1;
@@ -1656,6 +1767,27 @@ elf64_x86_64_size_dynamic_sections (bfd 
      sym dynamic relocs.  */
   elf_link_hash_traverse (&htab->elf, allocate_dynrelocs, (PTR) info);
 
+  /* For every jump slot reserved in the sgotplt, reloc_count is
+     incremented.  However, when we reserve space for TLS descriptors,
+     it's not incremented, so in order to compute the space reserved
+     for them, it suffices to multiply the reloc count by the jump
+     slot size.  */
+  if (htab->srelplt)
+    htab->sgotplt_jump_table_size
+      = elf64_x86_64_compute_jump_table_size (htab);
+
+  if (htab->tlsdesc_plt)
+    {
+      htab->tlsdesc_got = htab->sgot->size;
+      htab->sgot->size += GOT_ENTRY_SIZE;
+      /* Reserve room for the initial entry.
+	 FIXME: we could probably do away with it in this case.  */
+      if (htab->splt->size == 0)
+	htab->splt->size += PLT_ENTRY_SIZE;
+      htab->tlsdesc_plt = htab->splt->size;
+      htab->splt->size += PLT_ENTRY_SIZE;
+    }
+
   /* We now have determined the sizes of the various dynamic sections.
      Allocate memory for them.  */
   relocs = FALSE;
@@ -1679,7 +1811,8 @@ elf64_x86_64_size_dynamic_sections (bfd 
 
 	  /* We use the reloc_count field as a counter if we need
 	     to copy relocs into the output file.  */
-	  s->reloc_count = 0;
+	  if (s != htab->srelplt)
+	    s->reloc_count = 0;
 	}
       else
 	{
@@ -1739,6 +1872,11 @@ elf64_x86_64_size_dynamic_sections (bfd 
 	      || !add_dynamic_entry (DT_PLTREL, DT_RELA)
 	      || !add_dynamic_entry (DT_JMPREL, 0))
 	    return FALSE;
+
+	  if (htab->tlsdesc_plt
+	      && (!add_dynamic_entry (DT_TLSDESC_PLT, 0)
+		  || !add_dynamic_entry (DT_TLSDESC_GOT, 0)))
+	    return FALSE;
 	}
 
       if (relocs)
@@ -1766,6 +1904,41 @@ elf64_x86_64_size_dynamic_sections (bfd 
   return TRUE;
 }
 
+static bfd_boolean
+elf64_x86_64_always_size_sections (bfd *output_bfd,
+				   struct bfd_link_info *info)
+{
+  asection *tls_sec = elf_hash_table (info)->tls_sec;
+
+  if (tls_sec)
+    {
+      struct elf_link_hash_entry *tlsbase;
+
+      tlsbase = elf_link_hash_lookup (elf_hash_table (info),
+				      "_TLS_MODULE_BASE_",
+				      FALSE, FALSE, FALSE);
+
+      if (tlsbase && tlsbase->type == STT_TLS)
+	{
+	  struct bfd_link_hash_entry *bh = NULL;
+	  const struct elf_backend_data *bed
+	    = get_elf_backend_data (output_bfd);
+
+	  if (!(_bfd_generic_link_add_one_symbol
+		(info, output_bfd, "_TLS_MODULE_BASE_", BSF_LOCAL,
+		 tls_sec, 0, NULL, FALSE,
+		 bed->collect, &bh)))
+	    return FALSE;
+	  tlsbase = (struct elf_link_hash_entry *)bh;
+	  tlsbase->def_regular = 1;
+	  tlsbase->other = STV_HIDDEN;
+	  (*bed->elf_backend_hide_symbol) (info, tlsbase, TRUE);
+	}
+    }
+
+  return TRUE;
+}
+
 /* Return the base VMA address which should be subtracted from real addresses
    when resolving @dtpoff relocation.
    This is PT_TLS segment p_vaddr.  */
@@ -1824,6 +1997,7 @@ elf64_x86_64_relocate_section (bfd *outp
   Elf_Internal_Shdr *symtab_hdr;
   struct elf_link_hash_entry **sym_hashes;
   bfd_vma *local_got_offsets;
+  bfd_vma *local_tlsdesc_gotents;
   Elf_Internal_Rela *rel;
   Elf_Internal_Rela *relend;
 
@@ -1834,6 +2008,7 @@ elf64_x86_64_relocate_section (bfd *outp
   symtab_hdr = &elf_tdata (input_bfd)->symtab_hdr;
   sym_hashes = elf_sym_hashes (input_bfd);
   local_got_offsets = elf_local_got_offsets (input_bfd);
+  local_tlsdesc_gotents = elf64_x86_64_local_tlsdesc_gotent (input_bfd);
 
   rel = relocs;
   relend = relocs + input_section->reloc_count;
@@ -1845,7 +2020,7 @@ elf64_x86_64_relocate_section (bfd *outp
       struct elf_link_hash_entry *h;
       Elf_Internal_Sym *sym;
       asection *sec;
-      bfd_vma off;
+      bfd_vma off, offplt;
       bfd_vma relocation;
       bfd_boolean unresolved_reloc;
       bfd_reloc_status_type r;
@@ -2204,6 +2379,8 @@ elf64_x86_64_relocate_section (bfd *outp
 	  break;
 
 	case R_X86_64_TLSGD:
+	case R_X86_64_GOTPC32_TLSDESC:
+	case R_X86_64_TLSDESC_CALL:
 	case R_X86_64_GOTTPOFF:
 	  r_type = elf64_x86_64_tls_transition (info, r_type, h == NULL);
 	  tls_type = GOT_UNKNOWN;
@@ -2215,7 +2392,9 @@ elf64_x86_64_relocate_section (bfd *outp
 	      if (!info->shared && h->dynindx == -1 && tls_type == GOT_TLS_IE)
 		r_type = R_X86_64_TPOFF32;
 	    }
-	  if (r_type == R_X86_64_TLSGD)
+	  if (r_type == R_X86_64_TLSGD
+	      || r_type == R_X86_64_GOTPC32_TLSDESC
+	      || r_type == R_X86_64_TLSDESC_CALL)
 	    {
 	      if (tls_type == GOT_TLS_IE)
 		r_type = R_X86_64_GOTTPOFF;
@@ -2257,6 +2436,67 @@ elf64_x86_64_relocate_section (bfd *outp
 		  rel++;
 		  continue;
 		}
+	      else if (ELF64_R_TYPE (rel->r_info) == R_X86_64_GOTPC32_TLSDESC)
+		{
+		  /* GDesc -> LE transition.
+		     It's originally something like:
+		     leaq x@tlsdesc(%rip), %rax
+
+		     Change it to:
+		     movl $x@tpoff, %rax
+		     
+		     Registers other than %rax may be set up here.  */
+		  
+		  unsigned int val, type, type2;
+		  bfd_vma roff;
+
+		  /* First, make sure it's a leaq adding rip to a
+		     32-bit offset into any register, although it's
+		     probably almost always going to be rax.  */
+		  roff = rel->r_offset;
+		  BFD_ASSERT (roff >= 3);
+		  type = bfd_get_8 (input_bfd, contents + roff - 3);
+		  BFD_ASSERT ((type & 0xfb) == 0x48);
+		  type2 = bfd_get_8 (input_bfd, contents + roff - 2);
+		  BFD_ASSERT (type2 == 0x8d);
+		  val = bfd_get_8 (input_bfd, contents + roff - 1);
+		  BFD_ASSERT ((val & 0xc7) == 0x05);
+		  BFD_ASSERT (roff + 4 <= input_section->size);
+
+		  /* Now modify the instruction as appropriate.  */
+		  bfd_put_8 (output_bfd, 0x48 | ((type >> 2) & 1),
+			     contents + roff - 3);
+		  bfd_put_8 (output_bfd, 0xc7, contents + roff - 2);
+		  bfd_put_8 (output_bfd, 0xc0 | ((val >> 3) & 7),
+			     contents + roff - 1);
+		  bfd_put_32 (output_bfd, tpoff (info, relocation),
+			      contents + roff);
+		  continue;
+		}
+	      else if (ELF64_R_TYPE (rel->r_info) == R_X86_64_TLSDESC_CALL)
+		{
+		  /* GDesc -> LE transition.
+		     It's originally:
+		     call *(%rax)
+		     Turn it into:
+		     rex64 nop.  */
+		  
+		  unsigned int val, type;
+		  bfd_vma roff;
+
+		  /* First, make sure it's a call *(%rax).  */
+		  roff = rel->r_offset;
+		  BFD_ASSERT (roff + 2 <= input_section->size);
+		  type = bfd_get_8 (input_bfd, contents + roff);
+		  BFD_ASSERT (type == 0xff);
+		  val = bfd_get_8 (input_bfd, contents + roff + 1);
+		  BFD_ASSERT (val == 0x10);
+
+		  /* Now modify the instruction as appropriate.  */
+		  bfd_put_8 (output_bfd, 0x48, contents + roff);
+		  bfd_put_8 (output_bfd, 0x90, contents + roff + 1);
+		  continue;
+		}
 	      else
 		{
 		  unsigned int val, type, reg;
@@ -2322,13 +2562,17 @@ elf64_x86_64_relocate_section (bfd *outp
 	    abort ();
 
 	  if (h != NULL)
-	    off = h->got.offset;
+	    {
+	      off = h->got.offset;
+	      offplt = elf64_x86_64_hash_entry (h)->tlsdesc_got;
+	    }
 	  else
 	    {
 	      if (local_got_offsets == NULL)
 		abort ();
 
 	      off = local_got_offsets[r_symndx];
+	      offplt = local_tlsdesc_gotents[r_symndx];
 	    }
 
 	  if ((off & 1) != 0)
@@ -2338,30 +2582,61 @@ elf64_x86_64_relocate_section (bfd *outp
 	      Elf_Internal_Rela outrel;
 	      bfd_byte *loc;
 	      int dr_type, indx;
+	      asection *sreloc;
 
 	      if (htab->srelgot == NULL)
 		abort ();
 
+	      indx = h && h->dynindx != -1 ? h->dynindx : 0;
+
+	      if (GOT_TLS_GDESC_P (tls_type))
+		{
+		  outrel.r_info = ELF64_R_INFO (indx, R_X86_64_TLSDESC);
+		  BFD_ASSERT (htab->sgotplt_jump_table_size + offplt
+			      + 2 * GOT_ENTRY_SIZE <= htab->sgotplt->size);
+		  outrel.r_offset = (htab->sgotplt->output_section->vma
+				     + htab->sgotplt->output_offset
+				     + offplt
+				     + htab->sgotplt_jump_table_size);
+		  sreloc = htab->srelplt;
+		  loc = sreloc->contents;
+		  loc += sreloc->reloc_count++
+		    * sizeof (Elf64_External_Rela);
+		  BFD_ASSERT (loc + sizeof (Elf64_External_Rela)
+			      <= sreloc->contents + sreloc->size);
+		  if (indx == 0)
+		    outrel.r_addend = relocation - dtpoff_base (info);
+		  else
+		    outrel.r_addend = 0;
+		  bfd_elf64_swap_reloca_out (output_bfd, &outrel, loc);
+		}
+
+	      sreloc = htab->srelgot;
+
 	      outrel.r_offset = (htab->sgot->output_section->vma
 				 + htab->sgot->output_offset + off);
 
-	      indx = h && h->dynindx != -1 ? h->dynindx : 0;
-	      if (r_type == R_X86_64_TLSGD)
+	      if (GOT_TLS_GD_P (tls_type))
 		dr_type = R_X86_64_DTPMOD64;
+	      else if (GOT_TLS_GDESC_P (tls_type))
+		goto dr_done;
 	      else
 		dr_type = R_X86_64_TPOFF64;
 
 	      bfd_put_64 (output_bfd, 0, htab->sgot->contents + off);
 	      outrel.r_addend = 0;
-	      if (dr_type == R_X86_64_TPOFF64 && indx == 0)
+	      if ((dr_type == R_X86_64_TPOFF64
+		   || dr_type == R_X86_64_TLSDESC) && indx == 0)
 		outrel.r_addend = relocation - dtpoff_base (info);
 	      outrel.r_info = ELF64_R_INFO (indx, dr_type);
 
-	      loc = htab->srelgot->contents;
-	      loc += htab->srelgot->reloc_count++ * sizeof (Elf64_External_Rela);
+	      loc = sreloc->contents;
+	      loc += sreloc->reloc_count++ * sizeof (Elf64_External_Rela);
+	      BFD_ASSERT (loc + sizeof (Elf64_External_Rela)
+			  <= sreloc->contents + sreloc->size);
 	      bfd_elf64_swap_reloca_out (output_bfd, &outrel, loc);
 
-	      if (r_type == R_X86_64_TLSGD)
+	      if (GOT_TLS_GD_P (tls_type))
 		{
 		  if (indx == 0)
 		    {
@@ -2377,27 +2652,37 @@ elf64_x86_64_relocate_section (bfd *outp
 		      outrel.r_info = ELF64_R_INFO (indx,
 						    R_X86_64_DTPOFF64);
 		      outrel.r_offset += GOT_ENTRY_SIZE;
-		      htab->srelgot->reloc_count++;
+		      sreloc->reloc_count++;
 		      loc += sizeof (Elf64_External_Rela);
+		      BFD_ASSERT (loc + sizeof (Elf64_External_Rela)
+				  <= sreloc->contents + sreloc->size);
 		      bfd_elf64_swap_reloca_out (output_bfd, &outrel, loc);
 		    }
 		}
 
+	    dr_done:
 	      if (h != NULL)
 		h->got.offset |= 1;
 	      else
 		local_got_offsets[r_symndx] |= 1;
 	    }
 
-	  if (off >= (bfd_vma) -2)
+	  if (off >= (bfd_vma) -2
+	      && ! GOT_TLS_GDESC_P (tls_type))
 	    abort ();
 	  if (r_type == ELF64_R_TYPE (rel->r_info))
 	    {
-	      relocation = htab->sgot->output_section->vma
-			   + htab->sgot->output_offset + off;
+	      if (r_type == R_X86_64_GOTPC32_TLSDESC
+		  || r_type == R_X86_64_TLSDESC_CALL)
+		relocation = htab->sgotplt->output_section->vma
+		  + htab->sgotplt->output_offset
+		  + offplt + htab->sgotplt_jump_table_size;
+	      else
+		relocation = htab->sgot->output_section->vma
+		  + htab->sgot->output_offset + off;
 	      unresolved_reloc = FALSE;
 	    }
-	  else
+	  else if (ELF64_R_TYPE (rel->r_info) == R_X86_64_TLSGD)
 	    {
 	      unsigned int i;
 	      static unsigned char tlsgd[8]
@@ -2437,6 +2722,79 @@ elf64_x86_64_relocate_section (bfd *outp
 	      rel++;
 	      continue;
 	    }
+	  else if (ELF64_R_TYPE (rel->r_info) == R_X86_64_GOTPC32_TLSDESC)
+	    {
+	      /* GDesc -> IE transition.
+		 It's originally something like:
+		 leaq x@tlsdesc(%rip), %rax
+
+		 Change it to:
+		 movq x@gottpoff(%rip), %rax # before rex64 nop
+		     
+		 Registers other than %rax may be set up here.  */
+		  
+	      unsigned int val, type, type2;
+	      bfd_vma roff;
+
+	      /* First, make sure it's a leaq adding rip to a 32-bit
+		 offset into any register, although it's probably
+		 almost always going to be rax.  */
+	      roff = rel->r_offset;
+	      BFD_ASSERT (roff >= 3);
+	      type = bfd_get_8 (input_bfd, contents + roff - 3);
+	      BFD_ASSERT ((type & 0xfb) == 0x48);
+	      type2 = bfd_get_8 (input_bfd, contents + roff - 2);
+	      BFD_ASSERT (type2 == 0x8d);
+	      val = bfd_get_8 (input_bfd, contents + roff - 1);
+	      BFD_ASSERT ((val & 0xc7) == 0x05);
+	      BFD_ASSERT (roff + 4 <= input_section->size);
+
+	      /* Now modify the instruction as appropriate.  */
+	      /* To turn a leaq into a movq in the form we use it, it
+		 suffices to change the second byte from 0x8d to 0x8b.
+		 aoliva FIXME: should we decide to keep the leaq, all
+		 we have to do is remove the statement below, and
+		 adjust the relaxation of R_X86_64_TLSDESC_CALL.  */
+	      bfd_put_8 (output_bfd, 0x8b, contents + roff - 2);
+
+	      bfd_put_32 (output_bfd,
+			  htab->sgot->output_section->vma
+			  + htab->sgot->output_offset + off
+			  - rel->r_offset
+			  - input_section->output_section->vma
+			  - input_section->output_offset
+			  - 4,
+			  contents + roff);
+	      continue;
+	    }
+	  else if (ELF64_R_TYPE (rel->r_info) == R_X86_64_TLSDESC_CALL)
+	    {
+	      /* GDesc -> IE transition.
+		 It's originally:
+		 call *(%rax)
+
+		 Change it to:
+		 rex64 nop.  */
+		  
+	      unsigned int val, type;
+	      bfd_vma roff;
+
+	      /* First, make sure it's a call *(%eax).  */
+	      roff = rel->r_offset;
+	      BFD_ASSERT (roff + 2 <= input_section->size);
+	      type = bfd_get_8 (input_bfd, contents + roff);
+	      BFD_ASSERT (type == 0xff);
+	      val = bfd_get_8 (input_bfd, contents + roff + 1);
+	      BFD_ASSERT (val == 0x10);
+
+	      /* Now modify the instruction as appropriate.  */
+	      bfd_put_8 (output_bfd, 0x48, contents + roff);
+	      bfd_put_8 (output_bfd, 0x90, contents + roff + 1);
+
+	      continue;
+	    }
+	  else
+	    BFD_ASSERT (FALSE);
 	  break;
 
 	case R_X86_64_TLSLD:
@@ -2675,7 +3033,7 @@ elf64_x86_64_finish_dynamic_symbol (bfd 
     }
 
   if (h->got.offset != (bfd_vma) -1
-      && elf64_x86_64_hash_entry (h)->tls_type != GOT_TLS_GD
+      && ! GOT_TLS_GD_ANY_P (elf64_x86_64_hash_entry (h)->tls_type)
       && elf64_x86_64_hash_entry (h)->tls_type != GOT_TLS_IE)
     {
       Elf_Internal_Rela rela;
@@ -2830,6 +3188,18 @@ elf64_x86_64_finish_dynamic_sections (bf
 		  dyn.d_un.d_val -= s->size;
 		}
 	      break;
+
+	    case DT_TLSDESC_PLT:
+	      s = htab->splt;
+	      dyn.d_un.d_ptr = s->output_section->vma + s->output_offset
+		+ htab->tlsdesc_plt;
+	      break;
+	      
+	    case DT_TLSDESC_GOT:
+	      s = htab->sgot;
+	      dyn.d_un.d_ptr = s->output_section->vma + s->output_offset
+		+ htab->tlsdesc_got;
+	      break;
 	    }
 
 	  bfd_elf64_swap_dyn_out (output_bfd, &dyn, dyncon);
@@ -2864,6 +3234,40 @@ elf64_x86_64_finish_dynamic_sections (bf
 
 	  elf_section_data (htab->splt->output_section)->this_hdr.sh_entsize =
 	    PLT_ENTRY_SIZE;
+
+	  if (htab->tlsdesc_plt)
+	    {
+	      bfd_put_64 (output_bfd, (bfd_vma) 0,
+			  htab->sgot->contents + htab->tlsdesc_got);
+
+	      memcpy (htab->splt->contents + htab->tlsdesc_plt,
+		      elf64_x86_64_plt0_entry,
+		      PLT_ENTRY_SIZE);
+
+	      /* Add offset for pushq GOT+8(%rip), since the
+		 instruction uses 6 bytes subtract this value.  */
+	      bfd_put_32 (output_bfd,
+			  (htab->sgotplt->output_section->vma
+			   + htab->sgotplt->output_offset
+			   + 8
+			   - htab->splt->output_section->vma
+			   - htab->splt->output_offset
+			   - htab->tlsdesc_plt
+			   - 6),
+			  htab->splt->contents + htab->tlsdesc_plt + 2);
+	      /* Add offset for jmp *GOT+TDG(%rip), where TGD stands for
+		 htab->tlsdesc_got. The 12 is the offset to the end of
+		 the instruction.  */
+	      bfd_put_32 (output_bfd,
+			  (htab->sgot->output_section->vma
+			   + htab->sgot->output_offset
+			   + htab->tlsdesc_got
+			   - htab->splt->output_section->vma
+			   - htab->splt->output_offset
+			   - htab->tlsdesc_plt
+			   - 12),
+			  htab->splt->contents + htab->tlsdesc_plt + 8);
+	    }
 	}
     }
 
@@ -3135,6 +3539,7 @@ static const struct bfd_elf_special_sect
 #define elf_backend_reloc_type_class	    elf64_x86_64_reloc_type_class
 #define elf_backend_relocate_section	    elf64_x86_64_relocate_section
 #define elf_backend_size_dynamic_sections   elf64_x86_64_size_dynamic_sections
+#define elf_backend_always_size_sections    elf64_x86_64_always_size_sections
 #define elf_backend_plt_sym_val		    elf64_x86_64_plt_sym_val
 #define elf_backend_object_p		    elf64_x86_64_elf_object_p
 #define bfd_elf64_mkobject		    elf64_x86_64_mkobject
Index: bfd/libbfd.h
===================================================================
RCS file: /cvs/uberbaum/./bfd/libbfd.h,v
retrieving revision 1.157
diff -u -p -r1.157 libbfd.h
--- bfd/libbfd.h 8 Sep 2005 12:49:18 -0000 1.157
+++ bfd/libbfd.h 15 Sep 2005 22:38:20 -0000
@@ -1044,6 +1044,9 @@ static const char *const bfd_reloc_code_
   "BFD_RELOC_386_TLS_DTPMOD32",
   "BFD_RELOC_386_TLS_DTPOFF32",
   "BFD_RELOC_386_TLS_TPOFF32",
+  "BFD_RELOC_386_TLS_GOTDESC",
+  "BFD_RELOC_386_TLS_DESC",
+  "BFD_RELOC_386_TLS_DESC_CALL",
   "BFD_RELOC_X86_64_GOT32",
   "BFD_RELOC_X86_64_PLT32",
   "BFD_RELOC_X86_64_COPY",
@@ -1062,6 +1065,9 @@ static const char *const bfd_reloc_code_
   "BFD_RELOC_X86_64_TPOFF32",
   "BFD_RELOC_X86_64_GOTOFF64",
   "BFD_RELOC_X86_64_GOTPC32",
+  "BFD_RELOC_X86_64_GOTPC32_TLSDESC",
+  "BFD_RELOC_X86_64_TLSDESC",
+  "BFD_RELOC_X86_64_TLSDESC_CALL",
   "BFD_RELOC_NS32K_IMM_8",
   "BFD_RELOC_NS32K_IMM_16",
   "BFD_RELOC_NS32K_IMM_32",
Index: bfd/reloc.c
===================================================================
RCS file: /cvs/uberbaum/./bfd/reloc.c,v
retrieving revision 1.138
diff -u -p -r1.138 reloc.c
--- bfd/reloc.c 8 Sep 2005 12:49:19 -0000 1.138
+++ bfd/reloc.c 15 Sep 2005 22:38:22 -0000
@@ -2329,6 +2329,12 @@ ENUMX
   BFD_RELOC_386_TLS_DTPOFF32
 ENUMX
   BFD_RELOC_386_TLS_TPOFF32
+ENUMX
+  BFD_RELOC_386_TLS_GOTDESC
+ENUMX
+  BFD_RELOC_386_TLS_DESC
+ENUMX
+  BFD_RELOC_386_TLS_DESC_CALL
 ENUMDOC
   i386/elf relocations
 
@@ -2368,6 +2374,12 @@ ENUMX
   BFD_RELOC_X86_64_GOTOFF64
 ENUMX
   BFD_RELOC_X86_64_GOTPC32
+ENUMX
+  BFD_RELOC_X86_64_GOTPC32_TLSDESC
+ENUMX
+  BFD_RELOC_X86_64_TLSDESC
+ENUMX
+  BFD_RELOC_X86_64_TLSDESC_CALL
 ENUMDOC
   x86-64/elf relocations
 
Index: binutils/ChangeLog
from  Alexandre Oliva  <aoliva@redhat.com>

	Introduce TLS descriptors for i386 and x86_64.
	* readelf.c (get_dynamic_type): Handle DT_TLSDESC_GOT and
	DT_TLSDESC_PLT.

Index: binutils/readelf.c
===================================================================
RCS file: /cvs/uberbaum/./binutils/readelf.c,v
retrieving revision 1.315
diff -u -p -r1.315 readelf.c
--- binutils/readelf.c 9 Sep 2005 13:12:21 -0000 1.315
+++ binutils/readelf.c 15 Sep 2005 22:38:29 -0000
@@ -1632,6 +1632,8 @@ get_dynamic_type (unsigned long type)
 
     case DT_VERSYM:	return "VERSYM";
 
+    case DT_TLSDESC_GOT: return "TLSDESC_GOT";
+    case DT_TLSDESC_PLT: return "TLSDESC_PLT";
     case DT_RELACOUNT:	return "RELACOUNT";
     case DT_RELCOUNT:	return "RELCOUNT";
     case DT_FLAGS_1:	return "FLAGS_1";
Index: gas/ChangeLog
from  Alexandre Oliva  <aoliva@redhat.com>

	Introduce TLS descriptors for i386 and x86_64.
	* config/tc-i386.c (tc_i386_fix_adjustable): Handle
	BFD_RELOC_386_TLS_GOTDESC, BFD_RELOC_386_TLS_DESC_CALL,
	BFD_RELOC_X86_64_GOTPC32_TLSDESC, BFD_RELOC_X86_64_TLSDESC_CALL.
	(optimize_disp): Emit fix up for BFD_RELOC_386_TLS_DESC_CALL and
	BFD_RELOC_X86_64_TLSDESC_CALL immediately, and clear the
	displacement bits.
	(build_modrm_byte): Set up zero modrm for TLS desc calls.
	(lex_got): Handle @tlsdesc and @tlscall.
	(md_apply_fix, tc_gen_reloc): Handle the new relocations.

Index: gas/config/tc-i386.c
===================================================================
RCS file: /cvs/uberbaum/./gas/config/tc-i386.c,v
retrieving revision 1.196
diff -u -p -r1.196 tc-i386.c
--- gas/config/tc-i386.c 14 Sep 2005 06:33:25 -0000 1.196
+++ gas/config/tc-i386.c 15 Sep 2005 22:38:39 -0000
@@ -1326,6 +1326,8 @@ tc_i386_fix_adjustable (fixP)
       || fixP->fx_r_type == BFD_RELOC_386_TLS_GOTIE
       || fixP->fx_r_type == BFD_RELOC_386_TLS_LE_32
       || fixP->fx_r_type == BFD_RELOC_386_TLS_LE
+      || fixP->fx_r_type == BFD_RELOC_386_TLS_GOTDESC
+      || fixP->fx_r_type == BFD_RELOC_386_TLS_DESC_CALL
       || fixP->fx_r_type == BFD_RELOC_X86_64_PLT32
       || fixP->fx_r_type == BFD_RELOC_X86_64_GOT32
       || fixP->fx_r_type == BFD_RELOC_X86_64_GOTPCREL
@@ -1337,6 +1339,8 @@ tc_i386_fix_adjustable (fixP)
       || fixP->fx_r_type == BFD_RELOC_X86_64_TPOFF32
       || fixP->fx_r_type == BFD_RELOC_X86_64_TPOFF64
       || fixP->fx_r_type == BFD_RELOC_X86_64_GOTOFF64
+      || fixP->fx_r_type == BFD_RELOC_X86_64_GOTPC32_TLSDESC
+      || fixP->fx_r_type == BFD_RELOC_X86_64_TLSDESC_CALL
       || fixP->fx_r_type == BFD_RELOC_VTABLE_INHERIT
       || fixP->fx_r_type == BFD_RELOC_VTABLE_ENTRY)
     return 0;
@@ -2177,7 +2181,14 @@ optimize_disp ()
 		&& fits_in_signed_byte (disp))
 	      i.types[op] |= Disp8;
 	  }
-	else
+	else if (i.reloc[op] == BFD_RELOC_386_TLS_DESC_CALL
+		 || i.reloc[op] == BFD_RELOC_X86_64_TLSDESC_CALL)
+	  {
+	    fix_new_exp (frag_now, frag_more (0) - frag_now->fr_literal, 0,
+			 i.op[op].disps, 0, i.reloc[op]);
+	    i.types[op] &= ~Disp;
+	  }
+ 	else
 	  /* We only support 64bit displacement on constants.  */
 	  i.types[op] &= ~Disp64;
       }
@@ -3123,7 +3134,13 @@ build_modrm_byte ()
 		  if ((i.index_reg->reg_flags & RegRex) != 0)
 		    i.rex |= REX_EXTY;
 		}
-	      i.rm.mode = mode_from_disp_size (i.types[op]);
+
+	      if (i.disp_operands
+		  && (i.reloc[op] == BFD_RELOC_386_TLS_DESC_CALL
+		      || i.reloc[op] == BFD_RELOC_X86_64_TLSDESC_CALL))
+		i.rm.mode = 0;
+	      else
+		i.rm.mode = mode_from_disp_size (i.types[op]);
 	    }
 
 	  if (fake_zero_displacement)
@@ -3796,7 +3813,9 @@ lex_got (enum bfd_reloc_code_real *reloc
     { "DTPOFF",   { BFD_RELOC_386_TLS_LDO_32, BFD_RELOC_X86_64_DTPOFF32 }, Imm32|Imm32S|Imm64|Disp32|Disp64 },
     { "GOTNTPOFF",{ BFD_RELOC_386_TLS_GOTIE,  0                         }, 0 },
     { "INDNTPOFF",{ BFD_RELOC_386_TLS_IE,     0                         }, 0 },
-    { "GOT",      { BFD_RELOC_386_GOT32,      BFD_RELOC_X86_64_GOT32    }, Imm32|Imm32S|Disp32 }
+    { "GOT",      { BFD_RELOC_386_GOT32,      BFD_RELOC_X86_64_GOT32    }, Imm32|Imm32S|Disp32 },
+    { "TLSDESC",  { BFD_RELOC_386_TLS_GOTDESC, BFD_RELOC_X86_64_GOTPC32_TLSDESC }, Imm32|Imm32S|Disp32 },
+    { "TLSCALL",  { BFD_RELOC_386_TLS_DESC_CALL, BFD_RELOC_X86_64_TLSDESC_CALL }, Imm32|Imm32S|Disp32 }
   };
   char *cp;
   unsigned int j;
@@ -5006,9 +5025,11 @@ md_apply_fix (fixP, valP, seg)
       case BFD_RELOC_386_TLS_IE_32:
       case BFD_RELOC_386_TLS_IE:
       case BFD_RELOC_386_TLS_GOTIE:
+      case BFD_RELOC_386_TLS_GOTDESC:
       case BFD_RELOC_X86_64_TLSGD:
       case BFD_RELOC_X86_64_TLSLD:
       case BFD_RELOC_X86_64_GOTTPOFF:
+      case BFD_RELOC_X86_64_GOTPC32_TLSDESC:
 	value = 0; /* Fully resolved at runtime.  No addend.  */
 	/* Fallthrough */
       case BFD_RELOC_386_TLS_LE:
@@ -5021,6 +5042,13 @@ md_apply_fix (fixP, valP, seg)
 	S_SET_THREAD_LOCAL (fixP->fx_addsy);
 	break;
 
+      case BFD_RELOC_386_TLS_DESC_CALL:
+      case BFD_RELOC_X86_64_TLSDESC_CALL:
+	value = 0; /* Fully resolved at runtime.  No addend.  */
+	S_SET_THREAD_LOCAL (fixP->fx_addsy);
+	fixP->fx_done = 0;
+	return;
+
       case BFD_RELOC_386_GOT32:
       case BFD_RELOC_X86_64_GOT32:
 	value = 0; /* Fully resolved at runtime.  No addend.  */
@@ -5499,6 +5527,8 @@ tc_gen_reloc (section, fixp)
     case BFD_RELOC_386_TLS_GOTIE:
     case BFD_RELOC_386_TLS_LE_32:
     case BFD_RELOC_386_TLS_LE:
+    case BFD_RELOC_386_TLS_GOTDESC:
+    case BFD_RELOC_386_TLS_DESC_CALL:
     case BFD_RELOC_X86_64_TLSGD:
     case BFD_RELOC_X86_64_TLSLD:
     case BFD_RELOC_X86_64_DTPOFF32:
@@ -5508,6 +5538,8 @@ tc_gen_reloc (section, fixp)
     case BFD_RELOC_X86_64_TPOFF64:
     case BFD_RELOC_X86_64_GOTOFF64:
     case BFD_RELOC_X86_64_GOTPC32:
+    case BFD_RELOC_X86_64_GOTPC32_TLSDESC:
+    case BFD_RELOC_X86_64_TLSDESC_CALL:
     case BFD_RELOC_RVA:
     case BFD_RELOC_VTABLE_ENTRY:
     case BFD_RELOC_VTABLE_INHERIT:
@@ -5602,6 +5634,8 @@ tc_gen_reloc (section, fixp)
 	  case BFD_RELOC_X86_64_TLSGD:
 	  case BFD_RELOC_X86_64_TLSLD:
 	  case BFD_RELOC_X86_64_GOTTPOFF:
+	  case BFD_RELOC_X86_64_GOTPC32_TLSDESC:
+	  case BFD_RELOC_X86_64_TLSDESC_CALL:
 	    rel->addend = fixp->fx_offset - fixp->fx_size;
 	    break;
 	  default:
Index: ld/testsuite/ChangeLog
from  Alexandre Oliva  <aoliva@redhat.com>

	* ld-i386/i386.exp: Run on x86_64-*-linux* and amd64-*-linux*.
	Add new tests.
	* ld-i386/pcrel16.d: Add -melf_i386.
	* ld-i386/pcrel8.d: Likewise.
	* ld-i386/tlsbindesc.dd: New.
	* ld-i386/tlsbindesc.rd: New.
	* ld-i386/tlsbindesc.s: New.
	* ld-i386/tlsbindesc.sd: New.
	* ld-i386/tlsbindesc.td: New.
	* ld-i386/tlsdesc.dd: New.
	* ld-i386/tlsdesc.rd: New.
	* ld-i386/tlsdesc.s: New.
	* ld-i386/tlsdesc.sd: New.
	* ld-i386/tlsdesc.td: New.
	* ld-i386/tlsgdesc.dd: New.
	* ld-i386/tlsgdesc.rd: New.
	* ld-i386/tlsgdesc.s: New.
	* ld-x86-64/x86-64.exp: Run new tests.
	* ld-x86-64/tlsbindesc.dd: New.
	* ld-x86-64/tlsbindesc.rd: New.
	* ld-x86-64/tlsbindesc.s: New.
	* ld-x86-64/tlsbindesc.sd: New.
	* ld-x86-64/tlsbindesc.td: New.
	* ld-x86-64/tlsdesc.dd: New.
	* ld-x86-64/tlsdesc.pd: New.
	* ld-x86-64/tlsdesc.rd: New.
	* ld-x86-64/tlsdesc.s: New.
	* ld-x86-64/tlsdesc.sd: New.
	* ld-x86-64/tlsdesc.td: New.
	* ld-x86-64/tlsgdesc.dd: New.
	* ld-x86-64/tlsgdesc.rd: New.
	* ld-x86-64/tlsgdesc.s: New.

Index: ld/testsuite/ld-i386/i386.exp
===================================================================
RCS file: /cvs/uberbaum/./ld/testsuite/ld-i386/i386.exp,v
retrieving revision 1.10
diff -u -p -r1.10 i386.exp
--- ld/testsuite/ld-i386/i386.exp 18 Jul 2005 06:23:40 -0000 1.10
+++ ld/testsuite/ld-i386/i386.exp 15 Sep 2005 22:39:23 -0000
@@ -1,5 +1,5 @@
 # Expect script for ld-i386 tests
-#   Copyright (C) 2002 Free Software Foundation
+#   Copyright (C) 2002, 2005 Free Software Foundation
 #
 # This file is free software; you can redistribute it and/or modify
 # it under the terms of the GNU General Public License as published by
@@ -22,7 +22,9 @@
 if { !([istarget "i?86-*-elf*"]		
        || ([istarget "i?86-*-linux*"]
 	   && ![istarget "*-*-*aout*"]
-	   && ![istarget "*-*-*oldld*"])) } {
+	   && ![istarget "*-*-*oldld*"])
+       || [istarget "x86_64-*-linux*"]
+       || [istarget "amd64-*-linux*"]) } {
     return
 }
 
@@ -41,6 +43,11 @@ set i386tests {
      {{readelf -Ssrl tlspic.rd} {objdump -drj.text tlspic.dd}
       {objdump -sj.got tlspic.sd} {objdump -sj.tdata tlspic.td}}
       "libtlspic.so"}
+    {"TLS descriptor -fpic -shared transitions" "-shared -melf_i386"
+     "--32" {tlsdesc.s tlspic2.s}
+     {{readelf -Ssrl tlsdesc.rd} {objdump -drj.text tlsdesc.dd}
+      {objdump "-s -j.got -j.got.plt" tlsdesc.sd} {objdump -sj.tdata tlsdesc.td}}
+      "libtlsdesc.so"}
     {"Helper shared library" "-shared -melf_i386"
      "--32" {tlslib.s} {} "libtlslib.so"}
     {"TLS -fpic and -fno-pic exec transitions"
@@ -48,10 +55,19 @@ set i386tests {
      {{readelf -Ssrl tlsbin.rd} {objdump -drj.text tlsbin.dd}
       {objdump -sj.got tlsbin.sd} {objdump -sj.tdata tlsbin.td}}
       "tlsbin"}
+    {"TLS descriptor -fpic and -fno-pic exec transitions"
+     "-melf_i386 tmpdir/libtlslib.so" "--32" {tlsbindesc.s tlsbin.s}
+     {{readelf -Ssrl tlsbindesc.rd} {objdump -drj.text tlsbindesc.dd}
+      {objdump -sj.got tlsbindesc.sd} {objdump -sj.tdata tlsbindesc.td}}
+      "tlsbindesc"}
     {"TLS -fno-pic -shared" "-shared -melf_i386"
      "--32" {tlsnopic1.s tlsnopic2.s}
      {{readelf -Ssrl tlsnopic.rd} {objdump -drj.text tlsnopic.dd}
       {objdump -sj.got tlsnopic.sd}} "libtlsnopic.so"}
+    {"TLS with global dynamic and descriptors"
+	"-shared -melf_i386" "--32" {tlsgdesc.s}
+     {{readelf -Ssrl tlsgdesc.rd} {objdump -drj.text tlsgdesc.dd}}
+      "libtlsgdesc.so"}
     {"TLS in debug sections" "-melf_i386"
      "--32" {tlsg.s}
      {{objdump -sj.debug_foobar tlsg.sd}} "tlsg"}
Index: ld/testsuite/ld-i386/pcrel16.d
===================================================================
RCS file: /cvs/uberbaum/./ld/testsuite/ld-i386/pcrel16.d,v
retrieving revision 1.2
diff -u -p -r1.2 pcrel16.d
--- ld/testsuite/ld-i386/pcrel16.d 3 Aug 2005 16:30:34 -0000 1.2
+++ ld/testsuite/ld-i386/pcrel16.d 15 Sep 2005 22:39:23 -0000
@@ -1,5 +1,6 @@
 #name: PCREL16 overflow
-#ld: -Ttext 0x0
+#as: --32
+#ld: -melf_i386 -Ttext 0x0
 #objdump: -drj.text -m i8086
 
 .*: +file format elf32-i386
Index: ld/testsuite/ld-i386/pcrel8.d
===================================================================
RCS file: /cvs/uberbaum/./ld/testsuite/ld-i386/pcrel8.d,v
retrieving revision 1.1
diff -u -p -r1.1 pcrel8.d
--- ld/testsuite/ld-i386/pcrel8.d 18 Jul 2005 06:23:40 -0000 1.1
+++ ld/testsuite/ld-i386/pcrel8.d 15 Sep 2005 22:39:23 -0000
@@ -1,3 +1,4 @@
 #name: PCREL8 overflow
-#ld:
+#as: --32
+#ld: -melf_i386
 #error: .*relocation truncated to fit: R_386_PC8 .*
Index: ld/testsuite/ld-i386/tlsbindesc.dd
===================================================================
RCS file: ld/testsuite/ld-i386/tlsbindesc.dd
diff -N ld/testsuite/ld-i386/tlsbindesc.dd
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ ld/testsuite/ld-i386/tlsbindesc.dd 15 Sep 2005 22:39:23 -0000
@@ -0,0 +1,461 @@
+#source: tlsbindesc.s
+#source: tlsbin.s
+#as: --32
+#ld: -melf_i386 tmpdir/libtlslib.so
+#objdump: -drj.text
+#target: i?86-*-*
+
+# PT_TLS layout is:
+# Offset from	Offset from	Name
+# TCB base	TCB end
+# 0x00		-0xa0		sg1..sg8
+# 0x20		-0x80		sl1..sl8
+# 0x40		-0x60		sh1..sh8
+# 0x60		-0x40		bg1..bg8
+# 0x80		-0x20		bl1..bl8
+
+.*: +file format elf32-i386
+
+Disassembly of section .text:
+
+[0-9a-f]+ <fn2>:
+ [0-9a-f]+:	55[ 	]+push   %ebp
+ [0-9a-f]+:	89 e5[ 	]+mov    %esp,%ebp
+ [0-9a-f]+:	53[ 	]+push   %ebx
+ [0-9a-f]+:	50[ 	]+push   %eax
+ [0-9a-f]+:	e8 00 00 00 00[ 	]+call   [0-9a-f]+ <fn2\+0xa>
+ [0-9a-f]+:	5b[ 	]+pop    %ebx
+ [0-9a-f]+:	81 c3 fa 10 00 00[ 	]+add    \$0x10fa,%ebx
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+#  GD -> IE because variable is not defined in executable
+ [0-9a-f]+:	8b 83 f8 ff ff ff[ 	]+mov    0xfffffff8\(%ebx\),%eax
+#				->R_386_TLS_TPOFF32	sG1
+ [0-9a-f]+:	f7 d8[ 	]+neg    %eax
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+#  GD -> IE because variable is not defined in executable where
+#  the variable is referenced through @gottpoff too
+ [0-9a-f]+:	8b 83 e8 ff ff ff[ 	]+mov    0xffffffe8\(%ebx\),%eax
+#				->R_386_TLS_TPOFF32	sG2
+ [0-9a-f]+:	f7 d8[ 	]+neg    %eax
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+#  GD -> IE because variable is not defined in executable where
+#  the variable is referenced through @gotntpoff too
+ [0-9a-f]+:	8b 83 dc ff ff ff[ 	]+mov    0xffffffdc\(%ebx\),%eax
+#				->R_386_TLS_TPOFF	sG3
+ [0-9a-f]+:	89 c0[ 	]+mov    %eax,%eax
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+#  GD -> IE because variable is not defined in executable where
+#  the variable is referenced through @gottpoff and @gotntpoff too
+ [0-9a-f]+:	8b 83 f0 ff ff ff[ 	]+mov    0xfffffff0\(%ebx\),%eax
+#				->R_386_TLS_TPOFF32	sG4
+ [0-9a-f]+:	89 c0[ 	]+mov    %eax,%eax
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+#  GD -> LE with global variable defined in executable
+ [0-9a-f]+:	65[ 	]+gs
+ [0-9a-f]+:	b8 00 f0 ff ff[ 	]+mov    \$0xfffff000,%eax
+#							sg1
+ [0-9a-f]+:	89 c0[ 	]+mov    %eax,%eax
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+#  GD -> LE with local variable defined in executable
+ [0-9a-f]+:	65[ 	]+gs
+ [0-9a-f]+:	b8 20 f0 ff ff[ 	]+mov    \$0xfffff020,%eax
+#							sl1
+ [0-9a-f]+:	89 c0[ 	]+mov    %eax,%eax
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+#  GD -> LE with hidden variable defined in executable
+ [0-9a-f]+:	65[ 	]+gs
+ [0-9a-f]+:	b8 40 f0 ff ff[ 	]+mov    \$0xfffff040,%eax
+#							sh1
+ [0-9a-f]+:	89 c0[ 	]+mov    %eax,%eax
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+#  LD -> LE
+ [0-9a-f]+:	65[ 	]+gs
+ [0-9a-f]+:	b8 00 f0 ff ff[ 	]+mov    \$0xfffff000,%eax
+ [0-9a-f]+:	89 c0[ 	]+mov    %eax,%eax
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	8d 90 20 f0 ff ff[ 	]+lea    0xfffff020\(%eax\),%edx
+#							sl1
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	8d 88 24 f0 ff ff[ 	]+lea    0xfffff024\(%eax\),%ecx
+#							sl2
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+#  LD -> LE against hidden variables
+ [0-9a-f]+:	65[ 	]+gs
+ [0-9a-f]+:	b8 00 f0 ff ff[ 	]+mov    \$0xfffff000,%eax
+ [0-9a-f]+:	89 c0[ 	]+mov    %eax,%eax
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	8d 90 40 f0 ff ff[ 	]+lea    0xfffff040\(%eax\),%edx
+#							sh1
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	8d 88 44 f0 ff ff[ 	]+lea    0xfffff044\(%eax\),%ecx
+#							sh2
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+#  @gottpoff IE against global var
+ [0-9a-f]+:	65 8b 0d 00 00 00 00[ 	]+mov    %gs:0x0,%ecx
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	2b 8b e8 ff ff ff[ 	]+sub    0xffffffe8\(%ebx\),%ecx
+#				->R_386_TLS_TPOFF32	sG2
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+#  @gottpoff IE against global var
+ [0-9a-f]+:	65 a1 00 00 00 00[ 	]+mov    %gs:0x0,%eax
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	2b 83 ec ff ff ff[ 	]+sub    0xffffffec\(%ebx\),%eax
+#				->R_386_TLS_TPOFF32	sG4
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+#  @gotntpoff IE against global var
+ [0-9a-f]+:	65 8b 0d 00 00 00 00[ 	]+mov    %gs:0x0,%ecx
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	03 8b dc ff ff ff[ 	]+add    0xffffffdc\(%ebx\),%ecx
+#				->R_386_TLS_TPOFF	sG3
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+#  @gotntpoff IE against global var
+ [0-9a-f]+:	65 a1 00 00 00 00[ 	]+mov    %gs:0x0,%eax
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	03 83 f0 ff ff ff[ 	]+add    0xfffffff0\(%ebx\),%eax
+#				->R_386_TLS_TPOFF	sG4
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+#  @gottpoff IE -> LE against global var defined in exec
+ [0-9a-f]+:	65 8b 0d 00 00 00 00[ 	]+mov    %gs:0x0,%ecx
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	81 e9 00 10 00 00[ 	]+sub    \$0x1000,%ecx
+#							sg1
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+#  @gotntpoff IE -> LE against local var
+ [0-9a-f]+:	65 8b 0d 00 00 00 00[ 	]+mov    %gs:0x0,%ecx
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	81 c0 20 f0 ff ff[ 	]+add    \$0xfffff020,%eax
+#							sl1
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+#  @gottpoff IE -> LE against hidden var
+ [0-9a-f]+:	65 8b 0d 00 00 00 00[ 	]+mov    %gs:0x0,%ecx
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	81 e9 c0 0f 00 00[ 	]+sub    \$0xfc0,%ecx
+#							sh1
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+#  Direct access through %gs
+#  @gotntpoff IE against global var
+ [0-9a-f]+:	8b 8b e0 ff ff ff[ 	]+mov    0xffffffe0\(%ebx\),%ecx
+#				->R_386_TLS_TPOFF	sG5
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	65 8b 11[ 	]+mov    %gs:\(%ecx\),%edx
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+#  @gotntpoff IE->LE against local var
+ [0-9a-f]+:	c7 c0 30 f0 ff ff[ 	]+mov    \$0xfffff030,%eax
+#							sl5
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	65 8b 10[ 	]+mov    %gs:\(%eax\),%edx
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+#  @gotntpoff IE->LE against hidden var
+ [0-9a-f]+:	c7 c2 50 f0 ff ff[ 	]+mov    \$0xfffff050,%edx
+#							sh5
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	65 8b 12[ 	]+mov    %gs:\(%edx\),%edx
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	8b 5d fc[ 	]+mov    0xfffffffc\(%ebp\),%ebx
+ [0-9a-f]+:	c9[ 	]+leave *
+ [0-9a-f]+:	c3[ 	]+ret *
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+
+[0-9a-f]+ <_start>:
+ [0-9a-f]+:	55[ 	]+push   %ebp
+ [0-9a-f]+:	89 e5[ 	]+mov    %esp,%ebp
+ [0-9a-f]+:	e8 00 00 00 00[ 	]+call   [0-9a-f]+ <_start\+0x8>
+ [0-9a-f]+:	59[ 	]+pop    %ecx
+ [0-9a-f]+:	81 c1 a4 0f 00 00[ 	]+add    \$0xfa4,%ecx
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+#  @gottpoff IE against global var
+ [0-9a-f]+:	65 8b 15 00 00 00 00[ 	]+mov    %gs:0x0,%edx
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	2b 91 f4 ff ff ff[ 	]+sub    0xfffffff4\(%ecx\),%edx
+#				->R_386_TLS_TPOFF32	sG6
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+#  @indntpoff IE against global var
+ [0-9a-f]+:	65 a1 00 00 00 00[ 	]+mov    %gs:0x0,%eax
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	03 05 e8 a0 04 08[ 	]+add    0x804a0e8,%eax
+#				->R_386_TLS_TPOFF	sG7
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+#  @indntpoff direct %gs access IE against global var
+ [0-9a-f]+:	8b 15 00 a1 04 08[ 	]+mov    0x804a100,%edx
+#				->R_386_TLS_TPOFF	sG8
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	65 8b 02[ 	]+mov    %gs:\(%edx\),%eax
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+#  @gottpoff IE -> LE against global var defined in exec
+ [0-9a-f]+:	65 8b 15 00 00 00 00[ 	]+mov    %gs:0x0,%edx
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	81 ea 8c 0f 00 00[ 	]+sub    \$0xf8c,%edx
+#							bg6
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+#  @indntpoff IE -> LE against global var defined in exec
+ [0-9a-f]+:	65 a1 00 00 00 00[ 	]+mov    %gs:0x0,%eax
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	81 c0 78 f0 ff ff[ 	]+add    \$0xfffff078,%eax
+#							bg7
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+#  @indntpoff direct %gs access IE -> LE against global var defined
+#  in exec
+ [0-9a-f]+:	c7 c2 7c f0 ff ff[ 	]+mov    \$0xfffff07c,%edx
+#							bg8
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	65 8b 02[ 	]+mov    %gs:\(%edx\),%eax
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+#  @gottpoff IE -> LE against local var
+ [0-9a-f]+:	65 8b 15 00 00 00 00[ 	]+mov    %gs:0x0,%edx
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	81 ea 6c 0f 00 00[ 	]+sub    \$0xf6c,%edx
+#							bl6
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+#  @indntpoff IE -> LE against local var
+ [0-9a-f]+:	65 a1 00 00 00 00[ 	]+mov    %gs:0x0,%eax
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	81 c0 98 f0 ff ff[ 	]+add    \$0xfffff098,%eax
+#							bl7
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+#  @indntpoff direct %gs access IE -> LE against local var
+ [0-9a-f]+:	c7 c2 9c f0 ff ff[ 	]+mov    \$0xfffff09c,%edx
+#							bl8
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	65 8b 02[ 	]+mov    %gs:\(%edx\),%eax
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+#  @gottpoff IE -> LE against hidden but not local var
+ [0-9a-f]+:	65 8b 15 00 00 00 00[ 	]+mov    %gs:0x0,%edx
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	81 ea ac 0f 00 00[ 	]+sub    \$0xfac,%edx
+#							sh6
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+#  @indntpoff IE -> LE against hidden but not local var
+ [0-9a-f]+:	65 a1 00 00 00 00[ 	]+mov    %gs:0x0,%eax
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	81 c0 58 f0 ff ff[ 	]+add    \$0xfffff058,%eax
+#							sh7
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+#  @indntpoff direct %gs access IE -> LE against hidden but not
+#  local var
+ [0-9a-f]+:	c7 c2 5c f0 ff ff[ 	]+mov    \$0xfffff05c,%edx
+#							sh8
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	65 8b 02[ 	]+mov    %gs:\(%edx\),%eax
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+#  LE @tpoff, global var defined in exec
+ [0-9a-f]+:	ba 00 10 00 00[ 	]+mov    \$0x1000,%edx
+#							sg1
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	65 a1 00 00 00 00[ 	]+mov    %gs:0x0,%eax
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	29 d0[ 	]+sub    %edx,%eax
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+#  LE @tpoff, local var
+ [0-9a-f]+:	b8 7f 0f 00 00[ 	]+mov    \$0xf7f,%eax
+#							bl1+1
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	65 8b 15 00 00 00 00[ 	]+mov    %gs:0x0,%edx
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	29 c2[ 	]+sub    %eax,%edx
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+#  LE @tpoff, hidden var defined in exec
+ [0-9a-f]+:	b8 bd 0f 00 00[ 	]+mov    \$0xfbd,%eax
+#							sh1+3
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	65 8b 15 00 00 00 00[ 	]+mov    %gs:0x0,%edx
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	29 c2[ 	]+sub    %eax,%edx
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+#  LE @ntpoff, global var defined in exec
+ [0-9a-f]+:	65 a1 00 00 00 00[ 	]+mov    %gs:0x0,%eax
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	8d 90 04 f0 ff ff[ 	]+lea    0xfffff004\(%eax\),%edx
+#							sg2
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+#  LE @ntpoff, local var, non-canonical sequence
+ [0-9a-f]+:	b8 86 f0 ff ff[ 	]+mov    \$0xfffff086,%eax
+#							bl2+2
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	65 8b 15 00 00 00 00[ 	]+mov    %gs:0x0,%edx
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	01 c2[ 	]+add    %eax,%edx
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+#  LE @ntpoff, hidden var defined in exec, non-canonical sequence
+ [0-9a-f]+:	65 8b 15 00 00 00 00[ 	]+mov    %gs:0x0,%edx
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	81 c2 45 f0 ff ff[ 	]+add    \$0xfffff045,%edx
+#							sh2+1
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+#  LE @ntpoff, global var defined in exec
+ [0-9a-f]+:	65 a1 08 f0 ff ff[ 	]+mov    %gs:0xfffff008,%eax
+#							sg3
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+#  LE @ntpoff, local var
+ [0-9a-f]+:	65 8b 15 8b f0 ff ff[ 	]+mov    %gs:0xfffff08b,%edx
+#							bl3+3
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+#  LE @ntpoff, hidden var defined in exec
+ [0-9a-f]+:	65 8b 15 49 f0 ff ff[ 	]+mov    %gs:0xfffff049,%edx
+#							sh3+1
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	8b 5d fc[ 	]+mov    0xfffffffc\(%ebp\),%ebx
+ [0-9a-f]+:	c9[ 	]+leave *
+ [0-9a-f]+:	c3[ 	]+ret *
Index: ld/testsuite/ld-i386/tlsbindesc.rd
===================================================================
RCS file: ld/testsuite/ld-i386/tlsbindesc.rd
diff -N ld/testsuite/ld-i386/tlsbindesc.rd
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ ld/testsuite/ld-i386/tlsbindesc.rd 15 Sep 2005 22:39:23 -0000
@@ -0,0 +1,154 @@
+#source: tlsbindesc.s
+#source: tlsbin.s
+#as: --32
+#ld: -melf_i386 tmpdir/libtlslib.so
+#readelf: -Ssrl
+#target: i?86-*-*
+
+There are 15 section headers, starting at offset 0x[0-9a-f]+:
+
+Section Headers:
+  \[Nr\] Name +Type +Addr +Off +Size +ES Flg Lk Inf Al
+  \[ 0\] +NULL +0+ 0+ 0+ 0+ +0 +0 +0
+  \[ 1\] \.interp +.*
+  \[ 2\] \.hash +.*
+  \[ 3\] \.dynsym +.*
+  \[ 4\] \.dynstr +.*
+  \[ 5\] \.rel.dyn +.*
+  \[ 6\] \.text +PROGBITS +0+8049000 .*
+  \[ 7\] \.tdata +PROGBITS +0+804a000 [0-9a-f]+ 000060 00 WAT  0   0 4096
+  \[ 8\] \.tbss +NOBITS +[0-9a-f]+ [0-9a-f]+ 000040 00 WAT  0   0  1
+  \[ 9\] \.dynamic +DYNAMIC +0+804a060 .*
+  \[10\] \.got +PROGBITS +0+804a0e0 .*
+  \[11\] \.got\.plt +PROGBITS +0+804a104 .*
+  \[12\] \.shstrtab +.*
+  \[13\] \.symtab +.*
+  \[14\] \.strtab +.*
+Key to Flags:
+.*
+.*
+.*
+
+Elf file type is EXEC \(Executable file\)
+Entry point 0x8049158
+There are 6 program headers, starting at offset [0-9]+
+
+Program Headers:
+  Type +Offset +VirtAddr +PhysAddr +FileSiz +MemSiz +Flg Align
+  PHDR.*
+  INTERP.*
+.*Requesting program interpreter.*
+  LOAD.*
+  LOAD.*
+  DYNAMIC.*
+  TLS +0x[0-9a-f]+ 0x[0-9a-f]+ 0x[0-9a-f]+ 0x0+60 0x0+a0 R +0x1000
+
+ Section to Segment mapping:
+  Segment Sections...
+   00 +
+   01 +.interp *
+   02 +.interp .hash .dynsym .dynstr .rel.dyn .text *
+   03 +.tdata .dynamic .got .got.plt *
+   04 +.dynamic *
+   05 +.tdata .tbss *
+
+Relocation section '.rel.dyn' at offset 0x[0-9a-f]+ contains 9 entries:
+ Offset +Info +Type +Sym.Value +Sym. Name
+0+804a0e0  0000010e R_386_TLS_TPOFF +0+ +sG3
+0+804a0e4  0000020e R_386_TLS_TPOFF +0+ +sG5
+0+804a0e8  0000030e R_386_TLS_TPOFF +0+ +sG7
+0+804a0ec  00000425 R_386_TLS_TPOFF32 0+ +sG2
+0+804a0f0  00000525 R_386_TLS_TPOFF32 0+ +sG4
+0+804a0f4  0000050e R_386_TLS_TPOFF +0+ +sG4
+0+804a0f8  00000725 R_386_TLS_TPOFF32 0+ +sG6
+0+804a0fc  00000825 R_386_TLS_TPOFF32 0+ +sG1
+0+804a100  00000b0e R_386_TLS_TPOFF +0+ +sG8
+
+Symbol table '.dynsym' contains 12 entries:
+ +Num: +Value  Size Type +Bind +Vis +Ndx Name
+ +[0-9]+: 0+ +0 NOTYPE  LOCAL  DEFAULT  UND *
+ +[0-9]+: 0+ +0 TLS +GLOBAL DEFAULT  UND sG3
+ +[0-9]+: 0+ +0 TLS +GLOBAL DEFAULT  UND sG5
+ +[0-9]+: 0+ +0 TLS +GLOBAL DEFAULT  UND sG7
+ +[0-9]+: 0+ +0 TLS +GLOBAL DEFAULT  UND sG2
+ +[0-9]+: 0+ +0 TLS +GLOBAL DEFAULT  UND sG4
+ +[0-9]+: [0-9a-f]+ +0 NOTYPE  GLOBAL DEFAULT  ABS __bss_start
+ +[0-9]+: 0+ +0 TLS +GLOBAL DEFAULT  UND sG6
+ +[0-9]+: 0+ +0 TLS +GLOBAL DEFAULT  UND sG1
+ +[0-9]+: [0-9a-f]+ +0 NOTYPE  GLOBAL DEFAULT  ABS _edata
+ +[0-9]+: [0-9a-f]+ +0 NOTYPE  GLOBAL DEFAULT  ABS _end
+ +[0-9]+: 0+ +0 TLS +GLOBAL DEFAULT  UND sG8
+
+Symbol table '.symtab' contains 71 entries:
+ +Num: +Value  Size Type +Bind +Vis +Ndx Name
+ +[0-9]+: 0+ +0 NOTYPE  LOCAL  DEFAULT  UND *
+ +[0-9]+: [0-9a-f]+ +0 SECTION LOCAL  DEFAULT +1 *
+ +[0-9]+: [0-9a-f]+ +0 SECTION LOCAL  DEFAULT +2 *
+ +[0-9]+: [0-9a-f]+ +0 SECTION LOCAL  DEFAULT +3 *
+ +[0-9]+: [0-9a-f]+ +0 SECTION LOCAL  DEFAULT +4 *
+ +[0-9]+: [0-9a-f]+ +0 SECTION LOCAL  DEFAULT +5 *
+ +[0-9]+: [0-9a-f]+ +0 SECTION LOCAL  DEFAULT +6 *
+ +[0-9]+: [0-9a-f]+ +0 SECTION LOCAL  DEFAULT +7 *
+ +[0-9]+: [0-9a-f]+ +0 SECTION LOCAL  DEFAULT +8 *
+ +[0-9]+: [0-9a-f]+ +0 SECTION LOCAL  DEFAULT +9 *
+ +[0-9]+: [0-9a-f]+ +0 SECTION LOCAL  DEFAULT +10 *
+ +[0-9]+: [0-9a-f]+ +0 SECTION LOCAL  DEFAULT +11 *
+ +[0-9]+: [0-9a-f]+ +0 SECTION LOCAL  DEFAULT +12 *
+ +[0-9]+: [0-9a-f]+ +0 SECTION LOCAL  DEFAULT +13 *
+ +[0-9]+: [0-9a-f]+ +0 SECTION LOCAL  DEFAULT +14 *
+ +[0-9]+: 00000020 +0 TLS +LOCAL  DEFAULT +7 sl1
+ +[0-9]+: 00000024 +0 TLS +LOCAL  DEFAULT +7 sl2
+ +[0-9]+: 00000028 +0 TLS +LOCAL  DEFAULT +7 sl3
+ +[0-9]+: 0000002c +0 TLS +LOCAL  DEFAULT +7 sl4
+ +[0-9]+: 00000030 +0 TLS +LOCAL  DEFAULT +7 sl5
+ +[0-9]+: 00000034 +0 TLS +LOCAL  DEFAULT +7 sl6
+ +[0-9]+: 00000038 +0 TLS +LOCAL  DEFAULT +7 sl7
+ +[0-9]+: 0000003c +0 TLS +LOCAL  DEFAULT +7 sl8
+ +[0-9]+: 00000080 +0 TLS +LOCAL  DEFAULT +8 bl1
+ +[0-9]+: 00000084 +0 TLS +LOCAL  DEFAULT +8 bl2
+ +[0-9]+: 00000088 +0 TLS +LOCAL  DEFAULT +8 bl3
+ +[0-9]+: 0000008c +0 TLS +LOCAL  DEFAULT +8 bl4
+ +[0-9]+: 00000090 +0 TLS +LOCAL  DEFAULT +8 bl5
+ +[0-9]+: 00000094 +0 TLS +LOCAL  DEFAULT +8 bl6
+ +[0-9]+: 00000098 +0 TLS +LOCAL  DEFAULT +8 bl7
+ +[0-9]+: 0000009c +0 TLS +LOCAL  DEFAULT +8 bl8
+ +[0-9]+: 00000000 +0 TLS +LOCAL  HIDDEN +7 _TLS_MODULE_BASE_
+ +[0-9]+: 0+804a060 +0 OBJECT  LOCAL  HIDDEN    9 _DYNAMIC
+ +[0-9]+: [0-9a-f]+ +0 OBJECT  LOCAL  HIDDEN   11 _GLOBAL_OFFSET_TABLE_
+ +[0-9]+: 0+ +0 TLS +GLOBAL DEFAULT  UND sG3
+ +[0-9]+: 0000001c +0 TLS +GLOBAL DEFAULT +7 sg8
+ +[0-9]+: 0000007c +0 TLS +GLOBAL DEFAULT +8 bg8
+ +[0-9]+: 00000074 +0 TLS +GLOBAL DEFAULT +8 bg6
+ +[0-9]+: 0+ +0 TLS +GLOBAL DEFAULT  UND sG5
+ +[0-9]+: 00000068 +0 TLS +GLOBAL DEFAULT +8 bg3
+ +[0-9]+: 00000008 +0 TLS +GLOBAL DEFAULT +7 sg3
+ +[0-9]+: 0+ +0 TLS +GLOBAL DEFAULT  UND sG7
+ +[0-9]+: 00000048 +0 TLS +GLOBAL HIDDEN +7 sh3
+ +[0-9]+: 0+ +0 TLS +GLOBAL DEFAULT  UND sG2
+ +[0-9]+: 0000000c +0 TLS +GLOBAL DEFAULT +7 sg4
+ +[0-9]+: 0+ +0 TLS +GLOBAL DEFAULT  UND sG4
+ +[0-9]+: 00000010 +0 TLS +GLOBAL DEFAULT +7 sg5
+ +[0-9]+: 00000070 +0 TLS +GLOBAL DEFAULT +8 bg5
+ +[0-9]+: 00000058 +0 TLS +GLOBAL HIDDEN +7 sh7
+ +[0-9]+: 0000005c +0 TLS +GLOBAL HIDDEN +7 sh8
+ +[0-9]+: 0+ +0 TLS +GLOBAL DEFAULT +7 sg1
+ +[0-9]+: 0+8049158 +0 FUNC +GLOBAL DEFAULT +6 _start
+ +[0-9]+: 0000004c +0 TLS +GLOBAL HIDDEN +7 sh4
+ +[0-9]+: 00000078 +0 TLS +GLOBAL DEFAULT +8 bg7
+ +[0-9]+: 00000050 +0 TLS +GLOBAL HIDDEN +7 sh5
+ +[0-9]+: [0-9a-f]+ +0 NOTYPE  GLOBAL DEFAULT  ABS __bss_start
+ +[0-9]+: 0+ +0 TLS +GLOBAL DEFAULT  UND sG6
+ +[0-9]+: 0+8049000 +0 FUNC +GLOBAL DEFAULT +6 fn2
+ +[0-9]+: 00000004 +0 TLS +GLOBAL DEFAULT +7 sg2
+ +[0-9]+: 0+ +0 TLS +GLOBAL DEFAULT  UND sG1
+ +[0-9]+: 00000040 +0 TLS +GLOBAL HIDDEN +7 sh1
+ +[0-9]+: 00000014 +0 TLS +GLOBAL DEFAULT +7 sg6
+ +[0-9]+: 00000018 +0 TLS +GLOBAL DEFAULT +7 sg7
+ +[0-9]+: [0-9a-f]+ +0 NOTYPE  GLOBAL DEFAULT  ABS _edata
+ +[0-9]+: [0-9a-f]+ +0 NOTYPE  GLOBAL DEFAULT  ABS _end
+ +[0-9]+: 00000044 +0 TLS +GLOBAL HIDDEN +7 sh2
+ +[0-9]+: 00000054 +0 TLS +GLOBAL HIDDEN +7 sh6
+ +[0-9]+: 0+ +0 TLS +GLOBAL DEFAULT  UND sG8
+ +[0-9]+: 00000064 +0 TLS +GLOBAL DEFAULT +8 bg2
+ +[0-9]+: 00000060 +0 TLS +GLOBAL DEFAULT +8 bg1
+ +[0-9]+: 0000006c +0 TLS +GLOBAL DEFAULT +8 bg4
Index: ld/testsuite/ld-i386/tlsbindesc.s
===================================================================
RCS file: ld/testsuite/ld-i386/tlsbindesc.s
diff -N ld/testsuite/ld-i386/tlsbindesc.s
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ ld/testsuite/ld-i386/tlsbindesc.s 15 Sep 2005 22:39:23 -0000
@@ -0,0 +1,167 @@
+	/* Force .got aligned to 4K, so it very likely gets at 0x804a100
+	   (0x60 bytes .tdata and 0xa0 bytes .dynamic)  */
+	.section ".tdata", "awT", @progbits
+	.balign	4096
+	.globl sg1, sg2, sg3, sg4, sg5, sg6, sg7, sg8
+	.globl sh1, sh2, sh3, sh4, sh5, sh6, sh7, sh8
+	.hidden sh1, sh2, sh3, sh4, sh5, sh6, sh7, sh8
+sg1:	.long 17
+sg2:	.long 18
+sg3:	.long 19
+sg4:	.long 20
+sg5:	.long 21
+sg6:	.long 22
+sg7:	.long 23
+sg8:	.long 24
+sl1:	.long 65
+sl2:	.long 66
+sl3:	.long 67
+sl4:	.long 68
+sl5:	.long 69
+sl6:	.long 70
+sl7:	.long 71
+sl8:	.long 72
+sh1:	.long 257
+sh2:	.long 258
+sh3:	.long 259
+sh4:	.long 260
+sh5:	.long 261
+sh6:	.long 262
+sh7:	.long 263
+sh8:	.long 264
+	/* Force .text aligned to 4K, so it very likely gets at 0x8049000.  */
+	.text
+	.balign	4096
+	.globl	fn2
+	.type	fn2,@function
+fn2:
+	pushl	%ebp
+	movl	%esp, %ebp
+	pushl	%ebx
+	pushl	%eax
+	call	1f
+1:	popl	%ebx
+	addl	$_GLOBAL_OFFSET_TABLE_+[.-1b], %ebx
+	nop;nop;nop;nop
+
+	/* GD -> IE because variable is not defined in executable */
+	leal	sG1@tlsdesc(%ebx), %eax
+	call	*sG1@tlscall(%eax)
+	nop;nop;nop;nop
+
+	/* GD -> IE because variable is not defined in executable where
+	   the variable is referenced through @gottpoff too */
+	leal	sG2@tlsdesc(%ebx), %eax
+	call	*sG2@tlscall(%eax)
+	nop;nop;nop;nop
+
+	/* GD -> IE because variable is not defined in executable where
+	   the variable is referenced through @gotntpoff too */
+	leal	sG3@tlsdesc(%ebx), %eax
+	call	*sG3@tlscall(%eax)
+	nop;nop;nop;nop
+
+	/* GD -> IE because variable is not defined in executable where
+	   the variable is referenced through @gottpoff and @gotntpoff too */
+	leal	sG4@tlsdesc(%ebx), %eax
+	call	*sG4@tlscall(%eax)
+	nop;nop;nop;nop
+
+	/* GD -> LE with global variable defined in executable */
+	leal	sg1@tlsdesc(%ebx), %eax
+	call	*sg1@tlscall(%eax)
+	nop;nop;nop;nop
+
+	/* GD -> LE with local variable defined in executable */
+	leal	sl1@tlsdesc(%ebx), %eax
+	call	*sl1@tlscall(%eax)
+	nop;nop;nop;nop
+
+	/* GD -> LE with hidden variable defined in executable */
+	leal	sh1@tlsdesc(%ebx), %eax
+	call	*sh1@tlscall(%eax)
+	nop;nop;nop;nop
+
+	/* LD -> LE */
+	leal	_TLS_MODULE_BASE_@tlsdesc(%ebx), %eax
+	call	*_TLS_MODULE_BASE_@tlscall(%eax)
+	nop;nop
+	leal	sl1@dtpoff(%eax), %edx
+	nop;nop
+	leal	sl2@dtpoff(%eax), %ecx
+	nop;nop;nop;nop
+
+	/* LD -> LE against hidden variables */
+	leal	_TLS_MODULE_BASE_@tlsdesc(%ebx), %eax
+	call	*_TLS_MODULE_BASE_@tlscall(%eax)
+	nop;nop
+	leal	sh1@dtpoff(%eax), %edx
+	nop;nop
+	leal	sh2@dtpoff(%eax), %ecx
+	nop;nop;nop;nop
+
+	/* @gottpoff IE against global var  */
+	movl	%gs:0, %ecx
+	nop;nop
+	subl	sG2@gottpoff(%ebx), %ecx
+	nop;nop;nop;nop
+
+	/* @gottpoff IE against global var  */
+	movl	%gs:0, %eax
+	nop;nop
+	subl	sG4@gottpoff(%ebx), %eax
+	nop;nop;nop;nop
+
+	/* @gotntpoff IE against global var  */
+	movl	%gs:0, %ecx
+	nop;nop
+	addl	sG3@gotntpoff(%ebx), %ecx
+	nop;nop;nop;nop
+
+	/* @gotntpoff IE against global var  */
+	movl	%gs:0, %eax
+	nop;nop
+	addl	sG4@gotntpoff(%ebx), %eax
+	nop;nop;nop;nop
+
+	/* @gottpoff IE -> LE against global var defined in exec */
+	movl	%gs:0, %ecx
+	nop;nop
+	subl	sg1@gottpoff(%ebx), %ecx
+	nop;nop;nop;nop
+
+	/* @gotntpoff IE -> LE against local var */
+	movl	%gs:0, %ecx
+	nop;nop
+	addl	sl1@gotntpoff(%ebx), %eax
+	nop;nop;nop;nop
+
+	/* @gottpoff IE -> LE against hidden var */
+	movl	%gs:0, %ecx
+	nop;nop
+	subl	sh1@gottpoff(%ebx), %ecx
+	nop;nop;nop;nop
+
+	/* Direct access through %gs  */
+
+	/* @gotntpoff IE against global var  */
+	movl	sG5@gotntpoff(%ebx), %ecx
+	nop;nop
+	movl	%gs:(%ecx), %edx
+	nop;nop;nop;nop
+
+	/* @gotntpoff IE->LE against local var  */
+	movl	sl5@gotntpoff(%ebx), %eax
+	nop;nop
+	movl	%gs:(%eax), %edx
+	nop;nop;nop;nop
+
+	/* @gotntpoff IE->LE against hidden var  */
+	movl	sh5@gotntpoff(%ebx), %edx
+	nop;nop
+	movl	%gs:(%edx), %edx
+	nop;nop;nop;nop
+
+	movl    -4(%ebp), %ebx
+	leave
+	ret
Index: ld/testsuite/ld-i386/tlsbindesc.sd
===================================================================
RCS file: ld/testsuite/ld-i386/tlsbindesc.sd
diff -N ld/testsuite/ld-i386/tlsbindesc.sd
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ ld/testsuite/ld-i386/tlsbindesc.sd 15 Sep 2005 22:39:23 -0000
@@ -0,0 +1,13 @@
+#source: tlsbindesc.s
+#source: tlsbin.s
+#as: --32
+#ld: -melf_i386 tmpdir/libtlslib.so
+#objdump: -sj.got
+#target: i?86-*-*
+
+.*:     file format elf32-i386
+
+Contents of section \.got:
+ 804a0e0 [0-9a-f]+ 00000000 00000000 [0-9a-f]+  .*
+ 804a0f0 00000000 00000000 00000000 00000000  .*
+ 804a100 00000000  +.*
Index: ld/testsuite/ld-i386/tlsbindesc.td
===================================================================
RCS file: ld/testsuite/ld-i386/tlsbindesc.td
diff -N ld/testsuite/ld-i386/tlsbindesc.td
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ ld/testsuite/ld-i386/tlsbindesc.td 15 Sep 2005 22:39:23 -0000
@@ -0,0 +1,16 @@
+#source: tlsbindesc.s
+#source: tlsbin.s
+#as: --32
+#ld: -melf_i386 tmpdir/libtlslib.so
+#objdump: -sj.tdata
+#target: i?86-*-*
+
+.*:     file format elf32-i386
+
+Contents of section \.tdata:
+ 804a000 11000000 12000000 13000000 14000000  .*
+ 804a010 15000000 16000000 17000000 18000000  .*
+ 804a020 41000000 42000000 43000000 44000000  .*
+ 804a030 45000000 46000000 47000000 48000000  .*
+ 804a040 01010000 02010000 03010000 04010000  .*
+ 804a050 05010000 06010000 07010000 08010000  .*
Index: ld/testsuite/ld-i386/tlsdesc.dd
===================================================================
RCS file: ld/testsuite/ld-i386/tlsdesc.dd
diff -N ld/testsuite/ld-i386/tlsdesc.dd
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ ld/testsuite/ld-i386/tlsdesc.dd 15 Sep 2005 22:39:23 -0000
@@ -0,0 +1,391 @@
+#source: tlsdesc.s
+#source: tlspic2.s
+#as: --32
+#ld: -shared -melf_i386
+#objdump: -drj.text
+#target: i?86-*-*
+
+.*: +file format elf32-i386
+
+Disassembly of section .text:
+
+[0-9a-f]+ <fn1>:
+ [0-9a-f]+:	55[ 	]+push   %ebp
+ [0-9a-f]+:	89 e5[ 	]+mov    %esp,%ebp
+ [0-9a-f]+:	53[ 	]+push   %ebx
+ [0-9a-f]+:	50[ 	]+push   %eax
+ [0-9a-f]+:	e8 00 00 00 00[ 	]+call   [0-9a-f]+ <fn1\+0xa>
+ [0-9a-f]+:	5b[ 	]+pop    %ebx
+ [0-9a-f]+:	81 c3 9a 13 00 00[ 	]+add    \$0x[0-9a-f]+,%ebx
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+#  GDesc
+ [0-9a-f]+:	8d 83 24 00 00 00[ 	]+lea    0x24\(%ebx\),%eax
+#				->R_386_TLS_DESC	sg1
+ [0-9a-f]+:	ff 10[ 	]+call   \*\(%eax\)
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+#  GD -> IE because variable is referenced through @gottpoff too
+ [0-9a-f]+:	8b 83 f8 ff ff ff[ 	]+mov    0xfffffff8\(%ebx\),%eax
+#				->R_386_TLS_TPOFF	sg2
+ [0-9a-f]+:	f7 d8[ 	]+neg    %eax
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+#  GD -> IE because variable is referenced through @gotntpoff too
+ [0-9a-f]+:	8b 83 c4 ff ff ff[ 	]+mov    0xffffffc4\(%ebx\),%eax
+#				->R_386_TLS_TPOFF32	sg3
+ [0-9a-f]+:	89 c0[ 	]+mov    %eax,%eax
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+#  GD -> IE because variable is referenced through @gottpoff and
+ [0-9a-f]+:	8b 83 d4 ff ff ff[ 	]+mov    0xffffffd4\(%ebx\),%eax
+#				->R_386_TLS_TPOFF32	sg4
+ [0-9a-f]+:	89 c0[ 	]+mov    %eax,%eax
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+#  GD against local variable
+ [0-9a-f]+:	8d 83 0c 00 00 00[ 	]+lea    0xc\(%ebx\),%eax
+#				->R_386_TLS_DESC	sl1
+ [0-9a-f]+:	ff 10[ 	]+call   \*\(%eax\)
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+#  GD -> IE against local variable referenced through @gottpoff too
+ [0-9a-f]+:	8b 83 b0 ff ff ff[ 	]+mov    0xffffffb0\(%ebx\),%eax
+#				->R_386_TLS_TPOFF	sl2
+ [0-9a-f]+:	f7 d8[ 	]+neg    %eax
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+#  GD -> IE against local variable referenced through @gotntpoff
+ [0-9a-f]+:	8b 83 b4 ff ff ff[ 	]+mov    0xffffffb4\(%ebx\),%eax
+#				->R_386_TLS_TPOFF32	sl3
+ [0-9a-f]+:	89 c0[ 	]+mov    %eax,%eax
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+#  GD -> IE against local variable referenced through @gottpoff and
+ [0-9a-f]+:	8b 83 bc ff ff ff[ 	]+mov    0xffffffbc\(%ebx\),%eax
+#				->R_386_TLS_TPOFF32	sl4
+ [0-9a-f]+:	89 c0[ 	]+mov    %eax,%eax
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+#  GD against hidden and local variable
+ [0-9a-f]+:	8d 83 2c 00 00 00[ 	]+lea    0x2c\(%ebx\),%eax
+#				->R_386_TLS_DESC	sh1
+ [0-9a-f]+:	ff 10[ 	]+call   \*\(%eax\)
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+#  GD -> IE against hidden and local variable referenced through @gottpoff too
+ [0-9a-f]+:	8b 83 fc ff ff ff[ 	]+mov    0xfffffffc\(%ebx\),%eax
+#				->R_386_TLS_TPOFF	sh2
+ [0-9a-f]+:	f7 d8[ 	]+neg    %eax
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+#  GD -> IE against hidden and local variable referenced through @gotntpoff too
+ [0-9a-f]+:	8b 83 c8 ff ff ff[ 	]+mov    0xffffffc8\(%ebx\),%eax
+#				->R_386_TLS_TPOFF32	sh3
+ [0-9a-f]+:	89 c0[ 	]+mov    %eax,%eax
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+#  GD -> IE against hidden and local variable referenced through @gottpoff and @gotntpoff too
+ [0-9a-f]+:	8b 83 e8 ff ff ff[ 	]+mov    0xffffffe8\(%ebx\),%eax
+#				->R_386_TLS_TPOFF32	sh4
+ [0-9a-f]+:	89 c0[ 	]+mov    %eax,%eax
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+#  GD against hidden but not local variable
+ [0-9a-f]+:	8d 83 14 00 00 00[ 	]+lea    0x14\(%ebx\),%eax
+#				->R_386_TLS_DESC	sH1
+ [0-9a-f]+:	ff 10[ 	]+call   \*\(%eax\)
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+#  GD -> IE against hidden but not local variable referenced through
+ [0-9a-f]+:	8b 83 cc ff ff ff[ 	]+mov    0xffffffcc\(%ebx\),%eax
+#				->R_386_TLS_TPOFF	sH2
+ [0-9a-f]+:	f7 d8[ 	]+neg    %eax
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+#  GD -> IE against hidden but not local variable referenced through
+ [0-9a-f]+:	8b 83 ec ff ff ff[ 	]+mov    0xffffffec\(%ebx\),%eax
+#				->R_386_TLS_TPOFF32	sH3
+ [0-9a-f]+:	89 c0[ 	]+mov    %eax,%eax
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+#  GD -> IE against hidden but not local variable referenced through
+ [0-9a-f]+:	8b 83 e0 ff ff ff[ 	]+mov    0xffffffe0\(%ebx\),%eax
+#				->R_386_TLS_TPOFF32	sH4
+ [0-9a-f]+:	89 c0[ 	]+mov    %eax,%eax
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+#  LD
+ [0-9a-f]+:	8d 83 1c 00 00 00[ 	]+lea    0x1c\(%ebx\),%eax
+#				->R_386_TLS_DESC	_TLS_MODULE_BASE_
+ [0-9a-f]+:	ff 10[ 	]+call   \*\(%eax\)
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	8d 90 20 00 00 00[ 	]+lea    0x20\(%eax\),%edx
+#							sl1
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	8d 88 26 00 00 00[ 	]+lea    0x26\(%eax\),%ecx
+#							sl2+2
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+#  LD against hidden and local variables
+ [0-9a-f]+:	8d 90 40 00 00 00[ 	]+lea    0x40\(%eax\),%edx
+#							sh1
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	8d 88 47 00 00 00[ 	]+lea    0x47\(%eax\),%ecx
+#							sh2+3
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+#  LD against hidden but not local variables
+ [0-9a-f]+:	8d 90 60 00 00 00[ 	]+lea    0x60\(%eax\),%edx
+#							sH1
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	8d 88 65 00 00 00[ 	]+lea    0x65\(%eax\),%ecx
+#							sH2+1
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+#  @gottpoff IE against global var
+ [0-9a-f]+:	65 8b 0d 00 00 00 00[ 	]+mov    %gs:0x0,%ecx
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	2b 8b f8 ff ff ff[ 	]+sub    0xfffffff8\(%ebx\),%ecx
+#				->R_386_TLS_TPOFF32	sg2
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+#  @gottpoff IE against global var
+ [0-9a-f]+:	65 a1 00 00 00 00[ 	]+mov    %gs:0x0,%eax
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	2b 83 d0 ff ff ff[ 	]+sub    0xffffffd0\(%ebx\),%eax
+#				->R_386_TLS_TPOFF32	sg4
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+#  @gotntpoff IE against global var
+ [0-9a-f]+:	65 8b 0d 00 00 00 00[ 	]+mov    %gs:0x0,%ecx
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	03 8b c4 ff ff ff[ 	]+add    0xffffffc4\(%ebx\),%ecx
+#				->R_386_TLS_TPOFF	sg3
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+#  @gotntpoff IE against global var
+ [0-9a-f]+:	65 a1 00 00 00 00[ 	]+mov    %gs:0x0,%eax
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	03 83 d4 ff ff ff[ 	]+add    0xffffffd4\(%ebx\),%eax
+#				->R_386_TLS_TPOFF	sg4
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+#  @gottpoff IE against local var
+ [0-9a-f]+:	65 8b 0d 00 00 00 00[ 	]+mov    %gs:0x0,%ecx
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	2b 8b b0 ff ff ff[ 	]+sub    0xffffffb0\(%ebx\),%ecx
+#				->R_386_TLS_TPOFF32	[0xdcffffff]
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+#  @gottpoff IE against local var
+ [0-9a-f]+:	65 a1 00 00 00 00[ 	]+mov    %gs:0x0,%eax
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	2b 83 b8 ff ff ff[ 	]+sub    0xffffffb8\(%ebx\),%eax
+#				->R_386_TLS_TPOFF32	[0xd4ffffff]
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+#  @gotntpoff IE against local var
+ [0-9a-f]+:	65 8b 0d 00 00 00 00[ 	]+mov    %gs:0x0,%ecx
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	03 8b b4 ff ff ff[ 	]+add    0xffffffb4\(%ebx\),%ecx
+#				->R_386_TLS_TPOFF	[0x28000000]
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+#  @gotntpoff IE against local var
+ [0-9a-f]+:	65 a1 00 00 00 00[ 	]+mov    %gs:0x0,%eax
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	03 83 bc ff ff ff[ 	]+add    0xffffffbc\(%ebx\),%eax
+#				->R_386_TLS_TPOFF	[0x2c000000]
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+#  @gottpoff IE against hidden and local var
+ [0-9a-f]+:	65 8b 0d 00 00 00 00[ 	]+mov    %gs:0x0,%ecx
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	2b 8b fc ff ff ff[ 	]+sub    0xfffffffc\(%ebx\),%ecx
+#				->R_386_TLS_TPOFF32	[0xbcffffff]
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+#  @gottpoff IE against hidden and local var
+ [0-9a-f]+:	65 a1 00 00 00 00[ 	]+mov    %gs:0x0,%eax
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	2b 83 e4 ff ff ff[ 	]+sub    0xffffffe4\(%ebx\),%eax
+#				->R_386_TLS_TPOFF32	[0xb4ffffff]
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+#  @gotntpoff IE against hidden and local var
+ [0-9a-f]+:	65 8b 0d 00 00 00 00[ 	]+mov    %gs:0x0,%ecx
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	03 8b c8 ff ff ff[ 	]+add    0xffffffc8\(%ebx\),%ecx
+#				->R_386_TLS_TPOFF	[0x48000000]
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+#  @gotntpoff IE against hidden and local var
+ [0-9a-f]+:	65 a1 00 00 00 00[ 	]+mov    %gs:0x0,%eax
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	03 83 e8 ff ff ff[ 	]+add    0xffffffe8\(%ebx\),%eax
+#				->R_386_TLS_TPOFF	[0x4c000000]
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+#  @gottpoff IE against hidden but not local var
+ [0-9a-f]+:	65 8b 0d 00 00 00 00[ 	]+mov    %gs:0x0,%ecx
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	2b 8b cc ff ff ff[ 	]+sub    0xffffffcc\(%ebx\),%ecx
+#				->R_386_TLS_TPOFF32	[0x9cffffff]
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+#  @gottpoff IE against hidden but not local var
+ [0-9a-f]+:	65 a1 00 00 00 00[ 	]+mov    %gs:0x0,%eax
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	2b 83 dc ff ff ff[ 	]+sub    0xffffffdc\(%ebx\),%eax
+#				->R_386_TLS_TPOFF32	[0x94ffffff]
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+#  @gotntpoff IE against hidden but not local var
+ [0-9a-f]+:	65 8b 0d 00 00 00 00[ 	]+mov    %gs:0x0,%ecx
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	03 8b ec ff ff ff[ 	]+add    0xffffffec\(%ebx\),%ecx
+#				->R_386_TLS_TPOFF	[0x68000000]
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+#  @gotntpoff IE against hidden but not local var
+ [0-9a-f]+:	65 a1 00 00 00 00[ 	]+mov    %gs:0x0,%eax
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	03 83 e0 ff ff ff[ 	]+add    0xffffffe0\(%ebx\),%eax
+#				->R_386_TLS_TPOFF	[0x6c000000]
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+#  Direct access through %gs
+#  @gotntpoff IE against global var
+ [0-9a-f]+:	8b 8b d8 ff ff ff[ 	]+mov    0xffffffd8\(%ebx\),%ecx
+#				->R_386_TLS_TPOFF	sg5
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	65 8b 11[ 	]+mov    %gs:\(%ecx\),%edx
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+#  @gotntpoff IE against local var
+ [0-9a-f]+:	8b 83 c0 ff ff ff[ 	]+mov    0xffffffc0\(%ebx\),%eax
+#				->R_386_TLS_TPOFF	[0x30000000]
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	65 8b 10[ 	]+mov    %gs:\(%eax\),%edx
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+#  @gotntpoff IE against hidden and local var
+ [0-9a-f]+:	8b 93 f0 ff ff ff[ 	]+mov    0xfffffff0\(%ebx\),%edx
+#				->R_386_TLS_TPOFF	[0x50000000]
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	65 8b 12[ 	]+mov    %gs:\(%edx\),%edx
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+#  @gotntpoff IE against hidden but not local var
+ [0-9a-f]+:	8b 8b f4 ff ff ff[ 	]+mov    0xfffffff4\(%ebx\),%ecx
+#				->R_386_TLS_TPOFF	[0x70000000]
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	65 8b 11[ 	]+mov    %gs:\(%ecx\),%edx
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	8b 5d fc[ 	]+mov    0xfffffffc\(%ebp\),%ebx
+ [0-9a-f]+:	c9[ 	]+leave *
+ [0-9a-f]+:	c3[ 	]+ret *
Index: ld/testsuite/ld-i386/tlsdesc.rd
===================================================================
RCS file: ld/testsuite/ld-i386/tlsdesc.rd
diff -N ld/testsuite/ld-i386/tlsdesc.rd
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ ld/testsuite/ld-i386/tlsdesc.rd 15 Sep 2005 22:39:23 -0000
@@ -0,0 +1,155 @@
+#source: tlsdesc.s
+#source: tlspic2.s
+#as: --32
+#ld: -shared -melf_i386
+#readelf: -Ssrl
+#target: i?86-*-*
+
+There are [0-9]+ section headers, starting at offset 0x.*:
+
+Section Headers:
+  \[Nr\] Name +Type +Addr +Off +Size +ES Flg Lk Inf Al
+  \[ 0\] +NULL +0+ 0+ 0+ 0+ +0 +0 +0
+  \[ 1\] \.hash +.*
+  \[ 2\] \.dynsym +.*
+  \[ 3\] \.dynstr +.*
+  \[ 4\] \.rel.dyn +.*
+  \[ 5\] \.rel.plt +.*
+  \[ 6\] \.text +.*
+  \[ 7\] \.tdata +PROGBITS +[0-9a-f]+ [0-9a-f]+ 000060 00 WAT  0   0  1
+  \[ 8\] \.tbss +NOBITS +[0-9aa-f]+ [0-9a-f]+ 000020 00 WAT  0   0  1
+  \[ 9\] \.dynamic +.*
+  \[10\] \.got +.*
+  \[11\] \.got.plt +.*
+  \[12\] \.shstrtab +.*
+  \[13\] \.symtab +.*
+  \[14\] \.strtab +.*
+Key to Flags:
+.*
+.*
+.*
+
+Elf file type is DYN \(Shared object file\)
+Entry point 0x[0-9a-f]+
+There are [0-9]+ program headers, starting at offset [0-9]+
+
+Program Headers:
+  Type +Offset +VirtAddr +PhysAddr +FileSiz +MemSiz +Flg Align
+  LOAD.*
+  LOAD.*
+  DYNAMIC.*
+  TLS +0x[0-9a-f]+ 0x[0-9a-f]+ 0x[0-9a-f]+ 0x0+60 0x0+80 R +0x1
+
+ Section to Segment mapping:
+  Segment Sections...
+   00 +.hash .dynsym .dynstr .rel.dyn .rel.plt .text *
+   01 +.tdata .dynamic .got .got.plt *
+   02 +.dynamic *
+   03 +.tdata .tbss *
+
+Relocation section '.rel.dyn' at offset 0x[0-9a-f]+ contains 20 entries:
+ Offset +Info +Type +Sym.Value +Sym. Name
+[0-9a-f]+ +0+25 R_386_TLS_TPOFF32
+[0-9a-f]+ +0+0e R_386_TLS_TPOFF *
+[0-9a-f]+ +0+25 R_386_TLS_TPOFF32
+[0-9a-f]+ +0+0e R_386_TLS_TPOFF *
+[0-9a-f]+ +0+0e R_386_TLS_TPOFF *
+[0-9a-f]+ +0+0e R_386_TLS_TPOFF *
+[0-9a-f]+ +0+25 R_386_TLS_TPOFF32
+[0-9a-f]+ +0+25 R_386_TLS_TPOFF32
+[0-9a-f]+ +0+0e R_386_TLS_TPOFF *
+[0-9a-f]+ +0+25 R_386_TLS_TPOFF32
+[0-9a-f]+ +0+0e R_386_TLS_TPOFF *
+[0-9a-f]+ +0+0e R_386_TLS_TPOFF *
+[0-9a-f]+ +0+0e R_386_TLS_TPOFF *
+[0-9a-f]+ +0+0e R_386_TLS_TPOFF *
+[0-9a-f]+ +0+25 R_386_TLS_TPOFF32
+[0-9a-f]+ +0+50e R_386_TLS_TPOFF   0+8   sg3
+[0-9a-f]+ +0+625 R_386_TLS_TPOFF32 0+c   sg4
+[0-9a-f]+ +0+60e R_386_TLS_TPOFF   0+c   sg4
+[0-9a-f]+ +0+70e R_386_TLS_TPOFF   0+10   sg5
+[0-9a-f]+ +0+b25 R_386_TLS_TPOFF32 0+4   sg2
+
+Relocation section '.rel.plt' at offset 0x[0-9a-f]+ contains 5 entries:
+ Offset     Info    Type            Sym.Value  Sym. Name
+[0-9a-f]+ +0+827 R_386_TLS_DESC * 0+   sg1
+[0-9a-f]+ +0+27 R_386_TLS_DESC *
+[0-9a-f]+ +0+27 R_386_TLS_DESC *
+[0-9a-f]+ +0+27 R_386_TLS_DESC *
+[0-9a-f]+ +0+27 R_386_TLS_DESC *
+
+Symbol table '.dynsym' contains 16 entries:
+ +Num: + Value  Size Type + Bind +Vis +Ndx Name
+ +[0-9]+: 0+ +0 NOTYPE  LOCAL  DEFAULT  UND *
+ +[0-9]+: [0-9a-f]+ +0 SECTION LOCAL  DEFAULT +6 *
+ +[0-9]+: [0-9a-f]+ +0 SECTION LOCAL  DEFAULT +7 *
+ +[0-9]+: [0-9a-f]+ +0 SECTION LOCAL  DEFAULT +8 *
+ +[0-9]+: 0+1c +0 TLS +GLOBAL DEFAULT +7 sg8
+ +[0-9]+: 0+8 +0 TLS +GLOBAL DEFAULT +7 sg3
+ +[0-9]+: 0+c +0 TLS +GLOBAL DEFAULT +7 sg4
+ +[0-9]+: 0+10 +0 TLS +GLOBAL DEFAULT +7 sg5
+ +[0-9]+: 0+ +0 TLS +GLOBAL DEFAULT +7 sg1
+ +[0-9]+: [0-9a-f]+ +0 FUNC +GLOBAL DEFAULT +6 fn1
+ +[0-9]+: [0-9a-f]+ +0 NOTYPE  GLOBAL DEFAULT  ABS __bss_start
+ +[0-9]+: 0+4 +0 TLS +GLOBAL DEFAULT +7 sg2
+ +[0-9]+: 0+14 +0 TLS +GLOBAL DEFAULT +7 sg6
+ +[0-9]+: 0+18 +0 TLS +GLOBAL DEFAULT +7 sg7
+ +[0-9]+: [0-9a-f]+ +0 NOTYPE  GLOBAL DEFAULT  ABS _edata
+ +[0-9]+: [0-9a-f]+ +0 NOTYPE  GLOBAL DEFAULT  ABS _end
+
+Symbol table '.symtab' contains 54 entries:
+ +Num: +Value  Size Type +Bind +Vis +Ndx Name
+ +[0-9]+: 0+ +0 NOTYPE  LOCAL  DEFAULT  UND *
+ +[0-9]+: [0-9a-f]+ +0 SECTION LOCAL  DEFAULT +1 *
+ +[0-9]+: [0-9a-f]+ +0 SECTION LOCAL  DEFAULT +2 *
+ +[0-9]+: [0-9a-f]+ +0 SECTION LOCAL  DEFAULT +3 *
+ +[0-9]+: [0-9a-f]+ +0 SECTION LOCAL  DEFAULT +4 *
+ +[0-9]+: [0-9a-f]+ +0 SECTION LOCAL  DEFAULT +5 *
+ +[0-9]+: [0-9a-f]+ +0 SECTION LOCAL  DEFAULT +6 *
+ +[0-9]+: [0-9a-f]+ +0 SECTION LOCAL  DEFAULT +7 *
+ +[0-9]+: [0-9a-f]+ +0 SECTION LOCAL  DEFAULT +8 *
+ +[0-9]+: [0-9a-f]+ +0 SECTION LOCAL  DEFAULT +9 *
+ +[0-9]+: [0-9a-f]+ +0 SECTION LOCAL  DEFAULT +10 *
+ +[0-9]+: [0-9a-f]+ +0 SECTION LOCAL  DEFAULT +11 *
+ +[0-9]+: [0-9a-f]+ +0 SECTION LOCAL  DEFAULT +12 *
+ +[0-9]+: [0-9a-f]+ +0 SECTION LOCAL  DEFAULT +13 *
+ +[0-9]+: [0-9a-f]+ +0 SECTION LOCAL  DEFAULT +14 *
+ +[0-9]+: 0+20 +0 TLS +LOCAL  DEFAULT +7 sl1
+ +[0-9]+: 0+24 +0 TLS +LOCAL  DEFAULT +7 sl2
+ +[0-9]+: 0+28 +0 TLS +LOCAL  DEFAULT +7 sl3
+ +[0-9]+: 0+2c +0 TLS +LOCAL  DEFAULT +7 sl4
+ +[0-9]+: 0+30 +0 TLS +LOCAL  DEFAULT +7 sl5
+ +[0-9]+: 0+34 +0 TLS +LOCAL  DEFAULT +7 sl6
+ +[0-9]+: 0+38 +0 TLS +LOCAL  DEFAULT +7 sl7
+ +[0-9]+: 0+3c +0 TLS +LOCAL  DEFAULT +7 sl8
+ +[0-9]+: 0+60 +0 TLS +LOCAL  HIDDEN +8 sH1
+ +[0-9]+: 0+ +0 TLS +LOCAL  HIDDEN +7 _TLS_MODULE_BASE_
+ +[0-9]+: [0-9a-f]+ +0 OBJECT  LOCAL  HIDDEN  ABS _DYNAMIC
+ +[0-9]+: 0+48 +0 TLS +LOCAL  HIDDEN +7 sh3
+ +[0-9]+: 0+64 +0 TLS +LOCAL  HIDDEN +8 sH2
+ +[0-9]+: 0+78 +0 TLS +LOCAL  HIDDEN +8 sH7
+ +[0-9]+: 0+58 +0 TLS +LOCAL  HIDDEN +7 sh7
+ +[0-9]+: 0+5c +0 TLS +LOCAL  HIDDEN +7 sh8
+ +[0-9]+: 0+6c +0 TLS +LOCAL  HIDDEN +8 sH4
+ +[0-9]+: 0+4c +0 TLS +LOCAL  HIDDEN +7 sh4
+ +[0-9]+: 0+68 +0 TLS +LOCAL  HIDDEN +8 sH3
+ +[0-9]+: 0+50 +0 TLS +LOCAL  HIDDEN +7 sh5
+ +[0-9]+: 0+70 +0 TLS +LOCAL  HIDDEN +8 sH5
+ +[0-9]+: 0+74 +0 TLS +LOCAL  HIDDEN +8 sH6
+ +[0-9]+: 0+7c +0 TLS +LOCAL  HIDDEN +8 sH8
+ +[0-9]+: 0+40 +0 TLS +LOCAL  HIDDEN +7 sh1
+ +[0-9]+: [0-9a-f]+ +0 OBJECT  LOCAL  HIDDEN  ABS _GLOBAL_OFFSET_TABLE_
+ +[0-9]+: 0+44 +0 TLS +LOCAL  HIDDEN +7 sh2
+ +[0-9]+: 0+54 +0 TLS +LOCAL  HIDDEN +7 sh6
+ +[0-9]+: 0+1c +0 TLS +GLOBAL DEFAULT +7 sg8
+ +[0-9]+: 0+8 +0 TLS +GLOBAL DEFAULT +7 sg3
+ +[0-9]+: 0+c +0 TLS +GLOBAL DEFAULT +7 sg4
+ +[0-9]+: 0+10 +0 TLS +GLOBAL DEFAULT +7 sg5
+ +[0-9]+: 0+ +0 TLS +GLOBAL DEFAULT +7 sg1
+ +[0-9]+: [0-9a-f]+ +0 FUNC +GLOBAL DEFAULT +6 fn1
+ +[0-9]+: [0-9a-f]+ +0 NOTYPE  GLOBAL DEFAULT  ABS __bss_start
+ +[0-9]+: 0+4 +0 TLS +GLOBAL DEFAULT +7 sg2
+ +[0-9]+: 0+14 +0 TLS +GLOBAL DEFAULT +7 sg6
+ +[0-9]+: 0+18 +0 TLS +GLOBAL DEFAULT +7 sg7
+ +[0-9]+: [0-9a-f]+ +0 NOTYPE  GLOBAL DEFAULT  ABS _edata
+ +[0-9]+: [0-9a-f]+ +0 NOTYPE  GLOBAL DEFAULT  ABS _end
Index: ld/testsuite/ld-i386/tlsdesc.s
===================================================================
RCS file: ld/testsuite/ld-i386/tlsdesc.s
diff -N ld/testsuite/ld-i386/tlsdesc.s
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ ld/testsuite/ld-i386/tlsdesc.s 15 Sep 2005 22:39:24 -0000
@@ -0,0 +1,276 @@
+	.section ".tdata", "awT", @progbits
+	.globl sg1, sg2, sg3, sg4, sg5, sg6, sg7, sg8
+	.globl sh1, sh2, sh3, sh4, sh5, sh6, sh7, sh8
+	.hidden sh1, sh2, sh3, sh4, sh5, sh6, sh7, sh8
+sg1:	.long 17
+sg2:	.long 18
+sg3:	.long 19
+sg4:	.long 20
+sg5:	.long 21
+sg6:	.long 22
+sg7:	.long 23
+sg8:	.long 24
+sl1:	.long 65
+sl2:	.long 66
+sl3:	.long 67
+sl4:	.long 68
+sl5:	.long 69
+sl6:	.long 70
+sl7:	.long 71
+sl8:	.long 72
+sh1:	.long 257
+sh2:	.long 258
+sh3:	.long 259
+sh4:	.long 260
+sh5:	.long 261
+sh6:	.long 262
+sh7:	.long 263
+sh8:	.long 264
+	.text
+	.globl	fn1
+	.type	fn1,@function
+fn1:
+	pushl	%ebp
+	movl	%esp, %ebp
+	pushl	%ebx
+	pushl	%eax
+	call	1f
+1:	popl	%ebx
+	addl	$_GLOBAL_OFFSET_TABLE_+[.-1b], %ebx
+	nop;nop;nop;nop
+
+	/* GD */
+	leal	sg1@tlsdesc(%ebx), %eax
+	call	*sg1@tlscall(%eax)
+	nop;nop;nop;nop
+
+	/* GD -> IE because variable is referenced through @gottpoff too */
+	leal	sg2@tlsdesc(%ebx), %eax
+	call	*sg2@tlscall(%eax)
+	nop;nop;nop;nop
+
+	/* GD -> IE because variable is referenced through @gotntpoff too */
+	leal	sg3@tlsdesc(%ebx), %eax
+	call	*sg3@tlscall(%eax)
+	nop;nop;nop;nop
+
+	/* GD -> IE because variable is referenced through @gottpoff and
+	   @gotntpoff too */
+	leal	sg4@tlsdesc(%ebx), %eax
+	call	*sg4@tlscall(%eax)
+	nop;nop;nop;nop
+
+	/* GD against local variable */
+	leal	sl1@tlsdesc(%ebx), %eax
+	call	*sl1@tlscall(%eax)
+	nop;nop;nop;nop
+
+	/* GD -> IE against local variable referenced through @gottpoff too */
+	leal	sl2@tlsdesc(%ebx), %eax
+	call	*sl2@tlscall(%eax)
+	nop;nop;nop;nop
+
+	/* GD -> IE against local variable referenced through @gotntpoff
+	   too */
+	leal	sl3@tlsdesc(%ebx), %eax
+	call	*sl3@tlscall(%eax)
+	nop;nop;nop;nop
+
+	/* GD -> IE against local variable referenced through @gottpoff and
+	   @gotntpoff too */
+	leal	sl4@tlsdesc(%ebx), %eax
+	call	*sl4@tlscall(%eax)
+	nop;nop;nop;nop
+
+	/* GD against hidden and local variable */
+	leal	sh1@tlsdesc(%ebx), %eax
+	call	*sh1@tlscall(%eax)
+	nop;nop;nop;nop
+
+	/* GD -> IE against hidden and local variable referenced through
+	   @gottpoff too */
+	leal	sh2@tlsdesc(%ebx), %eax
+	call	*sh2@tlscall(%eax)
+	nop;nop;nop;nop
+
+	/* GD -> IE against hidden and local variable referenced through
+	   @gotntpoff too */
+	leal	sh3@tlsdesc(%ebx), %eax
+	call	*sh3@tlscall(%eax)
+	nop;nop;nop;nop
+
+	/* GD -> IE against hidden and local variable referenced through
+	   @gottpoff and @gotntpoff too */
+	leal	sh4@tlsdesc(%ebx), %eax
+	call	*sh4@tlscall(%eax)
+	nop;nop;nop;nop
+
+	/* GD against hidden but not local variable */
+	leal	sH1@tlsdesc(%ebx), %eax
+	call	*sH1@tlscall(%eax)
+	nop;nop;nop;nop
+
+	/* GD -> IE against hidden but not local variable referenced through
+	   @gottpoff too */
+	leal	sH2@tlsdesc(%ebx), %eax
+	call	*sH2@tlscall(%eax)
+	nop;nop;nop;nop
+
+	/* GD -> IE against hidden but not local variable referenced through
+	   @gotntpoff too */
+	leal	sH3@tlsdesc(%ebx), %eax
+	call	*sH3@tlscall(%eax)
+	nop;nop;nop;nop
+
+	/* GD -> IE against hidden but not local variable referenced through
+	   @gottpoff and @gotntpoff too */
+	leal	sH4@tlsdesc(%ebx), %eax
+	call	*sH4@tlscall(%eax)
+	nop;nop;nop;nop
+
+	/* LD */
+	leal	_TLS_MODULE_BASE_@tlsdesc(%ebx), %eax
+	call	*_TLS_MODULE_BASE_@tlscall(%eax)
+	nop;nop
+	leal	sl1@dtpoff(%eax), %edx
+	nop;nop
+	leal	2+sl2@dtpoff(%eax), %ecx
+	nop;nop;nop;nop
+
+	/* LD against hidden and local variables */
+	leal	sh1@dtpoff(%eax), %edx
+	nop;nop
+	leal	sh2@dtpoff+3(%eax), %ecx
+	nop;nop;nop;nop
+
+	/* LD against hidden but not local variables */
+	leal	sH1@dtpoff(%eax), %edx
+	nop;nop
+	leal	sH2@dtpoff+1(%eax), %ecx
+	nop;nop
+
+	/* @gottpoff IE against global var  */
+	movl	%gs:0, %ecx
+	nop;nop
+	subl	sg2@gottpoff(%ebx), %ecx
+	nop;nop;nop;nop
+
+	/* @gottpoff IE against global var  */
+	movl	%gs:0, %eax
+	nop;nop
+	subl	sg4@gottpoff(%ebx), %eax
+	nop;nop;nop;nop
+
+	/* @gotntpoff IE against global var  */
+	movl	%gs:0, %ecx
+	nop;nop
+	addl	sg3@gotntpoff(%ebx), %ecx
+	nop;nop;nop;nop
+
+	/* @gotntpoff IE against global var  */
+	movl	%gs:0, %eax
+	nop;nop
+	addl	sg4@gotntpoff(%ebx), %eax
+	nop;nop;nop;nop
+
+	/* @gottpoff IE against local var  */
+	movl	%gs:0, %ecx
+	nop;nop
+	subl	sl2@gottpoff(%ebx), %ecx
+	nop;nop;nop;nop
+
+	/* @gottpoff IE against local var  */
+	movl	%gs:0, %eax
+	nop;nop
+	subl	sl4@gottpoff(%ebx), %eax
+	nop;nop;nop;nop
+
+	/* @gotntpoff IE against local var  */
+	movl	%gs:0, %ecx
+	nop;nop
+	addl	sl3@gotntpoff(%ebx), %ecx
+	nop;nop;nop;nop
+
+	/* @gotntpoff IE against local var  */
+	movl	%gs:0, %eax
+	nop;nop
+	addl	sl4@gotntpoff(%ebx), %eax
+	nop;nop;nop;nop
+
+	/* @gottpoff IE against hidden and local var  */
+	movl	%gs:0, %ecx
+	nop;nop
+	subl	sh2@gottpoff(%ebx), %ecx
+	nop;nop;nop;nop
+
+	/* @gottpoff IE against hidden and local var  */
+	movl	%gs:0, %eax
+	nop;nop
+	subl	sh4@gottpoff(%ebx), %eax
+	nop;nop;nop;nop
+
+	/* @gotntpoff IE against hidden and local var  */
+	movl	%gs:0, %ecx
+	nop;nop
+	addl	sh3@gotntpoff(%ebx), %ecx
+	nop;nop;nop;nop
+
+	/* @gotntpoff IE against hidden and local var  */
+	movl	%gs:0, %eax
+	nop;nop
+	addl	sh4@gotntpoff(%ebx), %eax
+	nop;nop;nop;nop
+
+	/* @gottpoff IE against hidden but not local var  */
+	movl	%gs:0, %ecx
+	nop;nop
+	subl	sH2@gottpoff(%ebx), %ecx
+	nop;nop;nop;nop
+
+	/* @gottpoff IE against hidden but not local var  */
+	movl	%gs:0, %eax
+	nop;nop
+	subl	sH4@gottpoff(%ebx), %eax
+	nop;nop;nop;nop
+
+	/* @gotntpoff IE against hidden but not local var  */
+	movl	%gs:0, %ecx
+	nop;nop
+	addl	sH3@gotntpoff(%ebx), %ecx
+	nop;nop;nop;nop
+
+	/* @gotntpoff IE against hidden but not local var  */
+	movl	%gs:0, %eax
+	nop;nop
+	addl	sH4@gotntpoff(%ebx), %eax
+	nop;nop;nop;nop
+
+	/* Direct access through %gs  */
+
+	/* @gotntpoff IE against global var  */
+	movl	sg5@gotntpoff(%ebx), %ecx
+	nop;nop
+	movl	%gs:(%ecx), %edx
+	nop;nop;nop;nop
+
+	/* @gotntpoff IE against local var  */
+	movl	sl5@gotntpoff(%ebx), %eax
+	nop;nop
+	movl	%gs:(%eax), %edx
+	nop;nop;nop;nop
+
+	/* @gotntpoff IE against hidden and local var  */
+	movl	sh5@gotntpoff(%ebx), %edx
+	nop;nop
+	movl	%gs:(%edx), %edx
+	nop;nop;nop;nop
+
+	/* @gotntpoff IE against hidden but not local var  */
+	movl	sH5@gotntpoff(%ebx), %ecx
+	nop;nop
+	movl	%gs:(%ecx), %edx
+	nop;nop;nop;nop
+
+	movl    -4(%ebp), %ebx
+	leave
+	ret
Index: ld/testsuite/ld-i386/tlsdesc.sd
===================================================================
RCS file: ld/testsuite/ld-i386/tlsdesc.sd
diff -N ld/testsuite/ld-i386/tlsdesc.sd
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ ld/testsuite/ld-i386/tlsdesc.sd 15 Sep 2005 22:39:24 -0000
@@ -0,0 +1,20 @@
+#source: tlsdesc.s
+#source: tlspic2.s
+#as: --32
+#ld: -shared -melf_i386
+#objdump: -s -j.got -j.got.plt
+#target: i?86-*-*
+
+.*:     file format elf32-i386
+
+Contents of section \.got:
+ [0-9a-f]+ dcffffff 28000000 d4ffffff 2c000000  .*
+ [0-9a-f]+ 30000000 00000000 48000000 9cffffff  .*
+ [0-9a-f]+ 00000000 00000000 00000000 94ffffff  .*
+ [0-9a-f]+ 6c000000 b4ffffff 4c000000 68000000  .*
+ [0-9a-f]+ 50000000 70000000 00000000 bcffffff  .*
+Contents of section \.got\.plt:
+ [0-9a-f]+ ec150000 00000000 00000000 00000000  .*
+ [0-9a-f]+ 20000000 00000000 60000000 00000000  .*
+ [0-9a-f]+ 00000000 00000000 00000000 00000000  .*
+ [0-9a-f]+ 40000000 +.*
Index: ld/testsuite/ld-i386/tlsdesc.td
===================================================================
RCS file: ld/testsuite/ld-i386/tlsdesc.td
diff -N ld/testsuite/ld-i386/tlsdesc.td
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ ld/testsuite/ld-i386/tlsdesc.td 15 Sep 2005 22:39:24 -0000
@@ -0,0 +1,16 @@
+#source: tlsdesc.s
+#source: tlspic2.s
+#as: --32
+#ld: -shared -melf_i386
+#objdump: -sj.tdata
+#target: i?86-*-*
+
+.*:     file format elf32-i386
+
+Contents of section \.tdata:
+ [0-9a-f]+ 11000000 12000000 13000000 14000000  .*
+ [0-9a-f]+ 15000000 16000000 17000000 18000000  .*
+ [0-9a-f]+ 41000000 42000000 43000000 44000000  .*
+ [0-9a-f]+ 45000000 46000000 47000000 48000000  .*
+ [0-9a-f]+ 01010000 02010000 03010000 04010000  .*
+ [0-9a-f]+ 05010000 06010000 07010000 08010000  .*
Index: ld/testsuite/ld-i386/tlsgdesc.dd
===================================================================
RCS file: ld/testsuite/ld-i386/tlsgdesc.dd
diff -N ld/testsuite/ld-i386/tlsgdesc.dd
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ ld/testsuite/ld-i386/tlsgdesc.dd 15 Sep 2005 22:39:24 -0000
@@ -0,0 +1,156 @@
+#source: tlsgdesc.s
+#as: --32
+#ld: -shared -melf_i386
+#objdump: -drj.text
+#target: i?86-*-*
+
+.*: +file format elf32-i386
+
+Disassembly of section .text:
+
+[0-9a-f]+ <fc1>:
+ [0-9a-f]+:	55[ 	]+push   %ebp
+ [0-9a-f]+:	89 e5[ 	]+mov    %esp,%ebp
+ [0-9a-f]+:	53[ 	]+push   %ebx
+ [0-9a-f]+:	50[ 	]+push   %eax
+ [0-9a-f]+:	e8 00 00 00 00[ 	]+call   [0-9a-f]+ <.*>
+ [0-9a-f]+:	5b[ 	]+pop    %ebx
+ [0-9a-f]+:	81 c3 be 11 00 00[ 	]+add    \$0x[0-9a-f]+,%ebx
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+#  @gottpoff IE against global var
+ [0-9a-f]+:	65 8b 0d 00 00 00 00[ 	]+mov    %gs:0x0,%ecx
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	2b 8b e0 ff ff ff[ 	]+sub    0xffffffe0\(%ebx\),%ecx
+#				->R_386_TLS_TPOFF32	sG3
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+#  @gotntpoff IE against global var
+ [0-9a-f]+:	65 8b 0d 00 00 00 00[ 	]+mov    %gs:0x0,%ecx
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	03 8b f0 ff ff ff[ 	]+add    0xfffffff0\(%ebx\),%ecx
+#				->R_386_TLS_TPOFF	sG4
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+#  GD
+ [0-9a-f]+:	8d 04 1d f8 ff ff ff[ 	]+lea    0xfffffff8\(,%ebx,1\),%eax
+#				->R_386_TLS_DTPMOD32	sG1
+ [0-9a-f]+:	e8 a9 ff ff ff[ 	]+call   [0-9a-f]+ <___tls_get_addr@plt>
+#				->R_386_JUMP_SLOT	___tls_get_addr
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	8d 83 18 00 00 00[ 	]+lea    0x18\(%ebx\),%eax
+#				->R_386_TLS_DESC	sG1
+ [0-9a-f]+:	ff 10[ 	]+call   \*\(%eax\)
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	8d 83 10 00 00 00[ 	]+lea    0x10\(%ebx\),%eax
+#				->R_386_TLS_DESC	sG2
+ [0-9a-f]+:	ff 10[ 	]+call   \*\(%eax\)
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	8d 04 1d e8 ff ff ff[ 	]+lea    0xffffffe8\(,%ebx,1\),%eax
+#				->R_386_TLS_DTPMOD32	sG2
+ [0-9a-f]+:	e8 81 ff ff ff[ 	]+call   [0-9a-f]+ <___tls_get_addr@plt>
+#				->R_386_JUMP_SLOT	___tls_get_addr
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+#  GD -> IE because variable is referenced through @gottpoff too
+ [0-9a-f]+:	65 a1 00 00 00 00[ 	]+mov    %gs:0x0,%eax
+ [0-9a-f]+:	2b 83 e0 ff ff ff[ 	]+sub    0xffffffe0\(%ebx\),%eax
+#				->R_386_TLS_TPOFF32	sG3
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	8b 83 e0 ff ff ff[ 	]+mov    0xffffffe0\(%ebx\),%eax
+#				->R_386_TLS_TPOFF32	sG3
+ [0-9a-f]+:	f7 d8[ 	]+neg    %eax
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+#  GD -> IE because variable is referenced through @gotntpoff too
+ [0-9a-f]+:	8b 83 f0 ff ff ff[ 	]+mov    0xfffffff0\(%ebx\),%eax
+#				->R_386_TLS_TPOFF	sG4
+ [0-9a-f]+:	89 c0[ 	]+mov    %eax,%eax
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	65 a1 00 00 00 00[ 	]+mov    %gs:0x0,%eax
+ [0-9a-f]+:	03 83 f0 ff ff ff[ 	]+add    0xfffffff0\(%ebx\),%eax
+#				->R_386_TLS_TPOFF	sG4
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+#  GD -> IE because variable is referenced through @gotntpoff too
+ [0-9a-f]+:	65 a1 00 00 00 00[ 	]+mov    %gs:0x0,%eax
+ [0-9a-f]+:	03 83 e4 ff ff ff[ 	]+add    0xffffffe4\(%ebx\),%eax
+#				->R_386_TLS_TPOFF	sG5
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	8b 83 e4 ff ff ff[ 	]+mov    0xffffffe4\(%ebx\),%eax
+#				->R_386_TLS_TPOFF	sG5
+ [0-9a-f]+:	89 c0[ 	]+mov    %eax,%eax
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+#  GD -> IE because variable is referenced through @gottpoff too
+ [0-9a-f]+:	8b 83 f4 ff ff ff[ 	]+mov    0xfffffff4\(%ebx\),%eax
+#				->R_386_TLS_TPOFF32	sG6
+ [0-9a-f]+:	f7 d8[ 	]+neg    %eax
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	65 a1 00 00 00 00[ 	]+mov    %gs:0x0,%eax
+ [0-9a-f]+:	2b 83 f4 ff ff ff[ 	]+sub    0xfffffff4\(%ebx\),%eax
+#				->R_386_TLS_TPOFF32	sG6
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+#  @gotntpoff IE against global var
+ [0-9a-f]+:	65 8b 0d 00 00 00 00[ 	]+mov    %gs:0x0,%ecx
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	03 8b e4 ff ff ff[ 	]+add    0xffffffe4\(%ebx\),%ecx
+#				->R_386_TLS_TPOFF	sG5
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+#  @gottpoff IE against global var
+ [0-9a-f]+:	65 8b 0d 00 00 00 00[ 	]+mov    %gs:0x0,%ecx
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	2b 8b f4 ff ff ff[ 	]+sub    0xfffffff4\(%ebx\),%ecx
+#				->R_386_TLS_TPOFF32	sG6
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	8b 5d fc[ 	]+mov    0xfffffffc\(%ebp\),%ebx
+ [0-9a-f]+:	c9[ 	]+leave *
+ [0-9a-f]+:	c3[ 	]+ret *
Index: ld/testsuite/ld-i386/tlsgdesc.rd
===================================================================
RCS file: ld/testsuite/ld-i386/tlsgdesc.rd
diff -N ld/testsuite/ld-i386/tlsgdesc.rd
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ ld/testsuite/ld-i386/tlsgdesc.rd 15 Sep 2005 22:39:24 -0000
@@ -0,0 +1,107 @@
+#source: tlsgdesc.s
+#as: --32
+#ld: -shared -melf_i386
+#readelf: -Ssrl
+#target: i?86-*-*
+
+There are [0-9]+ section headers, starting at offset 0x.*:
+
+Section Headers:
+  \[Nr\] Name +Type +Addr +Off +Size +ES Flg Lk Inf Al
+  \[ 0\] +NULL +0+ 0+ 0+ 0+ +0 +0 +0
+  \[ 1\] \.hash +.*
+  \[ 2\] \.dynsym +.*
+  \[ 3\] \.dynstr +.*
+  \[ 4\] \.rel.dyn +.*
+  \[ 5\] \.rel.plt +.*
+  \[ 6\] \.plt +.*
+  \[ 7\] \.text +.*
+  \[ 8\] \.dynamic +.*
+  \[ 9\] \.got +.*
+  \[10\] \.got.plt +.*
+  \[11\] \.shstrtab +.*
+  \[12\] \.symtab +.*
+  \[13\] \.strtab +.*
+Key to Flags:
+.*
+.*
+.*
+
+Elf file type is DYN \(Shared object file\)
+Entry point 0x[0-9a-f]+
+There are [0-9]+ program headers, starting at offset [0-9]+
+
+Program Headers:
+  Type +Offset +VirtAddr +PhysAddr +FileSiz +MemSiz +Flg Align
+  LOAD.*
+  LOAD.*
+  DYNAMIC.*
+
+ Section to Segment mapping:
+  Segment Sections...
+   00 +.hash .dynsym .dynstr .rel.dyn .rel.plt .plt .text *
+   01 +.dynamic .got .got.plt *
+   02 +.dynamic *
+
+Relocation section '.rel.dyn' at offset 0x[0-9a-f]+ contains 8 entries:
+ Offset +Info +Type +Sym.Value +Sym. Name
+[0-9a-f]+ +0+225 R_386_TLS_TPOFF32 0+   sG3
+[0-9a-f]+ +0+30e R_386_TLS_TPOFF   0+   sG5
+[0-9a-f]+ +0+423 R_386_TLS_DTPMOD3 0+   sG2
+[0-9a-f]+ +0+424 R_386_TLS_DTPOFF3 0+   sG2
+[0-9a-f]+ +0+50e R_386_TLS_TPOFF   0+   sG4
+[0-9a-f]+ +0+725 R_386_TLS_TPOFF32 0+   sG6
+[0-9a-f]+ +0+923 R_386_TLS_DTPMOD3 0+   sG1
+[0-9a-f]+ +0+924 R_386_TLS_DTPOFF3 0+   sG1
+
+Relocation section '.rel.plt' at offset 0x[0-9a-f]+ contains 3 entries:
+ Offset     Info    Type            Sym.Value  Sym. Name
+[0-9a-f]+  0+c07 R_386_JUMP_SLOT   0+   ___tls_get_addr
+[0-9a-f]+  0+927 R_386_TLS_DESC    0+   sG1
+[0-9a-f]+  0+427 R_386_TLS_DESC    0+   sG2
+
+Symbol table '.dynsym' contains 13 entries:
+ +Num: + Value  Size Type + Bind +Vis +Ndx Name
+ +[0-9]+: 0+ +0 NOTYPE  LOCAL  DEFAULT  UND *
+ +[0-9]+: [0-9a-f]+ +0 SECTION LOCAL  DEFAULT +7 *
+ +[0-9]+: 0+ +0 TLS +GLOBAL DEFAULT  UND sG3
+ +[0-9]+: 0+ +0 TLS +GLOBAL DEFAULT  UND sG5
+ +[0-9]+: 0+ +0 TLS +GLOBAL DEFAULT  UND sG2
+ +[0-9]+: 0+ +0 TLS +GLOBAL DEFAULT  UND sG4
+ +[0-9]+: [0-9a-f]+ +0 NOTYPE  GLOBAL DEFAULT  ABS __bss_start
+ +[0-9]+: 0+ +0 TLS +GLOBAL DEFAULT  UND sG6
+ +[0-9]+: [0-9a-f]+ +0 FUNC +GLOBAL DEFAULT +7 fc1
+ +[0-9]+: 0+ +0 TLS +GLOBAL DEFAULT  UND sG1
+ +[0-9]+: [0-9a-f]+ +0 NOTYPE  GLOBAL DEFAULT  ABS _edata
+ +[0-9]+: [0-9a-f]+ +0 NOTYPE  GLOBAL DEFAULT  ABS _end
+ +[0-9]+: 0+ +0 NOTYPE  GLOBAL DEFAULT  UND ___tls_get_addr
+
+Symbol table '.symtab' contains 27 entries:
+ +Num: +Value  Size Type +Bind +Vis +Ndx Name
+ +[0-9]+: 0+ +0 NOTYPE  LOCAL  DEFAULT  UND *
+ +[0-9]+: [0-9a-f]+ +0 SECTION LOCAL  DEFAULT +1 *
+ +[0-9]+: [0-9a-f]+ +0 SECTION LOCAL  DEFAULT +2 *
+ +[0-9]+: [0-9a-f]+ +0 SECTION LOCAL  DEFAULT +3 *
+ +[0-9]+: [0-9a-f]+ +0 SECTION LOCAL  DEFAULT +4 *
+ +[0-9]+: [0-9a-f]+ +0 SECTION LOCAL  DEFAULT +5 *
+ +[0-9]+: [0-9a-f]+ +0 SECTION LOCAL  DEFAULT +6 *
+ +[0-9]+: [0-9a-f]+ +0 SECTION LOCAL  DEFAULT +7 *
+ +[0-9]+: [0-9a-f]+ +0 SECTION LOCAL  DEFAULT +8 *
+ +[0-9]+: [0-9a-f]+ +0 SECTION LOCAL  DEFAULT +9 *
+ +[0-9]+: [0-9a-f]+ +0 SECTION LOCAL  DEFAULT +10 *
+ +[0-9]+: [0-9a-f]+ +0 SECTION LOCAL  DEFAULT +11 *
+ +[0-9]+: [0-9a-f]+ +0 SECTION LOCAL  DEFAULT +12 *
+ +[0-9]+: [0-9a-f]+ +0 SECTION LOCAL  DEFAULT +13 *
+ +[0-9]+: [0-9a-f]+ +0 OBJECT  LOCAL  HIDDEN  ABS _DYNAMIC
+ +[0-9]+: [0-9a-f]+ +0 OBJECT  LOCAL  HIDDEN  ABS _GLOBAL_OFFSET_TABLE_
+ +[0-9]+: 0+ +0 TLS +GLOBAL DEFAULT  UND sG3
+ +[0-9]+: 0+ +0 TLS +GLOBAL DEFAULT  UND sG5
+ +[0-9]+: 0+ +0 TLS +GLOBAL DEFAULT  UND sG2
+ +[0-9]+: 0+ +0 TLS +GLOBAL DEFAULT  UND sG4
+ +[0-9]+: [0-9a-f]+ +0 NOTYPE  GLOBAL DEFAULT  ABS __bss_start
+ +[0-9]+: 0+ +0 TLS +GLOBAL DEFAULT  UND sG6
+ +[0-9]+: [0-9a-f]+ +0 FUNC +GLOBAL DEFAULT +7 fc1
+ +[0-9]+: 0+ +0 TLS +GLOBAL DEFAULT  UND sG1
+ +[0-9]+: [0-9a-f]+ +0 NOTYPE  GLOBAL DEFAULT  ABS _edata
+ +[0-9]+: [0-9a-f]+ +0 NOTYPE  GLOBAL DEFAULT  ABS _end
+ +[0-9]+: 0+ +0 NOTYPE  GLOBAL DEFAULT  UND ___tls_get_addr
Index: ld/testsuite/ld-i386/tlsgdesc.s
===================================================================
RCS file: ld/testsuite/ld-i386/tlsgdesc.s
diff -N ld/testsuite/ld-i386/tlsgdesc.s
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ ld/testsuite/ld-i386/tlsgdesc.s 15 Sep 2005 22:39:24 -0000
@@ -0,0 +1,100 @@
+	.text
+	.globl	fc1
+	.type	fc1,@function
+fc1:
+	pushl	%ebp
+	movl	%esp, %ebp
+	pushl	%ebx
+	pushl	%eax
+	call	1f
+1:	popl	%ebx
+	addl	$_GLOBAL_OFFSET_TABLE_+[.-1b], %ebx
+	nop;nop;nop;nop
+
+	/* @gottpoff IE against global var  */
+	movl	%gs:0, %ecx
+	nop;nop
+	subl	sG3@gottpoff(%ebx), %ecx
+	nop;nop;nop;nop
+
+	/* @gotntpoff IE against global var  */
+	movl	%gs:0, %ecx
+	nop;nop
+	addl	sG4@gotntpoff(%ebx), %ecx
+	nop;nop;nop;nop
+
+	/* GD */
+	leal	sG1@tlsgd(,%ebx,1), %eax
+	call	___tls_get_addr@plt
+	nop;nop;nop;nop
+
+	/* GD */
+	leal	sG1@tlsdesc(%ebx), %eax
+	call	*sG1@tlscall(%eax)
+	nop;nop;nop;nop
+
+	/* GD */
+	leal	sG2@tlsdesc(%ebx), %eax
+	call	*sG2@tlscall(%eax)
+	nop;nop;nop;nop
+
+	/* GD */
+	leal	sG2@tlsgd(,%ebx,1), %eax
+	call	___tls_get_addr@plt
+	nop;nop;nop;nop
+
+	/* GD -> IE tpoff */
+	leal	sG3@tlsgd(,%ebx,1), %eax
+	call	___tls_get_addr@plt
+	nop;nop;nop;nop
+
+	/* GD -> IE tpoff */
+	leal	sG3@tlsdesc(%ebx), %eax
+	call	*sG3@tlscall(%eax)
+	nop;nop;nop;nop
+
+	/* GD -> IE ntpoff */
+	leal	sG4@tlsdesc(%ebx), %eax
+	call	*sG4@tlscall(%eax)
+	nop;nop;nop;nop
+
+	/* GD -> IE ntpoff */
+	leal	sG4@tlsgd(,%ebx,1), %eax
+	call	___tls_get_addr@plt
+	nop;nop;nop;nop
+
+	/* GD -> IE ntpoff */
+	leal	sG5@tlsgd(,%ebx,1), %eax
+	call	___tls_get_addr@plt
+	nop;nop;nop;nop
+
+	/* GD -> IE ntpoff */
+	leal	sG5@tlsdesc(%ebx), %eax
+	call	*sG5@tlscall(%eax)
+	nop;nop;nop;nop
+
+	/* GD -> IE tpoff */
+	leal	sG6@tlsdesc(%ebx), %eax
+	call	*sG6@tlscall(%eax)
+	nop;nop;nop;nop
+
+	/* GD -> IE tpoff */
+	leal	sG6@tlsgd(,%ebx,1), %eax
+	call	___tls_get_addr@plt
+	nop;nop;nop;nop
+
+	/* @gotntpoff IE against global var  */
+	movl	%gs:0, %ecx
+	nop;nop
+	addl	sG5@gotntpoff(%ebx), %ecx
+	nop;nop;nop;nop
+
+	/* @gottpoff IE against global var  */
+	movl	%gs:0, %ecx
+	nop;nop
+	subl	sG6@gottpoff(%ebx), %ecx
+	nop;nop;nop;nop
+
+	movl    -4(%ebp), %ebx
+	leave
+	ret
Index: ld/testsuite/ld-x86-64/tlsbindesc.dd
===================================================================
RCS file: ld/testsuite/ld-x86-64/tlsbindesc.dd
diff -N ld/testsuite/ld-x86-64/tlsbindesc.dd
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ ld/testsuite/ld-x86-64/tlsbindesc.dd 15 Sep 2005 22:39:27 -0000
@@ -0,0 +1,301 @@
+#source: tlsbindesc.s
+#source: tlsbin.s
+#as: --64
+#ld: -shared -melf_x86_64
+#objdump: -drj.text
+#target: x86_64-*-*
+
+# PT_TLS layout is:
+# Offset from   Offset from     Name
+# TCB base      TCB end
+# 0x00          -0xa0           sg1..sg8
+# 0x20          -0x80           sl1..sl8
+# 0x40          -0x60           sh1..sh8
+# 0x60          -0x40           bg1..bg8
+# 0x80          -0x20           bl1..bl8
+
+.*: +file format elf64-x86-64
+
+Disassembly of section .text:
+
+0+401000 <fn2>:
+  [0-9a-f]+:	55[ 	]+push   %rbp
+  [0-9a-f]+:	48 89 e5[ 	]+mov    %rsp,%rbp
+#  GD -> IE because variable is not defined in executable
+  [0-9a-f]+:	48 8b 05 65 03 10 00[ 	]+mov    1049445\(%rip\),%rax +# 501370 <.*>
+#				-> R_X86_64_TPOFF64	sG1
+  [0-9a-f]+:	48 90[ 	]+rex64 nop *
+  [0-9a-f]+:	90[ 	]+nop *
+  [0-9a-f]+:	90[ 	]+nop *
+  [0-9a-f]+:	90[ 	]+nop *
+  [0-9a-f]+:	90[ 	]+nop *
+#  GD -> IE because variable is not defined in executable where
+#  the variable is referenced through IE too
+  [0-9a-f]+:	48 8b 05 48 03 10 00[ 	]+mov    1049416\(%rip\),%rax +# 501360 <.*>
+#				-> R_X86_64_TPOFF64	sG2
+  [0-9a-f]+:	48 90[ 	]+rex64 nop *
+  [0-9a-f]+:	90[ 	]+nop *
+  [0-9a-f]+:	90[ 	]+nop *
+  [0-9a-f]+:	90[ 	]+nop *
+  [0-9a-f]+:	90[ 	]+nop *
+#  GD -> LE with global variable defined in executable
+  [0-9a-f]+:	48 c7 c0 60 ff ff ff[ 	]+mov    \$0xf+60,%rax
+#							sg1
+  [0-9a-f]+:	48 90[ 	]+rex64 nop *
+  [0-9a-f]+:	90[ 	]+nop *
+  [0-9a-f]+:	90[ 	]+nop *
+  [0-9a-f]+:	90[ 	]+nop *
+  [0-9a-f]+:	90[ 	]+nop *
+#  GD -> LE with local variable defined in executable
+  [0-9a-f]+:	48 c7 c0 80 ff ff ff[ 	]+mov    \$0xf+80,%rax
+#							sl1
+  [0-9a-f]+:	48 90[ 	]+rex64 nop *
+  [0-9a-f]+:	90[ 	]+nop *
+  [0-9a-f]+:	90[ 	]+nop *
+  [0-9a-f]+:	90[ 	]+nop *
+  [0-9a-f]+:	90[ 	]+nop *
+#  GD -> LE with hidden variable defined in executable
+  [0-9a-f]+:	48 c7 c0 a0 ff ff ff[ 	]+mov    \$0xf+a0,%rax
+#							sh1
+  [0-9a-f]+:	48 90[ 	]+rex64 nop *
+  [0-9a-f]+:	90[ 	]+nop *
+  [0-9a-f]+:	90[ 	]+nop *
+  [0-9a-f]+:	90[ 	]+nop *
+  [0-9a-f]+:	90[ 	]+nop *
+#  LD -> LE
+  [0-9a-f]+:	48 c7 c0 60 ff ff ff[ 	]+mov    \$0xf+60,%rax
+  [0-9a-f]+:	48 90[ 	]+rex64 nop *
+  [0-9a-f]+:	90[ 	]+nop *
+  [0-9a-f]+:	90[ 	]+nop *
+  [0-9a-f]+:	48 8d 90 81 ff ff ff[ 	]+lea    0xf+81\(%rax\),%rdx
+#							sl1+1
+  [0-9a-f]+:	90[ 	]+nop *
+  [0-9a-f]+:	90[ 	]+nop *
+  [0-9a-f]+:	4c 8d 88 86 ff ff ff[ 	]+lea    0xf+86\(%rax\),%r9
+#							sl2+2
+  [0-9a-f]+:	90[ 	]+nop *
+  [0-9a-f]+:	90[ 	]+nop *
+  [0-9a-f]+:	90[ 	]+nop *
+  [0-9a-f]+:	90[ 	]+nop *
+#  LD -> LE against hidden variables
+  [0-9a-f]+:	48 8d 90 a0 ff ff ff[ 	]+lea    0xf+a0\(%rax\),%rdx
+#							sh1
+  [0-9a-f]+:	90[ 	]+nop *
+  [0-9a-f]+:	90[ 	]+nop *
+  [0-9a-f]+:	48 8d 88 a7 ff ff ff[ 	]+lea    0xf+a7\(%rax\),%rcx
+#							sh2+3
+  [0-9a-f]+:	90[ 	]+nop *
+  [0-9a-f]+:	90[ 	]+nop *
+  [0-9a-f]+:	90[ 	]+nop *
+  [0-9a-f]+:	90[ 	]+nop *
+#  IE against global var
+  [0-9a-f]+:	64 4c 8b 0c 25 00 00[ 	]+mov    %fs:0x0,%r9
+  [0-9a-f]+:	00 00 *
+  [0-9a-f]+:	90[ 	]+nop *
+  [0-9a-f]+:	90[ 	]+nop *
+  [0-9a-f]+:	4c 03 0d d6 02 10 00[ 	]+add    1049302\(%rip\),%r9 +# 501360 <.*>
+#				-> R_X86_64_TPOFF64	sG2
+  [0-9a-f]+:	90[ 	]+nop *
+  [0-9a-f]+:	90[ 	]+nop *
+  [0-9a-f]+:	90[ 	]+nop *
+  [0-9a-f]+:	90[ 	]+nop *
+#  IE -> LE against global var defined in exec
+  [0-9a-f]+:	64 4c 8b 14 25 00 00[ 	]+mov    %fs:0x0,%r10
+  [0-9a-f]+:	00 00 *
+  [0-9a-f]+:	90[ 	]+nop *
+  [0-9a-f]+:	90[ 	]+nop *
+  [0-9a-f]+:	4d 8d 92 60 ff ff ff[ 	]+lea    0xf+60\(%r10\),%r10
+#							sg1
+  [0-9a-f]+:	90[ 	]+nop *
+  [0-9a-f]+:	90[ 	]+nop *
+  [0-9a-f]+:	90[ 	]+nop *
+  [0-9a-f]+:	90[ 	]+nop *
+#  IE -> LE against local var
+  [0-9a-f]+:	64 48 8b 04 25 00 00[ 	]+mov    %fs:0x0,%rax
+  [0-9a-f]+:	00 00 *
+  [0-9a-f]+:	90[ 	]+nop *
+  [0-9a-f]+:	90[ 	]+nop *
+  [0-9a-f]+:	48 8d 80 80 ff ff ff[ 	]+lea    0xf+80\(%rax\),%rax
+#							sl1
+  [0-9a-f]+:	90[ 	]+nop *
+  [0-9a-f]+:	90[ 	]+nop *
+  [0-9a-f]+:	90[ 	]+nop *
+  [0-9a-f]+:	90[ 	]+nop *
+#  IE -> LE against hidden var
+  [0-9a-f]+:	64 48 8b 0c 25 00 00[ 	]+mov    %fs:0x0,%rcx
+  [0-9a-f]+:	00 00 *
+  [0-9a-f]+:	90[ 	]+nop *
+  [0-9a-f]+:	90[ 	]+nop *
+  [0-9a-f]+:	48 8d 89 a0 ff ff ff[ 	]+lea    0xf+a0\(%rcx\),%rcx
+#							sh1
+  [0-9a-f]+:	90[ 	]+nop *
+  [0-9a-f]+:	90[ 	]+nop *
+  [0-9a-f]+:	90[ 	]+nop *
+  [0-9a-f]+:	90[ 	]+nop *
+#  Direct access through %fs
+#  IE against global var
+  [0-9a-f]+:	48 8b 0d 81 02 10 00[ 	]+mov    1049217\(%rip\),%rcx +# 501358 <.*>
+#				-> R_X86_64_TPOFF64	sG5
+  [0-9a-f]+:	90[ 	]+nop *
+  [0-9a-f]+:	90[ 	]+nop *
+  [0-9a-f]+:	64 48 8b 11[ 	]+mov    %fs:\(%rcx\),%rdx
+  [0-9a-f]+:	90[ 	]+nop *
+  [0-9a-f]+:	90[ 	]+nop *
+  [0-9a-f]+:	90[ 	]+nop *
+  [0-9a-f]+:	90[ 	]+nop *
+#  IE->LE against local var
+  [0-9a-f]+:	49 c7 c3 90 ff ff ff[ 	]+mov    \$0xf+90,%r11
+#							sl5
+  [0-9a-f]+:	90[ 	]+nop *
+  [0-9a-f]+:	90[ 	]+nop *
+  [0-9a-f]+:	64 4d 8b 23[ 	]+mov    %fs:\(%r11\),%r12
+  [0-9a-f]+:	90[ 	]+nop *
+  [0-9a-f]+:	90[ 	]+nop *
+  [0-9a-f]+:	90[ 	]+nop *
+  [0-9a-f]+:	90[ 	]+nop *
+#  IE->LE against hidden var
+  [0-9a-f]+:	48 c7 c2 b0 ff ff ff[ 	]+mov    \$0xf+b0,%rdx
+  [0-9a-f]+:	90[ 	]+nop *
+  [0-9a-f]+:	90[ 	]+nop *
+  [0-9a-f]+:	64 48 8b 12[ 	]+mov    %fs:\(%rdx\),%rdx
+#							sh5
+  [0-9a-f]+:	90[ 	]+nop *
+  [0-9a-f]+:	90[ 	]+nop *
+  [0-9a-f]+:	90[ 	]+nop *
+  [0-9a-f]+:	90[ 	]+nop *
+  [0-9a-f]+:	c9[ 	]+leaveq *
+  [0-9a-f]+:	c3[ 	]+retq *
+  [0-9a-f]+:	90[ 	]+nop *
+  [0-9a-f]+:	90[ 	]+nop *
+  [0-9a-f]+:	90[ 	]+nop *
+
+[0-9a-f]+ <_start>:
+  [0-9a-f]+:	55[ 	]+push   %rbp
+  [0-9a-f]+:	48 89 e5[ 	]+mov    %rsp,%rbp
+#  IE against global var
+  [0-9a-f]+:	64 4c 8b 1c 25 00 00[ 	]+mov    %fs:0x0,%r11
+  [0-9a-f]+:	00 00 *
+  [0-9a-f]+:	90[ 	]+nop *
+  [0-9a-f]+:	90[ 	]+nop *
+  [0-9a-f]+:	4c 03 1d 4a 02 10 00[ 	]+add    1049162\(%rip\),%r11 +# 501368 <.*>
+#				-> R_X86_64_TPOFF64	sG6
+  [0-9a-f]+:	90[ 	]+nop *
+  [0-9a-f]+:	90[ 	]+nop *
+  [0-9a-f]+:	90[ 	]+nop *
+  [0-9a-f]+:	90[ 	]+nop *
+#  IE -> LE against global var defined in exec
+  [0-9a-f]+:	64 48 8b 14 25 00 00[ 	]+mov    %fs:0x0,%rdx
+  [0-9a-f]+:	00 00 *
+  [0-9a-f]+:	90[ 	]+nop *
+  [0-9a-f]+:	90[ 	]+nop *
+  [0-9a-f]+:	48 8d 92 d4 ff ff ff[ 	]+lea    0xf+d4\(%rdx\),%rdx
+#							bg6
+  [0-9a-f]+:	90[ 	]+nop *
+  [0-9a-f]+:	90[ 	]+nop *
+  [0-9a-f]+:	90[ 	]+nop *
+  [0-9a-f]+:	90[ 	]+nop *
+#  IE -> LE against local var
+  [0-9a-f]+:	64 4c 8b 24 25 00 00[ 	]+mov    %fs:0x0,%r12
+  [0-9a-f]+:	00 00 *
+  [0-9a-f]+:	90[ 	]+nop *
+  [0-9a-f]+:	90[ 	]+nop *
+  [0-9a-f]+:	49 81 c4 f4 ff ff ff[ 	]+add    \$0xf+f4,%r12
+#							bl6
+  [0-9a-f]+:	90[ 	]+nop *
+  [0-9a-f]+:	90[ 	]+nop *
+  [0-9a-f]+:	90[ 	]+nop *
+  [0-9a-f]+:	90[ 	]+nop *
+#  direct %fs access IE -> LE against local var
+  [0-9a-f]+:	48 c7 c2 fc ff ff ff[ 	]+mov    \$0xf+fc,%rdx
+#							bl8
+  [0-9a-f]+:	90[ 	]+nop *
+  [0-9a-f]+:	90[ 	]+nop *
+  [0-9a-f]+:	64 48 8b 02[ 	]+mov    %fs:\(%rdx\),%rax
+  [0-9a-f]+:	90[ 	]+nop *
+  [0-9a-f]+:	90[ 	]+nop *
+  [0-9a-f]+:	90[ 	]+nop *
+  [0-9a-f]+:	90[ 	]+nop *
+#  IE -> LE against hidden but not local var
+  [0-9a-f]+:	64 48 8b 14 25 00 00[ 	]+mov    %fs:0x0,%rdx
+  [0-9a-f]+:	00 00 *
+  [0-9a-f]+:	90[ 	]+nop *
+  [0-9a-f]+:	90[ 	]+nop *
+  [0-9a-f]+:	48 8d 92 b4 ff ff ff[ 	]+lea    0xf+b4\(%rdx\),%rdx
+#							sh6
+  [0-9a-f]+:	90[ 	]+nop *
+  [0-9a-f]+:	90[ 	]+nop *
+  [0-9a-f]+:	90[ 	]+nop *
+  [0-9a-f]+:	90[ 	]+nop *
+#  direct %fs access IE -> LE against hidden but not local var
+  [0-9a-f]+:	48 c7 c2 bc ff ff ff[ 	]+mov    \$0xf+bc,%rdx
+#							sh8
+  [0-9a-f]+:	90[ 	]+nop *
+  [0-9a-f]+:	90[ 	]+nop *
+  [0-9a-f]+:	64 48 8b 02[ 	]+mov    %fs:\(%rdx\),%rax
+  [0-9a-f]+:	90[ 	]+nop *
+  [0-9a-f]+:	90[ 	]+nop *
+  [0-9a-f]+:	90[ 	]+nop *
+  [0-9a-f]+:	90[ 	]+nop *
+#  LE, global var defined in exec
+  [0-9a-f]+:	64 48 8b 04 25 00 00[ 	]+mov    %fs:0x0,%rax
+  [0-9a-f]+:	00 00 *
+  [0-9a-f]+:	90[ 	]+nop *
+  [0-9a-f]+:	90[ 	]+nop *
+  [0-9a-f]+:	48 8d 90 64 ff ff ff[ 	]+lea    0xf+64\(%rax\),%rdx
+#							sg2
+  [0-9a-f]+:	90[ 	]+nop *
+  [0-9a-f]+:	90[ 	]+nop *
+  [0-9a-f]+:	90[ 	]+nop *
+  [0-9a-f]+:	90[ 	]+nop *
+#  LE, local var, non-canonical sequence
+  [0-9a-f]+:	49 c7 c1 e6 ff ff ff[ 	]+mov    \$0xf+e6,%r9
+#							bl2+2
+  [0-9a-f]+:	90[ 	]+nop *
+  [0-9a-f]+:	90[ 	]+nop *
+  [0-9a-f]+:	64 48 8b 14 25 00 00[ 	]+mov    %fs:0x0,%rdx
+  [0-9a-f]+:	00 00 *
+  [0-9a-f]+:	90[ 	]+nop *
+  [0-9a-f]+:	90[ 	]+nop *
+  [0-9a-f]+:	4c 01 ca[ 	]+add    %r9,%rdx
+  [0-9a-f]+:	90[ 	]+nop *
+  [0-9a-f]+:	90[ 	]+nop *
+  [0-9a-f]+:	90[ 	]+nop *
+  [0-9a-f]+:	90[ 	]+nop *
+#  LE, hidden var defined in exec, non-canonical sequence
+  [0-9a-f]+:	64 48 8b 14 25 00 00[ 	]+mov    %fs:0x0,%rdx
+  [0-9a-f]+:	00 00 *
+  [0-9a-f]+:	90[ 	]+nop *
+  [0-9a-f]+:	90[ 	]+nop *
+  [0-9a-f]+:	48 81 c2 a5 ff ff ff[ 	]+add    \$0xf+a5,%rdx
+#							sh2+1
+  [0-9a-f]+:	90[ 	]+nop *
+  [0-9a-f]+:	90[ 	]+nop *
+  [0-9a-f]+:	90[ 	]+nop *
+  [0-9a-f]+:	90[ 	]+nop *
+#  Direct %fs access
+#  LE, global var defined in exec
+  [0-9a-f]+:	64 48 8b 04 25 68 ff[ 	]+mov    %fs:0xf+68,%rax
+  [0-9a-f]+:	ff ff *
+#							sg3
+  [0-9a-f]+:	90[ 	]+nop *
+  [0-9a-f]+:	90[ 	]+nop *
+  [0-9a-f]+:	90[ 	]+nop *
+  [0-9a-f]+:	90[ 	]+nop *
+#  LE, local var
+  [0-9a-f]+:	64 4c 8b 14 25 eb ff[ 	]+mov    %fs:0xf+eb,%r10
+  [0-9a-f]+:	ff ff *
+#							bl3+3
+  [0-9a-f]+:	90[ 	]+nop *
+  [0-9a-f]+:	90[ 	]+nop *
+  [0-9a-f]+:	90[ 	]+nop *
+  [0-9a-f]+:	90[ 	]+nop *
+#  LE, hidden var defined in exec
+  [0-9a-f]+:	64 48 8b 14 25 a9 ff[ 	]+mov    %fs:0xf+a9,%rdx
+  [0-9a-f]+:	ff ff *
+#							sh3+1
+  [0-9a-f]+:	90[ 	]+nop *
+  [0-9a-f]+:	90[ 	]+nop *
+  [0-9a-f]+:	90[ 	]+nop *
+  [0-9a-f]+:	90[ 	]+nop *
+  [0-9a-f]+:	c9[ 	]+leaveq *
+  [0-9a-f]+:	c3[ 	]+retq *
Index: ld/testsuite/ld-x86-64/tlsbindesc.rd
===================================================================
RCS file: ld/testsuite/ld-x86-64/tlsbindesc.rd
diff -N ld/testsuite/ld-x86-64/tlsbindesc.rd
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ ld/testsuite/ld-x86-64/tlsbindesc.rd 15 Sep 2005 22:39:27 -0000
@@ -0,0 +1,141 @@
+#source: tlsbindesc.s
+#source: tlsbin.s
+#as: --64
+#ld: -shared -melf_x86_64
+#readelf: -WSsrl
+#target: x86_64-*-*
+
+There are 15 section headers, starting at offset 0x[0-9a-f]+:
+
+Section Headers:
+  \[Nr\] Name +Type +Address +Off +Size +ES Flg Lk Inf Al
+  \[ 0\] +NULL +0+ 0+ 0+ 00 +0 +0 +0
+  \[ 1\] .interp +.*
+  \[ 2\] .hash +.*
+  \[ 3\] .dynsym +.*
+  \[ 4\] .dynstr +.*
+  \[ 5\] .rela.dyn +.*
+  \[ 6\] .text +PROGBITS +0+401000 0+1000 0+1f6 00 +AX +0 +0 +4096
+  \[ 7\] .tdata +PROGBITS +0+5011f6 0+11f6 0+60 00 WAT +0 +0 +1
+  \[ 8\] .tbss +NOBITS +0+501256 0+1256 0+40 00 WAT +0 +0 +1
+  \[ 9\] .dynamic +DYNAMIC +0+501258 0+1258 0+100 10 +WA +4 +0 +8
+  \[10\] .got +PROGBITS +0+501358 0+1358 0+20 08 +WA +0 +0 +8
+  \[11\] .got.plt +PROGBITS +0+501378 0+1378 0+18 08 +WA +0 +0 +8
+  \[12\] .shstrtab +.*
+  \[13\] .symtab +.*
+  \[14\] .strtab +.*
+Key to Flags:
+.*
+.*
+.*
+
+Elf file type is EXEC \(Executable file\)
+Entry point 0x401108
+There are 6 program headers, starting at offset [0-9]+
+
+Program Headers:
+  Type +Offset +VirtAddr +PhysAddr +FileSiz +MemSiz +Flg Align
+  PHDR.*
+  INTERP.*
+.*Requesting program interpreter.*
+  LOAD +0x0+ 0x0+400000 0x0+400000 0x0+11f6 0x0+11f6 R E 0x100000
+  LOAD +0x0+11f6 0x0+5011f6 0x0+5011f6 0x0+19a 0x0+19a RW  0x100000
+  DYNAMIC +0x0+1258 0x0+501258 0x0+501258 0x0+100 0x0+100 RW  0x8
+  TLS +0x0+11f6 0x0+5011f6 0x0+5011f6 0x0+60 0x0+a0 R +0x1
+
+ Section to Segment mapping:
+  Segment Sections...
+   00 *
+   01 +.interp *
+   02 +.interp .hash .dynsym .dynstr .rela.dyn .text *
+   03 +.tdata .dynamic .got .got.plt *
+   04 +.dynamic *
+   05 +.tdata .tbss *
+
+Relocation section '.rela.dyn' at offset 0x[0-9a-f]+ contains 4 entries:
+ +Offset +Info +Type +Symbol's Value  Symbol's Name \+ Addend
+0+501358  0+100000012 R_X86_64_TPOFF64 +0+ sG5 \+ 0
+0+501360  0+200000012 R_X86_64_TPOFF64 +0+ sG2 \+ 0
+0+501368  0+400000012 R_X86_64_TPOFF64 +0+ sG6 \+ 0
+0+501370  0+500000012 R_X86_64_TPOFF64 +0+ sG1 \+ 0
+
+Symbol table '.dynsym' contains 8 entries:
+ +Num: +Value +Size Type +Bind +Vis +Ndx Name
+ +[0-9]+: 0+ +0 NOTYPE  LOCAL  DEFAULT  UND *
+ +[0-9]+: 0+ +0 TLS +GLOBAL DEFAULT  UND sG5
+ +[0-9]+: 0+ +0 TLS +GLOBAL DEFAULT  UND sG2
+ +[0-9]+: 0+[0-9a-f]+ +0 NOTYPE  GLOBAL DEFAULT  ABS __bss_start
+ +[0-9]+: 0+ +0 TLS +GLOBAL DEFAULT  UND sG6
+ +[0-9]+: 0+ +0 TLS +GLOBAL DEFAULT  UND sG1
+ +[0-9]+: 0+[0-9a-f]+ +0 NOTYPE  GLOBAL DEFAULT  ABS _edata
+ +[0-9]+: 0+[0-9a-f]+ +0 NOTYPE  GLOBAL DEFAULT  ABS _end
+
+Symbol table '.symtab' contains 67 entries:
+ +Num: +Value +Size Type +Bind +Vis +Ndx Name
+ +[0-9]+: 0+ +0 NOTYPE  LOCAL  DEFAULT  UND *
+ +[0-9]+: [0-9a-f]+ +0 SECTION LOCAL  DEFAULT +1 *
+ +[0-9]+: [0-9a-f]+ +0 SECTION LOCAL  DEFAULT +2 *
+ +[0-9]+: [0-9a-f]+ +0 SECTION LOCAL  DEFAULT +3 *
+ +[0-9]+: [0-9a-f]+ +0 SECTION LOCAL  DEFAULT +4 *
+ +[0-9]+: [0-9a-f]+ +0 SECTION LOCAL  DEFAULT +5 *
+ +[0-9]+: [0-9a-f]+ +0 SECTION LOCAL  DEFAULT +6 *
+ +[0-9]+: [0-9a-f]+ +0 SECTION LOCAL  DEFAULT +7 *
+ +[0-9]+: [0-9a-f]+ +0 SECTION LOCAL  DEFAULT +8 *
+ +[0-9]+: [0-9a-f]+ +0 SECTION LOCAL  DEFAULT +9 *
+ +[0-9]+: [0-9a-f]+ +0 SECTION LOCAL  DEFAULT +10 *
+ +[0-9]+: [0-9a-f]+ +0 SECTION LOCAL  DEFAULT +11 *
+ +[0-9]+: [0-9a-f]+ +0 SECTION LOCAL  DEFAULT +12 *
+ +[0-9]+: [0-9a-f]+ +0 SECTION LOCAL  DEFAULT +13 *
+ +[0-9]+: [0-9a-f]+ +0 SECTION LOCAL  DEFAULT +14 *
+ +[0-9]+: 0+20 +0 TLS +LOCAL  DEFAULT +7 sl1
+ +[0-9]+: 0+24 +0 TLS +LOCAL  DEFAULT +7 sl2
+ +[0-9]+: 0+28 +0 TLS +LOCAL  DEFAULT +7 sl3
+ +[0-9]+: 0+2c +0 TLS +LOCAL  DEFAULT +7 sl4
+ +[0-9]+: 0+30 +0 TLS +LOCAL  DEFAULT +7 sl5
+ +[0-9]+: 0+34 +0 TLS +LOCAL  DEFAULT +7 sl6
+ +[0-9]+: 0+38 +0 TLS +LOCAL  DEFAULT +7 sl7
+ +[0-9]+: 0+3c +0 TLS +LOCAL  DEFAULT +7 sl8
+ +[0-9]+: 0+80 +0 TLS +LOCAL  DEFAULT +8 bl1
+ +[0-9]+: 0+84 +0 TLS +LOCAL  DEFAULT +8 bl2
+ +[0-9]+: 0+88 +0 TLS +LOCAL  DEFAULT +8 bl3
+ +[0-9]+: 0+8c +0 TLS +LOCAL  DEFAULT +8 bl4
+ +[0-9]+: 0+90 +0 TLS +LOCAL  DEFAULT +8 bl5
+ +[0-9]+: 0+94 +0 TLS +LOCAL  DEFAULT +8 bl6
+ +[0-9]+: 0+98 +0 TLS +LOCAL  DEFAULT +8 bl7
+ +[0-9]+: 0+9c +0 TLS +LOCAL  DEFAULT +8 bl8
+ +[0-9]+: 0+0 +0 TLS +LOCAL  HIDDEN +7 _TLS_MODULE_BASE_
+ +[0-9]+: 0+501258 +0 OBJECT  LOCAL  HIDDEN    9 _DYNAMIC
+ +[0-9]+: 0+501378 +0 OBJECT  LOCAL  HIDDEN   11 _GLOBAL_OFFSET_TABLE_
+ +[0-9]+: 0+1c +0 TLS +GLOBAL DEFAULT +7 sg8
+ +[0-9]+: 0+7c +0 TLS +GLOBAL DEFAULT +8 bg8
+ +[0-9]+: 0+74 +0 TLS +GLOBAL DEFAULT +8 bg6
+ +[0-9]+: 0+ +0 TLS +GLOBAL DEFAULT  UND sG5
+ +[0-9]+: 0+68 +0 TLS +GLOBAL DEFAULT +8 bg3
+ +[0-9]+: 0+8 +0 TLS +GLOBAL DEFAULT +7 sg3
+ +[0-9]+: 0+48 +0 TLS +GLOBAL HIDDEN +7 sh3
+ +[0-9]+: 0+ +0 TLS +GLOBAL DEFAULT  UND sG2
+ +[0-9]+: 0+c +0 TLS +GLOBAL DEFAULT +7 sg4
+ +[0-9]+: 0+10 +0 TLS +GLOBAL DEFAULT +7 sg5
+ +[0-9]+: 0+70 +0 TLS +GLOBAL DEFAULT +8 bg5
+ +[0-9]+: 0+58 +0 TLS +GLOBAL HIDDEN +7 sh7
+ +[0-9]+: 0+5c +0 TLS +GLOBAL HIDDEN +7 sh8
+ +[0-9]+: 0+ +0 TLS +GLOBAL DEFAULT +7 sg1
+ +[0-9]+: 0+401108 +0 FUNC +GLOBAL DEFAULT +6 _start
+ +[0-9]+: 0+4c +0 TLS +GLOBAL HIDDEN +7 sh4
+ +[0-9]+: 0+78 +0 TLS +GLOBAL DEFAULT +8 bg7
+ +[0-9]+: 0+50 +0 TLS +GLOBAL HIDDEN +7 sh5
+ +[0-9]+: [0-9a-f]+ +0 NOTYPE  GLOBAL DEFAULT  ABS __bss_start
+ +[0-9]+: 0+ +0 TLS +GLOBAL DEFAULT  UND sG6
+ +[0-9]+: 0+401000 +0 FUNC +GLOBAL DEFAULT +6 fn2
+ +[0-9]+: 0+4 +0 TLS +GLOBAL DEFAULT +7 sg2
+ +[0-9]+: 0+ +0 TLS +GLOBAL DEFAULT  UND sG1
+ +[0-9]+: 0+40 +0 TLS +GLOBAL HIDDEN +7 sh1
+ +[0-9]+: 0+14 +0 TLS +GLOBAL DEFAULT +7 sg6
+ +[0-9]+: 0+18 +0 TLS +GLOBAL DEFAULT +7 sg7
+ +[0-9]+: [0-9a-f]+ +0 NOTYPE  GLOBAL DEFAULT  ABS _edata
+ +[0-9]+: [0-9a-f]+ +0 NOTYPE  GLOBAL DEFAULT  ABS _end
+ +[0-9]+: 0+44 +0 TLS +GLOBAL HIDDEN +7 sh2
+ +[0-9]+: 0+54 +0 TLS +GLOBAL HIDDEN +7 sh6
+ +[0-9]+: 0+64 +0 TLS +GLOBAL DEFAULT +8 bg2
+ +[0-9]+: 0+60 +0 TLS +GLOBAL DEFAULT +8 bg1
+ +[0-9]+: 0+6c +0 TLS +GLOBAL DEFAULT +8 bg4
Index: ld/testsuite/ld-x86-64/tlsbindesc.s
===================================================================
RCS file: ld/testsuite/ld-x86-64/tlsbindesc.s
diff -N ld/testsuite/ld-x86-64/tlsbindesc.s
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ ld/testsuite/ld-x86-64/tlsbindesc.s 15 Sep 2005 22:39:27 -0000
@@ -0,0 +1,128 @@
+	/* Force .data aligned to 4K, so that .got very likely gets at
+	   0x5021a0 (0x60 bytes .tdata and 0x140 bytes .dynamic)  */
+	.data
+	.balign	4096
+	.section ".tdata", "awT", @progbits
+	.globl sg1, sg2, sg3, sg4, sg5, sg6, sg7, sg8
+	.globl sh1, sh2, sh3, sh4, sh5, sh6, sh7, sh8
+	.hidden sh1, sh2, sh3, sh4, sh5, sh6, sh7, sh8
+sg1:	.long 17
+sg2:	.long 18
+sg3:	.long 19
+sg4:	.long 20
+sg5:	.long 21
+sg6:	.long 22
+sg7:	.long 23
+sg8:	.long 24
+sl1:	.long 65
+sl2:	.long 66
+sl3:	.long 67
+sl4:	.long 68
+sl5:	.long 69
+sl6:	.long 70
+sl7:	.long 71
+sl8:	.long 72
+sh1:	.long 257
+sh2:	.long 258
+sh3:	.long 259
+sh4:	.long 260
+sh5:	.long 261
+sh6:	.long 262
+sh7:	.long 263
+sh8:	.long 264
+	/* Force .text aligned to 4K, so it very likely gets at 0x401000.  */
+	.text
+	.balign	4096
+	.globl	fn2
+	.type	fn2,@function
+fn2:
+	pushq	%rbp
+	movq	%rsp, %rbp
+
+	/* GD -> IE because variable is not defined in executable */
+	leaq	sG1@tlsdesc(%rip), %rax
+	call	*sG1@tlscall(%rax)
+	nop;nop;nop;nop
+
+	/* GD -> IE because variable is not defined in executable where
+	   the variable is referenced through IE too */
+	leaq	sG2@tlsdesc(%rip), %rax
+	call	*sG2@tlscall(%rax)
+	nop;nop;nop;nop
+
+	/* GD -> LE with global variable defined in executable */
+	leaq	sg1@tlsdesc(%rip), %rax
+	call	*sg1@tlscall(%rax)
+	nop;nop;nop;nop
+
+	/* GD -> LE with local variable defined in executable */
+	leaq	sl1@tlsdesc(%rip), %rax
+	call	*sl1@tlscall(%rax)
+	nop;nop;nop;nop
+
+	/* GD -> LE with hidden variable defined in executable */
+	leaq	sh1@tlsdesc(%rip), %rax
+	call	*sh1@tlscall(%rax)
+	nop;nop;nop;nop
+
+	/* LD -> LE */
+	leaq	_TLS_MODULE_BASE_@tlsdesc(%rip), %rax
+	call	*_TLS_MODULE_BASE_@tlscall(%rax)
+	nop;nop
+	leaq	1+sl1@dtpoff(%rax), %rdx
+	nop;nop
+	leaq	sl2@dtpoff+2(%rax), %r9
+	nop;nop;nop;nop
+
+	/* LD -> LE against hidden variables */
+	leaq	sh1@dtpoff(%rax), %rdx
+	nop;nop
+	leaq	3+sh2@dtpoff(%rax), %rcx
+	nop;nop;nop;nop
+
+	/* IE against global var  */
+	movq	%fs:0, %r9
+	nop;nop
+	addq	sG2@gottpoff(%rip), %r9
+	nop;nop;nop;nop
+
+	/* IE -> LE against global var defined in exec */
+	movq	%fs:0, %r10
+	nop;nop
+	addq	sg1@gottpoff(%rip), %r10
+	nop;nop;nop;nop
+
+	/* IE -> LE against local var */
+	movq	%fs:0, %rax
+	nop;nop
+	addq	sl1@gottpoff(%rip), %rax
+	nop;nop;nop;nop
+
+	/* IE -> LE against hidden var */
+	movq	%fs:0, %rcx
+	nop;nop
+	addq	sh1@gottpoff(%rip), %rcx
+	nop;nop;nop;nop
+
+	/* Direct access through %fs  */
+
+	/* IE against global var  */
+	movq	sG5@gottpoff(%rip), %rcx
+	nop;nop
+	movq	%fs:(%rcx), %rdx
+	nop;nop;nop;nop
+
+	/* IE->LE against local var  */
+	movq	sl5@gottpoff(%rip), %r11
+	nop;nop
+	movq	%fs:(%r11), %r12
+	nop;nop;nop;nop
+
+	/* IE->LE against hidden var  */
+	movq	sh5@gottpoff(%rip), %rdx
+	nop;nop
+	movq	%fs:(%rdx), %rdx
+	nop;nop;nop;nop
+
+	leave
+	ret
Index: ld/testsuite/ld-x86-64/tlsbindesc.sd
===================================================================
RCS file: ld/testsuite/ld-x86-64/tlsbindesc.sd
diff -N ld/testsuite/ld-x86-64/tlsbindesc.sd
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ ld/testsuite/ld-x86-64/tlsbindesc.sd 15 Sep 2005 22:39:27 -0000
@@ -0,0 +1,12 @@
+#source: tlsbindesc.s
+#source: tlsbin.s
+#as: --64
+#ld: -shared -melf_x86_64
+#objdump: -sj.got
+#target: x86_64-*-*
+
+.*: +file format elf64-x86-64
+
+Contents of section .got:
+ 501358 00000000 00000000 00000000 00000000  .*
+ 501368 00000000 00000000 00000000 00000000  .*
Index: ld/testsuite/ld-x86-64/tlsbindesc.td
===================================================================
RCS file: ld/testsuite/ld-x86-64/tlsbindesc.td
diff -N ld/testsuite/ld-x86-64/tlsbindesc.td
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ ld/testsuite/ld-x86-64/tlsbindesc.td 15 Sep 2005 22:39:27 -0000
@@ -0,0 +1,16 @@
+#source: tlsbindesc.s
+#source: tlsbin.s
+#as: --64
+#ld: -shared -melf_x86_64
+#objdump: -sj.tdata
+#target: x86_64-*-*
+
+.*: +file format elf64-x86-64
+
+Contents of section .tdata:
+ 5011f6 11000000 12000000 13000000 14000000  .*
+ 501206 15000000 16000000 17000000 18000000  .*
+ 501216 41000000 42000000 43000000 44000000  .*
+ 501226 45000000 46000000 47000000 48000000  .*
+ 501236 01010000 02010000 03010000 04010000  .*
+ 501246 05010000 06010000 07010000 08010000  .*
Index: ld/testsuite/ld-x86-64/tlsdesc.dd
===================================================================
RCS file: ld/testsuite/ld-x86-64/tlsdesc.dd
diff -N ld/testsuite/ld-x86-64/tlsdesc.dd
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ ld/testsuite/ld-x86-64/tlsdesc.dd 15 Sep 2005 22:39:27 -0000
@@ -0,0 +1,200 @@
+#source: tlsdesc.s
+#source: tlspic2.s
+#as: --64
+#ld: -shared -melf_x86_64
+#objdump: -drj.text
+#target: x86_64-*-*
+
+.*: +file format elf64-x86-64
+
+Disassembly of section .text:
+
+0+[0-9a-f]+ <fn1>:
+ +[0-9a-f]+:	55[ 	]+push   %rbp
+ +[0-9a-f]+:	48 89 e5[ 	]+mov    %rsp,%rbp
+ +[0-9a-f]+:	90[ 	]+nop *
+ +[0-9a-f]+:	90[ 	]+nop *
+ +[0-9a-f]+:	90[ 	]+nop *
+ +[0-9a-f]+:	90[ 	]+nop *
+#  GD
+ +[0-9a-f]+:	48 8d 05 89 03 10 00[ 	]+lea    1049481\(%rip\),%rax +# 101398 <.*>
+#				-> R_X86_64_TLSDESC	sg1
+ +[0-9a-f]+:	ff 10[ 	]+callq  \*\(%rax\)
+ +[0-9a-f]+:	90[ 	]+nop *
+ +[0-9a-f]+:	90[ 	]+nop *
+ +[0-9a-f]+:	90[ 	]+nop *
+ +[0-9a-f]+:	90[ 	]+nop *
+#  GD -> IE because variable is referenced through IE too
+ +[0-9a-f]+:	48 8b 05 1c 03 10 00[ 	]+mov    1049372\(%rip\),%rax +# 101338 <.*>
+#				-> R_X86_64_TPOFF64	sg2
+ +[0-9a-f]+:	48 90[ 	]+rex64 nop *
+ +[0-9a-f]+:	90[ 	]+nop *
+ +[0-9a-f]+:	90[ 	]+nop *
+ +[0-9a-f]+:	90[ 	]+nop *
+ +[0-9a-f]+:	90[ 	]+nop *
+#  GD against local variable
+ +[0-9a-f]+:	48 8d 05 3f 03 10 00[ 	]+lea    1049407\(%rip\),%rax +# 101368 <.*>
+#				-> R_X86_64_TLSDESC	[0 0x2000000000000000]
+ +[0-9a-f]+:	ff 10[ 	]+callq  \*\(%rax\)
+ +[0-9a-f]+:	90[ 	]+nop *
+ +[0-9a-f]+:	90[ 	]+nop *
+ +[0-9a-f]+:	90[ 	]+nop *
+ +[0-9a-f]+:	90[ 	]+nop *
+#  GD -> IE against local variable referenced through IE too
+ +[0-9a-f]+:	48 8b 05 d2 02 10 00[ 	]+mov    1049298\(%rip\),%rax +# 101308 <.*>
+#				-> R_X86_64_TPOFF64	*ABS*+0x24
+ +[0-9a-f]+:	48 90[ 	]+rex64 nop *
+ +[0-9a-f]+:	90[ 	]+nop *
+ +[0-9a-f]+:	90[ 	]+nop *
+ +[0-9a-f]+:	90[ 	]+nop *
+ +[0-9a-f]+:	90[ 	]+nop *
+#  GD against hidden and local variable
+ +[0-9a-f]+:	48 8d 05 65 03 10 00[ 	]+lea    1049445\(%rip\),%rax +# 1013a8 <.*>
+#				-> R_X86_64_TLSDESC	[0 0x4000000000000000]
+ +[0-9a-f]+:	ff 10[ 	]+callq  \*\(%rax\)
+ +[0-9a-f]+:	90[ 	]+nop *
+ +[0-9a-f]+:	90[ 	]+nop *
+ +[0-9a-f]+:	90[ 	]+nop *
+ +[0-9a-f]+:	90[ 	]+nop *
+#  GD -> IE against hidden and local variable referenced through IE too
+ +[0-9a-f]+:	48 8b 05 f0 02 10 00[ 	]+mov    1049328\(%rip\),%rax +# 101340 <.*>
+#				-> R_X86_64_TPOFF64	*ABS*+0x44
+ +[0-9a-f]+:	48 90[ 	]+rex64 nop *
+ +[0-9a-f]+:	90[ 	]+nop *
+ +[0-9a-f]+:	90[ 	]+nop *
+ +[0-9a-f]+:	90[ 	]+nop *
+ +[0-9a-f]+:	90[ 	]+nop *
+#  GD against hidden but not local variable
+ +[0-9a-f]+:	48 8d 05 1b 03 10 00[ 	]+lea    1049371\(%rip\),%rax +# 101378 <.*>
+#				-> R_X86_64_TLSDESC	[0 0x6000000000000000]
+ +[0-9a-f]+:	ff 10[ 	]+callq  \*\(%rax\)
+ +[0-9a-f]+:	90[ 	]+nop *
+ +[0-9a-f]+:	90[ 	]+nop *
+ +[0-9a-f]+:	90[ 	]+nop *
+ +[0-9a-f]+:	90[ 	]+nop *
+#  GD -> IE against hidden but not local variable referenced through IE too
+ +[0-9a-f]+:	48 8b 05 ae 02 10 00[ 	]+mov    1049262\(%rip\),%rax +# 101318 <.*>
+#				-> R_X86_64_TPOFF64	*ABS*+0x64
+ +[0-9a-f]+:	48 90[ 	]+rex64 nop *
+ +[0-9a-f]+:	90[ 	]+nop *
+ +[0-9a-f]+:	90[ 	]+nop *
+ +[0-9a-f]+:	90[ 	]+nop *
+ +[0-9a-f]+:	90[ 	]+nop *
+#  LD
+ +[0-9a-f]+:	48 8d 05 11 03 10 00[ 	]+lea    1049361\(%rip\),%rax +# 101388 <.*>
+#				-> R_X86_64_TLSDESC	[0 0x000000000000000]
+ +[0-9a-f]+:	ff 10[ 	]+callq  \*\(%rax\)
+ +[0-9a-f]+:	90[ 	]+nop *
+ +[0-9a-f]+:	90[ 	]+nop *
+ +[0-9a-f]+:	48 8d 90 20 00 00 00[ 	]+lea    0x20\(%rax\),%rdx
+ +[0-9a-f]+:	90[ 	]+nop *
+ +[0-9a-f]+:	90[ 	]+nop *
+ +[0-9a-f]+:	4c 8d 88 26 00 00 00[ 	]+lea    0x26\(%rax\),%r9
+ +[0-9a-f]+:	90[ 	]+nop *
+ +[0-9a-f]+:	90[ 	]+nop *
+ +[0-9a-f]+:	90[ 	]+nop *
+ +[0-9a-f]+:	90[ 	]+nop *
+#  LD against hidden and local variables
+ +[0-9a-f]+:	48 8d 90 40 00 00 00[ 	]+lea    0x40\(%rax\),%rdx
+ +[0-9a-f]+:	90[ 	]+nop *
+ +[0-9a-f]+:	90[ 	]+nop *
+ +[0-9a-f]+:	48 8d 88 47 00 00 00[ 	]+lea    0x47\(%rax\),%rcx
+ +[0-9a-f]+:	90[ 	]+nop *
+ +[0-9a-f]+:	90[ 	]+nop *
+ +[0-9a-f]+:	90[ 	]+nop *
+ +[0-9a-f]+:	90[ 	]+nop *
+#  LD against hidden but not local variables
+ +[0-9a-f]+:	4c 8d a0 60 00 00 00[ 	]+lea    0x60\(%rax\),%r12
+ +[0-9a-f]+:	90[ 	]+nop *
+ +[0-9a-f]+:	90[ 	]+nop *
+ +[0-9a-f]+:	48 8d 88 65 00 00 00[ 	]+lea    0x65\(%rax\),%rcx
+ +[0-9a-f]+:	90[ 	]+nop *
+ +[0-9a-f]+:	90[ 	]+nop *
+#  IE against global var
+ +[0-9a-f]+:	64 48 8b 0c 25 00 00[ 	]+mov    %fs:0x0,%rcx
+ +[0-9a-f]+:	00 00 *
+ +[0-9a-f]+:	90[ 	]+nop *
+ +[0-9a-f]+:	90[ 	]+nop *
+ +[0-9a-f]+:	48 03 0d 71 02 10 00[ 	]+add    1049201\(%rip\),%rcx +# 101338 <.*>
+#				-> R_X86_64_TPOFF64	sg2
+ +[0-9a-f]+:	90[ 	]+nop *
+ +[0-9a-f]+:	90[ 	]+nop *
+ +[0-9a-f]+:	90[ 	]+nop *
+ +[0-9a-f]+:	90[ 	]+nop *
+#  IE against local var
+ +[0-9a-f]+:	64 4c 8b 34 25 00 00[ 	]+mov    %fs:0x0,%r14
+ +[0-9a-f]+:	00 00 *
+ +[0-9a-f]+:	90[ 	]+nop *
+ +[0-9a-f]+:	90[ 	]+nop *
+ +[0-9a-f]+:	4c 03 35 2b 02 10 00[ 	]+add    1049131\(%rip\),%r14 +# 101308 <.*>
+#				-> R_X86_64_TPOFF64	*ABS*+0x24
+ +[0-9a-f]+:	90[ 	]+nop *
+ +[0-9a-f]+:	90[ 	]+nop *
+ +[0-9a-f]+:	90[ 	]+nop *
+ +[0-9a-f]+:	90[ 	]+nop *
+#  IE against hidden and local var
+ +[0-9a-f]+:	64 48 8b 0c 25 00 00[ 	]+mov    %fs:0x0,%rcx
+ +[0-9a-f]+:	00 00 *
+ +[0-9a-f]+:	90[ 	]+nop *
+ +[0-9a-f]+:	90[ 	]+nop *
+ +[0-9a-f]+:	48 03 0d 4d 02 10 00[ 	]+add    1049165\(%rip\),%rcx +# 101340 <.*>
+#				-> R_X86_64_TPOFF64	*ABS*+0x44
+ +[0-9a-f]+:	90[ 	]+nop *
+ +[0-9a-f]+:	90[ 	]+nop *
+ +[0-9a-f]+:	90[ 	]+nop *
+ +[0-9a-f]+:	90[ 	]+nop *
+#  IE against hidden but not local var
+ +[0-9a-f]+:	64 48 8b 0c 25 00 00[ 	]+mov    %fs:0x0,%rcx
+ +[0-9a-f]+:	00 00 *
+ +[0-9a-f]+:	90[ 	]+nop *
+ +[0-9a-f]+:	90[ 	]+nop *
+ +[0-9a-f]+:	48 03 0d 0f 02 10 00[ 	]+add    1049103\(%rip\),%rcx +# 101318 <.*>
+#				-> R_X86_64_TPOFF64	*ABS*+0x64
+ +[0-9a-f]+:	90[ 	]+nop *
+ +[0-9a-f]+:	90[ 	]+nop *
+ +[0-9a-f]+:	90[ 	]+nop *
+ +[0-9a-f]+:	90[ 	]+nop *
+#  Direct access through %fs
+#  IE against global var
+ +[0-9a-f]+:	48 8b 0d 0c 02 10 00[ 	]+mov    1049100\(%rip\),%rcx +# 101320 <.*>
+#				-> R_X86_64_TPOFF64	sg5
+ +[0-9a-f]+:	90[ 	]+nop *
+ +[0-9a-f]+:	90[ 	]+nop *
+ +[0-9a-f]+:	64 48 8b 11[ 	]+mov    %fs:\(%rcx\),%rdx
+ +[0-9a-f]+:	90[ 	]+nop *
+ +[0-9a-f]+:	90[ 	]+nop *
+ +[0-9a-f]+:	90[ 	]+nop *
+ +[0-9a-f]+:	90[ 	]+nop *
+#  IE against local var
+ +[0-9a-f]+:	4c 8b 15 eb 01 10 00[ 	]+mov    1049067\(%rip\),%r10 +# 101310 <.*>
+#				-> R_X86_64_TPOFF64	*ABS*+0x30
+ +[0-9a-f]+:	90[ 	]+nop *
+ +[0-9a-f]+:	90[ 	]+nop *
+ +[0-9a-f]+:	64 4d 8b 22[ 	]+mov    %fs:\(%r10\),%r12
+ +[0-9a-f]+:	90[ 	]+nop *
+ +[0-9a-f]+:	90[ 	]+nop *
+ +[0-9a-f]+:	90[ 	]+nop *
+ +[0-9a-f]+:	90[ 	]+nop *
+#  IE against hidden and local var
+ +[0-9a-f]+:	48 8b 15 f2 01 10 00[ 	]+mov    1049074\(%rip\),%rdx +# 101328 <.*>
+#				-> R_X86_64_TPOFF64	*ABS*+0x50
+ +[0-9a-f]+:	90[ 	]+nop *
+ +[0-9a-f]+:	90[ 	]+nop *
+ +[0-9a-f]+:	64 48 8b 12[ 	]+mov    %fs:\(%rdx\),%rdx
+ +[0-9a-f]+:	90[ 	]+nop *
+ +[0-9a-f]+:	90[ 	]+nop *
+ +[0-9a-f]+:	90[ 	]+nop *
+ +[0-9a-f]+:	90[ 	]+nop *
+#  IE against hidden but not local var
+ +[0-9a-f]+:	48 8b 0d e9 01 10 00[ 	]+mov    1049065\(%rip\),%rcx +# 101330 <.*>
+#				-> R_X86_64_TPOFF64	*ABS*+0x70
+ +[0-9a-f]+:	90[ 	]+nop *
+ +[0-9a-f]+:	90[ 	]+nop *
+ +[0-9a-f]+:	64 48 8b 11[ 	]+mov    %fs:\(%rcx\),%rdx
+ +[0-9a-f]+:	90[ 	]+nop *
+ +[0-9a-f]+:	90[ 	]+nop *
+ +[0-9a-f]+:	90[ 	]+nop *
+ +[0-9a-f]+:	90[ 	]+nop *
+ +[0-9a-f]+:	c9[ 	]+leaveq *
+ +[0-9a-f]+:	c3[ 	]+retq *
+ +[0-9a-f]+:	90[ 	]+nop *
Index: ld/testsuite/ld-x86-64/tlsdesc.pd
===================================================================
RCS file: ld/testsuite/ld-x86-64/tlsdesc.pd
diff -N ld/testsuite/ld-x86-64/tlsdesc.pd
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ ld/testsuite/ld-x86-64/tlsdesc.pd 15 Sep 2005 22:39:27 -0000
@@ -0,0 +1,26 @@
+#source: tlsdesc.s
+#source: tlspic2.s
+#as: --64
+#ld: -shared -melf_x86_64
+#objdump: -drj.plt
+#target: x86_64-*-*
+
+.*: +file format elf64-x86-64
+
+Disassembly of section .plt:
+
+0000000000000470 <.*@plt-0x10>:
+ 470:	ff 35 e2 0e 10 00    	pushq  1052386\(%rip\)        # 101358 <_GLOBAL_OFFSET_TABLE_\+0x8>
+ 476:	ff 25 e4 0e 10 00    	jmpq   \*1052388\(%rip\)        # 101360 <_GLOBAL_OFFSET_TABLE_\+0x10>
+ 47c:	90                   	nop    
+ 47d:	90                   	nop    
+ 47e:	90                   	nop    
+ 47f:	90                   	nop    
+0000000000000480 <.*@plt>:
+ 480:	ff 35 d2 0e 10 00    	pushq  1052370\(%rip\)        # 101358 <_GLOBAL_OFFSET_TABLE_\+0x8>
+ 486:	ff 25 bc 0e 10 00    	jmpq   \*1052348\(%rip\)        # 101348 <_DYNAMIC\+0x190>
+ 48c:	90                   	nop    
+ 48d:	90                   	nop    
+ 48e:	90                   	nop    
+ 48f:	90                   	nop    
+
Index: ld/testsuite/ld-x86-64/tlsdesc.rd
===================================================================
RCS file: ld/testsuite/ld-x86-64/tlsdesc.rd
diff -N ld/testsuite/ld-x86-64/tlsdesc.rd
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ ld/testsuite/ld-x86-64/tlsdesc.rd 15 Sep 2005 22:39:27 -0000
@@ -0,0 +1,164 @@
+#source: tlsdesc.s
+#source: tlspic2.s
+#as: --64
+#ld: -shared -melf_x86_64
+#readelf: -WSsrld
+#target: x86_64-*-*
+
+There are 16 section headers, starting at offset 0x[0-9a-f]+:
+
+Section Headers:
+  \[Nr\] Name +Type +Address +Off +Size +ES Flg Lk Inf Al
+  \[ 0\] +NULL +0+ 0+ 0+ 00 +0 +0 +0
+  \[ 1\] .hash +.*
+  \[ 2\] .dynsym +.*
+  \[ 3\] .dynstr +.*
+  \[ 4\] .rela.dyn +.*
+  \[ 5\] .rela.plt +.*
+  \[ 6\] .plt +PROGBITS +0+470 0+470 0+20 10 +AX +0 +0 +4
+  \[ 7\] .text +PROGBITS +0+1000 0+1000 0+154 00 +AX +0 +0 4096
+  \[ 8\] .tdata +PROGBITS +0+101154 0+1154 0+60 00 WAT +0 +0 +1
+  \[ 9\] .tbss +NOBITS +0+1011b4 0+11b4 0+20 00 WAT +0 +0 +1
+  \[10\] .dynamic +DYNAMIC +0+1011b8 0+11b8 0+150 10 +WA +3 +0 +8
+  \[11\] .got +PROGBITS +0+101308 0+1308 0+48 08 +WA +0 +0 +8
+  \[12\] .got.plt +PROGBITS +0+101350 0+1350 0+68 08 +WA +0 +0 +8
+  \[13\] .shstrtab +.*
+  \[14\] .symtab +.*
+  \[15\] .strtab +.*
+Key to Flags:
+.*
+.*
+.*
+
+Elf file type is DYN \(Shared object file\)
+Entry point 0x1000
+There are 4 program headers, starting at offset [0-9]+
+
+Program Headers:
+  Type +Offset +VirtAddr +PhysAddr +FileSiz +MemSiz +Flg Align
+  LOAD +0x0+ 0x0+ 0x0+ 0x[0-9a-f]+ 0x[0-9a-f]+ R E 0x100000
+  LOAD +0x0+1154 0x0+101154 0x0+101154 0x0+264 0x0+264 RW +0x100000
+  DYNAMIC +0x0+11b8 0x0+1011b8 0x0+1011b8 0x0+150 0x0+150 RW +0x8
+  TLS +0x0+1154 0x0+101154 0x0+101154 0x0+60 0x0+80 R +0x1
+
+ Section to Segment mapping:
+  Segment Sections...
+   00 +.hash .dynsym .dynstr .rela.dyn .rela.plt .plt .text *
+   01 +.tdata .dynamic .got .got.plt *
+   02 +.dynamic *
+   03 +.tdata .tbss *
+
+Dynamic section at offset 0x[0-9a-f]+ contains 16 entries:
+ +Tag +Type +Name/Value
+ 0x[0-9a-f]+ +\(HASH\).*
+ 0x[0-9a-f]+ +\(STRTAB\).*
+ 0x[0-9a-f]+ +\(SYMTAB\).*
+ 0x[0-9a-f]+ +\(STRSZ\).*
+ 0x[0-9a-f]+ +\(SYMENT\).*
+ 0x[0-9a-f]+ +\(PLTGOT\).*
+ 0x[0-9a-f]+ +\(PLTRELSZ\).*
+ 0x[0-9a-f]+ +\(PLTREL\).*
+ 0x[0-9a-f]+ +\(JMPREL\).*
+ 0x[0-9a-f]+ +\(TLSDESC_PLT\) +0x480
+ 0x[0-9a-f]+ +\(TLSDESC_GOT\) +0x101348
+ 0x[0-9a-f]+ +\(RELA\).*
+ 0x[0-9a-f]+ +\(RELASZ\).*
+ 0x[0-9a-f]+ +\(RELAENT\).*
+ 0x[0-9a-f]+ +\(FLAGS\).*
+ 0x[0-9a-f]+ +\(NULL\).*
+
+Relocation section '.rela.dyn' at offset 0x[0-9a-f]+ contains 8 entries:
+ +Offset +Info +Type +Symbol's Value +Symbol's Name \+ Addend
+0+101308  0+12 R_X86_64_TPOFF64 +0+24
+0+101310  0+12 R_X86_64_TPOFF64 +0+30
+0+101318  0+12 R_X86_64_TPOFF64 +0+64
+0+101328  0+12 R_X86_64_TPOFF64 +0+50
+0+101330  0+12 R_X86_64_TPOFF64 +0+70
+0+101340  0+12 R_X86_64_TPOFF64 +0+44
+0+101320  0+700000012 R_X86_64_TPOFF64 +0+10 sg5 \+ 0
+0+101338  0+b00000012 R_X86_64_TPOFF64 +0+4 sg2 \+ 0
+
+Relocation section '.rela.plt' at offset 0x[0-9a-f]+ contains 5 entries:
+ +Offset +Info +Type +Symbol's Value  Symbol's Name \+ Addend
+0+101398  0+80000001c R_X86_64_TLSDESC +0+ sg1 \+ 0
+0+101368  0+1c R_X86_64_TLSDESC +0+20
+0+1013a8  0+1c R_X86_64_TLSDESC +0+40
+0+101378  0+1c R_X86_64_TLSDESC +0+60
+0+101388  0+1c R_X86_64_TLSDESC +0+
+
+Symbol table '.dynsym' contains 16 entries:
+ +Num: +Value +Size Type +Bind +Vis +Ndx Name
+ +[0-9]+: 0+ +0 NOTYPE  LOCAL  DEFAULT  UND *
+ +[0-9]+: [0-9a-f]+ +0 SECTION LOCAL  DEFAULT +7 *
+ +[0-9]+: [0-9a-f]+ +0 SECTION LOCAL  DEFAULT +8 *
+ +[0-9]+: [0-9a-f]+ +0 SECTION LOCAL  DEFAULT +9 *
+ +[0-9]+: 0+1c +0 TLS +GLOBAL DEFAULT +8 sg8
+ +[0-9]+: 0+8 +0 TLS +GLOBAL DEFAULT +8 sg3
+ +[0-9]+: 0+c +0 TLS +GLOBAL DEFAULT +8 sg4
+ +[0-9]+: 0+10 +0 TLS +GLOBAL DEFAULT +8 sg5
+ +[0-9]+: 0+ +0 TLS +GLOBAL DEFAULT +8 sg1
+ +[0-9]+: 0+1000 +0 FUNC +GLOBAL DEFAULT +7 fn1
+ +[0-9]+: [0-9a-f]+ +0 NOTYPE  GLOBAL DEFAULT  ABS __bss_start
+ +[0-9]+: 0+4 +0 TLS +GLOBAL DEFAULT +8 sg2
+ +[0-9]+: 0+14 +0 TLS +GLOBAL DEFAULT +8 sg6
+ +[0-9]+: 0+18 +0 TLS +GLOBAL DEFAULT +8 sg7
+ +[0-9]+: [0-9a-f]+ +0 NOTYPE  GLOBAL DEFAULT  ABS _edata
+ +[0-9]+: [0-9a-f]+ +0 NOTYPE  GLOBAL DEFAULT  ABS _end
+
+Symbol table '.symtab' contains 55 entries:
+ +Num: +Value +Size Type +Bind +Vis +Ndx Name
+ +[0-9]+: 0+ +0 NOTYPE  LOCAL  DEFAULT  UND *
+ +[0-9]+: [0-9a-f]+ +0 SECTION LOCAL  DEFAULT +1 *
+ +[0-9]+: [0-9a-f]+ +0 SECTION LOCAL  DEFAULT +2 *
+ +[0-9]+: [0-9a-f]+ +0 SECTION LOCAL  DEFAULT +3 *
+ +[0-9]+: [0-9a-f]+ +0 SECTION LOCAL  DEFAULT +4 *
+ +[0-9]+: [0-9a-f]+ +0 SECTION LOCAL  DEFAULT +5 *
+ +[0-9]+: [0-9a-f]+ +0 SECTION LOCAL  DEFAULT +6 *
+ +[0-9]+: [0-9a-f]+ +0 SECTION LOCAL  DEFAULT +7 *
+ +[0-9]+: [0-9a-f]+ +0 SECTION LOCAL  DEFAULT +8 *
+ +[0-9]+: [0-9a-f]+ +0 SECTION LOCAL  DEFAULT +9 *
+ +[0-9]+: [0-9a-f]+ +0 SECTION LOCAL  DEFAULT +10 *
+ +[0-9]+: [0-9a-f]+ +0 SECTION LOCAL  DEFAULT +11 *
+ +[0-9]+: [0-9a-f]+ +0 SECTION LOCAL  DEFAULT +12 *
+ +[0-9]+: [0-9a-f]+ +0 SECTION LOCAL  DEFAULT +13 *
+ +[0-9]+: [0-9a-f]+ +0 SECTION LOCAL  DEFAULT +14 *
+ +[0-9]+: [0-9a-f]+ +0 SECTION LOCAL  DEFAULT +15 *
+ +[0-9]+: 0+20 +0 TLS +LOCAL  DEFAULT +8 sl1
+ +[0-9]+: 0+24 +0 TLS +LOCAL  DEFAULT +8 sl2
+ +[0-9]+: 0+28 +0 TLS +LOCAL  DEFAULT +8 sl3
+ +[0-9]+: 0+2c +0 TLS +LOCAL  DEFAULT +8 sl4
+ +[0-9]+: 0+30 +0 TLS +LOCAL  DEFAULT +8 sl5
+ +[0-9]+: 0+34 +0 TLS +LOCAL  DEFAULT +8 sl6
+ +[0-9]+: 0+38 +0 TLS +LOCAL  DEFAULT +8 sl7
+ +[0-9]+: 0+3c +0 TLS +LOCAL  DEFAULT +8 sl8
+ +[0-9]+: 0+60 +0 TLS +LOCAL  HIDDEN +9 sH1
+ +[0-9]+: 0+ +0 TLS +LOCAL  HIDDEN +8 _TLS_MODULE_BASE_
+ +[0-9]+: 0+1011b8 +0 OBJECT  LOCAL  HIDDEN  ABS _DYNAMIC
+ +[0-9]+: 0+48 +0 TLS +LOCAL  HIDDEN +8 sh3
+ +[0-9]+: 0+64 +0 TLS +LOCAL  HIDDEN +9 sH2
+ +[0-9]+: 0+78 +0 TLS +LOCAL  HIDDEN +9 sH7
+ +[0-9]+: 0+58 +0 TLS +LOCAL  HIDDEN +8 sh7
+ +[0-9]+: 0+5c +0 TLS +LOCAL  HIDDEN +8 sh8
+ +[0-9]+: 0+6c +0 TLS +LOCAL  HIDDEN +9 sH4
+ +[0-9]+: 0+4c +0 TLS +LOCAL  HIDDEN +8 sh4
+ +[0-9]+: 0+68 +0 TLS +LOCAL  HIDDEN +9 sH3
+ +[0-9]+: 0+50 +0 TLS +LOCAL  HIDDEN +8 sh5
+ +[0-9]+: 0+70 +0 TLS +LOCAL  HIDDEN +9 sH5
+ +[0-9]+: 0+74 +0 TLS +LOCAL  HIDDEN +9 sH6
+ +[0-9]+: 0+7c +0 TLS +LOCAL  HIDDEN +9 sH8
+ +[0-9]+: 0+40 +0 TLS +LOCAL  HIDDEN +8 sh1
+ +[0-9]+: 0+101350 +0 OBJECT  LOCAL  HIDDEN  ABS _GLOBAL_OFFSET_TABLE_
+ +[0-9]+: 0+44 +0 TLS +LOCAL  HIDDEN +8 sh2
+ +[0-9]+: 0+54 +0 TLS +LOCAL  HIDDEN +8 sh6
+ +[0-9]+: 0+1c +0 TLS +GLOBAL DEFAULT +8 sg8
+ +[0-9]+: 0+8 +0 TLS +GLOBAL DEFAULT +8 sg3
+ +[0-9]+: 0+c +0 TLS +GLOBAL DEFAULT +8 sg4
+ +[0-9]+: 0+10 +0 TLS +GLOBAL DEFAULT +8 sg5
+ +[0-9]+: 0+ +0 TLS +GLOBAL DEFAULT +8 sg1
+ +[0-9]+: 0+1000 +0 FUNC +GLOBAL DEFAULT +7 fn1
+ +[0-9]+: [0-9a-f]+ +0 NOTYPE  GLOBAL DEFAULT  ABS __bss_start
+ +[0-9]+: 0+4 +0 TLS +GLOBAL DEFAULT +8 sg2
+ +[0-9]+: 0+14 +0 TLS +GLOBAL DEFAULT +8 sg6
+ +[0-9]+: 0+18 +0 TLS +GLOBAL DEFAULT +8 sg7
+ +[0-9]+: [0-9a-f]+ +0 NOTYPE  GLOBAL DEFAULT  ABS _edata
+ +[0-9]+: [0-9a-f]+ +0 NOTYPE  GLOBAL DEFAULT  ABS _end
Index: ld/testsuite/ld-x86-64/tlsdesc.s
===================================================================
RCS file: ld/testsuite/ld-x86-64/tlsdesc.s
diff -N ld/testsuite/ld-x86-64/tlsdesc.s
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ ld/testsuite/ld-x86-64/tlsdesc.s 15 Sep 2005 22:39:27 -0000
@@ -0,0 +1,157 @@
+	/* Force .data aligned to 4K, so .got very likely gets at 0x102190
+	   (0x60 bytes .tdata and 0x130 bytes .dynamic)  */
+        .data
+        .balign 4096
+	.section ".tdata", "awT", @progbits
+	.globl sg1, sg2, sg3, sg4, sg5, sg6, sg7, sg8
+	.globl sh1, sh2, sh3, sh4, sh5, sh6, sh7, sh8
+	.hidden sh1, sh2, sh3, sh4, sh5, sh6, sh7, sh8
+sg1:	.long 17
+sg2:	.long 18
+sg3:	.long 19
+sg4:	.long 20
+sg5:	.long 21
+sg6:	.long 22
+sg7:	.long 23
+sg8:	.long 24
+sl1:	.long 65
+sl2:	.long 66
+sl3:	.long 67
+sl4:	.long 68
+sl5:	.long 69
+sl6:	.long 70
+sl7:	.long 71
+sl8:	.long 72
+sh1:	.long 257
+sh2:	.long 258
+sh3:	.long 259
+sh4:	.long 260
+sh5:	.long 261
+sh6:	.long 262
+sh7:	.long 263
+sh8:	.long 264
+	/* Force .text aligned to 4K, so it very likely gets at 0x1000.  */
+	.text
+	.balign	4096
+	.globl	fn1
+	.type	fn1,@function
+fn1:
+	pushq	%rbp
+	movq	%rsp, %rbp
+	nop;nop;nop;nop
+
+	/* GD */
+	leaq	sg1@tlsdesc(%rip), %rax
+	call	*sg1@tlscall(%rax)
+	nop;nop;nop;nop
+
+	/* GD -> IE because variable is referenced through IE too */
+	leaq	sg2@tlsdesc(%rip), %rax
+	call	*sg2@tlscall(%rax)
+	nop;nop;nop;nop
+
+	/* GD against local variable */
+	leaq	sl1@tlsdesc(%rip), %rax
+	call	*sl1@tlscall(%rax)
+	nop;nop;nop;nop
+
+	/* GD -> IE against local variable referenced through IE too */
+	leaq	sl2@tlsdesc(%rip), %rax
+	call	*sl2@tlscall(%rax)
+	nop;nop;nop;nop
+
+	/* GD against hidden and local variable */
+	leaq	sh1@tlsdesc(%rip), %rax
+	call	*sh1@tlscall(%rax)
+	nop;nop;nop;nop
+
+	/* GD -> IE against hidden and local variable referenced through
+	   IE too */
+	leaq	sh2@tlsdesc(%rip), %rax
+	call	*sh2@tlscall(%rax)
+	nop;nop;nop;nop
+
+	/* GD against hidden but not local variable */
+	leaq	sH1@tlsdesc(%rip), %rax
+	call	*sH1@tlscall(%rax)
+	nop;nop;nop;nop
+
+	/* GD -> IE against hidden but not local variable referenced through
+	   IE too */
+	leaq	sH2@tlsdesc(%rip), %rax
+	call	*sH2@tlscall(%rax)
+	nop;nop;nop;nop
+
+	/* LD */
+	leaq	_TLS_MODULE_BASE_@tlsdesc(%rip), %rax
+	call	*_TLS_MODULE_BASE_@tlscall(%rax)
+	nop;nop
+	leaq	sl1@dtpoff(%rax), %rdx
+	nop;nop
+	leaq	2+sl2@dtpoff(%rax), %r9
+	nop;nop;nop;nop
+
+	/* LD against hidden and local variables */
+	leaq	sh1@dtpoff(%rax), %rdx
+	nop;nop
+	leaq	sh2@dtpoff+3(%rax), %rcx
+	nop;nop;nop;nop
+
+	/* LD against hidden but not local variables */
+	leaq	sH1@dtpoff(%rax), %r12
+	nop;nop
+	leaq	sH2@dtpoff+1(%rax), %rcx
+	nop;nop
+
+	/* IE against global var  */
+	movq	%fs:0, %rcx
+	nop;nop
+	addq	sg2@gottpoff(%rip), %rcx
+	nop;nop;nop;nop
+
+	/* IE against local var  */
+	movq	%fs:0, %r14
+	nop;nop
+	addq	sl2@gottpoff(%rip), %r14
+	nop;nop;nop;nop
+
+	/* IE against hidden and local var  */
+	movq	%fs:0, %rcx
+	nop;nop
+	addq	sh2@gottpoff(%rip), %rcx
+	nop;nop;nop;nop
+
+	/* IE against hidden but not local var  */
+	movq	%fs:0, %rcx
+	nop;nop
+	addq	sH2@gottpoff(%rip), %rcx
+	nop;nop;nop;nop
+
+	/* Direct access through %fs  */
+
+	/* IE against global var  */
+	movq	sg5@gottpoff(%rip), %rcx
+	nop;nop
+	movq	%fs:(%rcx), %rdx
+	nop;nop;nop;nop
+
+	/* IE against local var  */
+	movq	sl5@gottpoff(%rip), %r10
+	nop;nop
+	movq	%fs:(%r10), %r12
+	nop;nop;nop;nop
+
+	/* IE against hidden and local var  */
+	movq	sh5@gottpoff(%rip), %rdx
+	nop;nop
+	movq	%fs:(%rdx), %rdx
+	nop;nop;nop;nop
+
+	/* IE against hidden but not local var  */
+	movq	sH5@gottpoff(%rip), %rcx
+	nop;nop
+	movq	%fs:(%rcx), %rdx
+	nop;nop;nop;nop
+
+	leave
+	ret
Index: ld/testsuite/ld-x86-64/tlsdesc.sd
===================================================================
RCS file: ld/testsuite/ld-x86-64/tlsdesc.sd
diff -N ld/testsuite/ld-x86-64/tlsdesc.sd
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ ld/testsuite/ld-x86-64/tlsdesc.sd 15 Sep 2005 22:39:27 -0000
@@ -0,0 +1,23 @@
+#source: tlsdesc.s
+#source: tlspic2.s
+#as: --64
+#ld: -shared -melf_x86_64
+#objdump: -s -j.got -j.got.plt
+#target: x86_64-*-*
+
+.*: +file format elf64-x86-64
+
+Contents of section \.got:
+ 101308 00000000 00000000 00000000 00000000  .*
+ 101318 00000000 00000000 00000000 00000000  .*
+ 101328 00000000 00000000 00000000 00000000  .*
+ 101338 00000000 00000000 00000000 00000000  .*
+ 101348 00000000 00000000                    .*
+Contents of section \.got\.plt:
+ 101350 b8111000 00000000 00000000 00000000  .*
+ 101360 00000000 00000000 00000000 00000000  .*
+ 101370 00000000 00000000 00000000 00000000  .*
+ 101380 00000000 00000000 00000000 00000000  .*
+ 101390 00000000 00000000 00000000 00000000  .*
+ 1013a0 00000000 00000000 00000000 00000000  .*
+ 1013b0 00000000 00000000                    .*
Index: ld/testsuite/ld-x86-64/tlsdesc.td
===================================================================
RCS file: ld/testsuite/ld-x86-64/tlsdesc.td
diff -N ld/testsuite/ld-x86-64/tlsdesc.td
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ ld/testsuite/ld-x86-64/tlsdesc.td 15 Sep 2005 22:39:27 -0000
@@ -0,0 +1,16 @@
+#source: tlsdesc.s
+#source: tlspic2.s
+#as: --64
+#ld: -shared -melf_x86_64
+#objdump: -sj.tdata
+#target: x86_64-*-*
+
+.*: +file format elf64-x86-64
+
+Contents of section .tdata:
+ 101154 11000000 12000000 13000000 14000000  .*
+ 101164 15000000 16000000 17000000 18000000  .*
+ 101174 41000000 42000000 43000000 44000000  .*
+ 101184 45000000 46000000 47000000 48000000  .*
+ 101194 01010000 02010000 03010000 04010000  .*
+ 1011a4 05010000 06010000 07010000 08010000  .*
Index: ld/testsuite/ld-x86-64/tlsgdesc.dd
===================================================================
RCS file: ld/testsuite/ld-x86-64/tlsgdesc.dd
diff -N ld/testsuite/ld-x86-64/tlsgdesc.dd
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ ld/testsuite/ld-x86-64/tlsgdesc.dd 15 Sep 2005 22:39:27 -0000
@@ -0,0 +1,165 @@
+#source: tlsgdesc.s
+#as: --64
+#ld: -shared -melf_x86_64
+#objdump: -drj.text
+#target: x86_64-*-*
+
+.*: +file format elf64-x86-64
+
+Disassembly of section .text:
+
+0+[0-9a-f]+ <fc1>:
+ +[0-9a-f]+:	55[ 	]+push   %rbp
+ +[0-9a-f]+:	48 89 e5[ 	]+mov    %rsp,%rbp
+ +[0-9a-f]+:	90[ 	]+nop *
+ +[0-9a-f]+:	90[ 	]+nop *
+ +[0-9a-f]+:	90[ 	]+nop *
+ +[0-9a-f]+:	90[ 	]+nop *
+# IE
+ +[0-9a-f]+:	64 48 8b 0c 25 00 00[ 	]+mov    %fs:0x0,%rcx
+ +[0-9a-f]+:	00 00 *
+ +[0-9a-f]+:	90[ 	]+nop *
+ +[0-9a-f]+:	90[ 	]+nop *
+ +[0-9a-f]+:	48 03 0d 5e 02 10 00[ 	]+add    1049182\(%rip\),%rcx +# 100660 <.*>
+#				-> R_X86_64_TPOFF64	sG3
+ +[0-9a-f]+:	90[ 	]+nop *
+ +[0-9a-f]+:	90[ 	]+nop *
+ +[0-9a-f]+:	90[ 	]+nop *
+ +[0-9a-f]+:	90[ 	]+nop *
+# IE
+ +[0-9a-f]+:	64 48 8b 0c 25 00 00[ 	]+mov    %fs:0x0,%rcx
+ +[0-9a-f]+:	00 00 *
+ +[0-9a-f]+:	90[ 	]+nop *
+ +[0-9a-f]+:	90[ 	]+nop *
+ +[0-9a-f]+:	48 03 0d 68 02 10 00[ 	]+add    1049192\(%rip\),%rcx +# 100680 <.*>
+#				-> R_X86_64_TPOFF64	sG4
+ +[0-9a-f]+:	90[ 	]+nop *
+ +[0-9a-f]+:	90[ 	]+nop *
+ +[0-9a-f]+:	90[ 	]+nop *
+ +[0-9a-f]+:	90[ 	]+nop *
+# GD, gd first
+ +[0-9a-f]+:	66 48 8d 3d 6c 02 10[ 	]+lea    1049196\(%rip\),%rdi +# 100690 <.*>
+ +[0-9a-f]+:	00 *
+#				-> R_X86_64_DTPMOD64	sG1
+ +[0-9a-f]+:	66[ 	]+data16
+ +[0-9a-f]+:	66[ 	]+data16
+ +[0-9a-f]+:	48 e8 9c ff ff ff[ 	]+rex64 callq  [0-9a-f]+ <.*>
+#				-> R_X86_64_JUMP_SLOT	__tls_get_addr
+ +[0-9a-f]+:	90[ 	]+nop *
+ +[0-9a-f]+:	90[ 	]+nop *
+ +[0-9a-f]+:	90[ 	]+nop *
+ +[0-9a-f]+:	90[ 	]+nop *
+ +[0-9a-f]+:	48 8d 05 a1 02 10 00[ 	]+lea    1049249\(%rip\),%rax +# 1006d8 <.*>
+#				-> R_X86_64_TLSDESC	sG1
+ +[0-9a-f]+:	ff 10[ 	]+callq  \*\(%rax\)
+ +[0-9a-f]+:	90[ 	]+nop *
+ +[0-9a-f]+:	90[ 	]+nop *
+ +[0-9a-f]+:	90[ 	]+nop *
+ +[0-9a-f]+:	90[ 	]+nop *
+# GD, desc first
+ +[0-9a-f]+:	48 8d 05 84 02 10 00[ 	]+lea    1049220\(%rip\),%rax +# 1006c8 <.*>
+#				-> R_X86_64_TLSDESC	sG2
+ +[0-9a-f]+:	ff 10[ 	]+callq  \*\(%rax\)
+ +[0-9a-f]+:	90[ 	]+nop *
+ +[0-9a-f]+:	90[ 	]+nop *
+ +[0-9a-f]+:	90[ 	]+nop *
+ +[0-9a-f]+:	90[ 	]+nop *
+ +[0-9a-f]+:	66 48 8d 3d 1e 02 10[ 	]+lea    1049118\(%rip\),%rdi +# 100670 <.*>
+ +[0-9a-f]+:	00 *
+#				-> R_X86_64_DTPMOD64	sG2
+ +[0-9a-f]+:	66[ 	]+data16
+ +[0-9a-f]+:	66[ 	]+data16
+ +[0-9a-f]+:	48 e8 6e ff ff ff[ 	]+rex64 callq  [0-9a-f]+ <.*>
+#				-> R_X86_64_JUMP_SLOT	__tls_get_addr
+ +[0-9a-f]+:	90[ 	]+nop *
+ +[0-9a-f]+:	90[ 	]+nop *
+ +[0-9a-f]+:	90[ 	]+nop *
+ +[0-9a-f]+:	90[ 	]+nop *
+# GD -> IE, gd first, after IE use
+ +[0-9a-f]+:	64 48 8b 04 25 00 00[ 	]+mov    %fs:0x0,%rax
+ +[0-9a-f]+:	00 00 *
+ +[0-9a-f]+:	48 03 05 f2 01 10 00[ 	]+add    1049074\(%rip\),%rax +# 100660 <.*>
+#				-> R_X86_64_TPOFF64	sG3
+ +[0-9a-f]+:	90[ 	]+nop *
+ +[0-9a-f]+:	90[ 	]+nop *
+ +[0-9a-f]+:	90[ 	]+nop *
+ +[0-9a-f]+:	90[ 	]+nop *
+ +[0-9a-f]+:	48 8b 05 e7 01 10 00[ 	]+mov    1049063\(%rip\),%rax +# 100660 <.*>
+#				-> R_X86_64_TPOFF64	sG3
+ +[0-9a-f]+:	48 90[ 	]+rex64 nop *
+ +[0-9a-f]+:	90[ 	]+nop *
+ +[0-9a-f]+:	90[ 	]+nop *
+ +[0-9a-f]+:	90[ 	]+nop *
+ +[0-9a-f]+:	90[ 	]+nop *
+# GD -> IE, desc first, after IE use
+ +[0-9a-f]+:	48 8b 05 fa 01 10 00[ 	]+mov    1049082\(%rip\),%rax +# 100680 <.*>
+#				-> R_X86_64_TPOFF64	sG4
+ +[0-9a-f]+:	48 90[ 	]+rex64 nop *
+ +[0-9a-f]+:	90[ 	]+nop *
+ +[0-9a-f]+:	90[ 	]+nop *
+ +[0-9a-f]+:	90[ 	]+nop *
+ +[0-9a-f]+:	90[ 	]+nop *
+ +[0-9a-f]+:	64 48 8b 04 25 00 00[ 	]+mov    %fs:0x0,%rax
+ +[0-9a-f]+:	00 00 *
+ +[0-9a-f]+:	48 03 05 e4 01 10 00[ 	]+add    1049060\(%rip\),%rax +# 100680 <.*>
+#				-> R_X86_64_TPOFF64	sG4
+ +[0-9a-f]+:	90[ 	]+nop *
+ +[0-9a-f]+:	90[ 	]+nop *
+ +[0-9a-f]+:	90[ 	]+nop *
+ +[0-9a-f]+:	90[ 	]+nop *
+# GD -> IE, gd first, before IE use
+ +[0-9a-f]+:	64 48 8b 04 25 00 00[ 	]+mov    %fs:0x0,%rax
+ +[0-9a-f]+:	00 00 *
+ +[0-9a-f]+:	48 03 05 b8 01 10 00[ 	]+add    1049016\(%rip\),%rax +# 100668 <.*>
+#				-> R_X86_64_TPOFF64	sG5
+ +[0-9a-f]+:	90[ 	]+nop *
+ +[0-9a-f]+:	90[ 	]+nop *
+ +[0-9a-f]+:	90[ 	]+nop *
+ +[0-9a-f]+:	90[ 	]+nop *
+ +[0-9a-f]+:	48 8b 05 ad 01 10 00[ 	]+mov    1049005\(%rip\),%rax +# 100668 <.*>
+#				-> R_X86_64_TPOFF64	sG5
+ +[0-9a-f]+:	48 90[ 	]+rex64 nop *
+ +[0-9a-f]+:	90[ 	]+nop *
+ +[0-9a-f]+:	90[ 	]+nop *
+ +[0-9a-f]+:	90[ 	]+nop *
+ +[0-9a-f]+:	90[ 	]+nop *
+# GD -> IE, desc first, before IE use
+ +[0-9a-f]+:	48 8b 05 c0 01 10 00[ 	]+mov    1049024\(%rip\),%rax +# 100688 <.*>
+#				-> R_X86_64_TPOFF64	sG6
+ +[0-9a-f]+:	48 90[ 	]+rex64 nop *
+ +[0-9a-f]+:	90[ 	]+nop *
+ +[0-9a-f]+:	90[ 	]+nop *
+ +[0-9a-f]+:	90[ 	]+nop *
+ +[0-9a-f]+:	90[ 	]+nop *
+ +[0-9a-f]+:	64 48 8b 04 25 00 00[ 	]+mov    %fs:0x0,%rax
+ +[0-9a-f]+:	00 00 *
+ +[0-9a-f]+:	48 03 05 aa 01 10 00[ 	]+add    1049002\(%rip\),%rax +# 100688 <.*>
+#				-> R_X86_64_TPOFF64	sG6
+ +[0-9a-f]+:	90[ 	]+nop *
+ +[0-9a-f]+:	90[ 	]+nop *
+ +[0-9a-f]+:	90[ 	]+nop *
+ +[0-9a-f]+:	90[ 	]+nop *
+# IE
+ +[0-9a-f]+:	64 48 8b 0c 25 00 00[ 	]+mov    %fs:0x0,%rcx
+ +[0-9a-f]+:	00 00 *
+ +[0-9a-f]+:	90[ 	]+nop *
+ +[0-9a-f]+:	90[ 	]+nop *
+ +[0-9a-f]+:	48 03 0d 74 01 10 00[ 	]+add    1048948\(%rip\),%rcx +# 100668 <.*>
+#				-> R_X86_64_TPOFF64	sG5
+ +[0-9a-f]+:	90[ 	]+nop *
+ +[0-9a-f]+:	90[ 	]+nop *
+ +[0-9a-f]+:	90[ 	]+nop *
+ +[0-9a-f]+:	90[ 	]+nop *
+# IE
+ +[0-9a-f]+:	64 48 8b 0c 25 00 00[ 	]+mov    %fs:0x0,%rcx
+ +[0-9a-f]+:	00 00 *
+ +[0-9a-f]+:	90[ 	]+nop *
+ +[0-9a-f]+:	90[ 	]+nop *
+ +[0-9a-f]+:	48 03 0d 7e 01 10 00[ 	]+add    1048958\(%rip\),%rcx +# 100688 <.*>
+#				-> R_X86_64_TPOFF64	sG6
+ +[0-9a-f]+:	90[ 	]+nop *
+ +[0-9a-f]+:	90[ 	]+nop *
+ +[0-9a-f]+:	90[ 	]+nop *
+ +[0-9a-f]+:	90[ 	]+nop *
+ +[0-9a-f]+:	c9[ 	]+leaveq *
+ +[0-9a-f]+:	c3[ 	]+retq *
Index: ld/testsuite/ld-x86-64/tlsgdesc.rd
===================================================================
RCS file: ld/testsuite/ld-x86-64/tlsgdesc.rd
diff -N ld/testsuite/ld-x86-64/tlsgdesc.rd
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ ld/testsuite/ld-x86-64/tlsgdesc.rd 15 Sep 2005 22:39:29 -0000
@@ -0,0 +1,107 @@
+#source: tlsgdesc.s
+#as: --64
+#ld: -shared -melf64_x86_64
+#readelf: -WSsrl
+#target: x86_64-*-*
+
+There are [0-9]+ section headers, starting at offset 0x.*:
+
+Section Headers:
+  \[Nr\] Name +Type +Address +Off +Size +ES Flg Lk Inf Al
+  \[ 0\] +NULL +0+ 0+ 0+ 0+ +0 +0 +0
+  \[ 1\] \.hash +.*
+  \[ 2\] \.dynsym +.*
+  \[ 3\] \.dynstr +.*
+  \[ 4\] \.rela.dyn +.*
+  \[ 5\] \.rela.plt +.*
+  \[ 6\] \.plt +.*
+  \[ 7\] \.text +.*
+  \[ 8\] \.dynamic +.*
+  \[ 9\] \.got +.*
+  \[10\] \.got.plt +.*
+  \[11\] \.shstrtab +.*
+  \[12\] \.symtab +.*
+  \[13\] \.strtab +.*
+Key to Flags:
+.*
+.*
+.*
+
+Elf file type is DYN \(Shared object file\)
+Entry point 0x[0-9a-f]+
+There are [0-9]+ program headers, starting at offset [0-9]+
+
+Program Headers:
+  Type +Offset +VirtAddr +PhysAddr +FileSiz +MemSiz +Flg Align
+  LOAD.*
+  LOAD.*
+  DYNAMIC.*
+
+ Section to Segment mapping:
+  Segment Sections...
+   00 +.hash .dynsym .dynstr .rela.dyn .rela.plt .plt .text *
+   01 +.dynamic .got .got.plt *
+   02 +.dynamic *
+
+Relocation section '.rela.dyn' at offset 0x[0-9a-f]+ contains 8 entries:
+ +Offset +Info +Type +Symbol's Value  Symbol's Name \+ Addend
+[0-9a-f]+  0+200000012 R_X86_64_TPOFF64 +0+ sG3 \+ 0
+[0-9a-f]+  0+300000012 R_X86_64_TPOFF64 +0+ sG5 \+ 0
+[0-9a-f]+  0+400000010 R_X86_64_DTPMOD64 +0+ sG2 \+ 0
+[0-9a-f]+  0+400000011 R_X86_64_DTPOFF64 +0+ sG2 \+ 0
+[0-9a-f]+  0+500000012 R_X86_64_TPOFF64 +0+ sG4 \+ 0
+[0-9a-f]+  0+800000012 R_X86_64_TPOFF64 +0+ sG6 \+ 0
+[0-9a-f]+  0+a00000010 R_X86_64_DTPMOD64 +0+ sG1 \+ 0
+[0-9a-f]+  0+a00000011 R_X86_64_DTPOFF64 +0+ sG1 \+ 0
+
+Relocation section '.rela.plt' at offset 0x[0-9a-f]+ contains 3 entries:
+ +Offset +Info +Type +Symbol's Value  Symbol's Name \+ Addend
+[0-9a-f]+  0+600000007 R_X86_64_JUMP_SLOT +0+ __tls_get_addr \+ 0
+[0-9a-f]+  0+a0000001c R_X86_64_TLSDESC +0+ sG1 \+ 0
+[0-9a-f]+  0+40000001c R_X86_64_TLSDESC +0+ sG2 \+ 0
+
+Symbol table '.dynsym' contains 13 entries:
+ +Num: +Value +Size Type +Bind +Vis +Ndx Name
+ +[0-9]+: 0+ +0 NOTYPE  LOCAL  DEFAULT  UND *
+ +[0-9]+: [0-9a-f]+ +0 SECTION LOCAL  DEFAULT +7 *
+ +[0-9]+: 0+ +0 TLS +GLOBAL DEFAULT  UND sG3
+ +[0-9]+: 0+ +0 TLS +GLOBAL DEFAULT  UND sG5
+ +[0-9]+: 0+ +0 TLS +GLOBAL DEFAULT  UND sG2
+ +[0-9]+: 0+ +0 TLS +GLOBAL DEFAULT  UND sG4
+ +[0-9]+: 0+ +0 NOTYPE  GLOBAL DEFAULT  UND __tls_get_addr
+ +[0-9]+: [0-9a-f]+ +0 NOTYPE  GLOBAL DEFAULT  ABS __bss_start
+ +[0-9]+: 0+ +0 TLS +GLOBAL DEFAULT  UND sG6
+ +[0-9]+: [0-9a-f]+ +0 FUNC +GLOBAL DEFAULT +7 fc1
+ +[0-9]+: 0+ +0 TLS +GLOBAL DEFAULT  UND sG1
+ +[0-9]+: [0-9a-f]+ +0 NOTYPE  GLOBAL DEFAULT  ABS _edata
+ +[0-9]+: [0-9a-f]+ +0 NOTYPE  GLOBAL DEFAULT  ABS _end
+
+Symbol table '.symtab' contains 27 entries:
+ +Num: +Value +Size Type +Bind +Vis +Ndx Name
+ +[0-9]+: 0+ +0 NOTYPE  LOCAL  DEFAULT  UND *
+ +[0-9]+: [0-9a-f]+ +0 SECTION LOCAL  DEFAULT +1 *
+ +[0-9]+: [0-9a-f]+ +0 SECTION LOCAL  DEFAULT +2 *
+ +[0-9]+: [0-9a-f]+ +0 SECTION LOCAL  DEFAULT +3 *
+ +[0-9]+: [0-9a-f]+ +0 SECTION LOCAL  DEFAULT +4 *
+ +[0-9]+: [0-9a-f]+ +0 SECTION LOCAL  DEFAULT +5 *
+ +[0-9]+: [0-9a-f]+ +0 SECTION LOCAL  DEFAULT +6 *
+ +[0-9]+: [0-9a-f]+ +0 SECTION LOCAL  DEFAULT +7 *
+ +[0-9]+: [0-9a-f]+ +0 SECTION LOCAL  DEFAULT +8 *
+ +[0-9]+: [0-9a-f]+ +0 SECTION LOCAL  DEFAULT +9 *
+ +[0-9]+: [0-9a-f]+ +0 SECTION LOCAL  DEFAULT +10 *
+ +[0-9]+: [0-9a-f]+ +0 SECTION LOCAL  DEFAULT +11 *
+ +[0-9]+: [0-9a-f]+ +0 SECTION LOCAL  DEFAULT +12 *
+ +[0-9]+: [0-9a-f]+ +0 SECTION LOCAL  DEFAULT +13 *
+ +[0-9]+: [0-9a-f]+ +0 OBJECT  LOCAL  HIDDEN  ABS _DYNAMIC
+ +[0-9]+: [0-9a-f]+ +0 OBJECT  LOCAL  HIDDEN  ABS _GLOBAL_OFFSET_TABLE_
+ +[0-9]+: 0+ +0 TLS +GLOBAL DEFAULT  UND sG3
+ +[0-9]+: 0+ +0 TLS +GLOBAL DEFAULT  UND sG5
+ +[0-9]+: 0+ +0 TLS +GLOBAL DEFAULT  UND sG2
+ +[0-9]+: 0+ +0 TLS +GLOBAL DEFAULT  UND sG4
+ +[0-9]+: 0+ +0 NOTYPE  GLOBAL DEFAULT  UND __tls_get_addr
+ +[0-9]+: [0-9a-f]+ +0 NOTYPE  GLOBAL DEFAULT  ABS __bss_start
+ +[0-9]+: 0+ +0 TLS +GLOBAL DEFAULT  UND sG6
+ +[0-9]+: [0-9a-f]+ +0 FUNC +GLOBAL DEFAULT +7 fc1
+ +[0-9]+: 0+ +0 TLS +GLOBAL DEFAULT  UND sG1
+ +[0-9]+: [0-9a-f]+ +0 NOTYPE  GLOBAL DEFAULT  ABS _edata
+ +[0-9]+: [0-9a-f]+ +0 NOTYPE  GLOBAL DEFAULT  ABS _end
Index: ld/testsuite/ld-x86-64/tlsgdesc.s
===================================================================
RCS file: ld/testsuite/ld-x86-64/tlsgdesc.s
diff -N ld/testsuite/ld-x86-64/tlsgdesc.s
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ ld/testsuite/ld-x86-64/tlsgdesc.s 15 Sep 2005 22:39:29 -0000
@@ -0,0 +1,106 @@
+	.text
+	.globl	fc1
+	.type	fc1,@function
+fc1:
+	pushq	%rbp
+	movq	%rsp, %rbp
+	nop;nop;nop;nop
+
+	/* IE against global var.  */
+	movq	%fs:0, %rcx
+	nop;nop
+	addq	sG3@gottpoff(%rip), %rcx
+	nop;nop;nop;nop
+
+	/* IE against global var.  */
+	movq	%fs:0, %rcx
+	nop;nop
+	addq	sG4@gottpoff(%rip), %rcx
+	nop;nop;nop;nop
+
+	/* GD, gd first.  */
+	.byte	0x66
+	leaq	sG1@tlsgd(%rip), %rdi
+	.word	0x6666
+	rex64
+	call	__tls_get_addr@plt
+	nop;nop;nop;nop
+	
+	leaq	sG1@tlsdesc(%rip), %rax
+	call	*sG1@tlscall(%rax)
+	nop;nop;nop;nop
+
+	/* GD, desc first.  */
+	leaq	sG2@tlsdesc(%rip), %rax
+	call	*sG2@tlscall(%rax)
+	nop;nop;nop;nop
+
+	.byte	0x66
+	leaq	sG2@tlsgd(%rip), %rdi
+	.word	0x6666
+	rex64
+	call	__tls_get_addr@plt
+	nop;nop;nop;nop
+	
+	/* GD -> IE, gd first, after IE use.  */
+	.byte	0x66
+	leaq	sG3@tlsgd(%rip), %rdi
+	.word	0x6666
+	rex64
+	call	__tls_get_addr@plt
+	nop;nop;nop;nop
+	
+	leaq	sG3@tlsdesc(%rip), %rax
+	call	*sG3@tlscall(%rax)
+	nop;nop;nop;nop
+
+	/* GD -> IE, desc first, after IE use.  */
+	leaq	sG4@tlsdesc(%rip), %rax
+	call	*sG4@tlscall(%rax)
+	nop;nop;nop;nop
+
+	.byte	0x66
+	leaq	sG4@tlsgd(%rip), %rdi
+	.word	0x6666
+	rex64
+	call	__tls_get_addr@plt
+	nop;nop;nop;nop
+	
+	/* GD -> IE, gd first, before IE use.  */
+	.byte	0x66
+	leaq	sG5@tlsgd(%rip), %rdi
+	.word	0x6666
+	rex64
+	call	__tls_get_addr@plt
+	nop;nop;nop;nop
+	
+	leaq	sG5@tlsdesc(%rip), %rax
+	call	*sG5@tlscall(%rax)
+	nop;nop;nop;nop
+
+	/* GD -> IE, desc first, before IE use.  */
+	leaq	sG6@tlsdesc(%rip), %rax
+	call	*sG6@tlscall(%rax)
+	nop;nop;nop;nop
+
+	.byte	0x66
+	leaq	sG6@tlsgd(%rip), %rdi
+	.word	0x6666
+	rex64
+	call	__tls_get_addr@plt
+	nop;nop;nop;nop
+	
+	/* IE against global var.  */
+	movq	%fs:0, %rcx
+	nop;nop
+	addq	sG5@gottpoff(%rip), %rcx
+	nop;nop;nop;nop
+
+	/* IE against global var.  */
+	movq	%fs:0, %rcx
+	nop;nop
+	addq	sG6@gottpoff(%rip), %rcx
+	nop;nop;nop;nop
+
+	leave
+	ret
Index: ld/testsuite/ld-x86-64/x86-64.exp
===================================================================
RCS file: /cvs/uberbaum/./ld/testsuite/ld-x86-64/x86-64.exp,v
retrieving revision 1.4
diff -u -p -r1.4 x86-64.exp
--- ld/testsuite/ld-x86-64/x86-64.exp 18 Jul 2005 06:23:40 -0000 1.4
+++ ld/testsuite/ld-x86-64/x86-64.exp 15 Sep 2005 22:39:29 -0000
@@ -1,5 +1,5 @@
 # Expect script for ld-x86_64 tests
-#   Copyright (C) 2002 Free Software Foundation
+#   Copyright (C) 2002, 2005 Free Software Foundation
 #
 # This file is free software; you can redistribute it and/or modify
 # it under the terms of the GNU General Public License as published by
@@ -39,6 +39,11 @@ set x86_64tests {
      {{readelf -WSsrl tlspic.rd} {objdump -drj.text tlspic.dd}
       {objdump -sj.got tlspic.sd} {objdump -sj.tdata tlspic.td}}
       "libtlspic.so"}
+    {"TLS descriptor -fpic -shared transitions" "-shared -melf_x86_64"
+     "--64" {tlsdesc.s tlspic2.s}
+     {{readelf -WSsrld tlsdesc.rd} {objdump -drj.text tlsdesc.dd}
+      {objdump "-s -j.got -j.got.plt" tlsdesc.sd} {objdump -sj.tdata tlsdesc.td}
+      {objdump -drj.plt tlsdesc.pd}} "libtlsdesc.so"}
     {"Helper shared library" "-shared -melf_x86_64"
      "--64" {tlslib.s} {} "libtlslib.so"}
     {"TLS -fpic and -fno-pic exec transitions"
@@ -46,6 +51,15 @@ set x86_64tests {
      {{readelf -WSsrl tlsbin.rd} {objdump -drj.text tlsbin.dd}
       {objdump -sj.got tlsbin.sd} {objdump -sj.tdata tlsbin.td}}
       "tlsbin"}
+    {"TLS descriptor -fpic and -fno-pic exec transitions"
+     "-melf_x86_64 tmpdir/libtlslib.so" "--64" {tlsbindesc.s tlsbin.s}
+     {{readelf -WSsrl tlsbindesc.rd} {objdump -drj.text tlsbindesc.dd}
+      {objdump -sj.got tlsbindesc.sd} {objdump -sj.tdata tlsbindesc.td}}
+      "tlsbindesc"}
+    {"TLS with global dynamic and descriptors"
+	"-shared -melf_x86_64" "--64" {tlsgdesc.s}
+     {{readelf -WSsrl tlsgdesc.rd} {objdump -drj.text tlsgdesc.dd}}
+      "libtlsgdesc.so"}
     {"TLS in debug sections" "-melf_x86_64"
      "--64" {tlsg.s}
      {{objdump -sj.debug_foobar tlsg.sd}} "tlsg"}
-- 
Alexandre Oliva         http://www.lsd.ic.unicamp.br/~oliva/
Red Hat Compiler Engineer   aoliva@{redhat.com, gcc.gnu.org}
Free Software Evangelist  oliva@{lsd.ic.unicamp.br, gnu.org}

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