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]

Re: hppa-linux TLS work, extra DIR32 reloc for errno@@GLIBC_PRIVATE?


On Mon, May 30, 2005 at 02:23:30PM -0400, Daniel Jacobowitz wrote:
> On Mon, May 30, 2005 at 01:50:28PM -0400, Carlos O'Donell wrote:
> > The errno duplicate is the DIR32 and appears only at the
> > finish_dynamic_relocs phase. Writing it out trashes the first two relocs
> > you see in the example.
> > 
> > Where might we have gone wrong? Any clues or insight?
> 
> You didn't include any patches, or a description of what changes you've
> done, so it's hard to guess.  Obviously if you are corrupting
> something, your counting relocs does not match your generating relocs. 
> Why are you emitting a DIR32 relocation for a TLS symbol?

I wasn't looking for any specific comments, just maybe some insight.
Thanks for the interest Daniel.

I'm trying to track down where the DIR32 relocation is created for the
TLS symbol, but I'm relatively new to binutils.

Patch attached, please ignore the debugging fuzz, and instrumentation
code. Thanks again for your input.

c.

Index: bfd/bfd-in.h
===================================================================
RCS file: /cvs/src/src/bfd/bfd-in.h,v
retrieving revision 1.97
diff -u -p -r1.97 bfd-in.h
--- bfd/bfd-in.h	30 Mar 2005 17:19:27 -0000	1.97
+++ bfd/bfd-in.h	30 May 2005 18:26:57 -0000
@@ -24,6 +24,21 @@
 #ifndef __BFD_H_SEEN__
 #define __BFD_H_SEEN__
 
+#define __LFF __LINE__,__FILE__,__FUNCTION__
+
+#define DEBUG_BFD_L1 0x1
+#define DEBUG_BFD_L2 0x2
+#define DEBUG_BFD 0 
+/*#define DEBUG_BFD (DEBUG_BFD_L1 | DEBUG_BFD_L2)*/
+
+#if DEBUG_BFD
+#define DBG(LEVEL, ...) \
+          ((LEVEL & DEBUG_BFD) \
+	           ? printk(__VA_ARGS__) : (void) 0)
+#else
+#define DBG(LEVEL, ...)
+#endif
+
 #ifdef __cplusplus
 extern "C" {
 #endif
Index: bfd/bfd-in2.h
===================================================================
RCS file: /cvs/src/src/bfd/bfd-in2.h,v
retrieving revision 1.329
diff -u -p -r1.329 bfd-in2.h
--- bfd/bfd-in2.h	30 Mar 2005 17:19:28 -0000	1.329
+++ bfd/bfd-in2.h	30 May 2005 18:26:58 -0000
@@ -31,6 +31,22 @@
 #ifndef __BFD_H_SEEN__
 #define __BFD_H_SEEN__
 
+#define __LFF __LINE__,__FILE__,__FUNCTION__
+
+#define DEBUG_BFD_L1 0x1
+#define DEBUG_BFD_L2 0x2
+#define DEBUG_BFD 0 
+/*#define DEBUG_BFD (DEBUG_BFD_L1 | DEBUG_BFD_L2)*/
+
+#if DEBUG_BFD
+#define DBG(LEVEL, ...) \
+          ((LEVEL & DEBUG_BFD) \
+	           ? printk(__VA_ARGS__) : (void) 0)
+#else
+#define DBG(LEVEL, ...)
+#endif
+
+
 #ifdef __cplusplus
 extern "C" {
 #endif
Index: bfd/elf-hppa.h
===================================================================
RCS file: /cvs/src/src/bfd/elf-hppa.h,v
retrieving revision 1.76
diff -u -p -r1.76 elf-hppa.h
--- bfd/elf-hppa.h	21 Oct 2004 15:28:20 -0000	1.76
+++ bfd/elf-hppa.h	30 May 2005 18:26:58 -0000
@@ -387,7 +387,7 @@ static reloc_howto_type elf_hppa_howto_t
     bfd_elf_generic_reloc, "R_PARISC_UNIMPLEMENTED", FALSE, 0, 0, FALSE },
   { R_PARISC_TPREL32, 0, 0, 32, FALSE, 0, complain_overflow_dont,
     bfd_elf_generic_reloc, "R_PARISC_TPREL32", FALSE, 0, 0, FALSE },
-  { R_PARISC_TPREL21L, 0, 0, 21, FALSE, 0, complain_overflow_dont,
+  { R_PARISC_TPREL21L, 0, 0, 21, FALSE, 0, complain_overflow_bitfield,
     bfd_elf_generic_reloc, "R_PARISC_TPREL21L", FALSE, 0, 0, FALSE },
   { R_PARISC_UNIMPLEMENTED, 0, 0, 0, FALSE, 0, complain_overflow_dont,
     bfd_elf_generic_reloc, "R_PARISC_UNIMPLEMENTED", FALSE, 0, 0, FALSE },
@@ -395,7 +395,7 @@ static reloc_howto_type elf_hppa_howto_t
     bfd_elf_generic_reloc, "R_PARISC_UNIMPLEMENTED", FALSE, 0, 0, FALSE },
   { R_PARISC_UNIMPLEMENTED, 0, 0, 0, FALSE, 0, complain_overflow_dont,
     bfd_elf_generic_reloc, "R_PARISC_UNIMPLEMENTED", FALSE, 0, 0, FALSE },
-  { R_PARISC_TPREL14R, 0, 0, 14, FALSE, 0, complain_overflow_dont,
+  { R_PARISC_TPREL14R, 0, 0, 14, FALSE, 0, complain_overflow_bitfield,
     bfd_elf_generic_reloc, "R_PARISC_TPREL14R", FALSE, 0, 0, FALSE },
   { R_PARISC_UNIMPLEMENTED, 0, 0, 0, FALSE, 0, complain_overflow_dont,
     bfd_elf_generic_reloc, "R_PARISC_UNIMPLEMENTED", FALSE, 0, 0, FALSE },
@@ -413,7 +413,7 @@ static reloc_howto_type elf_hppa_howto_t
   { R_PARISC_UNIMPLEMENTED, 0, 0, 0, FALSE, 0, complain_overflow_bitfield,
     bfd_elf_generic_reloc, "R_PARISC_UNIMPLEMENTED", FALSE, 0, 0, FALSE },
   { R_PARISC_LTOFF_TP14R, 0, 0, 14, FALSE, 0, complain_overflow_bitfield,
-    bfd_elf_generic_reloc, "R_PARISC_UNIMPLEMENTED", FALSE, 0, 0, FALSE },
+    bfd_elf_generic_reloc, "R_PARISC_LTOFF_TP14R", FALSE, 0, 0, FALSE },
   { R_PARISC_LTOFF_TP14F, 0, 0, 14, FALSE, 0, complain_overflow_bitfield,
     bfd_elf_generic_reloc, "R_PARISC_LTOFF_TP14F", FALSE, 0, 0, FALSE },
   /* 168 */
@@ -557,6 +557,31 @@ static reloc_howto_type elf_hppa_howto_t
     bfd_elf_generic_reloc, "R_PARISC_GNU_VTENTRY", FALSE, 0, 0, FALSE },
   { R_PARISC_GNU_VTINHERIT, 0, 0, 0, FALSE, 0, complain_overflow_dont,
     bfd_elf_generic_reloc, "R_PARISC_GNU_VTINHERIT", FALSE, 0, 0, FALSE },
+  { R_PARISC_TLS_GD21L, 0, 0, 21, FALSE, 0, complain_overflow_bitfield,
+    bfd_elf_generic_reloc, "R_PARISC_TLS_GD21L", FALSE, 0, 0, FALSE },
+  { R_PARISC_TLS_GD14R, 0, 0, 14, FALSE, 0, complain_overflow_bitfield,
+    bfd_elf_generic_reloc, "R_PARISC_TLS_GD14R", FALSE, 0, 0, FALSE },
+  { R_PARISC_TLS_GDCALL, 0, 0, 0, FALSE, 0, complain_overflow_dont,
+    bfd_elf_generic_reloc, "R_PARISC_TLS_GDCALL", FALSE, 0, 0, FALSE },
+  { R_PARISC_TLS_LDM21L, 0, 0, 21, FALSE, 0, complain_overflow_bitfield,
+    bfd_elf_generic_reloc, "R_PARISC_TLS_LDM21L", FALSE, 0, 0, FALSE },
+  { R_PARISC_TLS_LDM14R, 0, 0, 14, FALSE, 0, complain_overflow_bitfield,
+    bfd_elf_generic_reloc, "R_PARISC_TLS_LDM14R", FALSE, 0, 0, FALSE },
+  { R_PARISC_TLS_LDMCALL, 0, 0, 0, FALSE, 0, complain_overflow_dont,
+    bfd_elf_generic_reloc, "R_PARISC_TLS_LDMCALL", FALSE, 0, 0, FALSE },
+  /* 240 */
+  { R_PARISC_TLS_LDO21L, 0, 0, 21, FALSE, 0, complain_overflow_bitfield,
+    bfd_elf_generic_reloc, "R_PARISC_TLS_LDO21L", FALSE, 0, 0, FALSE },
+  { R_PARISC_TLS_LDO14R, 0, 0, 14, FALSE, 0, complain_overflow_bitfield,
+    bfd_elf_generic_reloc, "R_PARISC_TLS_LDO14R", FALSE, 0, 0, FALSE },
+  { R_PARISC_TLS_DTPMOD32, 0, 0, 32, FALSE, 0, complain_overflow_bitfield,
+    bfd_elf_generic_reloc, "R_PARISC_TLS_DTPMOD32", FALSE, 0, 0, FALSE },
+  { R_PARISC_TLS_DTPMOD64, 0, 0, 64, FALSE, 0, complain_overflow_bitfield,
+    bfd_elf_generic_reloc, "R_PARISC_TLS_DTPMOD64", FALSE, 0, 0, FALSE },
+  { R_PARISC_TLS_DTPOFF32, 0, 0, 32, FALSE, 0, complain_overflow_bitfield,
+    bfd_elf_generic_reloc, "R_PARISC_TLS_DTPOFF32", FALSE, 0, 0, FALSE },
+  { R_PARISC_TLS_DTPOFF64, 0, 0, 64, FALSE, 0, complain_overflow_bitfield,
+    bfd_elf_generic_reloc, "R_PARISC_TLS_DTPOFF64", FALSE, 0, 0, FALSE },
 };
 
 #define OFFSET_14R_FROM_21L 4
@@ -838,6 +863,82 @@ elf_hppa_reloc_final_type (bfd *abfd,
 	}
       break;
 
