aboutsummaryrefslogtreecommitdiff
path: root/gold/symtab.cc
diff options
context:
space:
mode:
authorH.J. Lu <hjl.tools@gmail.com>2024-05-31 21:30:34 -0700
committerH.J. Lu <hjl.tools@gmail.com>2024-06-08 23:54:39 -0700
commit89d801850ac03d0531f7eef3d6978bec17a30a2d (patch)
tree7c8719feee02ca0df80571a765d46ce05394bd71 /gold/symtab.cc
parent2b05f934486de42f8200bf11cece21ae3bc284e6 (diff)
downloadgdb-89d801850ac03d0531f7eef3d6978bec17a30a2d.zip
gdb-89d801850ac03d0531f7eef3d6978bec17a30a2d.tar.gz
gdb-89d801850ac03d0531f7eef3d6978bec17a30a2d.tar.bz2
gold: Properly remove the versioned symbol
When the versioned symbol foo is removed from the shared library, the ".symver foo,foo@VER" directive provides binary compatibility for foo@VER. In this case, the unversioned symbol foo should be hidden and shouldn't generate a multiple definition error. PR gold/31830 * resolve.cc (Symbol_table::resolve): Move symbol version handling to ... * symtab.cc (Symbol_table::add_from_object): Here. If the hidden version from .symver is the same as the default version from the unversioned symbol, don't make the unversioned symbol the default versioned symbol. * testsuite/Makefile.am (check_SCRIPTS): Add ver_test_pr31830.sh. (check_DATA): ver_test_pr31830_a.syms and ver_test_pr31830_b.syms. (ver_test_pr31830_a.syms): New. (ver_test_pr31830_b.syms): Likewise. (ver_test_pr31830_a.so): Likewise. (ver_test_pr31830_b.so): Likewise. * testsuite/Makefile.in: Regenerated. * testsuite/ver_test_pr31830.script: New file. * testsuite/ver_test_pr31830.sh: Likewise. * testsuite/ver_test_pr31830_a.c: Likewise. * testsuite/ver_test_pr31830_b.c: Likewise. * testsuite/ver_test_pr31830_lto.c: Likewise. * testsuite/ver_test_pr31830_lto.sh: Likewise. Signed-off-by: H.J. Lu <hjl.tools@gmail.com>
Diffstat (limited to 'gold/symtab.cc')
-rw-r--r--gold/symtab.cc76
1 files changed, 65 insertions, 11 deletions
diff --git a/gold/symtab.cc b/gold/symtab.cc
index 9a55e6e..5857dd7 100644
--- a/gold/symtab.cc
+++ b/gold/symtab.cc
@@ -998,12 +998,64 @@ Symbol_table::add_from_object(Object* object,
ret = this->get_sized_symbol<size>(ins.first->second);
gold_assert(ret != NULL);
+ bool ret_is_ordinary;
+ const unsigned int ret_shndx = ret->shndx(&ret_is_ordinary);
+
was_undefined_in_reg = ret->is_undefined() && ret->in_reg();
// Commons from plugins are just placeholders.
was_common = ret->is_common() && ret->object()->pluginobj() == NULL;
- this->resolve(ret, sym, st_shndx, is_ordinary, orig_st_shndx, object,
- version, is_default_version);
+ // It's possible for a symbol to be defined in an object file
+ // using .symver to give it a version, and for there to also be
+ // a linker script giving that symbol the same version. We
+ // don't want to give a multiple-definition error for this
+ // harmless redefinition.
+ bool check_version = false;
+ bool erase_default_version = false;
+ bool no_default_version = false;
+ if (ret->source() == Symbol::FROM_OBJECT
+ && is_ordinary
+ && ret_shndx == st_shndx)
+ {
+ if (ret->object() == object)
+ check_version = true;
+
+ if (version != NULL && version == ret->version())
+ {
+ // Don't give a multiple-definition error if the hidden
+ // version from .symver is the same as the default version
+ // from the unversioned symbol.
+ if (is_default_version && !ret->is_default ())
+ {
+ no_default_version = true;
+ if (insdefault.second)
+ {
+ // Don't make the unversioned symbol the default
+ // version.
+ is_default_version = false;
+ erase_default_version = true;
+ check_version = true;
+ }
+ }
+ else if (!is_default_version && ret->is_default ())
+ {
+ // Don't make the unversioned symbol the default
+ // version.
+ ret->set_is_not_default();
+ no_default_version = true;
+ check_version = true;
+ }
+ }
+ }
+
+ if (!(check_version
+ && ret->is_defined()
+ && ret_is_ordinary
+ && (no_default_version
+ || ret->value() == sym.get_st_value())))
+ this->resolve(ret, sym, st_shndx, is_ordinary, orig_st_shndx,
+ object, version, is_default_version);
+
if (parameters->options().gc_sections())
this->gc_mark_dyn_syms(ret);
@@ -1012,13 +1064,7 @@ Symbol_table::add_from_object(Object* object,
insdefault.first);
else
{
- bool dummy;
- if (version != NULL
- && ret->source() == Symbol::FROM_OBJECT
- && ret->object() == object
- && is_ordinary
- && ret->shndx(&dummy) == st_shndx
- && ret->is_default())
+ if (version != NULL && check_version)
{
// We have seen NAME/VERSION already, and marked it as the
// default version, but now we see a definition for
@@ -1032,9 +1078,17 @@ Symbol_table::add_from_object(Object* object,
// In any other case, the two symbols should have generated
// a multiple definition error.
// (See PR gold/18703.)
- ret->set_is_not_default();
+ // If the hidden version from .symver is the same as the
+ // default version from the unversioned symbol, don't make
+ // the unversioned symbol the default versioned symbol.
const Stringpool::Key vnull_key = 0;
- this->table_.erase(std::make_pair(name_key, vnull_key));
+ if (erase_default_version)
+ this->table_.erase(std::make_pair(name_key, vnull_key));
+ else if (ret->object() == object)
+ {
+ ret->set_is_not_default();
+ this->table_.erase(std::make_pair(name_key, vnull_key));
+ }
}
}
}