bfd/
[deliverable/binutils-gdb.git] / bfd / elfxx-mips.c
index 403627340503e633ea12bec3aa9e5f4bf1848d80..a9f65bcc7c3261abafe405a0a6c4394e00f1d627 100644 (file)
@@ -1,6 +1,6 @@
 /* MIPS-specific support for ELF
    Copyright 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002,
-   2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011, 2012
+   2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011, 2012, 2013
    Free Software Foundation, Inc.
 
    Most of the information added by Ian Lance Taylor, Cygnus Support,
@@ -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
@@ -142,9 +140,6 @@ struct mips_got_page_entry
 
 struct mips_got_info
 {
-  /* The global symbol in the GOT with the lowest index in the dynamic
-     symbol table.  */
-  struct elf_link_hash_entry *global_gotsym;
   /* The number of global .got entries.  */
   unsigned int global_gotno;
   /* The number of global .got entries that are in the GGA_RELOC_ONLY area.  */
@@ -366,17 +361,18 @@ struct mips_elf_link_hash_entry
 #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;
@@ -420,11 +416,6 @@ struct mips_elf_link_hash_entry
 struct mips_elf_link_hash_table
 {
   struct elf_link_hash_table root;
-#if 0
-  /* We no longer use this.  */
-  /* String section indices for the dynamic section symbols.  */
-  bfd_size_type dynsym_sec_strindex[SIZEOF_MIPS_DYNSYM_SECNAMES];
-#endif
 
   /* The number of .rtproc entries.  */
   bfd_size_type procedure_count;
@@ -465,6 +456,10 @@ struct mips_elf_link_hash_table
   /* The master GOT information.  */
   struct mips_got_info *got_info;
 
+  /* The global symbol in the GOT with the lowest index in the dynamic
+     symbol table.  */
+  struct elf_link_hash_entry *global_gotsym;
+
   /* The size of the PLT header in bytes.  */
   bfd_vma plt_header_size;
 
@@ -703,8 +698,6 @@ static bfd_boolean mips_elf_create_dynamic_relocation
   (bfd *, struct bfd_link_info *, const Elf_Internal_Rela *,
    struct mips_elf_link_hash_entry *, asection *, bfd_vma,
    bfd_vma *, asection *);
-static hashval_t mips_elf_got_entry_hash
-  (const void *);
 static bfd_vma mips_elf_adjust_gp
   (bfd *, struct mips_got_info *, bfd *);
 static struct mips_got_info *mips_elf_got_for_ibfd
@@ -1117,7 +1110,8 @@ mips_elf_link_hash_newfunc (struct bfd_hash_entry *entry,
       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,33 +2793,18 @@ mips_elf_hash_bfd_vma (bfd_vma addr)
    use all fields to compute the hash, and compare the appropriate
    union members.  */
 
-static hashval_t
-mips_elf_got_entry_hash (const void *entry_)
-{
-  const struct mips_got_entry *entry = (struct mips_got_entry *)entry_;
-
-  return entry->symndx
-    + ((entry->tls_type & GOT_TLS_LDM) << 17)
-    + (! entry->abfd ? mips_elf_hash_bfd_vma (entry->d.address)
-       : entry->abfd->id
-         + (entry->symndx >= 0 ? mips_elf_hash_bfd_vma (entry->d.addend)
-           : entry->d.h->root.root.root.hash));
-}
-
 static int
 mips_elf_got_entry_eq (const void *entry1, const void *entry2)
 {
   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,
@@ -2834,19 +2813,17 @@ mips_elf_got_entry_eq (const void *entry1, const void *entry2)
    accordingly.  */
 
 static hashval_t
-mips_elf_multi_got_entry_hash (const void *entry_)
+mips_elf_got_entry_hash (const void *entry_)
 {
   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
@@ -2855,19 +2832,13 @@ mips_elf_multi_got_entry_eq (const void *entry1, const void *entry2)
   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
@@ -2889,6 +2860,36 @@ mips_got_page_entry_eq (const void *entry1_, const void *entry2_)
   return entry1->abfd == entry2->abfd && entry1->symndx == entry2->symndx;
 }
 \f
+/* Create and return a new mips_got_info structure.  MASTER_GOT_P
+   is true if this is the master GOT rather than a multigot.  */
+
+static struct mips_got_info *
+mips_elf_create_got_info (bfd *abfd, bfd_boolean master_got_p)
+{
+  struct mips_got_info *g;
+
+  g = bfd_zalloc (abfd, sizeof (struct mips_got_info));
+  if (g == NULL)
+    return NULL;
+
+  g->tls_ldm_offset = MINUS_ONE;
+  if (master_got_p)
+    g->got_entries = htab_try_create (1, mips_elf_got_entry_hash,
+                                     mips_elf_got_entry_eq, NULL);
+  else
+    g->got_entries = htab_try_create (1, mips_elf_got_entry_hash,
+                                     mips_elf_multi_got_entry_eq, NULL);
+  if (g->got_entries == NULL)
+    return NULL;
+
+  g->got_page_entries = htab_try_create (1, mips_got_page_entry_hash,
+                                        mips_got_page_entry_eq, NULL);
+  if (g->got_page_entries == NULL)
+    return NULL;
+
+  return g;
+}
+
 /* Return the dynamic relocation section.  If it doesn't exist, try to
    create a new it if CREATE_P, otherwise return NULL.  Also return NULL
    if creation fails.  */
@@ -2920,6 +2921,43 @@ mips_elf_rel_dyn_section (struct bfd_link_info *info, bfd_boolean create_p)
   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).  */
@@ -2929,7 +2967,6 @@ mips_tls_got_relocs (struct bfd_link_info *info, unsigned char tls_type,
                     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;
 
@@ -2944,22 +2981,22 @@ mips_tls_got_relocs (struct bfd_link_info *info, unsigned char tls_type,
     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
@@ -2987,9 +3024,13 @@ mips_elf_count_global_tls_entries (void *arg1, void *arg2)
     = (struct mips_elf_link_hash_entry *) arg1;
   struct mips_elf_count_tls_arg *arg = arg2;
 
-  if (hm->tls_type & GOT_TLS_GD)
+  if (hm->root.root.type == bfd_link_hash_indirect
+      || hm->root.root.type == bfd_link_hash_warning)
+    return 1;
+
+  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;
@@ -3005,7 +3046,12 @@ mips_elf_count_global_tls_relocs (void *arg1, void *arg2)
     = (struct mips_elf_link_hash_entry *) arg1;
   struct mips_elf_count_tls_arg *arg = arg2;
 
-  arg->needed += mips_tls_got_relocs (arg->info, hm->tls_type, &hm->root);
+  if (hm->root.root.type == bfd_link_hash_indirect
+      || hm->root.root.type == bfd_link_hash_warning)
+    return 1;
+
+  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;
 }
@@ -3053,7 +3099,7 @@ mips_elf_initialize_tls_slots (bfd *abfd, bfd_vma got_offset,
   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);
@@ -3090,65 +3136,59 @@ mips_elf_initialize_tls_slots (bfd *abfd, bfd_vma got_offset,
   /* 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,
@@ -3163,49 +3203,43 @@ mips_elf_initialize_tls_slots (bfd *abfd, bfd_vma got_offset,
          (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
@@ -3265,16 +3299,15 @@ mips_elf_local_got_index (bfd *abfd, bfd *ibfd, struct bfd_link_info *info,
   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;
@@ -3307,13 +3340,13 @@ mips_elf_global_got_index (bfd *abfd, bfd *ibfd, struct elf_link_hash_entry *h,
          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
@@ -3323,7 +3356,7 @@ mips_elf_global_got_index (bfd *abfd, bfd *ibfd, struct elf_link_hash_entry *h,
                         + 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
@@ -3331,8 +3364,8 @@ mips_elf_global_got_index (bfd *abfd, bfd *ibfd, struct elf_link_hash_entry *h,
        }
     }
 
-  if (gg->global_gotsym != NULL)
-    global_got_dynindx = gg->global_gotsym->dynindx;
+  if (htab->global_gotsym != NULL)
+    global_got_dynindx = htab->global_gotsym->dynindx;
 
   if (TLS_RELOC_P (r_type))
     {
@@ -3347,8 +3380,7 @@ mips_elf_global_got_index (bfd *abfd, bfd *ibfd, struct elf_link_hash_entry *h,
                 + 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
     {
@@ -3464,7 +3496,7 @@ mips_elf_create_local_got_entry (bfd *abfd, struct bfd_link_info *info,
   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)
@@ -3476,14 +3508,13 @@ mips_elf_create_local_got_entry (bfd *abfd, struct bfd_link_info *info,
   /* 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;
        }
@@ -3508,7 +3539,6 @@ mips_elf_create_local_got_entry (bfd *abfd, struct bfd_link_info *info,
     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);
 
@@ -3619,7 +3649,7 @@ mips_elf_sort_hash_table (bfd *abfd, struct bfd_link_info *info)
 
   /* Now we know which dynamic symbol has the lowest dynamic symbol
      table index in the GOT.  */
-  g->global_gotsym = hsd.low;
+  htab->global_gotsym = hsd.low;
 
   return TRUE;
 }
@@ -3645,15 +3675,11 @@ mips_elf_sort_hash_table_f (struct mips_elf_link_hash_entry *h, void *data)
       break;
 
     case GGA_NORMAL:
-      BFD_ASSERT (h->tls_type == GOT_NORMAL);
-
       h->root.dynindx = --hsd->min_got_dynindx;
       hsd->low = (struct elf_link_hash_entry *) h;
       break;
 
     case GGA_RELOC_ONLY:
-      BFD_ASSERT (h->tls_type == GOT_NORMAL);
-
       if (hsd->max_unref_got_dynindx == hsd->min_got_dynindx)
        hsd->low = (struct elf_link_hash_entry *) h;
       h->root.dynindx = hsd->max_unref_got_dynindx++;
@@ -3663,16 +3689,14 @@ mips_elf_sort_hash_table_f (struct mips_elf_link_hash_entry *h, void *data)
   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;
@@ -3708,7 +3732,7 @@ mips_elf_record_global_got_symbol (struct elf_link_hash_entry *h,
   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);
@@ -3716,10 +3740,7 @@ mips_elf_record_global_got_symbol (struct elf_link_hash_entry *h,
   /* 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);
 
@@ -3727,23 +3748,25 @@ mips_elf_record_global_got_symbol (struct elf_link_hash_entry *h,
     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;
@@ -3758,44 +3781,26 @@ mips_elf_record_local_got_symbol (bfd *abfd, long symndx, bfd_vma addend,
   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;
 
-  if (tls_flag != 0)
+  entry.gotidx = -1;
+  if (entry.tls_type)
     {
-      entry.gotidx = -1;
-      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
-    {
-      entry.gotidx = g->local_gotno++;
-      entry.tls_type = 0;
-    }
+    g->local_gotno += 1;
 
   *loc = (struct mips_got_entry *)bfd_alloc (abfd, sizeof entry);
 
@@ -4007,8 +4012,6 @@ mips_elf_recreate_got (void **entryp, void *data)
     }
   if (*slot == NULL)
     *slot = entry;
-  else
-    free (entry);
   return 1;
 }
 
@@ -4032,8 +4035,6 @@ mips_elf_resolve_final_got_entries (struct mips_got_info *g)
       if (new_got == NULL)
        return FALSE;
 
-      /* Each entry in g->got_entries has either been copied to new_got
-        or freed.  Now delete the hash table itself.  */
       htab_delete (g->got_entries);
       g->got_entries = new_got;
     }
@@ -4142,7 +4143,6 @@ mips_elf_get_got_for_bfd (struct htab *bfd2got, bfd *output_bfd,
                          bfd *input_bfd)
 {
   struct mips_elf_bfd2got_hash bfdgot_entry, *bfdgot;
-  struct mips_got_info *g;
   void **bfdgotp;
 
   bfdgot_entry.bfd = input_bfd;
@@ -4158,35 +4158,10 @@ mips_elf_get_got_for_bfd (struct htab *bfd2got, bfd *output_bfd,
 
       *bfdgotp = bfdgot;
 
-      g = ((struct mips_got_info *)
-          bfd_alloc (output_bfd, sizeof (struct mips_got_info)));
-      if (g == NULL)
-       return NULL;
-
       bfdgot->bfd = input_bfd;
-      bfdgot->g = g;
-
-      g->global_gotsym = NULL;
-      g->global_gotno = 0;
-      g->reloc_only_gotno = 0;
-      g->local_gotno = 0;
-      g->page_gotno = 0;
-      g->assigned_gotno = -1;
-      g->tls_gotno = 0;
-      g->tls_assigned_gotno = 0;
-      g->tls_ldm_offset = MINUS_ONE;
-      g->got_entries = htab_try_create (1, mips_elf_multi_got_entry_hash,
-                                       mips_elf_multi_got_entry_eq, NULL);
-      if (g->got_entries == NULL)
-       return NULL;
-
-      g->got_page_entries = htab_try_create (1, mips_got_page_entry_hash,
-                                            mips_got_page_entry_eq, NULL);
-      if (g->got_page_entries == NULL)
+      bfdgot->g = mips_elf_create_got_info (input_bfd, FALSE);
+      if (bfdgot->g == NULL)
        return NULL;
-
-      g->bfd2got = NULL;
-      g->next = NULL;
     }
 
   return bfdgot->g;
@@ -4219,16 +4194,11 @@ mips_elf_make_got_per_bfd (void **entryp, void *p)
   *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;
 }
@@ -4284,10 +4254,10 @@ mips_elf_merge_got_with (struct mips_elf_bfd2got_hash *bfd2got,
   estimate += from->local_gotno + to->local_gotno;
   estimate += from->tls_gotno + to->tls_gotno;
 
-  /* If we're merging with the primary got, we will always have
-     the full set of global entries.  Otherwise estimate those
+  /* If we're merging with the primary got, any TLS relocations will
+     come after the full set of global entries.  Otherwise estimate those
      conservatively as well.  */
-  if (to == arg->primary)
+  if (to == arg->primary && from->tls_gotno + to->tls_gotno)
     estimate += arg->global_count;
   else
     estimate += from->global_gotno + to->global_gotno;
@@ -4392,7 +4362,8 @@ mips_elf_initialize_tls_index (void **entryp, void *p)
   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;
@@ -4401,15 +4372,25 @@ mips_elf_initialize_tls_index (void **entryp, void *p)
     {
       /* 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
@@ -4422,15 +4403,10 @@ mips_elf_initialize_tls_index (void **entryp, void *p)
          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;
 }
 
@@ -4466,8 +4442,6 @@ mips_elf_set_global_got_offset (void **entryp, void *p)
     {
       if (g)
        {
-         BFD_ASSERT (g->global_gotsym == NULL);
-
          entry->gotidx = arg->value * (long) g->assigned_gotno++;
          if (arg->info->shared
              || (elf_hash_table (arg->info)->dynamic_sections_created
@@ -4589,33 +4563,7 @@ mips_elf_multi_got (bfd *abfd, struct bfd_link_info *info,
 
   /* If we do not find any suitable primary GOT, create an empty one.  */
   if (got_per_bfd_arg.primary == NULL)
-    {
-      g->next = (struct mips_got_info *)
-       bfd_alloc (abfd, sizeof (struct mips_got_info));
-      if (g->next == NULL)
-       return FALSE;
-
-      g->next->global_gotsym = NULL;
-      g->next->global_gotno = 0;
-      g->next->reloc_only_gotno = 0;
-      g->next->local_gotno = 0;
-      g->next->page_gotno = 0;
-      g->next->tls_gotno = 0;
-      g->next->assigned_gotno = 0;
-      g->next->tls_assigned_gotno = 0;
-      g->next->tls_ldm_offset = MINUS_ONE;
-      g->next->got_entries = htab_try_create (1, mips_elf_multi_got_entry_hash,
-                                             mips_elf_multi_got_entry_eq,
-                                             NULL);
-      if (g->next->got_entries == NULL)
-       return FALSE;
-      g->next->got_page_entries = htab_try_create (1, mips_got_page_entry_hash,
-                                                  mips_got_page_entry_eq,
-                                                  NULL);
-      if (g->next->got_page_entries == NULL)
-       return FALSE;
-      g->next->bfd2got = NULL;
-    }
+    g->next = mips_elf_create_got_info (abfd, FALSE);
   else
     g->next = got_per_bfd_arg.primary;
   g->next->next = got_per_bfd_arg.current;
@@ -4701,6 +4649,7 @@ mips_elf_multi_got (bfd *abfd, struct bfd_link_info *info,
         all non-TLS entries.  */
       g->tls_assigned_gotno = g->local_gotno + g->global_gotno;
       htab_traverse (g->got_entries, mips_elf_initialize_tls_index, g);
+      BFD_ASSERT (g->tls_assigned_gotno == assign);
 
       /* Move onto the next GOT.  It will be a secondary GOT if nonull.  */
       g = gn;
@@ -4712,9 +4661,7 @@ mips_elf_multi_got (bfd *abfd, struct bfd_link_info *info,
     }
   while (g);
 
-  got->size = (gg->next->local_gotno
-              + gg->next->global_gotno
-              + gg->next->tls_gotno) * MIPS_ELF_GOT_SIZE (abfd);
+  got->size = assign * MIPS_ELF_GOT_SIZE (abfd);
 
   needed_relocs = 0;
   set_got_offset_arg.value = MIPS_ELF_GOT_SIZE (abfd);
@@ -4900,8 +4847,6 @@ mips_elf_create_got_section (bfd *abfd, struct bfd_link_info *info)
   register asection *s;
   struct elf_link_hash_entry *h;
   struct bfd_link_hash_entry *bh;
-  struct mips_got_info *g;
-  bfd_size_type amt;
   struct mips_elf_link_hash_table *htab;
 
   htab = mips_elf_hash_table (info);
@@ -4941,29 +4886,7 @@ mips_elf_create_got_section (bfd *abfd, struct bfd_link_info *info)
       && ! bfd_elf_link_record_dynamic_symbol (info, h))
     return FALSE;
 
-  amt = sizeof (struct mips_got_info);
-  g = bfd_alloc (abfd, amt);
-  if (g == NULL)
-    return FALSE;
-  g->global_gotsym = NULL;
-  g->global_gotno = 0;
-  g->reloc_only_gotno = 0;
-  g->tls_gotno = 0;
-  g->local_gotno = 0;
-  g->page_gotno = 0;
-  g->assigned_gotno = 0;
-  g->bfd2got = NULL;
-  g->next = NULL;
-  g->tls_ldm_offset = MINUS_ONE;
-  g->got_entries = htab_try_create (1, mips_elf_got_entry_hash,
-                                   mips_elf_got_entry_eq, NULL);
-  if (g->got_entries == NULL)
-    return FALSE;
-  g->got_page_entries = htab_try_create (1, mips_got_page_entry_hash,
-                                        mips_got_page_entry_eq, NULL);
-  if (g->got_page_entries == NULL)
-    return FALSE;
-  htab->got_info = g;
+  htab->got_info = mips_elf_create_got_info (abfd, TRUE);
   mips_elf_section_data (s)->elf.this_hdr.sh_flags
     |= SHF_ALLOC | SHF_WRITE | SHF_MIPS_GPREL;
 
@@ -5330,7 +5253,7 @@ mips_elf_calculate_relocation (bfd *abfd, bfd *input_bfd,
          if (h->call_stub != NULL && h->call_fp_stub != NULL)
            {
              asection *o;
-             
+
              sec = NULL;
              for (o = input_bfd->sections; o != NULL; o = o->next)
                {
@@ -5463,7 +5386,7 @@ mips_elf_calculate_relocation (bfd *abfd, bfd *input_bfd,
              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);
@@ -5919,7 +5842,7 @@ mips_elf_obtain_contents (reloc_howto_type *howto,
 /* It has been determined that the result of the RELOCATION is the
    VALUE.  Use HOWTO to place VALUE into the output file at the
    appropriate position.  The SECTION is the section to which the
-   relocation applies.  
+   relocation applies.
    CROSS_MODE_JUMP_P is true if the relocation field
    is a MIPS16 or microMIPS jump to standard MIPS code, or vice versa.
 
@@ -6294,6 +6217,9 @@ _bfd_elf_mips_mach (flagword flags)
     case E_MIPS_MACH_5500:
       return bfd_mach_mips5500;
 
+    case E_MIPS_MACH_5900:
+      return bfd_mach_mips5900;
+
     case E_MIPS_MACH_9000:
       return bfd_mach_mips9000;
 
@@ -7837,14 +7763,14 @@ _bfd_mips_elf_check_relocs (bfd *abfd, struct bfd_link_info *info,
        {
          h = ((struct mips_elf_link_hash_entry *)
               sym_hashes[r_symndx - extsymoff]);
-         
+
          /* H is the symbol this stub is for.  */
-         
+
          if (CALL_FP_STUB_P (name))
            loc = &h->call_fp_stub;
          else
            loc = &h->call_stub;
-         
+
          /* If we already have an appropriate stub for this function, we
             don't need another one, so we can discard this one.  Since
             this function is called before the linker maps input sections
@@ -8048,7 +7974,7 @@ _bfd_mips_elf_check_relocs (bfd *abfd, struct bfd_link_info *info,
             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;
        }
 
@@ -8081,7 +8007,8 @@ _bfd_mips_elf_check_relocs (bfd *abfd, struct bfd_link_info *info,
              /* 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
@@ -8146,7 +8073,7 @@ _bfd_mips_elf_check_relocs (bfd *abfd, struct bfd_link_info *info,
        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;
 
@@ -8172,32 +8099,19 @@ _bfd_mips_elf_check_relocs (bfd *abfd, struct bfd_link_info *info,
        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:
@@ -8966,6 +8880,8 @@ mips_elf_lay_out_got (bfd *output_bfd, struct bfd_link_info *info)
       /* Set up TLS entries.  */
       g->tls_assigned_gotno = g->global_gotno + g->local_gotno;
       htab_traverse (g->got_entries, mips_elf_initialize_tls_index, g);
+      BFD_ASSERT (g->tls_assigned_gotno
+                 == g->global_gotno + g->local_gotno + g->tls_gotno);
 
       /* Allocate room for the TLS relocations.  */
       arg.info = info;
@@ -10099,7 +10015,7 @@ _bfd_mips_elf_finish_dynamic_symbol (bfd *output_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;
@@ -10656,9 +10572,9 @@ _bfd_mips_elf_finish_dynamic_sections (bfd *output_bfd,
              break;
 
            case DT_MIPS_GOTSYM:
-             if (gg->global_gotsym)
+             if (htab->global_gotsym)
                {
-                 dyn.d_un.d_val = gg->global_gotsym->dynindx;
+                 dyn.d_un.d_val = htab->global_gotsym->dynindx;
                  break;
                }
              /* In case if we don't have global got symbols we default
@@ -11026,6 +10942,10 @@ mips_set_isa_flags (bfd *abfd)
       val = E_MIPS_ARCH_4 | E_MIPS_MACH_5500;
       break;
 
+    case bfd_mach_mips5900:
+      val = E_MIPS_ARCH_3 | E_MIPS_MACH_5900;
+      break;
+
     case bfd_mach_mips9000:
       val = E_MIPS_ARCH_4 | E_MIPS_MACH_9000;
       break;
@@ -11610,8 +11530,10 @@ _bfd_mips_elf_copy_indirect_symbol (struct bfd_link_info *info,
   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;
 }
 \f
 #define PDR_SIZE 32
@@ -12942,7 +12864,7 @@ _bfd_mips_elf_link_hash_table_create (bfd *abfd)
   struct mips_elf_link_hash_table *ret;
   bfd_size_type amt = sizeof (struct mips_elf_link_hash_table);
 
-  ret = bfd_malloc (amt);
+  ret = bfd_zmalloc (amt);
   if (ret == NULL)
     return NULL;
 
@@ -12955,36 +12877,6 @@ _bfd_mips_elf_link_hash_table_create (bfd *abfd)
       return NULL;
     }
 
-#if 0
-  /* We no longer use this.  */
-  for (i = 0; i < SIZEOF_MIPS_DYNSYM_SECNAMES; i++)
-    ret->dynsym_sec_strindex[i] = (bfd_size_type) -1;
-#endif
-  ret->procedure_count = 0;
-  ret->compact_rel_size = 0;
-  ret->use_rld_obj_head = FALSE;
-  ret->rld_symbol = NULL;
-  ret->mips16_stubs_seen = FALSE;
-  ret->use_plts_and_copy_relocs = FALSE;
-  ret->is_vxworks = FALSE;
-  ret->small_data_overflow_reported = FALSE;
-  ret->srelbss = NULL;
-  ret->sdynbss = NULL;
-  ret->srelplt = NULL;
-  ret->srelplt2 = NULL;
-  ret->sgotplt = NULL;
-  ret->splt = NULL;
-  ret->sstubs = NULL;
-  ret->sgot = NULL;
-  ret->got_info = NULL;
-  ret->plt_header_size = 0;
-  ret->plt_entry_size = 0;
-  ret->lazy_stub_count = 0;
-  ret->function_stub_size = 0;
-  ret->strampoline = NULL;
-  ret->la25_stubs = NULL;
-  ret->add_stub_section = NULL;
-
   return &ret->root.root;
 }
 
@@ -13708,6 +13600,7 @@ static const struct mips_mach_extension mips_mach_extensions[] = {
   { bfd_mach_mips4300, bfd_mach_mips4000 },
   { bfd_mach_mips4100, bfd_mach_mips4000 },
   { bfd_mach_mips4010, bfd_mach_mips4000 },
+  { bfd_mach_mips5900, bfd_mach_mips4000 },
 
   /* MIPS32 extensions.  */
   { bfd_mach_mipsisa32r2, bfd_mach_mipsisa32 },
@@ -14024,7 +13917,7 @@ _bfd_mips_elf_merge_private_bfd_data (bfd *ibfd, bfd *obfd)
 
       if (bfd_get_arch (obfd) == bfd_get_arch (ibfd)
          && (bfd_get_arch_info (obfd)->the_default
-             || mips_mach_extends_p (bfd_get_mach (obfd), 
+             || mips_mach_extends_p (bfd_get_mach (obfd),
                                      bfd_get_mach (ibfd))))
        {
          if (! bfd_set_arch_mach (obfd, bfd_get_arch (ibfd),
This page took 0.041301 seconds and 4 git commands to generate.