From 0602e05a845a545a8b52386a4dec66b74a158bc7 Mon Sep 17 00:00:00 2001 From: Ian Lance Taylor Date: Fri, 27 Feb 2009 19:57:46 +0000 Subject: [PATCH] PR 9836 * symtab.cc (Symbol_table::add_from_object): If the visibility is hidden or internal, force the symbol to be local. * resolve.cc (Symbol::override_visibility): Define. (Symbol::override_base): Use override_visibility. (Symbol_table::resolve): Likewise. (Symbol::override_base_with_special): Likewise. (Symbol_table::override_with_special): If the visibility is hidden or internal, force the symbol to be local. * symtab.h (class Symbol): Add set_visibility and override_visibility. * testsuite/ver_test_1.sh: New file. * testsuite/Makefile.am (check_SCRIPTS): Add ver_test_1.sh. (check_DATA): Add ver_test_1.syms. (ver_test_1.syms): New target. * testsuite/Makefile.in: Rebuild. --- gold/ChangeLog | 19 +++++++++++++++++++ gold/resolve.cc | 36 ++++++++++++++++++++++++++++++++---- gold/symtab.cc | 14 ++++++++++++-- gold/symtab.h | 14 ++++++++++++-- gold/testsuite/Makefile.am | 5 +++++ gold/testsuite/Makefile.in | 16 ++++++++++------ gold/testsuite/ver_test_1.sh | 30 ++++++++++++++++++++++++++++++ 7 files changed, 120 insertions(+), 14 deletions(-) create mode 100755 gold/testsuite/ver_test_1.sh diff --git a/gold/ChangeLog b/gold/ChangeLog index 8630e5016bd..51592553312 100644 --- a/gold/ChangeLog +++ b/gold/ChangeLog @@ -1,3 +1,22 @@ +2009-02-27 Ian Lance Taylor + + PR 9836 + * symtab.cc (Symbol_table::add_from_object): If the visibility is + hidden or internal, force the symbol to be local. + * resolve.cc (Symbol::override_visibility): Define. + (Symbol::override_base): Use override_visibility. + (Symbol_table::resolve): Likewise. + (Symbol::override_base_with_special): Likewise. + (Symbol_table::override_with_special): If the visibility is hidden + or internal, force the symbol to be local. + * symtab.h (class Symbol): Add set_visibility and + override_visibility. + * testsuite/ver_test_1.sh: New file. + * testsuite/Makefile.am (check_SCRIPTS): Add ver_test_1.sh. + (check_DATA): Add ver_test_1.syms. + (ver_test_1.syms): New target. + * testsuite/Makefile.in: Rebuild. + 2009-02-25 Cary Coutant * layout.cc (Layout::choose_output_section): Don't rename sections diff --git a/gold/resolve.cc b/gold/resolve.cc index 17544f82a5c..bd327e88a58 100644 --- a/gold/resolve.cc +++ b/gold/resolve.cc @@ -1,6 +1,6 @@ // resolve.cc -- symbol resolution for gold -// Copyright 2006, 2007, 2008 Free Software Foundation, Inc. +// Copyright 2006, 2007, 2008, 2009 Free Software Foundation, Inc. // Written by Ian Lance Taylor . // This file is part of gold. @@ -63,6 +63,26 @@ Symbol::override_version(const char* version) } } +// This symbol is being overidden by another symbol whose visibility +// is VISIBILITY. Updated the VISIBILITY_ field accordingly. + +inline void +Symbol::override_visibility(elfcpp::STV visibility) +{ + // The rule for combining visibility is that we always choose the + // most constrained visibility. In order of increasing constraint, + // visibility goes PROTECTED, HIDDEN, INTERNAL. This is the reverse + // of the numeric values, so the effect is that we always want the + // smallest non-zero value. + if (visibility != elfcpp::STV_DEFAULT) + { + if (this->visibility_ == elfcpp::STV_DEFAULT) + this->visibility_ = visibility; + else if (this->visibility_ > visibility) + this->visibility_ = visibility; + } +} + // Override the fields in Symbol. template @@ -78,7 +98,7 @@ Symbol::override_base(const elfcpp::Sym& sym, this->is_ordinary_shndx_ = is_ordinary; this->type_ = sym.get_st_type(); this->binding_ = sym.get_st_bind(); - this->visibility_ = sym.get_st_visibility(); + this->override_visibility(sym.get_st_visibility()); this->nonvis_ = sym.get_st_nonvis(); if (object->is_dynamic()) this->in_dyn_ = true; @@ -279,6 +299,9 @@ Symbol_table::resolve(Sized_symbol* to, { if (adjust_common_sizes && sym.get_st_size() > to->symsize()) to->set_symsize(sym.get_st_size()); + // The ELF ABI says that even for a reference to a symbol we + // merge the visibility. + to->override_visibility(sym.get_st_visibility()); } // A new weak undefined reference, merging with an old weak @@ -721,7 +744,7 @@ Symbol::override_base_with_special(const Symbol* from) this->override_version(from->version_); this->type_ = from->type_; this->binding_ = from->binding_; - this->visibility_ = from->visibility_; + this->override_visibility(from->visibility_); this->nonvis_ = from->nonvis_; // Special symbols are always considered to be regular symbols. @@ -776,7 +799,12 @@ Symbol_table::override_with_special(Sized_symbol* tosym, } while (ssym != tosym); } - if (tosym->binding() == elfcpp::STB_LOCAL) + if (tosym->binding() == elfcpp::STB_LOCAL + || ((tosym->visibility() == elfcpp::STV_HIDDEN + || tosym->visibility() == elfcpp::STV_INTERNAL) + && (tosym->binding() == elfcpp::STB_GLOBAL + || tosym->binding() == elfcpp::STB_WEAK) + && !parameters->options().relocatable())) this->force_local(tosym); } diff --git a/gold/symtab.cc b/gold/symtab.cc index 54083850925..dcbb46e20da 100644 --- a/gold/symtab.cc +++ b/gold/symtab.cc @@ -648,7 +648,8 @@ Symbol_table::resolve(Sized_symbol* to, const Sized_symbol* from) this->gc_mark_dyn_syms(to); } -// Record that a symbol is forced to be local by a version script. +// Record that a symbol is forced to be local by a version script or +// by visibility. void Symbol_table::force_local(Symbol* sym) @@ -962,6 +963,15 @@ Symbol_table::add_from_object(Object* object, this->tls_commons_.push_back(ret); } + // If we're not doing a relocatable link, then any symbol with + // hidden or internal visibility is local. + if ((ret->visibility() == elfcpp::STV_HIDDEN + || ret->visibility() == elfcpp::STV_INTERNAL) + && (ret->binding() == elfcpp::STB_GLOBAL + || ret->binding() == elfcpp::STB_WEAK) + && !parameters->options().relocatable()) + this->force_local(ret); + if (def) ret->set_is_default(); return ret; @@ -1179,7 +1189,7 @@ Symbol_table::add_from_pluginobj( def, *sym, st_shndx, true, st_shndx); if (local) - this->force_local(res); + this->force_local(res); return res; } diff --git a/gold/symtab.h b/gold/symtab.h index 358dd32f794..b504d0a833a 100644 --- a/gold/symtab.h +++ b/gold/symtab.h @@ -1,6 +1,6 @@ // symtab.h -- the gold symbol table -*- C++ -*- -// Copyright 2006, 2007, 2008 Free Software Foundation, Inc. +// Copyright 2006, 2007, 2008, 2009 Free Software Foundation, Inc. // Written by Ian Lance Taylor . // This file is part of gold. @@ -210,6 +210,15 @@ class Symbol visibility() const { return this->visibility_; } + // Set the visibility. + void + set_visibility(elfcpp::STV visibility) + { this->visibility_ = visibility; } + + // Override symbol visibility. + void + override_visibility(elfcpp::STV); + // Return the non-visibility part of the st_other field. unsigned char nonvis() const @@ -1384,7 +1393,8 @@ class Symbol_table void resolve(Sized_symbol* to, const Sized_symbol* from); - // Record that a symbol is forced to be local by a version script. + // Record that a symbol is forced to be local by a version script or + // by visibility. void force_local(Symbol*); diff --git a/gold/testsuite/Makefile.am b/gold/testsuite/Makefile.am index 46c661f05a8..1ba7c9dd393 100644 --- a/gold/testsuite/Makefile.am +++ b/gold/testsuite/Makefile.am @@ -742,6 +742,11 @@ ver_test_3.o: ver_test_3.cc ver_test_4.o: ver_test_4.cc $(CXXCOMPILE) -c -fpic -o $@ $< +check_SCRIPTS += ver_test_1.sh +check_DATA += ver_test_1.syms +ver_test_1.syms: ver_test_1.so + $(TEST_READELF) -s $< >$@ 2>/dev/null + check_PROGRAMS += ver_test_2 ver_test_2_SOURCES = ver_test_main_2.cc ver_test_2_DEPENDENCIES = gcctestdir/ld ver_test_4.so ver_test_2.so diff --git a/gold/testsuite/Makefile.in b/gold/testsuite/Makefile.in index 6703f6f6698..9f0cfcbbfb0 100644 --- a/gold/testsuite/Makefile.in +++ b/gold/testsuite/Makefile.in @@ -166,9 +166,10 @@ check_PROGRAMS = object_unittest$(EXEEXT) binary_unittest$(EXEEXT) \ # Test --dynamic-list, --dynamic-list-data, --dynamic-list-cpp-new, # and --dynamic-list-cpp-typeinfo @GCC_TRUE@@NATIVE_LINKER_TRUE@am__append_6 = weak_plt.sh 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 ver_test_10.sh \ +@GCC_TRUE@@NATIVE_LINKER_TRUE@ undef_symbol.sh ver_test_1.sh \ +@GCC_TRUE@@NATIVE_LINKER_TRUE@ ver_test_2.sh ver_test_4.sh \ +@GCC_TRUE@@NATIVE_LINKER_TRUE@ ver_test_5.sh ver_test_7.sh \ +@GCC_TRUE@@NATIVE_LINKER_TRUE@ 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 \ @@ -183,9 +184,10 @@ check_PROGRAMS = object_unittest$(EXEEXT) binary_unittest$(EXEEXT) \ @GCC_TRUE@@NATIVE_LINKER_TRUE@am__append_7 = weak_plt_shared.so \ @GCC_TRUE@@NATIVE_LINKER_TRUE@ debug_msg.err debug_msg_so.err \ @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 ver_test_10.syms \ +@GCC_TRUE@@NATIVE_LINKER_TRUE@ undef_symbol.err ver_test_1.syms \ +@GCC_TRUE@@NATIVE_LINKER_TRUE@ ver_test_2.syms ver_test_4.syms \ +@GCC_TRUE@@NATIVE_LINKER_TRUE@ ver_test_5.syms ver_test_7.syms \ +@GCC_TRUE@@NATIVE_LINKER_TRUE@ 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 \ @@ -2404,6 +2406,8 @@ uninstall-am: uninstall-info-am @GCC_TRUE@@NATIVE_LINKER_TRUE@ $(CXXCOMPILE) -c -fpic -o $@ $< @GCC_TRUE@@NATIVE_LINKER_TRUE@ver_test_4.o: ver_test_4.cc @GCC_TRUE@@NATIVE_LINKER_TRUE@ $(CXXCOMPILE) -c -fpic -o $@ $< +@GCC_TRUE@@NATIVE_LINKER_TRUE@ver_test_1.syms: ver_test_1.so +@GCC_TRUE@@NATIVE_LINKER_TRUE@ $(TEST_READELF) -s $< >$@ 2>/dev/null @GCC_TRUE@@NATIVE_LINKER_TRUE@ver_test_2.syms: ver_test_2 @GCC_TRUE@@NATIVE_LINKER_TRUE@ $(TEST_READELF) -s $< >$@ 2>/dev/null @GCC_TRUE@@NATIVE_LINKER_TRUE@ver_test_4.syms: ver_test_4.so diff --git a/gold/testsuite/ver_test_1.sh b/gold/testsuite/ver_test_1.sh new file mode 100755 index 00000000000..edf73518b77 --- /dev/null +++ b/gold/testsuite/ver_test_1.sh @@ -0,0 +1,30 @@ +#!/bin/sh + +# ver_test_1.sh -- check that protected symbols are local + +# Copyright 2009 Free Software Foundation, Inc. +# Written by Ian Lance Taylor . + +# 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. + +syms=`grep ' HIDDEN ' ver_test_1.syms | grep ' GLOBAL '` +if test -n "$syms"; then + echo "Found GLOBAL HIDDEN symbols" + echo $syms + exit 1 +fi -- 2.30.2