/* MIPS-specific support for ELF
- Copyright (C) 1993-2019 Free Software Foundation, Inc.
+ Copyright (C) 1993-2020 Free Software Foundation, Inc.
Most of the information added by Ian Lance Taylor, Cygnus Support,
<ian@cygnus.com>.
#include "libbfd.h"
#include "libiberty.h"
#include "elf-bfd.h"
+#include "ecoff-bfd.h"
#include "elfxx-mips.h"
#include "elf/mips.h"
#include "elf-vxworks.h"
/* 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;
/* True if we are targetting R6 compact branches. */
bfd_boolean compact_branches;
- /* True if we're generating code for VxWorks. */
- bfd_boolean is_vxworks;
-
/* True if we already reported the small-data section overflow. */
bfd_boolean small_data_overflow_reported;
/* The name of the dynamic relocation section. */
#define MIPS_ELF_REL_DYN_NAME(INFO) \
- (mips_elf_hash_table (INFO)->is_vxworks ? ".rela.dyn" : ".rel.dyn")
+ (mips_elf_hash_table (INFO)->root.target_os == is_vxworks \
+ ? ".rela.dyn" : ".rel.dyn")
/* In case we're on a 32-bit machine, construct a 64-bit "-1" value
from smaller values. Start with zero, widen, *then* decrement. */
/* The offset of $gp from the beginning of the .got section. */
#define ELF_MIPS_GP_OFFSET(INFO) \
- (mips_elf_hash_table (INFO)->is_vxworks ? 0x0 : 0x7ff0)
+ (mips_elf_hash_table (INFO)->root.target_os == is_vxworks \
+ ? 0x0 : 0x7ff0)
/* The maximum size of the GOT for it to be addressable using 16-bit
offsets from $gp. */
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;
if (!sec->used_by_bfd)
{
struct _mips_elf_section_data *sdata;
- bfd_size_type amt = sizeof (*sdata);
+ size_t amt = sizeof (*sdata);
sdata = bfd_zalloc (abfd, amt);
if (sdata == NULL)
/* The symbolic header contains absolute file offsets and sizes to
read. */
#define READ(ptr, offset, count, size, type) \
- if (symhdr->count == 0) \
- debug->ptr = NULL; \
- else \
+ do \
{ \
- bfd_size_type amt = (bfd_size_type) size * symhdr->count; \
- debug->ptr = bfd_malloc (amt); \
- if (debug->ptr == NULL) \
+ size_t amt; \
+ debug->ptr = NULL; \
+ if (symhdr->count == 0) \
+ break; \
+ if (_bfd_mul_overflow (size, symhdr->count, &amt)) \
+ { \
+ bfd_set_error (bfd_error_file_too_big); \
+ goto error_return; \
+ } \
+ if (bfd_seek (abfd, symhdr->offset, SEEK_SET) != 0) \
goto error_return; \
- if (bfd_seek (abfd, symhdr->offset, SEEK_SET) != 0 \
- || bfd_bread (debug->ptr, amt, abfd) != amt) \
+ debug->ptr = (type) _bfd_malloc_and_read (abfd, amt, amt); \
+ if (debug->ptr == NULL) \
goto error_return; \
- }
+ } while (0)
READ (line, cbLineOffset, cbLine, sizeof (unsigned char), unsigned char *);
READ (external_dnr, cbDnOffset, idnMax, swap->external_dnr_size, void *);
return TRUE;
error_return:
- if (ext_hdr != NULL)
- free (ext_hdr);
- if (debug->line != NULL)
- free (debug->line);
- if (debug->external_dnr != NULL)
- free (debug->external_dnr);
- if (debug->external_pdr != NULL)
- free (debug->external_pdr);
- if (debug->external_sym != NULL)
- free (debug->external_sym);
- if (debug->external_opt != NULL)
- free (debug->external_opt);
- if (debug->external_aux != NULL)
- free (debug->external_aux);
- if (debug->ss != NULL)
- free (debug->ss);
- if (debug->ssext != NULL)
- free (debug->ssext);
- if (debug->external_fdr != NULL)
- free (debug->external_fdr);
- if (debug->external_rfd != NULL)
- free (debug->external_rfd);
- if (debug->external_ext != NULL)
- free (debug->external_ext);
+ free (ext_hdr);
+ free (debug->line);
+ free (debug->external_dnr);
+ free (debug->external_pdr);
+ free (debug->external_sym);
+ free (debug->external_opt);
+ free (debug->external_aux);
+ free (debug->ss);
+ free (debug->ssext);
+ free (debug->external_fdr);
+ free (debug->external_rfd);
+ free (debug->external_ext);
return FALSE;
}
\f
matters, but someday it might). */
s->map_head.link_order = NULL;
- if (epdr != NULL)
- free (epdr);
- if (rpdr != NULL)
- free (rpdr);
- if (esym != NULL)
- free (esym);
- if (ss != NULL)
- free (ss);
- if (sv != NULL)
- free (sv);
-
+ free (epdr);
+ free (rpdr);
+ free (esym);
+ free (ss);
+ free (sv);
return TRUE;
error_return:
- if (epdr != NULL)
- free (epdr);
- if (rpdr != NULL)
- free (rpdr);
- if (esym != NULL)
- free (esym);
- if (ss != NULL)
- free (ss);
- if (sv != NULL)
- free (sv);
+ free (epdr);
+ free (rpdr);
+ free (esym);
+ free (ss);
+ free (sv);
return FALSE;
}
\f
{
const char *name;
- name = bfd_get_section_name (section->owner, section);
+ name = bfd_section_name (section);
return (FN_STUB_P (name)
|| CALL_STUB_P (name)
|| CALL_FP_STUB_P (name)
/* Make sure that any padding goes before the stub. */
align = input_section->alignment_power;
- if (!bfd_set_section_alignment (s->owner, s, align))
+ if (!bfd_set_section_alignment (s, align))
return FALSE;
if (align > 3)
s->size = (1 << align) - 8;
asection *input_section = stub->h->root.root.u.def.section;
s = htab->add_stub_section (".text", NULL,
input_section->output_section);
- if (s == NULL || !bfd_set_section_alignment (s->owner, s, 4))
+ if (s == NULL || !bfd_set_section_alignment (s, 4))
return FALSE;
htab->strampoline = s;
}
bfd *output_bfd, char **error_message)
{
if ((symbol->flags & (BSF_GLOBAL | BSF_WEAK)) != 0
- || bfd_is_und_section (bfd_get_section (symbol))
- || bfd_is_com_section (bfd_get_section (symbol)))
+ || bfd_is_und_section (bfd_asymbol_section (symbol))
+ || bfd_is_com_section (bfd_asymbol_section (symbol)))
/* The relocation is against a global symbol. */
return _bfd_mips_elf_generic_reloc (abfd, reloc_entry, symbol, data,
input_section, output_bfd,
h->esym.asym.sc = scUndefined;
else
{
- name = bfd_section_name (output_section->owner, output_section);
+ name = bfd_section_name (output_section);
if (strcmp (name, ".text") == 0)
h->esym.asym.sc = scText;
| SEC_LINKER_CREATED
| SEC_READONLY));
if (sreloc == NULL
- || ! bfd_set_section_alignment (dynobj, sreloc,
- MIPS_ELF_LOG_FILE_ALIGN (dynobj)))
+ || !bfd_set_section_alignment (sreloc,
+ MIPS_ELF_LOG_FILE_ALIGN (dynobj)))
return NULL;
}
return sreloc;
MIPS_ELF_PUT_WORD (abfd, value, htab->root.sgot->contents + entry->gotidx);
/* These GOT entries need a dynamic relocation on VxWorks. */
- if (htab->is_vxworks)
+ if (htab->root.target_os == is_vxworks)
{
Elf_Internal_Rela outrel;
asection *s;
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;
}
s = mips_elf_rel_dyn_section (info, FALSE);
BFD_ASSERT (s != NULL);
- if (htab->is_vxworks)
+ if (htab->root.target_os == is_vxworks)
s->size += n * MIPS_ELF_RELA_SIZE (abfd);
else
{
entry if it was only used for relocations; those relocations
will be against the null or section symbol instead of H. */
h->global_got_area = GGA_NONE;
- else if (htab->is_vxworks
+ else if (htab->root.target_os == is_vxworks
&& h->got_only_for_calls
&& h->root.plt.plist->mips_offset != MINUS_ONE)
/* On VxWorks, calls can refer directly to the .got.plt entry;
s = bfd_make_section_anyway_with_flags (abfd, ".compact_rel", flags);
if (s == NULL
- || ! bfd_set_section_alignment (abfd, s,
- MIPS_ELF_LOG_FILE_ALIGN (abfd)))
+ || !bfd_set_section_alignment (s, MIPS_ELF_LOG_FILE_ALIGN (abfd)))
return FALSE;
s->size = sizeof (Elf32_External_compact_rel);
in the function stub generation and in the linker script. */
s = bfd_make_section_anyway_with_flags (abfd, ".got", flags);
if (s == NULL
- || ! bfd_set_section_alignment (abfd, s, 4))
+ || !bfd_set_section_alignment (s, 4))
return FALSE;
htab->root.sgot = s;
static bfd_boolean
is_gott_symbol (struct bfd_link_info *info, struct elf_link_hash_entry *h)
{
- return (mips_elf_hash_table (info)->is_vxworks
+ return (mips_elf_hash_table (info)->root.target_os == is_vxworks
&& bfd_link_pic (info)
&& (strcmp (h->root.root.string, "__GOTT_BASE__") == 0
|| strcmp (h->root.root.string, "__GOTT_INDEX__") == 0));
symtab_hdr->sh_link,
sym->st_name);
if (*namep == NULL || **namep == '\0')
- *namep = bfd_section_name (input_bfd, sec);
+ *namep = bfd_section_name (sec);
/* For relocations against a section symbol and ones against no
symbol (absolute relocations) infer the ISA mode from the addend. */
}
else
{
- bfd_boolean reject_undefined
- = (info->unresolved_syms_in_objects == RM_GENERATE_ERROR
- || ELF_ST_VISIBILITY (h->root.other) != STV_DEFAULT);
+ bfd_boolean reject_undefined
+ = (info->unresolved_syms_in_objects == RM_DIAGNOSE
+ && !info->warn_unresolved_syms)
+ || ELF_ST_VISIBILITY (h->root.other) != STV_DEFAULT;
- (*info->callbacks->undefined_symbol)
+ info->callbacks->undefined_symbol
(info, h->root.root.root.string, input_bfd,
input_section, relocation->r_offset, reject_undefined);
sec = NULL;
for (o = input_bfd->sections; o != NULL; o = o->next)
{
- if (CALL_FP_STUB_P (bfd_get_section_name (input_bfd, o)))
+ if (CALL_FP_STUB_P (bfd_section_name (o)))
{
sec = h->call_fp_stub;
break;
{
/* On VxWorks, CALL relocations should refer to the .got.plt
entry, which is initialized to point at the PLT stub. */
- if (htab->is_vxworks
+ if (htab->root.target_os == is_vxworks
&& (call_hi16_reloc_p (r_type)
|| call_lo16_reloc_p (r_type)
|| call16_reloc_p (r_type)))
MIPS_ELF_PUT_WORD (dynobj, symbol, htab->root.sgot->contents + g);
}
}
- else if (!htab->is_vxworks
+ else if (htab->root.target_os != is_vxworks
&& (call16_reloc_p (r_type) || got16_reloc_p (r_type)))
/* The calculation below does not involve "g". */
break;
case R_MICROMIPS_CALL16:
/* VxWorks does not have separate local and global semantics for
R_MIPS*_GOT16; every relocation evaluates to "G". */
- if (!htab->is_vxworks && local_p)
+ if (htab->root.target_os != is_vxworks && local_p)
{
value = mips_elf_got16_entry (abfd, input_bfd, info,
symbol + addend, !was_local_p);
}
/* Make this the JALX opcode. */
- x = (x & ~(0x3f << 26)) | (jalx_opcode << 26);
+ x = (x & ~(0x3fu << 26)) | (jalx_opcode << 26);
}
else if (cross_mode_jump_p && b_reloc_p (r_type))
{
in the relocation. */
if (h != NULL && ! SYMBOL_REFERENCES_LOCAL (info, &h->root))
{
- BFD_ASSERT (htab->is_vxworks || h->global_got_area != GGA_NONE);
+ BFD_ASSERT (htab->root.target_os == is_vxworks
+ || h->global_got_area != GGA_NONE);
indx = h->root.dynindx;
if (SGI_COMPAT (output_bfd))
defined_p = h->root.def_regular;
if (defined_p && r_type != R_MIPS_REL32)
*addendp += symbol;
- if (htab->is_vxworks)
+ if (htab->root.target_os == is_vxworks)
/* VxWorks uses non-relative relocations for this. */
outrel[0].r_info = ELF32_R_INFO (indx, R_MIPS_32);
else
(sreloc->contents
+ sreloc->reloc_count * sizeof (Elf64_Mips_External_Rel)));
}
- else if (htab->is_vxworks)
+ else if (htab->root.target_os == is_vxworks)
{
/* VxWorks uses RELA rather than REL dynamic relocations. */
outrel[0].r_addend = *addendp;
if (hdr->bfd_section != NULL)
{
- const char *name = bfd_get_section_name (abfd, hdr->bfd_section);
+ const char *name = bfd_section_name (hdr->bfd_section);
/* .sbss is not handled specially here because the GNU/Linux
prelinker can convert .sbss from NOBITS to PROGBITS and
/* Handle a MIPS specific section when reading an object file. This
is called when elfcode.h finds a section with an unknown type.
- This routine supports both the 32-bit and 64-bit ELF ABI.
-
- FIXME: We need to handle the SHF_MIPS_GPREL flag, but I'm not sure
- how to. */
+ This routine supports both the 32-bit and 64-bit ELF ABI. */
bfd_boolean
_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;
}
if (! _bfd_elf_make_section_from_shdr (abfd, hdr, name, shindex))
return FALSE;
+ if (hdr->sh_flags & SHF_MIPS_GPREL)
+ flags |= SEC_SMALL_DATA;
+
if (flags)
{
- if (! bfd_set_section_flags (abfd, hdr->bfd_section,
- (bfd_get_section_flags (abfd,
- hdr->bfd_section)
- | flags)))
+ if (!bfd_set_section_flags (hdr->bfd_section,
+ (bfd_section_flags (hdr->bfd_section)
+ | flags)))
return FALSE;
}
bfd_boolean
_bfd_mips_elf_fake_sections (bfd *abfd, Elf_Internal_Shdr *hdr, asection *sec)
{
- const char *name = bfd_get_section_name (abfd, sec);
+ const char *name = bfd_section_name (sec);
if (strcmp (name, ".liblist") == 0)
{
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
_bfd_mips_elf_section_from_bfd_section (bfd *abfd ATTRIBUTE_UNUSED,
asection *sec, int *retval)
{
- if (strcmp (bfd_get_section_name (abfd, sec), ".scommon") == 0)
+ if (strcmp (bfd_section_name (sec), ".scommon") == 0)
{
*retval = SHN_MIPS_SCOMMON;
return TRUE;
}
- if (strcmp (bfd_get_section_name (abfd, sec), ".acommon") == 0)
+ if (strcmp (bfd_section_name (sec), ".acommon") == 0)
{
*retval = SHN_MIPS_ACOMMON;
return TRUE;
{
asymbol *elf_text_symbol;
asection *elf_text_section;
- bfd_size_type amt = sizeof (asection);
+ size_t amt = sizeof (asection);
elf_text_section = bfd_zalloc (abfd, amt);
if (elf_text_section == NULL)
{
asymbol *elf_data_symbol;
asection *elf_data_section;
- bfd_size_type amt = sizeof (asection);
+ size_t amt = sizeof (asection);
elf_data_section = bfd_zalloc (abfd, amt);
if (elf_data_section == NULL)
/* The psABI requires a read-only .dynamic section, but the VxWorks
EABI doesn't. */
- if (!htab->is_vxworks)
+ if (htab->root.target_os != is_vxworks)
{
s = bfd_get_linker_section (abfd, ".dynamic");
if (s != NULL)
{
- if (! bfd_set_section_flags (abfd, s, flags))
+ if (!bfd_set_section_flags (s, flags))
return FALSE;
}
}
MIPS_ELF_STUB_SECTION_NAME (abfd),
flags | SEC_CODE);
if (s == NULL
- || ! bfd_set_section_alignment (abfd, s,
- MIPS_ELF_LOG_FILE_ALIGN (abfd)))
+ || !bfd_set_section_alignment (s, MIPS_ELF_LOG_FILE_ALIGN (abfd)))
return FALSE;
htab->sstubs = s;
s = bfd_make_section_anyway_with_flags (abfd, ".rld_map",
flags &~ (flagword) SEC_READONLY);
if (s == NULL
- || ! bfd_set_section_alignment (abfd, s,
- MIPS_ELF_LOG_FILE_ALIGN (abfd)))
+ || !bfd_set_section_alignment (s, MIPS_ELF_LOG_FILE_ALIGN (abfd)))
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
/* Change alignments of some sections. */
s = bfd_get_linker_section (abfd, ".hash");
if (s != NULL)
- (void) bfd_set_section_alignment (abfd, s, MIPS_ELF_LOG_FILE_ALIGN (abfd));
+ bfd_set_section_alignment (s, MIPS_ELF_LOG_FILE_ALIGN (abfd));
s = bfd_get_linker_section (abfd, ".dynsym");
if (s != NULL)
- (void) bfd_set_section_alignment (abfd, s, MIPS_ELF_LOG_FILE_ALIGN (abfd));
+ bfd_set_section_alignment (s, MIPS_ELF_LOG_FILE_ALIGN (abfd));
s = bfd_get_linker_section (abfd, ".dynstr");
if (s != NULL)
- (void) bfd_set_section_alignment (abfd, s, MIPS_ELF_LOG_FILE_ALIGN (abfd));
+ bfd_set_section_alignment (s, MIPS_ELF_LOG_FILE_ALIGN (abfd));
/* ??? */
s = bfd_get_section_by_name (abfd, ".reginfo");
if (s != NULL)
- (void) bfd_set_section_alignment (abfd, s, MIPS_ELF_LOG_FILE_ALIGN (abfd));
+ bfd_set_section_alignment (s, MIPS_ELF_LOG_FILE_ALIGN (abfd));
s = bfd_get_linker_section (abfd, ".dynamic");
if (s != NULL)
- (void) bfd_set_section_alignment (abfd, s, MIPS_ELF_LOG_FILE_ALIGN (abfd));
+ bfd_set_section_alignment (s, MIPS_ELF_LOG_FILE_ALIGN (abfd));
}
if (bfd_link_executable (info))
return FALSE;
/* Do the usual VxWorks handling. */
- if (htab->is_vxworks
+ if (htab->root.target_os == is_vxworks
&& !elf_vxworks_create_dynamic_sections (abfd, info, &htab->srelplt2))
return FALSE;
/* Check for the mips16 stub sections. */
- name = bfd_get_section_name (abfd, sec);
+ name = bfd_section_name (sec);
if (FN_STUB_P (name))
{
unsigned long r_symndx;
call_reloc_p = FALSE;
/* Set CONSTRAIN_SYMBOL_P if we need to take the relocation
- into account when deciding how to define the symbol.
- Relocations in nonallocatable sections such as .pdr and
- .debug* should have no effect. */
- constrain_symbol_p = ((sec->flags & SEC_ALLOC) != 0);
+ into account when deciding how to define the symbol. */
+ constrain_symbol_p = TRUE;
switch (r_type)
{
elf_hash_table (info)->dynobj = dynobj = abfd;
if (!mips_elf_create_got_section (dynobj, info))
return FALSE;
- if (htab->is_vxworks && !bfd_link_pic (info))
+ if (htab->root.target_os == is_vxworks
+ && !bfd_link_pic (info))
{
_bfd_error_handler
/* xgettext:c-format */
against a read-only section. */
if ((bfd_link_pic (info)
|| (h != NULL
- && !htab->is_vxworks
+ && htab->root.target_os != is_vxworks
&& strcmp (h->root.root.string, "__gnu_local_gp") != 0
&& !(!info->nocopyreloc
&& !PIC_OBJECT_P (abfd)
relocations related to taking the function's address.
This doesn't apply to VxWorks, where CALL relocs refer
to a .got.plt entry instead of a normal .got entry. */
- if (!htab->is_vxworks && (!can_make_dynamic_p || !call_reloc_p))
+ if (htab->root.target_os != is_vxworks
+ && (!can_make_dynamic_p || !call_reloc_p))
((struct mips_elf_link_hash_entry *) h)->no_fn_stub = TRUE;
}
else if (call_lo16_reloc_p (r_type)
|| got_lo16_reloc_p (r_type)
|| got_disp_reloc_p (r_type)
- || (got16_reloc_p (r_type) && htab->is_vxworks))
+ || (got16_reloc_p (r_type)
+ && htab->root.target_os == is_vxworks))
{
/* We may need a local GOT entry for this relocation. We
don't count R_MIPS_GOT_PAGE because we can estimate the
/* VxWorks executables are handled elsewhere; we only need to
allocate relocations in shared objects. */
- if (htab->is_vxworks && !bfd_link_pic (info))
+ if (htab->root.target_os == is_vxworks && !bfd_link_pic (info))
return TRUE;
/* Ignore indirect symbols. All relocations against such symbols
VxWorks does not enforce the same mapping between the GOT
and the symbol table, so the same requirement does not
apply there. */
- if (!htab->is_vxworks)
+ if (htab->root.target_os != is_vxworks)
{
if (hmips->global_got_area > GGA_RELOC_ONLY)
hmips->global_got_area = GGA_RELOC_ONLY;
hmips = (struct mips_elf_link_hash_entry *) h;
/* Make sure we know what is going on here. */
- BFD_ASSERT (dynobj != NULL
- && (h->needs_plt
- || h->is_weakalias
- || (h->def_dynamic
- && h->ref_regular
- && !h->def_regular)));
+ if (dynobj == NULL
+ || (! h->needs_plt
+ && ! h->is_weakalias
+ && (! h->def_dynamic
+ || ! h->ref_regular
+ || h->def_regular)))
+ {
+ if (h->type == STT_GNU_IFUNC)
+ _bfd_error_handler (_("IFUNC symbol %s in dynamic symbol table - IFUNCS are not supported"),
+ h->root.root.string);
+ else
+ _bfd_error_handler (_("non-dynamic symbol %s in dynamic symbol table"),
+ h->root.root.string);
+ return TRUE;
+ }
hmips = (struct mips_elf_link_hash_entry *) h;
Traditional stubs are only available on SVR4 psABI-based systems;
VxWorks always uses PLTs instead. */
- if (!htab->is_vxworks && h->needs_plt && !hmips->no_fn_stub)
+ if (htab->root.target_os != is_vxworks
+ && h->needs_plt
+ && !hmips->no_fn_stub)
{
if (! elf_hash_table (info)->dynamic_sections_created)
return TRUE;
entry is 16 bytes and the PLT0 entry is 32 bytes.
Encourage better cache usage by aligning. We do this
lazily to avoid pessimizing traditional objects. */
- if (!htab->is_vxworks
- && !bfd_set_section_alignment (dynobj, htab->root.splt, 5))
+ if (htab->root.target_os != is_vxworks
+ && !bfd_set_section_alignment (htab->root.splt, 5))
return FALSE;
/* Make sure that .got.plt is word-aligned. We do this lazily
for the same reason as above. */
- if (!bfd_set_section_alignment (dynobj, htab->root.sgotplt,
+ if (!bfd_set_section_alignment (htab->root.sgotplt,
MIPS_ELF_LOG_FILE_ALIGN (dynobj)))
return FALSE;
/* On non-VxWorks targets, the first two entries in .got.plt
are reserved. */
- if (!htab->is_vxworks)
+ if (htab->root.target_os != is_vxworks)
htab->plt_got_index
+= (get_elf_backend_data (dynobj)->got_header_size
/ MIPS_ELF_GOT_SIZE (dynobj));
/* On VxWorks, also allocate room for the header's
.rela.plt.unloaded entries. */
- if (htab->is_vxworks && !bfd_link_pic (info))
+ if (htab->root.target_os == is_vxworks
+ && !bfd_link_pic (info))
htab->srelplt2->size += 2 * sizeof (Elf32_External_Rela);
/* Now work out the sizes of individual PLT entries. */
- if (htab->is_vxworks && bfd_link_pic (info))
+ if (htab->root.target_os == is_vxworks
+ && bfd_link_pic (info))
htab->plt_mips_entry_size
= 4 * ARRAY_SIZE (mips_vxworks_shared_plt_entry);
- else if (htab->is_vxworks)
+ else if (htab->root.target_os == is_vxworks)
htab->plt_mips_entry_size
= 4 * ARRAY_SIZE (mips_vxworks_exec_plt_entry);
else if (newabi_p)
standard entry actually has to be used as the stub ends with a J
instruction. */
if (newabi_p
- || htab->is_vxworks
+ || htab->root.target_os == is_vxworks
|| hmips->call_stub
|| hmips->call_fp_stub)
{
hmips->use_plt_entry = TRUE;
/* Make room for the R_MIPS_JUMP_SLOT relocation. */
- htab->root.srelplt->size += (htab->is_vxworks
+ htab->root.srelplt->size += (htab->root.target_os == is_vxworks
? MIPS_ELF_RELA_SIZE (dynobj)
: MIPS_ELF_REL_SIZE (dynobj));
/* Make room for the .rela.plt.unloaded relocations. */
- if (htab->is_vxworks && !bfd_link_pic (info))
+ if (htab->root.target_os == is_vxworks && !bfd_link_pic (info))
htab->srelplt2->size += 3 * sizeof (Elf32_External_Rela);
/* All relocations against this symbol that could have been made
}
if ((h->root.u.def.section->flags & SEC_ALLOC) != 0)
{
- if (htab->is_vxworks)
+ if (htab->root.target_os == is_vxworks)
srel->size += sizeof (Elf32_External_Rela);
else
mips_elf_allocate_dynamic_relocations (dynobj, info, 1);
sect = bfd_get_section_by_name (output_bfd, ".reginfo");
if (sect != NULL)
{
- bfd_set_section_size (output_bfd, sect, sizeof (Elf32_External_RegInfo));
+ bfd_set_section_size (sect, sizeof (Elf32_External_RegInfo));
sect->flags |= SEC_FIXED_SIZE | SEC_HAS_CONTENTS;
}
sect = bfd_get_section_by_name (output_bfd, ".MIPS.abiflags");
if (sect != NULL)
{
- bfd_set_section_size (output_bfd, sect,
- sizeof (Elf_External_ABIFlags_v0));
+ bfd_set_section_size (sect, sizeof (Elf_External_ABIFlags_v0));
sect->flags |= SEC_FIXED_SIZE | SEC_HAS_CONTENTS;
}
/* Allocate room for the reserved entries. VxWorks always reserves
3 entries; other objects only reserve 2 entries. */
BFD_ASSERT (g->assigned_low_gotno == 0);
- if (htab->is_vxworks)
+ if (htab->root.target_os == is_vxworks)
htab->reserved_gotno = 3;
else
htab->reserved_gotno = 2;
}
}
- if (htab->is_vxworks)
+ if (htab->root.target_os == is_vxworks)
/* There's no need to allocate page entries for VxWorks; R_MIPS*_GOT16
relocations against local symbols evaluate to "G", and the EABI does
not include R_MIPS_GOT_PAGE. */
/* VxWorks does not support multiple GOTs. It initializes $gp to
__GOTT_BASE__[__GOTT_INDEX__], the value of which is set by the
dynamic loader. */
- if (!htab->is_vxworks && s->size > MIPS_ELF_GOT_MAX_SIZE (info))
+ if (htab->root.target_os != is_vxworks
+ && s->size > MIPS_ELF_GOT_MAX_SIZE (info))
{
if (!mips_elf_multi_got (output_bfd, info, s, page_gotno))
return FALSE;
== g->global_gotno + g->local_gotno + g->tls_gotno);
/* Each VxWorks GOT entry needs an explicit relocation. */
- if (htab->is_vxworks && bfd_link_pic (info))
+ if (htab->root.target_os == is_vxworks && bfd_link_pic (info))
g->relocs += g->global_gotno + g->local_gotno - htab->reserved_gotno;
/* Allocate room for the TLS relocations. */
/* For VxWorks, point at the PLT load stub rather than the lazy
resolution stub; this stub will become the canonical function
address. */
- if (htab->is_vxworks)
+ if (htab->root.target_os == is_vxworks)
val += 8;
h->root.root.u.def.section = htab->root.splt;
BFD_ASSERT (htab->root.sgotplt->size == 0);
BFD_ASSERT (htab->root.splt->size == 0);
- if (htab->is_vxworks && bfd_link_pic (info))
+ if (htab->root.target_os == is_vxworks && bfd_link_pic (info))
size = 4 * ARRAY_SIZE (mips_vxworks_shared_plt0_entry);
- else if (htab->is_vxworks)
+ else if (htab->root.target_os == is_vxworks)
size = 4 * ARRAY_SIZE (mips_vxworks_exec_plt0_entry);
else if (ABI_64_P (output_bfd))
size = 4 * ARRAY_SIZE (mips_n64_exec_plt0_entry);
/* It's OK to base decisions on the section name, because none
of the dynobj section names depend upon the input files. */
- name = bfd_get_section_name (dynobj, s);
+ name = bfd_section_name (s);
if ((s->flags & SEC_LINKER_CREATED) == 0)
continue;
assert a DT_TEXTREL entry rather than testing whether
there exists a relocation to a read only section or
not. */
- outname = bfd_get_section_name (output_bfd,
- s->output_section);
+ outname = bfd_section_name (s->output_section);
target = bfd_get_section_by_name (output_bfd, outname + 4);
if ((target != NULL
&& (target->flags & SEC_READONLY) != 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)
+ && htab->root.target_os != is_vxworks
+ && s->size > 0)
s->size += 4;
}
else if (! CONST_STRNEQ (name, ".init")
&& !MIPS_ELF_ADD_DYNAMIC_ENTRY (info, DT_DEBUG, 0))
return FALSE;
- if (reltext && (SGI_COMPAT (output_bfd) || htab->is_vxworks))
+ if (reltext
+ && (SGI_COMPAT (output_bfd)
+ || htab->root.target_os == is_vxworks))
info->flags |= DF_TEXTREL;
if ((info->flags & DF_TEXTREL) != 0)
return FALSE;
sreldyn = mips_elf_rel_dyn_section (info, FALSE);
- if (htab->is_vxworks)
+ if (htab->root.target_os == is_vxworks)
{
/* VxWorks uses .rela.dyn instead of .rel.dyn. It does not
use any of the DT_MIPS_* tags. */
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;
if (! MIPS_ELF_ADD_DYNAMIC_ENTRY (info, DT_MIPS_PLTGOT, 0))
return FALSE;
}
- if (htab->is_vxworks
+ if (htab->root.target_os == is_vxworks
&& !elf_vxworks_add_dynamic_entries (output_bfd, info))
return FALSE;
}
dynobj = elf_hash_table (info)->dynobj;
hmips = (struct mips_elf_link_hash_entry *) h;
- BFD_ASSERT (!htab->is_vxworks);
+ BFD_ASSERT (htab->root.target_os != is_vxworks);
if (h->plt.plist != NULL
&& (h->plt.plist->mips_offset != MINUS_ONE
break;
case DT_RELAENT:
- BFD_ASSERT (htab->is_vxworks);
+ BFD_ASSERT (htab->root.target_os == is_vxworks);
dyn.d_un.d_val = MIPS_ELF_RELA_SIZE (dynobj);
break;
case DT_PLTREL:
BFD_ASSERT (htab->use_plts_and_copy_relocs);
- if (htab->is_vxworks)
+ if (htab->root.target_os == is_vxworks)
dyn.d_un.d_val = DT_RELA;
else
dyn.d_un.d_val = DT_REL;
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
+ if (htab->root.target_os == is_vxworks
&& elf_vxworks_finish_dynamic_entry (output_bfd, &dyn))
swap_out_p = TRUE;
break;
if (sgot != NULL && sgot->size > 0
&& !bfd_is_abs_section (sgot->output_section))
{
- if (htab->is_vxworks)
+ if (htab->root.target_os == is_vxworks)
{
/* The first entry of the global offset table points to the
".dynamic" section. The second is initialized by the
increasing order of r_symndx. The VxWorks EABI doesn't require
this, and because the code below handles REL rather than RELA
relocations, using it for VxWorks would be outright harmful. */
- if (!htab->is_vxworks)
+ if (htab->root.target_os != is_vxworks)
{
s = mips_elf_rel_dyn_section (info, FALSE);
if (s != NULL
if (htab->root.splt && htab->root.splt->size > 0)
{
- if (htab->is_vxworks)
+ if (htab->root.target_os == is_vxworks)
{
if (bfd_link_pic (info))
mips_vxworks_finish_shared_plt (output_bfd, info);
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;
case SHT_MIPS_GPTAB:
BFD_ASSERT ((*hdrpp)->bfd_section != NULL);
- name = bfd_get_section_name (abfd, (*hdrpp)->bfd_section);
+ name = bfd_section_name ((*hdrpp)->bfd_section);
BFD_ASSERT (name != NULL
&& CONST_STRNEQ (name, ".gptab."));
sec = bfd_get_section_by_name (abfd, name + sizeof ".gptab" - 1);
case SHT_MIPS_CONTENT:
BFD_ASSERT ((*hdrpp)->bfd_section != NULL);
- name = bfd_get_section_name (abfd, (*hdrpp)->bfd_section);
+ name = bfd_section_name ((*hdrpp)->bfd_section);
BFD_ASSERT (name != NULL
&& CONST_STRNEQ (name, ".MIPS.content"));
sec = bfd_get_section_by_name (abfd,
case SHT_MIPS_EVENTS:
BFD_ASSERT ((*hdrpp)->bfd_section != NULL);
- name = bfd_get_section_name (abfd, (*hdrpp)->bfd_section);
+ name = bfd_section_name ((*hdrpp)->bfd_section);
BFD_ASSERT (name != NULL);
if (CONST_STRNEQ (name, ".MIPS.events"))
sec = bfd_get_section_by_name (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;
}
}
}
{
asection *s;
struct elf_segment_map *m, **pm;
- bfd_size_type amt;
+ size_t amt;
/* If there is a .reginfo section, we need a PT_MIPS_REGINFO
segment. */
&& s->vma + s->size <= high)
++c;
- amt = sizeof *n + (bfd_size_type) (c - 1) * sizeof (asection *);
+ amt = sizeof *n - sizeof (asection *) + c * sizeof (asection *);
n = bfd_zalloc (abfd, amt);
if (n == NULL)
return FALSE;
for (o = sub->sections; o != NULL; o = o->next)
if (!o->gc_mark
- && MIPS_ELF_ABIFLAGS_SECTION_NAME_P
- (bfd_get_section_name (sub, o)))
+ && MIPS_ELF_ABIFLAGS_SECTION_NAME_P (bfd_section_name (o)))
{
if (!_bfd_elf_gc_mark (info, o, gc_mark_hook))
return FALSE;
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,
- line_ptr))
- {
- /* PR 22789: If the function name or filename was not found through
- the debug information, then try an ordinary lookup instead. */
- if ((functionname_ptr != NULL && *functionname_ptr == NULL)
- || (filename_ptr != NULL && *filename_ptr == NULL))
- {
- /* Do not override already discovered names. */
- if (functionname_ptr != NULL && *functionname_ptr != NULL)
- functionname_ptr = NULL;
-
- if (filename_ptr != NULL && *filename_ptr != NULL)
- filename_ptr = NULL;
-
- _bfd_elf_find_function (abfd, symbols, section, offset,
- filename_ptr, functionname_ptr);
- }
+ == 1)
+ return TRUE;
+ if (_bfd_dwarf1_find_nearest_line (abfd, symbols, section, offset,
+ filename_ptr, functionname_ptr,
+ line_ptr))
+ {
+ if (!*functionname_ptr)
+ _bfd_elf_find_function (abfd, symbols, section, offset,
+ *filename_ptr ? NULL : filename_ptr,
+ functionname_ptr);
return TRUE;
}
if (elf_section_data (section) == NULL)
{
- bfd_size_type amt = sizeof (struct bfd_elf_section_data);
+ size_t amt = sizeof (struct bfd_elf_section_data);
section->used_by_bfd = bfd_zalloc (abfd, amt);
if (elf_section_data (section) == NULL)
return FALSE;
}
}
}
- if (reloc_vector != NULL)
- free (reloc_vector);
+ free (reloc_vector);
return data;
-error_return:
- if (reloc_vector != NULL)
- free (reloc_vector);
+ error_return:
+ free (reloc_vector);
return NULL;
}
\f
}
}
- if (internal_relocs != NULL
- && elf_section_data (sec)->relocs != internal_relocs)
+ if (elf_section_data (sec)->relocs != internal_relocs)
free (internal_relocs);
return TRUE;
error_return:
- if (isymbuf != NULL
- && symtab_hdr->contents != (unsigned char *) isymbuf)
+ if (symtab_hdr->contents != (unsigned char *) isymbuf)
free (isymbuf);
- if (contents != NULL
- && elf_section_data (sec)->this_hdr.contents != contents)
+ if (elf_section_data (sec)->this_hdr.contents != contents)
free (contents);
- if (internal_relocs != NULL
- && elf_section_data (sec)->relocs != internal_relocs)
+ if (elf_section_data (sec)->relocs != internal_relocs)
free (internal_relocs);
return FALSE;
_bfd_mips_elf_link_hash_table_create (bfd *abfd)
{
struct mips_elf_link_hash_table *ret;
- bfd_size_type amt = sizeof (struct mips_elf_link_hash_table);
+ size_t amt = sizeof (struct mips_elf_link_hash_table);
ret = bfd_zmalloc (amt);
if (ret == NULL)
htab = (struct mips_elf_link_hash_table *) ret;
htab->use_plts_and_copy_relocs = TRUE;
- htab->is_vxworks = TRUE;
}
return ret;
}
elf_gp (abfd) = (h->u.def.value
+ h->u.def.section->output_section->vma
+ h->u.def.section->output_offset);
- else if (htab->is_vxworks
+ else if (htab->root.target_os == is_vxworks
&& (h = bfd_link_hash_lookup (info->hash,
"_GLOBAL_OFFSET_TABLE_",
FALSE, FALSE, TRUE))
".rtproc",
flags);
if (rtproc_sec == NULL
- || ! bfd_set_section_alignment (abfd, rtproc_sec, 4))
+ || !bfd_set_section_alignment (rtproc_sec, 4))
return FALSE;
}
/* Check to see if the input BFD actually contains any sections. If not,
then it has no attributes, and its flags may not have been initialized
either, but it cannot actually cause any incompatibility. */
+ /* FIXME: This excludes any input shared library from consideration. */
for (sec = ibfd->sections; sec != NULL; sec = sec->next)
{
/* Ignore synthetic sections and empty .text, .data and .bss sections
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
};
-void
-_bfd_mips_post_process_headers (bfd *abfd, struct bfd_link_info *link_info)
+bfd_boolean
+_bfd_mips_init_file_header (bfd *abfd, struct bfd_link_info *link_info)
{
struct mips_elf_link_hash_table *htab = NULL;
Elf_Internal_Ehdr *i_ehdrp;
+ if (!_bfd_elf_init_file_header (abfd, link_info))
+ return FALSE;
+
i_ehdrp = elf_elfheader (abfd);
if (link_info)
{
BFD_ASSERT (htab != NULL);
}
- if (htab != NULL && htab->use_plts_and_copy_relocs && !htab->is_vxworks)
+ if (htab != NULL
+ && htab->use_plts_and_copy_relocs
+ && htab->root.target_os != is_vxworks)
i_ehdrp->e_ident[EI_ABIVERSION] = MIPS_LIBC_ABI_MIPS_PLT;
if (mips_elf_tdata (abfd)->abiflags.fp_abi == Val_GNU_MIPS_ABI_FP_64
if (htab != NULL && htab->use_absolute_zero && htab->gnu_target)
i_ehdrp->e_ident[EI_ABIVERSION] = MIPS_LIBC_ABI_ABSOLUTE;
- _bfd_elf_post_process_headers (abfd, link_info);
+ /* 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;
+ return TRUE;
}
int
{
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;
+}