This commit was generated by cvs2svn to track changes on a CVS vendor
[external/binutils.git] / ld / ldcref.c
1 /* ldcref.c -- output a cross reference table
2    Copyright (C) 1996, 1997, 1998, 1999 Free Software Foundation, Inc.
3    Written by Ian Lance Taylor <ian@cygnus.com>
4
5 This file is part of GLD, the Gnu Linker.
6
7 This program is free software; you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
9 the Free Software Foundation; either version 2 of the License, or
10 (at your option) any later version.
11
12 This program is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15 GNU General Public License for more details.
16
17 You should have received a copy of the GNU General Public License
18 along with this program; if not, write to the Free Software
19 Foundation, 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
39 struct 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
55 struct 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
66 struct cref_hash_table
67 {
68   struct bfd_hash_table root;
69 };
70
71 /* Local functions.  */
72
73 static struct bfd_hash_entry *cref_hash_newfunc
74   PARAMS ((struct bfd_hash_entry *, struct bfd_hash_table *, const char *));
75 static boolean cref_fill_array PARAMS ((struct cref_hash_entry *, PTR));
76 static int cref_sort_array PARAMS ((const PTR, const PTR));
77 static void output_one_cref PARAMS ((FILE *, struct cref_hash_entry *));
78 static boolean check_nocrossref PARAMS ((struct cref_hash_entry *, PTR));
79 static void check_refs
80   PARAMS ((struct cref_hash_entry *, struct bfd_link_hash_entry *,
81            struct lang_nocrossrefs *));
82 static 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
100 static struct cref_hash_table cref_table;
101
102 /* Whether the cref hash table has been initialized.  */
103
104 static boolean cref_initialized;
105
106 /* The number of symbols seen so far.  */
107
108 static size_t cref_symcount;
109
110 /* Create an entry in a cref hash table.  */
111
112 static struct bfd_hash_entry *
113 cref_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*/
149 void
150 add_cref (name, abfd, section, value)
151      const char *name;
152      bfd *abfd;
153      asection *section;
154      bfd_vma value ATTRIBUTE_UNUSED;
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
197 static boolean
198 cref_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
216 static int
217 cref_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
231 void
232 output_cref (fp)
233      FILE *fp;
234 {
235   int len;
236   struct cref_hash_entry **csyms, **csym_fill, **csym, **csym_end;
237   const char *msg;
238
239   fprintf (fp, _("\nCross Reference Table\n\n"));
240   msg = _("Symbol");
241   fprintf (fp, msg);
242   len = strlen (msg);
243   while (len < FILECOL)
244     {
245       putc (' ' , fp);
246       ++len;
247     }
248   fprintf (fp, _("File\n"));
249
250   if (! cref_initialized)
251     {
252       fprintf (fp, _("No symbols\n"));
253       return;
254     }
255
256   csyms = ((struct cref_hash_entry **)
257            xmalloc (cref_symcount * sizeof (*csyms)));
258
259   csym_fill = csyms;
260   cref_hash_traverse (&cref_table, cref_fill_array, &csym_fill);
261   ASSERT ((size_t) (csym_fill - csyms) == cref_symcount);
262
263   qsort (csyms, cref_symcount, sizeof (*csyms), cref_sort_array);
264
265   csym_end = csyms + cref_symcount;
266   for (csym = csyms; csym < csym_end; csym++)
267     output_one_cref (fp, *csym);
268 }
269
270 /* Output one entry in the cross reference table.  */
271
272 static void
273 output_one_cref (fp, h)
274      FILE *fp;
275      struct cref_hash_entry *h;
276 {
277   int len;
278   struct bfd_link_hash_entry *hl;
279   struct cref_ref *r;
280
281   hl = bfd_link_hash_lookup (link_info.hash, h->root.string, false,
282                              false, true);
283   if (hl == NULL)
284     einfo ("%P: symbol `%T' missing from main hash table\n",
285            h->root.string);
286   else
287     {
288       /* If this symbol is defined in a dynamic object but never
289          referenced by a normal object, then don't print it.  */
290       if (hl->type == bfd_link_hash_defined)
291         {
292           if (hl->u.def.section->output_section == NULL)
293             return;
294           if (hl->u.def.section->owner != NULL
295               && (hl->u.def.section->owner->flags & DYNAMIC) != 0)
296             {
297               for (r = h->refs; r != NULL; r = r->next)
298                 if ((r->abfd->flags & DYNAMIC) == 0)
299                   break;
300               if (r == NULL)
301                 return;
302             }
303         }
304     }
305
306   fprintf (fp, "%s ", h->demangled);
307   len = strlen (h->demangled) + 1;
308
309   for (r = h->refs; r != NULL; r = r->next)
310     {
311       if (r->def)
312         {
313           while (len < FILECOL)
314             {
315               putc (' ', fp);
316               ++len;
317             }
318           lfinfo (fp, "%B\n", r->abfd);
319           len = 0;
320         }
321     }
322
323   for (r = h->refs; r != NULL; r = r->next)
324     {
325       if (! r->def)
326         {
327           while (len < FILECOL)
328             {
329               putc (' ', fp);
330               ++len;
331             }
332           lfinfo (fp, "%B\n", r->abfd);
333           len = 0;
334         }
335     }
336
337   ASSERT (len == 0);
338 }
339
340 /* Check for prohibited cross references.  */
341
342 void
343 check_nocrossrefs ()
344 {
345   if (! cref_initialized)
346     return;
347
348   cref_hash_traverse (&cref_table, check_nocrossref, (PTR) NULL);
349 }
350
351 /* Check one symbol to see if it is a prohibited cross reference.  */
352
353 /*ARGSUSED*/
354 static boolean
355 check_nocrossref (h, ignore)
356      struct cref_hash_entry *h;
357      PTR ignore ATTRIBUTE_UNUSED;
358 {
359   struct bfd_link_hash_entry *hl;
360   asection *defsec;
361   const char *defsecname;
362   struct lang_nocrossrefs *ncrs;
363   struct lang_nocrossref *ncr;
364
365   hl = bfd_link_hash_lookup (link_info.hash, h->root.string, false,
366                              false, true);
367   if (hl == NULL)
368     {
369       einfo (_("%P: symbol `%T' missing from main hash table\n"),
370              h->root.string);
371       return true;
372     }
373
374   if (hl->type != bfd_link_hash_defined
375       && hl->type != bfd_link_hash_defweak)
376     return true;
377
378   defsec = hl->u.def.section->output_section;
379   if (defsec == NULL)
380     return true;
381   defsecname = bfd_get_section_name (defsec->owner, defsec);
382
383   for (ncrs = nocrossref_list; ncrs != NULL; ncrs = ncrs->next)
384     for (ncr = ncrs->list; ncr != NULL; ncr = ncr->next)
385       if (strcmp (ncr->name, defsecname) == 0)
386         check_refs (h, hl, ncrs);
387
388   return true;
389 }
390
391 /* The struct is used to pass information from check_refs to
392    check_reloc_refs through bfd_map_over_sections.  */
393
394 struct check_refs_info
395 {
396   struct cref_hash_entry *h;
397   asection *defsec;
398   struct lang_nocrossrefs *ncrs;
399   asymbol **asymbols;
400   boolean same;
401 };
402
403 /* This function is called for each symbol defined in a section which
404    prohibits cross references.  We need to look through all references
405    to this symbol, and ensure that the references are not from
406    prohibited sections.  */
407
408 static void
409 check_refs (h, hl, ncrs)
410      struct cref_hash_entry *h;
411      struct bfd_link_hash_entry *hl;
412      struct lang_nocrossrefs *ncrs;
413 {
414   struct cref_ref *ref;
415
416   for (ref = h->refs; ref != NULL; ref = ref->next)
417     {
418       lang_input_statement_type *li;
419       asymbol **asymbols;
420       struct check_refs_info info;
421
422       /* We need to look through the relocations for this BFD, to see
423          if any of the relocations which refer to this symbol are from
424          a prohibited section.  Note that we need to do this even for
425          the BFD in which the symbol is defined, since even a single
426          BFD might contain a prohibited cross reference; for this
427          case, we set the SAME field in INFO, which will cause
428          CHECK_RELOCS_REFS to check for relocations against the
429          section as well as against the symbol.  */
430
431       li = (lang_input_statement_type *) ref->abfd->usrdata;
432       if (li != NULL && li->asymbols != NULL)
433         asymbols = li->asymbols;
434       else
435         {
436           long symsize;
437           long symbol_count;
438
439           symsize = bfd_get_symtab_upper_bound (ref->abfd);
440           if (symsize < 0)
441             einfo (_("%B%F: could not read symbols; %E\n"), ref->abfd);
442           asymbols = (asymbol **) xmalloc (symsize);
443           symbol_count = bfd_canonicalize_symtab (ref->abfd, asymbols);
444           if (symbol_count < 0)
445             einfo (_("%B%F: could not read symbols: %E\n"), ref->abfd);
446           if (li != NULL)
447             {
448               li->asymbols = asymbols;
449               li->symbol_count = symbol_count;
450             }
451         }
452
453       info.h = h;
454       info.defsec = hl->u.def.section;
455       info.ncrs = ncrs;
456       info.asymbols = asymbols;
457       if (ref->abfd == hl->u.def.section->owner)
458         info.same = true;
459       else
460         info.same = false;
461       bfd_map_over_sections (ref->abfd, check_reloc_refs, (PTR) &info);
462
463       if (li == NULL)
464         free (asymbols);
465     }
466 }
467
468 /* This is called via bfd_map_over_sections.  INFO->H is a symbol
469    defined in INFO->DEFSECNAME.  If this section maps into any of the
470    sections listed in INFO->NCRS, other than INFO->DEFSECNAME, then we
471    look through the relocations.  If any of the relocations are to
472    INFO->H, then we report a prohibited cross reference error.  */
473
474 static void
475 check_reloc_refs (abfd, sec, iarg)
476      bfd *abfd;
477      asection *sec;
478      PTR iarg;
479 {
480   struct check_refs_info *info = (struct check_refs_info *) iarg;
481   asection *outsec;
482   const char *outsecname;
483   asection *outdefsec;
484   const char *outdefsecname;
485   struct lang_nocrossref *ncr;
486   const char *symname;
487   long relsize;
488   arelent **relpp;
489   long relcount;
490   arelent **p, **pend;
491
492   outsec = sec->output_section;
493   outsecname = bfd_get_section_name (outsec->owner, outsec);
494
495   outdefsec = info->defsec->output_section;
496   outdefsecname = bfd_get_section_name (outdefsec->owner, outdefsec);
497
498   /* The section where the symbol is defined is permitted.  */
499   if (strcmp (outsecname, outdefsecname) == 0)
500     return;
501
502   for (ncr = info->ncrs->list; ncr != NULL; ncr = ncr->next)
503     if (strcmp (outsecname, ncr->name) == 0)
504       break;
505
506   if (ncr == NULL)
507     return;
508
509   /* This section is one for which cross references are prohibited.
510      Look through the relocations, and see if any of them are to
511      INFO->H.  */
512
513   symname = info->h->root.string;
514
515   relsize = bfd_get_reloc_upper_bound (abfd, sec);
516   if (relsize < 0)
517     einfo (_("%B%F: could not read relocs: %E\n"), abfd);
518   if (relsize == 0)
519     return;
520
521   relpp = (arelent **) xmalloc (relsize);
522   relcount = bfd_canonicalize_reloc (abfd, sec, relpp, info->asymbols);
523   if (relcount < 0)
524     einfo (_("%B%F: could not read relocs: %E\n"), abfd);
525
526   p = relpp;
527   pend = p + relcount;
528   for (; p < pend && *p != NULL; p++)
529     {
530       arelent *q = *p;
531
532       if (q->sym_ptr_ptr != NULL
533           && *q->sym_ptr_ptr != NULL
534           && (strcmp (bfd_asymbol_name (*q->sym_ptr_ptr), symname) == 0
535               || (info->same
536                   && bfd_get_section (*q->sym_ptr_ptr) == info->defsec)))
537         {
538           /* We found a reloc for the symbol.  The symbol is defined
539              in OUTSECNAME.  This reloc is from a section which is
540              mapped into a section from which references to OUTSECNAME
541              are prohibited.  We must report an error.  */
542           einfo (_("%X%C: prohibited cross reference from %s to `%T' in %s\n"),
543                  abfd, sec, q->address, outsecname,
544                  bfd_asymbol_name (*q->sym_ptr_ptr), outdefsecname);
545         }
546     }
547
548   free (relpp);
549 }