/* 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
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;
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;
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
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;
}
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;
&& ! CONST_STRNEQ (name, ".MIPS.post_rel"))
return FALSE;
break;
+ case SHT_MIPS_XHASH:
+ if (strcmp (name, ".MIPS.xhash") != 0)
+ return FALSE;
default:
break;
}
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
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
{
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:
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,
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;
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;
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
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;
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;
(*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. */
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,
return "DT_MIPS_PLTGOT";
case DT_MIPS_RWPLT:
return "DT_MIPS_RWPLT";
+ case DT_MIPS_XHASH:
+ return "DT_MIPS_XHASH";
}
}
{ 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 }
};
MIPS_LIBC_ABI_UNIQUE,
MIPS_LIBC_ABI_MIPS_O32_FP64,
MIPS_LIBC_ABI_ABSOLUTE,
+ MIPS_LIBC_ABI_XHASH,
MIPS_LIBC_ABI_MAX
};
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);
}
{
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;
+}