+ // Plugins don't provide a symbol type, so adopt the existing type
+ // if the FROM symbol is from a plugin.
+ elfcpp::STT fromtype = (object->pluginobj() != NULL
+ ? to->type()
+ : sym.get_st_type());
+ unsigned int frombits = symbol_to_bits(sym.get_st_bind(),
+ object->is_dynamic(),
+ st_shndx, is_ordinary);
+
+ bool adjust_common_sizes;
+ bool adjust_dyndef;
+ typename Sized_symbol<size>::Size_type tosize = to->symsize();
+ if (Symbol_table::should_override(to, frombits, fromtype, OBJECT,
+ object, &adjust_common_sizes,
+ &adjust_dyndef, is_default_version))
+ {
+ elfcpp::STB orig_tobinding = to->binding();
+ typename Sized_symbol<size>::Value_type tovalue = to->value();
+ this->override(to, sym, st_shndx, is_ordinary, object, version);
+ if (adjust_common_sizes)
+ {
+ if (tosize > to->symsize())
+ to->set_symsize(tosize);
+ if (tovalue > to->value())
+ to->set_value(tovalue);
+ }
+ if (adjust_dyndef)
+ {
+ // We are overriding an UNDEF or WEAK UNDEF with a DYN DEF.
+ // Remember which kind of UNDEF it was for future reference.
+ to->set_undef_binding(orig_tobinding);
+ }
+ }
+ else
+ {
+ if (adjust_common_sizes)
+ {
+ if (sym.get_st_size() > tosize)
+ to->set_symsize(sym.get_st_size());
+ if (sym.get_st_value() > to->value())
+ to->set_value(sym.get_st_value());
+ }
+ if (adjust_dyndef)
+ {
+ // We are keeping a DYN DEF after seeing an UNDEF or WEAK UNDEF.
+ // Remember which kind of UNDEF it was.
+ to->set_undef_binding(sym.get_st_bind());
+ }
+ // The ELF ABI says that even for a reference to a symbol we
+ // merge the visibility.
+ to->override_visibility(sym.get_st_visibility());
+ }
+
+ // If we have a non-WEAK reference from a regular object to a
+ // dynamic object, mark the dynamic object as needed.
+ if (to->is_from_dynobj() && to->in_reg() && !to->is_undef_binding_weak())
+ to->object()->set_is_needed();
+
+ if (adjust_common_sizes && parameters->options().warn_common())
+ {
+ if (tosize > sym.get_st_size())
+ Symbol_table::report_resolve_problem(false,
+ _("common of '%s' overriding "
+ "smaller common"),
+ to, OBJECT, object);
+ else if (tosize < sym.get_st_size())
+ Symbol_table::report_resolve_problem(false,
+ _("common of '%s' overidden by "
+ "larger common"),
+ to, OBJECT, object);
+ else
+ Symbol_table::report_resolve_problem(false,
+ _("multiple common of '%s'"),
+ to, OBJECT, object);
+ }
+}
+
+// Handle the core of symbol resolution. This is called with the
+// existing symbol, TO, and a bitflag describing the new symbol. This
+// returns true if we should override the existing symbol with the new
+// one, and returns false otherwise. It sets *ADJUST_COMMON_SIZES to
+// true if we should set the symbol size to the maximum of the TO and
+// FROM sizes. It handles error conditions.
+
+bool
+Symbol_table::should_override(const Symbol* to, unsigned int frombits,
+ elfcpp::STT fromtype, Defined defined,
+ Object* object, bool* adjust_common_sizes,
+ bool* adjust_dyndef, bool is_default_version)
+{
+ *adjust_common_sizes = false;
+ *adjust_dyndef = false;
+
+ unsigned int tobits;
+ if (to->source() == Symbol::IS_UNDEFINED)
+ tobits = symbol_to_bits(to->binding(), false, elfcpp::SHN_UNDEF, true);
+ else if (to->source() != Symbol::FROM_OBJECT)
+ tobits = symbol_to_bits(to->binding(), false, elfcpp::SHN_ABS, false);
+ else
+ {
+ bool is_ordinary;
+ unsigned int shndx = to->shndx(&is_ordinary);
+ tobits = symbol_to_bits(to->binding(),
+ to->object()->is_dynamic(),
+ shndx,
+ is_ordinary);