Add heuristics for undefined symbol warnings.

This commit is contained in:
Ian Lance Taylor
2007-11-14 16:53:25 +00:00
parent 3e6fe5ae73
commit 9a2d698415
13 changed files with 129 additions and 48 deletions

View File

@ -1524,7 +1524,8 @@ Symbol_table::sized_finalize(unsigned index, off_t off, Stringpool* pool)
// Write out the global symbols.
void
Symbol_table::write_globals(const Target* target, const Stringpool* sympool,
Symbol_table::write_globals(const Input_objects* input_objects,
const Stringpool* sympool,
const Stringpool* dynpool, Output_file* of) const
{
if (parameters->get_size() == 32)
@ -1532,7 +1533,8 @@ Symbol_table::write_globals(const Target* target, const Stringpool* sympool,
if (parameters->is_big_endian())
{
#ifdef HAVE_TARGET_32_BIG
this->sized_write_globals<32, true>(target, sympool, dynpool, of);
this->sized_write_globals<32, true>(input_objects, sympool,
dynpool, of);
#else
gold_unreachable();
#endif
@ -1540,7 +1542,8 @@ Symbol_table::write_globals(const Target* target, const Stringpool* sympool,
else
{
#ifdef HAVE_TARGET_32_LITTLE
this->sized_write_globals<32, false>(target, sympool, dynpool, of);
this->sized_write_globals<32, false>(input_objects, sympool,
dynpool, of);
#else
gold_unreachable();
#endif
@ -1551,7 +1554,8 @@ Symbol_table::write_globals(const Target* target, const Stringpool* sympool,
if (parameters->is_big_endian())
{
#ifdef HAVE_TARGET_64_BIG
this->sized_write_globals<64, true>(target, sympool, dynpool, of);
this->sized_write_globals<64, true>(input_objects, sympool,
dynpool, of);
#else
gold_unreachable();
#endif
@ -1559,7 +1563,8 @@ Symbol_table::write_globals(const Target* target, const Stringpool* sympool,
else
{
#ifdef HAVE_TARGET_64_LITTLE
this->sized_write_globals<64, false>(target, sympool, dynpool, of);
this->sized_write_globals<64, false>(input_objects, sympool,
dynpool, of);
#else
gold_unreachable();
#endif
@ -1573,11 +1578,13 @@ Symbol_table::write_globals(const Target* target, const Stringpool* sympool,
template<int size, bool big_endian>
void
Symbol_table::sized_write_globals(const Target* target,
Symbol_table::sized_write_globals(const Input_objects* input_objects,
const Stringpool* sympool,
const Stringpool* dynpool,
Output_file* of) const
{
const Target* const target = input_objects->target();
const int sym_size = elfcpp::Elf_sizes<size>::sym_size;
unsigned int index = this->first_global_index_;
const off_t oview_size = this->output_count_ * sym_size;
@ -1599,25 +1606,8 @@ Symbol_table::sized_write_globals(const Target* target,
{
Sized_symbol<size>* sym = static_cast<Sized_symbol<size>*>(p->second);
// Optionally check for unresolved symbols in shared libraries.
// This is controlled by the --allow-shlib-undefined option. We
// only warn about libraries for which we have seen all the
// DT_NEEDED entries. We don't try to track down DT_NEEDED
// entries which were not seen in this link. If we didn't see a
// DT_NEEDED entry, we aren't going to be able to reliably
// report whether the symbol is undefined.
if (sym->source() == Symbol::FROM_OBJECT
&& sym->object()->is_dynamic()
&& sym->shndx() == elfcpp::SHN_UNDEF
&& sym->binding() != elfcpp::STB_WEAK
&& !parameters->allow_shlib_undefined())
{
// A very ugly cast.
Dynobj* dynobj = static_cast<Dynobj*>(sym->object());
if (!dynobj->has_unknown_needed_entries())
gold_error(_("%s: undefined reference to '%s'"),
sym->object()->name().c_str(), sym->name());
}
// Possibly warn about unresolved symbols in shared libraries.
this->warn_about_undefined_dynobj_symbol(input_objects, sym);
unsigned int sym_index = sym->symtab_index();
unsigned int dynsym_index;
@ -1749,6 +1739,42 @@ Symbol_table::sized_write_symbol(
osym.put_st_shndx(shndx);
}
// Check for unresolved symbols in shared libraries. This is
// controlled by the --allow-shlib-undefined option.
// We only warn about libraries for which we have seen all the
// DT_NEEDED entries. We don't try to track down DT_NEEDED entries
// which were not seen in this link. If we didn't see a DT_NEEDED
// entry, we aren't going to be able to reliably report whether the
// symbol is undefined.
// We also don't warn about libraries found in the system library
// directory (the directory were we find libc.so); we assume that
// those libraries are OK. This heuristic avoids problems in
// GNU/Linux, in which -ldl can have undefined references satisfied by
// ld-linux.so.
inline void
Symbol_table::warn_about_undefined_dynobj_symbol(
const Input_objects* input_objects,
Symbol* sym) const
{
if (sym->source() == Symbol::FROM_OBJECT
&& sym->object()->is_dynamic()
&& sym->shndx() == elfcpp::SHN_UNDEF
&& sym->binding() != elfcpp::STB_WEAK
&& !parameters->allow_shlib_undefined()
&& !input_objects->target()->is_defined_by_abi(sym)
&& !input_objects->found_in_system_library_directory(sym->object()))
{
// A very ugly cast.
Dynobj* dynobj = static_cast<Dynobj*>(sym->object());
if (!dynobj->has_unknown_needed_entries())
gold_error(_("%s: undefined reference to '%s'"),
sym->object()->name().c_str(), sym->name());
}
}
// Write out a section symbol. Return the update offset.
void