/* M32R-specific support for 32-bit ELF.
- Copyright (C) 1996, 1997, 1998 Free Software Foundation, Inc.
+ Copyright (C) 1996, 1997, 1998, 1999 Free Software Foundation, Inc.
This file is part of BFD, the Binary File Descriptor library.
PARAMS ((bfd *, asection *, bfd_vma, int));
#endif
+static bfd_reloc_status_type m32r_elf_final_sda_base
+ PARAMS ((bfd *, struct bfd_link_info *, const char **, bfd_vma *));
+static boolean m32r_elf_object_p
+ PARAMS ((bfd *));
+static void m32r_elf_final_write_processing
+ PARAMS ((bfd *, boolean));
+static boolean m32r_elf_set_private_flags
+ PARAMS ((bfd *, flagword));
+static boolean m32r_elf_copy_private_bfd_data
+ PARAMS ((bfd *, bfd *));
+static boolean m32r_elf_merge_private_bfd_data
+ PARAMS ((bfd *, bfd *));
+static boolean m32r_elf_print_private_bfd_data
+ PARAMS ((bfd *, PTR));
+
#define NOP_INSN 0x7000
#define MAKE_PARALLEL(insn) ((insn) | 0x8000)
HOWTO (R_M32R_18_PCREL, /* type */
2, /* rightshift */
2, /* size (0 = byte, 1 = short, 2 = long) */
- 18, /* bitsize */
+ 16, /* bitsize */
true, /* pc_relative */
0, /* bitpos */
complain_overflow_signed, /* complain_on_overflow */
0x0000ffff, /* src_mask */
0x0000ffff, /* dst_mask */
false), /* pcrel_offset */
+
+ /* GNU extension to record C++ vtable hierarchy */
+ HOWTO (R_M32R_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_M32R_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_M32R_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_M32R_GNU_VTENTRY", /* name */
+ false, /* partial_inplace */
+ 0, /* src_mask */
+ 0, /* dst_mask */
+ false), /* pcrel_offset */
+
};
\f
/* Handle the R_M32R_10_PCREL reloc. */
struct m32r_reloc_map
{
- unsigned char bfd_reloc_val;
+ bfd_reloc_code_real_type bfd_reloc_val;
unsigned char elf_reloc_val;
};
{ BFD_RELOC_M32R_HI16_SLO, R_M32R_HI16_SLO },
{ BFD_RELOC_M32R_LO16, R_M32R_LO16 },
{ BFD_RELOC_M32R_SDA16, R_M32R_SDA16 },
+ { BFD_RELOC_VTABLE_INHERIT, R_M32R_GNU_VTINHERIT },
+ { BFD_RELOC_VTABLE_ENTRY, R_M32R_GNU_VTENTRY },
};
static reloc_howto_type *
continue;
}
+ if (r_type == R_M32R_GNU_VTENTRY
+ || r_type == R_M32R_GNU_VTINHERIT)
+ continue;
+
howto = m32r_elf_howto_table + r_type;
r_symndx = ELF32_R_SYM (rel->r_info);
switch (elf_elfheader (abfd)->e_flags & EF_M32R_ARCH)
{
default:
- case E_M32R_ARCH: (void) bfd_default_set_arch_mach (abfd, bfd_arch_m32r, bfd_mach_m32r); break;
-/* start-sanitize-m32rx */
- case E_M32RX_ARCH: (void) bfd_default_set_arch_mach (abfd, bfd_arch_m32r, bfd_mach_m32rx); break;
-/* end-sanitize-m32rx */
+ case E_M32R_ARCH: (void) bfd_default_set_arch_mach (abfd, bfd_arch_m32r, bfd_mach_m32r); break;
}
return true;
}
/* Store the machine number in the flags field. */
-void
+static void
m32r_elf_final_write_processing (abfd, linker)
bfd * abfd;
boolean linker;
{
default:
case bfd_mach_m32r: val = E_M32R_ARCH; break;
-/* start-sanitize-m32rx */
- case bfd_mach_m32rx: val = E_M32RX_ARCH; break;
-/* end-sanitize-m32rx */
}
elf_elfheader (abfd)->e_flags &=~ EF_M32R_ARCH;
}
/* Function to keep M32R specific file flags. */
-boolean
+static boolean
m32r_elf_set_private_flags (abfd, flags)
bfd * abfd;
flagword flags;
}
/* Copy backend specific data from one object module to another */
-boolean
+static boolean
m32r_elf_copy_private_bfd_data (ibfd, obfd)
bfd * ibfd;
bfd * obfd;
/* Merge backend specific data from an object file to the output
object file when linking. */
-boolean
+static boolean
m32r_elf_merge_private_bfd_data (ibfd, obfd)
bfd * ibfd;
bfd * obfd;
switch (elf_elfheader (abfd)->e_flags & EF_M32R_ARCH)
{
default:
- case E_M32R_ARCH: fprintf (file, _(": m32r instructions")); break;
-/* start-sanitize-m32rx */
- case E_M32RX_ARCH: fprintf (file, _(": m32rx instructions")); break;
-/* end-sanitize-m32rx */
+ case E_M32R_ARCH: fprintf (file, _(": m32r instructions")); break;
}
fputc ('\n', file);
return true;
}
+asection *
+m32r_elf_gc_mark_hook (abfd, info, rel, h, sym)
+ bfd *abfd;
+ 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_M32R_GNU_VTINHERIT:
+ case R_M32R_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;
+ }
+ }
+ }
+ 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;
+}
+
+static boolean
+m32r_elf_gc_sweep_hook (abfd, info, sec, relocs)
+ bfd *abfd;
+ struct bfd_link_info *info;
+ asection *sec;
+ const Elf_Internal_Rela *relocs;
+{
+ /* we don't use got and plt entries for m32r */
+ 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
+m32r_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_M32R_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_M32R_GNU_VTENTRY:
+ if (!_bfd_elf32_gc_record_vtentry (abfd, sec, h, rel->r_offset))
+ return false;
+ break;
+ }
+ }
+
+ return true;
+}
+
+
\f
#define ELF_ARCH bfd_arch_m32r
#define elf_backend_symbol_processing _bfd_m32r_elf_symbol_processing
#define elf_backend_add_symbol_hook m32r_elf_add_symbol_hook
#define elf_backend_relocate_section m32r_elf_relocate_section
+#define elf_backend_gc_mark_hook m32r_elf_gc_mark_hook
+#define elf_backend_gc_sweep_hook m32r_elf_gc_sweep_hook
+#define elf_backend_check_relocs m32r_elf_check_relocs
+#define elf_backend_can_gc_sections 1
#if 0 /* not yet */
/* relax support */
#define bfd_elf32_bfd_relax_section m32r_elf_relax_section