public inbox for gcc-patches@gcc.gnu.org
 help / color / mirror / Atom feed
* RFC: PR target/46770: Use .init_array/.fini_array sections
@ 2010-12-15  1:50 H.J. Lu
  2011-01-27  0:08 ` PATCH: " H.J. Lu
  0 siblings, 1 reply; 10+ messages in thread
From: H.J. Lu @ 2010-12-15  1:50 UTC (permalink / raw)
  To: gcc-patches

This patch uses .init_array/.fini_array sections instead of
.ctors/.dtors sections if mixing .init_array/.fini_array and
.ctors/.dtors sections with init_priority works.

It removes .ctors/.ctors sections from executables and DSOes, which will
remove one function call at startup time from each executable and DSO.
It should reduce image size and improve system startup time. 

If a platform with a working .init_array/.fini_array support needs a
different .init_array/.fini_array implementation, it can set
use_initfini_array to no.

Since .init_array/.fini_array is a target feature. --enable-initfini-array
is default to no unless the native run-time test is passed.

To pass the native run-time test, a linker with SORT_BY_INIT_PRIORITY
support is required.  The binutils patch is available at

http://sourceware.org/ml/binutils/2010-12/msg00466.html

This patch passed 32bit/64bit regression test on Linux/x86-64.  Any
comments?

Thanks.

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

	PR target/46770
	* acinclude.m4 (gcc_AC_INITFINI_ARRAY): Removed.

	* config.gcc (use_initfini_array): New variable.
	Use initfini-array.o if supported.

	* crtstuff.c: Don't generate .ctors nor .dtors sections if
	NO_CTORS_DTORS_SECTIONS is defined.

	* configure.ac: Remove gcc_AC_INITFINI_ARRAY.  Add
	--enable-initfini-array and check if .init_array can be used with
	.ctors.

	* configure: Regenerated.

	* config/initfini-array.c: New.
	* config/initfini-array.h: Likewise.
	* config/t-initfini-array: Likewise.

diff --git a/gcc/acinclude.m4 b/gcc/acinclude.m4
index 6f0f979..b0ab6d0 100644
--- a/gcc/acinclude.m4
+++ b/gcc/acinclude.m4
@@ -369,26 +369,6 @@ else
 fi
 fi])
 
-AC_DEFUN([gcc_AC_INITFINI_ARRAY],
-[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
-  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])])
-  enable_initfini_array=$gcc_cv_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])
-
 dnl # _gcc_COMPUTE_GAS_VERSION
 dnl # Used by gcc_GAS_VERSION_GTE_IFELSE
 dnl #
diff --git a/gcc/config.gcc b/gcc/config.gcc
index 65cbf75..342bfa5 100644
--- a/gcc/config.gcc
+++ b/gcc/config.gcc
@@ -177,6 +177,9 @@
 #  configure_default_options
 #			Set to an initializer for configure_default_options
 #			in configargs.h, based on --with-cpu et cetera.
+#
+#  use_initfini_array	If set to yes, .init_array/.fini_array sections
+#			will be used if they work.
 
 # The following variables are used in each case-construct to build up the
 # outgoing variables:
@@ -219,6 +222,7 @@ default_gnu_indirect_function=no
 target_gtfiles=
 need_64bit_hwint=
 need_64bit_isa=
+use_initfini_array=yes
 
 # Don't carry these over build->host->target.  Please.
 xm_file=
@@ -3046,6 +3050,16 @@ if test x$with_schedule = x; then
 	esac
 fi
 
+# Support --enable-initfini-array.  Use initfini-array.h only if
+# use_initfini_array is also set to yes.  Some platforms don't need it
+# even if enable_initfini_array is yes.
+if test x$enable_initfini_array$use_initfini_array = xyesyes; then
+  tm_file="${tm_file} initfini-array.h"
+  tmake_file="${tmake_file} t-initfini-array"
+  extra_objs="$extra_objs initfini-array.o"
+  target_gtfiles="$target_gtfiles \$(srcdir)/config/initfini-array.c"
+fi
+
 # Validate and mark as valid any --with options supported
 # by this target.  In order to use a particular --with option
 # you must list it in supported_defaults; validating the value
diff --git a/gcc/config/initfini-array.c b/gcc/config/initfini-array.c
new file mode 100644
index 0000000..d5fd40f
--- /dev/null
+++ b/gcc/config/initfini-array.c
@@ -0,0 +1,79 @@
+/* Definitions for ELF systems with .init_array/.fini_array section
+   Copyright (C) 2010
+   Free Software Foundation, Inc.
+
+This file is part of GCC.
+
+GCC 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 3, or (at your option) any later
+version.
+
+GCC 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 GCC; see the file COPYING3.  If not see
+<http://www.gnu.org/licenses/>.  */
+
+#include "config.h"
+#include "system.h"
+#include "coretypes.h"
+#include "target.h"
+#include "output.h"
+#include "tree.h"
+#include "ggc.h"
+
+static GTY(()) section *init_array_section;
+static GTY(()) section *fini_array_section;
+
+void
+elf_initfini_array_init_sections (void)
+{
+  init_array_section = get_unnamed_section (0, output_section_asm_op,
+					    "\t.section\t.init_array");
+  fini_array_section = get_unnamed_section (0, output_section_asm_op,
+					    "\t.section\t.fini_array");
+}
+
+static section *
+get_elf_initfini_array_priority_section (int priority,
+					 bool constructor_p)
+{
+  section *sec;
+  if (priority != DEFAULT_INIT_PRIORITY)
+    {
+      char buf[18];
+      sprintf (buf, "%s.%.5u", 
+	       constructor_p ? ".init_array" : ".fini_array",
+	       priority);
+      sec = get_section (buf, SECTION_WRITE, NULL_TREE);
+    }
+  else
+    sec = constructor_p ? init_array_section : fini_array_section;
+  return sec;
+}
+
+/* Use .init_array section for constructors. */
+
+void
+elf_init_array_asm_out_constructor (rtx symbol, int priority)
+{
+  section *sec = get_elf_initfini_array_priority_section (priority,
+							  true);
+  assemble_addr_to_section (symbol, sec);
+}
+
+/* Use .fini_array section for destructors. */
+
+void
+elf_fini_array_asm_out_destructor (rtx symbol, int priority)
+{
+  section *sec = get_elf_initfini_array_priority_section (priority,
+							  false);
+  assemble_addr_to_section (symbol, sec);
+}
+
+#include "gt-initfini-array.h"
diff --git a/gcc/config/initfini-array.h b/gcc/config/initfini-array.h
new file mode 100644
index 0000000..b0b422a
--- /dev/null
+++ b/gcc/config/initfini-array.h
@@ -0,0 +1,46 @@
+/* Definitions for ELF systems with .init_array/.fini_array section
+   support.
+   Copyright (C) 2010
+   Free Software Foundation, Inc.
+
+   This file is part of GCC.
+
+   GCC 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 3, or (at your
+   option) any later version.
+
+   GCC 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 GCC; see the file COPYING3.  If not see
+   <http://www.gnu.org/licenses/>.  */
+
+/* No need for .ctors/.dtors section since linker can place them in
+   .init_array/.fini_array section.  */
+#define NO_CTORS_DTORS_SECTIONS
+
+#undef INIT_SECTION_ASM_OP
+#undef FINI_SECTION_ASM_OP
+
+/* FIXME: INIT_ARRAY_SECTION_ASM_OP and FINI_ARRAY_SECTION_ASM_OP
+	  aren't used in any assembly codes.  But we have to define
+	  them to something.  */
+#define INIT_ARRAY_SECTION_ASM_OP Something
+#define FINI_ARRAY_SECTION_ASM_OP Something
+
+#ifndef TARGET_ASM_INIT_SECTIONS
+#define TARGET_ASM_INIT_SECTIONS elf_initfini_array_init_sections
+#endif
+extern void elf_initfini_array_init_sections (void);
+
+/* Use .init_array/.fini_array section for constructors and destructors. */
+#undef TARGET_ASM_CONSTRUCTOR
+#define TARGET_ASM_CONSTRUCTOR elf_init_array_asm_out_constructor
+#undef TARGET_ASM_DESTRUCTOR
+#define TARGET_ASM_DESTRUCTOR elf_fini_array_asm_out_destructor
+extern void elf_init_array_asm_out_constructor (rtx, int);
+extern void elf_fini_array_asm_out_destructor (rtx, int);
diff --git a/gcc/config/t-initfini-array b/gcc/config/t-initfini-array
new file mode 100644
index 0000000..3dcb25d
--- /dev/null
+++ b/gcc/config/t-initfini-array
@@ -0,0 +1,23 @@
+# Copyright (C) 2010
+# 2009 Free Software Foundation, Inc.
+#
+# This file is part of GCC.
+#
+# GCC 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 3, or (at your option)
+# any later version.
+#
+# GCC 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 GCC; see the file COPYING3.  If not see
+# <http://www.gnu.org/licenses/>.
+
+initfini-array.o: $(srcdir)/config/initfini-array.c gt-initfini-array.h \
+	$(CONFIG_H) $(SYSTEM_H) coretypes.h $(TARGET_H) output.h \
+	$(TREE_H) $(GGC_H)
+	$(COMPILER) -c $(ALL_COMPILERFLAGS) $(ALL_CPPFLAGS) $(INCLUDES) $<
diff --git a/gcc/configure b/gcc/configure
index 9d76b41..a8cddf2 100755
--- a/gcc/configure
+++ b/gcc/configure
@@ -10442,6 +10442,7 @@ fi
 # Restore CFLAGS from before the gcc_AC_NEED_DECLARATIONS tests.
 CFLAGS="$saved_CFLAGS"
 
+# Check if .init_array can be used with .ctors.
 # Check whether --enable-initfini-array was given.
 if test "${enable_initfini_array+set}" = set; then :
   enableval=$enable_initfini_array;
@@ -10452,16 +10453,104 @@ $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;
+extern void abort ();
+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 };
+
+int
+main ()
+{
+  return 0;
+}
 _ACEOF
 if ac_fn_c_try_run "$LINENO"; then :
   gcc_cv_initfini_array=yes
@@ -10472,6 +10561,9 @@ 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; }
@@ -17513,7 +17605,7 @@ else
   lt_dlunknown=0; lt_dlno_uscore=1; lt_dlneed_uscore=2
   lt_status=$lt_dlunknown
   cat > conftest.$ac_ext <<_LT_EOF
-#line 17516 "configure"
+#line 17608 "configure"
 #include "confdefs.h"
 
 #if HAVE_DLFCN_H
@@ -17619,7 +17711,7 @@ else
   lt_dlunknown=0; lt_dlno_uscore=1; lt_dlneed_uscore=2
   lt_status=$lt_dlunknown
   cat > conftest.$ac_ext <<_LT_EOF
-#line 17622 "configure"
+#line 17714 "configure"
 #include "confdefs.h"
 
 #if HAVE_DLFCN_H
diff --git a/gcc/configure.ac b/gcc/configure.ac
index 166500e..0937aa3 100644
--- a/gcc/configure.ac
+++ b/gcc/configure.ac
@@ -1125,7 +1125,116 @@ fi
 # Restore CFLAGS from before the gcc_AC_NEED_DECLARATIONS tests.
 CFLAGS="$saved_CFLAGS"
 
-gcc_AC_INITFINI_ARRAY
+# Check if .init_array can be used with .ctors.
+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([
+extern void abort ();
+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 };
+
+int
+main ()
+{
+  return 0;
+}])],
+	     [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
+])
+if test $enable_initfini_array = yes; then
+  AC_DEFINE(HAVE_INITFINI_ARRAY, 1,
+    [Define .init_array/.fini_array sections are available and working.])
+fi
 
 # mkdir takes a single argument on some systems. 
 gcc_AC_FUNC_MKDIR_TAKES_ONE_ARG
diff --git a/gcc/crtstuff.c b/gcc/crtstuff.c
index 6fc571b..2573179 100644
--- a/gcc/crtstuff.c
+++ b/gcc/crtstuff.c
@@ -180,6 +180,9 @@ typedef void (*func_ptr) (void);
    refer to only the __CTOR_END__ symbol in crtend.o and the __DTOR_LIST__
    symbol in crtbegin.o, where they are defined.  */
 
+/* No need for .ctors/.dtors section if linker can place them in
+   .init_array/.fini_array section.  */
+#ifndef NO_CTORS_DTORS_SECTIONS
 /* The -1 is a flag to __do_global_[cd]tors indicating that this table
    does not start with a count of elements.  */
 #ifdef CTOR_LIST_BEGIN
@@ -210,6 +213,7 @@ STATIC func_ptr __DTOR_LIST__[1]
   __attribute__((section(".dtors"), aligned(sizeof(func_ptr))))
   = { (func_ptr) (-1) };
 #endif /* __DTOR_LIST__ alternatives */
+#endif /* NO_CTORS_DTORS_SECTIONS */
 
 #ifdef USE_EH_FRAME_REGISTRY
 /* Stick a label at the beginning of the frame unwind info so we can register
@@ -480,6 +484,9 @@ __do_global_ctors_1(void)
 
 #elif defined(CRT_END) /* ! CRT_BEGIN */
 
+/* No need for .ctors/.dtors section if linker can place them in
+   .init_array/.fini_array section.  */
+#ifndef NO_CTORS_DTORS_SECTIONS
 /* Put a word containing zero at the end of each of our two lists of function
    addresses.  Note that the words defined here go into the .ctors and .dtors
    sections of the crtend.o file, and since that file is always linked in
@@ -525,6 +532,7 @@ STATIC func_ptr __DTOR_END__[1]
   __attribute__((used, section(".dtors"), aligned(sizeof(func_ptr))))
   = { (func_ptr) 0 };
 #endif
+#endif /* NO_CTORS_DTORS_SECTIONS */
 
 #ifdef EH_FRAME_SECTION_NAME
 /* Terminate the frame unwind info section with a 4byte 0 as a sentinel;

^ permalink raw reply	[flat|nested] 10+ messages in thread

* PATCH: PR target/46770: Use .init_array/.fini_array sections
  2010-12-15  1:50 RFC: PR target/46770: Use .init_array/.fini_array sections H.J. Lu
@ 2011-01-27  0:08 ` H.J. Lu
  2011-01-27 11:09   ` Richard Guenther
  0 siblings, 1 reply; 10+ messages in thread
From: H.J. Lu @ 2011-01-27  0:08 UTC (permalink / raw)
  To: gcc-patches

On Tue, Dec 14, 2010 at 05:20:48PM -0800, H.J. Lu wrote:
> This patch uses .init_array/.fini_array sections instead of
> .ctors/.dtors sections if mixing .init_array/.fini_array and
> .ctors/.dtors sections with init_priority works.
> 
> It removes .ctors/.ctors sections from executables and DSOes, which will
> remove one function call at startup time from each executable and DSO.
> It should reduce image size and improve system startup time. 
> 
> If a platform with a working .init_array/.fini_array support needs a
> different .init_array/.fini_array implementation, it can set
> use_initfini_array to no.
> 
> Since .init_array/.fini_array is a target feature. --enable-initfini-array
> is default to no unless the native run-time test is passed.
> 
> To pass the native run-time test, a linker with SORT_BY_INIT_PRIORITY
> support is required.  The binutils patch is available at
> 
> http://sourceware.org/ml/binutils/2010-12/msg00466.html

Linker patch has been checked in.

> 
> This patch passed 32bit/64bit regression test on Linux/x86-64.  Any
> comments?
> 

This updated patch fixes build on Linux/ia64 and should work on others.
Any comments?

Thanks.


H.J.
----
2011-01-26  H.J. Lu  <hongjiu.lu@intel.com>

	PR target/46770
	* acinclude.m4 (gcc_AC_INITFINI_ARRAY): Removed.

	* config.gcc (use_initfini_array): New variable.
	Use initfini-array.o if supported.

	* crtstuff.c: Don't generate .ctors nor .dtors sections if
	NO_CTORS_DTORS_SECTIONS is defined.

	* configure.ac: Remove gcc_AC_INITFINI_ARRAY.  Add
	--enable-initfini-array and check if .init_array can be used with
	.ctors.

	* configure: Regenerated.

	* config/initfini-array.c: New.
	* config/initfini-array.h: Likewise.
	* config/t-initfini-array: Likewise.

	* config/arm/arm.c (arm_asm_init_sections): Call
	elf_initfini_array_init_sections if NO_CTORS_DTORS_SECTIONS
	is defined.
	* config/avr/avr.c (avr_asm_init_sections): Likewise.
	* config/ia64/ia64.c (ia64_asm_init_sections): Likewise.
	* config/mep/mep.c (mep_asm_init_sections): Likewise.
	* config/microblaze/microblaze.c (microblaze_elf_asm_init_sections):
	Likewise.
	* config/rs6000/rs6000.c (rs6000_elf_asm_init_sections): Likewise.
	* config/stormy16/stormy16.c (xstormy16_asm_init_sections):
	Likewise.
	* config/v850/v850.c (v850_asm_init_sections): Likewise.

diff --git a/gcc/acinclude.m4 b/gcc/acinclude.m4
index 6f0f979..b0ab6d0 100644
--- a/gcc/acinclude.m4
+++ b/gcc/acinclude.m4
@@ -369,26 +369,6 @@ else
 fi
 fi])
 
-AC_DEFUN([gcc_AC_INITFINI_ARRAY],
-[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
-  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])])
-  enable_initfini_array=$gcc_cv_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])
-
 dnl # _gcc_COMPUTE_GAS_VERSION
 dnl # Used by gcc_GAS_VERSION_GTE_IFELSE
 dnl #
diff --git a/gcc/config.gcc b/gcc/config.gcc
index 0f6aae1..256e433 100644
--- a/gcc/config.gcc
+++ b/gcc/config.gcc
@@ -177,6 +177,9 @@
 #  configure_default_options
 #			Set to an initializer for configure_default_options
 #			in configargs.h, based on --with-cpu et cetera.
+#
+#  use_initfini_array	If set to yes, .init_array/.fini_array sections
+#			will be used if they work.
 
 # The following variables are used in each case-construct to build up the
 # outgoing variables:
@@ -219,6 +222,7 @@ default_gnu_indirect_function=no
 target_gtfiles=
 need_64bit_hwint=
 need_64bit_isa=
+use_initfini_array=yes
 
 # Don't carry these over build->host->target.  Please.
 xm_file=
@@ -3093,6 +3097,16 @@ if test x$with_schedule = x; then
 	esac
 fi
 
+# Support --enable-initfini-array.  Use initfini-array.h only if
+# use_initfini_array is also set to yes.  Some platforms don't need it
+# even if enable_initfini_array is yes.
+if test x$enable_initfini_array$use_initfini_array = xyesyes; then
+  tm_file="${tm_file} initfini-array.h"
+  tmake_file="${tmake_file} t-initfini-array"
+  extra_objs="$extra_objs initfini-array.o"
+  target_gtfiles="$target_gtfiles \$(srcdir)/config/initfini-array.c"
+fi
+
 # Validate and mark as valid any --with options supported
 # by this target.  In order to use a particular --with option
 # you must list it in supported_defaults; validating the value
diff --git a/gcc/config/arm/arm.c b/gcc/config/arm/arm.c
index 3e75d7c..59a65c9 100644
--- a/gcc/config/arm/arm.c
+++ b/gcc/config/arm/arm.c
@@ -22599,6 +22599,9 @@ arm_asm_init_sections (void)
 {
   exception_section = get_unnamed_section (0, output_section_asm_op,
 					   "\t.handlerdata");
+#ifdef NO_CTORS_DTORS_SECTIONS
+  elf_initfini_array_init_sections ();
+#endif
 }
 #endif /* ARM_UNWIND_INFO */
 
diff --git a/gcc/config/avr/avr.c b/gcc/config/avr/avr.c
index 30e4626..6cbef2a 100644
--- a/gcc/config/avr/avr.c
+++ b/gcc/config/avr/avr.c
@@ -4958,6 +4958,9 @@ avr_asm_init_sections (void)
 					 avr_output_progmem_section_asm_op,
 					 NULL);
   readonly_data_section = data_section;
+#ifdef NO_CTORS_DTORS_SECTIONS
+  elf_initfini_array_init_sections ();
+#endif
 }
 
 static unsigned int
diff --git a/gcc/config/ia64/ia64.c b/gcc/config/ia64/ia64.c
index 5018e41..86f6049 100644
--- a/gcc/config/ia64/ia64.c
+++ b/gcc/config/ia64/ia64.c
@@ -10142,6 +10142,9 @@ ia64_asm_init_sections (void)
 {
   exception_section = get_unnamed_section (0, output_section_asm_op,
 					   "\t.handlerdata");
+#ifdef NO_CTORS_DTORS_SECTIONS
+  elf_initfini_array_init_sections ();
+#endif
 }
 
 /* Implement TARGET_DEBUG_UNWIND_INFO.  */
diff --git a/gcc/config/initfini-array.c b/gcc/config/initfini-array.c
new file mode 100644
index 0000000..d5fd40f
--- /dev/null
+++ b/gcc/config/initfini-array.c
@@ -0,0 +1,79 @@
+/* Definitions for ELF systems with .init_array/.fini_array section
+   Copyright (C) 2010
+   Free Software Foundation, Inc.
+
+This file is part of GCC.
+
+GCC 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 3, or (at your option) any later
+version.
+
+GCC 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 GCC; see the file COPYING3.  If not see
+<http://www.gnu.org/licenses/>.  */
+
+#include "config.h"
+#include "system.h"
+#include "coretypes.h"
+#include "target.h"
+#include "output.h"
+#include "tree.h"
+#include "ggc.h"
+
+static GTY(()) section *init_array_section;
+static GTY(()) section *fini_array_section;
+
+void
+elf_initfini_array_init_sections (void)
+{
+  init_array_section = get_unnamed_section (0, output_section_asm_op,
+					    "\t.section\t.init_array");
+  fini_array_section = get_unnamed_section (0, output_section_asm_op,
+					    "\t.section\t.fini_array");
+}
+
+static section *
+get_elf_initfini_array_priority_section (int priority,
+					 bool constructor_p)
+{
+  section *sec;
+  if (priority != DEFAULT_INIT_PRIORITY)
+    {
+      char buf[18];
+      sprintf (buf, "%s.%.5u", 
+	       constructor_p ? ".init_array" : ".fini_array",
+	       priority);
+      sec = get_section (buf, SECTION_WRITE, NULL_TREE);
+    }
+  else
+    sec = constructor_p ? init_array_section : fini_array_section;
+  return sec;
+}
+
+/* Use .init_array section for constructors. */
+
+void
+elf_init_array_asm_out_constructor (rtx symbol, int priority)
+{
+  section *sec = get_elf_initfini_array_priority_section (priority,
+							  true);
+  assemble_addr_to_section (symbol, sec);
+}
+
+/* Use .fini_array section for destructors. */
+
+void
+elf_fini_array_asm_out_destructor (rtx symbol, int priority)
+{
+  section *sec = get_elf_initfini_array_priority_section (priority,
+							  false);
+  assemble_addr_to_section (symbol, sec);
+}
+
+#include "gt-initfini-array.h"
diff --git a/gcc/config/initfini-array.h b/gcc/config/initfini-array.h
new file mode 100644
index 0000000..b0b422a
--- /dev/null
+++ b/gcc/config/initfini-array.h
@@ -0,0 +1,46 @@
+/* Definitions for ELF systems with .init_array/.fini_array section
+   support.
+   Copyright (C) 2010
+   Free Software Foundation, Inc.
+
+   This file is part of GCC.
+
+   GCC 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 3, or (at your
+   option) any later version.
+
+   GCC 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 GCC; see the file COPYING3.  If not see
+   <http://www.gnu.org/licenses/>.  */
+
+/* No need for .ctors/.dtors section since linker can place them in
+   .init_array/.fini_array section.  */
+#define NO_CTORS_DTORS_SECTIONS
+
+#undef INIT_SECTION_ASM_OP
+#undef FINI_SECTION_ASM_OP
+
+/* FIXME: INIT_ARRAY_SECTION_ASM_OP and FINI_ARRAY_SECTION_ASM_OP
+	  aren't used in any assembly codes.  But we have to define
+	  them to something.  */
+#define INIT_ARRAY_SECTION_ASM_OP Something
+#define FINI_ARRAY_SECTION_ASM_OP Something
+
+#ifndef TARGET_ASM_INIT_SECTIONS
+#define TARGET_ASM_INIT_SECTIONS elf_initfini_array_init_sections
+#endif
+extern void elf_initfini_array_init_sections (void);
+
+/* Use .init_array/.fini_array section for constructors and destructors. */
+#undef TARGET_ASM_CONSTRUCTOR
+#define TARGET_ASM_CONSTRUCTOR elf_init_array_asm_out_constructor
+#undef TARGET_ASM_DESTRUCTOR
+#define TARGET_ASM_DESTRUCTOR elf_fini_array_asm_out_destructor
+extern void elf_init_array_asm_out_constructor (rtx, int);
+extern void elf_fini_array_asm_out_destructor (rtx, int);
diff --git a/gcc/config/mep/mep.c b/gcc/config/mep/mep.c
index 913a30a..6651547 100644
--- a/gcc/config/mep/mep.c
+++ b/gcc/config/mep/mep.c
@@ -7372,6 +7372,9 @@ mep_asm_init_sections (void)
     = get_unnamed_section (SECTION_CODE, output_section_asm_op,
 			   "\t.section .ftext,\"ax\"\n\t.core");
 
+#ifdef NO_CTORS_DTORS_SECTIONS
+  elf_initfini_array_init_sections ();
+#endif
 }
 \f
 /* Initialize the GCC target structure.  */
diff --git a/gcc/config/microblaze/microblaze.c b/gcc/config/microblaze/microblaze.c
index b50c794..7e802f1 100644
--- a/gcc/config/microblaze/microblaze.c
+++ b/gcc/config/microblaze/microblaze.c
@@ -2765,6 +2765,9 @@ microblaze_elf_asm_init_sections (void)
   sdata2_section
     = get_unnamed_section (SECTION_WRITE, output_section_asm_op,
 			   SDATA2_SECTION_ASM_OP);
+#ifdef NO_CTORS_DTORS_SECTIONS
+  elf_initfini_array_init_sections ();
+#endif
 }
 
 /*  Generate assembler code for constant parts of a trampoline.  */
diff --git a/gcc/config/rs6000/rs6000.c b/gcc/config/rs6000/rs6000.c
index 30f8b75..03328d5 100644
--- a/gcc/config/rs6000/rs6000.c
+++ b/gcc/config/rs6000/rs6000.c
@@ -25063,6 +25063,10 @@ rs6000_elf_asm_init_sections (void)
   sdata2_section
     = get_unnamed_section (SECTION_WRITE, output_section_asm_op,
 			   SDATA2_SECTION_ASM_OP);
+
+#ifdef NO_CTORS_DTORS_SECTIONS
+  elf_initfini_array_init_sections ();
+#endif
 }
 
 /* Implement TARGET_SELECT_RTX_SECTION.  */
diff --git a/gcc/config/stormy16/stormy16.c b/gcc/config/stormy16/stormy16.c
index fa5c5b5..1819ef5 100644
--- a/gcc/config/stormy16/stormy16.c
+++ b/gcc/config/stormy16/stormy16.c
@@ -1604,6 +1604,9 @@ xstormy16_asm_init_sections (void)
     = get_unnamed_section (SECTION_WRITE | SECTION_BSS,
 			   output_section_asm_op,
 			   "\t.section \".bss_below100\",\"aw\",@nobits");
+#ifdef NO_CTORS_DTORS_SECTIONS
+  elf_initfini_array_init_sections ();
+#endif
 }
 
 /* Mark symbols with the "below100" attribute so that we can use the
diff --git a/gcc/config/t-initfini-array b/gcc/config/t-initfini-array
new file mode 100644
index 0000000..3dcb25d
--- /dev/null
+++ b/gcc/config/t-initfini-array
@@ -0,0 +1,23 @@
+# Copyright (C) 2010
+# 2009 Free Software Foundation, Inc.
+#
+# This file is part of GCC.
+#
+# GCC 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 3, or (at your option)
+# any later version.
+#
+# GCC 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 GCC; see the file COPYING3.  If not see
+# <http://www.gnu.org/licenses/>.
+
+initfini-array.o: $(srcdir)/config/initfini-array.c gt-initfini-array.h \
+	$(CONFIG_H) $(SYSTEM_H) coretypes.h $(TARGET_H) output.h \
+	$(TREE_H) $(GGC_H)
+	$(COMPILER) -c $(ALL_COMPILERFLAGS) $(ALL_CPPFLAGS) $(INCLUDES) $<
diff --git a/gcc/config/v850/v850.c b/gcc/config/v850/v850.c
index 6d6ed78..4534a9a 100644
--- a/gcc/config/v850/v850.c
+++ b/gcc/config/v850/v850.c
@@ -2978,6 +2978,10 @@ v850_asm_init_sections (void)
     = get_unnamed_section (SECTION_WRITE | SECTION_BSS,
 			   output_section_asm_op,
 			   "\t.section .zbss,\"aw\"");
+
+#ifdef NO_CTORS_DTORS_SECTIONS
+  elf_initfini_array_init_sections ();
+#endif
 }
 
 static section *
diff --git a/gcc/configure b/gcc/configure
index 7a3e1e1..a1f8cb7 100755
--- a/gcc/configure
+++ b/gcc/configure
@@ -10442,6 +10442,7 @@ fi
 # Restore CFLAGS from before the gcc_AC_NEED_DECLARATIONS tests.
 CFLAGS="$saved_CFLAGS"
 
+# Check if .init_array can be used with .ctors.
 # Check whether --enable-initfini-array was given.
 if test "${enable_initfini_array+set}" = set; then :
   enableval=$enable_initfini_array;
@@ -10452,16 +10453,104 @@ $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;
+extern void abort ();
+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 };
+
+int
+main ()
+{
+  return 0;
+}
 _ACEOF
 if ac_fn_c_try_run "$LINENO"; then :
   gcc_cv_initfini_array=yes
@@ -10472,6 +10561,9 @@ 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; }
diff --git a/gcc/configure.ac b/gcc/configure.ac
index 77af4a1..dd15d9f 100644
--- a/gcc/configure.ac
+++ b/gcc/configure.ac
@@ -1125,7 +1125,116 @@ fi
 # Restore CFLAGS from before the gcc_AC_NEED_DECLARATIONS tests.
 CFLAGS="$saved_CFLAGS"
 
-gcc_AC_INITFINI_ARRAY
+# Check if .init_array can be used with .ctors.
+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([
+extern void abort ();
+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 };
+
+int
+main ()
+{
+  return 0;
+}])],
+	     [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
+])
+if test $enable_initfini_array = yes; then
+  AC_DEFINE(HAVE_INITFINI_ARRAY, 1,
+    [Define .init_array/.fini_array sections are available and working.])
+fi
 
 # mkdir takes a single argument on some systems. 
 gcc_AC_FUNC_MKDIR_TAKES_ONE_ARG
diff --git a/gcc/crtstuff.c b/gcc/crtstuff.c
index b65f490..7d31934e 100644
--- a/gcc/crtstuff.c
+++ b/gcc/crtstuff.c
@@ -189,6 +189,9 @@ typedef void (*func_ptr) (void);
    refer to only the __CTOR_END__ symbol in crtend.o and the __DTOR_LIST__
    symbol in crtbegin.o, where they are defined.  */
 
+/* No need for .ctors/.dtors section if linker can place them in
+   .init_array/.fini_array section.  */
+#ifndef NO_CTORS_DTORS_SECTIONS
 /* The -1 is a flag to __do_global_[cd]tors indicating that this table
    does not start with a count of elements.  */
 #ifdef CTOR_LIST_BEGIN
@@ -219,6 +222,7 @@ STATIC func_ptr __DTOR_LIST__[1]
   __attribute__((section(".dtors"), aligned(sizeof(func_ptr))))
   = { (func_ptr) (-1) };
 #endif /* __DTOR_LIST__ alternatives */
+#endif /* NO_CTORS_DTORS_SECTIONS */
 
 #ifdef USE_EH_FRAME_REGISTRY
 /* Stick a label at the beginning of the frame unwind info so we can register
@@ -489,6 +493,9 @@ __do_global_ctors_1(void)
 
 #elif defined(CRT_END) /* ! CRT_BEGIN */
 
+/* No need for .ctors/.dtors section if linker can place them in
+   .init_array/.fini_array section.  */
+#ifndef NO_CTORS_DTORS_SECTIONS
 /* Put a word containing zero at the end of each of our two lists of function
    addresses.  Note that the words defined here go into the .ctors and .dtors
    sections of the crtend.o file, and since that file is always linked in
@@ -534,6 +541,7 @@ STATIC func_ptr __DTOR_END__[1]
   __attribute__((used, section(".dtors"), aligned(sizeof(func_ptr))))
   = { (func_ptr) 0 };
 #endif
+#endif /* NO_CTORS_DTORS_SECTIONS */
 
 #ifdef EH_FRAME_SECTION_NAME
 /* Terminate the frame unwind info section with a 4byte 0 as a sentinel;

^ permalink raw reply	[flat|nested] 10+ messages in thread

* Re: PATCH: PR target/46770: Use .init_array/.fini_array sections
  2011-01-27  0:08 ` PATCH: " H.J. Lu
