This is the mail archive of the binutils@sources.redhat.com mailing list for the binutils project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

[PATCH] TLS support for s390*.


Hi,
nobody seems to have any objections against the TLS ABI for s390*. So
Uli and I decided to go with it. Here is the patch that implements the
binutils part of the TLS support.

blue skies,
  Martin.

bfd/ChangeLog:
2003-01-24  Martin Schwidefsky  <sky@mschwid3.boeblingen.de.ibm.com>

	* bfd-in2.h: Regenerate.
	* elf32-s390.c (elf_s390_mkobject, elf_s390_tls_transition,
	s390_tls_reloc, dtpoff_base, tpoff, invalid_tls_insn): New functions.
	(elf_howto_table): Add TLS relocs.
	(elf_s390_reloc_type_lookup): Likewise.
	(elf_s390_link_hash_entry): Add tls_type.
	(elf_s390_hash_entry, elf_s390_obj_tdata, elf_s390_local_got_tls_type):
	New macros.
	(elf_s390_link_hash_table): Add tls_ldm_got.
	(link_hash_newfunc): Initialize tls_type.
	(elf_s390_link_hash_table_create): Initialize refcount of tls_ldm_got.
	(elf_s390_copy_indirect_symbol): Copy tls_type information.
	(elf_s390_check_relocs): Support TLS relocs.
	(elf_s390_gc_sweep_hook): Likewise.
	(allocate_dynrelocs): Likewise.
	(elf_s390_size_dynamic_sections): Likewise.
	(elf_s390_relocate_section): Likewise.
	(elf_s390_finish_dynamic_symbol): Likewise.
	(bfd_elf32_mkobject): Define for TLS.
	* elf64-s390.c: Same changes as for elf32-s390.c.
	* libbfd.h: Regenerate.
	* reloc.c: Add s390 TLS relocations.

gas/ChangeLog:
2003-01-24  Martin Schwidefsky  <sky@mschwid3.boeblingen.de.ibm.com>

	* config/tc-s390.c (s390_tls_suffix): New function.
	(elf_suffix_type): Add suffix enums for TLS relocations.
	(s390_elf_suffix): Add suffix strings for TLS relocations.
	(s390_elf_cons): Map new lenght/elf suffix combinations for TLS to
	bfd relocations.
	(md_gather_operands): Map new instruction operand/elf suffix
	combinations for TLS to bfd relocations.
	(tc_s390_fix_adjustable): Add new TLS relocations.
	(tc_s390_force_relocation): Likewise.
	(md_apply_fix3): Likewise.

include/elf/ChangeLog:
2003-01-24  Martin Schwidefsky  <sky@mschwid3.boeblingen.de.ibm.com>

	* s390.h: Add s390 TLS relocations.

ld/testsuite/ChangeLog:
2003-01-24  Martin Schwidefsky  <sky@mschwid3.boeblingen.de.ibm.com>

	* ld-s390/s390.exp: New file.
	* ld-s390/tlsbin_64.dd: New file.
	* ld-s390/tlsbin_64.rd: New file.
	* ld-s390/tlsbin_64.s: New file.
	* ld-s390/tlsbin_64.sd: New file.
	* ld-s390/tlsbin_64.td: New file.
	* ld-s390/tlsbin.dd: New file.
	* ld-s390/tlsbinpic_64.s: New file.
	* ld-s390/tlsbinpic.s: New file.
	* ld-s390/tlsbin.rd: New file.
	* ld-s390/tlsbin.s: New file.
	* ld-s390/tlsbin.sd: New file.
	* ld-s390/tlsbin.td: New file.
	* ld-s390/tlslib_64.s: New file.
	* ld-s390/tlslib.s: New file.
	* ld-s390/tlspic1_64.s: New file.
	* ld-s390/tlspic1.s: New file.
	* ld-s390/tlspic2_64.s: New file.
	* ld-s390/tlspic2.s: New file.
	* ld-s390/tlspic_64.dd: New file.
	* ld-s390/tlspic_64.rd: New file.
	* ld-s390/tlspic_64.sd: New file.
	* ld-s390/tlspic_64.td: New file.
	* ld-s390/tlspic.dd: New file.
	* ld-s390/tlspic.rd: New file.
	* ld-s390/tlspic.sd: New file.
	* ld-s390/tlspic.td: New file.

diff -urN src/bfd/bfd-in2.h src-s390/bfd/bfd-in2.h
--- src/bfd/bfd-in2.h	Mon Jan 20 12:38:30 2003
+++ src-s390/bfd/bfd-in2.h	Thu Jan 23 23:23:13 2003
@@ -3023,6 +3023,28 @@
 /* 64-bit rel. offset from the GOT to a PLT entry.  */
   BFD_RELOC_390_PLTOFF64,
 
+/* s390 tls relocations.  */
+  BFD_RELOC_390_TLS_LOAD,
+  BFD_RELOC_390_TLS_GDCALL,
+  BFD_RELOC_390_TLS_LDCALL,
+  BFD_RELOC_390_TLS_GD32,
+  BFD_RELOC_390_TLS_GD64,
+  BFD_RELOC_390_TLS_GOTIE12,
+  BFD_RELOC_390_TLS_GOTIE32,
+  BFD_RELOC_390_TLS_GOTIE64,
+  BFD_RELOC_390_TLS_LDM32,
+  BFD_RELOC_390_TLS_LDM64,
+  BFD_RELOC_390_TLS_IE32,
+  BFD_RELOC_390_TLS_IE64,
+  BFD_RELOC_390_TLS_IEENT,
+  BFD_RELOC_390_TLS_LE32,
+  BFD_RELOC_390_TLS_LE64,
+  BFD_RELOC_390_TLS_LDO32,
+  BFD_RELOC_390_TLS_LDO64,
+  BFD_RELOC_390_TLS_DTPMOD,
+  BFD_RELOC_390_TLS_DTPOFF,
+  BFD_RELOC_390_TLS_TPOFF,
+
 /* Scenix IP2K - 9-bit register number / data address  */
   BFD_RELOC_IP2K_FR9,
 
diff -urN src/bfd/elf32-s390.c src-s390/bfd/elf32-s390.c
--- src/bfd/elf32-s390.c	Mon Jan 20 12:38:30 2003
+++ src-s390/bfd/elf32-s390.c	Fri Jan 24 09:50:20 2003
@@ -72,10 +72,22 @@
   PARAMS ((const Elf_Internal_Rela *));
 static bfd_boolean elf_s390_finish_dynamic_sections
   PARAMS ((bfd *, struct bfd_link_info *));
+static bfd_boolean elf_s390_mkobject
+  PARAMS ((bfd *));
 static bfd_boolean elf_s390_object_p
   PARAMS ((bfd *));
 static bfd_boolean elf_s390_grok_prstatus
   PARAMS ((bfd *, Elf_Internal_Note *));
+static int elf_s390_tls_transition
+  PARAMS ((struct bfd_link_info *, int, int));
+static bfd_reloc_status_type s390_tls_reloc
+  PARAMS ((bfd *, arelent *, asymbol *, PTR, asection *, bfd *, char **));
+static bfd_vma dtpoff_base
+  PARAMS ((struct bfd_link_info *));
+static bfd_vma tpoff
+  PARAMS ((struct bfd_link_info *, bfd_vma));
+static void invalid_tls_insn
+  PARAMS ((bfd *, asection *, Elf_Internal_Rela *));
 
 #include "elf/s390.h"
 
@@ -162,6 +174,40 @@
   HOWTO(R_390_PLTOFF32,  0, 2, 32, FALSE, 0, complain_overflow_bitfield,
 	bfd_elf_generic_reloc, "R_390_PLTOFF32", FALSE, 0,0xffffffff, FALSE),
   EMPTY_HOWTO (R_390_PLTOFF64),	/* Empty entry for R_390_PLTOFF64.  */
+  HOWTO(R_390_TLS_LOAD, 0, 0, 0, FALSE, 0, complain_overflow_dont,
+	s390_tls_reloc, "R_390_TLS_LOAD", FALSE, 0, 0, FALSE),
+  HOWTO(R_390_TLS_GDCALL, 0, 0, 0, FALSE, 0, complain_overflow_dont,
+	s390_tls_reloc, "R_390_TLS_GDCALL", FALSE, 0, 0, FALSE),
+  HOWTO(R_390_TLS_LDCALL, 0, 0, 0, FALSE, 0, complain_overflow_dont,
+	s390_tls_reloc, "R_390_TLS_LDCALL", FALSE, 0, 0, FALSE),
+  HOWTO(R_390_TLS_GD32, 0, 2, 32, FALSE, 0, complain_overflow_bitfield,
+	bfd_elf_generic_reloc, "R_390_TLS_GD32", FALSE, 0, 0xffffffff, FALSE),
+  EMPTY_HOWTO (R_390_TLS_GD64),	/* Empty entry for R_390_TLS_GD64.  */
+  HOWTO(R_390_TLS_GOTIE12, 0, 1, 12, FALSE, 0, complain_overflow_dont,
+	bfd_elf_generic_reloc, "R_390_TLS_GOTIE12", FALSE, 0, 0x00000fff, FALSE),
+  HOWTO(R_390_TLS_GOTIE32, 0, 2, 32, FALSE, 0, complain_overflow_bitfield,
+	bfd_elf_generic_reloc, "R_390_TLS_GOTIE32", FALSE, 0, 0xffffffff, FALSE),
+  EMPTY_HOWTO (R_390_TLS_GOTIE64),	/* Empty entry for R_390_TLS_GOTIE64.  */
+  HOWTO(R_390_TLS_LDM32, 0, 2, 32, FALSE, 0, complain_overflow_bitfield,
+	bfd_elf_generic_reloc, "R_390_TLS_LDM32", FALSE, 0, 0xffffffff, FALSE),
+  EMPTY_HOWTO (R_390_TLS_LDM64),	/* Empty entry for R_390_TLS_LDM64.  */
+  HOWTO(R_390_TLS_IE32, 0, 2, 32, FALSE, 0, complain_overflow_bitfield,
+	bfd_elf_generic_reloc, "R_390_TLS_IE32", FALSE, 0, 0xffffffff, FALSE),
+  EMPTY_HOWTO (R_390_TLS_IE64),	/* Empty entry for R_390_TLS_IE64.  */
+  HOWTO(R_390_TLS_IEENT, 1, 2, 32, TRUE, 0, complain_overflow_bitfield,
+	bfd_elf_generic_reloc, "R_390_TLS_IEENT", FALSE, 0, 0xffffffff, TRUE),
+  HOWTO(R_390_TLS_LE32, 0, 2, 32, FALSE, 0, complain_overflow_bitfield,
+	bfd_elf_generic_reloc, "R_390_TLS_LE32", FALSE, 0, 0xffffffff, FALSE),
+  EMPTY_HOWTO (R_390_TLS_LE64),	/* Empty entry for R_390_TLS_LE64.  */
+  HOWTO(R_390_TLS_LDO32, 0, 2, 32, FALSE, 0, complain_overflow_bitfield,
+	bfd_elf_generic_reloc, "R_390_TLS_LDO32", FALSE, 0, 0xffffffff, FALSE),
+  EMPTY_HOWTO (R_390_TLS_LDO64),	/* Empty entry for R_390_TLS_LDO64.  */
+  HOWTO(R_390_TLS_DTPMOD, 0, 2, 32, FALSE, 0, complain_overflow_bitfield,
+	bfd_elf_generic_reloc, "R_390_TLS_DTPMOD", FALSE, 0, 0xffffffff, FALSE),
+  HOWTO(R_390_TLS_DTPOFF, 0, 2, 32, FALSE, 0, complain_overflow_bitfield,
+	bfd_elf_generic_reloc, "R_390_TLS_DTPOFF", FALSE, 0, 0xffffffff, FALSE),
+  HOWTO(R_390_TLS_TPOFF, 0, 2, 32, FALSE, 0, complain_overflow_bitfield,
+	bfd_elf_generic_reloc, "R_390_TLS_TPOFF", FALSE, 0, 0xffffffff, FALSE),
 };
 
 /* GNU extension to record C++ vtable hierarchy.  */
@@ -239,6 +285,34 @@
       return &elf_howto_table[(int) R_390_PLTOFF16];
     case BFD_RELOC_390_PLTOFF32:
       return &elf_howto_table[(int) R_390_PLTOFF32];
+    case BFD_RELOC_390_TLS_LOAD:
+      return &elf_howto_table[(int) R_390_TLS_LOAD];
+    case BFD_RELOC_390_TLS_GDCALL:
+      return &elf_howto_table[(int) R_390_TLS_GDCALL];
+    case BFD_RELOC_390_TLS_LDCALL:
+      return &elf_howto_table[(int) R_390_TLS_LDCALL];
+    case BFD_RELOC_390_TLS_GD32:
+      return &elf_howto_table[(int) R_390_TLS_GD32];
+    case BFD_RELOC_390_TLS_GOTIE12:
+      return &elf_howto_table[(int) R_390_TLS_GOTIE12];
+    case BFD_RELOC_390_TLS_GOTIE32:
+      return &elf_howto_table[(int) R_390_TLS_GOTIE32];
+    case BFD_RELOC_390_TLS_LDM32:
+      return &elf_howto_table[(int) R_390_TLS_LDM32];
+    case BFD_RELOC_390_TLS_IE32:
+      return &elf_howto_table[(int) R_390_TLS_IE32];
+    case BFD_RELOC_390_TLS_IEENT:
+      return &elf_howto_table[(int) R_390_TLS_IEENT];
+    case BFD_RELOC_390_TLS_LE32:
+      return &elf_howto_table[(int) R_390_TLS_LE32];
+    case BFD_RELOC_390_TLS_LDO32:
+      return &elf_howto_table[(int) R_390_TLS_LDO32];
+    case BFD_RELOC_390_TLS_DTPMOD:
+      return &elf_howto_table[(int) R_390_TLS_DTPMOD];
+    case BFD_RELOC_390_TLS_DTPOFF:
+      return &elf_howto_table[(int) R_390_TLS_DTPOFF];
+    case BFD_RELOC_390_TLS_TPOFF:
+      return &elf_howto_table[(int) R_390_TLS_TPOFF];
     case BFD_RELOC_VTABLE_INHERIT:
       return &elf32_s390_vtinherit_howto;
     case BFD_RELOC_VTABLE_ENTRY:
@@ -274,6 +348,23 @@
     }
 }
 
+/* A relocation function which doesn't do anything.  */
+static bfd_reloc_status_type
+s390_tls_reloc (abfd, reloc_entry, symbol, data, input_section,
+                      output_bfd, error_message)
+     bfd *abfd ATTRIBUTE_UNUSED;
+     arelent *reloc_entry;
+     asymbol *symbol ATTRIBUTE_UNUSED;
+     PTR data ATTRIBUTE_UNUSED;
+     asection *input_section;
+     bfd *output_bfd;
+     char **error_message ATTRIBUTE_UNUSED;
+{
+  if (output_bfd)
+    reloc_entry->address += input_section->output_offset;
+  return bfd_reloc_ok;
+}
+
 static bfd_boolean
 elf_s390_is_local_label_name (abfd, name)
      bfd *abfd;
@@ -476,8 +567,59 @@
 
   /* Number of GOTPLT references for a function.  */
   bfd_signed_vma gotplt_refcount;
+
+#define GOT_UNKNOWN	0
+#define GOT_NORMAL	1
+#define GOT_TLS_GD	2
+#define GOT_TLS_IE	3
+#define GOT_TLS_IE_NLT	4
+  unsigned char tls_type;
 };
 
+#define elf_s390_hash_entry(ent) \
+  ((struct elf_s390_link_hash_entry *)(ent))
+
+struct elf_s390_obj_tdata
+{
+  struct elf_obj_tdata root;
+
+  /* tls_type for each local got entry.  */
+  char *local_got_tls_type;
+};
+
+#define elf_s390_tdata(abfd) \
+  ((struct elf_s390_obj_tdata *) (abfd)->tdata.any)
+
+#define elf_s390_local_got_tls_type(abfd) \
+  (elf_s390_tdata (abfd)->local_got_tls_type)
+
+static bfd_boolean
+elf_s390_mkobject (abfd)
+     bfd *abfd;
+{
+  bfd_size_type amt = sizeof (struct elf_s390_obj_tdata);
+  abfd->tdata.any = bfd_zalloc (abfd, amt);
+  if (abfd->tdata.any == NULL)
+    return FALSE;
+  return TRUE;
+}
+
+static bfd_boolean
+elf_s390_object_p (abfd)
+     bfd *abfd;
+{
+  /* Allocate our special target data.  */
+  struct elf_s390_obj_tdata *new_tdata;
+  bfd_size_type amt = sizeof (struct elf_s390_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 s390 elf32 file.  */
+  return bfd_default_set_arch_mach (abfd, bfd_arch_s390, bfd_mach_s390_31);
+}
+
 /* s390 ELF linker hash table.  */
 
 struct elf_s390_link_hash_table
@@ -493,6 +635,11 @@
   asection *sdynbss;
   asection *srelbss;
 
+  union {
+    bfd_signed_vma refcount;
+    bfd_vma offset;
+  } tls_ldm_got;
+
   /* Small local sym to section mapping cache.  */
   struct sym_sec_cache sym_sec;
 };
@@ -529,6 +676,7 @@
       eh = (struct elf_s390_link_hash_entry *) entry;
       eh->dyn_relocs = NULL;
       eh->gotplt_refcount = 0;
+      eh->tls_type = GOT_UNKNOWN;
     }
 
   return entry;
@@ -560,6 +708,7 @@
   ret->srelplt = NULL;
   ret->sdynbss = NULL;
   ret->srelbss = NULL;
+  ret->tls_ldm_got.refcount = 0;
   ret->sym_sec.abfd = NULL;
 
   return &ret->elf.root;
@@ -672,9 +821,43 @@
       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 int
+elf_s390_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_390_TLS_GD32:
+    case R_390_TLS_IE32:
+      if (is_local)
+	return R_390_TLS_LE32;
+      return R_390_TLS_IE32;
+    case R_390_TLS_GOTIE32:
+      if (is_local)
+	return R_390_TLS_LE32;
+      return R_390_TLS_GOTIE32;
+    case R_390_TLS_LDM32:
+      return R_390_TLS_LE32;
+    }
+
+  return r_type;
+}
+
 /* Look through the relocs for a section during the first phase, and
    allocate space in the global offset table or procedure linkage
    table.  */
@@ -693,6 +876,7 @@
   const Elf_Internal_Rela *rel_end;
   asection *sreloc;
   bfd_signed_vma *local_got_refcounts;
+  int tls_type, old_tls_type;
 
   if (info->relocateable)
     return TRUE;
@@ -707,6 +891,7 @@
   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;
 
@@ -727,7 +912,10 @@
 
       /* Create got section and local_got_refcounts array if they
 	 are needed.  */
-      switch (ELF32_R_TYPE (rel->r_info))
+      r_type = elf_s390_tls_transition (info,
+					ELF32_R_TYPE (rel->r_info),
+					h == NULL);
+      switch (r_type)
 	{
 	case R_390_GOT12:
 	case R_390_GOT16:
@@ -737,18 +925,26 @@
 	case R_390_GOTPLT16:
 	case R_390_GOTPLT32:
 	case R_390_GOTPLTENT:
+	case R_390_TLS_GD32:
+	case R_390_TLS_GOTIE12:
+	case R_390_TLS_GOTIE32:
+	case R_390_TLS_IEENT:
+	case R_390_TLS_IE32:
+	case R_390_TLS_LDM32:
 	  if (h == NULL
 	      && local_got_refcounts == NULL)
 	    {
 	      bfd_size_type size;
 	      
 	      size = symtab_hdr->sh_info;
-	      size *= sizeof (bfd_signed_vma);
+	      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;
+	      elf_s390_local_got_tls_type (abfd)
+		= (char *) (local_got_refcounts + symtab_hdr->sh_info);
 	    }
 	  /* Fall through.  */
 	case R_390_GOTOFF16:
@@ -764,19 +960,8 @@
 	    }
 	}
 
-      switch (ELF32_R_TYPE (rel->r_info))
+      switch (r_type)
 	{
-	case R_390_GOT12:
-        case R_390_GOT16:
-	case R_390_GOT32:
-	case R_390_GOTENT:
-	  /* This symbol requires a global offset table entry.  */
-	  if (h != NULL)
-	    h->got.refcount += 1;
-	  else
-	    local_got_refcounts[r_symndx] += 1;
-	  break;
-
 	case R_390_GOTOFF16:
 	case R_390_GOTOFF32:
 	case R_390_GOTPC:
@@ -827,6 +1012,89 @@
 	    local_got_refcounts[r_symndx] += 1;
 	  break;
 
+	case R_390_TLS_LDM32:
+	  htab->tls_ldm_got.refcount += 1;
+	  break;
+
+	case R_390_TLS_IE32:
+	case R_390_TLS_GOTIE12:
+	case R_390_TLS_GOTIE32:
+	case R_390_TLS_IEENT:
+	  if (info->shared)
+	    info->flags |= DF_STATIC_TLS;
+	  /* Fall through */
+
+	case R_390_GOT12:
+        case R_390_GOT16:
+	case R_390_GOT32:
+	case R_390_GOTENT:
+	case R_390_TLS_GD32:
+	  /* This symbol requires a global offset table entry.  */
+	  switch (r_type)
+	    {
+	    default:
+	    case R_390_GOT12:
+	    case R_390_GOT16:
+	    case R_390_GOT32:
+	    case R_390_GOTENT:
+	      tls_type = GOT_NORMAL;
+	      break;
+	    case R_390_TLS_GD32:
+	      tls_type = GOT_TLS_GD;
+	      break;
+	    case R_390_TLS_IE32:
+	    case R_390_TLS_GOTIE32:
+	      tls_type = GOT_TLS_IE;
+	      break;
+	    case R_390_TLS_GOTIE12:
+	    case R_390_TLS_IEENT:
+	      tls_type = GOT_TLS_IE_NLT;
+	      break;
+	    }
+
+	  if (h != NULL)
+	    {
+	      h->got.refcount += 1;
+	      old_tls_type = elf_s390_hash_entry(h)->tls_type;
+	    }
+	  else
+	    {
+	      local_got_refcounts[r_symndx] += 1;
+	      old_tls_type = elf_s390_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)
+	    {
+	      if (old_tls_type == GOT_NORMAL || tls_type == GOT_NORMAL)
+		{
+		  (*_bfd_error_handler)
+		    (_("%s: `%s' accessed both as normal and thread local symbol"),
+		     bfd_archive_filename (abfd), h->root.root.string);
+		  return FALSE;
+		}
+	      if (old_tls_type > tls_type)
+		tls_type = old_tls_type;
+	    }
+
+	  if (old_tls_type != tls_type)
+	    {
+	      if (h != NULL)
+		elf_s390_hash_entry (h)->tls_type = tls_type;
+	      else
+		elf_s390_local_got_tls_type (abfd) [r_symndx] = tls_type;
+	    }
+
+	  if (r_type != R_390_TLS_IE32)
+	    break;
+	  /* Fall through */
+
+	case R_390_TLS_LE32:
+	  if (!info->shared)
+	    break;
+	  info->flags |= DF_STATIC_TLS;
+	  /* Fall through */	    
+
         case R_390_8:
         case R_390_16:
 	case R_390_32:
@@ -1059,6 +1327,7 @@
   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;
@@ -1077,8 +1346,21 @@
       else
 	h = sym_hashes[r_symndx - symtab_hdr->sh_info];
 
-      switch (ELF32_R_TYPE (rel->r_info))
+      r_type = elf_s390_tls_transition (info,
+					ELF32_R_TYPE (rel->r_info),
+					r_symndx >= symtab_hdr->sh_info);
+      switch (r_type)
 	{
+	case R_390_TLS_LDM32:
+	  if (elf_s390_hash_table (info)->tls_ldm_got.refcount > 0)
+	    elf_s390_hash_table (info)->tls_ldm_got.refcount -= 1;
+	  break;
+
+	case R_390_TLS_GD32:
+	case R_390_TLS_IE32:
+	case R_390_TLS_GOTIE12:
+	case R_390_TLS_GOTIE32:
+	case R_390_TLS_IEENT:
 	case R_390_GOT12:
 	case R_390_GOT16:
 	case R_390_GOT32:
@@ -1097,38 +1379,14 @@
 	      if (local_got_refcounts[r_symndx] > 0)
 		local_got_refcounts[r_symndx] -= 1;
 	    }
-	  break;
+	  if (r_type != R_390_TLS_IE32)
+	    break;
+	  /* Fall through */
 	  
-	case R_390_PLT16DBL:
-	case R_390_PLT32DBL:
-	case R_390_PLT32:
-	case R_390_PLTOFF16:
-	case R_390_PLTOFF32:
-	  if (h != NULL)
-	    {
-	      if (h->plt.refcount > 0)
-		h->plt.refcount -= 1;
-	    }
-	  break;
-
-	case R_390_GOTPLT12:
-	case R_390_GOTPLT16:
-	case R_390_GOTPLT32:
-	case R_390_GOTPLTENT:
-	  if (h != NULL)
-	    {
-	      if (h->plt.refcount > 0)
-		{
-		  ((struct elf_s390_link_hash_entry *) h)->gotplt_refcount--;
-		  h->plt.refcount -= 1;
-		}
-	    }
-	  else if (local_got_refcounts != NULL)
-	    {
-	      if (local_got_refcounts[r_symndx] > 0)
-		local_got_refcounts[r_symndx] -= 1;
-	    }
-	  break;
+	case R_390_TLS_LE32:
+	  if (!info->shared)
+	    break;
+	  /* Fall through */
 
 	case R_390_8:
 	case R_390_12:
@@ -1165,6 +1423,37 @@
 	    }
 	  break;
 	  
+	case R_390_PLT16DBL:
+	case R_390_PLT32DBL:
+	case R_390_PLT32:
+	case R_390_PLTOFF16:
+	case R_390_PLTOFF32:
+	  if (h != NULL)
+	    {
+	      if (h->plt.refcount > 0)
+		h->plt.refcount -= 1;
+	    }
+	  break;
+
+	case R_390_GOTPLT12:
+	case R_390_GOTPLT16:
+	case R_390_GOTPLT32:
+	case R_390_GOTPLTENT:
+	  if (h != NULL)
+	    {
+	      if (h->plt.refcount > 0)
+		{
+		  ((struct elf_s390_link_hash_entry *) h)->gotplt_refcount--;
+		  h->plt.refcount -= 1;
+		}
+	    }
+	  else if (local_got_refcounts != NULL)
+	    {
+	      if (local_got_refcounts[r_symndx] > 0)
+		local_got_refcounts[r_symndx] -= 1;
+	    }
+	  break;
+
 	default:
 	  break;
 	}
@@ -1437,10 +1726,31 @@
       elf_s390_adjust_gotplt((struct elf_s390_link_hash_entry *) h);
     }
 
-  if (h->got.refcount > 0)
-    {
+  /* If R_390_TLS_{IE32,GOTIE32,GOTIE12,IEENT} symbol is now local to
+     the binary, we can optimize a bit. IE32 and GOTIE32 get converted
+     to R_390_TLS_LE32 requiring no TLS entry. For GOTIE12 and IEENT
+     we can save the dynamic TLS relocation.  */
+  if (h->got.refcount > 0
+      && !info->shared
+      && h->dynindx == -1
+      && elf_s390_hash_entry(h)->tls_type >= GOT_TLS_IE)
+    {
+      if (elf_s390_hash_entry(h)->tls_type == GOT_TLS_IE_NLT)
+	/* For the GOTIE access without a literal pool entry the offset has
+	   to be stored somewhere. The immediate value in the instruction
+	   is not bit enough so the value is stored in the got.  */
+	{
+	  h->got.offset = htab->sgot->_raw_size;
+	  htab->sgot->_raw_size += GOT_ENTRY_SIZE;
+	}
+      else
+	h->got.offset = (bfd_vma) -1;
+    }
+  else if (h->got.refcount > 0)
+   {
       asection *s;
       bfd_boolean dyn;
+      int tls_type = elf_s390_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.  */
@@ -1454,8 +1764,18 @@
       s = htab->sgot;
       h->got.offset = s->_raw_size;
       s->_raw_size += GOT_ENTRY_SIZE;
+      /* R_390_TLS_GD32 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_390_TLS_IE32 needs one dynamic relocation,
+	 R_390_TLS_GD32 needs one if local symbol and two if global.  */
+      if ((tls_type == GOT_TLS_GD && h->dynindx == -1)
+	  || tls_type >= GOT_TLS_IE)
+	htab->srelgot->_raw_size += sizeof (Elf32_External_Rela);
+      else if (tls_type == GOT_TLS_GD)
+	htab->srelgot->_raw_size += 2 * sizeof (Elf32_External_Rela);
+      else if (WILL_CALL_FINISH_DYNAMIC_SYMBOL (dyn, info, h))
 	htab->srelgot->_raw_size += sizeof (Elf32_External_Rela);
     }
   else
@@ -1601,6 +1921,7 @@
     {
       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 *srela;
@@ -1642,14 +1963,17 @@
       symtab_hdr = &elf_tdata (ibfd)->symtab_hdr;
       locsymcount = symtab_hdr->sh_info;
       end_local_got = local_got + locsymcount;
+      local_tls_type = elf_s390_local_got_tls_type (ibfd);
       s = htab->sgot;
       srela = 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 (*local_tls_type == GOT_TLS_GD)
+		s->_raw_size += GOT_ENTRY_SIZE;
 	      if (info->shared)
 		srela->_raw_size += sizeof (Elf32_External_Rela);
 	    }
@@ -1658,6 +1982,17 @@
 	}
     }
 
+  if (htab->tls_ldm_got.refcount > 0)
+    {
+      /* Allocate 2 got entries and 1 dynamic reloc for R_390_TLS_LDM32
+	 relocs.  */
+      htab->tls_ldm_got.offset = htab->sgot->_raw_size;
+      htab->sgot->_raw_size += 2 * GOT_ENTRY_SIZE;
+      htab->srelgot->_raw_size += sizeof (Elf32_External_Rela);
+    }
+  else
+    htab->tls_ldm_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);
@@ -1768,6 +2103,58 @@
   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 (align_power (tls_segment->size, tls_segment->align)
+	  + tls_segment->start - address);
+}
+
+/* Complain if TLS instruction relocation is against an invalid
+   instruction.  */
+
+static void
+invalid_tls_insn (input_bfd, input_section, rel)
+     bfd *input_bfd;
+     asection *input_section;
+     Elf_Internal_Rela *rel;
+{
+  reloc_howto_type *howto;
+
+  howto = elf_howto_table + ELF32_R_TYPE (rel->r_info);
+  (*_bfd_error_handler)
+    (_("%s(%s+0x%lx): invalid instruction for TLS relocation %s"),
+     bfd_archive_filename (input_bfd),
+     bfd_get_section_name (input_bfd, input_section),
+     (long) rel->r_offset,
+     howto->name);
+}
+
 /* Relocate a 390 ELF section.  */
 
 static bfd_boolean
