/* FRV-specific support for 32-bit ELF.
- Copyright 2002, 2003, 2004 Free Software Foundation, Inc.
+ Copyright 2002, 2003, 2004, 2005, 2006, 2007, 2008
+ 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. */
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 *));
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 [] =
{
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 */
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 */
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 */
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 */
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 */
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 */
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 */
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 */
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 */
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 */
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 */
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 */
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 */
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. */
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. */
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 */
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. */
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. */
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 */
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 */
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. */
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
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. */
/* 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 */
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 */
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. */
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 */
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 */
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. */
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 */
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 */
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. */
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. */
/* 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 */
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. */
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)))
{
free (ret);
return NULL;
its function descriptor must be assigned by the dynamic linker. */
#define FRVFDPIC_SYM_LOCAL(INFO, H) \
(_bfd_elf_symbol_refs_local_p ((H), (INFO), 1) \
- || ! elf_hash_table (INFO)->dynamic_sections_created \
- /* These two additional alternatives are needed for TLS
- relocations, that use *ABS*+offset relocations to refer to the
- TLS section of the local module. FIXME: At some point during
- linking, the definition section ceases to be regarded as the
- absolute section, and starts being regarded as the undefined
- section. */ \
- || bfd_is_abs_section ((H)->root.u.def.section) \
- || bfd_is_und_section ((H)->root.u.def.section))
+ || ! elf_hash_table (INFO)->dynamic_sections_created)
#define FRVFDPIC_FUNCDESC_LOCAL(INFO, H) \
((H)->dynindx == -1 || ! elf_hash_table (INFO)->dynamic_sections_created)
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
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
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;
idx = dynindx;
ad = addend;
if (ad)
- return FALSE;
+ {
+ (*info->callbacks->reloc_dangerous)
+ (info, _("relocation requires zero addend"),
+ elf_hash_table (info)->dynobj,
+ frvfdpic_got_section (info),
+ entry->fdgot_entry);
+ return FALSE;
+ }
}
else
{
else if (entry->lazyplt)
{
if (ad)
- return FALSE;
+ {
+ (*info->callbacks->reloc_dangerous)
+ (info, _("relocation requires zero addend"),
+ elf_hash_table (info)->dynobj,
+ frvfdpic_got_section (info),
+ entry->fd_entry);
+ return FALSE;
+ }
fd_lazy_rel_offset = ofst;
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
&& (bfd_is_abs_section (sec)
|| bfd_is_und_section (sec)))
{
+ if (! elf_hash_table (info)->tls_sec)
+ {
+ (*info->callbacks->undefined_symbol)
+ (info, "TLS section", elf_hash_table (info)->dynobj,
+ frvfdpic_got_section (info), entry->tlsoff_entry, TRUE);
+ return FALSE;
+ }
idx = elf_section_data (elf_hash_table (info)->tls_sec)->dynindx;
ad += FRVFDPIC_TLS_BIAS;
}
->output_offset,
R_FRV_TLSOFF, idx, ad, entry);
}
-
+
bfd_put_32 (output_bfd, ad,
frvfdpic_got_section (info)->contents
+ frvfdpic_got_initial_offset (info)
&& (bfd_is_abs_section (sec)
|| bfd_is_und_section (sec)))
{
+ if (! elf_hash_table (info)->tls_sec)
+ {
+ (*info->callbacks->undefined_symbol)
+ (info, "TLS section", elf_hash_table (info)->dynobj,
+ frvfdpic_got_section (info), entry->tlsdesc_entry, TRUE);
+ return FALSE;
+ }
idx = elf_section_data (elf_hash_table (info)->tls_sec)->dynindx;
ad += FRVFDPIC_TLS_BIAS;
}
{
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)))
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. */
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)))
{
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
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;
|| 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;
}
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)
rel->r_addend))
{
(*_bfd_error_handler)
- (_("%B: relocation at `%A+0x%x' references symbol `%s' with nonzero addend"),
- input_bfd, input_section, rel->r_offset, name);
+ (_("%B(%A+0x%x): relocation to `%s+%x' may have caused the error above"),
+ input_bfd, input_section, rel->r_offset, name, rel->r_addend);
return FALSE;
-
}
break;
(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)))
name, input_bfd, input_section, rel->r_offset);
return FALSE;
}
-
+
if (RELAX_GETTLSOFF_LOCAL_EXEC_P (info, picrel,
relocation + rel->r_addend))
{
}
break;
-
+
case R_FRV_GOTTLSDESCLO:
insn = bfd_get_32 (input_bfd, contents + rel->r_offset);
}
break;
-
+
case R_FRV_TLSDESC_RELAX:
insn = bfd_get_32 (input_bfd, contents + rel->r_offset);
/*
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:
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))
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))
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;
}
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);
+ }
}
}
}
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))
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;
check_segment[1] =
_frvfdpic_osec_to_segment (output_bfd, sec->output_section);
}
+ else
+ check_segment[1] = -1;
break;
case R_FRV_GOTTLSOFF12:
? _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. */
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);
+ {
+ if (info->shared || info->pie)
+ (*_bfd_error_handler)
+ (_("%B(%A+0x%lx): reloc against `%s': %s"),
+ input_bfd, input_section, (long)rel->r_offset, name,
+ _("relocation references a different segment"));
+ else
+ info->callbacks->warning
+ (info,
+ _("relocation references a different segment"),
+ name, input_bfd, input_section, rel->r_offset);
+ }
if (!silence_segment_error && (info->shared || info->pie))
return FALSE;
elf_elfheader (output_bfd)->e_flags |= EF_FRV_PIC;
}
if (msg)
- r = info->callbacks->warning
- (info, msg, name, input_bfd, input_section, rel->r_offset);
+ {
+ (*_bfd_error_handler)
+ (_("%B(%A+0x%lx): reloc against `%s': %s"),
+ input_bfd, input_section, (long)rel->r_offset, name, msg);
+ return FALSE;
+ }
if (! r)
return FALSE;
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);
}
-
\f
/* 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. */
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;
}
| 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;
}
(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. */
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;
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. */
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
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;
}
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)
_frvfdpic_count_tls_entries (entry, dinfo, TRUE);
changed = TRUE;
}
-
+
entry->tlsplt =
entry->tlsoff12 = entry->tlsofflos = entry->tlsoffhilo = 0;
}
else
size = 16;
}
-
+
frvfdpic_plt_section (dinfo->g.info)->size += size;
}
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)
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;
+ }
- /* Create a stack section, and set its alignment. */
- sec = bfd_make_section (output_bfd, ".stack");
+ 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 (sec == NULL
- || ! bfd_set_section_alignment (output_bfd, sec, 3))
+ 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;
}
{
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;
}
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;
&& (hend->type == bfd_link_hash_defined
|| hend->type == bfd_link_hash_defweak))
{
- bfd_vma value =
+ bfd_vma value =
frvfdpic_gotfixup_section (info)->output_section->vma
+ frvfdpic_gotfixup_section (info)->output_offset
+ frvfdpic_gotfixup_section (info)->size
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;
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;
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))
{
case R_FRV_TLSDESC_VALUE:
picrel->relocstlsd++;
goto bad_reloc;
-
+
case R_FRV_GOTTLSDESC12:
picrel->tlsdesc12 = 1;
break;
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;
/* 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;
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;
}
_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)
{
}
\f
+/* 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_pid = 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
#define elf_info_to_howto frv_info_to_howto_rela
#define elf_backend_relocate_section elf32_frv_relocate_section
#define elf_backend_gc_mark_hook elf32_frv_gc_mark_hook
-#define elf_backend_gc_sweep_hook elf32_frv_gc_sweep_hook
#define elf_backend_check_relocs elf32_frv_check_relocs
#define elf_backend_object_p elf32_frv_object_p
#define elf_backend_add_symbol_hook elf32_frv_add_symbol_hook
#define elf_backend_rela_normal 1
#define bfd_elf32_bfd_reloc_type_lookup frv_reloc_type_lookup
+#define bfd_elf32_bfd_reloc_name_lookup frv_reloc_name_lookup
#define bfd_elf32_bfd_set_private_flags frv_elf_set_private_flags
#define bfd_elf32_bfd_copy_private_bfd_data frv_elf_copy_private_bfd_data
#define bfd_elf32_bfd_merge_private_bfd_data frv_elf_merge_private_bfd_data
#define 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
#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
#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