@ 2011-01-27 11:09   ` Richard Guenther
  2011-03-14 19:29     ` H.J. Lu
  0 siblings, 1 reply; 10+ messages in thread
From: Richard Guenther @ 2011-01-27 11:09 UTC (permalink / raw)
  To: H.J. Lu; +Cc: gcc-patches

On Thu, Jan 27, 2011 at 12:12 AM, H.J. Lu <hongjiu.lu@intel.com> wrote:
> On Tue, Dec 14, 2010 at 05:20:48PM -0800, H.J. Lu wrote:
>> This patch uses .init_array/.fini_array sections instead of
>> .ctors/.dtors sections if mixing .init_array/.fini_array and
>> .ctors/.dtors sections with init_priority works.
>>
>> It removes .ctors/.ctors sections from executables and DSOes, which will
>> remove one function call at startup time from each executable and DSO.
>> It should reduce image size and improve system startup time.
>>
>> If a platform with a working .init_array/.fini_array support needs a
>> different .init_array/.fini_array implementation, it can set
>> use_initfini_array to no.
>>
>> Since .init_array/.fini_array is a target feature. --enable-initfini-array
>> is default to no unless the native run-time test is passed.
>>
>> To pass the native run-time test, a linker with SORT_BY_INIT_PRIORITY
>> support is required.  The binutils patch is available at
>>
>> http://sourceware.org/ml/binutils/2010-12/msg00466.html
>
> Linker patch has been checked in.
>
>>
>> This patch passed 32bit/64bit regression test on Linux/x86-64.  Any
>> comments?
>>
>
> This updated patch fixes build on Linux/ia64 and should work on others.
> Any comments?

