diff --git a/gold/ChangeLog b/gold/ChangeLog index 1a52b850db..1883cc36c9 100644 --- a/gold/ChangeLog +++ b/gold/ChangeLog @@ -1,3 +1,20 @@ +2016-06-28 Igor Kudrin + + PR gold/18098 + * script-c.h (Sort_wildcard): Add SORT_WILDCARD_BY_INIT_PRIORITY. + * script-sections.cc (Input_section_sorter::get_init_priority): New method. + (Input_section_sorter::operator()): Handle SORT_WILDCARD_BY_INIT_PRIORITY. + (Output_section_element_input::print): Likewise. + * script.cc (script_keyword_parsecodes): Add entry SORT_BY_INIT_PRIORITY. + * yyscript.y (SORT_BY_INIT_PRIORITY): New token. + (wildcard_section): Handle SORT_BY_INIT_PRIORITY. + + * testsuite/Makefile.am (script_test_14): New test. + * testsuite/Makefile.in: Regenerate. + * testsuite/script_test_14.s: New test source file. + * testsuite/script_test_14.sh: New test script. + * testsuite/script_test_14.t: New test linker script. + 2016-06-28 James Clarke * sparc.cc (Target_sparc::Scan::local): Don't convert R_SPARC_32 diff --git a/gold/script-c.h b/gold/script-c.h index b6ca932cb7..478cf259d0 100644 --- a/gold/script-c.h +++ b/gold/script-c.h @@ -139,7 +139,8 @@ enum Sort_wildcard SORT_WILDCARD_BY_NAME, SORT_WILDCARD_BY_ALIGNMENT, SORT_WILDCARD_BY_NAME_BY_ALIGNMENT, - SORT_WILDCARD_BY_ALIGNMENT_BY_NAME + SORT_WILDCARD_BY_ALIGNMENT_BY_NAME, + SORT_WILDCARD_BY_INIT_PRIORITY }; /* The information we build for a single wildcard specification. */ diff --git a/gold/script-sections.cc b/gold/script-sections.cc index ef82953315..96c68de68e 100644 --- a/gold/script-sections.cc +++ b/gold/script-sections.cc @@ -1524,18 +1524,69 @@ class Input_section_sorter operator()(const Input_section_info&, const Input_section_info&) const; private: + static unsigned long + get_init_priority(const char*); + Sort_wildcard filename_sort_; Sort_wildcard section_sort_; }; +// Return a relative priority of the section with the specified NAME +// (a lower value meand a higher priority), or 0 if it should be compared +// with others as strings. +// The implementation of this function is copied from ld/ldlang.c. + +unsigned long +Input_section_sorter::get_init_priority(const char* name) +{ + char* end; + unsigned long init_priority; + + // GCC uses the following section names for the init_priority + // attribute with numerical values 101 and 65535 inclusive. A + // lower value means a higher priority. + // + // 1: .init_array.NNNN/.fini_array.NNNN: Where NNNN is the + // decimal numerical value of the init_priority attribute. + // The order of execution in .init_array is forward and + // .fini_array is backward. + // 2: .ctors.NNNN/.dtors.NNNN: Where NNNN is 65535 minus the + // decimal numerical value of the init_priority attribute. + // The order of execution in .ctors is backward and .dtors + // is forward. + + if (strncmp(name, ".init_array.", 12) == 0 + || strncmp(name, ".fini_array.", 12) == 0) + { + init_priority = strtoul(name + 12, &end, 10); + return *end ? 0 : init_priority; + } + else if (strncmp(name, ".ctors.", 7) == 0 + || strncmp(name, ".dtors.", 7) == 0) + { + init_priority = strtoul(name + 7, &end, 10); + return *end ? 0 : 65535 - init_priority; + } + + return 0; +} + bool Input_section_sorter::operator()(const Input_section_info& isi1, const Input_section_info& isi2) const { + if (this->section_sort_ == SORT_WILDCARD_BY_INIT_PRIORITY) + { + unsigned long ip1 = get_init_priority(isi1.section_name().c_str()); + unsigned long ip2 = get_init_priority(isi2.section_name().c_str()); + if (ip1 != 0 && ip2 != 0 && ip1 != ip2) + return ip1 < ip2; + } if (this->section_sort_ == SORT_WILDCARD_BY_NAME || this->section_sort_ == SORT_WILDCARD_BY_NAME_BY_ALIGNMENT || (this->section_sort_ == SORT_WILDCARD_BY_ALIGNMENT_BY_NAME - && isi1.addralign() == isi2.addralign())) + && isi1.addralign() == isi2.addralign()) + || this->section_sort_ == SORT_WILDCARD_BY_INIT_PRIORITY) { if (isi1.section_name() != isi2.section_name()) return isi1.section_name() < isi2.section_name(); @@ -1827,6 +1878,10 @@ Output_section_element_input::print(FILE* f) const fprintf(f, "SORT_BY_ALIGNMENT(SORT_BY_NAME("); close_parens = 2; break; + case SORT_WILDCARD_BY_INIT_PRIORITY: + fprintf(f, "SORT_BY_INIT_PRIORITY("); + close_parens = 1; + break; default: gold_unreachable(); } diff --git a/gold/script.cc b/gold/script.cc index f2ac3f7879..d6aa7b250a 100644 --- a/gold/script.cc +++ b/gold/script.cc @@ -1792,6 +1792,7 @@ script_keyword_parsecodes[] = { "SIZEOF_HEADERS", SIZEOF_HEADERS }, { "SORT", SORT_BY_NAME }, { "SORT_BY_ALIGNMENT", SORT_BY_ALIGNMENT }, + { "SORT_BY_INIT_PRIORITY", SORT_BY_INIT_PRIORITY }, { "SORT_BY_NAME", SORT_BY_NAME }, { "SPECIAL", SPECIAL }, { "SQUAD", SQUAD }, diff --git a/gold/testsuite/Makefile.am b/gold/testsuite/Makefile.am index 01cae9f1ce..9e232e9b5c 100644 --- a/gold/testsuite/Makefile.am +++ b/gold/testsuite/Makefile.am @@ -1859,6 +1859,17 @@ script_test_12a.o: script_test_12a.c script_test_12b.o: script_test_12b.c $(COMPILE) -O0 -c -o $@ $< +# Test for SORT_BY_INIT_PRIORITY. +check_SCRIPTS += script_test_14.sh +check_DATA += script_test_14.stdout +MOSTLYCLEANFILES += script_test_14 +script_test_14.o: script_test_14.s + $(TEST_AS) -o $@ $< +script_test_14: $(srcdir)/script_test_14.t script_test_14.o gcctestdir/ld + gcctestdir/ld -o $@ script_test_14.o -T $(srcdir)/script_test_14.t +script_test_14.stdout: script_test_14 + $(TEST_OBJDUMP) -s script_test_14 > $@ + # Test --dynamic-list, --dynamic-list-data, --dynamic-list-cpp-new, # and --dynamic-list-cpp-typeinfo diff --git a/gold/testsuite/Makefile.in b/gold/testsuite/Makefile.in index 3771f79801..5b66c9c470 100644 --- a/gold/testsuite/Makefile.in +++ b/gold/testsuite/Makefile.in @@ -340,9 +340,9 @@ check_PROGRAMS = $(am__EXEEXT_1) $(am__EXEEXT_2) $(am__EXEEXT_3) \ @GCC_TRUE@@NATIVE_LINKER_TRUE@ script_test_4 script_test_5 \ @GCC_TRUE@@NATIVE_LINKER_TRUE@ script_test_6 script_test_7 \ @GCC_TRUE@@NATIVE_LINKER_TRUE@ script_test_8 script_test_9 \ -@GCC_TRUE@@NATIVE_LINKER_TRUE@ dynamic_list dynamic_list.stdout \ -@GCC_TRUE@@NATIVE_LINKER_TRUE@ libthin1.a libthin3.a \ -@GCC_TRUE@@NATIVE_LINKER_TRUE@ libthinall.a \ +@GCC_TRUE@@NATIVE_LINKER_TRUE@ script_test_14 dynamic_list \ +@GCC_TRUE@@NATIVE_LINKER_TRUE@ dynamic_list.stdout libthin1.a \ +@GCC_TRUE@@NATIVE_LINKER_TRUE@ libthin3.a libthinall.a \ @GCC_TRUE@@NATIVE_LINKER_TRUE@ alt/thin_archive_test_2.o \ @GCC_TRUE@@NATIVE_LINKER_TRUE@ alt/thin_archive_test_4.o \ @GCC_TRUE@@NATIVE_LINKER_TRUE@ alt/libthin2.a alt/libthin4.a @@ -370,6 +370,8 @@ check_PROGRAMS = $(am__EXEEXT_1) $(am__EXEEXT_2) $(am__EXEEXT_3) \ # Similar to --detect-odr-violations: check for undefined symbols in .so's +# Test for SORT_BY_INIT_PRIORITY. + # Test --dynamic-list, --dynamic-list-data, --dynamic-list-cpp-new, # and --dynamic-list-cpp-typeinfo @GCC_TRUE@@NATIVE_LINKER_TRUE@am__append_36 = debug_msg.sh \ @@ -386,7 +388,9 @@ check_PROGRAMS = $(am__EXEEXT_1) $(am__EXEEXT_2) $(am__EXEEXT_3) \ @GCC_TRUE@@NATIVE_LINKER_TRUE@ script_test_6.sh \ @GCC_TRUE@@NATIVE_LINKER_TRUE@ script_test_7.sh \ @GCC_TRUE@@NATIVE_LINKER_TRUE@ script_test_8.sh \ -@GCC_TRUE@@NATIVE_LINKER_TRUE@ script_test_9.sh dynamic_list.sh +@GCC_TRUE@@NATIVE_LINKER_TRUE@ script_test_9.sh \ +@GCC_TRUE@@NATIVE_LINKER_TRUE@ script_test_14.sh \ +@GCC_TRUE@@NATIVE_LINKER_TRUE@ dynamic_list.sh # Create the data files that debug_msg.sh analyzes. @@ -432,6 +436,7 @@ check_PROGRAMS = $(am__EXEEXT_1) $(am__EXEEXT_2) $(am__EXEEXT_3) \ @GCC_TRUE@@NATIVE_LINKER_TRUE@ script_test_7.stdout \ @GCC_TRUE@@NATIVE_LINKER_TRUE@ script_test_8.stdout \ @GCC_TRUE@@NATIVE_LINKER_TRUE@ script_test_9.stdout \ +@GCC_TRUE@@NATIVE_LINKER_TRUE@ script_test_14.stdout \ @GCC_TRUE@@NATIVE_LINKER_TRUE@ dynamic_list.stdout @GCC_FALSE@script_test_1_DEPENDENCIES = @NATIVE_LINKER_FALSE@script_test_1_DEPENDENCIES = @@ -4605,6 +4610,8 @@ script_test_8.sh.log: script_test_8.sh @p='script_test_8.sh'; $(am__check_pre) $(LOG_COMPILE) "$$tst" $(am__check_post) script_test_9.sh.log: script_test_9.sh @p='script_test_9.sh'; $(am__check_pre) $(LOG_COMPILE) "$$tst" $(am__check_post) +script_test_14.sh.log: script_test_14.sh + @p='script_test_14.sh'; $(am__check_pre) $(LOG_COMPILE) "$$tst" $(am__check_post) dynamic_list.sh.log: dynamic_list.sh @p='dynamic_list.sh'; $(am__check_pre) $(LOG_COMPILE) "$$tst" $(am__check_post) plugin_test_1.sh.log: plugin_test_1.sh @@ -6057,6 +6064,12 @@ uninstall-am: @GCC_TRUE@@NATIVE_LINKER_TRUE@ $(COMPILE) -O0 -c -o $@ $< @GCC_TRUE@@NATIVE_LINKER_TRUE@script_test_12b.o: script_test_12b.c @GCC_TRUE@@NATIVE_LINKER_TRUE@ $(COMPILE) -O0 -c -o $@ $< +@GCC_TRUE@@NATIVE_LINKER_TRUE@script_test_14.o: script_test_14.s +@GCC_TRUE@@NATIVE_LINKER_TRUE@ $(TEST_AS) -o $@ $< +@GCC_TRUE@@NATIVE_LINKER_TRUE@script_test_14: $(srcdir)/script_test_14.t script_test_14.o gcctestdir/ld +@GCC_TRUE@@NATIVE_LINKER_TRUE@ gcctestdir/ld -o $@ script_test_14.o -T $(srcdir)/script_test_14.t +@GCC_TRUE@@NATIVE_LINKER_TRUE@script_test_14.stdout: script_test_14 +@GCC_TRUE@@NATIVE_LINKER_TRUE@ $(TEST_OBJDUMP) -s script_test_14 > $@ @GCC_TRUE@@NATIVE_LINKER_TRUE@dynamic_list: basic_test.o gcctestdir/ld $(srcdir)/dynamic_list.t @GCC_TRUE@@NATIVE_LINKER_TRUE@ $(CXXLINK) -Bgcctestdir/ basic_test.o \ @GCC_TRUE@@NATIVE_LINKER_TRUE@ -Wl,--dynamic-list $(srcdir)/dynamic_list.t \ diff --git a/gold/testsuite/script_test_14.s b/gold/testsuite/script_test_14.s new file mode 100644 index 0000000000..7fbe895240 --- /dev/null +++ b/gold/testsuite/script_test_14.s @@ -0,0 +1,59 @@ + .section .init_array.101,"aw" + .byte 0x01 + + .section .init_array.103,"aw" + .byte 0x04 + + .section .init_array,"aw" + .byte 0x00 + + .section .init_array.0103,"aw" + .byte 0x03 + + .section .fini_array.101,"aw" + .byte 0xf1 + + .section .fini_array.103,"aw" + .byte 0xf4 + + .section .fini_array,"aw" + .byte 0xf0 + + .section .fini_array.0103,"aw" + .byte 0xf3 + + .section .ctors.101,"aw" + .byte 0xc1 + + .section .ctors.103, "aw" + .byte 0xc4 + + .section .ctors,"aw" + .byte 0xc0 + + .section .ctors.0103,"aw" + .byte 0xc3 + + .section .dtors.101,"aw" + .byte 0xd1 + + .section .dtors.103,"aw" + .byte 0xd4 + + .section .dtors,"aw" + .byte 0xd0 + + .section .dtors.0103,"aw" + .byte 0xd3 + + .section .sec.101,"aw" + .byte 0xa1 + + .section .sec.103,"aw" + .byte 0xa4 + + .section .sec,"aw" + .byte 0xa0 + + .section .sec.0103,"aw" + .byte 0xa3 diff --git a/gold/testsuite/script_test_14.sh b/gold/testsuite/script_test_14.sh new file mode 100644 index 0000000000..b780027942 --- /dev/null +++ b/gold/testsuite/script_test_14.sh @@ -0,0 +1,84 @@ +#!/bin/sh + +# script_test_14.sh -- test SORT_BY_INIT_PRIORITY + +# Copyright (C) 2016 Free Software Foundation, Inc. +# Written by Igor Kudrin . + +# 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. + +file="script_test_14.stdout" + +check() +{ + section=$1 + pattern=$2 + found=`fgrep "Contents of section $section:" -A1 $file | tail -n 1` + if test -z "$found"; then + echo "Section \"$section\" not found in file $file" + echo "" + echo "Actual output below:" + cat "$file" + exit 1 + fi + match_pattern=`echo "$found" | grep -e "$pattern"` + if test -z "$match_pattern"; then + echo "Expected pattern was not found in section \"$section\":" + echo " $pattern" + echo "" + echo "Actual output below:" + cat "$file" + exit 1 + fi +} + +# Sort order for .init_array: +# * .init_array -- Doesn't have a numeric part, compared with others as strings. +# * .init_array.101 -- The numeric part is less than in the two others. +# * .init_array.0103 -- These names have numeric parts with the same value, +# * .init_array.103 / so they are compared as strings. +check ".init_array" "\<00010304\b" + +# Sort order for .fini_array, the same consideration as for .init_array: +# * .fini_array +# * .fini_array.101 +# * .fini_array.0103 +# * .fini_array.103 +check ".fini_array" "\. + + 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. */ + +SECTIONS +{ + .init_array : { *(SORT_BY_INIT_PRIORITY(.init_array*)) } + .fini_array : { *(SORT_BY_INIT_PRIORITY(.fini_array*)) } + .ctors : { *(SORT_BY_INIT_PRIORITY(.ctors*)) } + .dtors : { *(SORT_BY_INIT_PRIORITY(.dtors*)) } + .sec : { *(SORT_BY_INIT_PRIORITY(.sec*)) } +} diff --git a/gold/yyscript.y b/gold/yyscript.y index 4f3fa50bb0..7e6bd27b41 100644 --- a/gold/yyscript.y +++ b/gold/yyscript.y @@ -175,6 +175,7 @@ %token SIZEOF %token SIZEOF_HEADERS /* SIZEOF_HEADERS, sizeof_headers */ %token SORT_BY_ALIGNMENT +%token SORT_BY_INIT_PRIORITY %token SORT_BY_NAME %token SPECIAL %token SQUAD @@ -677,6 +678,11 @@ wildcard_section: abort(); } } + | SORT_BY_INIT_PRIORITY '(' wildcard_name ')' + { + $$.name = $3; + $$.sort = SORT_WILDCARD_BY_INIT_PRIORITY; + } ; /* A list of file names to exclude. */