/* FR30-specific support for 32-bit ELF.
- Copyright (C) 1998 Free Software Foundation, Inc.
+ Copyright (C) 1998, 1999 Free Software Foundation, Inc.
This file is part of BFD, the Binary File Descriptor library.
PARAMS ((bfd *, struct bfd_link_info *, bfd *, asection *, bfd_byte *, Elf_Internal_Rela *, Elf_Internal_Sym *, asection **));
static bfd_reloc_status_type fr30_final_link_relocate
PARAMS ((reloc_howto_type *, bfd *, asection *, bfd_byte *, Elf_Internal_Rela *, bfd_vma));
+static boolean fr30_elf_gc_sweep_hook
+ PARAMS ((bfd *, struct bfd_link_info *, asection *, const Elf_Internal_Rela *));
+static asection * fr30_elf_gc_mark_hook
+ PARAMS ((bfd *, struct bfd_link_info *, Elf_Internal_Rela *, struct elf_link_hash_entry *, Elf_Internal_Sym *));
static reloc_howto_type fr30_elf_howto_table [] =
{
bfd_elf_generic_reloc, /* special_function */
"R_FR30_8", /* name */
true, /* partial_inplace */
- 0x0ff0, /* src_mask */
+ 0x0000, /* src_mask */
0x0ff0, /* dst_mask */
false), /* pcrel_offset */
fr30_elf_i20_reloc, /* special_function */
"R_FR30_20", /* name */
true, /* partial_inplace */
- 0x00f0ffff, /* src_mask */
+ 0x00000000, /* src_mask */
0x00f0ffff, /* dst_mask */
false), /* pcrel_offset */
bfd_elf_generic_reloc, /* special_function */
"R_FR30_32", /* name */
true, /* partial_inplace */
- 0xffffffff, /* src_mask */
+ 0x00000000, /* src_mask */
0xffffffff, /* dst_mask */
false), /* pcrel_offset */
0, /* bitpos */
complain_overflow_bitfield, /* complain_on_overflow */
fr30_elf_i32_reloc, /* special_function */
- "R_FR30_32", /* name */
+ "R_FR30_48", /* name */
true, /* partial_inplace */
- 0xffffffff, /* src_mask */
+ 0x00000000, /* src_mask */
0xffffffff, /* dst_mask */
false), /* pcrel_offset */
bfd_elf_generic_reloc, /* special_function */
"R_FR30_6_IN_4", /* name */
true, /* partial_inplace */
- 0x00f0, /* src_mask */
+ 0x0000, /* src_mask */
0x00f0, /* dst_mask */
false), /* pcrel_offset */
bfd_elf_generic_reloc,/* special_function */
"R_FR30_8_IN_8", /* name */
true, /* partial_inplace */
- 0x0ff0, /* src_mask */
+ 0x0000, /* src_mask */
0x0ff0, /* dst_mask */
false), /* pcrel_offset */
bfd_elf_generic_reloc,/* special_function */
"R_FR30_9_IN_8", /* name */
true, /* partial_inplace */
- 0x0ff0, /* src_mask */
+ 0x0000, /* src_mask */
0x0ff0, /* dst_mask */
false), /* pcrel_offset */
bfd_elf_generic_reloc,/* special_function */
"R_FR30_10_IN_8", /* name */
true, /* partial_inplace */
- 0x0ff0, /* src_mask */
+ 0x0000, /* src_mask */
0x0ff0, /* dst_mask */
false), /* pcrel_offset */
bfd_elf_generic_reloc, /* special_function */
"R_FR30_9_PCREL", /* name */
false, /* partial_inplace */
- 0x00ff, /* src_mask */
+ 0x0000, /* src_mask */
0x00ff, /* dst_mask */
false), /* pcrel_offset */
bfd_elf_generic_reloc, /* special_function */
"R_FR30_12_PCREL", /* name */
false, /* partial_inplace */
- 0x07ff, /* src_mask */
+ 0x0000, /* src_mask */
0x07ff, /* dst_mask */
false), /* pcrel_offset */
+ /* GNU extension to record C++ vtable hierarchy */
+ HOWTO (R_FR30_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_FR30_GNU_VTINHERIT", /* name */
+ false, /* partial_inplace */
+ 0, /* src_mask */
+ 0, /* dst_mask */
+ false), /* pcrel_offset */
+
+ /* GNU extension to record C++ vtable member usage */
+ HOWTO (R_FR30_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_FR30_GNU_VTENTRY", /* name */
+ false, /* partial_inplace */
+ 0, /* src_mask */
+ 0, /* dst_mask */
+ false), /* pcrel_offset */
+
};
\f
/* Utility to actually perform an R_FR30_20 reloc. */
PTR data;
asection * input_section;
bfd * output_bfd;
- char ** error_message;
+ char ** error_message ATTRIBUTE_UNUSED;
{
bfd_vma relocation;
unsigned long x;
PTR data;
asection * input_section;
bfd * output_bfd;
- char ** error_message;
+ char ** error_message ATTRIBUTE_UNUSED;
{
bfd_vma relocation;
struct fr30_reloc_map
{
- unsigned int bfd_reloc_val;
+ bfd_reloc_code_real_type bfd_reloc_val;
unsigned int fr30_reloc_val;
};
{ BFD_RELOC_FR30_10_IN_8, R_FR30_10_IN_8 },
{ BFD_RELOC_FR30_9_PCREL, R_FR30_9_PCREL },
{ BFD_RELOC_FR30_12_PCREL, R_FR30_12_PCREL },
+ { BFD_RELOC_VTABLE_INHERIT, R_FR30_GNU_VTINHERIT },
+ { BFD_RELOC_VTABLE_ENTRY, R_FR30_GNU_VTENTRY },
};
static reloc_howto_type *
fr30_reloc_type_lookup (abfd, code)
- bfd * abfd;
+ bfd * abfd ATTRIBUTE_UNUSED;
bfd_reloc_code_real_type code;
{
unsigned int i;
static void
fr30_info_to_howto_rela (abfd, cache_ptr, dst)
- bfd * abfd;
+ bfd * abfd ATTRIBUTE_UNUSED;
arelent * cache_ptr;
Elf32_Internal_Rela * dst;
{
x = bfd_get_32 (input_bfd, contents);
x = (x & 0xff0f0000) | (relocation & 0x0000ffff) | ((relocation & 0x000f0000) << 4);
- bfd_put_32 (input_bfd, relocation, contents);
+ bfd_put_32 (input_bfd, x, contents);
break;
case R_FR30_48:
static boolean
fr30_elf_relocate_section (output_bfd, info, input_bfd, input_section,
contents, relocs, local_syms, local_sections)
- bfd * output_bfd;
+ bfd * output_bfd ATTRIBUTE_UNUSED;
struct bfd_link_info * info;
bfd * input_bfd;
asection * input_section;
bfd_vma relocation;
bfd_reloc_status_type r;
const char * name = NULL;
-
+ int r_type;
+
+ r_type = ELF32_R_TYPE (rel->r_info);
+
+ if ( r_type == R_FR30_GNU_VTINHERIT
+ || r_type == R_FR30_GNU_VTENTRY)
+ continue;
+
r_symndx = ELF32_R_SYM (rel->r_info);
if (info->relocateable)
return true;
}
\f
+/* Return the section that should be marked against GC for a given
+ relocation. */
+
+static asection *
+fr30_elf_gc_mark_hook (abfd, info, rel, h, sym)
+ bfd * abfd;
+ struct bfd_link_info * info ATTRIBUTE_UNUSED;
+ 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_FR30_GNU_VTINHERIT:
+ case R_FR30_GNU_VTENTRY:
+ break;
+
+ default:
+ switch (h->root.type)
+ {
+ 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;
+
+ default:
+ break;
+ }
+ }
+ }
+ else
+ {
+ if (!(elf_bad_symtab (abfd)
+ && ELF_ST_BIND (sym->st_info) != STB_LOCAL)
+ && ! ((sym->st_shndx <= 0 || sym->st_shndx >= SHN_LORESERVE)
+ && sym->st_shndx != SHN_COMMON))
+ {
+ return bfd_section_from_elf_index (abfd, sym->st_shndx);
+ }
+ }
+
+ return NULL;
+}
+
+/* Update the got entry reference counts for the section being removed. */
+
+static boolean
+fr30_elf_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;
+}
+
+/* Look through the relocs for a section during the first phase.
+ Since we don't do .gots or .plts, we just need to consider the
+ virtual table relocs for gc. */
+
+static boolean
+fr30_elf_check_relocs (abfd, info, sec, relocs)
+ bfd *abfd;
+ struct bfd_link_info *info;
+ asection *sec;
+ const Elf_Internal_Rela *relocs;
+{
+ Elf_Internal_Shdr *symtab_hdr;
+ struct elf_link_hash_entry **sym_hashes, **sym_hashes_end;
+ const Elf_Internal_Rela *rel;
+ const Elf_Internal_Rela *rel_end;
+
+ if (info->relocateable)
+ return true;
+
+ symtab_hdr = &elf_tdata (abfd)->symtab_hdr;
+ sym_hashes = elf_sym_hashes (abfd);
+ sym_hashes_end = sym_hashes + symtab_hdr->sh_size/sizeof(Elf32_External_Sym);
+ if (!elf_bad_symtab (abfd))
+ sym_hashes_end -= symtab_hdr->sh_info;
+
+ rel_end = relocs + sec->reloc_count;
+ for (rel = relocs; rel < rel_end; rel++)
+ {
+ struct elf_link_hash_entry *h;
+ unsigned long r_symndx;
+
+ 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];
+
+ switch (ELF32_R_TYPE (rel->r_info))
+ {
+ /* This relocation describes the C++ object vtable hierarchy.
+ Reconstruct it for later use during GC. */
+ case R_FR30_GNU_VTINHERIT:
+ if (!_bfd_elf32_gc_record_vtinherit (abfd, sec, h, rel->r_offset))
+ return false;
+ break;
+
+ /* This relocation describes which C++ vtable entries are actually
+ used. Record for later use during GC. */
+ case R_FR30_GNU_VTENTRY:
+ if (!_bfd_elf32_gc_record_vtentry (abfd, sec, h, rel->r_addend))
+ return false;
+ break;
+ }
+ }
+
+ return true;
+}
+\f
#define ELF_ARCH bfd_arch_fr30
#define ELF_MACHINE_CODE EM_CYGNUS_FR30
#define ELF_MAXPAGESIZE 0x1000
#define elf_info_to_howto_rel NULL
#define elf_info_to_howto fr30_info_to_howto_rela
#define elf_backend_relocate_section fr30_elf_relocate_section
+#define elf_backend_gc_mark_hook fr30_elf_gc_mark_hook
+#define elf_backend_gc_sweep_hook fr30_elf_gc_sweep_hook
+#define elf_backend_check_relocs fr30_elf_check_relocs
+
+#define elf_backend_can_gc_sections 1
#define bfd_elf32_bfd_reloc_type_lookup fr30_reloc_type_lookup
-
+
#include "elf32-target.h"