X-Git-Url: http://git.efficios.com/?a=blobdiff_plain;f=bfd%2Felf32-frv.c;h=7f3c4dd23ebcca41d3aa4c83d1e09c722734b5fa;hb=dd0c24e3bd5138180819aa90071856007e347c64;hp=009507a074c632e6b1a019ca519025ddd6aab386;hpb=303e4c21e7c9ddd98c577051f5c477f11a5c06ec;p=deliverable%2Fbinutils-gdb.git diff --git a/bfd/elf32-frv.c b/bfd/elf32-frv.c index 009507a074..7f3c4dd23e 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, 2011 + 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, 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 [] = { @@ -112,7 +112,7 @@ static reloc_howto_type elf32_frv_howto_table [] = FALSE), /* pcrel_offset */ /* A 16 bit pc-relative relocation. */ - HOWTO (R_FRV_LABEL16, /* type */ + HOWTO (R_FRV_LABEL16, /* type */ 2, /* rightshift */ 2, /* size (0 = byte, 1 = short, 2 = long) */ 16, /* bitsize */ @@ -124,10 +124,10 @@ static reloc_howto_type elf32_frv_howto_table [] = FALSE, /* partial_inplace */ 0xffff, /* src_mask */ 0xffff, /* dst_mask */ - TRUE), /* pcrel_offset */ + TRUE), /* pcrel_offset */ /* A 24-bit pc-relative relocation. */ - HOWTO (R_FRV_LABEL24, /* type */ + HOWTO (R_FRV_LABEL24, /* type */ 2, /* rightshift */ 2, /* size (0 = byte, 1 = short, 2 = long) */ 26, /* bitsize */ @@ -139,9 +139,9 @@ static reloc_howto_type elf32_frv_howto_table [] = FALSE, /* partial_inplace */ 0x7e03ffff, /* src_mask */ 0x7e03ffff, /* dst_mask */ - TRUE), /* pcrel_offset */ + TRUE), /* pcrel_offset */ - HOWTO (R_FRV_LO16, /* type */ + HOWTO (R_FRV_LO16, /* type */ 0, /* rightshift */ 2, /* size (0 = byte, 1 = short, 2 = long) */ 16, /* bitsize */ @@ -153,9 +153,9 @@ static reloc_howto_type elf32_frv_howto_table [] = FALSE, /* partial_inplace */ 0xffff, /* src_mask */ 0xffff, /* dst_mask */ - FALSE), /* pcrel_offset */ + FALSE), /* pcrel_offset */ - HOWTO (R_FRV_HI16, /* type */ + HOWTO (R_FRV_HI16, /* type */ 0, /* rightshift */ 2, /* size (0 = byte, 1 = short, 2 = long) */ 16, /* bitsize */ @@ -167,9 +167,9 @@ static reloc_howto_type elf32_frv_howto_table [] = FALSE, /* partial_inplace */ 0xffff, /* src_mask */ 0xffff, /* dst_mask */ - FALSE), /* pcrel_offset */ + FALSE), /* pcrel_offset */ - HOWTO (R_FRV_GPREL12, /* type */ + HOWTO (R_FRV_GPREL12, /* type */ 0, /* rightshift */ 2, /* size (0 = byte, 1 = short, 2 = long) */ 12, /* bitsize */ @@ -177,13 +177,13 @@ static reloc_howto_type elf32_frv_howto_table [] = 0, /* bitpos */ complain_overflow_dont, /* complain_on_overflow */ bfd_elf_generic_reloc, /* special_function */ - "R_FRV_GPREL12", /* name */ + "R_FRV_GPREL12", /* name */ FALSE, /* partial_inplace */ - 0xfff, /* src_mask */ - 0xfff, /* dst_mask */ - FALSE), /* pcrel_offset */ + 0xfff, /* src_mask */ + 0xfff, /* dst_mask */ + FALSE), /* pcrel_offset */ - HOWTO (R_FRV_GPRELU12, /* type */ + HOWTO (R_FRV_GPRELU12, /* type */ 0, /* rightshift */ 2, /* size (0 = byte, 1 = short, 2 = long) */ 12, /* bitsize */ @@ -191,13 +191,13 @@ static reloc_howto_type elf32_frv_howto_table [] = 0, /* bitpos */ complain_overflow_dont, /* complain_on_overflow */ bfd_elf_generic_reloc, /* special_function */ - "R_FRV_GPRELU12", /* name */ + "R_FRV_GPRELU12", /* name */ FALSE, /* partial_inplace */ - 0xfff, /* src_mask */ - 0x3f03f, /* dst_mask */ - FALSE), /* pcrel_offset */ + 0xfff, /* src_mask */ + 0x3f03f, /* dst_mask */ + FALSE), /* pcrel_offset */ - HOWTO (R_FRV_GPREL32, /* type */ + HOWTO (R_FRV_GPREL32, /* type */ 0, /* rightshift */ 2, /* size (0 = byte, 1 = short, 2 = long) */ 32, /* bitsize */ @@ -207,11 +207,11 @@ static reloc_howto_type elf32_frv_howto_table [] = bfd_elf_generic_reloc, /* special_function */ "R_FRV_GPREL32", /* name */ FALSE, /* partial_inplace */ - 0xffffffff, /* src_mask */ + 0xffffffff, /* src_mask */ 0xffffffff, /* dst_mask */ - FALSE), /* pcrel_offset */ + FALSE), /* pcrel_offset */ - HOWTO (R_FRV_GPRELHI, /* type */ + HOWTO (R_FRV_GPRELHI, /* type */ 0, /* rightshift */ 2, /* size (0 = byte, 1 = short, 2 = long) */ 16, /* bitsize */ @@ -221,11 +221,11 @@ static reloc_howto_type elf32_frv_howto_table [] = bfd_elf_generic_reloc, /* special_function */ "R_FRV_GPRELHI", /* name */ FALSE, /* partial_inplace */ - 0xffff, /* src_mask */ + 0xffff, /* src_mask */ 0xffff, /* dst_mask */ - FALSE), /* pcrel_offset */ + FALSE), /* pcrel_offset */ - HOWTO (R_FRV_GPRELLO, /* type */ + HOWTO (R_FRV_GPRELLO, /* type */ 0, /* rightshift */ 2, /* size (0 = byte, 1 = short, 2 = long) */ 16, /* bitsize */ @@ -235,13 +235,13 @@ static reloc_howto_type elf32_frv_howto_table [] = bfd_elf_generic_reloc, /* special_function */ "R_FRV_GPRELLO", /* name */ FALSE, /* partial_inplace */ - 0xffff, /* src_mask */ + 0xffff, /* src_mask */ 0xffff, /* dst_mask */ - FALSE), /* pcrel_offset */ + FALSE), /* pcrel_offset */ /* A 12-bit signed operand with the GOT offset for the address of the symbol. */ - HOWTO (R_FRV_GOT12, /* type */ + HOWTO (R_FRV_GOT12, /* type */ 0, /* rightshift */ 2, /* size (0 = byte, 1 = short, 2 = long) */ 12, /* bitsize */ @@ -251,13 +251,13 @@ static reloc_howto_type elf32_frv_howto_table [] = bfd_elf_generic_reloc, /* special_function */ "R_FRV_GOT12", /* name */ FALSE, /* partial_inplace */ - 0xfff, /* src_mask */ - 0xfff, /* dst_mask */ - FALSE), /* pcrel_offset */ + 0xfff, /* src_mask */ + 0xfff, /* dst_mask */ + FALSE), /* pcrel_offset */ /* The upper 16 bits of the GOT offset for the address of the symbol. */ - HOWTO (R_FRV_GOTHI, /* type */ + HOWTO (R_FRV_GOTHI, /* type */ 0, /* rightshift */ 2, /* size (0 = byte, 1 = short, 2 = long) */ 16, /* bitsize */ @@ -267,13 +267,13 @@ static reloc_howto_type elf32_frv_howto_table [] = bfd_elf_generic_reloc, /* special_function */ "R_FRV_GOTHI", /* name */ FALSE, /* partial_inplace */ - 0xffff, /* src_mask */ + 0xffff, /* src_mask */ 0xffff, /* dst_mask */ - FALSE), /* pcrel_offset */ + FALSE), /* pcrel_offset */ /* The lower 16 bits of the GOT offset for the address of the symbol. */ - HOWTO (R_FRV_GOTLO, /* type */ + HOWTO (R_FRV_GOTLO, /* type */ 0, /* rightshift */ 2, /* size (0 = byte, 1 = short, 2 = long) */ 16, /* bitsize */ @@ -285,7 +285,7 @@ static reloc_howto_type elf32_frv_howto_table [] = FALSE, /* partial_inplace */ 0xffff, /* src_mask */ 0xffff, /* dst_mask */ - FALSE), /* pcrel_offset */ + FALSE), /* pcrel_offset */ /* The 32-bit address of the canonical descriptor of a function. */ HOWTO (R_FRV_FUNCDESC, /* type */ @@ -314,9 +314,9 @@ static reloc_howto_type elf32_frv_howto_table [] = bfd_elf_generic_reloc, /* special_function */ "R_FRV_FUNCDESC_GOT12", /* name */ FALSE, /* partial_inplace */ - 0xfff, /* src_mask */ - 0xfff, /* dst_mask */ - FALSE), /* pcrel_offset */ + 0xfff, /* src_mask */ + 0xfff, /* dst_mask */ + FALSE), /* pcrel_offset */ /* The upper 16 bits of the GOT offset for the address of the canonical descriptor of a function. */ @@ -332,7 +332,7 @@ static reloc_howto_type elf32_frv_howto_table [] = FALSE, /* partial_inplace */ 0xffff, /* src_mask */ 0xffff, /* dst_mask */ - FALSE), /* pcrel_offset */ + FALSE), /* pcrel_offset */ /* The lower 16 bits of the GOT offset for the address of the canonical descriptor of a function. */ @@ -348,7 +348,7 @@ static reloc_howto_type elf32_frv_howto_table [] = FALSE, /* partial_inplace */ 0xffff, /* src_mask */ 0xffff, /* dst_mask */ - FALSE), /* pcrel_offset */ + FALSE), /* pcrel_offset */ /* The 64-bit descriptor of a function. */ HOWTO (R_FRV_FUNCDESC_VALUE, /* type */ @@ -377,9 +377,9 @@ static reloc_howto_type elf32_frv_howto_table [] = bfd_elf_generic_reloc, /* special_function */ "R_FRV_FUNCDESC_GOTOFF12", /* name */ FALSE, /* partial_inplace */ - 0xfff, /* src_mask */ - 0xfff, /* dst_mask */ - FALSE), /* pcrel_offset */ + 0xfff, /* src_mask */ + 0xfff, /* dst_mask */ + FALSE), /* pcrel_offset */ /* The upper 16 bits of the GOT offset for the address of the canonical descriptor of a function. */ @@ -395,7 +395,7 @@ static reloc_howto_type elf32_frv_howto_table [] = FALSE, /* partial_inplace */ 0xffff, /* src_mask */ 0xffff, /* dst_mask */ - FALSE), /* pcrel_offset */ + FALSE), /* pcrel_offset */ /* The lower 16 bits of the GOT offset for the address of the canonical descriptor of a function. */ @@ -411,11 +411,11 @@ static reloc_howto_type elf32_frv_howto_table [] = FALSE, /* partial_inplace */ 0xffff, /* src_mask */ 0xffff, /* dst_mask */ - FALSE), /* pcrel_offset */ + FALSE), /* pcrel_offset */ /* A 12-bit signed operand with the GOT offset for the address of the symbol. */ - HOWTO (R_FRV_GOTOFF12, /* type */ + HOWTO (R_FRV_GOTOFF12, /* type */ 0, /* rightshift */ 2, /* size (0 = byte, 1 = short, 2 = long) */ 12, /* bitsize */ @@ -425,13 +425,13 @@ static reloc_howto_type elf32_frv_howto_table [] = bfd_elf_generic_reloc, /* special_function */ "R_FRV_GOTOFF12", /* name */ FALSE, /* partial_inplace */ - 0xfff, /* src_mask */ - 0xfff, /* dst_mask */ - FALSE), /* pcrel_offset */ + 0xfff, /* src_mask */ + 0xfff, /* dst_mask */ + FALSE), /* pcrel_offset */ /* The upper 16 bits of the GOT offset for the address of the symbol. */ - HOWTO (R_FRV_GOTOFFHI, /* type */ + HOWTO (R_FRV_GOTOFFHI, /* type */ 0, /* rightshift */ 2, /* size (0 = byte, 1 = short, 2 = long) */ 16, /* bitsize */ @@ -443,7 +443,7 @@ static reloc_howto_type elf32_frv_howto_table [] = FALSE, /* partial_inplace */ 0xffff, /* src_mask */ 0xffff, /* dst_mask */ - FALSE), /* pcrel_offset */ + FALSE), /* pcrel_offset */ /* The lower 16 bits of the GOT offset for the address of the symbol. */ @@ -459,7 +459,7 @@ static reloc_howto_type elf32_frv_howto_table [] = FALSE, /* partial_inplace */ 0xffff, /* src_mask */ 0xffff, /* dst_mask */ - FALSE), /* pcrel_offset */ + FALSE), /* pcrel_offset */ /* A 24-bit pc-relative relocation referencing the TLS PLT entry for a thread-local symbol. If the symbol number is 0, it refers to @@ -476,7 +476,7 @@ static reloc_howto_type elf32_frv_howto_table [] = FALSE, /* partial_inplace */ 0x7e03ffff, /* src_mask */ 0x7e03ffff, /* dst_mask */ - TRUE), /* pcrel_offset */ + TRUE), /* pcrel_offset */ /* A 64-bit TLS descriptor for a symbol. This relocation is only valid as a REL, dynamic relocation. */ @@ -496,7 +496,7 @@ static reloc_howto_type elf32_frv_howto_table [] = /* A 12-bit signed operand with the GOT offset for the TLS descriptor of the symbol. */ - HOWTO (R_FRV_GOTTLSDESC12, /* type */ + HOWTO (R_FRV_GOTTLSDESC12, /* type */ 0, /* rightshift */ 2, /* size (0 = byte, 1 = short, 2 = long) */ 12, /* bitsize */ @@ -506,13 +506,13 @@ static reloc_howto_type elf32_frv_howto_table [] = bfd_elf_generic_reloc, /* special_function */ "R_FRV_GOTTLSDESC12", /* name */ FALSE, /* partial_inplace */ - 0xfff, /* src_mask */ - 0xfff, /* dst_mask */ - FALSE), /* pcrel_offset */ + 0xfff, /* src_mask */ + 0xfff, /* dst_mask */ + FALSE), /* pcrel_offset */ /* The upper 16 bits of the GOT offset for the TLS descriptor of the symbol. */ - HOWTO (R_FRV_GOTTLSDESCHI, /* type */ + HOWTO (R_FRV_GOTTLSDESCHI, /* type */ 0, /* rightshift */ 2, /* size (0 = byte, 1 = short, 2 = long) */ 16, /* bitsize */ @@ -524,7 +524,7 @@ static reloc_howto_type elf32_frv_howto_table [] = FALSE, /* partial_inplace */ 0xffff, /* src_mask */ 0xffff, /* dst_mask */ - FALSE), /* pcrel_offset */ + FALSE), /* pcrel_offset */ /* The lower 16 bits of the GOT offset for the TLS descriptor of the symbol. */ @@ -540,11 +540,11 @@ static reloc_howto_type elf32_frv_howto_table [] = FALSE, /* partial_inplace */ 0xffff, /* src_mask */ 0xffff, /* dst_mask */ - FALSE), /* pcrel_offset */ + FALSE), /* pcrel_offset */ /* A 12-bit signed operand with the offset from the module base address to the thread-local symbol address. */ - HOWTO (R_FRV_TLSMOFF12, /* type */ + HOWTO (R_FRV_TLSMOFF12, /* type */ 0, /* rightshift */ 2, /* size (0 = byte, 1 = short, 2 = long) */ 12, /* bitsize */ @@ -554,13 +554,13 @@ static reloc_howto_type elf32_frv_howto_table [] = bfd_elf_generic_reloc, /* special_function */ "R_FRV_TLSMOFF12", /* name */ FALSE, /* partial_inplace */ - 0xfff, /* src_mask */ - 0xfff, /* dst_mask */ - FALSE), /* pcrel_offset */ + 0xfff, /* src_mask */ + 0xfff, /* dst_mask */ + FALSE), /* pcrel_offset */ /* The upper 16 bits of the offset from the module base address to the thread-local symbol address. */ - HOWTO (R_FRV_TLSMOFFHI, /* type */ + HOWTO (R_FRV_TLSMOFFHI, /* type */ 0, /* rightshift */ 2, /* size (0 = byte, 1 = short, 2 = long) */ 16, /* bitsize */ @@ -572,7 +572,7 @@ static reloc_howto_type elf32_frv_howto_table [] = FALSE, /* partial_inplace */ 0xffff, /* src_mask */ 0xffff, /* dst_mask */ - FALSE), /* pcrel_offset */ + FALSE), /* pcrel_offset */ /* The lower 16 bits of the offset from the module base address to the thread-local symbol address. */ @@ -588,11 +588,11 @@ static reloc_howto_type elf32_frv_howto_table [] = FALSE, /* partial_inplace */ 0xffff, /* src_mask */ 0xffff, /* dst_mask */ - FALSE), /* pcrel_offset */ + FALSE), /* pcrel_offset */ /* A 12-bit signed operand with the GOT offset for the TLSOFF entry for a symbol. */ - HOWTO (R_FRV_GOTTLSOFF12, /* type */ + HOWTO (R_FRV_GOTTLSOFF12, /* type */ 0, /* rightshift */ 2, /* size (0 = byte, 1 = short, 2 = long) */ 12, /* bitsize */ @@ -602,13 +602,13 @@ static reloc_howto_type elf32_frv_howto_table [] = bfd_elf_generic_reloc, /* special_function */ "R_FRV_GOTTLSOFF12", /* name */ FALSE, /* partial_inplace */ - 0xfff, /* src_mask */ - 0xfff, /* dst_mask */ - FALSE), /* pcrel_offset */ + 0xfff, /* src_mask */ + 0xfff, /* dst_mask */ + FALSE), /* pcrel_offset */ /* The upper 16 bits of the GOT offset for the TLSOFF entry for a symbol. */ - HOWTO (R_FRV_GOTTLSOFFHI, /* type */ + HOWTO (R_FRV_GOTTLSOFFHI, /* type */ 0, /* rightshift */ 2, /* size (0 = byte, 1 = short, 2 = long) */ 16, /* bitsize */ @@ -620,7 +620,7 @@ static reloc_howto_type elf32_frv_howto_table [] = FALSE, /* partial_inplace */ 0xffff, /* src_mask */ 0xffff, /* dst_mask */ - FALSE), /* pcrel_offset */ + FALSE), /* pcrel_offset */ /* The lower 16 bits of the GOT offset for the TLSOFF entry for a symbol. */ @@ -636,7 +636,7 @@ static reloc_howto_type elf32_frv_howto_table [] = FALSE, /* partial_inplace */ 0xffff, /* src_mask */ 0xffff, /* dst_mask */ - FALSE), /* pcrel_offset */ + FALSE), /* pcrel_offset */ /* The 32-bit offset from the thread pointer (not the module base address) to a thread-local symbol. */ @@ -707,7 +707,7 @@ static reloc_howto_type elf32_frv_howto_table [] = /* A 32-bit offset from the module base address to the thread-local symbol address. */ - HOWTO (R_FRV_TLSMOFF, /* type */ + HOWTO (R_FRV_TLSMOFF, /* type */ 0, /* rightshift */ 2, /* size (0 = byte, 1 = short, 2 = long) */ 32, /* bitsize */ @@ -719,40 +719,40 @@ static reloc_howto_type elf32_frv_howto_table [] = FALSE, /* partial_inplace */ 0xffffffff, /* src_mask */ 0xffffffff, /* dst_mask */ - FALSE), /* pcrel_offset */ + FALSE), /* pcrel_offset */ }; /* GNU extension to record C++ vtable hierarchy. */ static reloc_howto_type elf32_frv_vtinherit_howto = - HOWTO (R_FRV_GNU_VTINHERIT, /* type */ - 0, /* rightshift */ - 2, /* size (0 = byte, 1 = short, 2 = long) */ - 0, /* bitsize */ - FALSE, /* pc_relative */ - 0, /* bitpos */ - complain_overflow_dont, /* complain_on_overflow */ - NULL, /* special_function */ - "R_FRV_GNU_VTINHERIT", /* name */ - FALSE, /* partial_inplace */ - 0, /* src_mask */ - 0, /* dst_mask */ - FALSE); /* pcrel_offset */ + HOWTO (R_FRV_GNU_VTINHERIT, /* type */ + 0, /* rightshift */ + 2, /* size (0 = byte, 1 = short, 2 = long) */ + 0, /* bitsize */ + FALSE, /* pc_relative */ + 0, /* bitpos */ + complain_overflow_dont, /* complain_on_overflow */ + NULL, /* special_function */ + "R_FRV_GNU_VTINHERIT", /* name */ + FALSE, /* partial_inplace */ + 0, /* src_mask */ + 0, /* dst_mask */ + FALSE); /* pcrel_offset */ /* GNU extension to record C++ vtable member usage. */ static reloc_howto_type elf32_frv_vtentry_howto = - HOWTO (R_FRV_GNU_VTENTRY, /* type */ - 0, /* rightshift */ - 2, /* size (0 = byte, 1 = short, 2 = long) */ - 0, /* bitsize */ - FALSE, /* pc_relative */ - 0, /* bitpos */ - complain_overflow_dont, /* complain_on_overflow */ - _bfd_elf_rel_vtable_reloc_fn, /* special_function */ - "R_FRV_GNU_VTENTRY", /* name */ - FALSE, /* partial_inplace */ - 0, /* src_mask */ - 0, /* dst_mask */ - FALSE); /* pcrel_offset */ + HOWTO (R_FRV_GNU_VTENTRY, /* type */ + 0, /* rightshift */ + 2, /* size (0 = byte, 1 = short, 2 = long) */ + 0, /* bitsize */ + FALSE, /* pc_relative */ + 0, /* bitpos */ + complain_overflow_dont, /* complain_on_overflow */ + _bfd_elf_rel_vtable_reloc_fn, /* special_function */ + "R_FRV_GNU_VTENTRY", /* name */ + FALSE, /* partial_inplace */ + 0, /* src_mask */ + 0, /* dst_mask */ + FALSE); /* pcrel_offset */ /* The following 3 relocations are REL. The only difference to the entries in the table above are that partial_inplace is TRUE. */ @@ -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; @@ -1144,8 +1147,8 @@ frvfdpic_relocs_info_hash (const void *entry_) const struct frvfdpic_relocs_info *entry = entry_; return (entry->symndx == -1 - ? (long)entry->d.h->root.root.hash - : entry->symndx + entry->d.abfd->id * 257) + entry->addend; + ? (long) entry->d.h->root.root.hash + : entry->symndx + (long) entry->d.abfd->id * 257) + entry->addend; } /* Test whether the key fields of two frvfdpic_relocs_info entries are @@ -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 @@ -1872,7 +1860,7 @@ _frvfdpic_emit_got_relocs_plt_entries (struct frvfdpic_relocs_info *entry, ->output_offset, R_FRV_TLSOFF, idx, ad, entry); } - + bfd_put_32 (output_bfd, ad, frvfdpic_got_section (info)->contents + frvfdpic_got_initial_offset (info) @@ -2004,7 +1992,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 && (entry->symndx != -1 || FRVFDPIC_SYM_LOCAL (info, entry->d.h))) @@ -2032,7 +2020,7 @@ _frvfdpic_emit_got_relocs_plt_entries (struct frvfdpic_relocs_info *entry, else idx = 0; } - + /* *ABS*+addend is special for TLS relocations, use only the addend for the TLS offset, and take the module id as 0. */ @@ -2044,7 +2032,7 @@ _frvfdpic_emit_got_relocs_plt_entries (struct frvfdpic_relocs_info *entry, TLS offset to the addend. */ else if (sec) ad += sec->output_section->vma - tls_biased_base (info); - + if ((bfd_signed_vma)ad >= -(1 << (16 - 1)) && (bfd_signed_vma)ad < (1 << (16 - 1))) { @@ -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; @@ -2765,7 +2770,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 +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; @@ -2792,54 +2796,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; + 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); + 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 && elf_discarded_section (sec)) + RELOC_AGAINST_DISCARDED_SECTION (info, input_bfd, input_section, + rel, relend, howto, contents); + + 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) @@ -2897,8 +2884,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; } @@ -2910,9 +2898,10 @@ elf32_frv_relocate_section (output_bfd, info, input_bfd, input_section, picrel = NULL; if (h && ! FRVFDPIC_SYM_LOCAL (info, h)) { - 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; @@ -2974,7 +2963,7 @@ elf32_frv_relocate_section (output_bfd, info, input_bfd, input_section, (LOCAL_EXEC_P ((info), (picrel))) #define RELAX_TLSDESC_INITIAL_EXEC_P(info, picrel) \ (INITIAL_EXEC_P ((info), (picrel))) - + #define RELAX_GOTTLSOFF_LOCAL_EXEC_P(info, picrel, value) \ (LOCAL_EXEC_P ((info), (picrel)) \ && TLSMOFF_IN_RANGE_FOR_SETLOS_P((value), (info))) @@ -2985,13 +2974,12 @@ 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; } - + if (RELAX_GETTLSOFF_LOCAL_EXEC_P (info, picrel, relocation + rel->r_addend)) { @@ -3027,10 +3015,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 +3086,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; } @@ -3128,18 +3116,17 @@ elf32_frv_relocate_section (output_bfd, info, input_bfd, input_section, } break; - + case R_FRV_GOTTLSDESCLO: insn = bfd_get_32 (input_bfd, contents + rel->r_offset); /* 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; } @@ -3176,17 +3163,17 @@ elf32_frv_relocate_section (output_bfd, info, input_bfd, input_section, } break; - + case R_FRV_TLSDESC_RELAX: insn = bfd_get_32 (input_bfd, contents + rel->r_offset); /* 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 +3254,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 +3308,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 +3338,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 +3367,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 +3397,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; } @@ -3457,10 +3442,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 +3469,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; } @@ -3506,12 +3490,12 @@ elf32_frv_relocate_section (output_bfd, info, input_bfd, input_section, /* There's nothing to relax in these: - R_FRV_TLSDESC_VALUE - R_FRV_TLSOFF - R_FRV_TLSMOFF12 - R_FRV_TLSMOFFHI - R_FRV_TLSMOFFLO - R_FRV_TLSMOFF + R_FRV_TLSDESC_VALUE + R_FRV_TLSOFF + R_FRV_TLSMOFF12 + R_FRV_TLSMOFFHI + R_FRV_TLSMOFFLO + R_FRV_TLSMOFF */ default: @@ -3606,9 +3590,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; @@ -3640,51 +3625,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 +3711,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; @@ -3757,33 +3753,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 +3790,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; @@ -3905,6 +3907,8 @@ elf32_frv_relocate_section (output_bfd, info, input_bfd, input_section, check_segment[1] = _frvfdpic_osec_to_segment (output_bfd, sec->output_section); } + else + check_segment[1] = -1; break; case R_FRV_GOTTLSOFF12: @@ -3919,7 +3923,7 @@ elf32_frv_relocate_section (output_bfd, info, input_bfd, input_section, ? _frvfdpic_osec_to_segment (output_bfd, sec->output_section) : tls_segment; break; - + case R_FRV_TLSDESC_VALUE: case R_FRV_TLSOFF: /* These shouldn't be present in input object files. */ @@ -3951,10 +3955,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 @@ -3962,12 +3966,11 @@ elf32_frv_relocate_section (output_bfd, info, input_bfd, input_section, symbols. */ && !(picrel && picrel->symndx == -1 && picrel->d.h->root.type == bfd_link_hash_undefined)) - info->callbacks->warning - (info, - (info->shared || info->pie) - ? _("relocations between different segments are not supported") - : _("warning: 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)) return FALSE; elf_elfheader (output_bfd)->e_flags |= EF_FRV_PIC; @@ -4113,8 +4116,12 @@ elf32_frv_relocate_section (output_bfd, info, input_bfd, input_section, } if (msg) - r = info->callbacks->warning - (info, msg, name, input_bfd, input_section, rel->r_offset); + { + info->callbacks->einfo + (_("%H: reloc against `%s': %s\n"), + input_bfd, input_section, rel->r_offset, name, msg); + return FALSE; + } if (! r) return FALSE; @@ -4128,54 +4135,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); + switch (ELF32_R_TYPE (rel->r_info)) + { + case R_FRV_GNU_VTINHERIT: + case R_FRV_GNU_VTENTRY: + return NULL; + } - return NULL; + return _bfd_elf_gc_mark_hook (sec, info, rel, h, sym); } - -/* Update the got entry reference counts for the section being removed. */ - -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; -} - /* 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. */ @@ -4201,11 +4176,11 @@ elf32_frv_add_symbol_hook (abfd, info, sym, namep, flagsp, secp, valp) if (scomm == NULL) { - scomm = bfd_make_section (abfd, ".scommon"); - if (scomm == NULL - || !bfd_set_section_flags (abfd, scomm, (SEC_ALLOC - | SEC_IS_COMMON - | SEC_LINKER_CREATED))) + scomm = bfd_make_section_with_flags (abfd, ".scommon", + (SEC_ALLOC + | SEC_IS_COMMON + | SEC_LINKER_CREATED)); + if (scomm == NULL) return FALSE; } @@ -4270,17 +4245,15 @@ _frv_create_got_section (bfd *abfd, struct bfd_link_info *info) | SEC_LINKER_CREATED); pltflags = flags; - s = bfd_make_section (abfd, ".got"); + s = bfd_make_section_with_flags (abfd, ".got", flags); if (s == NULL - || !bfd_set_section_flags (abfd, s, flags) || !bfd_set_section_alignment (abfd, s, ptralign)) return FALSE; if (bed->want_got_plt) { - s = bfd_make_section (abfd, ".got.plt"); + s = bfd_make_section_with_flags (abfd, ".got.plt", flags); if (s == NULL - || !bfd_set_section_flags (abfd, s, flags) || !bfd_set_section_alignment (abfd, s, ptralign)) return FALSE; } @@ -4291,27 +4264,19 @@ _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, - bed->got_symbol_offset, (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. */ - s->size += bed->got_header_size + bed->got_symbol_offset; + s->size += bed->got_header_size; /* This is the machine-specific part. Create and initialize section data for the got. */ @@ -4325,18 +4290,18 @@ _frv_create_got_section (bfd *abfd, struct bfd_link_info *info) if (! frvfdpic_relocs_info (info)) return FALSE; - s = bfd_make_section (abfd, ".rel.got"); + s = bfd_make_section_with_flags (abfd, ".rel.got", + (flags | SEC_READONLY)); if (s == NULL - || ! bfd_set_section_flags (abfd, s, (flags | SEC_READONLY)) || ! bfd_set_section_alignment (abfd, s, 2)) return FALSE; frvfdpic_gotrel_section (info) = s; /* Machine-specific. */ - s = bfd_make_section (abfd, ".rofixup"); + s = bfd_make_section_with_flags (abfd, ".rofixup", + (flags | SEC_READONLY)); if (s == NULL - || ! bfd_set_section_flags (abfd, s, (flags | SEC_READONLY)) || ! bfd_set_section_alignment (abfd, s, 2)) return FALSE; @@ -4383,39 +4348,28 @@ _frv_create_got_section (bfd *abfd, struct bfd_link_info *info) if (bed->plt_readonly) pltflags |= SEC_READONLY; - s = bfd_make_section (abfd, ".plt"); + s = bfd_make_section_with_flags (abfd, ".plt", pltflags); if (s == NULL - || ! bfd_set_section_flags (abfd, s, pltflags) || ! 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 (abfd, ".rel.plt"); + s = bfd_make_section_with_flags (abfd, ".rel.plt", + flags | SEC_READONLY); if (s == NULL - || ! bfd_set_section_flags (abfd, s, flags | SEC_READONLY) || ! bfd_set_section_alignment (abfd, s, bed->s->log_file_align)) return FALSE; /* FRV-specific: remember it. */ @@ -4461,9 +4415,9 @@ 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 (abfd, ".dynbss"); - if (s == NULL - || ! bfd_set_section_flags (abfd, s, SEC_ALLOC | SEC_LINKER_CREATED)) + s = bfd_make_section_with_flags (abfd, ".dynbss", + SEC_ALLOC | SEC_LINKER_CREATED); + if (s == NULL) return FALSE; /* The .rel[a].bss section holds copy relocs. This section is not @@ -4479,11 +4433,11 @@ elf32_frvfdpic_create_dynamic_sections (bfd *abfd, struct bfd_link_info *info) copy relocs. */ if (! info->shared) { - s = bfd_make_section (abfd, - (bed->default_use_rela_p - ? ".rela.bss" : ".rel.bss")); + s = bfd_make_section_with_flags (abfd, + (bed->default_use_rela_p + ? ".rela.bss" : ".rel.bss"), + flags | SEC_READONLY); if (s == NULL - || ! bfd_set_section_flags (abfd, s, flags | SEC_READONLY) || ! bfd_set_section_alignment (abfd, s, bed->s->log_file_align)) return FALSE; } @@ -4568,7 +4522,7 @@ _frvfdpic_count_tls_entries (struct frvfdpic_relocs_info *entry, bfd_boolean subtract) { const int l = subtract ? -1 : 1; - + /* Allocate space for a GOT entry with the TLS offset of the symbol. */ if (entry->tlsoff12) @@ -4752,7 +4706,7 @@ _frvfdpic_relax_tls_entries (struct frvfdpic_relocs_info *entry, _frvfdpic_count_tls_entries (entry, dinfo, TRUE); changed = TRUE; } - + entry->tlsplt = entry->tlsoff12 = entry->tlsofflos = entry->tlsoffhilo = 0; } @@ -5236,7 +5190,7 @@ _frvfdpic_assign_plt_entries (void **entryp, void *info_) else size = 16; } - + frvfdpic_plt_section (dinfo->g.info)->size += size; } @@ -5607,7 +5561,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) @@ -5634,12 +5587,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; + + 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; + 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); + } - /* Create a stack section, and set its alignment. */ - sec = bfd_make_section (output_bfd, ".stack"); + 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 (sec == NULL - || ! bfd_set_section_alignment (output_bfd, sec, 3)) + if (!_frvfdpic_size_got_plt (obfd, &gpinfo)) return FALSE; } @@ -5667,6 +5726,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; @@ -5722,48 +5785,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; @@ -5813,8 +5873,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; } @@ -5822,9 +5882,10 @@ 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 = + bfd_vma value = frvfdpic_gotfixup_section (info)->output_section->vma + frvfdpic_gotfixup_section (info)->output_offset + frvfdpic_gotfixup_section (info)->size @@ -6093,7 +6154,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; @@ -6104,9 +6165,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; @@ -6119,7 +6177,12 @@ 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; + } switch (ELF32_R_TYPE (rel->r_info)) { @@ -6267,7 +6330,7 @@ elf32_frv_check_relocs (abfd, info, sec, relocs) case R_FRV_TLSDESC_VALUE: picrel->relocstlsd++; goto bad_reloc; - + case R_FRV_GOTTLSDESC12: picrel->tlsdesc12 = 1; break; @@ -6287,13 +6350,13 @@ elf32_frv_check_relocs (abfd, info, sec, relocs) picrel->tlsoff12 = 1; info->flags |= DF_STATIC_TLS; break; - + case R_FRV_GOTTLSOFFHI: case R_FRV_GOTTLSOFFLO: picrel->tlsoffhilo = 1; info->flags |= DF_STATIC_TLS; break; - + case R_FRV_TLSOFF: picrel->relocstlsoff++; info->flags |= DF_STATIC_TLS; @@ -6309,7 +6372,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; @@ -6328,8 +6393,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; } @@ -6400,6 +6465,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; } @@ -6762,7 +6831,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) { @@ -6831,7 +6900,88 @@ 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 @@ -6841,7 +6991,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 @@ -6850,6 +6999,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 @@ -6865,6 +7015,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 @@ -6886,9 +7039,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 @@ -6912,6 +7065,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