[PATCH] x86-64 TLS support

Jakub Jelinek jakub@redhat.com
Thu Sep 26 13:56:00 GMT 2002


Hi!

The following patch adds x86-64 TLS support. I also moved run_ld_link_tests
(the version with 6 fields) to lib/ld-lib.exp, so that it can be shared and
adjusted sh64.exp (added the 6th fields into the array).
Ok to commit?
Andreas, if you have time, could you double check the testcases that
they really do what will be in tls.pdf. I went once over all the
instructions (and caught some bugs on it), but more eyes see
more definitely.

2002-09-26  Jakub Jelinek  <jakub@redhat.com>

bfd/
	* reloc.c: Add x86-64 TLS relocs.
	* bfd-in2.h, libbfd.h: Rebuilt.
	* elf64-x86-64.c (x86_64_elf_howto): Fix size fields for 32-bit
	relocs.  Add TLS relocs.
	(x86_64_reloc_map): Add TLS relocs.
	(elf64_x86_64_info_to_howto): Adjust for added TLS relocs.
	(struct elf64_x86_64_link_hash_entry): Add tls_type field.
	(GOT_UNKNOWN, GOT_NORMAL, GOT_TLS_GD, GOT_TLS_IE): Define.
	(elf64_x86_64_hash_entry): Define.
	(struct elf64_x86_64_obj_tdata): New.
	(elf64_x86_64_tdata, elf64_x86_64_local_got_tls_type): Define.
	(struct elf64_x86_64_link_hash_table): Add tls_ld_got.
	(link_hash_newfunc): Initialize tls_type.
	(elf64_x86_64_link_hash_table_create): Initialize tls_ld_got.
	(elf64_x86_64_copy_indirect_symbol): Swap tls_type if necessary.
	(elf64_x86_64_mkobject): New.
	(elf64_x86_64_elf_object_p): Allocate struct elf64_x86_64_obj_tdata.
	(elf64_x86_64_tls_transition): New.
	(elf64_x86_64_check_relocs): Add r_type variable and use it.
	Handle TLS relocs.
	(elf64_x86_64_gc_sweep_hook): Handle TLS relocs.
	(allocate_dynrelocs): Allocate GOT space for TLS relocs.
	(elf64_x86_64_size_dynamic_sections): Likewise.
	(dtpoff_base, tpoff): New.
	(elf64_x86_64_relocate_section): Handle TLS relocs.
	(elf64_x86_64_finish_dynamic_symbol): Only handle non-TLS GOT
	entries.
	(bfd_elf64_mkobject): Define.

	* elf32-i386.c (elf_i386_check_relocs) [R_386_TLS_LE]: Set
	DF_STATIC_TLS if shared.
gas/
	* config/tc-i386.c (tc_i386_fix_adjustable): Add x86-64 TLS relocs.
	Define them if not BFD_ASSEMBLER.
	(lex_got): Handle @tlsgd, @dtpoff and @tpoff in 64-bit mode, add
	@tlsld.
	(md_apply_fix3): No addend for BFD_RELOC_X86_64_TLSGD,
	BFD_RELOC_X86_64_TLSLD and BFD_RELOC_X86_64_GOTTPOFF.
	(tc_gen_reloc): Handle x86-64 TLS relocs.
include/
	* elf/x86-64.h: Add TLS relocs.
ld/testsuite/
	* lib/ld-lib.exp (run_ld_link_tests): Add.
	* ld-sh/sh64/sh64.exp (run_ld_link_tests, regexp_diff,
	file_contents): Remove.
	(sh64tests): Add 6th field to the tests array.
	* ld-i386/i386.exp (run_ld_link_tests): Remove.
	* ld-x86-64/x86-64.exp: New.
	* ld-x86-64/tlsbin.dd: New test.
	* ld-x86-64/tlsbinpic.s: New test.
	* ld-x86-64/tlsbin.rd: New test.
	* ld-x86-64/tlsbin.s: New test.
	* ld-x86-64/tlsbin.sd: New test.
	* ld-x86-64/tlsbin.td: New test.
	* ld-x86-64/tlslib.s: New test.
	* ld-x86-64/tlspic1.s: New test.
	* ld-x86-64/tlspic2.s: New test.
	* ld-x86-64/tlspic.dd: New test.
	* ld-x86-64/tlspic.rd: New test.
	* ld-x86-64/tlspic.sd: New test.
	* ld-x86-64/tlspic.td: New test.

--- bfd/reloc.c.jj	2002-09-19 11:38:14.000000000 +0200
+++ bfd/reloc.c	2002-09-25 11:29:50.000000000 +0200
@@ -2165,6 +2165,22 @@ ENUMX
   BFD_RELOC_X86_64_GOTPCREL
 ENUMX
   BFD_RELOC_X86_64_32S
+ENUMX
+  BFD_RELOC_X86_64_DTPMOD64
+ENUMX
+  BFD_RELOC_X86_64_DTPOFF64
+ENUMX
+  BFD_RELOC_X86_64_TPOFF64
+ENUMX
+  BFD_RELOC_X86_64_TLSGD
+ENUMX
+  BFD_RELOC_X86_64_TLSLD
+ENUMX
+  BFD_RELOC_X86_64_DTPOFF32
+ENUMX
+  BFD_RELOC_X86_64_GOTTPOFF
+ENUMX
+  BFD_RELOC_X86_64_TPOFF32
 ENUMDOC
   x86-64/elf relocations
 
--- bfd/bfd-in2.h.jj	2002-09-19 11:38:14.000000000 +0200
+++ bfd/bfd-in2.h	2002-09-25 11:29:50.000000000 +0200
@@ -2286,6 +2286,14 @@ to compensate for the borrow when the lo
   BFD_RELOC_X86_64_RELATIVE,
   BFD_RELOC_X86_64_GOTPCREL,
   BFD_RELOC_X86_64_32S,
+  BFD_RELOC_X86_64_DTPMOD64,
+  BFD_RELOC_X86_64_DTPOFF64,
+  BFD_RELOC_X86_64_TPOFF64,
+  BFD_RELOC_X86_64_TLSGD,
+  BFD_RELOC_X86_64_TLSLD,
+  BFD_RELOC_X86_64_DTPOFF32,
+  BFD_RELOC_X86_64_GOTTPOFF,
+  BFD_RELOC_X86_64_TPOFF32,
 
 /* ns32k relocations  */
   BFD_RELOC_NS32K_IMM_8,
--- bfd/libbfd.h.jj	2002-09-19 11:38:14.000000000 +0200
+++ bfd/libbfd.h	2002-09-25 11:29:50.000000000 +0200
@@ -819,6 +819,14 @@ static const char *const bfd_reloc_code_
   "BFD_RELOC_X86_64_RELATIVE",
   "BFD_RELOC_X86_64_GOTPCREL",
   "BFD_RELOC_X86_64_32S",
+  "BFD_RELOC_X86_64_DTPMOD64",
+  "BFD_RELOC_X86_64_DTPOFF64",
+  "BFD_RELOC_X86_64_TPOFF64",
+  "BFD_RELOC_X86_64_TLSGD",
+  "BFD_RELOC_X86_64_TLSLD",
+  "BFD_RELOC_X86_64_DTPOFF32",
+  "BFD_RELOC_X86_64_GOTTPOFF",
+  "BFD_RELOC_X86_64_TPOFF32",
   "BFD_RELOC_NS32K_IMM_8",
   "BFD_RELOC_NS32K_IMM_16",
   "BFD_RELOC_NS32K_IMM_32",
--- bfd/elf64-x86-64.c.jj	2002-09-10 14:50:44.000000000 +0200
+++ bfd/elf64-x86-64.c	2002-09-26 17:37:10.000000000 +0200
@@ -40,16 +40,16 @@ static reloc_howto_type x86_64_elf_howto
   HOWTO(R_X86_64_64, 0, 4, 64, false, 0, complain_overflow_bitfield,
 	bfd_elf_generic_reloc, "R_X86_64_64", false, MINUS_ONE, MINUS_ONE,
 	false),
