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 ld


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: ld/ChangeLog
from  Alexandre Oliva  <aoliva@redhat.com>

	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.

Index: ld/Makefile.am
===================================================================
RCS file: /home/aoliva/cygnus/uberbaum/ld/Makefile.am,v
retrieving revision 1.86
diff -u -p -r1.86 Makefile.am
--- ld/Makefile.am 2 Feb 2002 18:36:04 -0000 1.86
+++ ld/Makefile.am 3 Feb 2002 00:59:17 -0000
@@ -237,6 +237,8 @@ ALL_EMULATIONS = \
 	eriscix.o \
 	esa29200.o \
 	esh.o \
+	eshelf32.o \
+	eshlelf32.o \
 	eshelf.o \
 	eshelf_linux.o \
 	eshlelf_linux.o \
@@ -266,6 +268,8 @@ ALL_EMULATIONS = \
 ALL_64_EMULATIONS = \
 	eelf64_aix.o \
 	eelf64_ia64.o \
+	eshelf64.o \
+	eshlelf64.o \
 	eelf_x86_64.o \
 	eelf64_s390.o \
 	eelf64_sparc.o \
@@ -840,6 +844,14 @@ esh.c: $(srcdir)/emulparams/sh.sh \
 eshelf.c: $(srcdir)/emulparams/shelf.sh \
   $(srcdir)/emultempl/elf32.em $(srcdir)/scripttempl/elf.sc ${GEN_DEPENDS}
 	${GENSCRIPTS} shelf "$(tdir_shelf)"
+eshelf32.c: $(srcdir)/emulparams/shelf32.sh \
+  $(BFDDIR)/libbfd.h $(INCDIR)/libiberty.h \
+  $(srcdir)/emultempl/sh64elf.em $(INCDIR)/elf/sh.h $(BFDDIR)/elf-bfd.h \
+  $(srcdir)/emultempl/elf32.em $(srcdir)/scripttempl/elf.sc ${GEN_DEPENDS}
+	${GENSCRIPTS} shelf32 "$(tdir_shelf32)"
+eshelf64.c: $(srcdir)/emulparams/shelf64.sh $(srcdir)/emulparams/shelf32.sh \
+  $(srcdir)/emultempl/elf32.em $(srcdir)/scripttempl/elf.sc ${GEN_DEPENDS}
+	${GENSCRIPTS} shelf64 "$(tdir_shelf64)"
 eshelf_linux.c: $(srcdir)/emulparams/shelf_linux.sh \
   $(srcdir)/emulparams/shlelf_linux.sh \
   $(srcdir)/emultempl/elf32.em $(srcdir)/scripttempl/elf.sc ${GEN_DEPENDS}
@@ -860,6 +872,15 @@ eshlelf.c: $(srcdir)/emulparams/shlelf.s
   $(srcdir)/emulparams/shelf.sh \
   $(srcdir)/emultempl/elf32.em $(srcdir)/scripttempl/elf.sc ${GEN_DEPENDS}
 	${GENSCRIPTS} shlelf "$(tdir_shlelf)"
+eshlelf32.c: $(srcdir)/emulparams/shlelf32.sh \
+  $(BFDDIR)/libbfd.h $(INCDIR)/libiberty.h $(srcdir)/emulparams/shelf32.sh \
+  $(srcdir)/emultempl/sh64elf.em $(INCDIR)/elf/sh.h $(BFDDIR)/elf-bfd.h \
+  $(srcdir)/emultempl/elf32.em $(srcdir)/scripttempl/elf.sc ${GEN_DEPENDS}
+	${GENSCRIPTS} shlelf32 "$(tdir_shlelf32)"
+eshlelf64.c: $(srcdir)/emulparams/shlelf64.sh \
+  $(srcdir)/emulparams/shelf64.sh $(srcdir)/emulparams/shelf32.sh \
+  $(srcdir)/emultempl/elf32.em $(srcdir)/scripttempl/elf.sc ${GEN_DEPENDS}
+	${GENSCRIPTS} shlelf64 "$(tdir_shlelf64)"
 eshl.c: $(srcdir)/emulparams/shl.sh \
   $(srcdir)/emulparams/sh.sh \
   $(srcdir)/emultempl/generic.em $(srcdir)/scripttempl/sh.sc ${GEN_DEPENDS}
Index: ld/configure.tgt
===================================================================
RCS file: /home/aoliva/cygnus/uberbaum/ld/configure.tgt,v
retrieving revision 1.79
diff -u -p -r1.79 configure.tgt
--- ld/configure.tgt 2 Feb 2002 18:36:04 -0000 1.79
+++ ld/configure.tgt 3 Feb 2002 00:59:18 -0000
@@ -272,6 +272,11 @@ sh-*-elf* | sh-*-rtemself*)
 sh-*-pe)		targ_emul=shpe ;
 			targ_extra_ofiles="deffilep.o pe-dll.o" ;;
 sh-*-*|sh-*-rtems*)	targ_emul=sh; targ_extra_emuls=shl ;;
