Merge branch 'vendor/GREP'
[dragonfly.git] / contrib / binutils-2.20 / gold / cref.cc
1 // cref.cc -- cross reference for gold
2
3 // Copyright 2008 Free Software Foundation, Inc.
4 // Written by Ian Lance Taylor <iant@google.com>.
5
6 // This file is part of gold.
7
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.
12
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.
17
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.
22
23 #include "gold.h"
24
25 #include <cerrno>
26 #include <cstdio>
27 #include <cstring>
28 #include <map>
29 #include <string>
30 #include <vector>
31
32 #include "object.h"
33 #include "archive.h"
34 #include "cref.h"
35
36 namespace gold
37 {
38
39 // Class Cref_inputs.  This is used to hold the list of input files
40 // for cross referencing.
41
42 class Cref_inputs
43 {
44  public:
45   Cref_inputs()
46     : objects_(), archives_(), current_(&this->objects_)
47   { }
48
49   // Add an input object file.
50   void
51   add_object(Object* object);
52
53   // Start adding an archive.  We support nested archives for future
54   // flexibility.
55   void
56   add_archive_start(Archive*);
57
58   // Finish adding an archive.
59   void
60   add_archive_stop(Archive*);
61
62   // Report symbol counts.
63   void
64   print_symbol_counts(const Symbol_table*, FILE*) const;
65
66  private:
67   // A list of input objects.
68   typedef std::vector<Object*> Objects;
69
70   // Information we record for an archive.
71   struct Archive_info
72   {
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;
79   };
80
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;
84
85   // Report symbol counts for a list of Objects.
86   void
87   print_objects_symbol_counts(const Symbol_table*, FILE*, const Objects*) const;
88
89   // Report symbol counts for an object.
90   void
91   print_object_symbol_counts(const Symbol_table*, FILE*, const Object*) const;
92
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_;
100 };
101
102 // Add an object.
103
104 void
105 Cref_inputs::add_object(Object* object)
106 {
107   this->current_->push_back(object);
108 }
109
110 // Start adding an archive.
111
112 void
113 Cref_inputs::add_archive_start(Archive* archive)
114 {
115   gold_assert(this->current_ == &this->objects_);
116   if (this->archives_.find(archive->name()) == this->archives_.end())
117     {
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();
122     }
123   this->current_ = this->archives_[archive->name()].objects;
124 }
125
126 // Stop adding an archive.
127
128 void
129 Cref_inputs::add_archive_stop(Archive*)
130 {
131   gold_assert(this->current_ != &this->objects_);
132   this->current_ = &this->objects_;
133 }
134
135 // Report symbol counts for an object.
136
137 void
138 Cref_inputs::print_object_symbol_counts(const Symbol_table* symtab,
139                                         FILE* f,
140                                         const Object* object) const
141 {
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);
145 }
146
147 // Report symbol counts for a list of Inputs.
148
149 void
150 Cref_inputs::print_objects_symbol_counts(const Symbol_table* symtab,
151                                          FILE* f,
152                                          const Objects* objects) const
153 {
154   for (Objects::const_iterator p = objects->begin();
155        p != objects->end();
156        ++p)
157     this->print_object_symbol_counts(symtab, f, *p);
158 }
159
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.
163
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.
172
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.
177
178 void
179 Cref_inputs::print_symbol_counts(const Symbol_table* symtab, FILE* f) const
180 {
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)
185     {
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);
189     }
190 }
191
192 // Class Cref.
193
194 // Make sure the Cref_inputs object has been created.
195
196 void
197 Cref::need_inputs()
198 {
199   if (this->inputs_ == NULL)
200     this->inputs_ = new Cref_inputs();
201 }
202
203 // Add an input object file.
204
205 void
206 Cref::add_object(Object* object)
207 {
208   this->need_inputs();
209   this->inputs_->add_object(object);
210 }
211
212 // Start adding an archive.
213
214 void
215 Cref::add_archive_start(Archive* archive)
216 {
217   this->need_inputs();
218   this->inputs_->add_archive_start(archive);
219 }
220
221 // Stop adding an archive.
222
223 void
224 Cref::add_archive_stop(Archive* archive)
225 {
226   this->inputs_->add_archive_stop(archive);
227 }
228
229 // Print symbol counts.
230
231 void
232 Cref::print_symbol_counts(const Symbol_table* symtab) const
233 {
234   if (parameters->options().user_set_print_symbol_counts()
235       && this->inputs_ != NULL)
236     {
237       FILE* f;
238       if (strcmp(parameters->options().print_symbol_counts(), "-") == 0)
239         f = stdout;
240       else
241         {
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));
247         }
248       if (f != NULL)
249         this->inputs_->print_symbol_counts(symtab, f);
250     }
251 }
252
253 } // End namespace gold.