This is the mail archive of the binutils@sourceware.org mailing list for the binutils project.


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

[10/20] MIPS GOT: Use separate IE and GD TLS entries


This patch creates separate mips_got_entries for IE and GD references.
As an interim step, the symbol hash entries must have separate IE and
GD fields too, but that goes away later in the series.

The low part of tls_type now acts an enum, but again only becomes one
later in the series.

Richard


bfd/
	* elfxx-mips.c (mips_got_entry): Update comment above tls_type entry
	to say that each structure represents only one type of TLS reference.
	(GOT_TLS_TYPE): New define.
	(mips_elf_link_hash_entry): Temporarily split tls_type and
	tls_got_offset into two variables each.
	(mips_elf_link_hash_newfunc): Update accordingly.
	(mips_elf_got_entry_eq, mips_elf_got_entry_hash)
	(mips_elf_multi_got_entry_eq): Require the tls_type to be the same.
	(mips_elf_reloc_tls_type, mips_tls_got_entries): New functions.
	(mips_tls_got_relocs): Use a switch statement.
	(mips_elf_count_global_tls_entries): Handle the new hash entry fields.
	(mips_elf_initialize_tls_slots): Use a switch statement.  Avoid
	local "offset" variable.
	(mips_tls_got_index): Remove r_type argument and assert.  Remove
	code that handled entries with two TLS types; always use the
	original got_index instead.
	(mips_tls_single_got_index): New function.
	(mips_elf_local_got_index): Use entry->tls_type to check for
	TLS entries.  Use mips_tls_single_got_index.  Update call to
	mips_tls_got_index.
	(mips_elf_global_got_index): Use mips_elf_reloc_tls_type.
	Use p->tls_type to check for TLS entries.  Update call to
	mips_tls_got_index.  Use mips_tls_single_got_index.
	(mips_elf_create_local_got_entry): Use mips_elf_reloc_tls_type.
	Use entry.tls_type to check for TLS entries.
	(mips_elf_record_global_got_symbol): Replace tls_flag argument
	with r_type argument.  Use mips_elf_reloc_tls_type.
	Set up the new hash entry fields.
	(mips_elf_record_local_got_symbol): Replace tls_flag argument
	with r_type argument.  Use mips_elf_reloc_tls_type and
	mips_tls_got_entries.  Remove code that handled entries
	with multiple TLS types.
	(mips_elf_make_got_per_bfd): Use mips_tls_got_entries.
	(mips_elf_initialize_tls_index): Handle new hash entry fields.
	Use equality rather than masks when checking for specific TLS types.
	Use mips_tls_got_entries.  Remove code that handled entries
	with multiple TLS types.
	(mips_elf_calculate_relocation): Use TLS_RELOC_P instead of
	testing the hash table entry.
	(_bfd_mips_elf_check_relocs): Update calls to
	mips_elf_record_global_got_symbol and mips_elf_record_local_got_symbol.
	(_bfd_mips_elf_finish_dynamic_symbol): Don't check h->type.
	(_bfd_mips_elf_copy_indirect_symbol): Handle new hash entry fields.

Index: bfd/elfxx-mips.c
===================================================================
--- bfd/elfxx-mips.c	2013-02-11 14:06:34.436173914 +0000
+++ bfd/elfxx-mips.c	2013-02-11 16:36:19.906052997 +0000
@@ -101,11 +101,9 @@ struct mips_got_entry
     struct mips_elf_link_hash_entry *h;
   } d;
 
-  /* The TLS types included in this GOT entry (specifically, GD and
-     IE).  The GD and IE flags can be added as we encounter new
-     relocations.  LDM can also be set; it will always be alone, not
-     combined with any GD or IE flags.  An LDM GOT entry will be
-     a local symbol entry with r_symndx == 0.  */
+  /* The TLS type of this GOT entry: GOT_NORMAL, GOT_TLS_IE, GOT_TLS_GD
+     or GOT_TLS_LDM.  An LDM GOT entry will be a local symbol entry with
+     r_symndx == 0.  */
   unsigned char tls_type;
 
   /* The offset from the beginning of the .got section to the entry
@@ -363,17 +361,18 @@ #define GOT_NORMAL	0
 #define GOT_TLS_GD	1
 #define GOT_TLS_LDM	2
 #define GOT_TLS_IE	4
+#define GOT_TLS_TYPE	7
 #define GOT_TLS_OFFSET_DONE    0x40
 #define GOT_TLS_DONE    0x80
-  unsigned char tls_type;
+  unsigned char tls_ie_type;
+  unsigned char tls_gd_type;
 
-  /* This is only used in single-GOT mode; in multi-GOT mode there
+  /* These fields are only used in single-GOT mode; in multi-GOT mode there
      is one mips_got_entry per GOT entry, so the offset is stored
      there.  In single-GOT mode there may be many mips_got_entry
-     structures all referring to the same GOT slot.  It might be
-     possible to use root.got.offset instead, but that field is
-     overloaded already.  */
-  bfd_vma tls_got_offset;
+     structures all referring to the same GOT slot.  */
+  bfd_vma tls_ie_got_offset;
+  bfd_vma tls_gd_got_offset;
 
   /* The highest GGA_* value that satisfies all references to this symbol.  */
   unsigned int global_got_area : 2;
