method here from class Archive.
(Archive::Archive): Initialize base class.
(Archive::should_include_member): Move to base class.
(Archive::do_for_all_unused_symbols): New function.
(Add_archive_symbols::run): Remove redundant access to
incremental_inputs.
(Lib_group::Lib_group): Initialize base class.
(Lib_group::do_filename): New function.
(Lib_group::include_member): Pass pointer to Lib_group to
report_object.
(Lib_group::do_for_all_unused_symbols): New function.
(Add_lib_group_symbols::run): Report archive information for
incremental links.
* archive.h (class Library_base): New base class.
(class Archive): Derive from Library_base.
(Archive::filename): Move to base class.
(Archive::set_incremental_info): Likewise.
(Archive::incremental_info): Likewise.
(Archive::Should_include): Likewise.
(Archive::should_include_member): Likewise.
(Archive::Armap_entry): Remove.
(Archive::Unused_symbol_iterator): Remove.
(Archive::unused_symbols_begin): Remove.
(Archive::unused_symbols_end): Remove.
(Archive::do_filename): New function.
(Archive::do_get_mtime): New function.
(Archive::do_for_all_unused_symbols): New function.
(Archive::task_): Move to base class.
(Archive::incremental_info_): Likewise.
(class Lib_group): Derive from Library_base.
(Lib_group::do_filename): New function.
(Lib_group::do_get_mtime): New function.
(Lib_group::do_for_all_unused_symbols): New function.
(Lib_group::task_): Move to base class.
* dynobj.cc (Sized_dynobj::do_for_all_global_symbols): New
function.
* dynobj.h (Sized_dynobj::do_for_all_global_symbols): New
function.
* incremental.cc (Incremental_inputs::report_archive_begin):
Use Library_base; call library's get_mtime; add incremental inputs
entry before members.
(class Unused_symbol_visitor): New class.
(Incremental_inputs::report_archive_end): Use Library_base; use
visitor class to record unused symbols; don't add incremental inputs
entry after members.
(Incremental_inputs::report_object): Use Library_base.
* incremental.h
(Incremental_archive_entry::Incremental_archive_entry): Remove
unused Archive parameter.
(Incremental_inputs::report_archive_begin): Use Library_base.
(Incremental_inputs::report_archive_end): Likewise.
(Incremental_inputs::report_object): Likewise.
* object.cc (Sized_relobj::do_for_all_global_symbols): New
function.
* object.h (Object::for_all_global_symbols): New function.
(Object::do_for_all_global_symbols): New function.
(Sized_relobj::do_for_all_global_symbols): New function.
* plugin.cc (Sized_pluginobj::do_for_all_global_symbols): New
function.
* plugin.h (Sized_pluginobj::do_for_all_global_symbols): New
function.
+2011-03-29 Cary Coutant <ccoutant@google.com>
+
+ * archive.cc (Library_base::should_include_member): Move
+ method here from class Archive.
+ (Archive::Archive): Initialize base class.
+ (Archive::should_include_member): Move to base class.
+ (Archive::do_for_all_unused_symbols): New function.
+ (Add_archive_symbols::run): Remove redundant access to
+ incremental_inputs.
+ (Lib_group::Lib_group): Initialize base class.
+ (Lib_group::do_filename): New function.
+ (Lib_group::include_member): Pass pointer to Lib_group to
+ report_object.
+ (Lib_group::do_for_all_unused_symbols): New function.
+ (Add_lib_group_symbols::run): Report archive information for
+ incremental links.
+ * archive.h (class Library_base): New base class.
+ (class Archive): Derive from Library_base.
+ (Archive::filename): Move to base class.
+ (Archive::set_incremental_info): Likewise.
+ (Archive::incremental_info): Likewise.
+ (Archive::Should_include): Likewise.
+ (Archive::should_include_member): Likewise.
+ (Archive::Armap_entry): Remove.
+ (Archive::Unused_symbol_iterator): Remove.
+ (Archive::unused_symbols_begin): Remove.
+ (Archive::unused_symbols_end): Remove.
+ (Archive::do_filename): New function.
+ (Archive::do_get_mtime): New function.
+ (Archive::do_for_all_unused_symbols): New function.
+ (Archive::task_): Move to base class.
+ (Archive::incremental_info_): Likewise.
+ (class Lib_group): Derive from Library_base.
+ (Lib_group::do_filename): New function.
+ (Lib_group::do_get_mtime): New function.
+ (Lib_group::do_for_all_unused_symbols): New function.
+ (Lib_group::task_): Move to base class.
+ * dynobj.cc (Sized_dynobj::do_for_all_global_symbols): New
+ function.
+ * dynobj.h (Sized_dynobj::do_for_all_global_symbols): New
+ function.
+ * incremental.cc (Incremental_inputs::report_archive_begin):
+ Use Library_base; call library's get_mtime; add incremental inputs
+ entry before members.
+ (class Unused_symbol_visitor): New class.
+ (Incremental_inputs::report_archive_end): Use Library_base; use
+ visitor class to record unused symbols; don't add incremental inputs
+ entry after members.
+ (Incremental_inputs::report_object): Use Library_base.
+ * incremental.h
+ (Incremental_archive_entry::Incremental_archive_entry): Remove
+ unused Archive parameter.
+ (Incremental_inputs::report_archive_begin): Use Library_base.
+ (Incremental_inputs::report_archive_end): Likewise.
+ (Incremental_inputs::report_object): Likewise.
+ * object.cc (Sized_relobj::do_for_all_global_symbols): New
+ function.
+ * object.h (Object::for_all_global_symbols): New function.
+ (Object::do_for_all_global_symbols): New function.
+ (Sized_relobj::do_for_all_global_symbols): New function.
+ * plugin.cc (Sized_pluginobj::do_for_all_global_symbols): New
+ function.
+ * plugin.h (Sized_pluginobj::do_for_all_global_symbols): New
+ function.
+
2011-03-27 Ian Lance Taylor <iant@google.com>
* archive.cc (Archive::interpret_header): Return -1 if something
namespace gold
{
+// Library_base methods.
+
+// Determine whether a definition of SYM_NAME should cause an archive
+// library member to be included in the link. Returns SHOULD_INCLUDE_YES
+// if the symbol is referenced but not defined, SHOULD_INCLUDE_NO if the
+// symbol is already defined, and SHOULD_INCLUDE_UNKNOWN if the symbol is
+// neither referenced nor defined.
+
+Library_base::Should_include
+Library_base::should_include_member(Symbol_table* symtab, Layout* layout,
+ const char* sym_name, Symbol** symp,
+ std::string* why, char** tmpbufp,
+ size_t* tmpbuflen)
+{
+ // In an object file, and therefore in an archive map, an
+ // '@' in the name separates the symbol name from the
+ // version name. If there are two '@' characters, this is
+ // the default version.
+ char* tmpbuf = *tmpbufp;
+ const char* ver = strchr(sym_name, '@');
+ bool def = false;
+ if (ver != NULL)
+ {
+ size_t symlen = ver - sym_name;
+ if (symlen + 1 > *tmpbuflen)
+ {
+ tmpbuf = static_cast<char*>(xrealloc(tmpbuf, symlen + 1));
+ *tmpbufp = tmpbuf;
+ *tmpbuflen = symlen + 1;
+ }
+ memcpy(tmpbuf, sym_name, symlen);
+ tmpbuf[symlen] = '\0';
+ sym_name = tmpbuf;
+
+ ++ver;
+ if (*ver == '@')
+ {
+ ++ver;
+ def = true;
+ }
+ }
+
+ Symbol* sym = symtab->lookup(sym_name, ver);
+ if (def
+ && ver != NULL
+ && (sym == NULL
+ || !sym->is_undefined()
+ || sym->binding() == elfcpp::STB_WEAK))
+ sym = symtab->lookup(sym_name, NULL);
+
+ *symp = sym;
+
+ if (sym == NULL)
+ {
+ // Check whether the symbol was named in a -u option.
+ if (parameters->options().is_undefined(sym_name))
+ {
+ *why = "-u ";
+ *why += sym_name;
+ }
+ else if (layout->script_options()->is_referenced(sym_name))
+ {
+ size_t alc = 100 + strlen(sym_name);
+ char* buf = new char[alc];
+ snprintf(buf, alc, _("script or expression reference to %s"),
+ sym_name);
+ *why = buf;
+ delete[] buf;
+ }
+ else
+ return Library_base::SHOULD_INCLUDE_UNKNOWN;
+ }
+ else if (!sym->is_undefined())
+ return Library_base::SHOULD_INCLUDE_NO;
+ // PR 12001: Do not include an archive when the undefined
+ // symbol has actually been defined on the command line.
+ else if (layout->script_options()->is_pending_assignment(sym_name))
+ return Library_base::SHOULD_INCLUDE_NO;
+ else if (sym->binding() == elfcpp::STB_WEAK)
+ return Library_base::SHOULD_INCLUDE_UNKNOWN;
+
+ return Library_base::SHOULD_INCLUDE_YES;
+}
+
// The header of an entry in the archive. This is all readable text,
// padded with spaces where necessary. If the contents of an archive
// are all text file, the entire archive is readable.
Archive::Archive(const std::string& name, Input_file* input_file,
bool is_thin_archive, Dirsearch* dirpath, Task* task)
- : name_(name), input_file_(input_file), armap_(), armap_names_(),
- extended_names_(), armap_checked_(), seen_offsets_(), members_(),
- is_thin_archive_(is_thin_archive), included_member_(false),
- nested_archives_(), dirpath_(dirpath), task_(task), num_members_(0),
- incremental_info_(NULL)
+ : Library_base(task), name_(name), input_file_(input_file), armap_(),
+ armap_names_(), extended_names_(), armap_checked_(), seen_offsets_(),
+ members_(), is_thin_archive_(is_thin_archive), included_member_(false),
+ nested_archives_(), dirpath_(dirpath), num_members_(0)
{
this->no_export_ =
parameters->options().check_excluded_libs(input_file->found_name());
this->members_[off] = member;
}
-Archive::Should_include
-Archive::should_include_member(Symbol_table* symtab, Layout* layout,
- const char* sym_name, Symbol** symp,
- std::string* why, char** tmpbufp,
- size_t* tmpbuflen)
-{
- // In an object file, and therefore in an archive map, an
- // '@' in the name separates the symbol name from the
- // version name. If there are two '@' characters, this is
- // the default version.
- char* tmpbuf = *tmpbufp;
- const char* ver = strchr(sym_name, '@');
- bool def = false;
- if (ver != NULL)
- {
- size_t symlen = ver - sym_name;
- if (symlen + 1 > *tmpbuflen)
- {
- tmpbuf = static_cast<char*>(xrealloc(tmpbuf, symlen + 1));
- *tmpbufp = tmpbuf;
- *tmpbuflen = symlen + 1;
- }
- memcpy(tmpbuf, sym_name, symlen);
- tmpbuf[symlen] = '\0';
- sym_name = tmpbuf;
-
- ++ver;
- if (*ver == '@')
- {
- ++ver;
- def = true;
- }
- }
-
- Symbol* sym = symtab->lookup(sym_name, ver);
- if (def
- && ver != NULL
- && (sym == NULL
- || !sym->is_undefined()
- || sym->binding() == elfcpp::STB_WEAK))
- sym = symtab->lookup(sym_name, NULL);
-
- *symp = sym;
-
- if (sym == NULL)
- {
- // Check whether the symbol was named in a -u option.
- if (parameters->options().is_undefined(sym_name))
- {
- *why = "-u ";
- *why += sym_name;
- }
- else if (layout->script_options()->is_referenced(sym_name))
- {
- size_t alc = 100 + strlen(sym_name);
- char* buf = new char[alc];
- snprintf(buf, alc, _("script or expression reference to %s"),
- sym_name);
- *why = buf;
- delete[] buf;
- }
- else
- return Archive::SHOULD_INCLUDE_UNKNOWN;
- }
- else if (!sym->is_undefined())
- return Archive::SHOULD_INCLUDE_NO;
- // PR 12001: Do not include an archive when the undefined
- // symbol has actually been defined on the command line.
- else if (layout->script_options()->is_pending_assignment(sym_name))
- return Archive::SHOULD_INCLUDE_NO;
- else if (sym->binding() == elfcpp::STB_WEAK)
- return Archive::SHOULD_INCLUDE_UNKNOWN;
-
- return Archive::SHOULD_INCLUDE_YES;
-}
-
// 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
// the symbol table. If it exists as a strong undefined symbol, we
return true;
}
+// Iterate over all unused symbols, and call the visitor class V for each.
+
+void
+Archive::do_for_all_unused_symbols(Symbol_visitor_base* v) const
+{
+ for (std::vector<Armap_entry>::const_iterator p = this->armap_.begin();
+ p != this->armap_.end();
+ ++p)
+ {
+ if (this->seen_offsets_.find(p->file_offset)
+ == this->seen_offsets_.end())
+ v->visit(this->armap_names_.data() + p->name_offset);
+ }
+}
+
// Print statistical information to stderr. This is used for --stats.
void
else
{
// For an incremental link, finish recording the layout information.
- Incremental_inputs* incremental_inputs = this->layout_->incremental_inputs();
if (incremental_inputs != NULL)
incremental_inputs->report_archive_end(this->archive_);
unsigned int Lib_group::total_members_loaded;
Lib_group::Lib_group(const Input_file_lib* lib, Task* task)
- : lib_(lib), task_(task), members_()
+ : Library_base(task), lib_(lib), members_()
{
this->members_.resize(lib->size());
}
+const std::string&
+Lib_group::do_filename() const
+{
+ std::string *filename = new std::string("<group>");
+ return *filename;
+}
+
// Select members from the lib group and add them to the link. We walk
// through the members, and check if each one up should be included.
// If the object says it should be included, we do so. We have to do
obj->lock(this->task_);
if (input_objects->add_object(obj))
{
- // FIXME: Record incremental link info for --start-lib/--end-lib.
if (layout->incremental_inputs() != NULL)
- layout->incremental_inputs()->report_object(obj, NULL);
+ layout->incremental_inputs()->report_object(obj, this);
obj->layout(symtab, layout, sd);
obj->add_symbols(symtab, sd, layout);
}
obj->unlock(this->task_);
}
+// Iterate over all unused symbols, and call the visitor class V for each.
+
+void
+Lib_group::do_for_all_unused_symbols(Symbol_visitor_base* v) const
+{
+ // Files are removed from the members list when used, so all the
+ // files remaining on the list are unused.
+ for (std::vector<Archive_member>::const_iterator p = this->members_.begin();
+ p != this->members_.end();
+ ++p)
+ {
+ Object* obj = p->obj_;
+ obj->for_all_global_symbols(p->sd_, v);
+ }
+}
+
// Print statistical information to stderr. This is used for --stats.
void
void
Add_lib_group_symbols::run(Workqueue*)
{
+ // For an incremental link, begin recording layout information.
+ Incremental_inputs* incremental_inputs = this->layout_->incremental_inputs();
+ if (incremental_inputs != NULL)
+ incremental_inputs->report_archive_begin(this->lib_);
+
this->lib_->add_symbols(this->symtab_, this->layout_, this->input_objects_);
- // FIXME: Record incremental link info for --start_lib/--end_lib.
+ if (incremental_inputs != NULL)
+ incremental_inputs->report_archive_end(this->lib_);
}
Add_lib_group_symbols::~Add_lib_group_symbols()
Read_symbols_data* sd_;
};
+// This class serves as a base class for Archive and Lib_group objects.
+
+class Library_base
+{
+ public:
+ Library_base(Task* task)
+ : task_(task), incremental_info_(NULL)
+ { }
+
+ virtual
+ ~Library_base()
+ { }
+
+ // The file name.
+ const std::string&
+ filename() const
+ { return this->do_filename(); }
+
+ // The modification time of the archive file.
+ Timespec
+ get_mtime()
+ { return this->do_get_mtime(); }
+
+ // When we see a symbol in an archive we might decide to include the member,
+ // not include the member or be undecided. This enum represents these
+ // possibilities.
+
+ enum Should_include
+ {
+ SHOULD_INCLUDE_NO,
+ SHOULD_INCLUDE_YES,
+ SHOULD_INCLUDE_UNKNOWN
+ };
+
+ static Should_include
+ should_include_member(Symbol_table* symtab, Layout*, const char* sym_name,
+ Symbol** symp, std::string* why, char** tmpbufp,
+ size_t* tmpbuflen);
+
+ // Store a pointer to the incremental link info for the library.
+ void
+ set_incremental_info(Incremental_archive_entry* info)
+ { this->incremental_info_ = info; }
+
+ // Return the pointer to the incremental link info for the library.
+ Incremental_archive_entry*
+ incremental_info() const
+ { return this->incremental_info_; }
+
+ // Abstract base class for processing unused symbols.
+ class Symbol_visitor_base
+ {
+ public:
+ Symbol_visitor_base()
+ { }
+
+ virtual
+ ~Symbol_visitor_base()
+ { }
+
+ // This function will be called for each unused global
+ // symbol in a library, with a pointer to the symbol name.
+ virtual void
+ visit(const char* /* name */) = 0;
+ };
+
+ // Iterator for unused global symbols in the library.
+ // Calls v->visit() for each global symbol defined
+ // in each unused library member, passing a pointer to
+ // the symbol name.
+ void
+ for_all_unused_symbols(Symbol_visitor_base* v) const
+ { this->do_for_all_unused_symbols(v); }
+
+ protected:
+ // The task reading this archive.
+ Task *task_;
+
+ private:
+ // The file name.
+ virtual const std::string&
+ do_filename() const = 0;
+
+ // Return the modification time of the archive file.
+ virtual Timespec
+ do_get_mtime() = 0;
+
+ // Iterator for unused global symbols in the library.
+ virtual void
+ do_for_all_unused_symbols(Symbol_visitor_base* v) const = 0;
+
+ // The incremental link information for this archive.
+ Incremental_archive_entry* incremental_info_;
+};
+
// This class represents an archive--generally a libNAME.a file.
// Archives have a symbol table and a list of objects.
-class Archive
+class Archive : public Library_base
{
public:
Archive(const std::string& name, Input_file* input_file,
input_file() const
{ return this->input_file_; }
- // The file name.
- const std::string&
- filename() const
- { return this->input_file_->filename(); }
-
// Set up the archive: read the symbol map.
void
setup();
no_export()
{ return this->no_export_; }
- // Store a pointer to the incremental link info for the archive.
- void
- set_incremental_info(Incremental_archive_entry* info)
- { this->incremental_info_ = info; }
-
- // Return the pointer to the incremental link info for the archive.
- Incremental_archive_entry*
- incremental_info() const
- { return this->incremental_info_; }
-
- // When we see a symbol in an archive we might decide to include the member,
- // not include the member or be undecided. This enum represents these
- // possibilities.
-
- enum Should_include
- {
- SHOULD_INCLUDE_NO,
- SHOULD_INCLUDE_YES,
- SHOULD_INCLUDE_UNKNOWN
- };
-
- static Should_include
- should_include_member(Symbol_table* symtab, Layout*, const char* sym_name,
- Symbol** symp, std::string* why, char** tmpbufp,
- size_t* tmpbuflen);
-
- private:
- struct Armap_entry;
-
- public:
- // Iterator class for unused global symbols. This iterator is used
- // for incremental links.
-
- class Unused_symbol_iterator
- {
- public:
- Unused_symbol_iterator(Archive* arch,
- std::vector<Armap_entry>::const_iterator it)
- : arch_(arch), it_(it)
- { this->skip_used_symbols(); }
-
- const char*
- operator*() const
- { return this->arch_->armap_names_.data() + this->it_->name_offset; }
-
- Unused_symbol_iterator&
- operator++()
- {
- ++this->it_;
- this->skip_used_symbols();
- return *this;
- }
-
- bool
- operator==(const Unused_symbol_iterator p) const
- { return this->it_ == p.it_; }
-
- bool
- operator!=(const Unused_symbol_iterator p) const
- { return this->it_ != p.it_; }
-
- private:
- // Skip over symbols defined by members that have been included.
- void
- skip_used_symbols()
- {
- while (this->it_ != this->arch_->armap_.end()
- && (this->arch_->seen_offsets_.find(this->it_->file_offset)
- != this->arch_->seen_offsets_.end()))
- ++it_;
- }
-
- // The underlying archive.
- Archive* arch_;
-
- // The underlying iterator over all entries in the archive map.
- std::vector<Armap_entry>::const_iterator it_;
- };
-
- // Return an iterator referring to the first unused symbol.
- Unused_symbol_iterator
- unused_symbols_begin()
- { return Unused_symbol_iterator(this, this->armap_.begin()); }
-
- // Return an iterator referring to the end of the unused symbols.
- Unused_symbol_iterator
- unused_symbols_end()
- { return Unused_symbol_iterator(this, this->armap_.end()); }
-
private:
Archive(const Archive&);
Archive& operator=(const Archive&);
+ // The file name.
+ const std::string&
+ do_filename() const
+ { return this->input_file_->filename(); }
+
+ // The modification time of the archive file.
+ Timespec
+ do_get_mtime()
+ { return this->file().get_mtime(); }
+
struct Archive_header;
// Total number of archives seen.
friend class const_iterator;
+ // Iterator for unused global symbols in the library.
+ void
+ do_for_all_unused_symbols(Symbol_visitor_base* v) const;
+
// An entry in the archive map of symbols to object files.
struct Armap_entry
{
Nested_archive_table nested_archives_;
// The directory search path.
Dirsearch* dirpath_;
- // The task reading this archive.
- Task* task_;
// Number of members in this archive;
unsigned int num_members_;
// True if we exclude this library archive from automatic export.
bool no_export_;
- // The incremental link information for this archive.
- Incremental_archive_entry* incremental_info_;
};
// This class is used to read an archive and pick out the desired
// This class represents the files surrounded by a --start-lib ... --end-lib.
-class Lib_group
+class Lib_group : public Library_base
{
public:
Lib_group(const Input_file_lib* lib, Task* task);
return &this->members_[i];
}
- // Dump statistical information to stderr.
- static void
- print_stats();
-
// Total number of archives seen.
static unsigned int total_lib_groups;
// Total number of archive members seen.
// Number of archive members loaded.
static unsigned int total_members_loaded;
+ // Dump statistical information to stderr.
+ static void
+ print_stats();
+
private:
+ // The file name.
+ const std::string&
+ do_filename() const;
+
+ // A Lib_group does not have a modification time, since there is no
+ // real library file.
+ Timespec
+ do_get_mtime()
+ { return Timespec(0, 0); }
+
+ // Iterator for unused global symbols in the library.
+ void
+ do_for_all_unused_symbols(Symbol_visitor_base*) const;
+
// For reading the files.
const Input_file_lib* lib_;
- // The task reading this lib group.
- Task* task_;
// Table of the objects in the group.
std::vector<Archive_member> members_;
};
return Archive::SHOULD_INCLUDE_YES;
}
+// Iterate over global symbols, calling a visitor class V for each.
+
+template<int size, bool big_endian>
+void
+Sized_dynobj<size, big_endian>::do_for_all_global_symbols(
+ Read_symbols_data* sd,
+ Library_base::Symbol_visitor_base* v)
+{
+ const char* sym_names =
+ reinterpret_cast<const char*>(sd->symbol_names->data());
+ const unsigned char* syms =
+ sd->symbols->data() + sd->external_symbols_offset;
+ const int sym_size = elfcpp::Elf_sizes<size>::sym_size;
+ size_t symcount = ((sd->symbols_size - sd->external_symbols_offset)
+ / sym_size);
+ const unsigned char* p = syms;
+
+ for (size_t i = 0; i < symcount; ++i, p += sym_size)
+ {
+ elfcpp::Sym<size, big_endian> sym(p);
+ if (sym.get_st_shndx() != elfcpp::SHN_UNDEF
+ && sym.get_st_bind() != elfcpp::STB_LOCAL)
+ v->visit(sym_names + sym.get_st_name());
+ }
+}
+
// Get symbol counts.
template<int size, bool big_endian>
do_should_include_member(Symbol_table* symtab, Layout*, Read_symbols_data*,
std::string* why);
+ // Iterate over global symbols, calling a visitor class V for each.
+ void
+ do_for_all_global_symbols(Read_symbols_data* sd,
+ Library_base::Symbol_visitor_base* v);
+
// Get the size of a section.
uint64_t
do_section_size(unsigned int shndx)
// input objects until report_archive_end is called.
void
-Incremental_inputs::report_archive_begin(Archive* arch)
+Incremental_inputs::report_archive_begin(Library_base* arch)
{
Stringpool::Key filename_key;
- Timespec mtime = arch->file().get_mtime();
+ Timespec mtime = arch->get_mtime();
this->strtab_->add(arch->filename().c_str(), false, &filename_key);
Incremental_archive_entry* entry =
- new Incremental_archive_entry(filename_key, arch, mtime);
+ new Incremental_archive_entry(filename_key, mtime);
arch->set_incremental_info(entry);
+ this->inputs_.push_back(entry);
}
+// Visitor class for processing the unused global symbols in a library.
+// An instance of this class is passed to the library's
+// for_all_unused_symbols() iterator, which will call the visit()
+// function for each global symbol defined in each unused library
+// member. We add those symbol names to the incremental info for the
+// library.
+
+class Unused_symbol_visitor : public Library_base::Symbol_visitor_base
+{
+ public:
+ Unused_symbol_visitor(Incremental_archive_entry* entry, Stringpool* strtab)
+ : entry_(entry), strtab_(strtab)
+ { }
+
+ void
+ visit(const char* sym)
+ {
+ Stringpool::Key symbol_key;
+ this->strtab_->add(sym, true, &symbol_key);
+ this->entry_->add_unused_global_symbol(symbol_key);
+ }
+
+ private:
+ Incremental_archive_entry* entry_;
+ Stringpool* strtab_;
+};
+
// Finish recording the input archive file ARCHIVE. This is called by the
// Add_archive_symbols task after determining which archive members
// to include.
void
-Incremental_inputs::report_archive_end(Archive* arch)
+Incremental_inputs::report_archive_end(Library_base* arch)
{
Incremental_archive_entry* entry = arch->incremental_info();
gold_assert(entry != NULL);
// Collect unused global symbols.
- for (Archive::Unused_symbol_iterator p = arch->unused_symbols_begin();
- p != arch->unused_symbols_end();
- ++p)
- {
- Stringpool::Key symbol_key;
- this->strtab_->add(*p, true, &symbol_key);
- entry->add_unused_global_symbol(symbol_key);
- }
- this->inputs_.push_back(entry);
+ Unused_symbol_visitor v(entry, this->strtab_);
+ arch->for_all_unused_symbols(&v);
}
// Record the input object file OBJ. If ARCH is not NULL, attach
// Add_symbols task after finding out the type of the file.
void
-Incremental_inputs::report_object(Object* obj, Archive* arch)
+Incremental_inputs::report_object(Object* obj, Library_base* arch)
{
Stringpool::Key filename_key;
Timespec mtime = obj->input_file()->file().get_mtime();
class Incremental_archive_entry : public Incremental_input_entry
{
public:
- Incremental_archive_entry(Stringpool::Key filename_key, Archive*,
- Timespec mtime)
+ Incremental_archive_entry(Stringpool::Key filename_key, Timespec mtime)
: Incremental_input_entry(filename_key, mtime), members_(), unused_syms_()
{ }
// Record the initial info for archive file ARCHIVE.
void
- report_archive_begin(Archive* arch);
+ report_archive_begin(Library_base* arch);
// Record the final info for archive file ARCHIVE.
void
- report_archive_end(Archive* arch);
+ report_archive_end(Library_base* arch);
// Record the info for object file OBJ. If ARCH is not NULL,
// attach the object file to the archive.
void
- report_object(Object* obj, Archive* arch);
+ report_object(Object* obj, Library_base* arch);
// Record an input section belonging to object file OBJ.
void
return Archive::SHOULD_INCLUDE_UNKNOWN;
}
+// Iterate over global defined symbols, calling a visitor class V for each.
+
+template<int size, bool big_endian>
+void
+Sized_relobj<size, big_endian>::do_for_all_global_symbols(
+ Read_symbols_data* sd,
+ Library_base::Symbol_visitor_base* v)
+{
+ const char* sym_names =
+ reinterpret_cast<const char*>(sd->symbol_names->data());
+ const unsigned char* syms =
+ sd->symbols->data() + sd->external_symbols_offset;
+ const int sym_size = elfcpp::Elf_sizes<size>::sym_size;
+ size_t symcount = ((sd->symbols_size - sd->external_symbols_offset)
+ / sym_size);
+ const unsigned char* p = syms;
+
+ for (size_t i = 0; i < symcount; ++i, p += sym_size)
+ {
+ elfcpp::Sym<size, big_endian> sym(p);
+ if (sym.get_st_shndx() != elfcpp::SHN_UNDEF)
+ v->visit(sym_names + sym.get_st_name());
+ }
+}
+
// Return whether the local symbol SYMNDX has a PLT offset.
template<int size, bool big_endian>
Read_symbols_data* sd, std::string* why)
{ return this->do_should_include_member(symtab, layout, sd, why); }
+ // Iterate over global symbols, calling a visitor class V for each.
+ void
+ for_all_global_symbols(Read_symbols_data* sd,
+ Library_base::Symbol_visitor_base* v)
+ { return this->do_for_all_global_symbols(sd, v); }
+
// Functions and types for the elfcpp::Elf_file interface. This
// permit us to use Object as the File template parameter for
// elfcpp::Elf_file.
do_should_include_member(Symbol_table* symtab, Layout*, Read_symbols_data*,
std::string* why) = 0;
+ // Iterate over global symbols, calling a visitor class V for each.
+ virtual void
+ do_for_all_global_symbols(Read_symbols_data* sd,
+ Library_base::Symbol_visitor_base* v) = 0;
+
// Return the location of the contents of a section. Implemented by
// child class.
virtual Location
do_should_include_member(Symbol_table* symtab, Layout*, Read_symbols_data*,
std::string* why);
+ // Iterate over global symbols, calling a visitor class V for each.
+ void
+ do_for_all_global_symbols(Read_symbols_data* sd,
+ Library_base::Symbol_visitor_base* v);
+
// Read the relocs.
void
do_read_relocs(Read_relocs_data*);
return Archive::SHOULD_INCLUDE_UNKNOWN;
}
+// Iterate over global symbols, calling a visitor class V for each.
+
+template<int size, bool big_endian>
+void
+Sized_pluginobj<size, big_endian>::do_for_all_global_symbols(
+ Read_symbols_data*,
+ Library_base::Symbol_visitor_base* v)
+{
+ for (int i = 0; i < this->nsyms_; ++i)
+ {
+ const struct ld_plugin_symbol& sym = this->syms_[i];
+ if (sym.def != LDPK_UNDEF)
+ v->visit(sym.name);
+ }
+}
+
// Get the size of a section. Not used for plugin objects.
template<int size, bool big_endian>
do_should_include_member(Symbol_table* symtab, Layout*, Read_symbols_data*,
std::string* why);
+ // Iterate over global symbols, calling a visitor class V for each.
+ void
+ do_for_all_global_symbols(Read_symbols_data* sd,
+ Library_base::Symbol_visitor_base* v);
+
// Get the size of a section.
uint64_t
do_section_size(unsigned int shndx);