@@ -1811,6 +2198,7 @@
       bfd_vma relocation;
       bfd_boolean unresolved_reloc;
       bfd_reloc_status_type r;
+      int tls_type;
 
       r_type = ELF32_R_TYPE (rel->r_info);
       if (r_type == (int) R_390_GNU_VTINHERIT
@@ -2185,6 +2573,330 @@
             }
 	  break;
 
+	  /* Relocations for tls literal pool entries.  */
+	case R_390_TLS_IE32:
+	  if (info->shared)
+	    {
+	      Elf_Internal_Rela outrel;
+	      asection *sreloc;
+	      bfd_byte *loc;
+
+	      outrel.r_offset = rel->r_offset
+				+ input_section->output_section->vma
+				+ input_section->output_offset;
+	      outrel.r_info = ELF32_R_INFO (0, R_390_RELATIVE);
+	      sreloc = elf_section_data (input_section)->sreloc;
+	      if (sreloc == NULL)
+		abort ();
+	      loc = sreloc->contents;
+	      loc += sreloc->reloc_count++ * sizeof (Elf32_External_Rela);
+	      bfd_elf32_swap_reloc_out (output_bfd, &outrel, loc);
+	    }
+	  /* Fall through */
+
+	case R_390_TLS_GD32:
+	case R_390_TLS_GOTIE32:
+	  r_type = elf_s390_tls_transition (info, r_type, h == NULL);
+	  tls_type = GOT_UNKNOWN;
+	  if (h == NULL && local_got_offsets)
+	    tls_type = elf_s390_local_got_tls_type (input_bfd) [r_symndx];
+	  else if (h != NULL)
+	    {
+	      tls_type = elf_s390_hash_entry(h)->tls_type;
+	      if (!info->shared && h->dynindx == -1 && tls_type >= GOT_TLS_IE)
+		r_type = R_390_TLS_LE32;
+	    }
+	  if (r_type == R_390_TLS_GD32 && tls_type >= GOT_TLS_IE)
+	    r_type = R_390_TLS_IE32;
+
+	  if (r_type == R_390_TLS_LE32)
+	    {
+	      /* This relocation gets optimized away by the local exec
+		 access optimization.  */
+	      BFD_ASSERT (! unresolved_reloc);
+	      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];
+	    }
+
+	emit_tls_relocs:
+
+	  if ((off & 1) != 0)
+	    off &= ~1;
+          else
+	    {
+	      Elf_Internal_Rela outrel;
+	      bfd_byte *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_390_TLS_GD32)
+		dr_type = R_390_TLS_DTPMOD;
+	      else
+		dr_type = R_390_TLS_TPOFF;
+	      if (dr_type == R_390_TLS_TPOFF && indx == 0)
+		outrel.r_addend = relocation - dtpoff_base (info);
+	      else
+		outrel.r_addend = 0;
+	      outrel.r_info = ELF32_R_INFO (indx, dr_type);
+	      loc = htab->srelgot->contents;
+	      loc += htab->srelgot->reloc_count++
+		* sizeof (Elf32_External_Rela);
+	      bfd_elf32_swap_reloca_out (output_bfd, &outrel, loc);
+
+	      if (r_type == R_390_TLS_GD32)
+		{
+		  if (indx == 0)
+		    {
+	    	      BFD_ASSERT (! unresolved_reloc);
+		      bfd_put_32 (output_bfd,
+				  relocation - dtpoff_base (info),
+				  htab->sgot->contents + off + GOT_ENTRY_SIZE);
+		    }
+		  else
+		    {
+		      outrel.r_info = ELF32_R_INFO (indx, R_390_TLS_DTPOFF);
+		      outrel.r_offset += GOT_ENTRY_SIZE;
+		      outrel.r_addend = 0;
+		      htab->srelgot->reloc_count++;
+		      loc += sizeof (Elf32_External_Rela);
+		      bfd_elf32_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 == ELF32_R_TYPE (rel->r_info))
+	    {
+	      relocation = htab->sgot->output_offset + off;
+	      if (r_type == R_390_TLS_IE32 || r_type == R_390_TLS_IEENT)
+		relocation += htab->sgot->output_section->vma;
+	      unresolved_reloc = FALSE;
+	    }
+	  else
+	    {
+	      bfd_put_32 (output_bfd, htab->sgot->output_offset + off,
+			  contents + rel->r_offset);
+	      continue;
+	    }
+	  break;
+
+	case R_390_TLS_GOTIE12:
+	case R_390_TLS_IEENT:
+	  if (h == NULL)
+	    {
+	      if (local_got_offsets == NULL)
+		abort();
+	      off = local_got_offsets[r_symndx];
+	      if (info->shared)
+		goto emit_tls_relocs;
+	    }
+	  else
+	    {
+	      off = h->got.offset;
+	      tls_type = elf_s390_hash_entry(h)->tls_type;
+	      if (info->shared || h->dynindx != -1 || tls_type < GOT_TLS_IE)
+		goto emit_tls_relocs;
+	    }
+
+	  if (htab->sgot == NULL)
+	    abort ();
+
+	  BFD_ASSERT (! unresolved_reloc);
+	  bfd_put_32 (output_bfd, -tpoff (info, relocation),
+		      htab->sgot->contents + off);
+	  relocation = htab->sgot->output_offset + off;
+	  if (r_type == R_390_TLS_IEENT)
+	    relocation += htab->sgot->output_section->vma;
+	  unresolved_reloc = FALSE;
+	  break;
+
+	case R_390_TLS_LDM32:
+	  if (! info->shared)
+	    /* The literal pool entry this relocation refers to gets ignored
+	       by the optimized code of the local exec model. Do nothing
+	       and the value will turn out zero.  */
+	    continue;
+
+	  if (htab->sgot == NULL)
+	    abort ();
+
+	  off = htab->tls_ldm_got.offset;
+	  if (off & 1)
+	    off &= ~1;
+	  else
+	    {
+	      Elf_Internal_Rela outrel;
+	      bfd_byte *loc;
+
+	      if (htab->srelgot == NULL)
+		abort ();
+
+	      outrel.r_offset = (htab->sgot->output_section->vma
+				 + htab->sgot->output_offset + off);
+
+	      bfd_put_32 (output_bfd, 0,
+			  htab->sgot->contents + off + GOT_ENTRY_SIZE);
+	      outrel.r_info = ELF32_R_INFO (0, R_390_TLS_DTPMOD);
+	      outrel.r_addend = 0;
+	      loc = htab->srelgot->contents;
+	      loc += htab->srelgot->reloc_count++
+		* sizeof (Elf32_External_Rela);
+	      bfd_elf32_swap_reloca_out (output_bfd, &outrel, loc);
+	      htab->tls_ldm_got.offset |= 1;
+	    }
+	  relocation = htab->sgot->output_offset + off;
+	  unresolved_reloc = FALSE;	  
+	  break;
+
+	case R_390_TLS_LE32:
+	  if (info->shared)
+	    {
+	      /* Linking a shared library with non-fpic code requires
+		 a R_390_TLS_TPOFF relocation.  */
+	      Elf_Internal_Rela outrel;
+	      asection *sreloc;
+	      bfd_byte *loc;
+	      int indx;
+
+	      outrel.r_offset = rel->r_offset
+				+ input_section->output_section->vma
+				+ input_section->output_offset;
+	      if (h != NULL && h->dynindx != -1)
+		indx = h->dynindx;
+	      else
+		indx = 0;
+	      outrel.r_info = ELF32_R_INFO (indx, R_390_TLS_TPOFF);
+	      if (indx == 0)
+		outrel.r_addend = relocation - dtpoff_base (info);
+	      else
+		outrel.r_addend = 0;
+	      sreloc = elf_section_data (input_section)->sreloc;
+	      if (sreloc == NULL)
+		abort ();
+	      loc = sreloc->contents;
+	      loc += sreloc->reloc_count++ * sizeof (Elf32_External_Rela);
+	      bfd_elf32_swap_reloca_out (output_bfd, &outrel, loc);
+	    }
+	  else
+	    {
+	      BFD_ASSERT (! unresolved_reloc);
+	      bfd_put_32 (output_bfd, -tpoff (info, relocation),
+			  contents + rel->r_offset);
+	    }
+	  continue;
+
+	case R_390_TLS_LDO32:
+	  if (info->shared || (input_section->flags & SEC_CODE) == 0)
+	    relocation -= dtpoff_base (info);
+	  else
+	    /* When converting LDO to LE, we must negate.  */
+	    relocation = -tpoff (info, relocation);
+	  break;
+
+	  /* Relocations for tls instructions.  */
+	case R_390_TLS_LOAD:
+	case R_390_TLS_GDCALL:
+	case R_390_TLS_LDCALL:
+	  tls_type = GOT_UNKNOWN;
+	  if (h == NULL && local_got_offsets)
+	    tls_type = elf_s390_local_got_tls_type (input_bfd) [r_symndx];
+	  else if (h != NULL)
+	    tls_type = elf_s390_hash_entry(h)->tls_type;
+
+	  if (tls_type == GOT_TLS_GD)
+	    continue;
+
+	  if (r_type == R_390_TLS_LOAD)
+	    {
+	      if (!info->shared && (h == NULL || h->dynindx == -1))
+		{
+		  /* IE->LE transition. Four valid cases:
+		     l %rx,0(0,%ry)    -> lr %rx,%ry + bcr 0,0
+		     l %rx,0(%ry,0)    -> lr %rx,%ry + bcr 0,0
+		     l %rx,0(%ry,%r12) -> lr %rx,%ry + bcr 0,0
+		     l %rx,0(%r12,%ry) -> lr %rx,%ry + bcr 0,0 */
+		  unsigned int insn, ry;
+
+		  insn = bfd_get_32 (input_bfd, contents + rel->r_offset);
+		  ry = 0;
+		  if ((insn & 0xff00f000) == 0x58000000)
+		    /* l %rx,0(%ry,0) -> lr %rx,%ry + bcr 0,0  */
+		    ry = (insn & 0x000f0000);
+		  else if ((insn & 0xff0f0000) == 0x58000000)
+		    /* l %rx,0(0,%ry) -> lr %rx,%ry + bcr 0,0  */
+		    ry = (insn & 0x0000f000) << 4;
+		  else if ((insn & 0xff00f000) == 0x5800c000)
+		    /* l %rx,0(%ry,%r12) -> lr %rx,%ry + bcr 0,0  */
+		    ry = (insn & 0x000f0000);
+		  else if ((insn & 0xff0f0000) == 0x580c0000)
+		    /* l %rx,0(%r12,%ry) -> lr %rx,%ry + bcr 0,0  */
+		    ry = (insn & 0x0000f000) << 4;
+		  else
+		    invalid_tls_insn (input_bfd, input_section, rel);
+		  insn = 0x18000700 | (insn & 0x00f00000) | ry;
+		  bfd_put_32 (output_bfd, insn, contents + rel->r_offset);
+		}
+	    }
+	  else if (r_type == R_390_TLS_GDCALL)
+	    {
+	      unsigned int insn;
+
+	      insn = bfd_get_32 (input_bfd, contents + rel->r_offset);
+	      if ((insn & 0xff000fff) != 0x4d000000)
+		invalid_tls_insn (input_bfd, input_section, rel);
+	      if (!info->shared && (h == NULL || h->dynindx == -1))
+		/* GD->LE transition.
+		   bas %r14,0(%rx,%r13) -> bc 0,0  */
+		insn = 0x47000000;
+	      else
+		/* GD->IE transition.
+		   bas %r14,0(%rx,%r13) -> l %r2,0(%r2,%r12)  */
+		insn = 0x5822c000;
+	      bfd_put_32 (output_bfd, insn, contents + rel->r_offset);
+	    }
+	  else if (r_type == R_390_TLS_LDCALL)
+	    {
+	      if (!info->shared)
+		{
+		  unsigned int insn;
+
+		  insn = bfd_get_32 (input_bfd, contents + rel->r_offset);
+		  if ((insn & 0xff000fff) != 0x4d000000)
+		    invalid_tls_insn (input_bfd, input_section, rel);
+		  /* LD->LE transition.
+		     bas %r14,0(%rx,%r13) -> bc 0,0  */
+		  insn = 0x47000000;
+		  bfd_put_32 (output_bfd, insn, contents + rel->r_offset);
+		}
+	    }
+	  continue;
+
 	default:
 	  break;
 	}
@@ -2399,7 +3111,10 @@
 	}
     }
 
-  if (h->got.offset != (bfd_vma) -1)
+  if (h->got.offset != (bfd_vma) -1
+      && elf_s390_hash_entry(h)->tls_type != GOT_TLS_GD
+      && elf_s390_hash_entry(h)->tls_type != GOT_TLS_IE
+      && elf_s390_hash_entry(h)->tls_type != GOT_TLS_IE_NLT)
     {
       Elf_Internal_Rela rela;
       bfd_byte *loc;
@@ -2616,13 +3331,6 @@
 }
 
 static bfd_boolean
-elf_s390_object_p (abfd)
-     bfd *abfd;
-{
-  return bfd_default_set_arch_mach (abfd, bfd_arch_s390, bfd_mach_s390_31);
-}
-
-static bfd_boolean
 elf_s390_grok_prstatus (abfd, note)
      bfd * abfd;
      Elf_Internal_Note * note;
@@ -2689,6 +3397,7 @@
 #define elf_backend_reloc_type_class	      elf_s390_reloc_type_class
 #define elf_backend_grok_prstatus	      elf_s390_grok_prstatus
 
+#define bfd_elf32_mkobject		elf_s390_mkobject
 #define elf_backend_object_p            elf_s390_object_p
 
 #include "elf32-target.h"
diff -urN src/bfd/elf64-s390.c src-s390/bfd/elf64-s390.c
--- src/bfd/elf64-s390.c	Mon Jan 20 12:38:30 2003
+++ src-s390/bfd/elf64-s390.c	Fri Jan 24 09:53:39 2003
@@ -72,8 +72,20 @@
   PARAMS ((const Elf_Internal_Rela *));
 static bfd_boolean elf_s390_finish_dynamic_sections
   PARAMS ((bfd *, struct bfd_link_info *));
+static bfd_boolean elf_s390_mkobject
+  PARAMS ((bfd *));
 static bfd_boolean elf_s390_object_p
   PARAMS ((bfd *));
+static int elf_s390_tls_transition
+  PARAMS ((struct bfd_link_info *, int, int));
+static bfd_reloc_status_type s390_tls_reloc
+  PARAMS ((bfd *, arelent *, asymbol *, PTR, asection *, bfd *, char **));
+static bfd_vma dtpoff_base
+  PARAMS ((struct bfd_link_info *));
+static bfd_vma tpoff
+  PARAMS ((struct bfd_link_info *, bfd_vma));
+static void invalid_tls_insn
+  PARAMS ((bfd *, asection *, Elf_Internal_Rela *));
 
 #include "elf/s390.h"
 
@@ -170,6 +182,40 @@
 	bfd_elf_generic_reloc, "R_390_PLTOFF32", FALSE, 0,0xffffffff, FALSE),
   HOWTO(R_390_PLTOFF64,  0, 4, 64, FALSE, 0, complain_overflow_bitfield,
 	bfd_elf_generic_reloc, "R_390_PLTOFF64", FALSE, 0,MINUS_ONE,  FALSE),
+  HOWTO(R_390_TLS_LOAD, 0, 0, 0, FALSE, 0, complain_overflow_dont,
+	s390_tls_reloc, "R_390_TLS_LOAD", FALSE, 0, 0, FALSE),
+  HOWTO(R_390_TLS_GDCALL, 0, 0, 0, FALSE, 0, complain_overflow_dont,
+	s390_tls_reloc, "R_390_TLS_GDCALL", FALSE, 0, 0, FALSE),
+  HOWTO(R_390_TLS_LDCALL, 0, 0, 0, FALSE, 0, complain_overflow_dont,
+	s390_tls_reloc, "R_390_TLS_LDCALL", FALSE, 0, 0, FALSE),
+  EMPTY_HOWTO (R_390_TLS_GD32),	/* Empty entry for R_390_TLS_GD32.  */
+  HOWTO(R_390_TLS_GD64,  0, 4, 64, FALSE, 0, complain_overflow_bitfield,
+	bfd_elf_generic_reloc, "R_390_TLS_GD64", FALSE, 0, MINUS_ONE, FALSE),
+  HOWTO(R_390_TLS_GOTIE12, 0, 1, 12, FALSE, 0, complain_overflow_dont,
+	bfd_elf_generic_reloc, "R_390_TLS_GOTIE12", FALSE, 0, 0x00000fff, FALSE),
+  EMPTY_HOWTO (R_390_TLS_GOTIE32),	/* Empty entry for R_390_TLS_GOTIE32.  */
+  HOWTO(R_390_TLS_GOTIE64, 0, 4, 64, FALSE, 0, complain_overflow_bitfield,
+	bfd_elf_generic_reloc, "R_390_TLS_GOTIE64", FALSE, 0, MINUS_ONE, FALSE),
+  EMPTY_HOWTO (R_390_TLS_LDM32),	/* Empty entry for R_390_TLS_LDM32.  */
+  HOWTO(R_390_TLS_LDM64, 0, 4, 64, FALSE, 0, complain_overflow_bitfield,
+	bfd_elf_generic_reloc, "R_390_TLS_LDM64", FALSE, 0, MINUS_ONE, FALSE),
+  EMPTY_HOWTO (R_390_TLS_IE32),	/* Empty entry for R_390_TLS_IE32.  */
+  HOWTO(R_390_TLS_IE64,  0, 4, 64, FALSE, 0, complain_overflow_bitfield,
+	bfd_elf_generic_reloc, "R_390_TLS_IE64", FALSE, 0, MINUS_ONE, FALSE),
+  HOWTO(R_390_TLS_IEENT, 1, 2, 32, TRUE, 0, complain_overflow_bitfield,
+	bfd_elf_generic_reloc, "R_390_TLS_IEENT", FALSE, 0, MINUS_ONE, TRUE),
+  EMPTY_HOWTO (R_390_TLS_LE32),	/* Empty entry for R_390_TLS_LE32.  */
+  HOWTO(R_390_TLS_LE64,  0, 2, 32, FALSE, 0, complain_overflow_bitfield,
+	bfd_elf_generic_reloc, "R_390_TLS_LE64", FALSE, 0, MINUS_ONE, FALSE),
+  EMPTY_HOWTO (R_390_TLS_LDO32),	/* Empty entry for R_390_TLS_LDO32.  */
+  HOWTO(R_390_TLS_LDO64, 0, 4, 64, FALSE, 0, complain_overflow_bitfield,
+	bfd_elf_generic_reloc, "R_390_TLS_LDO64", FALSE, 0, MINUS_ONE, FALSE),
+  HOWTO(R_390_TLS_DTPMOD, 0, 4, 64, FALSE, 0, complain_overflow_bitfield,
+	bfd_elf_generic_reloc, "R_390_TLS_DTPMOD", FALSE, 0, MINUS_ONE, FALSE),
+  HOWTO(R_390_TLS_DTPOFF, 0, 4, 64, FALSE, 0, complain_overflow_bitfield,
+	bfd_elf_generic_reloc, "R_390_TLS_DTPOFF", FALSE, 0, MINUS_ONE, FALSE),
+  HOWTO(R_390_TLS_TPOFF, 0, 4, 64, FALSE, 0, complain_overflow_bitfield,
+	bfd_elf_generic_reloc, "R_390_TLS_TPOFF", FALSE, 0, MINUS_ONE, FALSE),
 };
 
 /* GNU extension to record C++ vtable hierarchy.  */
@@ -261,6 +307,34 @@
       return &elf_howto_table[(int) R_390_PLTOFF32];
     case BFD_RELOC_390_PLTOFF64:
       return &elf_howto_table[(int) R_390_PLTOFF64];
+    case BFD_RELOC_390_TLS_LOAD:
+      return &elf_howto_table[(int) R_390_TLS_LOAD];
+    case BFD_RELOC_390_TLS_GDCALL:
+      return &elf_howto_table[(int) R_390_TLS_GDCALL];
+    case BFD_RELOC_390_TLS_LDCALL:
+      return &elf_howto_table[(int) R_390_TLS_LDCALL];
+    case BFD_RELOC_390_TLS_GD64:
+      return &elf_howto_table[(int) R_390_TLS_GD64];
+    case BFD_RELOC_390_TLS_GOTIE12:
+      return &elf_howto_table[(int) R_390_TLS_GOTIE12];
+    case BFD_RELOC_390_TLS_GOTIE64:
+      return &elf_howto_table[(int) R_390_TLS_GOTIE64];
+    case BFD_RELOC_390_TLS_LDM64:
+      return &elf_howto_table[(int) R_390_TLS_LDM64];
+    case BFD_RELOC_390_TLS_IE64:
+      return &elf_howto_table[(int) R_390_TLS_IE64];
+    case BFD_RELOC_390_TLS_IEENT:
+      return &elf_howto_table[(int) R_390_TLS_IEENT];
+    case BFD_RELOC_390_TLS_LE64:
+      return &elf_howto_table[(int) R_390_TLS_LE64];
+    case BFD_RELOC_390_TLS_LDO64:
+      return &elf_howto_table[(int) R_390_TLS_LDO64];
+    case BFD_RELOC_390_TLS_DTPMOD:
+      return &elf_howto_table[(int) R_390_TLS_DTPMOD];
+    case BFD_RELOC_390_TLS_DTPOFF:
+      return &elf_howto_table[(int) R_390_TLS_DTPOFF];
+    case BFD_RELOC_390_TLS_TPOFF:
+      return &elf_howto_table[(int) R_390_TLS_TPOFF];
     case BFD_RELOC_VTABLE_INHERIT:
       return &elf64_s390_vtinherit_howto;
     case BFD_RELOC_VTABLE_ENTRY:
@@ -296,6 +370,23 @@
     }
 }
 
+/* A relocation function which doesn't do anything.  */
+static bfd_reloc_status_type
+s390_tls_reloc (abfd, reloc_entry, symbol, data, input_section,
+                      output_bfd, error_message)
+     bfd *abfd ATTRIBUTE_UNUSED;
+     arelent *reloc_entry;
+     asymbol *symbol ATTRIBUTE_UNUSED;
+     PTR data ATTRIBUTE_UNUSED;
+     asection *input_section;
+     bfd *output_bfd;
+     char **error_message ATTRIBUTE_UNUSED;
+{
+  if (output_bfd)
+    reloc_entry->address += input_section->output_offset;
+  return bfd_reloc_ok;
+}
+
 static bfd_boolean
 elf_s390_is_local_label_name (abfd, name)
      bfd *abfd;
@@ -430,8 +521,59 @@
 
   /* Number of GOTPLT references for a function.  */
   bfd_signed_vma gotplt_refcount;
+
+#define GOT_UNKNOWN	0
+#define GOT_NORMAL	1
+#define GOT_TLS_GD	2
+#define GOT_TLS_IE	3
+#define GOT_TLS_IE_NLT	3
+  unsigned char tls_type;
 };
 
+#define elf_s390_hash_entry(ent) \
+  ((struct elf_s390_link_hash_entry *)(ent))
+
+struct elf_s390_obj_tdata
+{
+  struct elf_obj_tdata root;
+
+  /* tls_type for each local got entry.  */
+  char *local_got_tls_type;
+};
+
+#define elf_s390_tdata(abfd) \
+  ((struct elf_s390_obj_tdata *) (abfd)->tdata.any)
+
+#define elf_s390_local_got_tls_type(abfd) \
+  (elf_s390_tdata (abfd)->local_got_tls_type)
+
+static bfd_boolean
+elf_s390_mkobject (abfd)
+     bfd *abfd;
+{
+  bfd_size_type amt = sizeof (struct elf_s390_obj_tdata);
+  abfd->tdata.any = bfd_zalloc (abfd, amt);
+  if (abfd->tdata.any == NULL)
+    return FALSE;
+  return TRUE;
+}
+
+static bfd_boolean
+elf_s390_object_p (abfd)
+     bfd *abfd;
+{
+  /* Allocate our special target data.  */
+  struct elf_s390_obj_tdata *new_tdata;
+  bfd_size_type amt = sizeof (struct elf_s390_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 s390 elf32 file.  */
+  return bfd_default_set_arch_mach (abfd, bfd_arch_s390, bfd_mach_s390_64);
+}
+
 /* s390 ELF linker hash table.  */
 
 struct elf_s390_link_hash_table
@@ -447,6 +589,11 @@
   asection *sdynbss;
   asection *srelbss;
 
+  union {
+    bfd_signed_vma refcount;
+    bfd_vma offset;
+  } tls_ldm_got;
+
   /* Small local sym to section mapping cache.  */
   struct sym_sec_cache sym_sec;
 };
@@ -483,6 +630,7 @@
       eh = (struct elf_s390_link_hash_entry *) entry;
       eh->dyn_relocs = NULL;
       eh->gotplt_refcount = 0;
+      eh->tls_type = GOT_UNKNOWN;
     }
 
   return entry;
@@ -514,6 +662,7 @@
   ret->srelplt = NULL;
   ret->sdynbss = NULL;
   ret->srelbss = NULL;
+  ret->tls_ldm_got.refcount = 0;
   ret->sym_sec.abfd = NULL;
 
   return &ret->elf.root;
@@ -626,9 +775,43 @@
       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 int
+elf_s390_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_390_TLS_GD64:
+    case R_390_TLS_IE64:
+      if (is_local)
+	return R_390_TLS_LE64;
+      return R_390_TLS_IE64;
+    case R_390_TLS_GOTIE64:
+      if (is_local)
+	return R_390_TLS_LE64;
+      return R_390_TLS_GOTIE64;
+    case R_390_TLS_LDM64:
+      return R_390_TLS_LE64;
+    }
+
+  return r_type;
+}
+
 /* Look through the relocs for a section during the first phase, and
    allocate space in the global offset table or procedure linkage
    table.  */
@@ -647,6 +830,7 @@
   const Elf_Internal_Rela *rel_end;
   asection *sreloc;
   bfd_signed_vma *local_got_refcounts;
+  int tls_type, old_tls_type;
 
   if (info->relocateable)
     return TRUE;
@@ -661,6 +845,7 @@
   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;
 
@@ -681,7 +866,10 @@
 
       /* Create got section and local_got_refcounts array if they
 	 are needed.  */
-      switch (ELF64_R_TYPE (rel->r_info))
+      r_type = elf_s390_tls_transition (info,
+					ELF64_R_TYPE (rel->r_info),
+					h == NULL);
+      switch (r_type)
 	{
 	case R_390_GOT12:
 	case R_390_GOT16:
@@ -693,18 +881,26 @@
 	case R_390_GOTPLT32:
 	case R_390_GOTPLT64:
 	case R_390_GOTPLTENT:
+	case R_390_TLS_GD64:
+	case R_390_TLS_GOTIE12:
+	case R_390_TLS_GOTIE64:
+	case R_390_TLS_IEENT:
+	case R_390_TLS_IE64:
+	case R_390_TLS_LDM64:
 	  if (h == NULL
 	      && local_got_refcounts == NULL)
 	    {
 	      bfd_size_type size;
 
 	      size = symtab_hdr->sh_info;
-	      size *= sizeof (bfd_signed_vma);
+	      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;
+	      elf_s390_local_got_tls_type (abfd)
+		= (char *) (local_got_refcounts + symtab_hdr->sh_info);
 	    }
 	  /* Fall through.  */
 	case R_390_GOTOFF16:
@@ -721,24 +917,8 @@
 	    }
 	}
 
-      switch (ELF64_R_TYPE (rel->r_info))
+      switch (r_type)
 	{
-	case R_390_GOT12:
-        case R_390_GOT16:
-	case R_390_GOT32:
-	case R_390_GOT64:
-	case R_390_GOTENT:
-	  /* This symbol requires a global offset table entry.  */
-	  if (h != NULL)
-	    {
-	      h->got.refcount += 1;
-	    }
-	  else
-	    {
-	      local_got_refcounts[r_symndx] += 1;
-	    }
-	  /* Fall through */
-
 	case R_390_GOTOFF16:
 	case R_390_GOTOFF32:
 	case R_390_GOTOFF64:
@@ -790,10 +970,92 @@
 	      h->plt.refcount += 1;
 	    }
 	  else
+	    local_got_refcounts[r_symndx] += 1;
+	  break;
+
+	case R_390_TLS_LDM64:
+	  htab->tls_ldm_got.refcount += 1;
+	  break;
+
+	case R_390_TLS_IE64:
+	case R_390_TLS_GOTIE12:
+	case R_390_TLS_GOTIE64:
+	case R_390_TLS_IEENT:
+	  if (info->shared)
+	    info->flags |= DF_STATIC_TLS;
+	  /* Fall through */
+
+	case R_390_GOT12:
+        case R_390_GOT16:
+	case R_390_GOT32:
+	case R_390_GOT64:
+	case R_390_GOTENT:
+	case R_390_TLS_GD64:
+	  /* This symbol requires a global offset table entry.  */
+	  switch (r_type)
+	    {
+	    default:
+	    case R_390_GOT12:
+	    case R_390_GOT16:
+	    case R_390_GOT32:
+	    case R_390_GOTENT:
+	      tls_type = GOT_NORMAL;
+	      break;
+	    case R_390_TLS_GD64:
+	      tls_type = GOT_TLS_GD;
+	      break;
+	    case R_390_TLS_IE64:
+	    case R_390_TLS_GOTIE64:
+	      tls_type = GOT_TLS_IE;
+	      break;
+	    case R_390_TLS_GOTIE12:
+	    case R_390_TLS_IEENT:
+	      tls_type = GOT_TLS_IE_NLT;
+	      break;
+	    }
+
+	  if (h != NULL)
+	    {
+	      h->got.refcount += 1;
+	      old_tls_type = elf_s390_hash_entry(h)->tls_type;
+	    }
+	  else
 	    {
 	      local_got_refcounts[r_symndx] += 1;
+	      old_tls_type = elf_s390_local_got_tls_type (abfd) [r_symndx];
 	    }
-	  break;
+	  /* 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)
+	    {
+	      if (old_tls_type == GOT_NORMAL || tls_type == GOT_NORMAL)
+		{
+		  (*_bfd_error_handler)
+		    (_("%s: `%s' accessed both as normal and thread local symbol"),
+		     bfd_archive_filename (abfd), h->root.root.string);
+		  return FALSE;
+		}
+	      if (old_tls_type > tls_type)
+		tls_type = old_tls_type;
+	    }
+
+	  if (old_tls_type != tls_type)
+	    {
+	      if (h != NULL)
+		elf_s390_hash_entry (h)->tls_type = tls_type;
+	      else
+		elf_s390_local_got_tls_type (abfd) [r_symndx] = tls_type;
+	    }
+
+	  if (r_type != R_390_TLS_IE64)
+	    break;
+	  /* Fall through */
+
+	case R_390_TLS_LE64:
+	  if (!info->shared)
+	    break;
+	  info->flags |= DF_STATIC_TLS;
+	  /* Fall through */
 
 	case R_390_8:
 	case R_390_16:
