* layout.cc: Include "object.h".
authorIan Lance Taylor <ian@airs.com>
Sat, 25 Jun 2011 00:40:57 +0000 (00:40 +0000)
committerIan Lance Taylor <ian@airs.com>
Sat, 25 Jun 2011 00:40:57 +0000 (00:40 +0000)
(ctors_sections_in_init_array): New static variable.
(Layout::is_ctors_in_init_array): New function.
(Layout::layout): Add entry to ctors_sections_in_init_array if
appropriate.
* layout.h (class Layout): Declare is_ctors_in_init_array.
* reloc.cc (Sized_relobj_file::do_relocate): Call reverse_words if
is_ctors_reverse_view is set.
(Sized_relobj_file::write_sections): Add layout parameter.  Change
all callers.  Set is_ctors_reverse_view field of View_size.
(Sized_relobj_file::reverse_words): New function.
* object.h (Sized_relobj_file::View_size): Add
is_ctors_reverse_view field.
(class Sized_relobj_file): Update declarations.
* testsuite/initpri3.c: New test.
* testsuite/Makefile.am: (check_PROGRAMS): Add initpri3a and
initpri3b.
(initpri3a_SOURCES, initpri3a_DEPENDENCIES): New variables.
(initpri3a_LDFLAGS, initpri3a_LDADD): New variables.
(initpri3b_SOURCES, initpri3b_DEPENDENCIES): New variables.
(initpri3b_LDFLAGS, initpri3b_LDADD): New variables.
* testsuite/Makefile.in: Rebuild.

gold/ChangeLog
gold/layout.cc
gold/layout.h
gold/object.h
gold/reloc.cc
gold/testsuite/Makefile.am
gold/testsuite/Makefile.in
gold/testsuite/initpri3.c [new file with mode: 0644]

index fe06e41..ff39a18 100644 (file)
@@ -1,3 +1,28 @@
+2011-06-24  Ian Lance Taylor  <iant@google.com>
+
+       * layout.cc: Include "object.h".
+       (ctors_sections_in_init_array): New static variable.
+       (Layout::is_ctors_in_init_array): New function.
+       (Layout::layout): Add entry to ctors_sections_in_init_array if
+       appropriate.
+       * layout.h (class Layout): Declare is_ctors_in_init_array.
+       * reloc.cc (Sized_relobj_file::do_relocate): Call reverse_words if
+       is_ctors_reverse_view is set.
+       (Sized_relobj_file::write_sections): Add layout parameter.  Change
+       all callers.  Set is_ctors_reverse_view field of View_size.
+       (Sized_relobj_file::reverse_words): New function.
+       * object.h (Sized_relobj_file::View_size): Add
+       is_ctors_reverse_view field.
+       (class Sized_relobj_file): Update declarations.
+       * testsuite/initpri3.c: New test.
+       * testsuite/Makefile.am: (check_PROGRAMS): Add initpri3a and
+       initpri3b.
+       (initpri3a_SOURCES, initpri3a_DEPENDENCIES): New variables.
+       (initpri3a_LDFLAGS, initpri3a_LDADD): New variables.
+       (initpri3b_SOURCES, initpri3b_DEPENDENCIES): New variables.
+       (initpri3b_LDFLAGS, initpri3b_LDADD): New variables.
+       * testsuite/Makefile.in: Rebuild.
+
 2011-06-24  Cary Coutant  <ccoutant@google.com>
 
        * testsuite/Makefile.am: Add in-tree assembler to gcctestdir.
index 82964ce..bfb1a7e 100644 (file)
@@ -46,6 +46,7 @@
 #include "ehframe.h"
 #include "compressed_output.h"
 #include "reduced_debug_output.h"
+#include "object.h"
 #include "reloc.h"
 #include "descriptors.h"
 #include "plugin.h"
@@ -617,6 +618,30 @@ Layout::find_output_segment(elfcpp::PT type, elfcpp::Elf_Word set,
   return NULL;
 }
 
