* [gold commit] Fix problem where version script causes predefined hidden symbol to be defined twice
@ 2016-12-22 1:25 Cary Coutant
0 siblings, 0 replies; only message in thread
From: Cary Coutant @ 2016-12-22 1:25 UTC (permalink / raw)
To: Binutils
[-- Attachment #1: Type: text/plain, Size: 1031 bytes --]
When creating a predefined hidden symbol like _GLOBAL_OFFSET_TABLE_,
gold was incorrectly letting a version script add a version to the
symbol, resulting in two copies of the symbol, both STB_LOCAL, but one
of which was grouped in the globals part of the symbol table.
-cary
2016-12-21 Cary Coutant <ccoutant@gmail.com>
gold/
* symtab.cc (Symbol_table::define_special_symbol): Add is_forced_local
parameter; if set, do not check version script.
(Symbol_table::do_define_in_output_data): Pass is_forced_local for
STB_LOCAL predefined symbols.
(Symbol_table::do_define_in_output_segment): Likewise.
(Symbol_table::do_define_in_output_segment): Likewise.
(Symbol_table::do_define_as_constant): Likewise.
* symtab.h (Symbol_table::define_special_symbol): Add is_forced_local
parameter. Adjust all callers.
* testsuite/Makefile.am (ver_test_8.sh): New test case.
* testsuite/Makefile.in: Regenerate.
* ver_test_8.sh: New test script.
[-- Attachment #2: local-version.patch --]
[-- Type: application/octet-stream, Size: 10004 bytes --]
Fix problem where version script causes predefined hidden symbol to be defined twice.
When creating a predefined hidden symbol like _GLOBAL_OFFSET_TABLE_, gold
was incorrectly letting a version script add a version to the symbol,
resulting in two copies of the symbol, both STB_LOCAL, but one of which
was grouped in the globals part of the symbol table.
2016-12-21 Cary Coutant <ccoutant@gmail.com>
gold/
* symtab.cc (Symbol_table::define_special_symbol): Add is_forced_local
parameter; if set, do not check version script.
(Symbol_table::do_define_in_output_data): Pass is_forced_local for
STB_LOCAL predefined symbols.
(Symbol_table::do_define_in_output_segment): Likewise.
(Symbol_table::do_define_in_output_segment): Likewise.
(Symbol_table::do_define_as_constant): Likewise.
* symtab.h (Symbol_table::define_special_symbol): Add is_forced_local
parameter. Adjust all callers.
* testsuite/Makefile.am (ver_test_8.sh): New test case.
* testsuite/Makefile.in: Regenerate.
* ver_test_8.sh: New test script.
diff --git a/gold/symtab.cc b/gold/symtab.cc
index 35989f0..d97fbdd 100644
--- a/gold/symtab.cc
+++ b/gold/symtab.cc
@@ -1759,7 +1759,7 @@ Sized_symbol<size>*
Symbol_table::define_special_symbol(const char** pname, const char** pversion,
bool only_if_ref,
Sized_symbol<size>** poldsym,
- bool* resolve_oldsym)
+ bool* resolve_oldsym, bool is_forced_local)
{
*resolve_oldsym = false;
*poldsym = NULL;
@@ -1768,7 +1768,7 @@ Symbol_table::define_special_symbol(const char** pname, const char** pversion,
// the version script.
std::string v;
bool is_default_version = false;
- if (*pversion == NULL)
+ if (!is_forced_local && *pversion == NULL)
{
bool is_global;
if (this->version_script_.get_symbol_version(*pname, &v, &is_global))
@@ -1966,13 +1966,15 @@ Symbol_table::do_define_in_output_data(
Sized_symbol<size>* sym;
Sized_symbol<size>* oldsym;
bool resolve_oldsym;
+ const bool is_forced_local = binding == elfcpp::STB_LOCAL;
if (parameters->target().is_big_endian())
{
#if defined(HAVE_TARGET_32_BIG) || defined(HAVE_TARGET_64_BIG)
sym = this->define_special_symbol<size, true>(&name, &version,
only_if_ref, &oldsym,
- &resolve_oldsym);
+ &resolve_oldsym,
+ is_forced_local);
#else
gold_unreachable();
#endif
@@ -1982,7 +1984,8 @@ Symbol_table::do_define_in_output_data(
#if defined(HAVE_TARGET_32_LITTLE) || defined(HAVE_TARGET_64_LITTLE)
sym = this->define_special_symbol<size, false>(&name, &version,
only_if_ref, &oldsym,
- &resolve_oldsym);
+ &resolve_oldsym,
+ is_forced_local);
#else
gold_unreachable();
#endif
@@ -1997,8 +2000,7 @@ Symbol_table::do_define_in_output_data(
if (oldsym == NULL)
{
- if (binding == elfcpp::STB_LOCAL
- || this->version_script_.symbol_is_local(name))
+ if (is_forced_local || this->version_script_.symbol_is_local(name))
this->force_local(sym);
else if (version != NULL)
sym->set_is_default();
@@ -2013,8 +2015,7 @@ Symbol_table::do_define_in_output_data(
else
{
if (defined == PREDEFINED
- && (binding == elfcpp::STB_LOCAL
- || this->version_script_.symbol_is_local(name)))
+ && (is_forced_local || this->version_script_.symbol_is_local(name)))
this->force_local(oldsym);
delete sym;
return oldsym;
@@ -2084,13 +2085,15 @@ Symbol_table::do_define_in_output_segment(
Sized_symbol<size>* sym;
Sized_symbol<size>* oldsym;
bool resolve_oldsym;
+ const bool is_forced_local = binding == elfcpp::STB_LOCAL;
if (parameters->target().is_big_endian())
{
#if defined(HAVE_TARGET_32_BIG) || defined(HAVE_TARGET_64_BIG)
sym = this->define_special_symbol<size, true>(&name, &version,
only_if_ref, &oldsym,
- &resolve_oldsym);
+ &resolve_oldsym,
+ is_forced_local);
#else
gold_unreachable();
#endif
@@ -2100,7 +2103,8 @@ Symbol_table::do_define_in_output_segment(
#if defined(HAVE_TARGET_32_LITTLE) || defined(HAVE_TARGET_64_LITTLE)
sym = this->define_special_symbol<size, false>(&name, &version,
only_if_ref, &oldsym,
- &resolve_oldsym);
+ &resolve_oldsym,
+ is_forced_local);
#else
gold_unreachable();
#endif
@@ -2115,8 +2119,7 @@ Symbol_table::do_define_in_output_segment(
if (oldsym == NULL)
{
- if (binding == elfcpp::STB_LOCAL
- || this->version_script_.symbol_is_local(name))
+ if (is_forced_local || this->version_script_.symbol_is_local(name))
this->force_local(sym);
else if (version != NULL)
sym->set_is_default();
@@ -2130,8 +2133,7 @@ Symbol_table::do_define_in_output_segment(
return sym;
else
{
- if (binding == elfcpp::STB_LOCAL
- || this->version_script_.symbol_is_local(name))
+ if (is_forced_local || this->version_script_.symbol_is_local(name))
this->force_local(oldsym);
delete sym;
return oldsym;
@@ -2200,13 +2202,15 @@ Symbol_table::do_define_as_constant(
Sized_symbol<size>* sym;
Sized_symbol<size>* oldsym;
bool resolve_oldsym;
+ const bool is_forced_local = binding == elfcpp::STB_LOCAL;
if (parameters->target().is_big_endian())
{
#if defined(HAVE_TARGET_32_BIG) || defined(HAVE_TARGET_64_BIG)
sym = this->define_special_symbol<size, true>(&name, &version,
only_if_ref, &oldsym,
- &resolve_oldsym);
+ &resolve_oldsym,
+ is_forced_local);
#else
gold_unreachable();
#endif
@@ -2216,7 +2220,8 @@ Symbol_table::do_define_as_constant(
#if defined(HAVE_TARGET_32_LITTLE) || defined(HAVE_TARGET_64_LITTLE)
sym = this->define_special_symbol<size, false>(&name, &version,
only_if_ref, &oldsym,
- &resolve_oldsym);
+ &resolve_oldsym,
+ is_forced_local);
#else
gold_unreachable();
#endif
@@ -2235,8 +2240,7 @@ Symbol_table::do_define_as_constant(
if ((version == NULL
|| name != version
|| value != 0)
- && (binding == elfcpp::STB_LOCAL
- || this->version_script_.symbol_is_local(name)))
+ && (is_forced_local || this->version_script_.symbol_is_local(name)))
this->force_local(sym);
else if (version != NULL
&& (name != version || value != 0))
@@ -2252,8 +2256,7 @@ Symbol_table::do_define_as_constant(
return sym;
else
{
- if (binding == elfcpp::STB_LOCAL
- || this->version_script_.symbol_is_local(name))
+ if (is_forced_local || this->version_script_.symbol_is_local(name))
this->force_local(oldsym);
delete sym;
return oldsym;
@@ -2444,7 +2447,8 @@ Symbol_table::add_undefined_symbol_from_command_line(const char* name)
#if defined(HAVE_TARGET_32_BIG) || defined(HAVE_TARGET_64_BIG)
sym = this->define_special_symbol<size, true>(&name, &version,
false, &oldsym,
- &resolve_oldsym);
+ &resolve_oldsym,
+ false);
#else
gold_unreachable();
#endif
@@ -2454,7 +2458,8 @@ Symbol_table::add_undefined_symbol_from_command_line(const char* name)
#if defined(HAVE_TARGET_32_LITTLE) || defined(HAVE_TARGET_64_LITTLE)
sym = this->define_special_symbol<size, false>(&name, &version,
false, &oldsym,
- &resolve_oldsym);
+ &resolve_oldsym,
+ false);
#else
gold_unreachable();
#endif
diff --git a/gold/symtab.h b/gold/symtab.h
index b26b4e0..d0be59f 100644
--- a/gold/symtab.h
+++ b/gold/symtab.h
@@ -1790,7 +1790,7 @@ class Symbol_table
Sized_symbol<size>*
define_special_symbol(const char** pname, const char** pversion,
bool only_if_ref, Sized_symbol<size>** poldsym,
- bool* resolve_oldsym);
+ bool* resolve_oldsym, bool is_forced_local);
// Define a symbol in an Output_data, sized version.
template<int size>
diff --git a/gold/testsuite/Makefile.am b/gold/testsuite/Makefile.am
index 7d91575..fbdc147 100644
--- a/gold/testsuite/Makefile.am
+++ b/gold/testsuite/Makefile.am
@@ -1739,6 +1739,11 @@ ver_test_8_1.so: two_file_test_1_pic.o two_file_test_1b_pic.o ver_test_8_2.so gc
ver_test_8_2.so: two_file_test_2_pic.o $(srcdir)/ver_test_8.script gcctestdir/ld
$(CXXLINK) -Bgcctestdir/ -shared -Wl,--version-script,$(srcdir)/ver_test_8.script two_file_test_2_pic.o
+check_SCRIPTS += ver_test_8.sh
+check_DATA += ver_test_8_2.so.syms
+ver_test_8_2.so.syms: ver_test_8_2.so
+ $(TEST_READELF) -s $< >$@ 2>/dev/null
+
check_PROGRAMS += ver_test_9
ver_test_9_SOURCES = ver_test_main.cc
ver_test_9_DEPENDENCIES = gcctestdir/ld ver_test_9.so
diff --git a/gold/testsuite/ver_test_8.sh b/gold/testsuite/ver_test_8.sh
new file mode 100755
index 0000000..4f46e3c
--- /dev/null
+++ b/gold/testsuite/ver_test_8.sh
@@ -0,0 +1,32 @@
+#!/bin/sh
+
+# ver_test_8.sh -- check that __GLOBAL_OFFSET_TABLE__ is defined only once.
+
+# Copyright (C) 2016 Free Software Foundation, Inc.
+# Written by Cary Coutant <ccoutant@gmail.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.
+
+count=`grep -c '_GLOBAL_OFFSET_TABLE_' ver_test_8_2.so.syms`
+
+if test "$count" -ne 1; then
+ echo "Found $count copies of '_GLOBAL_OFFSET_TABLE_' (should be only 1)"
+ exit 1
+fi
+
+exit 0
^ permalink raw reply [flat|nested] only message in thread
only message in thread, other threads:[~2016-12-22 1:25 UTC | newest]
Thread overview: (only message) (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2016-12-22 1:25 [gold commit] Fix problem where version script causes predefined hidden symbol to be defined twice Cary Coutant
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).