1 // cref.cc -- cross reference for gold
3 // Copyright (C) 2008-2024 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.
40 // Class Cref_inputs. This is used to hold the list of input files
41 // for cross referencing.
47 : objects_(), archives_(), current_(&this->objects_
)
50 // Add an input object file.
52 add_object(Object
* object
);
54 // Start adding an archive. We support nested archives for future
57 add_archive_start(Archive
*);
59 // Finish adding an archive.
61 add_archive_stop(Archive
*);
63 // Report symbol counts.
65 print_symbol_counts(const Symbol_table
*, FILE*) const;
67 // Print a cross reference table.
69 print_cref(const Symbol_table
*, FILE*) const;
72 // A list of input objects.
73 typedef std::vector
<Object
*> Objects
;
75 // Information we record for an archive.
80 // List of objects included from the archive.
82 // Number of archive members.
86 // A mapping from the name of an archive to the list of objects in
88 typedef std::map
<std::string
, Archive_info
> Archives
;
90 // For --cref, we build a cross reference table which maps from
91 // symbols to lists of objects. The symbols are sorted
94 class Cref_table_compare
98 operator()(const Symbol
*, const Symbol
*) const;
101 typedef std::map
<const Symbol
*, Objects
*, Cref_table_compare
> Cref_table
;
103 // Report symbol counts for a list of Objects.
105 print_objects_symbol_counts(const Symbol_table
*, FILE*, const Objects
*) const;
107 // Report symbol counts for an object.
109 print_object_symbol_counts(const Symbol_table
*, FILE*, const Object
*) const;
111 // Gather cross reference information.
113 gather_cref(const Objects
*, Cref_table
*) const;
115 // List of input objects.
117 // List of input archives. This is a mapping from the archive file
118 // name to the list of objects.
120 // The list to which we are currently adding objects.
127 Cref_inputs::add_object(Object
* object
)
129 this->current_
->push_back(object
);
132 // Start adding an archive.
135 Cref_inputs::add_archive_start(Archive
* archive
)
137 gold_assert(this->current_
== &this->objects_
);
138 if (this->archives_
.find(archive
->name()) == this->archives_
.end())
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();
145 this->current_
= this->archives_
[archive
->name()].objects
;
148 // Stop adding an archive.
151 Cref_inputs::add_archive_stop(Archive
*)
153 gold_assert(this->current_
!= &this->objects_
);
154 this->current_
= &this->objects_
;
157 // Report symbol counts for an object.
160 Cref_inputs::print_object_symbol_counts(const Symbol_table
* symtab
,
162 const Object
* object
) const
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
);
169 // Report symbol counts for a list of inputs.
172 Cref_inputs::print_objects_symbol_counts(const Symbol_table
* symtab
,
174 const Objects
* objects
) const
176 for (Objects::const_iterator p
= objects
->begin();
179 this->print_object_symbol_counts(symtab
, f
, *p
);
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.
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.
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.
201 Cref_inputs::print_symbol_counts(const Symbol_table
* symtab
, FILE* f
) const
203 this->print_objects_symbol_counts(symtab
, f
, &this->objects_
);
204 for (Archives::const_iterator p
= this->archives_
.begin();
205 p
!= this->archives_
.end();
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
);
214 // Sort symbols for the cross reference table.
217 Cref_inputs::Cref_table_compare::operator()(const Symbol
* s1
,
218 const Symbol
* s2
) const
220 int i
= strcmp(s1
->name(), s2
->name());
224 if (s1
->version() == NULL
)
226 if (s2
->version() != NULL
)
229 else if (s2
->version() == NULL
)
233 i
= strcmp(s1
->version(), s2
->version());
238 // We should never have two different symbols with the same name and
239 // version, where one doesn't forward to the other.
242 if (s1
->is_forwarder() && !s2
->is_forwarder())
244 if (!s1
->is_forwarder() && s2
->is_forwarder())
249 // Gather cross reference information from a list of inputs.
252 Cref_inputs::gather_cref(const Objects
* objects
, Cref_table
* table
) const
254 for (Objects::const_iterator po
= objects
->begin();
255 po
!= objects
->end();
258 const Object::Symbols
* symbols
= (*po
)->get_global_symbols();
261 for (Object::Symbols::const_iterator ps
= symbols
->begin();
262 ps
!= symbols
->end();
265 const Symbol
* sym
= *ps
;
268 Objects
* const onull
= NULL
;
269 std::pair
<Cref_table::iterator
, bool> ins
=
270 table
->insert(std::make_pair(sym
, onull
));
271 Cref_table::iterator pc
= ins
.first
;
273 pc
->second
= new Objects();
274 if (sym
->source() == Symbol::FROM_OBJECT
275 && sym
->object() == *po
276 && sym
->is_defined())
277 pc
->second
->insert(pc
->second
->begin(), *po
);
279 pc
->second
->push_back(*po
);
284 // The column where the file name starts in a cross reference table.
286 static const size_t filecol
= 50;
288 // Print a cross reference table.
291 Cref_inputs::print_cref(const Symbol_table
*, FILE* f
) const
294 this->gather_cref(&this->objects_
, &table
);
295 for (Archives::const_iterator p
= this->archives_
.begin();
296 p
!= this->archives_
.end();
298 this->gather_cref(p
->second
.objects
, &table
);
300 for (Cref_table::const_iterator pc
= table
.begin();
304 // If all the objects are dynamic, skip this symbol.
305 const Symbol
* sym
= pc
->first
;
306 const Objects
* objects
= pc
->second
;
307 Objects::const_iterator po
;
308 for (po
= objects
->begin(); po
!= objects
->end(); ++po
)
309 if (!(*po
)->is_dynamic())
311 if (po
== objects
->end())
314 std::string s
= sym
->demangled_name();
315 if (sym
->version() != NULL
)
318 if (sym
->is_default())
325 size_t len
= s
.length();
327 for (po
= objects
->begin(); po
!= objects
->end(); ++po
)
329 int n
= len
< filecol
? filecol
- len
: 1;
330 fprintf(f
, "%*c%s\n", n
, ' ', (*po
)->name().c_str());
338 // Make sure the Cref_inputs object has been created.
343 if (this->inputs_
== NULL
)
344 this->inputs_
= new Cref_inputs();
347 // Add an input object file.
350 Cref::add_object(Object
* object
)
353 this->inputs_
->add_object(object
);
356 // Start adding an archive.
359 Cref::add_archive_start(Archive
* archive
)
362 this->inputs_
->add_archive_start(archive
);
365 // Stop adding an archive.
368 Cref::add_archive_stop(Archive
* archive
)
370 this->inputs_
->add_archive_stop(archive
);
373 // Print symbol counts.
376 Cref::print_symbol_counts(const Symbol_table
* symtab
) const
378 if (parameters
->options().user_set_print_symbol_counts()
379 && this->inputs_
!= NULL
)
382 if (strcmp(parameters
->options().print_symbol_counts(), "-") == 0)
386 f
= fopen(parameters
->options().print_symbol_counts(), "w");
388 gold_error(_("cannot open symbol count file %s: %s"),
389 parameters
->options().print_symbol_counts(),
393 this->inputs_
->print_symbol_counts(symtab
, f
);
397 // Print a cross reference table.
400 Cref::print_cref(const Symbol_table
* symtab
, FILE* f
) const
402 fprintf(f
, _("\nCross Reference Table\n\n"));
403 const char* msg
= _("Symbol");
404 int len
= filecol
- strlen(msg
);
405 fprintf(f
, "%s%*c%s\n", msg
, len
, ' ', _("File"));
407 if (parameters
->options().cref() && this->inputs_
!= NULL
)
408 this->inputs_
->print_cref(symtab
, f
);
411 } // End namespace gold.