2000-10-09 Kazu Hirata <kazu@hxi.com>
[deliverable/binutils-gdb.git] / ld / ldcref.c
CommitLineData
252b5132 1/* ldcref.c -- output a cross reference table
305c7206 2 Copyright (C) 1996, 97, 98, 99, 2000 Free Software Foundation, Inc.
252b5132
RH
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
89cdebba 39struct cref_ref {
252b5132
RH
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
89cdebba 54struct cref_hash_entry {
252b5132
RH
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
89cdebba 64struct cref_hash_table {
252b5132
RH
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
252b5132
RH
145void
146add_cref (name, abfd, section, value)
147 const char *name;
148 bfd *abfd;
149 asection *section;
87f2a346 150 bfd_vma value ATTRIBUTE_UNUSED;
252b5132
RH
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");
305c7206 237 fprintf (fp, "%s", msg);
252b5132
RH
238 len = strlen (msg);
239 while (len < FILECOL)
240 {
4de2d33d 241 putc (' ', fp);
252b5132
RH
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
252b5132
RH
349static boolean
350check_nocrossref (h, ignore)
351 struct cref_hash_entry *h;
87f2a346 352 PTR ignore ATTRIBUTE_UNUSED;
252b5132
RH
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
89cdebba 389struct check_refs_info {
252b5132
RH
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}
This page took 0.08871 seconds and 4 git commands to generate.