1 /* ldcref.c -- output a cross reference table 2 Copyright (C) 1996, 97, 98, 99, 2000 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 ATTRIBUTE_UNUSED; 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 const char *msg; 238 239 fprintf (fp, _("\nCross Reference Table\n\n")); 240 msg = _("Symbol"); 241 fprintf (fp, "%s", msg); 242 len = strlen (msg); 243 while (len < FILECOL) 244 { 245 putc (' ' , fp); 246 ++len; 247 } 248 fprintf (fp, _("File\n")); 249 250 if (! cref_initialized) 251 { 252 fprintf (fp, _("No symbols\n")); 253 return; 254 } 255 256 csyms = ((struct cref_hash_entry **) 257 xmalloc (cref_symcount * sizeof (*csyms))); 258 259 csym_fill = csyms; 260 cref_hash_traverse (&cref_table, cref_fill_array, &csym_fill); 261 ASSERT ((size_t) (csym_fill - csyms) == cref_symcount); 262 263 qsort (csyms, cref_symcount, sizeof (*csyms), cref_sort_array); 264 265 csym_end = csyms + cref_symcount; 266 for (csym = csyms; csym < csym_end; csym++) 267 output_one_cref (fp, *csym); 268 } 269 270 /* Output one entry in the cross reference table. */ 271 272 static void 273 output_one_cref (fp, h) 274 FILE *fp; 275 struct cref_hash_entry *h; 276 { 277 int len; 278 struct bfd_link_hash_entry *hl; 279 struct cref_ref *r; 280 281 hl = bfd_link_hash_lookup (link_info.hash, h->root.string, false, 282 false, true); 283 if (hl == NULL) 284 einfo ("%P: symbol `%T' missing from main hash table\n", 285 h->root.string); 286 else 287 { 288 /* If this symbol is defined in a dynamic object but never 289 referenced by a normal object, then don't print it. */ 290 if (hl->type == bfd_link_hash_defined) 291 { 292 if (hl->u.def.section->output_section == NULL) 293 return; 294 if (hl->u.def.section->owner != NULL 295 && (hl->u.def.section->owner->flags & DYNAMIC) != 0) 296 { 297 for (r = h->refs; r != NULL; r = r->next) 298 if ((r->abfd->flags & DYNAMIC) == 0) 299 break; 300 if (r == NULL) 301 return; 302 } 303 } 304 } 305 306 fprintf (fp, "%s ", h->demangled); 307 len = strlen (h->demangled) + 1; 308 309 for (r = h->refs; r != NULL; r = r->next) 310 { 311 if (r->def) 312 { 313 while (len < FILECOL) 314 { 315 putc (' ', fp); 316 ++len; 317 } 318 lfinfo (fp, "%B\n", r->abfd); 319 len = 0; 320 } 321 } 322 323 for (r = h->refs; r != NULL; r = r->next) 324 { 325 if (! r->def) 326 { 327 while (len < FILECOL) 328 { 329 putc (' ', fp); 330 ++len; 331 } 332 lfinfo (fp, "%B\n", r->abfd); 333 len = 0; 334 } 335 } 336 337 ASSERT (len == 0); 338 } 339 340 /* Check for prohibited cross references. */ 341 342 void 343 check_nocrossrefs () 344 { 345 if (! cref_initialized) 346 return; 347 348 cref_hash_traverse (&cref_table, check_nocrossref, (PTR) NULL); 349 } 350 351 /* Check one symbol to see if it is a prohibited cross reference. */ 352 353 /*ARGSUSED*/ 354 static boolean 355 check_nocrossref (h, ignore) 356 struct cref_hash_entry *h; 357 PTR ignore ATTRIBUTE_UNUSED; 358 { 359 struct bfd_link_hash_entry *hl; 360 asection *defsec; 361 const char *defsecname; 362 struct lang_nocrossrefs *ncrs; 363 struct lang_nocrossref *ncr; 364 365 hl = bfd_link_hash_lookup (link_info.hash, h->root.string, false, 366 false, true); 367 if (hl == NULL) 368 { 369 einfo (_("%P: symbol `%T' missing from main hash table\n"), 370 h->root.string); 371 return true; 372 } 373 374 if (hl->type != bfd_link_hash_defined 375 && hl->type != bfd_link_hash_defweak) 376 return true; 377 378 defsec = hl->u.def.section->output_section; 379 if (defsec == NULL) 380 return true; 381 defsecname = bfd_get_section_name (defsec->owner, defsec); 382 383 for (ncrs = nocrossref_list; ncrs != NULL; ncrs = ncrs->next) 384 for (ncr = ncrs->list; ncr != NULL; ncr = ncr->next) 385 if (strcmp (ncr->name, defsecname) == 0) 386 check_refs (h, hl, ncrs); 387 388 return true; 389 } 390 391 /* The struct is used to pass information from check_refs to 392 check_reloc_refs through bfd_map_over_sections. */ 393 394 struct check_refs_info 395 { 396 struct cref_hash_entry *h; 397 asection *defsec; 398 struct lang_nocrossrefs *ncrs; 399 asymbol **asymbols; 400 boolean same; 401 }; 402 403 /* This function is called for each symbol defined in a section which 404 prohibits cross references. We need to look through all references 405 to this symbol, and ensure that the references are not from 406 prohibited sections. */ 407 408 static void 409 check_refs (h, hl, ncrs) 410 struct cref_hash_entry *h; 411 struct bfd_link_hash_entry *hl; 412 struct lang_nocrossrefs *ncrs; 413 { 414 struct cref_ref *ref; 415 416 for (ref = h->refs; ref != NULL; ref = ref->next) 417 { 418 lang_input_statement_type *li; 419 asymbol **asymbols; 420 struct check_refs_info info; 421 422 /* We need to look through the relocations for this BFD, to see 423 if any of the relocations which refer to this symbol are from 424 a prohibited section. Note that we need to do this even for 425 the BFD in which the symbol is defined, since even a single 426 BFD might contain a prohibited cross reference; for this 427 case, we set the SAME field in INFO, which will cause 428 CHECK_RELOCS_REFS to check for relocations against the 429 section as well as against the symbol. */ 430 431 li = (lang_input_statement_type *) ref->abfd->usrdata; 432 if (li != NULL && li->asymbols != NULL) 433 asymbols = li->asymbols; 434 else 435 { 436 long symsize; 437 long symbol_count; 438 439 symsize = bfd_get_symtab_upper_bound (ref->abfd); 440 if (symsize < 0) 441 einfo (_("%B%F: could not read symbols; %E\n"), ref->abfd); 442 asymbols = (asymbol **) xmalloc (symsize); 443 symbol_count = bfd_canonicalize_symtab (ref->abfd, asymbols); 444 if (symbol_count < 0) 445 einfo (_("%B%F: could not read symbols: %E\n"), ref->abfd); 446 if (li != NULL) 447 { 448 li->asymbols = asymbols; 449 li->symbol_count = symbol_count; 450 } 451 } 452 453 info.h = h; 454 info.defsec = hl->u.def.section; 455 info.ncrs = ncrs; 456 info.asymbols = asymbols; 457 if (ref->abfd == hl->u.def.section->owner) 458 info.same = true; 459 else 460 info.same = false; 461 bfd_map_over_sections (ref->abfd, check_reloc_refs, (PTR) &info); 462 463 if (li == NULL) 464 free (asymbols); 465 } 466 } 467 468 /* This is called via bfd_map_over_sections. INFO->H is a symbol 469 defined in INFO->DEFSECNAME. If this section maps into any of the 470 sections listed in INFO->NCRS, other than INFO->DEFSECNAME, then we 471 look through the relocations. If any of the relocations are to 472 INFO->H, then we report a prohibited cross reference error. */ 473 474 static void 475 check_reloc_refs (abfd, sec, iarg) 476 bfd *abfd; 477 asection *sec; 478 PTR iarg; 479 { 480 struct check_refs_info *info = (struct check_refs_info *) iarg; 481 asection *outsec; 482 const char *outsecname; 483 asection *outdefsec; 484 const char *outdefsecname; 485 struct lang_nocrossref *ncr; 486 const char *symname; 487 long relsize; 488 arelent **relpp; 489 long relcount; 490 arelent **p, **pend; 491 492 outsec = sec->output_section; 493 outsecname = bfd_get_section_name (outsec->owner, outsec); 494 495 outdefsec = info->defsec->output_section; 496 outdefsecname = bfd_get_section_name (outdefsec->owner, outdefsec); 497 498 /* The section where the symbol is defined is permitted. */ 499 if (strcmp (outsecname, outdefsecname) == 0) 500 return; 501 502 for (ncr = info->ncrs->list; ncr != NULL; ncr = ncr->next) 503 if (strcmp (outsecname, ncr->name) == 0) 504 break; 505 506 if (ncr == NULL) 507 return; 508 509 /* This section is one for which cross references are prohibited. 510 Look through the relocations, and see if any of them are to 511 INFO->H. */ 512 513 symname = info->h->root.string; 514 515 relsize = bfd_get_reloc_upper_bound (abfd, sec); 516 if (relsize < 0) 517 einfo (_("%B%F: could not read relocs: %E\n"), abfd); 518 if (relsize == 0) 519 return; 520 521 relpp = (arelent **) xmalloc (relsize); 522 relcount = bfd_canonicalize_reloc (abfd, sec, relpp, info->asymbols); 523 if (relcount < 0) 524 einfo (_("%B%F: could not read relocs: %E\n"), abfd); 525 526 p = relpp; 527 pend = p + relcount; 528 for (; p < pend && *p != NULL; p++) 529 { 530 arelent *q = *p; 531 532 if (q->sym_ptr_ptr != NULL 533 && *q->sym_ptr_ptr != NULL 534 && (strcmp (bfd_asymbol_name (*q->sym_ptr_ptr), symname) == 0 535 || (info->same 536 && bfd_get_section (*q->sym_ptr_ptr) == info->defsec))) 537 { 538 /* We found a reloc for the symbol. The symbol is defined 539 in OUTSECNAME. This reloc is from a section which is 540 mapped into a section from which references to OUTSECNAME 541 are prohibited. We must report an error. */ 542 einfo (_("%X%C: prohibited cross reference from %s to `%T' in %s\n"), 543 abfd, sec, q->address, outsecname, 544 bfd_asymbol_name (*q->sym_ptr_ptr), outdefsecname); 545 } 546 } 547 548 free (relpp); 549 } 550