Automatic date update in version.in
[deliverable/binutils-gdb.git] / bfd / elfxx-mips.c
index 5998bc43a8a0e0a8a35d833d34834d1dddbe5466..e3054043df3b3a2ad73a72af1efbc4783ca7a0f3 100644 (file)
@@ -292,6 +292,7 @@ struct mips_elf_la25_stub {
 
 #define LA25_LUI(VAL) (0x3c190000 | (VAL))     /* lui t9,VAL */
 #define LA25_J(VAL) (0x08000000 | (((VAL) >> 2) & 0x3ffffff)) /* j VAL */
+#define LA25_BC(VAL) (0xc8000000 | (((VAL) >> 2) & 0x3ffffff)) /* bc VAL */
 #define LA25_ADDIU(VAL) (0x27390000 | (VAL))   /* addiu t9,t9,VAL */
 #define LA25_LUI_MICROMIPS(VAL)                                                \
   (0x41b90000 | (VAL))                         /* lui t9,VAL */
@@ -321,6 +322,11 @@ struct mips_elf_hash_sort_data
   /* The greatest dynamic symbol table index corresponding to an external
      symbol without a GOT entry.  */
   bfd_size_type max_non_got_dynindx;
+  /* If non-NULL, output BFD for .MIPS.xhash finalization.  */
+  bfd *output_bfd;
+  /* If non-NULL, pointer to contents of .MIPS.xhash for filling in
+     real final dynindx.  */
+  bfd_byte *mipsxhash;
 };
 
 /* We make up to two PLT entries if needed, one for standard MIPS code
@@ -378,6 +384,9 @@ struct mips_elf_link_hash_entry
      being called returns a floating point value.  */
   asection *call_fp_stub;
 
+  /* If non-zero, location in .MIPS.xhash to write real final dynindx.  */
+  bfd_vma mipsxhash_loc;
+
   /* The highest GGA_* value that satisfies all references to this symbol.  */
   unsigned int global_got_area : 2;
 
@@ -449,6 +458,9 @@ struct mips_elf_link_hash_table
   /* True if we suppress checks for invalid branches between ISA modes.  */
   bfd_boolean ignore_branch_isa;
 
+  /* True if we are targetting R6 compact branches.  */
+  bfd_boolean compact_branches;
+
   /* True if we're generating code for VxWorks.  */
   bfd_boolean is_vxworks;
 
@@ -920,6 +932,7 @@ static bfd *reldyn_sorting_bfd;
 #define STUB_MOVE 0x03e07825                   /* or t7,ra,zero */
 #define STUB_LUI(VAL) (0x3c180000 + (VAL))     /* lui t8,VAL */
 #define STUB_JALR 0x0320f809                   /* jalr ra,t9 */
+#define STUB_JALRC 0xf8190000                  /* jalrc ra,t9 */
 #define STUB_ORI(VAL) (0x37180000 + (VAL))     /* ori t8,t8,VAL */
 #define STUB_LI16U(VAL) (0x34180000 + (VAL))   /* ori t8,zero,VAL unsigned */
 #define STUB_LI16S(abfd, VAL)                                          \
@@ -1036,6 +1049,20 @@ static const bfd_vma mips_o32_exec_plt0_entry[] =
   0x2718fffe   /* subu $24, $24, 2                                     */
 };
 
+/* The format of the first PLT entry in an O32 executable using compact
+   jumps.  */
+static const bfd_vma mipsr6_o32_exec_plt0_entry_compact[] =
+{
+  0x3c1c0000,  /* lui $28, %hi(&GOTPLT[0])                             */
+  0x8f990000,  /* lw $25, %lo(&GOTPLT[0])($28)                         */
+  0x279c0000,  /* addiu $28, $28, %lo(&GOTPLT[0])                      */
+  0x031cc023,  /* subu $24, $24, $28                                   */
+  0x03e07821,  /* move $15, $31        # 32-bit move (addu)            */
+  0x0018c082,  /* srl $24, $24, 2                                      */
+  0x2718fffe,  /* subu $24, $24, 2                                     */
+  0xf8190000   /* jalrc $25                                            */
+};
+
 /* 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[] =
@@ -1050,6 +1077,21 @@ static const bfd_vma mips_n32_exec_plt0_entry[] =
   0x2718fffe   /* subu $24, $24, 2                                     */
 };
 
