Restore GET_SAVED_REGISTERS
[deliverable/binutils-gdb.git] / bfd / elf32-mips.c
index d91bab9726841e2e304b21e4d74a8381a2e40639..5ab839e06cda59a95c27c5ae73944efe912dfd03 100644 (file)
@@ -5,6 +5,8 @@
    <ian@cygnus.com>.
    N32/64 ABI support added by Mark Mitchell, CodeSourcery, LLC.
    <mark@codesourcery.com>
+   Traditional MIPS targets support added by Koundinya.K, Dansk Data
+   Elektronik & Operations Research Group. <kk@ddeorg.soft.net>
 
 This file is part of BFD, the Binary File Descriptor library.
 
@@ -40,7 +42,7 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.  */
 #include "coff/internal.h"
 #include "coff/ecoff.h"
 #include "coff/mips.h"
-#define ECOFF_32
+#define ECOFF_SIGNED_32
 #include "ecoffswap.h"
 
 /* This structure is used to hold .got information when linking.  It
@@ -182,11 +184,11 @@ static asection * mips_elf_got_section PARAMS ((bfd *));
 static struct mips_got_info *mips_elf_got_info 
   PARAMS ((bfd *, asection **));
 static boolean mips_elf_local_relocation_p
-  PARAMS ((bfd *, const Elf_Internal_Rela *, asection **));
+  PARAMS ((bfd *, const Elf_Internal_Rela *, asection **, boolean));
 static bfd_vma mips_elf_create_local_got_entry 
   PARAMS ((bfd *, struct mips_got_info *, asection *, bfd_vma));
 static bfd_vma mips_elf_got16_entry 
-  PARAMS ((bfd *, struct bfd_link_info *, bfd_vma));
+  PARAMS ((bfd *, struct bfd_link_info *, bfd_vma, boolean));
 static boolean mips_elf_create_dynamic_relocation 
   PARAMS ((bfd *, struct bfd_link_info *, const Elf_Internal_Rela *,
           struct mips_elf_link_hash_entry *, asection *,
@@ -195,6 +197,10 @@ static void mips_elf_allocate_dynamic_relocations
   PARAMS ((bfd *, unsigned int));
 static boolean mips_elf_stub_section_p 
   PARAMS ((bfd *, asection *));
+static int sort_dynamic_relocs
+  PARAMS ((const void *, const void *));
+
+extern const bfd_target bfd_elf32_tradbigmips_vec;
 
 /* The level of IRIX compatibility we're striving for.  */
 
@@ -204,6 +210,9 @@ typedef enum {
   ict_irix6
 } irix_compat_t;
 
+/* This will be used when we sort the dynamic relocation records.  */
+static bfd *reldyn_sorting_bfd;
+
 /* Nonzero if ABFD is using the N32 ABI.  */
 
 #define ABI_N32_P(abfd) \
@@ -214,12 +223,12 @@ typedef enum {
 #define ABI_64_P(abfd) \
   ((elf_elfheader (abfd)->e_ident[EI_CLASS] == ELFCLASS64) != 0)
 
-/* What version of Irix we are trying to be compatible with.  FIXME:
-   At the moment, we never generate "normal" MIPS ELF ABI executables;
-   we always use some version of Irix.  */
+/* Depending on the target vector we generate some version of Irix
+   executables or "normal" MIPS ELF ABI executables. */
 
 #define IRIX_COMPAT(abfd) \
-  ((ABI_N32_P (abfd) || ABI_64_P (abfd)) ? ict_irix6 : ict_irix5)
+  (abfd->xvec == &bfd_elf32_tradbigmips_vec ? ict_none : \
+  ((ABI_N32_P (abfd) || ABI_64_P (abfd)) ? ict_irix6 : ict_irix5))
 
 /* Whether we are trying to be compatible with IRIX at all.  */
 
@@ -297,10 +306,12 @@ typedef enum {
    ? (ABI_64_P (abfd)                                                  \
       ? 0xdf998010             /* ld t9,0x8010(gp) */          \
       : 0x8f998010)             /* lw t9,0x8010(gp) */         \
-   : 0x8f998000)               /* lw t9,0x8000(gp) */
-#define STUB_MOVE 0x03e07825   /* move t7,ra */
-#define STUB_JALR 0x0320f809   /* jal t9 */
-#define STUB_LI16 0x34180000   /* ori t8,zero,0 */
+   : 0x8f998010)               /* lw t9,0x8000(gp) */
+#define STUB_MOVE(abfd)                                         \
+  (SGI_COMPAT (abfd) ? 0x03e07825 : 0x03e07821)         /* move t7,ra */
+#define STUB_JALR 0x0320f809                           /* jal t9 */
+#define STUB_LI16(abfd)                                         \
+  (SGI_COMPAT (abfd) ? 0x34180000 : 0x24180000)         /* ori t8,zero,0 */
 #define MIPS_FUNCTION_STUB_SIZE (16)
 
 #if 0
@@ -944,7 +955,6 @@ static reloc_howto_type elf_mips16_gprel_howto =
         0x07ff001f,            /* dst_mask */
         false);                /* pcrel_offset */
 
-
 /* GNU extensions for embedded-pic.  */
 /* High 16 bits of symbol value, pc-relative.  */
 static reloc_howto_type elf_mips_gnu_rel_hi16 =
