mirror of
https://github.com/espressif/binutils-gdb.git
synced 2025-06-23 03:29:47 +08:00
Warn about undefined references in shared libraries if we have seen
all the DT_NEEDED entries for that library.
This commit is contained in:
@ -39,7 +39,9 @@ namespace gold
|
|||||||
// see a DT_SONAME entry.
|
// see a DT_SONAME entry.
|
||||||
|
|
||||||
Dynobj::Dynobj(const std::string& name, Input_file* input_file, off_t offset)
|
Dynobj::Dynobj(const std::string& name, Input_file* input_file, off_t offset)
|
||||||
: Object(name, input_file, true, offset)
|
: Object(name, input_file, true, offset),
|
||||||
|
needed_(),
|
||||||
|
unknown_needed_(UNKNOWN_NEEDED_UNSET)
|
||||||
{
|
{
|
||||||
// This will be overridden by a DT_SONAME entry, hopefully. But if
|
// This will be overridden by a DT_SONAME entry, hopefully. But if
|
||||||
// we never see a DT_SONAME entry, our rule is to use the dynamic
|
// we never see a DT_SONAME entry, our rule is to use the dynamic
|
||||||
@ -60,14 +62,6 @@ Dynobj::Dynobj(const std::string& name, Input_file* input_file, off_t offset)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Return the string to use in a DT_NEEDED entry.
|
|
||||||
|
|
||||||
const char*
|
|
||||||
Dynobj::soname() const
|
|
||||||
{
|
|
||||||
return this->soname_.c_str();
|
|
||||||
}
|
|
||||||
|
|
||||||
// Class Sized_dynobj.
|
// Class Sized_dynobj.
|
||||||
|
|
||||||
template<int size, bool big_endian>
|
template<int size, bool big_endian>
|
||||||
@ -193,15 +187,16 @@ Sized_dynobj<size, big_endian>::read_dynsym_section(
|
|||||||
*view_info = shdr.get_sh_info();
|
*view_info = shdr.get_sh_info();
|
||||||
}
|
}
|
||||||
|
|
||||||
// Set the soname field if this shared object has a DT_SONAME tag.
|
// Read the dynamic tags. Set the soname field if this shared object
|
||||||
// PSHDRS points to the section headers. DYNAMIC_SHNDX is the section
|
// has a DT_SONAME tag. Record the DT_NEEDED tags. PSHDRS points to
|
||||||
// index of the SHT_DYNAMIC section. STRTAB_SHNDX, STRTAB, and
|
// the section headers. DYNAMIC_SHNDX is the section index of the
|
||||||
// STRTAB_SIZE are the section index and contents of a string table
|
// SHT_DYNAMIC section. STRTAB_SHNDX, STRTAB, and STRTAB_SIZE are the
|
||||||
// which may be the one associated with the SHT_DYNAMIC section.
|
// section index and contents of a string table which may be the one
|
||||||
|
// associated with the SHT_DYNAMIC section.
|
||||||
|
|
||||||
template<int size, bool big_endian>
|
template<int size, bool big_endian>
|
||||||
void
|
void
|
||||||
Sized_dynobj<size, big_endian>::set_soname(const unsigned char* pshdrs,
|
Sized_dynobj<size, big_endian>::read_dynamic(const unsigned char* pshdrs,
|
||||||
unsigned int dynamic_shndx,
|
unsigned int dynamic_shndx,
|
||||||
unsigned int strtab_shndx,
|
unsigned int strtab_shndx,
|
||||||
const unsigned char* strtabu,
|
const unsigned char* strtabu,
|
||||||
@ -236,30 +231,48 @@ Sized_dynobj<size, big_endian>::set_soname(const unsigned char* pshdrs,
|
|||||||
strtabu = this->get_view(strtabshdr.get_sh_offset(), strtab_size, false);
|
strtabu = this->get_view(strtabshdr.get_sh_offset(), strtab_size, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const char* const strtab = reinterpret_cast<const char*>(strtabu);
|
||||||
|
|
||||||
for (const unsigned char* p = pdynamic;
|
for (const unsigned char* p = pdynamic;
|
||||||
p < pdynamic + dynamic_size;
|
p < pdynamic + dynamic_size;
|
||||||
p += This::dyn_size)
|
p += This::dyn_size)
|
||||||
{
|
{
|
||||||
typename This::Dyn dyn(p);
|
typename This::Dyn dyn(p);
|
||||||
|
|
||||||
if (dyn.get_d_tag() == elfcpp::DT_SONAME)
|
switch (dyn.get_d_tag())
|
||||||
|
{
|
||||||
|
case elfcpp::DT_NULL:
|
||||||
|
// We should always see DT_NULL at the end of the dynamic
|
||||||
|
// tags.
|
||||||
|
return;
|
||||||
|
|
||||||
|
case elfcpp::DT_SONAME:
|
||||||
{
|
{
|
||||||
off_t val = dyn.get_d_val();
|
off_t val = dyn.get_d_val();
|
||||||
if (val >= strtab_size)
|
if (val >= strtab_size)
|
||||||
{
|
|
||||||
this->error(_("DT_SONAME value out of range: %lld >= %lld"),
|
this->error(_("DT_SONAME value out of range: %lld >= %lld"),
|
||||||
static_cast<long long>(val),
|
static_cast<long long>(val),
|
||||||
static_cast<long long>(strtab_size));
|
static_cast<long long>(strtab_size));
|
||||||
return;
|
else
|
||||||
}
|
|
||||||
|
|
||||||
const char* strtab = reinterpret_cast<const char*>(strtabu);
|
|
||||||
this->set_soname_string(strtab + val);
|
this->set_soname_string(strtab + val);
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
if (dyn.get_d_tag() == elfcpp::DT_NULL)
|
case elfcpp::DT_NEEDED:
|
||||||
return;
|
{
|
||||||
|
off_t val = dyn.get_d_val();
|
||||||
|
if (val >= strtab_size)
|
||||||
|
this->error(_("DT_NEEDED value out of range: %lld >= %lld"),
|
||||||
|
static_cast<long long>(val),
|
||||||
|
static_cast<long long>(strtab_size));
|
||||||
|
else
|
||||||
|
this->add_needed(strtab + val);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
this->error(_("missing DT_NULL in dynamic segment"));
|
this->error(_("missing DT_NULL in dynamic segment"));
|
||||||
@ -346,11 +359,11 @@ Sized_dynobj<size, big_endian>::do_read_symbols(Read_symbols_data* sd)
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Read the SHT_DYNAMIC section to find whether this shared object
|
// Read the SHT_DYNAMIC section to find whether this shared object
|
||||||
// has a DT_SONAME tag. This doesn't really have anything to do
|
// has a DT_SONAME tag and to record any DT_NEEDED tags. This
|
||||||
// with reading the symbols, but this is a convenient place to do
|
// doesn't really have anything to do with reading the symbols, but
|
||||||
// it.
|
// this is a convenient place to do it.
|
||||||
if (dynamic_shndx != -1U)
|
if (dynamic_shndx != -1U)
|
||||||
this->set_soname(pshdrs, dynamic_shndx, strtab_shndx,
|
this->read_dynamic(pshdrs, dynamic_shndx, strtab_shndx,
|
||||||
(sd->symbol_names == NULL
|
(sd->symbol_names == NULL
|
||||||
? NULL
|
? NULL
|
||||||
: sd->symbol_names->data()),
|
: sd->symbol_names->data()),
|
||||||
|
@ -39,11 +39,38 @@ class General_options;
|
|||||||
class Dynobj : public Object
|
class Dynobj : public Object
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
|
// We keep a list of all the DT_NEEDED entries we find.
|
||||||
|
typedef std::vector<std::string> Needed;
|
||||||
|
|
||||||
Dynobj(const std::string& name, Input_file* input_file, off_t offset = 0);
|
Dynobj(const std::string& name, Input_file* input_file, off_t offset = 0);
|
||||||
|
|
||||||
// Return the name to use in a DT_NEEDED entry for this object.
|
// Return the name to use in a DT_NEEDED entry for this object.
|
||||||
const char*
|
const char*
|
||||||
soname() const;
|
soname() const
|
||||||
|
{ return this->soname_.c_str(); }
|
||||||
|
|
||||||
|
// Return the list of DT_NEEDED strings.
|
||||||
|
const Needed&
|
||||||
|
needed() const
|
||||||
|
{ return this->needed_; }
|
||||||
|
|
||||||
|
// Return whether this dynamic object has any DT_NEEDED entries
|
||||||
|
// which were not seen during the link.
|
||||||
|
bool
|
||||||
|
has_unknown_needed_entries() const
|
||||||
|
{
|
||||||
|
gold_assert(this->unknown_needed_ != UNKNOWN_NEEDED_UNSET);
|
||||||
|
return this->unknown_needed_ == UNKNOWN_NEEDED_TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Set whether this dynamic object has any DT_NEEDED entries which
|
||||||
|
// were not seen during the link.
|
||||||
|
void
|
||||||
|
set_has_unknown_needed_entries(bool set)
|
||||||
|
{
|
||||||
|
gold_assert(this->unknown_needed_ == UNKNOWN_NEEDED_UNSET);
|
||||||
|
this->unknown_needed_ = set ? UNKNOWN_NEEDED_TRUE : UNKNOWN_NEEDED_FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
// Compute the ELF hash code for a string.
|
// Compute the ELF hash code for a string.
|
||||||
static uint32_t
|
static uint32_t
|
||||||
@ -74,6 +101,11 @@ class Dynobj : public Object
|
|||||||
set_soname_string(const char* s)
|
set_soname_string(const char* s)
|
||||||
{ this->soname_.assign(s); }
|
{ this->soname_.assign(s); }
|
||||||
|
|
||||||
|
// Add an entry to the list of DT_NEEDED strings.
|
||||||
|
void
|
||||||
|
add_needed(const char* s)
|
||||||
|
{ this->needed_.push_back(std::string(s)); }
|
||||||
|
|
||||||
private:
|
private:
|
||||||
// Compute the GNU hash code for a string.
|
// Compute the GNU hash code for a string.
|
||||||
static uint32_t
|
static uint32_t
|
||||||
@ -101,8 +133,21 @@ class Dynobj : public Object
|
|||||||
unsigned char** pphash,
|
unsigned char** pphash,
|
||||||
unsigned int* phashlen);
|
unsigned int* phashlen);
|
||||||
|
|
||||||
|
// Values for the has_unknown_needed_entries_ field.
|
||||||
|
enum Unknown_needed
|
||||||
|
{
|
||||||
|
UNKNOWN_NEEDED_UNSET,
|
||||||
|
UNKNOWN_NEEDED_TRUE,
|
||||||
|
UNKNOWN_NEEDED_FALSE
|
||||||
|
};
|
||||||
|
|
||||||
// The DT_SONAME name, if any.
|
// The DT_SONAME name, if any.
|
||||||
std::string soname_;
|
std::string soname_;
|
||||||
|
// The list of DT_NEEDED entries.
|
||||||
|
Needed needed_;
|
||||||
|
// Whether this dynamic object has any DT_NEEDED entries not seen
|
||||||
|
// during the link.
|
||||||
|
Unknown_needed unknown_needed_;
|
||||||
};
|
};
|
||||||
|
|
||||||
// A dynamic object, size and endian specific version.
|
// A dynamic object, size and endian specific version.
|
||||||
@ -187,10 +232,9 @@ class Sized_dynobj : public Dynobj
|
|||||||
File_view** view, off_t* view_size,
|
File_view** view, off_t* view_size,
|
||||||
unsigned int* view_info);
|
unsigned int* view_info);
|
||||||
|
|
||||||
// Set the SONAME from the SHT_DYNAMIC section at DYNAMIC_SHNDX.
|
// Read the dynamic tags.
|
||||||
// The STRTAB parameters may have the relevant string table.
|
|
||||||
void
|
void
|
||||||
set_soname(const unsigned char* pshdrs, unsigned int dynamic_shndx,
|
read_dynamic(const unsigned char* pshdrs, unsigned int dynamic_shndx,
|
||||||
unsigned int strtab_shndx, const unsigned char* strtabu,
|
unsigned int strtab_shndx, const unsigned char* strtabu,
|
||||||
off_t strtab_size);
|
off_t strtab_size);
|
||||||
|
|
||||||
|
@ -180,6 +180,10 @@ queue_middle_tasks(const General_options& options,
|
|||||||
(*input_objects->dynobj_begin())->name().c_str());
|
(*input_objects->dynobj_begin())->name().c_str());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// For each dynamic object, record whether we've seen all the
|
||||||
|
// dynamic objects that it depends upon.
|
||||||
|
input_objects->check_dynamic_dependencies();
|
||||||
|
|
||||||
// See if any of the input definitions violate the One Definition Rule.
|
// See if any of the input definitions violate the One Definition Rule.
|
||||||
// TODO: if this is too slow, do this as a task, rather than inline.
|
// TODO: if this is too slow, do this as a task, rather than inline.
|
||||||
symtab->detect_odr_violations();
|
symtab->detect_odr_violations();
|
||||||
|
@ -1080,6 +1080,32 @@ Input_objects::add_object(Object* obj)
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// For each dynamic object, record whether we've seen all of its
|
||||||
|
// explicit dependencies.
|
||||||
|
|
||||||
|
void
|
||||||
|
Input_objects::check_dynamic_dependencies() const
|
||||||
|
{
|
||||||
|
for (Dynobj_list::const_iterator p = this->dynobj_list_.begin();
|
||||||
|
p != this->dynobj_list_.end();
|
||||||
|
++p)
|
||||||
|
{
|
||||||
|
const Dynobj::Needed& needed((*p)->needed());
|
||||||
|
bool found_all = true;
|
||||||
|
for (Dynobj::Needed::const_iterator pneeded = needed.begin();
|
||||||
|
pneeded != needed.end();
|
||||||
|
++pneeded)
|
||||||
|
{
|
||||||
|
if (this->sonames_.find(*pneeded) == this->sonames_.end())
|
||||||
|
{
|
||||||
|
found_all = false;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
(*p)->set_has_unknown_needed_entries(!found_all);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Relocate_info methods.
|
// Relocate_info methods.
|
||||||
|
|
||||||
// Return a string describing the location of a relocation. This is
|
// Return a string describing the location of a relocation. This is
|
||||||
|
@ -951,6 +951,11 @@ class Input_objects
|
|||||||
target() const
|
target() const
|
||||||
{ return this->target_; }
|
{ return this->target_; }
|
||||||
|
|
||||||
|
// For each dynamic object, check whether we've seen all of its
|
||||||
|
// explicit dependencies.
|
||||||
|
void
|
||||||
|
check_dynamic_dependencies() const;
|
||||||
|
|
||||||
// Iterate over all regular objects.
|
// Iterate over all regular objects.
|
||||||
|
|
||||||
Relobj_iterator
|
Relobj_iterator
|
||||||
|
@ -337,6 +337,14 @@ namespace gold
|
|||||||
const options::One_option
|
const options::One_option
|
||||||
options::Command_line_options::options[] =
|
options::Command_line_options::options[] =
|
||||||
{
|
{
|
||||||
|
GENERAL_NOARG('\0', "allow-shlib-undefined",
|
||||||
|
N_("Allow unresolved references in shared libraries"),
|
||||||
|
NULL, TWO_DASHES,
|
||||||
|
&General_options::set_allow_shlib_undefined),
|
||||||
|
GENERAL_NOARG('\0', "no-allow-shlib-undefined",
|
||||||
|
N_("Do not allow unresolved references in shared libraries"),
|
||||||
|
NULL, TWO_DASHES,
|
||||||
|
&General_options::set_no_allow_shlib_undefined),
|
||||||
POSDEP_NOARG('\0', "as-needed",
|
POSDEP_NOARG('\0', "as-needed",
|
||||||
N_("Only set DT_NEEDED for dynamic libs if used"),
|
N_("Only set DT_NEEDED for dynamic libs if used"),
|
||||||
NULL, TWO_DASHES, &Position_dependent_options::set_as_needed),
|
NULL, TWO_DASHES, &Position_dependent_options::set_as_needed),
|
||||||
@ -475,6 +483,7 @@ General_options::General_options()
|
|||||||
output_file_name_("a.out"),
|
output_file_name_("a.out"),
|
||||||
is_relocatable_(false),
|
is_relocatable_(false),
|
||||||
strip_(STRIP_NONE),
|
strip_(STRIP_NONE),
|
||||||
|
allow_shlib_undefined_(false),
|
||||||
symbolic_(false),
|
symbolic_(false),
|
||||||
detect_odr_violations_(false),
|
detect_odr_violations_(false),
|
||||||
create_eh_frame_hdr_(false),
|
create_eh_frame_hdr_(false),
|
||||||
|
@ -148,6 +148,12 @@ class General_options
|
|||||||
strip_debug() const
|
strip_debug() const
|
||||||
{ return this->strip_ == STRIP_ALL || this->strip_ == STRIP_DEBUG; }
|
{ return this->strip_ == STRIP_ALL || this->strip_ == STRIP_DEBUG; }
|
||||||
|
|
||||||
|
// --allow-shlib-undefined: do not warn about unresolved symbols in
|
||||||
|
// --shared libraries.
|
||||||
|
bool
|
||||||
|
allow_shlib_undefined() const
|
||||||
|
{ return this->allow_shlib_undefined_; }
|
||||||
|
|
||||||
// -Bsymbolic: bind defined symbols locally.
|
// -Bsymbolic: bind defined symbols locally.
|
||||||
bool
|
bool
|
||||||
symbolic() const
|
symbolic() const
|
||||||
@ -300,6 +306,14 @@ class General_options
|
|||||||
set_strip_debug()
|
set_strip_debug()
|
||||||
{ this->strip_ = STRIP_DEBUG; }
|
{ this->strip_ = STRIP_DEBUG; }
|
||||||
|
|
||||||
|
void
|
||||||
|
set_allow_shlib_undefined()
|
||||||
|
{ this->allow_shlib_undefined_ = true; }
|
||||||
|
|
||||||
|
void
|
||||||
|
set_no_allow_shlib_undefined()
|
||||||
|
{ this->allow_shlib_undefined_ = false; }
|
||||||
|
|
||||||
void
|
void
|
||||||
set_symbolic()
|
set_symbolic()
|
||||||
{ this->symbolic_ = true; }
|
{ this->symbolic_ = true; }
|
||||||
@ -420,6 +434,7 @@ class General_options
|
|||||||
const char* output_file_name_;
|
const char* output_file_name_;
|
||||||
bool is_relocatable_;
|
bool is_relocatable_;
|
||||||
Strip strip_;
|
Strip strip_;
|
||||||
|
bool allow_shlib_undefined_;
|
||||||
bool symbolic_;
|
bool symbolic_;
|
||||||
bool detect_odr_violations_;
|
bool detect_odr_violations_;
|
||||||
bool create_eh_frame_hdr_;
|
bool create_eh_frame_hdr_;
|
||||||
|
@ -33,7 +33,8 @@ namespace gold
|
|||||||
Parameters::Parameters(Errors* errors)
|
Parameters::Parameters(Errors* errors)
|
||||||
: errors_(errors), output_file_name_(NULL),
|
: errors_(errors), output_file_name_(NULL),
|
||||||
output_file_type_(OUTPUT_INVALID), sysroot_(),
|
output_file_type_(OUTPUT_INVALID), sysroot_(),
|
||||||
strip_(STRIP_INVALID), symbolic_(false), detect_odr_violations_(false),
|
strip_(STRIP_INVALID), allow_shlib_undefined_(false),
|
||||||
|
symbolic_(false), detect_odr_violations_(false),
|
||||||
optimization_level_(0), export_dynamic_(false),
|
optimization_level_(0), export_dynamic_(false),
|
||||||
is_doing_static_link_valid_(false), doing_static_link_(false),
|
is_doing_static_link_valid_(false), doing_static_link_(false),
|
||||||
is_size_and_endian_valid_(false), size_(0), is_big_endian_(false)
|
is_size_and_endian_valid_(false), size_(0), is_big_endian_(false)
|
||||||
@ -47,6 +48,7 @@ Parameters::set_from_options(const General_options* options)
|
|||||||
{
|
{
|
||||||
this->output_file_name_ = options->output_file_name();
|
this->output_file_name_ = options->output_file_name();
|
||||||
this->sysroot_ = options->sysroot();
|
this->sysroot_ = options->sysroot();
|
||||||
|
this->allow_shlib_undefined_ = options->allow_shlib_undefined();
|
||||||
this->symbolic_ = options->symbolic();
|
this->symbolic_ = options->symbolic();
|
||||||
this->detect_odr_violations_ = options->detect_odr_violations();
|
this->detect_odr_violations_ = options->detect_odr_violations();
|
||||||
this->optimization_level_ = options->optimization_level();
|
this->optimization_level_ = options->optimization_level();
|
||||||
|
@ -112,6 +112,14 @@ class Parameters
|
|||||||
return this->strip_ == STRIP_ALL || this->strip_ == STRIP_DEBUG;
|
return this->strip_ == STRIP_ALL || this->strip_ == STRIP_DEBUG;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Whether to permit unresolved references from shared libraries.
|
||||||
|
bool
|
||||||
|
allow_shlib_undefined() const
|
||||||
|
{
|
||||||
|
gold_assert(this->options_valid_);
|
||||||
|
return this->allow_shlib_undefined_;
|
||||||
|
}
|
||||||
|
|
||||||
// Whether we are doing a symbolic link, in which all defined
|
// Whether we are doing a symbolic link, in which all defined
|
||||||
// symbols are bound locally.
|
// symbols are bound locally.
|
||||||
bool
|
bool
|
||||||
@ -224,6 +232,8 @@ class Parameters
|
|||||||
std::string sysroot_;
|
std::string sysroot_;
|
||||||
// Which symbols to strip.
|
// Which symbols to strip.
|
||||||
Strip strip_;
|
Strip strip_;
|
||||||
|
// Whether to allow undefined references from shared libraries.
|
||||||
|
bool allow_shlib_undefined_;
|
||||||
// Whether we are doing a symbolic link.
|
// Whether we are doing a symbolic link.
|
||||||
bool symbolic_;
|
bool symbolic_;
|
||||||
// Whether we try to detect One Definition Rule violations.
|
// Whether we try to detect One Definition Rule violations.
|
||||||
|
@ -1599,6 +1599,26 @@ Symbol_table::sized_write_globals(const Target* target,
|
|||||||
{
|
{
|
||||||
Sized_symbol<size>* sym = static_cast<Sized_symbol<size>*>(p->second);
|
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());
|
||||||
|
}
|
||||||
|
|
||||||
unsigned int sym_index = sym->symtab_index();
|
unsigned int sym_index = sym->symtab_index();
|
||||||
unsigned int dynsym_index;
|
unsigned int dynsym_index;
|
||||||
if (dynamic_view == NULL)
|
if (dynamic_view == NULL)
|
||||||
|
@ -28,12 +28,12 @@ TESTS = object_unittest
|
|||||||
|
|
||||||
if GCC
|
if GCC
|
||||||
|
|
||||||
TESTS += debug_msg.sh
|
|
||||||
|
|
||||||
check_DATA += debug_msg.err
|
|
||||||
|
|
||||||
if NATIVE_LINKER
|
if NATIVE_LINKER
|
||||||
|
|
||||||
|
TESTS += debug_msg.sh undef_symbol.sh
|
||||||
|
|
||||||
|
check_DATA += debug_msg.err undef_symbol.err
|
||||||
|
|
||||||
NATIVE_PROGS = \
|
NATIVE_PROGS = \
|
||||||
constructor_test \
|
constructor_test \
|
||||||
constructor_static_test \
|
constructor_static_test \
|
||||||
@ -116,19 +116,6 @@ object_unittest_SOURCES = object_unittest.cc
|
|||||||
|
|
||||||
if GCC
|
if GCC
|
||||||
|
|
||||||
debug_msg.o: debug_msg.cc
|
|
||||||
$(CXXCOMPILE) -O0 -g -c -w -o $@ $(srcdir)/debug_msg.cc
|
|
||||||
odr_violation1.o: odr_violation1.cc
|
|
||||||
$(CXXCOMPILE) -O0 -g -c -w -o $@ $(srcdir)/odr_violation1.cc
|
|
||||||
odr_violation2.o: odr_violation2.cc
|
|
||||||
$(CXXCOMPILE) -O0 -g -c -w -o $@ $(srcdir)/odr_violation2.cc
|
|
||||||
debug_msg.err: debug_msg.o odr_violation1.o odr_violation2.o
|
|
||||||
if $(CXXLINK) -Bgcctestdir/ -Wl,--detect-odr-violations -o debug_msg debug_msg.o odr_violation1.o odr_violation2.o 2>$@; \
|
|
||||||
then \
|
|
||||||
echo 2>&1 "Link of debug_msg.o should have failed"; \
|
|
||||||
exit 1; \
|
|
||||||
fi
|
|
||||||
|
|
||||||
if NATIVE_LINKER
|
if NATIVE_LINKER
|
||||||
|
|
||||||
gcctestdir/ld: ../ld-new
|
gcctestdir/ld: ../ld-new
|
||||||
@ -136,6 +123,32 @@ gcctestdir/ld: ../ld-new
|
|||||||
rm -f gcctestdir/ld
|
rm -f gcctestdir/ld
|
||||||
(cd gcctestdir && $(LN_S) ../../ld-new ld)
|
(cd gcctestdir && $(LN_S) ../../ld-new ld)
|
||||||
|
|
||||||
|
debug_msg.o: debug_msg.cc
|
||||||
|
$(CXXCOMPILE) -O0 -g -c -w -o $@ $(srcdir)/debug_msg.cc
|
||||||
|
odr_violation1.o: odr_violation1.cc
|
||||||
|
$(CXXCOMPILE) -O0 -g -c -w -o $@ $(srcdir)/odr_violation1.cc
|
||||||
|
odr_violation2.o: odr_violation2.cc
|
||||||
|
$(CXXCOMPILE) -O0 -g -c -w -o $@ $(srcdir)/odr_violation2.cc
|
||||||
|
debug_msg.err: debug_msg.o odr_violation1.o odr_violation2.o gcctestdir/ld
|
||||||
|
@echo $(CXXLINK) -Bgcctestdir/ -Wl,--detect-odr-violations -o debug_msg debug_msg.o odr_violation1.o odr_violation2.o "2>$@"
|
||||||
|
@if $(CXXLINK) -Bgcctestdir/ -Wl,--detect-odr-violations -o debug_msg debug_msg.o odr_violation1.o odr_violation2.o 2>$@; \
|
||||||
|
then \
|
||||||
|
echo 1>&2 "Link of debug_msg.o should have failed"; \
|
||||||
|
exit 1; \
|
||||||
|
fi
|
||||||
|
|
||||||
|
undef_symbol.o: undef_symbol.cc
|
||||||
|
$(CXXCOMPILE) -O0 -g -c -fPIC $<
|
||||||
|
undef_symbol.so: undef_symbol.o
|
||||||
|
$(CXXLINK) -shared undef_symbol.o
|
||||||
|
undef_symbol.err: undef_symbol_main.o undef_symbol.so gcctestdir/ld
|
||||||
|
@echo $(CXXLINK) -Bgcctestdir/ -o undef_symbol_test undef_symbol_main.o undef_symbol.so "2>$@"
|
||||||
|
@if $(CXXLINK) -Bgcctestdir/ -o undef_symbol_test undef_symbol_main.o undef_symbol.so 2>$@; \
|
||||||
|
then \
|
||||||
|
echo 1>&2 "Link of undef_symbol_test should have failed"; \
|
||||||
|
exit 1; \
|
||||||
|
fi
|
||||||
|
|
||||||
# Override the default CXXFLAGS--we don't want any optimization
|
# Override the default CXXFLAGS--we don't want any optimization
|
||||||
basic_test.o: basic_test.cc
|
basic_test.o: basic_test.cc
|
||||||
$(CXXCOMPILE) -O0 -c -o $@ $<
|
$(CXXCOMPILE) -O0 -c -o $@ $<
|
||||||
|
@ -42,8 +42,8 @@ POST_UNINSTALL = :
|
|||||||
build_triplet = @build@
|
build_triplet = @build@
|
||||||
host_triplet = @host@
|
host_triplet = @host@
|
||||||
target_triplet = @target@
|
target_triplet = @target@
|
||||||
@GCC_TRUE@am__append_1 = debug_msg.sh
|
@GCC_TRUE@@NATIVE_LINKER_TRUE@am__append_1 = debug_msg.sh undef_symbol.sh
|
||||||
@GCC_TRUE@am__append_2 = debug_msg.err
|
@GCC_TRUE@@NATIVE_LINKER_TRUE@am__append_2 = debug_msg.err undef_symbol.err
|
||||||
@FN_PTRS_IN_SO_WITHOUT_PIC_TRUE@@GCC_TRUE@@NATIVE_LINKER_TRUE@am__append_3 = \
|
@FN_PTRS_IN_SO_WITHOUT_PIC_TRUE@@GCC_TRUE@@NATIVE_LINKER_TRUE@am__append_3 = \
|
||||||
@FN_PTRS_IN_SO_WITHOUT_PIC_TRUE@@GCC_TRUE@@NATIVE_LINKER_TRUE@ two_file_shared_1_nonpic_test \
|
@FN_PTRS_IN_SO_WITHOUT_PIC_TRUE@@GCC_TRUE@@NATIVE_LINKER_TRUE@ two_file_shared_1_nonpic_test \
|
||||||
@FN_PTRS_IN_SO_WITHOUT_PIC_TRUE@@GCC_TRUE@@NATIVE_LINKER_TRUE@ two_file_shared_2_nonpic_test \
|
@FN_PTRS_IN_SO_WITHOUT_PIC_TRUE@@GCC_TRUE@@NATIVE_LINKER_TRUE@ two_file_shared_2_nonpic_test \
|
||||||
@ -1204,24 +1204,37 @@ uninstall-am: uninstall-info-am
|
|||||||
tags uninstall uninstall-am uninstall-info-am
|
tags uninstall uninstall-am uninstall-info-am
|
||||||
|
|
||||||
|
|
||||||
@GCC_TRUE@debug_msg.o: debug_msg.cc
|
|
||||||
@GCC_TRUE@ $(CXXCOMPILE) -O0 -g -c -w -o $@ $(srcdir)/debug_msg.cc
|
|
||||||
@GCC_TRUE@odr_violation1.o: odr_violation1.cc
|
|
||||||
@GCC_TRUE@ $(CXXCOMPILE) -O0 -g -c -w -o $@ $(srcdir)/odr_violation1.cc
|
|
||||||
@GCC_TRUE@odr_violation2.o: odr_violation2.cc
|
|
||||||
@GCC_TRUE@ $(CXXCOMPILE) -O0 -g -c -w -o $@ $(srcdir)/odr_violation2.cc
|
|
||||||
@GCC_TRUE@debug_msg.err: debug_msg.o odr_violation1.o odr_violation2.o
|
|
||||||
@GCC_TRUE@ if $(CXXLINK) -Bgcctestdir/ -Wl,--detect-odr-violations -o debug_msg debug_msg.o odr_violation1.o odr_violation2.o 2>$@; \
|
|
||||||
@GCC_TRUE@ then \
|
|
||||||
@GCC_TRUE@ echo 2>&1 "Link of debug_msg.o should have failed"; \
|
|
||||||
@GCC_TRUE@ exit 1; \
|
|
||||||
@GCC_TRUE@ fi
|
|
||||||
|
|
||||||
@GCC_TRUE@@NATIVE_LINKER_TRUE@gcctestdir/ld: ../ld-new
|
@GCC_TRUE@@NATIVE_LINKER_TRUE@gcctestdir/ld: ../ld-new
|
||||||
@GCC_TRUE@@NATIVE_LINKER_TRUE@ test -d gcctestdir || mkdir -p gcctestdir
|
@GCC_TRUE@@NATIVE_LINKER_TRUE@ test -d gcctestdir || mkdir -p gcctestdir
|
||||||
@GCC_TRUE@@NATIVE_LINKER_TRUE@ rm -f gcctestdir/ld
|
@GCC_TRUE@@NATIVE_LINKER_TRUE@ rm -f gcctestdir/ld
|
||||||
@GCC_TRUE@@NATIVE_LINKER_TRUE@ (cd gcctestdir && $(LN_S) ../../ld-new ld)
|
@GCC_TRUE@@NATIVE_LINKER_TRUE@ (cd gcctestdir && $(LN_S) ../../ld-new ld)
|
||||||
|
|
||||||
|
@GCC_TRUE@@NATIVE_LINKER_TRUE@debug_msg.o: debug_msg.cc
|
||||||
|
@GCC_TRUE@@NATIVE_LINKER_TRUE@ $(CXXCOMPILE) -O0 -g -c -w -o $@ $(srcdir)/debug_msg.cc
|
||||||
|
@GCC_TRUE@@NATIVE_LINKER_TRUE@odr_violation1.o: odr_violation1.cc
|
||||||
|
@GCC_TRUE@@NATIVE_LINKER_TRUE@ $(CXXCOMPILE) -O0 -g -c -w -o $@ $(srcdir)/odr_violation1.cc
|
||||||
|
@GCC_TRUE@@NATIVE_LINKER_TRUE@odr_violation2.o: odr_violation2.cc
|
||||||
|
@GCC_TRUE@@NATIVE_LINKER_TRUE@ $(CXXCOMPILE) -O0 -g -c -w -o $@ $(srcdir)/odr_violation2.cc
|
||||||
|
@GCC_TRUE@@NATIVE_LINKER_TRUE@debug_msg.err: debug_msg.o odr_violation1.o odr_violation2.o gcctestdir/ld
|
||||||
|
@GCC_TRUE@@NATIVE_LINKER_TRUE@ @echo $(CXXLINK) -Bgcctestdir/ -Wl,--detect-odr-violations -o debug_msg debug_msg.o odr_violation1.o odr_violation2.o "2>$@"
|
||||||
|
@GCC_TRUE@@NATIVE_LINKER_TRUE@ @if $(CXXLINK) -Bgcctestdir/ -Wl,--detect-odr-violations -o debug_msg debug_msg.o odr_violation1.o odr_violation2.o 2>$@; \
|
||||||
|
@GCC_TRUE@@NATIVE_LINKER_TRUE@ then \
|
||||||
|
@GCC_TRUE@@NATIVE_LINKER_TRUE@ echo 1>&2 "Link of debug_msg.o should have failed"; \
|
||||||
|
@GCC_TRUE@@NATIVE_LINKER_TRUE@ exit 1; \
|
||||||
|
@GCC_TRUE@@NATIVE_LINKER_TRUE@ fi
|
||||||
|
|
||||||
|
@GCC_TRUE@@NATIVE_LINKER_TRUE@undef_symbol.o: undef_symbol.cc
|
||||||
|
@GCC_TRUE@@NATIVE_LINKER_TRUE@ $(CXXCOMPILE) -O0 -g -c -fPIC $<
|
||||||
|
@GCC_TRUE@@NATIVE_LINKER_TRUE@undef_symbol.so: undef_symbol.o
|
||||||
|
@GCC_TRUE@@NATIVE_LINKER_TRUE@ $(CXXLINK) -shared undef_symbol.o
|
||||||
|
@GCC_TRUE@@NATIVE_LINKER_TRUE@undef_symbol.err: undef_symbol_main.o undef_symbol.so gcctestdir/ld
|
||||||
|
@GCC_TRUE@@NATIVE_LINKER_TRUE@ @echo $(CXXLINK) -Bgcctestdir/ -o undef_symbol_test undef_symbol_main.o undef_symbol.so "2>$@"
|
||||||
|
@GCC_TRUE@@NATIVE_LINKER_TRUE@ @if $(CXXLINK) -Bgcctestdir/ -o undef_symbol_test undef_symbol_main.o undef_symbol.so 2>$@; \
|
||||||
|
@GCC_TRUE@@NATIVE_LINKER_TRUE@ then \
|
||||||
|
@GCC_TRUE@@NATIVE_LINKER_TRUE@ echo 1>&2 "Link of undef_symbol_test should have failed"; \
|
||||||
|
@GCC_TRUE@@NATIVE_LINKER_TRUE@ exit 1; \
|
||||||
|
@GCC_TRUE@@NATIVE_LINKER_TRUE@ fi
|
||||||
|
|
||||||
# Override the default CXXFLAGS--we don't want any optimization
|
# Override the default CXXFLAGS--we don't want any optimization
|
||||||
@GCC_TRUE@@NATIVE_LINKER_TRUE@basic_test.o: basic_test.cc
|
@GCC_TRUE@@NATIVE_LINKER_TRUE@basic_test.o: basic_test.cc
|
||||||
@GCC_TRUE@@NATIVE_LINKER_TRUE@ $(CXXCOMPILE) -O0 -c -o $@ $<
|
@GCC_TRUE@@NATIVE_LINKER_TRUE@ $(CXXCOMPILE) -O0 -c -o $@ $<
|
||||||
|
38
gold/testsuite/undef_symbol.cc
Normal file
38
gold/testsuite/undef_symbol.cc
Normal file
@ -0,0 +1,38 @@
|
|||||||
|
// undef_symbol.cc -- a test case for undefined references
|
||||||
|
|
||||||
|
// Copyright 2007 Free Software Foundation, Inc.
|
||||||
|
// Written by Ian Lance Taylor <iant@google.com>.
|
||||||
|
|
||||||
|
// This file is part of gold.
|
||||||
|
|
||||||
|
// This program is free software; you can redistribute it and/or modify
|
||||||
|
// it under the terms of the GNU General Public License as published by
|
||||||
|
// the Free Software Foundation; either version 3 of the License, or
|
||||||
|
// (at your option) any later version.
|
||||||
|
|
||||||
|
// This program is distributed in the hope that it will be useful,
|
||||||
|
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
// GNU General Public License for more details.
|
||||||
|
|
||||||
|
// You should have received a copy of the GNU General Public License
|
||||||
|
// along with this program; if not, write to the Free Software
|
||||||
|
// Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston,
|
||||||
|
// MA 02110-1301, USA.
|
||||||
|
|
||||||
|
// This file is constructed to have an undefined reference to the
|
||||||
|
// global variable a. We should get an error when we link.
|
||||||
|
|
||||||
|
extern int a;
|
||||||
|
|
||||||
|
class Foo
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
Foo()
|
||||||
|
: a_(a)
|
||||||
|
{ }
|
||||||
|
private:
|
||||||
|
int a_;
|
||||||
|
};
|
||||||
|
|
||||||
|
static Foo foo;
|
45
gold/testsuite/undef_symbol.sh
Executable file
45
gold/testsuite/undef_symbol.sh
Executable file
@ -0,0 +1,45 @@
|
|||||||
|
#!/bin/sh
|
||||||
|
|
||||||
|
# undef_symbol.sh -- a test case for undefined symbols in shared libraries
|
||||||
|
|
||||||
|
# Copyright 2007 Free Software Foundation, Inc.
|
||||||
|
# Written by Ian Lance Taylor <iant@google.com>.
|
||||||
|
|
||||||
|
# This file is part of gold.
|
||||||
|
|
||||||
|
# This program is free software; you can redistribute it and/or modify
|
||||||
|
# it under the terms of the GNU General Public License as published by
|
||||||
|
# the Free Software Foundation; either version 3 of the License, or
|
||||||
|
# (at your option) any later version.
|
||||||
|
|
||||||
|
# This program is distributed in the hope that it will be useful,
|
||||||
|
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
# GNU General Public License for more details.
|
||||||
|
|
||||||
|
# You should have received a copy of the GNU General Public License
|
||||||
|
# along with this program; if not, write to the Free Software
|
||||||
|
# Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston,
|
||||||
|
# MA 02110-1301, USA.
|
||||||
|
|
||||||
|
# This file goes with debug_msg.cc, a C++ source file constructed to
|
||||||
|
# have undefined references. We compile that file with debug
|
||||||
|
# information and then try to link it, and make sure the proper errors
|
||||||
|
# are displayed. The errors will be found in debug_msg.err.
|
||||||
|
|
||||||
|
check()
|
||||||
|
{
|
||||||
|
if ! grep -q "$1" undef_symbol.err
|
||||||
|
then
|
||||||
|
echo "Did not find expected error:"
|
||||||
|
echo " $1"
|
||||||
|
echo ""
|
||||||
|
echo "Actual error output below:"
|
||||||
|
cat undef_symbol.err
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
check "undef_symbol.so: undefined reference to 'a'"
|
||||||
|
|
||||||
|
exit 0
|
29
gold/testsuite/undef_symbol_main.cc
Normal file
29
gold/testsuite/undef_symbol_main.cc
Normal file
@ -0,0 +1,29 @@
|
|||||||
|
// undef_symbol_1.cc -- a test case for undefined references
|
||||||
|
|
||||||
|
// Copyright 2007 Free Software Foundation, Inc.
|
||||||
|
// Written by Ian Lance Taylor <iant@google.com>.
|
||||||
|
|
||||||
|
// This file is part of gold.
|
||||||
|
|
||||||
|
// This program is free software; you can redistribute it and/or modify
|
||||||
|
// it under the terms of the GNU General Public License as published by
|
||||||
|
// the Free Software Foundation; either version 3 of the License, or
|
||||||
|
// (at your option) any later version.
|
||||||
|
|
||||||
|
// This program is distributed in the hope that it will be useful,
|
||||||
|
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
// GNU General Public License for more details.
|
||||||
|
|
||||||
|
// You should have received a copy of the GNU General Public License
|
||||||
|
// along with this program; if not, write to the Free Software
|
||||||
|
// Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston,
|
||||||
|
// MA 02110-1301, USA.
|
||||||
|
|
||||||
|
// Main function for undefined symbol test.
|
||||||
|
|
||||||
|
int
|
||||||
|
main()
|
||||||
|
{
|
||||||
|
return 0;
|
||||||
|
}
|
Reference in New Issue
Block a user