@@ -1111,7 +1110,8 @@ mips_elf_link_hash_newfunc (struct bfd_h
       ret->fn_stub = NULL;
       ret->call_stub = NULL;
       ret->call_fp_stub = NULL;
-      ret->tls_type = GOT_NORMAL;
+      ret->tls_ie_type = GOT_NORMAL;
+      ret->tls_gd_type = GOT_NORMAL;
       ret->global_got_area = GGA_NONE;
       ret->got_only_for_calls = TRUE;
       ret->readonly_reloc = FALSE;
@@ -2799,14 +2799,12 @@ mips_elf_got_entry_eq (const void *entry
   const struct mips_got_entry *e1 = (struct mips_got_entry *)entry1;
   const struct mips_got_entry *e2 = (struct mips_got_entry *)entry2;
 
-  /* An LDM entry can only match another LDM entry.  */
-  if ((e1->tls_type ^ e2->tls_type) & GOT_TLS_LDM)
-    return 0;
-
-  return e1->abfd == e2->abfd && e1->symndx == e2->symndx
-    && (! e1->abfd ? e1->d.address == e2->d.address
-	: e1->symndx >= 0 ? e1->d.addend == e2->d.addend
-	: e1->d.h == e2->d.h);
+  return (e1->abfd == e2->abfd
+	  && e1->symndx == e2->symndx
+	  && (e1->tls_type & GOT_TLS_TYPE) == (e2->tls_type & GOT_TLS_TYPE)
+	  && (!e1->abfd ? e1->d.address == e2->d.address
+	      : e1->symndx >= 0 ? e1->d.addend == e2->d.addend
+	      : e1->d.h == e2->d.h));
 }
 
 /* multi_got_entries are still a match in the case of global objects,
@@ -2819,15 +2817,13 @@ mips_elf_got_entry_hash (const void *ent
 {
   const struct mips_got_entry *entry = (struct mips_got_entry *)entry_;
 
-  return entry->symndx
-    + (! entry->abfd
-       ? mips_elf_hash_bfd_vma (entry->d.address)
-       : entry->symndx >= 0
-       ? ((entry->tls_type & GOT_TLS_LDM)
-	  ? (GOT_TLS_LDM << 17)
-	  : (entry->abfd->id
-	     + mips_elf_hash_bfd_vma (entry->d.addend)))
-       : entry->d.h->root.root.root.hash);
+  return (entry->symndx
+	  + (((entry->tls_type & GOT_TLS_TYPE) == GOT_TLS_LDM) << 18)
+	  + ((entry->tls_type & GOT_TLS_TYPE) == GOT_TLS_LDM ? 0
+	     : !entry->abfd ? mips_elf_hash_bfd_vma (entry->d.address)
+	     : entry->symndx >= 0 ? (entry->abfd->id
+				     + mips_elf_hash_bfd_vma (entry->d.addend))
+	     : entry->d.h->root.root.root.hash));
 }
 
 static int
@@ -2836,19 +2832,13 @@ mips_elf_multi_got_entry_eq (const void
   const struct mips_got_entry *e1 = (struct mips_got_entry *)entry1;
   const struct mips_got_entry *e2 = (struct mips_got_entry *)entry2;
 
-  /* Any two LDM entries match.  */
-  if (e1->tls_type & e2->tls_type & GOT_TLS_LDM)
-    return 1;
-
-  /* Nothing else matches an LDM entry.  */
-  if ((e1->tls_type ^ e2->tls_type) & GOT_TLS_LDM)
-    return 0;
-
-  return e1->symndx == e2->symndx
-    && (e1->symndx >= 0 ? e1->abfd == e2->abfd && e1->d.addend == e2->d.addend
-	: e1->abfd == NULL || e2->abfd == NULL
-	? e1->abfd == e2->abfd && e1->d.address == e2->d.address
-	: e1->d.h == e2->d.h);
+  return (e1->symndx == e2->symndx
+	  && (e1->tls_type & GOT_TLS_TYPE) == (e2->tls_type & GOT_TLS_TYPE)
+	  && ((e1->tls_type & GOT_TLS_TYPE) == GOT_TLS_LDM ? TRUE
+	      : !e1->abfd ? !e2->abfd && e1->d.address == e2->d.address
+	      : e1->symndx >= 0 ? (e1->abfd == e2->abfd
+				   && e1->d.addend == e2->d.addend)
+	      : e2->abfd && e1->d.h == e2->d.h));
 }
 
 static hashval_t
