From Craig Silverstein: rework seen handling to be based on archive

offsets rather than entries in archive symbol table.
This commit is contained in:
Ian Lance Taylor 2007-09-20 05:43:14 +00:00
parent 20e96b3e5d
commit e243ffc667
2 changed files with 25 additions and 15 deletions

View file

@ -121,10 +121,6 @@ Archive::read_armap(off_t start, off_t size)
program_name, this->name().c_str()); program_name, this->name().c_str());
gold_exit(false); gold_exit(false);
} }
// This array keeps track of which symbols are for archive elements
// which we have already included in the link.
this->seen_.resize(nsyms);
} }
// Read the header of an archive member at OFF. Fail if something // Read the header of an archive member at OFF. Fail if something
@ -230,6 +226,14 @@ Archive::interpret_header(const Archive_header* hdr, off_t off,
return member_size; return member_size;
} }
// A simple hash code for off_t values.
class Seen_hash
{
public:
size_t operator()(off_t val) const
{ return static_cast<size_t>(val); }
};
// Select members from the archive and add them to the link. We walk // Select members from the archive and add them to the link. We walk
// through the elements in the archive map, and look each one up in // through the elements in the archive map, and look each one up in
// the symbol table. If it exists as a strong undefined symbol, we // the symbol table. If it exists as a strong undefined symbol, we
@ -246,18 +250,25 @@ Archive::add_symbols(const General_options& options, Symbol_table* symtab,
const size_t armap_size = this->armap_.size(); const size_t armap_size = this->armap_.size();
// Track which elements in the archive map have already been included
// in the link. Elements are identified by their offset.
Unordered_set<off_t, Seen_hash> seen;
// This is a quick optimization, since we usually see many symbols
// in a row with the same offset. last_seen holds the last offset
// we saw that was present in the seen_ set.
off_t last_seen = -1;
bool added_new_object; bool added_new_object;
do do
{ {
added_new_object = false; added_new_object = false;
off_t last = -1;
for (size_t i = 0; i < armap_size; ++i) for (size_t i = 0; i < armap_size; ++i)
{ {
if (this->seen_[i]) if (this->armap_[i].offset == last_seen)
continue; continue;
if (this->armap_[i].offset == last) if (seen.find(this->armap_[i].offset) != seen.end())
{ {
this->seen_[i] = true; last_seen = this->armap_[i].offset;
continue; continue;
} }
@ -266,16 +277,18 @@ Archive::add_symbols(const General_options& options, Symbol_table* symtab,
continue; continue;
else if (!sym->is_undefined()) else if (!sym->is_undefined())
{ {
this->seen_[i] = true; seen.insert(this->armap_[i].offset);
last_seen = this->armap_[i].offset;
continue; continue;
} }
else if (sym->binding() == elfcpp::STB_WEAK) else if (sym->binding() == elfcpp::STB_WEAK)
continue; continue;
// We want to include this object in the link. // We want to include this object in the link.
last = this->armap_[i].offset; last_seen = this->armap_[i].offset;
this->include_member(options, symtab, layout, input_objects, last); seen.insert(last_seen);
this->seen_[i] = true; this->include_member(options, symtab, layout, input_objects,
last_seen);
added_new_object = true; added_new_object = true;
} }
} }

View file

@ -123,9 +123,6 @@ class Archive
std::vector<Armap_entry> armap_; std::vector<Armap_entry> armap_;
// The extended name table. // The extended name table.
std::string extended_names_; std::string extended_names_;
// Track which symbols in the archive map are for elements which
// have already been included in the link.
std::vector<bool> seen_;
}; };
// This class is used to read an archive and pick out the desired // This class is used to read an archive and pick out the desired