OpenCores
URL https://opencores.org/ocsvn/open8_urisc/open8_urisc/trunk

Subversion Repositories open8_urisc

[/] [open8_urisc/] [trunk/] [gnu/] [binutils/] [gold/] [cref.cc] - Blame information for rev 158

Go to most recent revision | Details | Compare with Previous | View Log

Line No. Rev Author Line
1 27 khays
// cref.cc -- cross reference for gold
2
 
3
// Copyright 2008, 2010 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 "symtab.h"
35
#include "cref.h"
36
 
37
namespace gold
38
{
39
 
40
// Class Cref_inputs.  This is used to hold the list of input files
41
// for cross referencing.
42
 
43
class Cref_inputs
44
{
45
 public:
46
  Cref_inputs()
47
    : objects_(), archives_(), current_(&this->objects_)
48
  { }
49
 
50
  // Add an input object file.
51
  void
52
  add_object(Object* object);
53
 
54
  // Start adding an archive.  We support nested archives for future
55
  // flexibility.
56
  void
57
  add_archive_start(Archive*);
58
 
59
  // Finish adding an archive.
60
  void
61
  add_archive_stop(Archive*);
62
 
63
  // Report symbol counts.
64
  void
65
  print_symbol_counts(const Symbol_table*, FILE*) const;
66
 
67
  // Print a cross reference table.
68
  void
69
  print_cref(const Symbol_table*, FILE*) const;
70
 
71
 private:
72
  // A list of input objects.
73
  typedef std::vector<Object*> Objects;
74
 
75
  // Information we record for an archive.
76
  struct Archive_info
77
  {
78
    // Archive name.
79
    std::string name;
80
    // List of objects included from the archive.
81
    Objects* objects;
82
    // Number of archive members.
83
    size_t member_count;
84
  };
85
 
86
  // A mapping from the name of an archive to the list of objects in
87
  // that archive.
88
  typedef std::map<std::string, Archive_info> Archives;
89
 
90
  // For --cref, we build a cross reference table which maps from
91
  // symbols to lists of objects.  The symbols are sorted
92
  // alphabetically.
93
 
94
  class Cref_table_compare
95
  {
96
  public:
97
    bool
98
    operator()(const Symbol*, const Symbol*) const;
99
  };
100
 
101
  typedef std::map<const Symbol*, Objects*, Cref_table_compare> Cref_table;
102
 
103
  // Report symbol counts for a list of Objects.
104
  void
105
  print_objects_symbol_counts(const Symbol_table*, FILE*, const Objects*) const;
106
 
107
  // Report symbol counts for an object.
108
  void
109
  print_object_symbol_counts(const Symbol_table*, FILE*, const Object*) const;
110
 
111
  // Gather cross reference information.
112
  void
113
  gather_cref(const Objects*, Cref_table*) const;
114
 
115
  // List of input objects.
116
  Objects objects_;
117
  // List of input archives.  This is a mapping from the archive file
118
  // name to the list of objects.
119
  Archives archives_;
120
  // The list to which we are currently adding objects.
121
  Objects* current_;
122
};
123
 
124
// Add an object.
125
 
126
void
127
Cref_inputs::add_object(Object* object)
128
{
129
  this->current_->push_back(object);
130
}
131
 
132
// Start adding an archive.
133
 
134
void
135
Cref_inputs::add_archive_start(Archive* archive)
136
{
137
  gold_assert(this->current_ == &this->objects_);
138
  if (this->archives_.find(archive->name()) == this->archives_.end())
139
    {
140
      Archive_info* pai = &this->archives_[archive->name()];
141
      pai->name = archive->filename();
142
      pai->objects = new Objects();
143
      pai->member_count = archive->count_members();
144
    }
145
  this->current_ = this->archives_[archive->name()].objects;
146
}
147
 
148
// Stop adding an archive.
149
 
150
void
151
Cref_inputs::add_archive_stop(Archive*)
152
{
153
  gold_assert(this->current_ != &this->objects_);
154
  this->current_ = &this->objects_;
155
}
156
 
157
// Report symbol counts for an object.
158
 
159
void
160
Cref_inputs::print_object_symbol_counts(const Symbol_table* symtab,
161
                                        FILE* f,
162
                                        const Object* object) const
163
{
164
  size_t defined, used;
165
  object->get_global_symbol_counts(symtab, &defined, &used);
166
  fprintf(f, "symbols %s %zu %zu\n", object->name().c_str(), defined, used);
167
}
168
 
169
// Report symbol counts for a list of inputs.
170
 
171
void
172
Cref_inputs::print_objects_symbol_counts(const Symbol_table* symtab,
173
                                         FILE* f,
174
                                         const Objects* objects) const
175
{
176
  for (Objects::const_iterator p = objects->begin();
177
       p != objects->end();
178
       ++p)
179
    this->print_object_symbol_counts(symtab, f, *p);
180
}
181
 
182
// Print symbol counts.  This implements --print-symbol-counts.  This
183
// is intended to be easily read by a program.  This outputs a series
184
// of lines.  There are two different types of lines.
185
 
186
// The first is "symbols FILENAME DEFINED USED".  FILENAME is the name
187
// of an object file included in the link; for an archive, this will
188
// be ARCHIVEFILENAME(MEMBERNAME).  DEFINED is the number of symbols
189
// which the object file defines.  USED is the number of symbols which
190
// are used in the final output; this is the number of symbols which
191
// appear in the final output table as having been defined by this
192
// object.  These numbers will be different when weak symbols are
193
// used, and they will be different for dynamic objects.
194
 
195
// The second is "archives FILENAME MEMBERS USED".  FILENAME is the
196
// name of an archive file included in the link.  MEMBERS is the
197
// number of members of the archive.  USED is the number of archive
198
// members included in the link.
199
 
200
void
201
Cref_inputs::print_symbol_counts(const Symbol_table* symtab, FILE* f) const
202
{
203
  this->print_objects_symbol_counts(symtab, f, &this->objects_);
204
  for (Archives::const_iterator p = this->archives_.begin();
205
       p != this->archives_.end();
206
       ++p)
207
    {
208
      fprintf(f, "archive %s %zu %zu\n", p->second.name.c_str(),
209
             p->second.member_count, p->second.objects->size());
210
      this->print_objects_symbol_counts(symtab, f, p->second.objects);
211
    }
212
}
213
 
214
// Sort symbols for the cross reference table.
215
 
216
bool
217
Cref_inputs::Cref_table_compare::operator()(const Symbol* s1,
218
                                            const Symbol* s2) const
219
{
220
  int i = strcmp(s1->name(), s2->name());
221
  if (i != 0)
222
    return i < 0;
223
 
224
  if (s1->version() == NULL)
225
    {
226
      if (s2->version() != NULL)
227
        return true;
228
    }
229
  else if (s2->version() == NULL)
230
    return false;
231
  else
232
    {
233
      i = strcmp(s1->version(), s2->version());
234
      if (i != 0)
235
        return i < 0;
236
    }
237
 
238
  // We should never have two different symbols with the same name and
239
  // version.
240
  if (s1 == s2)
241
    return false;
242
  gold_unreachable();
243
}
244
 
245
// Gather cross reference information from a list of inputs.
246
 
247
void
248
Cref_inputs::gather_cref(const Objects* objects, Cref_table* table) const
249
{
250
  for (Objects::const_iterator po = objects->begin();
251
       po != objects->end();
252
       ++po)
253
    {
254
      const Object::Symbols* symbols = (*po)->get_global_symbols();
255
      if (symbols == NULL)
256
        continue;
257
      for (Object::Symbols::const_iterator ps = symbols->begin();
258
           ps != symbols->end();
259
           ++ps)
260
        {
261
          const Symbol* sym = *ps;
262
          if (sym == NULL)
263
            continue;
264
          Objects* const onull = NULL;
265
          std::pair<Cref_table::iterator, bool> ins =
266
            table->insert(std::make_pair(sym, onull));
267
          Cref_table::iterator pc = ins.first;
268
          if (ins.second)
269
            pc->second = new Objects();
270
          if (sym->source() == Symbol::FROM_OBJECT
271
              && sym->object() == *po
272
              && sym->is_defined())
273
            pc->second->insert(pc->second->begin(), *po);
274
          else
275
            pc->second->push_back(*po);
276
        }
277
    }
278
}
279
 
280
// The column where the file name starts in a cross reference table.
281
 
282
static const size_t filecol = 50;
283
 
284
// Print a cross reference table.
285
 
286
void
287
Cref_inputs::print_cref(const Symbol_table*, FILE* f) const
288
{
289
  Cref_table table;
290
  this->gather_cref(&this->objects_, &table);
291
  for (Archives::const_iterator p = this->archives_.begin();
292
       p != this->archives_.end();
293
       ++p)
294
    this->gather_cref(p->second.objects, &table);
295
 
296
  for (Cref_table::const_iterator pc = table.begin();
297
       pc != table.end();
298
       ++pc)
299
    {
300
      // If all the objects are dynamic, skip this symbol.
301
      const Symbol* sym = pc->first;
302
      const Objects* objects = pc->second;
303
      Objects::const_iterator po;
304
      for (po = objects->begin(); po != objects->end(); ++po)
305
        if (!(*po)->is_dynamic())
306
          break;
307
      if (po == objects->end())
308
        continue;
309
 
310
      std::string s = sym->demangled_name();
311
      if (sym->version() != NULL)
312
        {
313
          s += '@';
314
          if (sym->is_default())
315
            s += '@';
316
          s += sym->version();
317
        }
318
 
319
      fputs(s.c_str(), f);
320
 
321
      size_t len = s.length();
322
 
323
      for (po = objects->begin(); po != objects->end(); ++po)
324
        {
325
          int n = len < filecol ? filecol - len : 1;
326
          fprintf(f, "%*c%s\n", n, ' ', (*po)->name().c_str());
327
          len = 0;
328
        }
329
    }
330
}
331
 
332
// Class Cref.
333
 
334
// Make sure the Cref_inputs object has been created.
335
 
336
void
337
Cref::need_inputs()
338
{
339
  if (this->inputs_ == NULL)
340
    this->inputs_ = new Cref_inputs();
341
}
342
 
343
// Add an input object file.
344
 
345
void
346
Cref::add_object(Object* object)
347
{
348
  this->need_inputs();
349
  this->inputs_->add_object(object);
350
}
351
 
352
// Start adding an archive.
353
 
354
void
355
Cref::add_archive_start(Archive* archive)
356
{
357
  this->need_inputs();
358
  this->inputs_->add_archive_start(archive);
359
}
360
 
361
// Stop adding an archive.
362
 
363
void
364
Cref::add_archive_stop(Archive* archive)
365
{
366
  this->inputs_->add_archive_stop(archive);
367
}
368
 
369
// Print symbol counts.
370
 
371
void
372
Cref::print_symbol_counts(const Symbol_table* symtab) const
373
{
374
  if (parameters->options().user_set_print_symbol_counts()
375
      && this->inputs_ != NULL)
376
    {
377
      FILE* f;
378
      if (strcmp(parameters->options().print_symbol_counts(), "-") == 0)
379
        f = stdout;
380
      else
381
        {
382
          f = fopen(parameters->options().print_symbol_counts(), "w");
383
          if (f == NULL)
384
            gold_error(_("cannot open symbol count file %s: %s"),
385
                       parameters->options().print_symbol_counts(),
386
                       strerror(errno));
387
        }
388
      if (f != NULL)
389
        this->inputs_->print_symbol_counts(symtab, f);
390
    }
391
}
392
 
393
// Print a cross reference table.
394
 
395
void
396
Cref::print_cref(const Symbol_table* symtab, FILE* f) const
397
{
398
  fprintf(f, _("\nCross Reference Table\n\n"));
399
  const char* msg = _("Symbol");
400
  int len = filecol - strlen(msg);
401
  fprintf(f, "%s%*c%s\n", msg, len, ' ', _("File"));
402
 
403
  if (parameters->options().cref() && this->inputs_ != NULL)
404
    this->inputs_->print_cref(symtab, f);
405
}
406
 
407
} // End namespace gold.

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.