From 1f25b93bc6e10b314ccdc5c42583f77db1b33e2e Mon Sep 17 00:00:00 2001 From: Cary Coutant Date: Thu, 6 Feb 2014 17:12:50 -0800 Subject: [PATCH] Fix problem where -u is ignored when a weak undef is seen. When the linker has a weak undefined symbol, it normally does not select an archive library member just to satisfy the reference. If the same symbol is also listed in a -u option, however, we should select the archive library member. This patch reorders the code in Library_base::should_include_member so that the additional checks are performed in the case of a weak undef. gold/ 2014-02-06 Cary Coutant * archive.cc (Library_base::should_include_member): Reorder code to check for -u option if a weak undef has already been seen. * testsuite/Makefile.am (weak_undef_test_2): New test case. * testsuite/Makefile.in: Regenerate. * testsuite/weak_undef_file3.cc: New file. * testsuite/weak_undef_file4.cc: New file. * testsuite/weak_undef_test_2.cc: New file. --- gold/archive.cc | 86 ++++++++++++++++------------- gold/testsuite/Makefile.am | 12 ++++ gold/testsuite/Makefile.in | 30 +++++++++- gold/testsuite/weak_undef_file3.cc | 29 ++++++++++ gold/testsuite/weak_undef_file4.cc | 29 ++++++++++ gold/testsuite/weak_undef_test_2.cc | 79 ++++++++++++++++++++++++++ 6 files changed, 224 insertions(+), 41 deletions(-) create mode 100644 gold/testsuite/weak_undef_file3.cc create mode 100644 gold/testsuite/weak_undef_file4.cc create mode 100644 gold/testsuite/weak_undef_test_2.cc diff --git a/gold/archive.cc b/gold/archive.cc index 53d88a23a12..b52ebd377c0 100644 --- a/gold/archive.cc +++ b/gold/archive.cc @@ -97,46 +97,56 @@ Library_base::should_include_member(Symbol_table* symtab, Layout* layout, *symp = sym; - if (sym == NULL) + if (sym != NULL) { - // Check whether the symbol was named in a -u option. - if (parameters->options().is_undefined(sym_name)) - { - *why = "-u "; - *why += sym_name; - } - else if (parameters->options().is_export_dynamic_symbol(sym_name)) - { - *why = "--export-dynamic-symbol "; - *why += sym_name; - } - else if (layout->script_options()->is_referenced(sym_name)) - { - size_t alc = 100 + strlen(sym_name); - char* buf = new char[alc]; - snprintf(buf, alc, _("script or expression reference to %s"), - sym_name); - *why = buf; - delete[] buf; - } - else if (strcmp(sym_name, parameters->entry()) == 0) - { - *why = "entry symbol "; - *why += sym_name; - } - else - return Library_base::SHOULD_INCLUDE_UNKNOWN; + if (!sym->is_undefined()) + return Library_base::SHOULD_INCLUDE_NO; + + // PR 12001: Do not include an archive when the undefined + // symbol has actually been defined on the command line. + if (layout->script_options()->is_pending_assignment(sym_name)) + return Library_base::SHOULD_INCLUDE_NO; + + // If the symbol is weak undefined, we still need to check + // for other reasons (like a -u option). + if (sym->binding() != elfcpp::STB_WEAK) + return Library_base::SHOULD_INCLUDE_YES; + } + + // Check whether the symbol was named in a -u option. + if (parameters->options().is_undefined(sym_name)) + { + *why = "-u "; + *why += sym_name; + return Library_base::SHOULD_INCLUDE_YES; + } + + if (parameters->options().is_export_dynamic_symbol(sym_name)) + { + *why = "--export-dynamic-symbol "; + *why += sym_name; + return Library_base::SHOULD_INCLUDE_YES; } - else if (!sym->is_undefined()) - return Library_base::SHOULD_INCLUDE_NO; - // PR 12001: Do not include an archive when the undefined - // symbol has actually been defined on the command line. - else if (layout->script_options()->is_pending_assignment(sym_name)) - return Library_base::SHOULD_INCLUDE_NO; - else if (sym->binding() == elfcpp::STB_WEAK) - return Library_base::SHOULD_INCLUDE_UNKNOWN; - - return Library_base::SHOULD_INCLUDE_YES; + + if (layout->script_options()->is_referenced(sym_name)) + { + size_t alc = 100 + strlen(sym_name); + char* buf = new char[alc]; + snprintf(buf, alc, _("script or expression reference to %s"), + sym_name); + *why = buf; + delete[] buf; + return Library_base::SHOULD_INCLUDE_YES; + } + + if (strcmp(sym_name, parameters->entry()) == 0) + { + *why = "entry symbol "; + *why += sym_name; + return Library_base::SHOULD_INCLUDE_YES; + } + + return Library_base::SHOULD_INCLUDE_UNKNOWN; } // The header of an entry in the archive. This is all readable text, diff --git a/gold/testsuite/Makefile.am b/gold/testsuite/Makefile.am index 0b22c1378b7..aa41290bc72 100644 --- a/gold/testsuite/Makefile.am +++ b/gold/testsuite/Makefile.am @@ -710,6 +710,18 @@ alt/weak_undef_lib.so: weak_undef_file2.o test -d alt || mkdir -p alt $(CXXLINK) -Bgcctestdir/ -shared weak_undef_file2.o +check_PROGRAMS += weak_undef_test_2 +weak_undef_test_2_SOURCES = weak_undef_test_2.cc +weak_undef_test_2_DEPENDENCIES = gcctestdir/ld libweak_undef_2.a +weak_undef_test_2_LDFLAGS = -Bgcctestdir/ -u weak_undef_2 +weak_undef_test_2_LDADD = -L . -lweak_undef_2 +libweak_undef_2.a: weak_undef_file3.o weak_undef_file4.o + $(TEST_AR) rc $@ $^ +weak_undef_file3.o: weak_undef_file3.cc + $(CXXCOMPILE) -c -o $@ $< +weak_undef_file4.o: weak_undef_file4.cc + $(CXXCOMPILE) -c -o $@ $< + if FN_PTRS_IN_SO_WITHOUT_PIC check_PROGRAMS += weak_undef_nonpic_test MOSTLYCLEANFILES += alt/weak_undef_lib_nonpic.so diff --git a/gold/testsuite/Makefile.in b/gold/testsuite/Makefile.in index 6a9228f1e07..60c2c10f5b2 100644 --- a/gold/testsuite/Makefile.in +++ b/gold/testsuite/Makefile.in @@ -208,7 +208,8 @@ check_PROGRAMS = $(am__EXEEXT_1) $(am__EXEEXT_2) $(am__EXEEXT_3) \ @NATIVE_LINKER_FALSE@exception_test_DEPENDENCIES = @GCC_TRUE@@HAVE_STATIC_TRUE@@NATIVE_LINKER_TRUE@am__append_14 = exception_static_test @GCC_TRUE@@NATIVE_LINKER_TRUE@am__append_15 = weak_test \ -@GCC_TRUE@@NATIVE_LINKER_TRUE@ weak_undef_test +@GCC_TRUE@@NATIVE_LINKER_TRUE@ weak_undef_test \ +@GCC_TRUE@@NATIVE_LINKER_TRUE@ weak_undef_test_2 @GCC_FALSE@weak_test_DEPENDENCIES = @NATIVE_LINKER_FALSE@weak_test_DEPENDENCIES = @FN_PTRS_IN_SO_WITHOUT_PIC_TRUE@@GCC_TRUE@@NATIVE_LINKER_TRUE@am__append_16 = weak_undef_nonpic_test @@ -777,7 +778,8 @@ libgoldtest_a_OBJECTS = $(am_libgoldtest_a_OBJECTS) @GCC_TRUE@@NATIVE_LINKER_TRUE@ exception_separate_shared_21_test$(EXEEXT) @GCC_TRUE@@HAVE_STATIC_TRUE@@NATIVE_LINKER_TRUE@am__EXEEXT_11 = exception_static_test$(EXEEXT) @GCC_TRUE@@NATIVE_LINKER_TRUE@am__EXEEXT_12 = weak_test$(EXEEXT) \ -@GCC_TRUE@@NATIVE_LINKER_TRUE@ weak_undef_test$(EXEEXT) +@GCC_TRUE@@NATIVE_LINKER_TRUE@ weak_undef_test$(EXEEXT) \ +@GCC_TRUE@@NATIVE_LINKER_TRUE@ weak_undef_test_2$(EXEEXT) @FN_PTRS_IN_SO_WITHOUT_PIC_TRUE@@GCC_TRUE@@NATIVE_LINKER_TRUE@am__EXEEXT_13 = weak_undef_nonpic_test$(EXEEXT) @GCC_TRUE@@NATIVE_LINKER_TRUE@am__EXEEXT_14 = \ @GCC_TRUE@@NATIVE_LINKER_TRUE@ weak_alias_test$(EXEEXT) \ @@ -1773,6 +1775,11 @@ weak_undef_nonpic_test_LINK = $(CXXLD) $(AM_CXXFLAGS) $(CXXFLAGS) \ weak_undef_test_OBJECTS = $(am_weak_undef_test_OBJECTS) weak_undef_test_LINK = $(CXXLD) $(AM_CXXFLAGS) $(CXXFLAGS) \ $(weak_undef_test_LDFLAGS) $(LDFLAGS) -o $@ +@GCC_TRUE@@NATIVE_LINKER_TRUE@am_weak_undef_test_2_OBJECTS = \ +@GCC_TRUE@@NATIVE_LINKER_TRUE@ weak_undef_test_2.$(OBJEXT) +weak_undef_test_2_OBJECTS = $(am_weak_undef_test_2_OBJECTS) +weak_undef_test_2_LINK = $(CXXLD) $(AM_CXXFLAGS) $(CXXFLAGS) \ + $(weak_undef_test_2_LDFLAGS) $(LDFLAGS) -o $@ DEFAULT_INCLUDES = -I.@am__isrc@ -I$(top_builddir) depcomp = $(SHELL) $(top_srcdir)/../depcomp am__depfiles_maybe = depfiles @@ -1860,7 +1867,8 @@ SOURCES = $(libgoldtest_a_SOURCES) basic_pic_test.c basic_pie_test.c \ $(ver_test_2_SOURCES) $(ver_test_6_SOURCES) \ $(ver_test_8_SOURCES) $(ver_test_9_SOURCES) \ $(weak_alias_test_SOURCES) weak_plt.c $(weak_test_SOURCES) \ - $(weak_undef_nonpic_test_SOURCES) $(weak_undef_test_SOURCES) + $(weak_undef_nonpic_test_SOURCES) $(weak_undef_test_SOURCES) \ + $(weak_undef_test_2_SOURCES) ETAGS = etags CTAGS = ctags am__tty_colors = \ @@ -2361,6 +2369,10 @@ LDADD = libgoldtest.a ../libgold.a ../../libiberty/libiberty.a $(LIBINTL) \ @GCC_TRUE@@NATIVE_LINKER_TRUE@weak_undef_test_DEPENDENCIES = gcctestdir/ld weak_undef_lib.so alt/weak_undef_lib.so @GCC_TRUE@@NATIVE_LINKER_TRUE@weak_undef_test_LDFLAGS = -Bgcctestdir/ -Wl,-R,alt @GCC_TRUE@@NATIVE_LINKER_TRUE@weak_undef_test_LDADD = -L . weak_undef_lib.so +@GCC_TRUE@@NATIVE_LINKER_TRUE@weak_undef_test_2_SOURCES = weak_undef_test_2.cc +@GCC_TRUE@@NATIVE_LINKER_TRUE@weak_undef_test_2_DEPENDENCIES = gcctestdir/ld libweak_undef_2.a +@GCC_TRUE@@NATIVE_LINKER_TRUE@weak_undef_test_2_LDFLAGS = -Bgcctestdir/ -u weak_undef_2 +@GCC_TRUE@@NATIVE_LINKER_TRUE@weak_undef_test_2_LDADD = -L . -lweak_undef_2 @FN_PTRS_IN_SO_WITHOUT_PIC_TRUE@@GCC_TRUE@@NATIVE_LINKER_TRUE@weak_undef_nonpic_test_SOURCES = weak_undef_test.cc @FN_PTRS_IN_SO_WITHOUT_PIC_TRUE@@GCC_TRUE@@NATIVE_LINKER_TRUE@weak_undef_nonpic_test_DEPENDENCIES = gcctestdir/ld weak_undef_lib_nonpic.so alt/weak_undef_lib_nonpic.so @FN_PTRS_IN_SO_WITHOUT_PIC_TRUE@@GCC_TRUE@@NATIVE_LINKER_TRUE@weak_undef_nonpic_test_LDFLAGS = -Bgcctestdir/ -Wl,-R,alt @@ -3451,6 +3463,9 @@ weak_undef_nonpic_test$(EXEEXT): $(weak_undef_nonpic_test_OBJECTS) $(weak_undef_ weak_undef_test$(EXEEXT): $(weak_undef_test_OBJECTS) $(weak_undef_test_DEPENDENCIES) @rm -f weak_undef_test$(EXEEXT) $(weak_undef_test_LINK) $(weak_undef_test_OBJECTS) $(weak_undef_test_LDADD) $(LIBS) +weak_undef_test_2$(EXEEXT): $(weak_undef_test_2_OBJECTS) $(weak_undef_test_2_DEPENDENCIES) + @rm -f weak_undef_test_2$(EXEEXT) + $(weak_undef_test_2_LINK) $(weak_undef_test_2_OBJECTS) $(weak_undef_test_2_LDADD) $(LIBS) mostlyclean-compile: -rm -f *.$(OBJEXT) @@ -3572,6 +3587,7 @@ distclean-compile: @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/weak_plt.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/weak_test.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/weak_undef_test.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/weak_undef_test_2.Po@am__quote@ .c.o: @am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $< @@ -4063,6 +4079,8 @@ weak_test.log: weak_test$(EXEEXT) @p='weak_test$(EXEEXT)'; $(am__check_pre) $(LOG_COMPILE) "$$tst" $(am__check_post) weak_undef_test.log: weak_undef_test$(EXEEXT) @p='weak_undef_test$(EXEEXT)'; $(am__check_pre) $(LOG_COMPILE) "$$tst" $(am__check_post) +weak_undef_test_2.log: weak_undef_test_2$(EXEEXT) + @p='weak_undef_test_2$(EXEEXT)'; $(am__check_pre) $(LOG_COMPILE) "$$tst" $(am__check_post) weak_undef_nonpic_test.log: weak_undef_nonpic_test$(EXEEXT) @p='weak_undef_nonpic_test$(EXEEXT)'; $(am__check_pre) $(LOG_COMPILE) "$$tst" $(am__check_post) weak_alias_test.log: weak_alias_test$(EXEEXT) @@ -4660,6 +4678,12 @@ uninstall-am: @GCC_TRUE@@NATIVE_LINKER_TRUE@alt/weak_undef_lib.so: weak_undef_file2.o @GCC_TRUE@@NATIVE_LINKER_TRUE@ test -d alt || mkdir -p alt @GCC_TRUE@@NATIVE_LINKER_TRUE@ $(CXXLINK) -Bgcctestdir/ -shared weak_undef_file2.o +@GCC_TRUE@@NATIVE_LINKER_TRUE@libweak_undef_2.a: weak_undef_file3.o weak_undef_file4.o +@GCC_TRUE@@NATIVE_LINKER_TRUE@ $(TEST_AR) rc $@ $^ +@GCC_TRUE@@NATIVE_LINKER_TRUE@weak_undef_file3.o: weak_undef_file3.cc +@GCC_TRUE@@NATIVE_LINKER_TRUE@ $(CXXCOMPILE) -c -o $@ $< +@GCC_TRUE@@NATIVE_LINKER_TRUE@weak_undef_file4.o: weak_undef_file4.cc +@GCC_TRUE@@NATIVE_LINKER_TRUE@ $(CXXCOMPILE) -c -o $@ $< @FN_PTRS_IN_SO_WITHOUT_PIC_TRUE@@GCC_TRUE@@NATIVE_LINKER_TRUE@weak_undef_file1_nonpic.o: weak_undef_file1.cc @FN_PTRS_IN_SO_WITHOUT_PIC_TRUE@@GCC_TRUE@@NATIVE_LINKER_TRUE@ $(CXXCOMPILE) -c -o $@ $< @FN_PTRS_IN_SO_WITHOUT_PIC_TRUE@@GCC_TRUE@@NATIVE_LINKER_TRUE@weak_undef_file2_nonpic.o: weak_undef_file2.cc diff --git a/gold/testsuite/weak_undef_file3.cc b/gold/testsuite/weak_undef_file3.cc new file mode 100644 index 00000000000..7c96d3ad1a8 --- /dev/null +++ b/gold/testsuite/weak_undef_file3.cc @@ -0,0 +1,29 @@ +// weak_undef_file3.cc -- test handling of weak undefined symbols for gold + +// Copyright 2014 Free Software Foundation, Inc. +// Written by Cary Coutant . + +// 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 tests that we correctly deal with weak undefined symbols +// when searching archive libraries. If we have a weak undefined symbol, +// it should not cause us to link an archive library member that defines +// that symbol. However, if the symbol is also listed in a -u option on +// the command line, it should cause the archive member to be linked. + +int weak_undef_1 = 1; diff --git a/gold/testsuite/weak_undef_file4.cc b/gold/testsuite/weak_undef_file4.cc new file mode 100644 index 00000000000..3f3cc145938 --- /dev/null +++ b/gold/testsuite/weak_undef_file4.cc @@ -0,0 +1,29 @@ +// weak_undef_file4.cc -- test handling of weak undefined symbols for gold + +// Copyright 2014 Free Software Foundation, Inc. +// Written by Cary Coutant . + +// 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 tests that we correctly deal with weak undefined symbols +// when searching archive libraries. If we have a weak undefined symbol, +// it should not cause us to link an archive library member that defines +// that symbol. However, if the symbol is also listed in a -u option on +// the command line, it should cause the archive member to be linked. + +int weak_undef_2 = 2; diff --git a/gold/testsuite/weak_undef_test_2.cc b/gold/testsuite/weak_undef_test_2.cc new file mode 100644 index 00000000000..fc9bbab6195 --- /dev/null +++ b/gold/testsuite/weak_undef_test_2.cc @@ -0,0 +1,79 @@ +// weak_undef_test_2.cc -- test handling of weak undefined symbols for gold + +// Copyright 2014 Free Software Foundation, Inc. +// Written by Cary Coutant . + +// 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 tests that we correctly deal with weak undefined symbols +// when searching archive libraries. If we have a weak undefined symbol, +// it should not cause us to link an archive library member that defines +// that symbol. However, if the symbol is also listed in a -u option on +// the command line, it should cause the archive member to be linked. + + +#include + +// This symbol is defined in weak_undef_file3.cc, but we should +// not load it from the library. +extern int weak_undef_1 __attribute__ ((weak)); + +// This symbol is defined in weak_undef_file4.cc, but is also +// listed in a -u option on the link command, so we should +// load it from the library. +extern int weak_undef_2 __attribute__ ((weak)); + +int *p1 = &weak_undef_1; + +int *p2 = &weak_undef_2; + +int +main() +{ + int status = 0; + + if (&weak_undef_1 != NULL) + { + fprintf(stderr, "FAILED weak undef test 1: %s\n", + "&weak_undef_1 is not NULL"); + status = 1; + } + + if (&weak_undef_2 == NULL) + { + fprintf(stderr, "FAILED weak undef test 2: %s\n", + "&weak_undef_2 is NULL"); + status = 1; + } + + if (p1 != NULL) + { + fprintf(stderr, "FAILED weak undef test 3: %s\n", + "p1 is not NULL"); + status = 1; + } + + if (p2 == NULL) + { + fprintf(stderr, "FAILED weak undef test 4: %s\n", + "p2 is NULL"); + status = 1; + } + + return status; +} -- 2.30.2