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