+/* The format of the first PLT entry in an N32 executable using compact
+   jumps.  Different because gp ($28) is not available; we use t2 ($14)
+   instead.  */
+static const bfd_vma mipsr6_n32_exec_plt0_entry_compact[] =
+{
+  0x3c0e0000,  /* lui $14, %hi(&GOTPLT[0])                             */
+  0x8dd90000,  /* lw $25, %lo(&GOTPLT[0])($14)                         */
+  0x25ce0000,  /* addiu $14, $14, %lo(&GOTPLT[0])                      */
+  0x030ec023,  /* subu $24, $24, $14                                   */
+  0x03e07821,  /* move $15, $31        # 32-bit move (addu)            */
+  0x0018c082,  /* srl $24, $24, 2                                      */
+  0x2718fffe,  /* subu $24, $24, 2                                     */
+  0xf8190000   /* jalrc $25                                            */
+};
+
 /* 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[] =
@@ -1064,6 +1106,22 @@ static const bfd_vma mips_n64_exec_plt0_entry[] =
   0x2718fffe   /* subu $24, $24, 2                                     */
 };
 
+/* The format of the first PLT entry in an N64 executable using compact
+   jumps.  Different from N32 because of the increased size of GOT
+   entries.  */
+static const bfd_vma mipsr6_n64_exec_plt0_entry_compact[] =
+{
+  0x3c0e0000,  /* lui $14, %hi(&GOTPLT[0])                             */
+  0xddd90000,  /* ld $25, %lo(&GOTPLT[0])($14)                         */
+  0x25ce0000,  /* addiu $14, $14, %lo(&GOTPLT[0])                      */
+  0x030ec023,  /* subu $24, $24, $14                                   */
+  0x03e0782d,  /* move $15, $31        # 64-bit move (daddu)           */
+  0x0018c0c2,  /* srl $24, $24, 3                                      */
+  0x2718fffe,  /* subu $24, $24, 2                                     */
+  0xf8190000   /* jalrc $25                                            */
+};
+
+
 /* The format of the microMIPS first PLT entry in an O32 executable.
    We rely on v0 ($2) rather than t8 ($24) to contain the address
    of the GOTPLT entry handled, so this stub may only be used when
@@ -1106,9 +1164,6 @@ static const bfd_vma mips_exec_plt_entry[] =
   0x03200008   /* jr $25                                       */
 };
 
-/* In the following PLT entry the JR and ADDIU instructions will
-   be swapped in _bfd_mips_elf_finish_dynamic_symbol because
-   LOAD_INTERLOCKS_P will be true for MIPS R6.  */
 static const bfd_vma mipsr6_exec_plt_entry[] =
 {
   0x3c0f0000,  /* lui $15, %hi(.got.plt entry)                 */
@@ -1117,6 +1172,14 @@ static const bfd_vma mipsr6_exec_plt_entry[] =
   0x03200009   /* jr $25                                       */
 };
 
+static const bfd_vma mipsr6_exec_plt_entry_compact[] =
+{
+  0x3c0f0000,  /* lui $15, %hi(.got.plt entry)                 */
+  0x01f90000,  /* l[wd] $25, %lo(.got.plt entry)($15)          */
+  0x25f80000,  /* addiu $24, $15, %lo(.got.plt entry)          */
+  0xd8190000   /* jic $25, 0                                   */
+};
+
 /* The format of subsequent MIPS16 o32 PLT entries.  We use v0 ($2)
    and v1 ($3) as temporaries because t8 ($24) and t9 ($25) are not
    directly addressable.  */
