This is the mail archive of the
binutils@sourceware.org
mailing list for the binutils project.
[gold commit] Fix problem where -u is ignored when a weak undef is seen
- From: ccoutant at google dot com (Cary Coutant)
- To: binutils at sourceware dot org
- Date: Thu, 06 Feb 2014 17:18:03 -0800
- Subject: [gold commit] Fix problem where -u is ignored when a weak undef is seen
- Authentication-results: sourceware.org; auth=none
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.
Tested on x86-64 and committed.
-cary
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.
diff --git a/gold/archive.cc b/gold/archive.cc
index 53d88a2..b52ebd3 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 0b22c13..aa41290 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/weak_undef_file3.cc b/gold/testsuite/weak_undef_file3.cc
new file mode 100644
index 0000000..7c96d3a
--- /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 <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
index 0000000..3f3cc14
--- /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 <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
index 0000000..fc9bbab
--- /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 <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;
+}