diff --git a/gold/resolve.cc b/gold/resolve.cc index 8f4d2e3..c220de0 100644 --- a/gold/resolve.cc +++ b/gold/resolve.cc @@ -298,6 +298,10 @@ Symbol_table::resolve(Sized_symbol* to, { // Record that we've seen this symbol in a dynamic object. to->set_in_dyn(); + if (st_shndx != elfcpp::SHN_UNDEF) + to->set_is_defined_in_dyn(); + else if (sym.get_st_bind() != elfcpp::STB_WEAK) + to->set_is_ref_dynamic_nonweak(); } // Record if we've seen this symbol in a real ELF object (i.e., the diff --git a/gold/symtab.cc b/gold/symtab.cc index 43909ff..8aff8e1 100644 --- a/gold/symtab.cc +++ b/gold/symtab.cc @@ -81,6 +81,8 @@ Symbol::init_fields(const char* name, const char* version, this->undef_binding_weak_ = false; this->is_predefined_ = false; this->is_protected_ = false; + this->is_defined_in_dyn_ = false; + this->is_ref_dynamic_nonweak_ = false; } // Return the demangled version of the symbol's name, but only @@ -126,6 +128,11 @@ Symbol::init_base_object(const char* name, const char* version, Object* object, this->in_reg_ = !object->is_dynamic(); this->in_dyn_ = object->is_dynamic(); this->in_real_elf_ = object->pluginobj() == NULL; + this->is_defined_in_dyn_ = object->is_dynamic() + && st_shndx != elfcpp::SHN_UNDEF; + this->is_ref_dynamic_nonweak_ = object->is_dynamic() + && st_shndx == elfcpp::SHN_UNDEF + && sym.get_st_bind() != elfcpp::STB_WEAK; } // Initialize the fields in the base class Symbol for a symbol defined @@ -3021,6 +3028,14 @@ Symbol_table::sized_write_globals(const Stringpool* sympool, else dynamic_view = of->get_output_view(this->dynamic_offset_, dynamic_size); + if (parameters->options().output_is_executable()) + { + for (Forced_locals::const_iterator p = this->forced_locals_.begin(); + p != this->forced_locals_.end(); + ++p) + this->warn_about_forced_local_dynobj_ref_symbol(*p); + } + for (Symbol_table_type::const_iterator p = this->table_.begin(); p != this->table_.end(); ++p) @@ -3323,6 +3338,26 @@ Symbol_table::warn_about_undefined_dynobj_symbol(Symbol* sym) const } } +// Check for forced local symbols which are referenced by shared libraries. + +// If the symbol is defined in another DSO, the requirement might be +// satisfied in that way, so we don't issue the error in that case. + +inline void +Symbol_table::warn_about_forced_local_dynobj_ref_symbol(Symbol* sym) const +{ + gold_assert(sym->is_forced_local()); + if (sym->source() == Symbol::FROM_OBJECT + && !sym->object()->is_dynamic() + && sym->is_ref_dynamic_nonweak() + && !sym->is_defined_in_dyn()) + { + gold_error("local symbol '%s' in %s is referenced by DSO.", + sym->demangled_name().c_str(), + sym->object()->name().c_str()); + } +} + // Write out a section symbol. Return the update offset. void diff --git a/gold/symtab.h b/gold/symtab.h index 46c7fce..1bc7a52 100644 --- a/gold/symtab.h +++ b/gold/symtab.h @@ -883,6 +883,25 @@ class Symbol set_is_protected() { this->is_protected_ = true; } + // Return true if this symbol is defined in a shared object and can + // be used by another object to satisfy a reference. + bool + is_defined_in_dyn() const + { return this->is_defined_in_dyn_; } + + // Mark this symbol as defined in a shared object. + void set_is_defined_in_dyn() + { this->is_defined_in_dyn_ = true; } + + // Return true if this symbol has a non-weak reference from a shared object. + bool + is_ref_dynamic_nonweak() const + { return this->is_ref_dynamic_nonweak_; } + + // Mark this symbol as strongly referenced from a shared object. + void set_is_ref_dynamic_nonweak() + { this->is_ref_dynamic_nonweak_ = true; } + protected: // Instances of this class should always be created at a specific // size. @@ -1084,6 +1103,11 @@ class Symbol // The visibility_ field will be STV_DEFAULT in this case because we // must treat it as such from outside the shared object. bool is_protected_ : 1; + // True if this symbol is defined in a dynamic object and can be used + // to satisfy a reference from another dynamic object (bit 36). + bool is_defined_in_dyn_ : 1; + // True if this symbol has a non-weak reference from a DSO (bit 37). + bool is_ref_dynamic_nonweak_ : 1; }; // The parts of a symbol which are size specific. Using a template @@ -1904,6 +1928,10 @@ class Symbol_table void warn_about_undefined_dynobj_symbol(Symbol*) const; + // Possibly warn about a forced local symbol referenced by a DSO. + void + warn_about_forced_local_dynobj_ref_symbol(Symbol*) const; + // Write out a section symbol, specialized for size and endianness. template void diff --git a/gold/testsuite/Makefile.am b/gold/testsuite/Makefile.am index d0803d2..d0cd476 100644 --- a/gold/testsuite/Makefile.am +++ b/gold/testsuite/Makefile.am @@ -3096,6 +3096,42 @@ script_test_10: $(srcdir)/script_test_10.t script_test_10.o gcctestdir/ld script_test_10.stdout: script_test_10 $(TEST_READELF) -SW script_test_10 > $@ +check_SCRIPTS += ver_test_14a.sh +check_DATA += ver_test_14a.err +MOSTLYCLEANFILES += ver_test_14a.err +ver_test_14a.err: $(srcdir)/ver_test_14.script ver_test_14_main.o ver_test_14_ref.so gcctestdir/ld + @if gcctestdir/ld -o ver_test_14a --version-script $(srcdir)/ver_test_14.script ver_test_14_main.o ver_test_14_ref.so 2>$@; \ + then \ + echo 1>&2 "Link of ver_test_14a should have failed"; \ + rm -f $@; \ + exit 1; \ + fi + +check_DATA += ver_test_14b +MOSTLYCLEANFILES += ver_test_14b +ver_test_14b: $(srcdir)/ver_test_14.script ver_test_14_main.o ver_test_14_ref_weak.so gcctestdir/ld + gcctestdir/ld -o $@ --version-script $(srcdir)/ver_test_14.script ver_test_14_main.o ver_test_14_ref_weak.so + +check_DATA += ver_test_14c +MOSTLYCLEANFILES += ver_test_14c +ver_test_14c: $(srcdir)/ver_test_14.script ver_test_14_main.o ver_test_14_ref.so ver_test_14_def.so gcctestdir/ld + gcctestdir/ld -o $@ --version-script $(srcdir)/ver_test_14.script ver_test_14_main.o ver_test_14_ref.so ver_test_14_def.so + +ver_test_14_main.o: ver_test_14_main.s + $(TEST_AS) -o $@ $< +ver_test_14_ref.o: ver_test_14_ref.s + $(TEST_AS) -o $@ $< +ver_test_14_ref_weak.o: ver_test_14_ref_weak.s + $(TEST_AS) -o $@ $< +ver_test_14_def.o: ver_test_14_def.s + $(TEST_AS) -o $@ $< +ver_test_14_ref.so: ver_test_14_ref.o gcctestdir/ld + gcctestdir/ld -shared -o $@ $< +ver_test_14_ref_weak.so: ver_test_14_ref_weak.o gcctestdir/ld + gcctestdir/ld -shared -o $@ $< +ver_test_14_def.so: ver_test_14_def.o gcctestdir/ld + gcctestdir/ld -shared -o $@ $< + # These tests work with cross linkers only. if DEFAULT_TARGET_I386 diff --git a/gold/testsuite/Makefile.in b/gold/testsuite/Makefile.in index 133e733..a5fd044 100644 --- a/gold/testsuite/Makefile.in +++ b/gold/testsuite/Makefile.in @@ -807,9 +807,14 @@ check_PROGRAMS = $(am__EXEEXT_1) $(am__EXEEXT_2) $(am__EXEEXT_3) \ # These tests work with native and cross linkers. # Test script section order. -@NATIVE_OR_CROSS_LINKER_TRUE@am__append_84 = script_test_10.sh -@NATIVE_OR_CROSS_LINKER_TRUE@am__append_85 = script_test_10.stdout -@NATIVE_OR_CROSS_LINKER_TRUE@am__append_86 = script_test_10 +@NATIVE_OR_CROSS_LINKER_TRUE@am__append_84 = script_test_10.sh \ +@NATIVE_OR_CROSS_LINKER_TRUE@ ver_test_14a.sh +@NATIVE_OR_CROSS_LINKER_TRUE@am__append_85 = script_test_10.stdout \ +@NATIVE_OR_CROSS_LINKER_TRUE@ ver_test_14a.err ver_test_14b \ +@NATIVE_OR_CROSS_LINKER_TRUE@ ver_test_14c +@NATIVE_OR_CROSS_LINKER_TRUE@am__append_86 = script_test_10 \ +@NATIVE_OR_CROSS_LINKER_TRUE@ ver_test_14a.err ver_test_14b \ +@NATIVE_OR_CROSS_LINKER_TRUE@ ver_test_14c # These tests work with cross linkers only. @DEFAULT_TARGET_I386_TRUE@@NATIVE_OR_CROSS_LINKER_TRUE@am__append_87 = split_i386.sh @@ -5251,6 +5256,8 @@ defsym_test.sh.log: defsym_test.sh @p='defsym_test.sh'; $(am__check_pre) $(LOG_COMPILE) "$$tst" $(am__check_post) script_test_10.sh.log: script_test_10.sh @p='script_test_10.sh'; $(am__check_pre) $(LOG_COMPILE) "$$tst" $(am__check_post) +ver_test_14a.sh.log: ver_test_14a.sh + @p='ver_test_14a.sh'; $(am__check_pre) $(LOG_COMPILE) "$$tst" $(am__check_post) split_i386.sh.log: split_i386.sh @p='split_i386.sh'; $(am__check_pre) $(LOG_COMPILE) "$$tst" $(am__check_post) split_x86_64.sh.log: split_x86_64.sh @@ -7319,6 +7326,32 @@ uninstall-am: @NATIVE_OR_CROSS_LINKER_TRUE@ gcctestdir/ld -o $@ script_test_10.o -T $(srcdir)/script_test_10.t @NATIVE_OR_CROSS_LINKER_TRUE@script_test_10.stdout: script_test_10 @NATIVE_OR_CROSS_LINKER_TRUE@ $(TEST_READELF) -SW script_test_10 > $@ +@NATIVE_OR_CROSS_LINKER_TRUE@ver_test_14a.err: $(srcdir)/ver_test_14.script ver_test_14_main.o ver_test_14_ref.so gcctestdir/ld +@NATIVE_OR_CROSS_LINKER_TRUE@ @if gcctestdir/ld -o ver_test_14a --version-script $(srcdir)/ver_test_14.script ver_test_14_main.o ver_test_14_ref.so 2>$@; \ +@NATIVE_OR_CROSS_LINKER_TRUE@ then \ +@NATIVE_OR_CROSS_LINKER_TRUE@ echo 1>&2 "Link of ver_test_14a should have failed"; \ +@NATIVE_OR_CROSS_LINKER_TRUE@ rm -f $@; \ +@NATIVE_OR_CROSS_LINKER_TRUE@ exit 1; \ +@NATIVE_OR_CROSS_LINKER_TRUE@ fi +@NATIVE_OR_CROSS_LINKER_TRUE@ver_test_14b: $(srcdir)/ver_test_14.script ver_test_14_main.o ver_test_14_ref_weak.so gcctestdir/ld +@NATIVE_OR_CROSS_LINKER_TRUE@ gcctestdir/ld -o $@ --version-script $(srcdir)/ver_test_14.script ver_test_14_main.o ver_test_14_ref_weak.so +@NATIVE_OR_CROSS_LINKER_TRUE@ver_test_14c: $(srcdir)/ver_test_14.script ver_test_14_main.o ver_test_14_ref.so ver_test_14_def.so gcctestdir/ld +@NATIVE_OR_CROSS_LINKER_TRUE@ gcctestdir/ld -o $@ --version-script $(srcdir)/ver_test_14.script ver_test_14_main.o ver_test_14_ref.so ver_test_14_def.so + +@NATIVE_OR_CROSS_LINKER_TRUE@ver_test_14_main.o: ver_test_14_main.s +@NATIVE_OR_CROSS_LINKER_TRUE@ $(TEST_AS) -o $@ $< +@NATIVE_OR_CROSS_LINKER_TRUE@ver_test_14_ref.o: ver_test_14_ref.s +@NATIVE_OR_CROSS_LINKER_TRUE@ $(TEST_AS) -o $@ $< +@NATIVE_OR_CROSS_LINKER_TRUE@ver_test_14_ref_weak.o: ver_test_14_ref_weak.s +@NATIVE_OR_CROSS_LINKER_TRUE@ $(TEST_AS) -o $@ $< +@NATIVE_OR_CROSS_LINKER_TRUE@ver_test_14_def.o: ver_test_14_def.s +@NATIVE_OR_CROSS_LINKER_TRUE@ $(TEST_AS) -o $@ $< +@NATIVE_OR_CROSS_LINKER_TRUE@ver_test_14_ref.so: ver_test_14_ref.o gcctestdir/ld +@NATIVE_OR_CROSS_LINKER_TRUE@ gcctestdir/ld -shared -o $@ $< +@NATIVE_OR_CROSS_LINKER_TRUE@ver_test_14_ref_weak.so: ver_test_14_ref_weak.o gcctestdir/ld +@NATIVE_OR_CROSS_LINKER_TRUE@ gcctestdir/ld -shared -o $@ $< +@NATIVE_OR_CROSS_LINKER_TRUE@ver_test_14_def.so: ver_test_14_def.o gcctestdir/ld +@NATIVE_OR_CROSS_LINKER_TRUE@ gcctestdir/ld -shared -o $@ $< @DEFAULT_TARGET_I386_TRUE@@NATIVE_OR_CROSS_LINKER_TRUE@split_i386_1.o: split_i386_1.s @DEFAULT_TARGET_I386_TRUE@@NATIVE_OR_CROSS_LINKER_TRUE@ $(TEST_AS) -o $@ $< @DEFAULT_TARGET_I386_TRUE@@NATIVE_OR_CROSS_LINKER_TRUE@split_i386_2.o: split_i386_2.s diff --git a/gold/testsuite/ver_test_14.script b/gold/testsuite/ver_test_14.script new file mode 100644 index 0000000..9db12e6 --- /dev/null +++ b/gold/testsuite/ver_test_14.script @@ -0,0 +1,4 @@ +{ + local: + bar; +}; diff --git a/gold/testsuite/ver_test_14_def.s b/gold/testsuite/ver_test_14_def.s new file mode 100644 index 0000000..bfd7f05 --- /dev/null +++ b/gold/testsuite/ver_test_14_def.s @@ -0,0 +1,4 @@ +.global bar +.text +bar: + nop diff --git a/gold/testsuite/ver_test_14_main.s b/gold/testsuite/ver_test_14_main.s new file mode 100644 index 0000000..2ac6889 --- /dev/null +++ b/gold/testsuite/ver_test_14_main.s @@ -0,0 +1,10 @@ +.global _start,__start,foo,bar +.type foo,"function" +.text +_start: +__start: + .dc.a foo + +.section ".text.bar","ax" +bar: + nop diff --git a/gold/testsuite/ver_test_14_ref.s b/gold/testsuite/ver_test_14_ref.s new file mode 100644 index 0000000..7f497d6 --- /dev/null +++ b/gold/testsuite/ver_test_14_ref.s @@ -0,0 +1,4 @@ +.global foo,bar +.text +foo: + .dc.a bar diff --git a/gold/testsuite/ver_test_14_ref_weak.s b/gold/testsuite/ver_test_14_ref_weak.s new file mode 100644 index 0000000..9881d73 --- /dev/null +++ b/gold/testsuite/ver_test_14_ref_weak.s @@ -0,0 +1,5 @@ +.global foo +.weak bar +.text +foo: + .dc.a bar diff --git a/gold/testsuite/ver_test_14a.sh b/gold/testsuite/ver_test_14a.sh new file mode 100755 index 0000000..a37e237 --- /dev/null +++ b/gold/testsuite/ver_test_14a.sh @@ -0,0 +1,40 @@ +#!/bin/sh + +# ver_test_14a.sh -- check for a forced local symbol referenced by DSO. + +# Copyright (C) 2017 Free Software Foundation, Inc. +# Written by Igor Kudrin . + +# 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. + +check() +{ + if ! grep -q "$2" "$1" + then + echo "Did not find expected error in $1:" + echo " $2" + echo "" + echo "Actual error output below:" + cat "$1" + exit 1 + fi +} + +check ver_test_14a.err "local symbol 'bar' in ver_test_14_main.o is referenced by DSO." + +exit 0