@@ -2931,6 +2921,43 @@ mips_elf_rel_dyn_section (struct bfd_lin
   return sreloc;
 }
 
+/* Return the GOT_TLS_* type required by relocation type R_TYPE.  */
+
+static int
+mips_elf_reloc_tls_type (unsigned int r_type)
+{
+  if (tls_gd_reloc_p (r_type))
+    return GOT_TLS_GD;
+
+  if (tls_ldm_reloc_p (r_type))
+    return GOT_TLS_LDM;
+
+  if (tls_gottprel_reloc_p (r_type))
+    return GOT_TLS_IE;
+
+  return GOT_NORMAL;
+}
+
+/* Return the number of GOT slots needed for GOT TLS type TYPE.  */
+
+static int
+mips_tls_got_entries (unsigned int type)
+{
+  switch (type)
+    {
+    case GOT_TLS_GD:
+    case GOT_TLS_LDM:
+      return 2;
+
+    case GOT_TLS_IE:
+      return 1;
+
+    case GOT_NORMAL:
+      return 0;
+    }
+  abort ();
+}
+
 /* Count the number of relocations needed for a TLS GOT entry, with
    access types from TLS_TYPE, and symbol H (or a local symbol if H
    is NULL).  */
@@ -2940,7 +2967,6 @@ mips_tls_got_relocs (struct bfd_link_inf
 		     struct elf_link_hash_entry *h)
 {
   int indx = 0;
-  int ret = 0;
   bfd_boolean need_relocs = FALSE;
   bfd_boolean dyn = elf_hash_table (info)->dynamic_sections_created;
 
@@ -2955,22 +2981,22 @@ mips_tls_got_relocs (struct bfd_link_inf
     need_relocs = TRUE;
 
   if (!need_relocs)
-    return FALSE;
+    return 0;
 
-  if (tls_type & GOT_TLS_GD)
+  switch (tls_type & GOT_TLS_TYPE)
     {
-      ret++;
-      if (indx != 0)
-	ret++;
-    }
+    case GOT_TLS_GD:
+      return indx != 0 ? 2 : 1;
 
-  if (tls_type & GOT_TLS_IE)
-    ret++;
+    case GOT_TLS_IE:
+      return 1;
 
-  if ((tls_type & GOT_TLS_LDM) && info->shared)
-    ret++;
+    case GOT_TLS_LDM:
+      return info->shared ? 1 : 0;
 
-  return ret;
+    default:
+      return 0;
+    }
 }
 
 /* Count the number of TLS relocations required for the GOT entry in
@@ -3002,9 +3028,9 @@ mips_elf_count_global_tls_entries (void
       || hm->root.root.type == bfd_link_hash_warning)
     return 1;
 
-  if (hm->tls_type & GOT_TLS_GD)
+  if (hm->tls_gd_type)
     arg->needed += 2;
-  if (hm->tls_type & GOT_TLS_IE)
+  if (hm->tls_ie_type)
     arg->needed += 1;
 
   return 1;
@@ -3024,7 +3050,8 @@ mips_elf_count_global_tls_relocs (void *
       || hm->root.root.type == bfd_link_hash_warning)
     return 1;
 
-  arg->needed += mips_tls_got_relocs (arg->info, hm->tls_type, &hm->root);
+  arg->needed += mips_tls_got_relocs (arg->info, hm->tls_ie_type, &hm->root);
+  arg->needed += mips_tls_got_relocs (arg->info, hm->tls_gd_type, &hm->root);
 
   return 1;
 }
@@ -3072,7 +3099,7 @@ mips_elf_initialize_tls_slots (bfd *abfd
   struct mips_elf_link_hash_table *htab;
   int indx;
   asection *sreloc, *sgot;
-  bfd_vma offset, offset2;
+  bfd_vma got_offset2;
   bfd_boolean need_relocs = FALSE;
 
   htab = mips_elf_hash_table (info);
@@ -3109,65 +3136,59 @@ mips_elf_initialize_tls_slots (bfd *abfd
   /* Emit necessary relocations.  */
   sreloc = mips_elf_rel_dyn_section (info, FALSE);
 
