+ return bits;
+}
+
+// Resolve a symbol. This is called the second and subsequent times
+// we see a symbol. TO is the pre-existing symbol. ST_SHNDX is the
+// section index for SYM, possibly adjusted for many sections.
+// IS_ORDINARY is whether ST_SHNDX is a normal section index rather
+// than a special code. ORIG_ST_SHNDX is the original section index,
+// before any munging because of discarded sections, except that all
+// non-ordinary section indexes are mapped to SHN_UNDEF. VERSION is
+// the version of SYM.
+
+template<int size, bool big_endian>
+void
+Symbol_table::resolve(Sized_symbol<size>* to,
+ const elfcpp::Sym<size, big_endian>& sym,
+ unsigned int st_shndx, bool is_ordinary,
+ unsigned int orig_st_shndx,
+ Object* object, const char* version,
+ bool is_default_version)
+{
+ bool to_is_ordinary;
+ const unsigned int to_shndx = to->shndx(&to_is_ordinary);
+
+ // 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.
+ if (to->source() == Symbol::FROM_OBJECT
+ && to->object() == object
+ && to->is_defined()
+ && is_ordinary
+ && to_is_ordinary
+ && to_shndx == st_shndx
+ && to->value() == sym.get_st_value())
+ return;
+
+ // Likewise for an absolute symbol defined twice with the same value.
+ if (!is_ordinary
+ && st_shndx == elfcpp::SHN_ABS
+ && !to_is_ordinary
+ && to_shndx == elfcpp::SHN_ABS
+ && to->value() == sym.get_st_value())
+ return;
+
+ if (parameters->target().has_resolve())
+ {
+ Sized_target<size, big_endian>* sized_target;
+ sized_target = parameters->sized_target<size, big_endian>();
+ if (sized_target->resolve(to, sym, object, version))
+ return;
+ }
+
+ if (!object->is_dynamic())
+ {
+ if (sym.get_st_type() == elfcpp::STT_COMMON
+ && (is_ordinary || !Symbol::is_common_shndx(st_shndx)))
+ {
+ gold_warning(_("STT_COMMON symbol '%s' in %s "
+ "is not in a common section"),
+ to->demangled_name().c_str(),
+ to->object()->name().c_str());
+ return;
+ }
+ // Record that we've seen this symbol in a regular object.
+ to->set_in_reg();
+ }
+ else if (st_shndx == elfcpp::SHN_UNDEF
+ && (to->visibility() == elfcpp::STV_HIDDEN
+ || to->visibility() == elfcpp::STV_INTERNAL))
+ {
+ // The symbol is hidden, so a reference from a shared object
+ // cannot bind to it. We tried issuing a warning in this case,
+ // but that produces false positives when the symbol is
+ // actually resolved in a different shared object (PR 15574).
+ return;
+ }
+ else
+ {
+ // Record that we've seen this symbol in a dynamic object.
+ to->set_in_dyn();
+ }
+
+ // Record if we've seen this symbol in a real ELF object (i.e., the
+ // symbol is referenced from outside the world known to the plugin).
+ if (object->pluginobj() == NULL && !object->is_dynamic())
+ to->set_in_real_elf();
+
+ // If we're processing replacement files, allow new symbols to override
+ // the placeholders from the plugin objects.
+ // Treat common symbols specially since it is possible that an ELF
+ // file increased the size of the alignment.
+ if (to->source() == Symbol::FROM_OBJECT)
+ {
+ Pluginobj* obj = to->object()->pluginobj();
+ if (obj != NULL
+ && parameters->options().plugins()->in_replacement_phase())
+ {
+ bool adjust_common = false;
+ typename Sized_symbol<size>::Size_type tosize = 0;
+ typename Sized_symbol<size>::Value_type tovalue = 0;
+ if (to->is_common()
+ && !is_ordinary && Symbol::is_common_shndx(st_shndx))
+ {
+ adjust_common = true;
+ tosize = to->symsize();
+ 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;
+ }
+ }
+
+ // A new weak undefined reference, merging with an old weak
+ // reference, could be a One Definition Rule (ODR) violation --
+ // especially if the types or sizes of the references differ. We'll
+ // store such pairs and look them up later to make sure they
+ // actually refer to the same lines of code. We also check
+ // combinations of weak and strong, which might occur if one case is
+ // inline and the other is not. (Note: not all ODR violations can
+ // be found this way, and not everything this finds is an ODR
+ // violation. But it's helpful to warn about.)
+ if (parameters->options().detect_odr_violations()
+ && (sym.get_st_bind() == elfcpp::STB_WEAK
+ || to->binding() == elfcpp::STB_WEAK)
+ && orig_st_shndx != elfcpp::SHN_UNDEF
+ && to_is_ordinary
+ && to_shndx != elfcpp::SHN_UNDEF
+ && sym.get_st_size() != 0 // Ignore weird 0-sized symbols.
+ && to->symsize() != 0
+ && (sym.get_st_type() != to->type()
+ || sym.get_st_size() != to->symsize())
+ // C does not have a concept of ODR, so we only need to do this
+ // on C++ symbols. These have (mangled) names starting with _Z.
+ && to->name()[0] == '_' && to->name()[1] == 'Z')