Implement SORT_BY_INIT_PRIORITY.
authorIgor Kudrin <ikudrin@accesssoftek.com>
Tue, 28 Jun 2016 20:56:05 +0000 (13:56 -0700)
committerCary Coutant <ccoutant@gmail.com>
Tue, 28 Jun 2016 20:56:05 +0000 (13:56 -0700)
2016-06-28  Igor Kudrin  <ikudrin@accesssoftek.com>

gold/
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.

gold/ChangeLog
gold/script-c.h
gold/script-sections.cc
gold/script.cc
gold/testsuite/Makefile.am
gold/testsuite/Makefile.in
gold/testsuite/script_test_14.s [new file with mode: 0644]
gold/testsuite/script_test_14.sh [new file with mode: 0644]
gold/testsuite/script_test_14.t [new file with mode: 0644]
gold/yyscript.y

index 1a52b850dbc983157017880592fca7072abd8048..1883cc36c90113b18d916f7870a38225767392d6 100644 (file)
@@ -1,3 +1,20 @@
+2016-06-28  Igor Kudrin  <ikudrin@accesssoftek.com>
+
+       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  <jrtc27@jrtc27.com>
 
        * sparc.cc (Target_sparc::Scan::local): Don't convert R_SPARC_32
index b6ca932cb772d30fd2871cd0223d9fca21295575..478cf259d0398ccb36804e4ca286f9c6e626e93f 100644 (file)
@@ -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.  */
index ef8295331518413eecd0ce6dbda1fc0fd006acda..96c68de68ea746dd629478cf96ce1277acf98456 100644 (file)
@@ -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();
            }
index f2ac3f7879bb227cf82b5c38ece27169dd5a94d6..d6aa7b250a4c6ecc5719d0ec99c6ddec5375eba7 100644 (file)
@@ -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 },
index 01cae9f1ce520255d7dd89c862ad1a35661b2a36..9e232e9b5c1c1288d5b9beadc9396a5b3d66bd0a 100644 (file)
@@ -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
 
index 3771f798016ee623a666b6a7da7c0245e57857ef..5b66c9c470ab1382433124997a74e9d1852a00e9 100644 (file)
@@ -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 (file)
index 0000000..7fbe895
--- /dev/null
@@ -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 (file)
index 0000000..b780027
--- /dev/null
@@ -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 <ikudrin@accesssoftek.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.
+
+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" "\<f0f1f3f4\b"
+
+# Sort order for .ctors:
+# * .ctors      -- Doesn't have a numeric part, compared with others as strings
+# * .ctors.0103 -- The numeric parts have the same value, which is greater than
+# * .ctors.103  /  in the last section's name. This pair is compared as strings.
+# * .ctors.101  -- The least numeric part among all sections which contain them.
+check ".ctors" "\<c0c3c4c1\b"
+
+# Sort order for .dtors, the same considerations as for .ctors:
+# * .dtors
+# * .dtors.0103
+# * .dtors.103
+# * .dtors.101
+check ".dtors" "\<d0d3d4d1\b"
+
+# Sort order for .sec, just sort as strings, because it's not the reserved name:
+# * .sec
+# * .sec.0103
+# * .sec.101
+# * .sec.103
+check ".sec" "\<a0a3a1a4\b"
+
diff --git a/gold/testsuite/script_test_14.t b/gold/testsuite/script_test_14.t
new file mode 100644 (file)
index 0000000..c068be3
--- /dev/null
@@ -0,0 +1,30 @@
+/* script_test_14.t -- test SORT_BY_INIT_PRIORITY.
+
+   Copyright (C) 2016 Free Software Foundation, Inc.
+   Written by Igor Kudrin <ikudrin@accesssoftek.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.  */
+
+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*)) }
+}
index 4f3fa50bb04fbb4d5f3192bb5eff439ca40cfd9e..7e6bd27b4121a471de481fcb1363c46d022e0824 100644 (file)
 %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.  */