1 /* ldcref.c -- output a cross reference table
2 Copyright 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2006
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., 51 Franklin Street - Fifth Floor, Boston, MA 02110-1301, 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"
38 /* We keep an instance of this structure for each reference to a
39 symbol from a given object. */
42 /* The next reference. */
43 struct cref_ref *next;
46 /* True if the symbol is defined. */
48 /* True if the symbol is common. */
49 unsigned int common : 1;
50 /* True if the symbol is undefined. */
51 unsigned int undef : 1;
54 /* We keep a hash table of symbols. Each entry looks like this. */
56 struct cref_hash_entry {
57 struct bfd_hash_entry root;
58 /* The demangled name. */
60 /* References to and definitions of this symbol. */
61 struct cref_ref *refs;
64 /* This is what the hash table looks like. */
66 struct cref_hash_table {
67 struct bfd_hash_table root;
70 /* Forward declarations. */
72 static void output_one_cref (FILE *, struct cref_hash_entry *);
73 static void check_local_sym_xref (lang_input_statement_type *);
74 static bfd_boolean check_nocrossref (struct cref_hash_entry *, void *);
75 static void check_refs (const char *, bfd_boolean, asection *, bfd *,
76 struct lang_nocrossrefs *);
77 static void check_reloc_refs (bfd *, asection *, void *);
79 /* Look up an entry in the cref hash table. */
81 #define cref_hash_lookup(table, string, create, copy) \
82 ((struct cref_hash_entry *) \
83 bfd_hash_lookup (&(table)->root, (string), (create), (copy)))
85 /* Traverse the cref hash table. */
87 #define cref_hash_traverse(table, func, info) \
90 (bfd_boolean (*) (struct bfd_hash_entry *, void *)) (func), \
93 /* The cref hash table. */
95 static struct cref_hash_table cref_table;
97 /* Whether the cref hash table has been initialized. */
99 static bfd_boolean cref_initialized;
101 /* The number of symbols seen so far. */
103 static size_t cref_symcount;
105 /* Used to take a snapshot of the cref hash table when starting to
106 add syms from an as-needed library. */
107 static struct bfd_hash_entry **old_table;
108 static unsigned int old_size;
109 static void *old_tab;
110 static void *alloc_mark;
111 static size_t tabsize, entsize, refsize;
112 static size_t old_symcount;
114 /* Create an entry in a cref hash table. */
116 static struct bfd_hash_entry *
117 cref_hash_newfunc (struct bfd_hash_entry *entry,
118 struct bfd_hash_table *table,
121 struct cref_hash_entry *ret = (struct cref_hash_entry *) entry;
123 /* Allocate the structure if it has not already been allocated by a
126 ret = ((struct cref_hash_entry *)
127 bfd_hash_allocate (table, sizeof (struct cref_hash_entry)));
131 /* Call the allocation method of the superclass. */
132 ret = ((struct cref_hash_entry *)
133 bfd_hash_newfunc ((struct bfd_hash_entry *) ret, table, string));
136 /* Set local fields. */
137 ret->demangled = NULL;
140 /* Keep a count of the number of entries created in the hash
148 /* Add a symbol to the cref hash table. This is called for every
149 global symbol that is seen during the link. */
152 add_cref (const char *name,
155 bfd_vma value ATTRIBUTE_UNUSED)
157 struct cref_hash_entry *h;
160 if (! cref_initialized)
162 if (!bfd_hash_table_init (&cref_table.root, cref_hash_newfunc,
163 sizeof (struct cref_hash_entry)))
164 einfo (_("%X%P: bfd_hash_table_init of cref table failed: %E\n"));
165 cref_initialized = TRUE;
168 h = cref_hash_lookup (&cref_table, name, TRUE, FALSE);
170 einfo (_("%X%P: cref_hash_lookup failed: %E\n"));
172 for (r = h->refs; r != NULL; r = r->next)
178 r = bfd_hash_allocate (&cref_table.root, sizeof *r);
180 einfo (_("%X%P: cref alloc failed: %E\n"));
189 if (bfd_is_und_section (section))
191 else if (bfd_is_com_section (section))
197 /* Called before loading an as-needed library to take a snapshot of
198 the cref hash table, and after we have loaded or found that the
199 library was not needed. */
202 handle_asneeded_cref (bfd *abfd ATTRIBUTE_UNUSED,
203 enum notice_asneeded_action act)
207 if (!cref_initialized)
210 if (act == notice_as_needed)
212 char *old_ent, *old_ref;
214 for (i = 0; i < cref_table.root.size; i++)
216 struct bfd_hash_entry *p;
217 struct cref_hash_entry *c;
220 for (p = cref_table.root.table[i]; p != NULL; p = p->next)
222 entsize += cref_table.root.entsize;
223 c = (struct cref_hash_entry *) p;
224 for (r = c->refs; r != NULL; r = r->next)
225 refsize += sizeof (struct cref_hash_entry);
229 tabsize = cref_table.root.size * sizeof (struct bfd_hash_entry *);
230 old_tab = xmalloc (tabsize + entsize + refsize);
232 alloc_mark = bfd_hash_allocate (&cref_table.root, 1);
233 if (alloc_mark == NULL)
236 memcpy (old_tab, cref_table.root.table, tabsize);
237 old_ent = (char *) old_tab + tabsize;
238 old_ref = (char *) old_ent + entsize;
239 old_table = cref_table.root.table;
240 old_size = cref_table.root.size;
241 old_symcount = cref_symcount;
243 for (i = 0; i < cref_table.root.size; i++)
245 struct bfd_hash_entry *p;
246 struct cref_hash_entry *c;
249 for (p = cref_table.root.table[i]; p != NULL; p = p->next)
251 memcpy (old_ent, p, cref_table.root.entsize);
252 old_ent = (char *) old_ent + cref_table.root.entsize;
253 c = (struct cref_hash_entry *) p;
254 for (r = c->refs; r != NULL; r = r->next)
256 memcpy (old_ref, r, sizeof (struct cref_hash_entry));
257 old_ref = (char *) old_ref + sizeof (struct cref_hash_entry);
264 if (act == notice_not_needed)
266 char *old_ent, *old_ref;
270 /* The only way old_tab can be NULL is if the cref hash table
271 had not been initialised when notice_as_needed. */
272 bfd_hash_table_free (&cref_table.root);
273 cref_initialized = FALSE;
277 old_ent = (char *) old_tab + tabsize;
278 old_ref = (char *) old_ent + entsize;
279 cref_table.root.table = old_table;
280 cref_table.root.size = old_size;
281 memcpy (cref_table.root.table, old_tab, tabsize);
282 cref_symcount = old_symcount;
284 for (i = 0; i < cref_table.root.size; i++)
286 struct bfd_hash_entry *p;
287 struct cref_hash_entry *c;
290 for (p = cref_table.root.table[i]; p != NULL; p = p->next)
292 memcpy (p, old_ent, cref_table.root.entsize);
293 old_ent = (char *) old_ent + cref_table.root.entsize;
294 c = (struct cref_hash_entry *) p;
295 for (r = c->refs; r != NULL; r = r->next)
297 memcpy (r, old_ref, sizeof (struct cref_hash_entry));
298 old_ref = (char *) old_ref + sizeof (struct cref_hash_entry);
303 objalloc_free_block ((struct objalloc *) cref_table.root.memory,
306 else if (act != notice_needed)
314 /* Copy the addresses of the hash table entries into an array. This
315 is called via cref_hash_traverse. We also fill in the demangled
319 cref_fill_array (struct cref_hash_entry *h, void *data)
321 struct cref_hash_entry ***pph = data;
323 ASSERT (h->demangled == NULL);
324 h->demangled = demangle (h->root.string);
333 /* Sort an array of cref hash table entries by name. */
336 cref_sort_array (const void *a1, const void *a2)
338 const struct cref_hash_entry * const *p1 = a1;
339 const struct cref_hash_entry * const *p2 = a2;
341 return strcmp ((*p1)->demangled, (*p2)->demangled);
344 /* Write out the cref table. */
349 output_cref (FILE *fp)
352 struct cref_hash_entry **csyms, **csym_fill, **csym, **csym_end;
355 fprintf (fp, _("\nCross Reference Table\n\n"));
357 fprintf (fp, "%s", msg);
359 while (len < FILECOL)
364 fprintf (fp, _("File\n"));
366 if (! cref_initialized)
368 fprintf (fp, _("No symbols\n"));
372 csyms = xmalloc (cref_symcount * sizeof (*csyms));
375 cref_hash_traverse (&cref_table, cref_fill_array, &csym_fill);
376 ASSERT ((size_t) (csym_fill - csyms) == cref_symcount);
378 qsort (csyms, cref_symcount, sizeof (*csyms), cref_sort_array);
380 csym_end = csyms + cref_symcount;
381 for (csym = csyms; csym < csym_end; csym++)
382 output_one_cref (fp, *csym);
385 /* Output one entry in the cross reference table. */
388 output_one_cref (FILE *fp, struct cref_hash_entry *h)
391 struct bfd_link_hash_entry *hl;
394 hl = bfd_link_hash_lookup (link_info.hash, h->root.string, FALSE,
397 einfo ("%P: symbol `%T' missing from main hash table\n",
401 /* If this symbol is defined in a dynamic object but never
402 referenced by a normal object, then don't print it. */
403 if (hl->type == bfd_link_hash_defined)
405 if (hl->u.def.section->output_section == NULL)
407 if (hl->u.def.section->owner != NULL
408 && (hl->u.def.section->owner->flags & DYNAMIC) != 0)
410 for (r = h->refs; r != NULL; r = r->next)
411 if ((r->abfd->flags & DYNAMIC) == 0)
419 fprintf (fp, "%s ", h->demangled);
420 len = strlen (h->demangled) + 1;
422 for (r = h->refs; r != NULL; r = r->next)
426 while (len < FILECOL)
431 lfinfo (fp, "%B\n", r->abfd);
436 for (r = h->refs; r != NULL; r = r->next)
440 while (len < FILECOL)
445 lfinfo (fp, "%B\n", r->abfd);
453 /* Check for prohibited cross references. */
456 check_nocrossrefs (void)
458 if (! cref_initialized)
461 cref_hash_traverse (&cref_table, check_nocrossref, NULL);
463 lang_for_each_file (check_local_sym_xref);
466 /* Check for prohibited cross references to local and section symbols. */
469 check_local_sym_xref (lang_input_statement_type *statement)
472 lang_input_statement_type *li;
473 asymbol **asymbols, **syms;
475 abfd = statement->the_bfd;
480 if (li != NULL && li->asymbols != NULL)
481 asymbols = li->asymbols;
487 symsize = bfd_get_symtab_upper_bound (abfd);
489 einfo (_("%B%F: could not read symbols; %E\n"), abfd);
490 asymbols = xmalloc (symsize);
491 symbol_count = bfd_canonicalize_symtab (abfd, asymbols);
492 if (symbol_count < 0)
493 einfo (_("%B%F: could not read symbols: %E\n"), abfd);
496 li->asymbols = asymbols;
497 li->symbol_count = symbol_count;
501 for (syms = asymbols; *syms; ++syms)
503 asymbol *sym = *syms;
504 if (sym->flags & (BSF_GLOBAL | BSF_WARNING | BSF_INDIRECT | BSF_FILE))
506 if ((sym->flags & (BSF_LOCAL | BSF_SECTION_SYM)) != 0
507 && sym->section->output_section != NULL)
509 const char *outsecname, *symname;
510 struct lang_nocrossrefs *ncrs;
511 struct lang_nocrossref *ncr;
513 outsecname = sym->section->output_section->name;
515 if ((sym->flags & BSF_SECTION_SYM) == 0)
517 for (ncrs = nocrossref_list; ncrs != NULL; ncrs = ncrs->next)
518 for (ncr = ncrs->list; ncr != NULL; ncr = ncr->next)
519 if (strcmp (ncr->name, outsecname) == 0)
520 check_refs (symname, FALSE, sym->section, abfd, ncrs);
528 /* Check one symbol to see if it is a prohibited cross reference. */
531 check_nocrossref (struct cref_hash_entry *h, void *ignore ATTRIBUTE_UNUSED)
533 struct bfd_link_hash_entry *hl;
535 const char *defsecname;
536 struct lang_nocrossrefs *ncrs;
537 struct lang_nocrossref *ncr;
538 struct cref_ref *ref;
540 hl = bfd_link_hash_lookup (link_info.hash, h->root.string, FALSE,
544 einfo (_("%P: symbol `%T' missing from main hash table\n"),
549 if (hl->type != bfd_link_hash_defined
550 && hl->type != bfd_link_hash_defweak)
553 defsec = hl->u.def.section->output_section;
556 defsecname = bfd_get_section_name (defsec->owner, defsec);
558 for (ncrs = nocrossref_list; ncrs != NULL; ncrs = ncrs->next)
559 for (ncr = ncrs->list; ncr != NULL; ncr = ncr->next)
560 if (strcmp (ncr->name, defsecname) == 0)
561 for (ref = h->refs; ref != NULL; ref = ref->next)
562 check_refs (hl->root.string, TRUE, hl->u.def.section,
568 /* The struct is used to pass information from check_refs to
569 check_reloc_refs through bfd_map_over_sections. */
571 struct check_refs_info {
572 const char *sym_name;
574 struct lang_nocrossrefs *ncrs;
579 /* This function is called for each symbol defined in a section which
580 prohibits cross references. We need to look through all references
581 to this symbol, and ensure that the references are not from
582 prohibited sections. */
585 check_refs (const char *name,
589 struct lang_nocrossrefs *ncrs)
591 lang_input_statement_type *li;
593 struct check_refs_info info;
595 /* We need to look through the relocations for this BFD, to see
596 if any of the relocations which refer to this symbol are from
597 a prohibited section. Note that we need to do this even for
598 the BFD in which the symbol is defined, since even a single
599 BFD might contain a prohibited cross reference. */
602 if (li != NULL && li->asymbols != NULL)
603 asymbols = li->asymbols;
609 symsize = bfd_get_symtab_upper_bound (abfd);
611 einfo (_("%B%F: could not read symbols; %E\n"), abfd);
612 asymbols = xmalloc (symsize);
613 symbol_count = bfd_canonicalize_symtab (abfd, asymbols);
614 if (symbol_count < 0)
615 einfo (_("%B%F: could not read symbols: %E\n"), abfd);
618 li->asymbols = asymbols;
619 li->symbol_count = symbol_count;
623 info.sym_name = name;
624 info.global = global;
627 info.asymbols = asymbols;
628 bfd_map_over_sections (abfd, check_reloc_refs, &info);
634 /* This is called via bfd_map_over_sections. INFO->SYM_NAME is a symbol
635 defined in INFO->DEFSECNAME. If this section maps into any of the
636 sections listed in INFO->NCRS, other than INFO->DEFSECNAME, then we
637 look through the relocations. If any of the relocations are to
638 INFO->SYM_NAME, then we report a prohibited cross reference error. */
641 check_reloc_refs (bfd *abfd, asection *sec, void *iarg)
643 struct check_refs_info *info = iarg;
645 const char *outsecname;
647 const char *outdefsecname;
648 struct lang_nocrossref *ncr;
656 outsec = sec->output_section;
657 outsecname = bfd_get_section_name (outsec->owner, outsec);
659 outdefsec = info->defsec->output_section;
660 outdefsecname = bfd_get_section_name (outdefsec->owner, outdefsec);
662 /* The section where the symbol is defined is permitted. */
663 if (strcmp (outsecname, outdefsecname) == 0)
666 for (ncr = info->ncrs->list; ncr != NULL; ncr = ncr->next)
667 if (strcmp (outsecname, ncr->name) == 0)
673 /* This section is one for which cross references are prohibited.
674 Look through the relocations, and see if any of them are to
675 INFO->SYM_NAME. If INFO->SYMNAME is NULL, check for relocations
676 against the section symbol. If INFO->GLOBAL is TRUE, the
677 definition is global, check for relocations against the global
678 symbols. Otherwise check for relocations against the local and
681 symname = info->sym_name;
682 global = info->global;
684 relsize = bfd_get_reloc_upper_bound (abfd, sec);
686 einfo (_("%B%F: could not read relocs: %E\n"), abfd);
690 relpp = xmalloc (relsize);
691 relcount = bfd_canonicalize_reloc (abfd, sec, relpp, info->asymbols);
693 einfo (_("%B%F: could not read relocs: %E\n"), abfd);
697 for (; p < pend && *p != NULL; p++)
701 if (q->sym_ptr_ptr != NULL
702 && *q->sym_ptr_ptr != NULL
704 && (bfd_is_und_section (bfd_get_section (*q->sym_ptr_ptr))
705 || bfd_is_com_section (bfd_get_section (*q->sym_ptr_ptr))
706 || ((*q->sym_ptr_ptr)->flags & (BSF_GLOBAL
709 && ((*q->sym_ptr_ptr)->flags & (BSF_LOCAL
710 | BSF_SECTION_SYM)) != 0))
712 ? strcmp (bfd_asymbol_name (*q->sym_ptr_ptr), symname) == 0
713 : (((*q->sym_ptr_ptr)->flags & BSF_SECTION_SYM) != 0
714 && bfd_get_section (*q->sym_ptr_ptr) == info->defsec)))
716 /* We found a reloc for the symbol. The symbol is defined
717 in OUTSECNAME. This reloc is from a section which is
718 mapped into a section from which references to OUTSECNAME
719 are prohibited. We must report an error. */
720 einfo (_("%X%C: prohibited cross reference from %s to `%T' in %s\n"),
721 abfd, sec, q->address, outsecname,
722 bfd_asymbol_name (*q->sym_ptr_ptr), outdefsecname);