1 /* corefile.c 2 3 Copyright 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2007, 2008 4 Free Software Foundation, Inc. 5 6 This file is part of GNU Binutils. 7 8 This program is free software; you can redistribute it and/or modify 9 it under the terms of the GNU General Public License as published by 10 the Free Software Foundation; either version 3 of the License, or 11 (at your option) any later version. 12 13 This program is distributed in the hope that it will be useful, 14 but WITHOUT ANY WARRANTY; without even the implied warranty of 15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 16 GNU General Public License for more details. 17 18 You should have received a copy of the GNU General Public License 19 along with this program; if not, write to the Free Software 20 Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA 21 02110-1301, USA. */ 22 23 #include "gprof.h" 24 #include "libiberty.h" 25 #include "search_list.h" 26 #include "source.h" 27 #include "symtab.h" 28 #include "hist.h" 29 #include "corefile.h" 30 #include "safe-ctype.h" 31 32 #include <stdlib.h> 33 34 bfd *core_bfd; 35 static int core_num_syms; 36 static asymbol **core_syms; 37 asection *core_text_sect; 38 PTR core_text_space; 39 40 static int min_insn_size; 41 int offset_to_code; 42 43 /* For mapping symbols to specific .o files during file ordering. */ 44 struct function_map *symbol_map; 45 unsigned int symbol_map_count; 46 47 static void read_function_mappings (const char *); 48 static int core_sym_class (asymbol *); 49 static bfd_boolean get_src_info 50 (bfd_vma, const char **, const char **, int *); 51 52 extern void i386_find_call (Sym *, bfd_vma, bfd_vma); 53 extern void alpha_find_call (Sym *, bfd_vma, bfd_vma); 54 extern void vax_find_call (Sym *, bfd_vma, bfd_vma); 55 extern void tahoe_find_call (Sym *, bfd_vma, bfd_vma); 56 extern void sparc_find_call (Sym *, bfd_vma, bfd_vma); 57 extern void mips_find_call (Sym *, bfd_vma, bfd_vma); 58 59 static void 60 parse_error (const char *filename) 61 { 62 fprintf (stderr, _("%s: unable to parse mapping file %s.\n"), whoami, filename); 63 done (1); 64 } 65 66 static void 67 read_function_mappings (const char *filename) 68 { 69 FILE *file = fopen (filename, "r"); 70 char dummy[1024]; 71 int count = 0; 72 73 if (!file) 74 { 75 fprintf (stderr, _("%s: could not open %s.\n"), whoami, filename); 76 done (1); 77 } 78 79 /* First parse the mapping file so we know how big we need to 80 make our tables. We also do some sanity checks at this 81 time. */ 82 while (!feof (file)) 83 { 84 int matches; 85 86 matches = fscanf (file, "%[^\n:]", dummy); 87 if (!matches) 88 parse_error (filename); 89 90 /* Just skip messages about files with no symbols. */ 91 if (!strncmp (dummy, "No symbols in ", 14)) 92 { 93 matches = fscanf (file, "\n"); 94 if (matches == EOF) 95 parse_error (filename); 96 continue; 97 } 98 99 /* Don't care what else is on this line at this point. */ 100 matches = fscanf (file, "%[^\n]\n", dummy); 101 if (!matches) 102 parse_error (filename); 103 count++; 104 } 105 106 /* Now we know how big we need to make our table. */ 107 symbol_map = ((struct function_map *) 108 xmalloc (count * sizeof (struct function_map))); 109 110 /* Rewind the input file so we can read it again. */ 111 rewind (file); 112 113 /* Read each entry and put it into the table. */ 114 count = 0; 115 while (!feof (file)) 116 { 117 int matches; 118 char *tmp; 119 120 matches = fscanf (file, "%[^\n:]", dummy); 121 if (!matches) 122 parse_error (filename); 123 124 /* Just skip messages about files with no symbols. */ 125 if (!strncmp (dummy, "No symbols in ", 14)) 126 { 127 matches = fscanf (file, "\n"); 128 if (matches == EOF) 129 parse_error (filename); 130 continue; 131 } 132 133 /* dummy has the filename, go ahead and copy it. */ 134 symbol_map[count].file_name = xmalloc (strlen (dummy) + 1); 135 strcpy (symbol_map[count].file_name, dummy); 136 137 /* Now we need the function name. */ 138 matches = fscanf (file, "%[^\n]\n", dummy); 139 if (!matches) 140 parse_error (filename); 141 tmp = strrchr (dummy, ' ') + 1; 142 symbol_map[count].function_name = xmalloc (strlen (tmp) + 1); 143 strcpy (symbol_map[count].function_name, tmp); 144 count++; 145 } 146 147 /* Record the size of the map table for future reference. */ 148 symbol_map_count = count; 149 } 150 151 152 void 153 core_init (const char *aout_name) 154 { 155 int core_sym_bytes; 156 asymbol *synthsyms; 157 long synth_count; 158 159 core_bfd = bfd_openr (aout_name, 0); 160 161 if (!core_bfd) 162 { 163 perror (aout_name); 164 done (1); 165 } 166 167 if (!bfd_check_format (core_bfd, bfd_object)) 168 { 169 fprintf (stderr, _("%s: %s: not in executable format\n"), whoami, aout_name); 170 done (1); 171 } 172 173 /* Get core's text section. */ 174 core_text_sect = bfd_get_section_by_name (core_bfd, ".text"); 175 if (!core_text_sect) 176 { 177 core_text_sect = bfd_get_section_by_name (core_bfd, "$CODE$"); 178 if (!core_text_sect) 179 { 180 fprintf (stderr, _("%s: can't find .text section in %s\n"), 181 whoami, aout_name); 182 done (1); 183 } 184 } 185 186 /* Read core's symbol table. */ 187 188 /* This will probably give us more than we need, but that's ok. */ 189 core_sym_bytes = bfd_get_symtab_upper_bound (core_bfd); 190 if (core_sym_bytes < 0) 191 { 192 fprintf (stderr, "%s: %s: %s\n", whoami, aout_name, 193 bfd_errmsg (bfd_get_error ())); 194 done (1); 195 } 196 197 core_syms = (asymbol **) xmalloc (core_sym_bytes); 198 core_num_syms = bfd_canonicalize_symtab (core_bfd, core_syms); 199 200 if (core_num_syms < 0) 201 { 202 fprintf (stderr, "%s: %s: %s\n", whoami, aout_name, 203 bfd_errmsg (bfd_get_error ())); 204 done (1); 205 } 206 207 synth_count = bfd_get_synthetic_symtab (core_bfd, core_num_syms, core_syms, 208 0, NULL, &synthsyms); 209 if (synth_count > 0) 210 { 211 asymbol **symp; 212 long new_size; 213 long i; 214 215 new_size = (core_num_syms + synth_count + 1) * sizeof (*core_syms); 216 core_syms = xrealloc (core_syms, new_size); 217 symp = core_syms + core_num_syms; 218 core_num_syms += synth_count; 219 for (i = 0; i < synth_count; i++) 220 *symp++ = synthsyms + i; 221 *symp = 0; 222 } 223 224 min_insn_size = 1; 225 offset_to_code = 0; 226 227 switch (bfd_get_arch (core_bfd)) 228 { 229 case bfd_arch_vax: 230 case bfd_arch_tahoe: 231 offset_to_code = 2; 232 break; 233 234 case bfd_arch_alpha: 235 min_insn_size = 4; 236 break; 237 238 default: 239 break; 240 } 241 242 if (function_mapping_file) 243 read_function_mappings (function_mapping_file); 244 } 245 246 /* Read in the text space of an a.out file. */ 247 248 void 249 core_get_text_space (bfd *cbfd) 250 { 251 core_text_space = malloc (bfd_get_section_size (core_text_sect)); 252 253 if (!core_text_space) 254 { 255 fprintf (stderr, _("%s: ran out room for %lu bytes of text space\n"), 256 whoami, (unsigned long) bfd_get_section_size (core_text_sect)); 257 done (1); 258 } 259 260 if (!bfd_get_section_contents (cbfd, core_text_sect, core_text_space, 261 0, bfd_get_section_size (core_text_sect))) 262 { 263 bfd_perror ("bfd_get_section_contents"); 264 free (core_text_space); 265 core_text_space = 0; 266 } 267 268 if (!core_text_space) 269 fprintf (stderr, _("%s: can't do -c\n"), whoami); 270 } 271 272 273 void 274 find_call (Sym *parent, bfd_vma p_lowpc, bfd_vma p_highpc) 275 { 276 if (core_text_space == 0) 277 return; 278 279 hist_clip_symbol_address (&p_lowpc, &p_highpc); 280 281 switch (bfd_get_arch (core_bfd)) 282 { 283 case bfd_arch_i386: 284 i386_find_call (parent, p_lowpc, p_highpc); 285 break; 286 287 case bfd_arch_alpha: 288 alpha_find_call (parent, p_lowpc, p_highpc); 289 break; 290 291 case bfd_arch_vax: 292 vax_find_call (parent, p_lowpc, p_highpc); 293 break; 294 295 case bfd_arch_sparc: 296 sparc_find_call (parent, p_lowpc, p_highpc); 297 break; 298 299 case bfd_arch_tahoe: 300 tahoe_find_call (parent, p_lowpc, p_highpc); 301 break; 302 303 case bfd_arch_mips: 304 mips_find_call (parent, p_lowpc, p_highpc); 305 break; 306 307 default: 308 fprintf (stderr, _("%s: -c not supported on architecture %s\n"), 309 whoami, bfd_printable_name(core_bfd)); 310 311 /* Don't give the error more than once. */ 312 ignore_direct_calls = FALSE; 313 } 314 } 315 316 /* Return class of symbol SYM. The returned class can be any of: 317 0 -> symbol is not interesting to us 318 'T' -> symbol is a global name 319 't' -> symbol is a local (static) name. */ 320 321 static int 322 core_sym_class (asymbol *sym) 323 { 324 symbol_info syminfo; 325 const char *name; 326 char sym_prefix; 327 int i; 328 329 if (sym->section == NULL || (sym->flags & BSF_DEBUGGING) != 0) 330 return 0; 331 332 /* Must be a text symbol, and static text symbols 333 don't qualify if ignore_static_funcs set. */ 334 if (ignore_static_funcs && (sym->flags & BSF_LOCAL)) 335 { 336 DBG (AOUTDEBUG, printf ("[core_sym_class] %s: not a function\n", 337 sym->name)); 338 return 0; 339 } 340 341 bfd_get_symbol_info (core_bfd, sym, &syminfo); 342 i = syminfo.type; 343 344 if (i == 'T') 345 return i; /* It's a global symbol. */ 346 347 if (i == 'W') 348 /* Treat weak symbols as text symbols. FIXME: a weak symbol may 349 also be a data symbol. */ 350 return 'T'; 351 352 if (i != 't') 353 { 354 /* Not a static text symbol. */ 355 DBG (AOUTDEBUG, printf ("[core_sym_class] %s is of class %c\n", 356 sym->name, i)); 357 return 0; 358 } 359 360 /* Do some more filtering on static function-names. */ 361 if (ignore_static_funcs) 362 return 0; 363 364 /* Can't zero-length name or funny characters in name, where 365 `funny' includes: `.' (.o file names) and `$' (Pascal labels). */ 366 if (!sym->name || sym->name[0] == '\0') 367 return 0; 368 369 for (name = sym->name; *name; ++name) 370 { 371 if (*name == '$') 372 return 0; 373 374 /* Do not discard nested subprograms (those 375 which end with .NNN, where N are digits). */ 376 if (*name == '.') 377 for (name++; *name; name++) 378 if (! ISDIGIT (*name)) 379 return 0; 380 } 381 382 /* On systems where the C compiler adds an underscore to all 383 names, static names without underscores seem usually to be 384 labels in hand written assembler in the library. We don't want 385 these names. This is certainly necessary on a Sparc running 386 SunOS 4.1 (try profiling a program that does a lot of 387 division). I don't know whether it has harmful side effects on 388 other systems. Perhaps it should be made configurable. */ 389 sym_prefix = bfd_get_symbol_leading_char (core_bfd); 390 391 if ((sym_prefix && sym_prefix != sym->name[0]) 392 /* GCC may add special symbols to help gdb figure out the file 393 language. We want to ignore these, since sometimes they mask 394 the real function. (dj@ctron) */ 395 || !strncmp (sym->name, "__gnu_compiled", 14) 396 || !strncmp (sym->name, "___gnu_compiled", 15)) 397 { 398 return 0; 399 } 400 401 /* If the object file supports marking of function symbols, then 402 we can zap anything that doesn't have BSF_FUNCTION set. */ 403 if (ignore_non_functions && (sym->flags & BSF_FUNCTION) == 0) 404 return 0; 405 406 return 't'; /* It's a static text symbol. */ 407 } 408 409 /* Get whatever source info we can get regarding address ADDR. */ 410 411 static bfd_boolean 412 get_src_info (bfd_vma addr, const char **filename, const char **name, int *line_num) 413 { 414 const char *fname = 0, *func_name = 0; 415 int l = 0; 416 417 if (bfd_find_nearest_line (core_bfd, core_text_sect, core_syms, 418 addr - core_text_sect->vma, 419 &fname, &func_name, (unsigned int *) &l) 420 && fname && func_name && l) 421 { 422 DBG (AOUTDEBUG, printf ("[get_src_info] 0x%lx -> %s:%d (%s)\n", 423 (unsigned long) addr, fname, l, func_name)); 424 *filename = fname; 425 *name = func_name; 426 *line_num = l; 427 return TRUE; 428 } 429 else 430 { 431 DBG (AOUTDEBUG, printf ("[get_src_info] no info for 0x%lx (%s:%d,%s)\n", 432 (unsigned long) addr, 433 fname ? fname : "<unknown>", l, 434 func_name ? func_name : "<unknown>")); 435 return FALSE; 436 } 437 } 438 439 /* Read in symbol table from core. 440 One symbol per function is entered. */ 441 442 void 443 core_create_function_syms () 444 { 445 bfd_vma min_vma = ~(bfd_vma) 0; 446 bfd_vma max_vma = 0; 447 int class; 448 long i, found, skip; 449 unsigned int j; 450 451 /* Pass 1 - determine upper bound on number of function names. */ 452 symtab.len = 0; 453 454 for (i = 0; i < core_num_syms; ++i) 455 { 456 if (!core_sym_class (core_syms[i])) 457 continue; 458 459 /* This should be replaced with a binary search or hashed 460 search. Gross. 461 462 Don't create a symtab entry for a function that has 463 a mapping to a file, unless it's the first function 464 in the file. */ 465 skip = 0; 466 for (j = 0; j < symbol_map_count; j++) 467 if (!strcmp (core_syms[i]->name, symbol_map[j].function_name)) 468 { 469 if (j > 0 && ! strcmp (symbol_map [j].file_name, 470 symbol_map [j - 1].file_name)) 471 skip = 1; 472 break; 473 } 474 475 if (!skip) 476 ++symtab.len; 477 } 478 479 if (symtab.len == 0) 480 { 481 fprintf (stderr, _("%s: file `%s' has no symbols\n"), whoami, a_out_name); 482 done (1); 483 } 484 485 /* The "+ 2" is for the sentinels. */ 486 symtab.base = (Sym *) xmalloc ((symtab.len + 2) * sizeof (Sym)); 487 488 /* Pass 2 - create symbols. */ 489 symtab.limit = symtab.base; 490 491 for (i = 0; i < core_num_syms; ++i) 492 { 493 asection *sym_sec; 494 495 class = core_sym_class (core_syms[i]); 496 497 if (!class) 498 { 499 DBG (AOUTDEBUG, 500 printf ("[core_create_function_syms] rejecting: 0x%lx %s\n", 501 (unsigned long) core_syms[i]->value, 502 core_syms[i]->name)); 503 continue; 504 } 505 506 /* This should be replaced with a binary search or hashed 507 search. Gross. */ 508 skip = 0; 509 found = 0; 510 511 for (j = 0; j < symbol_map_count; j++) 512 if (!strcmp (core_syms[i]->name, symbol_map[j].function_name)) 513 { 514 if (j > 0 && ! strcmp (symbol_map [j].file_name, 515 symbol_map [j - 1].file_name)) 516 skip = 1; 517 else 518 found = j; 519 break; 520 } 521 522 if (skip) 523 continue; 524 525 sym_init (symtab.limit); 526 527 /* Symbol offsets are always section-relative. */ 528 sym_sec = core_syms[i]->section; 529 symtab.limit->addr = core_syms[i]->value; 530 if (sym_sec) 531 symtab.limit->addr += bfd_get_section_vma (sym_sec->owner, sym_sec); 532 533 if (symbol_map_count 534 && !strcmp (core_syms[i]->name, symbol_map[found].function_name)) 535 { 536 symtab.limit->name = symbol_map[found].file_name; 537 symtab.limit->mapped = 1; 538 } 539 else 540 { 541 symtab.limit->name = core_syms[i]->name; 542 symtab.limit->mapped = 0; 543 } 544 545 /* Lookup filename and line number, if we can. */ 546 { 547 const char *filename, *func_name; 548 549 if (get_src_info (symtab.limit->addr, &filename, &func_name, 550 &symtab.limit->line_num)) 551 { 552 symtab.limit->file = source_file_lookup_path (filename); 553 554 /* FIXME: Checking __osf__ here does not work with a cross 555 gprof. */ 556 #ifdef __osf__ 557 /* Suppress symbols that are not function names. This is 558 useful to suppress code-labels and aliases. 559 560 This is known to be useful under DEC's OSF/1. Under SunOS 4.x, 561 labels do not appear in the symbol table info, so this isn't 562 necessary. */ 563 564 if (strcmp (symtab.limit->name, func_name) != 0) 565 { 566 /* The symbol's address maps to a different name, so 567 it can't be a function-entry point. This happens 568 for labels, for example. */ 569 DBG (AOUTDEBUG, 570 printf ("[core_create_function_syms: rej %s (maps to %s)\n", 571 symtab.limit->name, func_name)); 572 continue; 573 } 574 #endif 575 } 576 } 577 578 symtab.limit->is_func = TRUE; 579 symtab.limit->is_bb_head = TRUE; 580 581 if (class == 't') 582 symtab.limit->is_static = TRUE; 583 584 /* Keep track of the minimum and maximum vma addresses used by all 585 symbols. When computing the max_vma, use the ending address of the 586 section containing the symbol, if available. */ 587 min_vma = MIN (symtab.limit->addr, min_vma); 588 if (sym_sec) 589 max_vma = MAX (bfd_get_section_vma (sym_sec->owner, sym_sec) 590 + bfd_section_size (sym_sec->owner, sym_sec) - 1, 591 max_vma); 592 else 593 max_vma = MAX (symtab.limit->addr, max_vma); 594 595 DBG (AOUTDEBUG, printf ("[core_create_function_syms] %ld %s 0x%lx\n", 596 (long) (symtab.limit - symtab.base), 597 symtab.limit->name, 598 (unsigned long) symtab.limit->addr)); 599 ++symtab.limit; 600 } 601 602 /* Create sentinels. */ 603 sym_init (symtab.limit); 604 symtab.limit->name = "<locore>"; 605 symtab.limit->addr = 0; 606 symtab.limit->end_addr = min_vma - 1; 607 ++symtab.limit; 608 609 sym_init (symtab.limit); 610 symtab.limit->name = "<hicore>"; 611 symtab.limit->addr = max_vma + 1; 612 symtab.limit->end_addr = ~(bfd_vma) 0; 613 ++symtab.limit; 614 615 symtab.len = symtab.limit - symtab.base; 616 symtab_finalize (&symtab); 617 } 618 619 /* Read in symbol table from core. 620 One symbol per line of source code is entered. */ 621 622 void 623 core_create_line_syms () 624 { 625 char *prev_name, *prev_filename; 626 unsigned int prev_name_len, prev_filename_len; 627 bfd_vma vma, min_vma = ~(bfd_vma) 0, max_vma = 0; 628 Sym *prev, dummy, *sentinel, *sym; 629 const char *filename; 630 int prev_line_num; 631 Sym_Table ltab; 632 bfd_vma vma_high; 633 634 /* Create symbols for functions as usual. This is necessary in 635 cases where parts of a program were not compiled with -g. For 636 those parts we still want to get info at the function level. */ 637 core_create_function_syms (); 638 639 /* Pass 1: count the number of symbols. */ 640 641 /* To find all line information, walk through all possible 642 text-space addresses (one by one!) and get the debugging 643 info for each address. When the debugging info changes, 644 it is time to create a new symbol. 645 646 Of course, this is rather slow and it would be better if 647 BFD would provide an iterator for enumerating all line infos. */ 648 prev_name_len = PATH_MAX; 649 prev_filename_len = PATH_MAX; 650 prev_name = xmalloc (prev_name_len); 651 prev_filename = xmalloc (prev_filename_len); 652 ltab.len = 0; 653 prev_line_num = 0; 654 655 vma_high = core_text_sect->vma + bfd_get_section_size (core_text_sect); 656 for (vma = core_text_sect->vma; vma < vma_high; vma += min_insn_size) 657 { 658 unsigned int len; 659 660 if (!get_src_info (vma, &filename, &dummy.name, &dummy.line_num) 661 || (prev_line_num == dummy.line_num 662 && prev_name != NULL 663 && strcmp (prev_name, dummy.name) == 0 664 && strcmp (prev_filename, filename) == 0)) 665 continue; 666 667 ++ltab.len; 668 prev_line_num = dummy.line_num; 669 670 len = strlen (dummy.name); 671 if (len >= prev_name_len) 672 { 673 prev_name_len = len + 1024; 674 free (prev_name); 675 prev_name = xmalloc (prev_name_len); 676 } 677 678 strcpy (prev_name, dummy.name); 679 len = strlen (filename); 680 681 if (len >= prev_filename_len) 682 { 683 prev_filename_len = len + 1024; 684 free (prev_filename); 685 prev_filename = xmalloc (prev_filename_len); 686 } 687 688 strcpy (prev_filename, filename); 689 690 min_vma = MIN (vma, min_vma); 691 max_vma = MAX (vma, max_vma); 692 } 693 694 free (prev_name); 695 free (prev_filename); 696 697 /* Make room for function symbols, too. */ 698 ltab.len += symtab.len; 699 ltab.base = (Sym *) xmalloc (ltab.len * sizeof (Sym)); 700 ltab.limit = ltab.base; 701 702 /* Pass 2 - create symbols. */ 703 704 /* We now set is_static as we go along, rather than by running 705 through the symbol table at the end. 706 707 The old way called symtab_finalize before the is_static pass, 708 causing a problem since symtab_finalize uses is_static as part of 709 its address conflict resolution algorithm. Since global symbols 710 were prefered over static symbols, and all line symbols were 711 global at that point, static function names that conflicted with 712 their own line numbers (static, but labeled as global) were 713 rejected in favor of the line num. 714 715 This was not the desired functionality. We always want to keep 716 our function symbols and discard any conflicting line symbols. 717 Perhaps symtab_finalize should be modified to make this 718 distinction as well, but the current fix works and the code is a 719 lot cleaner now. */ 720 prev = 0; 721 722 for (vma = core_text_sect->vma; vma < vma_high; vma += min_insn_size) 723 { 724 sym_init (ltab.limit); 725 726 if (!get_src_info (vma, &filename, <ab.limit->name, <ab.limit->line_num) 727 || (prev && prev->line_num == ltab.limit->line_num 728 && strcmp (prev->name, ltab.limit->name) == 0 729 && strcmp (prev->file->name, filename) == 0)) 730 continue; 731 732 /* Make name pointer a malloc'ed string. */ 733 ltab.limit->name = xstrdup (ltab.limit->name); 734 ltab.limit->file = source_file_lookup_path (filename); 735 736 ltab.limit->addr = vma; 737 738 /* Set is_static based on the enclosing function, using either: 739 1) the previous symbol, if it's from the same function, or 740 2) a symtab lookup. */ 741 if (prev && ltab.limit->file == prev->file && 742 strcmp (ltab.limit->name, prev->name) == 0) 743 { 744 ltab.limit->is_static = prev->is_static; 745 } 746 else 747 { 748 sym = sym_lookup(&symtab, ltab.limit->addr); 749 ltab.limit->is_static = sym->is_static; 750 } 751 752 prev = ltab.limit; 753 754 DBG (AOUTDEBUG, printf ("[core_create_line_syms] %lu %s 0x%lx\n", 755 (unsigned long) (ltab.limit - ltab.base), 756 ltab.limit->name, 757 (unsigned long) ltab.limit->addr)); 758 ++ltab.limit; 759 } 760 761 /* Update sentinels. */ 762 sentinel = sym_lookup (&symtab, (bfd_vma) 0); 763 764 if (sentinel 765 && strcmp (sentinel->name, "<locore>") == 0 766 && min_vma <= sentinel->end_addr) 767 sentinel->end_addr = min_vma - 1; 768 769 sentinel = sym_lookup (&symtab, ~(bfd_vma) 0); 770 771 if (sentinel 772 && strcmp (sentinel->name, "<hicore>") == 0 773 && max_vma >= sentinel->addr) 774 sentinel->addr = max_vma + 1; 775 776 /* Copy in function symbols. */ 777 memcpy (ltab.limit, symtab.base, symtab.len * sizeof (Sym)); 778 ltab.limit += symtab.len; 779 780 if ((unsigned int) (ltab.limit - ltab.base) != ltab.len) 781 { 782 fprintf (stderr, 783 _("%s: somebody miscounted: ltab.len=%d instead of %ld\n"), 784 whoami, ltab.len, (long) (ltab.limit - ltab.base)); 785 done (1); 786 } 787 788 /* Finalize ltab and make it symbol table. */ 789 symtab_finalize (<ab); 790 free (symtab.base); 791 symtab = ltab; 792 } 793