diff options
author | Cary Coutant <ccoutant@gmail.com> | 2016-12-21 17:32:39 -0800 |
---|---|---|
committer | Cary Coutant <ccoutant@gmail.com> | 2016-12-22 16:00:06 -0800 |
commit | 40d7d93ff412f4c34cde3daa04890d5cd2e0d9c9 (patch) | |
tree | 0f063eb01c597b5b10b609e1caee825945c01acc /gold/symtab.cc | |
parent | ce0db13751aed2782c417bc4cf715313f9273e94 (diff) | |
download | gdb-40d7d93ff412f4c34cde3daa04890d5cd2e0d9c9.zip gdb-40d7d93ff412f4c34cde3daa04890d5cd2e0d9c9.tar.gz gdb-40d7d93ff412f4c34cde3daa04890d5cd2e0d9c9.tar.bz2 |
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.
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.
Diffstat (limited to 'gold/symtab.cc')
-rw-r--r-- | gold/symtab.cc | 49 |
1 files changed, 27 insertions, 22 deletions
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 |