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