aboutsummaryrefslogtreecommitdiff
path: root/bfd/elf.c
diff options
context:
space:
mode:
Diffstat (limited to 'bfd/elf.c')
-rw-r--r--bfd/elf.c208
1 files changed, 132 insertions, 76 deletions
diff --git a/bfd/elf.c b/bfd/elf.c
index 0e40d6d..ee894eb 100644
--- a/bfd/elf.c
+++ b/bfd/elf.c
@@ -504,17 +504,44 @@ bfd_elf_get_elf_syms (bfd *ibfd,
shndx = extshndx_buf;
isym < isymend;
esym += extsym_size, isym++, shndx = shndx != NULL ? shndx + 1 : NULL)
- if (!(*bed->s->swap_symbol_in) (ibfd, esym, shndx, isym))
- {
- symoffset += (esym - (bfd_byte *) extsym_buf) / extsym_size;
- /* xgettext:c-format */
- _bfd_error_handler (_("%pB symbol number %lu references"
- " nonexistent SHT_SYMTAB_SHNDX section"),
- ibfd, (unsigned long) symoffset);
- free (alloc_intsym);
- intsym_buf = NULL;
- goto out1;
- }
+ {
+ if (!(*bed->s->swap_symbol_in) (ibfd, esym, shndx, isym))
+ {
+ symoffset += (esym - (bfd_byte *) extsym_buf) / extsym_size;
+ /* xgettext:c-format */
+ _bfd_error_handler (_("%pB symbol number %lu references"
+ " nonexistent SHT_SYMTAB_SHNDX section"),
+ ibfd, (unsigned long) symoffset);
+ free (alloc_intsym);
+ intsym_buf = NULL;
+ goto out1;
+ }
+
+ /* PR 33019: Do not accept unsupported binding values - they will
+ likely cause problems later on. */
+ int bind = ELF_ST_BIND (isym->st_info);
+ if (bind > STB_WEAK && bind < STB_LOOS)
+ {
+ /* xgettext:c-format */
+ _bfd_error_handler (_("%pB symbol number %lu uses unsupported binding of %u"),
+ ibfd, (unsigned long) (isym - intsym_buf), bind);
+ free (alloc_intsym);
+ intsym_buf = NULL;
+ goto out1;
+ }
+
+ /* Paranoia: Also refuse to accept the only undefined symbol type: 7. */
+ int t = ELF_ST_TYPE (isym->st_info);
+ if (t == 7)
+ {
+ /* xgettext:c-format */
+ _bfd_error_handler (_("%pB symbol number %lu uses unsupported type of %u"),
+ ibfd, (unsigned long) (isym - intsym_buf), t);
+ free (alloc_intsym);
+ intsym_buf = NULL;
+ goto out1;
+ }
+ }
out1:
_bfd_munmap_temporary (alloc_extshndx, alloc_extshndx_size);
@@ -3469,7 +3496,7 @@ _bfd_elf_init_reloc_shdr (bfd *abfd,
struct bfd_elf_section_reloc_data *reldata,
const char *sec_name,
bool use_rela_p,
- bool delay_st_name_p)
+ bool delay_sh_name_p)
{
Elf_Internal_Shdr *rel_hdr;
const struct elf_backend_data *bed = get_elf_backend_data (abfd);
@@ -3480,7 +3507,7 @@ _bfd_elf_init_reloc_shdr (bfd *abfd,
return false;
reldata->hdr = rel_hdr;
- if (delay_st_name_p)
+ if (delay_sh_name_p)
rel_hdr->sh_name = (unsigned int) -1;
else if (!_bfd_elf_set_reloc_sh_name (abfd, rel_hdr, sec_name,
use_rela_p))
@@ -3526,7 +3553,7 @@ elf_fake_sections (bfd *abfd, asection *asect, void *fsarg)
Elf_Internal_Shdr *this_hdr;
unsigned int sh_type;
const char *name = asect->name;
- bool delay_st_name_p = false;
+ bool delay_sh_name_p = false;
bfd_vma mask;
if (arg->failed)
@@ -3542,16 +3569,18 @@ elf_fake_sections (bfd *abfd, asection *asect, void *fsarg)
if (arg->link_info
&& (abfd->flags & BFD_COMPRESS) != 0
&& (asect->flags & SEC_DEBUGGING) != 0
+ && (asect->flags & SEC_ALLOC) == 0
+ && (asect->flags & SEC_HAS_CONTENTS) != 0
&& name[1] == 'd'
&& name[6] == '_')
{
/* If this section will be compressed, delay adding section
name to section name section after it is compressed in
_bfd_elf_assign_file_positions_for_non_load. */
- delay_st_name_p = true;
+ delay_sh_name_p = true;
}
- if (delay_st_name_p)
+ if (delay_sh_name_p)
this_hdr->sh_name = (unsigned int) -1;
else
{
@@ -3750,14 +3779,14 @@ elf_fake_sections (bfd *abfd, asection *asect, void *fsarg)
{
if (esd->rel.count && esd->rel.hdr == NULL
&& !_bfd_elf_init_reloc_shdr (abfd, &esd->rel, name,
- false, delay_st_name_p))
+ false, delay_sh_name_p))
{
arg->failed = true;
return;
}
if (esd->rela.count && esd->rela.hdr == NULL
&& !_bfd_elf_init_reloc_shdr (abfd, &esd->rela, name,
- true, delay_st_name_p))
+ true, delay_sh_name_p))
{
arg->failed = true;
return;
@@ -3768,7 +3797,7 @@ elf_fake_sections (bfd *abfd, asection *asect, void *fsarg)
? &esd->rela : &esd->rel),
name,
asect->use_rela_p,
- delay_st_name_p))
+ delay_sh_name_p))
{
arg->failed = true;
return;
@@ -3942,20 +3971,17 @@ bfd_elf_set_group_contents (bfd *abfd, asection *sec, void *failedptrarg)
break;
}
- /* We should always get here with loc == sec->contents + 4, but it is
- possible to craft bogus SHT_GROUP sections that will cause segfaults
- in objcopy without checking loc here and in the loop above. */
- if (loc == sec->contents)
- BFD_ASSERT (0);
- else
+ /* We should always get here with loc == sec->contents + 4. Return
+ an error for bogus SHT_GROUP sections. */
+ loc -= 4;
+ if (loc != sec->contents)
{
- loc -= 4;
- if (loc != sec->contents)
- {
- BFD_ASSERT (0);
- memset (sec->contents + 4, 0, loc - sec->contents);
- loc = sec->contents;
- }
+ /* xgettext:c-format */
+ _bfd_error_handler (_("%pB: corrupted group section: `%pA'"),
+ abfd, sec);
+ bfd_set_error (bfd_error_bad_value);
+ *failedptr = true;
+ return;
}
H_PUT_32 (abfd, sec->flags & SEC_LINK_ONCE ? GRP_COMDAT : 0, loc);
@@ -4473,7 +4499,11 @@ elf_map_symbols (bfd *abfd, unsigned int *pnum_locals)
asection *sec = sym->section;
if (sec->owner != abfd)
- sec = sec->output_section;
+ {
+ sec = sec->output_section;
+ if (sec == NULL)
+ return false;
+ }
sect_syms[sec->index] = syms[idx];
}
@@ -5008,8 +5038,8 @@ _bfd_elf_map_sections_to_segments (bfd *abfd,
&& need_layout != NULL
&& bed->size_relative_relocs
&& !bed->size_relative_relocs (info, need_layout))
- info->callbacks->einfo
- (_("%F%P: failed to size relative relocations\n"));
+ info->callbacks->fatal
+ (_("%P: failed to size relative relocations\n"));
}
if (no_user_phdrs && bfd_count_sections (abfd) != 0)
@@ -5920,8 +5950,7 @@ assign_file_positions_for_load_sections (bfd *abfd,
asection **secpp;
bfd_vma off_adjust; /* Octets. */
bool no_contents;
- bfd_size_type p_align;
- bool p_align_p;
+ bfd_size_type align_pagesize;
/* An ELF segment (described by Elf_Internal_Phdr) may contain a
number of sections with contents contributing to both p_filesz
@@ -5932,8 +5961,6 @@ assign_file_positions_for_load_sections (bfd *abfd,
p = phdrs + m->idx;
p->p_type = m->p_type;
p->p_flags = m->p_flags;
- p_align = bed->p_align;
- p_align_p = false;
if (m->count == 0)
p->p_vaddr = m->p_vaddr_offset * opb;
@@ -5947,6 +5974,7 @@ assign_file_positions_for_load_sections (bfd *abfd,
else
p->p_paddr = (m->sections[0]->lma + m->p_vaddr_offset) * opb;
+ align_pagesize = 0;
if (p->p_type == PT_LOAD
&& (abfd->flags & D_PAGED) != 0)
{
@@ -5960,15 +5988,17 @@ assign_file_positions_for_load_sections (bfd *abfd,
segment. */
if (m->p_align_valid)
maxpagesize = m->p_align;
- else if (p_align != 0
+ else if (bed->p_align != 0
&& (link_info == NULL
|| !link_info->maxpagesize_is_set))
- /* Set p_align to the default p_align value while laying
- out segments aligning to the maximum page size or the
- largest section alignment. The run-time loader can
- align segments to the default p_align value or the
- maximum page size, depending on system page size. */
- p_align_p = true;
+ /* We will lay out this binary using maxpagesize but set
+ p->p_align later to the possibly smaller bed->p_align.
+ The run-time loader will then be able to load this
+ binary when the system page size is maxpagesize, but if
+ the system page size is smaller can use p->p_align.
+ In either case p->p_align will be increased if
+ necessary to match section alignment. */
+ align_pagesize = bed->p_align;
p->p_align = maxpagesize;
}
@@ -6001,22 +6031,20 @@ assign_file_positions_for_load_sections (bfd *abfd,
align_power = secalign;
}
align = (bfd_size_type) 1 << align_power;
+ /* If a section requires alignment higher than the
+ minimum p_align value, don't reduce a maxpagesize
+ p->p_align set earlier in this function. */
+ if (align > bed->p_align)
+ align_pagesize = 0;
if (align < maxpagesize)
- {
- /* If a section requires alignment higher than the
- default p_align value, don't set p_align to the
- default p_align value. */
- if (align > p_align)
- p_align_p = false;
- align = maxpagesize;
- }
+ align = maxpagesize;
else
{
/* If a section requires alignment higher than the
maximum page size, set p_align to the section
alignment. */
- p_align_p = true;
- p_align = align;
+ if ((abfd->flags & D_PAGED) != 0)
+ p->p_align = align;
}
}
@@ -6171,7 +6199,10 @@ assign_file_positions_for_load_sections (bfd *abfd,
align = p->p_align;
if (align < 1)
align = 1;
- p->p_offset = off % align;
+ /* Avoid p_offset of zero, which might be wrongly
+ interpreted as the segment being the first one,
+ containing the file header. PR32763. */
+ p->p_offset = (off + align - 1) % align + 1;
}
}
else
@@ -6185,6 +6216,9 @@ assign_file_positions_for_load_sections (bfd *abfd,
}
}
+ if (align_pagesize)
+ p->p_align = align_pagesize;
+
/* Set up p_filesz, p_memsz, p_align and p_flags from the section
maps. Set filepos for sections in PT_LOAD segments, and in
core files, for sections in PT_NOTE segments.
@@ -6287,27 +6321,28 @@ assign_file_positions_for_load_sections (bfd *abfd,
}
else
{
- if (p->p_type == PT_LOAD)
- {
- this_hdr->sh_offset = sec->filepos = off;
- if (this_hdr->sh_type != SHT_NOBITS)
- off += this_hdr->sh_size;
- }
- else if (this_hdr->sh_type == SHT_NOBITS
- && (this_hdr->sh_flags & SHF_TLS) != 0
- && this_hdr->sh_offset == 0)
+ if (this_hdr->sh_type == SHT_NOBITS
+ && (this_hdr->sh_flags & SHF_TLS) != 0
+ && this_hdr->sh_offset == 0)
{
- /* This is a .tbss section that didn't get a PT_LOAD.
- (See _bfd_elf_map_sections_to_segments "Create a
- final PT_LOAD".) Set sh_offset to the value it
- would have if we had created a zero p_filesz and
- p_memsz PT_LOAD header for the section. This
- also makes the PT_TLS header have the same
- p_offset value. */
+ /* Set sh_offset for .tbss sections to their nominal
+ offset after aligning. They are not loaded from
+ disk so the value doesn't really matter, except
+ when the .tbss section is the first one in a
+ PT_TLS segment. In that case it sets the
+ p_offset for the PT_TLS segment, which according
+ to the ELF gABI ought to satisfy
+ p_offset % p_align == p_vaddr % p_align. */
bfd_vma adjust = vma_page_aligned_bias (this_hdr->sh_addr,
off, align);
this_hdr->sh_offset = sec->filepos = off + adjust;
}
+ else if (p->p_type == PT_LOAD)
+ {
+ this_hdr->sh_offset = sec->filepos = off;
+ if (this_hdr->sh_type != SHT_NOBITS)
+ off += this_hdr->sh_size;
+ }
if (this_hdr->sh_type != SHT_NOBITS)
{
@@ -6403,9 +6438,6 @@ assign_file_positions_for_load_sections (bfd *abfd,
print_segment_map (m);
}
}
-
- if (p_align_p)
- p->p_align = p_align;
}
}
@@ -10389,6 +10421,12 @@ elfcore_grok_xstatereg (bfd *abfd, Elf_Internal_Note *note)
}
static bool
+elfcore_grok_sspreg (bfd *abfd, Elf_Internal_Note *note)
+{
+ return elfcore_make_note_pseudosection (abfd, ".reg-ssp", note);
+}
+
+static bool
elfcore_grok_ppc_vmx (bfd *abfd, Elf_Internal_Note *note)
{
return elfcore_make_note_pseudosection (abfd, ".reg-ppc-vmx", note);
@@ -11083,6 +11121,13 @@ elfcore_grok_note (bfd *abfd, Elf_Internal_Note *note)
else
return true;
+ case NT_X86_SHSTK: /* Linux CET extension. */
+ if (note->namesz == 6
+ && strcmp (note->namedata, "LINUX") == 0)
+ return elfcore_grok_sspreg (abfd, note);
+ else
+ return true;
+
case NT_PPC_VMX:
if (note->namesz == 6
&& strcmp (note->namedata, "LINUX") == 0)
@@ -12533,6 +12578,15 @@ elfcore_write_xstatereg (bfd *abfd, char *buf, int *bufsiz,
note_name, NT_X86_XSTATE, xfpregs, size);
}
+static char *
+elfcore_write_sspreg (bfd *abfd, char *buf, int *bufsiz,
+ const void *ssp, int size)
+{
+ const char *note_name = "LINUX";
+ return elfcore_write_note (abfd, buf, bufsiz,
+ note_name, NT_X86_SHSTK, ssp, size);
+}
+
char *
elfcore_write_x86_segbases (bfd *abfd, char *buf, int *bufsiz,
const void *regs, int size)
@@ -13128,6 +13182,8 @@ elfcore_write_register_note (bfd *abfd,
return elfcore_write_xstatereg (abfd, buf, bufsiz, data, size);
if (strcmp (section, ".reg-x86-segbases") == 0)
return elfcore_write_x86_segbases (abfd, buf, bufsiz, data, size);
+ if (strcmp (section, ".reg-ssp") == 0)
+ return elfcore_write_sspreg (abfd, buf, bufsiz, data, size);
if (strcmp (section, ".reg-ppc-vmx") == 0)
return elfcore_write_ppc_vmx (abfd, buf, bufsiz, data, size);
if (strcmp (section, ".reg-ppc-vsx") == 0)