@@ -1031,6 +1293,7 @@
   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;
@@ -1049,8 +1312,21 @@
       else
 	h = sym_hashes[r_symndx - symtab_hdr->sh_info];
 
-      switch (ELF64_R_TYPE (rel->r_info))
+      r_type = elf_s390_tls_transition (info,
+					ELF64_R_TYPE (rel->r_info),
+					r_symndx >= symtab_hdr->sh_info);
+      switch (r_type)
 	{
+	case R_390_TLS_LDM64:
+	  if (elf_s390_hash_table (info)->tls_ldm_got.refcount > 0)
+	    elf_s390_hash_table (info)->tls_ldm_got.refcount -= 1;
+	  break;
+
+	case R_390_TLS_GD64:
+	case R_390_TLS_IE64:
+	case R_390_TLS_GOTIE12:
+	case R_390_TLS_GOTIE64:
+	case R_390_TLS_IEENT:
 	case R_390_GOT12:
 	case R_390_GOT16:
 	case R_390_GOT32:
@@ -1071,41 +1347,14 @@
 	      if (local_got_refcounts[r_symndx] > 0)
 		local_got_refcounts[r_symndx] -= 1;
 	    }
-	  break;
+	  if (r_type != R_390_TLS_IE64)
+	    break;
+	  /* Fall through */
 	  
-	case R_390_PLT16DBL:
-	case R_390_PLT32:
-	case R_390_PLT32DBL:
-	case R_390_PLT64:
-	case R_390_PLTOFF16:
-	case R_390_PLTOFF32:
-	case R_390_PLTOFF64:
-	  if (h != NULL)
-	    {
-	      if (h->plt.refcount > 0)
-		h->plt.refcount -= 1;
-	    }
-	  break;
-
-	case R_390_GOTPLT12:
-	case R_390_GOTPLT16:
-	case R_390_GOTPLT32:
-	case R_390_GOTPLT64:
-	case R_390_GOTPLTENT:
-	  if (h != NULL)
-	    {
-	      if (h->plt.refcount > 0)
-		{
-		  ((struct elf_s390_link_hash_entry *) h)->gotplt_refcount--;
-		  h->plt.refcount -= 1;
-		}
-	    }
-	  else if (local_got_refcounts != NULL)
-	    {
-	      if (local_got_refcounts[r_symndx] > 0)
-		local_got_refcounts[r_symndx] -= 1;
-	    }
-	  break;
+	case R_390_TLS_LE64:
+	  if (!info->shared)
+	    break;
+	  /* Fall through */
 
 	case R_390_8:
 	case R_390_12:
@@ -1145,6 +1394,40 @@
 	    }
 	  break;
 
+	case R_390_PLT16DBL:
+	case R_390_PLT32:
+	case R_390_PLT32DBL:
+	case R_390_PLT64:
+	case R_390_PLTOFF16:
+	case R_390_PLTOFF32:
+	case R_390_PLTOFF64:
+	  if (h != NULL)
+	    {
+	      if (h->plt.refcount > 0)
+		h->plt.refcount -= 1;
+	    }
+	  break;
+
+	case R_390_GOTPLT12:
+	case R_390_GOTPLT16:
+	case R_390_GOTPLT32:
+	case R_390_GOTPLT64:
+	case R_390_GOTPLTENT:
+	  if (h != NULL)
+	    {
+	      if (h->plt.refcount > 0)
+		{
+		  ((struct elf_s390_link_hash_entry *) h)->gotplt_refcount--;
+		  h->plt.refcount -= 1;
+		}
+	    }
+	  else if (local_got_refcounts != NULL)
+	    {
+	      if (local_got_refcounts[r_symndx] > 0)
+		local_got_refcounts[r_symndx] -= 1;
+	    }
+	  break;
+
 	default:
 	  break;
 	}
@@ -1417,10 +1700,31 @@
       elf_s390_adjust_gotplt((struct elf_s390_link_hash_entry *) h);
     }
 
-  if (h->got.refcount > 0)
+  /* If R_390_TLS_{IE64,GOTIE64,GOTIE12,IEENT} symbol is now local to
+     the binary, we can optimize a bit. IE64 and GOTIE64 get converted
+     to R_390_TLS_LE64 requiring no TLS entry. For GOTIE12 and IEENT
+     we can save the dynamic TLS relocation.  */
+  if (h->got.refcount > 0
+      && !info->shared
+      && h->dynindx == -1
+      && elf_s390_hash_entry(h)->tls_type >= GOT_TLS_IE)
+    {
+      if (elf_s390_hash_entry(h)->tls_type == GOT_TLS_IE_NLT)
+	/* For the GOTIE access without a literal pool entry the offset has
+	   to be stored somewhere. The immediate value in the instruction
+	   is not bit enough so the value is stored in the got.  */
+	{
+	  h->got.offset = htab->sgot->_raw_size;
+	  htab->sgot->_raw_size += GOT_ENTRY_SIZE;
+	}
+      else
+	h->got.offset = (bfd_vma) -1;
+    }
+  else if (h->got.refcount > 0)
     {
       asection *s;
       bfd_boolean dyn;
+      int tls_type = elf_s390_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.  */
@@ -1434,8 +1738,18 @@
       s = htab->sgot;
       h->got.offset = s->_raw_size;
       s->_raw_size += GOT_ENTRY_SIZE;
+      /* R_390_TLS_GD64 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_390_TLS_IE64 needs one dynamic relocation,
+	 R_390_TLS_GD64 needs one if local symbol and two if global.  */
+      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
@@ -1581,6 +1895,7 @@
     {
       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 *srela;
@@ -1622,14 +1937,17 @@
       symtab_hdr = &elf_tdata (ibfd)->symtab_hdr;
       locsymcount = symtab_hdr->sh_info;
       end_local_got = local_got + locsymcount;
+      local_tls_type = elf_s390_local_got_tls_type (ibfd);
       s = htab->sgot;
       srela = 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 (*local_tls_type == GOT_TLS_GD)
+		s->_raw_size += GOT_ENTRY_SIZE;
 	      if (info->shared)
 		srela->_raw_size += sizeof (Elf64_External_Rela);
 	    }
@@ -1638,6 +1956,17 @@
 	}
     }
 
+  if (htab->tls_ldm_got.refcount > 0)
+    {
+      /* Allocate 2 got entries and 1 dynamic reloc for R_390_TLS_LDM64
+	 relocs.  */
+      htab->tls_ldm_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_ldm_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);
@@ -1748,6 +2077,58 @@
   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 (align_power (tls_segment->size, tls_segment->align)
+	  + tls_segment->start - address);
+}
+
+/* Complain if TLS instruction relocation is against an invalid
+   instruction.  */
+
+static void
+invalid_tls_insn (input_bfd, input_section, rel)
+     bfd *input_bfd;
+     asection *input_section;
+     Elf_Internal_Rela *rel;
+{
+  reloc_howto_type *howto;
+
+  howto = elf_howto_table + ELF64_R_TYPE (rel->r_info);
+  (*_bfd_error_handler)
+    (_("%s(%s+0x%lx): invalid instruction for TLS relocation %s"),
+     bfd_archive_filename (input_bfd),
+     bfd_get_section_name (input_bfd, input_section),
+     (long) rel->r_offset,
+     howto->name);
+}
+
 /* Relocate a 390 ELF section.  */
 
 static bfd_boolean
@@ -1791,6 +2172,7 @@
       bfd_vma relocation;
       bfd_boolean unresolved_reloc;
       bfd_reloc_status_type r;
+      int tls_type;
 
       r_type = ELF64_R_TYPE (rel->r_info);
       if (r_type == (int) R_390_GNU_VTINHERIT
@@ -2176,6 +2558,346 @@
 
 	  break;
 
+	  /* Relocations for tls literal pool entries.  */
+	case R_390_TLS_IE64:
+	  if (info->shared)
+	    {
+	      Elf_Internal_Rela outrel;
+	      asection *sreloc;
+	      bfd_byte *loc;
+
+	      outrel.r_offset = rel->r_offset
+				+ input_section->output_section->vma
+				+ input_section->output_offset;
+	      outrel.r_info = ELF64_R_INFO (0, R_390_RELATIVE);
+	      sreloc = elf_section_data (input_section)->sreloc;
+	      if (sreloc == NULL)
+		abort ();
+	      loc = sreloc->contents;
+	      loc += sreloc->reloc_count++ * sizeof (Elf64_External_Rela);
+	      bfd_elf64_swap_reloc_out (output_bfd, &outrel, loc);
+	    }
+	  /* Fall through */
+
+	case R_390_TLS_GD64:
+	case R_390_TLS_GOTIE64:
+	  r_type = elf_s390_tls_transition (info, r_type, h == NULL);
+	  tls_type = GOT_UNKNOWN;
+	  if (h == NULL && local_got_offsets)
+	    tls_type = elf_s390_local_got_tls_type (input_bfd) [r_symndx];
+	  else if (h != NULL)
+	    {
+	      tls_type = elf_s390_hash_entry(h)->tls_type;
+	      if (!info->shared && h->dynindx == -1 && tls_type >= GOT_TLS_IE)
+		r_type = R_390_TLS_LE64;
+	    }
+	  if (r_type == R_390_TLS_GD64 && tls_type >= GOT_TLS_IE)
+	    r_type = R_390_TLS_IE64;
+
+	  if (r_type == R_390_TLS_LE64)
+	    {
+	      /* This relocation gets optimized away by the local exec
+		 access optimization.  */
+	      BFD_ASSERT (! unresolved_reloc);
+	      bfd_put_64 (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];
+	    }
+
+	emit_tls_relocs:
+
+	  if ((off & 1) != 0)
+	    off &= ~1;
+          else
+	    {
+	      Elf_Internal_Rela outrel;
+	      bfd_byte *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_390_TLS_GD64)
+		dr_type = R_390_TLS_DTPMOD;
+	      else
+		dr_type = R_390_TLS_TPOFF;
+	      if (dr_type == R_390_TLS_TPOFF && indx == 0)
+		outrel.r_addend = relocation - dtpoff_base (info);
+	      else
+		outrel.r_addend = 0;
+	      outrel.r_info = ELF64_R_INFO (indx, dr_type);
+	      loc = htab->srelgot->contents;
+	      loc += htab->srelgot->reloc_count++
+		* sizeof (Elf64_External_Rela);
+	      bfd_elf64_swap_reloca_out (output_bfd, &outrel, loc);
+
+	      if (r_type == R_390_TLS_GD64)
+		{
+		  if (indx == 0)
+		    {
+	    	      BFD_ASSERT (! unresolved_reloc);
+		      bfd_put_64 (output_bfd,
+				  relocation - dtpoff_base (info),
+				  htab->sgot->contents + off + GOT_ENTRY_SIZE);
+		    }
+		  else
+		    {
+		      outrel.r_info = ELF64_R_INFO (indx, R_390_TLS_DTPOFF);
+		      outrel.r_offset += GOT_ENTRY_SIZE;
+		      outrel.r_addend = 0;
+		      htab->srelgot->reloc_count++;
+		      loc += sizeof (Elf64_External_Rela);
+		      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_offset + off;
+	      if (r_type == R_390_TLS_IE64 || r_type == R_390_TLS_IEENT)
+		relocation += htab->sgot->output_section->vma;
+	      unresolved_reloc = FALSE;
+	    }
+	  else
+	    {
+	      bfd_put_64 (output_bfd, htab->sgot->output_offset + off,
+			  contents + rel->r_offset);
+	      continue;
+	    }
+	  break;
+
+	case R_390_TLS_GOTIE12:
+	case R_390_TLS_IEENT:
+	  if (h == NULL)
+	    {
+	      if (local_got_offsets == NULL)
+		abort();
+	      off = local_got_offsets[r_symndx];
+	      if (info->shared)
+		goto emit_tls_relocs;
+	    }
+	  else
+	    {
+	      off = h->got.offset;
+	      tls_type = elf_s390_hash_entry(h)->tls_type;
+	      if (info->shared || h->dynindx != -1 || tls_type < GOT_TLS_IE)
+		goto emit_tls_relocs;
+	    }
+
+	  if (htab->sgot == NULL)
+	    abort ();
+
+	  BFD_ASSERT (! unresolved_reloc);
+	  bfd_put_64 (output_bfd, -tpoff (info, relocation),
+		      htab->sgot->contents + off);
+	  relocation = htab->sgot->output_offset + off;
+	  if (r_type == R_390_TLS_IEENT)
+	    relocation += htab->sgot->output_section->vma;
+	  unresolved_reloc = FALSE;
+	  break;
+
+	case R_390_TLS_LDM64:
+	  if (! info->shared)
+	    /* The literal pool entry this relocation refers to gets ignored
+	       by the optimized code of the local exec model. Do nothing
+	       and the value will turn out zero.  */
+	    continue;
+
+	  if (htab->sgot == NULL)
+	    abort ();
+
+	  off = htab->tls_ldm_got.offset;
+	  if (off & 1)
+	    off &= ~1;
+	  else
+	    {
+	      Elf_Internal_Rela outrel;
+	      bfd_byte *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 + GOT_ENTRY_SIZE);
+	      outrel.r_info = ELF64_R_INFO (0, R_390_TLS_DTPMOD);
+	      outrel.r_addend = 0;
+	      loc = htab->srelgot->contents;
+	      loc += htab->srelgot->reloc_count++
+		* sizeof (Elf64_External_Rela);
+	      bfd_elf64_swap_reloca_out (output_bfd, &outrel, loc);
+	      htab->tls_ldm_got.offset |= 1;
+	    }
+	  relocation = htab->sgot->output_offset + off;
+	  unresolved_reloc = FALSE;	  
+	  break;
+
+	case R_390_TLS_LE64:
+	  if (info->shared)
+	    {
+	      /* Linking a shared library with non-fpic code requires
+		 a R_390_TLS_TPOFF relocation.  */
+	      Elf_Internal_Rela outrel;
+	      asection *sreloc;
+	      bfd_byte *loc;
+	      int indx;
+
+	      outrel.r_offset = rel->r_offset
+				+ input_section->output_section->vma
+				+ input_section->output_offset;
+	      if (h != NULL && h->dynindx != -1)
+		indx = h->dynindx;
+	      else
+		indx = 0;
+	      outrel.r_info = ELF64_R_INFO (indx, R_390_TLS_TPOFF);
+	      if (indx == 0)
+		outrel.r_addend = relocation - dtpoff_base (info);
+	      else
+		outrel.r_addend = 0;
+	      sreloc = elf_section_data (input_section)->sreloc;
+	      if (sreloc == NULL)
+		abort ();
+	      loc = sreloc->contents;
+	      loc += sreloc->reloc_count++ * sizeof (Elf64_External_Rela);
+	      bfd_elf64_swap_reloca_out (output_bfd, &outrel, loc);
+	    }
+	  else
+	    {
+	      BFD_ASSERT (! unresolved_reloc);
+	      bfd_put_64 (output_bfd, -tpoff (info, relocation),
+			  contents + rel->r_offset);
+	    }
+	  continue;
+
+	case R_390_TLS_LDO64:
+	  if (info->shared || (input_section->flags & SEC_CODE) == 0)
+	    relocation -= dtpoff_base (info);
+	  else
+	    /* When converting LDO to LE, we must negate.  */
+	    relocation = -tpoff (info, relocation);
+	  break;
+
+	  /* Relocations for tls instructions.  */
+	case R_390_TLS_LOAD:
+	case R_390_TLS_GDCALL:
+	case R_390_TLS_LDCALL:
+	  tls_type = GOT_UNKNOWN;
+	  if (h == NULL && local_got_offsets)
+	    tls_type = elf_s390_local_got_tls_type (input_bfd) [r_symndx];
+	  else if (h != NULL)
+	    tls_type = elf_s390_hash_entry(h)->tls_type;
+
+	  if (tls_type == GOT_TLS_GD)
+	    continue;
+
+	  if (r_type == R_390_TLS_LOAD)
+	    {
+	      if (!info->shared && (h == NULL || h->dynindx == -1))
+		{
+		  /* IE->LE transition. Four valid cases:
+		     lg %rx,(0,%ry)    -> sllg %rx,%ry,0
+		     lg %rx,(%ry,0)    -> sllg %rx,%ry,0
+		     lg %rx,(%ry,%r12) -> sllg %rx,%ry,0
+		     lg %rx,(%r12,%ry) -> sllg %rx,%ry,0  */
+		  unsigned int insn0, insn1, ry;
+
+		  insn0 = bfd_get_32 (input_bfd, contents + rel->r_offset);
+		  insn1 = bfd_get_16 (input_bfd, contents + rel->r_offset + 4);
+		  if (insn1 != 0x0004)
+		    invalid_tls_insn (input_bfd, input_section, rel);
+		  ry = 0;
+		  if ((insn0 & 0xff00f000) == 0xe3000000)
+		    /* lg %rx,0(%ry,0) -> sllg %rx,%ry,0  */
+		    ry = (insn0 & 0x000f0000);
+		  else if ((insn0 & 0xff0f0000) == 0xe3000000)
+		    /* lg %rx,0(0,%ry) -> sllg %rx,%ry,0  */
+		    ry = (insn0 & 0x0000f000) << 4;
+		  else if ((insn0 & 0xff00f000) == 0xe300c000)
+		    /* lg %rx,0(%ry,%r12) -> sllg %rx,%ry,0  */
+		    ry = (insn0 & 0x000f0000);
+		  else if ((insn0 & 0xff0f0000) == 0xe30c0000)
+		    /* lg %rx,0(%r12,%ry) -> sllg %rx,%ry,0  */
+		    ry = (insn0 & 0x0000f000) << 4;
+		  else
+		    invalid_tls_insn (input_bfd, input_section, rel);
+		  insn0 = 0xeb000000 | (insn0 & 0x00f00000) | ry;
+		  insn1 = 0x000d;
+		  bfd_put_32 (output_bfd, insn0, contents + rel->r_offset);
+		  bfd_put_16 (output_bfd, insn1, contents + rel->r_offset + 4);
+		}
+	    }
+	  else if (r_type == R_390_TLS_GDCALL)
+	    {
+	      unsigned int insn0, insn1;
+
+	      insn0 = bfd_get_32 (input_bfd, contents + rel->r_offset);
+	      insn1 = bfd_get_16 (input_bfd, contents + rel->r_offset + 4);
+	      if ((insn0 & 0xffff0000) != 0xc0e50000)
+		invalid_tls_insn (input_bfd, input_section, rel);
+	      if (!info->shared && (h == NULL || h->dynindx == -1))
+		{
+		  /* GD->LE transition.
+		     brasl %r14,__tls_get_addr@plt -> brcl 0,. */
+		  insn0 = 0xc0040000;
+		  insn1 = 0x0000;
+		}
+	      else
+		{
+		  /* GD->IE transition.
+		     brasl %r14,__tls_get_addr@plt -> lg %r2,0(%r2,%r12)  */
+		  insn0 = 0xe322c000;
+		  insn1 = 0x0004;
+		}
+	      bfd_put_32 (output_bfd, insn0, contents + rel->r_offset);
+	      bfd_put_16 (output_bfd, insn1, contents + rel->r_offset + 4);
+	    }
+	  else if (r_type == R_390_TLS_LDCALL)
+	    {
+	      if (!info->shared)
+		{
+		  unsigned int insn0, insn1;
+
+		  insn0 = bfd_get_32 (input_bfd, contents + rel->r_offset);
+		  insn1 = bfd_get_16 (input_bfd, contents + rel->r_offset + 4);
+		  if ((insn0 & 0xffff0000) != 0xc0e50000)
+		    invalid_tls_insn (input_bfd, input_section, rel);
+		  /* LD->LE transition.
+		     brasl %r14,__tls_get_addr@plt -> brcl 0,. */
+		  insn0 = 0xc0040000;
+		  insn1 = 0x0000;
+		  bfd_put_32 (output_bfd, insn0, contents + rel->r_offset);
+		  bfd_put_16 (output_bfd, insn1, contents + rel->r_offset + 4);
+		}
+	    }
+	  continue;
+
 	default:
 	  break;
 	}
@@ -2335,7 +3057,10 @@
 	}
     }
 
-  if (h->got.offset != (bfd_vma) -1)
+  if (h->got.offset != (bfd_vma) -1
+      && elf_s390_hash_entry(h)->tls_type != GOT_TLS_GD
+      && elf_s390_hash_entry(h)->tls_type != GOT_TLS_IE
+      && elf_s390_hash_entry(h)->tls_type != GOT_TLS_IE_NLT)
     {
       Elf_Internal_Rela rela;
       bfd_byte *loc;
@@ -2553,13 +3278,6 @@
   return TRUE;
 }
 
-static bfd_boolean
-elf_s390_object_p (abfd)
-     bfd *abfd;
-{
-  return bfd_default_set_arch_mach (abfd, bfd_arch_s390, bfd_mach_s390_64);
-}
-
 /*
  * Why was the hash table entry size definition changed from
  * ARCH_SIZE/8 to 4? This breaks the 64 bit dynamic linker and
@@ -2633,6 +3351,7 @@
 #define elf_backend_size_dynamic_sections     elf_s390_size_dynamic_sections
 #define elf_backend_reloc_type_class	      elf_s390_reloc_type_class
 
-#define elf_backend_object_p		      elf_s390_object_p
+#define bfd_elf64_mkobject		elf_s390_mkobject
+#define elf_backend_object_p		elf_s390_object_p
 
 #include "elf64-target.h"
diff -urN src/bfd/libbfd.h src-s390/bfd/libbfd.h
--- src/bfd/libbfd.h	Mon Jan 20 12:38:30 2003
+++ src-s390/bfd/libbfd.h	Thu Jan 23 23:23:13 2003
@@ -1217,6 +1217,26 @@
   "BFD_RELOC_390_PLTOFF16",
   "BFD_RELOC_390_PLTOFF32",
   "BFD_RELOC_390_PLTOFF64",
+  "BFD_RELOC_390_TLS_LOAD",
+  "BFD_RELOC_390_TLS_GDCALL",
+  "BFD_RELOC_390_TLS_LDCALL",
+  "BFD_RELOC_390_TLS_GD32",
+  "BFD_RELOC_390_TLS_GD64",
+  "BFD_RELOC_390_TLS_GOTIE12",
+  "BFD_RELOC_390_TLS_GOTIE32",
+  "BFD_RELOC_390_TLS_GOTIE64",
+  "BFD_RELOC_390_TLS_LDM32",
+  "BFD_RELOC_390_TLS_LDM64",
+  "BFD_RELOC_390_TLS_IE32",
+  "BFD_RELOC_390_TLS_IE64",
+  "BFD_RELOC_390_TLS_IEENT",
+  "BFD_RELOC_390_TLS_LE32",
+  "BFD_RELOC_390_TLS_LE64",
+  "BFD_RELOC_390_TLS_LDO32",
+  "BFD_RELOC_390_TLS_LDO64",
+  "BFD_RELOC_390_TLS_DTPMOD",
+  "BFD_RELOC_390_TLS_DTPOFF",
+  "BFD_RELOC_390_TLS_TPOFF",
   "BFD_RELOC_IP2K_FR9",
   "BFD_RELOC_IP2K_BANK",
   "BFD_RELOC_IP2K_ADDR16CJP",
diff -urN src/bfd/reloc.c src-s390/bfd/reloc.c
--- src/bfd/reloc.c	Mon Jan 20 12:38:30 2003
+++ src-s390/bfd/reloc.c	Thu Jan 23 23:23:13 2003
@@ -3207,6 +3207,49 @@
   64-bit rel. offset from the GOT to a PLT entry.
 
 ENUM
+  BFD_RELOC_390_TLS_LOAD
+ENUMX
+  BFD_RELOC_390_TLS_GDCALL
+ENUMX
+  BFD_RELOC_390_TLS_LDCALL
+ENUMX
+  BFD_RELOC_390_TLS_GD32
+ENUMX
+  BFD_RELOC_390_TLS_GD64
+ENUMX
+  BFD_RELOC_390_TLS_GOTIE12
+ENUMX
+  BFD_RELOC_390_TLS_GOTIE32
+ENUMX
+  BFD_RELOC_390_TLS_GOTIE64
+ENUMX
+  BFD_RELOC_390_TLS_LDM32
+ENUMX
+  BFD_RELOC_390_TLS_LDM64
+ENUMX
+  BFD_RELOC_390_TLS_IE32
+ENUMX
+  BFD_RELOC_390_TLS_IE64
+ENUMX
+  BFD_RELOC_390_TLS_IEENT
+ENUMX
+  BFD_RELOC_390_TLS_LE32
+ENUMX
+  BFD_RELOC_390_TLS_LE64
+ENUMX
+  BFD_RELOC_390_TLS_LDO32
+ENUMX
+  BFD_RELOC_390_TLS_LDO64
+ENUMX
+  BFD_RELOC_390_TLS_DTPMOD
+ENUMX
+  BFD_RELOC_390_TLS_DTPOFF
+ENUMX
+  BFD_RELOC_390_TLS_TPOFF
+ENUMDOC
+  s390 tls relocations.
+
+ENUM
   BFD_RELOC_IP2K_FR9
 ENUMDOC
   Scenix IP2K - 9-bit register number / data address
diff -urN src/gas/config/tc-s390.c src-s390/gas/config/tc-s390.c
--- src/gas/config/tc-s390.c	Thu Jan 23 17:05:20 2003
+++ src-s390/gas/config/tc-s390.c	Thu Jan 23 23:23:13 2003
@@ -600,6 +600,67 @@
     }
 }
 
+struct map_tls
+  {
+    char *string;
+    int length;
+    bfd_reloc_code_real_type reloc;
+  };
+
+static bfd_reloc_code_real_type s390_tls_suffix
+  PARAMS ((char **, expressionS *));
+
+/* Parse tls marker and return the desired relocation.  */
+static bfd_reloc_code_real_type
+s390_tls_suffix (str_p, exp_p)
+     char **str_p;
+     expressionS *exp_p;
+{
+  static struct map_tls mapping[] =
+  {
+    { "tls_load", 8, BFD_RELOC_390_TLS_LOAD },
+    { "tls_gdcall", 10, BFD_RELOC_390_TLS_GDCALL  },
+    { "tls_ldcall", 10, BFD_RELOC_390_TLS_LDCALL  },
+    { NULL,  0, BFD_RELOC_UNUSED }
+  };
+  struct map_tls *ptr;
+  char *orig_line;
+  char *str;
+  char *ident;
+  int len;
+
+  str = *str_p;
+  if (*str++ != ':')
+    return BFD_RELOC_UNUSED;
+
+  ident = str;
+  while (ISIDNUM (*str))
+    str++;
+  len = str - ident;
+  if (*str++ != ':')
+    return BFD_RELOC_UNUSED;
+
+  orig_line = input_line_pointer;
+  input_line_pointer = str;
+  expression (exp_p);
+  str = input_line_pointer;
+  if (&input_line_pointer != str_p)
+    input_line_pointer = orig_line;
+
+  if (exp_p->X_op != O_symbol)
+    return BFD_RELOC_UNUSED;
+
+  for (ptr = &mapping[0]; ptr->length > 0; ptr++)
+    if (len == ptr->length
+	&& strncasecmp (ident, ptr->string, ptr->length) == 0)
+      {
+	/* Found a matching tls suffix.  */
+	*str_p = str;
+	return ptr->reloc;
+      }
+  return BFD_RELOC_UNUSED;
+}
+
 /* Structure used to hold suffixes.  */
 typedef enum
   {
@@ -609,7 +670,13 @@
     ELF_SUFFIX_GOTENT,
     ELF_SUFFIX_GOTOFF,
     ELF_SUFFIX_GOTPLT,
-    ELF_SUFFIX_PLTOFF
+    ELF_SUFFIX_PLTOFF,
+    ELF_SUFFIX_TLS_GD,
+    ELF_SUFFIX_TLS_GOTIE,
+    ELF_SUFFIX_TLS_IE,
+    ELF_SUFFIX_TLS_LDM,
+    ELF_SUFFIX_TLS_LDO,
+    ELF_SUFFIX_TLS_LE
   }
 elf_suffix_type;
 
@@ -641,6 +708,12 @@
     { "gotoff", 6, ELF_SUFFIX_GOTOFF },
     { "gotplt", 6, ELF_SUFFIX_GOTPLT },
     { "pltoff", 6, ELF_SUFFIX_PLTOFF },
+    { "tlsgd", 5, ELF_SUFFIX_TLS_GD },
+    { "gotntpoff", 9, ELF_SUFFIX_TLS_GOTIE },
+    { "indntpoff", 9, ELF_SUFFIX_TLS_IE },
+    { "tlsldm", 6, ELF_SUFFIX_TLS_LDM },
+    { "dtpoff", 6, ELF_SUFFIX_TLS_LDO },
+    { "ntpoff", 6, ELF_SUFFIX_TLS_LE },
     { NULL,  0, ELF_SUFFIX_NONE }
   };
 
@@ -956,38 +1029,72 @@
 	  int size;
 	  char *where;
 
