/* ELF executable support for BFD.
- Copyright (C) 1993-2020 Free Software Foundation, Inc.
+ Copyright (C) 1993-2021 Free Software Foundation, Inc.
This file is part of BFD, the Binary File Descriptor library.
const struct elf_backend_data *bed;
const char *name;
bfd_boolean ret = TRUE;
- static bfd_boolean * sections_being_created = NULL;
- static bfd * sections_being_created_abfd = NULL;
- static unsigned int nesting = 0;
if (shindex >= elf_numsections (abfd))
return FALSE;
- if (++ nesting > 3)
+ /* PR17512: A corrupt ELF binary might contain a loop of sections via
+ sh_link or sh_info. Detect this here, by refusing to load a
+ section that we are already in the process of loading. */
+ if (elf_tdata (abfd)->being_created[shindex])
{
- /* PR17512: A corrupt ELF binary might contain a recursive group of
- 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
- can expect to recurse at least once.
-
- FIXME: It would be better if this array was attached to the bfd,
- rather than being held in a static pointer. */
-
- if (sections_being_created_abfd != abfd)
- {
- free (sections_being_created);
- sections_being_created = NULL;
- }
- if (sections_being_created == NULL)
- {
- size_t amt = elf_numsections (abfd) * sizeof (bfd_boolean);
-
- /* PR 26005: Do not use bfd_zalloc here as the memory might
- be released before the bfd has been fully scanned. */
- sections_being_created = (bfd_boolean *) bfd_zmalloc (amt);
- if (sections_being_created == NULL)
- return FALSE;
- sections_being_created_abfd = abfd;
- }
- if (sections_being_created [shindex])
- {
- _bfd_error_handler
- (_("%pB: warning: loop in section dependencies detected"), abfd);
- return FALSE;
- }
- sections_being_created [shindex] = TRUE;
+ _bfd_error_handler
+ (_("%pB: warning: loop in section dependencies detected"), abfd);
+ return FALSE;
}
+ elf_tdata (abfd)->being_created[shindex] = TRUE;
hdr = elf_elfsections (abfd)[shindex];
ehdr = elf_elfheader (abfd);
fail:
ret = FALSE;
success:
- if (sections_being_created && sections_being_created_abfd == abfd)
- sections_being_created [shindex] = FALSE;
- if (-- nesting == 0)
- {
- free (sections_being_created);
- sections_being_created = NULL;
- sections_being_created_abfd = NULL;
- }
+ elf_tdata (abfd)->being_created[shindex] = FALSE;
return ret;
}
static const struct bfd_elf_special_section special_sections_g[] =
{
{ STRING_COMMA_LEN (".gnu.linkonce.b"), -2, SHT_NOBITS, SHF_ALLOC + SHF_WRITE },
+ { STRING_COMMA_LEN (".gnu.linkonce.n"), -2, SHT_NOBITS, SHF_ALLOC + SHF_WRITE },
+ { STRING_COMMA_LEN (".gnu.linkonce.p"), -2, SHT_PROGBITS, SHF_ALLOC + SHF_WRITE },
{ STRING_COMMA_LEN (".gnu.lto_"), -1, SHT_PROGBITS, SHF_EXCLUDE },
{ STRING_COMMA_LEN (".got"), 0, SHT_PROGBITS, SHF_ALLOC + SHF_WRITE },
{ STRING_COMMA_LEN (".gnu.version"), 0, SHT_GNU_versym, 0 },
static const struct bfd_elf_special_section special_sections_n[] =
{
+ { STRING_COMMA_LEN (".noinit"), -2, SHT_NOBITS, SHF_ALLOC + SHF_WRITE },
{ STRING_COMMA_LEN (".note.GNU-stack"), 0, SHT_PROGBITS, 0 },
{ STRING_COMMA_LEN (".note"), -1, SHT_NOTE, 0 },
{ NULL, 0, 0, 0, 0 }
static const struct bfd_elf_special_section special_sections_p[] =
{
+ { STRING_COMMA_LEN (".persistent"), -2, SHT_PROGBITS, SHF_ALLOC + SHF_WRITE },
{ 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 }
&& (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);
+ bfd_vma commonpagesize;
+ unsigned int page_align_power;
+
+ if (info != NULL)
+ commonpagesize = info->commonpagesize;
+ else
+ commonpagesize = bed->commonpagesize;
+ page_align_power = bfd_log2 (commonpagesize);
for (s = abfd->sections; s != NULL; s = s->next)
if (elf_section_flags (s) & SHF_GNU_MBIND)
{
phdr_size += bed->s->sizeof_ehdr;
/* phdr_size is compared to LMA values which are in bytes. */
phdr_size /= opb;
- maxpagesize = bed->maxpagesize;
+ if (info != NULL)
+ maxpagesize = info->maxpagesize;
+ else
+ maxpagesize = bed->maxpagesize;
if (maxpagesize == 0)
maxpagesize = 1;
phdr_in_segment = info != NULL && info->load_phdrs;
/* Put !SEC_LOAD sections after SEC_LOAD ones. */
-#define TOEND(x) (((x)->flags & (SEC_LOAD | SEC_THREAD_LOCAL)) == 0)
+#define TOEND(x) (((x)->flags & (SEC_LOAD | SEC_THREAD_LOCAL)) == 0 \
+ && (x)->size != 0)
if (TOEND (sec1))
{
maxpagesize = 1;
if ((abfd->flags & D_PAGED) != 0)
- maxpagesize = bed->maxpagesize;
+ {
+ if (link_info != NULL)
+ maxpagesize = link_info->maxpagesize;
+ else
+ maxpagesize = bed->maxpagesize;
+ }
/* Sections must map to file offsets past the ELF file header. */
off = bed->s->sizeof_ehdr;
struct elf_segment_map *m;
file_ptr off;
unsigned int opb = bfd_octets_per_byte (abfd, NULL);
+ bfd_vma maxpagesize;
+ if (link_info != NULL)
+ maxpagesize = link_info->maxpagesize;
+ else
+ maxpagesize = bed->maxpagesize;
i_shdrpp = elf_elfsections (abfd);
end_hdrpp = i_shdrpp + elf_numsections (abfd);
off = elf_next_file_pos (abfd);
/* We don't need to page align empty sections. */
if ((abfd->flags & D_PAGED) != 0 && hdr->sh_size != 0)
off += vma_page_aligned_bias (hdr->sh_addr, off,
- bed->maxpagesize);
+ maxpagesize);
else
off += vma_page_aligned_bias (hdr->sh_addr, off,
hdr->sh_addralign);
/* Rewrite program header information. */
static bfd_boolean
-rewrite_elf_program_header (bfd *ibfd, bfd *obfd)
+rewrite_elf_program_header (bfd *ibfd, bfd *obfd, bfd_vma maxpagesize)
{
Elf_Internal_Ehdr *iehdr;
struct elf_segment_map *map;
unsigned int num_segments;
bfd_boolean phdr_included = FALSE;
bfd_boolean p_paddr_valid;
- bfd_vma maxpagesize;
struct elf_segment_map *phdr_adjust_seg = NULL;
unsigned int phdr_adjust_num = 0;
const struct elf_backend_data *bed;
pointer_to_map = &map_first;
num_segments = elf_elfheader (ibfd)->e_phnum;
- maxpagesize = get_elf_backend_data (obfd)->maxpagesize;
/* Returns the end address of the segment + 1. */
#define SEGMENT_END(segment, start) \
map->p_flags = segment->p_flags;
map->p_flags_valid = 1;
+ if (map->p_type == PT_LOAD
+ && (ibfd->flags & D_PAGED) != 0
+ && maxpagesize > 1
+ && segment->p_align > 1)
+ {
+ map->p_align = segment->p_align;
+ if (segment->p_align > maxpagesize)
+ map->p_align = maxpagesize;
+ map->p_align_valid = 1;
+ }
+
/* If the first section in the input segment is removed, there is
no need to preserve segment physical address in the corresponding
output segment. */
static bfd_boolean
copy_private_bfd_data (bfd *ibfd, bfd *obfd)
{
+ bfd_vma maxpagesize;
+
if (bfd_get_flavour (ibfd) != bfd_target_elf_flavour
|| bfd_get_flavour (obfd) != bfd_target_elf_flavour)
return TRUE;
}
rewrite:
+ maxpagesize = 0;
if (ibfd->xvec == obfd->xvec)
{
/* When rewriting program header, set the output maxpagesize to
Elf_Internal_Phdr *segment;
unsigned int i;
unsigned int num_segments = elf_elfheader (ibfd)->e_phnum;
- bfd_vma maxpagesize = 0;
for (i = 0, segment = elf_tdata (ibfd)->phdr;
i < num_segments;
else
maxpagesize = segment->p_align;
}
-
- if (maxpagesize != get_elf_backend_data (obfd)->maxpagesize)
- bfd_emul_set_maxpagesize (bfd_get_target (obfd), maxpagesize);
}
+ if (maxpagesize == 0)
+ maxpagesize = get_elf_backend_data (obfd)->maxpagesize;
- return rewrite_elf_program_header (ibfd, obfd);
+ return rewrite_elf_program_header (ibfd, obfd, maxpagesize);
}
/* Initialize private output section information from input section. */
/* Read in any secondary relocs associated with SEC. */
bfd_boolean
-_bfd_elf_slurp_secondary_reloc_section (bfd * abfd,
- asection * sec,
- asymbol ** symbols)
+_bfd_elf_slurp_secondary_reloc_section (bfd * abfd,
+ asection * sec,
+ asymbol ** symbols,
+ bfd_boolean dynamic)
{
const struct elf_backend_data * const ebd = get_elf_backend_data (abfd);
asection * relsec;
continue;
}
- symcount = bfd_get_symcount (abfd);
+ if (dynamic)
+ symcount = bfd_get_dynamic_symcount (abfd);
+ else
+ symcount = bfd_get_symcount (abfd);
for (i = 0, internal_reloc = internal_relocs,
native_reloc = native_relocs;
asymbol **ps;
ps = symbols + r_sym (rela.r_info) - 1;
-
internal_reloc->sym_ptr_ptr = ps;
/* Make sure that this symbol is not removed by strip. */
(*ps)->flags |= BSF_KEEP;