-  /* General Dynamic.  */
-  if (*tls_type_p & GOT_TLS_GD)
+  switch (*tls_type_p & GOT_TLS_TYPE)
     {
-      offset = got_offset;
-      offset2 = offset + MIPS_ELF_GOT_SIZE (abfd);
+    case GOT_TLS_GD:
+      /* General Dynamic.  */
+      got_offset2 = got_offset + MIPS_ELF_GOT_SIZE (abfd);
 
       if (need_relocs)
 	{
 	  mips_elf_output_dynamic_relocation
 	    (abfd, sreloc, sreloc->reloc_count++, indx,
 	     ABI_64_P (abfd) ? R_MIPS_TLS_DTPMOD64 : R_MIPS_TLS_DTPMOD32,
-	     sgot->output_offset + sgot->output_section->vma + offset);
+	     sgot->output_offset + sgot->output_section->vma + got_offset);
 
 	  if (indx)
 	    mips_elf_output_dynamic_relocation
 	      (abfd, sreloc, sreloc->reloc_count++, indx,
 	       ABI_64_P (abfd) ? R_MIPS_TLS_DTPREL64 : R_MIPS_TLS_DTPREL32,
-	       sgot->output_offset + sgot->output_section->vma + offset2);
+	       sgot->output_offset + sgot->output_section->vma + got_offset2);
 	  else
 	    MIPS_ELF_PUT_WORD (abfd, value - dtprel_base (info),
-			       sgot->contents + offset2);
+			       sgot->contents + got_offset2);
 	}
       else
 	{
 	  MIPS_ELF_PUT_WORD (abfd, 1,
-			     sgot->contents + offset);
+			     sgot->contents + got_offset);
 	  MIPS_ELF_PUT_WORD (abfd, value - dtprel_base (info),
-			     sgot->contents + offset2);
+			     sgot->contents + got_offset2);
 	}
+      break;
 
-      got_offset += 2 * MIPS_ELF_GOT_SIZE (abfd);
-    }
-
-  /* Initial Exec model.  */
-  if (*tls_type_p & GOT_TLS_IE)
-    {
-      offset = got_offset;
-
+    case GOT_TLS_IE:
+      /* Initial Exec model.  */
       if (need_relocs)
 	{
 	  if (indx == 0)
 	    MIPS_ELF_PUT_WORD (abfd, value - elf_hash_table (info)->tls_sec->vma,
-			       sgot->contents + offset);
+			       sgot->contents + got_offset);
 	  else
 	    MIPS_ELF_PUT_WORD (abfd, 0,
-			       sgot->contents + offset);
+			       sgot->contents + got_offset);
 
 	  mips_elf_output_dynamic_relocation
 	    (abfd, sreloc, sreloc->reloc_count++, indx,
 	     ABI_64_P (abfd) ? R_MIPS_TLS_TPREL64 : R_MIPS_TLS_TPREL32,
-	     sgot->output_offset + sgot->output_section->vma + offset);
+	     sgot->output_offset + sgot->output_section->vma + got_offset);
 	}
       else
 	MIPS_ELF_PUT_WORD (abfd, value - tprel_base (info),
-			   sgot->contents + offset);
-    }
+			   sgot->contents + got_offset);
+      break;
 
