2013-04-29 Alexander Ivchenko <alexander.ivchenko@intel.com>

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.
This commit is contained in:
Cary Coutant 2013-04-29 17:15:09 +00:00
parent 5dad867cca
commit e31908b642
11 changed files with 194 additions and 20 deletions

View 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

View 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);

View 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();
}

View 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);

View 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;

View 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.

View 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

View 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

View File

@ -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

View File

@ -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";
}

View File

@ -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";
}