@@ -1520,7 +1530,7 @@ gprel16_with_gp (abfd, symbol, reloc_entry, input_section, relocateable, data,
     reloc_entry->address += input_section->output_offset;
 
   /* Make sure it fit in 16 bits.  */
-  if (val >= 0x8000 && val < 0xffff8000)
+  if ((long) val >= 0x8000 || (long) val < -0x8000)
     return bfd_reloc_overflow;
 
   return bfd_reloc_ok;
@@ -2460,21 +2470,8 @@ _bfd_mips_elf_merge_private_bfd_data (ibfd, obfd)
   boolean ok;
 
   /* Check if we have the same endianess */
-  if (ibfd->xvec->byteorder != obfd->xvec->byteorder
-      && obfd->xvec->byteorder != BFD_ENDIAN_UNKNOWN)
-    {
-      const char *msg;
-
-      if (bfd_big_endian (ibfd))
-       msg = _("%s: compiled for a big endian system and target is little endian");
-      else
-       msg = _("%s: compiled for a little endian system and target is big endian");
-
-      (*_bfd_error_handler) (msg, bfd_get_filename (ibfd));
-
-      bfd_set_error (bfd_error_wrong_format);
-      return false;
-    }
+  if (_bfd_generic_verify_endian_match (ibfd, obfd) == false)
+    return false;
 
   if (bfd_get_flavour (ibfd) != bfd_target_elf_flavour
       || bfd_get_flavour (obfd) != bfd_target_elf_flavour)
@@ -2884,17 +2881,23 @@ _bfd_mips_elf_fake_sections (abfd, hdr, sec)
       hdr->sh_type = SHT_MIPS_REGINFO;
       /* In a shared object on Irix 5.3, the .reginfo section has an
          entsize of 0x18.  FIXME: Does this matter?  */
-      if (SGI_COMPAT (abfd) && (abfd->flags & DYNAMIC) != 0)
-       hdr->sh_entsize = sizeof (Elf32_External_RegInfo);
+      if (SGI_COMPAT (abfd))
+        {
+          if ((abfd->flags & DYNAMIC) != 0)
+            hdr->sh_entsize = sizeof (Elf32_External_RegInfo);
+          else
+            hdr->sh_entsize = 1;
+        }
       else
-       hdr->sh_entsize = 1;
+        hdr->sh_entsize = sizeof (Elf32_External_RegInfo);
     }
   else if (SGI_COMPAT (abfd)
           && (strcmp (name, ".hash") == 0
               || strcmp (name, ".dynamic") == 0
               || strcmp (name, ".dynstr") == 0))
     {
-      hdr->sh_entsize = 0;
+      if ( SGI_COMPAT(abfd))
+        hdr->sh_entsize = 0;
 #if 0
       /* This isn't how the Irix 6 linker behaves.  */
       hdr->sh_info = SIZEOF_MIPS_DYNSYM_SECNAMES;
@@ -3181,18 +3184,6 @@ static asection mips_elf_acom_section;
 static asymbol mips_elf_acom_symbol;
 static asymbol *mips_elf_acom_symbol_ptr;
 
-/* The Irix 5 support uses two virtual sections, which represent
-   text/data symbols defined in dynamic objects.  */
-static asection mips_elf_text_section;
-static asection *mips_elf_text_section_ptr;
-static asymbol mips_elf_text_symbol;
-static asymbol *mips_elf_text_symbol_ptr;
-
-static asection mips_elf_data_section;
-static asection *mips_elf_data_section_ptr;
-static asymbol mips_elf_data_symbol;
-static asymbol *mips_elf_data_symbol_ptr;
-
 /* Handle the special MIPS section numbers that a symbol may use.
    This is used for both the 32-bit and the 64-bit ABI.  */
 
@@ -3279,9 +3270,6 @@ _bfd_mips_elf_additional_program_headers (abfd)
   asection *s;
   int ret = 0;
 
-  if (!SGI_COMPAT (abfd))
-    return 0;
-
   /* See if we need a PT_MIPS_REGINFO segment.  */
   s = bfd_get_section_by_name (abfd, ".reginfo");
   if (s && (s->flags & SEC_LOAD))
@@ -3311,9 +3299,6 @@ _bfd_mips_elf_modify_segment_map (abfd)
   asection *s;
   struct elf_segment_map *m, **pm;
 
-  if (! SGI_COMPAT (abfd))
-    return true;
-
   /* If there is a .reginfo section, we need a PT_MIPS_REGINFO
      segment.  */
   s = bfd_get_section_by_name (abfd, ".reginfo");
@@ -3383,58 +3368,72 @@ _bfd_mips_elf_modify_segment_map (abfd)
     }
   else
     {
-      /* If there are .dynamic and .mdebug sections, we make a room
-        for the RTPROC header.  FIXME: Rewrite without section names.  */
-      if (bfd_get_section_by_name (abfd, ".interp") == NULL
-         && bfd_get_section_by_name (abfd, ".dynamic") != NULL
-         && bfd_get_section_by_name (abfd, ".mdebug") != NULL)
+      if (IRIX_COMPAT (abfd) == ict_irix5)
        {
-         for (m = elf_tdata (abfd)->segment_map; m != NULL; m = m->next)
-           if (m->p_type == PT_MIPS_RTPROC)
-             break;
-         if (m == NULL)
+         /* If there are .dynamic and .mdebug sections, we make a room
+            for the RTPROC header.  FIXME: Rewrite without section names.  */
+         if (bfd_get_section_by_name (abfd, ".interp") == NULL
+             && bfd_get_section_by_name (abfd, ".dynamic") != NULL
+             && bfd_get_section_by_name (abfd, ".mdebug") != NULL)
            {
-             m = (struct elf_segment_map *) bfd_zalloc (abfd, sizeof *m);
+             for (m = elf_tdata (abfd)->segment_map; m != NULL; m = m->next)
+               if (m->p_type == PT_MIPS_RTPROC)
+                 break;
              if (m == NULL)
-               return false;
+               {
+                 m = (struct elf_segment_map *) bfd_zalloc (abfd, sizeof *m);
+                 if (m == NULL)
+                   return false;
 
-             m->p_type = PT_MIPS_RTPROC;
+                 m->p_type = PT_MIPS_RTPROC;
 
-             s = bfd_get_section_by_name (abfd, ".rtproc");
-             if (s == NULL)
-               {
-                 m->count = 0;
-                 m->p_flags = 0;
-                 m->p_flags_valid = 1;
-               }
-             else
-               {
-                 m->count = 1;
-                 m->sections[0] = s;
-               }
+                 s = bfd_get_section_by_name (abfd, ".rtproc");
+                 if (s == NULL)
+                   {
+                     m->count = 0;
+                     m->p_flags = 0;
+                     m->p_flags_valid = 1;
+                   }
+                 else
+                   {
+                     m->count = 1;
+                     m->sections[0] = s;
+                   }
 
-             /* We want to put it after the DYNAMIC segment.  */
-             pm = &elf_tdata (abfd)->segment_map;
-             while (*pm != NULL && (*pm)->p_type != PT_DYNAMIC)
-               pm = &(*pm)->next;
-             if (*pm != NULL)
-               pm = &(*pm)->next;
+                 /* We want to put it after the DYNAMIC segment.  */
+                 pm = &elf_tdata (abfd)->segment_map;
+                 while (*pm != NULL && (*pm)->p_type != PT_DYNAMIC)
+                   pm = &(*pm)->next;
+                 if (*pm != NULL)
+                   pm = &(*pm)->next;
 
-             m->next = *pm;
-             *pm = m;
+                 m->next = *pm;
+                 *pm = m;
+               }
            }
        }
-
       /* On Irix 5, the PT_DYNAMIC segment includes the .dynamic,
         .dynstr, .dynsym, and .hash sections, and everything in
         between.  */
-      for (pm = &elf_tdata (abfd)->segment_map; *pm != NULL; pm = &(*pm)->next)
+      for (pm = &elf_tdata (abfd)->segment_map; *pm != NULL;
+          pm = &(*pm)->next)
        if ((*pm)->p_type == PT_DYNAMIC)
          break;
       m = *pm;
+      if (IRIX_COMPAT (abfd) == ict_none)
+       {
+         /* For a normal mips executable the permissions for the PT_DYNAMIC
+            segment are read, write and execute. We do that here since
+            the code in elf.c sets only the read permission. This matters
+            sometimes for the dynamic linker. */
+         if (bfd_get_section_by_name (abfd, ".dynamic") != NULL)
+           {
+             m->p_flags = PF_R | PF_W | PF_X;
+             m->p_flags_valid = 1;
+           }
+       }
       if (m != NULL
-         && m->count == 1
-         && strcmp (m->sections[0]->name, ".dynamic") == 0)
+         && m->count == 1 && strcmp (m->sections[0]->name, ".dynamic") == 0)
        {
          static const char *sec_names[] =
          { ".dynamic", ".dynstr", ".dynsym", ".hash" };
@@ -3466,8 +3465,8 @@ _bfd_mips_elf_modify_segment_map (abfd)
            if ((s->flags & SEC_LOAD) != 0
                && s->vma >= low
                && ((s->vma
-                    + (s->_cooked_size != 0 ? s->_cooked_size : s->_raw_size))
-                   <= high))
+                    + (s->_cooked_size !=
+                       0 ? s->_cooked_size : s->_raw_size)) <= high))
              ++c;
 
          n = ((struct elf_segment_map *)
@@ -3484,8 +3483,7 @@ _bfd_mips_elf_modify_segment_map (abfd)
                  && s->vma >= low
                  && ((s->vma
                       + (s->_cooked_size != 0 ?
-                         s->_cooked_size : s->_raw_size))
-                     <= high))
+                         s->_cooked_size : s->_raw_size)) <= high))
                {
                  n->sections[i] = s;
                  ++i;
@@ -3895,6 +3893,27 @@ mips_elf_link_hash_newfunc (entry, table, string)
   return (struct bfd_hash_entry *) ret;
 }
 
