/* Motorola 68k series support for 32-bit ELF
Copyright 1993, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003,
- 2004, 2005, 2006, 2007, 2008, 2009 Free Software Foundation, Inc.
+ 2004, 2005, 2006, 2007, 2008, 2009, 2010 Free Software Foundation, Inc.
This file is part of BFD, the Binary File Descriptor library.
};
static void
-rtype_to_howto (abfd, cache_ptr, dst)
- bfd *abfd ATTRIBUTE_UNUSED;
- arelent *cache_ptr;
- Elf_Internal_Rela *dst;
+rtype_to_howto (bfd *abfd, arelent *cache_ptr, Elf_Internal_Rela *dst)
{
- BFD_ASSERT (ELF32_R_TYPE(dst->r_info) < (unsigned int) R_68K_max);
- cache_ptr->howto = &howto_table[ELF32_R_TYPE(dst->r_info)];
+ unsigned int indx = ELF32_R_TYPE (dst->r_info);
+
+ if (indx >= (unsigned int) R_68K_max)
+ {
+ (*_bfd_error_handler) (_("%B: invalid relocation type %d"),
+ abfd, (int) indx);
+ indx = R_68K_NONE;
+ }
+ cache_ptr->howto = &howto_table[indx];
}
#define elf_info_to_howto rtype_to_howto
/* Get the m68k ELF linker hash table from a link_info structure. */
#define elf_m68k_hash_table(p) \
- ((struct elf_m68k_link_hash_table *) (p)->hash)
+ (elf_hash_table_id ((struct elf_link_hash_table *) ((p)->hash)) \
+ == M68K_ELF_DATA ? ((struct elf_m68k_link_hash_table *) ((p)->hash)) : NULL)
/* Shortcut to multi-GOT data. */
#define elf_m68k_multi_got(INFO) (&elf_m68k_hash_table (INFO)->multi_got_)
/* Create an entry in an m68k ELF linker hash table. */
static struct bfd_hash_entry *
-elf_m68k_link_hash_newfunc (entry, table, string)
- struct bfd_hash_entry *entry;
- struct bfd_hash_table *table;
- const char *string;
+elf_m68k_link_hash_newfunc (struct bfd_hash_entry *entry,
+ struct bfd_hash_table *table,
+ const char *string)
{
struct bfd_hash_entry *ret = entry;
/* Create an m68k ELF linker hash table. */
static struct bfd_link_hash_table *
-elf_m68k_link_hash_table_create (abfd)
- bfd *abfd;
+elf_m68k_link_hash_table_create (bfd *abfd)
{
struct elf_m68k_link_hash_table *ret;
bfd_size_type amt = sizeof (struct elf_m68k_link_hash_table);
if (!_bfd_elf_link_hash_table_init (&ret->root, abfd,
elf_m68k_link_hash_newfunc,
- sizeof (struct elf_m68k_link_hash_entry)))
+ sizeof (struct elf_m68k_link_hash_entry),
+ M68K_ELF_DATA))
{
free (ret);
return NULL;
return TRUE;
}
+/* Somewhat reverse of elf32_m68k_object_p, this sets the e_flag
+ field based on the machine number. */
+
+static void
+elf_m68k_final_write_processing (bfd *abfd,
+ bfd_boolean linker ATTRIBUTE_UNUSED)
+{
+ int mach = bfd_get_mach (abfd);
+ unsigned long e_flags = elf_elfheader (abfd)->e_flags;
+
+ if (!e_flags)
+ {
+ unsigned int arch_mask;
+
+ arch_mask = bfd_m68k_mach_to_features (mach);
+
+ if (arch_mask & m68000)
+ e_flags = EF_M68K_M68000;
+ else if (arch_mask & cpu32)
+ e_flags = EF_M68K_CPU32;
+ else if (arch_mask & fido_a)
+ e_flags = EF_M68K_FIDO;
+ else
+ {
+ switch (arch_mask
+ & (mcfisa_a | mcfisa_aa | mcfisa_b | mcfisa_c | mcfhwdiv | mcfusp))
+ {
+ case mcfisa_a:
+ e_flags |= EF_M68K_CF_ISA_A_NODIV;
+ break;
+ case mcfisa_a | mcfhwdiv:
+ e_flags |= EF_M68K_CF_ISA_A;
+ break;
+ case mcfisa_a | mcfisa_aa | mcfhwdiv | mcfusp:
+ e_flags |= EF_M68K_CF_ISA_A_PLUS;
+ break;
+ case mcfisa_a | mcfisa_b | mcfhwdiv:
+ e_flags |= EF_M68K_CF_ISA_B_NOUSP;
+ break;
+ case mcfisa_a | mcfisa_b | mcfhwdiv | mcfusp:
+ e_flags |= EF_M68K_CF_ISA_B;
+ break;
+ case mcfisa_a | mcfisa_c | mcfhwdiv | mcfusp:
+ e_flags |= EF_M68K_CF_ISA_C;
+ break;
+ case mcfisa_a | mcfisa_c | mcfusp:
+ e_flags |= EF_M68K_CF_ISA_C_NODIV;
+ break;
+ }
+ if (arch_mask & mcfmac)
+ e_flags |= EF_M68K_CF_MAC;
+ else if (arch_mask & mcfemac)
+ e_flags |= EF_M68K_CF_EMAC;
+ if (arch_mask & cfloat)
+ e_flags |= EF_M68K_CF_FLOAT | EF_M68K_CFV4E;
+ }
+ elf_elfheader (abfd)->e_flags = e_flags;
+ }
+}
+
/* Keep m68k-specific flags in the ELF header. */
+
static bfd_boolean
elf32_m68k_set_private_flags (abfd, flags)
bfd *abfd;
static enum elf_m68k_reloc_type
elf_m68k_update_got_entry_type (struct elf_m68k_got *got,
enum elf_m68k_reloc_type was,
- enum elf_m68k_reloc_type new)
+ enum elf_m68k_reloc_type new_reloc)
{
enum elf_m68k_got_offset_size was_size;
enum elf_m68k_got_offset_size new_size;
/* Update all got->n_slots counters, including n_slots[R_32]. */
was_size = R_LAST;
- was = new;
+ was = new_reloc;
}
else
{
/* !!! We, probably, should emit an error rather then fail on assert
in such a case. */
BFD_ASSERT (elf_m68k_reloc_got_type (was)
- == elf_m68k_reloc_got_type (new));
+ == elf_m68k_reloc_got_type (new_reloc));
was_size = elf_m68k_reloc_got_offset_size (was);
}
- new_size = elf_m68k_reloc_got_offset_size (new);
- n_slots = elf_m68k_reloc_got_n_slots (new);
+ new_size = elf_m68k_reloc_got_offset_size (new_reloc);
+ n_slots = elf_m68k_reloc_got_n_slots (new_reloc);
while (was_size > new_size)
{
got->n_slots[was_size] += n_slots;
}
- if (new > was)
+ if (new_reloc > was)
/* Relocations are ordered from bigger got offset size to lesser,
so choose the relocation type with lesser offset size. */
- was = new;
+ was = new_reloc;
return was;
}
struct elf_link_hash_entry **sym_hashes;
const Elf_Internal_Rela *rel, *relend;
bfd *dynobj;
- asection *sgot;
- asection *srelgot;
struct elf_m68k_got *got;
if (info->relocatable)
symtab_hdr = &elf_tdata (abfd)->symtab_hdr;
sym_hashes = elf_sym_hashes (abfd);
-
- sgot = bfd_get_section_by_name (dynobj, ".got");
- srelgot = bfd_get_section_by_name (dynobj, ".rela.got");
got = NULL;
relend = relocs + sec->reloc_count;
elf_m68k_adjust_dynamic_symbol
#define elf_backend_size_dynamic_sections \
elf_m68k_size_dynamic_sections
+#define elf_backend_final_write_processing elf_m68k_final_write_processing
#define elf_backend_init_index_section _bfd_elf_init_1_index_section
#define elf_backend_relocate_section elf_m68k_relocate_section
#define elf_backend_finish_dynamic_symbol \