1 /* ldcref.c -- output a cross reference table
2 Copyright (C) 1996 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. */
26 #include "libiberty.h"
32 /* We keep an instance of this structure for each reference to a
33 symbol from a given object. */
37 /* The next reference. */
38 struct cref_ref
*next
;
41 /* True if the symbol is defined. */
43 /* True if the symbol is common. */
44 unsigned int common
: 1;
45 /* True if the symbol is undefined. */
46 unsigned int undef
: 1;
49 /* We keep a hash table of symbols. Each entry looks like this. */
51 struct cref_hash_entry
53 struct bfd_hash_entry root
;
54 /* The demangled name. */
56 /* References to and definitions of this symbol. */
57 struct cref_ref
*refs
;
60 /* This is what the hash table looks like. */
62 struct cref_hash_table
64 struct bfd_hash_table root
;
67 /* Local functions. */
69 static struct bfd_hash_entry
*cref_hash_newfunc
70 PARAMS ((struct bfd_hash_entry
*, struct bfd_hash_table
*, const char *));
71 static boolean cref_fill_array
PARAMS ((struct cref_hash_entry
*, PTR
));
72 static int cref_sort_array
PARAMS ((const PTR
, const PTR
));
73 static void output_one_cref
PARAMS ((FILE *, struct cref_hash_entry
*));
75 /* Look up an entry in the cref hash table. */
77 #define cref_hash_lookup(table, string, create, copy) \
78 ((struct cref_hash_entry *) \
79 bfd_hash_lookup (&(table)->root, (string), (create), (copy)))
81 /* Traverse the cref hash table. */
83 #define cref_hash_traverse(table, func, info) \
86 (boolean (*) PARAMS ((struct bfd_hash_entry *, PTR))) (func), \
89 /* The cref hash table. */
91 static struct cref_hash_table cref_table
;
93 /* Whether the cref hash table has been initialized. */
95 static boolean cref_initialized
;
97 /* The number of symbols seen so far. */
99 static size_t cref_symcount
;
101 /* Create an entry in a cref hash table. */
103 static struct bfd_hash_entry
*
104 cref_hash_newfunc (entry
, table
, string
)
105 struct bfd_hash_entry
*entry
;
106 struct bfd_hash_table
*table
;
109 struct cref_hash_entry
*ret
= (struct cref_hash_entry
*) entry
;
111 /* Allocate the structure if it has not already been allocated by a
114 ret
= ((struct cref_hash_entry
*)
115 bfd_hash_allocate (table
, sizeof (struct cref_hash_entry
)));
117 return (struct bfd_hash_entry
*) ret
;
119 /* Call the allocation method of the superclass. */
120 ret
= ((struct cref_hash_entry
*)
121 bfd_hash_newfunc ((struct bfd_hash_entry
*) ret
, table
, string
));
124 /* Set local fields. */
125 ret
->demangled
= NULL
;
128 /* Keep a count of the number of entries created in the hash
133 return (struct bfd_hash_entry
*) ret
;
136 /* Add a symbol to the cref hash table. This is called for every
137 symbol that is seen during the link. */
141 add_cref (name
, abfd
, section
, value
)
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
= (struct cref_ref
*) 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 (h
, data
)
190 struct cref_hash_entry
*h
;
193 struct cref_hash_entry
***pph
= (struct cref_hash_entry
***) data
;
195 ASSERT (h
->demangled
== NULL
);
196 h
->demangled
= demangle (h
->root
.string
);
205 /* Sort an array of cref hash table entries by name. */
208 cref_sort_array (a1
, a2
)
212 const struct cref_hash_entry
**p1
= (const struct cref_hash_entry
**) a1
;
213 const struct cref_hash_entry
**p2
= (const struct cref_hash_entry
**) a2
;
215 return strcmp ((*p1
)->demangled
, (*p2
)->demangled
);
218 /* Write out the cref table. */
227 struct cref_hash_entry
**csyms
, **csym_fill
, **csym
, **csym_end
;
229 fprintf (fp
, "\nCross Reference Table\n\n");
230 fprintf (fp
, "Symbol");
231 len
= sizeof "Symbol" - 1;
232 while (len
< FILECOL
)
237 fprintf (fp
, "File\n");
239 if (! cref_initialized
)
241 fprintf (fp
, "No symbols\n");
245 csyms
= ((struct cref_hash_entry
**)
246 xmalloc (cref_symcount
* sizeof (*csyms
)));
249 cref_hash_traverse (&cref_table
, cref_fill_array
, &csym_fill
);
250 ASSERT (csym_fill
- csyms
== cref_symcount
);
252 qsort (csyms
, cref_symcount
, sizeof (*csyms
), cref_sort_array
);
254 csym_end
= csyms
+ cref_symcount
;
255 for (csym
= csyms
; csym
< csym_end
; csym
++)
256 output_one_cref (fp
, *csym
);
259 /* Output one entry in the cross reference table. */
262 output_one_cref (fp
, h
)
264 struct cref_hash_entry
*h
;
267 struct bfd_link_hash_entry
*hl
;
270 hl
= bfd_link_hash_lookup (link_info
.hash
, h
->root
.string
, false,
273 einfo ("%P: symbol `%T' missing from main hash table\n",
277 /* If this symbol is defined in a dynamic object but never
278 referenced by a normal object, then don't print it. */
279 if (hl
->type
== bfd_link_hash_defined
)
281 if (hl
->u
.def
.section
->output_section
== NULL
)
283 if (hl
->u
.def
.section
->owner
!= NULL
284 && (hl
->u
.def
.section
->owner
->flags
& DYNAMIC
) != 0)
286 for (r
= h
->refs
; r
!= NULL
; r
= r
->next
)
287 if ((r
->abfd
->flags
& DYNAMIC
) == 0)
295 fprintf (fp
, "%s ", h
->demangled
);
296 len
= strlen (h
->demangled
) + 1;
298 for (r
= h
->refs
; r
!= NULL
; r
= r
->next
)
302 while (len
< FILECOL
)
307 finfo (fp
, "%B\n", r
->abfd
);
312 for (r
= h
->refs
; r
!= NULL
; r
= r
->next
)
316 while (len
< FILECOL
)
321 finfo (fp
, "%B\n", r
->abfd
);