mirror of
https://github.com/espressif/binutils-gdb.git
synced 2025-09-10 08:02:20 +08:00
More symbol resolution code.
This commit is contained in:
@ -437,6 +437,13 @@ elf_st_nonvis(unsigned char other)
|
|||||||
return static_cast<STV>(other >> 2);
|
return static_cast<STV>(other >> 2);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
inline unsigned char
|
||||||
|
elf_st_other(STV vis, unsigned char nonvis)
|
||||||
|
{
|
||||||
|
return ((nonvis << 2)
|
||||||
|
+ (static_cast<unsigned char>(vis) & 3));
|
||||||
|
}
|
||||||
|
|
||||||
} // End namespace elfcpp.
|
} // End namespace elfcpp.
|
||||||
|
|
||||||
// Include internal details after defining the types.
|
// Include internal details after defining the types.
|
||||||
@ -641,6 +648,56 @@ class Sym
|
|||||||
const internal::Sym_data<size>* p_;
|
const internal::Sym_data<size>* p_;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// Writer class for an ELF symbol table entry.
|
||||||
|
|
||||||
|
template<int size, bool big_endian>
|
||||||
|
class Sym_write
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
Sym_write(unsigned char* p)
|
||||||
|
: p_(reinterpret_cast<internal::Sym_data<size>*>(p))
|
||||||
|
{ }
|
||||||
|
|
||||||
|
void
|
||||||
|
put_st_name(Elf_Word v)
|
||||||
|
{ this->p_->st_name = internal::convert_word<big_endian>(v); }
|
||||||
|
|
||||||
|
void
|
||||||
|
put_st_value(typename Elf_types<size>::Elf_Addr v)
|
||||||
|
{ this->p_->st_value = internal::convert_addr<size, big_endian>(v); }
|
||||||
|
|
||||||
|
void
|
||||||
|
put_st_size(typename Elf_types<size>::Elf_WXword v)
|
||||||
|
{ this->p_->st_size = internal::convert_wxword<size, big_endian>(v); }
|
||||||
|
|
||||||
|
void
|
||||||
|
put_st_info(unsigned char v)
|
||||||
|
{ this->p_->st_info = v; }
|
||||||
|
|
||||||
|
void
|
||||||
|
put_st_info(STB bind, STT type)
|
||||||
|
{ this->p_->st_info = elf_st_info(bind, type); }
|
||||||
|
|
||||||
|
void
|
||||||
|
put_st_other(unsigned char v)
|
||||||
|
{ this->p_->st_other = v; }
|
||||||
|
|
||||||
|
void
|
||||||
|
put_st_other(STV vis, unsigned char nonvis)
|
||||||
|
{ this->p_->st_other = elf_st_other(vis, nonvis); }
|
||||||
|
|
||||||
|
void
|
||||||
|
put_st_shndx(Elf_Half v)
|
||||||
|
{ this->p_->st_shndx = internal::convert_half<big_endian>(v); }
|
||||||
|
|
||||||
|
Sym<size, big_endian>
|
||||||
|
sym()
|
||||||
|
{ return Sym<size, big_endian>(reinterpret_cast<unsigned char*>(this->p_)); }
|
||||||
|
|
||||||
|
private:
|
||||||
|
internal::Sym_data<size>* p_;
|
||||||
|
};
|
||||||
|
|
||||||
} // End namespace elfcpp.
|
} // End namespace elfcpp.
|
||||||
|
|
||||||
#endif // !defined(ELFPCP_H)
|
#endif // !defined(ELFPCP_H)
|
||||||
|
@ -8,7 +8,7 @@ msgid ""
|
|||||||
msgstr ""
|
msgstr ""
|
||||||
"Project-Id-Version: PACKAGE VERSION\n"
|
"Project-Id-Version: PACKAGE VERSION\n"
|
||||||
"Report-Msgid-Bugs-To: \n"
|
"Report-Msgid-Bugs-To: \n"
|
||||||
"POT-Creation-Date: 2006-08-18 15:26-0700\n"
|
"POT-Creation-Date: 2006-09-07 14:17-0700\n"
|
||||||
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
|
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
|
||||||
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
|
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
|
||||||
"Language-Team: LANGUAGE <LL@li.org>\n"
|
"Language-Team: LANGUAGE <LL@li.org>\n"
|
||||||
@ -220,22 +220,22 @@ msgstr ""
|
|||||||
msgid "%s: -%c: %s\n"
|
msgid "%s: -%c: %s\n"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: resolve.cc:103
|
#: resolve.cc:135
|
||||||
#, c-format
|
#, c-format
|
||||||
msgid "%s: %s: invalid STB_LOCAL symbol %s in external symbols\n"
|
msgid "%s: %s: invalid STB_LOCAL symbol %s in external symbols\n"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: resolve.cc:109
|
#: resolve.cc:141
|
||||||
#, c-format
|
#, c-format
|
||||||
msgid "%s: %s: unsupported symbol binding %d for symbol %s\n"
|
msgid "%s: %s: unsupported symbol binding %d for symbol %s\n"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: symtab.cc:262
|
#: symtab.cc:271
|
||||||
#, c-format
|
#, c-format
|
||||||
msgid "%s: %s: mixing 32-bit and 64-bit ELF objects\n"
|
msgid "%s: %s: mixing 32-bit and 64-bit ELF objects\n"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: symtab.cc:275
|
#: symtab.cc:284
|
||||||
#, c-format
|
#, c-format
|
||||||
msgid "%s: %s: bad symbol name offset %u at %lu\n"
|
msgid "%s: %s: bad symbol name offset %u at %lu\n"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
152
gold/resolve.cc
152
gold/resolve.cc
@ -10,13 +10,43 @@
|
|||||||
namespace gold
|
namespace gold
|
||||||
{
|
{
|
||||||
|
|
||||||
|
// Symbol methods used in this file.
|
||||||
|
|
||||||
|
// Override the fields in Symbol.
|
||||||
|
|
||||||
|
template<int size, bool big_endian>
|
||||||
|
void
|
||||||
|
Symbol::override_base(const elfcpp::Sym<size, big_endian>& sym,
|
||||||
|
Object* object)
|
||||||
|
{
|
||||||
|
this->object_ = object;
|
||||||
|
this->shnum_ = sym.get_st_shndx(); // FIXME: Handle SHN_XINDEX.
|
||||||
|
this->type_ = sym.get_st_type();
|
||||||
|
this->binding_ = sym.get_st_bind();
|
||||||
|
this->visibility_ = sym.get_st_visibility();
|
||||||
|
this->other_ = sym.get_st_nonvis();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Override the fields in Sized_symbol.
|
||||||
|
|
||||||
|
template<int size>
|
||||||
|
template<bool big_endian>
|
||||||
|
void
|
||||||
|
Sized_symbol<size>::override(const elfcpp::Sym<size, big_endian>& sym,
|
||||||
|
Object* object)
|
||||||
|
{
|
||||||
|
this->override_base(sym, object);
|
||||||
|
this->value_ = sym.get_st_value();
|
||||||
|
this->size_ = sym.get_st_size();
|
||||||
|
}
|
||||||
|
|
||||||
// Resolve a symbol. This is called the second and subsequent times
|
// Resolve a symbol. This is called the second and subsequent times
|
||||||
// we see a symbol. TO is the pre-existing symbol. SYM is the new
|
// we see a symbol. TO is the pre-existing symbol. SYM is the new
|
||||||
// symbol, seen in OBJECT.
|
// symbol, seen in OBJECT.
|
||||||
|
|
||||||
template<int size, bool big_endian>
|
template<int size, bool big_endian>
|
||||||
void
|
void
|
||||||
Symbol_table::resolve(Symbol* to,
|
Symbol_table::resolve(Sized_symbol<size>* to,
|
||||||
const elfcpp::Sym<size, big_endian>& sym,
|
const elfcpp::Sym<size, big_endian>& sym,
|
||||||
Object* object)
|
Object* object)
|
||||||
{
|
{
|
||||||
@ -84,6 +114,8 @@ Symbol_table::resolve(Symbol* to,
|
|||||||
break;
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
|
if (to->type() == elfcpp::STT_COMMON)
|
||||||
|
tobits |= (2 << 2);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -113,7 +145,12 @@ Symbol_table::resolve(Symbol* to,
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (object->is_dynamic())
|
if (object->is_dynamic())
|
||||||
frombits |= (1 << 1);
|
{
|
||||||
|
frombits |= (1 << 1);
|
||||||
|
|
||||||
|
// Record that we've seen this symbol in a dynamic object.
|
||||||
|
to->set_in_dyn();
|
||||||
|
}
|
||||||
|
|
||||||
switch (sym.get_st_shndx())
|
switch (sym.get_st_shndx())
|
||||||
{
|
{
|
||||||
@ -126,9 +163,13 @@ Symbol_table::resolve(Symbol* to,
|
|||||||
break;
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
|
if (sym.get_st_type() == elfcpp::STT_COMMON)
|
||||||
|
frombits |= (2 << 2);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// FIXME: Warn if either but not both of TO and SYM are STT_TLS.
|
||||||
|
|
||||||
// We use a giant switch table for symbol resolution. This code is
|
// We use a giant switch table for symbol resolution. This code is
|
||||||
// unwieldy, but: 1) it is efficient; 2) we definitely handle all
|
// unwieldy, but: 1) it is efficient; 2) we definitely handle all
|
||||||
// cases; 3) it is easy to change the handling of a particular case.
|
// cases; 3) it is easy to change the handling of a particular case.
|
||||||
@ -147,64 +188,124 @@ Symbol_table::resolve(Symbol* to,
|
|||||||
return;
|
return;
|
||||||
|
|
||||||
case WEAK_DEF * 16 + DEF:
|
case WEAK_DEF * 16 + DEF:
|
||||||
// In the original SVR4 linker, a weak definition followed by a
|
// We've seen a weak definition, and now we see a strong
|
||||||
// regular definition was treated as a multiple definition
|
// definition. In the original SVR4 linker, this was treated as
|
||||||
// error. In the Solaris linker and the GNU linker, a weak
|
// a multiple definition error. In the Solaris linker and the
|
||||||
// definition followed by a regular definition causes the
|
// GNU linker, a weak definition followed by a regular
|
||||||
// regular definition to be ignored. We are currently
|
// definition causes the weak definition to be overridden. We
|
||||||
// compatible with the GNU linker. In the future we should add
|
// are currently compatible with the GNU linker. In the future
|
||||||
// a target specific option to change this. FIXME.
|
// we should add a target specific option to change this.
|
||||||
|
// FIXME.
|
||||||
|
to->override(sym, object);
|
||||||
return;
|
return;
|
||||||
|
|
||||||
case DYN_DEF * 16 + DEF:
|
case DYN_DEF * 16 + DEF:
|
||||||
case DYN_WEAK_DEF * 16 + DEF:
|
case DYN_WEAK_DEF * 16 + DEF:
|
||||||
|
// We've seen a definition in a dynamic object, and now we see a
|
||||||
|
// definition in a regular object. The definition in the
|
||||||
|
// regular object overrides the definition in the dynamic
|
||||||
|
// object.
|
||||||
|
to->override(sym, object);
|
||||||
|
return;
|
||||||
|
|
||||||
case UNDEF * 16 + DEF:
|
case UNDEF * 16 + DEF:
|
||||||
case WEAK_UNDEF * 16 + DEF:
|
case WEAK_UNDEF * 16 + DEF:
|
||||||
case DYN_UNDEF * 16 + DEF:
|
case DYN_UNDEF * 16 + DEF:
|
||||||
case DYN_WEAK_UNDEF * 16 + DEF:
|
case DYN_WEAK_UNDEF * 16 + DEF:
|
||||||
|
// We've seen an undefined reference, and now we see a
|
||||||
|
// definition. We use the definition.
|
||||||
|
to->override(sym, object);
|
||||||
|
return;
|
||||||
|
|
||||||
case COMMON * 16 + DEF:
|
case COMMON * 16 + DEF:
|
||||||
case WEAK_COMMON * 16 + DEF:
|
case WEAK_COMMON * 16 + DEF:
|
||||||
case DYN_COMMON * 16 + DEF:
|
case DYN_COMMON * 16 + DEF:
|
||||||
case DYN_WEAK_COMMON * 16 + DEF:
|
case DYN_WEAK_COMMON * 16 + DEF:
|
||||||
|
// We've seen a common symbol and now we see a definition. The
|
||||||
|
// definition overrides. FIXME: We should optionally issue a
|
||||||
|
// warning.
|
||||||
|
to->override(sym, object);
|
||||||
|
return;
|
||||||
|
|
||||||
case DEF * 16 + WEAK_DEF:
|
case DEF * 16 + WEAK_DEF:
|
||||||
case WEAK_DEF * 16 + WEAK_DEF:
|
case WEAK_DEF * 16 + WEAK_DEF:
|
||||||
|
// We've seen a definition and now we see a weak definition. We
|
||||||
|
// ignore the new weak definition.
|
||||||
|
return;
|
||||||
|
|
||||||
case DYN_DEF * 16 + WEAK_DEF:
|
case DYN_DEF * 16 + WEAK_DEF:
|
||||||
case DYN_WEAK_DEF * 16 + WEAK_DEF:
|
case DYN_WEAK_DEF * 16 + WEAK_DEF:
|
||||||
|
// We've seen a dynamic definition and now we see a regular weak
|
||||||
|
// definition. The regular weak definition overrides.
|
||||||
|
to->override(sym, object);
|
||||||
|
return;
|
||||||
|
|
||||||
case UNDEF * 16 + WEAK_DEF:
|
case UNDEF * 16 + WEAK_DEF:
|
||||||
case WEAK_UNDEF * 16 + WEAK_DEF:
|
case WEAK_UNDEF * 16 + WEAK_DEF:
|
||||||
case DYN_UNDEF * 16 + WEAK_DEF:
|
case DYN_UNDEF * 16 + WEAK_DEF:
|
||||||
case DYN_WEAK_UNDEF * 16 + WEAK_DEF:
|
case DYN_WEAK_UNDEF * 16 + WEAK_DEF:
|
||||||
|
// A weak definition of a currently undefined symbol.
|
||||||
|
to->override(sym, object);
|
||||||
|
return;
|
||||||
|
|
||||||
case COMMON * 16 + WEAK_DEF:
|
case COMMON * 16 + WEAK_DEF:
|
||||||
case WEAK_COMMON * 16 + WEAK_DEF:
|
case WEAK_COMMON * 16 + WEAK_DEF:
|
||||||
|
// A weak definition does not override a common definition.
|
||||||
|
return;
|
||||||
|
|
||||||
case DYN_COMMON * 16 + WEAK_DEF:
|
case DYN_COMMON * 16 + WEAK_DEF:
|
||||||
case DYN_WEAK_COMMON * 16 + WEAK_DEF:
|
case DYN_WEAK_COMMON * 16 + WEAK_DEF:
|
||||||
|
// A weak definition does override a definition in a dynamic
|
||||||
|
// object. FIXME: We should optionally issue a warning.
|
||||||
|
to->override(sym, object);
|
||||||
|
return;
|
||||||
|
|
||||||
case DEF * 16 + DYN_DEF:
|
case DEF * 16 + DYN_DEF:
|
||||||
case WEAK_DEF * 16 + DYN_DEF:
|
case WEAK_DEF * 16 + DYN_DEF:
|
||||||
case DYN_DEF * 16 + DYN_DEF:
|
case DYN_DEF * 16 + DYN_DEF:
|
||||||
case DYN_WEAK_DEF * 16 + DYN_DEF:
|
case DYN_WEAK_DEF * 16 + DYN_DEF:
|
||||||
|
// Ignore a dynamic definition if we already have a definition.
|
||||||
|
return;
|
||||||
|
|
||||||
case UNDEF * 16 + DYN_DEF:
|
case UNDEF * 16 + DYN_DEF:
|
||||||
case WEAK_UNDEF * 16 + DYN_DEF:
|
case WEAK_UNDEF * 16 + DYN_DEF:
|
||||||
case DYN_UNDEF * 16 + DYN_DEF:
|
case DYN_UNDEF * 16 + DYN_DEF:
|
||||||
case DYN_WEAK_UNDEF * 16 + DYN_DEF:
|
case DYN_WEAK_UNDEF * 16 + DYN_DEF:
|
||||||
|
// Use a dynamic definition if we have a reference.
|
||||||
|
to->override(sym, object);
|
||||||
|
return;
|
||||||
|
|
||||||
case COMMON * 16 + DYN_DEF:
|
case COMMON * 16 + DYN_DEF:
|
||||||
case WEAK_COMMON * 16 + DYN_DEF:
|
case WEAK_COMMON * 16 + DYN_DEF:
|
||||||
case DYN_COMMON * 16 + DYN_DEF:
|
case DYN_COMMON * 16 + DYN_DEF:
|
||||||
case DYN_WEAK_COMMON * 16 + DYN_DEF:
|
case DYN_WEAK_COMMON * 16 + DYN_DEF:
|
||||||
|
// Ignore a dynamic definition if we already have a common
|
||||||
|
// definition.
|
||||||
|
return;
|
||||||
|
|
||||||
case DEF * 16 + DYN_WEAK_DEF:
|
case DEF * 16 + DYN_WEAK_DEF:
|
||||||
case WEAK_DEF * 16 + DYN_WEAK_DEF:
|
case WEAK_DEF * 16 + DYN_WEAK_DEF:
|
||||||
case DYN_DEF * 16 + DYN_WEAK_DEF:
|
case DYN_DEF * 16 + DYN_WEAK_DEF:
|
||||||
case DYN_WEAK_DEF * 16 + DYN_WEAK_DEF:
|
case DYN_WEAK_DEF * 16 + DYN_WEAK_DEF:
|
||||||
|
// Ignore a weak dynamic definition if we already have a
|
||||||
|
// definition.
|
||||||
|
return;
|
||||||
|
|
||||||
case UNDEF * 16 + DYN_WEAK_DEF:
|
case UNDEF * 16 + DYN_WEAK_DEF:
|
||||||
case WEAK_UNDEF * 16 + DYN_WEAK_DEF:
|
case WEAK_UNDEF * 16 + DYN_WEAK_DEF:
|
||||||
case DYN_UNDEF * 16 + DYN_WEAK_DEF:
|
case DYN_UNDEF * 16 + DYN_WEAK_DEF:
|
||||||
case DYN_WEAK_UNDEF * 16 + DYN_WEAK_DEF:
|
case DYN_WEAK_UNDEF * 16 + DYN_WEAK_DEF:
|
||||||
|
// Use a weak dynamic definition if we have a reference.
|
||||||
|
to->override(sym, object);
|
||||||
|
return;
|
||||||
|
|
||||||
case COMMON * 16 + DYN_WEAK_DEF:
|
case COMMON * 16 + DYN_WEAK_DEF:
|
||||||
case WEAK_COMMON * 16 + DYN_WEAK_DEF:
|
case WEAK_COMMON * 16 + DYN_WEAK_DEF:
|
||||||
case DYN_COMMON * 16 + DYN_WEAK_DEF:
|
case DYN_COMMON * 16 + DYN_WEAK_DEF:
|
||||||
case DYN_WEAK_COMMON * 16 + DYN_WEAK_DEF:
|
case DYN_WEAK_COMMON * 16 + DYN_WEAK_DEF:
|
||||||
|
// Ignore a weak dynamic definition if we already have a common
|
||||||
|
// definition.
|
||||||
|
return;
|
||||||
|
|
||||||
case DEF * 16 + UNDEF:
|
case DEF * 16 + UNDEF:
|
||||||
case WEAK_DEF * 16 + UNDEF:
|
case WEAK_DEF * 16 + UNDEF:
|
||||||
@ -218,6 +319,8 @@ Symbol_table::resolve(Symbol* to,
|
|||||||
case WEAK_COMMON * 16 + UNDEF:
|
case WEAK_COMMON * 16 + UNDEF:
|
||||||
case DYN_COMMON * 16 + UNDEF:
|
case DYN_COMMON * 16 + UNDEF:
|
||||||
case DYN_WEAK_COMMON * 16 + UNDEF:
|
case DYN_WEAK_COMMON * 16 + UNDEF:
|
||||||
|
// A new undefined reference tells us nothing.
|
||||||
|
return;
|
||||||
|
|
||||||
case DEF * 16 + WEAK_UNDEF:
|
case DEF * 16 + WEAK_UNDEF:
|
||||||
case WEAK_DEF * 16 + WEAK_UNDEF:
|
case WEAK_DEF * 16 + WEAK_UNDEF:
|
||||||
@ -231,6 +334,8 @@ Symbol_table::resolve(Symbol* to,
|
|||||||
case WEAK_COMMON * 16 + WEAK_UNDEF:
|
case WEAK_COMMON * 16 + WEAK_UNDEF:
|
||||||
case DYN_COMMON * 16 + WEAK_UNDEF:
|
case DYN_COMMON * 16 + WEAK_UNDEF:
|
||||||
case DYN_WEAK_COMMON * 16 + WEAK_UNDEF:
|
case DYN_WEAK_COMMON * 16 + WEAK_UNDEF:
|
||||||
|
// A new weak undefined reference tells us nothing.
|
||||||
|
return;
|
||||||
|
|
||||||
case DEF * 16 + DYN_UNDEF:
|
case DEF * 16 + DYN_UNDEF:
|
||||||
case WEAK_DEF * 16 + DYN_UNDEF:
|
case WEAK_DEF * 16 + DYN_UNDEF:
|
||||||
@ -244,6 +349,8 @@ Symbol_table::resolve(Symbol* to,
|
|||||||
case WEAK_COMMON * 16 + DYN_UNDEF:
|
case WEAK_COMMON * 16 + DYN_UNDEF:
|
||||||
case DYN_COMMON * 16 + DYN_UNDEF:
|
case DYN_COMMON * 16 + DYN_UNDEF:
|
||||||
case DYN_WEAK_COMMON * 16 + DYN_UNDEF:
|
case DYN_WEAK_COMMON * 16 + DYN_UNDEF:
|
||||||
|
// A new dynamic undefined reference tells us nothing.
|
||||||
|
return;
|
||||||
|
|
||||||
case DEF * 16 + DYN_WEAK_UNDEF:
|
case DEF * 16 + DYN_WEAK_UNDEF:
|
||||||
case WEAK_DEF * 16 + DYN_WEAK_UNDEF:
|
case WEAK_DEF * 16 + DYN_WEAK_UNDEF:
|
||||||
@ -257,15 +364,29 @@ Symbol_table::resolve(Symbol* to,
|
|||||||
case WEAK_COMMON * 16 + DYN_WEAK_UNDEF:
|
case WEAK_COMMON * 16 + DYN_WEAK_UNDEF:
|
||||||
case DYN_COMMON * 16 + DYN_WEAK_UNDEF:
|
case DYN_COMMON * 16 + DYN_WEAK_UNDEF:
|
||||||
case DYN_WEAK_COMMON * 16 + DYN_WEAK_UNDEF:
|
case DYN_WEAK_COMMON * 16 + DYN_WEAK_UNDEF:
|
||||||
|
// A new weak dynamic undefined reference tells us nothing.
|
||||||
|
return;
|
||||||
|
|
||||||
case DEF * 16 + COMMON:
|
case DEF * 16 + COMMON:
|
||||||
|
// A common symbol does not override a definition.
|
||||||
|
return;
|
||||||
|
|
||||||
case WEAK_DEF * 16 + COMMON:
|
case WEAK_DEF * 16 + COMMON:
|
||||||
case DYN_DEF * 16 + COMMON:
|
case DYN_DEF * 16 + COMMON:
|
||||||
case DYN_WEAK_DEF * 16 + COMMON:
|
case DYN_WEAK_DEF * 16 + COMMON:
|
||||||
|
// A common symbol does override a weak definition or a dynamic
|
||||||
|
// definition.
|
||||||
|
to->override(sym, object);
|
||||||
|
return;
|
||||||
|
|
||||||
case UNDEF * 16 + COMMON:
|
case UNDEF * 16 + COMMON:
|
||||||
case WEAK_UNDEF * 16 + COMMON:
|
case WEAK_UNDEF * 16 + COMMON:
|
||||||
case DYN_UNDEF * 16 + COMMON:
|
case DYN_UNDEF * 16 + COMMON:
|
||||||
case DYN_WEAK_UNDEF * 16 + COMMON:
|
case DYN_WEAK_UNDEF * 16 + COMMON:
|
||||||
|
// A common symbol is a definition for a reference.
|
||||||
|
to->override(sym, object);
|
||||||
|
return;
|
||||||
|
|
||||||
case COMMON * 16 + COMMON:
|
case COMMON * 16 + COMMON:
|
||||||
case WEAK_COMMON * 16 + COMMON:
|
case WEAK_COMMON * 16 + COMMON:
|
||||||
case DYN_COMMON * 16 + COMMON:
|
case DYN_COMMON * 16 + COMMON:
|
||||||
@ -309,8 +430,11 @@ Symbol_table::resolve(Symbol* to,
|
|||||||
case WEAK_COMMON * 16 + DYN_WEAK_COMMON:
|
case WEAK_COMMON * 16 + DYN_WEAK_COMMON:
|
||||||
case DYN_COMMON * 16 + DYN_WEAK_COMMON:
|
case DYN_COMMON * 16 + DYN_WEAK_COMMON:
|
||||||
case DYN_WEAK_COMMON * 16 + DYN_WEAK_COMMON:
|
case DYN_WEAK_COMMON * 16 + DYN_WEAK_COMMON:
|
||||||
|
abort();
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
abort();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -321,28 +445,28 @@ Symbol_table::resolve(Symbol* to,
|
|||||||
template
|
template
|
||||||
void
|
void
|
||||||
Symbol_table::resolve<32, true>(
|
Symbol_table::resolve<32, true>(
|
||||||
Symbol* to,
|
Sized_symbol<32>* to,
|
||||||
const elfcpp::Sym<32, true>& sym,
|
const elfcpp::Sym<32, true>& sym,
|
||||||
Object* object);
|
Object* object);
|
||||||
|
|
||||||
template
|
template
|
||||||
void
|
void
|
||||||
Symbol_table::resolve<32, false>(
|
Symbol_table::resolve<32, false>(
|
||||||
Symbol* to,
|
Sized_symbol<32>* to,
|
||||||
const elfcpp::Sym<32, false>& sym,
|
const elfcpp::Sym<32, false>& sym,
|
||||||
Object* object);
|
Object* object);
|
||||||
|
|
||||||
template
|
template
|
||||||
void
|
void
|
||||||
Symbol_table::resolve<64, true>(
|
Symbol_table::resolve<64, true>(
|
||||||
Symbol* to,
|
Sized_symbol<64>* to,
|
||||||
const elfcpp::Sym<64, true>& sym,
|
const elfcpp::Sym<64, true>& sym,
|
||||||
Object* object);
|
Object* object);
|
||||||
|
|
||||||
template
|
template
|
||||||
void
|
void
|
||||||
Symbol_table::resolve<64, false>(
|
Symbol_table::resolve<64, false>(
|
||||||
Symbol* to,
|
Sized_symbol<64>* to,
|
||||||
const elfcpp::Sym<64, false>& sym,
|
const elfcpp::Sym<64, false>& sym,
|
||||||
Object* object);
|
Object* object);
|
||||||
|
|
||||||
|
@ -15,10 +15,6 @@ namespace gold
|
|||||||
|
|
||||||
// Class Symbol.
|
// Class Symbol.
|
||||||
|
|
||||||
Symbol::~Symbol()
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
// Initialize the fields in the base class Symbol.
|
// Initialize the fields in the base class Symbol.
|
||||||
|
|
||||||
template<int size, bool big_endian>
|
template<int size, bool big_endian>
|
||||||
@ -34,9 +30,10 @@ Symbol::init_base(const char* name, const char* version, Object* object,
|
|||||||
this->binding_ = sym.get_st_bind();
|
this->binding_ = sym.get_st_bind();
|
||||||
this->visibility_ = sym.get_st_visibility();
|
this->visibility_ = sym.get_st_visibility();
|
||||||
this->other_ = sym.get_st_nonvis();
|
this->other_ = sym.get_st_nonvis();
|
||||||
this->special_ = false;
|
this->is_special_ = false;
|
||||||
this->def_ = false;
|
this->is_def_ = false;
|
||||||
this->forwarder_ = false;
|
this->is_forwarder_ = false;
|
||||||
|
this->in_dyn_ = object->is_dynamic();
|
||||||
}
|
}
|
||||||
|
|
||||||
// Initialize the fields in Sized_symbol.
|
// Initialize the fields in Sized_symbol.
|
||||||
@ -107,11 +104,22 @@ Symbol_table::resolve_forwards(Symbol* from) const
|
|||||||
// Resolve a Symbol with another Symbol. This is only used in the
|
// Resolve a Symbol with another Symbol. This is only used in the
|
||||||
// unusual case where there are references to both an unversioned
|
// unusual case where there are references to both an unversioned
|
||||||
// symbol and a symbol with a version, and we then discover that that
|
// symbol and a symbol with a version, and we then discover that that
|
||||||
// version is the default version.
|
// version is the default version. Because this is unusual, we do
|
||||||
|
// this the slow way, by converting back to an ELF symbol.
|
||||||
|
|
||||||
|
template<int size, bool big_endian>
|
||||||
void
|
void
|
||||||
Symbol_table::resolve(Symbol*, const Symbol*)
|
Symbol_table::resolve(Sized_symbol<size>* to, const Sized_symbol<size>* from)
|
||||||
{
|
{
|
||||||
|
unsigned char buf[elfcpp::Elf_sizes<size>::sym_size];
|
||||||
|
elfcpp::Sym_write<size, big_endian> esym(buf);
|
||||||
|
// We don't bother to set the st_name field.
|
||||||
|
esym.put_st_value(from->value());
|
||||||
|
esym.put_st_size(from->symsize());
|
||||||
|
esym.put_st_info(from->binding(), from->type());
|
||||||
|
esym.put_st_other(from->visibility(), from->other());
|
||||||
|
esym.put_st_shndx(from->shnum());
|
||||||
|
Symbol_table::resolve(to, esym.sym(), from->object());
|
||||||
}
|
}
|
||||||
|
|
||||||
// Add one symbol from OBJECT to the symbol table. NAME is symbol
|
// Add one symbol from OBJECT to the symbol table. NAME is symbol
|
||||||
@ -162,11 +170,11 @@ Symbol_table::add_from_object(Sized_object<size, big_endian>* object,
|
|||||||
// ins.first->second: the value (Symbol*).
|
// ins.first->second: the value (Symbol*).
|
||||||
// ins.second: true if new entry was inserted, false if not.
|
// ins.second: true if new entry was inserted, false if not.
|
||||||
|
|
||||||
Symbol* ret;
|
Sized_symbol<size>* ret;
|
||||||
if (!ins.second)
|
if (!ins.second)
|
||||||
{
|
{
|
||||||
// We already have an entry for NAME/VERSION.
|
// We already have an entry for NAME/VERSION.
|
||||||
ret = ins.first->second;
|
ret = this->get_sized_symbol<size>(ins.first->second);
|
||||||
assert(ret != NULL);
|
assert(ret != NULL);
|
||||||
Symbol_table::resolve(ret, sym, object);
|
Symbol_table::resolve(ret, sym, object);
|
||||||
|
|
||||||
@ -182,7 +190,9 @@ Symbol_table::add_from_object(Sized_object<size, big_endian>* object,
|
|||||||
{
|
{
|
||||||
// This is the unfortunate case where we already have
|
// This is the unfortunate case where we already have
|
||||||
// entries for both NAME/VERSION and NAME/NULL.
|
// entries for both NAME/VERSION and NAME/NULL.
|
||||||
Symbol_table::resolve(ret, insdef.first->second);
|
const Sized_symbol<size>* sym2 =
|
||||||
|
this->get_sized_symbol<size>(insdef.first->second);
|
||||||
|
Symbol_table::resolve<size, big_endian>(ret, sym2);
|
||||||
this->make_forwarder(insdef.first->second, ret);
|
this->make_forwarder(insdef.first->second, ret);
|
||||||
insdef.first->second = ret;
|
insdef.first->second = ret;
|
||||||
}
|
}
|
||||||
@ -196,18 +206,19 @@ Symbol_table::add_from_object(Sized_object<size, big_endian>* object,
|
|||||||
{
|
{
|
||||||
// We already have an entry for NAME/NULL. Make
|
// We already have an entry for NAME/NULL. Make
|
||||||
// NAME/VERSION point to it.
|
// NAME/VERSION point to it.
|
||||||
ret = insdef.first->second;
|
ret = this->get_sized_symbol<size>(insdef.first->second);
|
||||||
Symbol_table::resolve(ret, sym, object);
|
Symbol_table::resolve(ret, sym, object);
|
||||||
ins.first->second = ret;
|
ins.first->second = ret;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
Sized_symbol<size>* rs;
|
|
||||||
Sized_target<size, big_endian>* target = object->sized_target();
|
Sized_target<size, big_endian>* target = object->sized_target();
|
||||||
if (target->has_make_symbol())
|
if (!target->has_make_symbol())
|
||||||
|
ret = new Sized_symbol<size>();
|
||||||
|
else
|
||||||
{
|
{
|
||||||
rs = target->make_symbol();
|
ret = target->make_symbol();
|
||||||
if (rs == NULL)
|
if (ret == NULL)
|
||||||
{
|
{
|
||||||
// This means that we don't want a symbol table
|
// This means that we don't want a symbol table
|
||||||
// entry after all.
|
// entry after all.
|
||||||
@ -222,11 +233,9 @@ Symbol_table::add_from_object(Sized_object<size, big_endian>* object,
|
|||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
|
||||||
rs = new Sized_symbol<size>();
|
|
||||||
rs->init(name, version, object, sym);
|
|
||||||
|
|
||||||
ret = rs;
|
ret->init(name, version, object, sym);
|
||||||
|
|
||||||
ins.first->second = ret;
|
ins.first->second = ret;
|
||||||
if (def)
|
if (def)
|
||||||
{
|
{
|
||||||
|
123
gold/symtab.h
123
gold/symtab.h
@ -32,8 +32,6 @@ class Sized_target;
|
|||||||
class Symbol
|
class Symbol
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
virtual ~Symbol();
|
|
||||||
|
|
||||||
// Return the symbol name.
|
// Return the symbol name.
|
||||||
const char*
|
const char*
|
||||||
name() const
|
name() const
|
||||||
@ -45,18 +43,6 @@ class Symbol
|
|||||||
version() const
|
version() const
|
||||||
{ return this->version_; }
|
{ return this->version_; }
|
||||||
|
|
||||||
// Return whether this symbol is a forwarder. This will never be
|
|
||||||
// true of a symbol found in the hash table, but may be true of
|
|
||||||
// symbol pointers attached to object files.
|
|
||||||
bool
|
|
||||||
is_forwarder() const
|
|
||||||
{ return this->forwarder_; }
|
|
||||||
|
|
||||||
// Mark this symbol as a forwarder.
|
|
||||||
void
|
|
||||||
set_forwarder()
|
|
||||||
{ this->forwarder_ = true; }
|
|
||||||
|
|
||||||
// Return the object with which this symbol is associated.
|
// Return the object with which this symbol is associated.
|
||||||
Object*
|
Object*
|
||||||
object() const
|
object() const
|
||||||
@ -67,11 +53,48 @@ class Symbol
|
|||||||
binding() const
|
binding() const
|
||||||
{ return this->binding_; }
|
{ return this->binding_; }
|
||||||
|
|
||||||
|
// Return the symbol type.
|
||||||
|
elfcpp::STT
|
||||||
|
type() const
|
||||||
|
{ return this->type_; }
|
||||||
|
|
||||||
|
// Return the symbol visibility.
|
||||||
|
elfcpp::STV
|
||||||
|
visibility() const
|
||||||
|
{ return this->visibility_; }
|
||||||
|
|
||||||
|
// Return the non-visibility part of the st_other field.
|
||||||
|
unsigned char
|
||||||
|
other() const
|
||||||
|
{ return this->other_; }
|
||||||
|
|
||||||
// Return the section index.
|
// Return the section index.
|
||||||
unsigned int
|
unsigned int
|
||||||
shnum() const
|
shnum() const
|
||||||
{ return this->shnum_; }
|
{ return this->shnum_; }
|
||||||
|
|
||||||
|
// Return whether this symbol is a forwarder. This will never be
|
||||||
|
// true of a symbol found in the hash table, but may be true of
|
||||||
|
// symbol pointers attached to object files.
|
||||||
|
bool
|
||||||
|
is_forwarder() const
|
||||||
|
{ return this->is_forwarder_; }
|
||||||
|
|
||||||
|
// Mark this symbol as a forwarder.
|
||||||
|
void
|
||||||
|
set_forwarder()
|
||||||
|
{ this->is_forwarder_ = true; }
|
||||||
|
|
||||||
|
// Return whether this symbol was seen in a dynamic object.
|
||||||
|
bool
|
||||||
|
in_dyn() const
|
||||||
|
{ return this->in_dyn_; }
|
||||||
|
|
||||||
|
// Mark this symbol as seen in a dynamic object.
|
||||||
|
void
|
||||||
|
set_in_dyn()
|
||||||
|
{ this->in_dyn_ = true; }
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
// Instances of this class should always be created at a specific
|
// Instances of this class should always be created at a specific
|
||||||
// size.
|
// size.
|
||||||
@ -84,6 +107,11 @@ class Symbol
|
|||||||
init_base(const char *name, const char* version, Object* object,
|
init_base(const char *name, const char* version, Object* object,
|
||||||
const elfcpp::Sym<size, big_endian>&);
|
const elfcpp::Sym<size, big_endian>&);
|
||||||
|
|
||||||
|
// Override existing symbol.
|
||||||
|
template<int size, bool big_endian>
|
||||||
|
void
|
||||||
|
override_base(const elfcpp::Sym<size, big_endian>&, Object* object);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
Symbol(const Symbol&);
|
Symbol(const Symbol&);
|
||||||
Symbol& operator=(const Symbol&);
|
Symbol& operator=(const Symbol&);
|
||||||
@ -107,9 +135,9 @@ class Symbol
|
|||||||
unsigned int other_ : 6;
|
unsigned int other_ : 6;
|
||||||
// True if this symbol always requires special target-specific
|
// True if this symbol always requires special target-specific
|
||||||
// handling.
|
// handling.
|
||||||
bool special_ : 1;
|
bool is_special_ : 1;
|
||||||
// True if this is the default version of the symbol.
|
// True if this is the default version of the symbol.
|
||||||
bool def_ : 1;
|
bool is_def_ : 1;
|
||||||
// True if this symbol really forwards to another symbol. This is
|
// True if this symbol really forwards to another symbol. This is
|
||||||
// used when we discover after the fact that two different entries
|
// used when we discover after the fact that two different entries
|
||||||
// in the hash table really refer to the same symbol. This will
|
// in the hash table really refer to the same symbol. This will
|
||||||
@ -117,7 +145,9 @@ class Symbol
|
|||||||
// for a symbol found in the list of symbols attached to an Object.
|
// for a symbol found in the list of symbols attached to an Object.
|
||||||
// It forwards to the symbol found in the forwarders_ map of
|
// It forwards to the symbol found in the forwarders_ map of
|
||||||
// Symbol_table.
|
// Symbol_table.
|
||||||
bool forwarder_ : 1;
|
bool is_forwarder_ : 1;
|
||||||
|
// True if we've seen this symbol in a dynamic object.
|
||||||
|
bool in_dyn_ : 1;
|
||||||
};
|
};
|
||||||
|
|
||||||
// The parts of a symbol which are size specific. Using a template
|
// The parts of a symbol which are size specific. Using a template
|
||||||
@ -127,6 +157,9 @@ template<int size>
|
|||||||
class Sized_symbol : public Symbol
|
class Sized_symbol : public Symbol
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
|
typedef typename elfcpp::Elf_types<size>::Elf_Addr Value_type;
|
||||||
|
typedef typename elfcpp::Elf_types<size>::Elf_WXword Size_type;
|
||||||
|
|
||||||
Sized_symbol()
|
Sized_symbol()
|
||||||
{ }
|
{ }
|
||||||
|
|
||||||
@ -136,14 +169,30 @@ class Sized_symbol : public Symbol
|
|||||||
init(const char *name, const char* version, Object* object,
|
init(const char *name, const char* version, Object* object,
|
||||||
const elfcpp::Sym<size, big_endian>&);
|
const elfcpp::Sym<size, big_endian>&);
|
||||||
|
|
||||||
|
// Override existing symbol.
|
||||||
|
template<bool big_endian>
|
||||||
|
void
|
||||||
|
override(const elfcpp::Sym<size, big_endian>&, Object* object);
|
||||||
|
|
||||||
|
// Return the symbol's value.
|
||||||
|
Value_type
|
||||||
|
value() const
|
||||||
|
{ return this->value_; }
|
||||||
|
|
||||||
|
// Return the symbol's size (we can't call this 'size' because that
|
||||||
|
// is a template parameter).
|
||||||
|
Size_type
|
||||||
|
symsize() const
|
||||||
|
{ return this->size_; }
|
||||||
|
|
||||||
private:
|
private:
|
||||||
Sized_symbol(const Sized_symbol&);
|
Sized_symbol(const Sized_symbol&);
|
||||||
Sized_symbol& operator=(const Sized_symbol&);
|
Sized_symbol& operator=(const Sized_symbol&);
|
||||||
|
|
||||||
// Symbol value.
|
// Symbol value.
|
||||||
typename elfcpp::Elf_types<size>::Elf_Addr value_;
|
Value_type value_;
|
||||||
// Symbol size.
|
// Symbol size.
|
||||||
typename elfcpp::Elf_types<size>::Elf_WXword size_;
|
Size_type size_;
|
||||||
};
|
};
|
||||||
|
|
||||||
// The main linker symbol table.
|
// The main linker symbol table.
|
||||||
@ -153,7 +202,7 @@ class Symbol_table
|
|||||||
public:
|
public:
|
||||||
Symbol_table();
|
Symbol_table();
|
||||||
|
|
||||||
virtual ~Symbol_table();
|
~Symbol_table();
|
||||||
|
|
||||||
// Add COUNT external symbols from OBJECT to the symbol table. SYMS
|
// Add COUNT external symbols from OBJECT to the symbol table. SYMS
|
||||||
// is the symbols, SYM_NAMES is their names, SYM_NAME_SIZE is the
|
// is the symbols, SYM_NAMES is their names, SYM_NAME_SIZE is the
|
||||||
@ -175,6 +224,15 @@ class Symbol_table
|
|||||||
get_size() const
|
get_size() const
|
||||||
{ return this->size_; }
|
{ return this->size_; }
|
||||||
|
|
||||||
|
// Return the sized version of a symbol in this table.
|
||||||
|
template<int size>
|
||||||
|
Sized_symbol<size>*
|
||||||
|
get_sized_symbol(Symbol*);
|
||||||
|
|
||||||
|
template<int size>
|
||||||
|
const Sized_symbol<size>*
|
||||||
|
get_sized_symbol(const Symbol*);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
Symbol_table(const Symbol_table&);
|
Symbol_table(const Symbol_table&);
|
||||||
Symbol_table& operator=(const Symbol_table&);
|
Symbol_table& operator=(const Symbol_table&);
|
||||||
@ -198,10 +256,13 @@ class Symbol_table
|
|||||||
// Resolve symbols.
|
// Resolve symbols.
|
||||||
template<int size, bool big_endian>
|
template<int size, bool big_endian>
|
||||||
static void
|
static void
|
||||||
resolve(Symbol* to, const elfcpp::Sym<size, big_endian>& sym, Object*);
|
resolve(Sized_symbol<size>* to,
|
||||||
|
const elfcpp::Sym<size, big_endian>& sym,
|
||||||
|
Object*);
|
||||||
|
|
||||||
|
template<int size, bool big_endian>
|
||||||
static void
|
static void
|
||||||
resolve(Symbol* to, const Symbol* from);
|
resolve(Sized_symbol<size>* to, const Sized_symbol<size>* from);
|
||||||
|
|
||||||
typedef std::pair<const char*, const char*> Symbol_table_key;
|
typedef std::pair<const char*, const char*> Symbol_table_key;
|
||||||
|
|
||||||
@ -233,6 +294,24 @@ class Symbol_table
|
|||||||
Unordered_map<Symbol*, Symbol*> forwarders_;
|
Unordered_map<Symbol*, Symbol*> forwarders_;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// We inline get_sized_symbol for efficiency.
|
||||||
|
|
||||||
|
template<int size>
|
||||||
|
Sized_symbol<size>*
|
||||||
|
Symbol_table::get_sized_symbol(Symbol* sym)
|
||||||
|
{
|
||||||
|
assert(size == this->get_size());
|
||||||
|
return static_cast<Sized_symbol<size>*>(sym);
|
||||||
|
}
|
||||||
|
|
||||||
|
template<int size>
|
||||||
|
const Sized_symbol<size>*
|
||||||
|
Symbol_table::get_sized_symbol(const Symbol* sym)
|
||||||
|
{
|
||||||
|
assert(size == this->get_size());
|
||||||
|
return static_cast<const Sized_symbol<size>*>(sym);
|
||||||
|
}
|
||||||
|
|
||||||
} // End namespace gold.
|
} // End namespace gold.
|
||||||
|
|
||||||
#endif // !defined(GOLD_SYMTAB_H)
|
#endif // !defined(GOLD_SYMTAB_H)
|
||||||
|
Reference in New Issue
Block a user