diff options
-rw-r--r-- | gold/ChangeLog | 21 | ||||
-rw-r--r-- | gold/script.cc | 27 | ||||
-rw-r--r-- | gold/script.h | 28 | ||||
-rw-r--r-- | gold/symtab.cc | 83 | ||||
-rw-r--r-- | gold/testsuite/Makefile.am | 7 | ||||
-rw-r--r-- | gold/testsuite/Makefile.in | 8 | ||||
-rw-r--r-- | gold/testsuite/ver_test_10.script | 30 | ||||
-rwxr-xr-x | gold/testsuite/ver_test_10.sh | 44 |
8 files changed, 182 insertions, 66 deletions
diff --git a/gold/ChangeLog b/gold/ChangeLog index cb28b25..dca8a51 100644 --- a/gold/ChangeLog +++ b/gold/ChangeLog @@ -1,3 +1,24 @@ +2008-07-23 Ian Lance Taylor <iant@google.com> + + PR 6647 + * script.cc (Version_script_info::get_versions): Don't add empty + version tag to return value. + (Version_script_info::get_symbol_version_helper): Change return + type to bool. Add pversion parameter. Change all callers. + (script_register_vers_node): Don't require a non-NULL tag. + * script.h (class Version_script_info): Update declarations. + (Version_script_info::get_symbol_version): Change return type to + bool. Add version parameter. Change all callers. + * symtab.cc (Sized_symbol::add_from_relobj): Rework version + handling. Handle an empty version from a version script. + (Symbol_table::define_special_symbol): Likewise. + * testsuite/ver_test_10.script: New file. + * testsuite/ver_test_10.sh: New file. + * testsuite/Makefile.am (check_SCRIPTS): Add ver_test_10.sh. + (check_DATA): Add ver_test_10.syms. + (ver_test_10.syms, ver_test_10.so): New target. + * testsuite/Makefile.in: Rebuild. + 2008-07-23 Simon Baldwin <simonb@google.com> * symtab.cc (Symbol_table::sized_write_symbol): Only set st_size diff --git a/gold/script.cc b/gold/script.cc index 55cd4e6..4bfe33c 100644 --- a/gold/script.cc +++ b/gold/script.cc @@ -1732,7 +1732,8 @@ Version_script_info::get_versions() const { std::vector<std::string> ret; for (size_t j = 0; j < version_trees_.size(); ++j) - ret.push_back(version_trees_[j]->tag); + if (!this->version_trees_[j]->tag.empty()) + ret.push_back(this->version_trees_[j]->tag); return ret; } @@ -1753,9 +1754,16 @@ Version_script_info::get_dependencies(const char* version) const return ret; } -const std::string& +// Look up SYMBOL_NAME in the list of versions. If CHECK_GLOBAL is +// true look at the globally visible symbols, otherwise look at the +// symbols listed as "local:". Return true if the symbol is found, +// false otherwise. If the symbol is found, then if PVERSION is not +// NULL, set *PVERSION to the version. + +bool Version_script_info::get_symbol_version_helper(const char* symbol_name, - bool check_global) const + bool check_global, + std::string* pversion) const { for (size_t j = 0; j < version_trees_.size(); ++j) { @@ -1796,11 +1804,14 @@ Version_script_info::get_symbol_version_helper(const char* symbol_name, if (demangled_name != NULL) free(demangled_name); if (matched) - return version_trees_[j]->tag; + { + if (pversion != NULL) + *pversion = this->version_trees_[j]->tag; + return true; + } } } - static const std::string empty = ""; - return empty; + return false; } struct Version_dependency_list* @@ -2207,9 +2218,9 @@ script_register_vers_node(void*, struct Version_dependency_list *deps) { gold_assert(tree != NULL); - gold_assert(tag != NULL); tree->dependencies = deps; - tree->tag = std::string(tag, taglen); + if (tag != NULL) + tree->tag = std::string(tag, taglen); } // Add a dependencies to the list of existing dependencies, if any, diff --git a/gold/script.h b/gold/script.h index ea4b6af..e688a74 100644 --- a/gold/script.h +++ b/gold/script.h @@ -138,22 +138,17 @@ class Version_script_info empty() const { return this->version_trees_.empty(); } - // Return the version associated with the given symbol name. - // Strings are allocated out of the stringpool given in the - // constructor. Strings are allocated out of the stringpool given - // in the constructor. - const std::string& - get_symbol_version(const char* symbol) const - { return get_symbol_version_helper(symbol, true); } - - // Return whether this symbol matches the local: section of a - // version script (it doesn't matter which). + // If there is a version associated with SYMBOL, return true, and + // set *VERSION to the version. Otherwise, return false. + bool + get_symbol_version(const char* symbol, std::string* version) const + { return this->get_symbol_version_helper(symbol, true, version); } + + // Return whether this symbol matches the local: section of some + // version. bool symbol_is_local(const char* symbol) const - { - return (get_symbol_version(symbol).empty() - && !get_symbol_version_helper(symbol, false).empty()); - } + { return this->get_symbol_version_helper(symbol, false, NULL); } // Return the names of versions defined in the version script. // Strings are allocated out of the stringpool given in the @@ -186,8 +181,9 @@ class Version_script_info void print_expression_list(FILE* f, const Version_expression_list*) const; - const std::string& get_symbol_version_helper(const char* symbol, - bool check_global) const; + bool get_symbol_version_helper(const char* symbol, + bool check_global, + std::string* pversion) const; std::vector<struct Version_dependency_list*> dependency_lists_; std::vector<struct Version_expression_list*> expression_lists_; diff --git a/gold/symtab.cc b/gold/symtab.cc index 259004e..c8a5037 100644 --- a/gold/symtab.cc +++ b/gold/symtab.cc @@ -885,6 +885,7 @@ Symbol_table::add_from_relobj( // name from the version name. If there are two '@' characters, // this is the default version. const char* ver = strchr(name, '@'); + Stringpool::Key ver_key = 0; int namelen = 0; // DEF: is the version default? LOCAL: is the symbol forced local? bool def = false; @@ -900,26 +901,37 @@ Symbol_table::add_from_relobj( def = true; ++ver; } + ver = this->namepool_.add(ver, true, &ver_key); } // We don't want to assign a version to an undefined symbol, // even if it is listed in the version script. FIXME: What // about a common symbol? - else if (!version_script_.empty() - && st_shndx != elfcpp::SHN_UNDEF) - { - // The symbol name did not have a version, but - // the version script may assign a version anyway. - namelen = strlen(name); - def = true; - // Check the global: entries from the version script. - const std::string& version = - version_script_.get_symbol_version(name); - if (!version.empty()) - ver = version.c_str(); - // Check the local: entries from the version script - if (version_script_.symbol_is_local(name)) - local = true; - } + else + { + namelen = strlen(name); + if (!this->version_script_.empty() + && st_shndx != elfcpp::SHN_UNDEF) + { + // The symbol name did not have a version, but the + // version script may assign a version anyway. + std::string version; + if (this->version_script_.get_symbol_version(name, &version)) + { + // The version can be empty if the version script is + // only used to force some symbols to be local. + if (!version.empty()) + { + ver = this->namepool_.add_with_length(version.c_str(), + version.length(), + true, + &ver_key); + def = true; + } + } + else if (this->version_script_.symbol_is_local(name)) + local = true; + } + } elfcpp::Sym<size, big_endian>* psym = &sym; unsigned char symbuf[sym_size]; @@ -944,29 +956,17 @@ Symbol_table::add_from_relobj( psym = &sym2; } + Stringpool::Key name_key; + name = this->namepool_.add_with_length(name, namelen, true, + &name_key); + Sized_symbol<size>* res; - if (ver == NULL) - { - Stringpool::Key name_key; - name = this->namepool_.add(name, true, &name_key); - res = this->add_from_object(relobj, name, name_key, NULL, 0, - false, *psym, st_shndx, is_ordinary, - orig_st_shndx); - if (local) - this->force_local(res); - } - else - { - Stringpool::Key name_key; - name = this->namepool_.add_with_length(name, namelen, true, - &name_key); - Stringpool::Key ver_key; - ver = this->namepool_.add(ver, true, &ver_key); + res = this->add_from_object(relobj, name, name_key, ver, ver_key, + def, *psym, st_shndx, is_ordinary, + orig_st_shndx); - res = this->add_from_object(relobj, name, name_key, ver, ver_key, - def, *psym, st_shndx, is_ordinary, - orig_st_shndx); - } + if (local) + this->force_local(res); (*sympointers)[i] = res; } @@ -1270,11 +1270,14 @@ Symbol_table::define_special_symbol(const char** pname, const char** pversion, // If the caller didn't give us a version, see if we get one from // the version script. + std::string v; if (*pversion == NULL) { - const std::string& v(this->version_script_.get_symbol_version(*pname)); - if (!v.empty()) - *pversion = v.c_str(); + if (this->version_script_.get_symbol_version(*pname, &v)) + { + if (!v.empty()) + *pversion = v.c_str(); + } } if (only_if_ref) diff --git a/gold/testsuite/Makefile.am b/gold/testsuite/Makefile.am index 8e4ae0d..9c91c24 100644 --- a/gold/testsuite/Makefile.am +++ b/gold/testsuite/Makefile.am @@ -784,6 +784,13 @@ ver_test_9.so: ver_test_9.o ver_test_4.so ver_test_5.so gcctestdir/ld ver_test_9.o: ver_test_9.cc $(CXXCOMPILE) -c -fpic -o $@ $< +check_SCRIPTS += ver_test_10.sh +check_DATA += ver_test_10.syms +ver_test_10.syms: ver_test_10.so + $(TEST_READELF) -s $< >$@ 2>/dev/null +ver_test_10.so: gcctestdir/ld ver_test_2.o ver_test_10.script + $(CXXLINK) -Bgcctestdir/ -shared -Wl,--version-script,$(srcdir)/ver_test_10.script ver_test_2.o + check_PROGRAMS += protected_1 protected_1_SOURCES = \ protected_main_1.cc protected_main_2.cc protected_main_3.cc diff --git a/gold/testsuite/Makefile.in b/gold/testsuite/Makefile.in index beec5be..29fad42 100644 --- a/gold/testsuite/Makefile.in +++ b/gold/testsuite/Makefile.in @@ -186,7 +186,7 @@ check_PROGRAMS = object_unittest$(EXEEXT) binary_unittest$(EXEEXT) \ @GCC_TRUE@@NATIVE_LINKER_TRUE@am__append_14 = debug_msg.sh \ @GCC_TRUE@@NATIVE_LINKER_TRUE@ undef_symbol.sh ver_test_2.sh \ @GCC_TRUE@@NATIVE_LINKER_TRUE@ ver_test_4.sh ver_test_5.sh \ -@GCC_TRUE@@NATIVE_LINKER_TRUE@ ver_test_7.sh \ +@GCC_TRUE@@NATIVE_LINKER_TRUE@ ver_test_7.sh ver_test_10.sh \ @GCC_TRUE@@NATIVE_LINKER_TRUE@ ver_matching_test.sh \ @GCC_TRUE@@NATIVE_LINKER_TRUE@ script_test_3.sh \ @GCC_TRUE@@NATIVE_LINKER_TRUE@ script_test_4.sh @@ -202,7 +202,7 @@ check_PROGRAMS = object_unittest$(EXEEXT) binary_unittest$(EXEEXT) \ @GCC_TRUE@@NATIVE_LINKER_TRUE@ debug_msg_ndebug.err \ @GCC_TRUE@@NATIVE_LINKER_TRUE@ undef_symbol.err ver_test_2.syms \ @GCC_TRUE@@NATIVE_LINKER_TRUE@ ver_test_4.syms ver_test_5.syms \ -@GCC_TRUE@@NATIVE_LINKER_TRUE@ ver_test_7.syms \ +@GCC_TRUE@@NATIVE_LINKER_TRUE@ ver_test_7.syms ver_test_10.syms \ @GCC_TRUE@@NATIVE_LINKER_TRUE@ ver_matching_test.stdout \ @GCC_TRUE@@NATIVE_LINKER_TRUE@ script_test_3.stdout \ @GCC_TRUE@@NATIVE_LINKER_TRUE@ script_test_4.stdout @@ -2234,6 +2234,10 @@ uninstall-am: uninstall-info-am @GCC_TRUE@@NATIVE_LINKER_TRUE@ $(CXXLINK) -Bgcctestdir/ -shared ver_test_9.o ver_test_5.so ver_test_4.so @GCC_TRUE@@NATIVE_LINKER_TRUE@ver_test_9.o: ver_test_9.cc @GCC_TRUE@@NATIVE_LINKER_TRUE@ $(CXXCOMPILE) -c -fpic -o $@ $< +@GCC_TRUE@@NATIVE_LINKER_TRUE@ver_test_10.syms: ver_test_10.so +@GCC_TRUE@@NATIVE_LINKER_TRUE@ $(TEST_READELF) -s $< >$@ 2>/dev/null +@GCC_TRUE@@NATIVE_LINKER_TRUE@ver_test_10.so: gcctestdir/ld ver_test_2.o ver_test_10.script +@GCC_TRUE@@NATIVE_LINKER_TRUE@ $(CXXLINK) -Bgcctestdir/ -shared -Wl,--version-script,$(srcdir)/ver_test_10.script ver_test_2.o @GCC_TRUE@@NATIVE_LINKER_TRUE@protected_1.so: gcctestdir/ld protected_1_pic.o protected_2_pic.o protected_3_pic.o @GCC_TRUE@@NATIVE_LINKER_TRUE@ $(CXXLINK) -Bgcctestdir/ -shared protected_1_pic.o protected_2_pic.o protected_3_pic.o diff --git a/gold/testsuite/ver_test_10.script b/gold/testsuite/ver_test_10.script new file mode 100644 index 0000000..fa9f175 --- /dev/null +++ b/gold/testsuite/ver_test_10.script @@ -0,0 +1,30 @@ +## ver_test_10.script -- a test case for gold + +## Copyright 2008 Free Software Foundation, Inc. +## Written by Ian Lance Taylor <iant@google.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. + +# Test having a version script with no version. + +{ + global: + t3_2; + local: + *; +}; diff --git a/gold/testsuite/ver_test_10.sh b/gold/testsuite/ver_test_10.sh new file mode 100755 index 0000000..68138a6 --- /dev/null +++ b/gold/testsuite/ver_test_10.sh @@ -0,0 +1,44 @@ +#!/bin/sh + +# ver_test_10.sh -- test global/local symbols + +# Copyright 2008 Free Software Foundation, Inc. +# Written by Ian Lance Taylor <iant@google.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. + +# This file goes with ver_test_4.script and ver_test_5.script. The +# symbol t2_2 is not defined when ver_test_5.script is used. + +check() +{ + if ! grep -q "$2" "$1" + then + echo "Did not find expected symbol in $1:" + echo " $2" + echo "" + echo "Actual output below:" + cat "$1" + exit 1 + fi +} + +check ver_test_10.syms "GLOBAL.*t3_2" +check ver_test_10.syms "LOCAL.*t4_2" + +exit 0 |