PR 10980
authorIan Lance Taylor <ian@airs.com>
Tue, 5 Jan 2010 21:52:51 +0000 (21:52 +0000)
committerIan Lance Taylor <ian@airs.com>
Tue, 5 Jan 2010 21:52:51 +0000 (21:52 +0000)
* options.h (class General_options): Add --cref.
* main.cc (main): Print cref table if --cref.  Don't close mapfile
until after printing cref table.
* cref.cc: Include "symtab.h".
(class Cref_inputs): Define Cref_table_compare and Cref_table.
(Cref_table_compare::operator()): New function.
(Cref_inputs::gather_cref): New function.
(filecol): New static const.
(Cref_inputs::print_cref): New function.
(Cref::print_cref): New function.
* cref.h: Include <cstdio>.
(class Cref): Update declarations.
* mapfile.h (Mapfile::file): New function.
* object.h (class Object): Define Symbols.  Declare virtual
do_get_global_symbols.
(Object::get_global_symbols): New function.
* object.cc (Input_objects::add_object): Pass object to cref_ if
--cref.
(Input_objects::archive_start): Likewise.
(Input_objects::archive_stop): Likewise.
(Input_objects::print_cref): New function.
* dynobj.h (Sized_dynobj::do_get_global_symbols): New function.
* dynobj.cc (big_endian>::do_add_symbols): Create symbols_ if
--cref.
* plugin.cc (Sized_pluginobj::do_get_global_symbols): New
function.
* plugin.h (class Sized_pluginobj): Update declarations.

12 files changed:
gold/ChangeLog
gold/cref.cc
gold/cref.h
gold/dynobj.cc
gold/dynobj.h
gold/main.cc
gold/mapfile.h
gold/object.cc
gold/object.h
gold/options.h
gold/plugin.cc
gold/plugin.h

index 5330d5fcc8d8ed90b5c82bb0632d568ad596b6ad..e1762340c227817be318e042f16ef4c8e1b81334 100644 (file)
@@ -1,3 +1,34 @@
+2010-01-05  Ian Lance Taylor  <iant@google.com>
+
+       PR 10980
+       * options.h (class General_options): Add --cref.
+       * main.cc (main): Print cref table if --cref.  Don't close mapfile
+       until after printing cref table.
+       * cref.cc: Include "symtab.h".
+       (class Cref_inputs): Define Cref_table_compare and Cref_table.
+       (Cref_table_compare::operator()): New function.
+       (Cref_inputs::gather_cref): New function.
+       (filecol): New static const.
+       (Cref_inputs::print_cref): New function.
+       (Cref::print_cref): New function.
+       * cref.h: Include <cstdio>.
+       (class Cref): Update declarations.
+       * mapfile.h (Mapfile::file): New function.
+       * object.h (class Object): Define Symbols.  Declare virtual
+       do_get_global_symbols.
+       (Object::get_global_symbols): New function.
+       * object.cc (Input_objects::add_object): Pass object to cref_ if
+       --cref.
+       (Input_objects::archive_start): Likewise.
+       (Input_objects::archive_stop): Likewise.
+       (Input_objects::print_cref): New function.
+       * dynobj.h (Sized_dynobj::do_get_global_symbols): New function.
+       * dynobj.cc (big_endian>::do_add_symbols): Create symbols_ if
+       --cref.
+       * plugin.cc (Sized_pluginobj::do_get_global_symbols): New
+       function.
+       * plugin.h (class Sized_pluginobj): Update declarations.
+
 2010-01-05  Ian Lance Taylor  <iant@google.com>
 
        * symtab.cc (Symbol_table::add_from_object): Rename def parameter
index ec95f36db324475ec4313d6a7cb370a71fdc6645..c36f989635ce87c4cea4ae7db9a18435d6e898a3 100644 (file)
@@ -1,6 +1,6 @@
 // cref.cc -- cross reference for gold
 
-// Copyright 2008 Free Software Foundation, Inc.
+// Copyright 2008, 2010 Free Software Foundation, Inc.
 // Written by Ian Lance Taylor <iant@google.com>.
 
 // This file is part of gold.
@@ -31,6 +31,7 @@
 
 #include "object.h"
 #include "archive.h"
+#include "symtab.h"
 #include "cref.h"
 
 namespace gold
@@ -63,6 +64,10 @@ class Cref_inputs
   void
   print_symbol_counts(const Symbol_table*, FILE*) const;
 
+  // Print a cross reference tabl.e
+  void
+  print_cref(const Symbol_table*, FILE*) const;
+
  private:
   // A list of input objects.
   typedef std::vector<Object*> Objects;
@@ -82,6 +87,19 @@ class Cref_inputs
   // that archive.
   typedef std::map<std::string, Archive_info> Archives;
 
+  // For --cref, we build a cross reference table which maps from
+  // symbols to lists of objects.  The symbols are sorted
+  // alphabetically.
+
+  class Cref_table_compare
+  {
+  public:
+    bool
+    operator()(const Symbol*, const Symbol*) const;
+  };
+
+  typedef std::map<const Symbol*, Objects*, Cref_table_compare> Cref_table;
+
   // Report symbol counts for a list of Objects.
   void
   print_objects_symbol_counts(const Symbol_table*, FILE*, const Objects*) const;
@@ -90,6 +108,10 @@ class Cref_inputs
   void
   print_object_symbol_counts(const Symbol_table*, FILE*, const Object*) const;
 
+  // Gather cross reference information.
+  void
+  gather_cref(const Objects*, Cref_table*) const;
+
   // List of input objects.
   Objects objects_;
   // List of input archives.  This is a mapping from the archive file
@@ -144,7 +166,7 @@ Cref_inputs::print_object_symbol_counts(const Symbol_table* symtab,
   fprintf(f, "symbols %s %zu %zu\n", object->name().c_str(), defined, used);
 }
 
-// Report symbol counts for a list of Inputs.
+// Report symbol counts for a list of inputs.
 
 void
 Cref_inputs::print_objects_symbol_counts(const Symbol_table* symtab,
@@ -189,6 +211,124 @@ Cref_inputs::print_symbol_counts(const Symbol_table* symtab, FILE* f) const
     }
 }
 
+// Sort symbols for the cross reference table.
+
+bool
+Cref_inputs::Cref_table_compare::operator()(const Symbol* s1,
+                                           const Symbol* s2) const
+{
+  int i = strcmp(s1->name(), s2->name());
+  if (i != 0)
+    return i < 0;
+
+  if (s1->version() == NULL)
+    {
+      if (s2->version() != NULL)
+       return true;
+    }
+  else if (s2->version() == NULL)
+    return false;
+  else
+    {
+      i = strcmp(s1->version(), s2->version());
+      if (i != 0)
+       return i < 0;
+    }
+
+  // We should never have two different symbols with the same name and
+  // version.
+  if (s1 == s2)
+    return false;
+  gold_unreachable();
+}
+
+// Gather cross reference information from a list of inputs.
+
+void
+Cref_inputs::gather_cref(const Objects* objects, Cref_table* table) const
+{
+  for (Objects::const_iterator po = objects->begin();
+       po != objects->end();
+       ++po)
+    {
+      const Object::Symbols* symbols = (*po)->get_global_symbols();
+      if (symbols == NULL)
+       continue;
+      for (Object::Symbols::const_iterator ps = symbols->begin();
+          ps != symbols->end();
+          ++ps)
+       {
+         const Symbol* sym = *ps;
+         if (sym == NULL)
+           continue;
+         Objects* const onull = NULL;
+         std::pair<Cref_table::iterator, bool> ins =
+           table->insert(std::make_pair(sym, onull));
+         Cref_table::iterator pc = ins.first;
+         if (ins.second)
+           pc->second = new Objects();
+         if (sym->source() == Symbol::FROM_OBJECT
+             && sym->object() == *po
+             && sym->is_defined())
+           pc->second->insert(pc->second->begin(), *po);
+         else
+           pc->second->push_back(*po);
+       }
+    }
+}
+
+// The column where the file name starts in a cross reference table.
+
+static const size_t filecol = 50;
+
+// Print a cross reference table.
+
+void
+Cref_inputs::print_cref(const Symbol_table*, FILE* f) const
+{
+  Cref_table table;
+  this->gather_cref(&this->objects_, &table);
+  for (Archives::const_iterator p = this->archives_.begin();
+       p != this->archives_.end();
+       ++p)
+    this->gather_cref(p->second.objects, &table);
+
+  for (Cref_table::const_iterator pc = table.begin();
+       pc != table.end();
+       ++pc)
+    {
+      // If all the objects are dynamic, skip this symbol.
+      const Symbol* sym = pc->first;
+      const Objects* objects = pc->second;
+      Objects::const_iterator po;
+      for (po = objects->begin(); po != objects->end(); ++po)
+       if (!(*po)->is_dynamic())
+         break;
+      if (po == objects->end())
+       continue;
+
+      std::string s = sym->demangled_name();
+      if (sym->version() != NULL)
+       {
+         s += '@';
+         if (sym->is_default())
+           s += '@';
+         s += sym->version();
+       }
+
+      fputs(s.c_str(), f);
+
+      size_t len = s.length();
+
+      for (po = objects->begin(); po != objects->end(); ++po)
+       {
+         int n = len < filecol ? filecol - len : 1;
+         fprintf(f, "%*c%s\n", n, ' ', (*po)->name().c_str());
+         len = 0;
+       }
+    }
+}
+
 // Class Cref.
 
 // Make sure the Cref_inputs object has been created.
