ldcref.c revision 78828
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_refs
77  PARAMS ((struct cref_hash_entry *, struct bfd_link_hash_entry *,
78	   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
347/* Check one symbol to see if it is a prohibited cross reference.  */
348
349static boolean
350check_nocrossref (h, ignore)
351     struct cref_hash_entry *h;
352     PTR ignore ATTRIBUTE_UNUSED;
353{
354  struct bfd_link_hash_entry *hl;
355  asection *defsec;
356  const char *defsecname;
357  struct lang_nocrossrefs *ncrs;
358  struct lang_nocrossref *ncr;
359
360  hl = bfd_link_hash_lookup (link_info.hash, h->root.string, false,
361			     false, true);
362  if (hl == NULL)
363    {
364      einfo (_("%P: symbol `%T' missing from main hash table\n"),
365	     h->root.string);
366      return true;
367    }
368
369  if (hl->type != bfd_link_hash_defined
370      && hl->type != bfd_link_hash_defweak)
371    return true;
372
373  defsec = hl->u.def.section->output_section;
374  if (defsec == NULL)
375    return true;
376  defsecname = bfd_get_section_name (defsec->owner, defsec);
377
378  for (ncrs = nocrossref_list; ncrs != NULL; ncrs = ncrs->next)
379    for (ncr = ncrs->list; ncr != NULL; ncr = ncr->next)
380      if (strcmp (ncr->name, defsecname) == 0)
381	check_refs (h, hl, ncrs);
382
383  return true;
384}
385
386/* The struct is used to pass information from check_refs to
387   check_reloc_refs through bfd_map_over_sections.  */
388
389struct check_refs_info {
390  struct cref_hash_entry *h;
391  asection *defsec;
392  struct lang_nocrossrefs *ncrs;
393  asymbol **asymbols;
394  boolean same;
395};
396
397/* This function is called for each symbol defined in a section which
398   prohibits cross references.  We need to look through all references
399   to this symbol, and ensure that the references are not from
400   prohibited sections.  */
401
402static void
403check_refs (h, hl, ncrs)
404     struct cref_hash_entry *h;
405     struct bfd_link_hash_entry *hl;
406     struct lang_nocrossrefs *ncrs;
407{
408  struct cref_ref *ref;
409
410  for (ref = h->refs; ref != NULL; ref = ref->next)
411    {
412      lang_input_statement_type *li;
413      asymbol **asymbols;
414      struct check_refs_info info;
415
416      /* We need to look through the relocations for this BFD, to see
417         if any of the relocations which refer to this symbol are from
418         a prohibited section.  Note that we need to do this even for
419         the BFD in which the symbol is defined, since even a single
420         BFD might contain a prohibited cross reference; for this
421         case, we set the SAME field in INFO, which will cause
422         CHECK_RELOCS_REFS to check for relocations against the
423         section as well as against the symbol.  */
424
425      li = (lang_input_statement_type *) ref->abfd->usrdata;
426      if (li != NULL && li->asymbols != NULL)
427	asymbols = li->asymbols;
428      else
429	{
430	  long symsize;
431	  long symbol_count;
432
433	  symsize = bfd_get_symtab_upper_bound (ref->abfd);
434	  if (symsize < 0)
435	    einfo (_("%B%F: could not read symbols; %E\n"), ref->abfd);
436	  asymbols = (asymbol **) xmalloc (symsize);
437	  symbol_count = bfd_canonicalize_symtab (ref->abfd, asymbols);
438	  if (symbol_count < 0)
439	    einfo (_("%B%F: could not read symbols: %E\n"), ref->abfd);
440	  if (li != NULL)
441	    {
442	      li->asymbols = asymbols;
443	      li->symbol_count = symbol_count;
444	    }
445	}
446
447      info.h = h;
448      info.defsec = hl->u.def.section;
449      info.ncrs = ncrs;
450      info.asymbols = asymbols;
451      if (ref->abfd == hl->u.def.section->owner)
452	info.same = true;
453      else
454	info.same = false;
455      bfd_map_over_sections (ref->abfd, check_reloc_refs, (PTR) &info);
456
457      if (li == NULL)
458	free (asymbols);
459    }
460}
461
462/* This is called via bfd_map_over_sections.  INFO->H is a symbol
463   defined in INFO->DEFSECNAME.  If this section maps into any of the
464   sections listed in INFO->NCRS, other than INFO->DEFSECNAME, then we
465   look through the relocations.  If any of the relocations are to
466   INFO->H, then we report a prohibited cross reference error.  */
467
468static void
469check_reloc_refs (abfd, sec, iarg)
470     bfd *abfd;
471     asection *sec;
472     PTR iarg;
473{
474  struct check_refs_info *info = (struct check_refs_info *) iarg;
475  asection *outsec;
476  const char *outsecname;
477  asection *outdefsec;
478  const char *outdefsecname;
479  struct lang_nocrossref *ncr;
480  const char *symname;
481  long relsize;
482  arelent **relpp;
483  long relcount;
484  arelent **p, **pend;
485
486  outsec = sec->output_section;
487  outsecname = bfd_get_section_name (outsec->owner, outsec);
488
489  outdefsec = info->defsec->output_section;
490  outdefsecname = bfd_get_section_name (outdefsec->owner, outdefsec);
491
492  /* The section where the symbol is defined is permitted.  */
493  if (strcmp (outsecname, outdefsecname) == 0)
494    return;
495
496  for (ncr = info->ncrs->list; ncr != NULL; ncr = ncr->next)
497    if (strcmp (outsecname, ncr->name) == 0)
498      break;
499
500  if (ncr == NULL)
501    return;
502
503  /* This section is one for which cross references are prohibited.
504     Look through the relocations, and see if any of them are to
505     INFO->H.  */
506
507  symname = info->h->root.string;
508
509  relsize = bfd_get_reloc_upper_bound (abfd, sec);
510  if (relsize < 0)
511    einfo (_("%B%F: could not read relocs: %E\n"), abfd);
512  if (relsize == 0)
513    return;
514
515  relpp = (arelent **) xmalloc (relsize);
516  relcount = bfd_canonicalize_reloc (abfd, sec, relpp, info->asymbols);
517  if (relcount < 0)
518    einfo (_("%B%F: could not read relocs: %E\n"), abfd);
519
520  p = relpp;
521  pend = p + relcount;
522  for (; p < pend && *p != NULL; p++)
523    {
524      arelent *q = *p;
525
526      if (q->sym_ptr_ptr != NULL
527	  && *q->sym_ptr_ptr != NULL
528	  && (strcmp (bfd_asymbol_name (*q->sym_ptr_ptr), symname) == 0
529	      || (info->same
530		  && bfd_get_section (*q->sym_ptr_ptr) == info->defsec)))
531	{
532	  /* We found a reloc for the symbol.  The symbol is defined
533             in OUTSECNAME.  This reloc is from a section which is
534             mapped into a section from which references to OUTSECNAME
535             are prohibited.  We must report an error.  */
536	  einfo (_("%X%C: prohibited cross reference from %s to `%T' in %s\n"),
537		 abfd, sec, q->address, outsecname,
538		 bfd_asymbol_name (*q->sym_ptr_ptr), outdefsecname);
539	}
540    }
541
542  free (relpp);
543}
544