X-Git-Url: https://git.libre-soc.org/?a=blobdiff_plain;f=bfd%2Felf64-sparc.c;h=e9f03cf8e3a86bb79da458726ae3c3e1363c11eb;hb=ddc01737d34f16074b2c9a92c5a808be5c91340f;hp=41e1b7acf7e07b6fccdf04b296921014b13ae27d;hpb=8410d65b77164d020a45cc9aa17a0147dc76862d;p=binutils-gdb.git diff --git a/bfd/elf64-sparc.c b/bfd/elf64-sparc.c index 41e1b7acf7e..e9f03cf8e3a 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-2022 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) { - return (sec->reloc_count * 2 + 1) * sizeof (arelent *); +#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 * 2L + 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 @@ -50,10 +66,10 @@ elf64_sparc_get_dynamic_reloc_upper_bound (bfd *abfd) has secondary addend in ELF64_R_TYPE_DATA. We handle it as two relocations for the same location, R_SPARC_LO10 and R_SPARC_13. */ -static bfd_boolean +static bool elf64_sparc_slurp_one_reloc_table (bfd *abfd, asection *asect, Elf_Internal_Shdr *rel_hdr, - asymbol **symbols, bfd_boolean dynamic) + asymbol **symbols, bool dynamic) { void * allocated = NULL; bfd_byte *native_relocs; @@ -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; @@ -100,17 +114,17 @@ elf64_sparc_slurp_one_reloc_table (bfd *abfd, asection *asect, 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. */ - (!dynamic && ELF64_R_SYM(rela.r_info) > bfd_get_symcount(abfd)) - || (dynamic - && ELF64_R_SYM(rela.r_info) > bfd_get_dynamic_symcount(abfd))) - { - _bfd_error_handler + 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; @@ -147,22 +161,19 @@ elf64_sparc_slurp_one_reloc_table (bfd *abfd, asection *asect, canon_reloc_count (asect) += relent - relents; - if (allocated != NULL) - free (allocated); - - return TRUE; + free (allocated); + return true; error_return: - if (allocated != NULL) - free (allocated); - return FALSE; + free (allocated); + return false; } /* Read in and swap the external relocs. */ -static bfd_boolean +static bool elf64_sparc_slurp_reloc_table (bfd *abfd, asection *asect, - asymbol **symbols, bfd_boolean dynamic) + asymbol **symbols, bool dynamic) { struct bfd_elf_section_data * const d = elf_section_data (asect); Elf_Internal_Shdr *rel_hdr; @@ -170,13 +181,13 @@ elf64_sparc_slurp_reloc_table (bfd *abfd, asection *asect, bfd_size_type amt; if (asect->relocation != NULL) - return TRUE; + return true; if (! dynamic) { if ((asect->flags & SEC_RELOC) == 0 || asect->reloc_count == 0) - return TRUE; + return true; rel_hdr = d->rel.hdr; rel_hdr2 = d->rela.hdr; @@ -191,7 +202,7 @@ elf64_sparc_slurp_reloc_table (bfd *abfd, asection *asect, dynamic symbol table, and in that case bfd_section_from_shdr in elf.c does not update the RELOC_COUNT. */ if (asect->size == 0) - return TRUE; + return true; rel_hdr = &d->this_hdr; asect->reloc_count = NUM_SHDR_ENTRIES (rel_hdr); @@ -202,7 +213,7 @@ elf64_sparc_slurp_reloc_table (bfd *abfd, asection *asect, amt *= 2 * sizeof (arelent); asect->relocation = (arelent *) bfd_alloc (abfd, amt); if (asect->relocation == NULL) - return FALSE; + return false; /* The elf64_sparc_slurp_one_reloc_table routine increments canon_reloc_count. */ @@ -211,14 +222,14 @@ elf64_sparc_slurp_reloc_table (bfd *abfd, asection *asect, if (rel_hdr && !elf64_sparc_slurp_one_reloc_table (abfd, asect, rel_hdr, symbols, dynamic)) - return FALSE; + return false; if (rel_hdr2 && !elf64_sparc_slurp_one_reloc_table (abfd, asect, rel_hdr2, symbols, dynamic)) - return FALSE; + return false; - return TRUE; + return true; } /* Canonicalize the relocs. */ @@ -231,7 +242,7 @@ elf64_sparc_canonicalize_reloc (bfd *abfd, sec_ptr section, unsigned int i; const struct elf_backend_data *bed = get_elf_backend_data (abfd); - if (! bed->s->slurp_reloc_table (abfd, section, symbols, FALSE)) + if (! bed->s->slurp_reloc_table (abfd, section, symbols, false)) return -1; tblptr = section->relocation; @@ -275,7 +286,7 @@ elf64_sparc_canonicalize_dynamic_reloc (bfd *abfd, arelent **storage, arelent *p; long count, i; - if (! elf64_sparc_slurp_reloc_table (abfd, s, syms, TRUE)) + if (! elf64_sparc_slurp_reloc_table (abfd, s, syms, true)) return -1; count = canon_reloc_count (s); p = s->relocation; @@ -307,7 +318,7 @@ elf64_sparc_set_reloc (bfd *abfd ATTRIBUTE_UNUSED, static void elf64_sparc_write_relocs (bfd *abfd, asection *sec, void * data) { - bfd_boolean *failedp = (bfd_boolean *) data; + bool *failedp = (bool *) data; Elf_Internal_Shdr *rela_hdr; bfd_vma addr_offset; Elf64_External_Rela *outbound_relocas, *src_rela; @@ -359,7 +370,7 @@ elf64_sparc_write_relocs (bfd *abfd, asection *sec, void * data) rela_hdr->contents = bfd_alloc (abfd, rela_hdr->sh_size); if (rela_hdr->contents == NULL) { - *failedp = TRUE; + *failedp = true; return; } @@ -397,7 +408,7 @@ elf64_sparc_write_relocs (bfd *abfd, asection *sec, void * data) n = _bfd_elf_symbol_from_bfd_symbol (abfd, &sym); if (n < 0) { - *failedp = TRUE; + *failedp = true; return; } last_sym_idx = n; @@ -407,7 +418,7 @@ elf64_sparc_write_relocs (bfd *abfd, asection *sec, void * data) && (*ptr->sym_ptr_ptr)->the_bfd->xvec != abfd->xvec && ! _bfd_elf_validate_reloc (abfd, ptr)) { - *failedp = TRUE; + *failedp = true; return; } @@ -443,7 +454,7 @@ elf64_sparc_write_relocs (bfd *abfd, asection *sec, void * data) /* Hook called by the linker routine which adds symbols from an object file. We use it for STT_REGISTER symbols. */ -static bfd_boolean +static bool elf64_sparc_add_symbol_hook (bfd *abfd, struct bfd_link_info *info, Elf_Internal_Sym *sym, const char **namep, flagword *flagsp ATTRIBUTE_UNUSED, @@ -466,7 +477,7 @@ elf64_sparc_add_symbol_hook (bfd *abfd, struct bfd_link_info *info, _bfd_error_handler (_("%pB: only registers %%g[2367] can be declared using STT_REGISTER"), abfd); - return FALSE; + return false; } if (info->output_bfd->xvec != abfd->xvec @@ -476,7 +487,7 @@ elf64_sparc_add_symbol_hook (bfd *abfd, struct bfd_link_info *info, If STT_REGISTER comes from a dynamic object, don't put it into the output bfd. The dynamic linker will recheck it. */ *namep = NULL; - return TRUE; + return true; } p = _bfd_sparc_elf_hash_table(info)->app_regs + reg; @@ -489,7 +500,7 @@ elf64_sparc_add_symbol_hook (bfd *abfd, struct bfd_link_info *info, " previously %s in %pB"), (int) sym->st_value, **namep ? *namep : "#scratch", abfd, *p->name ? p->name : "#scratch", p->abfd); - return FALSE; + return false; } if (p->name == NULL) @@ -499,7 +510,7 @@ elf64_sparc_add_symbol_hook (bfd *abfd, struct bfd_link_info *info, struct elf_link_hash_entry *h; h = (struct elf_link_hash_entry *) - bfd_link_hash_lookup (info->hash, *namep, FALSE, FALSE, FALSE); + bfd_link_hash_lookup (info->hash, *namep, false, false, false); if (h != NULL) { @@ -512,13 +523,13 @@ elf64_sparc_add_symbol_hook (bfd *abfd, struct bfd_link_info *info, (_("symbol `%s' has differing types: REGISTER in %pB," " previously %s in %pB"), *namep, abfd, stt_types[type], p->abfd); - return FALSE; + return false; } p->name = bfd_hash_allocate (&info->hash->table, strlen (*namep) + 1); if (!p->name) - return FALSE; + return false; strcpy (p->name, *namep); } @@ -538,7 +549,7 @@ elf64_sparc_add_symbol_hook (bfd *abfd, struct bfd_link_info *info, } } *namep = NULL; - return TRUE; + return true; } else if (*namep && **namep && info->output_bfd->xvec == abfd->xvec) @@ -559,16 +570,16 @@ elf64_sparc_add_symbol_hook (bfd *abfd, struct bfd_link_info *info, (_("Symbol `%s' has differing types: %s in %pB," " previously REGISTER in %pB"), *namep, stt_types[type], abfd, p->abfd); - return FALSE; + return false; } } - return TRUE; + return true; } /* This function takes care of emitting STT_REGISTER symbols which we cannot easily keep in the symbol hash table. */ -static bfd_boolean +static bool elf64_sparc_output_arch_syms (bfd *output_bfd ATTRIBUTE_UNUSED, struct bfd_link_info *info, void * flaginfo, @@ -582,36 +593,13 @@ 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) { if (info->strip == strip_some && bfd_hash_lookup (info->keep_hash, app_regs [reg].name, - FALSE, FALSE) == NULL) + false, false) == NULL) continue; sym.st_value = reg < 2 ? reg + 2 : reg + 4; @@ -624,10 +612,10 @@ elf64_sparc_output_arch_syms (bfd *output_bfd ATTRIBUTE_UNUSED, sym.st_shndx == SHN_ABS ? bfd_abs_section_ptr : bfd_und_section_ptr, NULL) != 1) - return FALSE; + return false; } - return TRUE; + return true; } static int @@ -661,24 +649,24 @@ elf64_sparc_symbol_processing (bfd *abfd ATTRIBUTE_UNUSED, asymbol *asym) /* Merge backend specific data from an object file to the output object file when linking. */ -static bfd_boolean +static bool elf64_sparc_merge_private_bfd_data (bfd *ibfd, struct bfd_link_info *info) { bfd *obfd = info->output_bfd; - bfd_boolean error; + bool error; flagword new_flags, old_flags; int new_mm, old_mm; if (bfd_get_flavour (ibfd) != bfd_target_elf_flavour || bfd_get_flavour (obfd) != bfd_target_elf_flavour) - return TRUE; + return true; new_flags = elf_elfheader (ibfd)->e_flags; old_flags = elf_elfheader (obfd)->e_flags; if (!elf_flags_init (obfd)) /* First call, no flags set */ { - elf_flags_init (obfd) = TRUE; + elf_flags_init (obfd) = true; elf_elfheader (obfd)->e_flags = new_flags; } @@ -687,7 +675,7 @@ elf64_sparc_merge_private_bfd_data (bfd *ibfd, struct bfd_link_info *info) else /* Incompatible flags */ { - error = FALSE; + error = false; #define EF_SPARC_ISA_EXTENSIONS \ (EF_SPARC_SUN_US1 | EF_SPARC_SUN_US3 | EF_SPARC_HAL_R1) @@ -709,7 +697,7 @@ elf64_sparc_merge_private_bfd_data (bfd *ibfd, struct bfd_link_info *info) if ((old_flags & (EF_SPARC_SUN_US1 | EF_SPARC_SUN_US3)) && (old_flags & EF_SPARC_HAL_R1)) { - error = TRUE; + error = true; _bfd_error_handler (_("%pB: linking UltraSPARC specific with HAL specific code"), ibfd); @@ -728,7 +716,7 @@ elf64_sparc_merge_private_bfd_data (bfd *ibfd, struct bfd_link_info *info) /* Warn about any other mismatches */ if (new_flags != old_flags) { - error = TRUE; + error = true; _bfd_error_handler /* xgettext:c-format */ (_("%pB: uses different e_flags (%#x) fields than previous modules (%#x)"), @@ -740,7 +728,7 @@ elf64_sparc_merge_private_bfd_data (bfd *ibfd, struct bfd_link_info *info) if (error) { bfd_set_error (bfd_error_bad_value); - return FALSE; + return false; } } return _bfd_sparc_elf_merge_private_bfd_data (ibfd, info); @@ -748,14 +736,14 @@ elf64_sparc_merge_private_bfd_data (bfd *ibfd, struct bfd_link_info *info) /* MARCO: Set the correct entry size for the .stab section. */ -static bfd_boolean +static bool elf64_sparc_fake_sections (bfd *abfd ATTRIBUTE_UNUSED, Elf_Internal_Shdr *hdr ATTRIBUTE_UNUSED, asection *sec) { const char *name; - name = bfd_get_section_name (abfd, sec); + name = bfd_section_name (sec); if (strcmp (name, ".stab") == 0) { @@ -763,7 +751,7 @@ elf64_sparc_fake_sections (bfd *abfd ATTRIBUTE_UNUSED, elf_section_data (sec)->this_hdr.sh_entsize = 12; } - return TRUE; + return true; } /* Print a STT_REGISTER symbol to file FILE. */ @@ -792,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: @@ -985,4 +1004,24 @@ const struct elf_size_info elf64_sparc_size_info = #undef elf_backend_static_tls_alignment #define elf_backend_static_tls_alignment 16 +#undef elf_backend_strtab_flags +#define elf_backend_strtab_flags SHF_STRINGS + +static bool +elf64_sparc_copy_solaris_special_section_fields (const bfd *ibfd ATTRIBUTE_UNUSED, + bfd *obfd ATTRIBUTE_UNUSED, + const Elf_Internal_Shdr *isection ATTRIBUTE_UNUSED, + Elf_Internal_Shdr *osection ATTRIBUTE_UNUSED) +{ + /* PR 19938: FIXME: Need to add code for setting the sh_info + and sh_link fields of Solaris specific section types. */ + return false; +} + +#undef elf_backend_copy_special_section_fields +#define elf_backend_copy_special_section_fields elf64_sparc_copy_solaris_special_section_fields + #include "elf64-target.h" + +#undef elf_backend_strtab_flags +#undef elf_backend_copy_special_section_fields