@@ -250,4 +390,18 @@ Cref::print_symbol_counts(const Symbol_table* symtab) const
     }
 }
 
+// Print a cross reference table.
+
+void
+Cref::print_cref(const Symbol_table* symtab, FILE* f) const
+{
+  fprintf(f, _("\nCross Reference Table\n\n"));
+  const char* msg = _("Symbol");
+  int len = filecol - strlen(msg);
+  fprintf(f, "%s%*c%s\n", msg, len, ' ', _("File"));
+
+  if (parameters->options().cref() && this->inputs_ != NULL)
+    this->inputs_->print_cref(symtab, f);
+}
+
 } // End namespace gold.
index 3da5d3ad326fdbbd90d17b8f665bc3245c848930..a40a34af5fe8e80d227630862706cbf23e543f1d 100644 (file)
@@ -1,6 +1,6 @@
 // cref.h -- cross reference reports for gold   -*- C++ -*-
 
-// Copyright 2008 Free Software Foundation, Inc.
+// Copyright 2008, 2010 Free Software Foundation, Inc.
 // Written by Ian Lance Taylor <iant@google.com>.
 
 // This file is part of gold.
@@ -23,6 +23,8 @@
 #ifndef GOLD_CREF_H
 #define GOLD_CREF_H
 
+#include <cstdio>
+
 namespace gold
 {
 
@@ -61,6 +63,10 @@ class Cref
   void
   print_symbol_counts(const Symbol_table*) const;
 
+  // Print a cross reference table.
+  void
+  print_cref(const Symbol_table*, FILE*) const;
+
  private:
   void
   need_inputs();
index f982c4b469d395813b6c11319e35f5515ed3df29..fac8715d4136246880b2b0af480eca9e065adfd8 100644 (file)
@@ -1,6 +1,6 @@
 // dynobj.cc -- dynamic object support for gold
 
-// Copyright 2006, 2007, 2008 Free Software Foundation, Inc.
+// Copyright 2006, 2007, 2008, 2009, 2010 Free Software Foundation, Inc.
 // Written by Ian Lance Taylor <iant@google.com>.
 
 // This file is part of gold.
@@ -682,9 +682,10 @@ Sized_dynobj<size, big_endian>::do_add_symbols(Symbol_table* symtab,
   Version_map version_map;
   this->make_version_map(sd, &version_map);
 
-  // If printing symbol counts, we want to track symbols.
-  
-  if (parameters->options().user_set_print_symbol_counts())
+  // If printing symbol counts or a cross reference table, we want to
+  // track symbols.
+  if (parameters->options().user_set_print_symbol_counts()
+      || parameters->options().cref())
     {
       this->symbols_ = new Symbols();
       this->symbols_->resize(symcount);
index 66d2bff3a49c22d36baeb3c38e3882fa2475a7bd..71d1b68f60cf7963660fd13a2abc29a271a98575 100644 (file)
@@ -1,6 +1,6 @@
 // dynobj.h -- dynamic object support for gold   -*- C++ -*-
 
-// Copyright 2006, 2007, 2008 Free Software Foundation, Inc.
+// Copyright 2006, 2007, 2008, 2009, 2010 Free Software Foundation, Inc.
 // Written by Ian Lance Taylor <iant@google.com>.
 
 // This file is part of gold.
@@ -236,6 +236,11 @@ class Sized_dynobj : public Dynobj
   void
   do_get_global_symbol_counts(const Symbol_table*, size_t*, size_t*) const;
 
+  // Get the global symbols.
+  const Symbols*
+  do_get_global_symbols() const
+  { return this->symbols_; }
+
  private:
   // For convenience.
   typedef Sized_dynobj<size, big_endian> This;
index 5d6cbd5a0f5f3c075afa26953d795667aa479b2c..9be497204cc677a5cdd818caf2837cb1a57c7534 100644 (file)
@@ -1,6 +1,6 @@
 // main.cc -- gold main function.
 
-// Copyright 2006, 2007, 2008, 2009 Free Software Foundation, Inc.
+// Copyright 2006, 2007, 2008, 2009, 2010 Free Software Foundation, Inc.
 // Written by Ian Lance Taylor <iant@google.com>.
 
 // This file is part of gold.
@@ -270,13 +270,18 @@ main(int argc, char** argv)
       layout.print_stats();
     }
 
-  if (mapfile != NULL)
-    mapfile->close();
-
   // Issue defined symbol report.
   if (command_line.options().user_set_print_symbol_counts())
     input_objects.print_symbol_counts(&symtab);
 
+  // Output cross reference table.
+  if (command_line.options().cref())
+    input_objects.print_cref(&symtab,
+                            mapfile == NULL ? stdout : mapfile->file());
+
+  if (mapfile != NULL)
+    mapfile->close();
+
   if (parameters->options().fatal_warnings()
       && errors.warning_count() > 0
       && errors.error_count() == 0)
index ab55c38ea4f738ffbae26687d7f77ff07a4faf57..908a208ed5ce44c9584efe1d602de0f26b36cafe 100644 (file)
@@ -1,6 +1,6 @@
 // mapfile.h -- map file generation for gold   -*- C++ -*-
 
-// Copyright 2008 Free Software Foundation, Inc.
+// Copyright 2008, 2010 Free Software Foundation, Inc.
 // Written by Ian Lance Taylor <iant@google.com>.
 
 // This file is part of gold.
@@ -54,6 +54,11 @@ class Mapfile
   void
   close();
 
+  // Return the underlying file.
+  FILE*
+  file()
+  { return this->map_file_; }
+
   // Report that we are including a member from an archive.  This is
   // called by the archive reading code.
   void
index 127e3a6d6518d9d8f52de17e6c1bf32528d381a3..3fedcf83cf9dd868ad802799ac670422f3e21cb1 100644 (file)
@@ -1,6 +1,6 @@
 // object.cc -- support for an object file for linking in gold
 
-// Copyright 2006, 2007, 2008, 2009 Free Software Foundation, Inc.
+// Copyright 2006, 2007, 2008, 2009, 2010 Free Software Foundation, Inc.
 // Written by Ian Lance Taylor <iant@google.com>.
 
 // This file is part of gold.
@@ -2146,7 +2146,8 @@ Input_objects::add_object(Object* obj)
     }
 
   // Add this object to the cross-referencer if requested.
-  if (parameters->options().user_set_print_symbol_counts())
+  if (parameters->options().user_set_print_symbol_counts()
+      || parameters->options().cref())
     {
       if (this->cref_ == NULL)
        this->cref_ = new Cref();
@@ -2206,7 +2207,8 @@ Input_objects::check_dynamic_dependencies() const
 void
 Input_objects::archive_start(Archive* archive)
 {
-  if (parameters->options().user_set_print_symbol_counts())
+  if (parameters->options().user_set_print_symbol_counts()
+      || parameters->options().cref())
     {
       if (this->cref_ == NULL)
        this->cref_ = new Cref();
@@ -2219,7 +2221,8 @@ Input_objects::archive_start(Archive* archive)
 void
 Input_objects::archive_stop(Archive* archive)
 {
-  if (parameters->options().user_set_print_symbol_counts())
+  if (parameters->options().user_set_print_symbol_counts()
+      || parameters->options().cref())
     this->cref_->add_archive_stop(archive);
 }
 
@@ -2233,6 +2236,15 @@ Input_objects::print_symbol_counts(const Symbol_table* symtab) const
     this->cref_->print_symbol_counts(symtab);
 }
 
+// Print a cross reference table.
+
+void
+Input_objects::print_cref(const Symbol_table* symtab, FILE* f) const
+{
+  if (parameters->options().cref() && this->cref_ != NULL)
+    this->cref_->print_cref(symtab, f);
+}
+
 // Relocate_info methods.
 
 // Return a string describing the location of a relocation.  This is
index 187a10179b558c41a925af22d6be127228b0e4db..26e85f5b6a8373155aa6c6533e96f7e60ec328f1 100644 (file)
@@ -1,6 +1,6 @@
 // object.h -- support for an object file for linking in gold  -*- C++ -*-
 
-// Copyright 2006, 2007, 2008, 2009 Free Software Foundation, Inc.
+// Copyright 2006, 2007, 2008, 2009, 2010 Free Software Foundation, Inc.
 // Written by Ian Lance Taylor <iant@google.com>.
 
 // This file is part of gold.
@@ -188,6 +188,8 @@ class Xindex
 class Object
 {
  public:
+  typedef std::vector<Symbol*> Symbols;
+
   // NAME is the name of the object as we would report it to the user
   // (e.g., libfoo.a(bar.o) if this is in an archive.  INPUT_FILE is
   // used to read the file.  OFFSET is the offset within the input
@@ -466,6 +468,11 @@ class Object
                           size_t* used) const
   { this->do_get_global_symbol_counts(symtab, defined, used); }
 
+  // Get the symbols defined in this object.
+  const Symbols*
+  get_global_symbols() const
+  { return this->do_get_global_symbols(); }
+
   // Return whether this object was found in a system directory.
   bool
   is_in_system_directory() const
@@ -553,6 +560,9 @@ class Object
   virtual void
   do_get_global_symbol_counts(const Symbol_table*, size_t*, size_t*) const = 0;
 
+  virtual const Symbols*
+  do_get_global_symbols() const = 0;
+
   // Set the number of sections.
   void
   set_shnum(int shnum)
@@ -1596,6 +1606,11 @@ class Sized_relobj : public Relobj
   void
   do_get_global_symbol_counts(const Symbol_table*, size_t*, size_t*) const;
 
+  // Get the global symbols.
+  const Symbols*
+  do_get_global_symbols() const
+  { return &this->symbols_; }
+
   // Get the offset of a section.
   uint64_t
   do_output_section_offset(unsigned int shndx) const
@@ -1960,6 +1975,10 @@ class Input_objects
   void
   print_symbol_counts(const Symbol_table*) const;
 
+  // Print a cross reference table.
+  void
+  print_cref(const Symbol_table*, FILE*) const;
+
   // Iterate over all regular objects.
 
   Relobj_iterator
index 08c5fdc62693d6b8da70de2b50958ad1d794da1c..907a8a3481b6d5eebf887b02f72cb5dfb75cc898 100644 (file)
@@ -1,6 +1,6 @@
 // options.h -- handle command line options for gold  -*- C++ -*-
 
-// Copyright 2006, 2007, 2008, 2009 Free Software Foundation, Inc.
+// Copyright 2006, 2007, 2008, 2009, 2010 Free Software Foundation, Inc.
 // Written by Ian Lance Taylor <iant@google.com>.
 
 // This file is part of gold.
@@ -643,6 +643,10 @@ class General_options
              N_("Not supported"),
              N_("Do not copy DT_NEEDED tags from shared libraries"));
 
+  DEFINE_bool(cref, options::TWO_DASHES, '\0', false,
+             N_("Output cross reference table"),
+             N_("Do not output cross reference table"));
+
   DEFINE_bool(define_common, options::TWO_DASHES, 'd', false,
               N_("Define common symbols"),
               N_("Do not define common symbols"));
index ff9f98f282c989d58b7a3785e588c11f73740cdc..2831c2b19fdfe5a03fcb07d7a391825f55d056ec 100644 (file)
@@ -1,6 +1,6 @@
 // plugin.cc -- plugin manager for gold      -*- C++ -*-
 
-// Copyright 2008, 2009 Free Software Foundation, Inc.
+// Copyright 2008, 2009, 2010 Free Software Foundation, Inc.
 // Written by Cary Coutant <ccoutant@google.com>.
 
 // This file is part of gold.
@@ -784,6 +784,15 @@ Sized_pluginobj<size, big_endian>::do_get_global_symbol_counts(const Symbol_tabl
   gold_unreachable();
 }
 
+// Get symbols.  Not used for plugin objects.
+
+template<int size, bool big_endian>
+const Object::Symbols*
+Sized_pluginobj<size, big_endian>::do_get_global_symbols() const
+{
+  gold_unreachable();
+}
+
 // Class Plugin_finish.  This task runs after all replacement files have
 // been added.  It calls each plugin's cleanup handler.
 
index fa6e594d37a3dc765987054bd2051668c50d64cb..635ed6f861b99cdde688ea294e38b0dd8fdeb197 100644 (file)
@@ -1,6 +1,6 @@
 // plugin.h -- plugin manager for gold      -*- C++ -*-
 
-// Copyright 2008, 2009 Free Software Foundation, Inc.
+// Copyright 2008, 2009, 2010 Free Software Foundation, Inc.
 // Written by Cary Coutant <ccoutant@google.com>.
 
 // This file is part of gold.
@@ -415,6 +415,10 @@ class Sized_pluginobj : public Pluginobj
   void
   do_get_global_symbol_counts(const Symbol_table*, size_t*, size_t*) const;
 
+  // Get global symbols.
+  const Symbols*
+  do_get_global_symbols() const;
+
   // Add placeholder symbols from a claimed file.
   ld_plugin_status
   add_symbols_from_plugin(int nsyms, const ld_plugin_symbol* syms);