summaryrefslogtreecommitdiff
path: root/ld/emultempl/sh64elf.em
diff options
context:
space:
mode:
authorAlexandre Oliva <aoliva@redhat.com>2002-02-08 06:39:01 +0000
committerAlexandre Oliva <aoliva@redhat.com>2002-02-08 06:39:01 +0000
commit92b3caaaf8e7a98e00814449b1f36f0c159297e8 (patch)
tree5c59419548b5d18b789db737fb80c3f585a21c16 /ld/emultempl/sh64elf.em
parent92e7d8cd19ba3bd4f9ce9eccfe0ba09e4c2ac2de (diff)
downloadbinutils-redhat-92b3caaaf8e7a98e00814449b1f36f0c159297e8.tar.gz
Contribute sh64-elf.
2002-01-24 Alexandre Oliva <aoliva@redhat.com> * emulparams/shelf32.sh (STACK_ADDR): Define as formerly defined in OTHER_RELOCATABLE_SECTIONS. 2002-01-18 Alexandre Oliva <aoliva@redhat.com> * emulparams/shelf32.sh (STACK_ADDR): Define. (OTHER_RELOCATABLE_SECTIONS): Renamed to... (OTHER_SECTIONS): this. Removed stack settings. * emulparams/shelf64.sh (OTHER_RELOCATABLE_SECTIONS): Do not set. (OTHER_SECTIONS): Reset after sourcing shelf32.sh. 2001-03-12 DJ Delorie <dj@redhat.com> * emultempl/sh64elf.em (sh64_elf_$_before_allocation): Disable relaxing if any shmedia or mixed sections are found. 2001-03-07 DJ Delorie <dj@redhat.com> * emultempl/sh64elf.em (sh64_elf_before_allocation): Pass f to einfo. Gracefully decline to output to non-elf formats. 2001-03-06 Hans-Peter Nilsson <hpn@redhat.com> * emulparams/shelf64.sh (OTHER_RELOCATING_SECTIONS) <.stack>: Default to _end aligned to next multiple of 0x40000, plus 0x40000. * emulparams/shelf32.sh: Ditto. 2001-01-14 Hans-Peter Nilsson <hpn@cygnus.com> * emulparams/shelf32.sh (OTHER_RELOCATING_SECTIONS): Tweak comment. 2001-01-10 Ben Elliston <bje@redhat.com> * emulparams/shelf32.sh (OTHER_RELOCATING_SECTIONS): Avoid non-portable shell constructs. From Hans-Peter Nilsson. 2001-01-09 Hans-Peter Nilsson <hpn@cygnus.com> * emulparams/shelf64.sh (EXTRA_EM_FILE): Define empty. * Makefile.am (eshelf64.c, eshlelf64.c, eshlelf32.c): Adjust dependencies to the shell script include chain. * Makefile.in: Regenerate. 2001-01-06 Hans-Peter Nilsson <hpn@cygnus.com> * emultempl/sh64elf.em: Update and tweak comments. (sh64_elf_${EMULATION_NAME}_after_allocation): Always allocate and make a .cranges section SEC_IN_MEMORY. 2000-12-30 Hans-Peter Nilsson <hpn@cygnus.com> * emultempl/sh64elf.em (sh64_elf_${EMULATION_NAME}_before_allocation): Don't stop when .cranges section found to be necessary; continue and set stored section contents flags for sections with non-mixed contents. Use a struct sh64_section_data container and sh64_elf_section_data to store contents-type flags. Remove unused update of "isec". (sh64_elf_${EMULATION_NAME}_after_allocation): Only process sections marked SHF_SH5_ISA32_MIXED. Use sh64_elf_section_data to access contents-type flags. Assert that the associated container is initialized. Use that container, not elf_gp_size, to hold size of linker-generated cranges contents. 2000-12-18 Hans-Peter Nilsson <hpn@cygnus.com> * emultempl/sh64elf.em (sh64_elf_${EMULATION_NAME}_before_allocation): Exit early if there's already a .cranges section. When section flag difference is found, don't NULL-check cranges a second time. Tweak comments. (sh64_elf_${EMULATION_NAME}_after_allocation): Use size after merging, not max size, as size of ld-generated .cranges contents. Don't set ELF section flags in output section. When checking for needed .cranges descriptors, don't use a variable; compare incoming ELF section flags directly to SHF_SH5_ISA32_MIXED. Tweak comments. 2000-12-18 Hans-Peter Nilsson <hpn@cygnus.com> * emultempl/sh64elf.em: New file. * Makefile.am (eshelf32.c, eshlelf32.c): Adjust dependencies. * Makefile.in: Regenerate. * emulparams/shelf32.sh (OUTPUT_FORMAT): Only set if not set. (OTHER_RELOCATING_SECTIONS): Ditto. (EXTRA_EM_FILE): New, set to sh64elf if not set. * emulparams/shlelf32.sh: Stub out all settings except OUTPUT_FORMAT. Source shelf32.sh. * emulparams/shelf64.sh: Similar, but also keep ELF_SIZE and OTHER_RELOCATING_SECTIONS. (OTHER_RELOCATING_SECTIONS): Remove .cranges. * emulparams/shlelf64.sh: Stub out all settings except OUTPUT_FORMAT. Source shelf64.sh. 2000-12-15 Hans-Peter Nilsson <hpn@cygnus.com> * emulparams/shelf64.sh (OTHER_RELOCATING_SECTIONS): Include .cranges section. (DATA_START_SYMBOLS): Define, provide ___data. (OTHER_READONLY_SYMBOLS): Define, provide ___rodata and align to 8 for consecutive .data section. (OTHER_GOT_SECTIONS): Define, align to 8 for consecutive .bss section after .data section. * emulparams/shlelf64.sh: Ditto. * emulparams/shelf32.sh: Ditto. (ALIGNMENT): Define to 8. * emulparams/shelf32.sh: Ditto. 2000-12-12 Hans-Peter Nilsson <hpn@cygnus.com> * configure.tgt (sh64-*-elf*): Assign targ_extra_libpath to get built-in linker scripts. 2000-11-30 Hans-Peter Nilsson <hpn@cygnus.com> * emulparams/shlelf64.sh: New. * emulparams/shelf64.sh: New. * configure.tgt (sh64-*-elf*): Add shelf64 and shlelf64 to targ_extra_emuls. * Makefile.am: Add support for shlelf64 and shelf64. * Makefile.in: Regenerate. 2000-11-29 Hans-Peter Nilsson <hpn@cygnus.com> * configure.tgt (sh64-*-elf*): Add shelf as default. Add shlelf to targ_extra_emuls. 2000-11-24 Hans-Peter Nilsson <hpn@cygnus.com> * emulparams/shelf32.sh: New file. * emulparams/shlelf32.sh: New file. * Makefile.am: Add support for shlelf32 and shelf32. * configure.tgt: Map sh64-*-elf* to shlelf32 and shelf32. * Makefile.in: Regenerate.
Diffstat (limited to 'ld/emultempl/sh64elf.em')
-rw-r--r--ld/emultempl/sh64elf.em568
1 files changed, 568 insertions, 0 deletions
diff --git a/ld/emultempl/sh64elf.em b/ld/emultempl/sh64elf.em
new file mode 100644
index 0000000000..ffa3906b8e
--- /dev/null
+++ b/ld/emultempl/sh64elf.em
@@ -0,0 +1,568 @@
+# This shell script emits a C file. -*- C -*-
+# Copyright (C) 2000, 2001 Free Software Foundation, Inc.
+#
+# This file is part of GLD, the Gnu Linker.
+#
+# 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.
+#
+
+# This file is sourced from elf32.em, and defines extra sh64
+# specific routines.
+#
+
+LDEMUL_AFTER_ALLOCATION=sh64_elf_${EMULATION_NAME}_after_allocation
+LDEMUL_BEFORE_ALLOCATION=sh64_elf_${EMULATION_NAME}_before_allocation
+
+cat >>e${EMULATION_NAME}.c <<EOF
+
+#include "libiberty.h"
+#include "libbfd.h"
+#include "elf-bfd.h"
+#include "elf/sh.h"
+
+static void sh64_elf_${EMULATION_NAME}_before_allocation PARAMS ((void));
+static void sh64_elf_${EMULATION_NAME}_after_allocation PARAMS ((void));
+
+/* Check if we need a .cranges section and create it if it's not in any
+ input file. It might seem better to always create it and if unneeded,
+ discard it, but I don't find a simple way to discard it totally from
+ the output.
+
+ Putting it here instead of as a elf_backend_always_size_sections hook
+ in elf32-sh64.c, means that we have access to linker command line
+ options here, and we can access input sections in the order in which
+ they will be linked. */
+
+static void
+sh64_elf_${EMULATION_NAME}_before_allocation ()
+{
+ asection *cranges;
+ asection *osec;
+
+ /* Call main function; we're just extending it. */
+ gld${EMULATION_NAME}_before_allocation ();
+
+ cranges = bfd_get_section_by_name (output_bfd, SH64_CRANGES_SECTION_NAME);
+
+ if (cranges != NULL)
+ {
+ if (command_line.relax)
+ {
+ /* FIXME: Look through incoming sections with .cranges
+ descriptors, build up some kind of descriptors that the
+ relaxing function will pick up and adjust, or perhaps make it
+ find and adjust an associated .cranges descriptor. We could
+ also look through incoming relocs and kill the ones marking
+ relaxation areas, but that wouldn't be TRT. */
+ einfo
+ (_("%P: Sorry, turning off relaxing: .cranges section in input.\n"));
+ einfo (_(" A .cranges section is present in:\n"));
+
+ {
+ LANG_FOR_EACH_INPUT_STATEMENT (f)
+ {
+ asection *input_cranges
+ = bfd_get_section_by_name (f->the_bfd,
+ SH64_CRANGES_SECTION_NAME);
+ if (input_cranges != NULL)
+ einfo (" %I\n", f);
+ }
+ }
+
+ command_line.relax = false;
+ }
+
+ /* We wouldn't need to do anything when there's already a .cranges
+ section (and have a return here), except that we need to set the
+ section flags right for output sections that *don't* need a
+ .cranges section. */
+ }
+
+ if (command_line.relax)
+ {
+ LANG_FOR_EACH_INPUT_STATEMENT (f)
+ {
+ if (bfd_get_flavour (f->the_bfd) == bfd_target_elf_flavour)
+ {
+ asection *isec;
+ for (isec = f->the_bfd->sections;
+ isec != NULL;
+ isec = isec->next)
+ {
+ if (elf_section_data (isec)->this_hdr.sh_flags
+ & (SHF_SH5_ISA32 | SHF_SH5_ISA32_MIXED))
+ {
+ einfo (_("%P: Sorry, turning off relaxing: SHmedia sections present.\n"));
+ einfo (" %I\n", f);
+ command_line.relax = false;
+ goto done_scanning_shmedia_sections;
+ }
+ }
+ }
+ }
+ }
+ done_scanning_shmedia_sections:
+
+ /* For each non-empty input section in each output section, check if it
+ has the same SH64-specific flags. If some input section differs, we
+ need a .cranges section. */
+ for (osec = output_bfd->sections;
+ osec != NULL;
+ osec = osec->next)
+ {
+ struct sh64_section_data *sh64_sec_data;
+ bfd_vma oflags_isa = 0;
+ bfd_vma iflags_isa = 0;
+
+ if (bfd_get_flavour (output_bfd) != bfd_target_elf_flavour)
+ einfo (_("%FError: non-ELF output formats are not supported by this target's linker.\n"));
+
+ sh64_sec_data = sh64_elf_section_data (osec);
+
+ /* Omit excluded or garbage-collected sections. */
+ if (bfd_get_section_flags (output_bfd, osec) & SEC_EXCLUDE)
+ continue;
+
+ /* Make sure we have the target section data initialized. */
+ if (sh64_sec_data == NULL)
+ {
+ sh64_sec_data = xcalloc (1, sizeof (struct sh64_section_data));
+ sh64_elf_section_data (osec) = sh64_sec_data;
+ }
+
+ /* First find an input section so we have flags to compare with; the
+ flags in the output section are not valid. */
+ {
+ LANG_FOR_EACH_INPUT_STATEMENT (f)
+ {
+ asection *isec;
+
+ for (isec = f->the_bfd->sections;
+ isec != NULL;
+ isec = isec->next)
+ {
+ if (isec->output_section == osec
+ && isec->_raw_size != 0
+ && (bfd_get_section_flags (isec->owner, isec)
+ & SEC_EXCLUDE) == 0)
+ {
+ oflags_isa
+ = (elf_section_data (isec)->this_hdr.sh_flags
+ & (SHF_SH5_ISA32 | SHF_SH5_ISA32_MIXED));
+ goto break_1;
+ }
+ }
+ }
+ }
+
+ break_1:
+
+ /* Check that all input sections have the same contents-type flags
+ as the first input section. */
+ {
+ LANG_FOR_EACH_INPUT_STATEMENT (f)
+ {
+ asection *isec;
+
+ for (isec = f->the_bfd->sections;
+ isec != NULL;
+ isec = isec->next)
+ {
+ if (isec->output_section == osec
+ && isec->_raw_size != 0
+ && (bfd_get_section_flags (isec->owner, isec)
+ & SEC_EXCLUDE) == 0)
+ {
+ iflags_isa
+ = (elf_section_data (isec)->this_hdr.sh_flags
+ & (SHF_SH5_ISA32 | SHF_SH5_ISA32_MIXED));
+
+ /* If flags don't agree, we need a .cranges section.
+ Create it here if it did not exist through input
+ sections. */
+ if (iflags_isa != oflags_isa)
+ {
+ if (cranges == NULL)
+ {
+ /* This section will be *appended* to
+ sections, so the outer iteration will reach
+ it in due time and set
+ sh64_elf_section_data; no need to set it
+ specifically here. */
+ cranges
+ = bfd_make_section (output_bfd,
+ SH64_CRANGES_SECTION_NAME);
+ if (cranges == NULL
+ || (bfd_set_section_flags (output_bfd,
+ cranges,
+ SEC_LINKER_CREATED
+ | SEC_KEEP
+ | SEC_HAS_CONTENTS
+ | SEC_DEBUGGING)
+ == false))
+ einfo
+ (_("%P%E%F: Can't make .cranges section\n"));
+ }
+
+ /* We don't need to look at more input sections,
+ and we know this section will have mixed
+ contents. */
+ goto break_2;
+ }
+ }
+ }
+ }
+ }
+
+ /* If we got here, then all input sections in this output section
+ have the same contents flag. Put that where we expect to see
+ contents flags. We don't need to do this for sections that will
+ need additional, linker-generated .cranges entries. */
+ sh64_sec_data->contents_flags = iflags_isa;
+
+ break_2:
+ ;
+ }
+}
+
+/* Size up and extend the .cranges section, merging generated entries. */
+
+static void
+sh64_elf_${EMULATION_NAME}_after_allocation ()
+{
+ bfd_vma new_cranges = 0;
+ bfd_vma cranges_growth = 0;
+ asection *osec;
+ bfd_byte *crangesp;
+
+ asection *cranges
+ = bfd_get_section_by_name (output_bfd, SH64_CRANGES_SECTION_NAME);
+
+ /* If this ever starts doing something, we will pick it up. */
+ after_allocation_default ();
+
+ /* If there is no .cranges section, it is because it was seen earlier on
+ that none was needed. Otherwise it must have been created then, or
+ be present in input. */
+ if (cranges == NULL)
+ return;
+
+ /* First, we set the ISA flags for each output section according to the
+ first non-discarded section. For each input section in osec, we
+ check if it has the same flags. If it does not, we set flags to mark
+ a mixed section (and exit the loop early). */
+ for (osec = output_bfd->sections;
+ osec != NULL;
+ osec = osec->next)
+ {
+ bfd_vma oflags_isa = 0;
+ boolean need_check_cranges = false;
+
+ /* Omit excluded or garbage-collected sections. */
+ if (bfd_get_section_flags (output_bfd, osec) & SEC_EXCLUDE)
+ continue;
+
+ /* First find an input section so we have flags to compare with; the
+ flags in the output section are not valid. */
+ {
+ LANG_FOR_EACH_INPUT_STATEMENT (f)
+ {
+ asection *isec;
+
+ for (isec = f->the_bfd->sections;
+ isec != NULL;
+ isec = isec->next)
+ {
+ if (isec->output_section == osec
+ && isec->_raw_size != 0
+ && (bfd_get_section_flags (isec->owner, isec)
+ & SEC_EXCLUDE) == 0)
+ {
+ oflags_isa
+ = (elf_section_data (isec)->this_hdr.sh_flags
+ & (SHF_SH5_ISA32 | SHF_SH5_ISA32_MIXED));
+ goto break_1;
+ }
+ }
+ }
+ }
+
+ break_1:
+
+ /* Check that all input sections have the same contents-type flags
+ as the first input section. */
+ {
+ LANG_FOR_EACH_INPUT_STATEMENT (f)
+ {
+ asection *isec;
+
+ for (isec = f->the_bfd->sections;
+ isec != NULL;
+ isec = isec->next)
+ {
+ if (isec->output_section == osec
+ && isec->_raw_size != 0
+ && (bfd_get_section_flags (isec->owner, isec)
+ & SEC_EXCLUDE) == 0)
+ {
+ bfd_vma iflags_isa
+ = (elf_section_data (isec)->this_hdr.sh_flags
+ & (SHF_SH5_ISA32 | SHF_SH5_ISA32_MIXED));
+
+ /* If flags don't agree, set the target-specific data
+ of the section to mark that this section needs to
+ be have .cranges section entries added. Don't
+ bother setting ELF section flags in output section;
+ they will be cleared later and will have to be
+ re-initialized before the linked file is written. */
+ if (iflags_isa != oflags_isa)
+ {
+ oflags_isa = SHF_SH5_ISA32_MIXED;
+
+ BFD_ASSERT (sh64_elf_section_data (osec) != NULL);
+
+ sh64_elf_section_data (osec)->contents_flags
+ = SHF_SH5_ISA32_MIXED;
+ need_check_cranges = true;
+ goto break_2;
+ }
+ }
+ }
+ }
+ }
+
+ break_2:
+
+ /* If there were no new ranges for this output section, we don't
+ need to iterate over the input sections to check how many are
+ needed. */
+ if (! need_check_cranges)
+ continue;
+
+ /* If we found a section with differing contents type, we need more
+ ranges to mark the sections that are not mixed (and already have
+ .cranges descriptors). Calculate the maximum number of new
+ entries here. We may merge some of them, so that number is not
+ final; it can shrink. */
+ {
+ LANG_FOR_EACH_INPUT_STATEMENT (f)
+ {
+ asection *isec;
+
+ for (isec = f->the_bfd->sections;
+ isec != NULL;
+ isec = isec->next)
+ {
+ if (isec->output_section == osec
+ && isec->_raw_size != 0
+ && (bfd_get_section_flags (isec->owner, isec)
+ & SEC_EXCLUDE) == 0
+ && ((elf_section_data (isec)->this_hdr.sh_flags
+ & (SHF_SH5_ISA32 | SHF_SH5_ISA32_MIXED))
+ != SHF_SH5_ISA32_MIXED))
+ new_cranges++;
+ }
+ }
+ }
+ }
+
+ BFD_ASSERT (cranges->contents == NULL);
+ BFD_ASSERT (sh64_elf_section_data (cranges) != NULL);
+
+ /* Make sure we have .cranges in memory even if there were only
+ assembler-generated .cranges. */
+ cranges_growth = new_cranges * SH64_CRANGE_SIZE;
+ cranges->contents
+ = (bfd_byte *) xcalloc (cranges->_raw_size + cranges_growth, 1);
+ bfd_set_section_flags (cranges->owner, cranges,
+ bfd_get_section_flags (cranges->owner, cranges)
+ | SEC_IN_MEMORY);
+
+ /* If we don't need to grow the .cranges section beyond what was in the
+ input sections, we have nothing more to do here. We then only got
+ here because there was a .cranges section coming from input. Zero
+ out the number of generated .cranges. */
+ if (new_cranges == 0)
+ {
+ sh64_elf_section_data (cranges)->cranges_growth = 0;
+ return;
+ }
+
+ crangesp = cranges->contents + cranges->_raw_size;
+
+ /* Now pass over the sections again, and make reloc orders for the new
+ .cranges entries. Constants are set as we go. */
+ for (osec = output_bfd->sections;
+ osec != NULL;
+ osec = osec->next)
+ {
+ struct bfd_link_order *cr_addr_order = NULL;
+ enum sh64_elf_cr_type last_cr_type = CRT_NONE;
+ bfd_vma last_cr_size = 0;
+ bfd_vma continuation_vma = 0;
+
+ /* Omit excluded or garbage-collected sections, and output sections
+ which were not marked as needing further processing. */
+ if ((bfd_get_section_flags (output_bfd, osec) & SEC_EXCLUDE) != 0
+ || (sh64_elf_section_data (osec)->contents_flags
+ != SHF_SH5_ISA32_MIXED))
+ continue;
+
+ {
+ LANG_FOR_EACH_INPUT_STATEMENT (f)
+ {
+ asection *isec;
+
+ for (isec = f->the_bfd->sections;
+ isec != NULL;
+ isec = isec->next)
+ {
+ /* Allow only sections that have (at least initially) a
+ non-zero size, and are not excluded, and are not marked
+ as containing mixed data, thus already having .cranges
+ entries. */
+ if (isec->output_section == osec
+ && isec->_raw_size != 0
+ && (bfd_get_section_flags (isec->owner, isec)
+ & SEC_EXCLUDE) == 0
+ && ((elf_section_data (isec)->this_hdr.sh_flags
+ & (SHF_SH5_ISA32 | SHF_SH5_ISA32_MIXED))
+ != SHF_SH5_ISA32_MIXED))
+ {
+ enum sh64_elf_cr_type cr_type;
+ bfd_vma cr_size;
+ bfd_vma isa_flags
+ = (elf_section_data (isec)->this_hdr.sh_flags
+ & (SHF_SH5_ISA32 | SHF_SH5_ISA32_MIXED));
+
+ if (isa_flags == SHF_SH5_ISA32)
+ cr_type = CRT_SH5_ISA32;
+ else if ((bfd_get_section_flags (isec->owner, isec)
+ & SEC_CODE) == 0)
+ cr_type = CRT_DATA;
+ else
+ cr_type = CRT_SH5_ISA16;
+
+ cr_size
+ = (isec->_cooked_size
+ ? isec->_cooked_size : isec->_raw_size);
+
+ /* Sections can be empty, like .text in a file that
+ only contains other sections. Ranges shouldn't be
+ emitted for them. This can presumably happen after
+ relaxing and is not be caught at the "raw size"
+ test above. */
+ if (cr_size == 0)
+ continue;
+
+ /* See if this is a continuation of the previous range
+ for the same output section. If so, just change
+ the size of the last range and continue. */
+ if (cr_type == last_cr_type
+ && (continuation_vma
+ == osec->vma + isec->output_offset))
+ {
+ last_cr_size += cr_size;
+ bfd_put_32 (output_bfd, last_cr_size,
+ crangesp - SH64_CRANGE_SIZE
+ + SH64_CRANGE_CR_SIZE_OFFSET);
+
+ continuation_vma += cr_size;
+ continue;
+ }
+
+ /* If we emit relocateable contents, we need a
+ relocation for the start address. */
+ if (link_info.relocateable || link_info.emitrelocations)
+ {
+ /* FIXME: We could perhaps use lang_add_reloc and
+ friends here, but I'm not really sure that
+ would leave us free to do some optimizations
+ later. */
+ cr_addr_order
+ = bfd_new_link_order (output_bfd, cranges);
+
+ if (cr_addr_order == NULL)
+ {
+ einfo (_("%P%F: bfd_new_link_order failed\n"));
+ return;
+ }
+
+ cr_addr_order->type = bfd_section_reloc_link_order;
+ cr_addr_order->offset
+ = (cranges->output_offset
+ + crangesp + SH64_CRANGE_CR_ADDR_OFFSET
+ - cranges->contents);
+ cr_addr_order->size = 4;
+ cr_addr_order->u.reloc.p
+ = ((struct bfd_link_order_reloc *)
+ xmalloc (sizeof (struct bfd_link_order_reloc)));
+
+ cr_addr_order->u.reloc.p->reloc = BFD_RELOC_32;
+ cr_addr_order->u.reloc.p->u.section = osec;
+
+ /* Since SH, unlike normal RELA-targets, uses a
+ "partial inplace" REL-like relocation for this,
+ we put the addend in the contents and specify 0
+ for the reloc. */
+ bfd_put_32 (output_bfd, isec->output_offset,
+ crangesp + SH64_CRANGE_CR_ADDR_OFFSET);
+ cr_addr_order->u.reloc.p->addend = 0;
+
+ /* We must update the number of relocations here,
+ since the elf linker does not take link orders
+ into account when setting header sizes. The
+ actual relocation orders are however executed
+ correctly. */
+ elf_section_data(cranges)->rel_count++;
+ }
+ else
+ bfd_put_32 (output_bfd,
+ osec->vma + isec->output_offset,
+ crangesp + SH64_CRANGE_CR_ADDR_OFFSET);
+
+ /* If we could make a reloc for cr_size we would do
+ it, but we would have to have a symbol for the size
+ of the _input_ section and there's no way to
+ generate that. */
+ bfd_put_32 (output_bfd, cr_size,
+ crangesp + SH64_CRANGE_CR_SIZE_OFFSET);
+
+ bfd_put_16 (output_bfd, (bfd_vma) cr_type,
+ crangesp + SH64_CRANGE_CR_TYPE_OFFSET);
+
+ last_cr_type = cr_type;
+ last_cr_size = cr_size;
+ continuation_vma
+ = osec->vma + isec->output_offset + cr_size;
+ crangesp += SH64_CRANGE_SIZE;
+ }
+ }
+ }
+ }
+ }
+
+ /* The .cranges section will have this size, no larger or smaller.
+ Since relocs (if relocateable linking) will be emitted into the
+ "extended" size, we must set the raw size to the total. We have to
+ keep track of the number of new .cranges entries.
+
+ Sorting before writing is done by sh64_elf_final_write_processing. */
+
+ cranges->_cooked_size = crangesp - cranges->contents;
+ sh64_elf_section_data (cranges)->cranges_growth
+ = cranges->_cooked_size - cranges->_raw_size;
+ cranges->_raw_size = cranges->_cooked_size;
+}