* archive.cc (Library_base::should_include_member): Move
authorCary Coutant <ccoutant@google.com>
Wed, 30 Mar 2011 01:31:57 +0000 (01:31 +0000)
committerCary Coutant <ccoutant@google.com>
Wed, 30 Mar 2011 01:31:57 +0000 (01:31 +0000)
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.

gold/ChangeLog
gold/archive.cc
gold/archive.h
gold/dynobj.cc
gold/dynobj.h
gold/incremental.cc
gold/incremental.h
gold/object.cc
gold/object.h
gold/plugin.cc
gold/plugin.h

index f44f97b3d3996a5eac02be81aa6a1605ed9e5bb4..5319a6394407ddb63a1d46ef7217244aedee5b54 100644 (file)
@@ -1,3 +1,68 @@
+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
index b965709ba95b6f52b15b90f4ba0e340a91183433..4aafb71664dc9ede13a72413a9f0bfb05d8658ea 100644 (file)
 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.
@@ -87,11 +171,10 @@ const char Archive::arfmag[2] = { '`', '\n' };
 
 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());
@@ -619,82 +702,6 @@ Archive::read_symbols(off_t off)
   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
@@ -971,6 +978,21 @@ Archive::include_member(Symbol_table* symtab, Layout* layout,
   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
@@ -1047,7 +1069,6 @@ Add_archive_symbols::run(Workqueue* workqueue)
   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_);
 
@@ -1073,11 +1094,18 @@ unsigned int Lib_group::total_members;
 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
@@ -1167,9 +1195,8 @@ Lib_group::include_member(Symbol_table* symtab, Layout* layout,
   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);
     }
@@ -1178,6 +1205,22 @@ Lib_group::include_member(Symbol_table* symtab, Layout* 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
@@ -1210,9 +1253,15 @@ Add_lib_group_symbols::locks(Task_locker* tl)
 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()
index c5ba114ed5c446ebb79e719fa0e640eeaecd7abe..e4283158b30d373d1ea6540121c5cf43e9804d3a 100644 (file)
@@ -59,10 +59,105 @@ struct Archive_member
   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,
@@ -90,11 +185,6 @@ class Archive
   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();
@@ -169,99 +259,20 @@ class Archive
   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.
@@ -339,6 +350,10 @@ class Archive
 
   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
   {
@@ -384,14 +399,10 @@ class Archive
   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
@@ -451,7 +462,7 @@ class Add_archive_symbols : public Task
 
 // 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);
@@ -470,10 +481,6 @@ class Lib_group
     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.
@@ -481,11 +488,27 @@ class Lib_group
   // 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_;
 };
index d2ba8aec27126bfd4f07ad7d03a6377c670c5dc0..3b2031ff51b7b71971b5fe4bcc5f60eced08b837 100644 (file)
@@ -761,6 +761,32 @@ Sized_dynobj<size, big_endian>::do_should_include_member(Symbol_table*,
   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>
index 8787adaab60750428a139b55f738d69301de1d83..7f8576d2ca2c90162900a1c5704916ee18eb8e4a 100644 (file)
@@ -181,6 +181,11 @@ class Sized_dynobj : public Dynobj
   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)
index aa9d7d3a7fe99c9f6e1686ae8cd158622d6a74d2..f7edf0427adfc9f61416c9ea3932c7a757d8e6a0 100644 (file)
@@ -436,38 +436,59 @@ Incremental_inputs::report_command_line(int argc, const char* const* argv)
 // 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
@@ -475,7 +496,7 @@ Incremental_inputs::report_archive_end(Archive* arch)
 // 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();
index cc0e839ee94dc53f7eb5ab551b1ae1483eebae5c..b55aa7135d0a592d8bafbb3f3dd9625e8af2af8d 100644 (file)
@@ -451,8 +451,7 @@ class Incremental_object_entry : public Incremental_input_entry
 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_()
   { }
 
@@ -531,16 +530,16 @@ class Incremental_inputs
 
   // 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
index e2c011378e19eea68f2f7dbd58084062c5717e87..dfe2258476e657a604ab29f9a25671b70c23f5ba 100644 (file)
@@ -1691,6 +1691,31 @@ Sized_relobj<size, big_endian>::do_should_include_member(Symbol_table* symtab,
   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>
index 8ee03a703fe5af857609f9a5af732fbae405ff5c..0b25b423e22ac9b73a0afbf670c93d92e1c7b372 100644 (file)
@@ -422,6 +422,12 @@ class Object
                        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.
@@ -572,6 +578,11 @@ class Object
   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
@@ -1810,6 +1821,11 @@ class Sized_relobj : public Relobj
   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*);
index 7e259e0803345875e9a1938e5b31560db876e1b7..5701fd7d0ec3c8dcc5d18cf4b84fb9469b790269 100644 (file)
@@ -985,6 +985,22 @@ Sized_pluginobj<size, big_endian>::do_should_include_member(
   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>
index 87747bf2086d65b37508a7c03517b1f835165d5c..04be82c782dcf556c1e5dc43db1b2b33b6acc640 100644 (file)
@@ -449,6 +449,11 @@ class Sized_pluginobj : public Pluginobj
   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);