2009-05-25 Tristan Gingold <gingold@adacore.com>
[binutils.git] / gold / cref.cc
blobec95f36db324475ec4313d6a7cb370a71fdc6645
1 // cref.cc -- cross reference for gold
3 // Copyright 2008 Free Software Foundation, Inc.
4 // Written by Ian Lance Taylor <iant@google.com>.
6 // This file is part of gold.
8 // This program is free software; you can redistribute it and/or modify
9 // it under the terms of the GNU General Public License as published by
10 // the Free Software Foundation; either version 3 of the License, or
11 // (at your option) any later version.
13 // This program is distributed in the hope that it will be useful,
14 // but WITHOUT ANY WARRANTY; without even the implied warranty of
15 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 // GNU General Public License for more details.
18 // You should have received a copy of the GNU General Public License
19 // along with this program; if not, write to the Free Software
20 // Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston,
21 // MA 02110-1301, USA.
23 #include "gold.h"
25 #include <cerrno>
26 #include <cstdio>
27 #include <cstring>
28 #include <map>
29 #include <string>
30 #include <vector>
32 #include "object.h"
33 #include "archive.h"
34 #include "cref.h"
36 namespace gold
39 // Class Cref_inputs. This is used to hold the list of input files
40 // for cross referencing.
42 class Cref_inputs
44 public:
45 Cref_inputs()
46 : objects_(), archives_(), current_(&this->objects_)
47 { }
49 // Add an input object file.
50 void
51 add_object(Object* object);
53 // Start adding an archive. We support nested archives for future
54 // flexibility.
55 void
56 add_archive_start(Archive*);
58 // Finish adding an archive.
59 void
60 add_archive_stop(Archive*);
62 // Report symbol counts.
63 void
64 print_symbol_counts(const Symbol_table*, FILE*) const;
66 private:
67 // A list of input objects.
68 typedef std::vector<Object*> Objects;
70 // Information we record for an archive.
71 struct Archive_info
73 // Archive name.
74 std::string name;
75 // List of objects included from the archive.
76 Objects* objects;
77 // Number of archive members.
78 size_t member_count;
81 // A mapping from the name of an archive to the list of objects in
82 // that archive.
83 typedef std::map<std::string, Archive_info> Archives;
85 // Report symbol counts for a list of Objects.
86 void
87 print_objects_symbol_counts(const Symbol_table*, FILE*, const Objects*) const;
89 // Report symbol counts for an object.
90 void
91 print_object_symbol_counts(const Symbol_table*, FILE*, const Object*) const;
93 // List of input objects.
94 Objects objects_;
95 // List of input archives. This is a mapping from the archive file
96 // name to the list of objects.
97 Archives archives_;
98 // The list to which we are currently adding objects.
99 Objects* current_;
102 // Add an object.
104 void
105 Cref_inputs::add_object(Object* object)
107 this->current_->push_back(object);
110 // Start adding an archive.
112 void
113 Cref_inputs::add_archive_start(Archive* archive)
115 gold_assert(this->current_ == &this->objects_);
116 if (this->archives_.find(archive->name()) == this->archives_.end())
118 Archive_info* pai = &this->archives_[archive->name()];
119 pai->name = archive->filename();
120 pai->objects = new Objects();
121 pai->member_count = archive->count_members();
123 this->current_ = this->archives_[archive->name()].objects;
126 // Stop adding an archive.
128 void
129 Cref_inputs::add_archive_stop(Archive*)
131 gold_assert(this->current_ != &this->objects_);
132 this->current_ = &this->objects_;
135 // Report symbol counts for an object.
137 void
138 Cref_inputs::print_object_symbol_counts(const Symbol_table* symtab,
139 FILE* f,
140 const Object* object) const
142 size_t defined, used;
143 object->get_global_symbol_counts(symtab, &defined, &used);
144 fprintf(f, "symbols %s %zu %zu\n", object->name().c_str(), defined, used);
147 // Report symbol counts for a list of Inputs.
149 void
150 Cref_inputs::print_objects_symbol_counts(const Symbol_table* symtab,
151 FILE* f,
152 const Objects* objects) const
154 for (Objects::const_iterator p = objects->begin();
155 p != objects->end();
156 ++p)
157 this->print_object_symbol_counts(symtab, f, *p);
160 // Print symbol counts. This implements --print-symbol-counts. This
161 // is intended to be easily read by a program. This outputs a series
162 // of lines. There are two different types of lines.
164 // The first is "symbols FILENAME DEFINED USED". FILENAME is the name
165 // of an object file included in the link; for an archive, this will
166 // be ARCHIVEFILENAME(MEMBERNAME). DEFINED is the number of symbols
167 // which the object file defines. USED is the number of symbols which
168 // are used in the final output; this is the number of symbols which
169 // appear in the final output table as having been defined by this
170 // object. These numbers will be different when weak symbols are
171 // used, and they will be different for dynamic objects.
173 // The second is "archives FILENAME MEMBERS USED". FILENAME is the
174 // name of an archive file included in the link. MEMBERS is the
175 // number of members of the archive. USED is the number of archive
176 // members included in the link.
178 void
179 Cref_inputs::print_symbol_counts(const Symbol_table* symtab, FILE* f) const
181 this->print_objects_symbol_counts(symtab, f, &this->objects_);
182 for (Archives::const_iterator p = this->archives_.begin();
183 p != this->archives_.end();
184 ++p)
186 fprintf(f, "archive %s %zu %zu\n", p->second.name.c_str(),
187 p->second.member_count, p->second.objects->size());
188 this->print_objects_symbol_counts(symtab, f, p->second.objects);
192 // Class Cref.
194 // Make sure the Cref_inputs object has been created.
196 void
197 Cref::need_inputs()
199 if (this->inputs_ == NULL)
200 this->inputs_ = new Cref_inputs();
203 // Add an input object file.
205 void
206 Cref::add_object(Object* object)
208 this->need_inputs();
209 this->inputs_->add_object(object);
212 // Start adding an archive.
214 void
215 Cref::add_archive_start(Archive* archive)
217 this->need_inputs();
218 this->inputs_->add_archive_start(archive);
221 // Stop adding an archive.
223 void
224 Cref::add_archive_stop(Archive* archive)
226 this->inputs_->add_archive_stop(archive);
229 // Print symbol counts.
231 void
232 Cref::print_symbol_counts(const Symbol_table* symtab) const
234 if (parameters->options().user_set_print_symbol_counts()
235 && this->inputs_ != NULL)
237 FILE* f;
238 if (strcmp(parameters->options().print_symbol_counts(), "-") == 0)
239 f = stdout;
240 else
242 f = fopen(parameters->options().print_symbol_counts(), "w");
243 if (f == NULL)
244 gold_error(_("cannot open symbol count file %s: %s"),
245 parameters->options().print_symbol_counts(),
246 strerror(errno));
248 if (f != NULL)
249 this->inputs_->print_symbol_counts(symtab, f);
253 } // End namespace gold.