1/* 2 * Copyright (c) 1999 Apple Computer, Inc. All rights reserved. 3 * 4 * @APPLE_LICENSE_HEADER_START@ 5 * 6 * This file contains Original Code and/or Modifications of Original Code 7 * as defined in and that are subject to the Apple Public Source License 8 * Version 2.0 (the 'License'). You may not use this file except in 9 * compliance with the License. Please obtain a copy of the License at 10 * http://www.opensource.apple.com/apsl/ and read it before using this 11 * file. 12 * 13 * The Original Code and all software distributed under the License are 14 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER 15 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, 16 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, 17 * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. 18 * Please see the License for the specific language governing rights and 19 * limitations under the License. 20 * 21 * @APPLE_LICENSE_HEADER_END@ 22 */ 23#ifndef RLD 24#include <stdio.h> 25#include <string.h> 26#include "stuff/ofile.h" 27#include "stuff/breakout.h" 28#include "stuff/rnd.h" 29 30static void check_object( 31 struct arch *arch, 32 struct member *member, 33 struct object *object); 34 35static void symbol_string_at_end( 36 struct arch *arch, 37 struct member *member, 38 struct object *object); 39 40static void dyld_order( 41 struct arch *arch, 42 struct member *member, 43 struct object *object); 44 45static void order_error( 46 struct arch *arch, 47 struct member *member, 48 char *reason); 49 50__private_extern__ 51void 52checkout( 53struct arch *archs, 54uint32_t narchs) 55{ 56 uint32_t i, j; 57 58 for(i = 0; i < narchs; i++){ 59 if(archs[i].type == OFILE_ARCHIVE){ 60 for(j = 0; j < archs[i].nmembers; j++){ 61 if(archs[i].members[j].type == OFILE_Mach_O){ 62 check_object(archs + i, archs[i].members + j, 63 archs[i].members[j].object); 64 } 65 } 66 } 67 else if(archs[i].type == OFILE_Mach_O){ 68 check_object(archs + i, NULL, archs[i].object); 69 } 70 } 71} 72 73static 74void 75check_object( 76struct arch *arch, 77struct member *member, 78struct object *object) 79{ 80 uint32_t i, ncmds, flags; 81 struct load_command *lc; 82 struct segment_command *sg; 83 struct segment_command_64 *sg64; 84 struct dylib_command *dl_id; 85 86 /* 87 * Set up the symtab load command field and link edit segment feilds in 88 * the object structure. 89 */ 90 object->st = NULL; 91 object->dyst = NULL; 92 object->hints_cmd = NULL; 93 object->seg_linkedit = NULL; 94 object->seg_linkedit64 = NULL; 95 object->code_sig_cmd = NULL; 96 dl_id = NULL; 97 lc = object->load_commands; 98 if(object->mh != NULL){ 99 ncmds = object->mh->ncmds; 100 flags = object->mh->flags; 101 } 102 else{ 103 ncmds = object->mh64->ncmds; 104 flags = object->mh64->flags; 105 } 106 for(i = 0; i < ncmds; i++){ 107 if(lc->cmd == LC_SYMTAB){ 108 if(object->st != NULL) 109 fatal_arch(arch, member, "malformed file (more than one " 110 "LC_SYMTAB load command): "); 111 object->st = (struct symtab_command *)lc; 112 } 113 else if(lc->cmd == LC_DYSYMTAB){ 114 if(object->dyst != NULL) 115 fatal_arch(arch, member, "malformed file (more than one " 116 "LC_DYSYMTAB load command): "); 117 object->dyst = (struct dysymtab_command *)lc; 118 } 119 else if(lc->cmd == LC_TWOLEVEL_HINTS){ 120 if(object->hints_cmd != NULL) 121 fatal_arch(arch, member, "malformed file (more than one " 122 "LC_TWOLEVEL_HINTS load command): "); 123 object->hints_cmd = (struct twolevel_hints_command *)lc; 124 } 125 else if(lc->cmd == LC_CODE_SIGNATURE){ 126 if(object->code_sig_cmd != NULL) 127 fatal_arch(arch, member, "malformed file (more than one " 128 "LC_CODE_SIGNATURE load command): "); 129 object->code_sig_cmd = (struct linkedit_data_command *)lc; 130 } 131 else if(lc->cmd == LC_SEGMENT_SPLIT_INFO){ 132 if(object->split_info_cmd != NULL) 133 fatal_arch(arch, member, "malformed file (more than one " 134 "LC_SEGMENT_SPLIT_INFO load command): "); 135 object->split_info_cmd = (struct linkedit_data_command *)lc; 136 } 137 else if(lc->cmd == LC_FUNCTION_STARTS){ 138 if(object->func_starts_info_cmd != NULL) 139 fatal_arch(arch, member, "malformed file (more than one " 140 "LC_FUNCTION_STARTS load command): "); 141 object->func_starts_info_cmd = 142 (struct linkedit_data_command *)lc; 143 } 144 else if(lc->cmd == LC_DATA_IN_CODE){ 145 if(object->data_in_code_cmd != NULL) 146 fatal_arch(arch, member, "malformed file (more than one " 147 "LC_DATA_IN_CODE load command): "); 148 object->data_in_code_cmd = 149 (struct linkedit_data_command *)lc; 150 } 151 else if(lc->cmd == LC_DYLIB_CODE_SIGN_DRS){ 152 if(object->code_sign_drs_cmd != NULL) 153 fatal_arch(arch, member, "malformed file (more than one " 154 "LC_DYLIB_CODE_SIGN_DRS load command): "); 155 object->code_sign_drs_cmd = 156 (struct linkedit_data_command *)lc; 157 } 158 else if((lc->cmd == LC_DYLD_INFO) ||(lc->cmd == LC_DYLD_INFO_ONLY)){ 159 if(object->dyld_info != NULL) 160 fatal_arch(arch, member, "malformed file (more than one " 161 "LC_DYLD_INFO load command): "); 162 object->dyld_info = (struct dyld_info_command *)lc; 163 } 164 else if(lc->cmd == LC_SEGMENT){ 165 sg = (struct segment_command *)lc; 166 if(strcmp(sg->segname, SEG_LINKEDIT) == 0){ 167 if(object->seg_linkedit != NULL) 168 fatal_arch(arch, member, "malformed file (more than " 169 "one " SEG_LINKEDIT "segment): "); 170 object->seg_linkedit = sg; 171 } 172 } 173 else if(lc->cmd == LC_SEGMENT_64){ 174 sg64 = (struct segment_command_64 *)lc; 175 if(strcmp(sg64->segname, SEG_LINKEDIT) == 0){ 176 if(object->seg_linkedit64 != NULL) 177 fatal_arch(arch, member, "malformed file (more than " 178 "one " SEG_LINKEDIT "segment): "); 179 object->seg_linkedit64 = sg64; 180 } 181 } 182 else if(lc->cmd == LC_ID_DYLIB){ 183 if(dl_id != NULL) 184 fatal_arch(arch, member, "malformed file (more than one " 185 "LC_ID_DYLIB load command): "); 186 dl_id = (struct dylib_command *)lc; 187 if(dl_id->dylib.name.offset >= dl_id->cmdsize) 188 fatal_arch(arch, member, "malformed file (name.offset of " 189 "load command %u extends past the end of the load " 190 "command): ", i); 191 } 192 lc = (struct load_command *)((char *)lc + lc->cmdsize); 193 } 194 if((object->mh_filetype == MH_DYLIB || 195 (object->mh_filetype == MH_DYLIB_STUB && ncmds > 0)) && 196 dl_id == NULL) 197 fatal_arch(arch, member, "malformed file (no LC_ID_DYLIB load " 198 "command in %s file): ", object->mh_filetype == MH_DYLIB ? 199 "MH_DYLIB" : "MH_DYLIB_STUB"); 200 if(object->hints_cmd != NULL){ 201 if(object->dyst == NULL && object->hints_cmd->nhints != 0) 202 fatal_arch(arch, member, "malformed file (LC_TWOLEVEL_HINTS " 203 "load command present without an LC_DYSYMTAB load command):"); 204 if(object->hints_cmd->nhints != 0 && 205 object->hints_cmd->nhints != object->dyst->nundefsym) 206 fatal_arch(arch, member, "malformed file (LC_TWOLEVEL_HINTS " 207 "load command's nhints does not match LC_DYSYMTAB load " 208 "command's nundefsym):"); 209 } 210 211 /* 212 * For objects without a dynamic symbol table check to see that the 213 * string table is at the end of the file and that the symbol table is 214 * just before it. 215 */ 216 if(object->dyst == NULL){ 217 symbol_string_at_end(arch, member, object); 218 } 219 else{ 220 /* 221 * This file has a dynamic symbol table command. We handle three 222 * cases, a dynamic shared library, a file for the dynamic linker, 223 * and a relocatable object file. Since it has a dynamic symbol 224 * table command it could have an indirect symbol table. 225 */ 226 if(object->mh_filetype == MH_DYLIB /* || 227 object->mh_filetype == MH_DYLIB_STUB */ ){ 228 /* 229 * This is a dynamic shared library. 230 * The order of the symbolic info is: 231 * local relocation entries 232 * symbol table 233 * local symbols 234 * defined external symbols 235 * undefined symbols 236 * two-level namespace hints 237 * external relocation entries 238 * indirect symbol table 239 * table of contents 240 * module table 241 * reference table 242 * string table 243 * strings for external symbols 244 * strings for local symbols 245 * code signature data (16 byte aligned) 246 */ 247 dyld_order(arch, member, object); 248 } 249 else if(flags & MH_DYLDLINK){ 250 /* 251 * This is a file for the dynamic linker (output of ld(1) with 252 * -output_for_dyld . That is the relocation entries are split 253 * into local and external and hanging off the dysymtab not off 254 * the sections. 255 * The order of the symbolic info is: 256 * local relocation entries 257 * symbol table 258 * local symbols (in order as appeared in stabs) 259 * defined external symbols (sorted by name) 260 * undefined symbols (sorted by name) 261 * external relocation entries 262 * indirect symbol table 263 * string table 264 * strings for external symbols 265 * strings for local symbols 266 * code signature data (16 byte aligned) 267 */ 268 dyld_order(arch, member, object); 269 } 270 else{ 271 /* 272 * This is a relocatable object file either the output of the 273 * assembler or output of ld(1) with -r. For the output of 274 * the assembler: 275 * The order of the symbolic info is: 276 * relocation entries (by section) 277 * indirect symbol table 278 * symbol table 279 * local symbols (in order as appeared in stabs) 280 * defined external symbols (sorted by name) 281 * undefined symbols (sorted by name) 282 * string table 283 * strings for external symbols 284 * strings for local symbols 285 * With this order the symbol table can be replaced and the 286 * relocation entries and the indirect symbol table entries 287 * can be updated in the file and not moved. 288 * For the output of ld -r: 289 * The order of the symbolic info is: 290 * relocation entries (by section) 291 * symbol table 292 * local symbols (in order as appeared in stabs) 293 * defined external symbols (sorted by name) 294 * undefined symbols (sorted by name) 295 * indirect symbol table 296 * string table 297 * strings for external symbols 298 * strings for local symbols 299 * code signature 300 */ 301 symbol_string_at_end(arch, member, object); 302 } 303 } 304} 305 306static 307void 308dyld_order( 309struct arch *arch, 310struct member *member, 311struct object *object) 312{ 313 uint32_t offset, rounded_offset, isym; 314 315 if(object->mh != NULL){ 316 if(object->seg_linkedit == NULL) 317 fatal_arch(arch, member, "malformed file (no " SEG_LINKEDIT 318 " segment): "); 319 if(object->seg_linkedit->filesize != 0 && 320 object->seg_linkedit->fileoff + 321 object->seg_linkedit->filesize != object->object_size) 322 fatal_arch(arch, member, "the " SEG_LINKEDIT " segment " 323 "does not cover the end of the file (can't " 324 "be processed) in: "); 325 326 offset = object->seg_linkedit->fileoff; 327 } 328 else{ 329 if(object->seg_linkedit64 == NULL) 330 fatal_arch(arch, member, "malformed file (no " SEG_LINKEDIT 331 " segment): "); 332 if(object->seg_linkedit64->filesize != 0 && 333 object->seg_linkedit64->fileoff + 334 object->seg_linkedit64->filesize != object->object_size) 335 fatal_arch(arch, member, "the " SEG_LINKEDIT " segment " 336 "does not cover the end of the file (can't " 337 "be processed) in: "); 338 339 offset = object->seg_linkedit64->fileoff; 340 } 341 if(object->dyld_info != NULL){ 342 /* dyld_info starts at beginning of __LINKEDIT */ 343 if (object->dyld_info->rebase_off != 0){ 344 if (object->dyld_info->rebase_off != offset) 345 order_error(arch, member, "dyld_info " 346 "out of place"); 347 } 348 else if (object->dyld_info->bind_off != 0){ 349 if (object->dyld_info->bind_off != offset) 350 order_error(arch, member, "dyld_info " 351 "out of place"); 352 } 353 /* update offset to end of dyld_info contents */ 354 if (object->dyld_info->export_size != 0) 355 offset = object->dyld_info->export_off + 356 object->dyld_info->export_size; 357 else if (object->dyld_info->lazy_bind_size != 0) 358 offset = object->dyld_info->lazy_bind_off + 359 object->dyld_info->lazy_bind_size; 360 else if (object->dyld_info->weak_bind_size != 0) 361 offset = object->dyld_info->weak_bind_off + 362 object->dyld_info->weak_bind_size; 363 else if (object->dyld_info->bind_size != 0) 364 offset = object->dyld_info->bind_off + 365 object->dyld_info->bind_size; 366 else if (object->dyld_info->rebase_size != 0) 367 offset = object->dyld_info->rebase_off + 368 object->dyld_info->rebase_size; 369 } 370 if(object->dyst->nlocrel != 0){ 371 if(object->dyst->locreloff != offset) 372 order_error(arch, member, "local relocation entries " 373 "out of place"); 374 offset += object->dyst->nlocrel * 375 sizeof(struct relocation_info); 376 } 377 if(object->split_info_cmd != NULL){ 378 if(object->split_info_cmd->dataoff != offset) 379 order_error(arch, member, "split info data out of place"); 380 offset += object->split_info_cmd->datasize; 381 } 382 if(object->func_starts_info_cmd != NULL){ 383 if(object->func_starts_info_cmd->dataoff != offset) 384 order_error(arch, member, "function starts data out of place"); 385 offset += object->func_starts_info_cmd->datasize; 386 } 387 if(object->data_in_code_cmd != NULL){ 388 if(object->data_in_code_cmd->dataoff != offset) 389 order_error(arch, member, "data in code info out of place"); 390 offset += object->data_in_code_cmd->datasize; 391 } 392 if(object->code_sign_drs_cmd != NULL){ 393 if(object->code_sign_drs_cmd->dataoff != offset) 394 order_error(arch, member, "code signing DRs info out of place"); 395 offset += object->code_sign_drs_cmd->datasize; 396 } 397 if(object->st->nsyms != 0){ 398 if(object->st->symoff != offset) 399 order_error(arch, member, "symbol table out of place"); 400 if(object->mh != NULL) 401 offset += object->st->nsyms * sizeof(struct nlist); 402 else 403 offset += object->st->nsyms * sizeof(struct nlist_64); 404 } 405 isym = 0; 406 if(object->dyst->nlocalsym != 0){ 407 if(object->dyst->ilocalsym != isym) 408 order_error(arch, member, "local symbols out of place"); 409 isym += object->dyst->nlocalsym; 410 } 411 if(object->dyst->nextdefsym != 0){ 412 if(object->dyst->iextdefsym != isym) 413 order_error(arch, member, "externally defined symbols out of " 414 "place"); 415 isym += object->dyst->nextdefsym; 416 } 417 if(object->dyst->nundefsym != 0){ 418 if(object->dyst->iundefsym != isym) 419 order_error(arch, member, "undefined symbols out of place"); 420 isym += object->dyst->nundefsym; 421 } 422 if(object->hints_cmd != NULL && object->hints_cmd->nhints != 0){ 423 if(object->hints_cmd->offset != offset) 424 order_error(arch, member, "hints table out of place"); 425 offset += object->hints_cmd->nhints * sizeof(struct twolevel_hint); 426 } 427 if(object->dyst->nextrel != 0){ 428 if(object->dyst->extreloff != offset) 429 order_error(arch, member, "external relocation entries" 430 " out of place"); 431 offset += object->dyst->nextrel * 432 sizeof(struct relocation_info); 433 } 434 if(object->dyst->nindirectsyms != 0){ 435 if(object->dyst->indirectsymoff != offset) 436 order_error(arch, member, "indirect symbol table " 437 "out of place"); 438 offset += object->dyst->nindirectsyms * 439 sizeof(uint32_t); 440 } 441 442 /* 443 * If this is a 64-bit Mach-O file and has an odd number of indirect 444 * symbol table entries the next offset MAYBE rounded to a multiple of 445 * 8 or MAY NOT BE. This should done to keep all the tables aligned but 446 * was not done for 64-bit Mach-O in Mac OS X 10.4. 447 */ 448 object->input_indirectsym_pad = 0; 449 if(object->mh64 != NULL && 450 (object->dyst->nindirectsyms % 2) != 0){ 451 rounded_offset = rnd(offset, 8); 452 } 453 else{ 454 rounded_offset = offset; 455 } 456 457 if(object->dyst->ntoc != 0){ 458 if(object->dyst->tocoff != offset && 459 object->dyst->tocoff != rounded_offset) 460 order_error(arch, member, "table of contents out of place"); 461 if(object->dyst->tocoff == offset){ 462 offset += object->dyst->ntoc * 463 sizeof(struct dylib_table_of_contents); 464 rounded_offset = offset; 465 } 466 else if(object->dyst->tocoff == rounded_offset){ 467 object->input_indirectsym_pad = rounded_offset - offset; 468 rounded_offset += object->dyst->ntoc * 469 sizeof(struct dylib_table_of_contents); 470 offset = rounded_offset; 471 } 472 } 473 if(object->dyst->nmodtab != 0){ 474 if(object->dyst->modtaboff != offset && 475 object->dyst->modtaboff != rounded_offset) 476 order_error(arch, member, "module table out of place"); 477 if(object->mh != NULL){ 478 offset += object->dyst->nmodtab * 479 sizeof(struct dylib_module); 480 rounded_offset = offset; 481 } 482 else{ 483 if(object->dyst->modtaboff == offset){ 484 offset += object->dyst->nmodtab * 485 sizeof(struct dylib_module_64); 486 rounded_offset = offset; 487 } 488 else if(object->dyst->modtaboff == rounded_offset){ 489 object->input_indirectsym_pad = rounded_offset - offset; 490 rounded_offset += object->dyst->nmodtab * 491 sizeof(struct dylib_module_64); 492 offset = rounded_offset; 493 } 494 } 495 } 496 if(object->dyst->nextrefsyms != 0){ 497 if(object->dyst->extrefsymoff != offset && 498 object->dyst->extrefsymoff != rounded_offset) 499 order_error(arch, member, "reference table out of place"); 500 if(object->dyst->extrefsymoff == offset){ 501 offset += object->dyst->nextrefsyms * 502 sizeof(struct dylib_reference); 503 rounded_offset = offset; 504 } 505 else if(object->dyst->extrefsymoff == rounded_offset){ 506 object->input_indirectsym_pad = rounded_offset - offset; 507 rounded_offset += object->dyst->nextrefsyms * 508 sizeof(struct dylib_reference); 509 offset = rounded_offset; 510 } 511 } 512 if(object->st->strsize != 0){ 513 if(object->st->stroff != offset && 514 object->st->stroff != rounded_offset) 515 order_error(arch, member, "string table out of place"); 516 if(object->st->stroff == offset){ 517 offset += object->st->strsize; 518 rounded_offset = offset; 519 } 520 else if(object->st->stroff == rounded_offset){ 521 object->input_indirectsym_pad = rounded_offset - offset; 522 rounded_offset += object->st->strsize; 523 offset = rounded_offset; 524 } 525 } 526 if(object->code_sig_cmd != NULL){ 527 rounded_offset = rnd(rounded_offset, 16); 528 if(object->code_sig_cmd->dataoff != rounded_offset) 529 order_error(arch, member, "code signature data out of place"); 530 rounded_offset += object->code_sig_cmd->datasize; 531 offset = rounded_offset; 532 } 533 if(offset != object->object_size && 534 rounded_offset != object->object_size) 535 order_error(arch, member, "link edit information does not fill the " 536 SEG_LINKEDIT " segment"); 537} 538 539static 540void 541order_error( 542struct arch *arch, 543struct member *member, 544char *reason) 545{ 546 fatal_arch(arch, member, "file not in an order that can be processed " 547 "(%s): ", reason); 548} 549 550static 551void 552symbol_string_at_end( 553struct arch *arch, 554struct member *member, 555struct object *object) 556{ 557 uint32_t end, sigend, strend, rounded_strend; 558 uint32_t indirectend, rounded_indirectend; 559 560 if(object->st != NULL && object->st->nsyms != 0){ 561 end = object->object_size; 562 if(object->code_sig_cmd != NULL){ 563 sigend = object->code_sig_cmd->dataoff + 564 object->code_sig_cmd->datasize; 565 if(sigend != end) 566 fatal_arch(arch, member, "code signature not at the end " 567 "of the file (can't be processed) in file: "); 568 /* 569 * The code signature starts at a 16 byte offset. So if the 570 * string table end rouned to 16 bytes is the offset where the 571 * code signature starts then just back up the current "end" to 572 * the end of the string table. 573 */ 574 end = object->code_sig_cmd->dataoff; 575 if(object->st->strsize != 0){ 576 strend = object->st->stroff + object->st->strsize; 577 rounded_strend = rnd(strend, 16); 578 if(object->code_sig_cmd->dataoff == rounded_strend) 579 end = strend; 580 } 581 } 582 if(object->st->strsize != 0){ 583 strend = object->st->stroff + object->st->strsize; 584 /* 585 * Since archive member sizes are now rounded to 8 bytes the 586 * string table may not be exactly at the end of the 587 * object_size due to rounding. 588 */ 589 rounded_strend = rnd(strend, 8); 590 if(strend != end && rounded_strend != end) 591 fatal_arch(arch, member, "string table not at the end " 592 "of the file (can't be processed) in file: "); 593 /* 594 * To make the code work that assumes the end of string table is 595 * at the end of the object file change the object_size to be 596 * the end of the string table here. This could be done at the 597 * end of this routine but since all the later checks are fatal 598 * we'll just do this here. 599 */ 600 if(rounded_strend != strend) 601 object->object_size = strend; 602 end = object->st->stroff; 603 } 604 if(object->dyst != NULL && 605 object->dyst->nindirectsyms != 0 && 606 object->st->nsyms != 0 && 607 object->dyst->indirectsymoff > object->st->symoff){ 608 609 indirectend = object->dyst->indirectsymoff + 610 object->dyst->nindirectsyms * sizeof(uint32_t); 611 612 /* 613 * If this is a 64-bit Mach-O file and has an odd number of 614 * indirect symbol table entries the next offset MAYBE rounded 615 * to a multiple of 8 or MAY NOT BE. This should done to keep 616 * all the tables aligned but was not done for 64-bit Mach-O in 617 * Mac OS X 10.4. 618 */ 619 if(object->mh64 != NULL && 620 (object->dyst->nindirectsyms % 2) != 0){ 621 rounded_indirectend = rnd(indirectend, 8); 622 } 623 else{ 624 rounded_indirectend = indirectend; 625 } 626 627 if(indirectend != end && rounded_indirectend != end){ 628 fatal_arch(arch, member, "indirect symbol table does not " 629 "directly preceed the string table (can't be " 630 "processed) in file: "); 631 } 632 object->input_indirectsym_pad = end - indirectend; 633 end = object->dyst->indirectsymoff; 634 if(object->mh != NULL){ 635 if(object->st->symoff + 636 object->st->nsyms * sizeof(struct nlist) != end) 637 fatal_arch(arch, member, "symbol table does not " 638 "directly preceed the indirect symbol table (can't " 639 "be processed) in file: "); 640 } 641 else{ 642 if(object->st->symoff + 643 object->st->nsyms * sizeof(struct nlist_64) != end) 644 fatal_arch(arch, member, "symbol table does not " 645 "directly preceed the indirect symbol table (can't " 646 "be processed) in file: "); 647 } 648 } 649 else{ 650 if(object->mh != NULL){ 651 if(object->st->symoff + 652 object->st->nsyms * sizeof(struct nlist) != end) 653 fatal_arch(arch, member, "symbol table and string " 654 "table not at the end of the file (can't be " 655 "processed) in file: "); 656 } 657 else{ 658 if(object->st->symoff + 659 object->st->nsyms * sizeof(struct nlist_64) != end) 660 fatal_arch(arch, member, "symbol table and string " 661 "table not at the end of the file (can't be " 662 "processed) in file: "); 663 } 664 } 665 if(object->seg_linkedit != NULL && 666 (object->seg_linkedit->flags & SG_FVMLIB) != SG_FVMLIB && 667 object->seg_linkedit->filesize != 0){ 668 if(object->seg_linkedit->fileoff + 669 object->seg_linkedit->filesize != object->object_size) 670 fatal_arch(arch, member, "the " SEG_LINKEDIT " segment " 671 "does not cover the symbol and string table (can't " 672 "be processed) in file: "); 673 } 674 } 675} 676#endif /* !defined(RLD) */ 677