-  HOWTO(R_X86_64_PC32, 0, 4, 32, true, 0, complain_overflow_signed,
+  HOWTO(R_X86_64_PC32, 0, 2, 32, true, 0, complain_overflow_signed,
 	bfd_elf_generic_reloc, "R_X86_64_PC32", false, 0xffffffff, 0xffffffff,
 	true),
-  HOWTO(R_X86_64_GOT32, 0, 4, 32, false, 0, complain_overflow_signed,
+  HOWTO(R_X86_64_GOT32, 0, 2, 32, false, 0, complain_overflow_signed,
 	bfd_elf_generic_reloc, "R_X86_64_GOT32", false, 0xffffffff, 0xffffffff,
 	false),
-  HOWTO(R_X86_64_PLT32, 0, 4, 32, true, 0, complain_overflow_signed,
+  HOWTO(R_X86_64_PLT32, 0, 2, 32, true, 0, complain_overflow_signed,
 	bfd_elf_generic_reloc, "R_X86_64_PLT32", false, 0xffffffff, 0xffffffff,
 	true),
-  HOWTO(R_X86_64_COPY, 0, 4, 32, false, 0, complain_overflow_bitfield,
+  HOWTO(R_X86_64_COPY, 0, 2, 32, false, 0, complain_overflow_bitfield,
 	bfd_elf_generic_reloc, "R_X86_64_COPY", false, 0xffffffff, 0xffffffff,
 	false),
   HOWTO(R_X86_64_GLOB_DAT, 0, 4, 64, false, 0, complain_overflow_bitfield,
@@ -61,13 +61,13 @@ static reloc_howto_type x86_64_elf_howto
   HOWTO(R_X86_64_RELATIVE, 0, 4, 64, false, 0, complain_overflow_bitfield,
 	bfd_elf_generic_reloc, "R_X86_64_RELATIVE", false, MINUS_ONE,
 	MINUS_ONE, false),
-  HOWTO(R_X86_64_GOTPCREL, 0, 4, 32, true,0 , complain_overflow_signed,
+  HOWTO(R_X86_64_GOTPCREL, 0, 2, 32, true, 0, complain_overflow_signed,
 	bfd_elf_generic_reloc, "R_X86_64_GOTPCREL", false, 0xffffffff,
 	0xffffffff, true),
-  HOWTO(R_X86_64_32, 0, 4, 32, false, 0, complain_overflow_unsigned,
+  HOWTO(R_X86_64_32, 0, 2, 32, false, 0, complain_overflow_unsigned,
 	bfd_elf_generic_reloc, "R_X86_64_32", false, 0xffffffff, 0xffffffff,
 	false),
-  HOWTO(R_X86_64_32S, 0, 4, 32, false, 0, complain_overflow_signed,
+  HOWTO(R_X86_64_32S, 0, 2, 32, false, 0, complain_overflow_signed,
 	bfd_elf_generic_reloc, "R_X86_64_32S", false, 0xffffffff, 0xffffffff,
 	false),
   HOWTO(R_X86_64_16, 0, 1, 16, false, 0, complain_overflow_bitfield,
@@ -78,6 +78,30 @@ static reloc_howto_type x86_64_elf_howto
 	bfd_elf_generic_reloc, "R_X86_64_8", false, 0xff, 0xff, false),
   HOWTO(R_X86_64_PC8, 0, 0, 8, true, 0, complain_overflow_signed,
 	bfd_elf_generic_reloc, "R_X86_64_PC8", false, 0xff, 0xff, true),
+  HOWTO(R_X86_64_DTPMOD64, 0, 4, 64, false, 0, complain_overflow_bitfield,
+	bfd_elf_generic_reloc, "R_X86_64_DTPMOD64", false, MINUS_ONE,
+	MINUS_ONE, false),
+  HOWTO(R_X86_64_DTPOFF64, 0, 4, 64, false, 0, complain_overflow_bitfield,
+	bfd_elf_generic_reloc, "R_X86_64_DTPOFF64", false, MINUS_ONE,
+	MINUS_ONE, false),
+  HOWTO(R_X86_64_TPOFF64, 0, 4, 64, false, 0, complain_overflow_bitfield,
+	bfd_elf_generic_reloc, "R_X86_64_TPOFF64", false, MINUS_ONE,
+	MINUS_ONE, false),
+  HOWTO(R_X86_64_TLSGD, 0, 2, 32, true, 0, complain_overflow_signed,
+	bfd_elf_generic_reloc, "R_X86_64_TLSGD", false, 0xffffffff,
+	0xffffffff, true),
+  HOWTO(R_X86_64_TLSLD, 0, 2, 32, true, 0, complain_overflow_signed,
+	bfd_elf_generic_reloc, "R_X86_64_TLSLD", false, 0xffffffff,
+	0xffffffff, true),
+  HOWTO(R_X86_64_DTPOFF32, 0, 2, 32, false, 0, complain_overflow_bitfield,
+	bfd_elf_generic_reloc, "R_X86_64_DTPOFF32", false, 0xffffffff,
+	0xffffffff, false),
+  HOWTO(R_X86_64_GOTTPOFF, 0, 2, 32, true, 0, complain_overflow_signed,
+	bfd_elf_generic_reloc, "R_X86_64_GOTTPOFF", false, 0xffffffff,
+	0xffffffff, true),
+  HOWTO(R_X86_64_TPOFF32, 0, 2, 32, false, 0, complain_overflow_signed,
+	bfd_elf_generic_reloc, "R_X86_64_TPOFF32", false, 0xffffffff,
+	0xffffffff, false),
 
 /* GNU extension to record C++ vtable hierarchy.  */
   HOWTO (R_X86_64_GNU_VTINHERIT, 0, 4, 0, false, 0, complain_overflow_dont,
@@ -114,6 +138,14 @@ static const struct elf_reloc_map x86_64
   { BFD_RELOC_16_PCREL,		R_X86_64_PC16, },
   { BFD_RELOC_8,		R_X86_64_8, },
   { BFD_RELOC_8_PCREL,		R_X86_64_PC8, },
+  { BFD_RELOC_X86_64_DTPMOD64,	R_X86_64_DTPMOD64, },
+  { BFD_RELOC_X86_64_DTPOFF64,	R_X86_64_DTPOFF64, },
+  { BFD_RELOC_X86_64_TPOFF64,	R_X86_64_TPOFF64, },
+  { BFD_RELOC_X86_64_TLSGD,	R_X86_64_TLSGD, },
+  { BFD_RELOC_X86_64_TLSLD,	R_X86_64_TLSLD, },
+  { BFD_RELOC_X86_64_DTPOFF32,	R_X86_64_DTPOFF32, },
+  { BFD_RELOC_X86_64_GOTTPOFF,	R_X86_64_GOTTPOFF, },
+  { BFD_RELOC_X86_64_TPOFF32,	R_X86_64_TPOFF32, },
   { BFD_RELOC_VTABLE_INHERIT,	R_X86_64_GNU_VTINHERIT, },
   { BFD_RELOC_VTABLE_ENTRY,	R_X86_64_GNU_VTENTRY, },
 };
@@ -128,6 +160,10 @@ static boolean elf64_x86_64_grok_psinfo
   PARAMS ((bfd *, Elf_Internal_Note *));
 static struct bfd_link_hash_table *elf64_x86_64_link_hash_table_create
   PARAMS ((bfd *));
+static int elf64_x86_64_tls_transition
+  PARAMS ((struct bfd_link_info *, int, int));
+static boolean elf64_x86_64_mkobject
+  PARAMS((bfd *));
 static boolean elf64_x86_64_elf_object_p PARAMS ((bfd *abfd));
 static boolean create_got_section
   PARAMS((bfd *, struct bfd_link_info *));
@@ -158,6 +194,10 @@ static boolean readonly_dynrelocs
   PARAMS ((struct elf_link_hash_entry *, PTR));
 static boolean elf64_x86_64_size_dynamic_sections
   PARAMS ((bfd *, struct bfd_link_info *));
+static bfd_vma dtpoff_base
+  PARAMS ((struct bfd_link_info *));
+static bfd_vma tpoff
+  PARAMS ((struct bfd_link_info *, bfd_vma));
 static boolean elf64_x86_64_relocate_section
   PARAMS ((bfd *, struct bfd_link_info *, bfd *, asection *, bfd_byte *,
 	 Elf_Internal_Rela *, Elf_Internal_Sym *, asection **));
@@ -198,13 +238,13 @@ elf64_x86_64_info_to_howto (abfd, cache_
   r_type = ELF64_R_TYPE (dst->r_info);
   if (r_type < (unsigned int) R_X86_64_GNU_VTINHERIT)
     {
-      BFD_ASSERT (r_type <= (unsigned int) R_X86_64_PC8);
+      BFD_ASSERT (r_type <= (unsigned int) R_X86_64_TPOFF32);
       i = r_type;
     }
   else
     {
       BFD_ASSERT (r_type < (unsigned int) R_X86_64_max);
-      i = r_type - ((unsigned int) R_X86_64_GNU_VTINHERIT - R_X86_64_PC8 - 1);
+      i = r_type - ((unsigned int) R_X86_64_GNU_VTINHERIT - R_X86_64_TPOFF32 - 1);
     }
   cache_ptr->howto = &x86_64_elf_howto_table[i];
   BFD_ASSERT (r_type == cache_ptr->howto->type);
@@ -343,8 +383,32 @@ struct elf64_x86_64_link_hash_entry
 
   /* Track dynamic relocs copied for this symbol.  */
   struct elf64_x86_64_dyn_relocs *dyn_relocs;
+
+#define GOT_UNKNOWN	0
+#define GOT_NORMAL	1
+#define GOT_TLS_GD	2
+#define GOT_TLS_IE	3
+  unsigned char tls_type;
+};
+
+#define elf64_x86_64_hash_entry(ent) \
+  ((struct elf64_x86_64_link_hash_entry *)(ent))
+
+struct elf64_x86_64_obj_tdata
+{
+  struct elf_obj_tdata root;
+
+  /* tls_type for each local got entry.  */
+  char *local_got_tls_type;
 };
 
+#define elf64_x86_64_tdata(abfd) \
+  ((struct elf64_x86_64_obj_tdata *) (abfd)->tdata.any)
+
+#define elf64_x86_64_local_got_tls_type(abfd) \
+  (elf64_x86_64_tdata (abfd)->local_got_tls_type)
+
+
 /* x86-64 ELF linker hash table.  */
 
 struct elf64_x86_64_link_hash_table
@@ -360,6 +424,11 @@ struct elf64_x86_64_link_hash_table
   asection *sdynbss;
   asection *srelbss;
 
+  union {
+    bfd_signed_vma refcount;
+    bfd_vma offset;
+  } tls_ld_got;
+
   /* Small local sym to section mapping cache.  */
   struct sym_sec_cache sym_sec;
 };
@@ -395,6 +464,7 @@ link_hash_newfunc (entry, table, string)
 
       eh = (struct elf64_x86_64_link_hash_entry *) entry;
       eh->dyn_relocs = NULL;
+      eh->tls_type = GOT_UNKNOWN;
     }
 
   return entry;
@@ -427,6 +497,7 @@ elf64_x86_64_link_hash_table_create (abf
   ret->sdynbss = NULL;
   ret->srelbss = NULL;
   ret->sym_sec.abfd = NULL;
+  ret->tls_ld_got.refcount = 0;
 
   return &ret->elf.root;
 }
@@ -538,18 +609,67 @@ elf64_x86_64_copy_indirect_symbol (bed, 
       eind->dyn_relocs = NULL;
     }
 
+  if (ind->root.type == bfd_link_hash_indirect
+      && dir->got.refcount <= 0)
+    {
+      edir->tls_type = eind->tls_type;
+      eind->tls_type = GOT_UNKNOWN;
+    }
+
   _bfd_elf_link_hash_copy_indirect (bed, dir, ind);
 }
 
 static boolean
-elf64_x86_64_elf_object_p (abfd)
+elf64_x86_64_mkobject (abfd)
      bfd *abfd;
 {
+  bfd_size_type amt = sizeof (struct elf64_x86_64_obj_tdata);
+  abfd->tdata.any = bfd_zalloc (abfd, amt);
+  if (abfd->tdata.any == NULL)
+    return false;
+  return true;
+}
+
+static boolean
+elf64_x86_64_elf_object_p (abfd)
+  bfd *abfd;
+{
+  /* Allocate our special target data.  */
+  struct elf64_x86_64_obj_tdata *new_tdata;
+  bfd_size_type amt = sizeof (struct elf64_x86_64_obj_tdata);
+  new_tdata = bfd_zalloc (abfd, amt);
+  if (new_tdata == NULL)
+    return false;
+  new_tdata->root = *abfd->tdata.elf_obj_data;
+  abfd->tdata.any = new_tdata;
   /* Set the right machine number for an x86-64 elf64 file.  */
   bfd_default_set_arch_mach (abfd, bfd_arch_i386, bfd_mach_x86_64);
   return true;
 }
 
+static int
+elf64_x86_64_tls_transition (info, r_type, is_local)
+     struct bfd_link_info *info;
+     int r_type;
+     int is_local;
+{
+  if (info->shared)
+    return r_type;
+
+  switch (r_type)
+    {
+    case R_X86_64_TLSGD:
+    case R_X86_64_GOTTPOFF:
+      if (is_local)
+	return R_X86_64_TPOFF32;
+      return R_X86_64_GOTTPOFF;
+    case R_X86_64_TLSLD:
+      return R_X86_64_TPOFF32;
+    }
+
+   return r_type;
+}
+
 /* Look through the relocs for a section during the first phase, and
    calculate needed space in the global offset table, procedure
    linkage table, and dynamic reloc sections.  */
@@ -580,10 +700,12 @@ elf64_x86_64_check_relocs (abfd, info, s
   rel_end = relocs + sec->reloc_count;
   for (rel = relocs; rel < rel_end; rel++)
     {
+      unsigned int r_type;
       unsigned long r_symndx;
       struct elf_link_hash_entry *h;
 
       r_symndx = ELF64_R_SYM (rel->r_info);
+      r_type = ELF64_R_TYPE (rel->r_info);
 
       if (r_symndx >= NUM_SHDR_ENTRIES (symtab_hdr))
 	{
@@ -598,38 +720,103 @@ elf64_x86_64_check_relocs (abfd, info, s
       else
 	h = sym_hashes[r_symndx - symtab_hdr->sh_info];
 
-      switch (ELF64_R_TYPE (rel->r_info))
+      r_type = elf64_x86_64_tls_transition (info, r_type, h == NULL);
+      switch (r_type)
 	{
+	case R_X86_64_TLSLD:
+	  htab->tls_ld_got.refcount += 1;
+	  goto create_got;
+
+	case R_X86_64_TPOFF32:
+	  if (info->shared)
+	    {
+	      (*_bfd_error_handler)
+		(_("%s: relocation %s can not be used when making a shared object; recompile with -fPIC"),
+		 bfd_archive_filename (abfd),
+		 x86_64_elf_howto_table[r_type].name);
+	      bfd_set_error (bfd_error_bad_value);
+	      return false;
+	    }
+	  break;
+
+	case R_X86_64_GOTTPOFF:
+	  if (info->shared)
+	    info->flags |= DF_STATIC_TLS;
+	  /* Fall through */
+
 	case R_X86_64_GOT32:
 	case R_X86_64_GOTPCREL:
+	case R_X86_64_TLSGD:
 	  /* This symbol requires a global offset table entry.	*/
-	  if (h != NULL)
-	    {
-	      h->got.refcount += 1;
-	    }
-	  else
-	    {
-	      bfd_signed_vma *local_got_refcounts;
+	  {
+	    int tls_type, old_tls_type;
 
-	      /* This is a global offset table entry for a local symbol.  */
-	      local_got_refcounts = elf_local_got_refcounts (abfd);
-	      if (local_got_refcounts == NULL)
-		{
-		  bfd_size_type size;
+	    switch (r_type)
+	      {
+	      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;
+	      }
+
+	    if (h != NULL)
+	      {
+		h->got.refcount += 1;
+		old_tls_type = elf64_x86_64_hash_entry (h)->tls_type;
+	      }
+	    else
+	      {
+		bfd_signed_vma *local_got_refcounts;
+
+		/* This is a global offset table entry for a local symbol.  */
+		local_got_refcounts = elf_local_got_refcounts (abfd);
+		if (local_got_refcounts == NULL)
+		  {
+		    bfd_size_type size;
 
-		  size = symtab_hdr->sh_info;
-		  size *= sizeof (bfd_signed_vma);
-		  local_got_refcounts = ((bfd_signed_vma *)
-					 bfd_zalloc (abfd, size));
-		  if (local_got_refcounts == NULL)
+		    size = symtab_hdr->sh_info;
+		    size *= sizeof (bfd_signed_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_got_tls_type (abfd)
+		      = (char *) (local_got_refcounts + symtab_hdr->sh_info);
+		  }
+		local_got_refcounts[r_symndx] += 1;
+		old_tls_type
+		  = elf64_x86_64_local_got_tls_type (abfd) [r_symndx];
+	      }
+
+	    /* 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))
+	      {
+		if (old_tls_type == GOT_TLS_IE && tls_type == GOT_TLS_GD)
+		  tls_type = old_tls_type;
+		else
+		  {
+		    (*_bfd_error_handler)
+		      (_("%s: %s' accessed both as normal and thread local symbol"),
+		       bfd_archive_filename (abfd),
+		       h ? h->root.root.string : "<local>");
 		    return false;
-		  elf_local_got_refcounts (abfd) = local_got_refcounts;
-		}
-	      local_got_refcounts[r_symndx] += 1;
-	    }
+		  }
+	      }
+
+	    if (old_tls_type != tls_type)
+	      {
+		if (h != NULL)
+		  elf64_x86_64_hash_entry (h)->tls_type = tls_type;
+		else
+		  elf64_x86_64_local_got_tls_type (abfd) [r_symndx] = tls_type;
+	      }
+	  }
 	  /* Fall through */
 
 	  //case R_X86_64_GOTPCREL:
+	create_got:
 	  if (htab->sgot == NULL)
 	    {
 	      if (htab->elf.dynobj == NULL)
@@ -671,7 +858,7 @@ elf64_x86_64_check_relocs (abfd, info, s
 	      (*_bfd_error_handler)
 		(_("%s: relocation %s can not be used when making a shared object; recompile with -fPIC"),
 		 bfd_archive_filename (abfd),
-		 x86_64_elf_howto_table[ELF64_R_TYPE (rel->r_info)].name);
+		 x86_64_elf_howto_table[r_type].name);
 	      bfd_set_error (bfd_error_bad_value);
 	      return false;
 	    }
@@ -719,9 +906,9 @@ elf64_x86_64_check_relocs (abfd, info, s
 	     symbol.  */
 	  if ((info->shared
 	       && (sec->flags & SEC_ALLOC) != 0
-	       && (((ELF64_R_TYPE (rel->r_info) != R_X86_64_PC8)
-		    && (ELF64_R_TYPE (rel->r_info) != R_X86_64_PC16)
-		    && (ELF64_R_TYPE (rel->r_info) != R_X86_64_PC32))
+	       && (((r_type != R_X86_64_PC8)
+		    && (r_type != R_X86_64_PC16)
+		    && (r_type != R_X86_64_PC32))
 		   || (h != NULL
 		       && (! info->symbolic
 			   || h->root.type == bfd_link_hash_defweak
@@ -822,9 +1009,9 @@ elf64_x86_64_check_relocs (abfd, info, s
 		}
 
 	      p->count += 1;
-	      if (ELF64_R_TYPE (rel->r_info) == R_X86_64_PC8
-		  || ELF64_R_TYPE (rel->r_info) == R_X86_64_PC16
-		  || ELF64_R_TYPE (rel->r_info) == R_X86_64_PC32)
+	      if (r_type == R_X86_64_PC8
+		  || r_type == R_X86_64_PC16
+		  || r_type == R_X86_64_PC32)
 		p->pc_count += 1;
 	    }
 	  break;
@@ -905,6 +1092,7 @@ elf64_x86_64_gc_sweep_hook (abfd, info, 
   bfd_signed_vma *local_got_refcounts;
   const Elf_Internal_Rela *rel, *relend;
   unsigned long r_symndx;
+  int r_type;
   struct elf_link_hash_entry *h;
 
   elf_section_data (sec)->local_dynrel = NULL;
@@ -915,8 +1103,18 @@ elf64_x86_64_gc_sweep_hook (abfd, info, 
 
   relend = relocs + sec->reloc_count;
   for (rel = relocs; rel < relend; rel++)
-    switch (ELF64_R_TYPE (rel->r_info))
+    switch ((r_type = elf64_x86_64_tls_transition (info,
+						   ELF64_R_TYPE (rel->r_info),
+						   ELF64_R_SYM (rel->r_info)
+						   >= symtab_hdr->sh_info)))
       {
+      case R_X86_64_TLSLD:
+	if (elf64_x86_64_hash_table (info)->tls_ld_got.refcount > 0)
+	  elf64_x86_64_hash_table (info)->tls_ld_got.refcount -= 1;
+	break;
+
+      case R_X86_64_TLSGD:
+      case R_X86_64_GOTTPOFF:
       case R_X86_64_GOT32:
       case R_X86_64_GOTPCREL:
 	r_symndx = ELF64_R_SYM (rel->r_info);
@@ -1226,10 +1424,18 @@ allocate_dynrelocs (h, inf)
       h->elf_link_hash_flags &= ~ELF_LINK_HASH_NEEDS_PLT;
     }
 
-  if (h->got.refcount > 0)
+  /* 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
+      && !info->shared
+      && h->dynindx == -1
+      && elf64_x86_64_hash_entry (h)->tls_type == GOT_TLS_IE)
+    h->got.offset = (bfd_vma) -1;
+  else if (h->got.refcount > 0)
     {
       asection *s;
       boolean dyn;
+      int tls_type = elf64_x86_64_hash_entry (h)->tls_type;
 
       /* Make sure this symbol is output as a dynamic symbol.
 	 Undefined weak syms won't yet be marked as dynamic.  */
@@ -1243,8 +1449,19 @@ allocate_dynrelocs (h, inf)
       s = htab->sgot;
       h->got.offset = s->_raw_size;
       s->_raw_size += GOT_ENTRY_SIZE;
+      /* R_X86_64_TLSGD needs 2 consecutive GOT slots.  */
+      if (tls_type == GOT_TLS_GD)
+	s->_raw_size += GOT_ENTRY_SIZE;
       dyn = htab->elf.dynamic_sections_created;
-      if (WILL_CALL_FINISH_DYNAMIC_SYMBOL (dyn, info, h))
+      /* 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)
+	  || tls_type == GOT_TLS_IE)
+	htab->srelgot->_raw_size += sizeof (Elf64_External_Rela);
+      else if (tls_type == GOT_TLS_GD)
+	htab->srelgot->_raw_size += 2 * sizeof (Elf64_External_Rela);
+      else if (WILL_CALL_FINISH_DYNAMIC_SYMBOL (dyn, info, h))
 	htab->srelgot->_raw_size += sizeof (Elf64_External_Rela);
     }
   else
@@ -1390,6 +1607,7 @@ elf64_x86_64_size_dynamic_sections (outp
     {
       bfd_signed_vma *local_got;
       bfd_signed_vma *end_local_got;
+      char *local_tls_type;
       bfd_size_type locsymcount;
       Elf_Internal_Shdr *symtab_hdr;
       asection *srel;
@@ -1432,15 +1650,20 @@ elf64_x86_64_size_dynamic_sections (outp
       symtab_hdr = &elf_tdata (ibfd)->symtab_hdr;
       locsymcount = symtab_hdr->sh_info;
       end_local_got = local_got + locsymcount;
+      local_tls_type = elf64_x86_64_local_got_tls_type (ibfd);
       s = htab->sgot;
       srel = htab->srelgot;
-      for (; local_got < end_local_got; ++local_got)
+      for (; local_got < end_local_got; ++local_got, ++local_tls_type)
 	{
 	  if (*local_got > 0)
 	    {
 	      *local_got = s->_raw_size;
 	      s->_raw_size += GOT_ENTRY_SIZE;
-	      if (info->shared)
+	      if (*local_tls_type == GOT_TLS_GD)
+		s->_raw_size += GOT_ENTRY_SIZE;
+	      if (info->shared
+		  || *local_tls_type == GOT_TLS_GD
+		  || *local_tls_type == GOT_TLS_IE)
 		srel->_raw_size += sizeof (Elf64_External_Rela);
 	    }
 	  else
@@ -1448,6 +1671,17 @@ elf64_x86_64_size_dynamic_sections (outp
 	}
     }
 
+  if (htab->tls_ld_got.refcount > 0)
+    {
+      /* Allocate 2 got entries and 1 dynamic reloc for R_X86_64_TLSLD
+	 relocs.  */
+      htab->tls_ld_got.offset = htab->sgot->_raw_size;
+      htab->sgot->_raw_size += 2 * GOT_ENTRY_SIZE;
+      htab->srelgot->_raw_size += sizeof (Elf64_External_Rela);
+    }
+  else
+    htab->tls_ld_got.offset = -1;
+
   /* Allocate global sym .plt and .got entries, and space for global
      sym dynamic relocs.  */
   elf_link_hash_traverse (&htab->elf, allocate_dynrelocs, (PTR) info);
@@ -1558,6 +1792,38 @@ elf64_x86_64_size_dynamic_sections (outp
   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.  */
+
+static bfd_vma
+dtpoff_base (info)
+     struct bfd_link_info *info;
+{
+  /* If tls_segment is NULL, we should have signalled an error already.  */
+  if (elf_hash_table (info)->tls_segment == NULL)
+    return 0;
+  return elf_hash_table (info)->tls_segment->start;
+}
+
+/* Return the relocation value for @tpoff relocation
+   if STT_TLS virtual address is ADDRESS.  */
+
+static bfd_vma
+tpoff (info, address)
+     struct bfd_link_info *info;
+     bfd_vma address;
+{
+  struct elf_link_tls_segment *tls_segment
+    = elf_hash_table (info)->tls_segment;
+
+  /* If tls_segment is NULL, we should have signalled an error already.  */
+  if (tls_segment == NULL)
+    return 0;
+  return address - align_power (tls_segment->size, tls_segment->align)
+	 - tls_segment->start;
+}
+
 /* Relocate an x86_64 ELF section.  */
 
 static boolean
@@ -1591,7 +1857,7 @@ elf64_x86_64_relocate_section (output_bf
   relend = relocs + input_section->reloc_count;
   for (; rel < relend; rel++)
     {
-      int r_type;
+      unsigned int r_type;
       reloc_howto_type *howto;
       unsigned long r_symndx;
       struct elf_link_hash_entry *h;
@@ -1601,13 +1867,14 @@ elf64_x86_64_relocate_section (output_bf
       bfd_vma relocation;
       boolean unresolved_reloc;
       bfd_reloc_status_type r;
+      int tls_type;
 
       r_type = ELF64_R_TYPE (rel->r_info);
       if (r_type == (int) R_X86_64_GNU_VTINHERIT
 	  || r_type == (int) R_X86_64_GNU_VTENTRY)
 	continue;
 
-      if (r_type < 0 || r_type >= R_X86_64_max)
+      if (r_type >= R_X86_64_max)
 	{
 	  bfd_set_error (bfd_error_bad_value);
 	  return false;
@@ -1933,6 +2200,313 @@ elf64_x86_64_relocate_section (output_bf
 
 	  break;
 
+	case R_X86_64_TLSGD:
+	case R_X86_64_GOTTPOFF:
+	  r_type = elf64_x86_64_tls_transition (info, r_type, h == NULL);
+	  tls_type = GOT_UNKNOWN;
+	  if (h == NULL && local_got_offsets)
+	    tls_type = elf64_x86_64_local_got_tls_type (input_bfd) [r_symndx];
+	  else if (h != NULL)
+	    {
+	      tls_type = elf64_x86_64_hash_entry (h)->tls_type;
+	      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 (tls_type == GOT_TLS_IE)
+		r_type = R_X86_64_GOTTPOFF;
+	    }
+
+	  if (r_type == R_X86_64_TPOFF32)
+	    {
+	      BFD_ASSERT (! unresolved_reloc);
+	      if (ELF64_R_TYPE (rel->r_info) == R_X86_64_TLSGD)
+		{
+		  unsigned int i;
+		  static unsigned char tlsgd[7]
+		    = { 0x66, 0x66, 0x66, 0x66, 0x48, 0x8d, 0x3d };
+
+		  /* GD->LE transition.
+		     .long 0x66666666; leaq foo@tlsgd(%rip), %rdi
+		     callq __tls_get_addr@plt
+		     Change it into:
+		     movq %fs:0, %rax
+		     leaq foo@tpoff(%rax), %rax */
+		  BFD_ASSERT (rel->r_offset >= 7);
+		  for (i = 0; i < 7; i++)
+		    BFD_ASSERT (bfd_get_8 (input_bfd,
+					   contents + rel->r_offset - 7 + i)
+				== tlsgd[i]);
+		  BFD_ASSERT (rel->r_offset + 9 <= input_section->_raw_size);
+		  BFD_ASSERT (bfd_get_8 (input_bfd,
+					 contents + rel->r_offset + 4)
+			      == 0xe8);
+		  BFD_ASSERT (rel + 1 < relend);
+		  BFD_ASSERT (ELF64_R_TYPE (rel[1].r_info) == R_X86_64_PLT32);
+		  memcpy (contents + rel->r_offset - 7,
+			  "\x64\x48\x8b\x04\x25\0\0\0\0\x48\x8d\x80\0\0\0",
+			  16);
+		  bfd_put_32 (output_bfd, tpoff (info, relocation),
+			      contents + rel->r_offset + 5);
+		  /* Skip R_X86_64_PLT32.  */
+		  rel++;
+		  continue;
+		}
+	      else
+		{
+		  unsigned int val, type, reg;
+
+		  /* IE->LE transition:
+		     Originally it can be one of:
+		     movq foo@gottpoff(%rip), %reg
+		     addq foo@gottpoff(%rip), %reg
+		     We change it into:
+		     movq $foo, %reg
+		     leaq foo(%reg), %reg
+		     addq $foo, %reg.  */
+		  BFD_ASSERT (rel->r_offset >= 3);
+		  val = bfd_get_8 (input_bfd, contents + rel->r_offset - 3);
+		  BFD_ASSERT (val == 0x48 || val == 0x4c);
+		  type = bfd_get_8 (input_bfd, contents + rel->r_offset - 2);
+		  BFD_ASSERT (type == 0x8b || type == 0x03);
+		  reg = bfd_get_8 (input_bfd, contents + rel->r_offset - 1);
+		  BFD_ASSERT ((reg & 0xc7) == 5);
+		  reg >>= 3;
+		  BFD_ASSERT (rel->r_offset + 4 <= input_section->_raw_size);
+		  if (type == 0x8b)
+		    {
+		      /* movq */
+		      if (val == 0x4c)
+			bfd_put_8 (output_bfd, 0x49,
+				   contents + rel->r_offset - 3);
+		      bfd_put_8 (output_bfd, 0xc7,
+				 contents + rel->r_offset - 2);
+		      bfd_put_8 (output_bfd, 0xc0 | reg,
+				 contents + rel->r_offset - 1);
+		    }
+		  else if (reg == 4)
+		    {
+		      /* addq -> addq - addressing with %rsp/%r12 is
+			 special  */
+		      if (val == 0x4c)
+			bfd_put_8 (output_bfd, 0x49,
+				   contents + rel->r_offset - 3);
+		      bfd_put_8 (output_bfd, 0x81,
+				 contents + rel->r_offset - 2);
+		      bfd_put_8 (output_bfd, 0xc0 | reg,
+				 contents + rel->r_offset - 1);
+		    }
+		  else
+		    {
+		      /* addq -> leaq */
+		      if (val == 0x4c)
+			bfd_put_8 (output_bfd, 0x4d,
+				   contents + rel->r_offset - 3);
+		      bfd_put_8 (output_bfd, 0x8d,
+				 contents + rel->r_offset - 2);
+		      bfd_put_8 (output_bfd, 0x80 | reg | (reg << 3),
+				 contents + rel->r_offset - 1);
+		    }
+		  bfd_put_32 (output_bfd, tpoff (info, relocation),
+			      contents + rel->r_offset);
+		  continue;
+		}
+	    }
+
+	  if (htab->sgot == NULL)
+	    abort ();
+
+	  if (h != NULL)
+	    off = h->got.offset;
+	  else
+	    {
+	      if (local_got_offsets == NULL)
+		abort ();
+
+	      off = local_got_offsets[r_symndx];
+	    }
+
+	  if ((off & 1) != 0)
+	    off &= ~1;
+          else
+	    {
+	      Elf_Internal_Rela outrel;
+	      Elf64_External_Rela *loc;
+	      int dr_type, indx;
+
+	      if (htab->srelgot == NULL)
+		abort ();
+
+	      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)
+		dr_type = R_X86_64_DTPMOD64;
+	      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)
+		outrel.r_addend = relocation - dtpoff_base (info);
+	      outrel.r_info = ELF64_R_INFO (indx, dr_type);
+
+	      loc = (Elf64_External_Rela *) htab->srelgot->contents;
+	      loc += htab->srelgot->reloc_count++;
+	      bfd_elf64_swap_reloca_out (output_bfd, &outrel, loc);
+
+	      if (r_type == R_X86_64_TLSGD)
+		{
+		  if (indx == 0)
+		    {
+	    	      BFD_ASSERT (! unresolved_reloc);
+		      bfd_put_64 (output_bfd,
+				  relocation - dtpoff_base (info),
+				  htab->sgot->contents + off + GOT_ENTRY_SIZE);
+		    }
+		  else
+		    {
+		      bfd_put_64 (output_bfd, 0,
+				  htab->sgot->contents + off + GOT_ENTRY_SIZE);
+		      outrel.r_info = ELF64_R_INFO (indx,
+						    R_X86_64_DTPOFF64);
+		      outrel.r_offset += GOT_ENTRY_SIZE;
+		      htab->srelgot->reloc_count++;
+		      loc++;
+		      bfd_elf64_swap_reloca_out (output_bfd, &outrel,
+						 loc);
+		    }
+		}
+
+	      if (h != NULL)
+		h->got.offset |= 1;
+	      else
+		local_got_offsets[r_symndx] |= 1;
+	    }
+
+	  if (off >= (bfd_vma) -2)
+	    abort ();
+	  if (r_type == ELF64_R_TYPE (rel->r_info))
+	    {
+	      relocation = htab->sgot->output_section->vma
+			   + htab->sgot->output_offset + off;
+	      unresolved_reloc = false;
+	    }
+	  else
+	    {
+	      unsigned int i;
+	      static unsigned char tlsgd[7]
+		= { 0x66, 0x66, 0x66, 0x66, 0x48, 0x8d, 0x3d };
+
+	      /* GD->IE transition.
+		 .long 0x66666666; leaq foo@tlsgd(%rip), %rdi
+		 callq __tls_get_addr@plt
+		 Change it into:
+		 movq %fs:0, %rax
+		 addq foo@gottpoff(%rip), %rax */
+	      BFD_ASSERT (rel->r_offset >= 7);
+	      for (i = 0; i < 7; i++)
+	        BFD_ASSERT (bfd_get_8 (input_bfd,
+				       contents + rel->r_offset - 7 + i)
+			    == tlsgd[i]);
+	      BFD_ASSERT (rel->r_offset + 9 <= input_section->_raw_size);
+	      BFD_ASSERT (bfd_get_8 (input_bfd,
+				     contents + rel->r_offset + 4)
+			  == 0xe8);
+	      BFD_ASSERT (rel + 1 < relend);
+	      BFD_ASSERT (ELF64_R_TYPE (rel[1].r_info) == R_X86_64_PLT32);
+	      memcpy (contents + rel->r_offset - 7,
+		      "\x64\x48\x8b\x04\x25\0\0\0\0\x48\x03\x05\0\0\0",
+		      16);
+
+	      relocation = (htab->sgot->output_section->vma
+			    + htab->sgot->output_offset + off
+			    - rel->r_offset
+			    - input_section->output_section->vma
+			    - input_section->output_offset
+			    - 9);
+	      bfd_put_32 (output_bfd, relocation,
+			  contents + rel->r_offset + 5);
+	      /* Skip R_X86_64_PLT32.  */
+	      rel++;
+	      continue;
+	    }
+	  break;
+
+	case R_X86_64_TLSLD:
+	  if (! info->shared)
+	    {
+	      /* LD->LE transition:
+		 Ensure it is:
+		 leaq foo@tlsld(%rip), %rdi; call __tls_get_addr@plt.
+		 We change it into:
+		 .word 0x6666; .byte 0x66; movl %fs:0, %rax.  */
+	      BFD_ASSERT (rel->r_offset >= 3);
+	      BFD_ASSERT (bfd_get_8 (input_bfd, contents + rel->r_offset - 3)
+			  == 0x48);
+	      BFD_ASSERT (bfd_get_8 (input_bfd, contents + rel->r_offset - 2)
+			  == 0x8d);
+	      BFD_ASSERT (bfd_get_8 (input_bfd, contents + rel->r_offset - 1)
+			  == 0x3d);
+	      BFD_ASSERT (rel->r_offset + 9 <= input_section->_raw_size);
+	      BFD_ASSERT (bfd_get_8 (input_bfd, contents + rel->r_offset + 4)
+			  == 0xe8);
+	      BFD_ASSERT (rel + 1 < relend);
+	      BFD_ASSERT (ELF64_R_TYPE (rel[1].r_info) == R_X86_64_PLT32);
+	      memcpy (contents + rel->r_offset - 3,
+		      "\x66\x66\x66\x64\x48\x8b\x04\x25\0\0\0", 12);
+	      /* Skip R_X86_64_PLT32.  */
+	      rel++;
+	      continue;
+	    }
+
+	  if (htab->sgot == NULL)
+	    abort ();
+
+	  off = htab->tls_ld_got.offset;
+	  if (off & 1)
+	    off &= ~1;
+	  else
+	    {
+	      Elf_Internal_Rela outrel;
+	      Elf64_External_Rela *loc;
+
+	      if (htab->srelgot == NULL)
+		abort ();
+
+	      outrel.r_offset = (htab->sgot->output_section->vma
+				 + htab->sgot->output_offset + off);
+
+	      bfd_put_64 (output_bfd, 0,
+			  htab->sgot->contents + off);
+	      bfd_put_64 (output_bfd, 0,
+			  htab->sgot->contents + off + GOT_ENTRY_SIZE);
+	      outrel.r_info = ELF64_R_INFO (0, R_X86_64_DTPMOD64);
+	      outrel.r_addend = 0;
+	      loc = (Elf64_External_Rela *) htab->srelgot->contents;
+	      loc += htab->srelgot->reloc_count++;
+	      bfd_elf64_swap_reloca_out (output_bfd, &outrel, loc);
+	      htab->tls_ld_got.offset |= 1;
+	    }
+	  relocation = htab->sgot->output_section->vma
+		       + htab->sgot->output_offset + off;
+	  unresolved_reloc = false;
+	  break;
+
+	case R_X86_64_DTPOFF32:
+	  if (info->shared)
+	    relocation -= dtpoff_base (info);
+	  else
+	    relocation = tpoff (info, relocation);
+	  break;
+
+	case R_X86_64_TPOFF32:
+	  BFD_ASSERT (! info->shared);
+	  relocation = tpoff (info, relocation);
+	  break;
+
 	default:
 	  break;
 	}
@@ -2087,13 +2661,15 @@ elf64_x86_64_finish_dynamic_symbol (outp
 	}
     }
 
-  if (h->got.offset != (bfd_vma) -1)
+  if (h->got.offset != (bfd_vma) -1
+      && elf64_x86_64_hash_entry (h)->tls_type != GOT_TLS_GD
+      && elf64_x86_64_hash_entry (h)->tls_type != GOT_TLS_IE)
     {
       Elf_Internal_Rela rela;
       Elf64_External_Rela *loc;
 
       /* This symbol has an entry in the global offset table.  Set it
-         up.  */
+	 up.  */
 
       if (htab->sgot == NULL || htab->srelgot == NULL)
 	abort ();
@@ -2351,5 +2927,6 @@ elf64_x86_64_finish_dynamic_sections (ou
 #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_object_p		    elf64_x86_64_elf_object_p
+#define bfd_elf64_mkobject		    elf64_x86_64_mkobject
 
 #include "elf64-target.h"
--- bfd/elf32-i386.c.jj	2002-09-19 11:38:14.000000000 +0200
+++ bfd/elf32-i386.c	2002-09-25 18:45:11.000000000 +0200
@@ -1057,6 +1057,7 @@ elf_i386_check_relocs (abfd, info, sec, 
 	case R_386_TLS_LE:
 	  if (!info->shared)
 	    break;
+	  info->flags |= DF_STATIC_TLS;
 	  /* Fall through */	    
 
 	case R_386_32:
--- gas/config/tc-i386.c.jj	2002-09-24 14:48:05.000000000 +0200
+++ gas/config/tc-i386.c	2002-09-25 11:29:50.000000000 +0200
@@ -1235,6 +1235,11 @@ tc_i386_fix_adjustable (fixP)
       || 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
+      || fixP->fx_r_type == BFD_RELOC_X86_64_TLSGD
+      || fixP->fx_r_type == BFD_RELOC_X86_64_TLSLD
+      || fixP->fx_r_type == BFD_RELOC_X86_64_DTPOFF32
+      || fixP->fx_r_type == BFD_RELOC_X86_64_GOTTPOFF
+      || fixP->fx_r_type == BFD_RELOC_X86_64_TPOFF32
       || fixP->fx_r_type == BFD_RELOC_VTABLE_INHERIT
       || fixP->fx_r_type == BFD_RELOC_VTABLE_ENTRY)
     return 0;
@@ -1263,6 +1268,11 @@ tc_i386_fix_adjustable (fixP)
 #define BFD_RELOC_X86_64_PLT32		0
 #define BFD_RELOC_X86_64_GOT32		0
 #define BFD_RELOC_X86_64_GOTPCREL	0
+#define BFD_RELOC_X86_64_TLSGD		0
+#define BFD_RELOC_X86_64_TLSLD		0
+#define BFD_RELOC_X86_64_DTPOFF32	0
+#define BFD_RELOC_X86_64_GOTTPOFF	0
+#define BFD_RELOC_X86_64_TPOFF32	0
 #endif
 
 static int intel_float_operand PARAMS ((const char *mnemonic));
@@ -3484,12 +3494,13 @@ lex_got (reloc, adjust)
     { "PLT",      { BFD_RELOC_386_PLT32,      0, BFD_RELOC_X86_64_PLT32    } },
     { "GOTOFF",   { BFD_RELOC_386_GOTOFF,     0, 0                         } },
     { "GOTPCREL", { 0,                        0, BFD_RELOC_X86_64_GOTPCREL } },
-    { "TLSGD",    { BFD_RELOC_386_TLS_GD,     0, 0                         } },
+    { "TLSGD",    { BFD_RELOC_386_TLS_GD,     0, BFD_RELOC_X86_64_TLSGD    } },
     { "TLSLDM",   { BFD_RELOC_386_TLS_LDM,    0, 0                         } },
-    { "GOTTPOFF", { BFD_RELOC_386_TLS_IE_32,  0, 0                         } },
-    { "TPOFF",    { BFD_RELOC_386_TLS_LE_32,  0, 0                         } },
+    { "TLSLD",    { 0,                        0, BFD_RELOC_X86_64_TLSLD    } },
+    { "GOTTPOFF", { BFD_RELOC_386_TLS_IE_32,  0, BFD_RELOC_X86_64_GOTTPOFF } },
+    { "TPOFF",    { BFD_RELOC_386_TLS_LE_32,  0, BFD_RELOC_X86_64_TPOFF32  } },
     { "NTPOFF",   { BFD_RELOC_386_TLS_LE,     0, 0                         } },
-    { "DTPOFF",   { BFD_RELOC_386_TLS_LDO_32, 0, 0                         } },
+    { "DTPOFF",   { BFD_RELOC_386_TLS_LDO_32, 0, BFD_RELOC_X86_64_DTPOFF32 } },
     { "GOTNTPOFF",{ BFD_RELOC_386_TLS_GOTIE,  0, 0                         } },
     { "INDNTPOFF",{ BFD_RELOC_386_TLS_IE,     0, 0                         } },
     { "GOT",      { BFD_RELOC_386_GOT32,      0, BFD_RELOC_X86_64_GOT32    } }
@@ -4665,6 +4676,9 @@ md_apply_fix3 (fixP, valP, seg)
       case BFD_RELOC_386_TLS_IE:
       case BFD_RELOC_386_TLS_GOTIE:
       case BFD_RELOC_X86_64_GOT32:
+      case BFD_RELOC_X86_64_TLSGD:
+      case BFD_RELOC_X86_64_TLSLD:
+      case BFD_RELOC_X86_64_GOTTPOFF:
 	value = 0; /* Fully resolved at runtime.  No addend.  */
 	break;
 
@@ -5149,6 +5163,11 @@ tc_gen_reloc (section, fixp)
     case BFD_RELOC_386_TLS_LE_32:
     case BFD_RELOC_386_TLS_LE:
     case BFD_RELOC_X86_64_32S:
+    case BFD_RELOC_X86_64_TLSGD:
+    case BFD_RELOC_X86_64_TLSLD:
+    case BFD_RELOC_X86_64_DTPOFF32:
+    case BFD_RELOC_X86_64_GOTTPOFF:
+    case BFD_RELOC_X86_64_TPOFF32:
     case BFD_RELOC_RVA:
     case BFD_RELOC_VTABLE_ENTRY:
     case BFD_RELOC_VTABLE_INHERIT:
@@ -5226,6 +5245,9 @@ tc_gen_reloc (section, fixp)
 	  case BFD_RELOC_X86_64_PLT32:
 	  case BFD_RELOC_X86_64_GOT32:
 	  case BFD_RELOC_X86_64_GOTPCREL:
+	  case BFD_RELOC_X86_64_TLSGD:
+	  case BFD_RELOC_X86_64_TLSLD:
+	  case BFD_RELOC_X86_64_GOTTPOFF:
 	    rel->addend = fixp->fx_offset - fixp->fx_size;
 	    break;
 	  default:
--- include/elf/x86-64.h.jj	2001-04-24 20:42:12.000000000 +0200
+++ include/elf/x86-64.h	2002-09-25 11:29:50.000000000 +0200
@@ -1,5 +1,5 @@
 /* x86_64 ELF support for BFD.
-   Copyright (C) 2000 Free Software Foundation, Inc.
+   Copyright (C) 2000, 2002 Free Software Foundation, Inc.
    Contributed by Jan Hubicka <jh@suse.cz>
 
    This file is part of BFD, the Binary File Descriptor library.
@@ -25,22 +25,30 @@
 
 START_RELOC_NUMBERS (elf_x86_64_reloc_type)
      RELOC_NUMBER (R_X86_64_NONE,     0)      /* No reloc */
-     RELOC_NUMBER (R_X86_64_64,               1)      /* Direct 64 bit  */
+     RELOC_NUMBER (R_X86_64_64,       1)      /* Direct 64 bit  */
      RELOC_NUMBER (R_X86_64_PC32,     2)      /* PC relative 32 bit signed */
      RELOC_NUMBER (R_X86_64_GOT32,    3)      /* 32 bit GOT entry */
      RELOC_NUMBER (R_X86_64_PLT32,    4)      /* 32 bit PLT address */
      RELOC_NUMBER (R_X86_64_COPY,     5)      /* Copy symbol at runtime */
      RELOC_NUMBER (R_X86_64_GLOB_DAT, 6)      /* Create GOT entry */
-     RELOC_NUMBER (R_X86_64_JUMP_SLOT,        7)      /* Create PLT entry */
+     RELOC_NUMBER (R_X86_64_JUMP_SLOT,7)      /* Create PLT entry */
      RELOC_NUMBER (R_X86_64_RELATIVE, 8)      /* Adjust by program base */
      RELOC_NUMBER (R_X86_64_GOTPCREL, 9)      /* 32 bit signed pc relative
                                                  offset to GOT */
-     RELOC_NUMBER (R_X86_64_32,               10)     /* Direct 32 bit zero extended */
-     RELOC_NUMBER (R_X86_64_32S,              11)     /* Direct 32 bit sign extended */
-     RELOC_NUMBER (R_X86_64_16,               12)     /* Direct 16 bit zero extended */
+     RELOC_NUMBER (R_X86_64_32,       10)     /* Direct 32 bit zero extended */
+     RELOC_NUMBER (R_X86_64_32S,      11)     /* Direct 32 bit sign extended */
+     RELOC_NUMBER (R_X86_64_16,       12)     /* Direct 16 bit zero extended */
      RELOC_NUMBER (R_X86_64_PC16,     13)     /* 16 bit sign extended pc relative*/
-     RELOC_NUMBER (R_X86_64_8,                14)     /* Direct 8 bit sign extended */
-     RELOC_NUMBER (R_X86_64_PC8,              15)     /* 8 bit sign extended pc relative*/
+     RELOC_NUMBER (R_X86_64_8,        14)     /* Direct 8 bit sign extended */
+     RELOC_NUMBER (R_X86_64_PC8,      15)     /* 8 bit sign extended pc relative*/
+     RELOC_NUMBER (R_X86_64_DTPMOD64, 16)     /* ID of module containing symbol */
+     RELOC_NUMBER (R_X86_64_DTPOFF64, 17)     /* Offset in TLS block */
+     RELOC_NUMBER (R_X86_64_TPOFF64,  18)     /* Offset in initial TLS block */
+     RELOC_NUMBER (R_X86_64_TLSGD,    19)     /* PC relative offset to GD GOT block */
+     RELOC_NUMBER (R_X86_64_TLSLD,    20)     /* PC relative offset to LD GOT block */
+     RELOC_NUMBER (R_X86_64_DTPOFF32, 21)     /* Offset in TLS block */
+     RELOC_NUMBER (R_X86_64_GOTTPOFF, 22)     /* PC relative offset to IE GOT entry */
+     RELOC_NUMBER (R_X86_64_TPOFF32,  23)     /* Offset in initial TLS block */
      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)
--- ld/testsuite/lib/ld-lib.exp.jj	2002-07-18 11:38:47.000000000 +0200
+++ ld/testsuite/lib/ld-lib.exp	2002-09-25 14:27:57.000000000 +0200
@@ -961,6 +961,136 @@ proc file_contents { filename } {
     return $contents
 }
 
+# List contains test-items with 3 items followed by 2 lists:
+# 0:name 1:ld options 2:assembler options
+# 3:filenames of assembler files 4: action and options. 5: name of output file
+
+# Actions:
+# objdump: Apply objdump options on result.  Compare with regex (last arg).
+# nm: Apply nm options on result.  Compare with regex (last arg).
+# readelf: Apply readelf options on result.  Compare with regex (last arg).
+
+proc run_ld_link_tests { ldtests } {
+    global ld
+    global as
+    global nm
+    global objdump
+    global READELF
+    global srcdir
+    global subdir
+    global env
+
+    foreach testitem $ldtests {
+	set testname [lindex $testitem 0]
+	set ld_options [lindex $testitem 1]
+	set as_options [lindex $testitem 2]
+	set as_files  [lindex $testitem 3]
+	set actions [lindex $testitem 4]
+	set binfile tmpdir/[lindex $testitem 5]
+	set objfiles {}
+	set is_unresolved 0
+	set failed 0
+
+#	verbose -log "Testname is $testname"
+#	verbose -log "ld_options is $ld_options"
+#	verbose -log "as_options is $as_options"
+#	verbose -log "as_files is $as_files"
+#	verbose -log "actions is $actions"
+#	verbose -log "binfile is $binfile"
+
+	# Assemble each file in the test.
+	foreach as_file $as_files {
+	    set objfile "tmpdir/[file rootname $as_file].o"
+	    lappend objfiles $objfile
+
+	    if ![ld_assemble $as "$as_options $srcdir/$subdir/$as_file" $objfile] {
+		set is_unresolved 1
+		break
+	    }
+	}
+
+	# Catch assembler errors.
+	if { $is_unresolved != 0 } {
+	    unresolved $testname
+	    continue
+	}
+
+	if ![ld_simple_link $ld $binfile "-L$srcdir/$subdir $ld_options $objfiles"] {
+	    fail $testname
+	} else {
+	    set failed 0
+	    foreach actionlist $actions {
+		set action [lindex $actionlist 0]
+		set progopts [lindex $actionlist 1]
+
+		# There are actions where we run regexp_diff on the
+		# output, and there are other actions (presumably).
+		# Handling of the former look the same.
+		set dump_prog ""
+		switch -- $action {
+		    objdump
+		        { set dump_prog $objdump }
+		    nm
+		        { set dump_prog $nm }
+		    readelf
+		        { set dump_prog $READELF }
+		    default
+			{
+			    perror "Unrecognized action $action"
+			    set is_unresolved 1
+			    break
+			}
+		    }
+
+		if { $dump_prog != "" } {
+		    set dumpfile [lindex $actionlist 2]
+		    set binary $dump_prog
+
+		    # Ensure consistent sorting of symbols
+		    if {[info exists env(LC_ALL)]} {
+			set old_lc_all $env(LC_ALL)
+		    }
+		    set env(LC_ALL) "C"
+		    set cmd "$binary $progopts $binfile > dump.out"
+		    send_log "$cmd\n"
+		    catch "exec $cmd" comp_output
+		    if {[info exists old_lc_all]} {
+			set env(LC_ALL) $old_lc_all
+		    } else {
+			unset env(LC_ALL)
+		    }
+		    set comp_output [prune_warnings $comp_output]
+
+		    if ![string match "" $comp_output] then {
+			send_log "$comp_output\n"
+			set failed 1
+			break
+		    }
+
+		    if { [regexp_diff "dump.out" "$srcdir/$subdir/$dumpfile"] } then {
+			verbose "output is [file_contents "dump.out"]" 2
+			set failed 1
+			break
+		    }
+		}
+	    }
+
+	    if { $failed != 0 } {
+		fail $testname
+	    } else { if { $is_unresolved == 0 } {
+		pass $testname
+	    } }
+	}
+
+	# Catch action errors.
+	if { $is_unresolved != 0 } {
+	    unresolved $testname
+	    continue
+	}
+    }
+}
+
+
 proc verbose_eval { expr { level 1 } } {
     global verbose
     if $verbose>$level then { eval verbose "$expr" $level }
--- ld/testsuite/ld-sh/sh64/sh64.exp.jj	2002-09-10 14:51:15.000000000 +0200
+++ ld/testsuite/ld-sh/sh64/sh64.exp	2002-09-25 14:25:35.000000000 +0200
@@ -23,18 +23,14 @@ if ![istarget sh64-*-*] {
     return
 }
 
-# FIXME: This isn't set by testsuite/config/default.exp; make it.
-if ![info exists readelf] then {
-    set readelf [findfile $base_dir/../binutils/readelf]
-}
-
 # List contains test-items with 3 items followed by 2 lists:
 # 0:name 1:ld options 2:assembler options
-# 3:filenames of assembler files 4: action and options.
+# 3:filenames of assembler files 4: action and options. 5: name of output file
 
 # Actions:
 # objdump: Apply objdump options on result.  Compare with regex (last arg).
 # nm: Apply nm options on result.  Compare with regex (last arg).
+# readelf: Apply readelf options on result.  Compare with regex (last arg).
 
 # Note that the contents dump is the same for "inter-file datalabel
 # references, 64-bit ABI" as for 32-bit ABI and ELF so we re-use it.
@@ -42,323 +38,89 @@ if ![info exists readelf] then {
 set sh64tests {
     {"SH64 linking, 64-bit ABI" "-mshelf64"
      "--abi=64" {sh64-1.s sh64-2.s}
-     {{objdump -sr abi64.sd} {objdump -x abi64.xd}}}
+     {{objdump -sr abi64.sd} {objdump -x abi64.xd}} "abi64.bin" }
     {"SH64 linking, 64-bit ABI, -no-expand" "-mshelf64"
      "--abi=64 -no-expand" {sh64-1.s sh64-2.s}
-     {{objdump -sr abixx-noexp.sd}}}
+     {{objdump -sr abixx-noexp.sd}} "abi64-noexp.bin" }
     {"SH64 linking, 32-bit ABI" "-mshelf32"
      "--abi=32" {sh64-1.s sh64-2.s}
-     {{objdump -sr abi32.sd} {objdump -x abi32.xd}}}
+     {{objdump -sr abi32.sd} {objdump -x abi32.xd}} "abi32.bin" }
     {"SH64 linking, 32-bit ABI, -no-expand" "-mshelf32"
      "--abi=32 -no-expand" {sh64-1.s sh64-2.s}
-     {{objdump -sr abixx-noexp.sd}}}
+     {{objdump -sr abixx-noexp.sd}} "abi32-noexp.bin" }
     {"SH64 linking, single multi-ISA object" "-mshelf32"
      "--abi=32" {shmix-1.s}
-     {{objdump -sr mix1.sd} {objdump -x mix1.xd}}}
+     {{objdump -sr mix1.sd} {objdump -x mix1.xd}} "mix1.bin" }
     {"SH64 linking, single multi-ISA object, -no-expand" "-mshelf32"
      "--abi=32 -no-expand" {shmix-1.s}
-     {{objdump -sr mix1-noexp.sd}}}
+     {{objdump -sr mix1-noexp.sd}} "mix1-noexp.bin" }
     {"SH64 linking, two different-ISA objects" "-mshelf32"
      "--abi=32" {shmix-2.s shmix-3.s}
-     {{objdump -sr mix2.sd} {objdump -x mix2.xd}}}
+     {{objdump -sr mix2.sd} {objdump -x mix2.xd}} "mix2.bin" }
     {"SH64 linking, two different-ISA objects, -no-expand" "-mshelf32"
      "--abi=32 -no-expand" {shmix-2.s shmix-3.s}
-     {{objdump -sr mix2-noexp.sd}}}
+     {{objdump -sr mix2-noexp.sd}} "mix2-noexp.bin" }
     {"SH64 linking, single SHcompact" "-mshelf32"
      "--isa=SHcompact" {shcmp-1.s}
-     {{objdump -sr cmpct1.sd} {objdump -x cmpct1.xd}}}
+     {{objdump -sr cmpct1.sd} {objdump -x cmpct1.xd}} "cmpct1.bin" }
     {"SH64 inter-file datalabel references, 64-bit ABI" "-mshelf64"
      "--abi=64" {shdl-1.s shdl-2.s}
-     {{objdump -sr shdl64.sd} {objdump -x shdl64.xd}}}
+     {{objdump -sr shdl64.sd} {objdump -x shdl64.xd}} "shdl64.bin" }
     {"SH64 inter-file datalabel references, 32-bit ABI" "-mshelf32"
      "--abi=32" {shdl-1.s shdl-2.s}
-     {{objdump -sr shdl64.sd} {objdump -x shdl32.xd}}}
+     {{objdump -sr shdl64.sd} {objdump -x shdl32.xd}} "shdl32.bin" }
     {"SH64 inter-file datalabel references and gc-sections, 32-bit ABI" "-mshelf32 --gc-sections"
      "--abi=32" {dlsection-1.s }
-     {{objdump -sr dlsection.sd}}}
+     {{objdump -sr dlsection.sd}} "dlsection32.bin" }
     {"SH64 inter-file datalabel references and gc-sections, 64-bit ABI" "-mshelf64 --gc-sections"
      "--abi=64" {dlsection-1.s }
-     {{objdump -sr dlsection.sd}}}
+     {{objdump -sr dlsection.sd}} "dlsection64.bin" }
     {"SH64 simple partial linking, 32-bit ABI" "-mshelf32 -r"
      "--abi=32" {rel-1.s rel-2.s}
-     {{objdump -sx rel32.xd}}}
+     {{objdump -sx rel32.xd}} "rel32.bin" }
     {"SH64 simple partial linking, 64-bit ABI" "-mshelf64 -r"
      "--abi=64" {rel-1.s rel-2.s}
-     {{objdump -sx rel64.xd}}}
+     {{objdump -sx rel64.xd}} "rel64.bin" }
     {"SH64 partial linking with datalabel references, 32-bit ABI" "-mshelf32 -r"
      "--abi=32" {reldl-1.s reldl-2.s}
-     {{readelf {-s -r -x 1 -x 3} reldl32.rd}}}
+     {{readelf {-s -r -x 1 -x 3} reldl32.rd}} "reldl32.bin" }
     {"SH64 partial linking with datalabel references, 64-bit ABI" "-mshelf64 -r"
      "--abi=64" {reldl-1.s reldl-2.s}
-     {{readelf {-s -r -x 1 -x 3} reldl64.rd}}}
+     {{readelf {-s -r -x 1 -x 3} reldl64.rd}} "reldl64.bin" }
     {"Handling SH64 assembler-generated .cranges" "-mshelf32"
      "--abi=32" {crange-2a.s crange-1.s}
-     {{readelf {-S -s -r -x 1 -x 2 -x 9} crange1.rd}}}
+     {{readelf {-S -s -r -x 1 -x 2 -x 9} crange1.rd}} "crange1.bin" }
     {"Handling SH64 assembler-generated .cranges, partial linking" "-mshelf32 -r"
      "--abi=32" {crange-2a.s}
-     {{readelf {-S -s -r -x 2 -x 5} crangerel1.rd}}}
+     {{readelf {-S -s -r -x 2 -x 5} crangerel1.rd}} "crangerel1.bin" }
     {"Mixing SH64 assembler-generated with linker-generated .cranges" "-mshelf32"
      "--abi=32" {crange-2a.s crange-2b.s crange-1.s}
-     {{readelf {-S -s -r -x 2 -x 9} crange2.rd}}}
+     {{readelf {-S -s -r -x 2 -x 9} crange2.rd}} "crange2.bin" }
     {"Mixing SH64 assembler-generated with linker-generated .cranges, partial linking"
      "-mshelf32 -r"
      "--abi=32" {crange-2a.s crange-2c.s crange-2d.s crange-2e.s}
-     {{readelf {-S -s -r -x 2 -x 5} crangerel2.rd}}}
+     {{readelf {-S -s -r -x 2 -x 5} crangerel2.rd}} "crangerel2.bin" }
     {"Merge and use of SH64 .cranges, some not originally in order" "-mshelf32"
      "--abi=32"
      {crange-2e.s crange-2f.s crange-2g.s crange-2a.s crange-2d.s crange-2i.s
       crange-2h.s crange-1.s}
-      {{readelf {-S -s -x 2 -x 9} crange3.rd} {objdump -d crange3.dd}}}
+      {{readelf {-S -s -x 2 -x 9} crange3.rd} {objdump -d crange3.dd}} "crange3.bin" }
     {"Sorted SH64 .cranges, entry at SHcompact code" "-mshelf32 --entry diversion"
      "--abi=32"
      {crange-2e.s crange-2f.s crange-2g.s crange-2a.s crange-2d.s crange-2i.s
       crange-2h.s crange-1.s}
-      {{readelf {-h -S -s -x 2 -x 9} crange3-cmpct.rd}}}
+      {{readelf {-h -S -s -x 2 -x 9} crange3-cmpct.rd}} "crange3-cmpct.bin" }
     {"Sorted SH64 .cranges, entry at SHmedia code" "-mshelf32 --entry diversion2"
      "--abi=32"
      {crange-2e.s crange-2f.s crange-2g.s crange-2a.s crange-2d.s crange-2i.s
       crange-2h.s crange-1.s}
-      {{readelf {-h -S -s -x 2 -x 9} crange3-media.rd}}}
+      {{readelf {-h -S -s -x 2 -x 9} crange3-media.rd}} "crange3-media.bin" }
     {"SH64 Big Endianness" "-mshelf64 -Tendian.ld"
      "--abi=64" {endian.s}
-     {{objdump -s endian.sbd} {objdump -d endian.dbd}}}
+     {{objdump -s endian.sbd} {objdump -d endian.dbd}} "endianb.bin" }
     {"SH64 Little Endianness" "-mshlelf64 -Tendian.ld"
      "--abi=64 --little" {endian.s}
-     {{objdump -s endian.sld} {objdump -d endian.dld}}}
-
-}
-
-# FIXME: Generalize and move this to ld-lib.exp
-
-proc run_ld_link_tests { ldtests } {
-    global ld
-    global as
-    global nm
-    global objdump
-    global readelf
-    global srcdir
-    global subdir
-    global env
-
-    set binfile "tmpdir/linked"
-
-    foreach testitem $ldtests {
-	set testname [lindex $testitem 0]
-	set ld_options [lindex $testitem 1]
-	set as_options [lindex $testitem 2]
-	set as_files  [lindex $testitem 3]
-	set actions [lindex $testitem 4]
-	set objfiles {}
-	set is_unresolved 0
-	set failed 0
-
-#	verbose -log "Testname is $testname"
-#	verbose -log "ld_options is $ld_options"
-#	verbose -log "as_options is $as_options"
-#	verbose -log "as_files is $as_files"
-#	verbose -log "actions is $actions"
-
-	# Assemble each file in the test.
-	foreach as_file $as_files {
-	    set objfile "tmpdir/[file rootname $as_file].o"
-	    lappend objfiles $objfile
-
-	    if ![ld_assemble $as "$as_options $srcdir/$subdir/$as_file" $objfile] {
-		set is_unresolved 1
-		break
-	    }
-	}
-
-	# Catch assembler errors.
-	if { $is_unresolved != 0 } {
-	    unresolved $testname
-	    continue
-	}
-
-	if ![ld_simple_link $ld $binfile "-L$srcdir/$subdir $ld_options $objfiles"] {
-	    fail $testname
-	} else {
-	    set failed 0
-	    foreach actionlist $actions {
-		set action [lindex $actionlist 0]
-		set progopts [lindex $actionlist 1]
-
-		# There are actions where we run regexp_diff on the
-		# output, and there are other actions (presumably).
-		# Handling of the former look the same.
-		set dump_prog ""
-		switch -- $action {
-		    objdump
-		        { set dump_prog $objdump }
-		    nm
-		        { set dump_prog $nm }
-		    readelf
-		        { set dump_prog $readelf }
-		    default
-			{
-			    perror "Unrecognized action $action"
-			    set is_unresolved 1
-			    break
-			}
-		    }
-
-		if { $dump_prog != "" } {
-		    set dumpfile [lindex $actionlist 2]
-		    set binary $dump_prog
-
-		    # Ensure consistent sorting of symbols
-		    if {[info exists env(LC_ALL)]} {
-			set old_lc_all $env(LC_ALL)
-		    }
-		    set env(LC_ALL) "C"
-		    set cmd "$binary $progopts $binfile > dump.out"
-		    send_log "$cmd\n"
-		    catch "exec $cmd" comp_output
-		    if {[info exists old_lc_all]} {
-			set env(LC_ALL) $old_lc_all
-		    } else {
-			unset env(LC_ALL)
-		    }
-		    set comp_output [prune_warnings $comp_output]
-
-		    if ![string match "" $comp_output] then {
-			send_log "$comp_output\n"
-			set failed 1
-			break
-		    }
-
-		    if { [regexp_diff "dump.out" "$srcdir/$subdir/$dumpfile"] } then {
-			verbose "output is [file_contents "dump.out"]" 2
-			set failed 1
-			break
-		    }
-		}
-	    }
-
-	    if { $failed != 0 } {
-		fail $testname
-	    } else { if { $is_unresolved == 0 } {
-		pass $testname
-	    } }
-	}
-
-	# Catch action errors.
-	if { $is_unresolved != 0 } {
-	    unresolved $testname
-	    continue
-	}
-    }
-}
-
-# FIXME: Move this to ld-lib.exp or higher up.
-
-# regexp_diff, based on simple_diff taken from ld test suite
-#	compares two files line-by-line
-#	file1 contains strings, file2 contains regexps and #-comments
-#	blank lines are ignored in either file
-#	returns non-zero if differences exist
-#
-proc regexp_diff { file_1 file_2 } {
-
-    set eof -1
-    set end_1 0
-    set end_2 0
-    set differences 0
-    set diff_pass 0
-
-    if [file exists $file_1] then {
-	set file_a [open $file_1 r]
-    } else {
-	warning "$file_1 doesn't exist"
-	return 1
-    }
-
-    if [file exists $file_2] then {
-	set file_b [open $file_2 r]
-    } else {
-	fail "$file_2 doesn't exist"
-	close $file_a
-	return 1
-    }
-
-    verbose " Regexp-diff'ing: $file_1 $file_2" 2
-
-    while { 1 } {
-	set line_a ""
-	set line_b ""
-	while { [string length $line_a] == 0 } {
-	    if { [gets $file_a line_a] == $eof } {
-		set end_1 1
-		break
-	    }
-	}
-	while { [string length $line_b] == 0 || [string match "#*" $line_b] } {
-	    if [ string match "#pass" $line_b ] {
-		set end_2 1
-		set diff_pass 1
-		break
-	    } elseif [ string match "#..." $line_b ] {
-		if { [gets $file_b line_b] == $eof } {
-		    set end_2 1
-		    break
-		}
-		verbose "looking for \"^$line_b$\"" 3
-		while { ![regexp "^$line_b$" "$line_a"] } {
-		    verbose "skipping    \"$line_a\"" 3
-		    if { [gets $file_a line_a] == $eof } {
-			set end_1 1
-			break
-		    }
-		}
-		break
-	    }
-	    if { [gets $file_b line_b] == $eof } {
-		set end_2 1
-		break
-	    }
-	}
-
-        if { $diff_pass } {
-            break
-        } elseif { $end_1 && $end_2 } {
-            break
-        } elseif { $end_1 } {
-            send_log "extra regexps in $file_2 starting with \"^$line_b$\"\nEOF from $file_1\n"
-            verbose "extra regexps in $file_2 starting with \"^$line_b$\"\nEOF from $file_1" 3
-            set differences 1
-            break
-        } elseif { $end_2 } {
-            send_log "extra lines in $file_1 starting with \"^$line_a$\"\nEOF from $file_2\n"
-            verbose "extra lines in $file_1 starting with \"^$line_a$\"\nEOF from $file_2\n" 3
-            set differences 1
-            break
-        } else {
-            verbose "regexp \"^$line_b$\"\nline   \"$line_a\"" 3
-            if ![regexp "^$line_b$" "$line_a"] {
-		send_log "regexp_diff match failure\n"
-		send_log "regexp \"^$line_b$\"\nline   \"$line_a\"\n"
-		set differences 1
-            }
-        }
-    }
-
-    if { $differences == 0 && !$diff_pass && [eof $file_a] != [eof $file_b] } {
-	send_log "$file_1 and $file_2 are different lengths\n"
-	verbose "$file_1 and $file_2 are different lengths" 3
-	set differences 1
-    }
-
-    close $file_a
-    close $file_b
-
-    return $differences
-}
-
-proc file_contents { filename } {
-    set file [open $filename r]
-    set contents [read $file]
-    close $file
-    return $contents
+     {{objdump -s endian.sld} {objdump -d endian.dld}} "endinanl.bin" }
 }
 
 run_ld_link_tests $sh64tests
