1/*
2 * Copyright © 2009 Apple Inc. All rights reserved.
3 *
4 * @APPLE_LICENSE_HEADER_START@
5 *
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions are met:
8 *
9 * 1.  Redistributions of source code must retain the above copyright notice,
10 * this list of conditions and the following disclaimer.
11 * 2.  Redistributions in binary form must reproduce the above copyright notice,
12 * this list of conditions and the following disclaimer in the documentation
13 * and/or other materials provided with the distribution.
14 * 3.  Neither the name of Apple Inc. ("Apple") nor the names of its
15 * contributors may be used to endorse or promote products derived from this
16 * software without specific prior written permission.
17 *
18 * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY
19 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
20 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
21 * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY
22 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
23 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
24 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
25 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
26 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
27 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
28 *
29 * @APPLE_LICENSE_HEADER_END@
30 */
31#include "stdio.h"
32#include "stddef.h"
33#include "string.h"
34#include "mach-o/loader.h"
35#include "stuff/allocate.h"
36#include "stuff/bytesex.h"
37#include "stuff/symbol.h"
38#include "stuff/reloc.h"
39#include "ofile_print.h"
40
41extern char *oname;
42
43/*
44 * Here we need structures that have the same memory layout and size as the
45 * 64-bit Objective-C meta data structures that can be used in this 32-bit
46 * program.
47 *
48 * The real structure definitions come from the objc4 project in the private
49 * header file runtime/objc-runtime-new.h in that project.
50 */
51
52struct class_t {
53    uint64_t isa;		/* class_t * (64-bit pointer) */
54    uint64_t superclass;	/* class_t * (64-bit pointer) */
55    uint64_t cache;		/* Cache (64-bit pointer) */
56    uint64_t vtable;		/* IMP * (64-bit pointer) */
57    uint64_t data;		/* class_ro_t * (64-bit pointer) */
58};
59
60static
61void
62swap_class_t(
63struct class_t *c,
64enum byte_sex target_byte_sex)
65{
66	c->isa = SWAP_LONG_LONG(c->isa);
67	c->superclass = SWAP_LONG_LONG(c->superclass);
68	c->cache = SWAP_LONG_LONG(c->cache);
69	c->vtable = SWAP_LONG_LONG(c->vtable);
70	c->data = SWAP_LONG_LONG(c->data);
71}
72
73struct class_ro_t {
74    uint32_t flags;
75    uint32_t instanceStart;
76    uint32_t instanceSize;
77    uint32_t reserved;
78    uint64_t ivarLayout;	/* const uint8_t * (64-bit pointer) */
79    uint64_t name; 		/* const char * (64-bit pointer) */
80    uint64_t baseMethods; 	/* const method_list_t * (64-bit pointer) */
81    uint64_t baseProtocols; 	/* const protocol_list_t * (64-bit pointer) */
82    uint64_t ivars; 		/* const ivar_list_t * (64-bit pointer) */
83    uint64_t weakIvarLayout; 	/* const uint8_t * (64-bit pointer) */
84    uint64_t baseProperties; 	/* const struct objc_property_list *
85							(64-bit pointer) */
86};
87
88/* Values for class_ro_t->flags */
89#define RO_META               (1<<0)
90#define RO_ROOT               (1<<1)
91#define RO_HAS_CXX_STRUCTORS  (1<<2)
92
93
94static
95void
96swap_class_ro_t(
97struct class_ro_t *cro,
98enum byte_sex target_byte_sex)
99{
100	cro->flags = SWAP_INT(cro->flags);
101	cro->instanceStart = SWAP_INT(cro->instanceStart);
102	cro->instanceSize = SWAP_INT(cro->instanceSize);
103	cro->reserved = SWAP_INT(cro->reserved);
104	cro->ivarLayout = SWAP_LONG_LONG(cro->ivarLayout);
105	cro->name = SWAP_LONG_LONG(cro->name);
106	cro->baseMethods = SWAP_LONG_LONG(cro->baseMethods);
107	cro->baseProtocols = SWAP_LONG_LONG(cro->baseProtocols);
108	cro->ivars = SWAP_LONG_LONG(cro->ivars);
109	cro->weakIvarLayout = SWAP_LONG_LONG(cro->weakIvarLayout);
110	cro->baseProperties = SWAP_LONG_LONG(cro->baseProperties);
111}
112
113struct method_list_t {
114    uint32_t entsize;
115    uint32_t count;
116    /* struct method_t first;  These structures follow inline */
117};
118
119static
120void
121swap_method_list_t(
122struct method_list_t *ml,
123enum byte_sex target_byte_sex)
124{
125	ml->entsize = SWAP_INT(ml->entsize);
126	ml->count = SWAP_INT(ml->count);
127}
128
129struct method_t {
130    uint64_t name;	/* SEL (64-bit pointer) */
131    uint64_t types;	/* const char * (64-bit pointer) */
132    uint64_t imp;	/* IMP (64-bit pointer) */
133};
134
135static
136void
137swap_method_t(
138struct method_t *m,
139enum byte_sex target_byte_sex)
140{
141	m->name = SWAP_LONG_LONG(m->name);
142	m->types = SWAP_LONG_LONG(m->types);
143	m->imp = SWAP_LONG_LONG(m->imp);
144}
145
146struct ivar_list_t {
147    uint32_t entsize;
148    uint32_t count;
149    /* struct ivar_t first;  These structures follow inline */
150};
151
152static
153void
154swap_ivar_list_t(
155struct ivar_list_t *il,
156enum byte_sex target_byte_sex)
157{
158	il->entsize = SWAP_INT(il->entsize);
159	il->count = SWAP_INT(il->count);
160}
161
162struct ivar_t {
163    uint64_t offset;	/* uintptr_t * (64-bit pointer) */
164    uint64_t name;	/* const char * (64-bit pointer) */
165    uint64_t type;	/* const char * (64-bit pointer) */
166    uint32_t alignment;
167    uint32_t size;
168};
169
170static
171void
172swap_ivar_t(
173struct ivar_t *i,
174enum byte_sex target_byte_sex)
175{
176	i->offset = SWAP_LONG_LONG(i->offset);
177	i->name = SWAP_LONG_LONG(i->name);
178	i->type = SWAP_LONG_LONG(i->type);
179	i->alignment = SWAP_INT(i->alignment);
180	i->size = SWAP_INT(i->size);
181}
182
183struct protocol_list_t {
184    uint64_t count;	/* uintptr_t (a 64-bit value) */
185    /* struct protocol_t * list[0];  These pointers follow inline */
186};
187
188static
189void
190swap_protocol_list_t(
191struct protocol_list_t *pl,
192enum byte_sex target_byte_sex)
193{
194	pl->count = SWAP_LONG_LONG(pl->count);
195}
196
197struct protocol_t {
198    uint64_t isa;			/* id * (64-bit pointer) */
199    uint64_t name;			/* const char * (64-bit pointer) */
200    uint64_t protocols;			/* struct protocol_list_t *
201							(64-bit pointer) */
202    uint64_t instanceMethods;		/* method_list_t * (64-bit pointer) */
203    uint64_t classMethods;		/* method_list_t * (64-bit pointer) */
204    uint64_t optionalInstanceMethods;	/* method_list_t * (64-bit pointer) */
205    uint64_t optionalClassMethods;	/* method_list_t * (64-bit pointer) */
206    uint64_t instanceProperties;	/* struct objc_property_list *
207							   (64-bit pointer) */
208};
209
210static
211void
212swap_protocol_t(
213struct protocol_t *p,
214enum byte_sex target_byte_sex)
215{
216	p->isa = SWAP_LONG_LONG(p->isa);
217	p->name = SWAP_LONG_LONG(p->name);
218	p->protocols = SWAP_LONG_LONG(p->protocols);
219	p->instanceMethods = SWAP_LONG_LONG(p->instanceMethods);
220	p->classMethods = SWAP_LONG_LONG(p->classMethods);
221	p->optionalInstanceMethods = SWAP_LONG_LONG(p->optionalInstanceMethods);
222	p->optionalClassMethods = SWAP_LONG_LONG(p->optionalClassMethods);
223	p->instanceProperties = SWAP_LONG_LONG(p->instanceProperties);
224}
225
226struct objc_property_list {
227    uint32_t entsize;
228    uint32_t count;
229    /* struct objc_property first;  These structures follow inline */
230};
231
232static
233void
234swap_objc_property_list(
235struct objc_property_list *pl,
236enum byte_sex target_byte_sex)
237{
238	pl->entsize = SWAP_INT(pl->entsize);
239	pl->count = SWAP_INT(pl->count);
240}
241
242struct objc_property {
243    uint64_t name;		/* const char * (64-bit pointer) */
244    uint64_t attributes;	/* const char * (64-bit pointer) */
245};
246
247static
248void
249swap_objc_property(
250struct objc_property *op,
251enum byte_sex target_byte_sex)
252{
253	op->name = SWAP_LONG_LONG(op->name);
254	op->attributes = SWAP_LONG_LONG(op->attributes);
255}
256
257struct category_t {
258    uint64_t name; 		/* const char * (64-bit pointer) */
259    uint64_t cls;		/* struct class_t * (64-bit pointer) */
260    uint64_t instanceMethods;	/* struct method_list_t * (64-bit pointer) */
261    uint64_t classMethods;	/* struct method_list_t * (64-bit pointer) */
262    uint64_t protocols;		/* struct protocol_list_t * (64-bit pointer) */
263    uint64_t instanceProperties; /* struct objc_property_list *
264				    (64-bit pointer) */
265};
266
267static
268void
269swap_category_t(
270struct category_t *c,
271enum byte_sex target_byte_sex)
272{
273	c->name = SWAP_LONG_LONG(c->name);
274	c->cls = SWAP_LONG_LONG(c->cls);
275	c->instanceMethods = SWAP_LONG_LONG(c->instanceMethods);
276	c->classMethods = SWAP_LONG_LONG(c->classMethods);
277	c->protocols = SWAP_LONG_LONG(c->protocols);
278	c->instanceProperties = SWAP_LONG_LONG(c->instanceProperties);
279}
280
281struct message_ref {
282    uint64_t imp;	/* IMP (64-bit pointer) */
283    uint64_t sel;	/* SEL (64-bit pointer) */
284};
285
286static
287void
288swap_message_ref(
289struct message_ref *mr,
290enum byte_sex target_byte_sex)
291{
292	mr->imp = SWAP_LONG_LONG(mr->imp);
293	mr->sel = SWAP_LONG_LONG(mr->sel);
294}
295
296struct objc_image_info {
297    uint32_t version;
298    uint32_t flags;
299};
300/* masks for objc_image_info.flags */
301#define OBJC_IMAGE_IS_REPLACEMENT (1<<0)
302#define OBJC_IMAGE_SUPPORTS_GC (1<<1)
303
304
305static
306void
307swap_objc_image_info(
308struct objc_image_info *o,
309enum byte_sex target_byte_sex)
310{
311	o->version = SWAP_INT(o->version);
312	o->flags = SWAP_INT(o->flags);
313}
314
315struct objc_string_object_64 {
316    uint64_t isa;		/* class_t * (64-bit pointer) */
317    uint64_t characters;	/* char * (64-bit pointer) */
318    uint32_t _length;		/* number of non-NULL characters in above */
319    uint32_t _pad;		/* unused padding, compiler uses .space 4 */
320};
321
322static
323void
324swap_string_object_64(
325struct objc_string_object_64 *string_object,
326enum byte_sex target_byte_sex)
327{
328	string_object->isa = SWAP_LONG_LONG(string_object->isa);
329	string_object->characters = SWAP_LONG_LONG(string_object->characters);
330	string_object->_length = SWAP_INT(string_object->_length);
331	string_object->_pad = SWAP_INT(string_object->_pad);
332}
333
334struct info {
335    enum bool swapped;
336    enum byte_sex host_byte_sex;
337    struct section_info_64 *sections;
338    uint32_t nsections;
339    cpu_type_t cputype;
340    struct nlist_64 *symbols64;
341    uint32_t nsymbols;
342    char *strings;
343    uint32_t strings_size;
344    struct symbol *sorted_symbols;
345    uint32_t nsorted_symbols;
346    uint64_t database;
347    struct relocation_info *ext_relocs;
348    uint32_t next_relocs;
349    struct relocation_info *loc_relocs;
350    uint32_t nloc_relocs;
351    enum bool verbose;
352    enum bool Vflag;
353};
354
355struct section_info_64 {
356    char segname[16];
357    char sectname[16];
358    char *contents;
359    uint64_t addr;
360    uint64_t size;
361    uint32_t offset;
362    struct relocation_info *relocs;
363    uint32_t nrelocs;
364    enum bool cstring;
365    enum bool protected;
366    enum bool zerofill;
367};
368
369static void walk_pointer_list(
370    char *listname,
371    struct section_info_64 *s,
372    struct info *info,
373    void (*func)(uint64_t, struct info *));
374
375static void print_class_t(
376    uint64_t p,
377    struct info *info);
378
379static void print_class_ro_t(
380    uint64_t p,
381    struct info *info,
382    enum bool *is_meta_class);
383
384static void print_layout_map(
385    uint64_t p,
386    struct info *info);
387
388static void print_method_list_t(
389    uint64_t p,
390    struct info *info,
391    char *indent);
392
393static void print_ivar_list_t(
394    uint64_t p,
395    struct info *info);
396
397static void print_protocol_list_t(
398    uint64_t p,
399    struct info *info);
400
401static void print_objc_property_list(
402    uint64_t p,
403    struct info *info);
404
405static void print_category_t(
406    uint64_t p,
407    struct info *info);
408
409static void print_message_refs(
410    struct section_info_64 *s,
411    struct info *info);
412
413static void print_image_info(
414    struct section_info_64 *s,
415    struct info *info);
416
417static void get_sections_64(
418    struct load_command *load_commands,
419    uint32_t ncmds,
420    uint32_t sizeofcmds,
421    enum byte_sex object_byte_sex,
422    char *object_addr,
423    uint32_t object_size,
424    struct section_info_64 **sections,
425    uint32_t *nsections,
426    uint64_t *database);
427
428static struct section_info_64 *get_section_64(
429    struct section_info_64 *sections,
430    uint32_t nsections,
431    char *segname,
432    char *sectname);
433
434static void get_cstring_section_64(
435    struct load_command *load_commands,
436    uint32_t ncmds,
437    uint32_t sizeofcmds,
438    enum byte_sex object_byte_sex,
439    char *object_addr,
440    uint32_t object_size,
441    struct section_info_64 *cstring_section_ptr);
442
443static void *get_pointer_64(
444    uint64_t p,
445    uint32_t *offset,
446    uint32_t *left,
447    struct section_info_64 **s,
448    struct section_info_64 *sections,
449    uint32_t nsections);
450
451static const char *get_symbol_64(
452    uint32_t sect_offset,
453    uint64_t database_offset,
454    uint64_t value,
455    struct relocation_info *relocs,
456    uint32_t nrelocs,
457    struct info *info,
458    uint64_t *n_value);
459
460/*
461 * Print the objc2 meta data in 64-bit Mach-O files.
462 */
463void
464print_objc2_64bit(
465cpu_type_t cputype,
466struct load_command *load_commands,
467uint32_t ncmds,
468uint32_t sizeofcmds,
469enum byte_sex object_byte_sex,
470char *object_addr,
471uint32_t object_size,
472struct nlist_64 *symbols64,
473uint32_t nsymbols,
474char *strings,
475uint32_t strings_size,
476struct symbol *sorted_symbols,
477uint32_t nsorted_symbols,
478struct relocation_info *ext_relocs,
479uint32_t next_relocs,
480struct relocation_info *loc_relocs,
481uint32_t nloc_relocs,
482enum bool verbose,
483enum bool Vflag)
484{
485    struct section_info_64 *s;
486    struct info info;
487
488	info.host_byte_sex = get_host_byte_sex();
489	info.swapped = info.host_byte_sex != object_byte_sex;
490	info.cputype = cputype;
491	info.symbols64 = symbols64;
492	info.nsymbols = nsymbols;
493	info.strings = strings;
494	info.strings_size = strings_size;
495	info.sorted_symbols = sorted_symbols;
496	info.nsorted_symbols = nsorted_symbols;
497	info.ext_relocs = ext_relocs;
498	info.next_relocs = next_relocs;
499	info.loc_relocs = loc_relocs;
500	info.nloc_relocs = nloc_relocs;
501	info.verbose = verbose;
502	info.Vflag = Vflag;
503	get_sections_64(load_commands, ncmds, sizeofcmds, object_byte_sex,
504			object_addr, object_size, &info.sections,
505			&info.nsections, &info.database);
506
507	s = get_section_64(info.sections, info.nsections,
508				"__OBJC2", "__class_list");
509	if(s == NULL)
510	    s = get_section_64(info.sections, info.nsections,
511				"__DATA", "__objc_classlist");
512	walk_pointer_list("class", s, &info, print_class_t);
513
514	s = get_section_64(info.sections, info.nsections,
515				"__OBJC2", "__class_refs");
516	if(s == NULL)
517	    s = get_section_64(info.sections, info.nsections,
518				"__DATA", "__objc_classrefs");
519	walk_pointer_list("class refs", s, &info, NULL);
520
521	s = get_section_64(info.sections, info.nsections,
522				"__OBJC2", "__super_refs");
523	if(s == NULL)
524	    s = get_section_64(info.sections, info.nsections,
525				"__DATA", "__objc_superrefs");
526	walk_pointer_list("super refs", s, &info, NULL);
527
528	s = get_section_64(info.sections, info.nsections,
529				"__OBJC2", "__category_list");
530	if(s == NULL)
531	    s = get_section_64(info.sections, info.nsections,
532				"__DATA", "__objc_catlist");
533	walk_pointer_list("category", s, &info, print_category_t);
534
535	s = get_section_64(info.sections, info.nsections,
536				"__OBJC2", "__protocol_list");
537	if(s == NULL)
538	    s = get_section_64(info.sections, info.nsections,
539				"__DATA", "__objc_protolist");
540	walk_pointer_list("protocol", s, &info, NULL);
541
542	s = get_section_64(info.sections, info.nsections,
543				"__OBJC2", "__message_refs");
544	if(s == NULL)
545	    s = get_section_64(info.sections, info.nsections,
546				"__DATA", "__objc_msgrefs");
547	print_message_refs(s, &info);
548
549	s = get_section_64(info.sections, info.nsections,
550				"__OBJC", "__image_info");
551	if(s == NULL)
552	    s = get_section_64(info.sections, info.nsections,
553				"__DATA", "__objc_imageinfo");
554	print_image_info(s, &info);
555}
556
557static
558void
559walk_pointer_list(
560char *listname,
561struct section_info_64 *s,
562struct info *info,
563void (*func)(uint64_t, struct info *))
564{
565    uint32_t i, size, left;
566    uint64_t p, n_value;
567    const char *name;
568
569	if(s == NULL)
570	    return;
571
572	printf("Contents of (%.16s,%.16s) section\n", s->segname, s->sectname);
573	for(i = 0; i < s->size; i += sizeof(uint64_t)){
574
575	    memset(&p, '\0', sizeof(uint64_t));
576	    left = s->size - i;
577	    size = left < sizeof(uint64_t) ?
578		   left : sizeof(uint64_t);
579	    memcpy(&p, s->contents + i, size);
580
581	    if(i + sizeof(uint64_t) > s->size)
582		printf("%s list pointer extends past end of (%s,%s) "
583		       "section\n", listname, s->segname, s->sectname);
584	    printf("%016llx ", s->addr + i);
585
586	    if(info->swapped)
587		p = SWAP_LONG_LONG(p);
588
589	    name = get_symbol_64(i, s->addr - info->database, p,
590			         s->relocs, s->nrelocs, info, &n_value);
591	    if(n_value != 0){
592		printf("0x%llx", n_value);
593		if(p != 0)
594		    printf(" + 0x%llx", p);
595	    }
596	    else
597		printf("0x%llx", p);
598	    if(name != NULL)
599		printf(" %s", name);
600	    printf("\n");
601
602	    p += n_value;
603	    if(func != NULL)
604		func(p, info);
605	}
606}
607
608static
609void
610print_class_t(
611uint64_t p,
612struct info *info)
613{
614    struct class_t c;
615    void *r;
616    uint32_t offset, left;
617    struct section_info_64 *s;
618    const char *name;
619    enum bool is_meta_class;
620    uint64_t n_value, isa_n_value;
621
622	is_meta_class = FALSE;
623	r = get_pointer_64(p, &offset, &left, &s,
624			   info->sections, info->nsections);
625	if(r == NULL)
626	    return;
627	memset(&c, '\0', sizeof(struct class_t));
628	if(left < sizeof(struct class_t)){
629	    memcpy(&c, r, left);
630	    printf("   (class_t entends past the end of the section)\n");
631	}
632	else
633	    memcpy(&c, r, sizeof(struct class_t));
634	if(info->swapped)
635	    swap_class_t(&c, info->host_byte_sex);
636	printf("           isa 0x%llx", c.isa);
637	name = get_symbol_64(offset + offsetof(struct class_t, isa),
638			     s->addr - info->database, c.isa, s->relocs,
639			     s->nrelocs, info, &isa_n_value);
640	if(name != NULL)
641	    printf(" %s\n", name);
642	else
643	    printf("\n");
644	printf("    superclass 0x%llx", c.superclass);
645	name = get_symbol_64(offset + offsetof(struct class_t, superclass),
646			     s->addr - info->database, c.superclass, s->relocs,
647			     s->nrelocs, info, NULL);
648	if(name != NULL)
649	    printf(" %s\n", name);
650	else
651	    printf("\n");
652	printf("         cache 0x%llx", c.cache);
653	name = get_symbol_64(offset + offsetof(struct class_t, cache),
654			     s->addr - info->database, c.cache, s->relocs,
655			     s->nrelocs, info, NULL);
656	if(name != NULL)
657	    printf(" %s\n", name);
658	else
659	    printf("\n");
660	printf("        vtable 0x%llx", c.vtable);
661	name = get_symbol_64(offset + offsetof(struct class_t, vtable),
662			     s->addr - info->database, c.vtable, s->relocs,
663			     s->nrelocs, info, NULL);
664	if(name != NULL)
665	    printf(" %s\n", name);
666	else
667	    printf("\n");
668
669	name = get_symbol_64(offset + offsetof(struct class_t, data),
670			     s->addr - info->database, c.data, s->relocs,
671			     s->nrelocs, info, &n_value);
672	printf("          data ");
673	if(n_value != 0){
674	    if(info->Vflag && name != NULL)
675		printf("%s", name);
676	    else
677		printf("0x%llx", n_value);
678	    if(c.data != 0)
679		printf(" + 0x%llx", c.data);
680	}
681	else{
682	    printf("0x%llx", c.data);
683	}
684	printf(" (struct class_ro_t *)");
685	printf("\n");
686	print_class_ro_t(c.data + n_value, info, &is_meta_class);
687
688	if(is_meta_class == FALSE){
689	    printf("Meta Class\n");
690	    print_class_t(c.isa + isa_n_value, info);
691	}
692}
693
694static
695void
696print_class_ro_t(
697uint64_t p,
698struct info *info,
699enum bool *is_meta_class)
700{
701    struct class_ro_t cro;
702    void *r;
703    uint32_t offset, left;
704    struct section_info_64 *s;
705    const char *name, *sym_name;
706    uint64_t n_value;
707
708	r = get_pointer_64(p, &offset, &left, &s, info->sections,
709			   info->nsections);
710	if(r == NULL)
711	    return;
712	memset(&cro, '\0', sizeof(struct class_ro_t));
713	if(left < sizeof(struct class_ro_t)){
714	    memcpy(&cro, r, left);
715	    printf("   (class_ro_t entends past the end of the section)\n");
716	}
717	else
718	    memcpy(&cro, r, sizeof(struct class_ro_t));
719	if(info->swapped)
720	    swap_class_ro_t(&cro, info->host_byte_sex);
721	printf("                    flags 0x%x", cro.flags);
722	if(cro.flags & RO_META)
723	    printf(" RO_META");
724	if(cro.flags & RO_ROOT)
725	    printf(" RO_ROOT");
726	if(cro.flags & RO_HAS_CXX_STRUCTORS)
727	    printf(" RO_HAS_CXX_STRUCTORS");
728	printf("\n");
729	printf("            instanceStart %u\n", cro.instanceStart);
730	printf("             instanceSize %u\n", cro.instanceSize);
731	printf("                 reserved 0x%x\n", cro.reserved);
732	printf("               ivarLayout 0x%llx\n", cro.ivarLayout);
733	print_layout_map(cro.ivarLayout, info);
734
735	printf("                     name ");
736	sym_name = get_symbol_64(offset + offsetof(struct class_ro_t, name),
737			         s->addr - info->database, cro.name, s->relocs,
738			         s->nrelocs, info, &n_value);
739	if(n_value != 0){
740	    if(info->Vflag && sym_name != NULL)
741		printf("%s", sym_name);
742	    else
743		printf("0x%llx", n_value);
744	    if(cro.name != 0)
745		printf(" + 0x%llx", cro.name);
746	}
747	else
748	    printf("0x%llx", cro.name);
749	name = get_pointer_64(cro.name + n_value, NULL, &left, NULL,
750			      info->sections, info->nsections);
751	if(name != NULL)
752	    printf(" %.*s", (int)left, name);
753	printf("\n");
754
755	printf("              baseMethods ");
756	sym_name = get_symbol_64(offset +
757				    offsetof(struct class_ro_t, baseMethods),
758			         s->addr - info->database, cro.baseMethods,
759				 s->relocs, s->nrelocs, info, &n_value);
760	if(n_value != 0){
761	    if(info->Vflag && sym_name != NULL)
762		printf("%s", sym_name);
763	    else
764		printf("0x%llx", n_value);
765	    if(cro.baseMethods != 0)
766		printf(" + 0x%llx", cro.baseMethods);
767	}
768	else
769	    printf("0x%llx", cro.baseMethods);
770	printf(" (struct method_list_t *)\n");
771	if(cro.baseMethods + n_value != 0)
772	    print_method_list_t(cro.baseMethods + n_value, info, "");
773
774	printf("            baseProtocols ");
775	sym_name = get_symbol_64(offset +
776				    offsetof(struct class_ro_t, baseProtocols),
777			         s->addr - info->database, cro.baseProtocols,
778				 s->relocs, s->nrelocs, info, &n_value);
779	if(n_value != 0){
780	    if(info->Vflag && sym_name != NULL)
781		printf("%s", sym_name);
782	    else
783		printf("0x%llx", n_value);
784	    if(cro.baseProtocols != 0)
785		printf(" + 0x%llx", cro.baseProtocols);
786	}
787	else
788	    printf("0x%llx", cro.baseProtocols);
789	printf("\n");
790	if(cro.baseProtocols + n_value != 0)
791	    print_protocol_list_t(cro.baseProtocols + n_value, info);
792
793	printf("                    ivars ");
794	sym_name = get_symbol_64(offset +
795				    offsetof(struct class_ro_t, ivars),
796			         s->addr - info->database, cro.ivars,
797				 s->relocs, s->nrelocs, info, &n_value);
798	if(n_value != 0){
799	    if(info->Vflag && sym_name != NULL)
800		printf("%s", sym_name);
801	    else
802		printf("0x%llx", n_value);
803	    if(cro.ivars != 0)
804		printf(" + 0x%llx", cro.ivars);
805	}
806	else
807	    printf("0x%llx", cro.ivars);
808	printf("\n");
809	if(cro.ivars + n_value != 0)
810	    print_ivar_list_t(cro.ivars + n_value, info);
811
812	printf("           weakIvarLayout ");
813	sym_name = get_symbol_64(offset +
814				    offsetof(struct class_ro_t, weakIvarLayout),
815			         s->addr - info->database, cro.weakIvarLayout,
816				 s->relocs, s->nrelocs, info, &n_value);
817	if(n_value != 0){
818	    if(info->Vflag && sym_name != NULL)
819		printf("%s", sym_name);
820	    else
821		printf("0x%llx", n_value);
822	    if(cro.weakIvarLayout != 0)
823		printf(" + 0x%llx", cro.weakIvarLayout);
824	}
825	else
826	    printf("0x%llx", cro.weakIvarLayout);
827	printf("\n");
828	print_layout_map(cro.weakIvarLayout + n_value, info);
829
830	printf("           baseProperties ");
831	sym_name = get_symbol_64(offset +
832				    offsetof(struct class_ro_t, baseProperties),
833			         s->addr - info->database, cro.baseProperties,
834				 s->relocs, s->nrelocs, info, &n_value);
835	if(n_value != 0){
836	    if(info->Vflag && sym_name != NULL)
837		printf("%s", sym_name);
838	    else
839		printf("0x%llx", n_value);
840	    if(cro.baseProperties != 0)
841		printf(" + 0x%llx", cro.baseProperties);
842	}
843	else
844	    printf("0x%llx", cro.baseProperties);
845	printf("\n");
846	if(cro.baseProperties + n_value != 0)
847	    print_objc_property_list(cro.baseProperties + n_value, info);
848
849	if(is_meta_class)
850	    *is_meta_class = (cro.flags & RO_META) ? TRUE : FALSE;
851}
852
853static
854void
855print_layout_map(
856uint64_t p,
857struct info *info)
858{
859    uint32_t offset, left;
860    struct section_info_64 *s;
861    char *layout_map;
862
863	if(p == 0)
864	    return;
865	layout_map = get_pointer_64(p, &offset, &left, &s,
866				    info->sections, info->nsections);
867	if(layout_map != NULL){
868	    printf("                layout map: ");
869	    do{
870		printf("0x%02x ", (*layout_map) & 0xff);
871		left--;
872		layout_map++;
873	    }while(*layout_map != '\0' && left != 0);
874	    printf("\n");
875	}
876}
877
878static
879void
880print_method_list_t(
881uint64_t p,
882struct info *info,
883char *indent)
884{
885    struct method_list_t ml;
886    struct method_t m;
887    void *r;
888    uint32_t offset, left, i;
889    struct section_info_64 *s;
890    const char *name, *sym_name;
891    uint64_t n_value;
892
893	r = get_pointer_64(p, &offset, &left, &s, info->sections,
894			   info->nsections);
895	if(r == NULL)
896	    return;
897	memset(&ml, '\0', sizeof(struct method_list_t));
898	if(left < sizeof(struct method_list_t)){
899	    memcpy(&ml, r, left);
900	    printf("%s   (method_list_t entends past the end of the "
901		   "section)\n", indent);
902	}
903	else
904	    memcpy(&ml, r, sizeof(struct method_list_t));
905	if(info->swapped)
906	    swap_method_list_t(&ml, info->host_byte_sex);
907	printf("%s\t\t   entsize %u\n", indent, ml.entsize);
908	printf("%s\t\t     count %u\n", indent, ml.count);
909
910	p += sizeof(struct method_list_t);
911	offset += sizeof(struct method_list_t);
912	for(i = 0; i < ml.count; i++){
913	    r = get_pointer_64(p, &offset, &left, &s, info->sections,
914			       info->nsections);
915	    if(r == NULL)
916		return;
917	    memset(&m, '\0', sizeof(struct method_t));
918	    if(left < sizeof(struct method_t)){
919		memcpy(&ml, r, left);
920		printf("%s   (method_t entends past the end of the "
921		       "section)\n", indent);
922	    }
923	    else
924		memcpy(&m, r, sizeof(struct method_t));
925	    if(info->swapped)
926		swap_method_t(&m, info->host_byte_sex);
927
928	    printf("%s\t\t      name ", indent);
929	    sym_name = get_symbol_64(offset + offsetof(struct method_t, name),
930				     s->addr - info->database, m.name,
931				     s->relocs, s->nrelocs, info, &n_value);
932	    if(n_value != 0){
933		if(info->Vflag && sym_name != NULL)
934		    printf("%s", sym_name);
935		else
936		    printf("0x%llx", n_value);
937		if(m.name != 0)
938		    printf(" + 0x%llx", m.name);
939	    }
940	    else
941		printf("0x%llx", m.name);
942	    name = get_pointer_64(m.name + n_value, NULL, &left, NULL,
943				  info->sections, info->nsections);
944	    if(name != NULL)
945		printf(" %.*s", (int)left, name);
946	    printf("\n");
947
948	    printf("%s\t\t     types ", indent);
949	    sym_name = get_symbol_64(offset + offsetof(struct method_t, types),
950				     s->addr - info->database, m.types,
951				     s->relocs, s->nrelocs, info, &n_value);
952	    if(n_value != 0){
953		if(info->Vflag && sym_name != NULL)
954		    printf("%s", sym_name);
955		else
956		    printf("0x%llx", n_value);
957		if(m.name != 0)
958		    printf(" + 0x%llx", m.types);
959	    }
960	    else
961		printf("0x%llx", m.types);
962	    name = get_pointer_64(m.types + n_value, NULL, &left, NULL,
963				  info->sections, info->nsections);
964	    if(name != NULL)
965		printf(" %.*s", (int)left, name);
966	    printf("\n");
967
968	    printf("%s\t\t       imp ", indent);
969	    name = get_symbol_64(offset + offsetof(struct method_t, imp),
970				 s->addr - info->database, m.imp, s->relocs,
971				 s->nrelocs, info, &n_value);
972	    if(info->Vflag == FALSE || name == NULL){
973		if(n_value != 0){
974		    printf("0x%llx ", n_value);
975		    if(m.imp != 0)
976			printf("+ 0x%llx ", m.imp);
977		}
978		else
979		    printf("0x%llx ", m.imp);
980	    }
981	    if(name != NULL)
982		printf("%s", name);
983	    printf("\n");
984
985	    p += sizeof(struct method_t);
986	    offset += sizeof(struct method_t);
987	}
988}
989
990static
991void
992print_ivar_list_t(
993uint64_t p,
994struct info *info)
995{
996    struct ivar_list_t il;
997    struct ivar_t i;
998    void *r;
999    uint32_t offset, left, j;
1000    struct section_info_64 *s;
1001    const char *name, *sym_name;
1002    uint64_t *ivar_offset_p, ivar_offset, n_value;
1003
1004
1005	r = get_pointer_64(p, &offset, &left, &s, info->sections,
1006			   info->nsections);
1007	if(r == NULL)
1008	    return;
1009	memset(&il, '\0', sizeof(struct ivar_list_t));
1010	if(left < sizeof(struct ivar_list_t)){
1011	    memcpy(&il, r, left);
1012	    printf("   (ivar_list_t entends past the end of the section)\n");
1013	}
1014	else
1015	    memcpy(&il, r, sizeof(struct ivar_list_t));
1016	if(info->swapped)
1017	    swap_ivar_list_t(&il, info->host_byte_sex);
1018	printf("                    entsize %u\n", il.entsize);
1019	printf("                      count %u\n", il.count);
1020
1021	p += sizeof(struct ivar_list_t);
1022	offset += sizeof(struct ivar_list_t);
1023	for(j = 0; j < il.count; j++){
1024	    r = get_pointer_64(p, &offset, &left, &s, info->sections,
1025			       info->nsections);
1026	    if(r == NULL)
1027		return;
1028	    memset(&i, '\0', sizeof(struct ivar_t));
1029	    if(left < sizeof(struct ivar_t)){
1030		memcpy(&i, r, left);
1031		printf("   (ivar_t entends past the end of the section)\n");
1032	    }
1033	    else
1034		memcpy(&i, r, sizeof(struct ivar_t));
1035	    if(info->swapped)
1036		swap_ivar_t(&i, info->host_byte_sex);
1037
1038	    printf("\t\t\t   offset ");
1039	    sym_name = get_symbol_64(offset + offsetof(struct ivar_t, offset),
1040				     s->addr - info->database, i.offset,
1041				     s->relocs, s->nrelocs, info, &n_value);
1042	    if(n_value != 0){
1043		if(info->Vflag && sym_name != NULL)
1044		    printf("%s", sym_name);
1045		else
1046		    printf("0x%llx", n_value);
1047		if(i.offset != 0)
1048		    printf(" + 0x%llx", i.offset);
1049	    }
1050	    else
1051		printf("0x%llx", i.offset);
1052	    ivar_offset_p = get_pointer_64(i.offset + n_value, NULL, &left,
1053					   NULL,info->sections,info->nsections);
1054	    if(ivar_offset_p != NULL && left >= sizeof(*ivar_offset_p)){
1055		memcpy(&ivar_offset, ivar_offset_p, sizeof(ivar_offset));
1056		if(info->swapped)
1057		    ivar_offset = SWAP_LONG_LONG(ivar_offset);
1058		printf(" %llu\n", ivar_offset);
1059            }
1060	    else
1061		printf("\n");
1062
1063	    printf("\t\t\t     name ");
1064	    sym_name = get_symbol_64(offset + offsetof(struct ivar_t, name),
1065				     s->addr - info->database, i.name,
1066				     s->relocs, s->nrelocs, info, &n_value);
1067	    if(n_value != 0){
1068		if(info->Vflag && sym_name != NULL)
1069		    printf("%s", sym_name);
1070		else
1071		    printf("0x%llx", n_value);
1072		if(i.name != 0)
1073		    printf(" + 0x%llx", i.name);
1074	    }
1075	    else
1076		printf("0x%llx", i.name);
1077	    name = get_pointer_64(i.name + n_value, NULL, &left, NULL,
1078				  info->sections, info->nsections);
1079	    if(name != NULL)
1080		printf(" %.*s", (int)left, name);
1081	    printf("\n");
1082
1083	    printf("\t\t\t     type ");
1084	    sym_name = get_symbol_64(offset + offsetof(struct ivar_t, type),
1085				     s->addr - info->database, i.type,
1086				     s->relocs, s->nrelocs, info, &n_value);
1087	    name = get_pointer_64(i.type + n_value, NULL, &left, NULL,
1088				  info->sections, info->nsections);
1089	    if(n_value != 0){
1090		if(info->Vflag && sym_name != NULL)
1091		    printf("%s", sym_name);
1092		else
1093		    printf("0x%llx", n_value);
1094		if(i.type != 0)
1095		    printf(" + 0x%llx", i.type);
1096	    }
1097	    else
1098		printf("0x%llx", i.type);
1099	    if(name != NULL)
1100		printf(" %.*s", (int)left, name);
1101	    printf("\n");
1102
1103	    printf("\t\t\talignment %u\n", i.alignment);
1104	    printf("\t\t\t     size %u\n", i.size);
1105
1106	    p += sizeof(struct ivar_t);
1107	    offset += sizeof(struct ivar_t);
1108	}
1109}
1110
1111static
1112void
1113print_protocol_list_t(
1114uint64_t p,
1115struct info *info)
1116{
1117    struct protocol_list_t pl;
1118    uint64_t q, n_value;
1119    struct protocol_t pc;
1120    void *r;
1121    uint32_t offset, left, i;
1122    struct section_info_64 *s;
1123    const char *name, *sym_name;
1124
1125	r = get_pointer_64(p, &offset, &left, &s, info->sections,
1126			   info->nsections);
1127	if(r == NULL)
1128	    return;
1129	memset(&pl, '\0', sizeof(struct protocol_list_t));
1130	if(left < sizeof(struct protocol_list_t)){
1131	    memcpy(&pl, r, left);
1132	    printf("   (protocol_list_t entends past the end of the "
1133		   "section)\n");
1134	}
1135	else
1136	    memcpy(&pl, r, sizeof(struct protocol_list_t));
1137	if(info->swapped)
1138	    swap_protocol_list_t(&pl, info->host_byte_sex);
1139	printf("                      count %llu\n", pl.count);
1140
1141	p += sizeof(struct protocol_list_t);
1142	offset += sizeof(struct protocol_list_t);
1143	for(i = 0; i < pl.count; i++){
1144	    r = get_pointer_64(p, &offset, &left, &s, info->sections,
1145			       info->nsections);
1146	    if(r == NULL)
1147		return;
1148	    q = 0;
1149	    if(left < sizeof(uint64_t)){
1150		memcpy(&q, r, left);
1151		printf("   (protocol_t * entends past the end of the "
1152		       "section)\n");
1153	    }
1154	    else
1155		memcpy(&q, r, sizeof(uint64_t));
1156	    if(info->swapped)
1157		q = SWAP_LONG_LONG(q);
1158
1159	    printf("\t\t      list[%u] ", i);
1160	    sym_name = get_symbol_64(offset, s->addr - info->database, q,
1161				     s->relocs, s->nrelocs, info, &n_value);
1162	    if(n_value != 0){
1163		if(info->Vflag && sym_name != NULL)
1164		    printf("%s", sym_name);
1165		else
1166		    printf("0x%llx", n_value);
1167		if(q != 0)
1168		    printf(" + 0x%llx", q);
1169	    }
1170	    else
1171		printf("0x%llx", q);
1172	    printf(" (struct protocol_t *)\n");
1173
1174	    r = get_pointer_64(q + n_value, &offset, &left, &s, info->sections,
1175			       info->nsections);
1176	    if(r == NULL)
1177		return;
1178	    memset(&pc, '\0', sizeof(struct protocol_t));
1179	    if(left < sizeof(struct protocol_t)){
1180		memcpy(&pc, r, left);
1181		printf("   (protocol_t entends past the end of the section)\n");
1182	    }
1183	    else
1184		memcpy(&pc, r, sizeof(struct protocol_t));
1185	    if(info->swapped)
1186		swap_protocol_t(&pc, info->host_byte_sex);
1187
1188	    printf("\t\t\t      isa 0x%llx\n", pc.isa);
1189
1190	    printf("\t\t\t     name ");
1191	    sym_name = get_symbol_64(offset + offsetof(struct protocol_t, name),
1192				     s->addr - info->database, pc.name,
1193				     s->relocs, s->nrelocs, info, &n_value);
1194	    if(n_value != 0){
1195		if(info->Vflag && sym_name != NULL)
1196		    printf("%s", sym_name);
1197		else
1198		    printf("0x%llx", n_value);
1199		if(pc.name != 0)
1200		    printf(" + 0x%llx", pc.name);
1201	    }
1202	    else
1203		printf("0x%llx", pc.name);
1204	    name = get_pointer_64(pc.name + n_value , NULL, &left, NULL,
1205				  info->sections, info->nsections);
1206	    if(name != NULL)
1207		printf(" %.*s", (int)left, name);
1208	    printf("\n");
1209
1210	    printf("\t\t\tprotocols 0x%llx\n", pc.protocols);
1211
1212	    printf("\t\t  instanceMethods ");
1213	    sym_name = get_symbol_64(offset + offsetof(struct protocol_t,
1214						       instanceMethods),
1215				     s->addr - info->database,
1216				     pc.instanceMethods, s->relocs, s->nrelocs,
1217				     info, &n_value);
1218	    if(n_value != 0){
1219		if(info->Vflag && sym_name != NULL)
1220		    printf("%s", sym_name);
1221		else
1222		    printf("0x%llx", n_value);
1223		if(pc.instanceMethods != 0)
1224		    printf(" + 0x%llx", pc.instanceMethods);
1225	    }
1226	    else
1227		printf("0x%llx", pc.instanceMethods);
1228	    printf(" (struct method_list_t *)\n");
1229	    if(pc.instanceMethods + n_value != 0)
1230		print_method_list_t(pc.instanceMethods + n_value, info, "\t");
1231
1232	    printf("\t\t     classMethods ");
1233	    sym_name = get_symbol_64(offset + offsetof(struct protocol_t,
1234						       classMethods),
1235				     s->addr - info->database,
1236				     pc.classMethods, s->relocs, s->nrelocs,
1237				     info, &n_value);
1238	    if(n_value != 0){
1239		if(info->Vflag && sym_name != NULL)
1240		    printf("%s", sym_name);
1241		else
1242		    printf("0x%llx", n_value);
1243		if(pc.classMethods != 0)
1244		    printf(" + 0x%llx", pc.classMethods);
1245	    }
1246	    else
1247		printf("0x%llx", pc.classMethods);
1248	    printf(" (struct method_list_t *)\n");
1249
1250	    if(pc.classMethods + n_value != 0)
1251		print_method_list_t(pc.classMethods + n_value, info, "\t");
1252	    printf("\t  optionalInstanceMethods 0x%llx\n",
1253		   pc.optionalInstanceMethods);
1254	    printf("\t     optionalClassMethods 0x%llx\n",
1255		   pc.optionalClassMethods);
1256	    printf("\t       instanceProperties 0x%llx\n",
1257		   pc.instanceProperties);
1258
1259	    p += sizeof(uint64_t);
1260	    offset += sizeof(uint64_t);
1261	}
1262}
1263
1264static
1265void
1266print_objc_property_list(
1267uint64_t p,
1268struct info *info)
1269{
1270    struct objc_property_list opl;
1271    struct objc_property op;
1272    void *r;
1273    uint32_t offset, left, j;
1274    struct section_info_64 *s;
1275    const char *name, *sym_name;
1276    uint64_t n_value;
1277
1278	r = get_pointer_64(p, &offset, &left, &s, info->sections,
1279			   info->nsections);
1280	if(r == NULL)
1281	    return;
1282	memset(&opl, '\0', sizeof(struct objc_property_list));
1283	if(left < sizeof(struct objc_property_list)){
1284	    memcpy(&opl, r, left);
1285	    printf("   (objc_property_list entends past the end of the "
1286		   "section)\n");
1287	}
1288	else
1289	    memcpy(&opl, r, sizeof(struct objc_property_list));
1290	if(info->swapped)
1291	    swap_objc_property_list(&opl, info->host_byte_sex);
1292	printf("                    entsize %u\n", opl.entsize);
1293	printf("                      count %u\n", opl.count);
1294
1295	p += sizeof(struct objc_property_list);
1296	offset += sizeof(struct objc_property_list);
1297	for(j = 0; j < opl.count; j++){
1298	    r = get_pointer_64(p, &offset, &left, &s, info->sections,
1299			       info->nsections);
1300	    if(r == NULL)
1301		return;
1302	    memset(&op, '\0', sizeof(struct objc_property));
1303	    if(left < sizeof(struct objc_property)){
1304		memcpy(&op, r, left);
1305		printf("   (objc_property entends past the end of the "
1306		       "section)\n");
1307	    }
1308	    else
1309		memcpy(&op, r, sizeof(struct objc_property));
1310	    if(info->swapped)
1311		swap_objc_property(&op, info->host_byte_sex);
1312
1313	    printf("\t\t\t     name ");
1314	    sym_name = get_symbol_64(offset + offsetof(struct objc_property,
1315						       name),
1316				     s->addr - info->database, op.name,
1317				     s->relocs, s->nrelocs, info, &n_value);
1318	    if(n_value != 0){
1319		if(info->Vflag && sym_name != NULL)
1320		    printf("%s", sym_name);
1321		else
1322		    printf("0x%llx", n_value);
1323		if(op.name != 0)
1324		    printf(" + 0x%llx", op.name);
1325	    }
1326	    else
1327		printf("0x%llx", op.name);
1328	    name = get_pointer_64(op.name + n_value, NULL, &left, NULL,
1329				  info->sections, info->nsections);
1330	    if(name != NULL)
1331		printf(" %.*s", (int)left, name);
1332	    printf("\n");
1333
1334	    printf("\t\t\tattributes ");
1335	    sym_name = get_symbol_64(offset + offsetof(struct objc_property,
1336						       attributes),
1337				     s->addr - info->database, op.attributes,
1338				     s->relocs, s->nrelocs, info, &n_value);
1339	    if(n_value != 0){
1340		if(info->Vflag && sym_name != NULL)
1341		    printf("%s", sym_name);
1342		else
1343		    printf("0x%llx", n_value);
1344		if(op.attributes != 0)
1345		    printf(" + 0x%llx", op.attributes);
1346	    }
1347	    else
1348		printf("0x%llx", op.attributes);
1349	    name = get_pointer_64(op.attributes + n_value, NULL, &left, NULL,
1350				  info->sections, info->nsections);
1351	    if(name != NULL)
1352		printf(" %.*s", (int)left, name);
1353	    printf("\n");
1354
1355	    p += sizeof(struct objc_property);
1356	    offset += sizeof(struct objc_property);
1357	}
1358}
1359
1360static
1361void
1362print_category_t(
1363uint64_t p,
1364struct info *info)
1365{
1366    struct category_t c;
1367    void *r;
1368    uint32_t offset, left;
1369    struct section_info_64 *s;
1370    const char *name, *sym_name;
1371    uint64_t n_value;
1372
1373	r = get_pointer_64(p, &offset, &left, &s,
1374			   info->sections, info->nsections);
1375	if(r == NULL)
1376	    return;
1377	memset(&c, '\0', sizeof(struct category_t));
1378	if(left < sizeof(struct category_t)){
1379	    memcpy(&c, r, left);
1380	    printf("   (category_t entends past the end of the section)\n");
1381	}
1382	else
1383	    memcpy(&c, r, sizeof(struct category_t));
1384	if(info->swapped)
1385	    swap_category_t(&c, info->host_byte_sex);
1386
1387	printf("              name ");
1388	sym_name = get_symbol_64(offset + offsetof(struct category_t, name),
1389			         s->addr - info->database, c.name, s->relocs,
1390			         s->nrelocs, info, &n_value);
1391	if(n_value != 0){
1392	    if(info->Vflag && sym_name != NULL)
1393		printf("%s", sym_name);
1394	    else
1395		printf("0x%llx", n_value);
1396	    if(c.name != 0)
1397		printf(" + 0x%llx", c.name);
1398	}
1399	else
1400	    printf("0x%llx", c.name);
1401	name = get_pointer_64(c.name + n_value, NULL, &left, NULL,
1402			      info->sections, info->nsections);
1403	if(name != NULL)
1404	    printf(" %.*s", (int)left, name);
1405	printf("\n");
1406
1407	printf("               cls ");
1408	sym_name = get_symbol_64(offset + offsetof(struct category_t, cls),
1409			         s->addr - info->database, c.cls, s->relocs,
1410			         s->nrelocs, info, &n_value);
1411	if(n_value != 0){
1412	    if(info->Vflag && sym_name != NULL)
1413		printf("%s", sym_name);
1414	    else
1415		printf("0x%llx", n_value);
1416	    if(c.cls != 0)
1417		printf(" + 0x%llx", c.cls);
1418	}
1419	else
1420	    printf("0x%llx", c.cls);
1421	printf("\n");
1422	if(c.cls + n_value != 0)
1423	    print_class_t(c.cls + n_value, info);
1424
1425	printf("   instanceMethods ");
1426	sym_name = get_symbol_64(offset + offsetof(struct category_t,
1427						   instanceMethods),
1428			     s->addr - info->database, c.instanceMethods,
1429			     s->relocs, s->nrelocs, info, &n_value);
1430	if(n_value != 0){
1431	    if(info->Vflag && sym_name != NULL)
1432		printf("%s", sym_name);
1433	    else
1434		printf("0x%llx", n_value);
1435	    if(c.instanceMethods != 0)
1436		printf(" + 0x%llx", c.instanceMethods);
1437	}
1438	else
1439	    printf("0x%llx", c.instanceMethods);
1440	printf("\n");
1441	if(c.instanceMethods + n_value != 0)
1442	    print_method_list_t(c.instanceMethods + n_value, info, "");
1443
1444	printf("      classMethods ");
1445	sym_name = get_symbol_64(offset + offsetof(struct category_t,
1446						   classMethods),
1447			     s->addr - info->database, c.classMethods,
1448			     s->relocs, s->nrelocs, info, &n_value);
1449	if(n_value != 0){
1450	    if(info->Vflag && sym_name != NULL)
1451		printf("%s", sym_name);
1452	    else
1453		printf("0x%llx", n_value);
1454	    if(c.classMethods != 0)
1455		printf(" + 0x%llx", c.classMethods);
1456	}
1457	else
1458	    printf("0x%llx", c.classMethods);
1459	printf("\n");
1460	if(c.classMethods + n_value != 0)
1461	    print_method_list_t(c.classMethods + n_value, info, "");
1462
1463	printf("         protocols ");
1464	sym_name = get_symbol_64(offset + offsetof(struct category_t,
1465						   protocols),
1466			     s->addr - info->database, c.protocols,
1467			     s->relocs, s->nrelocs, info, &n_value);
1468	if(n_value != 0){
1469	    if(info->Vflag && sym_name != NULL)
1470		printf("%s", sym_name);
1471	    else
1472		printf("0x%llx", n_value);
1473	    if(c.protocols != 0)
1474		printf(" + 0x%llx", c.protocols);
1475	}
1476	else
1477	    printf("0x%llx", c.protocols);
1478	printf("\n");
1479	if(c.protocols + n_value != 0)
1480	    print_protocol_list_t(c.protocols + n_value, info);
1481
1482	printf("instanceProperties ");
1483	sym_name = get_symbol_64(offset + offsetof(struct category_t,
1484						   instanceProperties),
1485			     s->addr - info->database, c.instanceProperties,
1486			     s->relocs, s->nrelocs, info, &n_value);
1487	if(n_value != 0){
1488	    if(info->Vflag && sym_name != NULL)
1489		printf("%s", sym_name);
1490	    else
1491		printf("0x%llx", n_value);
1492	    if(c.instanceProperties != 0)
1493		printf(" + 0x%llx", c.instanceProperties);
1494	}
1495	else
1496	    printf("0x%llx", c.instanceProperties);
1497	printf("\n");
1498	if(c.instanceProperties + n_value)
1499	    print_objc_property_list(c.instanceProperties + n_value, info);
1500}
1501
1502static
1503void
1504print_message_refs(
1505struct section_info_64 *s,
1506struct info *info)
1507{
1508    uint32_t i, left, offset;
1509    uint64_t p, n_value;
1510    struct message_ref mr;
1511    const char *name, *sym_name;
1512    void *r;
1513
1514	if(s == NULL)
1515	    return;
1516
1517	printf("Contents of (%.16s,%.16s) section\n", s->segname, s->sectname);
1518	offset = 0;
1519	for(i = 0; i < s->size; i += sizeof(struct message_ref)){
1520	    p = s->addr + i;
1521	    r = get_pointer_64(p, &offset, &left, &s,
1522			       info->sections, info->nsections);
1523	    if(r == NULL)
1524		return;
1525	    memset(&mr, '\0', sizeof(struct message_ref));
1526	    if(left < sizeof(struct message_ref)){
1527		memcpy(&mr, r, left);
1528		printf(" (message_ref entends past the end of the section)\n");
1529	    }
1530	    else
1531		memcpy(&mr, r, sizeof(struct message_ref));
1532	    if(info->swapped)
1533		swap_message_ref(&mr, info->host_byte_sex);
1534
1535	    printf("  imp ");
1536	    name = get_symbol_64(offset + offsetof(struct message_ref, imp),
1537				 s->addr - info->database, mr.imp, s->relocs,
1538				 s->nrelocs, info, &n_value);
1539	    if(n_value != 0){
1540		printf("0x%llx", n_value);
1541		if(mr.imp != 0)
1542		    printf(" + 0x%llx", mr.imp);
1543	    }
1544	    else
1545		printf("0x%llx", mr.imp);
1546	    if(name != NULL)
1547		printf(" %s", name);
1548	    printf("\n");
1549
1550	    printf("  sel ");
1551	    sym_name = get_symbol_64(offset + offsetof(struct message_ref, sel),
1552				     s->addr - info->database, mr.sel,
1553				     s->relocs, s->nrelocs, info, &n_value);
1554	    if(n_value != 0){
1555		if(info->Vflag && sym_name != NULL)
1556		    printf("%s", sym_name);
1557		else
1558		    printf("0x%llx", n_value);
1559		if(mr.sel != 0)
1560		    printf(" + 0x%llx", mr.sel);
1561	    }
1562	    else
1563		printf("0x%llx", mr.sel);
1564	    name = get_pointer_64(mr.sel + n_value, NULL, &left, NULL,
1565				  info->sections, info->nsections);
1566	    if(name != NULL)
1567		printf(" %.*s", (int)left, name);
1568	    printf("\n");
1569
1570	    offset += sizeof(struct message_ref);
1571	}
1572}
1573
1574static
1575void
1576print_image_info(
1577struct section_info_64 *s,
1578struct info *info)
1579{
1580    uint32_t left, offset;
1581    uint64_t p;
1582    struct objc_image_info o;
1583    void *r;
1584
1585	if(s == NULL)
1586	    return;
1587
1588	printf("Contents of (%.16s,%.16s) section\n", s->segname, s->sectname);
1589	p = s->addr;
1590	r = get_pointer_64(p, &offset, &left, &s,
1591			   info->sections, info->nsections);
1592	if(r == NULL)
1593	    return;
1594	memset(&o, '\0', sizeof(struct objc_image_info));
1595	if(left < sizeof(struct objc_image_info)){
1596	    memcpy(&o, r, left);
1597	    printf(" (objc_image_info entends past the end of the section)\n");
1598	}
1599	else
1600	    memcpy(&o, r, sizeof(struct objc_image_info));
1601	if(info->swapped)
1602	    swap_objc_image_info(&o, info->host_byte_sex);
1603	printf("  version %u\n", o.version);
1604	printf("    flags 0x%x", o.flags);
1605	if(o.flags & OBJC_IMAGE_IS_REPLACEMENT)
1606	    printf(" OBJC_IMAGE_IS_REPLACEMENT");
1607	if(o.flags & OBJC_IMAGE_SUPPORTS_GC)
1608	    printf(" OBJC_IMAGE_SUPPORTS_GC");
1609	printf("\n");
1610}
1611
1612void
1613print_objc_string_object_section_64(
1614char *sectname,
1615struct load_command *load_commands,
1616uint32_t ncmds,
1617uint32_t sizeofcmds,
1618enum byte_sex object_byte_sex,
1619char *object_addr,
1620uint32_t object_size,
1621cpu_type_t cputype,
1622struct nlist_64 *symbols64,
1623uint32_t nsymbols,
1624char *strings,
1625const uint32_t strings_size,
1626struct symbol *sorted_symbols,
1627uint32_t nsorted_symbols,
1628enum bool verbose)
1629{
1630    struct info info;
1631    struct section_info_64 *o, cstring_section;
1632    struct objc_string_object_64 *string_objects, *s, string_object;
1633    uint64_t string_objects_addr, string_objects_size;
1634    uint32_t size, left;
1635    char *p;
1636    const char *name;
1637
1638	printf("Contents of (" SEG_OBJC ",%s) section\n", sectname);
1639	info.host_byte_sex = get_host_byte_sex();
1640	info.swapped = info.host_byte_sex != object_byte_sex;
1641	info.cputype = cputype;
1642	info.symbols64 = symbols64;
1643	info.nsymbols = nsymbols;
1644	info.strings = strings;
1645	info.strings_size = strings_size;
1646	info.sorted_symbols = sorted_symbols;
1647	info.nsorted_symbols = nsorted_symbols;
1648	info.verbose = verbose;
1649	get_sections_64(load_commands, ncmds, sizeofcmds, object_byte_sex,
1650			object_addr, object_size, &info.sections,
1651			&info.nsections, &info.database);
1652	o = get_section_64(info.sections, info.nsections, SEG_OBJC, sectname);
1653	get_cstring_section_64(load_commands, ncmds, sizeofcmds,object_byte_sex,
1654			       object_addr, object_size, &cstring_section);
1655
1656	string_objects = (struct objc_string_object_64 *)o->contents;
1657	string_objects_addr = o->addr;
1658	string_objects_size = o->size;
1659	for(s = string_objects;
1660	    (char *)s < (char *)string_objects + string_objects_size;
1661	    s++){
1662
1663	    memset(&string_object, '\0', sizeof(struct objc_string_object_64));
1664	    left = string_objects_size - (s - string_objects);
1665	    size = left < sizeof(struct objc_string_object_64) ?
1666		   left : sizeof(struct objc_string_object_64);
1667	    memcpy(&string_object, s, size);
1668
1669	    if((char *)s + sizeof(struct objc_string_object_64) >
1670	       (char *)s + string_objects_size)
1671		printf("String Object extends past end of %s section\n",
1672		       sectname);
1673	    printf("String Object 0x%llx\n",
1674		   string_objects_addr + ((char *)s - (char *)string_objects));
1675
1676	    if(info.swapped)
1677		swap_string_object_64(&string_object, info.host_byte_sex);
1678	    printf("           isa 0x%llx", string_object.isa);
1679	    name = get_symbol_64((uintptr_t)s - (uintptr_t)string_objects,
1680				 o->addr - info.database, string_object.isa,
1681				 o->relocs, o->nrelocs, &info, NULL);
1682	    if(name != NULL)
1683		printf(" %s\n", name);
1684	    else
1685		printf("\n");
1686	    printf("    characters 0x%llx", string_object.characters);
1687	    if(verbose){
1688		p = get_pointer_64(string_object.characters, NULL, &left,
1689				   NULL, info.sections, info.nsections);
1690		if(p != NULL)
1691		    printf(" %.*s\n", (int)left, p);
1692	    }
1693	    else
1694		printf("\n");
1695	    printf("       _length %u\n", string_object._length);
1696	    printf("          _pad %u\n", string_object._pad);
1697	}
1698}
1699
1700static
1701void
1702get_sections_64(
1703struct load_command *load_commands,
1704uint32_t ncmds,
1705uint32_t sizeofcmds,
1706enum byte_sex object_byte_sex,
1707char *object_addr,
1708uint32_t object_size,
1709struct section_info_64 **sections,
1710uint32_t *nsections,
1711uint64_t *database)
1712{
1713    enum byte_sex host_byte_sex;
1714    enum bool swapped, database_set, zerobased, encrypt_found, encrypt64_found;
1715
1716    uint32_t i, j, left, size;
1717    struct load_command lcmd, *lc;
1718    char *p;
1719    struct segment_command_64 sg64;
1720    struct section_64 s64;
1721    struct encryption_info_command encrypt;
1722    struct encryption_info_command_64 encrypt64;
1723
1724	host_byte_sex = get_host_byte_sex();
1725	swapped = host_byte_sex != object_byte_sex;
1726
1727	*sections = NULL;
1728	*nsections = 0;
1729	database_set = FALSE;
1730	*database = 0;
1731	zerobased = FALSE;
1732	encrypt_found = FALSE;
1733	encrypt64_found = FALSE;
1734
1735	lc = load_commands;
1736	for(i = 0 ; i < ncmds; i++){
1737	    memcpy((char *)&lcmd, (char *)lc, sizeof(struct load_command));
1738	    if(swapped)
1739		swap_load_command(&lcmd, host_byte_sex);
1740	    if(lcmd.cmdsize % sizeof(int32_t) != 0)
1741		printf("load command %u size not a multiple of "
1742		       "sizeof(int32_t)\n", i);
1743	    if((char *)lc + lcmd.cmdsize >
1744	       (char *)load_commands + sizeofcmds)
1745		printf("load command %u extends past end of load "
1746		       "commands\n", i);
1747	    left = sizeofcmds - ((char *)lc - (char *)load_commands);
1748
1749	    switch(lcmd.cmd){
1750	    case LC_SEGMENT_64:
1751		memset((char *)&sg64, '\0', sizeof(struct segment_command_64));
1752		size = left < sizeof(struct segment_command_64) ?
1753		       left : sizeof(struct segment_command_64);
1754		memcpy((char *)&sg64, (char *)lc, size);
1755		if(swapped)
1756		    swap_segment_command_64(&sg64, host_byte_sex);
1757		if((sg64.initprot & VM_PROT_WRITE) == VM_PROT_WRITE &&
1758		   database_set == FALSE){
1759		    *database = sg64.vmaddr;
1760		    database_set = TRUE;
1761		}
1762		if((sg64.initprot & VM_PROT_READ) == VM_PROT_READ &&
1763		   sg64.vmaddr == 0)
1764		    zerobased = TRUE;
1765		p = (char *)lc + sizeof(struct segment_command_64);
1766		for(j = 0 ; j < sg64.nsects ; j++){
1767		    if(p + sizeof(struct section_64) >
1768		       (char *)load_commands + sizeofcmds){
1769			printf("section structure command extends past "
1770			       "end of load commands\n");
1771		    }
1772		    left = sizeofcmds - (p - (char *)load_commands);
1773		    memset((char *)&s64, '\0', sizeof(struct section_64));
1774		    size = left < sizeof(struct section_64) ?
1775			   left : sizeof(struct section_64);
1776		    memcpy((char *)&s64, p, size);
1777		    if(swapped)
1778			swap_section_64(&s64, 1, host_byte_sex);
1779
1780		    *sections = reallocate(*sections,
1781		       sizeof(struct section_info_64) * (*nsections + 1));
1782		    memcpy((*sections)[*nsections].segname,
1783			   s64.segname, 16);
1784		    memcpy((*sections)[*nsections].sectname,
1785			   s64.sectname, 16);
1786		    (*sections)[*nsections].addr = s64.addr;
1787		    (*sections)[*nsections].contents = object_addr + s64.offset;
1788		    (*sections)[*nsections].offset = s64.offset;
1789		    (*sections)[*nsections].zerofill =
1790			(s64.flags & SECTION_TYPE) == S_ZEROFILL ? TRUE : FALSE;
1791		    if(s64.offset > object_size){
1792			printf("section contents of: (%.16s,%.16s) is past "
1793			       "end of file\n", s64.segname, s64.sectname);
1794			(*sections)[*nsections].size =  0;
1795		    }
1796		    else if(s64.offset + s64.size > object_size){
1797			printf("part of section contents of: (%.16s,%.16s) "
1798			       "is past end of file\n",
1799			       s64.segname, s64.sectname);
1800			(*sections)[*nsections].size = object_size - s64.offset;
1801		    }
1802		    else
1803			(*sections)[*nsections].size = s64.size;
1804		    if(s64.reloff >= object_size){
1805			printf("relocation entries offset for (%.16s,%.16s)"
1806			       ": is past end of file\n", s64.segname,
1807			       s64.sectname);
1808			(*sections)[*nsections].nrelocs = 0;
1809		    }
1810		    else{
1811			(*sections)[*nsections].relocs =
1812			    (struct relocation_info *)(object_addr +
1813						       s64.reloff);
1814			if(s64.reloff +
1815			   s64.nreloc * sizeof(struct relocation_info) >
1816							    object_size){
1817			    printf("relocation entries for section (%.16s,"
1818				   "%.16s) extends past end of file\n",
1819				   s64.segname, s64.sectname);
1820			    (*sections)[*nsections].nrelocs =
1821				(object_size - s64.reloff) /
1822					    sizeof(struct relocation_info);
1823			}
1824			else
1825			    (*sections)[*nsections].nrelocs = s64.nreloc;
1826			if(swapped)
1827			    swap_relocation_info(
1828				(*sections)[*nsections].relocs,
1829				(*sections)[*nsections].nrelocs,
1830				host_byte_sex);
1831		    }
1832		    if(sg64.flags & SG_PROTECTED_VERSION_1)
1833			(*sections)[*nsections].protected = TRUE;
1834		    else
1835			(*sections)[*nsections].protected = FALSE;
1836		    if((s64.flags & SECTION_TYPE) == S_CSTRING_LITERALS)
1837			(*sections)[*nsections].cstring = TRUE;
1838		    else
1839			(*sections)[*nsections].cstring = FALSE;
1840		    (*nsections)++;
1841
1842		    if(p + sizeof(struct section_64) >
1843		       (char *)load_commands + sizeofcmds)
1844			break;
1845		    p += size;
1846		}
1847		break;
1848	    case LC_ENCRYPTION_INFO:
1849		memset((char *)&encrypt, '\0',
1850		       sizeof(struct encryption_info_command));
1851		size = left < sizeof(struct encryption_info_command) ?
1852		       left : sizeof(struct encryption_info_command);
1853		memcpy((char *)&encrypt, (char *)lc, size);
1854		if(swapped)
1855		    swap_encryption_command(&encrypt, host_byte_sex);
1856		encrypt_found = TRUE;
1857		break;
1858	    case LC_ENCRYPTION_INFO_64:
1859		memset((char *)&encrypt64, '\0',
1860		       sizeof(struct encryption_info_command_64));
1861		size = left < sizeof(struct encryption_info_command_64) ?
1862		       left : sizeof(struct encryption_info_command_64);
1863		memcpy((char *)&encrypt64, (char *)lc, size);
1864		if(swapped)
1865		    swap_encryption_command_64(&encrypt64, host_byte_sex);
1866		encrypt64_found = TRUE;
1867		break;
1868	    }
1869	    if(lcmd.cmdsize == 0){
1870		printf("load command %u size zero (can't advance to other "
1871		       "load commands)\n", i);
1872		break;
1873	    }
1874	    lc = (struct load_command *)((char *)lc + lcmd.cmdsize);
1875	    if((char *)lc > (char *)load_commands + sizeofcmds)
1876		break;
1877	}
1878
1879	if(encrypt_found == TRUE && encrypt.cryptid != 0){
1880	    for(i = 0; i < *nsections; i++){
1881		if((*sections)[i].size > 0 && (*sections)[i].zerofill == FALSE){
1882		    if((*sections)[i].offset >
1883		       encrypt.cryptoff + encrypt.cryptsize){
1884			/* section starts past encryption area */ ;
1885		    }
1886		    else if((*sections)[i].offset + (*sections)[i].size <
1887			encrypt.cryptoff){
1888			/* section ends before encryption area */ ;
1889		    }
1890		    else{
1891			/* section has part in the encrypted area */
1892			(*sections)[i].protected = TRUE;
1893		    }
1894		}
1895	    }
1896	}
1897	if(encrypt64_found == TRUE && encrypt64.cryptid != 0){
1898	    for(i = 0; i < *nsections; i++){
1899		if((*sections)[i].size > 0 && (*sections)[i].zerofill == FALSE){
1900		    if((*sections)[i].offset >
1901		       encrypt64.cryptoff + encrypt64.cryptsize){
1902			/* section starts past encryption area */ ;
1903		    }
1904		    else if((*sections)[i].offset + (*sections)[i].size <
1905			encrypt64.cryptoff){
1906			/* section ends before encryption area */ ;
1907		    }
1908		    else{
1909			/* section has part in the encrypted area */
1910			(*sections)[i].protected = TRUE;
1911		    }
1912		}
1913	    }
1914	}
1915}
1916
1917static
1918struct section_info_64 *
1919get_section_64(
1920struct section_info_64 *sections,
1921uint32_t nsections,
1922char *segname,
1923char *sectname)
1924{
1925    uint32_t i;
1926
1927	for(i = 0; i < nsections; i++){
1928	    if(strncmp(sections[i].segname, segname, 16) == 0 &&
1929	       strncmp(sections[i].sectname, sectname, 16) == 0){
1930		return(sections + i);
1931	    }
1932	}
1933	return(NULL);
1934}
1935
1936static
1937void
1938get_cstring_section_64(
1939struct load_command *load_commands,
1940uint32_t ncmds,
1941uint32_t sizeofcmds,
1942enum byte_sex object_byte_sex,
1943char *object_addr,
1944uint32_t object_size,
1945struct section_info_64 *cstring_section)
1946{
1947    enum byte_sex host_byte_sex;
1948    enum bool swapped;
1949
1950    uint32_t i, j, left, size;
1951    struct load_command lcmd, *lc;
1952    char *p;
1953    struct segment_command_64 sg64;
1954    struct section_64 s64;
1955
1956	host_byte_sex = get_host_byte_sex();
1957	swapped = host_byte_sex != object_byte_sex;
1958
1959	memset(cstring_section, '\0', sizeof(struct section_info_64));
1960
1961	lc = load_commands;
1962	for(i = 0 ; i < ncmds; i++){
1963	    memcpy((char *)&lcmd, (char *)lc, sizeof(struct load_command));
1964	    if(swapped)
1965		swap_load_command(&lcmd, host_byte_sex);
1966	    if(lcmd.cmdsize % sizeof(int32_t) != 0)
1967		printf("load command %u size not a multiple of "
1968		       "sizeof(int32_t)\n", i);
1969	    if((char *)lc + lcmd.cmdsize >
1970	       (char *)load_commands + sizeofcmds)
1971		printf("load command %u extends past end of load "
1972		       "commands\n", i);
1973	    left = sizeofcmds - ((char *)lc - (char *)load_commands);
1974
1975	    switch(lcmd.cmd){
1976	    case LC_SEGMENT_64:
1977		memset((char *)&sg64, '\0', sizeof(struct segment_command_64));
1978		size = left < sizeof(struct segment_command_64) ?
1979		       left : sizeof(struct segment_command_64);
1980		memcpy((char *)&sg64, (char *)lc, size);
1981		if(swapped)
1982		    swap_segment_command_64(&sg64, host_byte_sex);
1983
1984		p = (char *)lc + sizeof(struct segment_command_64);
1985		for(j = 0 ; j < sg64.nsects ; j++){
1986		    if(p + sizeof(struct section_64) >
1987		       (char *)load_commands + sizeofcmds){
1988			printf("section structure command extends past "
1989			       "end of load commands\n");
1990		    }
1991		    left = sizeofcmds - (p - (char *)load_commands);
1992		    memset((char *)&s64, '\0', sizeof(struct section_64));
1993		    size = left < sizeof(struct section_64) ?
1994			   left : sizeof(struct section_64);
1995		    memcpy((char *)&s64, p, size);
1996		    if(swapped)
1997			swap_section_64(&s64, 1, host_byte_sex);
1998
1999		    if(strcmp(s64.segname, SEG_TEXT) == 0 &&
2000		       strcmp(s64.sectname, "__cstring") == 0){
2001			cstring_section->addr = s64.addr;
2002			cstring_section->contents = object_addr + s64.offset;
2003			if(s64.offset > object_size){
2004			    printf("section contents of: (%.16s,%.16s) is past "
2005				   "end of file\n", s64.segname, s64.sectname);
2006			    cstring_section->size = 0;
2007			}
2008			else if(s64.offset + s64.size > object_size){
2009			    printf("part of section contents of: (%.16s,%.16s) "
2010				   "is past end of file\n",
2011				   s64.segname, s64.sectname);
2012			    cstring_section->size = object_size - s64.offset;
2013			}
2014			else
2015			    cstring_section->size = s64.size;
2016			if(sg64.flags & SG_PROTECTED_VERSION_1)
2017			    cstring_section->protected = TRUE;
2018			else
2019			    cstring_section->protected = FALSE;
2020			cstring_section->cstring = TRUE;
2021			return;
2022		    }
2023
2024		    if(p + sizeof(struct section) >
2025		       (char *)load_commands + sizeofcmds)
2026			break;
2027		    p += size;
2028		}
2029		break;
2030	    }
2031	    if(lcmd.cmdsize == 0){
2032		printf("load command %u size zero (can't advance to other "
2033		       "load commands)\n", i);
2034		break;
2035	    }
2036	    lc = (struct load_command *)((char *)lc + lcmd.cmdsize);
2037	    if((char *)lc > (char *)load_commands + sizeofcmds)
2038		break;
2039	}
2040}
2041
2042static
2043void *
2044get_pointer_64(
2045uint64_t p,
2046uint32_t *offset,
2047uint32_t *left,
2048struct section_info_64 **s,
2049struct section_info_64 *sections,
2050uint32_t nsections)
2051{
2052    void *r;
2053    uint64_t addr;
2054    uint32_t i;
2055
2056	addr = p;
2057	for(i = 0; i < nsections; i++){
2058	    if(addr >= sections[i].addr &&
2059	       addr < sections[i].addr + sections[i].size){
2060		if(s != NULL)
2061		    *s = sections + i;
2062		if(offset != NULL)
2063		    *offset = addr - sections[i].addr;
2064		if(left != NULL)
2065		    *left = sections[i].size - (addr - sections[i].addr);
2066		if(sections[i].protected == TRUE && sections[i].cstring == TRUE)
2067		    r = "some string from a protected section";
2068		else
2069		    r = sections[i].contents + (addr - sections[i].addr);
2070		return(r);
2071	    }
2072	}
2073	if(s != NULL)
2074	    *s = NULL;
2075	if(offset != NULL)
2076	    *offset = 0;
2077	if(left != NULL)
2078	    *left = 0;
2079	return(NULL);
2080}
2081
2082/*
2083 * get_symbol() returns the name of a symbol (or NULL). Based on the relocation
2084 * information at the specified section offset or the value.
2085 */
2086static
2087const char *
2088get_symbol_64(
2089uint32_t sect_offset,
2090uint64_t database_offset,
2091uint64_t value,
2092struct relocation_info *relocs,
2093uint32_t nrelocs,
2094struct info *info,
2095uint64_t *n_value)
2096{
2097    uint32_t i;
2098    unsigned int r_symbolnum;
2099    uint32_t n_strx;
2100
2101	if(info->verbose == FALSE)
2102	    return(NULL);
2103
2104	for(i = 0; i < nrelocs; i++){
2105	    if((uint32_t)relocs[i].r_address == sect_offset){
2106		r_symbolnum = relocs[i].r_symbolnum;
2107		if(relocs[i].r_extern){
2108		    if(r_symbolnum >= info->nsymbols)
2109			break;
2110		    n_strx = info->symbols64[r_symbolnum].n_un.n_strx;
2111		    if(n_strx <= 0 || n_strx >= info->strings_size)
2112			break;
2113		    if(n_value != NULL)
2114			*n_value = info->symbols64[r_symbolnum].n_value;
2115		    return(info->strings + n_strx);
2116		}
2117		break;
2118	    }
2119	    if(reloc_has_pair(info->cputype, relocs[i].r_type) == TRUE)
2120		i++;
2121	}
2122	for(i = 0; i < info->next_relocs; i++){
2123	    if((uint32_t)info->ext_relocs[i].r_address ==
2124		database_offset + sect_offset){
2125		r_symbolnum = info->ext_relocs[i].r_symbolnum;
2126		if(info->ext_relocs[i].r_extern){
2127		    if(r_symbolnum >= info->nsymbols)
2128			break;
2129		    n_strx = info->symbols64[r_symbolnum].n_un.n_strx;
2130		    if(n_strx <= 0 || n_strx >= info->strings_size)
2131			break;
2132		    if(n_value != NULL)
2133			*n_value = info->symbols64[r_symbolnum].n_value;
2134		    return(info->strings + n_strx);
2135		}
2136		break;
2137	    }
2138	    if(reloc_has_pair(info->cputype, info->ext_relocs[i].r_type) ==TRUE)
2139		i++;
2140	}
2141	if(n_value != NULL)
2142	    *n_value = 0;
2143	if(value == 0)
2144	    return(NULL);
2145	return(guess_symbol(value, info->sorted_symbols, info->nsorted_symbols,
2146			    info->verbose));
2147}
2148