-	  if (nbytes == 2 && suffix == ELF_SUFFIX_GOT)
-	    reloc = BFD_RELOC_390_GOT16;
-	  else if (nbytes == 4 && suffix == ELF_SUFFIX_GOT)
-	    reloc = BFD_RELOC_32_GOT_PCREL;
-	  else if (nbytes == 8 && suffix == ELF_SUFFIX_GOT)
-	    reloc = BFD_RELOC_390_GOT64;
-	  else if (nbytes == 2 && suffix == ELF_SUFFIX_GOTOFF)
-	    reloc = BFD_RELOC_16_GOTOFF;
-	  else if (nbytes == 4 && suffix == ELF_SUFFIX_GOTOFF)
-	    reloc = BFD_RELOC_32_GOTOFF;
-	  else if (nbytes == 8 && suffix == ELF_SUFFIX_GOTOFF)
-	    reloc = BFD_RELOC_390_GOTOFF64;
-	  else if (nbytes == 2 && suffix == ELF_SUFFIX_PLTOFF)
-	    reloc = BFD_RELOC_390_PLTOFF16;
-	  else if (nbytes == 4 && suffix == ELF_SUFFIX_PLTOFF)
-	    reloc = BFD_RELOC_390_PLTOFF32;
-	  else if (nbytes == 8 && suffix == ELF_SUFFIX_PLTOFF)
-	    reloc = BFD_RELOC_390_PLTOFF64;
-	  else if (nbytes == 4 && suffix == ELF_SUFFIX_PLT)
-	    reloc = BFD_RELOC_390_PLT32;
-	  else if (nbytes == 8 && suffix == ELF_SUFFIX_PLT)
-	    reloc = BFD_RELOC_390_PLT64;
-	  else if (nbytes == 4 && suffix == ELF_SUFFIX_GOTPLT)
-	    reloc = BFD_RELOC_390_GOTPLT32;
-	  else if (nbytes == 8 && suffix == ELF_SUFFIX_GOTPLT)
-	    reloc = BFD_RELOC_390_GOTPLT64;
+	  if (nbytes == 2)
+	    {
+	      static bfd_reloc_code_real_type tab2[] =
+		{
+		  [ELF_SUFFIX_NONE] BFD_RELOC_UNUSED ,
+		  [ELF_SUFFIX_GOT] BFD_RELOC_390_GOT16,
+		  [ELF_SUFFIX_PLT] BFD_RELOC_UNUSED,
+		  [ELF_SUFFIX_GOTENT] BFD_RELOC_UNUSED,
+		  [ELF_SUFFIX_GOTOFF] BFD_RELOC_16_GOTOFF,
+		  [ELF_SUFFIX_GOTPLT] BFD_RELOC_UNUSED,
+		  [ELF_SUFFIX_PLTOFF] BFD_RELOC_390_PLTOFF16,
+		  [ELF_SUFFIX_TLS_GD] BFD_RELOC_UNUSED,
+		  [ELF_SUFFIX_TLS_GOTIE] BFD_RELOC_UNUSED,
+		  [ELF_SUFFIX_TLS_IE] BFD_RELOC_UNUSED,
+		  [ELF_SUFFIX_TLS_LDM] BFD_RELOC_UNUSED,
+		  [ELF_SUFFIX_TLS_LDO] BFD_RELOC_UNUSED,
+		  [ELF_SUFFIX_TLS_LE] BFD_RELOC_UNUSED,
+		};
+	      reloc = tab2[suffix];
+	    }
+	  else if (nbytes == 4)
+	    {
+	      static bfd_reloc_code_real_type tab4[] =
+		{
+		  [ELF_SUFFIX_NONE] BFD_RELOC_UNUSED ,
+		  [ELF_SUFFIX_GOT] BFD_RELOC_32_GOT_PCREL,
+		  [ELF_SUFFIX_PLT] BFD_RELOC_390_PLT32,
+		  [ELF_SUFFIX_GOTENT] BFD_RELOC_UNUSED,
+		  [ELF_SUFFIX_GOTOFF] BFD_RELOC_32_GOTOFF,
+		  [ELF_SUFFIX_GOTPLT] BFD_RELOC_390_GOTPLT32,
+		  [ELF_SUFFIX_PLTOFF] BFD_RELOC_390_PLTOFF32,
+		  [ELF_SUFFIX_TLS_GD] BFD_RELOC_390_TLS_GD32,
+		  [ELF_SUFFIX_TLS_GOTIE] BFD_RELOC_390_TLS_GOTIE32,
+		  [ELF_SUFFIX_TLS_IE] BFD_RELOC_390_TLS_IE32,
+		  [ELF_SUFFIX_TLS_LDM] BFD_RELOC_390_TLS_LDM32,
+		  [ELF_SUFFIX_TLS_LDO] BFD_RELOC_390_TLS_LDO32,
+		  [ELF_SUFFIX_TLS_LE] BFD_RELOC_390_TLS_LE32,
+		};
+	      reloc = tab4[suffix];
+	    }
+	  else if (nbytes == 8)
+	    {
+	      static bfd_reloc_code_real_type tab8[] =
+		{
+		  [ELF_SUFFIX_NONE] BFD_RELOC_UNUSED ,
+		  [ELF_SUFFIX_GOT] BFD_RELOC_390_GOT64,
+		  [ELF_SUFFIX_PLT] BFD_RELOC_390_PLT64,
+		  [ELF_SUFFIX_GOTENT] BFD_RELOC_UNUSED,
+		  [ELF_SUFFIX_GOTOFF] BFD_RELOC_390_GOTOFF64,
+		  [ELF_SUFFIX_GOTPLT] BFD_RELOC_390_GOTPLT64,
+		  [ELF_SUFFIX_PLTOFF] BFD_RELOC_390_PLTOFF64,
+		  [ELF_SUFFIX_TLS_GD] BFD_RELOC_390_TLS_GD64,
+		  [ELF_SUFFIX_TLS_GOTIE] BFD_RELOC_390_TLS_GOTIE64,
+		  [ELF_SUFFIX_TLS_IE] BFD_RELOC_390_TLS_IE64,
+		  [ELF_SUFFIX_TLS_LDM] BFD_RELOC_390_TLS_LDM64,
+		  [ELF_SUFFIX_TLS_LDO] BFD_RELOC_390_TLS_LDO64,
+		  [ELF_SUFFIX_TLS_LE] BFD_RELOC_390_TLS_LE64,
+		};
+	      reloc = tab8[suffix];
+	    }
 	  else
 	    reloc = BFD_RELOC_UNUSED;
 
