X-Git-Url: http://drtracing.org/?a=blobdiff_plain;f=bfd%2Felf64-sparc.c;h=8d352252b63aba8278f8764f5e4d746e1edf5b5e;hb=18493a005acc8fbccbee4a2b767334eaaf636dd2;hp=b4c04755ce325b3e14bf55aea55a4f5cd80b955e;hpb=f3185997ac0951edac802e29df03dfc0844fda34;p=deliverable%2Fbinutils-gdb.git diff --git a/bfd/elf64-sparc.c b/bfd/elf64-sparc.c index b4c04755ce..8d352252b6 100644 --- a/bfd/elf64-sparc.c +++ b/bfd/elf64-sparc.c @@ -1,5 +1,5 @@ /* SPARC-specific support for 64-bit ELF - Copyright (C) 1993-2018 Free Software Foundation, Inc. + Copyright (C) 1993-2020 Free Software Foundation, Inc. This file is part of BFD, the Binary File Descriptor library. @@ -19,6 +19,7 @@ MA 02110-1301, USA. */ #include "sysdep.h" +#include #include "bfd.h" #include "libbfd.h" #include "elf-bfd.h" @@ -36,13 +37,28 @@ static long elf64_sparc_get_reloc_upper_bound (bfd *abfd ATTRIBUTE_UNUSED, asection *sec) { +#if SIZEOF_LONG == SIZEOF_INT + if (sec->reloc_count >= LONG_MAX / 2 / sizeof (arelent *)) + { + bfd_set_error (bfd_error_file_too_big); + return -1; + } +#endif return (sec->reloc_count * 2 + 1) * sizeof (arelent *); } static long elf64_sparc_get_dynamic_reloc_upper_bound (bfd *abfd) { - return _bfd_elf_get_dynamic_reloc_upper_bound (abfd) * 2; + long ret = _bfd_elf_get_dynamic_reloc_upper_bound (abfd); + if (ret > LONG_MAX / 2) + { + bfd_set_error (bfd_error_file_too_big); + ret = -1; + } + else if (ret > 0) + ret *= 2; + return ret; } /* Read relocations for ASECT from REL_HDR. There are RELOC_COUNT of @@ -63,13 +79,11 @@ elf64_sparc_slurp_one_reloc_table (bfd *abfd, asection *asect, bfd_size_type count; arelent *relents; - allocated = bfd_malloc (rel_hdr->sh_size); + if (bfd_seek (abfd, rel_hdr->sh_offset, SEEK_SET) != 0) + return FALSE; + allocated = _bfd_malloc_and_read (abfd, rel_hdr->sh_size, rel_hdr->sh_size); if (allocated == NULL) - goto error_return; - - if (bfd_seek (abfd, rel_hdr->sh_offset, SEEK_SET) != 0 - || bfd_bread (allocated, rel_hdr->sh_size, abfd) != rel_hdr->sh_size) - goto error_return; + return FALSE; native_relocs = (bfd_byte *) allocated; @@ -97,12 +111,20 @@ elf64_sparc_slurp_one_reloc_table (bfd *abfd, asection *asect, else relent->address = rela.r_offset - asect->vma; - if (ELF64_R_SYM (rela.r_info) == STN_UNDEF - /* PR 17512: file: 996185f8. */ - || (!dynamic && ELF64_R_SYM(rela.r_info) > bfd_get_symcount(abfd)) - || (dynamic - && ELF64_R_SYM(rela.r_info) > bfd_get_dynamic_symcount(abfd))) + if (ELF64_R_SYM (rela.r_info) == STN_UNDEF) relent->sym_ptr_ptr = bfd_abs_section_ptr->symbol_ptr_ptr; + else if (/* PR 17512: file: 996185f8. */ + ELF64_R_SYM (rela.r_info) > (dynamic + ? bfd_get_dynamic_symcount (abfd) + : bfd_get_symcount (abfd))) + { + _bfd_error_handler + /* xgettext:c-format */ + (_("%pB(%pA): relocation %d has invalid symbol index %ld"), + abfd, asect, i, (long) ELF64_R_SYM (rela.r_info)); + bfd_set_error (bfd_error_bad_value); + relent->sym_ptr_ptr = bfd_abs_section_ptr->symbol_ptr_ptr; + } else { asymbol **ps, *s; @@ -139,14 +161,11 @@ elf64_sparc_slurp_one_reloc_table (bfd *abfd, asection *asect, canon_reloc_count (asect) += relent - relents; - if (allocated != NULL) - free (allocated); - + free (allocated); return TRUE; error_return: - if (allocated != NULL) - free (allocated); + free (allocated); return FALSE; } @@ -444,11 +463,6 @@ elf64_sparc_add_symbol_hook (bfd *abfd, struct bfd_link_info *info, { static const char *const stt_types[] = { "NOTYPE", "OBJECT", "FUNCTION" }; - if (ELF_ST_TYPE (sym->st_info) == STT_GNU_IFUNC - && (abfd->flags & DYNAMIC) == 0 - && bfd_get_flavour (info->output_bfd) == bfd_target_elf_flavour) - elf_tdata (info->output_bfd)->has_gnu_symbols |= elf_gnu_symbol_ifunc; - if (ELF_ST_TYPE (sym->st_info) == STT_REGISTER) { int reg; @@ -579,29 +593,6 @@ elf64_sparc_output_arch_syms (bfd *output_bfd ATTRIBUTE_UNUSED, _bfd_sparc_elf_hash_table(info)->app_regs; Elf_Internal_Sym sym; - /* We arranged in size_dynamic_sections to put the STT_REGISTER entries - at the end of the dynlocal list, so they came at the end of the local - symbols in the symtab. Except that they aren't STB_LOCAL, so we need - to back up symtab->sh_info. */ - if (elf_hash_table (info)->dynlocal) - { - bfd * dynobj = elf_hash_table (info)->dynobj; - asection *dynsymsec = bfd_get_linker_section (dynobj, ".dynsym"); - struct elf_link_local_dynamic_entry *e; - - for (e = elf_hash_table (info)->dynlocal; e ; e = e->next) - if (e->input_indx == -1) - break; - if (e) - { - elf_section_data (dynsymsec->output_section)->this_hdr.sh_info - = e->dynindx; - } - } - - if (info->strip == strip_all) - return TRUE; - for (reg = 0; reg < 4; reg++) if (app_regs [reg].name != NULL) { @@ -752,7 +743,7 @@ elf64_sparc_fake_sections (bfd *abfd ATTRIBUTE_UNUSED, { const char *name; - name = bfd_get_section_name (abfd, sec); + name = bfd_section_name (sec); if (strcmp (name, ".stab") == 0) { @@ -789,13 +780,44 @@ elf64_sparc_print_symbol_all (bfd *abfd ATTRIBUTE_UNUSED, void * filep, return symbol->name; } +/* Used to decide how to sort relocs in an optimal manner for the + dynamic linker, before writing them out. */ + static enum elf_reloc_type_class -elf64_sparc_reloc_type_class (const struct bfd_link_info *info ATTRIBUTE_UNUSED, +elf64_sparc_reloc_type_class (const struct bfd_link_info *info, const asection *rel_sec ATTRIBUTE_UNUSED, const Elf_Internal_Rela *rela) { + bfd *abfd = info->output_bfd; + const struct elf_backend_data *bed = get_elf_backend_data (abfd); + struct _bfd_sparc_elf_link_hash_table *htab + = _bfd_sparc_elf_hash_table (info); + BFD_ASSERT (htab != NULL); + + if (htab->elf.dynsym != NULL + && htab->elf.dynsym->contents != NULL) + { + /* Check relocation against STT_GNU_IFUNC symbol if there are + dynamic symbols. */ + unsigned long r_symndx = htab->r_symndx (rela->r_info); + if (r_symndx != STN_UNDEF) + { + Elf_Internal_Sym sym; + if (!bed->s->swap_symbol_in (abfd, + (htab->elf.dynsym->contents + + r_symndx * bed->s->sizeof_sym), + 0, &sym)) + abort (); + + if (ELF_ST_TYPE (sym.st_info) == STT_GNU_IFUNC) + return reloc_class_ifunc; + } + } + switch ((int) ELF64_R_TYPE (rela->r_info)) { + case R_SPARC_IRELATIVE: + return reloc_class_ifunc; case R_SPARC_RELATIVE: return reloc_class_relative; case R_SPARC_JMP_SLOT: