Re-implement ia64-linux-nat.c::ia64_linux_xfer_partial
[deliverable/binutils-gdb.git] / ld / ldcref.c
... / ...
CommitLineData
1/* ldcref.c -- output a cross reference table
2 Copyright 1996-2013 Free Software Foundation, Inc.
3 Written by Ian Lance Taylor <ian@cygnus.com>
4
5 This file is part of the GNU Binutils.
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 3 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., 51 Franklin Street - Fifth Floor, Boston,
20 MA 02110-1301, USA. */
21
22
23/* This file holds routines that manage the cross reference table.
24 The table is used to generate cross reference reports. It is also
25 used to implement the NOCROSSREFS command in the linker script. */
26
27#include "sysdep.h"
28#include "bfd.h"
29#include "bfdlink.h"
30#include "libiberty.h"
31#include "demangle.h"
32#include "objalloc.h"
33
34#include "ld.h"
35#include "ldmain.h"
36#include "ldmisc.h"
37#include "ldexp.h"
38#include "ldlang.h"
39
40/* We keep an instance of this structure for each reference to a
41 symbol from a given object. */
42
43struct cref_ref {
44 /* The next reference. */
45 struct cref_ref *next;
46 /* The object. */
47 bfd *abfd;
48 /* True if the symbol is defined. */
49 unsigned int def : 1;
50 /* True if the symbol is common. */
51 unsigned int common : 1;
52 /* True if the symbol is undefined. */
53 unsigned int undef : 1;
54};
55
56/* We keep a hash table of symbols. Each entry looks like this. */
57
58struct cref_hash_entry {
59 struct bfd_hash_entry root;
60 /* The demangled name. */
61 const char *demangled;
62 /* References to and definitions of this symbol. */
63 struct cref_ref *refs;
64};
65
66/* This is what the hash table looks like. */
67
68struct cref_hash_table {
69 struct bfd_hash_table root;
70};
71
72/* Forward declarations. */
73
74static void output_one_cref (FILE *, struct cref_hash_entry *);
75static void check_local_sym_xref (lang_input_statement_type *);
76static bfd_boolean check_nocrossref (struct cref_hash_entry *, void *);
77static void check_refs (const char *, bfd_boolean, asection *, bfd *,
78 struct lang_nocrossrefs *);
79static void check_reloc_refs (bfd *, asection *, void *);
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 (bfd_boolean (*) (struct bfd_hash_entry *, void *)) (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 bfd_boolean cref_initialized;
102
103/* The number of symbols seen so far. */
104
105static size_t cref_symcount;
106
107/* Used to take a snapshot of the cref hash table when starting to
108 add syms from an as-needed library. */
109static struct bfd_hash_entry **old_table;
110static unsigned int old_size;
111static unsigned int old_count;
112static void *old_tab;
113static void *alloc_mark;
114static size_t tabsize, entsize, refsize;
115static size_t old_symcount;
116
117/* Create an entry in a cref hash table. */
118
119static struct bfd_hash_entry *
120cref_hash_newfunc (struct bfd_hash_entry *entry,
121 struct bfd_hash_table *table,
122 const char *string)
123{
124 struct cref_hash_entry *ret = (struct cref_hash_entry *) entry;
125
126 /* Allocate the structure if it has not already been allocated by a
127 subclass. */
128 if (ret == NULL)
129 ret = ((struct cref_hash_entry *)
130 bfd_hash_allocate (table, sizeof (struct cref_hash_entry)));
131 if (ret == NULL)
132 return NULL;
133
134 /* Call the allocation method of the superclass. */
135 ret = ((struct cref_hash_entry *)
136 bfd_hash_newfunc ((struct bfd_hash_entry *) ret, table, string));
137 if (ret != NULL)
138 {
139 /* Set local fields. */
140 ret->demangled = NULL;
141 ret->refs = NULL;
142
143 /* Keep a count of the number of entries created in the hash
144 table. */
145 ++cref_symcount;
146 }
147
148 return &ret->root;
149}
150
151/* Add a symbol to the cref hash table. This is called for every
152 global symbol that is seen during the link. */
153
154void
155add_cref (const char *name,
156 bfd *abfd,
157 asection *section,
158 bfd_vma value ATTRIBUTE_UNUSED)
159{
160 struct cref_hash_entry *h;
161 struct cref_ref *r;
162
163 if (! cref_initialized)
164 {
165 if (!bfd_hash_table_init (&cref_table.root, cref_hash_newfunc,
166 sizeof (struct cref_hash_entry)))
167 einfo (_("%X%P: bfd_hash_table_init of cref table failed: %E\n"));
168 cref_initialized = TRUE;
169 }
170
171 h = cref_hash_lookup (&cref_table, name, TRUE, FALSE);
172 if (h == NULL)
173 einfo (_("%X%P: cref_hash_lookup failed: %E\n"));
174
175 for (r = h->refs; r != NULL; r = r->next)
176 if (r->abfd == abfd)
177 break;
178
179 if (r == NULL)
180 {
181 r = (struct cref_ref *) bfd_hash_allocate (&cref_table.root, sizeof *r);
182 if (r == NULL)
183 einfo (_("%X%P: cref alloc failed: %E\n"));
184 r->next = h->refs;
185 h->refs = r;
186 r->abfd = abfd;
187 r->def = FALSE;
188 r->common = FALSE;
189 r->undef = FALSE;
190 }
191
192 if (bfd_is_und_section (section))
193 r->undef = TRUE;
194 else if (bfd_is_com_section (section))
195 r->common = TRUE;
196 else
197 r->def = TRUE;
198}
199
200/* Called before loading an as-needed library to take a snapshot of
201 the cref hash table, and after we have loaded or found that the
202 library was not needed. */
203
204bfd_boolean
205handle_asneeded_cref (bfd *abfd ATTRIBUTE_UNUSED,
206 enum notice_asneeded_action act)
207{
208 unsigned int i;
209
210 if (!cref_initialized)
211 return TRUE;
212
213 if (act == notice_as_needed)
214 {
215 char *old_ent, *old_ref;
216
217 for (i = 0; i < cref_table.root.size; i++)
218 {
219 struct bfd_hash_entry *p;
220 struct cref_hash_entry *c;
221 struct cref_ref *r;
222
223 for (p = cref_table.root.table[i]; p != NULL; p = p->next)
224 {
225 entsize += cref_table.root.entsize;
226 c = (struct cref_hash_entry *) p;
227 for (r = c->refs; r != NULL; r = r->next)
228 refsize += sizeof (struct cref_ref);
229 }
230 }
231
232 tabsize = cref_table.root.size * sizeof (struct bfd_hash_entry *);
233 old_tab = xmalloc (tabsize + entsize + refsize);
234
235 alloc_mark = bfd_hash_allocate (&cref_table.root, 1);
236 if (alloc_mark == NULL)
237 return FALSE;
238
239 memcpy (old_tab, cref_table.root.table, tabsize);
240 old_ent = (char *) old_tab + tabsize;
241 old_ref = (char *) old_ent + entsize;
242 old_table = cref_table.root.table;
243 old_size = cref_table.root.size;
244 old_count = cref_table.root.count;
245 old_symcount = cref_symcount;
246
247 for (i = 0; i < cref_table.root.size; i++)
248 {
249 struct bfd_hash_entry *p;
250 struct cref_hash_entry *c;
251 struct cref_ref *r;
252
253 for (p = cref_table.root.table[i]; p != NULL; p = p->next)
254 {
255 memcpy (old_ent, p, cref_table.root.entsize);
256 old_ent = (char *) old_ent + cref_table.root.entsize;
257 c = (struct cref_hash_entry *) p;
258 for (r = c->refs; r != NULL; r = r->next)
259 {
260 memcpy (old_ref, r, sizeof (struct cref_ref));
261 old_ref = (char *) old_ref + sizeof (struct cref_ref);
262 }
263 }
264 }
265 return TRUE;
266 }
267
268 if (act == notice_not_needed)
269 {
270 char *old_ent, *old_ref;
271
272 if (old_tab == NULL)
273 {
274 /* The only way old_tab can be NULL is if the cref hash table
275 had not been initialised when notice_as_needed. */
276 bfd_hash_table_free (&cref_table.root);
277 cref_initialized = FALSE;
278 return TRUE;
279 }
280
281 old_ent = (char *) old_tab + tabsize;
282 old_ref = (char *) old_ent + entsize;
283 cref_table.root.table = old_table;
284 cref_table.root.size = old_size;
285 cref_table.root.count = old_count;
286 memcpy (cref_table.root.table, old_tab, tabsize);
287 cref_symcount = old_symcount;
288
289 for (i = 0; i < cref_table.root.size; i++)
290 {
291 struct bfd_hash_entry *p;
292 struct cref_hash_entry *c;
293 struct cref_ref *r;
294
295 for (p = cref_table.root.table[i]; p != NULL; p = p->next)
296 {
297 memcpy (p, old_ent, cref_table.root.entsize);
298 old_ent = (char *) old_ent + cref_table.root.entsize;
299 c = (struct cref_hash_entry *) p;
300 for (r = c->refs; r != NULL; r = r->next)
301 {
302 memcpy (r, old_ref, sizeof (struct cref_ref));
303 old_ref = (char *) old_ref + sizeof (struct cref_ref);
304 }
305 }
306 }
307
308 objalloc_free_block ((struct objalloc *) cref_table.root.memory,
309 alloc_mark);
310 }
311 else if (act != notice_needed)
312 return FALSE;
313
314 free (old_tab);
315 old_tab = NULL;
316 return TRUE;
317}
318
319/* Copy the addresses of the hash table entries into an array. This
320 is called via cref_hash_traverse. We also fill in the demangled
321 name. */
322
323static bfd_boolean
324cref_fill_array (struct cref_hash_entry *h, void *data)
325{
326 struct cref_hash_entry ***pph = (struct cref_hash_entry ***) data;
327
328 ASSERT (h->demangled == NULL);
329 h->demangled = bfd_demangle (link_info.output_bfd, h->root.string,
330 DMGL_ANSI | DMGL_PARAMS);
331 if (h->demangled == NULL)
332 h->demangled = h->root.string;
333
334 **pph = h;
335
336 ++*pph;
337
338 return TRUE;
339}
340
341/* Sort an array of cref hash table entries by name. */
342
343static int
344cref_sort_array (const void *a1, const void *a2)
345{
346 const struct cref_hash_entry * const *p1 =
347 (const struct cref_hash_entry * const *) a1;
348 const struct cref_hash_entry * const *p2 =
349 (const struct cref_hash_entry * const *) a2;
350
351 return strcmp ((*p1)->demangled, (*p2)->demangled);
352}
353
354/* Write out the cref table. */
355
356#define FILECOL (50)
357
358void
359output_cref (FILE *fp)
360{
361 int len;
362 struct cref_hash_entry **csyms, **csym_fill, **csym, **csym_end;
363 const char *msg;
364
365 fprintf (fp, _("\nCross Reference Table\n\n"));
366 msg = _("Symbol");
367 fprintf (fp, "%s", msg);
368 len = strlen (msg);
369 while (len < FILECOL)
370 {
371 putc (' ', fp);
372 ++len;
373 }
374 fprintf (fp, _("File\n"));
375
376 if (! cref_initialized)
377 {
378 fprintf (fp, _("No symbols\n"));
379 return;
380 }
381
382 csyms = (struct cref_hash_entry **) xmalloc (cref_symcount * sizeof (*csyms));
383
384 csym_fill = csyms;
385 cref_hash_traverse (&cref_table, cref_fill_array, &csym_fill);
386 ASSERT ((size_t) (csym_fill - csyms) == cref_symcount);
387
388 qsort (csyms, cref_symcount, sizeof (*csyms), cref_sort_array);
389
390 csym_end = csyms + cref_symcount;
391 for (csym = csyms; csym < csym_end; csym++)
392 output_one_cref (fp, *csym);
393}
394
395/* Output one entry in the cross reference table. */
396
397static void
398output_one_cref (FILE *fp, struct cref_hash_entry *h)
399{
400 int len;
401 struct bfd_link_hash_entry *hl;
402 struct cref_ref *r;
403
404 hl = bfd_link_hash_lookup (link_info.hash, h->root.string, FALSE,
405 FALSE, TRUE);
406 if (hl == NULL)
407 einfo ("%P: symbol `%T' missing from main hash table\n",
408 h->root.string);
409 else
410 {
411 /* If this symbol is defined in a dynamic object but never
412 referenced by a normal object, then don't print it. */
413 if (hl->type == bfd_link_hash_defined)
414 {
415 if (hl->u.def.section->output_section == NULL)
416 return;
417 if (hl->u.def.section->owner != NULL
418 && (hl->u.def.section->owner->flags & DYNAMIC) != 0)
419 {
420 for (r = h->refs; r != NULL; r = r->next)
421 if ((r->abfd->flags & DYNAMIC) == 0)
422 break;
423 if (r == NULL)
424 return;
425 }
426 }
427 }
428
429 fprintf (fp, "%s ", h->demangled);
430 len = strlen (h->demangled) + 1;
431
432 for (r = h->refs; r != NULL; r = r->next)
433 {
434 if (r->def)
435 {
436 while (len < FILECOL)
437 {
438 putc (' ', fp);
439 ++len;
440 }
441 lfinfo (fp, "%B\n", r->abfd);
442 len = 0;
443 }
444 }
445
446 for (r = h->refs; r != NULL; r = r->next)
447 {
448 if (r->common)
449 {
450 while (len < FILECOL)
451 {
452 putc (' ', fp);
453 ++len;
454 }
455 lfinfo (fp, "%B\n", r->abfd);
456 len = 0;
457 }
458 }
459
460 for (r = h->refs; r != NULL; r = r->next)
461 {
462 if (! r->def && ! r->common)
463 {
464 while (len < FILECOL)
465 {
466 putc (' ', fp);
467 ++len;
468 }
469 lfinfo (fp, "%B\n", r->abfd);
470 len = 0;
471 }
472 }
473
474 ASSERT (len == 0);
475}
476
477/* Check for prohibited cross references. */
478
479void
480check_nocrossrefs (void)
481{
482 if (! cref_initialized)
483 return;
484
485 cref_hash_traverse (&cref_table, check_nocrossref, NULL);
486
487 lang_for_each_file (check_local_sym_xref);
488}
489
490/* Check for prohibited cross references to local and section symbols. */
491
492static void
493check_local_sym_xref (lang_input_statement_type *statement)
494{
495 bfd *abfd;
496 asymbol **syms;
497
498 abfd = statement->the_bfd;
499 if (abfd == NULL)
500 return;
501
502 if (!bfd_generic_link_read_symbols (abfd))
503 einfo (_("%B%F: could not read symbols: %E\n"), abfd);
504
505 for (syms = bfd_get_outsymbols (abfd); *syms; ++syms)
506 {
507 asymbol *sym = *syms;
508 if (sym->flags & (BSF_GLOBAL | BSF_WARNING | BSF_INDIRECT | BSF_FILE))
509 continue;
510 if ((sym->flags & (BSF_LOCAL | BSF_SECTION_SYM)) != 0
511 && sym->section->output_section != NULL)
512 {
513 const char *outsecname, *symname;
514 struct lang_nocrossrefs *ncrs;
515 struct lang_nocrossref *ncr;
516
517 outsecname = sym->section->output_section->name;
518 symname = NULL;
519 if ((sym->flags & BSF_SECTION_SYM) == 0)
520 symname = sym->name;
521 for (ncrs = nocrossref_list; ncrs != NULL; ncrs = ncrs->next)
522 for (ncr = ncrs->list; ncr != NULL; ncr = ncr->next)
523 if (strcmp (ncr->name, outsecname) == 0)
524 check_refs (symname, FALSE, sym->section, abfd, ncrs);
525 }
526 }
527}
528
529/* Check one symbol to see if it is a prohibited cross reference. */
530
531static bfd_boolean
532check_nocrossref (struct cref_hash_entry *h, void *ignore ATTRIBUTE_UNUSED)
533{
534 struct bfd_link_hash_entry *hl;
535 asection *defsec;
536 const char *defsecname;
537 struct lang_nocrossrefs *ncrs;
538 struct lang_nocrossref *ncr;
539 struct cref_ref *ref;
540
541 hl = bfd_link_hash_lookup (link_info.hash, h->root.string, FALSE,
542 FALSE, TRUE);
543 if (hl == NULL)
544 {
545 einfo (_("%P: symbol `%T' missing from main hash table\n"),
546 h->root.string);
547 return TRUE;
548 }
549
550 if (hl->type != bfd_link_hash_defined
551 && hl->type != bfd_link_hash_defweak)
552 return TRUE;
553
554 defsec = hl->u.def.section->output_section;
555 if (defsec == NULL)
556 return TRUE;
557 defsecname = bfd_get_section_name (defsec->owner, defsec);
558
559 for (ncrs = nocrossref_list; ncrs != NULL; ncrs = ncrs->next)
560 for (ncr = ncrs->list; ncr != NULL; ncr = ncr->next)
561 if (strcmp (ncr->name, defsecname) == 0)
562 for (ref = h->refs; ref != NULL; ref = ref->next)
563 check_refs (hl->root.string, TRUE, hl->u.def.section,
564 ref->abfd, ncrs);
565
566 return TRUE;
567}
568
569/* The struct is used to pass information from check_refs to
570 check_reloc_refs through bfd_map_over_sections. */
571
572struct check_refs_info {
573 const char *sym_name;
574 asection *defsec;
575 struct lang_nocrossrefs *ncrs;
576 asymbol **asymbols;
577 bfd_boolean global;
578};
579
580/* This function is called for each symbol defined in a section which
581 prohibits cross references. We need to look through all references
582 to this symbol, and ensure that the references are not from
583 prohibited sections. */
584
585static void
586check_refs (const char *name,
587 bfd_boolean global,
588 asection *sec,
589 bfd *abfd,
590 struct lang_nocrossrefs *ncrs)
591{
592 struct check_refs_info info;
593
594 /* We need to look through the relocations for this BFD, to see
595 if any of the relocations which refer to this symbol are from
596 a prohibited section. Note that we need to do this even for
597 the BFD in which the symbol is defined, since even a single
598 BFD might contain a prohibited cross reference. */
599
600 if (!bfd_generic_link_read_symbols (abfd))
601 einfo (_("%B%F: could not read symbols: %E\n"), abfd);
602
603 info.sym_name = name;
604 info.global = global;
605 info.defsec = sec;
606 info.ncrs = ncrs;
607 info.asymbols = bfd_get_outsymbols (abfd);
608 bfd_map_over_sections (abfd, check_reloc_refs, &info);
609}
610
611/* This is called via bfd_map_over_sections. INFO->SYM_NAME is a symbol
612 defined in INFO->DEFSECNAME. If this section maps into any of the
613 sections listed in INFO->NCRS, other than INFO->DEFSECNAME, then we
614 look through the relocations. If any of the relocations are to
615 INFO->SYM_NAME, then we report a prohibited cross reference error. */
616
617static void
618check_reloc_refs (bfd *abfd, asection *sec, void *iarg)
619{
620 struct check_refs_info *info = (struct check_refs_info *) iarg;
621 asection *outsec;
622 const char *outsecname;
623 asection *outdefsec;
624 const char *outdefsecname;
625 struct lang_nocrossref *ncr;
626 const char *symname;
627 bfd_boolean global;
628 long relsize;
629 arelent **relpp;
630 long relcount;
631 arelent **p, **pend;
632
633 outsec = sec->output_section;
634 outsecname = bfd_get_section_name (outsec->owner, outsec);
635
636 outdefsec = info->defsec->output_section;
637 outdefsecname = bfd_get_section_name (outdefsec->owner, outdefsec);
638
639 /* The section where the symbol is defined is permitted. */
640 if (strcmp (outsecname, outdefsecname) == 0)
641 return;
642
643 for (ncr = info->ncrs->list; ncr != NULL; ncr = ncr->next)
644 if (strcmp (outsecname, ncr->name) == 0)
645 break;
646
647 if (ncr == NULL)
648 return;
649
650 /* This section is one for which cross references are prohibited.
651 Look through the relocations, and see if any of them are to
652 INFO->SYM_NAME. If INFO->SYMNAME is NULL, check for relocations
653 against the section symbol. If INFO->GLOBAL is TRUE, the
654 definition is global, check for relocations against the global
655 symbols. Otherwise check for relocations against the local and
656 section symbols. */
657
658 symname = info->sym_name;
659 global = info->global;
660
661 relsize = bfd_get_reloc_upper_bound (abfd, sec);
662 if (relsize < 0)
663 einfo (_("%B%F: could not read relocs: %E\n"), abfd);
664 if (relsize == 0)
665 return;
666
667 relpp = (arelent **) xmalloc (relsize);
668 relcount = bfd_canonicalize_reloc (abfd, sec, relpp, info->asymbols);
669 if (relcount < 0)
670 einfo (_("%B%F: could not read relocs: %E\n"), abfd);
671
672 p = relpp;
673 pend = p + relcount;
674 for (; p < pend && *p != NULL; p++)
675 {
676 arelent *q = *p;
677
678 if (q->sym_ptr_ptr != NULL
679 && *q->sym_ptr_ptr != NULL
680 && ((global
681 && (bfd_is_und_section (bfd_get_section (*q->sym_ptr_ptr))
682 || bfd_is_com_section (bfd_get_section (*q->sym_ptr_ptr))
683 || ((*q->sym_ptr_ptr)->flags & (BSF_GLOBAL
684 | BSF_WEAK)) != 0))
685 || (!global
686 && ((*q->sym_ptr_ptr)->flags & (BSF_LOCAL
687 | BSF_SECTION_SYM)) != 0
688 && bfd_get_section (*q->sym_ptr_ptr) == info->defsec))
689 && (symname != NULL
690 ? strcmp (bfd_asymbol_name (*q->sym_ptr_ptr), symname) == 0
691 : ((*q->sym_ptr_ptr)->flags & BSF_SECTION_SYM) != 0))
692 {
693 /* We found a reloc for the symbol. The symbol is defined
694 in OUTSECNAME. This reloc is from a section which is
695 mapped into a section from which references to OUTSECNAME
696 are prohibited. We must report an error. */
697 einfo (_("%X%C: prohibited cross reference from %s to `%T' in %s\n"),
698 abfd, sec, q->address, outsecname,
699 bfd_asymbol_name (*q->sym_ptr_ptr), outdefsecname);
700 }
701 }
702
703 free (relpp);
704}
This page took 0.025479 seconds and 4 git commands to generate.