ChangeLog:
[deliverable/binutils-gdb.git] / bfd / elfxx-mips.c
index eb6d55e042544d02b09bae6404a9ff621de734ea..814ba90cdb3c56da7235d4129734a7c8c267f970 100644 (file)
@@ -662,6 +662,12 @@ static struct mips_got_info *mips_elf_got_for_ibfd
 /* This will be used when we sort the dynamic relocation records.  */
 static bfd *reldyn_sorting_bfd;
 
+/* True if ABFD is for CPUs with load interlocking that include
+   non-MIPS1 CPUs and R3900.  */
+#define LOAD_INTERLOCKS_P(abfd) \
+  (   ((elf_elfheader (abfd)->e_flags & EF_MIPS_ARCH) != E_MIPS_ARCH_1) \
+   || ((elf_elfheader (abfd)->e_flags & EF_MIPS_MACH) == E_MIPS_MACH_3900))
+
 /* True if ABFD is a PIC object.  */
 #define PIC_OBJECT_P(abfd) \
   ((elf_elfheader (abfd)->e_flags & EF_MIPS_PIC) != 0)
@@ -878,7 +884,8 @@ static bfd *reldyn_sorting_bfd;
 #define CALL_FP_STUB_P(name) CONST_STRNEQ (name, CALL_FP_STUB)
 \f
 /* The format of the first PLT entry in an O32 executable.  */
