1/* 2 * Copyright © 2009 Apple Inc. All rights reserved. 3 * 4 * @APPLE_LICENSE_HEADER_START@ 5 * 6 * Redistribution and use in source and binary forms, with or without 7 * modification, are permitted provided that the following conditions are met: 8 * 9 * 1. Redistributions of source code must retain the above copyright notice, 10 * this list of conditions and the following disclaimer. 11 * 2. Redistributions in binary form must reproduce the above copyright notice, 12 * this list of conditions and the following disclaimer in the documentation 13 * and/or other materials provided with the distribution. 14 * 3. Neither the name of Apple Inc. ("Apple") nor the names of its 15 * contributors may be used to endorse or promote products derived from this 16 * software without specific prior written permission. 17 * 18 * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY 19 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 20 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 21 * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY 22 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 23 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 24 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND 25 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 26 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 27 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 28 * 29 * @APPLE_LICENSE_HEADER_END@ 30 */ 31#define __darwin_i386_exception_state i386_exception_state 32#define __darwin_i386_float_state i386_float_state 33#define __darwin_i386_thread_state i386_thread_state 34 35#ifndef RLD 36#ifdef SHLIB 37#include "shlib.h" 38#endif 39#include <libc.h> 40#include <mach/mach.h> 41#include "stuff/openstep_mach.h" 42#include <stddef.h> 43#include <stdarg.h> 44#include <limits.h> 45#include <errno.h> 46#include <ctype.h> 47#include <ar.h> 48#include <sys/file.h> 49#include <sys/types.h> 50#include <sys/mman.h> 51#include <mach-o/fat.h> 52#include <mach-o/loader.h> 53#import <mach/m68k/thread_status.h> 54#import <mach/ppc/thread_status.h> 55#undef MACHINE_THREAD_STATE /* need to undef these to avoid warnings */ 56#undef MACHINE_THREAD_STATE_COUNT 57#undef THREAD_STATE_NONE 58#undef VALID_THREAD_STATE_FLAVOR 59#import <mach/m88k/thread_status.h> 60#import <mach/i860/thread_status.h> 61#import <mach/i386/thread_status.h> 62#import <mach/sparc/thread_status.h> 63#import <mach/arm/thread_status.h> 64#include <mach-o/nlist.h> 65#include <mach-o/reloc.h> 66#include "stuff/bool.h" 67#ifdef OFI 68#include <mach-o/dyld.h> 69#else 70#include "stuff/lto.h" 71#endif 72#include "stuff/bytesex.h" 73#include "stuff/arch.h" 74#include "stuff/rnd.h" 75#include "stuff/errors.h" 76#include "stuff/allocate.h" 77#include "stuff/ofile.h" 78#include "stuff/print.h" 79 80#ifdef OTOOL 81#undef ALIGNMENT_CHECKS 82#include "otool.h" 83#include "ofile_print.h" 84static enum bool otool_first_ofile_map = TRUE; 85#else /* !define(OTOOL) */ 86 87#if (!defined(m68k) && !defined(__i386__) && !defined(__x86_64__) && !defined(__ppc__) && !defined(__arm__)) 88#define ALIGNMENT_CHECKS_ARCHIVE_64_BIT 89static enum bool archive_64_bit_align_warning = FALSE; 90#endif /* (!defined(m68k) && !defined(__i386__) && !defined(__x86_64__) && !defined(__ppc__) && !defined(__arm__)) */ 91 92#endif /* OTOOL */ 93 94/* <mach/loader.h> */ 95/* The maximum section alignment allowed to be specified, as a power of two */ 96#define MAXSECTALIGN 15 /* 2**15 or 0x8000 */ 97 98enum check_type { 99 CHECK_BAD, 100 CHECK_GOOD 101}; 102 103#ifndef OTOOL 104struct element { 105 uint32_t offset; 106 uint32_t size; 107 char *name; 108 struct element *next; 109}; 110#endif /* !defined(OTOOL) */ 111 112static enum bool ofile_specific_arch( 113 struct ofile *ofile, 114 uint32_t narch); 115static enum check_type check_fat( 116 struct ofile *ofile); 117static enum check_type check_fat_object_in_archive( 118 struct ofile *ofile); 119static enum check_type check_archive( 120 struct ofile *ofile, 121 enum bool archives_with_fat_objects); 122static enum check_type check_extend_format_1( 123 struct ofile *ofile, 124 struct ar_hdr *ar_hdr, 125 uint32_t size_left, 126 uint32_t *member_name_size); 127static enum check_type check_archive_toc( 128 struct ofile *ofile); 129static enum check_type check_Mach_O( 130 struct ofile *ofile); 131static void swap_back_Mach_O( 132 struct ofile *ofile); 133#ifndef OTOOL 134static enum check_type check_overlaping_element( 135 struct ofile *ofile, 136 struct element *head, 137 uint32_t offset, 138 uint32_t size, 139 char *name); 140static void free_elements( 141 struct element *head); 142#endif /* !defined(OTOOL) */ 143static enum check_type check_dylib_module( 144 struct ofile *ofile, 145 struct symtab_command *st, 146 struct dysymtab_command *dyst, 147 char *strings, 148 uint32_t module_index); 149 150#ifndef OTOOL 151#if defined(ALIGNMENT_CHECKS) || defined(ALIGNMENT_CHECKS_ARCHIVE_64_BIT) 152static 153void 154temporary_archive_member_warning( 155struct ofile *ofile, 156const char *format, ...) 157{ 158 va_list ap; 159 160 va_start(ap, format); 161 if(ofile->file_type == OFILE_FAT){ 162 print("%s: for architecture %s archive member: %s(%.*s) ", 163 progname, ofile->arch_flag.name, ofile->file_name, 164 (int)ofile->member_name_size, ofile->member_name); 165 } 166 else{ 167 print("%s: archive member: %s(%.*s) ", progname, ofile->file_name, 168 (int)ofile->member_name_size, ofile->member_name); 169 } 170 vprint(format, ap); 171 print("\n"); 172 va_end(ap); 173} 174#endif /* defined(ALIGNMENT_CHECKS) */ 175#endif /* !defined(OTOOL) */ 176 177#ifndef OFI 178/* 179 * ofile_process() processes the specified file name can calls the routine 180 * processor on the ofiles in it. arch_flags is an array of architectures 181 * containing narch_flags which are the only architectures to process if 182 * narch_flags is non-zero. If all_archs is TRUE then all architectures of 183 * the specified file are processed. The specified file name can be of the 184 * form "archive(member)" which is taken to mean that member in that archive 185 * (or that module of a dynamic library if dylib_flat is not FALSE). 186 * For each ofile that is to be processed the routine processor is called with 187 * the corresponding ofile struct, the arch_name pass to it is either NULL or 188 * an architecture name (when it should be printed or show by processor) and 189 * cookie is the same value as passed to ofile_process. 190 */ 191__private_extern__ 192void 193ofile_process( 194char *name, 195struct arch_flag *arch_flags, 196uint32_t narch_flags, 197enum bool all_archs, 198enum bool process_non_objects, 199enum bool dylib_flat, 200enum bool use_member_syntax, 201void (*processor)(struct ofile *ofile, char *arch_name, void *cookie), 202void *cookie) 203{ 204 char *member_name, *p, *arch_name; 205 uint32_t len, i; 206 struct ofile ofile; 207 enum bool flag, hostflag, arch_found, family; 208 struct arch_flag host_arch_flag; 209 const struct arch_flag *family_arch_flag; 210 211 /* 212 * If use_member_syntax is TRUE look for a name of the form 213 * "archive(member)" which is to mean a member in that archive (the 214 * member name must be at least one character long to be recognized as 215 * this form). 216 */ 217 member_name = NULL; 218 if(use_member_syntax == TRUE){ 219 len = strlen(name); 220 if(len >= 4 && name[len-1] == ')'){ 221 p = strrchr(name, '('); 222 if(p != NULL && p != name){ 223 member_name = p+1; 224 *p = '\0'; 225 name[len-1] = '\0'; 226 } 227 } 228 } 229 230#ifdef OTOOL 231 otool_first_ofile_map = TRUE; 232#endif /* OTOOL */ 233 if(ofile_map(name, NULL, NULL, &ofile, FALSE) == FALSE) 234 return; 235#ifdef OTOOL 236 otool_first_ofile_map = FALSE; 237#endif /* OTOOL */ 238 239 if(ofile.file_type == OFILE_FAT){ 240 /* 241 * This is a fat file so see if a list of architecture is 242 * specified and process only those. 243 */ 244 if(all_archs == FALSE && narch_flags != 0){ 245 for(i = 0; i < narch_flags; i++){ 246 if(ofile_first_arch(&ofile) == FALSE){ 247 ofile_unmap(&ofile); 248 return; 249 } 250 arch_found = FALSE; 251 family = FALSE; 252 family_arch_flag = 253 get_arch_family_from_cputype(arch_flags[i].cputype); 254 if(family_arch_flag != NULL) 255 family = (enum bool) 256 ((family_arch_flag->cpusubtype & ~CPU_SUBTYPE_MASK) == 257 (arch_flags[i].cpusubtype & ~CPU_SUBTYPE_MASK)); 258 if(narch_flags != 1) 259 arch_name = ofile.arch_flag.name; 260 else 261 arch_name = NULL; 262 do{ 263 if(ofile.arch_flag.cputype == 264 arch_flags[i].cputype && 265 ((ofile.arch_flag.cpusubtype & ~CPU_SUBTYPE_MASK) == 266 (arch_flags[i].cpusubtype & ~CPU_SUBTYPE_MASK) || 267 family == TRUE)){ 268 arch_found = TRUE; 269 if(ofile.arch_type == OFILE_ARCHIVE){ 270 if(member_name != NULL){ 271 if(ofile_specific_member(member_name, 272 &ofile) == TRUE){ 273 processor(&ofile, arch_name, cookie); 274 if(ofile.headers_swapped == TRUE) 275 swap_back_Mach_O(&ofile); 276 } 277 } 278 else{ 279 /* loop through archive */ 280#ifdef OTOOL 281 printf("Archive : %s", ofile.file_name); 282 if(arch_name != NULL) 283 printf(" (architecture %s)", 284 arch_name); 285 printf("\n"); 286#endif /* OTOOL */ 287 if(ofile_first_member(&ofile) == TRUE){ 288 flag = FALSE; 289 do{ 290 if(process_non_objects == TRUE || 291 ofile.member_type == 292 OFILE_Mach_O){ 293 processor(&ofile, arch_name, 294 cookie); 295 if(ofile.headers_swapped ==TRUE) 296 swap_back_Mach_O(&ofile); 297 flag = TRUE; 298 } 299 }while(ofile_next_member(&ofile) == 300 TRUE); 301 if(flag == FALSE){ 302 error("for architecture: %s " 303 "archive: %s contains no " 304 "members that are object " 305 "files", ofile.arch_flag.name, 306 ofile.file_name); 307 } 308 } 309 else{ 310 error("for architecture: %s archive: " 311 "%s contains no members", 312 ofile.arch_flag.name, 313 ofile.file_name); 314 } 315 } 316 } 317 else if(process_non_objects == TRUE || 318 ofile.arch_type == OFILE_Mach_O){ 319 if(ofile.arch_type == OFILE_Mach_O && 320 (ofile.mh_filetype == MH_DYLIB || 321 ofile.mh_filetype == MH_DYLIB_STUB)){ 322 if(dylib_flat == TRUE){ 323 processor(&ofile, arch_name, cookie); 324 if(ofile.headers_swapped == TRUE) 325 swap_back_Mach_O(&ofile); 326 } 327 else{ 328 if(member_name != NULL){ 329 if(ofile_specific_module( 330 member_name, &ofile) == TRUE){ 331 processor(&ofile, arch_name, 332 cookie); 333 if(ofile.headers_swapped ==TRUE) 334 swap_back_Mach_O(&ofile); 335 } 336 } 337 else{ 338 /*loop through the dynamic library*/ 339 if(ofile_first_module(&ofile)){ 340 do{ 341 processor(&ofile, arch_name, 342 cookie); 343 }while(ofile_next_module( 344 &ofile)); 345 } 346 else{ 347 processor(&ofile, arch_name, 348 cookie); 349 } 350 } 351 } 352 if(ofile.headers_swapped == TRUE) 353 swap_back_Mach_O(&ofile); 354 } 355 else{ 356 if(member_name != NULL) 357 error("for architecture: %s file: %s " 358 "is not an archive and thus does " 359 "not contain member: %s", 360 ofile.arch_flag.name, 361 ofile.file_name, 362 member_name); 363 else{ 364 processor(&ofile, arch_name, cookie); 365 if(ofile.headers_swapped == TRUE) 366 swap_back_Mach_O(&ofile); 367 } 368 } 369 } 370 else if(ofile.arch_type == OFILE_UNKNOWN){ 371 error("for architecture: %s file: %s is " 372 "not an object file", 373 ofile.arch_flag.name,ofile.file_name); 374 } 375 if(ofile.headers_swapped == TRUE) 376 swap_back_Mach_O(&ofile); 377 break; 378 } 379 else{ 380 if(ofile.headers_swapped == TRUE) 381 swap_back_Mach_O(&ofile); 382 } 383 }while(ofile_next_arch(&ofile) == TRUE); 384 if(arch_found == FALSE) 385 error("file: %s does not contain architecture: %s", 386 ofile.file_name, arch_flags[i].name); 387 } 388 ofile_unmap(&ofile); 389 return; 390 } 391 392 /* 393 * This is a fat file and no architectures has been specified 394 * so if it contains the host architecture process only that 395 * architecture but if not process all architectures 396 * specified. 397 */ 398 if(all_archs == FALSE){ 399 (void)get_arch_from_host(&host_arch_flag, NULL); 400#if __LP64__ 401 /* 402 * If runing as a 64-bit binary and on an Intel x86 host 403 * default to 64-bit. 404 */ 405 if(host_arch_flag.cputype == CPU_TYPE_I386) 406 host_arch_flag = 407 *get_arch_family_from_cputype(CPU_TYPE_X86_64); 408#endif /* __LP64__ */ 409 hostflag = FALSE; 410 411 family = FALSE; 412 family_arch_flag = 413 get_arch_family_from_cputype(host_arch_flag.cputype); 414 if(family_arch_flag != NULL) 415 family = (enum bool) 416 ((family_arch_flag->cpusubtype & ~CPU_SUBTYPE_MASK) == 417 (host_arch_flag.cpusubtype & ~CPU_SUBTYPE_MASK)); 418 419 ofile_unmap(&ofile); 420 if(ofile_map(name, NULL, NULL, &ofile, FALSE) == FALSE) 421 return; 422 if(ofile_first_arch(&ofile) == FALSE){ 423 ofile_unmap(&ofile); 424 return; 425 } 426 do{ 427 if(ofile.arch_flag.cputype == 428 host_arch_flag.cputype && 429 ((ofile.arch_flag.cpusubtype & ~CPU_SUBTYPE_MASK) == 430 (host_arch_flag.cpusubtype & ~CPU_SUBTYPE_MASK) || 431 family == TRUE)){ 432 hostflag = TRUE; 433 if(ofile.arch_type == OFILE_ARCHIVE){ 434 if(member_name != NULL){ 435 if(ofile_specific_member(member_name, 436 &ofile) == TRUE){ 437 processor(&ofile, NULL, cookie); 438 if(ofile.headers_swapped == TRUE) 439 swap_back_Mach_O(&ofile); 440 } 441 } 442 else{ 443 /* loop through archive */ 444#ifdef OTOOL 445 printf("Archive : %s\n", ofile.file_name); 446#endif /* OTOOL */ 447 if(ofile_first_member(&ofile) == TRUE){ 448 flag = FALSE; 449 do{ 450 if(process_non_objects == TRUE || 451 ofile.member_type == OFILE_Mach_O){ 452 processor(&ofile, NULL, cookie); 453 if(ofile.headers_swapped == TRUE) 454 swap_back_Mach_O(&ofile); 455 flag = TRUE; 456 } 457 }while(ofile_next_member(&ofile) == 458 TRUE); 459 if(flag == FALSE){ 460 error("archive: %s contains no " 461 "members that are object " 462 "files", ofile.file_name); 463 } 464 } 465 else{ 466 error("archive: %s contains no " 467 "members", ofile.file_name); 468 } 469 } 470 } 471 else if(process_non_objects == TRUE || 472 ofile.arch_type == OFILE_Mach_O){ 473 if(ofile.arch_type == OFILE_Mach_O && 474 (ofile.mh_filetype == MH_DYLIB || 475 ofile.mh_filetype == MH_DYLIB_STUB)){ 476 if(dylib_flat == TRUE){ 477 processor(&ofile, NULL, cookie); 478 } 479 else{ 480 if(member_name != NULL){ 481 if(ofile_specific_module(member_name, 482 &ofile) == TRUE) 483 processor(&ofile, NULL, cookie); 484 } 485 else{ 486 /* loop through the dynamic library */ 487 if(ofile_first_module(&ofile) == TRUE){ 488 do{ 489 processor(&ofile, NULL, cookie); 490 }while(ofile_next_module(&ofile)); 491 } 492 else{ 493 processor(&ofile, NULL, cookie); 494 } 495 } 496 } 497 if(ofile.headers_swapped == TRUE) 498 swap_back_Mach_O(&ofile); 499 } 500 else{ 501 if(member_name != NULL) 502 error("for architecture: %s file: %s is " 503 "not an archive and thus does not " 504 "contain member: %s", 505 ofile.arch_flag.name, ofile.file_name, 506 member_name); 507 else{ 508 processor(&ofile, NULL, cookie); 509 if(ofile.headers_swapped == TRUE) 510 swap_back_Mach_O(&ofile); 511 } 512 } 513 } 514 else if(ofile.arch_type == OFILE_UNKNOWN){ 515 error("file: %s is not an object file", 516 ofile.file_name); 517 } 518 } 519 else{ 520 if(ofile.headers_swapped == TRUE) 521 swap_back_Mach_O(&ofile); 522 } 523 }while(hostflag == FALSE && ofile_next_arch(&ofile) == TRUE); 524 if(hostflag == TRUE){ 525 ofile_unmap(&ofile); 526 return; 527 } 528 } 529 530 /* 531 * Either all architectures have been specified or none have 532 * been specified and it does not contain the host architecture 533 * so do all the architectures in the fat file 534 */ 535 ofile_unmap(&ofile); 536 if(ofile_map(name, NULL, NULL, &ofile, FALSE) == FALSE) 537 return; 538 if(ofile_first_arch(&ofile) == FALSE){ 539 ofile_unmap(&ofile); 540 return; 541 } 542 do{ 543 if(ofile.arch_type == OFILE_ARCHIVE){ 544 if(member_name != NULL){ 545 if(ofile_specific_member(member_name, &ofile) == TRUE) 546 processor(&ofile, ofile.arch_flag.name, cookie); 547 } 548 else{ 549 /* loop through archive */ 550#ifdef OTOOL 551 printf("Archive : %s (architecture %s)\n", 552 ofile.file_name, ofile.arch_flag.name); 553#endif /* OTOOL */ 554 if(ofile_first_member(&ofile) == TRUE){ 555 flag = FALSE; 556 do{ 557 if(process_non_objects == TRUE || 558 ofile.member_type == OFILE_Mach_O){ 559 processor(&ofile, ofile.arch_flag.name, 560 cookie); 561 flag = TRUE; 562 } 563 }while(ofile_next_member(&ofile) == TRUE); 564 if(flag == FALSE){ 565 error("for architecture: %s archive: %s " 566 "contains no members that are object " 567 "files", ofile.arch_flag.name, 568 ofile.file_name); 569 } 570 } 571 else{ 572 error("for architecture: %s archive: %s " 573 "contains no members", 574 ofile.arch_flag.name, ofile.file_name); 575 } 576 } 577 } 578 else if(process_non_objects == TRUE || 579 ofile.arch_type == OFILE_Mach_O){ 580 if(ofile.arch_type == OFILE_Mach_O && 581 (ofile.mh_filetype == MH_DYLIB || 582 ofile.mh_filetype == MH_DYLIB_STUB)){ 583 if(dylib_flat == TRUE){ 584 processor(&ofile, ofile.arch_flag.name, cookie); 585 } 586 else{ 587 if(member_name != NULL){ 588 if(ofile_specific_module(member_name, &ofile) 589 == TRUE) 590 processor(&ofile, ofile.arch_flag.name, 591 cookie); 592 } 593 else{ 594 /* loop through the dynamic library */ 595 if(ofile_first_module(&ofile) == TRUE){ 596 do{ 597 processor(&ofile, ofile.arch_flag.name, 598 cookie); 599 }while(ofile_next_module(&ofile) == TRUE); 600 } 601 else{ 602 processor(&ofile, ofile.arch_flag.name, 603 cookie); 604 } 605 } 606 } 607 } 608 else{ 609 if(member_name != NULL) 610 error("for architecture: %s file: %s is not an " 611 "archive and thus does not contain member: " 612 "%s", ofile.arch_flag.name, ofile.file_name, 613 member_name); 614 else 615 processor(&ofile, ofile.arch_flag.name, cookie); 616 } 617 } 618 else if(ofile.arch_type == OFILE_UNKNOWN){ 619 error("for architecture: %s file: %s is not an " 620 "object file", ofile.arch_flag.name, 621 ofile.file_name); 622 } 623 }while(ofile_next_arch(&ofile) == TRUE); 624 } 625 else if(ofile.file_type == OFILE_ARCHIVE){ 626 if(narch_flags != 0){ 627 arch_found = FALSE; 628 for(i = 0; i < narch_flags; i++){ 629 family = FALSE; 630 if(narch_flags == 1){ 631 family_arch_flag = 632 get_arch_family_from_cputype(arch_flags[0].cputype); 633 if(family_arch_flag != NULL) 634 family = (enum bool) 635 ((family_arch_flag->cpusubtype & 636 ~CPU_SUBTYPE_MASK) == 637 (arch_flags[0].cpusubtype & 638 ~CPU_SUBTYPE_MASK)); 639 } 640 if(ofile.archive_cputype == arch_flags[i].cputype && 641 ((ofile.archive_cpusubtype & ~CPU_SUBTYPE_MASK) == 642 (arch_flags[i].cpusubtype & ~CPU_SUBTYPE_MASK) || 643 family == TRUE)){ 644 arch_found = TRUE; 645 } 646 else{ 647 error("file: %s does not contain architecture: %s", 648 ofile.file_name, arch_flags[i].name); 649 } 650 } 651 if(arch_found == FALSE){ 652 ofile_unmap(&ofile); 653 return; 654 } 655 } 656 if(member_name != NULL){ 657 if(ofile_specific_member(member_name, &ofile) == TRUE) 658 processor(&ofile, NULL, cookie); 659 } 660 else{ 661 /* loop through archive */ 662#ifdef OTOOL 663 printf("Archive : %s\n", ofile.file_name); 664#endif /* OTOOL */ 665 if(ofile_first_member(&ofile) == TRUE){ 666 flag = FALSE; 667 do{ 668 if(process_non_objects == TRUE || 669 ofile.member_type == OFILE_Mach_O){ 670 processor(&ofile, NULL, cookie); 671 flag = TRUE; 672 } 673 }while(ofile_next_member(&ofile) == TRUE); 674 if(flag == FALSE){ 675 error("archive: %s contains no members that are " 676 "object files", ofile.file_name); 677 } 678 } 679 else{ 680 error("archive: %s contains no members", 681 ofile.file_name); 682 } 683 } 684 } 685 else if(ofile.file_type == OFILE_Mach_O){ 686 if(narch_flags != 0){ 687 arch_found = FALSE; 688 for(i = 0; i < narch_flags; i++){ 689 family = FALSE; 690 if(narch_flags == 1){ 691 family_arch_flag = 692 get_arch_family_from_cputype(arch_flags[0].cputype); 693 if(family_arch_flag != NULL) 694 family = (enum bool) 695 ((family_arch_flag->cpusubtype & 696 ~CPU_SUBTYPE_MASK) == 697 (arch_flags[0].cpusubtype & 698 ~CPU_SUBTYPE_MASK)); 699 } 700#ifdef OTOOL 701 if(ofile.mh != NULL){ 702 if(ofile.mh->magic == MH_MAGIC && 703 ofile.mh->cputype == arch_flags[i].cputype && 704 ((ofile.mh->cpusubtype & ~CPU_SUBTYPE_MASK) == 705 (arch_flags[i].cpusubtype & ~CPU_SUBTYPE_MASK) || 706 family == TRUE)){ 707 arch_found = TRUE; 708 } 709 if(ofile.mh->magic == SWAP_INT(MH_MAGIC) && 710 (cpu_type_t)SWAP_INT(ofile.mh->cputype) == 711 arch_flags[i].cputype && 712 ((cpu_subtype_t)SWAP_INT(ofile.mh->cpusubtype & 713 ~CPU_SUBTYPE_MASK) == 714 (arch_flags[i].cpusubtype & 715 ~CPU_SUBTYPE_MASK) || 716 family == TRUE)){ 717 arch_found = TRUE; 718 } 719 } 720 else if(ofile.mh64 != NULL){ 721 if(ofile.mh64->magic == MH_MAGIC_64 && 722 ofile.mh64->cputype == arch_flags[i].cputype && 723 ((ofile.mh64->cpusubtype & ~CPU_SUBTYPE_MASK) == 724 (arch_flags[i].cpusubtype & ~CPU_SUBTYPE_MASK) || 725 family == TRUE)){ 726 arch_found = TRUE; 727 } 728 if(ofile.mh64->magic == SWAP_INT(MH_MAGIC_64) && 729 (cpu_type_t)SWAP_INT(ofile.mh64->cputype) == 730 arch_flags[i].cputype && 731 ((cpu_subtype_t)SWAP_INT((ofile.mh64->cpusubtype & 732 ~CPU_SUBTYPE_MASK)) == 733 (arch_flags[i].cpusubtype & ~CPU_SUBTYPE_MASK) || 734 family == TRUE)){ 735 arch_found = TRUE; 736 } 737 } 738 else 739#endif /* OTOOL */ 740 if(ofile.mh_cputype == arch_flags[i].cputype && 741 ((ofile.mh_cpusubtype & ~CPU_SUBTYPE_MASK) == 742 (arch_flags[i].cpusubtype & ~CPU_SUBTYPE_MASK) || 743 family == TRUE)){ 744 arch_found = TRUE; 745 } 746 else{ 747 error("file: %s does not contain architecture: %s", 748 ofile.file_name, arch_flags[i].name); 749 } 750 } 751 if(arch_found == FALSE){ 752 ofile_unmap(&ofile); 753 return; 754 } 755 } 756 if(ofile.mh_filetype == MH_DYLIB || 757 ofile.mh_filetype == MH_DYLIB_STUB){ 758 if(dylib_flat == TRUE){ 759 processor(&ofile, NULL, cookie); 760 } 761 else{ 762 if(member_name != NULL){ 763 if(ofile_specific_module(member_name, &ofile) == TRUE) 764 processor(&ofile, NULL, cookie); 765 } 766 else{ 767 /* loop through the dynamic library */ 768 if(ofile_first_module(&ofile) == TRUE){ 769 do{ 770 processor(&ofile, NULL, cookie); 771 }while(ofile_next_module(&ofile) == TRUE); 772 } 773 else{ 774 processor(&ofile, NULL, cookie); 775 } 776 } 777 } 778 } 779 else{ 780 if(member_name != NULL) 781 error("file: %s is not an archive and thus does not contain" 782 " member: %s", ofile.file_name, member_name); 783 else 784 processor(&ofile, NULL, cookie); 785 } 786 } 787 else{ 788 if(process_non_objects == TRUE) 789 processor(&ofile, NULL, cookie); 790 else if(member_name != NULL) 791 error("file: %s(%s) is not an object file", name, 792 member_name); 793 else 794 error("file: %s is not an object file", name); 795 } 796 ofile_unmap(&ofile); 797} 798#endif /* !defined(OFI) */ 799 800/* 801 * ofile_map maps in the object file specified by file_name, arch_flag and 802 * object_name and fills in the ofile struct pointed to by ofile for it. 803 * When arch_flag and object_name are both NULL, the file is just set up into 804 * ofile (if the file can be opened and mapped in, if not this call fails 805 * are error routnes are called). If arch_flag is not NULL and object_file is 806 * NULL, then the file must be a Mach-O file or a fat file with the architecture 807 * specified in the arch_flag, if not this call fails and error routines are 808 * called. When arch_flag and object_name are both not NULL, then the file must 809 * be an archive or a fat file containing archives for the specified architec- 810 * ture and contain an archive member object file with the name object_name, 811 * otherwise this call fails and error routines are called. If arch_flag is 812 * NULL and object_file is not NULL, then the file name must be an archive (not 813 * a fat file containing archives) and contain an archive member object file 814 * with the name object_name, otherwise this call fails and calls error 815 * routines. If this call suceeds then it returns non-zero and the ofile 816 * structure pointed to by ofile is filled in. If this call fails it returns 0 817 * and calls error routines to print error messages and clears the 818 * ofile structure pointed to by ofile. 819 */ 820__private_extern__ 821#ifdef OFI 822NSObjectFileImageReturnCode 823#else 824enum bool 825#endif 826ofile_map( 827const char *file_name, 828const struct arch_flag *arch_flag, /* can be NULL */ 829const char *object_name, /* can be NULL */ 830struct ofile *ofile, 831enum bool archives_with_fat_objects) 832{ 833 int fd; 834 struct stat stat_buf; 835 uint64_t size; 836 uint32_t magic; 837 char *addr; 838 839 magic = 0; /* to shut up the compiler warning message */ 840 memset(ofile, '\0', sizeof(struct ofile)); 841 842 /* Open the file and map it in */ 843 if((fd = open(file_name, O_RDONLY)) == -1){ 844#ifdef OFI 845 return(NSObjectFileImageAccess); 846#else 847 system_error("can't open file: %s", file_name); 848 return(FALSE); 849#endif 850 } 851 if(fstat(fd, &stat_buf) == -1){ 852 close(fd); 853#ifdef OFI 854 return(NSObjectFileImageAccess); 855#else 856 system_error("can't stat file: %s", file_name); 857 return(FALSE); 858#endif 859 } 860 size = stat_buf.st_size; 861 862 addr = NULL; 863 if(size != 0){ 864 addr = mmap(0, size, PROT_READ|PROT_WRITE, MAP_FILE|MAP_PRIVATE, fd, 865 0); 866 if((intptr_t)addr == -1){ 867 system_error("can't map file: %s", file_name); 868 close(fd); 869 return(FALSE); 870 } 871 } 872 close(fd); 873#ifdef OTOOL 874 if(otool_first_ofile_map && Wflag) 875 printf("Modification time = %ld\n", (long int)stat_buf.st_mtime); 876#endif /* OTOOL */ 877 878 return(ofile_map_from_memory(addr, size, file_name, stat_buf.st_mtime, 879 arch_flag, object_name, ofile, archives_with_fat_objects)); 880} 881 882/* 883 * ofile_map_from_memory() is the guts of ofile_map() but with an interface 884 * to pass the address and size of the file already mapped in. 885 */ 886__private_extern__ 887#ifdef OFI 888NSObjectFileImageReturnCode 889#else 890enum bool 891#endif 892ofile_map_from_memory( 893char *addr, 894uint64_t size, 895const char *file_name, 896uint64_t mtime, 897const struct arch_flag *arch_flag, /* can be NULL */ 898const char *object_name, /* can be NULL */ 899struct ofile *ofile, 900enum bool archives_with_fat_objects) 901{ 902 uint32_t i; 903 uint32_t magic; 904 enum byte_sex host_byte_sex; 905 struct arch_flag host_arch_flag; 906 enum bool family; 907 const struct arch_flag *family_arch_flag; 908 uint64_t big_size; 909#ifdef OTOOL 910 uint32_t small_nfat_arch; 911#endif /* OTOOL */ 912 913 /* fill in the start of the ofile structure */ 914 ofile->file_name = savestr(file_name); 915 if(ofile->file_name == NULL) 916 return(FALSE); 917 ofile->file_addr = addr; 918 ofile->file_size = size; 919 ofile->file_mtime = mtime; 920 921 /* Try to figure out what kind of file this is */ 922 923 if(size >= sizeof(uint32_t)){ 924 magic = *((uint32_t *)addr); 925 } 926 host_byte_sex = get_host_byte_sex(); 927 928 /* see if this file is a fat file (always in big endian byte sex) */ 929#ifdef __BIG_ENDIAN__ 930 if(size >= sizeof(struct fat_header) && magic == FAT_MAGIC) 931#endif /* __BIG_ENDIAN__ */ 932#ifdef __LITTLE_ENDIAN__ 933 if(size >= sizeof(struct fat_header) && SWAP_INT(magic) == FAT_MAGIC) 934#endif /* __LITTLE_ENDIAN__ */ 935 { 936 ofile->file_type = OFILE_FAT; 937 ofile->fat_header = (struct fat_header *)addr; 938#ifdef __LITTLE_ENDIAN__ 939 swap_fat_header(ofile->fat_header, host_byte_sex); 940#endif /* __LITTLE_ENDIAN__ */ 941#ifdef OTOOL 942 if(otool_first_ofile_map && fflag) 943 printf("Fat headers\n"); 944#endif /* OTOOL */ 945 big_size = ofile->fat_header->nfat_arch; 946 big_size *= sizeof(struct fat_arch); 947 big_size += sizeof(struct fat_header); 948 if(big_size > size){ 949#ifdef OTOOL 950 error("fat file: %s truncated or malformed (fat_arch structs " 951 "would extend past the end of the file)", file_name); 952 ofile->fat_archs = allocate(size - sizeof(struct fat_header)); 953 memset(ofile->fat_archs, '\0', 954 size - sizeof(struct fat_header)); 955 memcpy(ofile->fat_archs, 956 addr + sizeof(struct fat_header), 957 size - sizeof(struct fat_header)); 958 small_nfat_arch = (size - sizeof(struct fat_header)) / 959 sizeof(struct fat_arch); 960#ifdef __LITTLE_ENDIAN__ 961 swap_fat_arch(ofile->fat_archs, small_nfat_arch, 962 host_byte_sex); 963#endif /* __LITTLE_ENDIAN__ */ 964 if(otool_first_ofile_map && fflag) 965 print_fat_headers(ofile->fat_header, ofile->fat_archs, 966 size, vflag); 967 free(ofile->fat_archs); 968 ofile_unmap(ofile); 969 return(FALSE); 970#else /* !defined(OTOOL) */ 971 goto unknown; 972#endif /* OTOOL */ 973 } 974 ofile->fat_archs = (struct fat_arch *)(addr + 975 sizeof(struct fat_header)); 976#ifdef __LITTLE_ENDIAN__ 977 swap_fat_arch(ofile->fat_archs, ofile->fat_header->nfat_arch, 978 host_byte_sex); 979#endif /* __LITTLE_ENDIAN__ */ 980#ifdef OTOOL 981 if(otool_first_ofile_map && fflag) 982 print_fat_headers(ofile->fat_header, ofile->fat_archs, 983 size, vflag); 984#endif /* OTOOL */ 985 if(check_fat(ofile) == CHECK_BAD){ 986 ofile_unmap(ofile); 987#ifdef OFI 988 return(NSObjectFileImageFormat); 989#else 990 return(FALSE); 991#endif 992 } 993 /* 994 * Now that the fat file is mapped fill in the ofile to the level 995 * the caller wants based on the arch_flag and object_name passed. 996 * If the caller did not specify an arch_flag or an object_name 997 * then everything the caller wants is done. 998 */ 999 if(arch_flag == NULL && object_name == NULL) 1000 goto success; 1001 if(arch_flag == NULL){ 1002 if(get_arch_from_host(&host_arch_flag, NULL) == 0){ 1003 error("can't determine the host architecture (specify an " 1004 "arch_flag or fix get_arch_from_host() )"); 1005 goto cleanup; 1006 } 1007 ofile->arch_flag.name = savestr(host_arch_flag.name); 1008 if(ofile->arch_flag.name == NULL) 1009 goto cleanup; 1010 ofile->arch_flag.cputype = host_arch_flag.cputype; 1011 ofile->arch_flag.cpusubtype = host_arch_flag.cpusubtype; 1012 } 1013 else{ 1014 ofile->arch_flag.name = savestr(arch_flag->name); 1015 if(ofile->arch_flag.name == NULL) 1016 goto cleanup; 1017 ofile->arch_flag.cputype = arch_flag->cputype; 1018 ofile->arch_flag.cpusubtype = arch_flag->cpusubtype; 1019 } 1020 1021 ofile->narch = UINT_MAX; 1022 for(i = 0; i < ofile->fat_header->nfat_arch; i++){ 1023 if(ofile->fat_archs[i].cputype == 1024 ofile->arch_flag.cputype && 1025 (ofile->fat_archs[i].cpusubtype & ~CPU_SUBTYPE_MASK) == 1026 (ofile->arch_flag.cpusubtype & ~CPU_SUBTYPE_MASK)){ 1027 ofile->narch = i; 1028 break; 1029 } 1030 } 1031 if(ofile->narch == UINT_MAX){ 1032 family = FALSE; 1033 family_arch_flag = 1034 get_arch_family_from_cputype(ofile->arch_flag.cputype); 1035 if(family_arch_flag != NULL) 1036 family = (enum bool) 1037 ((family_arch_flag->cpusubtype & ~CPU_SUBTYPE_MASK) == 1038 (ofile->arch_flag.cpusubtype & ~CPU_SUBTYPE_MASK)); 1039 ofile->narch = UINT_MAX; 1040 for(i = 0; i < ofile->fat_header->nfat_arch; i++){ 1041 if(ofile->fat_archs[i].cputype == 1042 ofile->arch_flag.cputype && 1043 (family == TRUE || 1044 (ofile->fat_archs[i].cpusubtype & ~CPU_SUBTYPE_MASK) == 1045 (ofile->arch_flag.cpusubtype & ~CPU_SUBTYPE_MASK))){ 1046 ofile->arch_flag.cpusubtype = 1047 ofile->fat_archs[i].cpusubtype; 1048 ofile->narch = i; 1049 break; 1050 } 1051 } 1052 } 1053 if(ofile->narch == UINT_MAX){ 1054#ifdef OFI 1055 ofile_unmap(ofile); 1056 return(NSObjectFileImageArch); 1057#else 1058 error("fat file: %s does not contain architecture %s", 1059 ofile->file_name, arch_flag->name); 1060 ofile_unmap(ofile); 1061 return(FALSE); 1062#endif 1063 } 1064 /* Now determine the file type for this specific architecture */ 1065 size = ofile->fat_archs[i].size; 1066 addr = addr + ofile->fat_archs[i].offset; 1067 if(size >= sizeof(struct mach_header)) 1068 memcpy(&magic, addr, sizeof(uint32_t)); 1069 /* see if this file is a 32-bit Mach-O file */ 1070 if(size >= sizeof(struct mach_header) && 1071 (magic == MH_MAGIC || 1072 magic == SWAP_INT(MH_MAGIC))){ 1073#ifdef ALIGNMENT_CHECKS 1074 if(ofile->fat_archs[i].offset % 4 != 0){ 1075 error("fat file: %s architecture %s malformed for a 32-bit " 1076 "object file (offset is not a multiple of 4)", 1077 ofile->file_name, arch_flag->name); 1078 ofile_unmap(ofile); 1079#ifdef OFI 1080 return(NSObjectFileImageFormat); 1081#else 1082 return(FALSE); 1083#endif 1084 } 1085#endif /* ALIGNMENT_CHECKS */ 1086 ofile->arch_type = OFILE_Mach_O; 1087 ofile->object_addr = addr; 1088 ofile->object_size = size; 1089 if(magic == MH_MAGIC) 1090 ofile->object_byte_sex = host_byte_sex; 1091 else 1092 ofile->object_byte_sex = 1093 host_byte_sex == BIG_ENDIAN_BYTE_SEX ? 1094 LITTLE_ENDIAN_BYTE_SEX : BIG_ENDIAN_BYTE_SEX; 1095 ofile->mh = (struct mach_header *)addr; 1096 ofile->load_commands = (struct load_command *)(addr + 1097 sizeof(struct mach_header)); 1098 if(check_Mach_O(ofile) == CHECK_BAD){ 1099 ofile_unmap(ofile); 1100#ifdef OFI 1101 return(NSObjectFileImageFormat); 1102#else 1103 return(FALSE); 1104#endif 1105 } 1106 if(object_name != NULL){ 1107 error("fat file: %s architecture %s is not an archive " 1108 "(object_name to ofile_map() can't be specified to " 1109 "be other than NULL)", ofile->file_name, 1110 arch_flag->name); 1111 goto cleanup; 1112 } 1113 } 1114 /* see if this file is a 64-bit Mach-O file */ 1115 else if(size >= sizeof(struct mach_header_64) && 1116 (magic == MH_MAGIC_64 || 1117 magic == SWAP_INT(MH_MAGIC_64))){ 1118#ifdef ALIGNMENT_CHECKS 1119 if(ofile->fat_archs[i].offset % 8 != 0){ 1120 error("fat file: %s architecture %s malformed for a 64-bit " 1121 "object file (offset is not a multiple of 8)", 1122 ofile->file_name, arch_flag->name); 1123 ofile_unmap(ofile); 1124#ifdef OFI 1125 return(NSObjectFileImageFormat); 1126#else 1127 return(FALSE); 1128#endif 1129 } 1130#endif /* ALIGNMENT_CHECKS */ 1131 ofile->arch_type = OFILE_Mach_O; 1132 ofile->object_addr = addr; 1133 ofile->object_size = size; 1134 if(magic == MH_MAGIC_64) 1135 ofile->object_byte_sex = host_byte_sex; 1136 else 1137 ofile->object_byte_sex = 1138 host_byte_sex == BIG_ENDIAN_BYTE_SEX ? 1139 LITTLE_ENDIAN_BYTE_SEX : BIG_ENDIAN_BYTE_SEX; 1140 ofile->mh64 = (struct mach_header_64 *)addr; 1141 ofile->load_commands = (struct load_command *)(addr + 1142 sizeof(struct mach_header_64)); 1143 if(check_Mach_O(ofile) == CHECK_BAD){ 1144 ofile_unmap(ofile); 1145#ifdef OFI 1146 return(NSObjectFileImageFormat); 1147#else 1148 return(FALSE); 1149#endif 1150 } 1151 if(object_name != NULL){ 1152 error("fat file: %s architecture %s is not an archive " 1153 "(object_name to ofile_map() can't be specified to " 1154 "be other than NULL)", ofile->file_name, 1155 arch_flag->name); 1156 goto cleanup; 1157 } 1158 } 1159 /* see if this file is an archive file */ 1160 else if(size >= SARMAG && strncmp(addr, ARMAG, SARMAG) == 0){ 1161 ofile->arch_type = OFILE_ARCHIVE; 1162 if(check_archive(ofile, FALSE) == CHECK_BAD){ 1163 ofile_unmap(ofile); 1164#ifdef OFI 1165 return(NSObjectFileImageInappropriateFile); 1166#else 1167 return(FALSE); 1168#endif 1169 } 1170#ifdef ALIGNMENT_CHECKS 1171 if(ofile->archive_cputype != 0 && 1172 ofile->fat_archs[i].offset % sizeof(uint32_t) != 0){ 1173 error("fat file: %s architecture %s malformed archive that " 1174 "contains object files (offset to archive is not a " 1175 "multiple of sizeof(uint32_t))", 1176 ofile->file_name, arch_flag->name); 1177 ofile_unmap(ofile); 1178#ifdef OFI 1179 return(NSObjectFileImageInappropriateFile); 1180#else 1181 return(FALSE); 1182#endif 1183 } 1184#endif /* ALIGNMENT_CHECKS */ 1185 if(object_name != NULL){ 1186 if(ofile_specific_member(object_name, ofile) == FALSE) 1187 goto cleanup; 1188 } 1189 } 1190 /* this file type is now known to be unknown to this program */ 1191 else{ 1192 ofile->file_type = OFILE_UNKNOWN; 1193 if(object_name != NULL){ 1194 error("fat file: %s architecture %s is not an archive " 1195 "(object_name to ofile_map() can't be specified to " 1196 "be other than NULL)", ofile->file_name, 1197 arch_flag->name); 1198 goto cleanup; 1199 } 1200 } 1201 } 1202 /* see if this file is a 32-bit Mach-O file */ 1203 else if(size >= sizeof(struct mach_header) && 1204 (magic == MH_MAGIC || 1205 magic == SWAP_INT(MH_MAGIC))){ 1206 ofile->file_type = OFILE_Mach_O; 1207 ofile->object_addr = addr; 1208 ofile->object_size = size; 1209 if(magic == MH_MAGIC) 1210 ofile->object_byte_sex = host_byte_sex; 1211 else 1212 ofile->object_byte_sex = host_byte_sex == BIG_ENDIAN_BYTE_SEX ? 1213 LITTLE_ENDIAN_BYTE_SEX : BIG_ENDIAN_BYTE_SEX; 1214 ofile->mh = (struct mach_header *)addr; 1215 ofile->load_commands = (struct load_command *)(addr + 1216 sizeof(struct mach_header)); 1217 if(check_Mach_O(ofile) == CHECK_BAD){ 1218 ofile_unmap(ofile); 1219#ifdef OFI 1220 return(NSObjectFileImageFormat); 1221#else 1222 return(FALSE); 1223#endif 1224 } 1225 if(object_name != NULL){ 1226 error("file: %s is not an archive (object_name to ofile_map() " 1227 "can't be specified to be other than NULL)", 1228 ofile->file_name); 1229 goto cleanup; 1230 } 1231 if(arch_flag != NULL){ 1232 if(arch_flag->cputype != ofile->mh_cputype && 1233 (arch_flag->cpusubtype & ~CPU_SUBTYPE_MASK) != 1234 (ofile->mh_cpusubtype & ~CPU_SUBTYPE_MASK)){ 1235#ifdef OFI 1236 ofile_unmap(ofile); 1237 return(NSObjectFileImageArch); 1238#else 1239 error("object file: %s does not match specified arch_flag: " 1240 "%s passed to ofile_map()", ofile->file_name, 1241 arch_flag->name); 1242 ofile_unmap(ofile); 1243 return(FALSE); 1244#endif 1245 goto cleanup; 1246 } 1247 } 1248 } 1249 /* see if this file is a 64-bit Mach-O file */ 1250 else if(size >= sizeof(struct mach_header_64) && 1251 (magic == MH_MAGIC_64 || 1252 magic == SWAP_INT(MH_MAGIC_64))){ 1253 ofile->file_type = OFILE_Mach_O; 1254 ofile->object_addr = addr; 1255 ofile->object_size = size; 1256 if(magic == MH_MAGIC_64) 1257 ofile->object_byte_sex = host_byte_sex; 1258 else 1259 ofile->object_byte_sex = host_byte_sex == BIG_ENDIAN_BYTE_SEX ? 1260 LITTLE_ENDIAN_BYTE_SEX : BIG_ENDIAN_BYTE_SEX; 1261 ofile->mh64 = (struct mach_header_64 *)addr; 1262 ofile->load_commands = (struct load_command *)(addr + 1263 sizeof(struct mach_header_64)); 1264 if(check_Mach_O(ofile) == CHECK_BAD){ 1265 ofile_unmap(ofile); 1266#ifdef OFI 1267 return(NSObjectFileImageFormat); 1268#else 1269 return(FALSE); 1270#endif 1271 } 1272 if(object_name != NULL){ 1273 error("file: %s is not an archive (object_name to ofile_map() " 1274 "can't be specified to be other than NULL)", 1275 ofile->file_name); 1276 goto cleanup; 1277 } 1278 if(arch_flag != NULL){ 1279 if(arch_flag->cputype != ofile->mh_cputype && 1280 (arch_flag->cpusubtype & ~CPU_SUBTYPE_MASK) != 1281 (ofile->mh_cpusubtype & ~CPU_SUBTYPE_MASK)){ 1282#ifdef OFI 1283 ofile_unmap(ofile); 1284 return(NSObjectFileImageArch); 1285#else 1286 error("object file: %s does not match specified arch_flag: " 1287 "%s passed to ofile_map()", ofile->file_name, 1288 arch_flag->name); 1289 ofile_unmap(ofile); 1290 return(FALSE); 1291#endif 1292 goto cleanup; 1293 } 1294 } 1295 } 1296 /* see if this file is an archive file */ 1297 else if(size >= SARMAG && strncmp(addr, ARMAG, SARMAG) == 0){ 1298 ofile->file_type = OFILE_ARCHIVE; 1299 if(check_archive(ofile, archives_with_fat_objects) == CHECK_BAD) 1300 goto cleanup; 1301 if(object_name != NULL){ 1302 if(ofile_specific_member(object_name, ofile) == FALSE) 1303 goto cleanup; 1304 if(arch_flag != NULL){ 1305 if(arch_flag->cputype != ofile->mh_cputype && 1306 (arch_flag->cpusubtype & ~CPU_SUBTYPE_MASK) != 1307 (ofile->mh_cpusubtype & ~CPU_SUBTYPE_MASK)){ 1308 error("object file: %s(%.*s) does not match specified " 1309 "arch_flag: %s passed to ofile_map()", 1310 ofile->file_name, (int)ofile->member_name_size, 1311 ofile->member_name, arch_flag->name); 1312 goto cleanup; 1313 } 1314 } 1315 } 1316 else{ 1317 if(arch_flag != NULL){ 1318 if(arch_flag->cputype != ofile->archive_cputype && 1319 (arch_flag->cpusubtype & ~CPU_SUBTYPE_MASK) != 1320 (ofile->archive_cpusubtype & ~CPU_SUBTYPE_MASK)){ 1321 error("archive file: %s objects do not match specified " 1322 "arch_flag: %s passed to ofile_map()", 1323 ofile->file_name, arch_flag->name); 1324 goto cleanup; 1325 } 1326 } 1327 } 1328 } 1329 /* this file type is now known to be unknown to this program */ 1330 else{ 1331#ifndef OTOOL 1332unknown: 1333#endif 1334#ifndef OFI 1335#ifdef LTO_SUPPORT 1336 if(is_llvm_bitcode(ofile, ofile->file_addr, ofile->file_size) == 1337 TRUE){ 1338 ofile->file_type = OFILE_LLVM_BITCODE; 1339 if(arch_flag != NULL){ 1340 if(arch_flag->cputype != ofile->lto_cputype && 1341 (arch_flag->cpusubtype & ~CPU_SUBTYPE_MASK) != 1342 (ofile->lto_cpusubtype & ~CPU_SUBTYPE_MASK)){ 1343 error("llvm bitcode file: %s does not match specified " 1344 "arch_flag: %s passed to ofile_map()", 1345 ofile->file_name, arch_flag->name); 1346 goto cleanup; 1347 } 1348 } 1349 if(object_name != NULL){ 1350 error("file: %s is not an archive (object_name to " 1351 "ofile_map() can't be specified to be other than " 1352 "NULL)", ofile->file_name); 1353 goto cleanup; 1354 } 1355 goto success; 1356 } 1357 else 1358#endif /* LTO_SUPPORT */ 1359#endif /* OFI */ 1360 ofile->file_type = OFILE_UNKNOWN; 1361 if(arch_flag != NULL){ 1362#ifdef OFI 1363 ofile_unmap(ofile); 1364 return(NSObjectFileImageInappropriateFile); 1365#else 1366 error("file: %s is unknown type (arch_flag to ofile_map() " 1367 "can't be specified to be other than NULL)", 1368 ofile->file_name); 1369 ofile_unmap(ofile); 1370 return(FALSE); 1371#endif 1372 } 1373 if(object_name != NULL){ 1374 error("file: %s is not an archive (object_name to ofile_map() " 1375 "can't be specified to be other than NULL)", 1376 ofile->file_name); 1377 goto cleanup; 1378 } 1379 } 1380success: 1381 return(TRUE); 1382 1383cleanup: 1384 ofile_unmap(ofile); 1385 return(FALSE); 1386} 1387 1388/* 1389 * ofile_unmap() deallocates the memory associated with the specified ofile 1390 * struct. 1391 */ 1392__private_extern__ 1393void 1394ofile_unmap( 1395struct ofile *ofile) 1396{ 1397 kern_return_t r; 1398 1399 if(ofile->file_addr != NULL){ 1400 if((r = vm_deallocate(mach_task_self(), 1401 (vm_address_t)ofile->file_addr, 1402 (vm_size_t)ofile->file_size)) != KERN_SUCCESS){ 1403 my_mach_error(r, "Can't vm_deallocate mapped memory for file: " 1404 "%s", ofile->file_name); 1405 } 1406 } 1407 if(ofile->file_name != NULL) 1408 free(ofile->file_name); 1409 if(ofile->arch_flag.name != NULL) 1410 free(ofile->arch_flag.name); 1411 memset(ofile, '\0', sizeof(struct ofile)); 1412} 1413 1414/* 1415 * ofile_first_arch() sets up the ofile struct for a fat file to the first arch 1416 * in it. 1417 */ 1418__private_extern__ 1419enum bool 1420ofile_first_arch( 1421struct ofile *ofile) 1422{ 1423 if(ofile->file_type == OFILE_FAT || 1424 (ofile->file_type == OFILE_ARCHIVE && 1425 ofile->member_type == OFILE_FAT) ) 1426 return(ofile_specific_arch(ofile, 0)); 1427 else{ 1428 error("ofile_first_arch() called and file type of: %s is not a fat " 1429 "file\n", ofile->file_name); 1430 return(FALSE); 1431 } 1432} 1433 1434/* 1435 * ofile_next_arch() sets up the ofile struct for a fat file to the next arch 1436 * in it. 1437 */ 1438__private_extern__ 1439enum bool 1440ofile_next_arch( 1441struct ofile *ofile) 1442{ 1443 if(ofile->file_type == OFILE_FAT || 1444 (ofile->file_type == OFILE_ARCHIVE && 1445 ofile->member_type == OFILE_FAT) ){ 1446 if(ofile->narch + 1 < ofile->fat_header->nfat_arch) 1447 return(ofile_specific_arch(ofile, ofile->narch + 1)); 1448 else 1449 return(FALSE); 1450 } 1451 else{ 1452 error("ofile_next_arch() called and file type of: %s is not a fat " 1453 "file\n", ofile->file_name); 1454 return(FALSE); 1455 } 1456} 1457 1458/* 1459 * ofile_specific_arch() sets up the ofile struct for the fat file for the 1460 * specified narch. 1461 */ 1462static 1463enum bool 1464ofile_specific_arch( 1465struct ofile *ofile, 1466uint32_t narch) 1467{ 1468 char *addr; 1469 uint32_t size; 1470 uint32_t magic; 1471 enum byte_sex host_byte_sex; 1472 1473 ofile->narch = narch; 1474 ofile->arch_type = OFILE_UNKNOWN; 1475 if(ofile->arch_flag.name != NULL) 1476 free(ofile->arch_flag.name); 1477 ofile->arch_flag.name = NULL; 1478 ofile->arch_flag.cputype = 0; 1479 ofile->arch_flag.cpusubtype = 0; 1480 ofile->archive_cputype = 0; 1481 ofile->archive_cpusubtype = 0; 1482 ofile->object_addr = NULL; 1483 ofile->object_size = 0; 1484 ofile->object_byte_sex = UNKNOWN_BYTE_SEX; 1485 ofile->mh = NULL; 1486 ofile->mh64 = NULL; 1487 ofile->load_commands = NULL; 1488 1489 ofile->arch_flag.cputype = ofile->fat_archs[ofile->narch].cputype; 1490 ofile->arch_flag.cpusubtype = ofile->fat_archs[ofile->narch].cpusubtype; 1491 set_arch_flag_name(&(ofile->arch_flag)); 1492 1493 1494 /* Now determine the file type for this specific architecture */ 1495 if(ofile->file_type == OFILE_FAT){ 1496 ofile->member_offset = 0; 1497 ofile->member_addr = NULL; 1498 ofile->member_size = 0; 1499 ofile->member_ar_hdr = NULL; 1500 ofile->member_type = OFILE_UNKNOWN; 1501 1502 size = ofile->fat_archs[ofile->narch].size; 1503 addr = ofile->file_addr + ofile->fat_archs[ofile->narch].offset; 1504 } 1505 else{ 1506 if(ofile->file_type != OFILE_ARCHIVE || 1507 ofile->member_type != OFILE_FAT){ 1508 error("internal error. ofile_specific_arch() called but file " 1509 "is not a fat file or an archive with a fat member "); 1510 } 1511 size = ofile->fat_archs[ofile->narch].size; 1512 addr = ofile->file_addr + 1513 ofile->member_offset + 1514 ofile->fat_archs[ofile->narch].offset; 1515 } 1516 1517#ifdef OTOOL 1518 if(addr - ofile->file_addr > (ptrdiff_t)ofile->file_size){ 1519 error("fat file: %s offset to architecture %s extends past end " 1520 "of file", ofile->file_name, ofile->arch_flag.name); 1521 return(FALSE); 1522 } 1523 if(addr + size > ofile->file_addr + ofile->file_size) 1524 size = (ofile->file_addr + ofile->file_size) - addr; 1525#endif /* OTOOL */ 1526 1527 if(size >= sizeof(struct mach_header)) 1528 memcpy(&magic, addr, sizeof(uint32_t)); 1529 /* see if this file is a 32-bit Mach-O file */ 1530 if(size >= sizeof(struct mach_header) && 1531 (magic == MH_MAGIC || magic == SWAP_INT(MH_MAGIC))){ 1532#ifdef ALIGNMENT_CHECKS 1533 if(ofile->fat_archs[ofile->narch].offset % 4 != 0){ 1534 if(ofile->file_type == OFILE_ARCHIVE){ 1535 error("fat file: %s(%.*s) architecture %s malformed for a " 1536 "32-bit object file (offset is not a multiple of 4)", 1537 ofile->file_name, (int)ofile->member_name_size, 1538 ofile->member_name, ofile->arch_flag.name); 1539 } 1540 else 1541 error("fat file: %s architecture %s malformed for a 32-bit " 1542 "object file (offset is not a multiple of 4)", 1543 ofile->file_name, ofile->arch_flag.name); 1544 goto cleanup; 1545 } 1546#endif /* ALIGNMENT_CHECKS */ 1547 ofile->arch_type = OFILE_Mach_O; 1548 ofile->object_addr = addr; 1549 ofile->object_size = size; 1550 host_byte_sex = get_host_byte_sex(); 1551 if(magic == MH_MAGIC) 1552 ofile->object_byte_sex = host_byte_sex; 1553 else 1554 ofile->object_byte_sex = 1555 host_byte_sex == BIG_ENDIAN_BYTE_SEX ? 1556 LITTLE_ENDIAN_BYTE_SEX : BIG_ENDIAN_BYTE_SEX; 1557 ofile->mh = (struct mach_header *)addr; 1558 ofile->load_commands = (struct load_command *)(addr + 1559 sizeof(struct mach_header)); 1560 if(check_Mach_O(ofile) == CHECK_BAD) 1561 goto cleanup; 1562 } 1563 /* see if this file is a 64-bit Mach-O file */ 1564 else if(size >= sizeof(struct mach_header_64) && 1565 (magic == MH_MAGIC_64 || magic == SWAP_INT(MH_MAGIC_64))){ 1566#ifdef ALIGNMENT_CHECKS 1567 if(ofile->fat_archs[ofile->narch].offset % 8 != 0){ 1568 if(ofile->file_type == OFILE_ARCHIVE){ 1569 error("fat file: %s(%.*s) architecture %s malformed for an " 1570 "object file (offset is not a multiple of 8)", 1571 ofile->file_name, (int)ofile->member_name_size, 1572 ofile->member_name, ofile->arch_flag.name); 1573 } 1574 else 1575 error("fat file: %s architecture %s malformed for a 64-bit " 1576 "object file (offset is not a multiple of 8", 1577 ofile->file_name, ofile->arch_flag.name); 1578 goto cleanup; 1579 } 1580#endif /* ALIGNMENT_CHECKS */ 1581 ofile->arch_type = OFILE_Mach_O; 1582 ofile->object_addr = addr; 1583 ofile->object_size = size; 1584 host_byte_sex = get_host_byte_sex(); 1585 if(magic == MH_MAGIC_64) 1586 ofile->object_byte_sex = host_byte_sex; 1587 else 1588 ofile->object_byte_sex = 1589 host_byte_sex == BIG_ENDIAN_BYTE_SEX ? 1590 LITTLE_ENDIAN_BYTE_SEX : BIG_ENDIAN_BYTE_SEX; 1591 ofile->mh64 = (struct mach_header_64 *)addr; 1592 ofile->load_commands = (struct load_command *)(addr + 1593 sizeof(struct mach_header_64)); 1594 if(check_Mach_O(ofile) == CHECK_BAD) 1595 goto cleanup; 1596 } 1597 /* see if this file is an archive file */ 1598 else if(size >= SARMAG && strncmp(addr, ARMAG, SARMAG) == 0){ 1599 ofile->arch_type = OFILE_ARCHIVE; 1600 if(check_archive(ofile, FALSE) == CHECK_BAD) 1601 goto cleanup; 1602#ifdef ALIGNMENT_CHECKS 1603 if(ofile->archive_cputype != 0 && 1604 ofile->fat_archs[ofile->narch].offset % 1605 sizeof(uint32_t) != 0){ 1606 error("fat file: %s architecture %s malformed archive that " 1607 "contains object files (offset to archive is not a " 1608 "multiple of sizeof(uint32_t))", 1609 ofile->file_name, ofile->arch_flag.name); 1610 goto cleanup; 1611 } 1612#endif /* ALIGNMENT_CHECKS */ 1613 } 1614 /* 1615 * This type for this architecture is now known to be unknown to this 1616 * program. 1617 */ 1618 else{ 1619#ifdef LTO_SUPPORT 1620 if(is_llvm_bitcode(ofile, addr, size) == TRUE){ 1621 ofile->arch_type = OFILE_LLVM_BITCODE; 1622 ofile->object_addr = addr; 1623 ofile->object_size = size; 1624 } 1625 else 1626#endif /* LTO_SUPPORT */ 1627 ofile->arch_type = OFILE_UNKNOWN; 1628 } 1629 return(TRUE); 1630cleanup: 1631 ofile->narch = 0;; 1632 ofile->arch_type = OFILE_UNKNOWN; 1633 if(ofile->arch_flag.name != NULL) 1634 free(ofile->arch_flag.name); 1635 ofile->arch_flag.name = NULL; 1636 ofile->arch_flag.cputype = 0; 1637 ofile->arch_flag.cpusubtype = 0; 1638 if(ofile->file_type != OFILE_ARCHIVE){ 1639 ofile->member_offset = 0; 1640 ofile->member_addr = NULL; 1641 ofile->member_size = 0; 1642 ofile->member_ar_hdr = NULL; 1643 ofile->member_type = OFILE_UNKNOWN; 1644 } 1645 ofile->archive_cputype = 0; 1646 ofile->archive_cpusubtype = 0; 1647 ofile->object_addr = NULL; 1648 ofile->object_size = 0; 1649 ofile->object_byte_sex = UNKNOWN_BYTE_SEX; 1650 ofile->mh = NULL; 1651 ofile->mh64 = NULL; 1652 ofile->load_commands = NULL; 1653 return(FALSE); 1654} 1655 1656/* 1657 * ofile_first_member() set up the ofile structure (the member_* fields and 1658 * the object file fields if the first member is an object file) for the first 1659 * member. 1660 */ 1661__private_extern__ 1662enum bool 1663ofile_first_member( 1664struct ofile *ofile) 1665{ 1666 char *addr; 1667 uint64_t size, offset; 1668 uint32_t magic; 1669 enum byte_sex host_byte_sex; 1670 struct ar_hdr *ar_hdr; 1671 uint32_t ar_name_size; 1672 1673 /* These fields are to be filled in by this routine, clear them first */ 1674 ofile->member_offset = 0; 1675 ofile->member_addr = NULL; 1676 ofile->member_size = 0; 1677 ofile->member_ar_hdr = NULL; 1678 ofile->member_name = NULL; 1679 ofile->member_name_size = 0; 1680 ofile->member_type = OFILE_UNKNOWN; 1681 ofile->object_addr = NULL; 1682 ofile->object_size = 0; 1683 ofile->object_byte_sex = UNKNOWN_BYTE_SEX; 1684 ofile->mh = NULL; 1685 ofile->mh64 = NULL; 1686 ofile->load_commands = NULL; 1687#ifdef LTO_SUPPORT 1688 /* 1689 * Note: it is up to the caller if they want to call free_lto() on this 1690 * when iterating through the members of an archive. 1691 */ 1692 ofile->lto = NULL; 1693#endif /* LTO_SUPPORT */ 1694 1695 /* 1696 * Get the address and size of the archive. 1697 */ 1698 if(ofile->file_type == OFILE_FAT){ 1699 if(ofile->arch_type != OFILE_ARCHIVE){ 1700 error("ofile_first_member() called on fat file: %s with a " 1701 "non-archive architecture or no architecture selected\n", 1702 ofile->file_name); 1703 return(FALSE); 1704 } 1705 addr = ofile->file_addr + ofile->fat_archs[ofile->narch].offset; 1706 size = ofile->fat_archs[ofile->narch].size; 1707 } 1708 else if(ofile->file_type == OFILE_ARCHIVE){ 1709 addr = ofile->file_addr; 1710 size = ofile->file_size; 1711 } 1712 else{ 1713 error("ofile_first_member() called and file type of %s is " 1714 "OFILE_UNKNOWN\n", ofile->file_name); 1715 return(FALSE); 1716 } 1717#ifdef OTOOL 1718 if((addr + SARMAG) - ofile->file_addr > (ptrdiff_t)ofile->file_size){ 1719 archive_error(ofile, "offset to first member extends past the end " 1720 "of the file"); 1721 return(FALSE); 1722 } 1723 if(addr + size > ofile->file_addr + ofile->file_size) 1724 size = (ofile->file_addr + ofile->file_size) - addr; 1725#endif /* OTOOL */ 1726 if(size < SARMAG || strncmp(addr, ARMAG, SARMAG) != 0){ 1727 archive_error(ofile, "internal error. ofile_first_member() " 1728 "called but file does not have an archive magic " 1729 "string"); 1730 return(FALSE); 1731 } 1732 1733 offset = SARMAG; 1734 if(offset != size && offset + sizeof(struct ar_hdr) > size){ 1735 archive_error(ofile, "truncated or malformed (archive header of " 1736 "first member extends past the end of the file)"); 1737 return(FALSE); 1738 } 1739 1740 /* check for empty archive */ 1741 if(size == offset) 1742 return(FALSE); 1743 1744 /* now we know there is a first member so set it up */ 1745 ar_hdr = (struct ar_hdr *)(addr + offset); 1746 offset += sizeof(struct ar_hdr); 1747 ofile->member_offset = offset; 1748 ofile->member_addr = addr + offset; 1749 ofile->member_size = strtoul(ar_hdr->ar_size, NULL, 10); 1750 ofile->member_ar_hdr = ar_hdr; 1751 ofile->member_type = OFILE_UNKNOWN; 1752 ofile->member_name = ar_hdr->ar_name; 1753 if(strncmp(ofile->member_name, AR_EFMT1, sizeof(AR_EFMT1) - 1) == 0){ 1754 ofile->member_name = ar_hdr->ar_name + sizeof(struct ar_hdr); 1755 ar_name_size = strtoul(ar_hdr->ar_name + sizeof(AR_EFMT1) - 1, 1756 NULL, 10); 1757 ofile->member_name_size = ar_name_size; 1758 ofile->member_offset += ar_name_size; 1759 ofile->member_addr += ar_name_size; 1760 ofile->member_size -= ar_name_size; 1761 } 1762 else{ 1763 ofile->member_name_size = size_ar_name(ar_hdr); 1764 ar_name_size = 0; 1765 } 1766 /* Clear these in case there is no table of contents */ 1767 ofile->toc_addr = NULL; 1768 ofile->toc_size = 0; 1769 ofile->toc_ar_hdr = NULL; 1770 ofile->toc_name = NULL; 1771 ofile->toc_name_size = 0; 1772 ofile->toc_ranlibs = NULL; 1773 ofile->toc_nranlibs = 0; 1774 ofile->toc_strings = NULL; 1775 ofile->toc_strsize = 0; 1776 ofile->toc_bad = FALSE; 1777 1778 host_byte_sex = get_host_byte_sex(); 1779 1780 if(ofile->member_size > sizeof(uint32_t)){ 1781 memcpy(&magic, ofile->member_addr, sizeof(uint32_t)); 1782#ifdef __BIG_ENDIAN__ 1783 if(magic == FAT_MAGIC) 1784#endif /* __BIG_ENDIAN__ */ 1785#ifdef __LITTLE_ENDIAN__ 1786 if(magic == SWAP_INT(FAT_MAGIC)) 1787#endif /* __LITTLE_ENDIAN__ */ 1788 { 1789 ofile->member_type = OFILE_FAT; 1790 ofile->fat_header = 1791 (struct fat_header *)(ofile->member_addr); 1792#ifdef __LITTLE_ENDIAN__ 1793 swap_fat_header(ofile->fat_header, host_byte_sex); 1794#endif /* __LITTLE_ENDIAN__ */ 1795 if(sizeof(struct fat_header) + 1796 ofile->fat_header->nfat_arch * 1797 sizeof(struct fat_arch) > ofile->member_size){ 1798 archive_member_error(ofile, "fat file truncated or " 1799 "malformed (fat_arch structs would extend past " 1800 "the end of the archive member)"); 1801 goto fatcleanup; 1802 } 1803 ofile->fat_archs = (struct fat_arch *) 1804 (ofile->member_addr + sizeof(struct fat_header)); 1805#ifdef __LITTLE_ENDIAN__ 1806 swap_fat_arch(ofile->fat_archs, 1807 ofile->fat_header->nfat_arch, host_byte_sex); 1808#endif /* __LITTLE_ENDIAN__ */ 1809 if(check_fat_object_in_archive(ofile) == FALSE) 1810 goto fatcleanup; 1811 } 1812 else if(size - (offset + ar_name_size) >= 1813 sizeof(struct mach_header) && 1814 (magic == MH_MAGIC || magic == SWAP_INT(MH_MAGIC))){ 1815#ifdef ALIGNMENT_CHECKS 1816 if((offset + ar_name_size) % 4 != 0){ 1817 archive_member_error(ofile, "offset in archive not a " 1818 "multiple of 4 (must be since member is a 32-bit " 1819 "object file)"); 1820 goto cleanup; 1821 } 1822#endif /* ALIGNMENT_CHECKS */ 1823 ofile->member_type = OFILE_Mach_O; 1824 ofile->object_addr = ofile->member_addr; 1825 ofile->object_size = ofile->member_size; 1826 if(magic == MH_MAGIC) 1827 ofile->object_byte_sex = host_byte_sex; 1828 else 1829 ofile->object_byte_sex = 1830 host_byte_sex == BIG_ENDIAN_BYTE_SEX ? 1831 LITTLE_ENDIAN_BYTE_SEX : BIG_ENDIAN_BYTE_SEX; 1832 ofile->mh = (struct mach_header *)(ofile->object_addr); 1833 ofile->load_commands = (struct load_command *) 1834 (ofile->object_addr + sizeof(struct mach_header)); 1835 if(check_Mach_O(ofile) == CHECK_BAD) 1836 goto cleanup; 1837 } 1838 else if(size - (offset + ar_name_size) >= 1839 sizeof(struct mach_header_64) && 1840 (magic == MH_MAGIC_64 || magic == SWAP_INT(MH_MAGIC_64))){ 1841#ifdef ALIGNMENT_CHECKS_ARCHIVE_64_BIT 1842 if(archive_64_bit_align_warning == FALSE && 1843 (offset + ar_name_size) % 8 != 0){ 1844 temporary_archive_member_warning(ofile, "offset in archive " 1845 "not a multiple of 8 (must be since member is an " 1846 "64-bit object file)"); 1847 archive_64_bit_align_warning = TRUE; 1848 /* goto cleanup; */ 1849 } 1850#endif /* ALIGNMENT_CHECKS_ARCHIVE_64_BIT */ 1851 ofile->member_type = OFILE_Mach_O; 1852 ofile->object_addr = ofile->member_addr; 1853 ofile->object_size = ofile->member_size; 1854 if(magic == MH_MAGIC_64) 1855 ofile->object_byte_sex = host_byte_sex; 1856 else 1857 ofile->object_byte_sex = 1858 host_byte_sex == BIG_ENDIAN_BYTE_SEX ? 1859 LITTLE_ENDIAN_BYTE_SEX : BIG_ENDIAN_BYTE_SEX; 1860 ofile->mh64 = (struct mach_header_64 *)(ofile->object_addr); 1861 ofile->load_commands = (struct load_command *) 1862 (ofile->object_addr + sizeof(struct mach_header_64)); 1863 if(check_Mach_O(ofile) == CHECK_BAD) 1864 goto cleanup; 1865 } 1866 if(ofile->member_type == OFILE_UNKNOWN && 1867 (strncmp(ofile->member_name, SYMDEF_SORTED, 1868 sizeof(SYMDEF_SORTED) - 1) == 0 || 1869 strncmp(ofile->member_name, SYMDEF, 1870 sizeof(SYMDEF) - 1) == 0)){ 1871 ofile->toc_addr = ofile->member_addr; 1872 ofile->toc_size = ofile->member_size; 1873 ofile->toc_ar_hdr = ofile->member_ar_hdr; 1874 ofile->toc_name = ofile->member_name; 1875 ofile->toc_name_size = ofile->member_name_size; 1876 if(check_archive_toc(ofile) == CHECK_BAD) 1877 goto cleanup; 1878 } 1879#ifdef LTO_SUPPORT 1880 if(ofile->member_type == OFILE_UNKNOWN && 1881 strncmp(ofile->member_name, SYMDEF_SORTED, 1882 sizeof(SYMDEF_SORTED) - 1) != 0 && 1883 strncmp(ofile->member_name, SYMDEF, 1884 sizeof(SYMDEF) - 1) != 0 && 1885 is_llvm_bitcode(ofile, ofile->member_addr, ofile->member_size) == 1886 TRUE){ 1887 ofile->member_type = OFILE_LLVM_BITCODE; 1888 ofile->object_addr = ofile->member_addr; 1889 ofile->object_size = ofile->member_size; 1890 } 1891#endif /* LTO_SUPPORT */ 1892 } 1893 return(TRUE); 1894 1895fatcleanup: 1896 ofile->fat_header = NULL; 1897 ofile->fat_archs = NULL; 1898cleanup: 1899 ofile->member_offset = 0; 1900 ofile->member_addr = 0; 1901 ofile->member_size = 0; 1902 ofile->member_ar_hdr = NULL; 1903 ofile->member_name = NULL; 1904 ofile->member_name_size = 0; 1905 ofile->member_type = OFILE_UNKNOWN; 1906 ofile->object_addr = NULL; 1907 ofile->object_size = 0; 1908 ofile->object_byte_sex = UNKNOWN_BYTE_SEX; 1909 ofile->mh = NULL; 1910 ofile->mh64 = NULL; 1911 ofile->load_commands = NULL; 1912#ifdef LTO_SUPPORT 1913 ofile->lto = NULL; 1914 ofile->lto_cputype = 0; 1915 ofile->lto_cpusubtype = 0; 1916#endif /* LTO_SUPPORT */ 1917 return(FALSE); 1918} 1919 1920/* 1921 * ofile_next_member() set up the ofile structure (the member_* fields and 1922 * the object file fields if the next member is an object file) for the next 1923 * member. 1924 */ 1925__private_extern__ 1926enum bool 1927ofile_next_member( 1928struct ofile *ofile) 1929{ 1930 char *addr; 1931 uint64_t size, offset; 1932 uint32_t magic; 1933 enum byte_sex host_byte_sex; 1934 struct ar_hdr *ar_hdr; 1935 uint32_t ar_name_size; 1936 1937 /* 1938 * Get the address and size of the archive. 1939 */ 1940 if(ofile->file_type == OFILE_FAT){ 1941 if(ofile->arch_type != OFILE_ARCHIVE){ 1942 error("ofile_next_member() called on fat file: %s with a " 1943 "non-archive architecture or no architecture selected\n", 1944 ofile->file_name); 1945 return(FALSE); 1946 } 1947 addr = ofile->file_addr + ofile->fat_archs[ofile->narch].offset; 1948 size = ofile->fat_archs[ofile->narch].size; 1949 } 1950 else if(ofile->file_type == OFILE_ARCHIVE){ 1951 addr = ofile->file_addr; 1952 size = ofile->file_size; 1953 } 1954 else{ 1955 error("ofile_next_member() called and file type of %s is " 1956 "OFILE_UNKNOWN\n", ofile->file_name); 1957 return(FALSE); 1958 } 1959 if(size < SARMAG || strncmp(addr, ARMAG, SARMAG) != 0){ 1960 archive_error(ofile, "internal error. ofile_next_member() " 1961 "called but file does not have an archive magic " 1962 "string"); 1963 return(FALSE); 1964 } 1965 if(ofile->member_ar_hdr == NULL){ 1966 archive_error(ofile, "internal error. ofile_next_member() called " 1967 "but the ofile struct does not have an archive " 1968 "member selected"); 1969 return(FALSE); 1970 } 1971 1972 /* figure out the offset to the next member */ 1973 offset = ofile->member_offset + rnd(ofile->member_size,sizeof(short)); 1974#ifdef OTOOL 1975 if((addr - ofile->file_addr) + offset > ofile->file_size){ 1976 archive_error(ofile, "offset to next member extends past the end " 1977 "of the file"); 1978 return(FALSE); 1979 } 1980#endif /* OTOOL */ 1981 /* if now at the end of the file then no more members */ 1982 if(offset == size) 1983 goto cleanup; 1984 if(offset > size){ 1985 archive_error(ofile, "truncated or malformed (archive header of " 1986 "next member extends past the end of the file)"); 1987 return(FALSE); 1988 } 1989 1990 /* now we know there is a next member so set it up */ 1991 ar_hdr = (struct ar_hdr *)(addr + offset); 1992 offset += sizeof(struct ar_hdr); 1993 ofile->member_offset = offset; 1994 ofile->member_addr = addr + offset; 1995 ofile->member_size = strtoul(ar_hdr->ar_size, NULL, 10); 1996 ofile->member_ar_hdr = ar_hdr; 1997 ofile->member_name = ar_hdr->ar_name; 1998 if(strncmp(ofile->member_name, AR_EFMT1, sizeof(AR_EFMT1) - 1) == 0){ 1999 ofile->member_name = ar_hdr->ar_name + sizeof(struct ar_hdr); 2000 ar_name_size = strtoul(ar_hdr->ar_name + sizeof(AR_EFMT1) - 1, 2001 NULL, 10); 2002 ofile->member_name_size = ar_name_size; 2003 ofile->member_offset += ar_name_size; 2004 ofile->member_addr += ar_name_size; 2005 ofile->member_size -= ar_name_size; 2006 } 2007 else{ 2008 ofile->member_name_size = size_ar_name(ar_hdr); 2009 ar_name_size = 0; 2010 } 2011 ofile->member_type = OFILE_UNKNOWN; 2012 ofile->object_addr = NULL; 2013 ofile->object_size = 0; 2014 ofile->object_byte_sex = UNKNOWN_BYTE_SEX; 2015 ofile->mh = NULL; 2016 ofile->mh64 = NULL; 2017 ofile->load_commands = NULL; 2018 2019 host_byte_sex = get_host_byte_sex(); 2020 2021 if(ofile->member_size > sizeof(uint32_t)){ 2022 memcpy(&magic, ofile->member_addr, sizeof(uint32_t)); 2023#ifdef __BIG_ENDIAN__ 2024 if(magic == FAT_MAGIC) 2025#endif /* __BIG_ENDIAN__ */ 2026#ifdef __LITTLE_ENDIAN__ 2027 if(magic == SWAP_INT(FAT_MAGIC)) 2028#endif /* __LITTLE_ENDIAN__ */ 2029 { 2030 ofile->member_type = OFILE_FAT; 2031 ofile->fat_header = (struct fat_header *)(ofile->member_addr); 2032#ifdef __LITTLE_ENDIAN__ 2033 swap_fat_header(ofile->fat_header, host_byte_sex); 2034#endif /* __LITTLE_ENDIAN__ */ 2035 if(sizeof(struct fat_header) + 2036 ofile->fat_header->nfat_arch * 2037 sizeof(struct fat_arch) > ofile->member_size){ 2038 archive_member_error(ofile, "fat file truncated or " 2039 "malformed (fat_arch structs would extend past " 2040 "the end of the archive member)"); 2041 goto cleanup; 2042 } 2043 ofile->fat_archs = (struct fat_arch *)(ofile->member_addr + 2044 sizeof(struct fat_header)); 2045#ifdef __LITTLE_ENDIAN__ 2046 swap_fat_arch(ofile->fat_archs, 2047 ofile->fat_header->nfat_arch, host_byte_sex); 2048#endif /* __LITTLE_ENDIAN__ */ 2049 if(check_fat_object_in_archive(ofile) == FALSE) 2050 goto cleanup; 2051 } 2052 else if(size - (offset + ar_name_size) >= 2053 sizeof(struct mach_header) && 2054 (magic == MH_MAGIC || 2055 magic == SWAP_INT(MH_MAGIC))){ 2056#ifdef ALIGNMENT_CHECKS 2057 if((offset + ar_name_size) % 4 != 0){ 2058 archive_member_error(ofile, "offset in archive not " 2059 "a multiple of 4 (must be since member is an 32-bit " 2060 "object file)"); 2061 goto cleanup; 2062 } 2063#endif /* ALIGNMENT_CHECKS */ 2064 ofile->member_type = OFILE_Mach_O; 2065 ofile->object_addr = ofile->member_addr; 2066 ofile->object_size = ofile->member_size; 2067 if(magic == MH_MAGIC) 2068 ofile->object_byte_sex = host_byte_sex; 2069 else 2070 ofile->object_byte_sex = 2071 host_byte_sex == BIG_ENDIAN_BYTE_SEX ? 2072 LITTLE_ENDIAN_BYTE_SEX : BIG_ENDIAN_BYTE_SEX; 2073 ofile->mh = (struct mach_header *)ofile->object_addr; 2074 ofile->load_commands = (struct load_command *) 2075 (ofile->object_addr + sizeof(struct mach_header)); 2076 if(check_Mach_O(ofile) == CHECK_BAD) 2077 goto cleanup; 2078 } 2079 else if(size - (offset + ar_name_size) >= 2080 sizeof(struct mach_header_64) && 2081 (magic == MH_MAGIC_64 || 2082 magic == SWAP_INT(MH_MAGIC_64))){ 2083#ifdef ALIGNMENT_CHECKS_ARCHIVE_64_BIT 2084 if(archive_64_bit_align_warning == FALSE && 2085 (offset + ar_name_size) % 8 != 0){ 2086 temporary_archive_member_warning(ofile, "offset in archive " 2087 "not a multiple of 8 (must be since member is an " 2088 "64-bit object file)"); 2089 archive_64_bit_align_warning = TRUE; 2090 /* goto cleanup; */ 2091 } 2092#endif /* ALIGNMENT_CHECKS_ARCHIVE_64_BIT */ 2093 ofile->member_type = OFILE_Mach_O; 2094 ofile->object_addr = ofile->member_addr; 2095 ofile->object_size = ofile->member_size; 2096 if(magic == MH_MAGIC_64) 2097 ofile->object_byte_sex = host_byte_sex; 2098 else 2099 ofile->object_byte_sex = 2100 host_byte_sex == BIG_ENDIAN_BYTE_SEX ? 2101 LITTLE_ENDIAN_BYTE_SEX : BIG_ENDIAN_BYTE_SEX; 2102 ofile->mh64 = (struct mach_header_64 *)ofile->object_addr; 2103 ofile->load_commands = (struct load_command *) 2104 (ofile->object_addr + sizeof(struct mach_header_64)); 2105 if(check_Mach_O(ofile) == CHECK_BAD) 2106 goto cleanup; 2107 } 2108#ifdef LTO_SUPPORT 2109 if(ofile->member_type == OFILE_UNKNOWN && 2110 is_llvm_bitcode(ofile, ofile->member_addr, ofile->member_size) == 2111 TRUE){ 2112 ofile->member_type = OFILE_LLVM_BITCODE; 2113 ofile->object_addr = ofile->member_addr; 2114 ofile->object_size = ofile->member_size; 2115 } 2116#endif /* LTO_SUPPORT */ 2117 } 2118 return(TRUE); 2119 2120cleanup: 2121 if(ofile->member_type == OFILE_FAT){ 2122 ofile->fat_header = NULL; 2123 ofile->fat_archs = NULL; 2124 } 2125 ofile->member_offset = 0; 2126 ofile->member_addr = NULL; 2127 ofile->member_size = 0; 2128 ofile->member_ar_hdr = NULL; 2129 ofile->member_name = NULL; 2130 ofile->member_name_size = 0; 2131 ofile->member_type = OFILE_UNKNOWN; 2132 ofile->object_addr = NULL; 2133 ofile->object_size = 0; 2134 ofile->object_byte_sex = UNKNOWN_BYTE_SEX; 2135 ofile->mh = NULL; 2136 ofile->mh64 = NULL; 2137 ofile->load_commands = NULL; 2138#ifdef LTO_SUPPORT 2139 ofile->lto = NULL; 2140 ofile->lto_cputype = 0; 2141 ofile->lto_cpusubtype = 0; 2142#endif /* LTO_SUPPORT */ 2143 return(FALSE); 2144} 2145 2146/* 2147 * ofile_specific_member() set up the ofile structure (the member_* fields and 2148 * the object file fields if the member is an object file) for the specified 2149 * member member_name. 2150 */ 2151__private_extern__ 2152enum bool 2153ofile_specific_member( 2154const char *member_name, 2155struct ofile *ofile) 2156{ 2157 int32_t i; 2158 char *addr; 2159 uint64_t size, offset; 2160 uint32_t magic; 2161 enum byte_sex host_byte_sex; 2162 char *ar_name; 2163 uint32_t ar_name_size; 2164 struct ar_hdr *ar_hdr; 2165 2166 /* These fields are to be filled in by this routine, clear them first */ 2167 ofile->member_offset = 0; 2168 ofile->member_addr = NULL; 2169 ofile->member_size = 0; 2170 ofile->member_ar_hdr = NULL; 2171 ofile->member_name = NULL; 2172 ofile->member_name_size = 0; 2173 ofile->member_type = OFILE_UNKNOWN; 2174 ofile->object_addr = NULL; 2175 ofile->object_size = 0; 2176 ofile->object_byte_sex = UNKNOWN_BYTE_SEX; 2177 ofile->mh = NULL; 2178 ofile->mh64 = NULL; 2179 ofile->load_commands = NULL; 2180 2181 /* 2182 * Get the address and size of the archive. 2183 */ 2184 if(ofile->file_type == OFILE_FAT){ 2185 if(ofile->arch_type != OFILE_ARCHIVE){ 2186 error("ofile_specific_member() called on fat file: %s with a " 2187 "non-archive architecture or no architecture selected\n", 2188 ofile->file_name); 2189 return(FALSE); 2190 } 2191 addr = ofile->file_addr + ofile->fat_archs[ofile->narch].offset; 2192 size = ofile->fat_archs[ofile->narch].size; 2193 } 2194 else if(ofile->file_type == OFILE_ARCHIVE){ 2195 addr = ofile->file_addr; 2196 size = ofile->file_size; 2197 } 2198 else{ 2199 error("ofile_specific_member() called and file type of %s is " 2200 "OFILE_UNKNOWN\n", ofile->file_name); 2201 return(FALSE); 2202 } 2203 if(size < SARMAG || strncmp(addr, ARMAG, SARMAG) != 0){ 2204 archive_error(ofile, "internal error. ofile_specific_member() " 2205 "called but file does not have an archive magic " 2206 "string"); 2207 return(FALSE); 2208 } 2209 2210 offset = SARMAG; 2211 if(offset != size && offset + sizeof(struct ar_hdr) > size){ 2212 archive_error(ofile, "truncated or malformed (archive header of " 2213 "first member extends past the end of the file)"); 2214 return(FALSE); 2215 } 2216 while(size > offset){ 2217 ar_hdr = (struct ar_hdr *)(addr + offset); 2218 offset += sizeof(struct ar_hdr); 2219 if(strncmp(ar_hdr->ar_name, AR_EFMT1, sizeof(AR_EFMT1) - 1) == 0){ 2220#ifdef OTOOL 2221 if(check_extend_format_1(ofile, ar_hdr, size - offset, 2222 &ar_name_size) == CHECK_BAD){ 2223 i = size_ar_name(ar_hdr); 2224 ar_name = ar_hdr->ar_name; 2225 ar_name_size = 0; 2226 } 2227 else 2228#endif /* OTOOL */ 2229 { 2230 i = strtoul(ar_hdr->ar_name + sizeof(AR_EFMT1) - 1,NULL,10); 2231 ar_name = ar_hdr->ar_name + sizeof(struct ar_hdr); 2232 ar_name_size = i; 2233 } 2234 } 2235 else{ 2236 i = size_ar_name(ar_hdr); 2237 ar_name = ar_hdr->ar_name; 2238 ar_name_size = 0; 2239 } 2240 if(i > 0 && strncmp(ar_name, member_name, i) == 0){ 2241 2242 ofile->member_name = ar_name; 2243 ofile->member_name_size = i; 2244 ofile->member_offset = offset + ar_name_size; 2245 ofile->member_addr = addr + offset + ar_name_size; 2246 ofile->member_size = strtoul(ar_hdr->ar_size, NULL, 10) - 2247 ar_name_size; 2248 ofile->member_ar_hdr = ar_hdr; 2249 ofile->member_type = OFILE_UNKNOWN; 2250 2251 host_byte_sex = get_host_byte_sex(); 2252 2253 if(ofile->member_size > sizeof(uint32_t)){ 2254 memcpy(&magic, addr + offset + ar_name_size, 2255 sizeof(uint32_t)); 2256#ifdef __BIG_ENDIAN__ 2257 if(magic == FAT_MAGIC) 2258#endif /* __BIG_ENDIAN__ */ 2259#ifdef __LITTLE_ENDIAN__ 2260 if(magic == SWAP_INT(FAT_MAGIC)) 2261#endif /* __LITTLE_ENDIAN__ */ 2262 { 2263 ofile->member_type = OFILE_FAT; 2264 ofile->fat_header = 2265 (struct fat_header *)(addr + offset + ar_name_size); 2266#ifdef __LITTLE_ENDIAN__ 2267 swap_fat_header(ofile->fat_header, host_byte_sex); 2268#endif /* __LITTLE_ENDIAN__ */ 2269 if(sizeof(struct fat_header) + 2270 ofile->fat_header->nfat_arch * 2271 sizeof(struct fat_arch) > ofile->member_size){ 2272 archive_member_error(ofile, "fat file truncated or " 2273 "malformed (fat_arch structs would extend " 2274 "past the end of the archive member)"); 2275 goto fatcleanup; 2276 } 2277 ofile->fat_archs = 2278 (struct fat_arch *)(addr + offset + ar_name_size + 2279 sizeof(struct fat_header)); 2280#ifdef __LITTLE_ENDIAN__ 2281 swap_fat_arch(ofile->fat_archs, 2282 ofile->fat_header->nfat_arch, 2283 host_byte_sex); 2284#endif /* __LITTLE_ENDIAN__ */ 2285 if(check_fat_object_in_archive(ofile) == FALSE) 2286 goto fatcleanup; 2287 } 2288 else if(size - (offset + ar_name_size) >= 2289 sizeof(struct mach_header) && 2290 (magic == MH_MAGIC || 2291 magic == SWAP_INT(MH_MAGIC))){ 2292#ifdef ALIGNMENT_CHECKS 2293 if((offset + ar_name_size) % 4 != 0){ 2294 archive_member_error(ofile, "offset in archive not " 2295 "a multiple of 4) (must be since member is a " 2296 "32-bit object file)"); 2297 goto cleanup; 2298 } 2299#endif /* ALIGNMENT_CHECKS */ 2300 ofile->member_type = OFILE_Mach_O; 2301 ofile->object_addr = ofile->member_addr; 2302 ofile->object_size = ofile->member_size; 2303 if(magic == MH_MAGIC) 2304 ofile->object_byte_sex = host_byte_sex; 2305 else 2306 ofile->object_byte_sex = 2307 host_byte_sex == BIG_ENDIAN_BYTE_SEX ? 2308 LITTLE_ENDIAN_BYTE_SEX : BIG_ENDIAN_BYTE_SEX; 2309 ofile->mh = (struct mach_header *)ofile->object_addr; 2310 ofile->load_commands = (struct load_command *) 2311 (ofile->object_addr + sizeof(struct mach_header)); 2312 if(check_Mach_O(ofile) == CHECK_BAD) 2313 goto cleanup; 2314 } 2315 else if(size - (offset + ar_name_size) >= 2316 sizeof(struct mach_header_64) && 2317 (magic == MH_MAGIC_64 || 2318 magic == SWAP_INT(MH_MAGIC_64))){ 2319#ifdef ALIGNMENT_CHECKS_ARCHIVE_64_BIT 2320 if(archive_64_bit_align_warning == FALSE && 2321 (offset + ar_name_size) % 8 != 0){ 2322 temporary_archive_member_warning(ofile, "offset in " 2323 "archive not a multiple of 8) (must be since " 2324 "member is a 64-bit object file)"); 2325 archive_64_bit_align_warning = TRUE; 2326 /* goto cleanup; */ 2327 } 2328#endif /* ALIGNMENT_CHECKS_ARCHIVE_64_BIT */ 2329 ofile->member_type = OFILE_Mach_O; 2330 ofile->object_addr = ofile->member_addr; 2331 ofile->object_size = ofile->member_size; 2332 if(magic == MH_MAGIC_64) 2333 ofile->object_byte_sex = host_byte_sex; 2334 else 2335 ofile->object_byte_sex = 2336 host_byte_sex == BIG_ENDIAN_BYTE_SEX ? 2337 LITTLE_ENDIAN_BYTE_SEX : BIG_ENDIAN_BYTE_SEX; 2338 ofile->mh64 = (struct mach_header_64 *) 2339 ofile->object_addr; 2340 ofile->load_commands = (struct load_command *) 2341 (ofile->object_addr +sizeof(struct mach_header_64)); 2342 if(check_Mach_O(ofile) == CHECK_BAD) 2343 goto cleanup; 2344 } 2345 } 2346#ifdef LTO_SUPPORT 2347 if(ofile->member_type == OFILE_UNKNOWN && 2348 is_llvm_bitcode(ofile, ofile->member_addr, 2349 ofile->member_size) == TRUE){ 2350 ofile->member_type = OFILE_LLVM_BITCODE; 2351 ofile->object_addr = ofile->member_addr; 2352 ofile->object_size = ofile->member_size; 2353 } 2354#endif /* LTO_SUPPORT */ 2355 return(TRUE); 2356 } 2357 offset += rnd(strtoul(ar_hdr->ar_size, NULL, 10), 2358 sizeof(short)); 2359 } 2360 archive_error(ofile, "does not contain a member named: %s", 2361 member_name); 2362fatcleanup: 2363 ofile->fat_header = NULL; 2364 ofile->fat_archs = NULL; 2365cleanup: 2366 ofile->member_offset = 0; 2367 ofile->member_addr = NULL; 2368 ofile->member_size = 0; 2369 ofile->member_ar_hdr = NULL; 2370 ofile->member_name = NULL; 2371 ofile->member_name_size = 0; 2372 ofile->member_type = OFILE_UNKNOWN; 2373 ofile->object_addr = NULL; 2374 ofile->object_size = 0; 2375 ofile->object_byte_sex = UNKNOWN_BYTE_SEX; 2376 ofile->mh = NULL; 2377 ofile->mh64 = NULL; 2378 ofile->load_commands = NULL; 2379#ifdef LTO_SUPPORT 2380 ofile->lto = NULL; 2381 ofile->lto_cputype = 0; 2382 ofile->lto_cpusubtype = 0; 2383#endif /* LTO_SUPPORT */ 2384 return(FALSE); 2385} 2386 2387/* 2388 * ofile_first_module() set up the ofile structure (the dylib_module field) 2389 * for the first module of an MH_DYLIB or MH_DYLIB_STUB file. 2390 */ 2391__private_extern__ 2392enum bool 2393ofile_first_module( 2394struct ofile *ofile) 2395{ 2396 uint32_t i, ncmds; 2397 struct symtab_command *st; 2398 struct dysymtab_command *dyst; 2399 struct load_command *lc; 2400 enum bool swapped; 2401 enum byte_sex host_byte_sex; 2402 struct dylib_module m; 2403 struct dylib_module_64 m64; 2404 char *strings; 2405 2406 /* These fields are to be filled in by this routine, clear them first */ 2407 ofile->modtab = NULL; 2408 ofile->modtab64 = NULL; 2409 ofile->nmodtab = 0; 2410 ofile->dylib_module = NULL; 2411 ofile->dylib_module64 = NULL; 2412 ofile->dylib_module_name = NULL; 2413 2414 if(ofile->file_type == OFILE_FAT){ 2415 if(ofile->arch_type != OFILE_Mach_O && 2416 (ofile->mh_filetype != MH_DYLIB && 2417 ofile->mh_filetype != MH_DYLIB_STUB)){ 2418 error("ofile_first_module() called on fat file: %s with a " 2419 "non-MH_DYLIB architecture or no architecture selected\n", 2420 ofile->file_name); 2421 return(FALSE); 2422 } 2423 } 2424 else if(ofile->arch_type != OFILE_Mach_O && 2425 (ofile->mh_filetype != MH_DYLIB && 2426 ofile->mh_filetype != MH_DYLIB_STUB)){ 2427 error("ofile_first_module() called and file type of %s is " 2428 "non-MH_DYLIB\n", ofile->file_name); 2429 return(FALSE); 2430 } 2431 2432 st = NULL; 2433 dyst = NULL; 2434 lc = ofile->load_commands; 2435 if(ofile->mh != NULL) 2436 ncmds = ofile->mh->ncmds; 2437 else 2438 ncmds = ofile->mh64->ncmds; 2439 for(i = 0; i < ncmds; i++){ 2440 if(st == NULL && lc->cmd == LC_SYMTAB){ 2441 st = (struct symtab_command *)lc; 2442 } 2443 else if(lc->cmd == LC_DYSYMTAB){ 2444 dyst = (struct dysymtab_command *)lc; 2445 } 2446 lc = (struct load_command *)((char *)lc + lc->cmdsize); 2447 } 2448 if(st == NULL || dyst == NULL){ 2449#ifndef OTOOL 2450 Mach_O_error(ofile, "MH_DYLIB format error (does not have a symbol " 2451 "table and/or a dynamic symbol table)"); 2452#endif 2453 return(FALSE); 2454 } 2455 if(dyst->nmodtab == 0) 2456 return(FALSE); 2457 2458 ofile->nmodtab = dyst->nmodtab; 2459 host_byte_sex = get_host_byte_sex(); 2460 swapped = (enum bool)(host_byte_sex != ofile->object_byte_sex); 2461 strings = (char *)(ofile->object_addr + st->stroff); 2462 2463 if(ofile->mh != NULL){ 2464 ofile->modtab = (struct dylib_module *)(ofile->object_addr + 2465 dyst->modtaboff); 2466 ofile->dylib_module = ofile->modtab; 2467 m = *ofile->dylib_module; 2468 if(swapped) 2469 swap_dylib_module(&m, 1, host_byte_sex); 2470 ofile->dylib_module_name = strings + m.module_name; 2471 } 2472 else{ 2473 ofile->modtab64 = (struct dylib_module_64 *)(ofile->object_addr + 2474 dyst->modtaboff); 2475 ofile->dylib_module64 = ofile->modtab64; 2476 m64 = *ofile->dylib_module64; 2477 if(swapped) 2478 swap_dylib_module_64(&m64, 1, host_byte_sex); 2479 ofile->dylib_module_name = strings + m64.module_name; 2480 } 2481 2482 if(check_dylib_module(ofile, st, dyst, strings, 0) == CHECK_BAD) 2483 return(FALSE); 2484 return(TRUE); 2485} 2486 2487/* 2488 * ofile_next_module() set up the ofile structure (the dylib_module field) 2489 * for the next module of an MH_DYLIB or MH_DYLIB_STUB file. 2490 */ 2491__private_extern__ 2492enum bool 2493ofile_next_module( 2494struct ofile *ofile) 2495{ 2496 uint32_t i, module_index, ncmds; 2497 struct symtab_command *st; 2498 struct dysymtab_command *dyst; 2499 struct load_command *lc; 2500 enum bool swapped; 2501 enum byte_sex host_byte_sex; 2502 struct dylib_module m; 2503 struct dylib_module_64 m64; 2504 char *strings; 2505 2506 if(ofile->file_type == OFILE_FAT){ 2507 if(ofile->arch_type != OFILE_Mach_O && 2508 (ofile->mh_filetype != MH_DYLIB && 2509 ofile->mh_filetype != MH_DYLIB_STUB)){ 2510 error("ofile_next_module() called on fat file: %s with a " 2511 "non-MH_DYLIB architecture or no architecture selected\n", 2512 ofile->file_name); 2513 return(FALSE); 2514 } 2515 } 2516 else if(ofile->arch_type != OFILE_Mach_O && 2517 (ofile->mh_filetype != MH_DYLIB && 2518 ofile->mh_filetype != MH_DYLIB_STUB)){ 2519 error("ofile_next_module() called and file type of %s is " 2520 "non-MH_DYLIB\n", ofile->file_name); 2521 return(FALSE); 2522 } 2523 st = NULL; 2524 dyst = NULL; 2525 lc = ofile->load_commands; 2526 if(ofile->mh != NULL) 2527 ncmds = ofile->mh->ncmds; 2528 else 2529 ncmds = ofile->mh64->ncmds; 2530 for(i = 0; i < ncmds; i++){ 2531 if(st == NULL && lc->cmd == LC_SYMTAB){ 2532 st = (struct symtab_command *)lc; 2533 } 2534 else if(lc->cmd == LC_DYSYMTAB){ 2535 dyst = (struct dysymtab_command *)lc; 2536 } 2537 lc = (struct load_command *)((char *)lc + lc->cmdsize); 2538 } 2539 if(st == NULL || dyst == NULL){ 2540#ifndef OTOOL 2541 Mach_O_error(ofile, "MH_DYLIB format error (does not have a symbol " 2542 "table and/or a dynamic symbol table)"); 2543#endif 2544 return(FALSE); 2545 } 2546 2547 if(ofile->mh != NULL) 2548 module_index = (ofile->dylib_module + 1) - ofile->modtab; 2549 else 2550 module_index = (ofile->dylib_module64 + 1) - ofile->modtab64; 2551 if(module_index >= ofile->nmodtab) 2552 return(FALSE); 2553 2554 host_byte_sex = get_host_byte_sex(); 2555 swapped = (enum bool)(host_byte_sex != ofile->object_byte_sex); 2556 strings = (char *)(ofile->object_addr + st->stroff); 2557 2558 if(ofile->mh != NULL){ 2559 ofile->dylib_module++; 2560 m = *ofile->dylib_module; 2561 if(swapped) 2562 swap_dylib_module(&m, 1, host_byte_sex); 2563 ofile->dylib_module_name = strings + m.module_name; 2564 } 2565 else{ 2566 ofile->dylib_module64++; 2567 m64 = *ofile->dylib_module64; 2568 if(swapped) 2569 swap_dylib_module_64(&m64, 1, host_byte_sex); 2570 ofile->dylib_module_name = strings + m64.module_name; 2571 } 2572 if(check_dylib_module(ofile, st, dyst, strings, module_index) == 2573 CHECK_BAD) 2574 return(FALSE); 2575 return(TRUE); 2576} 2577 2578/* 2579 * ofile_specific_module() set up the ofile structure (the dylib_module fields) 2580 * for the specified module, module_name, of an MH_DYLIB or an MH_DYLIB_STUB 2581 * file. 2582 */ 2583__private_extern__ 2584enum bool 2585ofile_specific_module( 2586const char *module_name, 2587struct ofile *ofile) 2588{ 2589 uint32_t i, ncmds; 2590 enum bool swapped; 2591 enum byte_sex host_byte_sex; 2592 struct symtab_command *st; 2593 struct dysymtab_command *dyst; 2594 struct load_command *lc; 2595 struct dylib_module *p, m; 2596 struct dylib_module_64 *p64, m64; 2597 char *strings; 2598 2599 /* These fields are to be filled in by this routine, clear them first */ 2600 ofile->modtab = NULL; 2601 ofile->modtab64 = NULL; 2602 ofile->nmodtab = 0; 2603 ofile->dylib_module = NULL; 2604 ofile->dylib_module64 = NULL; 2605 ofile->dylib_module_name = NULL; 2606 2607 if(ofile->file_type == OFILE_FAT){ 2608 if(ofile->arch_type != OFILE_Mach_O && 2609 (ofile->mh_filetype != MH_DYLIB && 2610 ofile->mh_filetype != MH_DYLIB_STUB)){ 2611 error("ofile_specific_module() called on fat file: %s with a " 2612 "non-MH_DYLIB architecture or no architecture selected\n", 2613 ofile->file_name); 2614 return(FALSE); 2615 } 2616 } 2617 else if(ofile->arch_type != OFILE_Mach_O && 2618 (ofile->mh_filetype != MH_DYLIB && 2619 ofile->mh_filetype != MH_DYLIB_STUB)){ 2620 error("ofile_specific_module() called and file type of %s is " 2621 "non-MH_DYLIB\n", ofile->file_name); 2622 return(FALSE); 2623 } 2624 2625 st = NULL; 2626 dyst = NULL; 2627 lc = ofile->load_commands; 2628 if(ofile->mh != NULL) 2629 ncmds = ofile->mh->ncmds; 2630 else 2631 ncmds = ofile->mh64->ncmds; 2632 for(i = 0; i < ncmds; i++){ 2633 if(st == NULL && lc->cmd == LC_SYMTAB){ 2634 st = (struct symtab_command *)lc; 2635 } 2636 else if(lc->cmd == LC_DYSYMTAB){ 2637 dyst = (struct dysymtab_command *)lc; 2638 } 2639 lc = (struct load_command *)((char *)lc + lc->cmdsize); 2640 } 2641 if(st == NULL || dyst == NULL){ 2642#ifndef OTOOL 2643 Mach_O_error(ofile, "MH_DYLIB format error (does not have a symbol " 2644 "table and/or a dynamic symbol table)"); 2645#endif 2646 return(FALSE); 2647 } 2648 if(dyst->nmodtab == 0) 2649 return(FALSE); 2650 2651 host_byte_sex = get_host_byte_sex(); 2652 swapped = (enum bool)(host_byte_sex != ofile->object_byte_sex); 2653 strings = (char *)(ofile->object_addr + st->stroff); 2654 2655 if(ofile->mh != NULL){ 2656 ofile->nmodtab = dyst->nmodtab; 2657 ofile->modtab = (struct dylib_module *)(ofile->object_addr + 2658 dyst->modtaboff); 2659 p = ofile->modtab; 2660 for(i = 0; i < dyst->nmodtab; i++){ 2661 m = *p; 2662 if(swapped) 2663 swap_dylib_module(&m, 1, host_byte_sex); 2664 ofile->dylib_module = p; 2665 if(check_dylib_module(ofile, st, dyst, strings, i) == CHECK_BAD) 2666 return(FALSE); 2667 if(strcmp(module_name, strings + m.module_name) == 0){ 2668 ofile->dylib_module_name = strings + m.module_name; 2669 return(TRUE); 2670 } 2671 p++; 2672 } 2673 m = *ofile->dylib_module; 2674 if(swapped) 2675 swap_dylib_module(&m, 1, host_byte_sex); 2676 ofile->dylib_module_name = strings + m.module_name; 2677 } 2678 else{ 2679 ofile->nmodtab = dyst->nmodtab; 2680 ofile->modtab64 = (struct dylib_module_64 *)(ofile->object_addr + 2681 dyst->modtaboff); 2682 p64 = ofile->modtab64; 2683 for(i = 0; i < dyst->nmodtab; i++){ 2684 m64 = *p64; 2685 if(swapped) 2686 swap_dylib_module_64(&m64, 1, host_byte_sex); 2687 ofile->dylib_module64 = p64; 2688 if(check_dylib_module(ofile, st, dyst, strings, i) == CHECK_BAD) 2689 return(FALSE); 2690 if(strcmp(module_name, strings + m64.module_name) == 0){ 2691 ofile->dylib_module_name = strings + m64.module_name; 2692 return(TRUE); 2693 } 2694 p64++; 2695 } 2696 m64 = *ofile->dylib_module64; 2697 if(swapped) 2698 swap_dylib_module_64(&m64, 1, host_byte_sex); 2699 ofile->dylib_module_name = strings + m64.module_name; 2700 } 2701#ifndef OTOOL 2702 Mach_O_error(ofile, "does not contain a module named: %s", module_name); 2703#endif 2704 ofile->modtab = NULL; 2705 ofile->nmodtab = 0; 2706 ofile->dylib_module = NULL; 2707 ofile->dylib_module_name = NULL; 2708 return(FALSE); 2709} 2710 2711#ifdef DEBUG 2712__private_extern__ 2713void 2714ofile_print( 2715struct ofile *ofile) 2716{ 2717 printf("file_name = %s\n", ofile->file_name); 2718 printf("file_addr = 0x%x\n", (unsigned int)ofile->file_addr); 2719 printf("file_size = 0x%x\n", (unsigned int)ofile->file_size); 2720 printf("file_type = 0x%x\n", (unsigned int)ofile->file_type); 2721 printf("fat_header = 0x%x\n", (unsigned int)ofile->fat_header); 2722 printf("fat_archs = 0x%x\n", (unsigned int)ofile->fat_archs); 2723 printf("narch = 0x%x\n", (unsigned int)ofile->narch); 2724 printf("arch_type = 0x%x\n", (unsigned int)ofile->arch_type); 2725 printf("arch_flag.name = %s\n", ofile->arch_flag.name); 2726 printf("arch_flag.cputype = 0x%x\n", 2727 (unsigned int)ofile->arch_flag.cputype); 2728 printf("arch_flag.cpusubtype = 0x%x\n", 2729 (unsigned int)ofile->arch_flag.cpusubtype); 2730 printf("member_offset = 0x%x\n", (unsigned int)ofile->member_offset); 2731 printf("member_addr = 0x%x\n", (unsigned int)ofile->member_addr); 2732 printf("member_size = 0x%x\n", (unsigned int)ofile->member_size); 2733 printf("member_ar_hdr = 0x%x\n", (unsigned int)ofile->member_ar_hdr); 2734 printf("member_type = 0x%x\n", (unsigned int)ofile->member_type); 2735 printf("archive_cputype = 0x%x\n", 2736 (unsigned int)ofile->archive_cputype); 2737 printf("archive_cpusubtype = 0x%x\n", 2738 (unsigned int)ofile->archive_cpusubtype); 2739 printf("object_addr = 0x%x\n", (unsigned int)ofile->object_addr); 2740 printf("object_size = 0x%x\n", (unsigned int)ofile->object_size); 2741 printf("object_byte_sex = 0x%x\n", 2742 (unsigned int)ofile->object_byte_sex); 2743 printf("mh = 0x%x\n", (unsigned int)ofile->mh); 2744 printf("mh64 = 0x%x\n", (unsigned int)ofile->mh64); 2745 printf("load_commands = 0x%x\n", (unsigned int)ofile->load_commands); 2746} 2747#endif /* DEBUG */ 2748 2749/* 2750 * check_fat() checks the fat ofile for correctness (the fat_header and 2751 * fat_archs are assumed to be in the host byte sex). 2752 */ 2753static 2754enum check_type 2755check_fat( 2756struct ofile *ofile) 2757{ 2758#ifdef OTOOL 2759 return(CHECK_GOOD); 2760#else /* !defined OTOOL */ 2761 2762 uint32_t i, j; 2763 uint64_t big_size; 2764 2765 if(ofile->file_type != OFILE_FAT){ 2766 error("internal error. check_fat() call and file type of: %s is " 2767 "not OFILE_FAT\n", ofile->file_name); 2768 return(CHECK_BAD); 2769 } 2770 if(ofile->fat_header->nfat_arch == 0){ 2771 error("fat file: %s malformed (contains zero architecture types)", 2772 ofile->file_name); 2773 return(CHECK_BAD); 2774 } 2775 for(i = 0; i < ofile->fat_header->nfat_arch; i++){ 2776 big_size = ofile->fat_archs[i].offset; 2777 big_size += ofile->fat_archs[i].size; 2778 if(big_size > ofile->file_size){ 2779 error("fat file: %s truncated or malformed (offset plus size " 2780 "of cputype (%d) cpusubtype (%d) extends past the " 2781 "end of the file)", ofile->file_name, 2782 ofile->fat_archs[i].cputype, 2783 ofile->fat_archs[i].cpusubtype & ~CPU_SUBTYPE_MASK); 2784 return(CHECK_BAD); 2785 } 2786 if(ofile->fat_archs[i].align > MAXSECTALIGN){ 2787 error("fat file: %s align (2^%u) too large for cputype (%d) " 2788 "cpusubtype (%d) (maximum 2^%d)", ofile->file_name, 2789 ofile->fat_archs[i].align, ofile->fat_archs[i].cputype, 2790 ofile->fat_archs[i].cpusubtype & ~CPU_SUBTYPE_MASK, 2791 MAXSECTALIGN); 2792 return(CHECK_BAD); 2793 } 2794 if(ofile->fat_archs[i].offset % 2795 (1 << ofile->fat_archs[i].align) != 0){ 2796 error("fat file: %s offset: %u for cputype (%d) cpusubtype " 2797 "(%d)) not aligned on it's alignment (2^%u)", 2798 ofile->file_name, 2799 ofile->fat_archs[i].offset, 2800 ofile->fat_archs[i].cputype, 2801 ofile->fat_archs[i].cpusubtype & ~CPU_SUBTYPE_MASK, 2802 ofile->fat_archs[i].align); 2803 return(CHECK_BAD); 2804 } 2805 } 2806 for(i = 0; i < ofile->fat_header->nfat_arch; i++){ 2807 for(j = i + 1; j < ofile->fat_header->nfat_arch; j++){ 2808 if(ofile->fat_archs[i].cputype == 2809 ofile->fat_archs[j].cputype && 2810 (ofile->fat_archs[i].cpusubtype & ~CPU_SUBTYPE_MASK) == 2811 (ofile->fat_archs[j].cpusubtype & ~CPU_SUBTYPE_MASK)){ 2812 error("fat file: %s contains two of the same " 2813 "architecture (cputype (%d) cpusubtype (%d))", 2814 ofile->file_name, ofile->fat_archs[i].cputype, 2815 ofile->fat_archs[i].cpusubtype & ~CPU_SUBTYPE_MASK); 2816 return(CHECK_BAD); 2817 } 2818 } 2819 } 2820 return(CHECK_GOOD); 2821#endif /* OTOOL */ 2822} 2823 2824/* 2825 * check_fat_object_in_archive() checks the fat object file which is a member 2826 * of a thin archive for correctness (the fat_header and fat_archs are assumed 2827 * to be in the host byte sex). This is not a legal form but allowed when 2828 * archives_with_fat_objects is TRUE when ofile_map() is called. 2829 */ 2830static 2831enum check_type 2832check_fat_object_in_archive( 2833struct ofile *ofile) 2834{ 2835 uint32_t i, j; 2836 uint32_t magic; 2837 2838 if(ofile->file_type != OFILE_ARCHIVE){ 2839 error("internal error. check_fat_object_in_archive() called and " 2840 "file type of: %s is not OFILE_ARCHIVE\n", ofile->file_name); 2841 return(CHECK_BAD); 2842 } 2843 if(ofile->fat_header->nfat_arch == 0){ 2844 archive_member_error(ofile, "fat file malformed (contains zero " 2845 "architecture types)"); 2846 return(CHECK_BAD); 2847 } 2848 for(i = 0; i < ofile->fat_header->nfat_arch; i++){ 2849 if(ofile->fat_archs[i].offset + ofile->fat_archs[i].size > 2850 ofile->member_size){ 2851 archive_member_error(ofile, "fat file truncated or malformed " 2852 "(offset plus size of cputype (%d) cpusubtype (%d) " 2853 "extends past the end of the file)", 2854 ofile->fat_archs[i].cputype, 2855 ofile->fat_archs[i].cpusubtype & ~CPU_SUBTYPE_MASK); 2856 return(CHECK_BAD); 2857 } 2858 if(ofile->fat_archs[i].align > MAXSECTALIGN){ 2859 archive_member_error(ofile, "fat file's align (2^%u) too " 2860 "large for cputype (%d) cpusubtype (%d) (maximum 2^%d)", 2861 ofile->fat_archs[i].align, ofile->fat_archs[i].cputype, 2862 ofile->fat_archs[i].cpusubtype & ~CPU_SUBTYPE_MASK, 2863 MAXSECTALIGN); 2864 return(CHECK_BAD); 2865 } 2866 if(ofile->fat_archs[i].offset % 2867 (1 << ofile->fat_archs[i].align) != 0){ 2868 archive_member_error(ofile, "fat file's offset: %u for " 2869 "cputype (%d) cpusubtype (%d) not aligned on it's " 2870 "alignment (2^%u)", ofile->fat_archs[i].offset, 2871 ofile->fat_archs[i].cputype, 2872 ofile->fat_archs[i].cpusubtype & ~CPU_SUBTYPE_MASK, 2873 ofile->fat_archs[i].align); 2874 return(CHECK_BAD); 2875 } 2876 2877 /* 2878 * The only supported format where fat files are allowed to appear 2879 * in archives is when the fat file contains only object files. 2880 */ 2881 if(ofile->fat_archs[i].size < sizeof(struct mach_header)){ 2882 archive_member_error(ofile, "fat file for cputype (%d) " 2883 "cpusubtype (%d) is not an object file (size too small " 2884 "to be an object file)", ofile->fat_archs[i].cputype, 2885 ofile->fat_archs[i].cpusubtype & ~CPU_SUBTYPE_MASK); 2886 return(CHECK_BAD); 2887 } 2888 memcpy(&magic, 2889 ofile->file_addr + ofile->member_offset + 2890 ofile->fat_archs[i].offset, 2891 sizeof(uint32_t)); 2892 if(magic == MH_MAGIC || magic == SWAP_INT(MH_MAGIC)){ 2893#ifdef ALIGNMENT_CHECKS 2894 if((ofile->member_offset + ofile->fat_archs[i].offset) % 2895 4 != 0){ 2896 archive_member_error(ofile, "fat object file's offset in " 2897 "archive not a multiple of 4) (must be since " 2898 "member is a 32-bit object file)"); 2899 return(CHECK_BAD); 2900 } 2901#endif /* ALIGNMENT_CHECKS */ 2902 } 2903 else if(magic == MH_MAGIC_64 || magic == SWAP_INT(MH_MAGIC_64)){ 2904#ifdef ALIGNMENT_CHECKS_ARCHIVE_64_BIT 2905 if(archive_64_bit_align_warning == FALSE && 2906 (ofile->member_offset + ofile->fat_archs[i].offset) % 2907 8 != 0){ 2908 temporary_archive_member_warning(ofile, "fat object file's " 2909 "offset in archive not a multiple of 8) (must be since " 2910 "member is a 64-bit object file)"); 2911 archive_64_bit_align_warning = TRUE; 2912 /* return(CHECK_BAD); */ 2913 } 2914#endif /* ALIGNMENT_CHECKS_ARCHIVE_64_BIT */ 2915 } 2916 else{ 2917#ifdef LTO_SUPPORT 2918 if(is_llvm_bitcode(ofile, ofile->file_addr + 2919 ofile->member_offset + ofile->fat_archs[i].offset, 2920 ofile->fat_archs[i].size) == TRUE){ 2921 ofile->member_type = OFILE_LLVM_BITCODE; 2922 ofile->object_addr = ofile->member_addr; 2923 ofile->object_size = ofile->member_size; 2924 } 2925 else 2926#endif /* LTO_SUPPORT */ 2927 { 2928 archive_member_error(ofile, "fat file for cputype (%d) " 2929 "cpusubtype (%d) is not an object file (bad magic " 2930 "number)", ofile->fat_archs[i].cputype, 2931 ofile->fat_archs[i].cpusubtype & ~CPU_SUBTYPE_MASK); 2932 return(CHECK_BAD); 2933 } 2934 } 2935 } 2936 for(i = 0; i < ofile->fat_header->nfat_arch; i++){ 2937 for(j = i + 1; j < ofile->fat_header->nfat_arch; j++){ 2938 if(ofile->fat_archs[i].cputype == 2939 ofile->fat_archs[j].cputype && 2940 (ofile->fat_archs[i].cpusubtype & ~CPU_SUBTYPE_MASK) == 2941 (ofile->fat_archs[j].cpusubtype & ~CPU_SUBTYPE_MASK)){ 2942 archive_member_error(ofile, "fat file contains two of the " 2943 "same architecture (cputype (%d) cpusubtype (%d))", 2944 ofile->fat_archs[i].cputype, 2945 ofile->fat_archs[i].cpusubtype & ~CPU_SUBTYPE_MASK); 2946 return(CHECK_BAD); 2947 } 2948 } 2949 } 2950 return(CHECK_GOOD); 2951} 2952 2953/* 2954 * check_archive() checks the archive referenced in the ofile for correctness. 2955 */ 2956static 2957enum check_type 2958check_archive( 2959struct ofile *ofile, 2960enum bool archives_with_fat_objects) 2961{ 2962#ifdef OTOOL 2963 return(CHECK_GOOD); 2964#else /* !defined OTOOL */ 2965 char *addr; 2966 uint64_t size, offset; 2967 uint64_t big_size; 2968 uint32_t magic; 2969 enum byte_sex host_byte_sex; 2970 enum bool swapped; 2971 struct mach_header mh; 2972 struct mach_header_64 mh64; 2973 struct ar_hdr *ar_hdr; 2974 uint32_t ar_name_size; 2975 2976 /* 2977 * Get the address and size of the archive (as well as the cputype and 2978 * cpusubtype if known) and make sure it is an archive. 2979 */ 2980 if(ofile->file_type == OFILE_FAT){ 2981 addr = ofile->file_addr + ofile->fat_archs[ofile->narch].offset; 2982 size = ofile->fat_archs[ofile->narch].size; 2983 ofile->archive_cputype = ofile->fat_archs[ofile->narch].cputype; 2984 ofile->archive_cpusubtype = 2985 ofile->fat_archs[ofile->narch].cpusubtype; 2986 } 2987 else if(ofile->file_type == OFILE_ARCHIVE){ 2988 addr = ofile->file_addr; 2989 size = ofile->file_size; 2990 ofile->archive_cputype = 0; 2991 ofile->archive_cpusubtype = 0; 2992 } 2993 else{ 2994 error("internal error. check_archive() call and file type of %s is " 2995 "OFILE_UNKNOWN\n", ofile->file_name); 2996 return(CHECK_BAD); 2997 } 2998 if(size < SARMAG || strncmp(addr, ARMAG, SARMAG) != 0){ 2999 error("internal error. check_archive() call for file %s which does " 3000 "not have an archive magic string", ofile->file_name); 3001 return(CHECK_BAD); 3002 } 3003 3004 host_byte_sex = get_host_byte_sex(); 3005 /* 3006 * Check this archive out to make sure that it does not contain 3007 * any fat files and that all object files it contains have the 3008 * same cputype and subsubtype. 3009 */ 3010 offset = SARMAG; 3011 if(offset == size) 3012 return(CHECK_GOOD); 3013 if(offset != size && offset + sizeof(struct ar_hdr) > size){ 3014 archive_error(ofile, "truncated or malformed (archive header of " 3015 "first member extends past the end of the file)"); 3016 return(CHECK_BAD); 3017 } 3018 while(size > offset){ 3019 ar_hdr = (struct ar_hdr *)(addr + offset); 3020 ofile->member_offset = offset; 3021 ofile->member_addr = addr + offset; 3022 ofile->member_size = strtoul(ar_hdr->ar_size, NULL, 10); 3023 ofile->member_ar_hdr = ar_hdr; 3024 ofile->member_name = ar_hdr->ar_name; 3025 ofile->member_name_size = size_ar_name(ofile->member_ar_hdr); 3026 offset += sizeof(struct ar_hdr); 3027 /* 3028 * See if this archive member is using extend format #1 where 3029 * the size of the name is in ar_name and the name follows the 3030 * archive header. 3031 */ 3032 ar_name_size = 0; 3033 if(strncmp(ofile->member_name,AR_EFMT1, sizeof(AR_EFMT1) - 1) == 0){ 3034 if(check_extend_format_1(ofile, ar_hdr, size - offset, 3035 &ar_name_size) == CHECK_BAD) 3036 return(CHECK_BAD); 3037 ofile->member_name = ar_hdr->ar_name + sizeof(struct ar_hdr); 3038 ofile->member_name_size = ar_name_size; 3039 offset += ar_name_size; 3040 ofile->member_offset += ar_name_size; 3041 ofile->member_addr += ar_name_size; 3042 ofile->member_size -= ar_name_size; 3043 } 3044 big_size = rnd(ofile->member_size, sizeof(short)); 3045 big_size += offset; 3046 if(big_size > size){ 3047 archive_member_error(ofile, "size too large (archive " 3048 "member extends past the end of the file)"); 3049 return(CHECK_BAD); 3050 } 3051 if(size - offset > sizeof(uint32_t)){ 3052 memcpy(&magic, addr + offset, sizeof(uint32_t)); 3053#ifdef __BIG_ENDIAN__ 3054 if(magic == FAT_MAGIC) 3055#endif /* __BIG_ENDIAN__ */ 3056#ifdef __LITTLE_ENDIAN__ 3057 if(magic == SWAP_INT(FAT_MAGIC)) 3058#endif /* __LITTLE_ENDIAN__ */ 3059 { 3060 if(archives_with_fat_objects == FALSE || 3061 ofile->file_type != OFILE_ARCHIVE){ 3062 archive_member_error(ofile, "is a fat file (not " 3063 "allowed in an archive)"); 3064 return(CHECK_BAD); 3065 } 3066 } 3067 else{ 3068 if(size - offset >= sizeof(struct mach_header) && 3069 (magic == MH_MAGIC || magic == SWAP_INT(MH_MAGIC))){ 3070 memcpy(&mh, addr + offset, sizeof(struct mach_header)); 3071 if(magic == SWAP_INT(MH_MAGIC)){ 3072 magic = MH_MAGIC; 3073 swapped = TRUE; 3074 swap_mach_header(&mh, host_byte_sex); 3075 } 3076 swapped = FALSE; 3077 } 3078 else if(size - offset >= sizeof(struct mach_header_64) && 3079 (magic == MH_MAGIC_64 || 3080 magic == SWAP_INT(MH_MAGIC_64))){ 3081 memcpy(&mh64, addr + offset, 3082 sizeof(struct mach_header_64)); 3083 if(magic == SWAP_INT(MH_MAGIC_64)){ 3084 magic = MH_MAGIC_64; 3085 swapped = TRUE; 3086 swap_mach_header_64(&mh64, host_byte_sex); 3087 } 3088 swapped = FALSE; 3089 } 3090 if(magic == MH_MAGIC){ 3091 if(ofile->archive_cputype == 0){ 3092 ofile->archive_cputype = mh.cputype; 3093 ofile->archive_cpusubtype = mh.cpusubtype; 3094 } 3095 else if(ofile->archive_cputype != mh.cputype){ 3096 archive_member_error(ofile, "cputype (%d) does not " 3097 "match previous archive members cputype (%d) " 3098 "(all members must match)", mh.cputype, 3099 ofile->archive_cputype); 3100 } 3101 } 3102 else if(magic == MH_MAGIC_64){ 3103 if(ofile->archive_cputype == 0){ 3104 ofile->archive_cputype = mh64.cputype; 3105 ofile->archive_cpusubtype = mh64.cpusubtype; 3106 } 3107 else if(ofile->archive_cputype != mh64.cputype){ 3108 archive_member_error(ofile, "cputype (%d) does not " 3109 "match previous archive members cputype (%d) " 3110 "(all members must match)", mh64.cputype, 3111 ofile->archive_cputype); 3112 } 3113 } 3114 } 3115 } 3116 offset += rnd(ofile->member_size, sizeof(short)); 3117 } 3118 ofile->member_offset = 0; 3119 ofile->member_addr = NULL; 3120 ofile->member_size = 0; 3121 ofile->member_ar_hdr = NULL;; 3122 ofile->member_name = NULL; 3123 ofile->member_name_size = 0; 3124 return(CHECK_GOOD); 3125#endif /* OTOOL */ 3126} 3127 3128/* 3129 * check_extend_format_1() checks the archive header for extended format #1. 3130 */ 3131static 3132enum check_type 3133check_extend_format_1( 3134struct ofile *ofile, 3135struct ar_hdr *ar_hdr, 3136uint32_t size_left, 3137uint32_t *member_name_size) 3138{ 3139 char *p, *endp, buf[sizeof(ar_hdr->ar_name)+1]; 3140 uint32_t ar_name_size; 3141 3142 *member_name_size = 0; 3143 3144 buf[sizeof(ar_hdr->ar_name)] = '\0'; 3145 memcpy(buf, ar_hdr->ar_name, sizeof(ar_hdr->ar_name)); 3146 p = buf + sizeof(AR_EFMT1) - 1; 3147 if(isdigit(*p) == 0){ 3148 archive_error(ofile, "malformed (ar_name: %.*s for archive " 3149 "extend format #1 starts with non-digit)", 3150 (int)sizeof(ar_hdr->ar_name), ar_hdr->ar_name); 3151 return(CHECK_BAD); 3152 } 3153 ar_name_size = strtoul(p, &endp, 10); 3154 if(ar_name_size == UINT_MAX && errno == ERANGE){ 3155 archive_error(ofile, "malformed (size in ar_name: %.*s for " 3156 "archive extend format #1 overflows uint32_t)", 3157 (int)sizeof(ar_hdr->ar_name), ar_hdr->ar_name); 3158 return(CHECK_BAD); 3159 } 3160 while(*endp == ' ' && *endp != '\0') 3161 endp++; 3162 if(*endp != '\0'){ 3163 archive_error(ofile, "malformed (size in ar_name: %.*s for " 3164 "archive extend format #1 contains non-digit and " 3165 "non-space characters)", (int)sizeof(ar_hdr->ar_name), 3166 ar_hdr->ar_name); 3167 return(CHECK_BAD); 3168 } 3169 if(ar_name_size > size_left){ 3170 archive_error(ofile, "truncated or malformed (archive name " 3171 "of member extends past the end of the file)"); 3172 return(CHECK_BAD); 3173 } 3174 *member_name_size = ar_name_size; 3175 return(CHECK_GOOD); 3176} 3177 3178/* 3179 * check_archive_toc() checks the archive table of contents referenced in the 3180 * thin archive via the ofile for correctness and if bad sets the bad_toc field 3181 * in the ofile struct to TRUE. If not it sets the other toc_* fields that 3182 * ranlib(1) uses to know it can't update the table of contents and doesn't 3183 * have to totally rebuild it. And by this always returning CHECK_GOOD it 3184 * allows otool(1) to print messed up tables of contents for debugging. 3185 */ 3186static 3187enum check_type 3188check_archive_toc( 3189struct ofile *ofile) 3190{ 3191 uint32_t i, symdef_length, offset, nranlibs, strsize; 3192 enum byte_sex host_byte_sex, toc_byte_sex; 3193 struct ranlib *ranlibs; 3194 char *strings; 3195 3196 ofile->toc_ranlibs = NULL; 3197 ofile->toc_nranlibs = 0; 3198 ofile->toc_strings = NULL; 3199 ofile->toc_strsize = 0; 3200 3201 /* 3202 * Note this can only be called when the whole file is a thin archive. 3203 */ 3204 if(ofile->file_type != OFILE_ARCHIVE) 3205 return(CHECK_GOOD); 3206 3207 symdef_length = ofile->toc_size; 3208 /* 3209 * The contents of a __.SYMDEF file is begins with a 32-bit word giving 3210 * the size in bytes of ranlib structures which immediately follow, and 3211 * then continues with a string table consisting of a 32-bit word giving 3212 * the number of bytes of strings which follow and then the strings 3213 * themselves. So the smallest valid size is two 32-bit words long. 3214 */ 3215 if(symdef_length < 2 * sizeof(uint32_t)){ 3216 /* 3217 * Size of table of contents for archive too small to be a valid 3218 * table of contents. 3219 */ 3220 ofile->toc_bad = TRUE; 3221 return(CHECK_GOOD); 3222 } 3223 host_byte_sex = get_host_byte_sex(); 3224 toc_byte_sex = get_toc_byte_sex(ofile->file_addr, ofile->file_size); 3225 if(toc_byte_sex == UNKNOWN_BYTE_SEX){ 3226 /* 3227 * Can't determine the byte order of table of contents as it 3228 * contains no Mach-O files. 3229 */ 3230 ofile->toc_bad = TRUE; 3231 return(CHECK_GOOD); 3232 } 3233 offset = 0; 3234 nranlibs = *((uint32_t *)(ofile->toc_addr + offset)); 3235 if(toc_byte_sex != host_byte_sex) 3236 nranlibs = SWAP_INT(nranlibs); 3237 nranlibs = nranlibs / sizeof(struct ranlib); 3238 offset += sizeof(uint32_t); 3239 ranlibs = (struct ranlib *)(ofile->toc_addr + offset); 3240 offset += sizeof(struct ranlib) * nranlibs; 3241 if(nranlibs == 0) 3242 return(CHECK_GOOD); 3243 if(offset - (2 * sizeof(uint32_t)) > symdef_length){ 3244 /* 3245 * Truncated or malformed archive. The ranlib structures in table 3246 * of contents extends past the end of the table of contents. 3247 */ 3248 ofile->toc_bad = TRUE; 3249 return(CHECK_GOOD); 3250 } 3251 strsize = *((uint32_t *)(ofile->toc_addr + offset)); 3252 if(toc_byte_sex != host_byte_sex) 3253 strsize = SWAP_INT(strsize); 3254 offset += sizeof(uint32_t); 3255 strings = ofile->toc_addr + offset; 3256 offset += strsize; 3257 if(offset - (2 * sizeof(uint32_t)) > symdef_length){ 3258 /* 3259 * Truncated or malformed archive. The ranlib strings in table of 3260 * contents extends past the end of the table of contents. 3261 */ 3262 ofile->toc_bad = TRUE; 3263 return(CHECK_GOOD); 3264 } 3265 if(symdef_length == 2 * sizeof(uint32_t)) 3266 return(CHECK_GOOD); 3267 3268 /* 3269 * Check the string offset and the member offsets of the ranlib structs. 3270 */ 3271 if(toc_byte_sex != host_byte_sex) 3272 swap_ranlib(ranlibs, nranlibs, host_byte_sex); 3273 for(i = 0; i < nranlibs; i++){ 3274 if(ranlibs[i].ran_un.ran_strx >= strsize){ 3275 /* 3276 * Malformed table of contents. The ranlib struct at this index 3277 * has a bad string index field. 3278 */ 3279 ofile->toc_bad = TRUE; 3280 return(CHECK_GOOD); 3281 } 3282 if(ranlibs[i].ran_off >= ofile->file_size){ 3283 /* 3284 * Malformed table of contents. The ranlib struct at this index 3285 * has a bad library member offset field. 3286 */ 3287 ofile->toc_bad = TRUE; 3288 return(CHECK_GOOD); 3289 } 3290 /* 3291 * These should be on 4 byte boundaries because the maximum 3292 * alignment of the header structures and relocation are 4 bytes. 3293 * But this is has to be 2 bytes because that's the way ar(1) has 3294 * worked historicly in the past. Fortunately this works on the 3295 * 68k machines but will have to change when this is on a real 3296 * machine. 3297 */ 3298#if defined(mc68000) || defined(__i386__) 3299 if(ranlibs[i].ran_off % sizeof(short) != 0){ 3300 /* 3301 * Malformed table of contents. This ranlib struct library 3302 * member offset not a multiple 2 bytes. 3303 */ 3304 ofile->toc_bad = TRUE; 3305 return(CHECK_GOOD); 3306 } 3307#else 3308 if(ranlibs[i].ran_off % sizeof(uint32_t) != 0){ 3309 /* 3310 * Malformed table of contents. This ranlib struct library 3311 * member offset not a multiple of 4 bytes. 3312 */ 3313 ofile->toc_bad = TRUE; 3314 return(CHECK_GOOD); 3315 } 3316#endif 3317 } 3318 ofile->toc_ranlibs = ranlibs; 3319 ofile->toc_nranlibs = nranlibs; 3320 ofile->toc_strings = strings; 3321 ofile->toc_strsize = strsize; 3322 return(CHECK_GOOD); 3323} 3324 3325/* 3326 * check_Mach_O() checks the object file's mach header and load commands 3327 * referenced in the ofile for correctness (this also swaps the mach header 3328 * and load commands into the host byte sex if needed). 3329 */ 3330static 3331enum check_type 3332check_Mach_O( 3333struct ofile *ofile) 3334{ 3335#ifdef OTOOL 3336 return(CHECK_GOOD); 3337#else /* !defined OTOOL */ 3338 uint32_t size, i, j, ncmds, sizeofcmds, load_command_multiple, sizeofhdrs; 3339 cpu_type_t cputype; 3340 char *addr, *cmd_name, *element_name; 3341 enum byte_sex host_byte_sex; 3342 enum bool swapped; 3343 struct mach_header *mh; 3344 struct mach_header_64 *mh64; 3345 struct load_command *load_commands, *lc, l; 3346 struct segment_command *sg; 3347 struct segment_command_64 *sg64; 3348 struct section *s; 3349 struct section_64 *s64; 3350 struct symtab_command *st; 3351 struct dysymtab_command *dyst; 3352 struct symseg_command *ss; 3353 struct fvmlib_command *fl; 3354 struct dylib_command *dl; 3355 struct sub_framework_command *sub; 3356 struct sub_umbrella_command *usub; 3357 struct sub_library_command *lsub; 3358 struct sub_client_command *csub; 3359 struct prebound_dylib_command *pbdylib; 3360 struct dylinker_command *dyld; 3361 struct thread_command *ut; 3362 struct ident_command *id; 3363 struct routines_command *rc; 3364 struct routines_command_64 *rc64; 3365 struct twolevel_hints_command *hints; 3366 struct linkedit_data_command *code_sig, *split_info, *func_starts, 3367 *data_in_code, *code_sign_drs, *linkedit_data; 3368 struct version_min_command *vers; 3369 struct prebind_cksum_command *cs; 3370 struct encryption_info_command *encrypt_info; 3371 struct encryption_info_command_64 *encrypt_info64; 3372 struct linker_option_command *lo; 3373 struct dyld_info_command *dyld_info; 3374 struct uuid_command *uuid; 3375 struct rpath_command *rpath; 3376 struct entry_point_command *ep; 3377 struct source_version_command *sv; 3378 uint32_t flavor, count, nflavor; 3379 char *p, *state; 3380 uint32_t sizeof_nlist, sizeof_dylib_module; 3381 char *struct_dylib_module_name, *struct_nlist_name; 3382 uint64_t big_size, big_end, big_load_end; 3383 struct element elements; 3384 3385 elements.offset = 0; 3386 elements.size = 0; 3387 elements.name = NULL; 3388 elements.next = NULL; 3389 3390 addr = ofile->object_addr; 3391 size = ofile->object_size; 3392 mh = ofile->mh; 3393 mh64 = ofile->mh64; 3394 load_commands = ofile->load_commands; 3395 host_byte_sex = get_host_byte_sex(); 3396 swapped = (enum bool)(host_byte_sex != ofile->object_byte_sex); 3397 3398 if(ofile->mh != NULL){ 3399 if(swapped) 3400 swap_mach_header(mh, host_byte_sex); 3401 big_size = mh->sizeofcmds; 3402 big_size += sizeof(struct mach_header); 3403 if(big_size > size){ 3404 Mach_O_error(ofile, "truncated or malformed object (load " 3405 "commands extend past the end of the file)"); 3406 return(CHECK_BAD); 3407 } 3408 sizeofhdrs = big_size; 3409 ofile->mh_cputype = mh->cputype; 3410 ofile->mh_cpusubtype = mh->cpusubtype; 3411 ofile->mh_filetype = mh->filetype; 3412 ncmds = mh->ncmds; 3413 sizeofcmds = mh->sizeofcmds; 3414 cputype = mh->cputype; 3415 load_command_multiple = 4; 3416 sizeof_nlist = sizeof(struct nlist); 3417 struct_nlist_name = "struct nlist"; 3418 sizeof_dylib_module = sizeof(struct dylib_module); 3419 struct_dylib_module_name = "struct dylib_module"; 3420 } 3421 else{ 3422 if(swapped) 3423 swap_mach_header_64(mh64, host_byte_sex); 3424 big_size = mh64->sizeofcmds; 3425 big_size += sizeof(struct mach_header_64); 3426 if(big_size > size){ 3427 Mach_O_error(ofile, "truncated or malformed object (load " 3428 "commands extend past the end of the file)"); 3429 return(CHECK_BAD); 3430 } 3431 sizeofhdrs = big_size; 3432 ofile->mh_cputype = mh64->cputype; 3433 ofile->mh_cpusubtype = mh64->cpusubtype; 3434 ofile->mh_filetype = mh64->filetype; 3435 ncmds = mh64->ncmds; 3436 sizeofcmds = mh64->sizeofcmds; 3437 cputype = mh64->cputype; 3438 load_command_multiple = 8; 3439 sizeof_nlist = sizeof(struct nlist_64); 3440 struct_nlist_name = "struct nlist_64"; 3441 sizeof_dylib_module = sizeof(struct dylib_module_64); 3442 struct_dylib_module_name = "struct dylib_module_64"; 3443 } 3444 if(check_overlaping_element(ofile, &elements, 0, sizeofhdrs, 3445 "Mach-O headers") == CHECK_BAD) 3446 goto return_bad; 3447 if(ofile->file_type == OFILE_FAT){ 3448 if(ofile->fat_archs[ofile->narch].cputype != ofile->mh_cputype){ 3449 Mach_O_error(ofile, "malformed fat file (fat header " 3450 "architecture: %u's cputype does not match " 3451 "object file's mach header)", ofile->narch); 3452 goto return_bad; 3453 } 3454 } 3455 /* 3456 * Make a pass through the load commands checking them to the level 3457 * that they can be parsed and all fields with offsets and sizes do 3458 * not extend past the end of the file. 3459 */ 3460 st = NULL; 3461 dyst = NULL; 3462 rc = NULL; 3463 rc64 = NULL; 3464 hints = NULL; 3465 code_sig = NULL; 3466 func_starts = NULL; 3467 data_in_code = NULL; 3468 code_sign_drs = NULL; 3469 split_info = NULL; 3470 cs = NULL; 3471 uuid = NULL; 3472 encrypt_info = NULL; 3473 dyld_info = NULL; 3474 vers = NULL; 3475 big_load_end = 0; 3476 for(i = 0, lc = load_commands; i < ncmds; i++){ 3477 l = *lc; 3478 if(swapped) 3479 swap_load_command(&l, host_byte_sex); 3480 /* 3481 * Check load command size for a multiple of load_command_multiple. 3482 */ 3483 if(l.cmdsize % load_command_multiple != 0){ 3484 /* 3485 * We have a hack here to allow 64-bit Mach-O core files to 3486 * have LC_THREAD commands that are only a multiple of 4 and 3487 * not 8 to be allowed since the kernel produces them. 3488 */ 3489 if(ofile->mh64 == NULL || 3490 ofile->mh64->filetype != MH_CORE || 3491 l.cmd != LC_THREAD || 3492 l.cmdsize % 4 != 0){ 3493 Mach_O_error(ofile, "malformed object (load command %u " 3494 "cmdsize not a multiple of %u)", i, 3495 load_command_multiple); 3496 goto return_bad; 3497 } 3498 } 3499 /* check that load command does not extends past end of commands */ 3500 big_load_end += l.cmdsize; 3501 if(big_load_end > sizeofcmds){ 3502 Mach_O_error(ofile, "truncated or malformed object (load " 3503 "command %u extends past the end of the file)",i); 3504 goto return_bad; 3505 } 3506 /* check that the load command size is not zero */ 3507 if(l.cmdsize == 0){ 3508 Mach_O_error(ofile, "malformed object (load command %u cmdsize" 3509 " is zero)", i); 3510 goto return_bad; 3511 } 3512 switch(l.cmd){ 3513 case LC_SEGMENT: 3514 if(l.cmdsize < sizeof(struct segment_command)){ 3515 Mach_O_error(ofile, "malformed object (LC_SEGMENT cmdsize " 3516 "too small) in command %u", i); 3517 goto return_bad; 3518 } 3519 sg = (struct segment_command *)lc; 3520 if(swapped) 3521 swap_segment_command(sg, host_byte_sex); 3522 big_size = sg->nsects; 3523 big_size *= sizeof(struct section); 3524 big_size += sizeof(struct segment_command); 3525 if(sg->cmdsize != big_size){ 3526 Mach_O_error(ofile, "malformed object (inconsistent " 3527 "cmdsize in LC_SEGMENT command %u for the " 3528 "number of sections)", i); 3529 goto return_bad; 3530 } 3531 if(sg->fileoff > size){ 3532 Mach_O_error(ofile, "truncated or malformed object (" 3533 "LC_SEGMENT command %u fileoff field " 3534 "extends past the end of the file)", i); 3535 goto return_bad; 3536 } 3537 big_size = sg->fileoff; 3538 big_size += sg->filesize; 3539 if(big_size > size){ 3540 Mach_O_error(ofile, "truncated or malformed object (" 3541 "LC_SEGMENT command %u fileoff field " 3542 "plus filesize field extends past the end of " 3543 "the file)", i); 3544 goto return_bad; 3545 } 3546 if(sg->vmsize != 0 && sg->filesize > sg->vmsize){ 3547 Mach_O_error(ofile, "malformed object (LC_SEGMENT command " 3548 "%u filesize field greater than vmsize field)", 3549 i); 3550 goto return_bad; 3551 } 3552 s = (struct section *) 3553 ((char *)sg + sizeof(struct segment_command)); 3554 if(swapped) 3555 swap_section(s, sg->nsects, host_byte_sex); 3556 for(j = 0 ; j < sg->nsects ; j++){ 3557 if(mh->filetype != MH_DYLIB_STUB && 3558 s->flags != S_ZEROFILL && 3559 s->flags != S_THREAD_LOCAL_ZEROFILL && s->offset > size){ 3560 Mach_O_error(ofile, "truncated or malformed object " 3561 "(offset field of section %u in LC_SEGMENT " 3562 "command %u extends past the end of the file)", 3563 j, i); 3564 goto return_bad; 3565 } 3566 if(mh->filetype != MH_DYLIB_STUB && 3567 s->flags != S_ZEROFILL && 3568 s->flags != S_THREAD_LOCAL_ZEROFILL && 3569 sg->fileoff == 0 && s->offset < sizeofhdrs && 3570 s->size != 0){ 3571 Mach_O_error(ofile, "malformed object (offset field of " 3572 "section %u in LC_SEGMENT command %u not " 3573 "past the headers of the file)", j, i); 3574 goto return_bad; 3575 } 3576 big_size = s->offset; 3577 big_size += s->size; 3578 if(mh->filetype != MH_DYLIB_STUB && 3579 s->flags != S_ZEROFILL && 3580 s->flags != S_THREAD_LOCAL_ZEROFILL && big_size > size){ 3581 Mach_O_error(ofile, "truncated or malformed object " 3582 "(offset field plus size field of section %u " 3583 "in LC_SEGMENT command %u extends " 3584 "past the end of the file)", j, i); 3585 goto return_bad; 3586 } 3587 if(mh->filetype != MH_DYLIB_STUB && 3588 s->flags != S_ZEROFILL && 3589 s->flags != S_THREAD_LOCAL_ZEROFILL && 3590 s->size > sg->filesize){ 3591 Mach_O_error(ofile, "malformed object (size field of " 3592 "section %u in LC_SEGMENT command %u greater " 3593 "than the segment)", j, i); 3594 goto return_bad; 3595 } 3596 if(mh->filetype != MH_DYLIB_STUB && 3597 s->size != 0 && s->addr < sg->vmaddr){ 3598 Mach_O_error(ofile, "malformed object (addr field of " 3599 "section %u in LC_SEGMENT command %u less than " 3600 "the segment's vmaddr)", j, i); 3601 goto return_bad; 3602 } 3603 big_size = s->addr; 3604 big_size += s->size; 3605 big_end = sg->vmaddr; 3606 big_end += sg->vmsize; 3607 if(sg->vmsize != 0 && s->size != 0 && big_size > big_end){ 3608 Mach_O_error(ofile, "malformed object (addr field plus " 3609 "size of section %u in LC_SEGMENT command %u " 3610 "greater than than the segment's vmaddr plus " 3611 "vmsize)", j, i); 3612 goto return_bad; 3613 } 3614 if(mh->filetype != MH_DYLIB_STUB && 3615 mh->filetype != MH_DSYM && 3616 s->flags != S_ZEROFILL && 3617 s->flags != S_THREAD_LOCAL_ZEROFILL && 3618 check_overlaping_element(ofile, &elements, s->offset, 3619 s->size, "section contents") == CHECK_BAD) 3620 goto return_bad; 3621 if(s->reloff > size){ 3622 Mach_O_error(ofile, "truncated or malformed object " 3623 "(reloff field of section %u in LC_SEGMENT " 3624 "command %u extends past the end of the file)", 3625 j, i); 3626 goto return_bad; 3627 } 3628 big_size = s->nreloc; 3629 big_size *= sizeof(struct relocation_info); 3630 big_size += s->reloff; 3631 if(big_size > size){ 3632 Mach_O_error(ofile, "truncated or malformed object " 3633 "(reloff field plus nreloc field times sizeof(" 3634 "struct relocation_info) of section %u in " 3635 "LC_SEGMENT command %u extends past the " 3636 "end of the file)", j, i); 3637 goto return_bad; 3638 } 3639 if(check_overlaping_element(ofile, &elements, s->reloff, 3640 s->nreloc * sizeof(struct relocation_info), 3641 "section relocation entries") == CHECK_BAD) 3642 goto return_bad; 3643 s++; 3644 } 3645 break; 3646 3647 case LC_SEGMENT_64: 3648 if(l.cmdsize < sizeof(struct segment_command_64)){ 3649 Mach_O_error(ofile, "malformed object (LC_SEGMENT_64 " 3650 "cmdsize too small) in command %u", i); 3651 goto return_bad; 3652 } 3653 sg64 = (struct segment_command_64 *)lc; 3654 if(swapped) 3655 swap_segment_command_64(sg64, host_byte_sex); 3656 big_size = sg64->nsects; 3657 big_size *= sizeof(struct section_64); 3658 big_size += sizeof(struct segment_command_64); 3659 if(sg64->cmdsize != big_size){ 3660 Mach_O_error(ofile, "malformed object (inconsistent " 3661 "cmdsize in LC_SEGMENT_64 command %u for " 3662 "the number of sections)", i); 3663 goto return_bad; 3664 } 3665 if(sg64->fileoff > size){ 3666 Mach_O_error(ofile, "truncated or malformed object (" 3667 "LC_SEGMENT_64 command %u fileoff field " 3668 "extends past the end of the file)", i); 3669 goto return_bad; 3670 } 3671 big_size = sg64->fileoff; 3672 big_size += sg64->filesize; 3673 if(big_size > size){ 3674 Mach_O_error(ofile, "truncated or malformed object (" 3675 "LC_SEGMENT_64 command %u fileoff field " 3676 "plus filesize field extends past the end of " 3677 "the file)", i); 3678 goto return_bad; 3679 } 3680 s64 = (struct section_64 *) 3681 ((char *)sg64 + sizeof(struct segment_command_64)); 3682 if(swapped) 3683 swap_section_64(s64, sg64->nsects, host_byte_sex); 3684 for(j = 0 ; j < sg64->nsects ; j++){ 3685 if(mh64->filetype != MH_DYLIB_STUB && 3686 s64->flags != S_ZEROFILL && 3687 s64->flags != S_THREAD_LOCAL_ZEROFILL && 3688 s64->offset > size){ 3689 Mach_O_error(ofile, "truncated or malformed object " 3690 "(offset field of section %u in LC_SEGMENT_64 " 3691 "command %u extends past the end of the file)", 3692 j, i); 3693 goto return_bad; 3694 } 3695 big_size = s64->offset; 3696 big_size += s64->size; 3697 if(mh64->filetype != MH_DYLIB_STUB && 3698 s64->flags != S_ZEROFILL && 3699 s64->flags != S_THREAD_LOCAL_ZEROFILL && 3700 big_size > size){ 3701 Mach_O_error(ofile, "truncated or malformed object " 3702 "(offset field plus size field of section %u " 3703 "in LC_SEGMENT_64 command %u extends " 3704 "past the end of the file)", j, i); 3705 goto return_bad; 3706 } 3707 if(mh64->filetype != MH_DYLIB_STUB && 3708 mh64->filetype != MH_DSYM && 3709 s64->flags != S_ZEROFILL && 3710 s64->flags != S_THREAD_LOCAL_ZEROFILL && 3711 check_overlaping_element(ofile, &elements, s64->offset, 3712 s64->size, "section contents") == CHECK_BAD) 3713 goto return_bad; 3714 if(s64->reloff > size){ 3715 Mach_O_error(ofile, "truncated or malformed object " 3716 "(reloff field of section %u in LC_SEGMENT_64 " 3717 "command %u extends past the end of the file)", 3718 j, i); 3719 goto return_bad; 3720 } 3721 big_size = s64->nreloc; 3722 big_size *= sizeof(struct relocation_info); 3723 big_size += s64->reloff; 3724 if(big_size > size){ 3725 Mach_O_error(ofile, "truncated or malformed object " 3726 "(reloff field plus nreloc field times sizeof(" 3727 "struct relocation_info) of section %u in " 3728 "LC_SEGMENT_64 command %u extends past the " 3729 "end of the file)", j, i); 3730 goto return_bad; 3731 } 3732 if(check_overlaping_element(ofile, &elements, s64->reloff, 3733 s64->nreloc * sizeof(struct relocation_info), 3734 "section relocation entries") == CHECK_BAD) 3735 goto return_bad; 3736 s64++; 3737 } 3738 break; 3739 3740 case LC_SYMTAB: 3741 if(l.cmdsize < sizeof(struct symtab_command)){ 3742 Mach_O_error(ofile, "malformed object (LC_SYMTAB cmdsize " 3743 "too small) in command %u", i); 3744 goto return_bad; 3745 } 3746 if(st != NULL){ 3747 Mach_O_error(ofile, "malformed object (more than one " 3748 "LC_SYMTAB command)"); 3749 goto return_bad; 3750 } 3751 st = (struct symtab_command *)lc; 3752 if(swapped) 3753 swap_symtab_command(st, host_byte_sex); 3754 if(st->cmdsize != sizeof(struct symtab_command)){ 3755 Mach_O_error(ofile, "malformed object (LC_SYMTAB command " 3756 "%u has incorrect cmdsize)", i); 3757 goto return_bad; 3758 } 3759 if(st->symoff > size){ 3760 Mach_O_error(ofile, "truncated or malformed object (symoff " 3761 "field of LC_SYMTAB command %u extends past the end " 3762 "of the file)", i); 3763 goto return_bad; 3764 } 3765 big_size = st->nsyms; 3766 big_size *= sizeof_nlist; 3767 big_size += st->symoff; 3768 if(big_size > size){ 3769 Mach_O_error(ofile, "truncated or malformed object (symoff " 3770 "field plus nsyms field times sizeof(%s) of LC_SYMTAB " 3771 "command %u extends past the end of the file)", 3772 struct_nlist_name, i); 3773 goto return_bad; 3774 } 3775 if(check_overlaping_element(ofile, &elements, st->symoff, 3776 st->nsyms * sizeof_nlist, "symbol table") == CHECK_BAD) 3777 goto return_bad; 3778 if(st->stroff > size){ 3779 Mach_O_error(ofile, "truncated or malformed object (stroff " 3780 "field of LC_SYMTAB command %u extends past the end " 3781 "of the file)", i); 3782 goto return_bad; 3783 } 3784 big_size = st->stroff; 3785 big_size += st->strsize; 3786 if(big_size > size){ 3787 Mach_O_error(ofile, "truncated or malformed object (stroff " 3788 "field plus strsize field of LC_SYMTAB command %u " 3789 "extends past the end of the file)", i); 3790 goto return_bad; 3791 } 3792 if(check_overlaping_element(ofile, &elements, st->stroff, 3793 st->strsize, "string table") == CHECK_BAD) 3794 goto return_bad; 3795 break; 3796 3797 case LC_DYSYMTAB: 3798 if(l.cmdsize < sizeof(struct dysymtab_command)){ 3799 Mach_O_error(ofile, "malformed object (LC_DYSYMTAB cmdsize " 3800 "too small) in command %u", i); 3801 goto return_bad; 3802 } 3803 if(dyst != NULL){ 3804 Mach_O_error(ofile, "malformed object (more than one " 3805 "LC_DYSYMTAB command)"); 3806 goto return_bad; 3807 } 3808 dyst = (struct dysymtab_command *)lc; 3809 if(swapped) 3810 swap_dysymtab_command(dyst, host_byte_sex); 3811 if(dyst->cmdsize != sizeof(struct dysymtab_command)){ 3812 Mach_O_error(ofile, "malformed object (LC_DYSYMTAB command " 3813 "%u has incorrect cmdsize)", i); 3814 goto return_bad; 3815 } 3816 if(dyst->tocoff > size){ 3817 Mach_O_error(ofile, "truncated or malformed object (tocoff " 3818 "field of LC_DYSYMTAB command %u extends past the end " 3819 "of the file)", i); 3820 goto return_bad; 3821 } 3822 big_size = dyst->ntoc; 3823 big_size *= sizeof(struct dylib_table_of_contents); 3824 big_size += dyst->tocoff; 3825 if(big_size > size){ 3826 Mach_O_error(ofile, "truncated or malformed object (tocoff " 3827 "field plus ntoc field times sizeof(struct dylib_table" 3828 "_of_contents) of LC_DYSYMTAB command %u extends past " 3829 "the end of the file)", i); 3830 goto return_bad; 3831 } 3832 if(check_overlaping_element(ofile, &elements, dyst->tocoff, 3833 dyst->ntoc * sizeof(struct dylib_table_of_contents), 3834 "table of contents") == CHECK_BAD) 3835 goto return_bad; 3836 if(dyst->modtaboff > size){ 3837 Mach_O_error(ofile, "truncated or malformed object " 3838 "(modtaboff field of LC_DYSYMTAB command %u extends " 3839 "past the end of the file)", i); 3840 goto return_bad; 3841 } 3842 big_size = dyst->nmodtab; 3843 big_size *= sizeof_dylib_module; 3844 big_size += dyst->modtaboff; 3845 if(big_size > size){ 3846 Mach_O_error(ofile, "truncated or malformed object " 3847 "(modtaboff field plus nmodtab field times sizeof(%s) " 3848 "of LC_DYSYMTAB command %u extends past the end of " 3849 "the file)", struct_dylib_module_name, i); 3850 goto return_bad; 3851 } 3852 if(check_overlaping_element(ofile, &elements, dyst->modtaboff, 3853 dyst->nmodtab * sizeof_dylib_module, "module table") == 3854 CHECK_BAD) 3855 goto return_bad; 3856 if(dyst->extrefsymoff > size){ 3857 Mach_O_error(ofile, "truncated or malformed object " 3858 "(extrefsymoff field of LC_DYSYMTAB command %u " 3859 "extends past the end of the file)", i); 3860 goto return_bad; 3861 } 3862 big_size = dyst->nextrefsyms; 3863 big_size *= sizeof(struct dylib_reference); 3864 big_size += dyst->extrefsymoff; 3865 if(big_size > size){ 3866 Mach_O_error(ofile, "truncated or malformed object " 3867 "(extrefsymoff field plus nextrefsyms field times " 3868 "sizeof(struct dylib_reference) of LC_DYSYMTAB command " 3869 "%u extends past the end of the file)", i); 3870 goto return_bad; 3871 } 3872 if(check_overlaping_element(ofile, &elements,dyst->extrefsymoff, 3873 dyst->nextrefsyms * sizeof(struct dylib_reference), 3874 "reference table") == CHECK_BAD) 3875 goto return_bad; 3876 if(dyst->indirectsymoff > size){ 3877 Mach_O_error(ofile, "truncated or malformed object " 3878 "(indirectsymoff field of LC_DYSYMTAB command %u " 3879 "extends past the end of the file)", i); 3880 goto return_bad; 3881 } 3882 big_size = dyst->nindirectsyms; 3883 big_size *= sizeof(uint32_t); 3884 big_size += dyst->indirectsymoff; 3885 if(big_size > size){ 3886 Mach_O_error(ofile, "truncated or malformed object " 3887 "(indirectsymoff field plus nindirectsyms field times " 3888 "sizeof(uint32_t) of LC_DYSYMTAB command " 3889 "%u extends past the end of the file)", i); 3890 goto return_bad; 3891 } 3892 if(check_overlaping_element(ofile, &elements, 3893 dyst->indirectsymoff, dyst->nindirectsyms * 3894 sizeof(uint32_t), "indirect table") == CHECK_BAD) 3895 goto return_bad; 3896 if(dyst->extreloff > size){ 3897 Mach_O_error(ofile, "truncated or malformed object " 3898 "(extreloff field of LC_DYSYMTAB command %u " 3899 "extends past the end of the file)", i); 3900 goto return_bad; 3901 } 3902 big_size = dyst->nextrel; 3903 big_size *= sizeof(struct relocation_info); 3904 big_size += dyst->extreloff; 3905 if(big_size > size){ 3906 Mach_O_error(ofile, "truncated or malformed object " 3907 "(extreloff field plus nextrel field times " 3908 "sizeof(struct relocation_info) of LC_DYSYMTAB command " 3909 "%u extends past the end of the file)", i); 3910 goto return_bad; 3911 } 3912 if(check_overlaping_element(ofile, &elements, dyst->extreloff, 3913 dyst->nextrel * sizeof(struct relocation_info), 3914 "external relocation table") == CHECK_BAD) 3915 goto return_bad; 3916 if(dyst->locreloff > size){ 3917 Mach_O_error(ofile, "truncated or malformed object " 3918 "(locreloff field of LC_DYSYMTAB command %u " 3919 "extends past the end of the file)", i); 3920 goto return_bad; 3921 } 3922 big_size = dyst->nlocrel; 3923 big_size *= sizeof(struct relocation_info); 3924 big_size += dyst->locreloff; 3925 if(big_size > size){ 3926 Mach_O_error(ofile, "truncated or malformed object " 3927 "(locreloff field plus nlocrel field times " 3928 "sizeof(struct relocation_info) of LC_DYSYMTAB command " 3929 "%u extends past the end of the file)", i); 3930 goto return_bad; 3931 } 3932 if(check_overlaping_element(ofile, &elements, dyst->locreloff, 3933 dyst->nlocrel * sizeof(struct relocation_info), 3934 "local relocation table") == CHECK_BAD) 3935 goto return_bad; 3936 break; 3937 3938 case LC_ROUTINES: 3939 if(l.cmdsize < sizeof(struct routines_command)){ 3940 Mach_O_error(ofile, "malformed object (LC_ROUTINES cmdsize " 3941 "too small) in command %u", i); 3942 goto return_bad; 3943 } 3944 if(rc != NULL){ 3945 Mach_O_error(ofile, "malformed object (more than one " 3946 "LC_ROUTINES command)"); 3947 goto return_bad; 3948 } 3949 rc = (struct routines_command *)lc; 3950 if(swapped) 3951 swap_routines_command(rc, host_byte_sex); 3952 if(rc->cmdsize != sizeof(struct routines_command)){ 3953 Mach_O_error(ofile, "malformed object (LC_ROUTINES " 3954 "command %u has incorrect cmdsize)", i); 3955 goto return_bad; 3956 } 3957 break; 3958 3959 case LC_ROUTINES_64: 3960 if(l.cmdsize < sizeof(struct routines_command_64)){ 3961 Mach_O_error(ofile, "malformed object (LC_ROUTINES_64 " 3962 "cmdsize too small) in command %u", i); 3963 goto return_bad; 3964 } 3965 if(rc64 != NULL){ 3966 Mach_O_error(ofile, "malformed object (more than one " 3967 "LC_ROUTINES_64 command)"); 3968 goto return_bad; 3969 } 3970 rc64 = (struct routines_command_64 *)lc; 3971 if(swapped) 3972 swap_routines_command_64(rc64, host_byte_sex); 3973 if(rc64->cmdsize != sizeof(struct routines_command_64)){ 3974 Mach_O_error(ofile, "malformed object (LC_ROUTINES_64 " 3975 "command %u has incorrect cmdsize)", i); 3976 goto return_bad; 3977 } 3978 break; 3979 3980 case LC_TWOLEVEL_HINTS: 3981 if(l.cmdsize < sizeof(struct twolevel_hints_command)){ 3982 Mach_O_error(ofile, "malformed object (LC_TWOLEVEL_HINTS " 3983 "cmdsize too small) in command %u", i); 3984 goto return_bad; 3985 } 3986 if(hints != NULL){ 3987 Mach_O_error(ofile, "malformed object (more than one " 3988 "LC_TWOLEVEL_HINTS command)"); 3989 goto return_bad; 3990 } 3991 hints = (struct twolevel_hints_command *)lc; 3992 if(swapped) 3993 swap_twolevel_hints_command(hints, host_byte_sex); 3994 if(hints->cmdsize != sizeof(struct twolevel_hints_command)){ 3995 Mach_O_error(ofile, "malformed object (LC_TWOLEVEL_HINTS " 3996 "command %u has incorrect cmdsize)", i); 3997 goto return_bad; 3998 } 3999 if(hints->offset > size){ 4000 Mach_O_error(ofile, "truncated or malformed object " 4001 "(offset field of LC_TWOLEVEL_HINTS command %u " 4002 "extends past the end of the file)", i); 4003 goto return_bad; 4004 } 4005 big_size = hints->nhints; 4006 big_size *= sizeof(struct twolevel_hint); 4007 big_size += hints->offset; 4008 if(big_size > size){ 4009 Mach_O_error(ofile, "truncated or malformed object " 4010 "(offset field plus nhints field times " 4011 "sizeof(struct twolevel_hint) of LC_TWOLEVEL_HINTS " 4012 " command %u extends past the end of the file)", i); 4013 goto return_bad; 4014 } 4015 if(check_overlaping_element(ofile, &elements, hints->offset, 4016 hints->nhints * sizeof(struct twolevel_hint), 4017 "two level hints") == CHECK_BAD) 4018 goto return_bad; 4019 break; 4020 4021 case LC_SEGMENT_SPLIT_INFO: 4022 cmd_name = "LC_SEGMENT_SPLIT_INFO"; 4023 element_name = "split info data"; 4024 if(split_info != NULL){ 4025 Mach_O_error(ofile, "malformed object (more than one " 4026 "%s command)", cmd_name); 4027 goto return_bad; 4028 } 4029 split_info = (struct linkedit_data_command *)lc; 4030 goto check_linkedit_data_command; 4031 4032 case LC_CODE_SIGNATURE: 4033 cmd_name = "LC_CODE_SIGNATURE"; 4034 element_name = "code signature data"; 4035 if(code_sig != NULL){ 4036 Mach_O_error(ofile, "malformed object (more than one " 4037 "%s command)", cmd_name); 4038 goto return_bad; 4039 } 4040 code_sig = (struct linkedit_data_command *)lc; 4041 goto check_linkedit_data_command; 4042 4043 case LC_FUNCTION_STARTS: 4044 cmd_name = "LC_FUNCTION_STARTS"; 4045 element_name = "function starts data"; 4046 if(func_starts != NULL){ 4047 Mach_O_error(ofile, "malformed object (more than one " 4048 "%s command)", cmd_name); 4049 goto return_bad; 4050 } 4051 func_starts = (struct linkedit_data_command *)lc; 4052 goto check_linkedit_data_command; 4053 4054 case LC_DATA_IN_CODE: 4055 cmd_name = "LC_DATA_IN_CODE"; 4056 element_name = "date in code info"; 4057 if(data_in_code != NULL){ 4058 Mach_O_error(ofile, "malformed object (more than one " 4059 "%s command)", cmd_name); 4060 goto return_bad; 4061 } 4062 data_in_code = (struct linkedit_data_command *)lc; 4063 goto check_linkedit_data_command; 4064 4065 case LC_DYLIB_CODE_SIGN_DRS: 4066 cmd_name = "LC_DYLIB_CODE_SIGN_DRS"; 4067 element_name = "code signing RDs data"; 4068 if(code_sign_drs != NULL){ 4069 Mach_O_error(ofile, "malformed object (more than one " 4070 "%s command)", cmd_name); 4071 goto return_bad; 4072 } 4073 code_sign_drs = (struct linkedit_data_command *)lc; 4074 goto check_linkedit_data_command; 4075 4076check_linkedit_data_command: 4077 if(l.cmdsize < sizeof(struct linkedit_data_command)){ 4078 Mach_O_error(ofile, "malformed object (%s cmdsize too " 4079 "small) in command %u", cmd_name, i); 4080 goto return_bad; 4081 } 4082 linkedit_data = (struct linkedit_data_command *)lc; 4083 if(swapped) 4084 swap_linkedit_data_command(linkedit_data, host_byte_sex); 4085 if(linkedit_data->cmdsize != 4086 sizeof(struct linkedit_data_command)){ 4087 Mach_O_error(ofile, "malformed object (%s command %u has " 4088 "incorrect cmdsize)", cmd_name, i); 4089 goto return_bad; 4090 } 4091 if(linkedit_data->dataoff > size){ 4092 Mach_O_error(ofile, "truncated or malformed object " 4093 "(dataoff field of %s command %u extends past the end " 4094 "of the file)", cmd_name, i); 4095 goto return_bad; 4096 } 4097 big_size = linkedit_data->dataoff; 4098 big_size += linkedit_data->datasize; 4099 if(big_size > size){ 4100 Mach_O_error(ofile, "truncated or malformed object " 4101 "(dataoff field plus datasize field of " 4102 "%s command %u extends past the end of " 4103 "the file)", cmd_name, i); 4104 goto return_bad; 4105 } 4106 if(check_overlaping_element(ofile, &elements, 4107 linkedit_data->dataoff, linkedit_data->datasize, 4108 element_name) == CHECK_BAD) 4109 goto return_bad; 4110 break; 4111 4112 case LC_VERSION_MIN_MACOSX: 4113 if(l.cmdsize < sizeof(struct version_min_command)){ 4114 Mach_O_error(ofile, "malformed object (LC_VERSION_MIN_" 4115 "MACOSX cmdsize too small) in command %u", i); 4116 goto return_bad; 4117 } 4118 if(vers != NULL){ 4119 Mach_O_error(ofile, "malformed object (more than one " 4120 "LC_VERSION_MIN_IPHONEOS or LC_VERSION_MIN_MACOSX " 4121 "command)"); 4122 goto return_bad; 4123 } 4124 vers = (struct version_min_command *)lc; 4125 if(swapped) 4126 swap_version_min_command(vers, host_byte_sex); 4127 if(vers->cmdsize < sizeof(struct version_min_command)){ 4128 Mach_O_error(ofile, "malformed object (LC_VERSION_MIN_" 4129 "MACOSX command %u has too small cmdsize field)", i); 4130 goto return_bad; 4131 } 4132 break; 4133 4134 case LC_VERSION_MIN_IPHONEOS: 4135 if(l.cmdsize < sizeof(struct version_min_command)){ 4136 Mach_O_error(ofile, "malformed object (LC_VERSION_MIN_" 4137 "IPHONEOS cmdsize too small) in command %u",i); 4138 goto return_bad; 4139 } 4140 if(vers != NULL){ 4141 Mach_O_error(ofile, "malformed object (more than one " 4142 "LC_VERSION_MIN_IPHONEOS or LC_VERSION_MIN_MACOSX " 4143 "command)"); 4144 goto return_bad; 4145 } 4146 vers = (struct version_min_command *)lc; 4147 if(swapped) 4148 swap_version_min_command(vers, host_byte_sex); 4149 if(vers->cmdsize < sizeof(struct version_min_command)){ 4150 Mach_O_error(ofile, "malformed object (LC_VERSION_MIN_" 4151 "IPHONEOS command %u has too small cmdsize field)", i); 4152 goto return_bad; 4153 } 4154 break; 4155 4156 case LC_ENCRYPTION_INFO: 4157 if(l.cmdsize < sizeof(struct encryption_info_command)){ 4158 Mach_O_error(ofile, "malformed object (LC_ENCRYPTION_INFO " 4159 "cmdsize too small) in command %u", i); 4160 goto return_bad; 4161 } 4162 encrypt_info = (struct encryption_info_command *)lc; 4163 if(swapped) 4164 swap_encryption_command(encrypt_info, host_byte_sex); 4165 if(encrypt_info->cmdsize != 4166 sizeof(struct encryption_info_command)){ 4167 Mach_O_error(ofile, "malformed object (LC_ENCRYPTION_INFO" 4168 "command %u has incorrect cmdsize)", i); 4169 goto return_bad; 4170 } 4171 if(encrypt_info->cryptoff > size){ 4172 Mach_O_error(ofile, "truncated or malformed object (cryptoff " 4173 "field of LC_ENCRYPTION_INFO command %u extends " 4174 "past the end of the file)", i); 4175 goto return_bad; 4176 } 4177 big_size = encrypt_info->cryptoff; 4178 big_size += encrypt_info->cryptsize; 4179 if(big_size > size){ 4180 Mach_O_error(ofile, "truncated or malformed object " 4181 "(cryptoff field plus cryptsize field of " 4182 "LC_ENCRYPTION_INFO command %u extends past " 4183 "the end of the file)", i); 4184 goto return_bad; 4185 } 4186 break; 4187 4188 case LC_ENCRYPTION_INFO_64: 4189 if(l.cmdsize < sizeof(struct encryption_info_command_64)){ 4190 Mach_O_error(ofile, "malformed object (LC_ENCRYPTION_INFO" 4191 "_64 cmdsize too small) in command %u", i); 4192 goto return_bad; 4193 } 4194 encrypt_info64 = (struct encryption_info_command_64 *)lc; 4195 if(swapped) 4196 swap_encryption_command_64(encrypt_info64, host_byte_sex); 4197 if(encrypt_info64->cmdsize != 4198 sizeof(struct encryption_info_command_64)){ 4199 Mach_O_error(ofile, "malformed object (LC_ENCRYPTION_INFO" 4200 "_64 command %u has incorrect cmdsize)", i); 4201 goto return_bad; 4202 } 4203 if(encrypt_info64->cryptoff > size){ 4204 Mach_O_error(ofile, "truncated or malformed object (cryptoff " 4205 "field of LC_ENCRYPTION_INFO_64 command %u extends" 4206 " past the end of the file)", i); 4207 goto return_bad; 4208 } 4209 big_size = encrypt_info64->cryptoff; 4210 big_size += encrypt_info64->cryptsize; 4211 if(big_size > size){ 4212 Mach_O_error(ofile, "truncated or malformed object " 4213 "(cryptoff field plus cryptsize field of " 4214 "LC_ENCRYPTION_INFO_64 command %u extends past" 4215 " the end of the file)", i); 4216 goto return_bad; 4217 } 4218 break; 4219 4220 case LC_LINKER_OPTION: 4221 if(l.cmdsize < sizeof(struct linker_option_command)){ 4222 Mach_O_error(ofile, "malformed object (LC_LINKER_OPTION " 4223 "cmdsize too small) in command %u", i); 4224 goto return_bad; 4225 } 4226 lo = (struct linker_option_command *)lc; 4227 if(swapped) 4228 swap_linker_option_command(lo, host_byte_sex); 4229 if(lo->cmdsize < 4230 sizeof(struct linker_option_command)){ 4231 Mach_O_error(ofile, "malformed object (LC_LINKER_OPTION " 4232 " command %u cmdsize too small)", i); 4233 goto return_bad; 4234 } 4235 break; 4236 4237 case LC_DYLD_INFO: 4238 case LC_DYLD_INFO_ONLY: 4239 if(l.cmdsize < sizeof(struct dyld_info_command)){ 4240 Mach_O_error(ofile, "malformed object (%s cmdsize " 4241 "too small) in command %u", l.cmd == 4242 LC_DYLD_INFO ? "LC_DYLD_INFO" : 4243 "LC_DYLD_INFO_ONLY", i); 4244 goto return_bad; 4245 } 4246 dyld_info = (struct dyld_info_command *)lc; 4247 if(swapped) 4248 swap_dyld_info_command(dyld_info, host_byte_sex); 4249 if(dyld_info->cmdsize != 4250 sizeof(struct dyld_info_command)){ 4251 Mach_O_error(ofile, "malformed object (LC_DYLD_INFO" 4252 "command %u has incorrect cmdsize)", i); 4253 goto return_bad; 4254 } 4255 if(dyld_info->rebase_off != 0 && dyld_info->rebase_off > size){ 4256 Mach_O_error(ofile, "truncated or malformed object " 4257 "(rebase_off field of LC_DYLD_INFO command %u " 4258 "extends past the end of the file)", i); 4259 goto return_bad; 4260 } 4261 if(dyld_info->rebase_off != 0){ 4262 big_size = dyld_info->rebase_off; 4263 big_size += dyld_info->rebase_size; 4264 if(big_size > size){ 4265 Mach_O_error(ofile, "truncated or malformed object " 4266 "(rebase_off plus rebase_size of LC_DYLD_INFO " 4267 "command %u extends past the end of the file)", i); 4268 goto return_bad; 4269 } 4270 } 4271 if(check_overlaping_element(ofile, &elements, 4272 dyld_info->rebase_off, dyld_info->rebase_size, 4273 "dyld rebase info") == CHECK_BAD) 4274 goto return_bad; 4275 if(dyld_info->bind_off != 0 && dyld_info->bind_off > size){ 4276 Mach_O_error(ofile, "truncated or malformed object " 4277 "(bind_off field of LC_DYLD_INFO command %u " 4278 "extends past the end of the file)", i); 4279 goto return_bad; 4280 } 4281 if(dyld_info->bind_off != 0){ 4282 big_size = dyld_info->bind_off; 4283 big_size += dyld_info->bind_size; 4284 if(big_size > size){ 4285 Mach_O_error(ofile, "truncated or malformed object " 4286 "(bind_off plus bind_size of LC_DYLD_INFO command " 4287 "%u extends past the end of the file)", i); 4288 goto return_bad; 4289 } 4290 } 4291 if(check_overlaping_element(ofile, &elements, 4292 dyld_info->bind_off, dyld_info->bind_size, 4293 "dyld bind info") == CHECK_BAD) 4294 goto return_bad; 4295 if(dyld_info->weak_bind_off != 0 && 4296 dyld_info->weak_bind_off > size){ 4297 Mach_O_error(ofile, "truncated or malformed object " 4298 "(weak_bind_off field of LC_DYLD_INFO command %u " 4299 "extends past the end of the file)", i); 4300 goto return_bad; 4301 } 4302 if(dyld_info->weak_bind_off != 0){ 4303 big_size = dyld_info->weak_bind_off; 4304 big_size += dyld_info->weak_bind_size; 4305 if(big_size > size){ 4306 Mach_O_error(ofile, "truncated or malformed object " 4307 "(weak_bind_off plus weak_bind_size of LC_DYLD_INFO" 4308 " command %u extends past the end of the file)", i); 4309 goto return_bad; 4310 } 4311 } 4312 if(check_overlaping_element(ofile, &elements, 4313 dyld_info->weak_bind_off, dyld_info->weak_bind_size, 4314 "dyld bind info") == CHECK_BAD) 4315 goto return_bad; 4316 if(dyld_info->lazy_bind_off != 0 && 4317 dyld_info->lazy_bind_off > size){ 4318 Mach_O_error(ofile, "truncated or malformed object " 4319 "(lazy_bind_off field of LC_DYLD_INFO command %u " 4320 "extends past the end of the file)", i); 4321 goto return_bad; 4322 } 4323 if(dyld_info->lazy_bind_off != 0){ 4324 big_size = dyld_info->lazy_bind_off; 4325 big_size += dyld_info->lazy_bind_size; 4326 if(big_size > size){ 4327 Mach_O_error(ofile, "truncated or malformed object " 4328 "(lazy_bind_off plus lazy_bind_size of LC_DYLD_INFO" 4329 " command %u extends past the end of the file)", i); 4330 goto return_bad; 4331 } 4332 } 4333 if(check_overlaping_element(ofile, &elements, 4334 dyld_info->lazy_bind_off, dyld_info->lazy_bind_size, 4335 "dyld lazy bind info") == CHECK_BAD) 4336 goto return_bad; 4337 if(dyld_info->export_off != 0 && dyld_info->export_off > size){ 4338 Mach_O_error(ofile, "truncated or malformed object " 4339 "(export_off field of LC_DYLD_INFO command %u " 4340 "extends past the end of the file)", i); 4341 goto return_bad; 4342 } 4343 if(dyld_info->export_off != 0){ 4344 big_size = dyld_info->export_off; 4345 big_size += dyld_info->export_size; 4346 if(big_size > size){ 4347 Mach_O_error(ofile, "truncated or malformed object " 4348 "(export_off plus export_size of LC_DYLD_INFO " 4349 "command %u extends past the end of the file)", i); 4350 goto return_bad; 4351 } 4352 } 4353 if(check_overlaping_element(ofile, &elements, 4354 dyld_info->export_off, dyld_info->export_size, 4355 "dyld export info") == CHECK_BAD) 4356 goto return_bad; 4357 break; 4358 4359 4360 4361 case LC_PREBIND_CKSUM: 4362 if(l.cmdsize < sizeof(struct prebind_cksum_command)){ 4363 Mach_O_error(ofile, "malformed object (LC_PREBIND_CKSUM " 4364 "cmdsize too small) in command %u", i); 4365 goto return_bad; 4366 } 4367 if(cs != NULL){ 4368 Mach_O_error(ofile, "malformed object (more than one " 4369 "LC_PREBIND_CKSUM command)"); 4370 goto return_bad; 4371 } 4372 cs = (struct prebind_cksum_command *)lc; 4373 if(swapped) 4374 swap_prebind_cksum_command(cs, host_byte_sex); 4375 if(cs->cmdsize != sizeof(struct prebind_cksum_command)){ 4376 Mach_O_error(ofile, "malformed object (LC_PREBIND_CKSUM " 4377 "command %u has incorrect cmdsize)", i); 4378 goto return_bad; 4379 } 4380 break; 4381 4382 case LC_UUID: 4383 if(l.cmdsize < sizeof(struct uuid_command)){ 4384 Mach_O_error(ofile, "malformed object (LC_UUID cmdsize " 4385 "too small) in command %u", i); 4386 goto return_bad; 4387 } 4388 if(uuid != NULL){ 4389 Mach_O_error(ofile, "malformed object (more than one " 4390 "LC_UUID command)"); 4391 goto return_bad; 4392 } 4393 uuid = (struct uuid_command *)lc; 4394 if(swapped) 4395 swap_uuid_command(uuid, host_byte_sex); 4396 if(uuid->cmdsize != sizeof(struct uuid_command)){ 4397 Mach_O_error(ofile, "malformed object (LC_UUID command %u " "has incorrect cmdsize)", i); 4398 goto return_bad; 4399 } 4400 break; 4401 4402 case LC_SYMSEG: 4403 if(l.cmdsize < sizeof(struct symseg_command)){ 4404 Mach_O_error(ofile, "malformed object (LC_SYMSEG cmdsize " 4405 "too small) in command %u", i); 4406 goto return_bad; 4407 } 4408 ss = (struct symseg_command *)lc; 4409 if(swapped) 4410 swap_symseg_command(ss, host_byte_sex); 4411 if(ss->cmdsize != sizeof(struct symseg_command)){ 4412 Mach_O_error(ofile, "malformed object (LC_SYMSEG command " 4413 "%u has incorrect cmdsize)", i); 4414 goto return_bad; 4415 } 4416 if(ss->offset > size){ 4417 Mach_O_error(ofile, "truncated or malformed object (offset " 4418 "field of LC_SYMSEG command %u extends past the end " 4419 "of the file)", i); 4420 goto return_bad; 4421 } 4422 big_size = ss->offset; 4423 big_size += ss->size; 4424 if(big_size > size){ 4425 Mach_O_error(ofile, "truncated or malformed object (offset " 4426 "field plus size field of LC_SYMTAB command %u " 4427 "extends past the end of the file)", i); 4428 goto return_bad; 4429 } 4430 if(check_overlaping_element(ofile, &elements, ss->offset, 4431 ss->size, "symseg info") == CHECK_BAD) 4432 goto return_bad; 4433 break; 4434 4435 case LC_IDFVMLIB: 4436 case LC_LOADFVMLIB: 4437 if(l.cmdsize < sizeof(struct fvmlib_command)){ 4438 Mach_O_error(ofile, "malformed object (%s cmdsize " 4439 "too small) in command %u", l.cmd == 4440 LC_IDFVMLIB ? "LC_IDFVMLIB" : 4441 "LC_LOADFVMLIB", i); 4442 goto return_bad; 4443 } 4444 fl = (struct fvmlib_command *)lc; 4445 if(swapped) 4446 swap_fvmlib_command(fl, host_byte_sex); 4447 if(fl->cmdsize < sizeof(struct fvmlib_command)){ 4448 Mach_O_error(ofile, "malformed object (%s command %u has " 4449 "too small cmdsize field)", fl->cmd == LC_IDFVMLIB ? 4450 "LC_IDFVMLIB" : "LC_LOADFVMLIB", i); 4451 goto return_bad; 4452 } 4453 if(fl->fvmlib.name.offset >= fl->cmdsize){ 4454 Mach_O_error(ofile, "truncated or malformed object (name." 4455 "offset field of %s command %u extends past the end " 4456 "of the file)", fl->cmd == LC_IDFVMLIB ? "LC_IDFVMLIB" 4457 : "LC_LOADFVMLIB", i); 4458 goto return_bad; 4459 } 4460 break; 4461 4462 case LC_ID_DYLIB: 4463 cmd_name = "LC_ID_DYLIB"; 4464 goto check_dylib_command; 4465 case LC_LOAD_DYLIB: 4466 cmd_name = "LC_LOAD_DYLIB"; 4467 goto check_dylib_command; 4468 case LC_LOAD_WEAK_DYLIB: 4469 cmd_name = "LC_LOAD_WEAK_DYLIB"; 4470 goto check_dylib_command; 4471 case LC_REEXPORT_DYLIB: 4472 cmd_name = "LC_REEXPORT_DYLIB"; 4473 goto check_dylib_command; 4474 case LC_LOAD_UPWARD_DYLIB: 4475 cmd_name = "LC_LOAD_UPWARD_DYLIB"; 4476 goto check_dylib_command; 4477 case LC_LAZY_LOAD_DYLIB: 4478 cmd_name = "LC_LAZY_LOAD_DYLIB"; 4479 goto check_dylib_command; 4480check_dylib_command: 4481 if(l.cmdsize < sizeof(struct dylib_command)){ 4482 Mach_O_error(ofile, "malformed object (%s cmdsize too " 4483 "small) in command %u", cmd_name, i); 4484 goto return_bad; 4485 } 4486 dl = (struct dylib_command *)lc; 4487 if(swapped) 4488 swap_dylib_command(dl, host_byte_sex); 4489 if(dl->cmdsize < sizeof(struct dylib_command)){ 4490 Mach_O_error(ofile, "malformed object (%s command %u has " 4491 "too small cmdsize field)", cmd_name, i); 4492 goto return_bad; 4493 } 4494 if(dl->dylib.name.offset >= dl->cmdsize){ 4495 Mach_O_error(ofile, "truncated or malformed object (name." 4496 "offset field of %s command %u extends past the end " 4497 "of the file)", cmd_name, i); 4498 goto return_bad; 4499 } 4500 break; 4501 4502 case LC_SUB_FRAMEWORK: 4503 if(l.cmdsize < sizeof(struct sub_framework_command)){ 4504 Mach_O_error(ofile, "malformed object (LC_SUB_FRAMEWORK " 4505 "cmdsize too small) in command %u", i); 4506 goto return_bad; 4507 } 4508 sub = (struct sub_framework_command *)lc; 4509 if(swapped) 4510 swap_sub_framework_command(sub, host_byte_sex); 4511 if(sub->cmdsize < sizeof(struct sub_framework_command)){ 4512 Mach_O_error(ofile, "malformed object (LC_SUB_FRAMEWORK " 4513 "command %u has too small cmdsize field)", i); 4514 goto return_bad; 4515 } 4516 if(sub->umbrella.offset >= sub->cmdsize){ 4517 Mach_O_error(ofile, "truncated or malformed object " 4518 "(umbrella.offset field of LC_SUB_FRAMEWORK command " 4519 "%u extends past the end of the file)", i); 4520 goto return_bad; 4521 } 4522 break; 4523 4524 case LC_SUB_UMBRELLA: 4525 if(l.cmdsize < sizeof(struct sub_umbrella_command)){ 4526 Mach_O_error(ofile, "malformed object (LC_SUB_UMBRELLA " 4527 "cmdsize too small) in command %u", i); 4528 goto return_bad; 4529 } 4530 usub = (struct sub_umbrella_command *)lc; 4531 if(swapped) 4532 swap_sub_umbrella_command(usub, host_byte_sex); 4533 if(usub->cmdsize < sizeof(struct sub_umbrella_command)){ 4534 Mach_O_error(ofile, "malformed object (LC_SUB_UMBRELLA " 4535 "command %u has too small cmdsize field)", i); 4536 goto return_bad; 4537 } 4538 if(usub->sub_umbrella.offset >= usub->cmdsize){ 4539 Mach_O_error(ofile, "truncated or malformed object " 4540 "(sub_umbrella.offset field of LC_SUB_UMBRELLA command " 4541 "%u extends past the end of the file)", i); 4542 goto return_bad; 4543 } 4544 break; 4545 4546 case LC_SUB_LIBRARY: 4547 if(l.cmdsize < sizeof(struct sub_library_command)){ 4548 Mach_O_error(ofile, "malformed object (LC_SUB_LIBRARY " 4549 "cmdsize too small) in command %u", i); 4550 goto return_bad; 4551 } 4552 lsub = (struct sub_library_command *)lc; 4553 if(swapped) 4554 swap_sub_library_command(lsub, host_byte_sex); 4555 if(lsub->cmdsize < sizeof(struct sub_library_command)){ 4556 Mach_O_error(ofile, "malformed object (LC_SUB_LIBRARY " 4557 "command %u has too small cmdsize field)", i); 4558 goto return_bad; 4559 } 4560 if(lsub->sub_library.offset >= lsub->cmdsize){ 4561 Mach_O_error(ofile, "truncated or malformed object " 4562 "(sub_library.offset field of LC_SUB_LIBRARY command " 4563 "%u extends past the end of the file)", i); 4564 goto return_bad; 4565 } 4566 break; 4567 4568 case LC_SUB_CLIENT: 4569 if(l.cmdsize < sizeof(struct sub_client_command)){ 4570 Mach_O_error(ofile, "malformed object (LC_SUB_CLIENT " 4571 "cmdsize too small) in command %u", i); 4572 goto return_bad; 4573 } 4574 csub = (struct sub_client_command *)lc; 4575 if(swapped) 4576 swap_sub_client_command(csub, host_byte_sex); 4577 if(csub->cmdsize < sizeof(struct sub_client_command)){ 4578 Mach_O_error(ofile, "malformed object (LC_SUB_CLIENT " 4579 "command %u has too small cmdsize field)", i); 4580 goto return_bad; 4581 } 4582 if(csub->client.offset >= csub->cmdsize){ 4583 Mach_O_error(ofile, "truncated or malformed object " 4584 "(cleient.offset field of LC_SUB_CLIENT command " 4585 "%u extends past the end of the file)", i); 4586 goto return_bad; 4587 } 4588 break; 4589 4590 case LC_PREBOUND_DYLIB: 4591 if(l.cmdsize < sizeof(struct prebound_dylib_command)){ 4592 Mach_O_error(ofile, "malformed object (LC_PREBOUND_DYLIB " 4593 "cmdsize too small) in command %u", i); 4594 goto return_bad; 4595 } 4596 pbdylib = (struct prebound_dylib_command *)lc; 4597 if(swapped) 4598 swap_prebound_dylib_command(pbdylib, host_byte_sex); 4599 if(pbdylib->cmdsize < sizeof(struct dylib_command)){ 4600 Mach_O_error(ofile, "malformed object (LC_PREBIND_DYLIB " 4601 "command %u has too small cmdsize field)", i); 4602 goto return_bad; 4603 } 4604 if(pbdylib->name.offset >= pbdylib->cmdsize){ 4605 Mach_O_error(ofile, "truncated or malformed object (name." 4606 "offset field of LC_PREBIND_DYLIB command %u extends " 4607 "past the end of the file)", i); 4608 goto return_bad; 4609 } 4610 if(pbdylib->linked_modules.offset >= pbdylib->cmdsize){ 4611 Mach_O_error(ofile, "truncated or malformed object (linked_" 4612 "modules.offset field of LC_PREBIND_DYLIB command %u " 4613 "extends past the end of the file)", i); 4614 goto return_bad; 4615 } 4616 break; 4617 4618 case LC_ID_DYLINKER: 4619 cmd_name = "LC_ID_DYLINKER"; 4620 goto check_dylinker_command; 4621 case LC_LOAD_DYLINKER: 4622 cmd_name = "LC_LOAD_DYLINKER"; 4623 goto check_dylinker_command; 4624 case LC_DYLD_ENVIRONMENT: 4625 cmd_name = "LC_DYLD_ENVIRONMENT"; 4626 goto check_dylinker_command; 4627check_dylinker_command: 4628 if(l.cmdsize < sizeof(struct dylinker_command)){ 4629 Mach_O_error(ofile, "malformed object (%s cmdsize " 4630 "too small) in command %u", cmd_name, i); 4631 goto return_bad; 4632 } 4633 dyld = (struct dylinker_command *)lc; 4634 if(swapped) 4635 swap_dylinker_command(dyld, host_byte_sex); 4636 if(dyld->cmdsize < sizeof(struct dylinker_command)){ 4637 Mach_O_error(ofile, "malformed object (%s command %u has " 4638 "too small cmdsize field)", cmd_name, i); 4639 goto return_bad; 4640 } 4641 if(dyld->name.offset >= dyld->cmdsize){ 4642 Mach_O_error(ofile, "truncated or malformed object (name." 4643 "offset field of %s command %u extends past the end " 4644 "of the file)", cmd_name, i); 4645 goto return_bad; 4646 } 4647 break; 4648 4649 case LC_UNIXTHREAD: 4650 case LC_THREAD: 4651 if(l.cmdsize < sizeof(struct thread_command)){ 4652 Mach_O_error(ofile, "malformed object (%s cmdsize " 4653 "too small) in command %u", l.cmd == 4654 LC_UNIXTHREAD ? "LC_UNIXTHREAD" : 4655 "LC_THREAD", i); 4656 goto return_bad; 4657 } 4658 ut = (struct thread_command *)lc; 4659 if(swapped) 4660 swap_thread_command(ut, host_byte_sex); 4661 state = (char *)ut + sizeof(struct thread_command); 4662 4663 if(cputype == CPU_TYPE_MC680x0){ 4664 struct m68k_thread_state_regs *cpu; 4665 struct m68k_thread_state_68882 *fpu; 4666 struct m68k_thread_state_user_reg *user_reg; 4667 4668 nflavor = 0; 4669 p = (char *)ut + ut->cmdsize; 4670 while(state < p){ 4671 if(state + sizeof(uint32_t) > 4672 (char *)ut + ut->cmdsize){ 4673 Mach_O_error(ofile, "malformed object (flavor in " 4674 "%s command %u extends past end of command)", 4675 ut->cmd == LC_UNIXTHREAD ? "LC_UNIXTHREAD" : 4676 "LC_THREAD", i); 4677 goto return_bad; 4678 } 4679 flavor = *((uint32_t *)state); 4680 if(swapped){ 4681 flavor = SWAP_INT(flavor); 4682 *((uint32_t *)state) = flavor; 4683 } 4684 state += sizeof(uint32_t); 4685 if(state + sizeof(uint32_t) > 4686 (char *)ut + ut->cmdsize){ 4687 Mach_O_error(ofile, "malformed object (count in " 4688 "%s command %u extends past end of command)", 4689 ut->cmd == LC_UNIXTHREAD ? "LC_UNIXTHREAD" : 4690 "LC_THREAD", i); 4691 goto return_bad; 4692 } 4693 count = *((uint32_t *)state); 4694 if(swapped){ 4695 count = SWAP_INT(count); 4696 *((uint32_t *)state) = count; 4697 } 4698 state += sizeof(uint32_t); 4699 switch(flavor){ 4700 case M68K_THREAD_STATE_REGS: 4701 if(count != M68K_THREAD_STATE_REGS_COUNT){ 4702 Mach_O_error(ofile, "malformed object (count " 4703 "not M68K_THREAD_STATE_REGS_COUNT for " 4704 "flavor number %u which is a M68K_THREAD_" 4705 "STATE_REGS flavor in %s command %u)", 4706 nflavor, ut->cmd == LC_UNIXTHREAD ? 4707 "LC_UNIXTHREAD" : "LC_THREAD", i); 4708 goto return_bad; 4709 } 4710 cpu = (struct m68k_thread_state_regs *)state; 4711 if(state + sizeof(struct m68k_thread_state_regs) > 4712 (char *)ut + ut->cmdsize){ 4713 Mach_O_error(ofile, "malformed object (" 4714 "M68K_THREAD_STATE_REGS in %s command %u " 4715 "extends past end of command)", ut->cmd == 4716 LC_UNIXTHREAD ? "LC_UNIXTHREAD" : 4717 "LC_THREAD", i); 4718 goto return_bad; 4719 } 4720 if(swapped) 4721 swap_m68k_thread_state_regs(cpu, host_byte_sex); 4722 state += sizeof(struct m68k_thread_state_regs); 4723 break; 4724 case M68K_THREAD_STATE_68882: 4725 if(count != M68K_THREAD_STATE_68882_COUNT){ 4726 Mach_O_error(ofile, "malformed object (count " 4727 "not M68K_THREAD_STATE_68882_COUNT for " 4728 "flavor number %u which is a M68K_THREAD_" 4729 "STATE_68882 flavor in %s command %u)", 4730 nflavor, ut->cmd == LC_UNIXTHREAD ? 4731 "LC_UNIXTHREAD" : "LC_THREAD", i); 4732 goto return_bad; 4733 } 4734 fpu = (struct m68k_thread_state_68882 *)state; 4735 if(state + sizeof(struct m68k_thread_state_68882) > 4736 (char *)ut + ut->cmdsize){ 4737 Mach_O_error(ofile, "malformed object (" 4738 "M68K_THREAD_STATE_68882 in %s command %u " 4739 "extends past end of command)", ut->cmd == 4740 LC_UNIXTHREAD ? "LC_UNIXTHREAD" : 4741 "LC_THREAD", i); 4742 goto return_bad; 4743 } 4744 if(swapped) 4745 swap_m68k_thread_state_68882(fpu,host_byte_sex); 4746 state += sizeof(struct m68k_thread_state_68882); 4747 break; 4748 case M68K_THREAD_STATE_USER_REG: 4749 if(count != M68K_THREAD_STATE_USER_REG_COUNT){ 4750 Mach_O_error(ofile, "malformed object (count " 4751 "not M68K_THREAD_STATE_USER_REG_COUNT for " 4752 "flavor number %u which is a M68K_THREAD_" 4753 "STATE_USER_REG flavor in %s command %u)", 4754 nflavor, ut->cmd == LC_UNIXTHREAD ? 4755 "LC_UNIXTHREAD" : "LC_THREAD", i); 4756 goto return_bad; 4757 } 4758 user_reg = 4759 (struct m68k_thread_state_user_reg *)state; 4760 if(state+sizeof(struct m68k_thread_state_user_reg) > 4761 (char *)ut + ut->cmdsize){ 4762 Mach_O_error(ofile, "malformed object (" 4763 "M68K_THREAD_STATE_USER_REG in %s command " 4764 "%u extends past end of command)", ut->cmd== 4765 LC_UNIXTHREAD ? "LC_UNIXTHREAD" : 4766 "LC_THREAD", i); 4767 goto return_bad; 4768 } 4769 if(swapped) 4770 swap_m68k_thread_state_user_reg(user_reg, 4771 host_byte_sex); 4772 state += sizeof(struct m68k_thread_state_user_reg); 4773 break; 4774 default: 4775 if(swapped){ 4776 Mach_O_error(ofile, "malformed object (unknown " 4777 "flavor for flavor number %u in %s command" 4778 " %u can't byte swap it)", nflavor, 4779 ut->cmd == LC_UNIXTHREAD ? "LC_UNIXTHREAD" : 4780 "LC_THREAD", i); 4781 goto return_bad; 4782 } 4783 state += count * sizeof(uint32_t); 4784 break; 4785 } 4786 nflavor++; 4787 } 4788 break; 4789 } 4790 if(cputype == CPU_TYPE_POWERPC || 4791 cputype == CPU_TYPE_VEO){ 4792 ppc_thread_state_t *nrw_cpu; 4793 4794 nflavor = 0; 4795 p = (char *)ut + ut->cmdsize; 4796 while(state < p){ 4797 if(state + sizeof(uint32_t) > 4798 (char *)ut + ut->cmdsize){ 4799 Mach_O_error(ofile, "malformed object (flavor in " 4800 "%s command %u extends past end of command)", 4801 ut->cmd == LC_UNIXTHREAD ? "LC_UNIXTHREAD" : 4802 "LC_THREAD", i); 4803 goto return_bad; 4804 } 4805 flavor = *((uint32_t *)state); 4806 if(swapped){ 4807 flavor = SWAP_INT(flavor); 4808 *((uint32_t *)state) = flavor; 4809 } 4810 state += sizeof(uint32_t); 4811 if(state + sizeof(uint32_t) > 4812 (char *)ut + ut->cmdsize){ 4813 Mach_O_error(ofile, "malformed object (count in " 4814 "%s command %u extends past end of command)", 4815 ut->cmd == LC_UNIXTHREAD ? "LC_UNIXTHREAD" : 4816 "LC_THREAD", i); 4817 goto return_bad; 4818 } 4819 count = *((uint32_t *)state); 4820 if(swapped){ 4821 count = SWAP_INT(count); 4822 *((uint32_t *)state) = count; 4823 } 4824 state += sizeof(uint32_t); 4825 switch(flavor){ 4826 case PPC_THREAD_STATE: 4827 if(count != PPC_THREAD_STATE_COUNT){ 4828 Mach_O_error(ofile, "malformed object (count " 4829 "not PPC_THREAD_STATE_COUNT for " 4830 "flavor number %u which is a PPC_THREAD_" 4831 "STATE flavor in %s command %u)", 4832 nflavor, ut->cmd == LC_UNIXTHREAD ? 4833 "LC_UNIXTHREAD" : "LC_THREAD", i); 4834 goto return_bad; 4835 } 4836 nrw_cpu = (ppc_thread_state_t *)state; 4837 if(state + sizeof(ppc_thread_state_t) > 4838 (char *)ut + ut->cmdsize){ 4839 Mach_O_error(ofile, "malformed object (" 4840 "PPC_THREAD_STATE in %s command %u extends" 4841 " past end of command)", ut->cmd == 4842 LC_UNIXTHREAD ? "LC_UNIXTHREAD" : 4843 "LC_THREAD", i); 4844 goto return_bad; 4845 } 4846 if(swapped) 4847 swap_ppc_thread_state_t(nrw_cpu, 4848 host_byte_sex); 4849 state += sizeof(ppc_thread_state_t); 4850 break; 4851 default: 4852 if(swapped){ 4853 Mach_O_error(ofile, "malformed object (unknown " 4854 "flavor for flavor number %u in %s command" 4855 " %u can't byte swap it)", nflavor, 4856 ut->cmd == LC_UNIXTHREAD ? "LC_UNIXTHREAD" : 4857 "LC_THREAD", i); 4858 goto return_bad; 4859 } 4860 state += count * sizeof(uint32_t); 4861 break; 4862 } 4863 nflavor++; 4864 } 4865 break; 4866 } 4867#ifdef PPC_THREAD_STATE64_COUNT 4868 if(cputype == CPU_TYPE_POWERPC64){ 4869 ppc_thread_state64_t *cpu; 4870 4871 nflavor = 0; 4872 p = (char *)ut + ut->cmdsize; 4873 while(state < p){ 4874 if(state + sizeof(uint32_t) > 4875 (char *)ut + ut->cmdsize){ 4876 Mach_O_error(ofile, "malformed object (flavor in " 4877 "%s command %u extends past end of command)", 4878 ut->cmd == LC_UNIXTHREAD ? "LC_UNIXTHREAD" : 4879 "LC_THREAD", i); 4880 goto return_bad; 4881 } 4882 flavor = *((uint32_t *)state); 4883 if(swapped){ 4884 flavor = SWAP_INT(flavor); 4885 *((uint32_t *)state) = flavor; 4886 } 4887 state += sizeof(uint32_t); 4888 if(state + sizeof(uint32_t) > 4889 (char *)ut + ut->cmdsize){ 4890 Mach_O_error(ofile, "malformed object (count in " 4891 "%s command %u extends past end of command)", 4892 ut->cmd == LC_UNIXTHREAD ? "LC_UNIXTHREAD" : 4893 "LC_THREAD", i); 4894 goto return_bad; 4895 } 4896 count = *((uint32_t *)state); 4897 if(swapped){ 4898 count = SWAP_INT(count); 4899 *((uint32_t *)state) = count; 4900 } 4901 state += sizeof(uint32_t); 4902 switch(flavor){ 4903 case PPC_THREAD_STATE64: 4904 if(count != PPC_THREAD_STATE64_COUNT){ 4905 Mach_O_error(ofile, "malformed object (count " 4906 "not PPC_THREAD_STATE64_COUNT for " 4907 "flavor number %u which is a PPC_THREAD_" 4908 "STATE64 flavor in %s command %u)", 4909 nflavor, ut->cmd == LC_UNIXTHREAD ? 4910 "LC_UNIXTHREAD" : "LC_THREAD", i); 4911 goto return_bad; 4912 } 4913 cpu = (ppc_thread_state64_t *)state; 4914 if(state + sizeof(ppc_thread_state64_t) > 4915 (char *)ut + ut->cmdsize){ 4916 Mach_O_error(ofile, "malformed object (" 4917 "PPC_THREAD_STATE64 in %s command %u " 4918 "extends past end of command)", ut->cmd == 4919 LC_UNIXTHREAD ? "LC_UNIXTHREAD" : 4920 "LC_THREAD", i); 4921 goto return_bad; 4922 } 4923 if(swapped) 4924 swap_ppc_thread_state64_t(cpu, host_byte_sex); 4925 state += sizeof(ppc_thread_state64_t); 4926 break; 4927 default: 4928 if(swapped){ 4929 Mach_O_error(ofile, "malformed object (unknown " 4930 "flavor for flavor number %u in %s command" 4931 " %u can't byte swap it)", nflavor, 4932 ut->cmd == LC_UNIXTHREAD ? "LC_UNIXTHREAD" : 4933 "LC_THREAD", i); 4934 goto return_bad; 4935 } 4936 state += count * sizeof(uint32_t); 4937 break; 4938 } 4939 nflavor++; 4940 } 4941 break; 4942 } 4943#endif /* PPC_THREAD_STATE64_COUNT */ 4944 if(cputype == CPU_TYPE_MC88000){ 4945 m88k_thread_state_grf_t *cpu; 4946 m88k_thread_state_xrf_t *fpu; 4947 m88k_thread_state_user_t *user; 4948 m88110_thread_state_impl_t *spu; 4949 4950 nflavor = 0; 4951 p = (char *)ut + ut->cmdsize; 4952 while(state < p){ 4953 if(state + sizeof(uint32_t) > 4954 (char *)ut + ut->cmdsize){ 4955 Mach_O_error(ofile, "malformed object (flavor in " 4956 "%s command %u extends past end of command)", 4957 ut->cmd == LC_UNIXTHREAD ? "LC_UNIXTHREAD" : 4958 "LC_THREAD", i); 4959 goto return_bad; 4960 } 4961 flavor = *((uint32_t *)state); 4962 if(swapped){ 4963 flavor = SWAP_INT(flavor); 4964 *((uint32_t *)state) = flavor; 4965 } 4966 state += sizeof(uint32_t); 4967 if(state + sizeof(uint32_t) > 4968 (char *)ut + ut->cmdsize){ 4969 Mach_O_error(ofile, "malformed object (count in " 4970 "%s command %u extends past end of command)", 4971 ut->cmd == LC_UNIXTHREAD ? "LC_UNIXTHREAD" : 4972 "LC_THREAD", i); 4973 goto return_bad; 4974 } 4975 count = *((uint32_t *)state); 4976 if(swapped){ 4977 count = SWAP_INT(count); 4978 *((uint32_t *)state) = count; 4979 } 4980 state += sizeof(uint32_t); 4981 switch(flavor){ 4982 case M88K_THREAD_STATE_GRF: 4983 if(count != M88K_THREAD_STATE_GRF_COUNT){ 4984 Mach_O_error(ofile, "malformed object (count " 4985 "not M88K_THREAD_STATE_GRF_COUNT for " 4986 "flavor number %u which is a M88K_THREAD_" 4987 "STATE_GRF flavor in %s command %u)", 4988 nflavor, ut->cmd == LC_UNIXTHREAD ? 4989 "LC_UNIXTHREAD" : "LC_THREAD", i); 4990 goto return_bad; 4991 } 4992 cpu = (m88k_thread_state_grf_t *)state; 4993 if(state + sizeof(m88k_thread_state_grf_t) > 4994 (char *)ut + ut->cmdsize){ 4995 Mach_O_error(ofile, "malformed object (" 4996 "M88K_THREAD_STATE_GRF in %s command %u " 4997 "extends past end of command)", ut->cmd == 4998 LC_UNIXTHREAD ? "LC_UNIXTHREAD" : 4999 "LC_THREAD", i); 5000 goto return_bad; 5001 } 5002 if(swapped) 5003 swap_m88k_thread_state_grf_t(cpu, 5004 host_byte_sex); 5005 state += sizeof(m88k_thread_state_grf_t); 5006 break; 5007 case M88K_THREAD_STATE_XRF: 5008 if(count != M88K_THREAD_STATE_XRF_COUNT){ 5009 Mach_O_error(ofile, "malformed object (count " 5010 "not M88K_THREAD_STATE_XRF_COUNT for " 5011 "flavor number %u which is a M88K_THREAD_" 5012 "STATE_XRF flavor in %s command %u)", 5013 nflavor, ut->cmd == LC_UNIXTHREAD ? 5014 "LC_UNIXTHREAD" : "LC_THREAD", i); 5015 goto return_bad; 5016 } 5017 fpu = (m88k_thread_state_xrf_t *)state; 5018 if(state + sizeof(m88k_thread_state_xrf_t) > 5019 (char *)ut + ut->cmdsize){ 5020 Mach_O_error(ofile, "malformed object (" 5021 "M88K_THREAD_STATE_XRF in %s command %u " 5022 "extends past end of command)", ut->cmd == 5023 LC_UNIXTHREAD ? "LC_UNIXTHREAD" : 5024 "LC_THREAD", i); 5025 goto return_bad; 5026 } 5027 if(swapped) 5028 swap_m88k_thread_state_xrf_t(fpu, 5029 host_byte_sex); 5030 state += sizeof(m88k_thread_state_xrf_t); 5031 break; 5032 case M88K_THREAD_STATE_USER: 5033 if(count != M88K_THREAD_STATE_USER_COUNT){ 5034 Mach_O_error(ofile, "malformed object (count " 5035 "not M88K_THREAD_STATE_USER_COUNT for " 5036 "flavor number %u which is a M88K_THREAD_" 5037 "STATE_USER flavor in %s command %u)", 5038 nflavor, ut->cmd == LC_UNIXTHREAD ? 5039 "LC_UNIXTHREAD" : "LC_THREAD", i); 5040 goto return_bad; 5041 } 5042 user = (m88k_thread_state_user_t *)state; 5043 if(state + sizeof(m88k_thread_state_user_t) > 5044 (char *)ut + ut->cmdsize){ 5045 Mach_O_error(ofile, "malformed object (" 5046 "M88K_THREAD_STATE_USER in %s command %u " 5047 "extends past end of command)", ut->cmd == 5048 LC_UNIXTHREAD ? "LC_UNIXTHREAD" : 5049 "LC_THREAD", i); 5050 goto return_bad; 5051 } 5052 if(swapped) 5053 swap_m88k_thread_state_user_t(user, 5054 host_byte_sex); 5055 state += sizeof(m88k_thread_state_user_t); 5056 break; 5057 case M88110_THREAD_STATE_IMPL: 5058 if(count != M88110_THREAD_STATE_IMPL_COUNT){ 5059 Mach_O_error(ofile, "malformed object (count " 5060 "not M88110_THREAD_STATE_IMPL_COUNT for " 5061 "flavor number %u which is a M88110_THREAD" 5062 "_STATE_IMPL flavor in %s command %u)", 5063 nflavor, ut->cmd == LC_UNIXTHREAD ? 5064 "LC_UNIXTHREAD" : "LC_THREAD", i); 5065 goto return_bad; 5066 } 5067 spu = (m88110_thread_state_impl_t *)state; 5068 if(state + sizeof(m88110_thread_state_impl_t) > 5069 (char *)ut + ut->cmdsize){ 5070 Mach_O_error(ofile, "malformed object (" 5071 "M88110_THREAD_STATE_IMPL in %s command %u " 5072 "extends past end of command)", ut->cmd == 5073 LC_UNIXTHREAD ? "LC_UNIXTHREAD" : 5074 "LC_THREAD", i); 5075 goto return_bad; 5076 } 5077 if(swapped) 5078 swap_m88110_thread_state_impl_t(spu, 5079 host_byte_sex); 5080 state += sizeof(m88110_thread_state_impl_t); 5081 break; 5082 default: 5083 if(swapped){ 5084 Mach_O_error(ofile, "malformed object (unknown " 5085 "flavor for flavor number %u in %s command" 5086 " %u can't byte swap it)", nflavor, 5087 ut->cmd == LC_UNIXTHREAD ? "LC_UNIXTHREAD" : 5088 "LC_THREAD", i); 5089 goto return_bad; 5090 } 5091 state += count * sizeof(uint32_t); 5092 break; 5093 } 5094 nflavor++; 5095 } 5096 break; 5097 } 5098 if(cputype == CPU_TYPE_I860){ 5099#ifdef m68k 5100 struct i860_thread_state_regs *cpu; 5101#endif 5102 5103 nflavor = 0; 5104 p = (char *)ut + ut->cmdsize; 5105 while(state < p){ 5106 if(state + sizeof(uint32_t) > 5107 (char *)ut + ut->cmdsize){ 5108 Mach_O_error(ofile, "malformed object (flavor in " 5109 "%s command %u extends past end of command)", 5110 ut->cmd == LC_UNIXTHREAD ? "LC_UNIXTHREAD" : 5111 "LC_THREAD", i); 5112 goto return_bad; 5113 } 5114 flavor = *((uint32_t *)state); 5115 if(swapped){ 5116 flavor = SWAP_INT(flavor); 5117 *((uint32_t *)state) = flavor; 5118 } 5119 state += sizeof(uint32_t); 5120 if(state + sizeof(uint32_t) > 5121 (char *)ut + ut->cmdsize){ 5122 Mach_O_error(ofile, "malformed object (count in " 5123 "%s command %u extends past end of command)", 5124 ut->cmd == LC_UNIXTHREAD ? "LC_UNIXTHREAD" : 5125 "LC_THREAD", i); 5126 return(CHECK_BAD); 5127 } 5128 count = *((uint32_t *)state); 5129 if(swapped){ 5130 count = SWAP_INT(count); 5131 *((uint32_t *)state) = count; 5132 } 5133 state += sizeof(uint32_t); 5134 switch(flavor){ 5135 case I860_THREAD_STATE_REGS: 5136#ifdef m68k 5137 if(count != I860_THREAD_STATE_REGS_COUNT){ 5138 Mach_O_error(ofile, "malformed object (count " 5139 "not I860_THREAD_STATE_REGS_COUNT for " 5140 "flavor number %u which is a I860_THREAD_" 5141 "STATE_REGS flavor in %s command %u)", 5142 nflavor, ut->cmd == LC_UNIXTHREAD ? 5143 "LC_UNIXTHREAD" : "LC_THREAD", i); 5144 goto return_bad; 5145 } 5146 cpu = (struct i860_thread_state_regs *)state; 5147 if(state + sizeof(struct i860_thread_state_regs) > 5148 (char *)ut + ut->cmdsize){ 5149 Mach_O_error(ofile, "malformed object (" 5150 "I860_THREAD_STATE_REGS in %s command %u " 5151 "extends past end of command)", ut->cmd == 5152 LC_UNIXTHREAD ? "LC_UNIXTHREAD" : 5153 "LC_THREAD", i); 5154 goto return_bad; 5155 } 5156 if(swapped) 5157 swap_i860_thread_state_regs(cpu, host_byte_sex); 5158 state += sizeof(struct i860_thread_state_regs); 5159#else 5160 state += count * sizeof(int); 5161#endif 5162 break; 5163 default: 5164 if(swapped){ 5165 Mach_O_error(ofile, "malformed object (unknown " 5166 "flavor for flavor number %u in %s command" 5167 " %u can't byte swap it)", nflavor, 5168 ut->cmd == LC_UNIXTHREAD ? "LC_UNIXTHREAD" : 5169 "LC_THREAD", i); 5170 goto return_bad; 5171 } 5172 state += count * sizeof(uint32_t); 5173 break; 5174 } 5175 nflavor++; 5176 } 5177 break; 5178 } 5179 if(cputype == CPU_TYPE_I386){ 5180 i386_thread_state_t *cpu; 5181/* current i386 thread states */ 5182#if i386_THREAD_STATE == 1 5183 struct i386_float_state *fpu; 5184 i386_exception_state_t *exc; 5185#endif /* i386_THREAD_STATE == 1 */ 5186 5187/* i386 thread states on older releases */ 5188#if i386_THREAD_STATE == -1 5189 i386_thread_fpstate_t *fpu; 5190 i386_thread_exceptstate_t *exc; 5191 i386_thread_cthreadstate_t *user; 5192#endif /* i386_THREAD_STATE == -1 */ 5193 5194 nflavor = 0; 5195 p = (char *)ut + ut->cmdsize; 5196 while(state < p){ 5197 if(state + sizeof(uint32_t) > 5198 (char *)ut + ut->cmdsize){ 5199 Mach_O_error(ofile, "malformed object (flavor in " 5200 "%s command %u extends past end of command)", 5201 ut->cmd == LC_UNIXTHREAD ? "LC_UNIXTHREAD" : 5202 "LC_THREAD", i); 5203 goto return_bad; 5204 } 5205 flavor = *((uint32_t *)state); 5206 if(swapped){ 5207 flavor = SWAP_INT(flavor); 5208 *((uint32_t *)state) = flavor; 5209 } 5210 state += sizeof(uint32_t); 5211 if(state + sizeof(uint32_t) > 5212 (char *)ut + ut->cmdsize){ 5213 Mach_O_error(ofile, "malformed object (count in " 5214 "%s command %u extends past end of command)", 5215 ut->cmd == LC_UNIXTHREAD ? "LC_UNIXTHREAD" : 5216 "LC_THREAD", i); 5217 goto return_bad; 5218 } 5219 count = *((uint32_t *)state); 5220 if(swapped){ 5221 count = SWAP_INT(count); 5222 *((uint32_t *)state) = count; 5223 } 5224 state += sizeof(uint32_t); 5225 switch((int)flavor){ 5226 case i386_THREAD_STATE: 5227#if i386_THREAD_STATE == 1 5228 case -1: 5229#endif /* i386_THREAD_STATE == 1 */ 5230/* i386 thread states on older releases */ 5231#if i386_THREAD_STATE == -1 5232 case 1: 5233#endif /* i386_THREAD_STATE == -1 */ 5234 if(count != i386_THREAD_STATE_COUNT){ 5235 Mach_O_error(ofile, "malformed object (count " 5236 "not i386_THREAD_STATE_COUNT for flavor " 5237 "number %u which is a i386_THREAD_STATE " 5238 "flavor in %s command %u)", nflavor, 5239 ut->cmd == LC_UNIXTHREAD ? "LC_UNIXTHREAD" : 5240 "LC_THREAD", i); 5241 goto return_bad; 5242 } 5243 cpu = (i386_thread_state_t *)state; 5244 if(state + sizeof(i386_thread_state_t) > 5245 (char *)ut + ut->cmdsize){ 5246 Mach_O_error(ofile, "malformed object (" 5247 "i386_THREAD_STATE in %s command %u " 5248 "extends past end of command)", ut->cmd == 5249 LC_UNIXTHREAD ? "LC_UNIXTHREAD" : 5250 "LC_THREAD", i); 5251 goto return_bad; 5252 } 5253 if(swapped) 5254 swap_i386_thread_state(cpu, host_byte_sex); 5255 state += sizeof(i386_thread_state_t); 5256 break; 5257/* current i386 thread states */ 5258#if i386_THREAD_STATE == 1 5259 case i386_FLOAT_STATE: 5260 if(count != i386_FLOAT_STATE_COUNT){ 5261 Mach_O_error(ofile, "malformed object (count " 5262 "not i386_FLOAT_STATE_COUNT for flavor " 5263 "number %u which is a i386_FLOAT_STATE " 5264 "flavor in %s command %u)", nflavor, 5265 ut->cmd == LC_UNIXTHREAD ? "LC_UNIXTHREAD" : 5266 "LC_THREAD", i); 5267 goto return_bad; 5268 } 5269 fpu = (struct i386_float_state *)state; 5270 if(state + sizeof(struct i386_float_state) > 5271 (char *)ut + ut->cmdsize){ 5272 Mach_O_error(ofile, "malformed object (" 5273 "i386_FLOAT_STATE in %s command %u " 5274 "extends past end of command)", ut->cmd == 5275 LC_UNIXTHREAD ? "LC_UNIXTHREAD" : 5276 "LC_THREAD", i); 5277 goto return_bad; 5278 } 5279 if(swapped) 5280 swap_i386_float_state(fpu, host_byte_sex); 5281 state += sizeof(struct i386_float_state); 5282 break; 5283 case i386_EXCEPTION_STATE: 5284 if(count != I386_EXCEPTION_STATE_COUNT){ 5285 Mach_O_error(ofile, "malformed object (count " 5286 "not I386_EXCEPTION_STATE_COUNT for " 5287 "flavor number %u which is a i386_" 5288 "EXCEPTION_STATE flavor in %s command %u)", 5289 nflavor, 5290 ut->cmd == LC_UNIXTHREAD ? "LC_UNIXTHREAD" : 5291 "LC_THREAD", i); 5292 goto return_bad; 5293 } 5294 exc = (i386_exception_state_t *)state; 5295 if(state + sizeof(i386_exception_state_t) > 5296 (char *)ut + ut->cmdsize){ 5297 Mach_O_error(ofile, "malformed object (" 5298 "i386_EXCEPTION_STATE in %s command %u " 5299 "extends past end of command)", ut->cmd == 5300 LC_UNIXTHREAD ? "LC_UNIXTHREAD" : 5301 "LC_THREAD", i); 5302 goto return_bad; 5303 } 5304 if(swapped) 5305 swap_i386_exception_state(exc,host_byte_sex); 5306 state += sizeof(i386_exception_state_t); 5307 break; 5308#endif /* i386_THREAD_STATE == 1 */ 5309 5310/* i386 thread states on older releases */ 5311#if i386_THREAD_STATE == -1 5312 case i386_THREAD_FPSTATE: 5313 if(count != i386_THREAD_FPSTATE_COUNT){ 5314 Mach_O_error(ofile, "malformed object (count " 5315 "not i386_THREAD_FPSTATE_COUNT for flavor " 5316 "number %u which is a i386_THREAD_FPSTATE " 5317 "flavor in %s command %u)", nflavor, 5318 ut->cmd == LC_UNIXTHREAD ? "LC_UNIXTHREAD" : 5319 "LC_THREAD", i); 5320 goto return_bad; 5321 } 5322 fpu = (i386_thread_fpstate_t *)state; 5323 if(state + sizeof(i386_thread_fpstate_t) > 5324 (char *)ut + ut->cmdsize){ 5325 Mach_O_error(ofile, "malformed object (" 5326 "i386_THREAD_FPSTATE in %s command %u " 5327 "extends past end of command)", ut->cmd == 5328 LC_UNIXTHREAD ? "LC_UNIXTHREAD" : 5329 "LC_THREAD", i); 5330 goto return_bad; 5331 } 5332 if(swapped) 5333 swap_i386_thread_fpstate(fpu, host_byte_sex); 5334 state += sizeof(i386_thread_fpstate_t); 5335 break; 5336 case i386_THREAD_EXCEPTSTATE: 5337 if(count != i386_THREAD_EXCEPTSTATE_COUNT){ 5338 Mach_O_error(ofile, "malformed object (count " 5339 "not i386_THREAD_EXCEPTSTATE_COUNT for " 5340 "flavor number %u which is a i386_THREAD_" 5341 "EXCEPTSTATE flavor in %s command %u)", 5342 nflavor, 5343 ut->cmd == LC_UNIXTHREAD ? "LC_UNIXTHREAD" : 5344 "LC_THREAD", i); 5345 goto return_bad; 5346 } 5347 exc = (i386_thread_exceptstate_t *)state; 5348 if(state + sizeof(i386_thread_exceptstate_t) > 5349 (char *)ut + ut->cmdsize){ 5350 Mach_O_error(ofile, "malformed object (" 5351 "i386_THREAD_EXCEPTSTATE in %s command %u " 5352 "extends past end of command)", ut->cmd == 5353 LC_UNIXTHREAD ? "LC_UNIXTHREAD" : 5354 "LC_THREAD", i); 5355 goto return_bad; 5356 } 5357 if(swapped) 5358 swap_i386_thread_exceptstate(exc,host_byte_sex); 5359 state += sizeof(i386_thread_exceptstate_t); 5360 break; 5361 case i386_THREAD_CTHREADSTATE: 5362 if(count != i386_THREAD_CTHREADSTATE_COUNT){ 5363 Mach_O_error(ofile, "malformed object (count " 5364 "not i386_THREAD_CTHREADSTATE_COUNT for " 5365 "flavor number %u which is a i386_THREAD_" 5366 "CTHREADSTATE flavor in %s command %u)", 5367 nflavor, 5368 ut->cmd == LC_UNIXTHREAD ? "LC_UNIXTHREAD" : 5369 "LC_THREAD", i); 5370 goto return_bad; 5371 } 5372 user = (i386_thread_cthreadstate_t *)state; 5373 if(state + sizeof(i386_thread_cthreadstate_t) > 5374 (char *)ut + ut->cmdsize){ 5375 Mach_O_error(ofile, "malformed object (" 5376 "i386_THREAD_CTHREADSTATE in %s command %u " 5377 "extends past end of command)", ut->cmd == 5378 LC_UNIXTHREAD ? "LC_UNIXTHREAD" : 5379 "LC_THREAD", i); 5380 goto return_bad; 5381 } 5382 if(swapped) 5383 swap_i386_thread_cthreadstate(user, 5384 host_byte_sex); 5385 state += sizeof(i386_thread_cthreadstate_t); 5386 break; 5387#endif /* i386_THREAD_STATE == -1 */ 5388 default: 5389 if(swapped){ 5390 Mach_O_error(ofile, "malformed object (unknown " 5391 "flavor for flavor number %u in %s command" 5392 " %u can't byte swap it)", nflavor, 5393 ut->cmd == LC_UNIXTHREAD ? "LC_UNIXTHREAD" : 5394 "LC_THREAD", i); 5395 goto return_bad; 5396 } 5397 state += count * sizeof(uint32_t); 5398 break; 5399 } 5400 nflavor++; 5401 } 5402 break; 5403 } 5404#ifdef x86_THREAD_STATE64_COUNT 5405 if(cputype == CPU_TYPE_X86_64){ 5406 x86_thread_state64_t *cpu; 5407 5408 nflavor = 0; 5409 p = (char *)ut + ut->cmdsize; 5410 while(state < p){ 5411 if(state + sizeof(uint32_t) > 5412 (char *)ut + ut->cmdsize){ 5413 Mach_O_error(ofile, "malformed object (flavor in " 5414 "%s command %u extends past end of command)", 5415 ut->cmd == LC_UNIXTHREAD ? "LC_UNIXTHREAD" : 5416 "LC_THREAD", i); 5417 goto return_bad; 5418 } 5419 flavor = *((uint32_t *)state); 5420 if(swapped){ 5421 flavor = SWAP_INT(flavor); 5422 *((uint32_t *)state) = flavor; 5423 } 5424 state += sizeof(uint32_t); 5425 if(state + sizeof(uint32_t) > 5426 (char *)ut + ut->cmdsize){ 5427 Mach_O_error(ofile, "malformed object (count in " 5428 "%s command %u extends past end of command)", 5429 ut->cmd == LC_UNIXTHREAD ? "LC_UNIXTHREAD" : 5430 "LC_THREAD", i); 5431 goto return_bad; 5432 } 5433 count = *((uint32_t *)state); 5434 if(swapped){ 5435 count = SWAP_INT(count); 5436 *((uint32_t *)state) = count; 5437 } 5438 state += sizeof(uint32_t); 5439 switch(flavor){ 5440 case x86_THREAD_STATE64: 5441 if(count != x86_THREAD_STATE64_COUNT){ 5442 Mach_O_error(ofile, "malformed object (count " 5443 "not x86_THREAD_STATE64_COUNT for " 5444 "flavor number %u which is a x86_THREAD_" 5445 "STATE64 flavor in %s command %u)", 5446 nflavor, ut->cmd == LC_UNIXTHREAD ? 5447 "LC_UNIXTHREAD" : "LC_THREAD", i); 5448 goto return_bad; 5449 } 5450 cpu = (x86_thread_state64_t *)state; 5451 if(state + sizeof(x86_thread_state64_t) > 5452 (char *)ut + ut->cmdsize){ 5453 Mach_O_error(ofile, "malformed object (" 5454 "x86_THREAD_STATE64 in %s command %u " 5455 "extends past end of command)", ut->cmd == 5456 LC_UNIXTHREAD ? "LC_UNIXTHREAD" : 5457 "LC_THREAD", i); 5458 goto return_bad; 5459 } 5460 if(swapped) 5461 swap_x86_thread_state64(cpu, host_byte_sex); 5462 state += sizeof(x86_thread_state64_t); 5463 break; 5464 default: 5465 if(swapped){ 5466 Mach_O_error(ofile, "malformed object (unknown " 5467 "flavor for flavor number %u in %s command" 5468 " %u can't byte swap it)", nflavor, 5469 ut->cmd == LC_UNIXTHREAD ? "LC_UNIXTHREAD" : 5470 "LC_THREAD", i); 5471 goto return_bad; 5472 } 5473 state += count * sizeof(uint32_t); 5474 break; 5475 } 5476 nflavor++; 5477 } 5478 break; 5479 } 5480#endif /* x86_THREAD_STATE64_COUNT */ 5481 if(cputype == CPU_TYPE_HPPA){ 5482 struct hp_pa_integer_thread_state *cpu; 5483 struct hp_pa_frame_thread_state *frame; 5484 struct hp_pa_fp_thread_state *fpu; 5485 5486 nflavor = 0; 5487 p = (char *)ut + ut->cmdsize; 5488 while(state < p){ 5489 if(state + sizeof(uint32_t) > 5490 (char *)ut + ut->cmdsize){ 5491 Mach_O_error(ofile, "malformed object (flavor in " 5492 "%s command %u extends past end of command)", 5493 ut->cmd == LC_UNIXTHREAD ? "LC_UNIXTHREAD" : 5494 "LC_THREAD", i); 5495 goto return_bad; 5496 } 5497 flavor = *((uint32_t *)state); 5498 if(swapped){ 5499 flavor = SWAP_INT(flavor); 5500 *((uint32_t *)state) = flavor; 5501 } 5502 state += sizeof(uint32_t); 5503 if(state + sizeof(uint32_t) > 5504 (char *)ut + ut->cmdsize){ 5505 Mach_O_error(ofile, "malformed object (count in " 5506 "%s command %u extends past end of command)", 5507 ut->cmd == LC_UNIXTHREAD ? "LC_UNIXTHREAD" : 5508 "LC_THREAD", i); 5509 goto return_bad; 5510 } 5511 count = *((uint32_t *)state); 5512 if(swapped){ 5513 count = SWAP_INT(count); 5514 *((uint32_t *)state) = count; 5515 } 5516 state += sizeof(uint32_t); 5517 switch(flavor){ 5518 case HPPA_INTEGER_THREAD_STATE: 5519 if(count != HPPA_INTEGER_THREAD_STATE_COUNT){ 5520 Mach_O_error(ofile, "malformed object (count " 5521 "not HPPA_INTEGER_THREAD_STATE_COUNT for " 5522 "flavor number %u which is a " 5523 "HPPA_INTEGER_THREAD_STATE " 5524 "flavor in %s command %u)", nflavor, 5525 ut->cmd == LC_UNIXTHREAD ? "LC_UNIXTHREAD" : 5526 "LC_THREAD", i); 5527 goto return_bad; 5528 } 5529 cpu = (struct hp_pa_integer_thread_state *)state; 5530 if(state+sizeof(struct hp_pa_integer_thread_state) > 5531 (char *)ut + ut->cmdsize){ 5532 Mach_O_error(ofile, "malformed object (" 5533 "HPPA_INTEGER_THREAD_STATE in %s command " 5534 "%u extends past end of command)", 5535 ut->cmd == LC_UNIXTHREAD ? "LC_UNIXTHREAD" : 5536 "LC_THREAD", i); 5537 goto return_bad; 5538 } 5539 if(swapped) 5540 swap_hppa_integer_thread_state(cpu, 5541 host_byte_sex); 5542 state += sizeof(struct hp_pa_integer_thread_state); 5543 break; 5544 case HPPA_FRAME_THREAD_STATE: 5545 if(count != HPPA_FRAME_THREAD_STATE_COUNT){ 5546 Mach_O_error(ofile, "malformed object (count " 5547 "not HPPA_FRAME_THREAD_STATE_COUNT for " 5548 "flavor number %u which is a HPPA_FRAME_" 5549 "THREAD_STATE flavor in %s command %u)", 5550 nflavor, 5551 ut->cmd == LC_UNIXTHREAD ? "LC_UNIXTHREAD" : 5552 "LC_THREAD", i); 5553 goto return_bad; 5554 } 5555 frame = (struct hp_pa_frame_thread_state *)state; 5556 if(state + sizeof(struct hp_pa_frame_thread_state) > 5557 (char *)ut + ut->cmdsize){ 5558 Mach_O_error(ofile, "malformed object (" 5559 "HPPA_FRAME_THREAD_STATE in %s command " 5560 "%u extends past end of command)", 5561 ut->cmd == LC_UNIXTHREAD ? "LC_UNIXTHREAD" : 5562 "LC_THREAD", i); 5563 goto return_bad; 5564 } 5565 if(swapped) 5566 swap_hppa_frame_thread_state(frame,host_byte_sex); 5567 state += sizeof(struct hp_pa_frame_thread_state); 5568 break; 5569 case HPPA_FP_THREAD_STATE: 5570 if(count != HPPA_FP_THREAD_STATE_COUNT){ 5571 Mach_O_error(ofile, "malformed object (count " 5572 "not HPPA_FP_THREAD_STATE_COUNT for " 5573 "flavor number %u which is a HPPA_FP_" 5574 "THREAD_STATE flavor in %s command %u)", 5575 nflavor, 5576 ut->cmd == LC_UNIXTHREAD ? "LC_UNIXTHREAD" : 5577 "LC_THREAD", i); 5578 goto return_bad; 5579 } 5580 fpu = (struct hp_pa_fp_thread_state *)state; 5581 if(state + sizeof(struct hp_pa_fp_thread_state) > 5582 (char *)ut + ut->cmdsize){ 5583 Mach_O_error(ofile, "malformed object (" 5584 "HPPA_FP_THREAD_STATE in %s command " 5585 "%u extends past end of command)", 5586 ut->cmd == LC_UNIXTHREAD ? "LC_UNIXTHREAD" : 5587 "LC_THREAD", i); 5588 goto return_bad; 5589 } 5590 if(swapped) 5591 swap_hppa_fp_thread_state(fpu,host_byte_sex); 5592 state += sizeof(struct hp_pa_fp_thread_state); 5593 break; 5594 default: 5595 if(swapped){ 5596 Mach_O_error(ofile, "malformed object (unknown " 5597 "flavor for flavor number %u in %s command" 5598 " %u can't byte swap it)", nflavor, 5599 ut->cmd == LC_UNIXTHREAD ? "LC_UNIXTHREAD" : 5600 "LC_THREAD", i); 5601 goto return_bad; 5602 } 5603 state += count * sizeof(uint32_t); 5604 break; 5605 } 5606 nflavor++; 5607 } 5608 break; 5609 } 5610 if(cputype == CPU_TYPE_SPARC){ 5611 struct sparc_thread_state_regs *cpu; 5612 struct sparc_thread_state_fpu *fpu; 5613 5614 nflavor = 0; 5615 p = (char *)ut + ut->cmdsize; 5616 while(state < p){ 5617 if(state + sizeof(uint32_t) > 5618 (char *)ut + ut->cmdsize){ 5619 Mach_O_error(ofile, "malformed object (flavor in " 5620 "%s command %u extends past end of command)", 5621 ut->cmd == LC_UNIXTHREAD ? "LC_UNIXTHREAD" : 5622 "LC_THREAD", i); 5623 goto return_bad; 5624 } 5625 flavor = *((uint32_t *)state); 5626 if(swapped){ 5627 flavor = SWAP_INT(flavor); 5628 *((uint32_t *)state) = flavor; 5629 } 5630 state += sizeof(uint32_t); 5631 if(state + sizeof(uint32_t) > 5632 (char *)ut + ut->cmdsize){ 5633 Mach_O_error(ofile, "malformed object (count in " 5634 "%s command %u extends past end of command)", 5635 ut->cmd == LC_UNIXTHREAD ? "LC_UNIXTHREAD" : 5636 "LC_THREAD", i); 5637 goto return_bad; 5638 } 5639 count = *((uint32_t *)state); 5640 if(swapped){ 5641 count = SWAP_INT(count); 5642 *((uint32_t *)state) = count; 5643 } 5644 state += sizeof(uint32_t); 5645 switch(flavor){ 5646 case SPARC_THREAD_STATE_REGS: 5647 if(count != SPARC_THREAD_STATE_REGS_COUNT){ 5648 Mach_O_error(ofile, "malformed object (count " 5649 "not SPARC_THREAD_STATE_REGS_COUNT for " 5650 "flavor number %u which is a SPARC_THREAD_" 5651 "STATE_REGS flavor in %s command %u)", 5652 nflavor, ut->cmd == LC_UNIXTHREAD ? 5653 "LC_UNIXTHREAD" : "LC_THREAD", i); 5654 goto return_bad; 5655 } 5656 cpu = (struct sparc_thread_state_regs *)state; 5657 if(state + sizeof(struct sparc_thread_state_regs) > 5658 (char *)ut + ut->cmdsize){ 5659 Mach_O_error(ofile, "malformed object (" 5660 "SPARC_THREAD_STATE_REGS in %s command %u " 5661 "extends past end of command)", ut->cmd == 5662 LC_UNIXTHREAD ? "LC_UNIXTHREAD" : 5663 "LC_THREAD", i); 5664 goto return_bad; 5665 } 5666 if(swapped) 5667 swap_sparc_thread_state_regs(cpu, host_byte_sex); 5668 state += sizeof(struct sparc_thread_state_regs); 5669 break; 5670 case SPARC_THREAD_STATE_FPU: 5671 if(count != SPARC_THREAD_STATE_FPU_COUNT){ 5672 Mach_O_error(ofile, "malformed object (count " 5673 "not SPARC_THREAD_STATE_FPU_COUNT for " 5674 "flavor number %u which is a SPARC_THREAD_" 5675 "STATE_FPU flavor in %s command %u)", 5676 nflavor, ut->cmd == LC_UNIXTHREAD ? 5677 "LC_UNIXTHREAD" : "LC_THREAD", i); 5678 goto return_bad; 5679 } 5680 fpu = (struct sparc_thread_state_fpu *)state; 5681 if(state + sizeof(struct sparc_thread_state_fpu) > 5682 (char *)ut + ut->cmdsize){ 5683 Mach_O_error(ofile, "malformed object (" 5684 "SPARC_THREAD_STATE_FPU in %s command %u " 5685 "extends past end of command)", ut->cmd == 5686 LC_UNIXTHREAD ? "LC_UNIXTHREAD" : 5687 "LC_THREAD", i); 5688 goto return_bad; 5689 } 5690 if(swapped) 5691 swap_sparc_thread_state_fpu(fpu, host_byte_sex); 5692 state += sizeof(struct sparc_thread_state_fpu); 5693 break; 5694 default: 5695 if(swapped){ 5696 Mach_O_error(ofile, "malformed object (unknown " 5697 "flavor for flavor number %u in %s command" 5698 " %u can't byte swap it)", nflavor, 5699 ut->cmd == LC_UNIXTHREAD ? "LC_UNIXTHREAD" : 5700 "LC_THREAD", i); 5701 goto return_bad; 5702 } 5703 state += count * sizeof(uint32_t); 5704 break; 5705 } 5706 nflavor++; 5707 } 5708 break; 5709 } 5710 if(cputype == CPU_TYPE_ARM){ 5711 arm_thread_state_t *cpu; 5712 5713 nflavor = 0; 5714 p = (char *)ut + ut->cmdsize; 5715 while(state < p){ 5716 if(state + sizeof(uint32_t) > 5717 (char *)ut + ut->cmdsize){ 5718 Mach_O_error(ofile, "malformed object (flavor in " 5719 "%s command %u extends past end of command)", 5720 ut->cmd == LC_UNIXTHREAD ? "LC_UNIXTHREAD" : 5721 "LC_THREAD", i); 5722 goto return_bad; 5723 } 5724 flavor = *((uint32_t *)state); 5725 if(swapped){ 5726 flavor = SWAP_INT(flavor); 5727 *((uint32_t *)state) = flavor; 5728 } 5729 state += sizeof(uint32_t); 5730 if(state + sizeof(uint32_t) > 5731 (char *)ut + ut->cmdsize){ 5732 Mach_O_error(ofile, "malformed object (count in " 5733 "%s command %u extends past end of command)", 5734 ut->cmd == LC_UNIXTHREAD ? "LC_UNIXTHREAD" : 5735 "LC_THREAD", i); 5736 goto return_bad; 5737 } 5738 count = *((uint32_t *)state); 5739 if(swapped){ 5740 count = SWAP_INT(count); 5741 *((uint32_t *)state) = count; 5742 } 5743 state += sizeof(uint32_t); 5744 switch(flavor){ 5745 case ARM_THREAD_STATE: 5746 if(count != ARM_THREAD_STATE_COUNT){ 5747 Mach_O_error(ofile, "malformed object (count " 5748 "not ARM_THREAD_STATE_COUNT for " 5749 "flavor number %u which is a ARM_THREAD_" 5750 "STATE flavor in %s command %u)", 5751 nflavor, ut->cmd == LC_UNIXTHREAD ? 5752 "LC_UNIXTHREAD" : "LC_THREAD", i); 5753 goto return_bad; 5754 } 5755 cpu = (arm_thread_state_t *)state; 5756 if(state + sizeof(arm_thread_state_t) > 5757 (char *)ut + ut->cmdsize){ 5758 Mach_O_error(ofile, "malformed object (" 5759 "ARM_THREAD_STATE in %s command %u " 5760 "extends past end of command)", ut->cmd == 5761 LC_UNIXTHREAD ? "LC_UNIXTHREAD" : 5762 "LC_THREAD", i); 5763 goto return_bad; 5764 } 5765 if(swapped) 5766 swap_arm_thread_state_t(cpu, host_byte_sex); 5767 state += sizeof(arm_thread_state_t); 5768 break; 5769 default: 5770 if(swapped){ 5771 Mach_O_error(ofile, "malformed object (unknown " 5772 "flavor for flavor number %u in %s command" 5773 " %u can't byte swap it)", nflavor, 5774 ut->cmd == LC_UNIXTHREAD ? "LC_UNIXTHREAD" : 5775 "LC_THREAD", i); 5776 goto return_bad; 5777 } 5778 state += count * sizeof(uint32_t); 5779 break; 5780 } 5781 nflavor++; 5782 } 5783 break; 5784 } 5785 if(swapped){ 5786 Mach_O_error(ofile, "malformed object (unknown cputype and " 5787 "cpusubtype of object and can't byte swap and check %s " 5788 "command %u)", ut->cmd == LC_UNIXTHREAD ? 5789 "LC_UNIXTHREAD" : "LC_THREAD", i); 5790 goto return_bad; 5791 } 5792 break; 5793 case LC_MAIN: 5794 if(l.cmdsize < sizeof(struct entry_point_command)){ 5795 Mach_O_error(ofile, "malformed object (LC_MAIN cmdsize " 5796 "too small) in command %u", i); 5797 goto return_bad; 5798 } 5799 ep = (struct entry_point_command *)lc; 5800 if(swapped) 5801 swap_entry_point_command(ep, host_byte_sex); 5802 /* 5803 * If we really wanted we could check that the entryoff field 5804 * really is an offset into the __TEXT segment. But since it 5805 * is not used here, we won't needlessly check it. 5806 */ 5807 break; 5808 case LC_SOURCE_VERSION: 5809 if(l.cmdsize < sizeof(struct source_version_command)){ 5810 Mach_O_error(ofile, "malformed object (LC_SOURCE_VERSION " 5811 "cmdsize too small) in command %u", i); 5812 goto return_bad; 5813 } 5814 sv = (struct source_version_command *)lc; 5815 if(swapped) 5816 swap_source_version_command(sv, host_byte_sex); 5817 case LC_IDENT: 5818 if(l.cmdsize < sizeof(struct ident_command)){ 5819 Mach_O_error(ofile, "malformed object (LC_IDENT cmdsize " 5820 "too small) in command %u", i); 5821 goto return_bad; 5822 } 5823 id = (struct ident_command *)lc; 5824 if(swapped) 5825 swap_ident_command(id, host_byte_sex); 5826 /* 5827 * Note the cmdsize field if the LC_IDENT command was checked 5828 * as part of checking all load commands cmdsize field before 5829 * the switch statement on the cmd field of the load command. 5830 */ 5831 break; 5832 case LC_RPATH: 5833 if(l.cmdsize < sizeof(struct rpath_command)){ 5834 Mach_O_error(ofile, "malformed object (LC_RPATH: cmdsize " 5835 "too small) in command %u", i); 5836 goto return_bad; 5837 } 5838 rpath = (struct rpath_command *)lc; 5839 if(swapped) 5840 swap_rpath_command(rpath, host_byte_sex); 5841 if(rpath->cmdsize < sizeof(struct rpath_command)){ 5842 Mach_O_error(ofile, "malformed object (LC_RPATH command " 5843 "%u has too small cmdsize field)", i); 5844 goto return_bad; 5845 } 5846 if(rpath->path.offset >= rpath->cmdsize){ 5847 Mach_O_error(ofile, "truncated or malformed object (path." 5848 "offset field of LC_RPATH command %u extends past the " 5849 "end of the file)", i); 5850 goto return_bad; 5851 } 5852 break; 5853 5854#ifndef OFI 5855 default: 5856 Mach_O_error(ofile, "malformed object (unknown load command " 5857 "%u)", i); 5858 goto return_bad; 5859#endif /* !defined(OFI) */ 5860 } 5861 5862 lc = (struct load_command *)((char *)lc + l.cmdsize); 5863 /* check that next load command does not extends past the end */ 5864 if((char *)lc > (char *)load_commands + sizeofcmds){ 5865 Mach_O_error(ofile, "truncated or malformed object (load " 5866 "command %u extends past the end of the file)", 5867 i + 1); 5868 goto return_bad; 5869 } 5870 } 5871 if(st == NULL){ 5872 if(dyst != NULL){ 5873 Mach_O_error(ofile, "truncated or malformed object (contains " 5874 "LC_DYSYMTAB load command without a LC_SYMTAB load command)"); 5875 goto return_bad; 5876 } 5877 } 5878 else{ 5879 if(dyst != NULL){ 5880 if(dyst->nlocalsym != 0 && 5881 dyst->ilocalsym > st->nsyms){ 5882 Mach_O_error(ofile, "truncated or malformed object " 5883 "(ilocalsym in LC_DYSYMTAB load command extends past " 5884 "the end of the symbol table)"); 5885 goto return_bad; 5886 } 5887 big_size = dyst->ilocalsym; 5888 big_size += dyst->nlocalsym; 5889 if(dyst->nlocalsym != 0 && big_size > st->nsyms){ 5890 Mach_O_error(ofile, "truncated or malformed object " 5891 "(ilocalsym plus nlocalsym in LC_DYSYMTAB load command " 5892 "extends past the end of the symbol table)"); 5893 goto return_bad; 5894 } 5895 5896 if(dyst->nextdefsym != 0 && 5897 dyst->iextdefsym > st->nsyms){ 5898 Mach_O_error(ofile, "truncated or malformed object " 5899 "(iextdefsym in LC_DYSYMTAB load command extends past " 5900 "the end of the symbol table)"); 5901 goto return_bad; 5902 } 5903 big_size = dyst->iextdefsym; 5904 big_size += dyst->nextdefsym; 5905 if(dyst->nextdefsym != 0 && big_size > st->nsyms){ 5906 Mach_O_error(ofile, "truncated or malformed object " 5907 "(iextdefsym plus nextdefsym in LC_DYSYMTAB load " 5908 "command extends past the end of the symbol table)"); 5909 goto return_bad; 5910 } 5911 5912 if(dyst->nundefsym != 0 && 5913 dyst->iundefsym > st->nsyms){ 5914 Mach_O_error(ofile, "truncated or malformed object " 5915 "(iundefsym in LC_DYSYMTAB load command extends past " 5916 "the end of the symbol table)"); 5917 goto return_bad; 5918 } 5919 big_size = dyst->iundefsym; 5920 big_size += dyst->nundefsym; 5921 if(dyst->nundefsym != 0 && big_size > st->nsyms){ 5922 Mach_O_error(ofile, "truncated or malformed object " 5923 "(iundefsym plus nundefsym in LC_DYSYMTAB load command " 5924 "extends past the end of the symbol table)"); 5925 goto return_bad; 5926 } 5927 if(rc != NULL){ 5928 if(rc->init_module > dyst->nmodtab){ 5929 Mach_O_error(ofile, "malformed object (init_module in " 5930 "LC_ROUTINES load command extends past the " 5931 "end of the module table)"); 5932 goto return_bad; 5933 } 5934 } 5935 if(rc64 != NULL){ 5936 if(rc64->init_module > dyst->nmodtab){ 5937 Mach_O_error(ofile, "malformed object (init_module in " 5938 "LC_ROUTINES_64 load command extends past the " 5939 "end of the module table)"); 5940 goto return_bad; 5941 } 5942 } 5943 if(hints != NULL){ 5944 if(hints->nhints != dyst->nundefsym){ 5945 Mach_O_error(ofile, "malformed object (nhints in " 5946 "LC_TWOLEVEL_HINTS load command not the same as " 5947 "nundefsym in LC_DYSYMTAB load command)"); 5948 goto return_bad; 5949 } 5950 } 5951 } 5952 } 5953 /* check for an inconsistent size of the load commands */ 5954 if((char *)load_commands + sizeofcmds != (char *)lc){ 5955 Mach_O_error(ofile, "malformed object (inconsistent sizeofcmds " 5956 "field in mach header)"); 5957 goto return_bad; 5958 } 5959 5960 /* 5961 * Mark this ofile so we know its headers have been swapped. We do this 5962 * in case we don't process it the first time so we can swap them back 5963 * in case we loop back to it in a fat file to process it later. 5964 */ 5965 if(swapped == TRUE) 5966 ofile->headers_swapped = TRUE; 5967 5968 /* looks good return ok */ 5969 free_elements(&elements); 5970 return(CHECK_GOOD); 5971 5972return_bad: 5973 free_elements(&elements); 5974 return(CHECK_BAD); 5975#endif /* OTOOL */ 5976} 5977 5978/* 5979 * swap_back_Mach_O() is called after the ofile has been processed to swap back 5980 * the mach header and load commands if check_Mach_O() above swapped them. 5981 */ 5982static 5983void 5984swap_back_Mach_O( 5985struct ofile *ofile) 5986{ 5987 if(ofile->headers_swapped == TRUE){ 5988 ofile->headers_swapped = FALSE; 5989 if(ofile->mh != NULL) 5990 swap_object_headers(ofile->mh, ofile->load_commands); 5991 else if(ofile->mh64 != NULL) 5992 swap_object_headers(ofile->mh64, ofile->load_commands); 5993 } 5994} 5995 5996#ifndef OTOOL 5997/* 5998 * check_overlaping_element() checks that the element in the ofile described by 5999 * offset, size and name does not overlap in list of elements in head. If it 6000 * does CHECK_BAD is returned and an error message is generated. If it doesn't 6001 * then an element is added in the ordered list and CHECK_GOOD is returned 6002 */ 6003static 6004enum check_type 6005check_overlaping_element( 6006struct ofile *ofile, 6007struct element *head, 6008uint32_t offset, 6009uint32_t size, 6010char *name) 6011{ 6012 struct element *e, *p, *n; 6013 6014 if(size == 0) 6015 return(CHECK_GOOD); 6016 6017 if(head->next == NULL){ 6018 n = allocate(sizeof(struct element)); 6019 n->offset = offset; 6020 n->size = size; 6021 n->name = name; 6022 n->next = NULL; 6023 head->next = n; 6024 return(CHECK_GOOD); 6025 } 6026 6027 p = NULL; 6028 e = head; 6029 while(e->next != NULL){ 6030 p = e; 6031 e = e->next; 6032 if((offset >= e->offset && 6033 offset < e->offset + e->size) || 6034 (offset + size > e->offset && 6035 offset + size < e->offset + e->size) || 6036 (offset <= e->offset && 6037 offset + size >= e->offset + e->size)){ 6038 Mach_O_error(ofile, "malformed object (%s at offset %u with a " 6039 "size of %u, overlaps %s at offset %u with a size of %u)", 6040 name, offset, size, e->name, e->offset, e->size); 6041 return(CHECK_BAD); 6042 } 6043 if(e->next != NULL && offset + size <= e->next->offset){ 6044 n = allocate(sizeof(struct element)); 6045 n->offset = offset; 6046 n->size = size; 6047 n->name = name; 6048 n->next = e; 6049 p->next = n; 6050 return(CHECK_GOOD); 6051 } 6052 } 6053 n = allocate(sizeof(struct element)); 6054 n->offset = offset; 6055 n->size = size; 6056 n->name = name; 6057 n->next = NULL; 6058 e->next = n; 6059 return(CHECK_GOOD); 6060} 6061 6062/* 6063 * free_elements() frees the list of elements on the list head. 6064 */ 6065static 6066void 6067free_elements( 6068struct element *head) 6069{ 6070 struct element *e, *e_next; 6071 6072 e = head->next; 6073 while(e != NULL){ 6074 e_next = e->next; 6075 free(e); 6076 e = e_next; 6077 } 6078} 6079#endif /* !defined(OTOOL) */ 6080 6081/* 6082 * check_dylib_module() checks the object file's dylib_module as referenced 6083 * by the dylib_module field in the ofile for correctness. 6084 */ 6085static 6086enum check_type 6087check_dylib_module( 6088struct ofile *ofile, 6089struct symtab_command *st, 6090struct dysymtab_command *dyst, 6091char *strings, 6092uint32_t module_index) 6093{ 6094#ifdef OTOOL 6095 return(CHECK_GOOD); 6096#else /* !defined OTOOL */ 6097 uint32_t i; 6098 enum byte_sex host_byte_sex; 6099 enum bool swapped; 6100 struct dylib_module m; 6101 struct dylib_module_64 m64; 6102 uint32_t module_name, nextdefsym, iextdefsym, nlocalsym, ilocalsym, nrefsym; 6103 uint32_t irefsym, nextrel, iextrel; 6104 6105 host_byte_sex = get_host_byte_sex(); 6106 swapped = (enum bool)(host_byte_sex != ofile->object_byte_sex); 6107 if(ofile->mh != NULL){ 6108 m = *ofile->dylib_module; 6109 if(swapped) 6110 swap_dylib_module(&m, 1, host_byte_sex); 6111 module_name = m.module_name; 6112 nextdefsym = m.nextdefsym; 6113 iextdefsym = m.iextdefsym; 6114 nlocalsym = m.nlocalsym; 6115 ilocalsym = m.ilocalsym; 6116 nrefsym = m.nrefsym; 6117 irefsym = m.irefsym; 6118 nextrel = m.nextrel; 6119 iextrel = m.iextrel; 6120 } 6121 else{ 6122 m64 = *ofile->dylib_module64; 6123 if(swapped) 6124 swap_dylib_module_64(&m64, 1, host_byte_sex); 6125 module_name = m64.module_name; 6126 nextdefsym = m64.nextdefsym; 6127 iextdefsym = m64.iextdefsym; 6128 nlocalsym = m64.nlocalsym; 6129 ilocalsym = m64.ilocalsym; 6130 nrefsym = m64.nrefsym; 6131 irefsym = m64.irefsym; 6132 nextrel = m64.nextrel; 6133 iextrel = m64.iextrel; 6134 } 6135 6136 if(module_name > st->strsize){ 6137 Mach_O_error(ofile, "truncated or malformed object (module_name " 6138 "of module table entry %u past the end of the string table)", 6139 module_index); 6140 return(CHECK_BAD); 6141 } 6142 for(i = module_name; i < st->strsize && strings[i] != '\0'; i++) 6143 ; 6144 if(i >= st->strsize){ 6145 Mach_O_error(ofile, "truncated or malformed object (module_name " 6146 "of module table entry %u extends past the end of the string " 6147 "table)", module_index); 6148 return(CHECK_BAD); 6149 } 6150 6151 if(nextdefsym != 0){ 6152 if(iextdefsym > st->nsyms){ 6153 Mach_O_error(ofile, "truncated or malformed object (iextdefsym " 6154 "field of module table entry %u past the end of the " 6155 "symbol table", module_index); 6156 return(CHECK_BAD); 6157 } 6158 if(iextdefsym + nextdefsym > st->nsyms){ 6159 Mach_O_error(ofile, "truncated or malformed object (iextdefsym " 6160 "field of module table entry %u plus nextdefsym field " 6161 "extends past the end of the symbol table", module_index); 6162 return(CHECK_BAD); 6163 } 6164 } 6165 if(nlocalsym != 0){ 6166 if(ilocalsym > st->nsyms){ 6167 Mach_O_error(ofile, "truncated or malformed object (ilocalsym " 6168 "field of module table entry %u past the end of the " 6169 "symbol table", module_index); 6170 return(CHECK_BAD); 6171 } 6172 if(ilocalsym + nlocalsym > st->nsyms){ 6173 Mach_O_error(ofile, "truncated or malformed object (ilocalsym " 6174 "field of module table entry %u plus nlocalsym field " 6175 "extends past the end of the symbol table", module_index); 6176 return(CHECK_BAD); 6177 } 6178 } 6179 if(nrefsym != 0){ 6180 if(irefsym > dyst->nextrefsyms){ 6181 Mach_O_error(ofile, "truncated or malformed object (irefsym " 6182 "field of module table entry %u past the end of the " 6183 "reference table", module_index); 6184 return(CHECK_BAD); 6185 } 6186 if(irefsym + nrefsym > dyst->nextrefsyms){ 6187 Mach_O_error(ofile, "truncated or malformed object (irefsym " 6188 "field of module table entry %u plus nrefsym field " 6189 "extends past the end of the reference table",module_index); 6190 return(CHECK_BAD); 6191 } 6192 } 6193 if(nextrel != 0){ 6194 if(iextrel > dyst->extreloff){ 6195 Mach_O_error(ofile, "truncated or malformed object (iextrel " 6196 "field of module table entry %u past the end of the " 6197 "external relocation enrties", module_index); 6198 return(CHECK_BAD); 6199 } 6200 if(iextrel + nextrel > dyst->extreloff){ 6201 Mach_O_error(ofile, "truncated or malformed object (iextrel " 6202 "field of module table entry %u plus nextrel field " 6203 "extends past the end of the external relocation enrties", 6204 module_index); 6205 return(CHECK_BAD); 6206 } 6207 } 6208 return(CHECK_GOOD); 6209#endif /* OTOOL */ 6210} 6211 6212__private_extern__ 6213uint32_t 6214size_ar_name( 6215const struct ar_hdr *ar_hdr) 6216{ 6217 int32_t i; 6218 6219 i = sizeof(ar_hdr->ar_name) - 1; 6220 if(ar_hdr->ar_name[i] == ' '){ 6221 do{ 6222 if(ar_hdr->ar_name[i] != ' ') 6223 break; 6224 i--; 6225 }while(i > 0); 6226 } 6227 return(i + 1); 6228} 6229#endif /* !defined(RLD) */ 6230