2013-04-29 Alexander Ivchenko <alexander.ivchenko@intel.com>
authorCary Coutant <ccoutant@google.com>
Mon, 29 Apr 2013 17:15:09 +0000 (17:15 +0000)
committerCary Coutant <ccoutant@google.com>
Mon, 29 Apr 2013 17:15:09 +0000 (17:15 +0000)
gold/
* output.cc (Output_section::add_merge_input_section): Allow
to merge sections if the alignment is more than character size.
* merge.h (Output_merge_string::Output_merge_string): Remove
assert.
* merge.cc (Output_merge_string<Char_type>::do_add_input_section): Count
only not-null strings. Check the alignment of strings.
* stringpool.h
(Stringpool_template<Stringpool_char>::Stringpool_template): Add
alignment as the argument.
(Stringpool_template<Stringpool_char>::addralign_): New class member.
* stringpool.cc (Stringpool_template<Stringpool_char>::new_key_offset):
Align non-zero length strings according to the addralign_.
(Stringpool_template<Stringpool_char>::set_string_offsets):
Updating offsets according to the given alignment.
* testsuite/Makefile.am (text_section_grouping): Test if string
literals are getting merged.
* testsuite/Makefile.in: Regenerate.
* testsuite/merge_string_literals_1.c: New file.
* testsuite/merge_string_literals_2.c: Ditto.
* testsuite/merge_string_literals.sh: Ditto.

gold/ChangeLog
gold/merge.cc
gold/merge.h
gold/output.cc
gold/stringpool.cc
gold/stringpool.h
gold/testsuite/Makefile.am
gold/testsuite/Makefile.in
gold/testsuite/merge_string_literals.sh [new file with mode: 0755]
gold/testsuite/merge_string_literals_1.c [new file with mode: 0644]
gold/testsuite/merge_string_literals_2.c [new file with mode: 0644]

index 97d2e35546f4e38341a3d6f8cf443ff8024827fb..aadefe00c413a72ab1073d77465e1afa24dd373b 100644 (file)
@@ -1,3 +1,26 @@
+2013-04-29  Alexander Ivchenko  <alexander.ivchenko@intel.com>
+
+       * output.cc (Output_section::add_merge_input_section): Allow
+       to merge sections if the alignment is more than character size.
+       * merge.h (Output_merge_string::Output_merge_string): Remove
+       assert.
+       * merge.cc (Output_merge_string<Char_type>::do_add_input_section): Count
+       only not-null strings. Check the alignment of strings.
+       * stringpool.h
+       (Stringpool_template<Stringpool_char>::Stringpool_template): Add
+       alignment as the argument.
+       (Stringpool_template<Stringpool_char>::addralign_): New class member.
+       * stringpool.cc (Stringpool_template<Stringpool_char>::new_key_offset):
+       Align non-zero length strings according to the addralign_.
+       (Stringpool_template<Stringpool_char>::set_string_offsets):
+       Updating offsets according to the given alignment.
+       * testsuite/Makefile.am (text_section_grouping): Test if string
+       literals are getting merged.
+       * testsuite/Makefile.in: Regenerate.
+       * testsuite/merge_string_literals_1.c: New file.
+       * testsuite/merge_string_literals_2.c: Ditto.
+       * testsuite/merge_string_literals.sh: Ditto.
+
 2013-04-26  Ian Lance Taylor  <iant@google.com>
 
        * target-reloc.h (relocate_section): If the reloc offset is out of