--- ld/testsuite/ld-i386/i386.exp.jj	2002-09-21 23:44:55.000000000 +0200
+++ ld/testsuite/ld-i386/i386.exp	2002-09-25 14:17:27.000000000 +0200
@@ -1,5 +1,5 @@
 # Expect script for ld-i386 tests
-#   Copyright (C) 2000, 2001, 2002 Free Software Foundation
+#   Copyright (C) 2002 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
@@ -26,11 +26,6 @@ if { !([istarget "i?86-*-elf*"]		
     return
 }
 
-# FIXME: This isn't set by testsuite/config/default.exp; make it.
-if ![info exists readelf] then {
-    set readelf [findfile $base_dir/../binutils/readelf]
-}
-
 # List contains test-items with 3 items followed by 2 lists:
 # 0:name 1:ld options 2:assembler options
 # 3:filenames of assembler files 4: action and options. 5: name of output file
@@ -59,126 +54,4 @@ set i386tests {
       {objdump -sj.got tlsnopic.sd}} "libtlsnopic.so"}
 }
 
-# FIXME: Generalize and move this to ld-lib.exp
-
-proc run_ld_link_tests { ldtests } {
-    global ld
-    global as
-    global nm
-    global objdump
-    global readelf
-    global srcdir
-    global subdir
-    global env
-
-    foreach testitem $ldtests {
-	set testname [lindex $testitem 0]
-	set ld_options [lindex $testitem 1]
-	set as_options [lindex $testitem 2]
-	set as_files  [lindex $testitem 3]
-	set actions [lindex $testitem 4]
-	set binfile tmpdir/[lindex $testitem 5]
-	set objfiles {}
-	set is_unresolved 0
-	set failed 0
-
-#	verbose -log "Testname is $testname"
-#	verbose -log "ld_options is $ld_options"
-#	verbose -log "as_options is $as_options"
-#	verbose -log "as_files is $as_files"
-#	verbose -log "actions is $actions"
-#	verbose -log "binfile is $binfile"
-
-	# Assemble each file in the test.
-	foreach as_file $as_files {
-	    set objfile "tmpdir/[file rootname $as_file].o"
-	    lappend objfiles $objfile
-
-	    if ![ld_assemble $as "$as_options $srcdir/$subdir/$as_file" $objfile] {
-		set is_unresolved 1
-		break
-	    }
-	}
-
-	# Catch assembler errors.
-	if { $is_unresolved != 0 } {
-	    unresolved $testname
-	    continue
-	}
-
-	if ![ld_simple_link $ld $binfile "-L$srcdir/$subdir $ld_options $objfiles"] {
-	    fail $testname
-	} else {
-	    set failed 0
-	    foreach actionlist $actions {
-		set action [lindex $actionlist 0]
-		set progopts [lindex $actionlist 1]
-
-		# There are actions where we run regexp_diff on the
-		# output, and there are other actions (presumably).
-		# Handling of the former look the same.
-		set dump_prog ""
-		switch -- $action {
-		    objdump
-		        { set dump_prog $objdump }
-		    nm
-		        { set dump_prog $nm }
-		    readelf
-		        { set dump_prog $readelf }
-		    default
-			{
-			    perror "Unrecognized action $action"
-			    set is_unresolved 1
-			    break
-			}
-		    }
-
-		if { $dump_prog != "" } {
-		    set dumpfile [lindex $actionlist 2]
-		    set binary $dump_prog
-
-		    # Ensure consistent sorting of symbols
-		    if {[info exists env(LC_ALL)]} {
-			set old_lc_all $env(LC_ALL)
-		    }
-		    set env(LC_ALL) "C"
-		    set cmd "$binary $progopts $binfile > dump.out"
-		    send_log "$cmd\n"
-		    catch "exec $cmd" comp_output
-		    if {[info exists old_lc_all]} {
-			set env(LC_ALL) $old_lc_all
-		    } else {
-			unset env(LC_ALL)
-		    }
-		    set comp_output [prune_warnings $comp_output]
-
-		    if ![string match "" $comp_output] then {
-			send_log "$comp_output\n"
-			set failed 1
-			break
-		    }
-
-		    if { [regexp_diff "dump.out" "$srcdir/$subdir/$dumpfile"] } then {
-			verbose "output is [file_contents "dump.out"]" 2
-			set failed 1
-			break
-		    }
-		}
-	    }
-
-	    if { $failed != 0 } {
-		fail $testname
-	    } else { if { $is_unresolved == 0 } {
-		pass $testname
-	    } }
-	}
-
-	# Catch action errors.
-	if { $is_unresolved != 0 } {
-	    unresolved $testname
-	    continue
-	}
-    }
-}
-
 run_ld_link_tests $i386tests
