Rework patch to check by both armap entry and archive offset. Also,
preserve information for --group.
This commit is contained in:
parent
e243ffc667
commit
a93d6d0708
2 changed files with 37 additions and 21 deletions
|
@ -121,6 +121,10 @@ 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->armap_checked_.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
|
||||||
|
@ -226,14 +230,6 @@ 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
|
||||||
|
@ -250,13 +246,13 @@ 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
|
// This is a quick optimization, since we usually see many symbols
|
||||||
// in a row with the same offset. last_seen holds the last offset
|
// in a row with the same offset. last_seen holds the last offset
|
||||||
// we saw that was present in the seen_ set.
|
// we saw that was present in the seen_ set.
|
||||||
off_t last_seen = -1;
|
off_t last_seen_offset = -1;
|
||||||
|
|
||||||
|
// Track which symbols in the symbol table we've already found to be
|
||||||
|
// defined.
|
||||||
|
|
||||||
bool added_new_object;
|
bool added_new_object;
|
||||||
do
|
do
|
||||||
|
@ -264,11 +260,18 @@ Archive::add_symbols(const General_options& options, Symbol_table* symtab,
|
||||||
added_new_object = false;
|
added_new_object = false;
|
||||||
for (size_t i = 0; i < armap_size; ++i)
|
for (size_t i = 0; i < armap_size; ++i)
|
||||||
{
|
{
|
||||||
if (this->armap_[i].offset == last_seen)
|
if (this->armap_checked_[i])
|
||||||
continue;
|
continue;
|
||||||
if (seen.find(this->armap_[i].offset) != seen.end())
|
if (this->armap_[i].offset == last_seen_offset)
|
||||||
|
{
|
||||||
|
this->armap_checked_[i] = true;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if (this->seen_offsets_.find(this->armap_[i].offset)
|
||||||
|
!= this->seen_offsets_.end())
|
||||||
{
|
{
|
||||||
last_seen = this->armap_[i].offset;
|
this->armap_checked_[i] = true;
|
||||||
|
last_seen_offset = this->armap_[i].offset;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -277,18 +280,18 @@ Archive::add_symbols(const General_options& options, Symbol_table* symtab,
|
||||||
continue;
|
continue;
|
||||||
else if (!sym->is_undefined())
|
else if (!sym->is_undefined())
|
||||||
{
|
{
|
||||||
seen.insert(this->armap_[i].offset);
|
this->armap_checked_[i] = true;
|
||||||
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_seen = this->armap_[i].offset;
|
last_seen_offset = this->armap_[i].offset;
|
||||||
seen.insert(last_seen);
|
this->seen_offsets_.insert(last_seen_offset);
|
||||||
|
this->armap_checked_[i] = true;
|
||||||
this->include_member(options, symtab, layout, input_objects,
|
this->include_member(options, symtab, layout, input_objects,
|
||||||
last_seen);
|
last_seen_offset);
|
||||||
added_new_object = true;
|
added_new_object = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -115,6 +115,14 @@ class Archive
|
||||||
off_t offset;
|
off_t offset;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// 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); }
|
||||||
|
};
|
||||||
|
|
||||||
// Name of object as printed to user.
|
// Name of object as printed to user.
|
||||||
std::string name_;
|
std::string name_;
|
||||||
// For reading the file.
|
// For reading the file.
|
||||||
|
@ -123,6 +131,11 @@ 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 are
|
||||||
|
// defined or which have already been included in the link.
|
||||||
|
std::vector<bool> armap_checked_;
|
||||||
|
// Track which elements have been included by offset.
|
||||||
|
Unordered_set<off_t, Seen_hash> seen_offsets_;
|
||||||
};
|
};
|
||||||
|
|
||||||
// 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
|
||||||
|
|
Loading…
Reference in a new issue