/* Motorola MCore specific support for 32-bit ELF
- Copyright 1994, 1995, 1999, 2000, 2001, 2002, 2003, 2004
- Free Software Foundation, Inc.
+ Copyright 1994, 1995, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006,
+ 2007 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 2 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 02110-1301, 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. */
/* This file is based on a preliminary RCE ELF ABI. The
information may not match the final RCE ELF ABI. */
-#include "bfd.h"
#include "sysdep.h"
+#include "bfd.h"
#include "bfdlink.h"
#include "libbfd.h"
#include "elf-bfd.h"
/* RELA relocs are used here... */
-static void mcore_elf_howto_init
- PARAMS ((void));
-static reloc_howto_type * mcore_elf_reloc_type_lookup
- PARAMS ((bfd *, bfd_reloc_code_real_type));
-static void mcore_elf_info_to_howto
- PARAMS ((bfd *, arelent *, Elf_Internal_Rela *));
-static bfd_boolean mcore_elf_set_private_flags
- PARAMS ((bfd *, flagword));
-static bfd_boolean mcore_elf_merge_private_bfd_data
- PARAMS ((bfd *, bfd *));
-static bfd_reloc_status_type mcore_elf_unsupported_reloc
- PARAMS ((bfd *, arelent *, asymbol *, PTR, asection *, bfd *, char **));
-static bfd_boolean mcore_elf_relocate_section
- PARAMS ((bfd *, struct bfd_link_info *, bfd *, asection *, bfd_byte *,
- Elf_Internal_Rela *, Elf_Internal_Sym *, asection **));
-static asection * mcore_elf_gc_mark_hook
- PARAMS ((asection *, struct bfd_link_info *, Elf_Internal_Rela *,
- struct elf_link_hash_entry *, Elf_Internal_Sym *));
-static bfd_boolean mcore_elf_gc_sweep_hook
- PARAMS ((bfd *, struct bfd_link_info *, asection *,
- const Elf_Internal_Rela *));
-static bfd_boolean mcore_elf_check_relocs
- PARAMS ((bfd *, struct bfd_link_info *, asection *,
- const Elf_Internal_Rela *));
+/* Function to set whether a module needs the -mrelocatable bit set. */
+
+static bfd_boolean
+mcore_elf_set_private_flags (bfd * abfd, flagword flags)
+{
+ BFD_ASSERT (! elf_flags_init (abfd)
+ || elf_elfheader (abfd)->e_flags == flags);
+
+ elf_elfheader (abfd)->e_flags = flags;
+ elf_flags_init (abfd) = TRUE;
+ return TRUE;
+}
+
+/* Merge backend specific data from an object file to the output
+ object file when linking. */
+
+static bfd_boolean
+mcore_elf_merge_private_bfd_data (bfd * ibfd, bfd * obfd)
+{
+ flagword old_flags;
+ flagword new_flags;
+
+ /* Check if we have the same endianess. */
+ if (! _bfd_generic_verify_endian_match (ibfd, obfd))
+ return FALSE;
+
+ if ( bfd_get_flavour (ibfd) != bfd_target_elf_flavour
+ || bfd_get_flavour (obfd) != bfd_target_elf_flavour)
+ return TRUE;
+
+ new_flags = elf_elfheader (ibfd)->e_flags;
+ old_flags = elf_elfheader (obfd)->e_flags;
+
+ if (! elf_flags_init (obfd))
+ {
+ /* First call, no flags set. */
+ elf_flags_init (obfd) = TRUE;
+ elf_elfheader (obfd)->e_flags = new_flags;
+ }
+ else if (new_flags == old_flags)
+ /* Compatible flags are OK. */
+ ;
+ else
+ {
+ /* FIXME */
+ }
+
+ return TRUE;
+}
+\f
+/* Don't pretend we can deal with unsupported relocs. */
+
+static bfd_reloc_status_type
+mcore_elf_unsupported_reloc (bfd * abfd,
+ arelent * reloc_entry,
+ asymbol * symbol ATTRIBUTE_UNUSED,
+ PTR data ATTRIBUTE_UNUSED,
+ asection * input_section ATTRIBUTE_UNUSED,
+ bfd * output_bfd ATTRIBUTE_UNUSED,
+ char ** error_message ATTRIBUTE_UNUSED)
+{
+ BFD_ASSERT (reloc_entry->howto != (reloc_howto_type *)0);
+
+ _bfd_error_handler (_("%B: Relocation %s (%d) is not currently supported.\n"),
+ abfd,
+ reloc_entry->howto->name,
+ reloc_entry->howto->type);
+
+ return bfd_reloc_notsupported;
+}
static reloc_howto_type * mcore_elf_howto_table [(int) R_MCORE_max];
0x7ff, /* dst_mask */
TRUE), /* pcrel_offset */
- /* GNU extension to record C++ vtable hierarchy */
+ /* GNU extension to record C++ vtable hierarchy. */
HOWTO (R_MCORE_GNU_VTINHERIT, /* type */
0, /* rightshift */
2, /* size (0 = byte, 1 = short, 2 = long) */
0, /* dst_mask */
FALSE), /* pcrel_offset */
- /* GNU extension to record C++ vtable member usage */
+ /* GNU extension to record C++ vtable member usage. */
HOWTO (R_MCORE_GNU_VTENTRY, /* type */
0, /* rightshift */
2, /* size (0 = byte, 1 = short, 2 = long) */
\f
/* Initialize the mcore_elf_howto_table, so that linear accesses can be done. */
static void
-mcore_elf_howto_init ()
+mcore_elf_howto_init (void)
{
unsigned int i;
}
\f
static reloc_howto_type *
-mcore_elf_reloc_type_lookup (abfd, code)
- bfd * abfd ATTRIBUTE_UNUSED;
- bfd_reloc_code_real_type code;
+mcore_elf_reloc_type_lookup (bfd * abfd ATTRIBUTE_UNUSED,
+ bfd_reloc_code_real_type code)
{
enum elf_mcore_reloc_type mcore_reloc = R_MCORE_NONE;
case BFD_RELOC_VTABLE_ENTRY: mcore_reloc = R_MCORE_GNU_VTENTRY; break;
case BFD_RELOC_RVA: mcore_reloc = R_MCORE_RELATIVE; break;
default:
- return (reloc_howto_type *)NULL;
+ return NULL;
}
- if (! mcore_elf_howto_table [R_MCORE_PCRELIMM8BY4]) /* Initialize howto table if needed */
+ if (! mcore_elf_howto_table [R_MCORE_PCRELIMM8BY4])
+ /* Initialize howto table if needed. */
mcore_elf_howto_init ();
return mcore_elf_howto_table [(int) mcore_reloc];
};
-/* Set the howto pointer for a RCE ELF reloc. */
-static void
-mcore_elf_info_to_howto (abfd, cache_ptr, dst)
- bfd * abfd ATTRIBUTE_UNUSED;
- arelent * cache_ptr;
- Elf_Internal_Rela * dst;
+static reloc_howto_type *
+mcore_elf_reloc_name_lookup (bfd *abfd ATTRIBUTE_UNUSED,
+ const char *r_name)
{
- if (! mcore_elf_howto_table [R_MCORE_PCRELIMM8BY4]) /* Initialize howto table if needed */
- mcore_elf_howto_init ();
-
- BFD_ASSERT (ELF32_R_TYPE (dst->r_info) < (unsigned int) R_MCORE_max);
-
- cache_ptr->howto = mcore_elf_howto_table [ELF32_R_TYPE (dst->r_info)];
-}
+ unsigned int i;
-/* Function to set whether a module needs the -mrelocatable bit set. */
-static bfd_boolean
-mcore_elf_set_private_flags (abfd, flags)
- bfd * abfd;
- flagword flags;
-{
- BFD_ASSERT (! elf_flags_init (abfd)
- || elf_elfheader (abfd)->e_flags == flags);
+ for (i = 0;
+ i < sizeof (mcore_elf_howto_raw) / sizeof (mcore_elf_howto_raw[0]);
+ i++)
+ if (mcore_elf_howto_raw[i].name != NULL
+ && strcasecmp (mcore_elf_howto_raw[i].name, r_name) == 0)
+ return &mcore_elf_howto_raw[i];
- elf_elfheader (abfd)->e_flags = flags;
- elf_flags_init (abfd) = TRUE;
- return TRUE;
+ return NULL;
}
-/* Merge backend specific data from an object file to the output
- object file when linking. */
-static bfd_boolean
-mcore_elf_merge_private_bfd_data (ibfd, obfd)
- bfd * ibfd;
- bfd * obfd;
-{
- flagword old_flags;
- flagword new_flags;
-
- /* Check if we have the same endianess */
- if (! _bfd_generic_verify_endian_match (ibfd, obfd))
- return FALSE;
-
- if ( bfd_get_flavour (ibfd) != bfd_target_elf_flavour
- || bfd_get_flavour (obfd) != bfd_target_elf_flavour)
- return TRUE;
-
- new_flags = elf_elfheader (ibfd)->e_flags;
- old_flags = elf_elfheader (obfd)->e_flags;
-
- if (! elf_flags_init (obfd)) /* First call, no flags set */
- {
- elf_flags_init (obfd) = TRUE;
- elf_elfheader (obfd)->e_flags = new_flags;
- }
- else if (new_flags == old_flags) /* Compatible flags are ok */
- ;
- else
- {
- /* FIXME */
- }
-
- return TRUE;
-}
-\f
-/* Don't pretend we can deal with unsupported relocs. */
+/* Set the howto pointer for a RCE ELF reloc. */
-static bfd_reloc_status_type
-mcore_elf_unsupported_reloc (abfd, reloc_entry, symbol, data, input_section,
- output_bfd, error_message)
- bfd * abfd;
- arelent * reloc_entry;
- asymbol * symbol ATTRIBUTE_UNUSED;
- PTR data ATTRIBUTE_UNUSED;
- asection * input_section ATTRIBUTE_UNUSED;
- bfd * output_bfd ATTRIBUTE_UNUSED;
- char ** error_message ATTRIBUTE_UNUSED;
+static void
+mcore_elf_info_to_howto (bfd * abfd ATTRIBUTE_UNUSED,
+ arelent * cache_ptr,
+ Elf_Internal_Rela * dst)
{
- BFD_ASSERT (reloc_entry->howto != (reloc_howto_type *)0);
+ if (! mcore_elf_howto_table [R_MCORE_PCRELIMM8BY4])
+ /* Initialize howto table if needed. */
+ mcore_elf_howto_init ();
- _bfd_error_handler (_("%B: Relocation %s (%d) is not currently supported.\n"),
- abfd,
- reloc_entry->howto->name,
- reloc_entry->howto->type);
+ BFD_ASSERT (ELF32_R_TYPE (dst->r_info) < (unsigned int) R_MCORE_max);
- return bfd_reloc_notsupported;
+ cache_ptr->howto = mcore_elf_howto_table [ELF32_R_TYPE (dst->r_info)];
}
\f
/* The RELOCATE_SECTION function is called by the ELF backend linker
accordingly. */
static bfd_boolean
-mcore_elf_relocate_section (output_bfd, info, input_bfd, input_section,
- contents, relocs, local_syms, local_sections)
- bfd * output_bfd;
- struct bfd_link_info * info;
- bfd * input_bfd;
- asection * input_section;
- bfd_byte * contents;
- Elf_Internal_Rela * relocs;
- Elf_Internal_Sym * local_syms;
- asection ** local_sections;
+mcore_elf_relocate_section (bfd * output_bfd,
+ struct bfd_link_info * info,
+ bfd * input_bfd,
+ asection * input_section,
+ bfd_byte * contents,
+ Elf_Internal_Rela * relocs,
+ Elf_Internal_Sym * local_syms,
+ asection ** local_sections)
{
Elf_Internal_Shdr * symtab_hdr = & elf_tdata (input_bfd)->symtab_hdr;
struct elf_link_hash_entry ** sym_hashes = elf_sym_hashes (input_bfd);
(info->relocatable) ? " (relocatable)" : "");
#endif
- if (info->relocatable)
- return TRUE;
-
if (! mcore_elf_howto_table [R_MCORE_PCRELIMM8BY4]) /* Initialize howto table if needed */
mcore_elf_howto_init ();
bfd_vma offset = rel->r_offset;
bfd_vma addend = rel->r_addend;
bfd_reloc_status_type r = bfd_reloc_other;
- asection * sec = (asection *) 0;
+ asection * sec = NULL;
reloc_howto_type * howto;
bfd_vma relocation;
- Elf_Internal_Sym * sym = (Elf_Internal_Sym *) 0;
+ Elf_Internal_Sym * sym = NULL;
unsigned long r_symndx;
- struct elf_link_hash_entry * h = (struct elf_link_hash_entry *) 0;
+ struct elf_link_hash_entry * h = NULL;
unsigned short oldinst = 0;
- /* Unknown relocation handling */
+ /* Unknown relocation handling. */
if ((unsigned) r_type >= (unsigned) R_MCORE_max
|| ! mcore_elf_howto_table [(int)r_type])
{
unresolved_reloc, warned);
}
+ 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 (info->relocatable)
+ continue;
+
switch (r_type)
{
default:
relocation. */
static asection *
-mcore_elf_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;
+mcore_elf_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_MCORE_GNU_VTINHERIT:
- case R_MCORE_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
- return bfd_section_from_elf_index (sec->owner, sym->st_shndx);
-
- return NULL;
+ switch (ELF32_R_TYPE (rel->r_info))
+ {
+ case R_MCORE_GNU_VTINHERIT:
+ case R_MCORE_GNU_VTENTRY:
+ 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
-mcore_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;
+mcore_elf_gc_sweep_hook (bfd * abfd ATTRIBUTE_UNUSED,
+ struct bfd_link_info * info ATTRIBUTE_UNUSED,
+ asection * sec ATTRIBUTE_UNUSED,
+ const Elf_Internal_Rela * relocs ATTRIBUTE_UNUSED)
{
return TRUE;
}
virtual table relocs for gc. */
static bfd_boolean
-mcore_elf_check_relocs (abfd, info, sec, relocs)
- bfd * abfd;
- struct bfd_link_info * info;
- asection * sec;
- const Elf_Internal_Rela * relocs;
+mcore_elf_check_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;
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))
{
return TRUE;
}
-static struct bfd_elf_special_section const mcore_elf_special_sections[]=
+static const struct bfd_elf_special_section mcore_elf_special_sections[]=
{
- { ".ctors", 6, -2, SHT_PROGBITS, SHF_ALLOC + SHF_WRITE },
- { ".dtors", 6, -2, SHT_PROGBITS, SHF_ALLOC + SHF_WRITE },
- { NULL, 0, 0, 0, 0 }
+ { STRING_COMMA_LEN (".ctors"), -2, SHT_PROGBITS, SHF_ALLOC + SHF_WRITE },
+ { STRING_COMMA_LEN (".dtors"), -2, SHT_PROGBITS, SHF_ALLOC + SHF_WRITE },
+ { NULL, 0, 0, 0, 0 }
};
#define TARGET_BIG_SYM bfd_elf32_mcore_big_vec
#define bfd_elf32_bfd_merge_private_bfd_data mcore_elf_merge_private_bfd_data
#define bfd_elf32_bfd_set_private_flags mcore_elf_set_private_flags
#define bfd_elf32_bfd_reloc_type_lookup mcore_elf_reloc_type_lookup
+#define bfd_elf32_bfd_reloc_name_lookup mcore_elf_reloc_name_lookup
#define elf_backend_relocate_section mcore_elf_relocate_section
#define elf_backend_gc_mark_hook mcore_elf_gc_mark_hook
#define elf_backend_gc_sweep_hook mcore_elf_gc_sweep_hook