diff --git a/gold/ChangeLog b/gold/ChangeLog index 87ac625373..4b39c3fe0f 100644 --- a/gold/ChangeLog +++ b/gold/ChangeLog @@ -1,3 +1,11 @@ +2014-09-25 Cary Coutant + + PR gold/17432 + * resolve.cc (Symbol_table::resolve): Override common placeholder + symbols, but adjust sizes. + * symtab.cc (Symbol_table::add_from_object): Don't add placeholder + symbols to common lists. + 2014-09-24 Alan Modra * po/POTFILES.in: Regenerate. diff --git a/gold/resolve.cc b/gold/resolve.cc index abb5d90d77..52dae8b999 100644 --- a/gold/resolve.cc +++ b/gold/resolve.cc @@ -309,11 +309,26 @@ Symbol_table::resolve(Sized_symbol* to, { Pluginobj* obj = to->object()->pluginobj(); if (obj != NULL - && parameters->options().plugins()->in_replacement_phase() - && !to->is_common()) + && parameters->options().plugins()->in_replacement_phase()) { - this->override(to, sym, st_shndx, is_ordinary, object, version); - return; + bool adjust_common = false; + typename Sized_symbol::Size_type tosize = 0; + typename Sized_symbol::Value_type tovalue = 0; + if (to->is_common() && !is_ordinary && st_shndx == elfcpp::SHN_COMMON) + { + adjust_common = true; + typename Sized_symbol::Size_type tosize = to->symsize(); + typename Sized_symbol::Value_type tovalue = to->value(); + } + this->override(to, sym, st_shndx, is_ordinary, object, version); + if (adjust_common) + { + if (tosize > to->symsize()) + to->set_symsize(tosize); + if (tovalue > to->value()) + to->set_value(tovalue); + } + return; } } diff --git a/gold/symtab.cc b/gold/symtab.cc index 210ab25927..70fb3f04f9 100644 --- a/gold/symtab.cc +++ b/gold/symtab.cc @@ -980,7 +980,8 @@ Symbol_table::add_from_object(Object* object, gold_assert(ret != NULL); was_undefined = ret->is_undefined(); - was_common = ret->is_common(); + // 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); @@ -1003,7 +1004,8 @@ Symbol_table::add_from_object(Object* object, ret = this->get_sized_symbol(insdefault.first->second); was_undefined = ret->is_undefined(); - was_common = ret->is_common(); + // 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); @@ -1066,8 +1068,10 @@ Symbol_table::add_from_object(Object* object, } // Keep track of common symbols, to speed up common symbol - // allocation. - if (!was_common && ret->is_common()) + // allocation. Don't record commons from plugin objects; + // we need to wait until we see the real symbol in the + // replacement file. + if (!was_common && ret->is_common() && ret->object()->pluginobj() == NULL) { if (ret->type() == elfcpp::STT_TLS) this->tls_commons_.push_back(ret);