-  if (*tls_type_p & GOT_TLS_LDM)
-    {
+    case GOT_TLS_LDM:
       /* The initial offset is zero, and the LD offsets will include the
 	 bias by DTP_OFFSET.  */
       MIPS_ELF_PUT_WORD (abfd, 0,
@@ -3182,49 +3203,43 @@ mips_elf_initialize_tls_slots (bfd *abfd
 	  (abfd, sreloc, sreloc->reloc_count++, indx,
 	   ABI_64_P (abfd) ? R_MIPS_TLS_DTPMOD64 : R_MIPS_TLS_DTPMOD32,
 	   sgot->output_offset + sgot->output_section->vma + got_offset);
+      break;
+
+    default:
+      abort ();
     }
 
   *tls_type_p |= GOT_TLS_DONE;
 }
 
-/* Return the GOT index to use for a relocation of type R_TYPE against
-   a symbol accessed using TLS_TYPE models.  The GOT entries for this
-   symbol in this GOT start at GOT_INDEX.  This function initializes the
-   GOT entries and corresponding relocations.  */
+/* Return the GOT index to use for a relocation against H using the
+   TLS model in *TLS_TYPE.  The GOT entries for this symbol/model
+   combination start at GOT_INDEX into ABFD's GOT.  This function
+   initializes the GOT entries and corresponding relocations.  */
 
 static bfd_vma
 mips_tls_got_index (bfd *abfd, bfd_vma got_index, unsigned char *tls_type,
-		    int r_type, struct bfd_link_info *info,
+		    struct bfd_link_info *info,
 		    struct mips_elf_link_hash_entry *h, bfd_vma symbol)
 {
-  BFD_ASSERT (tls_gottprel_reloc_p (r_type)
-	      || tls_gd_reloc_p (r_type)
-	      || tls_ldm_reloc_p (r_type));
-
   mips_elf_initialize_tls_slots (abfd, got_index, tls_type, info, h, symbol);
+  return got_index;
+}
 
-  if (tls_gottprel_reloc_p (r_type))
-    {
-      BFD_ASSERT (*tls_type & GOT_TLS_IE);
-      if (*tls_type & GOT_TLS_GD)
-	return got_index + 2 * MIPS_ELF_GOT_SIZE (abfd);
-      else
-	return got_index;
-    }
+/* Return the GOT index to use for a relocation of type R_TYPE against H
+   in ABFD.  */
 
+static bfd_vma
+mips_tls_single_got_index (bfd *abfd, int r_type, struct bfd_link_info *info,
+			   struct mips_elf_link_hash_entry *h, bfd_vma symbol)
+{
+  if (tls_gottprel_reloc_p (r_type))
+    return mips_tls_got_index (abfd, h->tls_ie_got_offset, &h->tls_ie_type,
+			       info, h, symbol);
   if (tls_gd_reloc_p (r_type))
-    {
-      BFD_ASSERT (*tls_type & GOT_TLS_GD);
-      return got_index;
-    }
-
-  if (tls_ldm_reloc_p (r_type))
-    {
-      BFD_ASSERT (*tls_type & GOT_TLS_LDM);
-      return got_index;
-    }
-
-  return got_index;
+    return mips_tls_got_index (abfd, h->tls_gd_got_offset, &h->tls_gd_type,
+			       info, h, symbol);
+  abort ();
 }
 
 /* Return the offset from _GLOBAL_OFFSET_TABLE_ of the .got.plt entry
@@ -3284,16 +3299,15 @@ mips_elf_local_got_index (bfd *abfd, bfd
   if (!entry)
     return MINUS_ONE;
 
-  if (TLS_RELOC_P (r_type))
+  if (entry->tls_type)
     {
       if (entry->symndx == -1 && htab->got_info->next == NULL)
 	/* A type (3) entry in the single-GOT case.  We use the symbol's
 	   hash table entry to track the index.  */
-	return mips_tls_got_index (abfd, h->tls_got_offset, &h->tls_type,
-				   r_type, info, h, value);
+	return mips_tls_single_got_index (abfd, r_type, info, h, value);
       else
 	return mips_tls_got_index (abfd, entry->gotidx, &entry->tls_type,
-				   r_type, info, h, value);
+				   info, h, value);
     }
   else
     return entry->gotidx;