@@ -1280,6 +1343,7 @@ mips_elf_link_hash_newfunc (struct bfd_hash_entry *entry,
       ret->fn_stub = NULL;
       ret->call_stub = NULL;
       ret->call_fp_stub = NULL;
+      ret->mipsxhash_loc = 0;
       ret->global_got_area = GGA_NONE;
       ret->got_only_for_calls = TRUE;
       ret->readonly_reloc = FALSE;
@@ -3852,6 +3916,18 @@ mips_elf_sort_hash_table (bfd *abfd, struct bfd_link_info *info)
      at the head of the table; see `_bfd_elf_link_renumber_dynsyms'.  */
   hsd.max_local_dynindx = count_section_dynsyms (abfd, info) + 1;
   hsd.max_non_got_dynindx = htab->root.local_dynsymcount + 1;
+  hsd.output_bfd = abfd;
+  if (htab->root.dynobj != NULL
+      && htab->root.dynamic_sections_created
+      && info->emit_gnu_hash)
+    {
+      asection *s = bfd_get_linker_section (htab->root.dynobj, ".MIPS.xhash");
+      BFD_ASSERT (s != NULL);
+      hsd.mipsxhash = s->contents;
+      BFD_ASSERT (hsd.mipsxhash != NULL);
+    }
+  else
+    hsd.mipsxhash = NULL;
   mips_elf_link_hash_traverse (htab, mips_elf_sort_hash_table_f, &hsd);
 
   /* There should have been enough room in the symbol table to
@@ -3903,6 +3979,12 @@ mips_elf_sort_hash_table_f (struct mips_elf_link_hash_entry *h, void *data)
       break;
     }
 
+  /* Populate the .MIPS.xhash translation table entry with
+     the symbol dynindx.  */
+  if (h->mipsxhash_loc != 0 && hsd->mipsxhash != NULL)
+    bfd_put_32 (hsd->output_bfd, h->root.dynindx,
+               hsd->mipsxhash + h->mipsxhash_loc);
+
   return TRUE;
 }
 
@@ -6271,8 +6353,6 @@ mips_elf_calculate_relocation (bfd *abfd, bfd *input_bfd,
 
     case R_MIPS_PCHI16:
       value = mips_elf_high (symbol + addend - p);
-      if (was_local_p || h->root.root.type != bfd_link_hash_undefweak)
-       overflowed_p = mips_elf_overflow_p (value, 16);
       value &= howto->dst_mask;
       break;
 
@@ -7422,6 +7502,9 @@ _bfd_mips_elf_section_from_shdr (bfd *abfd,
          && ! CONST_STRNEQ (name, ".MIPS.post_rel"))
        return FALSE;
       break;
+    case SHT_MIPS_XHASH:
+      if (strcmp (name, ".MIPS.xhash") != 0)
+       return FALSE;
     default:
       break;
     }
@@ -7655,6 +7738,12 @@ _bfd_mips_elf_fake_sections (bfd *abfd, Elf_Internal_Shdr *hdr, asection *sec)
       hdr->sh_flags |= SHF_ALLOC;
       hdr->sh_entsize = 8;
     }
+  else if (strcmp (name, ".MIPS.xhash") == 0)
+    {
+      hdr->sh_type = SHT_MIPS_XHASH;
+      hdr->sh_flags |= SHF_ALLOC;
+      hdr->sh_entsize = get_elf_backend_data(abfd)->s->arch_size == 64 ? 0 : 4;
+    }
 
   /* The generic elf_fake_sections will set up REL_HDR using the default
    kind of relocations.  We used to set up a second header for the
@@ -7941,6 +8030,11 @@ _bfd_mips_elf_create_dynamic_sections (bfd *abfd, struct bfd_link_info *info)
        return FALSE;
     }
 
+  /* Create .MIPS.xhash section.  */
+  if (info->emit_gnu_hash)
+    s = bfd_make_section_anyway_with_flags (abfd, ".MIPS.xhash",
+                                           flags | SEC_READONLY);
+
   /* On IRIX5, we adjust add some additional symbols and change the
      alignments of several sections.  There is no ABI documentation
      indicating that this is necessary on IRIX6, nor any evidence that
@@ -8992,9 +9086,7 @@ _bfd_mips_elf_check_relocs (bfd *abfd, struct bfd_link_info *info,
          /* This relocation describes which C++ vtable entries are actually
             used.  Record for later use during GC.  */
        case R_MIPS_GNU_VTENTRY:
-         BFD_ASSERT (h != NULL);
-         if (h != NULL
-             && !bfd_elf_gc_record_vtentry (abfd, sec, h, rel->r_offset))
+         if (!bfd_elf_gc_record_vtentry (abfd, sec, h, rel->r_offset))
            return FALSE;
          break;
 
@@ -9049,6 +9141,18 @@ _bfd_mips_elf_check_relocs (bfd *abfd, struct bfd_link_info *info,
        {
          switch (r_type)
            {
+           case R_MIPS_TLS_TPREL_HI16:
+           case R_MIPS16_TLS_TPREL_HI16:
+           case R_MICROMIPS_TLS_TPREL_HI16:
+           case R_MIPS_TLS_TPREL_LO16:
+           case R_MIPS16_TLS_TPREL_LO16:
+           case R_MICROMIPS_TLS_TPREL_LO16:
+             /* These are okay in PIE, but not in a shared library.  */
+             if (bfd_link_executable (info))
+               break;
+
+             /* FALLTHROUGH */
+
            case R_MIPS16_HI16:
            case R_MIPS_HI16:
            case R_MIPS_HIGHER:
@@ -9062,7 +9166,7 @@ _bfd_mips_elf_check_relocs (bfd *abfd, struct bfd_link_info *info,
                break;
 
              /* Likewise an absolute symbol.  */
-             if (bfd_is_abs_symbol (&h->root))
+             if (h != NULL && bfd_is_abs_symbol (&h->root))
                break;
 
              /* R_MIPS_HI16 against _gp_disp is used for $gp setup,
@@ -9080,13 +9184,16 @@ _bfd_mips_elf_check_relocs (bfd *abfd, struct bfd_link_info *info,
            case R_MIPS16_26:
            case R_MIPS_26:
            case R_MICROMIPS_26_S1:
-             howto = MIPS_ELF_RTYPE_TO_HOWTO (abfd, r_type, FALSE);
-             info->callbacks->einfo
-               /* xgettext:c-format */
-               (_("%X%H: relocation %s against `%s' cannot be used"
-                  " when making a shared object; recompile with -fPIC\n"),
-                abfd, sec, rel->r_offset, howto->name,
-                (h) ? h->root.root.string : "a local symbol");
+             howto = MIPS_ELF_RTYPE_TO_HOWTO (abfd, r_type, NEWABI_P (abfd));
+             /* An error for unsupported relocations is raised as part
+                of the above search, so we can skip the following.  */
+             if (howto != NULL)
+               info->callbacks->einfo
+                 /* xgettext:c-format */
+                 (_("%X%H: relocation %s against `%s' cannot be used"
+                    " when making a shared object; recompile with -fPIC\n"),
+                  abfd, sec, rel->r_offset, howto->name,
+                  (h) ? h->root.root.string : "a local symbol");
              break;
            default:
              break;
