diff options
Diffstat (limited to 'bfd/elf.c')
-rw-r--r-- | bfd/elf.c | 208 |
1 files changed, 132 insertions, 76 deletions
@@ -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) |