index dde43e9b124d1cc2566031adefab687f86144ad5..6480bd933117fd690a52298133be1c292914737e 100644 (file)
@@ -540,25 +540,43 @@ Output_merge_string<Char_type>::do_add_input_section(Relobj* object,
   this->merged_strings_lists_.push_back(merged_strings_list);
   Merged_strings& merged_strings = merged_strings_list->merged_strings;
 
-  // Count the number of strings in the section and size the list.
+  // Count the number of non-null strings in the section and size the list.
   size_t count = 0;
-  for (const Char_type* pt = p; pt < pend0; pt += string_length(pt) + 1)
-    ++count;
+  for (const Char_type* pt = p, len = string_length(pt);
+       pt < pend0;
+       pt += len + 1)
+    if (len != 0)
+      ++count;
   if (pend0 < pend)
     ++count;
   merged_strings.reserve(count + 1);
 
   // The index I is in bytes, not characters.
   section_size_type i = 0;
+
+  // We assume here that the beginning of the section is correctly
+  // aligned, so each string within the section must retain the same
+  // modulo.
+  uintptr_t init_align_modulo = (reinterpret_cast<uintptr_t>(pdata)
+                                & (this->addralign() - 1));
+  bool has_misaligned_strings = false;
+
   while (p < pend0)
     {
       size_t len = string_length(p);
 
-      Stringpool::Key key;
-      this->stringpool_.add_with_length(p, len, true, &key);
+      if (len != 0)
+       {
+         // Within merge input section each string must be aligned.
+         if ((reinterpret_cast<uintptr_t>(p) & (this->addralign() - 1))
+             != init_align_modulo)
+           has_misaligned_strings = true;
 
-      merged_strings.push_back(Merged_string(i, key));
+         Stringpool::Key key;
+         this->stringpool_.add_with_length(p, len, true, &key);
 
+         merged_strings.push_back(Merged_string(i, key));
+       }
       p += len + 1;
       i += (len + 1) * sizeof(Char_type);
     }
@@ -581,6 +599,12 @@ Output_merge_string<Char_type>::do_add_input_section(Relobj* object,
   this->input_count_ += count;
   this->input_size_ += len;
 
+  if (has_misaligned_strings)
+    gold_warning(_("%s: section %s contains incorrectly aligned strings;"
+                  " the alignment of those strings won't be preserved"),
+                object->name().c_str(),
+                object->section_name(shndx).c_str());
+
   // For script processing, we keep the input sections.
   if (this->keeps_input_sections())
     record_input_section(object, shndx);
index 625d731c8d6badc1c58712e72d2cf4bab6f9e5a4..92c634a57981c40c5d3b949f3a5cf2371b5c78b5 100644 (file)
@@ -461,10 +461,9 @@ class Output_merge_string : public Output_merge_base
 {
  public:
   Output_merge_string(uint64_t addralign)
-    : Output_merge_base(sizeof(Char_type), addralign), stringpool_(),
+    : Output_merge_base(sizeof(Char_type), addralign), stringpool_(addralign),
       merged_strings_lists_(), input_count_(0), input_size_(0)
   {
-    gold_assert(addralign <= sizeof(Char_type));
     this->stringpool_.set_no_zero_null();
   }
 
index 22c0bf02b56f7b6cdcc914478b88baba0e037ae3..75ce84093d8468ced5aa4f454c085c9c7289301b 100644 (file)
@@ -2635,11 +2635,6 @@ Output_section::add_merge_input_section(Relobj* object, unsigned int shndx,
 {
   bool is_string = (flags & elfcpp::SHF_STRINGS) != 0;
 
-  // We only merge strings if the alignment is not more than the
-  // character size.  This could be handled, but it's unusual.
-  if (is_string && addralign > entsize)
-    return false;
-
   // We cannot restore merged input section states.
   gold_assert(this->checkpoint_ == NULL);
 
index 434b2d62565d7e178bb559be45609f84c4be988d..072b00df7a393d444835ea0003cd6bfa2f7b7617 100644 (file)
@@ -34,9 +34,10 @@ namespace gold
 {
 
 template<typename Stringpool_char>
-Stringpool_template<Stringpool_char>::Stringpool_template()
+Stringpool_template<Stringpool_char>::Stringpool_template(uint64_t addralign)
   : string_set_(), key_to_offset_(), strings_(), strtab_size_(0),
-    zero_null_(true), optimize_(false), offset_(sizeof(Stringpool_char))
+    zero_null_(true), optimize_(false), offset_(sizeof(Stringpool_char)),
+    addralign_(addralign)
 {
   if (parameters->options_valid() && parameters->options().optimize() >= 2)
     this->optimize_ = true;
@@ -221,8 +222,10 @@ Stringpool_template<Stringpool_char>::new_key_offset(size_t length)
     offset = 0;
   else
     {
-      offset = this->offset_;
-      this->offset_ += (length + 1) * sizeof(Stringpool_char);
+      // Align non-zero length strings.
+      if (length != 0)
+       offset = align_address(this->offset_, this->addralign_);
+      this->offset_ = offset + (length + 1) * sizeof(Stringpool_char);
     }
   this->key_to_offset_.push_back(offset);
 }
@@ -421,8 +424,8 @@ Stringpool_template<Stringpool_char>::set_string_offsets()
                              * charsize));
           else
             {
-              this_offset = offset;
-              offset += ((*curr)->first.length + 1) * charsize;
+              this_offset = align_address(offset, this->addralign_);
+              offset = this_offset + ((*curr)->first.length + 1) * charsize;
             }
          this->key_to_offset_[(*curr)->second - 1] = this_offset;
          last_offset = this_offset;
index c51b143bea2da552fb7f778cf8b73a913cc9fc33..b6383296af0fae3cea887feb1ac1b8557db9442f 100644 (file)
@@ -180,7 +180,7 @@ class Stringpool_template
   typedef size_t Key;
 
   // Create a Stringpool.
-  Stringpool_template();
+  Stringpool_template(uint64_t addralign = 1);
 
   ~Stringpool_template();
 
@@ -409,6 +409,8 @@ class Stringpool_template
   bool optimize_;
   // offset of the next string.
   section_offset_type offset_;
+  // The alignment of strings in the stringpool.
+  uint64_t addralign_;
 };
 
 // The most common type of Stringpool.
index 4d0292569c2f86740f6a5ebc6477c825b21887c1..a1ac4743e9f27b4fdc093efcb41e590ed5ae157d 100644 (file)
@@ -329,6 +329,18 @@ icf_sht_rel_addend_test: icf_sht_rel_addend_test_1.o icf_sht_rel_addend_test_2.o
 icf_sht_rel_addend_test.stdout: icf_sht_rel_addend_test
        $(TEST_NM) icf_sht_rel_addend_test > icf_sht_rel_addend_test.stdout
 
+check_SCRIPTS += merge_string_literals.sh
+check_DATA += merge_string_literals.stdout
+MOSTLYCLEANFILES += merge_string_literals
+merge_string_literals_1.o: merge_string_literals_1.c
+       $(CXXCOMPILE) -O2 -c -fPIC -g -o $@ $<
+merge_string_literals_2.o: merge_string_literals_2.c
+       $(CXXCOMPILE) -O2 -c -fPIC -g -o $@ $<
+merge_string_literals: merge_string_literals_1.o merge_string_literals_2.o gcctestdir/ld
+       $(CXXLINK) -Bgcctestdir/ merge_string_literals_1.o merge_string_literals_2.o -O2 -shared -nostdlib
+merge_string_literals.stdout: merge_string_literals
+       $(TEST_OBJDUMP) -s -j.rodata merge_string_literals > merge_string_literals.stdout
+
 check_PROGRAMS += basic_test
 check_PROGRAMS += basic_pic_test
 basic_test.o: basic_test.cc
index fa9e80f8346816799638a590bb67abd5900278c9..7d159e756ad00493aeb38e80bfdd941a1c383edd 100644 (file)
@@ -85,6 +85,7 @@ check_PROGRAMS = $(am__EXEEXT_1) $(am__EXEEXT_2) $(am__EXEEXT_3) \
 @GCC_TRUE@@NATIVE_LINKER_TRUE@ icf_preemptible_functions_test.sh \
 @GCC_TRUE@@NATIVE_LINKER_TRUE@ icf_string_merge_test.sh \
 @GCC_TRUE@@NATIVE_LINKER_TRUE@ icf_sht_rel_addend_test.sh \
+@GCC_TRUE@@NATIVE_LINKER_TRUE@ merge_string_literals.sh \
 @GCC_TRUE@@NATIVE_LINKER_TRUE@ two_file_shared.sh weak_plt.sh \
 @GCC_TRUE@@NATIVE_LINKER_TRUE@ debug_msg.sh undef_symbol.sh \
 @GCC_TRUE@@NATIVE_LINKER_TRUE@ ver_test_1.sh ver_test_2.sh \
@@ -119,6 +120,7 @@ check_PROGRAMS = $(am__EXEEXT_1) $(am__EXEEXT_2) $(am__EXEEXT_3) \
 @GCC_TRUE@@NATIVE_LINKER_TRUE@ icf_preemptible_functions_test.stdout \
 @GCC_TRUE@@NATIVE_LINKER_TRUE@ icf_string_merge_test.stdout \
 @GCC_TRUE@@NATIVE_LINKER_TRUE@ icf_sht_rel_addend_test.stdout \
+@GCC_TRUE@@NATIVE_LINKER_TRUE@ merge_string_literals.stdout \
 @GCC_TRUE@@NATIVE_LINKER_TRUE@ two_file_shared.dbg \
 @GCC_TRUE@@NATIVE_LINKER_TRUE@ weak_plt_shared.so debug_msg.err
 @GCC_TRUE@@NATIVE_LINKER_TRUE@am__append_4 = incremental_test \
@@ -140,6 +142,7 @@ check_PROGRAMS = $(am__EXEEXT_1) $(am__EXEEXT_2) $(am__EXEEXT_3) \
 @GCC_TRUE@@NATIVE_LINKER_TRUE@ icf_preemptible_functions_test \
 @GCC_TRUE@@NATIVE_LINKER_TRUE@ icf_string_merge_test \
 @GCC_TRUE@@NATIVE_LINKER_TRUE@ icf_sht_rel_addend_test \
+@GCC_TRUE@@NATIVE_LINKER_TRUE@ merge_string_literals \
 @GCC_TRUE@@NATIVE_LINKER_TRUE@ two_file_shared.dbg \
 @GCC_TRUE@@NATIVE_LINKER_TRUE@ alt/weak_undef_lib.so
 @GCC_TRUE@@NATIVE_LINKER_TRUE@am__append_5 = icf_virtual_function_folding_test \
@@ -3755,6 +3758,8 @@ icf_string_merge_test.sh.log: icf_string_merge_test.sh
        @p='icf_string_merge_test.sh'; $(am__check_pre) $(LOG_COMPILE) "$$tst" $(am__check_post)
 icf_sht_rel_addend_test.sh.log: icf_sht_rel_addend_test.sh
        @p='icf_sht_rel_addend_test.sh'; $(am__check_pre) $(LOG_COMPILE) "$$tst" $(am__check_post)
+merge_string_literals.sh.log: merge_string_literals.sh
+       @p='merge_string_literals.sh'; $(am__check_pre) $(LOG_COMPILE) "$$tst" $(am__check_post)
 two_file_shared.sh.log: two_file_shared.sh
        @p='two_file_shared.sh'; $(am__check_pre) $(LOG_COMPILE) "$$tst" $(am__check_post)
 weak_plt.sh.log: weak_plt.sh
@@ -4440,6 +4445,14 @@ uninstall-am:
 @GCC_TRUE@@NATIVE_LINKER_TRUE@ $(CXXLINK) -Bgcctestdir/ -Wl,--icf=all icf_sht_rel_addend_test_1.o icf_sht_rel_addend_test_2.o
 @GCC_TRUE@@NATIVE_LINKER_TRUE@icf_sht_rel_addend_test.stdout: icf_sht_rel_addend_test
 @GCC_TRUE@@NATIVE_LINKER_TRUE@ $(TEST_NM) icf_sht_rel_addend_test > icf_sht_rel_addend_test.stdout
+@GCC_TRUE@@NATIVE_LINKER_TRUE@merge_string_literals_1.o: merge_string_literals_1.c
+@GCC_TRUE@@NATIVE_LINKER_TRUE@ $(CXXCOMPILE) -O2 -c -fPIC -g -o $@ $<
+@GCC_TRUE@@NATIVE_LINKER_TRUE@merge_string_literals_2.o: merge_string_literals_2.c
+@GCC_TRUE@@NATIVE_LINKER_TRUE@ $(CXXCOMPILE) -O2 -c -fPIC -g -o $@ $<
+@GCC_TRUE@@NATIVE_LINKER_TRUE@merge_string_literals: merge_string_literals_1.o merge_string_literals_2.o gcctestdir/ld
+@GCC_TRUE@@NATIVE_LINKER_TRUE@ $(CXXLINK) -Bgcctestdir/ merge_string_literals_1.o merge_string_literals_2.o -O2 -shared -nostdlib
+@GCC_TRUE@@NATIVE_LINKER_TRUE@merge_string_literals.stdout: merge_string_literals
+@GCC_TRUE@@NATIVE_LINKER_TRUE@ $(TEST_OBJDUMP) -s -j.rodata merge_string_literals > merge_string_literals.stdout
 @GCC_TRUE@@NATIVE_LINKER_TRUE@basic_test.o: basic_test.cc
 @GCC_TRUE@@NATIVE_LINKER_TRUE@ $(CXXCOMPILE) -O0 -c -o $@ $<
 @GCC_TRUE@@NATIVE_LINKER_TRUE@basic_test: basic_test.o gcctestdir/ld
diff --git a/gold/testsuite/merge_string_literals.sh b/gold/testsuite/merge_string_literals.sh
new file mode 100755 (executable)
index 0000000..486a895
--- /dev/null
@@ -0,0 +1,41 @@
+#!/bin/sh
+
+# merge_string_literals.sh -- test
+
+# Copyright 2013 Free Software Foundation, Inc.
+# Written by Alexander Ivchenko <alexander.ivchenko@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.
+
+# The goal of this program is to check whether string literals from different
+# object files are merged together
+
+set -e
+
+check()
+{
+    number_of_occurrence=`grep $2 ./$1 -o| wc -l`
+    if [ $number_of_occurrence != $3 ]
+    then
+       echo "String literals were not merged"
+       exit 1
+    fi
+}
+
+# If string literals were merged, then "abcd" appears two times
+check merge_string_literals.stdout "abcd" 2
diff --git a/gold/testsuite/merge_string_literals_1.c b/gold/testsuite/merge_string_literals_1.c
new file mode 100644 (file)
index 0000000..fc0487c
--- /dev/null
@@ -0,0 +1,31 @@
+// merge_string_literals_1.c -- a test case for gold
+
+// Copyright 2013 Free Software Foundation, Inc.
+// Written by Alexander Ivchenko <alexander.ivchenko@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.
+
+// The goal of this program is to check whether string literals from different
+// object files are merged together
+
+const char* bar1() {
+    return "abcdefghijklmnopqrstuvwxyz0123456789";
+}
+const char* bar1_short() {
+    return "abcdef";
+}
diff --git a/gold/testsuite/merge_string_literals_2.c b/gold/testsuite/merge_string_literals_2.c
new file mode 100644 (file)
index 0000000..d1185cd
--- /dev/null
@@ -0,0 +1,31 @@
+// merge_string_literals_2.c -- a test case for gold
+
+// Copyright 2013 Free Software Foundation, Inc.
+// Written by Alexander Ivchenko <alexander.ivchenko@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.
+
+// The goal of this program is to check whether string literals from different
+// object files are merged together
+
+const char* bar2() {
+    return "abcdefghijklmnopqrstuvwxyz0123456789";
+}
+const char* bar2_short() {
+    return "abcdef";
+}