@@ -10110,6 +10217,10 @@ _bfd_mips_elf_size_dynamic_sections (bfd *output_bfd,
          if (! MIPS_ELF_ADD_DYNAMIC_ENTRY (info, DT_MIPS_GOTSYM, 0))
            return FALSE;
 
+         if (info->emit_gnu_hash
+             && ! MIPS_ELF_ADD_DYNAMIC_ENTRY (info, DT_MIPS_XHASH, 0))
+           return FALSE;
+
          if (IRIX_COMPAT (dynobj) == ict_irix5
              && ! MIPS_ELF_ADD_DYNAMIC_ENTRY (info, DT_MIPS_HIPAGENO, 0))
            return FALSE;
@@ -10606,6 +10717,8 @@ mips_elf_create_la25_stub (void **slot, void *data)
   asection *s;
   bfd_byte *loc;
   bfd_vma offset, target, target_high, target_low;
+  bfd_vma branch_pc;
+  bfd_signed_vma pcrel_offset = 0;
 
   stub = (struct mips_elf_la25_stub *) *slot;
   hti = (struct mips_htab_traverse_info *) data;
@@ -10629,6 +10742,12 @@ mips_elf_create_la25_stub (void **slot, void *data)
   /* Work out where in the section this stub should go.  */
   offset = stub->offset;
 
+  /* We add 8 here to account for the LUI/ADDIU instructions
+     before the branch instruction.  This cannot be moved down to
+     where pcrel_offset is calculated as 's' is updated in
+     mips_elf_get_la25_target.  */
+  branch_pc = s->output_section->vma + s->output_offset + offset + 8;
+
   /* Work out the target address.  */
   target = mips_elf_get_la25_target (stub, &s);
   target += s->output_section->vma + s->output_offset;
@@ -10636,6 +10755,12 @@ mips_elf_create_la25_stub (void **slot, void *data)
   target_high = ((target + 0x8000) >> 16) & 0xffff;
   target_low = (target & 0xffff);
 
+  /* Calculate the PC of the compact branch instruction (for the case where
+     compact branches are used for either microMIPSR6 or MIPSR6 with
+     compact branches.  Add 4-bytes to account for BC using the PC of the
+     next instruction as the base.  */
+  pcrel_offset = target - (branch_pc + 4);
+
   if (stub->stub_section != htab->strampoline)
     {
       /* This is a simple LUI/ADDIU stub.  Zero out the beginning
@@ -10674,8 +10799,16 @@ mips_elf_create_la25_stub (void **slot, void *data)
       else
        {
          bfd_put_32 (hti->output_bfd, LA25_LUI (target_high), loc);
-         bfd_put_32 (hti->output_bfd, LA25_J (target), loc + 4);
-         bfd_put_32 (hti->output_bfd, LA25_ADDIU (target_low), loc + 8);
+         if (MIPSR6_P (hti->output_bfd) && htab->compact_branches)
+           {
+             bfd_put_32 (hti->output_bfd, LA25_ADDIU (target_low), loc + 4);
+             bfd_put_32 (hti->output_bfd, LA25_BC (pcrel_offset), loc + 8);
+           }
+         else
+           {
+             bfd_put_32 (hti->output_bfd, LA25_J (target), loc + 4);
+             bfd_put_32 (hti->output_bfd, LA25_ADDIU (target_low), loc + 8);
+           }
          bfd_put_32 (hti->output_bfd, 0, loc + 12);
        }
     }
@@ -10832,14 +10965,16 @@ _bfd_mips_elf_finish_dynamic_symbol (bfd *output_bfd,
          /* Fill in the PLT entry itself.  */
 
          if (MIPSR6_P (output_bfd))
-           plt_entry = mipsr6_exec_plt_entry;
+           plt_entry = htab->compact_branches ? mipsr6_exec_plt_entry_compact
+                                              : mipsr6_exec_plt_entry;
          else
            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);
 
-         if (! LOAD_INTERLOCKS_P (output_bfd))
+         if (! LOAD_INTERLOCKS_P (output_bfd)
+             || (MIPSR6_P (output_bfd) && htab->compact_branches))
            {
              bfd_put_32 (output_bfd, plt_entry[2] | got_address_low, loc + 8);
              bfd_put_32 (output_bfd, plt_entry[3], loc + 12);
@@ -11043,8 +11178,12 @@ _bfd_mips_elf_finish_dynamic_symbol (bfd *output_bfd,
                          stub + idx);
              idx += 4;
            }
-         bfd_put_32 (output_bfd, STUB_JALR, stub + idx);
-         idx += 4;
+
+         if (!(MIPSR6_P (output_bfd) && htab->compact_branches))
+           {
+             bfd_put_32 (output_bfd, STUB_JALR, stub + idx);
+             idx += 4;
+           }
 
          /* If a large stub is not required and sign extension is not a
             problem, then use legacy code in the stub.  */
@@ -11057,6 +11196,10 @@ _bfd_mips_elf_finish_dynamic_symbol (bfd *output_bfd,
          else
            bfd_put_32 (output_bfd, STUB_LI16S (output_bfd, h->dynindx),
                        stub + idx);
+         idx += 4;
+
+         if (MIPSR6_P (output_bfd) && htab->compact_branches)
+           bfd_put_32 (output_bfd, STUB_JALRC, stub + idx);
        }
 
       BFD_ASSERT (h->plt.plist->stub_offset <= htab->sstubs->size);
@@ -11430,11 +11573,17 @@ mips_finish_exec_plt (bfd *output_bfd, struct bfd_link_info *info)
   BFD_ASSERT (htab != NULL);
 
   if (ABI_64_P (output_bfd))
-    plt_entry = mips_n64_exec_plt0_entry;
+    plt_entry = (htab->compact_branches
+                ? mipsr6_n64_exec_plt0_entry_compact
+                : mips_n64_exec_plt0_entry);
   else if (ABI_N32_P (output_bfd))
-    plt_entry = mips_n32_exec_plt0_entry;
+    plt_entry = (htab->compact_branches
+                ? mipsr6_n32_exec_plt0_entry_compact
+                : mips_n32_exec_plt0_entry);
   else if (!htab->plt_header_is_comp)
-    plt_entry = mips_o32_exec_plt0_entry;
+    plt_entry = (htab->compact_branches
+                ? mipsr6_o32_exec_plt0_entry_compact
+                : mips_o32_exec_plt0_entry);
   else if (htab->insn32)
     plt_entry = micromips_insn32_o32_exec_plt0_entry;
   else
@@ -11849,6 +11998,12 @@ _bfd_mips_elf_finish_dynamic_sections (bfd *output_bfd,
                swap_out_p = FALSE;
              break;
 
+           case DT_MIPS_XHASH:
+             name = ".MIPS.xhash";
+             s = bfd_get_linker_section (dynobj, name);
+             dyn.d_un.d_ptr = s->output_section->vma + s->output_offset;
+             break;
+
            default:
              swap_out_p = FALSE;
              if (htab->is_vxworks
@@ -12089,6 +12244,12 @@ mips_set_isa_flags (bfd *abfd)
   switch (bfd_get_mach (abfd))
     {
     default:
+      if (ABI_N32_P (abfd) || ABI_64_P (abfd))
+        val = E_MIPS_ARCH_3;
+      else
+        val = E_MIPS_ARCH_1;
+      break;
+
     case bfd_mach_mips3000:
       val = E_MIPS_ARCH_1;
       break;
@@ -12254,8 +12415,7 @@ _bfd_mips_elf_sort_relocs_p (asection *sec)
    number.  This is used by both the 32-bit and the 64-bit ABI.  */
 
 void
-_bfd_mips_elf_final_write_processing (bfd *abfd,
-                                     bfd_boolean linker ATTRIBUTE_UNUSED)
+_bfd_mips_final_write_processing (bfd *abfd)
 {
   unsigned int i;
   Elf_Internal_Shdr **hdrpp;
@@ -12331,9 +12491,20 @@ _bfd_mips_elf_final_write_processing (bfd *abfd,
          (*hdrpp)->sh_link = elf_section_data (sec)->this_idx;
          break;
 
+       case SHT_MIPS_XHASH:
+         sec = bfd_get_section_by_name (abfd, ".dynsym");
+         if (sec != NULL)
+           (*hdrpp)->sh_link = elf_section_data (sec)->this_idx;
        }
     }
 }
+
+bfd_boolean
+_bfd_mips_elf_final_write_processing (bfd *abfd)
+{
+  _bfd_mips_final_write_processing (abfd);
+  return _bfd_elf_final_write_processing (abfd);
+}
 \f
 /* When creating an IRIX5 executable, we need REGINFO and RTPROC
    segments.  */
@@ -12913,7 +13084,6 @@ _bfd_mips_elf_find_nearest_line (bfd *abfd, asymbol **symbols,
                                     filename_ptr, functionname_ptr,
                                     line_ptr, discriminator_ptr,
                                     dwarf_debug_sections,
-                                    ABI_64_P (abfd) ? 8 : 0,
                                     &elf_tdata (abfd)->dwarf2_find_line_info)
       || _bfd_dwarf1_find_nearest_line (abfd, symbols, section, offset,
                                        filename_ptr, functionname_ptr,
@@ -14192,6 +14362,16 @@ _bfd_mips_elf_linker_flags (struct bfd_link_info *info, bfd_boolean insn32,
   mips_elf_hash_table (info)->ignore_branch_isa = ignore_branch_isa;
   mips_elf_hash_table (info)->gnu_target = gnu_target;
 }
+
+/* A function that the linker calls to enable use of compact branches in
+   linker generated code for MIPSR6.  */
+
+void
+_bfd_mips_elf_compact_branches (struct bfd_link_info *info, bfd_boolean on)
+{
+  mips_elf_hash_table (info)->compact_branches = on;
+}
+
 \f
 /* Structure for saying that BFD machine EXTENSION extends BASE.  */
 
@@ -15817,6 +15997,8 @@ _bfd_mips_elf_get_target_dtag (bfd_vma dtag)
       return "DT_MIPS_PLTGOT";
     case DT_MIPS_RWPLT:
       return "DT_MIPS_RWPLT";
+    case DT_MIPS_XHASH:
+      return "DT_MIPS_XHASH";
     }
 }
 
@@ -16150,6 +16332,7 @@ const struct bfd_elf_special_section _bfd_mips_elf_special_sections[] =
   { STRING_COMMA_LEN (".sbss"),         -2, SHT_NOBITS,     SHF_ALLOC + SHF_WRITE + SHF_MIPS_GPREL },
   { STRING_COMMA_LEN (".sdata"), -2, SHT_PROGBITS,   SHF_ALLOC + SHF_WRITE + SHF_MIPS_GPREL },
   { STRING_COMMA_LEN (".ucode"),  0, SHT_MIPS_UCODE, 0 },
+  { STRING_COMMA_LEN (".MIPS.xhash"),  0, SHT_MIPS_XHASH,   SHF_ALLOC },
   { NULL,                    0,  0, 0,              0 }
 };
 
@@ -16464,6 +16647,7 @@ enum
   MIPS_LIBC_ABI_UNIQUE,
   MIPS_LIBC_ABI_MIPS_O32_FP64,
   MIPS_LIBC_ABI_ABSOLUTE,
+  MIPS_LIBC_ABI_XHASH,
   MIPS_LIBC_ABI_MAX
 };
 
