2 * Copyright © 2009 Apple Inc. All rights reserved.
4 * @APPLE_LICENSE_HEADER_START@
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions are met:
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@
35 #include "mach-o/loader.h"
36 #include "stuff/allocate.h"
37 #include "stuff/bytesex.h"
38 #include "stuff/symbol.h"
39 #include "stuff/reloc.h"
40 #include "dyld_bind_info.h"
41 #include "ofile_print.h"
46 * Here we need structures that have the same memory layout and size as the
47 * 64-bit Objective-C meta data structures that can be used in this 32-bit
50 * The real structure definitions come from the objc4 project in the private
51 * header file runtime/objc-runtime-new.h in that project.
55 uint64_t isa
; /* class_t * (64-bit pointer) */
56 uint64_t superclass
; /* class_t * (64-bit pointer) */
57 uint64_t cache
; /* Cache (64-bit pointer) */
58 uint64_t vtable
; /* IMP * (64-bit pointer) */
59 uint64_t data
; /* class_ro_t * (64-bit pointer) */
66 enum byte_sex target_byte_sex
)
68 c
->isa
= SWAP_LONG_LONG(c
->isa
);
69 c
->superclass
= SWAP_LONG_LONG(c
->superclass
);
70 c
->cache
= SWAP_LONG_LONG(c
->cache
);
71 c
->vtable
= SWAP_LONG_LONG(c
->vtable
);
72 c
->data
= SWAP_LONG_LONG(c
->data
);
77 uint32_t instanceStart
;
78 uint32_t instanceSize
;
80 uint64_t ivarLayout
; /* const uint8_t * (64-bit pointer) */
81 uint64_t name
; /* const char * (64-bit pointer) */
82 uint64_t baseMethods
; /* const method_list_t * (64-bit pointer) */
83 uint64_t baseProtocols
; /* const protocol_list_t * (64-bit pointer) */
84 uint64_t ivars
; /* const ivar_list_t * (64-bit pointer) */
85 uint64_t weakIvarLayout
; /* const uint8_t * (64-bit pointer) */
86 uint64_t baseProperties
; /* const struct objc_property_list *
90 /* Values for class_ro_t->flags */
91 #define RO_META (1<<0)
92 #define RO_ROOT (1<<1)
93 #define RO_HAS_CXX_STRUCTORS (1<<2)
99 struct class_ro_t
*cro
,
100 enum byte_sex target_byte_sex
)
102 cro
->flags
= SWAP_INT(cro
->flags
);
103 cro
->instanceStart
= SWAP_INT(cro
->instanceStart
);
104 cro
->instanceSize
= SWAP_INT(cro
->instanceSize
);
105 cro
->reserved
= SWAP_INT(cro
->reserved
);
106 cro
->ivarLayout
= SWAP_LONG_LONG(cro
->ivarLayout
);
107 cro
->name
= SWAP_LONG_LONG(cro
->name
);
108 cro
->baseMethods
= SWAP_LONG_LONG(cro
->baseMethods
);
109 cro
->baseProtocols
= SWAP_LONG_LONG(cro
->baseProtocols
);
110 cro
->ivars
= SWAP_LONG_LONG(cro
->ivars
);
111 cro
->weakIvarLayout
= SWAP_LONG_LONG(cro
->weakIvarLayout
);
112 cro
->baseProperties
= SWAP_LONG_LONG(cro
->baseProperties
);
115 struct method_list_t
{
118 /* struct method_t first; These structures follow inline */
124 struct method_list_t
*ml
,
125 enum byte_sex target_byte_sex
)
127 ml
->entsize
= SWAP_INT(ml
->entsize
);
128 ml
->count
= SWAP_INT(ml
->count
);
132 uint64_t name
; /* SEL (64-bit pointer) */
133 uint64_t types
; /* const char * (64-bit pointer) */
134 uint64_t imp
; /* IMP (64-bit pointer) */
141 enum byte_sex target_byte_sex
)
143 m
->name
= SWAP_LONG_LONG(m
->name
);
144 m
->types
= SWAP_LONG_LONG(m
->types
);
145 m
->imp
= SWAP_LONG_LONG(m
->imp
);
151 /* struct ivar_t first; These structures follow inline */
157 struct ivar_list_t
*il
,
158 enum byte_sex target_byte_sex
)
160 il
->entsize
= SWAP_INT(il
->entsize
);
161 il
->count
= SWAP_INT(il
->count
);
165 uint64_t offset
; /* uintptr_t * (64-bit pointer) */
166 uint64_t name
; /* const char * (64-bit pointer) */
167 uint64_t type
; /* const char * (64-bit pointer) */
176 enum byte_sex target_byte_sex
)
178 i
->offset
= SWAP_LONG_LONG(i
->offset
);
179 i
->name
= SWAP_LONG_LONG(i
->name
);
180 i
->type
= SWAP_LONG_LONG(i
->type
);
181 i
->alignment
= SWAP_INT(i
->alignment
);
182 i
->size
= SWAP_INT(i
->size
);
185 struct protocol_list_t
{
186 uint64_t count
; /* uintptr_t (a 64-bit value) */
187 /* struct protocol_t * list[0]; These pointers follow inline */
192 swap_protocol_list_t(
193 struct protocol_list_t
*pl
,
194 enum byte_sex target_byte_sex
)
196 pl
->count
= SWAP_LONG_LONG(pl
->count
);
200 uint64_t isa
; /* id * (64-bit pointer) */
201 uint64_t name
; /* const char * (64-bit pointer) */
202 uint64_t protocols
; /* struct protocol_list_t *
204 uint64_t instanceMethods
; /* method_list_t * (64-bit pointer) */
205 uint64_t classMethods
; /* method_list_t * (64-bit pointer) */
206 uint64_t optionalInstanceMethods
; /* method_list_t * (64-bit pointer) */
207 uint64_t optionalClassMethods
; /* method_list_t * (64-bit pointer) */
208 uint64_t instanceProperties
; /* struct objc_property_list *
215 struct protocol_t
*p
,
216 enum byte_sex target_byte_sex
)
218 p
->isa
= SWAP_LONG_LONG(p
->isa
);
219 p
->name
= SWAP_LONG_LONG(p
->name
);
220 p
->protocols
= SWAP_LONG_LONG(p
->protocols
);
221 p
->instanceMethods
= SWAP_LONG_LONG(p
->instanceMethods
);
222 p
->classMethods
= SWAP_LONG_LONG(p
->classMethods
);
223 p
->optionalInstanceMethods
= SWAP_LONG_LONG(p
->optionalInstanceMethods
);
224 p
->optionalClassMethods
= SWAP_LONG_LONG(p
->optionalClassMethods
);
225 p
->instanceProperties
= SWAP_LONG_LONG(p
->instanceProperties
);
228 struct objc_property_list
{
231 /* struct objc_property first; These structures follow inline */
236 swap_objc_property_list(
237 struct objc_property_list
*pl
,
238 enum byte_sex target_byte_sex
)
240 pl
->entsize
= SWAP_INT(pl
->entsize
);
241 pl
->count
= SWAP_INT(pl
->count
);
244 struct objc_property
{
245 uint64_t name
; /* const char * (64-bit pointer) */
246 uint64_t attributes
; /* const char * (64-bit pointer) */
252 struct objc_property
*op
,
253 enum byte_sex target_byte_sex
)
255 op
->name
= SWAP_LONG_LONG(op
->name
);
256 op
->attributes
= SWAP_LONG_LONG(op
->attributes
);
260 uint64_t name
; /* const char * (64-bit pointer) */
261 uint64_t cls
; /* struct class_t * (64-bit pointer) */
262 uint64_t instanceMethods
; /* struct method_list_t * (64-bit pointer) */
263 uint64_t classMethods
; /* struct method_list_t * (64-bit pointer) */
264 uint64_t protocols
; /* struct protocol_list_t * (64-bit pointer) */
265 uint64_t instanceProperties
; /* struct objc_property_list *
272 struct category_t
*c
,
273 enum byte_sex target_byte_sex
)
275 c
->name
= SWAP_LONG_LONG(c
->name
);
276 c
->cls
= SWAP_LONG_LONG(c
->cls
);
277 c
->instanceMethods
= SWAP_LONG_LONG(c
->instanceMethods
);
278 c
->classMethods
= SWAP_LONG_LONG(c
->classMethods
);
279 c
->protocols
= SWAP_LONG_LONG(c
->protocols
);
280 c
->instanceProperties
= SWAP_LONG_LONG(c
->instanceProperties
);
284 uint64_t imp
; /* IMP (64-bit pointer) */
285 uint64_t sel
; /* SEL (64-bit pointer) */
291 struct message_ref
*mr
,
292 enum byte_sex target_byte_sex
)
294 mr
->imp
= SWAP_LONG_LONG(mr
->imp
);
295 mr
->sel
= SWAP_LONG_LONG(mr
->sel
);
298 struct objc_image_info
{
302 /* masks for objc_image_info.flags */
303 #define OBJC_IMAGE_IS_REPLACEMENT (1<<0)
304 #define OBJC_IMAGE_SUPPORTS_GC (1<<1)
309 swap_objc_image_info(
310 struct objc_image_info
*o
,
311 enum byte_sex target_byte_sex
)
313 o
->version
= SWAP_INT(o
->version
);
314 o
->flags
= SWAP_INT(o
->flags
);
317 struct objc_string_object_64
{
318 uint64_t isa
; /* class_t * (64-bit pointer) */
319 uint64_t characters
; /* char * (64-bit pointer) */
320 uint32_t _length
; /* number of non-NULL characters in above */
321 uint32_t _pad
; /* unused padding, compiler uses .space 4 */
326 swap_string_object_64(
327 struct objc_string_object_64
*string_object
,
328 enum byte_sex target_byte_sex
)
330 string_object
->isa
= SWAP_LONG_LONG(string_object
->isa
);
331 string_object
->characters
= SWAP_LONG_LONG(string_object
->characters
);
332 string_object
->_length
= SWAP_INT(string_object
->_length
);
333 string_object
->_pad
= SWAP_INT(string_object
->_pad
);
337 uint64_t isa
; /* class_t * (64-bit pointer) */
338 uint64_t flags
; /* flag bits */
339 uint64_t characters
; /* char * (64-bit pointer) */
340 uint64_t length
; /* number of non-NULL characters in above */
346 struct cfstring_t
*cfstring
,
347 enum byte_sex target_byte_sex
)
349 cfstring
->isa
= SWAP_LONG_LONG(cfstring
->isa
);
350 cfstring
->flags
= SWAP_LONG_LONG(cfstring
->flags
);
351 cfstring
->characters
= SWAP_LONG_LONG(cfstring
->characters
);
352 cfstring
->length
= SWAP_LONG_LONG(cfstring
->length
);
357 enum byte_sex host_byte_sex
;
358 struct section_info_64
*sections
;
361 struct nlist_64
*symbols64
;
364 uint32_t strings_size
;
365 struct symbol
*sorted_symbols
;
366 uint32_t nsorted_symbols
;
368 struct relocation_info
*ext_relocs
;
369 uint32_t next_relocs
;
370 struct relocation_info
*loc_relocs
;
371 uint32_t nloc_relocs
;
372 struct dyld_bind_info
*dbi
;
378 struct section_info_64
{
385 struct relocation_info
*relocs
;
392 static void walk_pointer_list(
394 struct section_info_64
*s
,
396 void (*func
)(uint64_t, struct info
*));
398 static void print_class_t(
402 static void print_class_ro_t(
405 enum bool *is_meta_class
);
407 static void print_layout_map(
411 static void print_method_list_t(
416 static void print_ivar_list_t(
420 static void print_protocol_list_t(
424 static void print_objc_property_list(
428 static void print_category_t(
432 static void print_message_refs(
433 struct section_info_64
*s
,
436 static void print_image_info(
437 struct section_info_64
*s
,
440 static void get_sections_64(
441 struct load_command
*load_commands
,
444 enum byte_sex object_byte_sex
,
446 uint32_t object_size
,
447 struct section_info_64
**sections
,
451 static struct section_info_64
*get_section_64(
452 struct section_info_64
*sections
,
457 static void get_cstring_section_64(
458 struct load_command
*load_commands
,
461 enum byte_sex object_byte_sex
,
463 uint32_t object_size
,
464 struct section_info_64
*cstring_section_ptr
);
466 static void *get_pointer_64(
470 struct section_info_64
**s
,
471 struct section_info_64
*sections
,
474 static const char *get_symbol_64(
475 uint32_t sect_offset
,
476 uint64_t database_offset
,
478 struct relocation_info
*relocs
,
484 * Print the objc2 meta data in 64-bit Mach-O files.
489 struct load_command
*load_commands
,
492 enum byte_sex object_byte_sex
,
494 uint32_t object_size
,
495 struct nlist_64
*symbols64
,
498 uint32_t strings_size
,
499 struct symbol
*sorted_symbols
,
500 uint32_t nsorted_symbols
,
501 struct relocation_info
*ext_relocs
,
502 uint32_t next_relocs
,
503 struct relocation_info
*loc_relocs
,
504 uint32_t nloc_relocs
,
505 struct dyld_bind_info
*dbi
,
510 struct section_info_64
*s
;
513 info
.host_byte_sex
= get_host_byte_sex();
514 info
.swapped
= info
.host_byte_sex
!= object_byte_sex
;
515 info
.cputype
= cputype
;
516 info
.symbols64
= symbols64
;
517 info
.nsymbols
= nsymbols
;
518 info
.strings
= strings
;
519 info
.strings_size
= strings_size
;
520 info
.sorted_symbols
= sorted_symbols
;
521 info
.nsorted_symbols
= nsorted_symbols
;
522 info
.ext_relocs
= ext_relocs
;
523 info
.next_relocs
= next_relocs
;
524 info
.loc_relocs
= loc_relocs
;
525 info
.nloc_relocs
= nloc_relocs
;
528 info
.verbose
= verbose
;
530 get_sections_64(load_commands
, ncmds
, sizeofcmds
, object_byte_sex
,
531 object_addr
, object_size
, &info
.sections
,
532 &info
.nsections
, &info
.database
);
534 s
= get_section_64(info
.sections
, info
.nsections
,
535 "__OBJC2", "__class_list");
537 s
= get_section_64(info
.sections
, info
.nsections
,
538 "__DATA", "__objc_classlist");
539 walk_pointer_list("class", s
, &info
, print_class_t
);
541 s
= get_section_64(info
.sections
, info
.nsections
,
542 "__OBJC2", "__class_refs");
544 s
= get_section_64(info
.sections
, info
.nsections
,
545 "__DATA", "__objc_classrefs");
546 walk_pointer_list("class refs", s
, &info
, NULL
);
548 s
= get_section_64(info
.sections
, info
.nsections
,
549 "__OBJC2", "__super_refs");
551 s
= get_section_64(info
.sections
, info
.nsections
,
552 "__DATA", "__objc_superrefs");
553 walk_pointer_list("super refs", s
, &info
, NULL
);
555 s
= get_section_64(info
.sections
, info
.nsections
,
556 "__OBJC2", "__category_list");
558 s
= get_section_64(info
.sections
, info
.nsections
,
559 "__DATA", "__objc_catlist");
560 walk_pointer_list("category", s
, &info
, print_category_t
);
562 s
= get_section_64(info
.sections
, info
.nsections
,
563 "__OBJC2", "__protocol_list");
565 s
= get_section_64(info
.sections
, info
.nsections
,
566 "__DATA", "__objc_protolist");
567 walk_pointer_list("protocol", s
, &info
, NULL
);
569 s
= get_section_64(info
.sections
, info
.nsections
,
570 "__OBJC2", "__message_refs");
572 s
= get_section_64(info
.sections
, info
.nsections
,
573 "__DATA", "__objc_msgrefs");
574 print_message_refs(s
, &info
);
576 s
= get_section_64(info
.sections
, info
.nsections
,
577 "__OBJC", "__image_info");
579 s
= get_section_64(info
.sections
, info
.nsections
,
580 "__DATA", "__objc_imageinfo");
581 print_image_info(s
, &info
);
588 struct section_info_64
*s
,
590 void (*func
)(uint64_t, struct info
*))
592 uint32_t i
, size
, left
;
599 printf("Contents of (%.16s,%.16s) section\n", s
->segname
, s
->sectname
);
600 for(i
= 0; i
< s
->size
; i
+= sizeof(uint64_t)){
602 memset(&p
, '\0', sizeof(uint64_t));
604 size
= left
< sizeof(uint64_t) ?
605 left
: sizeof(uint64_t);
606 memcpy(&p
, s
->contents
+ i
, size
);
608 if(i
+ sizeof(uint64_t) > s
->size
)
609 printf("%s list pointer extends past end of (%s,%s) "
610 "section\n", listname
, s
->segname
, s
->sectname
);
611 printf("%016llx ", s
->addr
+ i
);
614 p
= SWAP_LONG_LONG(p
);
616 name
= get_symbol_64(i
, s
->addr
- info
->database
, p
,
617 s
->relocs
, s
->nrelocs
, info
, &n_value
);
619 name
= get_dyld_bind_info_symbolname(s
->addr
+ i
, info
->dbi
,
622 printf("0x%llx", n_value
);
624 printf(" + 0x%llx", p
);
639 * get_objc2_64bit_cfstring_name() is used for disassembly and is passed a
640 * pointer to a cfstring and returns its name.
643 get_objc2_64bit_cfstring_name(
645 struct load_command
*load_commands
,
648 enum byte_sex object_byte_sex
,
650 uint32_t object_size
)
652 struct section_info_64
*sections
;
653 uint32_t nsections
, left
;
655 struct cfstring_t cfs
;
659 get_sections_64(load_commands
, ncmds
, sizeofcmds
, object_byte_sex
,
660 object_addr
, object_size
, §ions
, &nsections
,
663 r
= get_pointer_64(p
, NULL
, &left
, NULL
, sections
, nsections
);
664 if(r
== NULL
|| left
< sizeof(struct cfstring_t
))
666 memcpy(&cfs
, r
, sizeof(struct cfstring_t
));
667 if(get_host_byte_sex() != object_byte_sex
)
668 swap_cfstring_t(&cfs
, get_host_byte_sex());
669 if(cfs
.characters
== 0)
672 name
= get_pointer_64(cfs
.characters
, NULL
, &left
, NULL
,
673 sections
, nsections
);
682 * get_objc2_64bit_class_name() is used for disassembly and is passed a pointer
683 * to an Objective-C class and returns the class name.
686 get_objc2_64bit_class_name(
688 struct load_command
*load_commands
,
691 enum byte_sex object_byte_sex
,
693 uint32_t object_size
)
695 struct section_info_64
*sections
;
696 uint32_t nsections
, left
;
699 struct class_ro_t cro
;
703 get_sections_64(load_commands
, ncmds
, sizeofcmds
, object_byte_sex
,
704 object_addr
, object_size
, §ions
, &nsections
,
707 r
= get_pointer_64(p
, NULL
, &left
, NULL
, sections
, nsections
);
708 if(r
== NULL
|| left
< sizeof(struct class_t
))
710 memcpy(&c
, r
, sizeof(struct class_t
));
711 if(get_host_byte_sex() != object_byte_sex
)
712 swap_class_t(&c
, get_host_byte_sex());
716 r
= get_pointer_64(c
.data
, NULL
, &left
, NULL
, sections
, nsections
);
717 if(r
== NULL
|| left
< sizeof(struct class_ro_t
))
719 memcpy(&cro
, r
, sizeof(struct class_ro_t
));
720 if(get_host_byte_sex() != object_byte_sex
)
721 swap_class_ro_t(&cro
, get_host_byte_sex());
726 name
= get_pointer_64(cro
.name
, NULL
, &left
, NULL
, sections
, nsections
);
742 uint32_t offset
, left
;
743 struct section_info_64
*s
;
745 enum bool is_meta_class
;
746 uint64_t n_value
, isa_n_value
;
748 is_meta_class
= FALSE
;
749 r
= get_pointer_64(p
, &offset
, &left
, &s
,
750 info
->sections
, info
->nsections
);
753 memset(&c
, '\0', sizeof(struct class_t
));
754 if(left
< sizeof(struct class_t
)){
756 printf(" (class_t entends past the end of the section)\n");
759 memcpy(&c
, r
, sizeof(struct class_t
));
761 swap_class_t(&c
, info
->host_byte_sex
);
762 printf(" isa 0x%llx", c
.isa
);
763 name
= get_symbol_64(offset
+ offsetof(struct class_t
, isa
),
764 s
->addr
- info
->database
, c
.isa
, s
->relocs
,
765 s
->nrelocs
, info
, &isa_n_value
);
767 printf(" %s\n", name
);
770 printf(" superclass 0x%llx", c
.superclass
);
771 name
= get_symbol_64(offset
+ offsetof(struct class_t
, superclass
),
772 s
->addr
- info
->database
, c
.superclass
, s
->relocs
,
773 s
->nrelocs
, info
, NULL
);
775 printf(" %s\n", name
);
778 printf(" cache 0x%llx", c
.cache
);
779 name
= get_symbol_64(offset
+ offsetof(struct class_t
, cache
),
780 s
->addr
- info
->database
, c
.cache
, s
->relocs
,
781 s
->nrelocs
, info
, NULL
);
783 printf(" %s\n", name
);
786 printf(" vtable 0x%llx", c
.vtable
);
787 name
= get_symbol_64(offset
+ offsetof(struct class_t
, vtable
),
788 s
->addr
- info
->database
, c
.vtable
, s
->relocs
,
789 s
->nrelocs
, info
, NULL
);
791 printf(" %s\n", name
);
795 name
= get_symbol_64(offset
+ offsetof(struct class_t
, data
),
796 s
->addr
- info
->database
, c
.data
, s
->relocs
,
797 s
->nrelocs
, info
, &n_value
);
800 if(info
->Vflag
&& name
!= NULL
)
803 printf("0x%llx", n_value
);
805 printf(" + 0x%llx", c
.data
);
808 printf("0x%llx", c
.data
);
810 printf(" (struct class_ro_t *)");
812 * This is a Swift class if some of the low bits of the pointer
815 if((c
.data
+ n_value
) & 0x7)
816 printf(" Swift class");
818 print_class_ro_t((c
.data
+ n_value
) & ~0x7, info
, &is_meta_class
);
820 if(is_meta_class
== FALSE
){
821 printf("Meta Class\n");
822 print_class_t(c
.isa
+ isa_n_value
, info
);
831 enum bool *is_meta_class
)
833 struct class_ro_t cro
;
835 uint32_t offset
, left
;
836 struct section_info_64
*s
;
837 const char *name
, *sym_name
;
840 r
= get_pointer_64(p
, &offset
, &left
, &s
, info
->sections
,
844 memset(&cro
, '\0', sizeof(struct class_ro_t
));
845 if(left
< sizeof(struct class_ro_t
)){
846 memcpy(&cro
, r
, left
);
847 printf(" (class_ro_t entends past the end of the section)\n");
850 memcpy(&cro
, r
, sizeof(struct class_ro_t
));
852 swap_class_ro_t(&cro
, info
->host_byte_sex
);
853 printf(" flags 0x%x", cro
.flags
);
854 if(cro
.flags
& RO_META
)
856 if(cro
.flags
& RO_ROOT
)
858 if(cro
.flags
& RO_HAS_CXX_STRUCTORS
)
859 printf(" RO_HAS_CXX_STRUCTORS");
861 printf(" instanceStart %u\n", cro
.instanceStart
);
862 printf(" instanceSize %u\n", cro
.instanceSize
);
863 printf(" reserved 0x%x\n", cro
.reserved
);
864 printf(" ivarLayout 0x%llx\n", cro
.ivarLayout
);
865 print_layout_map(cro
.ivarLayout
, info
);
868 sym_name
= get_symbol_64(offset
+ offsetof(struct class_ro_t
, name
),
869 s
->addr
- info
->database
, cro
.name
, s
->relocs
,
870 s
->nrelocs
, info
, &n_value
);
872 if(info
->Vflag
&& sym_name
!= NULL
)
873 printf("%s", sym_name
);
875 printf("0x%llx", n_value
);
877 printf(" + 0x%llx", cro
.name
);
880 printf("0x%llx", cro
.name
);
881 name
= get_pointer_64(cro
.name
+ n_value
, NULL
, &left
, NULL
,
882 info
->sections
, info
->nsections
);
884 printf(" %.*s", (int)left
, name
);
887 printf(" baseMethods ");
888 sym_name
= get_symbol_64(offset
+
889 offsetof(struct class_ro_t
, baseMethods
),
890 s
->addr
- info
->database
, cro
.baseMethods
,
891 s
->relocs
, s
->nrelocs
, info
, &n_value
);
893 if(info
->Vflag
&& sym_name
!= NULL
)
894 printf("%s", sym_name
);
896 printf("0x%llx", n_value
);
897 if(cro
.baseMethods
!= 0)
898 printf(" + 0x%llx", cro
.baseMethods
);
901 printf("0x%llx", cro
.baseMethods
);
902 printf(" (struct method_list_t *)\n");
903 if(cro
.baseMethods
+ n_value
!= 0)
904 print_method_list_t(cro
.baseMethods
+ n_value
, info
, "");
906 printf(" baseProtocols ");
907 sym_name
= get_symbol_64(offset
+
908 offsetof(struct class_ro_t
, baseProtocols
),
909 s
->addr
- info
->database
, cro
.baseProtocols
,
910 s
->relocs
, s
->nrelocs
, info
, &n_value
);
912 if(info
->Vflag
&& sym_name
!= NULL
)
913 printf("%s", sym_name
);
915 printf("0x%llx", n_value
);
916 if(cro
.baseProtocols
!= 0)
917 printf(" + 0x%llx", cro
.baseProtocols
);
920 printf("0x%llx", cro
.baseProtocols
);
922 if(cro
.baseProtocols
+ n_value
!= 0)
923 print_protocol_list_t(cro
.baseProtocols
+ n_value
, info
);
926 sym_name
= get_symbol_64(offset
+
927 offsetof(struct class_ro_t
, ivars
),
928 s
->addr
- info
->database
, cro
.ivars
,
929 s
->relocs
, s
->nrelocs
, info
, &n_value
);
931 if(info
->Vflag
&& sym_name
!= NULL
)
932 printf("%s", sym_name
);
934 printf("0x%llx", n_value
);
936 printf(" + 0x%llx", cro
.ivars
);
939 printf("0x%llx", cro
.ivars
);
941 if(cro
.ivars
+ n_value
!= 0)
942 print_ivar_list_t(cro
.ivars
+ n_value
, info
);
944 printf(" weakIvarLayout ");
945 sym_name
= get_symbol_64(offset
+
946 offsetof(struct class_ro_t
, weakIvarLayout
),
947 s
->addr
- info
->database
, cro
.weakIvarLayout
,
948 s
->relocs
, s
->nrelocs
, info
, &n_value
);
950 if(info
->Vflag
&& sym_name
!= NULL
)
951 printf("%s", sym_name
);
953 printf("0x%llx", n_value
);
954 if(cro
.weakIvarLayout
!= 0)
955 printf(" + 0x%llx", cro
.weakIvarLayout
);
958 printf("0x%llx", cro
.weakIvarLayout
);
960 print_layout_map(cro
.weakIvarLayout
+ n_value
, info
);
962 printf(" baseProperties ");
963 sym_name
= get_symbol_64(offset
+
964 offsetof(struct class_ro_t
, baseProperties
),
965 s
->addr
- info
->database
, cro
.baseProperties
,
966 s
->relocs
, s
->nrelocs
, info
, &n_value
);
968 if(info
->Vflag
&& sym_name
!= NULL
)
969 printf("%s", sym_name
);
971 printf("0x%llx", n_value
);
972 if(cro
.baseProperties
!= 0)
973 printf(" + 0x%llx", cro
.baseProperties
);
976 printf("0x%llx", cro
.baseProperties
);
978 if(cro
.baseProperties
+ n_value
!= 0)
979 print_objc_property_list(cro
.baseProperties
+ n_value
, info
);
982 *is_meta_class
= (cro
.flags
& RO_META
) ? TRUE
: FALSE
;
991 uint32_t offset
, left
;
992 struct section_info_64
*s
;
997 layout_map
= get_pointer_64(p
, &offset
, &left
, &s
,
998 info
->sections
, info
->nsections
);
999 if(layout_map
!= NULL
){
1000 printf(" layout map: ");
1002 printf("0x%02x ", (*layout_map
) & 0xff);
1005 }while(*layout_map
!= '\0' && left
!= 0);
1012 print_method_list_t(
1017 struct method_list_t ml
;
1020 uint32_t offset
, left
, i
;
1021 struct section_info_64
*s
;
1022 const char *name
, *sym_name
;
1025 r
= get_pointer_64(p
, &offset
, &left
, &s
, info
->sections
,
1029 memset(&ml
, '\0', sizeof(struct method_list_t
));
1030 if(left
< sizeof(struct method_list_t
)){
1031 memcpy(&ml
, r
, left
);
1032 printf("%s (method_list_t entends past the end of the "
1033 "section)\n", indent
);
1036 memcpy(&ml
, r
, sizeof(struct method_list_t
));
1038 swap_method_list_t(&ml
, info
->host_byte_sex
);
1039 printf("%s\t\t entsize %u\n", indent
, ml
.entsize
);
1040 printf("%s\t\t count %u\n", indent
, ml
.count
);
1042 p
+= sizeof(struct method_list_t
);
1043 offset
+= sizeof(struct method_list_t
);
1044 for(i
= 0; i
< ml
.count
; i
++){
1045 r
= get_pointer_64(p
, &offset
, &left
, &s
, info
->sections
,
1049 memset(&m
, '\0', sizeof(struct method_t
));
1050 if(left
< sizeof(struct method_t
)){
1051 memcpy(&ml
, r
, left
);
1052 printf("%s (method_t entends past the end of the "
1053 "section)\n", indent
);
1056 memcpy(&m
, r
, sizeof(struct method_t
));
1058 swap_method_t(&m
, info
->host_byte_sex
);
1060 printf("%s\t\t name ", indent
);
1061 sym_name
= get_symbol_64(offset
+ offsetof(struct method_t
, name
),
1062 s
->addr
- info
->database
, m
.name
,
1063 s
->relocs
, s
->nrelocs
, info
, &n_value
);
1065 if(info
->Vflag
&& sym_name
!= NULL
)
1066 printf("%s", sym_name
);
1068 printf("0x%llx", n_value
);
1070 printf(" + 0x%llx", m
.name
);
1073 printf("0x%llx", m
.name
);
1074 name
= get_pointer_64(m
.name
+ n_value
, NULL
, &left
, NULL
,
1075 info
->sections
, info
->nsections
);
1077 printf(" %.*s", (int)left
, name
);
1080 printf("%s\t\t types ", indent
);
1081 sym_name
= get_symbol_64(offset
+ offsetof(struct method_t
, types
),
1082 s
->addr
- info
->database
, m
.types
,
1083 s
->relocs
, s
->nrelocs
, info
, &n_value
);
1085 if(info
->Vflag
&& sym_name
!= NULL
)
1086 printf("%s", sym_name
);
1088 printf("0x%llx", n_value
);
1090 printf(" + 0x%llx", m
.types
);
1093 printf("0x%llx", m
.types
);
1094 name
= get_pointer_64(m
.types
+ n_value
, NULL
, &left
, NULL
,
1095 info
->sections
, info
->nsections
);
1097 printf(" %.*s", (int)left
, name
);
1100 printf("%s\t\t imp ", indent
);
1101 name
= get_symbol_64(offset
+ offsetof(struct method_t
, imp
),
1102 s
->addr
- info
->database
, m
.imp
, s
->relocs
,
1103 s
->nrelocs
, info
, &n_value
);
1104 if(info
->Vflag
== FALSE
|| name
== NULL
){
1106 printf("0x%llx ", n_value
);
1108 printf("+ 0x%llx ", m
.imp
);
1111 printf("0x%llx ", m
.imp
);
1117 p
+= sizeof(struct method_t
);
1118 offset
+= sizeof(struct method_t
);
1128 struct ivar_list_t il
;
1131 uint32_t offset
, left
, j
;
1132 struct section_info_64
*s
;
1133 const char *name
, *sym_name
;
1134 uint64_t *ivar_offset_p
, ivar_offset
, n_value
;
1137 r
= get_pointer_64(p
, &offset
, &left
, &s
, info
->sections
,
1141 memset(&il
, '\0', sizeof(struct ivar_list_t
));
1142 if(left
< sizeof(struct ivar_list_t
)){
1143 memcpy(&il
, r
, left
);
1144 printf(" (ivar_list_t entends past the end of the section)\n");
1147 memcpy(&il
, r
, sizeof(struct ivar_list_t
));
1149 swap_ivar_list_t(&il
, info
->host_byte_sex
);
1150 printf(" entsize %u\n", il
.entsize
);
1151 printf(" count %u\n", il
.count
);
1153 p
+= sizeof(struct ivar_list_t
);
1154 offset
+= sizeof(struct ivar_list_t
);
1155 for(j
= 0; j
< il
.count
; j
++){
1156 r
= get_pointer_64(p
, &offset
, &left
, &s
, info
->sections
,
1160 memset(&i
, '\0', sizeof(struct ivar_t
));
1161 if(left
< sizeof(struct ivar_t
)){
1162 memcpy(&i
, r
, left
);
1163 printf(" (ivar_t entends past the end of the section)\n");
1166 memcpy(&i
, r
, sizeof(struct ivar_t
));
1168 swap_ivar_t(&i
, info
->host_byte_sex
);
1170 printf("\t\t\t offset ");
1171 sym_name
= get_symbol_64(offset
+ offsetof(struct ivar_t
, offset
),
1172 s
->addr
- info
->database
, i
.offset
,
1173 s
->relocs
, s
->nrelocs
, info
, &n_value
);
1175 if(info
->Vflag
&& sym_name
!= NULL
)
1176 printf("%s", sym_name
);
1178 printf("0x%llx", n_value
);
1180 printf(" + 0x%llx", i
.offset
);
1183 printf("0x%llx", i
.offset
);
1184 ivar_offset_p
= get_pointer_64(i
.offset
+ n_value
, NULL
, &left
,
1185 NULL
,info
->sections
,info
->nsections
);
1186 if(ivar_offset_p
!= NULL
&& left
>= sizeof(*ivar_offset_p
)){
1187 memcpy(&ivar_offset
, ivar_offset_p
, sizeof(ivar_offset
));
1189 ivar_offset
= SWAP_LONG_LONG(ivar_offset
);
1190 printf(" %llu\n", ivar_offset
);
1195 printf("\t\t\t name ");
1196 sym_name
= get_symbol_64(offset
+ offsetof(struct ivar_t
, name
),
1197 s
->addr
- info
->database
, i
.name
,
1198 s
->relocs
, s
->nrelocs
, info
, &n_value
);
1200 if(info
->Vflag
&& sym_name
!= NULL
)
1201 printf("%s", sym_name
);
1203 printf("0x%llx", n_value
);
1205 printf(" + 0x%llx", i
.name
);
1208 printf("0x%llx", i
.name
);
1209 name
= get_pointer_64(i
.name
+ n_value
, NULL
, &left
, NULL
,
1210 info
->sections
, info
->nsections
);
1212 printf(" %.*s", (int)left
, name
);
1215 printf("\t\t\t type ");
1216 sym_name
= get_symbol_64(offset
+ offsetof(struct ivar_t
, type
),
1217 s
->addr
- info
->database
, i
.type
,
1218 s
->relocs
, s
->nrelocs
, info
, &n_value
);
1219 name
= get_pointer_64(i
.type
+ n_value
, NULL
, &left
, NULL
,
1220 info
->sections
, info
->nsections
);
1222 if(info
->Vflag
&& sym_name
!= NULL
)
1223 printf("%s", sym_name
);
1225 printf("0x%llx", n_value
);
1227 printf(" + 0x%llx", i
.type
);
1230 printf("0x%llx", i
.type
);
1232 printf(" %.*s", (int)left
, name
);
1235 printf("\t\t\talignment %u\n", i
.alignment
);
1236 printf("\t\t\t size %u\n", i
.size
);
1238 p
+= sizeof(struct ivar_t
);
1239 offset
+= sizeof(struct ivar_t
);
1245 print_protocol_list_t(
1249 struct protocol_list_t pl
;
1250 uint64_t q
, n_value
;
1251 struct protocol_t pc
;
1253 uint32_t offset
, left
, i
;
1254 struct section_info_64
*s
;
1255 const char *name
, *sym_name
;
1257 r
= get_pointer_64(p
, &offset
, &left
, &s
, info
->sections
,
1261 memset(&pl
, '\0', sizeof(struct protocol_list_t
));
1262 if(left
< sizeof(struct protocol_list_t
)){
1263 memcpy(&pl
, r
, left
);
1264 printf(" (protocol_list_t entends past the end of the "
1268 memcpy(&pl
, r
, sizeof(struct protocol_list_t
));
1270 swap_protocol_list_t(&pl
, info
->host_byte_sex
);
1271 printf(" count %llu\n", pl
.count
);
1273 p
+= sizeof(struct protocol_list_t
);
1274 offset
+= sizeof(struct protocol_list_t
);
1275 for(i
= 0; i
< pl
.count
; i
++){
1276 r
= get_pointer_64(p
, &offset
, &left
, &s
, info
->sections
,
1281 if(left
< sizeof(uint64_t)){
1282 memcpy(&q
, r
, left
);
1283 printf(" (protocol_t * entends past the end of the "
1287 memcpy(&q
, r
, sizeof(uint64_t));
1289 q
= SWAP_LONG_LONG(q
);
1291 printf("\t\t list[%u] ", i
);
1292 sym_name
= get_symbol_64(offset
, s
->addr
- info
->database
, q
,
1293 s
->relocs
, s
->nrelocs
, info
, &n_value
);
1295 if(info
->Vflag
&& sym_name
!= NULL
)
1296 printf("%s", sym_name
);
1298 printf("0x%llx", n_value
);
1300 printf(" + 0x%llx", q
);
1303 printf("0x%llx", q
);
1304 printf(" (struct protocol_t *)\n");
1306 r
= get_pointer_64(q
+ n_value
, &offset
, &left
, &s
, info
->sections
,
1310 memset(&pc
, '\0', sizeof(struct protocol_t
));
1311 if(left
< sizeof(struct protocol_t
)){
1312 memcpy(&pc
, r
, left
);
1313 printf(" (protocol_t entends past the end of the section)\n");
1316 memcpy(&pc
, r
, sizeof(struct protocol_t
));
1318 swap_protocol_t(&pc
, info
->host_byte_sex
);
1320 printf("\t\t\t isa 0x%llx\n", pc
.isa
);
1322 printf("\t\t\t name ");
1323 sym_name
= get_symbol_64(offset
+ offsetof(struct protocol_t
, name
),
1324 s
->addr
- info
->database
, pc
.name
,
1325 s
->relocs
, s
->nrelocs
, info
, &n_value
);
1327 if(info
->Vflag
&& sym_name
!= NULL
)
1328 printf("%s", sym_name
);
1330 printf("0x%llx", n_value
);
1332 printf(" + 0x%llx", pc
.name
);
1335 printf("0x%llx", pc
.name
);
1336 name
= get_pointer_64(pc
.name
+ n_value
, NULL
, &left
, NULL
,
1337 info
->sections
, info
->nsections
);
1339 printf(" %.*s", (int)left
, name
);
1342 printf("\t\t\tprotocols 0x%llx\n", pc
.protocols
);
1344 printf("\t\t instanceMethods ");
1345 sym_name
= get_symbol_64(offset
+ offsetof(struct protocol_t
,
1347 s
->addr
- info
->database
,
1348 pc
.instanceMethods
, s
->relocs
, s
->nrelocs
,
1351 if(info
->Vflag
&& sym_name
!= NULL
)
1352 printf("%s", sym_name
);
1354 printf("0x%llx", n_value
);
1355 if(pc
.instanceMethods
!= 0)
1356 printf(" + 0x%llx", pc
.instanceMethods
);
1359 printf("0x%llx", pc
.instanceMethods
);
1360 printf(" (struct method_list_t *)\n");
1361 if(pc
.instanceMethods
+ n_value
!= 0)
1362 print_method_list_t(pc
.instanceMethods
+ n_value
, info
, "\t");
1364 printf("\t\t classMethods ");
1365 sym_name
= get_symbol_64(offset
+ offsetof(struct protocol_t
,
1367 s
->addr
- info
->database
,
1368 pc
.classMethods
, s
->relocs
, s
->nrelocs
,
1371 if(info
->Vflag
&& sym_name
!= NULL
)
1372 printf("%s", sym_name
);
1374 printf("0x%llx", n_value
);
1375 if(pc
.classMethods
!= 0)
1376 printf(" + 0x%llx", pc
.classMethods
);
1379 printf("0x%llx", pc
.classMethods
);
1380 printf(" (struct method_list_t *)\n");
1382 if(pc
.classMethods
+ n_value
!= 0)
1383 print_method_list_t(pc
.classMethods
+ n_value
, info
, "\t");
1384 printf("\t optionalInstanceMethods 0x%llx\n",
1385 pc
.optionalInstanceMethods
);
1386 printf("\t optionalClassMethods 0x%llx\n",
1387 pc
.optionalClassMethods
);
1388 printf("\t instanceProperties 0x%llx\n",
1389 pc
.instanceProperties
);
1391 p
+= sizeof(uint64_t);
1392 offset
+= sizeof(uint64_t);
1398 print_objc_property_list(
1402 struct objc_property_list opl
;
1403 struct objc_property op
;
1405 uint32_t offset
, left
, j
;
1406 struct section_info_64
*s
;
1407 const char *name
, *sym_name
;
1410 r
= get_pointer_64(p
, &offset
, &left
, &s
, info
->sections
,
1414 memset(&opl
, '\0', sizeof(struct objc_property_list
));
1415 if(left
< sizeof(struct objc_property_list
)){
1416 memcpy(&opl
, r
, left
);
1417 printf(" (objc_property_list entends past the end of the "
1421 memcpy(&opl
, r
, sizeof(struct objc_property_list
));
1423 swap_objc_property_list(&opl
, info
->host_byte_sex
);
1424 printf(" entsize %u\n", opl
.entsize
);
1425 printf(" count %u\n", opl
.count
);
1427 p
+= sizeof(struct objc_property_list
);
1428 offset
+= sizeof(struct objc_property_list
);
1429 for(j
= 0; j
< opl
.count
; j
++){
1430 r
= get_pointer_64(p
, &offset
, &left
, &s
, info
->sections
,
1434 memset(&op
, '\0', sizeof(struct objc_property
));
1435 if(left
< sizeof(struct objc_property
)){
1436 memcpy(&op
, r
, left
);
1437 printf(" (objc_property entends past the end of the "
1441 memcpy(&op
, r
, sizeof(struct objc_property
));
1443 swap_objc_property(&op
, info
->host_byte_sex
);
1445 printf("\t\t\t name ");
1446 sym_name
= get_symbol_64(offset
+ offsetof(struct objc_property
,
1448 s
->addr
- info
->database
, op
.name
,
1449 s
->relocs
, s
->nrelocs
, info
, &n_value
);
1451 if(info
->Vflag
&& sym_name
!= NULL
)
1452 printf("%s", sym_name
);
1454 printf("0x%llx", n_value
);
1456 printf(" + 0x%llx", op
.name
);
1459 printf("0x%llx", op
.name
);
1460 name
= get_pointer_64(op
.name
+ n_value
, NULL
, &left
, NULL
,
1461 info
->sections
, info
->nsections
);
1463 printf(" %.*s", (int)left
, name
);
1466 printf("\t\t\tattributes ");
1467 sym_name
= get_symbol_64(offset
+ offsetof(struct objc_property
,
1469 s
->addr
- info
->database
, op
.attributes
,
1470 s
->relocs
, s
->nrelocs
, info
, &n_value
);
1472 if(info
->Vflag
&& sym_name
!= NULL
)
1473 printf("%s", sym_name
);
1475 printf("0x%llx", n_value
);
1476 if(op
.attributes
!= 0)
1477 printf(" + 0x%llx", op
.attributes
);
1480 printf("0x%llx", op
.attributes
);
1481 name
= get_pointer_64(op
.attributes
+ n_value
, NULL
, &left
, NULL
,
1482 info
->sections
, info
->nsections
);
1484 printf(" %.*s", (int)left
, name
);
1487 p
+= sizeof(struct objc_property
);
1488 offset
+= sizeof(struct objc_property
);
1498 struct category_t c
;
1500 uint32_t offset
, left
;
1501 struct section_info_64
*s
;
1502 const char *name
, *sym_name
;
1505 r
= get_pointer_64(p
, &offset
, &left
, &s
,
1506 info
->sections
, info
->nsections
);
1509 memset(&c
, '\0', sizeof(struct category_t
));
1510 if(left
< sizeof(struct category_t
)){
1511 memcpy(&c
, r
, left
);
1512 printf(" (category_t entends past the end of the section)\n");
1515 memcpy(&c
, r
, sizeof(struct category_t
));
1517 swap_category_t(&c
, info
->host_byte_sex
);
1520 sym_name
= get_symbol_64(offset
+ offsetof(struct category_t
, name
),
1521 s
->addr
- info
->database
, c
.name
, s
->relocs
,
1522 s
->nrelocs
, info
, &n_value
);
1524 if(info
->Vflag
&& sym_name
!= NULL
)
1525 printf("%s", sym_name
);
1527 printf("0x%llx", n_value
);
1529 printf(" + 0x%llx", c
.name
);
1532 printf("0x%llx", c
.name
);
1533 name
= get_pointer_64(c
.name
+ n_value
, NULL
, &left
, NULL
,
1534 info
->sections
, info
->nsections
);
1536 printf(" %.*s", (int)left
, name
);
1540 sym_name
= get_symbol_64(offset
+ offsetof(struct category_t
, cls
),
1541 s
->addr
- info
->database
, c
.cls
, s
->relocs
,
1542 s
->nrelocs
, info
, &n_value
);
1544 if(info
->Vflag
&& sym_name
!= NULL
)
1545 printf("%s", sym_name
);
1547 printf("0x%llx", n_value
);
1549 printf(" + 0x%llx", c
.cls
);
1552 printf("0x%llx", c
.cls
);
1554 if(c
.cls
+ n_value
!= 0)
1555 print_class_t(c
.cls
+ n_value
, info
);
1557 printf(" instanceMethods ");
1558 sym_name
= get_symbol_64(offset
+ offsetof(struct category_t
,
1560 s
->addr
- info
->database
, c
.instanceMethods
,
1561 s
->relocs
, s
->nrelocs
, info
, &n_value
);
1563 if(info
->Vflag
&& sym_name
!= NULL
)
1564 printf("%s", sym_name
);
1566 printf("0x%llx", n_value
);
1567 if(c
.instanceMethods
!= 0)
1568 printf(" + 0x%llx", c
.instanceMethods
);
1571 printf("0x%llx", c
.instanceMethods
);
1573 if(c
.instanceMethods
+ n_value
!= 0)
1574 print_method_list_t(c
.instanceMethods
+ n_value
, info
, "");
1576 printf(" classMethods ");
1577 sym_name
= get_symbol_64(offset
+ offsetof(struct category_t
,
1579 s
->addr
- info
->database
, c
.classMethods
,
1580 s
->relocs
, s
->nrelocs
, info
, &n_value
);
1582 if(info
->Vflag
&& sym_name
!= NULL
)
1583 printf("%s", sym_name
);
1585 printf("0x%llx", n_value
);
1586 if(c
.classMethods
!= 0)
1587 printf(" + 0x%llx", c
.classMethods
);
1590 printf("0x%llx", c
.classMethods
);
1592 if(c
.classMethods
+ n_value
!= 0)
1593 print_method_list_t(c
.classMethods
+ n_value
, info
, "");
1595 printf(" protocols ");
1596 sym_name
= get_symbol_64(offset
+ offsetof(struct category_t
,
1598 s
->addr
- info
->database
, c
.protocols
,
1599 s
->relocs
, s
->nrelocs
, info
, &n_value
);
1601 if(info
->Vflag
&& sym_name
!= NULL
)
1602 printf("%s", sym_name
);
1604 printf("0x%llx", n_value
);
1605 if(c
.protocols
!= 0)
1606 printf(" + 0x%llx", c
.protocols
);
1609 printf("0x%llx", c
.protocols
);
1611 if(c
.protocols
+ n_value
!= 0)
1612 print_protocol_list_t(c
.protocols
+ n_value
, info
);
1614 printf("instanceProperties ");
1615 sym_name
= get_symbol_64(offset
+ offsetof(struct category_t
,
1616 instanceProperties
),
1617 s
->addr
- info
->database
, c
.instanceProperties
,
1618 s
->relocs
, s
->nrelocs
, info
, &n_value
);
1620 if(info
->Vflag
&& sym_name
!= NULL
)
1621 printf("%s", sym_name
);
1623 printf("0x%llx", n_value
);
1624 if(c
.instanceProperties
!= 0)
1625 printf(" + 0x%llx", c
.instanceProperties
);
1628 printf("0x%llx", c
.instanceProperties
);
1630 if(c
.instanceProperties
+ n_value
)
1631 print_objc_property_list(c
.instanceProperties
+ n_value
, info
);
1637 struct section_info_64
*s
,
1640 uint32_t i
, left
, offset
;
1641 uint64_t p
, n_value
;
1642 struct message_ref mr
;
1643 const char *name
, *sym_name
;
1649 printf("Contents of (%.16s,%.16s) section\n", s
->segname
, s
->sectname
);
1651 for(i
= 0; i
< s
->size
; i
+= sizeof(struct message_ref
)){
1653 r
= get_pointer_64(p
, &offset
, &left
, &s
,
1654 info
->sections
, info
->nsections
);
1657 memset(&mr
, '\0', sizeof(struct message_ref
));
1658 if(left
< sizeof(struct message_ref
)){
1659 memcpy(&mr
, r
, left
);
1660 printf(" (message_ref entends past the end of the section)\n");
1663 memcpy(&mr
, r
, sizeof(struct message_ref
));
1665 swap_message_ref(&mr
, info
->host_byte_sex
);
1668 name
= get_symbol_64(offset
+ offsetof(struct message_ref
, imp
),
1669 s
->addr
- info
->database
, mr
.imp
, s
->relocs
,
1670 s
->nrelocs
, info
, &n_value
);
1672 printf("0x%llx", n_value
);
1674 printf(" + 0x%llx", mr
.imp
);
1677 printf("0x%llx", mr
.imp
);
1679 printf(" %s", name
);
1683 sym_name
= get_symbol_64(offset
+ offsetof(struct message_ref
, sel
),
1684 s
->addr
- info
->database
, mr
.sel
,
1685 s
->relocs
, s
->nrelocs
, info
, &n_value
);
1687 if(info
->Vflag
&& sym_name
!= NULL
)
1688 printf("%s", sym_name
);
1690 printf("0x%llx", n_value
);
1692 printf(" + 0x%llx", mr
.sel
);
1695 printf("0x%llx", mr
.sel
);
1696 name
= get_pointer_64(mr
.sel
+ n_value
, NULL
, &left
, NULL
,
1697 info
->sections
, info
->nsections
);
1699 printf(" %.*s", (int)left
, name
);
1702 offset
+= sizeof(struct message_ref
);
1709 struct section_info_64
*s
,
1712 uint32_t left
, offset
;
1714 struct objc_image_info o
;
1720 printf("Contents of (%.16s,%.16s) section\n", s
->segname
, s
->sectname
);
1722 r
= get_pointer_64(p
, &offset
, &left
, &s
,
1723 info
->sections
, info
->nsections
);
1726 memset(&o
, '\0', sizeof(struct objc_image_info
));
1727 if(left
< sizeof(struct objc_image_info
)){
1728 memcpy(&o
, r
, left
);
1729 printf(" (objc_image_info entends past the end of the section)\n");
1732 memcpy(&o
, r
, sizeof(struct objc_image_info
));
1734 swap_objc_image_info(&o
, info
->host_byte_sex
);
1735 printf(" version %u\n", o
.version
);
1736 printf(" flags 0x%x", o
.flags
);
1737 if(o
.flags
& OBJC_IMAGE_IS_REPLACEMENT
)
1738 printf(" OBJC_IMAGE_IS_REPLACEMENT");
1739 if(o
.flags
& OBJC_IMAGE_SUPPORTS_GC
)
1740 printf(" OBJC_IMAGE_SUPPORTS_GC");
1745 print_objc_string_object_section_64(
1747 struct load_command
*load_commands
,
1749 uint32_t sizeofcmds
,
1750 enum byte_sex object_byte_sex
,
1752 uint32_t object_size
,
1754 struct nlist_64
*symbols64
,
1757 const uint32_t strings_size
,
1758 struct symbol
*sorted_symbols
,
1759 uint32_t nsorted_symbols
,
1763 struct section_info_64
*o
, cstring_section
;
1764 struct objc_string_object_64
*string_objects
, *s
, string_object
;
1765 uint64_t string_objects_addr
, string_objects_size
;
1766 uint32_t size
, left
;
1770 printf("Contents of (" SEG_OBJC
",%s) section\n", sectname
);
1771 info
.host_byte_sex
= get_host_byte_sex();
1772 info
.swapped
= info
.host_byte_sex
!= object_byte_sex
;
1773 info
.cputype
= cputype
;
1774 info
.symbols64
= symbols64
;
1775 info
.nsymbols
= nsymbols
;
1776 info
.strings
= strings
;
1777 info
.strings_size
= strings_size
;
1778 info
.sorted_symbols
= sorted_symbols
;
1779 info
.nsorted_symbols
= nsorted_symbols
;
1780 info
.verbose
= verbose
;
1781 get_sections_64(load_commands
, ncmds
, sizeofcmds
, object_byte_sex
,
1782 object_addr
, object_size
, &info
.sections
,
1783 &info
.nsections
, &info
.database
);
1784 o
= get_section_64(info
.sections
, info
.nsections
, SEG_OBJC
, sectname
);
1787 get_cstring_section_64(load_commands
, ncmds
, sizeofcmds
,object_byte_sex
,
1788 object_addr
, object_size
, &cstring_section
);
1790 string_objects
= (struct objc_string_object_64
*)o
->contents
;
1791 string_objects_addr
= o
->addr
;
1792 string_objects_size
= o
->size
;
1793 for(s
= string_objects
;
1794 (char *)s
< (char *)string_objects
+ string_objects_size
;
1797 memset(&string_object
, '\0', sizeof(struct objc_string_object_64
));
1798 left
= string_objects_size
- (s
- string_objects
);
1799 size
= left
< sizeof(struct objc_string_object_64
) ?
1800 left
: sizeof(struct objc_string_object_64
);
1801 memcpy(&string_object
, s
, size
);
1803 if((char *)s
+ sizeof(struct objc_string_object_64
) >
1804 (char *)s
+ string_objects_size
)
1805 printf("String Object extends past end of %s section\n",
1807 printf("String Object 0x%llx\n",
1808 string_objects_addr
+ ((char *)s
- (char *)string_objects
));
1811 swap_string_object_64(&string_object
, info
.host_byte_sex
);
1812 printf(" isa 0x%llx", string_object
.isa
);
1813 name
= get_symbol_64((uintptr_t)s
- (uintptr_t)string_objects
,
1814 o
->addr
- info
.database
, string_object
.isa
,
1815 o
->relocs
, o
->nrelocs
, &info
, NULL
);
1817 printf(" %s\n", name
);
1820 printf(" characters 0x%llx", string_object
.characters
);
1822 p
= get_pointer_64(string_object
.characters
, NULL
, &left
,
1823 NULL
, info
.sections
, info
.nsections
);
1825 printf(" %.*s\n", (int)left
, p
);
1829 printf(" _length %u\n", string_object
._length
);
1830 printf(" _pad %u\n", string_object
._pad
);
1837 struct load_command
*load_commands
,
1839 uint32_t sizeofcmds
,
1840 enum byte_sex object_byte_sex
,
1842 uint32_t object_size
,
1843 struct section_info_64
**sections
,
1844 uint32_t *nsections
,
1847 enum byte_sex host_byte_sex
;
1848 enum bool swapped
, database_set
, zerobased
, encrypt_found
, encrypt64_found
;
1850 uint32_t i
, j
, left
, size
;
1851 struct load_command lcmd
, *lc
;
1853 struct segment_command_64 sg64
;
1854 struct section_64 s64
;
1855 struct encryption_info_command encrypt
;
1856 struct encryption_info_command_64 encrypt64
;
1858 host_byte_sex
= get_host_byte_sex();
1859 swapped
= host_byte_sex
!= object_byte_sex
;
1863 database_set
= FALSE
;
1866 encrypt_found
= FALSE
;
1867 encrypt64_found
= FALSE
;
1870 for(i
= 0 ; i
< ncmds
; i
++){
1871 memcpy((char *)&lcmd
, (char *)lc
, sizeof(struct load_command
));
1873 swap_load_command(&lcmd
, host_byte_sex
);
1874 if(lcmd
.cmdsize
% sizeof(int32_t) != 0)
1875 printf("load command %u size not a multiple of "
1876 "sizeof(int32_t)\n", i
);
1877 if((char *)lc
+ lcmd
.cmdsize
>
1878 (char *)load_commands
+ sizeofcmds
)
1879 printf("load command %u extends past end of load "
1881 left
= sizeofcmds
- ((char *)lc
- (char *)load_commands
);
1885 memset((char *)&sg64
, '\0', sizeof(struct segment_command_64
));
1886 size
= left
< sizeof(struct segment_command_64
) ?
1887 left
: sizeof(struct segment_command_64
);
1888 memcpy((char *)&sg64
, (char *)lc
, size
);
1890 swap_segment_command_64(&sg64
, host_byte_sex
);
1891 if((sg64
.initprot
& VM_PROT_WRITE
) == VM_PROT_WRITE
&&
1892 database_set
== FALSE
){
1893 *database
= sg64
.vmaddr
;
1894 database_set
= TRUE
;
1896 if((sg64
.initprot
& VM_PROT_READ
) == VM_PROT_READ
&&
1899 p
= (char *)lc
+ sizeof(struct segment_command_64
);
1900 for(j
= 0 ; j
< sg64
.nsects
; j
++){
1901 if(p
+ sizeof(struct section_64
) >
1902 (char *)load_commands
+ sizeofcmds
){
1903 printf("section structure command extends past "
1904 "end of load commands\n");
1906 left
= sizeofcmds
- (p
- (char *)load_commands
);
1907 memset((char *)&s64
, '\0', sizeof(struct section_64
));
1908 size
= left
< sizeof(struct section_64
) ?
1909 left
: sizeof(struct section_64
);
1910 memcpy((char *)&s64
, p
, size
);
1912 swap_section_64(&s64
, 1, host_byte_sex
);
1914 *sections
= reallocate(*sections
,
1915 sizeof(struct section_info_64
) * (*nsections
+ 1));
1916 memcpy((*sections
)[*nsections
].segname
,
1918 memcpy((*sections
)[*nsections
].sectname
,
1920 (*sections
)[*nsections
].addr
= s64
.addr
;
1921 (*sections
)[*nsections
].contents
= object_addr
+ s64
.offset
;
1922 (*sections
)[*nsections
].offset
= s64
.offset
;
1923 (*sections
)[*nsections
].zerofill
=
1924 (s64
.flags
& SECTION_TYPE
) == S_ZEROFILL
? TRUE
: FALSE
;
1925 if(s64
.offset
> object_size
){
1926 printf("section contents of: (%.16s,%.16s) is past "
1927 "end of file\n", s64
.segname
, s64
.sectname
);
1928 (*sections
)[*nsections
].size
= 0;
1930 else if(s64
.offset
+ s64
.size
> object_size
){
1931 printf("part of section contents of: (%.16s,%.16s) "
1932 "is past end of file\n",
1933 s64
.segname
, s64
.sectname
);
1934 (*sections
)[*nsections
].size
= object_size
- s64
.offset
;
1937 (*sections
)[*nsections
].size
= s64
.size
;
1938 if(s64
.reloff
>= object_size
){
1939 printf("relocation entries offset for (%.16s,%.16s)"
1940 ": is past end of file\n", s64
.segname
,
1942 (*sections
)[*nsections
].nrelocs
= 0;
1945 (*sections
)[*nsections
].relocs
=
1946 (struct relocation_info
*)(object_addr
+
1949 s64
.nreloc
* sizeof(struct relocation_info
) >
1951 printf("relocation entries for section (%.16s,"
1952 "%.16s) extends past end of file\n",
1953 s64
.segname
, s64
.sectname
);
1954 (*sections
)[*nsections
].nrelocs
=
1955 (object_size
- s64
.reloff
) /
1956 sizeof(struct relocation_info
);
1959 (*sections
)[*nsections
].nrelocs
= s64
.nreloc
;
1961 swap_relocation_info(
1962 (*sections
)[*nsections
].relocs
,
1963 (*sections
)[*nsections
].nrelocs
,
1966 if(sg64
.flags
& SG_PROTECTED_VERSION_1
)
1967 (*sections
)[*nsections
].protected = TRUE
;
1969 (*sections
)[*nsections
].protected = FALSE
;
1970 if((s64
.flags
& SECTION_TYPE
) == S_CSTRING_LITERALS
)
1971 (*sections
)[*nsections
].cstring
= TRUE
;
1973 (*sections
)[*nsections
].cstring
= FALSE
;
1976 if(p
+ sizeof(struct section_64
) >
1977 (char *)load_commands
+ sizeofcmds
)
1982 case LC_ENCRYPTION_INFO
:
1983 memset((char *)&encrypt
, '\0',
1984 sizeof(struct encryption_info_command
));
1985 size
= left
< sizeof(struct encryption_info_command
) ?
1986 left
: sizeof(struct encryption_info_command
);
1987 memcpy((char *)&encrypt
, (char *)lc
, size
);
1989 swap_encryption_command(&encrypt
, host_byte_sex
);
1990 encrypt_found
= TRUE
;
1992 case LC_ENCRYPTION_INFO_64
:
1993 memset((char *)&encrypt64
, '\0',
1994 sizeof(struct encryption_info_command_64
));
1995 size
= left
< sizeof(struct encryption_info_command_64
) ?
1996 left
: sizeof(struct encryption_info_command_64
);
1997 memcpy((char *)&encrypt64
, (char *)lc
, size
);
1999 swap_encryption_command_64(&encrypt64
, host_byte_sex
);
2000 encrypt64_found
= TRUE
;
2003 if(lcmd
.cmdsize
== 0){
2004 printf("load command %u size zero (can't advance to other "
2005 "load commands)\n", i
);
2008 lc
= (struct load_command
*)((char *)lc
+ lcmd
.cmdsize
);
2009 if((char *)lc
> (char *)load_commands
+ sizeofcmds
)
2013 if(encrypt_found
== TRUE
&& encrypt
.cryptid
!= 0){
2014 for(i
= 0; i
< *nsections
; i
++){
2015 if((*sections
)[i
].size
> 0 && (*sections
)[i
].zerofill
== FALSE
){
2016 if((*sections
)[i
].offset
>
2017 encrypt
.cryptoff
+ encrypt
.cryptsize
){
2018 /* section starts past encryption area */ ;
2020 else if((*sections
)[i
].offset
+ (*sections
)[i
].size
<
2022 /* section ends before encryption area */ ;
2025 /* section has part in the encrypted area */
2026 (*sections
)[i
].protected = TRUE
;
2031 if(encrypt64_found
== TRUE
&& encrypt64
.cryptid
!= 0){
2032 for(i
= 0; i
< *nsections
; i
++){
2033 if((*sections
)[i
].size
> 0 && (*sections
)[i
].zerofill
== FALSE
){
2034 if((*sections
)[i
].offset
>
2035 encrypt64
.cryptoff
+ encrypt64
.cryptsize
){
2036 /* section starts past encryption area */ ;
2038 else if((*sections
)[i
].offset
+ (*sections
)[i
].size
<
2039 encrypt64
.cryptoff
){
2040 /* section ends before encryption area */ ;
2043 /* section has part in the encrypted area */
2044 (*sections
)[i
].protected = TRUE
;
2052 struct section_info_64
*
2054 struct section_info_64
*sections
,
2061 for(i
= 0; i
< nsections
; i
++){
2062 if(strncmp(sections
[i
].segname
, segname
, 16) == 0 &&
2063 strncmp(sections
[i
].sectname
, sectname
, 16) == 0){
2064 return(sections
+ i
);
2072 get_cstring_section_64(
2073 struct load_command
*load_commands
,
2075 uint32_t sizeofcmds
,
2076 enum byte_sex object_byte_sex
,
2078 uint32_t object_size
,
2079 struct section_info_64
*cstring_section
)
2081 enum byte_sex host_byte_sex
;
2084 uint32_t i
, j
, left
, size
;
2085 struct load_command lcmd
, *lc
;
2087 struct segment_command_64 sg64
;
2088 struct section_64 s64
;
2090 host_byte_sex
= get_host_byte_sex();
2091 swapped
= host_byte_sex
!= object_byte_sex
;
2093 memset(cstring_section
, '\0', sizeof(struct section_info_64
));
2096 for(i
= 0 ; i
< ncmds
; i
++){
2097 memcpy((char *)&lcmd
, (char *)lc
, sizeof(struct load_command
));
2099 swap_load_command(&lcmd
, host_byte_sex
);
2100 if(lcmd
.cmdsize
% sizeof(int32_t) != 0)
2101 printf("load command %u size not a multiple of "
2102 "sizeof(int32_t)\n", i
);
2103 if((char *)lc
+ lcmd
.cmdsize
>
2104 (char *)load_commands
+ sizeofcmds
)
2105 printf("load command %u extends past end of load "
2107 left
= sizeofcmds
- ((char *)lc
- (char *)load_commands
);
2111 memset((char *)&sg64
, '\0', sizeof(struct segment_command_64
));
2112 size
= left
< sizeof(struct segment_command_64
) ?
2113 left
: sizeof(struct segment_command_64
);
2114 memcpy((char *)&sg64
, (char *)lc
, size
);
2116 swap_segment_command_64(&sg64
, host_byte_sex
);
2118 p
= (char *)lc
+ sizeof(struct segment_command_64
);
2119 for(j
= 0 ; j
< sg64
.nsects
; j
++){
2120 if(p
+ sizeof(struct section_64
) >
2121 (char *)load_commands
+ sizeofcmds
){
2122 printf("section structure command extends past "
2123 "end of load commands\n");
2125 left
= sizeofcmds
- (p
- (char *)load_commands
);
2126 memset((char *)&s64
, '\0', sizeof(struct section_64
));
2127 size
= left
< sizeof(struct section_64
) ?
2128 left
: sizeof(struct section_64
);
2129 memcpy((char *)&s64
, p
, size
);
2131 swap_section_64(&s64
, 1, host_byte_sex
);
2133 if(strcmp(s64
.segname
, SEG_TEXT
) == 0 &&
2134 strcmp(s64
.sectname
, "__cstring") == 0){
2135 cstring_section
->addr
= s64
.addr
;
2136 cstring_section
->contents
= object_addr
+ s64
.offset
;
2137 if(s64
.offset
> object_size
){
2138 printf("section contents of: (%.16s,%.16s) is past "
2139 "end of file\n", s64
.segname
, s64
.sectname
);
2140 cstring_section
->size
= 0;
2142 else if(s64
.offset
+ s64
.size
> object_size
){
2143 printf("part of section contents of: (%.16s,%.16s) "
2144 "is past end of file\n",
2145 s64
.segname
, s64
.sectname
);
2146 cstring_section
->size
= object_size
- s64
.offset
;
2149 cstring_section
->size
= s64
.size
;
2150 if(sg64
.flags
& SG_PROTECTED_VERSION_1
)
2151 cstring_section
->protected = TRUE
;
2153 cstring_section
->protected = FALSE
;
2154 cstring_section
->cstring
= TRUE
;
2158 if(p
+ sizeof(struct section
) >
2159 (char *)load_commands
+ sizeofcmds
)
2165 if(lcmd
.cmdsize
== 0){
2166 printf("load command %u size zero (can't advance to other "
2167 "load commands)\n", i
);
2170 lc
= (struct load_command
*)((char *)lc
+ lcmd
.cmdsize
);
2171 if((char *)lc
> (char *)load_commands
+ sizeofcmds
)
2182 struct section_info_64
**s
,
2183 struct section_info_64
*sections
,
2191 for(i
= 0; i
< nsections
; i
++){
2192 if(addr
>= sections
[i
].addr
&&
2193 addr
< sections
[i
].addr
+ sections
[i
].size
){
2197 *offset
= addr
- sections
[i
].addr
;
2199 *left
= sections
[i
].size
- (addr
- sections
[i
].addr
);
2200 if(sections
[i
].protected == TRUE
&& sections
[i
].cstring
== TRUE
)
2201 r
= "some string from a protected section";
2203 r
= sections
[i
].contents
+ (addr
- sections
[i
].addr
);
2217 * get_symbol() returns the name of a symbol (or NULL). Based on the relocation
2218 * information at the specified section offset or the value.
2223 uint32_t sect_offset
,
2224 uint64_t database_offset
,
2226 struct relocation_info
*relocs
,
2232 unsigned int r_symbolnum
;
2238 if(info
->verbose
== FALSE
)
2241 for(i
= 0; i
< nrelocs
; i
++){
2242 if((uint32_t)relocs
[i
].r_address
== sect_offset
){
2243 r_symbolnum
= relocs
[i
].r_symbolnum
;
2244 if(relocs
[i
].r_extern
){
2245 if(r_symbolnum
>= info
->nsymbols
)
2247 n_strx
= info
->symbols64
[r_symbolnum
].n_un
.n_strx
;
2248 if(n_strx
<= 0 || n_strx
>= info
->strings_size
)
2251 *n_value
= info
->symbols64
[r_symbolnum
].n_value
;
2252 return(info
->strings
+ n_strx
);
2256 if(reloc_has_pair(info
->cputype
, relocs
[i
].r_type
) == TRUE
)
2259 for(i
= 0; i
< info
->next_relocs
; i
++){
2260 if((uint32_t)info
->ext_relocs
[i
].r_address
==
2261 database_offset
+ sect_offset
){
2262 r_symbolnum
= info
->ext_relocs
[i
].r_symbolnum
;
2263 if(info
->ext_relocs
[i
].r_extern
){
2264 if(r_symbolnum
>= info
->nsymbols
)
2266 n_strx
= info
->symbols64
[r_symbolnum
].n_un
.n_strx
;
2267 if(n_strx
<= 0 || n_strx
>= info
->strings_size
)
2270 *n_value
= info
->symbols64
[r_symbolnum
].n_value
;
2271 return(info
->strings
+ n_strx
);
2275 if(reloc_has_pair(info
->cputype
, info
->ext_relocs
[i
].r_type
) ==TRUE
)
2280 return(guess_symbol(value
, info
->sorted_symbols
, info
->nsorted_symbols
,