1/* 2 * Copyright (c) 1999 Apple Computer, Inc. All rights reserved. 3 * 4 * @APPLE_LICENSE_HEADER_START@ 5 * 6 * This file contains Original Code and/or Modifications of Original Code 7 * as defined in and that are subject to the Apple Public Source License 8 * Version 2.0 (the 'License'). You may not use this file except in 9 * compliance with the License. Please obtain a copy of the License at 10 * http://www.opensource.apple.com/apsl/ and read it before using this 11 * file. 12 * 13 * The Original Code and all software distributed under the License are 14 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER 15 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, 16 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, 17 * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. 18 * Please see the License for the specific language governing rights and 19 * limitations under the License. 20 * 21 * @APPLE_LICENSE_HEADER_END@ 22 */ 23#include <stdint.h> 24#import <stdio.h> 25#import <stdlib.h> 26#import <string.h> 27#import "stuff/ofile.h" 28#import "stuff/errors.h" 29#import "stuff/allocate.h" 30 31enum file_part_type { 32 FP_FAT_HEADERS, 33 FP_MACH_O, 34 FP_EMPTY_SPACE 35}; 36char *file_part_type_names[] = { 37 "FP_FAT_HEADERS", 38 "FP_MACH_O", 39 "FP_EMPTY_SPACE" 40}; 41 42struct file_part { 43 uint64_t offset; 44 uint64_t size; 45 enum file_part_type type; 46 struct mach_o_part *mp; 47 struct mach_header *mh; 48 struct mach_header_64 *mh64; 49 struct symtab_command *st; 50 struct nlist *symbols; 51 struct nlist_64 *symbols64; 52 char *strings; 53 struct file_part *prev; 54 struct file_part *next; 55}; 56struct file_part *file_parts = NULL; 57 58enum mach_o_part_type { 59 MP_MACH_HEADERS, 60 MP_SECTION, 61 MP_SECTION_64, 62 MP_RELOCS, 63 MP_RELOCS_64, 64 MP_LOCAL_SYMBOLS, 65 MP_EXTDEF_SYMBOLS, 66 MP_UNDEF_SYMBOLS, 67 MP_TOC, 68 MP_MODULE_TABLE, 69 MP_REFERENCE_TABLE, 70 MP_INDIRECT_SYMBOL_TABLE, 71 MP_EXT_RELOCS, 72 MP_LOC_RELOCS, 73 MP_SPLIT_INFO, 74 MP_SYMBOL_TABLE, 75 MP_HINTS_TABLE, 76 MP_STRING_TABLE, 77 MP_EXT_STRING_TABLE, 78 MP_LOC_STRING_TABLE, 79 MP_CODE_SIG, 80 MP_FUNCTION_STARTS, 81 MP_DATA_IN_CODE, 82 MP_CODE_SIGN_DRS, 83 MP_DYLD_INFO_REBASE, 84 MP_DYLD_INFO_BIND, 85 MP_DYLD_INFO_WEAK_BIND, 86 MP_DYLD_INFO_LAZY_BIND, 87 MP_DYLD_INFO_EXPORT, 88 MP_EMPTY_SPACE 89}; 90static char *mach_o_part_type_names[] = { 91 "MP_MACH_HEADERS", 92 "MP_SECTION", 93 "MP_SECTION_64", 94 "MP_RELOCS", 95 "MP_RELOCS_64", 96 "MP_LOCAL_SYMBOLS", 97 "MP_EXTDEF_SYMBOLS", 98 "MP_UNDEF_SYMBOLS", 99 "MP_TOC", 100 "MP_MODULE_TABLE", 101 "MP_REFERENCE_TABLE", 102 "MP_INDIRECT_SYMBOL_TABLE", 103 "MP_EXT_RELOCS", 104 "MP_LOC_RELOCS", 105 "MP_SPLIT_INFO", 106 "MP_SYMBOL_TABLE", 107 "MP_HINTS_TABLE", 108 "MP_STRING_TABLE", 109 "MP_EXT_STRING_TABLE", 110 "MP_LOC_STRING_TABLE", 111 "MP_CODE_SIG", 112 "MP_FUNCTION_STARTS", 113 "MP_DATA_IN_CODE", 114 "MP_CODE_SIGN_DRS", 115 "MP_DYLD_INFO_REBASE", 116 "MP_DYLD_INFO_BIND", 117 "MP_DYLD_INFO_WEAK_BIND", 118 "MP_DYLD_INFO_LAZY_BIND", 119 "MP_DYLD_INFO_EXPORT", 120 "MP_EMPTY_SPACE" 121}; 122 123struct mach_o_part { 124 uint64_t offset; 125 uint64_t size; 126 enum mach_o_part_type type; 127 struct section *s; 128 struct section_64 *s64; 129 struct mach_o_part *prev; 130 struct mach_o_part *next; 131}; 132 133/* The name of the program for error messages */ 134char *progname = NULL; 135 136/* The ofile for the Mach-O file argument to the program */ 137static struct ofile ofile; 138 139/* The -arch flag if any, and its offset and size in the file */ 140static struct arch_flag *arch_flag = NULL; 141uint64_t arch_offset = 0; 142uint64_t arch_size = 0; 143enum bool arch_found = FALSE; 144 145static struct nlist *sorted_symbols = NULL; 146static struct nlist_64 *sorted_symbols64 = NULL; 147 148static void usage(void); 149 150static void create_file_parts( 151 char *file_name); 152static struct file_part *new_file_part( 153 void); 154static void insert_file_part( 155 struct file_part *new); 156static void print_file_parts( 157 void); 158 159static void create_mach_o_parts( 160 struct file_part *fp); 161static struct mach_o_part *new_mach_o_part( 162 void); 163static void insert_mach_o_part( 164 struct file_part *fp, 165 struct mach_o_part *new); 166static void print_mach_o_parts( 167 struct mach_o_part *mp); 168 169static void print_parts_for_page( 170 uint32_t page_number); 171static void print_arch( 172 struct file_part *fp); 173static void print_file_part( 174 struct file_part *fp); 175static void print_mach_o_part( 176 struct mach_o_part *mp); 177static void print_symbols( 178 struct file_part *fp, 179 uint64_t low_addr, 180 uint64_t high_addr); 181static void print_symbols64( 182 struct file_part *fp, 183 uint64_t low_addr, 184 uint64_t high_addr); 185static int compare( 186 struct nlist *p1, 187 struct nlist *p2); 188static int compare64( 189 struct nlist_64 *p1, 190 struct nlist_64 *p2); 191 192/* apple_version is created by the libstuff/Makefile */ 193extern char apple_version[]; 194char *version = apple_version; 195 196/* 197 * pagestuff is invoked as follows: 198 * 199 * % pagestuff mach-o [-arch name] [-p] [-a] pagenumber [pagenumber ...] 200 * 201 * It prints out what stuff is on the page numbers listed. 202 */ 203int 204main( 205int argc, 206char *argv[]) 207{ 208 int i, start; 209 uint32_t j, page_number; 210 char *endp; 211 struct arch_flag a; 212 213 progname = argv[0]; 214 if(argc < 3) 215 usage(); 216 start = 2; 217 218 if(strcmp(argv[start], "-arch") == 0){ 219 if(start + 1 == argc){ 220 error("missing argument to -arch option"); 221 exit(EXIT_FAILURE); 222 } 223 if(get_arch_from_flag(argv[start+1], &a) == 0){ 224 error("unknown architecture specification flag: " 225 "%s %s", argv[start], argv[start+1]); 226 exit(EXIT_FAILURE); 227 } 228 arch_flag = &a; 229 start += 2; 230 if(argc < 5) 231 usage(); 232 } 233 234 create_file_parts(argv[1]); 235 if(arch_flag != NULL && arch_found == FALSE){ 236 error("file: %s does not contain architecture: %s", argv[1], 237 arch_flag->name); 238 exit(EXIT_FAILURE); 239 } 240 if(strcmp(argv[start], "-p") == 0){ 241 print_file_parts(); 242 start++; 243 } 244 if(errors) 245 exit(EXIT_FAILURE); 246 if(start >= argc) 247 exit(EXIT_SUCCESS); 248 249 if(strcmp(argv[start], "-a") == 0){ 250 if(arch_flag == NULL) 251 page_number = (ofile.file_size + vm_page_size - 1) / 252 vm_page_size; 253 else 254 page_number = (arch_size + vm_page_size - 1) / 255 vm_page_size; 256 for(j = 0; j < page_number; j++){ 257 print_parts_for_page(j); 258 } 259 start++; 260 } 261 if(start >= argc) 262 exit(EXIT_SUCCESS); 263 264 for(i = start; i < argc; i++){ 265 page_number = strtoul(argv[i], &endp, 10); 266 if(*endp != '\0') 267 fatal("page number argument: %s is not a proper unsigned " 268 "number", argv[i]); 269 print_parts_for_page(page_number); 270 } 271 272 return(EXIT_SUCCESS); 273} 274 275static 276void 277usage(void) 278{ 279 fprintf(stderr, "Usage: %s mach-o [-arch name] [-p] [-a] " 280 "pagenumber [pagenumber ...]\n", 281 progname); 282 exit(EXIT_FAILURE); 283} 284 285static 286void 287create_file_parts( 288char *file_name) 289{ 290 static struct file_part *fp; 291 292 if(ofile_map(file_name, arch_flag, NULL, &ofile, FALSE) == FALSE) 293 exit(EXIT_FAILURE); 294 295 /* first create an empty space for the whole file */ 296 fp = new_file_part(); 297 fp->offset = 0; 298 fp->size = ofile.file_size; 299 fp->type = FP_EMPTY_SPACE; 300 file_parts = fp; 301 302 if(ofile.file_type == OFILE_FAT){ 303 fp = new_file_part(); 304 fp->offset = 0; 305 fp->size = sizeof(struct fat_header) + 306 ofile.fat_header->nfat_arch * sizeof(struct fat_arch); 307 fp->type = FP_FAT_HEADERS; 308 insert_file_part(fp); 309 310 (void)ofile_first_arch(&ofile); 311 do{ 312 if(ofile.arch_type == OFILE_ARCHIVE){ 313 error("for architecture: %s file: %s is an archive (not " 314 "supported with %s)", ofile.arch_flag.name, file_name, 315 progname); 316 } 317 else if(ofile.arch_type == OFILE_Mach_O){ 318 if(arch_flag != NULL && arch_found == FALSE && 319 arch_flag->cputype == ofile.mh_cputype && 320 (arch_flag->cpusubtype & ~CPU_SUBTYPE_MASK) == 321 (ofile.mh_cpusubtype & ~CPU_SUBTYPE_MASK)){ 322 arch_offset = ofile.fat_archs[ofile.narch].offset; 323 arch_size = ofile.fat_archs[ofile.narch].size; 324 arch_found = TRUE; 325 } 326 /* make mach-o parts for this */ 327 fp = new_file_part(); 328 fp->offset = ofile.fat_archs[ofile.narch].offset; 329 fp->size = ofile.fat_archs[ofile.narch].size; 330 fp->type = FP_MACH_O; 331 insert_file_part(fp); 332 create_mach_o_parts(fp); 333 } 334 else if(ofile.arch_type == OFILE_UNKNOWN){ 335 error("for architecture: %s file: %s is not an object file " 336 "(not supported with %s)", ofile.arch_flag.name, 337 file_name, progname); 338 } 339 }while(ofile_next_arch(&ofile) == TRUE); 340 } 341 else if(ofile.file_type == OFILE_ARCHIVE){ 342 error("file: %s is an archive (not supported with %s)", file_name, 343 progname); 344 } 345 else if(ofile.file_type == OFILE_Mach_O){ 346 if(arch_flag != NULL && arch_found == FALSE && 347 arch_flag->cputype == ofile.mh_cputype && 348 (arch_flag->cpusubtype & ~CPU_SUBTYPE_MASK) == 349 (ofile.mh_cpusubtype & ~CPU_SUBTYPE_MASK)){ 350 arch_offset = 0; 351 arch_size = ofile.file_size; 352 arch_found = TRUE; 353 } 354 /* make mach-o parts for this */ 355 fp = new_file_part(); 356 fp->offset = 0; 357 fp->size = ofile.file_size; 358 fp->type = FP_MACH_O; 359 insert_file_part(fp); 360 create_mach_o_parts(fp); 361 } 362 else{ /* ofile.file_type == OFILE_UNKNOWN */ 363 error("file: %s is not an object file (not supported with %s)", 364 file_name, progname); 365 } 366} 367 368static 369struct file_part * 370new_file_part( 371void) 372{ 373 struct file_part *fp; 374 375 fp = allocate(sizeof(struct file_part)); 376 memset(fp, '\0', sizeof(struct file_part)); 377 return(fp); 378} 379 380static 381void 382insert_file_part( 383struct file_part *new) 384{ 385 struct file_part *p, *q; 386 387 for(p = file_parts; p != NULL; p = p->next){ 388 /* find an existing part that contains the new part */ 389 if(new->offset >= p->offset && 390 new->offset + new->size <= p->offset + p->size){ 391 if(p->type != FP_EMPTY_SPACE) 392 fatal("internal error: new file part not contained in " 393 "empty space"); 394 /* if new is the same as p replace p with new */ 395 if(new->offset == p->offset && 396 new->size == p->size){ 397 new->prev = p->prev; 398 new->next = p->next; 399 if(p->next != NULL) 400 p->next->prev = new; 401 if(p->prev != NULL) 402 p->prev->next = new; 403 if(file_parts == p) 404 file_parts = new; 405 free(p); 406 return; 407 } 408 /* if new starts at p put new before p and move p's offset */ 409 if(new->offset == p->offset){ 410 p->offset = new->offset + new->size; 411 p->size = p->size - new->size; 412 if(p->prev != NULL) 413 p->prev->next = new; 414 new->prev = p->prev; 415 p->prev = new; 416 new->next = p; 417 if(file_parts == p) 418 file_parts = new; 419 return; 420 } 421 /* if new ends at p put new after p and change p's size */ 422 if(new->offset + new->size == p->offset + p->size){ 423 p->size = new->offset - p->offset; 424 new->next = p->next; 425 if(p->next != NULL) 426 p->next->prev = new; 427 p->next = new; 428 new->prev = p; 429 return; 430 } 431 /* new is in the middle of p */ 432 q = new_file_part(); 433 q->type = FP_EMPTY_SPACE; 434 q->offset = new->offset + new->size; 435 q->size = p->offset + p->size - (new->offset + new->size); 436 p->size = new->offset - p->offset; 437 new->prev = p; 438 new->next = q; 439 q->prev = new; 440 q->next = p->next; 441 if(p->next != NULL) 442 p->next->prev = q; 443 p->next = new; 444 return; 445 } 446 } 447 fatal("internal error: new file part not found in existing part"); 448} 449 450static 451void 452print_file_parts( 453void) 454{ 455 struct file_part *p, *prev; 456 uint64_t offset; 457 458 prev = NULL; 459 offset = 0; 460 for(p = file_parts; p != NULL; p = p->next){ 461 if(arch_flag == NULL){ 462 printf("%s\n", file_part_type_names[p->type]); 463 printf(" offset = %llu\n", p->offset); 464 printf(" size = %llu\n", p->size); 465 } 466 if(prev != NULL) 467 if(prev != p->prev) 468 printf("bad prev pointer\n"); 469 prev = p; 470 if(offset != p->offset) 471 printf("bad offset\n"); 472 offset += p->size; 473 if(p->type == FP_MACH_O){ 474 if(arch_flag == NULL || p->offset == arch_offset) 475 print_mach_o_parts(p->mp); 476 } 477 } 478} 479 480static 481void 482create_mach_o_parts( 483struct file_part *fp) 484{ 485 uint32_t i, j; 486 uint32_t ncmds, filetype; 487 struct mach_o_part *mp; 488 struct load_command *lc; 489 struct symtab_command *st; 490 struct dysymtab_command *dyst; 491 struct dyld_info_command *dyld_info; 492 struct twolevel_hints_command *hints; 493 struct segment_command *sg; 494 struct segment_command_64 *sg64; 495 struct section *s; 496 struct section_64 *s64; 497 struct nlist *allocated_symbols, *symbols; 498 struct nlist_64 *allocated_symbols64, *symbols64; 499 uint32_t ext_low, ext_high, local_low, local_high, n_strx, n_type; 500 char *strings; 501 struct dylib_module *modtab; 502 struct dylib_module_64 *modtab64; 503 struct linkedit_data_command *split_info, *code_sig, *func_starts, 504 *data_in_code, *code_sign_drs; 505 enum bool dylib_stub; 506 507 mp = new_mach_o_part(); 508 mp->offset = fp->offset; 509 mp->size = ofile.object_size; 510 mp->type = MP_EMPTY_SPACE; 511 fp->mp = mp; 512 513 mp = new_mach_o_part(); 514 mp->offset = fp->offset; 515 if(ofile.mh != NULL){ 516 fp->mh = ofile.mh; 517 fp->mh64 = NULL; 518 mp->size = sizeof(struct mach_header) + ofile.mh->sizeofcmds; 519 ncmds = ofile.mh->ncmds; 520 dylib_stub = ofile.mh->filetype == MH_DYLIB_STUB; 521 } 522 else{ 523 fp->mh64 = ofile.mh64; 524 fp->mh = NULL; 525 mp->size = sizeof(struct mach_header_64) + ofile.mh64->sizeofcmds; 526 ncmds = ofile.mh64->ncmds; 527 dylib_stub = ofile.mh64->filetype == MH_DYLIB_STUB; 528 } 529 mp->type = MP_MACH_HEADERS; 530 insert_mach_o_part(fp, mp); 531 532 533 st = NULL; 534 dyst = NULL; 535 dyld_info = NULL; 536 hints = NULL; 537 symbols = NULL; 538 symbols64 = NULL; 539 strings = NULL; 540 split_info = NULL; 541 code_sig = NULL; 542 func_starts = NULL; 543 data_in_code = NULL; 544 code_sign_drs = NULL; 545 546 lc = ofile.load_commands; 547 for(i = 0; i < ncmds; i++){ 548 if(st == NULL && lc->cmd == LC_SYMTAB){ 549 st = (struct symtab_command *)lc; 550 } 551 else if(dyst == NULL && lc->cmd == LC_DYSYMTAB){ 552 dyst = (struct dysymtab_command *)lc; 553 } 554 else if(dyld_info == NULL && lc->cmd == LC_DYLD_INFO_ONLY){ 555 dyld_info = (struct dyld_info_command *)lc; 556 } 557 else if(hints == NULL && lc->cmd == LC_TWOLEVEL_HINTS){ 558 hints = (struct twolevel_hints_command *)lc; 559 } 560 else if(split_info == NULL && lc->cmd == LC_SEGMENT_SPLIT_INFO){ 561 split_info = (struct linkedit_data_command *)lc; 562 } 563 else if(code_sig == NULL && lc->cmd == LC_CODE_SIGNATURE){ 564 code_sig = (struct linkedit_data_command *)lc; 565 } 566 else if(func_starts == NULL && lc->cmd == LC_FUNCTION_STARTS){ 567 func_starts = (struct linkedit_data_command *)lc; 568 } 569 else if(data_in_code == NULL && lc->cmd == LC_DATA_IN_CODE){ 570 data_in_code = (struct linkedit_data_command *)lc; 571 } 572 else if(code_sign_drs == NULL && lc->cmd == LC_DYLIB_CODE_SIGN_DRS){ 573 code_sign_drs = (struct linkedit_data_command *)lc; 574 } 575 else if(lc->cmd == LC_SEGMENT && dylib_stub == FALSE){ 576 sg = (struct segment_command *)lc; 577 s = (struct section *) 578 ((char *)sg + sizeof(struct segment_command)); 579 for(j = 0; j < sg->nsects; j++){ 580 if(s->nreloc != 0){ 581 mp = new_mach_o_part(); 582 mp->offset = fp->offset + s->reloff; 583 mp->size = s->nreloc * sizeof(struct relocation_info); 584 mp->type = MP_RELOCS; 585 mp->s = s; 586 mp->s64 = NULL; 587 insert_mach_o_part(fp, mp); 588 } 589 if((s->flags & SECTION_TYPE) != S_ZEROFILL && 590 (s->flags & SECTION_TYPE) != S_THREAD_LOCAL_ZEROFILL && 591 s->size != 0){ 592 mp = new_mach_o_part(); 593 mp->offset = fp->offset + s->offset; 594 mp->size = s->size; 595 mp->type = MP_SECTION; 596 mp->s = s; 597 mp->s64 = NULL; 598 insert_mach_o_part(fp, mp); 599 } 600 if(((s->flags & SECTION_TYPE) == S_ZEROFILL || 601 (s->flags & SECTION_TYPE) == S_THREAD_LOCAL_ZEROFILL) && 602 s->size != 0){ 603 if(s->addr - sg->vmaddr < sg->filesize){ 604 mp = new_mach_o_part(); 605 mp->offset = fp->offset + sg->fileoff + 606 s->addr - sg->vmaddr; 607 if(s->addr - sg->vmaddr + s->size <= sg->filesize) 608 mp->size = s->size; 609 else 610 mp->size = sg->filesize -(s->addr - sg->vmaddr); 611 mp->type = MP_SECTION; 612 mp->s = s; 613 mp->s64 = NULL; 614 insert_mach_o_part(fp, mp); 615 } 616 } 617 s++; 618 } 619 } 620 else if(lc->cmd == LC_SEGMENT_64 && dylib_stub == FALSE){ 621 sg64 = (struct segment_command_64 *)lc; 622 s64 = (struct section_64 *) 623 ((char *)sg64 + sizeof(struct segment_command_64)); 624 for(j = 0; j < sg64->nsects; j++){ 625 if(s64->nreloc != 0){ 626 mp = new_mach_o_part(); 627 mp->offset = fp->offset + s64->reloff; 628 mp->size = s64->nreloc * sizeof(struct relocation_info); 629 mp->type = MP_RELOCS_64; 630 mp->s64 = s64; 631 mp->s = NULL; 632 insert_mach_o_part(fp, mp); 633 } 634 if((s64->flags & SECTION_TYPE) != S_ZEROFILL && 635 (s64->flags & SECTION_TYPE) != S_THREAD_LOCAL_ZEROFILL && 636 s64->size != 0){ 637 mp = new_mach_o_part(); 638 mp->offset = fp->offset + s64->offset; 639 mp->size = s64->size; 640 mp->type = MP_SECTION_64; 641 mp->s64 = s64; 642 mp->s = NULL; 643 insert_mach_o_part(fp, mp); 644 } 645 if(((s64->flags & SECTION_TYPE) == S_ZEROFILL || 646 (s64->flags & SECTION_TYPE) == 647 S_THREAD_LOCAL_ZEROFILL) && 648 s64->size != 0){ 649 if(s64->addr - sg64->vmaddr < sg64->filesize){ 650 mp = new_mach_o_part(); 651 mp->offset = fp->offset + sg64->fileoff + 652 s64->addr - sg64->vmaddr; 653 if(s64->addr - sg64->vmaddr + s64->size <= 654 sg64->filesize) 655 mp->size = s64->size; 656 else 657 mp->size = sg64->filesize - 658 (s64->addr - sg64->vmaddr); 659 mp->type = MP_SECTION_64; 660 mp->s64 = s64; 661 mp->s = NULL; 662 insert_mach_o_part(fp, mp); 663 } 664 } 665 s64++; 666 } 667 } 668 lc = (struct load_command *)((char *)lc + lc->cmdsize); 669 } 670 if(st != NULL){ 671 if(ofile.mh != NULL){ 672 allocated_symbols = NULL; 673 symbols = (struct nlist *)(ofile.object_addr + st->symoff); 674 if(ofile.object_byte_sex != get_host_byte_sex()){ 675 allocated_symbols = allocate(sizeof(struct nlist) * 676 st->nsyms); 677 memcpy(allocated_symbols, symbols, 678 sizeof(struct nlist) * st->nsyms); 679 swap_nlist(allocated_symbols, st->nsyms, 680 get_host_byte_sex()); 681 symbols = allocated_symbols; 682 } 683 fp->symbols = symbols; 684 fp->symbols64 = NULL; 685 } 686 else{ 687 allocated_symbols64 = NULL; 688 symbols64 = (struct nlist_64 *)(ofile.object_addr + st->symoff); 689 if(ofile.object_byte_sex != get_host_byte_sex()){ 690 allocated_symbols64 = allocate(sizeof(struct nlist_64) * 691 st->nsyms); 692 memcpy(allocated_symbols64, symbols64, 693 sizeof(struct nlist_64) * st->nsyms); 694 swap_nlist_64(allocated_symbols64, st->nsyms, 695 get_host_byte_sex()); 696 symbols64 = allocated_symbols64; 697 } 698 fp->symbols64 = symbols64; 699 fp->symbols = NULL; 700 } 701 strings = ofile.object_addr + st->stroff; 702 fp->st = st; 703 fp->strings = strings; 704 } 705 706 if(dyst != NULL && st != NULL){ 707 if(dyst->nlocalsym != 0){ 708 mp = new_mach_o_part(); 709 if(ofile.mh != NULL){ 710 mp->offset = fp->offset + st->symoff + 711 dyst->ilocalsym * sizeof(struct nlist); 712 mp->size = dyst->nlocalsym * sizeof(struct nlist); 713 } 714 else{ 715 mp->offset = fp->offset + st->symoff + 716 dyst->ilocalsym * sizeof(struct nlist_64); 717 mp->size = dyst->nlocalsym * sizeof(struct nlist_64); 718 } 719 mp->type = MP_LOCAL_SYMBOLS; 720 insert_mach_o_part(fp, mp); 721 } 722 if(dyst->nextdefsym != 0){ 723 mp = new_mach_o_part(); 724 if(ofile.mh != NULL){ 725 mp->offset = fp->offset + st->symoff + 726 dyst->iextdefsym * sizeof(struct nlist); 727 mp->size = dyst->nextdefsym * sizeof(struct nlist); 728 } 729 else{ 730 mp->offset = fp->offset + st->symoff + 731 dyst->iextdefsym * sizeof(struct nlist_64); 732 mp->size = dyst->nextdefsym * sizeof(struct nlist_64); 733 } 734 mp->type = MP_EXTDEF_SYMBOLS; 735 insert_mach_o_part(fp, mp); 736 } 737 if(dyst->nundefsym != 0){ 738 mp = new_mach_o_part(); 739 if(ofile.mh != NULL){ 740 mp->offset = fp->offset + st->symoff + 741 dyst->iundefsym * sizeof(struct nlist); 742 mp->size = dyst->nundefsym * sizeof(struct nlist); 743 } 744 else{ 745 mp->offset = fp->offset + st->symoff + 746 dyst->iundefsym * sizeof(struct nlist_64); 747 mp->size = dyst->nundefsym * sizeof(struct nlist_64); 748 } 749 mp->type = MP_UNDEF_SYMBOLS; 750 insert_mach_o_part(fp, mp); 751 } 752 if(hints != NULL && hints->nhints != 0){ 753 mp = new_mach_o_part(); 754 mp->offset = fp->offset + hints->offset; 755 mp->size = hints->nhints * 756 sizeof(struct twolevel_hint); 757 mp->type = MP_HINTS_TABLE; 758 insert_mach_o_part(fp, mp); 759 } 760 if(split_info != NULL && split_info->datasize != 0){ 761 mp = new_mach_o_part(); 762 mp->offset = fp->offset + split_info->dataoff; 763 mp->size = split_info->datasize; 764 mp->type = MP_SPLIT_INFO; 765 insert_mach_o_part(fp, mp); 766 } 767 if(dyst->ntoc != 0){ 768 mp = new_mach_o_part(); 769 mp->offset = fp->offset + dyst->tocoff; 770 mp->size = dyst->ntoc * sizeof(struct dylib_table_of_contents); 771 mp->type = MP_TOC; 772 insert_mach_o_part(fp, mp); 773 } 774 if(dyst->nmodtab != 0){ 775 mp = new_mach_o_part(); 776 mp->offset = fp->offset + dyst->modtaboff; 777 if(ofile.mh != NULL) 778 mp->size = dyst->nmodtab * sizeof(struct dylib_module); 779 else 780 mp->size = dyst->nmodtab * sizeof(struct dylib_module_64); 781 mp->type = MP_MODULE_TABLE; 782 insert_mach_o_part(fp, mp); 783 } 784 if(dyst->nextrefsyms != 0){ 785 mp = new_mach_o_part(); 786 mp->offset = fp->offset + dyst->extrefsymoff; 787 mp->size = dyst->nextrefsyms * sizeof(struct dylib_reference); 788 mp->type = MP_REFERENCE_TABLE; 789 insert_mach_o_part(fp, mp); 790 } 791 if(dyst->nindirectsyms != 0){ 792 mp = new_mach_o_part(); 793 mp->offset = fp->offset + dyst->indirectsymoff; 794 mp->size = dyst->nindirectsyms * sizeof(uint32_t); 795 mp->type = MP_INDIRECT_SYMBOL_TABLE; 796 insert_mach_o_part(fp, mp); 797 } 798 if(dyst->nextrel != 0){ 799 mp = new_mach_o_part(); 800 mp->offset = fp->offset + dyst->extreloff; 801 mp->size = dyst->nextrel * sizeof(struct relocation_info); 802 mp->type = MP_EXT_RELOCS; 803 insert_mach_o_part(fp, mp); 804 } 805 if(dyst->nlocrel != 0){ 806 mp = new_mach_o_part(); 807 mp->offset = fp->offset + dyst->locreloff; 808 mp->size = dyst->nlocrel * sizeof(struct relocation_info); 809 mp->type = MP_LOC_RELOCS; 810 insert_mach_o_part(fp, mp); 811 } 812 if(dyst->nlocalsym != 0 && 813 (dyst->nextdefsym != 0 || dyst->nundefsym != 0)){ 814 /* 815 * Try to break the string table into the local and external 816 * parts knowing the tools should put all the external strings 817 * first and all the local string last. 818 */ 819 ext_low = st->strsize; 820 local_low = st->strsize; 821 ext_high = 0; 822 local_high = 0; 823 for(i = 0; i < st->nsyms; i++){ 824 if(ofile.mh != NULL){ 825 n_strx = symbols[i].n_un.n_strx; 826 n_type = symbols[i].n_type; 827 filetype = fp->mh->filetype; 828 } 829 else{ 830 n_strx = symbols64[i].n_un.n_strx; 831 n_type = symbols64[i].n_type; 832 filetype = fp->mh64->filetype; 833 } 834 if(n_strx == 0) 835 continue; 836 /* 837 * If this object has any bad string indexes don't try to 838 * break the string table into the local and external 839 * parts. 840 */ 841 if(n_strx > st->strsize){ 842 ext_low = st->strsize; 843 local_low = st->strsize; 844 ext_high = 0; 845 local_high = 0; 846 break; 847 } 848 if(n_type & N_EXT || 849 (filetype == MH_EXECUTE && n_type & N_PEXT)){ 850 if(n_strx > ext_high) 851 ext_high = n_strx; 852 if(n_strx < ext_low) 853 ext_low = n_strx; 854 } 855 else{ 856 if(n_strx > local_high) 857 local_high = n_strx; 858 if(n_strx < local_low) 859 local_low = n_strx; 860 } 861 } 862 863 if(ofile.mh != NULL){ 864 modtab = (struct dylib_module *)(ofile.object_addr + 865 dyst->modtaboff); 866 if(ofile.object_byte_sex != get_host_byte_sex()) 867 swap_dylib_module(modtab, dyst->nmodtab, 868 get_host_byte_sex()); 869 for(i = 0; i < dyst->nmodtab; i++){ 870 if(modtab[i].module_name > local_high) 871 local_high = modtab[i].module_name; 872 if(modtab[i].module_name < local_low) 873 local_low = modtab[i].module_name; 874 } 875 } 876 else{ 877 modtab64 = (struct dylib_module_64 *)(ofile.object_addr + 878 dyst->modtaboff); 879 if(ofile.object_byte_sex != get_host_byte_sex()) 880 swap_dylib_module_64(modtab64, dyst->nmodtab, 881 get_host_byte_sex()); 882 for(i = 0; i < dyst->nmodtab; i++){ 883 if(modtab64[i].module_name > local_high) 884 local_high = modtab64[i].module_name; 885 if(modtab64[i].module_name < local_low) 886 local_low = modtab64[i].module_name; 887 } 888 } 889 890 if(ext_high < local_low && local_low < local_high){ 891 mp = new_mach_o_part(); 892 mp->offset = fp->offset + st->stroff + ext_low; 893 mp->size = ext_high - ext_low + 894 strlen(strings + ext_high) + 1; 895 mp->type = MP_EXT_STRING_TABLE; 896 insert_mach_o_part(fp, mp); 897 898 mp = new_mach_o_part(); 899 mp->offset = fp->offset + st->stroff + local_low; 900 mp->size = local_high - local_low + 901 strlen(strings + local_high) + 1; 902 mp->type = MP_LOC_STRING_TABLE; 903 insert_mach_o_part(fp, mp); 904 } 905 else{ 906 mp = new_mach_o_part(); 907 mp->offset = fp->offset + st->stroff; 908 mp->size = st->strsize; 909 mp->type = MP_STRING_TABLE; 910 insert_mach_o_part(fp, mp); 911 } 912 } 913 else if(dyst->nextdefsym != 0 || dyst->nundefsym != 0){ 914 if(st->strsize != 0){ 915 mp = new_mach_o_part(); 916 mp->offset = fp->offset + st->stroff; 917 mp->size = st->strsize; 918 mp->type = MP_EXT_STRING_TABLE; 919 insert_mach_o_part(fp, mp); 920 } 921 } 922 else{ 923 if(st->strsize != 0){ 924 mp = new_mach_o_part(); 925 mp->offset = fp->offset + st->stroff; 926 mp->size = st->strsize; 927 mp->type = MP_LOC_STRING_TABLE; 928 insert_mach_o_part(fp, mp); 929 } 930 } 931 } 932 else if(st != NULL){ 933 if(st->nsyms != 0){ 934 mp = new_mach_o_part(); 935 mp->offset = fp->offset + st->symoff; 936 if(ofile.mh != NULL) 937 mp->size = st->nsyms * sizeof(struct nlist); 938 else 939 mp->size = st->nsyms * sizeof(struct nlist_64); 940 mp->type = MP_SYMBOL_TABLE; 941 insert_mach_o_part(fp, mp); 942 } 943 if(st->strsize != 0){ 944 mp = new_mach_o_part(); 945 mp->offset = fp->offset + st->stroff; 946 mp->size = st->strsize; 947 mp->type = MP_STRING_TABLE; 948 insert_mach_o_part(fp, mp); 949 } 950 } 951 if(dyld_info != NULL){ 952 if(dyld_info->rebase_size != 0){ 953 mp = new_mach_o_part(); 954 mp->offset = fp->offset + dyld_info->rebase_off; 955 mp->size = dyld_info->rebase_size; 956 mp->type = MP_DYLD_INFO_REBASE; 957 insert_mach_o_part(fp, mp); 958 } 959 if(dyld_info->bind_size != 0){ 960 mp = new_mach_o_part(); 961 mp->offset = fp->offset + dyld_info->bind_off; 962 mp->size = dyld_info->bind_size; 963 mp->type = MP_DYLD_INFO_BIND; 964 insert_mach_o_part(fp, mp); 965 } 966 if(dyld_info->weak_bind_size != 0){ 967 mp = new_mach_o_part(); 968 mp->offset = fp->offset + dyld_info->weak_bind_off; 969 mp->size = dyld_info->weak_bind_size; 970 mp->type = MP_DYLD_INFO_WEAK_BIND; 971 insert_mach_o_part(fp, mp); 972 } 973 if(dyld_info->lazy_bind_size != 0){ 974 mp = new_mach_o_part(); 975 mp->offset = fp->offset + dyld_info->lazy_bind_off; 976 mp->size = dyld_info->lazy_bind_size; 977 mp->type = MP_DYLD_INFO_LAZY_BIND; 978 insert_mach_o_part(fp, mp); 979 } 980 if(dyld_info->export_size != 0){ 981 mp = new_mach_o_part(); 982 mp->offset = fp->offset + dyld_info->export_off; 983 mp->size = dyld_info->export_size; 984 mp->type = MP_DYLD_INFO_EXPORT; 985 insert_mach_o_part(fp, mp); 986 } 987 } 988 if(code_sig != NULL && code_sig->datasize != 0){ 989 mp = new_mach_o_part(); 990 mp->offset = fp->offset + code_sig->dataoff; 991 mp->size = code_sig->datasize; 992 mp->type = MP_CODE_SIG; 993 insert_mach_o_part(fp, mp); 994 } 995 if(func_starts != NULL && func_starts->datasize != 0){ 996 mp = new_mach_o_part(); 997 mp->offset = fp->offset + func_starts->dataoff; 998 mp->size = func_starts->datasize; 999 mp->type = MP_FUNCTION_STARTS; 1000 insert_mach_o_part(fp, mp); 1001 } 1002 if(data_in_code != NULL && data_in_code->datasize != 0){ 1003 mp = new_mach_o_part(); 1004 mp->offset = fp->offset + data_in_code->dataoff; 1005 mp->size = data_in_code->datasize; 1006 mp->type = MP_DATA_IN_CODE; 1007 insert_mach_o_part(fp, mp); 1008 } 1009 if(code_sign_drs != NULL && code_sign_drs->datasize != 0){ 1010 mp = new_mach_o_part(); 1011 mp->offset = fp->offset + code_sign_drs->dataoff; 1012 mp->size = code_sign_drs->datasize; 1013 mp->type = MP_CODE_SIGN_DRS; 1014 insert_mach_o_part(fp, mp); 1015 } 1016} 1017 1018static 1019struct mach_o_part * 1020new_mach_o_part( 1021void) 1022{ 1023 struct mach_o_part *mp; 1024 1025 mp = allocate(sizeof(struct mach_o_part)); 1026 memset(mp, '\0', sizeof(struct mach_o_part)); 1027 return(mp); 1028} 1029 1030static 1031void 1032insert_mach_o_part( 1033struct file_part *fp, 1034struct mach_o_part *new) 1035{ 1036 struct mach_o_part *p, *q; 1037 1038 for(p = fp->mp; p != NULL; p = p->next){ 1039 /* find an existing part that contains the new part */ 1040 if(new->offset >= p->offset && 1041 new->offset + new->size <= p->offset + p->size){ 1042 if(p->type != MP_EMPTY_SPACE) 1043 fatal("internal error: new mach_o part not contained in " 1044 "empty space"); 1045 /* if new is the same as p replace p with new */ 1046 if(new->offset == p->offset && 1047 new->size == p->size){ 1048 new->prev = p->prev; 1049 new->next = p->next; 1050 if(p->next != NULL) 1051 p->next->prev = new; 1052 if(p->prev != NULL) 1053 p->prev->next = new; 1054 if(fp->mp == p) 1055 fp->mp = new; 1056 free(p); 1057 return; 1058 } 1059 /* if new starts at p put new before p and move p's offset */ 1060 if(new->offset == p->offset){ 1061 p->offset = new->offset + new->size; 1062 p->size = p->size - new->size; 1063 new->prev = p->prev; 1064 if(p->prev != NULL) 1065 p->prev->next = new; 1066 p->prev = new; 1067 new->next = p; 1068 if(fp->mp == p) 1069 fp->mp = new; 1070 return; 1071 } 1072 /* if new ends at p put new after p and change p's size */ 1073 if(new->offset + new->size == p->offset + p->size){ 1074 p->size = new->offset - p->offset; 1075 new->next = p->next; 1076 if(p->next != NULL) 1077 p->next->prev = new; 1078 p->next = new; 1079 new->prev = p; 1080 return; 1081 } 1082 /* new is in the middle of p */ 1083 q = new_mach_o_part(); 1084 q->type = MP_EMPTY_SPACE; 1085 q->offset = new->offset + new->size; 1086 q->size = p->offset + p->size - (new->offset + new->size); 1087 p->size = new->offset - p->offset; 1088 new->prev = p; 1089 new->next = q; 1090 q->prev = new; 1091 q->next = p->next; 1092 if(p->next != NULL) 1093 p->next->prev = q; 1094 p->next = new; 1095 return; 1096 } 1097 } 1098 fatal("internal error: new mach_o part not found in existing part"); 1099} 1100 1101static 1102void 1103print_mach_o_parts( 1104struct mach_o_part *mp) 1105{ 1106 struct mach_o_part *p, *prev; 1107 uint32_t offset; 1108 char *indent; 1109 1110 if(arch_flag == NULL) 1111 indent = " "; 1112 else 1113 indent = ""; 1114 offset = 0; 1115 prev = NULL; 1116 if(mp != NULL) 1117 offset = mp->offset; 1118 for(p = mp; p != NULL; p = p->next){ 1119 if(p->type == MP_SECTION) 1120 printf("%sMP_SECTION (%.16s,%.16s)\n", indent, 1121 p->s->segname, p->s->sectname); 1122 else if(p->type == MP_SECTION_64) 1123 printf("%sMP_SECTION_64 (%.16s,%.16s)\n", indent, 1124 p->s64->segname, p->s64->sectname); 1125 else 1126 printf("%s%s\n", indent, mach_o_part_type_names[p->type]); 1127 printf("%s offset = %llu\n", indent, p->offset - arch_offset); 1128 printf("%s size = %llu\n", indent, p->size); 1129 if(prev != NULL) 1130 if(prev != p->prev) 1131 printf("bad prev pointer\n"); 1132 prev = p; 1133 if(offset != p->offset) 1134 printf("bad offset\n"); 1135 offset += p->size; 1136 } 1137} 1138 1139static 1140void 1141print_parts_for_page( 1142uint32_t page_number) 1143{ 1144 uint64_t offset, size, low_addr, high_addr, new_low_addr, new_high_addr; 1145 struct file_part *fp; 1146 struct mach_o_part *mp; 1147 enum bool printed; 1148 enum bool sections, sections64; 1149 const char *arch_name; 1150 1151 offset = page_number * vm_page_size; 1152 size = vm_page_size; 1153 low_addr = 0; 1154 high_addr = 0; 1155 1156 if(arch_flag == NULL){ 1157 if(offset > ofile.file_size){ 1158 printf("File has no page %u (file has only %u pages)\n", 1159 page_number, (uint32_t)((ofile.file_size + 1160 vm_page_size -1) / 1161 vm_page_size)); 1162 return; 1163 } 1164 } 1165 else{ 1166 if(offset > arch_size){ 1167 printf("File for architecture %s has no page %u (has only %u " 1168 "pages)\n", arch_flag->name, 1169 page_number, (uint32_t)((arch_size + 1170 vm_page_size -1) / 1171 vm_page_size)); 1172 return; 1173 } 1174 } 1175 1176 /* 1177 * First pass through the file printing whats on the page ignoring the 1178 * empty spaces. 1179 */ 1180 printed = FALSE; 1181 for(fp = file_parts; fp != NULL; fp = fp->next){ 1182 if(offset + size <= fp->offset - arch_offset) 1183 continue; 1184 if(offset > fp->offset - arch_offset + fp->size) 1185 continue; 1186 switch(fp->type){ 1187 case FP_FAT_HEADERS: 1188 printf("File Page %u contains fat file headers\n", 1189 page_number); 1190 printed = TRUE; 1191 break; 1192 case FP_MACH_O: 1193 sections = FALSE; 1194 sections64 = FALSE; 1195 for(mp = fp->mp; mp != NULL; mp = mp->next){ 1196 if(offset + size <= mp->offset - arch_offset) 1197 continue; 1198 if(offset > mp->offset - arch_offset + mp->size) 1199 continue; 1200 switch(mp->type){ 1201 case MP_MACH_HEADERS: 1202 printf("File Page %u contains Mach-O headers", 1203 page_number); 1204 print_arch(fp); 1205 printed = TRUE; 1206 break; 1207 case MP_SECTION: 1208 printf("File Page %u contains contents of " 1209 "section (%.16s,%.16s)", page_number, 1210 mp->s->segname, mp->s->sectname); 1211 print_arch(fp); 1212 printed = TRUE; 1213 if(offset < mp->offset - arch_offset) 1214 new_low_addr = mp->s->addr; 1215 else 1216 new_low_addr = mp->s->addr + offset - mp->offset - 1217 arch_offset; 1218 if(offset + size > mp->offset - arch_offset + mp->size) 1219 new_high_addr = mp->s->addr + mp->s->size; 1220 else 1221 new_high_addr = mp->s->addr + 1222 (offset + size - (mp->offset - arch_offset)); 1223 if(sections == FALSE){ 1224 low_addr = new_low_addr; 1225 high_addr = new_high_addr; 1226 } 1227 else{ 1228 if(new_low_addr < low_addr) 1229 low_addr = new_low_addr; 1230 if(new_high_addr > high_addr) 1231 high_addr = new_high_addr; 1232 } 1233 sections = TRUE; 1234 break; 1235 case MP_SECTION_64: 1236 printf("File Page %u contains contents of " 1237 "section (%.16s,%.16s)", page_number, 1238 mp->s64->segname, mp->s64->sectname); 1239 print_arch(fp); 1240 printed = TRUE; 1241 if(offset < mp->offset - arch_offset) 1242 new_low_addr = mp->s64->addr; 1243 else 1244 new_low_addr = mp->s64->addr + offset - 1245 (mp->offset - arch_offset); 1246 if(offset + size > (mp->offset - arch_offset) + 1247 mp->size) 1248 new_high_addr = mp->s64->addr + mp->s64->size; 1249 else 1250 new_high_addr = mp->s64->addr + 1251 (offset + size - (mp->offset - arch_offset)); 1252 if(sections64 == FALSE){ 1253 low_addr = new_low_addr; 1254 high_addr = new_high_addr; 1255 } 1256 else{ 1257 if(new_low_addr < low_addr) 1258 low_addr = new_low_addr; 1259 if(new_high_addr > high_addr) 1260 high_addr = new_high_addr; 1261 } 1262 sections64 = TRUE; 1263 break; 1264 case MP_RELOCS: 1265 printf("File Page %u contains relocation entries for " 1266 "section (%.16s,%.16s)", page_number, 1267 mp->s->segname, mp->s->sectname); 1268 print_arch(fp); 1269 printed = TRUE; 1270 break; 1271 case MP_RELOCS_64: 1272 printf("File Page %u contains relocation entries for " 1273 "section (%.16s,%.16s)", page_number, 1274 mp->s64->segname, mp->s64->sectname); 1275 print_arch(fp); 1276 printed = TRUE; 1277 break; 1278 case MP_SPLIT_INFO: 1279 printf("File Page %u contains local of info to split " 1280 "segments", page_number); 1281 print_arch(fp); 1282 printed = TRUE; 1283 break; 1284 case MP_LOCAL_SYMBOLS: 1285 printf("File Page %u contains symbol table for " 1286 "non-global symbols", page_number); 1287 print_arch(fp); 1288 printed = TRUE; 1289 break; 1290 case MP_EXTDEF_SYMBOLS: 1291 printf("File Page %u contains symbol table for " 1292 "defined global symbols", page_number); 1293 print_arch(fp); 1294 printed = TRUE; 1295 break; 1296 case MP_UNDEF_SYMBOLS: 1297 printf("File Page %u contains symbol table for " 1298 "undefined symbols", page_number); 1299 print_arch(fp); 1300 printed = TRUE; 1301 break; 1302 case MP_TOC: 1303 printf("File Page %u contains table of contents", 1304 page_number); 1305 print_arch(fp); 1306 printed = TRUE; 1307 break; 1308 case MP_MODULE_TABLE: 1309 printf("File Page %u contains module table", 1310 page_number); 1311 print_arch(fp); 1312 printed = TRUE; 1313 break; 1314 case MP_REFERENCE_TABLE: 1315 printf("File Page %u contains reference table", 1316 page_number); 1317 print_arch(fp); 1318 printed = TRUE; 1319 break; 1320 case MP_INDIRECT_SYMBOL_TABLE: 1321 printf("File Page %u contains indirect symbols table", 1322 page_number); 1323 print_arch(fp); 1324 printed = TRUE; 1325 break; 1326 case MP_EXT_RELOCS: 1327 printf("File Page %u contains external relocation " 1328 "entries", page_number); 1329 print_arch(fp); 1330 printed = TRUE; 1331 break; 1332 case MP_LOC_RELOCS: 1333 printf("File Page %u contains local relocation " 1334 "entries", page_number); 1335 print_arch(fp); 1336 printed = TRUE; 1337 break; 1338 case MP_SYMBOL_TABLE: 1339 printf("File Page %u contains symbol table", 1340 page_number); 1341 print_arch(fp); 1342 printed = TRUE; 1343 break; 1344 case MP_HINTS_TABLE: 1345 printf("File Page %u contains hints table", 1346 page_number); 1347 print_arch(fp); 1348 printed = TRUE; 1349 break; 1350 case MP_STRING_TABLE: 1351 printf("File Page %u contains string table", 1352 page_number); 1353 print_arch(fp); 1354 printed = TRUE; 1355 break; 1356 case MP_EXT_STRING_TABLE: 1357 printf("File Page %u contains string table for " 1358 "external symbols", page_number); 1359 print_arch(fp); 1360 printed = TRUE; 1361 break; 1362 case MP_LOC_STRING_TABLE: 1363 printf("File Page %u contains string table for " 1364 "local symbols", page_number); 1365 print_arch(fp); 1366 printed = TRUE; 1367 break; 1368 case MP_CODE_SIG: 1369 printf("File Page %u contains data of code signature", 1370 page_number); 1371 print_arch(fp); 1372 printed = TRUE; 1373 break; 1374 case MP_FUNCTION_STARTS: 1375 printf("File Page %u contains data of function starts", 1376 page_number); 1377 print_arch(fp); 1378 printed = TRUE; 1379 break; 1380 case MP_DATA_IN_CODE: 1381 printf("File Page %u contains info for data in code", 1382 page_number); 1383 print_arch(fp); 1384 printed = TRUE; 1385 break; 1386 case MP_CODE_SIGN_DRS: 1387 printf("File Page %u contains info for code signing " 1388 "DRs copied from linked dylib", page_number); 1389 print_arch(fp); 1390 printed = TRUE; 1391 break; 1392 case MP_DYLD_INFO_REBASE: 1393 printf("File Page %u contains dyld info for sliding " 1394 "an image", page_number); 1395 print_arch(fp); 1396 printed = TRUE; 1397 break; 1398 case MP_DYLD_INFO_BIND: 1399 printf("File Page %u contains dyld info for binding " 1400 "symbols", page_number); 1401 print_arch(fp); 1402 printed = TRUE; 1403 break; 1404 case MP_DYLD_INFO_WEAK_BIND: 1405 printf("File Page %u contains dyld info for weak bound " 1406 "symbols", page_number); 1407 print_arch(fp); 1408 printed = TRUE; 1409 break; 1410 case MP_DYLD_INFO_LAZY_BIND: 1411 printf("File Page %u contains dyld info for lazy bound " 1412 "symbols", page_number); 1413 print_arch(fp); 1414 printed = TRUE; 1415 break; 1416 case MP_DYLD_INFO_EXPORT: 1417 printf("File Page %u contains dyld info for symbols " 1418 "exported by a dylib", page_number); 1419 print_arch(fp); 1420 printed = TRUE; 1421 break; 1422 case MP_EMPTY_SPACE: 1423 break; 1424 } 1425 } 1426 if(sections == TRUE || sections64 == TRUE){ 1427 printf("Symbols on file page %u virtual address 0x%llx to " 1428 "0x%llx\n", page_number, low_addr, high_addr); 1429 if(sections == TRUE) 1430 print_symbols(fp, low_addr, high_addr); 1431 else 1432 print_symbols64(fp, low_addr, high_addr); 1433 } 1434 break; 1435 1436 case FP_EMPTY_SPACE: 1437 break; 1438 } 1439 } 1440 1441 /* 1442 * Make a second pass through the file if nothing got printing on the 1443 * first pass because the page covers empty space in the file. 1444 */ 1445 if(printed == TRUE) 1446 return; 1447 for(fp = file_parts; fp != NULL; fp = fp->next){ 1448 if(offset + size <= fp->offset) 1449 continue; 1450 if(offset > fp->offset + fp->size) 1451 continue; 1452 if(fp->type == FP_MACH_O){ 1453 for(mp = fp->mp; mp != NULL; mp = mp->next){ 1454 if(offset + size <= mp->offset - arch_offset) 1455 continue; 1456 if(offset > (mp->offset - arch_offset) + mp->size) 1457 continue; 1458 if(fp->mh != NULL) 1459 arch_name = get_arch_name_from_types(fp->mh->cputype, 1460 fp->mh->cpusubtype); 1461 else 1462 arch_name = get_arch_name_from_types(fp->mh64->cputype, 1463 fp->mh64->cpusubtype); 1464 printf("File Page %u contains empty space in the Mach-O " 1465 "file for %s between:\n", page_number, arch_name); 1466 if(mp->prev == NULL) 1467 printf(" the start of the Mach-O file"); 1468 else{ 1469 printf(" "); 1470 print_mach_o_part(mp->prev); 1471 } 1472 printf(" and\n"); 1473 if(mp->next == NULL) 1474 printf(" the end of the Mach-O file\n"); 1475 else{ 1476 printf(" "); 1477 print_mach_o_part(mp->next); 1478 } 1479 printf("\n"); 1480 return; 1481 } 1482 break; 1483 } 1484 printf("File Page %u contains empty space in the file between:\n", 1485 page_number); 1486 if(fp->prev == NULL) 1487 printf(" the start of the file"); 1488 else{ 1489 printf(" "); 1490 print_file_part(fp->prev); 1491 } 1492 printf(" and\n"); 1493 if(fp->next == NULL) 1494 printf(" the end of the file\n"); 1495 else{ 1496 printf(" "); 1497 print_file_part(fp->next); 1498 } 1499 printf("\n"); 1500 return; 1501 } 1502} 1503 1504static 1505void 1506print_arch( 1507struct file_part *fp) 1508{ 1509 if(ofile.file_type == OFILE_FAT){ 1510 if(fp->mh != NULL) 1511 printf(" (%s)\n", 1512 get_arch_name_from_types(fp->mh->cputype, 1513 fp->mh->cpusubtype)); 1514 else 1515 printf(" (%s)\n", 1516 get_arch_name_from_types(fp->mh64->cputype, 1517 fp->mh64->cpusubtype)); 1518 } 1519 else 1520 printf("\n"); 1521} 1522 1523static 1524void 1525print_file_part( 1526struct file_part *fp) 1527{ 1528 const char *arch_name; 1529 1530 switch(fp->type){ 1531 case FP_FAT_HEADERS: 1532 printf("fat file headers"); 1533 break; 1534 case FP_MACH_O: 1535 if(fp->mh != NULL) 1536 arch_name = get_arch_name_from_types(fp->mh->cputype, 1537 fp->mh->cpusubtype); 1538 else 1539 arch_name = get_arch_name_from_types(fp->mh64->cputype, 1540 fp->mh64->cpusubtype); 1541 printf("Mach-O file for %s", arch_name); 1542 break; 1543 case FP_EMPTY_SPACE: 1544 printf("empty space"); 1545 break; 1546 } 1547} 1548 1549static 1550void 1551print_mach_o_part( 1552struct mach_o_part *mp) 1553{ 1554 switch(mp->type){ 1555 case MP_MACH_HEADERS: 1556 printf("Mach-O headers"); 1557 break; 1558 case MP_SECTION: 1559 printf("contents of section (%.16s,%.16s)", 1560 mp->s->segname, mp->s->sectname); 1561 break; 1562 case MP_SECTION_64: 1563 printf("contents of section (%.16s,%.16s)", 1564 mp->s64->segname, mp->s64->sectname); 1565 break; 1566 case MP_RELOCS: 1567 printf("relocation entries for section (%.16s,%.16s)", 1568 mp->s->segname, mp->s->sectname); 1569 break; 1570 case MP_RELOCS_64: 1571 printf("relocation entries for section (%.16s,%.16s)", 1572 mp->s64->segname, mp->s64->sectname); 1573 break; 1574 case MP_SPLIT_INFO: 1575 printf("local of info to split segments"); 1576 break; 1577 case MP_LOCAL_SYMBOLS: 1578 printf("symbol table for non-global symbols"); 1579 break; 1580 case MP_EXTDEF_SYMBOLS: 1581 printf("symbol table for defined global symbols"); 1582 break; 1583 case MP_UNDEF_SYMBOLS: 1584 printf("symbol table for undefined symbols"); 1585 break; 1586 case MP_TOC: 1587 printf("table of contents"); 1588 break; 1589 case MP_MODULE_TABLE: 1590 printf("module table"); 1591 break; 1592 case MP_REFERENCE_TABLE: 1593 printf("reference table"); 1594 break; 1595 case MP_INDIRECT_SYMBOL_TABLE: 1596 printf("indirect symbol table"); 1597 break; 1598 case MP_EXT_RELOCS: 1599 printf("external relocation entries"); 1600 break; 1601 case MP_LOC_RELOCS: 1602 printf("local relocation entries"); 1603 break; 1604 case MP_SYMBOL_TABLE: 1605 printf("symbol table"); 1606 break; 1607 case MP_HINTS_TABLE: 1608 printf("hints table"); 1609 break; 1610 case MP_STRING_TABLE: 1611 printf("string table"); 1612 break; 1613 case MP_EXT_STRING_TABLE: 1614 printf("string table for external symbols"); 1615 break; 1616 case MP_LOC_STRING_TABLE: 1617 printf("string table for local symbols"); 1618 break; 1619 case MP_CODE_SIG: 1620 printf("data of code signature"); 1621 break; 1622 case MP_FUNCTION_STARTS: 1623 printf("data of function starts"); 1624 break; 1625 case MP_DATA_IN_CODE: 1626 printf("info for data in code"); 1627 break; 1628 case MP_CODE_SIGN_DRS: 1629 printf("info for code signing DRs copied from linked dylibs"); 1630 break; 1631 case MP_DYLD_INFO_REBASE: 1632 printf("dyld info for sliding an image"); 1633 break; 1634 case MP_DYLD_INFO_BIND: 1635 printf("dyld info for binding symbols"); 1636 break; 1637 case MP_DYLD_INFO_WEAK_BIND: 1638 printf("dyld info for binding weak symbols"); 1639 break; 1640 case MP_DYLD_INFO_LAZY_BIND: 1641 printf("dyld info for binding lazy symbols"); 1642 break; 1643 case MP_DYLD_INFO_EXPORT: 1644 printf("dyld info for exported symbols"); 1645 break; 1646 case MP_EMPTY_SPACE: 1647 printf("empty space"); 1648 break; 1649 } 1650} 1651 1652static 1653void 1654print_symbols( 1655struct file_part *fp, 1656uint64_t low_addr, 1657uint64_t high_addr) 1658{ 1659 uint32_t i, count; 1660 1661 if(fp->st == NULL) 1662 return; 1663 1664 if(sorted_symbols == NULL) 1665 sorted_symbols = allocate(sizeof(struct nlist) * fp->st->nsyms); 1666 1667 count = 0; 1668 for(i = 0; i < fp->st->nsyms; i++){ 1669 if((fp->symbols[i].n_type & N_STAB) != 0) 1670 continue; 1671 if(fp->symbols[i].n_value >= low_addr && 1672 fp->symbols[i].n_value <= high_addr){ 1673 sorted_symbols[count] = fp->symbols[i]; 1674 count++; 1675 } 1676 } 1677 1678 qsort(sorted_symbols, count, sizeof(struct nlist), 1679 (int (*)(const void *, const void *))compare); 1680 1681 for(i = 0; i < count; i++){ 1682 printf(" 0x%08x %s\n", (unsigned int)sorted_symbols[i].n_value, 1683 fp->strings + sorted_symbols[i].n_un.n_strx); 1684 } 1685} 1686 1687static 1688void 1689print_symbols64( 1690struct file_part *fp, 1691uint64_t low_addr, 1692uint64_t high_addr) 1693{ 1694 uint32_t i, count; 1695 1696 if(fp->st == NULL) 1697 return; 1698 1699 if(sorted_symbols64 == NULL) 1700 sorted_symbols64 = allocate(sizeof(struct nlist_64) * 1701 fp->st->nsyms); 1702 1703 count = 0; 1704 for(i = 0; i < fp->st->nsyms; i++){ 1705 if((fp->symbols64[i].n_type & N_STAB) != 0) 1706 continue; 1707 if(fp->symbols64[i].n_value >= low_addr && 1708 fp->symbols64[i].n_value <= high_addr){ 1709 sorted_symbols64[count] = fp->symbols64[i]; 1710 count++; 1711 } 1712 } 1713 1714 qsort(sorted_symbols64, count, sizeof(struct nlist_64), 1715 (int (*)(const void *, const void *))compare64); 1716 1717 for(i = 0; i < count; i++){ 1718 printf(" 0x%016llx %s\n", sorted_symbols64[i].n_value, 1719 fp->strings + sorted_symbols64[i].n_un.n_strx); 1720 } 1721} 1722 1723static 1724int 1725compare( 1726struct nlist *p1, 1727struct nlist *p2) 1728{ 1729 if(p1->n_value > p2->n_value) 1730 return(1); 1731 else if(p1->n_value < p2->n_value) 1732 return(-1); 1733 else 1734 return(0); 1735} 1736 1737static 1738int 1739compare64( 1740struct nlist_64 *p1, 1741struct nlist_64 *p2) 1742{ 1743 if(p1->n_value > p2->n_value) 1744 return(1); 1745 else if(p1->n_value < p2->n_value) 1746 return(-1); 1747 else 1748 return(0); 1749} 1750