Yes.  This is stage1 material.

Thanks,
Richard.

> Thanks.
>
>
> H.J.
> ----
> 2011-01-26  H.J. Lu  <hongjiu.lu@intel.com>
>
>        PR target/46770
>        * acinclude.m4 (gcc_AC_INITFINI_ARRAY): Removed.
>
>        * config.gcc (use_initfini_array): New variable.
>        Use initfini-array.o if supported.
>
>        * crtstuff.c: Don't generate .ctors nor .dtors sections if
>        NO_CTORS_DTORS_SECTIONS is defined.
>
>        * configure.ac: Remove gcc_AC_INITFINI_ARRAY.  Add
>        --enable-initfini-array and check if .init_array can be used with
>        .ctors.
>
>        * configure: Regenerated.
>
>        * config/initfini-array.c: New.
>        * config/initfini-array.h: Likewise.
>        * config/t-initfini-array: Likewise.
>
>        * config/arm/arm.c (arm_asm_init_sections): Call
>        elf_initfini_array_init_sections if NO_CTORS_DTORS_SECTIONS
>        is defined.
>        * config/avr/avr.c (avr_asm_init_sections): Likewise.
>        * config/ia64/ia64.c (ia64_asm_init_sections): Likewise.
>        * config/mep/mep.c (mep_asm_init_sections): Likewise.
>        * config/microblaze/microblaze.c (microblaze_elf_asm_init_sections):
>        Likewise.
>        * config/rs6000/rs6000.c (rs6000_elf_asm_init_sections): Likewise.
>        * config/stormy16/stormy16.c (xstormy16_asm_init_sections):
>        Likewise.
>        * config/v850/v850.c (v850_asm_init_sections): Likewise.
>
> diff --git a/gcc/acinclude.m4 b/gcc/acinclude.m4
> index 6f0f979..b0ab6d0 100644
> --- a/gcc/acinclude.m4
> +++ b/gcc/acinclude.m4
> @@ -369,26 +369,6 @@ else
>  fi
>  fi])
>
> -AC_DEFUN([gcc_AC_INITFINI_ARRAY],
> -[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
> -  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])])
> -  enable_initfini_array=$gcc_cv_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])
> -
>  dnl # _gcc_COMPUTE_GAS_VERSION
>  dnl # Used by gcc_GAS_VERSION_GTE_IFELSE
>  dnl #
> diff --git a/gcc/config.gcc b/gcc/config.gcc
> index 0f6aae1..256e433 100644
> --- a/gcc/config.gcc
> +++ b/gcc/config.gcc
> @@ -177,6 +177,9 @@
>  #  configure_default_options
>  #                      Set to an initializer for configure_default_options
>  #                      in configargs.h, based on --with-cpu et cetera.
> +#
> +#  use_initfini_array  If set to yes, .init_array/.fini_array sections
> +#                      will be used if they work.
>
>  # The following variables are used in each case-construct to build up the
>  # outgoing variables:
> @@ -219,6 +222,7 @@ default_gnu_indirect_function=no
>  target_gtfiles=
>  need_64bit_hwint=
>  need_64bit_isa=
> +use_initfini_array=yes
>
>  # Don't carry these over build->host->target.  Please.
>  xm_file=
> @@ -3093,6 +3097,16 @@ if test x$with_schedule = x; then
>        esac
>  fi
>
> +# Support --enable-initfini-array.  Use initfini-array.h only if
> +# use_initfini_array is also set to yes.  Some platforms don't need it
> +# even if enable_initfini_array is yes.
> +if test x$enable_initfini_array$use_initfini_array = xyesyes; then
> +  tm_file="${tm_file} initfini-array.h"
> +  tmake_file="${tmake_file} t-initfini-array"
> +  extra_objs="$extra_objs initfini-array.o"
> +  target_gtfiles="$target_gtfiles \$(srcdir)/config/initfini-array.c"
> +fi
> +
>  # Validate and mark as valid any --with options supported
>  # by this target.  In order to use a particular --with option
>  # you must list it in supported_defaults; validating the value
> diff --git a/gcc/config/arm/arm.c b/gcc/config/arm/arm.c
> index 3e75d7c..59a65c9 100644
> --- a/gcc/config/arm/arm.c
> +++ b/gcc/config/arm/arm.c
> @@ -22599,6 +22599,9 @@ arm_asm_init_sections (void)
>  {
>   exception_section = get_unnamed_section (0, output_section_asm_op,
>                                           "\t.handlerdata");
> +#ifdef NO_CTORS_DTORS_SECTIONS
> +  elf_initfini_array_init_sections ();
> +#endif
>  }
>  #endif /* ARM_UNWIND_INFO */
>
> diff --git a/gcc/config/avr/avr.c b/gcc/config/avr/avr.c
> index 30e4626..6cbef2a 100644
> --- a/gcc/config/avr/avr.c
> +++ b/gcc/config/avr/avr.c
> @@ -4958,6 +4958,9 @@ avr_asm_init_sections (void)
>                                         avr_output_progmem_section_asm_op,
>                                         NULL);
>   readonly_data_section = data_section;
> +#ifdef NO_CTORS_DTORS_SECTIONS
> +  elf_initfini_array_init_sections ();
> +#endif
>  }
>
>  static unsigned int
> diff --git a/gcc/config/ia64/ia64.c b/gcc/config/ia64/ia64.c
> index 5018e41..86f6049 100644
> --- a/gcc/config/ia64/ia64.c
> +++ b/gcc/config/ia64/ia64.c
> @@ -10142,6 +10142,9 @@ ia64_asm_init_sections (void)
>  {
>   exception_section = get_unnamed_section (0, output_section_asm_op,
>                                           "\t.handlerdata");
> +#ifdef NO_CTORS_DTORS_SECTIONS
> +  elf_initfini_array_init_sections ();
> +#endif
>  }
>
>  /* Implement TARGET_DEBUG_UNWIND_INFO.  */
> diff --git a/gcc/config/initfini-array.c b/gcc/config/initfini-array.c
> new file mode 100644
> index 0000000..d5fd40f
> --- /dev/null
> +++ b/gcc/config/initfini-array.c
> @@ -0,0 +1,79 @@
> +/* Definitions for ELF systems with .init_array/.fini_array section
> +   Copyright (C) 2010
> +   Free Software Foundation, Inc.
> +
> +This file is part of GCC.
> +
> +GCC 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 3, or (at your option) any later
> +version.
> +
> +GCC 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 GCC; see the file COPYING3.  If not see
> +<http://www.gnu.org/licenses/>.  */
> +
> +#include "config.h"
> +#include "system.h"
> +#include "coretypes.h"
> +#include "target.h"
> +#include "output.h"
> +#include "tree.h"
> +#include "ggc.h"
> +
> +static GTY(()) section *init_array_section;
> +static GTY(()) section *fini_array_section;
> +
> +void
> +elf_initfini_array_init_sections (void)
> +{
> +  init_array_section = get_unnamed_section (0, output_section_asm_op,
> +                                           "\t.section\t.init_array");
> +  fini_array_section = get_unnamed_section (0, output_section_asm_op,
> +                                           "\t.section\t.fini_array");
> +}
> +
> +static section *
> +get_elf_initfini_array_priority_section (int priority,
> +                                        bool constructor_p)
> +{
> +  section *sec;
> +  if (priority != DEFAULT_INIT_PRIORITY)
> +    {
> +      char buf[18];
> +      sprintf (buf, "%s.%.5u",
> +              constructor_p ? ".init_array" : ".fini_array",
> +              priority);
> +      sec = get_section (buf, SECTION_WRITE, NULL_TREE);
> +    }
> +  else
> +    sec = constructor_p ? init_array_section : fini_array_section;
> +  return sec;
> +}
> +
> +/* Use .init_array section for constructors. */
> +
> +void
> +elf_init_array_asm_out_constructor (rtx symbol, int priority)
> +{
> +  section *sec = get_elf_initfini_array_priority_section (priority,
> +                                                         true);
> +  assemble_addr_to_section (symbol, sec);
> +}
> +
> +/* Use .fini_array section for destructors. */
> +
> +void
> +elf_fini_array_asm_out_destructor (rtx symbol, int priority)
> +{
> +  section *sec = get_elf_initfini_array_priority_section (priority,
> +                                                         false);
> +  assemble_addr_to_section (symbol, sec);
> +}
> +
> +#include "gt-initfini-array.h"
> diff --git a/gcc/config/initfini-array.h b/gcc/config/initfini-array.h
> new file mode 100644
> index 0000000..b0b422a
> --- /dev/null
> +++ b/gcc/config/initfini-array.h
> @@ -0,0 +1,46 @@
> +/* Definitions for ELF systems with .init_array/.fini_array section
> +   support.
> +   Copyright (C) 2010
> +   Free Software Foundation, Inc.
> +
> +   This file is part of GCC.
> +
> +   GCC 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 3, or (at your
> +   option) any later version.
> +
> +   GCC 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 GCC; see the file COPYING3.  If not see
> +   <http://www.gnu.org/licenses/>.  */
> +
> +/* No need for .ctors/.dtors section since linker can place them in
> +   .init_array/.fini_array section.  */
> +#define NO_CTORS_DTORS_SECTIONS
> +
> +#undef INIT_SECTION_ASM_OP
> +#undef FINI_SECTION_ASM_OP
> +
> +/* FIXME: INIT_ARRAY_SECTION_ASM_OP and FINI_ARRAY_SECTION_ASM_OP
> +         aren't used in any assembly codes.  But we have to define
> +         them to something.  */
> +#define INIT_ARRAY_SECTION_ASM_OP Something
> +#define FINI_ARRAY_SECTION_ASM_OP Something
> +
> +#ifndef TARGET_ASM_INIT_SECTIONS
> +#define TARGET_ASM_INIT_SECTIONS elf_initfini_array_init_sections
> +#endif
> +extern void elf_initfini_array_init_sections (void);
> +
> +/* Use .init_array/.fini_array section for constructors and destructors. */
> +#undef TARGET_ASM_CONSTRUCTOR
> +#define TARGET_ASM_CONSTRUCTOR elf_init_array_asm_out_constructor
> +#undef TARGET_ASM_DESTRUCTOR
> +#define TARGET_ASM_DESTRUCTOR elf_fini_array_asm_out_destructor
> +extern void elf_init_array_asm_out_constructor (rtx, int);
> +extern void elf_fini_array_asm_out_destructor (rtx, int);
> diff --git a/gcc/config/mep/mep.c b/gcc/config/mep/mep.c
> index 913a30a..6651547 100644
> --- a/gcc/config/mep/mep.c
> +++ b/gcc/config/mep/mep.c
> @@ -7372,6 +7372,9 @@ mep_asm_init_sections (void)
>     = get_unnamed_section (SECTION_CODE, output_section_asm_op,
>                           "\t.section .ftext,\"ax\"\n\t.core");
>
> +#ifdef NO_CTORS_DTORS_SECTIONS
> +  elf_initfini_array_init_sections ();
> +#endif
>  }
>
>  /* Initialize the GCC target structure.  */
> diff --git a/gcc/config/microblaze/microblaze.c b/gcc/config/microblaze/microblaze.c
> index b50c794..7e802f1 100644
> --- a/gcc/config/microblaze/microblaze.c
> +++ b/gcc/config/microblaze/microblaze.c
> @@ -2765,6 +2765,9 @@ microblaze_elf_asm_init_sections (void)
>   sdata2_section
>     = get_unnamed_section (SECTION_WRITE, output_section_asm_op,
>                           SDATA2_SECTION_ASM_OP);
> +#ifdef NO_CTORS_DTORS_SECTIONS
> +  elf_initfini_array_init_sections ();
> +#endif
>  }
>
>  /*  Generate assembler code for constant parts of a trampoline.  */
> diff --git a/gcc/config/rs6000/rs6000.c b/gcc/config/rs6000/rs6000.c
> index 30f8b75..03328d5 100644
> --- a/gcc/config/rs6000/rs6000.c
> +++ b/gcc/config/rs6000/rs6000.c
> @@ -25063,6 +25063,10 @@ rs6000_elf_asm_init_sections (void)
>   sdata2_section
>     = get_unnamed_section (SECTION_WRITE, output_section_asm_op,
>                           SDATA2_SECTION_ASM_OP);
> +
> +#ifdef NO_CTORS_DTORS_SECTIONS
> +  elf_initfini_array_init_sections ();
> +#endif
>  }
>
>  /* Implement TARGET_SELECT_RTX_SECTION.  */
> diff --git a/gcc/config/stormy16/stormy16.c b/gcc/config/stormy16/stormy16.c
> index fa5c5b5..1819ef5 100644
> --- a/gcc/config/stormy16/stormy16.c
> +++ b/gcc/config/stormy16/stormy16.c
> @@ -1604,6 +1604,9 @@ xstormy16_asm_init_sections (void)
>     = get_unnamed_section (SECTION_WRITE | SECTION_BSS,
>                           output_section_asm_op,
>                           "\t.section \".bss_below100\",\"aw\",@nobits");
> +#ifdef NO_CTORS_DTORS_SECTIONS
> +  elf_initfini_array_init_sections ();
> +#endif
>  }
>
>  /* Mark symbols with the "below100" attribute so that we can use the
> diff --git a/gcc/config/t-initfini-array b/gcc/config/t-initfini-array
> new file mode 100644
> index 0000000..3dcb25d
> --- /dev/null
> +++ b/gcc/config/t-initfini-array
> @@ -0,0 +1,23 @@
> +# Copyright (C) 2010
> +# 2009 Free Software Foundation, Inc.
> +#
> +# This file is part of GCC.
> +#
> +# GCC 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 3, or (at your option)
> +# any later version.
> +#
> +# GCC 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 GCC; see the file COPYING3.  If not see
> +# <http://www.gnu.org/licenses/>.
> +
> +initfini-array.o: $(srcdir)/config/initfini-array.c gt-initfini-array.h \
> +       $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TARGET_H) output.h \
> +       $(TREE_H) $(GGC_H)
> +       $(COMPILER) -c $(ALL_COMPILERFLAGS) $(ALL_CPPFLAGS) $(INCLUDES) $<
> diff --git a/gcc/config/v850/v850.c b/gcc/config/v850/v850.c
> index 6d6ed78..4534a9a 100644
> --- a/gcc/config/v850/v850.c
> +++ b/gcc/config/v850/v850.c
> @@ -2978,6 +2978,10 @@ v850_asm_init_sections (void)
>     = get_unnamed_section (SECTION_WRITE | SECTION_BSS,
>                           output_section_asm_op,
>                           "\t.section .zbss,\"aw\"");
> +
> +#ifdef NO_CTORS_DTORS_SECTIONS
> +  elf_initfini_array_init_sections ();
> +#endif
>  }
>
>  static section *
> diff --git a/gcc/configure b/gcc/configure
> index 7a3e1e1..a1f8cb7 100755
> --- a/gcc/configure
> +++ b/gcc/configure
> @@ -10442,6 +10442,7 @@ fi
>  # Restore CFLAGS from before the gcc_AC_NEED_DECLARATIONS tests.
>  CFLAGS="$saved_CFLAGS"
>
> +# Check if .init_array can be used with .ctors.
>  # Check whether --enable-initfini-array was given.
>  if test "${enable_initfini_array+set}" = set; then :
>   enableval=$enable_initfini_array;
> @@ -10452,16 +10453,104 @@ $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;
> +extern void abort ();
> +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 };
> +
> +int
> +main ()
> +{
> +  return 0;
> +}
>  _ACEOF
>  if ac_fn_c_try_run "$LINENO"; then :
>   gcc_cv_initfini_array=yes
> @@ -10472,6 +10561,9 @@ 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; }
> diff --git a/gcc/configure.ac b/gcc/configure.ac
> index 77af4a1..dd15d9f 100644
> --- a/gcc/configure.ac
> +++ b/gcc/configure.ac
> @@ -1125,7 +1125,116 @@ fi
>  # Restore CFLAGS from before the gcc_AC_NEED_DECLARATIONS tests.
>  CFLAGS="$saved_CFLAGS"
>
> -gcc_AC_INITFINI_ARRAY
> +# Check if .init_array can be used with .ctors.
> +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([
> +extern void abort ();
> +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 };
> +
> +int
> +main ()
> +{
> +  return 0;
> +}])],
> +            [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
> +])
> +if test $enable_initfini_array = yes; then
> +  AC_DEFINE(HAVE_INITFINI_ARRAY, 1,
> +    [Define .init_array/.fini_array sections are available and working.])
> +fi
>
>  # mkdir takes a single argument on some systems.
>  gcc_AC_FUNC_MKDIR_TAKES_ONE_ARG
> diff --git a/gcc/crtstuff.c b/gcc/crtstuff.c
> index b65f490..7d31934e 100644
> --- a/gcc/crtstuff.c
> +++ b/gcc/crtstuff.c
> @@ -189,6 +189,9 @@ typedef void (*func_ptr) (void);
>    refer to only the __CTOR_END__ symbol in crtend.o and the __DTOR_LIST__
>    symbol in crtbegin.o, where they are defined.  */
>
> +/* No need for .ctors/.dtors section if linker can place them in
> +   .init_array/.fini_array section.  */
> +#ifndef NO_CTORS_DTORS_SECTIONS
>  /* The -1 is a flag to __do_global_[cd]tors indicating that this table
>    does not start with a count of elements.  */
>  #ifdef CTOR_LIST_BEGIN
> @@ -219,6 +222,7 @@ STATIC func_ptr __DTOR_LIST__[1]
>   __attribute__((section(".dtors"), aligned(sizeof(func_ptr))))
>   = { (func_ptr) (-1) };
>  #endif /* __DTOR_LIST__ alternatives */
> +#endif /* NO_CTORS_DTORS_SECTIONS */
>
>  #ifdef USE_EH_FRAME_REGISTRY
>  /* Stick a label at the beginning of the frame unwind info so we can register
> @@ -489,6 +493,9 @@ __do_global_ctors_1(void)
>
>  #elif defined(CRT_END) /* ! CRT_BEGIN */
>
> +/* No need for .ctors/.dtors section if linker can place them in
> +   .init_array/.fini_array section.  */
> +#ifndef NO_CTORS_DTORS_SECTIONS
>  /* Put a word containing zero at the end of each of our two lists of function
>    addresses.  Note that the words defined here go into the .ctors and .dtors
>    sections of the crtend.o file, and since that file is always linked in
> @@ -534,6 +541,7 @@ STATIC func_ptr __DTOR_END__[1]
>   __attribute__((used, section(".dtors"), aligned(sizeof(func_ptr))))
>   = { (func_ptr) 0 };
>  #endif
> +#endif /* NO_CTORS_DTORS_SECTIONS */
>
>  #ifdef EH_FRAME_SECTION_NAME
>  /* Terminate the frame unwind info section with a 4byte 0 as a sentinel;
>

^ permalink raw reply	[flat|nested] 10+ messages in thread

* Re: PATCH: PR target/46770: Use .init_array/.fini_array sections
  2011-01-27 11:09   ` Richard Guenther
@ 2011-03-14 19:29     ` H.J. Lu
  0 siblings, 0 replies; 10+ messages in thread
From: H.J. Lu @ 2011-03-14 19:29 UTC (permalink / raw)
  To: Richard Guenther; +Cc: gcc-patches

[-- Attachment #1: Type: text/plain, Size: 2696 bytes --]

On Thu, Jan 27, 2011 at 2:40 AM, Richard Guenther
<richard.guenther@gmail.com> wrote:
> On Thu, Jan 27, 2011 at 12:12 AM, H.J. Lu <hongjiu.lu@intel.com> wrote:
>> On Tue, Dec 14, 2010 at 05:20:48PM -0800, H.J. Lu wrote:
>>> This patch uses .init_array/.fini_array sections instead of
>>> .ctors/.dtors sections if mixing .init_array/.fini_array and
>>> .ctors/.dtors sections with init_priority works.
>>>
>>> It removes .ctors/.ctors sections from executables and DSOes, which will
>>> remove one function call at startup time from each executable and DSO.
>>> It should reduce image size and improve system startup time.
>>>
>>> If a platform with a working .init_array/.fini_array support needs a
>>> different .init_array/.fini_array implementation, it can set
>>> use_initfini_array to no.
>>>
>>> Since .init_array/.fini_array is a target feature. --enable-initfini-array
>>> is default to no unless the native run-time test is passed.
>>>
>>> To pass the native run-time test, a linker with SORT_BY_INIT_PRIORITY
>>> support is required.  The binutils patch is available at
>>>
>>> http://sourceware.org/ml/binutils/2010-12/msg00466.html
>>
>> Linker patch has been checked in.
>>
>>>
>>> This patch passed 32bit/64bit regression test on Linux/x86-64.  Any
>>> comments?
>>>
>>
>> This updated patch fixes build on Linux/ia64 and should work on others.
>> Any comments?
>
> Yes.  This is stage1 material.
>

Here is the updated patch.  OK for trunk?

Thanks.


-- 
H.J.
----
2011-03-14  H.J. Lu  <hongjiu.lu@intel.com>

	PR target/46770
	* acinclude.m4 (gcc_AC_INITFINI_ARRAY): Removed.

	* config.gcc (use_initfini_array): New variable.
	Use initfini-array.o if supported.

	* crtstuff.c: Don't generate .ctors nor .dtors sections if
	NO_CTORS_DTORS_SECTIONS is defined.

	* configure.ac: Remove gcc_AC_INITFINI_ARRAY.  Add
	--enable-initfini-array and check if .init_array can be used with
	.ctors.

	* configure: Regenerated.

	* config/initfini-array.c: New.
	* config/initfini-array.h: Likewise.
	* config/t-initfini-array: Likewise.

	* config/arm/arm.c (arm_asm_init_sections): Call
	elf_initfini_array_init_sections if NO_CTORS_DTORS_SECTIONS
	is defined.
	* config/avr/avr.c (avr_asm_init_sections): Likewise.
	* config/ia64/ia64.c (ia64_asm_init_sections): Likewise.
	* config/mep/mep.c (mep_asm_init_sections): Likewise.
	* config/microblaze/microblaze.c (microblaze_elf_asm_init_sections):
	Likewise.
	* config/rs6000/rs6000.c (rs6000_elf_asm_init_sections): Likewise.
	* config/stormy16/stormy16.c (xstormy16_asm_init_sections):
	Likewise.
	* config/v850/v850.c (v850_asm_init_sections): Likewise.

[-- Attachment #2: gcc-pr46770-5.patch --]
[-- Type: text/plain, Size: 21822 bytes --]

This patch uses .init_array/.fini_array sections instead of
.ctors/.dtors sections if mixing .init_array/.fini_array and
.ctors/.dtors sections with init_priority works.

It removes .ctors/.ctors sections from executables and DSOes, which will
remove one function call at startup time from each executable and DSO.
It should reduce image size and improve system startup time. 

If a platform with a working .init_array/.fini_array support needs a
different .init_array/.fini_array implementation, it can set
use_initfini_array to no.

Since .init_array/.fini_array is a target feature. --enable-initfini-array
is default to no unless the native run-time test is passed.

To pass the native run-time test, a linker with SORT_BY_INIT_PRIORITY
support is required.  The binutils patch is available at

http://sourceware.org/ml/binutils/2010-12/msg00466.html

This patch passed 32bit/64bit regression test on Linux/x86-64.

Thanks.

H.J.
---
2011-03-14  H.J. Lu  <hongjiu.lu@intel.com>

	PR target/46770
	* acinclude.m4 (gcc_AC_INITFINI_ARRAY): Removed.

	* config.gcc (use_initfini_array): New variable.
	Use initfini-array.o if supported.

	* crtstuff.c: Don't generate .ctors nor .dtors sections if
	NO_CTORS_DTORS_SECTIONS is defined.

	* configure.ac: Remove gcc_AC_INITFINI_ARRAY.  Add
	--enable-initfini-array and check if .init_array can be used with
	.ctors.

	* configure: Regenerated.

	* config/initfini-array.c: New.
	* config/initfini-array.h: Likewise.
	* config/t-initfini-array: Likewise.

	* config/arm/arm.c (arm_asm_init_sections): Call
	elf_initfini_array_init_sections if NO_CTORS_DTORS_SECTIONS
	is defined.
	* config/avr/avr.c (avr_asm_init_sections): Likewise.
	* config/ia64/ia64.c (ia64_asm_init_sections): Likewise.
	* config/mep/mep.c (mep_asm_init_sections): Likewise.
	* config/microblaze/microblaze.c (microblaze_elf_asm_init_sections):
	Likewise.
	* config/rs6000/rs6000.c (rs6000_elf_asm_init_sections): Likewise.
	* config/stormy16/stormy16.c (xstormy16_asm_init_sections):
	Likewise.
	* config/v850/v850.c (v850_asm_init_sections): Likewise.

diff --git a/gcc/acinclude.m4 b/gcc/acinclude.m4
index 3eec559..0f5f686 100644
--- a/gcc/acinclude.m4
+++ b/gcc/acinclude.m4
@@ -369,26 +369,6 @@ else
 fi
 fi])
 
-AC_DEFUN([gcc_AC_INITFINI_ARRAY],
-[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
-  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])])
-  enable_initfini_array=$gcc_cv_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])
-
 dnl # _gcc_COMPUTE_GAS_VERSION
 dnl # Used by gcc_GAS_VERSION_GTE_IFELSE
 dnl #
diff --git a/gcc/config.gcc b/gcc/config.gcc
index 58f6787..e954cf0 100644
--- a/gcc/config.gcc
+++ b/gcc/config.gcc
@@ -177,6 +177,9 @@
 #  configure_default_options
 #			Set to an initializer for configure_default_options
 #			in configargs.h, based on --with-cpu et cetera.
+#
+#  use_initfini_array	If set to yes, .init_array/.fini_array sections
+#			will be used if they work.
 
 # The following variables are used in each case-construct to build up the
 # outgoing variables:
@@ -219,6 +222,7 @@ default_gnu_indirect_function=no
 target_gtfiles=
 need_64bit_hwint=
 need_64bit_isa=
+use_initfini_array=yes
 
 # Don't carry these over build->host->target.  Please.
 xm_file=
@@ -3150,6 +3154,16 @@ if test x$with_schedule = x; then
 	esac
 fi
 
+# Support --enable-initfini-array.  Use initfini-array.h only if
+# use_initfini_array is also set to yes.  Some platforms don't need it
+# even if enable_initfini_array is yes.
+if test x$enable_initfini_array$use_initfini_array = xyesyes; then
+  tm_file="${tm_file} initfini-array.h"
+  tmake_file="${tmake_file} t-initfini-array"
+  extra_objs="$extra_objs initfini-array.o"
+  target_gtfiles="$target_gtfiles \$(srcdir)/config/initfini-array.c"
+fi
+
 # Validate and mark as valid any --with options supported
 # by this target.  In order to use a particular --with option
 # you must list it in supported_defaults; validating the value
diff --git a/gcc/config/arm/arm.c b/gcc/config/arm/arm.c
index 8515002..1c438a1 100644
--- a/gcc/config/arm/arm.c
+++ b/gcc/config/arm/arm.c
@@ -22684,6 +22684,9 @@ arm_asm_init_sections (void)
 {
   exception_section = get_unnamed_section (0, output_section_asm_op,
 					   "\t.handlerdata");
+#ifdef NO_CTORS_DTORS_SECTIONS
+  elf_initfini_array_init_sections ();
+#endif
 }
 #endif /* ARM_UNWIND_INFO */
 
