diff --git a/gold/dynobj.cc b/gold/dynobj.cc index 7afaaa55a7..1bd5a85e43 100644 --- a/gold/dynobj.cc +++ b/gold/dynobj.cc @@ -1324,12 +1324,12 @@ Versions::finalize(const Target* target, Symbol_table* symtab, // Create a version symbol if necessary. if (!(*p)->is_symbol_created()) { - Symbol* vsym =symtab->define_as_constant(target, (*p)->name(), - (*p)->name(), 0, 0, - elfcpp::STT_OBJECT, - elfcpp::STB_GLOBAL, - elfcpp::STV_DEFAULT, 0, - false); + Symbol* vsym = symtab->define_as_constant(target, (*p)->name(), + (*p)->name(), 0, 0, + elfcpp::STT_OBJECT, + elfcpp::STB_GLOBAL, + elfcpp::STV_DEFAULT, 0, + false); vsym->set_needs_dynsym_entry(); ++dynsym_index; syms->push_back(vsym); diff --git a/gold/object.cc b/gold/object.cc index 2086fed1b9..01c4c1625c 100644 --- a/gold/object.cc +++ b/gold/object.cc @@ -718,15 +718,29 @@ Sized_relobj::write_local_symbols(Output_file* of, // Input_objects methods. -// Add a regular relocatable object to the list. +// Add a regular relocatable object to the list. Return false if this +// object should be ignored. -void +bool Input_objects::add_object(Object* obj) { - if (obj->is_dynamic()) - this->dynobj_list_.push_back(static_cast(obj)); - else + if (!obj->is_dynamic()) this->relobj_list_.push_back(static_cast(obj)); + else + { + // See if this is a duplicate SONAME. + Dynobj* dynobj = static_cast(obj); + + std::pair::iterator, bool> ins = + this->sonames_.insert(dynobj->soname()); + if (!ins.second) + { + // We have already seen a dynamic object with this soname. + return false; + } + + this->dynobj_list_.push_back(dynobj); + } Target* target = obj->target(); if (this->target_ == NULL) @@ -737,6 +751,8 @@ Input_objects::add_object(Object* obj) program_name, obj->name().c_str()); gold_exit(false); } + + return true; } // Relocate_info methods. diff --git a/gold/object.h b/gold/object.h index b823599cbc..2df04abad8 100644 --- a/gold/object.h +++ b/gold/object.h @@ -600,7 +600,7 @@ class Input_objects { public: Input_objects() - : relobj_list_(), target_(NULL) + : relobj_list_(), dynobj_list_(), target_(NULL), sonames_() { } // The type of the list of input relocateable objects. @@ -611,8 +611,9 @@ class Input_objects typedef std::vector Dynobj_list; typedef Dynobj_list::const_iterator Dynobj_iterator; - // Add an object to the list. - void + // Add an object to the list. Return true if all is well, or false + // if this object should be ignored. + bool add_object(Object*); // Get the target we should use for the output file. @@ -649,9 +650,14 @@ class Input_objects Input_objects(const Input_objects&); Input_objects& operator=(const Input_objects&); + // The list of ordinary objects included in the link. Relobj_list relobj_list_; + // The list of dynamic objects included in the link. Dynobj_list dynobj_list_; + // The target. Target* target_; + // SONAMEs that we have seen. + Unordered_set sonames_; }; // Some of the information we pass to the relocation routines. We diff --git a/gold/po/gold.pot b/gold/po/gold.pot index abce13a1d8..f89d7cef0b 100644 --- a/gold/po/gold.pot +++ b/gold/po/gold.pot @@ -8,7 +8,7 @@ msgid "" msgstr "" "Project-Id-Version: PACKAGE VERSION\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2006-12-05 15:53-0800\n" +"POT-Creation-Date: 2006-12-05 17:51-0800\n" "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" "Last-Translator: FULL NAME \n" "Language-Team: LANGUAGE \n" @@ -166,7 +166,7 @@ msgstr "" msgid "%s: %s: size of dynamic symbols is not multiple of symbol size\n" msgstr "" -#: dynobj.cc:1240 +#: dynobj.cc:1241 #, c-format msgid "%s: symbol %s has undefined version %s\n" msgstr "" @@ -360,42 +360,42 @@ msgstr "" msgid "%s: %s: local symbol %u section name out of range: %u >= %u\n" msgstr "" -#: object.cc:799 +#: object.cc:815 #, c-format msgid "%s: %s: unsupported ELF file type %d\n" msgstr "" -#: object.cc:818 object.cc:871 object.cc:892 +#: object.cc:834 object.cc:887 object.cc:908 #, c-format msgid "%s: %s: ELF file too short\n" msgstr "" -#: object.cc:827 +#: object.cc:843 #, c-format msgid "%s: %s: invalid ELF version 0\n" msgstr "" -#: object.cc:830 +#: object.cc:846 #, c-format msgid "%s: %s: unsupported ELF version %d\n" msgstr "" -#: object.cc:838 +#: object.cc:854 #, c-format msgid "%s: %s: invalid ELF class 0\n" msgstr "" -#: object.cc:845 +#: object.cc:861 #, c-format msgid "%s: %s: unsupported ELF class %d\n" msgstr "" -#: object.cc:853 +#: object.cc:869 #, c-format msgid "%s: %s: invalid ELF data encoding\n" msgstr "" -#: object.cc:860 +#: object.cc:876 #, c-format msgid "%s: %s: unsupported ELF data encoding %d\n" msgstr "" @@ -592,42 +592,42 @@ msgstr "" msgid "%s: %s: unsupported symbol binding %d for symbol %s\n" msgstr "" -#: symtab.cc:445 symtab.cc:542 +#: symtab.cc:450 symtab.cc:547 #, c-format msgid "%s: %s: mixing 32-bit and 64-bit ELF objects\n" msgstr "" -#: symtab.cc:462 +#: symtab.cc:467 #, c-format msgid "%s: %s: bad global symbol name offset %u at %lu\n" msgstr "" -#: symtab.cc:549 +#: symtab.cc:554 #, c-format msgid "%s: %s: too few symbol versions\n" msgstr "" -#: symtab.cc:569 +#: symtab.cc:574 #, c-format msgid "%s: %s: bad symbol name offset %u at %lu\n" msgstr "" -#: symtab.cc:613 +#: symtab.cc:618 #, c-format msgid "%s: %s: versym for symbol %zu out of range: %u\n" msgstr "" -#: symtab.cc:621 +#: symtab.cc:626 #, c-format msgid "%s: %s: versym for symbol %zu has no name: %u\n" msgstr "" -#: symtab.cc:1093 symtab.cc:1265 +#: symtab.cc:1106 symtab.cc:1278 #, c-format msgid "%s: %s: unsupported symbol section 0x%x\n" msgstr "" -#: symtab.cc:1458 +#: symtab.cc:1471 #, c-format msgid "%s: %s: warning: %s\n" msgstr "" diff --git a/gold/readsyms.cc b/gold/readsyms.cc index ba3e85e70a..86828fc0a7 100644 --- a/gold/readsyms.cc +++ b/gold/readsyms.cc @@ -240,10 +240,17 @@ Add_symbols::locks(Workqueue* workqueue) void Add_symbols::run(Workqueue*) { - this->input_objects_->add_object(this->object_); - this->object_->layout(this->options_, this->symtab_, this->layout_, - this->sd_); - this->object_->add_symbols(this->symtab_, this->sd_); + if (!this->input_objects_->add_object(this->object_)) + { + // FIXME: We need to close the descriptor here. + delete this->object_; + } + else + { + this->object_->layout(this->options_, this->symtab_, this->layout_, + this->sd_); + this->object_->add_symbols(this->symtab_, this->sd_); + } delete this->sd_; this->sd_ = NULL; } diff --git a/gold/resolve.cc b/gold/resolve.cc index 1272e0588a..1d874863d6 100644 --- a/gold/resolve.cc +++ b/gold/resolve.cc @@ -156,7 +156,12 @@ Symbol_table::resolve(Sized_symbol* to, gold_exit(false); } - if (object->is_dynamic()) + if (!object->is_dynamic()) + { + // Record that we've seen this symbol in a regular object. + to->set_in_reg(); + } + else { frombits |= (1 << 1); diff --git a/gold/symtab.cc b/gold/symtab.cc index 5b61152652..01e000d874 100644 --- a/gold/symtab.cc +++ b/gold/symtab.cc @@ -39,6 +39,7 @@ Symbol::init_fields(const char* name, const char* version, this->is_def_ = false; this->is_forwarder_ = false; this->needs_dynsym_entry_ = false; + this->in_reg_ = false; this->in_dyn_ = false; this->has_got_offset_ = false; this->has_warning_ = false; @@ -57,6 +58,7 @@ Symbol::init_base(const char* name, const char* version, Object* object, // FIXME: Handle SHN_XINDEX. this->u_.from_object.shndx = sym.get_st_shndx(); this->source_ = FROM_OBJECT; + this->in_reg_ = !object->is_dynamic(); this->in_dyn_ = object->is_dynamic(); } @@ -72,6 +74,7 @@ Symbol::init_base(const char* name, Output_data* od, elfcpp::STT type, this->u_.in_output_data.output_data = od; this->u_.in_output_data.offset_is_from_end = offset_is_from_end; this->source_ = IN_OUTPUT_DATA; + this->in_reg_ = true; } // Initialize the fields in the base class Symbol for a symbol defined @@ -86,6 +89,7 @@ Symbol::init_base(const char* name, Output_segment* os, elfcpp::STT type, this->u_.in_output_segment.output_segment = os; this->u_.in_output_segment.offset_base = offset_base; this->source_ = IN_OUTPUT_SEGMENT; + this->in_reg_ = true; } // Initialize the fields in the base class Symbol for a symbol defined @@ -98,6 +102,7 @@ Symbol::init_base(const char* name, elfcpp::STT type, { this->init_fields(name, NULL, type, binding, visibility, nonvis); this->source_ = CONSTANT; + this->in_reg_ = true; } // Initialize the fields in Sized_symbol for SYM in OBJECT. @@ -1078,6 +1083,14 @@ Symbol_table::sized_finalize(unsigned index, off_t off, Stringpool* pool) if (sym->has_symtab_index()) continue; + if (!sym->in_reg()) + { + gold_assert(!sym->has_symtab_index()); + sym->set_symtab_index(-1U); + gold_assert(sym->dynsym_index() == -1U); + continue; + } + typename Sized_symbol::Value_type value; switch (sym->source()) diff --git a/gold/symtab.h b/gold/symtab.h index 6e4344d4be..66e98bc6d2 100644 --- a/gold/symtab.h +++ b/gold/symtab.h @@ -185,6 +185,16 @@ class Symbol set_needs_dynsym_entry() { this->needs_dynsym_entry_ = true; } + // Return whether this symbol has been seen in a regular object. + bool + in_reg() const + { return this->in_reg_; } + + // Mark this symbol as having been seen in a regular object. + void + set_in_reg() + { this->in_reg_ = true; } + // Mark this symbol as having been seen in a dynamic object. void set_in_dyn() @@ -469,6 +479,8 @@ class Symbol bool is_forwarder_ : 1; // True if this symbol needs to be in the dynamic symbol table. bool needs_dynsym_entry_ : 1; + // True if we've seen this symbol in a regular object. + bool in_reg_ : 1; // True if we've seen this symbol in a dynamic object. bool in_dyn_ : 1; // True if the symbol has an entry in the GOT section.