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#include "stdio.h" 32#include "string.h" 33#include "mach-o/loader.h" 34#include "objc/objc-runtime.h" 35#include "stuff/allocate.h" 36#include "stuff/bytesex.h" 37#include "stuff/symbol.h" 38#include "ofile_print.h" 39 40/* 41 * Here we need structures that have the same memory layout and size as the 42 * 32-bit Objective-C 1 meta data structures. 43 * 44 * The real structure definitions come from the header file objc/objc-runtime.h 45 * and those it includes like objc/objc-class.h, etc. But since this program 46 * must also run on 64-bit hosts that can't be used. 47 */ 48 49struct objc_module_t { 50 uint32_t version; 51 uint32_t size; 52 uint32_t name; /* char * (32-bit pointer) */ 53 uint32_t symtab; /* struct objc_symtab * (32-bit pointer) */ 54}; 55 56struct objc_symtab_t { 57 uint32_t sel_ref_cnt; 58 uint32_t refs; /* SEL * (32-bit pointer) */ 59 uint16_t cls_def_cnt; 60 uint16_t cat_def_cnt; 61 uint32_t defs[1]; /* void * (32-bit pointer) variable size */ 62}; 63 64struct objc_class_t { 65 uint32_t isa; /* struct objc_class * (32-bit pointer) */ 66 uint32_t super_class; /* struct objc_class * (32-bit pointer) */ 67 uint32_t name; /* const char * (32-bit pointer) */ 68 int32_t version; 69 int32_t info; 70 int32_t instance_size; 71 uint32_t ivars; /* struct objc_ivar_list * (32-bit pointer) */ 72 uint32_t methodLists; /* struct objc_method_list ** (32-bit pointer) */ 73 uint32_t cache; /* struct objc_cache * (32-bit pointer) */ 74 uint32_t protocols; /* struct objc_protocol_list * (32-bit pointer) */ 75}; 76 77struct objc_category_t { 78 uint32_t category_name; /* char * (32-bit pointer) */ 79 uint32_t class_name; /* char * (32-bit pointer) */ 80 uint32_t instance_methods; /* struct objc_method_list * (32-bit pointer) */ 81 uint32_t class_methods; /* struct objc_method_list * (32-bit pointer) */ 82 uint32_t protocols; /* struct objc_protocol_list * (32-bit ptr) */ 83}; 84 85struct objc_ivar_t { 86 uint32_t ivar_name; /* char * (32-bit pointer) */ 87 uint32_t ivar_type; /* char * (32-bit pointer) */ 88 int32_t ivar_offset; 89}; 90 91struct objc_ivar_list_t { 92 int32_t ivar_count; 93 struct objc_ivar_t ivar_list[1]; /* variable length structure */ 94}; 95 96struct objc_method_t { 97 uint32_t method_name; /* SEL, aka struct objc_selector * (32-bit pointer) */ 98 uint32_t method_types; /* char * (32-bit pointer) */ 99 uint32_t method_imp; /* IMP, aka function pointer, (*IMP)(id, SEL, ...) 100 (32-bit pointer) */ 101}; 102 103struct objc_method_list_t { 104 uint32_t obsolete; /* struct objc_method_list * (32-bit pointer) */ 105 int32_t method_count; 106 struct objc_method_t method_list[1]; /* variable length structure */ 107}; 108 109struct objc_protocol_t { 110 uint32_t isa; /* struct objc_class * (32-bit pointer) */ 111 uint32_t protocol_name; /* char * (32-bit pointer) */ 112 uint32_t protocol_list; /* struct objc_protocol_list * 113 (32-bit pointer) */ 114 uint32_t instance_methods; /* struct objc_method_description_list * 115 (32-bit pointer) */ 116 uint32_t class_methods; /* struct objc_method_description_list * 117 (32-bit pointer) */ 118}; 119 120struct objc_protocol_list_t { 121 uint32_t next; /* struct objc_protocol_list * (32-bit pointer) */ 122 int32_t count; 123 uint32_t list[1]; /* Protocol *, aka struct objc_protocol_t * ( 124 (32-bit pointer) */ 125}; 126 127struct objc_method_description_t { 128 uint32_t name; /* SEL, aka struct objc_selector * (32-bit pointer) */ 129 uint32_t types; /* char * (32-bit pointer) */ 130}; 131 132struct objc_method_description_list_t { 133 int32_t count; 134 struct objc_method_description_t list[1]; 135}; 136 137 138/* 139 * The header file "objc/NXString.h" has gone away and there is no real public 140 * header file to get this definition from anymore. 141 */ 142struct objc_string_object_t { 143 uint32_t isa; /* struct objc_class * (32-bit pointer) */ 144 uint32_t characters; /* char * (32-bit pointer) */ 145 uint32_t _length; 146}; 147typedef struct objc_string_object_t NXConstantString; 148 149#define SIZEHASHTABLE 821 150struct _hashEntry_t { 151 uint32_t next; /* struct _hashEntry * (32-bit pointer) */ 152 uint32_t sel; /* char * (32-bit pointer) */ 153}; 154 155struct imageInfo_t { 156 uint32_t version; 157 uint32_t flags; 158}; 159 160static 161void 162swap_imageInfo_t( 163struct imageInfo_t *o, 164enum byte_sex target_byte_sex) 165{ 166 o->version = SWAP_INT(o->version); 167 o->flags = SWAP_INT(o->flags); 168} 169 170void 171swap_objc_module_t( 172struct objc_module_t *module, 173enum byte_sex target_byte_sex) 174{ 175 module->version = SWAP_INT(module->version); 176 module->size = SWAP_INT(module->size); 177 module->name = SWAP_INT(module->name); 178 module->symtab = SWAP_INT(module->symtab); 179} 180 181void 182swap_objc_symtab_t( 183struct objc_symtab_t *symtab, 184enum byte_sex target_byte_sex) 185{ 186 symtab->sel_ref_cnt = SWAP_INT(symtab->sel_ref_cnt); 187 symtab->refs = SWAP_INT(symtab->refs); 188 symtab->cls_def_cnt = SWAP_SHORT(symtab->cls_def_cnt); 189 symtab->cat_def_cnt = SWAP_SHORT(symtab->cat_def_cnt); 190} 191 192void 193swap_objc_class_t( 194struct objc_class_t *objc_class, 195enum byte_sex target_byte_sex) 196{ 197 objc_class->isa = SWAP_INT(objc_class->isa); 198 objc_class->super_class = SWAP_INT(objc_class->super_class); 199 objc_class->name = SWAP_INT(objc_class->name); 200 objc_class->version = SWAP_INT(objc_class->version); 201 objc_class->info = SWAP_INT(objc_class->info); 202 objc_class->instance_size = SWAP_INT(objc_class->instance_size); 203 objc_class->ivars = SWAP_INT(objc_class->ivars); 204 objc_class->methodLists = SWAP_INT(objc_class->methodLists); 205 objc_class->cache = SWAP_INT(objc_class->cache); 206 objc_class->protocols = SWAP_INT(objc_class->protocols); 207} 208 209void 210swap_objc_category_t( 211struct objc_category_t *objc_category, 212enum byte_sex target_byte_sex) 213{ 214 objc_category->category_name = SWAP_INT(objc_category->category_name); 215 objc_category->class_name = SWAP_INT(objc_category->class_name); 216 objc_category->instance_methods = 217 SWAP_INT(objc_category->instance_methods); 218 objc_category->class_methods = 219 SWAP_INT(objc_category->class_methods); 220 objc_category->protocols = 221 SWAP_INT(objc_category->protocols); 222} 223 224void 225swap_objc_ivar_list_t( 226struct objc_ivar_list_t *objc_ivar_list, 227enum byte_sex target_byte_sex) 228{ 229 objc_ivar_list->ivar_count = SWAP_INT(objc_ivar_list->ivar_count); 230} 231 232void 233swap_objc_ivar_t( 234struct objc_ivar_t *objc_ivar, 235enum byte_sex target_byte_sex) 236{ 237 objc_ivar->ivar_name = SWAP_INT(objc_ivar->ivar_name); 238 objc_ivar->ivar_type = SWAP_INT(objc_ivar->ivar_type); 239 objc_ivar->ivar_offset = SWAP_INT(objc_ivar->ivar_offset); 240} 241 242void 243swap_objc_method_list_t( 244struct objc_method_list_t *method_list, 245enum byte_sex target_byte_sex) 246{ 247 method_list->obsolete = SWAP_INT(method_list->obsolete); 248 method_list->method_count = SWAP_INT(method_list->method_count); 249} 250 251void 252swap_objc_method_t( 253struct objc_method_t *method, 254enum byte_sex target_byte_sex) 255{ 256 method->method_name = SWAP_INT(method->method_name); 257 method->method_types = SWAP_INT(method->method_types); 258 method->method_imp = SWAP_INT(method->method_imp); 259} 260 261void 262swap_objc_protocol_list_t( 263struct objc_protocol_list_t *protocol_list, 264enum byte_sex target_byte_sex) 265{ 266 protocol_list->next = SWAP_INT(protocol_list->next); 267 protocol_list->count = SWAP_INT(protocol_list->count); 268} 269 270void 271swap_objc_protocol_t( 272struct objc_protocol_t *protocol, 273enum byte_sex target_byte_sex) 274{ 275 protocol->isa = SWAP_INT(protocol->isa); 276 protocol->protocol_name = SWAP_INT(protocol->protocol_name); 277 protocol->protocol_list = SWAP_INT(protocol->protocol_list); 278 protocol->instance_methods = SWAP_INT(protocol->instance_methods); 279 protocol->class_methods = SWAP_INT(protocol->class_methods); 280} 281 282void 283swap_objc_method_description_list_t( 284struct objc_method_description_list_t *mdl, 285enum byte_sex target_byte_sex) 286{ 287 mdl->count = SWAP_INT(mdl->count); 288} 289 290void 291swap_objc_method_description_t( 292struct objc_method_description_t *md, 293enum byte_sex target_byte_sex) 294{ 295 md->name = SWAP_INT(md->name); 296 md->types = SWAP_INT(md->types); 297} 298 299void 300swap_string_object_t( 301struct objc_string_object_t *string_object, 302enum byte_sex target_byte_sex) 303{ 304 string_object->isa = SWAP_INT(string_object->isa); 305 string_object->characters = SWAP_INT(string_object->characters); 306 string_object->_length = SWAP_INT(string_object->_length); 307} 308 309void 310swap_hashEntry_t( 311struct _hashEntry_t *_hashEntry, 312enum byte_sex target_byte_sex) 313{ 314 _hashEntry->next = SWAP_INT(_hashEntry->next); 315 _hashEntry->sel = SWAP_INT(_hashEntry->sel); 316} 317 318struct section_info { 319 char *contents; 320 uint32_t addr; 321 uint32_t size; 322 uint32_t offset; 323 enum bool protected; 324 enum bool zerofill; 325}; 326 327static void get_objc_sections( 328 struct load_command *load_commands, 329 uint32_t ncmds, 330 uint32_t sizeofcmds, 331 enum byte_sex object_byte_sex, 332 char *object_addr, 333 uint32_t object_size, 334 struct section_info **objc_sections, 335 uint32_t *nobjc_sections, 336 char *sectname, 337 char **sect, 338 uint32_t *sect_addr, 339 uint32_t *sect_size); 340 341static void get_cstring_section( 342 struct load_command *load_commands, 343 uint32_t ncmds, 344 uint32_t sizeofcmds, 345 enum byte_sex object_byte_sex, 346 char *object_addr, 347 uint32_t object_size, 348 struct section_info *cstring_section_ptr); 349 350static enum bool print_method_list( 351 uint32_t addr, 352 struct section_info *objc_sections, 353 uint32_t nobjc_sections, 354 struct section_info *cstring_section_ptr, 355 enum byte_sex host_byte_sex, 356 enum bool swapped, 357 struct symbol *sorted_symbols, 358 uint32_t nsorted_symbols, 359 enum bool verbose); 360 361static enum bool print_protocol_list( 362 uint32_t indent, 363 uint32_t addr, 364 struct section_info *objc_sections, 365 uint32_t nobjc_sections, 366 struct section_info *cstring_section_ptr, 367 enum byte_sex host_byte_sex, 368 enum bool swapped, 369 enum bool verbose); 370 371static void print_protocol( 372 uint32_t indent, 373 struct objc_protocol_t *protocol, 374 struct section_info *objc_sections, 375 uint32_t nobjc_sections, 376 struct section_info *cstring_section_ptr, 377 enum byte_sex host_byte_sex, 378 enum bool swapped, 379 enum bool verbose); 380 381static enum bool print_method_description_list( 382 uint32_t indent, 383 uint32_t addr, 384 struct section_info *objc_sections, 385 uint32_t nobjc_sections, 386 struct section_info *cstring_section_ptr, 387 enum byte_sex host_byte_sex, 388 enum bool swapped, 389 enum bool verbose); 390 391static enum bool print_PHASH( 392 uint32_t indent, 393 uint32_t addr, 394 struct section_info *objc_sections, 395 uint32_t nobjc_sections, 396 struct section_info *cstring_section_ptr, 397 enum byte_sex host_byte_sex, 398 enum bool swapped, 399 enum bool verbose); 400 401static void print_indent( 402 uint32_t indent); 403 404static void *get_pointer( 405 uint32_t addr, 406 uint32_t *left, 407 struct section_info *objc_sections, 408 uint32_t nobjc_sections, 409 struct section_info *cstring_section_ptr); 410 411static enum bool get_symtab( 412 uint32_t addr, 413 struct objc_symtab_t *symtab, 414 uint32_t **defs, 415 uint32_t *left, 416 enum bool *trunc, 417 struct section_info *objc_sections, 418 uint32_t nobjc_sections, 419 enum byte_sex host_byte_sex, 420 enum bool swapped); 421 422static enum bool get_objc_class( 423 uint32_t addr, 424 struct objc_class_t *objc_class, 425 enum bool *trunc, 426 struct section_info *objc_sections, 427 uint32_t nobjc_sections, 428 enum byte_sex host_byte_sex, 429 enum bool swapped); 430 431static enum bool get_objc_category( 432 uint32_t addr, 433 struct objc_category_t *objc_category, 434 enum bool *trunc, 435 struct section_info *objc_sections, 436 uint32_t nobjc_sections, 437 enum byte_sex host_byte_sex, 438 enum bool swapped); 439 440static enum bool get_ivar_list( 441 uint32_t addr, 442 struct objc_ivar_list_t *objc_ivar_list, 443 struct objc_ivar_t **ivar_list, 444 uint32_t *left, 445 enum bool *trunc, 446 struct section_info *objc_sections, 447 uint32_t nobjc_sections, 448 enum byte_sex host_byte_sex, 449 enum bool swapped); 450 451static enum bool get_method_list( 452 uint32_t addr, 453 struct objc_method_list_t *method_list, 454 struct objc_method_t **methods, 455 uint32_t *left, 456 enum bool *trunc, 457 struct section_info *objc_sections, 458 uint32_t nobjc_sections, 459 enum byte_sex host_byte_sex, 460 enum bool swapped); 461 462static enum bool get_protocol_list( 463 uint32_t addr, 464 struct objc_protocol_list_t *protocol_list, 465 uint32_t **list, 466 uint32_t *left, 467 enum bool *trunc, 468 struct section_info *objc_sections, 469 uint32_t nobjc_sections, 470 enum byte_sex host_byte_sex, 471 enum bool swapped); 472 473static enum bool get_protocol( 474 uint32_t addr, 475 struct objc_protocol_t *protocol, 476 enum bool *trunc, 477 struct section_info *objc_sections, 478 uint32_t nobjc_sections, 479 enum byte_sex host_byte_sex, 480 enum bool swapped); 481 482static enum bool get_method_description_list( 483 uint32_t addr, 484 struct objc_method_description_list_t *mdl, 485 struct objc_method_description_t **list, 486 uint32_t *left, 487 enum bool *trunc, 488 struct section_info *objc_sections, 489 uint32_t nobjc_sections, 490 enum byte_sex host_byte_sex, 491 enum bool swapped); 492 493static enum bool get_hashEntry( 494 uint32_t addr, 495 struct _hashEntry_t *_hashEntry, 496 enum bool *trunc, 497 struct section_info *objc_sections, 498 uint32_t nobjc_sections, 499 enum byte_sex host_byte_sex, 500 enum bool swapped); 501 502/* 503 * Print the objc segment. 504 */ 505enum bool 506print_objc_segment( 507cpu_type_t mh_cputype, 508struct load_command *load_commands, 509uint32_t ncmds, 510uint32_t sizeofcmds, 511enum byte_sex object_byte_sex, 512char *object_addr, 513uint32_t object_size, 514struct symbol *sorted_symbols, 515uint32_t nsorted_symbols, 516enum bool verbose) 517{ 518 enum byte_sex host_byte_sex; 519 enum bool swapped, trunc; 520 uint32_t i, j, left, size, defs_left, def, ivar_list_left; 521 char *p; 522 struct section_info *objc_sections; 523 uint32_t nobjc_sections; 524 struct section_info cstring_section; 525 526 struct objc_module_t *modules, *m, module; 527 uint32_t modules_addr, modules_size; 528 struct objc_symtab_t symtab; 529 uint32_t *defs; 530 struct objc_class_t objc_class; 531 struct objc_ivar_list_t objc_ivar_list; 532 struct objc_ivar_t *ivar_list, ivar; 533 struct objc_category_t objc_category; 534 535 struct imageInfo_t *imageInfo, info; 536 uint32_t imageInfo_addr, imageInfo_size; 537 538 printf("Objective-C segment\n"); 539 get_objc_sections(load_commands, ncmds, sizeofcmds, object_byte_sex, 540 object_addr, object_size, &objc_sections, 541 &nobjc_sections, SECT_OBJC_MODULES, (char **)&modules, 542 &modules_addr, &modules_size); 543 544 if(modules == NULL){ 545 if(mh_cputype == CPU_TYPE_I386) 546 return(FALSE); 547 printf("can't print objective-C information no (" SEG_OBJC "," 548 SECT_OBJC_MODULES ") section\n"); 549 return(TRUE); 550 } 551 552 if (verbose) 553 get_cstring_section(load_commands, ncmds, sizeofcmds, object_byte_sex, 554 object_addr, object_size, &cstring_section); 555 556 host_byte_sex = get_host_byte_sex(); 557 swapped = host_byte_sex != object_byte_sex; 558 559 memset(&module, '\0', sizeof(struct objc_module_t)); 560 561 for(m = modules; 562 (char *)m < (char *)modules + modules_size; 563 m = (struct objc_module_t *)((char *)m + module.size) ){ 564 565 memset(&module, '\0', sizeof(struct objc_module_t)); 566 left = modules_size - (m - modules); 567 size = left < sizeof(struct objc_module_t) ? 568 left : sizeof(struct objc_module_t); 569 memcpy(&module, m, size); 570 if(swapped) 571 swap_objc_module_t(&module, host_byte_sex); 572 573 if((char *)m + module.size > (char *)m + modules_size) 574 printf("module extends past end of " SECT_OBJC_MODULES 575 " section\n"); 576 printf("Module 0x%x\n", (unsigned int) 577 (modules_addr + (char *)m - (char *)modules)); 578 579 printf(" version %u\n", module.version); 580 printf(" size %u\n", module.size); 581 if(verbose){ 582 p = get_pointer(module.name, &left, 583 objc_sections, nobjc_sections, &cstring_section); 584 if(p != NULL) 585 printf(" name %.*s\n", (int)left, p); 586 else 587 printf(" name 0x%08x (not in an " SEG_OBJC 588 " section)\n", (unsigned int)module.name); 589 } 590 else 591 printf(" name 0x%08x\n", (unsigned int)(module.name)); 592 593 if(get_symtab(module.symtab, &symtab, &defs, &defs_left, &trunc, 594 objc_sections, nobjc_sections, 595 host_byte_sex, swapped) == FALSE){ 596 printf(" symtab 0x%08x (not in an " SEG_OBJC 597 " section)\n", (unsigned int)module.symtab); 598 continue; 599 } 600 printf(" symtab 0x%08x\n", (unsigned int)module.symtab); 601 if(trunc == TRUE) 602 printf("\tsymtab extends past end of an " SEG_OBJC 603 " section\n"); 604 printf("\tsel_ref_cnt %u\n", symtab.sel_ref_cnt); 605 p = get_pointer(symtab.refs, &left, 606 objc_sections, nobjc_sections, &cstring_section); 607 if(p != NULL) 608 printf("\trefs 0x%08x", symtab.refs); 609 else 610 printf("\trefs 0x%08x (not in an " SEG_OBJC " section)\n", 611 symtab.refs); 612 613 printf("\tcls_def_cnt %d\n", symtab.cls_def_cnt); 614 printf("\tcat_def_cnt %d\n", symtab.cat_def_cnt); 615 if(symtab.cls_def_cnt > 0) 616 printf("\tClass Definitions\n"); 617 for(i = 0; i < symtab.cls_def_cnt; i++){ 618 if((i + 1) * sizeof(uint32_t) > defs_left){ 619 printf("\t(remaining class defs entries entends past " 620 "the end of the section)\n"); 621 break; 622 } 623 624 memcpy(&def, defs + i, sizeof(uint32_t)); 625 if(swapped) 626 def = SWAP_INT(def); 627 628 if(get_objc_class(def, &objc_class, &trunc, objc_sections, 629 nobjc_sections, host_byte_sex, swapped) == TRUE){ 630 printf("\tdefs[%u] 0x%08x", i, def); 631print_objc_class: 632 if(trunc == TRUE) 633 printf(" (entends past the end of the section)\n"); 634 else 635 printf("\n"); 636 printf("\t\t isa 0x%08x", objc_class.isa); 637 638 if(verbose && CLS_GETINFO(&objc_class, CLS_META)){ 639 p = get_pointer(objc_class.isa, &left, objc_sections, 640 nobjc_sections, &cstring_section); 641 if(p != NULL) 642 printf(" %.*s\n", (int)left, p); 643 else 644 printf(" (not in an " SEG_OBJC " section)\n"); 645 } 646 else 647 printf("\n"); 648 649 printf("\t super_class 0x%08x",objc_class.super_class); 650 if(verbose){ 651 p = get_pointer(objc_class.super_class, &left, 652 objc_sections, nobjc_sections, &cstring_section); 653 if(p != NULL) 654 printf(" %.*s\n", (int)left, p); 655 else 656 printf(" (not in an " SEG_OBJC " section)\n"); 657 } 658 else 659 printf("\n"); 660 661 printf("\t\t name 0x%08x", objc_class.name); 662 if(verbose){ 663 p = get_pointer(objc_class.name, &left, 664 objc_sections, nobjc_sections, &cstring_section); 665 if(p != NULL) 666 printf(" %.*s\n", (int)left, p); 667 else 668 printf(" (not in an " SEG_OBJC " section)\n"); 669 } 670 else 671 printf("\n"); 672 printf("\t\t version 0x%08x\n", 673 (unsigned int)objc_class.version); 674 printf("\t\t info 0x%08x", 675 (unsigned int)objc_class.info); 676 if(verbose){ 677 if(CLS_GETINFO(&objc_class, CLS_CLASS)) 678 printf(" CLS_CLASS\n"); 679 else if(CLS_GETINFO(&objc_class, CLS_META)) 680 printf(" CLS_META\n"); 681 else 682 printf("\n"); 683 } 684 else 685 printf("\n"); 686 printf("\t instance_size 0x%08x\n", 687 (unsigned int)objc_class.instance_size); 688 689 if(get_ivar_list(objc_class.ivars, &objc_ivar_list, 690 &ivar_list, &ivar_list_left, &trunc, 691 objc_sections, nobjc_sections, host_byte_sex, 692 swapped) == TRUE){ 693 printf("\t\t ivars 0x%08x\n", 694 (unsigned int)objc_class.ivars); 695 if(trunc == TRUE) 696 printf("\t\t objc_ivar_list extends past end " 697 "of " SECT_OBJC_SYMBOLS " section\n"); 698 printf("\t\t ivar_count %d\n", 699 objc_ivar_list.ivar_count); 700 for(j = 0; 701 j < (uint32_t)objc_ivar_list.ivar_count; 702 j++){ 703 if((j + 1) * sizeof(struct objc_ivar_t) > 704 ivar_list_left){ 705 printf("\t\t remaining ivar's extend past " 706 "the of the section\n"); 707 break; 708 } 709 memcpy(&ivar, ivar_list + j, 710 sizeof(struct objc_ivar_t)); 711 if(swapped) 712 swap_objc_ivar_t(&ivar, host_byte_sex); 713 714 printf("\t\t\tivar_name 0x%08x", 715 (unsigned int)ivar.ivar_name); 716 if(verbose){ 717 p = get_pointer(ivar.ivar_name, &left, 718 objc_sections, nobjc_sections, &cstring_section); 719 if(p != NULL) 720 printf(" %.*s\n", (int)left, p); 721 else 722 printf(" (not in an " SEG_OBJC 723 " section)\n"); 724 } 725 else 726 printf("\n"); 727 printf("\t\t\tivar_type 0x%08x", 728 (unsigned int)ivar.ivar_type); 729 if(verbose){ 730 p = get_pointer(ivar.ivar_type, &left, 731 objc_sections, nobjc_sections, &cstring_section); 732 if(p != NULL) 733 printf(" %.*s\n", (int)left, p); 734 else 735 printf(" (not in an " SEG_OBJC 736 " section)\n"); 737 } 738 else 739 printf("\n"); 740 printf("\t\t ivar_offset 0x%08x\n", 741 (unsigned int)ivar.ivar_offset); 742 } 743 } 744 else{ 745 printf("\t\t ivars 0x%08x (not in an " SEG_OBJC 746 " section)\n", 747 (unsigned int)objc_class.ivars); 748 } 749 750 printf("\t\t methods 0x%08x", 751 (unsigned int)objc_class.methodLists); 752 if(print_method_list(objc_class.methodLists, 753 objc_sections, nobjc_sections, 754 &cstring_section, 755 host_byte_sex, swapped, sorted_symbols, 756 nsorted_symbols, verbose) == FALSE) 757 printf(" (not in an " SEG_OBJC " section)\n"); 758 759 printf("\t\t cache 0x%08x\n", 760 (unsigned int)objc_class.cache); 761 762 printf("\t\tprotocols 0x%08x", 763 (unsigned int)objc_class.protocols); 764 if(print_protocol_list(16, objc_class.protocols, 765 objc_sections, nobjc_sections, &cstring_section, 766 host_byte_sex, swapped, verbose) == FALSE) 767 printf(" (not in an " SEG_OBJC " section)\n"); 768 769 if(CLS_GETINFO((&objc_class), CLS_CLASS)){ 770 printf("\tMeta Class"); 771 if(get_objc_class((uint32_t)objc_class.isa, 772 &objc_class, &trunc, objc_sections, nobjc_sections, 773 host_byte_sex, swapped) == TRUE){ 774 goto print_objc_class; 775 } 776 else 777 printf(" (not in " SECT_OBJC_SYMBOLS 778 " section)\n"); 779 } 780 } 781 else 782 printf("\tdefs[%u] 0x%08x (not in an " SEG_OBJC 783 " section)\n", i, (unsigned int)def); 784 } 785 if(symtab.cat_def_cnt > 0) 786 printf("\tCategory Definitions\n"); 787 for(i = 0; i < symtab.cat_def_cnt; i++){ 788 if((i + symtab.cls_def_cnt + 1) * sizeof(uint32_t) > 789 defs_left){ 790 printf("\t(remaining category defs entries entends " 791 "past the end of the section)\n"); 792 break; 793 } 794 795 memcpy(&def, defs + i + symtab.cls_def_cnt, sizeof(uint32_t)); 796 if(swapped) 797 def = SWAP_INT(def); 798 799 if(get_objc_category(def, &objc_category, &trunc, 800 objc_sections, nobjc_sections, 801 host_byte_sex, swapped) == TRUE){ 802 printf("\tdefs[%u] 0x%08x", i + symtab.cls_def_cnt, 803 (unsigned int)def); 804 if(trunc == TRUE) 805 printf(" (entends past the end of the section)\n"); 806 else 807 printf("\n"); 808 printf("\t category name 0x%08x", 809 objc_category.category_name); 810 if(verbose){ 811 p = get_pointer(objc_category.category_name, &left, 812 objc_sections, nobjc_sections, 813 &cstring_section); 814 if(p != NULL) 815 printf(" %.*s\n", (int)left, p); 816 else 817 printf(" (not in an " SEG_OBJC " section)\n"); 818 } 819 else 820 printf("\n"); 821 822 printf("\t\t class name 0x%08x", objc_category.class_name); 823 if(verbose){ 824 p = get_pointer(objc_category.class_name, &left, 825 objc_sections, nobjc_sections, 826 &cstring_section); 827 if(p != NULL) 828 printf(" %.*s\n", (int)left, p); 829 else 830 printf(" (not in an " SEG_OBJC " section)\n"); 831 } 832 else 833 printf("\n"); 834 835 printf("\t instance methods 0x%08x", 836 objc_category.instance_methods); 837 if(print_method_list(objc_category.instance_methods, 838 objc_sections, nobjc_sections, 839 &cstring_section, 840 host_byte_sex, swapped, 841 sorted_symbols, nsorted_symbols, 842 verbose) == FALSE) 843 printf(" (not in an " SEG_OBJC " section)\n"); 844 845 printf("\t class methods 0x%08x", 846 objc_category.class_methods); 847 if(print_method_list(objc_category.class_methods, 848 objc_sections, nobjc_sections, &cstring_section, 849 host_byte_sex, swapped, sorted_symbols, nsorted_symbols, 850 verbose) == FALSE) 851 printf(" (not in an " SEG_OBJC " section)\n"); 852 } 853 else 854 printf("\tdefs[%u] 0x%08x (not in an " SEG_OBJC 855 " section)\n", i + symtab.cls_def_cnt, 856 (unsigned int)def); 857 } 858 } 859 860 printf("Contents of (%s,%s) section\n", SEG_OBJC, "__image_info"); 861 get_objc_sections(load_commands, ncmds, sizeofcmds, object_byte_sex, 862 object_addr, object_size, &objc_sections, 863 &nobjc_sections, "__image_info", (char **)&imageInfo, 864 &imageInfo_addr, &imageInfo_size); 865 memset(&info, '\0', sizeof(struct imageInfo_t)); 866 if(imageInfo_size < sizeof(struct imageInfo_t)){ 867 memcpy(&info, imageInfo, imageInfo_size); 868 printf(" (imageInfo entends past the end of the section)\n"); 869 } 870 else 871 memcpy(&info, imageInfo, sizeof(struct imageInfo_t)); 872 if(swapped) 873 swap_imageInfo_t(&info, host_byte_sex); 874 printf(" version %u\n", info.version); 875 printf(" flags 0x%x", info.flags); 876 if(info.flags & 0x1) 877 printf(" F&C"); 878 if(info.flags & 0x2) 879 printf(" GC"); 880 if(info.flags & 0x4) 881 printf(" GC-only"); 882 else 883 printf(" RR"); 884 printf("\n"); 885 return(TRUE); 886} 887 888void 889print_objc_protocol_section( 890struct load_command *load_commands, 891uint32_t ncmds, 892uint32_t sizeofcmds, 893enum byte_sex object_byte_sex, 894char *object_addr, 895uint32_t object_size, 896enum bool verbose) 897{ 898 enum byte_sex host_byte_sex; 899 enum bool swapped; 900 struct section_info *objc_sections, cstring_section; 901 uint32_t nobjc_sections; 902 struct objc_protocol_t *protocols, *p, protocol; 903 uint32_t protocols_addr, protocols_size; 904 uint32_t size, left; 905 906 printf("Contents of (" SEG_OBJC ",__protocol) section\n"); 907 get_objc_sections(load_commands, ncmds, sizeofcmds, object_byte_sex, 908 object_addr, object_size, &objc_sections, 909 &nobjc_sections, "__protocol", (char **)&protocols, 910 &protocols_addr, &protocols_size); 911 912 if (verbose) 913 get_cstring_section(load_commands, ncmds, sizeofcmds, object_byte_sex, 914 object_addr, object_size, &cstring_section); 915 916 host_byte_sex = get_host_byte_sex(); 917 swapped = host_byte_sex != object_byte_sex; 918 919 for(p = protocols; (char *)p < (char *)protocols + protocols_size; p++){ 920 921 memset(&protocol, '\0', sizeof(struct objc_protocol_t)); 922 left = protocols_size - (p - protocols); 923 size = left < sizeof(struct objc_protocol_t) ? 924 left : sizeof(struct objc_protocol_t); 925 memcpy(&protocol, p, size); 926 927 if((char *)p + sizeof(struct objc_protocol_t) > 928 (char *)p + protocols_size) 929 printf("Protocol extends past end of __protocol section\n"); 930 printf("Protocol 0x%x\n", (unsigned int) 931 (protocols_addr + (char *)p - (char *)protocols)); 932 933 print_protocol(0, &protocol, 934 objc_sections, nobjc_sections, &cstring_section, 935 host_byte_sex, swapped, verbose); 936 } 937} 938 939void 940print_objc_string_object_section( 941char *sectname, 942struct load_command *load_commands, 943uint32_t ncmds, 944uint32_t sizeofcmds, 945enum byte_sex object_byte_sex, 946char *object_addr, 947uint32_t object_size, 948enum bool verbose) 949{ 950 enum byte_sex host_byte_sex; 951 enum bool swapped; 952 struct section_info *objc_sections; 953 uint32_t nobjc_sections; 954 struct section_info cstring_section; 955 struct objc_string_object_t *string_objects, *s, string_object; 956 uint32_t string_objects_addr, string_objects_size; 957 uint32_t size, left; 958 char *p; 959 960 printf("Contents of (" SEG_OBJC ",%s) section\n", sectname); 961 get_objc_sections(load_commands, ncmds, sizeofcmds, object_byte_sex, 962 object_addr, object_size, &objc_sections, 963 &nobjc_sections, sectname, (char **)&string_objects, 964 &string_objects_addr, &string_objects_size); 965 966 get_cstring_section(load_commands, ncmds, sizeofcmds, object_byte_sex, 967 object_addr, object_size, &cstring_section); 968 969 host_byte_sex = get_host_byte_sex(); 970 swapped = host_byte_sex != object_byte_sex; 971 972 for(s = string_objects; 973 (char *)s < (char *)string_objects + string_objects_size; 974 s++){ 975 976 memset(&string_object, '\0', sizeof(struct objc_string_object_t)); 977 left = string_objects_size - (s - string_objects); 978 size = left < sizeof(struct objc_string_object_t) ? 979 left : sizeof(struct objc_string_object_t); 980 memcpy(&string_object, s, size); 981 982 if((char *)s + sizeof(struct objc_string_object_t) > 983 (char *)s + string_objects_size) 984 printf("String Object extends past end of %s section\n", 985 sectname); 986 printf("String Object 0x%x\n", (unsigned int) 987 (string_objects_addr + (char *)s - (char *)string_objects)); 988 989 if(swapped) 990 swap_string_object_t(&string_object, host_byte_sex); 991 printf(" isa 0x%x\n", string_object.isa); 992 printf(" characters 0x%x", 993 (unsigned int)string_object.characters); 994 if(verbose){ 995 p = get_pointer(string_object.characters, &left, 996 &cstring_section, 1, &cstring_section); 997 if(p != NULL) 998 printf(" %.*s\n", (int)left, p); 999 else 1000 printf(" (not in the (" SEG_TEXT ",__cstring) section)\n"); 1001 } 1002 else 1003 printf("\n"); 1004 printf(" _length %u\n", string_object._length); 1005 } 1006} 1007 1008/* 1009 * PHASH[SIZEHASHTABLE]; 1010 * HASH[?]; variable sized (computed from size of section). 1011 */ 1012void 1013print_objc_runtime_setup_section( 1014struct load_command *load_commands, 1015uint32_t ncmds, 1016uint32_t sizeofcmds, 1017enum byte_sex object_byte_sex, 1018char *object_addr, 1019uint32_t object_size, 1020enum bool verbose) 1021{ 1022 1023 enum byte_sex host_byte_sex; 1024 enum bool swapped; 1025 struct section_info *objc_sections, cstring_section; 1026 uint32_t i, nobjc_sections, left; 1027 struct _hashEntry_t **PHASH, *HASH, _hashEntry; 1028 char *sect, *p; 1029 uint32_t sect_addr, sect_size, phash; 1030 1031 printf("Contents of (" SEG_OBJC ",__runtime_setup) section\n"); 1032 get_objc_sections(load_commands, ncmds, sizeofcmds, object_byte_sex, 1033 object_addr, object_size, &objc_sections, 1034 &nobjc_sections, "__runtime_setup", §, §_addr, 1035 §_size); 1036 1037 if (verbose) 1038 get_cstring_section(load_commands, ncmds, sizeofcmds, object_byte_sex, 1039 object_addr, object_size, &cstring_section); 1040 1041 host_byte_sex = get_host_byte_sex(); 1042 swapped = host_byte_sex != object_byte_sex; 1043 1044 PHASH = (struct _hashEntry_t **)sect; 1045 for(i = 0; 1046 i < SIZEHASHTABLE && (i + 1) * sizeof(uint32_t) < sect_size; 1047 i++){ 1048 1049 memcpy(&phash, PHASH + i, sizeof(uint32_t)); 1050 if(swapped) 1051 phash = SWAP_INT(phash); 1052 1053 if(phash == 0) 1054 continue; 1055 1056 printf("PHASH[%3u] 0x%x", i, (unsigned int)phash); 1057 if(print_PHASH(4, phash, 1058 objc_sections, nobjc_sections, &cstring_section, 1059 host_byte_sex, swapped, verbose) == FALSE) 1060 printf(" (not in an " SEG_OBJC " section)\n"); 1061 } 1062 1063 HASH = (struct _hashEntry_t *)(PHASH + SIZEHASHTABLE); 1064 for(i = 0; (char *)(HASH + i) < sect + sect_size; i++){ 1065 memcpy((char *)&_hashEntry, HASH + i, sizeof(struct _hashEntry_t)); 1066 if(swapped) 1067 swap_hashEntry_t(&_hashEntry, host_byte_sex); 1068 1069 printf("HASH at 0x%08x\n", 1070 (unsigned int)(sect_addr + (char *)(HASH + i) - sect)); 1071 printf(" sel 0x%08x", (unsigned int)_hashEntry.sel); 1072 if(verbose){ 1073 p = get_pointer(_hashEntry.sel, &left, objc_sections, 1074 nobjc_sections, &cstring_section); 1075 if(p != NULL) 1076 printf(" %.*s\n", (int)left, p); 1077 else 1078 printf(" (not in an " SEG_OBJC " section)\n"); 1079 } 1080 else 1081 printf("\n"); 1082 1083 printf(" next 0x%08x", (unsigned int)_hashEntry.next); 1084 if(_hashEntry.next == 0){ 1085 printf("\n"); 1086 } 1087 else{ 1088 if((uint32_t)_hashEntry.next < sect_addr || 1089 (uint32_t)_hashEntry.next >= sect_addr + sect_size) 1090 printf(" (not in the ("SEG_OBJC ",__runtime_setup " 1091 "section)\n"); 1092 else 1093 printf("\n"); 1094 } 1095 } 1096} 1097 1098static 1099void 1100get_objc_sections( 1101struct load_command *load_commands, 1102uint32_t ncmds, 1103uint32_t sizeofcmds, 1104enum byte_sex object_byte_sex, 1105char *object_addr, 1106uint32_t object_size, 1107struct section_info **objc_sections, 1108uint32_t *nobjc_sections, 1109char *sectname, 1110char **sect, 1111uint32_t *sect_addr, 1112uint32_t *sect_size) 1113{ 1114 enum byte_sex host_byte_sex; 1115 enum bool swapped, encrypt_found, encrypt64_found; 1116 1117 uint32_t i, j, left, size; 1118 struct load_command lcmd, *lc; 1119 char *p; 1120 struct segment_command sg; 1121 struct section s; 1122 struct encryption_info_command encrypt; 1123 struct encryption_info_command_64 encrypt64; 1124 1125 host_byte_sex = get_host_byte_sex(); 1126 swapped = host_byte_sex != object_byte_sex; 1127 1128 *objc_sections = NULL; 1129 *nobjc_sections = 0; 1130 *sect = NULL; 1131 *sect_addr = 0; 1132 *sect_size = 0; 1133 encrypt_found = FALSE; 1134 encrypt64_found = FALSE; 1135 1136 lc = load_commands; 1137 for(i = 0 ; i < ncmds; i++){ 1138 memcpy((char *)&lcmd, (char *)lc, sizeof(struct load_command)); 1139 if(swapped) 1140 swap_load_command(&lcmd, host_byte_sex); 1141 if(lcmd.cmdsize % sizeof(int32_t) != 0) 1142 printf("load command %u size not a multiple of " 1143 "sizeof(int32_t)\n", i); 1144 if((char *)lc + lcmd.cmdsize > 1145 (char *)load_commands + sizeofcmds) 1146 printf("load command %u extends past end of load " 1147 "commands\n", i); 1148 left = sizeofcmds - ((char *)lc - (char *)load_commands); 1149 1150 switch(lcmd.cmd){ 1151 case LC_SEGMENT: 1152 memset((char *)&sg, '\0', sizeof(struct segment_command)); 1153 size = left < sizeof(struct segment_command) ? 1154 left : sizeof(struct segment_command); 1155 memcpy((char *)&sg, (char *)lc, size); 1156 if(swapped) 1157 swap_segment_command(&sg, host_byte_sex); 1158 1159 p = (char *)lc + sizeof(struct segment_command); 1160 for(j = 0 ; j < sg.nsects ; j++){ 1161 if(p + sizeof(struct section) > 1162 (char *)load_commands + sizeofcmds){ 1163 printf("section structure command extends past " 1164 "end of load commands\n"); 1165 } 1166 left = sizeofcmds - (p - (char *)load_commands); 1167 memset((char *)&s, '\0', sizeof(struct section)); 1168 size = left < sizeof(struct section) ? 1169 left : sizeof(struct section); 1170 memcpy((char *)&s, p, size); 1171 if(swapped) 1172 swap_section(&s, 1, host_byte_sex); 1173 1174 if(strcmp(s.segname, SEG_OBJC) == 0){ 1175 *objc_sections = reallocate(*objc_sections, 1176 sizeof(struct section_info) * (*nobjc_sections + 1)); 1177 (*objc_sections)[*nobjc_sections].addr = s.addr; 1178 (*objc_sections)[*nobjc_sections].contents = 1179 object_addr + s.offset; 1180 (*objc_sections)[*nobjc_sections].offset = s.offset; 1181 (*objc_sections)[*nobjc_sections].zerofill = 1182 (s.flags & SECTION_TYPE) == S_ZEROFILL ? TRUE : FALSE; 1183 if(s.offset > object_size){ 1184 printf("section contents of: (%.16s,%.16s) is past " 1185 "end of file\n", s.segname, s.sectname); 1186 (*objc_sections)[*nobjc_sections].size = 0; 1187 } 1188 else if(s.offset + s.size > object_size){ 1189 printf("part of section contents of: (%.16s,%.16s) " 1190 "is past end of file\n", 1191 s.segname, s.sectname); 1192 (*objc_sections)[*nobjc_sections].size = 1193 object_size - s.offset; 1194 } 1195 else 1196 (*objc_sections)[*nobjc_sections].size = s.size; 1197 1198 if(strncmp(s.sectname, sectname, 16) == 0){ 1199 if(*sect != NULL) 1200 printf("more than one (" SEG_OBJC ",%s) " 1201 "section\n", sectname); 1202 else{ 1203 *sect = (object_addr + s.offset); 1204 *sect_size = s.size; 1205 *sect_addr = s.addr; 1206 } 1207 } 1208 if(sg.flags & SG_PROTECTED_VERSION_1) 1209 (*objc_sections)[*nobjc_sections].protected = TRUE; 1210 else 1211 (*objc_sections)[*nobjc_sections].protected = FALSE; 1212 (*nobjc_sections)++; 1213 } 1214 1215 if(p + sizeof(struct section) > 1216 (char *)load_commands + sizeofcmds) 1217 break; 1218 p += size; 1219 } 1220 break; 1221 case LC_ENCRYPTION_INFO: 1222 memset((char *)&encrypt, '\0', 1223 sizeof(struct encryption_info_command)); 1224 size = left < sizeof(struct encryption_info_command) ? 1225 left : sizeof(struct encryption_info_command); 1226 memcpy((char *)&encrypt, (char *)lc, size); 1227 if(swapped) 1228 swap_encryption_command(&encrypt, host_byte_sex); 1229 encrypt_found = TRUE; 1230 break; 1231 case LC_ENCRYPTION_INFO_64: 1232 memset((char *)&encrypt64, '\0', 1233 sizeof(struct encryption_info_command_64)); 1234 size = left < sizeof(struct encryption_info_command_64) ? 1235 left : sizeof(struct encryption_info_command_64); 1236 memcpy((char *)&encrypt64, (char *)lc, size); 1237 if(swapped) 1238 swap_encryption_command_64(&encrypt64, host_byte_sex); 1239 encrypt64_found = TRUE; 1240 break; 1241 } 1242 if(lcmd.cmdsize == 0){ 1243 printf("load command %u size zero (can't advance to other " 1244 "load commands)\n", i); 1245 break; 1246 } 1247 lc = (struct load_command *)((char *)lc + lcmd.cmdsize); 1248 if((char *)lc > (char *)load_commands + sizeofcmds) 1249 break; 1250 } 1251 1252 if(encrypt_found == TRUE && encrypt.cryptid != 0){ 1253 for(i = 0; i < *nobjc_sections; i++){ 1254 if((*objc_sections)[i].size > 0 && 1255 (*objc_sections)[i].zerofill == FALSE){ 1256 if((*objc_sections)[i].offset > 1257 encrypt.cryptoff + encrypt.cryptsize){ 1258 /* section starts past encryption area */ ; 1259 } 1260 else if((*objc_sections)[i].offset + 1261 (*objc_sections)[i].size < encrypt.cryptoff){ 1262 /* section ends before encryption area */ ; 1263 } 1264 else{ 1265 /* section has part in the encrypted area */ 1266 (*objc_sections)[i].protected = TRUE; 1267 } 1268 } 1269 } 1270 } 1271 if(encrypt64_found == TRUE && encrypt64.cryptid != 0){ 1272 for(i = 0; i < *nobjc_sections; i++){ 1273 if((*objc_sections)[i].size > 0 && 1274 (*objc_sections)[i].zerofill == FALSE){ 1275 if((*objc_sections)[i].offset > 1276 encrypt64.cryptoff + encrypt64.cryptsize){ 1277 /* section starts past encryption area */ ; 1278 } 1279 else if((*objc_sections)[i].offset + 1280 (*objc_sections)[i].size < encrypt64.cryptoff){ 1281 /* section ends before encryption area */ ; 1282 } 1283 else{ 1284 /* section has part in the encrypted area */ 1285 (*objc_sections)[i].protected = TRUE; 1286 } 1287 } 1288 } 1289 } 1290} 1291 1292static 1293void 1294get_cstring_section( 1295struct load_command *load_commands, 1296uint32_t ncmds, 1297uint32_t sizeofcmds, 1298enum byte_sex object_byte_sex, 1299char *object_addr, 1300uint32_t object_size, 1301struct section_info *cstring_section) 1302{ 1303 enum byte_sex host_byte_sex; 1304 enum bool swapped; 1305 1306 uint32_t i, j, left, size; 1307 struct load_command lcmd, *lc; 1308 char *p; 1309 struct segment_command sg; 1310 struct section s; 1311 1312 host_byte_sex = get_host_byte_sex(); 1313 swapped = host_byte_sex != object_byte_sex; 1314 1315 memset(cstring_section, '\0', sizeof(struct section_info)); 1316 1317 lc = load_commands; 1318 for(i = 0 ; i < ncmds; i++){ 1319 memcpy((char *)&lcmd, (char *)lc, sizeof(struct load_command)); 1320 if(swapped) 1321 swap_load_command(&lcmd, host_byte_sex); 1322 if(lcmd.cmdsize % sizeof(int32_t) != 0) 1323 printf("load command %u size not a multiple of " 1324 "sizeof(int32_t)\n", i); 1325 if((char *)lc + lcmd.cmdsize > 1326 (char *)load_commands + sizeofcmds) 1327 printf("load command %u extends past end of load " 1328 "commands\n", i); 1329 left = sizeofcmds - ((char *)lc - (char *)load_commands); 1330 1331 switch(lcmd.cmd){ 1332 case LC_SEGMENT: 1333 memset((char *)&sg, '\0', sizeof(struct segment_command)); 1334 size = left < sizeof(struct segment_command) ? 1335 left : sizeof(struct segment_command); 1336 memcpy((char *)&sg, (char *)lc, size); 1337 if(swapped) 1338 swap_segment_command(&sg, host_byte_sex); 1339 1340 p = (char *)lc + sizeof(struct segment_command); 1341 for(j = 0 ; j < sg.nsects ; j++){ 1342 if(p + sizeof(struct section) > 1343 (char *)load_commands + sizeofcmds){ 1344 printf("section structure command extends past " 1345 "end of load commands\n"); 1346 } 1347 left = sizeofcmds - (p - (char *)load_commands); 1348 memset((char *)&s, '\0', sizeof(struct section)); 1349 size = left < sizeof(struct section) ? 1350 left : sizeof(struct section); 1351 memcpy((char *)&s, p, size); 1352 if(swapped) 1353 swap_section(&s, 1, host_byte_sex); 1354 1355 if(strcmp(s.segname, SEG_TEXT) == 0 && 1356 strcmp(s.sectname, "__cstring") == 0){ 1357 cstring_section->addr = s.addr; 1358 cstring_section->contents = object_addr + s.offset; 1359 if(s.offset > object_size){ 1360 printf("section contents of: (%.16s,%.16s) is past " 1361 "end of file\n", s.segname, s.sectname); 1362 cstring_section->size = 0; 1363 } 1364 else if(s.offset + s.size > object_size){ 1365 printf("part of section contents of: (%.16s,%.16s) " 1366 "is past end of file\n", 1367 s.segname, s.sectname); 1368 cstring_section->size = object_size - s.offset; 1369 } 1370 else 1371 cstring_section->size = s.size; 1372 if(sg.flags & SG_PROTECTED_VERSION_1) 1373 cstring_section->protected = TRUE; 1374 else 1375 cstring_section->protected = FALSE; 1376 return; 1377 } 1378 1379 if(p + sizeof(struct section) > 1380 (char *)load_commands + sizeofcmds) 1381 break; 1382 p += size; 1383 } 1384 break; 1385 } 1386 if(lcmd.cmdsize == 0){ 1387 printf("load command %u size zero (can't advance to other " 1388 "load commands)\n", i); 1389 break; 1390 } 1391 lc = (struct load_command *)((char *)lc + lcmd.cmdsize); 1392 if((char *)lc > (char *)load_commands + sizeofcmds) 1393 break; 1394 } 1395} 1396 1397static 1398enum bool 1399print_method_list( 1400uint32_t addr, 1401struct section_info *objc_sections, 1402uint32_t nobjc_sections, 1403struct section_info *cstring_section_ptr, 1404enum byte_sex host_byte_sex, 1405enum bool swapped, 1406struct symbol *sorted_symbols, 1407uint32_t nsorted_symbols, 1408enum bool verbose) 1409{ 1410 struct objc_method_t *methods, method; 1411 struct objc_method_list_t method_list; 1412 enum bool trunc; 1413 uint32_t i, methods_left, left; 1414 char *p; 1415 1416 if(get_method_list(addr, &method_list, &methods, &methods_left, &trunc, 1417 objc_sections, nobjc_sections, 1418 host_byte_sex, swapped) == FALSE) 1419 return(FALSE); 1420 1421 printf("\n"); 1422 if(trunc == TRUE) 1423 printf("\t\t objc_method_list extends past end of the section\n"); 1424 1425 printf("\t\t obsolete 0x%08x\n", 1426 (unsigned int)method_list.obsolete); 1427 printf("\t\t method_count %d\n", 1428 method_list.method_count); 1429 1430 for(i = 0; i < (uint32_t)method_list.method_count; i++){ 1431 if((i + 1) * sizeof(struct objc_method_t) > methods_left){ 1432 printf("\t\t remaining method's extend past the of the " 1433 "section\n"); 1434 break; 1435 } 1436 memcpy(&method, methods + i, sizeof(struct objc_method_t)); 1437 if(swapped) 1438 swap_objc_method_t(&method, host_byte_sex); 1439 1440 printf("\t\t method_name 0x%08x", method.method_name); 1441 if(verbose){ 1442 p = get_pointer(method.method_name, &left, objc_sections, 1443 nobjc_sections, cstring_section_ptr); 1444 if(p != NULL) 1445 printf(" %.*s\n", (int)left, p); 1446 else 1447 printf(" (not in an " SEG_OBJC " section)\n"); 1448 } 1449 else 1450 printf("\n"); 1451 1452 printf("\t\t method_types 0x%08x", method.method_types); 1453 if(verbose){ 1454 p = get_pointer(method.method_types, &left, objc_sections, 1455 nobjc_sections, cstring_section_ptr); 1456 if(p != NULL) 1457 printf(" %.*s\n", (int)left, p); 1458 else 1459 printf(" (not in an " SEG_OBJC " section)\n"); 1460 } 1461 else 1462 printf("\n"); 1463 printf("\t\t method_imp 0x%08x ", method.method_imp); 1464 if(verbose) 1465 print_label(method.method_imp, FALSE, sorted_symbols, 1466 nsorted_symbols); 1467 printf("\n"); 1468 } 1469 return(TRUE); 1470} 1471 1472static 1473enum bool 1474print_protocol_list( 1475uint32_t indent, 1476uint32_t addr, 1477struct section_info *objc_sections, 1478uint32_t nobjc_sections, 1479struct section_info *cstring_section_ptr, 1480enum byte_sex host_byte_sex, 1481enum bool swapped, 1482enum bool verbose) 1483{ 1484 uint32_t *list; 1485 struct objc_protocol_t protocol; 1486 struct objc_protocol_list_t protocol_list; 1487 enum bool trunc; 1488 uint32_t l, i, list_left; 1489 1490 if(get_protocol_list(addr, &protocol_list, &list, &list_left, &trunc, 1491 objc_sections, nobjc_sections, 1492 host_byte_sex, swapped) == FALSE) 1493 return(FALSE); 1494 1495 printf("\n"); 1496 if(trunc == TRUE){ 1497 print_indent(indent); 1498 printf(" objc_protocol_list extends past end of the section\n"); 1499 } 1500 1501 print_indent(indent); 1502 printf(" next 0x%08x\n", 1503 (unsigned int)protocol_list.next); 1504 print_indent(indent); 1505 printf(" count %u\n", protocol_list.count); 1506 1507 for(i = 0; i < protocol_list.count; i++){ 1508 if((i + 1) * sizeof(uint32_t) > list_left){ 1509 print_indent(indent); 1510 printf(" remaining list entries extend past the of the " 1511 "section\n"); 1512 break; 1513 } 1514 memcpy(&l, list + i, sizeof(uint32_t)); 1515 if(swapped) 1516 l = SWAP_INT(l); 1517 1518 print_indent(indent); 1519 printf(" list[%u] 0x%08x", i, l); 1520 if(get_protocol(l, &protocol, &trunc, objc_sections, nobjc_sections, 1521 host_byte_sex, swapped) == FALSE){ 1522 printf(" (not in an " SEG_OBJC " section)\n"); 1523 continue; 1524 } 1525 printf("\n"); 1526 if(trunc == TRUE){ 1527 print_indent(indent); 1528 printf(" Protocol extends past end of the " 1529 "section\n"); 1530 } 1531 print_protocol(indent, &protocol, 1532 objc_sections, nobjc_sections, cstring_section_ptr, 1533 host_byte_sex, swapped, verbose); 1534 } 1535 return(TRUE); 1536} 1537 1538static 1539void 1540print_protocol( 1541uint32_t indent, 1542struct objc_protocol_t *protocol, 1543struct section_info *objc_sections, 1544uint32_t nobjc_sections, 1545struct section_info *cstring_section_ptr, 1546enum byte_sex host_byte_sex, 1547enum bool swapped, 1548enum bool verbose) 1549{ 1550 uint32_t left; 1551 char *p; 1552 1553 print_indent(indent); 1554 printf(" isa 0x%08x\n", 1555 (unsigned int)protocol->isa); 1556 print_indent(indent); 1557 printf(" protocol_name 0x%08x", 1558 (unsigned int)protocol->protocol_name); 1559 if(verbose){ 1560 p = get_pointer(protocol->protocol_name, &left, 1561 objc_sections, nobjc_sections, cstring_section_ptr); 1562 if(p != NULL) 1563 printf(" %.*s\n", (int)left, p); 1564 else 1565 printf(" (not in an " SEG_OBJC " section)\n"); 1566 } 1567 else 1568 printf("\n"); 1569 print_indent(indent); 1570 printf(" protocol_list 0x%08x", 1571 (unsigned int)protocol->protocol_list); 1572 if(print_protocol_list(indent + 4, protocol->protocol_list, 1573 objc_sections, nobjc_sections, cstring_section_ptr, 1574 host_byte_sex, swapped, verbose) == FALSE) 1575 printf(" (not in an " SEG_OBJC " section)\n"); 1576 1577 print_indent(indent); 1578 printf(" instance_methods 0x%08x", 1579 (unsigned int)protocol->instance_methods); 1580 if(print_method_description_list(indent, protocol->instance_methods, 1581 objc_sections, nobjc_sections, cstring_section_ptr, 1582 host_byte_sex, swapped, verbose) == FALSE) 1583 printf(" (not in an " SEG_OBJC " section)\n"); 1584 1585 print_indent(indent); 1586 printf(" class_methods 0x%08x", 1587 (unsigned int)protocol->class_methods); 1588 if(print_method_description_list(indent, protocol->class_methods, 1589 objc_sections, nobjc_sections, cstring_section_ptr, 1590 host_byte_sex, swapped, verbose) == FALSE) 1591 printf(" (not in an " SEG_OBJC " section)\n"); 1592} 1593 1594static 1595enum bool 1596print_method_description_list( 1597 uint32_t indent, 1598 uint32_t addr, 1599 struct section_info *objc_sections, 1600 uint32_t nobjc_sections, 1601 struct section_info *cstring_section_ptr, 1602 enum byte_sex host_byte_sex, 1603 enum bool swapped, 1604 enum bool verbose) 1605{ 1606 struct objc_method_description_list_t mdl; 1607 struct objc_method_description_t *list, md; 1608 enum bool trunc; 1609 uint32_t i, list_left, left; 1610 char *p; 1611 1612 if(get_method_description_list(addr, &mdl, &list, &list_left, 1613 &trunc, objc_sections, nobjc_sections, 1614 host_byte_sex, swapped) == FALSE) 1615 return(FALSE); 1616 1617 printf("\n"); 1618 if(trunc == TRUE){ 1619 print_indent(indent); 1620 printf(" objc_method_description_list extends past end of the " 1621 "section\n"); 1622 } 1623 1624 print_indent(indent); 1625 printf(" count %d\n", mdl.count); 1626 1627 for(i = 0; i < (uint32_t)mdl.count; i++){ 1628 if((i + 1) * sizeof(struct objc_method_description_t) > list_left){ 1629 print_indent(indent); 1630 printf(" remaining list entries extend past the of the " 1631 "section\n"); 1632 break; 1633 } 1634 print_indent(indent); 1635 printf(" list[%u]\n", i); 1636 memcpy(&md, list + i, sizeof(struct objc_method_description_t)); 1637 if(swapped) 1638 swap_objc_method_description_t(&md, host_byte_sex); 1639 1640 print_indent(indent); 1641 printf(" name 0x%08x", (unsigned int)md.name); 1642 if(verbose){ 1643 p = get_pointer(md.name, &left, 1644 objc_sections, nobjc_sections, cstring_section_ptr); 1645 if(p != NULL) 1646 printf(" %.*s\n", (int)left, p); 1647 else 1648 printf(" (not in an " SEG_OBJC " section)\n"); 1649 } 1650 else 1651 printf("\n"); 1652 1653 print_indent(indent); 1654 printf(" types 0x%08x", (unsigned int)md.types); 1655 if(verbose){ 1656 p = get_pointer(md.types, &left, 1657 objc_sections, nobjc_sections, cstring_section_ptr); 1658 if(p != NULL) 1659 printf(" %.*s\n", (int)left, p); 1660 else 1661 printf(" (not in an " SEG_OBJC " section)\n"); 1662 } 1663 else 1664 printf("\n"); 1665 } 1666 return(TRUE); 1667} 1668 1669static enum bool 1670print_PHASH( 1671uint32_t indent, 1672uint32_t addr, 1673struct section_info *objc_sections, 1674uint32_t nobjc_sections, 1675struct section_info *cstring_section_ptr, 1676enum byte_sex host_byte_sex, 1677enum bool swapped, 1678enum bool verbose) 1679{ 1680 struct _hashEntry_t _hashEntry; 1681 enum bool trunc; 1682 uint32_t left; 1683 char *p; 1684 1685 if(get_hashEntry(addr, &_hashEntry, &trunc, objc_sections, 1686 nobjc_sections, host_byte_sex, swapped) == FALSE) 1687 return(FALSE); 1688 1689 printf("\n"); 1690 if(trunc == TRUE){ 1691 print_indent(indent); 1692 printf("_hashEntry extends past end of the section\n"); 1693 } 1694 1695 print_indent(indent); 1696 printf(" sel 0x%08x", (unsigned int)_hashEntry.sel); 1697 if(verbose){ 1698 p = get_pointer(_hashEntry.sel, &left, 1699 objc_sections, nobjc_sections, cstring_section_ptr); 1700 if(p != NULL) 1701 printf(" %.*s\n", (int)left, p); 1702 else 1703 printf(" (not in an " SEG_OBJC " section)\n"); 1704 } 1705 else 1706 printf("\n"); 1707 1708 print_indent(indent); 1709 printf("next 0x%08x", (unsigned int)_hashEntry.next); 1710 if(_hashEntry.next == 0){ 1711 printf("\n"); 1712 return(TRUE); 1713 } 1714 if(print_PHASH(indent+4, _hashEntry.next, 1715 objc_sections, nobjc_sections, cstring_section_ptr, 1716 host_byte_sex, swapped, verbose) == FALSE) 1717 printf(" (not in an " SEG_OBJC " section)\n"); 1718 return(TRUE); 1719} 1720 1721static 1722void 1723print_indent( 1724uint32_t indent) 1725{ 1726 uint32_t i; 1727 1728 for(i = 0; i < indent; ){ 1729 if(indent - i >= 8){ 1730 printf("\t"); 1731 i += 8; 1732 } 1733 else{ 1734 printf("%.*s", (int)(indent - i), " "); 1735 return; 1736 } 1737 } 1738} 1739 1740static 1741void * 1742get_pointer( 1743uint32_t addr, 1744uint32_t *left, 1745struct section_info *objc_sections, 1746uint32_t nobjc_sections, 1747struct section_info *cstring_section_ptr) 1748{ 1749 void* returnValue = NULL; 1750 uint32_t i; 1751 1752 if(addr >= cstring_section_ptr->addr && 1753 addr < cstring_section_ptr->addr + cstring_section_ptr->size){ 1754 *left = cstring_section_ptr->size - 1755 (addr - cstring_section_ptr->addr); 1756 if(cstring_section_ptr->protected == TRUE) 1757 returnValue = "some string from a protected section"; 1758 else 1759 returnValue = (cstring_section_ptr->contents + 1760 (addr - cstring_section_ptr->addr)); 1761 } 1762 for(i = 0; returnValue != NULL && i < nobjc_sections; i++){ 1763 if(addr >= objc_sections[i].addr && 1764 addr < objc_sections[i].addr + objc_sections[i].size){ 1765 *left = objc_sections[i].size - 1766 (addr - objc_sections[i].addr); 1767 returnValue = (objc_sections[i].contents + 1768 (addr - objc_sections[i].addr)); 1769 } 1770 } 1771 return(returnValue); 1772} 1773 1774static 1775enum bool 1776get_symtab( 1777uint32_t addr, 1778struct objc_symtab_t *symtab, 1779uint32_t **defs, 1780uint32_t *left, 1781enum bool *trunc, 1782struct section_info *objc_sections, 1783uint32_t nobjc_sections, 1784enum byte_sex host_byte_sex, 1785enum bool swapped) 1786{ 1787 uint32_t i; 1788 1789 memset(symtab, '\0', sizeof(struct objc_symtab_t)); 1790 if(addr == 0) 1791 return(0); 1792 for(i = 0; i < nobjc_sections; i++){ 1793 if(addr >= objc_sections[i].addr && 1794 addr < objc_sections[i].addr + objc_sections[i].size){ 1795 1796 *left = objc_sections[i].size - 1797 (addr - objc_sections[i].addr); 1798 if(*left >= sizeof(struct objc_symtab_t) - sizeof(uint32_t)){ 1799 memcpy(symtab, 1800 objc_sections[i].contents + 1801 (addr - objc_sections[i].addr), 1802 sizeof(struct objc_symtab_t) - sizeof(uint32_t)); 1803 *left -= sizeof(struct objc_symtab_t) - sizeof(uint32_t); 1804 *defs = (uint32_t *)(objc_sections[i].contents + 1805 (addr - objc_sections[i].addr) + 1806 sizeof(struct objc_symtab_t) - 1807 sizeof(uint32_t)); 1808 *trunc = FALSE; 1809 } 1810 else{ 1811 memcpy(symtab, 1812 objc_sections[i].contents + 1813 (addr - objc_sections[i].addr), 1814 *left); 1815 *left = 0; 1816 *defs = NULL; 1817 *trunc = TRUE; 1818 } 1819 if(swapped) 1820 swap_objc_symtab_t(symtab, host_byte_sex); 1821 return(TRUE); 1822 } 1823 } 1824 return(FALSE); 1825} 1826 1827static 1828enum bool 1829get_objc_class( 1830uint32_t addr, 1831struct objc_class_t *objc_class, 1832enum bool *trunc, 1833struct section_info *objc_sections, 1834uint32_t nobjc_sections, 1835enum byte_sex host_byte_sex, 1836enum bool swapped) 1837{ 1838 uint32_t left, i; 1839 1840 memset(objc_class, '\0', sizeof(struct objc_class_t)); 1841 if(addr == 0) 1842 return(FALSE); 1843 for(i = 0; i < nobjc_sections; i++){ 1844 if(addr >= objc_sections[i].addr && 1845 addr < objc_sections[i].addr + objc_sections[i].size){ 1846 1847 left = objc_sections[i].size - 1848 (addr - objc_sections[i].addr); 1849 if(left >= sizeof(struct objc_class_t)){ 1850 memcpy(objc_class, 1851 objc_sections[i].contents + 1852 (addr - objc_sections[i].addr), 1853 sizeof(struct objc_class_t)); 1854 *trunc = FALSE; 1855 } 1856 else{ 1857 memcpy(objc_class, 1858 objc_sections[i].contents + 1859 (addr - objc_sections[i].addr), 1860 left); 1861 *trunc = TRUE; 1862 } 1863 if(swapped) 1864 swap_objc_class_t(objc_class, host_byte_sex); 1865 return(TRUE); 1866 } 1867 } 1868 return(FALSE); 1869} 1870 1871static 1872enum bool 1873get_objc_category( 1874uint32_t addr, 1875struct objc_category_t *objc_category, 1876enum bool *trunc, 1877struct section_info *objc_sections, 1878uint32_t nobjc_sections, 1879enum byte_sex host_byte_sex, 1880enum bool swapped) 1881{ 1882 uint32_t left, i; 1883 1884 memset(objc_category, '\0', sizeof(struct objc_category_t)); 1885 if(addr == 0) 1886 return(FALSE); 1887 for(i = 0; i < nobjc_sections; i++){ 1888 if(addr >= objc_sections[i].addr && 1889 addr < objc_sections[i].addr + objc_sections[i].size){ 1890 1891 left = objc_sections[i].size - 1892 (addr - objc_sections[i].addr); 1893 if(left >= sizeof(struct objc_category_t)){ 1894 memcpy(objc_category, 1895 objc_sections[i].contents + 1896 (addr - objc_sections[i].addr), 1897 sizeof(struct objc_category_t)); 1898 *trunc = FALSE; 1899 } 1900 else{ 1901 memcpy(objc_category, 1902 objc_sections[i].contents + 1903 (addr - objc_sections[i].addr), 1904 left); 1905 *trunc = TRUE; 1906 } 1907 if(swapped) 1908 swap_objc_category_t(objc_category, host_byte_sex); 1909 return(TRUE); 1910 } 1911 } 1912 return(FALSE); 1913} 1914 1915static 1916enum bool 1917get_ivar_list( 1918uint32_t addr, 1919struct objc_ivar_list_t *objc_ivar_list, 1920struct objc_ivar_t **ivar_list, 1921uint32_t *left, 1922enum bool *trunc, 1923struct section_info *objc_sections, 1924uint32_t nobjc_sections, 1925enum byte_sex host_byte_sex, 1926enum bool swapped) 1927{ 1928 uint32_t i; 1929 1930 memset(objc_ivar_list, '\0', sizeof(struct objc_ivar_list_t)); 1931 if(addr == 0) 1932 return(FALSE); 1933 for(i = 0; i < nobjc_sections; i++){ 1934 if(addr >= objc_sections[i].addr && 1935 addr < objc_sections[i].addr + objc_sections[i].size){ 1936 1937 *left = objc_sections[i].size - 1938 (addr - objc_sections[i].addr); 1939 if(*left >= sizeof(struct objc_ivar_list_t) - 1940 sizeof(struct objc_ivar_t)){ 1941 memcpy(objc_ivar_list, 1942 objc_sections[i].contents + 1943 (addr - objc_sections[i].addr), 1944 sizeof(struct objc_ivar_list_t) - 1945 sizeof(struct objc_ivar_t)); 1946 *left -= sizeof(struct objc_ivar_list_t) - 1947 sizeof(struct objc_ivar_t); 1948 *ivar_list = (struct objc_ivar_t *) 1949 (objc_sections[i].contents + 1950 (addr - objc_sections[i].addr) + 1951 sizeof(struct objc_ivar_list_t) - 1952 sizeof(struct objc_ivar_t)); 1953 *trunc = FALSE; 1954 } 1955 else{ 1956 memcpy(objc_ivar_list, 1957 objc_sections[i].contents + 1958 (addr - objc_sections[i].addr), 1959 *left); 1960 *left = 0; 1961 *ivar_list = NULL; 1962 *trunc = TRUE; 1963 } 1964 if(swapped) 1965 swap_objc_ivar_list_t(objc_ivar_list, host_byte_sex); 1966 return(TRUE); 1967 } 1968 } 1969 return(FALSE); 1970} 1971 1972static 1973enum bool 1974get_method_list( 1975uint32_t addr, 1976struct objc_method_list_t *method_list, 1977struct objc_method_t **methods, 1978uint32_t *left, 1979enum bool *trunc, 1980struct section_info *objc_sections, 1981uint32_t nobjc_sections, 1982enum byte_sex host_byte_sex, 1983enum bool swapped) 1984{ 1985 uint32_t i; 1986 1987 memset(method_list, '\0', sizeof(struct objc_method_list_t)); 1988 if(addr == 0) 1989 return(FALSE); 1990 for(i = 0; i < nobjc_sections; i++){ 1991 if(addr >= objc_sections[i].addr && 1992 addr < objc_sections[i].addr + objc_sections[i].size){ 1993 1994 *left = objc_sections[i].size - 1995 (addr - objc_sections[i].addr); 1996 if(*left >= sizeof(struct objc_method_list_t) - 1997 sizeof(struct objc_method_t)){ 1998 memcpy(method_list, 1999 objc_sections[i].contents + 2000 (addr - objc_sections[i].addr), 2001 sizeof(struct objc_method_list_t) - 2002 sizeof(struct objc_method_t)); 2003 *left -= sizeof(struct objc_method_list_t) - 2004 sizeof(struct objc_method_t); 2005 *methods = (struct objc_method_t *) 2006 (objc_sections[i].contents + 2007 (addr - objc_sections[i].addr) + 2008 sizeof(struct objc_method_list_t) - 2009 sizeof(struct objc_method_t)); 2010 *trunc = FALSE; 2011 } 2012 else{ 2013 memcpy(method_list, 2014 objc_sections[i].contents + 2015 (addr - objc_sections[i].addr), 2016 *left); 2017 *left = 0; 2018 *methods = NULL; 2019 *trunc = TRUE; 2020 } 2021 if(swapped) 2022 swap_objc_method_list_t(method_list, host_byte_sex); 2023 return(TRUE); 2024 } 2025 } 2026 return(FALSE); 2027} 2028 2029static 2030enum bool 2031get_protocol_list( 2032uint32_t addr, 2033struct objc_protocol_list_t *protocol_list, 2034uint32_t **list, 2035uint32_t *left, 2036enum bool *trunc, 2037struct section_info *objc_sections, 2038uint32_t nobjc_sections, 2039enum byte_sex host_byte_sex, 2040enum bool swapped) 2041{ 2042 uint32_t i; 2043 2044 memset(protocol_list, '\0', sizeof(struct objc_protocol_list_t)); 2045 if(addr == 0) 2046 return(FALSE); 2047 for(i = 0; i < nobjc_sections; i++){ 2048 if(addr >= objc_sections[i].addr && 2049 addr < objc_sections[i].addr + objc_sections[i].size){ 2050 2051 *left = objc_sections[i].size - 2052 (addr - objc_sections[i].addr); 2053 if(*left >= sizeof(struct objc_protocol_list_t) - 2054 sizeof(uint32_t)){ 2055 memcpy(protocol_list, 2056 objc_sections[i].contents + 2057 (addr - objc_sections[i].addr), 2058 sizeof(struct objc_protocol_list_t) - 2059 sizeof(uint32_t)); 2060 *left -= sizeof(struct objc_protocol_list_t) - 2061 sizeof(uint32_t); 2062 *list = (uint32_t *) 2063 (objc_sections[i].contents + 2064 (addr - objc_sections[i].addr) + 2065 sizeof(struct objc_protocol_list_t) - 2066 sizeof(uint32_t)); 2067 *trunc = FALSE; 2068 } 2069 else{ 2070 memcpy(protocol_list, 2071 objc_sections[i].contents + 2072 (addr - objc_sections[i].addr), 2073 *left); 2074 *left = 0; 2075 *list = NULL; 2076 *trunc = TRUE; 2077 } 2078 if(swapped) 2079 swap_objc_protocol_list_t(protocol_list, host_byte_sex); 2080 return(TRUE); 2081 } 2082 } 2083 return(FALSE); 2084} 2085 2086static 2087enum bool 2088get_protocol( 2089uint32_t addr, 2090struct objc_protocol_t *protocol, 2091enum bool *trunc, 2092struct section_info *objc_sections, 2093uint32_t nobjc_sections, 2094enum byte_sex host_byte_sex, 2095enum bool swapped) 2096{ 2097 uint32_t left, i; 2098 2099 memset(protocol, '\0', sizeof(struct objc_protocol_t)); 2100 if(addr == 0) 2101 return(FALSE); 2102 for(i = 0; i < nobjc_sections; i++){ 2103 if(addr >= objc_sections[i].addr && 2104 addr < objc_sections[i].addr + objc_sections[i].size){ 2105 2106 left = objc_sections[i].size - 2107 (addr - objc_sections[i].addr); 2108 if(left >= sizeof(struct objc_protocol_t)){ 2109 memcpy(protocol, 2110 objc_sections[i].contents + 2111 (addr - objc_sections[i].addr), 2112 sizeof(struct objc_protocol_t)); 2113 *trunc = FALSE; 2114 } 2115 else{ 2116 memcpy(protocol, 2117 objc_sections[i].contents + 2118 (addr - objc_sections[i].addr), 2119 left); 2120 *trunc = TRUE; 2121 } 2122 if(swapped) 2123 swap_objc_protocol_t(protocol, host_byte_sex); 2124 return(TRUE); 2125 } 2126 } 2127 return(FALSE); 2128} 2129 2130static 2131enum bool 2132get_method_description_list( 2133uint32_t addr, 2134struct objc_method_description_list_t *mdl, 2135struct objc_method_description_t **list, 2136uint32_t *left, 2137enum bool *trunc, 2138struct section_info *objc_sections, 2139uint32_t nobjc_sections, 2140enum byte_sex host_byte_sex, 2141enum bool swapped) 2142{ 2143 uint32_t i; 2144 2145 memset(mdl, '\0', sizeof(struct objc_method_description_list_t)); 2146 if(addr == 0) 2147 return(FALSE); 2148 for(i = 0; i < nobjc_sections; i++){ 2149 if(addr >= objc_sections[i].addr && 2150 addr < objc_sections[i].addr + objc_sections[i].size){ 2151 2152 *left = objc_sections[i].size - 2153 (addr - objc_sections[i].addr); 2154 if(*left >= sizeof(struct objc_method_description_list_t) - 2155 sizeof(struct objc_method_description_t)){ 2156 memcpy(mdl, 2157 objc_sections[i].contents + 2158 (addr - objc_sections[i].addr), 2159 sizeof(struct objc_method_description_list_t) - 2160 sizeof(struct objc_method_description_t)); 2161 *left -= sizeof(struct objc_method_description_list_t) - 2162 sizeof(struct objc_method_description_t); 2163 *list = (struct objc_method_description_t *) 2164 (objc_sections[i].contents + 2165 (addr - objc_sections[i].addr) + 2166 sizeof(struct objc_method_description_list_t) - 2167 sizeof(struct objc_method_description_t)); 2168 *trunc = FALSE; 2169 } 2170 else{ 2171 memcpy(mdl, 2172 objc_sections[i].contents + 2173 (addr - objc_sections[i].addr), 2174 *left); 2175 *left = 0; 2176 *list = NULL; 2177 *trunc = TRUE; 2178 } 2179 if(swapped) 2180 swap_objc_method_description_list_t(mdl, host_byte_sex); 2181 return(TRUE); 2182 } 2183 } 2184 return(FALSE); 2185} 2186 2187static 2188enum bool 2189get_hashEntry( 2190uint32_t addr, 2191struct _hashEntry_t *_hashEntry, 2192enum bool *trunc, 2193struct section_info *objc_sections, 2194uint32_t nobjc_sections, 2195enum byte_sex host_byte_sex, 2196enum bool swapped) 2197{ 2198 uint32_t left, i; 2199 2200 memset(_hashEntry, '\0', sizeof(struct _hashEntry_t)); 2201 if(addr == 0) 2202 return(FALSE); 2203 for(i = 0; i < nobjc_sections; i++){ 2204 if(addr >= objc_sections[i].addr && 2205 addr < objc_sections[i].addr + objc_sections[i].size){ 2206 2207 left = objc_sections[i].size - 2208 (addr - objc_sections[i].addr); 2209 if(left >= sizeof(struct _hashEntry_t)){ 2210 memcpy(_hashEntry, 2211 objc_sections[i].contents + 2212 (addr - objc_sections[i].addr), 2213 sizeof(struct _hashEntry_t)); 2214 *trunc = FALSE; 2215 } 2216 else{ 2217 memcpy(_hashEntry, 2218 objc_sections[i].contents + 2219 (addr - objc_sections[i].addr), 2220 left); 2221 *trunc = TRUE; 2222 } 2223 if(swapped) 2224 swap_hashEntry_t(_hashEntry, host_byte_sex); 2225 return(TRUE); 2226 } 2227 } 2228 return(FALSE); 2229} 2230