diff options
-rw-r--r-- | gold/ChangeLog | 25 | ||||
-rw-r--r-- | gold/layout.cc | 51 | ||||
-rw-r--r-- | gold/layout.h | 6 | ||||
-rw-r--r-- | gold/object.h | 9 | ||||
-rw-r--r-- | gold/reloc.cc | 34 | ||||
-rw-r--r-- | gold/testsuite/Makefile.am | 12 | ||||
-rw-r--r-- | gold/testsuite/Makefile.in | 52 | ||||
-rw-r--r-- | gold/testsuite/initpri3.c | 80 |
8 files changed, 253 insertions, 16 deletions
diff --git a/gold/ChangeLog b/gold/ChangeLog index fe06e41..ff39a18 100644 --- a/gold/ChangeLog +++ b/gold/ChangeLog @@ -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. diff --git a/gold/layout.cc b/gold/layout.cc index 82964ce..bfb1a7e 100644 --- a/gold/layout.cc +++ b/gold/layout.cc @@ -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(); diff --git a/gold/layout.h b/gold/layout.h index 3eee820..0f6840e 100644 --- a/gold/layout.h +++ b/gold/layout.h @@ -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 diff --git a/gold/object.h b/gold/object.h index 1031833..8735f9e 100644 --- a/gold/object.h +++ b/gold/object.h @@ -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, diff --git a/gold/reloc.cc b/gold/reloc.cc index dacab35..4c28b03 100644 --- a/gold/reloc.cc +++ b/gold/reloc.cc @@ -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> diff --git a/gold/testsuite/Makefile.am b/gold/testsuite/Makefile.am index ca486cf..d075cdc 100644 --- a/gold/testsuite/Makefile.am +++ b/gold/testsuite/Makefile.am @@ -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 diff --git a/gold/testsuite/Makefile.in b/gold/testsuite/Makefile.in index 20171bf..10bce4e 100644 --- a/gold/testsuite/Makefile.in +++ b/gold/testsuite/Makefile.in @@ -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 index 0000000..01e233d --- /dev/null +++ b/gold/testsuite/initpri3.c @@ -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; +} |