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 * 32-bit Objective-C 2 meta data structures.
46 *
47 * The real structure definitions come from the objc4 project in the private
48 * header file runtime/objc-runtime-new.h in that project.
49 */
50
51struct class_t {
52    uint32_t isa;		/* class_t * (32-bit pointer) */
53    uint32_t superclass;	/* class_t * (32-bit pointer) */
54    uint32_t cache;		/* Cache (32-bit pointer) */
55    uint32_t vtable;		/* IMP * (32-bit pointer) */
56    uint32_t data;		/* class_ro_t * (32-bit pointer) */
57};
58
59static
60void
61swap_class_t(
62struct class_t *c,
63enum byte_sex target_byte_sex)
64{
65	c->isa = SWAP_INT(c->isa);
66	c->superclass = SWAP_INT(c->superclass);
67	c->cache = SWAP_INT(c->cache);
68	c->vtable = SWAP_INT(c->vtable);
69	c->data = SWAP_INT(c->data);
70}
71
72struct class_ro_t {
73    uint32_t flags;
74    uint32_t instanceStart;
75    uint32_t instanceSize;
76    uint32_t ivarLayout;	/* const uint8_t * (32-bit pointer) */
77    uint32_t name; 		/* const char * (32-bit pointer) */
78    uint32_t baseMethods; 	/* const method_list_t * (32-bit pointer) */
79    uint32_t baseProtocols; 	/* const protocol_list_t * (32-bit pointer) */
80    uint32_t ivars; 		/* const ivar_list_t * (32-bit pointer) */
81    uint32_t weakIvarLayout; 	/* const uint8_t * (32-bit pointer) */
82    uint32_t baseProperties; 	/* const struct objc_property_list *
83							(32-bit pointer) */
84};
85
86/* Values for class_ro_t->flags */
87#define RO_META               (1<<0)
88#define RO_ROOT               (1<<1)
89#define RO_HAS_CXX_STRUCTORS  (1<<2)
90
91
92static
93void
94swap_class_ro_t(
95struct class_ro_t *cro,
96enum byte_sex target_byte_sex)
97{
98	cro->flags = SWAP_INT(cro->flags);
99	cro->instanceStart = SWAP_INT(cro->instanceStart);
100	cro->instanceSize = SWAP_INT(cro->instanceSize);
101	cro->ivarLayout = SWAP_INT(cro->ivarLayout);
102	cro->name = SWAP_INT(cro->name);
103	cro->baseMethods = SWAP_INT(cro->baseMethods);
104	cro->baseProtocols = SWAP_INT(cro->baseProtocols);
105	cro->ivars = SWAP_INT(cro->ivars);
106	cro->weakIvarLayout = SWAP_INT(cro->weakIvarLayout);
107	cro->baseProperties = SWAP_INT(cro->baseProperties);
108}
109
110struct method_list_t {
111    uint32_t entsize;
112    uint32_t count;
113    /* struct method_t first;  These structures follow inline */
114};
115
116static
117void
118swap_method_list_t(
119struct method_list_t *ml,
120enum byte_sex target_byte_sex)
121{
122	ml->entsize = SWAP_INT(ml->entsize);
123	ml->count = SWAP_INT(ml->count);
124}
125
126struct method_t {
127    uint32_t name;	/* SEL (32-bit pointer) */
128    uint32_t types;	/* const char * (32-bit pointer) */
129    uint32_t imp;	/* IMP (32-bit pointer) */
130};
131
132static
133void
134swap_method_t(
135struct method_t *m,
136enum byte_sex target_byte_sex)
137{
138	m->name = SWAP_INT(m->name);
139	m->types = SWAP_INT(m->types);
140	m->imp = SWAP_INT(m->imp);
141}
142
143struct ivar_list_t {
144    uint32_t entsize;
145    uint32_t count;
146    /* struct ivar_t first;  These structures follow inline */
147};
148
149static
150void
151swap_ivar_list_t(
152struct ivar_list_t *il,
153enum byte_sex target_byte_sex)
154{
155	il->entsize = SWAP_INT(il->entsize);
156	il->count = SWAP_INT(il->count);
157}
158
159struct ivar_t {
160    uint32_t offset;	/* uintptr_t * (32-bit pointer) */
161    uint32_t name;	/* const char * (32-bit pointer) */
162    uint32_t type;	/* const char * (32-bit pointer) */
163    uint32_t alignment;
164    uint32_t size;
165};
166
167static
168void
169swap_ivar_t(
170struct ivar_t *i,
171enum byte_sex target_byte_sex)
172{
173	i->offset = SWAP_INT(i->offset);
174	i->name = SWAP_INT(i->name);
175	i->type = SWAP_INT(i->type);
176	i->alignment = SWAP_INT(i->alignment);
177	i->size = SWAP_INT(i->size);
178}
179
180struct protocol_list_t {
181    uint32_t count;	/* uintptr_t (a 32-bit value) */
182    /* struct protocol_t * list[0];  These pointers follow inline */
183};
184
185static
186void
187swap_protocol_list_t(
188struct protocol_list_t *pl,
189enum byte_sex target_byte_sex)
190{
191	pl->count = SWAP_INT(pl->count);
192}
193
194struct protocol_t {
195    uint32_t isa;			/* id * (32-bit pointer) */
196    uint32_t name;			/* const char * (32-bit pointer) */
197    uint32_t protocols;			/* struct protocol_list_t *
198							(32-bit pointer) */
199    uint32_t instanceMethods;		/* method_list_t * (32-bit pointer) */
200    uint32_t classMethods;		/* method_list_t * (32-bit pointer) */
201    uint32_t optionalInstanceMethods;	/* method_list_t * (32-bit pointer) */
202    uint32_t optionalClassMethods;	/* method_list_t * (32-bit pointer) */
203    uint32_t instanceProperties;	/* struct objc_property_list *
204							   (32-bit pointer) */
205};
206
207static
208void
209swap_protocol_t(
210struct protocol_t *p,
211enum byte_sex target_byte_sex)
212{
213	p->isa = SWAP_INT(p->isa);
214	p->name = SWAP_INT(p->name);
215	p->protocols = SWAP_INT(p->protocols);
216	p->instanceMethods = SWAP_INT(p->instanceMethods);
217	p->classMethods = SWAP_INT(p->classMethods);
218	p->optionalInstanceMethods = SWAP_INT(p->optionalInstanceMethods);
219	p->optionalClassMethods = SWAP_INT(p->optionalClassMethods);
220	p->instanceProperties = SWAP_INT(p->instanceProperties);
221}
222
223struct objc_property_list {
224    uint32_t entsize;
225    uint32_t count;
226    /* struct objc_property first;  These structures follow inline */
227};
228
229static
230void
231swap_objc_property_list(
232struct objc_property_list *pl,
233enum byte_sex target_byte_sex)
234{
235	pl->entsize = SWAP_INT(pl->entsize);
236	pl->count = SWAP_INT(pl->count);
237}
238
239struct objc_property {
240    uint32_t name;		/* const char * (32-bit pointer) */
241    uint32_t attributes;	/* const char * (32-bit pointer) */
242};
243
244static
245void
246swap_objc_property(
247struct objc_property *op,
248enum byte_sex target_byte_sex)
249{
250	op->name = SWAP_INT(op->name);
251	op->attributes = SWAP_INT(op->attributes);
252}
253
254struct category_t {
255    uint32_t name; 		/* const char * (32-bit pointer) */
256    uint32_t cls;		/* struct class_t * (32-bit pointer) */
257    uint32_t instanceMethods;	/* struct method_list_t * (32-bit pointer) */
258    uint32_t classMethods;	/* struct method_list_t * (32-bit pointer) */
259    uint32_t protocols;		/* struct protocol_list_t * (32-bit pointer) */
260    uint32_t instanceProperties; /* struct objc_property_list *
261				    (32-bit pointer) */
262};
263
264static
265void
266swap_category_t(
267struct category_t *c,
268enum byte_sex target_byte_sex)
269{
270	c->name = SWAP_INT(c->name);
271	c->cls = SWAP_INT(c->cls);
272	c->instanceMethods = SWAP_INT(c->instanceMethods);
273	c->classMethods = SWAP_INT(c->classMethods);
274	c->protocols = SWAP_INT(c->protocols);
275	c->instanceProperties = SWAP_INT(c->instanceProperties);
276}
277
278struct message_ref {
279    uint32_t imp;	/* IMP (32-bit pointer) */
280    uint32_t sel;	/* SEL (32-bit pointer) */
281};
282
283static
284void
285swap_message_ref(
286struct message_ref *mr,
287enum byte_sex target_byte_sex)
288{
289	mr->imp = SWAP_INT(mr->imp);
290	mr->sel = SWAP_INT(mr->sel);
291}
292
293struct objc_image_info {
294    uint32_t version;
295    uint32_t flags;
296};
297/* masks for objc_image_info.flags */
298#define OBJC_IMAGE_IS_REPLACEMENT (1<<0)
299#define OBJC_IMAGE_SUPPORTS_GC (1<<1)
300
301
302static
303void
304swap_objc_image_info(
305struct objc_image_info *o,
306enum byte_sex target_byte_sex)
307{
308	o->version = SWAP_INT(o->version);
309	o->flags = SWAP_INT(o->flags);
310}
311
312struct info {
313    enum bool swapped;
314    enum byte_sex host_byte_sex;
315    struct section_info_32 *sections;
316    uint32_t nsections;
317    cpu_type_t cputype;
318    struct nlist *symbols;
319    uint32_t nsymbols;
320    char *strings;
321    uint32_t strings_size;
322    struct symbol *sorted_symbols;
323    uint32_t nsorted_symbols;
324    uint32_t database;
325    struct relocation_info *ext_relocs;
326    uint32_t next_relocs;
327    struct relocation_info *loc_relocs;
328    uint32_t nloc_relocs;
329    enum bool verbose;
330};
331
332struct section_info_32 {
333    char segname[16];
334    char sectname[16];
335    char *contents;
336    uint32_t addr;
337    uint32_t size;
338    uint32_t offset;
339    struct relocation_info *relocs;
340    uint32_t nrelocs;
341    enum bool protected;
342    enum bool zerofill;
343};
344
345static void walk_pointer_list(
346    char *listname,
347    struct section_info_32 *s,
348    struct info *info,
349    void (*func)(uint32_t, struct info *));
350
351static void print_class_t(
352    uint32_t p,
353    struct info *info);
354
355static void print_class_ro_t(
356    uint32_t p,
357    struct info *info,
358    enum bool *is_meta_class);
359
360static void print_layout_map(
361    uint32_t p,
362    struct info *info);
363
364static void print_method_list_t(
365    uint32_t p,
366    struct info *info,
367    char *indent);
368
369static void print_ivar_list_t(
370    uint32_t p,
371    struct info *info);
372
373static void print_protocol_list_t(
374    uint32_t p,
375    struct info *info);
376
377static void print_objc_property_list(
378    uint32_t p,
379    struct info *info);
380
381static void print_category_t(
382    uint32_t p,
383    struct info *info);
384
385static void print_message_refs(
386    struct section_info_32 *s,
387    struct info *info);
388
389static void print_image_info(
390    struct section_info_32 *s,
391    struct info *info);
392
393static void get_sections_32(
394    struct load_command *load_commands,
395    uint32_t ncmds,
396    uint32_t sizeofcmds,
397    enum byte_sex object_byte_sex,
398    char *object_addr,
399    uint32_t object_size,
400    struct section_info_32 **sections,
401    uint32_t *nsections,
402    uint32_t *database);
403
404static struct section_info_32 *get_section_32(
405    struct section_info_32 *sections,
406    uint32_t nsections,
407    char *segname,
408    char *sectname);
409
410static void *get_pointer_32(
411    uint32_t p,
412    uint32_t *offset,
413    uint32_t *left,
414    struct section_info_32 **s,
415    struct section_info_32 *sections,
416    uint32_t nsections);
417
418static const char *get_symbol_32(
419    uint32_t sect_offset,
420    uint32_t database_offset,
421    uint64_t value,
422    struct relocation_info *relocs,
423    uint32_t nrelocs,
424    struct info *info);
425
426/*
427 * Print the objc2 meta data in 32-bit Mach-O files.
428 */
429void
430print_objc2_32bit(
431cpu_type_t cputype,
432struct load_command *load_commands,
433uint32_t ncmds,
434uint32_t sizeofcmds,
435enum byte_sex object_byte_sex,
436char *object_addr,
437uint32_t object_size,
438struct nlist *symbols,
439uint32_t nsymbols,
440char *strings,
441uint32_t strings_size,
442struct symbol *sorted_symbols,
443uint32_t nsorted_symbols,
444struct relocation_info *ext_relocs,
445uint32_t next_relocs,
446struct relocation_info *loc_relocs,
447uint32_t nloc_relocs,
448enum bool verbose)
449{
450    struct section_info_32 *s;
451    struct info info;
452
453	info.host_byte_sex = get_host_byte_sex();
454	info.swapped = info.host_byte_sex != object_byte_sex;
455	info.cputype = cputype;
456	info.symbols = symbols;
457	info.nsymbols = nsymbols;
458	info.strings = strings;
459	info.strings_size = strings_size;
460	info.sorted_symbols = sorted_symbols;
461	info.nsorted_symbols = nsorted_symbols;
462	info.ext_relocs = ext_relocs;
463	info.next_relocs = next_relocs;
464	info.loc_relocs = loc_relocs;
465	info.nloc_relocs = nloc_relocs;
466	info.verbose = verbose;
467	get_sections_32(load_commands, ncmds, sizeofcmds, object_byte_sex,
468			object_addr, object_size, &info.sections,
469			&info.nsections, &info.database);
470
471	s = get_section_32(info.sections, info.nsections,
472				"__OBJC2", "__class_list");
473	if(s == NULL)
474	    s = get_section_32(info.sections, info.nsections,
475				"__DATA", "__objc_classlist");
476	walk_pointer_list("class", s, &info, print_class_t);
477
478	s = get_section_32(info.sections, info.nsections,
479				"__OBJC2", "__class_refs");
480	if(s == NULL)
481	    s = get_section_32(info.sections, info.nsections,
482				"__DATA", "__objc_classrefs");
483	walk_pointer_list("class refs", s, &info, NULL);
484
485	s = get_section_32(info.sections, info.nsections,
486				"__OBJC2", "__super_refs");
487	if(s == NULL)
488	    s = get_section_32(info.sections, info.nsections,
489				"__DATA", "__objc_superrefs");
490	walk_pointer_list("super refs", s, &info, NULL);
491
492	s = get_section_32(info.sections, info.nsections,
493				"__OBJC2", "__category_list");
494	if(s == NULL)
495	    s = get_section_32(info.sections, info.nsections,
496				"__DATA", "__objc_catlist");
497	walk_pointer_list("category", s, &info, print_category_t);
498
499	s = get_section_32(info.sections, info.nsections,
500				"__OBJC2", "__protocol_list");
501	if(s == NULL)
502	    s = get_section_32(info.sections, info.nsections,
503				"__DATA", "__objc_protolist");
504	walk_pointer_list("protocol", s, &info, NULL);
505
506	s = get_section_32(info.sections, info.nsections,
507				"__OBJC2", "__message_refs");
508	if(s == NULL)
509	    s = get_section_32(info.sections, info.nsections,
510				"__DATA", "__objc_msgrefs");
511	print_message_refs(s, &info);
512
513	s = get_section_32(info.sections, info.nsections,
514				"__OBJC", "__image_info");
515	if(s == NULL)
516	    s = get_section_32(info.sections, info.nsections,
517				"__DATA", "__objc_imageinfo");
518	print_image_info(s, &info);
519}
520
521static
522void
523walk_pointer_list(
524char *listname,
525struct section_info_32 *s,
526struct info *info,
527void (*func)(uint32_t, struct info *))
528{
529    uint32_t i, size, left;
530    uint32_t p;
531    const char *name;
532
533	if(s == NULL)
534	    return;
535
536	printf("Contents of (%.16s,%.16s) section\n", s->segname, s->sectname);
537	for(i = 0; i < s->size; i += sizeof(uint32_t)){
538
539	    memset(&p, '\0', sizeof(uint32_t));
540	    left = s->size - i;
541	    size = left < sizeof(uint32_t) ?
542		   left : sizeof(uint32_t);
543	    memcpy(&p, s->contents + i, size);
544
545	    if(i + sizeof(uint32_t) > s->size)
546		printf("%s list pointer extends past end of (%.16s,%.16s) "
547		       "section\n", listname, s->segname, s->sectname);
548	    printf("%08x ", s->addr + i);
549
550	    if(info->swapped)
551		p = SWAP_INT(p);
552	    printf("0x%x", p);
553
554	    name = get_symbol_32(i, s->addr - info->database, p,
555			         s->relocs, s->nrelocs, info);
556	    if(name != NULL)
557		printf(" %s\n", name);
558	    else
559		printf("\n");
560	    if(func != NULL)
561		func(p, info);
562	}
563}
564
565static
566void
567print_class_t(
568uint32_t p,
569struct info *info)
570{
571    struct class_t c;
572    void *r;
573    uint32_t offset, left;
574    struct section_info_32 *s;
575    const char *name;
576    enum bool is_meta_class;
577
578	is_meta_class = FALSE;
579	r = get_pointer_32(p, &offset, &left, &s,
580			   info->sections, info->nsections);
581	if(r == NULL)
582	    return;
583	memset(&c, '\0', sizeof(struct class_t));
584	if(left < sizeof(struct class_t)){
585	    memcpy(&c, r, left);
586	    printf("   (class_t entends past the end of the section)\n");
587	}
588	else
589	    memcpy(&c, r, sizeof(struct class_t));
590	if(info->swapped)
591	    swap_class_t(&c, info->host_byte_sex);
592	printf("           isa 0x%x", c.isa);
593	name = get_symbol_32(offset + offsetof(struct class_t, isa),
594			     s->addr - info->database, c.isa, s->relocs,
595			     s->nrelocs, info);
596	if(name != NULL)
597	    printf(" %s\n", name);
598	else
599	    printf("\n");
600	printf("    superclass 0x%x", c.superclass);
601	name = get_symbol_32(offset + offsetof(struct class_t, superclass),
602			     s->addr - info->database, c.superclass, s->relocs,
603			     s->nrelocs, info);
604	if(name != NULL)
605	    printf(" %s\n", name);
606	else
607	    printf("\n");
608	printf("         cache 0x%x", c.cache);
609	name = get_symbol_32(offset + offsetof(struct class_t, cache),
610			     s->addr - info->database, c.cache, s->relocs,
611			     s->nrelocs, info);
612	if(name != NULL)
613	    printf(" %s\n", name);
614	else
615	    printf("\n");
616	printf("        vtable 0x%x", c.vtable);
617	name = get_symbol_32(offset + offsetof(struct class_t, vtable),
618			     s->addr - info->database, c.vtable, s->relocs,
619			     s->nrelocs, info);
620	if(name != NULL)
621	    printf(" %s\n", name);
622	else
623	    printf("\n");
624	printf("          data 0x%x (struct class_ro_t *)\n", c.data);
625	print_class_ro_t(c.data, info, &is_meta_class);
626
627	if(! is_meta_class)
628	    {
629		printf("Meta Class\n");
630		print_class_t(c.isa, info);
631	    }
632}
633
634static
635void
636print_class_ro_t(
637uint32_t p,
638struct info *info,
639enum bool *is_meta_class)
640{
641    struct class_ro_t cro;
642    void *r;
643    uint32_t offset, left;
644    struct section_info_32 *s;
645    const char *name;
646
647	r = get_pointer_32(p, &offset, &left, &s, info->sections,
648			   info->nsections);
649	if(r == NULL)
650	    return;
651	memset(&cro, '\0', sizeof(struct class_ro_t));
652	if(left < sizeof(struct class_ro_t)){
653	    memcpy(&cro, r, left);
654	    printf("   (class_ro_t entends past the end of the section)\n");
655	}
656	else
657	    memcpy(&cro, r, sizeof(struct class_ro_t));
658	if(info->swapped)
659	    swap_class_ro_t(&cro, info->host_byte_sex);
660	printf("                    flags 0x%x", cro.flags);
661	if(cro.flags & RO_META)
662	    printf(" RO_META");
663	if(cro.flags & RO_ROOT)
664	    printf(" RO_ROOT");
665	if(cro.flags & RO_HAS_CXX_STRUCTORS)
666	    printf(" RO_HAS_CXX_STRUCTORS");
667	printf("\n");
668	printf("            instanceStart %u\n", cro.instanceStart);
669	printf("             instanceSize %u\n", cro.instanceSize);
670	printf("               ivarLayout 0x%x\n", cro.ivarLayout);
671	print_layout_map(cro.ivarLayout, info);
672	printf("                     name 0x%x", cro.name);
673	name = get_pointer_32(cro.name, NULL, &left, NULL, info->sections,
674			      info->nsections);
675	if(name != NULL)
676	    printf(" %.*s\n", (int)left, name);
677	else
678	    printf("\n");
679	printf("              baseMethods 0x%x (struct method_list_t *)\n",
680	       cro.baseMethods);
681	if(cro.baseMethods != 0)
682	    print_method_list_t(cro.baseMethods, info, "");
683	printf("            baseProtocols 0x%x\n", cro.baseProtocols);
684	if(cro.baseProtocols != 0)
685	    print_protocol_list_t(cro.baseProtocols, info);
686	printf("                    ivars 0x%x\n", cro.ivars);
687	if(cro.ivars != 0)
688	    print_ivar_list_t(cro.ivars, info);
689	printf("           weakIvarLayout 0x%x\n", cro.weakIvarLayout);
690	print_layout_map(cro.weakIvarLayout, info);
691	printf("           baseProperties 0x%x\n", cro.baseProperties);
692	if(cro.baseProperties != 0)
693	    print_objc_property_list(cro.baseProperties, info);
694	if (is_meta_class)
695	    *is_meta_class = (cro.flags & RO_META) ? TRUE : FALSE;
696}
697
698static
699void
700print_layout_map(
701uint32_t p,
702struct info *info)
703{
704    uint32_t offset, left;
705    struct section_info_32 *s;
706    char *layout_map;
707
708	if(p == 0)
709	    return;
710	layout_map = get_pointer_32(p, &offset, &left, &s,
711				    info->sections, info->nsections);
712	if(layout_map != NULL){
713	    printf("                layout map: ");
714	    do{
715		printf("0x%02x ", (*layout_map) & 0xff);
716		left--;
717		layout_map++;
718	    }while(*layout_map != '\0' && left != 0);
719	    printf("\n");
720	}
721}
722
723static
724void
725print_method_list_t(
726uint32_t p,
727struct info *info,
728char *indent)
729{
730    struct method_list_t ml;
731    struct method_t m;
732    void *r;
733    uint32_t offset, left, i;
734    struct section_info_32 *s;
735    const char *name;
736
737	r = get_pointer_32(p, &offset, &left, &s, info->sections,
738			   info->nsections);
739	if(r == NULL)
740	    return;
741	memset(&ml, '\0', sizeof(struct method_list_t));
742	if(left < sizeof(struct method_list_t)){
743	    memcpy(&ml, r, left);
744	    printf("%s   (method_list_t entends past the end of the "
745		   "section)\n", indent);
746	}
747	else
748	    memcpy(&ml, r, sizeof(struct method_list_t));
749	if(info->swapped)
750	    swap_method_list_t(&ml, info->host_byte_sex);
751	printf("%s\t\t   entsize %u\n", indent, ml.entsize);
752	printf("%s\t\t     count %u\n", indent, ml.count);
753
754	p += sizeof(struct method_list_t);
755	offset += sizeof(struct method_list_t);
756	for(i = 0; i < ml.count; i++){
757	    r = get_pointer_32(p, &offset, &left, &s, info->sections,
758			       info->nsections);
759	    if(r == NULL)
760		return;
761	    memset(&m, '\0', sizeof(struct method_t));
762	    if(left < sizeof(struct method_t)){
763		memcpy(&m, r, left);
764		printf("%s   (method_t entends past the end of the "
765		       "section)\n", indent);
766	    }
767	    else
768		memcpy(&m, r, sizeof(struct method_t));
769	    if(info->swapped)
770		swap_method_t(&m, info->host_byte_sex);
771
772	    printf("%s\t\t      name 0x%x", indent, m.name);
773	    name = get_pointer_32(m.name, NULL, &left, NULL, info->sections,
774				  info->nsections);
775	    if(name != NULL)
776		printf(" %.*s\n", (int)left, name);
777	    else
778		printf("\n");
779	    printf("%s\t\t     types 0x%x", indent, m.types);
780	    name = get_pointer_32(m.types, NULL, &left, NULL, info->sections,
781				  info->nsections);
782	    if(name != NULL)
783		printf(" %.*s\n", (int)left, name);
784	    else
785		printf("\n");
786	    printf("%s\t\t       imp 0x%x", indent, m.imp);
787	    name = get_symbol_32(offset + offsetof(struct method_t, imp),
788				 s->addr - info->database, m.imp, s->relocs,
789				 s->nrelocs, info);
790	    if(name != NULL)
791		printf(" %s\n", name);
792	    else
793		printf("\n");
794
795	    p += sizeof(struct method_t);
796	    offset += sizeof(struct method_t);
797	}
798}
799
800static
801void
802print_ivar_list_t(
803uint32_t p,
804struct info *info)
805{
806    struct ivar_list_t il;
807    struct ivar_t i;
808    void *r;
809    uint32_t offset, left, j;
810    struct section_info_32 *s;
811    const char *name;
812    uint32_t *ivar_offset_p, ivar_offset;
813
814	r = get_pointer_32(p, &offset, &left, &s, info->sections,
815			   info->nsections);
816	if(r == NULL)
817	    return;
818	memset(&il, '\0', sizeof(struct ivar_list_t));
819	if(left < sizeof(struct ivar_list_t)){
820	    memcpy(&il, r, left);
821	    printf("   (ivar_list_t entends past the end of the section)\n");
822	}
823	else
824	    memcpy(&il, r, sizeof(struct ivar_list_t));
825	if(info->swapped)
826	    swap_ivar_list_t(&il, info->host_byte_sex);
827	printf("                    entsize %u\n", il.entsize);
828	printf("                      count %u\n", il.count);
829
830	p += sizeof(struct ivar_list_t);
831	offset += sizeof(struct ivar_list_t);
832	for(j = 0; j < il.count; j++){
833	    r = get_pointer_32(p, &offset, &left, &s, info->sections,
834			       info->nsections);
835	    if(r == NULL)
836		return;
837	    memset(&i, '\0', sizeof(struct ivar_t));
838	    if(left < sizeof(struct ivar_t)){
839		memcpy(&i, r, left);
840		printf("   (ivar_t entends past the end of the section)\n");
841	    }
842	    else
843		memcpy(&i, r, sizeof(struct ivar_t));
844	    if(info->swapped)
845		swap_ivar_t(&i, info->host_byte_sex);
846
847	    printf("\t\t\t   offset 0x%x", i.offset);
848	    ivar_offset_p = get_pointer_32(i.offset, NULL, &left, NULL,
849					   info->sections, info->nsections);
850	    if(ivar_offset_p != NULL && left >= sizeof(*ivar_offset_p)){
851		memcpy(&ivar_offset, ivar_offset_p, sizeof(ivar_offset));
852		if(info->swapped)
853		    ivar_offset = SWAP_INT(ivar_offset);
854		printf(" %u\n", ivar_offset);
855            }
856	    else
857		printf("\n");
858
859	    printf("\t\t\t     name 0x%x", i.name);
860	    name = get_pointer_32(i.name, NULL, &left, NULL, info->sections,
861				  info->nsections);
862	    if(name != NULL)
863		printf(" %.*s\n", (int)left, name);
864	    else
865		printf("\n");
866	    printf("\t\t\t     type 0x%x", i.type);
867	    name = get_pointer_32(i.type, NULL, &left, NULL, info->sections,
868				  info->nsections);
869	    if(name != NULL)
870		printf(" %.*s\n", (int)left, name);
871	    else
872		printf("\n");
873	    printf("\t\t\talignment %u\n", i.alignment);
874	    printf("\t\t\t     size %u\n", i.size);
875
876	    p += sizeof(struct ivar_t);
877	    offset += sizeof(struct ivar_t);
878	}
879}
880
881static
882void
883print_protocol_list_t(
884uint32_t p,
885struct info *info)
886{
887    struct protocol_list_t pl;
888    uint32_t q;
889    struct protocol_t pc;
890    void *r;
891    uint32_t offset, left, i;
892    struct section_info_32 *s;
893    const char *name;
894
895	r = get_pointer_32(p, &offset, &left, &s, info->sections,
896			   info->nsections);
897	if(r == NULL)
898	    return;
899	memset(&pl, '\0', sizeof(struct protocol_list_t));
900	if(left < sizeof(struct protocol_list_t)){
901	    memcpy(&pl, r, left);
902	    printf("   (protocol_list_t entends past the end of the "
903		   "section)\n");
904	}
905	else
906	    memcpy(&pl, r, sizeof(struct protocol_list_t));
907	if(info->swapped)
908	    swap_protocol_list_t(&pl, info->host_byte_sex);
909	printf("                      count %u\n", pl.count);
910
911	p += sizeof(struct protocol_list_t);
912	offset += sizeof(struct protocol_list_t);
913	for(i = 0; i < pl.count; i++){
914	    r = get_pointer_32(p, &offset, &left, &s, info->sections,
915			       info->nsections);
916	    if(r == NULL)
917		return;
918	    q = 0;
919	    if(left < sizeof(uint32_t)){
920		memcpy(&q, r, left);
921		printf("   (protocol_t * entends past the end of the "
922		       "section)\n");
923	    }
924	    else
925		memcpy(&q, r, sizeof(uint32_t));
926	    if(info->swapped)
927		q = SWAP_INT(q);
928	    printf("\t\t      list[%u] 0x%x (struct protocol_t *)\n", i, q);
929
930	    r = get_pointer_32(q, &offset, &left, &s, info->sections,
931			       info->nsections);
932	    if(r == NULL)
933		return;
934	    memset(&pc, '\0', sizeof(struct protocol_t));
935	    if(left < sizeof(struct protocol_t)){
936		memcpy(&pc, r, left);
937		printf("   (protocol_t entends past the end of the section)\n");
938	    }
939	    else
940		memcpy(&pc, r, sizeof(struct protocol_t));
941	    if(info->swapped)
942		swap_protocol_t(&pc, info->host_byte_sex);
943
944	    printf("\t\t\t      isa 0x%x\n", pc.isa);
945	    printf("\t\t\t     name 0x%x", pc.name);
946	    name = get_pointer_32(pc.name, NULL, &left, NULL, info->sections,
947				  info->nsections);
948	    if(name != NULL)
949		printf(" %.*s\n", (int)left, name);
950	    else
951		printf("\n");
952	    printf("\t\t\tprotocols 0x%x\n", pc.protocols);
953	    printf("\t\t  instanceMethods 0x%x (struct method_list_t *)\n",
954		   pc.instanceMethods);
955	    if(pc.instanceMethods != 0)
956		print_method_list_t(pc.instanceMethods, info, "\t");
957	    printf("\t\t     classMethods 0x%x (struct method_list_t *)\n",
958		   pc.classMethods);
959	    if(pc.classMethods != 0)
960		print_method_list_t(pc.classMethods, info, "\t");
961	    printf("\t  optionalInstanceMethods 0x%x\n",
962		   pc.optionalInstanceMethods);
963	    printf("\t     optionalClassMethods 0x%x\n",
964		   pc.optionalClassMethods);
965	    printf("\t       instanceProperties 0x%x\n",
966		   pc.instanceProperties);
967
968	    p += sizeof(uint32_t);
969	    offset += sizeof(uint32_t);
970	}
971}
972
973static
974void
975print_objc_property_list(
976uint32_t p,
977struct info *info)
978{
979    struct objc_property_list opl;
980    struct objc_property op;
981    void *r;
982    uint32_t offset, left, j;
983    struct section_info_32 *s;
984    const char *name;
985
986	r = get_pointer_32(p, &offset, &left, &s, info->sections,
987			   info->nsections);
988	if(r == NULL)
989	    return;
990	memset(&opl, '\0', sizeof(struct objc_property_list));
991	if(left < sizeof(struct objc_property_list)){
992	    memcpy(&opl, r, left);
993	    printf("   (objc_property_list entends past the end of the "
994		   "section)\n");
995	}
996	else
997	    memcpy(&opl, r, sizeof(struct objc_property_list));
998	if(info->swapped)
999	    swap_objc_property_list(&opl, info->host_byte_sex);
1000	printf("                    entsize %u\n", opl.entsize);
1001	printf("                      count %u\n", opl.count);
1002
1003	p += sizeof(struct objc_property_list);
1004	offset += sizeof(struct objc_property_list);
1005	for(j = 0; j < opl.count; j++){
1006	    r = get_pointer_32(p, &offset, &left, &s, info->sections,
1007			       info->nsections);
1008	    if(r == NULL)
1009		return;
1010	    memset(&op, '\0', sizeof(struct objc_property));
1011	    if(left < sizeof(struct objc_property)){
1012		memcpy(&op, r, left);
1013		printf("   (objc_property entends past the end of the "
1014		       "section)\n");
1015	    }
1016	    else
1017		memcpy(&op, r, sizeof(struct objc_property));
1018	    if(info->swapped)
1019		swap_objc_property(&op, info->host_byte_sex);
1020
1021	    printf("\t\t\t     name 0x%x", op.name);
1022	    name = get_pointer_32(op.name, NULL, &left, NULL, info->sections,
1023				  info->nsections);
1024	    if(name != NULL)
1025		printf(" %.*s\n", (int)left, name);
1026	    else
1027		printf("\n");
1028	    printf("\t\t\tattributes x%x", op.attributes);
1029	    name = get_pointer_32(op.attributes, NULL, &left, NULL,
1030				  info->sections, info->nsections);
1031	    if(name != NULL)
1032		printf(" %.*s\n", (int)left, name);
1033	    else
1034		printf("\n");
1035
1036	    p += sizeof(struct objc_property);
1037	    offset += sizeof(struct objc_property);
1038	}
1039}
1040
1041static
1042void
1043print_category_t(
1044uint32_t p,
1045struct info *info)
1046{
1047    struct category_t c;
1048    void *r;
1049    uint32_t offset, left;
1050    struct section_info_32 *s;
1051    const char *name;
1052
1053	r = get_pointer_32(p, &offset, &left, &s,
1054			   info->sections, info->nsections);
1055	if(r == NULL)
1056	    return;
1057	memset(&c, '\0', sizeof(struct category_t));
1058	if(left < sizeof(struct category_t)){
1059	    memcpy(&c, r, left);
1060	    printf("   (category_t entends past the end of the section)\n");
1061	}
1062	else
1063	    memcpy(&c, r, sizeof(struct category_t));
1064	if(info->swapped)
1065	    swap_category_t(&c, info->host_byte_sex);
1066	printf("              name 0x%x", c.name);
1067	name = get_symbol_32(offset + offsetof(struct category_t, name),
1068			     s->addr - info->database, c.name, s->relocs,
1069			     s->nrelocs, info);
1070	if(name != NULL)
1071	    printf(" %s\n", name);
1072	else
1073	    printf("\n");
1074	printf("               cls 0x%x\n", c.cls);
1075	if(c.cls != 0)
1076	    print_class_t(c.cls, info);
1077	printf("   instanceMethods 0x%x\n", c.instanceMethods);
1078	if(c.instanceMethods != 0)
1079	    print_method_list_t(c.instanceMethods, info, "");
1080	printf("      classMethods 0x%x\n", c.classMethods);
1081	if(c.classMethods != 0)
1082	    print_method_list_t(c.classMethods, info, "");
1083	printf("         protocols 0x%x\n", c.protocols);
1084	if(c.protocols != 0)
1085	    print_protocol_list_t(c.protocols, info);
1086	printf("instanceProperties 0x%x\n", c.instanceProperties);
1087	if(c.instanceProperties)
1088	    print_objc_property_list(c.instanceProperties, info);
1089}
1090
1091static
1092void
1093print_message_refs(
1094struct section_info_32 *s,
1095struct info *info)
1096{
1097    uint32_t i, left, offset;
1098    uint32_t p;
1099    struct message_ref mr;
1100    const char *name;
1101    void *r;
1102
1103	if(s == NULL)
1104	    return;
1105
1106	printf("Contents of (%.16s,%.16s) section\n", s->segname, s->sectname);
1107	offset = 0;
1108	for(i = 0; i < s->size; i += sizeof(struct message_ref)){
1109	    p = s->addr + i;
1110	    r = get_pointer_32(p, &offset, &left, &s,
1111			       info->sections, info->nsections);
1112	    if(r == NULL)
1113		return;
1114	    memset(&mr, '\0', sizeof(struct message_ref));
1115	    if(left < sizeof(struct message_ref)){
1116		memcpy(&mr, r, left);
1117		printf(" (message_ref entends past the end of the section)\n");
1118	    }
1119	    else
1120		memcpy(&mr, r, sizeof(struct message_ref));
1121	    if(info->swapped)
1122		swap_message_ref(&mr, info->host_byte_sex);
1123	    printf("  imp 0x%x", mr.imp);
1124	    name = get_symbol_32(offset + offsetof(struct message_ref, imp),
1125				 s->addr - info->database, mr.imp, s->relocs,
1126				 s->nrelocs, info);
1127	    if(name != NULL)
1128		printf(" %s\n", name);
1129	    else
1130		printf("\n");
1131	    printf("  sel 0x%x", mr.sel);
1132	    name = get_pointer_32(mr.sel, NULL, &left, NULL, info->sections,
1133				  info->nsections);
1134	    if(name != NULL)
1135		printf(" %.*s\n", (int)left, name);
1136	    else
1137		printf("\n");
1138	    offset += sizeof(struct message_ref);
1139	}
1140}
1141
1142static
1143void
1144print_image_info(
1145struct section_info_32 *s,
1146struct info *info)
1147{
1148    uint32_t left, offset;
1149    uint32_t p;
1150    struct objc_image_info o;
1151    void *r;
1152
1153	if(s == NULL)
1154	    return;
1155
1156	printf("Contents of (%.16s,%.16s) section\n", s->segname, s->sectname);
1157	p = s->addr;
1158	r = get_pointer_32(p, &offset, &left, &s,
1159			   info->sections, info->nsections);
1160	if(r == NULL)
1161	    return;
1162	memset(&o, '\0', sizeof(struct objc_image_info));
1163	if(left < sizeof(struct objc_image_info)){
1164	    memcpy(&o, r, left);
1165	    printf(" (objc_image_info entends past the end of the section)\n");
1166	}
1167	else
1168	    memcpy(&o, r, sizeof(struct objc_image_info));
1169	if(info->swapped)
1170	    swap_objc_image_info(&o, info->host_byte_sex);
1171	printf("  version %u\n", o.version);
1172	printf("    flags 0x%x", o.flags);
1173	if(o.flags & OBJC_IMAGE_IS_REPLACEMENT)
1174	    printf(" OBJC_IMAGE_IS_REPLACEMENT");
1175	if(o.flags & OBJC_IMAGE_SUPPORTS_GC)
1176	    printf(" OBJC_IMAGE_SUPPORTS_GC");
1177	printf("\n");
1178}
1179
1180static
1181void
1182get_sections_32(
1183struct load_command *load_commands,
1184uint32_t ncmds,
1185uint32_t sizeofcmds,
1186enum byte_sex object_byte_sex,
1187char *object_addr,
1188uint32_t object_size,
1189struct section_info_32 **sections,
1190uint32_t *nsections,
1191uint32_t *database)
1192{
1193    enum byte_sex host_byte_sex;
1194    enum bool swapped, database_set, zerobased, encrypt_found, encrypt64_found;
1195
1196    uint32_t i, j, left, size;
1197    struct load_command lcmd, *lc;
1198    char *p;
1199    struct segment_command sg;
1200    struct section s;
1201    struct encryption_info_command encrypt;
1202    struct encryption_info_command_64 encrypt64;
1203
1204	host_byte_sex = get_host_byte_sex();
1205	swapped = host_byte_sex != object_byte_sex;
1206
1207	*sections = NULL;
1208	*nsections = 0;
1209	database_set = FALSE;
1210	*database = 0;
1211	zerobased = FALSE;
1212	encrypt_found = FALSE;
1213	encrypt64_found = FALSE;
1214
1215	lc = load_commands;
1216	for(i = 0 ; i < ncmds; i++){
1217	    memcpy((char *)&lcmd, (char *)lc, sizeof(struct load_command));
1218	    if(swapped)
1219		swap_load_command(&lcmd, host_byte_sex);
1220	    if(lcmd.cmdsize % sizeof(int32_t) != 0)
1221		printf("load command %u size not a multiple of "
1222		       "sizeof(int32_t)\n", i);
1223	    if((char *)lc + lcmd.cmdsize >
1224	       (char *)load_commands + sizeofcmds)
1225		printf("load command %u extends past end of load "
1226		       "commands\n", i);
1227	    left = sizeofcmds - ((char *)lc - (char *)load_commands);
1228
1229	    switch(lcmd.cmd){
1230	    case LC_SEGMENT:
1231		memset((char *)&sg, '\0', sizeof(struct segment_command));
1232		size = left < sizeof(struct segment_command) ?
1233		       left : sizeof(struct segment_command);
1234		memcpy((char *)&sg, (char *)lc, size);
1235		if(swapped)
1236		    swap_segment_command(&sg, host_byte_sex);
1237		if((sg.initprot & VM_PROT_WRITE) == VM_PROT_WRITE &&
1238		   database_set == FALSE){
1239		    *database = sg.vmaddr;
1240		    database_set = TRUE;
1241		}
1242		if((sg.initprot & VM_PROT_READ) == VM_PROT_READ &&
1243		   sg.vmaddr == 0)
1244		    zerobased = TRUE;
1245		p = (char *)lc + sizeof(struct segment_command);
1246		for(j = 0 ; j < sg.nsects ; j++){
1247		    if(p + sizeof(struct section) >
1248		       (char *)load_commands + sizeofcmds){
1249			printf("section structure command extends past "
1250			       "end of load commands\n");
1251		    }
1252		    left = sizeofcmds - (p - (char *)load_commands);
1253		    memset((char *)&s, '\0', sizeof(struct section));
1254		    size = left < sizeof(struct section) ?
1255			   left : sizeof(struct section);
1256		    memcpy((char *)&s, p, size);
1257		    if(swapped)
1258			swap_section(&s, 1, host_byte_sex);
1259
1260		    *sections = reallocate(*sections,
1261		       sizeof(struct section_info_32) * (*nsections + 1));
1262		    memcpy((*sections)[*nsections].segname,
1263			   s.segname, 16);
1264		    memcpy((*sections)[*nsections].sectname,
1265			   s.sectname, 16);
1266		    (*sections)[*nsections].addr = s.addr;
1267		    (*sections)[*nsections].contents = object_addr + s.offset;
1268		    (*sections)[*nsections].offset = s.offset;
1269		    (*sections)[*nsections].zerofill = (s.flags & SECTION_TYPE)
1270			== S_ZEROFILL ? TRUE : FALSE;
1271		    if(s.offset > object_size){
1272			printf("section contents of: (%.16s,%.16s) is past "
1273			       "end of file\n", s.segname, s.sectname);
1274			(*sections)[*nsections].size =  0;
1275		    }
1276		    else if(s.offset + s.size > object_size){
1277			printf("part of section contents of: (%.16s,%.16s) "
1278			       "is past end of file\n",
1279			       s.segname, s.sectname);
1280			(*sections)[*nsections].size = object_size - s.offset;
1281		    }
1282		    else
1283			(*sections)[*nsections].size = s.size;
1284		    if(s.reloff >= object_size){
1285			printf("relocation entries offset for (%.16s,%.16s)"
1286			       ": is past end of file\n", s.segname,
1287			       s.sectname);
1288			(*sections)[*nsections].nrelocs = 0;
1289		    }
1290		    else{
1291			(*sections)[*nsections].relocs =
1292			    (struct relocation_info *)(object_addr +
1293						       s.reloff);
1294			if(s.reloff +
1295			   s.nreloc * sizeof(struct relocation_info) >
1296							    object_size){
1297			    printf("relocation entries for section (%.16s,"
1298				   "%.16s) extends past end of file\n",
1299				   s.segname, s.sectname);
1300			    (*sections)[*nsections].nrelocs =
1301				(object_size - s.reloff) /
1302					    sizeof(struct relocation_info);
1303			}
1304			else
1305			    (*sections)[*nsections].nrelocs = s.nreloc;
1306			if(swapped)
1307			    swap_relocation_info(
1308				(*sections)[*nsections].relocs,
1309				(*sections)[*nsections].nrelocs,
1310				host_byte_sex);
1311		    }
1312		    if(sg.flags & SG_PROTECTED_VERSION_1)
1313			(*sections)[*nsections].protected = TRUE;
1314		    else
1315			(*sections)[*nsections].protected = FALSE;
1316		    (*nsections)++;
1317
1318		    if(p + sizeof(struct section) >
1319		       (char *)load_commands + sizeofcmds)
1320			break;
1321		    p += size;
1322		}
1323		break;
1324	    case LC_ENCRYPTION_INFO:
1325		memset((char *)&encrypt, '\0',
1326		       sizeof(struct encryption_info_command));
1327		size = left < sizeof(struct encryption_info_command) ?
1328		       left : sizeof(struct encryption_info_command);
1329		memcpy((char *)&encrypt, (char *)lc, size);
1330		if(swapped)
1331		    swap_encryption_command(&encrypt, host_byte_sex);
1332		encrypt_found = TRUE;
1333		break;
1334	    case LC_ENCRYPTION_INFO_64:
1335		memset((char *)&encrypt64, '\0',
1336		       sizeof(struct encryption_info_command_64));
1337		size = left < sizeof(struct encryption_info_command_64) ?
1338		       left : sizeof(struct encryption_info_command_64);
1339		memcpy((char *)&encrypt64, (char *)lc, size);
1340		if(swapped)
1341		    swap_encryption_command_64(&encrypt64, host_byte_sex);
1342		encrypt64_found = TRUE;
1343		break;
1344	    }
1345	    if(lcmd.cmdsize == 0){
1346		printf("load command %u size zero (can't advance to other "
1347		       "load commands)\n", i);
1348		break;
1349	    }
1350	    lc = (struct load_command *)((char *)lc + lcmd.cmdsize);
1351	    if((char *)lc > (char *)load_commands + sizeofcmds)
1352		break;
1353	}
1354	if(zerobased == TRUE)
1355	    *database = 0;
1356
1357	if(encrypt_found == TRUE && encrypt.cryptid != 0){
1358	    for(i = 0; i < *nsections; i++){
1359		if((*sections)[i].size > 0 && (*sections)[i].zerofill == FALSE){
1360		    if((*sections)[i].offset >
1361		       encrypt.cryptoff + encrypt.cryptsize){
1362			/* section starts past encryption area */ ;
1363		    }
1364		    else if((*sections)[i].offset + (*sections)[i].size <
1365			encrypt.cryptoff){
1366			/* section ends before encryption area */ ;
1367		    }
1368		    else{
1369			/* section has part in the encrypted area */
1370			(*sections)[i].protected = TRUE;
1371		    }
1372		}
1373	    }
1374	}
1375	if(encrypt64_found == TRUE && encrypt64.cryptid != 0){
1376	    for(i = 0; i < *nsections; i++){
1377		if((*sections)[i].size > 0 && (*sections)[i].zerofill == FALSE){
1378		    if((*sections)[i].offset >
1379		       encrypt64.cryptoff + encrypt64.cryptsize){
1380			/* section starts past encryption area */ ;
1381		    }
1382		    else if((*sections)[i].offset + (*sections)[i].size <
1383			encrypt64.cryptoff){
1384			/* section ends before encryption area */ ;
1385		    }
1386		    else{
1387			/* section has part in the encrypted area */
1388			(*sections)[i].protected = TRUE;
1389		    }
1390		}
1391	    }
1392	}
1393}
1394
1395static
1396struct section_info_32 *
1397get_section_32(
1398struct section_info_32 *sections,
1399uint32_t nsections,
1400char *segname,
1401char *sectname)
1402{
1403    uint32_t i;
1404
1405	for(i = 0; i < nsections; i++){
1406	    if(strncmp(sections[i].segname, segname, 16) == 0 &&
1407	       strncmp(sections[i].sectname, sectname, 16) == 0){
1408		return(sections + i);
1409	    }
1410	}
1411	return(NULL);
1412}
1413
1414static
1415void *
1416get_pointer_32(
1417uint32_t p,
1418uint32_t *offset,
1419uint32_t *left,
1420struct section_info_32 **s,
1421struct section_info_32 *sections,
1422uint32_t nsections)
1423{
1424    void *r;
1425    uint32_t addr;
1426    uint32_t i;
1427
1428	addr = p;
1429	for(i = 0; i < nsections; i++){
1430	    if(addr >= sections[i].addr &&
1431	       addr < sections[i].addr + sections[i].size){
1432		if(s != NULL)
1433		    *s = sections + i;
1434		if(offset != NULL)
1435		    *offset = addr - sections[i].addr;
1436		if(left != NULL)
1437		    *left = sections[i].size - (addr - sections[i].addr);
1438		if(sections[i].protected == TRUE)
1439		    r = "some string from a protected section";
1440		else
1441		    r = sections[i].contents + (addr - sections[i].addr);
1442		return(r);
1443	    }
1444	}
1445	if(s != NULL)
1446	    *s = NULL;
1447	if(offset != NULL)
1448	    *offset = 0;
1449	if(left != NULL)
1450	    *left = 0;
1451	return(NULL);
1452}
1453
1454/*
1455 * get_symbol() returns the name of a symbol (or NULL). Based on the relocation
1456 * information at the specified section offset or the value.
1457 */
1458static
1459const char *
1460get_symbol_32(
1461uint32_t sect_offset,
1462uint32_t database_offset,
1463uint64_t value,
1464struct relocation_info *relocs,
1465uint32_t nrelocs,
1466struct info *info)
1467{
1468    uint32_t i;
1469    unsigned int r_symbolnum;
1470    uint32_t n_strx;
1471
1472	if(info->verbose == FALSE)
1473	    return(NULL);
1474
1475	for(i = 0; i < nrelocs; i++){
1476	    if((uint32_t)relocs[i].r_address == sect_offset){
1477		r_symbolnum = relocs[i].r_symbolnum;
1478		if(relocs[i].r_extern){
1479		    if(r_symbolnum >= info->nsymbols)
1480			break;
1481		    n_strx = info->symbols[r_symbolnum].n_un.n_strx;
1482		    if(n_strx <= 0 || n_strx >= info->strings_size)
1483			break;
1484		    return(info->strings + n_strx);
1485		}
1486		break;
1487	    }
1488	    if(reloc_has_pair(info->cputype, relocs[i].r_type) == TRUE)
1489		i++;
1490	}
1491	for(i = 0; i < info->next_relocs; i++){
1492	    if((uint32_t)info->ext_relocs[i].r_address ==
1493		database_offset + sect_offset){
1494		r_symbolnum = info->ext_relocs[i].r_symbolnum;
1495		if(info->ext_relocs[i].r_extern){
1496		    if(r_symbolnum >= info->nsymbols)
1497			break;
1498		    n_strx = info->symbols[r_symbolnum].n_un.n_strx;
1499		    if(n_strx <= 0 || n_strx >= info->strings_size)
1500			break;
1501		    return(info->strings + n_strx);
1502		}
1503		break;
1504	    }
1505	    if(reloc_has_pair(info->cputype, info->ext_relocs[i].r_type) ==TRUE)
1506		i++;
1507	}
1508	return(guess_symbol(value, info->sorted_symbols, info->nsorted_symbols,
1509			    info->verbose));
1510}
1511