@@ -3326,13 +3340,13 @@ mips_elf_global_got_index (bfd *abfd, bf
 	  e.abfd = ibfd;
 	  e.symndx = -1;
 	  e.d.h = (struct mips_elf_link_hash_entry *)h;
-	  e.tls_type = 0;
+	  e.tls_type = mips_elf_reloc_tls_type (r_type);
 
 	  p = htab_find (g->got_entries, &e);
 
-	  BFD_ASSERT (p->gotidx > 0);
+	  BFD_ASSERT (p && p->gotidx > 0);
 
-	  if (TLS_RELOC_P (r_type))
+	  if (p->tls_type)
 	    {
 	      bfd_vma value = MINUS_ONE;
 	      if ((h->root.type == bfd_link_hash_defined
@@ -3342,7 +3356,7 @@ mips_elf_global_got_index (bfd *abfd, bf
 			 + h->root.u.def.section->output_offset
 			 + h->root.u.def.section->output_section->vma);
 
-	      return mips_tls_got_index (abfd, p->gotidx, &p->tls_type, r_type,
+	      return mips_tls_got_index (abfd, p->gotidx, &p->tls_type,
 					 info, e.d.h, value);
 	    }
 	  else
@@ -3366,8 +3380,7 @@ mips_elf_global_got_index (bfd *abfd, bf
 		 + h->root.u.def.section->output_offset
 		 + h->root.u.def.section->output_section->vma);
 
-      got_index = mips_tls_got_index (abfd, hm->tls_got_offset, &hm->tls_type,
-				      r_type, info, hm, value);
+      got_index = mips_tls_single_got_index (abfd, r_type, info, hm, value);
     }
   else
     {
@@ -3483,7 +3496,7 @@ mips_elf_create_local_got_entry (bfd *ab
   entry.abfd = NULL;
   entry.symndx = -1;
   entry.d.address = value;
-  entry.tls_type = 0;
+  entry.tls_type = mips_elf_reloc_tls_type (r_type);
 
   g = mips_elf_got_for_ibfd (htab->got_info, ibfd);
   if (g == NULL)
@@ -3495,14 +3508,13 @@ mips_elf_create_local_got_entry (bfd *ab
   /* This function shouldn't be called for symbols that live in the global
      area of the GOT.  */
   BFD_ASSERT (h == NULL || h->global_got_area == GGA_NONE);
-  if (TLS_RELOC_P (r_type))
+  if (entry.tls_type)
     {
       struct mips_got_entry *p;
 
       entry.abfd = ibfd;
       if (tls_ldm_reloc_p (r_type))
 	{
-	  entry.tls_type = GOT_TLS_LDM;
 	  entry.symndx = 0;
 	  entry.d.addend = 0;
 	}
@@ -3527,7 +3539,6 @@ mips_elf_create_local_got_entry (bfd *ab
     return *loc;
 
   entry.gotidx = MIPS_ELF_GOT_SIZE (abfd) * g->assigned_gotno++;
-  entry.tls_type = 0;
 
   *loc = (struct mips_got_entry *)bfd_alloc (abfd, sizeof entry);
 
@@ -3678,16 +3689,14 @@ mips_elf_sort_hash_table_f (struct mips_
   return TRUE;
 }
 
-/* If H is a symbol that needs a global GOT entry, but has a dynamic
-   symbol table index lower than any we've seen to date, record it for
-   posterity.  FOR_CALL is true if the caller is only interested in
+/* ABFD has a GOT relocation of type R_TYPE against H.  Reserve a GOT
+   entry for it.  FOR_CALL is true if the caller is only interested in
    using the GOT entry for calls.  */
 
 static bfd_boolean
 mips_elf_record_global_got_symbol (struct elf_link_hash_entry *h,
 				   bfd *abfd, struct bfd_link_info *info,
-				   bfd_boolean for_call,
-				   unsigned char tls_flag)
+				   bfd_boolean for_call, int r_type)
 {
   struct mips_elf_link_hash_table *htab;
   struct mips_elf_link_hash_entry *hmips;
@@ -3723,7 +3732,7 @@ mips_elf_record_global_got_symbol (struc
   entry.abfd = abfd;
   entry.symndx = -1;
   entry.d.h = (struct mips_elf_link_hash_entry *) h;
-  entry.tls_type = 0;
+  entry.tls_type = mips_elf_reloc_tls_type (r_type);
 
   loc = (struct mips_got_entry **) htab_find_slot (g->got_entries, &entry,
 						   INSERT);
@@ -3731,10 +3740,7 @@ mips_elf_record_global_got_symbol (struc
   /* If we've already marked this entry as needing GOT space, we don't
      need to do it again.  */
   if (*loc)
-    {
-      (*loc)->tls_type |= tls_flag;
-      return TRUE;
-    }
+    return TRUE;
 
   *loc = (struct mips_got_entry *)bfd_alloc (abfd, sizeof entry);
 
@@ -3742,23 +3748,25 @@ mips_elf_record_global_got_symbol (struc
     return FALSE;
 
   entry.gotidx = -1;
-  entry.tls_type = tls_flag;
 
   memcpy (*loc, &entry, sizeof entry);
 
-  if (tls_flag == 0)
+  if (entry.tls_type == GOT_NORMAL)
     hmips->global_got_area = GGA_NORMAL;
+  else if (entry.tls_type == GOT_TLS_IE)
+    hmips->tls_ie_type = entry.tls_type;
+  else if (entry.tls_type == GOT_TLS_GD)
+    hmips->tls_gd_type = entry.tls_type;
 
   return TRUE;
 }
 
-/* Reserve space in G for a GOT entry containing the value of symbol
-   SYMNDX in input bfd ABDF, plus ADDEND.  */
+/* ABFD has a GOT relocation of type R_TYPE against symbol SYMNDX + ADDEND,
+   where SYMNDX is a local symbol.  Reserve a GOT entry for it.  */
 
 static bfd_boolean
 mips_elf_record_local_got_symbol (bfd *abfd, long symndx, bfd_vma addend,
-				  struct bfd_link_info *info,
-				  unsigned char tls_flag)
+				  struct bfd_link_info *info, int r_type)
 {
   struct mips_elf_link_hash_table *htab;
   struct mips_got_info *g;
@@ -3773,44 +3781,26 @@ mips_elf_record_local_got_symbol (bfd *a
   entry.abfd = abfd;
   entry.symndx = symndx;
   entry.d.addend = addend;
-  entry.tls_type = tls_flag;
+  entry.tls_type = mips_elf_reloc_tls_type (r_type);
   loc = (struct mips_got_entry **)
     htab_find_slot (g->got_entries, &entry, INSERT);
 
   if (*loc)
-    {
-      if (tls_flag == GOT_TLS_GD && !((*loc)->tls_type & GOT_TLS_GD))
-	{
-	  g->tls_gotno += 2;
-	  (*loc)->tls_type |= tls_flag;
-	}
-      else if (tls_flag == GOT_TLS_IE && !((*loc)->tls_type & GOT_TLS_IE))
-	{
-	  g->tls_gotno += 1;
-	  (*loc)->tls_type |= tls_flag;
-	}
-      return TRUE;
-    }
+    return TRUE;
 
   entry.gotidx = -1;
-  if (tls_flag != 0)
+  if (entry.tls_type)
     {
-      entry.tls_type = tls_flag;
-      if (tls_flag == GOT_TLS_IE)
-	g->tls_gotno += 1;
-      else if (tls_flag == GOT_TLS_GD)
-	g->tls_gotno += 2;
+      if (entry.tls_type != GOT_TLS_LDM)
+	g->tls_gotno += mips_tls_got_entries (entry.tls_type);
       else if (g->tls_ldm_offset == MINUS_ONE)
 	{
 	  g->tls_ldm_offset = MINUS_TWO;
-	  g->tls_gotno += 2;
+	  g->tls_gotno += mips_tls_got_entries (entry.tls_type);
 	}
     }
   else
-    {
-      g->local_gotno += 1;
-      entry.tls_type = 0;
-    }
+    g->local_gotno += 1;
 
   *loc = (struct mips_got_entry *)bfd_alloc (abfd, sizeof entry);
 
@@ -4204,16 +4194,11 @@ mips_elf_make_got_per_bfd (void **entryp
   *entryp = entry;
 
   if (entry->tls_type)
-    {
-      if (entry->tls_type & (GOT_TLS_GD | GOT_TLS_LDM))
-	g->tls_gotno += 2;
-      if (entry->tls_type & GOT_TLS_IE)
-	g->tls_gotno += 1;
-    }
+    g->tls_gotno += mips_tls_got_entries (entry->tls_type & GOT_TLS_TYPE);
   else if (entry->symndx >= 0 || entry->d.h->global_got_area == GGA_NONE)
-    ++g->local_gotno;
+    g->local_gotno += 1;
   else
-    ++g->global_gotno;
+    g->global_gotno += 1;
 
   return 1;
 }
@@ -4377,7 +4362,8 @@ mips_elf_initialize_tls_index (void **en
   unsigned char tls_type;
 
   /* We're only interested in TLS symbols.  */
-  if (entry->tls_type == 0)
+  tls_type = (entry->tls_type & GOT_TLS_TYPE);
+  if (tls_type == 0)
     return 1;
 
   next_index = MIPS_ELF_GOT_SIZE (entry->abfd) * (long) g->tls_assigned_gotno;
@@ -4386,15 +4372,25 @@ mips_elf_initialize_tls_index (void **en
     {
       /* A type (3) got entry in the single-GOT case.  We use the symbol's
 	 hash table entry to track its index.  */
-      if (entry->d.h->tls_type & GOT_TLS_OFFSET_DONE)
-	return 1;
-      entry->d.h->tls_type |= GOT_TLS_OFFSET_DONE;
-      entry->d.h->tls_got_offset = next_index;
-      tls_type = entry->d.h->tls_type;
+      if (tls_type == GOT_TLS_IE)
+	{
+	  if (entry->d.h->tls_ie_type & GOT_TLS_OFFSET_DONE)
+	    return 1;
+	  entry->d.h->tls_ie_type |= GOT_TLS_OFFSET_DONE;
+	  entry->d.h->tls_ie_got_offset = next_index;
+	}
+      else
+	{
+	  BFD_ASSERT (tls_type == GOT_TLS_GD);
+	  if (entry->d.h->tls_gd_type & GOT_TLS_OFFSET_DONE)
+	    return 1;
+	  entry->d.h->tls_gd_type |= GOT_TLS_OFFSET_DONE;
+	  entry->d.h->tls_gd_got_offset = next_index;
+	}
     }
   else
     {
-      if (entry->tls_type & GOT_TLS_LDM)
+      if (tls_type == GOT_TLS_LDM)
 	{
 	  /* There are separate mips_got_entry objects for each input bfd
 	     that requires an LDM entry.  Make sure that all LDM entries in
@@ -4407,15 +4403,10 @@ mips_elf_initialize_tls_index (void **en
 	  g->tls_ldm_offset = next_index;
 	}
       entry->gotidx = next_index;
-      tls_type = entry->tls_type;
     }
 
   /* Account for the entries we've just allocated.  */
-  if (tls_type & (GOT_TLS_GD | GOT_TLS_LDM))
-    g->tls_assigned_gotno += 2;
-  if (tls_type & GOT_TLS_IE)
-    g->tls_assigned_gotno += 1;
-
+  g->tls_assigned_gotno += mips_tls_got_entries (tls_type);
   return 1;
 }
 
@@ -5395,7 +5386,7 @@ mips_elf_calculate_relocation (bfd *abfd
 	      BFD_ASSERT (addend == 0);
 	      g = mips_elf_global_got_index (dynobj, input_bfd,
 					     &h->root, r_type, info);
-	      if (h->tls_type == GOT_NORMAL
+	      if (!TLS_RELOC_P (r_type)
 		  && !elf_hash_table (info)->dynamic_sections_created)
 		/* This is a static link.  We must initialize the GOT entry.  */
 		MIPS_ELF_PUT_WORD (dynobj, symbol, htab->sgot->contents + g);
@@ -7983,7 +7974,7 @@ _bfd_mips_elf_check_relocs (bfd *abfd, s
 	     R_MIPS_CALL_HI16 because these are always followed by an
 	     R_MIPS_GOT_LO16 or R_MIPS_CALL_LO16.  */
 	  if (!mips_elf_record_local_got_symbol (abfd, r_symndx,
-						 rel->r_addend, info, 0))
+						 rel->r_addend, info, r_type))
 	    return FALSE;
 	}
 
@@ -8016,7 +8007,8 @@ _bfd_mips_elf_check_relocs (bfd *abfd, s
 	      /* Make sure there is room in the regular GOT to hold the
 		 function's address.  We may eliminate it in favour of
 		 a .got.plt entry later; see mips_elf_count_got_symbols.  */
-	      if (!mips_elf_record_global_got_symbol (h, abfd, info, TRUE, 0))
+	      if (!mips_elf_record_global_got_symbol (h, abfd, info, TRUE,
+						      r_type))
 		return FALSE;
 
 	      /* We need a stub, not a plt entry for the undefined
@@ -8081,7 +8073,7 @@ _bfd_mips_elf_check_relocs (bfd *abfd, s
 	case R_MIPS_GOT_DISP:
 	case R_MICROMIPS_GOT_DISP:
 	  if (h && !mips_elf_record_global_got_symbol (h, abfd, info,
-						       FALSE, 0))
+						       FALSE, r_type))
 	    return FALSE;
 	  break;
 
@@ -8107,32 +8099,19 @@ _bfd_mips_elf_check_relocs (bfd *abfd, s
 	case R_MICROMIPS_TLS_GD:
 	  /* This symbol requires a global offset table entry, or two
 	     for TLS GD relocations.  */
-	  {
-	    unsigned char flag;
-
-	    flag = (tls_gd_reloc_p (r_type)
-		    ? GOT_TLS_GD
-		    : tls_ldm_reloc_p (r_type) ? GOT_TLS_LDM : GOT_TLS_IE);
-	    if (h != NULL)
-	      {
-		struct mips_elf_link_hash_entry *hmips =
-		  (struct mips_elf_link_hash_entry *) h;
-		hmips->tls_type |= flag;
-
-		if (h && !mips_elf_record_global_got_symbol (h, abfd, info,
-							     FALSE, flag))
-		  return FALSE;
-	      }
-	    else
-	      {
-		BFD_ASSERT (flag == GOT_TLS_LDM || r_symndx != STN_UNDEF);
-
-		if (!mips_elf_record_local_got_symbol (abfd, r_symndx,
-						       rel->r_addend,
-						       info, flag))
-		  return FALSE;
-	      }
-	  }
+	  if (h != NULL)
+	    {
+	      if (!mips_elf_record_global_got_symbol (h, abfd, info,
+						      FALSE, r_type))
+		return FALSE;
+	    }
+	  else
+	    {
+	      if (!mips_elf_record_local_got_symbol (abfd, r_symndx,
+						     rel->r_addend,
+						     info, r_type))
+		return FALSE;
+	    }
 	  break;
 
 	case R_MIPS_32:
@@ -10036,7 +10015,7 @@ _bfd_mips_elf_finish_dynamic_symbol (bfd
       MIPS_ELF_PUT_WORD (output_bfd, value, sgot->contents + offset);
     }
 
-  if (hmips->global_got_area != GGA_NONE && g->next && h->type != STT_TLS)
+  if (hmips->global_got_area != GGA_NONE && g->next)
     {
       struct mips_got_entry e, *p;
       bfd_vma entry;
@@ -11551,8 +11530,10 @@ _bfd_mips_elf_copy_indirect_symbol (stru
   if (indmips->has_nonpic_branches)
     dirmips->has_nonpic_branches = TRUE;
 
-  if (dirmips->tls_type == 0)
-    dirmips->tls_type = indmips->tls_type;
+  if (dirmips->tls_ie_type == 0)
+    dirmips->tls_ie_type = indmips->tls_ie_type;
+  if (dirmips->tls_gd_type == 0)
+    dirmips->tls_gd_type = indmips->tls_gd_type;
 }
 
 #define PDR_SIZE 32


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