-	  if (reloc != BFD_RELOC_UNUSED)
+	  if (reloc != BFD_RELOC_UNUSED
+	      && (reloc_howto = bfd_reloc_type_lookup (stdoutput, reloc)))
 	    {
-	      reloc_howto = bfd_reloc_type_lookup (stdoutput, reloc);
 	      size = bfd_get_reloc_size (reloc_howto);
 	      if (size > nbytes)
 		as_bad (_("%s relocations do not fit in %d bytes"),
@@ -1035,6 +1142,7 @@
   struct s390_fixup fixups[MAX_INSN_FIXUPS];
   const struct s390_operand *operand;
   const unsigned char *opindex_ptr;
+  expressionS ex;
   elf_suffix_type suffix;
   bfd_reloc_code_real_type reloc;
   int skip_optional;
@@ -1052,7 +1160,6 @@
   fc = 0;
   for (opindex_ptr = opcode->operands; *opindex_ptr != 0; opindex_ptr++)
     {
-      expressionS ex;
       char *hold;
 
       operand = s390_operands + *opindex_ptr;
@@ -1167,6 +1274,18 @@
 		       && (operand->bits == 32))
 		reloc = BFD_RELOC_390_GOTPLTENT;
 	    }
+	  else if (suffix == ELF_SUFFIX_TLS_GOTIE)
+	    {
+	      if ((operand->flags & S390_OPERAND_DISP)
+		  && (operand->bits == 12))
+		reloc = BFD_RELOC_390_TLS_GOTIE12;
+	    }
+	  else if (suffix == ELF_SUFFIX_TLS_IE)
+	    {
+	      if ((operand->flags & S390_OPERAND_PCREL)
+		       && (operand->bits == 32))
+		reloc = BFD_RELOC_390_TLS_IEENT;
+	    }
 
 	  if (suffix != ELF_SUFFIX_NONE && reloc == BFD_RELOC_UNUSED)
 	    as_bad (_("invalid operand suffix"));
@@ -1262,6 +1381,20 @@
   while (ISSPACE (*str))
     ++str;
 
+  /* Check for tls instruction marker.  */
+  reloc = s390_tls_suffix (&str, &ex);
+  if (reloc != BFD_RELOC_UNUSED)
+    {
+      /* We need to generate a fixup of type 'reloc' for this
+	 instruction.  */
+      if (fc >= MAX_INSN_FIXUPS)
+	as_fatal (_("too many fixups"));
+      fixups[fc].exp = ex;
+      fixups[fc].opindex = -1;
+      fixups[fc].reloc = reloc;
+      ++fc;
+    }
+
   if (*str != '\0')
     {
       char *linefeed;
@@ -1286,6 +1419,15 @@
      md_apply_fix3.  */
   for (i = 0; i < fc; i++)
     {
+
+      if (fixups[i].opindex < 0)
+	{
+	  /* Create tls instruction marker relocation.  */
+	  fix_new_exp (frag_now, f - frag_now->fr_literal, opcode->oplen,
+		       &fixups[i].exp, 0, fixups[i].reloc);
+	  continue;
+	}
+
       operand = s390_operands + fixups[i].opindex;
 
       if (fixups[i].reloc != BFD_RELOC_UNUSED)
@@ -1699,6 +1841,26 @@
       || fixP->fx_r_type == BFD_RELOC_390_GOTPLT32
       || fixP->fx_r_type == BFD_RELOC_390_GOTPLT64
       || fixP->fx_r_type == BFD_RELOC_390_GOTPLTENT
+      || fixP->fx_r_type == BFD_RELOC_390_TLS_LOAD
+      || fixP->fx_r_type == BFD_RELOC_390_TLS_GDCALL
+      || fixP->fx_r_type == BFD_RELOC_390_TLS_LDCALL
+      || fixP->fx_r_type == BFD_RELOC_390_TLS_GD32
+      || fixP->fx_r_type == BFD_RELOC_390_TLS_GD64
+      || fixP->fx_r_type == BFD_RELOC_390_TLS_GOTIE12
+      || fixP->fx_r_type == BFD_RELOC_390_TLS_GOTIE32
+      || fixP->fx_r_type == BFD_RELOC_390_TLS_GOTIE64
+      || fixP->fx_r_type == BFD_RELOC_390_TLS_LDM32
+      || fixP->fx_r_type == BFD_RELOC_390_TLS_LDM64
+      || fixP->fx_r_type == BFD_RELOC_390_TLS_IE32
+      || fixP->fx_r_type == BFD_RELOC_390_TLS_IE64
+      || fixP->fx_r_type == BFD_RELOC_390_TLS_IEENT
+      || fixP->fx_r_type == BFD_RELOC_390_TLS_LE32
+      || fixP->fx_r_type == BFD_RELOC_390_TLS_LE64
+      || fixP->fx_r_type == BFD_RELOC_390_TLS_LDO32
+      || fixP->fx_r_type == BFD_RELOC_390_TLS_LDO64
+      || fixP->fx_r_type == BFD_RELOC_390_TLS_DTPMOD
+      || fixP->fx_r_type == BFD_RELOC_390_TLS_DTPOFF
+      || fixP->fx_r_type == BFD_RELOC_390_TLS_TPOFF
       || fixP->fx_r_type == BFD_RELOC_VTABLE_INHERIT
       || fixP->fx_r_type == BFD_RELOC_VTABLE_ENTRY)
     return 0;
@@ -1972,6 +2134,32 @@
 	case BFD_RELOC_VTABLE_ENTRY:
 	  fixP->fx_done = 0;
 	  return;
+
+	case BFD_RELOC_390_TLS_LOAD:
+	case BFD_RELOC_390_TLS_GDCALL:
+	case BFD_RELOC_390_TLS_LDCALL:
+	case BFD_RELOC_390_TLS_GD32:
+	case BFD_RELOC_390_TLS_GD64:
+	case BFD_RELOC_390_TLS_GOTIE12:
+	case BFD_RELOC_390_TLS_GOTIE32:
+	case BFD_RELOC_390_TLS_GOTIE64:
+	case BFD_RELOC_390_TLS_LDM32:
+	case BFD_RELOC_390_TLS_LDM64:
+	case BFD_RELOC_390_TLS_IE32:
+	case BFD_RELOC_390_TLS_IE64:
+	case BFD_RELOC_390_TLS_LE32:
+	case BFD_RELOC_390_TLS_LE64:
+	case BFD_RELOC_390_TLS_LDO32:
+	case BFD_RELOC_390_TLS_LDO64:
+	case BFD_RELOC_390_TLS_DTPMOD:
+	case BFD_RELOC_390_TLS_DTPOFF:
+	case BFD_RELOC_390_TLS_TPOFF:
+	  /* Fully resolved at link time.  */
+	  break;
+	case BFD_RELOC_390_TLS_IEENT:
+	  /* Fully resolved at link time.  */
+	  value += 2;
+	  break;
 
 	default:
 	  {
diff -urN src/include/elf/s390.h src-s390/include/elf/s390.h
--- src/include/elf/s390.h	Mon Jan 20 12:38:30 2003
+++ src-s390/include/elf/s390.h	Thu Jan 23 23:23:13 2003
@@ -73,6 +73,43 @@
     RELOC_NUMBER (R_390_PLTOFF16, 34)   /* 16 bit offset from GOT to PLT. */
     RELOC_NUMBER (R_390_PLTOFF32, 35)   /* 32 bit offset from GOT to PLT. */
     RELOC_NUMBER (R_390_PLTOFF64, 36)   /* 16 bit offset from GOT to PLT. */
+    RELOC_NUMBER (R_390_TLS_LOAD, 37)	/* Tag for load insn in TLS code. */
+    RELOC_NUMBER (R_390_TLS_GDCALL, 38)	/* Tag for function call in general
+					   dynamic TLS code.  */
+    RELOC_NUMBER (R_390_TLS_LDCALL, 39)	/* Tag for function call in local
+					   dynamic TLS code.  */
+    RELOC_NUMBER (R_390_TLS_GD32, 40)	/* Direct 32 bit for general dynamic
+					   thread local data.  */
+    RELOC_NUMBER (R_390_TLS_GD64, 41)	/* Direct 64 bit for general dynamic
+					   thread local data.  */
+    RELOC_NUMBER (R_390_TLS_GOTIE12, 42)/* 12 bit GOT offset for static TLS
+					   block offset.  */
+    RELOC_NUMBER (R_390_TLS_GOTIE32, 43)/* 32 bit GOT offset for static TLS
+					   block offset.  */
+    RELOC_NUMBER (R_390_TLS_GOTIE64, 44)/* 64 bit GOT offset for static TLS
+					   block offset.  */
+    RELOC_NUMBER (R_390_TLS_LDM32, 45)	/* Direct 32 bit for local dynamic
+					   thread local data in LD code.  */
+    RELOC_NUMBER (R_390_TLS_LDM64, 46)	/* Direct 64 bit for local dynamic
+					   thread local data in LD code.  */
+    RELOC_NUMBER (R_390_TLS_IE32, 47)	/* 32 bit address of GOT entry for
+					   negated static TLS block offset.  */
+    RELOC_NUMBER (R_390_TLS_IE64, 48)	/* 64 bit address of GOT entry for
+					   negated static TLS block offset.  */
+    RELOC_NUMBER (R_390_TLS_IEENT, 49)	/* 32 bit rel. offset to GOT entry for
+					   negated static TLS block offset.  */
+    RELOC_NUMBER (R_390_TLS_LE32, 50)	/* 32 bit negated offset relative to
+					   static TLS block.  */
+    RELOC_NUMBER (R_390_TLS_LE64, 51)	/* 64 bit negated offset relative to
+					   static TLS block.  */
+    RELOC_NUMBER (R_390_TLS_LDO32, 52)	/* 32 bit offset relative to TLS
+					   block.  */
+    RELOC_NUMBER (R_390_TLS_LDO64, 53)	/* 64 bit offset relative to TLS
+					   block.  */
+    RELOC_NUMBER (R_390_TLS_DTPMOD, 54)	/* ID of module containing symbol.  */
+    RELOC_NUMBER (R_390_TLS_DTPOFF, 55)	/* Offset in TLS block.  */
+    RELOC_NUMBER (R_390_TLS_TPOFF, 56)	/* Negate offset in static TLS
+					   block.  */
     /* These are GNU extensions to enable C++ vtable garbage collection.  */
     RELOC_NUMBER (R_390_GNU_VTINHERIT, 250)
     RELOC_NUMBER (R_390_GNU_VTENTRY, 251)
diff -urN src/ld/testsuite/ld-s390/s390.exp src-s390/ld/testsuite/ld-s390/s390.exp
--- src/ld/testsuite/ld-s390/s390.exp	Thu Jan  1 01:00:00 1970
+++ src-s390/ld/testsuite/ld-s390/s390.exp	Thu Jan 23 23:23:13 2003
@@ -0,0 +1,72 @@
+# Expect script for ld-s390 tests
+#   Copyright (C) 2003 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 s390 linking; all types of relocs.  This tests the assembler and
+# tools like objdump as well as the linker.
+
+if { !([istarget "s390-*-*"] || [istarget "s390x-*-*"]) } {
+    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 s390tests {
+    {"TLS -fpic -shared transitions" "-shared -melf_s390"
+     "-m31" {tlspic1.s tlspic2.s}
+     {{readelf -Ssrl tlspic.rd} {objdump -dzrj.text tlspic.dd}
+      {objdump -sj.got tlspic.sd} {objdump -sj.tdata tlspic.td}}
+     "libtlspic.so"}
+    {"Helper shared library" "-shared -melf_s390"
+     "-m31" {tlslib.s} {} "libtlslib.so"}
+    {"TLS -fpic and -fno-pic exec transitions"
+     "-melf_s390 tmpdir/libtlslib.so" "-m31" {tlsbinpic.s tlsbin.s}
+     {{readelf -Ssrl tlsbin.rd} {objdump -dzrj.text tlsbin.dd}
+      {objdump -sj.got tlsbin.sd} {objdump -sj.tdata tlsbin.td}}
+     "tlsbin"}
+}
+
+set s390xtests {
+    {"TLS -fpic -shared transitions" "-shared -melf64_s390"
+     "-m64 -Aesame" {tlspic1_64.s tlspic2_64.s}
+     {{readelf -WSsrl tlspic_64.rd} {objdump -dzrj.text tlspic_64.dd}
+      {objdump -sj.got tlspic_64.sd} {objdump -sj.tdata tlspic_64.td}}
+     "libtlspic_64.so"}
+    {"Helper shared library" "-shared -melf64_s390"
+     "-m64 -Aesame" {tlslib_64.s} {} "libtlslib_64.so"}
+    {"TLS -fpic and -fno-pic exec transitions"
+     "-melf64_s390 tmpdir/libtlslib_64.so" "-m64 -Aesame"
+     {tlsbinpic_64.s tlsbin_64.s}
+     {{readelf -WSsrl tlsbin_64.rd} {objdump -dzrj.text tlsbin_64.dd}
+      {objdump -sj.got tlsbin_64.sd} {objdump -sj.tdata tlsbin_64.td}}
+     "tlsbin_64"}
+}
+
+if [istarget "s390-*-*"] {
+    run_ld_link_tests $s390tests
+}
+
+if [istarget "s390x-*-*"] {
+    run_ld_link_tests $s390xtests
+}
diff -urN src/ld/testsuite/ld-s390/tlsbin.dd src-s390/ld/testsuite/ld-s390/tlsbin.dd
--- src/ld/testsuite/ld-s390/tlsbin.dd	Thu Jan  1 01:00:00 1970
+++ src-s390/ld/testsuite/ld-s390/tlsbin.dd	Thu Jan 23 23:23:13 2003
@@ -0,0 +1,185 @@
+#source: tlsbinpic.s
+#source: tlsbin.s
+#as: -m31
+#ld: -shared -melf_s390
+#objdump: -dzrj.text
+#target: s390-*-*
+
+# PT_TLS layout is:
+# Offset from   Offset from     Name
+# TCB base      TCB end
+# 0x00          -0xa0           sg1..sg2
+# 0x20          -0x80           sl1..sl2
+# 0x40          -0x60           sh1..sh2
+# 0x60          -0x40           bg1..bg2
+# 0x80          -0x20           bl1..bl2
+
+.*: +file format elf32-s390
+
+Disassembly of section .text:
+
+0+4002e4 <fn2>:
+# function prolog
+ +4002e4:	90 6e f0 18       	stm	%r6,%r14,24\(%r15\)
+ +4002e8:	a7 d5 00 24       	bras	%r13,400330 <fn2\+0x4c>
+# _GLOBAL_OFFSET_TABLE_
+ +4002ec:	00 00 12 90       	.long	0x00001290
+# __tls_get_addr@plt-.LT1
+ +4002f0:	ff ff ff d8       	.long	0xffffffd8
+# sG1@tlsgd
+ +4002f4:	00 00 00 28       	.long	0x00000028
+# sG2@tlsgd
+ +4002f8:	00 00 00 20       	.long	0x00000020
+# sg1@tlsgd
+ +4002fc:	ff ff ff 60       	.long	0xffffff60
+# sl1@tlsgd
+ +400300:	ff ff ff 80       	.long	0xffffff80
+# sh1@tlsgd
+ +400304:	ff ff ff a0       	.long	0xffffffa0
+# sl1@tlsldm
+ +400308:	00 00 00 00       	.long	0x00000000
+# sl1@dtpoff
+ +40030c:	ff ff ff 80       	.long	0xffffff80
+# sl2@dtpoff
+ +400310:	ff ff ff 84       	.long	0xffffff84
+# sh1@tlsldm
+ +400314:	00 00 00 00       	.long	0x00000000
+# sh1@dtpoff
+ +400318:	ff ff ff a0       	.long	0xffffffa0
+# sh2@dtpoff
+ +40031c:	ff ff ff a4       	.long	0xffffffa4
+# sG2@gotntpoff
+ +400320:	00 00 00 20       	.long	0x00000020
+# sg1@gotntpoff
+ +400324:	ff ff ff 60       	.long	0xffffff60
+# sl1@gotntpoff
+ +400328:	ff ff ff 80       	.long	0xffffff80
+# sh1@gotntpoff
+ +40032c:	ff ff ff a0       	.long	0xffffffa0
+# function prolog
+ +400330:	18 ef             	lr	%r14,%r15
+ +400332:	58 c0 d0 00       	l	%r12,0\(%r13\)
+ +400336:	a7 fa ff a0       	ahi	%r15,-96
+ +40033a:	41 cc d0 00       	la	%r12,0\(%r12,%r13\)
+ +40033e:	50 e0 e0 00       	st	%r14,0\(%r14\)
+# Extract TCB and load branch offset
+ +400342:	b2 4f 00 90       	ear	%r9,%a0
+ +400346:	58 70 d0 04       	l	%r7,4\(%r13\)
+# GD -> IE because variable is not defined in executable
+ +40034a:	58 20 d0 08       	l	%r2,8\(%r13\)
+ +40034e:	58 22 c0 00       	l	%r2,0\(%r2,%r12\)
+ +400352:	41 22 90 00       	la	%r2,0\(%r2,%r9\)
+# GD -> IE because variable is not defined in executable where
+# the variable is referenced through IE too
+ +400356:	58 20 d0 0c       	l	%r2,12\(%r13\)
+ +40035a:	58 22 c0 00       	l	%r2,0\(%r2,%r12\)
+ +40035e:	41 22 90 00       	la	%r2,0\(%r2,%r9\)
+# GD -> LE with global variable defined in executable
+ +400362:	58 20 d0 10       	l	%r2,16\(%r13\)
+ +400366:	47 00 00 00       	bc	0,0
+ +40036a:	41 22 90 00       	la	%r2,0\(%r2,%r9\)
+# GD -> LE with local variable defined in executable
+ +40036e:	58 20 d0 14       	l	%r2,20\(%r13\)
+ +400372:	47 00 00 00       	bc	0,0
+ +400376:	41 22 90 00       	la	%r2,0\(%r2,%r9\)
+# GD -> LE with hidden variable defined in executable
+ +40037a:	58 20 d0 18       	l	%r2,24\(%r13\)
+ +40037e:	47 00 00 00       	bc	0,0
+ +400382:	41 22 90 00       	la	%r2,0\(%r2,%r9\)
+# LD -> LE
+ +400386:	58 20 d0 1c       	l	%r2,28\(%r13\)
+ +40038a:	47 00 00 00       	bc	0,0
+ +40038e:	41 32 90 00       	la	%r3,0\(%r2,%r9\)
+ +400392:	58 40 d0 20       	l	%r4,32\(%r13\)
+ +400396:	41 54 30 00       	la	%r5,0\(%r4,%r3\)
+ +40039a:	58 40 d0 24       	l	%r4,36\(%r13\)
+ +40039e:	41 54 30 00       	la	%r5,0\(%r4,%r3\)
+# LD -> LE against hidden variables
+ +4003a2:	58 20 d0 28       	l	%r2,40\(%r13\)
+ +4003a6:	47 00 00 00       	bc	0,0
+ +4003aa:	41 32 90 00       	la	%r3,0\(%r2,%r9\)
+ +4003ae:	58 40 d0 2c       	l	%r4,44\(%r13\)
+ +4003b2:	41 54 30 00       	la	%r5,0\(%r4,%r3\)
+ +4003b6:	58 40 d0 30       	l	%r4,48\(%r13\)
+ +4003ba:	41 54 30 00       	la	%r5,0\(%r4,%r3\)
+# IE against global var
+ +4003be:	58 30 d0 34       	l	%r3,52\(%r13\)
+ +4003c2:	58 33 c0 00       	l	%r3,0\(%r3,%r12\)
+ +4003c6:	58 33 90 00       	l	%r3,0\(%r3,%r9\)
+# IE -> LE against global var defined in exec
+ +4003ca:	58 30 d0 38       	l	%r3,56\(%r13\)
+ +4003ce:	18 43             	lr	%r4,%r3
+ +4003d0:	07 00             	bcr	0,%r0
+ +4003d2:	41 54 90 00       	la	%r5,0\(%r4,%r9\)
+# IE -> LE against local var
+ +4003d6:	58 30 d0 3c       	l	%r3,60\(%r13\)
+ +4003da:	18 43             	lr	%r4,%r3
+ +4003dc:	07 00             	bcr	0,%r0
+ +4003de:	41 54 90 00       	la	%r5,0\(%r4,%r9\)
+# IE -> LE against hidden var
+ +4003e2:	58 30 d0 40       	l	%r3,64\(%r13\)
+ +4003e6:	18 43             	lr	%r4,%r3
+ +4003e8:	07 00             	bcr	0,%r0
+ +4003ea:	41 54 90 00       	la	%r5,0\(%r4,%r9\)
+# IE against global var with small got access (no optimization)
+ +4003ee:	58 30 c0 14       	l	%r3,20\(%r12\)
+ +4003f2:	41 33 90 00       	la	%r3,0\(%r3,%r9\)
+# IE against global var defined in exec with small got access
+# (no optimization)
+ +4003f6:	58 30 c0 18       	l	%r3,24\(%r12\)
+ +4003fa:	41 33 90 00       	la	%r3,0\(%r3,%r9\)
+# IE against local var with small got access (no optimization)
+ +4003fe:	58 30 c0 10       	l	%r3,16\(%r12\)
+ +400402:	41 33 90 00       	la	%r3,0\(%r3,%r9\)
+# IE against hidden var with small got access (no optimization)
+ +400406:	58 30 c0 1c       	l	%r3,28\(%r12\)
+ +40040a:	41 33 90 00       	la	%r3,0\(%r3,%r9\)
+# function epilog
+ +40040e:	98 6e f0 78       	lm	%r6,%r14,120\(%r15\)
+ +400412:	07 fe             	br	%r14
+
+0+400414 <_start>:
+# function prolog
+ +400414:	90 6e f0 18       	stm	%r6,%r14,24\(%r15\)
+ +400418:	a7 d5 00 0c       	bras	%r13,400430 <_start\+0x1c>
+# sG6@indntpoff
+ +40041c:	00 40 15 a0       	.long	0x004015a0
+# bg6@indntpoff
+ +400420:	ff ff ff d4       	.long	0xffffffd4
+# bl6@indntpoff
+ +400424:	ff ff ff f4       	.long	0xfffffff4
+# sh6@indntpoff
+ +400428:	ff ff ff b4       	.long	0xffffffb4
+# sg3@indntpoff
+ +40042c:	ff ff ff 68       	.long	0xffffff68
+# function prolog
+ +400430:	18 ef             	lr	%r14,%r15
+ +400432:	a7 fa ff a0       	ahi	%r15,-96
+ +400436:	50 e0 e0 00       	st	%r14,0\(%r14\)
+# Extract TCB
+ +40043a:	b2 4f 00 90       	ear	%r9,%a0
+# IE against global var
+ +40043e:	58 30 d0 00       	l	%r3,0\(%r13\)
+ +400442:	58 33 c0 00       	l	%r3,0\(%r3,%r12\)
+ +400446:	41 33 90 00       	la	%r3,0\(%r3,%r9\)
+# IE -> LE against global var defined in exec
+ +40044a:	58 30 d0 04       	l	%r3,4\(%r13\)
+ +40044e:	18 43             	lr	%r4,%r3
+ +400450:	07 00             	bcr	0,%r0
+ +400452:	41 54 90 00       	la	%r5,0\(%r4,%r9\)
+# IE -> LE against local var
+ +400456:	58 30 d0 08       	l	%r3,8\(%r13\)
+ +40045a:	18 43             	lr	%r4,%r3
+ +40045c:	07 00             	bcr	0,%r0
+ +40045e:	41 54 90 00       	la	%r5,0\(%r4,%r9\)
+# IE -> LE against hidden but not local var
+ +400462:	58 30 d0 0c       	l	%r3,12\(%r13\)
+ +400466:	18 43             	lr	%r4,%r3
+ +400468:	07 00             	bcr	0,%r0
+ +40046a:	41 54 90 00       	la	%r5,0\(%r4,%r9\)
+# LE, global var defined in exec
+ +40046e:	58 40 d0 10       	l	%r4,16\(%r13\)
+ +400472:	41 54 90 00       	la	%r5,0\(%r4,%r9\)
+# function epilog
+ +400476:	98 6e f0 78       	lm	%r6,%r14,120\(%r15\)
+ +40047a:	07 fe             	br	%r14
diff -urN src/ld/testsuite/ld-s390/tlsbin.rd src-s390/ld/testsuite/ld-s390/tlsbin.rd
--- src/ld/testsuite/ld-s390/tlsbin.rd	Thu Jan  1 01:00:00 1970
+++ src-s390/ld/testsuite/ld-s390/tlsbin.rd	Thu Jan 23 23:23:13 2003
@@ -0,0 +1,156 @@
+#source: tlsbinpic.s
+#source: tlsbin.s
+#as: -m31
+#ld: -shared -melf_s390
+#readelf: -Ssrl
+#target: s390-*-*
+
+There are 19 section headers, starting at offset 0x[0-9a-f]+:
+
+Section Headers:
+  \[Nr\] Name +Type +Addr +Off +Size +ES Flg Lk Inf Al
+  \[ 0\] +NULL +0+ 0+ 0+ 00 +0 +0 +0
+  \[ 1\] .interp +.*
+  \[ 2\] .hash +.*
+  \[ 3\] .dynsym +.*
+  \[ 4\] .dynstr +.*
+  \[ 5\] .rela.dyn +.*
+  \[ 6\] .rela.plt +.*
+  \[ 7\] .plt +.*
+  \[ 8\] .text +PROGBITS +0+4002e4 0+2e4 0+198 00 +AX +0 +0 +4
+  \[ 9\] .data +.*
+  \[10\] .tdata +PROGBITS +0+40147c 0+47c 0+60 00 WAT +0 +0 +1
+  \[11\] .tbss +NOBITS +0+4014dc 0+4dc 0+40 00 WAT +0 +0 +1
+  \[12\] .dynamic +DYNAMIC +0+4014dc 0+4dc 0+a0 08 +WA +4 +0 +4
+  \[13\] .got +PROGBITS +0+40157c 0+57c 0+2c 04 +WA +0 +0 +4
+  \[14\] .sbss +.*
+  \[15\] .bss +.*
+  \[16\] .shstrtab +.*
+  \[17\] .symtab +.*
+  \[18\] .strtab +.*
+Key to Flags:
+.*
+.*
+.*
+
+Elf file type is EXEC \(Executable file\)
+Entry point 0x400414
+There are 6 program headers, starting at offset [0-9]+
+
+Program Headers:
+  Type +Offset +VirtAddr +PhysAddr +FileSiz +MemSiz +Flg Align
+  PHDR +0x0+34 0x0+400034 0x0+400034 0x0+c0 0x0+c0 R E 0x4
+  INTERP +0x0+f4 0x0+4000f4 0x0+4000f4 0x0+11 0x0+11 R +0x1
+.*Requesting program interpreter.*
+  LOAD +0x0+ 0x0+400000 0x0+400000 0x0+47c 0x0+47c R E 0x1000
+  LOAD +0x0+47c 0x0+40147c 0x0+40147c 0x0+12c 0x0+12c RW  0x1000
+  DYNAMIC +0x0+4dc 0x0+4014dc 0x0+4014dc 0x0+a0 0x0+a0 RW  0x4
+  TLS +0x0+47c 0x0+40147c 0x0+40147c 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 0x268 contains 4 entries:
+ Offset +Info +Type +Sym.Value  Sym. Name \+ Addend
+[0-9a-f]+  0+138 R_390_TLS_TPOFF +0+ +sG3 \+ 0
+[0-9a-f]+  0+338 R_390_TLS_TPOFF +0+ +sG2 \+ 0
+[0-9a-f]+  0+638 R_390_TLS_TPOFF +0+ +sG6 \+ 0
+[0-9a-f]+  0+738 R_390_TLS_TPOFF +0+ +sG1 \+ 0
+
+Relocation section '.rela.plt' at offset 0x[0-9a-f]+ contains 1 entries:
+ Offset +Info +Type +Sym.Value  Sym. Name \+ Addend
+[0-9a-f]+  0+40b R_390_JMP_SLOT +0+40+2c4 +__tls_get_offset \+ 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 sG3
+ +2: [0-9a-f]+ +0 OBJECT  GLOBAL DEFAULT  ABS _DYNAMIC
+ +3: 0+ +0 TLS +GLOBAL DEFAULT  UND sG2
+ +4: [0-9a-f]+ +0 FUNC +GLOBAL DEFAULT  UND __tls_get_offset
+ +5: [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-9a-f]+ +0 NOTYPE  GLOBAL DEFAULT  ABS _edata
+ +9: [0-9a-f]+ +0 OBJECT  GLOBAL DEFAULT  ABS _GLOBAL_OFFSET_TABLE_
+ +10: [0-9a-f]+ +0 NOTYPE  GLOBAL DEFAULT  ABS _end
+
+Symbol table '.symtab' contains 71 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-9a-f]+ +0 SECTION LOCAL  DEFAULT +18 
+ +19: 0+20 +0 TLS +LOCAL  DEFAULT +10 sl1
+ +20: 0+24 +0 TLS +LOCAL  DEFAULT +10 sl2
+ +21: 0+28 +0 TLS +LOCAL  DEFAULT +10 sl3
+ +22: 0+2c +0 TLS +LOCAL  DEFAULT +10 sl4
+ +23: 0+30 +0 TLS +LOCAL  DEFAULT +10 sl5
+ +24: 0+34 +0 TLS +LOCAL  DEFAULT +10 sl6
+ +25: 0+38 +0 TLS +LOCAL  DEFAULT +10 sl7
+ +26: 0+3c +0 TLS +LOCAL  DEFAULT +10 sl8
+ +27: 0+80 +0 TLS +LOCAL  DEFAULT +11 bl1
+ +28: 0+84 +0 TLS +LOCAL  DEFAULT +11 bl2
+ +29: 0+88 +0 TLS +LOCAL  DEFAULT +11 bl3
+ +30: 0+8c +0 TLS +LOCAL  DEFAULT +11 bl4
+ +31: 0+90 +0 TLS +LOCAL  DEFAULT +11 bl5
+ +32: 0+94 +0 TLS +LOCAL  DEFAULT +11 bl6
+ +33: 0+98 +0 TLS +LOCAL  DEFAULT +11 bl7
+ +34: 0+9c +0 TLS +LOCAL  DEFAULT +11 bl8
+ +35: 0+ +0 TLS +GLOBAL DEFAULT  UND sG3
+ +36: 0+1c +0 TLS +GLOBAL DEFAULT +10 sg8
+ +37: 0+7c +0 TLS +GLOBAL DEFAULT +11 bg8
+ +38: 0+74 +0 TLS +GLOBAL DEFAULT +11 bg6
+ +39: 0+68 +0 TLS +GLOBAL DEFAULT +11 bg3
+ +40: [0-9a-f]+ +0 OBJECT  GLOBAL DEFAULT  ABS _DYNAMIC
+ +41: 0+8 +0 TLS +GLOBAL DEFAULT +10 sg3
+ +42: 0+48 +0 TLS +GLOBAL HIDDEN +10 sh3
+ +43: 0+ +0 TLS +GLOBAL DEFAULT  UND sG2
+ +44: 0+c +0 TLS +GLOBAL DEFAULT +10 sg4
+ +45: 0+10 +0 TLS +GLOBAL DEFAULT +10 sg5
+ +46: 0+70 +0 TLS +GLOBAL DEFAULT +11 bg5
+ +47: 0+58 +0 TLS +GLOBAL HIDDEN +10 sh7
+ +48: 0+5c +0 TLS +GLOBAL HIDDEN +10 sh8
+ +49: [0-9a-f]+ +0 FUNC +GLOBAL DEFAULT  UND __tls_get_offset
+ +50: 0+ +0 TLS +GLOBAL DEFAULT +10 sg1
+ +51: [0-9a-f]+ +0 FUNC +GLOBAL DEFAULT +8 _start
+ +52: 0+4c +0 TLS +GLOBAL HIDDEN +10 sh4
+ +53: 0+78 +0 TLS +GLOBAL DEFAULT +11 bg7
+ +54: 0+50 +0 TLS +GLOBAL HIDDEN +10 sh5
+ +55: [0-9a-f]+ +0 NOTYPE  GLOBAL DEFAULT  ABS __bss_start
+ +56: 0+ +0 TLS +GLOBAL DEFAULT  UND sG6
+ +57: [0-9a-f]+ +0 FUNC +GLOBAL DEFAULT +8 fn2
+ +58: 0+4 +0 TLS +GLOBAL DEFAULT +10 sg2
+ +59: 0+ +0 TLS +GLOBAL DEFAULT  UND sG1
+ +60: 0+40 +0 TLS +GLOBAL HIDDEN +10 sh1
+ +61: 0+14 +0 TLS +GLOBAL DEFAULT +10 sg6
+ +62: 0+18 +0 TLS +GLOBAL DEFAULT +10 sg7
+ +63: [0-9a-f]+ +0 NOTYPE  GLOBAL DEFAULT  ABS _edata
+ +64: [0-9a-f]+ +0 OBJECT  GLOBAL DEFAULT  ABS _GLOBAL_OFFSET_TABLE_
+ +65: [0-9a-f]+ +0 NOTYPE  GLOBAL DEFAULT  ABS _end
+ +66: 0+44 +0 TLS +GLOBAL HIDDEN +10 sh2
+ +67: 0+54 +0 TLS +GLOBAL HIDDEN +10 sh6
+ +68: 0+64 +0 TLS +GLOBAL DEFAULT +11 bg2
+ +69: 0+60 +0 TLS +GLOBAL DEFAULT +11 bg1
+ +70: 0+6c +0 TLS +GLOBAL DEFAULT +11 bg4
diff -urN src/ld/testsuite/ld-s390/tlsbin.s src-s390/ld/testsuite/ld-s390/tlsbin.s
--- src/ld/testsuite/ld-s390/tlsbin.s	Thu Jan  1 01:00:00 1970
+++ src-s390/ld/testsuite/ld-s390/tlsbin.s	Thu Jan 23 23:23:13 2003
@@ -0,0 +1,73 @@
+	.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:
+	/* Function prolog */
+	stm	%r6,%r14,24(%r15)
+	bras	%r13,.LTN1
+	/* Literal pool */
+.LT1:
+.LC0:
+	.long	sG6@indntpoff
+.LC1:
+	.long	bg6@indntpoff
+.LC2:
+	.long	bl6@indntpoff
+.LC3:
+	.long	sh6@indntpoff
+.LC4:
+	.long	sg3@indntpoff
+.LTN1:
+	/* Function prolog */
+	lr	%r14,%r15
+	ahi	%r15,-96
+	st	%r14,0(%r14)
+
+	/* Extract TCB */
+	ear	%r9,%a0
+
+	/* IE against global var  */
+	l	%r3,.LC0-.LT1(%r13)
+	l	%r3,0(%r3,%r12):tls_load:sG6
+	la	%r3,0(%r3,%r9)
+
+	/* IE -> LE against global var defined in exec  */
+	l	%r3,.LC1-.LT1(%r13)
+	l	%r4,0(%r3,%r12):tls_load:bg6
+	la	%r5,0(%r4,%r9)
+
+	/* IE -> LE against local var  */
+	l	%r3,.LC2-.LT1(%r13)
+	l	%r4,0(%r3,%r12):tls_load:bl6
+	la	%r5,0(%r4,%r9)
+
+	/* IE -> LE against hidden but not local var  */
+	l	%r3,.LC3-.LT1(%r13)
+	l	%r4,0(%r3,%r12):tls_load:sh6
+	la	%r5,0(%r4,%r9)
+
+	/* LE, global var defined in exec  */
+	l	%r4,.LC4-.LT1(%r13)
+	la	%r5,0(%r4,%r9)
+
+	/* Function epilog */
+	lm	%r6,%r14,120(%r15)
+	br	%r14
diff -urN src/ld/testsuite/ld-s390/tlsbin.sd src-s390/ld/testsuite/ld-s390/tlsbin.sd
--- src/ld/testsuite/ld-s390/tlsbin.sd	Thu Jan  1 01:00:00 1970
+++ src-s390/ld/testsuite/ld-s390/tlsbin.sd	Thu Jan 23 23:23:13 2003
@@ -0,0 +1,13 @@
+#source: tlsbinpic.s
+#source: tlsbin.s
+#as: -m31
+#ld: -shared -melf_s390
+#objdump: -sj.got
+#target: s390-*-*
+
+.*:     file format elf32-s390
+
+Contents of section .got:
+ 40157c [0-9a-f]+ 00000000 00000000 [0-9a-f]+  .@...........@..
+ 40158c ffffff88 00000000 ffffff68 ffffffa8  ...........h....
+ 40159c 00000000 00000000 00000000           ............    
diff -urN src/ld/testsuite/ld-s390/tlsbin.td src-s390/ld/testsuite/ld-s390/tlsbin.td
--- src/ld/testsuite/ld-s390/tlsbin.td	Thu Jan  1 01:00:00 1970
+++ src-s390/ld/testsuite/ld-s390/tlsbin.td	Thu Jan 23 23:23:13 2003
@@ -0,0 +1,16 @@
+#source: tlsbinpic.s
+#source: tlsbin.s
+#as: -m31
+#ld: -shared -melf_s390
+#objdump: -sj.tdata
+#target: s390-*-*
+
+.*:     file format elf32-s390
+
+Contents of section .tdata:
+ 40147c 00000011 00000012 00000013 00000014  .*
+ 40148c 00000015 00000016 00000017 00000018  .*
+ 40149c 00000041 00000042 00000043 00000044  .*
+ 4014ac 00000045 00000046 00000047 00000048  .*
+ 4014bc 00000101 00000102 00000103 00000104  .*
+ 4014cc 00000105 00000106 00000107 00000108  .*
diff -urN src/ld/testsuite/ld-s390/tlsbin_64.dd src-s390/ld/testsuite/ld-s390/tlsbin_64.dd
--- src/ld/testsuite/ld-s390/tlsbin_64.dd	Thu Jan  1 01:00:00 1970
+++ src-s390/ld/testsuite/ld-s390/tlsbin_64.dd	Thu Jan 23 23:23:13 2003
@@ -0,0 +1,213 @@
+#source: tlsbinpic_64.s
+#source: tlsbin_64.s
+#as: -m64 -Aesame
+#ld: -shared -melf64_s390
+#objdump: -dzrj.text
+#target: s390x-*-*
+
+# PT_TLS layout is:
+# Offset from   Offset from     Name
+# TCB base      TCB end
+# 0x00          -0xa0           sg1..sg2
+# 0x20          -0x80           sl1..sl2
+# 0x40          -0x60           sh1..sh2
+# 0x60          -0x40           bg1..bg2
+# 0x80          -0x20           bl1..bl2
+
+.*: +file format elf64-s390
+
+Disassembly of section .text:
+
+0+80000458 <fn2>:
+# function prolog
+ +80000458:	eb 6e f0 30 00 24 	stmg	%r6,%r14,48\(%r15\)
+ +8000045e:	a7 d5 00 3e       	bras	%r13,800004da <fn2\+0x82>
+# sG1@tlsgd
+ +80000462:	00 00 00 00       	.long	0x00000000
+ +80000466:	00 00 00 60       	.long	0x00000060
+# sG2@tlsgd
+ +8000046a:	00 00 00 00       	.long	0x00000000
+ +8000046e:	00 00 00 48       	.long	0x00000048
+# sg1@tlsgd
+ +80000472:	ff ff ff ff       	.long	0xffffffff
+ +80000476:	ff ff ff 60       	.long	0xffffff60
+# sl1@tlsgd
+ +8000047a:	ff ff ff ff       	.long	0xffffffff
+ +8000047e:	ff ff ff 80       	.long	0xffffff80
+# sh1@tlsgd
+ +80000482:	ff ff ff ff       	.long	0xffffffff
+ +80000486:	ff ff ff a0       	.long	0xffffffa0
+# sl1@tlsldm
+ +8000048a:	00 00 00 00       	.long	0x00000000
+ +8000048e:	00 00 00 00       	.long	0x00000000
+# sl1@dtpoff
+ +80000492:	ff ff ff ff       	.long	0xffffffff
+ +80000496:	ff ff ff 80       	.long	0xffffff80
+# sl2@dtpoff
+ +8000049a:	ff ff ff ff       	.long	0xffffffff
+ +8000049e:	ff ff ff 84       	.long	0xffffff84
+# sh1@tlsldm
+ +800004a2:	00 00 00 00       	.long	0x00000000
+ +800004a6:	00 00 00 00       	.long	0x00000000
+# sh1@dtpoff
+ +800004aa:	ff ff ff ff       	.long	0xffffffff
+ +800004ae:	ff ff ff a0       	.long	0xffffffa0
+# sh2@dtpoff
+ +800004b2:	ff ff ff ff       	.long	0xffffffff
+ +800004b6:	ff ff ff a4       	.long	0xffffffa4
+# sG2@gotntpoff
+ +800004ba:	00 00 00 00       	.long	0x00000000
+ +800004be:	00 00 00 48       	.long	0x00000048
+# sg1@gotntpoff
+ +800004c2:	ff ff ff ff       	.long	0xffffffff
+ +800004c6:	ff ff ff 60       	.long	0xffffff60
+# sl1@gotntpoff
+ +800004ca:	ff ff ff ff       	.long	0xffffffff
+ +800004ce:	ff ff ff 80       	.long	0xffffff80
+# sh1@gotntpoff
+ +800004d2:	ff ff ff ff       	.long	0xffffffff
+ +800004d6:	ff ff ff a0       	.long	0xffffffa0
+# function prolog
+ +800004da:	b9 04 00 ef       	lgr	%r14,%r15
+ +800004de:	a7 fb ff 60       	aghi	%r15,-160
+ +800004e2:	c0 c0 00 00 09 d3 	larl	%r12,80001888 <_GLOBAL_OFFSET_TABLE_>
+ +800004e8:	e3 e0 e0 00 00 24 	stg	%r14,0\(%r14\)
+# extract TCB
+ +800004ee:	b2 4f 00 90       	ear	%r9,%a0
+ +800004f2:	eb 94 00 20 00 0d 	sllg	%r9,%r4,32
+ +800004f8:	b2 4f 00 91       	ear	%r9,%a1
+# GD -> IE because variable is not defined in executable
+ +800004fc:	e3 c0 d0 00 00 04 	lg	%r12,0\(%r13\)
+ +80000502:	e3 22 c0 00 00 04 	lg	%r2,0\(%r2,%r12\)
+ +80000508:	41 22 90 00       	la	%r2,0\(%r2,%r9\)
+# GD -> IE because variable is not defined in executable where
+# the variable is referenced through IE too
+ +8000050c:	e3 20 d0 08 00 04 	lg	%r2,8\(%r13\)
+ +80000512:	e3 22 c0 00 00 04 	lg	%r2,0\(%r2,%r12\)
+ +80000518:	41 22 90 00       	la	%r2,0\(%r2,%r9\)
+# GD -> LE with global variable defined in executable
+ +8000051c:	e3 20 d0 10 00 04 	lg	%r2,16\(%r13\)
+ +80000522:	c0 04 00 00 00 00 	brcl	0,80000522 <fn2\+0xca>
+ +80000528:	41 22 90 00       	la	%r2,0\(%r2,%r9\)
+# GD -> LE with local variable defined in executable
+ +8000052c:	e3 20 d0 18 00 04 	lg	%r2,24\(%r13\)
+ +80000532:	c0 04 00 00 00 00 	brcl	0,80000532 <fn2\+0xda>
+ +80000538:	41 22 90 00       	la	%r2,0\(%r2,%r9\)
+# GD -> LE with hidden variable defined in executable
+ +8000053c:	e3 20 d0 20 00 04 	lg	%r2,32\(%r13\)
+ +80000542:	c0 04 00 00 00 00 	brcl	0,80000542 <fn2\+0xea>
+ +80000548:	41 22 90 00       	la	%r2,0\(%r2,%r9\)
+# LD -> LE
+ +8000054c:	e3 20 d0 28 00 04 	lg	%r2,40\(%r13\)
+ +80000552:	c0 04 00 00 00 00 	brcl	0,80000552 <fn2\+0xfa>
+ +80000558:	41 32 90 00       	la	%r3,0\(%r2,%r9\)
+ +8000055c:	e3 40 d0 30 00 04 	lg	%r4,48\(%r13\)
+ +80000562:	41 54 30 00       	la	%r5,0\(%r4,%r3\)
+ +80000566:	e3 40 d0 38 00 04 	lg	%r4,56\(%r13\)
+ +8000056c:	41 54 30 00       	la	%r5,0\(%r4,%r3\)
+ +80000570:	e3 20 d0 40 00 04 	lg	%r2,64\(%r13\)
+ +80000576:	c0 04 00 00 00 00 	brcl	0,80000576 <fn2\+0x11e>
+ +8000057c:	41 32 90 00       	la	%r3,0\(%r2,%r9\)
+ +80000580:	e3 40 d0 48 00 04 	lg	%r4,72\(%r13\)
+ +80000586:	41 54 30 00       	la	%r5,0\(%r4,%r3\)
+ +8000058a:	e3 40 d0 50 00 04 	lg	%r4,80\(%r13\)
+ +80000590:	41 54 30 00       	la	%r5,0\(%r4,%r3\)
+# IE against global var
+ +80000594:	e3 30 d0 58 00 04 	lg	%r3,88\(%r13\)
+ +8000059a:	e3 33 c0 00 00 04 	lg	%r3,0\(%r3,%r12\)
+ +800005a0:	41 33 90 00       	la	%r3,0\(%r3,%r9\)
+# IE -> LE against global var defined in exec
+ +800005a4:	e3 30 d0 60 00 04 	lg	%r3,96\(%r13\)
+ +800005aa:	eb 43 00 00 00 0d 	sllg	%r4,%r3,0
+ +800005b0:	41 54 90 00       	la	%r5,0\(%r4,%r9\)
+# IE -> LE against local var
+ +800005b4:	e3 30 d0 68 00 04 	lg	%r3,104\(%r13\)
+ +800005ba:	eb 43 00 00 00 0d 	sllg	%r4,%r3,0
+ +800005c0:	41 54 90 00       	la	%r5,0\(%r4,%r9\)
+# IE -> LE against hidden var
+ +800005c4:	e3 30 d0 70 00 04 	lg	%r3,112\(%r13\)
+ +800005ca:	eb 43 00 00 00 0d 	sllg	%r4,%r3,0
+ +800005d0:	41 54 90 00       	la	%r5,0\(%r4,%r9\)
+# IE against global var with larl got access
+ +800005d4:	c0 30 00 00 09 6e 	larl	%r3,800018b0 <\_GLOBAL\_OFFSET\_TABLE\_\+0x28>
+ +800005da:	e3 33 c0 00 00 04 	lg	%r3,0\(%r3,%r12\)
+ +800005e0:	41 33 90 00       	la	%r3,0\(%r3,%r9\)
+# IE against global var defined in exec with larl got access
+ +800005e4:	c0 30 00 00 09 6e 	larl	%r3,800018c0 <\_GLOBAL\_OFFSET\_TABLE\_\+0x38>
+ +800005ea:	eb 43 00 00 00 0d 	sllg	%r4,%r3,0
+ +800005f0:	41 54 90 00       	la	%r5,0\(%r4,%r9\)
+# IE against local var with larl got access
+ +800005f4:	c0 30 00 00 09 5a 	larl	%r3,800018a8 <\_GLOBAL\_OFFSET\_TABLE\_\+0x20>
+ +800005fa:	eb 43 00 00 00 0d 	sllg	%r4,%r3,0
+ +80000600:	41 54 90 00       	la	%r5,0\(%r4,%r9\)
+# IE against hidden var with larl got access
+ +80000604:	c0 30 00 00 09 62 	larl	%r3,800018c8 <\_GLOBAL\_OFFSET\_TABLE\_\+0x40>
+ +8000060a:	eb 43 00 00 00 0d 	sllg	%r4,%r3,0
+ +80000610:	41 54 90 00       	la	%r5,0\(%r4,%r9\)
+# IE against global var with small got access (no optimization)
+ +80000614:	e3 30 c0 28 00 04 	lg	%r3,40\(%r12\)
+ +8000061a:	41 33 90 00       	la	%r3,0\(%r3,%r9\)
+# IE against global var defined in exec with small got access
+# (no optimization)
+ +8000061e:	e3 30 c0 38 00 04 	lg	%r3,56\(%r12\)
+ +80000624:	41 33 90 00       	la	%r3,0\(%r3,%r9\)
+# IE against local var with small got access (no optimization)
+ +80000628:	e3 30 c0 20 00 04 	lg	%r3,32\(%r12\)
+ +8000062e:	41 33 90 00       	la	%r3,0\(%r3,%r9\)
+# IE against hidden var with small got access (no optimization)
+ +80000632:	e3 30 c0 40 00 04 	lg	%r3,64\(%r12\)
+ +80000638:	41 33 90 00       	la	%r3,0\(%r3,%r9\)
+# function epilog
+ +8000063c:	eb 6e f0 d0 00 04 	lmg	%r6,%r14,208\(%r15\)
+ +80000642:	07 fe             	br	%r14
+
+0+80000644 <_start>:
+# function prolog
+ +80000644:	90 6e f0 18       	stm	%r6,%r14,24\(%r15\)
+ +80000648:	a7 d5 00 16       	bras	%r13,80000674 <_start\+0x30>
+# sG6@indntpoff
+ +8000064c:	00 00 00 00       	.long	0x00000000
+ +80000650:	80 00 18 e0       	ssm	2272\(%r1\)
+# bg6@indntpoff
+ +80000654:	ff ff ff ff       	.long	0xffffffff
+ +80000658:	ff ff ff d4       	.long	0xffffffd4
+# bl6@indntpoff
+ +8000065c:	ff ff ff ff       	.long	0xffffffff
+ +80000660:	ff ff ff f4       	.long	0xfffffff4
+# sh6@indntpoff
+ +80000664:	ff ff ff ff       	.long	0xffffffff
+ +80000668:	ff ff ff b4       	.long	0xffffffb4
+# sg3@indntpoff
+ +8000066c:	ff ff ff ff       	.long	0xffffffff
+ +80000670:	ff ff ff 68       	.long	0xffffff68
+# function prolog
+ +80000674:	b9 04 00 ef       	lgr	%r14,%r15
+ +80000678:	a7 fb ff 60       	aghi	%r15,-160
+ +8000067c:	e3 e0 e0 00 00 24 	stg	%r14,0\(%r14\)
+# extract TCB
+ +80000682:	b2 4f 00 90       	ear	%r9,%a0
+ +80000686:	eb 94 00 20 00 0d 	sllg	%r9,%r4,32
+ +8000068c:	b2 4f 00 91       	ear	%r9,%a1
+# IE against global var
+ +80000690:	e3 30 d0 00 00 04 	lg	%r3,0\(%r13\)
+ +80000696:	e3 33 c0 00 00 04 	lg	%r3,0\(%r3,%r12\)
+ +8000069c:	41 33 90 00       	la	%r3,0\(%r3,%r9\)
+# IE -> LE against global var defined in exec
+ +800006a0:	e3 30 d0 08 00 04 	lg	%r3,8\(%r13\)
+ +800006a6:	eb 43 00 00 00 0d 	sllg	%r4,%r3,0
+ +800006ac:	41 54 90 00       	la	%r5,0\(%r4,%r9\)
+# IE -> LE against local var
+ +800006b0:	e3 30 d0 10 00 04 	lg	%r3,16\(%r13\)
+ +800006b6:	eb 43 00 00 00 0d 	sllg	%r4,%r3,0
+ +800006bc:	41 54 90 00       	la	%r5,0\(%r4,%r9\)
+# IE -> LE against hidden but not local var
+ +800006c0:	e3 30 d0 18 00 04 	lg	%r3,24\(%r13\)
+ +800006c6:	eb 43 00 00 00 0d 	sllg	%r4,%r3,0
+ +800006cc:	41 54 90 00       	la	%r5,0\(%r4,%r9\)
+# LE, global var defined in exec
+ +800006d0:	e3 40 d0 20 00 04 	lg	%r4,32\(%r13\)
+ +800006d6:	41 54 90 00       	la	%r5,0\(%r4,%r9\)
+# function epilog
+ +800006da:	eb 6e f0 d0 00 04 	lmg	%r6,%r14,208\(%r15\)
+ +800006e0:	07 fe             	br	%r14
+ +800006e2:	07 07             	bcr	0,%r7
diff -urN src/ld/testsuite/ld-s390/tlsbin_64.rd src-s390/ld/testsuite/ld-s390/tlsbin_64.rd
--- src/ld/testsuite/ld-s390/tlsbin_64.rd	Thu Jan  1 01:00:00 1970
+++ src-s390/ld/testsuite/ld-s390/tlsbin_64.rd	Thu Jan 23 23:23:13 2003
@@ -0,0 +1,156 @@
+#source: tlsbinpic.s
+#source: tlsbin.s
+#as: -m64 -Aesame
+#ld: -shared -melf64_s390
+#readelf: -Ssrl
+#target: s390x-*-*
+
+There are 19 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+80000458 0+458 0+28c 00 +AX +0 +0 +4
+  \[ 9\] .data +.*
+  \[10\] .tdata +PROGBITS +0+800016e8 0+6e8 0+60 00 WAT +0 +0 +1
+  \[11\] .tbss +NOBITS +0+80001748 0+748 0+40 00 WAT +0 +0 +1
+  \[12\] .dynamic +DYNAMIC +0+80001748 0+748 0+140 10 +WA +4 +0 +8
+  \[13\] .got +PROGBITS +0+80001888 0+888 0+78 08 +WA +0 +0 +8
+  \[14\] .sbss +.*
+  \[15\] .bss +.*
+  \[16\] .shstrtab +.*
+  \[17\] .symtab +.*
+  \[18\] .strtab +.*
+Key to Flags:
+.*
+.*
+.*
+
+Elf file type is EXEC \(Executable file\)
+Entry point 0x80000644
+There are 6 program headers, starting at offset [0-9]+
+
+Program Headers:
+  Type +Offset +VirtAddr +PhysAddr +FileSiz +MemSiz +Flg Align
+  PHDR +0x0+40 0x0+80000040 0x0+80000040 0x0+150 0x0+150 R E 0x8
+  INTERP +0x0+190 0x0+80000190 0x0+80000190 0x0+11 0x0+11 R +0x1
+.*Requesting program interpreter.*
+  LOAD +0x0+ 0x0+80000000 0x0+80000000 0x0+6e4 0x0+6e4 R E 0x1000
+  LOAD +0x0+6e8 0x0+800016e8 0x0+800016e8 0x0+218 0x0+218 RW  0x1000
+  DYNAMIC +0x0+748 0x0+80001748 0x0+80001748 0x0+140 0x0+140 RW  0x8
+  TLS +0x0+6e8 0x0+800016e8 0x0+800016e8 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 0x[0-9a-z]+ contains 4 entries:
+ +Offset +Info +Type +Symbol's Value +Symbol's Name \+ Addend
+[0-9a-z]+ +0+10+38 R_390_TLS_TPOFF +0+ sG3 \+ 0
+[0-9a-z]+ +0+30+38 R_390_TLS_TPOFF +0+ sG2 \+ 0
+[0-9a-z]+ +0+60+38 R_390_TLS_TPOFF +0+ sG6 \+ 0
+[0-9a-z]+ +0+70+38 R_390_TLS_TPOFF +0+ sG1 \+ 0
+
+Relocation section '.rela.plt' at offset 0x40+ contains 1 entries:
+ +Offset +Info +Type +Symbol's Value +Symbol's Name \+ Addend
+[0-9a-z]+ +0+40+b R_390_JMP_SLOT +0+80+438 __tls_get_offset \+ 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 sG3
+ +2: [0-9a-z]+ +0 OBJECT +GLOBAL DEFAULT +ABS _DYNAMIC
+ +3: 0+ +0 TLS +GLOBAL DEFAULT +UND sG2
+ +4: [0-9a-z]+ +0 FUNC +GLOBAL DEFAULT +UND __tls_get_offset
+ +5: [0-9a-z]+ +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-9a-z]+ +0 NOTYPE +GLOBAL DEFAULT +ABS _edata
+ +9: [0-9a-z]+ +0 OBJECT +GLOBAL DEFAULT +ABS _GLOBAL_OFFSET_TABLE_
+ +10: [0-9a-z]+ +0 NOTYPE +GLOBAL DEFAULT +ABS _end
+
+Symbol table '.symtab' contains 71 entries:
+ +Num: +Value +Size Type +Bind +Vis +Ndx Name
+ +0: 0+ +0 NOTYPE +LOCAL +DEFAULT +UND 
+ +1: [0-9a-z]+ +0 SECTION LOCAL +DEFAULT +1 
+ +2: [0-9a-z]+ +0 SECTION LOCAL +DEFAULT +2 
+ +3: [0-9a-z]+ +0 SECTION LOCAL +DEFAULT +3 
+ +4: [0-9a-z]+ +0 SECTION LOCAL +DEFAULT +4 
+ +5: [0-9a-z]+ +0 SECTION LOCAL +DEFAULT +5 
+ +6: [0-9a-z]+ +0 SECTION LOCAL +DEFAULT +6 
+ +7: [0-9a-z]+ +0 SECTION LOCAL +DEFAULT +7 
+ +8: [0-9a-z]+ +0 SECTION LOCAL +DEFAULT +8 
+ +9: [0-9a-z]+ +0 SECTION LOCAL +DEFAULT +9 
+ +10: [0-9a-z]+ +0 SECTION LOCAL +DEFAULT +10 
+ +11: [0-9a-z]+ +0 SECTION LOCAL +DEFAULT +11 
+ +12: [0-9a-z]+ +0 SECTION LOCAL +DEFAULT +12 
+ +13: [0-9a-z]+ +0 SECTION LOCAL +DEFAULT +13 
+ +14: [0-9a-z]+ +0 SECTION LOCAL +DEFAULT +14 
+ +15: [0-9a-z]+ +0 SECTION LOCAL +DEFAULT +15 
+ +16: [0-9a-z]+ +0 SECTION LOCAL +DEFAULT +16 
+ +17: [0-9a-z]+ +0 SECTION LOCAL +DEFAULT +17 
+ +18: [0-9a-z]+ +0 SECTION LOCAL +DEFAULT +18 
+ +19: 0+20 +0 TLS +LOCAL +DEFAULT +10 sl1
+ +20: 0+24 +0 TLS +LOCAL +DEFAULT +10 sl2
+ +21: 0+28 +0 TLS +LOCAL +DEFAULT +10 sl3
+ +22: 0+2c +0 TLS +LOCAL +DEFAULT +10 sl4
+ +23: 0+30 +0 TLS +LOCAL +DEFAULT +10 sl5
+ +24: 0+34 +0 TLS +LOCAL +DEFAULT +10 sl6
+ +25: 0+38 +0 TLS +LOCAL +DEFAULT +10 sl7
+ +26: 0+3c +0 TLS +LOCAL +DEFAULT +10 sl8
+ +27: 0+80 +0 TLS +LOCAL +DEFAULT +11 bl1
+ +28: 0+84 +0 TLS +LOCAL +DEFAULT +11 bl2
+ +29: 0+88 +0 TLS +LOCAL +DEFAULT +11 bl3
+ +30: 0+8c +0 TLS +LOCAL +DEFAULT +11 bl4
+ +31: 0+90 +0 TLS +LOCAL +DEFAULT +11 bl5
+ +32: 0+94 +0 TLS +LOCAL +DEFAULT +11 bl6
+ +33: 0+98 +0 TLS +LOCAL +DEFAULT +11 bl7
+ +34: 0+9c +0 TLS +LOCAL +DEFAULT +11 bl8
+ +35: 0+ +0 TLS +GLOBAL DEFAULT +UND sG3
+ +36: 0+1c +0 TLS +GLOBAL DEFAULT +10 sg8
+ +37: 0+7c +0 TLS +GLOBAL DEFAULT +11 bg8
+ +38: 0+74 +0 TLS +GLOBAL DEFAULT +11 bg6
+ +39: 0+68 +0 TLS +GLOBAL DEFAULT +11 bg3
+ +40: [0-9a-z]+ +0 OBJECT +GLOBAL DEFAULT +ABS _DYNAMIC
+ +41: 0+8 +0 TLS +GLOBAL DEFAULT +10 sg3
+ +42: 0+48 +0 TLS +GLOBAL HIDDEN +10 sh3
+ +43: 0+ +0 TLS +GLOBAL DEFAULT +UND sG2
+ +44: 0+c +0 TLS +GLOBAL DEFAULT +10 sg4
+ +45: 0+10 +0 TLS +GLOBAL DEFAULT +10 sg5
+ +46: 0+70 +0 TLS +GLOBAL DEFAULT +11 bg5
+ +47: 0+58 +0 TLS +GLOBAL HIDDEN +10 sh7
+ +48: 0+5c +0 TLS +GLOBAL HIDDEN +10 sh8
+ +49: [0-9a-z]+ +0 FUNC +GLOBAL DEFAULT +UND __tls_get_offset
+ +50: 0+ +0 TLS +GLOBAL DEFAULT +10 sg1
+ +51: [0-9a-z]+ +0 FUNC +GLOBAL DEFAULT +8 _start
+ +52: 0+4c +0 TLS +GLOBAL HIDDEN +10 sh4
+ +53: 0+78 +0 TLS +GLOBAL DEFAULT +11 bg7
+ +54: 0+50 +0 TLS +GLOBAL HIDDEN +10 sh5
+ +55: [0-9a-z]+ +0 NOTYPE +GLOBAL DEFAULT +ABS __bss_start
+ +56: 0+ +0 TLS +GLOBAL DEFAULT +UND sG6
+ +57: [0-9a-z]+ +0 FUNC +GLOBAL DEFAULT +8 fn2
+ +58: 0+4 +0 TLS +GLOBAL DEFAULT +10 sg2
+ +59: 0+ +0 TLS +GLOBAL DEFAULT +UND sG1
+ +60: 0+40 +0 TLS +GLOBAL HIDDEN +10 sh1
+ +61: 0+14 +0 TLS +GLOBAL DEFAULT +10 sg6
+ +62: 0+18 +0 TLS +GLOBAL DEFAULT +10 sg7
+ +63: [0-9a-z]+ +0 NOTYPE +GLOBAL DEFAULT +ABS _edata
+ +64: [0-9a-z]+ +0 OBJECT +GLOBAL DEFAULT +ABS _GLOBAL_OFFSET_TABLE_
+ +65: 0+80+190+ +0 NOTYPE +GLOBAL DEFAULT +ABS _end
+ +66: 0+44 +0 TLS +GLOBAL HIDDEN +10 sh2
+ +67: 0+54 +0 TLS +GLOBAL HIDDEN +10 sh6
+ +68: 0+64 +0 TLS +GLOBAL DEFAULT +11 bg2
+ +69: 0+60 +0 TLS +GLOBAL DEFAULT +11 bg1
+ +70: 0+6c +0 TLS +GLOBAL DEFAULT +11 bg4
diff -urN src/ld/testsuite/ld-s390/tlsbin_64.s src-s390/ld/testsuite/ld-s390/tlsbin_64.s
--- src/ld/testsuite/ld-s390/tlsbin_64.s	Thu Jan  1 01:00:00 1970
+++ src-s390/ld/testsuite/ld-s390/tlsbin_64.s	Thu Jan 23 23:23:13 2003
@@ -0,0 +1,75 @@
+	.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:
+	/* Function prolog */
+	stm	%r6,%r14,24(%r15)
+	bras	%r13,.LTN1
+	/* Literal pool */
+.LT1:
+.LC0:
+	.quad	sG6@indntpoff
+.LC1:
+	.quad	bg6@indntpoff
+.LC2:
+	.quad	bl6@indntpoff
+.LC3:
+	.quad	sh6@indntpoff
+.LC4:
+	.quad	sg3@indntpoff
+.LTN1:
+	/* Function prolog */
+	lgr	%r14,%r15
+	aghi	%r15,-160
+	stg	%r14,0(%r14)
+
+	/* Extract TCB */
+	ear	%r9,%a0
+	sllg	%r9,%r4,32
+	ear	%r9,%a1
+
+	/* IE against global var  */
+	lg	%r3,.LC0-.LT1(%r13)
+	lg	%r3,0(%r3,%r12):tls_load:sG6
+	la	%r3,0(%r3,%r9)
+
+	/* IE -> LE against global var defined in exec  */
+	lg	%r3,.LC1-.LT1(%r13)
+	lg	%r4,0(%r3,%r12):tls_load:bg6
+	la	%r5,0(%r4,%r9)
+
+	/* IE -> LE against local var  */
+	lg	%r3,.LC2-.LT1(%r13)
+	lg	%r4,0(%r3,%r12):tls_load:bl6
+	la	%r5,0(%r4,%r9)
+
+	/* IE -> LE against hidden but not local var  */
+	lg	%r3,.LC3-.LT1(%r13)
+	lg	%r4,0(%r3,%r12):tls_load:sh6
+	la	%r5,0(%r4,%r9)
+
+	/* LE, global var defined in exec  */
+	lg	%r4,.LC4-.LT1(%r13)
+	la	%r5,0(%r4,%r9)
+
+	/* Function epilog */
+	lmg	%r6,%r14,208(%r15)
+	br	%r14
diff -urN src/ld/testsuite/ld-s390/tlsbin_64.sd src-s390/ld/testsuite/ld-s390/tlsbin_64.sd
--- src/ld/testsuite/ld-s390/tlsbin_64.sd	Thu Jan  1 01:00:00 1970
+++ src-s390/ld/testsuite/ld-s390/tlsbin_64.sd	Thu Jan 23 23:23:13 2003
@@ -0,0 +1,18 @@
+#source: tlsbinpic_64.s
+#source: tlsbin_64.s
+#as: -m64 -Aesame
+#ld: -shared -melf64_s390
+#objdump: -sj.got
+#target: s390x-*-*
+
+.*:     file format elf64-s390
+
+Contents of section .got:
+ 80001888 [0-9a-f]+ [0-9a-f]+ 00000000 00000000  .*
+ 80001898 00000000 00000000 [0-9a-f]+ [0-9a-f]+  .*
+ 800018a8 ffffffff ffffff88 00000000 00000000  .*
+ 800018b8 00000000 00000000 ffffffff ffffff68  .*
+ 800018c8 ffffffff ffffffa8 00000000 00000000  .*
+ 800018d8 00000000 00000000 00000000 00000000  .*
+ 800018e8 00000000 00000000 00000000 00000000  .*
+ 800018f8 00000000 00000000                    .*
diff -urN src/ld/testsuite/ld-s390/tlsbin_64.td src-s390/ld/testsuite/ld-s390/tlsbin_64.td
--- src/ld/testsuite/ld-s390/tlsbin_64.td	Thu Jan  1 01:00:00 1970
+++ src-s390/ld/testsuite/ld-s390/tlsbin_64.td	Thu Jan 23 23:23:13 2003
@@ -0,0 +1,16 @@
+#source: tlsbinpic_64.s
+#source: tlsbin_64.s
+#as: -m64 -Aesame
+#ld: -shared -melf64_s390
+#objdump: -sj.tdata
+#target: s390x-*-*
+
+.*:     file format elf64-s390
+
+Contents of section .tdata:
+ 800016e8 00000011 00000012 00000013 00000014  .*
+ 800016f8 00000015 00000016 00000017 00000018  .*
+ 80001708 00000041 00000042 00000043 00000044  .*
+ 80001718 00000045 00000046 00000047 00000048  .*
+ 80001728 00000101 00000102 00000103 00000104  .*
+ 80001738 00000105 00000106 00000107 00000108  .*
diff -urN src/ld/testsuite/ld-s390/tlsbinpic.s src-s390/ld/testsuite/ld-s390/tlsbinpic.s
--- src/ld/testsuite/ld-s390/tlsbinpic.s	Thu Jan  1 01:00:00 1970
+++ src-s390/ld/testsuite/ld-s390/tlsbinpic.s	Thu Jan 23 23:23:13 2003
@@ -0,0 +1,168 @@
+	.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
+	.hidden sh1, sh2
+sg1:	.long 17
+sg2:	.long 18
+sg3:	.long 19
+sg4:	.long 20
+sg5:	.long 21
+sg6:	.long 22
+sg7:	.long 23
+sg8:	.long 24
+sl1:	.long 65
+sl2:	.long 66
+sl3:	.long 67
+sl4:	.long 68
+sl5:	.long 69
+sl6:	.long 70
+sl7:	.long 71
+sl8:	.long 72
+sh1:	.long 257
+sh2:	.long 258
+sh3:	.long 259
+sh4:	.long 260
+sh5:	.long 261
+sh6:	.long 262
+sh7:	.long 263
+sh8:	.long 264
+	.text
+	.globl	fn2
+	.type	fn2,@function
+fn2:
+	/* Function prolog */
+	stm	%r6,%r14,24(%r15)
+	bras	%r13,.LTN1
+	/* Literal pool */
+.LT1:
+.LC0:
+	.long	_GLOBAL_OFFSET_TABLE_-.LT1
+.LC1:
+	.long	__tls_get_offset@plt-.LT1
+.LC2:
+	.long	sG1@tlsgd
+.LC3:
+	.long	sG2@tlsgd
+.LC4:
+	.long	sg1@tlsgd
+.LC5:
+	.long	sl1@tlsgd
+.LC6:
+	.long	sh1@tlsgd
+.LC7:
+	.long	sl1@tlsldm
+.LC8:
+	.long	sl1@dtpoff
+.LC9:
+	.long	sl2@dtpoff
+.LC10:
+	.long	sh1@tlsldm
+.LC11:
+	.long	sh1@dtpoff
+.LC12:
+	.long	sh2@dtpoff
+.LC13:
+	.long	sG2@gotntpoff
+.LC14:
+	.long	sg1@gotntpoff
+.LC15:
+	.long	sl1@gotntpoff
+.LC16:
+	.long	sh1@gotntpoff
+.LTN1:
+	/* Function prolog */
+	lr	%r14,%r15
+	l	%r12,.LC0-.LT1(%r13)
+	ahi	%r15,-96
+	la	%r12,0(%r12,%r13)
+	st	%r14,0(%r14)
+
+	/* Extract TCB and load branch offset */
+	ear	%r9,%a0
+	l	%r7,.LC1-.LT1(%r13)
+	
+	/* GD -> IE because variable is not defined in executable */
+	l	%r2,.LC2-.LT1(%r13)
+	bas	%r14,0(%r7,%r13):tls_gdcall:sG1
+	la	%r2,0(%r2,%r9)
+
+	/* GD -> IE because variable is not defined in executable where
+	   the variable is referenced through IE too */
+	l	%r2,.LC3-.LT1(%r13)
+	bas	%r14,0(%r7,%r13):tls_gdcall:sG2
+	la	%r2,0(%r2,%r9)
+
+	/* GD -> LE with global variable defined in executable */
+	l	%r2,.LC4-.LT1(%r13)
+	bas	%r14,0(%r7,%r13):tls_gdcall:sg1
+	la	%r2,0(%r2,%r9)
+
+	/* GD -> LE with local variable defined in executable */
+	l	%r2,.LC5-.LT1(%r13)
+	bas	%r14,0(%r7,%r13):tls_gdcall:sl1
+	la	%r2,0(%r2,%r9)
+
+	/* GD -> LE with hidden variable defined in executable */
+	l	%r2,.LC6-.LT1(%r13)
+	bas	%r14,0(%r7,%r13):tls_gdcall:sh1
+	la	%r2,0(%r2,%r9)
+
+	/* LD -> LE */
+	l	%r2,.LC7-.LT1(%r13)
+	bas	%r14,0(%r7,%r13):tls_ldcall:sl1
+	la	%r3,0(%r2,%r9)
+	l	%r4,.LC8-.LT1(%r13)
+	la	%r5,0(%r4,%r3)
+	l	%r4,.LC9-.LT1(%r13)
+	la	%r5,0(%r4,%r3)
+
+	/* LD -> LE against hidden variables */
+	l	%r2,.LC10-.LT1(%r13)
+	bas	%r14,0(%r7,%r13):tls_ldcall:sh1
+	la	%r3,0(%r2,%r9)
+	l	%r4,.LC11-.LT1(%r13)
+	la	%r5,0(%r4,%r3)
+	l	%r4,.LC12-.LT1(%r13)
+	la	%r5,0(%r4,%r3)
+
+	/* IE against global var  */
+	l	%r3,.LC13-.LT1(%r13)
+	l	%r3,0(%r3,%r12):tls_load:sG2
+	l	%r3,0(%r3,%r9)
+
+	/* IE -> LE against global var defined in exec */
+	l	%r3,.LC14-.LT1(%r13)
+	l	%r4,0(%r3,%r12):tls_load:sg1
+	la	%r5,0(%r4,%r9)
+
+	/* IE -> LE against local var */
+	l	%r3,.LC15-.LT1(%r13)
+	l	%r4,0(%r3,%r12):tls_load:sl1
+	la	%r5,0(%r4,%r9)
+
+	/* IE -> LE against hidden var */
+	l	%r3,.LC16-.LT1(%r13)
+	l	%r4,0(%r3,%r12):tls_load:sh1
+	la	%r5,0(%r4,%r9)
+
+	/* IE against global var with small got access (no optimization) */
+	l	%r3,sG3@gotntpoff(%r12)
+	la	%r3,0(%r3,%r9)
+
+	/* IE against global var defined in exec with small got access
+	   (no optimization) */
+	l	%r3,sg3@gotntpoff(%r12)
+	la	%r3,0(%r3,%r9)
+
+	/* IE against local var with small got access (no optimization) */
+	l	%r3,sl3@gotntpoff(%r12)
+	la	%r3,0(%r3,%r9)
+
+	/* IE against hidden var with small got access (no optimization) */
+	l	%r3,sh3@gotntpoff(%r12)
+	la	%r3,0(%r3,%r9)
+
+	/* Function epilog */
+	lm	%r6,%r14,120(%r15)
+	br	%r14
diff -urN src/ld/testsuite/ld-s390/tlsbinpic_64.s src-s390/ld/testsuite/ld-s390/tlsbinpic_64.s
--- src/ld/testsuite/ld-s390/tlsbinpic_64.s	Thu Jan  1 01:00:00 1970
+++ src-s390/ld/testsuite/ld-s390/tlsbinpic_64.s	Thu Jan 23 23:23:13 2003
@@ -0,0 +1,184 @@
+	.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
+	.hidden sh1, sh2
+sg1:	.long 17
+sg2:	.long 18
+sg3:	.long 19
+sg4:	.long 20
+sg5:	.long 21
+sg6:	.long 22
+sg7:	.long 23
+sg8:	.long 24
+sl1:	.long 65
+sl2:	.long 66
+sl3:	.long 67
+sl4:	.long 68
+sl5:	.long 69
+sl6:	.long 70
+sl7:	.long 71
+sl8:	.long 72
+sh1:	.long 257
+sh2:	.long 258
+sh3:	.long 259
+sh4:	.long 260
+sh5:	.long 261
+sh6:	.long 262
+sh7:	.long 263
+sh8:	.long 264
+	.text
+	.globl	fn2
+	.type	fn2,@function
+fn2:
+	/* Function prolog */
+	stmg	%r6,%r14,48(%r15)
+	bras	%r13,.LTN1
+	/* Literal pool */
+.LT1:
+.LC2:
+	.quad	sG1@tlsgd
+.LC3:
+	.quad	sG2@tlsgd
+.LC4:
+	.quad	sg1@tlsgd
+.LC5:
+	.quad	sl1@tlsgd
+.LC6:
+	.quad	sh1@tlsgd
+.LC7:
+	.quad	sl1@tlsldm
+.LC8:
+	.quad	sl1@dtpoff
+.LC9:
+	.quad	sl2@dtpoff
+.LC10:
+	.quad	sh1@tlsldm
+.LC11:
+	.quad	sh1@dtpoff
+.LC12:
+	.quad	sh2@dtpoff
+.LC13:
+	.quad	sG2@gotntpoff
+.LC14:
+	.quad	sg1@gotntpoff
+.LC15:
+	.quad	sl1@gotntpoff
+.LC16:
+	.quad	sh1@gotntpoff
+.LTN1:
+	/* Function prolog */
+	lgr	%r14,%r15
+	aghi	%r15,-160
+	larl	%r12,_GLOBAL_OFFSET_TABLE_
+	stg	%r14,0(%r14)
+
+	/* Extract TCB */
+	ear	%r9,%a0
+	sllg	%r9,%r4,32
+	ear	%r9,%a1
+
+	/* GD -> IE because variable is not defined in executable */
+	lg	%r12,.LC2-.LT1(%r13)
+	brasl	%r14,__tls_get_offset@plt:tls_gdcall:sG1
+	la	%r2,0(%r2,%r9)
+
+	/* GD -> IE because variable is not defined in executable where
+	   the variable is referenced through IE too */
+	lg	%r2,.LC3-.LT1(%r13)
+	brasl	%r14,__tls_get_offset@plt:tls_gdcall:sG2
+	la	%r2,0(%r2,%r9)
+
+	/* GD -> LE with global variable defined in executable */
+	lg	%r2,.LC4-.LT1(%r13)
+	brasl	%r14,__tls_get_offset@plt:tls_gdcall:sg1
+	la	%r2,0(%r2,%r9)
+
+	/* GD -> LE with local variable defined in executable */
+	lg	%r2,.LC5-.LT1(%r13)
+	brasl	%r14,__tls_get_offset@plt:tls_gdcall:sl1
+	la	%r2,0(%r2,%r9)
+
+	/* GD -> LE with hidden variable defined in executable */
+	lg	%r2,.LC6-.LT1(%r13)
+	brasl	%r14,__tls_get_offset@plt:tls_gdcall:sh1
+	la	%r2,0(%r2,%r9)
+
+	/* LD -> LE */
+	lg	%r2,.LC7-.LT1(%r13)
+	brasl	%r14,__tls_get_offset@plt:tls_ldcall:sl1
+	la	%r3,0(%r2,%r9)
+	lg	%r4,.LC8-.LT1(%r13)
+	la	%r5,0(%r4,%r3)
+	lg	%r4,.LC9-.LT1(%r13)
+	la	%r5,0(%r4,%r3)
+
+	/* LD -> LE against hidden variables */
+	lg	%r2,.LC10-.LT1(%r13)
+	brasl	%r14,__tls_get_offset@plt:tls_ldcall:sh1
+	la	%r3,0(%r2,%r9)
+	lg	%r4,.LC11-.LT1(%r13)
+	la	%r5,0(%r4,%r3)
+	lg	%r4,.LC12-.LT1(%r13)
+	la	%r5,0(%r4,%r3)
+
+	/* IE against global var  */
+	lg	%r3,.LC13-.LT1(%r13)
+	lg	%r3,0(%r3,%r12):tls_load:sG2
+	la	%r3,0(%r3,%r9)
+
+	/* IE -> LE against global var defined in exec */
+	lg	%r3,.LC14-.LT1(%r13)
+	lg	%r4,0(%r3,%r12):tls_load:sg1
+	la	%r5,0(%r4,%r9)
+
+	/* IE -> LE against local var */
+	lg	%r3,.LC15-.LT1(%r13)
+	lg	%r4,0(%r3,%r12):tls_load:sl2
+	la	%r5,0(%r4,%r9)
+
+	/* IE -> LE against hidden var */
+	lg	%r3,.LC16-.LT1(%r13)
+	lg	%r4,0(%r3,%r12):tls_load:sh1
+	la	%r5,0(%r4,%r9)
+
+	/* IE against global var with larl got access */
+	larl	%r3,sG3@indntpoff
+	lg	%r3,0(%r3,%r12):tls_load:sG3
+	la	%r3,0(%r3,%r9)
+
+	/* IE against global var defined in exec with larl got access */
+	larl	%r3,sg3@indntpoff
+	lg	%r4,0(%r3,%r12):tls_load:sg3
+	la	%r5,0(%r4,%r9)
+
+	/* IE against local var with larl got access */
+	larl	%r3,sl3@indntpoff
+	lg	%r4,0(%r3,%r12):tls_load:sl3
+	la	%r5,0(%r4,%r9)
+	
+	/* IE against hidden var with larl got access */
+	larl	%r3,sh3@indntpoff
+	lg	%r4,0(%r3,%r12):tls_load:sh3
+	la	%r5,0(%r4,%r9)
+
+	/* IE against global var with small got access (no optimization) */
+	lg	%r3,sG3@gotntpoff(%r12)
+	la	%r3,0(%r3,%r9)
+
+	/* IE against global var defined in exec with small got access
+	   (no optimization) */
+	lg	%r3,sg3@gotntpoff(%r12)
+	la	%r3,0(%r3,%r9)
+
+	/* IE against local var with small got access (no optimization) */
+	lg	%r3,sl3@gotntpoff(%r12)
+	la	%r3,0(%r3,%r9)
+
+	/* IE against hidden var with small got access (no optimization) */
+	lg	%r3,sh3@gotntpoff(%r12)
+	la	%r3,0(%r3,%r9)
+	
+	/* Function epilog */
+	lmg	%r6,%r14,208(%r15)
+	br	%r14
diff -urN src/ld/testsuite/ld-s390/tlslib.s src-s390/ld/testsuite/ld-s390/tlslib.s
--- src/ld/testsuite/ld-s390/tlslib.s	Thu Jan  1 01:00:00 1970
+++ src-s390/ld/testsuite/ld-s390/tlslib.s	Thu Jan 23 23:23:13 2003
@@ -0,0 +1,17 @@
+	.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_offset
+	.type   __tls_get_offset,@function
+__tls_get_offset:
+	br	%r14
diff -urN src/ld/testsuite/ld-s390/tlslib_64.s src-s390/ld/testsuite/ld-s390/tlslib_64.s
--- src/ld/testsuite/ld-s390/tlslib_64.s	Thu Jan  1 01:00:00 1970
+++ src-s390/ld/testsuite/ld-s390/tlslib_64.s	Thu Jan 23 23:23:13 2003
@@ -0,0 +1,17 @@
+	.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_offset
+	.type   __tls_get_offset,@function
+__tls_get_offset:
+	br	%r14
diff -urN src/ld/testsuite/ld-s390/tlspic.dd src-s390/ld/testsuite/ld-s390/tlspic.dd
--- src/ld/testsuite/ld-s390/tlspic.dd	Thu Jan  1 01:00:00 1970
+++ src-s390/ld/testsuite/ld-s390/tlspic.dd	Thu Jan 23 23:23:13 2003
@@ -0,0 +1,161 @@
+#source: tlspic1.s
+#source: tlspic2.s
+#as: -m31
+#ld: -shared -melf_s390
+#objdump: -dzrj.text
+#target: s390-*-*
+
+.*: +file format elf32-s390
+
+Disassembly of section .text:
+
+0+4bc <fn1>:
+# function prolog
+ +4bc:	90 6e f0 18       	stm	%r6,%r14,24\(%r15\)
+ +4c0:	a7 d5 00 30       	bras	%r13,520 <fn1\+0x64>
+# _GLOBAL_OFFSET_TABLE_-.LT1
+ +4c4:	00 00 12 78       	.long	0x00001278
+# __tls_get_addr@plt-.LT1
+ +4c8:	ff ff ff d8       	.long	0xffffffd8
+# sg1@tlsgd
+ +4cc:	00 00 00 38       	.long	0x00000038
+# sg2@tlsgd
+ +4d0:	00 00 00 48       	.long	0x00000048
+# sl1@tlsgd
+ +4d4:	00 00 00 10       	.long	0x00000010
+# sl2@tlsgd
+ +4d8:	00 00 00 18       	.long	0x00000018
+# sh1@tlsgd
+ +4dc:	00 00 00 4c       	.long	0x0000004c
+# sh2@tlsgd
+ +4e0:	00 00 00 54       	.long	0x00000054
+# sH1@tlsgd
+ +4e4:	00 00 00 28       	.long	0x00000028
+# sH2@tlsgd
+ +4e8:	00 00 00 30       	.long	0x00000030
+# sl1@tlsldm
+ +4ec:	00 00 00 20       	.long	0x00000020
+# sl1@dtpoff
+ +4f0:	00 00 00 20       	.long	0x00000020
+# sl2@dtpoff
+ +4f4:	00 00 00 24       	.long	0x00000024
+# sh1@tlsldm
+ +4f8:	00 00 00 20       	.long	0x00000020
+# sh1@dtpoff
+ +4fc:	00 00 00 40       	.long	0x00000040
+# sh2@dtpoff
+ +500:	00 00 00 44       	.long	0x00000044
+# sH1@tlsldm
+ +504:	00 00 00 20       	.long	0x00000020
+# sH1@dtpoff
+ +508:	00 00 00 60       	.long	0x00000060
+# sH2@dtpoff
+ +50c:	00 00 00 64       	.long	0x00000064
+# sg2@gotntpoff
+ +510:	00 00 00 48       	.long	0x00000048
+# sl2@gotntpoff
+ +514:	00 00 00 18       	.long	0x00000018
+# sh2@gotntpoff
+ +518:	00 00 00 54       	.long	0x00000054
+# sH2@gotntpoff
+ +51c:	00 00 00 30       	.long	0x00000030
+# function prolog
+ +520:	18 ef             	lr	%r14,%r15
+ +522:	58 c0 d0 00       	l	%r12,0\(%r13\)
+ +526:	a7 fa ff a0       	ahi	%r15,-96
+ +52a:	41 cc d0 00       	la	%r12,0\(%r12,%r13\)
+ +52e:	50 e0 e0 00       	st	%r14,0\(%r14\)
+# Extract TCB and load branch offset
+ +532:	b2 4f 00 90       	ear	%r9,%a0
+ +536:	58 70 d0 04       	l	%r7,4\(%r13\)
+# GD
+ +53a:	58 20 d0 08       	l	%r2,8\(%r13\)
+ +53e:	4d e7 d0 00       	bas	%r14,0\(%r7,%r13\)
+ +542:	41 22 90 00       	la	%r2,0\(%r2,%r9\)
+# GD -> IE because variable is referenced through IE too
+ +546:	58 20 d0 0c       	l	%r2,12\(%r13\)
+ +54a:	58 22 c0 00       	l	%r2,0\(%r2,%r12\)
+ +54e:	41 22 90 00       	la	%r2,0\(%r2,%r9\)
+# GD against local variable
+ +552:	58 20 d0 10       	l	%r2,16\(%r13\)
+ +556:	4d e7 d0 00       	bas	%r14,0\(%r7,%r13\)
+ +55a:	41 22 90 00       	la	%r2,0\(%r2,%r9\)
+# GD -> IE against local variable referenced through IE too
+ +55e:	58 20 d0 14       	l	%r2,20\(%r13\)
+ +562:	58 22 c0 00       	l	%r2,0\(%r2,%r12\)
+ +566:	41 22 90 00       	la	%r2,0\(%r2,%r9\)
+# GD against hidden and local variable
+ +56a:	58 20 d0 18       	l	%r2,24\(%r13\)
+ +56e:	4d e7 d0 00       	bas	%r14,0\(%r7,%r13\)
+ +572:	41 22 90 00       	la	%r2,0\(%r2,%r9\)
+# GD -> IE against hidden and local variable referenced through
+# IE too
+ +576:	58 20 d0 1c       	l	%r2,28\(%r13\)
+ +57a:	58 22 c0 00       	l	%r2,0\(%r2,%r12\)
+ +57e:	41 22 90 00       	la	%r2,0\(%r2,%r9\)
+# GD against hidden but not local variable
+ +582:	58 20 d0 20       	l	%r2,32\(%r13\)
+ +586:	4d e7 d0 00       	bas	%r14,0\(%r7,%r13\)
+ +58a:	41 22 90 00       	la	%r2,0\(%r2,%r9\)
+# GD -> IE against hidden but not local variable referenced through
+# IE too
+ +58e:	58 20 d0 24       	l	%r2,36\(%r13\)
+ +592:	58 22 c0 00       	l	%r2,0\(%r2,%r12\)
+ +596:	41 22 90 00       	la	%r2,0\(%r2,%r9\)
+# LD
+ +59a:	58 20 d0 28       	l	%r2,40\(%r13\)
+ +59e:	4d e7 d0 00       	bas	%r14,0\(%r7,%r13\)
+ +5a2:	41 32 90 00       	la	%r3,0\(%r2,%r9\)
+ +5a6:	58 40 d0 2c       	l	%r4,44\(%r13\)
+ +5aa:	41 54 30 00       	la	%r5,0\(%r4,%r3\)
+ +5ae:	58 40 d0 30       	l	%r4,48\(%r13\)
+ +5b2:	41 54 30 00       	la	%r5,0\(%r4,%r3\)
+# LD against hidden and local variables
+ +5b6:	58 20 d0 34       	l	%r2,52\(%r13\)
+ +5ba:	4d e7 d0 00       	bas	%r14,0\(%r7,%r13\)
+ +5be:	41 32 90 00       	la	%r3,0\(%r2,%r9\)
+ +5c2:	58 40 d0 38       	l	%r4,56\(%r13\)
+ +5c6:	41 54 30 00       	la	%r5,0\(%r4,%r3\)
+ +5ca:	58 40 d0 34       	l	%r4,52\(%r13\)
+ +5ce:	41 55 30 00       	la	%r5,0\(%r5,%r3\)
+# LD against hidden but not local variables
+ +5d2:	58 20 d0 40       	l	%r2,64\(%r13\)
+ +5d6:	4d e7 d0 00       	bas	%r14,0\(%r7,%r13\)
+ +5da:	41 32 90 00       	la	%r3,0\(%r2,%r9\)
+ +5de:	58 30 d0 44       	l	%r3,68\(%r13\)
+ +5e2:	41 54 30 00       	la	%r5,0\(%r4,%r3\)
+ +5e6:	58 40 d0 48       	l	%r4,72\(%r13\)
+ +5ea:	41 54 30 00       	la	%r5,0\(%r4,%r3\)
+# IE against global var
+ +5ee:	58 30 d0 4c       	l	%r3,76\(%r13\)
+ +5f2:	58 33 c0 00       	l	%r3,0\(%r3,%r12\)
+ +5f6:	41 33 30 00       	la	%r3,0\(%r3,%r3\)
+# IE against local var
+ +5fa:	58 30 d0 50       	l	%r3,80\(%r13\)
+ +5fe:	58 43 c0 00       	l	%r4,0\(%r3,%r12\)
+ +602:	41 54 30 00       	la	%r5,0\(%r4,%r3\)
+# IE against hidden and local var
+ +606:	58 30 d0 54       	l	%r3,84\(%r13\)
+ +60a:	58 43 c0 00       	l	%r4,0\(%r3,%r12\)
+ +60e:	41 54 30 00       	la	%r5,0\(%r4,%r3\)
+# IE against hidden but not local var
+ +612:	58 30 d0 58       	l	%r3,88\(%r13\)
+ +616:	58 43 c0 00       	l	%r4,0\(%r3,%r12\)
+ +61a:	41 54 30 00       	la	%r5,0\(%r4,%r3\)
+# IE against global var with small got access (no optimization)
+ +61e:	58 30 c0 34       	l	%r3,52\(%r12\)
+ +622:	41 33 90 00       	la	%r3,0\(%r3,%r9\)
+# IE against local var with small got access (no optimization)
+ +626:	58 30 c0 1c       	l	%r3,28\(%r12\)
+ +62a:	41 33 90 00       	la	%r3,0\(%r3,%r9\)
+# IE against hidden and local var with small got access
+# (no optimization)
+ +62e:	58 30 c0 40       	l	%r3,64\(%r12\)
+ +632:	41 33 90 00       	la	%r3,0\(%r3,%r9\)
+# IE against hidden but not local var with small got access
+# (no optimization)
+ +636:	58 30 c0 44       	l	%r3,68\(%r12\)
+ +63a:	41 33 90 00       	la	%r3,0\(%r3,%r9\)
+# function prolog
+ +63e:	98 6e f0 78       	lm	%r6,%r14,120\(%r15\)
+ +642:	07 fe             	br	%r14
diff -urN src/ld/testsuite/ld-s390/tlspic.rd src-s390/ld/testsuite/ld-s390/tlspic.rd
--- src/ld/testsuite/ld-s390/tlspic.rd	Thu Jan  1 01:00:00 1970
+++ src-s390/ld/testsuite/ld-s390/tlspic.rd	Thu Jan 23 23:23:13 2003
@@ -0,0 +1,165 @@
+#source: tlspic1.s
+#source: tlspic2.s
+#as: -m31
+#ld: -shared -melf_s390
+#readelf: -Ssrl
+#target: s390-*-*
+
+There are 18 section headers, starting at offset 0x[0-9a-f]+:
+
+Section Headers:
+  \[Nr\] Name +Type +Addr +Off +Size +ES Flg Lk Inf Al
+  \[ 0\] +NULL +0+ 0+ 0+ 00 +0 +0  0
+  \[ 1\] .hash +.*
+  \[ 2\] .dynsym +.*
+  \[ 3\] .dynstr +.*
+  \[ 4\] .rela.dyn +.*
+  \[ 5\] .rela.plt +.*
+  \[ 6\] .plt +.*
+  \[ 7\] .text +PROGBITS +0+4bc 0+4bc 0+188 00  AX  0 +0  4
+  \[ 8\] .data +.*
+  \[ 9\] .tdata +PROGBITS +0+1644 0+644 0+60 00 WAT  0 +0  1
+  \[10\] .tbss +NOBITS +0+16a4 0+6a4 0+20 00 WAT  0 +0  1
+  \[11\] .dynamic +DYNAMIC +0+16a4 0+6a4 0+98 08  WA  3 +0  4
+  \[12\] .got +PROGBITS +0+173c 0+73c 0+58 04  WA  0 +0  4
+  \[13\] .sbss +.*
+  \[14\] .bss +.*
+  \[15\] .shstrtab +.*
+  \[16\] .symtab +.*
+  \[17\] .strtab +.*
+Key to Flags:
+.*
+.*
+.*
+
+Elf file type is DYN \(Shared object file\)
+Entry point 0x4bc
+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 0x1000
+  LOAD +0x0+644 0x0+1644 0x0+1644 0x00150 0x00150 RW  0x1000
+  DYNAMIC +0x0+6a4 0x0+16a4 0x0+16a4 0x0+98 0x0+98 RW  0x4
+  TLS +0x0+644 0x0+1644 0x0+1644 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 0x3c8 contains 14 entries:
+ Offset +Info +Type +Sym.Value  Sym. Name \+ Addend
+[0-9a-f]+  0+36 R_390_TLS_DTPMOD +0+
+[0-9a-f]+  0+38 R_390_TLS_TPOFF +0+24
+[0-9a-f]+  0+38 R_390_TLS_TPOFF +0+30
+[0-9a-f]+  0+36 R_390_TLS_DTPMOD +0+
+[0-9a-f]+  0+36 R_390_TLS_DTPMOD +0+
+[0-9a-f]+  0+38 R_390_TLS_TPOFF +0+64
+[0-9a-f]+  0+38 R_390_TLS_TPOFF +0+50
+[0-9a-f]+  0+38 R_390_TLS_TPOFF +0+70
+[0-9a-f]+  0+36 R_390_TLS_DTPMOD +0+
+[0-9a-f]+  0+38 R_390_TLS_TPOFF +0+44
+[0-9a-f]+  0+1338 R_390_TLS_TPOFF +0+10 +sg5 \+ 0
+[0-9a-f]+  0+1536 R_390_TLS_DTPMOD  0+ +sg1 \+ 0
+[0-9a-f]+  0+1537 R_390_TLS_DTPOFF  0+ +sg1 \+ 0
+[0-9a-f]+  0+1838 R_390_TLS_TPOFF +0+4 +sg2 \+ 0
+
+Relocation section '.rela.plt' at offset 0x[0-9a-f]+ contains 1 entries:
+ Offset +Info +Type +Sym.Value  Sym. Name \+ Addend
+[0-9a-f]+  0+140b R_390_JMP_SLOT +0+ +__tls_get_offset \+ 0
+
+Symbol table '.dynsym' contains 30 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+1c +0 TLS +GLOBAL DEFAULT +9 sg8
+ +16: [0-9a-f]+ +0 OBJECT  GLOBAL DEFAULT  ABS _DYNAMIC
+ +17: 0+8 +0 TLS +GLOBAL DEFAULT +9 sg3
+ +18: 0+c +0 TLS +GLOBAL DEFAULT +9 sg4
+ +19: 0+10 +0 TLS +GLOBAL DEFAULT +9 sg5
+ +20: 0+ +0 NOTYPE  GLOBAL DEFAULT  UND __tls_get_offset
+ +21: 0+ +0 TLS +GLOBAL DEFAULT +9 sg1
+ +22: [0-9a-f]+ +0 FUNC +GLOBAL DEFAULT +7 fn1
+ +23: [0-9a-f]+ +0 NOTYPE  GLOBAL DEFAULT  ABS __bss_start
+ +24: 0+4 +0 TLS +GLOBAL DEFAULT +9 sg2
+ +25: 0+14 +0 TLS +GLOBAL DEFAULT +9 sg6
+ +26: 0+18 +0 TLS +GLOBAL DEFAULT +9 sg7
+ +27: [0-9a-f]+ +0 NOTYPE  GLOBAL DEFAULT  ABS _edata
+ +28: [0-9a-f]+ +0 OBJECT  GLOBAL DEFAULT  ABS _GLOBAL_OFFSET_TABLE_
+ +29: [0-9a-f]+ +0 NOTYPE  GLOBAL DEFAULT  ABS _end
+
+Symbol table '.symtab' contains 57 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 +9 sl1
+ +19: 0+24 +0 TLS +LOCAL  DEFAULT +9 sl2
+ +20: 0+28 +0 TLS +LOCAL  DEFAULT +9 sl3
+ +21: 0+2c +0 TLS +LOCAL  DEFAULT +9 sl4
+ +22: 0+30 +0 TLS +LOCAL  DEFAULT +9 sl5
+ +23: 0+34 +0 TLS +LOCAL  DEFAULT +9 sl6
+ +24: 0+38 +0 TLS +LOCAL  DEFAULT +9 sl7
+ +25: 0+3c +0 TLS +LOCAL  DEFAULT +9 sl8
+ +26: 0+60 +0 TLS +LOCAL  HIDDEN +10 sH1
+ +27: 0+48 +0 TLS +LOCAL  HIDDEN +9 sh3
+ +28: 0+64 +0 TLS +LOCAL  HIDDEN +10 sH2
+ +29: 0+78 +0 TLS +LOCAL  HIDDEN +10 sH7
+ +30: 0+58 +0 TLS +LOCAL  HIDDEN +9 sh7
+ +31: 0+5c +0 TLS +LOCAL  HIDDEN +9 sh8
+ +32: 0+6c +0 TLS +LOCAL  HIDDEN +10 sH4
+ +33: 0+4c +0 TLS +LOCAL  HIDDEN +9 sh4
+ +34: 0+68 +0 TLS +LOCAL  HIDDEN +10 sH3
+ +35: 0+50 +0 TLS +LOCAL  HIDDEN +9 sh5
+ +36: 0+70 +0 TLS +LOCAL  HIDDEN +10 sH5
+ +37: 0+74 +0 TLS +LOCAL  HIDDEN +10 sH6
+ +38: 0+7c +0 TLS +LOCAL  HIDDEN +10 sH8
+ +39: 0+40 +0 TLS +LOCAL  HIDDEN +9 sh1
+ +40: 0+44 +0 TLS +LOCAL  HIDDEN +9 sh2
+ +41: 0+54 +0 TLS +LOCAL  HIDDEN +9 sh6
+ +42: 0+1c +0 TLS +GLOBAL DEFAULT +9 sg8
+ +43: [0-9a-f]+ +0 OBJECT  GLOBAL DEFAULT  ABS _DYNAMIC
+ +44: 0+8 +0 TLS +GLOBAL DEFAULT +9 sg3
+ +45: 0+c +0 TLS +GLOBAL DEFAULT +9 sg4
+ +46: 0+10 +0 TLS +GLOBAL DEFAULT +9 sg5
+ +47: 0+ +0 NOTYPE  GLOBAL DEFAULT  UND __tls_get_offset
+ +48: 0+ +0 TLS +GLOBAL DEFAULT +9 sg1
+ +49: [0-9a-f]+ +0 FUNC +GLOBAL DEFAULT +7 fn1
+ +50: [0-9a-f]+ +0 NOTYPE  GLOBAL DEFAULT  ABS __bss_start
+ +51: 0+4 +0 TLS +GLOBAL DEFAULT +9 sg2
+ +52: 0+14 +0 TLS +GLOBAL DEFAULT +9 sg6
+ +53: 0+18 +0 TLS +GLOBAL DEFAULT +9 sg7
+ +54: [0-9a-f]+ +0 NOTYPE  GLOBAL DEFAULT  ABS _edata
+ +55: [0-9a-f]+ +0 OBJECT  GLOBAL DEFAULT  ABS _GLOBAL_OFFSET_TABLE_
+ +56: [0-9a-f]+ +0 NOTYPE  GLOBAL DEFAULT  ABS _end
diff -urN src/ld/testsuite/ld-s390/tlspic.sd src-s390/ld/testsuite/ld-s390/tlspic.sd
--- src/ld/testsuite/ld-s390/tlspic.sd	Thu Jan  1 01:00:00 1970
+++ src-s390/ld/testsuite/ld-s390/tlspic.sd	Thu Jan 23 23:23:13 2003
@@ -0,0 +1,16 @@
+#source: tlspic1.s
+#source: tlspic2.s
+#as: -m31
+#ld: -shared -melf_s390
+#objdump: -sj.got
+#target: s390-*-*
+
+.*: +file format elf32-s390
+
+Contents of section .got:
+ 173c [0-9a-f]+ 00000000 00000000 [0-9a-f]+  .*
+ 174c 00000000 00000020 00000000 00000000  .*
+ 175c 00000000 00000000 00000000 00000060  .*
+ 176c 00000000 00000000 00000000 00000000  .*
+ 177c 00000000 00000000 00000000 00000000  .*
+ 178c 00000040 00000000  +.*
diff -urN src/ld/testsuite/ld-s390/tlspic.td src-s390/ld/testsuite/ld-s390/tlspic.td
--- src/ld/testsuite/ld-s390/tlspic.td	Thu Jan  1 01:00:00 1970
+++ src-s390/ld/testsuite/ld-s390/tlspic.td	Thu Jan 23 23:23:13 2003
@@ -0,0 +1,16 @@
+#source: tlspic1.s
+#source: tlspic2.s
+#as: -m31
+#ld: -shared -melf_s390
+#objdump: -sj.tdata
+#target: s390-*-*
+
+.*: +file format elf32-s390
+
+Contents of section .tdata:
+ 1644 00000011 00000012 00000013 00000014  .*
+ 1654 00000015 00000016 00000017 00000018  .*
+ 1664 00000041 00000042 00000043 00000044  .*
+ 1674 00000045 00000046 00000047 00000048  .*
+ 1684 00000101 00000102 00000103 00000104  .*
+ 1694 00000105 00000106 00000107 00000108  .*
diff -urN src/ld/testsuite/ld-s390/tlspic1.s src-s390/ld/testsuite/ld-s390/tlspic1.s
--- src/ld/testsuite/ld-s390/tlspic1.s	Thu Jan  1 01:00:00 1970
+++ src-s390/ld/testsuite/ld-s390/tlspic1.s	Thu Jan 23 23:23:13 2003
@@ -0,0 +1,206 @@
+	.section ".tdata", "awT", @progbits
+	.globl sg1, sg2, sg3, sg4, sg5, sg6, sg7, sg8
+	.globl sh1, sh2, sh3, sh4, sh5, sh6, sh7, sh8
+	.hidden sh1, sh2, sh3, sh4, sh5, sh6, sh7, sh8
+sg1:	.long 17
+sg2:	.long 18
+sg3:	.long 19
+sg4:	.long 20
+sg5:	.long 21
+sg6:	.long 22
+sg7:	.long 23
+sg8:	.long 24
+sl1:	.long 65
+sl2:	.long 66
+sl3:	.long 67
+sl4:	.long 68
+sl5:	.long 69
+sl6:	.long 70
+sl7:	.long 71
+sl8:	.long 72
+sh1:	.long 257
+sh2:	.long 258
+sh3:	.long 259
+sh4:	.long 260
+sh5:	.long 261
+sh6:	.long 262
+sh7:	.long 263
+sh8:	.long 264
+	.text
+	.globl	fn1
+	.type	fn1,@function
+fn1:
+	/* Funtion prolog */
+	stm	%r6,%r14,24(%r15)
+	bras	%r13,.LTN1
+	/* Literal pool */
+.LT1:
+.LC0:
+	.long	_GLOBAL_OFFSET_TABLE_-.LT1
+.LC1:
+	.long	__tls_get_offset@plt-.LT1
+.LC2:
+	.long	sg1@tlsgd
+.LC3:
+	.long	sg2@tlsgd
+.LC4:
+	.long	sl1@tlsgd
+.LC5:
+	.long	sl2@tlsgd
+.LC6:
+	.long	sh1@tlsgd
+.LC7:
+	.long	sh2@tlsgd
+.LC8:
+	.long	sH1@tlsgd
+.LC9:
+	.long	sH2@tlsgd
+.LC10:
+	.long	sl1@tlsldm
+.LC11:
+	.long	sl1@dtpoff
+.LC12:
+	.long	sl2@dtpoff
+.LC13:
+	.long	sh1@tlsldm
+.LC14:
+	.long	sh1@dtpoff
+.LC15:
+	.long	sh2@dtpoff
+.LC16:
+	.long	sH1@tlsldm
+.LC17:
+	.long	sH1@dtpoff
+.LC18:
+	.long	sH2@dtpoff
+.LC19:
+	.long	sg2@gotntpoff
+.LC20:
+	.long	sl2@gotntpoff
+.LC21:
+	.long	sh2@gotntpoff
+.LC22:
+	.long	sH2@gotntpoff
+.LTN1:	
+	/* Funtion prolog */
+	lr	%r14,%r15
+	l	%r12,.LC0-.LT1(%r13)
+	ahi	%r15,-96
+	la	%r12,0(%r12,%r13)
+	st	%r14,0(%r14)
+
+	/* Extract TCB and load branch offset */
+	ear	%r9,%a0
+	l	%r7,.LC1-.LT1(%r13)
+
+	/* GD */
+	l	%r2,.LC2-.LT1(%r13)
+	bas	%r14,0(%r7,%r13):tls_gdcall:sg1
+	la	%r2,0(%r2,%r9)
+
+	/* GD -> IE because variable is referenced through IE too */
+	l	%r2,.LC3-.LT1(%r13)
+	bas	%r14,0(%r7,%r13):tls_gdcall:sg2
+	la	%r2,0(%r2,%r9)
+
+	/* GD against local variable */
+	l	%r2,.LC4-.LT1(%r13)
+	bas	%r14,0(%r7,%r13):tls_gdcall:sl1
+	la	%r2,0(%r2,%r9)
+	
+	/* GD -> IE against local variable referenced through IE too */
+	l	%r2,.LC5-.LT1(%r13)
+	bas	%r14,0(%r7,%r13):tls_gdcall:sl2
+	la	%r2,0(%r2,%r9)
+
+	/* GD against hidden and local variable */
+	l	%r2,.LC6-.LT1(%r13)
+	bas	%r14,0(%r7,%r13):tls_gdcall:sh1
+	la	%r2,0(%r2,%r9)
+		
+	/* GD -> IE against hidden and local variable referenced through
+	   IE too */
+	l	%r2,.LC7-.LT1(%r13)
+	bas	%r14,0(%r7,%r13):tls_gdcall:sh2
+	la	%r2,0(%r2,%r9)
+
+	/* GD against hidden but not local variable */
+	l	%r2,.LC8-.LT1(%r13)
+	bas	%r14,0(%r7,%r13):tls_gdcall:sH1
+	la	%r2,0(%r2,%r9)
+
+	/* GD -> IE against hidden but not local variable referenced through
+	   IE too */
+	l	%r2,.LC9-.LT1(%r13)
+	bas	%r14,0(%r7,%r13):tls_gdcall:sH2
+	la	%r2,0(%r2,%r9)
+
+	/* LD */
+	l	%r2,.LC10-.LT1(%r13)
+	bas	%r14,0(%r7,%r13):tls_ldcall:sl1
+	la	%r3,0(%r2,%r9)
+	l	%r4,.LC11-.LT1(%r13)
+	la	%r5,0(%r4,%r3)
+	l	%r4,.LC12-.LT1(%r13)
+	la	%r5,0(%r4,%r3)
+
+	/* LD against hidden and local variables */
+	l	%r2,.LC13-.LT1(%r13)
+	bas	%r14,0(%r7,%r13):tls_ldcall:sh1
+	la	%r3,0(%r2,%r9)
+	l	%r4,.LC14-.LT1(%r13)
+	la	%r5,0(%r4,%r3)
+	l	%r4,.LC13-.LT1(%r13)
+	la	%r5,0(%r5,%r3)
+	
+	/* LD against hidden but not local variables */
+	l	%r2,.LC16-.LT1(%r13)
+	bas	%r14,0(%r7,%r13):tls_ldcall:sH1
+	la	%r3,0(%r2,%r9)
+	l	%r3,.LC17-.LT1(%r13)
+	la	%r5,0(%r4,%r3)
+	l	%r4,.LC18-.LT1(%r13)
+	la	%r5,0(%r4,%r3)
+
+	/* IE against global var  */
+	l	%r3,.LC19-.LT1(%r13)
+	l	%r3,0(%r3,%r12):tls_load:sg2
+	la	%r3,0(%r3,%r3)
+
+	/* IE against local var  */
+	l	%r3,.LC20-.LT1(%r13)
+	l	%r4,0(%r3,%r12):tls_load:sl2
+	la	%r5,0(%r4,%r3)
+
+	/* IE against hidden and local var  */
+	l	%r3,.LC21-.LT1(%r13)
+	l	%r4,0(%r3,%r12):tls_load:sh2
+	la	%r5,0(%r4,%r3)
+	
+	/* IE against hidden but not local var  */
+	l	%r3,.LC22-.LT1(%r13)
+	l	%r4,0(%r3,%r12):tls_load:sH2
+	la	%r5,0(%r4,%r3)
+
+	/* IE against global var with small got access (no optimization) */
+	l	%r3,sg5@gotntpoff(%r12)
+	la	%r3,0(%r3,%r9)
+
+	/* IE against local var with small got access (no optimization) */
+	l	%r3,sl5@gotntpoff(%r12)
+	la	%r3,0(%r3,%r9)
+
+	/* IE against hidden and local var with small got access
+	   (no optimization) */
+	l	%r3,sh5@gotntpoff(%r12)
+	la	%r3,0(%r3,%r9)
+
+	/* IE against hidden but not local var with small got access
+	   (no optimization) */
+	l	%r3,sH5@gotntpoff(%r12)
+	la	%r3,0(%r3,%r9)
+
+	/* Function epilog */
+	lm	%r6,%r14,120(%r15)
+	br	%r14
+
diff -urN src/ld/testsuite/ld-s390/tlspic1_64.s src-s390/ld/testsuite/ld-s390/tlspic1_64.s
--- src/ld/testsuite/ld-s390/tlspic1_64.s	Thu Jan  1 01:00:00 1970
+++ src-s390/ld/testsuite/ld-s390/tlspic1_64.s	Thu Jan 23 23:23:13 2003
@@ -0,0 +1,222 @@
+	.section ".tdata", "awT", @progbits
+	.globl sg1, sg2, sg3, sg4, sg5, sg6, sg7, sg8
+	.globl sh1, sh2, sh3, sh4, sh5, sh6, sh7, sh8
+	.hidden sh1, sh2, sh3, sh4, sh5, sh6, sh7, sh8
+sg1:	.long 17
+sg2:	.long 18
+sg3:	.long 19
+sg4:	.long 20
+sg5:	.long 21
+sg6:	.long 22
+sg7:	.long 23
+sg8:	.long 24
+sl1:	.long 65
+sl2:	.long 66
+sl3:	.long 67
+sl4:	.long 68
+sl5:	.long 69
+sl6:	.long 70
+sl7:	.long 71
+sl8:	.long 72
+sh1:	.long 257
+sh2:	.long 258
+sh3:	.long 259
+sh4:	.long 260
+sh5:	.long 261
+sh6:	.long 262
+sh7:	.long 263
+sh8:	.long 264
+	.text
+	.globl	fn1
+	.type	fn1,@function
+fn1:
+	/* Funtion prolog */
+	stmg	%r6,%r14,48(%r15)
+	bras	%r13,.LTN1
+	/* Literal pool */
+.LT1:
+.LC2:
+	.quad	sg1@tlsgd
+.LC3:
+	.quad	sg2@tlsgd
+.LC4:
+	.quad	sl1@tlsgd
+.LC5:
+	.quad	sl2@tlsgd
+.LC6:
+	.quad	sh1@tlsgd
+.LC7:
+	.quad	sh2@tlsgd
+.LC8:
+	.quad	sH1@tlsgd
+.LC9:
+	.quad	sH2@tlsgd
+.LC10:
+	.quad	sl1@tlsldm
+.LC11:
+	.quad	sl1@dtpoff
+.LC12:
+	.quad	sl2@dtpoff
+.LC13:
+	.quad	sh1@tlsldm
+.LC14:
+	.quad	sh1@dtpoff
+.LC15:
+	.quad	sh2@dtpoff
+.LC16:
+	.quad	sH1@tlsldm
+.LC17:
+	.quad	sH1@dtpoff
+.LC18:
+	.quad	sH2@dtpoff
+.LC19:
+	.quad	sg2@gotntpoff
+.LC20:
+	.quad	sl2@gotntpoff
+.LC21:
+	.quad	sh2@gotntpoff
+.LC22:
+	.quad	sH2@gotntpoff
+.LTN1:	
+	/* Funtion prolog */
+	lgr	%r14,%r15
+	larl	%r12,_GLOBAL_OFFSET_TABLE_
+	aghi	%r15,-160
+	stg	%r14,0(%r14)
+
+	/* Extract TCB */
+	ear	%r9,%a0
+	sllg	%r9,%r4,32
+	ear	%r9,%a1
+
+	/* GD */
+	lg	%r2,.LC2-.LT1(%r13)
+	brasl	%r14,__tls_get_offset@plt:tls_gdcall:sg1
+	la	%r2,0(%r2,%r9)
+
+	/* GD -> IE because variable is referenced through IE too */
+	lg	%r2,.LC3-.LT1(%r13)
+	brasl	%r14,__tls_get_offset@plt:tls_gdcall:sg2
+	la	%r2,0(%r2,%r9)
+
+	/* GD against local variable */
+	lg	%r2,.LC4-.LT1(%r13)
+	brasl	%r14,__tls_get_offset@plt:tls_gdcall:sl1
+	la	%r2,0(%r2,%r9)
+
+	/* GD -> IE against local variable referenced through IE too */
+	lg	%r2,.LC5-.LT1(%r13)
+	brasl	%r14,__tls_get_offset@plt:tls_gdcall:sl2
+	la	%r2,0(%r2,%r9)
+
+	/* GD against hidden and local variable */
+	lg	%r2,.LC6-.LT1(%r13)
+	brasl	%r14,__tls_get_offset@plt:tls_gdcall:sh1
+	la	%r2,0(%r2,%r9)
+	
+	/* GD -> IE against hidden and local variable referenced through
+	   IE too */
+	lg	%r2,.LC7-.LT1(%r13)
+	brasl	%r14,__tls_get_offset@plt:tls_gdcall:sh2
+	la	%r2,0(%r2,%r9)
+
+	/* GD against hidden but not local variable */
+	lg	%r2,.LC8-.LT1(%r13)
+	brasl	%r14,__tls_get_offset@plt:tls_gdcall:sH1
+	la	%r2,0(%r2,%r9)
+
+	/* GD -> IE against hidden but not local variable referenced through
+	   IE too */
+	lg	%r2,.LC9-.LT1(%r13)
+	brasl	%r14,__tls_get_offset@plt:tls_gdcall:sH2
+	la	%r2,0(%r2,%r9)
+
+	/* LD */
+	lg	%r2,.LC10-.LT1(%r13)
+	brasl	%r14,__tls_get_offset@plt:tls_ldcall:sl1
+	la	%r3,0(%r2,%r9)
+	lg	%r4,.LC11-.LT1(%r13)
+	la	%r5,0(%r4,%r3)
+	lg	%r4,.LC12-.LT1(%r13)
+	la	%r5,0(%r4,%r3)
+
+	/* LD against hidden and local variables */
+	lg	%r2,.LC13-.LT1(%r13)
+	brasl	%r14,__tls_get_offset@plt:tls_ldcall:sh1
+	la	%r3,0(%r2,%r9)
+	lg	%r4,.LC14-.LT1(%r13)
+	la	%r5,0(%r4,%r3)
+	lg	%r4,.LC15-.LT1(%r13)
+	la	%r5,0(%r4,%r3)
+	
+	/* LD against hidden but not local variables */
+	lg	%r2,.LC16-.LT1(%r13)
+	brasl	%r14,__tls_get_offset@plt:tls_ldcall:sH1
+	la	%r3,0(%r2,%r9)
+	lg	%r4,.LC17-.LT1(%r13)
+	la	%r5,0(%r4,%r3)
+	lg	%r4,.LC18-.LT1(%r13)
+	la	%r5,0(%r4,%r3)
+
+	/* IE against global var  */
+	lg	%r3,.LC19-.LT1(%r13)
+	lg	%r3,0(%r3,%r12):tls_load:sg2
+	la	%r3,0(%r3,%r9)
+
+	/* IE against local var  */
+	lg	%r3,.LC20-.LT1(%r13)
+	lg	%r4,0(%r3,%r12):tls_load:sl2
+	la	%r5,0(%r4,%r9)
+
+	/* IE against hidden and local var  */
+	lg	%r3,.LC21-.LT1(%r13)
+	lg	%r4,0(%r3,%r12):tls_load:sh2
+	la	%r5,0(%r4,%r9)
+	
+	/* IE against hidden but not local var  */
+	lg	%r3,.LC22-.LT1(%r13)
+	lg	%r4,0(%r3,%r12):tls_load:sH2
+	la	%r5,0(%r4,%r9)
+
+	/* IE against global var with larl got access */
+	larl	%r3,sg5@indntpoff
+	lg	%r3,0(%r3,%r12):tls_load:sg2
+	la	%r3,0(%r3,%r9)
+
+	/* IE against local var with larl got access */
+	larl	%r3,sl5@indntpoff
+	lg	%r4,0(%r3,%r12):tls_load:sl2
+	la	%r5,0(%r4,%r9)
+
+	/* IE against hidden and local var with larl got access */
+	larl	%r3,sh5@indntpoff
+	lg	%r4,0(%r3,%r12):tls_load:sh2
+	la	%r5,0(%r4,%r9)
+	
+	/* IE against hidden but not local var with larl got access */
+	larl	%r3,sH5@indntpoff
+	lg	%r4,0(%r3,%r12):tls_load:sH2
+	la	%r5,0(%r4,%r9)
+
+	/* IE against global var with small got access (no optimization) */
+	lg	%r3,sg5@gotntpoff(%r12)
+	la	%r3,0(%r3,%r9)
+
+	/* IE against local var with small got access (no optimization) */
+	lg	%r3,sl5@gotntpoff(%r12)
+	la	%r3,0(%r3,%r9)
+
+	/* IE against hidden and local var with small got access
+	   (no optimization) */
+	lg	%r3,sh5@gotntpoff(%r12)
+	la	%r3,0(%r3,%r9)
+
+	/* IE against hidden but not local var with small got access
+	   (no optimization) */
+	lg	%r3,sH5@gotntpoff(%r12)
+	la	%r3,0(%r3,%r9)
+
+	/* Function epilog */
+	lmg	%r6,%r14,208(%r15)
+	br	%r14
+	
diff -urN src/ld/testsuite/ld-s390/tlspic2.s src-s390/ld/testsuite/ld-s390/tlspic2.s
--- src/ld/testsuite/ld-s390/tlspic2.s	Thu Jan  1 01:00:00 1970
+++ src-s390/ld/testsuite/ld-s390/tlspic2.s	Thu Jan 23 23:23:13 2003
@@ -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
diff -urN src/ld/testsuite/ld-s390/tlspic2_64.s src-s390/ld/testsuite/ld-s390/tlspic2_64.s
--- src/ld/testsuite/ld-s390/tlspic2_64.s	Thu Jan  1 01:00:00 1970
+++ src-s390/ld/testsuite/ld-s390/tlspic2_64.s	Thu Jan 23 23:23:13 2003
@@ -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
diff -urN src/ld/testsuite/ld-s390/tlspic_64.dd src-s390/ld/testsuite/ld-s390/tlspic_64.dd
--- src/ld/testsuite/ld-s390/tlspic_64.dd	Thu Jan  1 01:00:00 1970
+++ src-s390/ld/testsuite/ld-s390/tlspic_64.dd	Thu Jan 23 23:23:13 2003
@@ -0,0 +1,194 @@
+#source: tlspic1.s
+#source: tlspic2.s
+#as: -m64 -Aesame
+#ld: -shared -melf64_s390
+#objdump: -dzrj.text
+#target: s390x-*-*
+
+.*: +file format elf64-s390
+
+Disassembly of section .text:
+
+0+790 <fn1>:
+# function prolog
+ +790:	eb 6e f0 30 00 24 	stmg	%r6,%r14,48\(%r15\)
+ +796:	a7 d5 00 56       	bras	%r13,842 <fn1\+0xb2>
+# sg1@tlsgd
+ +79a:	00 00 00 00       	.long	0x00000000
+ +79e:	00 00 00 70       	.long	0x00000070
+# sg2@tlsgd
+ +7a2:	00 00 00 00       	.long	0x00000000
+ +7a6:	00 00 00 90       	.long	0x00000090
+# sl1@tlsgd
+ +7aa:	00 00 00 00       	.long	0x00000000
+ +7ae:	00 00 00 20       	.long	0x00000020
+# sl2@tlsgd
+ +7b2:	00 00 00 00       	.long	0x00000000
+ +7b6:	00 00 00 30       	.long	0x00000030
+# sh1@tlsgd
+ +7ba:	00 00 00 00       	.long	0x00000000
+ +7be:	00 00 00 98       	.long	0x00000098
+# sh2@tlsgd
+ +7c2:	00 00 00 00       	.long	0x00000000
+ +7c6:	00 00 00 a8       	.long	0x000000a8
+# sH1@tlsgd
+ +7ca:	00 00 00 00       	.long	0x00000000
+ +7ce:	00 00 00 50       	.long	0x00000050
+# sH2@tlsgd
+ +7d2:	00 00 00 00       	.long	0x00000000
+ +7d6:	00 00 00 60       	.long	0x00000060
+# sl1@tlsldm
+ +7da:	00 00 00 00       	.long	0x00000000
+ +7de:	00 00 00 40       	.long	0x00000040
+# sl1@dtpoff
+ +7e2:	00 00 00 00       	.long	0x00000000
+ +7e6:	00 00 00 20       	.long	0x00000020
+# sl2@dtpoff
+ +7ea:	00 00 00 00       	.long	0x00000000
+ +7ee:	00 00 00 24       	.long	0x00000024
+# sh1@tlsldm
+ +7f2:	00 00 00 00       	.long	0x00000000
+ +7f6:	00 00 00 40       	.long	0x00000040
+# sh1@dtpoff
+ +7fa:	00 00 00 00       	.long	0x00000000
+ +7fe:	00 00 00 40       	.long	0x00000040
+# sh2@dtpoff
+ +802:	00 00 00 00       	.long	0x00000000
+ +806:	00 00 00 44       	.long	0x00000044
+# sH1@tlsldm
+ +80a:	00 00 00 00       	.long	0x00000000
+ +80e:	00 00 00 40       	.long	0x00000040
+# sH1@dtpoff
+ +812:	00 00 00 00       	.long	0x00000000
+ +816:	00 00 00 60       	.long	0x00000060
+# sH2@dtpoff
+ +81a:	00 00 00 00       	.long	0x00000000
+ +81e:	00 00 00 64       	.long	0x00000064
+# sg2@gotntpoff
+ +822:	00 00 00 00       	.long	0x00000000
+ +826:	00 00 00 90       	.long	0x00000090
+# sl2@gotntpoff
+ +82a:	00 00 00 00       	.long	0x00000000
+ +82e:	00 00 00 30       	.long	0x00000030
+# sh2@gotntpoff
+ +832:	00 00 00 00       	.long	0x00000000
+ +836:	00 00 00 a8       	.long	0x000000a8
+# sH2@gotntpoff
+ +83a:	00 00 00 00       	.long	0x00000000
+ +83e:	00 00 00 60       	.long	0x00000060
+# function prolog
+ +842:	b9 04 00 ef       	lgr	%r14,%r15
+ +846:	c0 c0 00 00 09 a5 	larl	%r12,1b90 <_GLOBAL_OFFSET_TABLE_>
+ +84c:	a7 fb ff 60       	aghi	%r15,-160
+ +850:	e3 e0 e0 00 00 24 	stg	%r14,0\(%r14\)
+# extract TCB
+ +856:	b2 4f 00 90       	ear	%r9,%a0
+ +85a:	eb 94 00 20 00 0d 	sllg	%r9,%r4,32
+ +860:	b2 4f 00 91       	ear	%r9,%a1
+# GD
+ +864:	e3 20 d0 00 00 04 	lg	%r2,0\(%r13\)
+ +86a:	c0 e5 ff ff ff 83 	brasl	%r14,770 <sH8\+0x6f4>
+ +870:	41 22 90 00       	la	%r2,0\(%r2,%r9\)
+# GD -> IE because variable is referenced through IE too
+ +874:	e3 20 d0 08 00 04 	lg	%r2,8\(%r13\)
+ +87a:	e3 22 c0 00 00 04 	lg	%r2,0\(%r2,%r12\)
+ +880:	41 22 90 00       	la	%r2,0\(%r2,%r9\)
+# GD against local variable
+ +884:	e3 20 d0 10 00 04 	lg	%r2,16\(%r13\)
+ +88a:	c0 e5 ff ff ff 73 	brasl	%r14,770 <sH8\+0x6f4>
+ +890:	41 22 90 00       	la	%r2,0\(%r2,%r9\)
+# GD -> IE against local variable referenced through IE too
+ +894:	e3 20 d0 18 00 04 	lg	%r2,24\(%r13\)
+ +89a:	e3 22 c0 00 00 04 	lg	%r2,0\(%r2,%r12\)
+ +8a0:	41 22 90 00       	la	%r2,0\(%r2,%r9\)
+# GD against hidden and local variable
+ +8a4:	e3 20 d0 20 00 04 	lg	%r2,32\(%r13\)
+ +8aa:	c0 e5 ff ff ff 63 	brasl	%r14,770 <sH8\+0x6f4>
+ +8b0:	41 22 90 00       	la	%r2,0\(%r2,%r9\)
+# GD -> IE against hidden and local variable referenced through
+# IE too
+ +8b4:	e3 20 d0 28 00 04 	lg	%r2,40\(%r13\)
+ +8ba:	e3 22 c0 00 00 04 	lg	%r2,0\(%r2,%r12\)
+ +8c0:	41 22 90 00       	la	%r2,0\(%r2,%r9\)
+# GD against hidden but not local variable
+ +8c4:	e3 20 d0 30 00 04 	lg	%r2,48\(%r13\)
+ +8ca:	c0 e5 ff ff ff 53 	brasl	%r14,770 <sH8\+0x6f4>
+ +8d0:	41 22 90 00       	la	%r2,0\(%r2,%r9\)
+# GD -> IE against hidden but not local variable referenced through
+# IE too
+ +8d4:	e3 20 d0 38 00 04 	lg	%r2,56\(%r13\)
+ +8da:	e3 22 c0 00 00 04 	lg	%r2,0\(%r2,%r12\)
+ +8e0:	41 22 90 00       	la	%r2,0\(%r2,%r9\)
+# LD
+ +8e4:	e3 20 d0 40 00 04 	lg	%r2,64\(%r13\)
+ +8ea:	c0 e5 ff ff ff 43 	brasl	%r14,770 <sH8\+0x6f4>
+ +8f0:	41 32 90 00       	la	%r3,0\(%r2,%r9\)
+ +8f4:	e3 40 d0 48 00 04 	lg	%r4,72\(%r13\)
+ +8fa:	41 54 30 00       	la	%r5,0\(%r4,%r3\)
+ +8fe:	e3 40 d0 50 00 04 	lg	%r4,80\(%r13\)
+ +904:	41 54 30 00       	la	%r5,0\(%r4,%r3\)
+# LD against hidden and local variables
+ +908:	e3 20 d0 58 00 04 	lg	%r2,88\(%r13\)
+ +90e:	c0 e5 ff ff ff 31 	brasl	%r14,770 <sH8\+0x6f4>
+ +914:	41 32 90 00       	la	%r3,0\(%r2,%r9\)
+ +918:	e3 40 d0 60 00 04 	lg	%r4,96\(%r13\)
+ +91e:	41 54 30 00       	la	%r5,0\(%r4,%r3\)
+ +922:	e3 40 d0 68 00 04 	lg	%r4,104\(%r13\)
+ +928:	41 54 30 00       	la	%r5,0\(%r4,%r3\)
+# LD against hidden but not local variables
+ +92c:	e3 20 d0 70 00 04 	lg	%r2,112\(%r13\)
+ +932:	c0 e5 ff ff ff 1f 	brasl	%r14,770 <sH8\+0x6f4>
+ +938:	41 32 90 00       	la	%r3,0\(%r2,%r9\)
+ +93c:	e3 40 d0 78 00 04 	lg	%r4,120\(%r13\)
+ +942:	41 54 30 00       	la	%r5,0\(%r4,%r3\)
+ +946:	e3 40 d0 80 00 04 	lg	%r4,128\(%r13\)
+ +94c:	41 54 30 00       	la	%r5,0\(%r4,%r3\)
+# IE against global var
+ +950:	e3 30 d0 88 00 04 	lg	%r3,136\(%r13\)
+ +956:	e3 33 c0 00 00 04 	lg	%r3,0\(%r3,%r12\)
+ +95c:	41 33 90 00       	la	%r3,0\(%r3,%r9\)
+# IE against local var
+ +960:	e3 30 d0 90 00 04 	lg	%r3,144\(%r13\)
+ +966:	e3 43 c0 00 00 04 	lg	%r4,0\(%r3,%r12\)
+ +96c:	41 54 90 00       	la	%r5,0\(%r4,%r9\)
+# IE against hidden and local var
+ +970:	e3 30 d0 98 00 04 	lg	%r3,152\(%r13\)
+ +976:	e3 43 c0 00 00 04 	lg	%r4,0\(%r3,%r12\)
+ +97c:	41 54 90 00       	la	%r5,0\(%r4,%r9\)
+# IE against hidden but not local var
+ +980:	e3 30 d0 a0 00 04 	lg	%r3,160\(%r13\)
+ +986:	e3 43 c0 00 00 04 	lg	%r4,0\(%r3,%r12\)
+ +98c:	41 54 90 00       	la	%r5,0\(%r4,%r9\)
+# IE against global var with larl got access
+ +990:	c0 30 00 00 09 34 	larl	%r3,1bf8 <\_GLOBAL\_OFFSET\_TABLE\_\+0x68>
+ +996:	e3 33 c0 00 00 04 	lg	%r3,0\(%r3,%r12\)
+ +99c:	41 33 90 00       	la	%r3,0\(%r3,%r9\)
+# IE against local var with larl got access
+ +9a0:	c0 30 00 00 09 14 	larl	%r3,1bc8 <\_GLOBAL\_OFFSET\_TABLE\_\+0x38>
+ +9a6:	e3 43 c0 00 00 04 	lg	%r4,0\(%r3,%r12\)
+ +9ac:	41 54 90 00       	la	%r5,0\(%r4,%r9\)
+# IE against hidden and local var with larl got access
+ +9b0:	c0 30 00 00 09 30 	larl	%r3,1c10 <\_GLOBAL\_OFFSET\_TABLE\_\+0x80>
+ +9b6:	e3 43 c0 00 00 04 	lg	%r4,0\(%r3,%r12\)
+ +9bc:	41 54 90 00       	la	%r5,0\(%r4,%r9\)
+# IE against hidden but not local var with larl got access
+ +9c0:	c0 30 00 00 09 2c 	larl	%r3,1c18 <\_GLOBAL\_OFFSET\_TABLE\_\+0x88>
+ +9c6:	e3 43 c0 00 00 04 	lg	%r4,0\(%r3,%r12\)
+ +9cc:	41 54 90 00       	la	%r5,0\(%r4,%r9\)
+# IE against global var with small got access (no optimization)
+ +9d0:	e3 30 c0 68 00 04 	lg	%r3,104\(%r12\)
+ +9d6:	41 33 90 00       	la	%r3,0\(%r3,%r9\)
+# IE against local var with small got access (no optimization)
+ +9da:	e3 30 c0 38 00 04 	lg	%r3,56\(%r12\)
+ +9e0:	41 33 90 00       	la	%r3,0\(%r3,%r9\)
+# IE against hidden and local var with small got access
+# (no optimization)
+ +9e4:	e3 30 c0 80 00 04 	lg	%r3,128\(%r12\)
+ +9ea:	41 33 90 00       	la	%r3,0\(%r3,%r9\)
+# IE against hidden but not local var with small got access
+# (no optimization)
+ +9ee:	e3 30 c0 88 00 04 	lg	%r3,136\(%r12\)
+ +9f4:	41 33 90 00       	la	%r3,0\(%r3,%r9\)
+# function epilog
+ +9f8:	eb 6e f0 d0 00 04 	lmg	%r6,%r14,208\(%r15\)
+ +9fe:	07 fe             	br	%r14
diff -urN src/ld/testsuite/ld-s390/tlspic_64.rd src-s390/ld/testsuite/ld-s390/tlspic_64.rd
--- src/ld/testsuite/ld-s390/tlspic_64.rd	Thu Jan  1 01:00:00 1970
+++ src-s390/ld/testsuite/ld-s390/tlspic_64.rd	Thu Jan 23 23:23:13 2003
@@ -0,0 +1,165 @@
+#source: tlspic1.s
+#source: tlspic2.s
+#as: -m64 -Aesame
+#ld: -shared -melf64_s390
+#readelf: -WSsrl
+#target: s390x-*-*
+
+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+ 0+ +0 +0 +0
+  \[ 1\] .hash +.*
+  \[ 2\] .dynsym +.*
+  \[ 3\] .dynstr +.*
+  \[ 4\] .rela.dyn +.*
+  \[ 5\] .rela.plt +.*
+  \[ 6\] .plt +.*
+  \[ 7\] .text +PROGBITS +0+790 0+790 0+270 00 +AX +0 +0 +4
+  \[ 8\] .data +.*
+  \[ 9\] .tdata +PROGBITS +0+1a00 0+a00 0+60 00 WAT +0 +0 +1
+  \[10\] .tbss +NOBITS +0+1a60 0+a60 0+20 00 WAT +0 +0 +1
+  \[11\] .dynamic +DYNAMIC +0+1a60 0+a60 0+130 10 +WA +3 +0 +8
+  \[12\] .got +PROGBITS +0+1b90 0+b90 0+b0 08 +WA +0 +0 +8
+  \[13\] .sbss +.*
+  \[14\] .bss +.*
+  \[15\] .shstrtab +.*
+  \[16\] .symtab +.*
+  \[17\] .strtab +.*
+Key to Flags:
+.*
+.*
+.*
+
+Elf file type is DYN \(Shared object file\)
+Entry point 0x790
+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 0x1000
+  LOAD +0x0+a00 0x0+1a00 0x0+1a00 0x0+240 0x0+240 RW +0x1000
+  DYNAMIC +0x0+a60 0x0+1a60 0x0+1a60 0x0+130 0x0+130 RW +0x8
+  TLS +0x0+a00 0x0+1a00 0x0+1a00 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-9a-z]+  0+36 R_390_TLS_DTPMOD +0+
+[0-9a-z]+  0+38 R_390_TLS_TPOFF +0+24
+[0-9a-z]+  0+38 R_390_TLS_TPOFF +0+30
+[0-9a-z]+  0+36 R_390_TLS_DTPMOD +0+
+[0-9a-z]+  0+36 R_390_TLS_DTPMOD +0+
+[0-9a-z]+  0+38 R_390_TLS_TPOFF +0+64
+[0-9a-z]+  0+38 R_390_TLS_TPOFF +0+50
+[0-9a-z]+  0+38 R_390_TLS_TPOFF +0+70
+[0-9a-z]+  0+36 R_390_TLS_DTPMOD +0+
+[0-9a-z]+  0+38 R_390_TLS_TPOFF +0+44
+[0-9a-z]+  0+130+38 R_390_TLS_TPOFF +0+10 sg5 \+ 0
+[0-9a-z]+  0+150+36 R_390_TLS_DTPMOD +0+ sg1 \+ 0
+[0-9a-z]+  0+150+37 R_390_TLS_DTPOFF +0+ sg1 \+ 0
+[0-9a-z]+  0+180+38 R_390_TLS_TPOFF +0+4 sg2 \+ 0
+
+Relocation section '.rela.plt' at offset 0x738 contains 1 entries:
+ +Offset +Info +Type +Symbol's Value  Symbol's Name \+ Addend
+0+1ba8  0+140+b R_390_JMP_SLOT +0+ __tls_get_offset \+ 0
+
+Symbol table '.dynsym' contains 30 entries:
+ +Num: +Value +Size Type +Bind +Vis +Ndx Name
+ +0: 0+ +0 NOTYPE  LOCAL  DEFAULT  UND 
+ +1: [0-9a-z]+ +0 SECTION LOCAL  DEFAULT +1 
+ +2: [0-9a-z]+ +0 SECTION LOCAL  DEFAULT +2 
+ +3: [0-9a-z]+ +0 SECTION LOCAL  DEFAULT +3 
+ +4: [0-9a-z]+ +0 SECTION LOCAL  DEFAULT +4 
+ +5: [0-9a-z]+ +0 SECTION LOCAL  DEFAULT +5 
+ +6: [0-9a-z]+ +0 SECTION LOCAL  DEFAULT +6 
+ +7: [0-9a-z]+ +0 SECTION LOCAL  DEFAULT +7 
+ +8: [0-9a-z]+ +0 SECTION LOCAL  DEFAULT +8 
+ +9: [0-9a-z]+ +0 SECTION LOCAL  DEFAULT +9 
+ +10: [0-9a-z]+ +0 SECTION LOCAL  DEFAULT +10 
+ +11: [0-9a-z]+ +0 SECTION LOCAL  DEFAULT +11 
+ +12: [0-9a-z]+ +0 SECTION LOCAL  DEFAULT +12 
+ +13: [0-9a-z]+ +0 SECTION LOCAL  DEFAULT +13 
+ +14: [0-9a-z]+ +0 SECTION LOCAL  DEFAULT +14 
+ +15: 0+1c +0 TLS +GLOBAL DEFAULT +9 sg8
+ +16: [0-9a-z]+ +0 OBJECT  GLOBAL DEFAULT  ABS _DYNAMIC
+ +17: 0+8 +0 TLS +GLOBAL DEFAULT +9 sg3
+ +18: 0+c +0 TLS +GLOBAL DEFAULT +9 sg4
+ +19: 0+10 +0 TLS +GLOBAL DEFAULT +9 sg5
+ +20: 0+ +0 NOTYPE  GLOBAL DEFAULT  UND __tls_get_offset
+ +21: 0+ +0 TLS +GLOBAL DEFAULT +9 sg1
+ +22: [0-9a-z]+ +0 FUNC +GLOBAL DEFAULT +7 fn1
+ +23: [0-9a-z]+ +0 NOTYPE  GLOBAL DEFAULT  ABS __bss_start
+ +24: 0+4 +0 TLS +GLOBAL DEFAULT +9 sg2
+ +25: 0+14 +0 TLS +GLOBAL DEFAULT +9 sg6
+ +26: 0+18 +0 TLS +GLOBAL DEFAULT +9 sg7
+ +27: [0-9a-z]+ +0 NOTYPE  GLOBAL DEFAULT  ABS _edata
+ +28: [0-9a-z]+ +0 OBJECT  GLOBAL DEFAULT  ABS _GLOBAL_OFFSET_TABLE_
+ +29: 0+1c40 +0 NOTYPE  GLOBAL DEFAULT  ABS _end
+
+Symbol table '.symtab' contains 57 entries:
+ +Num: +Value +Size Type +Bind +Vis +Ndx Name
+ +0: 0+ +0 NOTYPE  LOCAL  DEFAULT  UND 
+ +1: [0-9a-z]+ +0 SECTION LOCAL  DEFAULT +1 
+ +2: [0-9a-z]+ +0 SECTION LOCAL  DEFAULT +2 
+ +3: [0-9a-z]+ +0 SECTION LOCAL  DEFAULT +3 
+ +4: [0-9a-z]+ +0 SECTION LOCAL  DEFAULT +4 
+ +5: [0-9a-z]+ +0 SECTION LOCAL  DEFAULT +5 
+ +6: [0-9a-z]+ +0 SECTION LOCAL  DEFAULT +6 
+ +7: [0-9a-z]+ +0 SECTION LOCAL  DEFAULT +7 
+ +8: [0-9a-z]+ +0 SECTION LOCAL  DEFAULT +8 
+ +9: [0-9a-z]+ +0 SECTION LOCAL  DEFAULT +9 
+ +10: [0-9a-z]+ +0 SECTION LOCAL  DEFAULT +10 
+ +11: [0-9a-z]+ +0 SECTION LOCAL  DEFAULT +11 
+ +12: [0-9a-z]+ +0 SECTION LOCAL  DEFAULT +12 
+ +13: [0-9a-z]+ +0 SECTION LOCAL  DEFAULT +13 
+ +14: [0-9a-z]+ +0 SECTION LOCAL  DEFAULT +14 
+ +15: [0-9a-z]+ +0 SECTION LOCAL  DEFAULT +15 
+ +16: [0-9a-z]+ +0 SECTION LOCAL  DEFAULT +16 
+ +17: [0-9a-z]+ +0 SECTION LOCAL  DEFAULT +17 
+ +18: 0+20 +0 TLS +LOCAL  DEFAULT +9 sl1
+ +19: 0+24 +0 TLS +LOCAL  DEFAULT +9 sl2
+ +20: 0+28 +0 TLS +LOCAL  DEFAULT +9 sl3
+ +21: 0+2c +0 TLS +LOCAL  DEFAULT +9 sl4
+ +22: 0+30 +0 TLS +LOCAL  DEFAULT +9 sl5
+ +23: 0+34 +0 TLS +LOCAL  DEFAULT +9 sl6
+ +24: 0+38 +0 TLS +LOCAL  DEFAULT +9 sl7
+ +25: 0+3c +0 TLS +LOCAL  DEFAULT +9 sl8
+ +26: 0+60 +0 TLS +LOCAL  HIDDEN +10 sH1
+ +27: 0+48 +0 TLS +LOCAL  HIDDEN +9 sh3
+ +28: 0+64 +0 TLS +LOCAL  HIDDEN +10 sH2
+ +29: 0+78 +0 TLS +LOCAL  HIDDEN +10 sH7
+ +30: 0+58 +0 TLS +LOCAL  HIDDEN +9 sh7
+ +31: 0+5c +0 TLS +LOCAL  HIDDEN +9 sh8
+ +32: 0+6c +0 TLS +LOCAL  HIDDEN +10 sH4
+ +33: 0+4c +0 TLS +LOCAL  HIDDEN +9 sh4
+ +34: 0+68 +0 TLS +LOCAL  HIDDEN +10 sH3
+ +35: 0+50 +0 TLS +LOCAL  HIDDEN +9 sh5
+ +36: 0+70 +0 TLS +LOCAL  HIDDEN +10 sH5
+ +37: 0+74 +0 TLS +LOCAL  HIDDEN +10 sH6
+ +38: 0+7c +0 TLS +LOCAL  HIDDEN +10 sH8
+ +39: 0+40 +0 TLS +LOCAL  HIDDEN +9 sh1
+ +40: 0+44 +0 TLS +LOCAL  HIDDEN +9 sh2
+ +41: 0+54 +0 TLS +LOCAL  HIDDEN +9 sh6
+ +42: 0+1c +0 TLS +GLOBAL DEFAULT +9 sg8
+ +43: [0-9a-z]+ +0 OBJECT  GLOBAL DEFAULT  ABS _DYNAMIC
+ +44: 0+8 +0 TLS +GLOBAL DEFAULT +9 sg3
+ +45: 0+c +0 TLS +GLOBAL DEFAULT +9 sg4
+ +46: 0+10 +0 TLS +GLOBAL DEFAULT +9 sg5
+ +47: 0+ +0 NOTYPE  GLOBAL DEFAULT  UND __tls_get_offset
+ +48: 0+ +0 TLS +GLOBAL DEFAULT +9 sg1
+ +49: [0-9a-z]+ +0 FUNC +GLOBAL DEFAULT +7 fn1
+ +50: [0-9a-z]+ +0 NOTYPE  GLOBAL DEFAULT  ABS __bss_start
+ +51: 0+4 +0 TLS +GLOBAL DEFAULT +9 sg2
+ +52: 0+14 +0 TLS +GLOBAL DEFAULT +9 sg6
+ +53: 0+18 +0 TLS +GLOBAL DEFAULT +9 sg7
+ +54: [0-9a-z]+ +0 NOTYPE  GLOBAL DEFAULT  ABS _edata
+ +55: [0-9a-z]+ +0 OBJECT  GLOBAL DEFAULT  ABS _GLOBAL_OFFSET_TABLE_
+ +56: [0-9a-z]+ +0 NOTYPE  GLOBAL DEFAULT  ABS _end
diff -urN src/ld/testsuite/ld-s390/tlspic_64.sd src-s390/ld/testsuite/ld-s390/tlspic_64.sd
--- src/ld/testsuite/ld-s390/tlspic_64.sd	Thu Jan  1 01:00:00 1970
+++ src-s390/ld/testsuite/ld-s390/tlspic_64.sd	Thu Jan 23 23:23:13 2003
@@ -0,0 +1,21 @@
+#source: tlspic1.s
+#source: tlspic2.s
+#as: -m64 -Aesame
+#ld: -shared -melf64_s390
+#objdump: -sj.got
+#target: s390x-*-*
+
+.*: +file format elf64-s390
+
+Contents of section .got:
+ 1b90 [0-9a-f]+ [0-9a-f]+ 00000000 00000000  .*
+ 1ba0 00000000 00000000 [0-9a-f]+ [0-9a-f]+  .*
+ 1bb0 00000000 00000000 00000000 00000020  .*
+ 1bc0 00000000 00000000 00000000 00000000  .*
+ 1bd0 00000000 00000000 00000000 00000000  .*
+ 1be0 00000000 00000000 00000000 00000060  .*
+ 1bf0 00000000 00000000 00000000 00000000  .*
+ 1c00 00000000 00000000 00000000 00000000  .*
+ 1c10 00000000 00000000 00000000 00000000  .*
+ 1c20 00000000 00000000 00000000 00000000  .*
+ 1c30 00000000 00000040 00000000 00000000  .*
diff -urN src/ld/testsuite/ld-s390/tlspic_64.td src-s390/ld/testsuite/ld-s390/tlspic_64.td
--- src/ld/testsuite/ld-s390/tlspic_64.td	Thu Jan  1 01:00:00 1970
+++ src-s390/ld/testsuite/ld-s390/tlspic_64.td	Thu Jan 23 23:23:13 2003
@@ -0,0 +1,16 @@
+#source: tlspic1.s
+#source: tlspic2.s
+#as: -m64 -Aesame
+#ld: -shared -melf64_s390
+#objdump: -sj.tdata
+#target: s390x-*-*
+
+.*: +file format elf64-s390
+
+Contents of section .tdata:
+ 1a00 00000011 00000012 00000013 00000014  .*
+ 1a10 00000015 00000016 00000017 00000018  .*
+ 1a20 00000041 00000042 00000043 00000044  .*
+ 1a30 00000045 00000046 00000047 00000048  .*
+ 1a40 00000101 00000102 00000103 00000104  .*
+ 1a50 00000105 00000106 00000107 00000108  .*


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