+sh64-*-elf*)
+			targ_emul=shelf
+			targ_extra_emuls="shlelf shelf32 shlelf32 shelf64 shlelf64"
+			targ_extra_libpath=$targ_extra_emuls
+			;;
 m68k-sony-*)		targ_emul=news ;;
 m68k-hp-bsd*)		targ_emul=hp300bsd ;;
 m68*-motorola-sysv*)	targ_emul=delta68 ;;
Index: ld/emulparams/shelf32.sh
===================================================================
RCS file: ld/emulparams/shelf32.sh
diff -N ld/emulparams/shelf32.sh
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ ld/emulparams/shelf32.sh 2 Feb 2002 04:00:47 -0000
@@ -0,0 +1,43 @@
+# Note: this parameter script is sourced by the other
+# sh[l]elf(32|64).sh parameter scripts.
+SCRIPT_NAME=elf
+OUTPUT_FORMAT=${OUTPUT_FORMAT-"elf32-sh64"}
+TEXT_START_ADDR=0x1000
+STACK_ADDR='ALIGN (0x40000) + 0x40000'
+MAXPAGESIZE=128
+ARCH=sh
+MACHINE=
+ALIGNMENT=8
+TEMPLATE_NAME=elf32
+GENERATE_SHLIB_SCRIPT=yes
+EMBEDDED=yes
+
+DATA_START_SYMBOLS='PROVIDE (___data = .);'
+
+# If data is located right after .text (not explicitly specified),
+# then we need to align it to an 8-byte boundary.
+OTHER_READONLY_SECTIONS='
+PROVIDE (___rodata = DEFINED (.rodata) ? .rodata : 0);
+. = ALIGN (8);
+'
+
+# Make _edata and .bss aligned by smuggling in an alignment directive.
+OTHER_GOT_SECTIONS='. = ALIGN (8);'
+
+# These are for compatibility with the COFF toolchain.
+ENTRY=start
+CTOR_START='___ctors = .;'
+CTOR_END='___ctors_end = .;'
+DTOR_START='___dtors = .;'
+DTOR_END='___dtors_end = .;'
+
+# Do not use the varname=${varname-'string'} construct here; there are
+# problems with that on some shells (e.g. on Solaris) where there is a bug
+# that trigs when $varname contains a "}".
+OTHER_SECTIONS='
+ .cranges 0 : { *(.cranges) }
+'
+
+# We need to adjust sizes in the .cranges section after relaxation, so
+# we need an after_allocation function, and it goes in this file.
+EXTRA_EM_FILE=${EXTRA_EM_FILE-sh64elf}
Index: ld/emulparams/shelf64.sh
===================================================================
RCS file: ld/emulparams/shelf64.sh
diff -N ld/emulparams/shelf64.sh
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ ld/emulparams/shelf64.sh 2 Feb 2002 04:00:47 -0000
@@ -0,0 +1,9 @@
+# Note: this is sourced in turn by shlelf64.sh
+OUTPUT_FORMAT=${OUTPUT_FORMAT-"elf64-sh64"}
+ELFSIZE=64
+
+EXTRA_EM_FILE=
+. ${srcdir}/emulparams/shelf32.sh
+
+# We do not need .cranges
+OTHER_SECTIONS=''
Index: ld/emulparams/shlelf32.sh
===================================================================
RCS file: ld/emulparams/shlelf32.sh
diff -N ld/emulparams/shlelf32.sh
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ ld/emulparams/shlelf32.sh 2 Feb 2002 04:00:47 -0000
@@ -0,0 +1,2 @@
+OUTPUT_FORMAT="elf32-sh64l"
+. ${srcdir}/emulparams/shelf32.sh
Index: ld/emulparams/shlelf64.sh
===================================================================
RCS file: ld/emulparams/shlelf64.sh
diff -N ld/emulparams/shlelf64.sh
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ ld/emulparams/shlelf64.sh 2 Feb 2002 04:00:47 -0000
@@ -0,0 +1,2 @@
+OUTPUT_FORMAT="elf64-sh64l"
+. ${srcdir}/emulparams/shelf64.sh
Index: ld/emultempl/sh64elf.em
===================================================================
RCS file: ld/emultempl/sh64elf.em
diff -N ld/emultempl/sh64elf.em
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ ld/emultempl/sh64elf.em 2 Feb 2002 04:00:47 -0000
@@ -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;
+}

-- 
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]