diff --git a/gcc/config.gcc b/gcc/config.gcc
index 4a16ff8..0eac43a 100644
--- a/gcc/config.gcc
+++ b/gcc/config.gcc
@@ -186,6 +186,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:
@@ -238,6 +241,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=
@@ -3053,6 +3057,14 @@ 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"
+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 6e2b799..02b713e 100644
--- a/gcc/config/arm/arm.c
+++ b/gcc/config/arm/arm.c
@@ -23023,6 +23023,7 @@ arm_asm_init_sections (void)
 {
   exception_section = get_unnamed_section (0, output_section_asm_op,
 					   "\t.handlerdata");
+  default_initfini_array_init_sections ();
 }
 #endif /* ARM_UNWIND_INFO */
 
diff --git a/gcc/config/avr/avr.c b/gcc/config/avr/avr.c
index 4951f56..bb72bba 100644
--- a/gcc/config/avr/avr.c
+++ b/gcc/config/avr/avr.c
@@ -5099,6 +5099,8 @@ avr_asm_init_sections (void)
   readonly_data_section->unnamed.callback = avr_output_data_section_asm_op;
   data_section->unnamed.callback = avr_output_data_section_asm_op;
   bss_section->unnamed.callback = avr_output_bss_section_asm_op;
+
+  default_initfini_array_init_sections ();
 }
 
 
diff --git a/gcc/config/ia64/ia64.c b/gcc/config/ia64/ia64.c
index fa3b93f..5b8ea01 100644
--- a/gcc/config/ia64/ia64.c
+++ b/gcc/config/ia64/ia64.c
@@ -9989,6 +9989,7 @@ ia64_asm_init_sections (void)
 {
   exception_section = get_unnamed_section (0, output_section_asm_op,
 					   "\t.handlerdata");
+  default_initfini_array_init_sections ();
 }
 
 /* Implement TARGET_DEBUG_UNWIND_INFO.  */
diff --git a/gcc/config/initfini-array.h b/gcc/config/initfini-array.h
new file mode 100644
index 0000000..914cf08
--- /dev/null
+++ b/gcc/config/initfini-array.h
@@ -0,0 +1,44 @@
+/* Definitions for ELF systems with .init_array/.fini_array section
+   support.
+   Copyright (C) 2011
+   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/>.  */
+
+#define USE_INITFINI_ARRAY
+
+#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 default_elf_initfini_array_init_sections
+#endif
+extern void default_elf_initfini_array_init_sections (void);
+
+/* Use .init_array/.fini_array section for constructors and destructors. */
+#undef TARGET_ASM_CONSTRUCTOR
+#define TARGET_ASM_CONSTRUCTOR default_elf_init_array_asm_out_constructor
+#undef TARGET_ASM_DESTRUCTOR
+#define TARGET_ASM_DESTRUCTOR default_elf_fini_array_asm_out_destructor
+extern void default_elf_init_array_asm_out_constructor (rtx, int);
+extern void default_elf_fini_array_asm_out_destructor (rtx, int);
diff --git a/gcc/config/mep/mep.c b/gcc/config/mep/mep.c
index c18e7b7..5a4d5a6 100644
--- a/gcc/config/mep/mep.c
+++ b/gcc/config/mep/mep.c
@@ -7336,6 +7336,7 @@ mep_asm_init_sections (void)
     = get_unnamed_section (SECTION_CODE, output_section_asm_op,
 			   "\t.section .ftext,\"ax\"\n\t.core");
 
+  default_initfini_array_init_sections ();
 }
 
 /* Initialize the GCC target structure.  */
diff --git a/gcc/config/microblaze/microblaze.c b/gcc/config/microblaze/microblaze.c
index 288b86f..e31296d 100644
--- a/gcc/config/microblaze/microblaze.c
+++ b/gcc/config/microblaze/microblaze.c
@@ -2753,6 +2753,7 @@ microblaze_elf_asm_init_sections (void)
   sdata2_section
     = get_unnamed_section (SECTION_WRITE, output_section_asm_op,
 			   SDATA2_SECTION_ASM_OP);
+  default_initfini_array_init_sections ();
 }
 
 /*  Generate assembler code for constant parts of a trampoline.  */
diff --git a/gcc/config/rs6000/rs6000.c b/gcc/config/rs6000/rs6000.c
index 20b3cb8..d81ff94 100644
--- a/gcc/config/rs6000/rs6000.c
+++ b/gcc/config/rs6000/rs6000.c
@@ -24766,6 +24766,8 @@ rs6000_elf_asm_init_sections (void)
   sdata2_section
     = get_unnamed_section (SECTION_WRITE, output_section_asm_op,
 			   SDATA2_SECTION_ASM_OP);
+
+  default_initfini_array_init_sections ();
 }
 
 /* Implement TARGET_SELECT_RTX_SECTION.  */
diff --git a/gcc/config/stormy16/stormy16.c b/gcc/config/stormy16/stormy16.c
index 910dc2e..835ba2b 100644
--- a/gcc/config/stormy16/stormy16.c
+++ b/gcc/config/stormy16/stormy16.c
@@ -1573,6 +1573,7 @@ xstormy16_asm_init_sections (void)
     = get_unnamed_section (SECTION_WRITE | SECTION_BSS,
 			   output_section_asm_op,
 			   "\t.section \".bss_below100\",\"aw\",@nobits");
+  default_initfini_array_init_sections ();
 }
 
 /* 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..3824ed4
--- /dev/null
+++ b/gcc/config/t-initfini-array
@@ -0,0 +1,23 @@
+# Copyright (C) 2011
+# 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 5074ebe..6666544 100644
--- a/gcc/config/v850/v850.c
+++ b/gcc/config/v850/v850.c
@@ -2900,6 +2900,8 @@ v850_asm_init_sections (void)
     = get_unnamed_section (SECTION_WRITE | SECTION_BSS,
 			   output_section_asm_op,
 			   "\t.section .zbss,\"aw\"");
+
+  default_initfini_array_init_sections ();
 }
 
 static section *
diff --git a/gcc/crtstuff.c b/gcc/crtstuff.c
index b65f490..010d472 100644
--- a/gcc/crtstuff.c
+++ b/gcc/crtstuff.c
@@ -1,7 +1,8 @@
 /* Specialized bits of code needed to support construction and
    destruction of file-scope objects in C++ code.
    Copyright (C) 1991, 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001
-   2002, 2003, 2004, 2005, 2006, 2007, 2009, 2010 Free Software Foundation, Inc.
+   2002, 2003, 2004, 2005, 2006, 2007, 2009, 2010, 2011
+   Free Software Foundation, Inc.
    Contributed by Ron Guilmette (rfg@monkeys.com).
 
 This file is part of GCC.
@@ -189,6 +190,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 USE_INITFINI_ARRAY
 /* 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 +223,7 @@ STATIC func_ptr __DTOR_LIST__[1]
   __attribute__((section(".dtors"), aligned(sizeof(func_ptr))))
   = { (func_ptr) (-1) };
 #endif /* __DTOR_LIST__ alternatives */
+#endif /* USE_INITFINI_ARRAY */
 
 #ifdef USE_EH_FRAME_REGISTRY
 /* Stick a label at the beginning of the frame unwind info so we can register
@@ -489,6 +494,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 USE_INITFINI_ARRAY
 /* 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 +542,7 @@ STATIC func_ptr __DTOR_END__[1]
   __attribute__((used, section(".dtors"), aligned(sizeof(func_ptr))))
   = { (func_ptr) 0 };
 #endif
+#endif /* USE_INITFINI_ARRAY */
 
 #ifdef EH_FRAME_SECTION_NAME
 /* Terminate the frame unwind info section with a 4byte 0 as a sentinel;
diff --git a/gcc/output.h b/gcc/output.h
index c668d35..92a7075 100644
--- a/gcc/output.h
+++ b/gcc/output.h
@@ -656,6 +656,8 @@ extern void default_elf_asm_output_external (FILE *file, tree,
 					     const char *);
 extern int maybe_assemble_visibility (tree);
 
+extern void default_initfini_array_init_sections (void);
+
 extern int default_address_cost (rtx, bool);
 
 /* Output stack usage information.  */
diff --git a/gcc/varasm.c b/gcc/varasm.c
index 88aea9b..f96863b 100644
--- a/gcc/varasm.c
+++ b/gcc/varasm.c
@@ -7350,4 +7350,62 @@ make_debug_expr_from_rtl (const_rtx exp)
   return dval;
 }
 
+static GTY(()) section *elf_init_array_section;
+static GTY(()) section *elf_fini_array_section;
+
+void
+default_elf_initfini_array_init_sections (void)
+{
+  elf_init_array_section = get_unnamed_section (0, output_section_asm_op,
+						"\t.section\t.init_array");
+  elf_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 ? elf_init_array_section : elf_fini_array_section;
+  return sec;
+}
+
+/* Use .init_array section for constructors. */
+
+void
+default_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
+default_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);
+}
+
+void
+default_initfini_array_init_sections (void)
+{
+#ifdef USE_INITFINI_ARRAY
+  default_elf_initfini_array_init_sections ();
+#endif
+}
+
 #include "gt-varasm.h"
