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