Add SORT_BY_INIT_PRIORITY.
authorH.J. Lu <hjl.tools@gmail.com>
Wed, 15 Dec 2010 14:56:40 +0000 (14:56 +0000)
committerH.J. Lu <hjl.tools@gmail.com>
Wed, 15 Dec 2010 14:56:40 +0000 (14:56 +0000)
bfd/

2010-12-15  H.J. Lu  <hongjiu.lu@intel.com>

* elf.c (_bfd_elf_new_section_hook): Special handling for
.init_array/.fini_array output sections.

ld/

2010-12-15  H.J. Lu  <hongjiu.lu@intel.com>

* Makefile.am (GENSCRIPTS): Add @enable_initfini_array@.

* NEWS: Mention SORT_BY_INIT_PRIORITY.

* configure.in: Add AC_CANONICAL_BUILD.
Add --enable-initfini-array.

* genscripts.sh (ENABLE_INITFINI_ARRAY): New.

* ld.h (sort_type): Add by_init_priority.

* ld.texinfo: Document SORT_BY_INIT_PRIORITY.

* ldgram.y (SORT_BY_INIT_PRIORITY): New.
(wildcard_spec): Handle SORT_BY_INIT_PRIORITY.

* ldlang.c (get_init_priority): New.
(compare_section): Use get_init_priority for by_init_priority.

* ldlex.l (SORT_BY_INIT_PRIORITY): New.

* scripttempl/elf.sc: Support ENABLE_INITFINI_ARRAY.

* Makefile.in: Regenerated.
* aclocal.m4: Regenerated.
* config.in: Likewise.
* configure: Likewise.

ld/testsuite/

2010-12-15  H.J. Lu  <hongjiu.lu@intel.com>

* ld-elf/elf.exp (array_tests): Add init-mixed.
(array_tests_static): Likewise.
Also delete tmpdir/init-mixed.

* ld-elf/init-mixed.c: New.
* ld-elf/init-mixed.out: Likewise.

20 files changed:
bfd/ChangeLog
bfd/elf.c
ld/ChangeLog
ld/Makefile.am
ld/Makefile.in
ld/NEWS
ld/config.in
ld/configure
ld/configure.in
ld/genscripts.sh
ld/ld.h
ld/ld.texinfo
ld/ldgram.y
ld/ldlang.c
ld/ldlex.l
ld/scripttempl/elf.sc
ld/testsuite/ChangeLog
ld/testsuite/ld-elf/elf.exp
ld/testsuite/ld-elf/init-mixed.c [new file with mode: 0644]
ld/testsuite/ld-elf/init-mixed.out [new file with mode: 0644]

index 8e1246178b44b8d1636cef9a84b48b2c6518b0bc..fcf2843931999c8354887dd3b158b8fae3d36f90 100644 (file)
@@ -1,3 +1,8 @@
+2010-12-15  H.J. Lu  <hongjiu.lu@intel.com>
+
+       * elf.c (_bfd_elf_new_section_hook): Special handling for
+       .init_array/.fini_array output sections.
+
 2010-12-13  Alan Modra  <amodra@gmail.com>
 
        * aoutx.h (aout_link_check_ar_symbols): Formatting.
index 0e7cd9af6e4e5ba3ec5e0f5499c2f5e65e65908e..de0ab61dcb6875c1cbe8ca6d75273e787ff74e38 100644 (file)
--- a/bfd/elf.c
+++ b/bfd/elf.c
@@ -2304,12 +2304,19 @@ _bfd_elf_new_section_hook (bfd *abfd, asection *sec)
      anyway.  We will set ELF section type and flags for all linker
      created sections.  If user specifies BFD section flags, we will
      set ELF section type and flags based on BFD section flags in
