From c5617f2fb6d7c6a1898d920ac662209a195b3c9e Mon Sep 17 00:00:00 2001 From: Doug Kwan Date: Fri, 16 Oct 2009 19:11:32 +0000 Subject: [PATCH] 2009-10-16 Doug Kwan * dynobj.cc (Versions::Versions): Initialize version_script_. Only insert base version symbol definition for a shared object if version script defines any version versions. (Versions::define_base_version): New method definition. (Versions::add_def): Check that base version is not needed. (Versions::add_need): Define base version lazily. * dynobj.h (Versions::define_base_version): New method declaration. (Versions::needs_base_version_): New data member declaration. * testsuite/Makefile.am (check_SCRIPTS): Add no_version_test.sh (check_DATA): Add no_version_test.stdout. (libno_version_test.so, no_version_test.o no_version_test.stdout): New make rules. * testsuite/Makefile.in: Regenerate. * testsuite/no_version_test.c: New file. * testsuite/no_version_test.sh: Ditto. --- gold/ChangeLog | 18 ++++++++++++++ gold/dynobj.cc | 52 +++++++++++++++++++++++++++------------ gold/dynobj.h | 7 ++++++ gold/testsuite/Makefile.am | 14 +++++++++++ gold/testsuite/Makefile.in | 21 +++++++++++++--- gold/testsuite/no_version_test.c | 32 ++++++++++++++++++++++++ gold/testsuite/no_version_test.sh | 45 +++++++++++++++++++++++++++++++++ 7 files changed, 170 insertions(+), 19 deletions(-) create mode 100644 gold/testsuite/no_version_test.c create mode 100755 gold/testsuite/no_version_test.sh diff --git a/gold/ChangeLog b/gold/ChangeLog index 6358191..55c3a70 100644 --- a/gold/ChangeLog +++ b/gold/ChangeLog @@ -1,5 +1,23 @@ 2009-10-16 Doug Kwan + * dynobj.cc (Versions::Versions): Initialize version_script_. + Only insert base version symbol definition for a shared object + if version script defines any version versions. + (Versions::define_base_version): New method definition. + (Versions::add_def): Check that base version is not needed. + (Versions::add_need): Define base version lazily. + * dynobj.h (Versions::define_base_version): New method declaration. + (Versions::needs_base_version_): New data member declaration. + * testsuite/Makefile.am (check_SCRIPTS): Add no_version_test.sh + (check_DATA): Add no_version_test.stdout. + (libno_version_test.so, no_version_test.o no_version_test.stdout): + New make rules. + * testsuite/Makefile.in: Regenerate. + * testsuite/no_version_test.c: New file. + * testsuite/no_version_test.sh: Ditto. + +2009-10-16 Doug Kwan + * expression.cc (class Segment_start_expression): New class definition. (Segment_start_expression::value): New method definition. (script_exp_function_segment_start): Return a new diff --git a/gold/dynobj.cc b/gold/dynobj.cc index b14d06d..dec6f3d 100644 --- a/gold/dynobj.cc +++ b/gold/dynobj.cc @@ -1300,27 +1300,18 @@ Verneed::write(const Stringpool* dynpool, bool is_last, Versions::Versions(const Version_script_info& version_script, Stringpool* dynpool) : defs_(), needs_(), version_table_(), - is_finalized_(false), version_script_(version_script) + is_finalized_(false), version_script_(version_script), + needs_base_version_(parameters->options().shared()) { - // We always need a base version, so define that first. Nothing - // explicitly declares itself as part of base, so it doesn't need to - // be in version_table_. - if (parameters->options().shared()) - { - const char* name = parameters->options().soname(); - if (name == NULL) - name = parameters->options().output_file_name(); - name = dynpool->add(name, false, NULL); - Verdef* vdbase = new Verdef(name, std::vector(), - true, false, true); - this->defs_.push_back(vdbase); - } - if (!this->version_script_.empty()) { // Parse the version script, and insert each declared version into // defs_ and version_table_. std::vector versions = this->version_script_.get_versions(); + + if (this->needs_base_version_ && !versions.empty()) + this->define_base_version(dynpool); + for (size_t k = 0; k < versions.size(); ++k) { Stringpool::Key version_key; @@ -1350,6 +1341,28 @@ Versions::~Versions() delete *p; } +// Define the base version of a shared library. The base version definition +// must be the first entry in defs_. We insert it lazily so that defs_ is +// empty if no symbol versioning is used. Then layout can just drop the +// version sections. + +void +Versions::define_base_version(Stringpool* dynpool) +{ + // If we do any versioning at all, we always need a base version, so + // define that first. Nothing explicitly declares itself as part of base, + // so it doesn't need to be in version_table_. + gold_assert(this->defs_.empty()); + const char* name = parameters->options().soname(); + if (name == NULL) + name = parameters->options().output_file_name(); + name = dynpool->add(name, false, NULL); + Verdef* vdbase = new Verdef(name, std::vector(), + true, false, true); + this->defs_.push_back(vdbase); + this->needs_base_version_ = false; +} + // Return the dynamic object which a symbol refers to. Dynobj* @@ -1421,7 +1434,10 @@ Versions::add_def(const Symbol* sym, const char* version, if (parameters->options().shared()) gold_error(_("symbol %s has undefined version %s"), sym->demangled_name().c_str(), version); - + else + // We only insert a base version for shared library. + gold_assert(!this->needs_base_version_); + // When creating a regular executable, automatically define // a new version. Verdef* vd = new Verdef(version, std::vector(), @@ -1468,6 +1484,10 @@ Versions::add_need(Stringpool* dynpool, const char* filename, const char* name, if (vn == NULL) { + // Create base version definition lazily for shared library. + if (this->needs_base_version_) + this->define_base_version(dynpool); + // We have a new filename. vn = new Verneed(filename); this->needs_.push_back(vn); diff --git a/gold/dynobj.h b/gold/dynobj.h index 2768c83..66d2bff 100644 --- a/gold/dynobj.h +++ b/gold/dynobj.h @@ -584,6 +584,10 @@ class Versions version_index(const Symbol_table*, const Stringpool*, const Symbol* sym) const; + // Define the base version of a shared library. + void + define_base_version(Stringpool* dynpool); + // We keep a hash table mapping canonicalized name/version pairs to // a version base. typedef std::pair Key; @@ -616,6 +620,9 @@ class Versions bool is_finalized_; // Contents of --version-script, if passed, or NULL. const Version_script_info& version_script_; + // Whether we need to insert a base version. This is only used for + // shared libaries and is cleared when the base version is defined. + bool needs_base_version_; }; } // End namespace gold. diff --git a/gold/testsuite/Makefile.am b/gold/testsuite/Makefile.am index 6fa1e18..b343ca3 100644 --- a/gold/testsuite/Makefile.am +++ b/gold/testsuite/Makefile.am @@ -1249,6 +1249,20 @@ alt/searched_file_test_lib.a: searched_file_test_lib.o test -d alt || mkdir -p alt $(TEST_AR) rc $@ $^ +# Test that no .gnu.version sections are created when +# symbol versioning is not used. +check_SCRIPTS += no_version_test.sh +check_DATA += no_version_test.stdout +MOSTLYCLEANFILES += libno_version_test.so no_version_test.stdout +# We invoke the linker directly since gcc may include additional objects that +# uses symbol versioning. +libno_version_test.so: no_version_test.o gcctestdir/ld + gcctestdir/ld -shared -o $@ no_version_test.o +no_version_test.o: no_version_test.c + $(COMPILE) -o $@ -c -fPIC $< +no_version_test.stdout: libno_version_test.so + $(TEST_OBJDUMP) -h $< > $@ + endif GCC endif NATIVE_LINKER diff --git a/gold/testsuite/Makefile.in b/gold/testsuite/Makefile.in index 193888a..ed08580 100644 --- a/gold/testsuite/Makefile.in +++ b/gold/testsuite/Makefile.in @@ -354,14 +354,19 @@ check_PROGRAMS = object_unittest$(EXEEXT) binary_unittest$(EXEEXT) \ # referenced by a shared library. # Test -retain-symbols-file. + +# Test that no .gnu.version sections are created when +# symbol versioning is not used. @GCC_TRUE@@NATIVE_LINKER_TRUE@am__append_27 = exclude_libs_test.sh \ @GCC_TRUE@@NATIVE_LINKER_TRUE@ discard_locals_test.sh \ @GCC_TRUE@@NATIVE_LINKER_TRUE@ hidden_test.sh \ -@GCC_TRUE@@NATIVE_LINKER_TRUE@ retain_symbols_file_test.sh +@GCC_TRUE@@NATIVE_LINKER_TRUE@ retain_symbols_file_test.sh \ +@GCC_TRUE@@NATIVE_LINKER_TRUE@ no_version_test.sh @GCC_TRUE@@NATIVE_LINKER_TRUE@am__append_28 = exclude_libs_test.syms \ @GCC_TRUE@@NATIVE_LINKER_TRUE@ discard_locals_test.syms \ @GCC_TRUE@@NATIVE_LINKER_TRUE@ hidden_test.err \ -@GCC_TRUE@@NATIVE_LINKER_TRUE@ retain_symbols_file_test.stdout +@GCC_TRUE@@NATIVE_LINKER_TRUE@ retain_symbols_file_test.stdout \ +@GCC_TRUE@@NATIVE_LINKER_TRUE@ no_version_test.stdout @GCC_TRUE@@NATIVE_LINKER_TRUE@am__append_29 = exclude_libs_test.syms \ @GCC_TRUE@@NATIVE_LINKER_TRUE@ libexclude_libs_test_1.a \ @GCC_TRUE@@NATIVE_LINKER_TRUE@ libexclude_libs_test_2.a \ @@ -373,7 +378,9 @@ check_PROGRAMS = object_unittest$(EXEEXT) binary_unittest$(EXEEXT) \ @GCC_TRUE@@NATIVE_LINKER_TRUE@ retain_symbols_file_test.stdout \ @GCC_TRUE@@NATIVE_LINKER_TRUE@ searched_file_test \ @GCC_TRUE@@NATIVE_LINKER_TRUE@ searched_file_test_lib.o \ -@GCC_TRUE@@NATIVE_LINKER_TRUE@ alt/searched_file_test_lib.a +@GCC_TRUE@@NATIVE_LINKER_TRUE@ alt/searched_file_test_lib.a \ +@GCC_TRUE@@NATIVE_LINKER_TRUE@ libno_version_test.so \ +@GCC_TRUE@@NATIVE_LINKER_TRUE@ no_version_test.stdout @GCC_TRUE@@MCMODEL_MEDIUM_TRUE@@NATIVE_LINKER_TRUE@am__append_30 = large @GCC_FALSE@large_DEPENDENCIES = libgoldtest.a ../libgold.a \ @GCC_FALSE@ ../../libiberty/libiberty.a $(am__DEPENDENCIES_1) \ @@ -3104,6 +3111,14 @@ uninstall-am: @GCC_TRUE@@NATIVE_LINKER_TRUE@alt/searched_file_test_lib.a: searched_file_test_lib.o @GCC_TRUE@@NATIVE_LINKER_TRUE@ test -d alt || mkdir -p alt @GCC_TRUE@@NATIVE_LINKER_TRUE@ $(TEST_AR) rc $@ $^ +# We invoke the linker directly since gcc may include additional objects that +# uses symbol versioning. +@GCC_TRUE@@NATIVE_LINKER_TRUE@libno_version_test.so: no_version_test.o gcctestdir/ld +@GCC_TRUE@@NATIVE_LINKER_TRUE@ gcctestdir/ld -shared -o $@ no_version_test.o +@GCC_TRUE@@NATIVE_LINKER_TRUE@no_version_test.o: no_version_test.c +@GCC_TRUE@@NATIVE_LINKER_TRUE@ $(COMPILE) -o $@ -c -fPIC $< +@GCC_TRUE@@NATIVE_LINKER_TRUE@no_version_test.stdout: libno_version_test.so +@GCC_TRUE@@NATIVE_LINKER_TRUE@ $(TEST_OBJDUMP) -h $< > $@ @DEFAULT_TARGET_I386_TRUE@split_i386_1.o: split_i386_1.s @DEFAULT_TARGET_I386_TRUE@ $(TEST_AS) -o $@ $< @DEFAULT_TARGET_I386_TRUE@split_i386_2.o: split_i386_2.s diff --git a/gold/testsuite/no_version_test.c b/gold/testsuite/no_version_test.c new file mode 100644 index 0000000..e42d04f --- /dev/null +++ b/gold/testsuite/no_version_test.c @@ -0,0 +1,32 @@ +// ver_no_default.c -- a test case for gold + +// Copyright 2009 Free Software Foundation, Inc. +// Written by Doug Kwan . + +// 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. + +// We should not create any .gnu.version sections if symbol versioning +// is not used. + +extern int the_answer(void); + +int +the_answer(void) +{ + return 42; +} diff --git a/gold/testsuite/no_version_test.sh b/gold/testsuite/no_version_test.sh new file mode 100755 index 0000000..f4ca9b1 --- /dev/null +++ b/gold/testsuite/no_version_test.sh @@ -0,0 +1,45 @@ +#!/bin/sh + +# no_version_test.sh -- test that .gnu.version* sections are not created +# in a shared object when symbol versioning is not used. + +# Copyright 2009 Free Software Foundation, Inc. +# Written by Doug Kwan + +# 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 file goes with no_version_test.c, a C source file +# linked with option -shared -nostdlib. We run objdump on +# the resulting executable and check that .gnu.version* sections +# are not created. + +check() +{ + file=$1 + + found=`egrep "\.gnu\.version.*" $file` + if test -n "$found"; then + echo "These section should not be in $file:" + echo "$found" + exit 1 + fi +} + +check "no_version_test.stdout" + +exit 0 -- 2.7.4