diff --git a/gcc/config/avr/avr.c b/gcc/config/avr/avr.c
index 92cc7b6..9c84261 100644
--- a/gcc/config/avr/avr.c
+++ b/gcc/config/avr/avr.c
@@ -5027,6 +5027,9 @@ avr_asm_init_sections (void)
 					 avr_output_progmem_section_asm_op,
 					 NULL);
   readonly_data_section = data_section;
+#ifdef NO_CTORS_DTORS_SECTIONS
+  elf_initfini_array_init_sections ();
+#endif
 }
 
 static unsigned int
diff --git a/gcc/config/ia64/ia64.c b/gcc/config/ia64/ia64.c
index 1d3f8b1..fb440a5 100644
--- a/gcc/config/ia64/ia64.c
+++ b/gcc/config/ia64/ia64.c
@@ -10096,6 +10096,9 @@ ia64_asm_init_sections (void)
 {
   exception_section = get_unnamed_section (0, output_section_asm_op,
 					   "\t.handlerdata");
+#ifdef NO_CTORS_DTORS_SECTIONS
+  elf_initfini_array_init_sections ();
+#endif
 }
 
 /* Implement TARGET_DEBUG_UNWIND_INFO.  */
diff --git a/gcc/config/initfini-array.c b/gcc/config/initfini-array.c
new file mode 100644
index 0000000..d5fd40f
--- /dev/null
+++ b/gcc/config/initfini-array.c
@@ -0,0 +1,79 @@
+/* Definitions for ELF systems with .init_array/.fini_array section
+   Copyright (C) 2010
+   Free Software Foundation, Inc.
+
+This file is part of GCC.
+
+GCC 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 3, or (at your option) any later
+version.
+
+GCC 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 GCC; see the file COPYING3.  If not see
+<http://www.gnu.org/licenses/>.  */
+
+#include "config.h"
+#include "system.h"
+#include "coretypes.h"
+#include "target.h"
+#include "output.h"
+#include "tree.h"
+#include "ggc.h"
+
+static GTY(()) section *init_array_section;
+static GTY(()) section *fini_array_section;
+
+void
+elf_initfini_array_init_sections (void)
+{
+  init_array_section = get_unnamed_section (0, output_section_asm_op,
+					    "\t.section\t.init_array");
+  fini_array_section = get_unnamed_section (0, output_section_asm_op,
+					    "\t.section\t.fini_array");
+}
+
+static section *
+get_elf_initfini_array_priority_section (int priority,
+					 bool constructor_p)
+{
+  section *sec;
+  if (priority != DEFAULT_INIT_PRIORITY)
+    {
+      char buf[18];
+      sprintf (buf, "%s.%.5u", 
+	       constructor_p ? ".init_array" : ".fini_array",
+	       priority);
+      sec = get_section (buf, SECTION_WRITE, NULL_TREE);
+    }
+  else
+    sec = constructor_p ? init_array_section : fini_array_section;
+  return sec;
+}
+
+/* Use .init_array section for constructors. */
+
+void
+elf_init_array_asm_out_constructor (rtx symbol, int priority)
+{
+  section *sec = get_elf_initfini_array_priority_section (priority,
+							  true);
+  assemble_addr_to_section (symbol, sec);
+}
+
+/* Use .fini_array section for destructors. */
+
+void
+elf_fini_array_asm_out_destructor (rtx symbol, int priority)
+{
+  section *sec = get_elf_initfini_array_priority_section (priority,
+							  false);
+  assemble_addr_to_section (symbol, sec);
+}
+
+#include "gt-initfini-array.h"
diff --git a/gcc/config/initfini-array.h b/gcc/config/initfini-array.h
new file mode 100644
index 0000000..b0b422a
--- /dev/null
+++ b/gcc/config/initfini-array.h
@@ -0,0 +1,46 @@
+/* Definitions for ELF systems with .init_array/.fini_array section
+   support.
+   Copyright (C) 2010
+   Free Software Foundation, Inc.
+
+   This file is part of GCC.
+
+   GCC 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 3, or (at your
+   option) any later version.
+
+   GCC 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 GCC; see the file COPYING3.  If not see
+   <http://www.gnu.org/licenses/>.  */
+
+/* No need for .ctors/.dtors section since linker can place them in
+   .init_array/.fini_array section.  */
+#define NO_CTORS_DTORS_SECTIONS
+
+#undef INIT_SECTION_ASM_OP
+#undef FINI_SECTION_ASM_OP
+
+/* FIXME: INIT_ARRAY_SECTION_ASM_OP and FINI_ARRAY_SECTION_ASM_OP
+	  aren't used in any assembly codes.  But we have to define
+	  them to something.  */
+#define INIT_ARRAY_SECTION_ASM_OP Something
+#define FINI_ARRAY_SECTION_ASM_OP Something
+
+#ifndef TARGET_ASM_INIT_SECTIONS
+#define TARGET_ASM_INIT_SECTIONS elf_initfini_array_init_sections
+#endif
+extern void elf_initfini_array_init_sections (void);
+
+/* Use .init_array/.fini_array section for constructors and destructors. */
+#undef TARGET_ASM_CONSTRUCTOR
+#define TARGET_ASM_CONSTRUCTOR elf_init_array_asm_out_constructor
+#undef TARGET_ASM_DESTRUCTOR
+#define TARGET_ASM_DESTRUCTOR elf_fini_array_asm_out_destructor
+extern void elf_init_array_asm_out_constructor (rtx, int);
+extern void elf_fini_array_asm_out_destructor (rtx, int);
diff --git a/gcc/config/mep/mep.c b/gcc/config/mep/mep.c
index 913a30a..6651547 100644
--- a/gcc/config/mep/mep.c
+++ b/gcc/config/mep/mep.c
@@ -7372,6 +7372,9 @@ mep_asm_init_sections (void)
     = get_unnamed_section (SECTION_CODE, output_section_asm_op,
 			   "\t.section .ftext,\"ax\"\n\t.core");
 