-     elf_fake_sections.  */
-  if ((!sec->flags && abfd->direction != read_direction)
+     elf_fake_sections.  Special handling for .init_array/.fini_array
+     output sections since they may contain .ctors/.dtors input
+     sections.  We don't want _bfd_elf_init_private_section_data to
+     copy ELF section type from .ctors/.dtors input sections.  */
+  if (abfd->direction != read_direction
       || (sec->flags & SEC_LINKER_CREATED) != 0)
     {
       ssect = (*bed->get_sec_type_attr) (abfd, sec);
-      if (ssect != NULL)
+      if (ssect != NULL
+         && (!sec->flags
+             || (sec->flags & SEC_LINKER_CREATED) != 0
+             || ssect->type == SHT_INIT_ARRAY
+             || ssect->type == SHT_FINI_ARRAY))
        {
          elf_section_type (sec) = ssect->type;
          elf_section_flags (sec) = ssect->attr;
index d41197b33850aaba829959a51465d60116fd3617..c145a7e5ad9285cce6a97772b2f9d61020314742 100644 (file)
@@ -1,3 +1,33 @@
+2010-12-15  H.J. Lu  <hongjiu.lu@intel.com>
+
+       * Makefile.am (GENSCRIPTS): Add @enable_initfini_array@.
+
+       * NEWS: Mention SORT_BY_INIT_PRIORITY.
+
+       * configure.in: Add AC_CANONICAL_BUILD.
+       Add --enable-initfini-array.
+
+       * genscripts.sh (ENABLE_INITFINI_ARRAY): New.
+
+       * ld.h (sort_type): Add by_init_priority.
+
+       * ld.texinfo: Document SORT_BY_INIT_PRIORITY.
+
+       * ldgram.y (SORT_BY_INIT_PRIORITY): New.
+       (wildcard_spec): Handle SORT_BY_INIT_PRIORITY.
+
+       * ldlang.c (get_init_priority): New.
+       (compare_section): Use get_init_priority for by_init_priority.
+
+       * ldlex.l (SORT_BY_INIT_PRIORITY): New.
+
+       * scripttempl/elf.sc: Support ENABLE_INITFINI_ARRAY.
+
+       * Makefile.in: Regenerated.
+       * aclocal.m4: Regenerated.
+       * config.in: Likewise.
+       * configure: Likewise.
+
 2010-12-13  Alan Modra  <amodra@gmail.com>
 
        * ldlang.c (load_symbols): Correct last change.
index d9e1bcca243f36523b26e78c1d9d11828e3f55e8..9f016df0ab573999b928e3537e71596efa725894 100644 (file)
@@ -611,7 +611,7 @@ stringify.sed: ${srcdir}/emultempl/$(STRINGIFY)
 
 # These all start with e so 'make clean' can find them.
 
-GENSCRIPTS = LIB_PATH='${LIB_PATH}' $(SHELL) $(srcdir)/genscripts.sh "${srcdir}" "${libdir}" "${prefix}" "${exec_prefix}" @host@ @target@ @target_alias@ "@EMULATION_LIBPATH@" "@NATIVE_LIB_DIRS@" @use_sysroot@
+GENSCRIPTS = LIB_PATH='${LIB_PATH}' $(SHELL) $(srcdir)/genscripts.sh "${srcdir}" "${libdir}" "${prefix}" "${exec_prefix}" @host@ @target@ @target_alias@ "@EMULATION_LIBPATH@" "@NATIVE_LIB_DIRS@" @use_sysroot@ @enable_initfini_array@
 GEN_DEPENDS = $(srcdir)/genscripts.sh stringify.sed
 ELF_DEPS = $(srcdir)/emultempl/elf32.em $(srcdir)/emultempl/elf-generic.em
 ELF_GEN_DEPS = $(srcdir)/emultempl/generic.em $(srcdir)/emultempl/elf-generic.em $(srcdir)/emultempl/genelf.em
index 01511bcf6eec7e041c80382dbe2f712221dfba17..3cb62347ea4b02e31556c8e127083c68db86038e 100644 (file)
@@ -299,6 +299,7 @@ datarootdir = @datarootdir@
 do_compare = @do_compare@
 docdir = @docdir@
 dvidir = @dvidir@
+enable_initfini_array = @enable_initfini_array@
 exec_prefix = @exec_prefix@
 host = @host@
 host_alias = @host_alias@
@@ -797,7 +798,7 @@ EMULATION_FILES = emultempl/pe.em emultempl/armcoff.em
 POTFILES = $(CFILES) $(HFILES) $(EMULATION_FILES)
 
 # These all start with e so 'make clean' can find them.
-GENSCRIPTS = LIB_PATH='${LIB_PATH}' $(SHELL) $(srcdir)/genscripts.sh "${srcdir}" "${libdir}" "${prefix}" "${exec_prefix}" @host@ @target@ @target_alias@ "@EMULATION_LIBPATH@" "@NATIVE_LIB_DIRS@" @use_sysroot@
+GENSCRIPTS = LIB_PATH='${LIB_PATH}' $(SHELL) $(srcdir)/genscripts.sh "${srcdir}" "${libdir}" "${prefix}" "${exec_prefix}" @host@ @target@ @target_alias@ "@EMULATION_LIBPATH@" "@NATIVE_LIB_DIRS@" @use_sysroot@ @enable_initfini_array@
 GEN_DEPENDS = $(srcdir)/genscripts.sh stringify.sed
 ELF_DEPS = $(srcdir)/emultempl/elf32.em $(srcdir)/emultempl/elf-generic.em
 ELF_GEN_DEPS = $(srcdir)/emultempl/generic.em $(srcdir)/emultempl/elf-generic.em $(srcdir)/emultempl/genelf.em
diff --git a/ld/NEWS b/ld/NEWS
index eaa5b0bca34a07fd6a728315f710df7884685240..b303490cd0b0c27f34f9b4d84669d658da6bc19a 100644 (file)
--- a/ld/NEWS
+++ b/ld/NEWS
@@ -1,5 +1,9 @@
 -*- text -*-
 
+* Added SORT_BY_INIT_PRIORITY to the linker script language to permit
+sorting sections by numerical value of the GCC init_priority attribute
+encoded in the section name.
+
 Changes in 2.21:
 
 
index f49327c11a7c23455d7ca14af0d57cc37dbe1b7a..929da9088f349c45c1a4ab8c95cbae9a46b7b2a0 100644 (file)
@@ -61,6 +61,9 @@
 /* Define to 1 if you have the `glob' function. */
 #undef HAVE_GLOB
 
+/* Define .init_array/.fini_array sections are available and working. */
+#undef HAVE_INITFINI_ARRAY
+
 /* Define to 1 if you have the <inttypes.h> header file. */
 #undef HAVE_INTTYPES_H
 
index 088c721de775db83cfae6dede46b57d833384afc..a6802ddc318b22695f133ec7d415da7719f37e39 100755 (executable)
@@ -609,6 +609,7 @@ EMUL_EXTRA_OFILES
 EMULATION_OFILES
 EMUL
 STRINGIFY
+enable_initfini_array
 ENABLE_PLUGINS_FALSE
 ENABLE_PLUGINS_TRUE
 NATIVE_LIB_DIRS
@@ -778,6 +779,7 @@ enable_fast_install
 with_gnu_ld
 enable_libtool_lock
 enable_nls
+enable_initfini_array
 '
       ac_precious_vars='build_alias
 host_alias
@@ -1427,6 +1429,7 @@ Optional Features:
                           optimize for fast installation [default=yes]
   --disable-libtool-lock  avoid locking (might break parallel builds)
   --disable-nls           do not use Native Language Support
+  --enable-initfini-array      use .init_array/.fini_array sections
 
 Optional Packages:
   --with-PACKAGE[=ARG]    use PACKAGE [ARG=yes]
@@ -2591,6 +2594,7 @@ test -n "$target_alias" &&
   test "$program_prefix$program_suffix$program_transform_name" = \
     NONENONEs,x,x, &&
   program_prefix=${target_alias}-
+
 ac_ext=c
 ac_cpp='$CPP $CPPFLAGS'
 ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
@@ -11622,7 +11626,7 @@ else
   lt_dlunknown=0; lt_dlno_uscore=1; lt_dlneed_uscore=2
   lt_status=$lt_dlunknown
   cat > conftest.$ac_ext <<_LT_EOF
-#line 11625 "configure"
+#line 11629 "configure"
 #include "confdefs.h"
 
 #if HAVE_DLFCN_H
@@ -11728,7 +11732,7 @@ else
   lt_dlunknown=0; lt_dlno_uscore=1; lt_dlneed_uscore=2
   lt_status=$lt_dlunknown
   cat > conftest.$ac_ext <<_LT_EOF
-#line 11731 "configure"
+#line 11735 "configure"
 #include "confdefs.h"
 
 #if HAVE_DLFCN_H
@@ -12944,6 +12948,54 @@ else
 fi
 
 
+# Check whether --enable-initfini-array was given.
+if test "${enable_initfini_array+set}" = set; then :
+  enableval=$enable_initfini_array;
+else
+
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for .preinit_array/.init_array/.fini_array support" >&5
+$as_echo_n "checking for .preinit_array/.init_array/.fini_array support... " >&6; }
+if test "${gcc_cv_initfini_array+set}" = set; then :
+  $as_echo_n "(cached) " >&6
+else
+    if test "x${build}" = "x${target}" ; then
+    if test "$cross_compiling" = yes; then :
+  gcc_cv_initfini_array=no
+else
+  cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+
+static int x = -1;
+int main (void) { return x; }
+int foo (void) { x = 0; }
+int (*fp) (void) __attribute__ ((section (".init_array"))) = foo;
+_ACEOF
+if ac_fn_c_try_run "$LINENO"; then :
+  gcc_cv_initfini_array=yes
+else
+  gcc_cv_initfini_array=no
+fi
+rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext \
+  conftest.$ac_objext conftest.beam conftest.$ac_ext
+fi
+
+   else
+     gcc_cv_initfini_array=no
+   fi
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $gcc_cv_initfini_array" >&5
+$as_echo "$gcc_cv_initfini_array" >&6; }
+  enable_initfini_array=$gcc_cv_initfini_array
+
+fi
+
+
+if test $enable_initfini_array = yes; then
+
+$as_echo "#define HAVE_INITFINI_ARRAY 1" >>confdefs.h
+
+fi
+
 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for a known getopt prototype in unistd.h" >&5
 $as_echo_n "checking for a known getopt prototype in unistd.h... " >&6; }
 if test "${ld_cv_decl_getopt_unistd_h+set}" = set; then :
