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