+#ifdef NO_CTORS_DTORS_SECTIONS
+  elf_initfini_array_init_sections ();
+#endif
 }
 \f
 /* Initialize the GCC target structure.  */
diff --git a/gcc/config/microblaze/microblaze.c b/gcc/config/microblaze/microblaze.c
index b50c794..7e802f1 100644
--- a/gcc/config/microblaze/microblaze.c
+++ b/gcc/config/microblaze/microblaze.c
@@ -2765,6 +2765,9 @@ microblaze_elf_asm_init_sections (void)
   sdata2_section
     = get_unnamed_section (SECTION_WRITE, output_section_asm_op,
 			   SDATA2_SECTION_ASM_OP);
+#ifdef NO_CTORS_DTORS_SECTIONS
+  elf_initfini_array_init_sections ();
+#endif
 }
 
 /*  Generate assembler code for constant parts of a trampoline.  */
diff --git a/gcc/config/rs6000/rs6000.c b/gcc/config/rs6000/rs6000.c
index 231651e..ee5b466 100644
--- a/gcc/config/rs6000/rs6000.c
+++ b/gcc/config/rs6000/rs6000.c
@@ -25274,6 +25274,10 @@ rs6000_elf_asm_init_sections (void)
   sdata2_section
     = get_unnamed_section (SECTION_WRITE, output_section_asm_op,
 			   SDATA2_SECTION_ASM_OP);
