862
[darwin-xtools.git] / cctools / otool / print_objc2_64bit.c
blob79786776f3113b8d732d80731473d766df0423bf
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 "stdlib.h"
33 #include "stddef.h"
34 #include "string.h"
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"
43 extern char *oname;
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
48 * program.
50 * The real structure definitions come from the objc4 project in the private
51 * header file runtime/objc-runtime-new.h in that project.
54 struct class_t {
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) */
62 static
63 void
64 swap_class_t(
65 struct class_t *c,
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);
75 struct class_ro_t {
76 uint32_t flags;
77 uint32_t instanceStart;
78 uint32_t instanceSize;
79 uint32_t reserved;
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 *
87 (64-bit pointer) */
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)
96 static
97 void
98 swap_class_ro_t(
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 {
116 uint32_t entsize;
117 uint32_t count;
118 /* struct method_t first; These structures follow inline */
121 static
122 void
123 swap_method_list_t(
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);
131 struct method_t {
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) */
137 static
138 void
139 swap_method_t(
140 struct method_t *m,
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);
148 struct ivar_list_t {
149 uint32_t entsize;
150 uint32_t count;
151 /* struct ivar_t first; These structures follow inline */
154 static
155 void
156 swap_ivar_list_t(
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);
164 struct ivar_t {
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) */
168 uint32_t alignment;
169 uint32_t size;
172 static
173 void
174 swap_ivar_t(
175 struct ivar_t *i,
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 */
190 static
191 void
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);
199 struct protocol_t {
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 *
203 (64-bit pointer) */
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 *
209 (64-bit pointer) */
212 static
213 void
214 swap_protocol_t(
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 {
229 uint32_t entsize;
230 uint32_t count;
231 /* struct objc_property first; These structures follow inline */
234 static
235 void
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) */
249 static
250 void
251 swap_objc_property(
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);
259 struct category_t {
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 *
266 (64-bit pointer) */
269 static
270 void
271 swap_category_t(
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);
283 struct message_ref {
284 uint64_t imp; /* IMP (64-bit pointer) */
285 uint64_t sel; /* SEL (64-bit pointer) */
288 static
289 void
290 swap_message_ref(
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 {
299 uint32_t version;
300 uint32_t flags;
302 /* masks for objc_image_info.flags */
303 #define OBJC_IMAGE_IS_REPLACEMENT (1<<0)
304 #define OBJC_IMAGE_SUPPORTS_GC (1<<1)
307 static
308 void
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 */
324 static
325 void
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);
336 struct cfstring_t {
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 */
343 static
344 void
345 swap_cfstring_t(
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);
355 struct info {
356 enum bool swapped;
357 enum byte_sex host_byte_sex;
358 struct section_info_64 *sections;
359 uint32_t nsections;
360 cpu_type_t cputype;
361 struct nlist_64 *symbols64;
362 uint32_t nsymbols;
363 char *strings;
364 uint32_t strings_size;
365 struct symbol *sorted_symbols;
366 uint32_t nsorted_symbols;
367 uint64_t database;
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;
373 uint64_t ndbi;
374 enum bool verbose;
375 enum bool Vflag;
378 struct section_info_64 {
379 char segname[16];
380 char sectname[16];
381 char *contents;
382 uint64_t addr;
383 uint64_t size;
384 uint32_t offset;
385 struct relocation_info *relocs;
386 uint32_t nrelocs;
387 enum bool cstring;
388 enum bool protected;
389 enum bool zerofill;
392 static void walk_pointer_list(
393 char *listname,
394 struct section_info_64 *s,
395 struct info *info,
396 void (*func)(uint64_t, struct info *));
398 static void print_class_t(
399 uint64_t p,
400 struct info *info);
402 static void print_class_ro_t(
403 uint64_t p,
404 struct info *info,
405 enum bool *is_meta_class);
407 static void print_layout_map(
408 uint64_t p,
409 struct info *info);
411 static void print_method_list_t(
412 uint64_t p,
413 struct info *info,
414 char *indent);
416 static void print_ivar_list_t(
417 uint64_t p,
418 struct info *info);
420 static void print_protocol_list_t(
421 uint64_t p,
422 struct info *info);
424 static void print_objc_property_list(
425 uint64_t p,
426 struct info *info);
428 static void print_category_t(
429 uint64_t p,
430 struct info *info);
432 static void print_message_refs(
433 struct section_info_64 *s,
434 struct info *info);
436 static void print_image_info(
437 struct section_info_64 *s,
438 struct info *info);
440 static void get_sections_64(
441 struct load_command *load_commands,
442 uint32_t ncmds,
443 uint32_t sizeofcmds,
444 enum byte_sex object_byte_sex,
445 char *object_addr,
446 uint32_t object_size,
447 struct section_info_64 **sections,
448 uint32_t *nsections,
449 uint64_t *database);
451 static struct section_info_64 *get_section_64(
452 struct section_info_64 *sections,
453 uint32_t nsections,
454 char *segname,
455 char *sectname);
457 static void get_cstring_section_64(
458 struct load_command *load_commands,
459 uint32_t ncmds,
460 uint32_t sizeofcmds,
461 enum byte_sex object_byte_sex,
462 char *object_addr,
463 uint32_t object_size,
464 struct section_info_64 *cstring_section_ptr);
466 static void *get_pointer_64(
467 uint64_t p,
468 uint32_t *offset,
469 uint32_t *left,
470 struct section_info_64 **s,
471 struct section_info_64 *sections,
472 uint32_t nsections);
474 static const char *get_symbol_64(
475 uint32_t sect_offset,
476 uint64_t database_offset,
477 uint64_t value,
478 struct relocation_info *relocs,
479 uint32_t nrelocs,
480 struct info *info,
481 uint64_t *n_value);
484 * Print the objc2 meta data in 64-bit Mach-O files.
486 void
487 print_objc2_64bit(
488 cpu_type_t cputype,
489 struct load_command *load_commands,
490 uint32_t ncmds,
491 uint32_t sizeofcmds,
492 enum byte_sex object_byte_sex,
493 char *object_addr,
494 uint32_t object_size,
495 struct nlist_64 *symbols64,
496 uint32_t nsymbols,
497 char *strings,
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,
506 uint64_t ndbi,
507 enum bool verbose,
508 enum bool Vflag)
510 struct section_info_64 *s;
511 struct info info;
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;
526 info.dbi = dbi;
527 info.ndbi = ndbi;
528 info.verbose = verbose;
529 info.Vflag = Vflag;
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");
536 if(s == NULL)
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");
543 if(s == NULL)
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");
550 if(s == NULL)
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");
557 if(s == NULL)
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");
564 if(s == NULL)
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");
571 if(s == NULL)
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");
578 if(s == NULL)
579 s = get_section_64(info.sections, info.nsections,
580 "__DATA", "__objc_imageinfo");
581 print_image_info(s, &info);
584 static
585 void
586 walk_pointer_list(
587 char *listname,
588 struct section_info_64 *s,
589 struct info *info,
590 void (*func)(uint64_t, struct info *))
592 uint32_t i, size, left;
593 uint64_t p, n_value;
594 const char *name;
596 if(s == NULL)
597 return;
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));
603 left = s->size - i;
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);
613 if(info->swapped)
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);
618 if(name == NULL)
619 name = get_dyld_bind_info_symbolname(s->addr + i, info->dbi,
620 info->ndbi);
621 if(n_value != 0){
622 printf("0x%llx", n_value);
623 if(p != 0)
624 printf(" + 0x%llx", p);
626 else
627 printf("0x%llx", p);
628 if(name != NULL)
629 printf(" %s", name);
630 printf("\n");
632 p += n_value;
633 if(func != NULL)
634 func(p, info);
639 * get_objc2_64bit_cfstring_name() is used for disassembly and is passed a
640 * pointer to a cfstring and returns its name.
642 char *
643 get_objc2_64bit_cfstring_name(
644 uint64_t p,
645 struct load_command *load_commands,
646 uint32_t ncmds,
647 uint32_t sizeofcmds,
648 enum byte_sex object_byte_sex,
649 char *object_addr,
650 uint32_t object_size)
652 struct section_info_64 *sections;
653 uint32_t nsections, left;
654 uint64_t database;
655 struct cfstring_t cfs;
656 char *name;
657 void *r;
659 get_sections_64(load_commands, ncmds, sizeofcmds, object_byte_sex,
660 object_addr, object_size, &sections, &nsections,
661 &database);
663 r = get_pointer_64(p, NULL, &left, NULL, sections, nsections);
664 if(r == NULL || left < sizeof(struct cfstring_t))
665 return(NULL);
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)
670 return(NULL);
672 name = get_pointer_64(cfs.characters, NULL, &left, NULL,
673 sections, nsections);
675 if(sections != NULL)
676 free(sections);
678 return(name);
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.
685 char *
686 get_objc2_64bit_class_name(
687 uint64_t p,
688 struct load_command *load_commands,
689 uint32_t ncmds,
690 uint32_t sizeofcmds,
691 enum byte_sex object_byte_sex,
692 char *object_addr,
693 uint32_t object_size)
695 struct section_info_64 *sections;
696 uint32_t nsections, left;
697 uint64_t database;
698 struct class_t c;
699 struct class_ro_t cro;
700 char *name;
701 void *r;
703 get_sections_64(load_commands, ncmds, sizeofcmds, object_byte_sex,
704 object_addr, object_size, &sections, &nsections,
705 &database);
707 r = get_pointer_64(p, NULL, &left, NULL, sections, nsections);
708 if(r == NULL || left < sizeof(struct class_t))
709 return(NULL);
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());
713 if(c.data == 0)
714 return(NULL);
716 r = get_pointer_64(c.data, NULL, &left, NULL, sections, nsections);
717 if(r == NULL || left < sizeof(struct class_ro_t))
718 return(NULL);
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());
723 if(cro.name == 0)
724 return(NULL);
726 name = get_pointer_64(cro.name, NULL, &left, NULL, sections, nsections);
728 if(sections != NULL)
729 free(sections);
731 return(name);
734 static
735 void
736 print_class_t(
737 uint64_t p,
738 struct info *info)
740 struct class_t c;
741 void *r;
742 uint32_t offset, left;
743 struct section_info_64 *s;
744 const char *name;
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);
751 if(r == NULL)
752 return;
753 memset(&c, '\0', sizeof(struct class_t));
754 if(left < sizeof(struct class_t)){
755 memcpy(&c, r, left);
756 printf(" (class_t entends past the end of the section)\n");
758 else
759 memcpy(&c, r, sizeof(struct class_t));
760 if(info->swapped)
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);
766 if(name != NULL)
767 printf(" %s\n", name);
768 else
769 printf("\n");
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);
774 if(name != NULL)
775 printf(" %s\n", name);
776 else
777 printf("\n");
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);
782 if(name != NULL)
783 printf(" %s\n", name);
784 else
785 printf("\n");
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);
790 if(name != NULL)
791 printf(" %s\n", name);
792 else
793 printf("\n");
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);
798 printf(" data ");
799 if(n_value != 0){
800 if(info->Vflag && name != NULL)
801 printf("%s", name);
802 else
803 printf("0x%llx", n_value);
804 if(c.data != 0)
805 printf(" + 0x%llx", c.data);
807 else{
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
813 * are set.
815 if((c.data + n_value) & 0x7)
816 printf(" Swift class");
817 printf("\n");
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);
826 static
827 void
828 print_class_ro_t(
829 uint64_t p,
830 struct info *info,
831 enum bool *is_meta_class)
833 struct class_ro_t cro;
834 void *r;
835 uint32_t offset, left;
836 struct section_info_64 *s;
837 const char *name, *sym_name;
838 uint64_t n_value;
840 r = get_pointer_64(p, &offset, &left, &s, info->sections,
841 info->nsections);
842 if(r == NULL)
843 return;
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");
849 else
850 memcpy(&cro, r, sizeof(struct class_ro_t));
851 if(info->swapped)
852 swap_class_ro_t(&cro, info->host_byte_sex);
853 printf(" flags 0x%x", cro.flags);
854 if(cro.flags & RO_META)
855 printf(" RO_META");
856 if(cro.flags & RO_ROOT)
857 printf(" RO_ROOT");
858 if(cro.flags & RO_HAS_CXX_STRUCTORS)
859 printf(" RO_HAS_CXX_STRUCTORS");
860 printf("\n");
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);
867 printf(" name ");
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);
871 if(n_value != 0){
872 if(info->Vflag && sym_name != NULL)
873 printf("%s", sym_name);
874 else
875 printf("0x%llx", n_value);
876 if(cro.name != 0)
877 printf(" + 0x%llx", cro.name);
879 else
880 printf("0x%llx", cro.name);
881 name = get_pointer_64(cro.name + n_value, NULL, &left, NULL,
882 info->sections, info->nsections);
883 if(name != NULL)
884 printf(" %.*s", (int)left, name);
885 printf("\n");
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);
892 if(n_value != 0){
893 if(info->Vflag && sym_name != NULL)
894 printf("%s", sym_name);
895 else
896 printf("0x%llx", n_value);
897 if(cro.baseMethods != 0)
898 printf(" + 0x%llx", cro.baseMethods);
900 else
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);
911 if(n_value != 0){
912 if(info->Vflag && sym_name != NULL)
913 printf("%s", sym_name);
914 else
915 printf("0x%llx", n_value);
916 if(cro.baseProtocols != 0)
917 printf(" + 0x%llx", cro.baseProtocols);
919 else
920 printf("0x%llx", cro.baseProtocols);
921 printf("\n");
922 if(cro.baseProtocols + n_value != 0)
923 print_protocol_list_t(cro.baseProtocols + n_value, info);
925 printf(" ivars ");
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);
930 if(n_value != 0){
931 if(info->Vflag && sym_name != NULL)
932 printf("%s", sym_name);
933 else
934 printf("0x%llx", n_value);
935 if(cro.ivars != 0)
936 printf(" + 0x%llx", cro.ivars);
938 else
939 printf("0x%llx", cro.ivars);
940 printf("\n");
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);
949 if(n_value != 0){
950 if(info->Vflag && sym_name != NULL)
951 printf("%s", sym_name);
952 else
953 printf("0x%llx", n_value);
954 if(cro.weakIvarLayout != 0)
955 printf(" + 0x%llx", cro.weakIvarLayout);
957 else
958 printf("0x%llx", cro.weakIvarLayout);
959 printf("\n");
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);
967 if(n_value != 0){
968 if(info->Vflag && sym_name != NULL)
969 printf("%s", sym_name);
970 else
971 printf("0x%llx", n_value);
972 if(cro.baseProperties != 0)
973 printf(" + 0x%llx", cro.baseProperties);
975 else
976 printf("0x%llx", cro.baseProperties);
977 printf("\n");
978 if(cro.baseProperties + n_value != 0)
979 print_objc_property_list(cro.baseProperties + n_value, info);
981 if(is_meta_class)
982 *is_meta_class = (cro.flags & RO_META) ? TRUE : FALSE;
985 static
986 void
987 print_layout_map(
988 uint64_t p,
989 struct info *info)
991 uint32_t offset, left;
992 struct section_info_64 *s;
993 char *layout_map;
995 if(p == 0)
996 return;
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);
1003 left--;
1004 layout_map++;
1005 }while(*layout_map != '\0' && left != 0);
1006 printf("\n");
1010 static
1011 void
1012 print_method_list_t(
1013 uint64_t p,
1014 struct info *info,
1015 char *indent)
1017 struct method_list_t ml;
1018 struct method_t m;
1019 void *r;
1020 uint32_t offset, left, i;
1021 struct section_info_64 *s;
1022 const char *name, *sym_name;
1023 uint64_t n_value;
1025 r = get_pointer_64(p, &offset, &left, &s, info->sections,
1026 info->nsections);
1027 if(r == NULL)
1028 return;
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);
1035 else
1036 memcpy(&ml, r, sizeof(struct method_list_t));
1037 if(info->swapped)
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,
1046 info->nsections);
1047 if(r == NULL)
1048 return;
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);
1055 else
1056 memcpy(&m, r, sizeof(struct method_t));
1057 if(info->swapped)
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);
1064 if(n_value != 0){
1065 if(info->Vflag && sym_name != NULL)
1066 printf("%s", sym_name);
1067 else
1068 printf("0x%llx", n_value);
1069 if(m.name != 0)
1070 printf(" + 0x%llx", m.name);
1072 else
1073 printf("0x%llx", m.name);
1074 name = get_pointer_64(m.name + n_value, NULL, &left, NULL,
1075 info->sections, info->nsections);
1076 if(name != NULL)
1077 printf(" %.*s", (int)left, name);
1078 printf("\n");
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);
1084 if(n_value != 0){
1085 if(info->Vflag && sym_name != NULL)
1086 printf("%s", sym_name);
1087 else
1088 printf("0x%llx", n_value);
1089 if(m.name != 0)
1090 printf(" + 0x%llx", m.types);
1092 else
1093 printf("0x%llx", m.types);
1094 name = get_pointer_64(m.types + n_value, NULL, &left, NULL,
1095 info->sections, info->nsections);
1096 if(name != NULL)
1097 printf(" %.*s", (int)left, name);
1098 printf("\n");
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){
1105 if(n_value != 0){
1106 printf("0x%llx ", n_value);
1107 if(m.imp != 0)
1108 printf("+ 0x%llx ", m.imp);
1110 else
1111 printf("0x%llx ", m.imp);
1113 if(name != NULL)
1114 printf("%s", name);
1115 printf("\n");
1117 p += sizeof(struct method_t);
1118 offset += sizeof(struct method_t);
1122 static
1123 void
1124 print_ivar_list_t(
1125 uint64_t p,
1126 struct info *info)
1128 struct ivar_list_t il;
1129 struct ivar_t i;
1130 void *r;
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,
1138 info->nsections);
1139 if(r == NULL)
1140 return;
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");
1146 else
1147 memcpy(&il, r, sizeof(struct ivar_list_t));
1148 if(info->swapped)
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,
1157 info->nsections);
1158 if(r == NULL)
1159 return;
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");
1165 else
1166 memcpy(&i, r, sizeof(struct ivar_t));
1167 if(info->swapped)
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);
1174 if(n_value != 0){
1175 if(info->Vflag && sym_name != NULL)
1176 printf("%s", sym_name);
1177 else
1178 printf("0x%llx", n_value);
1179 if(i.offset != 0)
1180 printf(" + 0x%llx", i.offset);
1182 else
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));
1188 if(info->swapped)
1189 ivar_offset = SWAP_LONG_LONG(ivar_offset);
1190 printf(" %llu\n", ivar_offset);
1192 else
1193 printf("\n");
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);
1199 if(n_value != 0){
1200 if(info->Vflag && sym_name != NULL)
1201 printf("%s", sym_name);
1202 else
1203 printf("0x%llx", n_value);
1204 if(i.name != 0)
1205 printf(" + 0x%llx", i.name);
1207 else
1208 printf("0x%llx", i.name);
1209 name = get_pointer_64(i.name + n_value, NULL, &left, NULL,
1210 info->sections, info->nsections);
1211 if(name != NULL)
1212 printf(" %.*s", (int)left, name);
1213 printf("\n");
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);
1221 if(n_value != 0){
1222 if(info->Vflag && sym_name != NULL)
1223 printf("%s", sym_name);
1224 else
1225 printf("0x%llx", n_value);
1226 if(i.type != 0)
1227 printf(" + 0x%llx", i.type);
1229 else
1230 printf("0x%llx", i.type);
1231 if(name != NULL)
1232 printf(" %.*s", (int)left, name);
1233 printf("\n");
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);
1243 static
1244 void
1245 print_protocol_list_t(
1246 uint64_t p,
1247 struct info *info)
1249 struct protocol_list_t pl;
1250 uint64_t q, n_value;
1251 struct protocol_t pc;
1252 void *r;
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,
1258 info->nsections);
1259 if(r == NULL)
1260 return;
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 "
1265 "section)\n");
1267 else
1268 memcpy(&pl, r, sizeof(struct protocol_list_t));
1269 if(info->swapped)
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,
1277 info->nsections);
1278 if(r == NULL)
1279 return;
1280 q = 0;
1281 if(left < sizeof(uint64_t)){
1282 memcpy(&q, r, left);
1283 printf(" (protocol_t * entends past the end of the "
1284 "section)\n");
1286 else
1287 memcpy(&q, r, sizeof(uint64_t));
1288 if(info->swapped)
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);
1294 if(n_value != 0){
1295 if(info->Vflag && sym_name != NULL)
1296 printf("%s", sym_name);
1297 else
1298 printf("0x%llx", n_value);
1299 if(q != 0)
1300 printf(" + 0x%llx", q);
1302 else
1303 printf("0x%llx", q);
1304 printf(" (struct protocol_t *)\n");
1306 r = get_pointer_64(q + n_value, &offset, &left, &s, info->sections,
1307 info->nsections);
1308 if(r == NULL)
1309 return;
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");
1315 else
1316 memcpy(&pc, r, sizeof(struct protocol_t));
1317 if(info->swapped)
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);
1326 if(n_value != 0){
1327 if(info->Vflag && sym_name != NULL)
1328 printf("%s", sym_name);
1329 else
1330 printf("0x%llx", n_value);
1331 if(pc.name != 0)
1332 printf(" + 0x%llx", pc.name);
1334 else
1335 printf("0x%llx", pc.name);
1336 name = get_pointer_64(pc.name + n_value , NULL, &left, NULL,
1337 info->sections, info->nsections);
1338 if(name != NULL)
1339 printf(" %.*s", (int)left, name);
1340 printf("\n");
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,
1346 instanceMethods),
1347 s->addr - info->database,
1348 pc.instanceMethods, s->relocs, s->nrelocs,
1349 info, &n_value);
1350 if(n_value != 0){
1351 if(info->Vflag && sym_name != NULL)
1352 printf("%s", sym_name);
1353 else
1354 printf("0x%llx", n_value);
1355 if(pc.instanceMethods != 0)
1356 printf(" + 0x%llx", pc.instanceMethods);
1358 else
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,
1366 classMethods),
1367 s->addr - info->database,
1368 pc.classMethods, s->relocs, s->nrelocs,
1369 info, &n_value);
1370 if(n_value != 0){
1371 if(info->Vflag && sym_name != NULL)
1372 printf("%s", sym_name);
1373 else
1374 printf("0x%llx", n_value);
1375 if(pc.classMethods != 0)
1376 printf(" + 0x%llx", pc.classMethods);
1378 else
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);
1396 static
1397 void
1398 print_objc_property_list(
1399 uint64_t p,
1400 struct info *info)
1402 struct objc_property_list opl;
1403 struct objc_property op;
1404 void *r;
1405 uint32_t offset, left, j;
1406 struct section_info_64 *s;
1407 const char *name, *sym_name;
1408 uint64_t n_value;
1410 r = get_pointer_64(p, &offset, &left, &s, info->sections,
1411 info->nsections);
1412 if(r == NULL)
1413 return;
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 "
1418 "section)\n");
1420 else
1421 memcpy(&opl, r, sizeof(struct objc_property_list));
1422 if(info->swapped)
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,
1431 info->nsections);
1432 if(r == NULL)
1433 return;
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 "
1438 "section)\n");
1440 else
1441 memcpy(&op, r, sizeof(struct objc_property));
1442 if(info->swapped)
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,
1447 name),
1448 s->addr - info->database, op.name,
1449 s->relocs, s->nrelocs, info, &n_value);
1450 if(n_value != 0){
1451 if(info->Vflag && sym_name != NULL)
1452 printf("%s", sym_name);
1453 else
1454 printf("0x%llx", n_value);
1455 if(op.name != 0)
1456 printf(" + 0x%llx", op.name);
1458 else
1459 printf("0x%llx", op.name);
1460 name = get_pointer_64(op.name + n_value, NULL, &left, NULL,
1461 info->sections, info->nsections);
1462 if(name != NULL)
1463 printf(" %.*s", (int)left, name);
1464 printf("\n");
1466 printf("\t\t\tattributes ");
1467 sym_name = get_symbol_64(offset + offsetof(struct objc_property,
1468 attributes),
1469 s->addr - info->database, op.attributes,
1470 s->relocs, s->nrelocs, info, &n_value);
1471 if(n_value != 0){
1472 if(info->Vflag && sym_name != NULL)
1473 printf("%s", sym_name);
1474 else
1475 printf("0x%llx", n_value);
1476 if(op.attributes != 0)
1477 printf(" + 0x%llx", op.attributes);
1479 else
1480 printf("0x%llx", op.attributes);
1481 name = get_pointer_64(op.attributes + n_value, NULL, &left, NULL,
1482 info->sections, info->nsections);
1483 if(name != NULL)
1484 printf(" %.*s", (int)left, name);
1485 printf("\n");
1487 p += sizeof(struct objc_property);
1488 offset += sizeof(struct objc_property);
1492 static
1493 void
1494 print_category_t(
1495 uint64_t p,
1496 struct info *info)
1498 struct category_t c;
1499 void *r;
1500 uint32_t offset, left;
1501 struct section_info_64 *s;
1502 const char *name, *sym_name;
1503 uint64_t n_value;
1505 r = get_pointer_64(p, &offset, &left, &s,
1506 info->sections, info->nsections);
1507 if(r == NULL)
1508 return;
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");
1514 else
1515 memcpy(&c, r, sizeof(struct category_t));
1516 if(info->swapped)
1517 swap_category_t(&c, info->host_byte_sex);
1519 printf(" name ");
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);
1523 if(n_value != 0){
1524 if(info->Vflag && sym_name != NULL)
1525 printf("%s", sym_name);
1526 else
1527 printf("0x%llx", n_value);
1528 if(c.name != 0)
1529 printf(" + 0x%llx", c.name);
1531 else
1532 printf("0x%llx", c.name);
1533 name = get_pointer_64(c.name + n_value, NULL, &left, NULL,
1534 info->sections, info->nsections);
1535 if(name != NULL)
1536 printf(" %.*s", (int)left, name);
1537 printf("\n");
1539 printf(" cls ");
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);
1543 if(n_value != 0){
1544 if(info->Vflag && sym_name != NULL)
1545 printf("%s", sym_name);
1546 else
1547 printf("0x%llx", n_value);
1548 if(c.cls != 0)
1549 printf(" + 0x%llx", c.cls);
1551 else
1552 printf("0x%llx", c.cls);
1553 printf("\n");
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,
1559 instanceMethods),
1560 s->addr - info->database, c.instanceMethods,
1561 s->relocs, s->nrelocs, info, &n_value);
1562 if(n_value != 0){
1563 if(info->Vflag && sym_name != NULL)
1564 printf("%s", sym_name);
1565 else
1566 printf("0x%llx", n_value);
1567 if(c.instanceMethods != 0)
1568 printf(" + 0x%llx", c.instanceMethods);
1570 else
1571 printf("0x%llx", c.instanceMethods);
1572 printf("\n");
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,
1578 classMethods),
1579 s->addr - info->database, c.classMethods,
1580 s->relocs, s->nrelocs, info, &n_value);
1581 if(n_value != 0){
1582 if(info->Vflag && sym_name != NULL)
1583 printf("%s", sym_name);
1584 else
1585 printf("0x%llx", n_value);
1586 if(c.classMethods != 0)
1587 printf(" + 0x%llx", c.classMethods);
1589 else
1590 printf("0x%llx", c.classMethods);
1591 printf("\n");
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,
1597 protocols),
1598 s->addr - info->database, c.protocols,
1599 s->relocs, s->nrelocs, info, &n_value);
1600 if(n_value != 0){
1601 if(info->Vflag && sym_name != NULL)
1602 printf("%s", sym_name);
1603 else
1604 printf("0x%llx", n_value);
1605 if(c.protocols != 0)
1606 printf(" + 0x%llx", c.protocols);
1608 else
1609 printf("0x%llx", c.protocols);
1610 printf("\n");
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);
1619 if(n_value != 0){
1620 if(info->Vflag && sym_name != NULL)
1621 printf("%s", sym_name);
1622 else
1623 printf("0x%llx", n_value);
1624 if(c.instanceProperties != 0)
1625 printf(" + 0x%llx", c.instanceProperties);
1627 else
1628 printf("0x%llx", c.instanceProperties);
1629 printf("\n");
1630 if(c.instanceProperties + n_value)
1631 print_objc_property_list(c.instanceProperties + n_value, info);
1634 static
1635 void
1636 print_message_refs(
1637 struct section_info_64 *s,
1638 struct info *info)
1640 uint32_t i, left, offset;
1641 uint64_t p, n_value;
1642 struct message_ref mr;
1643 const char *name, *sym_name;
1644 void *r;
1646 if(s == NULL)
1647 return;
1649 printf("Contents of (%.16s,%.16s) section\n", s->segname, s->sectname);
1650 offset = 0;
1651 for(i = 0; i < s->size; i += sizeof(struct message_ref)){
1652 p = s->addr + i;
1653 r = get_pointer_64(p, &offset, &left, &s,
1654 info->sections, info->nsections);
1655 if(r == NULL)
1656 return;
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");
1662 else
1663 memcpy(&mr, r, sizeof(struct message_ref));
1664 if(info->swapped)
1665 swap_message_ref(&mr, info->host_byte_sex);
1667 printf(" imp ");
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);
1671 if(n_value != 0){
1672 printf("0x%llx", n_value);
1673 if(mr.imp != 0)
1674 printf(" + 0x%llx", mr.imp);
1676 else
1677 printf("0x%llx", mr.imp);
1678 if(name != NULL)
1679 printf(" %s", name);
1680 printf("\n");
1682 printf(" sel ");
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);
1686 if(n_value != 0){
1687 if(info->Vflag && sym_name != NULL)
1688 printf("%s", sym_name);
1689 else
1690 printf("0x%llx", n_value);
1691 if(mr.sel != 0)
1692 printf(" + 0x%llx", mr.sel);
1694 else
1695 printf("0x%llx", mr.sel);
1696 name = get_pointer_64(mr.sel + n_value, NULL, &left, NULL,
1697 info->sections, info->nsections);
1698 if(name != NULL)
1699 printf(" %.*s", (int)left, name);
1700 printf("\n");
1702 offset += sizeof(struct message_ref);
1706 static
1707 void
1708 print_image_info(
1709 struct section_info_64 *s,
1710 struct info *info)
1712 uint32_t left, offset;
1713 uint64_t p;
1714 struct objc_image_info o;
1715 void *r;
1717 if(s == NULL)
1718 return;
1720 printf("Contents of (%.16s,%.16s) section\n", s->segname, s->sectname);
1721 p = s->addr;
1722 r = get_pointer_64(p, &offset, &left, &s,
1723 info->sections, info->nsections);
1724 if(r == NULL)
1725 return;
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");
1731 else
1732 memcpy(&o, r, sizeof(struct objc_image_info));
1733 if(info->swapped)
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");
1741 printf("\n");
1744 void
1745 print_objc_string_object_section_64(
1746 char *sectname,
1747 struct load_command *load_commands,
1748 uint32_t ncmds,
1749 uint32_t sizeofcmds,
1750 enum byte_sex object_byte_sex,
1751 char *object_addr,
1752 uint32_t object_size,
1753 cpu_type_t cputype,
1754 struct nlist_64 *symbols64,
1755 uint32_t nsymbols,
1756 char *strings,
1757 const uint32_t strings_size,
1758 struct symbol *sorted_symbols,
1759 uint32_t nsorted_symbols,
1760 enum bool verbose)
1762 struct info info;
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;
1767 char *p;
1768 const char *name;
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);
1785 if(o == NULL)
1786 return;
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;
1795 s++){
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",
1806 sectname);
1807 printf("String Object 0x%llx\n",
1808 string_objects_addr + ((char *)s - (char *)string_objects));
1810 if(info.swapped)
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);
1816 if(name != NULL)
1817 printf(" %s\n", name);
1818 else
1819 printf("\n");
1820 printf(" characters 0x%llx", string_object.characters);
1821 if(verbose){
1822 p = get_pointer_64(string_object.characters, NULL, &left,
1823 NULL, info.sections, info.nsections);
1824 if(p != NULL)
1825 printf(" %.*s\n", (int)left, p);
1827 else
1828 printf("\n");
1829 printf(" _length %u\n", string_object._length);
1830 printf(" _pad %u\n", string_object._pad);
1834 static
1835 void
1836 get_sections_64(
1837 struct load_command *load_commands,
1838 uint32_t ncmds,
1839 uint32_t sizeofcmds,
1840 enum byte_sex object_byte_sex,
1841 char *object_addr,
1842 uint32_t object_size,
1843 struct section_info_64 **sections,
1844 uint32_t *nsections,
1845 uint64_t *database)
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;
1852 char *p;
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;
1861 *sections = NULL;
1862 *nsections = 0;
1863 database_set = FALSE;
1864 *database = 0;
1865 zerobased = FALSE;
1866 encrypt_found = FALSE;
1867 encrypt64_found = FALSE;
1869 lc = load_commands;
1870 for(i = 0 ; i < ncmds; i++){
1871 memcpy((char *)&lcmd, (char *)lc, sizeof(struct load_command));
1872 if(swapped)
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 "
1880 "commands\n", i);
1881 left = sizeofcmds - ((char *)lc - (char *)load_commands);
1883 switch(lcmd.cmd){
1884 case LC_SEGMENT_64:
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);
1889 if(swapped)
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 &&
1897 sg64.vmaddr == 0)
1898 zerobased = TRUE;
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);
1911 if(swapped)
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,
1917 s64.segname, 16);
1918 memcpy((*sections)[*nsections].sectname,
1919 s64.sectname, 16);
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;
1936 else
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,
1941 s64.sectname);
1942 (*sections)[*nsections].nrelocs = 0;
1944 else{
1945 (*sections)[*nsections].relocs =
1946 (struct relocation_info *)(object_addr +
1947 s64.reloff);
1948 if(s64.reloff +
1949 s64.nreloc * sizeof(struct relocation_info) >
1950 object_size){
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);
1958 else
1959 (*sections)[*nsections].nrelocs = s64.nreloc;
1960 if(swapped)
1961 swap_relocation_info(
1962 (*sections)[*nsections].relocs,
1963 (*sections)[*nsections].nrelocs,
1964 host_byte_sex);
1966 if(sg64.flags & SG_PROTECTED_VERSION_1)
1967 (*sections)[*nsections].protected = TRUE;
1968 else
1969 (*sections)[*nsections].protected = FALSE;
1970 if((s64.flags & SECTION_TYPE) == S_CSTRING_LITERALS)
1971 (*sections)[*nsections].cstring = TRUE;
1972 else
1973 (*sections)[*nsections].cstring = FALSE;
1974 (*nsections)++;
1976 if(p + sizeof(struct section_64) >
1977 (char *)load_commands + sizeofcmds)
1978 break;
1979 p += size;
1981 break;
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);
1988 if(swapped)
1989 swap_encryption_command(&encrypt, host_byte_sex);
1990 encrypt_found = TRUE;
1991 break;
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);
1998 if(swapped)
1999 swap_encryption_command_64(&encrypt64, host_byte_sex);
2000 encrypt64_found = TRUE;
2001 break;
2003 if(lcmd.cmdsize == 0){
2004 printf("load command %u size zero (can't advance to other "
2005 "load commands)\n", i);
2006 break;
2008 lc = (struct load_command *)((char *)lc + lcmd.cmdsize);
2009 if((char *)lc > (char *)load_commands + sizeofcmds)
2010 break;
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 <
2021 encrypt.cryptoff){
2022 /* section ends before encryption area */ ;
2024 else{
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 */ ;
2042 else{
2043 /* section has part in the encrypted area */
2044 (*sections)[i].protected = TRUE;
2051 static
2052 struct section_info_64 *
2053 get_section_64(
2054 struct section_info_64 *sections,
2055 uint32_t nsections,
2056 char *segname,
2057 char *sectname)
2059 uint32_t i;
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);
2067 return(NULL);
2070 static
2071 void
2072 get_cstring_section_64(
2073 struct load_command *load_commands,
2074 uint32_t ncmds,
2075 uint32_t sizeofcmds,
2076 enum byte_sex object_byte_sex,
2077 char *object_addr,
2078 uint32_t object_size,
2079 struct section_info_64 *cstring_section)
2081 enum byte_sex host_byte_sex;
2082 enum bool swapped;
2084 uint32_t i, j, left, size;
2085 struct load_command lcmd, *lc;
2086 char *p;
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));
2095 lc = load_commands;
2096 for(i = 0 ; i < ncmds; i++){
2097 memcpy((char *)&lcmd, (char *)lc, sizeof(struct load_command));
2098 if(swapped)
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 "
2106 "commands\n", i);
2107 left = sizeofcmds - ((char *)lc - (char *)load_commands);
2109 switch(lcmd.cmd){
2110 case LC_SEGMENT_64:
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);
2115 if(swapped)
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);
2130 if(swapped)
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;
2148 else
2149 cstring_section->size = s64.size;
2150 if(sg64.flags & SG_PROTECTED_VERSION_1)
2151 cstring_section->protected = TRUE;
2152 else
2153 cstring_section->protected = FALSE;
2154 cstring_section->cstring = TRUE;
2155 return;
2158 if(p + sizeof(struct section) >
2159 (char *)load_commands + sizeofcmds)
2160 break;
2161 p += size;
2163 break;
2165 if(lcmd.cmdsize == 0){
2166 printf("load command %u size zero (can't advance to other "
2167 "load commands)\n", i);
2168 break;
2170 lc = (struct load_command *)((char *)lc + lcmd.cmdsize);
2171 if((char *)lc > (char *)load_commands + sizeofcmds)
2172 break;
2176 static
2177 void *
2178 get_pointer_64(
2179 uint64_t p,
2180 uint32_t *offset,
2181 uint32_t *left,
2182 struct section_info_64 **s,
2183 struct section_info_64 *sections,
2184 uint32_t nsections)
2186 void *r;
2187 uint64_t addr;
2188 uint32_t i;
2190 addr = p;
2191 for(i = 0; i < nsections; i++){
2192 if(addr >= sections[i].addr &&
2193 addr < sections[i].addr + sections[i].size){
2194 if(s != NULL)
2195 *s = sections + i;
2196 if(offset != NULL)
2197 *offset = addr - sections[i].addr;
2198 if(left != NULL)
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";
2202 else
2203 r = sections[i].contents + (addr - sections[i].addr);
2204 return(r);
2207 if(s != NULL)
2208 *s = NULL;
2209 if(offset != NULL)
2210 *offset = 0;
2211 if(left != NULL)
2212 *left = 0;
2213 return(NULL);
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.
2220 static
2221 const char *
2222 get_symbol_64(
2223 uint32_t sect_offset,
2224 uint64_t database_offset,
2225 uint64_t value,
2226 struct relocation_info *relocs,
2227 uint32_t nrelocs,
2228 struct info *info,
2229 uint64_t *n_value)
2231 uint32_t i;
2232 unsigned int r_symbolnum;
2233 uint32_t n_strx;
2235 if(n_value != NULL)
2236 *n_value = 0;
2238 if(info->verbose == FALSE)
2239 return(NULL);
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)
2246 break;
2247 n_strx = info->symbols64[r_symbolnum].n_un.n_strx;
2248 if(n_strx <= 0 || n_strx >= info->strings_size)
2249 break;
2250 if(n_value != NULL)
2251 *n_value = info->symbols64[r_symbolnum].n_value;
2252 return(info->strings + n_strx);
2254 break;
2256 if(reloc_has_pair(info->cputype, relocs[i].r_type) == TRUE)
2257 i++;
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)
2265 break;
2266 n_strx = info->symbols64[r_symbolnum].n_un.n_strx;
2267 if(n_strx <= 0 || n_strx >= info->strings_size)
2268 break;
2269 if(n_value != NULL)
2270 *n_value = info->symbols64[r_symbolnum].n_value;
2271 return(info->strings + n_strx);
2273 break;
2275 if(reloc_has_pair(info->cputype, info->ext_relocs[i].r_type) ==TRUE)
2276 i++;
2278 if(value == 0)
2279 return(NULL);
2280 return(guess_symbol(value, info->sorted_symbols, info->nsorted_symbols,
2281 info->verbose));