+    case R_PARISC_TLS_GD21L:
+      switch (field)
+	{
+	  case e_ltsel:
+	  case e_lrsel:
+	    final_type = R_PARISC_TLS_GD21L;
+	    break;
+	  case e_rtsel:
+	  case e_rrsel:
+	    final_type = R_PARISC_TLS_GD14R;
+	    break;
+	  default:
+	    return R_PARISC_NONE;
+	}
+      break;
+
+    case R_PARISC_TLS_LDM21L:
+      switch (field)
+	{
+	  case e_ltsel:
+	  case e_lrsel:
+	    final_type = R_PARISC_TLS_LDM21L;
+	    break;
+	  case e_rtsel:
+	  case e_rrsel:
+	    final_type = R_PARISC_TLS_LDM14R;
+	    break;
+	  default:
+	    return R_PARISC_NONE;
+	}
+      break;
+
+    case R_PARISC_TLS_LDO21L:
+      switch (field)
+	{
+	  case e_lrsel:
+	    final_type = R_PARISC_TLS_LDO21L;
+	    break;
+	  case e_rrsel:
+	    final_type = R_PARISC_TLS_LDO14R;
+	    break;
+	  default:
+	    return R_PARISC_NONE;
+	}
+      break;
+
+    case R_PARISC_TLS_IE21L:
+      switch (field)
+	{
+	  case e_ltsel:
+	  case e_lrsel:
+	    final_type = R_PARISC_TLS_IE21L;
+	    break;
+	  case e_rtsel:
+	  case e_rrsel:
+	    final_type = R_PARISC_TLS_IE14R;
+	    break;
+	  default:
+	    return R_PARISC_NONE;
+	}
+      break;
+
+    case R_PARISC_TLS_LE21L:
+      switch (field)
+	{
+	  case e_lrsel:
+	    final_type = R_PARISC_TLS_LE21L;
+	    break;
+	  case e_rrsel:
+	    final_type = R_PARISC_TLS_LE14R;
+	    break;
+	  default:
+	    return R_PARISC_NONE;
+	}
+      break;
+
     case R_PARISC_GNU_VTENTRY:
     case R_PARISC_GNU_VTINHERIT:
     case R_PARISC_SEGREL32:
Index: bfd/elf.c
===================================================================
RCS file: /cvs/src/src/bfd/elf.c,v
retrieving revision 1.277
diff -u -p -r1.277 elf.c
--- bfd/elf.c	5 Apr 2005 04:01:09 -0000	1.277
+++ bfd/elf.c	30 May 2005 18:26:59 -0000
@@ -4743,7 +4743,10 @@ _bfd_elf_assign_file_positions_for_reloc
       shdrp = *shdrpp;
       if ((shdrp->sh_type == SHT_REL || shdrp->sh_type == SHT_RELA)
 	  && shdrp->sh_offset == -1)
-	off = _bfd_elf_assign_file_position_for_section (shdrp, off, TRUE);
+        {
+	  DBG(1,"%d: %s (%s): _bfd_elf_assign_file_position_for_section off=0x%x\n",__LFF,off);
+	  off = _bfd_elf_assign_file_position_for_section (shdrp, off, TRUE);
+	}
     }
 
   elf_tdata (abfd)->next_file_pos = off;
Index: bfd/elf32-hppa.c
===================================================================
RCS file: /cvs/src/src/bfd/elf32-hppa.c,v
retrieving revision 1.127
diff -u -p -r1.127 elf32-hppa.c
--- bfd/elf32-hppa.c	7 Mar 2005 06:01:17 -0000	1.127
+++ bfd/elf32-hppa.c	30 May 2005 18:26:59 -0000
@@ -209,6 +209,10 @@ struct elf32_hppa_link_hash_entry {
 #endif
   } *dyn_relocs;
 
+  enum {
+    GOT_UNKNOWN = -1, GOT_NORMAL=1, GOT_TLS_GD, GOT_TLS_LDM, GOT_TLS_IE
+  } tls_type;
+
   /* Set if this symbol is used by a plabel reloc.  */
   unsigned int plabel:1;
 };
