1 /* ldcref.c -- output a cross reference table
2 Copyright 1996-2013 Free Software Foundation, Inc.
3 Written by Ian Lance Taylor <ian@cygnus.com>
5 This file is part of the GNU Binutils.
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 3 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., 51 Franklin Street - Fifth Floor, Boston,
20 MA 02110-1301, USA. */
23 /* This file holds routines that manage the cross reference table.
24 The table is used to generate cross reference reports. It is also
25 used to implement the NOCROSSREFS command in the linker script. */
30 #include "libiberty.h"
40 /* We keep an instance of this structure for each reference to a
41 symbol from a given object. */
44 /* The next reference. */
45 struct cref_ref
*next
;
48 /* True if the symbol is defined. */
50 /* True if the symbol is common. */
51 unsigned int common
: 1;
52 /* True if the symbol is undefined. */
53 unsigned int undef
: 1;
56 /* We keep a hash table of symbols. Each entry looks like this. */
58 struct cref_hash_entry
{
59 struct bfd_hash_entry root
;
60 /* The demangled name. */
61 const char *demangled
;
62 /* References to and definitions of this symbol. */
63 struct cref_ref
*refs
;
66 /* This is what the hash table looks like. */
68 struct cref_hash_table
{
69 struct bfd_hash_table root
;
72 /* Forward declarations. */
74 static void output_one_cref (FILE *, struct cref_hash_entry
*);
75 static void check_local_sym_xref (lang_input_statement_type
*);
76 static bfd_boolean
check_nocrossref (struct cref_hash_entry
*, void *);
77 static void check_refs (const char *, bfd_boolean
, asection
*, bfd
*,
78 struct lang_nocrossrefs
*);
79 static void check_reloc_refs (bfd
*, asection
*, void *);
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 (bfd_boolean (*) (struct bfd_hash_entry *, void *)) (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 bfd_boolean cref_initialized
;
103 /* The number of symbols seen so far. */
105 static size_t cref_symcount
;
107 /* Used to take a snapshot of the cref hash table when starting to
108 add syms from an as-needed library. */
109 static struct bfd_hash_entry
**old_table
;
110 static unsigned int old_size
;
111 static unsigned int old_count
;
112 static void *old_tab
;
113 static void *alloc_mark
;
114 static size_t tabsize
, entsize
, refsize
;
115 static size_t old_symcount
;
117 /* Create an entry in a cref hash table. */
119 static struct bfd_hash_entry
*
120 cref_hash_newfunc (struct bfd_hash_entry
*entry
,
121 struct bfd_hash_table
*table
,
124 struct cref_hash_entry
*ret
= (struct cref_hash_entry
*) entry
;
126 /* Allocate the structure if it has not already been allocated by a
129 ret
= ((struct cref_hash_entry
*)
130 bfd_hash_allocate (table
, sizeof (struct cref_hash_entry
)));
134 /* Call the allocation method of the superclass. */
135 ret
= ((struct cref_hash_entry
*)
136 bfd_hash_newfunc ((struct bfd_hash_entry
*) ret
, table
, string
));
139 /* Set local fields. */
140 ret
->demangled
= NULL
;
143 /* Keep a count of the number of entries created in the hash
151 /* Add a symbol to the cref hash table. This is called for every
152 global symbol that is seen during the link. */
155 add_cref (const char *name
,
158 bfd_vma value ATTRIBUTE_UNUSED
)
160 struct cref_hash_entry
*h
;
163 if (! cref_initialized
)
165 if (!bfd_hash_table_init (&cref_table
.root
, cref_hash_newfunc
,
166 sizeof (struct cref_hash_entry
)))
167 einfo (_("%X%P: bfd_hash_table_init of cref table failed: %E\n"));
168 cref_initialized
= TRUE
;
171 h
= cref_hash_lookup (&cref_table
, name
, TRUE
, FALSE
);
173 einfo (_("%X%P: cref_hash_lookup failed: %E\n"));
175 for (r
= h
->refs
; r
!= NULL
; r
= r
->next
)
181 r
= (struct cref_ref
*) bfd_hash_allocate (&cref_table
.root
, sizeof *r
);
183 einfo (_("%X%P: cref alloc failed: %E\n"));
192 if (bfd_is_und_section (section
))
194 else if (bfd_is_com_section (section
))
200 /* Called before loading an as-needed library to take a snapshot of
201 the cref hash table, and after we have loaded or found that the
202 library was not needed. */
205 handle_asneeded_cref (bfd
*abfd ATTRIBUTE_UNUSED
,
206 enum notice_asneeded_action act
)
210 if (!cref_initialized
)
213 if (act
== notice_as_needed
)
215 char *old_ent
, *old_ref
;
217 for (i
= 0; i
< cref_table
.root
.size
; i
++)
219 struct bfd_hash_entry
*p
;
220 struct cref_hash_entry
*c
;
223 for (p
= cref_table
.root
.table
[i
]; p
!= NULL
; p
= p
->next
)
225 entsize
+= cref_table
.root
.entsize
;
226 c
= (struct cref_hash_entry
*) p
;
227 for (r
= c
->refs
; r
!= NULL
; r
= r
->next
)
228 refsize
+= sizeof (struct cref_ref
);
232 tabsize
= cref_table
.root
.size
* sizeof (struct bfd_hash_entry
*);
233 old_tab
= xmalloc (tabsize
+ entsize
+ refsize
);
235 alloc_mark
= bfd_hash_allocate (&cref_table
.root
, 1);
236 if (alloc_mark
== NULL
)
239 memcpy (old_tab
, cref_table
.root
.table
, tabsize
);
240 old_ent
= (char *) old_tab
+ tabsize
;
241 old_ref
= (char *) old_ent
+ entsize
;
242 old_table
= cref_table
.root
.table
;
243 old_size
= cref_table
.root
.size
;
244 old_count
= cref_table
.root
.count
;
245 old_symcount
= cref_symcount
;
247 for (i
= 0; i
< cref_table
.root
.size
; i
++)
249 struct bfd_hash_entry
*p
;
250 struct cref_hash_entry
*c
;
253 for (p
= cref_table
.root
.table
[i
]; p
!= NULL
; p
= p
->next
)
255 memcpy (old_ent
, p
, cref_table
.root
.entsize
);
256 old_ent
= (char *) old_ent
+ cref_table
.root
.entsize
;
257 c
= (struct cref_hash_entry
*) p
;
258 for (r
= c
->refs
; r
!= NULL
; r
= r
->next
)
260 memcpy (old_ref
, r
, sizeof (struct cref_ref
));
261 old_ref
= (char *) old_ref
+ sizeof (struct cref_ref
);
268 if (act
== notice_not_needed
)
270 char *old_ent
, *old_ref
;
274 /* The only way old_tab can be NULL is if the cref hash table
275 had not been initialised when notice_as_needed. */
276 bfd_hash_table_free (&cref_table
.root
);
277 cref_initialized
= FALSE
;
281 old_ent
= (char *) old_tab
+ tabsize
;
282 old_ref
= (char *) old_ent
+ entsize
;
283 cref_table
.root
.table
= old_table
;
284 cref_table
.root
.size
= old_size
;
285 cref_table
.root
.count
= old_count
;
286 memcpy (cref_table
.root
.table
, old_tab
, tabsize
);
287 cref_symcount
= old_symcount
;
289 for (i
= 0; i
< cref_table
.root
.size
; i
++)
291 struct bfd_hash_entry
*p
;
292 struct cref_hash_entry
*c
;
295 for (p
= cref_table
.root
.table
[i
]; p
!= NULL
; p
= p
->next
)
297 memcpy (p
, old_ent
, cref_table
.root
.entsize
);
298 old_ent
= (char *) old_ent
+ cref_table
.root
.entsize
;
299 c
= (struct cref_hash_entry
*) p
;
300 for (r
= c
->refs
; r
!= NULL
; r
= r
->next
)
302 memcpy (r
, old_ref
, sizeof (struct cref_ref
));
303 old_ref
= (char *) old_ref
+ sizeof (struct cref_ref
);
308 objalloc_free_block ((struct objalloc
*) cref_table
.root
.memory
,
311 else if (act
!= notice_needed
)
319 /* Copy the addresses of the hash table entries into an array. This
320 is called via cref_hash_traverse. We also fill in the demangled
324 cref_fill_array (struct cref_hash_entry
*h
, void *data
)
326 struct cref_hash_entry
***pph
= (struct cref_hash_entry
***) data
;
328 ASSERT (h
->demangled
== NULL
);
329 h
->demangled
= bfd_demangle (link_info
.output_bfd
, h
->root
.string
,
330 DMGL_ANSI
| DMGL_PARAMS
);
331 if (h
->demangled
== NULL
)
332 h
->demangled
= h
->root
.string
;
341 /* Sort an array of cref hash table entries by name. */
344 cref_sort_array (const void *a1
, const void *a2
)
346 const struct cref_hash_entry
* const *p1
=
347 (const struct cref_hash_entry
* const *) a1
;
348 const struct cref_hash_entry
* const *p2
=
349 (const struct cref_hash_entry
* const *) a2
;
351 return strcmp ((*p1
)->demangled
, (*p2
)->demangled
);
354 /* Write out the cref table. */
359 output_cref (FILE *fp
)
362 struct cref_hash_entry
**csyms
, **csym_fill
, **csym
, **csym_end
;
365 fprintf (fp
, _("\nCross Reference Table\n\n"));
367 fprintf (fp
, "%s", msg
);
369 while (len
< FILECOL
)
374 fprintf (fp
, _("File\n"));
376 if (! cref_initialized
)
378 fprintf (fp
, _("No symbols\n"));
382 csyms
= (struct cref_hash_entry
**) xmalloc (cref_symcount
* sizeof (*csyms
));
385 cref_hash_traverse (&cref_table
, cref_fill_array
, &csym_fill
);
386 ASSERT ((size_t) (csym_fill
- csyms
) == cref_symcount
);
388 qsort (csyms
, cref_symcount
, sizeof (*csyms
), cref_sort_array
);
390 csym_end
= csyms
+ cref_symcount
;
391 for (csym
= csyms
; csym
< csym_end
; csym
++)
392 output_one_cref (fp
, *csym
);
395 /* Output one entry in the cross reference table. */
398 output_one_cref (FILE *fp
, struct cref_hash_entry
*h
)
401 struct bfd_link_hash_entry
*hl
;
404 hl
= bfd_link_hash_lookup (link_info
.hash
, h
->root
.string
, FALSE
,
407 einfo ("%P: symbol `%T' missing from main hash table\n",
411 /* If this symbol is defined in a dynamic object but never
412 referenced by a normal object, then don't print it. */
413 if (hl
->type
== bfd_link_hash_defined
)
415 if (hl
->u
.def
.section
->output_section
== NULL
)
417 if (hl
->u
.def
.section
->owner
!= NULL
418 && (hl
->u
.def
.section
->owner
->flags
& DYNAMIC
) != 0)
420 for (r
= h
->refs
; r
!= NULL
; r
= r
->next
)
421 if ((r
->abfd
->flags
& DYNAMIC
) == 0)
429 fprintf (fp
, "%s ", h
->demangled
);
430 len
= strlen (h
->demangled
) + 1;
432 for (r
= h
->refs
; r
!= NULL
; r
= r
->next
)
436 while (len
< FILECOL
)
441 lfinfo (fp
, "%B\n", r
->abfd
);
446 for (r
= h
->refs
; r
!= NULL
; r
= r
->next
)
450 while (len
< FILECOL
)
455 lfinfo (fp
, "%B\n", r
->abfd
);
460 for (r
= h
->refs
; r
!= NULL
; r
= r
->next
)
462 if (! r
->def
&& ! r
->common
)
464 while (len
< FILECOL
)
469 lfinfo (fp
, "%B\n", r
->abfd
);
477 /* Check for prohibited cross references. */
480 check_nocrossrefs (void)
482 if (! cref_initialized
)
485 cref_hash_traverse (&cref_table
, check_nocrossref
, NULL
);
487 lang_for_each_file (check_local_sym_xref
);
490 /* Check for prohibited cross references to local and section symbols. */
493 check_local_sym_xref (lang_input_statement_type
*statement
)
498 abfd
= statement
->the_bfd
;
502 if (!bfd_generic_link_read_symbols (abfd
))
503 einfo (_("%B%F: could not read symbols: %E\n"), abfd
);
505 for (syms
= bfd_get_outsymbols (abfd
); *syms
; ++syms
)
507 asymbol
*sym
= *syms
;
508 if (sym
->flags
& (BSF_GLOBAL
| BSF_WARNING
| BSF_INDIRECT
| BSF_FILE
))
510 if ((sym
->flags
& (BSF_LOCAL
| BSF_SECTION_SYM
)) != 0
511 && sym
->section
->output_section
!= NULL
)
513 const char *outsecname
, *symname
;
514 struct lang_nocrossrefs
*ncrs
;
515 struct lang_nocrossref
*ncr
;
517 outsecname
= sym
->section
->output_section
->name
;
519 if ((sym
->flags
& BSF_SECTION_SYM
) == 0)
521 for (ncrs
= nocrossref_list
; ncrs
!= NULL
; ncrs
= ncrs
->next
)
522 for (ncr
= ncrs
->list
; ncr
!= NULL
; ncr
= ncr
->next
)
523 if (strcmp (ncr
->name
, outsecname
) == 0)
524 check_refs (symname
, FALSE
, sym
->section
, abfd
, ncrs
);
529 /* Check one symbol to see if it is a prohibited cross reference. */
532 check_nocrossref (struct cref_hash_entry
*h
, void *ignore ATTRIBUTE_UNUSED
)
534 struct bfd_link_hash_entry
*hl
;
536 const char *defsecname
;
537 struct lang_nocrossrefs
*ncrs
;
538 struct lang_nocrossref
*ncr
;
539 struct cref_ref
*ref
;
541 hl
= bfd_link_hash_lookup (link_info
.hash
, h
->root
.string
, FALSE
,
545 einfo (_("%P: symbol `%T' missing from main hash table\n"),
550 if (hl
->type
!= bfd_link_hash_defined
551 && hl
->type
!= bfd_link_hash_defweak
)
554 defsec
= hl
->u
.def
.section
->output_section
;
557 defsecname
= bfd_get_section_name (defsec
->owner
, defsec
);
559 for (ncrs
= nocrossref_list
; ncrs
!= NULL
; ncrs
= ncrs
->next
)
560 for (ncr
= ncrs
->list
; ncr
!= NULL
; ncr
= ncr
->next
)
561 if (strcmp (ncr
->name
, defsecname
) == 0)
562 for (ref
= h
->refs
; ref
!= NULL
; ref
= ref
->next
)
563 check_refs (hl
->root
.string
, TRUE
, hl
->u
.def
.section
,
569 /* The struct is used to pass information from check_refs to
570 check_reloc_refs through bfd_map_over_sections. */
572 struct check_refs_info
{
573 const char *sym_name
;
575 struct lang_nocrossrefs
*ncrs
;
580 /* This function is called for each symbol defined in a section which
581 prohibits cross references. We need to look through all references
582 to this symbol, and ensure that the references are not from
583 prohibited sections. */
586 check_refs (const char *name
,
590 struct lang_nocrossrefs
*ncrs
)
592 struct check_refs_info info
;
594 /* We need to look through the relocations for this BFD, to see
595 if any of the relocations which refer to this symbol are from
596 a prohibited section. Note that we need to do this even for
597 the BFD in which the symbol is defined, since even a single
598 BFD might contain a prohibited cross reference. */
600 if (!bfd_generic_link_read_symbols (abfd
))
601 einfo (_("%B%F: could not read symbols: %E\n"), abfd
);
603 info
.sym_name
= name
;
604 info
.global
= global
;
607 info
.asymbols
= bfd_get_outsymbols (abfd
);
608 bfd_map_over_sections (abfd
, check_reloc_refs
, &info
);
611 /* This is called via bfd_map_over_sections. INFO->SYM_NAME is a symbol
612 defined in INFO->DEFSECNAME. If this section maps into any of the
613 sections listed in INFO->NCRS, other than INFO->DEFSECNAME, then we
614 look through the relocations. If any of the relocations are to
615 INFO->SYM_NAME, then we report a prohibited cross reference error. */
618 check_reloc_refs (bfd
*abfd
, asection
*sec
, void *iarg
)
620 struct check_refs_info
*info
= (struct check_refs_info
*) iarg
;
622 const char *outsecname
;
624 const char *outdefsecname
;
625 struct lang_nocrossref
*ncr
;
633 outsec
= sec
->output_section
;
634 outsecname
= bfd_get_section_name (outsec
->owner
, outsec
);
636 outdefsec
= info
->defsec
->output_section
;
637 outdefsecname
= bfd_get_section_name (outdefsec
->owner
, outdefsec
);
639 /* The section where the symbol is defined is permitted. */
640 if (strcmp (outsecname
, outdefsecname
) == 0)
643 for (ncr
= info
->ncrs
->list
; ncr
!= NULL
; ncr
= ncr
->next
)
644 if (strcmp (outsecname
, ncr
->name
) == 0)
650 /* This section is one for which cross references are prohibited.
651 Look through the relocations, and see if any of them are to
652 INFO->SYM_NAME. If INFO->SYMNAME is NULL, check for relocations
653 against the section symbol. If INFO->GLOBAL is TRUE, the
654 definition is global, check for relocations against the global
655 symbols. Otherwise check for relocations against the local and
658 symname
= info
->sym_name
;
659 global
= info
->global
;
661 relsize
= bfd_get_reloc_upper_bound (abfd
, sec
);
663 einfo (_("%B%F: could not read relocs: %E\n"), abfd
);
667 relpp
= (arelent
**) xmalloc (relsize
);
668 relcount
= bfd_canonicalize_reloc (abfd
, sec
, relpp
, info
->asymbols
);
670 einfo (_("%B%F: could not read relocs: %E\n"), abfd
);
674 for (; p
< pend
&& *p
!= NULL
; p
++)
678 if (q
->sym_ptr_ptr
!= NULL
679 && *q
->sym_ptr_ptr
!= NULL
681 && (bfd_is_und_section (bfd_get_section (*q
->sym_ptr_ptr
))
682 || bfd_is_com_section (bfd_get_section (*q
->sym_ptr_ptr
))
683 || ((*q
->sym_ptr_ptr
)->flags
& (BSF_GLOBAL
686 && ((*q
->sym_ptr_ptr
)->flags
& (BSF_LOCAL
687 | BSF_SECTION_SYM
)) != 0
688 && bfd_get_section (*q
->sym_ptr_ptr
) == info
->defsec
))
690 ? strcmp (bfd_asymbol_name (*q
->sym_ptr_ptr
), symname
) == 0
691 : ((*q
->sym_ptr_ptr
)->flags
& BSF_SECTION_SYM
) != 0))
693 /* We found a reloc for the symbol. The symbol is defined
694 in OUTSECNAME. This reloc is from a section which is
695 mapped into a section from which references to OUTSECNAME
696 are prohibited. We must report an error. */
697 einfo (_("%X%C: prohibited cross reference from %s to `%T' in %s\n"),
698 abfd
, sec
, q
->address
, outsecname
,
699 bfd_asymbol_name (*q
->sym_ptr_ptr
), outdefsecname
);