Warn about undefined references in shared libraries if we have seen
all the DT_NEEDED entries for that library.
This commit is contained in:
parent
a55ce7febf
commit
e2827e5f52
15 changed files with 367 additions and 81 deletions
|
@ -39,7 +39,9 @@ namespace gold
|
|||
// see a DT_SONAME entry.
|
||||
|
||||
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
|
||||
// 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.
|
||||
|
||||
template<int size, bool big_endian>
|
||||
|
@ -193,19 +187,20 @@ Sized_dynobj<size, big_endian>::read_dynsym_section(
|
|||
*view_info = shdr.get_sh_info();
|
||||
}
|
||||
|
||||
// Set the soname field if this shared object has a DT_SONAME tag.
|
||||
// PSHDRS points to the section headers. DYNAMIC_SHNDX is the section
|
||||
// index of the SHT_DYNAMIC section. STRTAB_SHNDX, STRTAB, and
|
||||
// STRTAB_SIZE are the section index and contents of a string table
|
||||
// which may be the one associated with the SHT_DYNAMIC section.
|
||||
// Read the dynamic tags. Set the soname field if this shared object
|
||||
// has a DT_SONAME tag. Record the DT_NEEDED tags. PSHDRS points to
|
||||
// the section headers. DYNAMIC_SHNDX is the section index of the
|
||||
// SHT_DYNAMIC section. STRTAB_SHNDX, STRTAB, and STRTAB_SIZE are the
|
||||
// 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>
|
||||
void
|
||||
Sized_dynobj<size, big_endian>::set_soname(const unsigned char* pshdrs,
|
||||
unsigned int dynamic_shndx,
|
||||
unsigned int strtab_shndx,
|
||||
const unsigned char* strtabu,
|
||||
off_t strtab_size)
|
||||
Sized_dynobj<size, big_endian>::read_dynamic(const unsigned char* pshdrs,
|
||||
unsigned int dynamic_shndx,
|
||||
unsigned int strtab_shndx,
|
||||
const unsigned char* strtabu,
|
||||
off_t strtab_size)
|
||||
{
|
||||
typename This::Shdr dynamicshdr(pshdrs + dynamic_shndx * This::shdr_size);
|
||||
gold_assert(dynamicshdr.get_sh_type() == elfcpp::SHT_DYNAMIC);
|
||||
|
@ -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);
|
||||
}
|
||||
|
||||
const char* const strtab = reinterpret_cast<const char*>(strtabu);
|
||||
|
||||
for (const unsigned char* p = pdynamic;
|
||||
p < pdynamic + dynamic_size;
|
||||
p += This::dyn_size)
|
||||
{
|
||||
typename This::Dyn dyn(p);
|
||||
|
||||
if (dyn.get_d_tag() == elfcpp::DT_SONAME)
|
||||
switch (dyn.get_d_tag())
|
||||
{
|
||||
off_t val = dyn.get_d_val();
|
||||
if (val >= strtab_size)
|
||||
{
|
||||
this->error(_("DT_SONAME value out of range: %lld >= %lld"),
|
||||
static_cast<long long>(val),
|
||||
static_cast<long long>(strtab_size));
|
||||
return;
|
||||
}
|
||||
|
||||
const char* strtab = reinterpret_cast<const char*>(strtabu);
|
||||
this->set_soname_string(strtab + val);
|
||||
case elfcpp::DT_NULL:
|
||||
// We should always see DT_NULL at the end of the dynamic
|
||||
// tags.
|
||||
return;
|
||||
}
|
||||
|
||||
if (dyn.get_d_tag() == elfcpp::DT_NULL)
|
||||
return;
|
||||
case elfcpp::DT_SONAME:
|
||||
{
|
||||
off_t val = dyn.get_d_val();
|
||||
if (val >= strtab_size)
|
||||
this->error(_("DT_SONAME value out of range: %lld >= %lld"),
|
||||
static_cast<long long>(val),
|
||||
static_cast<long long>(strtab_size));
|
||||
else
|
||||
this->set_soname_string(strtab + val);
|
||||
}
|
||||
break;
|
||||
|
||||
case elfcpp::DT_NEEDED:
|
||||
{
|
||||
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"));
|
||||
|
@ -346,15 +359,15 @@ Sized_dynobj<size, big_endian>::do_read_symbols(Read_symbols_data* sd)
|
|||
}
|
||||
|
||||
// Read the SHT_DYNAMIC section to find whether this shared object
|
||||
// has a DT_SONAME tag. This doesn't really have anything to do
|
||||
// with reading the symbols, but this is a convenient place to do
|
||||
// it.
|
||||
// has a DT_SONAME tag and to record any DT_NEEDED tags. This
|
||||
// doesn't really have anything to do with reading the symbols, but
|
||||
// this is a convenient place to do it.
|
||||
if (dynamic_shndx != -1U)
|
||||
this->set_soname(pshdrs, dynamic_shndx, strtab_shndx,
|
||||
(sd->symbol_names == NULL
|
||||
? NULL
|
||||
: sd->symbol_names->data()),
|
||||
sd->symbol_names_size);
|
||||
this->read_dynamic(pshdrs, dynamic_shndx, strtab_shndx,
|
||||
(sd->symbol_names == NULL
|
||||
? NULL
|
||||
: sd->symbol_names->data()),
|
||||
sd->symbol_names_size);
|
||||
}
|
||||
|
||||
// Lay out the input sections for a dynamic object. We don't want to
|
||||
|
|
|
@ -39,11 +39,38 @@ class General_options;
|
|||
class Dynobj : public Object
|
||||
{
|
||||
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);
|
||||
|
||||
// Return the name to use in a DT_NEEDED entry for this object.
|
||||
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.
|
||||
static uint32_t
|
||||
|
@ -74,6 +101,11 @@ class Dynobj : public Object
|
|||
set_soname_string(const char* 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:
|
||||
// Compute the GNU hash code for a string.
|
||||
static uint32_t
|
||||
|
@ -101,8 +133,21 @@ class Dynobj : public Object
|
|||
unsigned char** pphash,
|
||||
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.
|
||||
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.
|
||||
|
@ -187,12 +232,11 @@ class Sized_dynobj : public Dynobj
|
|||
File_view** view, off_t* view_size,
|
||||
unsigned int* view_info);
|
||||
|
||||
// Set the SONAME from the SHT_DYNAMIC section at DYNAMIC_SHNDX.
|
||||
// The STRTAB parameters may have the relevant string table.
|
||||
// Read the dynamic tags.
|
||||
void
|
||||
set_soname(const unsigned char* pshdrs, unsigned int dynamic_shndx,
|
||||
unsigned int strtab_shndx, const unsigned char* strtabu,
|
||||
off_t strtab_size);
|
||||
read_dynamic(const unsigned char* pshdrs, unsigned int dynamic_shndx,
|
||||
unsigned int strtab_shndx, const unsigned char* strtabu,
|
||||
off_t strtab_size);
|
||||
|
||||
// Mapping from version number to version name.
|
||||
typedef std::vector<const char*> Version_map;
|
||||
|
|
|
@ -180,6 +180,10 @@ queue_middle_tasks(const General_options& options,
|
|||
(*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.
|
||||
// TODO: if this is too slow, do this as a task, rather than inline.
|
||||
symtab->detect_odr_violations();
|
||||
|
|
|
@ -1080,6 +1080,32 @@ Input_objects::add_object(Object* obj)
|
|||
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.
|
||||
|
||||
// Return a string describing the location of a relocation. This is
|
||||
|
|
|
@ -951,6 +951,11 @@ class Input_objects
|
|||
target() const
|
||||
{ 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.
|
||||
|
||||
Relobj_iterator
|
||||
|
|
|
@ -337,6 +337,14 @@ namespace gold
|
|||
const options::One_option
|
||||
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",
|
||||
N_("Only set DT_NEEDED for dynamic libs if used"),
|
||||
NULL, TWO_DASHES, &Position_dependent_options::set_as_needed),
|
||||
|
@ -475,6 +483,7 @@ General_options::General_options()
|
|||
output_file_name_("a.out"),
|
||||
is_relocatable_(false),
|
||||
strip_(STRIP_NONE),
|
||||
allow_shlib_undefined_(false),
|
||||
symbolic_(false),
|
||||
detect_odr_violations_(false),
|
||||
create_eh_frame_hdr_(false),
|
||||
|
|
|
@ -148,6 +148,12 @@ class General_options
|
|||
strip_debug() const
|
||||
{ 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.
|
||||
bool
|
||||
symbolic() const
|
||||
|
@ -300,6 +306,14 @@ class General_options
|
|||
set_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
|
||||
set_symbolic()
|
||||
{ this->symbolic_ = true; }
|
||||
|
@ -420,6 +434,7 @@ class General_options
|
|||
const char* output_file_name_;
|
||||
bool is_relocatable_;
|
||||
Strip strip_;
|
||||
bool allow_shlib_undefined_;
|
||||
bool symbolic_;
|
||||
bool detect_odr_violations_;
|
||||
bool create_eh_frame_hdr_;
|
||||
|
|
|
@ -33,7 +33,8 @@ namespace gold
|
|||
Parameters::Parameters(Errors* errors)
|
||||
: errors_(errors), output_file_name_(NULL),
|
||||
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),
|
||||
is_doing_static_link_valid_(false), doing_static_link_(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->sysroot_ = options->sysroot();
|
||||
this->allow_shlib_undefined_ = options->allow_shlib_undefined();
|
||||
this->symbolic_ = options->symbolic();
|
||||
this->detect_odr_violations_ = options->detect_odr_violations();
|
||||
this->optimization_level_ = options->optimization_level();
|
||||
|
|
|
@ -112,6 +112,14 @@ class Parameters
|
|||
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
|
||||
// symbols are bound locally.
|
||||
bool
|
||||
|
@ -224,6 +232,8 @@ class Parameters
|
|||
std::string sysroot_;
|
||||
// Which symbols to strip.
|
||||
Strip strip_;
|
||||
// Whether to allow undefined references from shared libraries.
|
||||
bool allow_shlib_undefined_;
|
||||
// Whether we are doing a symbolic link.
|
||||
bool symbolic_;
|
||||
// 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);
|
||||
|
||||
// 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 dynsym_index;
|
||||
if (dynamic_view == NULL)
|
||||
|
|
|
@ -28,12 +28,12 @@ TESTS = object_unittest
|
|||
|
||||
if GCC
|
||||
|
||||
TESTS += debug_msg.sh
|
||||
|
||||
check_DATA += debug_msg.err
|
||||
|
||||
if NATIVE_LINKER
|
||||
|
||||
TESTS += debug_msg.sh undef_symbol.sh
|
||||
|
||||
check_DATA += debug_msg.err undef_symbol.err
|
||||
|
||||
NATIVE_PROGS = \
|
||||
constructor_test \
|
||||
constructor_static_test \
|
||||
|
@ -116,19 +116,6 @@ object_unittest_SOURCES = object_unittest.cc
|
|||
|
||||
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
|
||||
|
||||
gcctestdir/ld: ../ld-new
|
||||
|
@ -136,6 +123,32 @@ gcctestdir/ld: ../ld-new
|
|||
rm -f gcctestdir/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
|
||||
basic_test.o: basic_test.cc
|
||||
$(CXXCOMPILE) -O0 -c -o $@ $<
|
||||
|
|
|
@ -42,8 +42,8 @@ POST_UNINSTALL = :
|
|||
build_triplet = @build@
|
||||
host_triplet = @host@
|
||||
target_triplet = @target@
|
||||
@GCC_TRUE@am__append_1 = debug_msg.sh
|
||||
@GCC_TRUE@am__append_2 = debug_msg.err
|
||||
@GCC_TRUE@@NATIVE_LINKER_TRUE@am__append_1 = debug_msg.sh undef_symbol.sh
|
||||
@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@ two_file_shared_1_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
|
||||
|
||||
|
||||
@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@ test -d gcctestdir || mkdir -p gcctestdir
|
||||
@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@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
|
||||
@GCC_TRUE@@NATIVE_LINKER_TRUE@basic_test.o: basic_test.cc
|
||||
@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;
|
||||
}
|
Loading…
Reference in a new issue