+// When we put a .ctors or .dtors section with more than one word into
+// a .init_array or .fini_array section, we need to reverse the words
+// in the .ctors/.dtors section.  This is because .init_array executes
+// constructors front to back, where .ctors executes them back to
+// front, and vice-versa for .fini_array/.dtors.  Although we do want
+// to remap .ctors/.dtors into .init_array/.fini_array because it can
+// be more efficient, we don't want to change the order in which
+// constructors/destructors are run.  This set just keeps track of
+// these sections which need to be reversed.  It is only changed by
+// Layout::layout.  It should be a private member of Layout, but that
+// would require layout.h to #include object.h to get the definition
+// of Section_id.
+static Unordered_set<Section_id, Section_id_hash> ctors_sections_in_init_array;
+
+// Return whether OBJECT/SHNDX is a .ctors/.dtors section mapped to a
+// .init_array/.fini_array section.
+
+bool
+Layout::is_ctors_in_init_array(Relobj* relobj, unsigned int shndx) const
+{
+  return (ctors_sections_in_init_array.find(Section_id(relobj, shndx))
+         != ctors_sections_in_init_array.end());
+}
+
 // Return the output section to use for section NAME with type TYPE
 // and section flags FLAGS.  NAME must be canonicalized in the string
 // pool, and NAME_KEY is the key.  ORDER is where this should appear
@@ -922,11 +947,11 @@ Layout::layout(Sized_relobj_file<size, big_endian>* object, unsigned int shndx,
     }
 
   // 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.  When we put .ctor
-  // sections in .init_array and .dtor sections in .fini_array, we
-  // must also sort plain .ctor and .dtor sections.
+  // .ctors.*, .dtors.*, .init_array.*, or .fini_array.*.  The
+  // sections are sorted by name.  This is used to implement
+  // constructor 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)
@@ -938,6 +963,22 @@ Layout::layout(Sized_relobj_file<size, big_endian>* object, unsigned int shndx,
                  || strcmp(name, ".dtors") == 0))))
     os->set_must_sort_attached_input_sections();
 
+  // If this is a .ctors or .ctors.* section being mapped to a
+  // .init_array section, or a .dtors or .dtors.* section being mapped
+  // to a .fini_array section, we will need to reverse the words if
+  // there is more than one.  Record this section for later.  See
+  // ctors_sections_in_init_array above.
+  if (!this->script_options_->saw_sections_clause()
+      && !parameters->options().relocatable()
+      && shdr.get_sh_size() > size / 8
+      && (((strcmp(name, ".ctors") == 0
+           || is_prefix_of(".ctors.", name))
+          && strcmp(os->name(), ".init_array") == 0)
+         || ((strcmp(name, ".dtors") == 0
+              || is_prefix_of(".dtors.", name))
+             && strcmp(os->name(), ".fini_array") == 0)))
+    ctors_sections_in_init_array.insert(Section_id(object, shndx));
+
   // FIXME: Handle SHF_LINK_ORDER somewhere.
 
   elfcpp::Elf_Xword orig_flags = os->flags();
index 3eee820..0f6840e 100644 (file)
@@ -651,6 +651,12 @@ class Layout
   static bool
   match_file_name(const Relobj* relobj, const char* file_name);
 
+  // Return whether section SHNDX in RELOBJ is a .ctors/.dtors section
+  // with more than one word being mapped to a .init_array/.fini_array
+  // section.
+  bool
+  is_ctors_in_init_array(Relobj* relobj, unsigned int shndx) const;
+
   // 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
index 1031833..8735f9e 100644 (file)
@@ -2220,6 +2220,7 @@ class Sized_relobj_file : public Sized_relobj<size, big_endian>
     section_size_type view_size;
     bool is_input_output_view;
     bool is_postprocessing_view;
+    bool is_ctors_reverse_view;
   };
 
   typedef std::vector<View_size> Views;
@@ -2311,7 +2312,8 @@ class Sized_relobj_file : public Sized_relobj<size, big_endian>
   // Write section data to the output file.  Record the views and
   // sizes in VIEWS for use when relocating.
   void
-  write_sections(const unsigned char* pshdrs, Output_file*, Views*);
+  write_sections(const Layout*, const unsigned char* pshdrs, Output_file*,
+                Views*);
 
   // Relocate the sections in the output file.
   void
@@ -2320,6 +2322,11 @@ class Sized_relobj_file : public Sized_relobj<size, big_endian>
                    Views* pviews)
   { this->do_relocate_sections(symtab, layout, pshdrs, of, pviews); }
 
