aboutsummaryrefslogtreecommitdiff
path: root/bfd/elf32-sh.c
diff options
context:
space:
mode:
Diffstat (limited to 'bfd/elf32-sh.c')
-rw-r--r--bfd/elf32-sh.c120
1 files changed, 118 insertions, 2 deletions
diff --git a/bfd/elf32-sh.c b/bfd/elf32-sh.c
index ea5bd9f..ea0426e 100644
--- a/bfd/elf32-sh.c
+++ b/bfd/elf32-sh.c
@@ -1,5 +1,5 @@
/* Hitachi SH specific support for 32-bit ELF
- Copyright 1996, 1997, 1998, 1999 Free Software Foundation, Inc.
+ Copyright 1996, 97, 98, 1999, 2000 Free Software Foundation, Inc.
Contributed by Ian Lance Taylor, Cygnus Support.
This file is part of BFD, the Binary File Descriptor library.
@@ -33,6 +33,14 @@ static reloc_howto_type *sh_elf_reloc_type_lookup
PARAMS ((bfd *, bfd_reloc_code_real_type));
static void sh_elf_info_to_howto
PARAMS ((bfd *, arelent *, Elf_Internal_Rela *));
+static boolean sh_elf_set_private_flags
+ PARAMS ((bfd *, flagword));
+static boolean sh_elf_copy_private_data
+ PARAMS ((bfd *, bfd *));
+static boolean sh_elf_merge_private_data
+ PARAMS ((bfd *, bfd *));
+boolean sh_elf_set_mach_from_flags
+ PARAMS ((bfd *));
static boolean sh_elf_relax_section
PARAMS ((bfd *, asection *, struct bfd_link_info *, boolean *));
static boolean sh_elf_relax_delete_bytes
@@ -2087,6 +2095,109 @@ sh_elf_check_relocs (abfd, info, sec, relocs)
return true;
}
+boolean
+sh_elf_set_mach_from_flags (abfd)
+ bfd * abfd;
+{
+ flagword flags = elf_elfheader (abfd)->e_flags;
+
+ switch (elf_elfheader (abfd)->e_flags & EF_SH_MACH_MASK)
+ {
+ case EF_SH1:
+ bfd_default_set_arch_mach (abfd, bfd_arch_sh, bfd_mach_sh);
+ break;
+ case EF_SH2:
+ bfd_default_set_arch_mach (abfd, bfd_arch_sh, bfd_mach_sh2);
+ break;
+ case EF_SH_DSP:
+ bfd_default_set_arch_mach (abfd, bfd_arch_sh, bfd_mach_sh_dsp);
+ break;
+ case EF_SH3:
+ bfd_default_set_arch_mach (abfd, bfd_arch_sh, bfd_mach_sh3);
+ break;
+ case EF_SH3_DSP:
+ bfd_default_set_arch_mach (abfd, bfd_arch_sh, bfd_mach_sh3_dsp);
+ break;
+ case EF_SH3E:
+ bfd_default_set_arch_mach (abfd, bfd_arch_sh, bfd_mach_sh3e);
+ break;
+ case EF_SH_UNKNOWN:
+ case EF_SH4:
+ bfd_default_set_arch_mach (abfd, bfd_arch_sh, bfd_mach_sh4);
+ break;
+ default:
+ return false;
+ }
+ return true;
+}
+
+/* Function to keep SH specific file flags. */
+static boolean
+sh_elf_set_private_flags (abfd, 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 sh_elf_set_mach_from_flags (abfd);
+}
+
+/* Copy backend specific data from one object module to another */
+static boolean
+sh_elf_copy_private_data (ibfd, obfd)
+ bfd * ibfd;
+ bfd * obfd;
+{
+ if ( bfd_get_flavour (ibfd) != bfd_target_elf_flavour
+ || bfd_get_flavour (obfd) != bfd_target_elf_flavour)
+ return true;
+
+ return sh_elf_set_private_flags (obfd, elf_elfheader (ibfd)->e_flags);
+}
+
+/* This routine checks for linking big and little endian objects
+ together, and for linking sh-dsp with sh3e / sh4 objects. */
+
+static boolean
+sh_elf_merge_private_data (ibfd, obfd)
+ bfd *ibfd;
+ bfd *obfd;
+{
+ flagword old_flags, new_flags;
+
+ if (_bfd_generic_verify_endian_match (ibfd, obfd) == false)
+ return false;
+
+ if ( bfd_get_flavour (ibfd) != bfd_target_elf_flavour
+ || bfd_get_flavour (obfd) != bfd_target_elf_flavour)
+ return true;
+
+ if (! elf_flags_init (obfd))
+ {
+ elf_flags_init (obfd) = true;
+ elf_elfheader (obfd)->e_flags = 0;
+ }
+ old_flags = elf_elfheader (obfd)->e_flags;
+ new_flags = elf_elfheader (ibfd)->e_flags;
+ if ((EF_SH_HAS_DSP (old_flags) && EF_SH_HAS_FP (new_flags))
+ || (EF_SH_HAS_DSP (new_flags) && EF_SH_HAS_FP (old_flags)))
+ {
+ (*_bfd_error_handler)
+ ("%s: uses %s instructions while previous modules use %s instructions",
+ bfd_get_filename (ibfd),
+ EF_SH_HAS_DSP (new_flags) ? "dsp" : "floating point",
+ EF_SH_HAS_DSP (new_flags) ? "floating point" : "dsp");
+ bfd_set_error (bfd_error_bad_value);
+ return false;
+ }
+ elf_elfheader (obfd)->e_flags = EF_SH_MERGE_MACH (old_flags, new_flags);
+
+ return sh_elf_set_mach_from_flags (obfd);
+}
+
#define TARGET_BIG_SYM bfd_elf32_sh_vec
#define TARGET_BIG_NAME "elf32-sh"
#define TARGET_LITTLE_SYM bfd_elf32_shl_vec
@@ -2103,8 +2214,13 @@ sh_elf_check_relocs (abfd, info, sec, relocs)
#define elf_backend_relocate_section sh_elf_relocate_section
#define bfd_elf32_bfd_get_relocated_section_contents \
sh_elf_get_relocated_section_contents
+#define elf_backend_object_p sh_elf_set_mach_from_flags
+#define bfd_elf32_bfd_set_private_bfd_flags \
+ sh_elf_set_private_flags
+#define bfd_elf32_bfd_copy_private_bfd_data \
+ sh_elf_copy_private_data
#define bfd_elf32_bfd_merge_private_bfd_data \
- _bfd_generic_verify_endian_match
+ sh_elf_merge_private_data
#define elf_backend_gc_mark_hook sh_elf_gc_mark_hook
#define elf_backend_gc_sweep_hook sh_elf_gc_sweep_hook