+
+#ifdef NO_CTORS_DTORS_SECTIONS
+  elf_initfini_array_init_sections ();
+#endif
 }
 
 /* Implement TARGET_SELECT_RTX_SECTION.  */
diff --git a/gcc/config/stormy16/stormy16.c b/gcc/config/stormy16/stormy16.c
index 3954d50..f6f38f8 100644
--- a/gcc/config/stormy16/stormy16.c
+++ b/gcc/config/stormy16/stormy16.c
@@ -1569,6 +1569,9 @@ xstormy16_asm_init_sections (void)
     = get_unnamed_section (SECTION_WRITE | SECTION_BSS,
 			   output_section_asm_op,
 			   "\t.section \".bss_below100\",\"aw\",@nobits");
+#ifdef NO_CTORS_DTORS_SECTIONS
+  elf_initfini_array_init_sections ();
+#endif
 }
 
 /* Mark symbols with the "below100" attribute so that we can use the
diff --git a/gcc/config/t-initfini-array b/gcc/config/t-initfini-array
new file mode 100644
index 0000000..3dcb25d
--- /dev/null
+++ b/gcc/config/t-initfini-array
@@ -0,0 +1,23 @@
+# Copyright (C) 2010
+# 2009 Free Software Foundation, Inc.
+#
+# This file is part of GCC.
+#
+# GCC 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 3, or (at your option)
+# any later version.
+#
+# GCC 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 GCC; see the file COPYING3.  If not see
+# <http://www.gnu.org/licenses/>.
+
+initfini-array.o: $(srcdir)/config/initfini-array.c gt-initfini-array.h \
+	$(CONFIG_H) $(SYSTEM_H) coretypes.h $(TARGET_H) output.h \
+	$(TREE_H) $(GGC_H)
+	$(COMPILER) -c $(ALL_COMPILERFLAGS) $(ALL_CPPFLAGS) $(INCLUDES) $<
diff --git a/gcc/config/v850/v850.c b/gcc/config/v850/v850.c
index 6d6ed78..4534a9a 100644
--- a/gcc/config/v850/v850.c
+++ b/gcc/config/v850/v850.c
@@ -2978,6 +2978,10 @@ v850_asm_init_sections (void)
     = get_unnamed_section (SECTION_WRITE | SECTION_BSS,
 			   output_section_asm_op,
 			   "\t.section .zbss,\"aw\"");
+
+#ifdef NO_CTORS_DTORS_SECTIONS
+  elf_initfini_array_init_sections ();
+#endif
 }
 
 static section *
diff --git a/gcc/configure b/gcc/configure
index a454946..8d6b8e3 100755
--- a/gcc/configure
+++ b/gcc/configure
@@ -10442,6 +10442,7 @@ fi
 # Restore CFLAGS from before the gcc_AC_NEED_DECLARATIONS tests.
 CFLAGS="$saved_CFLAGS"
 
+# Check if .init_array can be used with .ctors.
 # Check whether --enable-initfini-array was given.
 if test "${enable_initfini_array+set}" = set; then :
   enableval=$enable_initfini_array;
@@ -10452,16 +10453,104 @@ $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;
+extern void abort ();
+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 };
+
+int
+main ()
+{
+  return 0;
+}
 _ACEOF
 if ac_fn_c_try_run "$LINENO"; then :
   gcc_cv_initfini_array=yes
@@ -10472,6 +10561,9 @@ 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; }
@@ -17505,7 +17597,7 @@ else
   lt_dlunknown=0; lt_dlno_uscore=1; lt_dlneed_uscore=2
   lt_status=$lt_dlunknown
   cat > conftest.$ac_ext <<_LT_EOF
-#line 17508 "configure"
+#line 17600 "configure"
 #include "confdefs.h"
 
 #if HAVE_DLFCN_H
@@ -17611,7 +17703,7 @@ else
   lt_dlunknown=0; lt_dlno_uscore=1; lt_dlneed_uscore=2
   lt_status=$lt_dlunknown
   cat > conftest.$ac_ext <<_LT_EOF
-#line 17614 "configure"
+#line 17706 "configure"
 #include "confdefs.h"
 
 #if HAVE_DLFCN_H
diff --git a/gcc/configure.ac b/gcc/configure.ac
index 03a8cef..c38a344 100644
--- a/gcc/configure.ac
+++ b/gcc/configure.ac
@@ -1125,7 +1125,116 @@ fi
 # Restore CFLAGS from before the gcc_AC_NEED_DECLARATIONS tests.
 CFLAGS="$saved_CFLAGS"
 
-gcc_AC_INITFINI_ARRAY
+# Check if .init_array can be used with .ctors.
+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([
+extern void abort ();
+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 };
+
+int
+main ()
+{
+  return 0;
+}])],
+	     [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
+])
+if test $enable_initfini_array = yes; then
+  AC_DEFINE(HAVE_INITFINI_ARRAY, 1,
+    [Define .init_array/.fini_array sections are available and working.])
+fi
 
 # mkdir takes a single argument on some systems. 
 gcc_AC_FUNC_MKDIR_TAKES_ONE_ARG
diff --git a/gcc/crtstuff.c b/gcc/crtstuff.c
index b65f490..7d31934e 100644
--- a/gcc/crtstuff.c
+++ b/gcc/crtstuff.c
@@ -189,6 +189,9 @@ typedef void (*func_ptr) (void);
    refer to only the __CTOR_END__ symbol in crtend.o and the __DTOR_LIST__
    symbol in crtbegin.o, where they are defined.  */
 
+/* No need for .ctors/.dtors section if linker can place them in
+   .init_array/.fini_array section.  */
+#ifndef NO_CTORS_DTORS_SECTIONS
 /* The -1 is a flag to __do_global_[cd]tors indicating that this table
    does not start with a count of elements.  */
 #ifdef CTOR_LIST_BEGIN
@@ -219,6 +222,7 @@ STATIC func_ptr __DTOR_LIST__[1]
   __attribute__((section(".dtors"), aligned(sizeof(func_ptr))))
   = { (func_ptr) (-1) };
 #endif /* __DTOR_LIST__ alternatives */
+#endif /* NO_CTORS_DTORS_SECTIONS */
 
 #ifdef USE_EH_FRAME_REGISTRY
 /* Stick a label at the beginning of the frame unwind info so we can register
@@ -489,6 +493,9 @@ __do_global_ctors_1(void)
 
 #elif defined(CRT_END) /* ! CRT_BEGIN */
 
