1 /* ldcref.c -- output a cross reference table
2 Copyright 1996, 1997, 1998, 2000 Free Software Foundation, Inc.
3 Written by Ian Lance Taylor <ian@cygnus.com>
5 This file is part of GLD, the Gnu Linker.
7 This program is free software; you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
9 the Free Software Foundation; either version 2 of the License, or
10 (at your option) any later version.
12 This program is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 GNU General Public License for more details.
17 You should have received a copy of the GNU General Public License
18 along with this program; if not, write to the Free Software
19 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
21 /* This file holds routines that manage the cross reference table.
22 The table is used to generate cross reference reports. It is also
23 used to implement the NOCROSSREFS command in the linker script. */
28 #include "libiberty.h"
36 /* We keep an instance of this structure for each reference to a
37 symbol from a given object. */
40 /* The next reference. */
41 struct cref_ref
*next
;
44 /* True if the symbol is defined. */
46 /* True if the symbol is common. */
47 unsigned int common
: 1;
48 /* True if the symbol is undefined. */
49 unsigned int undef
: 1;
52 /* We keep a hash table of symbols. Each entry looks like this. */
54 struct cref_hash_entry
{
55 struct bfd_hash_entry root
;
56 /* The demangled name. */
58 /* References to and definitions of this symbol. */
59 struct cref_ref
*refs
;
62 /* This is what the hash table looks like. */
64 struct cref_hash_table
{
65 struct bfd_hash_table root
;
68 /* Local functions. */
70 static struct bfd_hash_entry
*cref_hash_newfunc
71 PARAMS ((struct bfd_hash_entry
*, struct bfd_hash_table
*, const char *));
72 static boolean cref_fill_array
PARAMS ((struct cref_hash_entry
*, PTR
));
73 static int cref_sort_array
PARAMS ((const PTR
, const PTR
));
74 static void output_one_cref
PARAMS ((FILE *, struct cref_hash_entry
*));
75 static boolean check_nocrossref
PARAMS ((struct cref_hash_entry
*, PTR
));
76 static void check_refs
77 PARAMS ((struct cref_hash_entry
*, struct bfd_link_hash_entry
*,
78 struct lang_nocrossrefs
*));
79 static void check_reloc_refs
PARAMS ((bfd
*, asection
*, PTR
));
81 /* Look up an entry in the cref hash table. */
83 #define cref_hash_lookup(table, string, create, copy) \
84 ((struct cref_hash_entry *) \
85 bfd_hash_lookup (&(table)->root, (string), (create), (copy)))
87 /* Traverse the cref hash table. */
89 #define cref_hash_traverse(table, func, info) \
92 (boolean (*) PARAMS ((struct bfd_hash_entry *, PTR))) (func), \
95 /* The cref hash table. */
97 static struct cref_hash_table cref_table
;
99 /* Whether the cref hash table has been initialized. */
101 static boolean cref_initialized
;
103 /* The number of symbols seen so far. */
105 static size_t cref_symcount
;
107 /* Create an entry in a cref hash table. */
109 static struct bfd_hash_entry
*
110 cref_hash_newfunc (entry
, table
, string
)
111 struct bfd_hash_entry
*entry
;
112 struct bfd_hash_table
*table
;
115 struct cref_hash_entry
*ret
= (struct cref_hash_entry
*) entry
;
117 /* Allocate the structure if it has not already been allocated by a
120 ret
= ((struct cref_hash_entry
*)
121 bfd_hash_allocate (table
, sizeof (struct cref_hash_entry
)));
123 return (struct bfd_hash_entry
*) ret
;
125 /* Call the allocation method of the superclass. */
126 ret
= ((struct cref_hash_entry
*)
127 bfd_hash_newfunc ((struct bfd_hash_entry
*) ret
, table
, string
));
130 /* Set local fields. */
131 ret
->demangled
= NULL
;
134 /* Keep a count of the number of entries created in the hash
139 return (struct bfd_hash_entry
*) ret
;
142 /* Add a symbol to the cref hash table. This is called for every
143 symbol that is seen during the link. */
146 add_cref (name
, abfd
, section
, value
)
150 bfd_vma value ATTRIBUTE_UNUSED
;
152 struct cref_hash_entry
*h
;
155 if (! cref_initialized
)
157 if (! bfd_hash_table_init (&cref_table
.root
, cref_hash_newfunc
))
158 einfo (_("%X%P: bfd_hash_table_init of cref table failed: %E\n"));
159 cref_initialized
= true;
162 h
= cref_hash_lookup (&cref_table
, name
, true, false);
164 einfo (_("%X%P: cref_hash_lookup failed: %E\n"));
166 for (r
= h
->refs
; r
!= NULL
; r
= r
->next
)
172 r
= (struct cref_ref
*) xmalloc (sizeof *r
);
181 if (bfd_is_und_section (section
))
183 else if (bfd_is_com_section (section
))
189 /* Copy the addresses of the hash table entries into an array. This
190 is called via cref_hash_traverse. We also fill in the demangled
194 cref_fill_array (h
, data
)
195 struct cref_hash_entry
*h
;
198 struct cref_hash_entry
***pph
= (struct cref_hash_entry
***) data
;
200 ASSERT (h
->demangled
== NULL
);
201 h
->demangled
= demangle (h
->root
.string
);
210 /* Sort an array of cref hash table entries by name. */
213 cref_sort_array (a1
, a2
)
217 const struct cref_hash_entry
**p1
= (const struct cref_hash_entry
**) a1
;
218 const struct cref_hash_entry
**p2
= (const struct cref_hash_entry
**) a2
;
220 return strcmp ((*p1
)->demangled
, (*p2
)->demangled
);
223 /* Write out the cref table. */
232 struct cref_hash_entry
**csyms
, **csym_fill
, **csym
, **csym_end
;
235 fprintf (fp
, _("\nCross Reference Table\n\n"));
237 fprintf (fp
, "%s", msg
);
239 while (len
< FILECOL
)
244 fprintf (fp
, _("File\n"));
246 if (! cref_initialized
)
248 fprintf (fp
, _("No symbols\n"));
252 csyms
= ((struct cref_hash_entry
**)
253 xmalloc (cref_symcount
* sizeof (*csyms
)));
256 cref_hash_traverse (&cref_table
, cref_fill_array
, &csym_fill
);
257 ASSERT ((size_t) (csym_fill
- csyms
) == cref_symcount
);
259 qsort (csyms
, cref_symcount
, sizeof (*csyms
), cref_sort_array
);
261 csym_end
= csyms
+ cref_symcount
;
262 for (csym
= csyms
; csym
< csym_end
; csym
++)
263 output_one_cref (fp
, *csym
);
266 /* Output one entry in the cross reference table. */
269 output_one_cref (fp
, h
)
271 struct cref_hash_entry
*h
;
274 struct bfd_link_hash_entry
*hl
;
277 hl
= bfd_link_hash_lookup (link_info
.hash
, h
->root
.string
, false,
280 einfo ("%P: symbol `%T' missing from main hash table\n",
284 /* If this symbol is defined in a dynamic object but never
285 referenced by a normal object, then don't print it. */
286 if (hl
->type
== bfd_link_hash_defined
)
288 if (hl
->u
.def
.section
->output_section
== NULL
)
290 if (hl
->u
.def
.section
->owner
!= NULL
291 && (hl
->u
.def
.section
->owner
->flags
& DYNAMIC
) != 0)
293 for (r
= h
->refs
; r
!= NULL
; r
= r
->next
)
294 if ((r
->abfd
->flags
& DYNAMIC
) == 0)
302 fprintf (fp
, "%s ", h
->demangled
);
303 len
= strlen (h
->demangled
) + 1;
305 for (r
= h
->refs
; r
!= NULL
; r
= r
->next
)
309 while (len
< FILECOL
)
314 lfinfo (fp
, "%B\n", r
->abfd
);
319 for (r
= h
->refs
; r
!= NULL
; r
= r
->next
)
323 while (len
< FILECOL
)
328 lfinfo (fp
, "%B\n", r
->abfd
);
336 /* Check for prohibited cross references. */
341 if (! cref_initialized
)
344 cref_hash_traverse (&cref_table
, check_nocrossref
, (PTR
) NULL
);
347 /* Check one symbol to see if it is a prohibited cross reference. */
350 check_nocrossref (h
, ignore
)
351 struct cref_hash_entry
*h
;
352 PTR ignore ATTRIBUTE_UNUSED
;
354 struct bfd_link_hash_entry
*hl
;
356 const char *defsecname
;
357 struct lang_nocrossrefs
*ncrs
;
358 struct lang_nocrossref
*ncr
;
360 hl
= bfd_link_hash_lookup (link_info
.hash
, h
->root
.string
, false,
364 einfo (_("%P: symbol `%T' missing from main hash table\n"),
369 if (hl
->type
!= bfd_link_hash_defined
370 && hl
->type
!= bfd_link_hash_defweak
)
373 defsec
= hl
->u
.def
.section
->output_section
;
376 defsecname
= bfd_get_section_name (defsec
->owner
, defsec
);
378 for (ncrs
= nocrossref_list
; ncrs
!= NULL
; ncrs
= ncrs
->next
)
379 for (ncr
= ncrs
->list
; ncr
!= NULL
; ncr
= ncr
->next
)
380 if (strcmp (ncr
->name
, defsecname
) == 0)
381 check_refs (h
, hl
, ncrs
);
386 /* The struct is used to pass information from check_refs to
387 check_reloc_refs through bfd_map_over_sections. */
389 struct check_refs_info
{
390 struct cref_hash_entry
*h
;
392 struct lang_nocrossrefs
*ncrs
;
397 /* This function is called for each symbol defined in a section which
398 prohibits cross references. We need to look through all references
399 to this symbol, and ensure that the references are not from
400 prohibited sections. */
403 check_refs (h
, hl
, ncrs
)
404 struct cref_hash_entry
*h
;
405 struct bfd_link_hash_entry
*hl
;
406 struct lang_nocrossrefs
*ncrs
;
408 struct cref_ref
*ref
;
410 for (ref
= h
->refs
; ref
!= NULL
; ref
= ref
->next
)
412 lang_input_statement_type
*li
;
414 struct check_refs_info info
;
416 /* We need to look through the relocations for this BFD, to see
417 if any of the relocations which refer to this symbol are from
418 a prohibited section. Note that we need to do this even for
419 the BFD in which the symbol is defined, since even a single
420 BFD might contain a prohibited cross reference; for this
421 case, we set the SAME field in INFO, which will cause
422 CHECK_RELOCS_REFS to check for relocations against the
423 section as well as against the symbol. */
425 li
= (lang_input_statement_type
*) ref
->abfd
->usrdata
;
426 if (li
!= NULL
&& li
->asymbols
!= NULL
)
427 asymbols
= li
->asymbols
;
433 symsize
= bfd_get_symtab_upper_bound (ref
->abfd
);
435 einfo (_("%B%F: could not read symbols; %E\n"), ref
->abfd
);
436 asymbols
= (asymbol
**) xmalloc (symsize
);
437 symbol_count
= bfd_canonicalize_symtab (ref
->abfd
, asymbols
);
438 if (symbol_count
< 0)
439 einfo (_("%B%F: could not read symbols: %E\n"), ref
->abfd
);
442 li
->asymbols
= asymbols
;
443 li
->symbol_count
= symbol_count
;
448 info
.defsec
= hl
->u
.def
.section
;
450 info
.asymbols
= asymbols
;
451 if (ref
->abfd
== hl
->u
.def
.section
->owner
)
455 bfd_map_over_sections (ref
->abfd
, check_reloc_refs
, (PTR
) &info
);
462 /* This is called via bfd_map_over_sections. INFO->H is a symbol
463 defined in INFO->DEFSECNAME. If this section maps into any of the
464 sections listed in INFO->NCRS, other than INFO->DEFSECNAME, then we
465 look through the relocations. If any of the relocations are to
466 INFO->H, then we report a prohibited cross reference error. */
469 check_reloc_refs (abfd
, sec
, iarg
)
474 struct check_refs_info
*info
= (struct check_refs_info
*) iarg
;
476 const char *outsecname
;
478 const char *outdefsecname
;
479 struct lang_nocrossref
*ncr
;
486 outsec
= sec
->output_section
;
487 outsecname
= bfd_get_section_name (outsec
->owner
, outsec
);
489 outdefsec
= info
->defsec
->output_section
;
490 outdefsecname
= bfd_get_section_name (outdefsec
->owner
, outdefsec
);
492 /* The section where the symbol is defined is permitted. */
493 if (strcmp (outsecname
, outdefsecname
) == 0)
496 for (ncr
= info
->ncrs
->list
; ncr
!= NULL
; ncr
= ncr
->next
)
497 if (strcmp (outsecname
, ncr
->name
) == 0)
503 /* This section is one for which cross references are prohibited.
504 Look through the relocations, and see if any of them are to
507 symname
= info
->h
->root
.string
;
509 relsize
= bfd_get_reloc_upper_bound (abfd
, sec
);
511 einfo (_("%B%F: could not read relocs: %E\n"), abfd
);
515 relpp
= (arelent
**) xmalloc (relsize
);
516 relcount
= bfd_canonicalize_reloc (abfd
, sec
, relpp
, info
->asymbols
);
518 einfo (_("%B%F: could not read relocs: %E\n"), abfd
);
522 for (; p
< pend
&& *p
!= NULL
; p
++)
526 if (q
->sym_ptr_ptr
!= NULL
527 && *q
->sym_ptr_ptr
!= NULL
528 && (strcmp (bfd_asymbol_name (*q
->sym_ptr_ptr
), symname
) == 0
530 && bfd_get_section (*q
->sym_ptr_ptr
) == info
->defsec
)))
532 /* We found a reloc for the symbol. The symbol is defined
533 in OUTSECNAME. This reloc is from a section which is
534 mapped into a section from which references to OUTSECNAME
535 are prohibited. We must report an error. */
536 einfo (_("%X%C: prohibited cross reference from %s to `%T' in %s\n"),
537 abfd
, sec
, q
->address
, outsecname
,
538 bfd_asymbol_name (*q
->sym_ptr_ptr
), outdefsecname
);