diff options
Diffstat (limited to 'bfd/elf.c')
-rw-r--r-- | bfd/elf.c | 214 |
1 files changed, 140 insertions, 74 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) @@ -3543,16 +3570,17 @@ elf_fake_sections (bfd *abfd, asection *asect, void *fsarg) && (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 { @@ -3751,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; @@ -3769,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; @@ -3943,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); @@ -4474,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]; } @@ -8346,25 +8375,34 @@ copy_private_bfd_data (bfd *ibfd, bfd *obfd) return rewrite_elf_program_header (ibfd, obfd, maxpagesize); } -/* Initialize private output section information from input section. */ +/* Copy private section information from input to output. This function + is called both by objcopy where LINK_INFO is NULL, and ld where + LINK_INFO is non-NULL in the usual case but NULL for a special case + when dealing with LTO IR or cloning output sections. */ bool -_bfd_elf_init_private_section_data (bfd *ibfd, +_bfd_elf_copy_private_section_data (bfd *ibfd, asection *isec, bfd *obfd, asection *osec, struct bfd_link_info *link_info) - { - Elf_Internal_Shdr *ihdr, *ohdr; - bool final_link = (link_info != NULL - && !bfd_link_relocatable (link_info)); - if (ibfd->xvec->flavour != bfd_target_elf_flavour || obfd->xvec->flavour != bfd_target_elf_flavour) return true; - BFD_ASSERT (elf_section_data (osec) != NULL); + Elf_Internal_Shdr *ihdr = &elf_section_data (isec)->this_hdr; + Elf_Internal_Shdr *ohdr = &elf_section_data (osec)->this_hdr; + if (link_info == NULL) + { + ohdr->sh_entsize = ihdr->sh_entsize; + + if (ihdr->sh_type == SHT_SYMTAB + || ihdr->sh_type == SHT_DYNSYM + || ihdr->sh_type == SHT_GNU_verneed + || ihdr->sh_type == SHT_GNU_verdef) + ohdr->sh_info = ihdr->sh_info; + } /* If this is a known ABI section, ELF section type and flags may have been set up when OSEC was created. For normal sections we @@ -8374,11 +8412,14 @@ _bfd_elf_init_private_section_data (bfd *ibfd, || elf_section_type (osec) == SHT_NOTE || elf_section_type (osec) == SHT_NOBITS) elf_section_type (osec) = SHT_NULL; + /* For objcopy and relocatable link, copy the ELF section type from the input file if the BFD section flags are the same. (If they are different the user may be doing something like "objcopy --set-section-flags .text=alloc,data".) For a final link allow some flags that the linker clears to differ. */ + bool final_link = (link_info != NULL + && !bfd_link_relocatable (link_info)); if (elf_section_type (osec) == SHT_NULL && (osec->flags == isec->flags || (final_link @@ -8416,14 +8457,11 @@ _bfd_elf_init_private_section_data (bfd *ibfd, elf_section_flags (osec) |= (elf_section_flags (isec) & SHF_COMPRESSED); - ihdr = &elf_section_data (isec)->this_hdr; - /* We need to handle elf_linked_to_section for SHF_LINK_ORDER. We don't use the output section of the linked-to section since it may be NULL at this point. */ if ((ihdr->sh_flags & SHF_LINK_ORDER) != 0) { - ohdr = &elf_section_data (osec)->this_hdr; ohdr->sh_flags |= SHF_LINK_ORDER; elf_linked_to_section (osec) = elf_linked_to_section (isec); } @@ -8433,36 +8471,6 @@ _bfd_elf_init_private_section_data (bfd *ibfd, return true; } -/* Copy private section information. This copies over the entsize - field, and sometimes the info field. */ - -bool -_bfd_elf_copy_private_section_data (bfd *ibfd, - asection *isec, - bfd *obfd, - asection *osec) -{ - Elf_Internal_Shdr *ihdr, *ohdr; - - if (ibfd->xvec->flavour != bfd_target_elf_flavour - || obfd->xvec->flavour != bfd_target_elf_flavour) - return true; - - ihdr = &elf_section_data (isec)->this_hdr; - ohdr = &elf_section_data (osec)->this_hdr; - - ohdr->sh_entsize = ihdr->sh_entsize; - - if (ihdr->sh_type == SHT_SYMTAB - || ihdr->sh_type == SHT_DYNSYM - || ihdr->sh_type == SHT_GNU_verneed - || ihdr->sh_type == SHT_GNU_verdef) - ohdr->sh_info = ihdr->sh_info; - - return _bfd_elf_init_private_section_data (ibfd, isec, obfd, osec, - NULL); -} - /* Look at all the SHT_GROUP sections in IBFD, making any adjustments necessary if we are removing either the SHT_GROUP section or any of the group member sections. DISCARDED is the value that a section's @@ -10392,6 +10400,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); @@ -10623,6 +10637,15 @@ elfcore_grok_aarch_zt (bfd *abfd, Elf_Internal_Note *note) return elfcore_make_note_pseudosection (abfd, ".reg-aarch-zt", note); } +/* Convert NOTE into a bfd_section called ".reg-aarch-gcs". Return TRUE if + successful, otherwise return FALSE. */ + +static bool +elfcore_grok_aarch_gcs (bfd *abfd, Elf_Internal_Note *note) +{ + return elfcore_make_note_pseudosection (abfd, ".reg-aarch-gcs", note); +} + static bool elfcore_grok_arc_v2 (bfd *abfd, Elf_Internal_Note *note) { @@ -11086,6 +11109,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) @@ -11359,6 +11389,12 @@ elfcore_grok_note (bfd *abfd, Elf_Internal_Note *note) else return true; + case NT_ARM_GCS: + if (note->namesz == 6 && strcmp (note->namedata, "LINUX") == 0) + return elfcore_grok_aarch_gcs (abfd, note); + else + return true; + case NT_GDB_TDESC: if (note->namesz == 4 && strcmp (note->namedata, "GDB") == 0) @@ -12536,6 +12572,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) @@ -13020,6 +13065,20 @@ elfcore_write_aarch_zt (bfd *abfd, size); } +/* Write the buffer of GCS register values in AARCH_GCS (length SIZE) into + the note buffer BUF and update *BUFSIZ. ABFD is the bfd the note is being + written into. Return a pointer to the new start of the note buffer, to + replace BUF which may no longer be valid. */ + +static char * +elfcore_write_aarch_gcs (bfd *abfd, char *buf, int *bufsiz, + const void *aarch_gcs, int size) +{ + const char *note_name = "LINUX"; + return elfcore_write_note (abfd, buf, bufsiz, note_name, NT_ARM_GCS, + aarch_gcs, size); +} + char * elfcore_write_arc_v2 (bfd *abfd, char *buf, @@ -13131,6 +13190,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) @@ -13207,6 +13268,8 @@ elfcore_write_register_note (bfd *abfd, return elfcore_write_aarch_za (abfd, buf, bufsiz, data, size); if (strcmp (section, ".reg-aarch-zt") == 0) return elfcore_write_aarch_zt (abfd, buf, bufsiz, data, size); + if (strcmp (section, ".reg-aarch-gcs") == 0) + return elfcore_write_aarch_gcs (abfd, buf, bufsiz, data, size); if (strcmp (section, ".reg-arc-v2") == 0) return elfcore_write_arc_v2 (abfd, buf, bufsiz, data, size); if (strcmp (section, ".gdb-tdesc") == 0) @@ -13493,6 +13556,9 @@ _bfd_elf_section_offset (bfd *abfd, case SEC_INFO_TYPE_EH_FRAME: return _bfd_elf_eh_frame_section_offset (abfd, info, sec, offset); + case SEC_INFO_TYPE_SFRAME: + return _bfd_elf_sframe_section_offset (abfd, info, sec, offset); + default: if ((sec->flags & SEC_ELF_REVERSE_COPY) != 0) { |