-static const bfd_vma mips_o32_exec_plt0_entry[] = {
+static const bfd_vma mips_o32_exec_plt0_entry[] =
+{
   0x3c1c0000,  /* lui $28, %hi(&GOTPLT[0])                             */
   0x8f990000,  /* lw $25, %lo(&GOTPLT[0])($28)                         */
   0x279c0000,  /* addiu $28, $28, %lo(&GOTPLT[0])                      */
@@ -891,7 +898,8 @@ static const bfd_vma mips_o32_exec_plt0_entry[] = {
 
 /* The format of the first PLT entry in an N32 executable.  Different
    because gp ($28) is not available; we use t2 ($14) instead.  */
-static const bfd_vma mips_n32_exec_plt0_entry[] = {
+static const bfd_vma mips_n32_exec_plt0_entry[] =
+{
   0x3c0e0000,  /* lui $14, %hi(&GOTPLT[0])                             */
   0x8dd90000,  /* lw $25, %lo(&GOTPLT[0])($14)                         */
   0x25ce0000,  /* addiu $14, $14, %lo(&GOTPLT[0])                      */
@@ -904,7 +912,8 @@ static const bfd_vma mips_n32_exec_plt0_entry[] = {
 
 /* The format of the first PLT entry in an N64 executable.  Different
    from N32 because of the increased size of GOT entries.  */
-static const bfd_vma mips_n64_exec_plt0_entry[] = {
+static const bfd_vma mips_n64_exec_plt0_entry[] =
+{
   0x3c0e0000,  /* lui $14, %hi(&GOTPLT[0])                             */
   0xddd90000,  /* ld $25, %lo(&GOTPLT[0])($14)                         */
   0x25ce0000,  /* addiu $14, $14, %lo(&GOTPLT[0])                      */
@@ -916,7 +925,8 @@ static const bfd_vma mips_n64_exec_plt0_entry[] = {
 };
 
 /* The format of subsequent PLT entries.  */
-static const bfd_vma mips_exec_plt_entry[] = {
+static const bfd_vma mips_exec_plt_entry[] =
+{
   0x3c0f0000,  /* lui $15, %hi(.got.plt entry)                 */
   0x01f90000,  /* l[wd] $25, %lo(.got.plt entry)($15)          */
   0x25f80000,  /* addiu $24, $15, %lo(.got.plt entry)          */
@@ -924,7 +934,8 @@ static const bfd_vma mips_exec_plt_entry[] = {
 };
 
 /* The format of the first PLT entry in a VxWorks executable.  */
-static const bfd_vma mips_vxworks_exec_plt0_entry[] = {
+static const bfd_vma mips_vxworks_exec_plt0_entry[] =
+{
   0x3c190000,  /* lui t9, %hi(_GLOBAL_OFFSET_TABLE_)           */
   0x27390000,  /* addiu t9, t9, %lo(_GLOBAL_OFFSET_TABLE_)     */
   0x8f390008,  /* lw t9, 8(t9)                                 */
@@ -934,7 +945,8 @@ static const bfd_vma mips_vxworks_exec_plt0_entry[] = {
 };
 
 /* The format of subsequent PLT entries.  */
-static const bfd_vma mips_vxworks_exec_plt_entry[] = {
+static const bfd_vma mips_vxworks_exec_plt_entry[] =
+{
   0x10000000,  /* b .PLT_resolver                      */
   0x24180000,  /* li t8, <pltindex>                    */
   0x3c190000,  /* lui t9, %hi(<.got.plt slot>)         */
@@ -946,7 +958,8 @@ static const bfd_vma mips_vxworks_exec_plt_entry[] = {
 };
 
 /* The format of the first PLT entry in a VxWorks shared object.  */
-static const bfd_vma mips_vxworks_shared_plt0_entry[] = {
+static const bfd_vma mips_vxworks_shared_plt0_entry[] =
+{
   0x8f990008,  /* lw t9, 8(gp)         */
   0x00000000,  /* nop                  */
   0x03200008,  /* jr t9                */
@@ -956,7 +969,8 @@ static const bfd_vma mips_vxworks_shared_plt0_entry[] = {
 };
 
 /* The format of subsequent PLT entries.  */
-static const bfd_vma mips_vxworks_shared_plt_entry[] = {
+static const bfd_vma mips_vxworks_shared_plt_entry[] =
+{
   0x10000000,  /* b .PLT_resolver      */
   0x24180000   /* li t8, <pltindex>    */
 };
@@ -1409,7 +1423,8 @@ section_allows_mips16_refs_p (asection *section)
    function, or 0 if we can't decide which function that is.  */
 
 static unsigned long
-mips16_stub_symndx (asection *sec, const Elf_Internal_Rela *relocs,
+mips16_stub_symndx (asection *sec ATTRIBUTE_UNUSED,
+                   const Elf_Internal_Rela *relocs,
                    const Elf_Internal_Rela *relend)
 {
   const Elf_Internal_Rela *rel;
@@ -5878,6 +5893,9 @@ _bfd_elf_mips_mach (flagword flags)
     case E_MIPS_MACH_OCTEON:
       return bfd_mach_mips_octeon;
 
+    case E_MIPS_MACH_XLR:
+      return bfd_mach_mips_xlr;
+
     default:
       switch (flags & EF_MIPS_ARCH)
        {
@@ -6245,6 +6263,13 @@ _bfd_mips_elf_section_processing (bfd *abfd, Elf_Internal_Shdr *hdr)
     {
       const char *name = bfd_get_section_name (abfd, hdr->bfd_section);
 
+      /* .sbss is not handled specially here because the GNU/Linux
+        prelinker can convert .sbss from NOBITS to PROGBITS and
+        changing it back to NOBITS breaks the binary.  The entry in
+        _bfd_mips_elf_special_sections will ensure the correct flags
+        are set on .sbss if BFD creates it without reading it from an
+        input file, and without special handling here the flags set
+        on it in an input file will be followed.  */
       if (strcmp (name, ".sdata") == 0
          || strcmp (name, ".lit8") == 0
          || strcmp (name, ".lit4") == 0)
@@ -6252,11 +6277,6 @@ _bfd_mips_elf_section_processing (bfd *abfd, Elf_Internal_Shdr *hdr)
          hdr->sh_flags |= SHF_ALLOC | SHF_WRITE | SHF_MIPS_GPREL;
          hdr->sh_type = SHT_PROGBITS;
        }
-      else if (strcmp (name, ".sbss") == 0)
-       {
-         hdr->sh_flags |= SHF_ALLOC | SHF_WRITE | SHF_MIPS_GPREL;
-         hdr->sh_type = SHT_NOBITS;
-       }
       else if (strcmp (name, ".srdata") == 0)
        {
          hdr->sh_flags |= SHF_ALLOC | SHF_MIPS_GPREL;
@@ -6779,7 +6799,7 @@ _bfd_mips_elf_add_symbol_hook (bfd *abfd, struct bfd_link_info *info,
    symbol.  We mark symbols as small common if appropriate.  This is
    also where we undo the increment of the value for a mips16 symbol.  */
 
-bfd_boolean
+int
 _bfd_mips_elf_link_output_symbol_hook
   (struct bfd_link_info *info ATTRIBUTE_UNUSED,
    const char *name ATTRIBUTE_UNUSED, Elf_Internal_Sym *sym,
@@ -6795,7 +6815,7 @@ _bfd_mips_elf_link_output_symbol_hook
   if (ELF_ST_IS_MIPS16 (sym->st_other))
     sym->st_value &= ~1;
 
-  return TRUE;
+  return 1;
 }
 \f
 /* Functions for the dynamic linker.  */
@@ -7574,7 +7594,7 @@ _bfd_mips_elf_check_relocs (bfd *abfd, struct bfd_link_info *info,
        case R_MIPS_CALL_LO16:
          if (h != NULL)
            {
-             /* VxWorks call relocations point the function's .got.plt
+             /* VxWorks call relocations point at the function's .got.plt
                 entry, which will be allocated by adjust_dynamic_symbol.
                 Otherwise, this symbol requires a global GOT entry.  */
              if ((!htab->is_vxworks || h->forced_local)
@@ -8625,8 +8645,10 @@ _bfd_mips_elf_size_dynamic_sections (bfd *output_bfd,
       else if (s == htab->splt)
        {
          /* If the last PLT entry has a branch delay slot, allocate
-            room for an extra nop to fill the delay slot.  */
-         if (!htab->is_vxworks && s->size > 0)
+            room for an extra nop to fill the delay slot.  This is
+            for CPUs without load interlocking.  */
+         if (! LOAD_INTERLOCKS_P (output_bfd)
+             && ! htab->is_vxworks && s->size > 0)
            s->size += 4;
        }
       else if (! CONST_STRNEQ (name, ".init")
@@ -9349,8 +9371,17 @@ _bfd_mips_elf_finish_dynamic_symbol (bfd *output_bfd,
       plt_entry = mips_exec_plt_entry;
       bfd_put_32 (output_bfd, plt_entry[0] | got_address_high, loc);
       bfd_put_32 (output_bfd, plt_entry[1] | got_address_low | load, loc + 4);
-      bfd_put_32 (output_bfd, plt_entry[2] | got_address_low, loc + 8);
-      bfd_put_32 (output_bfd, plt_entry[3], loc + 12);
+
+      if (! LOAD_INTERLOCKS_P (output_bfd))
+       {
+         bfd_put_32 (output_bfd, plt_entry[2] | got_address_low, loc + 8);
+         bfd_put_32 (output_bfd, plt_entry[3], loc + 12);
+       }
+      else
+       {
+         bfd_put_32 (output_bfd, plt_entry[3], loc + 8);
+         bfd_put_32 (output_bfd, plt_entry[2] | got_address_low, loc + 12);
+       }
 
       /* Emit an R_MIPS_JUMP_SLOT relocation against the .got.plt entry.  */
       mips_elf_output_dynamic_relocation (output_bfd, htab->srelplt,
@@ -10399,6 +10430,8 @@ mips_set_isa_flags (bfd *abfd)
     case bfd_mach_mips8000:
     case bfd_mach_mips10000:
     case bfd_mach_mips12000:
+    case bfd_mach_mips14000:
+    case bfd_mach_mips16000:
       val = E_MIPS_ARCH_4;
       break;
 
@@ -10422,6 +10455,10 @@ mips_set_isa_flags (bfd *abfd)
       val = E_MIPS_ARCH_64R2 | E_MIPS_MACH_OCTEON;
       break;
 
+    case bfd_mach_mips_xlr:
+      val = E_MIPS_ARCH_64 | E_MIPS_MACH_XLR;
+      break;
+
     case bfd_mach_mipsisa32:
       val = E_MIPS_ARCH_32;
       break;
@@ -10923,6 +10960,26 @@ _bfd_mips_elf_copy_indirect_symbol (struct bfd_link_info *info,
     dirmips->readonly_reloc = TRUE;
   if (indmips->no_fn_stub)
     dirmips->no_fn_stub = TRUE;
+  if (indmips->fn_stub)
+    {
+      dirmips->fn_stub = indmips->fn_stub;
+      indmips->fn_stub = NULL;
+    }
+  if (indmips->need_fn_stub)
+    {
+      dirmips->need_fn_stub = TRUE;
+      indmips->need_fn_stub = FALSE;
+    }
+  if (indmips->call_stub)
+    {
+      dirmips->call_stub = indmips->call_stub;
+      indmips->call_stub = NULL;
+    }
+  if (indmips->call_fp_stub)
+    {
+      dirmips->call_fp_stub = indmips->call_fp_stub;
+      indmips->call_fp_stub = NULL;
+    }
   if (indmips->global_got_area < dirmips->global_got_area)
     dirmips->global_got_area = indmips->global_got_area;
   if (indmips->global_got_area < GGA_NONE)
@@ -12097,12 +12154,15 @@ static const struct mips_mach_extension mips_mach_extensions[] = {
   /* MIPS64 extensions.  */
   { bfd_mach_mipsisa64r2, bfd_mach_mipsisa64 },
   { bfd_mach_mips_sb1, bfd_mach_mipsisa64 },
+  { bfd_mach_mips_xlr, bfd_mach_mipsisa64 },
 
   /* MIPS V extensions.  */
   { bfd_mach_mipsisa64, bfd_mach_mips5 },
 
   /* R10000 extensions.  */
   { bfd_mach_mips12000, bfd_mach_mips10000 },
+  { bfd_mach_mips14000, bfd_mach_mips10000 },
+  { bfd_mach_mips16000, bfd_mach_mips10000 },
 
   /* R5000 extensions.  Note: the vr5500 ISA is an extension of the core
      vr5400 ISA, but doesn't include the multimedia stuff.  It seems
This page took 0.02977 seconds and 4 git commands to generate.