index 85fe903d3b17267ffd8cdd0d7fd6652168e4d15a..15d7685c0252d5562b86eccd4a8fcefcd56e31c7 100644 (file)
@@ -5,6 +5,7 @@ AC_INIT
 AC_CONFIG_SRCDIR(ldmain.c)
 
 AC_CANONICAL_TARGET
+AC_CANONICAL_BUILD
 AC_ISC_POSIX
 
 changequote(,)dnl
@@ -175,6 +176,30 @@ if test x$enable_plugins = xno ; then
 fi
 AM_CONDITIONAL([ENABLE_PLUGINS], [test x$enable_plugins = xyes])
 
+AC_ARG_ENABLE(initfini-array,
+       [  --enable-initfini-array      use .init_array/.fini_array sections],
+       [], [
+AC_CACHE_CHECK(for .preinit_array/.init_array/.fini_array support,
+                gcc_cv_initfini_array, [dnl
+  if test "x${build}" = "x${target}" ; then
+    AC_RUN_IFELSE([AC_LANG_SOURCE([
+static int x = -1;
+int main (void) { return x; }
+int foo (void) { x = 0; }
+int (*fp) (void) __attribute__ ((section (".init_array"))) = foo;])],
+            [gcc_cv_initfini_array=yes], [gcc_cv_initfini_array=no],
+            [gcc_cv_initfini_array=no])
+   else
+     gcc_cv_initfini_array=no
+   fi])
+  enable_initfini_array=$gcc_cv_initfini_array
+])
+AC_SUBST(enable_initfini_array)
+if test $enable_initfini_array = yes; then
+  AC_DEFINE(HAVE_INITFINI_ARRAY, 1,
+    [Define .init_array/.fini_array sections are available and working.])
+fi
+
 AC_MSG_CHECKING(for a known getopt prototype in unistd.h)
 AC_CACHE_VAL(ld_cv_decl_getopt_unistd_h,
 [AC_COMPILE_IFELSE([AC_LANG_PROGRAM([#include <unistd.h>], [extern int getopt (int, char *const*, const char *);])],
index c86631b500a551d72f3699e7977113cc496514b7..61981bdd81ccd26572645ea238169c84a617ac6d 100755 (executable)
@@ -30,6 +30,7 @@
 #          default_emulation \
 #          native_lib_dirs \
 #          use_sysroot \
+#          enable_initfini_array \
 #          this_emulation \
 # optional:
 #          tool_dir \
@@ -89,9 +90,10 @@ EMULATION_LIBPATH=$8
 NATIVE_LIB_DIRS=$9
 shift 9
 use_sysroot=$1
-EMULATION_NAME=$2
-TOOL_LIB=$3
-CUSTOMIZER_SCRIPT=$4
+ENABLE_INITFINI_ARRAY=$2
+EMULATION_NAME=$3
+TOOL_LIB=$4
+CUSTOMIZER_SCRIPT=$5
 
 # Can't use ${TOOL_LIB:-$target_alias} here due to an Ultrix shell bug.
 if [ "x${TOOL_LIB}" = "x" ] ; then
diff --git a/ld/ld.h b/ld/ld.h
index aa0979d6f272ab9e7d895945b284bab743739686..21323d89f6181ca2a7667646a9571ded81dbc70b 100644 (file)
--- a/ld/ld.h
+++ b/ld/ld.h
@@ -86,7 +86,8 @@ typedef enum {sort_none, sort_ascending, sort_descending} sort_order;
 /* A wildcard specification.  */
 
 typedef enum {
-  none, by_name, by_alignment, by_name_alignment, by_alignment_name
+  none, by_name, by_alignment, by_name_alignment, by_alignment_name,
+  by_init_priority
 } sort_type;
 
 extern sort_type sort_section;
index 4c58e4855c9999cb4e8f065f34a08a130b7fe64a..6d36dfb63ddb60a8fd22779b2af028b9ba22b403 100644 (file)
@@ -3911,6 +3911,12 @@ into ascending order by name before placing them in the output file.
 difference is @code{SORT_BY_ALIGNMENT} will sort sections into
 ascending order by alignment before placing them in the output file.
 
+@cindex SORT_BY_INIT_PRIORITY
+@code{SORT_BY_INIT_PRIORITY} is very similar to @code{SORT_BY_NAME}. The
+difference is @code{SORT_BY_INIT_PRIORITY} will sort sections into
+ascending order by numerical value of the GCC init_priority attribute
+encoded in the section name before placing them in the output file.
+
 @cindex SORT
 @code{SORT} is an alias for @code{SORT_BY_NAME}.
 
index 69a84c72982b8b181695c4ed8b98d92555033cc8..ed0aaa76259933ba42e4eef343779ed173d1d354 100644 (file)
@@ -126,6 +126,7 @@ static int error_index;
 %token SECTIONS PHDRS INSERT_K AFTER BEFORE
 %token DATA_SEGMENT_ALIGN DATA_SEGMENT_RELRO_END DATA_SEGMENT_END
 %token SORT_BY_NAME SORT_BY_ALIGNMENT
+%token SORT_BY_INIT_PRIORITY
 %token '{' '}'
 %token SIZEOF_HEADERS OUTPUT_FORMAT FORCE_COMMON_ALLOCATION OUTPUT_ARCH
 %token INHIBIT_COMMON_ALLOCATION
@@ -482,6 +483,12 @@ wildcard_spec:
                          $$.sorted = by_name;
                          $$.exclude_name_list = $5;
                        }
+       |       SORT_BY_INIT_PRIORITY '(' wildcard_name ')'
+                       {
+                         $$.name = $3;
+                         $$.sorted = by_init_priority;
+                         $$.exclude_name_list = NULL;
+                       }
        ;
 
 exclude_name_list:
index 6dc022989fd3c3d7ef1039f61ab0c7d43232e587..32c4af3ef78020de1d28d3cf4811d341d3c31b2a 100644 (file)
@@ -371,18 +371,70 @@ match_simple_wild (const char *pattern, const char *name)
   return TRUE;
 }
 
+/* Return the numerical value of the init_priority attribute from
+   section name NAME.  */
+
+static unsigned long
+get_init_priority (const char *name)
+{
+  char *end;
+  unsigned long init_priority;
+
+  /* GCC uses the following section names for the init_priority
+     attribute with numerical values 101 and 65535 inclusive. A
+     lower value means a higher priority.
+
+     1: .init_array.NNNN/.fini_array.NNNN: Where NNNN is the
+       decimal numerical value of the init_priority attribute.
+       The order of execution in .init_array is forward and
+       .fini_array is backward.
+     2: .ctors.NNNN/.ctors.NNNN: Where NNNN is 65535 minus the
+       decimal numerical value of the init_priority attribute.
+       The order of execution in .ctors is backward and .dtors
+       is forward.
+   */
+  if (strncmp (name, ".init_array.", 12) == 0
+      || strncmp (name, ".fini_array.", 12) == 0)
+    {
+      init_priority = strtoul (name + 12, &end, 10);
+      return *end ? 0 : init_priority;
+    }
+  else if (strncmp (name, ".ctors.", 7) == 0
+          || strncmp (name, ".dtors.", 7) == 0)
+    {
+      init_priority = strtoul (name + 7, &end, 10);
+      return *end ? 0 : 65535 - init_priority;
+    }
+
+  return 0;
+}
+
 /* Compare sections ASEC and BSEC according to SORT.  */
 
 static int
 compare_section (sort_type sort, asection *asec, asection *bsec)
 {
   int ret;
+  unsigned long ainit_priority, binit_priority;
 
   switch (sort)
     {
     default:
       abort ();
 
+    case by_init_priority:
+      ainit_priority
+       = get_init_priority (bfd_get_section_name (asec->owner, asec));
+      binit_priority
+       = get_init_priority (bfd_get_section_name (bsec->owner, bsec));
+      if (ainit_priority == 0 || binit_priority == 0)
+       goto sort_by_name;
+      ret = ainit_priority - binit_priority;
+      if (ret)
+       break;
+      else
+       goto sort_by_name;
+
     case by_alignment_name:
       ret = (bfd_section_alignment (bsec->owner, bsec)
             - bfd_section_alignment (asec->owner, asec));
@@ -391,6 +443,7 @@ compare_section (sort_type sort, asection *asec, asection *bsec)
       /* Fall through.  */
 
     case by_name:
+sort_by_name:
       ret = strcmp (bfd_get_section_name (asec->owner, asec),
                    bfd_get_section_name (bsec->owner, bsec));
       break;
index 7f038b32a4aec27cd0965adc56b115885727f254..7560ca2149264614d8c10fa2de2f74e60a1b2a8f 100644 (file)
@@ -297,6 +297,7 @@ V_IDENTIFIER [*?.$_a-zA-Z\[\]\-\!\^\\]([*?.$_a-zA-Z0-9\[\]\-\!\^\\]|::)*
 <BOTH,SCRIPT>"SORT_BY_NAME"            { RTOKEN(SORT_BY_NAME); }
 <BOTH,SCRIPT>"SORT_BY_ALIGNMENT"       { RTOKEN(SORT_BY_ALIGNMENT); }
 <BOTH,SCRIPT>"SORT"                    { RTOKEN(SORT_BY_NAME); }
+<BOTH,SCRIPT>"SORT_BY_INIT_PRIORITY"   { RTOKEN(SORT_BY_INIT_PRIORITY); }
 <EXPRESSION,BOTH,SCRIPT>"NOLOAD"       { RTOKEN(NOLOAD);}
 <EXPRESSION,BOTH,SCRIPT>"DSECT"                { RTOKEN(DSECT);}
 <EXPRESSION,BOTH,SCRIPT>"COPY"         { RTOKEN(COPY);}
index f020a668da0e3d2cba83a4d1e2f8851d076c7d2b..37f766737e63747ff0188cd85c0dca6755bef97e 100644 (file)
@@ -222,18 +222,31 @@ test "${LARGE_SECTIONS}" = "yes" && LARGE_SECTIONS="
     *(.ldata${RELOCATING+ .ldata.* .gnu.linkonce.l.*})
     ${RELOCATING+. = ALIGN(. != 0 ? ${ALIGNMENT} : 1);}
   }"
+if test "${ENABLE_INITFINI_ARRAY}" = "yes"; then
+  SORT_INIT_ARRAY="KEEP (*(SORT_BY_INIT_PRIORITY(.init_array.*) SORT_BY_INIT_PRIORITY(.ctors.*)))"
+  SORT_FINI_ARRAY="KEEP (*(SORT_BY_INIT_PRIORITY(.fini_array.*) SORT_BY_INIT_PRIORITY(.dtors.*)))"
+  CTORS_IN_INIT_ARRAY="KEEP (*(EXCLUDE_FILE (*crtbegin.o *crtbegin?.o *crtend.o *crtend?.o $OTHER_EXCLUDE_FILES) .ctors))"
+  DTORS_IN_FINI_ARRAY="KEEP (*(EXCLUDE_FILE (*crtbegin.o *crtbegin?.o *crtend.o *crtend?.o $OTHER_EXCLUDE_FILES) .dtors))"
+else
+  SORT_INIT_ARRAY="KEEP (*(SORT(.init_array.*)))"
+  SORT_FINI_ARRAY="KEEP (*(SORT(.fini_array.*)))"
+  CTORS_IN_INIT_ARRAY=
+  DTORS_IN_FINI_ARRAY=
+fi
 INIT_ARRAY=".init_array   ${RELOCATING-0} :
   {
     ${RELOCATING+${CREATE_SHLIB-PROVIDE_HIDDEN (${USER_LABEL_PREFIX}__init_array_start = .);}}
-    KEEP (*(SORT(.init_array.*)))
+    ${SORT_INIT_ARRAY}
     KEEP (*(.init_array))
+    ${CTORS_IN_INIT_ARRAY}
     ${RELOCATING+${CREATE_SHLIB-PROVIDE_HIDDEN (${USER_LABEL_PREFIX}__init_array_end = .);}}
   }"
 FINI_ARRAY=".fini_array   ${RELOCATING-0} :
   {
     ${RELOCATING+${CREATE_SHLIB-PROVIDE_HIDDEN (${USER_LABEL_PREFIX}__fini_array_start = .);}}
-    KEEP (*(SORT(.fini_array.*)))
+    ${SORT_FINI_ARRAY}
     KEEP (*(.fini_array))
+    ${DTORS_IN_FINI_ARRAY}
     ${RELOCATING+${CREATE_SHLIB-PROVIDE_HIDDEN (${USER_LABEL_PREFIX}__fini_array_end = .);}}
   }"
 CTOR=".ctors        ${CONSTRUCTING-0} : 
index 379132cd6e29b065dd7be77b22ac5b0c3184eca5..3f0fc2be8ca8f287fb30cde876a1e14c5dd275e0 100644 (file)
@@ -1,3 +1,12 @@
+2010-12-15  H.J. Lu  <hongjiu.lu@intel.com>
+
+       * ld-elf/elf.exp (array_tests): Add init-mixed.
+       (array_tests_static): Likewise.
+       Also delete tmpdir/init-mixed.
+
+       * ld-elf/init-mixed.c: New.
+       * ld-elf/init-mixed.out: Likewise.
+
 2010-12-11  Alan Modra  <amodra@gmail.com>
 
        * ld-elfvers/vers25a.dsym: Really include _? in match.
index fc216833c933e88ddaf3722e6b7926a0aef05155..a1e70da4fd485a0b21f14144b34f204ce71c0681 100644 (file)
@@ -74,11 +74,13 @@ set array_tests {
     {"preinit array" "" "" {preinit.c} "preinit" "preinit.out"}
     {"init array" "" "" {init.c} "init" "init.out"}
     {"fini array" "" "" {fini.c} "fini" "fini.out"}
+    {"init array mixed" "" "" {init-mixed.c} "init-mixed" "init-mixed.out" "-I."}
 }
 set array_tests_static {
     {"static preinit array" "-static" "" {preinit.c} "preinit" "preinit.out"}
     {"static init array" "-static" "" {init.c} "init" "init.out"}
     {"static fini array" "-static" "" {fini.c} "fini" "fini.out"}
+    {"static init array mixed" "" "" {init-mixed.c} "init-mixed" "init-mixed.out" "-I."}
 }
 
 # NetBSD ELF systems do not currently support the .*_array sections.
@@ -93,4 +95,4 @@ switch -regexp $target_triplet {
 }
 run_ld_link_exec_tests $xfails $array_tests_static
 
-catch "exec rm -f tmpdir/preinit tmpdir/init tmpdir/fini" status
+catch "exec rm -f tmpdir/preinit tmpdir/init tmpdir/fini tmpdir/init-mixed" status
diff --git a/ld/testsuite/ld-elf/init-mixed.c b/ld/testsuite/ld-elf/init-mixed.c
new file mode 100644 (file)
index 0000000..1d0c727
--- /dev/null
@@ -0,0 +1,98 @@
+#include <stdio.h>
+#include <stdlib.h>
+
+#include "config.h"
+
+#ifdef HAVE_INITFINI_ARRAY
+static int count;
+
+static void
+init1005 ()
+{
+  if (count != 0)
+    abort ();
+  count = 1005;
+}
+void (*const init_array1005[]) ()
+  __attribute__ ((section (".init_array.01005"), aligned (sizeof (void *))))
+  = { init1005 };
+static void
+fini1005 ()
+{
+  if (count != 1005)
+    abort ();
+}
+void (*const fini_array1005[]) ()
+  __attribute__ ((section (".fini_array.01005"), aligned (sizeof (void *))))
+  = { fini1005 };
+
+static void
+ctor1007 ()
+{
+  if (count != 1005)
+    abort ();
+  count = 1007;
+}
+void (*const ctors1007[]) ()
+  __attribute__ ((section (".ctors.64528"), aligned (sizeof (void *))))
+  = { ctor1007 };
+static void
+dtor1007 ()
+{
+  if (count != 1007)
+    abort ();
+  count = 1005;
+}
+void (*const dtors1007[]) ()
+  __attribute__ ((section (".dtors.64528"), aligned (sizeof (void *))))
+  = { dtor1007 };
+
+static void
+init65530 ()
+{
+  if (count != 1007)
+    abort ();
+  count = 65530;
+}
+void (*const init_array65530[]) ()
+  __attribute__ ((section (".init_array.65530"), aligned (sizeof (void *))))
+  = { init65530 };
+static void
+fini65530 ()
+{
+  if (count != 65530)
+    abort ();
+  count = 1007;
+}
+void (*const fini_array65530[]) ()
+  __attribute__ ((section (".fini_array.65530"), aligned (sizeof (void *))))
+  = { fini65530 };
+
+static void
+ctor65535 ()
+{
+  if (count != 65530)
+    abort ();
+  count = 65535;
+}
+void (*const ctors65535[]) ()
+  __attribute__ ((section (".ctors"), aligned (sizeof (void *))))
+  = { ctor65535 };
+static void
+dtor65535 ()
+{
+  if (count != 65535)
+    abort ();
+  count = 65530;
+}
+void (*const dtors65535[]) ()
+  __attribute__ ((section (".dtors"), aligned (sizeof (void *))))
+  = { dtor65535 };
+#endif
+
+int
+main ()
+{
+  printf ("OK\n");
+  return 0;
+}
diff --git a/ld/testsuite/ld-elf/init-mixed.out b/ld/testsuite/ld-elf/init-mixed.out
new file mode 100644 (file)
index 0000000..d86bac9
--- /dev/null
@@ -0,0 +1 @@
+OK