aboutsummaryrefslogtreecommitdiff
path: root/gold
diff options
context:
space:
mode:
Diffstat (limited to 'gold')
-rw-r--r--gold/ChangeLog31
-rw-r--r--gold/cref.cc158
-rw-r--r--gold/cref.h8
-rw-r--r--gold/dynobj.cc9
-rw-r--r--gold/dynobj.h7
-rw-r--r--gold/main.cc13
-rw-r--r--gold/mapfile.h7
-rw-r--r--gold/object.cc20
-rw-r--r--gold/object.h21
-rw-r--r--gold/options.h6
-rw-r--r--gold/plugin.cc11
-rw-r--r--gold/plugin.h6
12 files changed, 276 insertions, 21 deletions
diff --git a/gold/ChangeLog b/gold/ChangeLog
index 5330d5f..e176234 100644
--- a/gold/ChangeLog
+++ b/gold/ChangeLog
@@ -1,5 +1,36 @@
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
to is_default_version. Rename insdef to insdefault.
(Symbol_table::add_from_relobj): Rename def to is_default_version
diff --git a/gold/cref.cc b/gold/cref.cc
index ec95f36..c36f989 100644
--- a/gold/cref.cc
+++ b/gold/cref.cc
@@ -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.
diff --git a/gold/cref.h b/gold/cref.h
index 3da5d3a..a40a34a 100644
--- a/gold/cref.h
+++ b/gold/cref.h
@@ -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();
diff --git a/gold/dynobj.cc b/gold/dynobj.cc
index f982c4b..fac8715 100644
--- a/gold/dynobj.cc
+++ b/gold/dynobj.cc
@@ -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);
diff --git a/gold/dynobj.h b/gold/dynobj.h
index 66d2bff..71d1b68 100644
--- a/gold/dynobj.h
+++ b/gold/dynobj.h
@@ -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;
diff --git a/gold/main.cc b/gold/main.cc
index 5d6cbd5..9be4972 100644
--- a/gold/main.cc
+++ b/gold/main.cc
@@ -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)
diff --git a/gold/mapfile.h b/gold/mapfile.h
index ab55c38..908a208 100644
--- a/gold/mapfile.h
+++ b/gold/mapfile.h
@@ -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
diff --git a/gold/object.cc b/gold/object.cc
index 127e3a6..3fedcf8 100644
--- a/gold/object.cc
+++ b/gold/object.cc
@@ -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
diff --git a/gold/object.h b/gold/object.h
index 187a101..26e85f5 100644
--- a/gold/object.h
+++ b/gold/object.h
@@ -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
diff --git a/gold/options.h b/gold/options.h
index 08c5fdc..907a8a3 100644
--- a/gold/options.h
+++ b/gold/options.h
@@ -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"));
diff --git a/gold/plugin.cc b/gold/plugin.cc
index ff9f98f..2831c2b 100644
--- a/gold/plugin.cc
+++ b/gold/plugin.cc
@@ -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.
diff --git a/gold/plugin.h b/gold/plugin.h
index fa6e594..635ed6f 100644
--- a/gold/plugin.h
+++ b/gold/plugin.h
@@ -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);