1 /* ldcref.c -- output a cross reference table
2 Copyright 1996, 1997, 1998, 2000, 2002, 2003
3 Free Software Foundation, Inc.
4 Written by Ian Lance Taylor <ian@cygnus.com>
6 This file is part of GLD, the Gnu Linker.
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 2 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
22 /* This file holds routines that manage the cross reference table.
23 The table is used to generate cross reference reports. It is also
24 used to implement the NOCROSSREFS command in the linker script. */
29 #include "libiberty.h"
37 /* We keep an instance of this structure for each reference to a
38 symbol from a given object. */
41 /* The next reference. */
42 struct cref_ref *next;
45 /* True if the symbol is defined. */
47 /* True if the symbol is common. */
48 unsigned int common : 1;
49 /* True if the symbol is undefined. */
50 unsigned int undef : 1;
53 /* We keep a hash table of symbols. Each entry looks like this. */
55 struct cref_hash_entry {
56 struct bfd_hash_entry root;
57 /* The demangled name. */
59 /* References to and definitions of this symbol. */
60 struct cref_ref *refs;
63 /* This is what the hash table looks like. */
65 struct cref_hash_table {
66 struct bfd_hash_table root;
69 /* Forward declarations. */
71 static void output_one_cref (FILE *, struct cref_hash_entry *);
72 static void check_section_sym_xref (lang_input_statement_type *);
73 static bfd_boolean check_nocrossref (struct cref_hash_entry *, void *);
74 static void check_refs (const char *, asection *, bfd *,
75 struct lang_nocrossrefs *);
76 static void check_reloc_refs (bfd *, asection *, void *);
78 /* Look up an entry in the cref hash table. */
80 #define cref_hash_lookup(table, string, create, copy) \
81 ((struct cref_hash_entry *) \
82 bfd_hash_lookup (&(table)->root, (string), (create), (copy)))
84 /* Traverse the cref hash table. */
86 #define cref_hash_traverse(table, func, info) \
89 (bfd_boolean (*) (struct bfd_hash_entry *, void *)) (func), \
92 /* The cref hash table. */
94 static struct cref_hash_table cref_table;
96 /* Whether the cref hash table has been initialized. */
98 static bfd_boolean cref_initialized;
100 /* The number of symbols seen so far. */
102 static size_t cref_symcount;
104 /* Create an entry in a cref hash table. */
106 static struct bfd_hash_entry *
107 cref_hash_newfunc (struct bfd_hash_entry *entry,
108 struct bfd_hash_table *table,
111 struct cref_hash_entry *ret = (struct cref_hash_entry *) entry;
113 /* Allocate the structure if it has not already been allocated by a
116 ret = ((struct cref_hash_entry *)
117 bfd_hash_allocate (table, sizeof (struct cref_hash_entry)));
121 /* Call the allocation method of the superclass. */
122 ret = ((struct cref_hash_entry *)
123 bfd_hash_newfunc ((struct bfd_hash_entry *) ret, table, string));
126 /* Set local fields. */
127 ret->demangled = NULL;
130 /* Keep a count of the number of entries created in the hash
138 /* Add a symbol to the cref hash table. This is called for every
139 symbol that is seen during the link. */
142 add_cref (const char *name,
145 bfd_vma value ATTRIBUTE_UNUSED)
147 struct cref_hash_entry *h;
150 if (! cref_initialized)
152 if (! bfd_hash_table_init (&cref_table.root, cref_hash_newfunc))
153 einfo (_("%X%P: bfd_hash_table_init of cref table failed: %E\n"));
154 cref_initialized = TRUE;
157 h = cref_hash_lookup (&cref_table, name, TRUE, FALSE);
159 einfo (_("%X%P: cref_hash_lookup failed: %E\n"));
161 for (r = h->refs; r != NULL; r = r->next)
167 r = xmalloc (sizeof *r);
176 if (bfd_is_und_section (section))
178 else if (bfd_is_com_section (section))
184 /* Copy the addresses of the hash table entries into an array. This
185 is called via cref_hash_traverse. We also fill in the demangled
189 cref_fill_array (struct cref_hash_entry *h, void *data)
191 struct cref_hash_entry ***pph = data;
193 ASSERT (h->demangled == NULL);
194 h->demangled = demangle (h->root.string);
203 /* Sort an array of cref hash table entries by name. */
206 cref_sort_array (const void *a1, const void *a2)
208 const struct cref_hash_entry * const *p1 = a1;
209 const struct cref_hash_entry * const *p2 = a2;
211 return strcmp ((*p1)->demangled, (*p2)->demangled);
214 /* Write out the cref table. */
219 output_cref (FILE *fp)
222 struct cref_hash_entry **csyms, **csym_fill, **csym, **csym_end;
225 fprintf (fp, _("\nCross Reference Table\n\n"));
227 fprintf (fp, "%s", msg);
229 while (len < FILECOL)
234 fprintf (fp, _("File\n"));
236 if (! cref_initialized)
238 fprintf (fp, _("No symbols\n"));
242 csyms = xmalloc (cref_symcount * sizeof (*csyms));
245 cref_hash_traverse (&cref_table, cref_fill_array, &csym_fill);
246 ASSERT ((size_t) (csym_fill - csyms) == cref_symcount);
248 qsort (csyms, cref_symcount, sizeof (*csyms), cref_sort_array);
250 csym_end = csyms + cref_symcount;
251 for (csym = csyms; csym < csym_end; csym++)
252 output_one_cref (fp, *csym);
255 /* Output one entry in the cross reference table. */
258 output_one_cref (FILE *fp, struct cref_hash_entry *h)
261 struct bfd_link_hash_entry *hl;
264 hl = bfd_link_hash_lookup (link_info.hash, h->root.string, FALSE,
267 einfo ("%P: symbol `%T' missing from main hash table\n",
271 /* If this symbol is defined in a dynamic object but never
272 referenced by a normal object, then don't print it. */
273 if (hl->type == bfd_link_hash_defined)
275 if (hl->u.def.section->output_section == NULL)
277 if (hl->u.def.section->owner != NULL
278 && (hl->u.def.section->owner->flags & DYNAMIC) != 0)
280 for (r = h->refs; r != NULL; r = r->next)
281 if ((r->abfd->flags & DYNAMIC) == 0)
289 fprintf (fp, "%s ", h->demangled);
290 len = strlen (h->demangled) + 1;
292 for (r = h->refs; r != NULL; r = r->next)
296 while (len < FILECOL)
301 lfinfo (fp, "%B\n", r->abfd);
306 for (r = h->refs; r != NULL; r = r->next)
310 while (len < FILECOL)
315 lfinfo (fp, "%B\n", r->abfd);
323 /* Check for prohibited cross references. */
326 check_nocrossrefs (void)
328 if (! cref_initialized)
331 cref_hash_traverse (&cref_table, check_nocrossref, NULL);
333 lang_for_each_file (check_section_sym_xref);
336 /* Checks for prohibited cross references to section symbols. */
339 check_section_sym_xref (lang_input_statement_type *statement)
344 abfd = statement->the_bfd;
348 for (sec = abfd->sections; sec != NULL; sec = sec->next)
352 outsec = sec->output_section;
355 const char *outsecname;
356 struct lang_nocrossrefs *ncrs;
357 struct lang_nocrossref *ncr;
359 outsecname = outsec->name;
360 for (ncrs = nocrossref_list; ncrs != NULL; ncrs = ncrs->next)
361 for (ncr = ncrs->list; ncr != NULL; ncr = ncr->next)
362 if (strcmp (ncr->name, outsecname) == 0)
363 check_refs (NULL, sec, abfd, ncrs);
368 /* Check one symbol to see if it is a prohibited cross reference. */
371 check_nocrossref (struct cref_hash_entry *h, void *ignore ATTRIBUTE_UNUSED)
373 struct bfd_link_hash_entry *hl;
375 const char *defsecname;
376 struct lang_nocrossrefs *ncrs;
377 struct lang_nocrossref *ncr;
378 struct cref_ref *ref;
380 hl = bfd_link_hash_lookup (link_info.hash, h->root.string, FALSE,
384 einfo (_("%P: symbol `%T' missing from main hash table\n"),
389 if (hl->type != bfd_link_hash_defined
390 && hl->type != bfd_link_hash_defweak)
393 defsec = hl->u.def.section->output_section;
396 defsecname = bfd_get_section_name (defsec->owner, defsec);
398 for (ncrs = nocrossref_list; ncrs != NULL; ncrs = ncrs->next)
399 for (ncr = ncrs->list; ncr != NULL; ncr = ncr->next)
400 if (strcmp (ncr->name, defsecname) == 0)
401 for (ref = h->refs; ref != NULL; ref = ref->next)
402 check_refs (hl->root.string, hl->u.def.section, ref->abfd, ncrs);
407 /* The struct is used to pass information from check_refs to
408 check_reloc_refs through bfd_map_over_sections. */
410 struct check_refs_info {
411 const char *sym_name;
413 struct lang_nocrossrefs *ncrs;
417 /* This function is called for each symbol defined in a section which
418 prohibits cross references. We need to look through all references
419 to this symbol, and ensure that the references are not from
420 prohibited sections. */
423 check_refs (const char *name,
426 struct lang_nocrossrefs *ncrs)
428 lang_input_statement_type *li;
430 struct check_refs_info info;
432 /* We need to look through the relocations for this BFD, to see
433 if any of the relocations which refer to this symbol are from
434 a prohibited section. Note that we need to do this even for
435 the BFD in which the symbol is defined, since even a single
436 BFD might contain a prohibited cross reference. */
439 if (li != NULL && li->asymbols != NULL)
440 asymbols = li->asymbols;
446 symsize = bfd_get_symtab_upper_bound (abfd);
448 einfo (_("%B%F: could not read symbols; %E\n"), abfd);
449 asymbols = xmalloc (symsize);
450 symbol_count = bfd_canonicalize_symtab (abfd, asymbols);
451 if (symbol_count < 0)
452 einfo (_("%B%F: could not read symbols: %E\n"), abfd);
455 li->asymbols = asymbols;
456 li->symbol_count = symbol_count;
460 info.sym_name = name;
463 info.asymbols = asymbols;
464 bfd_map_over_sections (abfd, check_reloc_refs, &info);
470 /* This is called via bfd_map_over_sections. INFO->SYM_NAME is a symbol
471 defined in INFO->DEFSECNAME. If this section maps into any of the
472 sections listed in INFO->NCRS, other than INFO->DEFSECNAME, then we
473 look through the relocations. If any of the relocations are to
474 INFO->SYM_NAME, then we report a prohibited cross reference error. */
477 check_reloc_refs (bfd *abfd, asection *sec, void *iarg)
479 struct check_refs_info *info = iarg;
481 const char *outsecname;
483 const char *outdefsecname;
484 struct lang_nocrossref *ncr;
491 outsec = sec->output_section;
492 outsecname = bfd_get_section_name (outsec->owner, outsec);
494 outdefsec = info->defsec->output_section;
495 outdefsecname = bfd_get_section_name (outdefsec->owner, outdefsec);
497 /* The section where the symbol is defined is permitted. */
498 if (strcmp (outsecname, outdefsecname) == 0)
501 for (ncr = info->ncrs->list; ncr != NULL; ncr = ncr->next)
502 if (strcmp (outsecname, ncr->name) == 0)
508 /* This section is one for which cross references are prohibited.
509 Look through the relocations, and see if any of them are to
510 INFO->SYM_NAME. If INFO->SYMNAME is NULL, check for relocations
511 against the section symbol. */
513 symname = info->sym_name;
515 relsize = bfd_get_reloc_upper_bound (abfd, sec);
517 einfo (_("%B%F: could not read relocs: %E\n"), abfd);
521 relpp = xmalloc (relsize);
522 relcount = bfd_canonicalize_reloc (abfd, sec, relpp, info->asymbols);
524 einfo (_("%B%F: could not read relocs: %E\n"), abfd);
528 for (; p < pend && *p != NULL; p++)
532 if (q->sym_ptr_ptr != NULL
533 && *q->sym_ptr_ptr != NULL
535 ? strcmp (bfd_asymbol_name (*q->sym_ptr_ptr), symname) == 0
536 : (((*q->sym_ptr_ptr)->flags & BSF_SECTION_SYM) != 0
537 && bfd_get_section (*q->sym_ptr_ptr) == info->defsec)))
539 /* We found a reloc for the symbol. The symbol is defined
540 in OUTSECNAME. This reloc is from a section which is
541 mapped into a section from which references to OUTSECNAME
542 are prohibited. We must report an error. */
543 einfo (_("%X%C: prohibited cross reference from %s to `%T' in %s\n"),
544 abfd, sec, q->address, outsecname,
545 bfd_asymbol_name (*q->sym_ptr_ptr), outdefsecname);