X-Git-Url: http://drtracing.org/?a=blobdiff_plain;f=bfd%2Felf32-frv.c;h=5990faaeb93ad96327b32e4da7a73acbb2be0d2e;hb=46a2d504dd875caf60f9be191a55c9ff676bcd5c;hp=5ff7791a8d03417ed192a625d130beaaefc0bd03;hpb=3b36f7e6294151e194b7bf437379e9dcf5b857cb;p=deliverable%2Fbinutils-gdb.git diff --git a/bfd/elf32-frv.c b/bfd/elf32-frv.c index 5ff7791a8d..5990faaeb9 100644 --- a/bfd/elf32-frv.c +++ b/bfd/elf32-frv.c @@ -1,94 +1,44 @@ /* FRV-specific support for 32-bit ELF. - Copyright 2002, 2003, 2004, 2005 Free Software Foundation, Inc. + Copyright (C) 2002-2016 Free Software Foundation, Inc. -This file is part of BFD, the Binary File Descriptor library. + This file is part of BFD, the Binary File Descriptor library. -This program is free software; you can redistribute it and/or modify -it under the terms of the GNU General Public License as published by -the Free Software Foundation; either version 2 of the License, or -(at your option) any later version. + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. -This program is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -GNU General Public License for more details. + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. -You should have received a copy of the GNU General Public License -along with this program; if not, write to the Free Software -Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA 02110-1301, USA. */ + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, + MA 02110-1301, USA. */ -#include "bfd.h" #include "sysdep.h" +#include "bfd.h" #include "libbfd.h" #include "elf-bfd.h" #include "elf/frv.h" -#include "elf/dwarf2.h" +#include "dwarf2.h" #include "hashtab.h" /* Forward declarations. */ -static bfd_reloc_status_type elf32_frv_relocate_lo16 - PARAMS ((bfd *, Elf_Internal_Rela *, bfd_byte *, bfd_vma)); -static bfd_reloc_status_type elf32_frv_relocate_hi16 - PARAMS ((bfd *, Elf_Internal_Rela *, bfd_byte *, bfd_vma)); -static bfd_reloc_status_type elf32_frv_relocate_label24 - PARAMS ((bfd *, asection *, Elf_Internal_Rela *, bfd_byte *, bfd_vma)); -static bfd_reloc_status_type elf32_frv_relocate_gprel12 - PARAMS ((struct bfd_link_info *, bfd *, asection *, Elf_Internal_Rela *, - bfd_byte *, bfd_vma)); -static bfd_reloc_status_type elf32_frv_relocate_gprelu12 - PARAMS ((struct bfd_link_info *, bfd *, asection *, Elf_Internal_Rela *, - bfd_byte *, bfd_vma)); -static bfd_reloc_status_type elf32_frv_relocate_gprello - PARAMS ((struct bfd_link_info *, bfd *, asection *, Elf_Internal_Rela *, - bfd_byte *, bfd_vma)); -static bfd_reloc_status_type elf32_frv_relocate_gprelhi - PARAMS ((struct bfd_link_info *, bfd *, asection *, Elf_Internal_Rela *, - bfd_byte *, bfd_vma)); -static reloc_howto_type *frv_reloc_type_lookup - PARAMS ((bfd *, bfd_reloc_code_real_type)); -static void frv_info_to_howto_rela - PARAMS ((bfd *, arelent *, Elf_Internal_Rela *)); -static bfd_boolean elf32_frv_relocate_section - PARAMS ((bfd *, struct bfd_link_info *, bfd *, asection *, bfd_byte *, - Elf_Internal_Rela *, Elf_Internal_Sym *, asection **)); -static bfd_boolean elf32_frv_add_symbol_hook - PARAMS (( bfd *, struct bfd_link_info *, Elf_Internal_Sym *, - const char **, flagword *, asection **, bfd_vma *)); -static bfd_reloc_status_type frv_final_link_relocate - PARAMS ((reloc_howto_type *, bfd *, asection *, bfd_byte *, - Elf_Internal_Rela *, bfd_vma)); -static bfd_boolean elf32_frv_gc_sweep_hook - PARAMS ((bfd *, struct bfd_link_info *, asection *, const - Elf_Internal_Rela *)); -static asection * elf32_frv_gc_mark_hook - PARAMS ((asection *, struct bfd_link_info *, Elf_Internal_Rela *, - struct elf_link_hash_entry *, Elf_Internal_Sym *)); -static bfd_boolean elf32_frv_check_relocs - PARAMS ((bfd *, struct bfd_link_info *, asection *, - const Elf_Internal_Rela *)); -static int elf32_frv_machine - PARAMS ((bfd *)); -static bfd_boolean elf32_frv_object_p - PARAMS ((bfd *)); -static bfd_boolean frv_elf_set_private_flags - PARAMS ((bfd *, flagword)); -static bfd_boolean frv_elf_copy_private_bfd_data - PARAMS ((bfd *, bfd *)); -static bfd_boolean frv_elf_merge_private_bfd_data - PARAMS ((bfd *, bfd *)); -static bfd_boolean frv_elf_print_private_bfd_data - PARAMS ((bfd *, PTR)); + static reloc_howto_type elf32_frv_howto_table [] = { /* This reloc does nothing. */ HOWTO (R_FRV_NONE, /* type */ 0, /* rightshift */ - 2, /* size (0 = byte, 1 = short, 2 = long) */ - 32, /* bitsize */ + 3, /* size (0 = byte, 1 = short, 2 = long) */ + 0, /* bitsize */ FALSE, /* pc_relative */ 0, /* bitpos */ - complain_overflow_bitfield, /* complain_on_overflow */ + complain_overflow_dont, /* complain_on_overflow */ bfd_elf_generic_reloc, /* special_function */ "R_FRV_NONE", /* name */ FALSE, /* partial_inplace */ @@ -846,8 +796,8 @@ static reloc_howto_type elf32_frv_rel_tlsoff_howto = -extern const bfd_target bfd_elf32_frvfdpic_vec; -#define IS_FDPIC(bfd) ((bfd)->xvec == &bfd_elf32_frvfdpic_vec) +extern const bfd_target frv_elf32_fdpic_vec; +#define IS_FDPIC(bfd) ((bfd)->xvec == &frv_elf32_fdpic_vec) /* An extension of the elf hash table data structure, containing some additional FRV-specific data. */ @@ -882,8 +832,9 @@ struct frvfdpic_elf_link_hash_table /* Get the FRV ELF linker hash table from a link_info structure. */ -#define frvfdpic_hash_table(info) \ - ((struct frvfdpic_elf_link_hash_table *) ((info)->hash)) +#define frvfdpic_hash_table(p) \ + (elf_hash_table_id ((struct elf_link_hash_table *) ((p)->hash)) \ + == FRV_ELF_DATA ? ((struct frvfdpic_elf_link_hash_table *) ((p)->hash)) : NULL) #define frvfdpic_got_section(info) \ (frvfdpic_hash_table (info)->sgot) @@ -1000,12 +951,14 @@ frvfdpic_elf_link_hash_table_create (bfd *abfd) struct frvfdpic_elf_link_hash_table *ret; bfd_size_type amt = sizeof (struct frvfdpic_elf_link_hash_table); - ret = bfd_zalloc (abfd, amt); + ret = bfd_zmalloc (amt); if (ret == NULL) return NULL; - if (! _bfd_elf_link_hash_table_init (&ret->elf, abfd, - _bfd_elf_link_hash_newfunc)) + if (!_bfd_elf_link_hash_table_init (&ret->elf, abfd, + _bfd_elf_link_hash_newfunc, + sizeof (struct elf_link_hash_entry), + FRV_ELF_DATA)) { free (ret); return NULL; @@ -1340,26 +1293,9 @@ _frvfdpic_add_rofixup (bfd *output_bfd, asection *rofixup, bfd_vma offset, static unsigned _frvfdpic_osec_to_segment (bfd *output_bfd, asection *osec) { - struct elf_segment_map *m; - Elf_Internal_Phdr *p; - - /* Find the segment that contains the output_section. */ - for (m = elf_tdata (output_bfd)->segment_map, - p = elf_tdata (output_bfd)->phdr; - m != NULL; - m = m->next, p++) - { - int i; + Elf_Internal_Phdr *p = _bfd_elf_find_segment_containing_section (output_bfd, osec); - for (i = m->count - 1; i >= 0; i--) - if (m->sections[i] == osec) - break; - - if (i >= 0) - break; - } - - return p - elf_tdata (output_bfd)->phdr; + return (p != NULL) ? p - elf_tdata (output_bfd)->phdr : -1; } inline static bfd_boolean @@ -1413,7 +1349,8 @@ _frvfdpic_emit_got_relocs_plt_entries (struct frvfdpic_relocs_info *entry, dynindx = entry->d.h->dynindx; else { - if (sec->output_section + if (sec + && sec->output_section && ! bfd_is_abs_section (sec->output_section) && ! bfd_is_und_section (sec->output_section)) dynindx = elf_section_data (sec->output_section)->dynindx; @@ -1447,7 +1384,7 @@ _frvfdpic_emit_got_relocs_plt_entries (struct frvfdpic_relocs_info *entry, /* If we're linking an executable at a fixed address, we can omit the dynamic relocation as long as the symbol is local to this module. */ - if (info->executable && !info->pie + if (bfd_link_pde (info) && (entry->symndx != -1 || FRVFDPIC_SYM_LOCAL (info, entry->d.h))) { @@ -1502,7 +1439,7 @@ _frvfdpic_emit_got_relocs_plt_entries (struct frvfdpic_relocs_info *entry, if (entry->symndx == -1 && ! FRVFDPIC_FUNCDESC_LOCAL (info, entry->d.h) && FRVFDPIC_SYM_LOCAL (info, entry->d.h) - && !(info->executable && !info->pie)) + && !bfd_link_pde (info)) { reloc = R_FRV_FUNCDESC; idx = elf_section_data (entry->d.h->root.u.def.section @@ -1545,7 +1482,7 @@ _frvfdpic_emit_got_relocs_plt_entries (struct frvfdpic_relocs_info *entry, dynamic symbol entry for the got section, so idx will be zero, which means we can and should compute the address of the private descriptor ourselves. */ - if (info->executable && !info->pie + if (bfd_link_pde (info) && (entry->symndx != -1 || FRVFDPIC_FUNCDESC_LOCAL (info, entry->d.h))) { @@ -1608,7 +1545,7 @@ _frvfdpic_emit_got_relocs_plt_entries (struct frvfdpic_relocs_info *entry, /* If we're linking an executable at a fixed address, we can omit the dynamic relocation as long as the symbol is local to this module. */ - if (info->executable && !info->pie + if (bfd_link_pde (info) && (entry->symndx != -1 || FRVFDPIC_SYM_LOCAL (info, entry->d.h))) { if (sec) @@ -1656,7 +1593,9 @@ _frvfdpic_emit_got_relocs_plt_entries (struct frvfdpic_relocs_info *entry, /* If we've omitted the dynamic relocation, just emit the fixed addresses of the symbol and of the local GOT base offset. */ - if (info->executable && !info->pie && sec && sec->output_section) + if (bfd_link_pde (info) + && sec + && sec->output_section) { lowword = ad; highword = frvfdpic_got_section (info)->output_section->vma @@ -1695,8 +1634,9 @@ _frvfdpic_emit_got_relocs_plt_entries (struct frvfdpic_relocs_info *entry, of the section. For a non-local function, it's disregarded. */ lowword = ad; - if (entry->symndx == -1 && entry->d.h->dynindx != -1 - && entry->d.h->dynindx == idx) + if (sec == NULL + || (entry->symndx == -1 && entry->d.h->dynindx != -1 + && entry->d.h->dynindx == idx)) highword = 0; else highword = _frvfdpic_osec_to_segment @@ -1830,14 +1770,14 @@ _frvfdpic_emit_got_relocs_plt_entries (struct frvfdpic_relocs_info *entry, /* *ABS*+addend is special for TLS relocations, use only the addend. */ - if (info->executable + if (bfd_link_executable (info) && idx == 0 && (bfd_is_abs_section (sec) || bfd_is_und_section (sec))) ; /* If we're linking an executable, we can entirely omit the dynamic relocation if the symbol is local to this module. */ - else if (info->executable + else if (bfd_link_executable (info) && (entry->symndx != -1 || FRVFDPIC_SYM_LOCAL (info, entry->d.h))) { @@ -1903,10 +1843,10 @@ _frvfdpic_emit_got_relocs_plt_entries (struct frvfdpic_relocs_info *entry, /* If we didn't set up a TLS offset entry, but we're linking an executable and the symbol binds locally, we can use the module offset in the TLS descriptor in relaxations. */ - if (info->executable && ! entry->tlsoff_entry) + if (bfd_link_executable (info) && ! entry->tlsoff_entry) entry->tlsoff_entry = entry->tlsdesc_entry + 4; - if (info->executable && !info->pie + if (bfd_link_pde (info) && ((idx == 0 && (bfd_is_abs_section (sec) || bfd_is_und_section (sec))) @@ -2005,7 +1945,7 @@ _frvfdpic_emit_got_relocs_plt_entries (struct frvfdpic_relocs_info *entry, bfd_byte *plt_code = frvfdpic_plt_section (info)->contents + entry->tlsplt_entry; - if (info->executable + if (bfd_link_executable (info) && (entry->symndx != -1 || FRVFDPIC_SYM_LOCAL (info, entry->d.h))) { @@ -2188,14 +2128,12 @@ _frvfdpic_emit_got_relocs_plt_entries (struct frvfdpic_relocs_info *entry, /* Handle an FRV small data reloc. */ static bfd_reloc_status_type -elf32_frv_relocate_gprel12 (info, input_bfd, input_section, relocation, - contents, value) - struct bfd_link_info *info; - bfd *input_bfd; - asection *input_section; - Elf_Internal_Rela *relocation; - bfd_byte *contents; - bfd_vma value; +elf32_frv_relocate_gprel12 (struct bfd_link_info *info, + bfd *input_bfd, + asection *input_section, + Elf_Internal_Rela *relocation, + bfd_byte *contents, + bfd_vma value) { bfd_vma insn; bfd_vma gp; @@ -2227,14 +2165,12 @@ elf32_frv_relocate_gprel12 (info, input_bfd, input_section, relocation, /* Handle an FRV small data reloc. for the u12 field. */ static bfd_reloc_status_type -elf32_frv_relocate_gprelu12 (info, input_bfd, input_section, relocation, - contents, value) - struct bfd_link_info *info; - bfd *input_bfd; - asection *input_section; - Elf_Internal_Rela *relocation; - bfd_byte *contents; - bfd_vma value; +elf32_frv_relocate_gprelu12 (struct bfd_link_info *info, + bfd *input_bfd, + asection *input_section, + Elf_Internal_Rela *relocation, + bfd_byte *contents, + bfd_vma value) { bfd_vma insn; bfd_vma gp; @@ -2269,11 +2205,10 @@ elf32_frv_relocate_gprelu12 (info, input_bfd, input_section, relocation, /* Handle an FRV ELF HI16 reloc. */ static bfd_reloc_status_type -elf32_frv_relocate_hi16 (input_bfd, relhi, contents, value) - bfd *input_bfd; - Elf_Internal_Rela *relhi; - bfd_byte *contents; - bfd_vma value; +elf32_frv_relocate_hi16 (bfd *input_bfd, + Elf_Internal_Rela *relhi, + bfd_byte *contents, + bfd_vma value) { bfd_vma insn; @@ -2292,11 +2227,10 @@ elf32_frv_relocate_hi16 (input_bfd, relhi, contents, value) } static bfd_reloc_status_type -elf32_frv_relocate_lo16 (input_bfd, rello, contents, value) - bfd *input_bfd; - Elf_Internal_Rela *rello; - bfd_byte *contents; - bfd_vma value; +elf32_frv_relocate_lo16 (bfd *input_bfd, + Elf_Internal_Rela *rello, + bfd_byte *contents, + bfd_vma value) { bfd_vma insn; @@ -2317,12 +2251,11 @@ elf32_frv_relocate_lo16 (input_bfd, rello, contents, value) /* Perform the relocation for the CALL label24 instruction. */ static bfd_reloc_status_type -elf32_frv_relocate_label24 (input_bfd, input_section, rello, contents, value) - bfd *input_bfd; - asection *input_section; - Elf_Internal_Rela *rello; - bfd_byte *contents; - bfd_vma value; +elf32_frv_relocate_label24 (bfd *input_bfd, + asection *input_section, + Elf_Internal_Rela *rello, + bfd_byte *contents, + bfd_vma value) { bfd_vma insn; bfd_vma label6; @@ -2360,14 +2293,12 @@ elf32_frv_relocate_label24 (input_bfd, input_section, rello, contents, value) } static bfd_reloc_status_type -elf32_frv_relocate_gprelhi (info, input_bfd, input_section, relocation, - contents, value) - struct bfd_link_info *info; - bfd *input_bfd; - asection *input_section; - Elf_Internal_Rela *relocation; - bfd_byte *contents; - bfd_vma value; +elf32_frv_relocate_gprelhi (struct bfd_link_info *info, + bfd *input_bfd, + asection *input_section, + Elf_Internal_Rela *relocation, + bfd_byte *contents, + bfd_vma value) { bfd_vma insn; bfd_vma gp; @@ -2395,14 +2326,12 @@ elf32_frv_relocate_gprelhi (info, input_bfd, input_section, relocation, } static bfd_reloc_status_type -elf32_frv_relocate_gprello (info, input_bfd, input_section, relocation, - contents, value) - struct bfd_link_info *info; - bfd *input_bfd; - asection *input_section; - Elf_Internal_Rela *relocation; - bfd_byte *contents; - bfd_vma value; +elf32_frv_relocate_gprello (struct bfd_link_info *info, + bfd *input_bfd, + asection *input_section, + Elf_Internal_Rela *relocation, + bfd_byte *contents, + bfd_vma value) { bfd_vma insn; bfd_vma gp; @@ -2431,9 +2360,8 @@ elf32_frv_relocate_gprello (info, input_bfd, input_section, relocation, } static reloc_howto_type * -frv_reloc_type_lookup (abfd, code) - bfd *abfd ATTRIBUTE_UNUSED; - bfd_reloc_code_real_type code; +frv_reloc_type_lookup (bfd *abfd ATTRIBUTE_UNUSED, + bfd_reloc_code_real_type code) { switch (code) { @@ -2590,13 +2518,32 @@ frv_reloc_type_lookup (abfd, code) return NULL; } +static reloc_howto_type * +frv_reloc_name_lookup (bfd *abfd ATTRIBUTE_UNUSED, const char *r_name) +{ + unsigned int i; + + for (i = 0; + i < sizeof (elf32_frv_howto_table) / sizeof (elf32_frv_howto_table[0]); + i++) + if (elf32_frv_howto_table[i].name != NULL + && strcasecmp (elf32_frv_howto_table[i].name, r_name) == 0) + return &elf32_frv_howto_table[i]; + + if (strcasecmp (elf32_frv_vtinherit_howto.name, r_name) == 0) + return &elf32_frv_vtinherit_howto; + if (strcasecmp (elf32_frv_vtentry_howto.name, r_name) == 0) + return &elf32_frv_vtentry_howto; + + return NULL; +} + /* Set the howto pointer for an FRV ELF reloc. */ static void -frv_info_to_howto_rela (abfd, cache_ptr, dst) - bfd *abfd ATTRIBUTE_UNUSED; - arelent *cache_ptr; - Elf_Internal_Rela *dst; +frv_info_to_howto_rela (bfd *abfd ATTRIBUTE_UNUSED, + arelent *cache_ptr, + Elf_Internal_Rela *dst) { unsigned int r_type; @@ -2612,6 +2559,11 @@ frv_info_to_howto_rela (abfd, cache_ptr, dst) break; default: + if (r_type >= (unsigned int) R_FRV_max) + { + _bfd_error_handler (_("%B: invalid FRV reloc number: %d"), abfd, r_type); + r_type = 0; + } cache_ptr->howto = & elf32_frv_howto_table [r_type]; break; } @@ -2657,14 +2609,12 @@ frvfdpic_info_to_howto_rel (bfd *abfd ATTRIBUTE_UNUSED, routines, but a few relocs, we have to do them ourselves. */ static bfd_reloc_status_type -frv_final_link_relocate (howto, input_bfd, input_section, contents, rel, - relocation) - reloc_howto_type *howto; - bfd *input_bfd; - asection *input_section; - bfd_byte *contents; - Elf_Internal_Rela *rel; - bfd_vma relocation; +frv_final_link_relocate (reloc_howto_type *howto, + bfd *input_bfd, + asection *input_section, + bfd_byte *contents, + Elf_Internal_Rela *rel, + bfd_vma relocation) { return _bfd_final_link_relocate (howto, input_bfd, input_section, contents, rel->r_offset, relocation, @@ -2703,16 +2653,14 @@ frv_final_link_relocate (howto, input_bfd, input_section, contents, rel, accordingly. */ static bfd_boolean -elf32_frv_relocate_section (output_bfd, info, input_bfd, input_section, - contents, relocs, local_syms, local_sections) - bfd *output_bfd ATTRIBUTE_UNUSED; - struct bfd_link_info *info; - bfd *input_bfd; - asection *input_section; - bfd_byte *contents; - Elf_Internal_Rela *relocs; - Elf_Internal_Sym *local_syms; - asection **local_sections; +elf32_frv_relocate_section (bfd *output_bfd ATTRIBUTE_UNUSED, + struct bfd_link_info *info, + bfd *input_bfd, + asection *input_section, + bfd_byte *contents, + Elf_Internal_Rela *relocs, + Elf_Internal_Sym *local_syms, + asection **local_sections) { Elf_Internal_Shdr *symtab_hdr; struct elf_link_hash_entry **sym_hashes; @@ -2720,12 +2668,9 @@ elf32_frv_relocate_section (output_bfd, info, input_bfd, input_section, Elf_Internal_Rela *relend; unsigned isec_segment, got_segment, plt_segment, gprel_segment, tls_segment, check_segment[2]; - int silence_segment_error = !(info->shared || info->pie); + int silence_segment_error = !bfd_link_pic (info); unsigned long insn; - if (info->relocatable) - return TRUE; - symtab_hdr = & elf_tdata (input_bfd)->symtab_hdr; sym_hashes = elf_sym_hashes (input_bfd); relend = relocs + input_section->reloc_count; @@ -2765,7 +2710,7 @@ elf32_frv_relocate_section (output_bfd, info, input_bfd, input_section, struct elf_link_hash_entry *h; bfd_vma relocation; bfd_reloc_status_type r; - const char * name = NULL; + const char *name; int r_type; asection *osec; struct frvfdpic_relocs_info *picrel; @@ -2777,7 +2722,6 @@ elf32_frv_relocate_section (output_bfd, info, input_bfd, input_section, || r_type == R_FRV_GNU_VTENTRY) continue; - /* This is a final link. */ r_symndx = ELF32_R_SYM (rel->r_info); howto = elf32_frv_howto_table + ELF32_R_TYPE (rel->r_info); h = NULL; @@ -2792,54 +2736,37 @@ elf32_frv_relocate_section (output_bfd, info, input_bfd, input_section, name = bfd_elf_string_from_elf_section (input_bfd, symtab_hdr->sh_link, sym->st_name); - name = (name == NULL) ? bfd_section_name (input_bfd, sec) : name; + if (name == NULL || name[0] == 0) + name = bfd_section_name (input_bfd, sec); } else { - h = sym_hashes [r_symndx - symtab_hdr->sh_info]; - - while (h->root.type == bfd_link_hash_indirect - || h->root.type == bfd_link_hash_warning) - h = (struct elf_link_hash_entry *) h->root.u.i.link; + bfd_boolean warned, ignored; + bfd_boolean unresolved_reloc; + RELOC_FOR_GLOBAL_SYMBOL (info, input_bfd, input_section, rel, + r_symndx, symtab_hdr, sym_hashes, + h, sec, relocation, + unresolved_reloc, warned, ignored); + osec = sec; name = h->root.root.string; + } - if ((h->root.type == bfd_link_hash_defined - || h->root.type == bfd_link_hash_defweak)) - { - if (/* TLSMOFF forces local binding. */ - r_type != R_FRV_TLSMOFF - && ! FRVFDPIC_SYM_LOCAL (info, h)) - { - sec = NULL; - relocation = 0; - } - else - { - sec = h->root.u.def.section; - relocation = (h->root.u.def.value - + sec->output_section->vma - + sec->output_offset); - } - } - else if (h->root.type == bfd_link_hash_undefweak) - { - relocation = 0; - } - else if (info->unresolved_syms_in_objects == RM_IGNORE - && ELF_ST_VISIBILITY (h->other) == STV_DEFAULT) - relocation = 0; - else - { - if (! ((*info->callbacks->undefined_symbol) - (info, h->root.root.string, input_bfd, - input_section, rel->r_offset, - (info->unresolved_syms_in_objects == RM_GENERATE_ERROR - || ELF_ST_VISIBILITY (h->other))))) - return FALSE; - relocation = 0; - } - osec = sec; + if (sec != NULL && discarded_section (sec)) + RELOC_AGAINST_DISCARDED_SECTION (info, input_bfd, input_section, + rel, 1, relend, howto, 0, contents); + + if (bfd_link_relocatable (info)) + continue; + + if (r_type != R_FRV_TLSMOFF + && h != NULL + && (h->root.type == bfd_link_hash_defined + || h->root.type == bfd_link_hash_defweak) + && !FRVFDPIC_SYM_LOCAL (info, h)) + { + osec = sec = NULL; + relocation = 0; } switch (r_type) @@ -2897,8 +2824,9 @@ elf32_frv_relocate_section (output_bfd, info, input_bfd, input_section, osec, sym, rel->r_addend)) { - (*_bfd_error_handler) - (_("%B(%A+0x%x): relocation to `%s+%x' may have caused the error above"), + info->callbacks->einfo + (_("%H: relocation to `%s+%v'" + " may have caused the error above\n"), input_bfd, input_section, rel->r_offset, name, rel->r_addend); return FALSE; } @@ -2908,11 +2836,15 @@ elf32_frv_relocate_section (output_bfd, info, input_bfd, input_section, default: non_fdpic: picrel = NULL; - if (h && ! FRVFDPIC_SYM_LOCAL (info, h)) + if (h + && ! FRVFDPIC_SYM_LOCAL (info, h) + && _bfd_elf_section_offset (output_bfd, info, input_section, + rel->r_offset) != (bfd_vma) -1) { - info->callbacks->warning - (info, _("relocation references symbol not defined in the module"), - name, input_bfd, input_section, rel->r_offset); + info->callbacks->einfo + (_("%H: relocation references symbol" + " not defined in the module\n"), + input_bfd, input_section, rel->r_offset); return FALSE; } break; @@ -2950,10 +2882,10 @@ elf32_frv_relocate_section (output_bfd, info, input_bfd, input_section, { #define LOCAL_EXEC_P(info, picrel) \ - ((info)->executable \ + (bfd_link_executable (info) \ && (picrel->symndx != -1 || FRVFDPIC_SYM_LOCAL ((info), (picrel)->d.h))) #define INITIAL_EXEC_P(info, picrel) \ - (((info)->executable || (info)->flags & DF_STATIC_TLS) \ + ((bfd_link_executable (info)|| (info)->flags & DF_STATIC_TLS) \ && (picrel)->tlsoff_entry) #define IN_RANGE_FOR_OFST12_P(value) \ @@ -2985,10 +2917,9 @@ elf32_frv_relocate_section (output_bfd, info, input_bfd, input_section, /* Is this a call instruction? */ if ((insn & (unsigned long)0x01fc0000) != 0x003c0000) { - r = info->callbacks->warning - (info, - _("R_FRV_GETTLSOFF not applied to a call instruction"), - name, input_bfd, input_section, rel->r_offset); + info->callbacks->einfo + (_("%H: R_FRV_GETTLSOFF not applied to a call instruction\n"), + input_bfd, input_section, rel->r_offset); return FALSE; } @@ -3027,10 +2958,10 @@ elf32_frv_relocate_section (output_bfd, info, input_bfd, input_section, /* Is this an lddi instruction? */ if ((insn & (unsigned long)0x01fc0000) != 0x00cc0000) { - r = info->callbacks->warning - (info, - _("R_FRV_GOTTLSDESC12 not applied to an lddi instruction"), - name, input_bfd, input_section, rel->r_offset); + info->callbacks->einfo + (_("%H: R_FRV_GOTTLSDESC12" + " not applied to an lddi instruction\n"), + input_bfd, input_section, rel->r_offset); return FALSE; } @@ -3098,10 +3029,10 @@ elf32_frv_relocate_section (output_bfd, info, input_bfd, input_section, /* Is this a sethi instruction? */ if ((insn & (unsigned long)0x01ff0000) != 0x00f80000) { - r = info->callbacks->warning - (info, - _("R_FRV_GOTTLSDESCHI not applied to a sethi instruction"), - name, input_bfd, input_section, rel->r_offset); + info->callbacks->einfo + (_("%H: R_FRV_GOTTLSDESCHI" + " not applied to a sethi instruction\n"), + input_bfd, input_section, rel->r_offset); return FALSE; } @@ -3135,11 +3066,10 @@ elf32_frv_relocate_section (output_bfd, info, input_bfd, input_section, /* Is this a setlo or setlos instruction? */ if ((insn & (unsigned long)0x01f70000) != 0x00f40000) { - r = info->callbacks->warning - (info, - _("R_FRV_GOTTLSDESCLO" - " not applied to a setlo or setlos instruction"), - name, input_bfd, input_section, rel->r_offset); + info->callbacks->einfo + (_("%H: R_FRV_GOTTLSDESCLO" + " not applied to a setlo or setlos instruction\n"), + input_bfd, input_section, rel->r_offset); return FALSE; } @@ -3183,10 +3113,10 @@ elf32_frv_relocate_section (output_bfd, info, input_bfd, input_section, /* Is this an ldd instruction? */ if ((insn & (unsigned long)0x01fc0fc0) != 0x00080140) { - r = info->callbacks->warning - (info, - _("R_FRV_TLSDESC_RELAX not applied to an ldd instruction"), - name, input_bfd, input_section, rel->r_offset); + info->callbacks->einfo + (_("%H: R_FRV_TLSDESC_RELAX" + " not applied to an ldd instruction\n"), + input_bfd, input_section, rel->r_offset); return FALSE; } @@ -3267,11 +3197,10 @@ elf32_frv_relocate_section (output_bfd, info, input_bfd, input_section, /* Is this a calll or callil instruction? */ if ((insn & (unsigned long)0x7ff80fc0) != 0x02300000) { - r = info->callbacks->warning - (info, - _("R_FRV_GETTLSOFF_RELAX" - " not applied to a calll instruction"), - name, input_bfd, input_section, rel->r_offset); + info->callbacks->einfo + (_("%H: R_FRV_GETTLSOFF_RELAX" + " not applied to a calll instruction\n"), + input_bfd, input_section, rel->r_offset); return FALSE; } @@ -3322,10 +3251,10 @@ elf32_frv_relocate_section (output_bfd, info, input_bfd, input_section, /* Is this an ldi instruction? */ if ((insn & (unsigned long)0x01fc0000) != 0x00c80000) { - r = info->callbacks->warning - (info, - _("R_FRV_GOTTLSOFF12 not applied to an ldi instruction"), - name, input_bfd, input_section, rel->r_offset); + info->callbacks->einfo + (_("%H: R_FRV_GOTTLSOFF12" + " not applied to an ldi instruction\n"), + input_bfd, input_section, rel->r_offset); return FALSE; } @@ -3352,10 +3281,10 @@ elf32_frv_relocate_section (output_bfd, info, input_bfd, input_section, /* Is this a sethi instruction? */ if ((insn & (unsigned long)0x01ff0000) != 0x00f80000) { - r = info->callbacks->warning - (info, - _("R_FRV_GOTTLSOFFHI not applied to a sethi instruction"), - name, input_bfd, input_section, rel->r_offset); + info->callbacks->einfo + (_("%H: R_FRV_GOTTLSOFFHI" + " not applied to a sethi instruction\n"), + input_bfd, input_section, rel->r_offset); return FALSE; } @@ -3381,11 +3310,10 @@ elf32_frv_relocate_section (output_bfd, info, input_bfd, input_section, /* Is this a setlo or setlos instruction? */ if ((insn & (unsigned long)0x01f70000) != 0x00f40000) { - r = info->callbacks->warning - (info, - _("R_FRV_GOTTLSOFFLO" - " not applied to a setlo or setlos instruction"), - name, input_bfd, input_section, rel->r_offset); + info->callbacks->einfo + (_("%H: R_FRV_GOTTLSOFFLO" + " not applied to a setlo or setlos instruction\n"), + input_bfd, input_section, rel->r_offset); return FALSE; } @@ -3412,10 +3340,10 @@ elf32_frv_relocate_section (output_bfd, info, input_bfd, input_section, /* Is this an ld instruction? */ if ((insn & (unsigned long)0x01fc0fc0) != 0x00080100) { - r = info->callbacks->warning - (info, - _("R_FRV_TLSOFF_RELAX not applied to an ld instruction"), - name, input_bfd, input_section, rel->r_offset); + info->callbacks->einfo + (_("%H: R_FRV_TLSOFF_RELAX" + " not applied to an ld instruction\n"), + input_bfd, input_section, rel->r_offset); return FALSE; } @@ -3441,7 +3369,7 @@ elf32_frv_relocate_section (output_bfd, info, input_bfd, input_section, with ldi @(grB, #gottlsoff12(symbol+offset), grC. Preserve the packing bit. */ insn = (insn & (unsigned long)0xfe03f000) - | (unsigned long)0x00c80000;; + | (unsigned long)0x00c80000; bfd_put_32 (input_bfd, insn, contents + rel->r_offset); r_type = R_FRV_GOTTLSOFF12; @@ -3457,10 +3385,10 @@ elf32_frv_relocate_section (output_bfd, info, input_bfd, input_section, /* Is this a sethi instruction? */ if ((insn & (unsigned long)0x01ff0000) != 0x00f80000) { - r = info->callbacks->warning - (info, - _("R_FRV_TLSMOFFHI not applied to a sethi instruction"), - name, input_bfd, input_section, rel->r_offset); + info->callbacks->einfo + (_("%H: R_FRV_TLSMOFFHI" + " not applied to a sethi instruction\n"), + input_bfd, input_section, rel->r_offset); return FALSE; } @@ -3484,11 +3412,10 @@ elf32_frv_relocate_section (output_bfd, info, input_bfd, input_section, /* Is this a setlo or setlos instruction? */ if ((insn & (unsigned long)0x01f70000) != 0x00f40000) { - r = info->callbacks->warning - (info, - _("R_FRV_TLSMOFFLO" - " not applied to a setlo or setlos instruction"), - name, input_bfd, input_section, rel->r_offset); + info->callbacks->einfo + (_("R_FRV_TLSMOFFLO" + " not applied to a setlo or setlos instruction\n"), + input_bfd, input_section, rel->r_offset); return FALSE; } @@ -3595,7 +3522,7 @@ elf32_frv_relocate_section (output_bfd, info, input_bfd, input_section, section+offset. */ if (h && ! FRVFDPIC_FUNCDESC_LOCAL (info, h) && FRVFDPIC_SYM_LOCAL (info, h) - && !(info->executable && !info->pie)) + && !bfd_link_pde (info)) { dynindx = elf_section_data (h->root.u.def.section ->output_section)->dynindx; @@ -3606,9 +3533,10 @@ elf32_frv_relocate_section (output_bfd, info, input_bfd, input_section, { if (addend) { - info->callbacks->warning - (info, _("R_FRV_FUNCDESC references dynamic symbol with nonzero addend"), - name, input_bfd, input_section, rel->r_offset); + info->callbacks->einfo + (_("%H: R_FRV_FUNCDESC references dynamic symbol" + " with nonzero addend\n"), + input_bfd, input_section, rel->r_offset); return FALSE; } dynindx = h->dynindx; @@ -3632,7 +3560,7 @@ elf32_frv_relocate_section (output_bfd, info, input_bfd, input_section, dynamic symbol entry for the got section, so idx will be zero, which means we can and should compute the address of the private descriptor ourselves. */ - if (info->executable && !info->pie + if (bfd_link_pde (info) && (!h || FRVFDPIC_FUNCDESC_LOCAL (info, h))) { addend += frvfdpic_got_section (info)->output_section->vma; @@ -3640,51 +3568,61 @@ elf32_frv_relocate_section (output_bfd, info, input_bfd, input_section, input_section->output_section) & (SEC_ALLOC | SEC_LOAD)) == (SEC_ALLOC | SEC_LOAD)) { + bfd_vma offset; + if (_frvfdpic_osec_readonly_p (output_bfd, input_section ->output_section)) { - info->callbacks->warning - (info, - _("cannot emit fixups in read-only section"), - name, input_bfd, input_section, rel->r_offset); + info->callbacks->einfo + (_("%H: cannot emit fixups" + " in read-only section\n"), + input_bfd, input_section, rel->r_offset); return FALSE; } - _frvfdpic_add_rofixup (output_bfd, - frvfdpic_gotfixup_section - (info), - _bfd_elf_section_offset - (output_bfd, info, - input_section, rel->r_offset) - + input_section - ->output_section->vma - + input_section->output_offset, - picrel); + + offset = _bfd_elf_section_offset + (output_bfd, info, + input_section, rel->r_offset); + + if (offset != (bfd_vma)-1) + _frvfdpic_add_rofixup (output_bfd, + frvfdpic_gotfixup_section + (info), + offset + input_section + ->output_section->vma + + input_section->output_offset, + picrel); } } else if ((bfd_get_section_flags (output_bfd, input_section->output_section) & (SEC_ALLOC | SEC_LOAD)) == (SEC_ALLOC | SEC_LOAD)) { + bfd_vma offset; + if (_frvfdpic_osec_readonly_p (output_bfd, input_section ->output_section)) { - info->callbacks->warning - (info, - _("cannot emit dynamic relocations in read-only section"), - name, input_bfd, input_section, rel->r_offset); + info->callbacks->einfo + (_("%H: cannot emit dynamic relocations" + " in read-only section\n"), + input_bfd, input_section, rel->r_offset); return FALSE; } - _frvfdpic_add_dyn_reloc (output_bfd, - frvfdpic_gotrel_section (info), - _bfd_elf_section_offset - (output_bfd, info, - input_section, rel->r_offset) - + input_section - ->output_section->vma - + input_section->output_offset, - r_type, dynindx, addend, picrel); + + offset = _bfd_elf_section_offset + (output_bfd, info, + input_section, rel->r_offset); + + if (offset != (bfd_vma)-1) + _frvfdpic_add_dyn_reloc (output_bfd, + frvfdpic_gotrel_section (info), + offset + input_section + ->output_section->vma + + input_section->output_offset, + r_type, dynindx, addend, picrel); } else addend += frvfdpic_got_section (info)->output_section->vma; @@ -3716,9 +3654,10 @@ elf32_frv_relocate_section (output_bfd, info, input_bfd, input_section, { if (addend && r_type == R_FRV_FUNCDESC_VALUE) { - info->callbacks->warning - (info, _("R_FRV_FUNCDESC_VALUE references dynamic symbol with nonzero addend"), - name, input_bfd, input_section, rel->r_offset); + info->callbacks->einfo + (_("%H: R_FRV_FUNCDESC_VALUE" + " references dynamic symbol with nonzero addend\n"), + input_bfd, input_section, rel->r_offset); return FALSE; } dynindx = h->dynindx; @@ -3743,7 +3682,7 @@ elf32_frv_relocate_section (output_bfd, info, input_bfd, input_section, can omit the dynamic relocation as long as the symbol is defined in the current link unit (which is implied by its output section not being NULL). */ - if (info->executable && !info->pie + if (bfd_link_pde (info) && (!h || FRVFDPIC_SYM_LOCAL (info, h))) { if (osec) @@ -3757,33 +3696,34 @@ elf32_frv_relocate_section (output_bfd, info, input_bfd, input_section, input_section ->output_section)) { - info->callbacks->warning - (info, - _("cannot emit fixups in read-only section"), - name, input_bfd, input_section, rel->r_offset); + info->callbacks->einfo + (_("%H: cannot emit fixups in read-only section\n"), + input_bfd, input_section, rel->r_offset); return FALSE; } if (!h || h->root.type != bfd_link_hash_undefweak) { - _frvfdpic_add_rofixup (output_bfd, - frvfdpic_gotfixup_section - (info), - _bfd_elf_section_offset - (output_bfd, info, - input_section, rel->r_offset) - + input_section - ->output_section->vma - + input_section->output_offset, - picrel); - if (r_type == R_FRV_FUNCDESC_VALUE) - _frvfdpic_add_rofixup - (output_bfd, - frvfdpic_gotfixup_section (info), - _bfd_elf_section_offset - (output_bfd, info, - input_section, rel->r_offset) - + input_section->output_section->vma - + input_section->output_offset + 4, picrel); + bfd_vma offset = _bfd_elf_section_offset + (output_bfd, info, + input_section, rel->r_offset); + + if (offset != (bfd_vma)-1) + { + _frvfdpic_add_rofixup (output_bfd, + frvfdpic_gotfixup_section + (info), + offset + input_section + ->output_section->vma + + input_section->output_offset, + picrel); + if (r_type == R_FRV_FUNCDESC_VALUE) + _frvfdpic_add_rofixup + (output_bfd, + frvfdpic_gotfixup_section (info), + offset + + input_section->output_section->vma + + input_section->output_offset + 4, picrel); + } } } } @@ -3793,25 +3733,30 @@ elf32_frv_relocate_section (output_bfd, info, input_bfd, input_section, input_section->output_section) & (SEC_ALLOC | SEC_LOAD)) == (SEC_ALLOC | SEC_LOAD)) { + bfd_vma offset; + if (_frvfdpic_osec_readonly_p (output_bfd, input_section ->output_section)) { - info->callbacks->warning - (info, - _("cannot emit dynamic relocations in read-only section"), - name, input_bfd, input_section, rel->r_offset); + info->callbacks->einfo + (_("%H: cannot emit dynamic relocations" + " in read-only section\n"), + input_bfd, input_section, rel->r_offset); return FALSE; } - _frvfdpic_add_dyn_reloc (output_bfd, - frvfdpic_gotrel_section (info), - _bfd_elf_section_offset - (output_bfd, info, - input_section, rel->r_offset) - + input_section - ->output_section->vma - + input_section->output_offset, - r_type, dynindx, addend, picrel); + + offset = _bfd_elf_section_offset + (output_bfd, info, + input_section, rel->r_offset); + + if (offset != (bfd_vma)-1) + _frvfdpic_add_dyn_reloc (output_bfd, + frvfdpic_gotrel_section (info), + offset + input_section + ->output_section->vma + + input_section->output_offset, + r_type, dynindx, addend, picrel); } else if (osec) addend += osec->output_section->vma; @@ -3826,7 +3771,7 @@ elf32_frv_relocate_section (output_bfd, info, input_bfd, input_section, /* If we've omitted the dynamic relocation, just emit the fixed addresses of the symbol and of the local GOT base offset. */ - if (info->executable && !info->pie + if (bfd_link_pde (info) && (!h || FRVFDPIC_SYM_LOCAL (info, h))) bfd_put_32 (output_bfd, frvfdpic_got_section (info)->output_section->vma @@ -3953,10 +3898,10 @@ elf32_frv_relocate_section (output_bfd, info, input_bfd, input_section, if (silence_segment_error == 1) silence_segment_error = (strlen (input_bfd->filename) == 6 - && strcmp (input_bfd->filename, "crt0.o") == 0) + && filename_cmp (input_bfd->filename, "crt0.o") == 0) || (strlen (input_bfd->filename) > 6 - && strcmp (input_bfd->filename - + strlen (input_bfd->filename) - 7, + && filename_cmp (input_bfd->filename + + strlen (input_bfd->filename) - 7, "/crt0.o") == 0) ? -1 : 0; if (!silence_segment_error @@ -3965,18 +3910,11 @@ elf32_frv_relocate_section (output_bfd, info, input_bfd, input_section, && !(picrel && picrel->symndx == -1 && picrel->d.h->root.type == bfd_link_hash_undefined)) { - if (info->shared || info->pie) - (*_bfd_error_handler) - (_("%B(%A+0x%lx): reloc against `%s': %s"), - input_bfd, input_section, (long)rel->r_offset, name, - _("relocation references a different segment")); - else - info->callbacks->warning - (info, - _("relocation references a different segment"), - name, input_bfd, input_section, rel->r_offset); + info->callbacks->einfo + (_("%H: reloc against `%s' references a different segment\n"), + input_bfd, input_section, rel->r_offset, name); } - if (!silence_segment_error && (info->shared || info->pie)) + if (!silence_segment_error && bfd_link_pic (info)) return FALSE; elf_elfheader (output_bfd)->e_flags |= EF_FRV_PIC; } @@ -4093,13 +4031,13 @@ elf32_frv_relocate_section (output_bfd, info, input_bfd, input_section, switch (r) { case bfd_reloc_overflow: - r = info->callbacks->reloc_overflow + (*info->callbacks->reloc_overflow) (info, (h ? &h->root : NULL), name, howto->name, (bfd_vma) 0, input_bfd, input_section, rel->r_offset); break; case bfd_reloc_undefined: - r = info->callbacks->undefined_symbol + (*info->callbacks->undefined_symbol) (info, name, input_bfd, input_section, rel->r_offset, TRUE); break; @@ -4122,14 +4060,11 @@ elf32_frv_relocate_section (output_bfd, info, input_bfd, input_section, if (msg) { - (*_bfd_error_handler) - (_("%B(%A+0x%lx): reloc against `%s': %s"), - input_bfd, input_section, (long)rel->r_offset, name, msg); + info->callbacks->einfo + (_("%H: reloc against `%s': %s\n"), + input_bfd, input_section, rel->r_offset, name, msg); return FALSE; } - - if (! r) - return FALSE; } } @@ -4140,70 +4075,37 @@ elf32_frv_relocate_section (output_bfd, info, input_bfd, input_section, relocation. */ static asection * -elf32_frv_gc_mark_hook (sec, info, rel, h, sym) - asection *sec; - struct bfd_link_info *info ATTRIBUTE_UNUSED; - Elf_Internal_Rela *rel; - struct elf_link_hash_entry *h; - Elf_Internal_Sym *sym; +elf32_frv_gc_mark_hook (asection *sec, + struct bfd_link_info *info, + Elf_Internal_Rela *rel, + struct elf_link_hash_entry *h, + Elf_Internal_Sym *sym) { if (h != NULL) - { - switch (ELF32_R_TYPE (rel->r_info)) - { - case R_FRV_GNU_VTINHERIT: - case R_FRV_GNU_VTENTRY: - break; - - default: - switch (h->root.type) - { - default: - break; - - case bfd_link_hash_defined: - case bfd_link_hash_defweak: - return h->root.u.def.section; - - case bfd_link_hash_common: - return h->root.u.c.p->section; - } - } - } - else - return bfd_section_from_elf_index (sec->owner, sym->st_shndx); - - return NULL; -} - -/* Update the got entry reference counts for the section being removed. */ + switch (ELF32_R_TYPE (rel->r_info)) + { + case R_FRV_GNU_VTINHERIT: + case R_FRV_GNU_VTENTRY: + return NULL; + } -static bfd_boolean -elf32_frv_gc_sweep_hook (abfd, info, sec, relocs) - bfd *abfd ATTRIBUTE_UNUSED; - struct bfd_link_info *info ATTRIBUTE_UNUSED; - asection *sec ATTRIBUTE_UNUSED; - const Elf_Internal_Rela *relocs ATTRIBUTE_UNUSED; -{ - return TRUE; + return _bfd_elf_gc_mark_hook (sec, info, rel, h, sym); } - /* Hook called by the linker routine which adds symbols from an object file. We use it to put .comm items in .scomm, and not .comm. */ static bfd_boolean -elf32_frv_add_symbol_hook (abfd, info, sym, namep, flagsp, secp, valp) - bfd *abfd; - struct bfd_link_info *info; - Elf_Internal_Sym *sym; - const char **namep ATTRIBUTE_UNUSED; - flagword *flagsp ATTRIBUTE_UNUSED; - asection **secp; - bfd_vma *valp; +elf32_frv_add_symbol_hook (bfd *abfd, + struct bfd_link_info *info, + Elf_Internal_Sym *sym, + const char **namep ATTRIBUTE_UNUSED, + flagword *flagsp ATTRIBUTE_UNUSED, + asection **secp, + bfd_vma *valp) { if (sym->st_shndx == SHN_COMMON - && !info->relocatable + && !bfd_link_relocatable (info) && (int)sym->st_size <= (int)bfd_get_gp_size (abfd)) { /* Common symbols less than or equal to -G nn bytes are @@ -4268,8 +4170,8 @@ _frv_create_got_section (bfd *abfd, struct bfd_link_info *info) int offset; /* This function may be called more than once. */ - s = bfd_get_section_by_name (abfd, ".got"); - if (s != NULL && (s->flags & SEC_LINKER_CREATED) != 0) + s = bfd_get_linker_section (abfd, ".got"); + if (s != NULL) return TRUE; /* Machine specific: although pointers are 32-bits wide, we want the @@ -4282,14 +4184,14 @@ _frv_create_got_section (bfd *abfd, struct bfd_link_info *info) | SEC_LINKER_CREATED); pltflags = flags; - s = bfd_make_section_with_flags (abfd, ".got", flags); + s = bfd_make_section_anyway_with_flags (abfd, ".got", flags); if (s == NULL || !bfd_set_section_alignment (abfd, s, ptralign)) return FALSE; if (bed->want_got_plt) { - s = bfd_make_section_with_flags (abfd, ".got.plt", flags); + s = bfd_make_section_anyway_with_flags (abfd, ".got.plt", flags); if (s == NULL || !bfd_set_section_alignment (abfd, s, ptralign)) return FALSE; @@ -4301,22 +4203,15 @@ _frv_create_got_section (bfd *abfd, struct bfd_link_info *info) (or .got.plt) section. We don't do this in the linker script because we don't want to define the symbol if we are not creating a global offset table. */ - bh = NULL; - if (!(_bfd_generic_link_add_one_symbol - (info, abfd, "_GLOBAL_OFFSET_TABLE_", BSF_GLOBAL, s, - 0, (const char *) NULL, FALSE, bed->collect, &bh))) + h = _bfd_elf_define_linkage_sym (abfd, info, s, "_GLOBAL_OFFSET_TABLE_"); + elf_hash_table (info)->hgot = h; + if (h == NULL) return FALSE; - h = (struct elf_link_hash_entry *) bh; - h->def_regular = 1; - h->type = STT_OBJECT; - /* h->other = STV_HIDDEN; */ /* Should we? */ /* Machine-specific: we want the symbol for executables as well. */ if (! bfd_elf_link_record_dynamic_symbol (info, h)) return FALSE; - - elf_hash_table (info)->hgot = h; } /* The first bit of the global offset table is the header. */ @@ -4334,8 +4229,8 @@ _frv_create_got_section (bfd *abfd, struct bfd_link_info *info) if (! frvfdpic_relocs_info (info)) return FALSE; - s = bfd_make_section_with_flags (abfd, ".rel.got", - (flags | SEC_READONLY)); + s = bfd_make_section_anyway_with_flags (abfd, ".rel.got", + (flags | SEC_READONLY)); if (s == NULL || ! bfd_set_section_alignment (abfd, s, 2)) return FALSE; @@ -4343,8 +4238,8 @@ _frv_create_got_section (bfd *abfd, struct bfd_link_info *info) frvfdpic_gotrel_section (info) = s; /* Machine-specific. */ - s = bfd_make_section_with_flags (abfd, ".rofixup", - (flags | SEC_READONLY)); + s = bfd_make_section_anyway_with_flags (abfd, ".rofixup", + (flags | SEC_READONLY)); if (s == NULL || ! bfd_set_section_alignment (abfd, s, 2)) return FALSE; @@ -4392,37 +4287,27 @@ _frv_create_got_section (bfd *abfd, struct bfd_link_info *info) if (bed->plt_readonly) pltflags |= SEC_READONLY; - s = bfd_make_section_with_flags (abfd, ".plt", pltflags); + s = bfd_make_section_anyway_with_flags (abfd, ".plt", pltflags); if (s == NULL || ! bfd_set_section_alignment (abfd, s, bed->plt_alignment)) return FALSE; /* FRV-specific: remember it. */ frvfdpic_plt_section (info) = s; + /* Define the symbol _PROCEDURE_LINKAGE_TABLE_ at the start of the + .plt section. */ if (bed->want_plt_sym) { - /* Define the symbol _PROCEDURE_LINKAGE_TABLE_ at the start of the - .plt section. */ - struct elf_link_hash_entry *h; - struct bfd_link_hash_entry *bh = NULL; - - if (! (_bfd_generic_link_add_one_symbol - (info, abfd, "_PROCEDURE_LINKAGE_TABLE_", BSF_GLOBAL, s, 0, NULL, - FALSE, get_elf_backend_data (abfd)->collect, &bh))) - return FALSE; - h = (struct elf_link_hash_entry *) bh; - h->def_regular = 1; - h->type = STT_OBJECT; - /* h->other = STV_HIDDEN; */ /* Should we? */ - - if (! info->executable - && ! bfd_elf_link_record_dynamic_symbol (info, h)) + h = _bfd_elf_define_linkage_sym (abfd, info, s, + "_PROCEDURE_LINKAGE_TABLE_"); + elf_hash_table (info)->hplt = h; + if (h == NULL) return FALSE; } /* FRV-specific: we want rel relocations for the plt. */ - s = bfd_make_section_with_flags (abfd, ".rel.plt", - flags | SEC_READONLY); + s = bfd_make_section_anyway_with_flags (abfd, ".rel.plt", + flags | SEC_READONLY); if (s == NULL || ! bfd_set_section_alignment (abfd, s, bed->s->log_file_align)) return FALSE; @@ -4469,8 +4354,8 @@ elf32_frvfdpic_create_dynamic_sections (bfd *abfd, struct bfd_link_info *info) image and use a R_*_COPY reloc to tell the dynamic linker to initialize them at run time. The linker script puts the .dynbss section into the .bss section of the final image. */ - s = bfd_make_section_with_flags (abfd, ".dynbss", - SEC_ALLOC | SEC_LINKER_CREATED); + s = bfd_make_section_anyway_with_flags (abfd, ".dynbss", + SEC_ALLOC | SEC_LINKER_CREATED); if (s == NULL) return FALSE; @@ -4485,12 +4370,12 @@ elf32_frvfdpic_create_dynamic_sections (bfd *abfd, struct bfd_link_info *info) be needed, we can discard it later. We will never need this section when generating a shared object, since they do not use copy relocs. */ - if (! info->shared) + if (! bfd_link_pic (info)) { - s = bfd_make_section_with_flags (abfd, - (bed->default_use_rela_p - ? ".rela.bss" : ".rel.bss"), - flags | SEC_READONLY); + s = bfd_make_section_anyway_with_flags (abfd, + (bed->default_use_rela_p + ? ".rela.bss" : ".rel.bss"), + flags | SEC_READONLY); if (s == NULL || ! bfd_set_section_alignment (abfd, s, bed->s->log_file_align)) return FALSE; @@ -4622,7 +4507,7 @@ _frvfdpic_count_relocs_fixups (struct frvfdpic_relocs_info *entry, { bfd_vma relocs = 0, fixups = 0, tlsrets = 0; - if (!dinfo->info->executable || dinfo->info->pie) + if (!bfd_link_pde (dinfo->info)) { relocs = entry->relocs32 + entry->relocsfd + entry->relocsfdv + entry->relocstlsd; @@ -4634,7 +4519,7 @@ _frvfdpic_count_relocs_fixups (struct frvfdpic_relocs_info *entry, emit dynamic relocations even for local symbols, because we don't know the module id the library is going to get at run-time, nor its TLS base offset. */ - if (!dinfo->info->executable + if (!bfd_link_executable (dinfo->info) || (entry->symndx == -1 && ! FRVFDPIC_SYM_LOCAL (dinfo->info, entry->d.h))) relocs += entry->relocstlsoff; @@ -4693,7 +4578,7 @@ _frvfdpic_relax_tls_entries (struct frvfdpic_relocs_info *entry, { bfd_boolean changed = ! relaxing; - BFD_ASSERT (dinfo->info->executable + BFD_ASSERT (bfd_link_executable (dinfo->info) || (dinfo->info->flags & DF_STATIC_TLS)); if (entry->tlsdesc12 || entry->tlsdesclos || entry->tlsdeschilo) @@ -4712,7 +4597,7 @@ _frvfdpic_relax_tls_entries (struct frvfdpic_relocs_info *entry, to GOTTLSOFF, we must keep the GOT entry in range. We know it has to fit because we'll be trading the 4 words of hte TLS descriptor for a single word in the same range. */ - if (! dinfo->info->executable + if (! bfd_link_executable (dinfo->info) || (entry->symndx == -1 && ! FRVFDPIC_SYM_LOCAL (dinfo->info, entry->d.h))) { @@ -4736,7 +4621,7 @@ _frvfdpic_relax_tls_entries (struct frvfdpic_relocs_info *entry, do better than this. */ if ((entry->tlsplt || entry->tlsoff12 || entry->tlsofflos || entry->tlsoffhilo) - && dinfo->info->executable && relaxing + && bfd_link_executable (dinfo->info) && relaxing && ((entry->symndx == -1 && FRVFDPIC_SYM_LOCAL (dinfo->info, entry->d.h) /* The above may hold for an undefweak TLS symbol, so make @@ -4752,7 +4637,7 @@ _frvfdpic_relax_tls_entries (struct frvfdpic_relocs_info *entry, + 32768) < (bfd_vma)65536)) || (entry->symndx != -1 && (elf_hash_table (dinfo->info)->tls_sec->size - + abs (entry->addend) < 32768 + FRVFDPIC_TLS_BIAS)))) + + entry->addend < 32768 + FRVFDPIC_TLS_BIAS)))) { if (! changed) { @@ -4809,7 +4694,8 @@ _frvfdpic_count_got_plt_entries (void **entryp, void *dinfo_) _frvfdpic_count_nontls_entries (entry, dinfo); - if (dinfo->info->executable || (dinfo->info->flags & DF_STATIC_TLS)) + if (bfd_link_executable (dinfo->info) + || (dinfo->info->flags & DF_STATIC_TLS)) _frvfdpic_relax_tls_entries (entry, dinfo, FALSE); else { @@ -5202,7 +5088,7 @@ _frvfdpic_assign_plt_entries (void **entryp, void *info_) entry->tlsplt_entry = frvfdpic_plt_section (dinfo->g.info)->size; - if (dinfo->g.info->executable + if (bfd_link_executable (dinfo->g.info) && (entry->symndx != -1 || FRVFDPIC_SYM_LOCAL (dinfo->g.info, entry->d.h))) { @@ -5553,9 +5439,9 @@ elf32_frvfdpic_size_dynamic_sections (bfd *output_bfd, if (elf_hash_table (info)->dynamic_sections_created) { /* Set the contents of the .interp section to the interpreter. */ - if (info->executable) + if (bfd_link_executable (info) && !info->nointerp) { - s = bfd_get_section_by_name (dynobj, ".interp"); + s = bfd_get_linker_section (dynobj, ".interp"); BFD_ASSERT (s != NULL); s->size = sizeof ELF_DYNAMIC_INTERPRETER; s->contents = (bfd_byte *) ELF_DYNAMIC_INTERPRETER; @@ -5612,42 +5498,121 @@ static bfd_boolean elf32_frvfdpic_always_size_sections (bfd *output_bfd, struct bfd_link_info *info) { - if (!info->relocatable) + if (!bfd_link_relocatable (info) + && !bfd_elf_stack_segment_size (output_bfd, info, + "__stacksize", DEFAULT_STACK_SIZE)) + return FALSE; + + return TRUE; +} + +/* Check whether any of the relocations was optimized away, and + subtract it from the relocation or fixup count. */ +static bfd_boolean +_frvfdpic_check_discarded_relocs (bfd *abfd, asection *sec, + struct bfd_link_info *info, + + bfd_boolean *changed) +{ + Elf_Internal_Shdr *symtab_hdr; + struct elf_link_hash_entry **sym_hashes; + Elf_Internal_Rela *rel, *erel; + + if ((sec->flags & SEC_RELOC) == 0 + || sec->reloc_count == 0) + return TRUE; + + symtab_hdr = &elf_tdata (abfd)->symtab_hdr; + sym_hashes = elf_sym_hashes (abfd); + + rel = elf_section_data (sec)->relocs; + + /* Now examine each relocation. */ + for (erel = rel + sec->reloc_count; rel < erel; rel++) { struct elf_link_hash_entry *h; - asection *sec; + unsigned long r_symndx; + struct frvfdpic_relocs_info *picrel; + struct _frvfdpic_dynamic_got_info *dinfo; + + if (ELF32_R_TYPE (rel->r_info) != R_FRV_32 + && ELF32_R_TYPE (rel->r_info) != R_FRV_FUNCDESC) + continue; - /* Force a PT_GNU_STACK segment to be created. */ - if (! elf_tdata (output_bfd)->stack_flags) - elf_tdata (output_bfd)->stack_flags = PF_R | PF_W | PF_X; + if (_bfd_elf_section_offset (sec->output_section->owner, + info, sec, rel->r_offset) + != (bfd_vma)-1) + continue; - /* Define __stacksize if it's not defined yet. */ - h = elf_link_hash_lookup (elf_hash_table (info), "__stacksize", - FALSE, FALSE, FALSE); - if (! h || h->root.type != bfd_link_hash_defined - || h->type != STT_OBJECT - || !h->def_regular) + r_symndx = ELF32_R_SYM (rel->r_info); + if (r_symndx < symtab_hdr->sh_info) + h = NULL; + else { - struct bfd_link_hash_entry *bh = NULL; + h = sym_hashes[r_symndx - symtab_hdr->sh_info]; + while (h->root.type == bfd_link_hash_indirect + || h->root.type == bfd_link_hash_warning) + h = (struct elf_link_hash_entry *)h->root.u.i.link; + } - if (!(_bfd_generic_link_add_one_symbol - (info, output_bfd, "__stacksize", - BSF_GLOBAL, bfd_abs_section_ptr, DEFAULT_STACK_SIZE, - (const char *) NULL, FALSE, - get_elf_backend_data (output_bfd)->collect, &bh))) - return FALSE; + if (h != NULL) + picrel = frvfdpic_relocs_info_for_global (frvfdpic_relocs_info (info), + abfd, h, + rel->r_addend, NO_INSERT); + else + picrel = frvfdpic_relocs_info_for_local (frvfdpic_relocs_info (info), + abfd, r_symndx, + rel->r_addend, NO_INSERT); - h = (struct elf_link_hash_entry *) bh; - h->def_regular = 1; - h->type = STT_OBJECT; - /* This one must NOT be hidden. */ - } + if (! picrel) + return FALSE; + + *changed = TRUE; + dinfo = frvfdpic_dynamic_got_plt_info (info); + + _frvfdpic_count_relocs_fixups (picrel, dinfo, TRUE); + if (ELF32_R_TYPE (rel->r_info) == R_FRV_32) + picrel->relocs32--; + else /* we know (ELF32_R_TYPE (rel->r_info) == R_FRV_FUNCDESC) */ + picrel->relocsfd--; + _frvfdpic_count_relocs_fixups (picrel, dinfo, FALSE); + } + + return TRUE; +} - /* Create a stack section, and set its alignment. */ - sec = bfd_make_section (output_bfd, ".stack"); +static bfd_boolean +frvfdpic_elf_discard_info (bfd *ibfd, + struct elf_reloc_cookie *cookie ATTRIBUTE_UNUSED, + struct bfd_link_info *info) +{ + bfd_boolean changed = FALSE; + asection *s; + bfd *obfd = NULL; + + /* Account for relaxation of .eh_frame section. */ + for (s = ibfd->sections; s; s = s->next) + if (s->sec_info_type == SEC_INFO_TYPE_EH_FRAME) + { + if (!_frvfdpic_check_discarded_relocs (ibfd, s, info, &changed)) + return FALSE; + obfd = s->output_section->owner; + } + + if (changed) + { + struct _frvfdpic_dynamic_got_plt_info gpinfo; + + memset (&gpinfo, 0, sizeof (gpinfo)); + memcpy (&gpinfo.g, frvfdpic_dynamic_got_plt_info (info), + sizeof (gpinfo.g)); + + /* Clear GOT and PLT assignments. */ + htab_traverse (frvfdpic_relocs_info (info), + _frvfdpic_reset_got_plt_entries, + NULL); - if (sec == NULL - || ! bfd_set_section_alignment (output_bfd, sec, 3)) + if (!_frvfdpic_size_got_plt (obfd, &gpinfo)) return FALSE; } @@ -5675,6 +5640,10 @@ elf32_frvfdpic_relax_section (bfd *abfd ATTRIBUTE_UNUSED, asection *sec, { struct _frvfdpic_dynamic_got_plt_info gpinfo; + if (bfd_link_relocatable (info)) + (*info->callbacks->einfo) + (_("%P%F: --relax and -r may not be used together\n")); + /* If we return early, we didn't change anything. */ *again = FALSE; @@ -5684,7 +5653,7 @@ elf32_frvfdpic_relax_section (bfd *abfd ATTRIBUTE_UNUSED, asection *sec, /* We can only relax when linking the main executable or a library that can't be dlopened. */ - if (! info->executable && ! (info->flags & DF_STATIC_TLS)) + if (! bfd_link_executable (info) && ! (info->flags & DF_STATIC_TLS)) return TRUE; /* If there isn't a TLS section for this binary, we can't do @@ -5729,54 +5698,6 @@ elf32_frvfdpic_relax_section (bfd *abfd ATTRIBUTE_UNUSED, asection *sec, return TRUE; } -static bfd_boolean -elf32_frvfdpic_modify_segment_map (bfd *output_bfd, - struct bfd_link_info *info) -{ - struct elf_segment_map *m; - - /* objcopy and strip preserve what's already there using - elf32_frvfdpic_copy_private_bfd_data (). */ - if (! info) - return TRUE; - - for (m = elf_tdata (output_bfd)->segment_map; m != NULL; m = m->next) - if (m->p_type == PT_GNU_STACK) - break; - - if (m) - { - asection *sec = bfd_get_section_by_name (output_bfd, ".stack"); - struct elf_link_hash_entry *h; - - if (sec) - { - /* Obtain the pointer to the __stacksize symbol. */ - h = elf_link_hash_lookup (elf_hash_table (info), "__stacksize", - FALSE, FALSE, FALSE); - while (h->root.type == bfd_link_hash_indirect - || h->root.type == bfd_link_hash_warning) - h = (struct elf_link_hash_entry *)h->root.u.i.link; - BFD_ASSERT (h->root.type == bfd_link_hash_defined); - - /* Set the section size from the symbol value. We - intentionally ignore the symbol section. */ - if (h->root.type == bfd_link_hash_defined) - sec->size = h->root.u.def.value; - else - sec->size = DEFAULT_STACK_SIZE; - - /* Add the stack section to the PT_GNU_STACK segment, - such that its size and alignment requirements make it - to the segment. */ - m->sections[m->count] = sec; - m->count++; - } - } - - return TRUE; -} - /* Fill in code and data in dynamic sections. */ static bfd_boolean @@ -5821,8 +5742,8 @@ elf32_frvfdpic_finish_dynamic_sections (bfd *output_bfd, != (frvfdpic_gotfixup_section (info)->reloc_count * 4)) { error: - (*_bfd_error_handler) - ("LINKER BUG: .rofixup section size mismatch"); + info->callbacks->einfo + ("LINKER BUG: .rofixup section size mismatch\n"); return FALSE; } @@ -5830,7 +5751,8 @@ elf32_frvfdpic_finish_dynamic_sections (bfd *output_bfd, FALSE, FALSE, TRUE); if (hend && (hend->type == bfd_link_hash_defined - || hend->type == bfd_link_hash_defweak)) + || hend->type == bfd_link_hash_defweak) + && hend->u.def.section->output_section != NULL) { bfd_vma value = frvfdpic_gotfixup_section (info)->output_section->vma @@ -5857,7 +5779,7 @@ elf32_frvfdpic_finish_dynamic_sections (bfd *output_bfd, Elf32_External_Dyn * dyncon; Elf32_External_Dyn * dynconend; - sdyn = bfd_get_section_by_name (dynobj, ".dynamic"); + sdyn = bfd_get_linker_section (dynobj, ".dynamic"); BFD_ASSERT (sdyn != NULL); @@ -6094,27 +6016,23 @@ frvfdpic_elf_encode_eh_address (bfd *abfd, Given infinite time and money... :-) */ static bfd_boolean -elf32_frv_check_relocs (abfd, info, sec, relocs) - bfd *abfd; - struct bfd_link_info *info; - asection *sec; - const Elf_Internal_Rela *relocs; +elf32_frv_check_relocs (bfd *abfd, + struct bfd_link_info *info, + asection *sec, + const Elf_Internal_Rela *relocs) { Elf_Internal_Shdr *symtab_hdr; - struct elf_link_hash_entry **sym_hashes, **sym_hashes_end; + struct elf_link_hash_entry **sym_hashes; const Elf_Internal_Rela *rel; const Elf_Internal_Rela *rel_end; bfd *dynobj; struct frvfdpic_relocs_info *picrel; - if (info->relocatable) + if (bfd_link_relocatable (info)) return TRUE; symtab_hdr = &elf_tdata (abfd)->symtab_hdr; sym_hashes = elf_sym_hashes (abfd); - sym_hashes_end = sym_hashes + symtab_hdr->sh_size/sizeof(Elf32_External_Sym); - if (!elf_bad_symtab (abfd)) - sym_hashes_end -= symtab_hdr->sh_info; dynobj = elf_hash_table (info)->dynobj; rel_end = relocs + sec->reloc_count; @@ -6127,7 +6045,16 @@ elf32_frv_check_relocs (abfd, info, sec, relocs) if (r_symndx < symtab_hdr->sh_info) h = NULL; else - h = sym_hashes[r_symndx - symtab_hdr->sh_info]; + { + h = sym_hashes[r_symndx - symtab_hdr->sh_info]; + while (h->root.type == bfd_link_hash_indirect + || h->root.type == bfd_link_hash_warning) + h = (struct elf_link_hash_entry *) h->root.u.i.link; + + /* PR15323, ref flags aren't set for references in the same + object. */ + h->root.non_ir_ref = 1; + } switch (ELF32_R_TYPE (rel->r_info)) { @@ -6317,7 +6244,9 @@ elf32_frv_check_relocs (abfd, info, sec, relocs) /* This relocation describes which C++ vtable entries are actually used. Record for later use during GC. */ case R_FRV_GNU_VTENTRY: - if (!bfd_elf_gc_record_vtentry (abfd, sec, h, rel->r_addend)) + BFD_ASSERT (h != NULL); + if (h != NULL + && !bfd_elf_gc_record_vtentry (abfd, sec, h, rel->r_addend)) return FALSE; break; @@ -6336,8 +6265,8 @@ elf32_frv_check_relocs (abfd, info, sec, relocs) default: bad_reloc: - (*_bfd_error_handler) - (_("%B: unsupported relocation type %i"), + info->callbacks->einfo + (_("%B: unsupported relocation type %i\n"), abfd, ELF32_R_TYPE (rel->r_info)); return FALSE; } @@ -6350,8 +6279,7 @@ elf32_frv_check_relocs (abfd, info, sec, relocs) /* Return the machine subcode from the ELF e_flags header. */ static int -elf32_frv_machine (abfd) - bfd *abfd; +elf32_frv_machine (bfd *abfd) { switch (elf_elfheader (abfd)->e_flags & EF_FRV_CPU_MASK) { @@ -6372,8 +6300,7 @@ elf32_frv_machine (abfd) /* Set the right machine number for a FRV ELF file. */ static bfd_boolean -elf32_frv_object_p (abfd) - bfd *abfd; +elf32_frv_object_p (bfd *abfd) { bfd_default_set_arch_mach (abfd, bfd_arch_frv, elf32_frv_machine (abfd)); return (((elf_elfheader (abfd)->e_flags & EF_FRV_FDPIC) != 0) @@ -6383,34 +6310,13 @@ elf32_frv_object_p (abfd) /* Function to set the ELF flag bits. */ static bfd_boolean -frv_elf_set_private_flags (abfd, flags) - bfd *abfd; - flagword flags; +frv_elf_set_private_flags (bfd *abfd, flagword flags) { elf_elfheader (abfd)->e_flags = flags; elf_flags_init (abfd) = TRUE; return TRUE; } -/* Copy backend specific data from one object module to another. */ - -static bfd_boolean -frv_elf_copy_private_bfd_data (ibfd, obfd) - bfd *ibfd; - bfd *obfd; -{ - if (bfd_get_flavour (ibfd) != bfd_target_elf_flavour - || bfd_get_flavour (obfd) != bfd_target_elf_flavour) - return TRUE; - - BFD_ASSERT (!elf_flags_init (obfd) - || elf_elfheader (obfd)->e_flags == elf_elfheader (ibfd)->e_flags); - - elf_elfheader (obfd)->e_flags = elf_elfheader (ibfd)->e_flags; - elf_flags_init (obfd) = TRUE; - return TRUE; -} - /* Return true if the architecture described by elf header flag EXTENSION is an extension of the architecture described by BASE. */ @@ -6438,57 +6344,11 @@ frv_elf_arch_extension_p (flagword base, flagword extension) return FALSE; } -static bfd_boolean -elf32_frvfdpic_copy_private_bfd_data (bfd *ibfd, bfd *obfd) -{ - unsigned i; - - if (bfd_get_flavour (ibfd) != bfd_target_elf_flavour - || bfd_get_flavour (obfd) != bfd_target_elf_flavour) - return TRUE; - - if (! frv_elf_copy_private_bfd_data (ibfd, obfd)) - return FALSE; - - if (! elf_tdata (ibfd) || ! elf_tdata (ibfd)->phdr - || ! elf_tdata (obfd) || ! elf_tdata (obfd)->phdr) - return TRUE; - - /* Copy the stack size. */ - for (i = 0; i < elf_elfheader (ibfd)->e_phnum; i++) - if (elf_tdata (ibfd)->phdr[i].p_type == PT_GNU_STACK) - { - Elf_Internal_Phdr *iphdr = &elf_tdata (ibfd)->phdr[i]; - - for (i = 0; i < elf_elfheader (obfd)->e_phnum; i++) - if (elf_tdata (obfd)->phdr[i].p_type == PT_GNU_STACK) - { - memcpy (&elf_tdata (obfd)->phdr[i], iphdr, sizeof (*iphdr)); - - /* Rewrite the phdrs, since we're only called after they - were first written. */ - if (bfd_seek (obfd, (bfd_signed_vma) get_elf_backend_data (obfd) - ->s->sizeof_ehdr, SEEK_SET) != 0 - || get_elf_backend_data (obfd)->s - ->write_out_phdrs (obfd, elf_tdata (obfd)->phdr, - elf_elfheader (obfd)->e_phnum) != 0) - return FALSE; - break; - } - - break; - } - - return TRUE; -} - /* Merge backend specific data from an object file to the output object file when linking. */ static bfd_boolean -frv_elf_merge_private_bfd_data (ibfd, obfd) - bfd *ibfd; - bfd *obfd; +frv_elf_merge_private_bfd_data (bfd *ibfd, bfd *obfd) { flagword old_flags, old_partial; flagword new_flags, new_partial; @@ -6756,10 +6616,8 @@ frv_elf_merge_private_bfd_data (ibfd, obfd) } -bfd_boolean -frv_elf_print_private_bfd_data (abfd, ptr) - bfd *abfd; - PTR ptr; +static bfd_boolean +frv_elf_print_private_bfd_data (bfd *abfd, void * ptr) { FILE *file = (FILE *) ptr; flagword flags; @@ -6770,7 +6628,7 @@ frv_elf_print_private_bfd_data (abfd, ptr) _bfd_elf_print_private_bfd_data (abfd, ptr); flags = elf_elfheader (abfd)->e_flags; - fprintf (file, _("private flags = 0x%lx:"), (long)flags); + fprintf (file, _("private flags = 0x%lx:"), (unsigned long) flags); switch (flags & EF_FRV_CPU_MASK) { @@ -6839,27 +6697,108 @@ frv_elf_print_private_bfd_data (abfd, ptr) } +/* Support for core dump NOTE sections. */ + +static bfd_boolean +elf32_frv_grok_prstatus (bfd *abfd, Elf_Internal_Note *note) +{ + int offset; + unsigned int raw_size; + + switch (note->descsz) + { + default: + return FALSE; + + /* The Linux/FRV elf_prstatus struct is 268 bytes long. The other + hardcoded offsets and sizes listed below (and contained within + this lexical block) refer to fields in the target's elf_prstatus + struct. */ + case 268: + /* `pr_cursig' is at offset 12. */ + elf_tdata (abfd)->core->signal = bfd_get_16 (abfd, note->descdata + 12); + + /* `pr_pid' is at offset 24. */ + elf_tdata (abfd)->core->lwpid = bfd_get_32 (abfd, note->descdata + 24); + + /* `pr_reg' is at offset 72. */ + offset = 72; + + /* Most grok_prstatus implementations set `raw_size' to the size + of the pr_reg field. For Linux/FRV, we set `raw_size' to be + the size of `pr_reg' plus the size of `pr_exec_fdpic_loadmap' + and `pr_interp_fdpic_loadmap', both of which (by design) + immediately follow `pr_reg'. This will allow these fields to + be viewed by GDB as registers. + + `pr_reg' is 184 bytes long. `pr_exec_fdpic_loadmap' and + `pr_interp_fdpic_loadmap' are 4 bytes each. */ + raw_size = 184 + 4 + 4; + + break; + } + + /* Make a ".reg/999" section. */ + return _bfd_elfcore_make_pseudosection (abfd, ".reg", raw_size, + note->descpos + offset); +} + +static bfd_boolean +elf32_frv_grok_psinfo (bfd *abfd, Elf_Internal_Note *note) +{ + switch (note->descsz) + { + default: + return FALSE; + + /* The Linux/FRV elf_prpsinfo struct is 124 bytes long. */ + case 124: + + /* `pr_fname' is found at offset 28 and is 16 bytes long. */ + elf_tdata (abfd)->core->program + = _bfd_elfcore_strndup (abfd, note->descdata + 28, 16); + + /* `pr_psargs' is found at offset 44 and is 80 bytes long. */ + elf_tdata (abfd)->core->command + = _bfd_elfcore_strndup (abfd, note->descdata + 44, 80); + } + + /* Note that for some reason, a spurious space is tacked + onto the end of the args in some (at least one anyway) + implementations, so strip it off if it exists. */ + + { + char *command = elf_tdata (abfd)->core->command; + int n = strlen (command); + + if (0 < n && command[n - 1] == ' ') + command[n - 1] = '\0'; + } + + return TRUE; +} #define ELF_ARCH bfd_arch_frv +#define ELF_TARGET_ID FRV_ELF_DATA #define ELF_MACHINE_CODE EM_CYGNUS_FRV #define ELF_MAXPAGESIZE 0x1000 -#define TARGET_BIG_SYM bfd_elf32_frv_vec +#define TARGET_BIG_SYM frv_elf32_vec #define TARGET_BIG_NAME "elf32-frv" #define elf_info_to_howto frv_info_to_howto_rela #define elf_backend_relocate_section elf32_frv_relocate_section #define elf_backend_gc_mark_hook elf32_frv_gc_mark_hook -#define elf_backend_gc_sweep_hook elf32_frv_gc_sweep_hook #define elf_backend_check_relocs elf32_frv_check_relocs #define elf_backend_object_p elf32_frv_object_p #define elf_backend_add_symbol_hook elf32_frv_add_symbol_hook +#define elf_backend_stack_align 8 #define elf_backend_can_gc_sections 1 #define elf_backend_rela_normal 1 #define bfd_elf32_bfd_reloc_type_lookup frv_reloc_type_lookup +#define bfd_elf32_bfd_reloc_name_lookup frv_reloc_name_lookup #define bfd_elf32_bfd_set_private_flags frv_elf_set_private_flags -#define bfd_elf32_bfd_copy_private_bfd_data frv_elf_copy_private_bfd_data #define bfd_elf32_bfd_merge_private_bfd_data frv_elf_merge_private_bfd_data #define bfd_elf32_bfd_print_private_bfd_data frv_elf_print_private_bfd_data @@ -6873,13 +6812,16 @@ frv_elf_print_private_bfd_data (abfd, ptr) #define elf_backend_finish_dynamic_sections \ elf32_frv_finish_dynamic_sections +#define elf_backend_grok_prstatus elf32_frv_grok_prstatus +#define elf_backend_grok_psinfo elf32_frv_grok_psinfo + #include "elf32-target.h" #undef ELF_MAXPAGESIZE #define ELF_MAXPAGESIZE 0x4000 #undef TARGET_BIG_SYM -#define TARGET_BIG_SYM bfd_elf32_frvfdpic_vec +#define TARGET_BIG_SYM frv_elf32_fdpic_vec #undef TARGET_BIG_NAME #define TARGET_BIG_NAME "elf32-frvfdpic" #undef elf32_bed @@ -6894,12 +6836,6 @@ frv_elf_print_private_bfd_data (abfd, ptr) #undef elf_backend_always_size_sections #define elf_backend_always_size_sections \ elf32_frvfdpic_always_size_sections -#undef elf_backend_modify_segment_map -#define elf_backend_modify_segment_map \ - elf32_frvfdpic_modify_segment_map -#undef bfd_elf32_bfd_copy_private_bfd_data -#define bfd_elf32_bfd_copy_private_bfd_data \ - elf32_frvfdpic_copy_private_bfd_data #undef elf_backend_create_dynamic_sections #define elf_backend_create_dynamic_sections \ @@ -6920,6 +6856,9 @@ frv_elf_print_private_bfd_data (abfd, ptr) #define elf_backend_finish_dynamic_sections \ elf32_frvfdpic_finish_dynamic_sections +#undef elf_backend_discard_info +#define elf_backend_discard_info \ + frvfdpic_elf_discard_info #undef elf_backend_can_make_relative_eh_frame #define elf_backend_can_make_relative_eh_frame \ frvfdpic_elf_use_relative_eh_frame