This is the mail archive of the binutils@sourceware.org mailing list for the binutils project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

gold patch committed: Put .ctors in .init_array


This patch to gold changes it to put .ctors in .init_array (and .dtors
in .fini_array) by default.  This is what GNU ld now does for most ELF
targets.  The resulting code is marginally more efficient.  It also
means that no crtbegin and crtend files are required.  Because it is
possible that not all operating systems support DT_INIT_ARRAY, I made
this optional, controlled by the new --ctors-in-init-array option.  The
new option defaults to true.  Committed to mainline.

Ian


2011-06-22  Ian Lance Taylor  <iant@google.com>

	PR gold/12910
	* options.h (class General_options): Add --ctors-in-init-array.
	* layout.cc (Layout::get_output_section): Treat SHT_INIT_ARRAY and
	friends as SHT_PROGBITS for merging sections.
	(Layout::layout): Remove special handling of .init_array and
	friends.  Don't sort if doing relocatable link.  Sort for .ctors
	and .dtors if ctors_in_init_array.
	(Layout::make_output_section): Force correct section types for
	.init_array and friends.  Don't sort if doing relocatable link,
	Don't sort .ctors and .dtors if ctors_in_init_array.
	(Layout::section_name_mapping): Remove .ctors. and .dtorso.
	(Layout::output_section_name): Add relobj parameter.  Change all
	callers.  Handle .ctors. and .dtors. in code rather than table.
	Handle .ctors and .dtors if ctors_in_init_array.
	(Layout::match_file_name): New function, moved from output.cc.
	* layout.h (class Layout): Update declarations.
	* output.cc: Include "layout.h".
	(Input_section_sort_entry::get_priority): New function.
	(Input_section_sort_entry::match_file_name): Just call
	Layout::match_file_name.
	(Output_section::Input_section_sort_init_fini_compare::operator()):
	Handle .ctors and .dtors.  Sort by explicit priority rather than
	by name.
	* configure.ac: Remove CONSTRUCTOR_PRIORITY test and conditional.
	* testsuite/initpri2.c: New test.
	* testsuite/Makefile.am: Don't test CONSTRUCTOR_PRIORITY.
	(check_PROGRAMS): Add initpri2.
	(initpri2_SOURCES, initpri2_DEPENDENCIES): New variables.
	(initpri2_LDFLAGS, initpri2_LDADD): New variables.
	* configure, testsuite/Makefile.in: Rebuild.


Index: layout.h
===================================================================
RCS file: /cvs/src/src/gold/layout.h,v
retrieving revision 1.92
diff -u -p -r1.92 layout.h
--- layout.h	17 Jun 2011 13:00:01 -0000	1.92
+++ layout.h	23 Jun 2011 00:32:32 -0000
@@ -645,6 +645,12 @@ class Layout
             || strncmp(name, ".stab", sizeof(".stab") - 1) == 0);
   }
 
+  // Return true if RELOBJ is an input file whose base name matches
+  // FILE_NAME.  The base name must have an extension of ".o", and
+  // must be exactly FILE_NAME.o or FILE_NAME, one character, ".o".
+  static bool
+  match_file_name(const Relobj* relobj, const char* file_name);
+
   // Check if a comdat group or .gnu.linkonce section with the given
   // NAME is selected for the link.  If there is already a section,
   // *KEPT_SECTION is set to point to the signature and the function
@@ -965,7 +971,7 @@ class Layout
   // name.  Set *PLEN to the length of the name.  *PLEN must be
   // initialized to the length of NAME.
   static const char*
-  output_section_name(const char* name, size_t* plen);
+  output_section_name(const Relobj*, const char* name, size_t* plen);
 
   // Return the number of allocated output sections.
   size_t
Index: layout.cc
===================================================================
RCS file: /cvs/src/src/gold/layout.cc,v
retrieving revision 1.204
diff -u -p -r1.204 layout.cc
--- layout.cc	19 Jun 2011 22:09:17 -0000	1.204
+++ layout.cc	23 Jun 2011 00:32:34 -0000
@@ -627,6 +627,18 @@ Layout::get_output_section(const char* n
 			   elfcpp::Elf_Word type, elfcpp::Elf_Xword flags,
 			   Output_section_order order, bool is_relro)
 {
+  elfcpp::Elf_Word lookup_type = type;
+
+  // For lookup purposes, treat INIT_ARRAY, FINI_ARRAY, and
+  // PREINIT_ARRAY like PROGBITS.  This ensures that we combine
+  // .init_array, .fini_array, and .preinit_array sections by name
+  // whatever their type in the input file.  We do this because the
+  // types are not always right in the input files.
+  if (lookup_type == elfcpp::SHT_INIT_ARRAY
+      || lookup_type == elfcpp::SHT_FINI_ARRAY
+      || lookup_type == elfcpp::SHT_PREINIT_ARRAY)
+    lookup_type = elfcpp::SHT_PROGBITS;
+
   elfcpp::Elf_Xword lookup_flags = flags;
 
   // Ignoring SHF_WRITE and SHF_EXECINSTR here means that we combine
@@ -635,7 +647,7 @@ Layout::get_output_section(const char* n
   // controlling this.
   lookup_flags &= ~(elfcpp::SHF_WRITE | elfcpp::SHF_EXECINSTR);
 
-  const Key key(name_key, std::make_pair(type, lookup_flags));
+  const Key key(name_key, std::make_pair(lookup_type, lookup_flags));
   const std::pair<Key, Output_section*> v(key, NULL);
   std::pair<Section_name_map::iterator, bool> ins(
     this->section_name_map_.insert(v));
@@ -652,20 +664,24 @@ Layout::get_output_section(const char* n
       // there should be an option to control this.
       Output_section* os = NULL;
 
-      if (type == elfcpp::SHT_PROGBITS)
+      if (lookup_type == elfcpp::SHT_PROGBITS)
 	{
           if (flags == 0)
             {
               Output_section* same_name = this->find_output_section(name);
               if (same_name != NULL
-                  && same_name->type() == elfcpp::SHT_PROGBITS
+                  && (same_name->type() == elfcpp::SHT_PROGBITS
+		      || same_name->type() == elfcpp::SHT_INIT_ARRAY
+		      || same_name->type() == elfcpp::SHT_FINI_ARRAY
+		      || same_name->type() == elfcpp::SHT_PREINIT_ARRAY)
                   && (same_name->flags() & elfcpp::SHF_TLS) == 0)
                 os = same_name;
             }
           else if ((flags & elfcpp::SHF_TLS) == 0)
             {
               elfcpp::Elf_Xword zero_flags = 0;
-              const Key zero_key(name_key, std::make_pair(type, zero_flags));
+              const Key zero_key(name_key, std::make_pair(lookup_type,
+							  zero_flags));
               Section_name_map::iterator p =
                   this->section_name_map_.find(zero_key);
               if (p != this->section_name_map_.end())
@@ -815,7 +831,7 @@ Layout::choose_output_section(const Relo
   if (is_input_section
       && !this->script_options_->saw_sections_clause()
       && !parameters->options().relocatable())
-    name = Layout::output_section_name(name, &len);
+    name = Layout::output_section_name(relobj, name, &len);
 
   Stringpool::Key name_key;
   name = this->namepool_.add_with_length(name, len, true, &name_key);
@@ -884,32 +900,11 @@ Layout::layout(Sized_relobj_file<size, b
   if (!this->include_section(object, name, shdr))
     return NULL;
 
-  Output_section* os;
-
-  // Sometimes .init_array*, .preinit_array* and .fini_array* do not have
-  // correct section types.  Force them here.
   elfcpp::Elf_Word sh_type = shdr.get_sh_type();
-  if (sh_type == elfcpp::SHT_PROGBITS)
-    {
-      static const char init_array_prefix[] = ".init_array";
-      static const char preinit_array_prefix[] = ".preinit_array";
-      static const char fini_array_prefix[] = ".fini_array";
-      static size_t init_array_prefix_size = sizeof(init_array_prefix) - 1;
-      static size_t preinit_array_prefix_size =
-	sizeof(preinit_array_prefix) - 1;
-      static size_t fini_array_prefix_size = sizeof(fini_array_prefix) - 1;
-
-      if (strncmp(name, init_array_prefix, init_array_prefix_size) == 0)
-	sh_type = elfcpp::SHT_INIT_ARRAY;
-      else if (strncmp(name, preinit_array_prefix, preinit_array_prefix_size)
-	       == 0)
-	sh_type = elfcpp::SHT_PREINIT_ARRAY;
-      else if (strncmp(name, fini_array_prefix, fini_array_prefix_size) == 0)
-	sh_type = elfcpp::SHT_FINI_ARRAY;
-    }
 
   // In a relocatable link a grouped section must not be combined with
   // any other sections.
+  Output_section* os;
   if (parameters->options().relocatable()
       && (shdr.get_sh_flags() & elfcpp::SHF_GROUP) != 0)
     {
@@ -929,12 +924,18 @@ Layout::layout(Sized_relobj_file<size, b
   // By default the GNU linker sorts input sections whose names match
   // .ctor.*, .dtor.*, .init_array.*, or .fini_array.*.  The sections
   // are sorted by name.  This is used to implement constructor
-  // priority ordering.  We are compatible.
+  // priority ordering.  We are compatible.  When we put .ctor
+  // sections in .init_array and .dtor sections in .fini_array, we
+  // must also sort plain .ctor and .dtor sections.
   if (!this->script_options_->saw_sections_clause()
+      && !parameters->options().relocatable()
       && (is_prefix_of(".ctors.", name)
 	  || is_prefix_of(".dtors.", name)
 	  || is_prefix_of(".init_array.", name)
-	  || is_prefix_of(".fini_array.", name)))
+	  || is_prefix_of(".fini_array.", name)
+	  || (parameters->options().ctors_in_init_array()
+	      && (strcmp(name, ".ctors") == 0
+		  || strcmp(name, ".dtors") == 0))))
     os->set_must_sort_attached_input_sections();
 
   // FIXME: Handle SHF_LINK_ORDER somewhere.
@@ -1256,6 +1257,18 @@ Layout::make_output_section(const char* 
     }
   else
     {
+      // Sometimes .init_array*, .preinit_array* and .fini_array* do
+      // not have correct section types.  Force them here.
+      if (type == elfcpp::SHT_PROGBITS)
+	{
+	  if (is_prefix_of(".init_array", name))
+	    type = elfcpp::SHT_INIT_ARRAY;
+	  else if (is_prefix_of(".preinit_array", name))
+	    type = elfcpp::SHT_PREINIT_ARRAY;
+	  else if (is_prefix_of(".fini_array", name))
+	    type = elfcpp::SHT_FINI_ARRAY;
+	}
+
       // FIXME: const_cast is ugly.
       Target* target = const_cast<Target*>(&parameters->target());
       os = target->make_output_section(name, type, flags);
@@ -1303,10 +1316,12 @@ Layout::make_output_section(const char* 
   // do the same.  We need to know that this might happen before we
   // attach any input sections.
   if (!this->script_options_->saw_sections_clause()
-      && (strcmp(name, ".ctors") == 0
-	  || strcmp(name, ".dtors") == 0
-	  || strcmp(name, ".init_array") == 0
-	  || strcmp(name, ".fini_array") == 0))
+      && !parameters->options().relocatable()
+      && (strcmp(name, ".init_array") == 0
+	  || strcmp(name, ".fini_array") == 0
+	  || (!parameters->options().ctors_in_init_array()
+	      && (strcmp(name, ".ctors") == 0
+		  || strcmp(name, ".dtors") == 0))))
     os->set_may_sort_attached_input_sections();
 
   // Check for .stab*str sections, as .stab* sections need to link to
@@ -4202,8 +4217,6 @@ Layout::set_dynamic_symbol_size(const Sy
 const Layout::Section_name_mapping Layout::section_name_mapping[] =
 {
   MAPPING_INIT(".text.", ".text"),
-  MAPPING_INIT(".ctors.", ".ctors"),
-  MAPPING_INIT(".dtors.", ".dtors"),
   MAPPING_INIT(".rodata.", ".rodata"),
   MAPPING_INIT(".data.rel.ro.local", ".data.rel.ro.local"),
   MAPPING_INIT(".data.rel.ro", ".data.rel.ro"),
@@ -4255,7 +4268,8 @@ const int Layout::section_name_mapping_c
 // length of NAME.
 
 const char*
-Layout::output_section_name(const char* name, size_t* plen)
+Layout::output_section_name(const Relobj* relobj, const char* name,
+			    size_t* plen)
 {
   // gcc 4.3 generates the following sorts of section names when it
   // needs a section name specific to a function:
@@ -4302,9 +4316,62 @@ Layout::output_section_name(const char* 
 	}
     }
 
+  // As an additional complication, .ctors sections are output in
+  // either .ctors or .init_array sections, and .dtors sections are
+  // output in either .dtors or .fini_array sections.
+  if (is_prefix_of(".ctors.", name) || is_prefix_of(".dtors.", name))
+    {
+      if (parameters->options().ctors_in_init_array())
+	{
+	  *plen = 11;
+	  return name[1] == 'c' ? ".init_array" : ".fini_array";
+	}
+      else
+	{
+	  *plen = 6;
+	  return name[1] == 'c' ? ".ctors" : ".dtors";
+	}
+    }
+  if (parameters->options().ctors_in_init_array()
+      && (strcmp(name, ".ctors") == 0 || strcmp(name, ".dtors") == 0))
+    {
+      // To make .init_array/.fini_array work with gcc we must exclude
+      // .ctors and .dtors sections from the crtbegin and crtend
+      // files.
+      if (relobj == NULL
+	  || (!Layout::match_file_name(relobj, "crtbegin")
+	      && !Layout::match_file_name(relobj, "crtend")))
+	{
+	  *plen = 11;
+	  return name[1] == 'c' ? ".init_array" : ".fini_array";
+	}
+    }
+
   return name;
 }
 
+// Return true if RELOBJ is an input file whose base name matches
+// FILE_NAME.  The base name must have an extension of ".o", and must
+// be exactly FILE_NAME.o or FILE_NAME, one character, ".o".  This is
+// to match crtbegin.o as well as crtbeginS.o without getting confused
+// by other possibilities.  Overall matching the file name this way is
+// a dreadful hack, but the GNU linker does it in order to better
+// support gcc, and we need to be compatible.
+
+bool
+Layout::match_file_name(const Relobj* relobj, const char* match)
+{
+  const std::string& file_name(relobj->name());
+  const char* base_name = lbasename(file_name.c_str());
+  size_t match_len = strlen(match);
+  if (strncmp(base_name, match, match_len) != 0)
+    return false;
+  size_t base_len = strlen(base_name);
+  if (base_len != match_len + 2 && base_len != match_len + 3)
+    return false;
+  return memcmp(base_name + base_len - 2, ".o", 2) == 0;
+}
+
 // Check if a comdat group or .gnu.linkonce section with the given
 // NAME is selected for the link.  If there is already a section,
 // *KEPT_SECTION is set to point to the existing section and the
Index: output.cc
===================================================================
RCS file: /cvs/src/src/gold/output.cc,v
retrieving revision 1.151
diff -u -p -r1.151 output.cc
--- output.cc	8 Jun 2011 04:43:28 -0000	1.151
+++ output.cc	23 Jun 2011 00:32:37 -0000
@@ -42,6 +42,7 @@
 #include "reloc.h"
 #include "merge.h"
 #include "descriptors.h"
+#include "layout.h"
 #include "output.h"
 
 // For systems without mmap support.
@@ -3017,7 +3018,7 @@ Output_section::do_set_tls_offset(uint64
 // priority ordering implemented by the GNU linker, in which the
 // priority becomes part of the section name and the sections are
 // sorted by name.  We only do this for an output section if we see an
-// attached input section matching ".ctor.*", ".dtor.*",
+// attached input section matching ".ctors.*", ".dtors.*",
 // ".init_array.*" or ".fini_array.*".
 
 class Output_section::Input_section_sort_entry
@@ -3092,6 +3093,34 @@ class Output_section::Input_section_sort
     return this->section_name_.find('.', 1) != std::string::npos;
   }
 
+  // Return the priority.  Believe it or not, gcc encodes the priority
+  // differently for .ctors/.dtors and .init_array/.fini_array
+  // sections.
+  unsigned int
+  get_priority() const
+  {
+    gold_assert(this->section_has_name_);
+    bool is_ctors;
+    if (is_prefix_of(".ctors.", this->section_name_.c_str())
+	|| is_prefix_of(".dtors.", this->section_name_.c_str()))
+      is_ctors = true;
+    else if (is_prefix_of(".init_array.", this->section_name_.c_str())
+	     || is_prefix_of(".fini_array.", this->section_name_.c_str()))
+      is_ctors = false;
+    else
+      return 0;
+    char* end;
+    unsigned long prio = strtoul((this->section_name_.c_str()
+				  + (is_ctors ? 7 : 12)),
+				 &end, 10);
+    if (*end != '\0')
+      return 0;
+    else if (is_ctors)
+      return 65535 - prio;
+    else
+      return prio;
+  }
+
   // Return true if this an input file whose base name matches
   // FILE_NAME.  The base name must have an extension of ".o", and
   // must be exactly FILE_NAME.o or FILE_NAME, one character, ".o".
@@ -3100,18 +3129,8 @@ class Output_section::Input_section_sort
   // file name this way is a dreadful hack, but the GNU linker does it
   // in order to better support gcc, and we need to be compatible.
   bool
-  match_file_name(const char* match_file_name) const
-  {
-    const std::string& file_name(this->input_section_.relobj()->name());
-    const char* base_name = lbasename(file_name.c_str());
-    size_t match_len = strlen(match_file_name);
-    if (strncmp(base_name, match_file_name, match_len) != 0)
-      return false;
-    size_t base_len = strlen(base_name);
-    if (base_len != match_len + 2 && base_len != match_len + 3)
-      return false;
-    return memcmp(base_name + base_len - 2, ".o", 2) == 0;
-  }
+  match_file_name(const char* file_name) const
+  { return Layout::match_file_name(this->input_section_.relobj(), file_name); }
 
   // Returns 1 if THIS should appear before S in section order, -1 if S
   // appears before THIS and 0 if they are not comparable.
@@ -3233,6 +3252,28 @@ Output_section::Input_section_sort_init_
   if (!s1_has_priority && s2_has_priority)
     return false;
 
+  // .ctors and .dtors sections without priority come after
+  // .init_array and .fini_array sections without priority.
+  if (!s1_has_priority
+      && (s1.section_name() == ".ctors" || s1.section_name() == ".dtors")
+      && s1.section_name() != s2.section_name())
+    return false;
+  if (!s2_has_priority
+      && (s2.section_name() == ".ctors" || s2.section_name() == ".dtors")
+      && s2.section_name() != s1.section_name())
+    return true;
+
+  // Sort by priority if we can.
+  if (s1_has_priority)
+    {
+      unsigned int s1_prio = s1.get_priority();
+      unsigned int s2_prio = s2.get_priority();
+      if (s1_prio < s2_prio)
+	return true;
+      else if (s1_prio > s2_prio)
+	return false;
+    }
+
   // Check if a section order exists for these sections through a section
   // ordering file.  If sequence_num is 0, an order does not exist.
   int sequence_num = s1.compare_section_ordering(s2);
Index: options.h
===================================================================
RCS file: /cvs/src/src/gold/options.h,v
retrieving revision 1.159
diff -u -p -r1.159 options.h
--- options.h	24 May 2011 23:31:07 -0000	1.159
+++ options.h	23 Jun 2011 00:32:40 -0000
@@ -1,6 +1,6 @@
 // options.h -- handle command line options for gold  -*- C++ -*-
 
-// Copyright 2006, 2007, 2008, 2009, 2010 Free Software Foundation, Inc.
+// Copyright 2006, 2007, 2008, 2009, 2010, 2011 Free Software Foundation, Inc.
 // Written by Ian Lance Taylor <iant@google.com>.
 
 // This file is part of gold.
@@ -663,6 +663,10 @@ class General_options
 	      N_("Output cross reference table"),
 	      N_("Do not output cross reference table"));
 
+  DEFINE_bool(ctors_in_init_array, options::TWO_DASHES, '\0', true,
+	      N_("Use DT_INIT_ARRAY for all constructors (default)"),
+	      N_("Handle constructors as directed by compiler"));
+
   DEFINE_bool(define_common, options::TWO_DASHES, 'd', false,
               N_("Define common symbols"),
               N_("Do not define common symbols"));
Index: configure.ac
===================================================================
RCS file: /cvs/src/src/gold/configure.ac,v
retrieving revision 1.62
diff -u -p -r1.62 configure.ac
--- configure.ac	12 Apr 2011 18:06:16 -0000	1.62
+++ configure.ac	23 Jun 2011 00:32:40 -0000
@@ -346,14 +346,6 @@ error
 
 AM_CONDITIONAL(TLS_DESCRIPTORS, test "$gold_cv_lib_glibc29" = "yes")
 
-dnl Check whether the compiler supports constructor priorities in
-dnl attributes, which were added in gcc 4.3.
-AC_CACHE_CHECK([for constructor priorities], [gold_cv_c_conprio],
-[AC_COMPILE_IFELSE([void f() __attribute__ ((constructor (1)));],
-[gold_cv_c_conprio=yes], [gold_cv_c_conprio=no])])
-
-AM_CONDITIONAL(CONSTRUCTOR_PRIORITY, test "$gold_cv_c_conprio" = "yes")
-
 dnl Test for the -frandom-seed option.
 AC_CACHE_CHECK([for -frandom-seed support], [gold_cv_c_random_seed],
 [save_CFLAGS="$CFLAGS"
Index: testsuite/Makefile.am
===================================================================
RCS file: /cvs/src/src/gold/testsuite/Makefile.am,v
retrieving revision 1.163
diff -u -p -r1.163 Makefile.am
--- testsuite/Makefile.am	8 Jun 2011 04:24:59 -0000	1.163
+++ testsuite/Makefile.am	23 Jun 2011 00:32:57 -0000
@@ -828,16 +828,17 @@ many_sections_r_test.o: many_sections_te
 many_sections_r_test: many_sections_r_test.o gcctestdir/ld
 	$(CXXLINK) -Bgcctestdir/ many_sections_r_test.o $(LIBS)
 
-if CONSTRUCTOR_PRIORITY
-
 check_PROGRAMS += initpri1
 initpri1_SOURCES = initpri1.c
 initpri1_DEPENDENCIES = gcctestdir/ld
 initpri1_LDFLAGS = -Bgcctestdir/
 initpri1_LDADD =
 
-endif
-
+check_PROGRAMS += initpri2
+initpri2_SOURCES = initpri2.c
+initpri2_DEPENDENCIES = gcctestdir/ld
+initpri2_LDFLAGS = -Bgcctestdir/
+initpri2_LDADD =
 
 # Test --detect-odr-violations
 check_SCRIPTS += debug_msg.sh
Index: testsuite/initpri2.c
===================================================================
RCS file: testsuite/initpri2.c
diff -N testsuite/initpri2.c
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ testsuite/initpri2.c	23 Jun 2011 00:32:59 -0000
@@ -0,0 +1,118 @@
+/* initpri2.c -- test mixing init_array and ctor priorities.
+
+   Copyright 2011 Free Software Foundation, Inc.
+   Copied from the gcc configury, where the test was contributed by
+   H.J. Lu <hongjiu.lu@intel.com>.
+
+   This file is part of gold.
+
+   This program is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 3 of the License, or
+   (at your option) any later version.
+
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program; if not, write to the Free Software
+   Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston,
+   MA 02110-1301, USA.  */
+
+/* This tests that the linker correctly combines .ctor and .init_array
+   sections when both have priorities.  */
+
+#include <stdlib.h>
+
+static int count;
+
+static void
+init1005 (void)
+{
+  if (count != 0)
+    abort ();
+  count = 1005;
+}
+void (*const init_array1005[]) (void)
+  __attribute__ ((section (".init_array.01005"), aligned (sizeof (void *))))
+  = { init1005 };
+static void
+fini1005 (void)
+{
+  if (count != 1005)
+    abort ();
+}
+void (*const fini_array1005[]) (void)
+  __attribute__ ((section (".fini_array.01005"), aligned (sizeof (void *))))
+  = { fini1005 };
+
+static void
+ctor1007 (void)
+{
+  if (count != 1005)
+    abort ();
+  count = 1007;
+}
+void (*const ctors1007[]) (void)
+  __attribute__ ((section (".ctors.64528"), aligned (sizeof (void *))))
+  = { ctor1007 };
+static void
+dtor1007 (void)
+{
+  if (count != 1007)
+    abort ();
+  count = 1005;
+}
+void (*const dtors1007[]) (void)
+  __attribute__ ((section (".dtors.64528"), aligned (sizeof (void *))))
+  = { dtor1007 };
+
+static void
+init65530 (void)
+{
+  if (count != 1007)
+    abort ();
+  count = 65530;
+}
+void (*const init_array65530[]) (void)
+  __attribute__ ((section (".init_array.65530"), aligned (sizeof (void *))))
+  = { init65530 };
+static void
+fini65530 (void)
+{
+  if (count != 65530)
+    abort ();
+  count = 1007;
+}
+void (*const fini_array65530[]) (void)
+  __attribute__ ((section (".fini_array.65530"), aligned (sizeof (void *))))
+  = { fini65530 };
+
+static void
+ctor65535 (void)
+{
+  if (count != 65530)
+    abort ();
+  count = 65535;
+}
+void (*const ctors65535[]) (void)
+  __attribute__ ((section (".ctors"), aligned (sizeof (void *))))
+  = { ctor65535 };
+static void
+dtor65535 (void)
+{
+  if (count != 65535)
+    abort ();
+  count = 65530;
+}
+void (*const dtors65535[]) (void)
+  __attribute__ ((section (".dtors"), aligned (sizeof (void *))))
+  = { dtor65535 };
+
+int
+main (void)
+{
+  return 0;
+}

Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]