/* 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"
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;
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;
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;
}
/* 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))
{
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,
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)
{
_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)
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;
}
/* 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))
/* 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;
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;
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))
+ && !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;
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;
}
/* 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
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,
{
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)
".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
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)
{
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 TRUE;
}
int