+/* No need for .ctors/.dtors section if linker can place them in
+   .init_array/.fini_array section.  */
+#ifndef NO_CTORS_DTORS_SECTIONS
 /* Put a word containing zero at the end of each of our two lists of function
    addresses.  Note that the words defined here go into the .ctors and .dtors
    sections of the crtend.o file, and since that file is always linked in
@@ -534,6 +541,7 @@ STATIC func_ptr __DTOR_END__[1]
   __attribute__((used, section(".dtors"), aligned(sizeof(func_ptr))))
   = { (func_ptr) 0 };
 #endif
+#endif /* NO_CTORS_DTORS_SECTIONS */
 
 #ifdef EH_FRAME_SECTION_NAME
 /* Terminate the frame unwind info section with a 4byte 0 as a sentinel;

^ permalink raw reply	[flat|nested] 10+ messages in thread

* Re: PATCH: PR target/46770: Use .init_array/.fini_array sections
  2010-12-10  9:49       ` Richard Guenther
@ 2010-12-10 12:43         ` H.J. Lu
  0 siblings, 0 replies; 10+ messages in thread
From: H.J. Lu @ 2010-12-10 12:43 UTC (permalink / raw)
  To: Richard Guenther; +Cc: Joseph S. Myers, gcc-patches, Uros Bizjak

On Fri, Dec 10, 2010 at 1:40 AM, Richard Guenther
<richard.guenther@gmail.com> wrote:
> On Thu, Dec 9, 2010 at 7:44 PM, H.J. Lu <hjl.tools@gmail.com> wrote:
>> On Tue, Dec 7, 2010 at 8:57 AM, H.J. Lu <hjl.tools@gmail.com> wrote:
>>> On Tue, Dec 7, 2010 at 8:31 AM, Joseph S. Myers <joseph@codesourcery.com> wrote:
>>>> On Tue, 7 Dec 2010, H.J. Lu wrote:
>>>>
>>>>> @@ -2698,6 +2698,7 @@ esac
>>>>>  case ${target} in
>>>>>  i[34567]86-*-linux* | x86_64-*-linux*)
>>>>>       tmake_file="${tmake_file} i386/t-pmm_malloc i386/t-i386"
>>>>> +     use_initfini_array=yes
>>>>
>>>> Please update the comment at the top of config.gcc listing the variables
>>>> it sets, and put a default (empty or "no") setting of this variable along
>>>> with the other defaults as well.
>>>
>>> Done.
>>>
>>>>> +#include "tree.h"
>>>>
>>>> What is tree.h needed for here?
>>>
>>> DEFAULT_INIT_PRIORITY is defined in tree.h.
>>>
>>>>> +     $(TREE_H) $(GCC_H)
>>>>
>>>> I think you mean $(GGC_H) not $(GCC_H) (which is gcc.h, the header for the
>>>> driver).
>>>>
>>>
>>> Fixed.
>>>
>>>  Here is the updated patch. OK for trunk?
>>>
>>> Thanks.
>>>
>>> --
>>> H.J.
>>> ---
>>> 2010-12-07  H.J. Lu  <hongjiu.lu@intel.com>
>>>
>>>        PR target/46770
>>>        * config.gcc (use_initfini_array): New variable.
>>>        Use initfini-array.o if supported.
>>>
>>>        * config/initfini-array.c: New.
>>>        * config/initfini-array.h: Likewise.
>>>        * config/t-initfini-array: Likewise.
>>>
>>
>> This is a platform feature. I helped put this into gABI and implemented
>> it in as/ld/glibc 10 years ago.  It is the time to enable it on Linux/x86 now.
>> Any objections to check it in if there are no further comments in 48hours?
>
> I don't see any approval.
>
> Do you really think it is an appropriate change at this stage?
>

Yes, 10 years is long enough,


-- 
H.J.

^ permalink raw reply	[flat|nested] 10+ messages in thread

* Re: PATCH: PR target/46770: Use .init_array/.fini_array sections
  2010-12-09 19:00     ` H.J. Lu
@ 2010-12-10  9:49       ` Richard Guenther
  2010-12-10 12:43         ` H.J. Lu
  0 siblings, 1 reply; 10+ messages in thread
From: Richard Guenther @ 2010-12-10  9:49 UTC (permalink / raw)
  To: H.J. Lu; +Cc: Joseph S. Myers, gcc-patches, Uros Bizjak

On Thu, Dec 9, 2010 at 7:44 PM, H.J. Lu <hjl.tools@gmail.com> wrote:
> On Tue, Dec 7, 2010 at 8:57 AM, H.J. Lu <hjl.tools@gmail.com> wrote:
>> On Tue, Dec 7, 2010 at 8:31 AM, Joseph S. Myers <joseph@codesourcery.com> wrote:
>>> On Tue, 7 Dec 2010, H.J. Lu wrote:
>>>
>>>> @@ -2698,6 +2698,7 @@ esac
>>>>  case ${target} in
>>>>  i[34567]86-*-linux* | x86_64-*-linux*)
>>>>       tmake_file="${tmake_file} i386/t-pmm_malloc i386/t-i386"
>>>> +     use_initfini_array=yes
>>>
>>> Please update the comment at the top of config.gcc listing the variables
>>> it sets, and put a default (empty or "no") setting of this variable along
>>> with the other defaults as well.
>>
>> Done.
>>
>>>> +#include "tree.h"
>>>
>>> What is tree.h needed for here?
>>
>> DEFAULT_INIT_PRIORITY is defined in tree.h.
>>
>>>> +     $(TREE_H) $(GCC_H)
>>>
>>> I think you mean $(GGC_H) not $(GCC_H) (which is gcc.h, the header for the
>>> driver).
>>>
>>
>> Fixed.
>>
>>  Here is the updated patch. OK for trunk?
>>
>> Thanks.
>>
>> --
>> H.J.
>> ---
>> 2010-12-07  H.J. Lu  <hongjiu.lu@intel.com>
>>
>>        PR target/46770
>>        * config.gcc (use_initfini_array): New variable.
>>        Use initfini-array.o if supported.
>>
>>        * config/initfini-array.c: New.
>>        * config/initfini-array.h: Likewise.
>>        * config/t-initfini-array: Likewise.
>>
>
> This is a platform feature. I helped put this into gABI and implemented
> it in as/ld/glibc 10 years ago.  It is the time to enable it on Linux/x86 now.
> Any objections to check it in if there are no further comments in 48hours?

I don't see any approval.

Do you really think it is an appropriate change at this stage?

Thanks,
Richard.

> Thanks.
>
>
> --
> H.J.
>

^ permalink raw reply	[flat|nested] 10+ messages in thread

* Re: PATCH: PR target/46770: Use .init_array/.fini_array sections
  2010-12-07 17:01   ` H.J. Lu
@ 2010-12-09 19:00     ` H.J. Lu
  2010-12-10  9:49       ` Richard Guenther
  0 siblings, 1 reply; 10+ messages in thread
From: H.J. Lu @ 2010-12-09 19:00 UTC (permalink / raw)
  To: Joseph S. Myers; +Cc: gcc-patches, Uros Bizjak

On Tue, Dec 7, 2010 at 8:57 AM, H.J. Lu <hjl.tools@gmail.com> wrote:
> On Tue, Dec 7, 2010 at 8:31 AM, Joseph S. Myers <joseph@codesourcery.com> wrote:
>> On Tue, 7 Dec 2010, H.J. Lu wrote:
>>
>>> @@ -2698,6 +2698,7 @@ esac
>>>  case ${target} in
>>>  i[34567]86-*-linux* | x86_64-*-linux*)
>>>       tmake_file="${tmake_file} i386/t-pmm_malloc i386/t-i386"
>>> +     use_initfini_array=yes
>>
>> Please update the comment at the top of config.gcc listing the variables
>> it sets, and put a default (empty or "no") setting of this variable along
>> with the other defaults as well.
>
> Done.
>
>>> +#include "tree.h"
>>
>> What is tree.h needed for here?
>
> DEFAULT_INIT_PRIORITY is defined in tree.h.
>
>>> +     $(TREE_H) $(GCC_H)
>>
>> I think you mean $(GGC_H) not $(GCC_H) (which is gcc.h, the header for the
>> driver).
>>
>
> Fixed.
>
>  Here is the updated patch. OK for trunk?
>
> Thanks.
>
> --
> H.J.
> ---
> 2010-12-07  H.J. Lu  <hongjiu.lu@intel.com>
>
>        PR target/46770
>        * config.gcc (use_initfini_array): New variable.
>        Use initfini-array.o if supported.
>
>        * config/initfini-array.c: New.
>        * config/initfini-array.h: Likewise.
>        * config/t-initfini-array: Likewise.
>

This is a platform feature. I helped put this into gABI and implemented
it in as/ld/glibc 10 years ago.  It is the time to enable it on Linux/x86 now.
Any objections to check it in if there are no further comments in 48hours?

Thanks.


-- 
H.J.

^ permalink raw reply	[flat|nested] 10+ messages in thread

* Re: PATCH: PR target/46770: Use .init_array/.fini_array sections
  2010-12-07 16:36 ` Joseph S. Myers
@ 2010-12-07 17:01   ` H.J. Lu
  2010-12-09 19:00     ` H.J. Lu
  0 siblings, 1 reply; 10+ messages in thread
From: H.J. Lu @ 2010-12-07 17:01 UTC (permalink / raw)
  To: Joseph S. Myers; +Cc: gcc-patches, Uros Bizjak

[-- Attachment #1: Type: text/plain, Size: 1110 bytes --]

On Tue, Dec 7, 2010 at 8:31 AM, Joseph S. Myers <joseph@codesourcery.com> wrote:
> On Tue, 7 Dec 2010, H.J. Lu wrote:
>
>> @@ -2698,6 +2698,7 @@ esac
>>  case ${target} in
>>  i[34567]86-*-linux* | x86_64-*-linux*)
>>       tmake_file="${tmake_file} i386/t-pmm_malloc i386/t-i386"
>> +     use_initfini_array=yes
>
> Please update the comment at the top of config.gcc listing the variables
> it sets, and put a default (empty or "no") setting of this variable along
> with the other defaults as well.

Done.

>> +#include "tree.h"
>
> What is tree.h needed for here?

DEFAULT_INIT_PRIORITY is defined in tree.h.

>> +     $(TREE_H) $(GCC_H)
>
> I think you mean $(GGC_H) not $(GCC_H) (which is gcc.h, the header for the
> driver).
>

Fixed.

 Here is the updated patch. OK for trunk?

Thanks.

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

	PR target/46770
	* config.gcc (use_initfini_array): New variable.
	Use initfini-array.o if supported.

	* config/initfini-array.c: New.
	* config/initfini-array.h: Likewise.
	* config/t-initfini-array: Likewise.

[-- Attachment #2: gcc-pr46770-2.patch --]
[-- Type: text/plain, Size: 7066 bytes --]

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

	PR target/46770
	* config.gcc (use_initfini_array): New variable.
	Use initfini-array.o if supported.

	* config/initfini-array.c: New.
	* config/initfini-array.h: Likewise.
	* config/t-initfini-array: Likewise.

diff --git a/gcc/config.gcc b/gcc/config.gcc
index dfbf2c5..917c1ce 100644
--- a/gcc/config.gcc
+++ b/gcc/config.gcc
@@ -177,6 +177,9 @@
 #  configure_default_options
 #			Set to an initializer for configure_default_options
 #			in configargs.h, based on --with-cpu et cetera.
+#
+#  use_initfini_array	If set to yes, .init_array/.fini_array sections
+#			will be used if they work.
 
 # The following variables are used in each case-construct to build up the
 # outgoing variables:
@@ -219,6 +222,7 @@ default_gnu_indirect_function=no
 target_gtfiles=
 need_64bit_hwint=
 need_64bit_isa=
+use_initfini_array=
 
 # Don't carry these over build->host->target.  Please.
 xm_file=
@@ -2698,6 +2702,7 @@ esac
 case ${target} in
 i[34567]86-*-linux* | x86_64-*-linux*)
 	tmake_file="${tmake_file} i386/t-pmm_malloc i386/t-i386"
+	use_initfini_array=yes
 	;;
 i[34567]86-*-* | x86_64-*-*)
 	tmake_file="${tmake_file} i386/t-gmm_malloc i386/t-i386"
@@ -3050,6 +3055,16 @@ if test x$with_schedule = x; then
 	esac
 fi
 
+# Support --enable-initfini-array.  Use initfini-array.h only if
+# use_initfini_array is also set to yes.  Some platforms don't need it
+# even if enable_initfini_array is yes.
+if test x$enable_initfini_array$use_initfini_array = xyesyes; then
+  tm_file="${tm_file} initfini-array.h"
+  tmake_file="${tmake_file} t-initfini-array"
+  extra_objs="$extra_objs initfini-array.o"
+  target_gtfiles="$target_gtfiles \$(srcdir)/config/initfini-array.c"
+fi
+
 # Validate and mark as valid any --with options supported
 # by this target.  In order to use a particular --with option
 # you must list it in supported_defaults; validating the value
diff --git a/gcc/config/initfini-array.c b/gcc/config/initfini-array.c
new file mode 100644
index 0000000..d5fd40f
--- /dev/null
+++ b/gcc/config/initfini-array.c
@@ -0,0 +1,79 @@
+/* Definitions for ELF systems with .init_array/.fini_array section
+   Copyright (C) 2010
+   Free Software Foundation, Inc.
+
+This file is part of GCC.
+
+GCC 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 3, or (at your option) any later
+version.
+
+GCC 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 GCC; see the file COPYING3.  If not see
+<http://www.gnu.org/licenses/>.  */
+
+#include "config.h"
+#include "system.h"
+#include "coretypes.h"
+#include "target.h"
+#include "output.h"
+#include "tree.h"
+#include "ggc.h"
+
+static GTY(()) section *init_array_section;
+static GTY(()) section *fini_array_section;
+
+void
+elf_initfini_array_init_sections (void)
+{
+  init_array_section = get_unnamed_section (0, output_section_asm_op,
+					    "\t.section\t.init_array");
+  fini_array_section = get_unnamed_section (0, output_section_asm_op,
+					    "\t.section\t.fini_array");
+}
+
+static section *
+get_elf_initfini_array_priority_section (int priority,
+					 bool constructor_p)
+{
+  section *sec;
+  if (priority != DEFAULT_INIT_PRIORITY)
+    {
+      char buf[18];
+      sprintf (buf, "%s.%.5u", 
+	       constructor_p ? ".init_array" : ".fini_array",
+	       priority);
+      sec = get_section (buf, SECTION_WRITE, NULL_TREE);
+    }
+  else
+    sec = constructor_p ? init_array_section : fini_array_section;
+  return sec;
+}
+
+/* Use .init_array section for constructors. */
+
+void
+elf_init_array_asm_out_constructor (rtx symbol, int priority)
+{
+  section *sec = get_elf_initfini_array_priority_section (priority,
+							  true);
+  assemble_addr_to_section (symbol, sec);
+}
+
+/* Use .fini_array section for destructors. */
+
+void
+elf_fini_array_asm_out_destructor (rtx symbol, int priority)
+{
+  section *sec = get_elf_initfini_array_priority_section (priority,
+							  false);
+  assemble_addr_to_section (symbol, sec);
+}
+
+#include "gt-initfini-array.h"
diff --git a/gcc/config/initfini-array.h b/gcc/config/initfini-array.h
new file mode 100644
index 0000000..115996e
--- /dev/null
+++ b/gcc/config/initfini-array.h
@@ -0,0 +1,33 @@
+/* Definitions for ELF systems with .init_array/.fini_array section
+   support.
+   Copyright (C) 2010
+   Free Software Foundation, Inc.
+
+   This file is part of GCC.
+
+   GCC 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 3, or (at your
+   option) any later version.
+
+   GCC 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 GCC; see the file COPYING3.  If not see
+   <http://www.gnu.org/licenses/>.  */
+
+#ifndef TARGET_ASM_INIT_SECTIONS
+#define TARGET_ASM_INIT_SECTIONS elf_initfini_array_init_sections
+#endif
+extern void elf_initfini_array_init_sections (void);
+
+/* Use .init_array/.fini_array section for constructors and destructors. */
+#undef TARGET_ASM_CONSTRUCTOR
+#define TARGET_ASM_CONSTRUCTOR elf_init_array_asm_out_constructor
+#undef TARGET_ASM_DESTRUCTOR
+#define TARGET_ASM_DESTRUCTOR elf_fini_array_asm_out_destructor
+extern void elf_init_array_asm_out_constructor (rtx, int);
+extern void elf_fini_array_asm_out_destructor (rtx, int);
diff --git a/gcc/config/t-initfini-array b/gcc/config/t-initfini-array
new file mode 100644
index 0000000..3dcb25d
--- /dev/null
+++ b/gcc/config/t-initfini-array
@@ -0,0 +1,23 @@
+# Copyright (C) 2010
+# 2009 Free Software Foundation, Inc.
+#
+# This file is part of GCC.
+#
+# GCC 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 3, or (at your option)
+# any later version.
+#
+# GCC 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 GCC; see the file COPYING3.  If not see
+# <http://www.gnu.org/licenses/>.
+
+initfini-array.o: $(srcdir)/config/initfini-array.c gt-initfini-array.h \
+	$(CONFIG_H) $(SYSTEM_H) coretypes.h $(TARGET_H) output.h \
+	$(TREE_H) $(GGC_H)
+	$(COMPILER) -c $(ALL_COMPILERFLAGS) $(ALL_CPPFLAGS) $(INCLUDES) $<