+void
+_bfd_mips_elf_hide_symbol(info, h)
+     struct bfd_link_info *info;
+     struct mips_elf_link_hash_entry *h;
+{
+  bfd *dynobj;
+  asection *got;
+  struct mips_got_info *g;
+  dynobj = elf_hash_table (info)->dynobj;
+  got = bfd_get_section_by_name (dynobj, ".got");
+  g = (struct mips_got_info *) elf_section_data (got)->tdata;
+
+  h->root.elf_link_hash_flags &= ~ELF_LINK_HASH_NEEDS_PLT;
+  h->root.plt.offset = (bfd_vma) -1;
+  h->root.dynindx = -1;
+
+  /* FIXME: Do we allocate too much GOT space here?  */
+  g->local_gotno++;
+  got->_raw_size += MIPS_ELF_GOT_SIZE (dynobj);
+}
+
 /* Create a MIPS ELF linker hash table.  */
 
 struct bfd_link_hash_table *
@@ -3969,48 +3988,78 @@ _bfd_mips_elf_add_symbol_hook (abfd, info, sym, namep, flagsp, secp, valp)
 
     case SHN_MIPS_TEXT:
       /* This section is used in a shared object.  */
-      if (mips_elf_text_section_ptr == NULL)
+      if (elf_tdata (abfd)->elf_text_section == NULL)
        {
+         asymbol *elf_text_symbol;
+         asection *elf_text_section;
+
+         elf_text_section = bfd_zalloc (abfd, sizeof (asection));
+         if (elf_text_section == NULL)
+           return false;
+
+         elf_text_symbol = bfd_zalloc (abfd, sizeof (asymbol));
+         if (elf_text_symbol == NULL)
+           return false;
+
          /* Initialize the section.  */
-         mips_elf_text_section.name = ".text";
-         mips_elf_text_section.flags = SEC_NO_FLAGS;
-         mips_elf_text_section.output_section = NULL;
-         mips_elf_text_section.symbol = &mips_elf_text_symbol;
-         mips_elf_text_section.symbol_ptr_ptr = &mips_elf_text_symbol_ptr;
-         mips_elf_text_symbol.name = ".text";
-         mips_elf_text_symbol.flags = BSF_SECTION_SYM | BSF_DYNAMIC;
-         mips_elf_text_symbol.section = &mips_elf_text_section;
-         mips_elf_text_symbol_ptr = &mips_elf_text_symbol;
-         mips_elf_text_section_ptr = &mips_elf_text_section;
+
+         elf_tdata (abfd)->elf_text_section = elf_text_section;
+         elf_tdata (abfd)->elf_text_symbol = elf_text_symbol;
+
+         elf_text_section->symbol = elf_text_symbol;
+         elf_text_section->symbol_ptr_ptr = &elf_tdata (abfd)->elf_text_symbol;
+
+         elf_text_section->name = ".text";
+         elf_text_section->flags = SEC_NO_FLAGS;
+         elf_text_section->output_section = NULL;
+         elf_text_section->owner = abfd;
+         elf_text_symbol->name = ".text";
+         elf_text_symbol->flags = BSF_SECTION_SYM | BSF_DYNAMIC;
+         elf_text_symbol->section = elf_text_section;
        }
       /* This code used to do *secp = bfd_und_section_ptr if
          info->shared.  I don't know why, and that doesn't make sense,
          so I took it out.  */
-      *secp = mips_elf_text_section_ptr;
+      *secp = elf_tdata (abfd)->elf_text_section;
       break;
 
     case SHN_MIPS_ACOMMON:
       /* Fall through. XXX Can we treat this as allocated data?  */
     case SHN_MIPS_DATA:
       /* This section is used in a shared object.  */
-      if (mips_elf_data_section_ptr == NULL)
+      if (elf_tdata (abfd)->elf_data_section == NULL)
        {
+         asymbol *elf_data_symbol;
+         asection *elf_data_section;
+
+         elf_data_section = bfd_zalloc (abfd, sizeof (asection));
+         if (elf_data_section == NULL)
+           return false;
+
+         elf_data_symbol = bfd_zalloc (abfd, sizeof (asymbol));
+         if (elf_data_symbol == NULL)
+           return false;
+
          /* Initialize the section.  */
-         mips_elf_data_section.name = ".data";
-         mips_elf_data_section.flags = SEC_NO_FLAGS;
-         mips_elf_data_section.output_section = NULL;
-         mips_elf_data_section.symbol = &mips_elf_data_symbol;
-         mips_elf_data_section.symbol_ptr_ptr = &mips_elf_data_symbol_ptr;
-         mips_elf_data_symbol.name = ".data";
-         mips_elf_data_symbol.flags = BSF_SECTION_SYM | BSF_DYNAMIC;
-         mips_elf_data_symbol.section = &mips_elf_data_section;
-         mips_elf_data_symbol_ptr = &mips_elf_data_symbol;
-         mips_elf_data_section_ptr = &mips_elf_data_section;
+
+         elf_tdata (abfd)->elf_data_section = elf_data_section;
+         elf_tdata (abfd)->elf_data_symbol = elf_data_symbol;
+
+         elf_data_section->symbol = elf_data_symbol;
+         elf_data_section->symbol_ptr_ptr = &elf_tdata (abfd)->elf_data_symbol;
+
+         elf_data_section->name = ".data";
+         elf_data_section->flags = SEC_NO_FLAGS;
+         elf_data_section->output_section = NULL;
+         elf_data_section->owner = abfd;
+         elf_data_symbol->name = ".data";
+         elf_data_symbol->flags = BSF_SECTION_SYM | BSF_DYNAMIC;
+         elf_data_symbol->section = elf_data_section;
        }
       /* This code used to do *secp = bfd_und_section_ptr if
          info->shared.  I don't know why, and that doesn't make sense,
          so I took it out.  */
-      *secp = mips_elf_data_section_ptr;
+      *secp = elf_tdata (abfd)->elf_data_section;
       break;
 
     case SHN_MIPS_SUNDEFINED:
@@ -4115,9 +4164,8 @@ mips_elf_output_extsym (h, data)
       h->esym.asym.value = 0;
       h->esym.asym.st = stGlobal;
 
