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