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