^ permalink raw reply	[flat|nested] 10+ messages in thread

* Re: PATCH: PR target/46770: Use .init_array/.fini_array sections
  2010-12-07 16:16 H.J. Lu
@ 2010-12-07 16:36 ` Joseph S. Myers
  2010-12-07 17:01   ` H.J. Lu
  0 siblings, 1 reply; 10+ messages in thread
From: Joseph S. Myers @ 2010-12-07 16:36 UTC (permalink / raw)
  To: H.J. Lu; +Cc: gcc-patches, Uros Bizjak

On Tue, 7 Dec 2010, H.J. Lu wrote:

> @@ -2698,6 +2698,7 @@ esac
>  case ${target} in
>  i[34567]86-*-linux* | x86_64-*-linux*)
>  	tmake_file="${tmake_file} i386/t-pmm_malloc i386/t-i386"
> +	use_initfini_array=yes

Please update the comment at the top of config.gcc listing the variables 
it sets, and put a default (empty or "no") setting of this variable along 
with the other defaults as well.

> +#include "tree.h"

What is tree.h needed for here?

> +	$(TREE_H) $(GCC_H)

I think you mean $(GGC_H) not $(GCC_H) (which is gcc.h, the header for the 
driver).

-- 
Joseph S. Myers
joseph@codesourcery.com

^ permalink raw reply	[flat|nested] 10+ messages in thread

* PATCH: PR target/46770: Use .init_array/.fini_array sections
@ 2010-12-07 16:16 H.J. Lu
  2010-12-07 16:36 ` Joseph S. Myers
  0 siblings, 1 reply; 10+ messages in thread
From: H.J. Lu @ 2010-12-07 16:16 UTC (permalink / raw)
  To: gcc-patches; +Cc: Uros Bizjak

Hi,

This patch uses .init_array/.fini_array sections if they work and
are needed. Some platforms use .init_array/.fini_array sections by
default.  So checking --enable-initfini-array alone isn't sufficient.
I added use_initfini_array.  Each platform should set it if
.init_array/.fini_array sections should be used.

This patch only changes Linux/x86.  OK for trunk if there are no
regressions on Linux/x86-64?

Thanks.


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

	PR target/46770
	* config.gcc: Use initfini-array.o if supported.

	* config/initfini-array.c: New.
	* config/initfini-array.h: Likewise.
	* config/t-initfini-array: Likewise.

diff --git a/gcc/config.gcc b/gcc/config.gcc
index dfbf2c5..12d2aae 100644
--- a/gcc/config.gcc
+++ b/gcc/config.gcc
@@ -2698,6 +2698,7 @@ esac
 case ${target} in
 i[34567]86-*-linux* | x86_64-*-linux*)
 	tmake_file="${tmake_file} i386/t-pmm_malloc i386/t-i386"
+	use_initfini_array=yes
 	;;
 i[34567]86-*-* | x86_64-*-*)
 	tmake_file="${tmake_file} i386/t-gmm_malloc i386/t-i386"
@@ -3050,6 +3051,16 @@ if test x$with_schedule = x; then
 	esac
 fi
 
+# Support --enable-initfini-array.  Use initfini-array.h only if
+# use_initfini_array is also set to yes.  Some platforms don't need it
+# even if enable_initfini_array is yes.
+if test x$enable_initfini_array$use_initfini_array = xyesyes; then
+  tm_file="${tm_file} initfini-array.h"
+  tmake_file="${tmake_file} t-initfini-array"
+  extra_objs="$extra_objs initfini-array.o"
+  target_gtfiles="$target_gtfiles \$(srcdir)/config/initfini-array.c"
+fi
+
 # Validate and mark as valid any --with options supported
 # by this target.  In order to use a particular --with option
 # you must list it in supported_defaults; validating the value
diff --git a/gcc/config/initfini-array.c b/gcc/config/initfini-array.c
new file mode 100644
index 0000000..d5fd40f
--- /dev/null
+++ b/gcc/config/initfini-array.c
@@ -0,0 +1,79 @@
+/* Definitions for ELF systems with .init_array/.fini_array section
+   Copyright (C) 2010
+   Free Software Foundation, Inc.
+
+This file is part of GCC.
+
+GCC 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 3, or (at your option) any later
+version.
+
+GCC 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 GCC; see the file COPYING3.  If not see
+<http://www.gnu.org/licenses/>.  */
+
+#include "config.h"
+#include "system.h"
+#include "coretypes.h"
+#include "target.h"
+#include "output.h"
+#include "tree.h"
+#include "ggc.h"
+
+static GTY(()) section *init_array_section;
+static GTY(()) section *fini_array_section;
+
+void
+elf_initfini_array_init_sections (void)
+{
+  init_array_section = get_unnamed_section (0, output_section_asm_op,
+					    "\t.section\t.init_array");
+  fini_array_section = get_unnamed_section (0, output_section_asm_op,
+					    "\t.section\t.fini_array");
+}
+
+static section *
+get_elf_initfini_array_priority_section (int priority,
+					 bool constructor_p)
+{
+  section *sec;
+  if (priority != DEFAULT_INIT_PRIORITY)
+    {
+      char buf[18];
+      sprintf (buf, "%s.%.5u", 
+	       constructor_p ? ".init_array" : ".fini_array",
+	       priority);
+      sec = get_section (buf, SECTION_WRITE, NULL_TREE);
+    }
+  else
+    sec = constructor_p ? init_array_section : fini_array_section;
+  return sec;
+}
+
+/* Use .init_array section for constructors. */
+
+void
+elf_init_array_asm_out_constructor (rtx symbol, int priority)
+{
+  section *sec = get_elf_initfini_array_priority_section (priority,
+							  true);
+  assemble_addr_to_section (symbol, sec);
+}
+
+/* Use .fini_array section for destructors. */
+
+void
+elf_fini_array_asm_out_destructor (rtx symbol, int priority)
+{
+  section *sec = get_elf_initfini_array_priority_section (priority,
+							  false);
+  assemble_addr_to_section (symbol, sec);
+}
+
+#include "gt-initfini-array.h"
diff --git a/gcc/config/initfini-array.h b/gcc/config/initfini-array.h
new file mode 100644
index 0000000..115996e
--- /dev/null
+++ b/gcc/config/initfini-array.h
@@ -0,0 +1,33 @@
+/* Definitions for ELF systems with .init_array/.fini_array section
+   support.
+   Copyright (C) 2010
+   Free Software Foundation, Inc.
+
+   This file is part of GCC.
+
+   GCC 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 3, or (at your
+   option) any later version.
+
+   GCC 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 GCC; see the file COPYING3.  If not see
+   <http://www.gnu.org/licenses/>.  */
+
+#ifndef TARGET_ASM_INIT_SECTIONS
+#define TARGET_ASM_INIT_SECTIONS elf_initfini_array_init_sections
+#endif
+extern void elf_initfini_array_init_sections (void);
+
+/* Use .init_array/.fini_array section for constructors and destructors. */
+#undef TARGET_ASM_CONSTRUCTOR
+#define TARGET_ASM_CONSTRUCTOR elf_init_array_asm_out_constructor
+#undef TARGET_ASM_DESTRUCTOR
+#define TARGET_ASM_DESTRUCTOR elf_fini_array_asm_out_destructor
+extern void elf_init_array_asm_out_constructor (rtx, int);
+extern void elf_fini_array_asm_out_destructor (rtx, int);
diff --git a/gcc/config/t-initfini-array b/gcc/config/t-initfini-array
new file mode 100644
index 0000000..6987d76
--- /dev/null
+++ b/gcc/config/t-initfini-array
@@ -0,0 +1,23 @@
+# Copyright (C) 2010
+# 2009 Free Software Foundation, Inc.
+#
+# This file is part of GCC.
+#
+# GCC 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 3, or (at your option)
+# any later version.
+#
+# GCC 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 GCC; see the file COPYING3.  If not see
+# <http://www.gnu.org/licenses/>.
+
+initfini-array.o: $(srcdir)/config/initfini-array.c gt-initfini-array.h \
+	$(CONFIG_H) $(SYSTEM_H) coretypes.h $(TARGET_H) output.h \
+	$(TREE_H) $(GCC_H)
+	$(COMPILER) -c $(ALL_COMPILERFLAGS) $(ALL_CPPFLAGS) $(INCLUDES) $<

^ permalink raw reply	[flat|nested] 10+ messages in thread

end of thread, other threads:[~2011-03-14 19:29 UTC | newest]

Thread overview: 10+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2010-12-15  1:50 RFC: PR target/46770: Use .init_array/.fini_array sections H.J. Lu
2011-01-27  0:08 ` PATCH: " H.J. Lu
2011-01-27 11:09   ` Richard Guenther
2011-03-14 19:29     ` H.J. Lu
  -- strict thread matches above, loose matches on Subject: below --
2010-12-07 16:16 H.J. Lu
2010-12-07 16:36 ` Joseph S. Myers
2010-12-07 17:01   ` H.J. Lu
2010-12-09 19:00     ` H.J. Lu
2010-12-10  9:49       ` Richard Guenther
2010-12-10 12:43         ` H.J. Lu

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).