From: David McCullough <davidm@snapgear.com>
Date: Fri, 21 Jul 2006 13:11:04 +0000 (+0000)
Subject: This patch adds elf2flt support for prioritised constructors and destructors,
X-Git-Url: https://git.wh0rd.org/?a=commitdiff_plain;h=38d2a6bded9d7aab9311046639e75f0ae41aadc5;p=elf2flt.git

This patch adds elf2flt support for prioritised constructors and destructors,
but only when --enable-emit-relocs is in effect.

GCC puts prioritised constructors and destructors in special .ctor.N
and .dtor.N sections (where N encodes the priority).  The constructors
and destructors in these sections have a lower priority than those
in the default .ctor and .dtor sections.  However, we need to treat
the crtbegin.o's and crtend.o's sections specially; crtbegin.o's .[cd]tor
sections must come before all the other .[cd]tor* contents and crtend.o's
.[cd]tor sections must come after all other contents.

In --disable-emit-relocs links, it wasn't possible to treat crtbegin.o
and crtend.o specially.  ld-elf2flt would do:

                ld -r -o foo.elf2flt ...input objects...
                    |                               |
            ld -r -o foo.elf foo.elf2flt -T script  |
                                                    |
                                   ld -o foo.gdb foo.elf2flt -T script

so all the input .[cd]tor sections would already be lumped together by the
time the script was used.  This isn't a problem for --enable-emit-relocs as
it only links once.

The patch copies the [cd]tor support from the standard binutils linker
script.  The question is: should the new lines be used unconditionally,
or only when --enable-emit-relocs is in effect?

We could use the new lines for --disable-emit-relocs without breaking
programs that don't use prioritised [cd]tors.  However, it would be a user
interface regression for programs that _do_ use them.  At the moment,
if you try to use prioritised [cd]tors with --disable-emit-relocs,
you get a linker error like this:

   error: no memory region specified for loadable section `.ctors.60535'

With the new lines, the link would silently succeed, and you'd get a
runtime failure instead.  I've therefore guarded the lines with
"SINGLE_LINK:", a bit like the "W_RODAT" stuff that's already there.

Tested on Coldfire, with both --enable-emit-relocs and
--disable-emit-relocs.  It fixes the GCC ecos.exp tests.
Please install if OK.

Richard

Signed-off-by: Richard Sandiford <richard@codesourcery.com>
---

diff --git a/elf2flt.ld b/elf2flt.ld
index 0c2e71d..cd4e652 100644
--- a/elf2flt.ld
+++ b/elf2flt.ld
@@ -91,12 +91,31 @@ R_RODAT		*(.gnu.linkonce.r*)
 		. = ALIGN(4) ;
 		__CTOR_LIST__ = .;
 		LONG((__CTOR_END__ - __CTOR_LIST__) / 4 - 2)
-		*(.ctors)
+SINGLE_LINK:	/* gcc uses crtbegin.o to find the start of
+SINGLE_LINK:	   the constructors, so we make sure it is
+SINGLE_LINK:	   first.  Because this is a wildcard, it
+SINGLE_LINK:	   doesn't matter if the user does not
+SINGLE_LINK:	   actually link against crtbegin.o; the
+SINGLE_LINK:	   linker won't look for a file to match a
+SINGLE_LINK:	   wildcard.  The wildcard also means that it
+SINGLE_LINK:	   doesn't matter which directory crtbegin.o
+SINGLE_LINK:	   is in.  */
+SINGLE_LINK:	KEEP (*crtbegin*.o(.ctors))
+SINGLE_LINK:	/* We don't want to include the .ctor section from
+SINGLE_LINK:	   from the crtend.o file until after the sorted ctors.
+SINGLE_LINK:	   The .ctor section from the crtend file contains the
+SINGLE_LINK:	   end of ctors marker and it must be last */
+SINGLE_LINK:	KEEP (*(EXCLUDE_FILE (*crtend*.o ) .ctors))
+SINGLE_LINK:	KEEP (*(SORT(.ctors.*)))
+		KEEP (*(.ctors))
 		LONG(0)
 		__CTOR_END__ = .;
 		__DTOR_LIST__ = .;
 		LONG((__DTOR_END__ - __DTOR_LIST__) / 4 - 2)
-		*(.dtors)
+SINGLE_LINK:	KEEP (*crtbegin*.o(.dtors))
+SINGLE_LINK:	KEEP (*(EXCLUDE_FILE (*crtend*.o ) .dtors))
+SINGLE_LINK:	KEEP (*(SORT(.dtors.*)))
+		KEEP (*(.dtors))
 		LONG(0)
 		__DTOR_END__ = .;
 
diff --git a/ld-elf2flt.in b/ld-elf2flt.in
index 134ea45..ff7a734 100644
--- a/ld-elf2flt.in
+++ b/ld-elf2flt.in
@@ -127,6 +127,12 @@ then
 			esac
 			ARG1="$ARG1 -defsym $GOT_OFFSET=`expr ${SHARED_ID} '*' -4 - 4`"
 		fi
+		if [ "@emit_relocs@" = "yes" ]
+		then
+			SEDOP="$SEDOP -e s/^SINGLE_LINK://"
+		else
+			SEDOP="$SEDOP -e /^SINGLE_LINK:/d"
+		fi
 		
 		# provide a default linker script, we usually need one
 		[ -z "$LDSCRIPT" ] && LDSCRIPT="${LDSCRIPTPATH}/elf2flt.ld"