Fix problem where -u is ignored when a weak undef is seen.
authorCary Coutant <ccoutant@google.com>
Fri, 7 Feb 2014 01:12:50 +0000 (17:12 -0800)
committerCary Coutant <ccoutant@google.com>
Fri, 7 Feb 2014 01:15:02 +0000 (17:15 -0800)
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  <ccoutant@google.com>

* 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
gold/testsuite/Makefile.am
gold/testsuite/Makefile.in
gold/testsuite/weak_undef_file3.cc [new file with mode: 0644]
gold/testsuite/weak_undef_file4.cc [new file with mode: 0644]
gold/testsuite/weak_undef_test_2.cc [new file with mode: 0644]

index 53d88a2..b52ebd3 100644 (file)
@@ -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,
index 0b22c13..aa41290 100644 (file)
@@ -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
index 6a9228f..60c2c10 100644 (file)
@@ -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 (file)
index 0000000..7c96d3a
--- /dev/null
@@ -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 <ccoutant@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 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 (file)
index 0000000..3f3cc14
--- /dev/null
@@ -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 <ccoutant@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 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 (file)
index 0000000..fc9bbab
--- /dev/null
@@ -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 <ccoutant@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 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 <cstdio>
+
+// 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;
+}