[PATCH][GOLD] Let a weak reference override a dynamic weak reference.

Doug Kwan (關振德) dougkwan@google.com
Sat Aug 28 00:44:00 GMT 2010


Hi,

    This patch fixes a problem in which a weak reference in input
because a non-weak reference in the output when gold sees another weak
reference to the same symbol in a DSO first.  This was first found in
a scenario involving something like:

    ld .... -ldso -lstatic

If both libdso.so and the part of libstatic.a that get linked contain
weak references to some symbol S, gold enters a dynamic weak reference
to S into the symbol table first.  The symbol will also have the
previous binding intialized to be non-weak.  After that, gold sees the
static weak reference to S in libstatic.a and tries to resolve the
symbol.   The static weak reference will be ignored by the resolver.
When gold finally outputs S, it will find S to be a dynamic weak
reference and will use the previous non-weak binding!   The fix is to
let a weak reference override an existing dynamic weak reference to
the same symbol.  This has been tested for x86_64.

-Doug

2010-08-27  Doug Kwan  <dougkwan@google.com>

        * gold/resolve.cc (Symbol_table::should_override): Let a weak
        reference override an existing dynamic weak reference.
        * testsuite/Makefile.am: Add new test dyn_weak_ref.
        * testsuite/Makefile.in: Regenerate.
        * testsuite/dyn_weak_ref.sh: New file.
        * testsuite/dyn_weak_ref_1.c: Ditto.
        * testsuite/dyn_weak_ref_2.c: Ditto.
