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