836
[darwin-xtools.git] / cctools / otool / print_objc.c
blob925cdc4292749d17c05e57ac323b3811dcb18543
1 /*
2 * Copyright © 2009 Apple Inc. All rights reserved.
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.
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.
29 * @APPLE_LICENSE_HEADER_END@
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"
41 * Here we need structures that have the same memory layout and size as the
42 * 32-bit Objective-C 1 meta data structures.
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.
49 struct 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) */
56 struct 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 */
64 struct 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) */
77 struct 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) */
85 struct 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;
91 struct objc_ivar_list_t {
92 int32_t ivar_count;
93 struct objc_ivar_t ivar_list[1]; /* variable length structure */
96 struct 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) */
103 struct 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 */
109 struct 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) */
120 struct 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) */
127 struct objc_method_description_t {
128 uint32_t name; /* SEL, aka struct objc_selector * (32-bit pointer) */
129 uint32_t types; /* char * (32-bit pointer) */
132 struct objc_method_description_list_t {
133 int32_t count;
134 struct objc_method_description_t list[1];
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.
142 struct 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;
147 typedef struct objc_string_object_t NXConstantString;
149 #define SIZEHASHTABLE 821
150 struct _hashEntry_t {
151 uint32_t next; /* struct _hashEntry * (32-bit pointer) */
152 uint32_t sel; /* char * (32-bit pointer) */
155 struct imageInfo_t {
156 uint32_t version;
157 uint32_t flags;
160 static
161 void
162 swap_imageInfo_t(
163 struct imageInfo_t *o,
164 enum byte_sex target_byte_sex)
166 o->version = SWAP_INT(o->version);
167 o->flags = SWAP_INT(o->flags);
170 void
171 swap_objc_module_t(
172 struct objc_module_t *module,
173 enum byte_sex target_byte_sex)
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);
181 void
182 swap_objc_symtab_t(
183 struct objc_symtab_t *symtab,
184 enum byte_sex target_byte_sex)
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);
192 void
193 swap_objc_class_t(
194 struct objc_class_t *objc_class,
195 enum byte_sex target_byte_sex)
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);
209 void
210 swap_objc_category_t(
211 struct objc_category_t *objc_category,
212 enum byte_sex target_byte_sex)
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);
224 void
225 swap_objc_ivar_list_t(
226 struct objc_ivar_list_t *objc_ivar_list,
227 enum byte_sex target_byte_sex)
229 objc_ivar_list->ivar_count = SWAP_INT(objc_ivar_list->ivar_count);
232 void
233 swap_objc_ivar_t(
234 struct objc_ivar_t *objc_ivar,
235 enum byte_sex target_byte_sex)
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);
242 void
243 swap_objc_method_list_t(
244 struct objc_method_list_t *method_list,
245 enum byte_sex target_byte_sex)
247 method_list->obsolete = SWAP_INT(method_list->obsolete);
248 method_list->method_count = SWAP_INT(method_list->method_count);
251 void
252 swap_objc_method_t(
253 struct objc_method_t *method,
254 enum byte_sex target_byte_sex)
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);
261 void
262 swap_objc_protocol_list_t(
263 struct objc_protocol_list_t *protocol_list,
264 enum byte_sex target_byte_sex)
266 protocol_list->next = SWAP_INT(protocol_list->next);
267 protocol_list->count = SWAP_INT(protocol_list->count);
270 void
271 swap_objc_protocol_t(
272 struct objc_protocol_t *protocol,
273 enum byte_sex target_byte_sex)
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);
282 void
283 swap_objc_method_description_list_t(
284 struct objc_method_description_list_t *mdl,
285 enum byte_sex target_byte_sex)
287 mdl->count = SWAP_INT(mdl->count);
290 void
291 swap_objc_method_description_t(
292 struct objc_method_description_t *md,
293 enum byte_sex target_byte_sex)
295 md->name = SWAP_INT(md->name);
296 md->types = SWAP_INT(md->types);
299 void
300 swap_string_object_t(
301 struct objc_string_object_t *string_object,
302 enum byte_sex target_byte_sex)
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);
309 void
310 swap_hashEntry_t(
311 struct _hashEntry_t *_hashEntry,
312 enum byte_sex target_byte_sex)
314 _hashEntry->next = SWAP_INT(_hashEntry->next);
315 _hashEntry->sel = SWAP_INT(_hashEntry->sel);
318 struct 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;
327 static 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);
341 static 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);
350 static 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);
361 static 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);
371 static 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);
381 static 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);
391 static 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);
401 static void print_indent(
402 uint32_t indent);
404 static 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);
411 static 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);
422 static 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);
431 static 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);
440 static 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);
451 static 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);
462 static 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);
473 static 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);
482 static 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);
493 static 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);
503 * Print the objc segment.
505 enum bool
506 print_objc_segment(
507 cpu_type_t mh_cputype,
508 struct load_command *load_commands,
509 uint32_t ncmds,
510 uint32_t sizeofcmds,
511 enum byte_sex object_byte_sex,
512 char *object_addr,
513 uint32_t object_size,
514 struct symbol *sorted_symbols,
515 uint32_t nsorted_symbols,
516 enum bool verbose)
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;
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;
535 struct imageInfo_t *imageInfo, info;
536 uint32_t imageInfo_addr, imageInfo_size;
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);
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);
552 if (verbose)
553 get_cstring_section(load_commands, ncmds, sizeofcmds, object_byte_sex,
554 object_addr, object_size, &cstring_section);
556 host_byte_sex = get_host_byte_sex();
557 swapped = host_byte_sex != object_byte_sex;
559 memset(&module, '\0', sizeof(struct objc_module_t));
561 for(m = modules;
562 (char *)m < (char *)modules + modules_size;
563 m = (struct objc_module_t *)((char *)m + module.size) ){
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);
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));
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);
590 else
591 printf(" name 0x%08x\n", (unsigned int)(module.name));
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;
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);
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;
624 memcpy(&def, defs + i, sizeof(uint32_t));
625 if(swapped)
626 def = SWAP_INT(def);
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);
631 print_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);
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");
646 else
647 printf("\n");
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");
658 else
659 printf("\n");
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");
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");
684 else
685 printf("\n");
686 printf("\t instance_size 0x%08x\n",
687 (unsigned int)objc_class.instance_size);
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;
709 memcpy(&ivar, ivar_list + j,
710 sizeof(struct objc_ivar_t));
711 if(swapped)
712 swap_objc_ivar_t(&ivar, host_byte_sex);
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");
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");
738 else
739 printf("\n");
740 printf("\t\t ivar_offset 0x%08x\n",
741 (unsigned int)ivar.ivar_offset);
744 else{
745 printf("\t\t ivars 0x%08x (not in an " SEG_OBJC
746 " section)\n",
747 (unsigned int)objc_class.ivars);
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");
759 printf("\t\t cache 0x%08x\n",
760 (unsigned int)objc_class.cache);
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");
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;
776 else
777 printf(" (not in " SECT_OBJC_SYMBOLS
778 " section)\n");
781 else
782 printf("\tdefs[%u] 0x%08x (not in an " SEG_OBJC
783 " section)\n", i, (unsigned int)def);
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;
795 memcpy(&def, defs + i + symtab.cls_def_cnt, sizeof(uint32_t));
796 if(swapped)
797 def = SWAP_INT(def);
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");
819 else
820 printf("\n");
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");
832 else
833 printf("\n");
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");
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");
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);
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");
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);
888 void
889 print_objc_protocol_section(
890 struct load_command *load_commands,
891 uint32_t ncmds,
892 uint32_t sizeofcmds,
893 enum byte_sex object_byte_sex,
894 char *object_addr,
895 uint32_t object_size,
896 enum bool verbose)
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;
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);
912 if (verbose)
913 get_cstring_section(load_commands, ncmds, sizeofcmds, object_byte_sex,
914 object_addr, object_size, &cstring_section);
916 host_byte_sex = get_host_byte_sex();
917 swapped = host_byte_sex != object_byte_sex;
919 for(p = protocols; (char *)p < (char *)protocols + protocols_size; p++){
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);
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));
933 print_protocol(0, &protocol,
934 objc_sections, nobjc_sections, &cstring_section,
935 host_byte_sex, swapped, verbose);
939 void
940 print_objc_string_object_section(
941 char *sectname,
942 struct load_command *load_commands,
943 uint32_t ncmds,
944 uint32_t sizeofcmds,
945 enum byte_sex object_byte_sex,
946 char *object_addr,
947 uint32_t object_size,
948 enum bool verbose)
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;
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);
966 get_cstring_section(load_commands, ncmds, sizeofcmds, object_byte_sex,
967 object_addr, object_size, &cstring_section);
969 host_byte_sex = get_host_byte_sex();
970 swapped = host_byte_sex != object_byte_sex;
972 for(s = string_objects;
973 (char *)s < (char *)string_objects + string_objects_size;
974 s++){
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);
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));
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");
1002 else
1003 printf("\n");
1004 printf(" _length %u\n", string_object._length);
1009 * PHASH[SIZEHASHTABLE];
1010 * HASH[?]; variable sized (computed from size of section).
1012 void
1013 print_objc_runtime_setup_section(
1014 struct load_command *load_commands,
1015 uint32_t ncmds,
1016 uint32_t sizeofcmds,
1017 enum byte_sex object_byte_sex,
1018 char *object_addr,
1019 uint32_t object_size,
1020 enum bool verbose)
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;
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", &sect, &sect_addr,
1035 &sect_size);
1037 if (verbose)
1038 get_cstring_section(load_commands, ncmds, sizeofcmds, object_byte_sex,
1039 object_addr, object_size, &cstring_section);
1041 host_byte_sex = get_host_byte_sex();
1042 swapped = host_byte_sex != object_byte_sex;
1044 PHASH = (struct _hashEntry_t **)sect;
1045 for(i = 0;
1046 i < SIZEHASHTABLE && (i + 1) * sizeof(uint32_t) < sect_size;
1047 i++){
1049 memcpy(&phash, PHASH + i, sizeof(uint32_t));
1050 if(swapped)
1051 phash = SWAP_INT(phash);
1053 if(phash == 0)
1054 continue;
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");
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);
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");
1080 else
1081 printf("\n");
1083 printf(" next 0x%08x", (unsigned int)_hashEntry.next);
1084 if(_hashEntry.next == 0){
1085 printf("\n");
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");
1098 static
1099 void
1100 get_objc_sections(
1101 struct load_command *load_commands,
1102 uint32_t ncmds,
1103 uint32_t sizeofcmds,
1104 enum byte_sex object_byte_sex,
1105 char *object_addr,
1106 uint32_t object_size,
1107 struct section_info **objc_sections,
1108 uint32_t *nobjc_sections,
1109 char *sectname,
1110 char **sect,
1111 uint32_t *sect_addr,
1112 uint32_t *sect_size)
1114 enum byte_sex host_byte_sex;
1115 enum bool swapped, encrypt_found, encrypt64_found;
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;
1125 host_byte_sex = get_host_byte_sex();
1126 swapped = host_byte_sex != object_byte_sex;
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;
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);
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);
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");
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);
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;
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;
1195 else
1196 (*objc_sections)[*nobjc_sections].size = s.size;
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;
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)++;
1215 if(p + sizeof(struct section) >
1216 (char *)load_commands + sizeofcmds)
1217 break;
1218 p += size;
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;
1242 if(lcmd.cmdsize == 0){
1243 printf("load command %u size zero (can't advance to other "
1244 "load commands)\n", i);
1245 break;
1247 lc = (struct load_command *)((char *)lc + lcmd.cmdsize);
1248 if((char *)lc > (char *)load_commands + sizeofcmds)
1249 break;
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 */ ;
1260 else if((*objc_sections)[i].offset +
1261 (*objc_sections)[i].size < encrypt.cryptoff){
1262 /* section ends before encryption area */ ;
1264 else{
1265 /* section has part in the encrypted area */
1266 (*objc_sections)[i].protected = TRUE;
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 */ ;
1279 else if((*objc_sections)[i].offset +
1280 (*objc_sections)[i].size < encrypt64.cryptoff){
1281 /* section ends before encryption area */ ;
1283 else{
1284 /* section has part in the encrypted area */
1285 (*objc_sections)[i].protected = TRUE;
1292 static
1293 void
1294 get_cstring_section(
1295 struct load_command *load_commands,
1296 uint32_t ncmds,
1297 uint32_t sizeofcmds,
1298 enum byte_sex object_byte_sex,
1299 char *object_addr,
1300 uint32_t object_size,
1301 struct section_info *cstring_section)
1303 enum byte_sex host_byte_sex;
1304 enum bool swapped;
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;
1312 host_byte_sex = get_host_byte_sex();
1313 swapped = host_byte_sex != object_byte_sex;
1315 memset(cstring_section, '\0', sizeof(struct section_info));
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);
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);
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");
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);
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;
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;
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;
1379 if(p + sizeof(struct section) >
1380 (char *)load_commands + sizeofcmds)
1381 break;
1382 p += size;
1384 break;
1386 if(lcmd.cmdsize == 0){
1387 printf("load command %u size zero (can't advance to other "
1388 "load commands)\n", i);
1389 break;
1391 lc = (struct load_command *)((char *)lc + lcmd.cmdsize);
1392 if((char *)lc > (char *)load_commands + sizeofcmds)
1393 break;
1397 static
1398 enum bool
1399 print_method_list(
1400 uint32_t addr,
1401 struct section_info *objc_sections,
1402 uint32_t nobjc_sections,
1403 struct section_info *cstring_section_ptr,
1404 enum byte_sex host_byte_sex,
1405 enum bool swapped,
1406 struct symbol *sorted_symbols,
1407 uint32_t nsorted_symbols,
1408 enum bool verbose)
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;
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);
1421 printf("\n");
1422 if(trunc == TRUE)
1423 printf("\t\t objc_method_list extends past end of the section\n");
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);
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;
1436 memcpy(&method, methods + i, sizeof(struct objc_method_t));
1437 if(swapped)
1438 swap_objc_method_t(&method, host_byte_sex);
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");
1449 else
1450 printf("\n");
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");
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");
1469 return(TRUE);
1472 static
1473 enum bool
1474 print_protocol_list(
1475 uint32_t indent,
1476 uint32_t addr,
1477 struct section_info *objc_sections,
1478 uint32_t nobjc_sections,
1479 struct section_info *cstring_section_ptr,
1480 enum byte_sex host_byte_sex,
1481 enum bool swapped,
1482 enum bool verbose)
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;
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);
1495 printf("\n");
1496 if(trunc == TRUE){
1497 print_indent(indent);
1498 printf(" objc_protocol_list extends past end of the section\n");
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);
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;
1514 memcpy(&l, list + i, sizeof(uint32_t));
1515 if(swapped)
1516 l = SWAP_INT(l);
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;
1525 printf("\n");
1526 if(trunc == TRUE){
1527 print_indent(indent);
1528 printf(" Protocol extends past end of the "
1529 "section\n");
1531 print_protocol(indent, &protocol,
1532 objc_sections, nobjc_sections, cstring_section_ptr,
1533 host_byte_sex, swapped, verbose);
1535 return(TRUE);
1538 static
1539 void
1540 print_protocol(
1541 uint32_t indent,
1542 struct objc_protocol_t *protocol,
1543 struct section_info *objc_sections,
1544 uint32_t nobjc_sections,
1545 struct section_info *cstring_section_ptr,
1546 enum byte_sex host_byte_sex,
1547 enum bool swapped,
1548 enum bool verbose)
1550 uint32_t left;
1551 char *p;
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");
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");
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");
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");
1594 static
1595 enum bool
1596 print_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)
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;
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);
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");
1624 print_indent(indent);
1625 printf(" count %d\n", mdl.count);
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;
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);
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");
1650 else
1651 printf("\n");
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");
1663 else
1664 printf("\n");
1666 return(TRUE);
1669 static enum bool
1670 print_PHASH(
1671 uint32_t indent,
1672 uint32_t addr,
1673 struct section_info *objc_sections,
1674 uint32_t nobjc_sections,
1675 struct section_info *cstring_section_ptr,
1676 enum byte_sex host_byte_sex,
1677 enum bool swapped,
1678 enum bool verbose)
1680 struct _hashEntry_t _hashEntry;
1681 enum bool trunc;
1682 uint32_t left;
1683 char *p;
1685 if(get_hashEntry(addr, &_hashEntry, &trunc, objc_sections,
1686 nobjc_sections, host_byte_sex, swapped) == FALSE)
1687 return(FALSE);
1689 printf("\n");
1690 if(trunc == TRUE){
1691 print_indent(indent);
1692 printf("_hashEntry extends past end of the section\n");
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");
1705 else
1706 printf("\n");
1708 print_indent(indent);
1709 printf("next 0x%08x", (unsigned int)_hashEntry.next);
1710 if(_hashEntry.next == 0){
1711 printf("\n");
1712 return(TRUE);
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);
1721 static
1722 void
1723 print_indent(
1724 uint32_t indent)
1726 uint32_t i;
1728 for(i = 0; i < indent; ){
1729 if(indent - i >= 8){
1730 printf("\t");
1731 i += 8;
1733 else{
1734 printf("%.*s", (int)(indent - i), " ");
1735 return;
1740 static
1741 void *
1742 get_pointer(
1743 uint32_t addr,
1744 uint32_t *left,
1745 struct section_info *objc_sections,
1746 uint32_t nobjc_sections,
1747 struct section_info *cstring_section_ptr)
1749 void* returnValue = NULL;
1750 uint32_t i;
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));
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));
1771 return(returnValue);
1774 static
1775 enum bool
1776 get_symtab(
1777 uint32_t addr,
1778 struct objc_symtab_t *symtab,
1779 uint32_t **defs,
1780 uint32_t *left,
1781 enum bool *trunc,
1782 struct section_info *objc_sections,
1783 uint32_t nobjc_sections,
1784 enum byte_sex host_byte_sex,
1785 enum bool swapped)
1787 uint32_t i;
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){
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;
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;
1819 if(swapped)
1820 swap_objc_symtab_t(symtab, host_byte_sex);
1821 return(TRUE);
1824 return(FALSE);
1827 static
1828 enum bool
1829 get_objc_class(
1830 uint32_t addr,
1831 struct objc_class_t *objc_class,
1832 enum bool *trunc,
1833 struct section_info *objc_sections,
1834 uint32_t nobjc_sections,
1835 enum byte_sex host_byte_sex,
1836 enum bool swapped)
1838 uint32_t left, i;
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){
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;
1856 else{
1857 memcpy(objc_class,
1858 objc_sections[i].contents +
1859 (addr - objc_sections[i].addr),
1860 left);
1861 *trunc = TRUE;
1863 if(swapped)
1864 swap_objc_class_t(objc_class, host_byte_sex);
1865 return(TRUE);
1868 return(FALSE);
1871 static
1872 enum bool
1873 get_objc_category(
1874 uint32_t addr,
1875 struct objc_category_t *objc_category,
1876 enum bool *trunc,
1877 struct section_info *objc_sections,
1878 uint32_t nobjc_sections,
1879 enum byte_sex host_byte_sex,
1880 enum bool swapped)
1882 uint32_t left, i;
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){
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;
1900 else{
1901 memcpy(objc_category,
1902 objc_sections[i].contents +
1903 (addr - objc_sections[i].addr),
1904 left);
1905 *trunc = TRUE;
1907 if(swapped)
1908 swap_objc_category_t(objc_category, host_byte_sex);
1909 return(TRUE);
1912 return(FALSE);
1915 static
1916 enum bool
1917 get_ivar_list(
1918 uint32_t addr,
1919 struct objc_ivar_list_t *objc_ivar_list,
1920 struct objc_ivar_t **ivar_list,
1921 uint32_t *left,
1922 enum bool *trunc,
1923 struct section_info *objc_sections,
1924 uint32_t nobjc_sections,
1925 enum byte_sex host_byte_sex,
1926 enum bool swapped)
1928 uint32_t i;
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){
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;
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;
1964 if(swapped)
1965 swap_objc_ivar_list_t(objc_ivar_list, host_byte_sex);
1966 return(TRUE);
1969 return(FALSE);
1972 static
1973 enum bool
1974 get_method_list(
1975 uint32_t addr,
1976 struct objc_method_list_t *method_list,
1977 struct objc_method_t **methods,
1978 uint32_t *left,
1979 enum bool *trunc,
1980 struct section_info *objc_sections,
1981 uint32_t nobjc_sections,
1982 enum byte_sex host_byte_sex,
1983 enum bool swapped)
1985 uint32_t i;
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){
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;
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;
2021 if(swapped)
2022 swap_objc_method_list_t(method_list, host_byte_sex);
2023 return(TRUE);
2026 return(FALSE);
2029 static
2030 enum bool
2031 get_protocol_list(
2032 uint32_t addr,
2033 struct objc_protocol_list_t *protocol_list,
2034 uint32_t **list,
2035 uint32_t *left,
2036 enum bool *trunc,
2037 struct section_info *objc_sections,
2038 uint32_t nobjc_sections,
2039 enum byte_sex host_byte_sex,
2040 enum bool swapped)
2042 uint32_t i;
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){
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;
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;
2078 if(swapped)
2079 swap_objc_protocol_list_t(protocol_list, host_byte_sex);
2080 return(TRUE);
2083 return(FALSE);
2086 static
2087 enum bool
2088 get_protocol(
2089 uint32_t addr,
2090 struct objc_protocol_t *protocol,
2091 enum bool *trunc,
2092 struct section_info *objc_sections,
2093 uint32_t nobjc_sections,
2094 enum byte_sex host_byte_sex,
2095 enum bool swapped)
2097 uint32_t left, i;
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){
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;
2115 else{
2116 memcpy(protocol,
2117 objc_sections[i].contents +
2118 (addr - objc_sections[i].addr),
2119 left);
2120 *trunc = TRUE;
2122 if(swapped)
2123 swap_objc_protocol_t(protocol, host_byte_sex);
2124 return(TRUE);
2127 return(FALSE);
2130 static
2131 enum bool
2132 get_method_description_list(
2133 uint32_t addr,
2134 struct objc_method_description_list_t *mdl,
2135 struct objc_method_description_t **list,
2136 uint32_t *left,
2137 enum bool *trunc,
2138 struct section_info *objc_sections,
2139 uint32_t nobjc_sections,
2140 enum byte_sex host_byte_sex,
2141 enum bool swapped)
2143 uint32_t i;
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){
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;
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;
2179 if(swapped)
2180 swap_objc_method_description_list_t(mdl, host_byte_sex);
2181 return(TRUE);
2184 return(FALSE);
2187 static
2188 enum bool
2189 get_hashEntry(
2190 uint32_t addr,
2191 struct _hashEntry_t *_hashEntry,
2192 enum bool *trunc,
2193 struct section_info *objc_sections,
2194 uint32_t nobjc_sections,
2195 enum byte_sex host_byte_sex,
2196 enum bool swapped)
2198 uint32_t left, i;
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){
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;
2216 else{
2217 memcpy(_hashEntry,
2218 objc_sections[i].contents +
2219 (addr - objc_sections[i].addr),
2220 left);
2221 *trunc = TRUE;
2223 if(swapped)
2224 swap_hashEntry_t(_hashEntry, host_byte_sex);
2225 return(TRUE);
2228 return(FALSE);