2000-10-09 Kazu Hirata <kazu@hxi.com>
[deliverable/binutils-gdb.git] / ld / ldcref.c
CommitLineData
252b5132 1/* ldcref.c -- output a cross reference table
305c7206 2 Copyright (C) 1996, 97, 98, 99, 2000 Free Software Foundation, Inc.
252b5132
RH
3 Written by Ian Lance Taylor <ian@cygnus.com>
4
5This file is part of GLD, the Gnu Linker.
6
7This program is free software; you can redistribute it and/or modify
8it under the terms of the GNU General Public License as published by
9the Free Software Foundation; either version 2 of the License, or
10(at your option) any later version.
11
12This program is distributed in the hope that it will be useful,
13but WITHOUT ANY WARRANTY; without even the implied warranty of
14MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15GNU General Public License for more details.
16
17You should have received a copy of the GNU General Public License
18along with this program; if not, write to the Free Software
19Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
20
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. */
24
25#include "bfd.h"
26#include "sysdep.h"
27#include "bfdlink.h"
28#include "libiberty.h"
29
30#include "ld.h"
31#include "ldmain.h"
32#include "ldmisc.h"
33#include "ldexp.h"
34#include "ldlang.h"
35
36/* We keep an instance of this structure for each reference to a
37 symbol from a given object. */
38
39struct cref_ref
40{
41 /* The next reference. */
42 struct cref_ref *next;
43 /* The object. */
44 bfd *abfd;
45 /* True if the symbol is defined. */
46 unsigned int def : 1;
47 /* True if the symbol is common. */
48 unsigned int common : 1;
49 /* True if the symbol is undefined. */
50 unsigned int undef : 1;
51};
52
53/* We keep a hash table of symbols. Each entry looks like this. */
54
55struct cref_hash_entry
56{
57 struct bfd_hash_entry root;
58 /* The demangled name. */
59 char *demangled;
60 /* References to and definitions of this symbol. */
61 struct cref_ref *refs;
62};
63
64/* This is what the hash table looks like. */
65
66struct cref_hash_table
67{
68 struct bfd_hash_table root;
69};
70
71/* Local functions. */
72
73static struct bfd_hash_entry *cref_hash_newfunc
74 PARAMS ((struct bfd_hash_entry *, struct bfd_hash_table *, const char *));
75static boolean cref_fill_array PARAMS ((struct cref_hash_entry *, PTR));
76static int cref_sort_array PARAMS ((const PTR, const PTR));
77static void output_one_cref PARAMS ((FILE *, struct cref_hash_entry *));
78static boolean check_nocrossref PARAMS ((struct cref_hash_entry *, PTR));
79static void check_refs
80 PARAMS ((struct cref_hash_entry *, struct bfd_link_hash_entry *,
81 struct lang_nocrossrefs *));
82static void check_reloc_refs PARAMS ((bfd *, asection *, PTR));
83
84/* Look up an entry in the cref hash table. */
85
86#define cref_hash_lookup(table, string, create, copy) \
87 ((struct cref_hash_entry *) \
88 bfd_hash_lookup (&(table)->root, (string), (create), (copy)))
89
90/* Traverse the cref hash table. */
91
92#define cref_hash_traverse(table, func, info) \
93 (bfd_hash_traverse \
94 (&(table)->root, \
95 (boolean (*) PARAMS ((struct bfd_hash_entry *, PTR))) (func), \
96 (info)))
97
98/* The cref hash table. */
99
100static struct cref_hash_table cref_table;
101
102/* Whether the cref hash table has been initialized. */
103
104static boolean cref_initialized;
105
106/* The number of symbols seen so far. */
107
108static size_t cref_symcount;
109
110/* Create an entry in a cref hash table. */
111
112static struct bfd_hash_entry *
113cref_hash_newfunc (entry, table, string)
114 struct bfd_hash_entry *entry;
115 struct bfd_hash_table *table;
116 const char *string;
117{
118 struct cref_hash_entry *ret = (struct cref_hash_entry *) entry;
119
120 /* Allocate the structure if it has not already been allocated by a
121 subclass. */
122 if (ret == NULL)
123 ret = ((struct cref_hash_entry *)
124 bfd_hash_allocate (table, sizeof (struct cref_hash_entry)));
125 if (ret == NULL)
126 return (struct bfd_hash_entry *) ret;
127
128 /* Call the allocation method of the superclass. */
129 ret = ((struct cref_hash_entry *)
130 bfd_hash_newfunc ((struct bfd_hash_entry *) ret, table, string));
131 if (ret != NULL)
132 {
133 /* Set local fields. */
134 ret->demangled = NULL;
135 ret->refs = NULL;
136
137 /* Keep a count of the number of entries created in the hash
138 table. */
139 ++cref_symcount;
140 }
141
142 return (struct bfd_hash_entry *) ret;
143}
144
145/* Add a symbol to the cref hash table. This is called for every
146 symbol that is seen during the link. */
147
252b5132
RH
148void
149add_cref (name, abfd, section, value)
150 const char *name;
151 bfd *abfd;
152 asection *section;
87f2a346 153 bfd_vma value ATTRIBUTE_UNUSED;
252b5132
RH
154{
155 struct cref_hash_entry *h;
156 struct cref_ref *r;
157
158 if (! cref_initialized)
159 {
160 if (! bfd_hash_table_init (&cref_table.root, cref_hash_newfunc))
161 einfo (_("%X%P: bfd_hash_table_init of cref table failed: %E\n"));
162 cref_initialized = true;
163 }
164
165 h = cref_hash_lookup (&cref_table, name, true, false);
166 if (h == NULL)
167 einfo (_("%X%P: cref_hash_lookup failed: %E\n"));
168
169 for (r = h->refs; r != NULL; r = r->next)
170 if (r->abfd == abfd)
171 break;
172
173 if (r == NULL)
174 {
175 r = (struct cref_ref *) xmalloc (sizeof *r);
176 r->next = h->refs;
177 h->refs = r;
178 r->abfd = abfd;
179 r->def = false;
180 r->common = false;
181 r->undef = false;
182 }
183
184 if (bfd_is_und_section (section))
185 r->undef = true;
186 else if (bfd_is_com_section (section))
187 r->common = true;
188 else
189 r->def = true;
190}
191
192/* Copy the addresses of the hash table entries into an array. This
193 is called via cref_hash_traverse. We also fill in the demangled
194 name. */
195
196static boolean
197cref_fill_array (h, data)
198 struct cref_hash_entry *h;
199 PTR data;
200{
201 struct cref_hash_entry ***pph = (struct cref_hash_entry ***) data;
202
203 ASSERT (h->demangled == NULL);
204 h->demangled = demangle (h->root.string);
205
206 **pph = h;
207
208 ++*pph;
209
210 return true;
211}
212
213/* Sort an array of cref hash table entries by name. */
214
215static int
216cref_sort_array (a1, a2)
217 const PTR a1;
218 const PTR a2;
219{
220 const struct cref_hash_entry **p1 = (const struct cref_hash_entry **) a1;
221 const struct cref_hash_entry **p2 = (const struct cref_hash_entry **) a2;
222
223 return strcmp ((*p1)->demangled, (*p2)->demangled);
224}
225
226/* Write out the cref table. */
227
228#define FILECOL (50)
229
230void
231output_cref (fp)
232 FILE *fp;
233{
234 int len;
235 struct cref_hash_entry **csyms, **csym_fill, **csym, **csym_end;
236 const char *msg;
237
238 fprintf (fp, _("\nCross Reference Table\n\n"));
239 msg = _("Symbol");
305c7206 240 fprintf (fp, "%s", msg);
252b5132
RH
241 len = strlen (msg);
242 while (len < FILECOL)
243 {
4de2d33d 244 putc (' ', fp);
252b5132
RH
245 ++len;
246 }
247 fprintf (fp, _("File\n"));
248
249 if (! cref_initialized)
250 {
251 fprintf (fp, _("No symbols\n"));
252 return;
253 }
254
255 csyms = ((struct cref_hash_entry **)
256 xmalloc (cref_symcount * sizeof (*csyms)));
257
258 csym_fill = csyms;
259 cref_hash_traverse (&cref_table, cref_fill_array, &csym_fill);
260 ASSERT ((size_t) (csym_fill - csyms) == cref_symcount);
261
262 qsort (csyms, cref_symcount, sizeof (*csyms), cref_sort_array);
263
264 csym_end = csyms + cref_symcount;
265 for (csym = csyms; csym < csym_end; csym++)
266 output_one_cref (fp, *csym);
267}
268
269/* Output one entry in the cross reference table. */
270
271static void
272output_one_cref (fp, h)
273 FILE *fp;
274 struct cref_hash_entry *h;
275{
276 int len;
277 struct bfd_link_hash_entry *hl;
278 struct cref_ref *r;
279
280 hl = bfd_link_hash_lookup (link_info.hash, h->root.string, false,
281 false, true);
282 if (hl == NULL)
283 einfo ("%P: symbol `%T' missing from main hash table\n",
284 h->root.string);
285 else
286 {
287 /* If this symbol is defined in a dynamic object but never
288 referenced by a normal object, then don't print it. */
289 if (hl->type == bfd_link_hash_defined)
290 {
291 if (hl->u.def.section->output_section == NULL)
292 return;
293 if (hl->u.def.section->owner != NULL
294 && (hl->u.def.section->owner->flags & DYNAMIC) != 0)
295 {
296 for (r = h->refs; r != NULL; r = r->next)
297 if ((r->abfd->flags & DYNAMIC) == 0)
298 break;
299 if (r == NULL)
300 return;
301 }
302 }
303 }
304
305 fprintf (fp, "%s ", h->demangled);
306 len = strlen (h->demangled) + 1;
307
308 for (r = h->refs; r != NULL; r = r->next)
309 {
310 if (r->def)
311 {
312 while (len < FILECOL)
313 {
314 putc (' ', fp);
315 ++len;
316 }
317 lfinfo (fp, "%B\n", r->abfd);
318 len = 0;
319 }
320 }
321
322 for (r = h->refs; r != NULL; r = r->next)
323 {
324 if (! r->def)
325 {
326 while (len < FILECOL)
327 {
328 putc (' ', fp);
329 ++len;
330 }
331 lfinfo (fp, "%B\n", r->abfd);
332 len = 0;
333 }
334 }
335
336 ASSERT (len == 0);
337}
338
339/* Check for prohibited cross references. */
340
341void
342check_nocrossrefs ()
343{
344 if (! cref_initialized)
345 return;
346
347 cref_hash_traverse (&cref_table, check_nocrossref, (PTR) NULL);
348}
349
350/* Check one symbol to see if it is a prohibited cross reference. */
351
252b5132
RH
352static boolean
353check_nocrossref (h, ignore)
354 struct cref_hash_entry *h;
87f2a346 355 PTR ignore ATTRIBUTE_UNUSED;
252b5132
RH
356{
357 struct bfd_link_hash_entry *hl;
358 asection *defsec;
359 const char *defsecname;
360 struct lang_nocrossrefs *ncrs;
361 struct lang_nocrossref *ncr;
362
363 hl = bfd_link_hash_lookup (link_info.hash, h->root.string, false,
364 false, true);
365 if (hl == NULL)
366 {
367 einfo (_("%P: symbol `%T' missing from main hash table\n"),
368 h->root.string);
369 return true;
370 }
371
372 if (hl->type != bfd_link_hash_defined
373 && hl->type != bfd_link_hash_defweak)
374 return true;
375
376 defsec = hl->u.def.section->output_section;
377 if (defsec == NULL)
378 return true;
379 defsecname = bfd_get_section_name (defsec->owner, defsec);
380
381 for (ncrs = nocrossref_list; ncrs != NULL; ncrs = ncrs->next)
382 for (ncr = ncrs->list; ncr != NULL; ncr = ncr->next)
383 if (strcmp (ncr->name, defsecname) == 0)
384 check_refs (h, hl, ncrs);
385
386 return true;
387}
388
389/* The struct is used to pass information from check_refs to
390 check_reloc_refs through bfd_map_over_sections. */
391
392struct check_refs_info
393{
394 struct cref_hash_entry *h;
395 asection *defsec;
396 struct lang_nocrossrefs *ncrs;
397 asymbol **asymbols;
398 boolean same;
399};
400
401/* This function is called for each symbol defined in a section which
402 prohibits cross references. We need to look through all references
403 to this symbol, and ensure that the references are not from
404 prohibited sections. */
405
406static void
407check_refs (h, hl, ncrs)
408 struct cref_hash_entry *h;
409 struct bfd_link_hash_entry *hl;
410 struct lang_nocrossrefs *ncrs;
411{
412 struct cref_ref *ref;
413
414 for (ref = h->refs; ref != NULL; ref = ref->next)
415 {
416 lang_input_statement_type *li;
417 asymbol **asymbols;
418 struct check_refs_info info;
419
420 /* We need to look through the relocations for this BFD, to see
421 if any of the relocations which refer to this symbol are from
422 a prohibited section. Note that we need to do this even for
423 the BFD in which the symbol is defined, since even a single
424 BFD might contain a prohibited cross reference; for this
425 case, we set the SAME field in INFO, which will cause
426 CHECK_RELOCS_REFS to check for relocations against the
427 section as well as against the symbol. */
428
429 li = (lang_input_statement_type *) ref->abfd->usrdata;
430 if (li != NULL && li->asymbols != NULL)
431 asymbols = li->asymbols;
432 else
433 {
434 long symsize;
435 long symbol_count;
436
437 symsize = bfd_get_symtab_upper_bound (ref->abfd);
438 if (symsize < 0)
439 einfo (_("%B%F: could not read symbols; %E\n"), ref->abfd);
440 asymbols = (asymbol **) xmalloc (symsize);
441 symbol_count = bfd_canonicalize_symtab (ref->abfd, asymbols);
442 if (symbol_count < 0)
443 einfo (_("%B%F: could not read symbols: %E\n"), ref->abfd);
444 if (li != NULL)
445 {
446 li->asymbols = asymbols;
447 li->symbol_count = symbol_count;
448 }
449 }
450
451 info.h = h;
452 info.defsec = hl->u.def.section;
453 info.ncrs = ncrs;
454 info.asymbols = asymbols;
455 if (ref->abfd == hl->u.def.section->owner)
456 info.same = true;
457 else
458 info.same = false;
459 bfd_map_over_sections (ref->abfd, check_reloc_refs, (PTR) &info);
460
461 if (li == NULL)
462 free (asymbols);
463 }
464}
465
466/* This is called via bfd_map_over_sections. INFO->H is a symbol
467 defined in INFO->DEFSECNAME. If this section maps into any of the
468 sections listed in INFO->NCRS, other than INFO->DEFSECNAME, then we
469 look through the relocations. If any of the relocations are to
470 INFO->H, then we report a prohibited cross reference error. */
471
472static void
473check_reloc_refs (abfd, sec, iarg)
474 bfd *abfd;
475 asection *sec;
476 PTR iarg;
477{
478 struct check_refs_info *info = (struct check_refs_info *) iarg;
479 asection *outsec;
480 const char *outsecname;
481 asection *outdefsec;
482 const char *outdefsecname;
483 struct lang_nocrossref *ncr;
484 const char *symname;
485 long relsize;
486 arelent **relpp;
487 long relcount;
488 arelent **p, **pend;
489
490 outsec = sec->output_section;
491 outsecname = bfd_get_section_name (outsec->owner, outsec);
492
493 outdefsec = info->defsec->output_section;
494 outdefsecname = bfd_get_section_name (outdefsec->owner, outdefsec);
495
496 /* The section where the symbol is defined is permitted. */
497 if (strcmp (outsecname, outdefsecname) == 0)
498 return;
499
500 for (ncr = info->ncrs->list; ncr != NULL; ncr = ncr->next)
501 if (strcmp (outsecname, ncr->name) == 0)
502 break;
503
504 if (ncr == NULL)
505 return;
506
507 /* This section is one for which cross references are prohibited.
508 Look through the relocations, and see if any of them are to
509 INFO->H. */
510
511 symname = info->h->root.string;
512
513 relsize = bfd_get_reloc_upper_bound (abfd, sec);
514 if (relsize < 0)
515 einfo (_("%B%F: could not read relocs: %E\n"), abfd);
516 if (relsize == 0)
517 return;
518
519 relpp = (arelent **) xmalloc (relsize);
520 relcount = bfd_canonicalize_reloc (abfd, sec, relpp, info->asymbols);
521 if (relcount < 0)
522 einfo (_("%B%F: could not read relocs: %E\n"), abfd);
523
524 p = relpp;
525 pend = p + relcount;
526 for (; p < pend && *p != NULL; p++)
527 {
528 arelent *q = *p;
529
530 if (q->sym_ptr_ptr != NULL
531 && *q->sym_ptr_ptr != NULL
532 && (strcmp (bfd_asymbol_name (*q->sym_ptr_ptr), symname) == 0
533 || (info->same
534 && bfd_get_section (*q->sym_ptr_ptr) == info->defsec)))
535 {
536 /* We found a reloc for the symbol. The symbol is defined
537 in OUTSECNAME. This reloc is from a section which is
538 mapped into a section from which references to OUTSECNAME
539 are prohibited. We must report an error. */
540 einfo (_("%X%C: prohibited cross reference from %s to `%T' in %s\n"),
541 abfd, sec, q->address, outsecname,
542 bfd_asymbol_name (*q->sym_ptr_ptr), outdefsecname);
543 }
544 }
545
546 free (relpp);
547}
This page took 0.086087 seconds and 4 git commands to generate.