/* ELF executable support for BFD.
- Copyright (C) 1993-2018 Free Software Foundation, Inc.
+ Copyright (C) 1993-2019 Free Software Foundation, Inc.
This file is part of BFD, the Binary File Descriptor library.
/* For sparc64-cross-sparc32. */
#define _SYSCALL32
#include "sysdep.h"
+#include <limits.h>
#include "bfd.h"
#include "bfdlink.h"
#include "libbfd.h"
/* Allocate and clear an extra byte at the end, to prevent crashes
in case the string table is not terminated. */
if (shstrtabsize + 1 <= 1
+ || shstrtabsize > bfd_get_file_size (abfd)
|| bfd_seek (abfd, offset, SEEK_SET) != 0
|| (shstrtab = (bfd_byte *) bfd_alloc (abfd, shstrtabsize + 1)) == NULL)
shstrtab = NULL;
if (bfd_elf_get_str_section (abfd, shindex) == NULL)
return NULL;
}
+ else
+ {
+ /* PR 24273: The string section's contents may have already
+ been loaded elsewhere, eg because a corrupt file has the
+ string section index in the ELF header pointing at a group
+ section. So be paranoid, and test that the last byte of
+ the section is zero. */
+ if (hdr->sh_size == 0 || hdr->contents[hdr->sh_size - 1] != 0)
+ return NULL;
+ }
if (strindex >= hdr->sh_size)
{
bfd_alloc2 (abfd, num_group, sizeof (Elf_Internal_Shdr *));
if (elf_tdata (abfd)->group_sect_ptr == NULL)
return FALSE;
- memset (elf_tdata (abfd)->group_sect_ptr, 0, num_group * sizeof (Elf_Internal_Shdr *));
+ memset (elf_tdata (abfd)->group_sect_ptr, 0,
+ num_group * sizeof (Elf_Internal_Shdr *));
num_group = 0;
for (i = 0; i < shnum; i++)
BFD_ASSERT (sizeof (*dest) >= 4);
amt = shdr->sh_size * sizeof (*dest) / 4;
shdr->contents = (unsigned char *)
- bfd_alloc2 (abfd, shdr->sh_size, sizeof (*dest) / 4);
+ bfd_alloc2 (abfd, shdr->sh_size, sizeof (*dest) / 4);
/* PR binutils/4110: Handle corrupt group headers. */
if (shdr->contents == NULL)
{
|= SEC_LINK_ONCE | SEC_LINK_DUPLICATES_DISCARD;
break;
}
- if (idx >= shnum)
+ if (idx < shnum)
+ {
+ dest->shdr = elf_elfsections (abfd)[idx];
+ /* PR binutils/23199: All sections in a
+ section group should be marked with
+ SHF_GROUP. But some tools generate
+ broken objects without SHF_GROUP. Fix
+ them up here. */
+ dest->shdr->sh_flags |= SHF_GROUP;
+ }
+ if (idx >= shnum
+ || dest->shdr->sh_type == SHT_GROUP)
{
_bfd_error_handler
- (_("%pB: invalid SHT_GROUP entry"), abfd);
- idx = 0;
+ (_("%pB: invalid entry in SHT_GROUP section [%u]"),
+ abfd, i);
+ dest->shdr = NULL;
}
- dest->shdr = elf_elfsections (abfd)[idx];
}
}
}
idx = (Elf_Internal_Group *) shdr->contents;
n_elt = shdr->sh_size / 4;
while (--n_elt != 0)
- if ((s = (++idx)->shdr->bfd_section) != NULL
+ if ((++idx)->shdr != NULL
+ && (s = idx->shdr->bfd_section) != NULL
&& elf_next_in_group (s) != NULL)
break;
if (n_elt != 0)
return new_name;
}
+/* This a copy of lto_section defined in GCC (lto-streamer.h). */
+
+struct lto_section
+{
+ int16_t major_version;
+ int16_t minor_version;
+ unsigned char slim_object;
+
+ /* Flags is a private field that is not defined publicly. */
+ uint16_t flags;
+};
+
/* Make a BFD section from an ELF section. We store a pointer to the
BFD section in the bfd_section field of the header. */
if ((hdr->sh_flags & SHF_EXCLUDE) != 0)
flags |= SEC_EXCLUDE;
+ switch (elf_elfheader (abfd)->e_ident[EI_OSABI])
+ {
+ /* FIXME: We should not recognize SHF_GNU_MBIND for ELFOSABI_NONE,
+ but binutils as of 2019-07-23 did not set the EI_OSABI header
+ byte. */
+ case ELFOSABI_NONE:
+ case ELFOSABI_GNU:
+ case ELFOSABI_FREEBSD:
+ if ((hdr->sh_flags & SHF_GNU_MBIND) != 0)
+ elf_tdata (abfd)->has_gnu_osabi |= elf_gnu_osabi_mbind;
+ break;
+ }
+
if ((flags & SEC_ALLOC) == 0)
{
/* The debugging sections appear to be recognized only by name,
enum { nothing, compress, decompress } action = nothing;
int compression_header_size;
bfd_size_type uncompressed_size;
+ unsigned int uncompressed_align_power;
bfd_boolean compressed
= bfd_is_section_compressed_with_header (abfd, newsect,
&compression_header_size,
- &uncompressed_size);
-
+ &uncompressed_size,
+ &uncompressed_align_power);
if (compressed)
{
/* Compressed section. Check if we should decompress. */
newsect->flags |= SEC_ELF_RENAME;
}
+ /* GCC uses .gnu.lto_.lto.<some_hash> as a LTO bytecode information
+ section. */
+ const char *lto_section_name = ".gnu.lto_.lto.";
+ if (strncmp (name, lto_section_name, strlen (lto_section_name)) == 0)
+ {
+ struct lto_section lsection;
+ if (bfd_get_section_contents (abfd, newsect, &lsection, 0,
+ sizeof (struct lto_section)))
+ abfd->lto_slim_object = lsection.slim_object;
+ }
+
return TRUE;
}
section_match (const Elf_Internal_Shdr * a,
const Elf_Internal_Shdr * b)
{
- return
- a->sh_type == b->sh_type
- && (a->sh_flags & ~ SHF_INFO_LINK)
- == (b->sh_flags & ~ SHF_INFO_LINK)
- && a->sh_addralign == b->sh_addralign
- && a->sh_size == b->sh_size
- && a->sh_entsize == b->sh_entsize
- /* FIXME: Check sh_addr ? */
- ;
+ if (a->sh_type != b->sh_type
+ || ((a->sh_flags ^ b->sh_flags) & ~SHF_INFO_LINK) != 0
+ || a->sh_addralign != b->sh_addralign
+ || a->sh_entsize != b->sh_entsize)
+ return FALSE;
+ if (a->sh_type == SHT_SYMTAB
+ || a->sh_type == SHT_STRTAB)
+ return TRUE;
+ return a->sh_size == b->sh_size;
}
/* Find a section in OBFD that has the same characteristics
if (vernum == 0)
version_string = "";
- else if (vernum == 1)
+ else if (vernum == 1
+ && (vernum > elf_tdata (abfd)->cverdefs
+ || (elf_tdata (abfd)->verdef[0].vd_flags
+ == VER_FLG_BASE)))
version_string = "Base";
else if (vernum <= elf_tdata (abfd)->cverdefs)
version_string =
{
Elf_Internal_Verneed *t;
- version_string = "";
+ version_string = _("<corrupt>");
for (t = elf_tdata (abfd)->verref;
t != NULL;
t = t->vn_nextref)
if (++ nesting > 3)
{
/* PR17512: A corrupt ELF binary might contain a recursive group of
- sections, with each the string indicies pointing to the next in the
+ sections, with each the string indices pointing to the next in the
loop. Detect this here, by refusing to load a section that we are
already in the process of loading. We only trigger this test if
we have nested at least three sections deep as normal ELF binaries
sections_being_created = NULL;
if (sections_being_created == NULL)
{
- /* FIXME: It would be more efficient to attach this array to the bfd somehow. */
sections_being_created = (bfd_boolean *)
- bfd_zalloc (abfd, elf_numsections (abfd) * sizeof (bfd_boolean));
+ bfd_zalloc2 (abfd, elf_numsections (abfd), sizeof (bfd_boolean));
sections_being_created_abfd = abfd;
}
if (sections_being_created [shindex])
if (entry->ndx == shindex)
goto success;
- entry = bfd_alloc (abfd, sizeof * entry);
+ entry = bfd_alloc (abfd, sizeof (*entry));
if (entry == NULL)
goto fail;
entry->ndx = shindex;
&& ! bfd_section_from_shdr (abfd, hdr->sh_link))
goto fail;
- /* If this reloc section does not use the main symbol table we
- don't treat it as a reloc section. BFD can't adequately
- represent such a section, so at least for now, we don't
- try. We just present it as a normal section. We also
- can't use it as a reloc section if it points to the null
- section, an invalid section, another reloc section, or its
- sh_link points to the null section. */
- if (hdr->sh_link != elf_onesymtab (abfd)
+ /* If this is an alloc section in an executable or shared
+ library, or the reloc section does not use the main symbol
+ table we don't treat it as a reloc section. BFD can't
+ adequately represent such a section, so at least for now,
+ we don't try. We just present it as a normal section. We
+ also can't use it as a reloc section if it points to the
+ null section, an invalid section, another reloc section, or
+ its sh_link points to the null section. */
+ if (((abfd->flags & (DYNAMIC | EXEC_P)) != 0
+ && (hdr->sh_flags & SHF_ALLOC) != 0)
|| hdr->sh_link == SHN_UNDEF
+ || hdr->sh_link != elf_onesymtab (abfd)
|| hdr->sh_info == SHN_UNDEF
|| hdr->sh_info >= num_sec
|| elf_elfsections (abfd)[hdr->sh_info]->sh_type == SHT_REL
int
bfd_elf_get_default_section_type (flagword flags)
{
- if ((flags & SEC_ALLOC) != 0
+ if ((flags & (SEC_ALLOC | SEC_IS_COMMON)) != 0
&& (flags & (SEC_LOAD | SEC_HAS_CONTENTS)) == 0)
return SHT_NOBITS;
return SHT_PROGBITS;
/* Ignore linker created group section. See elfNN_ia64_object_p in
elfxx-ia64.c. */
- if (((sec->flags & (SEC_GROUP | SEC_LINKER_CREATED)) != SEC_GROUP)
+ if ((sec->flags & (SEC_GROUP | SEC_LINKER_CREATED)) != SEC_GROUP
+ || sec->size == 0
|| *failedptr)
return;
_bfd_elf_strtab_addref (elf_shstrtab (abfd), t->symtab_hdr.sh_name);
if (section_number > ((SHN_LORESERVE - 2) & 0xFFFF))
{
- elf_section_list * entry;
+ elf_section_list *entry;
BFD_ASSERT (elf_symtab_shndx_list (abfd) == NULL);
- entry = bfd_zalloc (abfd, sizeof * entry);
+ entry = bfd_zalloc (abfd, sizeof (*entry));
entry->ndx = section_number++;
elf_symtab_shndx_list (abfd) = entry;
entry->hdr.sh_name
{
elf_symbol_type *type_ptr;
+ if (sym == NULL)
+ return FALSE;
+
if ((sym->flags & BSF_SECTION_SYM) == 0)
return FALSE;
+ if (sym->section == NULL)
+ return TRUE;
+
type_ptr = elf_symbol_from (abfd, sym);
return ((type_ptr != NULL
&& type_ptr->internal_elf_sym.st_shndx != 0
&& bfd_is_abs_section (sym->section))
|| !(sym->section->owner == abfd
- || (sym->section->output_section->owner == abfd
+ || (sym->section->output_section != NULL
+ && sym->section->output_section->owner == abfd
&& sym->section->output_offset == 0)
|| bfd_is_abs_section (sym->section)));
}
segs = 2;
s = bfd_get_section_by_name (abfd, ".interp");
- if (s != NULL && (s->flags & SEC_LOAD) != 0)
+ if (s != NULL && (s->flags & SEC_LOAD) != 0 && s->size != 0)
{
/* If we have a loadable interpreter section, we need a
PT_INTERP segment. In this case, assume we also need a
++segs;
}
+ s = bfd_get_section_by_name (abfd,
+ NOTE_GNU_PROPERTY_SECTION_NAME);
+ if (s != NULL && s->size != 0)
+ {
+ /* We need a PT_GNU_PROPERTY segment. */
+ ++segs;
+ }
+
for (s = abfd->sections; s != NULL; s = s->next)
{
if ((s->flags & SEC_LOAD) != 0
- && CONST_STRNEQ (s->name, ".note"))
+ && elf_section_type (s) == SHT_NOTE)
{
+ unsigned int alignment_power;
/* We need a PT_NOTE segment. */
++segs;
- /* Try to create just one PT_NOTE segment
- for all adjacent loadable .note* sections.
- gABI requires that within a PT_NOTE segment
- (and also inside of each SHT_NOTE section)
- each note is padded to a multiple of 4 size,
- so we check whether the sections are correctly
- aligned. */
- if (s->alignment_power == 2)
- while (s->next != NULL
- && s->next->alignment_power == 2
- && (s->next->flags & SEC_LOAD) != 0
- && CONST_STRNEQ (s->next->name, ".note"))
- s = s->next;
+ /* Try to create just one PT_NOTE segment for all adjacent
+ loadable SHT_NOTE sections. gABI requires that within a
+ PT_NOTE segment (and also inside of each SHT_NOTE section)
+ each note should have the same alignment. So we check
+ whether the sections are correctly aligned. */
+ alignment_power = s->alignment_power;
+ while (s->next != NULL
+ && s->next->alignment_power == alignment_power
+ && (s->next->flags & SEC_LOAD) != 0
+ && elf_section_type (s->next) == SHT_NOTE)
+ s = s->next;
}
}
bed = get_elf_backend_data (abfd);
- if ((abfd->flags & D_PAGED) != 0)
- {
- /* Add a PT_GNU_MBIND segment for each mbind section. */
- unsigned int page_align_power = bfd_log2 (bed->commonpagesize);
- for (s = abfd->sections; s != NULL; s = s->next)
- if (elf_section_flags (s) & SHF_GNU_MBIND)
- {
- if (elf_section_data (s)->this_hdr.sh_info
- > PT_GNU_MBIND_NUM)
- {
- _bfd_error_handler
- /* xgettext:c-format */
- (_("%pB: GNU_MBIN section `%pA' has invalid sh_info field: %d"),
- abfd, s, elf_section_data (s)->this_hdr.sh_info);
- continue;
- }
- /* Align mbind section to page size. */
- if (s->alignment_power < page_align_power)
- s->alignment_power = page_align_power;
- segs ++;
- }
- }
-
- /* Let the backend count up any program headers it might need. */
- if (bed->elf_backend_additional_program_headers)
+ if ((abfd->flags & D_PAGED) != 0
+ && (elf_tdata (abfd)->has_gnu_osabi & elf_gnu_osabi_mbind) != 0)
+ {
+ /* Add a PT_GNU_MBIND segment for each mbind section. */
+ unsigned int page_align_power = bfd_log2 (bed->commonpagesize);
+ for (s = abfd->sections; s != NULL; s = s->next)
+ if (elf_section_flags (s) & SHF_GNU_MBIND)
+ {
+ if (elf_section_data (s)->this_hdr.sh_info > PT_GNU_MBIND_NUM)
+ {
+ _bfd_error_handler
+ /* xgettext:c-format */
+ (_("%pB: GNU_MBIND section `%pA' has invalid "
+ "sh_info field: %d"),
+ abfd, s, elf_section_data (s)->this_hdr.sh_info);
+ continue;
+ }
+ /* Align mbind section to page size. */
+ if (s->alignment_power < page_align_power)
+ s->alignment_power = page_align_power;
+ segs ++;
+ }
+ }
+
+ /* Let the backend count up any program headers it might need. */
+ if (bed->elf_backend_additional_program_headers)
{
int a;
asection **hdrpp;
bfd_size_type amt;
- amt = sizeof (struct elf_segment_map);
- amt += (to - from - 1) * sizeof (asection *);
+ amt = sizeof (struct elf_segment_map) - sizeof (asection *);
+ amt += (to - from) * sizeof (asection *);
m = (struct elf_segment_map *) bfd_zalloc (abfd, amt);
if (m == NULL)
return NULL;
struct elf_segment_map **pm;
asection *last_hdr;
bfd_vma last_size;
- unsigned int phdr_index;
+ unsigned int hdr_index;
bfd_vma maxpagesize;
asection **hdrpp;
- bfd_boolean phdr_in_segment = TRUE;
+ bfd_boolean phdr_in_segment;
bfd_boolean writable;
bfd_boolean executable;
int tls_count = 0;
asection *dynsec, *eh_frame_hdr;
bfd_size_type amt;
bfd_vma addr_mask, wrap_to = 0;
- bfd_boolean linker_created_pt_phdr_segment = FALSE;
+ bfd_size_type phdr_size;
/* Select the allocated sections, and sort them. */
qsort (sections, (size_t) count, sizeof (asection *), elf_sort_sections);
- /* Build the mapping. */
+ phdr_size = elf_program_header_size (abfd);
+ if (phdr_size == (bfd_size_type) -1)
+ phdr_size = get_program_header_size (abfd, info);
+ phdr_size += bed->s->sizeof_ehdr;
+ maxpagesize = bed->maxpagesize;
+ if (maxpagesize == 0)
+ maxpagesize = 1;
+ phdr_in_segment = info != NULL && info->load_phdrs;
+ if (count != 0
+ && (((sections[0]->lma & addr_mask) & (maxpagesize - 1))
+ >= (phdr_size & (maxpagesize - 1))))
+ /* For compatibility with old scripts that may not be using
+ SIZEOF_HEADERS, add headers when it looks like space has
+ been left for them. */
+ phdr_in_segment = TRUE;
+ /* Build the mapping. */
mfirst = NULL;
pm = &mfirst;
the program headers and a PT_INTERP segment for the .interp
section. */
s = bfd_get_section_by_name (abfd, ".interp");
- if (s != NULL && (s->flags & SEC_LOAD) != 0)
+ if (s != NULL && (s->flags & SEC_LOAD) != 0 && s->size != 0)
{
amt = sizeof (struct elf_segment_map);
m = (struct elf_segment_map *) bfd_zalloc (abfd, amt);
m->p_flags = PF_R;
m->p_flags_valid = 1;
m->includes_phdrs = 1;
- linker_created_pt_phdr_segment = TRUE;
+ phdr_in_segment = TRUE;
*pm = m;
pm = &m->next;
a few bytes of the end of the first section. */
last_hdr = NULL;
last_size = 0;
- phdr_index = 0;
- maxpagesize = bed->maxpagesize;
- /* PR 17512: file: c8455299.
- Avoid divide-by-zero errors later on.
- FIXME: Should we abort if the maxpagesize is zero ? */
- if (maxpagesize == 0)
- maxpagesize = 1;
+ hdr_index = 0;
writable = FALSE;
executable = FALSE;
dynsec = bfd_get_section_by_name (abfd, ".dynamic");
&& (dynsec->flags & SEC_LOAD) == 0)
dynsec = NULL;
+ if ((abfd->flags & D_PAGED) == 0)
+ phdr_in_segment = FALSE;
+
/* Deal with -Ttext or something similar such that the first section
is not adjacent to the program headers. This is an
approximation, since at this point we don't know exactly how many
program headers we will need. */
- if (count > 0)
+ if (phdr_in_segment && count > 0)
{
- bfd_size_type phdr_size = elf_program_header_size (abfd);
+ bfd_vma phdr_lma;
+ bfd_boolean separate_phdr = FALSE;
- if (phdr_size == (bfd_size_type) -1)
- phdr_size = get_program_header_size (abfd, info);
- phdr_size += bed->s->sizeof_ehdr;
- if ((abfd->flags & D_PAGED) == 0
- || (sections[0]->lma & addr_mask) < phdr_size
- || ((sections[0]->lma & addr_mask) % maxpagesize
- < phdr_size % maxpagesize)
- || (sections[0]->lma & addr_mask & -maxpagesize) < wrap_to)
+ phdr_lma = (sections[0]->lma - phdr_size) & addr_mask & -maxpagesize;
+ if (info != NULL
+ && info->separate_code
+ && (sections[0]->flags & SEC_CODE) != 0)
{
- /* PR 20815: The ELF standard says that a PT_PHDR segment, if
- present, must be included as part of the memory image of the
- program. Ie it must be part of a PT_LOAD segment as well.
- If we have had to create our own PT_PHDR segment, but it is
- not going to be covered by the first PT_LOAD segment, then
- force the inclusion if we can... */
- if ((abfd->flags & D_PAGED) != 0
- && linker_created_pt_phdr_segment)
- phdr_in_segment = TRUE;
- else
- phdr_in_segment = FALSE;
+ /* If data sections should be separate from code and
+ thus not executable, and the first section is
+ executable then put the file and program headers in
+ their own PT_LOAD. */
+ separate_phdr = TRUE;
+ if ((((phdr_lma + phdr_size - 1) & addr_mask & -maxpagesize)
+ == (sections[0]->lma & addr_mask & -maxpagesize)))
+ {
+ /* The file and program headers are currently on the
+ same page as the first section. Put them on the
+ previous page if we can. */
+ if (phdr_lma >= maxpagesize)
+ phdr_lma -= maxpagesize;
+ else
+ separate_phdr = FALSE;
+ }
+ }
+ if ((sections[0]->lma & addr_mask) < phdr_lma
+ || (sections[0]->lma & addr_mask) < phdr_size)
+ /* If file and program headers would be placed at the end
+ of memory then it's probably better to omit them. */
+ phdr_in_segment = FALSE;
+ else if (phdr_lma < wrap_to)
+ /* If a section wraps around to where we'll be placing
+ file and program headers, then the headers will be
+ overwritten. */
+ phdr_in_segment = FALSE;
+ else if (separate_phdr)
+ {
+ m = make_mapping (abfd, sections, 0, 0, phdr_in_segment);
+ if (m == NULL)
+ goto error_return;
+ m->p_paddr = phdr_lma;
+ m->p_vaddr_offset
+ = (sections[0]->vma - phdr_size) & addr_mask & -maxpagesize;
+ m->p_paddr_valid = 1;
+ *pm = m;
+ pm = &m->next;
+ phdr_in_segment = FALSE;
}
}
}
/* We need a new program segment. We must create a new program
- header holding all the sections from phdr_index until hdr. */
+ header holding all the sections from hdr_index until hdr. */
- m = make_mapping (abfd, sections, phdr_index, i, phdr_in_segment);
+ m = make_mapping (abfd, sections, hdr_index, i, phdr_in_segment);
if (m == NULL)
goto error_return;
last_hdr = hdr;
/* .tbss sections effectively have zero size. */
last_size = !IS_TBSS (hdr) ? hdr->size : 0;
- phdr_index = i;
+ hdr_index = i;
phdr_in_segment = FALSE;
}
/* Create a final PT_LOAD program segment, but not if it's just
for .tbss. */
if (last_hdr != NULL
- && (i - phdr_index != 1
+ && (i - hdr_index != 1
|| !IS_TBSS (last_hdr)))
{
- m = make_mapping (abfd, sections, phdr_index, i, phdr_in_segment);
+ m = make_mapping (abfd, sections, hdr_index, i, phdr_in_segment);
if (m == NULL)
goto error_return;
pm = &m->next;
}
- /* For each batch of consecutive loadable .note sections,
+ /* For each batch of consecutive loadable SHT_NOTE sections,
add a PT_NOTE segment. We don't use bfd_get_section_by_name,
because if we link together nonloadable .note sections and
loadable .note sections, we will generate two .note sections
- in the output file. FIXME: Using names for section types is
- bogus anyhow. */
+ in the output file. */
for (s = abfd->sections; s != NULL; s = s->next)
{
if ((s->flags & SEC_LOAD) != 0
- && CONST_STRNEQ (s->name, ".note"))
+ && elf_section_type (s) == SHT_NOTE)
{
asection *s2;
+ unsigned int alignment_power = s->alignment_power;
count = 1;
- amt = sizeof (struct elf_segment_map);
- if (s->alignment_power == 2)
- for (s2 = s; s2->next != NULL; s2 = s2->next)
- {
- if (s2->next->alignment_power == 2
- && (s2->next->flags & SEC_LOAD) != 0
- && CONST_STRNEQ (s2->next->name, ".note")
- && align_power (s2->lma + s2->size, 2)
- == s2->next->lma)
- count++;
- else
- break;
- }
- amt += (count - 1) * sizeof (asection *);
+ for (s2 = s; s2->next != NULL; s2 = s2->next)
+ {
+ if (s2->next->alignment_power == alignment_power
+ && (s2->next->flags & SEC_LOAD) != 0
+ && elf_section_type (s2->next) == SHT_NOTE
+ && align_power (s2->lma + s2->size,
+ alignment_power)
+ == s2->next->lma)
+ count++;
+ else
+ break;
+ }
+ amt = sizeof (struct elf_segment_map) - sizeof (asection *);
+ amt += count * sizeof (asection *);
m = (struct elf_segment_map *) bfd_zalloc (abfd, amt);
if (m == NULL)
goto error_return;
/* If there are any SHF_TLS output sections, add PT_TLS segment. */
if (tls_count > 0)
{
- amt = sizeof (struct elf_segment_map);
- amt += (tls_count - 1) * sizeof (asection *);
+ amt = sizeof (struct elf_segment_map) - sizeof (asection *);
+ amt += tls_count * sizeof (asection *);
m = (struct elf_segment_map *) bfd_zalloc (abfd, amt);
if (m == NULL)
goto error_return;
pm = &m->next;
}
- if (first_mbind && (abfd->flags & D_PAGED) != 0)
+ if (first_mbind
+ && (abfd->flags & D_PAGED) != 0
+ && (elf_tdata (abfd)->has_gnu_osabi & elf_gnu_osabi_mbind) != 0)
for (s = first_mbind; s != NULL; s = s->next)
if ((elf_section_flags (s) & SHF_GNU_MBIND) != 0
- && (elf_section_data (s)->this_hdr.sh_info
- <= PT_GNU_MBIND_NUM))
+ && elf_section_data (s)->this_hdr.sh_info <= PT_GNU_MBIND_NUM)
{
/* Mandated PF_R. */
unsigned long p_flags = PF_R;
pm = &m->next;
}
+ s = bfd_get_section_by_name (abfd,
+ NOTE_GNU_PROPERTY_SECTION_NAME);
+ if (s != NULL && s->size != 0)
+ {
+ amt = sizeof (struct elf_segment_map) + sizeof (asection *);
+ m = bfd_zalloc (abfd, amt);
+ if (m == NULL)
+ goto error_return;
+ m->next = NULL;
+ m->p_type = PT_GNU_PROPERTY;
+ m->count = 1;
+ m->p_flags_valid = 1;
+ m->sections[0] = s;
+ m->p_flags = PF_R;
+ *pm = m;
+ pm = &m->next;
+ }
+
/* If there is a .eh_frame_hdr section, throw in a PT_GNU_EH_FRAME
segment. */
eh_frame_hdr = elf_eh_frame_hdr (abfd);
{
if (TOEND (sec2))
{
- /* If the indicies are the same, do not return 0
+ /* If the indices are the same, do not return 0
here, but continue to try the next comparison. */
if (sec1->target_index - sec2->target_index != 0)
return sec1->target_index - sec2->target_index;
p->p_flags = m->p_flags;
if (m->count == 0)
- p->p_vaddr = 0;
+ p->p_vaddr = m->p_vaddr_offset;
else
- p->p_vaddr = m->sections[0]->vma - m->p_vaddr_offset;
+ p->p_vaddr = m->sections[0]->vma + m->p_vaddr_offset;
if (m->p_paddr_valid)
p->p_paddr = m->p_paddr;
else if (m->count == 0)
p->p_paddr = 0;
else
- p->p_paddr = m->sections[0]->lma - m->p_vaddr_offset;
+ p->p_paddr = m->sections[0]->lma + m->p_vaddr_offset;
if (p->p_type == PT_LOAD
&& (abfd->flags & D_PAGED) != 0)
return TRUE;
}
+/* Determine if a bfd is a debuginfo file. Unfortunately there
+ is no defined method for detecting such files, so we have to
+ use heuristics instead. */
+
+bfd_boolean
+is_debuginfo_file (bfd *abfd)
+{
+ if (abfd == NULL || bfd_get_flavour (abfd) != bfd_target_elf_flavour)
+ return FALSE;
+
+ Elf_Internal_Shdr **start_headers = elf_elfsections (abfd);
+ Elf_Internal_Shdr **end_headers = start_headers + elf_numsections (abfd);
+ Elf_Internal_Shdr **headerp;
+
+ for (headerp = start_headers; headerp < end_headers; headerp ++)
+ {
+ Elf_Internal_Shdr *header = * headerp;
+
+ /* Debuginfo files do not have any allocated SHT_PROGBITS sections.
+ The only allocated sections are SHT_NOBITS or SHT_NOTES. */
+ if ((header->sh_flags & SHF_ALLOC) == SHF_ALLOC
+ && header->sh_type != SHT_NOBITS
+ && header->sh_type != SHT_NOTE)
+ return FALSE;
+ }
+
+ return TRUE;
+}
+
/* Assign file positions for the other sections. */
static bfd_boolean
BFD_ASSERT (hdr->sh_offset == hdr->bfd_section->filepos);
else if ((hdr->sh_flags & SHF_ALLOC) != 0)
{
- if (hdr->sh_size != 0)
+ if (hdr->sh_size != 0
+ /* PR 24717 - debuginfo files are known to be not strictly
+ compliant with the ELF standard. In particular they often
+ have .note.gnu.property sections that are outside of any
+ loadable segment. This is not a problem for such files,
+ so do not warn about them. */
+ && ! is_debuginfo_file (abfd))
_bfd_error_handler
/* xgettext:c-format */
(_("%pB: warning: allocated section `%s' not in segment"),
if (! abfd->output_has_begun
&& ! _bfd_elf_compute_section_file_positions (abfd, NULL))
return FALSE;
+ /* Do not rewrite ELF data when the BFD has been opened for update.
+ abfd->output_has_begun was set to TRUE on opening, so creation of new
+ sections, and modification of existing section sizes was restricted.
+ This means the ELF header, program headers and section headers can't have
+ changed.
+ If the contents of any sections has been modified, then those changes have
+ already been written to the BFD. */
+ else if (abfd->direction == both_direction)
+ {
+ BFD_ASSERT (abfd->output_has_begun);
+ return TRUE;
+ }
i_shdrp = elf_elfsections (abfd);
|| !_bfd_elf_strtab_emit (abfd, elf_shstrtab (abfd))))
return FALSE;
- if (bed->elf_backend_final_write_processing)
- (*bed->elf_backend_final_write_processing) (abfd, elf_linker (abfd));
+ if (!(*bed->elf_backend_final_write_processing) (abfd))
+ return FALSE;
if (!bed->s->write_shdrs_and_ehdr (abfd))
return FALSE;
the given segment. LMA addresses are compared. */
#define IS_CONTAINED_BY_LMA(section, segment, base) \
(section->lma >= base \
+ && (section->lma + SECTION_SIZE (section, segment) >= section->lma) \
&& (section->lma + SECTION_SIZE (section, segment) \
<= SEGMENT_END (segment, base)))
: segment->p_vaddr != section->vma) \
|| (strcmp (bfd_get_section_name (ibfd, section), ".dynamic") \
== 0)) \
- && !section->segment_mark)
+ && (segment->p_type != PT_LOAD || !section->segment_mark))
/* If the output section of a section in the input segment is NULL,
it is removed from the corresponding output segment. */
asection **sections;
asection *output_section;
unsigned int isec;
- bfd_vma matching_lma;
- bfd_vma suggested_lma;
+ asection *matching_lma;
+ asection *suggested_lma;
unsigned int j;
bfd_size_type amt;
asection *first_section;
- bfd_boolean first_matching_lma;
- bfd_boolean first_suggested_lma;
if (segment->p_type == PT_NULL)
continue;
/* Allocate a segment map big enough to contain
all of the sections we have selected. */
- amt = sizeof (struct elf_segment_map);
- amt += ((bfd_size_type) section_count - 1) * sizeof (asection *);
+ amt = sizeof (struct elf_segment_map) - sizeof (asection *);
+ amt += (bfd_size_type) section_count * sizeof (asection *);
map = (struct elf_segment_map *) bfd_zalloc (obfd, amt);
if (map == NULL)
return FALSE;
" at vaddr=%#" PRIx64 ", is this intentional?"),
ibfd, (uint64_t) segment->p_vaddr);
+ map->p_vaddr_offset = segment->p_vaddr;
map->count = 0;
*pointer_to_map = map;
pointer_to_map = &map->next;
we have completely filled the segment, and there is nothing
more to do. */
isec = 0;
- matching_lma = 0;
- suggested_lma = 0;
- first_matching_lma = TRUE;
- first_suggested_lma = TRUE;
+ matching_lma = NULL;
+ suggested_lma = NULL;
for (section = first_section, j = 0;
section != NULL;
&& !bed->want_p_paddr_set_to_zero
&& isec == 0
&& output_section->lma != 0
- && output_section->vma == (segment->p_vaddr
- + (map->includes_filehdr
- ? iehdr->e_ehsize
- : 0)
- + (map->includes_phdrs
- ? (iehdr->e_phnum
- * iehdr->e_phentsize)
- : 0)))
+ && (align_power (segment->p_vaddr
+ + (map->includes_filehdr
+ ? iehdr->e_ehsize : 0)
+ + (map->includes_phdrs
+ ? iehdr->e_phnum * iehdr->e_phentsize
+ : 0),
+ output_section->alignment_power)
+ == output_section->vma))
map->p_paddr = segment->p_vaddr;
/* Match up the physical address of the segment with the
|| (bed->want_p_paddr_set_to_zero
&& IS_CONTAINED_BY_VMA (output_section, segment)))
{
- if (first_matching_lma || output_section->lma < matching_lma)
- {
- matching_lma = output_section->lma;
- first_matching_lma = FALSE;
- }
+ if (matching_lma == NULL
+ || output_section->lma < matching_lma->lma)
+ matching_lma = output_section;
/* We assume that if the section fits within the segment
then it does not overlap any other section within that
segment. */
map->sections[isec++] = output_section;
}
- else if (first_suggested_lma)
- {
- suggested_lma = output_section->lma;
- first_suggested_lma = FALSE;
- }
+ else if (suggested_lma == NULL)
+ suggested_lma = output_section;
if (j == section_count)
break;
if (p_paddr_valid
&& !bed->want_p_paddr_set_to_zero
- && matching_lma != map->p_paddr
+ && matching_lma->lma != map->p_paddr
&& !map->includes_filehdr
&& !map->includes_phdrs)
/* There is some padding before the first section in the
segment. So, we must account for that in the output
segment's vma. */
- map->p_vaddr_offset = matching_lma - map->p_paddr;
+ map->p_vaddr_offset = map->p_paddr - matching_lma->lma;
free (sections);
continue;
}
else
{
- if (!first_matching_lma)
- {
- /* At least one section fits inside the current segment.
- Keep it, but modify its physical address to match the
- LMA of the first section that fitted. */
- map->p_paddr = matching_lma;
- }
- else
- {
- /* None of the sections fitted inside the current segment.
- Change the current segment's physical address to match
- the LMA of the first section. */
- map->p_paddr = suggested_lma;
- }
+ /* Change the current segment's physical address to match
+ the LMA of the first section that fitted, or if no
+ section fitted, the first section. */
+ if (matching_lma == NULL)
+ matching_lma = suggested_lma;
+
+ map->p_paddr = matching_lma->lma;
/* Offset the segment physical address from the lma
to allow for space taken up by elf headers. */
- if (map->includes_filehdr)
+ if (map->includes_phdrs)
{
- if (map->p_paddr >= iehdr->e_ehsize)
- map->p_paddr -= iehdr->e_ehsize;
- else
- {
- map->includes_filehdr = FALSE;
- map->includes_phdrs = FALSE;
- }
+ map->p_paddr -= iehdr->e_phnum * iehdr->e_phentsize;
+
+ /* iehdr->e_phnum is just an estimate of the number
+ of program headers that we will need. Make a note
+ here of the number we used and the segment we chose
+ to hold these headers, so that we can adjust the
+ offset when we know the correct value. */
+ phdr_adjust_num = iehdr->e_phnum;
+ phdr_adjust_seg = map;
}
- if (map->includes_phdrs)
+ if (map->includes_filehdr)
{
- if (map->p_paddr >= iehdr->e_phnum * iehdr->e_phentsize)
- {
- map->p_paddr -= iehdr->e_phnum * iehdr->e_phentsize;
-
- /* iehdr->e_phnum is just an estimate of the number
- of program headers that we will need. Make a note
- here of the number we used and the segment we chose
- to hold these headers, so that we can adjust the
- offset when we know the correct value. */
- phdr_adjust_num = iehdr->e_phnum;
- phdr_adjust_seg = map;
- }
- else
- map->includes_phdrs = FALSE;
+ bfd_vma align = (bfd_vma) 1 << matching_lma->alignment_power;
+ map->p_paddr -= iehdr->e_ehsize;
+ /* We've subtracted off the size of headers from the
+ first section lma, but there may have been some
+ alignment padding before that section too. Try to
+ account for that by adjusting the segment lma down to
+ the same alignment. */
+ if (segment->p_align != 0 && segment->p_align < align)
+ align = segment->p_align;
+ map->p_paddr &= -align;
}
}
do
{
map->count = 0;
- suggested_lma = 0;
- first_suggested_lma = TRUE;
+ suggested_lma = NULL;
/* Fill the current segment with sections that fit. */
for (j = 0; j < section_count; j++)
/* If the first section in a segment does not start at
the beginning of the segment, then something is
wrong. */
- if (output_section->lma
- != (map->p_paddr
- + (map->includes_filehdr ? iehdr->e_ehsize : 0)
- + (map->includes_phdrs
- ? iehdr->e_phnum * iehdr->e_phentsize
- : 0)))
+ if (align_power (map->p_paddr
+ + (map->includes_filehdr
+ ? iehdr->e_ehsize : 0)
+ + (map->includes_phdrs
+ ? iehdr->e_phnum * iehdr->e_phentsize
+ : 0),
+ output_section->alignment_power)
+ != output_section->lma)
abort ();
}
else
|| (prev_sec->lma + prev_sec->size
> output_section->lma))
{
- if (first_suggested_lma)
- {
- suggested_lma = output_section->lma;
- first_suggested_lma = FALSE;
- }
+ if (suggested_lma == NULL)
+ suggested_lma = output_section;
continue;
}
map->sections[map->count++] = output_section;
++isec;
sections[j] = NULL;
- section->segment_mark = TRUE;
- }
- else if (first_suggested_lma)
- {
- suggested_lma = output_section->lma;
- first_suggested_lma = FALSE;
+ if (segment->p_type == PT_LOAD)
+ section->segment_mark = TRUE;
}
+ else if (suggested_lma == NULL)
+ suggested_lma = output_section;
}
- BFD_ASSERT (map->count > 0);
+ /* PR 23932. A corrupt input file may contain sections that cannot
+ be assigned to any segment - because for example they have a
+ negative size - or segments that do not contain any sections. */
+ if (map->count == 0)
+ {
+ bfd_set_error (bfd_error_bad_value);
+ free (sections);
+ return FALSE;
+ }
/* Add the current segment to the list of built segments. */
*pointer_to_map = map;
/* We still have not allocated all of the sections to
segments. Create a new segment here, initialise it
and carry on looping. */
- amt = sizeof (struct elf_segment_map);
- amt += ((bfd_size_type) section_count - 1) * sizeof (asection *);
+ amt = sizeof (struct elf_segment_map) - sizeof (asection *);
+ amt += (bfd_size_type) section_count * sizeof (asection *);
map = (struct elf_segment_map *) bfd_zalloc (obfd, amt);
if (map == NULL)
{
map->p_type = segment->p_type;
map->p_flags = segment->p_flags;
map->p_flags_valid = 1;
- map->p_paddr = suggested_lma;
+ map->p_paddr = suggested_lma->lma;
map->p_paddr_valid = p_paddr_valid;
map->includes_filehdr = 0;
map->includes_phdrs = 0;
if (count > phdr_adjust_num)
phdr_adjust_seg->p_paddr
-= (count - phdr_adjust_num) * iehdr->e_phentsize;
+
+ for (map = map_first; map != NULL; map = map->next)
+ if (map->p_type == PT_PHDR)
+ {
+ bfd_vma adjust
+ = phdr_adjust_seg->includes_filehdr ? iehdr->e_ehsize : 0;
+ map->p_paddr = phdr_adjust_seg->p_paddr + adjust;
+ break;
+ }
}
#undef SEGMENT_END
Elf_Internal_Shdr *this_hdr;
asection *first_section = NULL;
asection *lowest_section;
+ bfd_boolean no_contents = TRUE;
/* Compute how many sections are in this segment. */
for (section = ibfd->sections, section_count = 0;
{
if (first_section == NULL)
first_section = section;
+ if (elf_section_type (section) != SHT_NOBITS)
+ no_contents = FALSE;
section_count++;
}
}
/* Allocate a segment map big enough to contain
all of the sections we have selected. */
- amt = sizeof (struct elf_segment_map);
- if (section_count != 0)
- amt += ((bfd_size_type) section_count - 1) * sizeof (asection *);
+ amt = sizeof (struct elf_segment_map) - sizeof (asection *);
+ amt += (bfd_size_type) section_count * sizeof (asection *);
map = (struct elf_segment_map *) bfd_zalloc (obfd, amt);
if (map == NULL)
return FALSE;
}
if (map->includes_filehdr && lowest_section != NULL)
- /* We need to keep the space used by the headers fixed. */
- map->header_size = lowest_section->vma - segment->p_vaddr;
+ {
+ /* Try to keep the space used by the headers plus any
+ padding fixed. If there are sections with file contents
+ in this segment then the lowest sh_offset is the best
+ guess. Otherwise the segment only has file contents for
+ the headers, and p_filesz is the best guess. */
+ if (no_contents)
+ map->header_size = segment->p_filesz;
+ else
+ map->header_size = lowest_section->filepos;
+ }
- if (!map->includes_phdrs
- && !map->includes_filehdr
- && map->p_paddr_valid)
- /* There is some other padding before the first section. */
- map->p_vaddr_offset = ((lowest_section ? lowest_section->lma : 0)
- - segment->p_paddr);
+ if (section_count == 0)
+ map->p_vaddr_offset = segment->p_vaddr;
+ else if (!map->includes_phdrs
+ && !map->includes_filehdr
+ && map->p_paddr_valid)
+ /* Account for padding before the first section. */
+ map->p_vaddr_offset = (segment->p_paddr
+ - (lowest_section ? lowest_section->lma : 0));
map->count = section_count;
*pointer_to_map = map;
& (SHF_MASKOS | SHF_MASKPROC));
/* Copy sh_info from input for mbind section. */
- if (elf_section_flags (isec) & SHF_GNU_MBIND)
+ if ((elf_tdata (ibfd)->has_gnu_osabi & elf_gnu_osabi_mbind) != 0
+ && elf_section_flags (isec) & SHF_GNU_MBIND)
elf_section_data (osec)->this_hdr.sh_info
= elf_section_data (isec)->this_hdr.sh_info;
symstrtab_hdr->sh_type = SHT_STRTAB;
/* Allocate buffer to swap out the .strtab section. */
- symstrtab = (struct elf_sym_strtab *) bfd_malloc ((symcount + 1)
- * sizeof (*symstrtab));
+ symstrtab = (struct elf_sym_strtab *) bfd_malloc2 (symcount + 1,
+ sizeof (*symstrtab));
if (symstrtab == NULL)
{
_bfd_elf_strtab_free (stt);
long
_bfd_elf_get_symtab_upper_bound (bfd *abfd)
{
- long symcount;
+ bfd_size_type symcount;
long symtab_size;
Elf_Internal_Shdr *hdr = &elf_tdata (abfd)->symtab_hdr;
symcount = hdr->sh_size / get_elf_backend_data (abfd)->s->sizeof_sym;
+ if (symcount >= LONG_MAX / sizeof (asymbol *))
+ {
+ bfd_set_error (bfd_error_file_too_big);
+ return -1;
+ }
symtab_size = (symcount + 1) * (sizeof (asymbol *));
if (symcount > 0)
symtab_size -= sizeof (asymbol *);
long
_bfd_elf_get_dynamic_symtab_upper_bound (bfd *abfd)
{
- long symcount;
+ bfd_size_type symcount;
long symtab_size;
Elf_Internal_Shdr *hdr = &elf_tdata (abfd)->dynsymtab_hdr;
}
symcount = hdr->sh_size / get_elf_backend_data (abfd)->s->sizeof_sym;
+ if (symcount >= LONG_MAX / sizeof (asymbol *))
+ {
+ bfd_set_error (bfd_error_file_too_big);
+ return -1;
+ }
symtab_size = (symcount + 1) * (sizeof (asymbol *));
if (symcount > 0)
symtab_size -= sizeof (asymbol *);
_bfd_elf_get_reloc_upper_bound (bfd *abfd ATTRIBUTE_UNUSED,
sec_ptr asect)
{
+#if SIZEOF_LONG == SIZEOF_INT
+ if (asect->reloc_count >= LONG_MAX / sizeof (arelent *))
+ {
+ bfd_set_error (bfd_error_file_too_big);
+ return -1;
+ }
+#endif
return (asect->reloc_count + 1) * sizeof (arelent *);
}
long
_bfd_elf_get_dynamic_reloc_upper_bound (bfd *abfd)
{
- long ret;
+ bfd_size_type count;
asection *s;
if (elf_dynsymtab (abfd) == 0)
return -1;
}
- ret = sizeof (arelent *);
+ count = 1;
for (s = abfd->sections; s != NULL; s = s->next)
if (elf_section_data (s)->this_hdr.sh_link == elf_dynsymtab (abfd)
&& (elf_section_data (s)->this_hdr.sh_type == SHT_REL
|| elf_section_data (s)->this_hdr.sh_type == SHT_RELA))
- ret += ((s->size / elf_section_data (s)->this_hdr.sh_entsize)
- * sizeof (arelent *));
-
- return ret;
+ {
+ count += s->size / elf_section_data (s)->this_hdr.sh_entsize;
+ if (count > LONG_MAX / sizeof (arelent *))
+ {
+ bfd_set_error (bfd_error_file_too_big);
+ return -1;
+ }
+ }
+ return count * sizeof (arelent *);
}
/* Canonicalize the dynamic relocation entries. Note that we return the
goto error_return;
}
+ ufile_ptr filesize = bfd_get_file_size (abfd);
+ if (filesize > 0 && filesize < hdr->sh_size)
+ {
+ /* PR 24708: Avoid attempts to allocate a ridiculous amount
+ of memory. */
+ bfd_set_error (bfd_error_no_memory);
+ _bfd_error_handler
+ /* xgettext:c-format */
+ (_("error: %pB version reference section is too large (%#" PRIx64 " bytes)"),
+ abfd, (uint64_t) hdr->sh_size);
+ goto error_return_verref;
+ }
contents = (bfd_byte *) bfd_malloc (hdr->sh_size);
if (contents == NULL)
goto error_return_verref;
{
elf_symbol_type *newsym;
- newsym = (elf_symbol_type *) bfd_zalloc (abfd, sizeof * newsym);
+ newsym = (elf_symbol_type *) bfd_zalloc (abfd, sizeof (*newsym));
if (!newsym)
return NULL;
newsym->symbol.the_bfd = abfd;
if (_bfd_dwarf2_find_nearest_line (abfd, symbols, NULL, section, offset,
filename_ptr, functionname_ptr,
line_ptr, discriminator_ptr,
- dwarf_debug_sections, 0,
+ dwarf_debug_sections,
&elf_tdata (abfd)->dwarf2_find_line_info)
|| _bfd_dwarf1_find_nearest_line (abfd, symbols, section, offset,
filename_ptr, functionname_ptr,
{
return _bfd_dwarf2_find_nearest_line (abfd, symbols, symbol, NULL, 0,
filename_ptr, NULL, line_ptr, NULL,
- dwarf_debug_sections, 0,
+ dwarf_debug_sections,
&elf_tdata (abfd)->dwarf2_find_line_info);
}
return elfcore_maybe_make_sect (abfd, name, sect);
}
+static bfd_boolean
+elfcore_make_auxv_note_section (bfd *abfd, Elf_Internal_Note *note,
+ size_t offs)
+{
+ asection *sect = bfd_make_section_anyway_with_flags (abfd, ".auxv",
+ SEC_HAS_CONTENTS);
+
+ if (sect == NULL)
+ return FALSE;
+
+ sect->size = note->descsz - offs;
+ sect->filepos = note->descpos + offs;
+ sect->alignment_power = 1 + bfd_get_arch_size (abfd) / 32;
+
+ return TRUE;
+}
+
/* prstatus_t exists on:
solaris 2.5+
linux 2.[01] + glibc
}
static bfd_boolean
+elfcore_grok_ppc_tar (bfd *abfd, Elf_Internal_Note *note)
+{
+ return elfcore_make_note_pseudosection (abfd, ".reg-ppc-tar", note);
+}
+
+static bfd_boolean
+elfcore_grok_ppc_ppr (bfd *abfd, Elf_Internal_Note *note)
+{
+ return elfcore_make_note_pseudosection (abfd, ".reg-ppc-ppr", note);
+}
+
+static bfd_boolean
+elfcore_grok_ppc_dscr (bfd *abfd, Elf_Internal_Note *note)
+{
+ return elfcore_make_note_pseudosection (abfd, ".reg-ppc-dscr", note);
+}
+
+static bfd_boolean
+elfcore_grok_ppc_ebb (bfd *abfd, Elf_Internal_Note *note)
+{
+ return elfcore_make_note_pseudosection (abfd, ".reg-ppc-ebb", note);
+}
+
+static bfd_boolean
+elfcore_grok_ppc_pmu (bfd *abfd, Elf_Internal_Note *note)
+{
+ return elfcore_make_note_pseudosection (abfd, ".reg-ppc-pmu", note);
+}
+
+static bfd_boolean
+elfcore_grok_ppc_tm_cgpr (bfd *abfd, Elf_Internal_Note *note)
+{
+ return elfcore_make_note_pseudosection (abfd, ".reg-ppc-tm-cgpr", note);
+}
+
+static bfd_boolean
+elfcore_grok_ppc_tm_cfpr (bfd *abfd, Elf_Internal_Note *note)
+{
+ return elfcore_make_note_pseudosection (abfd, ".reg-ppc-tm-cfpr", note);
+}
+
+static bfd_boolean
+elfcore_grok_ppc_tm_cvmx (bfd *abfd, Elf_Internal_Note *note)
+{
+ return elfcore_make_note_pseudosection (abfd, ".reg-ppc-tm-cvmx", note);
+}
+
+static bfd_boolean
+elfcore_grok_ppc_tm_cvsx (bfd *abfd, Elf_Internal_Note *note)
+{
+ return elfcore_make_note_pseudosection (abfd, ".reg-ppc-tm-cvsx", note);
+}
+
+static bfd_boolean
+elfcore_grok_ppc_tm_spr (bfd *abfd, Elf_Internal_Note *note)
+{
+ return elfcore_make_note_pseudosection (abfd, ".reg-ppc-tm-spr", note);
+}
+
+static bfd_boolean
+elfcore_grok_ppc_tm_ctar (bfd *abfd, Elf_Internal_Note *note)
+{
+ return elfcore_make_note_pseudosection (abfd, ".reg-ppc-tm-ctar", note);
+}
+
+static bfd_boolean
+elfcore_grok_ppc_tm_cppr (bfd *abfd, Elf_Internal_Note *note)
+{
+ return elfcore_make_note_pseudosection (abfd, ".reg-ppc-tm-cppr", note);
+}
+
+static bfd_boolean
+elfcore_grok_ppc_tm_cdscr (bfd *abfd, Elf_Internal_Note *note)
+{
+ return elfcore_make_note_pseudosection (abfd, ".reg-ppc-tm-cdscr", note);
+}
+
+static bfd_boolean
elfcore_grok_s390_high_gprs (bfd *abfd, Elf_Internal_Note *note)
{
return elfcore_make_note_pseudosection (abfd, ".reg-s390-high-gprs", note);
return elfcore_make_note_pseudosection (abfd, ".reg-aarch-hw-watch", note);
}
+static bfd_boolean
+elfcore_grok_aarch_sve (bfd *abfd, Elf_Internal_Note *note)
+{
+ return elfcore_make_note_pseudosection (abfd, ".reg-aarch-sve", note);
+}
+
+static bfd_boolean
+elfcore_grok_aarch_pauth (bfd *abfd, Elf_Internal_Note *note)
+{
+ return elfcore_make_note_pseudosection (abfd, ".reg-aarch-pauth", note);
+}
+
#if defined (HAVE_PRPSINFO_T)
typedef prpsinfo_t elfcore_psinfo_t;
#if defined (HAVE_PRPSINFO32_T) /* Sparc64 cross Sparc32 */
else
return TRUE;
+ case NT_PPC_TAR:
+ if (note->namesz == 6
+ && strcmp (note->namedata, "LINUX") == 0)
+ return elfcore_grok_ppc_tar (abfd, note);
+ else
+ return TRUE;
+
+ case NT_PPC_PPR:
+ if (note->namesz == 6
+ && strcmp (note->namedata, "LINUX") == 0)
+ return elfcore_grok_ppc_ppr (abfd, note);
+ else
+ return TRUE;
+
+ case NT_PPC_DSCR:
+ if (note->namesz == 6
+ && strcmp (note->namedata, "LINUX") == 0)
+ return elfcore_grok_ppc_dscr (abfd, note);
+ else
+ return TRUE;
+
+ case NT_PPC_EBB:
+ if (note->namesz == 6
+ && strcmp (note->namedata, "LINUX") == 0)
+ return elfcore_grok_ppc_ebb (abfd, note);
+ else
+ return TRUE;
+
+ case NT_PPC_PMU:
+ if (note->namesz == 6
+ && strcmp (note->namedata, "LINUX") == 0)
+ return elfcore_grok_ppc_pmu (abfd, note);
+ else
+ return TRUE;
+
+ case NT_PPC_TM_CGPR:
+ if (note->namesz == 6
+ && strcmp (note->namedata, "LINUX") == 0)
+ return elfcore_grok_ppc_tm_cgpr (abfd, note);
+ else
+ return TRUE;
+
+ case NT_PPC_TM_CFPR:
+ if (note->namesz == 6
+ && strcmp (note->namedata, "LINUX") == 0)
+ return elfcore_grok_ppc_tm_cfpr (abfd, note);
+ else
+ return TRUE;
+
+ case NT_PPC_TM_CVMX:
+ if (note->namesz == 6
+ && strcmp (note->namedata, "LINUX") == 0)
+ return elfcore_grok_ppc_tm_cvmx (abfd, note);
+ else
+ return TRUE;
+
+ case NT_PPC_TM_CVSX:
+ if (note->namesz == 6
+ && strcmp (note->namedata, "LINUX") == 0)
+ return elfcore_grok_ppc_tm_cvsx (abfd, note);
+ else
+ return TRUE;
+
+ case NT_PPC_TM_SPR:
+ if (note->namesz == 6
+ && strcmp (note->namedata, "LINUX") == 0)
+ return elfcore_grok_ppc_tm_spr (abfd, note);
+ else
+ return TRUE;
+
+ case NT_PPC_TM_CTAR:
+ if (note->namesz == 6
+ && strcmp (note->namedata, "LINUX") == 0)
+ return elfcore_grok_ppc_tm_ctar (abfd, note);
+ else
+ return TRUE;
+
+ case NT_PPC_TM_CPPR:
+ if (note->namesz == 6
+ && strcmp (note->namedata, "LINUX") == 0)
+ return elfcore_grok_ppc_tm_cppr (abfd, note);
+ else
+ return TRUE;
+
+ case NT_PPC_TM_CDSCR:
+ if (note->namesz == 6
+ && strcmp (note->namedata, "LINUX") == 0)
+ return elfcore_grok_ppc_tm_cdscr (abfd, note);
+ else
+ return TRUE;
+
case NT_S390_HIGH_GPRS:
if (note->namesz == 6
&& strcmp (note->namedata, "LINUX") == 0)
else
return TRUE;
+ case NT_ARM_SVE:
+ if (note->namesz == 6
+ && strcmp (note->namedata, "LINUX") == 0)
+ return elfcore_grok_aarch_sve (abfd, note);
+ else
+ return TRUE;
+
+ case NT_ARM_PAC_MASK:
+ if (note->namesz == 6
+ && strcmp (note->namedata, "LINUX") == 0)
+ return elfcore_grok_aarch_pauth (abfd, note);
+ else
+ return TRUE;
+
case NT_PRPSINFO:
case NT_PSINFO:
if (bed->elf_backend_grok_psinfo)
#endif
case NT_AUXV:
- {
- asection *sect = bfd_make_section_anyway_with_flags (abfd, ".auxv",
- SEC_HAS_CONTENTS);
-
- if (sect == NULL)
- return FALSE;
- sect->size = note->descsz;
- sect->filepos = note->descpos;
- sect->alignment_power = 1 + bfd_get_arch_size (abfd) / 32;
-
- return TRUE;
- }
+ return elfcore_make_auxv_note_section (abfd, note, 0);
case NT_FILE:
return elfcore_make_note_pseudosection (abfd, ".note.linuxcore.file",
elfobj_grok_stapsdt_note_1 (bfd *abfd, Elf_Internal_Note *note)
{
struct sdt_note *cur =
- (struct sdt_note *) bfd_alloc (abfd, sizeof (struct sdt_note)
- + note->descsz);
+ (struct sdt_note *) bfd_alloc (abfd,
+ sizeof (struct sdt_note) + note->descsz);
cur->next = (struct sdt_note *) (elf_tdata (abfd))->sdt_note_head;
cur->size = (bfd_size_type) note->descsz;
note);
case NT_FREEBSD_PROCSTAT_AUXV:
- {
- asection *sect = bfd_make_section_anyway_with_flags (abfd, ".auxv",
- SEC_HAS_CONTENTS);
-
- if (sect == NULL)
- return FALSE;
- sect->size = note->descsz - 4;
- sect->filepos = note->descpos + 4;
- sect->alignment_power = 1 + bfd_get_arch_size (abfd) / 32;
-
- return TRUE;
- }
+ return elfcore_make_auxv_note_section (abfd, note, 4);
case NT_X86_XSTATE:
if (note->namesz == 8)
if (elfcore_netbsd_get_lwpid (note, &lwp))
elf_tdata (abfd)->core->lwpid = lwp;
- if (note->type == NT_NETBSDCORE_PROCINFO)
+ switch (note->type)
{
+ case NT_NETBSDCORE_PROCINFO:
/* NetBSD-specific core "procinfo". Note that we expect to
find this note before any of the others, which is fine,
since the kernel writes this note out first when it
creates a core file. */
-
return elfcore_grok_netbsd_procinfo (abfd, note);
+#ifdef NT_NETBSDCORE_AUXV
+ case NT_NETBSDCORE_AUXV:
+ /* NetBSD-specific Elf Auxiliary Vector data. */
+ return elfcore_make_auxv_note_section (abfd, note, 4);
+#endif
+ default:
+ break;
}
- /* As of Jan 2002 there are no other machine-independent notes
+ /* As of March 2017 there are no other machine-independent notes
defined for NetBSD core files. If the note type is less
than the start of the machine-dependent note types, we don't
understand it. */
return TRUE;
}
+ /* On SuperH, PT_GETREGS == mach+3 and PT_GETFPREGS == mach+5.
+ There's also old PT___GETREGS40 == mach + 1 for old reg
+ structure which lacks GBR. */
+
+ case bfd_arch_sh:
+ switch (note->type)
+ {
+ case NT_NETBSDCORE_FIRSTMACH+3:
+ return elfcore_make_note_pseudosection (abfd, ".reg", note);
+
+ case NT_NETBSDCORE_FIRSTMACH+5:
+ return elfcore_make_note_pseudosection (abfd, ".reg2", note);
+
+ default:
+ return TRUE;
+ }
+
/* On all other arch's, PT_GETREGS == mach+1 and
PT_GETFPREGS == mach+3. */
return elfcore_make_note_pseudosection (abfd, ".reg-xfp", note);
if (note->type == NT_OPENBSD_AUXV)
- {
- asection *sect = bfd_make_section_anyway_with_flags (abfd, ".auxv",
- SEC_HAS_CONTENTS);
-
- if (sect == NULL)
- return FALSE;
- sect->size = note->descsz;
- sect->filepos = note->descpos;
- sect->alignment_power = 1 + bfd_get_arch_size (abfd) / 32;
-
- return TRUE;
- }
+ return elfcore_make_auxv_note_section (abfd, note, 0);
if (note->type == NT_OPENBSD_WCOOKIE)
{
return buf;
}
+/* gcc-8 warns (*) on all the strncpy calls in this function about
+ possible string truncation. The "truncation" is not a bug. We
+ have an external representation of structs with fields that are not
+ necessarily NULL terminated and corresponding internal
+ representation fields that are one larger so that they can always
+ be NULL terminated.
+ gcc versions between 4.2 and 4.6 do not allow pragma control of
+ diagnostics inside functions, giving a hard error if you try to use
+ the finer control available with later versions.
+ gcc prior to 4.2 warns about diagnostic push and pop.
+ gcc-5, gcc-6 and gcc-7 warn that -Wstringop-truncation is unknown,
+ unless you also add #pragma GCC diagnostic ignored "-Wpragma".
+ (*) Depending on your system header files! */
+#if GCC_VERSION >= 8000
+# pragma GCC diagnostic push
+# pragma GCC diagnostic ignored "-Wstringop-truncation"
+#endif
char *
elfcore_write_prpsinfo (bfd *abfd,
char *buf,
}
#if defined (HAVE_PRPSINFO_T) || defined (HAVE_PSINFO_T)
-#if defined (HAVE_PRPSINFO32_T) || defined (HAVE_PSINFO32_T)
+# if defined (HAVE_PRPSINFO32_T) || defined (HAVE_PSINFO32_T)
if (bed->s->elfclass == ELFCLASS32)
{
-#if defined (HAVE_PSINFO32_T)
+# if defined (HAVE_PSINFO32_T)
psinfo32_t data;
int note_type = NT_PSINFO;
-#else
+# else
prpsinfo32_t data;
int note_type = NT_PRPSINFO;
-#endif
+# endif
memset (&data, 0, sizeof (data));
strncpy (data.pr_fname, fname, sizeof (data.pr_fname));
"CORE", note_type, &data, sizeof (data));
}
else
-#endif
+# endif
{
-#if defined (HAVE_PSINFO_T)
+# if defined (HAVE_PSINFO_T)
psinfo_t data;
int note_type = NT_PSINFO;
-#else
+# else
prpsinfo_t data;
int note_type = NT_PRPSINFO;
-#endif
+# endif
memset (&data, 0, sizeof (data));
strncpy (data.pr_fname, fname, sizeof (data.pr_fname));
free (buf);
return NULL;
}
+#if GCC_VERSION >= 8000
+# pragma GCC diagnostic pop
+#endif
char *
elfcore_write_linux_prpsinfo32
note_name, NT_PPC_VSX, ppc_vsx, size);
}
+char *
+elfcore_write_ppc_tar (bfd *abfd,
+ char *buf,
+ int *bufsiz,
+ const void *ppc_tar,
+ int size)
+{
+ char *note_name = "LINUX";
+ return elfcore_write_note (abfd, buf, bufsiz,
+ note_name, NT_PPC_TAR, ppc_tar, size);
+}
+
+char *
+elfcore_write_ppc_ppr (bfd *abfd,
+ char *buf,
+ int *bufsiz,
+ const void *ppc_ppr,
+ int size)
+{
+ char *note_name = "LINUX";
+ return elfcore_write_note (abfd, buf, bufsiz,
+ note_name, NT_PPC_PPR, ppc_ppr, size);
+}
+
+char *
+elfcore_write_ppc_dscr (bfd *abfd,
+ char *buf,
+ int *bufsiz,
+ const void *ppc_dscr,
+ int size)
+{
+ char *note_name = "LINUX";
+ return elfcore_write_note (abfd, buf, bufsiz,
+ note_name, NT_PPC_DSCR, ppc_dscr, size);
+}
+
+char *
+elfcore_write_ppc_ebb (bfd *abfd,
+ char *buf,
+ int *bufsiz,
+ const void *ppc_ebb,
+ int size)
+{
+ char *note_name = "LINUX";
+ return elfcore_write_note (abfd, buf, bufsiz,
+ note_name, NT_PPC_EBB, ppc_ebb, size);
+}
+
+char *
+elfcore_write_ppc_pmu (bfd *abfd,
+ char *buf,
+ int *bufsiz,
+ const void *ppc_pmu,
+ int size)
+{
+ char *note_name = "LINUX";
+ return elfcore_write_note (abfd, buf, bufsiz,
+ note_name, NT_PPC_PMU, ppc_pmu, size);
+}
+
+char *
+elfcore_write_ppc_tm_cgpr (bfd *abfd,
+ char *buf,
+ int *bufsiz,
+ const void *ppc_tm_cgpr,
+ int size)
+{
+ char *note_name = "LINUX";
+ return elfcore_write_note (abfd, buf, bufsiz,
+ note_name, NT_PPC_TM_CGPR, ppc_tm_cgpr, size);
+}
+
+char *
+elfcore_write_ppc_tm_cfpr (bfd *abfd,
+ char *buf,
+ int *bufsiz,
+ const void *ppc_tm_cfpr,
+ int size)
+{
+ char *note_name = "LINUX";
+ return elfcore_write_note (abfd, buf, bufsiz,
+ note_name, NT_PPC_TM_CFPR, ppc_tm_cfpr, size);
+}
+
+char *
+elfcore_write_ppc_tm_cvmx (bfd *abfd,
+ char *buf,
+ int *bufsiz,
+ const void *ppc_tm_cvmx,
+ int size)
+{
+ char *note_name = "LINUX";
+ return elfcore_write_note (abfd, buf, bufsiz,
+ note_name, NT_PPC_TM_CVMX, ppc_tm_cvmx, size);
+}
+
+char *
+elfcore_write_ppc_tm_cvsx (bfd *abfd,
+ char *buf,
+ int *bufsiz,
+ const void *ppc_tm_cvsx,
+ int size)
+{
+ char *note_name = "LINUX";
+ return elfcore_write_note (abfd, buf, bufsiz,
+ note_name, NT_PPC_TM_CVSX, ppc_tm_cvsx, size);
+}
+
+char *
+elfcore_write_ppc_tm_spr (bfd *abfd,
+ char *buf,
+ int *bufsiz,
+ const void *ppc_tm_spr,
+ int size)
+{
+ char *note_name = "LINUX";
+ return elfcore_write_note (abfd, buf, bufsiz,
+ note_name, NT_PPC_TM_SPR, ppc_tm_spr, size);
+}
+
+char *
+elfcore_write_ppc_tm_ctar (bfd *abfd,
+ char *buf,
+ int *bufsiz,
+ const void *ppc_tm_ctar,
+ int size)
+{
+ char *note_name = "LINUX";
+ return elfcore_write_note (abfd, buf, bufsiz,
+ note_name, NT_PPC_TM_CTAR, ppc_tm_ctar, size);
+}
+
+char *
+elfcore_write_ppc_tm_cppr (bfd *abfd,
+ char *buf,
+ int *bufsiz,
+ const void *ppc_tm_cppr,
+ int size)
+{
+ char *note_name = "LINUX";
+ return elfcore_write_note (abfd, buf, bufsiz,
+ note_name, NT_PPC_TM_CPPR, ppc_tm_cppr, size);
+}
+
+char *
+elfcore_write_ppc_tm_cdscr (bfd *abfd,
+ char *buf,
+ int *bufsiz,
+ const void *ppc_tm_cdscr,
+ int size)
+{
+ char *note_name = "LINUX";
+ return elfcore_write_note (abfd, buf, bufsiz,
+ note_name, NT_PPC_TM_CDSCR, ppc_tm_cdscr, size);
+}
+
static char *
elfcore_write_s390_high_gprs (bfd *abfd,
char *buf,
}
char *
+elfcore_write_aarch_sve (bfd *abfd,
+ char *buf,
+ int *bufsiz,
+ const void *aarch_sve,
+ int size)
+{
+ char *note_name = "LINUX";
+ return elfcore_write_note (abfd, buf, bufsiz,
+ note_name, NT_ARM_SVE, aarch_sve, size);
+}
+
+char *
+elfcore_write_aarch_pauth (bfd *abfd,
+ char *buf,
+ int *bufsiz,
+ const void *aarch_pauth,
+ int size)
+{
+ char *note_name = "LINUX";
+ return elfcore_write_note (abfd, buf, bufsiz,
+ note_name, NT_ARM_PAC_MASK, aarch_pauth, size);
+}
+
+char *
elfcore_write_register_note (bfd *abfd,
char *buf,
int *bufsiz,
return elfcore_write_ppc_vmx (abfd, buf, bufsiz, data, size);
if (strcmp (section, ".reg-ppc-vsx") == 0)
return elfcore_write_ppc_vsx (abfd, buf, bufsiz, data, size);
+ if (strcmp (section, ".reg-ppc-tar") == 0)
+ return elfcore_write_ppc_tar (abfd, buf, bufsiz, data, size);
+ if (strcmp (section, ".reg-ppc-ppr") == 0)
+ return elfcore_write_ppc_ppr (abfd, buf, bufsiz, data, size);
+ if (strcmp (section, ".reg-ppc-dscr") == 0)
+ return elfcore_write_ppc_dscr (abfd, buf, bufsiz, data, size);
+ if (strcmp (section, ".reg-ppc-ebb") == 0)
+ return elfcore_write_ppc_ebb (abfd, buf, bufsiz, data, size);
+ if (strcmp (section, ".reg-ppc-pmu") == 0)
+ return elfcore_write_ppc_pmu (abfd, buf, bufsiz, data, size);
+ if (strcmp (section, ".reg-ppc-tm-cgpr") == 0)
+ return elfcore_write_ppc_tm_cgpr (abfd, buf, bufsiz, data, size);
+ if (strcmp (section, ".reg-ppc-tm-cfpr") == 0)
+ return elfcore_write_ppc_tm_cfpr (abfd, buf, bufsiz, data, size);
+ if (strcmp (section, ".reg-ppc-tm-cvmx") == 0)
+ return elfcore_write_ppc_tm_cvmx (abfd, buf, bufsiz, data, size);
+ if (strcmp (section, ".reg-ppc-tm-cvsx") == 0)
+ return elfcore_write_ppc_tm_cvsx (abfd, buf, bufsiz, data, size);
+ if (strcmp (section, ".reg-ppc-tm-spr") == 0)
+ return elfcore_write_ppc_tm_spr (abfd, buf, bufsiz, data, size);
+ if (strcmp (section, ".reg-ppc-tm-ctar") == 0)
+ return elfcore_write_ppc_tm_ctar (abfd, buf, bufsiz, data, size);
+ if (strcmp (section, ".reg-ppc-tm-cppr") == 0)
+ return elfcore_write_ppc_tm_cppr (abfd, buf, bufsiz, data, size);
+ if (strcmp (section, ".reg-ppc-tm-cdscr") == 0)
+ return elfcore_write_ppc_tm_cdscr (abfd, buf, bufsiz, data, size);
if (strcmp (section, ".reg-s390-high-gprs") == 0)
return elfcore_write_s390_high_gprs (abfd, buf, bufsiz, data, size);
if (strcmp (section, ".reg-s390-timer") == 0)
return elfcore_write_aarch_hw_break (abfd, buf, bufsiz, data, size);
if (strcmp (section, ".reg-aarch-hw-watch") == 0)
return elfcore_write_aarch_hw_watch (abfd, buf, bufsiz, data, size);
+ if (strcmp (section, ".reg-aarch-sve") == 0)
+ return elfcore_write_aarch_sve (abfd, buf, bufsiz, data, size);
+ if (strcmp (section, ".reg-aarch-pauth") == 0)
+ return elfcore_write_aarch_pauth (abfd, buf, bufsiz, data, size);
return NULL;
}
}
num_phdrs = elf_elfheader (abfd)->e_phnum;
- memcpy (phdrs, elf_tdata (abfd)->phdr,
- num_phdrs * sizeof (Elf_Internal_Phdr));
+ if (num_phdrs != 0)
+ memcpy (phdrs, elf_tdata (abfd)->phdr,
+ num_phdrs * sizeof (Elf_Internal_Phdr));
return num_phdrs;
}
"LARGE_COMMON", 0, SEC_IS_COMMON);
void
-_bfd_elf_post_process_headers (bfd * abfd,
- struct bfd_link_info * link_info ATTRIBUTE_UNUSED)
+_bfd_elf_post_process_headers (bfd *abfd ATTRIBUTE_UNUSED,
+ struct bfd_link_info *info ATTRIBUTE_UNUSED)
{
- Elf_Internal_Ehdr * i_ehdrp; /* ELF file header, internal form. */
+}
- i_ehdrp = elf_elfheader (abfd);
+bfd_boolean
+_bfd_elf_final_write_processing (bfd *abfd)
+{
+ Elf_Internal_Ehdr *i_ehdrp; /* ELF file header, internal form. */
- i_ehdrp->e_ident[EI_OSABI] = get_elf_backend_data (abfd)->elf_osabi;
+ i_ehdrp = elf_elfheader (abfd);
- /* To make things simpler for the loader on Linux systems we set the
- osabi field to ELFOSABI_GNU if the binary contains symbols of
- the STT_GNU_IFUNC type or STB_GNU_UNIQUE binding. */
- if (i_ehdrp->e_ident[EI_OSABI] == ELFOSABI_NONE
- && elf_tdata (abfd)->has_gnu_symbols)
- i_ehdrp->e_ident[EI_OSABI] = ELFOSABI_GNU;
+ if (i_ehdrp->e_ident[EI_OSABI] == ELFOSABI_NONE)
+ i_ehdrp->e_ident[EI_OSABI] = get_elf_backend_data (abfd)->elf_osabi;
+
+ /* Set the osabi field to ELFOSABI_GNU if the binary contains
+ SHF_GNU_MBIND sections or symbols of STT_GNU_IFUNC type or
+ STB_GNU_UNIQUE binding. */
+ if (elf_tdata (abfd)->has_gnu_osabi != 0)
+ {
+ if (i_ehdrp->e_ident[EI_OSABI] == ELFOSABI_NONE)
+ i_ehdrp->e_ident[EI_OSABI] = ELFOSABI_GNU;
+ else if (i_ehdrp->e_ident[EI_OSABI] != ELFOSABI_GNU
+ && i_ehdrp->e_ident[EI_OSABI] != ELFOSABI_FREEBSD)
+ {
+ if (elf_tdata (abfd)->has_gnu_osabi & elf_gnu_osabi_mbind)
+ _bfd_error_handler (_("GNU_MBIND section is unsupported"));
+ if (elf_tdata (abfd)->has_gnu_osabi & elf_gnu_osabi_ifunc)
+ _bfd_error_handler (_("symbol type STT_GNU_IFUNC is unsupported"));
+ if (elf_tdata (abfd)->has_gnu_osabi & elf_gnu_osabi_unique)
+ _bfd_error_handler (_("symbol binding STB_GNU_UNIQUE is unsupported"));
+ bfd_set_error (bfd_error_bad_value);
+ return FALSE;
+ }
+ }
+ return TRUE;
}