+  // Reverse the words in a section.  Used for .ctors sections mapped
+  // to .init_array sections.
+  void
+  reverse_words(unsigned char*, section_size_type);
+
   // Scan the input relocations for --emit-relocs.
   void
   emit_relocs_scan(Symbol_table*, Layout*, const unsigned char* plocal_syms,
index dacab35..4c28b03 100644 (file)
@@ -659,7 +659,7 @@ Sized_relobj_file<size, big_endian>::do_relocate(const Symbol_table* symtab,
   // section data to the output file.  The second one applies
   // relocations.
 
-  this->write_sections(pshdrs, of, &views);
+  this->write_sections(layout, pshdrs, of, &views);
 
   // To speed up relocations, we set up hash tables for fast lookup of
   // input offsets to output addresses.
@@ -678,6 +678,8 @@ Sized_relobj_file<size, big_endian>::do_relocate(const Symbol_table* symtab,
     {
       if (views[i].view != NULL)
        {
+         if (views[i].is_ctors_reverse_view)
+           this->reverse_words(views[i].view, views[i].view_size);
          if (!views[i].is_postprocessing_view)
            {
              if (views[i].is_input_output_view)
@@ -712,7 +714,8 @@ struct Read_multiple_compare
 
 template<int size, bool big_endian>
 void
-Sized_relobj_file<size, big_endian>::write_sections(const unsigned char* pshdrs,
+Sized_relobj_file<size, big_endian>::write_sections(const Layout* layout,
+                                                   const unsigned char* pshdrs,
                                                    Output_file* of,
                                                    Views* pviews)
 {
@@ -761,6 +764,7 @@ Sized_relobj_file<size, big_endian>::write_sections(const unsigned char* pshdrs,
          pvs->address = posd->address();
          pvs->is_input_output_view = false;
          pvs->is_postprocessing_view = false;
+         pvs->is_ctors_reverse_view = false;
 
          continue;
        }
@@ -875,6 +879,12 @@ Sized_relobj_file<size, big_endian>::write_sections(const unsigned char* pshdrs,
       pvs->view_size = view_size;
       pvs->is_input_output_view = output_offset == invalid_address;
       pvs->is_postprocessing_view = os->requires_postprocessing();
+      pvs->is_ctors_reverse_view =
+       (!parameters->options().relocatable()
+        && view_size > size / 8
+        && (strcmp(os->name(), ".init_array") == 0
+            || strcmp(os->name(), ".fini_array") == 0)
+        && layout->is_ctors_in_init_array(this, i));
     }
 
   // Actually read the data.
@@ -1483,6 +1493,26 @@ Sized_relobj_file<size, big_endian>::find_functions(
     }
 }
 
+// Reverse the words in a section.  Used for .ctors sections mapped to
+// .init_array sections.  See ctors_sections_in_init_array in
+// layout.cc.
+
+template<int size, bool big_endian>
+void
+Sized_relobj_file<size, big_endian>::reverse_words(unsigned char* view,
+                                                  section_size_type view_size)
+{
+  typedef typename elfcpp::Swap<size, big_endian>::Valtype Valtype;
+  Valtype* vview = reinterpret_cast<Valtype*>(view);
+  section_size_type vview_size = view_size / (size / 8);
+  for (section_size_type i = 0; i < vview_size / 2; ++i)
+    {
+      Valtype tmp = vview[i];
+      vview[i] = vview[vview_size - 1 - i];
+      vview[vview_size - 1 - i] = tmp;
+    }
+}
+
 // Class Merged_symbol_value.
 
 template<int size>
index ca486cf..d075cdc 100644 (file)
@@ -846,6 +846,18 @@ initpri2_DEPENDENCIES = gcctestdir/ld
 initpri2_LDFLAGS = -Bgcctestdir/
 initpri2_LDADD =
 
+check_PROGRAMS += initpri3a
+initpri3a_SOURCES = initpri3.c
+initpri3a_DEPENDENCIES = gcctestdir/ld
+initpri3a_LDFLAGS = -Bgcctestdir/
+initpri3a_LDADD =
+
+check_PROGRAMS += initpri3b
+initpri3b_SOURCES = initpri3.c
+initpri3b_DEPENDENCIES = gcctestdir/ld
+initpri3b_LDFLAGS = -Bgcctestdir/ -Wl,--no-ctors-in-init-array
+initpri3b_LDADD =
+
 # Test --detect-odr-violations
 check_SCRIPTS += debug_msg.sh
 
index 20171bf..10bce4e 100644 (file)
@@ -181,7 +181,8 @@ check_PROGRAMS = $(am__EXEEXT_1) $(am__EXEEXT_2) $(am__EXEEXT_3) \
 # Test -o when emitting to a special file (such as something in /dev).
 @GCC_TRUE@@NATIVE_LINKER_TRUE@am__append_16 = many_sections_test \
 @GCC_TRUE@@NATIVE_LINKER_TRUE@ many_sections_r_test initpri1 \
-@GCC_TRUE@@NATIVE_LINKER_TRUE@ initpri2 flagstest_o_specialfile
+@GCC_TRUE@@NATIVE_LINKER_TRUE@ initpri2 initpri3a initpri3b \
+@GCC_TRUE@@NATIVE_LINKER_TRUE@ flagstest_o_specialfile
 @GCC_FALSE@many_sections_test_DEPENDENCIES =
 @NATIVE_LINKER_FALSE@many_sections_test_DEPENDENCIES =
 @GCC_TRUE@@NATIVE_LINKER_TRUE@am__append_17 = many_sections_define.h \
@@ -193,6 +194,10 @@ check_PROGRAMS = $(am__EXEEXT_1) $(am__EXEEXT_2) $(am__EXEEXT_3) \
 @NATIVE_LINKER_FALSE@initpri1_DEPENDENCIES =
 @GCC_FALSE@initpri2_DEPENDENCIES =
 @NATIVE_LINKER_FALSE@initpri2_DEPENDENCIES =
+@GCC_FALSE@initpri3a_DEPENDENCIES =
+@NATIVE_LINKER_FALSE@initpri3a_DEPENDENCIES =
+@GCC_FALSE@initpri3b_DEPENDENCIES =
+@NATIVE_LINKER_FALSE@initpri3b_DEPENDENCIES =
 
 # Check that --detect-odr-violations works with compressed debug sections.
 @GCC_TRUE@@HAVE_ZLIB_TRUE@@NATIVE_LINKER_TRUE@am__append_19 = debug_msg_cdebug.err
@@ -618,6 +623,8 @@ libgoldtest_a_OBJECTS = $(am_libgoldtest_a_OBJECTS)
 @GCC_TRUE@@NATIVE_LINKER_TRUE@ many_sections_r_test$(EXEEXT) \
 @GCC_TRUE@@NATIVE_LINKER_TRUE@ initpri1$(EXEEXT) \
 @GCC_TRUE@@NATIVE_LINKER_TRUE@ initpri2$(EXEEXT) \
+@GCC_TRUE@@NATIVE_LINKER_TRUE@ initpri3a$(EXEEXT) \
+@GCC_TRUE@@NATIVE_LINKER_TRUE@ initpri3b$(EXEEXT) \
 @GCC_TRUE@@NATIVE_LINKER_TRUE@ flagstest_o_specialfile$(EXEEXT)
 @GCC_TRUE@@HAVE_ZLIB_TRUE@@NATIVE_LINKER_TRUE@am__EXEEXT_13 = flagstest_compress_debug_sections$(EXEEXT) \
 @GCC_TRUE@@HAVE_ZLIB_TRUE@@NATIVE_LINKER_TRUE@ flagstest_o_specialfile_and_compress_debug_sections$(EXEEXT)
@@ -1058,6 +1065,16 @@ initpri1_LINK = $(CCLD) $(AM_CFLAGS) $(CFLAGS) $(initpri1_LDFLAGS) \
 initpri2_OBJECTS = $(am_initpri2_OBJECTS)
 initpri2_LINK = $(CCLD) $(AM_CFLAGS) $(CFLAGS) $(initpri2_LDFLAGS) \
        $(LDFLAGS) -o $@
+@GCC_TRUE@@NATIVE_LINKER_TRUE@am_initpri3a_OBJECTS =  \
+@GCC_TRUE@@NATIVE_LINKER_TRUE@ initpri3.$(OBJEXT)
+initpri3a_OBJECTS = $(am_initpri3a_OBJECTS)
+initpri3a_LINK = $(CCLD) $(AM_CFLAGS) $(CFLAGS) $(initpri3a_LDFLAGS) \
+       $(LDFLAGS) -o $@
+@GCC_TRUE@@NATIVE_LINKER_TRUE@am_initpri3b_OBJECTS =  \
+@GCC_TRUE@@NATIVE_LINKER_TRUE@ initpri3.$(OBJEXT)
+initpri3b_OBJECTS = $(am_initpri3b_OBJECTS)
+initpri3b_LINK = $(CCLD) $(AM_CFLAGS) $(CFLAGS) $(initpri3b_LDFLAGS) \
+       $(LDFLAGS) -o $@
 @GCC_TRUE@@NATIVE_LINKER_TRUE@am_justsyms_OBJECTS =  \
 @GCC_TRUE@@NATIVE_LINKER_TRUE@ justsyms_1.$(OBJEXT)
 justsyms_OBJECTS = $(am_justsyms_OBJECTS)
@@ -1535,13 +1552,13 @@ SOURCES = $(libgoldtest_a_SOURCES) basic_pic_test.c basic_pie_test.c \
        $(ifuncmain7static_SOURCES) incremental_common_test_1.c \
        incremental_copy_test.c incremental_test_2.c \
        incremental_test_3.c incremental_test_4.c $(initpri1_SOURCES) \
-       $(initpri2_SOURCES) $(justsyms_SOURCES) $(large_SOURCES) \
-       local_labels_test.c many_sections_r_test.c \
-       $(many_sections_test_SOURCES) $(object_unittest_SOURCES) \
-       permission_test.c plugin_test_1.c plugin_test_2.c \
-       plugin_test_3.c plugin_test_4.c plugin_test_5.c \
-       plugin_test_6.c plugin_test_7.c plugin_test_8.c \
-       $(protected_1_SOURCES) $(protected_2_SOURCES) \
+       $(initpri2_SOURCES) $(initpri3a_SOURCES) $(initpri3b_SOURCES) \
+       $(justsyms_SOURCES) $(large_SOURCES) local_labels_test.c \
+       many_sections_r_test.c $(many_sections_test_SOURCES) \
+       $(object_unittest_SOURCES) permission_test.c plugin_test_1.c \
+       plugin_test_2.c plugin_test_3.c plugin_test_4.c \
+       plugin_test_5.c plugin_test_6.c plugin_test_7.c \
+       plugin_test_8.c $(protected_1_SOURCES) $(protected_2_SOURCES) \
        $(relro_script_test_SOURCES) $(relro_strip_test_SOURCES) \
        $(relro_test_SOURCES) $(script_test_1_SOURCES) \
        $(script_test_2_SOURCES) script_test_3.c \
@@ -2111,6 +2128,14 @@ LDADD = libgoldtest.a ../libgold.a ../../libiberty/libiberty.a $(LIBINTL) \
 @GCC_TRUE@@NATIVE_LINKER_TRUE@initpri2_DEPENDENCIES = gcctestdir/ld
 @GCC_TRUE@@NATIVE_LINKER_TRUE@initpri2_LDFLAGS = -Bgcctestdir/
 @GCC_TRUE@@NATIVE_LINKER_TRUE@initpri2_LDADD = 
+@GCC_TRUE@@NATIVE_LINKER_TRUE@initpri3a_SOURCES = initpri3.c
+@GCC_TRUE@@NATIVE_LINKER_TRUE@initpri3a_DEPENDENCIES = gcctestdir/ld
+@GCC_TRUE@@NATIVE_LINKER_TRUE@initpri3a_LDFLAGS = -Bgcctestdir/
+@GCC_TRUE@@NATIVE_LINKER_TRUE@initpri3a_LDADD = 
+@GCC_TRUE@@NATIVE_LINKER_TRUE@initpri3b_SOURCES = initpri3.c
+@GCC_TRUE@@NATIVE_LINKER_TRUE@initpri3b_DEPENDENCIES = gcctestdir/ld
+@GCC_TRUE@@NATIVE_LINKER_TRUE@initpri3b_LDFLAGS = -Bgcctestdir/ -Wl,--no-ctors-in-init-array
+@GCC_TRUE@@NATIVE_LINKER_TRUE@initpri3b_LDADD = 
 @GCC_TRUE@@NATIVE_LINKER_TRUE@ver_test_SOURCES = ver_test_main.cc
 @GCC_TRUE@@NATIVE_LINKER_TRUE@ver_test_DEPENDENCIES = gcctestdir/ld ver_test_1.so ver_test_2.so ver_test_4.so
 @GCC_TRUE@@NATIVE_LINKER_TRUE@ver_test_LDFLAGS = -Bgcctestdir/ -Wl,-R,.
@@ -2663,6 +2688,12 @@ initpri1$(EXEEXT): $(initpri1_OBJECTS) $(initpri1_DEPENDENCIES)
 initpri2$(EXEEXT): $(initpri2_OBJECTS) $(initpri2_DEPENDENCIES) 
        @rm -f initpri2$(EXEEXT)
        $(initpri2_LINK) $(initpri2_OBJECTS) $(initpri2_LDADD) $(LIBS)
+initpri3a$(EXEEXT): $(initpri3a_OBJECTS) $(initpri3a_DEPENDENCIES) 
+       @rm -f initpri3a$(EXEEXT)
+       $(initpri3a_LINK) $(initpri3a_OBJECTS) $(initpri3a_LDADD) $(LIBS)
+initpri3b$(EXEEXT): $(initpri3b_OBJECTS) $(initpri3b_DEPENDENCIES) 
+       @rm -f initpri3b$(EXEEXT)
+       $(initpri3b_LINK) $(initpri3b_OBJECTS) $(initpri3b_LDADD) $(LIBS)
 justsyms$(EXEEXT): $(justsyms_OBJECTS) $(justsyms_DEPENDENCIES) 
        @rm -f justsyms$(EXEEXT)
        $(justsyms_LINK) $(justsyms_OBJECTS) $(justsyms_LDADD) $(LIBS)
@@ -3034,6 +3065,7 @@ distclean-compile:
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/incremental_test_4.Po@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/initpri1.Po@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/initpri2.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/initpri3.Po@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/justsyms_1.Po@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/large-large.Po@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/local_labels_test.Po@am__quote@
@@ -3571,6 +3603,10 @@ initpri1.log: initpri1$(EXEEXT)
        @p='initpri1$(EXEEXT)'; $(am__check_pre) $(LOG_COMPILE) "$$tst" $(am__check_post)
 initpri2.log: initpri2$(EXEEXT)
        @p='initpri2$(EXEEXT)'; $(am__check_pre) $(LOG_COMPILE) "$$tst" $(am__check_post)
+initpri3a.log: initpri3a$(EXEEXT)
+       @p='initpri3a$(EXEEXT)'; $(am__check_pre) $(LOG_COMPILE) "$$tst" $(am__check_post)
+initpri3b.log: initpri3b$(EXEEXT)
+       @p='initpri3b$(EXEEXT)'; $(am__check_pre) $(LOG_COMPILE) "$$tst" $(am__check_post)
 flagstest_o_specialfile.log: flagstest_o_specialfile$(EXEEXT)
        @p='flagstest_o_specialfile$(EXEEXT)'; $(am__check_pre) $(LOG_COMPILE) "$$tst" $(am__check_post)
 flagstest_compress_debug_sections.log: flagstest_compress_debug_sections$(EXEEXT)
diff --git a/gold/testsuite/initpri3.c b/gold/testsuite/initpri3.c
new file mode 100644 (file)
index 0000000..01e233d
--- /dev/null
@@ -0,0 +1,80 @@
+/* initpri3.c -- test ctor odering when using init_array.
+
+   Copyright 2011 Free Software Foundation, Inc.
+   Written by Ian Lance Taylor <iant@google.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 orders .ctor entries when
+   putting them into .init_array, as is the default.  */
+
+#include <assert.h>
+
+int i = 1;
+
+static void
+ctor1 (void)
+{
+  assert (i == 1);
+  i = 2;
+}
+
+static void
+ctor2 (void)
+{
+  assert (i == 2);
+  i = 3;
+}
+
+static void
+dtor1 (void)
+{
+  assert (i == 3);
+  i = 2;
+}
+
+static void
+dtor2 (void)
+{
+  assert (i == 2);
+  i = 1;
+}
+
+/* The .ctors section is run in reverse order, the .dtors section in
+   run in forward order.  We give these arrays the "aligned" attribute
+   because the x86_64 ABI would otherwise give them a 16-byte
+   alignment, which may leave a hole in the section.  */
+
+void (*ctors[]) (void)
+  __attribute__ ((aligned (4), section (".ctors"))) = {
+  ctor2,
+  ctor1
+};
+
+void (*dtors[]) (void)
+  __attribute__ ((aligned (4), section (".dtors"))) = {
+  dtor1,
+  dtor2
+};
+
+int
+main (void)
+{
+  assert (i == 3);
+  return 0;
+}