@@ -277,10 +281,20 @@ struct elf32_hppa_link_hash_table {
 #define hppa_link_hash_table(p) \
   ((struct elf32_hppa_link_hash_table *) ((p)->hash))
 
+#define hppa_elf_hash_entry(ent) \
+  ((struct elf32_hppa_link_hash_entry *)(ent))
+
 #define hppa_stub_hash_lookup(table, string, create, copy) \
   ((struct elf32_hppa_stub_hash_entry *) \
    bfd_hash_lookup ((table), (string), (create), (copy)))
 
+#define hppa_elf_local_got_tls_type(abfd) \
+  ((char *)(elf_local_got_offsets (abfd) + (elf_tdata (abfd)->symtab_hdr.sh_info * 2)))
+
+static int
+elf32_hppa_optimized_tls_reloc (struct bfd_link_info *info,
+				int r_type, int is_local);
+
 /* Assorted hash table functions.  */
 
 /* Initialize an entry in the stub hash table.  */
@@ -348,6 +362,7 @@ hppa_link_hash_newfunc (struct bfd_hash_
       eh->stub_cache = NULL;
       eh->dyn_relocs = NULL;
       eh->plabel = 0;
+      eh->tls_type = GOT_UNKNOWN;
     }
 
   return entry;
@@ -690,10 +705,12 @@ hppa_build_one_stub (struct bfd_hash_ent
 
       val = hppa_field_adjust (sym_value, 0, e_lrsel);
       insn = hppa_rebuild_insn ((int) LDIL_R1, val, 21);
+      DBG(1,"%d: %s (%s): bfd_put_32 loc=0x%x\n",__LFF,loc);
       bfd_put_32 (stub_bfd, insn, loc);
 
       val = hppa_field_adjust (sym_value, 0, e_rrsel) >> 2;
       insn = hppa_rebuild_insn ((int) BE_SR4_R1, val, 17);
+      DBG(1,"%d: %s (%s): bfd_put_32 loc=0x%x\n",__LFF,loc+4);
       bfd_put_32 (stub_bfd, insn, loc + 4);
 
       size = 8;
@@ -710,6 +727,7 @@ hppa_build_one_stub (struct bfd_hash_ent
 		    + stub_sec->output_offset
 		    + stub_sec->output_section->vma);
 
+      DBG(1,"%d: %s (%s): bfd_put_32 loc=0x%x\n",__LFF,loc);
       bfd_put_32 (stub_bfd, (bfd_vma) BL_R1, loc);
       val = hppa_field_adjust (sym_value, (bfd_signed_vma) -8, e_lrsel);
       insn = hppa_rebuild_insn ((int) ADDIL_R1, val, 21);
@@ -717,6 +735,8 @@ hppa_build_one_stub (struct bfd_hash_ent
 
       val = hppa_field_adjust (sym_value, (bfd_signed_vma) -8, e_rrsel) >> 2;
       insn = hppa_rebuild_insn ((int) BE_SR4_R1, val, 17);
+
+      DBG(1,"%d: %s (%s): bfd_put_32 loc=0x%x\n",__LFF,loc+8);
       bfd_put_32 (stub_bfd, insn, loc + 8);
       size = 12;
       break;
@@ -740,6 +760,7 @@ hppa_build_one_stub (struct bfd_hash_ent
 #endif
       val = hppa_field_adjust (sym_value, 0, e_lrsel),
       insn = hppa_rebuild_insn ((int) insn, val, 21);
+      DBG(1,"%d: %s (%s): bfd_put_32 loc=0x%x\n",__LFF,loc);
       bfd_put_32 (stub_bfd, insn, loc);
 
       /* It is critical to use lrsel/rrsel here because we are using
@@ -749,26 +770,37 @@ hppa_build_one_stub (struct bfd_hash_ent
 	 between the lsel and rsel value.  */
       val = hppa_field_adjust (sym_value, 0, e_rrsel);
       insn = hppa_rebuild_insn ((int) LDW_R1_R21, val, 14);
+      
+      DBG(1,"%d: %s (%s): bfd_put_32 loc=0x%x\n",__LFF,loc+4);
       bfd_put_32 (stub_bfd, insn, loc + 4);
 
       if (htab->multi_subspace)
 	{
 	  val = hppa_field_adjust (sym_value, (bfd_signed_vma) 4, e_rrsel);
 	  insn = hppa_rebuild_insn ((int) LDW_R1_DLT, val, 14);
+
+          DBG(1,"%d: %s (%s): bfd_put_32 loc=0x%x\n",__LFF,loc+8);
 	  bfd_put_32 (stub_bfd, insn, loc + 8);
 
+	  
+          DBG(1,"%d: %s (%s): bfd_put_32 loc=0x%x\n",__LFF,loc+12);
 	  bfd_put_32 (stub_bfd, (bfd_vma) LDSID_R21_R1, loc + 12);
+          DBG(1,"%d: %s (%s): bfd_put_32 loc=0x%x\n",__LFF,loc+16);
 	  bfd_put_32 (stub_bfd, (bfd_vma) MTSP_R1,      loc + 16);
+          DBG(1,"%d: %s (%s): bfd_put_32 loc=0x%x\n",__LFF,loc+20);
 	  bfd_put_32 (stub_bfd, (bfd_vma) BE_SR0_R21,   loc + 20);
+          DBG(1,"%d: %s (%s): bfd_put_32 loc=0x%x\n",__LFF,loc+24);
 	  bfd_put_32 (stub_bfd, (bfd_vma) STW_RP,       loc + 24);
 
 	  size = 28;
 	}
       else
 	{
+          DBG(1,"%d: %s (%s): bfd_put_32 loc=0x%x\n",__LFF,loc+8);
 	  bfd_put_32 (stub_bfd, (bfd_vma) BV_R0_R21, loc + 8);
 	  val = hppa_field_adjust (sym_value, (bfd_signed_vma) 4, e_rrsel);
 	  insn = hppa_rebuild_insn ((int) LDW_R1_DLT, val, 14);
+          DBG(1,"%d: %s (%s): bfd_put_32 loc=0x%x\n",__LFF,loc+12);
 	  bfd_put_32 (stub_bfd, insn, loc + 12);
 
 	  size = 16;
@@ -806,12 +838,19 @@ hppa_build_one_stub (struct bfd_hash_ent
 	insn = hppa_rebuild_insn ((int) BL_RP, val, 17);
       else
 	insn = hppa_rebuild_insn ((int) BL22_RP, val, 22);
+
+      DBG(1,"%d: %s (%s): bfd_put_32 loc=0x%x\n",__LFF,loc);
       bfd_put_32 (stub_bfd, insn, loc);
 
+      DBG(1,"%d: %s (%s): bfd_put_32 loc=0x%x\n",__LFF,loc+4);
       bfd_put_32 (stub_bfd, (bfd_vma) NOP,         loc + 4);
+      DBG(1,"%d: %s (%s): bfd_put_32 loc=0x%x\n",__LFF,loc+8);
       bfd_put_32 (stub_bfd, (bfd_vma) LDW_RP,      loc + 8);
+      DBG(1,"%d: %s (%s): bfd_put_32 loc=0x%x\n",__LFF,loc+12);
       bfd_put_32 (stub_bfd, (bfd_vma) LDSID_RP_R1, loc + 12);
+      DBG(1,"%d: %s (%s): bfd_put_32 loc=0x%x\n",__LFF,loc+16);
       bfd_put_32 (stub_bfd, (bfd_vma) MTSP_R1,     loc + 16);
+      DBG(1,"%d: %s (%s): bfd_put_32 loc=0x%x\n",__LFF,loc+20);
       bfd_put_32 (stub_bfd, (bfd_vma) BE_SR0_RP,   loc + 20);
 
       /* Point the function symbol at the stub.  */
@@ -926,6 +965,9 @@ elf32_hppa_object_p (bfd *abfd)
       return bfd_default_set_arch_mach (abfd, bfd_arch_hppa, 20);
     case EFA_PARISC_2_0 | EF_PARISC_WIDE:
       return bfd_default_set_arch_mach (abfd, bfd_arch_hppa, 25);
+    default:
+      BFD_FAIL ();
+      return FALSE;
     }
   return TRUE;
 }
@@ -1057,6 +1099,7 @@ elf32_hppa_check_relocs (bfd *abfd,
   struct elf32_hppa_link_hash_table *htab;
   asection *sreloc;
   asection *stubreloc;
+  int tls_type, old_tls_type = GOT_UNKNOWN;
 
   if (info->relocatable)
     return TRUE;
@@ -1079,18 +1122,26 @@ elf32_hppa_check_relocs (bfd *abfd,
 
       unsigned int r_symndx, r_type;
       struct elf32_hppa_link_hash_entry *h;
-      int need_entry;
+      int need_entry = 0;
 
       r_symndx = ELF32_R_SYM (rel->r_info);
 
       if (r_symndx < symtab_hdr->sh_info)
-	h = NULL;
+        {
+	  h = NULL;
+          DBG(1,"%d: %s (%s): h=%p\n",__LFF, h);
+	}
       else
-	h = ((struct elf32_hppa_link_hash_entry *)
-	     sym_hashes[r_symndx - symtab_hdr->sh_info]);
+        {
+          h = ((struct elf32_hppa_link_hash_entry *)
+	       sym_hashes[r_symndx - symtab_hdr->sh_info]);
+          DBG(1,"%d: %s (%s): h=%p sym %s\n",__LFF, h, h->elf.root.root.string);
+	}
 
       r_type = ELF32_R_TYPE (rel->r_info);
 
+      r_type = elf32_hppa_optimized_tls_reloc (info, r_type, h == NULL);
+
       switch (r_type)
 	{
 	case R_PARISC_DLTIND14F:
@@ -1100,10 +1151,15 @@ elf32_hppa_check_relocs (bfd *abfd,
 	  need_entry = NEED_GOT;
 	  break;
 
+	case R_PARISC_PLABEL32:
+          DBG(1,"%d: %s (%s): PLABEL32\n",__LFF);
+	  
 	case R_PARISC_PLABEL14R: /* "Official" procedure labels.  */
 	case R_PARISC_PLABEL21L:
-	case R_PARISC_PLABEL32:
+	/*case R_PARISC_PLABEL32:*/
 	  /* If the addend is non-zero, we break badly.  */
+
+	  
 	  if (rel->r_addend != 0)
 	    abort ();
 
@@ -1211,13 +1267,55 @@ elf32_hppa_check_relocs (bfd *abfd,
 	    return FALSE;
 	  continue;
 
+	case R_PARISC_TLS_GD21L:
+	case R_PARISC_TLS_GD14R:
+	case R_PARISC_TLS_LDM21L:
+	case R_PARISC_TLS_LDM14R:
+	  need_entry = NEED_GOT;
+	  break;
+
+	case R_PARISC_TLS_IE21L:
+	case R_PARISC_TLS_IE14R:
+	  if (info->shared)
+            info->flags |= DF_STATIC_TLS;
+	  need_entry = NEED_GOT;
+	  break;
+
 	default:
+          DBG(1,"%d: %s (%s): Unhandled relocation = 0x%x\n",__LFF, r_type);
 	  continue;
 	}
 
       /* Now carry out our orders.  */
       if (need_entry & NEED_GOT)
 	{
+	  switch (r_type)
+	    {
+	    case R_PARISC_TLS_GD21L:
+	    case R_PARISC_TLS_GD14R:
+	      tls_type = GOT_TLS_GD;
+	      break;
+	    case R_PARISC_TLS_LDM21L:
+	    case R_PARISC_TLS_LDM14R:
+	      tls_type = GOT_TLS_LDM;
+	      break;
+	    case R_PARISC_TLS_IE21L:
+	    case R_PARISC_TLS_IE14R:
+	      tls_type = GOT_TLS_IE;
+// if (h) printf("h=%p sym %s tls_type = TLS_IE\n", h, h->elf.root.root.string);
+	      break;
+	    case R_PARISC_DLTIND14F:
+	    case R_PARISC_DLTIND14R:
+	    case R_PARISC_DLTIND21L:
+	      tls_type = GOT_NORMAL;
+	      break;
+	    default:
+              DBG(1,"%d: %s (%s): Unhandled relocation = 0x%x (GOT_NORMAL?)\n",__LFF, r_type);
+	      tls_type = GOT_UNKNOWN;
+	      break;
+
+	    }
+
 	  /* Allocate space for a GOT entry, as well as a dynamic
 	     relocation for this entry.  */
 	  if (htab->sgot == NULL)
@@ -1231,6 +1329,9 @@ elf32_hppa_check_relocs (bfd *abfd,
 	  if (h != NULL)
 	    {
 	      h->elf.got.refcount += 1;
+	      old_tls_type = hppa_elf_hash_entry (h)->tls_type;
+	      if (old_tls_type == 0)
+	        abort();
 	    }
 	  else
 	    {
@@ -1248,12 +1349,45 @@ elf32_hppa_check_relocs (bfd *abfd,
 		     pointer.  */
 		  size = symtab_hdr->sh_info;
 		  size *= 2 * sizeof (bfd_signed_vma);
+		  /* Add in space to store the local GOT TLS types.  */
+		  size += symtab_hdr->sh_info;
 		  local_got_refcounts = bfd_zalloc (abfd, size);
 		  if (local_got_refcounts == NULL)
 		    return FALSE;
 		  elf_local_got_refcounts (abfd) = local_got_refcounts;
+		  memset (hppa_elf_local_got_tls_type (abfd),
+			  GOT_UNKNOWN, symtab_hdr->sh_info);
 		}
 	      local_got_refcounts[r_symndx] += 1;
+
+	      old_tls_type = hppa_elf_local_got_tls_type (abfd) [r_symndx];
+	      if (old_tls_type == 0)
+		      abort();
+	    }
+
+	  /* If a TLS symbol is accessed using IE at least once,
+	     there is no point to use dynamic model for it.  */
+	  if (old_tls_type != tls_type && old_tls_type != GOT_UNKNOWN
+	      && (old_tls_type != GOT_TLS_GD || tls_type != GOT_TLS_IE))
+	    {
+	      if (old_tls_type == GOT_TLS_IE && tls_type == GOT_TLS_GD)
+		tls_type = GOT_TLS_IE;
+	      else
+		{
+		  (*_bfd_error_handler)
+		    (_("%B: `%s' accessed both as normal and thread local symbol"),
+		     abfd, h ? h->elf.root.root.string : "<local>");
+		  return FALSE;
+		}
+	    }
+
+	  if (old_tls_type != tls_type)
+	    {
+	      if (h != NULL) {
+		hppa_elf_hash_entry (h)->tls_type = tls_type;
+// if (h) printf("sym %s refcount %d assigning tls_type = %d\n", h->elf.root.root.string, h->elf.got.refcount, tls_type);
+	      } else
+		hppa_elf_local_got_tls_type (abfd) [r_symndx] = tls_type;
 	    }
 	}
 
@@ -1294,6 +1428,8 @@ elf32_hppa_check_relocs (bfd *abfd,
 			 plt offsets.  */
 		      size = symtab_hdr->sh_info;
 		      size *= 2 * sizeof (bfd_signed_vma);
+		      /* Add in space to store the local GOT TLS types.  */
+		      size += symtab_hdr->sh_info;
 		      local_got_refcounts = bfd_zalloc (abfd, size);
 		      if (local_got_refcounts == NULL)
 			return FALSE;
@@ -1470,6 +1606,7 @@ elf32_hppa_gc_mark_hook (asection *sec,
 	  break;
 
 	default:
+          DBG(1,"%d: %s (%s): Handle cleanup?",__LFF);
 	  switch (h->root.type)
 	    {
 	    case bfd_link_hash_defined:
@@ -1480,6 +1617,7 @@ elf32_hppa_gc_mark_hook (asection *sec,
 	      return h->root.u.c.p->section;
 
 	    default:
+              DBG(1,"%d: %s (%s): Unhandled section in cleanup? h->root.type = 0x%x",__LFF,h->root.type);
 	      break;
 	    }
 	}
@@ -1518,7 +1656,7 @@ elf32_hppa_gc_sweep_hook (bfd *abfd,
   for (rel = relocs; rel < relend; rel++)
     {
       unsigned long r_symndx;
-      unsigned int r_type;
+      unsigned int r_type, r_type_optimized;
       struct elf_link_hash_entry *h = NULL;
 
       r_symndx = ELF32_R_SYM (rel->r_info);
@@ -1544,11 +1682,18 @@ elf32_hppa_gc_sweep_hook (bfd *abfd,
 	}
 
       r_type = ELF32_R_TYPE (rel->r_info);
-      switch (r_type)
+      r_type_optimized = elf32_hppa_optimized_tls_reloc (info, r_type, h != NULL);
+      switch (r_type_optimized)
 	{
 	case R_PARISC_DLTIND14F:
 	case R_PARISC_DLTIND14R:
 	case R_PARISC_DLTIND21L:
+	case R_PARISC_TLS_GD21L:
+	case R_PARISC_TLS_GD14R:
+	case R_PARISC_TLS_LDM21L:
+	case R_PARISC_TLS_LDM14R:
+	case R_PARISC_TLS_IE21L:
+	case R_PARISC_TLS_IE14R:
 	  if (h != NULL)
 	    {
 	      if (h->got.refcount > 0)
@@ -1572,9 +1717,14 @@ elf32_hppa_gc_sweep_hook (bfd *abfd,
 	    }
 	  break;
 
+	case R_PARISC_PLABEL32:
+          DBG(1,"%d: %s (%s): PLABEL32\n",__LFF);
+
 	case R_PARISC_PLABEL14R:
 	case R_PARISC_PLABEL21L:
-	case R_PARISC_PLABEL32:
+	/*case R_PARISC_PLABEL32:*/
+
+
 	  if (h != NULL)
 	    {
 	      if (h->plt.refcount > 0)
@@ -1588,6 +1738,7 @@ elf32_hppa_gc_sweep_hook (bfd *abfd,
 	  break;
 
 	default:
+          DBG(1,"%d: %s (%s): Unhandled relocation = 0x%x (r_type_optimized?)\n",__LFF, r_type);
 	  break;
 	}
     }
@@ -1831,6 +1982,7 @@ allocate_plt_static (struct elf_link_has
 {
   struct bfd_link_info *info;
   struct elf32_hppa_link_hash_table *htab;
+  struct elf32_hppa_link_hash_entry *eh;
   asection *s;
 
   if (h->root.type == bfd_link_hash_indirect)
@@ -1840,6 +1992,7 @@ allocate_plt_static (struct elf_link_has
     h = (struct elf_link_hash_entry *) h->root.u.i.link;
 
   info = inf;
+  eh = (struct elf32_hppa_link_hash_entry *) h;
   htab = hppa_link_hash_table (info);
   if (htab->elf.dynamic_sections_created
       && h->plt.refcount > 0)
@@ -1906,9 +2059,10 @@ allocate_dynrelocs (struct elf_link_hash
 
   info = inf;
   htab = hppa_link_hash_table (info);
+  eh = hppa_elf_hash_entry (h);
   if (htab->elf.dynamic_sections_created
       && h->plt.offset != (bfd_vma) -1
-      && !((struct elf32_hppa_link_hash_entry *) h)->plabel)
+      && !eh->plabel)
     {
       /* Make an entry in the .plt section.  */
       s = htab->splt;
@@ -1934,19 +2088,25 @@ allocate_dynrelocs (struct elf_link_hash
 
       s = htab->sgot;
       h->got.offset = s->size;
+//printf("h=%p assigning got offset for sym %s at 0x%x tls_type %d\n", h, h->root.root.string, h->got.offset, hppa_elf_hash_entry (h)->tls_type);
       s->size += GOT_ENTRY_SIZE;
+      /* R_PARISC_TLS_GD* and R_PARISC_TLS_LDM* needs two GOT entries */
+      if (eh->tls_type == GOT_TLS_GD || eh->tls_type == GOT_TLS_LDM)
+      	s->size += GOT_ENTRY_SIZE;
       if (htab->elf.dynamic_sections_created
 	  && (info->shared
 	      || (h->dynindx != -1
 		  && !h->forced_local)))
 	{
 	  htab->srelgot->size += sizeof (Elf32_External_Rela);
+          if (eh->tls_type == GOT_TLS_GD
+	      || eh->tls_type == GOT_TLS_LDM)
+	    htab->srelgot->size += sizeof (Elf32_External_Rela);
 	}
     }
   else
     h->got.offset = (bfd_vma) -1;
 
-  eh = (struct elf32_hppa_link_hash_entry *) h;
   if (eh->dyn_relocs == NULL)
     return TRUE;
 
@@ -2122,6 +2282,7 @@ elf32_hppa_size_dynamic_sections (bfd *o
       bfd_size_type locsymcount;
       Elf_Internal_Shdr *symtab_hdr;
       asection *srel;
+      char *local_tls_type;
 
       if (bfd_get_flavour (ibfd) != bfd_target_elf_flavour)
 	continue;
@@ -2160,6 +2321,7 @@ elf32_hppa_size_dynamic_sections (bfd *o
       symtab_hdr = &elf_tdata (ibfd)->symtab_hdr;
       locsymcount = symtab_hdr->sh_info;
       end_local_got = local_got + locsymcount;
+      local_tls_type = hppa_elf_local_got_tls_type (ibfd);
       s = htab->sgot;
       srel = htab->srelgot;
       for (; local_got < end_local_got; ++local_got)
@@ -2168,11 +2330,20 @@ elf32_hppa_size_dynamic_sections (bfd *o
 	    {
 	      *local_got = s->size;
 	      s->size += GOT_ENTRY_SIZE;
-	      if (info->shared)
-		srel->size += sizeof (Elf32_External_Rela);
+	      if (*local_tls_type == GOT_TLS_GD 
+		  || *local_tls_type == GOT_TLS_LDM)
+		s->size += GOT_ENTRY_SIZE;
+	      if (info->shared) {
+	        srel->size += sizeof (Elf32_External_Rela);
+	        if (*local_tls_type == GOT_TLS_GD
+		    || *local_tls_type == GOT_TLS_LDM)
+		  srel->size += sizeof (Elf32_External_Rela);
+	      }
 	    }
 	  else
 	    *local_got = (bfd_vma) -1;
+
+	  ++local_tls_type;
 	}
 
       local_plt = end_local_got;
@@ -3044,6 +3215,35 @@ elf32_hppa_build_stubs (struct bfd_link_
   return TRUE;
 }
 
+/* Return the base vma address which should be subtracted from the real
+   address when resolving a dtpoff relocation.  
+   This is PT_TLS segment p_vaddr.  */
+
+static bfd_vma
+dtpoff_base (struct bfd_link_info *info)
+{
+  /* If tls_sec is NULL, we should have signalled an error already.  */
+  if (elf_hash_table (info)->tls_sec == NULL)
+    return 0;
+  return elf_hash_table (info)->tls_sec->vma;
+}
+
+/* Return the relocation value for R_PARISC_TLS_TPOFF*..  */
+
+static bfd_vma
+tpoff (struct bfd_link_info *info, bfd_vma address)
+{
+  struct elf_link_hash_table *htab = elf_hash_table (info);
+
+  /* If tls_sec is NULL, we should have signalled an error already.  */
+  if (htab->tls_sec == NULL)
+    return 0;
+  /* hppa TLS ABI is variant I and static TLS block start just after 
+     tcbhead structure which has 2 pointer fields.  */
+  return (address - htab->tls_sec->vma 
+	  + align_power ((bfd_vma) 8, htab->tls_sec->alignment_power));
+}
+
 /* Perform a final link.  */
 
 static bfd_boolean
@@ -3113,6 +3313,12 @@ final_link_relocate (asection *input_sec
   struct elf32_hppa_stub_hash_entry *stub_entry = NULL;
   int val;
 
+
+  if(h != NULL)
+   DBG(1,"%d: %s (%s): Enter h=%p sym %s\n",__LFF, h, h->elf.root.root.string);
+  else
+   DBG(1,"%d: %s (%s): Enter h=%p\n",__LFF, h);
+
   if (r_type == R_PARISC_NONE)
     return bfd_reloc_ok;
 
@@ -3140,6 +3346,25 @@ final_link_relocate (asection *input_sec
 	  case R_PARISC_DLTIND14F:
 	    r_type = R_PARISC_DPREL14F;
 	    break;
+
+	  /* Other unconverted non-shared relocs */
+	  case R_PARISC_DIR32:
+	  case R_PARISC_DIR21L:
+          case R_PARISC_DIR14R:
+	  case R_PARISC_PCREL17F:
+	  case R_PARISC_PCREL32:
+	  case R_PARISC_DPREL21L:
+	  case R_PARISC_DPREL14R:
+	  case R_PARISC_SEGREL32:
+	  case R_PARISC_PLABEL32:
+	  case R_PARISC_PLABEL21L:
+	  case R_PARISC_PLABEL14R:
+            DBG(1,"%d: %s (%s): Skipping r_type = 0x%x\n",__LFF, r_type);
+	    break;
+	    
+	  default:
+            DBG(1,"%d: %s (%s): Unhandled static relocation = 0x%x\n",__LFF, r_type);
+	    break;
 	}
     }
 
@@ -3255,6 +3480,12 @@ final_link_relocate (asection *input_sec
     case R_PARISC_DLTIND21L:
     case R_PARISC_DLTIND14R:
     case R_PARISC_DLTIND14F:
+    case R_PARISC_TLS_GD21L:
+    case R_PARISC_TLS_GD14R:
+    case R_PARISC_TLS_LDM21L:
+    case R_PARISC_TLS_LDM14R:
+    case R_PARISC_TLS_IE21L:
+    case R_PARISC_TLS_IE14R:
       value -= elf_gp (input_section->output_section->owner);
       break;
 
@@ -3265,12 +3496,26 @@ final_link_relocate (asection *input_sec
 	value -= htab->data_segment_base;
       break;
 
+    /* Skipping these relocs */
+    case R_PARISC_DIR32:
+    case R_PARISC_DIR21L:
+    case R_PARISC_DIR14R:
+    case R_PARISC_PLABEL21L:
+    case R_PARISC_PLABEL14R:
+    case R_PARISC_PLABEL32:
+      DBG(1,"%d: %s (%s): Skipping r_type = 0x%x\n",__LFF, r_type);
+      break;
+
     default:
+      DBG(1,"%d: %s (%s): Unhandled relocation = 0x%x\n",__LFF,r_type);
       break;
     }
 
   switch (r_type)
     {
+
+    case R_PARISC_PLABEL32:
+      DBG(1,"%d: %s (%s): PLABEL32\n",__LFF);
     case R_PARISC_DIR32:
     case R_PARISC_DIR14F:
     case R_PARISC_DIR17F:
@@ -3278,10 +3523,13 @@ final_link_relocate (asection *input_sec
     case R_PARISC_PCREL14F:
     case R_PARISC_PCREL32:
     case R_PARISC_DPREL14F:
-    case R_PARISC_PLABEL32:
+    /*case R_PARISC_PLABEL32:*/
     case R_PARISC_DLTIND14F:
     case R_PARISC_SEGBASE:
     case R_PARISC_SEGREL32:
+    case R_PARISC_TLS_DTPMOD32:
+    case R_PARISC_TLS_DTPOFF32:
+    case R_PARISC_TLS_TPREL32:
       r_field = e_fsel;
       break;
 
@@ -3293,6 +3541,11 @@ final_link_relocate (asection *input_sec
 
     case R_PARISC_DIR21L:
     case R_PARISC_DPREL21L:
+    case R_PARISC_TLS_GD21L:
+    case R_PARISC_TLS_LDM21L:
+    case R_PARISC_TLS_LDO21L:
+    case R_PARISC_TLS_IE21L:
+    case R_PARISC_TLS_LE21L:
       r_field = e_lrsel;
       break;
 
@@ -3306,6 +3559,11 @@ final_link_relocate (asection *input_sec
     case R_PARISC_DIR17R:
     case R_PARISC_DIR14R:
     case R_PARISC_DPREL14R:
+    case R_PARISC_TLS_GD14R:
+    case R_PARISC_TLS_LDM14R:
+    case R_PARISC_TLS_LDO14R:
+    case R_PARISC_TLS_IE14R:
+    case R_PARISC_TLS_LE14R:
       r_field = e_rrsel;
       break;
 
@@ -3354,6 +3612,7 @@ final_link_relocate (asection *input_sec
 
     /* Something we don't know how to handle.  */
     default:
+      DBG(1,"%d: %s (%s): Unhandled relocation = 0x%x\n",__LFF, r_type);
       return bfd_reloc_notsupported;
     }
 
@@ -3389,17 +3648,42 @@ final_link_relocate (asection *input_sec
       val >>= 2;
       break;
 
+    /* Skipping */
+    case R_PARISC_DIR32:
+    case R_PARISC_DIR21L:
+    case R_PARISC_DIR14R:
+    case R_PARISC_PCREL32:
+    case R_PARISC_DPREL21L:
+    case R_PARISC_DPREL14R:
+    case R_PARISC_SEGREL32:
+    case R_PARISC_PLABEL21L:
+    case R_PARISC_PLABEL14R:
+    case R_PARISC_PLABEL32:
+      DBG(1,"%d: %s (%s): Skipping r_type = 0x%x\n",__LFF, r_type);
+      break;
+      
     default:
+      DBG(1,"%d: %s (%s): Unhandled relocation = 0x%x\n",__LFF, r_type);
       break;
     }
 
   insn = hppa_rebuild_insn (insn, val, r_format);
 
   /* Update the instruction word.  */
+
+  DBG(1,"%d: %s (%s): bfd_put_32 loc=0x%x\n",__LFF,hit_data);
   bfd_put_32 (input_bfd, (bfd_vma) insn, hit_data);
   return bfd_reloc_ok;
 }
 
+static int
+elf32_hppa_optimized_tls_reloc (struct bfd_link_info *info ATTRIBUTE_UNUSED,
+				int r_type, int is_local ATTRIBUTE_UNUSED)
+{
+  /* For now we don't support linker optimizations.  */
+  return r_type;
+}
+
 /* Relocate an HPPA ELF section.  */
 
 static bfd_boolean
@@ -3464,6 +3748,8 @@ elf32_hppa_relocate_section (bfd *output
 	  sym = local_syms + r_symndx;
 	  sym_sec = local_sections[r_symndx];
 	  relocation = _bfd_elf_rela_local_sym (output_bfd, sym, &sym_sec, rel);
+          DBG(1,"%d: %s (%s): h=%p, r_info=0x%x, r_offset=0x%x\n",
+	      __LFF, h, rel->r_info, rel->r_offset);
 	}
       else
 	{
@@ -3492,7 +3778,9 @@ elf32_hppa_relocate_section (bfd *output
 		  warned_undef = TRUE;
 		}
 	    }
-	  h = (struct elf32_hppa_link_hash_entry *) hh;
+	  h = hppa_elf_hash_entry (hh);
+          DBG(1,"%d: %s (%s): h=%p sym %s, r_info=0x%x, r_offset=0x%x\n",
+	      __LFF, h, h->elf.root.root.string, rel->r_info, rel->r_offset);
 	}
 
       /* Do any required modifications to the relocation value, and
@@ -3529,6 +3817,7 @@ elf32_hppa_relocate_section (bfd *output
 		      off &= ~1;
 		    else
 		      {
+//printf("DLTIND reloc against %s\n", h->elf.root.root.string);
 			h->elf.got.offset |= 1;
 			do_got = 1;
 		      }
@@ -3572,11 +3861,19 @@ elf32_hppa_relocate_section (bfd *output
 		    outrel.r_addend = relocation;
 		    loc = s->contents;
 		    loc += s->reloc_count++ * sizeof (Elf32_External_Rela);
+
+                    DBG(1,"%d: %s (%s): bfd_elf32_swap_reloca_out (DIR32) outrel "
+		           "r_info=0x%x, r_offset=0x%x, r_addend=0x%x, loc=0x%x\n",
+	                   __LFF, outrel.r_info, outrel.r_offset,
+			   outrel.r_addend, loc);
 		    bfd_elf32_swap_reloca_out (output_bfd, &outrel, loc);
 		  }
 		else
-		  bfd_put_32 (output_bfd, relocation,
+		  {
+                    DBG(1,"%d: %s (%s): bfd_put_32 loc=0x%x\n",__LFF,htab->sgot->contents + off);
+		    bfd_put_32 (output_bfd, relocation,
 			      htab->sgot->contents + off);
+                  }
 	      }
 
 	    if (off >= (bfd_vma) -2)
@@ -3596,11 +3893,17 @@ elf32_hppa_relocate_section (bfd *output
 	    bfd_map_over_sections (output_bfd, hppa_record_segment_addr, htab);
 	  break;
 
+
+	case R_PARISC_PLABEL32:
+          DBG(1,"%d: %s (%s): PLABEL32\n",__LFF);
 	case R_PARISC_PLABEL14R:
 	case R_PARISC_PLABEL21L:
-	case R_PARISC_PLABEL32:
+	/*case R_PARISC_PLABEL32:*/
 	  if (htab->elf.dynamic_sections_created)
 	    {
+
+	      DBG(1,"%d: %s (%s): PLABEL relocs and dynamic_sections_created.\n", __LFF);
+	      
 	      bfd_vma off;
 	      bfd_boolean do_plt = 0;
 
@@ -3663,13 +3966,18 @@ elf32_hppa_relocate_section (bfd *output
 		      outrel.r_addend = relocation;
 		      loc = s->contents;
 		      loc += s->reloc_count++ * sizeof (Elf32_External_Rela);
+		      DBG(1,"%d: %s (%s): bfd_elf32_swap_reloca_out (IPLT), "
+			     "r_info = 0x%x, r_addend = 0x%x, r_offset = 0x%x, loc = 0x%x\n",
+			      __LFF, outrel.r_info, outrel.r_addend, outrel.r_offset, loc);
 		      bfd_elf32_swap_reloca_out (output_bfd, &outrel, loc);
 		    }
 		  else
 		    {
+                      DBG(1,"%d: %s (%s): bfd_put_32 loc=0x%x\n",__LFF,htab->splt->contents + off);
 		      bfd_put_32 (output_bfd,
 				  relocation,
 				  htab->splt->contents + off);
+                      DBG(1,"%d: %s (%s): bfd_put_32 loc=0x%x\n",__LFF,htab->splt->contents + off + 4);
 		      bfd_put_32 (output_bfd,
 				  elf_gp (htab->splt->output_section->owner),
 				  htab->splt->contents + off + 4);
@@ -3697,6 +4005,7 @@ elf32_hppa_relocate_section (bfd *output
 	      plabel = 1;
 	    }
 	  /* Fall through and possibly emit a dynamic relocation.  */
+          DBG(1,"%d: %s (%s): PLABEL falling through to DIR and DPREL relocs.\n", __LFF);
 
 	case R_PARISC_DIR17F:
 	case R_PARISC_DIR17R:
@@ -3813,11 +4122,208 @@ elf32_hppa_relocate_section (bfd *output
 
 	      loc = sreloc->contents;
 	      loc += sreloc->reloc_count++ * sizeof (Elf32_External_Rela);
+              DBG(1,"%d: %s (%s): bfd_elf32_swap_reloca_out (???) outrel "
+                    "r_info=0x%x, r_offset=0x%x, r_addend=0x%x, loc=0x%x\n",
+	            __LFF, outrel.r_info, outrel.r_offset, outrel.r_addend, loc);
+
 	      bfd_elf32_swap_reloca_out (output_bfd, &outrel, loc);
 	    }
 	  break;
 
+	case R_PARISC_TLS_GD21L:
+	case R_PARISC_TLS_GD14R:
+	case R_PARISC_TLS_LDM21L:
+	case R_PARISC_TLS_LDM14R:
+	  if (htab->elf.dynamic_sections_created)
+	  {
+	    bfd_vma off;
+	    bfd_boolean do_got = 0;
+
+	    /* Relocation is to the entry for this symbol in the
+	       global offset table.  */
+	    if (h != NULL)
+	      {
+		off = h->elf.got.offset;
+		if ((off & 1) != 0)
+		  off &= ~1;
+		else
+		  {
+//printf("TLSGD/LD reloc against %s\n", h->elf.root.root.string);
+		    h->elf.got.offset |= 1;
+		    do_got = 1;
+		  }
+	      }
+	    else
+	      {
+		/* Local symbol case.  */
+		if (local_got_offsets == NULL)
+		  abort ();
+
+		off = local_got_offsets[r_symndx];
+
+		/* The offset must always be a multiple of 4.  We use
+		   the least significant bit to record whether we have
+		   already generated the necessary reloc.  */
+		if ((off & 1) != 0)
+		  off &= ~1;
+		else
+		  {
+		    local_got_offsets[r_symndx] |= 1;
+		    do_got = 1;
+		  }
+	      }
+
+	    if (do_got)
+	      {
+		Elf_Internal_Rela outrel;
+		bfd_byte *loc;
+		asection *s = htab->srelgot;
+	    	int indx;
+
+	        if (h == NULL || h->elf.dynindx == -1)
+		  indx = 0;
+	        else
+		  indx = h->elf.dynindx;
+
+		outrel.r_offset = (off
+				   + htab->sgot->output_offset
+				   + htab->sgot->output_section->vma);
+
+
+		if (r_type == R_PARISC_TLS_GD21L 
+		    || r_type == R_PARISC_TLS_GD14R) {
+		  outrel.r_info = ELF32_R_INFO (0, R_PARISC_TLS_DTPMOD32);
+		  outrel.r_addend = 0;
+
+		  loc = s->contents + s->reloc_count++ * sizeof (Elf32_External_Rela);
+	          DBG(1,"%d: %s (%s): bfd_elf32_swap_reloca_out (Output DTPMOD32), "
+	               "r_info = 0x%x, r_addend = 0x%x, r_offset = 0x%x, loc = 0x%x\n",
+                       __LFF, outrel.r_info, outrel.r_addend, outrel.r_offset, loc);
+
+		  bfd_elf32_swap_reloca_out (output_bfd, &outrel, loc);
+
+		  outrel.r_offset += 4;
+		}
+
+		outrel.r_info = ELF32_R_INFO (indx, R_PARISC_TLS_DTPOFF32);
+		outrel.r_addend = 0;
+		loc = s->contents + s->reloc_count++ * sizeof (Elf32_External_Rela);
+	        DBG(1,"%d: %s (%s): bfd_elf32_swap_reloca_out (Output DTPOFF32), "
+	               "r_info = 0x%x, r_addend = 0x%x, r_offset = 0x%x, loc = 0x%x\n",
+                       __LFF, outrel.r_info, outrel.r_addend, outrel.r_offset, loc);
+
+		bfd_elf32_swap_reloca_out (output_bfd, &outrel, loc);
+	      }
+
+	    if (off >= (bfd_vma) -2)
+	      abort ();
+
+	    /* Add the base of the GOT to the relocation value.  */
+	    relocation = (off
+			  + htab->sgot->output_offset
+			  + htab->sgot->output_section->vma);
+	  }
+	  break;
+
+	case R_PARISC_TLS_LDO21L:
+	case R_PARISC_TLS_LDO14R:
+	  if (! info->shared)
+	    relocation = tpoff (info, relocation);
+	  else
+	    relocation -= dtpoff_base (info);
+	  break;
+
+	case R_PARISC_TLS_IE21L:
+	case R_PARISC_TLS_IE14R:
+	  if (htab->elf.dynamic_sections_created)
+	  {
+	    bfd_vma off;
+	    bfd_boolean do_got = 0;
+
+	    if (h != NULL)
+	      {
+		off = h->elf.got.offset;
+		if ((off & 1) != 0)
+		  off &= ~1;
+		else
+		  {
+//printf("TLSIE reloc against %s\n", h->elf.root.root.string);
+		    h->elf.got.offset |= 1;
+		    do_got = 1;
+		  }
+	      }
+	    else
+	      {
+		/* Local symbol case.  */
+		if (local_got_offsets == NULL)
+		  abort ();
+
+		off = local_got_offsets[r_symndx];
+
+		/* The offset must always be a multiple of 4.  We use
+		   the least significant bit to record whether we have
+		   already generated the necessary reloc.  */
+		if ((off & 1) != 0)
+		  off &= ~1;
+		else
+		  {
+		    local_got_offsets[r_symndx] |= 1;
+		    do_got = 1;
+		  }
+	      }
+
+	    if (do_got)
+	      {
+		Elf_Internal_Rela outrel;
+		bfd_byte *loc;
+		asection *s = htab->srelgot;
+	    	int indx;
+
+		indx = h && h->elf.dynindx != -1 ? h->elf.dynindx : 0;
+
+		outrel.r_offset = (off
+				   + htab->sgot->output_offset
+				   + htab->sgot->output_section->vma);
+		outrel.r_info = ELF32_R_INFO (indx, R_PARISC_TLS_TPREL32);
+		if (indx == 0)
+		  outrel.r_addend = relocation - dtpoff_base (info);
+		else
+		  outrel.r_addend = 0;
+
+		loc = s->contents + s->reloc_count++ * sizeof (Elf32_External_Rela);
+	        DBG(1,"%d: %s (%s): bfd_elf32_swap_reloca_out (TPREL32), "
+	               "r_info = 0x%x, r_addend = 0x%x, r_offset = 0x%x, loc = 0x%x\n",
+                       __LFF, outrel.r_info, outrel.r_addend, outrel.r_offset, loc);
+
+		bfd_elf32_swap_reloca_out (output_bfd, &outrel, loc);
+	      }
+
+	    if (off >= (bfd_vma) -2)
+	      abort ();
+
+	    /* Add the base of the GOT to the relocation value.  */
+	    relocation = (off
+			  + htab->sgot->output_offset
+			  + htab->sgot->output_section->vma);
+	  }
+	  break;
+
+	case R_PARISC_TLS_LE21L:
+	case R_PARISC_TLS_LE14R:
+	  {
+	    relocation = tpoff (info, relocation);
+	    break;
+	  }
+	  break;
+
+        /* Skipping this */
+	case R_PARISC_PCREL17F:
+	case R_PARISC_PCREL32:
+          DBG(1,"%d: %s (%s): Skipping r_type = 0x%x\n",__LFF, r_type);
+	  break;
+	  
 	default:
+          DBG(1,"%d: %s (%s): Unhandled relocation = 0x%x\n",__LFF, r_type);
 	  break;
 	}
 
@@ -3884,6 +4390,9 @@ elf32_hppa_finish_dynamic_symbol (bfd *o
 
   htab = hppa_link_hash_table (info);
 
+  DBG(1,"%d: %s (%s): sym %s got.offset 0x%x tls_type %d\n",
+         __LFF,h->root.root.string, h->got.offset, hppa_elf_hash_entry (h)->tls_type);
+
   if (h->plt.offset != (bfd_vma) -1)
     {
       bfd_vma value;
@@ -3927,6 +4436,11 @@ elf32_hppa_finish_dynamic_symbol (bfd *o
 
       loc = htab->srelplt->contents;
       loc += htab->srelplt->reloc_count++ * sizeof (Elf32_External_Rela);
+                    DBG(1,"%d: %s (%s): bfd_elf32_swap_reloca_out (IPLT) outrel "
+		           "r_info=0x%x, r_offset=0x%x, r_addend=0x%x, loc=0x%x\n",
+	                   __LFF, rel.r_info, rel.r_offset,
+			   rel.r_addend, loc);
+
       bfd_elf32_swap_reloca_out (htab->splt->output_section->owner, &rel, loc);
 
       if (!h->def_regular)
@@ -3937,7 +4451,9 @@ elf32_hppa_finish_dynamic_symbol (bfd *o
 	}
     }
 
-  if (h->got.offset != (bfd_vma) -1)
+  if (h->got.offset != (bfd_vma) -1
+      && hppa_elf_hash_entry (h)->tls_type != GOT_TLS_GD
+      && hppa_elf_hash_entry (h)->tls_type != GOT_TLS_IE)
     {
       /* This symbol has an entry in the global offset table.  Set it
 	 up.  */
@@ -3962,15 +4478,25 @@ elf32_hppa_finish_dynamic_symbol (bfd *o
 	}
       else
 	{
+		/*
 	  if ((h->got.offset & 1) != 0)
 	    abort ();
-	  bfd_put_32 (output_bfd, 0, htab->sgot->contents + h->got.offset);
+	    */
+
+          DBG(1,"%d: %s (%s): bfd_put_32 loc=0x%x\n",__LFF,htab->sgot->contents + (h->got.offset & ~1));
+	  bfd_put_32 (output_bfd, 0, htab->sgot->contents + (h->got.offset & ~1));
 	  rel.r_info = ELF32_R_INFO (h->dynindx, R_PARISC_DIR32);
 	  rel.r_addend = 0;
 	}
 
       loc = htab->srelgot->contents;
       loc += htab->srelgot->reloc_count++ * sizeof (Elf32_External_Rela);
+      DBG(1,"%d: %s (%s): bfd_elf32_swap_reloca_out (DIR32) outrel "
+             "r_info=0x%x, r_offset=0x%x, r_addend=0x%x, loc=0x%x\n",
+             __LFF, rel.r_info, rel.r_offset,
+             rel.r_addend, loc);
+
+
       bfd_elf32_swap_reloca_out (output_bfd, &rel, loc);
     }
 
@@ -3993,6 +4519,12 @@ elf32_hppa_finish_dynamic_symbol (bfd *o
       rel.r_addend = 0;
       rel.r_info = ELF32_R_INFO (h->dynindx, R_PARISC_COPY);
       loc = s->contents + s->reloc_count++ * sizeof (Elf32_External_Rela);
+                    DBG(1,"%d: %s (%s): bfd_elf32_swap_reloca_out (COPY) outrel "
+		           "r_info=0x%x, r_offset=0x%x, r_addend=0x%x, loc=0x%x\n",
+	                   __LFF, rel.r_info, rel.r_offset,
+			   rel.r_addend, loc);
+
+
       bfd_elf32_swap_reloca_out (output_bfd, &rel, loc);
     }
 
@@ -4013,6 +4545,19 @@ elf32_hppa_finish_dynamic_symbol (bfd *o
 static enum elf_reloc_type_class
 elf32_hppa_reloc_type_class (const Elf_Internal_Rela *rela)
 {
+  /* Handle TLS relocs first; we don't want them to be marked
+    relative by the "if (ELF32_R_SYM (rela->r_info) == 0)"
+    check below.  */
+  switch ((int) ELF32_R_TYPE (rela->r_info))
+    {
+    case R_PARISC_TLS_DTPMOD32:
+    case R_PARISC_TLS_DTPOFF32:
+    case R_PARISC_TLS_TPREL32:
+      return reloc_class_normal;
+    default:
+      break;
+    }
+
   if (ELF32_R_SYM (rela->r_info) == 0)
     return reloc_class_relative;
 
@@ -4061,6 +4606,7 @@ elf32_hppa_finish_dynamic_sections (bfd 
 	  switch (dyn.d_tag)
 	    {
 	    default:
+              DBG(1,"%d: %s (%s): Unhandled dyanmic entry = 0x%x\n",__LFF,dyn.d_tag);
 	      continue;
 
 	    case DT_PLTGOT:
@@ -4108,6 +4654,8 @@ elf32_hppa_finish_dynamic_sections (bfd 
     {
       /* Fill in the first entry in the global offset table.
 	 We use it to point to our dynamic section, if we have one.  */
+
+      DBG(1,"%d: %s (%s): bfd_put_32 loc=0x%x\n",__LFF,htab->sgot->contents);
       bfd_put_32 (output_bfd,
 		  sdyn ? sdyn->output_section->vma + sdyn->output_offset : 0,
 		  htab->sgot->contents);
Index: bfd/elfcode.h
===================================================================
RCS file: /cvs/src/src/bfd/elfcode.h,v
retrieving revision 1.64
diff -u -p -r1.64 elfcode.h
--- bfd/elfcode.h	20 Feb 2005 14:59:07 -0000	1.64
+++ bfd/elfcode.h	30 May 2005 18:26:59 -0000
@@ -71,6 +71,8 @@ Foundation, Inc., 59 Temple Place - Suit
 #include "libbfd.h"
 #include "elf-bfd.h"
 
+#define __LFF __LINE__,__FILE__,__FUNCTION__
+
 /* Renaming structures, typedefs, macros and functions to be size-specific.  */
 #define Elf_External_Ehdr	NAME(Elf,External_Ehdr)
 #define Elf_External_Sym	NAME(Elf,External_Sym)
@@ -884,6 +886,13 @@ elf_write_relocs (bfd *abfd, asection *s
       src_rela.r_offset = ptr->address + addr_offset;
       src_rela.r_info = ELF_R_INFO (n, ptr->howto->type);
       src_rela.r_addend = ptr->addend;
+      DBG(1,"%d: %s (%s): *swap_out "
+	     "src_rela.r_offset=0x%x, "
+	     "src_rela.r_info=0x%x, "
+	     "src_rela.r_addend=0x%x, "
+	     "dst_rela=0x%x\n",
+	  __LFF, src_rela.r_offset, src_rela.r_info, src_rela.r_addend,
+	  dst_rela);
       (*swap_out) (abfd, &src_rela, dst_rela);
     }
 }
Index: gas/config/tc-hppa.c
===================================================================
RCS file: /cvs/src/src/gas/config/tc-hppa.c,v
retrieving revision 1.115
diff -u -p -r1.115 tc-hppa.c
--- gas/config/tc-hppa.c	3 Mar 2005 11:47:50 -0000	1.115
+++ gas/config/tc-hppa.c	30 May 2005 18:27:00 -0000
@@ -1210,6 +1210,26 @@ static struct default_space_dict pa_def_
   ((exp).X_op == O_subtract			\
    && strcmp (S_GET_NAME ((exp).X_op_symbol), "$PIC_pcrel$0") == 0)
 
+#define is_tls_gdidx(exp)			\
+  ((exp).X_op == O_subtract			\
+   && strcmp (S_GET_NAME ((exp).X_op_symbol), "$tls_gdidx$") == 0)
+
+#define is_tls_ldidx(exp)			\
+  ((exp).X_op == O_subtract			\
+   && strcmp (S_GET_NAME ((exp).X_op_symbol), "$tls_ldidx$") == 0)
+
+#define is_tls_dtpoff(exp)			\
+  ((exp).X_op == O_subtract			\
+   && strcmp (S_GET_NAME ((exp).X_op_symbol), "$tls_dtpoff$") == 0)
+
+#define is_tls_ieoff(exp)			\
+  ((exp).X_op == O_subtract			\
+   && strcmp (S_GET_NAME ((exp).X_op_symbol), "$tls_ieoff$") == 0)
+
+#define is_tls_leoff(exp)			\
+  ((exp).X_op == O_subtract			\
+   && strcmp (S_GET_NAME ((exp).X_op_symbol), "$tls_leoff$") == 0)
+
 /* We need some complex handling for stabs (sym1 - sym2).  Luckily, we'll
    always be able to reduce the expression to a constant, so we don't
    need real complex handling yet.  */
@@ -1371,7 +1391,12 @@ fix_new_hppa (frag, where, size, add_sym
      it now so as not to confuse write.c.  Ditto for $PIC_pcrel$0.  */
   if (new_fix->fx_subsy
       && (strcmp (S_GET_NAME (new_fix->fx_subsy), "$global$") == 0
-	  || strcmp (S_GET_NAME (new_fix->fx_subsy), "$PIC_pcrel$0") == 0))
+	  || strcmp (S_GET_NAME (new_fix->fx_subsy), "$PIC_pcrel$0") == 0
+	  || strcmp (S_GET_NAME (new_fix->fx_subsy), "$tls_gdidx$") == 0 
+	  || strcmp (S_GET_NAME (new_fix->fx_subsy), "$tls_ldidx$") == 0 
+	  || strcmp (S_GET_NAME (new_fix->fx_subsy), "$tls_dtpoff$") == 0
+	  || strcmp (S_GET_NAME (new_fix->fx_subsy), "$tls_ieoff$") == 0
+	  || strcmp (S_GET_NAME (new_fix->fx_subsy), "$tls_leoff$") == 0))
     new_fix->fx_subsy = NULL;
 }
 
@@ -1403,6 +1428,18 @@ cons_fix_new_hppa (frag, where, size, ex
     rel_type = R_HPPA_GOTOFF;
   else if (is_PC_relative (*exp))
     rel_type = R_HPPA_PCREL_CALL;
+#ifdef OBJ_ELF
+  else if (is_tls_gdidx (*exp))
+    rel_type = R_PARISC_TLS_GD21L;
+  else if (is_tls_ldidx (*exp))
+    rel_type = R_PARISC_TLS_LDM21L;
+  else if (is_tls_dtpoff (*exp))
+    rel_type = R_PARISC_TLS_LDO21L;
+  else if (is_tls_ieoff (*exp))
+    rel_type = R_PARISC_TLS_IE21L;
+  else if (is_tls_leoff (*exp))
+    rel_type = R_PARISC_TLS_LE21L;
+#endif
   else if (is_complex (*exp))
     rel_type = R_HPPA_COMPLEX;
   else
@@ -2979,6 +3016,18 @@ pa_ip (str)
 		    the_insn.reloc = R_HPPA_GOTOFF;
 		  else if (is_PC_relative (the_insn.exp))
 		    the_insn.reloc = R_HPPA_PCREL_CALL;
+#ifdef OBJ_ELF
+		  else if (is_tls_gdidx (the_insn.exp))
+		    the_insn.reloc = R_PARISC_TLS_GD21L;
+		  else if (is_tls_ldidx (the_insn.exp))
+		    the_insn.reloc = R_PARISC_TLS_LDM21L;
+		  else if (is_tls_dtpoff (the_insn.exp))
+		    the_insn.reloc = R_PARISC_TLS_LDO21L;
+		  else if (is_tls_ieoff (the_insn.exp))
+		    the_insn.reloc = R_PARISC_TLS_IE21L;
+		  else if (is_tls_leoff (the_insn.exp))
+		    the_insn.reloc = R_PARISC_TLS_LE21L;
+#endif
 		  else
 		    the_insn.reloc = R_HPPA;
 		  the_insn.format = 11;
@@ -3096,6 +3145,18 @@ pa_ip (str)
 		    the_insn.reloc = R_HPPA_GOTOFF;
 		  else if (is_PC_relative (the_insn.exp))
 		    the_insn.reloc = R_HPPA_PCREL_CALL;
+#ifdef OBJ_ELF
+		  else if (is_tls_gdidx (the_insn.exp))
+		    the_insn.reloc = R_PARISC_TLS_GD21L;
+		  else if (is_tls_ldidx (the_insn.exp))
+		    the_insn.reloc = R_PARISC_TLS_LDM21L;
+		  else if (is_tls_dtpoff (the_insn.exp))
+		    the_insn.reloc = R_PARISC_TLS_LDO21L;
+		  else if (is_tls_ieoff (the_insn.exp))
+		    the_insn.reloc = R_PARISC_TLS_IE21L;
+		  else if (is_tls_leoff (the_insn.exp))
+		    the_insn.reloc = R_PARISC_TLS_LE21L;
+#endif
 		  else
 		    the_insn.reloc = R_HPPA;
 		  the_insn.format = 14;
@@ -3126,6 +3187,18 @@ pa_ip (str)
 		    the_insn.reloc = R_HPPA_GOTOFF;
 		  else if (is_PC_relative (the_insn.exp))
 		    the_insn.reloc = R_HPPA_PCREL_CALL;
+#ifdef OBJ_ELF
+		  else if (is_tls_gdidx (the_insn.exp))
+		    the_insn.reloc = R_PARISC_TLS_GD21L;
+		  else if (is_tls_ldidx (the_insn.exp))
+		    the_insn.reloc = R_PARISC_TLS_LDM21L;
+		  else if (is_tls_dtpoff (the_insn.exp))
+		    the_insn.reloc = R_PARISC_TLS_LDO21L;
+		  else if (is_tls_ieoff (the_insn.exp))
+		    the_insn.reloc = R_PARISC_TLS_IE21L;
+		  else if (is_tls_leoff (the_insn.exp))
+		    the_insn.reloc = R_PARISC_TLS_LE21L;
+#endif
 		  else
 		    the_insn.reloc = R_HPPA;
 		  the_insn.format = 14;
@@ -3150,6 +3223,18 @@ pa_ip (str)
 		    the_insn.reloc = R_HPPA_GOTOFF;
 		  else if (is_PC_relative (the_insn.exp))
 		    the_insn.reloc = R_HPPA_PCREL_CALL;
+#ifdef OBJ_ELF
+		  else if (is_tls_gdidx (the_insn.exp))
+		    the_insn.reloc = R_PARISC_TLS_GD21L;
+		  else if (is_tls_ldidx (the_insn.exp))
+		    the_insn.reloc = R_PARISC_TLS_LDM21L;
+		  else if (is_tls_dtpoff (the_insn.exp))
+		    the_insn.reloc = R_PARISC_TLS_LDO21L;
+		  else if (is_tls_ieoff (the_insn.exp))
+		    the_insn.reloc = R_PARISC_TLS_IE21L;
+		  else if (is_tls_leoff (the_insn.exp))
+		    the_insn.reloc = R_PARISC_TLS_LE21L;
+#endif
 		  else
 		    the_insn.reloc = R_HPPA;
 		  the_insn.format = 14;
@@ -3174,6 +3259,18 @@ pa_ip (str)
 		    the_insn.reloc = R_HPPA_GOTOFF;
 		  else if (is_PC_relative (the_insn.exp))
 		    the_insn.reloc = R_HPPA_PCREL_CALL;
+#ifdef OBJ_ELF
+		  else if (is_tls_gdidx (the_insn.exp))
+		    the_insn.reloc = R_PARISC_TLS_GD21L;
+		  else if (is_tls_ldidx (the_insn.exp))
+		    the_insn.reloc = R_PARISC_TLS_LDM21L;
+		  else if (is_tls_dtpoff (the_insn.exp))
+		    the_insn.reloc = R_PARISC_TLS_LDO21L;
+		  else if (is_tls_ieoff (the_insn.exp))
+		    the_insn.reloc = R_PARISC_TLS_IE21L;
+		  else if (is_tls_leoff (the_insn.exp))
+		    the_insn.reloc = R_PARISC_TLS_LE21L;
+#endif
 		  else
 		    the_insn.reloc = R_HPPA;
 		  the_insn.format = 21;
@@ -3199,6 +3296,18 @@ pa_ip (str)
 		    the_insn.reloc = R_HPPA_GOTOFF;
 		  else if (is_PC_relative (the_insn.exp))
 		    the_insn.reloc = R_HPPA_PCREL_CALL;
+#ifdef OBJ_ELF
+		  else if (is_tls_gdidx (the_insn.exp))
+		    the_insn.reloc = R_PARISC_TLS_GD21L;
+		  else if (is_tls_ldidx (the_insn.exp))
+		    the_insn.reloc = R_PARISC_TLS_LDM21L;
+		  else if (is_tls_dtpoff (the_insn.exp))
+		    the_insn.reloc = R_PARISC_TLS_LDO21L;
+		  else if (is_tls_ieoff (the_insn.exp))
+		    the_insn.reloc = R_PARISC_TLS_IE21L;
+		  else if (is_tls_leoff (the_insn.exp))
+		    the_insn.reloc = R_PARISC_TLS_LE21L;
+#endif
 		  else
 		    the_insn.reloc = R_HPPA;
 		  the_insn.format = 14;
@@ -3225,6 +3334,18 @@ pa_ip (str)
 		    the_insn.reloc = R_HPPA_GOTOFF;
 		  else if (is_PC_relative (the_insn.exp))
 		    the_insn.reloc = R_HPPA_PCREL_CALL;
+#ifdef OBJ_ELF
+		  else if (is_tls_gdidx (the_insn.exp))
+		    the_insn.reloc = R_PARISC_TLS_GD21L;
+		  else if (is_tls_ldidx (the_insn.exp))
+		    the_insn.reloc = R_PARISC_TLS_LDM21L;
+		  else if (is_tls_dtpoff (the_insn.exp))
+		    the_insn.reloc = R_PARISC_TLS_LDO21L;
+		  else if (is_tls_ieoff (the_insn.exp))
+		    the_insn.reloc = R_PARISC_TLS_IE21L;
+		  else if (is_tls_leoff (the_insn.exp))
+		    the_insn.reloc = R_PARISC_TLS_LE21L;
+#endif
 		  else
 		    the_insn.reloc = R_HPPA;
 		  the_insn.format = 14;
@@ -3251,6 +3372,18 @@ pa_ip (str)
 		    the_insn.reloc = R_HPPA_GOTOFF;
 		  else if (is_PC_relative (the_insn.exp))
 		    the_insn.reloc = R_HPPA_PCREL_CALL;
+#ifdef OBJ_ELF
+		  else if (is_tls_gdidx (the_insn.exp))
+		    the_insn.reloc = R_PARISC_TLS_GD21L;
+		  else if (is_tls_ldidx (the_insn.exp))
+		    the_insn.reloc = R_PARISC_TLS_LDM21L;
+		  else if (is_tls_dtpoff (the_insn.exp))
+		    the_insn.reloc = R_PARISC_TLS_LDO21L;
+		  else if (is_tls_ieoff (the_insn.exp))
+		    the_insn.reloc = R_PARISC_TLS_IE21L;
+		  else if (is_tls_leoff (the_insn.exp))
+		    the_insn.reloc = R_PARISC_TLS_LE21L;
+#endif
 		  else
 		    the_insn.reloc = R_HPPA;
 		  the_insn.format = 14;
@@ -4643,6 +4776,25 @@ md_apply_fix3 (fixP, valP, seg)
       return;
     }
 
+#ifdef OBJ_ELF
+  switch (fixP->fx_r_type)
+    {
+      case R_PARISC_TLS_GD21L:
+      case R_PARISC_TLS_GD14R:
+      case R_PARISC_TLS_LDM21L:
+      case R_PARISC_TLS_LDM14R:
+      case R_PARISC_TLS_LE21L:
+      case R_PARISC_TLS_LE14R:
+      case R_PARISC_TLS_IE21L:
+      case R_PARISC_TLS_IE14R:
+        if (fixP->fx_addsy)
+	  S_SET_THREAD_LOCAL (fixP->fx_addsy);
+	break;
+      default:
+	break;
+    }
+#endif
+
   /* Insert the relocation.  */
   bfd_put_32 (stdoutput, insn, buf);
 }
Index: gas/config/tc-hppa.h
===================================================================
RCS file: /cvs/src/src/gas/config/tc-hppa.h,v
retrieving revision 1.27
diff -u -p -r1.27 tc-hppa.h
--- gas/config/tc-hppa.h	19 Feb 2005 08:56:08 -0000	1.27
+++ gas/config/tc-hppa.h	30 May 2005 18:27:00 -0000
@@ -179,7 +179,12 @@ int hppa_fix_adjustable PARAMS((struct f
 	|| (S_GET_SEGMENT (sym) == &bfd_abs_section \
 	    && ! S_IS_EXTERNAL (sym)) \
 	|| strcmp (S_GET_NAME (sym), "$global$") == 0 \
-	|| strcmp (S_GET_NAME (sym), "$PIC_pcrel$0") == 0) \
+	|| strcmp (S_GET_NAME (sym), "$PIC_pcrel$0") == 0 \
+	|| strcmp (S_GET_NAME (sym), "$tls_gdidx$") == 0 \
+	|| strcmp (S_GET_NAME (sym), "$tls_ldidx$") == 0 \
+	|| strcmp (S_GET_NAME (sym), "$tls_dtpoff$") == 0 \
+	|| strcmp (S_GET_NAME (sym), "$tls_ieoff$") == 0 \
+	|| strcmp (S_GET_NAME (sym), "$tls_leoff$") == 0) \
       punt = 1; \
   }
 
Index: include/elf/hppa.h
===================================================================
RCS file: /cvs/src/src/include/elf/hppa.h,v
retrieving revision 1.15
diff -u -p -r1.15 hppa.h
--- include/elf/hppa.h	14 Mar 2001 02:27:44 -0000	1.15
+++ include/elf/hppa.h	30 May 2005 18:27:01 -0000
@@ -481,8 +481,28 @@ RELOC_NUMBER (R_PARISC_LTOFF_TP16DF,   2
 RELOC_NUMBER (R_PARISC_GNU_VTENTRY,    232)
 RELOC_NUMBER (R_PARISC_GNU_VTINHERIT,  233)
 
+RELOC_NUMBER (R_PARISC_TLS_GD21L,	234)
+RELOC_NUMBER (R_PARISC_TLS_GD14R,	235)
+RELOC_NUMBER (R_PARISC_TLS_GDCALL,	236)
+RELOC_NUMBER (R_PARISC_TLS_LDM21L,	237)
+RELOC_NUMBER (R_PARISC_TLS_LDM14R,	238)
+RELOC_NUMBER (R_PARISC_TLS_LDMCALL,	239)
+RELOC_NUMBER (R_PARISC_TLS_LDO21L,	240)
+RELOC_NUMBER (R_PARISC_TLS_LDO14R,	241)
+RELOC_NUMBER (R_PARISC_TLS_DTPMOD32,	242)
+RELOC_NUMBER (R_PARISC_TLS_DTPMOD64,	243)
+RELOC_NUMBER (R_PARISC_TLS_DTPOFF32,	244)
+RELOC_NUMBER (R_PARISC_TLS_DTPOFF64,	245)
+
 END_RELOC_NUMBERS (R_PARISC_UNIMPLEMENTED)
 
+#define R_PARISC_TLS_LE21L	R_PARISC_TPREL21L
+#define R_PARISC_TLS_LE14R	R_PARISC_TPREL14R
+#define R_PARISC_TLS_IE21L	R_PARISC_LTOFF_TP21L
+#define R_PARISC_TLS_IE14R	R_PARISC_LTOFF_TP14R
+#define R_PARISC_TLS_TPREL32	R_PARISC_TPREL32
+#define R_PARISC_TLS_TPREL64	R_PARISC_TPREL64
+
 #ifndef RELOC_MACROS_GEN_FUNC
 typedef enum elf_hppa_reloc_type elf_hppa_reloc_type;
 #endif
Index: ld/ldwrite.c
===================================================================
RCS file: /cvs/src/src/ld/ldwrite.c,v
retrieving revision 1.19
diff -u -p -r1.19 ldwrite.c
--- ld/ldwrite.c	22 Feb 2005 13:00:25 -0000	1.19
+++ ld/ldwrite.c	30 May 2005 18:27:01 -0000
@@ -110,16 +110,19 @@ build_link_order (lang_statement_union_t
 		  case SQUAD:
 		    if (sizeof (bfd_vma) >= QUAD_SIZE)
 		      {
+			DBG(1,"%d: %s (%s): bfd_putl64 value=0x%x, buffer=0x%x\n",__LFF,value,buffer);
 			bfd_putl64 (value, buffer);
 			value = bfd_getb64 (buffer);
 			break;
 		      }
 		    /* Fall through.  */
 		  case LONG:
+                    DBG(1,"%d: %s (%s): bfd_putl32 value=0x%x, buffer=0x%x\n",__LFF,value,buffer);
 		    bfd_putl32 (value, buffer);
 		    value = bfd_getb32 (buffer);
 		    break;
 		  case SHORT:
+                    DBG(1,"%d: %s (%s): bfd_putl16 value=0x%x, buffer=0x%x\n",__LFF,value,buffer);
 		    bfd_putl16 (value, buffer);
 		    value = bfd_getb16 (buffer);
 		    break;
@@ -137,7 +140,11 @@ build_link_order (lang_statement_union_t
 	  case QUAD:
 	  case SQUAD:
 	    if (sizeof (bfd_vma) >= QUAD_SIZE)
-	      bfd_put_64 (output_bfd, value, link_order->u.data.contents);
+	      {
+
+                DBG(1,"%d: %s (%s): bfd_put_64 value=0x%x, buffer=0x%x\n",__LFF,value,link_order->u.data.contents);
+	        bfd_put_64 (output_bfd, value, link_order->u.data.contents);
+	      }
 	    else
 	      {
 		bfd_vma high;
@@ -148,9 +155,12 @@ build_link_order (lang_statement_union_t
 		  high = 0;
 		else
 		  high = (bfd_vma) -1;
+                DBG(1,"%d: %s (%s): bfd_put_32 value=0x%x, buffer=0x%x\n",__LFF,value,link_order->u.data.contents+(big_endian ? 0:4));
 		bfd_put_32 (output_bfd, high,
 			    (link_order->u.data.contents
 			     + (big_endian ? 0 : 4)));
+
+                DBG(1,"%d: %s (%s): bfd_put_32 value=0x%x, buffer=0x%x\n",__LFF,value,link_order->u.data.contents+(big_endian ? 4:0));
 		bfd_put_32 (output_bfd, value,
 			    (link_order->u.data.contents
 			     + (big_endian ? 4 : 0)));
@@ -158,14 +168,17 @@ build_link_order (lang_statement_union_t
 	    link_order->size = QUAD_SIZE;
 	    break;
 	  case LONG:
+            DBG(1,"%d: %s (%s): bfd_put_32 value=0x%x, buffer=0x%x\n",__LFF,value,link_order->u.data.contents);
 	    bfd_put_32 (output_bfd, value, link_order->u.data.contents);
 	    link_order->size = LONG_SIZE;
 	    break;
 	  case SHORT:
+            DBG(1,"%d: %s (%s): bfd_put_16 value=0x%x, buffer=0x%x\n",__LFF,value,link_order->u.data.contents);
 	    bfd_put_16 (output_bfd, value, link_order->u.data.contents);
 	    link_order->size = SHORT_SIZE;
 	    break;
 	  case BYTE:
+            DBG(1,"%d: %s (%s): bfd_put_8 value=0x%x, buffer=0x%x\n",__LFF,value,link_order->u.data.contents);
 	    bfd_put_8 (output_bfd, value, link_order->u.data.contents);
 	    link_order->size = BYTE_SIZE;
 	    break;
@@ -543,6 +556,7 @@ split_sections (bfd *abfd, struct bfd_li
 void
 ldwrite (void)
 {
+  DBG(1,"%d: %s (%s): Enter\n",__LFF);
   /* Reset error indicator, which can typically something like invalid
      format from opening up the .o files.  */
   bfd_set_error (bfd_error_no_error);
@@ -562,4 +576,5 @@ ldwrite (void)
       else
 	xexit (1);
     }
+  DBG(1,"%d: %s (%s): Return\n",__LFF);
 }



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