-------------- next part --------------
? gold/autom4te.cache
Index: gold/resolve.cc
===================================================================
RCS file: /cvs/src/src/gold/resolve.cc,v
retrieving revision 1.56
diff -u -u -p -r1.56 resolve.cc
--- gold/resolve.cc	13 Aug 2010 00:18:18 -0000	1.56
+++ gold/resolve.cc	27 Aug 2010 23:56:38 -0000
@@ -630,14 +630,21 @@ Symbol_table::should_override(const Symb
     case UNDEF * 16 + WEAK_UNDEF:
     case WEAK_UNDEF * 16 + WEAK_UNDEF:
     case DYN_UNDEF * 16 + WEAK_UNDEF:
-    case DYN_WEAK_UNDEF * 16 + WEAK_UNDEF:
     case COMMON * 16 + WEAK_UNDEF:
     case WEAK_COMMON * 16 + WEAK_UNDEF:
     case DYN_COMMON * 16 + WEAK_UNDEF:
     case DYN_WEAK_COMMON * 16 + WEAK_UNDEF:
-      // A new weak undefined reference tells us nothing.
+      // A new weak undefined reference tells us nothing unless the
+      // exisiting symbol is a dynamic weak reference.
       return false;
 
+    case DYN_WEAK_UNDEF * 16 + WEAK_UNDEF:
+      // A new weak reference overrides an existing dynamic weak reference.
+      // This is necessary because a dynamic weak reference remembers
+      // the old binding, which may not be weak.  If we keeps the existing
+      // dynamic weak reference, the weakness may be dropped in the output.
+      return true;
+
     case DYN_DEF * 16 + WEAK_UNDEF:
     case DYN_WEAK_DEF * 16 + WEAK_UNDEF:
       // For a dynamic def, we need to remember which kind of undef we see.
Index: gold/testsuite/Makefile.am
===================================================================
RCS file: /cvs/src/src/gold/testsuite/Makefile.am,v
retrieving revision 1.142
diff -u -u -p -r1.142 Makefile.am
--- gold/testsuite/Makefile.am	20 Aug 2010 00:35:12 -0000	1.142
+++ gold/testsuite/Makefile.am	27 Aug 2010 23:56:38 -0000
@@ -1750,6 +1750,26 @@ strong_ref_weak_def_1.so: strong_ref_wea
 strong_ref_weak_def.stdout: strong_ref_weak_def_1.so
 	$(TEST_READELF) -sWD $< > $@
 
+# Test that a strong weak reference remains strong if there is another
+# weak reference in a DSO.
+check_SCRIPTS += dyn_weak_ref.sh
+check_DATA += dyn_weak_ref.stdout
+MOSTLYCLEANFILES += dyn_weak_ref_1.so dyn_weak_ref_2.so \
+	dyn_weak_ref.stdout
+dyn_weak_ref_2.o: dyn_weak_ref_2.c
+	$(COMPILE) -o $@ -c -fPIC $<
+dyn_weak_ref_2.so: dyn_weak_ref_2.o gcctestdir/ld
+	gcctestdir/ld -shared -o $@ dyn_weak_ref_2.o
+dyn_weak_ref_1.o: dyn_weak_ref_1.c
+	$(COMPILE) -o $@ -c -fPIC $<
+# We intentionally put dyn_weak_ref_2.so in front of dyn_weak_ref_1.o
+# so that the weak ref there goes to gold's symbol table first.
+dyn_weak_ref_1.so: dyn_weak_ref_1.o dyn_weak_ref_2.so gcctestdir/ld
+	gcctestdir/ld -shared -o $@ dyn_weak_ref_2.so dyn_weak_ref_1.o
+dyn_weak_ref.stdout: dyn_weak_ref_1.so
+	$(TEST_READELF) -sWD $< > $@
+
+
 # Test that --start-lib and --end-lib function correctly.
 check_PROGRAMS += start_lib_test
 start_lib_test: start_lib_test_main.o libstart_lib_test.a start_lib_test_2.o start_lib_test_3.o \
Index: gold/testsuite/Makefile.in
===================================================================
RCS file: /cvs/src/src/gold/testsuite/Makefile.in,v
retrieving revision 1.151
diff -u -u -p -r1.151 Makefile.in
--- gold/testsuite/Makefile.in	20 Aug 2010 00:35:12 -0000	1.151
+++ gold/testsuite/Makefile.in	27 Aug 2010 23:56:38 -0000
@@ -309,12 +309,16 @@ check_PROGRAMS = object_unittest$(EXEEXT
 # symbol versioning is not used.
 
 # Test that strong reference to a weak symbol in a DSO remains strong.
+
+# Test that a strong weak reference remains strong if there is another
+# weak reference in a DSO.
 @GCC_TRUE@@NATIVE_LINKER_TRUE@am__append_27 = exclude_libs_test.sh \
 @GCC_TRUE@@NATIVE_LINKER_TRUE@	discard_locals_test.sh \
 @GCC_TRUE@@NATIVE_LINKER_TRUE@	hidden_test.sh \
 @GCC_TRUE@@NATIVE_LINKER_TRUE@	retain_symbols_file_test.sh \
 @GCC_TRUE@@NATIVE_LINKER_TRUE@	no_version_test.sh \
-@GCC_TRUE@@NATIVE_LINKER_TRUE@	strong_ref_weak_def.sh
+@GCC_TRUE@@NATIVE_LINKER_TRUE@	strong_ref_weak_def.sh \
+@GCC_TRUE@@NATIVE_LINKER_TRUE@	dyn_weak_ref.sh
 @GCC_TRUE@@NATIVE_LINKER_TRUE@am__append_28 = exclude_libs_test.syms \
 @GCC_TRUE@@NATIVE_LINKER_TRUE@	discard_locals_test.syms \
 @GCC_TRUE@@NATIVE_LINKER_TRUE@	discard_locals_relocatable_test1.syms \
@@ -322,7 +326,8 @@ check_PROGRAMS = object_unittest$(EXEEXT
 @GCC_TRUE@@NATIVE_LINKER_TRUE@	hidden_test.err \
 @GCC_TRUE@@NATIVE_LINKER_TRUE@	retain_symbols_file_test.stdout \
 @GCC_TRUE@@NATIVE_LINKER_TRUE@	no_version_test.stdout \
-@GCC_TRUE@@NATIVE_LINKER_TRUE@	strong_ref_weak_def.stdout
+@GCC_TRUE@@NATIVE_LINKER_TRUE@	strong_ref_weak_def.stdout \
+@GCC_TRUE@@NATIVE_LINKER_TRUE@	dyn_weak_ref.stdout
 @GCC_TRUE@@NATIVE_LINKER_TRUE@am__append_29 = exclude_libs_test.syms \
 @GCC_TRUE@@NATIVE_LINKER_TRUE@	libexclude_libs_test_1.a \
 @GCC_TRUE@@NATIVE_LINKER_TRUE@	libexclude_libs_test_2.a \
@@ -343,7 +348,10 @@ check_PROGRAMS = object_unittest$(EXEEXT
 @GCC_TRUE@@NATIVE_LINKER_TRUE@	no_version_test.stdout \
 @GCC_TRUE@@NATIVE_LINKER_TRUE@	strong_ref_weak_def_1.so \
 @GCC_TRUE@@NATIVE_LINKER_TRUE@	strong_ref_weak_def_2.so \
-@GCC_TRUE@@NATIVE_LINKER_TRUE@	strong_ref_weak_def.stdout
+@GCC_TRUE@@NATIVE_LINKER_TRUE@	strong_ref_weak_def.stdout \
+@GCC_TRUE@@NATIVE_LINKER_TRUE@	dyn_weak_ref_1.so \
+@GCC_TRUE@@NATIVE_LINKER_TRUE@	dyn_weak_ref_2.so \
+@GCC_TRUE@@NATIVE_LINKER_TRUE@	dyn_weak_ref.stdout
 @GCC_TRUE@@MCMODEL_MEDIUM_TRUE@@NATIVE_LINKER_TRUE@am__append_30 = large
 @GCC_FALSE@large_DEPENDENCIES =
 @MCMODEL_MEDIUM_FALSE@large_DEPENDENCIES =
@@ -3272,6 +3280,8 @@ no_version_test.sh.log: no_version_test.
 	@p='no_version_test.sh'; $(am__check_pre) $(LOG_COMPILE) "$$tst" $(am__check_post)
 strong_ref_weak_def.sh.log: strong_ref_weak_def.sh
 	@p='strong_ref_weak_def.sh'; $(am__check_pre) $(LOG_COMPILE) "$$tst" $(am__check_post)
+dyn_weak_ref.sh.log: dyn_weak_ref.sh
+	@p='dyn_weak_ref.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
@@ -4448,6 +4458,18 @@ uninstall-am:
 @GCC_TRUE@@NATIVE_LINKER_TRUE@		strong_ref_weak_def_2.so
 @GCC_TRUE@@NATIVE_LINKER_TRUE@strong_ref_weak_def.stdout: strong_ref_weak_def_1.so
 @GCC_TRUE@@NATIVE_LINKER_TRUE@	$(TEST_READELF) -sWD $< > $@
+@GCC_TRUE@@NATIVE_LINKER_TRUE@dyn_weak_ref_2.o: dyn_weak_ref_2.c
+@GCC_TRUE@@NATIVE_LINKER_TRUE@	$(COMPILE) -o $@ -c -fPIC $<
+@GCC_TRUE@@NATIVE_LINKER_TRUE@dyn_weak_ref_2.so: dyn_weak_ref_2.o gcctestdir/ld
+@GCC_TRUE@@NATIVE_LINKER_TRUE@	gcctestdir/ld -shared -o $@ dyn_weak_ref_2.o
+@GCC_TRUE@@NATIVE_LINKER_TRUE@dyn_weak_ref_1.o: dyn_weak_ref_1.c
+@GCC_TRUE@@NATIVE_LINKER_TRUE@	$(COMPILE) -o $@ -c -fPIC $<
+# We intentionally put dyn_weak_ref_2.so in front of dyn_weak_ref_1.o
+# so that the weak ref there goes to gold's symbol table first.
+@GCC_TRUE@@NATIVE_LINKER_TRUE@dyn_weak_ref_1.so: dyn_weak_ref_1.o dyn_weak_ref_2.so gcctestdir/ld
+@GCC_TRUE@@NATIVE_LINKER_TRUE@	gcctestdir/ld -shared -o $@ dyn_weak_ref_2.so dyn_weak_ref_1.o
+@GCC_TRUE@@NATIVE_LINKER_TRUE@dyn_weak_ref.stdout: dyn_weak_ref_1.so
+@GCC_TRUE@@NATIVE_LINKER_TRUE@	$(TEST_READELF) -sWD $< > $@
 @GCC_TRUE@@NATIVE_LINKER_TRUE@start_lib_test: start_lib_test_main.o libstart_lib_test.a start_lib_test_2.o start_lib_test_3.o \
 @GCC_TRUE@@NATIVE_LINKER_TRUE@	gcctestdir/ld
 @GCC_TRUE@@NATIVE_LINKER_TRUE@	$(LINK) -Bgcctestdir/ -o $@ start_lib_test_main.o -L. -lstart_lib_test \
Index: gold/testsuite/dyn_weak_ref.sh
===================================================================
RCS file: gold/testsuite/dyn_weak_ref.sh
diff -N gold/testsuite/dyn_weak_ref.sh
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ gold/testsuite/dyn_weak_ref.sh	27 Aug 2010 23:56:38 -0000
@@ -0,0 +1,42 @@
+#!/bin/sh
+
+# dyn_weak_ref.sh -- test weak reference remains weak in output even if
+# gold sees a dynamic weak reference before a static one.
+
+# Copyright 2010 Free Software Foundation, Inc.
+# Written by Doug Kwan <dougkwan@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 checks that the reference to 'weak_ref' have WEAK binding.
+
+check()
+{
+    file=$1
+    pattern=$2
+    found=`grep "$pattern" $file`
+    if test -z "$found"; then
+        echo "pattern \"$pattern\" not found in file $file."
+	echo $found
+        exit 1
+    fi
+}
+
+check dyn_weak_ref.stdout ".* WEAK .* UND.* weak_ref"
+
+exit 0
Index: gold/testsuite/dyn_weak_ref_1.c
===================================================================
RCS file: gold/testsuite/dyn_weak_ref_1.c
diff -N gold/testsuite/dyn_weak_ref_1.c
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ gold/testsuite/dyn_weak_ref_1.c	27 Aug 2010 23:56:38 -0000
@@ -0,0 +1,39 @@
+// dyn_weak_ref_1.c -- test that a weak ref remains weak in output when
+// there is a DSO with the same weak ref.
+
+// Copyright 2010 Free Software Foundation, Inc.
+// Written by Doug Kwan <dougkwan@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.
+
+// We test that we correctly deal with a weak reference to from both
+// a DSO and a weak reference to the same symbol in an executable.  The
+// symbol should remains weak.
+
+// This source is used to build an DSO that references the same weak
+// symbol as in a dependent DSO.
+
+extern void weak_ref (void) __attribute__((weak));
+
+void* ptr1 = weak_ref;
+
+int
+main (void)
+{
+  return 0;
+}
Index: gold/testsuite/dyn_weak_ref_2.c
===================================================================
RCS file: gold/testsuite/dyn_weak_ref_2.c
diff -N gold/testsuite/dyn_weak_ref_2.c
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ gold/testsuite/dyn_weak_ref_2.c	27 Aug 2010 23:56:38 -0000
@@ -0,0 +1,32 @@
+// dyn_weak_ref_1.c -- test that a weak ref remains weak in output when
+// there is a DSO with the same weak ref.
+
+// Copyright 2010 Free Software Foundation, Inc.
+// Written by Doug Kwan <dougkwan@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.
+
+// We test that we correctly deal with a weak reference to from both
+// a DSO and a weak reference to the same symbol in an executable.  The
+// symbol should remains weak.
+
+// This source is used to build a DSO that contains a weak reference.
+
+extern void weak_ref (void) __attribute__((weak));
+
+void* ptr2 = weak_ref;


More information about the Binutils mailing list