/* ELF executable support for BFD.
- Copyright (C) 1993-2016 Free Software Foundation, Inc.
+ Copyright (C) 1993-2017 Free Software Foundation, Inc.
This file is part of BFD, the Binary File Descriptor library.
if (hdr->sh_type != SHT_STRTAB && hdr->sh_type < SHT_LOOS)
{
/* PR 17512: file: f057ec89. */
- _bfd_error_handler (_("%B: attempt to load strings from a non-string section (number %d)"),
+ /* xgettext:c-format */
+ _bfd_error_handler (_("%B: attempt to load strings from"
+ " a non-string section (number %d)"),
abfd, shindex);
return NULL;
}
if (strindex >= hdr->sh_size)
{
unsigned int shstrndx = elf_elfheader(abfd)->e_shstrndx;
- (*_bfd_error_handler)
+ _bfd_error_handler
+ /* xgettext:c-format */
(_("%B: invalid string offset %u >= %lu for section `%s'"),
abfd, strindex, (unsigned long) hdr->sh_size,
(shindex == shstrndx && strindex == hdr->sh_name
if (!(*bed->s->swap_symbol_in) (ibfd, esym, shndx, isym))
{
symoffset += (esym - (bfd_byte *) extsym_buf) / extsym_size;
- (*_bfd_error_handler) (_("%B symbol number %lu references "
- "nonexistent SHT_SYMTAB_SHNDX section"),
- ibfd, (unsigned long) symoffset);
+ /* xgettext:c-format */
+ _bfd_error_handler (_("%B symbol number %lu references"
+ " nonexistent SHT_SYMTAB_SHNDX section"),
+ ibfd, (unsigned long) symoffset);
if (alloc_intsym != NULL)
free (alloc_intsym);
intsym_buf = NULL;
if (shdr->contents == NULL)
{
_bfd_error_handler
- (_("%B: corrupt size field in group section header: 0x%lx"), abfd, shdr->sh_size);
+ /* xgettext:c-format */
+ (_("%B: corrupt size field in group section"
+ " header: 0x%lx"), abfd, shdr->sh_size);
bfd_set_error (bfd_error_bad_value);
-- num_group;
continue;
!= shdr->sh_size))
{
_bfd_error_handler
- (_("%B: invalid size field in group section header: 0x%lx"), abfd, shdr->sh_size);
+ /* xgettext:c-format */
+ (_("%B: invalid size field in group section"
+ " header: 0x%lx"), abfd, shdr->sh_size);
bfd_set_error (bfd_error_bad_value);
-- num_group;
- /* PR 17510: If the group contents are even partially
- corrupt, do not allow any of the contents to be used. */
+ /* PR 17510: If the group contents are even
+ partially corrupt, do not allow any of the
+ contents to be used. */
memset (shdr->contents, 0, amt);
continue;
}
}
if (idx >= shnum)
{
- ((*_bfd_error_handler)
- (_("%B: invalid SHT_GROUP entry"), abfd));
+ _bfd_error_handler
+ (_("%B: invalid SHT_GROUP entry"), abfd);
idx = 0;
}
dest->shdr = elf_elfsections (abfd)[idx];
{
elf_tdata (abfd)->group_sect_ptr = NULL;
elf_tdata (abfd)->num_group = num_group = -1;
- (*_bfd_error_handler) (_("%B: no valid group sections found"), abfd);
+ _bfd_error_handler
+ (_("%B: no valid group sections found"), abfd);
bfd_set_error (bfd_error_bad_value);
}
}
if (elf_group_name (newsect) == NULL)
{
- (*_bfd_error_handler) (_("%B: no group info for section %A"),
- abfd, newsect);
+ /* xgettext:c-format */
+ _bfd_error_handler (_("%B: no group info for section %A"),
+ abfd, newsect);
return FALSE;
}
return TRUE;
const struct elf_backend_data *bed = get_elf_backend_data (abfd);
if (bed->link_order_error_handler)
bed->link_order_error_handler
+ /* xgettext:c-format */
(_("%B: warning: sh_link not set for section `%A'"),
abfd, s);
}
sh_link. We don't want to proceed. */
if (linksec == NULL)
{
- (*_bfd_error_handler)
+ _bfd_error_handler
+ /* xgettext:c-format */
(_("%B: sh_link [%d] in section `%A' is incorrect"),
- s->owner, s, elfsec);
+ s->owner, elfsec, s);
result = FALSE;
}
else if (this_hdr->sh_type == SHT_GROUP
&& elf_next_in_group (s) == NULL)
{
- (*_bfd_error_handler)
+ _bfd_error_handler
+ /* xgettext:c-format */
(_("%B: SHT_GROUP section [index %d] has no SHF_GROUP sections"),
abfd, elf_section_data (s)->this_idx);
result = FALSE;
/* PR binutils/18758: Beware of corrupt binaries with invalid group data. */
if (shdr == NULL || shdr->bfd_section == NULL || shdr->contents == NULL)
{
- (*_bfd_error_handler)
+ _bfd_error_handler
+ /* xgettext:c-format */
(_("%B: section group entry number %u is corrupt"),
abfd, i);
result = FALSE;
else
{
/* There are some unknown sections in the group. */
- (*_bfd_error_handler)
- (_("%B: unknown [%d] section `%s' in group [%s]"),
+ _bfd_error_handler
+ /* xgettext:c-format */
+ (_("%B: unknown [%d] section `%s' in group [%A]"),
abfd,
(unsigned int) idx->shdr->sh_type,
bfd_elf_string_from_elf_section (abfd,
(elf_elfheader (abfd)
->e_shstrndx),
idx->shdr->sh_name),
- shdr->bfd_section->name);
+ shdr->bfd_section);
result = FALSE;
}
}
if (!bfd_malloc_and_get_section (abfd, newsect, &contents))
return FALSE;
- elf_parse_notes (abfd, (char *) contents, hdr->sh_size, -1);
+ elf_parse_notes (abfd, (char *) contents, hdr->sh_size, hdr->sh_offset);
free (contents);
}
{
if (!bfd_init_section_compress_status (abfd, newsect))
{
- (*_bfd_error_handler)
+ _bfd_error_handler
+ /* xgettext:c-format */
(_("%B: unable to initialize compress status for section %s"),
abfd, name);
return FALSE;
{
if (!bfd_init_section_decompress_status (abfd, newsect))
{
- (*_bfd_error_handler)
+ _bfd_error_handler
+ /* xgettext:c-format */
(_("%B: unable to initialize decompress status for section %s"),
abfd, name);
return FALSE;
Elf_Internal_Shdr ** oheaders = elf_elfsections (obfd);
unsigned int i;
- if (section_match (oheaders[hint], iheader))
+ BFD_ASSERT (iheader != NULL);
+
+ /* See PR 20922 for a reproducer of the NULL test. */
+ if (oheaders[hint] != NULL
+ && section_match (oheaders[hint], iheader))
return hint;
for (i = 1; i < elf_numsections (obfd); i++)
{
Elf_Internal_Shdr * oheader = oheaders[i];
+ if (oheader == NULL)
+ continue;
if (section_match (oheader, iheader))
/* FIXME: Do we care if there is a potential for
multiple matches ? */
in the input bfd. */
if (iheader->sh_link != SHN_UNDEF)
{
+ /* See PR 20931 for a reproducer. */
+ if (iheader->sh_link >= elf_numsections (ibfd))
+ {
+ (* _bfd_error_handler)
+ /* xgettext:c-format */
+ (_("%B: Invalid sh_link field (%d) in section number %d"),
+ ibfd, iheader->sh_link, secnum);
+ return FALSE;
+ }
+
sh_link = find_link (obfd, iheaders[iheader->sh_link], iheader->sh_link);
if (sh_link != SHN_UNDEF)
{
/* FIXME: Should we install iheader->sh_link
if we could not find a match ? */
(* _bfd_error_handler)
+ /* xgettext:c-format */
(_("%B: Failed to find link section for section %d"), obfd, secnum);
}
}
else
(* _bfd_error_handler)
+ /* xgettext:c-format */
(_("%B: Failed to find info section for section %d"), obfd, secnum);
}
}
if (sections_being_created [shindex])
{
- (*_bfd_error_handler)
+ _bfd_error_handler
(_("%B: warning: loop in section dependencies detected"), abfd);
return FALSE;
}
Unusual, but possible. Warn, but continue. */
if (elf_onesymtab (abfd) != 0)
{
- (*_bfd_error_handler)
- (_("%B: warning: multiple symbol tables detected - ignoring the table in section %u"),
+ _bfd_error_handler
+ /* xgettext:c-format */
+ (_("%B: warning: multiple symbol tables detected"
+ " - ignoring the table in section %u"),
abfd, shindex);
goto success;
}
Unusual, but possible. Warn, but continue. */
if (elf_dynsymtab (abfd) != 0)
{
- (*_bfd_error_handler)
- (_("%B: warning: multiple dynamic symbol tables detected - ignoring the table in section %u"),
+ _bfd_error_handler
+ /* xgettext:c-format */
+ (_("%B: warning: multiple dynamic symbol tables detected"
+ " - ignoring the table in section %u"),
abfd, shindex);
goto success;
}
/* Check for a bogus link to avoid crashing. */
if (hdr->sh_link >= num_sec)
{
- ((*_bfd_error_handler)
- (_("%B: invalid link %lu for reloc section %s (index %u)"),
- abfd, hdr->sh_link, name, shindex));
+ _bfd_error_handler
+ /* xgettext:c-format */
+ (_("%B: invalid link %lu for reloc section %s (index %u)"),
+ abfd, hdr->sh_link, name, shindex);
ret = _bfd_elf_make_section_from_shdr (abfd, hdr, name,
shindex);
goto success;
*hdr2 = *hdr;
*p_hdr = hdr2;
elf_elfsections (abfd)[shindex] = hdr2;
- target_sect->reloc_count += NUM_SHDR_ENTRIES (hdr);
+ target_sect->reloc_count += (NUM_SHDR_ENTRIES (hdr)
+ * bed->s->int_rels_per_ext_rel);
target_sect->flags |= SEC_RELOC;
target_sect->relocation = NULL;
target_sect->rel_filepos = hdr->sh_offset;
if ((hdr->sh_flags & SHF_ALLOC) != 0)
/* FIXME: How to properly handle allocated section reserved
for applications? */
- (*_bfd_error_handler)
+ _bfd_error_handler
+ /* xgettext:c-format */
(_("%B: don't know how to handle allocated, application "
"specific section `%s' [0x%8x]"),
abfd, name, hdr->sh_type);
else if (hdr->sh_type >= SHT_LOPROC
&& hdr->sh_type <= SHT_HIPROC)
/* FIXME: We should handle this section. */
- (*_bfd_error_handler)
+ _bfd_error_handler
+ /* xgettext:c-format */
(_("%B: don't know how to handle processor specific section "
"`%s' [0x%8x]"),
abfd, name, hdr->sh_type);
/* SHF_OS_NONCONFORMING indicates that special knowledge is
required to correctly process the section and the file should
be rejected with an error message. */
- (*_bfd_error_handler)
+ _bfd_error_handler
+ /* xgettext:c-format */
(_("%B: don't know how to handle OS specific section "
"`%s' [0x%8x]"),
abfd, name, hdr->sh_type);
}
else
/* FIXME: We should handle this section. */
- (*_bfd_error_handler)
+ _bfd_error_handler
+ /* xgettext:c-format */
(_("%B: don't know how to handle section `%s' [0x%8x]"),
abfd, name, hdr->sh_type);
static const struct bfd_elf_special_section special_sections_f[] =
{
- { STRING_COMMA_LEN (".fini"), 0, SHT_PROGBITS, SHF_ALLOC + SHF_EXECINSTR },
- { STRING_COMMA_LEN (".fini_array"), 0, SHT_FINI_ARRAY, SHF_ALLOC + SHF_WRITE },
- { NULL, 0, 0, 0, 0 }
+ { STRING_COMMA_LEN (".fini"), 0, SHT_PROGBITS, SHF_ALLOC + SHF_EXECINSTR },
+ { STRING_COMMA_LEN (".fini_array"), -2, SHT_FINI_ARRAY, SHF_ALLOC + SHF_WRITE },
+ { NULL, 0 , 0, 0, 0 }
};
static const struct bfd_elf_special_section special_sections_g[] =
static const struct bfd_elf_special_section special_sections_i[] =
{
- { STRING_COMMA_LEN (".init"), 0, SHT_PROGBITS, SHF_ALLOC + SHF_EXECINSTR },
- { STRING_COMMA_LEN (".init_array"), 0, SHT_INIT_ARRAY, SHF_ALLOC + SHF_WRITE },
- { STRING_COMMA_LEN (".interp"), 0, SHT_PROGBITS, 0 },
- { NULL, 0, 0, 0, 0 }
+ { STRING_COMMA_LEN (".init"), 0, SHT_PROGBITS, SHF_ALLOC + SHF_EXECINSTR },
+ { STRING_COMMA_LEN (".init_array"), -2, SHT_INIT_ARRAY, SHF_ALLOC + SHF_WRITE },
+ { STRING_COMMA_LEN (".interp"), 0, SHT_PROGBITS, 0 },
+ { NULL, 0, 0, 0, 0 }
};
static const struct bfd_elf_special_section special_sections_l[] =
static const struct bfd_elf_special_section special_sections_p[] =
{
- { STRING_COMMA_LEN (".preinit_array"), 0, SHT_PREINIT_ARRAY, SHF_ALLOC + SHF_WRITE },
- { STRING_COMMA_LEN (".plt"), 0, SHT_PROGBITS, SHF_ALLOC + SHF_EXECINSTR },
- { NULL, 0, 0, 0, 0 }
+ { STRING_COMMA_LEN (".preinit_array"), -2, SHT_PREINIT_ARRAY, SHF_ALLOC + SHF_WRITE },
+ { STRING_COMMA_LEN (".plt"), 0, SHT_PROGBITS, SHF_ALLOC + SHF_EXECINSTR },
+ { NULL, 0, 0, 0, 0 }
};
static const struct bfd_elf_special_section special_sections_r[] =
/* PR 17512: file: 0eb809fe, 8b0535ee. */
if (asect->alignment_power >= (sizeof (bfd_vma) * 8) - 1)
{
- (*_bfd_error_handler)
+ _bfd_error_handler
+ /* xgettext:c-format */
(_("%B: error: Alignment power %d of section `%A' is too big"),
- abfd, asect, asect->alignment_power);
+ abfd, asect->alignment_power, asect);
arg->failed = TRUE;
return;
}
allow the link to proceed. This can happen when users link
non-bss input sections to bss output sections, or emit data
to a bss output section via a linker script. */
- (*_bfd_error_handler)
+ _bfd_error_handler
(_("warning: section `%A' type changed to PROGBITS"), asect);
this_hdr->sh_type = sh_type;
}
H_PUT_32 (abfd, sec->flags & SEC_LINK_ONCE ? GRP_COMDAT : 0, loc);
}
-/* Return the section which RELOC_SEC applies to. */
+/* Given NAME, the name of a relocation section stripped of its
+ .rel/.rela prefix, return the section in ABFD to which the
+ relocations apply. */
asection *
-_bfd_elf_get_reloc_section (asection *reloc_sec)
+_bfd_elf_plt_get_reloc_section (bfd *abfd, const char *name)
+{
+ /* If a target needs .got.plt section, relocations in rela.plt/rel.plt
+ section likely apply to .got.plt or .got section. */
+ if (get_elf_backend_data (abfd)->want_got_plt
+ && strcmp (name, ".plt") == 0)
+ {
+ asection *sec;
+
+ name = ".got.plt";
+ sec = bfd_get_section_by_name (abfd, name);
+ if (sec != NULL)
+ return sec;
+ name = ".got";
+ }
+
+ return bfd_get_section_by_name (abfd, name);
+}
+
+/* Return the section to which RELOC_SEC applies. */
+
+static asection *
+elf_get_reloc_section (asection *reloc_sec)
{
const char *name;
unsigned int type;
bfd *abfd;
-
- if (reloc_sec == NULL)
- return NULL;
+ const struct elf_backend_data *bed;
type = elf_section_data (reloc_sec)->this_hdr.sh_type;
if (type != SHT_REL && type != SHT_RELA)
/* We look up the section the relocs apply to by name. */
name = reloc_sec->name;
- if (type == SHT_REL)
- name += 4;
- else
- name += 5;
+ if (strncmp (name, ".rel", 4) != 0)
+ return NULL;
+ name += 4;
+ if (type == SHT_RELA && *name++ != 'a')
+ return NULL;
- /* If a target needs .got.plt section, relocations in rela.plt/rel.plt
- section apply to .got.plt section. */
abfd = reloc_sec->owner;
- if (get_elf_backend_data (abfd)->want_got_plt
- && strcmp (name, ".plt") == 0)
- {
- /* .got.plt is a linker created input section. It may be mapped
- to some other output section. Try two likely sections. */
- name = ".got.plt";
- reloc_sec = bfd_get_section_by_name (abfd, name);
- if (reloc_sec != NULL)
- return reloc_sec;
- name = ".got";
- }
-
- reloc_sec = bfd_get_section_by_name (abfd, name);
- return reloc_sec;
+ bed = get_elf_backend_data (abfd);
+ return bed->get_reloc_section (abfd, name);
}
/* Assign all ELF section numbers. The dummy first section is handled here
if (section_number >= SHN_LORESERVE)
{
+ /* xgettext:c-format */
_bfd_error_handler (_("%B: too many sections: %u"),
abfd, section_number);
return FALSE;
if (discarded_section (s))
{
asection *kept;
- (*_bfd_error_handler)
- (_("%B: sh_link of section `%A' points to discarded section `%A' of `%B'"),
+ _bfd_error_handler
+ /* xgettext:c-format */
+ (_("%B: sh_link of section `%A' points to"
+ " discarded section `%A' of `%B'"),
abfd, d->this_hdr.bfd_section,
s, s->owner);
/* Point to the kept section if it has the same
/* Handle objcopy. */
if (s->output_section == NULL)
{
- (*_bfd_error_handler)
- (_("%B: sh_link of section `%A' points to removed section `%A' of `%B'"),
+ _bfd_error_handler
+ /* xgettext:c-format */
+ (_("%B: sh_link of section `%A' points to"
+ " removed section `%A' of `%B'"),
abfd, d->this_hdr.bfd_section, s, s->owner);
bfd_set_error (bfd_error_bad_value);
return FALSE;
= get_elf_backend_data (abfd);
if (bed->link_order_error_handler)
bed->link_order_error_handler
+ /* xgettext:c-format */
(_("%B: warning: sh_link not set for section `%A'"),
abfd, sec);
}
if (s != NULL)
d->this_hdr.sh_link = elf_section_data (s)->this_idx;
- s = get_elf_backend_data (abfd)->get_reloc_section (sec);
+ s = elf_get_reloc_section (sec);
if (s != NULL)
{
d->this_hdr.sh_info = elf_section_data (s)->this_idx;
}
}
- /* Let the backend count up any program headers it might need. */
bed = get_elf_backend_data (abfd);
- if (bed->elf_backend_additional_program_headers)
+
+ 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 */
+ (_("%B: GNU_MBIN section `%A' 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;
}
(*m)->count = new_count;
- if (remove_empty_load && (*m)->p_type == PT_LOAD && (*m)->count == 0)
+ if (remove_empty_load
+ && (*m)->p_type == PT_LOAD
+ && (*m)->count == 0
+ && !(*m)->includes_phdrs)
*m = (*m)->next;
else
m = &(*m)->next;
bfd_boolean writable;
int tls_count = 0;
asection *first_tls = NULL;
+ asection *first_mbind = NULL;
asection *dynsec, *eh_frame_hdr;
bfd_size_type amt;
bfd_vma addr_mask, wrap_to = 0;
+ bfd_boolean linker_created_pt_phdr_segment = FALSE;
/* Select the allocated sections, and sort them. */
m->p_flags = PF_R | PF_X;
m->p_flags_valid = 1;
m->includes_phdrs = 1;
-
+ linker_created_pt_phdr_segment = TRUE;
*pm = m;
pm = &m->next;
|| ((sections[0]->lma & addr_mask) % maxpagesize
< phdr_size % maxpagesize)
|| (sections[0]->lma & addr_mask & -maxpagesize) < wrap_to)
- phdr_in_segment = FALSE;
+ {
+ /* 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;
+ }
}
for (i = 0, hdrpp = sections; i < count; i++, hdrpp++)
first_tls = s;
tls_count++;
}
+ if (first_mbind == NULL
+ && (elf_section_flags (s) & SHF_GNU_MBIND) != 0)
+ first_mbind = s;
}
/* If there are any SHF_TLS output sections, add PT_TLS segment. */
pm = &m->next;
}
+ if (first_mbind && (abfd->flags & D_PAGED) != 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))
+ {
+ /* Mandated PF_R. */
+ unsigned long p_flags = PF_R;
+ if ((s->flags & SEC_READONLY) == 0)
+ p_flags |= PF_W;
+ if ((s->flags & SEC_CODE) != 0)
+ p_flags |= PF_X;
+
+ 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_MBIND_LO
+ + elf_section_data (s)->this_hdr.sh_info);
+ m->count = 1;
+ m->p_flags_valid = 1;
+ m->sections[0] = s;
+ m->p_flags = p_flags;
+
+ *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);
Elf_Internal_Phdr *p;
file_ptr off;
bfd_size_type maxpagesize;
+ unsigned int pt_load_count = 0;
unsigned int alloc;
unsigned int i, j;
bfd_vma header_pad = 0;
maxpagesize = m->p_align;
p->p_align = maxpagesize;
+ pt_load_count += 1;
}
else if (m->p_align_valid)
p->p_align = m->p_align;
}
off_adjust = vma_page_aligned_bias (p->p_vaddr, off, align);
+
+ /* Broken hardware and/or kernel require that files do not
+ map the same page with different permissions on some hppa
+ processors. */
+ if (pt_load_count > 1
+ && bed->no_page_alias
+ && (off & (maxpagesize - 1)) != 0
+ && (off & -maxpagesize) == ((off + off_adjust) & -maxpagesize))
+ off_adjust += maxpagesize;
off += off_adjust;
if (no_contents)
{
&& strcmp (m->sections[0]->name, ".dynamic") != 0)
{
_bfd_error_handler
- (_("%B: The first section in the PT_DYNAMIC segment is not the .dynamic section"),
+ (_("%B: The first section in the PT_DYNAMIC segment"
+ " is not the .dynamic section"),
abfd);
bfd_set_error (bfd_error_bad_value);
return FALSE;
|| (!m->p_paddr_valid
&& p->p_paddr < (bfd_vma) off))
{
- (*_bfd_error_handler)
- (_("%B: Not enough room for program headers, try linking with -N"),
+ _bfd_error_handler
+ (_("%B: Not enough room for program headers,"
+ " try linking with -N"),
abfd);
bfd_set_error (bfd_error_bad_value);
return FALSE;
&& (s_start < p_end
|| p_end < p_start))
{
- (*_bfd_error_handler)
+ _bfd_error_handler
+ /* xgettext:c-format */
(_("%B: section %A lma %#lx adjusted to %#lx"), abfd, sec,
(unsigned long) s_start, (unsigned long) p_end);
adjust = 0;
if (!ELF_SECTION_IN_SEGMENT_1 (this_hdr, p, check_vma, 0)
&& !ELF_TBSS_SPECIAL (this_hdr, p))
{
- (*_bfd_error_handler)
+ _bfd_error_handler
+ /* xgettext:c-format */
(_("%B: section `%A' can't be allocated in segment %d"),
abfd, sec, j);
print_segment_map (m);
else if ((hdr->sh_flags & SHF_ALLOC) != 0)
{
if (hdr->sh_size != 0)
- (*_bfd_error_handler)
+ _bfd_error_handler
+ /* xgettext:c-format */
(_("%B: warning: allocated section `%s' not in segment"),
abfd,
(hdr->bfd_section == NULL
else if (m->count != 0)
{
unsigned int i;
+
if (p->p_type != PT_LOAD
&& (p->p_type != PT_NOTE
|| bfd_get_format (abfd) != bfd_core))
{
+ /* A user specified segment layout may include a PHDR
+ segment that overlaps with a LOAD segment... */
+ if (p->p_type == PT_PHDR)
+ {
+ m->count = 0;
+ continue;
+ }
+
if (m->includes_filehdr || m->includes_phdrs)
{
/* PR 17512: file: 2195325e. */
- (*_bfd_error_handler)
- (_("%B: warning: non-load segment includes file header and/or program header"),
- abfd);
+ _bfd_error_handler
+ (_("%B: error: non-load segment %d includes file header and/or program header"),
+ abfd, (int)(p - phdrs));
return FALSE;
}
/* Write out the program headers. */
alloc = elf_program_header_size (abfd) / bed->s->sizeof_phdr;
+
+ /* Sort the program headers into the ordering required by the ELF standard. */
+ if (alloc == 0)
+ return TRUE;
+
+ /* PR ld/20815 - Check that the program header segment, if present, will
+ be loaded into memory. FIXME: The check below is not sufficient as
+ really all PT_LOAD segments should be checked before issuing an error
+ message. Plus the PHDR segment does not have to be the first segment
+ in the program header table. But this version of the check should
+ catch all real world use cases.
+
+ FIXME: We used to have code here to sort the PT_LOAD segments into
+ ascending order, as per the ELF spec. But this breaks some programs,
+ including the Linux kernel. But really either the spec should be
+ changed or the programs updated. */
+ if (alloc > 1
+ && tdata->phdr[0].p_type == PT_PHDR
+ && ! bed->elf_backend_allow_non_load_phdr (abfd, tdata->phdr, alloc)
+ && tdata->phdr[1].p_type == PT_LOAD
+ && (tdata->phdr[1].p_vaddr > tdata->phdr[0].p_vaddr
+ || (tdata->phdr[1].p_vaddr + tdata->phdr[1].p_memsz)
+ < (tdata->phdr[0].p_vaddr + tdata->phdr[0].p_memsz)))
+ {
+ /* The fix for this error is usually to edit the linker script being
+ used and set up the program headers manually. Either that or
+ leave room for the headers at the start of the SECTIONS. */
+ _bfd_error_handler (_("\
+%B: error: PHDR segment not covered by LOAD segment"),
+ abfd);
+ return FALSE;
+ }
+
if (bfd_seek (abfd, (bfd_signed_vma) bed->s->sizeof_ehdr, SEEK_SET) != 0
|| bed->s->write_out_phdrs (abfd, tdata->phdr, alloc) != 0)
return FALSE;
{
/* This case can occur when using --strip-symbol on a symbol
which is used in a relocation entry. */
- (*_bfd_error_handler)
+ _bfd_error_handler
+ /* xgettext:c-format */
(_("%B: symbol `%s' required but not present"),
abfd, bfd_asymbol_name (asym_ptr));
bfd_set_error (bfd_error_no_symbols);
/* Special segments, such as the PT_PHDR segment, may contain
no sections, but ordinary, loadable segments should contain
something. They are allowed by the ELF spec however, so only
- a warning is produced. */
- if (segment->p_type == PT_LOAD)
- (*_bfd_error_handler) (_("\
-%B: warning: Empty loadable segment detected, is this intentional ?"),
- ibfd);
+ a warning is produced.
+ There is however the valid use case of embedded systems which
+ have segments with p_filesz of 0 and a p_memsz > 0 to initialize
+ flash memory with zeros. No warning is shown for that case. */
+ if (segment->p_type == PT_LOAD
+ && (segment->p_filesz > 0 || segment->p_memsz == 0))
+ /* xgettext:c-format */
+ _bfd_error_handler (_("\
+%B: warning: Empty loadable segment detected at vaddr=0x%.8x, is this intentional ?"),
+ ibfd, segment->p_vaddr);
map->count = 0;
*pointer_to_map = map;
for (section = obfd->sections; section != NULL;
section = section->next)
{
- if (section->segment_mark == FALSE)
+ if (!section->segment_mark)
goto rewrite;
else
section->segment_mark = FALSE;
{
/* PR 17512: file: f17299af. */
if (segment->p_align > (bfd_vma) 1 << ((sizeof (bfd_vma) * 8) - 2))
- (*_bfd_error_handler) (_("\
+ /* xgettext:c-format */
+ _bfd_error_handler (_("\
%B: warning: segment alignment of 0x%llx is too large"),
- ibfd, (long long) segment->p_align);
+ ibfd, (long long) segment->p_align);
else
maxpagesize = segment->p_align;
}
elf_section_flags (osec) |= (elf_section_flags (isec)
& (SHF_MASKOS | SHF_MASKPROC));
+ /* Copy sh_info from input for mbind section. */
+ if (elf_section_flags (isec) & SHF_GNU_MBIND)
+ elf_section_data (osec)->this_hdr.sh_info
+ = elf_section_data (isec)->this_hdr.sh_info;
+
/* Set things up for objcopy and relocatable link. The output
SHT_GROUP section will have its elf_next_in_group pointing back
to the input group members. Ignore linker created group section.
shndx = _bfd_elf_section_from_bfd_section (abfd, sec2);
if (shndx == SHN_BAD)
{
+ /* xgettext:c-format */
_bfd_error_handler (_("\
Unable to find equivalent output section for symbol '%s' from section '%s'"),
syms[idx]->name ? syms[idx]->name : "<Local sym>",
if (hdr->sh_info == 0 || hdr->sh_size < sizeof (Elf_External_Verneed))
{
error_return_bad_verref:
- (*_bfd_error_handler)
+ _bfd_error_handler
(_("%B: .gnu.version_r invalid entry"), abfd);
bfd_set_error (bfd_error_bad_value);
error_return_verref:
if (hdr->sh_info == 0 || hdr->sh_size < sizeof (Elf_External_Verdef))
{
error_return_bad_verdef:
- (*_bfd_error_handler)
+ _bfd_error_handler
(_("%B: .gnu.version_d invalid entry"), abfd);
bfd_set_error (bfd_error_bad_value);
error_return_verdef:
return TRUE;
fail:
- (*_bfd_error_handler)
+ _bfd_error_handler
+ /* xgettext:c-format */
(_("%B: unsupported relocation type %s"),
abfd, areloc->howto->name);
bfd_set_error (bfd_error_bad_value);
default:
return TRUE;
+ case NT_GNU_PROPERTY_TYPE_0:
+ return _bfd_elf_parse_gnu_properties (abfd, note);
+
case NT_GNU_BUILD_ID:
return elfobj_grok_gnu_build_id (abfd, note);
}
{
size_t offset;
- switch (abfd->arch_info->bits_per_word)
+ switch (elf_elfheader (abfd)->e_ident[EI_CLASS])
{
- case 32:
+ case ELFCLASS32:
if (note->descsz < 108)
return FALSE;
break;
- case 64:
+ case ELFCLASS64:
if (note->descsz < 120)
return FALSE;
break;
offset = 4;
/* Skip over pr_psinfosz. */
- if (abfd->arch_info->bits_per_word == 32)
+ if (elf_elfheader (abfd)->e_ident[EI_CLASS] == ELFCLASS32)
offset += 4;
else
{
offset = 4;
/* Skip over pr_statussz. */
- switch (abfd->arch_info->bits_per_word)
+ switch (elf_elfheader (abfd)->e_ident[EI_CLASS])
{
- case 32:
+ case ELFCLASS32:
offset += 4;
break;
- case 64:
+ case ELFCLASS64:
offset += 4; /* Padding before pr_statussz. */
offset += 8;
break;
}
/* Extract size of pr_reg from pr_gregsetsz. */
- if (abfd->arch_info->bits_per_word == 32)
+ if (elf_elfheader (abfd)->e_ident[EI_CLASS] == ELFCLASS32)
size = bfd_h_get_32 (abfd, (bfd_byte *) note->descdata + offset);
else
size = bfd_h_get_64 (abfd, (bfd_byte *) note->descdata + offset);
/* Skip over pr_gregsetsz and pr_fpregsetsz. */
- offset += (abfd->arch_info->bits_per_word / 8) * 2;
+ if (elf_elfheader (abfd)->e_ident[EI_CLASS] == ELFCLASS32)
+ offset += 4 * 2;
+ else
+ offset += 8 * 2;
/* Skip over pr_osreldate. */
offset += 4;
offset += 4;
/* Padding before pr_reg. */
- if (abfd->arch_info->bits_per_word == 64)
+ if (elf_elfheader (abfd)->e_ident[EI_CLASS] == ELFCLASS64)
offset += 4;
/* Make a ".reg/999" section and a ".reg" section. */
return n;
}
-/* It is only used by x86-64 so far. */
+/* It is only used by x86-64 so far.
+ ??? This repeats *COM* id of zero. sec->id is supposed to be unique,
+ but current usage would allow all of _bfd_std_section to be zero. */
+static const asymbol lcomm_sym
+ = GLOBAL_SYM_INIT ("LARGE_COMMON", &_bfd_elf_large_com_section);
asection _bfd_elf_large_com_section
- = BFD_FAKE_SECTION (_bfd_elf_large_com_section,
- SEC_IS_COMMON, NULL, "LARGE_COMMON", 0);
+ = BFD_FAKE_SECTION (_bfd_elf_large_com_section, &lcomm_sym,
+ "LARGE_COMMON", 0, SEC_IS_COMMON);
void
_bfd_elf_post_process_headers (bfd * abfd,