1 /* ldcref.c -- output a cross reference table
2    Copyright 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004
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 
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 *
cref_hash_newfunc(struct bfd_hash_entry * entry,struct bfd_hash_table * table,const char * string)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
add_cref(const char * name,bfd * abfd,asection * section,bfd_vma value ATTRIBUTE_UNUSED)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
cref_fill_array(struct cref_hash_entry * h,void * data)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
cref_sort_array(const void * a1,const void * a2)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
output_cref(FILE * fp)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
output_one_cref(FILE * fp,struct cref_hash_entry * h)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
check_nocrossrefs(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
check_local_sym_xref(lang_input_statement_type * statement)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
check_nocrossref(struct cref_hash_entry * h,void * ignore ATTRIBUTE_UNUSED)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
check_refs(const char * name,asection * sec,bfd * abfd,struct lang_nocrossrefs * ncrs)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
check_reloc_refs(bfd * abfd,asection * sec,void * iarg)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 }
581