--- ld/testsuite/ld-x86-64/tlspic1.s.jj	2002-09-25 11:29:50.000000000 +0200
+++ ld/testsuite/ld-x86-64/tlspic1.s	2002-09-26 16:11:31.000000000 +0200
@@ -0,0 +1,171 @@
+	/* 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 */
+	.long	0x66666666
+	leaq	sg1@tlsgd(%rip), %rdi
+	call	__tls_get_addr@plt
+	nop;nop;nop;nop
+
+	/* GD -> IE because variable is referenced through IE too */
+	.long	0x66666666
+	leaq	sg2@tlsgd(%rip), %rdi
+	call	__tls_get_addr@plt
+	nop;nop;nop;nop
+
+	/* GD against local variable */
+	.long	0x66666666
+	leaq	sl1@tlsgd(%rip), %rdi
+	call	__tls_get_addr@plt
+	nop;nop;nop;nop
+
+	/* GD -> IE against local variable referenced through IE too */
+	.long	0x66666666
+	leaq	sl2@tlsgd(%rip), %rdi
+	call	__tls_get_addr@plt
+	nop;nop;nop;nop
+
+	/* GD against hidden and local variable */
+	.long	0x66666666
+	leaq	sh1@tlsgd(%rip), %rdi
+	call	__tls_get_addr@plt
+	nop;nop;nop;nop
+
+	/* GD -> IE against hidden and local variable referenced through
+	   IE too */
+	.long	0x66666666
+	leaq	sh2@tlsgd(%rip), %rdi
+	call	__tls_get_addr@plt
+	nop;nop;nop;nop
+
+	/* GD against hidden but not local variable */
+	.long	0x66666666
+	leaq	sH1@tlsgd(%rip), %rdi
+	call	__tls_get_addr@plt
+	nop;nop;nop;nop
+
+	/* GD -> IE against hidden but not local variable referenced through
+	   IE too */
+	.long	0x66666666
+	leaq	sH2@tlsgd(%rip), %rdi
+	call	__tls_get_addr@plt
+	nop;nop;nop;nop
+
+	/* LD */
+	leaq	sl1@tlsld(%rip), %rdi
+	call	__tls_get_addr@plt
+	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@tlsld(%rip), %rdi
+	call	__tls_get_addr@plt
+	nop;nop
+	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@tlsld(%rip), %rdi
+	call	__tls_get_addr@plt
+	nop;nop
+	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
--- ld/testsuite/ld-x86-64/x86-64.exp.jj	2002-09-25 11:29:50.000000000 +0200
+++ ld/testsuite/ld-x86-64/x86-64.exp	2002-09-26 13:18:22.000000000 +0200
@@ -0,0 +1,51 @@
+# Expect script for ld-x86_64 tests
+#   Copyright (C) 2002 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
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+#
+
+# Test x86_64 linking; all types of relocs.  This tests the assembler and
+# tools like objdump as well as the linker.
+
+if { !([istarget "x86_64-*-elf*"]
+       || [istarget "x86_64-*-linux*"]) } {
+    return
+}
+
+# List contains test-items with 3 items followed by 2 lists:
+# 0:name 1:ld options 2:assembler options
+# 3:filenames of assembler files 4: action and options. 5: name of output file
+
+# Actions:
+# objdump: Apply objdump options on result.  Compare with regex (last arg).
+# nm: Apply nm options on result.  Compare with regex (last arg).
+# readelf: Apply readelf options on result.  Compare with regex (last arg).
+
+set x86_64tests {
+    {"TLS -fpic -shared transitions" "-shared -melf_x86_64"
+     "--64" {tlspic1.s tlspic2.s}
+     {{readelf -WSsrl tlspic.rd} {objdump -drj.text tlspic.dd}
+      {objdump -sj.got tlspic.sd} {objdump -sj.tdata tlspic.td}}
+      "libtlspic.so"}
+    {"Helper shared library" "-shared -melf_x86_64"
+     "--64" {tlslib.s} {} "libtlslib.so"}
+    {"TLS -fpic and -fno-pic exec transitions"
+     "-melf_x86_64 tmpdir/libtlslib.so" "--64" {tlsbinpic.s tlsbin.s}
+     {{readelf -WSsrl tlsbin.rd} {objdump -drj.text tlsbin.dd}
+      {objdump -sj.got tlsbin.sd} {objdump -sj.tdata tlsbin.td}}
+      "tlsbin"}
+}
+
+run_ld_link_tests $x86_64tests
--- ld/testsuite/ld-x86-64/tlspic2.s.jj	2002-09-25 11:29:50.000000000 +0200
+++ ld/testsuite/ld-x86-64/tlspic2.s	2002-09-25 11:30:19.000000000 +0200
@@ -0,0 +1,11 @@
+	.section ".tbss", "awT", @nobits
+	.globl sH1, sH2, sH3, sH4, sH5, sH6, sH7, sH8
+	.hidden sH1, sH2, sH3, sH4, sH5, sH6, sH7, sH8
+sH1:	.space 4
+sH2:	.space 4
+sH3:	.space 4
+sH4:	.space 4
+sH5:	.space 4
+sH6:	.space 4
+sH7:	.space 4
+sH8:	.space 4
--- ld/testsuite/ld-x86-64/tlsbin.s.jj	2002-09-25 11:29:50.000000000 +0200
+++ ld/testsuite/ld-x86-64/tlsbin.s	2002-09-26 16:18:32.000000000 +0200
@@ -0,0 +1,97 @@
+	.section ".tbss", "awT", @nobits
+	.globl bg1, bg2, bg3, bg4, bg5, bg6, bg7, bg8
+bg1:	.space 4
+bg2:	.space 4
+bg3:	.space 4
+bg4:	.space 4
+bg5:	.space 4
+bg6:	.space 4
+bg7:	.space 4
+bg8:	.space 4
+bl1:	.space 4
+bl2:	.space 4
+bl3:	.space 4
+bl4:	.space 4
+bl5:	.space 4
+bl6:	.space 4
+bl7:	.space 4
+bl8:	.space 4
+	.text
+	.globl	_start
+	.type	_start,@function
+_start:
+	pushq	%rbp
+	movq	%rsp, %rbp
+
+	/* IE against global var  */
+	movq	%fs:0, %r11
+	nop;nop
+	addq	sG6@gottpoff(%rip), %r11
+	nop;nop;nop;nop
+
+	/* IE -> LE against global var defined in exec  */
+	movq	%fs:0, %rdx
+	nop;nop
+	addq	bg6@gottpoff(%rip), %rdx
+	nop;nop;nop;nop
+
+	/* IE -> LE against local var  */
+	movq	%fs:0, %r12
+	nop;nop
+	addq	bl6@gottpoff(%rip), %r12
+	nop;nop;nop;nop
+
+	/* direct %fs access IE -> LE against local var  */
+	movq	bl8@gottpoff(%rip), %rdx
+	nop;nop
+	movq	%fs:(%rdx), %rax
+	nop;nop;nop;nop
+
+	/* IE -> LE against hidden but not local var  */
+	movq	%fs:0, %rdx
+	nop;nop
+	addq	sh6@gottpoff(%rip), %rdx
+	nop;nop;nop;nop
+
+	/* direct %fs access IE -> LE against hidden but not local var  */
+	movq	sh8@gottpoff(%rip), %rdx
+	nop;nop
+	movq	%fs:(%rdx), %rax
+	nop;nop;nop;nop
+
+	/* LE, global var defined in exec  */
+	movq	%fs:0, %rax
+	nop;nop
+	leaq	sg2@tpoff(%rax), %rdx
+	nop;nop;nop;nop
+
+	/* LE, local var, non-canonical sequence  */
+	movq	$2+bl2@tpoff, %r9
+	nop;nop
+	movq	%fs:0, %rdx
+	nop;nop
+	addq	%r9, %rdx
+	nop;nop;nop;nop
+
+	/* LE, hidden var defined in exec, non-canonical sequence */
+	movq	%fs:0, %rdx
+	nop;nop
+	addq	$sh2@tpoff+1, %rdx
+	nop;nop;nop;nop
+
+	/* Direct %fs access  */
+
+	/* LE, global var defined in exec  */
+	movq	%fs:sg3@tpoff, %rax
+	nop;nop;nop;nop
+
+	/* LE, local var  */
+	movq	%fs:bl3@tpoff+3, %r10
+	nop;nop;nop;nop
+
+	/* LE, hidden var defined in exec  */
+	movq	%fs:1+sh3@tpoff, %rdx
+	nop;nop;nop;nop
+
+	leave
+	ret
--- ld/testsuite/ld-x86-64/tlslib.s.jj	2002-09-25 11:29:50.000000000 +0200
+++ ld/testsuite/ld-x86-64/tlslib.s	2002-09-25 11:30:19.000000000 +0200
@@ -0,0 +1,18 @@
+	.section ".tdata", "awT", @progbits
+	.globl sG1, sG2, sG3, sG4, sG5, sG6, sG7, sG8
+sG1:	.long 513
+sG2:	.long 514
+sG3:	.long 515
+sG4:	.long 516
+sG5:	.long 517
+sG6:	.long 518
+sG7:	.long 519
+sG8:	.long 520
+
+	.text
+	/* Dummy.  */
+	.globl __tls_get_addr
+	.type   __tls_get_addr,@function
+__tls_get_addr:
+	movq	%rdi, %rax
+	ret
--- ld/testsuite/ld-x86-64/tlsbinpic.s.jj	2002-09-25 11:29:50.000000000 +0200
+++ ld/testsuite/ld-x86-64/tlsbinpic.s	2002-09-26 16:29:52.000000000 +0200
@@ -0,0 +1,136 @@
+	/* 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 */
+	.long	0x66666666
+	leaq	sG1@tlsgd(%rip), %rdi
+	call	__tls_get_addr@plt
+	nop;nop;nop;nop
+
+	/* GD -> IE because variable is not defined in executable where
+	   the variable is referenced through IE too */
+	.long	0x66666666
+	leaq	sG2@tlsgd(%rip), %rdi
+	call	__tls_get_addr@plt
+	nop;nop;nop;nop
+
+	/* GD -> LE with global variable defined in executable */
+	.long	0x66666666
+	leaq	sg1@tlsgd(%rip), %rdi
+	call	__tls_get_addr@plt
+	nop;nop;nop;nop
+
+	/* GD -> LE with local variable defined in executable */
+	.long	0x66666666
+	leaq	sl1@tlsgd(%rip), %rdi
+	call	__tls_get_addr@plt
+	nop;nop;nop;nop
+
+	/* GD -> LE with hidden variable defined in executable */
+	.long	0x66666666
+	leaq	sh1@tlsgd(%rip), %rdi
+	call	__tls_get_addr@plt
+	nop;nop;nop;nop
+
+	/* LD */
+	leaq	sl1@tlsld(%rip), %rdi
+	call	__tls_get_addr@plt
+	nop;nop
+	leaq	1+sl1@dtpoff(%rax), %rdx
+	nop;nop
+	leaq	sl2@dtpoff+2(%rax), %r9
+	nop;nop;nop;nop
+
+	/* LD against hidden variables */
+	leaq	sh1@tlsld(%rip), %rdi
+	call	__tls_get_addr@plt
+	nop;nop
+	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
--- ld/testsuite/ld-x86-64/tlsbin.rd.jj	2002-09-26 14:34:00.000000000 +0200
+++ ld/testsuite/ld-x86-64/tlsbin.rd	2002-09-26 14:49:41.000000000 +0200
@@ -0,0 +1,154 @@
+#source: tlsbinpic.s
+#source: tlsbin.s
+#as: --64
+#ld: -shared -melf_x86_64
+#readelf: -WSsrl
+#target: x86_64-*-*
+
+There are 18 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\] .rela.plt +.*
+  \[ 7\] .plt +.*
+  \[ 8\] .text +PROGBITS +0+401000 0+1000 0+22a 00 +AX +0 +0 +4096
+  \[ 9\] .data +.*
+  \[10\] .tdata +PROGBITS +0+502000 0+2000 0+60 00 WAT +0 +0 +1
+  \[11\] .tbss +NOBITS +0+502060 0+2060 0+40 00 WAT +0 +0 +1
+  \[12\] .dynamic +DYNAMIC +0+502060 0+2060 0+140 10 +WA +4 +0 +8
+  \[13\] .got +PROGBITS +0+5021a0 0+21a0 0+40 08 +WA +0 +0 +8
+  \[14\] .bss +.*
+  \[15\] .shstrtab +.*
+  \[16\] .symtab +.*
+  \[17\] .strtab +.*
+Key to Flags:
+.*
+.*
+.*
+
+Elf file type is EXEC \(Executable file\)
+Entry point 0x40113c
+There are 6 program headers, starting at offset [0-9]+
+
+Program Headers:
+  Type +Offset +VirtAddr +PhysAddr +FileSiz +MemSiz +Flg Align
+  PHDR +0x0+40 0x0+400040 0x0+400040 0x0+150 0x0+150 R E 0x8
+  INTERP +0x0+190 0x0+400190 0x0+400190 0x0+f 0x0+f R +0x1
+.*Requesting program interpreter.*
+  LOAD +0x0+ 0x0+400000 0x0+400000 0x0+122a 0x0+122a R E 0x100000
+  LOAD +0x0+2000 0x0+502000 0x0+502000 0x0+1e0 0x0+1e0 RW  0x100000
+  DYNAMIC +0x0+2060 0x0+502060 0x0+502060 0x0+140 0x0+140 RW  0x8
+  TLS +0x0+2000 0x0+502000 0x0+502000 0x0+60 0x0+a0 R +0x1
+
+ Section to Segment mapping:
+  Segment Sections...
+   00 *
+   01 +.interp *
+   02 +.interp .hash .dynsym .dynstr .rela.dyn .rela.plt .plt .text *
+   03 +.tdata .tbss .dynamic .got *
+   04 +.tbss .dynamic *
+   05 +.tdata .tbss *
+
+Relocation section '.rela.dyn' at offset 0x358 contains 4 entries:
+ +Offset +Info +Type +Symbol's Value  Symbol's Name \+ Addend
+0+5021c0  0+100000012 R_X86_64_TPOFF64 +0+ sG5 \+ 0
+0+5021c8  0+300000012 R_X86_64_TPOFF64 +0+ sG2 \+ 0
+0+5021d0  0+600000012 R_X86_64_TPOFF64 +0+ sG6 \+ 0
+0+5021d8  0+700000012 R_X86_64_TPOFF64 +0+ sG1 \+ 0
+
+Relocation section '.rela.plt' at offset 0x3b8 contains 1 entries:
+ +Offset +Info +Type +Symbol's Value  Symbol's Name \+ Addend
+0+[0-9a-f]+  0+400000007 R_X86_64_JUMP_SLOT +0+[0-9a-f]+ __tls_get_addr \+ 0
+
+Symbol table '.dynsym' contains 11 entries:
+ +Num: +Value +Size Type +Bind +Vis +Ndx Name
+ +0: 0+ +0 NOTYPE  LOCAL  DEFAULT  UND *
+ +1: 0+ +0 TLS +GLOBAL DEFAULT  UND sG5
+ +2: 0+502060 +0 OBJECT  GLOBAL DEFAULT  ABS _DYNAMIC
+ +3: 0+ +0 TLS +GLOBAL DEFAULT  UND sG2
+ +4: 0+[0-9a-f]+ +0 FUNC +GLOBAL DEFAULT  UND __tls_get_addr
+ +5: 0+[0-9a-f]+ +0 NOTYPE  GLOBAL DEFAULT  ABS __bss_start
+ +6: 0+ +0 TLS +GLOBAL DEFAULT  UND sG6
+ +7: 0+ +0 TLS +GLOBAL DEFAULT  UND sG1
+ +8: 0+[0-9a-f]+ +0 NOTYPE  GLOBAL DEFAULT  ABS _edata
+ +9: 0+5021a0 +0 OBJECT  GLOBAL DEFAULT  ABS _GLOBAL_OFFSET_TABLE_
+ +10: 0+[0-9a-f]+ +0 NOTYPE  GLOBAL DEFAULT  ABS _end
+
+Symbol table '.symtab' contains 70 entries:
+ +Num: +Value +Size Type +Bind +Vis +Ndx Name
+ +0: 0+ +0 NOTYPE  LOCAL  DEFAULT  UND *
+ +1: [0-9a-f]+ +0 SECTION LOCAL  DEFAULT +1 *
+ +2: [0-9a-f]+ +0 SECTION LOCAL  DEFAULT +2 *
+ +3: [0-9a-f]+ +0 SECTION LOCAL  DEFAULT +3 *
+ +4: [0-9a-f]+ +0 SECTION LOCAL  DEFAULT +4 *
+ +5: [0-9a-f]+ +0 SECTION LOCAL  DEFAULT +5 *
+ +6: [0-9a-f]+ +0 SECTION LOCAL  DEFAULT +6 *
+ +7: [0-9a-f]+ +0 SECTION LOCAL  DEFAULT +7 *
+ +8: [0-9a-f]+ +0 SECTION LOCAL  DEFAULT +8 *
+ +9: [0-9a-f]+ +0 SECTION LOCAL  DEFAULT +9 *
+ +10: [0-9a-f]+ +0 SECTION LOCAL  DEFAULT +10 *
+ +11: [0-9a-f]+ +0 SECTION LOCAL  DEFAULT +11 *
+ +12: [0-9a-f]+ +0 SECTION LOCAL  DEFAULT +12 *
+ +13: [0-9a-f]+ +0 SECTION LOCAL  DEFAULT +13 *
+ +14: [0-9a-f]+ +0 SECTION LOCAL  DEFAULT +14 *
+ +15: [0-9a-f]+ +0 SECTION LOCAL  DEFAULT +15 *
+ +16: [0-9a-f]+ +0 SECTION LOCAL  DEFAULT +16 *
+ +17: [0-9a-f]+ +0 SECTION LOCAL  DEFAULT +17 *
+ +18: 0+20 +0 TLS +LOCAL  DEFAULT +10 sl1
+ +19: 0+24 +0 TLS +LOCAL  DEFAULT +10 sl2
+ +20: 0+28 +0 TLS +LOCAL  DEFAULT +10 sl3
+ +21: 0+2c +0 TLS +LOCAL  DEFAULT +10 sl4
+ +22: 0+30 +0 TLS +LOCAL  DEFAULT +10 sl5
+ +23: 0+34 +0 TLS +LOCAL  DEFAULT +10 sl6
+ +24: 0+38 +0 TLS +LOCAL  DEFAULT +10 sl7
+ +25: 0+3c +0 TLS +LOCAL  DEFAULT +10 sl8
+ +26: 0+80 +0 TLS +LOCAL  DEFAULT +11 bl1
+ +27: 0+84 +0 TLS +LOCAL  DEFAULT +11 bl2
+ +28: 0+88 +0 TLS +LOCAL  DEFAULT +11 bl3
+ +29: 0+8c +0 TLS +LOCAL  DEFAULT +11 bl4
+ +30: 0+90 +0 TLS +LOCAL  DEFAULT +11 bl5
+ +31: 0+94 +0 TLS +LOCAL  DEFAULT +11 bl6
+ +32: 0+98 +0 TLS +LOCAL  DEFAULT +11 bl7
+ +33: 0+9c +0 TLS +LOCAL  DEFAULT +11 bl8
+ +34: 0+1c +0 TLS +GLOBAL DEFAULT +10 sg8
+ +35: 0+7c +0 TLS +GLOBAL DEFAULT +11 bg8
+ +36: 0+74 +0 TLS +GLOBAL DEFAULT +11 bg6
+ +37: 0+ +0 TLS +GLOBAL DEFAULT  UND sG5
+ +38: 0+68 +0 TLS +GLOBAL DEFAULT +11 bg3
+ +39: 0+502060 +0 OBJECT  GLOBAL DEFAULT  ABS _DYNAMIC
+ +40: 0+8 +0 TLS +GLOBAL DEFAULT +10 sg3
+ +41: 0+48 +0 TLS +GLOBAL HIDDEN +10 sh3
+ +42: 0+ +0 TLS +GLOBAL DEFAULT  UND sG2
+ +43: 0+c +0 TLS +GLOBAL DEFAULT +10 sg4
+ +44: 0+10 +0 TLS +GLOBAL DEFAULT +10 sg5
+ +45: 0+70 +0 TLS +GLOBAL DEFAULT +11 bg5
+ +46: [0-9a-f]+ +0 FUNC +GLOBAL DEFAULT  UND __tls_get_addr
+ +47: 0+58 +0 TLS +GLOBAL HIDDEN +10 sh7
+ +48: 0+5c +0 TLS +GLOBAL HIDDEN +10 sh8
+ +49: 0+ +0 TLS +GLOBAL DEFAULT +10 sg1
+ +50: 0+40113c +0 FUNC +GLOBAL DEFAULT +8 _start
+ +51: 0+4c +0 TLS +GLOBAL HIDDEN +10 sh4
+ +52: 0+78 +0 TLS +GLOBAL DEFAULT +11 bg7
+ +53: 0+50 +0 TLS +GLOBAL HIDDEN +10 sh5
+ +54: [0-9a-f]+ +0 NOTYPE  GLOBAL DEFAULT  ABS __bss_start
+ +55: 0+ +0 TLS +GLOBAL DEFAULT  UND sG6
+ +56: 0+401000 +0 FUNC +GLOBAL DEFAULT +8 fn2
+ +57: 0+4 +0 TLS +GLOBAL DEFAULT +10 sg2
+ +58: 0+ +0 TLS +GLOBAL DEFAULT  UND sG1
+ +59: 0+40 +0 TLS +GLOBAL HIDDEN +10 sh1
+ +60: 0+14 +0 TLS +GLOBAL DEFAULT +10 sg6
+ +61: 0+18 +0 TLS +GLOBAL DEFAULT +10 sg7
+ +62: [0-9a-f]+ +0 NOTYPE  GLOBAL DEFAULT  ABS _edata
+ +63: 0+5021a0 +0 OBJECT  GLOBAL DEFAULT  ABS _GLOBAL_OFFSET_TABLE_
+ +64: [0-9a-f]+ +0 NOTYPE  GLOBAL DEFAULT  ABS _end
+ +65: 0+44 +0 TLS +GLOBAL HIDDEN +10 sh2
+ +66: 0+54 +0 TLS +GLOBAL HIDDEN +10 sh6
+ +67: 0+64 +0 TLS +GLOBAL DEFAULT +11 bg2
+ +68: 0+60 +0 TLS +GLOBAL DEFAULT +11 bg1
+ +69: 0+6c +0 TLS +GLOBAL DEFAULT +11 bg4
--- ld/testsuite/ld-x86-64/tlspic.rd.jj	2002-09-25 18:47:12.000000000 +0200
+++ ld/testsuite/ld-x86-64/tlspic.rd	2002-09-26 13:35:55.000000000 +0200
@@ -0,0 +1,162 @@
+#source: tlspic1.s
+#source: tlspic2.s
+#as: --64
+#ld: -shared -melf_x86_64
+#readelf: -WSsrl
+#target: x86_64-*-*
+
+There are 17 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 +.*
+  \[ 7\] .text +PROGBITS +0+1000 0+1000 0+1ac 00 +AX +0 +0 4096
+  \[ 8\] .data +.*
+  \[ 9\] .tdata +PROGBITS +0+102000 0+2000 0+60 00 WAT +0 +0 +1
+  \[10\] .tbss +NOBITS +0+102060 0+2060 0+20 00 WAT +0 +0 +1
+  \[11\] .dynamic +DYNAMIC +0+102060 0+2060 0+130 10 +WA +3 +0 +8
+  \[12\] .got +PROGBITS +0+102190 0+2190 0+b0 08 +WA +0 +0 +8
+  \[13\] .bss +.*
+  \[14\] .shstrtab +.*
+  \[15\] .symtab +.*
+  \[16\] .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+2000 0x0+102000 0x0+102000 0x0+240 0x0+240 RW +0x100000
+  DYNAMIC +0x0+2060 0x0+102060 0x0+102060 0x0+130 0x0+130 RW +0x8
+  TLS +0x0+2000 0x0+102000 0x0+102000 0x0+60 0x0+80 R +0x1
+
+ Section to Segment mapping:
+  Segment Sections...
+   00 +.hash .dynsym .dynstr .rela.dyn .rela.plt .plt .text *
+   01 +.tdata .tbss .dynamic .got *
+   02 +.tbss .dynamic *
+   03 +.tdata .tbss *
+
+Relocation section '.rela.dyn' at offset 0x[0-9a-f]+ contains 14 entries:
+ +Offset +Info +Type +Symbol's Value +Symbol's Name \+ Addend
+0+1021b0  0+10 R_X86_64_DTPMOD64 +0+
+0+1021c0  0+12 R_X86_64_TPOFF64 +0+24
+0+1021c8  0+12 R_X86_64_TPOFF64 +0+30
+0+1021d0  0+10 R_X86_64_DTPMOD64 +0+
+0+1021e0  0+10 R_X86_64_DTPMOD64 +0+
+0+1021f0  0+12 R_X86_64_TPOFF64 +0+64
+0+102210  0+12 R_X86_64_TPOFF64 +0+50
+0+102218  0+12 R_X86_64_TPOFF64 +0+70
+0+102228  0+10 R_X86_64_DTPMOD64 +0+
+0+102238  0+12 R_X86_64_TPOFF64 +0+44
+0+1021f8  0+1200000012 R_X86_64_TPOFF64 +0+10 sg5 \+ 0
+0+102200  0+1400000010 R_X86_64_DTPMOD64 +0+ sg1 \+ 0
+0+102208  0+1400000011 R_X86_64_DTPOFF64 +0+ sg1 \+ 0
+0+102220  0+1700000012 R_X86_64_TPOFF64 +0+4 sg2 \+ 0
+
+Relocation section '.rela.plt' at offset 0x658 contains 1 entries:
+ +Offset +Info +Type +Symbol's Value  Symbol's Name \+ Addend
+0+[0-9a-f]+  0+1300000007 R_X86_64_JUMP_SLOT +0+ __tls_get_addr \+ 0
+
+Symbol table '.dynsym' contains 29 entries:
+ +Num: +Value +Size Type +Bind +Vis +Ndx Name
+ +0: 0+ +0 NOTYPE  LOCAL  DEFAULT  UND *
+ +1: [0-9a-f]+ +0 SECTION LOCAL  DEFAULT +1 *
+ +2: [0-9a-f]+ +0 SECTION LOCAL  DEFAULT +2 *
+ +3: [0-9a-f]+ +0 SECTION LOCAL  DEFAULT +3 *
+ +4: [0-9a-f]+ +0 SECTION LOCAL  DEFAULT +4 *
+ +5: [0-9a-f]+ +0 SECTION LOCAL  DEFAULT +5 *
+ +6: [0-9a-f]+ +0 SECTION LOCAL  DEFAULT +6 *
+ +7: [0-9a-f]+ +0 SECTION LOCAL  DEFAULT +7 *
+ +8: [0-9a-f]+ +0 SECTION LOCAL  DEFAULT +8 *
+ +9: [0-9a-f]+ +0 SECTION LOCAL  DEFAULT +9 *
+ +10: [0-9a-f]+ +0 SECTION LOCAL  DEFAULT +10 *
+ +11: [0-9a-f]+ +0 SECTION LOCAL  DEFAULT +11 *
+ +12: [0-9a-f]+ +0 SECTION LOCAL  DEFAULT +12 *
+ +13: [0-9a-f]+ +0 SECTION LOCAL  DEFAULT +13 *
+ +14: 0+1c +0 TLS +GLOBAL DEFAULT +9 sg8
+ +15: 0+102060 +0 OBJECT  GLOBAL DEFAULT  ABS _DYNAMIC
+ +16: 0+8 +0 TLS +GLOBAL DEFAULT +9 sg3
+ +17: 0+c +0 TLS +GLOBAL DEFAULT +9 sg4
+ +18: 0+10 +0 TLS +GLOBAL DEFAULT +9 sg5
+ +19: 0+ +0 NOTYPE  GLOBAL DEFAULT  UND __tls_get_addr
+ +20: 0+ +0 TLS +GLOBAL DEFAULT +9 sg1
+ +21: 0+1000 +0 FUNC +GLOBAL DEFAULT +7 fn1
+ +22: 0+102240 +0 NOTYPE  GLOBAL DEFAULT  ABS __bss_start
+ +23: 0+4 +0 TLS +GLOBAL DEFAULT +9 sg2
+ +24: 0+14 +0 TLS +GLOBAL DEFAULT +9 sg6
+ +25: 0+18 +0 TLS +GLOBAL DEFAULT +9 sg7
+ +26: 0+102240 +0 NOTYPE  GLOBAL DEFAULT  ABS _edata
+ +27: 0+102190 +0 OBJECT  GLOBAL DEFAULT  ABS _GLOBAL_OFFSET_TABLE_
+ +28: 0+102240 +0 NOTYPE  GLOBAL DEFAULT  ABS _end
+
+Symbol table '.symtab' contains 56 entries:
+ +Num: +Value +Size Type +Bind +Vis +Ndx Name
+ +0: 0+ +0 NOTYPE  LOCAL  DEFAULT  UND *
+ +1: [0-9a-f]+ +0 SECTION LOCAL  DEFAULT +1 *
+ +2: [0-9a-f]+ +0 SECTION LOCAL  DEFAULT +2 *
+ +3: [0-9a-f]+ +0 SECTION LOCAL  DEFAULT +3 *
+ +4: [0-9a-f]+ +0 SECTION LOCAL  DEFAULT +4 *
+ +5: [0-9a-f]+ +0 SECTION LOCAL  DEFAULT +5 *
+ +6: [0-9a-f]+ +0 SECTION LOCAL  DEFAULT +6 *
+ +7: [0-9a-f]+ +0 SECTION LOCAL  DEFAULT +7 *
+ +8: [0-9a-f]+ +0 SECTION LOCAL  DEFAULT +8 *
+ +9: [0-9a-f]+ +0 SECTION LOCAL  DEFAULT +9 *
+ +10: [0-9a-f]+ +0 SECTION LOCAL  DEFAULT +10 *
+ +11: [0-9a-f]+ +0 SECTION LOCAL  DEFAULT +11 *
+ +12: [0-9a-f]+ +0 SECTION LOCAL  DEFAULT +12 *
+ +13: [0-9a-f]+ +0 SECTION LOCAL  DEFAULT +13 *
+ +14: [0-9a-f]+ +0 SECTION LOCAL  DEFAULT +14 *
+ +15: [0-9a-f]+ +0 SECTION LOCAL  DEFAULT +15 *
+ +16: [0-9a-f]+ +0 SECTION LOCAL  DEFAULT +16 *
+ +17: 0+20 +0 TLS +LOCAL  DEFAULT +9 sl1
+ +18: 0+24 +0 TLS +LOCAL  DEFAULT +9 sl2
+ +19: 0+28 +0 TLS +LOCAL  DEFAULT +9 sl3
+ +20: 0+2c +0 TLS +LOCAL  DEFAULT +9 sl4
+ +21: 0+30 +0 TLS +LOCAL  DEFAULT +9 sl5
+ +22: 0+34 +0 TLS +LOCAL  DEFAULT +9 sl6
+ +23: 0+38 +0 TLS +LOCAL  DEFAULT +9 sl7
+ +24: 0+3c +0 TLS +LOCAL  DEFAULT +9 sl8
+ +25: 0+60 +0 TLS +LOCAL  HIDDEN +10 sH1
+ +26: 0+48 +0 TLS +LOCAL  HIDDEN +9 sh3
+ +27: 0+64 +0 TLS +LOCAL  HIDDEN +10 sH2
+ +28: 0+78 +0 TLS +LOCAL  HIDDEN +10 sH7
+ +29: 0+58 +0 TLS +LOCAL  HIDDEN +9 sh7
+ +30: 0+5c +0 TLS +LOCAL  HIDDEN +9 sh8
+ +31: 0+6c +0 TLS +LOCAL  HIDDEN +10 sH4
+ +32: 0+4c +0 TLS +LOCAL  HIDDEN +9 sh4
+ +33: 0+68 +0 TLS +LOCAL  HIDDEN +10 sH3
+ +34: 0+50 +0 TLS +LOCAL  HIDDEN +9 sh5
+ +35: 0+70 +0 TLS +LOCAL  HIDDEN +10 sH5
+ +36: 0+74 +0 TLS +LOCAL  HIDDEN +10 sH6
+ +37: 0+7c +0 TLS +LOCAL  HIDDEN +10 sH8
+ +38: 0+40 +0 TLS +LOCAL  HIDDEN +9 sh1
+ +39: 0+44 +0 TLS +LOCAL  HIDDEN +9 sh2
+ +40: 0+54 +0 TLS +LOCAL  HIDDEN +9 sh6
+ +41: 0+1c +0 TLS +GLOBAL DEFAULT +9 sg8
+ +42: 0+102060 +0 OBJECT  GLOBAL DEFAULT  ABS _DYNAMIC
+ +43: 0+8 +0 TLS +GLOBAL DEFAULT +9 sg3
+ +44: 0+c +0 TLS +GLOBAL DEFAULT +9 sg4
+ +45: 0+10 +0 TLS +GLOBAL DEFAULT +9 sg5
+ +46: 0+ +0 NOTYPE  GLOBAL DEFAULT  UND __tls_get_addr
+ +47: 0+ +0 TLS +GLOBAL DEFAULT +9 sg1
+ +48: 0+1000 +0 FUNC +GLOBAL DEFAULT +7 fn1
+ +49: [0-9a-f]+ +0 NOTYPE  GLOBAL DEFAULT  ABS __bss_start
+ +50: 0+4 +0 TLS +GLOBAL DEFAULT +9 sg2
+ +51: 0+14 +0 TLS +GLOBAL DEFAULT +9 sg6
+ +52: 0+18 +0 TLS +GLOBAL DEFAULT +9 sg7
+ +53: [0-9a-f]+ +0 NOTYPE  GLOBAL DEFAULT  ABS _edata
+ +54: 0+102190 +0 OBJECT  GLOBAL DEFAULT  ABS _GLOBAL_OFFSET_TABLE_
+ +55: [0-9a-f]+ +0 NOTYPE  GLOBAL DEFAULT  ABS _end
--- ld/testsuite/ld-x86-64/tlspic.dd.jj	2002-09-26 13:37:26.000000000 +0200
+++ ld/testsuite/ld-x86-64/tlspic.dd	2002-09-26 16:20:08.000000000 +0200
@@ -0,0 +1,226 @@
+#source: tlspic1.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+1000 <fn1>:
+ +1000:	55[ 	]+push   %rbp
+ +1001:	48 89 e5[ 	]+mov    %rsp,%rbp
+ +1004:	90[ 	]+nop *
+ +1005:	90[ 	]+nop *
+ +1006:	90[ 	]+nop *
+ +1007:	90[ 	]+nop *
+#  GD
+ +1008:	66 66 66 66 48 8d 3d[ 	]+lea    1053165\(%rip\),%rdi +# 102200 <_GLOBAL_OFFSET_TABLE_\+0x70>
+ +100f:	ed 11 10 00 *
+#				-> R_X86_64_DTPMOD64	sg1
+ +1013:	e8 68 f6 ff ff[ 	]+callq  [0-9a-f]+ <.*>
+#				-> R_X86_64_JUMP_SLOT	__tls_get_addr
+ +1018:	90[ 	]+nop *
+ +1019:	90[ 	]+nop *
+ +101a:	90[ 	]+nop *
+ +101b:	90[ 	]+nop *
+#  GD -> IE because variable is referenced through IE too
+ +101c:	64 48 8b 04 25 00 00[ 	]+mov    %fs:0x0,%rax
+ +1023:	00 00 *
+ +1025:	48 03 05 f4 11 10 00[ 	]+add    1053172\(%rip\),%rax +# 102220 <_GLOBAL_OFFSET_TABLE_\+0x90>
+#				-> R_X86_64_TPOFF64	sg2
+ +102c:	90[ 	]+nop *
+ +102d:	90[ 	]+nop *
+ +102e:	90[ 	]+nop *
+ +102f:	90[ 	]+nop *
+#  GD against local variable
+ +1030:	66 66 66 66 48 8d 3d[ 	]+lea    1053045\(%rip\),%rdi +# 1021b0 <_GLOBAL_OFFSET_TABLE_\+0x20>
+ +1037:	75 11 10 00 *
+#				-> R_X86_64_DTPMOD64	[0 0x2000000000000000]
+ +103b:	e8 40 f6 ff ff[ 	]+callq  [0-9a-f]+ <.*>
+#				-> R_X86_64_JUMP_SLOT	__tls_get_addr
+ +1040:	90[ 	]+nop *
+ +1041:	90[ 	]+nop *
+ +1042:	90[ 	]+nop *
+ +1043:	90[ 	]+nop *
+#  GD -> IE against local variable referenced through IE too
+ +1044:	64 48 8b 04 25 00 00[ 	]+mov    %fs:0x0,%rax
+ +104b:	00 00 *
+ +104d:	48 03 05 6c 11 10 00[ 	]+add    1053036\(%rip\),%rax +# 1021c0 <_GLOBAL_OFFSET_TABLE_\+0x30>
+#				-> R_X86_64_TPOFF64	*ABS*+0x24
+ +1054:	90[ 	]+nop *
+ +1055:	90[ 	]+nop *
+ +1056:	90[ 	]+nop *
+ +1057:	90[ 	]+nop *
+#  GD against hidden and local variable
+ +1058:	66 66 66 66 48 8d 3d[ 	]+lea    1053125\(%rip\),%rdi +# 102228 <_GLOBAL_OFFSET_TABLE_\+0x98>
+ +105f:	c5 11 10 00 *
+#				-> R_X86_64_DTPMOD64	[0 0x4000000000000000]
+ +1063:	e8 18 f6 ff ff[ 	]+callq  [0-9a-f]+ <.*>
+#				-> R_X86_64_JUMP_SLOT	__tls_get_addr
+ +1068:	90[ 	]+nop *
+ +1069:	90[ 	]+nop *
+ +106a:	90[ 	]+nop *
+ +106b:	90[ 	]+nop *
+#  GD -> IE against hidden and local variable referenced through IE too
+ +106c:	64 48 8b 04 25 00 00[ 	]+mov    %fs:0x0,%rax
+ +1073:	00 00 *
+ +1075:	48 03 05 bc 11 10 00[ 	]+add    1053116\(%rip\),%rax +# 102238 <_GLOBAL_OFFSET_TABLE_\+0xa8>
+#				-> R_X86_64_TPOFF64	*ABS*+0x44
+ +107c:	90[ 	]+nop *
+ +107d:	90[ 	]+nop *
+ +107e:	90[ 	]+nop *
+ +107f:	90[ 	]+nop *
+#  GD against hidden but not local variable
+ +1080:	66 66 66 66 48 8d 3d[ 	]+lea    1053013\(%rip\),%rdi +# 1021e0 <_GLOBAL_OFFSET_TABLE_\+0x50>
+ +1087:	55 11 10 00 *
+#				-> R_X86_64_DTPMOD64	[0 0x6000000000000000]
+ +108b:	e8 f0 f5 ff ff[ 	]+callq  [0-9a-f]+ <.*>
+#				-> R_X86_64_JUMP_SLOT	__tls_get_addr
+ +1090:	90[ 	]+nop *
+ +1091:	90[ 	]+nop *
+ +1092:	90[ 	]+nop *
+ +1093:	90[ 	]+nop *
+#  GD -> IE against hidden but not local variable referenced through IE too
+ +1094:	64 48 8b 04 25 00 00[ 	]+mov    %fs:0x0,%rax
+ +109b:	00 00 *
+ +109d:	48 03 05 4c 11 10 00[ 	]+add    1053004\(%rip\),%rax +# 1021f0 <_GLOBAL_OFFSET_TABLE_\+0x60>
+#				-> R_X86_64_TPOFF64	*ABS*+0x64
+ +10a4:	90[ 	]+nop *
+ +10a5:	90[ 	]+nop *
+ +10a6:	90[ 	]+nop *
+ +10a7:	90[ 	]+nop *
+#  LD
+ +10a8:	48 8d 3d 21 11 10 00[ 	]+lea    1052961\(%rip\),%rdi +# 1021d0 <_GLOBAL_OFFSET_TABLE_\+0x40>
+#				-> R_X86_64_DTPMOD64	[0 0x000000000000000]
+ +10af:	e8 cc f5 ff ff[ 	]+callq  [0-9a-f]+ <.*>
+#				-> R_X86_64_JUMP_SLOT	__tls_get_addr
+ +10b4:	90[ 	]+nop *
+ +10b5:	90[ 	]+nop *
+ +10b6:	48 8d 90 20 00 00 00[ 	]+lea    0x20\(%rax\),%rdx
+ +10bd:	90[ 	]+nop *
+ +10be:	90[ 	]+nop *
+ +10bf:	4c 8d 88 26 00 00 00[ 	]+lea    0x26\(%rax\),%r9
+ +10c6:	90[ 	]+nop *
+ +10c7:	90[ 	]+nop *
+ +10c8:	90[ 	]+nop *
+ +10c9:	90[ 	]+nop *
+#  LD against hidden and local variables
+ +10ca:	48 8d 3d ff 10 10 00[ 	]+lea    1052927\(%rip\),%rdi +# 1021d0 <_GLOBAL_OFFSET_TABLE_\+0x40>
+#				-> R_X86_64_DTPMOD64	[0 0x000000000000000]
+ +10d1:	e8 aa f5 ff ff[ 	]+callq  [0-9a-f]+ <.*>
+#				-> R_X86_64_JUMP_SLOT	__tls_get_addr
+ +10d6:	90[ 	]+nop *
+ +10d7:	90[ 	]+nop *
+ +10d8:	48 8d 90 40 00 00 00[ 	]+lea    0x40\(%rax\),%rdx
+ +10df:	90[ 	]+nop *
+ +10e0:	90[ 	]+nop *
+ +10e1:	48 8d 88 47 00 00 00[ 	]+lea    0x47\(%rax\),%rcx
+ +10e8:	90[ 	]+nop *
+ +10e9:	90[ 	]+nop *
+ +10ea:	90[ 	]+nop *
+ +10eb:	90[ 	]+nop *
+#  LD against hidden but not local variables
+ +10ec:	48 8d 3d dd 10 10 00[ 	]+lea    1052893\(%rip\),%rdi +# 1021d0 <_GLOBAL_OFFSET_TABLE_\+0x40>
+#				-> R_X86_64_DTPMOD64	[0 0x000000000000000]
+ +10f3:	e8 88 f5 ff ff[ 	]+callq  [0-9a-f]+ <.*>
+#				-> R_X86_64_JUMP_SLOT	__tls_get_addr
+ +10f8:	90[ 	]+nop *
+ +10f9:	90[ 	]+nop *
+ +10fa:	4c 8d a0 60 00 00 00[ 	]+lea    0x60\(%rax\),%r12
+ +1101:	90[ 	]+nop *
+ +1102:	90[ 	]+nop *
+ +1103:	48 8d 88 65 00 00 00[ 	]+lea    0x65\(%rax\),%rcx
+ +110a:	90[ 	]+nop *
+ +110b:	90[ 	]+nop *
+#  IE against global var
+ +110c:	64 48 8b 0c 25 00 00[ 	]+mov    %fs:0x0,%rcx
+ +1113:	00 00 *
+ +1115:	90[ 	]+nop *
+ +1116:	90[ 	]+nop *
+ +1117:	48 03 0d 02 11 10 00[ 	]+add    1052930\(%rip\),%rcx +# 102220 <_GLOBAL_OFFSET_TABLE_\+0x90>
+#				-> R_X86_64_TPOFF64	sg2
+ +111e:	90[ 	]+nop *
+ +111f:	90[ 	]+nop *
+ +1120:	90[ 	]+nop *
+ +1121:	90[ 	]+nop *
+#  IE against local var
+ +1122:	64 4c 8b 34 25 00 00[ 	]+mov    %fs:0x0,%r14
+ +1129:	00 00 *
+ +112b:	90[ 	]+nop *
+ +112c:	90[ 	]+nop *
+ +112d:	4c 03 35 8c 10 10 00[ 	]+add    1052812\(%rip\),%r14 +# 1021c0 <_GLOBAL_OFFSET_TABLE_\+0x30>
+#				-> R_X86_64_TPOFF64	*ABS*+0x24
+ +1134:	90[ 	]+nop *
+ +1135:	90[ 	]+nop *
+ +1136:	90[ 	]+nop *
+ +1137:	90[ 	]+nop *
+#  IE against hidden and local var
+ +1138:	64 48 8b 0c 25 00 00[ 	]+mov    %fs:0x0,%rcx
+ +113f:	00 00 *
+ +1141:	90[ 	]+nop *
+ +1142:	90[ 	]+nop *
+ +1143:	48 03 0d ee 10 10 00[ 	]+add    1052910\(%rip\),%rcx +# 102238 <_GLOBAL_OFFSET_TABLE_\+0xa8>
+#				-> R_X86_64_TPOFF64	*ABS*+0x44
+ +114a:	90[ 	]+nop *
+ +114b:	90[ 	]+nop *
+ +114c:	90[ 	]+nop *
+ +114d:	90[ 	]+nop *
+#  IE against hidden but not local var
+ +114e:	64 48 8b 0c 25 00 00[ 	]+mov    %fs:0x0,%rcx
+ +1155:	00 00 *
+ +1157:	90[ 	]+nop *
+ +1158:	90[ 	]+nop *
+ +1159:	48 03 0d 90 10 10 00[ 	]+add    1052816\(%rip\),%rcx +# 1021f0 <_GLOBAL_OFFSET_TABLE_\+0x60>
+#				-> R_X86_64_TPOFF64	*ABS*+0x64
+ +1160:	90[ 	]+nop *
+ +1161:	90[ 	]+nop *
+ +1162:	90[ 	]+nop *
+ +1163:	90[ 	]+nop *
+#  Direct access through %fs
+#  IE against global var
+ +1164:	48 8b 0d 8d 10 10 00[ 	]+mov    1052813\(%rip\),%rcx +# 1021f8 <_GLOBAL_OFFSET_TABLE_\+0x68>
+#				-> R_X86_64_TPOFF64	sg5
+ +116b:	90[ 	]+nop *
+ +116c:	90[ 	]+nop *
+ +116d:	64 48 8b 11[ 	]+mov    %fs:\(%rcx\),%rdx
+ +1171:	90[ 	]+nop *
+ +1172:	90[ 	]+nop *
+ +1173:	90[ 	]+nop *
+ +1174:	90[ 	]+nop *
+#  IE against local var
+ +1175:	4c 8b 15 4c 10 10 00[ 	]+mov    1052748\(%rip\),%r10 +# 1021c8 <_GLOBAL_OFFSET_TABLE_\+0x38>
+#				-> R_X86_64_TPOFF64	*ABS*+0x30
+ +117c:	90[ 	]+nop *
+ +117d:	90[ 	]+nop *
+ +117e:	64 4d 8b 22[ 	]+mov    %fs:\(%r10\),%r12
+ +1182:	90[ 	]+nop *
+ +1183:	90[ 	]+nop *
+ +1184:	90[ 	]+nop *
+ +1185:	90[ 	]+nop *
+#  IE against hidden and local var
+ +1186:	48 8b 15 83 10 10 00[ 	]+mov    1052803\(%rip\),%rdx +# 102210 <_GLOBAL_OFFSET_TABLE_\+0x80>
+#				-> R_X86_64_TPOFF64	*ABS*+0x50
+ +118d:	90[ 	]+nop *
+ +118e:	90[ 	]+nop *
+ +118f:	64 48 8b 12[ 	]+mov    %fs:\(%rdx\),%rdx
+ +1193:	90[ 	]+nop *
+ +1194:	90[ 	]+nop *
+ +1195:	90[ 	]+nop *
+ +1196:	90[ 	]+nop *
+#  IE against hidden but not local var
+ +1197:	48 8b 0d 7a 10 10 00[ 	]+mov    1052794\(%rip\),%rcx +# 102218 <_GLOBAL_OFFSET_TABLE_\+0x88>
+#				-> R_X86_64_TPOFF64	*ABS*+0x70
+ +119e:	90[ 	]+nop *
+ +119f:	90[ 	]+nop *
+ +11a0:	64 48 8b 11[ 	]+mov    %fs:\(%rcx\),%rdx
+ +11a4:	90[ 	]+nop *
+ +11a5:	90[ 	]+nop *
+ +11a6:	90[ 	]+nop *
+ +11a7:	90[ 	]+nop *
+ +11a8:	c9[ 	]+leaveq *
+ +11a9:	c3[ 	]+retq *
+ +11aa:	90[ 	]+nop *
+ +11ab:	90[ 	]+nop *
--- ld/testsuite/ld-x86-64/tlspic.sd.jj	2002-09-26 13:44:46.000000000 +0200
+++ ld/testsuite/ld-x86-64/tlspic.sd	2002-09-26 14:15:16.000000000 +0200
@@ -0,0 +1,21 @@
+#source: tlspic1.s
+#source: tlspic2.s
+#as: --64
+#ld: -shared -melf_x86_64
+#objdump: -sj.got
+#target: x86_64-*-*
+
+.*: +file format elf64-x86-64
+
+Contents of section .got:
+ 102190 [0-9a-f]+ [0-9a-f]+ 00000000 00000000  .*
+ 1021a0 00000000 00000000 [0-9a-f]+ [0-9a-f]+  .*
+ 1021b0 00000000 00000000 20000000 00000000  .*
+ 1021c0 00000000 00000000 00000000 00000000  .*
+ 1021d0 00000000 00000000 00000000 00000000  .*
+ 1021e0 00000000 00000000 60000000 00000000  .*
+ 1021f0 00000000 00000000 00000000 00000000  .*
+ 102200 00000000 00000000 00000000 00000000  .*
+ 102210 00000000 00000000 00000000 00000000  .*
+ 102220 00000000 00000000 00000000 00000000  .*
+ 102230 40000000 00000000 00000000 00000000  .*
--- ld/testsuite/ld-x86-64/tlspic.td.jj	2002-09-26 13:44:50.000000000 +0200
+++ ld/testsuite/ld-x86-64/tlspic.td	2002-09-26 13:45:32.000000000 +0200
@@ -0,0 +1,16 @@
+#source: tlspic1.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:
+ 102000 11000000 12000000 13000000 14000000  .*
+ 102010 15000000 16000000 17000000 18000000  .*
+ 102020 41000000 42000000 43000000 44000000  .*
+ 102030 45000000 46000000 47000000 48000000  .*
+ 102040 01010000 02010000 03010000 04010000  .*
+ 102050 05010000 06010000 07010000 08010000  .*
--- ld/testsuite/ld-x86-64/tlsbin.dd.jj	2002-09-26 14:51:28.000000000 +0200
+++ ld/testsuite/ld-x86-64/tlsbin.dd	2002-09-26 17:27:09.000000000 +0200
@@ -0,0 +1,310 @@
+#source: tlsbinpic.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>:
+  401000:	55[ 	]+push   %rbp
+  401001:	48 89 e5[ 	]+mov    %rsp,%rbp
+#  GD -> IE because variable is not defined in executable
+  401004:	64 48 8b 04 25 00 00[ 	]+mov    %fs:0x0,%rax
+  40100b:	00 00 *
+  40100d:	48 03 05 c4 11 10 00[ 	]+add    1053124\(%rip\),%rax +# 5021d8 <_GLOBAL_OFFSET_TABLE_\+0x38>
+#				-> R_X86_64_TPOFF64	sG1
+  401014:	90[ 	]+nop *
+  401015:	90[ 	]+nop *
+  401016:	90[ 	]+nop *
+  401017:	90[ 	]+nop *
+#  GD -> IE because variable is not defined in executable where
+#  the variable is referenced through IE too
+  401018:	64 48 8b 04 25 00 00[ 	]+mov    %fs:0x0,%rax
+  40101f:	00 00 *
+  401021:	48 03 05 a0 11 10 00[ 	]+add    1053088\(%rip\),%rax +# 5021c8 <_GLOBAL_OFFSET_TABLE_\+0x28>
+#				-> R_X86_64_TPOFF64	sG2
+  401028:	90[ 	]+nop *
+  401029:	90[ 	]+nop *
+  40102a:	90[ 	]+nop *
+  40102b:	90[ 	]+nop *
+#  GD -> LE with global variable defined in executable
+  40102c:	64 48 8b 04 25 00 00[ 	]+mov    %fs:0x0,%rax
+  401033:	00 00 *
+  401035:	48 8d 80 60 ff ff ff[ 	]+lea    0xf+60\(%rax\),%rax
+#							sg1
+  40103c:	90[ 	]+nop *
+  40103d:	90[ 	]+nop *
+  40103e:	90[ 	]+nop *
+  40103f:	90[ 	]+nop *
+#  GD -> LE with local variable defined in executable
+  401040:	64 48 8b 04 25 00 00[ 	]+mov    %fs:0x0,%rax
+  401047:	00 00 *
+  401049:	48 8d 80 80 ff ff ff[ 	]+lea    0xf+80\(%rax\),%rax
+#							sl1
+  401050:	90[ 	]+nop *
+  401051:	90[ 	]+nop *
+  401052:	90[ 	]+nop *
+  401053:	90[ 	]+nop *
+#  GD -> LE with hidden variable defined in executable
+  401054:	64 48 8b 04 25 00 00[ 	]+mov    %fs:0x0,%rax
+  40105b:	00 00 *
+  40105d:	48 8d 80 a0 ff ff ff[ 	]+lea    0xf+a0\(%rax\),%rax
+#							sh1
+  401064:	90[ 	]+nop *
+  401065:	90[ 	]+nop *
+  401066:	90[ 	]+nop *
+  401067:	90[ 	]+nop *
+#  LD
+  401068:	66 66 66 64 48 8b 04[ 	]+mov    %fs:0x0,%rax
+  40106f:	25 00 00 00 00 *
+  401074:	90[ 	]+nop *
+  401075:	90[ 	]+nop *
+  401076:	48 8d 90 81 ff ff ff[ 	]+lea    0xf+81\(%rax\),%rdx
+#							sl1+1
+  40107d:	90[ 	]+nop *
+  40107e:	90[ 	]+nop *
+  40107f:	4c 8d 88 86 ff ff ff[ 	]+lea    0xf+86\(%rax\),%r9
+#							sl2+2
+  401086:	90[ 	]+nop *
+  401087:	90[ 	]+nop *
+  401088:	90[ 	]+nop *
+  401089:	90[ 	]+nop *
+#  LD against hidden variables
+  40108a:	66 66 66 64 48 8b 04[ 	]+mov    %fs:0x0,%rax
+  401091:	25 00 00 00 00 *
+  401096:	90[ 	]+nop *
+  401097:	90[ 	]+nop *
+  401098:	48 8d 90 a0 ff ff ff[ 	]+lea    0xf+a0\(%rax\),%rdx
+#							sh1
+  40109f:	90[ 	]+nop *
+  4010a0:	90[ 	]+nop *
+  4010a1:	48 8d 88 a7 ff ff ff[ 	]+lea    0xf+a7\(%rax\),%rcx
+#							sh2+3
+  4010a8:	90[ 	]+nop *
+  4010a9:	90[ 	]+nop *
+  4010aa:	90[ 	]+nop *
+  4010ab:	90[ 	]+nop *
+#  IE against global var
+  4010ac:	64 4c 8b 0c 25 00 00[ 	]+mov    %fs:0x0,%r9
+  4010b3:	00 00 *
+  4010b5:	90[ 	]+nop *
+  4010b6:	90[ 	]+nop *
+  4010b7:	4c 03 0d 0a 11 10 00[ 	]+add    1052938\(%rip\),%r9 +# 5021c8 <_GLOBAL_OFFSET_TABLE_\+0x28>
+#				-> R_X86_64_TPOFF64	sG2
+  4010be:	90[ 	]+nop *
+  4010bf:	90[ 	]+nop *
+  4010c0:	90[ 	]+nop *
+  4010c1:	90[ 	]+nop *
+#  IE -> LE against global var defined in exec
+  4010c2:	64 4c 8b 14 25 00 00[ 	]+mov    %fs:0x0,%r10
+  4010c9:	00 00 *
+  4010cb:	90[ 	]+nop *
+  4010cc:	90[ 	]+nop *
+  4010cd:	4d 8d 92 60 ff ff ff[ 	]+lea    0xf+60\(%r10\),%r10
+#							sg1
+  4010d4:	90[ 	]+nop *
+  4010d5:	90[ 	]+nop *
+  4010d6:	90[ 	]+nop *
+  4010d7:	90[ 	]+nop *
+#  IE -> LE against local var
+  4010d8:	64 48 8b 04 25 00 00[ 	]+mov    %fs:0x0,%rax
+  4010df:	00 00 *
+  4010e1:	90[ 	]+nop *
+  4010e2:	90[ 	]+nop *
+  4010e3:	48 8d 80 80 ff ff ff[ 	]+lea    0xf+80\(%rax\),%rax
+#							sl1
+  4010ea:	90[ 	]+nop *
+  4010eb:	90[ 	]+nop *
+  4010ec:	90[ 	]+nop *
+  4010ed:	90[ 	]+nop *
+#  IE -> LE against hidden var
+  4010ee:	64 48 8b 0c 25 00 00[ 	]+mov    %fs:0x0,%rcx
+  4010f5:	00 00 *
+  4010f7:	90[ 	]+nop *
+  4010f8:	90[ 	]+nop *
+  4010f9:	48 8d 89 a0 ff ff ff[ 	]+lea    0xf+a0\(%rcx\),%rcx
+#							sh1
+  401100:	90[ 	]+nop *
+  401101:	90[ 	]+nop *
+  401102:	90[ 	]+nop *
+  401103:	90[ 	]+nop *
+#  Direct access through %fs
+#  IE against global var
+  401104:	48 8b 0d b5 10 10 00[ 	]+mov    1052853\(%rip\),%rcx +# 5021c0 <_GLOBAL_OFFSET_TABLE_\+0x20>
+#				-> R_X86_64_TPOFF64	sG5
+  40110b:	90[ 	]+nop *
+  40110c:	90[ 	]+nop *
+  40110d:	64 48 8b 11[ 	]+mov    %fs:\(%rcx\),%rdx
+  401111:	90[ 	]+nop *
+  401112:	90[ 	]+nop *
+  401113:	90[ 	]+nop *
+  401114:	90[ 	]+nop *
+#  IE->LE against local var
+  401115:	49 c7 c3 90 ff ff ff[ 	]+mov    \$0xf+90,%r11
+#							sl5
+  40111c:	90[ 	]+nop *
+  40111d:	90[ 	]+nop *
+  40111e:	64 4d 8b 23[ 	]+mov    %fs:\(%r11\),%r12
+  401122:	90[ 	]+nop *
+  401123:	90[ 	]+nop *
+  401124:	90[ 	]+nop *
+  401125:	90[ 	]+nop *
+#  IE->LE against hidden var
+  401126:	48 c7 c2 b0 ff ff ff[ 	]+mov    \$0xf+b0,%rdx
+  40112d:	90[ 	]+nop *
+  40112e:	90[ 	]+nop *
+  40112f:	64 48 8b 12[ 	]+mov    %fs:\(%rdx\),%rdx
+#							sh5
+  401133:	90[ 	]+nop *
+  401134:	90[ 	]+nop *
+  401135:	90[ 	]+nop *
+  401136:	90[ 	]+nop *
+  401137:	c9[ 	]+leaveq *
+  401138:	c3[ 	]+retq *
+  401139:	90[ 	]+nop *
+  40113a:	90[ 	]+nop *
+  40113b:	90[ 	]+nop *
+
+0+40113c <_start>:
+  40113c:	55[ 	]+push   %rbp
+  40113d:	48 89 e5[ 	]+mov    %rsp,%rbp
+#  IE against global var
+  401140:	64 4c 8b 1c 25 00 00[ 	]+mov    %fs:0x0,%r11
+  401147:	00 00 *
+  401149:	90[ 	]+nop *
+  40114a:	90[ 	]+nop *
+  40114b:	4c 03 1d 7e 10 10 00[ 	]+add    1052798\(%rip\),%r11 +# 5021d0 <_GLOBAL_OFFSET_TABLE_\+0x30>
+#				-> R_X86_64_TPOFF64	sG6
+  401152:	90[ 	]+nop *
+  401153:	90[ 	]+nop *
+  401154:	90[ 	]+nop *
+  401155:	90[ 	]+nop *
+#  IE -> LE against global var defined in exec
+  401156:	64 48 8b 14 25 00 00[ 	]+mov    %fs:0x0,%rdx
+  40115d:	00 00 *
+  40115f:	90[ 	]+nop *
+  401160:	90[ 	]+nop *
+  401161:	48 8d 92 d4 ff ff ff[ 	]+lea    0xf+d4\(%rdx\),%rdx
+#							bg6
+  401168:	90[ 	]+nop *
+  401169:	90[ 	]+nop *
+  40116a:	90[ 	]+nop *
+  40116b:	90[ 	]+nop *
+#  IE -> LE against local var
+  40116c:	64 4c 8b 24 25 00 00[ 	]+mov    %fs:0x0,%r12
+  401173:	00 00 *
+  401175:	90[ 	]+nop *
+  401176:	90[ 	]+nop *
+  401177:	49 81 c4 f4 ff ff ff[ 	]+add    \$0xf+f4,%r12
+#							bl6
+  40117e:	90[ 	]+nop *
+  40117f:	90[ 	]+nop *
+  401180:	90[ 	]+nop *
+  401181:	90[ 	]+nop *
+#  direct %fs access IE -> LE against local var
+  401182:	48 c7 c2 fc ff ff ff[ 	]+mov    \$0xf+fc,%rdx
+#							bl8
+  401189:	90[ 	]+nop *
+  40118a:	90[ 	]+nop *
+  40118b:	64 48 8b 02[ 	]+mov    %fs:\(%rdx\),%rax
+  40118f:	90[ 	]+nop *
+  401190:	90[ 	]+nop *
+  401191:	90[ 	]+nop *
+  401192:	90[ 	]+nop *
+#  IE -> LE against hidden but not local var
+  401193:	64 48 8b 14 25 00 00[ 	]+mov    %fs:0x0,%rdx
+  40119a:	00 00 *
+  40119c:	90[ 	]+nop *
+  40119d:	90[ 	]+nop *
+  40119e:	48 8d 92 b4 ff ff ff[ 	]+lea    0xf+b4\(%rdx\),%rdx
+#							sh6
+  4011a5:	90[ 	]+nop *
+  4011a6:	90[ 	]+nop *
+  4011a7:	90[ 	]+nop *
+  4011a8:	90[ 	]+nop *
+#  direct %fs access IE -> LE against hidden but not local var
+  4011a9:	48 c7 c2 bc ff ff ff[ 	]+mov    \$0xf+bc,%rdx
+#							sh8
+  4011b0:	90[ 	]+nop *
+  4011b1:	90[ 	]+nop *
+  4011b2:	64 48 8b 02[ 	]+mov    %fs:\(%rdx\),%rax
+  4011b6:	90[ 	]+nop *
+  4011b7:	90[ 	]+nop *
+  4011b8:	90[ 	]+nop *
+  4011b9:	90[ 	]+nop *
+#  LE, global var defined in exec
+  4011ba:	64 48 8b 04 25 00 00[ 	]+mov    %fs:0x0,%rax
+  4011c1:	00 00 *
+  4011c3:	90[ 	]+nop *
+  4011c4:	90[ 	]+nop *
+  4011c5:	48 8d 90 64 ff ff ff[ 	]+lea    0xf+64\(%rax\),%rdx
+#							sg2
+  4011cc:	90[ 	]+nop *
+  4011cd:	90[ 	]+nop *
+  4011ce:	90[ 	]+nop *
+  4011cf:	90[ 	]+nop *
+#  LE, local var, non-canonical sequence
+  4011d0:	49 c7 c1 e6 ff ff ff[ 	]+mov    \$0xf+e6,%r9
+#							bl2+2
+  4011d7:	90[ 	]+nop *
+  4011d8:	90[ 	]+nop *
+  4011d9:	64 48 8b 14 25 00 00[ 	]+mov    %fs:0x0,%rdx
+  4011e0:	00 00 *
+  4011e2:	90[ 	]+nop *
+  4011e3:	90[ 	]+nop *
+  4011e4:	4c 01 ca[ 	]+add    %r9,%rdx
+  4011e7:	90[ 	]+nop *
+  4011e8:	90[ 	]+nop *
+  4011e9:	90[ 	]+nop *
+  4011ea:	90[ 	]+nop *
+#  LE, hidden var defined in exec, non-canonical sequence
+  4011eb:	64 48 8b 14 25 00 00[ 	]+mov    %fs:0x0,%rdx
+  4011f2:	00 00 *
+  4011f4:	90[ 	]+nop *
+  4011f5:	90[ 	]+nop *
+  4011f6:	48 81 c2 a5 ff ff ff[ 	]+add    \$0xf+a5,%rdx
+#							sh2+1
+  4011fd:	90[ 	]+nop *
+  4011fe:	90[ 	]+nop *
+  4011ff:	90[ 	]+nop *
+  401200:	90[ 	]+nop *
+#  Direct %fs access
+#  LE, global var defined in exec
+  401201:	64 48 8b 04 25 68 ff[ 	]+mov    %fs:0xf+68,%rax
+  401208:	ff ff *
+#							sg3
+  40120a:	90[ 	]+nop *
+  40120b:	90[ 	]+nop *
+  40120c:	90[ 	]+nop *
+  40120d:	90[ 	]+nop *
+#  LE, local var
+  40120e:	64 4c 8b 14 25 eb ff[ 	]+mov    %fs:0xf+eb,%r10
+  401215:	ff ff *
+#							bl3+3
+  401217:	90[ 	]+nop *
+  401218:	90[ 	]+nop *
+  401219:	90[ 	]+nop *
+  40121a:	90[ 	]+nop *
+#  LE, hidden var defined in exec
+  40121b:	64 48 8b 14 25 a9 ff[ 	]+mov    %fs:0xf+a9,%rdx
+  401222:	ff ff *
+#							sh3+1
+  401224:	90[ 	]+nop *
+  401225:	90[ 	]+nop *
+  401226:	90[ 	]+nop *
+  401227:	90[ 	]+nop *
+  401228:	c9[ 	]+leaveq *
+  401229:	c3[ 	]+retq *
--- ld/testsuite/ld-x86-64/tlsbin.sd.jj	2002-09-26 14:55:26.000000000 +0200
+++ ld/testsuite/ld-x86-64/tlsbin.sd	2002-09-26 15:31:00.000000000 +0200
@@ -0,0 +1,14 @@
+#source: tlsbinpic.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:
+ 5021a0 [0-9a-f]+ [0-9a-f]+ 00000000 00000000  .*
+ 5021b0 00000000 00000000 [0-9a-f]+ [0-9a-f]+  .*
+ 5021c0 00000000 00000000 00000000 00000000  .*
+ 5021d0 00000000 00000000 00000000 00000000  .*
--- ld/testsuite/ld-x86-64/tlsbin.td.jj	2002-09-26 14:55:30.000000000 +0200
+++ ld/testsuite/ld-x86-64/tlsbin.td	2002-09-26 15:00:17.000000000 +0200
@@ -0,0 +1,16 @@
+#source: tlsbinpic.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:
+ 502000 11000000 12000000 13000000 14000000  .*
+ 502010 15000000 16000000 17000000 18000000  .*
+ 502020 41000000 42000000 43000000 44000000  .*
+ 502030 45000000 46000000 47000000 48000000  .*
+ 502040 01010000 02010000 03010000 04010000  .*
+ 502050 05010000 06010000 07010000 08010000  .*

	Jakub



More information about the Binutils mailing list