From dde3f402cfe649f271730fa5de983ee663743ea3 Mon Sep 17 00:00:00 2001 From: Ian Lance Taylor Date: Tue, 5 Jan 2010 21:52:51 +0000 Subject: [PATCH] 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 . (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. --- gold/ChangeLog | 31 ++++++++++ gold/cref.cc | 158 ++++++++++++++++++++++++++++++++++++++++++++++++- gold/cref.h | 8 ++- gold/dynobj.cc | 9 +-- gold/dynobj.h | 7 ++- gold/main.cc | 13 ++-- gold/mapfile.h | 7 ++- gold/object.cc | 20 +++++-- gold/object.h | 21 ++++++- gold/options.h | 6 +- gold/plugin.cc | 11 +++- gold/plugin.h | 6 +- 12 files changed, 276 insertions(+), 21 deletions(-) diff --git a/gold/ChangeLog b/gold/ChangeLog index 5330d5fcc8d..e1762340c22 100644 --- a/gold/ChangeLog +++ b/gold/ChangeLog @@ -1,3 +1,34 @@ +2010-01-05 Ian Lance Taylor + + 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 . + (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 * symtab.cc (Symbol_table::add_from_object): Rename def parameter diff --git a/gold/cref.cc b/gold/cref.cc index ec95f36db32..c36f989635c 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 . // 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 Objects; @@ -82,6 +87,19 @@ class Cref_inputs // that archive. typedef std::map 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 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 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 3da5d3ad326..a40a34af5fe 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 . // This file is part of gold. @@ -23,6 +23,8 @@ #ifndef GOLD_CREF_H #define GOLD_CREF_H +#include + 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 f982c4b469d..fac8715d413 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 . // This file is part of gold. @@ -682,9 +682,10 @@ Sized_dynobj::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 66d2bff3a49..71d1b68f60c 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 . // 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 This; diff --git a/gold/main.cc b/gold/main.cc index 5d6cbd5a0f5..9be497204cc 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 . // 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 ab55c38ea4f..908a208ed5c 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 . // 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 127e3a6d651..3fedcf83cf9 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 . // 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 187a10179b5..26e85f5b6a8 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 . // This file is part of gold. @@ -188,6 +188,8 @@ class Xindex class Object { public: + typedef std::vector 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 08c5fdc6269..907a8a3481b 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 . // 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 ff9f98f282c..2831c2b19fd 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 . // This file is part of gold. @@ -784,6 +784,15 @@ Sized_pluginobj::do_get_global_symbol_counts(const Symbol_tabl gold_unreachable(); } +// Get symbols. Not used for plugin objects. + +template +const Object::Symbols* +Sized_pluginobj::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 fa6e594d37a..635ed6f861b 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 . // 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); -- 2.30.2