]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - contrib/binutils/ld/ldcref.c
Merge ^vendor/binutils/dist@214082 into contrib/binutils.
[FreeBSD/FreeBSD.git] / contrib / binutils / ld / ldcref.c
1 /* ldcref.c -- output a cross reference table
2    Copyright 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2006
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., 51 Franklin Street - Fifth Floor, Boston, MA 02110-1301, 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 #include "objalloc.h"
31
32 #include "ld.h"
33 #include "ldmain.h"
34 #include "ldmisc.h"
35 #include "ldexp.h"
36 #include "ldlang.h"
37
38 /* We keep an instance of this structure for each reference to a
39    symbol from a given object.  */
40
41 struct cref_ref {
42   /* The next reference.  */
43   struct cref_ref *next;
44   /* The object.  */
45   bfd *abfd;
46   /* True if the symbol is defined.  */
47   unsigned int def : 1;
48   /* True if the symbol is common.  */
49   unsigned int common : 1;
50   /* True if the symbol is undefined.  */
51   unsigned int undef : 1;
52 };
53
54 /* We keep a hash table of symbols.  Each entry looks like this.  */
55
56 struct cref_hash_entry {
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
66 struct cref_hash_table {
67   struct bfd_hash_table root;
68 };
69
70 /* Forward declarations.  */
71
72 static void output_one_cref (FILE *, struct cref_hash_entry *);
73 static void check_local_sym_xref (lang_input_statement_type *);
74 static bfd_boolean check_nocrossref (struct cref_hash_entry *, void *);
75 static void check_refs (const char *, bfd_boolean, asection *, bfd *,
76                         struct lang_nocrossrefs *);
77 static void check_reloc_refs (bfd *, asection *, void *);
78
79 /* Look up an entry in the cref hash table.  */
80
81 #define cref_hash_lookup(table, string, create, copy)           \
82   ((struct cref_hash_entry *)                                   \
83    bfd_hash_lookup (&(table)->root, (string), (create), (copy)))
84
85 /* Traverse the cref hash table.  */
86
87 #define cref_hash_traverse(table, func, info)                           \
88   (bfd_hash_traverse                                                    \
89    (&(table)->root,                                                     \
90     (bfd_boolean (*) (struct bfd_hash_entry *, void *)) (func),         \
91     (info)))
92
93 /* The cref hash table.  */
94
95 static struct cref_hash_table cref_table;
96
97 /* Whether the cref hash table has been initialized.  */
98
99 static bfd_boolean cref_initialized;
100
101 /* The number of symbols seen so far.  */
102
103 static size_t cref_symcount;
104
105 /* Used to take a snapshot of the cref hash table when starting to
106    add syms from an as-needed library.  */
107 static struct bfd_hash_entry **old_table;
108 static unsigned int old_size;
109 static void *old_tab;
110 static void *alloc_mark;
111 static size_t tabsize, entsize, refsize;
112 static size_t old_symcount;
113
114 /* Create an entry in a cref hash table.  */
115
116 static struct bfd_hash_entry *
117 cref_hash_newfunc (struct bfd_hash_entry *entry,
118                    struct bfd_hash_table *table,
119                    const char *string)
120 {
121   struct cref_hash_entry *ret = (struct cref_hash_entry *) entry;
122
123   /* Allocate the structure if it has not already been allocated by a
124      subclass.  */
125   if (ret == NULL)
126     ret = ((struct cref_hash_entry *)
127            bfd_hash_allocate (table, sizeof (struct cref_hash_entry)));
128   if (ret == NULL)
129     return NULL;
130
131   /* Call the allocation method of the superclass.  */
132   ret = ((struct cref_hash_entry *)
133          bfd_hash_newfunc ((struct bfd_hash_entry *) ret, table, string));
134   if (ret != NULL)
135     {
136       /* Set local fields.  */
137       ret->demangled = NULL;
138       ret->refs = NULL;
139
140       /* Keep a count of the number of entries created in the hash
141          table.  */
142       ++cref_symcount;
143     }
144
145   return &ret->root;
146 }
147
148 /* Add a symbol to the cref hash table.  This is called for every
149    global symbol that is seen during the link.  */
150
151 void
152 add_cref (const char *name,
153           bfd *abfd,
154           asection *section,
155           bfd_vma value ATTRIBUTE_UNUSED)
156 {
157   struct cref_hash_entry *h;
158   struct cref_ref *r;
159
160   if (! cref_initialized)
161     {
162       if (!bfd_hash_table_init (&cref_table.root, cref_hash_newfunc,
163                                 sizeof (struct cref_hash_entry)))
164         einfo (_("%X%P: bfd_hash_table_init of cref table failed: %E\n"));
165       cref_initialized = TRUE;
166     }
167
168   h = cref_hash_lookup (&cref_table, name, TRUE, FALSE);
169   if (h == NULL)
170     einfo (_("%X%P: cref_hash_lookup failed: %E\n"));
171
172   for (r = h->refs; r != NULL; r = r->next)
173     if (r->abfd == abfd)
174       break;
175
176   if (r == NULL)
177     {
178       r = bfd_hash_allocate (&cref_table.root, sizeof *r);
179       if (r == NULL)
180         einfo (_("%X%P: cref alloc failed: %E\n"));
181       r->next = h->refs;
182       h->refs = r;
183       r->abfd = abfd;
184       r->def = FALSE;
185       r->common = FALSE;
186       r->undef = FALSE;
187     }
188
189   if (bfd_is_und_section (section))
190     r->undef = TRUE;
191   else if (bfd_is_com_section (section))
192     r->common = TRUE;
193   else
194     r->def = TRUE;
195 }
196
197 /* Called before loading an as-needed library to take a snapshot of
198    the cref hash table, and after we have loaded or found that the
199    library was not needed.  */
200
201 bfd_boolean
202 handle_asneeded_cref (bfd *abfd ATTRIBUTE_UNUSED,
203                       enum notice_asneeded_action act)
204 {
205   unsigned int i;
206
207   if (!cref_initialized)
208     return TRUE;
209
210   if (act == notice_as_needed)
211     {
212       char *old_ent, *old_ref;
213
214       for (i = 0; i < cref_table.root.size; i++)
215         {
216           struct bfd_hash_entry *p;
217           struct cref_hash_entry *c;
218           struct cref_ref *r;
219
220           for (p = cref_table.root.table[i]; p != NULL; p = p->next)
221             {
222               entsize += cref_table.root.entsize;
223               c = (struct cref_hash_entry *) p;
224               for (r = c->refs; r != NULL; r = r->next)
225                 refsize += sizeof (struct cref_hash_entry);
226             }
227         }
228
229       tabsize = cref_table.root.size * sizeof (struct bfd_hash_entry *);
230       old_tab = xmalloc (tabsize + entsize + refsize);
231
232       alloc_mark = bfd_hash_allocate (&cref_table.root, 1);
233       if (alloc_mark == NULL)
234         return FALSE;
235
236       memcpy (old_tab, cref_table.root.table, tabsize);
237       old_ent = (char *) old_tab + tabsize;
238       old_ref = (char *) old_ent + entsize;
239       old_table = cref_table.root.table;
240       old_size = cref_table.root.size;
241       old_symcount = cref_symcount;
242
243       for (i = 0; i < cref_table.root.size; i++)
244         {
245           struct bfd_hash_entry *p;
246           struct cref_hash_entry *c;
247           struct cref_ref *r;
248
249           for (p = cref_table.root.table[i]; p != NULL; p = p->next)
250             {
251               memcpy (old_ent, p, cref_table.root.entsize);
252               old_ent = (char *) old_ent + cref_table.root.entsize;
253               c = (struct cref_hash_entry *) p;
254               for (r = c->refs; r != NULL; r = r->next)
255                 {
256                   memcpy (old_ref, r, sizeof (struct cref_hash_entry));
257                   old_ref = (char *) old_ref + sizeof (struct cref_hash_entry);
258                 }
259             }
260         }
261       return TRUE;
262     }
263
264   if (act == notice_not_needed)
265     {
266       char *old_ent, *old_ref;
267
268       if (old_tab == NULL)
269         {
270           /* The only way old_tab can be NULL is if the cref hash table
271              had not been initialised when notice_as_needed.  */
272           bfd_hash_table_free (&cref_table.root);
273           cref_initialized = FALSE;
274           return TRUE;
275         }
276
277       old_ent = (char *) old_tab + tabsize;
278       old_ref = (char *) old_ent + entsize;
279       cref_table.root.table = old_table;
280       cref_table.root.size = old_size;
281       memcpy (cref_table.root.table, old_tab, tabsize);
282       cref_symcount = old_symcount;
283
284       for (i = 0; i < cref_table.root.size; i++)
285         {
286           struct bfd_hash_entry *p;
287           struct cref_hash_entry *c;
288           struct cref_ref *r;
289
290           for (p = cref_table.root.table[i]; p != NULL; p = p->next)
291             {
292               memcpy (p, old_ent, cref_table.root.entsize);
293               old_ent = (char *) old_ent + cref_table.root.entsize;
294               c = (struct cref_hash_entry *) p;
295               for (r = c->refs; r != NULL; r = r->next)
296                 {
297                   memcpy (r, old_ref, sizeof (struct cref_hash_entry));
298                   old_ref = (char *) old_ref + sizeof (struct cref_hash_entry);
299                 }
300             }
301         }
302
303       objalloc_free_block ((struct objalloc *) cref_table.root.memory,
304                            alloc_mark);
305     }
306   else if (act != notice_needed)
307     return FALSE;
308
309   free (old_tab);
310   old_tab = NULL;
311   return TRUE;
312 }
313
314 /* Copy the addresses of the hash table entries into an array.  This
315    is called via cref_hash_traverse.  We also fill in the demangled
316    name.  */
317
318 static bfd_boolean
319 cref_fill_array (struct cref_hash_entry *h, void *data)
320 {
321   struct cref_hash_entry ***pph = data;
322
323   ASSERT (h->demangled == NULL);
324   h->demangled = demangle (h->root.string);
325
326   **pph = h;
327
328   ++*pph;
329
330   return TRUE;
331 }
332
333 /* Sort an array of cref hash table entries by name.  */
334
335 static int
336 cref_sort_array (const void *a1, const void *a2)
337 {
338   const struct cref_hash_entry * const *p1 = a1;
339   const struct cref_hash_entry * const *p2 = a2;
340
341   return strcmp ((*p1)->demangled, (*p2)->demangled);
342 }
343
344 /* Write out the cref table.  */
345
346 #define FILECOL (50)
347
348 void
349 output_cref (FILE *fp)
350 {
351   int len;
352   struct cref_hash_entry **csyms, **csym_fill, **csym, **csym_end;
353   const char *msg;
354
355   fprintf (fp, _("\nCross Reference Table\n\n"));
356   msg = _("Symbol");
357   fprintf (fp, "%s", msg);
358   len = strlen (msg);
359   while (len < FILECOL)
360     {
361       putc (' ', fp);
362       ++len;
363     }
364   fprintf (fp, _("File\n"));
365
366   if (! cref_initialized)
367     {
368       fprintf (fp, _("No symbols\n"));
369       return;
370     }
371
372   csyms = xmalloc (cref_symcount * sizeof (*csyms));
373
374   csym_fill = csyms;
375   cref_hash_traverse (&cref_table, cref_fill_array, &csym_fill);
376   ASSERT ((size_t) (csym_fill - csyms) == cref_symcount);
377
378   qsort (csyms, cref_symcount, sizeof (*csyms), cref_sort_array);
379
380   csym_end = csyms + cref_symcount;
381   for (csym = csyms; csym < csym_end; csym++)
382     output_one_cref (fp, *csym);
383 }
384
385 /* Output one entry in the cross reference table.  */
386
387 static void
388 output_one_cref (FILE *fp, struct cref_hash_entry *h)
389 {
390   int len;
391   struct bfd_link_hash_entry *hl;
392   struct cref_ref *r;
393
394   hl = bfd_link_hash_lookup (link_info.hash, h->root.string, FALSE,
395                              FALSE, TRUE);
396   if (hl == NULL)
397     einfo ("%P: symbol `%T' missing from main hash table\n",
398            h->root.string);
399   else
400     {
401       /* If this symbol is defined in a dynamic object but never
402          referenced by a normal object, then don't print it.  */
403       if (hl->type == bfd_link_hash_defined)
404         {
405           if (hl->u.def.section->output_section == NULL)
406             return;
407           if (hl->u.def.section->owner != NULL
408               && (hl->u.def.section->owner->flags & DYNAMIC) != 0)
409             {
410               for (r = h->refs; r != NULL; r = r->next)
411                 if ((r->abfd->flags & DYNAMIC) == 0)
412                   break;
413               if (r == NULL)
414                 return;
415             }
416         }
417     }
418
419   fprintf (fp, "%s ", h->demangled);
420   len = strlen (h->demangled) + 1;
421
422   for (r = h->refs; r != NULL; r = r->next)
423     {
424       if (r->def)
425         {
426           while (len < FILECOL)
427             {
428               putc (' ', fp);
429               ++len;
430             }
431           lfinfo (fp, "%B\n", r->abfd);
432           len = 0;
433         }
434     }
435
436   for (r = h->refs; r != NULL; r = r->next)
437     {
438       if (! r->def)
439         {
440           while (len < FILECOL)
441             {
442               putc (' ', fp);
443               ++len;
444             }
445           lfinfo (fp, "%B\n", r->abfd);
446           len = 0;
447         }
448     }
449
450   ASSERT (len == 0);
451 }
452
453 /* Check for prohibited cross references.  */
454
455 void
456 check_nocrossrefs (void)
457 {
458   if (! cref_initialized)
459     return;
460
461   cref_hash_traverse (&cref_table, check_nocrossref, NULL);
462
463   lang_for_each_file (check_local_sym_xref);
464 }
465
466 /* Check for prohibited cross references to local and section symbols.  */
467
468 static void
469 check_local_sym_xref (lang_input_statement_type *statement)
470 {
471   bfd *abfd;
472   lang_input_statement_type *li;
473   asymbol **asymbols, **syms;
474
475   abfd = statement->the_bfd;
476   if (abfd == NULL)
477     return;
478
479   li = abfd->usrdata;
480   if (li != NULL && li->asymbols != NULL)
481     asymbols = li->asymbols;
482   else
483     {
484       long symsize;
485       long symbol_count;
486
487       symsize = bfd_get_symtab_upper_bound (abfd);
488       if (symsize < 0)
489         einfo (_("%B%F: could not read symbols; %E\n"), abfd);
490       asymbols = xmalloc (symsize);
491       symbol_count = bfd_canonicalize_symtab (abfd, asymbols);
492       if (symbol_count < 0)
493         einfo (_("%B%F: could not read symbols: %E\n"), abfd);
494       if (li != NULL)
495         {
496           li->asymbols = asymbols;
497           li->symbol_count = symbol_count;
498         }
499     }
500
501   for (syms = asymbols; *syms; ++syms)
502     {
503       asymbol *sym = *syms;
504       if (sym->flags & (BSF_GLOBAL | BSF_WARNING | BSF_INDIRECT | BSF_FILE))
505         continue;
506       if ((sym->flags & (BSF_LOCAL | BSF_SECTION_SYM)) != 0
507           && sym->section->output_section != NULL)
508         {
509           const char *outsecname, *symname;
510           struct lang_nocrossrefs *ncrs;
511           struct lang_nocrossref *ncr;
512
513           outsecname = sym->section->output_section->name;
514           symname = NULL;
515           if ((sym->flags & BSF_SECTION_SYM) == 0)
516             symname = sym->name;
517           for (ncrs = nocrossref_list; ncrs != NULL; ncrs = ncrs->next)
518             for (ncr = ncrs->list; ncr != NULL; ncr = ncr->next)
519               if (strcmp (ncr->name, outsecname) == 0)
520                 check_refs (symname, FALSE, sym->section, abfd, ncrs);
521         }
522     }
523
524   if (li == NULL)
525     free (asymbols);
526 }
527
528 /* Check one symbol to see if it is a prohibited cross reference.  */
529
530 static bfd_boolean
531 check_nocrossref (struct cref_hash_entry *h, void *ignore ATTRIBUTE_UNUSED)
532 {
533   struct bfd_link_hash_entry *hl;
534   asection *defsec;
535   const char *defsecname;
536   struct lang_nocrossrefs *ncrs;
537   struct lang_nocrossref *ncr;
538   struct cref_ref *ref;
539
540   hl = bfd_link_hash_lookup (link_info.hash, h->root.string, FALSE,
541                              FALSE, TRUE);
542   if (hl == NULL)
543     {
544       einfo (_("%P: symbol `%T' missing from main hash table\n"),
545              h->root.string);
546       return TRUE;
547     }
548
549   if (hl->type != bfd_link_hash_defined
550       && hl->type != bfd_link_hash_defweak)
551     return TRUE;
552
553   defsec = hl->u.def.section->output_section;
554   if (defsec == NULL)
555     return TRUE;
556   defsecname = bfd_get_section_name (defsec->owner, defsec);
557
558   for (ncrs = nocrossref_list; ncrs != NULL; ncrs = ncrs->next)
559     for (ncr = ncrs->list; ncr != NULL; ncr = ncr->next)
560       if (strcmp (ncr->name, defsecname) == 0)
561         for (ref = h->refs; ref != NULL; ref = ref->next)
562           check_refs (hl->root.string, TRUE, hl->u.def.section,
563                       ref->abfd, ncrs);
564
565   return TRUE;
566 }
567
568 /* The struct is used to pass information from check_refs to
569    check_reloc_refs through bfd_map_over_sections.  */
570
571 struct check_refs_info {
572   const char *sym_name;
573   asection *defsec;
574   struct lang_nocrossrefs *ncrs;
575   asymbol **asymbols;
576   bfd_boolean global;
577 };
578
579 /* This function is called for each symbol defined in a section which
580    prohibits cross references.  We need to look through all references
581    to this symbol, and ensure that the references are not from
582    prohibited sections.  */
583
584 static void
585 check_refs (const char *name,
586             bfd_boolean global,
587             asection *sec,
588             bfd *abfd,
589             struct lang_nocrossrefs *ncrs)
590 {
591   lang_input_statement_type *li;
592   asymbol **asymbols;
593   struct check_refs_info info;
594
595   /* We need to look through the relocations for this BFD, to see
596      if any of the relocations which refer to this symbol are from
597      a prohibited section.  Note that we need to do this even for
598      the BFD in which the symbol is defined, since even a single
599      BFD might contain a prohibited cross reference.  */
600
601   li = abfd->usrdata;
602   if (li != NULL && li->asymbols != NULL)
603     asymbols = li->asymbols;
604   else
605     {
606       long symsize;
607       long symbol_count;
608
609       symsize = bfd_get_symtab_upper_bound (abfd);
610       if (symsize < 0)
611         einfo (_("%B%F: could not read symbols; %E\n"), abfd);
612       asymbols = xmalloc (symsize);
613       symbol_count = bfd_canonicalize_symtab (abfd, asymbols);
614       if (symbol_count < 0)
615         einfo (_("%B%F: could not read symbols: %E\n"), abfd);
616       if (li != NULL)
617         {
618           li->asymbols = asymbols;
619           li->symbol_count = symbol_count;
620         }
621     }
622
623   info.sym_name = name;
624   info.global = global;
625   info.defsec = sec;
626   info.ncrs = ncrs;
627   info.asymbols = asymbols;
628   bfd_map_over_sections (abfd, check_reloc_refs, &info);
629
630   if (li == NULL)
631     free (asymbols);
632 }
633
634 /* This is called via bfd_map_over_sections.  INFO->SYM_NAME is a symbol
635    defined in INFO->DEFSECNAME.  If this section maps into any of the
636    sections listed in INFO->NCRS, other than INFO->DEFSECNAME, then we
637    look through the relocations.  If any of the relocations are to
638    INFO->SYM_NAME, then we report a prohibited cross reference error.  */
639
640 static void
641 check_reloc_refs (bfd *abfd, asection *sec, void *iarg)
642 {
643   struct check_refs_info *info = iarg;
644   asection *outsec;
645   const char *outsecname;
646   asection *outdefsec;
647   const char *outdefsecname;
648   struct lang_nocrossref *ncr;
649   const char *symname;
650   bfd_boolean global;
651   long relsize;
652   arelent **relpp;
653   long relcount;
654   arelent **p, **pend;
655
656   outsec = sec->output_section;
657   outsecname = bfd_get_section_name (outsec->owner, outsec);
658
659   outdefsec = info->defsec->output_section;
660   outdefsecname = bfd_get_section_name (outdefsec->owner, outdefsec);
661
662   /* The section where the symbol is defined is permitted.  */
663   if (strcmp (outsecname, outdefsecname) == 0)
664     return;
665
666   for (ncr = info->ncrs->list; ncr != NULL; ncr = ncr->next)
667     if (strcmp (outsecname, ncr->name) == 0)
668       break;
669
670   if (ncr == NULL)
671     return;
672
673   /* This section is one for which cross references are prohibited.
674      Look through the relocations, and see if any of them are to
675      INFO->SYM_NAME.  If INFO->SYMNAME is NULL, check for relocations
676      against the section symbol.  If INFO->GLOBAL is TRUE, the
677      definition is global, check for relocations against the global
678      symbols.  Otherwise check for relocations against the local and
679      section symbols.  */
680
681   symname = info->sym_name;
682   global = info->global;
683
684   relsize = bfd_get_reloc_upper_bound (abfd, sec);
685   if (relsize < 0)
686     einfo (_("%B%F: could not read relocs: %E\n"), abfd);
687   if (relsize == 0)
688     return;
689
690   relpp = xmalloc (relsize);
691   relcount = bfd_canonicalize_reloc (abfd, sec, relpp, info->asymbols);
692   if (relcount < 0)
693     einfo (_("%B%F: could not read relocs: %E\n"), abfd);
694
695   p = relpp;
696   pend = p + relcount;
697   for (; p < pend && *p != NULL; p++)
698     {
699       arelent *q = *p;
700
701       if (q->sym_ptr_ptr != NULL
702           && *q->sym_ptr_ptr != NULL
703           && ((global
704                && (bfd_is_und_section (bfd_get_section (*q->sym_ptr_ptr))
705                    || bfd_is_com_section (bfd_get_section (*q->sym_ptr_ptr))
706                    || ((*q->sym_ptr_ptr)->flags & (BSF_GLOBAL
707                                                    | BSF_WEAK)) != 0))
708               || (!global
709                   && ((*q->sym_ptr_ptr)->flags & (BSF_LOCAL
710                                                   | BSF_SECTION_SYM)) != 0))
711           && (symname != NULL
712               ? strcmp (bfd_asymbol_name (*q->sym_ptr_ptr), symname) == 0
713               : (((*q->sym_ptr_ptr)->flags & BSF_SECTION_SYM) != 0
714                  && bfd_get_section (*q->sym_ptr_ptr) == info->defsec)))
715         {
716           /* We found a reloc for the symbol.  The symbol is defined
717              in OUTSECNAME.  This reloc is from a section which is
718              mapped into a section from which references to OUTSECNAME
719              are prohibited.  We must report an error.  */
720           einfo (_("%X%C: prohibited cross reference from %s to `%T' in %s\n"),
721                  abfd, sec, q->address, outsecname,
722                  bfd_asymbol_name (*q->sym_ptr_ptr), outdefsecname);
723         }
724     }
725
726   free (relpp);
727 }