This is the mail archive of the binutils@sources.redhat.com mailing list for the binutils project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

Re: sh64-elf (SH5) port: directory bfd


On Feb  3, 2002, Alexandre Oliva <aoliva@redhat.com> wrote:

> I'm extremely pleased to contribute the SH5 port of binutils,
> developed mostly by Hans-Peter Nilsson, with some contributions by DJ
> Delorie and Ben Elliston, later extended to support PIC by myself.

Index: bfd/ChangeLog
from  Alexandre Oliva  <aoliva@redhat.com>

	Contribute sh64-elf.
	2002-01-23  Alexandre Oliva  <aoliva@redhat.com>
	* reloc.c (R_SH_GOTPLT32, R_SH_GOT_LOW16, R_SH_GOT_MEDLOW16,
	R_SH_GOT_MEDHI16, R_SH_GOT_HI16, R_SH_GOTPLT_LOW16,
	R_SH_GOTPLT_MEDLOW16, R_SH_GOTPLT_MEDHI16, R_SH_GOTPLT_HI16,
	R_SH_PLT_LOW16, R_SH_PLT_MEDLOW16, R_SH_PLT_MEDHI16,
	R_SH_PLT_HI16, R_SH_GOTOFF_LOW16, R_SH_GOTOFF_MEDLOW16,
	R_SH_GOTOFF_MEDHI16, R_SH_GOTOFF_HI16, R_SH_GOTPC_LOW16,
	R_SH_GOTPC_MEDLOW16, R_SH_GOTPC_MEDHI16, R_SH_GOTPC_HI16,
	R_SH_GOT10BY4, R_SH_GOTPLT10BY4, R_SH_GOT10BY8, R_SH_GOTPLT10BY8,
	R_SH_COPY64, R_SH_GLOB_DAT64, R_SH_JMP_SLOT64, R_SH_RELATIVE64):
	New relocs.
	* libbfd.h, bfd-in2.h: Rebuilt.
	* elf32-sh.c (sh_elf_howto_table): Define new relocs.
	(sh_reloc_map): Map them.
	(PLT_ENTRY_SIZE, elf_sh_plt0_entry_be, elf_sh_plt0_entry_le,
	elf_sh_plt_entry_be, elf_sh_plt_entry_le, elf_sh_pic_plt_entry_be,
	elf_sh_pic_plt_entry_le, elf_sh_plt0_entry, elf_sh_plt_entry,
	elf_sh_pic_plt_entry, elf_sh_sizeof_plt, elf_sh_plt_plt0_offset,
	elf_sh_plt0_gotplt_offset, elf_sh_plt_temp_offset,
	elf_sh_plt_symbol_offset, elf_sh_plt_reloc_offset,
	movi_shori_putval) [INCLUDE_SHMEDIA]: New.
	(elf_sh_link_hash_entry) [INCLUDE_SHMEDIA]: Add
	datalabel_got_offset.
	(sh_elf_link_hash_newfunc): Initialize it.
	(sh_elf_relocate_section): Augment the scope of
	seen_stt_datalabel.  Introduce GOTPLT support.  Extend GOTPC, PLT,
	GOT and GOTOFF handling to new SHmedia relocation types.  Support
	GOT_BIAS.
	(sh_elf_check_relocs): Likewise.
	(sh_elf_finish_dynamic_symbol) [TARGET_SHMEDIA]: Set up values in
	PLT entries using movi_shori_putval.  Support GOT_BIAS.
	(sh_elf_finish_dynamic_sections): Likewise.
	* elf32-sh64.c (shmedia_prepare_reloc): Do not add addend to
	relocation, it's now done by the caller.
	(GOT_BIAS): New.
	* elf64-sh64.c (GOT_BIAS, PLT_ENTRY_SIZE, elf_sh64_sizeof_plt,
	elf_sh64_plt_plt0_offset, elf_sh64_plt0_gotplt_offset,
	elf_sh64_plt_temp_offset, elf_sh64_plt_symbol_offset,
	elf_sh64_plt_reloc_offset, ELF_DYNAMIC_INTERPRETER,
	elf_sh64_pcrel_relocs_copied, elf_sh64_link_hash_entry,
	elf_sh64_link_hash_table, sh64_elf64_link_hash_traverse,
	sh64_elf64_hash_table): New.
	(sh_elf64_howto_table): Introduce new relocs.
	(sh_elf64_info_to_howto): Accept new PIC relocs.
	(sh_elf64_relocate_section): Augment the scope of
	seen_stt_datalabel.  Support new PIC relocs.
	(sh_elf64_check_relocs): Support new PIC relocs.
	(elf_sh64_plt0_entry_be, elf_sh64_plt0_entry_le,
	elf_sh64_plt_entry_be, elf_sh64_plt_entry_le,
	elf_sh64_pic_plt_entry_be, elf_sh64_pic_plt_entry_le,
	elf_sh64_plt0_entry, elf_sh64_plt_entry, elf_sh64_pic_plt_entry,
	sh64_elf64_link_hash_newfunc, sh64_elf64_link_hash_table_create,
	movi_shori_putval, movi_3shori_putval,
	sh64_elf64_create_dynamic_sections,
	sh64_elf64_adjust_dynamic_symbol, sh64_elf64_discard_copies,
	sh64_elf64_size_dynamic_sections,
	sh64_elf64_finish_dynamic_symbol,
	sh64_elf64_finish_dynamic_sections): New.
	(elf_backend_create_dynamic-sections,
	bfd_elf64_bfd_link_hash_table_create,
	elf_backend_adjust_dynamic_symbol,
	elf_backend_size_dynamic_sections,
	elf_backend_finish_dynamic_symbol,
	elf_backend_finish_dynamic_sections, elf_backend_want_got_plt,
	elf_backend_plt_readonly, elf_backend_want_plt_sym,
	elf_backend_got_header_size, elf_backend_plt_header_size):
	Define.
	2001-05-16  Alexandre Oliva  <aoliva@redhat.com>
	* elf32-sh.c: Renumbered and renamed some SH5 relocations to
	match official numbers and names; moved unmaching ones to the
	range 0xf2-0xff.
	* elf32-sh64.c, elf64-sh64.c: Likewise.
	2001-03-12  DJ Delorie  <dj@redhat.com>
	* elf32-sh.c (sh_elf_relax_section): Don't relax SHmedia
	sections.
	2001-03-12  DJ Delorie  <dj@redhat.com>
	* elf32-sh64.c (shmedia_prepare_reloc): Validate relocs that must
	be aligned.
	* elf64-sh64.c (sh_elf64_relocate_section): Ditto.
	2001-01-14  Hans-Peter Nilsson  <hpn@cygnus.com>
	* elf32-sh64.c (bfd_elf32_bfd_copy_private_section_data): Define.
	(sh64_elf_fake_sections): Set type to SHT_SH5_CR_SORTED for a
	.cranges section with SEC_SORT_ENTRIES set.
	(sh64_backend_section_from_shdr): Set SEC_SORT_ENTRIES on an
	incoming sorted .cranges section.
	(sh64_bfd_elf_copy_private_section_data): New.
	(sh64_elf_final_write_processing): Only sort .cranges and modify
	start address if called by linker.
	2001-01-08  Ben Elliston  <bje@redhat.com>
	* elf32-sh64.c (sh64_elf_final_write_processing): Activate
	Hans-Peter Nilsson's set bit 0 patch from 	2001-01-06.
	* elf64-sh64.c (sh64_elf64_final_write_processing): Ditto.
	2001-01-06  Hans-Peter Nilsson  <hpn@cygnus.com>
	* elf64-sh64.c (sh_elf64_howto_table): No open brace at start of
	line.  Add comments before all entries.
	<R_SH_PT_16, R_SH_SHMEDIA_CODE>: Correct and clarify describing
	comment.
	(sh_elf64_reloc): Correct head comment.
	(sh_elf64_relocate_section): Correct spacing.
	<relocating for a local symbol>: Do not honour STO_SH5_ISA32;
	instead call reloc_dangerous callback.
	<case R_SH_SHMEDIA_CODE>: New case.
	(sh_elf64_gc_mark_hook): Correct spacing.
	(sh_elf64_check_relocs): Ditto.
	* elf32-sh64.c (shmedia_prepare_reloc) <case R_SH_SHMEDIA_CODE>:
	New case.
	* elf32-sh.c: Correct #endif comments for #ifndef-wrapped
	functions.
 	(sh_elf_howto_table) <R_SH_PT_16, R_SH_SHMEDIA_CODE>: Correct,
	clarify describing comment.  Add comments before all entries.
	(sh_elf_relocate_section) <relocating for a local symbol>: Do not
	honour STO_SH5_ISA32; instead call reloc_dangerous callback.
	2001-01-06  Hans-Peter Nilsson  <hpn@cygnus.com>
	Sort .cranges section in final link.  Prepare to set bit 0 on
	entry address.
	* elf32-sh64.c (struct sh64_find_section_vma_data): New.
	(sh64_elf_link_output_symbol_hook): Fix typo in prototype.
	(sh64_elf_set_mach_from_flags): Set SEC_DEBUGGING on incoming
	.cranges section.
	(sh64_backend_section_from_shdr): New, to recognize
	SHT_SH5_CR_SORTED on incoming .cranges section.
	(elf_backend_section_from_shdr): Define.
	(sh64_elf_final_write_processing): Sort outgoing .cranges
	section.  (New, temporarily disabled:) Set bit 0 on entry address
	according to ISA type.
	(sh64_find_section_for_address): New.
	(crange_qsort_cmpb, crange_qsort_cmpl, crange_bsearch_cmpb,
	crange_bsearch_cmpl): Move here from opcodes/sh64-dis.c.
	(sh64_address_in_cranges): Move here from opcodes/sh64-dis.c.  Use
	bfd_malloc, not xmalloc.
	(sh64_get_contents_type): Move here from opcodes/sh64-dis.c.  Make
	global.
	* elf32-sh64.c (sh64_elf64_final_write_processing): New, (but
	temporarily disabled) setting bit 0 on entry address.
	(elf_backend_final_write_processing): Define.
	2001-01-05  Hans-Peter Nilsson  <hpn@cygnus.com>
	* elf32-sh.c (sh_elf_howto_table) <R_SH_PT_16>: Adjust fields to
	be a proper relocation for PTA and PTB rather than a marker.
	<R_SH_IMMU5, R_SH_IMMS6, R_SH_IMMU6, R_SH_IMMS10, R_SH_IMMS10BY2,
	R_SH_IMMS10BY4, R_SH_IMMS10BY8, R_SH_IMMS16, R_SH_IMMU16,
	R_SH_IMM_LOW16, R_SH_IMM_LOW16_PCREL, R_SH_IMM_MEDLOW16,
	R_SH_IMM_MEDLOW16_PCREL, R_SH_IMM_MEDHI16, R_SH_IMM_MEDHI16_PCREL,
	R_SH_IMM_HI16, R_SH_IMM_HI16_PCREL, R_SH_64, R_SH_64_PCREL>:
 	Zero src_mask.
	* elf64-sh64.c: Ditto.
	(sh_elf64_relocate_section) <case R_SH_PT_16>: New case.
	* elf32-sh64.c: Include opcodes/sh64-opc.h
	(shmedia_prepare_reloc): Take a bfd_link_info pointer as first
	argument.  Drop const qualifiers from "bfd *" and "bfd_byte *"
	parameters.  No unused parameters.  Caller changed.
  	<case R_SH_PT_16>: New case.
	* Makefile.am (elf32-sh64.lo): Add dependency on sh64-opc.h.
	* Makefile.in: Regenerate.
	2000-12-30  Hans-Peter Nilsson  <hpn@cygnus.com>
	* elf64-sh64.c (sh64_elf64_fake_sections): Set SHF_SH5_ISA32 for
	all code sections.
	(sh_elf64_set_mach_from_flags): Change from EF_SH64 to EF_SH5.
	(sh64_elf_merge_private_data): Ditto.
	* elf32-sh64.c (sh64_elf_fake_sections): Use sh64_elf_section_data
	to access stored section flags.
	(sh64_elf_final_write_processing): Return immediately unless
	called by linker.  Use sh64_elf_section_data (cranges) to get size
	of linker-generated cranges entries.
	(sh64_elf_copy_private_data): Add missing "return true".
	(sh64_elf_set_mach_from_flags): Change from EF_SH64 to EF_SH5.
	(sh_elf64_merge_private_data): Ditto.
	2000-12-19  Hans-Peter Nilsson  <hpn@cygnus.com>
	* elf64-sh64.c (sh64_elf64_fake_sections): New, copy of
	elf64-sh64.c:sh64_elf_fake_sections.
	(elf_backend_fake_sections): Define as sh64_elf64_fake_sections.
	2000-12-18  Hans-Peter Nilsson  <hpn@cygnus.com>
	* elf32-sh64.c (sh64_elf_copy_private_data_internal): Delete.
	(sh64_elf_final_write_processing): New.
	(elf_backend_final_write_processing): Define.
	(sh64_elf_fake_sections): Get header flags from tdata field.
	(sh64_elf_copy_private_data): Do not call
	sh64_elf_copy_private_data_internal, just copy e_flags field.
	(sh64_elf_merge_private_data): Do not call
	sh64_elf_copy_private_data_internal.
	2000-12-12  Hans-Peter Nilsson  <hpn@cygnus.com>
	Remove EF_SH64_ABI64, let ELF size make difference.
  	Remove SH64-specific BFD section flag.
	* elf32-sh64.c (sh64_elf_fake_sections): Recognize section as
	containing SHmedia through elf_section_data (asect)->tdata
	non-zero, not using a BFD section flag.
	(sh64_elf_set_mach_from_flags): Don't recognize EF_SH64_ABI64.
	(sh64_elf_merge_private_data): Similar.
	(elf_backend_section_flags): Don't define.
	(sh64_elf_backend_section_flags): Delete.
	* elf64-sh64.c (sh_elf64_set_mach_from_flags): Recognize EF_SH64,
	not EF_SH64_ABI64.
	(sh_elf64_merge_private_data): Similar.
	* section.c (Section flags definitions): Don't define
	SEC_SH_ISA_SHMEDIA.
	(bfd-in2.h): Regenerate.
	2000-12-09  Hans-Peter Nilsson  <hpn@cygnus.com>
	Make DataLabel references work with partial linking.
	* elf32-sh64.c: Fix formatting.
	(sh64_elf_link_output_symbol_hook): New.
	(elf_backend_link_output_symbol_hook): Define to
	sh64_elf_link_output_symbol_hook.
	(sh64_elf_add_symbol_hook): Make DataLabel symbol just global
	undefined if partial linking.  Adjust sanity check.
	* elf64-sh64.c (sh64_elf64_link_output_symbol_hook): New.
	(elf_backend_link_output_symbol_hook): Define to
	sh64_elf64_link_output_symbol_hook.
	(sh64_elf64_add_symbol_hook): Make DataLabel symbol just global
	undefined if partial linking.  Adjust sanity check.
	2000-12-07  Hans-Peter Nilsson  <hpn@cygnus.com>
	Implement semantics for inter-file DataLabel references.
	* elf64-sh64.c (DATALABEL_SUFFIX): Define.
	(sh64_elf64_add_symbol_hook): New.
	(sh_elf64_relocate_section): If passing an indirect symbol with
	st_type STT_DATALABEL on the way to a symbol with st_other
	STO_SH5_ISA32, do not bitor 1 to the relocation.
	(elf_backend_add_symbol_hook): Define to
	sh64_elf64_add_symbol_hook.
	* elf64-sh32.c: Tweak comments.
 	(DATALABEL_SUFFIX): Define.
	(sh64_elf_add_symbol_hook): New.
	(elf_backend_add_symbol_hook): Define to sh64_elf_add_symbol_hook.
	* elf32-sh.c (sh_elf_relocate_section): If passing an indirect
	symbol with st_type STT_DATALABEL on the way to a symbol with
	st_other STO_SH5_ISA32, do not bitor 1 to the relocation.
	2000-12-05  Hans-Peter Nilsson  <hpn@cygnus.com>
	Pass through STT_DATALABEL.
	* elf32-sh64.c (sh64_elf_get_symbol_type): New.
	(elf_backend_get_symbol_type): Define.
	* elf64-sh64.c (sh64_elf64_get_symbol_type): New.
	(elf_backend_get_symbol_type): Define.
	2000-11-30  Hans-Peter Nilsson  <hpn@cygnus.com>
	* elf32-sh64.c: Tweak comments.
	(sh64_elf_copy_private_data_internal): Add prototype.
	(bfd_elf32_bfd_set_private_flags): Define.
	(sh64_elf_copy_private_data_internal): Compare machine name, not
	textual BFD target name, to check whether to copy section flag
	SHF_SH5_ISA32.
	(sh64_elf_merge_private_data): Validize bfd_get_arch_size.
	Tweak section-contents-type-mismatch message.
	(shmedia_prepare_reloc): Add ATTRIBUTE_UNUSED markers.
	Validize reloc-types.
	* elf64-sh64.c: New file.
	* targets.c (bfd_elf64_sh64_vec, bfd_elf64_sh64l_vec): Declare.
	* Makefile.am (BFD64_BACKENDS): Add elf64-sh64.lo.
	(BFD64_BACKENDS_CFILES): Add elf64-sh64.c.
	Regenerate dependencies.
	* Makefile.in: Regenerate.
	* config.bfd (sh64-*-elf*): Add bfd_elf64_sh64_vec and
	bfd_elf64_sh64l_vec.
	* configure.in: Handle bfd_elf64_sh64_vec and
	bfd_elf64_sh64l_vec.
	* configure: Regenerate.
	* po/POTFILES.in: Regenerate.
	* po/bfd.pot: Regenerate.
	2000-11-29  Hans-Peter Nilsson  <hpn@cygnus.com>
	* elf32-sh64.c (sh64_elf_set_mach_from_flags): Do not recognize
	anything else but EF_SH64 and EF_SH64_ABI64.
	(sh64_elf_merge_private_data): Emit error for anything else but
	EF_SH64 and EF_SH64_ABI64.
	* config.bfd: Remove bfd_elf32_shblin_vec and bfd_elf32_shlin_vec
	from targ_selvecs.
	* configure.in: Add cofflink.lo to bfd_elf32_sh64_vec and
	bfd_elf32_sh64l_vec as a temporary measure.
	* configure: Regenerate.
	2000-11-27  Hans-Peter Nilsson  <hpn@cygnus.com>
	* cpu-sh.c (arch_info_struct): Include sh5 item
	unconditionalized.
	* config.bfd (sh64-*-elf*): Do not set targ_cflags.
	Add targ_selvecs bfd_elf32_sh_vec, bfd_elf32_shl_vec,
	bfd_elf32_shblin_vec and bfd_elf32_shlin_vec.
	* elf32-sh64.c: Tweak comments.
 	(sh64_elf_set_mach_from_flags): Recognize all machine flags that
	are proper subsets of SH64 as bfd_mach_sh5.  Add EF_SH64_ABI64.
	(sh64_elf_copy_private_data_internal): Wrap long line.
	(sh64_elf_merge_private_data): Rewrite to allow objects from
	SH64 subsets to be linked together.
	(INCLUDE_SHMEDIA): Define.
	* elf32-sh.c (sh_elf_relocate_section) <local symbol>:
	Parenthesize plus-expression inside or-expression.
	<global symbol>: Ditto.
	(sh_elf_set_mach_from_flags): Remove code refusing
	deleted EF_SH64_32BIT_ABI flag.
	2000-11-26  Hans-Peter Nilsson  <hpn@cygnus.com>
	* elf32-sh.c (sh_elf_howto_table) <R_SH_IMM_LOW16_PCREL,
	R_SH_IMM_MEDLOW16_PCREL, R_SH_IMM_MEDHI16_PCREL,
	R_SH_IMM_HI16_PCREL, R_SH_64_PCREL>: Set pcrel_offset to true.
	(sh_elf_relocate_section) <local symbol>: Or 1 in
	calculation of relocation if sym->st_other & STO_SH5_ISA32.
	<global symbol>: Ditto if h->other & STO_SH5_ISA32.
	* elf32-sh64.c (shmedia_prepare_reloc): Add rel->r_addend to
	relocation.
	2000-11-24  Hans-Peter Nilsson  <hpn@cygnus.com>
	* Makefile.am (BFD32_BACKENDS): Add elf32-sh64.lo.
	(BFD32_BACKENDS_CFILES): Add elf32-sh64.c.
	Regenerate dependencies.
	* Makefile.in: Regenerate.
	* archures.c: Add bfd_mach_sh5.
	* config.bfd: Map targ_cpu sh* to bfd_sh_arch.
	Handle sh64-*-elf*.  Set targ_cflags to -DINCLUDE_SHMEDIA.
	* configure.in: Handle bfd_elf32_sh64_vec and bfd_elf32_sh64l_vec.
	* configure: Regenerate.
	* reloc.c (BFD_RELOC_SH_SHMEDIA_CODE, BFD_RELOC_SH_IMMU5,
	BFD_RELOC_SH_IMMS6, BFD_RELOC_SH_IMMS6BY32, BFD_RELOC_SH_IMMU6,
	BFD_RELOC_SH_IMMS10, BFD_RELOC_SH_IMMS10BY2,
	BFD_RELOC_SH_IMMS10BY4, BFD_RELOC_SH_IMMS10BY8,
	BFD_RELOC_SH_IMMS16, BFD_RELOC_SH_IMMU16, BFD_RELOC_SH_IMM_LOW16,
	BFD_RELOC_SH_IMM_LOW16_PCREL, BFD_RELOC_SH_IMM_MEDLOW16,
	BFD_RELOC_SH_IMM_MEDLOW16_PCREL, BFD_RELOC_SH_IMM_MEDHI16,
	BFD_RELOC_SH_IMM_MEDHI16_PCREL, BFD_RELOC_SH_IMM_HI16,
	BFD_RELOC_SH_IMM_HI16_PCREL, BFD_RELOC_SH_PT_16): New relocations.
	* cpu-sh.c [INCLUDE_SHMEDIA] (arch_info_struct): Define and link
	in item for SH5.
	* elf32-sh.c [INCLUDE_SHMEDIA] (sh_elf_howto_table): Add howto items
	for SHmedia relocs.
	[INCLUDE_SHMEDIA] (sh_rel): Add mappings for SHmedia relocs.
	[INCLUDE_SHMEDIA] (sh_elf_relocate_section) [default]: Call
	shmedia_prepare_reloc, goto final_link_relocate if it returns
	non-zero, else fail as before.
	(sh_elf_set_mach_from_flags): Provide function only if not defined
	as macro.  Do not recognize objects with EF_SH64_32BIT_ABI set.
	(sh_elf_set_private_flags): Provide function only if not defined
	as a macro.
	(sh_elf_copy_private_data): Similar.
	(sh_elf_merge_private_data): Similar.
	* section.c (SEC_SH_ISA_SHMEDIA): New.
	* targets.c (bfd_elf32_sh64_vec, bfd_elf32_sh64l_vec): Declare.
	* elf32-sh64.c: New file.
	* libbfd.h: Regenerate.
	* bfd-in2.h: Regenerate.
	* po/POTFILES.in: Regenerate.
	* po/bfd.pot: Regenerate.
	* bfd-in2.h: Regenerate.
	* libbfd.h: Regenerate.

Index: bfd/Makefile.am
===================================================================
RCS file: /home/aoliva/cygnus/uberbaum/bfd/Makefile.am,v
retrieving revision 1.75
diff -u -p -r1.75 Makefile.am
--- bfd/Makefile.am 1 Feb 2002 03:26:28 -0000 1.75
+++ bfd/Makefile.am 2 Feb 2002 04:00:28 -0000
@@ -221,6 +221,7 @@ BFD32_BACKENDS = \
 	elf32-s390.lo \
 	elf32-sh.lo \
 	elf32-sh-lin.lo \
+	elf32-sh64.lo \
 	elf32-sh-nbsd.lo \
 	elf32-sparc.lo \
 	elf32-v850.lo \
@@ -364,6 +365,7 @@ BFD32_BACKENDS_CFILES = \
 	elf32-or32.c \
 	elf32-pj.c \
 	elf32-ppc.c \
+	elf32-sh64.c \
 	elf32-s390.c \
 	elf32-sh.c \
 	elf32-sh-lin.c \
@@ -451,6 +453,7 @@ BFD64_BACKENDS = \
 	elf64-gen.lo \
 	elf64-mips.lo \
 	elf64-mmix.lo \
+	elf64-sh64.lo \
 	elf64-ppc.lo \
 	elf64-s390.lo \
 	elf64-sparc.lo \
@@ -474,6 +477,7 @@ BFD64_BACKENDS_CFILES = \
 	elf64-mmix.c \
 	elf64-ppc.c \
 	elf64-s390.c \
+	elf64-sh64.c \
 	elf64-sparc.c \
 	elf64.c \
 	mmo.c \
@@ -1135,6 +1139,14 @@ elf32-ppc.lo: elf32-ppc.c $(INCDIR)/file
   elf-bfd.h $(INCDIR)/elf/common.h $(INCDIR)/elf/internal.h \
   $(INCDIR)/elf/external.h $(INCDIR)/elf/ppc.h $(INCDIR)/elf/reloc-macros.h \
   elf32-target.h
+elf32-sh64.lo: elf32-sh64.c $(INCDIR)/filenames.h elf-bfd.h \
+  $(INCDIR)/elf/common.h $(INCDIR)/elf/internal.h $(INCDIR)/elf/external.h \
+  $(INCDIR)/bfdlink.h elf32-sh.c $(INCDIR)/elf/sh.h $(INCDIR)/elf/reloc-macros.h \
+  elf32-target.h $(srcdir)/../opcodes/sh64-opc.h
+elf64-sh64.lo: elf64-sh64.c $(INCDIR)/filenames.h $(INCDIR)/bfdlink.h \
+  elf-bfd.h $(INCDIR)/elf/common.h $(INCDIR)/elf/internal.h \
+  $(INCDIR)/elf/external.h $(INCDIR)/elf/sh.h $(INCDIR)/elf/reloc-macros.h \
+  elf64-target.h
 elf32-s390.lo: elf32-s390.c $(INCDIR)/filenames.h $(INCDIR)/bfdlink.h \
   elf-bfd.h $(INCDIR)/elf/common.h $(INCDIR)/elf/internal.h \
   $(INCDIR)/elf/external.h $(INCDIR)/elf/s390.h $(INCDIR)/elf/reloc-macros.h \
Index: bfd/archures.c
===================================================================
RCS file: /home/aoliva/cygnus/uberbaum/bfd/archures.c,v
retrieving revision 1.43
diff -u -p -r1.43 archures.c
--- bfd/archures.c 31 Jan 2002 17:32:54 -0000 1.43
+++ bfd/archures.c 2 Feb 2002 04:00:28 -0000
@@ -206,6 +206,7 @@ DESCRIPTION
 .#define bfd_mach_sh3_dsp    0x3d
 .#define bfd_mach_sh3e       0x3e
 .#define bfd_mach_sh4        0x40
+.#define bfd_mach_sh5        0x50
 .  bfd_arch_alpha,     {* Dec Alpha *}
 .#define bfd_mach_alpha_ev4  0x10
 .#define bfd_mach_alpha_ev5  0x20
Index: bfd/config.bfd
===================================================================
RCS file: /home/aoliva/cygnus/uberbaum/bfd/config.bfd,v
retrieving revision 1.84
diff -u -p -r1.84 config.bfd
--- bfd/config.bfd 2 Feb 2002 18:36:00 -0000 1.84
+++ bfd/config.bfd 3 Feb 2002 00:57:23 -0000
@@ -57,6 +57,7 @@ v850*)	         targ_archs=bfd_v850_arch
 x86_64)          targ_archs=bfd_i386_arch ;;
 xscale*)         targ_archs=bfd_arm_arch ;;
 z8k*)	         targ_archs=bfd_z8k_arch ;;
+sh*)	         targ_archs=bfd_sh_arch ;;
 *)	         targ_archs=bfd_${targ_cpu}_arch ;;
 esac
 
@@ -844,6 +845,14 @@ case "${targ}" in
     targ_defvec=bfd_elf64_s390_vec
     ;;
 #endif
+
+#ifdef BFD64
+  sh64-*-elf*)
+    targ_defvec=bfd_elf32_sh64_vec
+    targ_selvecs="bfd_elf32_sh64l_vec bfd_elf64_sh64_vec bfd_elf64_sh64l_vec bfd_elf32_sh_vec bfd_elf32_shl_vec"
+    targ_underscore=yes
+    ;;
+#endif /* BFD64 */
 
   sh-*-linux*)
     targ_defvec=bfd_elf32_shblin_vec
Index: bfd/configure.in
===================================================================
RCS file: /home/aoliva/cygnus/uberbaum/bfd/configure.in,v
retrieving revision 1.84
diff -u -p -r1.84 configure.in
--- bfd/configure.in 2 Feb 2002 20:43:38 -0000 1.84
+++ bfd/configure.in 3 Feb 2002 00:57:24 -0000
@@ -515,6 +515,17 @@ do
     # This list is alphabetized to make it easy to compare
     # with the two vector lists in targets.c.  For the same reason,
     # use one entry per line, even though this leads to long lines.
+    # FIXME: We include cofflink.lo not because it's needed for
+    # bfd_elf32_sh64[l]_vec, but because we include bfd_elf32_sh[l]_vec
+    # which needs it but does not list it.  Should be fixed in right place.
+    bfd_elf32_sh64_vec)		tb="$tb elf32-sh64.lo elf32.lo $elf cofflink.lo"
+				target_size=64 ;;
+    bfd_elf32_sh64l_vec)	tb="$tb elf32-sh64.lo elf32.lo $elf cofflink.lo"
+				target_size=64 ;;
+    bfd_elf64_sh64_vec)		tb="$tb elf64-sh64.lo elf64.lo $elf"
+				target_size=64 ;;
+    bfd_elf64_sh64l_vec)	tb="$tb elf64-sh64.lo elf64.lo $elf"
+				target_size=64 ;;
     a29kcoff_big_vec)		tb="$tb coff-a29k.lo cofflink.lo" ;;
     a_out_adobe_vec)		tb="$tb aout-adobe.lo aout32.lo" ;;
     aout0_big_vec)		tb="$tb aout0.lo aout32.lo" ;;
Index: bfd/cpu-sh.c
===================================================================
RCS file: /home/aoliva/cygnus/uberbaum/bfd/cpu-sh.c,v
retrieving revision 1.6
diff -u -p -r1.6 cpu-sh.c
--- bfd/cpu-sh.c 18 Sep 2001 09:57:22 -0000 1.6
+++ bfd/cpu-sh.c 2 Feb 2002 04:00:28 -0000
@@ -58,6 +58,9 @@ compatible (a,b)
 #define SH3_DSP_NEXT &arch_info_struct[4]
 #define SH3E_NEXT    &arch_info_struct[5]
 #define SH4_NEXT     NULL
+#undef  SH4_NEXT
+#define SH4_NEXT     &arch_info_struct[6]
+#define SH64_NEXT    NULL
 
 static const bfd_arch_info_type arch_info_struct[] =
 {
@@ -144,6 +147,20 @@ static const bfd_arch_info_type arch_inf
     bfd_default_compatible,
     scan_mach,
     SH4_NEXT
+  },
+  {
+    64,				/* 64 bits in a word */
+    64,				/* 64 bits in an address */
+    8,				/* 8 bits in a byte */
+    bfd_arch_sh,
+    bfd_mach_sh5,
+    "sh",			/* arch_name  */
+    "sh5",			/* printable name */
+    1,
+    false,			/* not the default */
+    bfd_default_compatible,
+    scan_mach,
+    SH64_NEXT
   },
 };
 
Index: bfd/elf32-sh.c
===================================================================
RCS file: /home/aoliva/cygnus/uberbaum/bfd/elf32-sh.c,v
retrieving revision 1.41
diff -u -p -r1.41 elf32-sh.c
--- bfd/elf32-sh.c 17 Dec 2001 00:52:35 -0000 1.41
+++ bfd/elf32-sh.c 2 Feb 2002 04:00:28 -0000
@@ -1,5 +1,5 @@
 /* Hitachi SH specific support for 32-bit ELF
-   Copyright 1996, 1997, 1998, 1999, 2000, 2001
+   Copyright 1996, 1997, 1998, 1999, 2000, 2001, 2002
    Free Software Foundation, Inc.
    Contributed by Ian Lance Taylor, Cygnus Support.
 
@@ -492,6 +492,114 @@ static reloc_howto_type sh_elf_howto_tab
   EMPTY_HOWTO (42),
   EMPTY_HOWTO (43),
   EMPTY_HOWTO (44),
+
+#ifdef INCLUDE_SHMEDIA
+  /* Used in SHLLI.L and SHLRI.L.  */
+  HOWTO (R_SH_DIR5U,		/* type */
+	 0,			/* rightshift */
+	 2,			/* size (0 = byte, 1 = short, 2 = long) */
+	 5,			/* bitsize */
+	 false,			/* pc_relative */
+	 10,			/* bitpos */
+	 complain_overflow_unsigned, /* complain_on_overflow */
+	 bfd_elf_generic_reloc,	/* special_function */
+	 "R_SH_DIR5U",		/* name */
+	 false,			/* partial_inplace */
+	 0,			/* src_mask */
+	 0xfc00,		/* dst_mask */
+	 false),	       	/* pcrel_offset */
+
+  /* Used in SHARI, SHLLI et al.  */
+  HOWTO (R_SH_DIR6U,		/* type */
+	 0,			/* rightshift */
+	 2,			/* size (0 = byte, 1 = short, 2 = long) */
+	 6,			/* bitsize */
+	 false,			/* pc_relative */
+	 10,			/* bitpos */
+	 complain_overflow_unsigned, /* complain_on_overflow */
+	 bfd_elf_generic_reloc,	/* special_function */
+	 "R_SH_DIR6U",		/* name */
+	 false,			/* partial_inplace */
+	 0,			/* src_mask */
+	 0xfc00,		/* dst_mask */
+	 false),	       	/* pcrel_offset */
+
+  /* Used in BxxI, LDHI.L et al.  */
+  HOWTO (R_SH_DIR6S,		/* type */
+	 0,			/* rightshift */
+	 2,			/* size (0 = byte, 1 = short, 2 = long) */
+	 6,			/* bitsize */
+	 false,			/* pc_relative */
+	 10,			/* bitpos */
+	 complain_overflow_signed, /* complain_on_overflow */
+	 bfd_elf_generic_reloc,	/* special_function */
+	 "R_SH_DIR6S",		/* name */
+	 false,			/* partial_inplace */
+	 0,			/* src_mask */
+	 0xfc00,		/* dst_mask */
+	 false),	       	/* pcrel_offset */
+
+  /* Used in ADDI, ANDI et al.  */
+  HOWTO (R_SH_DIR10S,		/* type */
+	 0,			/* rightshift */
+	 2,			/* size (0 = byte, 1 = short, 2 = long) */
+	 10,			/* bitsize */
+	 false,			/* pc_relative */
+	 10,			/* bitpos */
+	 complain_overflow_signed, /* complain_on_overflow */
+	 bfd_elf_generic_reloc,	/* special_function */
+	 "R_SH_DIR10S",		/* name */
+	 false,			/* partial_inplace */
+	 0,			/* src_mask */
+	 0xffc00,		/* dst_mask */
+	 false),	       	/* pcrel_offset */
+
+  /* Used in LD.UW, ST.W et al.  */
+  HOWTO (R_SH_DIR10SW,	/* type */
+	 1,			/* rightshift */
+	 2,			/* size (0 = byte, 1 = short, 2 = long) */
+	 11,			/* bitsize */
+	 false,			/* pc_relative */
+	 10,			/* bitpos */
+	 complain_overflow_signed, /* complain_on_overflow */
+	 bfd_elf_generic_reloc,	/* special_function */
+	 "R_SH_DIR10SW",	/* name */
+	 false,			/* partial_inplace */
+	 0,			/* src_mask */
+	 0xffc00,		/* dst_mask */
+	 false),	       	/* pcrel_offset */
+
+  /* Used in LD.L, FLD.S et al.  */
+  HOWTO (R_SH_DIR10SL,	/* type */
+	 2,			/* rightshift */
+	 2,			/* size (0 = byte, 1 = short, 2 = long) */
+	 12,			/* bitsize */
+	 false,			/* pc_relative */
+	 10,			/* bitpos */
+	 complain_overflow_signed, /* complain_on_overflow */
+	 bfd_elf_generic_reloc,	/* special_function */
+	 "R_SH_DIR10SL",	/* name */
+	 false,			/* partial_inplace */
+	 0,			/* src_mask */
+	 0xffc00,		/* dst_mask */
+	 false),	       	/* pcrel_offset */
+
+  /* Used in FLD.D, FST.P et al.  */
+  HOWTO (R_SH_DIR10SQ,	/* type */
+	 3,			/* rightshift */
+	 2,			/* size (0 = byte, 1 = short, 2 = long) */
+	 13,			/* bitsize */
+	 false,			/* pc_relative */
+	 10,			/* bitpos */
+	 complain_overflow_signed, /* complain_on_overflow */
+	 bfd_elf_generic_reloc,	/* special_function */
+	 "R_SH_DIR10SQ",	/* name */
+	 false,			/* partial_inplace */
+	 0,			/* src_mask */
+	 0xffc00,		/* dst_mask */
+	 false),	       	/* pcrel_offset */
+
+#else
   EMPTY_HOWTO (45),
   EMPTY_HOWTO (46),
   EMPTY_HOWTO (47),
@@ -499,6 +607,8 @@ static reloc_howto_type sh_elf_howto_tab
   EMPTY_HOWTO (49),
   EMPTY_HOWTO (50),
   EMPTY_HOWTO (51),
+#endif
+
   EMPTY_HOWTO (52),
   EMPTY_HOWTO (53),
   EMPTY_HOWTO (54),
@@ -720,6 +830,704 @@ static reloc_howto_type sh_elf_howto_tab
 	 0xffffffff,		/* dst_mask */
 	 true),			/* pcrel_offset */
 
+  HOWTO (R_SH_GOTPLT32,		/* type */
+	 0,			/* rightshift */
+	 2,			/* size (0 = byte, 1 = short, 2 = long) */
+	 32,			/* bitsize */
+	 false,			/* pc_relative */
+	 0,			/* bitpos */
+	 complain_overflow_bitfield, /* complain_on_overflow */
+	 bfd_elf_generic_reloc, /* */
+	 "R_SH_GOTPLT32",	/* name */
+	 false,			/* partial_inplace */
+	 0xffffffff,		/* src_mask */
+	 0xffffffff,		/* dst_mask */
+	 false),		/* pcrel_offset */
+
+#ifdef INCLUDE_SHMEDIA
+  /* Used in MOVI and SHORI (x & 65536).  */
+  HOWTO (R_SH_GOT_LOW16,	/* type */
+	 0,			/* rightshift */
+	 2,			/* size (0 = byte, 1 = short, 2 = long) */
+	 64,			/* bitsize */
+	 false,			/* pc_relative */
+	 10,			/* bitpos */
+	 complain_overflow_dont, /* complain_on_overflow */
+	 bfd_elf_generic_reloc,	/* special_function */
+	 "R_SH_GOT_LOW16",    	/* name */
+	 false,			/* partial_inplace */
+	 0,			/* src_mask */
+	 0x3fffc00,		/* dst_mask */
+	 false),	       	/* pcrel_offset */
+
+  /* Used in MOVI and SHORI ((x >> 16) & 65536).  */
+  HOWTO (R_SH_GOT_MEDLOW16,	/* type */
+	 16,			/* rightshift */
+	 2,			/* size (0 = byte, 1 = short, 2 = long) */
+	 64,			/* bitsize */
+	 false,			/* pc_relative */
+	 10,			/* bitpos */
+	 complain_overflow_dont, /* complain_on_overflow */
+	 bfd_elf_generic_reloc,	/* special_function */
+	 "R_SH_GOT_MEDLOW16",	/* name */
+	 false,			/* partial_inplace */
+	 0,			/* src_mask */
+	 0x3fffc00,		/* dst_mask */
+	 false),	       	/* pcrel_offset */
+
+  /* Used in MOVI and SHORI ((x >> 32) & 65536).  */
+  HOWTO (R_SH_GOT_MEDHI16,	/* type */
+	 32,			/* rightshift */
+	 2,			/* size (0 = byte, 1 = short, 2 = long) */
+	 64,			/* bitsize */
+	 false,			/* pc_relative */
+	 10,			/* bitpos */
+	 complain_overflow_dont, /* complain_on_overflow */
+	 bfd_elf_generic_reloc,	/* special_function */
+	 "R_SH_GOT_MEDHI16",	/* name */
+	 false,			/* partial_inplace */
+	 0,			/* src_mask */
+	 0x3fffc00,		/* dst_mask */
+	 false),	       	/* pcrel_offset */
+
+  /* Used in MOVI and SHORI ((x >> 48) & 65536).  */
+  HOWTO (R_SH_GOT_HI16,		/* type */
+	 48,			/* rightshift */
+	 2,			/* size (0 = byte, 1 = short, 2 = long) */
+	 64,			/* bitsize */
+	 false,			/* pc_relative */
+	 10,			/* bitpos */
+	 complain_overflow_dont, /* complain_on_overflow */
+	 bfd_elf_generic_reloc,	/* special_function */
+	 "R_SH_GOT_HI16",	/* name */
+	 false,			/* partial_inplace */
+	 0,			/* src_mask */
+	 0x3fffc00,		/* dst_mask */
+	 false),	       	/* pcrel_offset */
+
+  /* Used in MOVI and SHORI (x & 65536).  */
+  HOWTO (R_SH_GOTPLT_LOW16,	/* type */
+	 0,			/* rightshift */
+	 2,			/* size (0 = byte, 1 = short, 2 = long) */
+	 64,			/* bitsize */
+	 false,			/* pc_relative */
+	 10,			/* bitpos */
+	 complain_overflow_dont, /* complain_on_overflow */
+	 bfd_elf_generic_reloc,	/* special_function */
+	 "R_SH_GOTPLT_LOW16",   /* name */
+	 false,			/* partial_inplace */
+	 0,			/* src_mask */
+	 0x3fffc00,		/* dst_mask */
+	 false),	       	/* pcrel_offset */
+
+  /* Used in MOVI and SHORI ((x >> 16) & 65536).  */
+  HOWTO (R_SH_GOTPLT_MEDLOW16,	/* type */
+	 16,			/* rightshift */
+	 2,			/* size (0 = byte, 1 = short, 2 = long) */
+	 64,			/* bitsize */
+	 false,			/* pc_relative */
+	 10,			/* bitpos */
+	 complain_overflow_dont, /* complain_on_overflow */
+	 bfd_elf_generic_reloc,	/* special_function */
+	 "R_SH_GOTPLT_MEDLOW16", /* name */
+	 false,			/* partial_inplace */
+	 0,			/* src_mask */
+	 0x3fffc00,		/* dst_mask */
+	 false),	       	/* pcrel_offset */
+
+  /* Used in MOVI and SHORI ((x >> 32) & 65536).  */
+  HOWTO (R_SH_GOTPLT_MEDHI16,	/* type */
+	 32,			/* rightshift */
+	 2,			/* size (0 = byte, 1 = short, 2 = long) */
+	 64,			/* bitsize */
+	 false,			/* pc_relative */
+	 10,			/* bitpos */
+	 complain_overflow_dont, /* complain_on_overflow */
+	 bfd_elf_generic_reloc,	/* special_function */
+	 "R_SH_GOTPLT_MEDHI16",	/* name */
+	 false,			/* partial_inplace */
+	 0,			/* src_mask */
+	 0x3fffc00,		/* dst_mask */
+	 false),	       	/* pcrel_offset */
+
+  /* Used in MOVI and SHORI ((x >> 48) & 65536).  */
+  HOWTO (R_SH_GOTPLT_HI16,	/* type */
+	 48,			/* rightshift */
+	 2,			/* size (0 = byte, 1 = short, 2 = long) */
+	 64,			/* bitsize */
+	 false,			/* pc_relative */
+	 10,			/* bitpos */
+	 complain_overflow_dont, /* complain_on_overflow */
+	 bfd_elf_generic_reloc,	/* special_function */
+	 "R_SH_GOTPLT_HI16",	/* name */
+	 false,			/* partial_inplace */
+	 0,			/* src_mask */
+	 0x3fffc00,		/* dst_mask */
+	 false),	       	/* pcrel_offset */
+
+  /* Used in MOVI and SHORI (x & 65536).  */
+  HOWTO (R_SH_PLT_LOW16,	/* type */
+	 0,			/* rightshift */
+	 2,			/* size (0 = byte, 1 = short, 2 = long) */
+	 64,			/* bitsize */
+	 true,			/* pc_relative */
+	 10,			/* bitpos */
+	 complain_overflow_dont, /* complain_on_overflow */
+	 bfd_elf_generic_reloc,	/* special_function */
+	 "R_SH_PLT_LOW16",    	/* name */
+	 false,			/* partial_inplace */
+	 0,			/* src_mask */
+	 0x3fffc00,		/* dst_mask */
+	 true),		       	/* pcrel_offset */
+
+  /* Used in MOVI and SHORI ((x >> 16) & 65536).  */
+  HOWTO (R_SH_PLT_MEDLOW16,	/* type */
+	 16,			/* rightshift */
+	 2,			/* size (0 = byte, 1 = short, 2 = long) */
+	 64,			/* bitsize */
+	 true,			/* pc_relative */
+	 10,			/* bitpos */
+	 complain_overflow_dont, /* complain_on_overflow */
+	 bfd_elf_generic_reloc,	/* special_function */
+	 "R_SH_PLT_MEDLOW16",	/* name */
+	 false,			/* partial_inplace */
+	 0,			/* src_mask */
+	 0x3fffc00,		/* dst_mask */
+	 true),		       	/* pcrel_offset */
+
+  /* Used in MOVI and SHORI ((x >> 32) & 65536).  */
+  HOWTO (R_SH_PLT_MEDHI16,	/* type */
+	 32,			/* rightshift */
+	 2,			/* size (0 = byte, 1 = short, 2 = long) */
+	 64,			/* bitsize */
+	 true,			/* pc_relative */
+	 10,			/* bitpos */
+	 complain_overflow_dont, /* complain_on_overflow */
+	 bfd_elf_generic_reloc,	/* special_function */
+	 "R_SH_PLT_MEDHI16",	/* name */
+	 false,			/* partial_inplace */
+	 0,			/* src_mask */
+	 0x3fffc00,		/* dst_mask */
+	 true),		       	/* pcrel_offset */
+
+  /* Used in MOVI and SHORI ((x >> 48) & 65536).  */
+  HOWTO (R_SH_PLT_HI16,		/* type */
+	 48,			/* rightshift */
+	 2,			/* size (0 = byte, 1 = short, 2 = long) */
+	 64,			/* bitsize */
+	 true,			/* pc_relative */
+	 10,			/* bitpos */
+	 complain_overflow_dont, /* complain_on_overflow */
+	 bfd_elf_generic_reloc,	/* special_function */
+	 "R_SH_PLT_HI16",	/* name */
+	 false,			/* partial_inplace */
+	 0,			/* src_mask */
+	 0x3fffc00,		/* dst_mask */
+	 true),		       	/* pcrel_offset */
+
+  /* Used in MOVI and SHORI (x & 65536).  */
+  HOWTO (R_SH_GOTOFF_LOW16,	/* type */
+	 0,			/* rightshift */
+	 2,			/* size (0 = byte, 1 = short, 2 = long) */
+	 64,			/* bitsize */
+	 false,			/* pc_relative */
+	 10,			/* bitpos */
+	 complain_overflow_dont, /* complain_on_overflow */
+	 bfd_elf_generic_reloc,	/* special_function */
+	 "R_SH_GOTOFF_LOW16",   /* name */
+	 false,			/* partial_inplace */
+	 0,			/* src_mask */
+	 0x3fffc00,		/* dst_mask */
+	 false),	       	/* pcrel_offset */
+
+  /* Used in MOVI and SHORI ((x >> 16) & 65536).  */
+  HOWTO (R_SH_GOTOFF_MEDLOW16,	/* type */
+	 16,			/* rightshift */
+	 2,			/* size (0 = byte, 1 = short, 2 = long) */
+	 64,			/* bitsize */
+	 false,			/* pc_relative */
+	 10,			/* bitpos */
+	 complain_overflow_dont, /* complain_on_overflow */
+	 bfd_elf_generic_reloc,	/* special_function */
+	 "R_SH_GOTOFF_MEDLOW16", /* name */
+	 false,			/* partial_inplace */
+	 0,			/* src_mask */
+	 0x3fffc00,		/* dst_mask */
+	 false),	       	/* pcrel_offset */
+
+  /* Used in MOVI and SHORI ((x >> 32) & 65536).  */
+  HOWTO (R_SH_GOTOFF_MEDHI16,	/* type */
+	 32,			/* rightshift */
+	 2,			/* size (0 = byte, 1 = short, 2 = long) */
+	 64,			/* bitsize */
+	 false,			/* pc_relative */
+	 10,			/* bitpos */
+	 complain_overflow_dont, /* complain_on_overflow */
+	 bfd_elf_generic_reloc,	/* special_function */
+	 "R_SH_GOTOFF_MEDHI16",	/* name */
+	 false,			/* partial_inplace */
+	 0,			/* src_mask */
+	 0x3fffc00,		/* dst_mask */
+	 false),	       	/* pcrel_offset */
+
+  /* Used in MOVI and SHORI ((x >> 48) & 65536).  */
+  HOWTO (R_SH_GOTOFF_HI16,	/* type */
+	 48,			/* rightshift */
+	 2,			/* size (0 = byte, 1 = short, 2 = long) */
+	 64,			/* bitsize */
+	 false,			/* pc_relative */
+	 10,			/* bitpos */
+	 complain_overflow_dont, /* complain_on_overflow */
+	 bfd_elf_generic_reloc,	/* special_function */
+	 "R_SH_GOTOFF_HI16",	/* name */
+	 false,			/* partial_inplace */
+	 0,			/* src_mask */
+	 0x3fffc00,		/* dst_mask */
+	 false),	       	/* pcrel_offset */
+
+  /* Used in MOVI and SHORI (x & 65536).  */
+  HOWTO (R_SH_GOTPC_LOW16,	/* type */
+	 0,			/* rightshift */
+	 2,			/* size (0 = byte, 1 = short, 2 = long) */
+	 64,			/* bitsize */
+	 true,			/* pc_relative */
+	 10,			/* bitpos */
+	 complain_overflow_dont, /* complain_on_overflow */
+	 bfd_elf_generic_reloc,	/* special_function */
+	 "R_SH_GOTPC_LOW16",    /* name */
+	 false,			/* partial_inplace */
+	 0,			/* src_mask */
+	 0x3fffc00,		/* dst_mask */
+	 true),		       	/* pcrel_offset */
+
+  /* Used in MOVI and SHORI ((x >> 16) & 65536).  */
+  HOWTO (R_SH_GOTPC_MEDLOW16,	/* type */
+	 16,			/* rightshift */
+	 2,			/* size (0 = byte, 1 = short, 2 = long) */
+	 64,			/* bitsize */
+	 true,			/* pc_relative */
+	 10,			/* bitpos */
+	 complain_overflow_dont, /* complain_on_overflow */
+	 bfd_elf_generic_reloc,	/* special_function */
+	 "R_SH_GOTPC_MEDLOW16", /* name */
+	 false,			/* partial_inplace */
+	 0,			/* src_mask */
+	 0x3fffc00,		/* dst_mask */
+	 true),		       	/* pcrel_offset */
+
+  /* Used in MOVI and SHORI ((x >> 32) & 65536).  */
+  HOWTO (R_SH_GOTPC_MEDHI16,	/* type */
+	 32,			/* rightshift */
+	 2,			/* size (0 = byte, 1 = short, 2 = long) */
+	 64,			/* bitsize */
+	 true,			/* pc_relative */
+	 10,			/* bitpos */
+	 complain_overflow_dont, /* complain_on_overflow */
+	 bfd_elf_generic_reloc,	/* special_function */
+	 "R_SH_GOTPC_MEDHI16",	/* name */
+	 false,			/* partial_inplace */
+	 0,			/* src_mask */
+	 0x3fffc00,		/* dst_mask */
+	 true),		       	/* pcrel_offset */
+
+  /* Used in MOVI and SHORI ((x >> 48) & 65536).  */
+  HOWTO (R_SH_GOTPC_HI16,	/* type */
+	 48,			/* rightshift */
+	 2,			/* size (0 = byte, 1 = short, 2 = long) */
+	 64,			/* bitsize */
+	 true,			/* pc_relative */
+	 10,			/* bitpos */
+	 complain_overflow_dont, /* complain_on_overflow */
+	 bfd_elf_generic_reloc,	/* special_function */
+	 "R_SH_GOTPC_HI16",	/* name */
+	 false,			/* partial_inplace */
+	 0,			/* src_mask */
+	 0x3fffc00,		/* dst_mask */
+	 true),		       	/* pcrel_offset */
+
+  /* Used in LD.L, FLD.S et al.  */
+  HOWTO (R_SH_GOT10BY4,		/* type */
+	 2,			/* rightshift */
+	 2,			/* size (0 = byte, 1 = short, 2 = long) */
+	 12,			/* bitsize */
+	 false,			/* pc_relative */
+	 10,			/* bitpos */
+	 complain_overflow_signed, /* complain_on_overflow */
+	 bfd_elf_generic_reloc,	/* special_function */
+	 "R_SH_GOT10BY4",	/* name */
+	 false,			/* partial_inplace */
+	 0,			/* src_mask */
+	 0xffc00,		/* dst_mask */
+	 false),	       	/* pcrel_offset */
+
+  /* Used in LD.L, FLD.S et al.  */
+  HOWTO (R_SH_GOTPLT10BY4,	/* type */
+	 2,			/* rightshift */
+	 2,			/* size (0 = byte, 1 = short, 2 = long) */
+	 12,			/* bitsize */
+	 false,			/* pc_relative */
+	 10,			/* bitpos */
+	 complain_overflow_signed, /* complain_on_overflow */
+	 bfd_elf_generic_reloc,	/* special_function */
+	 "R_SH_GOTPLT10BY4",	/* name */
+	 false,			/* partial_inplace */
+	 0,			/* src_mask */
+	 0xffc00,		/* dst_mask */
+	 false),	       	/* pcrel_offset */
+
+  /* Used in FLD.D, FST.P et al.  */
+  HOWTO (R_SH_GOT10BY8,		/* type */
+	 3,			/* rightshift */
+	 2,			/* size (0 = byte, 1 = short, 2 = long) */
+	 13,			/* bitsize */
+	 false,			/* pc_relative */
+	 10,			/* bitpos */
+	 complain_overflow_signed, /* complain_on_overflow */
+	 bfd_elf_generic_reloc,	/* special_function */
+	 "R_SH_GOT10BY8",	/* name */
+	 false,			/* partial_inplace */
+	 0,			/* src_mask */
+	 0xffc00,		/* dst_mask */
+	 false),	       	/* pcrel_offset */
+
+  /* Used in FLD.D, FST.P et al.  */
+  HOWTO (R_SH_GOTPLT10BY8,	/* type */
+	 3,			/* rightshift */
+	 2,			/* size (0 = byte, 1 = short, 2 = long) */
+	 13,			/* bitsize */
+	 false,			/* pc_relative */
+	 10,			/* bitpos */
+	 complain_overflow_signed, /* complain_on_overflow */
+	 bfd_elf_generic_reloc,	/* special_function */
+	 "R_SH_GOTPLT10BY8",	/* name */
+	 false,			/* partial_inplace */
+	 0,			/* src_mask */
+	 0xffc00,		/* dst_mask */
+	 false),	       	/* pcrel_offset */
+
+  HOWTO (R_SH_COPY64,		/* type */
+	 0,			/* rightshift */
+	 4,			/* size (0 = byte, 1 = short, 2 = long) */
+	 64,			/* bitsize */
+	 false,			/* pc_relative */
+	 0,			/* bitpos */
+	 complain_overflow_dont, /* complain_on_overflow */
+	 bfd_elf_generic_reloc,	/* special_function */
+	 "R_SH_COPY64", 	/* name */
+	 false,			/* partial_inplace */
+	 0,			/* src_mask */
+	 ((bfd_vma) 0) - 1,	/* dst_mask */
+	 false),	       	/* pcrel_offset */
+
+  HOWTO (R_SH_GLOB_DAT64,	/* type */
+	 0,			/* rightshift */
+	 4,			/* size (0 = byte, 1 = short, 2 = long) */
+	 64,			/* bitsize */
+	 false,			/* pc_relative */
+	 0,			/* bitpos */
+	 complain_overflow_dont, /* complain_on_overflow */
+	 bfd_elf_generic_reloc,	/* special_function */
+	 "R_SH_GLOB_DAT64", 	/* name */
+	 false,			/* partial_inplace */
+	 0,			/* src_mask */
+	 ((bfd_vma) 0) - 1,	/* dst_mask */
+	 false),	       	/* pcrel_offset */
+
+  HOWTO (R_SH_JMP_SLOT64,	/* type */
+	 0,			/* rightshift */
+	 4,			/* size (0 = byte, 1 = short, 2 = long) */
+	 64,			/* bitsize */
+	 false,			/* pc_relative */
+	 0,			/* bitpos */
+	 complain_overflow_dont, /* complain_on_overflow */
+	 bfd_elf_generic_reloc,	/* special_function */
+	 "R_SH_JMP_SLOT64", 	/* name */
+	 false,			/* partial_inplace */
+	 0,			/* src_mask */
+	 ((bfd_vma) 0) - 1,	/* dst_mask */
+	 false),	       	/* pcrel_offset */
+
+  HOWTO (R_SH_RELATIVE64,	/* type */
+	 0,			/* rightshift */
+	 4,			/* size (0 = byte, 1 = short, 2 = long) */
+	 64,			/* bitsize */
+	 false,			/* pc_relative */
+	 0,			/* bitpos */
+	 complain_overflow_dont, /* complain_on_overflow */
+	 bfd_elf_generic_reloc,	/* special_function */
+	 "R_SH_RELATIVE64", 	/* name */
+	 false,			/* partial_inplace */
+	 0,			/* src_mask */
+	 ((bfd_vma) 0) - 1,	/* dst_mask */
+	 false),	       	/* pcrel_offset */
+
+  EMPTY_HOWTO (197),
+  EMPTY_HOWTO (198),
+  EMPTY_HOWTO (199),
+  EMPTY_HOWTO (200),
+  EMPTY_HOWTO (201),
+  EMPTY_HOWTO (202),
+  EMPTY_HOWTO (203),
+  EMPTY_HOWTO (204),
+  EMPTY_HOWTO (205),
+  EMPTY_HOWTO (206),
+  EMPTY_HOWTO (207),
+  EMPTY_HOWTO (208),
+  EMPTY_HOWTO (209),
+  EMPTY_HOWTO (210),
+  EMPTY_HOWTO (211),
+  EMPTY_HOWTO (212),
+  EMPTY_HOWTO (213),
+  EMPTY_HOWTO (214),
+  EMPTY_HOWTO (215),
+  EMPTY_HOWTO (216),
+  EMPTY_HOWTO (217),
+  EMPTY_HOWTO (218),
+  EMPTY_HOWTO (219),
+  EMPTY_HOWTO (220),
+  EMPTY_HOWTO (221),
+  EMPTY_HOWTO (222),
+  EMPTY_HOWTO (223),
+  EMPTY_HOWTO (224),
+  EMPTY_HOWTO (225),
+  EMPTY_HOWTO (226),
+  EMPTY_HOWTO (227),
+  EMPTY_HOWTO (228),
+  EMPTY_HOWTO (229),
+  EMPTY_HOWTO (230),
+  EMPTY_HOWTO (231),
+  EMPTY_HOWTO (232),
+  EMPTY_HOWTO (233),
+  EMPTY_HOWTO (234),
+  EMPTY_HOWTO (235),
+  EMPTY_HOWTO (236),
+  EMPTY_HOWTO (237),
+  EMPTY_HOWTO (238),
+  EMPTY_HOWTO (239),
+  EMPTY_HOWTO (240),
+  EMPTY_HOWTO (241),
+
+  /* Relocations for SHmedia code.  None of these are partial_inplace or
+     use the field being relocated (except R_SH_PT_16).  */
+
+  /* The assembler will generate this reloc before a block of SHmedia
+     instructions.  A section should be processed as assuming it contains
+     data, unless this reloc is seen.  Note that a block of SHcompact
+     instructions are instead preceded by R_SH_CODE.
+     This is currently not implemented, but should be used for SHmedia
+     linker relaxation.  */
+  HOWTO (R_SH_SHMEDIA_CODE,	/* type */
+	 0,			/* rightshift */
+	 1,			/* size (0 = byte, 1 = short, 2 = long) */
+	 0,			/* bitsize */
+	 false,			/* pc_relative */
+	 0,			/* bitpos */
+	 complain_overflow_unsigned, /* complain_on_overflow */
+	 sh_elf_ignore_reloc,	/* special_function */
+	 "R_SH_SHMEDIA_CODE",	/* name */
+	 false,			/* partial_inplace */
+	 0,			/* src_mask */
+	 0,			/* dst_mask */
+	 false),		/* pcrel_offset */
+
+  /* The assembler will generate this reloc at a PTA or PTB instruction,
+     and the linker checks the right type of target, or changes a PTA to a
+     PTB, if the original insn was PT.  */
+  HOWTO (R_SH_PT_16,		/* type */
+	 2,			/* rightshift */
+	 2,			/* size (0 = byte, 1 = short, 2 = long) */
+	 18,			/* bitsize */
+	 true,			/* pc_relative */
+	 10,			/* bitpos */
+	 complain_overflow_signed, /* complain_on_overflow */
+	 bfd_elf_generic_reloc,	/* special_function */
+	 "R_SH_PT_16",		/* name */
+	 false,			/* partial_inplace */
+	 0,			/* src_mask */
+	 0x3fffc00,		/* dst_mask */
+	 true),			/* pcrel_offset */
+
+  /* Used in unexpanded MOVI.  */
+  HOWTO (R_SH_IMMS16,		/* type */
+	 0,			/* rightshift */
+	 2,			/* size (0 = byte, 1 = short, 2 = long) */
+	 16,			/* bitsize */
+	 false,			/* pc_relative */
+	 10,			/* bitpos */
+	 complain_overflow_signed, /* complain_on_overflow */
+	 bfd_elf_generic_reloc,	/* special_function */
+	 "R_SH_IMMS16",		/* name */
+	 false,			/* partial_inplace */
+	 0,			/* src_mask */
+	 0x3fffc00,		/* dst_mask */
+	 false),	       	/* pcrel_offset */
+
+  /* Used in SHORI.  */
+  HOWTO (R_SH_IMMU16,		/* type */
+	 0,			/* rightshift */
+	 2,			/* size (0 = byte, 1 = short, 2 = long) */
+	 16,			/* bitsize */
+	 false,			/* pc_relative */
+	 10,			/* bitpos */
+	 complain_overflow_unsigned, /* complain_on_overflow */
+	 bfd_elf_generic_reloc,	/* special_function */
+	 "R_SH_IMMU16",		/* name */
+	 false,			/* partial_inplace */
+	 0,			/* src_mask */
+	 0x3fffc00,		/* dst_mask */
+	 false),	       	/* pcrel_offset */
+
+  /* Used in MOVI and SHORI (x & 65536).  */
+  HOWTO (R_SH_IMM_LOW16,	/* type */
+	 0,			/* rightshift */
+	 2,			/* size (0 = byte, 1 = short, 2 = long) */
+	 64,			/* bitsize */
+	 false,			/* pc_relative */
+	 10,			/* bitpos */
+	 complain_overflow_dont, /* complain_on_overflow */
+	 bfd_elf_generic_reloc,	/* special_function */
+	 "R_SH_IMM_LOW16",    	/* name */
+	 false,			/* partial_inplace */
+	 0,			/* src_mask */
+	 0x3fffc00,		/* dst_mask */
+	 false),	       	/* pcrel_offset */
+
+  /* Used in MOVI and SHORI ((x - $) & 65536).  */
+  HOWTO (R_SH_IMM_LOW16_PCREL,	/* type */
+	 0,			/* rightshift */
+	 2,			/* size (0 = byte, 1 = short, 2 = long) */
+	 64,			/* bitsize */
+	 true,			/* pc_relative */
+	 10,			/* bitpos */
+	 complain_overflow_dont, /* complain_on_overflow */
+	 bfd_elf_generic_reloc,	/* special_function */
+	 "R_SH_IMM_LOW16_PCREL", /* name */
+	 false,			/* partial_inplace */
+	 0,			/* src_mask */
+	 0x3fffc00,		/* dst_mask */
+	 true),			/* pcrel_offset */
+
+  /* Used in MOVI and SHORI ((x >> 16) & 65536).  */
+  HOWTO (R_SH_IMM_MEDLOW16,	/* type */
+	 16,			/* rightshift */
+	 2,			/* size (0 = byte, 1 = short, 2 = long) */
+	 64,			/* bitsize */
+	 false,			/* pc_relative */
+	 10,			/* bitpos */
+	 complain_overflow_dont, /* complain_on_overflow */
+	 bfd_elf_generic_reloc,	/* special_function */
+	 "R_SH_IMM_MEDLOW16",	/* name */
+	 false,			/* partial_inplace */
+	 0,			/* src_mask */
+	 0x3fffc00,		/* dst_mask */
+	 false),	       	/* pcrel_offset */
+
+  /* Used in MOVI and SHORI (((x - $) >> 16) & 65536).  */
+  HOWTO (R_SH_IMM_MEDLOW16_PCREL, /* type */
+	 16,			/* rightshift */
+	 2,			/* size (0 = byte, 1 = short, 2 = long) */
+	 64,			/* bitsize */
+	 true,			/* pc_relative */
+	 10,			/* bitpos */
+	 complain_overflow_dont, /* complain_on_overflow */
+	 bfd_elf_generic_reloc,	/* special_function */
+	 "R_SH_IMM_MEDLOW16_PCREL", /* name */
+	 false,			/* partial_inplace */
+	 0,			/* src_mask */
+	 0x3fffc00,		/* dst_mask */
+	 true),			/* pcrel_offset */
+
+  /* Used in MOVI and SHORI ((x >> 32) & 65536).  */
+  HOWTO (R_SH_IMM_MEDHI16,	/* type */
+	 32,			/* rightshift */
+	 2,			/* size (0 = byte, 1 = short, 2 = long) */
+	 64,			/* bitsize */
+	 false,			/* pc_relative */
+	 10,			/* bitpos */
+	 complain_overflow_dont, /* complain_on_overflow */
+	 bfd_elf_generic_reloc,	/* special_function */
+	 "R_SH_IMM_MEDHI16",	/* name */
+	 false,			/* partial_inplace */
+	 0,			/* src_mask */
+	 0x3fffc00,		/* dst_mask */
+	 false),	       	/* pcrel_offset */
+
+  /* Used in MOVI and SHORI (((x - $) >> 32) & 65536).  */
+  HOWTO (R_SH_IMM_MEDHI16_PCREL, /* type */
+	 32,			/* rightshift */
+	 2,			/* size (0 = byte, 1 = short, 2 = long) */
+	 64,			/* bitsize */
+	 true,			/* pc_relative */
+	 10,			/* bitpos */
+	 complain_overflow_dont, /* complain_on_overflow */
+	 bfd_elf_generic_reloc,	/* special_function */
+	 "R_SH_IMM_MEDHI16_PCREL", /* name */
+	 false,			/* partial_inplace */
+	 0,			/* src_mask */
+	 0x3fffc00,		/* dst_mask */
+	 true),			/* pcrel_offset */
+
+  /* Used in MOVI and SHORI ((x >> 48) & 65536).  */
+  HOWTO (R_SH_IMM_HI16,		/* type */
+	 48,			/* rightshift */
+	 2,			/* size (0 = byte, 1 = short, 2 = long) */
+	 64,			/* bitsize */
+	 false,			/* pc_relative */
+	 10,			/* bitpos */
+	 complain_overflow_dont, /* complain_on_overflow */
+	 bfd_elf_generic_reloc,	/* special_function */
+	 "R_SH_IMM_HI16",	/* name */
+	 false,			/* partial_inplace */
+	 0,			/* src_mask */
+	 0x3fffc00,		/* dst_mask */
+	 false),	       	/* pcrel_offset */
+
+  /* Used in MOVI and SHORI (((x - $) >> 48) & 65536).  */
+  HOWTO (R_SH_IMM_HI16_PCREL,	/* type */
+	 48,			/* rightshift */
+	 2,			/* size (0 = byte, 1 = short, 2 = long) */
+	 64,			/* bitsize */
+	 true,			/* pc_relative */
+	 10,			/* bitpos */
+	 complain_overflow_dont, /* complain_on_overflow */
+	 bfd_elf_generic_reloc,	/* special_function */
+	 "R_SH_IMM_HI16_PCREL", /* name */
+	 false,			/* partial_inplace */
+	 0,			/* src_mask */
+	 0x3fffc00,		/* dst_mask */
+	 true),			/* pcrel_offset */
+
+  /* For the .uaquad pseudo.  */
+  HOWTO (R_SH_64,		/* type */
+	 0,			/* rightshift */
+	 4,			/* size (0 = byte, 1 = short, 2 = long) */
+	 64,			/* bitsize */
+	 false,			/* pc_relative */
+	 0,			/* bitpos */
+	 complain_overflow_dont, /* complain_on_overflow */
+	 bfd_elf_generic_reloc,	/* special_function */
+	 "R_SH_64", 		/* name */
+	 false,			/* partial_inplace */
+	 0,			/* src_mask */
+	 ((bfd_vma) 0) - 1,	/* dst_mask */
+	 false),	       	/* pcrel_offset */
+
+  /* For the .uaquad pseudo, (x - $).  */
+  HOWTO (R_SH_64_PCREL,		/* type */
+	 48,			/* rightshift */
+	 2,			/* size (0 = byte, 1 = short, 2 = long) */
+	 64,			/* bitsize */
+	 true,			/* pc_relative */
+	 10,			/* bitpos */
+	 complain_overflow_dont, /* complain_on_overflow */
+	 bfd_elf_generic_reloc,	/* special_function */
+	 "R_SH_64_PCREL",	/* name */
+	 false,			/* partial_inplace */
+	 0,			/* src_mask */
+	 ((bfd_vma) 0) - 1,	/* dst_mask */
+	 true),			/* pcrel_offset */
+
+#endif
 };
 
 static bfd_reloc_status_type
@@ -965,6 +1773,58 @@ static const struct elf_reloc_map sh_rel
   { BFD_RELOC_SH_RELATIVE, R_SH_RELATIVE },
   { BFD_RELOC_32_GOTOFF, R_SH_GOTOFF },
   { BFD_RELOC_SH_GOTPC, R_SH_GOTPC },
+  { BFD_RELOC_SH_GOTPLT32, R_SH_GOTPLT32 },
+#ifdef INCLUDE_SHMEDIA
+  { BFD_RELOC_SH_GOT_LOW16, R_SH_GOT_LOW16 },
+  { BFD_RELOC_SH_GOT_MEDLOW16, R_SH_GOT_MEDLOW16 },
+  { BFD_RELOC_SH_GOT_MEDHI16, R_SH_GOT_MEDHI16 },
+  { BFD_RELOC_SH_GOT_HI16, R_SH_GOT_HI16 },
+  { BFD_RELOC_SH_GOTPLT_LOW16, R_SH_GOTPLT_LOW16 },
+  { BFD_RELOC_SH_GOTPLT_MEDLOW16, R_SH_GOTPLT_MEDLOW16 },
+  { BFD_RELOC_SH_GOTPLT_MEDHI16, R_SH_GOTPLT_MEDHI16 },
+  { BFD_RELOC_SH_GOTPLT_HI16, R_SH_GOTPLT_HI16 },
+  { BFD_RELOC_SH_PLT_LOW16, R_SH_PLT_LOW16 },
+  { BFD_RELOC_SH_PLT_MEDLOW16, R_SH_PLT_MEDLOW16 },
+  { BFD_RELOC_SH_PLT_MEDHI16, R_SH_PLT_MEDHI16 },
+  { BFD_RELOC_SH_PLT_HI16, R_SH_PLT_HI16 },
+  { BFD_RELOC_SH_GOTOFF_LOW16, R_SH_GOTOFF_LOW16 },
+  { BFD_RELOC_SH_GOTOFF_MEDLOW16, R_SH_GOTOFF_MEDLOW16 },
+  { BFD_RELOC_SH_GOTOFF_MEDHI16, R_SH_GOTOFF_MEDHI16 },
+  { BFD_RELOC_SH_GOTOFF_HI16, R_SH_GOTOFF_HI16 },
+  { BFD_RELOC_SH_GOTPC_LOW16, R_SH_GOTPC_LOW16 },
+  { BFD_RELOC_SH_GOTPC_MEDLOW16, R_SH_GOTPC_MEDLOW16 },
+  { BFD_RELOC_SH_GOTPC_MEDHI16, R_SH_GOTPC_MEDHI16 },
+  { BFD_RELOC_SH_GOTPC_HI16, R_SH_GOTPC_HI16 },
+  { BFD_RELOC_SH_COPY64, R_SH_COPY64 },
+  { BFD_RELOC_SH_GLOB_DAT64, R_SH_GLOB_DAT64 },
+  { BFD_RELOC_SH_JMP_SLOT64, R_SH_JMP_SLOT64 },
+  { BFD_RELOC_SH_RELATIVE64, R_SH_RELATIVE64 },
+  { BFD_RELOC_SH_GOT10BY4, R_SH_GOT10BY4 },
+  { BFD_RELOC_SH_GOT10BY8, R_SH_GOT10BY8 },
+  { BFD_RELOC_SH_GOTPLT10BY4, R_SH_GOTPLT10BY4 },
+  { BFD_RELOC_SH_GOTPLT10BY8, R_SH_GOTPLT10BY8 },
+  { BFD_RELOC_SH_PT_16, R_SH_PT_16 },
+  { BFD_RELOC_SH_SHMEDIA_CODE, R_SH_SHMEDIA_CODE },
+  { BFD_RELOC_SH_IMMU5, R_SH_DIR5U },
+  { BFD_RELOC_SH_IMMS6, R_SH_DIR6S },
+  { BFD_RELOC_SH_IMMU6, R_SH_DIR6U },
+  { BFD_RELOC_SH_IMMS10, R_SH_DIR10S },
+  { BFD_RELOC_SH_IMMS10BY2, R_SH_DIR10SW },
+  { BFD_RELOC_SH_IMMS10BY4, R_SH_DIR10SL },
+  { BFD_RELOC_SH_IMMS10BY8, R_SH_DIR10SQ },
+  { BFD_RELOC_SH_IMMS16, R_SH_IMMS16 },
+  { BFD_RELOC_SH_IMMU16, R_SH_IMMU16 },
+  { BFD_RELOC_SH_IMM_LOW16, R_SH_IMM_LOW16 },
+  { BFD_RELOC_SH_IMM_LOW16_PCREL, R_SH_IMM_LOW16_PCREL },
+  { BFD_RELOC_SH_IMM_MEDLOW16, R_SH_IMM_MEDLOW16 },
+  { BFD_RELOC_SH_IMM_MEDLOW16_PCREL, R_SH_IMM_MEDLOW16_PCREL },
+  { BFD_RELOC_SH_IMM_MEDHI16, R_SH_IMM_MEDHI16 },
+  { BFD_RELOC_SH_IMM_MEDHI16_PCREL, R_SH_IMM_MEDHI16_PCREL },
+  { BFD_RELOC_SH_IMM_HI16, R_SH_IMM_HI16 },
+  { BFD_RELOC_SH_IMM_HI16_PCREL, R_SH_IMM_HI16_PCREL },
+  { BFD_RELOC_64, R_SH_64 },
+  { BFD_RELOC_64_PCREL, R_SH_64_PCREL },
+#endif /* not INCLUDE_SHMEDIA */
 };
 
 /* Given a BFD reloc code, return the howto structure for the
@@ -1001,6 +1861,8 @@ sh_elf_info_to_howto (abfd, cache_ptr, d
   BFD_ASSERT (r < (unsigned int) R_SH_max);
   BFD_ASSERT (r < R_SH_FIRST_INVALID_RELOC || r > R_SH_LAST_INVALID_RELOC);
   BFD_ASSERT (r < R_SH_FIRST_INVALID_RELOC_2 || r > R_SH_LAST_INVALID_RELOC_2);
+  BFD_ASSERT (r < R_SH_FIRST_INVALID_RELOC_3 || r > R_SH_LAST_INVALID_RELOC_3);
+  BFD_ASSERT (r < R_SH_FIRST_INVALID_RELOC_4 || r > R_SH_LAST_INVALID_RELOC_4);
 
   cache_ptr->howto = &sh_elf_howto_table[r];
 }
@@ -1041,6 +1903,14 @@ sh_elf_relax_section (abfd, sec, link_in
       || sec->reloc_count == 0)
     return true;
 
+#ifdef INCLUDE_SHMEDIA
+  if (elf_section_data (sec)->this_hdr.sh_flags
+      & (SHF_SH5_ISA32 | SHF_SH5_ISA32_MIXED))
+    {
+      return true;
+    }
+#endif
+
   /* If this is the first time we have been called for this section,
      initialize the cooked size.  */
   if (sec->_cooked_size == 0)
@@ -2140,6 +3010,178 @@ sh_elf_swap_insns (abfd, sec, relocs, co
   return true;
 }
 
+#ifdef INCLUDE_SHMEDIA
+
+/* The size in bytes of an entry in the procedure linkage table.  */
+
+#define PLT_ENTRY_SIZE 64
+
+/* First entry in an absolute procedure linkage table look like this.  */
+
+static const bfd_byte elf_sh_plt0_entry_be[PLT_ENTRY_SIZE] =
+{
+  0xcc, 0x00, 0x01, 0x10, /* movi  .got.plt >> 16, r17 */
+  0xc8, 0x00, 0x01, 0x10, /* shori .got.plt & 65535, r17 */
+  0x89, 0x10, 0x09, 0x90, /* ld.l  r17, 8, r25 */
+  0x6b, 0xf1, 0x46, 0x00, /* ptabs r17, tr0 */
+  0x89, 0x10, 0x05, 0x10, /* ld.l  r17, 4, r17 */
+  0x44, 0x01, 0xff, 0xf0, /* blink tr0, r63 */
+  0x6f, 0xf0, 0xff, 0xf0, /* nop */
+  0x6f, 0xf0, 0xff, 0xf0, /* nop */
+  0x6f, 0xf0, 0xff, 0xf0, /* nop */
+  0x6f, 0xf0, 0xff, 0xf0, /* nop */
+  0x6f, 0xf0, 0xff, 0xf0, /* nop */
+  0x6f, 0xf0, 0xff, 0xf0, /* nop */
+  0x6f, 0xf0, 0xff, 0xf0, /* nop */
+  0x6f, 0xf0, 0xff, 0xf0, /* nop */
+  0x6f, 0xf0, 0xff, 0xf0, /* nop */
+  0x6f, 0xf0, 0xff, 0xf0, /* nop */
+};
+
+static const bfd_byte elf_sh_plt0_entry_le[PLT_ENTRY_SIZE] =
+{
+  0x10, 0x01, 0x00, 0xcc, /* movi  .got.plt >> 16, r17 */
+  0x10, 0x01, 0x00, 0xc8, /* shori .got.plt & 65535, r17 */
+  0x90, 0x09, 0x10, 0x89, /* ld.l  r17, 8, r25 */
+  0x00, 0x46, 0xf1, 0x6b, /* ptabs r17, tr0 */
+  0x10, 0x05, 0x10, 0x89, /* ld.l  r17, 4, r17 */
+  0xf0, 0xff, 0x01, 0x44, /* blink tr0, r63 */
+  0xf0, 0xff, 0xf0, 0x6f, /* nop */
+  0xf0, 0xff, 0xf0, 0x6f, /* nop */
+  0xf0, 0xff, 0xf0, 0x6f, /* nop */
+  0xf0, 0xff, 0xf0, 0x6f, /* nop */
+  0xf0, 0xff, 0xf0, 0x6f, /* nop */
+  0xf0, 0xff, 0xf0, 0x6f, /* nop */
+  0xf0, 0xff, 0xf0, 0x6f, /* nop */
+  0xf0, 0xff, 0xf0, 0x6f, /* nop */
+  0xf0, 0xff, 0xf0, 0x6f, /* nop */
+  0xf0, 0xff, 0xf0, 0x6f, /* nop */
+};
+
+/* Sebsequent entries in an absolute procedure linkage table look like
+   this.  */
+
+static const bfd_byte elf_sh_plt_entry_be[PLT_ENTRY_SIZE] =
+{
+  0xcc, 0x00, 0x01, 0x90, /* movi  nameN-in-GOT >> 16, r25 */
+  0xc8, 0x00, 0x01, 0x90, /* shori nameN-in-GOT & 65535, r25 */
+  0x89, 0x90, 0x01, 0x90, /* ld.l  r25, 0, r25 */
+  0x6b, 0xf1, 0x66, 0x00, /* ptabs r25, tr0 */
+  0x44, 0x01, 0xff, 0xf0, /* blink tr0, r63 */
+  0x6f, 0xf0, 0xff, 0xf0, /* nop */
+  0x6f, 0xf0, 0xff, 0xf0, /* nop */
+  0x6f, 0xf0, 0xff, 0xf0, /* nop */
+  0xcc, 0x00, 0x01, 0x90, /* movi  .PLT0 >> 16, r25 */
+  0xc8, 0x00, 0x01, 0x90, /* shori .PLT0 & 65535, r25 */
+  0x6b, 0xf1, 0x66, 0x00, /* ptabs r25, tr0 */
+  0xcc, 0x00, 0x01, 0x50, /* movi  reloc-offset >> 16, r21 */
+  0xc8, 0x00, 0x01, 0x50, /* shori reloc-offset & 65535, r21 */
+  0x44, 0x01, 0xff, 0xf0, /* blink tr0, r63 */
+  0x6f, 0xf0, 0xff, 0xf0, /* nop */
+  0x6f, 0xf0, 0xff, 0xf0, /* nop */
+};
+
+static const bfd_byte elf_sh_plt_entry_le[PLT_ENTRY_SIZE] =
+{
+  0x90, 0x01, 0x00, 0xcc, /* movi  nameN-in-GOT >> 16, r25 */
+  0x90, 0x01, 0x00, 0xc8, /* shori nameN-in-GOT & 65535, r25 */
+  0x90, 0x01, 0x90, 0x89, /* ld.l  r25, 0, r25 */
+  0x00, 0x66, 0xf1, 0x6b, /* ptabs r25, tr0 */
+  0xf0, 0xff, 0x01, 0x44, /* blink tr0, r63 */
+  0xf0, 0xff, 0xf0, 0x6f, /* nop */
+  0xf0, 0xff, 0xf0, 0x6f, /* nop */
+  0xf0, 0xff, 0xf0, 0x6f, /* nop */
+  0x90, 0x01, 0x00, 0xcc, /* movi  .PLT0 >> 16, r25 */
+  0x90, 0x01, 0x00, 0xc8, /* shori .PLT0 & 65535, r25 */
+  0x00, 0x66, 0xf1, 0x6b, /* ptabs r25, tr0 */
+  0x50, 0x01, 0x00, 0xcc, /* movi  reloc-offset >> 16, r21 */
+  0x50, 0x01, 0x00, 0xc8, /* shori reloc-offset & 65535, r21 */
+  0xf0, 0xff, 0x01, 0x44, /* blink tr0, r63 */
+  0xf0, 0xff, 0xf0, 0x6f, /* nop */
+  0xf0, 0xff, 0xf0, 0x6f, /* nop */
+};
+
+/* Entries in a PIC procedure linkage table look like this.  */
+
+static const bfd_byte elf_sh_pic_plt_entry_be[PLT_ENTRY_SIZE] =
+{
+  0xcc, 0x00, 0x01, 0x90, /* movi  nameN@GOT >> 16, r25 */
+  0xc8, 0x00, 0x01, 0x90, /* shori nameN@GOT & 65535, r25 */
+  0x40, 0xc2, 0x65, 0x90, /* ldx.l r12, r25, r25 */
+  0x6b, 0xf1, 0x66, 0x00, /* ptabs r25, tr0 */
+  0x44, 0x01, 0xff, 0xf0, /* blink tr0, r63 */
+  0x6f, 0xf0, 0xff, 0xf0, /* nop */
+  0x6f, 0xf0, 0xff, 0xf0, /* nop */
+  0x6f, 0xf0, 0xff, 0xf0, /* nop */
+  0xce, 0x00, 0x01, 0x10, /* movi  -GOT_BIAS, r17 */
+  0x00, 0xca, 0x45, 0x10, /* sub.l r12, r17, r17 */
+  0x89, 0x10, 0x09, 0x90, /* ld.l  r17, 8, r25 */
+  0x6b, 0xf1, 0x66, 0x00, /* ptabs r25, tr0 */
+  0x89, 0x10, 0x05, 0x10, /* ld.l  r17, 4, r17 */
+  0xcc, 0x00, 0x01, 0x50, /* movi  reloc-offset >> 16, r21 */
+  0xc8, 0x00, 0x01, 0x50, /* shori reloc-offset & 65535, r21 */
+  0x44, 0x01, 0xff, 0xf0, /* blink tr0, r63 */
+};
+
+static const bfd_byte elf_sh_pic_plt_entry_le[PLT_ENTRY_SIZE] =
+{
+  0x90, 0x01, 0x00, 0xcc, /* movi  nameN@GOT >> 16, r25 */
+  0x90, 0x01, 0x00, 0xc8, /* shori nameN@GOT & 65535, r25 */
+  0x90, 0x65, 0xc2, 0x40, /* ldx.l r12, r25, r25 */
+  0x00, 0x66, 0xf1, 0x6b, /* ptabs r25, tr0 */
+  0xf0, 0xff, 0x01, 0x44, /* blink tr0, r63 */
+  0xf0, 0xff, 0xf0, 0x6f, /* nop */
+  0xf0, 0xff, 0xf0, 0x6f, /* nop */
+  0xf0, 0xff, 0xf0, 0x6f, /* nop */
+  0x10, 0x01, 0x00, 0xce, /* movi  -GOT_BIAS, r17 */
+  0x10, 0x45, 0xca, 0x00, /* sub.l r12, r17, r17 */
+  0x90, 0x09, 0x10, 0x89, /* ld.l  r17, 8, r25 */
+  0x00, 0x66, 0xf1, 0x6b, /* ptabs r25, tr0 */
+  0x10, 0x05, 0x10, 0x89, /* ld.l  r17, 4, r17 */
+  0x50, 0x01, 0x00, 0xcc, /* movi  reloc-offset >> 16, r21 */
+  0x50, 0x01, 0x00, 0xc8, /* shori reloc-offset & 65535, r21 */
+  0xf0, 0xff, 0x01, 0x44, /* blink tr0, r63 */
+};
+
+static const bfd_byte *elf_sh_plt0_entry;
+static const bfd_byte *elf_sh_plt_entry;
+static const bfd_byte *elf_sh_pic_plt_entry;
+
+/* Return size of a PLT entry.  */
+#define elf_sh_sizeof_plt(info) PLT_ENTRY_SIZE
+
+/* Return offset of the PLT0 address in an absolute PLT entry.  */
+#define elf_sh_plt_plt0_offset(info) 32
+
+/* Return offset of the linker in PLT0 entry.  */
+#define elf_sh_plt0_gotplt_offset(info) 0
+
+/* Return offset of the trampoline in PLT entry */
+#define elf_sh_plt_temp_offset(info) 33 /* Add one because it's SHmedia.  */
+
+/* Return offset of the symbol in PLT entry.  */
+#define elf_sh_plt_symbol_offset(info) 0
+
+/* Return offset of the relocation in PLT entry.  */
+#define elf_sh_plt_reloc_offset(info) (info->shared ? 52 : 44)
+
+inline static void
+movi_shori_putval (output_bfd, value, addr)
+     bfd *output_bfd;
+     unsigned long value;
+     char *addr;
+{
+  bfd_put_32 (output_bfd,
+	      bfd_get_32 (output_bfd, addr)
+	      | ((value >> 6) & 0x3fffc00),
+	      addr);
+  bfd_put_32 (output_bfd,
+	      bfd_get_32 (output_bfd, addr + 4)
+	      | ((value << 10) & 0x3fffc00),
+	      addr + 4);
+}
+
+#else
 /* The size in bytes of an entry in the procedure linkage table.  */
 
 #define PLT_ENTRY_SIZE 28
@@ -2379,6 +3421,7 @@ static const bfd_byte *elf_sh_pic_plt_en
 
 /* Return offset of the relocation in PLT entry.  */
 #define elf_sh_plt_reloc_offset(info) 24
+#endif
 
 /* The sh linker needs to keep track of the number of relocs that it
    decides to copy in check_relocs for each symbol.  This is so that
@@ -2405,6 +3448,10 @@ struct elf_sh_link_hash_entry
 {
   struct elf_link_hash_entry root;
 
+#ifdef INCLUDE_SHMEDIA
+  bfd_vma datalabel_got_offset;
+#endif
+
   /* Number of PC relative relocs copied for this symbol.  */
   struct elf_sh_pcrel_relocs_copied *pcrel_relocs_copied;
 };
@@ -2461,6 +3508,9 @@ sh_elf_link_hash_newfunc (entry, table, 
   if (ret != (struct elf_sh_link_hash_entry *) NULL)
     {
       ret->pcrel_relocs_copied = NULL;
+#ifdef INCLUDE_SHMEDIA
+      ret->datalabel_got_offset = (bfd_vma) -1;
+#endif
     }
 
   return (struct bfd_hash_entry *) ret;
@@ -3014,6 +4064,7 @@ sh_elf_relocate_section (output_bfd, inf
   bfd *dynobj;
   bfd_vma *local_got_offsets;
   asection *sgot;
+  asection *sgotplt;
   asection *splt;
   asection *sreloc;
 
@@ -3023,6 +4074,7 @@ sh_elf_relocate_section (output_bfd, inf
   local_got_offsets = elf_local_got_offsets (input_bfd);
 
   sgot = NULL;
+  sgotplt = NULL;
   splt = NULL;
   sreloc = NULL;
 
@@ -3039,6 +4091,7 @@ sh_elf_relocate_section (output_bfd, inf
       bfd_vma relocation;
       bfd_vma addend = (bfd_vma) 0;
       bfd_reloc_status_type r;
+      int seen_stt_datalabel = 0;
 
       r_symndx = ELF32_R_SYM (rel->r_info);
 
@@ -3056,6 +4109,10 @@ sh_elf_relocate_section (output_bfd, inf
 	  || r_type >= R_SH_max
 	  || (r_type >= (int) R_SH_FIRST_INVALID_RELOC
 	      && r_type <= (int) R_SH_LAST_INVALID_RELOC)
+	  || (   r_type >= (int) R_SH_FIRST_INVALID_RELOC_3
+	      && r_type <= (int) R_SH_LAST_INVALID_RELOC_3)
+	  || (   r_type >= (int) R_SH_FIRST_INVALID_RELOC_4
+	      && r_type <= (int) R_SH_LAST_INVALID_RELOC_4)
 	  || (r_type >= (int) R_SH_FIRST_INVALID_RELOC_2
 	      && r_type <= (int) R_SH_LAST_INVALID_RELOC_2))
 	{
@@ -3080,6 +4137,14 @@ sh_elf_relocate_section (output_bfd, inf
 	  relocation = (sec->output_section->vma
 			+ sec->output_offset
 			+ sym->st_value);
+	  /* A local symbol never has STO_SH5_ISA32, so we don't need
+	     datalabel processing here.  Make sure this does not change
+	     without notice.  */
+	  if ((sym->st_other & STO_SH5_ISA32) != 0)
+	    ((*info->callbacks->reloc_dangerous)
+	     (info,
+	      _("Unexpected STO_SH5_ISA32 on local symbol is not handled"),
+	      input_bfd, input_section, rel->r_offset));
 	  if (info->relocateable)
 	    {
 	      /* This is a relocateable link.  We don't have to change
@@ -3158,7 +4223,15 @@ sh_elf_relocate_section (output_bfd, inf
 	  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;
+	    {
+#ifdef INCLUDE_SHMEDIA
+	      /* If the reference passes a symbol marked with
+		 STT_DATALABEL, then any STO_SH5_ISA32 on the final value
+		 doesn't count.  */
+	      seen_stt_datalabel |= h->type == STT_DATALABEL;
+#endif
+	      h = (struct elf_link_hash_entry *) h->root.u.i.link;
+	    }
 	  if (h->root.type == bfd_link_hash_defined
 	      || h->root.type == bfd_link_hash_defweak)
 	    {
@@ -3167,9 +4240,21 @@ sh_elf_relocate_section (output_bfd, inf
 		 We check specially because in some obscure cases
 		 sec->output_section will be NULL.  */
 	      if (r_type == R_SH_GOTPC
-		  || (r_type == R_SH_PLT32
+		  || r_type == R_SH_GOTPC_LOW16
+		  || r_type == R_SH_GOTPC_MEDLOW16
+		  || r_type == R_SH_GOTPC_MEDHI16
+		  || r_type == R_SH_GOTPC_HI16
+		  || ((r_type == R_SH_PLT32
+		       || r_type == R_SH_PLT_LOW16
+		       || r_type == R_SH_PLT_MEDLOW16
+		       || r_type == R_SH_PLT_MEDHI16
+		       || r_type == R_SH_PLT_HI16)
 		      && h->plt.offset != (bfd_vma) -1)
-		  || (r_type == R_SH_GOT32
+		  || ((r_type == R_SH_GOT32
+		       || r_type == R_SH_GOT_LOW16
+		       || r_type == R_SH_GOT_MEDLOW16
+		       || r_type == R_SH_GOT_MEDHI16
+		       || r_type == R_SH_GOT_HI16)
 		      && elf_hash_table (info)->dynamic_sections_created
 		      && (! info->shared
 			  || (! info->symbolic && h->dynindx != -1)
@@ -3204,9 +4289,14 @@ sh_elf_relocate_section (output_bfd, inf
 		  relocation = 0;
 		}
 	      else
-		relocation = (h->root.u.def.value
+		relocation = ((h->root.u.def.value
 			      + sec->output_section->vma
-			      + sec->output_offset);
+			      + sec->output_offset)
+			      /* A STO_SH5_ISA32 causes a "bitor 1" to the
+				 symbol value, unless we've seen
+				 STT_DATALABEL on the way to it.  */
+			      | ((h->other & STO_SH5_ISA32) != 0
+				 && ! seen_stt_datalabel));
 	    }
 	  else if (h->root.type == bfd_link_hash_undefweak)
 	    relocation = 0;
@@ -3277,6 +4367,11 @@ sh_elf_relocate_section (output_bfd, inf
 	  break;
 
 	default:
+#ifdef INCLUDE_SHMEDIA
+	  if (shmedia_prepare_reloc (info, input_bfd, input_section,
+				     contents, rel, &relocation))
+	    goto final_link_relocate;
+#endif
 	  bfd_set_error (bfd_error_bad_value);
 	  return false;
 
@@ -3383,7 +4478,56 @@ sh_elf_relocate_section (output_bfd, inf
 	    }
 	  goto final_link_relocate;
 
+	case R_SH_GOTPLT32:
+#ifdef INCLUDE_SHMEDIA
+	case R_SH_GOTPLT_LOW16:
+	case R_SH_GOTPLT_MEDLOW16:
+	case R_SH_GOTPLT_MEDHI16:
+	case R_SH_GOTPLT_HI16:
+	case R_SH_GOTPLT10BY4:
+	case R_SH_GOTPLT10BY8:
+#endif
+	  /* Relocation is to the entry for this symbol in the
+	     procedure linkage table.  */
+
+	  if (h == NULL
+	      || ELF_ST_VISIBILITY (h->other) == STV_INTERNAL
+	      || ELF_ST_VISIBILITY (h->other) == STV_HIDDEN
+	      || ! info->shared
+	      || info->symbolic
+	      || h->dynindx == -1
+	      || h->plt.offset == (bfd_vma) -1
+	      || h->got.offset != (bfd_vma) -1)
+	    goto force_got;
+
+	  /* Relocation is to the entry for this symbol in the global
+	     offset table extension for the procedure linkage table.  */
+	  if (sgotplt == NULL)
+	    {
+	      sgotplt = bfd_get_section_by_name (dynobj, ".got.plt");
+	      BFD_ASSERT (sgotplt != NULL);
+	    }
+
+	  relocation = (sgotplt->output_offset
+			+ ((h->plt.offset / elf_sh_sizeof_plt (info)
+			    - 1 + 3) * 4));
+
+#ifdef GOT_BIAS
+	  relocation -= GOT_BIAS;
+#endif
+
+	  goto final_link_relocate;
+
+	force_got:
 	case R_SH_GOT32:
+#ifdef INCLUDE_SHMEDIA
+	case R_SH_GOT_LOW16:
+	case R_SH_GOT_MEDLOW16:
+	case R_SH_GOT_MEDHI16:
+	case R_SH_GOT_HI16:
+	case R_SH_GOT10BY4:
+	case R_SH_GOT10BY8:
+#endif
 	  /* Relocation is to the entry for this symbol in the global
 	     offset table.  */
 	  if (sgot == NULL)
@@ -3397,6 +4541,15 @@ sh_elf_relocate_section (output_bfd, inf
 	      bfd_vma off;
 
 	      off = h->got.offset;
+#ifdef INCLUDE_SHMEDIA
+	      if (seen_stt_datalabel)
+		{
+		  struct elf_sh_link_hash_entry *hsh;
+
+		  hsh = (struct elf_sh_link_hash_entry *)h;
+		  off = hsh->datalabel_got_offset;
+		}
+#endif
 	      BFD_ASSERT (off != (bfd_vma) -1);
 
 	      if (! elf_hash_table (info)->dynamic_sections_created
@@ -3424,7 +4577,17 @@ sh_elf_relocate_section (output_bfd, inf
 		    {
 		      bfd_put_32 (output_bfd, relocation,
 				  sgot->contents + off);
-		      h->got.offset |= 1;
+#ifdef INCLUDE_SHMEDIA
+		      if (seen_stt_datalabel)
+			{
+			  struct elf_sh_link_hash_entry *hsh;
+
+			  hsh = (struct elf_sh_link_hash_entry *)h;
+			  hsh->datalabel_got_offset |= 1;
+			}
+		      else
+#endif
+			h->got.offset |= 1;
 		    }
 		}
 
@@ -3434,10 +4597,27 @@ sh_elf_relocate_section (output_bfd, inf
 	    {
 	      bfd_vma off;
 
+#ifdef INCLUDE_SHMEDIA
+	      if (rel->r_addend)
+		{
+		  BFD_ASSERT (local_got_offsets != NULL
+			      && (local_got_offsets[symtab_hdr->sh_info
+						    + r_symndx]
+				  != (bfd_vma) -1));
+
+		  off = local_got_offsets[symtab_hdr->sh_info
+					  + r_symndx];
+		}
+	      else
+		{
+#endif
 	      BFD_ASSERT (local_got_offsets != NULL
 			  && local_got_offsets[r_symndx] != (bfd_vma) -1);
 
 	      off = local_got_offsets[r_symndx];
+#ifdef INCLUDE_SHMEDIA
+		}
+#endif
 
 	      /* The offset must always be a multiple of 4.  We use
 		 the least significant bit to record whether we have
@@ -3468,15 +4648,30 @@ sh_elf_relocate_section (output_bfd, inf
 		      ++srelgot->reloc_count;
 		    }
 
-		  local_got_offsets[r_symndx] |= 1;
+#ifdef INCLUDE_SHMEDIA
+		  if (rel->r_addend)
+		    local_got_offsets[symtab_hdr->sh_info + r_symndx] |= 1;
+		  else
+#endif
+		    local_got_offsets[r_symndx] |= 1;
 		}
 
 	      relocation = sgot->output_offset + off;
 	    }
 
+#ifdef GOT_BIAS
+ 	  relocation -= GOT_BIAS;
+#endif
+
 	  goto final_link_relocate;
 
 	case R_SH_GOTOFF:
+#ifdef INCLUDE_SHMEDIA
+	case R_SH_GOTOFF_LOW16:
+	case R_SH_GOTOFF_MEDLOW16:
+	case R_SH_GOTOFF_MEDHI16:
+	case R_SH_GOTOFF_HI16:
+#endif
 	  /* Relocation is relative to the start of the global offset
 	     table.  */
 
@@ -3493,9 +4688,21 @@ sh_elf_relocate_section (output_bfd, inf
 	     calculation.  */
 	  relocation -= sgot->output_section->vma;
 
+#ifdef GOT_BIAS
+	  relocation -= GOT_BIAS;
+#endif
+
+	  addend = rel->r_addend;
+
 	  goto final_link_relocate;
 
 	case R_SH_GOTPC:
+#ifdef INCLUDE_SHMEDIA
+	case R_SH_GOTPC_LOW16:
+	case R_SH_GOTPC_MEDLOW16:
+	case R_SH_GOTPC_MEDHI16:
+	case R_SH_GOTPC_HI16:
+#endif
 	  /* Use global offset table as symbol value.  */
 
 	  if (sgot == NULL)
@@ -3506,9 +4713,21 @@ sh_elf_relocate_section (output_bfd, inf
 
 	  relocation = sgot->output_section->vma;
 
+#ifdef GOT_BIAS
+	  relocation += GOT_BIAS;
+#endif
+
+	  addend = rel->r_addend;
+
 	  goto final_link_relocate;
 
 	case R_SH_PLT32:
+#ifdef INCLUDE_SHMEDIA
+	case R_SH_PLT_LOW16:
+	case R_SH_PLT_MEDLOW16:
+	case R_SH_PLT_MEDHI16:
+	case R_SH_PLT_HI16:
+#endif
 	  /* Relocation is to the entry for this symbol in the
 	     procedure linkage table.  */
 
@@ -3539,6 +4758,12 @@ sh_elf_relocate_section (output_bfd, inf
 			+ splt->output_offset
 			+ h->plt.offset);
 
+#ifdef INCLUDE_SHMEDIA
+	  relocation++;
+#endif
+
+	  addend = rel->r_addend;
+
 	  goto final_link_relocate;
 
 	case R_SH_LOOP_START:
@@ -3851,9 +5076,32 @@ sh_elf_check_relocs (abfd, info, sec, re
 	{
 	  switch (ELF32_R_TYPE (rel->r_info))
 	    {
+	    case R_SH_GOTPLT32:
 	    case R_SH_GOT32:
 	    case R_SH_GOTOFF:
 	    case R_SH_GOTPC:
+#ifdef INCLUDE_SHMEDIA
+	    case R_SH_GOTPLT_LOW16:
+	    case R_SH_GOTPLT_MEDLOW16:
+	    case R_SH_GOTPLT_MEDHI16:
+	    case R_SH_GOTPLT_HI16:
+	    case R_SH_GOTPLT10BY4:
+	    case R_SH_GOTPLT10BY8:
+	    case R_SH_GOT_LOW16:
+	    case R_SH_GOT_MEDLOW16:
+	    case R_SH_GOT_MEDHI16:
+	    case R_SH_GOT_HI16:
+	    case R_SH_GOT10BY4:
+	    case R_SH_GOT10BY8:
+	    case R_SH_GOTOFF_LOW16:
+	    case R_SH_GOTOFF_MEDLOW16:
+	    case R_SH_GOTOFF_MEDHI16:
+	    case R_SH_GOTOFF_HI16:
+	    case R_SH_GOTPC_LOW16:
+	    case R_SH_GOTPC_MEDLOW16:
+	    case R_SH_GOTPC_MEDHI16:
+	    case R_SH_GOTPC_HI16:
+#endif
 	      elf_hash_table (info)->dynobj = dynobj = abfd;
 	      if (! _bfd_elf_create_got_section (dynobj, info))
 		return false;
@@ -3880,7 +5128,16 @@ sh_elf_check_relocs (abfd, info, sec, re
 	    return false;
 	  break;
 
+	force_got:
 	case R_SH_GOT32:
+#ifdef INCLUDE_SHMEDIA
+	case R_SH_GOT_LOW16:
+	case R_SH_GOT_MEDLOW16:
+	case R_SH_GOT_MEDHI16:
+	case R_SH_GOT_HI16:
+	case R_SH_GOT10BY4:
+	case R_SH_GOT10BY8:
+#endif
 	  /* This symbol requires a global offset table entry.  */
 
 	  if (sgot == NULL)
@@ -3911,12 +5168,30 @@ sh_elf_check_relocs (abfd, info, sec, re
 
 	  if (h != NULL)
 	    {
+#ifdef INCLUDE_SHMEDIA
+	      if (h->type == STT_DATALABEL)
+		{
+		  struct elf_sh_link_hash_entry *hsh;
+
+		  h = (struct elf_link_hash_entry *) h->root.u.i.link;
+		  hsh = (struct elf_sh_link_hash_entry *)h;
+		  if (hsh->datalabel_got_offset != (bfd_vma) -1)
+		    break;
+
+		  hsh->datalabel_got_offset = sgot->_raw_size;
+		}
+	      else
+		{
+#endif
 	      if (h->got.offset != (bfd_vma) -1)
 		{
 		  /* We have already allocated space in the .got.  */
 		  break;
 		}
 	      h->got.offset = sgot->_raw_size;
+#ifdef INCLUDE_SHMEDIA
+		}
+#endif
 
 	      /* Make sure this symbol is output as a dynamic symbol.  */
 	      if (h->dynindx == -1)
@@ -3938,19 +5213,46 @@ sh_elf_check_relocs (abfd, info, sec, re
 
 		  size = symtab_hdr->sh_info;
 		  size *= sizeof (bfd_vma);
+#ifdef INCLUDE_SHMEDIA
+		  /* Reserve space for both the datalabel and
+		     codelabel local GOT offsets.  */
+		  size *= 2;
+#endif
 		  local_got_offsets = (bfd_vma *) bfd_alloc (abfd, size);
 		  if (local_got_offsets == NULL)
 		    return false;
 		  elf_local_got_offsets (abfd) = local_got_offsets;
 		  for (i = 0; i < symtab_hdr->sh_info; i++)
 		    local_got_offsets[i] = (bfd_vma) -1;
+#ifdef INCLUDE_SHMEDIA
+		  for (; i < 2 * symtab_hdr->sh_info; i++)
+		    local_got_offsets[i] = (bfd_vma) -1;
+#endif
 		}
+#ifdef INCLUDE_SHMEDIA
+	      if ((rel->r_addend & 1) != 0)
+		{
+		  if (local_got_offsets[symtab_hdr->sh_info
+					+ r_symndx] != (bfd_vma) -1)
+		    {
+		      /* We have already allocated space in the .got.  */
+		      break;
+		    }
+		  local_got_offsets[symtab_hdr->sh_info
+				    + r_symndx] = sgot->_raw_size;
+		}
+	      else
+		{
+#endif
 	      if (local_got_offsets[r_symndx] != (bfd_vma) -1)
 		{
 		  /* We have already allocated space in the .got.  */
 		  break;
 		}
 	      local_got_offsets[r_symndx] = sgot->_raw_size;
+#ifdef INCLUDE_SHMEDIA
+		}
+#endif
 
 	      if (info->shared)
 		{
@@ -3965,7 +5267,45 @@ sh_elf_check_relocs (abfd, info, sec, re
 
 	  break;
 
+	case R_SH_GOTPLT32:
+#ifdef INCLUDE_SHMEDIA
+	case R_SH_GOTPLT_LOW16:
+	case R_SH_GOTPLT_MEDLOW16:
+	case R_SH_GOTPLT_MEDHI16:
+	case R_SH_GOTPLT_HI16:
+	case R_SH_GOTPLT10BY4:
+	case R_SH_GOTPLT10BY8:
+#endif
+	  /* If this is a local symbol, we resolve it directly without
+	     creating a procedure linkage table entry.  */
+
+	  if (h == NULL
+	      || ELF_ST_VISIBILITY (h->other) == STV_INTERNAL
+	      || ELF_ST_VISIBILITY (h->other) == STV_HIDDEN
+	      || ! info->shared
+	      || info->symbolic
+	      || h->dynindx == -1
+	      || h->got.offset != (bfd_vma) -1)
+	    goto force_got;
+
+	  /* Make sure this symbol is output as a dynamic symbol.  */
+	  if (h->dynindx == -1)
+	    {
+	      if (! bfd_elf32_link_record_dynamic_symbol (info, h))
+		return false;
+	    }
+
+	  h->elf_link_hash_flags |= ELF_LINK_HASH_NEEDS_PLT;
+
+	  break;
+
 	case R_SH_PLT32:
+#ifdef INCLUDE_SHMEDIA
+	case R_SH_PLT_LOW16:
+	case R_SH_PLT_MEDLOW16:
+	case R_SH_PLT_MEDHI16:
+	case R_SH_PLT_HI16:
+#endif
 	  /* This symbol requires a procedure linkage table entry.  We
 	     actually build the entry in adjust_dynamic_symbol,
 	     because this might be a case of linking PIC code which is
@@ -4093,6 +5433,7 @@ sh_elf_check_relocs (abfd, info, sec, re
   return true;
 }
 
+#ifndef sh_elf_set_mach_from_flags
 static boolean
 sh_elf_set_mach_from_flags (abfd)
      bfd *abfd;
@@ -4128,7 +5469,9 @@ sh_elf_set_mach_from_flags (abfd)
     }
   return true;
 }
+#endif /* not sh_elf_set_mach_from_flags */
 
+#ifndef sh_elf_set_private_flags
 /* Function to keep SH specific file flags.  */
 
 static boolean
@@ -4143,7 +5486,9 @@ sh_elf_set_private_flags (abfd, flags)
   elf_flags_init (abfd) = true;
   return sh_elf_set_mach_from_flags (abfd);
 }
+#endif /* not sh_elf_set_private_flags */
 
+#ifndef sh_elf_copy_private_data
 /* Copy backend specific data from one object module to another */
 
 static boolean
@@ -4157,7 +5502,9 @@ sh_elf_copy_private_data (ibfd, obfd)
 
   return sh_elf_set_private_flags (obfd, elf_elfheader (ibfd)->e_flags);
 }
+#endif /* not sh_elf_copy_private_data */
 
+#ifndef sh_elf_merge_private_data
 /* This routine checks for linking big and little endian objects
    together, and for linking sh-dsp with sh3e / sh4 objects.  */
 
@@ -4198,6 +5545,7 @@ sh_elf_merge_private_data (ibfd, obfd)
 
   return sh_elf_set_mach_from_flags (obfd);
 }
+#endif /* not sh_elf_merge_private_data */
 
 /* Finish up dynamic symbol handling.  We set the contents of various
    dynamic sections here.  */
@@ -4244,6 +5592,10 @@ sh_elf_finish_dynamic_symbol (output_bfd
 	 The first three are reserved.  */
       got_offset = (plt_index + 3) * 4;
 
+#ifdef GOT_BIAS
+      got_offset -= GOT_BIAS;
+#endif
+
       /* Fill in the entry in the procedure linkage table.  */
       if (! info->shared)
 	{
@@ -4254,6 +5606,19 @@ sh_elf_finish_dynamic_symbol (output_bfd
 	    }
 	  memcpy (splt->contents + h->plt.offset, elf_sh_plt_entry,
 		  elf_sh_sizeof_plt (info));
+#ifdef INCLUDE_SHMEDIA
+	  movi_shori_putval (output_bfd,
+			     (sgot->output_section->vma
+			      + sgot->output_offset
+			      + got_offset),
+			     (splt->contents + h->plt.offset
+			      + elf_sh_plt_symbol_offset (info)));
+
+	  movi_shori_putval (output_bfd,
+			     (splt->output_section->vma + splt->output_offset),
+			     (splt->contents + h->plt.offset
+			      + elf_sh_plt_plt0_offset (info)));
+#else
 	  bfd_put_32 (output_bfd,
 		      (sgot->output_section->vma
 		       + sgot->output_offset
@@ -4265,6 +5630,7 @@ sh_elf_finish_dynamic_symbol (output_bfd
 		      (splt->output_section->vma + splt->output_offset),
 		      (splt->contents + h->plt.offset
 		       + elf_sh_plt_plt0_offset (info)));
+#endif
 	}
       else
 	{
@@ -4276,14 +5642,31 @@ sh_elf_finish_dynamic_symbol (output_bfd
 	    }
 	  memcpy (splt->contents + h->plt.offset, elf_sh_pic_plt_entry,
 		  elf_sh_sizeof_plt (info));
+#ifdef INCLUDE_SHMEDIA
+	  movi_shori_putval (output_bfd, got_offset,
+			     (splt->contents + h->plt.offset
+			      + elf_sh_plt_symbol_offset (info)));
+#else
 	  bfd_put_32 (output_bfd, got_offset,
 		      (splt->contents + h->plt.offset
 		       + elf_sh_plt_symbol_offset (info)));
+#endif
 	}
 
+#ifdef GOT_BIAS
+      got_offset += GOT_BIAS;
+#endif
+
+#ifdef INCLUDE_SHMEDIA
+      movi_shori_putval (output_bfd,
+			 plt_index * sizeof (Elf32_External_Rela),
+			 (splt->contents + h->plt.offset
+			  + elf_sh_plt_reloc_offset (info)));
+#else
       bfd_put_32 (output_bfd, plt_index * sizeof (Elf32_External_Rela),
 		  (splt->contents + h->plt.offset
 		   + elf_sh_plt_reloc_offset (info)));
+#endif
 
       /* Fill in the entry in the global offset table.  */
       bfd_put_32 (output_bfd,
@@ -4299,6 +5682,9 @@ sh_elf_finish_dynamic_symbol (output_bfd
 		      + got_offset);
       rel.r_info = ELF32_R_INFO (h->dynindx, R_SH_JMP_SLOT);
       rel.r_addend = 0;
+#ifdef GOT_BIAS
+      rel.r_addend = GOT_BIAS;
+#endif
       bfd_elf32_swap_reloca_out (output_bfd, &rel,
 				((Elf32_External_Rela *) srel->contents
 				 + plt_index));
@@ -4498,12 +5884,20 @@ sh_elf_finish_dynamic_sections (output_b
 				       elf_sh_plt0_entry_le);
 		}
 	      memcpy (splt->contents, elf_sh_plt0_entry, PLT_ENTRY_SIZE);
+#ifdef INCLUDE_SHMEDIA
+	      movi_shori_putval (output_bfd,
+				 sgot->output_section->vma
+				 + sgot->output_offset,
+				 splt->contents
+				 + elf_sh_plt0_gotplt_offset (info));
+#else
 	      bfd_put_32 (output_bfd,
 			  sgot->output_section->vma + sgot->output_offset + 4,
 			  splt->contents + elf_sh_plt0_gotid_offset (info));
 	      bfd_put_32 (output_bfd,
 			  sgot->output_section->vma + sgot->output_offset + 8,
 			  splt->contents + elf_sh_plt0_linker_offset (info));
+#endif
 	    }
 
 	  /* UnixWare sets the entsize of .plt to 4, although that doesn't
Index: bfd/elf32-sh64.c
===================================================================
RCS file: bfd/elf32-sh64.c
diff -N bfd/elf32-sh64.c
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ bfd/elf32-sh64.c 2 Feb 2002 04:00:28 -0000
@@ -0,0 +1,983 @@
+/* Hitachi SH64-specific support for 32-bit ELF
+   Copyright (C) 2000, 2001, 2002 Free Software Foundation, Inc.
+
+   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 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 02111-1307, USA.  */
+
+#define SH64_ELF
+
+#include "bfd.h"
+#include "sysdep.h"
+#include "elf-bfd.h"
+#include "../opcodes/sh64-opc.h"
+
+/* Add a suffix for datalabel indirection symbols.  It must not match any
+   other symbols; user symbols with or without version or other
+   decoration.  It must only be used internally and not emitted by any
+   means.  */
+#define DATALABEL_SUFFIX " DL"
+
+/* Used to hold data for function called through bfd_map_over_sections.  */
+struct sh64_find_section_vma_data
+ {
+   asection *section;
+   bfd_vma addr;
+ };
+
+static boolean sh64_elf_copy_private_data PARAMS ((bfd *, bfd *));
+static boolean sh64_elf_merge_private_data PARAMS ((bfd *, bfd *));
+static boolean sh64_elf_fake_sections PARAMS ((bfd *, Elf_Internal_Shdr *,
+					      asection *));
+static boolean sh64_elf_set_private_flags PARAMS ((bfd *, flagword));
+static boolean sh64_elf_set_mach_from_flags PARAMS ((bfd *));
+static boolean shmedia_prepare_reloc
+  PARAMS ((struct bfd_link_info *, bfd *, asection *,
+	   bfd_byte *, const Elf_Internal_Rela *, bfd_vma *));
+static int sh64_elf_get_symbol_type PARAMS ((Elf_Internal_Sym *, int));
+static boolean sh64_elf_add_symbol_hook
+  PARAMS ((bfd *, struct bfd_link_info *, const Elf_Internal_Sym *,
+	   const char **, flagword *, asection **, bfd_vma *));
+static boolean sh64_elf_link_output_symbol_hook
+  PARAMS ((bfd *, struct bfd_link_info *, const char *, Elf_Internal_Sym *,
+	   asection *));
+static boolean sh64_backend_section_from_shdr
+  PARAMS ((bfd *, Elf_Internal_Shdr *, char *));
+static void sh64_elf_final_write_processing PARAMS ((bfd *, boolean));
+static boolean sh64_bfd_elf_copy_private_section_data
+  PARAMS ((bfd *, asection *, bfd *, asection *));
+
+/* Let elf32-sh.c handle the "bfd_" definitions, so we only have to
+   intrude with an #ifndef around the function definition.  */
+#define sh_elf_copy_private_data		sh64_elf_copy_private_data
+#define sh_elf_merge_private_data		sh64_elf_merge_private_data
+#define sh_elf_set_private_flags		sh64_elf_set_private_flags
+/* Typo in elf32-sh.c (and unlinear name).  */
+#define bfd_elf32_bfd_set_private_flags		sh64_elf_set_private_flags
+#define sh_elf_set_mach_from_flags		sh64_elf_set_mach_from_flags
+
+#define elf_backend_sign_extend_vma		1
+#define elf_backend_fake_sections		sh64_elf_fake_sections
+#define elf_backend_get_symbol_type		sh64_elf_get_symbol_type
+#define elf_backend_add_symbol_hook		sh64_elf_add_symbol_hook
+#define elf_backend_link_output_symbol_hook \
+	sh64_elf_link_output_symbol_hook
+#define elf_backend_final_write_processing 	sh64_elf_final_write_processing
+#define elf_backend_section_from_shdr		sh64_backend_section_from_shdr
+
+/* For objcopy, we need to set up sh64_elf_section_data (asection *) from
+   incoming section flags.  This is otherwise done in sh64elf.em when
+   linking or tc-sh64.c when assembling.  */
+#define bfd_elf32_bfd_copy_private_section_data \
+	sh64_bfd_elf_copy_private_section_data
+
+/* This COFF-only function (only compiled with COFF support, making
+   ELF-only chains problematic) returns true early for SH4, so let's just
+   define it true here.  */
+#define _bfd_sh_align_load_span(a,b,c,d,e,f,g,h,i,j) true
+
+#ifndef ELF_ARCH
+#define TARGET_BIG_SYM		bfd_elf32_sh64_vec
+#define TARGET_BIG_NAME		"elf32-sh64"
+#define TARGET_LITTLE_SYM	bfd_elf32_sh64l_vec
+#define TARGET_LITTLE_NAME	"elf32-sh64l"
+#define ELF_ARCH		bfd_arch_sh
+#define ELF_MACHINE_CODE	EM_SH
+#define ELF_MAXPAGESIZE		128
+
+#define elf_symbol_leading_char '_'
+#endif /* ELF_ARCH */
+
+#define GOT_BIAS (-((long)-32768))
+#define INCLUDE_SHMEDIA
+#include "elf32-sh.c"
+
+/* The type sh64_elf_crange is defined in elf/sh.h which is included in
+   elf32-sh.c, hence these prototypes located after including it.  */
+static int crange_qsort_cmpb PARAMS ((const void *, const void *));
+static int crange_qsort_cmpl PARAMS ((const void *, const void *));
+static int crange_bsearch_cmpb PARAMS ((const void *, const void *));
+static int crange_bsearch_cmpl PARAMS ((const void *, const void *));
+static boolean sh64_address_in_cranges
+  PARAMS ((asection *cranges, bfd_vma, sh64_elf_crange *));
+
+/* Set the SHF_SH5_ISA32 flag for ISA SHmedia code sections, and pass
+   through SHT_SH5_CR_SORTED on a sorted .cranges section.  */
+
+boolean
+sh64_elf_fake_sections (output_bfd, elf_section_hdr, asect)
+     bfd *output_bfd ATTRIBUTE_UNUSED;
+     Elf_Internal_Shdr *elf_section_hdr;
+     asection *asect;
+{
+  if (sh64_elf_section_data (asect) != NULL)
+    elf_section_hdr->sh_flags
+      |= sh64_elf_section_data (asect)->contents_flags;
+
+  /* If this section has the SEC_SORT_ENTRIES flag set, it is a sorted
+     .cranges section passing through objcopy.  */
+  if ((bfd_get_section_flags (output_bfd, asect) & SEC_SORT_ENTRIES) != 0
+      && strcmp (bfd_get_section_name (output_bfd, asect),
+		 SH64_CRANGES_SECTION_NAME) == 0)
+    elf_section_hdr->sh_type = SHT_SH5_CR_SORTED;
+
+  return true;
+}
+
+static boolean
+sh64_elf_set_mach_from_flags (abfd)
+     bfd *abfd;
+{
+  flagword flags = elf_elfheader (abfd)->e_flags;
+  asection *cranges;
+
+  switch (flags & EF_SH_MACH_MASK)
+    {
+    case EF_SH5:
+      /* These are fit to execute on SH5.  Just one but keep the switch
+	 construct to make additions easy.  */
+      bfd_default_set_arch_mach (abfd, bfd_arch_sh, bfd_mach_sh5);
+      break;
+
+    default:
+      bfd_set_error (bfd_error_wrong_format);
+      return false;
+    }
+
+  /* We also need to set SEC_DEBUGGING on an incoming .cranges section.
+     We could have used elf_backend_section_flags if it had given us the
+     section name; the bfd_section member in the header argument is not
+     set at the point of the call.  FIXME: Find out whether that is by
+     undocumented design or a bug.  */
+  cranges = bfd_get_section_by_name (abfd, SH64_CRANGES_SECTION_NAME);
+  if (cranges != NULL
+      && ! bfd_set_section_flags (abfd, cranges,
+				  bfd_get_section_flags (abfd, cranges)
+				  | SEC_DEBUGGING))
+    return false;
+
+  return true;
+}
+
+static boolean
+sh64_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;
+
+  BFD_ASSERT (!elf_flags_init (obfd)
+	      || (elf_elfheader (obfd)->e_flags
+		  == elf_elfheader (ibfd)->e_flags));
+
+  elf_elfheader (obfd)->e_flags = elf_elfheader (ibfd)->e_flags;
+  return true;
+}
+
+static boolean
+sh64_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 (bfd_get_arch_size (ibfd) != bfd_get_arch_size (obfd))
+    {
+      const char *msg;
+
+      if (bfd_get_arch_size (ibfd) == 32
+	  && bfd_get_arch_size (obfd) == 64)
+	msg = _("%s: compiled as 32-bit object and %s is 64-bit");
+      else if (bfd_get_arch_size (ibfd) == 64
+	       && bfd_get_arch_size (obfd) == 32)
+	msg = _("%s: compiled as 64-bit object and %s is 32-bit");
+      else
+	msg = _("%s: object size does not match that of target %s");
+
+      (*_bfd_error_handler) (msg, bfd_get_filename (ibfd),
+			     bfd_get_filename (obfd));
+      bfd_set_error (bfd_error_wrong_format);
+      return false;
+    }
+
+  old_flags = elf_elfheader (obfd)->e_flags;
+  new_flags = elf_elfheader (ibfd)->e_flags;
+  if (! elf_flags_init (obfd))
+    {
+      /* This happens when ld starts out with a 'blank' output file.  */
+      elf_flags_init (obfd) = true;
+      elf_elfheader (obfd)->e_flags = old_flags = new_flags;
+    }
+  /* We don't allow linking in non-SH64 code.  */
+  else if ((new_flags & EF_SH_MACH_MASK) != EF_SH5)
+    {
+      (*_bfd_error_handler)
+	("%s: uses non-SH64 instructions while previous modules use SH64 instructions",
+	 bfd_get_filename (ibfd));
+      bfd_set_error (bfd_error_bad_value);
+      return false;
+    }
+
+  /* I can't think of anything sane other than old_flags being EF_SH5 and
+     that we need to preserve that.  */
+  elf_elfheader (obfd)->e_flags = old_flags;
+  return sh64_elf_set_mach_from_flags (obfd);
+}
+
+/* Handle a SH64-specific section when reading an object file.  This
+   is called when elfcode.h finds a section with an unknown type.
+
+   We only recognize SHT_SH5_CR_SORTED, on the .cranges section.  */
+
+boolean
+sh64_backend_section_from_shdr (abfd, hdr, name)
+     bfd *abfd;
+     Elf_Internal_Shdr *hdr;
+     char *name;
+{
+  flagword flags = 0;
+
+  /* We do like MIPS with a bit switch for recognized types, and returning
+     false for a recognized section type with an unexpected name.  Right
+     now we only have one recognized type, but that might change.  */
+  switch (hdr->sh_type)
+    {
+    case SHT_SH5_CR_SORTED:
+      if (strcmp (name, SH64_CRANGES_SECTION_NAME) != 0)
+	return false;
+
+      /* We set the SEC_SORT_ENTRIES flag so it can be passed on to
+	 sh64_elf_fake_sections, keeping SHT_SH5_CR_SORTED if this object
+	 passes through objcopy.  Perhaps it is brittle; the flag can
+	 suddenly be used by other BFD parts, but it seems not really used
+	 anywhere at the moment.  */
+      flags = SEC_DEBUGGING | SEC_SORT_ENTRIES;
+      break;
+
+    default:
+      return false;
+    }
+
+  if (! _bfd_elf_make_section_from_shdr (abfd, hdr, name))
+    return false;
+
+  if (flags
+      && ! bfd_set_section_flags (abfd, hdr->bfd_section,
+				  bfd_get_section_flags (abfd,
+							 hdr->bfd_section)
+				  | flags))
+    return false;
+
+  return true;
+}
+
+/* In contrast to sh64_backend_section_from_shdr, this is called for all
+   sections, but only when copying sections, not when linking or
+   assembling.  We need to set up the sh64_elf_section_data (asection *)
+   structure for the SH64 ELF section flags to be copied correctly.  */
+
+boolean
+sh64_bfd_elf_copy_private_section_data (ibfd, isec, obfd, osec)
+     bfd *ibfd;
+     asection *isec;
+     bfd *obfd;
+     asection *osec;
+{
+  struct sh64_section_data *sh64_sec_data;
+
+  if (ibfd->xvec->flavour != bfd_target_elf_flavour
+      || obfd->xvec->flavour != bfd_target_elf_flavour)
+    return true;
+
+  if (! _bfd_elf_copy_private_section_data (ibfd, isec, obfd, osec))
+    return false;
+
+  sh64_sec_data = sh64_elf_section_data (isec);
+  if (sh64_sec_data == NULL)
+    {
+      sh64_sec_data = bfd_zmalloc (sizeof (struct sh64_section_data));
+
+      if (sh64_sec_data == NULL)
+	return false;
+
+      sh64_sec_data->contents_flags
+	= (elf_section_data (isec)->this_hdr.sh_flags
+	   & (SHF_SH5_ISA32 | SHF_SH5_ISA32_MIXED));
+
+      sh64_elf_section_data (osec) = sh64_sec_data;
+    }
+
+  return true;
+}
+
+/* Function to keep SH64 specific file flags.  */
+
+static boolean
+sh64_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 sh64_elf_set_mach_from_flags (abfd);
+}
+
+/* Called when writing out an object file to decide the type of a symbol.  */
+
+static int
+sh64_elf_get_symbol_type (elf_sym, type)
+     Elf_Internal_Sym * elf_sym;
+     int type;
+{
+  if (ELF_ST_TYPE (elf_sym->st_info) == STT_DATALABEL)
+    return STT_DATALABEL;
+
+  return type;
+}
+
+/* Hook called by the linker routine which adds symbols from an object
+   file.  We must make indirect symbols for undefined symbols marked with
+   STT_DATALABEL, so relocations passing them will pick up that attribute
+   and neutralize STO_SH5_ISA32 found on the symbol definition.
+
+   There is a problem, though: We want to fill in the hash-table entry for
+   this symbol and signal to the caller that no further processing is
+   needed.  But we don't have the index for this hash-table entry.  We
+   rely here on that the current entry is the first hash-entry with NULL,
+   which seems brittle.  Also, iterating over the hash-table to find that
+   entry is a linear operation on the number of symbols in this input
+   file, and this function should take constant time, so that's not good
+   too.  Only comfort is that DataLabel references should only be found in
+   hand-written assembly code and thus be rare.  FIXME: Talk maintainers
+   into adding an option to elf_add_symbol_hook (preferably) for the index
+   or the hash entry, alternatively adding the index to Elf_Internal_Sym
+   (not so good).  */
+
+static boolean
+sh64_elf_add_symbol_hook (abfd, info, sym, namep, flagsp, secp, valp)
+     bfd *abfd;
+     struct bfd_link_info *info;
+     const Elf_Internal_Sym *sym;
+     const char **namep;
+     flagword *flagsp ATTRIBUTE_UNUSED;
+     asection **secp;
+     bfd_vma *valp;
+{
+  /* We want to do this for relocatable as well as final linking.  */
+  if (ELF_ST_TYPE (sym->st_info) == STT_DATALABEL)
+    {
+      struct elf_link_hash_entry *h;
+
+      /* For relocateable links, we register the DataLabel sym in its own
+	 right, and tweak the name when it's output.  Otherwise, we make
+	 an indirect symbol of it.  */
+      flagword flags
+	= info->relocateable || info->emitrelocations
+	? BSF_GLOBAL : BSF_GLOBAL | BSF_INDIRECT;
+
+      char *dl_name
+	= bfd_malloc (strlen (*namep) + sizeof (DATALABEL_SUFFIX));
+      struct elf_link_hash_entry ** sym_hash = elf_sym_hashes (abfd);
+
+      BFD_ASSERT (sym_hash != NULL);
+
+      /* Allocation may fail.  */
+      if (dl_name == NULL)
+	return false;
+
+      strcpy (dl_name, *namep);
+      strcat (dl_name, DATALABEL_SUFFIX);
+
+      h = (struct elf_link_hash_entry *)
+	bfd_link_hash_lookup (info->hash, dl_name, false, false, false);
+
+      if (h == NULL)
+	{
+	  /* No previous datalabel symbol.  Make one.  */
+	  if (! _bfd_generic_link_add_one_symbol (info, abfd, dl_name,
+						  flags, *secp, *valp,
+						  *namep, false,
+						  get_elf_backend_data (abfd)->collect,
+						  (struct bfd_link_hash_entry **) &h))
+	    {
+	      free (dl_name);
+	      return false;
+	    }
+
+	  h->elf_link_hash_flags &=~ ELF_LINK_NON_ELF;
+	  h->type = STT_DATALABEL;
+	}
+      else
+	/* If a new symbol was created, it holds the allocated name.
+	   Otherwise, we don't need it anymore and should deallocate it.  */
+	free (dl_name);
+
+      if (h->type != STT_DATALABEL
+	  || ((info->relocateable || info->emitrelocations)
+	      && h->root.type != bfd_link_hash_undefined)
+	  || (! info->relocateable && !info->emitrelocations
+	      && h->root.type != bfd_link_hash_indirect))
+	{
+	  /* Make sure we don't get confused on invalid input.  */
+	  (*_bfd_error_handler)
+	    (_("%s: encountered datalabel symbol in input"),
+	     bfd_get_filename (abfd));
+	  bfd_set_error (bfd_error_bad_value);
+	  return false;
+	}
+
+      /* Now find the hash-table slot for this entry and fill it in.  */
+      while (*sym_hash != NULL)
+	sym_hash++;
+      *sym_hash = h;
+
+      /* Signal to caller to skip this symbol - we've handled it.  */
+      *namep = NULL;
+    }
+
+  return true;
+}
+
+/* This hook function is called before the linker writes out a global
+   symbol.  For relocatable links, DataLabel symbols will be present in
+   linker output.  We cut off the special suffix on those symbols, so the
+   right name appears in the output.
+
+   When linking and emitting relocations, there can appear global symbols
+   that are not referenced by relocs, but rather only implicitly through
+   DataLabel references, a relation that is not visible to the linker.
+   Since no stripping of global symbols in done when doing such linking,
+   we don't need to look up and make sure to emit the main symbol for each
+   DataLabel symbol.  */
+
+boolean
+sh64_elf_link_output_symbol_hook (abfd, info, cname, sym, input_sec)
+     bfd *abfd ATTRIBUTE_UNUSED;
+     struct bfd_link_info *info;
+     const char *cname;
+     Elf_Internal_Sym *sym;
+     asection *input_sec ATTRIBUTE_UNUSED;
+{
+  char *name = (char *) cname;
+
+  if (info->relocateable || info->emitrelocations)
+    {
+      if (ELF_ST_TYPE (sym->st_info) == STT_DATALABEL)
+	name[strlen (name) - strlen (DATALABEL_SUFFIX)] = 0;
+    }
+
+  return true;
+}
+
+/* Check a SH64-specific reloc and put the value to relocate to into
+   RELOCATION, ready to pass to _bfd_final_link_relocate.  Return FALSE if
+   bad value, TRUE if ok.  */
+
+static boolean
+shmedia_prepare_reloc (info, abfd, input_section,
+		       contents, rel, relocation)
+     struct bfd_link_info *info;
+     bfd *abfd;
+     asection *input_section;
+     bfd_byte *contents;
+     const Elf_Internal_Rela *rel;
+     bfd_vma *relocation;
+{
+  bfd_vma disp, dropped;
+
+  switch (ELF32_R_TYPE (rel->r_info))
+    {
+    case R_SH_PT_16:
+      /* Check the lowest bit of the destination field.  If it is 1, we
+	 check the ISA type of the destination (i.e. the low bit of the
+	 "relocation" value, and emit an error if the instruction does not
+	 match).  If it is 0, we change a PTA to PTB.  There should never
+	 be a PTB that should change to a PTA; that indicates a toolchain
+	 error; a mismatch with GAS.  */
+      {
+	char *msg = NULL;
+	bfd_vma insn = bfd_get_32 (abfd, contents + rel->r_offset);
+
+	if (insn & (1 << 10))
+	  {
+	    /* Check matching insn and ISA (address of target).  */
+	    if ((insn & SHMEDIA_PTB_BIT) != 0
+		&& ((*relocation + rel->r_addend) & 1) != 0)
+	      msg = _("PTB mismatch: a SHmedia address (bit 0 == 1)");
+	    else if ((insn & SHMEDIA_PTB_BIT) == 0
+		     && ((*relocation + rel->r_addend) & 1) == 0)
+	      msg = _("PTA mismatch: a SHcompact address (bit 0 == 0)");
+
+	    if (msg != NULL
+		&& ! ((*info->callbacks->reloc_dangerous)
+		      (info, msg, abfd, input_section,
+		       rel->r_offset)))
+	      return false;
+	  }
+	else
+	  {
+	    /* We shouldn't get here with a PTB insn and a R_SH_PT_16.  It
+	       means GAS output does not match expectations; a PTA or PTB
+	       expressed as such (or a PT found at assembly to be PTB)
+	       would match the test above, and PT expansion with an
+	       unknown destination (or when relaxing) will get us here.  */
+	    if ((insn & SHMEDIA_PTB_BIT) != 0)
+	      {
+		(*_bfd_error_handler)
+		  (_("%s: GAS error: unexpected PTB insn with R_SH_PT_16"),
+		   bfd_get_filename (input_section->owner));
+		return false;
+	      }
+
+	    /* Change the PTA to a PTB, if destination indicates so.  */
+	    if (((*relocation + rel->r_addend) & 1) == 0)
+	      bfd_put_32 (abfd, insn | SHMEDIA_PTB_BIT,
+			  contents + rel->r_offset);
+	  }
+      }
+
+    case R_SH_SHMEDIA_CODE:
+    case R_SH_DIR5U:
+    case R_SH_DIR6S:
+    case R_SH_DIR6U:
+    case R_SH_DIR10S:
+    case R_SH_DIR10SW:
+    case R_SH_DIR10SL:
+    case R_SH_DIR10SQ:
+    case R_SH_IMMS16:
+    case R_SH_IMMU16:
+    case R_SH_IMM_LOW16:
+    case R_SH_IMM_LOW16_PCREL:
+    case R_SH_IMM_MEDLOW16:
+    case R_SH_IMM_MEDLOW16_PCREL:
+    case R_SH_IMM_MEDHI16:
+    case R_SH_IMM_MEDHI16_PCREL:
+    case R_SH_IMM_HI16:
+    case R_SH_IMM_HI16_PCREL:
+    case R_SH_64:
+    case R_SH_64_PCREL:
+      break;
+
+    default:
+      return false;
+    }
+
+  disp = (*relocation & 0xf);
+  dropped = 0;
+  switch (ELF32_R_TYPE (rel->r_info))
+    {
+    case R_SH_DIR10SW: dropped = disp & 1; break;
+    case R_SH_DIR10SL: dropped = disp & 3; break;
+    case R_SH_DIR10SQ: dropped = disp & 7; break;
+    }
+  if (dropped != 0)
+    {
+      (*_bfd_error_handler)
+	(_("%s: error: unaligned relocation type %d at %08x reloc %08x\n"),
+	 bfd_get_filename (input_section->owner), ELF32_R_TYPE (rel->r_info),
+	 (unsigned)rel->r_offset, (unsigned)relocation);
+      return false;
+    }
+
+  return true;
+}
+
+/* Helper function to locate the section holding a certain address.  This
+   is called via bfd_map_over_sections.  */
+
+static void
+sh64_find_section_for_address (abfd, section, data)
+     bfd *abfd ATTRIBUTE_UNUSED;
+     asection *section;
+     PTR data;
+{
+  bfd_vma vma;
+  bfd_size_type size;
+  struct sh64_find_section_vma_data *fsec_datap
+    = (struct sh64_find_section_vma_data *) data;
+
+  /* Return if already found.  */
+  if (fsec_datap->section)
+    return;
+
+  /* If this section isn't part of the addressable contents, skip it.  */
+  if ((bfd_get_section_flags (abfd, section) & SEC_ALLOC) == 0)
+    return;
+
+  vma = bfd_get_section_vma (abfd, section);
+  if (fsec_datap->addr < vma)
+    return;
+
+  /* FIXME: section->reloc_done isn't set properly; a generic buglet
+     preventing us from using bfd_get_section_size_after_reloc.  */
+  size
+    = section->_cooked_size ? section->_cooked_size : section->_raw_size;
+
+  if (fsec_datap->addr >= vma + size)
+    return;
+
+  fsec_datap->section = section;
+}
+
+/* Make sure to write out the generated entries in the .cranges section
+   when doing partial linking, and set bit 0 on the entry address if it
+   points to SHmedia code and write sorted .cranges entries when writing
+   executables (final linking and objcopy).  */
+
+static void
+sh64_elf_final_write_processing (abfd, linker)
+     bfd *   abfd;
+     boolean linker ATTRIBUTE_UNUSED;
+{
+  bfd_vma ld_generated_cranges_size;
+  asection *cranges
+    = bfd_get_section_by_name (abfd, SH64_CRANGES_SECTION_NAME);
+
+  /* If no new .cranges were added, the generic ELF linker parts will
+     write it all out.  If not, we need to write them out when doing
+     partial linking.  For a final link, we will sort them and write them
+     all out further below.  */
+  if (linker
+      && cranges != NULL
+      && elf_elfheader (abfd)->e_type != ET_EXEC
+      && (ld_generated_cranges_size
+	  = sh64_elf_section_data (cranges)->cranges_growth) != 0)
+    {
+      bfd_vma incoming_cranges_size
+	= ((cranges->_cooked_size != 0
+	    ? cranges->_cooked_size : cranges->_raw_size)
+	   - ld_generated_cranges_size);
+
+      if (! bfd_set_section_contents (abfd, cranges,
+				      cranges->contents
+				      + incoming_cranges_size,
+				      cranges->output_offset
+				      + incoming_cranges_size,
+				      ld_generated_cranges_size))
+	{
+	  bfd_set_error (bfd_error_file_truncated);
+	  (*_bfd_error_handler)
+	    (_("%s: could not write out added .cranges entries"),
+	     bfd_get_filename (abfd));
+	}
+    }
+
+  /* Only set entry address bit 0 and sort .cranges when linking to an
+     executable; never with objcopy or strip.  */
+  if (linker && elf_elfheader (abfd)->e_type == ET_EXEC)
+    {
+      struct sh64_find_section_vma_data fsec_data;
+      sh64_elf_crange dummy;
+
+      /* For a final link, set the low bit of the entry address to
+	 reflect whether or not it is a SHmedia address.
+	 FIXME: Perhaps we shouldn't do this if the entry address was
+	 supplied numerically, but we currently lack the infrastructure to
+	 recognize that: The entry symbol, and info whether it is numeric
+	 or a symbol name is kept private in the linker.  */
+      fsec_data.addr = elf_elfheader (abfd)->e_entry;
+      fsec_data.section = NULL;
+
+      bfd_map_over_sections (abfd, sh64_find_section_for_address,
+			     (PTR) &fsec_data);
+      if (fsec_data.section
+	  && (sh64_get_contents_type (fsec_data.section,
+				      elf_elfheader (abfd)->e_entry,
+				      &dummy) == CRT_SH5_ISA32))
+	elf_elfheader (abfd)->e_entry |= 1;
+
+      /* If we have a .cranges section, sort the entries.  */
+      if (cranges != NULL)
+	{
+	  bfd_size_type cranges_size
+	    = (cranges->_cooked_size != 0
+	       ? cranges->_cooked_size : cranges->_raw_size);
+
+	  /* We know we always have these in memory at this time.  */
+	  BFD_ASSERT (cranges->contents != NULL);
+
+	  /* The .cranges may already have been sorted in the process of
+	     finding out the ISA-type of the entry address.  If not, we do
+	     it here.  */
+	  if (elf_section_data (cranges)->this_hdr.sh_type
+	      != SHT_SH5_CR_SORTED)
+	    {
+	      qsort (cranges->contents, cranges_size / SH64_CRANGE_SIZE,
+		     SH64_CRANGE_SIZE,
+		     bfd_big_endian (cranges->owner)
+		     ? crange_qsort_cmpb : crange_qsort_cmpl);
+	      elf_section_data (cranges)->this_hdr.sh_type
+		= SHT_SH5_CR_SORTED;
+	    }
+
+	  /* We need to write it out in whole as sorted.  */
+	  if (! bfd_set_section_contents (abfd, cranges,
+					  cranges->contents,
+					  cranges->output_offset,
+					  cranges_size))
+	    {
+	      bfd_set_error (bfd_error_file_truncated);
+	      (*_bfd_error_handler)
+		(_("%s: could not write out sorted .cranges entries"),
+		 bfd_get_filename (abfd));
+	    }
+	}
+    }
+}
+
+/* Ordering functions of a crange, for the qsort and bsearch calls and for
+   different endianness.  */
+
+static int
+crange_qsort_cmpb (p1, p2)
+     const PTR p1;
+     const PTR p2;
+{
+  bfd_vma a1 = bfd_getb32 (p1);
+  bfd_vma a2 = bfd_getb32 (p2);
+
+  /* Preserve order if there's ambiguous contents.  */
+  if (a1 == a2)
+    return (char *) p1 - (char *) p2;
+
+  return a1 - a2;
+}
+
+static int
+crange_qsort_cmpl (p1, p2)
+     const PTR p1;
+     const PTR p2;
+{
+  bfd_vma a1 = (bfd_vma) bfd_getl32 (p1);
+  bfd_vma a2 = (bfd_vma) bfd_getl32 (p2);
+
+  /* Preserve order if there's ambiguous contents.  */
+  if (a1 == a2)
+    return (char *) p1 - (char *) p2;
+
+  return a1 - a2;
+}
+
+static int
+crange_bsearch_cmpb (p1, p2)
+     const PTR p1;
+     const PTR p2;
+{
+  bfd_vma a1 = *(bfd_vma *) p1;
+  bfd_vma a2 = (bfd_vma) bfd_getb32 (p2);
+  bfd_size_type size
+    = (bfd_size_type) bfd_getb32 (SH64_CRANGE_CR_SIZE_OFFSET + (char *) p2);
+
+  if (a1 >= a2 + size)
+    return 1;
+  if (a1 < a2)
+    return -1;
+  return 0;
+}
+
+static int
+crange_bsearch_cmpl (p1, p2)
+     const PTR p1;
+     const PTR p2;
+{
+  bfd_vma a1 = *(bfd_vma *) p1;
+  bfd_vma a2 = (bfd_vma) bfd_getl32 (p2);
+  bfd_size_type size
+    = (bfd_size_type) bfd_getl32 (SH64_CRANGE_CR_SIZE_OFFSET + (char *) p2);
+
+  if (a1 >= a2 + size)
+    return 1;
+  if (a1 < a2)
+    return -1;
+  return 0;
+}
+
+/* Check whether a specific address is specified within a .cranges
+   section.  Return FALSE if not found, and TRUE if found, and the region
+   filled into RANGEP if non-NULL.  */
+
+static boolean
+sh64_address_in_cranges (cranges, addr, rangep)
+     asection *cranges;
+     bfd_vma addr;
+     sh64_elf_crange *rangep;
+{
+  bfd_byte *cranges_contents;
+  bfd_byte *found_rangep;
+  bfd_size_type cranges_size = bfd_section_size (cranges->owner, cranges);
+
+  /* If the size is not a multiple of the cranges entry size, then
+     something is badly wrong.  */
+  if ((cranges_size % SH64_CRANGE_SIZE) != 0)
+    return false;
+
+  /* If this section has relocations, then we can't do anything sane.  */
+  if (bfd_get_section_flags (cranges->owner, cranges) & SEC_RELOC)
+    return false;
+
+  /* Has some kind soul (or previous call) left processed, sorted contents
+     for us?  */
+  if ((bfd_get_section_flags (cranges->owner, cranges) & SEC_IN_MEMORY)
+      && elf_section_data (cranges)->this_hdr.sh_type == SHT_SH5_CR_SORTED)
+    cranges_contents = cranges->contents;
+  else
+    {
+      cranges_contents
+	= bfd_malloc (cranges->_cooked_size == 0
+		      ? cranges->_cooked_size : cranges->_raw_size);
+      if (cranges_contents == NULL)
+	return false;
+
+      if (! bfd_get_section_contents (cranges->owner, cranges,
+				      cranges_contents, (file_ptr) 0,
+				      cranges_size))
+	goto error_return;
+
+      /* Is it sorted?  */
+      if (elf_section_data (cranges)->this_hdr.sh_type
+	  != SHT_SH5_CR_SORTED)
+	/* Nope.  Lets sort it.  */
+	qsort (cranges_contents, cranges_size / SH64_CRANGE_SIZE,
+	       SH64_CRANGE_SIZE,
+	       bfd_big_endian (cranges->owner)
+	       ? crange_qsort_cmpb : crange_qsort_cmpl);
+
+      /* Let's keep it around.  */
+      cranges->contents = cranges_contents;
+      bfd_set_section_flags (cranges->owner, cranges,
+			     bfd_get_section_flags (cranges->owner, cranges)
+			     | SEC_IN_MEMORY);
+
+      /* It's sorted now.  */
+      elf_section_data (cranges)->this_hdr.sh_type = SHT_SH5_CR_SORTED;
+    }
+
+  /* Try and find a matching range.  */
+  found_rangep
+    = bsearch (&addr, cranges_contents, cranges_size / SH64_CRANGE_SIZE, 
+	       SH64_CRANGE_SIZE,
+	       bfd_big_endian (cranges->owner)
+	       ? crange_bsearch_cmpb : crange_bsearch_cmpl);
+
+  /* Fill in a few return values if we found a matching range.  */
+  if (found_rangep)
+    {
+      enum sh64_elf_cr_type cr_type
+	= bfd_get_16 (cranges->owner,
+		      SH64_CRANGE_CR_TYPE_OFFSET + found_rangep);
+      bfd_vma cr_addr
+	= bfd_get_32 (cranges->owner,
+		      SH64_CRANGE_CR_ADDR_OFFSET
+		      + (char *) found_rangep);
+      bfd_size_type cr_size
+	= bfd_get_32 (cranges->owner,
+		      SH64_CRANGE_CR_SIZE_OFFSET
+		      + (char *) found_rangep);
+
+      rangep->cr_addr = cr_addr;
+      rangep->cr_size = cr_size;
+      rangep->cr_type = cr_type;
+
+      return true;
+    }
+
+  /* There is a .cranges section, but it does not have a descriptor
+     matching this address.  */
+  return false;
+
+error_return:
+  free (cranges_contents);
+  return false;
+}
+
+/* Determine what ADDR points to in SEC, and fill in a range descriptor in
+   *RANGEP if it's non-NULL.  */
+
+enum sh64_elf_cr_type
+sh64_get_contents_type (sec, addr, rangep)
+     asection *sec;
+     bfd_vma addr;
+     sh64_elf_crange *rangep;
+{
+  asection *cranges;
+
+  /* Fill in the range with the boundaries of the section as a default.  */
+  if (bfd_get_flavour (sec->owner) == bfd_target_elf_flavour
+      && elf_elfheader (sec->owner)->e_type == ET_EXEC)
+    {
+      rangep->cr_addr = bfd_get_section_vma (sec->owner, sec);
+      rangep->cr_size = bfd_section_size (sec->owner, sec);
+      rangep->cr_type = CRT_NONE;
+    }
+  else
+    return false;
+
+  /* If none of the pertinent bits are set, then it's a SHcompact (or at
+     least not SHmedia).  */
+  if ((elf_section_data (sec)->this_hdr.sh_flags
+       & (SHF_SH5_ISA32 | SHF_SH5_ISA32_MIXED)) == 0)
+    {
+      enum sh64_elf_cr_type cr_type
+	= ((bfd_get_section_flags (sec->owner, sec) & SEC_CODE) != 0
+	   ? CRT_SH5_ISA16 : CRT_DATA);
+      rangep->cr_type = cr_type;
+      return cr_type;
+    }
+
+  /* If only the SHF_SH5_ISA32 bit is set, then we have SHmedia.  */
+  if ((elf_section_data (sec)->this_hdr.sh_flags
+       & (SHF_SH5_ISA32 | SHF_SH5_ISA32_MIXED)) == SHF_SH5_ISA32)
+    {
+      rangep->cr_type = CRT_SH5_ISA32;
+      return CRT_SH5_ISA32;
+    }
+
+  /* Otherwise, we have to look up the .cranges section.  */
+  cranges = bfd_get_section_by_name (sec->owner, SH64_CRANGES_SECTION_NAME);
+
+  if (cranges == NULL)
+    /* A mixed section but there's no .cranges section.  This is probably
+       bad input; it does not comply to specs.  */
+    return CRT_NONE;
+
+  /* If this call fails, we will still have CRT_NONE in rangep->cr_type
+     and that will be suitable to return.  */
+  sh64_address_in_cranges (cranges, addr, rangep);
+
+  return rangep->cr_type;
+}
+
+/* This is a simpler exported interface for the benefit of gdb et al.  */
+
+boolean
+sh64_address_is_shmedia (sec, addr)
+     asection *sec;
+     bfd_vma addr;
+{
+  sh64_elf_crange dummy;
+  return sh64_get_contents_type (sec, addr, &dummy) == CRT_SH5_ISA32;
+}
Index: bfd/elf64-sh64.c
===================================================================
RCS file: bfd/elf64-sh64.c
diff -N bfd/elf64-sh64.c
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ bfd/elf64-sh64.c 2 Feb 2002 04:00:28 -0000
@@ -0,0 +1,4193 @@
+/* Hitachi SH64-specific support for 64-bit ELF
+   Copyright (C) 2000, 2001, 2002 Free Software Foundation, Inc.
+
+   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 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 02111-1307, USA.  */
+
+#define SH64_ELF64
+
+#include "bfd.h"
+#include "sysdep.h"
+#include "bfdlink.h"
+#include "libbfd.h"
+#include "elf-bfd.h"
+#include "elf/sh.h"
+
+/* Add a suffix for datalabel indirection symbols.  It must not match any
+   other symbols; user symbols with or without version or other
+   decoration.  It must only be used internally and not emitted by any
+   means.  */
+#define DATALABEL_SUFFIX " DL"
+
+#define GOT_BIAS (-((long)-32768))
+
+#define PLT_ENTRY_SIZE 64
+
+/* Return size of a PLT entry.  */
+#define elf_sh64_sizeof_plt(info) PLT_ENTRY_SIZE
+
+/* Return offset of the PLT0 address in an absolute PLT entry.  */
+#define elf_sh64_plt_plt0_offset(info) 32
+
+/* Return offset of the linker in PLT0 entry.  */
+#define elf_sh64_plt0_gotplt_offset(info) 0
+
+/* Return offset of the trampoline in PLT entry */
+#define elf_sh64_plt_temp_offset(info) 33 /* Add one because it's SHmedia.  */
+
+/* Return offset of the symbol in PLT entry.  */
+#define elf_sh64_plt_symbol_offset(info) 0
+
+/* Return offset of the relocation in PLT entry.  */
+#define elf_sh64_plt_reloc_offset(info) (info->shared ? 52 : 44)
+
+#define ELF_DYNAMIC_INTERPRETER "/usr/lib/libc.so.1"
+
+/* The sh linker needs to keep track of the number of relocs that it
+   decides to copy in check_relocs for each symbol.  This is so that
+   it can discard PC relative relocs if it doesn't need them when
+   linking with -Bsymbolic.  We store the information in a field
+   extending the regular ELF linker hash table.  */
+
+/* This structure keeps track of the number of PC relative relocs we
+   have copied for a given symbol.  */
+
+struct elf_sh64_pcrel_relocs_copied
+{
+  /* Next section.  */
+  struct elf_sh64_pcrel_relocs_copied *next;
+  /* A section in dynobj.  */
+  asection *section;
+  /* Number of relocs copied in this section.  */
+  bfd_size_type count;
+};
+
+/* sh ELF linker hash entry.  */
+
+struct elf_sh64_link_hash_entry
+{
+  struct elf_link_hash_entry root;
+
+  bfd_vma datalabel_got_offset;
+
+  /* Number of PC relative relocs copied for this symbol.  */
+  struct elf_sh_pcrel_relocs_copied *pcrel_relocs_copied;
+};
+
+/* sh ELF linker hash table.  */
+
+struct elf_sh64_link_hash_table
+{
+  struct elf_link_hash_table root;
+};
+
+/* Traverse an sh ELF linker hash table.  */
+
+#define sh64_elf64_link_hash_traverse(table, func, info)		\
+  (elf_link_hash_traverse						\
+   (&(table)->root,							\
+    (boolean (*) PARAMS ((struct elf_link_hash_entry *, PTR))) (func),	\
+    (info)))
+
+/* Get the sh ELF linker hash table from a link_info structure.  */
+
+#define sh64_elf64_hash_table(p) \
+  ((struct elf_sh64_link_hash_table *) ((p)->hash))
+
+static boolean sh_elf64_copy_private_data PARAMS ((bfd *, bfd *));
+static boolean sh_elf64_copy_private_data_internal PARAMS ((bfd *, bfd *));
+static boolean sh_elf64_merge_private_data PARAMS ((bfd *, bfd *));
+static bfd_reloc_status_type sh_elf64_ignore_reloc
+  PARAMS ((bfd *, arelent *, asymbol *, PTR, asection *, bfd *, char **));
+static bfd_reloc_status_type sh_elf64_reloc
+  PARAMS ((bfd *, arelent *, asymbol *, PTR, asection *, bfd *, char **));
+static reloc_howto_type *sh_elf64_reloc_type_lookup
+  PARAMS ((bfd *, bfd_reloc_code_real_type));
+static void sh_elf64_info_to_howto
+  PARAMS ((bfd *, arelent *, Elf_Internal_Rela *));
+static boolean sh_elf64_relocate_section
+  PARAMS ((bfd *, struct bfd_link_info *, bfd *, asection *, bfd_byte *,
+	   Elf_Internal_Rela *, Elf_Internal_Sym *, asection **));
+static bfd_byte *sh_elf64_get_relocated_section_contents
+  PARAMS ((bfd *, struct bfd_link_info *, struct bfd_link_order *,
+	   bfd_byte *, boolean, asymbol **));
+static boolean sh_elf64_set_mach_from_flags PARAMS ((bfd *));
+static boolean sh_elf64_set_private_flags PARAMS ((bfd *, flagword));
+static asection *sh_elf64_gc_mark_hook
+  PARAMS ((bfd *, struct bfd_link_info *, Elf_Internal_Rela *,
+	   struct elf_link_hash_entry *, Elf_Internal_Sym *));
+static boolean sh_elf64_gc_sweep_hook
+  PARAMS ((bfd *, struct bfd_link_info *, asection *,
+	   const Elf_Internal_Rela *));
+static boolean sh_elf64_check_relocs
+  PARAMS ((bfd *, struct bfd_link_info *, asection *,
+	   const Elf_Internal_Rela *));
+static int sh64_elf64_get_symbol_type PARAMS ((Elf_Internal_Sym *, int));
+static boolean sh64_elf64_add_symbol_hook
+  PARAMS ((bfd *, struct bfd_link_info *, const Elf_Internal_Sym *,
+	   const char **, flagword *, asection **, bfd_vma *));
+extern boolean sh64_elf64_link_output_symbol_hook
+  PARAMS ((bfd *, struct bfd_link_info *, const char *, Elf_Internal_Sym *,
+	   asection *));
+static boolean sh64_elf64_fake_sections
+  PARAMS ((bfd *, Elf_Internal_Shdr *, asection *));
+static void sh64_elf64_final_write_processing PARAMS ((bfd *, boolean));
+
+static reloc_howto_type sh_elf64_howto_table[] = {
+  /* No relocation.  */
+  HOWTO (R_SH_NONE,		/* type */
+	 0,			/* rightshift */
+	 0,			/* size (0 = byte, 1 = short, 2 = long) */
+	 0,			/* bitsize */
+	 false,			/* pc_relative */
+	 0,			/* bitpos */
+	 complain_overflow_dont, /* complain_on_overflow */
+	 sh_elf64_ignore_reloc,	/* special_function */
+	 "R_SH_NONE",		/* name */
+	 false,			/* partial_inplace */
+	 0,			/* src_mask */
+	 0,			/* dst_mask */
+	 false),		/* pcrel_offset */
+
+  /* 32 bit absolute relocation.  Setting partial_inplace to true and
+     src_mask to a non-zero value is similar to the COFF toolchain.  */
+  HOWTO (R_SH_DIR32,		/* type */
+	 0,			/* rightshift */
+	 2,			/* size (0 = byte, 1 = short, 2 = long) */
+	 32,			/* bitsize */
+	 false,			/* pc_relative */
+	 0,			/* bitpos */
+	 complain_overflow_bitfield, /* complain_on_overflow */
+	 sh_elf64_reloc,		/* special_function */
+	 "R_SH_DIR32",		/* name */
+	 true,			/* partial_inplace */
+	 0xffffffff,		/* src_mask */
+	 0xffffffff,		/* dst_mask */
+	 false),		/* pcrel_offset */
+
+  /* 32 bit PC relative relocation.  */
+  HOWTO (R_SH_REL32,		/* type */
+	 0,			/* rightshift */
+	 2,			/* size (0 = byte, 1 = short, 2 = long) */
+	 32,			/* bitsize */
+	 true,			/* pc_relative */
+	 0,			/* bitpos */
+	 complain_overflow_signed, /* complain_on_overflow */
+	 sh_elf64_ignore_reloc,	/* special_function */
+	 "R_SH_REL32",		/* name */
+	 false,			/* partial_inplace */
+	 0,			/* src_mask */
+	 0xffffffff,		/* dst_mask */
+	 true),			/* pcrel_offset */
+
+  /* For 32-bit sh, this is R_SH_DIR8WPN.  */
+  EMPTY_HOWTO (3),
+
+  /* For 32-bit sh, this is R_SH_IND12W.  */
+  EMPTY_HOWTO (4),
+
+  /* For 32-bit sh, this is R_SH_DIR8WPL.  */
+  EMPTY_HOWTO (5),
+
+  /* For 32-bit sh, this is R_SH_DIR8WPZ.  */
+  EMPTY_HOWTO (6),
+
+  /* For 32-bit sh, this is R_SH_DIR8BP.  */
+  EMPTY_HOWTO (7),
+
+  /* For 32-bit sh, this is R_SH_DIR8W.  */
+  EMPTY_HOWTO (8),
+
+  /* For 32-bit sh, this is R_SH_DIR8L.  */
+  EMPTY_HOWTO (9),
+
+  EMPTY_HOWTO (10),
+  EMPTY_HOWTO (11),
+  EMPTY_HOWTO (12),
+  EMPTY_HOWTO (13),
+  EMPTY_HOWTO (14),
+  EMPTY_HOWTO (15),
+  EMPTY_HOWTO (16),
+  EMPTY_HOWTO (17),
+  EMPTY_HOWTO (18),
+  EMPTY_HOWTO (19),
+  EMPTY_HOWTO (20),
+  EMPTY_HOWTO (21),
+  EMPTY_HOWTO (22),
+  EMPTY_HOWTO (23),
+  EMPTY_HOWTO (24),
+
+  /* The remaining relocs are a GNU extension used for relaxing.  The
+     final pass of the linker never needs to do anything with any of
+     these relocs.  Any required operations are handled by the
+     relaxation code.  */
+
+  /* A 16 bit switch table entry.  This is generated for an expression
+     such as ``.word L1 - L2''.  The offset holds the difference
+     between the reloc address and L2.  */
+  HOWTO (R_SH_SWITCH16,		/* type */
+	 0,			/* rightshift */
+	 1,			/* size (0 = byte, 1 = short, 2 = long) */
+	 16,			/* bitsize */
+	 false,			/* pc_relative */
+	 0,			/* bitpos */
+	 complain_overflow_unsigned, /* complain_on_overflow */
+	 sh_elf64_ignore_reloc,	/* special_function */
+	 "R_SH_SWITCH16",	/* name */
+	 false,			/* partial_inplace */
+	 0,			/* src_mask */
+	 0,			/* dst_mask */
+	 true),			/* pcrel_offset */
+
+  /* A 32 bit switch table entry.  This is generated for an expression
+     such as ``.long L1 - L2''.  The offset holds the difference
+     between the reloc address and L2.  */
+  HOWTO (R_SH_SWITCH32,		/* type */
+	 0,			/* rightshift */
+	 2,			/* size (0 = byte, 1 = short, 2 = long) */
+	 32,			/* bitsize */
+	 false,			/* pc_relative */
+	 0,			/* bitpos */
+	 complain_overflow_unsigned, /* complain_on_overflow */
+	 sh_elf64_ignore_reloc,	/* special_function */
+	 "R_SH_SWITCH32",	/* name */
+	 false,			/* partial_inplace */
+	 0,			/* src_mask */
+	 0,			/* dst_mask */
+	 true),			/* pcrel_offset */
+
+  /* For 32-bit sh, this is R_SH_USES.  */
+  EMPTY_HOWTO (27),
+
+  /* For 32-bit sh, this is R_SH_COUNT.  */
+  EMPTY_HOWTO (28),
+
+  /* For 32-bit sh, this is R_SH_ALIGN.  FIXME: For linker relaxation,
+     this might be emitted.  When linker relaxation is implemented, we
+     might want to use it.  */
+  EMPTY_HOWTO (29),
+
+  /* For 32-bit sh, this is R_SH_CODE.  FIXME: For linker relaxation,
+     this might be emitted.  When linker relaxation is implemented, we
+     might want to use it.  */
+  EMPTY_HOWTO (30),
+
+  /* For 32-bit sh, this is R_SH_DATA.  FIXME: For linker relaxation,
+     this might be emitted.  When linker relaxation is implemented, we
+     might want to use it.  */
+  EMPTY_HOWTO (31),
+
+  /* For 32-bit sh, this is R_SH_LABEL.  FIXME: For linker relaxation,
+     this might be emitted.  When linker relaxation is implemented, we
+     might want to use it.  */
+  EMPTY_HOWTO (32),
+
+  /* An 8 bit switch table entry.  This is generated for an expression
+     such as ``.word L1 - L2''.  The offset holds the difference
+     between the reloc address and L2.  */
+  HOWTO (R_SH_SWITCH8,		/* type */
+	 0,			/* rightshift */
+	 0,			/* size (0 = byte, 1 = short, 2 = long) */
+	 8,			/* bitsize */
+	 false,			/* pc_relative */
+	 0,			/* bitpos */
+	 complain_overflow_unsigned, /* complain_on_overflow */
+	 sh_elf64_ignore_reloc,	/* special_function */
+	 "R_SH_SWITCH8",	/* name */
+	 false,			/* partial_inplace */
+	 0,			/* src_mask */
+	 0,			/* dst_mask */
+	 true),			/* pcrel_offset */
+
+  /* GNU extension to record C++ vtable hierarchy */
+  HOWTO (R_SH_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_SH_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_SH_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_SH_GNU_VTENTRY",   /* name */
+         false,                 /* partial_inplace */
+         0,                     /* src_mask */
+         0,                     /* dst_mask */
+         false),                /* pcrel_offset */
+
+  /* For 32-bit sh, this is R_SH_LOOP_START.  */
+  EMPTY_HOWTO (36),
+
+  /* For 32-bit sh, this is R_SH_LOOP_END.  */
+  EMPTY_HOWTO (37),
+
+  EMPTY_HOWTO (38),
+  EMPTY_HOWTO (39),
+  EMPTY_HOWTO (40),
+  EMPTY_HOWTO (41),
+  EMPTY_HOWTO (42),
+  EMPTY_HOWTO (43),
+  EMPTY_HOWTO (44),
+
+  /* Used in SHLLI.L and SHLRI.L.  */
+  HOWTO (R_SH_DIR5U,		/* type */
+	 0,			/* rightshift */
+	 2,			/* size (0 = byte, 1 = short, 2 = long) */
+	 5,			/* bitsize */
+	 false,			/* pc_relative */
+	 10,			/* bitpos */
+	 complain_overflow_unsigned, /* complain_on_overflow */
+	 bfd_elf_generic_reloc,	/* special_function */
+	 "R_SH_DIR5U",		/* name */
+	 false,			/* partial_inplace */
+	 0,			/* src_mask */
+	 0xfc00,		/* dst_mask */
+	 false),	       	/* pcrel_offset */
+
+  /* Used in SHARI, SHLLI et al.  */
+  HOWTO (R_SH_DIR6U,		/* type */
+	 0,			/* rightshift */
+	 2,			/* size (0 = byte, 1 = short, 2 = long) */
+	 6,			/* bitsize */
+	 false,			/* pc_relative */
+	 10,			/* bitpos */
+	 complain_overflow_unsigned, /* complain_on_overflow */
+	 bfd_elf_generic_reloc,	/* special_function */
+	 "R_SH_DIR6U",		/* name */
+	 false,			/* partial_inplace */
+	 0,			/* src_mask */
+	 0xfc00,		/* dst_mask */
+	 false),	       	/* pcrel_offset */
+
+  /* Used in BxxI, LDHI.L et al.  */
+  HOWTO (R_SH_DIR6S,		/* type */
+	 0,			/* rightshift */
+	 2,			/* size (0 = byte, 1 = short, 2 = long) */
+	 6,			/* bitsize */
+	 false,			/* pc_relative */
+	 10,			/* bitpos */
+	 complain_overflow_signed, /* complain_on_overflow */
+	 bfd_elf_generic_reloc,	/* special_function */
+	 "R_SH_DIR6S",		/* name */
+	 false,			/* partial_inplace */
+	 0,			/* src_mask */
+	 0xfc00,		/* dst_mask */
+	 false),	       	/* pcrel_offset */
+
+  /* Used in ADDI, ANDI et al.  */
+  HOWTO (R_SH_DIR10S,		/* type */
+	 0,			/* rightshift */
+	 2,			/* size (0 = byte, 1 = short, 2 = long) */
+	 10,			/* bitsize */
+	 false,			/* pc_relative */
+	 10,			/* bitpos */
+	 complain_overflow_signed, /* complain_on_overflow */
+	 bfd_elf_generic_reloc,	/* special_function */
+	 "R_SH_DIR10S",		/* name */
+	 false,			/* partial_inplace */
+	 0,			/* src_mask */
+	 0xffc00,		/* dst_mask */
+	 false),	       	/* pcrel_offset */
+
+  /* Used in LD.UW, ST.W et al.  */
+  HOWTO (R_SH_DIR10SW,	/* type */
+	 1,			/* rightshift */
+	 2,			/* size (0 = byte, 1 = short, 2 = long) */
+	 11,			/* bitsize */
+	 false,			/* pc_relative */
+	 10,			/* bitpos */
+	 complain_overflow_signed, /* complain_on_overflow */
+	 bfd_elf_generic_reloc,	/* special_function */
+	 "R_SH_DIR10SW",	/* name */
+	 false,			/* partial_inplace */
+	 0,			/* src_mask */
+	 0xffc00,		/* dst_mask */
+	 false),	       	/* pcrel_offset */
+
+  /* Used in LD.L, FLD.S et al.  */
+  HOWTO (R_SH_DIR10SL,	/* type */
+	 2,			/* rightshift */
+	 2,			/* size (0 = byte, 1 = short, 2 = long) */
+	 12,			/* bitsize */
+	 false,			/* pc_relative */
+	 10,			/* bitpos */
+	 complain_overflow_signed, /* complain_on_overflow */
+	 bfd_elf_generic_reloc,	/* special_function */
+	 "R_SH_DIR10SL",	/* name */
+	 false,			/* partial_inplace */
+	 0,			/* src_mask */
+	 0xffc00,		/* dst_mask */
+	 false),	       	/* pcrel_offset */
+
+  /* Used in FLD.D, FST.P et al.  */
+  HOWTO (R_SH_DIR10SQ,	/* type */
+	 3,			/* rightshift */
+	 2,			/* size (0 = byte, 1 = short, 2 = long) */
+	 13,			/* bitsize */
+	 false,			/* pc_relative */
+	 10,			/* bitpos */
+	 complain_overflow_signed, /* complain_on_overflow */
+	 bfd_elf_generic_reloc,	/* special_function */
+	 "R_SH_DIR10SQ",	/* name */
+	 false,			/* partial_inplace */
+	 0,			/* src_mask */
+	 0xffc00,		/* dst_mask */
+	 false),	       	/* pcrel_offset */
+
+  EMPTY_HOWTO (52),
+  EMPTY_HOWTO (53),
+  EMPTY_HOWTO (54),
+  EMPTY_HOWTO (55),
+  EMPTY_HOWTO (56),
+  EMPTY_HOWTO (57),
+  EMPTY_HOWTO (58),
+  EMPTY_HOWTO (59),
+  EMPTY_HOWTO (60),
+  EMPTY_HOWTO (61),
+  EMPTY_HOWTO (62),
+  EMPTY_HOWTO (63),
+  EMPTY_HOWTO (64),
+  EMPTY_HOWTO (65),
+  EMPTY_HOWTO (66),
+  EMPTY_HOWTO (67),
+  EMPTY_HOWTO (68),
+  EMPTY_HOWTO (69),
+  EMPTY_HOWTO (70),
+  EMPTY_HOWTO (71),
+  EMPTY_HOWTO (72),
+  EMPTY_HOWTO (73),
+  EMPTY_HOWTO (74),
+  EMPTY_HOWTO (75),
+  EMPTY_HOWTO (76),
+  EMPTY_HOWTO (77),
+  EMPTY_HOWTO (78),
+  EMPTY_HOWTO (79),
+  EMPTY_HOWTO (80),
+  EMPTY_HOWTO (81),
+  EMPTY_HOWTO (82),
+  EMPTY_HOWTO (83),
+  EMPTY_HOWTO (84),
+  EMPTY_HOWTO (85),
+  EMPTY_HOWTO (86),
+  EMPTY_HOWTO (87),
+  EMPTY_HOWTO (88),
+  EMPTY_HOWTO (89),
+  EMPTY_HOWTO (90),
+  EMPTY_HOWTO (91),
+  EMPTY_HOWTO (92),
+  EMPTY_HOWTO (93),
+  EMPTY_HOWTO (94),
+  EMPTY_HOWTO (95),
+  EMPTY_HOWTO (96),
+  EMPTY_HOWTO (97),
+  EMPTY_HOWTO (98),
+  EMPTY_HOWTO (99),
+  EMPTY_HOWTO (100),
+  EMPTY_HOWTO (101),
+  EMPTY_HOWTO (102),
+  EMPTY_HOWTO (103),
+  EMPTY_HOWTO (104),
+  EMPTY_HOWTO (105),
+  EMPTY_HOWTO (106),
+  EMPTY_HOWTO (107),
+  EMPTY_HOWTO (108),
+  EMPTY_HOWTO (109),
+  EMPTY_HOWTO (110),
+  EMPTY_HOWTO (111),
+  EMPTY_HOWTO (112),
+  EMPTY_HOWTO (113),
+  EMPTY_HOWTO (114),
+  EMPTY_HOWTO (115),
+  EMPTY_HOWTO (116),
+  EMPTY_HOWTO (117),
+  EMPTY_HOWTO (118),
+  EMPTY_HOWTO (119),
+  EMPTY_HOWTO (120),
+  EMPTY_HOWTO (121),
+  EMPTY_HOWTO (122),
+  EMPTY_HOWTO (123),
+  EMPTY_HOWTO (124),
+  EMPTY_HOWTO (125),
+  EMPTY_HOWTO (126),
+  EMPTY_HOWTO (127),
+  EMPTY_HOWTO (128),
+  EMPTY_HOWTO (129),
+  EMPTY_HOWTO (130),
+  EMPTY_HOWTO (131),
+  EMPTY_HOWTO (132),
+  EMPTY_HOWTO (133),
+  EMPTY_HOWTO (134),
+  EMPTY_HOWTO (135),
+  EMPTY_HOWTO (136),
+  EMPTY_HOWTO (137),
+  EMPTY_HOWTO (138),
+  EMPTY_HOWTO (139),
+  EMPTY_HOWTO (140),
+  EMPTY_HOWTO (141),
+  EMPTY_HOWTO (142),
+  EMPTY_HOWTO (143),
+  EMPTY_HOWTO (144),
+  EMPTY_HOWTO (145),
+  EMPTY_HOWTO (146),
+  EMPTY_HOWTO (147),
+  EMPTY_HOWTO (148),
+  EMPTY_HOWTO (149),
+  EMPTY_HOWTO (150),
+  EMPTY_HOWTO (151),
+  EMPTY_HOWTO (152),
+  EMPTY_HOWTO (153),
+  EMPTY_HOWTO (154),
+  EMPTY_HOWTO (155),
+  EMPTY_HOWTO (156),
+  EMPTY_HOWTO (157),
+  EMPTY_HOWTO (158),
+  EMPTY_HOWTO (159),
+
+  /* Relocs for dynamic linking for 32-bit SH would follow.  We don't have
+     any dynamic linking support for 64-bit SH at present.  */
+
+  EMPTY_HOWTO (160),
+  EMPTY_HOWTO (161),
+  EMPTY_HOWTO (162),
+  EMPTY_HOWTO (163),
+  EMPTY_HOWTO (164),
+  EMPTY_HOWTO (165),
+  EMPTY_HOWTO (166),
+  EMPTY_HOWTO (167),
+  EMPTY_HOWTO (168),
+
+  /* Back to SH5 relocations.  */
+  /* Used in MOVI and SHORI (x & 65536).  */
+  HOWTO (R_SH_GOT_LOW16,	/* type */
+	 0,			/* rightshift */
+	 2,			/* size (0 = byte, 1 = short, 2 = long) */
+	 64,			/* bitsize */
+	 false,			/* pc_relative */
+	 10,			/* bitpos */
+	 complain_overflow_dont, /* complain_on_overflow */
+	 bfd_elf_generic_reloc,	/* special_function */
+	 "R_SH_GOT_LOW16",    	/* name */
+	 false,			/* partial_inplace */
+	 0,			/* src_mask */
+	 0x3fffc00,		/* dst_mask */
+	 false),	       	/* pcrel_offset */
+
+  /* Used in MOVI and SHORI ((x >> 16) & 65536).  */
+  HOWTO (R_SH_GOT_MEDLOW16,	/* type */
+	 16,			/* rightshift */
+	 2,			/* size (0 = byte, 1 = short, 2 = long) */
+	 64,			/* bitsize */
+	 false,			/* pc_relative */
+	 10,			/* bitpos */
+	 complain_overflow_dont, /* complain_on_overflow */
+	 bfd_elf_generic_reloc,	/* special_function */
+	 "R_SH_GOT_MEDLOW16",	/* name */
+	 false,			/* partial_inplace */
+	 0,			/* src_mask */
+	 0x3fffc00,		/* dst_mask */
+	 false),	       	/* pcrel_offset */
+
+  /* Used in MOVI and SHORI ((x >> 32) & 65536).  */
+  HOWTO (R_SH_GOT_MEDHI16,	/* type */
+	 32,			/* rightshift */
+	 2,			/* size (0 = byte, 1 = short, 2 = long) */
+	 64,			/* bitsize */
+	 false,			/* pc_relative */
+	 10,			/* bitpos */
+	 complain_overflow_dont, /* complain_on_overflow */
+	 bfd_elf_generic_reloc,	/* special_function */
+	 "R_SH_GOT_MEDHI16",	/* name */
+	 false,			/* partial_inplace */
+	 0,			/* src_mask */
+	 0x3fffc00,		/* dst_mask */
+	 false),	       	/* pcrel_offset */
+
+  /* Used in MOVI and SHORI ((x >> 48) & 65536).  */
+  HOWTO (R_SH_GOT_HI16,		/* type */
+	 48,			/* rightshift */
+	 2,			/* size (0 = byte, 1 = short, 2 = long) */
+	 64,			/* bitsize */
+	 false,			/* pc_relative */
+	 10,			/* bitpos */
+	 complain_overflow_dont, /* complain_on_overflow */
+	 bfd_elf_generic_reloc,	/* special_function */
+	 "R_SH_GOT_HI16",	/* name */
+	 false,			/* partial_inplace */
+	 0,			/* src_mask */
+	 0x3fffc00,		/* dst_mask */
+	 false),	       	/* pcrel_offset */
+
+  /* Used in MOVI and SHORI (x & 65536).  */
+  HOWTO (R_SH_GOTPLT_LOW16,	/* type */
+	 0,			/* rightshift */
+	 2,			/* size (0 = byte, 1 = short, 2 = long) */
+	 64,			/* bitsize */
+	 false,			/* pc_relative */
+	 10,			/* bitpos */
+	 complain_overflow_dont, /* complain_on_overflow */
+	 bfd_elf_generic_reloc,	/* special_function */
+	 "R_SH_GOTPLT_LOW16",   /* name */
+	 false,			/* partial_inplace */
+	 0,			/* src_mask */
+	 0x3fffc00,		/* dst_mask */
+	 false),	       	/* pcrel_offset */
+
+  /* Used in MOVI and SHORI ((x >> 16) & 65536).  */
+  HOWTO (R_SH_GOTPLT_MEDLOW16,	/* type */
+	 16,			/* rightshift */
+	 2,			/* size (0 = byte, 1 = short, 2 = long) */
+	 64,			/* bitsize */
+	 false,			/* pc_relative */
+	 10,			/* bitpos */
+	 complain_overflow_dont, /* complain_on_overflow */
+	 bfd_elf_generic_reloc,	/* special_function */
+	 "R_SH_GOTPLT_MEDLOW16", /* name */
+	 false,			/* partial_inplace */
+	 0,			/* src_mask */
+	 0x3fffc00,		/* dst_mask */
+	 false),	       	/* pcrel_offset */
+
+  /* Used in MOVI and SHORI ((x >> 32) & 65536).  */
+  HOWTO (R_SH_GOTPLT_MEDHI16,	/* type */
+	 32,			/* rightshift */
+	 2,			/* size (0 = byte, 1 = short, 2 = long) */
+	 64,			/* bitsize */
+	 false,			/* pc_relative */
+	 10,			/* bitpos */
+	 complain_overflow_dont, /* complain_on_overflow */
+	 bfd_elf_generic_reloc,	/* special_function */
+	 "R_SH_GOTPLT_MEDHI16",	/* name */
+	 false,			/* partial_inplace */
+	 0,			/* src_mask */
+	 0x3fffc00,		/* dst_mask */
+	 false),	       	/* pcrel_offset */
+
+  /* Used in MOVI and SHORI ((x >> 48) & 65536).  */
+  HOWTO (R_SH_GOTPLT_HI16,	/* type */
+	 48,			/* rightshift */
+	 2,			/* size (0 = byte, 1 = short, 2 = long) */
+	 64,			/* bitsize */
+	 false,			/* pc_relative */
+	 10,			/* bitpos */
+	 complain_overflow_dont, /* complain_on_overflow */
+	 bfd_elf_generic_reloc,	/* special_function */
+	 "R_SH_GOTPLT_HI16",	/* name */
+	 false,			/* partial_inplace */
+	 0,			/* src_mask */
+	 0x3fffc00,		/* dst_mask */
+	 false),	       	/* pcrel_offset */
+
+  /* Used in MOVI and SHORI (x & 65536).  */
+  HOWTO (R_SH_PLT_LOW16,	/* type */
+	 0,			/* rightshift */
+	 2,			/* size (0 = byte, 1 = short, 2 = long) */
+	 64,			/* bitsize */
+	 true,			/* pc_relative */
+	 10,			/* bitpos */
+	 complain_overflow_dont, /* complain_on_overflow */
+	 bfd_elf_generic_reloc,	/* special_function */
+	 "R_SH_PLT_LOW16",    	/* name */
+	 false,			/* partial_inplace */
+	 0,			/* src_mask */
+	 0x3fffc00,		/* dst_mask */
+	 true),		       	/* pcrel_offset */
+
+  /* Used in MOVI and SHORI ((x >> 16) & 65536).  */
+  HOWTO (R_SH_PLT_MEDLOW16,	/* type */
+	 16,			/* rightshift */
+	 2,			/* size (0 = byte, 1 = short, 2 = long) */
+	 64,			/* bitsize */
+	 true,			/* pc_relative */
+	 10,			/* bitpos */
+	 complain_overflow_dont, /* complain_on_overflow */
+	 bfd_elf_generic_reloc,	/* special_function */
+	 "R_SH_PLT_MEDLOW16",	/* name */
+	 false,			/* partial_inplace */
+	 0,			/* src_mask */
+	 0x3fffc00,		/* dst_mask */
+	 true),		       	/* pcrel_offset */
+
+  /* Used in MOVI and SHORI ((x >> 32) & 65536).  */
+  HOWTO (R_SH_PLT_MEDHI16,	/* type */
+	 32,			/* rightshift */
+	 2,			/* size (0 = byte, 1 = short, 2 = long) */
+	 64,			/* bitsize */
+	 true,			/* pc_relative */
+	 10,			/* bitpos */
+	 complain_overflow_dont, /* complain_on_overflow */
+	 bfd_elf_generic_reloc,	/* special_function */
+	 "R_SH_PLT_MEDHI16",	/* name */
+	 false,			/* partial_inplace */
+	 0,			/* src_mask */
+	 0x3fffc00,		/* dst_mask */
+	 true),		       	/* pcrel_offset */
+
+  /* Used in MOVI and SHORI ((x >> 48) & 65536).  */
+  HOWTO (R_SH_PLT_HI16,		/* type */
+	 48,			/* rightshift */
+	 2,			/* size (0 = byte, 1 = short, 2 = long) */
+	 64,			/* bitsize */
+	 true,			/* pc_relative */
+	 10,			/* bitpos */
+	 complain_overflow_dont, /* complain_on_overflow */
+	 bfd_elf_generic_reloc,	/* special_function */
+	 "R_SH_PLT_HI16",	/* name */
+	 false,			/* partial_inplace */
+	 0,			/* src_mask */
+	 0x3fffc00,		/* dst_mask */
+	 true),		       	/* pcrel_offset */
+
+  /* Used in MOVI and SHORI (x & 65536).  */
+  HOWTO (R_SH_GOTOFF_LOW16,	/* type */
+	 0,			/* rightshift */
+	 2,			/* size (0 = byte, 1 = short, 2 = long) */
+	 64,			/* bitsize */
+	 false,			/* pc_relative */
+	 10,			/* bitpos */
+	 complain_overflow_dont, /* complain_on_overflow */
+	 bfd_elf_generic_reloc,	/* special_function */
+	 "R_SH_GOTOFF_LOW16",   /* name */
+	 false,			/* partial_inplace */
+	 0,			/* src_mask */
+	 0x3fffc00,		/* dst_mask */
+	 false),	       	/* pcrel_offset */
+
+  /* Used in MOVI and SHORI ((x >> 16) & 65536).  */
+  HOWTO (R_SH_GOTOFF_MEDLOW16,	/* type */
+	 16,			/* rightshift */
+	 2,			/* size (0 = byte, 1 = short, 2 = long) */
+	 64,			/* bitsize */
+	 false,			/* pc_relative */
+	 10,			/* bitpos */
+	 complain_overflow_dont, /* complain_on_overflow */
+	 bfd_elf_generic_reloc,	/* special_function */
+	 "R_SH_GOTOFF_MEDLOW16", /* name */
+	 false,			/* partial_inplace */
+	 0,			/* src_mask */
+	 0x3fffc00,		/* dst_mask */
+	 false),	       	/* pcrel_offset */
+
+  /* Used in MOVI and SHORI ((x >> 32) & 65536).  */
+  HOWTO (R_SH_GOTOFF_MEDHI16,	/* type */
+	 32,			/* rightshift */
+	 2,			/* size (0 = byte, 1 = short, 2 = long) */
+	 64,			/* bitsize */
+	 false,			/* pc_relative */
+	 10,			/* bitpos */
+	 complain_overflow_dont, /* complain_on_overflow */
+	 bfd_elf_generic_reloc,	/* special_function */
+	 "R_SH_GOTOFF_MEDHI16",	/* name */
+	 false,			/* partial_inplace */
+	 0,			/* src_mask */
+	 0x3fffc00,		/* dst_mask */
+	 false),	       	/* pcrel_offset */
+
+  /* Used in MOVI and SHORI ((x >> 48) & 65536).  */
+  HOWTO (R_SH_GOTOFF_HI16,	/* type */
+	 48,			/* rightshift */
+	 2,			/* size (0 = byte, 1 = short, 2 = long) */
+	 64,			/* bitsize */
+	 false,			/* pc_relative */
+	 10,			/* bitpos */
+	 complain_overflow_dont, /* complain_on_overflow */
+	 bfd_elf_generic_reloc,	/* special_function */
+	 "R_SH_GOTOFF_HI16",	/* name */
+	 false,			/* partial_inplace */
+	 0,			/* src_mask */
+	 0x3fffc00,		/* dst_mask */
+	 false),	       	/* pcrel_offset */
+
+  /* Used in MOVI and SHORI (x & 65536).  */
+  HOWTO (R_SH_GOTPC_LOW16,	/* type */
+	 0,			/* rightshift */
+	 2,			/* size (0 = byte, 1 = short, 2 = long) */
+	 64,			/* bitsize */
+	 true,			/* pc_relative */
+	 10,			/* bitpos */
+	 complain_overflow_dont, /* complain_on_overflow */
+	 bfd_elf_generic_reloc,	/* special_function */
+	 "R_SH_GOTPC_LOW16",    /* name */
+	 false,			/* partial_inplace */
+	 0,			/* src_mask */
+	 0x3fffc00,		/* dst_mask */
+	 true),		       	/* pcrel_offset */
+
+  /* Used in MOVI and SHORI ((x >> 16) & 65536).  */
+  HOWTO (R_SH_GOTPC_MEDLOW16,	/* type */
+	 16,			/* rightshift */
+	 2,			/* size (0 = byte, 1 = short, 2 = long) */
+	 64,			/* bitsize */
+	 true,			/* pc_relative */
+	 10,			/* bitpos */
+	 complain_overflow_dont, /* complain_on_overflow */
+	 bfd_elf_generic_reloc,	/* special_function */
+	 "R_SH_GOTPC_MEDLOW16", /* name */
+	 false,			/* partial_inplace */
+	 0,			/* src_mask */
+	 0x3fffc00,		/* dst_mask */
+	 true),		       	/* pcrel_offset */
+
+  /* Used in MOVI and SHORI ((x >> 32) & 65536).  */
+  HOWTO (R_SH_GOTPC_MEDHI16,	/* type */
+	 32,			/* rightshift */
+	 2,			/* size (0 = byte, 1 = short, 2 = long) */
+	 64,			/* bitsize */
+	 true,			/* pc_relative */
+	 10,			/* bitpos */
+	 complain_overflow_dont, /* complain_on_overflow */
+	 bfd_elf_generic_reloc,	/* special_function */
+	 "R_SH_GOTPC_MEDHI16",	/* name */
+	 false,			/* partial_inplace */
+	 0,			/* src_mask */
+	 0x3fffc00,		/* dst_mask */
+	 true),		       	/* pcrel_offset */
+
+  /* Used in MOVI and SHORI ((x >> 48) & 65536).  */
+  HOWTO (R_SH_GOTPC_HI16,	/* type */
+	 48,			/* rightshift */
+	 2,			/* size (0 = byte, 1 = short, 2 = long) */
+	 64,			/* bitsize */
+	 true,			/* pc_relative */
+	 10,			/* bitpos */
+	 complain_overflow_dont, /* complain_on_overflow */
+	 bfd_elf_generic_reloc,	/* special_function */
+	 "R_SH_GOTPC_HI16",	/* name */
+	 false,			/* partial_inplace */
+	 0,			/* src_mask */
+	 0x3fffc00,		/* dst_mask */
+	 true),		       	/* pcrel_offset */
+
+  /* Used in LD.L, FLD.S et al.  */
+  HOWTO (R_SH_GOT10BY4,		/* type */
+	 2,			/* rightshift */
+	 2,			/* size (0 = byte, 1 = short, 2 = long) */
+	 12,			/* bitsize */
+	 false,			/* pc_relative */
+	 10,			/* bitpos */
+	 complain_overflow_signed, /* complain_on_overflow */
+	 bfd_elf_generic_reloc,	/* special_function */
+	 "R_SH_GOT10BY4",	/* name */
+	 false,			/* partial_inplace */
+	 0,			/* src_mask */
+	 0xffc00,		/* dst_mask */
+	 false),	       	/* pcrel_offset */
+
+  /* Used in LD.L, FLD.S et al.  */
+  HOWTO (R_SH_GOTPLT10BY4,	/* type */
+	 2,			/* rightshift */
+	 2,			/* size (0 = byte, 1 = short, 2 = long) */
+	 12,			/* bitsize */
+	 false,			/* pc_relative */
+	 10,			/* bitpos */
+	 complain_overflow_signed, /* complain_on_overflow */
+	 bfd_elf_generic_reloc,	/* special_function */
+	 "R_SH_GOTPLT10BY4",	/* name */
+	 false,			/* partial_inplace */
+	 0,			/* src_mask */
+	 0xffc00,		/* dst_mask */
+	 false),	       	/* pcrel_offset */
+
+  /* Used in FLD.D, FST.P et al.  */
+  HOWTO (R_SH_GOT10BY8,		/* type */
+	 3,			/* rightshift */
+	 2,			/* size (0 = byte, 1 = short, 2 = long) */
+	 13,			/* bitsize */
+	 false,			/* pc_relative */
+	 10,			/* bitpos */
+	 complain_overflow_signed, /* complain_on_overflow */
+	 bfd_elf_generic_reloc,	/* special_function */
+	 "R_SH_GOT10BY8",	/* name */
+	 false,			/* partial_inplace */
+	 0,			/* src_mask */
+	 0xffc00,		/* dst_mask */
+	 false),	       	/* pcrel_offset */
+
+  /* Used in FLD.D, FST.P et al.  */
+  HOWTO (R_SH_GOTPLT10BY8,	/* type */
+	 3,			/* rightshift */
+	 2,			/* size (0 = byte, 1 = short, 2 = long) */
+	 13,			/* bitsize */
+	 false,			/* pc_relative */
+	 10,			/* bitpos */
+	 complain_overflow_signed, /* complain_on_overflow */
+	 bfd_elf_generic_reloc,	/* special_function */
+	 "R_SH_GOTPLT10BY8",	/* name */
+	 false,			/* partial_inplace */
+	 0,			/* src_mask */
+	 0xffc00,		/* dst_mask */
+	 false),	       	/* pcrel_offset */
+
+  HOWTO (R_SH_COPY64,		/* type */
+	 0,			/* rightshift */
+	 4,			/* size (0 = byte, 1 = short, 2 = long) */
+	 64,			/* bitsize */
+	 false,			/* pc_relative */
+	 0,			/* bitpos */
+	 complain_overflow_dont, /* complain_on_overflow */
+	 bfd_elf_generic_reloc,	/* special_function */
+	 "R_SH_COPY64", 	/* name */
+	 false,			/* partial_inplace */
+	 0,			/* src_mask */
+	 ((bfd_vma) 0) - 1,	/* dst_mask */
+	 false),	       	/* pcrel_offset */
+
+  HOWTO (R_SH_GLOB_DAT64,	/* type */
+	 0,			/* rightshift */
+	 4,			/* size (0 = byte, 1 = short, 2 = long) */
+	 64,			/* bitsize */
+	 false,			/* pc_relative */
+	 0,			/* bitpos */
+	 complain_overflow_dont, /* complain_on_overflow */
+	 bfd_elf_generic_reloc,	/* special_function */
+	 "R_SH_GLOB_DAT64", 	/* name */
+	 false,			/* partial_inplace */
+	 0,			/* src_mask */
+	 ((bfd_vma) 0) - 1,	/* dst_mask */
+	 false),	       	/* pcrel_offset */
+
+  HOWTO (R_SH_JMP_SLOT64,	/* type */
+	 0,			/* rightshift */
+	 4,			/* size (0 = byte, 1 = short, 2 = long) */
+	 64,			/* bitsize */
+	 false,			/* pc_relative */
+	 0,			/* bitpos */
+	 complain_overflow_dont, /* complain_on_overflow */
+	 bfd_elf_generic_reloc,	/* special_function */
+	 "R_SH_JMP_SLOT64", 	/* name */
+	 false,			/* partial_inplace */
+	 0,			/* src_mask */
+	 ((bfd_vma) 0) - 1,	/* dst_mask */
+	 false),	       	/* pcrel_offset */
+
+  HOWTO (R_SH_RELATIVE64,	/* type */
+	 0,			/* rightshift */
+	 4,			/* size (0 = byte, 1 = short, 2 = long) */
+	 64,			/* bitsize */
+	 false,			/* pc_relative */
+	 0,			/* bitpos */
+	 complain_overflow_dont, /* complain_on_overflow */
+	 bfd_elf_generic_reloc,	/* special_function */
+	 "R_SH_RELATIVE64", 	/* name */
+	 false,			/* partial_inplace */
+	 0,			/* src_mask */
+	 ((bfd_vma) 0) - 1,	/* dst_mask */
+	 false),	       	/* pcrel_offset */
+
+  EMPTY_HOWTO (197),
+  EMPTY_HOWTO (198),
+  EMPTY_HOWTO (199),
+  EMPTY_HOWTO (200),
+  EMPTY_HOWTO (201),
+  EMPTY_HOWTO (202),
+  EMPTY_HOWTO (203),
+  EMPTY_HOWTO (204),
+  EMPTY_HOWTO (205),
+  EMPTY_HOWTO (206),
+  EMPTY_HOWTO (207),
+  EMPTY_HOWTO (208),
+  EMPTY_HOWTO (209),
+  EMPTY_HOWTO (210),
+  EMPTY_HOWTO (211),
+  EMPTY_HOWTO (212),
+  EMPTY_HOWTO (213),
+  EMPTY_HOWTO (214),
+  EMPTY_HOWTO (215),
+  EMPTY_HOWTO (216),
+  EMPTY_HOWTO (217),
+  EMPTY_HOWTO (218),
+  EMPTY_HOWTO (219),
+  EMPTY_HOWTO (220),
+  EMPTY_HOWTO (221),
+  EMPTY_HOWTO (222),
+  EMPTY_HOWTO (223),
+  EMPTY_HOWTO (224),
+  EMPTY_HOWTO (225),
+  EMPTY_HOWTO (226),
+  EMPTY_HOWTO (227),
+  EMPTY_HOWTO (228),
+  EMPTY_HOWTO (229),
+  EMPTY_HOWTO (230),
+  EMPTY_HOWTO (231),
+  EMPTY_HOWTO (232),
+  EMPTY_HOWTO (233),
+  EMPTY_HOWTO (234),
+  EMPTY_HOWTO (235),
+  EMPTY_HOWTO (236),
+  EMPTY_HOWTO (237),
+  EMPTY_HOWTO (238),
+  EMPTY_HOWTO (239),
+  EMPTY_HOWTO (240),
+  EMPTY_HOWTO (241),
+
+  /* Relocations for SHmedia code.  None of these are partial_inplace or
+     use the field being relocated.  */
+
+  /* The assembler will generate this reloc before a block of SHmedia
+     instructions.  A section should be processed as assuming it contains
+     data, unless this reloc is seen.  Note that a block of SHcompact
+     instructions are instead preceded by R_SH_CODE.
+     This is currently not implemented, but should be used for SHmedia
+     linker relaxation.  */
+  HOWTO (R_SH_SHMEDIA_CODE,	/* type */
+	 0,			/* rightshift */
+	 1,			/* size (0 = byte, 1 = short, 2 = long) */
+	 0,			/* bitsize */
+	 false,			/* pc_relative */
+	 0,			/* bitpos */
+	 complain_overflow_unsigned, /* complain_on_overflow */
+	 sh_elf64_ignore_reloc,	/* special_function */
+	 "R_SH_SHMEDIA_CODE",	/* name */
+	 false,			/* partial_inplace */
+	 0,			/* src_mask */
+	 0,			/* dst_mask */
+	 false),		/* pcrel_offset */
+
+  /* The assembler will generate this reloc at a PTA or PTB instruction,
+     and the linker checks the right type of target, or changes a PTA to a
+     PTB, if the original insn was PT.  */
+  HOWTO (R_SH_PT_16,		/* type */
+	 2,			/* rightshift */
+	 2,			/* size (0 = byte, 1 = short, 2 = long) */
+	 18,			/* bitsize */
+	 true,			/* pc_relative */
+	 10,			/* bitpos */
+	 complain_overflow_signed, /* complain_on_overflow */
+	 bfd_elf_generic_reloc,	/* special_function */
+	 "R_SH_PT_16",		/* name */
+	 false,			/* partial_inplace */
+	 0,			/* src_mask */
+	 0x3fffc00,		/* dst_mask */
+	 true),			/* pcrel_offset */
+
+  /* Used in unexpanded MOVI.  */
+  HOWTO (R_SH_IMMS16,		/* type */
+	 0,			/* rightshift */
+	 2,			/* size (0 = byte, 1 = short, 2 = long) */
+	 16,			/* bitsize */
+	 false,			/* pc_relative */
+	 10,			/* bitpos */
+	 complain_overflow_signed, /* complain_on_overflow */
+	 bfd_elf_generic_reloc,	/* special_function */
+	 "R_SH_IMMS16",		/* name */
+	 false,			/* partial_inplace */
+	 0,			/* src_mask */
+	 0x3fffc00,		/* dst_mask */
+	 false),	       	/* pcrel_offset */
+
+  /* Used in SHORI.  */
+  HOWTO (R_SH_IMMU16,		/* type */
+	 0,			/* rightshift */
+	 2,			/* size (0 = byte, 1 = short, 2 = long) */
+	 16,			/* bitsize */
+	 false,			/* pc_relative */
+	 10,			/* bitpos */
+	 complain_overflow_unsigned, /* complain_on_overflow */
+	 bfd_elf_generic_reloc,	/* special_function */
+	 "R_SH_IMMU16",		/* name */
+	 false,			/* partial_inplace */
+	 0,			/* src_mask */
+	 0x3fffc00,		/* dst_mask */
+	 false),	       	/* pcrel_offset */
+
+  /* Used in MOVI and SHORI (x & 65536).  */
+  HOWTO (R_SH_IMM_LOW16,	/* type */
+	 0,			/* rightshift */
+	 2,			/* size (0 = byte, 1 = short, 2 = long) */
+	 64,			/* bitsize */
+	 false,			/* pc_relative */
+	 10,			/* bitpos */
+	 complain_overflow_dont, /* complain_on_overflow */
+	 bfd_elf_generic_reloc,	/* special_function */
+	 "R_SH_IMM_LOW16",    	/* name */
+	 false,			/* partial_inplace */
+	 0,			/* src_mask */
+	 0x3fffc00,		/* dst_mask */
+	 false),	       	/* pcrel_offset */
+
+  /* Used in MOVI and SHORI ((x - $) & 65536).  */
+  HOWTO (R_SH_IMM_LOW16_PCREL,	/* type */
+	 0,			/* rightshift */
+	 2,			/* size (0 = byte, 1 = short, 2 = long) */
+	 64,			/* bitsize */
+	 true,			/* pc_relative */
+	 10,			/* bitpos */
+	 complain_overflow_dont, /* complain_on_overflow */
+	 bfd_elf_generic_reloc,	/* special_function */
+	 "R_SH_IMM_LOW16_PCREL", /* name */
+	 false,			/* partial_inplace */
+	 0,			/* src_mask */
+	 0x3fffc00,		/* dst_mask */
+	 true),			/* pcrel_offset */
+
+  /* Used in MOVI and SHORI ((x >> 16) & 65536).  */
+  HOWTO (R_SH_IMM_MEDLOW16,	/* type */
+	 16,			/* rightshift */
+	 2,			/* size (0 = byte, 1 = short, 2 = long) */
+	 64,			/* bitsize */
+	 false,			/* pc_relative */
+	 10,			/* bitpos */
+	 complain_overflow_dont, /* complain_on_overflow */
+	 bfd_elf_generic_reloc,	/* special_function */
+	 "R_SH_IMM_MEDLOW16",	/* name */
+	 false,			/* partial_inplace */
+	 0,			/* src_mask */
+	 0x3fffc00,		/* dst_mask */
+	 false),	       	/* pcrel_offset */
+
+  /* Used in MOVI and SHORI (((x - $) >> 16) & 65536).  */
+  HOWTO (R_SH_IMM_MEDLOW16_PCREL, /* type */
+	 16,			/* rightshift */
+	 2,			/* size (0 = byte, 1 = short, 2 = long) */
+	 64,			/* bitsize */
+	 true,			/* pc_relative */
+	 10,			/* bitpos */
+	 complain_overflow_dont, /* complain_on_overflow */
+	 bfd_elf_generic_reloc,	/* special_function */
+	 "R_SH_IMM_MEDLOW16_PCREL", /* name */
+	 false,			/* partial_inplace */
+	 0,			/* src_mask */
+	 0x3fffc00,		/* dst_mask */
+	 true),			/* pcrel_offset */
+
+  /* Used in MOVI and SHORI ((x >> 32) & 65536).  */
+  HOWTO (R_SH_IMM_MEDHI16,	/* type */
+	 32,			/* rightshift */
+	 2,			/* size (0 = byte, 1 = short, 2 = long) */
+	 64,			/* bitsize */
+	 false,			/* pc_relative */
+	 10,			/* bitpos */
+	 complain_overflow_dont, /* complain_on_overflow */
+	 bfd_elf_generic_reloc,	/* special_function */
+	 "R_SH_IMM_MEDHI16",	/* name */
+	 false,			/* partial_inplace */
+	 0,			/* src_mask */
+	 0x3fffc00,		/* dst_mask */
+	 false),	       	/* pcrel_offset */
+
+  /* Used in MOVI and SHORI (((x - $) >> 32) & 65536).  */
+  HOWTO (R_SH_IMM_MEDHI16_PCREL, /* type */
+	 32,			/* rightshift */
+	 2,			/* size (0 = byte, 1 = short, 2 = long) */
+	 64,			/* bitsize */
+	 true,			/* pc_relative */
+	 10,			/* bitpos */
+	 complain_overflow_dont, /* complain_on_overflow */
+	 bfd_elf_generic_reloc,	/* special_function */
+	 "R_SH_IMM_MEDHI16_PCREL", /* name */
+	 false,			/* partial_inplace */
+	 0,			/* src_mask */
+	 0x3fffc00,		/* dst_mask */
+	 true),			/* pcrel_offset */
+
+  /* Used in MOVI and SHORI ((x >> 48) & 65536).  */
+  HOWTO (R_SH_IMM_HI16,		/* type */
+	 48,			/* rightshift */
+	 2,			/* size (0 = byte, 1 = short, 2 = long) */
+	 64,			/* bitsize */
+	 false,			/* pc_relative */
+	 10,			/* bitpos */
+	 complain_overflow_dont, /* complain_on_overflow */
+	 bfd_elf_generic_reloc,	/* special_function */
+	 "R_SH_IMM_HI16",	/* name */
+	 false,			/* partial_inplace */
+	 0,			/* src_mask */
+	 0x3fffc00,		/* dst_mask */
+	 false),	       	/* pcrel_offset */
+
+  /* Used in MOVI and SHORI (((x - $) >> 48) & 65536).  */
+  HOWTO (R_SH_IMM_HI16_PCREL,	/* type */
+	 48,			/* rightshift */
+	 2,			/* size (0 = byte, 1 = short, 2 = long) */
+	 64,			/* bitsize */
+	 true,			/* pc_relative */
+	 10,			/* bitpos */
+	 complain_overflow_dont, /* complain_on_overflow */
+	 bfd_elf_generic_reloc,	/* special_function */
+	 "R_SH_IMM_HI16_PCREL", /* name */
+	 false,			/* partial_inplace */
+	 0,			/* src_mask */
+	 0x3fffc00,		/* dst_mask */
+	 true),			/* pcrel_offset */
+
+  /* For the .uaquad pseudo.  */
+  HOWTO (R_SH_64,		/* type */
+	 0,			/* rightshift */
+	 4,			/* size (0 = byte, 1 = short, 2 = long) */
+	 64,			/* bitsize */
+	 false,			/* pc_relative */
+	 0,			/* bitpos */
+	 complain_overflow_dont, /* complain_on_overflow */
+	 bfd_elf_generic_reloc,	/* special_function */
+	 "R_SH_64", 		/* name */
+	 false,			/* partial_inplace */
+	 0,			/* src_mask */
+	 ((bfd_vma) 0) - 1,	/* dst_mask */
+	 false),	       	/* pcrel_offset */
+
+  /* For the .uaquad pseudo, (x - $).  */
+  HOWTO (R_SH_64_PCREL,		/* type */
+	 48,			/* rightshift */
+	 2,			/* size (0 = byte, 1 = short, 2 = long) */
+	 64,			/* bitsize */
+	 true,			/* pc_relative */
+	 10,			/* bitpos */
+	 complain_overflow_dont, /* complain_on_overflow */
+	 bfd_elf_generic_reloc,	/* special_function */
+	 "R_SH_64_PCREL",	/* name */
+	 false,			/* partial_inplace */
+	 0,			/* src_mask */
+	 ((bfd_vma) 0) - 1,	/* dst_mask */
+	 true),			/* pcrel_offset */
+
+};
+
+/* This function is used for relocs which are only used for relaxing,
+   which the linker should otherwise ignore.  */
+
+static bfd_reloc_status_type
+sh_elf64_ignore_reloc (abfd, reloc_entry, symbol, data, input_section,
+		     output_bfd, error_message)
+     bfd *abfd ATTRIBUTE_UNUSED;
+     arelent *reloc_entry;
+     asymbol *symbol ATTRIBUTE_UNUSED;
+     PTR data ATTRIBUTE_UNUSED;
+     asection *input_section;
+     bfd *output_bfd;
+     char **error_message ATTRIBUTE_UNUSED;
+{
+  if (output_bfd != NULL)
+    reloc_entry->address += input_section->output_offset;
+  return bfd_reloc_ok;
+}
+
+/* This function is used for normal relocs.  This used to be like the COFF
+   function, and is almost certainly incorrect for other ELF targets.
+
+   See sh_elf_reloc in elf32-sh.c for the original.  */
+
+static bfd_reloc_status_type
+sh_elf64_reloc (abfd, reloc_entry, symbol_in, data, input_section, output_bfd,
+	  error_message)
+     bfd *abfd;
+     arelent *reloc_entry;
+     asymbol *symbol_in;
+     PTR data;
+     asection *input_section;
+     bfd *output_bfd;
+     char **error_message ATTRIBUTE_UNUSED;
+{
+  unsigned long insn;
+  bfd_vma sym_value;
+  enum elf_sh_reloc_type r_type;
+  bfd_vma addr = reloc_entry->address;
+  bfd_byte *hit_data = addr + (bfd_byte *) data;
+
+  r_type = (enum elf_sh_reloc_type) reloc_entry->howto->type;
+
+  if (output_bfd != NULL)
+    {
+      /* Partial linking--do nothing.  */
+      reloc_entry->address += input_section->output_offset;
+      return bfd_reloc_ok;
+    }
+
+  if (symbol_in != NULL
+      && bfd_is_und_section (symbol_in->section))
+    return bfd_reloc_undefined;
+
+  if (bfd_is_com_section (symbol_in->section))
+    sym_value = 0;                           
+  else 
+    sym_value = (symbol_in->value +
+		 symbol_in->section->output_section->vma +
+		 symbol_in->section->output_offset);
+
+  switch (r_type)
+    {
+    case R_SH_DIR32:
+      insn = bfd_get_32 (abfd, hit_data);
+      insn += sym_value + reloc_entry->addend;
+      bfd_put_32 (abfd, insn, hit_data);
+      break;
+
+    default:
+      abort ();
+      break;
+    }
+
+  return bfd_reloc_ok;
+}
+
+/* This structure is used to map BFD reloc codes to SH ELF relocs.  */
+
+struct elf_reloc_map
+{
+  bfd_reloc_code_real_type bfd_reloc_val;
+  unsigned char elf_reloc_val;
+};
+
+/* An array mapping BFD reloc codes to SH ELF relocs.  */
+
+static const struct elf_reloc_map sh64_reloc_map[] =
+{
+  { BFD_RELOC_NONE, R_SH_NONE },
+  { BFD_RELOC_32, R_SH_DIR32 },
+  { BFD_RELOC_CTOR, R_SH_DIR32 },
+  { BFD_RELOC_32_PCREL, R_SH_REL32 },
+  { BFD_RELOC_8_PCREL, R_SH_SWITCH8 },
+  { BFD_RELOC_SH_SWITCH16, R_SH_SWITCH16 },
+  { BFD_RELOC_SH_SWITCH32, R_SH_SWITCH32 },
+  { BFD_RELOC_VTABLE_INHERIT, R_SH_GNU_VTINHERIT },
+  { BFD_RELOC_VTABLE_ENTRY, R_SH_GNU_VTENTRY },
+  { BFD_RELOC_SH_GOT_LOW16, R_SH_GOT_LOW16 },
+  { BFD_RELOC_SH_GOT_MEDLOW16, R_SH_GOT_MEDLOW16 },
+  { BFD_RELOC_SH_GOT_MEDHI16, R_SH_GOT_MEDHI16 },
+  { BFD_RELOC_SH_GOT_HI16, R_SH_GOT_HI16 },
+  { BFD_RELOC_SH_GOTPLT_LOW16, R_SH_GOTPLT_LOW16 },
+  { BFD_RELOC_SH_GOTPLT_MEDLOW16, R_SH_GOTPLT_MEDLOW16 },
+  { BFD_RELOC_SH_GOTPLT_MEDHI16, R_SH_GOTPLT_MEDHI16 },
+  { BFD_RELOC_SH_GOTPLT_HI16, R_SH_GOTPLT_HI16 },
+  { BFD_RELOC_SH_PLT_LOW16, R_SH_PLT_LOW16 },
+  { BFD_RELOC_SH_PLT_MEDLOW16, R_SH_PLT_MEDLOW16 },
+  { BFD_RELOC_SH_PLT_MEDHI16, R_SH_PLT_MEDHI16 },
+  { BFD_RELOC_SH_PLT_HI16, R_SH_PLT_HI16 },
+  { BFD_RELOC_SH_GOTOFF_LOW16, R_SH_GOTOFF_LOW16 },
+  { BFD_RELOC_SH_GOTOFF_MEDLOW16, R_SH_GOTOFF_MEDLOW16 },
+  { BFD_RELOC_SH_GOTOFF_MEDHI16, R_SH_GOTOFF_MEDHI16 },
+  { BFD_RELOC_SH_GOTOFF_HI16, R_SH_GOTOFF_HI16 },
+  { BFD_RELOC_SH_GOTPC_LOW16, R_SH_GOTPC_LOW16 },
+  { BFD_RELOC_SH_GOTPC_MEDLOW16, R_SH_GOTPC_MEDLOW16 },
+  { BFD_RELOC_SH_GOTPC_MEDHI16, R_SH_GOTPC_MEDHI16 },
+  { BFD_RELOC_SH_GOTPC_HI16, R_SH_GOTPC_HI16 },
+  { BFD_RELOC_SH_COPY64, R_SH_COPY64 },
+  { BFD_RELOC_SH_GLOB_DAT64, R_SH_GLOB_DAT64 },
+  { BFD_RELOC_SH_JMP_SLOT64, R_SH_JMP_SLOT64 },
+  { BFD_RELOC_SH_RELATIVE64, R_SH_RELATIVE64 },
+  { BFD_RELOC_SH_GOT10BY4, R_SH_GOT10BY4 },
+  { BFD_RELOC_SH_GOT10BY8, R_SH_GOT10BY8 },
+  { BFD_RELOC_SH_GOTPLT10BY4, R_SH_GOTPLT10BY4 },
+  { BFD_RELOC_SH_GOTPLT10BY8, R_SH_GOTPLT10BY8 },
+  { BFD_RELOC_SH_PT_16, R_SH_PT_16 },
+  { BFD_RELOC_SH_SHMEDIA_CODE, R_SH_SHMEDIA_CODE },
+  { BFD_RELOC_SH_IMMU5, R_SH_DIR5U },
+  { BFD_RELOC_SH_IMMS6, R_SH_DIR6S },
+  { BFD_RELOC_SH_IMMU6, R_SH_DIR6U },
+  { BFD_RELOC_SH_IMMS10, R_SH_DIR10S },
+  { BFD_RELOC_SH_IMMS10BY2, R_SH_DIR10SW },
+  { BFD_RELOC_SH_IMMS10BY4, R_SH_DIR10SL },
+  { BFD_RELOC_SH_IMMS10BY8, R_SH_DIR10SQ },
+  { BFD_RELOC_SH_IMMS16, R_SH_IMMS16 },
+  { BFD_RELOC_SH_IMMU16, R_SH_IMMU16 },
+  { BFD_RELOC_SH_IMM_LOW16, R_SH_IMM_LOW16 },
+  { BFD_RELOC_SH_IMM_LOW16_PCREL, R_SH_IMM_LOW16_PCREL },
+  { BFD_RELOC_SH_IMM_MEDLOW16, R_SH_IMM_MEDLOW16 },
+  { BFD_RELOC_SH_IMM_MEDLOW16_PCREL, R_SH_IMM_MEDLOW16_PCREL },
+  { BFD_RELOC_SH_IMM_MEDHI16, R_SH_IMM_MEDHI16 },
+  { BFD_RELOC_SH_IMM_MEDHI16_PCREL, R_SH_IMM_MEDHI16_PCREL },
+  { BFD_RELOC_SH_IMM_HI16, R_SH_IMM_HI16 },
+  { BFD_RELOC_SH_IMM_HI16_PCREL, R_SH_IMM_HI16_PCREL },
+  { BFD_RELOC_64, R_SH_64 },
+  { BFD_RELOC_64_PCREL, R_SH_64_PCREL },
+};
+
+/* Given a BFD reloc code, return the howto structure for the
+   corresponding SH ELf reloc.  */
+
+static reloc_howto_type *
+sh_elf64_reloc_type_lookup (abfd, code)
+     bfd *abfd ATTRIBUTE_UNUSED;
+     bfd_reloc_code_real_type code;
+{
+  unsigned int i;
+
+  for (i = 0; i < sizeof (sh64_reloc_map) / sizeof (struct elf_reloc_map); i++)
+    {
+      if (sh64_reloc_map[i].bfd_reloc_val == code)
+	return &sh_elf64_howto_table[(int) sh64_reloc_map[i].elf_reloc_val];
+    }
+
+  return NULL;
+}
+
+/* Given an ELF reloc, fill in the howto field of a relent.
+
+   See sh_elf_info_to_howto in elf32-sh.c for the original.  */
+
+static void
+sh_elf64_info_to_howto (abfd, cache_ptr, dst)
+     bfd *abfd ATTRIBUTE_UNUSED;
+     arelent *cache_ptr;
+     Elf_Internal_Rela *dst;
+{
+  unsigned int r;
+
+  r = ELF64_R_TYPE (dst->r_info);
+
+  BFD_ASSERT (r <= (unsigned int) R_SH_64_PCREL);
+  BFD_ASSERT (r < R_SH_FIRST_INVALID_RELOC || r > R_SH_LAST_INVALID_RELOC);
+  BFD_ASSERT (r < R_SH_DIR8WPN || r > R_SH_LAST_INVALID_RELOC_2);
+  BFD_ASSERT (r < R_SH_FIRST_INVALID_RELOC_3 || r > R_SH_GOTPLT32);
+  BFD_ASSERT (r < R_SH_FIRST_INVALID_RELOC_4 || r > R_SH_LAST_INVALID_RELOC_4);
+
+  cache_ptr->howto = &sh_elf64_howto_table[r];
+}
+
+/* Relocate an SH ELF section.
+
+   See sh_elf_info_to_howto in elf32-sh.c for the original.  */
+
+static boolean
+sh_elf64_relocate_section (output_bfd, info, input_bfd, input_section,
+			   contents, relocs, local_syms, local_sections)
+     bfd *output_bfd ATTRIBUTE_UNUSED;
+     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;
+  struct elf_link_hash_entry **sym_hashes;
+  Elf_Internal_Rela *rel, *relend;
+  bfd *dynobj;
+  bfd_vma *local_got_offsets;
+  asection *sgot;
+  asection *sgotplt;
+  asection *splt;
+  asection *sreloc;
+  bfd_vma disp, dropped;
+
+  symtab_hdr = &elf_tdata (input_bfd)->symtab_hdr;
+  sym_hashes = elf_sym_hashes (input_bfd);
+  dynobj = elf_hash_table (info)->dynobj;
+  local_got_offsets = elf_local_got_offsets (input_bfd);
+
+  sgot = NULL;
+  sgotplt = NULL;
+  splt = NULL;
+  sreloc = NULL;
+
+  rel = relocs;
+  relend = relocs + input_section->reloc_count;
+  for (; rel < relend; rel++)
+    {
+      int r_type;
+      reloc_howto_type *howto;
+      unsigned long r_symndx;
+      Elf_Internal_Sym *sym;
+      asection *sec;
+      struct elf_link_hash_entry *h;
+      bfd_vma relocation;
+      bfd_vma addend = (bfd_vma)0;
+      bfd_reloc_status_type r;
+      int seen_stt_datalabel = 0;
+
+      r_symndx = ELF64_R_SYM (rel->r_info);
+
+      r_type = ELF64_R_TYPE (rel->r_info);
+
+      if (r_type == (int) R_SH_NONE)
+	continue;
+
+      if (r_type < 0
+	  || r_type > R_SH_64_PCREL
+	  || (r_type >= (int) R_SH_FIRST_INVALID_RELOC
+	      && r_type <= (int) R_SH_LAST_INVALID_RELOC)
+	  || (r_type >= (int) R_SH_DIR8WPN
+	      && r_type <= (int) R_SH_LAST_INVALID_RELOC_2)
+	  || (r_type >= (int) R_SH_FIRST_INVALID_RELOC_3
+	      && r_type <= R_SH_GOTPLT32)
+	  || (r_type >= (int) R_SH_FIRST_INVALID_RELOC_4
+	      && r_type <= (int) R_SH_LAST_INVALID_RELOC_4))
+	{
+	  bfd_set_error (bfd_error_bad_value);
+	  return false;
+	}
+
+      howto = sh_elf64_howto_table + r_type;
+
+      /* This is a final link.  */
+      h = NULL;
+      sym = NULL;
+      sec = NULL;
+      if (r_symndx < symtab_hdr->sh_info)
+	{
+	  sym = local_syms + r_symndx;
+	  sec = local_sections[r_symndx];
+	  relocation = ((sec->output_section->vma
+			 + sec->output_offset
+			 + sym->st_value)
+			| ((sym->st_other & STO_SH5_ISA32) != 0));
+
+	  /* A local symbol never has STO_SH5_ISA32, so we don't need
+	     datalabel processing here.  Make sure this does not change
+	     without notice.  */
+	  if ((sym->st_other & STO_SH5_ISA32) != 0)
+	    ((*info->callbacks->reloc_dangerous)
+	     (info,
+	      _("Unexpected STO_SH5_ISA32 on local symbol is not handled"),
+	      input_bfd, input_section, rel->r_offset));
+
+	  if (info->relocateable)
+	    {
+	      /* This is a relocateable link.  We don't have to change
+		 anything, unless the reloc is against a section symbol,
+		 in which case we have to adjust according to where the
+		 section symbol winds up in the output section.  */
+	      sym = local_syms + r_symndx;
+	      if (ELF_ST_TYPE (sym->st_info) == STT_SECTION)
+		goto final_link_relocate;
+
+	      continue;
+	    }
+	}
+      else
+	{
+	  /* Section symbols are never (?) placed in the hash table, so
+	     we can just ignore hash relocations when creating a
+	     relocateable object file.  */
+	  if (info->relocateable)
+	    continue;
+
+	  h = sym_hashes[r_symndx - symtab_hdr->sh_info];
+	  while (h->root.type == bfd_link_hash_indirect
+		 || h->root.type == bfd_link_hash_warning)
+	    {
+	      /* If the reference passes a symbol marked with
+		 STT_DATALABEL, then any STO_SH5_ISA32 on the final value
+		 doesn't count.  */
+	      seen_stt_datalabel |= h->type == STT_DATALABEL;
+	      h = (struct elf_link_hash_entry *) h->root.u.i.link;
+	    }
+
+	  if (h->root.type == bfd_link_hash_defined
+	      || h->root.type == bfd_link_hash_defweak)
+	    {
+	      sec = h->root.u.def.section;
+	      /* In these cases, we don't need the relocation value.
+		 We check specially because in some obscure cases
+		 sec->output_section will be NULL. */
+	      if (r_type == R_SH_GOTPC_LOW16
+		  || r_type == R_SH_GOTPC_MEDLOW16
+		  || r_type == R_SH_GOTPC_MEDHI16
+		  || r_type == R_SH_GOTPC_HI16
+		  || ((r_type == R_SH_PLT_LOW16
+		       || r_type == R_SH_PLT_MEDLOW16
+		       || r_type == R_SH_PLT_MEDHI16
+		       || r_type == R_SH_PLT_HI16)
+		      && h->plt.offset != (bfd_vma) -1)
+		  || ((r_type == R_SH_GOT_LOW16
+		       || r_type == R_SH_GOT_MEDLOW16
+		       || r_type == R_SH_GOT_MEDHI16
+		       || r_type == R_SH_GOT_HI16)
+		      && elf_hash_table (info)->dynamic_sections_created
+		      && (! info->shared
+			  || (! info->symbolic && h->dynindx != -1)
+			  || (h->elf_link_hash_flags
+			      & ELF_LINK_HASH_DEF_REGULAR) == 0))
+		  /* The cases above are those in which relocation is
+		     overwritten in the switch block below.  The cases
+		     below are those in which we must defer relocation
+		     to run-time, because we can't resolve absolute
+		     addresses when creating a shared library.  */
+		  || (info->shared
+		      && ((! info->symbolic && h->dynindx != -1)
+			  || (h->elf_link_hash_flags
+			      & ELF_LINK_HASH_DEF_REGULAR) == 0)
+		      && ((r_type == R_SH_64
+			   && !(ELF_ST_VISIBILITY (h->other) == STV_INTERNAL
+				|| ELF_ST_VISIBILITY (h->other) == STV_HIDDEN))
+			  || r_type == R_SH_64_PCREL)
+		      && ((input_section->flags & SEC_ALLOC) != 0
+			  /* DWARF will emit R_SH_DIR32 relocations in its
+			     sections against symbols defined externally
+			     in shared libraries.  We can't do anything
+			     with them here.  */
+			  || (input_section->flags & SEC_DEBUGGING) != 0)))
+		relocation = 0;
+	      else if (sec->output_section == NULL)
+		{
+		  (*_bfd_error_handler)
+		    (_("%s: warning: unresolvable relocation against symbol `%s' from %s section"),
+		     bfd_get_filename (input_bfd), h->root.root.string,
+		     bfd_get_section_name (input_bfd, input_section));
+		  relocation = 0;
+		}
+	      else
+		relocation = ((h->root.u.def.value
+			       + sec->output_section->vma
+			       + sec->output_offset)
+			      /* A STO_SH5_ISA32 causes a "bitor 1" to the
+				 symbol value, unless we've seen
+				 STT_DATALABEL on the way to it.  */
+			      | ((h->other & STO_SH5_ISA32) != 0
+				 && ! seen_stt_datalabel));
+	    }
+	  else if (h->root.type == bfd_link_hash_undefweak)
+	    relocation = 0;
+	  else if (info->shared && !info->symbolic && !info->no_undefined)
+	    relocation = 0;
+	  else
+	    {
+	      if (! ((*info->callbacks->undefined_symbol)
+		     (info, h->root.root.string, input_bfd,
+		      input_section, rel->r_offset, true)))
+		return false;
+	      relocation = 0;
+	    }
+	}
+
+      disp = (relocation
+	      - input_section->output_section->vma
+	      - input_section->output_offset
+	      - rel->r_offset);
+      dropped = 0;
+      switch ((int)r_type)
+	{
+	case R_SH_PT_16:     dropped = disp & 2; break;
+	case R_SH_DIR10SW: dropped = disp & 1; break;
+	case R_SH_DIR10SL: dropped = disp & 3; break;
+	case R_SH_DIR10SQ: dropped = disp & 7; break;
+	}
+      if (dropped != 0)
+	{
+	  (*_bfd_error_handler)
+	    (_("%s: error: unaligned relocation type %d at %08x reloc %08x\n"),
+	     bfd_get_filename (input_bfd), (int)r_type, (unsigned)rel->r_offset, (unsigned)relocation);
+	  bfd_set_error (bfd_error_bad_value);
+	  return false;
+	}
+      switch ((int)r_type)
+	{
+	case R_SH_64:
+	case R_SH_64_PCREL:
+	  if (info->shared
+	      && (input_section->flags & SEC_ALLOC) != 0
+	      && (r_type != R_SH_64_PCREL
+		  || (h != NULL
+		      && h->dynindx != -1
+		      && (! info->symbolic
+			  || (h->elf_link_hash_flags
+			      & ELF_LINK_HASH_DEF_REGULAR) == 0))))
+	    {
+	      Elf_Internal_Rela outrel;
+	      boolean skip, relocate;
+
+	      /* When generating a shared object, these relocations
+		 are copied into the output file to be resolved at run
+		 time.  */
+
+	      if (sreloc == NULL)
+		{
+		  const char *name;
+
+		  name = (bfd_elf_string_from_elf_section
+			  (input_bfd,
+			   elf_elfheader (input_bfd)->e_shstrndx,
+			   elf_section_data (input_section)->rel_hdr.sh_name));
+		  if (name == NULL)
+		    return false;
+
+		  BFD_ASSERT (strncmp (name, ".rela", 5) == 0
+			      && strcmp (bfd_get_section_name (input_bfd,
+							       input_section),
+					 name + 5) == 0);
+
+		  sreloc = bfd_get_section_by_name (dynobj, name);
+		  BFD_ASSERT (sreloc != NULL);
+		}
+
+	      skip = false;
+
+	      outrel.r_offset
+		= _bfd_elf_section_offset (output_bfd,
+					   &elf_hash_table (info)->stab_info,
+					   input_section,
+					   rel->r_offset);
+
+	      if (outrel.r_offset == (bfd_vma) -1)
+		skip = true;
+	      
+	      outrel.r_offset += (input_section->output_section->vma
+				  + input_section->output_offset);
+
+	      if (skip)
+		{
+		  memset (&outrel, 0, sizeof outrel);
+		  relocate = false;
+		}
+	      else if (r_type == R_SH_64_PCREL)
+		{
+		  BFD_ASSERT (h != NULL && h->dynindx != -1);
+		  relocate = false;
+		  outrel.r_info = ELF64_R_INFO (h->dynindx, R_SH_64_PCREL);
+		  outrel.r_addend = rel->r_addend;
+		}
+	      else
+		{
+		  /* h->dynindx may be -1 if this symbol was marked to
+		     become local.  */
+		  if (h == NULL
+		      || ((info->symbolic || h->dynindx == -1)
+			  && (h->elf_link_hash_flags
+			      & ELF_LINK_HASH_DEF_REGULAR) != 0))
+		    {
+		      relocate = true;
+		      outrel.r_info = ELF64_R_INFO (0, R_SH_RELATIVE64);
+		      outrel.r_addend = relocation + rel->r_addend;
+		    }
+		  else
+		    {
+		      BFD_ASSERT (h->dynindx != -1);
+		      relocate = false;
+		      outrel.r_info = ELF64_R_INFO (h->dynindx, R_SH_64);
+		      outrel.r_addend = relocation + rel->r_addend;
+		    }
+		}
+
+	      bfd_elf64_swap_reloca_out (output_bfd, &outrel,
+					 (((Elf64_External_Rela *)
+					   sreloc->contents)
+					  + sreloc->reloc_count));
+	      ++sreloc->reloc_count;
+
+	      /* If this reloc is against an external symbol, we do
+		 not want to fiddle with the addend.  Otherwise, we
+		 need to include the symbol value so that it becomes
+		 an addend for the dynamic reloc.  */
+	      if (! relocate)
+		continue;
+	    }
+	  else if (r_type == R_SH_64)
+	    addend = rel->r_addend;
+	  goto final_link_relocate;
+
+	case R_SH_GOTPLT_LOW16:
+	case R_SH_GOTPLT_MEDLOW16:
+	case R_SH_GOTPLT_MEDHI16:
+	case R_SH_GOTPLT_HI16:
+	case R_SH_GOTPLT10BY4:
+	case R_SH_GOTPLT10BY8:
+	  /* Relocation is to the entry for this symbol in the
+	     procedure linkage table.  */
+
+	  if (h == NULL
+	      || ELF_ST_VISIBILITY (h->other) == STV_INTERNAL
+	      || ELF_ST_VISIBILITY (h->other) == STV_HIDDEN
+	      || ! info->shared
+	      || info->symbolic
+	      || h->dynindx == -1
+	      || h->plt.offset == (bfd_vma) -1
+	      || h->got.offset != (bfd_vma) -1)
+	    goto force_got;
+
+	  /* Relocation is to the entry for this symbol in the global
+	     offset table extension for the procedure linkage table.  */
+	  if (sgotplt == NULL)
+	    {
+	      sgotplt = bfd_get_section_by_name (dynobj, ".got.plt");
+	      BFD_ASSERT (sgotplt != NULL);
+	    }
+
+	  relocation = (sgotplt->output_offset
+			+ ((h->plt.offset / elf_sh64_sizeof_plt (info)
+			    - 1 + 3) * 8));
+
+	  relocation -= GOT_BIAS;
+
+	  goto final_link_relocate;
+
+	force_got:
+	case R_SH_GOT_LOW16:
+	case R_SH_GOT_MEDLOW16:
+	case R_SH_GOT_MEDHI16:
+	case R_SH_GOT_HI16:
+	case R_SH_GOT10BY4:
+	case R_SH_GOT10BY8:
+	  /* Relocation is to the entry for this symbol in the global
+	     offset table.  */
+	  if (sgot == NULL)
+	    {
+	      sgot = bfd_get_section_by_name (dynobj, ".got");
+	      BFD_ASSERT (sgot != NULL);
+	    }
+
+	  if (h != NULL)
+	    {
+	      bfd_vma off;
+
+	      off = h->got.offset;
+	      if (seen_stt_datalabel)
+		{
+		  struct elf_sh64_link_hash_entry *hsh;
+
+		  hsh = (struct elf_sh64_link_hash_entry *)h;
+		  off = hsh->datalabel_got_offset;
+		}
+	      BFD_ASSERT (off != (bfd_vma) -1);
+
+	      if (! elf_hash_table (info)->dynamic_sections_created
+		  || (info->shared
+		      && (info->symbolic || h->dynindx == -1
+			  || ELF_ST_VISIBILITY (h->other) == STV_INTERNAL
+			  || ELF_ST_VISIBILITY (h->other) == STV_HIDDEN)
+		      && (h->elf_link_hash_flags & ELF_LINK_HASH_DEF_REGULAR)))
+		{
+		  /* This is actually a static link, or it is a
+		     -Bsymbolic link and the symbol is defined
+		     locally, or the symbol was forced to be local
+		     because of a version file.  We must initialize
+		     this entry in the global offset table.  Since the
+		     offset must always be a multiple of 4, we use the
+		     least significant bit to record whether we have
+		     initialized it already.
+
+		     When doing a dynamic link, we create a .rela.got
+		     relocation entry to initialize the value.  This
+		     is done in the finish_dynamic_symbol routine.  */
+		  if ((off & 1) != 0)
+		    off &= ~1;
+		  else
+		    {
+		      bfd_put_64 (output_bfd, relocation,
+				  sgot->contents + off);
+		      if (seen_stt_datalabel)
+			{
+			  struct elf_sh64_link_hash_entry *hsh;
+
+			  hsh = (struct elf_sh64_link_hash_entry *)h;
+			  hsh->datalabel_got_offset |= 1;
+			}
+		      else
+			h->got.offset |= 1;
+		    }
+		}
+
+	      relocation = sgot->output_offset + off;
+	    }
+	  else
+	    {
+	      bfd_vma off;
+
+	      if (rel->r_addend)
+		{
+		  BFD_ASSERT (local_got_offsets != NULL
+			      && (local_got_offsets[symtab_hdr->sh_info
+						    + r_symndx]
+				  != (bfd_vma) -1));
+
+		  off = local_got_offsets[symtab_hdr->sh_info
+					  + r_symndx];
+		}
+	      else
+		{
+		  BFD_ASSERT (local_got_offsets != NULL
+			      && local_got_offsets[r_symndx] != (bfd_vma) -1);
+
+		  off = local_got_offsets[r_symndx];
+		}
+
+	      /* The offset must always be a multiple of 8.  We use
+		 the least significant bit to record whether we have
+		 already generated the necessary reloc.  */
+	      if ((off & 1) != 0)
+		off &= ~1;
+	      else
+		{
+		  bfd_put_64 (output_bfd, relocation, sgot->contents + off);
+
+		  if (info->shared)
+		    {
+		      asection *srelgot;
+		      Elf_Internal_Rela outrel;
+
+		      srelgot = bfd_get_section_by_name (dynobj, ".rela.got");
+		      BFD_ASSERT (srelgot != NULL);
+
+		      outrel.r_offset = (sgot->output_section->vma
+					 + sgot->output_offset
+					 + off);
+		      outrel.r_info = ELF64_R_INFO (0, R_SH_RELATIVE64);
+		      outrel.r_addend = relocation;
+		      bfd_elf64_swap_reloca_out (output_bfd, &outrel,
+						(((Elf64_External_Rela *)
+						  srelgot->contents)
+						 + srelgot->reloc_count));
+		      ++srelgot->reloc_count;
+		    }
+
+		  if (rel->r_addend)
+		    local_got_offsets[symtab_hdr->sh_info + r_symndx] |= 1;
+		  else
+		    local_got_offsets[r_symndx] |= 1;
+		}
+
+	      relocation = sgot->output_offset + off;
+	    }
+
+ 	  relocation -= GOT_BIAS;
+
+	  goto final_link_relocate;
+
+	case R_SH_GOTOFF_LOW16:
+	case R_SH_GOTOFF_MEDLOW16:
+	case R_SH_GOTOFF_MEDHI16:
+	case R_SH_GOTOFF_HI16:
+	  /* Relocation is relative to the start of the global offset
+	     table.  */
+
+	  if (sgot == NULL)
+	    {
+	      sgot = bfd_get_section_by_name (dynobj, ".got");
+	      BFD_ASSERT (sgot != NULL);
+	    }
+
+	  /* Note that sgot->output_offset is not involved in this
+	     calculation.  We always want the start of .got.  If we
+	     defined _GLOBAL_OFFSET_TABLE in a different way, as is
+	     permitted by the ABI, we might have to change this
+	     calculation.  */
+	  relocation -= sgot->output_section->vma;
+
+	  relocation -= GOT_BIAS;
+
+	  addend = rel->r_addend;
+
+	  goto final_link_relocate;
+
+	case R_SH_GOTPC_LOW16:
+	case R_SH_GOTPC_MEDLOW16:
+	case R_SH_GOTPC_MEDHI16:
+	case R_SH_GOTPC_HI16:
+	  /* Use global offset table as symbol value.  */
+
+	  if (sgot == NULL)
+	    {
+	      sgot = bfd_get_section_by_name (dynobj, ".got");
+	      BFD_ASSERT (sgot != NULL);
+	    }
+
+	  relocation = sgot->output_section->vma;
+
+	  relocation += GOT_BIAS;
+
+	  addend = rel->r_addend;
+
+	  goto final_link_relocate;
+
+	case R_SH_PLT_LOW16:
+	case R_SH_PLT_MEDLOW16:
+	case R_SH_PLT_MEDHI16:
+	case R_SH_PLT_HI16:
+	  /* Relocation is to the entry for this symbol in the
+	     procedure linkage table.  */
+
+	  /* Resolve a PLT reloc against a local symbol directly,
+	     without using the procedure linkage table.  */
+	  if (h == NULL)
+	    goto final_link_relocate;
+
+	  if (ELF_ST_VISIBILITY (h->other) == STV_INTERNAL
+	      || ELF_ST_VISIBILITY (h->other) == STV_HIDDEN)
+	    goto final_link_relocate;
+
+	  if (h->plt.offset == (bfd_vma) -1)
+	    {
+	      /* We didn't make a PLT entry for this symbol.  This
+		 happens when statically linking PIC code, or when
+		 using -Bsymbolic.  */
+	      goto final_link_relocate;
+	    }
+
+	  if (splt == NULL)
+	    {
+	      splt = bfd_get_section_by_name (dynobj, ".plt");
+	      BFD_ASSERT (splt != NULL);
+	    }
+
+	  relocation = (splt->output_section->vma
+			+ splt->output_offset
+			+ h->plt.offset);
+	  relocation++;
+
+	  addend = rel->r_addend;
+
+	  goto final_link_relocate;
+
+	case R_SH_DIR32:
+	case R_SH_SHMEDIA_CODE:
+	case R_SH_PT_16:
+	case R_SH_DIR5U:
+	case R_SH_DIR6S:
+	case R_SH_DIR6U:
+	case R_SH_DIR10S:
+	case R_SH_DIR10SW:
+	case R_SH_DIR10SL:
+	case R_SH_DIR10SQ:
+	case R_SH_IMMS16:
+	case R_SH_IMMU16:
+	case R_SH_IMM_LOW16:
+	case R_SH_IMM_LOW16_PCREL:
+	case R_SH_IMM_MEDLOW16:
+	case R_SH_IMM_MEDLOW16_PCREL:
+	case R_SH_IMM_MEDHI16:
+	case R_SH_IMM_MEDHI16_PCREL:
+	case R_SH_IMM_HI16:
+	case R_SH_IMM_HI16_PCREL:
+	  addend = rel->r_addend;
+	  /* Fall through.  */
+	case R_SH_REL32:
+	final_link_relocate:
+	  r = _bfd_final_link_relocate (howto, input_bfd, input_section,
+					contents, rel->r_offset,
+					relocation, addend);
+	  break;
+
+	default:
+	  bfd_set_error (bfd_error_bad_value);
+	  return false;
+
+	}
+
+      if (r != bfd_reloc_ok)
+	{
+	  switch (r)
+	    {
+	    default:
+	    case bfd_reloc_outofrange:
+	      abort ();
+	    case bfd_reloc_overflow:
+	      {
+		const char *name;
+
+		if (h != NULL)
+		  name = h->root.root.string;
+		else
+		  {
+		    name = (bfd_elf_string_from_elf_section
+			    (input_bfd, symtab_hdr->sh_link, sym->st_name));
+		    if (name == NULL)
+		      return false;
+		    if (*name == '\0')
+		      name = bfd_section_name (input_bfd, sec);
+		  }
+		if (! ((*info->callbacks->reloc_overflow)
+		       (info, name, howto->name, (bfd_vma) 0,
+			input_bfd, input_section, rel->r_offset)))
+		  return false;
+	      }
+	      break;
+	    }
+	}
+    }
+
+  return true;
+}
+
+/* This is a version of bfd_generic_get_relocated_section_contents
+   that uses sh_elf64_relocate_section.
+
+   See sh_elf_relocate_section in elf32-sh.c for the original.  */
+
+static bfd_byte *
+sh_elf64_get_relocated_section_contents (output_bfd, link_info, link_order,
+					 data, relocateable, symbols)
+     bfd *output_bfd;
+     struct bfd_link_info *link_info;
+     struct bfd_link_order *link_order;
+     bfd_byte *data;
+     boolean relocateable;
+     asymbol **symbols;
+{
+  Elf_Internal_Shdr *symtab_hdr;
+  Elf_Internal_Shdr *shndx_hdr;
+  asection *input_section = link_order->u.indirect.section;
+  bfd *input_bfd = input_section->owner;
+  asection **sections = NULL;
+  Elf_Internal_Rela *internal_relocs = NULL;
+  Elf64_External_Sym *external_syms = NULL;
+  Elf_External_Sym_Shndx *shndx_buf = NULL;
+  Elf_External_Sym_Shndx *shndx;
+  Elf_Internal_Sym *internal_syms = NULL;
+
+  /* We only need to handle the case of relaxing, or of having a
+     particular set of section contents, specially.  */
+  if (relocateable
+      || elf_section_data (input_section)->this_hdr.contents == NULL)
+    return bfd_generic_get_relocated_section_contents (output_bfd, link_info,
+						       link_order, data,
+						       relocateable,
+						       symbols);
+
+  symtab_hdr = &elf_tdata (input_bfd)->symtab_hdr;
+  shndx_hdr  = &elf_tdata (input_bfd)->symtab_shndx_hdr;
+
+  memcpy (data, elf_section_data (input_section)->this_hdr.contents,
+	  input_section->_raw_size);
+
+  if ((input_section->flags & SEC_RELOC) != 0
+      && input_section->reloc_count > 0)
+    {
+      Elf_Internal_Sym *isymp;
+      asection **secpp;
+      Elf64_External_Sym *esym, *esymend;
+      bfd_size_type amt;
+
+      if (symtab_hdr->contents != NULL)
+	external_syms = (Elf64_External_Sym *) symtab_hdr->contents;
+      else
+	{
+	  amt = symtab_hdr->sh_info;
+	  amt *= sizeof (Elf64_External_Sym);
+
+	  external_syms = (Elf64_External_Sym *) bfd_malloc (amt);
+	  if (external_syms == NULL && symtab_hdr->sh_info > 0)
+	    goto error_return;
+
+	  if (bfd_seek (input_bfd, symtab_hdr->sh_offset, SEEK_SET) != 0
+	      || (bfd_bread ((PTR) external_syms, amt, input_bfd) != amt))
+	    goto error_return;
+	}
+
+      if (symtab_hdr->sh_info != 0 && shndx_hdr->sh_size != 0)
+	{
+	  amt = symtab_hdr->sh_info;
+	  amt *= sizeof (Elf_External_Sym_Shndx);
+
+	  shndx_buf = (Elf_External_Sym_Shndx *) bfd_malloc (amt);
+	  if (shndx_buf == NULL)
+	    goto error_return;
+
+	  if (bfd_seek (input_bfd, shndx_hdr->sh_offset, SEEK_SET) != 0
+	      || bfd_bread ((PTR) shndx_buf, amt, input_bfd) != amt)
+	    goto error_return;
+	}
+
+      internal_relocs = (_bfd_elf64_link_read_relocs
+			 (input_bfd, input_section, (PTR) NULL,
+			  (Elf_Internal_Rela *) NULL, false));
+      if (internal_relocs == NULL)
+	goto error_return;
+
+      internal_syms = ((Elf_Internal_Sym *)
+		       bfd_malloc (symtab_hdr->sh_info
+				   * sizeof (Elf_Internal_Sym)));
+      if (internal_syms == NULL && symtab_hdr->sh_info > 0)
+	goto error_return;
+
+      sections = (asection **) bfd_malloc (symtab_hdr->sh_info
+					   * sizeof (asection *));
+      if (sections == NULL && symtab_hdr->sh_info > 0)
+	goto error_return;
+
+      isymp = internal_syms;
+      secpp = sections;
+      esym = external_syms;
+      esymend = esym + symtab_hdr->sh_info;
+      shndx = shndx_buf;
+      for (; esym < esymend;
+	   ++esym, ++isymp, ++secpp, shndx = (shndx ? shndx + 1 : NULL))
+	{
+	  asection *isec;
+
+	  bfd_elf64_swap_symbol_in (input_bfd, esym, shndx, isymp);
+
+	  if (isymp->st_shndx == SHN_UNDEF)
+	    isec = bfd_und_section_ptr;
+	  else if (isymp->st_shndx > 0 && isymp->st_shndx < SHN_LORESERVE)
+	    isec = bfd_section_from_elf_index (input_bfd, isymp->st_shndx);
+	  else if (isymp->st_shndx == SHN_ABS)
+	    isec = bfd_abs_section_ptr;
+	  else if (isymp->st_shndx == SHN_COMMON)
+	    isec = bfd_com_section_ptr;
+	  else
+	    {
+	      /* Who knows?  */
+	      isec = NULL;
+	    }
+
+	  *secpp = isec;
+	}
+
+      if (! sh_elf64_relocate_section (output_bfd, link_info, input_bfd,
+				       input_section, data, internal_relocs,
+				       internal_syms, sections))
+	goto error_return;
+
+      if (sections != NULL)
+	free (sections);
+      sections = NULL;
+      if (internal_syms != NULL)
+	free (internal_syms);
+      internal_syms = NULL;
+      if (external_syms != NULL && symtab_hdr->contents == NULL)
+	free (external_syms);
+      external_syms = NULL;
+      if (internal_relocs != elf_section_data (input_section)->relocs)
+	free (internal_relocs);
+      internal_relocs = NULL;
+    }
+
+  return data;
+
+ error_return:
+  if (internal_relocs != NULL
+      && internal_relocs != elf_section_data (input_section)->relocs)
+    free (internal_relocs);
+  if (external_syms != NULL && symtab_hdr->contents == NULL)
+    free (external_syms);
+  if (internal_syms != NULL)
+    free (internal_syms);
+  if (sections != NULL)
+    free (sections);
+  return NULL;
+}
+
+/* Set the SHF_SH5_ISA32 flag for ISA SHmedia code sections.  */
+
+boolean
+sh64_elf64_fake_sections (output_bfd, elf_section_hdr, asect)
+     bfd *output_bfd ATTRIBUTE_UNUSED;
+     Elf_Internal_Shdr *elf_section_hdr;
+     asection *asect;
+{
+  /* Code sections can only contain SH64 code, so mark them as such.  */
+  if (bfd_get_section_flags (output_bfd, asect) & SEC_CODE)
+    elf_section_hdr->sh_flags |= SHF_SH5_ISA32;
+
+  return true;
+}
+
+static boolean
+sh_elf64_set_mach_from_flags (abfd)
+     bfd *abfd;
+{
+  flagword flags = elf_elfheader (abfd)->e_flags;
+
+  switch (flags & EF_SH_MACH_MASK)
+    {
+    case EF_SH5:
+      /* Just one, but keep the switch construct to make additions easy.  */
+      bfd_default_set_arch_mach (abfd, bfd_arch_sh, bfd_mach_sh5);
+      break;
+
+    default:
+      bfd_set_error (bfd_error_wrong_format);
+      return false;
+    }
+  return true;
+}
+
+/* Function to keep SH64 specific file flags.
+
+   See sh64_elf_set_private_flags in elf32-sh64.c for the original.  */
+
+static boolean
+sh_elf64_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_elf64_set_mach_from_flags (abfd);
+}
+
+/* Copy the SHF_SH5_ISA32 attribute that we keep on all sections with
+   code, to keep attributes the same as for SHmedia in 32-bit ELF.  */
+
+static boolean
+sh_elf64_copy_private_data_internal (ibfd, obfd)
+     bfd * ibfd;
+     bfd * obfd;
+{
+  Elf_Internal_Shdr **o_shdrp;
+  asection *isec;
+  asection *osec;
+
+  if (bfd_get_flavour (ibfd) != bfd_target_elf_flavour
+      || bfd_get_flavour (obfd) != bfd_target_elf_flavour)
+    return true;
+
+  o_shdrp = elf_elfsections (obfd);
+  for (osec = obfd->sections; osec; osec = osec->next)
+    {
+      int oIndex = ((struct bfd_elf_section_data *) elf_section_data (osec))->this_idx;
+      for (isec = ibfd->sections; isec; isec = isec->next)
+	{
+	  if (strcmp (osec->name, isec->name) == 0)
+	    {
+	      /* Note that we're not disallowing mixing data and code.  */
+	      if ((elf_section_data (isec)->this_hdr.sh_flags
+		   & SHF_SH5_ISA32) != 0)
+		o_shdrp[oIndex]->sh_flags |= SHF_SH5_ISA32;
+	      break;
+	    }
+	}
+    }
+
+  return sh_elf64_set_private_flags (obfd, elf_elfheader (ibfd)->e_flags);
+}
+
+static boolean
+sh_elf64_copy_private_data (ibfd, obfd)
+     bfd * ibfd;
+     bfd * obfd;
+{
+  return sh_elf64_copy_private_data_internal (ibfd, obfd);
+}
+
+static boolean
+sh_elf64_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 (bfd_get_arch_size (ibfd) != bfd_get_arch_size (obfd))
+    {
+      const char *msg;
+
+      if (bfd_get_arch_size (ibfd) == 32
+	  && bfd_get_arch_size (obfd) == 64)
+	msg = _("%s: compiled as 32-bit object and %s is 64-bit");
+      else if (bfd_get_arch_size (ibfd) == 64
+	       && bfd_get_arch_size (obfd) == 32)
+	msg = _("%s: compiled as 64-bit object and %s is 32-bit");
+      else
+	msg = _("%s: object size does not match that of target %s");
+
+      (*_bfd_error_handler) (msg, bfd_get_filename (ibfd),
+			     bfd_get_filename (obfd));
+      bfd_set_error (bfd_error_wrong_format);
+      return false;
+    }
+
+  old_flags = elf_elfheader (obfd)->e_flags;
+  new_flags = elf_elfheader (ibfd)->e_flags;
+  if (! elf_flags_init (obfd))
+    {
+      /* This happens when ld starts out with a 'blank' output file.  */
+      elf_flags_init (obfd) = true;
+      elf_elfheader (obfd)->e_flags = old_flags = new_flags;
+    }
+  /* We don't allow linking in anything else than SH64 code, and since
+     this is a 64-bit ELF, we assume the 64-bit ABI is used.  Add code
+     here as things change.  */
+  else if ((new_flags & EF_SH_MACH_MASK) != EF_SH5)
+    {
+      (*_bfd_error_handler)
+	("%s: does not use the SH64 64-bit ABI as previous modules do",
+	 bfd_get_filename (ibfd));
+      bfd_set_error (bfd_error_bad_value);
+      return false;
+    }
+
+  sh_elf64_copy_private_data_internal (ibfd, obfd);
+
+  /* I can't think of anything sane other than old_flags being EF_SH5 and
+     that we need to preserve that.  */
+  elf_elfheader (obfd)->e_flags = old_flags;
+
+  return sh_elf64_set_mach_from_flags (obfd);
+}
+
+/* Return the section that should be marked against GC for a given
+   relocation.  */
+
+static asection *
+sh_elf64_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 (ELF64_R_TYPE (rel->r_info))
+	{
+	case R_SH_GNU_VTINHERIT:
+	case R_SH_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
+sh_elf64_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;
+{
+  /* No got and plt entries for 64-bit SH at present.  */
+  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
+sh_elf64_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;
+  bfd *dynobj;
+  bfd_vma *local_got_offsets;
+  asection *sgot;
+  asection *srelgot;
+  asection *sreloc;
+
+  sgot = NULL;
+  srelgot = NULL;
+  sreloc = NULL;
+
+  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(Elf64_External_Sym);
+  if (!elf_bad_symtab (abfd))
+    sym_hashes_end -= symtab_hdr->sh_info;
+ 
+  dynobj = elf_hash_table (info)->dynobj;
+  local_got_offsets = elf_local_got_offsets (abfd);
+
+  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 = ELF64_R_SYM (rel->r_info);
+      if (r_symndx < symtab_hdr->sh_info)
+        h = NULL;
+      else
+        h = sym_hashes[r_symndx - symtab_hdr->sh_info];
+ 
+      /* Some relocs require a global offset table.  */
+      if (dynobj == NULL)
+	{
+	  switch (ELF64_R_TYPE (rel->r_info))
+	    {
+	    case R_SH_GOTPLT_LOW16:
+	    case R_SH_GOTPLT_MEDLOW16:
+	    case R_SH_GOTPLT_MEDHI16:
+	    case R_SH_GOTPLT_HI16:
+	    case R_SH_GOTPLT10BY4:
+	    case R_SH_GOTPLT10BY8:
+	    case R_SH_GOT_LOW16:
+	    case R_SH_GOT_MEDLOW16:
+	    case R_SH_GOT_MEDHI16:
+	    case R_SH_GOT_HI16:
+	    case R_SH_GOT10BY4:
+	    case R_SH_GOT10BY8:
+	    case R_SH_GOTOFF_LOW16:
+	    case R_SH_GOTOFF_MEDLOW16:
+	    case R_SH_GOTOFF_MEDHI16:
+	    case R_SH_GOTOFF_HI16:
+	    case R_SH_GOTPC_LOW16:
+	    case R_SH_GOTPC_MEDLOW16:
+	    case R_SH_GOTPC_MEDHI16:
+	    case R_SH_GOTPC_HI16:
+	      elf_hash_table (info)->dynobj = dynobj = abfd;
+	      if (! _bfd_elf_create_got_section (dynobj, info))
+		return false;
+	      break;
+
+	    default:
+	      break;
+	    }
+	}
+
+      switch (ELF64_R_TYPE (rel->r_info))
+        {
+	  /* This relocation describes the C++ object vtable hierarchy.
+	     Reconstruct it for later use during GC.  */
+        case R_SH_GNU_VTINHERIT:
+          if (!_bfd_elf64_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_SH_GNU_VTENTRY:
+          if (!_bfd_elf64_gc_record_vtentry (abfd, sec, h, rel->r_addend))
+            return false;
+          break;
+
+	force_got:
+	case R_SH_GOT_LOW16:
+	case R_SH_GOT_MEDLOW16:
+	case R_SH_GOT_MEDHI16:
+	case R_SH_GOT_HI16:
+	case R_SH_GOT10BY4:
+	case R_SH_GOT10BY8:
+	  /* This symbol requires a global offset table entry.  */
+
+	  if (sgot == NULL)
+	    {
+	      sgot = bfd_get_section_by_name (dynobj, ".got");
+	      BFD_ASSERT (sgot != NULL);
+	    }
+
+	  if (srelgot == NULL
+	      && (h != NULL || info->shared))
+	    {
+	      srelgot = bfd_get_section_by_name (dynobj, ".rela.got");
+	      if (srelgot == NULL)
+		{
+		  srelgot = bfd_make_section (dynobj, ".rela.got");
+		  if (srelgot == NULL
+		      || ! bfd_set_section_flags (dynobj, srelgot,
+						  (SEC_ALLOC
+						   | SEC_LOAD
+						   | SEC_HAS_CONTENTS
+						   | SEC_IN_MEMORY
+						   | SEC_LINKER_CREATED
+						   | SEC_READONLY))
+		      || ! bfd_set_section_alignment (dynobj, srelgot, 2))
+		    return false;
+		}
+	    }
+
+	  if (h != NULL)
+	    {
+	      if (h->type == STT_DATALABEL)
+		{
+		  struct elf_sh64_link_hash_entry *hsh;
+
+		  h = (struct elf_link_hash_entry *) h->root.u.i.link;
+		  hsh = (struct elf_sh64_link_hash_entry *)h;
+		  if (hsh->datalabel_got_offset != (bfd_vma) -1)
+		    break;
+
+		  hsh->datalabel_got_offset = sgot->_raw_size;
+		}
+	      else
+		{
+		  if (h->got.offset != (bfd_vma) -1)
+		    {
+		      /* We have already allocated space in the .got.  */
+		      break;
+		    }
+		  h->got.offset = sgot->_raw_size;
+		}
+
+	      /* Make sure this symbol is output as a dynamic symbol.  */
+	      if (h->dynindx == -1)
+		{
+		  if (! bfd_elf64_link_record_dynamic_symbol (info, h))
+		    return false;
+		}
+
+	      srelgot->_raw_size += sizeof (Elf64_External_Rela);
+	    }
+	  else
+	    {
+     	      /* This is a global offset table entry for a local
+		 symbol.  */
+	      if (local_got_offsets == NULL)
+		{
+		  size_t size;
+		  register unsigned int i;
+
+		  size = symtab_hdr->sh_info * sizeof (bfd_vma);
+		  /* Reserve space for both the datalabel and
+		     codelabel local GOT offsets.  */
+		  size *= 2;
+		  local_got_offsets = (bfd_vma *) bfd_alloc (abfd, size);
+		  if (local_got_offsets == NULL)
+		    return false;
+		  elf_local_got_offsets (abfd) = local_got_offsets;
+		  for (i = 0; i < symtab_hdr->sh_info; i++)
+		    local_got_offsets[i] = (bfd_vma) -1;
+		  for (; i < 2 * symtab_hdr->sh_info; i++)
+		    local_got_offsets[i] = (bfd_vma) -1;
+		}
+	      if ((rel->r_addend & 1) != 0)
+		{
+		  if (local_got_offsets[symtab_hdr->sh_info
+					+ r_symndx] != (bfd_vma) -1)
+		    {
+		      /* We have already allocated space in the .got.  */
+		      break;
+		    }
+		  local_got_offsets[symtab_hdr->sh_info
+				    + r_symndx] = sgot->_raw_size;
+		}
+	      else
+		{
+		  if (local_got_offsets[r_symndx] != (bfd_vma) -1)
+		    {
+		      /* We have already allocated space in the .got.  */
+		      break;
+		    }
+		  local_got_offsets[r_symndx] = sgot->_raw_size;
+		}
+
+	      if (info->shared)
+		{
+		  /* If we are generating a shared object, we need to
+		     output a R_SH_RELATIVE reloc so that the dynamic
+		     linker can adjust this GOT entry.  */
+		  srelgot->_raw_size += sizeof (Elf64_External_Rela);
+		}
+	    }
+
+	  sgot->_raw_size += 8;
+
+	  break;
+
+	case R_SH_GOTPLT_LOW16:
+	case R_SH_GOTPLT_MEDLOW16:
+	case R_SH_GOTPLT_MEDHI16:
+	case R_SH_GOTPLT_HI16:
+	case R_SH_GOTPLT10BY4:
+	case R_SH_GOTPLT10BY8:
+	  /* If this is a local symbol, we resolve it directly without
+	     creating a procedure linkage table entry.  */
+
+	  if (h == NULL
+	      || ELF_ST_VISIBILITY (h->other) == STV_INTERNAL
+	      || ELF_ST_VISIBILITY (h->other) == STV_HIDDEN
+	      || ! info->shared
+	      || info->symbolic
+	      || h->dynindx == -1
+	      || h->got.offset != (bfd_vma) -1)
+	    goto force_got;
+
+	  /* Make sure this symbol is output as a dynamic symbol.  */
+	  if (h->dynindx == -1)
+	    {
+	      if (! bfd_elf64_link_record_dynamic_symbol (info, h))
+		return false;
+	    }
+
+	  h->elf_link_hash_flags |= ELF_LINK_HASH_NEEDS_PLT;
+
+	  break;
+
+	case R_SH_PLT_LOW16:
+	case R_SH_PLT_MEDLOW16:
+	case R_SH_PLT_MEDHI16:
+	case R_SH_PLT_HI16:
+	  /* This symbol requires a procedure linkage table entry.  We
+	     actually build the entry in adjust_dynamic_symbol,
+	     because this might be a case of linking PIC code which is
+	     never referenced by a dynamic object, in which case we
+	     don't need to generate a procedure linkage table entry
+	     after all.  */
+
+	  /* If this is a local symbol, we resolve it directly without
+	     creating a procedure linkage table entry.  */
+	  if (h == NULL)
+	    continue;
+
+	  if (ELF_ST_VISIBILITY (h->other) == STV_INTERNAL
+	      || ELF_ST_VISIBILITY (h->other) == STV_HIDDEN)
+	    break;
+
+	  h->elf_link_hash_flags |= ELF_LINK_HASH_NEEDS_PLT;
+
+	  break;
+
+	case R_SH_64:
+	case R_SH_64_PCREL:
+	  if (h != NULL)
+	    h->elf_link_hash_flags |= ELF_LINK_NON_GOT_REF;
+
+	  /* If we are creating a shared library, and this is a reloc
+	     against a global symbol, or a non PC relative reloc
+	     against a local symbol, then we need to copy the reloc
+	     into the shared library.  However, if we are linking with
+	     -Bsymbolic, we do not need to copy a reloc against a
+	     global symbol which is defined in an object we are
+	     including in the link (i.e., DEF_REGULAR is set).  At
+	     this point we have not seen all the input files, so it is
+	     possible that DEF_REGULAR is not set now but will be set
+	     later (it is never cleared).  We account for that
+	     possibility below by storing information in the
+	     pcrel_relocs_copied field of the hash table entry.  */
+	  if (info->shared
+	      && (sec->flags & SEC_ALLOC) != 0
+	      && (ELF32_R_TYPE (rel->r_info) != R_SH_64_PCREL
+		  || (h != NULL
+		      && (! info->symbolic
+			  || (h->elf_link_hash_flags
+			      & ELF_LINK_HASH_DEF_REGULAR) == 0))))
+	    {
+	      /* When creating a shared object, we must copy these
+		 reloc types into the output file.  We create a reloc
+		 section in dynobj and make room for this reloc.  */
+	      if (sreloc == NULL)
+		{
+		  const char *name;
+
+		  name = (bfd_elf_string_from_elf_section
+			  (abfd,
+			   elf_elfheader (abfd)->e_shstrndx,
+			   elf_section_data (sec)->rel_hdr.sh_name));
+		  if (name == NULL)
+		    return false;
+
+		  BFD_ASSERT (strncmp (name, ".rela", 5) == 0
+			      && strcmp (bfd_get_section_name (abfd, sec),
+					 name + 5) == 0);
+
+		  sreloc = bfd_get_section_by_name (dynobj, name);
+		  if (sreloc == NULL)
+		    {
+		      flagword flags;
+
+		      sreloc = bfd_make_section (dynobj, name);
+		      flags = (SEC_HAS_CONTENTS | SEC_READONLY
+			       | SEC_IN_MEMORY | SEC_LINKER_CREATED);
+		      if ((sec->flags & SEC_ALLOC) != 0)
+			flags |= SEC_ALLOC | SEC_LOAD;
+		      if (sreloc == NULL
+			  || ! bfd_set_section_flags (dynobj, sreloc, flags)
+			  || ! bfd_set_section_alignment (dynobj, sreloc, 2))
+			return false;
+		    }
+		}
+
+	      sreloc->_raw_size += sizeof (Elf64_External_Rela);
+
+	      /* If we are linking with -Bsymbolic, and this is a
+		 global symbol, we count the number of PC relative
+		 relocations we have entered for this symbol, so that
+		 we can discard them again if the symbol is later
+		 defined by a regular object.  Note that this function
+		 is only called if we are using an elf_sh linker
+		 hash table, which means that h is really a pointer to
+		 an elf_sh_link_hash_entry.  */
+	      if (h != NULL && info->symbolic
+		  && ELF64_R_TYPE (rel->r_info) == R_SH_64_PCREL)
+		{
+		  struct elf_sh64_link_hash_entry *eh;
+		  struct elf_sh64_pcrel_relocs_copied *p;
+
+		  eh = (struct elf_sh64_link_hash_entry *) h;
+
+		  for (p = eh->pcrel_relocs_copied; p != NULL; p = p->next)
+		    if (p->section == sreloc)
+		      break;
+
+		  if (p == NULL)
+		    {
+		      p = ((struct elf_sh64_pcrel_relocs_copied *)
+			   bfd_alloc (dynobj, sizeof *p));
+		      if (p == NULL)
+			return false;
+		      p->next = eh->pcrel_relocs_copied;
+		      eh->pcrel_relocs_copied = p;
+		      p->section = sreloc;
+		      p->count = 0;
+		    }
+
+		  ++p->count;
+		}
+	    }
+
+	  break;
+        }
+    }
+ 
+  return true;
+}
+
+static int
+sh64_elf64_get_symbol_type (elf_sym, type)
+     Elf_Internal_Sym * elf_sym;
+     int type;
+{
+  if (ELF_ST_TYPE (elf_sym->st_info) == STT_DATALABEL)
+    return STT_DATALABEL;
+
+  return type;
+}
+
+/* FIXME: This is a copy of sh64_elf_add_symbol_hook in elf32-sh64.c.
+   Either file can presumably exist without the other, but do not differ
+   in elf-size-ness.  How to share?
+
+   Hook called by the linker routine which adds symbols from an object
+   file.  We must make indirect symbols for undefined symbols marked with
+   STT_DATALABEL, so relocations passing them will pick up that attribute
+   and neutralize STO_SH5_ISA32 found on the symbol definition.
+
+   There is a problem, though: We want to fill in the hash-table entry for
+   this symbol and signal to the caller that no further processing is
+   needed.  But we don't have the index for this hash-table entry.  We
+   rely here on that the current entry is the first hash-entry with NULL,
+   which seems brittle.  Also, iterating over the hash-table to find that
+   entry is a linear operation on the number of symbols in this input
+   file, and this function should take constant time, so that's not good
+   too.  Only comfort is that DataLabel references should only be found in
+   hand-written assembly code and thus be rare.  FIXME: Talk maintainers
+   into adding an option to elf_add_symbol_hook (preferably) for the index
+   or the hash entry, alternatively adding the index to Elf_Internal_Sym
+   (not so good).  */
+
+static boolean
+sh64_elf64_add_symbol_hook (abfd, info, sym, namep, flagsp, secp, valp)
+     bfd *abfd;
+     struct bfd_link_info *info;
+     const Elf_Internal_Sym *sym;
+     const char **namep;
+     flagword *flagsp ATTRIBUTE_UNUSED;
+     asection **secp;
+     bfd_vma *valp;
+{
+  /* We want to do this for relocatable as well as final linking.  */
+  if (ELF_ST_TYPE (sym->st_info) == STT_DATALABEL)
+    {
+      struct elf_link_hash_entry *h;
+
+      /* For relocateable links, we register the DataLabel sym in its own
+	 right, and tweak the name when it's output.  Otherwise, we make
+	 an indirect symbol of it.  */
+      flagword flags
+	= info->relocateable || info->emitrelocations
+	? BSF_GLOBAL : BSF_GLOBAL | BSF_INDIRECT;
+
+      char *dl_name
+	= bfd_malloc (strlen (*namep) + sizeof (DATALABEL_SUFFIX));
+      struct elf_link_hash_entry ** sym_hash = elf_sym_hashes (abfd);
+
+      BFD_ASSERT (sym_hash != NULL);
+
+      /* Allocation may fail.  */
+      if (dl_name == NULL)
+	return false;
+
+      strcpy (dl_name, *namep);
+      strcat (dl_name, DATALABEL_SUFFIX);
+
+      h = (struct elf_link_hash_entry *)
+	bfd_link_hash_lookup (info->hash, dl_name, false, false, false);
+
+      if (h == NULL)
+	{
+	  /* No previous datalabel symbol.  Make one.  */
+	  if (! _bfd_generic_link_add_one_symbol (info, abfd, dl_name,
+						  flags, *secp, *valp,
+						  *namep, false,
+						  get_elf_backend_data (abfd)->collect,
+						  (struct bfd_link_hash_entry **) &h))
+	    {
+	      free (dl_name);
+	      return false;
+	    }
+
+	  h->elf_link_hash_flags &=~ ELF_LINK_NON_ELF;
+	  h->type = STT_DATALABEL;
+	}
+      else
+	/* If a new symbol was created, it holds the allocated name.
+	   Otherwise, we don't need it anymore and should deallocate it.  */
+	free (dl_name);
+
+      if (h->type != STT_DATALABEL
+	  || ((info->relocateable || info->emitrelocations)
+	      && h->root.type != bfd_link_hash_undefined)
+	  || (! info->relocateable && !info->emitrelocations
+	      && h->root.type != bfd_link_hash_indirect))
+	{
+	  /* Make sure we don't get confused on invalid input.  */
+	  (*_bfd_error_handler)
+	    (_("%s: encountered datalabel symbol in input"),
+	     bfd_get_filename (abfd));
+	  bfd_set_error (bfd_error_bad_value);
+	  return false;
+	}
+
+      /* Now find the hash-table slot for this entry and fill it in.  */
+      while (*sym_hash != NULL)
+	sym_hash++;
+      *sym_hash = h;
+
+      /* Signal to caller to skip this symbol - we've handled it.  */
+      *namep = NULL;
+    }
+
+  return true;
+}
+
+/* This hook function is called before the linker writes out a global
+   symbol.  For relocatable links, DataLabel symbols will be present in
+   linker output.  We cut off the special suffix on those symbols, so the
+   right name appears in the output.
+
+   When linking and emitting relocations, there can appear global symbols
+   that are not referenced by relocs, but rather only implicitly through
+   DataLabel references, a relation that is not visible to the linker.
+   Since no stripping of global symbols in done when doing such linking,
+   we don't need to look up and make sure to emit the main symbol for each
+   DataLabel symbol.  */
+
+boolean
+sh64_elf64_link_output_symbol_hook (abfd, info, cname, sym, input_sec)
+     bfd *abfd ATTRIBUTE_UNUSED;
+     struct bfd_link_info *info;
+     const char *cname;
+     Elf_Internal_Sym *sym;
+     asection *input_sec ATTRIBUTE_UNUSED;
+{
+  char *name = (char *) cname;
+
+  if (info->relocateable || info->emitrelocations)
+    {
+      if (ELF_ST_TYPE (sym->st_info) == STT_DATALABEL)
+	name[strlen (name) - strlen (DATALABEL_SUFFIX)] = 0;
+    }
+
+  return true;
+}
+
+/* Set bit 0 on the entry address; it always points to SHmedia code.  This
+   is mostly for symmetry with the 32-bit format, where code can be
+   SHcompact and we need to make a distinction to make sure execution
+   starts in the right ISA mode.  It is also convenient for a loader,
+   which would otherwise have to set this bit when loading a TR register
+   before jumping to the program entry.  */
+
+static void
+sh64_elf64_final_write_processing (abfd, linker)
+     bfd *abfd;
+     boolean linker ATTRIBUTE_UNUSED;
+{
+  /* FIXME: Perhaps we shouldn't do this if the entry address was supplied
+     numerically, but we currently lack the infrastructure to recognize
+     that: The entry symbol, and info whether it is numeric or a symbol
+     name is kept private in the linker.  */
+  if (elf_elfheader (abfd)->e_type == ET_EXEC)
+    elf_elfheader (abfd)->e_entry |= 1;
+}
+
+/* First entry in an absolute procedure linkage table look like this.  */
+
+static const bfd_byte elf_sh64_plt0_entry_be[PLT_ENTRY_SIZE] =
+{
+  0xcc, 0x00, 0x01, 0x10, /* movi  .got.plt >> 48, r17 */
+  0xc8, 0x00, 0x01, 0x10, /* shori (.got.plt >> 32) & 65535, r17 */
+  0xc8, 0x00, 0x01, 0x10, /* shori (.got.plt >> 16) & 65535, r17 */
+  0xc8, 0x00, 0x01, 0x10, /* shori .got.plt & 65535, r17 */
+  0x8d, 0x10, 0x09, 0x90, /* ld.q  r17, 16, r25 */
+  0x6b, 0xf1, 0x46, 0x00, /* ptabs r17, tr0 */
+  0x8d, 0x10, 0x05, 0x10, /* ld.q  r17, 8, r17 */
+  0x44, 0x01, 0xff, 0xf0, /* blink tr0, r63 */
+  0x6f, 0xf0, 0xff, 0xf0, /* nop */
+  0x6f, 0xf0, 0xff, 0xf0, /* nop */
+  0x6f, 0xf0, 0xff, 0xf0, /* nop */
+  0x6f, 0xf0, 0xff, 0xf0, /* nop */
+  0x6f, 0xf0, 0xff, 0xf0, /* nop */
+  0x6f, 0xf0, 0xff, 0xf0, /* nop */
+  0x6f, 0xf0, 0xff, 0xf0, /* nop */
+  0x6f, 0xf0, 0xff, 0xf0, /* nop */
+};
+
+static const bfd_byte elf_sh64_plt0_entry_le[PLT_ENTRY_SIZE] =
+{
+  0x10, 0x01, 0x00, 0xcc, /* movi  .got.plt >> 16, r17 */
+  0x10, 0x01, 0x00, 0xc8, /* shori (.got.plt >> 32) & 65535, r17 */
+  0x10, 0x01, 0x00, 0xc8, /* shori (.got.plt >> 16) & 65535, r17 */
+  0x10, 0x01, 0x00, 0xc8, /* shori .got.plt & 65535, r17 */
+  0x90, 0x09, 0x10, 0x8d, /* ld.q  r17, 16, r25 */
+  0x00, 0x46, 0xf1, 0x6b, /* ptabs r17, tr0 */
+  0x10, 0x05, 0x10, 0x8d, /* ld.q  r17, 8, r17 */
+  0xf0, 0xff, 0x01, 0x44, /* blink tr0, r63 */
+  0xf0, 0xff, 0xf0, 0x6f, /* nop */
+  0xf0, 0xff, 0xf0, 0x6f, /* nop */
+  0xf0, 0xff, 0xf0, 0x6f, /* nop */
+  0xf0, 0xff, 0xf0, 0x6f, /* nop */
+  0xf0, 0xff, 0xf0, 0x6f, /* nop */
+  0xf0, 0xff, 0xf0, 0x6f, /* nop */
+  0xf0, 0xff, 0xf0, 0x6f, /* nop */
+  0xf0, 0xff, 0xf0, 0x6f, /* nop */
+};
+
+/* Sebsequent entries in an absolute procedure linkage table look like
+   this.  */
+
+static const bfd_byte elf_sh64_plt_entry_be[PLT_ENTRY_SIZE] =
+{
+  0xcc, 0x00, 0x01, 0x90, /* movi  nameN-in-GOT >> 48, r25 */
+  0xc8, 0x00, 0x01, 0x90, /* shori (nameN-in-GOT >> 32) & 65535, r25 */
+  0xc8, 0x00, 0x01, 0x90, /* shori (nameN-in-GOT >> 16) & 65535, r25 */
+  0xc8, 0x00, 0x01, 0x90, /* shori nameN-in-GOT & 65535, r25 */
+  0x8d, 0x90, 0x01, 0x90, /* ld.q  r25, 0, r25 */
+  0x6b, 0xf1, 0x66, 0x00, /* ptabs r25, tr0 */
+  0x44, 0x01, 0xff, 0xf0, /* blink tr0, r63 */
+  0x6f, 0xf0, 0xff, 0xf0, /* nop */
+  0xcc, 0x00, 0x01, 0x90, /* movi  .PLT0 >> 16, r25 */
+  0xc8, 0x00, 0x01, 0x90, /* shori .PLT0 & 65535, r25 */
+  0x6b, 0xf1, 0x66, 0x00, /* ptabs r25, tr0 */
+  0xcc, 0x00, 0x01, 0x50, /* movi  reloc-offset >> 16, r21 */
+  0xc8, 0x00, 0x01, 0x50, /* shori reloc-offset & 65535, r21 */
+  0x44, 0x01, 0xff, 0xf0, /* blink tr0, r63 */
+  0x6f, 0xf0, 0xff, 0xf0, /* nop */
+  0x6f, 0xf0, 0xff, 0xf0, /* nop */
+};
+
+static const bfd_byte elf_sh64_plt_entry_le[PLT_ENTRY_SIZE] =
+{
+  0x90, 0x01, 0x00, 0xcc, /* movi  nameN-in-GOT >> 16, r25 */
+  0x90, 0x01, 0x00, 0xc8, /* shori nameN-in-GOT & 65535, r25 */
+  0x90, 0x01, 0x00, 0xc8, /* shori nameN-in-GOT & 65535, r25 */
+  0x90, 0x01, 0x00, 0xc8, /* shori nameN-in-GOT & 65535, r25 */
+  0x90, 0x01, 0x90, 0x8d, /* ld.q  r25, 0, r25 */
+  0x00, 0x66, 0xf1, 0x6b, /* ptabs r25, tr0 */
+  0xf0, 0xff, 0x01, 0x44, /* blink tr0, r63 */
+  0xf0, 0xff, 0xf0, 0x6f, /* nop */
+  0x90, 0x01, 0x00, 0xcc, /* movi  .PLT0 >> 16, r25 */
+  0x90, 0x01, 0x00, 0xc8, /* shori .PLT0 & 65535, r25 */
+  0x00, 0x66, 0xf1, 0x6b, /* ptabs r25, tr0 */
+  0x50, 0x01, 0x00, 0xcc, /* movi  reloc-offset >> 16, r21 */
+  0x50, 0x01, 0x00, 0xc8, /* shori reloc-offset & 65535, r21 */
+  0xf0, 0xff, 0x01, 0x44, /* blink tr0, r63 */
+  0xf0, 0xff, 0xf0, 0x6f, /* nop */
+  0xf0, 0xff, 0xf0, 0x6f, /* nop */
+};
+
+/* Entries in a PIC procedure linkage table look like this.  */
+
+static const bfd_byte elf_sh64_pic_plt_entry_be[PLT_ENTRY_SIZE] =
+{
+  0xcc, 0x00, 0x01, 0x90, /* movi  nameN@GOT >> 16, r25 */
+  0xc8, 0x00, 0x01, 0x90, /* shori nameN@GOT & 65535, r25 */
+  0x40, 0xc3, 0x65, 0x90, /* ldx.q r12, r25, r25 */
+  0x6b, 0xf1, 0x66, 0x00, /* ptabs r25, tr0 */
+  0x44, 0x01, 0xff, 0xf0, /* blink tr0, r63 */
+  0x6f, 0xf0, 0xff, 0xf0, /* nop */
+  0x6f, 0xf0, 0xff, 0xf0, /* nop */
+  0x6f, 0xf0, 0xff, 0xf0, /* nop */
+  0xce, 0x00, 0x01, 0x10, /* movi  -GOT_BIAS, r17 */
+  0x00, 0xcb, 0x45, 0x10, /* sub   r12, r17, r17 */
+  0x8d, 0x10, 0x09, 0x90, /* ld.q  r17, 16, r25 */
+  0x6b, 0xf1, 0x66, 0x00, /* ptabs r25, tr0 */
+  0x8d, 0x10, 0x05, 0x10, /* ld.q  r17, 8, r17 */
+  0xcc, 0x00, 0x01, 0x50, /* movi  reloc-offset >> 16, r21 */
+  0xc8, 0x00, 0x01, 0x50, /* shori reloc-offset & 65535, r21 */
+  0x44, 0x01, 0xff, 0xf0, /* blink tr0, r63 */
+};
+
+static const bfd_byte elf_sh64_pic_plt_entry_le[PLT_ENTRY_SIZE] =
+{
+  0x90, 0x01, 0x00, 0xcc, /* movi  nameN@GOT >> 16, r25 */
+  0x90, 0x01, 0x00, 0xc8, /* shori nameN@GOT & 65535, r25 */
+  0x90, 0x65, 0xc3, 0x40, /* ldx.q r12, r25, r25 */
+  0x00, 0x66, 0xf1, 0x6b, /* ptabs r25, tr0 */
+  0xf0, 0xff, 0x01, 0x44, /* blink tr0, r63 */
+  0xf0, 0xff, 0xf0, 0x6f, /* nop */
+  0xf0, 0xff, 0xf0, 0x6f, /* nop */
+  0xf0, 0xff, 0xf0, 0x6f, /* nop */
+  0x10, 0x01, 0x00, 0xce, /* movi  -GOT_BIAS, r17 */
+  0x10, 0x45, 0xcb, 0x00, /* sub   r12, r17, r17 */
+  0x90, 0x09, 0x10, 0x8d, /* ld.q  r17, 16, r25 */
+  0x00, 0x66, 0xf1, 0x6b, /* ptabs r25, tr0 */
+  0x10, 0x05, 0x10, 0x8d, /* ld.q  r17, 8, r17 */
+  0x50, 0x01, 0x00, 0xcc, /* movi  reloc-offset >> 16, r21 */
+  0x50, 0x01, 0x00, 0xc8, /* shori reloc-offset & 65535, r21 */
+  0xf0, 0xff, 0x01, 0x44, /* blink tr0, r63 */
+};
+
+static const bfd_byte *elf_sh64_plt0_entry;
+static const bfd_byte *elf_sh64_plt_entry;
+static const bfd_byte *elf_sh64_pic_plt_entry;
+
+/* Create an entry in an sh ELF linker hash table.  */
+
+static struct bfd_hash_entry *
+sh64_elf64_link_hash_newfunc (entry, table, string)
+     struct bfd_hash_entry *entry;
+     struct bfd_hash_table *table;
+     const char *string;
+{
+  struct elf_sh64_link_hash_entry *ret =
+    (struct elf_sh64_link_hash_entry *) entry;
+
+  /* Allocate the structure if it has not already been allocated by a
+     subclass.  */
+  if (ret == (struct elf_sh64_link_hash_entry *) NULL)
+    ret = ((struct elf_sh64_link_hash_entry *)
+	   bfd_hash_allocate (table,
+			      sizeof (struct elf_sh64_link_hash_entry)));
+  if (ret == (struct elf_sh64_link_hash_entry *) NULL)
+    return (struct bfd_hash_entry *) ret;
+
+  /* Call the allocation method of the superclass.  */
+  ret = ((struct elf_sh64_link_hash_entry *)
+	 _bfd_elf_link_hash_newfunc ((struct bfd_hash_entry *) ret,
+				     table, string));
+  if (ret != (struct elf_sh64_link_hash_entry *) NULL)
+    {
+      ret->pcrel_relocs_copied = NULL;
+      ret->datalabel_got_offset = (bfd_vma) -1;
+    }
+
+  return (struct bfd_hash_entry *) ret;
+}
+
+/* Create an sh64 ELF linker hash table.  */
+
+static struct bfd_link_hash_table *
+sh64_elf64_link_hash_table_create (abfd)
+     bfd *abfd;
+{
+  struct elf_sh64_link_hash_table *ret;
+
+  ret = ((struct elf_sh64_link_hash_table *)
+	 bfd_alloc (abfd, sizeof (struct elf_sh64_link_hash_table)));
+  if (ret == (struct elf_sh64_link_hash_table *) NULL)
+    return NULL;
+
+  if (! _bfd_elf_link_hash_table_init (&ret->root, abfd,
+				       sh64_elf64_link_hash_newfunc))
+    {
+      bfd_release (abfd, ret);
+      return NULL;
+    }
+
+  return &ret->root.root;
+}
+
+inline static void
+movi_shori_putval (output_bfd, value, addr)
+     bfd *output_bfd;
+     unsigned long value;
+     char *addr;
+{
+  bfd_put_32 (output_bfd,
+	      bfd_get_32 (output_bfd, addr)
+	      | ((value >> 6) & 0x3fffc00),
+	      addr);
+  bfd_put_32 (output_bfd,
+	      bfd_get_32 (output_bfd, addr + 4)
+	      | ((value << 10) & 0x3fffc00),
+	      addr + 4);
+}
+
+inline static void
+movi_3shori_putval (output_bfd, value, addr)
+     bfd *output_bfd;
+     bfd_vma value;
+     char *addr;
+{
+  bfd_put_32 (output_bfd,
+	      bfd_get_32 (output_bfd, addr)
+	      | ((value >> 38) & 0x3fffc00),
+	      addr);
+  bfd_put_32 (output_bfd,
+	      bfd_get_32 (output_bfd, addr + 4)
+	      | ((value >> 22) & 0x3fffc00),
+	      addr + 4);
+  bfd_put_32 (output_bfd,
+	      bfd_get_32 (output_bfd, addr + 8)
+	      | ((value >> 6) & 0x3fffc00),
+	      addr + 8);
+  bfd_put_32 (output_bfd,
+	      bfd_get_32 (output_bfd, addr + 12)
+	      | ((value << 10) & 0x3fffc00),
+	      addr + 12);
+}
+
+/* Create dynamic sections when linking against a dynamic object.  */
+
+static boolean
+sh64_elf64_create_dynamic_sections (abfd, info)
+     bfd *abfd;
+     struct bfd_link_info *info;
+{
+  flagword flags, pltflags;
+  register asection *s;
+  struct elf_backend_data *bed = get_elf_backend_data (abfd);
+  int ptralign = 0;
+
+  switch (bed->s->arch_size)
+    {
+    case 32:
+      ptralign = 2;
+      break;
+
+    case 64:
+      ptralign = 3;
+      break;
+
+    default:
+      bfd_set_error (bfd_error_bad_value);
+      return false;
+    }
+
+  /* We need to create .plt, .rel[a].plt, .got, .got.plt, .dynbss, and
+     .rel[a].bss sections.  */
+
+  flags = (SEC_ALLOC | SEC_LOAD | SEC_HAS_CONTENTS | SEC_IN_MEMORY
+	   | SEC_LINKER_CREATED);
+
+  pltflags = flags;
+  pltflags |= SEC_CODE;
+  if (bed->plt_not_loaded)
+    pltflags &= ~ (SEC_LOAD | SEC_HAS_CONTENTS);
+  if (bed->plt_readonly)
+    pltflags |= SEC_READONLY;
+
+  s = bfd_make_section (abfd, ".plt");
+  if (s == NULL
+      || ! bfd_set_section_flags (abfd, s, pltflags)
+      || ! bfd_set_section_alignment (abfd, s, bed->plt_alignment))
+    return false;
+
+  if (bed->want_plt_sym)
+    {
+      /* Define the symbol _PROCEDURE_LINKAGE_TABLE_ at the start of the
+	 .plt section.  */
+      struct elf_link_hash_entry *h = NULL;
+      if (! (_bfd_generic_link_add_one_symbol
+	     (info, abfd, "_PROCEDURE_LINKAGE_TABLE_", BSF_GLOBAL, s,
+	      (bfd_vma) 0, (const char *) NULL, false,
+	      get_elf_backend_data (abfd)->collect,
+	      (struct bfd_link_hash_entry **) &h)))
+	return false;
+      h->elf_link_hash_flags |= ELF_LINK_HASH_DEF_REGULAR;
+      h->type = STT_OBJECT;
+
+      if (info->shared
+	  && ! _bfd_elf_link_record_dynamic_symbol (info, h))
+	return false;
+    }
+
+  s = bfd_make_section (abfd,
+			bed->default_use_rela_p ? ".rela.plt" : ".rel.plt");
+  if (s == NULL
+      || ! bfd_set_section_flags (abfd, s, flags | SEC_READONLY)
+      || ! bfd_set_section_alignment (abfd, s, ptralign))
+    return false;
+
+  if (! _bfd_elf_create_got_section (abfd, info))
+    return false;
+
+  {
+    const char *secname;
+    char *relname;
+    flagword secflags;
+    asection *sec;
+
+    for (sec = abfd->sections; sec; sec = sec->next)
+      {
+	secflags = bfd_get_section_flags (abfd, sec);
+	if ((secflags & (SEC_DATA | SEC_LINKER_CREATED))
+	    || ((secflags & SEC_HAS_CONTENTS) != SEC_HAS_CONTENTS))
+	  continue;
+	secname = bfd_get_section_name (abfd, sec);
+	relname = (char *) bfd_malloc (strlen (secname) + 6);
+	strcpy (relname, ".rela");
+	strcat (relname, secname);
+	s = bfd_make_section (abfd, relname);
+	if (s == NULL
+	    || ! bfd_set_section_flags (abfd, s, flags | SEC_READONLY)
+	    || ! bfd_set_section_alignment (abfd, s, ptralign))
+	  return false;
+      }
+  }
+
+  if (bed->want_dynbss)
+    {
+      /* The .dynbss section is a place to put symbols which are defined
+	 by dynamic objects, are referenced by regular objects, and are
+	 not functions.  We must allocate space for them in the process
+	 image and use a R_*_COPY reloc to tell the dynamic linker to
+	 initialize them at run time.  The linker script puts the .dynbss
+	 section into the .bss section of the final image.  */
+      s = bfd_make_section (abfd, ".dynbss");
+      if (s == NULL
+	  || ! bfd_set_section_flags (abfd, s, SEC_ALLOC))
+	return false;
+
+      /* The .rel[a].bss section holds copy relocs.  This section is not
+	 normally needed.  We need to create it here, though, so that the
+	 linker will map it to an output section.  We can't just create it
+	 only if we need it, because we will not know whether we need it
+	 until we have seen all the input files, and the first time the
+	 main linker code calls BFD after examining all the input files
+	 (size_dynamic_sections) the input sections have already been
+	 mapped to the output sections.  If the section turns out not to
+	 be needed, we can discard it later.  We will never need this
+	 section when generating a shared object, since they do not use
+	 copy relocs.  */
+      if (! info->shared)
+	{
+	  s = bfd_make_section (abfd,
+				(bed->default_use_rela_p
+				 ? ".rela.bss" : ".rel.bss"));
+	  if (s == NULL
+	      || ! bfd_set_section_flags (abfd, s, flags | SEC_READONLY)
+	      || ! bfd_set_section_alignment (abfd, s, ptralign))
+	    return false;
+	}
+    }
+
+  return true;
+}
+
+/* Adjust a symbol defined by a dynamic object and referenced by a
+   regular object.  The current definition is in some section of the
+   dynamic object, but we're not including those sections.  We have to
+   change the definition to something the rest of the link can
+   understand.  */
+
+static boolean
+sh64_elf64_adjust_dynamic_symbol (info, h)
+     struct bfd_link_info *info;
+     struct elf_link_hash_entry *h;
+{
+  bfd *dynobj;
+  asection *s;
+  unsigned int power_of_two;
+
+  dynobj = elf_hash_table (info)->dynobj;
+
+  /* Make sure we know what is going on here.  */
+  BFD_ASSERT (dynobj != NULL
+	      && ((h->elf_link_hash_flags & ELF_LINK_HASH_NEEDS_PLT)
+		  || h->weakdef != NULL
+		  || ((h->elf_link_hash_flags
+		       & ELF_LINK_HASH_DEF_DYNAMIC) != 0
+		      && (h->elf_link_hash_flags
+			  & ELF_LINK_HASH_REF_REGULAR) != 0
+		      && (h->elf_link_hash_flags
+			  & ELF_LINK_HASH_DEF_REGULAR) == 0)));
+
+  /* If this is a function, put it in the procedure linkage table.  We
+     will fill in the contents of the procedure linkage table later,
+     when we know the address of the .got section.  */
+  if (h->type == STT_FUNC
+      || (h->elf_link_hash_flags & ELF_LINK_HASH_NEEDS_PLT) != 0)
+    {
+      if (! info->shared
+	  && (h->elf_link_hash_flags & ELF_LINK_HASH_DEF_DYNAMIC) == 0
+	  && (h->elf_link_hash_flags & ELF_LINK_HASH_REF_DYNAMIC) == 0)
+	{
+	  /* This case can occur if we saw a PLT reloc in an input
+	     file, but the symbol was never referred to by a dynamic
+	     object.  In such a case, we don't actually need to build
+	     a procedure linkage table, and we can just do a REL64
+	     reloc instead.  */
+	  BFD_ASSERT ((h->elf_link_hash_flags & ELF_LINK_HASH_NEEDS_PLT) != 0);
+	  return true;
+	}
+
+      /* Make sure this symbol is output as a dynamic symbol.  */
+      if (h->dynindx == -1)
+	{
+	  if (! bfd_elf64_link_record_dynamic_symbol (info, h))
+	    return false;
+	}
+
+      s = bfd_get_section_by_name (dynobj, ".plt");
+      BFD_ASSERT (s != NULL);
+
+      /* If this is the first .plt entry, make room for the special
+	 first entry.  */
+      if (s->_raw_size == 0)
+	s->_raw_size += PLT_ENTRY_SIZE;
+
+      /* If this symbol is not defined in a regular file, and we are
+	 not generating a shared library, then set the symbol to this
+	 location in the .plt.  This is required to make function
+	 pointers compare as equal between the normal executable and
+	 the shared library.  */
+      if (! info->shared
+	  && (h->elf_link_hash_flags & ELF_LINK_HASH_DEF_REGULAR) == 0)
+	{
+	  h->root.u.def.section = s;
+	  h->root.u.def.value = s->_raw_size;
+	}
+
+      h->plt.offset = s->_raw_size;
+
+      /* Make room for this entry.  */
+      s->_raw_size += elf_sh64_sizeof_plt (info);
+
+      /* We also need to make an entry in the .got.plt section, which
+	 will be placed in the .got section by the linker script.  */
+
+      s = bfd_get_section_by_name (dynobj, ".got.plt");
+      BFD_ASSERT (s != NULL);
+      s->_raw_size += 8;
+
+      /* We also need to make an entry in the .rela.plt section.  */
+
+      s = bfd_get_section_by_name (dynobj, ".rela.plt");
+      BFD_ASSERT (s != NULL);
+      s->_raw_size += sizeof (Elf64_External_Rela);
+
+      return true;
+    }
+
+  /* If this is a weak symbol, and there is a real definition, the
+     processor independent code will have arranged for us to see the
+     real definition first, and we can just use the same value.  */
+  if (h->weakdef != NULL)
+    {
+      BFD_ASSERT (h->weakdef->root.type == bfd_link_hash_defined
+		  || h->weakdef->root.type == bfd_link_hash_defweak);
+      h->root.u.def.section = h->weakdef->root.u.def.section;
+      h->root.u.def.value = h->weakdef->root.u.def.value;
+      return true;
+    }
+
+  /* This is a reference to a symbol defined by a dynamic object which
+     is not a function.  */
+
+  /* If we are creating a shared library, we must presume that the
+     only references to the symbol are via the global offset table.
+     For such cases we need not do anything here; the relocations will
+     be handled correctly by relocate_section.  */
+  if (info->shared)
+    return true;
+
+  /* If there are no references to this symbol that do not use the
+     GOT, we don't need to generate a copy reloc.  */
+  if ((h->elf_link_hash_flags & ELF_LINK_NON_GOT_REF) == 0)
+    return true;
+
+  /* We must allocate the symbol in our .dynbss section, which will
+     become part of the .bss section of the executable.  There will be
+     an entry for this symbol in the .dynsym section.  The dynamic
+     object will contain position independent code, so all references
+     from the dynamic object to this symbol will go through the global
+     offset table.  The dynamic linker will use the .dynsym entry to
+     determine the address it must put in the global offset table, so
+     both the dynamic object and the regular object will refer to the
+     same memory location for the variable.  */
+
+  s = bfd_get_section_by_name (dynobj, ".dynbss");
+  BFD_ASSERT (s != NULL);
+
+  /* We must generate a R_SH_COPY reloc to tell the dynamic linker to
+     copy the initial value out of the dynamic object and into the
+     runtime process image.  We need to remember the offset into the
+     .rela.bss section we are going to use.  */
+  if ((h->root.u.def.section->flags & SEC_ALLOC) != 0)
+    {
+      asection *srel;
+
+      srel = bfd_get_section_by_name (dynobj, ".rela.bss");
+      BFD_ASSERT (srel != NULL);
+      srel->_raw_size += sizeof (Elf64_External_Rela);
+      h->elf_link_hash_flags |= ELF_LINK_HASH_NEEDS_COPY;
+    }
+
+  /* We need to figure out the alignment required for this symbol.  I
+     have no idea how ELF linkers handle this.  */
+  power_of_two = bfd_log2 (h->size);
+  if (power_of_two > 3)
+    power_of_two = 3;
+
+  /* Apply the required alignment.  */
+  s->_raw_size = BFD_ALIGN (s->_raw_size,
+			    (bfd_size_type) (1 << power_of_two));
+  if (power_of_two > bfd_get_section_alignment (dynobj, s))
+    {
+      if (! bfd_set_section_alignment (dynobj, s, power_of_two))
+	return false;
+    }
+
+  /* Define the symbol as being at this point in the section.  */
+  h->root.u.def.section = s;
+  h->root.u.def.value = s->_raw_size;
+
+  /* Increment the section size to make room for the symbol.  */
+  s->_raw_size += h->size;
+
+  return true;
+}
+
+/* This function is called via sh_elf_link_hash_traverse if we are
+   creating a shared object with -Bsymbolic.  It discards the space
+   allocated to copy PC relative relocs against symbols which are
+   defined in regular objects.  We allocated space for them in the
+   check_relocs routine, but we won't fill them in in the
+   relocate_section routine.  */
+
+static boolean
+sh64_elf64_discard_copies (h, ignore)
+     struct elf_sh64_link_hash_entry *h;
+     PTR ignore ATTRIBUTE_UNUSED;
+{
+  struct elf_sh64_pcrel_relocs_copied *s;
+
+  /* We only discard relocs for symbols defined in a regular object.  */
+  if ((h->root.elf_link_hash_flags & ELF_LINK_HASH_DEF_REGULAR) == 0)
+    return true;
+
+  for (s = h->pcrel_relocs_copied; s != NULL; s = s->next)
+    s->section->_raw_size -= s->count * sizeof (Elf64_External_Rela);
+
+  return true;
+}
+
+/* Set the sizes of the dynamic sections.  */
+
+static boolean
+sh64_elf64_size_dynamic_sections (output_bfd, info)
+     bfd *output_bfd;
+     struct bfd_link_info *info;
+{
+  bfd *dynobj;
+  asection *s;
+  boolean plt;
+  boolean relocs;
+  boolean reltext;
+
+  dynobj = elf_hash_table (info)->dynobj;
+  BFD_ASSERT (dynobj != NULL);
+
+  if (elf_hash_table (info)->dynamic_sections_created)
+    {
+      /* Set the contents of the .interp section to the interpreter.  */
+      if (! info->shared)
+	{
+	  s = bfd_get_section_by_name (dynobj, ".interp");
+	  BFD_ASSERT (s != NULL);
+	  s->_raw_size = sizeof ELF_DYNAMIC_INTERPRETER;
+	  s->contents = (unsigned char *) ELF_DYNAMIC_INTERPRETER;
+	}
+    }
+  else
+    {
+      /* We may have created entries in the .rela.got section.
+	 However, if we are not creating the dynamic sections, we will
+	 not actually use these entries.  Reset the size of .rela.got,
+	 which will cause it to get stripped from the output file
+	 below.  */
+      s = bfd_get_section_by_name (dynobj, ".rela.got");
+      if (s != NULL)
+	s->_raw_size = 0;
+    }
+
+  /* If this is a -Bsymbolic shared link, then we need to discard all
+     PC relative relocs against symbols defined in a regular object.
+     We allocated space for them in the check_relocs routine, but we
+     will not fill them in in the relocate_section routine.  */
+  if (info->shared && info->symbolic)
+    sh64_elf64_link_hash_traverse (sh64_elf64_hash_table (info),
+				   sh64_elf64_discard_copies,
+				   (PTR) NULL);
+
+  /* The check_relocs and adjust_dynamic_symbol entry points have
+     determined the sizes of the various dynamic sections.  Allocate
+     memory for them.  */
+  plt = false;
+  relocs = false;
+  reltext = false;
+  for (s = dynobj->sections; s != NULL; s = s->next)
+    {
+      const char *name;
+      boolean strip;
+
+      if ((s->flags & SEC_LINKER_CREATED) == 0)
+	continue;
+
+      /* It's OK to base decisions on the section name, because none
+	 of the dynobj section names depend upon the input files.  */
+      name = bfd_get_section_name (dynobj, s);
+
+      strip = false;
+
+      if (strcmp (name, ".plt") == 0)
+	{
+	  if (s->_raw_size == 0)
+	    {
+	      /* Strip this section if we don't need it; see the
+		 comment below.  */
+	      strip = true;
+	    }
+	  else
+	    {
+	      /* Remember whether there is a PLT.  */
+	      plt = true;
+	    }
+	}
+      else if (strncmp (name, ".rela", 5) == 0)
+	{
+	  if (s->_raw_size == 0)
+	    {
+	      /* If we don't need this section, strip it from the
+		 output file.  This is mostly to handle .rela.bss and
+		 .rela.plt.  We must create both sections in
+		 create_dynamic_sections, because they must be created
+		 before the linker maps input sections to output
+		 sections.  The linker does that before
+		 adjust_dynamic_symbol is called, and it is that
+		 function which decides whether anything needs to go
+		 into these sections.  */
+	      strip = true;
+	    }
+	  else
+	    {
+	      asection *target;
+
+	      /* Remember whether there are any reloc sections other
+		 than .rela.plt.  */
+	      if (strcmp (name, ".rela.plt") != 0)
+		{
+		  const char *outname;
+
+		  relocs = true;
+
+		  /* If this relocation section applies to a read only
+		     section, then we probably need a DT_TEXTREL
+		     entry.  The entries in the .rela.plt section
+		     really apply to the .got section, which we
+		     created ourselves and so know is not readonly.  */
+		  outname = bfd_get_section_name (output_bfd,
+						  s->output_section);
+		  target = bfd_get_section_by_name (output_bfd, outname + 5);
+		  if (target != NULL
+		      && (target->flags & SEC_READONLY) != 0
+		      && (target->flags & SEC_ALLOC) != 0)
+		    reltext = true;
+		}
+
+	      /* We use the reloc_count field as a counter if we need
+		 to copy relocs into the output file.  */
+	      s->reloc_count = 0;
+	    }
+	}
+      else if (strncmp (name, ".got", 4) != 0)
+	{
+	  /* It's not one of our sections, so don't allocate space.  */
+	  continue;
+	}
+
+      if (strip)
+	{
+	  _bfd_strip_section_from_output (info, s);
+	  continue;
+	}
+
+      /* Allocate memory for the section contents.  */
+      s->contents = (bfd_byte *) bfd_alloc (dynobj, s->_raw_size);
+      if (s->contents == NULL && s->_raw_size != 0)
+	return false;
+    }
+
+  if (elf_hash_table (info)->dynamic_sections_created)
+    {
+      /* Add some entries to the .dynamic section.  We fill in the
+	 values later, in sh64_elf64_finish_dynamic_sections, but we
+	 must add the entries now so that we get the correct size for
+	 the .dynamic section.  The DT_DEBUG entry is filled in by the
+	 dynamic linker and used by the debugger.  */
+      if (! info->shared)
+	{
+	  if (! bfd_elf64_add_dynamic_entry (info, DT_DEBUG, 0))
+	    return false;
+	}
+
+      if (plt)
+	{
+	  if (! bfd_elf64_add_dynamic_entry (info, DT_PLTGOT, 0)
+	      || ! bfd_elf64_add_dynamic_entry (info, DT_PLTRELSZ, 0)
+	      || ! bfd_elf64_add_dynamic_entry (info, DT_PLTREL, DT_RELA)
+	      || ! bfd_elf64_add_dynamic_entry (info, DT_JMPREL, 0))
+	    return false;
+	}
+
+      if (relocs)
+	{
+	  if (! bfd_elf64_add_dynamic_entry (info, DT_RELA, 0)
+	      || ! bfd_elf64_add_dynamic_entry (info, DT_RELASZ, 0)
+	      || ! bfd_elf64_add_dynamic_entry (info, DT_RELAENT,
+						sizeof (Elf64_External_Rela)))
+	    return false;
+	}
+
+      if (reltext)
+	{
+	  if (! bfd_elf64_add_dynamic_entry (info, DT_TEXTREL, 0))
+	    return false;
+	}
+    }
+
+  return true;
+}
+
+/* Finish up dynamic symbol handling.  We set the contents of various
+   dynamic sections here.  */
+
+static boolean
+sh64_elf64_finish_dynamic_symbol (output_bfd, info, h, sym)
+     bfd *output_bfd;
+     struct bfd_link_info *info;
+     struct elf_link_hash_entry *h;
+     Elf_Internal_Sym *sym;
+{
+  bfd *dynobj;
+
+  dynobj = elf_hash_table (info)->dynobj;
+
+  if (h->plt.offset != (bfd_vma) -1)
+    {
+      asection *splt;
+      asection *sgot;
+      asection *srel;
+
+      bfd_vma plt_index;
+      bfd_vma got_offset;
+      Elf_Internal_Rela rel;
+
+      /* This symbol has an entry in the procedure linkage table.  Set
+	 it up.  */
+
+      BFD_ASSERT (h->dynindx != -1);
+
+      splt = bfd_get_section_by_name (dynobj, ".plt");
+      sgot = bfd_get_section_by_name (dynobj, ".got.plt");
+      srel = bfd_get_section_by_name (dynobj, ".rela.plt");
+      BFD_ASSERT (splt != NULL && sgot != NULL && srel != NULL);
+
+      /* Get the index in the procedure linkage table which
+	 corresponds to this symbol.  This is the index of this symbol
+	 in all the symbols for which we are making plt entries.  The
+	 first entry in the procedure linkage table is reserved.  */
+      plt_index = h->plt.offset / elf_sh64_sizeof_plt (info) - 1;
+
+      /* Get the offset into the .got table of the entry that
+	 corresponds to this function.  Each .got entry is 8 bytes.
+	 The first three are reserved.  */
+      got_offset = (plt_index + 3) * 8;
+
+      got_offset -= GOT_BIAS;
+
+      /* Fill in the entry in the procedure linkage table.  */
+      if (! info->shared)
+	{
+	  if (elf_sh64_plt_entry == NULL)
+	    {
+	      elf_sh64_plt_entry = (bfd_big_endian (output_bfd) ?
+				  elf_sh64_plt_entry_be : elf_sh64_plt_entry_le);
+	    }
+	  memcpy (splt->contents + h->plt.offset, elf_sh64_plt_entry,
+		  elf_sh64_sizeof_plt (info));
+	  movi_3shori_putval (output_bfd,
+			      (sgot->output_section->vma
+			       + sgot->output_offset
+			       + got_offset),
+			      (splt->contents + h->plt.offset
+			       + elf_sh64_plt_symbol_offset (info)));
+
+	  movi_shori_putval (output_bfd,
+			     (splt->output_section->vma + splt->output_offset),
+			     (splt->contents + h->plt.offset
+			      + elf_sh64_plt_plt0_offset (info)));
+	}
+      else
+	{
+	  if (elf_sh64_pic_plt_entry == NULL)
+	    {
+	      elf_sh64_pic_plt_entry = (bfd_big_endian (output_bfd) ?
+				      elf_sh64_pic_plt_entry_be :
+				      elf_sh64_pic_plt_entry_le);
+	    }
+	  memcpy (splt->contents + h->plt.offset, elf_sh64_pic_plt_entry,
+		  elf_sh64_sizeof_plt (info));
+	  movi_shori_putval (output_bfd, got_offset,
+			     (splt->contents + h->plt.offset
+			      + elf_sh64_plt_symbol_offset (info)));
+	}
+
+      got_offset += GOT_BIAS;
+
+      movi_shori_putval (output_bfd,
+			 plt_index * sizeof (Elf64_External_Rela),
+			 (splt->contents + h->plt.offset
+			  + elf_sh64_plt_reloc_offset (info)));
+
+      /* Fill in the entry in the global offset table.  */
+      bfd_put_64 (output_bfd,
+		  (splt->output_section->vma
+		   + splt->output_offset
+		   + h->plt.offset
+		   + elf_sh64_plt_temp_offset (info)),
+		  sgot->contents + got_offset);
+
+      /* Fill in the entry in the .rela.plt section.  */
+      rel.r_offset = (sgot->output_section->vma
+		      + sgot->output_offset
+		      + got_offset);
+      rel.r_info = ELF64_R_INFO (h->dynindx, R_SH_JMP_SLOT64);
+      rel.r_addend = 0;
+      rel.r_addend = GOT_BIAS;
+      bfd_elf64_swap_reloca_out (output_bfd, &rel,
+				((Elf64_External_Rela *) srel->contents
+				 + plt_index));
+
+      if ((h->elf_link_hash_flags & ELF_LINK_HASH_DEF_REGULAR) == 0)
+	{
+	  /* Mark the symbol as undefined, rather than as defined in
+	     the .plt section.  Leave the value alone.  */
+	  sym->st_shndx = SHN_UNDEF;
+	}
+    }
+
+  if (h->got.offset != (bfd_vma) -1)
+    {
+      asection *sgot;
+      asection *srel;
+      Elf_Internal_Rela rel;
+
+      /* This symbol has an entry in the global offset table.  Set it
+	 up.  */
+
+      sgot = bfd_get_section_by_name (dynobj, ".got");
+      srel = bfd_get_section_by_name (dynobj, ".rela.got");
+      BFD_ASSERT (sgot != NULL && srel != NULL);
+
+      rel.r_offset = (sgot->output_section->vma
+		      + sgot->output_offset
+		      + (h->got.offset &~ 1));
+
+      /* If this is a -Bsymbolic link, and the symbol is defined
+	 locally, we just want to emit a RELATIVE reloc.  Likewise if
+	 the symbol was forced to be local because of a version file.
+	 The entry in the global offset table will already have been
+	 initialized in the relocate_section function.  */
+      if (info->shared
+	  && (info->symbolic || h->dynindx == -1)
+	  && (h->elf_link_hash_flags & ELF_LINK_HASH_DEF_REGULAR))
+	{
+	  rel.r_info = ELF64_R_INFO (0, R_SH_RELATIVE64);
+	  rel.r_addend = (h->root.u.def.value
+			  + h->root.u.def.section->output_section->vma
+			  + h->root.u.def.section->output_offset);
+	}
+      else
+	{
+	  bfd_put_64 (output_bfd, (bfd_vma) 0, sgot->contents + h->got.offset);
+	  rel.r_info = ELF64_R_INFO (h->dynindx, R_SH_GLOB_DAT64);
+	  rel.r_addend = 0;
+	}
+
+      bfd_elf64_swap_reloca_out (output_bfd, &rel,
+				 ((Elf64_External_Rela *) srel->contents
+				  + srel->reloc_count));
+      ++srel->reloc_count;
+    }
+
+  if ((h->elf_link_hash_flags & ELF_LINK_HASH_NEEDS_COPY) != 0)
+    {
+      asection *s;
+      Elf_Internal_Rela rel;
+
+      /* This symbol needs a copy reloc.  Set it up.  */
+
+      BFD_ASSERT (h->dynindx != -1
+		  && (h->root.type == bfd_link_hash_defined
+		      || h->root.type == bfd_link_hash_defweak));
+
+      s = bfd_get_section_by_name (h->root.u.def.section->owner,
+				   ".rela.bss");
+      BFD_ASSERT (s != NULL);
+
+      rel.r_offset = (h->root.u.def.value
+		      + h->root.u.def.section->output_section->vma
+		      + h->root.u.def.section->output_offset);
+      rel.r_info = ELF64_R_INFO (h->dynindx, R_SH_COPY64);
+      rel.r_addend = 0;
+      bfd_elf64_swap_reloca_out (output_bfd, &rel,
+				 ((Elf64_External_Rela *) s->contents
+				  + s->reloc_count));
+      ++s->reloc_count;
+    }
+
+  /* Mark _DYNAMIC and _GLOBAL_OFFSET_TABLE_ as absolute.  */
+  if (strcmp (h->root.root.string, "_DYNAMIC") == 0
+      || strcmp (h->root.root.string, "_GLOBAL_OFFSET_TABLE_") == 0)
+    sym->st_shndx = SHN_ABS;
+
+  return true;
+}
+
+/* Finish up the dynamic sections.  */
+
+static boolean
+sh64_elf64_finish_dynamic_sections (output_bfd, info)
+     bfd *output_bfd;
+     struct bfd_link_info *info;
+{
+  bfd *dynobj;
+  asection *sgot;
+  asection *sdyn;
+
+  dynobj = elf_hash_table (info)->dynobj;
+
+  sgot = bfd_get_section_by_name (dynobj, ".got.plt");
+  BFD_ASSERT (sgot != NULL);
+  sdyn = bfd_get_section_by_name (dynobj, ".dynamic");
+
+  if (elf_hash_table (info)->dynamic_sections_created)
+    {
+      asection *splt;
+      Elf64_External_Dyn *dyncon, *dynconend;
+
+      BFD_ASSERT (sdyn != NULL);
+
+      dyncon = (Elf64_External_Dyn *) sdyn->contents;
+      dynconend = (Elf64_External_Dyn *) (sdyn->contents + sdyn->_raw_size);
+      for (; dyncon < dynconend; dyncon++)
+	{
+	  Elf_Internal_Dyn dyn;
+	  const char *name;
+	  asection *s;
+
+	  bfd_elf64_swap_dyn_in (dynobj, dyncon, &dyn);
+
+	  switch (dyn.d_tag)
+	    {
+	    default:
+	      break;
+
+	    case DT_PLTGOT:
+	      name = ".got";
+	      goto get_vma;
+
+	    case DT_JMPREL:
+	      name = ".rela.plt";
+	    get_vma:
+	      s = bfd_get_section_by_name (output_bfd, name);
+	      BFD_ASSERT (s != NULL);
+	      dyn.d_un.d_ptr = s->vma;
+	      bfd_elf64_swap_dyn_out (output_bfd, &dyn, dyncon);
+	      break;
+
+	    case DT_PLTRELSZ:
+	      s = bfd_get_section_by_name (output_bfd, ".rela.plt");
+	      BFD_ASSERT (s != NULL);
+	      if (s->_cooked_size != 0)
+		dyn.d_un.d_val = s->_cooked_size;
+	      else
+		dyn.d_un.d_val = s->_raw_size;
+	      bfd_elf64_swap_dyn_out (output_bfd, &dyn, dyncon);
+	      break;
+
+	    case DT_RELASZ:
+	      /* My reading of the SVR4 ABI indicates that the
+		 procedure linkage table relocs (DT_JMPREL) should be
+		 included in the overall relocs (DT_RELA).  This is
+		 what Solaris does.  However, UnixWare can not handle
+		 that case.  Therefore, we override the DT_RELASZ entry
+		 here to make it not include the JMPREL relocs.  Since
+		 the linker script arranges for .rela.plt to follow all
+		 other relocation sections, we don't have to worry
+		 about changing the DT_RELA entry.  */
+	      s = bfd_get_section_by_name (output_bfd, ".rela.plt");
+	      if (s != NULL)
+		{
+		  if (s->_cooked_size != 0)
+		    dyn.d_un.d_val -= s->_cooked_size;
+		  else
+		    dyn.d_un.d_val -= s->_raw_size;
+		}
+	      bfd_elf64_swap_dyn_out (output_bfd, &dyn, dyncon);
+	      break;
+	    }
+	}
+
+      /* Fill in the first entry in the procedure linkage table.  */
+      splt = bfd_get_section_by_name (dynobj, ".plt");
+      if (splt && splt->_raw_size > 0)
+	{
+	  if (info->shared)
+	    {
+	      if (elf_sh64_pic_plt_entry == NULL)
+		{
+		  elf_sh64_pic_plt_entry = (bfd_big_endian (output_bfd) ?
+					  elf_sh64_pic_plt_entry_be :
+					  elf_sh64_pic_plt_entry_le);
+		}
+	      memcpy (splt->contents, elf_sh64_pic_plt_entry,
+		      elf_sh64_sizeof_plt (info));
+	    }
+	  else
+	    {
+	      if (elf_sh64_plt0_entry == NULL)
+		{
+		  elf_sh64_plt0_entry = (bfd_big_endian (output_bfd) ?
+				       elf_sh64_plt0_entry_be :
+				       elf_sh64_plt0_entry_le);
+		}
+	      memcpy (splt->contents, elf_sh64_plt0_entry, PLT_ENTRY_SIZE);
+	      movi_3shori_putval (output_bfd,
+				  sgot->output_section->vma
+				  + sgot->output_offset,
+				  splt->contents
+				  + elf_sh64_plt0_gotplt_offset (info));
+	    }
+
+	  /* UnixWare sets the entsize of .plt to 8, although that doesn't
+	     really seem like the right value.  */
+	  elf_section_data (splt->output_section)->this_hdr.sh_entsize = 8;
+	}
+    }
+
+  /* Fill in the first three entries in the global offset table.  */
+  if (sgot->_raw_size > 0)
+    {
+      if (sdyn == NULL)
+	bfd_put_64 (output_bfd, (bfd_vma) 0, sgot->contents);
+      else
+	bfd_put_64 (output_bfd,
+		    sdyn->output_section->vma + sdyn->output_offset,
+		    sgot->contents);
+      bfd_put_64 (output_bfd, (bfd_vma) 0, sgot->contents + 8);
+      bfd_put_64 (output_bfd, (bfd_vma) 0, sgot->contents + 16);
+    }
+
+  elf_section_data (sgot->output_section)->this_hdr.sh_entsize = 8;
+
+  return true;
+}
+
+
+#ifndef ELF_ARCH
+#define TARGET_BIG_SYM		bfd_elf64_sh64_vec
+#define TARGET_BIG_NAME		"elf64-sh64"
+#define TARGET_LITTLE_SYM	bfd_elf64_sh64l_vec
+#define TARGET_LITTLE_NAME	"elf64-sh64l"
+#define ELF_ARCH		bfd_arch_sh
+#define ELF_MACHINE_CODE	EM_SH
+#define ELF_MAXPAGESIZE		128
+
+#define elf_symbol_leading_char '_'
+#endif /* ELF_ARCH */
+
+#define bfd_elf64_bfd_reloc_type_lookup	sh_elf64_reloc_type_lookup
+#define elf_info_to_howto		sh_elf64_info_to_howto
+
+/* Note: there's no relaxation at present.  */
+
+#define elf_backend_relocate_section	sh_elf64_relocate_section
+#define bfd_elf64_bfd_get_relocated_section_contents \
+					sh_elf64_get_relocated_section_contents
+#define elf_backend_object_p		sh_elf64_set_mach_from_flags
+#define bfd_elf64_bfd_set_private_flags \
+					sh_elf64_set_private_flags
+#define bfd_elf64_bfd_copy_private_bfd_data \
+					sh_elf64_copy_private_data
+#define bfd_elf64_bfd_merge_private_bfd_data \
+					sh_elf64_merge_private_data
+#define elf_backend_fake_sections	sh64_elf64_fake_sections
+
+#define elf_backend_gc_mark_hook        sh_elf64_gc_mark_hook
+#define elf_backend_gc_sweep_hook       sh_elf64_gc_sweep_hook
+#define elf_backend_check_relocs        sh_elf64_check_relocs
+
+#define elf_backend_can_gc_sections	1
+
+#define elf_backend_get_symbol_type	sh64_elf64_get_symbol_type
+
+#define elf_backend_add_symbol_hook	sh64_elf64_add_symbol_hook
+
+#define elf_backend_link_output_symbol_hook \
+	sh64_elf64_link_output_symbol_hook
+
+#define elf_backend_final_write_processing \
+ 	sh64_elf64_final_write_processing
+
+#define elf_backend_create_dynamic_sections \
+					sh64_elf64_create_dynamic_sections
+#define bfd_elf64_bfd_link_hash_table_create \
+					sh64_elf64_link_hash_table_create
+#define elf_backend_adjust_dynamic_symbol \
+					sh64_elf64_adjust_dynamic_symbol
+#define elf_backend_size_dynamic_sections \
+					sh64_elf64_size_dynamic_sections
+#define elf_backend_finish_dynamic_symbol \
+					sh64_elf64_finish_dynamic_symbol
+#define elf_backend_finish_dynamic_sections \
+					sh64_elf64_finish_dynamic_sections
+
+#define elf_backend_want_got_plt	1
+#define elf_backend_plt_readonly	1
+#define elf_backend_want_plt_sym	0
+#define elf_backend_got_header_size	24
+#define elf_backend_plt_header_size	PLT_ENTRY_SIZE
+
+#include "elf64-target.h"
Index: bfd/reloc.c
===================================================================
RCS file: /home/aoliva/cygnus/uberbaum/bfd/reloc.c,v
retrieving revision 1.53
diff -u -p -r1.53 reloc.c
--- bfd/reloc.c 30 Jan 2002 18:12:16 -0000 1.53
+++ bfd/reloc.c 2 Feb 2002 04:00:29 -0000
@@ -1,6 +1,6 @@
 /* BFD support for handling relocation entries.
    Copyright 1990, 1991, 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999,
-   2000, 2001
+   2000, 2001, 2002
    Free Software Foundation, Inc.
    Written by Cygnus Support.
 
@@ -2042,6 +2042,107 @@ ENUMX
   BFD_RELOC_MIPS_RELGOT
 ENUMX
   BFD_RELOC_MIPS_JALR
+COMMENT
+COMMENT
+ENUMX
+  BFD_RELOC_SH_GOT_LOW16
+ENUMX
+  BFD_RELOC_SH_GOT_MEDLOW16
+ENUMX
+  BFD_RELOC_SH_GOT_MEDHI16
+ENUMX
+  BFD_RELOC_SH_GOT_HI16
+ENUMX
+  BFD_RELOC_SH_GOTPLT_LOW16
+ENUMX
+  BFD_RELOC_SH_GOTPLT_MEDLOW16
+ENUMX
+  BFD_RELOC_SH_GOTPLT_MEDHI16
+ENUMX
+  BFD_RELOC_SH_GOTPLT_HI16
+ENUMX
+  BFD_RELOC_SH_PLT_LOW16
+ENUMX
+  BFD_RELOC_SH_PLT_MEDLOW16
+ENUMX
+  BFD_RELOC_SH_PLT_MEDHI16
+ENUMX
+  BFD_RELOC_SH_PLT_HI16
+ENUMX
+  BFD_RELOC_SH_GOTOFF_LOW16
+ENUMX
+  BFD_RELOC_SH_GOTOFF_MEDLOW16
+ENUMX
+  BFD_RELOC_SH_GOTOFF_MEDHI16
+ENUMX
+  BFD_RELOC_SH_GOTOFF_HI16
+ENUMX
+  BFD_RELOC_SH_GOTPC_LOW16
+ENUMX
+  BFD_RELOC_SH_GOTPC_MEDLOW16
+ENUMX
+  BFD_RELOC_SH_GOTPC_MEDHI16
+ENUMX
+  BFD_RELOC_SH_GOTPC_HI16
+ENUMX
+  BFD_RELOC_SH_COPY64
+ENUMX
+  BFD_RELOC_SH_GLOB_DAT64
+ENUMX
+  BFD_RELOC_SH_JMP_SLOT64
+ENUMX
+  BFD_RELOC_SH_RELATIVE64
+ENUMX
+  BFD_RELOC_SH_GOT10BY4
+ENUMX
+  BFD_RELOC_SH_GOT10BY8
+ENUMX
+  BFD_RELOC_SH_GOTPLT10BY4
+ENUMX
+  BFD_RELOC_SH_GOTPLT10BY8
+ENUMX
+  BFD_RELOC_SH_GOTPLT32
+COMMENT
+ENUMX
+  BFD_RELOC_SH_SHMEDIA_CODE
+ENUMX
+  BFD_RELOC_SH_IMMU5
+ENUMX
+  BFD_RELOC_SH_IMMS6
+ENUMX
+  BFD_RELOC_SH_IMMS6BY32
+ENUMX
+  BFD_RELOC_SH_IMMU6
+ENUMX
+  BFD_RELOC_SH_IMMS10
+ENUMX
+  BFD_RELOC_SH_IMMS10BY2
+ENUMX
+  BFD_RELOC_SH_IMMS10BY4
+ENUMX
+  BFD_RELOC_SH_IMMS10BY8
+ENUMX
+  BFD_RELOC_SH_IMMS16
+ENUMX
+  BFD_RELOC_SH_IMMU16
+ENUMX
+  BFD_RELOC_SH_IMM_LOW16
+ENUMX
+  BFD_RELOC_SH_IMM_LOW16_PCREL
+ENUMX
+  BFD_RELOC_SH_IMM_MEDLOW16
+ENUMX
+  BFD_RELOC_SH_IMM_MEDLOW16_PCREL
+ENUMX
+  BFD_RELOC_SH_IMM_MEDHI16
+ENUMX
+  BFD_RELOC_SH_IMM_MEDHI16_PCREL
+ENUMX
+  BFD_RELOC_SH_IMM_HI16
+ENUMX
+  BFD_RELOC_SH_IMM_HI16_PCREL
+ENUMX
+  BFD_RELOC_SH_PT_16
 COMMENT
 ENUMDOC
   MIPS ELF relocations.
Index: bfd/targets.c
===================================================================
RCS file: /home/aoliva/cygnus/uberbaum/bfd/targets.c,v
retrieving revision 1.56
diff -u -p -r1.56 targets.c
--- bfd/targets.c 31 Jan 2002 17:32:55 -0000 1.56
+++ bfd/targets.c 2 Feb 2002 04:00:29 -0000
@@ -682,6 +682,10 @@ extern const bfd_target ptrace_core_vec;
 extern const bfd_target sco5_core_vec;
 extern const bfd_target trad_core_vec;
 
+extern const bfd_target bfd_elf32_sh64_vec;
+extern const bfd_target bfd_elf32_sh64l_vec;
+extern const bfd_target bfd_elf64_sh64_vec;
+extern const bfd_target bfd_elf64_sh64l_vec;
 static const bfd_target * const _bfd_target_vector[] = {
 
 #ifdef SELECT_VECS

-- 
Alexandre Oliva   Enjoy Guarana', see http://www.ic.unicamp.br/~oliva/
Red Hat GCC Developer                  aoliva@{cygnus.com, redhat.com}
CS PhD student at IC-Unicamp        oliva@{lsd.ic.unicamp.br, gnu.org}
Free Software Evangelist                Professional serial bug killer

Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]