-      if (SGI_COMPAT (einfo->abfd)
-         && (h->root.root.type == bfd_link_hash_undefined
-             || h->root.root.type == bfd_link_hash_undefweak))
+      if (h->root.root.type == bfd_link_hash_undefined
+             || h->root.root.type == bfd_link_hash_undefweak)
        {
          const char *name;
 
@@ -4427,6 +4475,15 @@ _bfd_mips_elf_final_link (abfd, info)
     = get_elf_backend_data (abfd)->elf_backend_ecoff_debug_swap;
   HDRR *symhdr = &debug.symbolic_header;
   PTR mdebug_handle = NULL;
+  asection *s;
+  EXTR esym;
+  bfd_vma last;
+  unsigned int i;
+  static const char * const name[] =
+      { ".text", ".init", ".fini", ".data",
+          ".rodata", ".sdata", ".sbss", ".bss" };
+  static const int sc[] = { scText, scInit, scFini, scData,
+                          scRData, scSData, scSBss, scBss };
 
   /* If all the things we linked together were PIC, but we're
      producing an executable (rather than a shared object), then the
@@ -4475,7 +4532,7 @@ _bfd_mips_elf_final_link (abfd, info)
      include it, even though we don't process it quite right.  (Some
      entries are supposed to be merged.)  Empirically, we seem to be
      better off including it then not.  */
-  if (IRIX_COMPAT (abfd) == ict_irix5)
+  if (IRIX_COMPAT (abfd) == ict_irix5 || IRIX_COMPAT (abfd) == ict_none)
     for (secpp = &abfd->sections; *secpp != NULL; secpp = &(*secpp)->next)
       {
        if (strcmp ((*secpp)->name, MIPS_ELF_OPTIONS_SECTION_NAME (abfd)) == 0)
@@ -4637,45 +4694,31 @@ _bfd_mips_elf_final_link (abfd, info)
          if (mdebug_handle == (PTR) NULL)
            return false;
 
-         if (SGI_COMPAT (abfd))
-           {
-             asection *s;
-             EXTR esym;
-             bfd_vma last;
-             unsigned int i;
-             static const char * const name[] =
-               { ".text", ".init", ".fini", ".data",
-                   ".rodata", ".sdata", ".sbss", ".bss" };
-             static const int sc[] = { scText, scInit, scFini, scData,
-                                         scRData, scSData, scSBss, scBss };
-
-             esym.jmptbl = 0;
-             esym.cobol_main = 0;
-             esym.weakext = 0;
-             esym.reserved = 0;
-             esym.ifd = ifdNil;
-             esym.asym.iss = issNil;
-             esym.asym.st = stLocal;
-             esym.asym.reserved = 0;
-             esym.asym.index = indexNil;
-             last = 0;
-             for (i = 0; i < 8; i++)
-               {
-                 esym.asym.sc = sc[i];
-                 s = bfd_get_section_by_name (abfd, name[i]);
-                 if (s != NULL)
-                   {
-                     esym.asym.value = s->vma;
-                     last = s->vma + s->_raw_size;
-                   }
-                 else
-                   esym.asym.value = last;
-
-                 if (! bfd_ecoff_debug_one_external (abfd, &debug, swap,
-                                                     name[i], &esym))
-                   return false;
-               }
-           }
+          esym.jmptbl = 0;
+          esym.cobol_main = 0;
+          esym.weakext = 0;
+          esym.reserved = 0;
+          esym.ifd = ifdNil;
+          esym.asym.iss = issNil;
+          esym.asym.st = stLocal;
+          esym.asym.reserved = 0;
+          esym.asym.index = indexNil;
+          last = 0;
+          for (i = 0; i < 8; i++)
+            {
+              esym.asym.sc = sc[i];
+              s = bfd_get_section_by_name (abfd, name[i]);
+              if (s != NULL)
+                {
+                  esym.asym.value = s->vma;
+                  last = s->vma + s->_raw_size;
+                }
+              else
+                esym.asym.value = last;
+              if (!bfd_ecoff_debug_one_external (abfd, &debug, swap,
+                                                 name[i], &esym))
+                return false;
+            }
 
          for (p = o->link_order_head;
               p != (struct bfd_link_order *) NULL;
@@ -5116,6 +5159,26 @@ _bfd_mips_elf_final_link (abfd, info)
   return true;
 }
 
+/* This function is called via qsort() to sort the dynamic relocation
+   entries by increasing r_symndx value.  */
+
+static int
+sort_dynamic_relocs (arg1,arg2)
+        const PTR arg1;
+        const PTR arg2;
+{
+  const Elf32_External_Rel *ext_reloc1 = (const Elf32_External_Rel *) arg1;
+  const Elf32_External_Rel *ext_reloc2 = (const Elf32_External_Rel *) arg2;
+
+  Elf_Internal_Rel int_reloc1;
+  Elf_Internal_Rel int_reloc2;
+
+  bfd_elf32_swap_reloc_in(reldyn_sorting_bfd, ext_reloc1, &int_reloc1);
+  bfd_elf32_swap_reloc_in(reldyn_sorting_bfd, ext_reloc2, &int_reloc2);
+
+  return (ELF32_R_SYM(int_reloc1.r_info) - ELF32_R_SYM(int_reloc2.r_info));
+}
+
 /* Returns the GOT section for ABFD.  */
 
 static asection *
@@ -5151,24 +5214,42 @@ mips_elf_got_info (abfd, sgotp)
 /* Return whether a relocation is against a local symbol.  */
 
 static boolean
-mips_elf_local_relocation_p (input_bfd, relocation, local_sections)
+mips_elf_local_relocation_p (input_bfd, relocation, local_sections,
+                            check_forced)
      bfd *input_bfd;
      const Elf_Internal_Rela *relocation;
      asection **local_sections;
+     boolean check_forced;
 {
   unsigned long r_symndx;
   Elf_Internal_Shdr *symtab_hdr;
+  struct mips_elf_link_hash_entry* h;
+  size_t extsymoff;
 
   r_symndx = ELF32_R_SYM (relocation->r_info);
   symtab_hdr = &elf_tdata (input_bfd)->symtab_hdr;
-  if (! elf_bad_symtab (input_bfd))
-    return r_symndx < symtab_hdr->sh_info;
-  else
+  extsymoff = (elf_bad_symtab (input_bfd)) ? 0 : symtab_hdr->sh_info;
+
+  if (r_symndx < extsymoff)
+    return true;
+  if (elf_bad_symtab (input_bfd) && local_sections[r_symndx] != NULL)
+    return true;
+
+  if (check_forced)
     {
-      /* The symbol table does not follow the rule that local symbols
-        must come before globals.  */
-      return local_sections[r_symndx] != NULL;
+       /* Look up the hash table to check whether the symbol
+        was forced local.  */
+       h = (struct mips_elf_link_hash_entry *)
+         elf_sym_hashes (input_bfd) [r_symndx - extsymoff];
+       /* Find the real hash-table entry for this symbol.  */
+       while (h->root.root.type == bfd_link_hash_indirect
+            || h->root.root.type == bfd_link_hash_warning)
+         h = (struct mips_elf_link_hash_entry *) h->root.root.u.i.link;
+       if ((h->root.elf_link_hash_flags & ELF_LINK_FORCED_LOCAL) != 0)
+         return true;
     }
+
+  return false;
 }
 
 /* Sign-extend VALUE, which has the indicated number of BITS.  */
@@ -5387,7 +5468,7 @@ mips_elf_sort_hash_table (info, max_local)
 
   /* There shoud have been enough room in the symbol table to
      accomodate both the GOT and non-GOT symbols.  */
-  BFD_ASSERT (hsd.min_got_dynindx == hsd.max_non_got_dynindx);
+  BFD_ASSERT (hsd.max_non_got_dynindx <= hsd.min_got_dynindx);
 
   /* Now we know which dynamic symbol has the lowest dynamic symbol
      table index in the GOT.  */
@@ -5509,10 +5590,11 @@ mips_elf_got_page (abfd, info, value, offsetp)
    for value.  Return the index into the GOT for this entry.  */
 
 static bfd_vma
-mips_elf_got16_entry (abfd, info, value)
+mips_elf_got16_entry (abfd, info, value, external)
      bfd *abfd;
      struct bfd_link_info *info;
      bfd_vma value;
+     boolean external;
 {
   asection *sgot;
   struct mips_got_info *g;
@@ -5521,11 +5603,15 @@ mips_elf_got16_entry (abfd, info, value)
   bfd_vma index = 0;
   bfd_vma address;
 
-  /* Although the ABI says that it is "the high-order 16 bits" that we
-     want, it is really the %high value.  The complete value is
-     calculated with a `addiu' of a LO16 relocation, just as with a
-     HI16/LO16 pair.  */
-  value = mips_elf_high (value) << 16;
+  if (! external)
+    {
+      /* Although the ABI says that it is "the high-order 16 bits" that we
+        want, it is really the %high value.  The complete value is
+        calculated with a `addiu' of a LO16 relocation, just as with a
+        HI16/LO16 pair.  */
+      value = mips_elf_high (value) << 16;
+    }
+
   g = mips_elf_got_info (elf_hash_table (info)->dynobj, &sgot);
 
   /* Look to see if we already have an appropriate entry.  */
@@ -5536,9 +5622,10 @@ mips_elf_got16_entry (abfd, info, value)
        entry += MIPS_ELF_GOT_SIZE (abfd))
     {
       address = MIPS_ELF_GET_WORD (abfd, entry);
-      if ((address & 0xffff0000) == value)
+      if (address == value)
        {
-         /* This entry has the right high-order 16 bits.  */
+         /* This entry has the right high-order 16 bits, and the low-order
+            16 bits are set to zero.  */
          index = entry - sgot->contents;
          break;
        }
@@ -5581,7 +5668,7 @@ mips_elf_next_relocation (r_type, relocation, relend)
 
 /* Create a rel.dyn relocation for the dynamic linker to resolve.  REL
    is the original relocation, which is now being transformed into a
-   dyanmic relocation.  The ADDENDP is adjusted if necessary; the
+   dynamic relocation.  The ADDENDP is adjusted if necessary; the
    caller should store the result in place of the original addend.  */
 
 static boolean
@@ -5608,6 +5695,7 @@ mips_elf_create_dynamic_relocation (output_bfd, info, rel, h, sec,
     = bfd_get_section_by_name (dynobj,
                               MIPS_ELF_REL_DYN_SECTION_NAME (output_bfd));
   BFD_ASSERT (sreloc != NULL);
+  BFD_ASSERT (sreloc->contents != NULL);
 
   skip = false;
 
@@ -5634,7 +5722,7 @@ mips_elf_create_dynamic_relocation (output_bfd, info, rel, h, sec,
        skip = true;
     }
 
-  /* If we've decided to skip this relocation, just output an emtpy
+  /* If we've decided to skip this relocation, just output an empty
      record.  Note that R_MIPS_NONE == 0, so that this call to memset
      is a way of setting R_TYPE to R_MIPS_NONE.  */
   if (skip)
@@ -5651,7 +5739,10 @@ mips_elf_create_dynamic_relocation (output_bfd, info, rel, h, sec,
                                   & ELF_LINK_HASH_DEF_REGULAR) == 0))
        {
          indx = h->root.dynindx;
-         BFD_ASSERT (indx != -1);
+         /* h->root.dynindx may be -1 if this symbol was marked to
+            become local.  */
+         if (indx == -1)
+               indx = 0;
        }
       else
        {
@@ -5849,7 +5940,7 @@ mips_elf_calculate_relocation (abfd,
      used in the array of hash table entries.  */
   symtab_hdr = &elf_tdata (input_bfd)->symtab_hdr;
   local_p = mips_elf_local_relocation_p (input_bfd, relocation,
-                                        local_sections);
+                                        local_sections, false);
   if (! elf_bad_symtab (input_bfd))
     extsymoff = symtab_hdr->sh_info;
   else
@@ -5890,8 +5981,8 @@ mips_elf_calculate_relocation (abfd,
       h = ((struct mips_elf_link_hash_entry *) 
           elf_sym_hashes (input_bfd) [r_symndx - extsymoff]);
       /* Find the real hash-table entry for this symbol.  */
-      while (h->root.type == bfd_link_hash_indirect
-            || h->root.type == bfd_link_hash_warning)
+      while (h->root.root.type == bfd_link_hash_indirect
+            || h->root.root.type == bfd_link_hash_warning)
        h = (struct mips_elf_link_hash_entry *) h->root.root.u.i.link;
       
       /* Record the name of this symbol, for our caller.  */
@@ -5930,12 +6021,15 @@ mips_elf_calculate_relocation (abfd,
           and check to see if they exist by looking at their
           addresses.  */
        symbol = 0;
-      else if (info->shared && !info->symbolic && !info->no_undefined)
+      else if (info->shared && !info->symbolic && !info->no_undefined
+              && ELF_ST_VISIBILITY (h->root.other) == STV_DEFAULT)
        symbol = 0;
-      else if (strcmp (h->root.root.root.string, "_DYNAMIC_LINK") == 0)
+      else if (strcmp (h->root.root.root.string, "_DYNAMIC_LINK") == 0 ||
+              strcmp (h->root.root.root.string, "_DYNAMIC_LINKING") == 0)
        {
          /* If this is a dynamic link, we should have created a
-            _DYNAMIC_LINK symbol in mips_elf_create_dynamic_sections.
+            _DYNAMIC_LINK symbol or _DYNAMIC_LINKING(for normal mips) symbol 
+            in in mips_elf_create_dynamic_sections.
             Otherwise, we should define the symbol with a value of 0.
             FIXME: It should probably get into the symbol table
             somehow as well.  */
@@ -5948,7 +6042,8 @@ mips_elf_calculate_relocation (abfd,
          if (! ((*info->callbacks->undefined_symbol)
                 (info, h->root.root.root.string, input_bfd,
                  input_section, relocation->r_offset,
-                 (!info->shared || info->no_undefined))))
+                 (!info->shared || info->no_undefined
+                  || ELF_ST_VISIBILITY (h->root.other)))))
            return bfd_reloc_undefined;
          symbol = 0;
        }
@@ -6019,6 +6114,9 @@ mips_elf_calculate_relocation (abfd,
   *require_jalxp = (!info->relocateable
                    && ((r_type == R_MIPS16_26) != target_is_16_bit_code_p));
 
+  local_p = mips_elf_local_relocation_p (input_bfd, relocation,
+                                        local_sections, true);
+
   /* If we haven't already determined the GOT offset, or the GP value,
      and we're going to need it, get it now.  */
   switch (r_type)
@@ -6037,6 +6135,19 @@ mips_elf_calculate_relocation (abfd,
          g = mips_elf_global_got_index 
            (elf_hash_table (info)->dynobj,
             (struct elf_link_hash_entry*) h);
+         if (! elf_hash_table(info)->dynamic_sections_created
+             || (info->shared
+                 && (info->symbolic || h->root.dynindx == -1)
+                 && (h->root.elf_link_hash_flags & ELF_LINK_HASH_DEF_REGULAR)))
+           {
+             /* This is a static link or a -Bsymbolic link.  The
+                symbol is defined locally, or was forced to be local.
+                We must initialize this entry in the GOT.  */
+             asection *sgot = mips_elf_got_section(elf_hash_table
+                                                   (info)->dynobj);
+             MIPS_ELF_PUT_WORD (elf_hash_table (info)->dynobj,
+                                symbol + addend, sgot->contents + g);
+           }
        }
       else if (r_type == R_MIPS_GOT16)
        /* There's no need to create a local GOT entry here; the
@@ -6084,8 +6195,8 @@ mips_elf_calculate_relocation (abfd,
       if ((info->shared
           || (elf_hash_table (info)->dynamic_sections_created
               && h != NULL
-              && ((h->root.elf_link_hash_flags & ELF_LINK_HASH_DEF_REGULAR)
-                  == 0)))
+              && ((h->root.elf_link_hash_flags & ELF_LINK_HASH_DEF_DYNAMIC)
+                  != 0)))
          && (input_section->flags & SEC_ALLOC) != 0)
        {
          /* If we're creating a shared library, or this relocation is
@@ -6208,7 +6319,14 @@ mips_elf_calculate_relocation (abfd,
     case R_MIPS_GOT16:
       if (local_p)
        {
-         value = mips_elf_got16_entry (abfd, info, symbol + addend);
+         boolean forced;
+         
+         /* The special case is when the symbol is forced to be local.  We
+            need the full address in the GOT since no R_MIPS_LO16 relocation
+            follows.  */
+         forced = ! mips_elf_local_relocation_p (input_bfd, relocation,
+                                                 local_sections, false);
+         value = mips_elf_got16_entry (abfd, info, symbol + addend, forced);
          if (value == (bfd_vma) -1)
            return false;
          value 
@@ -6613,7 +6731,7 @@ _bfd_mips_elf_relocate_section (output_bfd, info, input_bfd, input_section,
                  || r_type == R_MIPS_GNU_REL_HI16
                  || (r_type == R_MIPS_GOT16
                      && mips_elf_local_relocation_p (input_bfd, rel,
-                                                     local_sections)))
+                                                     local_sections, false)))
                {
                  bfd_vma l;
                  const Elf_Internal_Rela *lo16_relocation;
@@ -6679,7 +6797,8 @@ _bfd_mips_elf_relocate_section (output_bfd, info, input_bfd, input_section,
             relative in which case we need to adjust by the amount
             that we're adjusting GP in this relocateable object.  */
 
-         if (!mips_elf_local_relocation_p (input_bfd, rel, local_sections))
+         if (!mips_elf_local_relocation_p (input_bfd, rel, local_sections,
+                                           false))
            /* There's nothing to do for non-local relocations.  */
            continue;
 
@@ -6739,8 +6858,8 @@ _bfd_mips_elf_relocate_section (output_bfd, info, input_bfd, input_section,
                  bfd_vma low_bits;
                  bfd_vma high_bits;
                  
-                 if (addend & 0x80000000u)
-                   sign_bits = 0xffffffffu;
+                 if (addend & ((bfd_vma) 1 << 31))
+                   sign_bits = ((bfd_vma) 1 << 32) - 1;
                  else
                    sign_bits = 0;
                  
@@ -6859,8 +6978,8 @@ _bfd_mips_elf_relocate_section (output_bfd, info, input_bfd, input_section,
          bfd_vma low_bits;
          bfd_vma high_bits;
 
-         if (value & 0x80000000u)
-           sign_bits = 0xffffffffu;
+         if (value & ((bfd_vma) 1 << 31))
+           sign_bits = ((bfd_vma) 1 << 32) - 1;
          else
            sign_bits = 0;
 
@@ -6980,7 +7099,7 @@ _bfd_mips_elf_create_dynamic_sections (abfd, info)
        return false;
     }
 
-  if (IRIX_COMPAT (abfd) == ict_irix5
+  if ((IRIX_COMPAT (abfd) == ict_irix5 || IRIX_COMPAT (abfd) == ict_none)
       && !info->shared
       && bfd_get_section_by_name (abfd, ".rld_map") == NULL)
     {
@@ -7016,8 +7135,11 @@ _bfd_mips_elf_create_dynamic_sections (abfd, info)
        }
 
       /* We need to create a .compact_rel section.  */
-      if (! mips_elf_create_compact_rel_section (abfd, info))
-       return false;
+      if (SGI_COMPAT (abfd))
+        {
+          if (!mips_elf_create_compact_rel_section (abfd, info))
+           return false;
+        }
 
       /* Change aligments of some sections.  */
       s = bfd_get_section_by_name (abfd, ".hash");
@@ -7040,12 +7162,25 @@ _bfd_mips_elf_create_dynamic_sections (abfd, info)
   if (!info->shared)
     {
       h = NULL;
-      if (! (_bfd_generic_link_add_one_symbol
+      if (SGI_COMPAT (abfd))
+        {
+          if (!(_bfd_generic_link_add_one_symbol
             (info, abfd, "_DYNAMIC_LINK", BSF_GLOBAL, bfd_abs_section_ptr,
              (bfd_vma) 0, (const char *) NULL, false,
              get_elf_backend_data (abfd)->collect,
              (struct bfd_link_hash_entry **) &h)))
-       return false;
+           return false;
+        }
+      else
+        {
+          /* For normal mips it is _DYNAMIC_LINKING. */
+          if (!(_bfd_generic_link_add_one_symbol
+                (info, abfd, "_DYNAMIC_LINKING", BSF_GLOBAL, 
+                 bfd_abs_section_ptr, (bfd_vma) 0, (const char *) NULL, false,
+                 get_elf_backend_data (abfd)->collect,
+                 (struct bfd_link_hash_entry **) &h)))
+            return false;
+        }
       h->elf_link_hash_flags &=~ ELF_LINK_NON_ELF;
       h->elf_link_hash_flags |= ELF_LINK_HASH_DEF_REGULAR;
       h->type = STT_SECTION;
@@ -7063,12 +7198,25 @@ _bfd_mips_elf_create_dynamic_sections (abfd, info)
          BFD_ASSERT (s != NULL);
 
          h = NULL;
-         if (! (_bfd_generic_link_add_one_symbol
+          if (SGI_COMPAT (abfd))
+            {
+              if (!(_bfd_generic_link_add_one_symbol
                 (info, abfd, "__rld_map", BSF_GLOBAL, s,
                  (bfd_vma) 0, (const char *) NULL, false,
                  get_elf_backend_data (abfd)->collect,
                  (struct bfd_link_hash_entry **) &h)))
-           return false;
+               return false;
+            }
+          else
+            {
+              /* For normal mips the symbol is __RLD_MAP. */
+              if (!(_bfd_generic_link_add_one_symbol
+                    (info, abfd, "__RLD_MAP", BSF_GLOBAL, s,
+                     (bfd_vma) 0, (const char *) NULL, false,
+                     get_elf_backend_data (abfd)->collect,
+                     (struct bfd_link_hash_entry **) &h)))
+                return false;
+            }
          h->elf_link_hash_flags &=~ ELF_LINK_NON_ELF;
          h->elf_link_hash_flags |= ELF_LINK_HASH_DEF_REGULAR;
          h->type = STT_OBJECT;
@@ -7445,6 +7593,13 @@ _bfd_mips_elf_check_relocs (abfd, info, sec, relocs)
 
       if (r_symndx < extsymoff)
        h = NULL;
+      else if (r_symndx >= extsymoff + (symtab_hdr->sh_size / symtab_hdr->sh_entsize))
+       {
+         (*_bfd_error_handler)
+           (_("Malformed reloc detected for section %s"), name);
+         bfd_set_error (bfd_error_bad_value);
+         return false;
+       }
       else
        {
          h = sym_hashes[r_symndx - extsymoff];
@@ -7602,7 +7757,7 @@ _bfd_mips_elf_check_relocs (abfd, info, sec, relocs)
                return false;
            }
 
-         if (SGI_COMPAT (dynobj))
+         if (SGI_COMPAT (abfd))
            mips_elf_hash_table (info)->compact_rel_size +=
              sizeof (Elf32_External_crinfo);
          break;
@@ -7611,7 +7766,7 @@ _bfd_mips_elf_check_relocs (abfd, info, sec, relocs)
        case R_MIPS_GPREL16:
        case R_MIPS_LITERAL:
        case R_MIPS_GPREL32:
-         if (SGI_COMPAT (dynobj))
+         if (SGI_COMPAT (abfd))
            mips_elf_hash_table (info)->compact_rel_size +=
              sizeof (Elf32_External_crinfo);
          break;
@@ -7750,6 +7905,26 @@ _bfd_mips_elf_gc_sweep_hook (abfd, info, sec, relocs)
   return true;
 }
 
+/* Copy data from a MIPS ELF indirect symbol to its direct symbol,
+   hiding the old indirect symbol.  Process additional relocation
+   information.  */
+
+void
+_bfd_mips_elf_copy_indirect_symbol (dir, ind)
+     struct elf_link_hash_entry *dir, *ind;
+{
+  struct mips_elf_link_hash_entry *dirmips, *indmips;
+
+  _bfd_elf_link_hash_copy_indirect (dir, ind);
+
+  dirmips = (struct mips_elf_link_hash_entry *) dir;
+  indmips = (struct mips_elf_link_hash_entry *) ind;
+  dirmips->possibly_dynamic_relocs += indmips->possibly_dynamic_relocs;
+  if (dirmips->min_dyn_reloc_index == 0
+      || (indmips->min_dyn_reloc_index != 0
+          && indmips->min_dyn_reloc_index < dirmips->min_dyn_reloc_index))
+    dirmips->min_dyn_reloc_index = indmips->min_dyn_reloc_index;
+}
 
 /* Adjust a symbol defined by a dynamic object and referenced by a
    regular object.  The current definition is in some section of the
@@ -7790,8 +7965,7 @@ _bfd_mips_elf_adjust_dynamic_symbol (info, h)
                                           hmips->possibly_dynamic_relocs);
 
   /* For a function, create a stub, if needed. */
-  if (h->type == STT_FUNC
-      || (h->elf_link_hash_flags & ELF_LINK_HASH_NEEDS_PLT) != 0)
+  if ((h->elf_link_hash_flags & ELF_LINK_HASH_NEEDS_PLT) != 0)
     {
       if (! elf_hash_table (info)->dynamic_sections_created)
        return true;
@@ -7821,6 +7995,14 @@ _bfd_mips_elf_adjust_dynamic_symbol (info, h)
          return true;
        }
     }
+  else if ((h->type == STT_FUNC)
+           && (h->elf_link_hash_flags & ELF_LINK_HASH_NEEDS_PLT) == 0)
+    {
+      /* This will set the entry for this symbol in the GOT to 0, and
+         the dynamic linker will take care of this. */
+      h->root.u.def.value = 0;
+      return true;
+    }
 
   /* If this is a weak symbol, and there is a real definition, the
      processor independent code will have arranged for us to see the
@@ -8121,22 +8303,30 @@ _bfd_mips_elf_size_dynamic_sections (output_bfd, info)
         dynamic linker and used by the debugger.  */
       if (! info->shared)
        {
-         if (SGI_COMPAT (output_bfd))
-           {
-             /* SGI object has the equivalence of DT_DEBUG in the
-                DT_MIPS_RLD_MAP entry.  */
-             if (! MIPS_ELF_ADD_DYNAMIC_ENTRY (info, DT_MIPS_RLD_MAP, 0))
-               return false;
-           }
-         else
-           if (! MIPS_ELF_ADD_DYNAMIC_ENTRY (info, DT_DEBUG, 0))
-             return false;
-       }
-
-      if (reltext)
+          /* SGI object has the equivalence of DT_DEBUG in the
+             DT_MIPS_RLD_MAP entry.  */
+          if (!MIPS_ELF_ADD_DYNAMIC_ENTRY (info, DT_MIPS_RLD_MAP, 0))
+            return false;
+          if (!SGI_COMPAT (output_bfd))
+            {
+              if (!MIPS_ELF_ADD_DYNAMIC_ENTRY (info, DT_DEBUG, 0))
+                return false;
+            }
+        }
+      else
+        {
+          /* Shared libraries on traditional mips have DT_DEBUG. */
+          if (!SGI_COMPAT (output_bfd))
+            {
+              if (!MIPS_ELF_ADD_DYNAMIC_ENTRY (info, DT_DEBUG, 0))
+                return false;
+            }
+        }
+      if (reltext && SGI_COMPAT(output_bfd))
        {
          if (! MIPS_ELF_ADD_DYNAMIC_ENTRY (info, DT_TEXTREL, 0))
            return false;
+         info->flags |= DF_TEXTREL;
        }
 
       if (! MIPS_ELF_ADD_DYNAMIC_ENTRY (info, DT_PLTGOT, 0))
@@ -8155,11 +8345,17 @@ _bfd_mips_elf_size_dynamic_sections (output_bfd, info)
            return false;
        }
 
-      if (! MIPS_ELF_ADD_DYNAMIC_ENTRY (info, DT_MIPS_CONFLICTNO, 0))
-       return false;
+      if (SGI_COMPAT (output_bfd))
+        {
+          if (!MIPS_ELF_ADD_DYNAMIC_ENTRY (info, DT_MIPS_CONFLICTNO, 0))
+           return false;
+        }
 
-      if (! MIPS_ELF_ADD_DYNAMIC_ENTRY (info, DT_MIPS_LIBLISTNO, 0))
-       return false;
+      if (SGI_COMPAT (output_bfd))
+        {
+          if (!MIPS_ELF_ADD_DYNAMIC_ENTRY (info, DT_MIPS_LIBLISTNO, 0))
+           return false;
+        }
 
       if (bfd_get_section_by_name (dynobj, ".conflict") != NULL)
        {
@@ -8320,7 +8516,7 @@ _bfd_mips_elf_finish_dynamic_symbol (output_bfd, info, h, sym)
       p = stub;
       bfd_put_32 (output_bfd, STUB_LW(output_bfd), p);
       p += 4;
-      bfd_put_32 (output_bfd, STUB_MOVE, p);
+      bfd_put_32 (output_bfd, STUB_MOVE(output_bfd), p);
       p += 4;
 
       /* FIXME: Can h->dynindex be more than 64K?  */
@@ -8329,7 +8525,7 @@ _bfd_mips_elf_finish_dynamic_symbol (output_bfd, info, h, sym)
 
       bfd_put_32 (output_bfd, STUB_JALR, p);
       p += 4;
-      bfd_put_32 (output_bfd, STUB_LI16 + h->dynindx, p);
+      bfd_put_32 (output_bfd, STUB_LI16(output_bfd) + h->dynindx, p);
 
       BFD_ASSERT (h->plt.offset <= s->_raw_size);
       memcpy (s->contents + h->plt.offset, stub, MIPS_FUNCTION_STUB_SIZE);
@@ -8345,7 +8541,8 @@ _bfd_mips_elf_finish_dynamic_symbol (output_bfd, info, h, sym)
       sym->st_value = gval;
     }
 
-  BFD_ASSERT (h->dynindx != -1);
+  BFD_ASSERT (h->dynindx != -1
+             || (h->elf_link_hash_flags & ELF_LINK_FORCED_LOCAL) != 0);
 
   sgot = mips_elf_got_section (dynobj);
   BFD_ASSERT (sgot != NULL);
@@ -8364,13 +8561,18 @@ _bfd_mips_elf_finish_dynamic_symbol (output_bfd, info, h, sym)
       if (sym->st_value)
        value = sym->st_value;
       else
-       /* For an entity defined in a shared object, this will be
-          NULL.  (For functions in shared objects for
-          which we have created stubs, ST_VALUE will be non-NULL.
-          That's because such the functions are now no longer defined
-          in a shared object.)  */
-       value = h->root.u.def.value;
-
+        {
+          /* For an entity defined in a shared object, this will be
+             NULL.  (For functions in shared objects for
+             which we have created stubs, ST_VALUE will be non-NULL.
+             That's because such the functions are now no longer defined
+             in a shared object.)  */
+
+          if (info->shared && h->root.type == bfd_link_hash_undefined)
+            value = 0;
+          else
+            value = h->root.u.def.value;
+        }
       offset = mips_elf_global_got_index (dynobj, h);
       MIPS_ELF_PUT_WORD (output_bfd, value, sgot->contents + offset);
     }
@@ -8396,21 +8598,22 @@ _bfd_mips_elf_finish_dynamic_symbol (output_bfd, info, h, sym)
   if (strcmp (name, "_DYNAMIC") == 0
       || strcmp (name, "_GLOBAL_OFFSET_TABLE_") == 0)
     sym->st_shndx = SHN_ABS;
-  else if (strcmp (name, "_DYNAMIC_LINK") == 0)
+  else if (strcmp (name, "_DYNAMIC_LINK") == 0
+           || strcmp (name, "_DYNAMIC_LINKING") == 0)
     {
       sym->st_shndx = SHN_ABS;
       sym->st_info = ELF_ST_INFO (STB_GLOBAL, STT_SECTION);
       sym->st_value = 1;
     }
+  else if (strcmp (name, "_gp_disp") == 0)
+    {
+      sym->st_shndx = SHN_ABS;
+      sym->st_info = ELF_ST_INFO (STB_GLOBAL, STT_SECTION);
+      sym->st_value = elf_gp (output_bfd);
+    }
   else if (SGI_COMPAT (output_bfd))
     {
-      if (strcmp (name, "_gp_disp") == 0)
-       {
-         sym->st_shndx = SHN_ABS;
-         sym->st_info = ELF_ST_INFO (STB_GLOBAL, STT_SECTION);
-         sym->st_value = elf_gp (output_bfd);
-       }
-      else if (strcmp (name, mips_elf_dynsym_rtproc_names[0]) == 0
+      if (strcmp (name, mips_elf_dynsym_rtproc_names[0]) == 0
               || strcmp (name, mips_elf_dynsym_rtproc_names[1]) == 0)
        {
          sym->st_info = ELF_ST_INFO (STB_GLOBAL, STT_SECTION);
@@ -8438,11 +8641,11 @@ _bfd_mips_elf_finish_dynamic_symbol (output_bfd, info, h, sym)
   if (IRIX_COMPAT (output_bfd) == ict_irix6)
     mips_elf_irix6_finish_dynamic_symbol (output_bfd, name, sym);
 
-  if (SGI_COMPAT (output_bfd)
-      && ! info->shared)
+  if (! info->shared)
     {
       if (! mips_elf_hash_table (info)->use_rld_obj_head
-         && strcmp (name, "__rld_map") == 0)
+         && (strcmp (name, "__rld_map") == 0
+             || strcmp (name, "__RLD_MAP") == 0))
        {
          asection *s = bfd_get_section_by_name (dynobj, ".rld_map");
          BFD_ASSERT (s != NULL);
@@ -8455,7 +8658,8 @@ _bfd_mips_elf_finish_dynamic_symbol (output_bfd, info, h, sym)
               && strcmp (name, "__rld_obj_head") == 0)
        {
          /* IRIX6 does not use a .rld_map section.  */
-         if (IRIX_COMPAT (output_bfd) == ict_irix5)
+         if (IRIX_COMPAT (output_bfd) == ict_irix5
+              || IRIX_COMPAT (output_bfd) == ict_none)
            BFD_ASSERT (bfd_get_section_by_name (dynobj, ".rld_map") 
                        != NULL);
          mips_elf_hash_table (info)->rld_value = sym->st_value;
@@ -8737,6 +8941,23 @@ _bfd_mips_elf_finish_dynamic_sections (output_bfd, info)
          }
       }
 
+    /* We need to sort the entries of the dynamic relocation section.  */
+
+    if (!ABI_64_P (output_bfd))
+      {
+            asection *reldyn;
+
+            reldyn = bfd_get_section_by_name (dynobj,
+                                     MIPS_ELF_REL_DYN_SECTION_NAME (dynobj));
+            if (reldyn != NULL && reldyn->reloc_count > 2)
+              {
+                reldyn_sorting_bfd = output_bfd;
+                qsort ((Elf32_External_Rel *) reldyn->contents + 1,
+                       (size_t) reldyn->reloc_count - 1,
+                       sizeof (Elf32_External_Rel), sort_dynamic_relocs);
+              }
+      }
+
     /* Clean up a first relocation in .rel.dyn.  */
     s = bfd_get_section_by_name (dynobj, 
                                 MIPS_ELF_REL_DYN_SECTION_NAME (dynobj));
@@ -9030,6 +9251,11 @@ static const struct ecoff_debug_swap mips_elf32_ecoff_debug_swap =
 #define elf_backend_got_header_size    (4*MIPS_RESERVED_GOTNO)
 #define elf_backend_plt_header_size    0
 
+#define elf_backend_copy_indirect_symbol \
+                                       _bfd_mips_elf_copy_indirect_symbol
+
+#define elf_backend_hide_symbol                _bfd_mips_elf_hide_symbol
+
 #define bfd_elf32_bfd_is_local_label_name \
                                        mips_elf_is_local_label_name
 #define bfd_elf32_find_nearest_line    _bfd_mips_elf_find_nearest_line
@@ -9045,3 +9271,20 @@ static const struct ecoff_debug_swap mips_elf32_ecoff_debug_swap =
 #define bfd_elf32_bfd_print_private_bfd_data \
                                        _bfd_mips_elf_print_private_bfd_data
 #include "elf32-target.h"
+
+/* Support for traditional mips targets */
+
+#define INCLUDED_TARGET_FILE            /* More a type of flag */
+
+#undef TARGET_LITTLE_SYM
+#undef TARGET_LITTLE_NAME
+#undef TARGET_BIG_SYM
+#undef TARGET_BIG_NAME
+
+#define TARGET_LITTLE_SYM               bfd_elf32_tradlittlemips_vec
+#define TARGET_LITTLE_NAME              "elf32-tradlittlemips"
+#define TARGET_BIG_SYM                  bfd_elf32_tradbigmips_vec
+#define TARGET_BIG_NAME                 "elf32-tradbigmips"
+
+/* Include the target file again for this target */
+#include "elf32-target.h"
This page took 0.056014 seconds and 4 git commands to generate.