Keep track of weak aliases, so that overriding environ works.

This commit is contained in:
Ian Lance Taylor 2007-10-14 15:35:27 +00:00
parent ad435a2465
commit aeddab66fe
3 changed files with 271 additions and 72 deletions

View file

@ -71,6 +71,35 @@ Sized_symbol<size>::override(const elfcpp::Sym<size, big_endian>& sym,
this->symsize_ = sym.get_st_size();
}
// Override TOSYM with symbol FROMSYM, defined in OBJECT, with version
// VERSION. This handles all aliases of TOSYM.
template<int size, bool big_endian>
void
Symbol_table::override(Sized_symbol<size>* tosym,
const elfcpp::Sym<size, big_endian>& fromsym,
Object* object, const char* version)
{
tosym->override(fromsym, object, version);
if (tosym->has_alias())
{
Symbol* sym = this->weak_aliases_[tosym];
gold_assert(sym != NULL);
Sized_symbol<size>* ssym;
ssym = this->get_sized_symbol SELECT_SIZE_NAME(size) (sym
SELECT_SIZE(size));
do
{
ssym->override(fromsym, object, version);
sym = this->weak_aliases_[ssym];
gold_assert(sym != NULL);
ssym = this->get_sized_symbol SELECT_SIZE_NAME(size) (
sym SELECT_SIZE(size));
}
while (ssym != tosym);
}
}
// The resolve functions build a little code for each symbol.
// Bit 0: 0 for global, 1 for weak.
// Bit 1: 0 for regular object, 1 for shared object
@ -175,7 +204,7 @@ Symbol_table::resolve(Sized_symbol<size>* to,
{
typename Sized_symbol<size>::Size_type tosize = to->symsize();
to->override(sym, object, version);
this->override(to, sym, object, version);
if (adjust_common_sizes && tosize > to->symsize())
to->set_symsize(tosize);
@ -636,6 +665,34 @@ Sized_symbol<size>::override_with_special(const Sized_symbol<size>* from)
this->symsize_ = from->symsize_;
}
// Override TOSYM with the special symbol FROMSYM. This handles all
// aliases of TOSYM.
template<int size>
void
Symbol_table::override_with_special(Sized_symbol<size>* tosym,
const Sized_symbol<size>* fromsym)
{
tosym->override_with_special(fromsym);
if (tosym->has_alias())
{
Symbol* sym = this->weak_aliases_[tosym];
gold_assert(sym != NULL);
Sized_symbol<size>* ssym;
ssym = this->get_sized_symbol SELECT_SIZE_NAME(size) (sym
SELECT_SIZE(size));
do
{
ssym->override_with_special(fromsym);
sym = this->weak_aliases_[ssym];
gold_assert(sym != NULL);
ssym = this->get_sized_symbol SELECT_SIZE_NAME(size) (
sym SELECT_SIZE(size));
}
while (ssym != tosym);
}
}
// Instantiate the templates we need. We could use the configure
// script to restrict this to only the ones needed for implemented
// targets.
@ -683,13 +740,15 @@ Symbol_table::resolve<64, true>(
#if defined(HAVE_TARGET_32_LITTLE) || defined(HAVE_TARGET_32_BIG)
template
void
Sized_symbol<32>::override_with_special(const Sized_symbol<32>*);
Symbol_table::override_with_special<32>(Sized_symbol<32>*,
const Sized_symbol<32>*);
#endif
#if defined(HAVE_TARGET_64_LITTLE) || defined(HAVE_TARGET_64_BIG)
template
void
Sized_symbol<64>::override_with_special(const Sized_symbol<64>*);
Symbol_table::override_with_special<64>(Sized_symbol<64>*,
const Sized_symbol<64>*);
#endif
} // End namespace gold.