[RFA][Bug gold/10471] hidden symbol gets added to dynamic symbol table

Cary Coutant ccoutant@google.com
Wed Aug 12 18:13:00 GMT 2009


The attached patch is a proposed fix for PR 10471, where gold ends up putting a
local symbol in the dynamic symbol table when a DSO tries to reference a hidden
(or internal) symbol. In this patch, I issue a warning and refuse to resolve
the symbol, but the link completes successfully. For the included test case, we
get these warning messages:

gcctestdir/ld: warning: hidden symbol 'main_hidden' in hidden_test_main.o is
referenced by DSO libhidden.so
gcctestdir/ld: warning: internal symbol 'main_internal' in hidden_test_main.o
is referenced by DSO libhidden.so

I'm not sure whether these should be made errors (along with undefined symbol
errors, we'd want to see them all before terminating the link) or not.

For comparison, gnu ld prints a message (not sure whether it's a warning or an
error) about the first such symbol, then terminates with a mysterious error
message:

/usr/bin/ld: a.out: internal symbol `main_internal' in hidden_test_main.o is
referenced by DSO
/usr/bin/ld: final link failed: Nonrepresentable section on output

Comments?

-cary


	PR 10471
	* resolve.cc (Symbol_table::resolve): Check for references from
	dynamic objects to hidden and internal symbols.
	* testsuite/Makefile.am (hidden_test.sh): New test.
	* testsuite/Makefile.in: Regenerate.
	* testsuite/hidden_test.sh: New script.
	* testsuite/hidden_test_1.c: New test source.
	* testsuite/hidden_test_main.c: New test source.
-------------- next part --------------
Index: resolve.cc
===================================================================
RCS file: /cvs/src/src/gold/resolve.cc,v
retrieving revision 1.40
diff -u -p -r1.40 resolve.cc
--- resolve.cc	22 Jun 2009 06:51:53 -0000	1.40
+++ resolve.cc	7 Aug 2009 22:40:43 -0000
@@ -257,6 +257,20 @@ Symbol_table::resolve(Sized_symbol<size>
       // Record that we've seen this symbol in a regular object.
       to->set_in_reg();
     }
+  else if (to->visibility() == elfcpp::STV_HIDDEN
+           || to->visibility() == elfcpp::STV_INTERNAL)
+    {
+      // A dynamic object cannot reference a hidden or internal symbol
+      // defined in another object.
+      gold_warning(_("%s symbol '%s' in %s is referenced by DSO %s"),
+                   (to->visibility() == elfcpp::STV_HIDDEN
+                    ? "hidden"
+                    : "internal"),
+                   to->demangled_name().c_str(),
+                   to->object()->name().c_str(),
+                   object->name().c_str());
+      return;
+    }
   else
     {
       // Record that we've seen this symbol in a dynamic object.
Index: testsuite/Makefile.am
===================================================================
RCS file: /cvs/src/src/gold/testsuite/Makefile.am,v
retrieving revision 1.95
diff -u -p -r1.95 Makefile.am
--- testsuite/Makefile.am	5 Aug 2009 20:51:56 -0000	1.95
+++ testsuite/Makefile.am	7 Aug 2009 22:40:43 -0000
@@ -1109,5 +1109,17 @@ large_DEPENDENCIES = gcctestdir/ld
 large_LDFLAGS = -Bgcctestdir/
 endif MCMODEL_MEDIUM
 
+# Test that hidden and internal symbols in the main program cannot be
+# referenced by a shared library.
+check_SCRIPTS += hidden_test.sh
+check_DATA += hidden_test.err
+MOSTLYCLEANFILES += hidden_test hidden_test.err
+libhidden.so: hidden_test_1.c gcctestdir/ld
+	$(COMPILE) -Bgcctestdir/ -g -shared -fPIC -w -o $@ $(srcdir)/hidden_test_1.c
+hidden_test: hidden_test_main.o libhidden.so gcctestdir/ld
+	$(LINK) -Bgcctestdir/ -Wl,-R,. hidden_test_main.o libhidden.so 2>hidden_test.err
+hidden_test.err: hidden_test
+	@touch hidden_test.err
+
 endif GCC
 endif NATIVE_LINKER
Index: testsuite/Makefile.in
===================================================================
RCS file: /cvs/src/src/gold/testsuite/Makefile.in,v
retrieving revision 1.100
diff -u -p -r1.100 Makefile.in
--- testsuite/Makefile.in	5 Aug 2009 20:51:56 -0000	1.100
+++ testsuite/Makefile.in	7 Aug 2009 22:40:44 -0000
@@ -323,15 +323,21 @@ check_PROGRAMS = object_unittest$(EXEEXT
 @GCC_TRUE@@NATIVE_LINKER_TRUE@am__append_24 = exclude_libs_test \
 @GCC_TRUE@@NATIVE_LINKER_TRUE@	local_labels_test \
 @GCC_TRUE@@NATIVE_LINKER_TRUE@	discard_locals_test
+
+# Test that hidden and internal symbols in the main program cannot be
+# referenced by a shared library.
 @GCC_TRUE@@NATIVE_LINKER_TRUE@am__append_25 = exclude_libs_test.sh \
-@GCC_TRUE@@NATIVE_LINKER_TRUE@	discard_locals_test.sh
+@GCC_TRUE@@NATIVE_LINKER_TRUE@	discard_locals_test.sh \
+@GCC_TRUE@@NATIVE_LINKER_TRUE@	hidden_test.sh
 @GCC_TRUE@@NATIVE_LINKER_TRUE@am__append_26 = exclude_libs_test.syms \
-@GCC_TRUE@@NATIVE_LINKER_TRUE@	discard_locals_test.syms
+@GCC_TRUE@@NATIVE_LINKER_TRUE@	discard_locals_test.syms \
+@GCC_TRUE@@NATIVE_LINKER_TRUE@	hidden_test.err
 @GCC_TRUE@@NATIVE_LINKER_TRUE@am__append_27 = exclude_libs_test.syms \
 @GCC_TRUE@@NATIVE_LINKER_TRUE@	libexclude_libs_test_1.a \
 @GCC_TRUE@@NATIVE_LINKER_TRUE@	libexclude_libs_test_2.a \
 @GCC_TRUE@@NATIVE_LINKER_TRUE@	alt/libexclude_libs_test_3.a \
-@GCC_TRUE@@NATIVE_LINKER_TRUE@	discard_locals_test.syms
+@GCC_TRUE@@NATIVE_LINKER_TRUE@	discard_locals_test.syms \
+@GCC_TRUE@@NATIVE_LINKER_TRUE@	hidden_test hidden_test.err
 @GCC_TRUE@@MCMODEL_MEDIUM_TRUE@@NATIVE_LINKER_TRUE@am__append_28 = large
 @GCC_FALSE@large_DEPENDENCIES = libgoldtest.a ../libgold.a \
 @GCC_FALSE@	../../libiberty/libiberty.a $(am__DEPENDENCIES_1) \
@@ -347,7 +353,7 @@ check_PROGRAMS = object_unittest$(EXEEXT
 @NATIVE_LINKER_FALSE@	$(am__DEPENDENCIES_1) \
 @NATIVE_LINKER_FALSE@	$(am__DEPENDENCIES_1)
 subdir = testsuite
-DIST_COMMON = $(srcdir)/Makefile.am $(srcdir)/Makefile.in ChangeLog
+DIST_COMMON = $(srcdir)/Makefile.am $(srcdir)/Makefile.in
 ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
 am__aclocal_m4_deps = $(top_srcdir)/../config/depstand.m4 \
 	$(top_srcdir)/../config/gettext-sister.m4 \
@@ -2712,6 +2718,12 @@ uninstall-am: uninstall-info-am
 # '-Wa,-L' is required to preserve the local label used for testing.
 @GCC_TRUE@@NATIVE_LINKER_TRUE@discard_locals_test.o: discard_locals_test.c
 @GCC_TRUE@@NATIVE_LINKER_TRUE@	$(COMPILE) -c -Wa,-L -o $@ $<
+@GCC_TRUE@@NATIVE_LINKER_TRUE@libhidden.so: hidden_test_1.c gcctestdir/ld
+@GCC_TRUE@@NATIVE_LINKER_TRUE@	$(COMPILE) -Bgcctestdir/ -g -shared -fPIC -w -o $@ $(srcdir)/hidden_test_1.c
+@GCC_TRUE@@NATIVE_LINKER_TRUE@hidden_test: hidden_test_main.o libhidden.so gcctestdir/ld
+@GCC_TRUE@@NATIVE_LINKER_TRUE@	$(LINK) -Bgcctestdir/ -Wl,-R,. hidden_test_main.o libhidden.so 2>hidden_test.err
+@GCC_TRUE@@NATIVE_LINKER_TRUE@hidden_test.err: hidden_test
+@GCC_TRUE@@NATIVE_LINKER_TRUE@	@touch hidden_test.err
 # Tell versions [3.59,3.63) of GNU make to not export all variables.
 # Otherwise a system limit (for SysV at least) may be exceeded.
 .NOEXPORT:
Index: testsuite/hidden_test.sh
===================================================================
RCS file: testsuite/hidden_test.sh
diff -N testsuite/hidden_test.sh
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ testsuite/hidden_test.sh	7 Aug 2009 22:40:44 -0000
@@ -0,0 +1,66 @@
+#!/bin/sh
+
+# hidden_test.sh -- a test case for hidden and internal symbols.
+
+# Copyright 2009 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 goes with hidden_test_main.c and hidden_test_1.c.
+# The main program defines several symbols with each of the ELF
+# visibilities, and the shared library attempts to reference the
+# symbols.  We try to link the program and check that the expected
+# error messages are issued for the references to internal and
+# hidden symbols.  The errors will be found in hidden_test.err.
+
+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_missing()
+{
+    if grep -q "$2" "$1"
+    then
+	echo "Found unexpected error in $1:"
+	echo "   $2"
+	echo ""
+	echo "Actual error output below:"
+	cat "$1"
+	exit 1
+    fi
+}
+
+# We should see errors for hidden and internal symbols.
+check hidden_test.err "hidden symbol 'main_hidden' in hidden_test_main.o is referenced by DSO libhidden.so"
+check hidden_test.err "internal symbol 'main_internal' in hidden_test_main.o is referenced by DSO libhidden.so"
+
+# We shouldn't see errors for the default and protected symbols.
+check_missing hidden_test.err "main_default"
+check_missing hidden_test.err "main_protected"
+
+exit 0
Index: testsuite/hidden_test_1.c
===================================================================
RCS file: testsuite/hidden_test_1.c
diff -N testsuite/hidden_test_1.c
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ testsuite/hidden_test_1.c	7 Aug 2009 22:40:44 -0000
@@ -0,0 +1,41 @@
+/* hidden_test_1.c -- test hidden and internal symbols
+
+   Copyright 2009 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 is a test of symbols of various visibilities in the main program
+   and attempts to reference those symbols from a shared library.
+   The linker should issue an error message for references to hidden
+   and internal symbols.  */
+
+extern void main_default (void);
+extern void main_hidden (void);
+extern void main_internal (void);
+extern void main_protected (void);
+
+int
+lib1 (void)
+{
+  main_default ();
+  main_hidden ();
+  main_internal ();
+  main_protected ();
+  return 0;
+}
Index: testsuite/hidden_test_main.c
===================================================================
RCS file: testsuite/hidden_test_main.c
diff -N testsuite/hidden_test_main.c
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ testsuite/hidden_test_main.c	7 Aug 2009 22:40:44 -0000
@@ -0,0 +1,61 @@
+/* hidden_test_main.c -- test hidden and internal symbols
+
+   Copyright 2009 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 is a test of symbols of various visibilities in the main program
+   and attempts to reference those symbols from a shared library.
+   The linker should issue an error message for references to hidden
+   and internal symbols.  */
+
+extern void lib1 (void);
+
+void main_default (void);
+void main_hidden (void);
+void main_internal (void);
+void main_protected (void);
+
+void __attribute__((visibility ("default")))
+main_default (void)
+{
+}
+
+void __attribute__((visibility ("hidden")))
+main_hidden (void)
+{
+}
+
+void __attribute__((visibility ("internal")))
+main_internal (void)
+{
+}
+
+void __attribute__((visibility ("protected")))
+main_protected (void)
+{
+}
+
+int
+main (int argc __attribute__ ((unused)),
+      char** argv __attribute__ ((unused)))
+{
+  lib1 ();
+  return 0;
+}


More information about the Binutils mailing list