X-Git-Url: http://drtracing.org/?a=blobdiff_plain;f=bfd%2Felf32-frv.c;h=811d5f5b3ae41ccff1992a498872219a9eeaa9f5;hb=964e4306f80f7da4474eea57ce49492b73611acb;hp=5d604328270f48c4f6c134914c2116fa6375d7ba;hpb=973a3492d553c8b18c8a3257b4874253c0efa68a;p=deliverable%2Fbinutils-gdb.git diff --git a/bfd/elf32-frv.c b/bfd/elf32-frv.c index 5d60432827..811d5f5b3a 100644 --- a/bfd/elf32-frv.c +++ b/bfd/elf32-frv.c @@ -1,28 +1,30 @@ /* FRV-specific support for 32-bit ELF. - Copyright 2002, 2003, 2004, 2005 Free Software Foundation, Inc. + Copyright 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010 + 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. */ @@ -57,12 +59,6 @@ static bfd_boolean elf32_frv_add_symbol_hook 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 *)); @@ -78,6 +74,10 @@ 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 bfd_boolean elf32_frv_grok_prstatus (bfd * abfd, + Elf_Internal_Note * note); +static bfd_boolean elf32_frv_grok_psinfo (bfd * abfd, + Elf_Internal_Note * note); static reloc_howto_type elf32_frv_howto_table [] = { @@ -882,8 +882,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) @@ -1004,8 +1005,10 @@ frvfdpic_elf_link_hash_table_create (bfd *abfd) 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 +1343,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; - - for (i = m->count - 1; i >= 0; i--) - if (m->sections[i] == osec) - break; - - if (i >= 0) - break; - } + Elf_Internal_Phdr *p = _bfd_elf_find_segment_containing_section (output_bfd, osec); - return p - elf_tdata (output_bfd)->phdr; + return (p != NULL) ? p - elf_tdata (output_bfd)->phdr : -1; } inline static bfd_boolean @@ -1413,7 +1399,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; @@ -1695,8 +1682,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 @@ -2590,6 +2578,26 @@ 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 @@ -2723,9 +2731,6 @@ elf32_frv_relocate_section (output_bfd, info, input_bfd, input_section, int silence_segment_error = !(info->shared || info->pie); 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; @@ -2777,7 +2782,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; @@ -2796,50 +2800,38 @@ elf32_frv_relocate_section (output_bfd, info, input_bfd, input_section, } else { - h = sym_hashes [r_symndx - symtab_hdr->sh_info]; + bfd_boolean warned; + bfd_boolean unresolved_reloc; - 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; + RELOC_FOR_GLOBAL_SYMBOL (info, input_bfd, input_section, rel, + r_symndx, symtab_hdr, sym_hashes, + h, sec, relocation, + unresolved_reloc, warned); + osec = sec; + } - name = h->root.root.string; + if (sec != NULL && elf_discarded_section (sec)) + { + /* For relocs against symbols from removed linkonce sections, + or sections discarded by a linker script, we just want the + section contents zeroed. Avoid any special processing. */ + _bfd_clear_contents (howto, input_bfd, contents + rel->r_offset); + rel->r_info = 0; + rel->r_addend = 0; + continue; + } - 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 (info->relocatable) + 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) @@ -3640,6 +3632,8 @@ 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)) @@ -3650,22 +3644,27 @@ elf32_frv_relocate_section (output_bfd, info, input_bfd, input_section, name, 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)) @@ -3676,15 +3675,18 @@ elf32_frv_relocate_section (output_bfd, info, input_bfd, input_section, name, 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; @@ -3765,25 +3767,27 @@ elf32_frv_relocate_section (output_bfd, info, input_bfd, input_section, } 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,6 +3797,8 @@ 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)) @@ -3803,15 +3809,18 @@ elf32_frv_relocate_section (output_bfd, info, input_bfd, input_section, name, 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; @@ -4140,54 +4149,22 @@ 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. */ @@ -4301,22 +4278,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. */ @@ -4399,24 +4369,14 @@ _frv_create_got_section (bfd *abfd, struct bfd_link_info *info) /* 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; } @@ -5615,7 +5575,6 @@ elf32_frvfdpic_always_size_sections (bfd *output_bfd, if (!info->relocatable) { struct elf_link_hash_entry *h; - asection *sec; /* Force a PT_GNU_STACK segment to be created. */ if (! elf_tdata (output_bfd)->stack_flags) @@ -5642,12 +5601,118 @@ elf32_frvfdpic_always_size_sections (bfd *output_bfd, h->type = STT_OBJECT; /* This one must NOT be hidden. */ } + } + + 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; - /* Create a stack section, and set its alignment. */ - sec = bfd_make_section (output_bfd, ".stack"); + 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); - if (sec == NULL - || ! bfd_set_section_alignment (output_bfd, sec, 3)) + 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; + 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; + + if (_bfd_elf_section_offset (sec->output_section->owner, + info, sec, rel->r_offset) + != (bfd_vma)-1) + continue; + + r_symndx = ELF32_R_SYM (rel->r_info); + if (r_symndx < symtab_hdr->sh_info) + h = NULL; + 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; + } + + 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); + + 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; +} + +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 == ELF_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 (!_frvfdpic_size_got_plt (obfd, &gpinfo)) return FALSE; } @@ -5675,6 +5740,10 @@ elf32_frvfdpic_relax_section (bfd *abfd ATTRIBUTE_UNUSED, asection *sec, { struct _frvfdpic_dynamic_got_plt_info gpinfo; + if (info->relocatable) + (*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; @@ -5730,48 +5799,45 @@ elf32_frvfdpic_relax_section (bfd *abfd ATTRIBUTE_UNUSED, asection *sec, } static bfd_boolean -elf32_frvfdpic_modify_segment_map (bfd *output_bfd, - struct bfd_link_info *info) +elf32_frvfdpic_modify_program_headers (bfd *output_bfd, + struct bfd_link_info *info) { + struct elf_obj_tdata *tdata = elf_tdata (output_bfd); struct elf_segment_map *m; + Elf_Internal_Phdr *p; /* 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) + for (p = tdata->phdr, m = tdata->segment_map; m != NULL; m = m->next, p++) 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); + if (h) { - /* 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; + 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; + /* Set the header p_memsz from the symbol value. We + intentionally ignore the symbol section. */ + if (h && h->root.type == bfd_link_hash_defined) + p->p_memsz = h->root.u.def.value; + else + p->p_memsz = 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++; - } + p->p_align = 8; } return TRUE; @@ -6101,7 +6167,7 @@ elf32_frv_check_relocs (abfd, info, sec, relocs) 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; @@ -6112,9 +6178,6 @@ elf32_frv_check_relocs (abfd, info, sec, relocs) 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; @@ -6322,7 +6385,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; @@ -6413,6 +6478,10 @@ frv_elf_copy_private_bfd_data (ibfd, obfd) elf_elfheader (obfd)->e_flags = elf_elfheader (ibfd)->e_flags; elf_flags_init (obfd) = TRUE; + + /* Copy object attributes. */ + _bfd_elf_copy_obj_attributes (ibfd, obfd); + return TRUE; } @@ -6775,7 +6844,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) { @@ -6844,6 +6913,86 @@ 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_MACHINE_CODE EM_CYGNUS_FRV #define ELF_MAXPAGESIZE 0x1000 @@ -6854,7 +7003,6 @@ frv_elf_print_private_bfd_data (abfd, ptr) #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 @@ -6863,6 +7011,7 @@ frv_elf_print_private_bfd_data (abfd, ptr) #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 @@ -6878,6 +7027,9 @@ 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 @@ -6899,9 +7051,9 @@ 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 elf_backend_modify_program_headers +#define elf_backend_modify_program_headers \ + elf32_frvfdpic_modify_program_headers #undef bfd_elf32_bfd_copy_private_bfd_data #define bfd_elf32_bfd_copy_private_bfd_data \ elf32_frvfdpic_copy_private_bfd_data @@ -6925,6 +7077,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