@@ -16491,6 +16675,11 @@ _bfd_mips_post_process_headers (bfd *abfd, struct bfd_link_info *link_info)
   if (htab != NULL && htab->use_absolute_zero && htab->gnu_target)
     i_ehdrp->e_ident[EI_ABIVERSION] = MIPS_LIBC_ABI_ABSOLUTE;
 
+  /* Mark that we need support for .MIPS.xhash in the dynamic linker,
+     if it is the only hash section that will be created.  */
+  if (link_info && link_info->emit_gnu_hash && !link_info->emit_hash)
+    i_ehdrp->e_ident[EI_ABIVERSION] = MIPS_LIBC_ABI_XHASH;
+
   _bfd_elf_post_process_headers (abfd, link_info);
 }
 
@@ -16509,3 +16698,17 @@ _bfd_mips_elf_cant_unwind_opcode
 {
   return COMPACT_EH_CANT_UNWIND_OPCODE;
 }
+
+/* Record a position XLAT_LOC in the xlat translation table, associated with
+   the hash entry H.  The entry in the translation table will later be
+   populated with the real symbol dynindx.  */
+
+void
+_bfd_mips_elf_record_xhash_symbol (struct elf_link_hash_entry *h,
+                                  bfd_vma xlat_loc)
+{
+  struct mips_elf_link_hash_entry *hmips;
+
+  hmips = (struct mips_elf_link_hash_entry *) h;
+  hmips->mipsxhash_loc = xlat_loc;
+}
This page took 0.036883 seconds and 4 git commands to generate.