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#define __darwin_i386_exception_state i386_exception_state
32#define __darwin_i386_float_state i386_float_state
33#define __darwin_i386_thread_state i386_thread_state
34
35#ifndef RLD
36#ifdef SHLIB
37#include "shlib.h"
38#endif
39#include <libc.h>
40#include <mach/mach.h>
41#include "stuff/openstep_mach.h"
42#include <stddef.h>
43#include <stdarg.h>
44#include <limits.h>
45#include <errno.h>
46#include <ctype.h>
47#include <ar.h>
48#include <sys/file.h>
49#include <sys/types.h>
50#include <sys/mman.h>
51#include <mach-o/fat.h>
52#include <mach-o/loader.h>
53#import <mach/m68k/thread_status.h>
54#import <mach/ppc/thread_status.h>
55#undef MACHINE_THREAD_STATE     /* need to undef these to avoid warnings */
56#undef MACHINE_THREAD_STATE_COUNT
57#undef THREAD_STATE_NONE
58#undef VALID_THREAD_STATE_FLAVOR
59#import <mach/m88k/thread_status.h>
60#import <mach/i860/thread_status.h>
61#import <mach/i386/thread_status.h>
62#import <mach/sparc/thread_status.h>
63#import <mach/arm/thread_status.h>
64#include <mach-o/nlist.h>
65#include <mach-o/reloc.h>
66#include "stuff/bool.h"
67#ifdef OFI
68#include <mach-o/dyld.h>
69#else
70#include "stuff/lto.h"
71#endif
72#include "stuff/bytesex.h"
73#include "stuff/arch.h"
74#include "stuff/rnd.h"
75#include "stuff/errors.h"
76#include "stuff/allocate.h"
77#include "stuff/ofile.h"
78#include "stuff/print.h"
79
80#ifdef OTOOL
81#undef ALIGNMENT_CHECKS
82#include "otool.h"
83#include "ofile_print.h"
84static enum bool otool_first_ofile_map = TRUE;
85#else /* !define(OTOOL) */
86
87#if (!defined(m68k) && !defined(__i386__) && !defined(__x86_64__) && !defined(__ppc__) && !defined(__arm__))
88#define ALIGNMENT_CHECKS_ARCHIVE_64_BIT
89static enum bool archive_64_bit_align_warning = FALSE;
90#endif /* (!defined(m68k) && !defined(__i386__) && !defined(__x86_64__) && !defined(__ppc__) && !defined(__arm__)) */
91
92#endif /* OTOOL */
93
94/* <mach/loader.h> */
95/* The maximum section alignment allowed to be specified, as a power of two */
96#define MAXSECTALIGN		15 /* 2**15 or 0x8000 */
97
98enum check_type {
99    CHECK_BAD,
100    CHECK_GOOD
101};
102
103#ifndef OTOOL
104struct element {
105    uint32_t offset;
106    uint32_t size;
107    char *name;
108    struct element *next;
109};
110#endif /* !defined(OTOOL) */
111
112static enum bool ofile_specific_arch(
113    struct ofile *ofile,
114    uint32_t narch);
115static enum check_type check_fat(
116    struct ofile *ofile);
117static enum check_type check_fat_object_in_archive(
118    struct ofile *ofile);
119static enum check_type check_archive(
120    struct ofile *ofile,
121    enum bool archives_with_fat_objects);
122static enum check_type check_extend_format_1(
123    struct ofile *ofile,
124    struct ar_hdr *ar_hdr,
125    uint32_t size_left,
126    uint32_t *member_name_size);
127static enum check_type check_archive_toc(
128    struct ofile *ofile);
129static enum check_type check_Mach_O(
130    struct ofile *ofile);
131static void swap_back_Mach_O(
132    struct ofile *ofile);
133#ifndef OTOOL
134static enum check_type check_overlaping_element(
135    struct ofile *ofile,
136    struct element *head,
137    uint32_t offset,
138    uint32_t size,
139    char *name);
140static void free_elements(
141    struct element *head);
142#endif /* !defined(OTOOL) */
143static enum check_type check_dylib_module(
144    struct ofile *ofile,
145    struct symtab_command *st,
146    struct dysymtab_command *dyst,
147    char *strings,
148    uint32_t module_index);
149
150#ifndef OTOOL
151#if defined(ALIGNMENT_CHECKS) || defined(ALIGNMENT_CHECKS_ARCHIVE_64_BIT)
152static
153void
154temporary_archive_member_warning(
155struct ofile *ofile,
156const char *format, ...)
157{
158    va_list ap;
159
160	va_start(ap, format);
161	if(ofile->file_type == OFILE_FAT){
162	    print("%s: for architecture %s archive member: %s(%.*s) ",
163		  progname, ofile->arch_flag.name, ofile->file_name,
164		  (int)ofile->member_name_size, ofile->member_name);
165	}
166	else{
167	    print("%s: archive member: %s(%.*s) ", progname, ofile->file_name,
168		  (int)ofile->member_name_size, ofile->member_name);
169	}
170	vprint(format, ap);
171        print("\n");
172	va_end(ap);
173}
174#endif /* defined(ALIGNMENT_CHECKS) */
175#endif /* !defined(OTOOL) */
176
177#ifndef OFI
178/*
179 * ofile_process() processes the specified file name can calls the routine
180 * processor on the ofiles in it.  arch_flags is an array of architectures
181 * containing narch_flags which are the only architectures to process if
182 * narch_flags is non-zero.  If all_archs is TRUE then all architectures of
183 * the specified file are processed.  The specified file name can be of the
184 * form "archive(member)" which is taken to mean that member in that archive
185 * (or that module of a dynamic library if dylib_flat is not FALSE).
186 * For each ofile that is to be processed the routine processor is called with
187 * the corresponding ofile struct, the arch_name pass to it is either NULL or
188 * an architecture name (when it should be printed or show by processor) and
189 * cookie is the same value as passed to ofile_process.
190 */
191__private_extern__
192void
193ofile_process(
194char *name,
195struct arch_flag *arch_flags,
196uint32_t narch_flags,
197enum bool all_archs,
198enum bool process_non_objects,
199enum bool dylib_flat,
200enum bool use_member_syntax,
201void (*processor)(struct ofile *ofile, char *arch_name, void *cookie),
202void *cookie)
203{
204    char *member_name, *p, *arch_name;
205    uint32_t len, i;
206    struct ofile ofile;
207    enum bool flag, hostflag, arch_found, family;
208    struct arch_flag host_arch_flag;
209    const struct arch_flag *family_arch_flag;
210
211	/*
212	 * If use_member_syntax is TRUE look for a name of the form
213	 * "archive(member)" which is to mean a member in that archive (the
214	 * member name must be at least one character long to be recognized as
215	 * this form).
216	 */
217	member_name = NULL;
218	if(use_member_syntax == TRUE){
219	    len = strlen(name);
220	    if(len >= 4 && name[len-1] == ')'){
221		p = strrchr(name, '(');
222		if(p != NULL && p != name){
223		    member_name = p+1;
224		    *p = '\0';
225		    name[len-1] = '\0';
226		}
227	    }
228	}
229
230#ifdef OTOOL
231	otool_first_ofile_map = TRUE;
232#endif /* OTOOL */
233	if(ofile_map(name, NULL, NULL, &ofile, FALSE) == FALSE)
234	    return;
235#ifdef OTOOL
236	otool_first_ofile_map = FALSE;
237#endif /* OTOOL */
238
239	if(ofile.file_type == OFILE_FAT){
240	    /*
241	     * This is a fat file so see if a list of architecture is
242	     * specified and process only those.
243	     */
244	    if(all_archs == FALSE && narch_flags != 0){
245		for(i = 0; i < narch_flags; i++){
246		    if(ofile_first_arch(&ofile) == FALSE){
247			ofile_unmap(&ofile);
248			return;
249		    }
250		    arch_found = FALSE;
251		    family = FALSE;
252		    family_arch_flag =
253			get_arch_family_from_cputype(arch_flags[i].cputype);
254		    if(family_arch_flag != NULL)
255			family = (enum bool)
256			  ((family_arch_flag->cpusubtype & ~CPU_SUBTYPE_MASK) ==
257			   (arch_flags[i].cpusubtype & ~CPU_SUBTYPE_MASK));
258		    if(narch_flags != 1)
259			arch_name = ofile.arch_flag.name;
260		    else
261			arch_name = NULL;
262		    do{
263			if(ofile.arch_flag.cputype ==
264				arch_flags[i].cputype &&
265			   ((ofile.arch_flag.cpusubtype & ~CPU_SUBTYPE_MASK) ==
266			    (arch_flags[i].cpusubtype & ~CPU_SUBTYPE_MASK) ||
267			    family == TRUE)){
268			    arch_found = TRUE;
269			    if(ofile.arch_type == OFILE_ARCHIVE){
270				if(member_name != NULL){
271				    if(ofile_specific_member(member_name,
272							     &ofile) == TRUE){
273					processor(&ofile, arch_name, cookie);
274					if(ofile.headers_swapped == TRUE)
275					    swap_back_Mach_O(&ofile);
276				    }
277				}
278				else{
279				    /* loop through archive */
280#ifdef OTOOL
281				    printf("Archive : %s", ofile.file_name);
282				    if(arch_name != NULL)
283					printf(" (architecture %s)",
284					       arch_name);
285				    printf("\n");
286#endif /* OTOOL */
287				    if(ofile_first_member(&ofile) == TRUE){
288					flag = FALSE;
289					do{
290					    if(process_non_objects == TRUE ||
291					       ofile.member_type ==
292								OFILE_Mach_O){
293						processor(&ofile, arch_name,
294							  cookie);
295						if(ofile.headers_swapped ==TRUE)
296						    swap_back_Mach_O(&ofile);
297						flag = TRUE;
298					    }
299					}while(ofile_next_member(&ofile) ==
300						TRUE);
301					if(flag == FALSE){
302					    error("for architecture: %s "
303						  "archive: %s contains no "
304						  "members that are object "
305						  "files", ofile.arch_flag.name,
306						  ofile.file_name);
307					}
308				    }
309				    else{
310					error("for architecture: %s archive: "
311					      "%s contains no members",
312					      ofile.arch_flag.name,
313					      ofile.file_name);
314				    }
315				}
316			    }
317			    else if(process_non_objects == TRUE ||
318				    ofile.arch_type == OFILE_Mach_O){
319				if(ofile.arch_type == OFILE_Mach_O &&
320				   (ofile.mh_filetype == MH_DYLIB ||
321				    ofile.mh_filetype == MH_DYLIB_STUB)){
322				    if(dylib_flat == TRUE){
323					processor(&ofile, arch_name, cookie);
324					if(ofile.headers_swapped == TRUE)
325					    swap_back_Mach_O(&ofile);
326				    }
327				    else{
328					if(member_name != NULL){
329					    if(ofile_specific_module(
330						member_name, &ofile) == TRUE){
331						processor(&ofile, arch_name,
332							  cookie);
333						if(ofile.headers_swapped ==TRUE)
334						    swap_back_Mach_O(&ofile);
335					    }
336					}
337					else{
338					    /*loop through the dynamic library*/
339					    if(ofile_first_module(&ofile)){
340						do{
341						    processor(&ofile, arch_name,
342							cookie);
343						}while(ofile_next_module(
344							&ofile));
345					    }
346					    else{
347						processor(&ofile, arch_name,
348							  cookie);
349					    }
350					}
351				    }
352				    if(ofile.headers_swapped == TRUE)
353					swap_back_Mach_O(&ofile);
354				}
355				else{
356				    if(member_name != NULL)
357					error("for architecture: %s file: %s "
358					      "is not an archive and thus does "
359					      "not contain member: %s",
360					      ofile.arch_flag.name,
361					      ofile.file_name,
362					      member_name);
363				    else{
364					processor(&ofile, arch_name, cookie);
365					if(ofile.headers_swapped == TRUE)
366					    swap_back_Mach_O(&ofile);
367				     }
368				}
369			    }
370			    else if(ofile.arch_type == OFILE_UNKNOWN){
371				error("for architecture: %s file: %s is "
372				      "not an object file",
373				      ofile.arch_flag.name,ofile.file_name);
374			    }
375			    if(ofile.headers_swapped == TRUE)
376				swap_back_Mach_O(&ofile);
377			    break;
378			}
379			else{
380			    if(ofile.headers_swapped == TRUE)
381				swap_back_Mach_O(&ofile);
382			}
383		    }while(ofile_next_arch(&ofile) == TRUE);
384		    if(arch_found == FALSE)
385			error("file: %s does not contain architecture: %s",
386			      ofile.file_name, arch_flags[i].name);
387		}
388		ofile_unmap(&ofile);
389		return;
390	    }
391
392	    /*
393	     * This is a fat file and no architectures has been specified
394	     * so if it contains the host architecture process only that
395	     * architecture but if not process all architectures
396	     * specified.
397	     */
398	    if(all_archs == FALSE){
399		(void)get_arch_from_host(&host_arch_flag, NULL);
400#if __LP64__
401		/*
402		 * If runing as a 64-bit binary and on an Intel x86 host
403		 * default to 64-bit.
404		 */
405		if(host_arch_flag.cputype == CPU_TYPE_I386)
406		    host_arch_flag =
407			*get_arch_family_from_cputype(CPU_TYPE_X86_64);
408#endif /* __LP64__ */
409		hostflag = FALSE;
410
411		family = FALSE;
412		family_arch_flag =
413		    get_arch_family_from_cputype(host_arch_flag.cputype);
414		if(family_arch_flag != NULL)
415		    family = (enum bool)
416			((family_arch_flag->cpusubtype & ~CPU_SUBTYPE_MASK) ==
417			 (host_arch_flag.cpusubtype & ~CPU_SUBTYPE_MASK));
418
419		ofile_unmap(&ofile);
420		if(ofile_map(name, NULL, NULL, &ofile, FALSE) == FALSE)
421		    return;
422		if(ofile_first_arch(&ofile) == FALSE){
423		    ofile_unmap(&ofile);
424		    return;
425		}
426		do{
427		    if(ofile.arch_flag.cputype ==
428			    host_arch_flag.cputype &&
429		       ((ofile.arch_flag.cpusubtype & ~CPU_SUBTYPE_MASK) ==
430			(host_arch_flag.cpusubtype & ~CPU_SUBTYPE_MASK) ||
431			family == TRUE)){
432			hostflag = TRUE;
433			if(ofile.arch_type == OFILE_ARCHIVE){
434			    if(member_name != NULL){
435				if(ofile_specific_member(member_name,
436							 &ofile) == TRUE){
437				    processor(&ofile, NULL, cookie);
438				    if(ofile.headers_swapped == TRUE)
439					swap_back_Mach_O(&ofile);
440				}
441			    }
442			    else{
443				/* loop through archive */
444#ifdef OTOOL
445				printf("Archive : %s\n", ofile.file_name);
446#endif /* OTOOL */
447				if(ofile_first_member(&ofile) == TRUE){
448				    flag = FALSE;
449				    do{
450					if(process_non_objects == TRUE ||
451				           ofile.member_type == OFILE_Mach_O){
452					    processor(&ofile, NULL, cookie);
453					    if(ofile.headers_swapped == TRUE)
454						swap_back_Mach_O(&ofile);
455					    flag = TRUE;
456					}
457				    }while(ofile_next_member(&ofile) ==
458					   TRUE);
459				    if(flag == FALSE){
460					error("archive: %s contains no "
461					      "members that are object "
462					      "files", ofile.file_name);
463				    }
464				}
465				else{
466				    error("archive: %s contains no "
467					  "members", ofile.file_name);
468				}
469			    }
470			}
471			else if(process_non_objects == TRUE ||
472				ofile.arch_type == OFILE_Mach_O){
473			    if(ofile.arch_type == OFILE_Mach_O &&
474			       (ofile.mh_filetype == MH_DYLIB ||
475				ofile.mh_filetype == MH_DYLIB_STUB)){
476				if(dylib_flat == TRUE){
477				    processor(&ofile, NULL, cookie);
478				}
479				else{
480				    if(member_name != NULL){
481					if(ofile_specific_module(member_name,
482						&ofile) == TRUE)
483					    processor(&ofile, NULL, cookie);
484				    }
485				    else{
486					/* loop through the dynamic library */
487					if(ofile_first_module(&ofile) == TRUE){
488					    do{
489						processor(&ofile, NULL, cookie);
490					    }while(ofile_next_module(&ofile));
491					}
492					else{
493					    processor(&ofile, NULL, cookie);
494					}
495				    }
496				}
497				if(ofile.headers_swapped == TRUE)
498				    swap_back_Mach_O(&ofile);
499			    }
500			    else{
501				if(member_name != NULL)
502				    error("for architecture: %s file: %s is "
503					  "not an archive and thus does not "
504					  "contain member: %s",
505					  ofile.arch_flag.name, ofile.file_name,
506					  member_name);
507				else{
508				    processor(&ofile, NULL, cookie);
509				    if(ofile.headers_swapped == TRUE)
510					swap_back_Mach_O(&ofile);
511				}
512			    }
513			}
514			else if(ofile.arch_type == OFILE_UNKNOWN){
515			    error("file: %s is not an object file",
516				  ofile.file_name);
517			}
518		    }
519		    else{
520			if(ofile.headers_swapped == TRUE)
521			    swap_back_Mach_O(&ofile);
522		    }
523		}while(hostflag == FALSE && ofile_next_arch(&ofile) == TRUE);
524		if(hostflag == TRUE){
525		    ofile_unmap(&ofile);
526		    return;
527		}
528	    }
529
530	    /*
531	     * Either all architectures have been specified or none have
532	     * been specified and it does not contain the host architecture
533	     * so do all the architectures in the fat file
534	     */
535	    ofile_unmap(&ofile);
536	    if(ofile_map(name, NULL, NULL, &ofile, FALSE) == FALSE)
537		return;
538	    if(ofile_first_arch(&ofile) == FALSE){
539		ofile_unmap(&ofile);
540		return;
541	    }
542	    do{
543		if(ofile.arch_type == OFILE_ARCHIVE){
544		    if(member_name != NULL){
545			if(ofile_specific_member(member_name, &ofile) == TRUE)
546			    processor(&ofile, ofile.arch_flag.name, cookie);
547		    }
548		    else{
549			/* loop through archive */
550#ifdef OTOOL
551			printf("Archive : %s (architecture %s)\n",
552			       ofile.file_name, ofile.arch_flag.name);
553#endif /* OTOOL */
554			if(ofile_first_member(&ofile) == TRUE){
555			    flag = FALSE;
556			    do{
557				if(process_non_objects == TRUE ||
558				   ofile.member_type == OFILE_Mach_O){
559				    processor(&ofile, ofile.arch_flag.name,
560					      cookie);
561				    flag = TRUE;
562				}
563			    }while(ofile_next_member(&ofile) == TRUE);
564			    if(flag == FALSE){
565				error("for architecture: %s archive: %s "
566				      "contains no members that are object "
567				      "files", ofile.arch_flag.name,
568				      ofile.file_name);
569			    }
570			}
571			else{
572			    error("for architecture: %s archive: %s "
573				  "contains no members",
574				  ofile.arch_flag.name, ofile.file_name);
575			}
576		    }
577		}
578		else if(process_non_objects == TRUE ||
579			ofile.arch_type == OFILE_Mach_O){
580		    if(ofile.arch_type == OFILE_Mach_O &&
581		       (ofile.mh_filetype == MH_DYLIB ||
582			ofile.mh_filetype == MH_DYLIB_STUB)){
583			if(dylib_flat == TRUE){
584			    processor(&ofile, ofile.arch_flag.name, cookie);
585			}
586			else{
587			    if(member_name != NULL){
588				if(ofile_specific_module(member_name, &ofile)
589				   == TRUE)
590				    processor(&ofile, ofile.arch_flag.name,
591					      cookie);
592			    }
593			    else{
594				/* loop through the dynamic library */
595				if(ofile_first_module(&ofile) == TRUE){
596				    do{
597					processor(&ofile, ofile.arch_flag.name,
598						  cookie);
599				    }while(ofile_next_module(&ofile) == TRUE);
600				}
601				else{
602				    processor(&ofile, ofile.arch_flag.name,
603					      cookie);
604				}
605			    }
606			}
607		    }
608		    else{
609			if(member_name != NULL)
610			    error("for architecture: %s file: %s is not an "
611				  "archive and thus does not contain member: "
612				  "%s", ofile.arch_flag.name, ofile.file_name,
613				  member_name);
614			else
615			    processor(&ofile, ofile.arch_flag.name, cookie);
616		    }
617		}
618		else if(ofile.arch_type == OFILE_UNKNOWN){
619		    error("for architecture: %s file: %s is not an "
620			  "object file", ofile.arch_flag.name,
621			  ofile.file_name);
622		}
623	    }while(ofile_next_arch(&ofile) == TRUE);
624	}
625	else if(ofile.file_type == OFILE_ARCHIVE){
626	    if(narch_flags != 0){
627		arch_found = FALSE;
628		for(i = 0; i < narch_flags; i++){
629		    family = FALSE;
630		    if(narch_flags == 1){
631			family_arch_flag =
632			    get_arch_family_from_cputype(arch_flags[0].cputype);
633			if(family_arch_flag != NULL)
634			    family = (enum bool)
635				((family_arch_flag->cpusubtype &
636				  ~CPU_SUBTYPE_MASK) ==
637				 (arch_flags[0].cpusubtype &
638				  ~CPU_SUBTYPE_MASK));
639		    }
640		    if(ofile.archive_cputype == arch_flags[i].cputype &&
641		       ((ofile.archive_cpusubtype & ~CPU_SUBTYPE_MASK) ==
642			(arch_flags[i].cpusubtype & ~CPU_SUBTYPE_MASK) ||
643			family == TRUE)){
644			arch_found = TRUE;
645		    }
646		    else{
647			error("file: %s does not contain architecture: %s",
648			      ofile.file_name, arch_flags[i].name);
649		    }
650		}
651		if(arch_found == FALSE){
652		    ofile_unmap(&ofile);
653		    return;
654		}
655	    }
656	    if(member_name != NULL){
657		if(ofile_specific_member(member_name, &ofile) == TRUE)
658		    processor(&ofile, NULL, cookie);
659	    }
660	    else{
661		/* loop through archive */
662#ifdef OTOOL
663		printf("Archive : %s\n", ofile.file_name);
664#endif /* OTOOL */
665		if(ofile_first_member(&ofile) == TRUE){
666		    flag = FALSE;
667		    do{
668			if(process_non_objects == TRUE ||
669			    ofile.member_type == OFILE_Mach_O){
670			    processor(&ofile, NULL, cookie);
671			    flag = TRUE;
672			}
673		    }while(ofile_next_member(&ofile) == TRUE);
674		    if(flag == FALSE){
675			error("archive: %s contains no members that are "
676			      "object files", ofile.file_name);
677		    }
678		}
679		else{
680		    error("archive: %s contains no members",
681			  ofile.file_name);
682		}
683	    }
684	}
685	else if(ofile.file_type == OFILE_Mach_O){
686	    if(narch_flags != 0){
687		arch_found = FALSE;
688		for(i = 0; i < narch_flags; i++){
689		    family = FALSE;
690		    if(narch_flags == 1){
691			family_arch_flag =
692			    get_arch_family_from_cputype(arch_flags[0].cputype);
693			if(family_arch_flag != NULL)
694			    family = (enum bool)
695				((family_arch_flag->cpusubtype &
696				  ~CPU_SUBTYPE_MASK) ==
697				 (arch_flags[0].cpusubtype &
698				  ~CPU_SUBTYPE_MASK));
699		    }
700#ifdef OTOOL
701		    if(ofile.mh != NULL){
702		        if(ofile.mh->magic == MH_MAGIC &&
703			   ofile.mh->cputype == arch_flags[i].cputype &&
704			   ((ofile.mh->cpusubtype & ~CPU_SUBTYPE_MASK) ==
705			    (arch_flags[i].cpusubtype & ~CPU_SUBTYPE_MASK) ||
706			    family == TRUE)){
707			    arch_found = TRUE;
708			}
709		        if(ofile.mh->magic == SWAP_INT(MH_MAGIC) &&
710			   (cpu_type_t)SWAP_INT(ofile.mh->cputype) ==
711				arch_flags[i].cputype &&
712			   ((cpu_subtype_t)SWAP_INT(ofile.mh->cpusubtype &
713						    ~CPU_SUBTYPE_MASK) ==
714				(arch_flags[i].cpusubtype &
715				 ~CPU_SUBTYPE_MASK) ||
716			    family == TRUE)){
717			    arch_found = TRUE;
718			}
719		    }
720		    else if(ofile.mh64 != NULL){
721		        if(ofile.mh64->magic == MH_MAGIC_64 &&
722			   ofile.mh64->cputype == arch_flags[i].cputype &&
723			   ((ofile.mh64->cpusubtype & ~CPU_SUBTYPE_MASK) ==
724			    (arch_flags[i].cpusubtype & ~CPU_SUBTYPE_MASK) ||
725			    family == TRUE)){
726			    arch_found = TRUE;
727			}
728		        if(ofile.mh64->magic == SWAP_INT(MH_MAGIC_64) &&
729			   (cpu_type_t)SWAP_INT(ofile.mh64->cputype) ==
730				arch_flags[i].cputype &&
731			   ((cpu_subtype_t)SWAP_INT((ofile.mh64->cpusubtype &
732						     ~CPU_SUBTYPE_MASK)) ==
733			    (arch_flags[i].cpusubtype & ~CPU_SUBTYPE_MASK) ||
734			    family == TRUE)){
735			    arch_found = TRUE;
736			}
737		    }
738		    else
739#endif /* OTOOL */
740		    if(ofile.mh_cputype == arch_flags[i].cputype &&
741		       ((ofile.mh_cpusubtype & ~CPU_SUBTYPE_MASK) ==
742			(arch_flags[i].cpusubtype & ~CPU_SUBTYPE_MASK) ||
743			family == TRUE)){
744			arch_found = TRUE;
745		    }
746		    else{
747			error("file: %s does not contain architecture: %s",
748			      ofile.file_name, arch_flags[i].name);
749		    }
750		}
751		if(arch_found == FALSE){
752		    ofile_unmap(&ofile);
753		    return;
754		}
755	    }
756	    if(ofile.mh_filetype == MH_DYLIB ||
757	       ofile.mh_filetype == MH_DYLIB_STUB){
758		if(dylib_flat == TRUE){
759		    processor(&ofile, NULL, cookie);
760		}
761		else{
762		    if(member_name != NULL){
763			if(ofile_specific_module(member_name, &ofile) == TRUE)
764			    processor(&ofile, NULL, cookie);
765		    }
766		    else{
767			/* loop through the dynamic library */
768			if(ofile_first_module(&ofile) == TRUE){
769			    do{
770				processor(&ofile, NULL, cookie);
771			    }while(ofile_next_module(&ofile) == TRUE);
772			}
773			else{
774			    processor(&ofile, NULL, cookie);
775			}
776		    }
777		}
778	    }
779	    else{
780		if(member_name != NULL)
781		    error("file: %s is not an archive and thus does not contain"
782			  " member: %s", ofile.file_name, member_name);
783		else
784		    processor(&ofile, NULL, cookie);
785	    }
786	}
787	else{
788	    if(process_non_objects == TRUE)
789		processor(&ofile, NULL, cookie);
790	    else if(member_name != NULL)
791		error("file: %s(%s) is not an object file", name,
792		      member_name);
793	    else
794		error("file: %s is not an object file", name);
795	}
796	ofile_unmap(&ofile);
797}
798#endif /* !defined(OFI) */
799
800/*
801 * ofile_map maps in the object file specified by file_name, arch_flag and
802 * object_name and fills in the ofile struct pointed to by ofile for it.
803 * When arch_flag and object_name are both NULL, the file is just set up into
804 * ofile (if the file can be opened and mapped in, if not this call fails
805 * are error routnes are called).  If arch_flag is not NULL and object_file is
806 * NULL, then the file must be a Mach-O file or a fat file with the architecture
807 * specified in the arch_flag, if not this call fails and error routines are
808 * called.  When arch_flag and object_name are both not NULL, then the file must
809 * be an archive or a fat file containing archives for the specified architec-
810 * ture and contain an archive member object file with the name object_name,
811 * otherwise this call fails and error routines are called.  If arch_flag is
812 * NULL and object_file is not NULL, then the file name must be an archive (not
813 * a fat file containing archives) and contain an archive member object file
814 * with the name object_name, otherwise this call fails and calls error
815 * routines.  If this call suceeds then it returns non-zero and the ofile
816 * structure pointed to by ofile is filled in.  If this call fails it returns 0
817 * and calls error routines to print error messages and clears the
818 * ofile structure pointed to by ofile.
819 */
820__private_extern__
821#ifdef OFI
822NSObjectFileImageReturnCode
823#else
824enum bool
825#endif
826ofile_map(
827const char *file_name,
828const struct arch_flag *arch_flag,	/* can be NULL */
829const char *object_name,		/* can be NULL */
830struct ofile *ofile,
831enum bool archives_with_fat_objects)
832{
833    int fd;
834    struct stat stat_buf;
835    uint64_t size;
836    uint32_t magic;
837    char *addr;
838
839	magic = 0; /* to shut up the compiler warning message */
840	memset(ofile, '\0', sizeof(struct ofile));
841
842	/* Open the file and map it in */
843	if((fd = open(file_name, O_RDONLY)) == -1){
844#ifdef OFI
845	    return(NSObjectFileImageAccess);
846#else
847	    system_error("can't open file: %s", file_name);
848	    return(FALSE);
849#endif
850	}
851	if(fstat(fd, &stat_buf) == -1){
852	    close(fd);
853#ifdef OFI
854	    return(NSObjectFileImageAccess);
855#else
856	    system_error("can't stat file: %s", file_name);
857	    return(FALSE);
858#endif
859	}
860	size = stat_buf.st_size;
861
862	addr = NULL;
863	if(size != 0){
864	    addr = mmap(0, size, PROT_READ|PROT_WRITE, MAP_FILE|MAP_PRIVATE, fd,
865		        0);
866	    if((intptr_t)addr == -1){
867		system_error("can't map file: %s", file_name);
868		close(fd);
869		return(FALSE);
870	    }
871	}
872	close(fd);
873#ifdef OTOOL
874	if(otool_first_ofile_map && Wflag)
875	    printf("Modification time = %ld\n", (long int)stat_buf.st_mtime);
876#endif /* OTOOL */
877
878	return(ofile_map_from_memory(addr, size, file_name, stat_buf.st_mtime,
879		  arch_flag, object_name, ofile, archives_with_fat_objects));
880}
881
882/*
883 * ofile_map_from_memory() is the guts of ofile_map() but with an interface
884 * to pass the address and size of the file already mapped in.
885 */
886__private_extern__
887#ifdef OFI
888NSObjectFileImageReturnCode
889#else
890enum bool
891#endif
892ofile_map_from_memory(
893char *addr,
894uint64_t size,
895const char *file_name,
896uint64_t mtime,
897const struct arch_flag *arch_flag,	/* can be NULL */
898const char *object_name,		/* can be NULL */
899struct ofile *ofile,
900enum bool archives_with_fat_objects)
901{
902    uint32_t i;
903    uint32_t magic;
904    enum byte_sex host_byte_sex;
905    struct arch_flag host_arch_flag;
906    enum bool family;
907    const struct arch_flag *family_arch_flag;
908    uint64_t big_size;
909#ifdef OTOOL
910    uint32_t small_nfat_arch;
911#endif /* OTOOL */
912
913	/* fill in the start of the ofile structure */
914	ofile->file_name = savestr(file_name);
915	if(ofile->file_name == NULL)
916	    return(FALSE);
917	ofile->file_addr = addr;
918	ofile->file_size = size;
919	ofile->file_mtime = mtime;
920
921	/* Try to figure out what kind of file this is */
922
923	if(size >= sizeof(uint32_t)){
924	   magic = *((uint32_t *)addr);
925	}
926	host_byte_sex = get_host_byte_sex();
927
928	/* see if this file is a fat file (always in big endian byte sex) */
929#ifdef __BIG_ENDIAN__
930	if(size >= sizeof(struct fat_header) && magic == FAT_MAGIC)
931#endif /* __BIG_ENDIAN__ */
932#ifdef __LITTLE_ENDIAN__
933	if(size >= sizeof(struct fat_header) && SWAP_INT(magic) == FAT_MAGIC)
934#endif /* __LITTLE_ENDIAN__ */
935	{
936	    ofile->file_type = OFILE_FAT;
937	    ofile->fat_header = (struct fat_header *)addr;
938#ifdef __LITTLE_ENDIAN__
939	    swap_fat_header(ofile->fat_header, host_byte_sex);
940#endif /* __LITTLE_ENDIAN__ */
941#ifdef OTOOL
942	    if(otool_first_ofile_map && fflag)
943		printf("Fat headers\n");
944#endif /* OTOOL */
945	    big_size = ofile->fat_header->nfat_arch;
946	    big_size *= sizeof(struct fat_arch);
947	    big_size += sizeof(struct fat_header);
948	    if(big_size > size){
949#ifdef OTOOL
950		error("fat file: %s truncated or malformed (fat_arch structs "
951		      "would extend past the end of the file)", file_name);
952		ofile->fat_archs = allocate(size - sizeof(struct fat_header));
953		memset(ofile->fat_archs, '\0',
954		       size - sizeof(struct fat_header));
955		memcpy(ofile->fat_archs,
956		       addr + sizeof(struct fat_header),
957	    	       size - sizeof(struct fat_header));
958		small_nfat_arch = (size - sizeof(struct fat_header)) /
959				  sizeof(struct fat_arch);
960#ifdef __LITTLE_ENDIAN__
961		swap_fat_arch(ofile->fat_archs, small_nfat_arch,
962			      host_byte_sex);
963#endif /* __LITTLE_ENDIAN__ */
964		if(otool_first_ofile_map && fflag)
965		    print_fat_headers(ofile->fat_header, ofile->fat_archs,
966				      size, vflag);
967		free(ofile->fat_archs);
968		ofile_unmap(ofile);
969		return(FALSE);
970#else /* !defined(OTOOL) */
971		goto unknown;
972#endif /* OTOOL */
973	    }
974	    ofile->fat_archs = (struct fat_arch *)(addr +
975						   sizeof(struct fat_header));
976#ifdef __LITTLE_ENDIAN__
977	    swap_fat_arch(ofile->fat_archs, ofile->fat_header->nfat_arch,
978			  host_byte_sex);
979#endif /* __LITTLE_ENDIAN__ */
980#ifdef OTOOL
981	    if(otool_first_ofile_map && fflag)
982		print_fat_headers(ofile->fat_header, ofile->fat_archs,
983				  size, vflag);
984#endif /* OTOOL */
985	    if(check_fat(ofile) == CHECK_BAD){
986		ofile_unmap(ofile);
987#ifdef OFI
988		return(NSObjectFileImageFormat);
989#else
990		return(FALSE);
991#endif
992	    }
993	    /*
994	     * Now that the fat file is mapped fill in the ofile to the level
995	     * the caller wants based on the arch_flag and object_name passed.
996	     * If the caller did not specify an arch_flag or an object_name
997	     * then everything the caller wants is done.
998	     */
999	    if(arch_flag == NULL && object_name == NULL)
1000		goto success;
1001	    if(arch_flag == NULL){
1002		if(get_arch_from_host(&host_arch_flag, NULL) == 0){
1003		    error("can't determine the host architecture (specify an "
1004			  "arch_flag or fix get_arch_from_host() )");
1005		    goto cleanup;
1006		}
1007		ofile->arch_flag.name = savestr(host_arch_flag.name);
1008		if(ofile->arch_flag.name == NULL)
1009		    goto cleanup;
1010		ofile->arch_flag.cputype = host_arch_flag.cputype;
1011		ofile->arch_flag.cpusubtype = host_arch_flag.cpusubtype;
1012	    }
1013	    else{
1014		ofile->arch_flag.name = savestr(arch_flag->name);
1015		if(ofile->arch_flag.name == NULL)
1016		    goto cleanup;
1017		ofile->arch_flag.cputype = arch_flag->cputype;
1018		ofile->arch_flag.cpusubtype = arch_flag->cpusubtype;
1019	    }
1020
1021	    ofile->narch = UINT_MAX;
1022	    for(i = 0; i < ofile->fat_header->nfat_arch; i++){
1023		if(ofile->fat_archs[i].cputype ==
1024			ofile->arch_flag.cputype &&
1025		   (ofile->fat_archs[i].cpusubtype & ~CPU_SUBTYPE_MASK) ==
1026			(ofile->arch_flag.cpusubtype & ~CPU_SUBTYPE_MASK)){
1027		    ofile->narch = i;
1028		    break;
1029		}
1030	    }
1031	    if(ofile->narch == UINT_MAX){
1032		family = FALSE;
1033		family_arch_flag =
1034		    get_arch_family_from_cputype(ofile->arch_flag.cputype);
1035		if(family_arch_flag != NULL)
1036		    family = (enum bool)
1037			((family_arch_flag->cpusubtype & ~CPU_SUBTYPE_MASK) ==
1038			 (ofile->arch_flag.cpusubtype & ~CPU_SUBTYPE_MASK));
1039		ofile->narch = UINT_MAX;
1040		for(i = 0; i < ofile->fat_header->nfat_arch; i++){
1041		    if(ofile->fat_archs[i].cputype ==
1042			    ofile->arch_flag.cputype &&
1043		       (family == TRUE ||
1044			(ofile->fat_archs[i].cpusubtype & ~CPU_SUBTYPE_MASK) ==
1045			(ofile->arch_flag.cpusubtype & ~CPU_SUBTYPE_MASK))){
1046			ofile->arch_flag.cpusubtype =
1047			    ofile->fat_archs[i].cpusubtype;
1048			ofile->narch = i;
1049			break;
1050		    }
1051		}
1052	    }
1053	    if(ofile->narch == UINT_MAX){
1054#ifdef OFI
1055		ofile_unmap(ofile);
1056		return(NSObjectFileImageArch);
1057#else
1058		error("fat file: %s does not contain architecture %s",
1059		      ofile->file_name, arch_flag->name);
1060		ofile_unmap(ofile);
1061		return(FALSE);
1062#endif
1063	    }
1064	    /* Now determine the file type for this specific architecture */
1065	    size = ofile->fat_archs[i].size;
1066	    addr = addr + ofile->fat_archs[i].offset;
1067	    if(size >= sizeof(struct mach_header))
1068		memcpy(&magic, addr, sizeof(uint32_t));
1069	    /* see if this file is a 32-bit Mach-O file */
1070	    if(size >= sizeof(struct mach_header) &&
1071	       (magic == MH_MAGIC ||
1072		magic == SWAP_INT(MH_MAGIC))){
1073#ifdef ALIGNMENT_CHECKS
1074		if(ofile->fat_archs[i].offset % 4 != 0){
1075		    error("fat file: %s architecture %s malformed for a 32-bit "
1076			  "object file (offset is not a multiple of 4)",
1077			  ofile->file_name, arch_flag->name);
1078		    ofile_unmap(ofile);
1079#ifdef OFI
1080		    return(NSObjectFileImageFormat);
1081#else
1082		    return(FALSE);
1083#endif
1084		}
1085#endif /* ALIGNMENT_CHECKS */
1086		ofile->arch_type = OFILE_Mach_O;
1087		ofile->object_addr = addr;
1088		ofile->object_size = size;
1089		if(magic == MH_MAGIC)
1090		    ofile->object_byte_sex = host_byte_sex;
1091		else
1092		    ofile->object_byte_sex =
1093			host_byte_sex == BIG_ENDIAN_BYTE_SEX ?
1094			LITTLE_ENDIAN_BYTE_SEX : BIG_ENDIAN_BYTE_SEX;
1095		ofile->mh = (struct mach_header *)addr;
1096		ofile->load_commands = (struct load_command *)(addr +
1097					    sizeof(struct mach_header));
1098		if(check_Mach_O(ofile) == CHECK_BAD){
1099		    ofile_unmap(ofile);
1100#ifdef OFI
1101		    return(NSObjectFileImageFormat);
1102#else
1103		    return(FALSE);
1104#endif
1105		}
1106		if(object_name != NULL){
1107		    error("fat file: %s architecture %s is not an archive "
1108			  "(object_name to ofile_map() can't be specified to "
1109			  "be other than NULL)", ofile->file_name,
1110			  arch_flag->name);
1111		    goto cleanup;
1112		}
1113	    }
1114	    /* see if this file is a 64-bit Mach-O file */
1115	    else if(size >= sizeof(struct mach_header_64) &&
1116	            (magic == MH_MAGIC_64 ||
1117		     magic == SWAP_INT(MH_MAGIC_64))){
1118#ifdef ALIGNMENT_CHECKS
1119		if(ofile->fat_archs[i].offset % 8 != 0){
1120		    error("fat file: %s architecture %s malformed for a 64-bit "
1121			  "object file (offset is not a multiple of 8)",
1122			  ofile->file_name, arch_flag->name);
1123		    ofile_unmap(ofile);
1124#ifdef OFI
1125		    return(NSObjectFileImageFormat);
1126#else
1127		    return(FALSE);
1128#endif
1129		}
1130#endif /* ALIGNMENT_CHECKS */
1131		ofile->arch_type = OFILE_Mach_O;
1132		ofile->object_addr = addr;
1133		ofile->object_size = size;
1134		if(magic == MH_MAGIC_64)
1135		    ofile->object_byte_sex = host_byte_sex;
1136		else
1137		    ofile->object_byte_sex =
1138			host_byte_sex == BIG_ENDIAN_BYTE_SEX ?
1139			LITTLE_ENDIAN_BYTE_SEX : BIG_ENDIAN_BYTE_SEX;
1140		ofile->mh64 = (struct mach_header_64 *)addr;
1141		ofile->load_commands = (struct load_command *)(addr +
1142					sizeof(struct mach_header_64));
1143		if(check_Mach_O(ofile) == CHECK_BAD){
1144		    ofile_unmap(ofile);
1145#ifdef OFI
1146		    return(NSObjectFileImageFormat);
1147#else
1148		    return(FALSE);
1149#endif
1150		}
1151		if(object_name != NULL){
1152		    error("fat file: %s architecture %s is not an archive "
1153			  "(object_name to ofile_map() can't be specified to "
1154			  "be other than NULL)", ofile->file_name,
1155			  arch_flag->name);
1156		    goto cleanup;
1157		}
1158	    }
1159	    /* see if this file is an archive file */
1160	    else if(size >= SARMAG && strncmp(addr, ARMAG, SARMAG) == 0){
1161		ofile->arch_type = OFILE_ARCHIVE;
1162		if(check_archive(ofile, FALSE) == CHECK_BAD){
1163		    ofile_unmap(ofile);
1164#ifdef OFI
1165		    return(NSObjectFileImageInappropriateFile);
1166#else
1167		    return(FALSE);
1168#endif
1169		}
1170#ifdef ALIGNMENT_CHECKS
1171		if(ofile->archive_cputype != 0 &&
1172		   ofile->fat_archs[i].offset % sizeof(uint32_t) != 0){
1173		    error("fat file: %s architecture %s malformed archive that "
1174			  "contains object files (offset to archive is not a "
1175			  "multiple of sizeof(uint32_t))",
1176			  ofile->file_name, arch_flag->name);
1177		    ofile_unmap(ofile);
1178#ifdef OFI
1179		    return(NSObjectFileImageInappropriateFile);
1180#else
1181		    return(FALSE);
1182#endif
1183		}
1184#endif /* ALIGNMENT_CHECKS */
1185		if(object_name != NULL){
1186		    if(ofile_specific_member(object_name, ofile) == FALSE)
1187			goto cleanup;
1188		}
1189	    }
1190	    /* this file type is now known to be unknown to this program */
1191	    else{
1192		ofile->file_type = OFILE_UNKNOWN;
1193		if(object_name != NULL){
1194		    error("fat file: %s architecture %s is not an archive "
1195			  "(object_name to ofile_map() can't be specified to "
1196			  "be other than NULL)", ofile->file_name,
1197			  arch_flag->name);
1198		    goto cleanup;
1199		}
1200	    }
1201	}
1202	/* see if this file is a 32-bit Mach-O file */
1203	else if(size >= sizeof(struct mach_header) &&
1204		(magic == MH_MAGIC ||
1205		 magic == SWAP_INT(MH_MAGIC))){
1206	    ofile->file_type = OFILE_Mach_O;
1207	    ofile->object_addr = addr;
1208	    ofile->object_size = size;
1209	    if(magic == MH_MAGIC)
1210		ofile->object_byte_sex = host_byte_sex;
1211	    else
1212		ofile->object_byte_sex = host_byte_sex == BIG_ENDIAN_BYTE_SEX ?
1213				 LITTLE_ENDIAN_BYTE_SEX : BIG_ENDIAN_BYTE_SEX;
1214	    ofile->mh = (struct mach_header *)addr;
1215	    ofile->load_commands = (struct load_command *)(addr +
1216				    sizeof(struct mach_header));
1217	    if(check_Mach_O(ofile) == CHECK_BAD){
1218		ofile_unmap(ofile);
1219#ifdef OFI
1220		return(NSObjectFileImageFormat);
1221#else
1222		return(FALSE);
1223#endif
1224	    }
1225	    if(object_name != NULL){
1226		error("file: %s is not an archive (object_name to ofile_map() "
1227		      "can't be specified to be other than NULL)",
1228		      ofile->file_name);
1229		goto cleanup;
1230	    }
1231	    if(arch_flag != NULL){
1232		if(arch_flag->cputype != ofile->mh_cputype &&
1233		   (arch_flag->cpusubtype & ~CPU_SUBTYPE_MASK) !=
1234		   (ofile->mh_cpusubtype & ~CPU_SUBTYPE_MASK)){
1235#ifdef OFI
1236		    ofile_unmap(ofile);
1237		    return(NSObjectFileImageArch);
1238#else
1239		    error("object file: %s does not match specified arch_flag: "
1240			  "%s passed to ofile_map()", ofile->file_name,
1241			  arch_flag->name);
1242		    ofile_unmap(ofile);
1243		    return(FALSE);
1244#endif
1245		    goto cleanup;
1246		}
1247	    }
1248	}
1249	/* see if this file is a 64-bit Mach-O file */
1250	else if(size >= sizeof(struct mach_header_64) &&
1251		(magic == MH_MAGIC_64 ||
1252		 magic == SWAP_INT(MH_MAGIC_64))){
1253	    ofile->file_type = OFILE_Mach_O;
1254	    ofile->object_addr = addr;
1255	    ofile->object_size = size;
1256	    if(magic == MH_MAGIC_64)
1257		ofile->object_byte_sex = host_byte_sex;
1258	    else
1259		ofile->object_byte_sex = host_byte_sex == BIG_ENDIAN_BYTE_SEX ?
1260				 LITTLE_ENDIAN_BYTE_SEX : BIG_ENDIAN_BYTE_SEX;
1261	    ofile->mh64 = (struct mach_header_64 *)addr;
1262	    ofile->load_commands = (struct load_command *)(addr +
1263				    sizeof(struct mach_header_64));
1264	    if(check_Mach_O(ofile) == CHECK_BAD){
1265		ofile_unmap(ofile);
1266#ifdef OFI
1267		return(NSObjectFileImageFormat);
1268#else
1269		return(FALSE);
1270#endif
1271	    }
1272	    if(object_name != NULL){
1273		error("file: %s is not an archive (object_name to ofile_map() "
1274		      "can't be specified to be other than NULL)",
1275		      ofile->file_name);
1276		goto cleanup;
1277	    }
1278	    if(arch_flag != NULL){
1279		if(arch_flag->cputype != ofile->mh_cputype &&
1280		   (arch_flag->cpusubtype & ~CPU_SUBTYPE_MASK) !=
1281		   (ofile->mh_cpusubtype & ~CPU_SUBTYPE_MASK)){
1282#ifdef OFI
1283		    ofile_unmap(ofile);
1284		    return(NSObjectFileImageArch);
1285#else
1286		    error("object file: %s does not match specified arch_flag: "
1287			  "%s passed to ofile_map()", ofile->file_name,
1288			  arch_flag->name);
1289		    ofile_unmap(ofile);
1290		    return(FALSE);
1291#endif
1292		    goto cleanup;
1293		}
1294	    }
1295	}
1296	/* see if this file is an archive file */
1297	else if(size >= SARMAG && strncmp(addr, ARMAG, SARMAG) == 0){
1298	    ofile->file_type = OFILE_ARCHIVE;
1299	    if(check_archive(ofile, archives_with_fat_objects) == CHECK_BAD)
1300		goto cleanup;
1301	    if(object_name != NULL){
1302		if(ofile_specific_member(object_name, ofile) == FALSE)
1303		    goto cleanup;
1304		if(arch_flag != NULL){
1305		    if(arch_flag->cputype != ofile->mh_cputype &&
1306		       (arch_flag->cpusubtype & ~CPU_SUBTYPE_MASK) !=
1307		       (ofile->mh_cpusubtype & ~CPU_SUBTYPE_MASK)){
1308			error("object file: %s(%.*s) does not match specified "
1309			    "arch_flag: %s passed to ofile_map()",
1310			    ofile->file_name, (int)ofile->member_name_size,
1311			    ofile->member_name, arch_flag->name);
1312			goto cleanup;
1313		    }
1314		}
1315	    }
1316	    else{
1317		if(arch_flag != NULL){
1318		    if(arch_flag->cputype != ofile->archive_cputype &&
1319		       (arch_flag->cpusubtype & ~CPU_SUBTYPE_MASK) !=
1320		       (ofile->archive_cpusubtype & ~CPU_SUBTYPE_MASK)){
1321			error("archive file: %s objects do not match specified "
1322			      "arch_flag: %s passed to ofile_map()",
1323			      ofile->file_name, arch_flag->name);
1324			goto cleanup;
1325		    }
1326		}
1327	    }
1328	}
1329	/* this file type is now known to be unknown to this program */
1330	else{
1331#ifndef OTOOL
1332unknown:
1333#endif
1334#ifndef OFI
1335#ifdef LTO_SUPPORT
1336	    if(is_llvm_bitcode(ofile, ofile->file_addr, ofile->file_size) ==
1337	       TRUE){
1338		ofile->file_type = OFILE_LLVM_BITCODE;
1339		if(arch_flag != NULL){
1340		    if(arch_flag->cputype != ofile->lto_cputype &&
1341		       (arch_flag->cpusubtype & ~CPU_SUBTYPE_MASK) !=
1342		       (ofile->lto_cpusubtype & ~CPU_SUBTYPE_MASK)){
1343			error("llvm bitcode file: %s does not match specified "
1344			      "arch_flag: %s passed to ofile_map()",
1345			      ofile->file_name, arch_flag->name);
1346			goto cleanup;
1347		    }
1348		}
1349		if(object_name != NULL){
1350		    error("file: %s is not an archive (object_name to "
1351			  "ofile_map() can't be specified to be other than "
1352			  "NULL)", ofile->file_name);
1353		    goto cleanup;
1354		}
1355		goto success;
1356	    }
1357	    else
1358#endif /* LTO_SUPPORT */
1359#endif /* OFI */
1360		ofile->file_type = OFILE_UNKNOWN;
1361	    if(arch_flag != NULL){
1362#ifdef OFI
1363		ofile_unmap(ofile);
1364		return(NSObjectFileImageInappropriateFile);
1365#else
1366		error("file: %s is unknown type (arch_flag to ofile_map() "
1367		      "can't be specified to be other than NULL)",
1368		      ofile->file_name);
1369		ofile_unmap(ofile);
1370		return(FALSE);
1371#endif
1372	    }
1373	    if(object_name != NULL){
1374		error("file: %s is not an archive (object_name to ofile_map() "
1375		      "can't be specified to be other than NULL)",
1376		      ofile->file_name);
1377		goto cleanup;
1378	    }
1379	}
1380success:
1381	return(TRUE);
1382
1383cleanup:
1384	ofile_unmap(ofile);
1385	return(FALSE);
1386}
1387
1388/*
1389 * ofile_unmap() deallocates the memory associated with the specified ofile
1390 * struct.
1391 */
1392__private_extern__
1393void
1394ofile_unmap(
1395struct ofile *ofile)
1396{
1397    kern_return_t r;
1398
1399	if(ofile->file_addr != NULL){
1400	    if((r = vm_deallocate(mach_task_self(),
1401				 (vm_address_t)ofile->file_addr,
1402				 (vm_size_t)ofile->file_size)) != KERN_SUCCESS){
1403		my_mach_error(r, "Can't vm_deallocate mapped memory for file: "
1404			      "%s", ofile->file_name);
1405	    }
1406	}
1407	if(ofile->file_name != NULL)
1408	    free(ofile->file_name);
1409	if(ofile->arch_flag.name != NULL)
1410	    free(ofile->arch_flag.name);
1411	memset(ofile, '\0', sizeof(struct ofile));
1412}
1413
1414/*
1415 * ofile_first_arch() sets up the ofile struct for a fat file to the first arch
1416 * in it.
1417 */
1418__private_extern__
1419enum bool
1420ofile_first_arch(
1421struct ofile *ofile)
1422{
1423	if(ofile->file_type == OFILE_FAT ||
1424	   (ofile->file_type == OFILE_ARCHIVE &&
1425	    ofile->member_type == OFILE_FAT) )
1426	    return(ofile_specific_arch(ofile, 0));
1427	else{
1428	    error("ofile_first_arch() called and file type of: %s is not a fat "
1429		  "file\n", ofile->file_name);
1430	    return(FALSE);
1431	}
1432}
1433
1434/*
1435 * ofile_next_arch() sets up the ofile struct for a fat file to the next arch
1436 * in it.
1437 */
1438__private_extern__
1439enum bool
1440ofile_next_arch(
1441struct ofile *ofile)
1442{
1443	if(ofile->file_type == OFILE_FAT ||
1444	   (ofile->file_type == OFILE_ARCHIVE &&
1445	    ofile->member_type == OFILE_FAT) ){
1446	    if(ofile->narch + 1 < ofile->fat_header->nfat_arch)
1447		return(ofile_specific_arch(ofile, ofile->narch + 1));
1448	    else
1449		return(FALSE);
1450	}
1451	else{
1452	    error("ofile_next_arch() called and file type of: %s is not a fat "
1453		  "file\n", ofile->file_name);
1454	    return(FALSE);
1455	}
1456}
1457
1458/*
1459 * ofile_specific_arch() sets up the ofile struct for the fat file for the
1460 * specified narch.
1461 */
1462static
1463enum bool
1464ofile_specific_arch(
1465struct ofile *ofile,
1466uint32_t narch)
1467{
1468    char *addr;
1469    uint32_t size;
1470    uint32_t magic;
1471    enum byte_sex host_byte_sex;
1472
1473	ofile->narch = narch;
1474	ofile->arch_type = OFILE_UNKNOWN;
1475	if(ofile->arch_flag.name != NULL)
1476	    free(ofile->arch_flag.name);
1477	ofile->arch_flag.name = NULL;
1478	ofile->arch_flag.cputype = 0;
1479	ofile->arch_flag.cpusubtype = 0;
1480	ofile->archive_cputype = 0;
1481	ofile->archive_cpusubtype = 0;
1482	ofile->object_addr = NULL;
1483	ofile->object_size = 0;
1484	ofile->object_byte_sex = UNKNOWN_BYTE_SEX;
1485	ofile->mh = NULL;
1486	ofile->mh64 = NULL;
1487	ofile->load_commands = NULL;
1488
1489	ofile->arch_flag.cputype = ofile->fat_archs[ofile->narch].cputype;
1490	ofile->arch_flag.cpusubtype = ofile->fat_archs[ofile->narch].cpusubtype;
1491	set_arch_flag_name(&(ofile->arch_flag));
1492
1493
1494	/* Now determine the file type for this specific architecture */
1495	if(ofile->file_type == OFILE_FAT){
1496	    ofile->member_offset = 0;
1497	    ofile->member_addr = NULL;
1498	    ofile->member_size = 0;
1499	    ofile->member_ar_hdr = NULL;
1500	    ofile->member_type = OFILE_UNKNOWN;
1501
1502	    size = ofile->fat_archs[ofile->narch].size;
1503	    addr = ofile->file_addr + ofile->fat_archs[ofile->narch].offset;
1504	}
1505	else{
1506	    if(ofile->file_type != OFILE_ARCHIVE ||
1507	       ofile->member_type != OFILE_FAT){
1508		error("internal error. ofile_specific_arch() called but file "
1509		      "is not a fat file or an archive with a fat member ");
1510	    }
1511	    size = ofile->fat_archs[ofile->narch].size;
1512	    addr = ofile->file_addr +
1513		   ofile->member_offset +
1514		   ofile->fat_archs[ofile->narch].offset;
1515	}
1516
1517#ifdef OTOOL
1518	if(addr - ofile->file_addr > (ptrdiff_t)ofile->file_size){
1519	    error("fat file: %s offset to architecture %s extends past end "
1520		  "of file", ofile->file_name, ofile->arch_flag.name);
1521	    return(FALSE);
1522	}
1523	if(addr + size > ofile->file_addr + ofile->file_size)
1524	    size = (ofile->file_addr + ofile->file_size) - addr;
1525#endif /* OTOOL */
1526
1527	if(size >= sizeof(struct mach_header))
1528	    memcpy(&magic, addr, sizeof(uint32_t));
1529	/* see if this file is a 32-bit Mach-O file */
1530	if(size >= sizeof(struct mach_header) &&
1531	   (magic == MH_MAGIC || magic == SWAP_INT(MH_MAGIC))){
1532#ifdef ALIGNMENT_CHECKS
1533	    if(ofile->fat_archs[ofile->narch].offset % 4 != 0){
1534		if(ofile->file_type == OFILE_ARCHIVE){
1535		    error("fat file: %s(%.*s) architecture %s malformed for a "
1536			  "32-bit object file (offset is not a multiple of 4)",
1537			  ofile->file_name, (int)ofile->member_name_size,
1538			  ofile->member_name, ofile->arch_flag.name);
1539		}
1540		else
1541		    error("fat file: %s architecture %s malformed for a 32-bit "
1542			  "object file (offset is not a multiple of 4)",
1543			  ofile->file_name, ofile->arch_flag.name);
1544		goto cleanup;
1545	    }
1546#endif /* ALIGNMENT_CHECKS */
1547	    ofile->arch_type = OFILE_Mach_O;
1548	    ofile->object_addr = addr;
1549	    ofile->object_size = size;
1550	    host_byte_sex = get_host_byte_sex();
1551	    if(magic == MH_MAGIC)
1552		ofile->object_byte_sex = host_byte_sex;
1553	    else
1554		ofile->object_byte_sex =
1555		    host_byte_sex == BIG_ENDIAN_BYTE_SEX ?
1556		    LITTLE_ENDIAN_BYTE_SEX : BIG_ENDIAN_BYTE_SEX;
1557	    ofile->mh = (struct mach_header *)addr;
1558	    ofile->load_commands = (struct load_command *)(addr +
1559				    sizeof(struct mach_header));
1560	    if(check_Mach_O(ofile) == CHECK_BAD)
1561		goto cleanup;
1562	}
1563	/* see if this file is a 64-bit Mach-O file */
1564	else if(size >= sizeof(struct mach_header_64) &&
1565	   (magic == MH_MAGIC_64 || magic == SWAP_INT(MH_MAGIC_64))){
1566#ifdef ALIGNMENT_CHECKS
1567	    if(ofile->fat_archs[ofile->narch].offset % 8 != 0){
1568		if(ofile->file_type == OFILE_ARCHIVE){
1569		    error("fat file: %s(%.*s) architecture %s malformed for an "
1570			  "object file (offset is not a multiple of 8)",
1571			  ofile->file_name, (int)ofile->member_name_size,
1572			  ofile->member_name, ofile->arch_flag.name);
1573		}
1574		else
1575		    error("fat file: %s architecture %s malformed for a 64-bit "
1576			  "object file (offset is not a multiple of 8",
1577			  ofile->file_name, ofile->arch_flag.name);
1578		goto cleanup;
1579	    }
1580#endif /* ALIGNMENT_CHECKS */
1581	    ofile->arch_type = OFILE_Mach_O;
1582	    ofile->object_addr = addr;
1583	    ofile->object_size = size;
1584	    host_byte_sex = get_host_byte_sex();
1585	    if(magic == MH_MAGIC_64)
1586		ofile->object_byte_sex = host_byte_sex;
1587	    else
1588		ofile->object_byte_sex =
1589		    host_byte_sex == BIG_ENDIAN_BYTE_SEX ?
1590		    LITTLE_ENDIAN_BYTE_SEX : BIG_ENDIAN_BYTE_SEX;
1591	    ofile->mh64 = (struct mach_header_64 *)addr;
1592	    ofile->load_commands = (struct load_command *)(addr +
1593				    sizeof(struct mach_header_64));
1594	    if(check_Mach_O(ofile) == CHECK_BAD)
1595		goto cleanup;
1596	}
1597	/* see if this file is an archive file */
1598	else if(size >= SARMAG && strncmp(addr, ARMAG, SARMAG) == 0){
1599	    ofile->arch_type = OFILE_ARCHIVE;
1600	    if(check_archive(ofile, FALSE) == CHECK_BAD)
1601		goto cleanup;
1602#ifdef ALIGNMENT_CHECKS
1603	    if(ofile->archive_cputype != 0 &&
1604	       ofile->fat_archs[ofile->narch].offset %
1605		sizeof(uint32_t) != 0){
1606		error("fat file: %s architecture %s malformed archive that "
1607		      "contains object files (offset to archive is not a "
1608		      "multiple of sizeof(uint32_t))",
1609		      ofile->file_name, ofile->arch_flag.name);
1610		goto cleanup;
1611	    }
1612#endif /* ALIGNMENT_CHECKS */
1613	}
1614	/*
1615	 * This type for this architecture is now known to be unknown to this
1616	 * program.
1617	 */
1618	else{
1619#ifdef LTO_SUPPORT
1620	    if(is_llvm_bitcode(ofile, addr, size) == TRUE){
1621		ofile->arch_type = OFILE_LLVM_BITCODE;
1622		ofile->object_addr = addr;
1623		ofile->object_size = size;
1624	    }
1625	    else
1626#endif /* LTO_SUPPORT */
1627	        ofile->arch_type = OFILE_UNKNOWN;
1628	}
1629	return(TRUE);
1630cleanup:
1631	ofile->narch = 0;;
1632	ofile->arch_type = OFILE_UNKNOWN;
1633	if(ofile->arch_flag.name != NULL)
1634	    free(ofile->arch_flag.name);
1635	ofile->arch_flag.name = NULL;
1636	ofile->arch_flag.cputype = 0;
1637	ofile->arch_flag.cpusubtype = 0;
1638	if(ofile->file_type != OFILE_ARCHIVE){
1639	    ofile->member_offset = 0;
1640	    ofile->member_addr = NULL;
1641	    ofile->member_size = 0;
1642	    ofile->member_ar_hdr = NULL;
1643	    ofile->member_type = OFILE_UNKNOWN;
1644	}
1645	ofile->archive_cputype = 0;
1646	ofile->archive_cpusubtype = 0;
1647	ofile->object_addr = NULL;
1648	ofile->object_size = 0;
1649	ofile->object_byte_sex = UNKNOWN_BYTE_SEX;
1650	ofile->mh = NULL;
1651	ofile->mh64 = NULL;
1652	ofile->load_commands = NULL;
1653	return(FALSE);
1654}
1655
1656/*
1657 * ofile_first_member() set up the ofile structure (the member_* fields and
1658 * the object file fields if the first member is an object file) for the first
1659 * member.
1660 */
1661__private_extern__
1662enum bool
1663ofile_first_member(
1664struct ofile *ofile)
1665{
1666    char *addr;
1667    uint64_t size, offset;
1668    uint32_t magic;
1669    enum byte_sex host_byte_sex;
1670    struct ar_hdr *ar_hdr;
1671    uint32_t ar_name_size;
1672
1673	/* These fields are to be filled in by this routine, clear them first */
1674	ofile->member_offset = 0;
1675	ofile->member_addr = NULL;
1676	ofile->member_size = 0;
1677	ofile->member_ar_hdr = NULL;
1678	ofile->member_name = NULL;
1679	ofile->member_name_size = 0;
1680	ofile->member_type = OFILE_UNKNOWN;
1681	ofile->object_addr = NULL;
1682	ofile->object_size = 0;
1683	ofile->object_byte_sex = UNKNOWN_BYTE_SEX;
1684	ofile->mh = NULL;
1685	ofile->mh64 = NULL;
1686	ofile->load_commands = NULL;
1687#ifdef LTO_SUPPORT
1688	/*
1689	 * Note: it is up to the caller if they want to call free_lto() on this
1690	 * when iterating through the members of an archive.
1691	 */
1692	ofile->lto = NULL;
1693#endif /* LTO_SUPPORT */
1694
1695	/*
1696	 * Get the address and size of the archive.
1697	 */
1698	if(ofile->file_type == OFILE_FAT){
1699	    if(ofile->arch_type != OFILE_ARCHIVE){
1700		error("ofile_first_member() called on fat file: %s with a "
1701		      "non-archive architecture or no architecture selected\n",
1702		      ofile->file_name);
1703		return(FALSE);
1704	    }
1705	    addr = ofile->file_addr + ofile->fat_archs[ofile->narch].offset;
1706	    size = ofile->fat_archs[ofile->narch].size;
1707	}
1708	else if(ofile->file_type == OFILE_ARCHIVE){
1709	    addr = ofile->file_addr;
1710	    size = ofile->file_size;
1711	}
1712	else{
1713	    error("ofile_first_member() called and file type of %s is "
1714		  "OFILE_UNKNOWN\n", ofile->file_name);
1715	    return(FALSE);
1716	}
1717#ifdef OTOOL
1718	if((addr + SARMAG) - ofile->file_addr > (ptrdiff_t)ofile->file_size){
1719	    archive_error(ofile, "offset to first member extends past the end "
1720			  "of the file");
1721	    return(FALSE);
1722	}
1723	if(addr + size > ofile->file_addr + ofile->file_size)
1724	    size = (ofile->file_addr + ofile->file_size) - addr;
1725#endif /* OTOOL */
1726	if(size < SARMAG || strncmp(addr, ARMAG, SARMAG) != 0){
1727	    archive_error(ofile, "internal error. ofile_first_member() "
1728			  "called but file does not have an archive magic "
1729			  "string");
1730	    return(FALSE);
1731	}
1732
1733	offset = SARMAG;
1734	if(offset != size && offset + sizeof(struct ar_hdr) > size){
1735	    archive_error(ofile, "truncated or malformed (archive header of "
1736			  "first member extends past the end of the file)");
1737	    return(FALSE);
1738	}
1739
1740	/* check for empty archive */
1741	if(size == offset)
1742	    return(FALSE);
1743
1744	/* now we know there is a first member so set it up */
1745	ar_hdr = (struct ar_hdr *)(addr + offset);
1746	offset += sizeof(struct ar_hdr);
1747	ofile->member_offset = offset;
1748	ofile->member_addr = addr + offset;
1749	ofile->member_size = strtoul(ar_hdr->ar_size, NULL, 10);
1750	ofile->member_ar_hdr = ar_hdr;
1751	ofile->member_type = OFILE_UNKNOWN;
1752	ofile->member_name = ar_hdr->ar_name;
1753	if(strncmp(ofile->member_name, AR_EFMT1, sizeof(AR_EFMT1) - 1) == 0){
1754	    ofile->member_name = ar_hdr->ar_name + sizeof(struct ar_hdr);
1755	    ar_name_size = strtoul(ar_hdr->ar_name + sizeof(AR_EFMT1) - 1,
1756				   NULL, 10);
1757	    ofile->member_name_size = ar_name_size;
1758	    ofile->member_offset += ar_name_size;
1759	    ofile->member_addr += ar_name_size;
1760	    ofile->member_size -= ar_name_size;
1761	}
1762	else{
1763	    ofile->member_name_size = size_ar_name(ar_hdr);
1764	    ar_name_size = 0;
1765	}
1766	/* Clear these in case there is no table of contents */
1767	ofile->toc_addr = NULL;
1768	ofile->toc_size = 0;
1769	ofile->toc_ar_hdr = NULL;
1770	ofile->toc_name = NULL;
1771	ofile->toc_name_size = 0;
1772	ofile->toc_ranlibs = NULL;
1773	ofile->toc_nranlibs = 0;
1774	ofile->toc_strings = NULL;
1775	ofile->toc_strsize = 0;
1776	ofile->toc_bad = FALSE;
1777
1778	host_byte_sex = get_host_byte_sex();
1779
1780	if(ofile->member_size > sizeof(uint32_t)){
1781	    memcpy(&magic, ofile->member_addr, sizeof(uint32_t));
1782#ifdef __BIG_ENDIAN__
1783	    if(magic == FAT_MAGIC)
1784#endif /* __BIG_ENDIAN__ */
1785#ifdef __LITTLE_ENDIAN__
1786	    if(magic == SWAP_INT(FAT_MAGIC))
1787#endif /* __LITTLE_ENDIAN__ */
1788	    {
1789		ofile->member_type = OFILE_FAT;
1790		ofile->fat_header =
1791			(struct fat_header *)(ofile->member_addr);
1792#ifdef __LITTLE_ENDIAN__
1793		swap_fat_header(ofile->fat_header, host_byte_sex);
1794#endif /* __LITTLE_ENDIAN__ */
1795		if(sizeof(struct fat_header) +
1796		   ofile->fat_header->nfat_arch *
1797		   sizeof(struct fat_arch) > ofile->member_size){
1798		    archive_member_error(ofile, "fat file truncated or "
1799			    "malformed (fat_arch structs would extend past "
1800			    "the end of the archive member)");
1801		    goto fatcleanup;
1802		}
1803		ofile->fat_archs = (struct fat_arch *)
1804		    (ofile->member_addr + sizeof(struct fat_header));
1805#ifdef __LITTLE_ENDIAN__
1806		swap_fat_arch(ofile->fat_archs,
1807			      ofile->fat_header->nfat_arch, host_byte_sex);
1808#endif /* __LITTLE_ENDIAN__ */
1809		if(check_fat_object_in_archive(ofile) == FALSE)
1810		    goto fatcleanup;
1811	    }
1812	    else if(size - (offset + ar_name_size) >=
1813		    sizeof(struct mach_header) &&
1814	       (magic == MH_MAGIC || magic == SWAP_INT(MH_MAGIC))){
1815#ifdef ALIGNMENT_CHECKS
1816		if((offset + ar_name_size) % 4 != 0){
1817		    archive_member_error(ofile, "offset in archive not a "
1818			"multiple of 4 (must be since member is a 32-bit "
1819			"object file)");
1820		    goto cleanup;
1821		}
1822#endif /* ALIGNMENT_CHECKS */
1823		ofile->member_type = OFILE_Mach_O;
1824		ofile->object_addr = ofile->member_addr;
1825		ofile->object_size = ofile->member_size;
1826		if(magic == MH_MAGIC)
1827		    ofile->object_byte_sex = host_byte_sex;
1828		else
1829		    ofile->object_byte_sex =
1830			   host_byte_sex == BIG_ENDIAN_BYTE_SEX ?
1831			   LITTLE_ENDIAN_BYTE_SEX : BIG_ENDIAN_BYTE_SEX;
1832		ofile->mh = (struct mach_header *)(ofile->object_addr);
1833		ofile->load_commands = (struct load_command *)
1834		    (ofile->object_addr + sizeof(struct mach_header));
1835		if(check_Mach_O(ofile) == CHECK_BAD)
1836		    goto cleanup;
1837	    }
1838	    else if(size - (offset + ar_name_size) >=
1839		    sizeof(struct mach_header_64) &&
1840	       (magic == MH_MAGIC_64 || magic == SWAP_INT(MH_MAGIC_64))){
1841#ifdef ALIGNMENT_CHECKS_ARCHIVE_64_BIT
1842		if(archive_64_bit_align_warning == FALSE &&
1843		   (offset + ar_name_size) % 8 != 0){
1844		    temporary_archive_member_warning(ofile, "offset in archive "
1845			"not a multiple of 8 (must be since member is an "
1846			"64-bit object file)");
1847		    archive_64_bit_align_warning = TRUE;
1848		    /* goto cleanup; */
1849		}
1850#endif /* ALIGNMENT_CHECKS_ARCHIVE_64_BIT */
1851		ofile->member_type = OFILE_Mach_O;
1852		ofile->object_addr = ofile->member_addr;
1853		ofile->object_size = ofile->member_size;
1854		if(magic == MH_MAGIC_64)
1855		    ofile->object_byte_sex = host_byte_sex;
1856		else
1857		    ofile->object_byte_sex =
1858			   host_byte_sex == BIG_ENDIAN_BYTE_SEX ?
1859			   LITTLE_ENDIAN_BYTE_SEX : BIG_ENDIAN_BYTE_SEX;
1860		ofile->mh64 = (struct mach_header_64 *)(ofile->object_addr);
1861		ofile->load_commands = (struct load_command *)
1862		    (ofile->object_addr + sizeof(struct mach_header_64));
1863		if(check_Mach_O(ofile) == CHECK_BAD)
1864		    goto cleanup;
1865	    }
1866	    if(ofile->member_type == OFILE_UNKNOWN &&
1867	       (strncmp(ofile->member_name, SYMDEF_SORTED,
1868		        sizeof(SYMDEF_SORTED) - 1) == 0 ||
1869	        strncmp(ofile->member_name, SYMDEF,
1870		        sizeof(SYMDEF) - 1) == 0)){
1871		ofile->toc_addr = ofile->member_addr;
1872		ofile->toc_size = ofile->member_size;
1873		ofile->toc_ar_hdr = ofile->member_ar_hdr;
1874		ofile->toc_name = ofile->member_name;
1875		ofile->toc_name_size = ofile->member_name_size;
1876		if(check_archive_toc(ofile) == CHECK_BAD)
1877		    goto cleanup;
1878	    }
1879#ifdef LTO_SUPPORT
1880	    if(ofile->member_type == OFILE_UNKNOWN &&
1881	       strncmp(ofile->member_name, SYMDEF_SORTED,
1882		       sizeof(SYMDEF_SORTED) - 1) != 0 &&
1883	       strncmp(ofile->member_name, SYMDEF,
1884		       sizeof(SYMDEF) - 1) != 0 &&
1885	       is_llvm_bitcode(ofile, ofile->member_addr, ofile->member_size) ==
1886	       TRUE){
1887		ofile->member_type = OFILE_LLVM_BITCODE;
1888		ofile->object_addr = ofile->member_addr;
1889		ofile->object_size = ofile->member_size;
1890	    }
1891#endif /* LTO_SUPPORT */
1892	}
1893	return(TRUE);
1894
1895fatcleanup:
1896	ofile->fat_header = NULL;
1897	ofile->fat_archs = NULL;
1898cleanup:
1899	ofile->member_offset = 0;
1900	ofile->member_addr = 0;
1901	ofile->member_size = 0;
1902	ofile->member_ar_hdr = NULL;
1903	ofile->member_name = NULL;
1904	ofile->member_name_size = 0;
1905	ofile->member_type = OFILE_UNKNOWN;
1906	ofile->object_addr = NULL;
1907	ofile->object_size = 0;
1908	ofile->object_byte_sex = UNKNOWN_BYTE_SEX;
1909	ofile->mh = NULL;
1910	ofile->mh64 = NULL;
1911	ofile->load_commands = NULL;
1912#ifdef LTO_SUPPORT
1913	ofile->lto = NULL;
1914	ofile->lto_cputype = 0;
1915	ofile->lto_cpusubtype = 0;
1916#endif /* LTO_SUPPORT */
1917	return(FALSE);
1918}
1919
1920/*
1921 * ofile_next_member() set up the ofile structure (the member_* fields and
1922 * the object file fields if the next member is an object file) for the next
1923 * member.
1924 */
1925__private_extern__
1926enum bool
1927ofile_next_member(
1928struct ofile *ofile)
1929{
1930    char *addr;
1931    uint64_t size, offset;
1932    uint32_t magic;
1933    enum byte_sex host_byte_sex;
1934    struct ar_hdr *ar_hdr;
1935    uint32_t ar_name_size;
1936
1937	/*
1938	 * Get the address and size of the archive.
1939	 */
1940	if(ofile->file_type == OFILE_FAT){
1941	    if(ofile->arch_type != OFILE_ARCHIVE){
1942		error("ofile_next_member() called on fat file: %s with a "
1943		      "non-archive architecture or no architecture selected\n",
1944		      ofile->file_name);
1945		return(FALSE);
1946	    }
1947	    addr = ofile->file_addr + ofile->fat_archs[ofile->narch].offset;
1948	    size = ofile->fat_archs[ofile->narch].size;
1949	}
1950	else if(ofile->file_type == OFILE_ARCHIVE){
1951	    addr = ofile->file_addr;
1952	    size = ofile->file_size;
1953	}
1954	else{
1955	    error("ofile_next_member() called and file type of %s is "
1956		  "OFILE_UNKNOWN\n", ofile->file_name);
1957	    return(FALSE);
1958	}
1959	if(size < SARMAG || strncmp(addr, ARMAG, SARMAG) != 0){
1960	    archive_error(ofile, "internal error. ofile_next_member() "
1961			  "called but file does not have an archive magic "
1962			  "string");
1963	    return(FALSE);
1964	}
1965	if(ofile->member_ar_hdr == NULL){
1966	    archive_error(ofile, "internal error. ofile_next_member() called "
1967			  "but the ofile struct does not have an archive "
1968			  "member selected");
1969	    return(FALSE);
1970	}
1971
1972	/* figure out the offset to the next member */
1973	offset = ofile->member_offset + rnd(ofile->member_size,sizeof(short));
1974#ifdef OTOOL
1975	if((addr - ofile->file_addr) + offset > ofile->file_size){
1976	    archive_error(ofile, "offset to next member extends past the end "
1977			  "of the file");
1978	    return(FALSE);
1979	}
1980#endif /* OTOOL */
1981	/* if now at the end of the file then no more members */
1982	if(offset == size)
1983	     goto cleanup;
1984	if(offset > size){
1985	    archive_error(ofile, "truncated or malformed (archive header of "
1986			  "next member extends past the end of the file)");
1987	    return(FALSE);
1988	}
1989
1990	/* now we know there is a next member so set it up */
1991	ar_hdr = (struct ar_hdr *)(addr + offset);
1992	offset += sizeof(struct ar_hdr);
1993	ofile->member_offset = offset;
1994	ofile->member_addr = addr + offset;
1995	ofile->member_size = strtoul(ar_hdr->ar_size, NULL, 10);
1996	ofile->member_ar_hdr = ar_hdr;
1997	ofile->member_name = ar_hdr->ar_name;
1998	if(strncmp(ofile->member_name, AR_EFMT1, sizeof(AR_EFMT1) - 1) == 0){
1999	    ofile->member_name = ar_hdr->ar_name + sizeof(struct ar_hdr);
2000	    ar_name_size = strtoul(ar_hdr->ar_name + sizeof(AR_EFMT1) - 1,
2001				   NULL, 10);
2002	    ofile->member_name_size = ar_name_size;
2003	    ofile->member_offset += ar_name_size;
2004	    ofile->member_addr += ar_name_size;
2005	    ofile->member_size -= ar_name_size;
2006	}
2007	else{
2008	    ofile->member_name_size = size_ar_name(ar_hdr);
2009	    ar_name_size = 0;
2010	}
2011	ofile->member_type = OFILE_UNKNOWN;
2012	ofile->object_addr = NULL;
2013	ofile->object_size = 0;
2014	ofile->object_byte_sex = UNKNOWN_BYTE_SEX;
2015	ofile->mh = NULL;
2016	ofile->mh64 = NULL;
2017	ofile->load_commands = NULL;
2018
2019	host_byte_sex = get_host_byte_sex();
2020
2021	if(ofile->member_size > sizeof(uint32_t)){
2022	    memcpy(&magic, ofile->member_addr, sizeof(uint32_t));
2023#ifdef __BIG_ENDIAN__
2024	    if(magic == FAT_MAGIC)
2025#endif /* __BIG_ENDIAN__ */
2026#ifdef __LITTLE_ENDIAN__
2027	    if(magic == SWAP_INT(FAT_MAGIC))
2028#endif /* __LITTLE_ENDIAN__ */
2029	    {
2030		ofile->member_type = OFILE_FAT;
2031		ofile->fat_header = (struct fat_header *)(ofile->member_addr);
2032#ifdef __LITTLE_ENDIAN__
2033		swap_fat_header(ofile->fat_header, host_byte_sex);
2034#endif /* __LITTLE_ENDIAN__ */
2035		if(sizeof(struct fat_header) +
2036		   ofile->fat_header->nfat_arch *
2037		   sizeof(struct fat_arch) > ofile->member_size){
2038		    archive_member_error(ofile, "fat file truncated or "
2039			    "malformed (fat_arch structs would extend past "
2040			    "the end of the archive member)");
2041		    goto cleanup;
2042		}
2043		ofile->fat_archs = (struct fat_arch *)(ofile->member_addr +
2044					       sizeof(struct fat_header));
2045#ifdef __LITTLE_ENDIAN__
2046		swap_fat_arch(ofile->fat_archs,
2047			      ofile->fat_header->nfat_arch, host_byte_sex);
2048#endif /* __LITTLE_ENDIAN__ */
2049		if(check_fat_object_in_archive(ofile) == FALSE)
2050		    goto cleanup;
2051	    }
2052	    else if(size - (offset + ar_name_size) >=
2053		    sizeof(struct mach_header) &&
2054		    (magic == MH_MAGIC ||
2055		     magic == SWAP_INT(MH_MAGIC))){
2056#ifdef ALIGNMENT_CHECKS
2057		if((offset + ar_name_size) % 4 != 0){
2058		    archive_member_error(ofile, "offset in archive not "
2059			"a multiple of 4 (must be since member is an 32-bit "
2060			"object file)");
2061		    goto cleanup;
2062		}
2063#endif /* ALIGNMENT_CHECKS */
2064		ofile->member_type = OFILE_Mach_O;
2065		ofile->object_addr = ofile->member_addr;
2066		ofile->object_size = ofile->member_size;
2067		if(magic == MH_MAGIC)
2068		    ofile->object_byte_sex = host_byte_sex;
2069		else
2070		    ofile->object_byte_sex =
2071			   host_byte_sex == BIG_ENDIAN_BYTE_SEX ?
2072			   LITTLE_ENDIAN_BYTE_SEX : BIG_ENDIAN_BYTE_SEX;
2073		ofile->mh = (struct mach_header *)ofile->object_addr;
2074		ofile->load_commands = (struct load_command *)
2075			   (ofile->object_addr + sizeof(struct mach_header));
2076		if(check_Mach_O(ofile) == CHECK_BAD)
2077		    goto cleanup;
2078	    }
2079	    else if(size - (offset + ar_name_size) >=
2080		    sizeof(struct mach_header_64) &&
2081		    (magic == MH_MAGIC_64 ||
2082		     magic == SWAP_INT(MH_MAGIC_64))){
2083#ifdef ALIGNMENT_CHECKS_ARCHIVE_64_BIT
2084		if(archive_64_bit_align_warning == FALSE &&
2085		   (offset + ar_name_size) % 8 != 0){
2086		    temporary_archive_member_warning(ofile, "offset in archive "
2087			"not a multiple of 8 (must be since member is an "
2088			"64-bit object file)");
2089		    archive_64_bit_align_warning = TRUE;
2090		    /* goto cleanup; */
2091		}
2092#endif /* ALIGNMENT_CHECKS_ARCHIVE_64_BIT */
2093		ofile->member_type = OFILE_Mach_O;
2094		ofile->object_addr = ofile->member_addr;
2095		ofile->object_size = ofile->member_size;
2096		if(magic == MH_MAGIC_64)
2097		    ofile->object_byte_sex = host_byte_sex;
2098		else
2099		    ofile->object_byte_sex =
2100			   host_byte_sex == BIG_ENDIAN_BYTE_SEX ?
2101			   LITTLE_ENDIAN_BYTE_SEX : BIG_ENDIAN_BYTE_SEX;
2102		ofile->mh64 = (struct mach_header_64 *)ofile->object_addr;
2103		ofile->load_commands = (struct load_command *)
2104			   (ofile->object_addr + sizeof(struct mach_header_64));
2105		if(check_Mach_O(ofile) == CHECK_BAD)
2106		    goto cleanup;
2107	    }
2108#ifdef LTO_SUPPORT
2109	    if(ofile->member_type == OFILE_UNKNOWN &&
2110	       is_llvm_bitcode(ofile, ofile->member_addr, ofile->member_size) ==
2111	       TRUE){
2112		ofile->member_type = OFILE_LLVM_BITCODE;
2113		ofile->object_addr = ofile->member_addr;
2114		ofile->object_size = ofile->member_size;
2115	    }
2116#endif /* LTO_SUPPORT */
2117	}
2118	return(TRUE);
2119
2120cleanup:
2121	if(ofile->member_type == OFILE_FAT){
2122	    ofile->fat_header = NULL;
2123	    ofile->fat_archs = NULL;
2124	}
2125	ofile->member_offset = 0;
2126	ofile->member_addr = NULL;
2127	ofile->member_size = 0;
2128	ofile->member_ar_hdr = NULL;
2129	ofile->member_name = NULL;
2130	ofile->member_name_size = 0;
2131	ofile->member_type = OFILE_UNKNOWN;
2132	ofile->object_addr = NULL;
2133	ofile->object_size = 0;
2134	ofile->object_byte_sex = UNKNOWN_BYTE_SEX;
2135	ofile->mh = NULL;
2136	ofile->mh64 = NULL;
2137	ofile->load_commands = NULL;
2138#ifdef LTO_SUPPORT
2139	ofile->lto = NULL;
2140	ofile->lto_cputype = 0;
2141	ofile->lto_cpusubtype = 0;
2142#endif /* LTO_SUPPORT */
2143	return(FALSE);
2144}
2145
2146/*
2147 * ofile_specific_member() set up the ofile structure (the member_* fields and
2148 * the object file fields if the member is an object file) for the specified
2149 * member member_name.
2150 */
2151__private_extern__
2152enum bool
2153ofile_specific_member(
2154const char *member_name,
2155struct ofile *ofile)
2156{
2157    int32_t i;
2158    char *addr;
2159    uint64_t size, offset;
2160    uint32_t magic;
2161    enum byte_sex host_byte_sex;
2162    char *ar_name;
2163    uint32_t ar_name_size;
2164    struct ar_hdr *ar_hdr;
2165
2166	/* These fields are to be filled in by this routine, clear them first */
2167	ofile->member_offset = 0;
2168	ofile->member_addr = NULL;
2169	ofile->member_size = 0;
2170	ofile->member_ar_hdr = NULL;
2171	ofile->member_name = NULL;
2172	ofile->member_name_size = 0;
2173	ofile->member_type = OFILE_UNKNOWN;
2174	ofile->object_addr = NULL;
2175	ofile->object_size = 0;
2176	ofile->object_byte_sex = UNKNOWN_BYTE_SEX;
2177	ofile->mh = NULL;
2178	ofile->mh64 = NULL;
2179	ofile->load_commands = NULL;
2180
2181	/*
2182	 * Get the address and size of the archive.
2183	 */
2184	if(ofile->file_type == OFILE_FAT){
2185	    if(ofile->arch_type != OFILE_ARCHIVE){
2186		error("ofile_specific_member() called on fat file: %s with a "
2187		      "non-archive architecture or no architecture selected\n",
2188		      ofile->file_name);
2189		return(FALSE);
2190	    }
2191	    addr = ofile->file_addr + ofile->fat_archs[ofile->narch].offset;
2192	    size = ofile->fat_archs[ofile->narch].size;
2193	}
2194	else if(ofile->file_type == OFILE_ARCHIVE){
2195	    addr = ofile->file_addr;
2196	    size = ofile->file_size;
2197	}
2198	else{
2199	    error("ofile_specific_member() called and file type of %s is "
2200		  "OFILE_UNKNOWN\n", ofile->file_name);
2201	    return(FALSE);
2202	}
2203	if(size < SARMAG || strncmp(addr, ARMAG, SARMAG) != 0){
2204	    archive_error(ofile, "internal error. ofile_specific_member() "
2205			  "called but file does not have an archive magic "
2206			  "string");
2207	    return(FALSE);
2208	}
2209
2210	offset = SARMAG;
2211	if(offset != size && offset + sizeof(struct ar_hdr) > size){
2212	    archive_error(ofile, "truncated or malformed (archive header of "
2213			  "first member extends past the end of the file)");
2214	    return(FALSE);
2215	}
2216	while(size > offset){
2217	    ar_hdr = (struct ar_hdr *)(addr + offset);
2218	    offset += sizeof(struct ar_hdr);
2219	    if(strncmp(ar_hdr->ar_name, AR_EFMT1, sizeof(AR_EFMT1) - 1) == 0){
2220#ifdef OTOOL
2221		if(check_extend_format_1(ofile, ar_hdr, size - offset,
2222				&ar_name_size) == CHECK_BAD){
2223		    i = size_ar_name(ar_hdr);
2224		    ar_name = ar_hdr->ar_name;
2225		    ar_name_size = 0;
2226		}
2227		else
2228#endif /* OTOOL */
2229		{
2230		    i = strtoul(ar_hdr->ar_name + sizeof(AR_EFMT1) - 1,NULL,10);
2231		    ar_name = ar_hdr->ar_name + sizeof(struct ar_hdr);
2232		    ar_name_size = i;
2233		}
2234	    }
2235	    else{
2236		i = size_ar_name(ar_hdr);
2237		ar_name = ar_hdr->ar_name;
2238		ar_name_size = 0;
2239	    }
2240	    if(i > 0 && strncmp(ar_name, member_name, i) == 0){
2241
2242		ofile->member_name = ar_name;
2243		ofile->member_name_size = i;
2244		ofile->member_offset = offset + ar_name_size;
2245		ofile->member_addr = addr + offset + ar_name_size;
2246		ofile->member_size = strtoul(ar_hdr->ar_size, NULL, 10) -
2247				     ar_name_size;
2248		ofile->member_ar_hdr = ar_hdr;
2249		ofile->member_type = OFILE_UNKNOWN;
2250
2251		host_byte_sex = get_host_byte_sex();
2252
2253		if(ofile->member_size > sizeof(uint32_t)){
2254		    memcpy(&magic, addr + offset + ar_name_size,
2255			   sizeof(uint32_t));
2256#ifdef __BIG_ENDIAN__
2257		    if(magic == FAT_MAGIC)
2258#endif /* __BIG_ENDIAN__ */
2259#ifdef __LITTLE_ENDIAN__
2260		    if(magic == SWAP_INT(FAT_MAGIC))
2261#endif /* __LITTLE_ENDIAN__ */
2262		    {
2263			ofile->member_type = OFILE_FAT;
2264			ofile->fat_header =
2265			    (struct fat_header *)(addr + offset + ar_name_size);
2266#ifdef __LITTLE_ENDIAN__
2267			swap_fat_header(ofile->fat_header, host_byte_sex);
2268#endif /* __LITTLE_ENDIAN__ */
2269			if(sizeof(struct fat_header) +
2270			   ofile->fat_header->nfat_arch *
2271			   sizeof(struct fat_arch) > ofile->member_size){
2272			    archive_member_error(ofile, "fat file truncated or "
2273				    "malformed (fat_arch structs would extend "
2274				    "past the end of the archive member)");
2275			    goto fatcleanup;
2276			}
2277			ofile->fat_archs =
2278			    (struct fat_arch *)(addr + offset + ar_name_size +
2279					        sizeof(struct fat_header));
2280#ifdef __LITTLE_ENDIAN__
2281			swap_fat_arch(ofile->fat_archs,
2282				      ofile->fat_header->nfat_arch,
2283				      host_byte_sex);
2284#endif /* __LITTLE_ENDIAN__ */
2285			if(check_fat_object_in_archive(ofile) == FALSE)
2286			    goto fatcleanup;
2287		    }
2288		    else if(size - (offset + ar_name_size) >=
2289			    sizeof(struct mach_header) &&
2290			   (magic == MH_MAGIC ||
2291			    magic == SWAP_INT(MH_MAGIC))){
2292#ifdef ALIGNMENT_CHECKS
2293			if((offset + ar_name_size) % 4 != 0){
2294			    archive_member_error(ofile, "offset in archive not "
2295				"a multiple of 4) (must be since member is a "
2296				"32-bit object file)");
2297			    goto cleanup;
2298			}
2299#endif /* ALIGNMENT_CHECKS */
2300			ofile->member_type = OFILE_Mach_O;
2301			ofile->object_addr = ofile->member_addr;
2302			ofile->object_size = ofile->member_size;
2303			if(magic == MH_MAGIC)
2304			    ofile->object_byte_sex = host_byte_sex;
2305			else
2306			    ofile->object_byte_sex =
2307				   host_byte_sex == BIG_ENDIAN_BYTE_SEX ?
2308				   LITTLE_ENDIAN_BYTE_SEX : BIG_ENDIAN_BYTE_SEX;
2309			ofile->mh = (struct mach_header *)ofile->object_addr;
2310			ofile->load_commands = (struct load_command *)
2311			    (ofile->object_addr + sizeof(struct mach_header));
2312			if(check_Mach_O(ofile) == CHECK_BAD)
2313			    goto cleanup;
2314		    }
2315		    else if(size - (offset + ar_name_size) >=
2316			    sizeof(struct mach_header_64) &&
2317			   (magic == MH_MAGIC_64 ||
2318			    magic == SWAP_INT(MH_MAGIC_64))){
2319#ifdef ALIGNMENT_CHECKS_ARCHIVE_64_BIT
2320			if(archive_64_bit_align_warning == FALSE &&
2321			   (offset + ar_name_size) % 8 != 0){
2322			    temporary_archive_member_warning(ofile, "offset in "
2323				"archive not a multiple of 8) (must be since "
2324				"member is a 64-bit object file)");
2325			    archive_64_bit_align_warning = TRUE;
2326			    /* goto cleanup; */
2327			}
2328#endif /* ALIGNMENT_CHECKS_ARCHIVE_64_BIT */
2329			ofile->member_type = OFILE_Mach_O;
2330			ofile->object_addr = ofile->member_addr;
2331			ofile->object_size = ofile->member_size;
2332			if(magic == MH_MAGIC_64)
2333			    ofile->object_byte_sex = host_byte_sex;
2334			else
2335			    ofile->object_byte_sex =
2336				   host_byte_sex == BIG_ENDIAN_BYTE_SEX ?
2337				   LITTLE_ENDIAN_BYTE_SEX : BIG_ENDIAN_BYTE_SEX;
2338			ofile->mh64 = (struct mach_header_64 *)
2339				      ofile->object_addr;
2340			ofile->load_commands = (struct load_command *)
2341			    (ofile->object_addr +sizeof(struct mach_header_64));
2342			if(check_Mach_O(ofile) == CHECK_BAD)
2343			    goto cleanup;
2344		    }
2345		}
2346#ifdef LTO_SUPPORT
2347		if(ofile->member_type == OFILE_UNKNOWN &&
2348		   is_llvm_bitcode(ofile, ofile->member_addr,
2349				   ofile->member_size) == TRUE){
2350		    ofile->member_type = OFILE_LLVM_BITCODE;
2351		    ofile->object_addr = ofile->member_addr;
2352		    ofile->object_size = ofile->member_size;
2353		}
2354#endif /* LTO_SUPPORT */
2355		return(TRUE);
2356	    }
2357	    offset += rnd(strtoul(ar_hdr->ar_size, NULL, 10),
2358			    sizeof(short));
2359	}
2360	archive_error(ofile, "does not contain a member named: %s",
2361		      member_name);
2362fatcleanup:
2363	ofile->fat_header = NULL;
2364	ofile->fat_archs = NULL;
2365cleanup:
2366	ofile->member_offset = 0;
2367	ofile->member_addr = NULL;
2368	ofile->member_size = 0;
2369	ofile->member_ar_hdr = NULL;
2370	ofile->member_name = NULL;
2371	ofile->member_name_size = 0;
2372	ofile->member_type = OFILE_UNKNOWN;
2373	ofile->object_addr = NULL;
2374	ofile->object_size = 0;
2375	ofile->object_byte_sex = UNKNOWN_BYTE_SEX;
2376	ofile->mh = NULL;
2377	ofile->mh64 = NULL;
2378	ofile->load_commands = NULL;
2379#ifdef LTO_SUPPORT
2380	ofile->lto = NULL;
2381	ofile->lto_cputype = 0;
2382	ofile->lto_cpusubtype = 0;
2383#endif /* LTO_SUPPORT */
2384	return(FALSE);
2385}
2386
2387/*
2388 * ofile_first_module() set up the ofile structure (the dylib_module field)
2389 * for the first module of an MH_DYLIB or MH_DYLIB_STUB file.
2390 */
2391__private_extern__
2392enum bool
2393ofile_first_module(
2394struct ofile *ofile)
2395{
2396    uint32_t i, ncmds;
2397    struct symtab_command *st;
2398    struct dysymtab_command *dyst;
2399    struct load_command *lc;
2400    enum bool swapped;
2401    enum byte_sex host_byte_sex;
2402    struct dylib_module m;
2403    struct dylib_module_64 m64;
2404    char *strings;
2405
2406	/* These fields are to be filled in by this routine, clear them first */
2407	ofile->modtab = NULL;
2408	ofile->modtab64 = NULL;
2409	ofile->nmodtab = 0;
2410	ofile->dylib_module = NULL;
2411	ofile->dylib_module64 = NULL;
2412	ofile->dylib_module_name = NULL;
2413
2414	if(ofile->file_type == OFILE_FAT){
2415	    if(ofile->arch_type != OFILE_Mach_O &&
2416	       (ofile->mh_filetype != MH_DYLIB &&
2417	        ofile->mh_filetype != MH_DYLIB_STUB)){
2418		error("ofile_first_module() called on fat file: %s with a "
2419		      "non-MH_DYLIB architecture or no architecture selected\n",
2420		      ofile->file_name);
2421		return(FALSE);
2422	    }
2423	}
2424	else if(ofile->arch_type != OFILE_Mach_O &&
2425	        (ofile->mh_filetype != MH_DYLIB &&
2426	         ofile->mh_filetype != MH_DYLIB_STUB)){
2427	    error("ofile_first_module() called and file type of %s is "
2428		  "non-MH_DYLIB\n", ofile->file_name);
2429	    return(FALSE);
2430	}
2431
2432	st = NULL;
2433	dyst = NULL;
2434	lc = ofile->load_commands;
2435	if(ofile->mh != NULL)
2436	    ncmds = ofile->mh->ncmds;
2437	else
2438	    ncmds = ofile->mh64->ncmds;
2439	for(i = 0; i < ncmds; i++){
2440	    if(st == NULL && lc->cmd == LC_SYMTAB){
2441		st = (struct symtab_command *)lc;
2442	    }
2443	    else if(lc->cmd == LC_DYSYMTAB){
2444		dyst = (struct dysymtab_command *)lc;
2445	    }
2446	    lc = (struct load_command *)((char *)lc + lc->cmdsize);
2447	}
2448	if(st == NULL || dyst == NULL){
2449#ifndef OTOOL
2450	    Mach_O_error(ofile, "MH_DYLIB format error (does not have a symbol "
2451		"table and/or a dynamic symbol table)");
2452#endif
2453	    return(FALSE);
2454	}
2455	if(dyst->nmodtab == 0)
2456	    return(FALSE);
2457
2458	ofile->nmodtab = dyst->nmodtab;
2459	host_byte_sex = get_host_byte_sex();
2460	swapped = (enum bool)(host_byte_sex != ofile->object_byte_sex);
2461	strings = (char *)(ofile->object_addr + st->stroff);
2462
2463	if(ofile->mh != NULL){
2464	    ofile->modtab = (struct dylib_module *)(ofile->object_addr +
2465						    dyst->modtaboff);
2466	    ofile->dylib_module = ofile->modtab;
2467	    m = *ofile->dylib_module;
2468	    if(swapped)
2469		swap_dylib_module(&m, 1, host_byte_sex);
2470	    ofile->dylib_module_name = strings + m.module_name;
2471	}
2472	else{
2473	    ofile->modtab64 = (struct dylib_module_64 *)(ofile->object_addr +
2474						         dyst->modtaboff);
2475	    ofile->dylib_module64 = ofile->modtab64;
2476	    m64 = *ofile->dylib_module64;
2477	    if(swapped)
2478		swap_dylib_module_64(&m64, 1, host_byte_sex);
2479	    ofile->dylib_module_name = strings + m64.module_name;
2480	}
2481
2482	if(check_dylib_module(ofile, st, dyst, strings, 0) == CHECK_BAD)
2483	    return(FALSE);
2484	return(TRUE);
2485}
2486
2487/*
2488 * ofile_next_module() set up the ofile structure (the dylib_module field)
2489 * for the next module of an MH_DYLIB or MH_DYLIB_STUB file.
2490 */
2491__private_extern__
2492enum bool
2493ofile_next_module(
2494struct ofile *ofile)
2495{
2496    uint32_t i, module_index, ncmds;
2497    struct symtab_command *st;
2498    struct dysymtab_command *dyst;
2499    struct load_command *lc;
2500    enum bool swapped;
2501    enum byte_sex host_byte_sex;
2502    struct dylib_module m;
2503    struct dylib_module_64 m64;
2504    char *strings;
2505
2506	if(ofile->file_type == OFILE_FAT){
2507	    if(ofile->arch_type != OFILE_Mach_O &&
2508	       (ofile->mh_filetype != MH_DYLIB &&
2509	        ofile->mh_filetype != MH_DYLIB_STUB)){
2510		error("ofile_next_module() called on fat file: %s with a "
2511		      "non-MH_DYLIB architecture or no architecture selected\n",
2512		      ofile->file_name);
2513		return(FALSE);
2514	    }
2515	}
2516	else if(ofile->arch_type != OFILE_Mach_O &&
2517	        (ofile->mh_filetype != MH_DYLIB &&
2518	         ofile->mh_filetype != MH_DYLIB_STUB)){
2519	    error("ofile_next_module() called and file type of %s is "
2520		  "non-MH_DYLIB\n", ofile->file_name);
2521	    return(FALSE);
2522	}
2523	st = NULL;
2524	dyst = NULL;
2525	lc = ofile->load_commands;
2526	if(ofile->mh != NULL)
2527	    ncmds = ofile->mh->ncmds;
2528	else
2529	    ncmds = ofile->mh64->ncmds;
2530	for(i = 0; i < ncmds; i++){
2531	    if(st == NULL && lc->cmd == LC_SYMTAB){
2532		st = (struct symtab_command *)lc;
2533	    }
2534	    else if(lc->cmd == LC_DYSYMTAB){
2535		dyst = (struct dysymtab_command *)lc;
2536	    }
2537	    lc = (struct load_command *)((char *)lc + lc->cmdsize);
2538	}
2539	if(st == NULL || dyst == NULL){
2540#ifndef OTOOL
2541	    Mach_O_error(ofile, "MH_DYLIB format error (does not have a symbol "
2542		"table and/or a dynamic symbol table)");
2543#endif
2544	    return(FALSE);
2545	}
2546
2547	if(ofile->mh != NULL)
2548	    module_index = (ofile->dylib_module + 1) - ofile->modtab;
2549	else
2550	    module_index = (ofile->dylib_module64 + 1) - ofile->modtab64;
2551	if(module_index >= ofile->nmodtab)
2552	    return(FALSE);
2553
2554	host_byte_sex = get_host_byte_sex();
2555	swapped = (enum bool)(host_byte_sex != ofile->object_byte_sex);
2556	strings = (char *)(ofile->object_addr + st->stroff);
2557
2558	if(ofile->mh != NULL){
2559	    ofile->dylib_module++;
2560	    m = *ofile->dylib_module;
2561	    if(swapped)
2562		swap_dylib_module(&m, 1, host_byte_sex);
2563	    ofile->dylib_module_name = strings + m.module_name;
2564	}
2565	else{
2566	    ofile->dylib_module64++;
2567	    m64 = *ofile->dylib_module64;
2568	    if(swapped)
2569		swap_dylib_module_64(&m64, 1, host_byte_sex);
2570	    ofile->dylib_module_name = strings + m64.module_name;
2571	}
2572	if(check_dylib_module(ofile, st, dyst, strings, module_index) ==
2573	   CHECK_BAD)
2574	    return(FALSE);
2575	return(TRUE);
2576}
2577
2578/*
2579 * ofile_specific_module() set up the ofile structure (the dylib_module fields)
2580 * for the specified module, module_name, of an MH_DYLIB or an MH_DYLIB_STUB
2581 * file.
2582 */
2583__private_extern__
2584enum bool
2585ofile_specific_module(
2586const char *module_name,
2587struct ofile *ofile)
2588{
2589    uint32_t i, ncmds;
2590    enum bool swapped;
2591    enum byte_sex host_byte_sex;
2592    struct symtab_command *st;
2593    struct dysymtab_command *dyst;
2594    struct load_command *lc;
2595    struct dylib_module *p, m;
2596    struct dylib_module_64 *p64, m64;
2597    char *strings;
2598
2599	/* These fields are to be filled in by this routine, clear them first */
2600	ofile->modtab = NULL;
2601	ofile->modtab64 = NULL;
2602	ofile->nmodtab = 0;
2603	ofile->dylib_module = NULL;
2604	ofile->dylib_module64 = NULL;
2605	ofile->dylib_module_name = NULL;
2606
2607	if(ofile->file_type == OFILE_FAT){
2608	    if(ofile->arch_type != OFILE_Mach_O &&
2609	       (ofile->mh_filetype != MH_DYLIB &&
2610	        ofile->mh_filetype != MH_DYLIB_STUB)){
2611		error("ofile_specific_module() called on fat file: %s with a "
2612		      "non-MH_DYLIB architecture or no architecture selected\n",
2613		      ofile->file_name);
2614		return(FALSE);
2615	    }
2616	}
2617	else if(ofile->arch_type != OFILE_Mach_O &&
2618	        (ofile->mh_filetype != MH_DYLIB &&
2619	         ofile->mh_filetype != MH_DYLIB_STUB)){
2620	    error("ofile_specific_module() called and file type of %s is "
2621		  "non-MH_DYLIB\n", ofile->file_name);
2622	    return(FALSE);
2623	}
2624
2625	st = NULL;
2626	dyst = NULL;
2627	lc = ofile->load_commands;
2628	if(ofile->mh != NULL)
2629	    ncmds = ofile->mh->ncmds;
2630	else
2631	    ncmds = ofile->mh64->ncmds;
2632	for(i = 0; i < ncmds; i++){
2633	    if(st == NULL && lc->cmd == LC_SYMTAB){
2634		st = (struct symtab_command *)lc;
2635	    }
2636	    else if(lc->cmd == LC_DYSYMTAB){
2637		dyst = (struct dysymtab_command *)lc;
2638	    }
2639	    lc = (struct load_command *)((char *)lc + lc->cmdsize);
2640	}
2641	if(st == NULL || dyst == NULL){
2642#ifndef OTOOL
2643	    Mach_O_error(ofile, "MH_DYLIB format error (does not have a symbol "
2644		"table and/or a dynamic symbol table)");
2645#endif
2646	    return(FALSE);
2647	}
2648	if(dyst->nmodtab == 0)
2649	    return(FALSE);
2650
2651	host_byte_sex = get_host_byte_sex();
2652	swapped = (enum bool)(host_byte_sex != ofile->object_byte_sex);
2653	strings = (char *)(ofile->object_addr + st->stroff);
2654
2655	if(ofile->mh != NULL){
2656	    ofile->nmodtab = dyst->nmodtab;
2657	    ofile->modtab = (struct dylib_module *)(ofile->object_addr +
2658						    dyst->modtaboff);
2659	    p = ofile->modtab;
2660	    for(i = 0; i < dyst->nmodtab; i++){
2661		m = *p;
2662		if(swapped)
2663		    swap_dylib_module(&m, 1, host_byte_sex);
2664		ofile->dylib_module = p;
2665		if(check_dylib_module(ofile, st, dyst, strings, i) == CHECK_BAD)
2666		    return(FALSE);
2667		if(strcmp(module_name, strings + m.module_name) == 0){
2668		    ofile->dylib_module_name = strings + m.module_name;
2669		    return(TRUE);
2670		}
2671		p++;
2672	    }
2673	    m = *ofile->dylib_module;
2674	    if(swapped)
2675		swap_dylib_module(&m, 1, host_byte_sex);
2676	    ofile->dylib_module_name = strings + m.module_name;
2677	}
2678	else{
2679	    ofile->nmodtab = dyst->nmodtab;
2680	    ofile->modtab64 = (struct dylib_module_64 *)(ofile->object_addr +
2681						         dyst->modtaboff);
2682	    p64 = ofile->modtab64;
2683	    for(i = 0; i < dyst->nmodtab; i++){
2684		m64 = *p64;
2685		if(swapped)
2686		    swap_dylib_module_64(&m64, 1, host_byte_sex);
2687		ofile->dylib_module64 = p64;
2688		if(check_dylib_module(ofile, st, dyst, strings, i) == CHECK_BAD)
2689		    return(FALSE);
2690		if(strcmp(module_name, strings + m64.module_name) == 0){
2691		    ofile->dylib_module_name = strings + m64.module_name;
2692		    return(TRUE);
2693		}
2694		p64++;
2695	    }
2696	    m64 = *ofile->dylib_module64;
2697	    if(swapped)
2698		swap_dylib_module_64(&m64, 1, host_byte_sex);
2699	    ofile->dylib_module_name = strings + m64.module_name;
2700	}
2701#ifndef OTOOL
2702	Mach_O_error(ofile, "does not contain a module named: %s", module_name);
2703#endif
2704	ofile->modtab = NULL;
2705	ofile->nmodtab = 0;
2706	ofile->dylib_module = NULL;
2707	ofile->dylib_module_name = NULL;
2708	return(FALSE);
2709}
2710
2711#ifdef DEBUG
2712__private_extern__
2713void
2714ofile_print(
2715struct ofile *ofile)
2716{
2717	printf("file_name = %s\n", ofile->file_name);
2718	printf("file_addr = 0x%x\n", (unsigned int)ofile->file_addr);
2719	printf("file_size = 0x%x\n", (unsigned int)ofile->file_size);
2720	printf("file_type = 0x%x\n", (unsigned int)ofile->file_type);
2721	printf("fat_header = 0x%x\n", (unsigned int)ofile->fat_header);
2722	printf("fat_archs = 0x%x\n", (unsigned int)ofile->fat_archs);
2723	printf("narch = 0x%x\n", (unsigned int)ofile->narch);
2724	printf("arch_type = 0x%x\n", (unsigned int)ofile->arch_type);
2725	printf("arch_flag.name = %s\n", ofile->arch_flag.name);
2726	printf("arch_flag.cputype = 0x%x\n",
2727		(unsigned int)ofile->arch_flag.cputype);
2728	printf("arch_flag.cpusubtype = 0x%x\n",
2729		(unsigned int)ofile->arch_flag.cpusubtype);
2730	printf("member_offset = 0x%x\n", (unsigned int)ofile->member_offset);
2731	printf("member_addr = 0x%x\n", (unsigned int)ofile->member_addr);
2732	printf("member_size = 0x%x\n", (unsigned int)ofile->member_size);
2733	printf("member_ar_hdr = 0x%x\n", (unsigned int)ofile->member_ar_hdr);
2734	printf("member_type = 0x%x\n", (unsigned int)ofile->member_type);
2735	printf("archive_cputype = 0x%x\n",
2736		(unsigned int)ofile->archive_cputype);
2737	printf("archive_cpusubtype = 0x%x\n",
2738		(unsigned int)ofile->archive_cpusubtype);
2739	printf("object_addr = 0x%x\n", (unsigned int)ofile->object_addr);
2740	printf("object_size = 0x%x\n", (unsigned int)ofile->object_size);
2741	printf("object_byte_sex = 0x%x\n",
2742		(unsigned int)ofile->object_byte_sex);
2743	printf("mh = 0x%x\n", (unsigned int)ofile->mh);
2744	printf("mh64 = 0x%x\n", (unsigned int)ofile->mh64);
2745	printf("load_commands = 0x%x\n", (unsigned int)ofile->load_commands);
2746}
2747#endif /* DEBUG */
2748
2749/*
2750 * check_fat() checks the fat ofile for correctness (the fat_header and
2751 * fat_archs are assumed to be in the host byte sex).
2752 */
2753static
2754enum check_type
2755check_fat(
2756struct ofile *ofile)
2757{
2758#ifdef OTOOL
2759	return(CHECK_GOOD);
2760#else /* !defined OTOOL */
2761
2762    uint32_t i, j;
2763    uint64_t big_size;
2764
2765	if(ofile->file_type != OFILE_FAT){
2766	    error("internal error. check_fat() call and file type of: %s is "
2767		  "not OFILE_FAT\n", ofile->file_name);
2768	    return(CHECK_BAD);
2769	}
2770	if(ofile->fat_header->nfat_arch == 0){
2771	    error("fat file: %s malformed (contains zero architecture types)",
2772		  ofile->file_name);
2773	    return(CHECK_BAD);
2774	}
2775	for(i = 0; i < ofile->fat_header->nfat_arch; i++){
2776	    big_size = ofile->fat_archs[i].offset;
2777	    big_size += ofile->fat_archs[i].size;
2778	    if(big_size > ofile->file_size){
2779		error("fat file: %s truncated or malformed (offset plus size "
2780		      "of cputype (%d) cpusubtype (%d) extends past the "
2781		      "end of the file)", ofile->file_name,
2782		      ofile->fat_archs[i].cputype,
2783		      ofile->fat_archs[i].cpusubtype & ~CPU_SUBTYPE_MASK);
2784		return(CHECK_BAD);
2785	    }
2786	    if(ofile->fat_archs[i].align > MAXSECTALIGN){
2787		error("fat file: %s align (2^%u) too large for cputype (%d) "
2788		      "cpusubtype (%d) (maximum 2^%d)", ofile->file_name,
2789		      ofile->fat_archs[i].align, ofile->fat_archs[i].cputype,
2790		      ofile->fat_archs[i].cpusubtype & ~CPU_SUBTYPE_MASK,
2791		      MAXSECTALIGN);
2792		return(CHECK_BAD);
2793	    }
2794	    if(ofile->fat_archs[i].offset %
2795	       (1 << ofile->fat_archs[i].align) != 0){
2796		error("fat file: %s offset: %u for cputype (%d) cpusubtype "
2797		      "(%d)) not aligned on it's alignment (2^%u)",
2798		      ofile->file_name,
2799		      ofile->fat_archs[i].offset,
2800		      ofile->fat_archs[i].cputype,
2801		      ofile->fat_archs[i].cpusubtype & ~CPU_SUBTYPE_MASK,
2802		      ofile->fat_archs[i].align);
2803		return(CHECK_BAD);
2804	    }
2805	}
2806	for(i = 0; i < ofile->fat_header->nfat_arch; i++){
2807	    for(j = i + 1; j < ofile->fat_header->nfat_arch; j++){
2808		if(ofile->fat_archs[i].cputype ==
2809		     ofile->fat_archs[j].cputype &&
2810		   (ofile->fat_archs[i].cpusubtype & ~CPU_SUBTYPE_MASK) ==
2811		     (ofile->fat_archs[j].cpusubtype & ~CPU_SUBTYPE_MASK)){
2812		    error("fat file: %s contains two of the same "
2813			  "architecture (cputype (%d) cpusubtype (%d))",
2814			  ofile->file_name, ofile->fat_archs[i].cputype,
2815			  ofile->fat_archs[i].cpusubtype & ~CPU_SUBTYPE_MASK);
2816		    return(CHECK_BAD);
2817		}
2818	    }
2819	}
2820	return(CHECK_GOOD);
2821#endif /* OTOOL */
2822}
2823
2824/*
2825 * check_fat_object_in_archive() checks the fat object file which is a member
2826 * of a thin archive for correctness (the fat_header and fat_archs are assumed
2827 * to be in the host byte sex).  This is not a legal form but allowed when
2828 * archives_with_fat_objects is TRUE when ofile_map() is called.
2829 */
2830static
2831enum check_type
2832check_fat_object_in_archive(
2833struct ofile *ofile)
2834{
2835    uint32_t i, j;
2836    uint32_t magic;
2837
2838	if(ofile->file_type != OFILE_ARCHIVE){
2839	    error("internal error. check_fat_object_in_archive() called and "
2840		  "file type of: %s is not OFILE_ARCHIVE\n", ofile->file_name);
2841	    return(CHECK_BAD);
2842	}
2843	if(ofile->fat_header->nfat_arch == 0){
2844	    archive_member_error(ofile, "fat file malformed (contains zero "
2845				 "architecture types)");
2846	    return(CHECK_BAD);
2847	}
2848	for(i = 0; i < ofile->fat_header->nfat_arch; i++){
2849	    if(ofile->fat_archs[i].offset + ofile->fat_archs[i].size >
2850	       ofile->member_size){
2851		archive_member_error(ofile, "fat file truncated or malformed "
2852			"(offset plus size of cputype (%d) cpusubtype (%d) "
2853			"extends past the end of the file)",
2854		        ofile->fat_archs[i].cputype,
2855		        ofile->fat_archs[i].cpusubtype & ~CPU_SUBTYPE_MASK);
2856		return(CHECK_BAD);
2857	    }
2858	    if(ofile->fat_archs[i].align > MAXSECTALIGN){
2859		archive_member_error(ofile, "fat file's align (2^%u) too "
2860			"large for cputype (%d) cpusubtype (%d) (maximum 2^%d)",
2861			ofile->fat_archs[i].align, ofile->fat_archs[i].cputype,
2862			ofile->fat_archs[i].cpusubtype & ~CPU_SUBTYPE_MASK,
2863			MAXSECTALIGN);
2864		return(CHECK_BAD);
2865	    }
2866	    if(ofile->fat_archs[i].offset %
2867	       (1 << ofile->fat_archs[i].align) != 0){
2868		archive_member_error(ofile, "fat file's offset: %u for "
2869			"cputype (%d) cpusubtype (%d) not aligned on it's "
2870			"alignment (2^%u)", ofile->fat_archs[i].offset,
2871			ofile->fat_archs[i].cputype,
2872			ofile->fat_archs[i].cpusubtype & ~CPU_SUBTYPE_MASK,
2873			ofile->fat_archs[i].align);
2874		return(CHECK_BAD);
2875	    }
2876
2877	    /*
2878	     * The only supported format where fat files are allowed to appear
2879	     * in archives is when the fat file contains only object files.
2880	     */
2881	    if(ofile->fat_archs[i].size < sizeof(struct mach_header)){
2882		archive_member_error(ofile, "fat file for cputype (%d) "
2883			"cpusubtype (%d) is not an object file (size too small "
2884			"to be an object file)", ofile->fat_archs[i].cputype,
2885			ofile->fat_archs[i].cpusubtype & ~CPU_SUBTYPE_MASK);
2886		return(CHECK_BAD);
2887	    }
2888	    memcpy(&magic,
2889		   ofile->file_addr + ofile->member_offset +
2890			ofile->fat_archs[i].offset,
2891		   sizeof(uint32_t));
2892	    if(magic == MH_MAGIC || magic == SWAP_INT(MH_MAGIC)){
2893#ifdef ALIGNMENT_CHECKS
2894		if((ofile->member_offset + ofile->fat_archs[i].offset) %
2895		   4 != 0){
2896		    archive_member_error(ofile, "fat object file's offset in "
2897			    "archive not a multiple of 4) (must be since "
2898			    "member is a 32-bit object file)");
2899		    return(CHECK_BAD);
2900		}
2901#endif /* ALIGNMENT_CHECKS */
2902	    }
2903	    else if(magic == MH_MAGIC_64 || magic == SWAP_INT(MH_MAGIC_64)){
2904#ifdef ALIGNMENT_CHECKS_ARCHIVE_64_BIT
2905		if(archive_64_bit_align_warning == FALSE &&
2906		   (ofile->member_offset + ofile->fat_archs[i].offset) %
2907		   8 != 0){
2908		    temporary_archive_member_warning(ofile, "fat object file's "
2909			"offset in archive not a multiple of 8) (must be since "
2910			"member is a 64-bit object file)");
2911		    archive_64_bit_align_warning = TRUE;
2912		    /* return(CHECK_BAD); */
2913		}
2914#endif /* ALIGNMENT_CHECKS_ARCHIVE_64_BIT */
2915	    }
2916	    else{
2917#ifdef LTO_SUPPORT
2918	        if(is_llvm_bitcode(ofile, ofile->file_addr +
2919		   ofile->member_offset + ofile->fat_archs[i].offset,
2920		   ofile->fat_archs[i].size) == TRUE){
2921		    ofile->member_type = OFILE_LLVM_BITCODE;
2922		    ofile->object_addr = ofile->member_addr;
2923		    ofile->object_size = ofile->member_size;
2924	        }
2925		else
2926#endif /* LTO_SUPPORT */
2927		{
2928		    archive_member_error(ofile, "fat file for cputype (%d) "
2929			    "cpusubtype (%d) is not an object file (bad magic "
2930			    "number)", ofile->fat_archs[i].cputype,
2931			    ofile->fat_archs[i].cpusubtype & ~CPU_SUBTYPE_MASK);
2932		    return(CHECK_BAD);
2933		}
2934	    }
2935	}
2936	for(i = 0; i < ofile->fat_header->nfat_arch; i++){
2937	    for(j = i + 1; j < ofile->fat_header->nfat_arch; j++){
2938		if(ofile->fat_archs[i].cputype ==
2939		     ofile->fat_archs[j].cputype &&
2940		   (ofile->fat_archs[i].cpusubtype & ~CPU_SUBTYPE_MASK) ==
2941		     (ofile->fat_archs[j].cpusubtype & ~CPU_SUBTYPE_MASK)){
2942		    archive_member_error(ofile, "fat file contains two of the "
2943			"same architecture (cputype (%d) cpusubtype (%d))",
2944			ofile->fat_archs[i].cputype,
2945			ofile->fat_archs[i].cpusubtype & ~CPU_SUBTYPE_MASK);
2946		    return(CHECK_BAD);
2947		}
2948	    }
2949	}
2950	return(CHECK_GOOD);
2951}
2952
2953/*
2954 * check_archive() checks the archive referenced in the ofile for correctness.
2955 */
2956static
2957enum check_type
2958check_archive(
2959struct ofile *ofile,
2960enum bool archives_with_fat_objects)
2961{
2962#ifdef OTOOL
2963	return(CHECK_GOOD);
2964#else /* !defined OTOOL */
2965    char *addr;
2966    uint64_t size, offset;
2967    uint64_t big_size;
2968    uint32_t magic;
2969    enum byte_sex host_byte_sex;
2970    enum bool swapped;
2971    struct mach_header mh;
2972    struct mach_header_64 mh64;
2973    struct ar_hdr *ar_hdr;
2974    uint32_t ar_name_size;
2975
2976	/*
2977	 * Get the address and size of the archive (as well as the cputype and
2978	 * cpusubtype if known) and make sure it is an archive.
2979	 */
2980	if(ofile->file_type == OFILE_FAT){
2981	    addr = ofile->file_addr + ofile->fat_archs[ofile->narch].offset;
2982	    size = ofile->fat_archs[ofile->narch].size;
2983	    ofile->archive_cputype = ofile->fat_archs[ofile->narch].cputype;
2984	    ofile->archive_cpusubtype =
2985				     ofile->fat_archs[ofile->narch].cpusubtype;
2986	}
2987	else if(ofile->file_type == OFILE_ARCHIVE){
2988	    addr = ofile->file_addr;
2989	    size = ofile->file_size;
2990	    ofile->archive_cputype = 0;
2991	    ofile->archive_cpusubtype = 0;
2992	}
2993	else{
2994	    error("internal error. check_archive() call and file type of %s is "
2995		  "OFILE_UNKNOWN\n", ofile->file_name);
2996	    return(CHECK_BAD);
2997	}
2998	if(size < SARMAG || strncmp(addr, ARMAG, SARMAG) != 0){
2999	    error("internal error. check_archive() call for file %s which does "
3000		  "not have an archive magic string", ofile->file_name);
3001	    return(CHECK_BAD);
3002	}
3003
3004	host_byte_sex = get_host_byte_sex();
3005	/*
3006	 * Check this archive out to make sure that it does not contain
3007	 * any fat files and that all object files it contains have the
3008	 * same cputype and subsubtype.
3009	 */
3010	offset = SARMAG;
3011	if(offset == size)
3012	    return(CHECK_GOOD);
3013	if(offset != size && offset + sizeof(struct ar_hdr) > size){
3014	    archive_error(ofile, "truncated or malformed (archive header of "
3015			  "first member extends past the end of the file)");
3016	    return(CHECK_BAD);
3017	}
3018	while(size > offset){
3019	    ar_hdr = (struct ar_hdr *)(addr + offset);
3020	    ofile->member_offset = offset;
3021	    ofile->member_addr = addr + offset;
3022	    ofile->member_size = strtoul(ar_hdr->ar_size, NULL, 10);
3023	    ofile->member_ar_hdr = ar_hdr;
3024	    ofile->member_name = ar_hdr->ar_name;
3025	    ofile->member_name_size = size_ar_name(ofile->member_ar_hdr);
3026	    offset += sizeof(struct ar_hdr);
3027	    /*
3028	     * See if this archive member is using extend format #1 where
3029	     * the size of the name is in ar_name and the name follows the
3030	     * archive header.
3031	     */
3032	    ar_name_size = 0;
3033	    if(strncmp(ofile->member_name,AR_EFMT1, sizeof(AR_EFMT1) - 1) == 0){
3034		if(check_extend_format_1(ofile, ar_hdr, size - offset,
3035				&ar_name_size) == CHECK_BAD)
3036		    return(CHECK_BAD);
3037		ofile->member_name = ar_hdr->ar_name + sizeof(struct ar_hdr);
3038		ofile->member_name_size = ar_name_size;
3039		offset += ar_name_size;
3040		ofile->member_offset += ar_name_size;
3041		ofile->member_addr += ar_name_size;
3042		ofile->member_size -= ar_name_size;
3043	    }
3044	    big_size = rnd(ofile->member_size, sizeof(short));
3045	    big_size += offset;
3046	    if(big_size > size){
3047		archive_member_error(ofile, "size too large (archive "
3048			      "member extends past the end of the file)");
3049		return(CHECK_BAD);
3050	    }
3051	    if(size - offset > sizeof(uint32_t)){
3052		memcpy(&magic, addr + offset, sizeof(uint32_t));
3053#ifdef __BIG_ENDIAN__
3054		if(magic == FAT_MAGIC)
3055#endif /* __BIG_ENDIAN__ */
3056#ifdef __LITTLE_ENDIAN__
3057		if(magic == SWAP_INT(FAT_MAGIC))
3058#endif /* __LITTLE_ENDIAN__ */
3059		{
3060		    if(archives_with_fat_objects == FALSE ||
3061		       ofile->file_type != OFILE_ARCHIVE){
3062			archive_member_error(ofile, "is a fat file (not "
3063					     "allowed in an archive)");
3064			return(CHECK_BAD);
3065		    }
3066		}
3067		else{
3068		    if(size - offset >= sizeof(struct mach_header) &&
3069		       (magic == MH_MAGIC || magic == SWAP_INT(MH_MAGIC))){
3070			memcpy(&mh, addr + offset, sizeof(struct mach_header));
3071			if(magic == SWAP_INT(MH_MAGIC)){
3072			    magic = MH_MAGIC;
3073			    swapped = TRUE;
3074			    swap_mach_header(&mh, host_byte_sex);
3075			}
3076			swapped = FALSE;
3077		    }
3078		    else if(size - offset >= sizeof(struct mach_header_64) &&
3079		       (magic == MH_MAGIC_64 ||
3080			magic == SWAP_INT(MH_MAGIC_64))){
3081			memcpy(&mh64, addr + offset,
3082			       sizeof(struct mach_header_64));
3083			if(magic == SWAP_INT(MH_MAGIC_64)){
3084			    magic = MH_MAGIC_64;
3085			    swapped = TRUE;
3086			    swap_mach_header_64(&mh64, host_byte_sex);
3087			}
3088			swapped = FALSE;
3089		    }
3090		    if(magic == MH_MAGIC){
3091			if(ofile->archive_cputype == 0){
3092			    ofile->archive_cputype = mh.cputype;
3093			    ofile->archive_cpusubtype = mh.cpusubtype;
3094			}
3095			else if(ofile->archive_cputype != mh.cputype){
3096			    archive_member_error(ofile, "cputype (%d) does not "
3097				"match previous archive members cputype (%d) "
3098				"(all members must match)", mh.cputype,
3099				ofile->archive_cputype);
3100			}
3101		    }
3102		    else if(magic == MH_MAGIC_64){
3103			if(ofile->archive_cputype == 0){
3104			    ofile->archive_cputype = mh64.cputype;
3105			    ofile->archive_cpusubtype = mh64.cpusubtype;
3106			}
3107			else if(ofile->archive_cputype != mh64.cputype){
3108			    archive_member_error(ofile, "cputype (%d) does not "
3109				"match previous archive members cputype (%d) "
3110				"(all members must match)", mh64.cputype,
3111				ofile->archive_cputype);
3112			}
3113		    }
3114		}
3115	    }
3116	    offset += rnd(ofile->member_size, sizeof(short));
3117	}
3118	ofile->member_offset = 0;
3119	ofile->member_addr = NULL;
3120	ofile->member_size = 0;
3121	ofile->member_ar_hdr = NULL;;
3122	ofile->member_name = NULL;
3123	ofile->member_name_size = 0;
3124	return(CHECK_GOOD);
3125#endif /* OTOOL */
3126}
3127
3128/*
3129 * check_extend_format_1() checks the archive header for extended format #1.
3130 */
3131static
3132enum check_type
3133check_extend_format_1(
3134struct ofile *ofile,
3135struct ar_hdr *ar_hdr,
3136uint32_t size_left,
3137uint32_t *member_name_size)
3138{
3139    char *p, *endp, buf[sizeof(ar_hdr->ar_name)+1];
3140    uint32_t ar_name_size;
3141
3142	*member_name_size = 0;
3143
3144	buf[sizeof(ar_hdr->ar_name)] = '\0';
3145	memcpy(buf, ar_hdr->ar_name, sizeof(ar_hdr->ar_name));
3146	p = buf + sizeof(AR_EFMT1) - 1;
3147	if(isdigit(*p) == 0){
3148	    archive_error(ofile, "malformed (ar_name: %.*s for archive "
3149		"extend format #1 starts with non-digit)",
3150		(int)sizeof(ar_hdr->ar_name), ar_hdr->ar_name);
3151	    return(CHECK_BAD);
3152	}
3153	ar_name_size = strtoul(p, &endp, 10);
3154	if(ar_name_size == UINT_MAX && errno == ERANGE){
3155	    archive_error(ofile, "malformed (size in ar_name: %.*s for "
3156		"archive extend format #1 overflows uint32_t)",
3157		(int)sizeof(ar_hdr->ar_name), ar_hdr->ar_name);
3158	    return(CHECK_BAD);
3159	}
3160	while(*endp == ' ' && *endp != '\0')
3161	    endp++;
3162	if(*endp != '\0'){
3163	    archive_error(ofile, "malformed (size in ar_name: %.*s for "
3164		"archive extend format #1 contains non-digit and "
3165		"non-space characters)", (int)sizeof(ar_hdr->ar_name),
3166		ar_hdr->ar_name);
3167	    return(CHECK_BAD);
3168	}
3169	if(ar_name_size > size_left){
3170	    archive_error(ofile, "truncated or malformed (archive name "
3171		"of member extends past the end of the file)");
3172	    return(CHECK_BAD);
3173	}
3174	*member_name_size = ar_name_size;
3175	return(CHECK_GOOD);
3176}
3177
3178/*
3179 * check_archive_toc() checks the archive table of contents referenced in the
3180 * thin archive via the ofile for correctness and if bad sets the bad_toc field
3181 * in the ofile struct to TRUE.   If not it sets the other toc_* fields that
3182 * ranlib(1) uses to know it can't update the table of contents and doesn't
3183 * have to totally rebuild it.  And by this always returning CHECK_GOOD it
3184 * allows otool(1) to print messed up tables of contents for debugging.
3185 */
3186static
3187enum check_type
3188check_archive_toc(
3189struct ofile *ofile)
3190{
3191    uint32_t i, symdef_length, offset, nranlibs, strsize;
3192    enum byte_sex host_byte_sex, toc_byte_sex;
3193    struct ranlib *ranlibs;
3194    char *strings;
3195
3196	ofile->toc_ranlibs = NULL;
3197	ofile->toc_nranlibs = 0;
3198	ofile->toc_strings = NULL;
3199	ofile->toc_strsize = 0;
3200
3201	/*
3202	 * Note this can only be called when the whole file is a thin archive.
3203	 */
3204	if(ofile->file_type != OFILE_ARCHIVE)
3205	    return(CHECK_GOOD);
3206
3207	symdef_length = ofile->toc_size;
3208	/*
3209	 * The contents of a __.SYMDEF file is begins with a 32-bit word giving
3210	 * the size in bytes of ranlib structures which immediately follow, and
3211	 * then continues with a string table consisting of a 32-bit word giving
3212	 * the number of bytes of strings which follow and then the strings
3213	 * themselves.  So the smallest valid size is two 32-bit words long.
3214	 */
3215	if(symdef_length < 2 * sizeof(uint32_t)){
3216	    /*
3217	     * Size of table of contents for archive too small to be a valid
3218	     * table of contents.
3219	     */
3220	    ofile->toc_bad = TRUE;
3221	    return(CHECK_GOOD);
3222	}
3223	host_byte_sex = get_host_byte_sex();
3224	toc_byte_sex = get_toc_byte_sex(ofile->file_addr, ofile->file_size);
3225	if(toc_byte_sex == UNKNOWN_BYTE_SEX){
3226	    /*
3227	     * Can't determine the byte order of table of contents as it
3228	     * contains no Mach-O files.
3229	     */
3230	    ofile->toc_bad = TRUE;
3231	    return(CHECK_GOOD);
3232	}
3233	offset = 0;
3234	nranlibs = *((uint32_t *)(ofile->toc_addr + offset));
3235	if(toc_byte_sex != host_byte_sex)
3236	    nranlibs = SWAP_INT(nranlibs);
3237	nranlibs = nranlibs / sizeof(struct ranlib);
3238	offset += sizeof(uint32_t);
3239	ranlibs = (struct ranlib *)(ofile->toc_addr + offset);
3240	offset += sizeof(struct ranlib) * nranlibs;
3241	if(nranlibs == 0)
3242	    return(CHECK_GOOD);
3243	if(offset - (2 * sizeof(uint32_t)) > symdef_length){
3244	    /*
3245	     * Truncated or malformed archive.  The ranlib structures in table
3246	     * of contents extends past the end of the table of contents.
3247	     */
3248	    ofile->toc_bad = TRUE;
3249	    return(CHECK_GOOD);
3250	}
3251	strsize = *((uint32_t *)(ofile->toc_addr + offset));
3252	if(toc_byte_sex != host_byte_sex)
3253	    strsize = SWAP_INT(strsize);
3254	offset += sizeof(uint32_t);
3255	strings = ofile->toc_addr + offset;
3256	offset += strsize;
3257	if(offset - (2 * sizeof(uint32_t)) > symdef_length){
3258	    /*
3259	     * Truncated or malformed archive.  The ranlib strings in table of
3260	     * contents extends past the end of the table of contents.
3261	     */
3262	    ofile->toc_bad = TRUE;
3263	    return(CHECK_GOOD);
3264	}
3265	if(symdef_length == 2 * sizeof(uint32_t))
3266	    return(CHECK_GOOD);
3267
3268	/*
3269	 * Check the string offset and the member offsets of the ranlib structs.
3270	 */
3271	if(toc_byte_sex != host_byte_sex)
3272	    swap_ranlib(ranlibs, nranlibs, host_byte_sex);
3273	for(i = 0; i < nranlibs; i++){
3274	    if(ranlibs[i].ran_un.ran_strx >= strsize){
3275		/*
3276		 * Malformed table of contents.  The ranlib struct at this index
3277		 * has a bad string index field.
3278		 */
3279		ofile->toc_bad = TRUE;
3280		return(CHECK_GOOD);
3281	    }
3282	    if(ranlibs[i].ran_off >= ofile->file_size){
3283		/*
3284		 * Malformed table of contents.  The ranlib struct at this index
3285		 * has a bad library member offset field.
3286		 */
3287		ofile->toc_bad = TRUE;
3288		return(CHECK_GOOD);
3289	    }
3290	    /*
3291	     * These should be on 4 byte boundaries because the maximum
3292	     * alignment of the header structures and relocation are 4 bytes.
3293	     * But this is has to be 2 bytes because that's the way ar(1) has
3294	     * worked historicly in the past.  Fortunately this works on the
3295	     * 68k machines but will have to change when this is on a real
3296	     * machine.
3297	     */
3298#if defined(mc68000) || defined(__i386__)
3299	    if(ranlibs[i].ran_off % sizeof(short) != 0){
3300		/*
3301		 * Malformed table of contents.  This ranlib struct library
3302		 * member offset not a multiple 2 bytes.
3303		 */
3304		ofile->toc_bad = TRUE;
3305		return(CHECK_GOOD);
3306	    }
3307#else
3308	    if(ranlibs[i].ran_off % sizeof(uint32_t) != 0){
3309		/*
3310		 * Malformed table of contents.  This ranlib struct library
3311	         * member offset not a multiple of 4 bytes.
3312		 */
3313		ofile->toc_bad = TRUE;
3314		return(CHECK_GOOD);
3315	    }
3316#endif
3317	}
3318	ofile->toc_ranlibs = ranlibs;
3319	ofile->toc_nranlibs = nranlibs;
3320	ofile->toc_strings = strings;
3321	ofile->toc_strsize = strsize;
3322	return(CHECK_GOOD);
3323}
3324
3325/*
3326 * check_Mach_O() checks the object file's mach header and load commands
3327 * referenced in the ofile for correctness (this also swaps the mach header
3328 * and load commands into the host byte sex if needed).
3329 */
3330static
3331enum check_type
3332check_Mach_O(
3333struct ofile *ofile)
3334{
3335#ifdef OTOOL
3336	return(CHECK_GOOD);
3337#else /* !defined OTOOL */
3338    uint32_t size, i, j, ncmds, sizeofcmds, load_command_multiple, sizeofhdrs;
3339    cpu_type_t cputype;
3340    char *addr, *cmd_name, *element_name;
3341    enum byte_sex host_byte_sex;
3342    enum bool swapped;
3343    struct mach_header *mh;
3344    struct mach_header_64 *mh64;
3345    struct load_command *load_commands, *lc, l;
3346    struct segment_command *sg;
3347    struct segment_command_64 *sg64;
3348    struct section *s;
3349    struct section_64 *s64;
3350    struct symtab_command *st;
3351    struct dysymtab_command *dyst;
3352    struct symseg_command *ss;
3353    struct fvmlib_command *fl;
3354    struct dylib_command *dl;
3355    struct sub_framework_command *sub;
3356    struct sub_umbrella_command *usub;
3357    struct sub_library_command *lsub;
3358    struct sub_client_command *csub;
3359    struct prebound_dylib_command *pbdylib;
3360    struct dylinker_command *dyld;
3361    struct thread_command *ut;
3362    struct ident_command *id;
3363    struct routines_command *rc;
3364    struct routines_command_64 *rc64;
3365    struct twolevel_hints_command *hints;
3366    struct linkedit_data_command *code_sig, *split_info, *func_starts,
3367			     *data_in_code, *code_sign_drs, *linkedit_data;
3368    struct version_min_command *vers;
3369    struct prebind_cksum_command *cs;
3370    struct encryption_info_command *encrypt_info;
3371    struct encryption_info_command_64 *encrypt_info64;
3372    struct linker_option_command *lo;
3373    struct dyld_info_command *dyld_info;
3374    struct uuid_command *uuid;
3375    struct rpath_command *rpath;
3376    struct entry_point_command *ep;
3377    struct source_version_command *sv;
3378    uint32_t flavor, count, nflavor;
3379    char *p, *state;
3380    uint32_t sizeof_nlist, sizeof_dylib_module;
3381    char *struct_dylib_module_name, *struct_nlist_name;
3382    uint64_t big_size, big_end, big_load_end;
3383    struct element elements;
3384
3385	elements.offset = 0;
3386	elements.size = 0;
3387	elements.name = NULL;
3388	elements.next = NULL;
3389
3390	addr = ofile->object_addr;
3391	size = ofile->object_size;
3392	mh = ofile->mh;
3393	mh64 = ofile->mh64;
3394	load_commands = ofile->load_commands;
3395	host_byte_sex = get_host_byte_sex();
3396	swapped = (enum bool)(host_byte_sex != ofile->object_byte_sex);
3397
3398	if(ofile->mh != NULL){
3399	    if(swapped)
3400		swap_mach_header(mh, host_byte_sex);
3401	    big_size = mh->sizeofcmds;
3402	    big_size += sizeof(struct mach_header);
3403	    if(big_size > size){
3404		Mach_O_error(ofile, "truncated or malformed object (load "
3405			     "commands extend past the end of the file)");
3406		return(CHECK_BAD);
3407	    }
3408	    sizeofhdrs = big_size;
3409	    ofile->mh_cputype = mh->cputype;
3410	    ofile->mh_cpusubtype = mh->cpusubtype;
3411	    ofile->mh_filetype = mh->filetype;
3412	    ncmds = mh->ncmds;
3413	    sizeofcmds = mh->sizeofcmds;
3414	    cputype = mh->cputype;
3415	    load_command_multiple = 4;
3416	    sizeof_nlist = sizeof(struct nlist);
3417	    struct_nlist_name = "struct nlist";
3418	    sizeof_dylib_module = sizeof(struct dylib_module);
3419	    struct_dylib_module_name = "struct dylib_module";
3420	}
3421	else{
3422	    if(swapped)
3423		swap_mach_header_64(mh64, host_byte_sex);
3424	    big_size = mh64->sizeofcmds;
3425	    big_size += sizeof(struct mach_header_64);
3426	    if(big_size > size){
3427		Mach_O_error(ofile, "truncated or malformed object (load "
3428			     "commands extend past the end of the file)");
3429		return(CHECK_BAD);
3430	    }
3431	    sizeofhdrs = big_size;
3432	    ofile->mh_cputype = mh64->cputype;
3433	    ofile->mh_cpusubtype = mh64->cpusubtype;
3434	    ofile->mh_filetype = mh64->filetype;
3435	    ncmds = mh64->ncmds;
3436	    sizeofcmds = mh64->sizeofcmds;
3437	    cputype = mh64->cputype;
3438	    load_command_multiple = 8;
3439	    sizeof_nlist = sizeof(struct nlist_64);
3440	    struct_nlist_name = "struct nlist_64";
3441	    sizeof_dylib_module = sizeof(struct dylib_module_64);
3442	    struct_dylib_module_name = "struct dylib_module_64";
3443	}
3444	if(check_overlaping_element(ofile, &elements, 0, sizeofhdrs,
3445		"Mach-O headers") == CHECK_BAD)
3446	    goto return_bad;
3447	if(ofile->file_type == OFILE_FAT){
3448	    if(ofile->fat_archs[ofile->narch].cputype != ofile->mh_cputype){
3449		Mach_O_error(ofile, "malformed fat file (fat header "
3450		    "architecture: %u's cputype does not match "
3451		    "object file's mach header)", ofile->narch);
3452		goto return_bad;
3453	    }
3454	}
3455	/*
3456	 * Make a pass through the load commands checking them to the level
3457	 * that they can be parsed and all fields with offsets and sizes do
3458	 * not extend past the end of the file.
3459	 */
3460	st = NULL;
3461	dyst = NULL;
3462	rc = NULL;
3463	rc64 = NULL;
3464	hints = NULL;
3465	code_sig = NULL;
3466	func_starts = NULL;
3467	data_in_code = NULL;
3468	code_sign_drs = NULL;
3469	split_info = NULL;
3470	cs = NULL;
3471	uuid = NULL;
3472	encrypt_info = NULL;
3473	dyld_info = NULL;
3474	vers = NULL;
3475	big_load_end = 0;
3476	for(i = 0, lc = load_commands; i < ncmds; i++){
3477	    l = *lc;
3478	    if(swapped)
3479		swap_load_command(&l, host_byte_sex);
3480	    /*
3481	     * Check load command size for a multiple of load_command_multiple.
3482	     */
3483	    if(l.cmdsize % load_command_multiple != 0){
3484		/*
3485		 * We have a hack here to allow 64-bit Mach-O core files to
3486		 * have LC_THREAD commands that are only a multiple of 4 and
3487		 * not 8 to be allowed since the kernel produces them.
3488		 */
3489		if(ofile->mh64 == NULL ||
3490		   ofile->mh64->filetype != MH_CORE ||
3491		   l.cmd != LC_THREAD ||
3492		   l.cmdsize % 4 != 0){
3493		    Mach_O_error(ofile, "malformed object (load command %u "
3494				 "cmdsize not a multiple of %u)", i,
3495				 load_command_multiple);
3496		    goto return_bad;
3497		}
3498	    }
3499	    /* check that load command does not extends past end of commands */
3500	    big_load_end += l.cmdsize;
3501	    if(big_load_end > sizeofcmds){
3502		Mach_O_error(ofile, "truncated or malformed object (load "
3503			     "command %u extends past the end of the file)",i);
3504		goto return_bad;
3505	    }
3506	    /* check that the load command size is not zero */
3507	    if(l.cmdsize == 0){
3508		Mach_O_error(ofile, "malformed object (load command %u cmdsize"
3509			     " is zero)", i);
3510		goto return_bad;
3511	    }
3512	    switch(l.cmd){
3513	    case LC_SEGMENT:
3514		if(l.cmdsize < sizeof(struct segment_command)){
3515		    Mach_O_error(ofile, "malformed object (LC_SEGMENT cmdsize "
3516			         "too small) in command %u", i);
3517		    goto return_bad;
3518		}
3519		sg = (struct segment_command *)lc;
3520		if(swapped)
3521		    swap_segment_command(sg, host_byte_sex);
3522		big_size = sg->nsects;
3523		big_size *= sizeof(struct section);
3524		big_size += sizeof(struct segment_command);
3525		if(sg->cmdsize != big_size){
3526		    Mach_O_error(ofile, "malformed object (inconsistent "
3527				 "cmdsize in LC_SEGMENT command %u for the "
3528				 "number of sections)", i);
3529		    goto return_bad;
3530		}
3531		if(sg->fileoff > size){
3532		    Mach_O_error(ofile, "truncated or malformed object ("
3533				 "LC_SEGMENT command %u fileoff field "
3534				 "extends past the end of the file)", i);
3535		    goto return_bad;
3536		}
3537		big_size = sg->fileoff;
3538		big_size += sg->filesize;
3539		if(big_size > size){
3540		    Mach_O_error(ofile, "truncated or malformed object ("
3541				 "LC_SEGMENT command %u fileoff field "
3542				 "plus filesize field extends past the end of "
3543				 "the file)", i);
3544		    goto return_bad;
3545		}
3546		if(sg->vmsize != 0 && sg->filesize > sg->vmsize){
3547		    Mach_O_error(ofile, "malformed object (LC_SEGMENT command "
3548				 "%u filesize field greater than vmsize field)",
3549				 i);
3550		    goto return_bad;
3551		}
3552		s = (struct section *)
3553		    ((char *)sg + sizeof(struct segment_command));
3554		if(swapped)
3555		    swap_section(s, sg->nsects, host_byte_sex);
3556		for(j = 0 ; j < sg->nsects ; j++){
3557		    if(mh->filetype != MH_DYLIB_STUB &&
3558		       s->flags != S_ZEROFILL &&
3559		       s->flags != S_THREAD_LOCAL_ZEROFILL && s->offset > size){
3560			Mach_O_error(ofile, "truncated or malformed object "
3561				"(offset field of section %u in LC_SEGMENT "
3562				"command %u extends past the end of the file)",
3563				j, i);
3564			goto return_bad;
3565		    }
3566		    if(mh->filetype != MH_DYLIB_STUB &&
3567		       s->flags != S_ZEROFILL &&
3568		       s->flags != S_THREAD_LOCAL_ZEROFILL &&
3569		       sg->fileoff == 0 && s->offset < sizeofhdrs &&
3570		       s->size != 0){
3571			Mach_O_error(ofile, "malformed object (offset field of "
3572				"section %u in LC_SEGMENT command %u not "
3573				"past the headers of the file)", j, i);
3574			goto return_bad;
3575		    }
3576		    big_size = s->offset;
3577		    big_size += s->size;
3578		    if(mh->filetype != MH_DYLIB_STUB &&
3579		       s->flags != S_ZEROFILL &&
3580		       s->flags != S_THREAD_LOCAL_ZEROFILL && big_size > size){
3581			Mach_O_error(ofile, "truncated or malformed object "
3582				"(offset field plus size field of section %u "
3583				"in LC_SEGMENT command %u extends "
3584				"past the end of the file)", j, i);
3585			goto return_bad;
3586		    }
3587		    if(mh->filetype != MH_DYLIB_STUB &&
3588		       s->flags != S_ZEROFILL &&
3589		       s->flags != S_THREAD_LOCAL_ZEROFILL &&
3590		       s->size > sg->filesize){
3591			Mach_O_error(ofile, "malformed object (size field of "
3592				"section %u in LC_SEGMENT command %u greater "
3593				"than the segment)", j, i);
3594			goto return_bad;
3595		    }
3596		    if(mh->filetype != MH_DYLIB_STUB &&
3597		       s->size != 0 && s->addr < sg->vmaddr){
3598			Mach_O_error(ofile, "malformed object (addr field of "
3599				"section %u in LC_SEGMENT command %u less than "
3600				"the segment's vmaddr)", j, i);
3601			goto return_bad;
3602		    }
3603		    big_size = s->addr;
3604		    big_size += s->size;
3605		    big_end = sg->vmaddr;
3606		    big_end += sg->vmsize;
3607		    if(sg->vmsize != 0 && s->size != 0 && big_size > big_end){
3608			Mach_O_error(ofile, "malformed object (addr field plus "
3609				"size of section %u in LC_SEGMENT command %u "
3610				"greater than than the segment's vmaddr plus "
3611				"vmsize)", j, i);
3612			goto return_bad;
3613		    }
3614		    if(mh->filetype != MH_DYLIB_STUB &&
3615		       mh->filetype != MH_DSYM &&
3616		       s->flags != S_ZEROFILL &&
3617		       s->flags != S_THREAD_LOCAL_ZEROFILL &&
3618		       check_overlaping_element(ofile, &elements, s->offset,
3619			    s->size, "section contents") == CHECK_BAD)
3620			goto return_bad;
3621		    if(s->reloff > size){
3622			Mach_O_error(ofile, "truncated or malformed object "
3623				"(reloff field of section %u in LC_SEGMENT "
3624				"command %u extends past the end of the file)",
3625				j, i);
3626			goto return_bad;
3627		    }
3628		    big_size = s->nreloc;
3629		    big_size *= sizeof(struct relocation_info);
3630		    big_size += s->reloff;
3631		    if(big_size > size){
3632			Mach_O_error(ofile, "truncated or malformed object "
3633				"(reloff field plus nreloc field times sizeof("
3634				"struct relocation_info) of section %u in "
3635				"LC_SEGMENT command %u extends past the "
3636				"end of the file)", j, i);
3637			goto return_bad;
3638		    }
3639		    if(check_overlaping_element(ofile, &elements, s->reloff,
3640			    s->nreloc * sizeof(struct relocation_info),
3641			    "section relocation entries") == CHECK_BAD)
3642			goto return_bad;
3643		    s++;
3644		}
3645		break;
3646
3647	    case LC_SEGMENT_64:
3648		if(l.cmdsize < sizeof(struct segment_command_64)){
3649		    Mach_O_error(ofile, "malformed object (LC_SEGMENT_64 "
3650				 "cmdsize too small) in command %u", i);
3651		    goto return_bad;
3652		}
3653		sg64 = (struct segment_command_64 *)lc;
3654		if(swapped)
3655		    swap_segment_command_64(sg64, host_byte_sex);
3656		big_size = sg64->nsects;
3657		big_size *= sizeof(struct section_64);
3658		big_size += sizeof(struct segment_command_64);
3659		if(sg64->cmdsize != big_size){
3660		    Mach_O_error(ofile, "malformed object (inconsistent "
3661				 "cmdsize in LC_SEGMENT_64 command %u for "
3662				 "the number of sections)", i);
3663		    goto return_bad;
3664		}
3665		if(sg64->fileoff > size){
3666		    Mach_O_error(ofile, "truncated or malformed object ("
3667				 "LC_SEGMENT_64 command %u fileoff field "
3668				 "extends past the end of the file)", i);
3669		    goto return_bad;
3670		}
3671		big_size = sg64->fileoff;
3672		big_size += sg64->filesize;
3673		if(big_size > size){
3674		    Mach_O_error(ofile, "truncated or malformed object ("
3675				 "LC_SEGMENT_64 command %u fileoff field "
3676				 "plus filesize field extends past the end of "
3677				 "the file)", i);
3678		    goto return_bad;
3679		}
3680		s64 = (struct section_64 *)
3681		    ((char *)sg64 + sizeof(struct segment_command_64));
3682		if(swapped)
3683		    swap_section_64(s64, sg64->nsects, host_byte_sex);
3684		for(j = 0 ; j < sg64->nsects ; j++){
3685		    if(mh64->filetype != MH_DYLIB_STUB &&
3686		       s64->flags != S_ZEROFILL &&
3687		       s64->flags != S_THREAD_LOCAL_ZEROFILL &&
3688		       s64->offset > size){
3689			Mach_O_error(ofile, "truncated or malformed object "
3690				"(offset field of section %u in LC_SEGMENT_64 "
3691				"command %u extends past the end of the file)",
3692				j, i);
3693			goto return_bad;
3694		    }
3695		    big_size = s64->offset;
3696		    big_size += s64->size;
3697		    if(mh64->filetype != MH_DYLIB_STUB &&
3698		       s64->flags != S_ZEROFILL &&
3699		       s64->flags != S_THREAD_LOCAL_ZEROFILL &&
3700		       big_size > size){
3701			Mach_O_error(ofile, "truncated or malformed object "
3702				"(offset field plus size field of section %u "
3703				"in LC_SEGMENT_64 command %u extends "
3704				"past the end of the file)", j, i);
3705			goto return_bad;
3706		    }
3707		    if(mh64->filetype != MH_DYLIB_STUB &&
3708		       mh64->filetype != MH_DSYM &&
3709		       s64->flags != S_ZEROFILL &&
3710		       s64->flags != S_THREAD_LOCAL_ZEROFILL &&
3711		       check_overlaping_element(ofile, &elements, s64->offset,
3712			    s64->size, "section contents") == CHECK_BAD)
3713			goto return_bad;
3714		    if(s64->reloff > size){
3715			Mach_O_error(ofile, "truncated or malformed object "
3716				"(reloff field of section %u in LC_SEGMENT_64 "
3717				"command %u extends past the end of the file)",
3718				j, i);
3719			goto return_bad;
3720		    }
3721		    big_size = s64->nreloc;
3722		    big_size *= sizeof(struct relocation_info);
3723		    big_size += s64->reloff;
3724		    if(big_size > size){
3725			Mach_O_error(ofile, "truncated or malformed object "
3726				"(reloff field plus nreloc field times sizeof("
3727				"struct relocation_info) of section %u in "
3728				"LC_SEGMENT_64 command %u extends past the "
3729				"end of the file)", j, i);
3730			goto return_bad;
3731		    }
3732		    if(check_overlaping_element(ofile, &elements, s64->reloff,
3733			    s64->nreloc * sizeof(struct relocation_info),
3734			    "section relocation entries") == CHECK_BAD)
3735			goto return_bad;
3736		    s64++;
3737		}
3738		break;
3739
3740	    case LC_SYMTAB:
3741		if(l.cmdsize < sizeof(struct symtab_command)){
3742		    Mach_O_error(ofile, "malformed object (LC_SYMTAB cmdsize "
3743			         "too small) in command %u", i);
3744		    goto return_bad;
3745		}
3746		if(st != NULL){
3747		    Mach_O_error(ofile, "malformed object (more than one "
3748			"LC_SYMTAB command)");
3749		    goto return_bad;
3750		}
3751		st = (struct symtab_command *)lc;
3752		if(swapped)
3753		    swap_symtab_command(st, host_byte_sex);
3754		if(st->cmdsize != sizeof(struct symtab_command)){
3755		    Mach_O_error(ofile, "malformed object (LC_SYMTAB command "
3756			"%u has incorrect cmdsize)", i);
3757		    goto return_bad;
3758		}
3759		if(st->symoff > size){
3760		    Mach_O_error(ofile, "truncated or malformed object (symoff "
3761			"field of LC_SYMTAB command %u extends past the end "
3762			"of the file)", i);
3763		    goto return_bad;
3764		}
3765		big_size = st->nsyms;
3766		big_size *= sizeof_nlist;
3767		big_size += st->symoff;
3768		if(big_size > size){
3769		    Mach_O_error(ofile, "truncated or malformed object (symoff "
3770			"field plus nsyms field times sizeof(%s) of LC_SYMTAB "
3771			"command %u extends past the end of the file)",
3772			struct_nlist_name, i);
3773		    goto return_bad;
3774		}
3775		if(check_overlaping_element(ofile, &elements, st->symoff,
3776			st->nsyms * sizeof_nlist, "symbol table") == CHECK_BAD)
3777		    goto return_bad;
3778		if(st->stroff > size){
3779		    Mach_O_error(ofile, "truncated or malformed object (stroff "
3780			"field of LC_SYMTAB command %u extends past the end "
3781			"of the file)", i);
3782		    goto return_bad;
3783		}
3784		big_size = st->stroff;
3785		big_size += st->strsize;
3786		if(big_size > size){
3787		    Mach_O_error(ofile, "truncated or malformed object (stroff "
3788			"field plus strsize field of LC_SYMTAB command %u "
3789			"extends past the end of the file)", i);
3790		    goto return_bad;
3791		}
3792		if(check_overlaping_element(ofile, &elements, st->stroff,
3793			st->strsize, "string table") == CHECK_BAD)
3794		    goto return_bad;
3795		break;
3796
3797	    case LC_DYSYMTAB:
3798		if(l.cmdsize < sizeof(struct dysymtab_command)){
3799		    Mach_O_error(ofile, "malformed object (LC_DYSYMTAB cmdsize "
3800			         "too small) in command %u", i);
3801		    goto return_bad;
3802		}
3803		if(dyst != NULL){
3804		    Mach_O_error(ofile, "malformed object (more than one "
3805			"LC_DYSYMTAB command)");
3806		    goto return_bad;
3807		}
3808		dyst = (struct dysymtab_command *)lc;
3809		if(swapped)
3810		    swap_dysymtab_command(dyst, host_byte_sex);
3811		if(dyst->cmdsize != sizeof(struct dysymtab_command)){
3812		    Mach_O_error(ofile, "malformed object (LC_DYSYMTAB command "
3813			"%u has incorrect cmdsize)", i);
3814		    goto return_bad;
3815		}
3816		if(dyst->tocoff > size){
3817		    Mach_O_error(ofile, "truncated or malformed object (tocoff "
3818			"field of LC_DYSYMTAB command %u extends past the end "
3819			"of the file)", i);
3820		    goto return_bad;
3821		}
3822		big_size = dyst->ntoc;
3823		big_size *= sizeof(struct dylib_table_of_contents);
3824		big_size += dyst->tocoff;
3825		if(big_size > size){
3826		    Mach_O_error(ofile, "truncated or malformed object (tocoff "
3827			"field plus ntoc field times sizeof(struct dylib_table"
3828			"_of_contents) of LC_DYSYMTAB command %u extends past "
3829			"the end of the file)", i);
3830		    goto return_bad;
3831		}
3832		if(check_overlaping_element(ofile, &elements, dyst->tocoff,
3833			dyst->ntoc * sizeof(struct dylib_table_of_contents),
3834			"table of contents") == CHECK_BAD)
3835		    goto return_bad;
3836		if(dyst->modtaboff > size){
3837		    Mach_O_error(ofile, "truncated or malformed object "
3838			"(modtaboff field of LC_DYSYMTAB command %u extends "
3839			"past the end of the file)", i);
3840		    goto return_bad;
3841		}
3842		big_size = dyst->nmodtab;
3843		big_size *= sizeof_dylib_module;
3844		big_size += dyst->modtaboff;
3845		if(big_size > size){
3846		    Mach_O_error(ofile, "truncated or malformed object "
3847			"(modtaboff field plus nmodtab field times sizeof(%s) "
3848			"of LC_DYSYMTAB command %u extends past the end of "
3849			"the file)", struct_dylib_module_name, i);
3850		    goto return_bad;
3851		}
3852		if(check_overlaping_element(ofile, &elements, dyst->modtaboff,
3853			dyst->nmodtab * sizeof_dylib_module, "module table") ==
3854			CHECK_BAD)
3855		    goto return_bad;
3856		if(dyst->extrefsymoff > size){
3857		    Mach_O_error(ofile, "truncated or malformed object "
3858			"(extrefsymoff field of LC_DYSYMTAB command %u "
3859			"extends past the end of the file)", i);
3860		    goto return_bad;
3861		}
3862		big_size = dyst->nextrefsyms;
3863		big_size *= sizeof(struct dylib_reference);
3864		big_size += dyst->extrefsymoff;
3865		if(big_size > size){
3866		    Mach_O_error(ofile, "truncated or malformed object "
3867			"(extrefsymoff field plus nextrefsyms field times "
3868			"sizeof(struct dylib_reference) of LC_DYSYMTAB command "
3869			"%u extends past the end of the file)", i);
3870		    goto return_bad;
3871		}
3872		if(check_overlaping_element(ofile, &elements,dyst->extrefsymoff,
3873			dyst->nextrefsyms * sizeof(struct dylib_reference),
3874			"reference table") == CHECK_BAD)
3875		    goto return_bad;
3876		if(dyst->indirectsymoff > size){
3877		    Mach_O_error(ofile, "truncated or malformed object "
3878			"(indirectsymoff field of LC_DYSYMTAB command %u "
3879			"extends past the end of the file)", i);
3880		    goto return_bad;
3881		}
3882		big_size = dyst->nindirectsyms;
3883		big_size *= sizeof(uint32_t);
3884		big_size += dyst->indirectsymoff;
3885		if(big_size > size){
3886		    Mach_O_error(ofile, "truncated or malformed object "
3887			"(indirectsymoff field plus nindirectsyms field times "
3888			"sizeof(uint32_t) of LC_DYSYMTAB command "
3889			"%u extends past the end of the file)", i);
3890		    goto return_bad;
3891		}
3892		if(check_overlaping_element(ofile, &elements,
3893			dyst->indirectsymoff, dyst->nindirectsyms *
3894			sizeof(uint32_t), "indirect table") == CHECK_BAD)
3895		    goto return_bad;
3896		if(dyst->extreloff > size){
3897		    Mach_O_error(ofile, "truncated or malformed object "
3898			"(extreloff field of LC_DYSYMTAB command %u "
3899			"extends past the end of the file)", i);
3900		    goto return_bad;
3901		}
3902		big_size = dyst->nextrel;
3903		big_size *= sizeof(struct relocation_info);
3904		big_size += dyst->extreloff;
3905		if(big_size > size){
3906		    Mach_O_error(ofile, "truncated or malformed object "
3907			"(extreloff field plus nextrel field times "
3908			"sizeof(struct relocation_info) of LC_DYSYMTAB command "
3909			"%u extends past the end of the file)", i);
3910		    goto return_bad;
3911		}
3912		if(check_overlaping_element(ofile, &elements, dyst->extreloff,
3913			dyst->nextrel * sizeof(struct relocation_info),
3914			"external relocation table") == CHECK_BAD)
3915		    goto return_bad;
3916		if(dyst->locreloff > size){
3917		    Mach_O_error(ofile, "truncated or malformed object "
3918			"(locreloff field of LC_DYSYMTAB command %u "
3919			"extends past the end of the file)", i);
3920		    goto return_bad;
3921		}
3922		big_size = dyst->nlocrel;
3923		big_size *= sizeof(struct relocation_info);
3924		big_size += dyst->locreloff;
3925		if(big_size > size){
3926		    Mach_O_error(ofile, "truncated or malformed object "
3927			"(locreloff field plus nlocrel field times "
3928			"sizeof(struct relocation_info) of LC_DYSYMTAB command "
3929			"%u extends past the end of the file)", i);
3930		    goto return_bad;
3931		}
3932		if(check_overlaping_element(ofile, &elements, dyst->locreloff,
3933			dyst->nlocrel * sizeof(struct relocation_info),
3934			"local relocation table") == CHECK_BAD)
3935		    goto return_bad;
3936		break;
3937
3938	    case LC_ROUTINES:
3939		if(l.cmdsize < sizeof(struct routines_command)){
3940		    Mach_O_error(ofile, "malformed object (LC_ROUTINES cmdsize "
3941			         "too small) in command %u", i);
3942		    goto return_bad;
3943		}
3944		if(rc != NULL){
3945		    Mach_O_error(ofile, "malformed object (more than one "
3946			"LC_ROUTINES command)");
3947		    goto return_bad;
3948		}
3949		rc = (struct routines_command *)lc;
3950		if(swapped)
3951		    swap_routines_command(rc, host_byte_sex);
3952		if(rc->cmdsize != sizeof(struct routines_command)){
3953		    Mach_O_error(ofile, "malformed object (LC_ROUTINES "
3954			"command %u has incorrect cmdsize)", i);
3955		    goto return_bad;
3956		}
3957		break;
3958
3959	    case LC_ROUTINES_64:
3960		if(l.cmdsize < sizeof(struct routines_command_64)){
3961		    Mach_O_error(ofile, "malformed object (LC_ROUTINES_64 "
3962				 "cmdsize too small) in command %u", i);
3963		    goto return_bad;
3964		}
3965		if(rc64 != NULL){
3966		    Mach_O_error(ofile, "malformed object (more than one "
3967			"LC_ROUTINES_64 command)");
3968		    goto return_bad;
3969		}
3970		rc64 = (struct routines_command_64 *)lc;
3971		if(swapped)
3972		    swap_routines_command_64(rc64, host_byte_sex);
3973		if(rc64->cmdsize != sizeof(struct routines_command_64)){
3974		    Mach_O_error(ofile, "malformed object (LC_ROUTINES_64 "
3975			"command %u has incorrect cmdsize)", i);
3976		    goto return_bad;
3977		}
3978		break;
3979
3980	    case LC_TWOLEVEL_HINTS:
3981		if(l.cmdsize < sizeof(struct twolevel_hints_command)){
3982		    Mach_O_error(ofile, "malformed object (LC_TWOLEVEL_HINTS "
3983				 "cmdsize too small) in command %u", i);
3984		    goto return_bad;
3985		}
3986		if(hints != NULL){
3987		    Mach_O_error(ofile, "malformed object (more than one "
3988			"LC_TWOLEVEL_HINTS command)");
3989		    goto return_bad;
3990		}
3991		hints = (struct twolevel_hints_command *)lc;
3992		if(swapped)
3993		    swap_twolevel_hints_command(hints, host_byte_sex);
3994		if(hints->cmdsize != sizeof(struct twolevel_hints_command)){
3995		    Mach_O_error(ofile, "malformed object (LC_TWOLEVEL_HINTS "
3996			         "command %u has incorrect cmdsize)", i);
3997		    goto return_bad;
3998		}
3999		if(hints->offset > size){
4000		    Mach_O_error(ofile, "truncated or malformed object "
4001			"(offset field of LC_TWOLEVEL_HINTS command %u "
4002			"extends past the end of the file)", i);
4003		    goto return_bad;
4004		}
4005		big_size = hints->nhints;
4006		big_size *= sizeof(struct twolevel_hint);
4007		big_size += hints->offset;
4008		if(big_size > size){
4009		    Mach_O_error(ofile, "truncated or malformed object "
4010			"(offset field plus nhints field times "
4011			"sizeof(struct twolevel_hint) of LC_TWOLEVEL_HINTS "
4012			" command %u extends past the end of the file)", i);
4013		    goto return_bad;
4014		}
4015		if(check_overlaping_element(ofile, &elements, hints->offset,
4016			hints->nhints * sizeof(struct twolevel_hint),
4017			"two level hints") == CHECK_BAD)
4018		    goto return_bad;
4019		break;
4020
4021	    case LC_SEGMENT_SPLIT_INFO:
4022		cmd_name = "LC_SEGMENT_SPLIT_INFO";
4023		element_name = "split info data";
4024		if(split_info != NULL){
4025		    Mach_O_error(ofile, "malformed object (more than one "
4026			"%s command)", cmd_name);
4027		    goto return_bad;
4028		}
4029		split_info = (struct linkedit_data_command *)lc;
4030		goto check_linkedit_data_command;
4031
4032	    case LC_CODE_SIGNATURE:
4033		cmd_name = "LC_CODE_SIGNATURE";
4034		element_name = "code signature data";
4035		if(code_sig != NULL){
4036		    Mach_O_error(ofile, "malformed object (more than one "
4037			"%s command)", cmd_name);
4038		    goto return_bad;
4039		}
4040		code_sig = (struct linkedit_data_command *)lc;
4041		goto check_linkedit_data_command;
4042
4043	    case LC_FUNCTION_STARTS:
4044		cmd_name = "LC_FUNCTION_STARTS";
4045		element_name = "function starts data";
4046		if(func_starts != NULL){
4047		    Mach_O_error(ofile, "malformed object (more than one "
4048			"%s command)", cmd_name);
4049		    goto return_bad;
4050		}
4051		func_starts = (struct linkedit_data_command *)lc;
4052		goto check_linkedit_data_command;
4053
4054	    case LC_DATA_IN_CODE:
4055		cmd_name = "LC_DATA_IN_CODE";
4056		element_name = "date in code info";
4057		if(data_in_code != NULL){
4058		    Mach_O_error(ofile, "malformed object (more than one "
4059			"%s command)", cmd_name);
4060		    goto return_bad;
4061		}
4062		data_in_code = (struct linkedit_data_command *)lc;
4063		goto check_linkedit_data_command;
4064
4065	    case LC_DYLIB_CODE_SIGN_DRS:
4066		cmd_name = "LC_DYLIB_CODE_SIGN_DRS";
4067		element_name = "code signing RDs data";
4068		if(code_sign_drs != NULL){
4069		    Mach_O_error(ofile, "malformed object (more than one "
4070			"%s command)", cmd_name);
4071		    goto return_bad;
4072		}
4073		code_sign_drs = (struct linkedit_data_command *)lc;
4074		goto check_linkedit_data_command;
4075
4076check_linkedit_data_command:
4077		if(l.cmdsize < sizeof(struct linkedit_data_command)){
4078		    Mach_O_error(ofile, "malformed object (%s cmdsize too "
4079				 "small) in command %u", cmd_name, i);
4080		    goto return_bad;
4081		}
4082		linkedit_data = (struct linkedit_data_command *)lc;
4083		if(swapped)
4084		    swap_linkedit_data_command(linkedit_data, host_byte_sex);
4085		if(linkedit_data->cmdsize !=
4086		   sizeof(struct linkedit_data_command)){
4087		    Mach_O_error(ofile, "malformed object (%s command %u has "
4088				 "incorrect cmdsize)", cmd_name, i);
4089		    goto return_bad;
4090		}
4091		if(linkedit_data->dataoff > size){
4092		    Mach_O_error(ofile, "truncated or malformed object "
4093			"(dataoff field of %s command %u extends past the end "
4094			"of the file)", cmd_name, i);
4095		    goto return_bad;
4096		}
4097		big_size = linkedit_data->dataoff;
4098		big_size += linkedit_data->datasize;
4099		if(big_size > size){
4100		    Mach_O_error(ofile, "truncated or malformed object "
4101			"(dataoff field plus datasize field of "
4102			"%s command %u extends past the end of "
4103			"the file)", cmd_name, i);
4104		    goto return_bad;
4105		}
4106		if(check_overlaping_element(ofile, &elements,
4107			linkedit_data->dataoff, linkedit_data->datasize,
4108			element_name) == CHECK_BAD)
4109		    goto return_bad;
4110		break;
4111
4112	    case LC_VERSION_MIN_MACOSX:
4113		if(l.cmdsize < sizeof(struct version_min_command)){
4114		    Mach_O_error(ofile, "malformed object (LC_VERSION_MIN_"
4115				 "MACOSX cmdsize too small) in command %u", i);
4116		    goto return_bad;
4117		}
4118		if(vers != NULL){
4119		    Mach_O_error(ofile, "malformed object (more than one "
4120			"LC_VERSION_MIN_IPHONEOS or LC_VERSION_MIN_MACOSX "
4121			"command)");
4122		    goto return_bad;
4123		}
4124		vers = (struct version_min_command *)lc;
4125		if(swapped)
4126		    swap_version_min_command(vers, host_byte_sex);
4127		if(vers->cmdsize < sizeof(struct version_min_command)){
4128		    Mach_O_error(ofile, "malformed object (LC_VERSION_MIN_"
4129			"MACOSX command %u has too small cmdsize field)", i);
4130		    goto return_bad;
4131		}
4132		break;
4133
4134	    case LC_VERSION_MIN_IPHONEOS:
4135		if(l.cmdsize < sizeof(struct version_min_command)){
4136		    Mach_O_error(ofile, "malformed object (LC_VERSION_MIN_"
4137				 "IPHONEOS cmdsize too small) in command %u",i);
4138		    goto return_bad;
4139		}
4140		if(vers != NULL){
4141		    Mach_O_error(ofile, "malformed object (more than one "
4142			"LC_VERSION_MIN_IPHONEOS or LC_VERSION_MIN_MACOSX "
4143			"command)");
4144		    goto return_bad;
4145		}
4146		vers = (struct version_min_command *)lc;
4147		if(swapped)
4148		    swap_version_min_command(vers, host_byte_sex);
4149		if(vers->cmdsize < sizeof(struct version_min_command)){
4150		    Mach_O_error(ofile, "malformed object (LC_VERSION_MIN_"
4151			"IPHONEOS command %u has too small cmdsize field)", i);
4152		    goto return_bad;
4153		}
4154		break;
4155
4156	    case LC_ENCRYPTION_INFO:
4157		if(l.cmdsize < sizeof(struct encryption_info_command)){
4158		    Mach_O_error(ofile, "malformed object (LC_ENCRYPTION_INFO "
4159				 "cmdsize too small) in command %u", i);
4160		    goto return_bad;
4161		}
4162		encrypt_info = (struct encryption_info_command *)lc;
4163		if(swapped)
4164		    swap_encryption_command(encrypt_info, host_byte_sex);
4165		if(encrypt_info->cmdsize !=
4166		   sizeof(struct encryption_info_command)){
4167		    Mach_O_error(ofile, "malformed object (LC_ENCRYPTION_INFO"
4168				 "command %u has incorrect cmdsize)", i);
4169		    goto return_bad;
4170		}
4171		if(encrypt_info->cryptoff > size){
4172		Mach_O_error(ofile, "truncated or malformed object (cryptoff "
4173			     "field of LC_ENCRYPTION_INFO command %u extends "
4174			     "past the end of the file)", i);
4175		    goto return_bad;
4176		}
4177		big_size = encrypt_info->cryptoff;
4178		big_size += encrypt_info->cryptsize;
4179		if(big_size > size){
4180		    Mach_O_error(ofile, "truncated or malformed object "
4181				 "(cryptoff field plus cryptsize field of "
4182				 "LC_ENCRYPTION_INFO command %u extends past "
4183				 "the end of the file)", i);
4184		    goto return_bad;
4185		}
4186		break;
4187
4188	    case LC_ENCRYPTION_INFO_64:
4189		if(l.cmdsize < sizeof(struct encryption_info_command_64)){
4190		    Mach_O_error(ofile, "malformed object (LC_ENCRYPTION_INFO"
4191			         "_64 cmdsize too small) in command %u", i);
4192		    goto return_bad;
4193		}
4194		encrypt_info64 = (struct encryption_info_command_64 *)lc;
4195		if(swapped)
4196		    swap_encryption_command_64(encrypt_info64, host_byte_sex);
4197		if(encrypt_info64->cmdsize !=
4198		   sizeof(struct encryption_info_command_64)){
4199		    Mach_O_error(ofile, "malformed object (LC_ENCRYPTION_INFO"
4200				 "_64 command %u has incorrect cmdsize)", i);
4201		    goto return_bad;
4202		}
4203		if(encrypt_info64->cryptoff > size){
4204		Mach_O_error(ofile, "truncated or malformed object (cryptoff "
4205			     "field of LC_ENCRYPTION_INFO_64 command %u extends"
4206			     " past the end of the file)", i);
4207		    goto return_bad;
4208		}
4209		big_size = encrypt_info64->cryptoff;
4210		big_size += encrypt_info64->cryptsize;
4211		if(big_size > size){
4212		    Mach_O_error(ofile, "truncated or malformed object "
4213				 "(cryptoff field plus cryptsize field of "
4214				 "LC_ENCRYPTION_INFO_64 command %u extends past"
4215				 " the end of the file)", i);
4216		    goto return_bad;
4217		}
4218		break;
4219
4220	    case LC_LINKER_OPTION:
4221		if(l.cmdsize < sizeof(struct linker_option_command)){
4222		    Mach_O_error(ofile, "malformed object (LC_LINKER_OPTION "
4223			         "cmdsize too small) in command %u", i);
4224		    goto return_bad;
4225		}
4226		lo = (struct linker_option_command *)lc;
4227		if(swapped)
4228		    swap_linker_option_command(lo, host_byte_sex);
4229		if(lo->cmdsize <
4230		   sizeof(struct linker_option_command)){
4231		    Mach_O_error(ofile, "malformed object (LC_LINKER_OPTION "
4232				 " command %u cmdsize too small)", i);
4233		    goto return_bad;
4234		}
4235		break;
4236
4237	    case LC_DYLD_INFO:
4238	    case LC_DYLD_INFO_ONLY:
4239		if(l.cmdsize < sizeof(struct dyld_info_command)){
4240		    Mach_O_error(ofile, "malformed object (%s cmdsize "
4241			         "too small) in command %u", l.cmd ==
4242				 LC_DYLD_INFO ? "LC_DYLD_INFO" :
4243				 "LC_DYLD_INFO_ONLY", i);
4244		    goto return_bad;
4245		}
4246		dyld_info = (struct dyld_info_command *)lc;
4247		if(swapped)
4248		    swap_dyld_info_command(dyld_info, host_byte_sex);
4249		if(dyld_info->cmdsize !=
4250		   sizeof(struct dyld_info_command)){
4251		    Mach_O_error(ofile, "malformed object (LC_DYLD_INFO"
4252				 "command %u has incorrect cmdsize)", i);
4253		    goto return_bad;
4254		}
4255		if(dyld_info->rebase_off != 0 && dyld_info->rebase_off > size){
4256		    Mach_O_error(ofile, "truncated or malformed object "
4257			"(rebase_off field of LC_DYLD_INFO command %u "
4258			"extends past the end of the file)", i);
4259		    goto return_bad;
4260		}
4261		if(dyld_info->rebase_off != 0){
4262		    big_size = dyld_info->rebase_off;
4263		    big_size += dyld_info->rebase_size;
4264		    if(big_size > size){
4265			Mach_O_error(ofile, "truncated or malformed object "
4266			    "(rebase_off plus rebase_size of LC_DYLD_INFO "
4267			    "command %u extends past the end of the file)", i);
4268			goto return_bad;
4269		    }
4270		}
4271		if(check_overlaping_element(ofile, &elements,
4272			dyld_info->rebase_off, dyld_info->rebase_size,
4273			"dyld rebase info") == CHECK_BAD)
4274		    goto return_bad;
4275		if(dyld_info->bind_off != 0 && dyld_info->bind_off > size){
4276		    Mach_O_error(ofile, "truncated or malformed object "
4277			"(bind_off field of LC_DYLD_INFO command %u "
4278			"extends past the end of the file)", i);
4279		    goto return_bad;
4280		}
4281		if(dyld_info->bind_off != 0){
4282		    big_size = dyld_info->bind_off;
4283		    big_size += dyld_info->bind_size;
4284		    if(big_size > size){
4285			Mach_O_error(ofile, "truncated or malformed object "
4286			    "(bind_off plus bind_size of LC_DYLD_INFO command "
4287			    "%u extends past the end of the file)", i);
4288			goto return_bad;
4289		    }
4290		}
4291		if(check_overlaping_element(ofile, &elements,
4292			dyld_info->bind_off, dyld_info->bind_size,
4293			"dyld bind info") == CHECK_BAD)
4294		    goto return_bad;
4295		if(dyld_info->weak_bind_off != 0 &&
4296		   dyld_info->weak_bind_off > size){
4297		    Mach_O_error(ofile, "truncated or malformed object "
4298			"(weak_bind_off field of LC_DYLD_INFO command %u "
4299			"extends past the end of the file)", i);
4300		    goto return_bad;
4301		}
4302		if(dyld_info->weak_bind_off != 0){
4303		    big_size = dyld_info->weak_bind_off;
4304		    big_size += dyld_info->weak_bind_size;
4305		    if(big_size > size){
4306			Mach_O_error(ofile, "truncated or malformed object "
4307			    "(weak_bind_off plus weak_bind_size of LC_DYLD_INFO"
4308			    " command %u extends past the end of the file)", i);
4309			goto return_bad;
4310		    }
4311		}
4312		if(check_overlaping_element(ofile, &elements,
4313			dyld_info->weak_bind_off, dyld_info->weak_bind_size,
4314			"dyld bind info") == CHECK_BAD)
4315		    goto return_bad;
4316		if(dyld_info->lazy_bind_off != 0 &&
4317		   dyld_info->lazy_bind_off > size){
4318		    Mach_O_error(ofile, "truncated or malformed object "
4319			"(lazy_bind_off field of LC_DYLD_INFO command %u "
4320			"extends past the end of the file)", i);
4321		    goto return_bad;
4322		}
4323		if(dyld_info->lazy_bind_off != 0){
4324		    big_size = dyld_info->lazy_bind_off;
4325		    big_size += dyld_info->lazy_bind_size;
4326		    if(big_size > size){
4327			Mach_O_error(ofile, "truncated or malformed object "
4328			    "(lazy_bind_off plus lazy_bind_size of LC_DYLD_INFO"
4329			    " command %u extends past the end of the file)", i);
4330			goto return_bad;
4331		    }
4332		}
4333		if(check_overlaping_element(ofile, &elements,
4334			dyld_info->lazy_bind_off, dyld_info->lazy_bind_size,
4335			"dyld lazy bind info") == CHECK_BAD)
4336		    goto return_bad;
4337		if(dyld_info->export_off != 0 && dyld_info->export_off > size){
4338		    Mach_O_error(ofile, "truncated or malformed object "
4339			"(export_off field of LC_DYLD_INFO command %u "
4340			"extends past the end of the file)", i);
4341		    goto return_bad;
4342		}
4343		if(dyld_info->export_off != 0){
4344		    big_size = dyld_info->export_off;
4345		    big_size += dyld_info->export_size;
4346		    if(big_size > size){
4347			Mach_O_error(ofile, "truncated or malformed object "
4348			    "(export_off plus export_size of LC_DYLD_INFO "
4349			    "command %u extends past the end of the file)", i);
4350			goto return_bad;
4351		    }
4352		}
4353		if(check_overlaping_element(ofile, &elements,
4354			dyld_info->export_off, dyld_info->export_size,
4355			"dyld export info") == CHECK_BAD)
4356		    goto return_bad;
4357		break;
4358
4359
4360
4361	    case LC_PREBIND_CKSUM:
4362		if(l.cmdsize < sizeof(struct prebind_cksum_command)){
4363		    Mach_O_error(ofile, "malformed object (LC_PREBIND_CKSUM "
4364				 "cmdsize too small) in command %u", i);
4365		    goto return_bad;
4366		}
4367		if(cs != NULL){
4368		    Mach_O_error(ofile, "malformed object (more than one "
4369			"LC_PREBIND_CKSUM command)");
4370		    goto return_bad;
4371		}
4372		cs = (struct prebind_cksum_command *)lc;
4373		if(swapped)
4374		    swap_prebind_cksum_command(cs, host_byte_sex);
4375		if(cs->cmdsize != sizeof(struct prebind_cksum_command)){
4376		    Mach_O_error(ofile, "malformed object (LC_PREBIND_CKSUM "
4377			"command %u has incorrect cmdsize)", i);
4378		    goto return_bad;
4379		}
4380		break;
4381
4382	    case LC_UUID:
4383		if(l.cmdsize < sizeof(struct uuid_command)){
4384		    Mach_O_error(ofile, "malformed object (LC_UUID cmdsize "
4385			         "too small) in command %u", i);
4386		    goto return_bad;
4387		}
4388		if(uuid != NULL){
4389		    Mach_O_error(ofile, "malformed object (more than one "
4390			"LC_UUID command)");
4391		    goto return_bad;
4392		}
4393		uuid = (struct uuid_command *)lc;
4394		if(swapped)
4395		    swap_uuid_command(uuid, host_byte_sex);
4396		if(uuid->cmdsize != sizeof(struct uuid_command)){
4397		    Mach_O_error(ofile, "malformed object (LC_UUID command %u "			"has incorrect cmdsize)", i);
4398		    goto return_bad;
4399		}
4400		break;
4401
4402	    case LC_SYMSEG:
4403		if(l.cmdsize < sizeof(struct symseg_command)){
4404		    Mach_O_error(ofile, "malformed object (LC_SYMSEG cmdsize "
4405			         "too small) in command %u", i);
4406		    goto return_bad;
4407		}
4408		ss = (struct symseg_command *)lc;
4409		if(swapped)
4410		    swap_symseg_command(ss, host_byte_sex);
4411		if(ss->cmdsize != sizeof(struct symseg_command)){
4412		    Mach_O_error(ofile, "malformed object (LC_SYMSEG command "
4413			"%u has incorrect cmdsize)", i);
4414		    goto return_bad;
4415		}
4416		if(ss->offset > size){
4417		    Mach_O_error(ofile, "truncated or malformed object (offset "
4418			"field of LC_SYMSEG command %u extends past the end "
4419			"of the file)", i);
4420		    goto return_bad;
4421		}
4422		big_size = ss->offset;
4423		big_size += ss->size;
4424		if(big_size > size){
4425		    Mach_O_error(ofile, "truncated or malformed object (offset "
4426			"field plus size field of LC_SYMTAB command %u "
4427			"extends past the end of the file)", i);
4428		    goto return_bad;
4429		}
4430		if(check_overlaping_element(ofile, &elements, ss->offset,
4431			ss->size, "symseg info") == CHECK_BAD)
4432		    goto return_bad;
4433		break;
4434
4435	    case LC_IDFVMLIB:
4436	    case LC_LOADFVMLIB:
4437		if(l.cmdsize < sizeof(struct fvmlib_command)){
4438		    Mach_O_error(ofile, "malformed object (%s cmdsize "
4439			         "too small) in command %u", l.cmd ==
4440				 LC_IDFVMLIB ? "LC_IDFVMLIB" :
4441				 "LC_LOADFVMLIB", i);
4442		    goto return_bad;
4443		}
4444		fl = (struct fvmlib_command *)lc;
4445		if(swapped)
4446		    swap_fvmlib_command(fl, host_byte_sex);
4447		if(fl->cmdsize < sizeof(struct fvmlib_command)){
4448		    Mach_O_error(ofile, "malformed object (%s command %u has "
4449			"too small cmdsize field)", fl->cmd == LC_IDFVMLIB ?
4450			"LC_IDFVMLIB" : "LC_LOADFVMLIB", i);
4451		    goto return_bad;
4452		}
4453		if(fl->fvmlib.name.offset >= fl->cmdsize){
4454		    Mach_O_error(ofile, "truncated or malformed object (name."
4455			"offset field of %s command %u extends past the end "
4456			"of the file)", fl->cmd == LC_IDFVMLIB ? "LC_IDFVMLIB"
4457			: "LC_LOADFVMLIB", i);
4458		    goto return_bad;
4459		}
4460		break;
4461
4462	    case LC_ID_DYLIB:
4463		cmd_name = "LC_ID_DYLIB";
4464		goto check_dylib_command;
4465	    case LC_LOAD_DYLIB:
4466		cmd_name = "LC_LOAD_DYLIB";
4467		goto check_dylib_command;
4468	    case LC_LOAD_WEAK_DYLIB:
4469		cmd_name = "LC_LOAD_WEAK_DYLIB";
4470		goto check_dylib_command;
4471	    case LC_REEXPORT_DYLIB:
4472		cmd_name = "LC_REEXPORT_DYLIB";
4473		goto check_dylib_command;
4474	    case LC_LOAD_UPWARD_DYLIB:
4475		cmd_name = "LC_LOAD_UPWARD_DYLIB";
4476		goto check_dylib_command;
4477	    case LC_LAZY_LOAD_DYLIB:
4478		cmd_name = "LC_LAZY_LOAD_DYLIB";
4479		goto check_dylib_command;
4480check_dylib_command:
4481		if(l.cmdsize < sizeof(struct dylib_command)){
4482		    Mach_O_error(ofile, "malformed object (%s cmdsize too "
4483				 "small) in command %u", cmd_name, i);
4484		    goto return_bad;
4485		}
4486		dl = (struct dylib_command *)lc;
4487		if(swapped)
4488		    swap_dylib_command(dl, host_byte_sex);
4489		if(dl->cmdsize < sizeof(struct dylib_command)){
4490		    Mach_O_error(ofile, "malformed object (%s command %u has "
4491			"too small cmdsize field)", cmd_name, i);
4492		    goto return_bad;
4493		}
4494		if(dl->dylib.name.offset >= dl->cmdsize){
4495		    Mach_O_error(ofile, "truncated or malformed object (name."
4496			"offset field of %s command %u extends past the end "
4497			"of the file)", cmd_name, i);
4498		    goto return_bad;
4499		}
4500		break;
4501
4502	    case LC_SUB_FRAMEWORK:
4503		if(l.cmdsize < sizeof(struct sub_framework_command)){
4504		    Mach_O_error(ofile, "malformed object (LC_SUB_FRAMEWORK "
4505				 "cmdsize too small) in command %u", i);
4506		    goto return_bad;
4507		}
4508		sub = (struct sub_framework_command *)lc;
4509		if(swapped)
4510		    swap_sub_framework_command(sub, host_byte_sex);
4511		if(sub->cmdsize < sizeof(struct sub_framework_command)){
4512		    Mach_O_error(ofile, "malformed object (LC_SUB_FRAMEWORK "
4513			"command %u has too small cmdsize field)", i);
4514		    goto return_bad;
4515		}
4516		if(sub->umbrella.offset >= sub->cmdsize){
4517		    Mach_O_error(ofile, "truncated or malformed object "
4518			"(umbrella.offset field of LC_SUB_FRAMEWORK command "
4519			"%u extends past the end of the file)", i);
4520		    goto return_bad;
4521		}
4522		break;
4523
4524	    case LC_SUB_UMBRELLA:
4525		if(l.cmdsize < sizeof(struct sub_umbrella_command)){
4526		    Mach_O_error(ofile, "malformed object (LC_SUB_UMBRELLA "
4527				 "cmdsize too small) in command %u", i);
4528		    goto return_bad;
4529		}
4530		usub = (struct sub_umbrella_command *)lc;
4531		if(swapped)
4532		    swap_sub_umbrella_command(usub, host_byte_sex);
4533		if(usub->cmdsize < sizeof(struct sub_umbrella_command)){
4534		    Mach_O_error(ofile, "malformed object (LC_SUB_UMBRELLA "
4535			"command %u has too small cmdsize field)", i);
4536		    goto return_bad;
4537		}
4538		if(usub->sub_umbrella.offset >= usub->cmdsize){
4539		    Mach_O_error(ofile, "truncated or malformed object "
4540			"(sub_umbrella.offset field of LC_SUB_UMBRELLA command "
4541			"%u extends past the end of the file)", i);
4542		    goto return_bad;
4543		}
4544		break;
4545
4546	    case LC_SUB_LIBRARY:
4547		if(l.cmdsize < sizeof(struct sub_library_command)){
4548		    Mach_O_error(ofile, "malformed object (LC_SUB_LIBRARY "
4549				 "cmdsize too small) in command %u", i);
4550		    goto return_bad;
4551		}
4552		lsub = (struct sub_library_command *)lc;
4553		if(swapped)
4554		    swap_sub_library_command(lsub, host_byte_sex);
4555		if(lsub->cmdsize < sizeof(struct sub_library_command)){
4556		    Mach_O_error(ofile, "malformed object (LC_SUB_LIBRARY "
4557			"command %u has too small cmdsize field)", i);
4558		    goto return_bad;
4559		}
4560		if(lsub->sub_library.offset >= lsub->cmdsize){
4561		    Mach_O_error(ofile, "truncated or malformed object "
4562			"(sub_library.offset field of LC_SUB_LIBRARY command "
4563			"%u extends past the end of the file)", i);
4564		    goto return_bad;
4565		}
4566		break;
4567
4568	    case LC_SUB_CLIENT:
4569		if(l.cmdsize < sizeof(struct sub_client_command)){
4570		    Mach_O_error(ofile, "malformed object (LC_SUB_CLIENT "
4571				 "cmdsize too small) in command %u", i);
4572		    goto return_bad;
4573		}
4574		csub = (struct sub_client_command *)lc;
4575		if(swapped)
4576		    swap_sub_client_command(csub, host_byte_sex);
4577		if(csub->cmdsize < sizeof(struct sub_client_command)){
4578		    Mach_O_error(ofile, "malformed object (LC_SUB_CLIENT "
4579			"command %u has too small cmdsize field)", i);
4580		    goto return_bad;
4581		}
4582		if(csub->client.offset >= csub->cmdsize){
4583		    Mach_O_error(ofile, "truncated or malformed object "
4584			"(cleient.offset field of LC_SUB_CLIENT command "
4585			"%u extends past the end of the file)", i);
4586		    goto return_bad;
4587		}
4588		break;
4589
4590	    case LC_PREBOUND_DYLIB:
4591		if(l.cmdsize < sizeof(struct prebound_dylib_command)){
4592		    Mach_O_error(ofile, "malformed object (LC_PREBOUND_DYLIB "
4593				 "cmdsize too small) in command %u", i);
4594		    goto return_bad;
4595		}
4596		pbdylib = (struct prebound_dylib_command *)lc;
4597		if(swapped)
4598		    swap_prebound_dylib_command(pbdylib, host_byte_sex);
4599		if(pbdylib->cmdsize < sizeof(struct dylib_command)){
4600		    Mach_O_error(ofile, "malformed object (LC_PREBIND_DYLIB "
4601			"command %u has too small cmdsize field)", i);
4602		    goto return_bad;
4603		}
4604		if(pbdylib->name.offset >= pbdylib->cmdsize){
4605		    Mach_O_error(ofile, "truncated or malformed object (name."
4606			"offset field of LC_PREBIND_DYLIB command %u extends "
4607			"past the end of the file)", i);
4608		    goto return_bad;
4609		}
4610		if(pbdylib->linked_modules.offset >= pbdylib->cmdsize){
4611		    Mach_O_error(ofile, "truncated or malformed object (linked_"
4612			"modules.offset field of LC_PREBIND_DYLIB command %u "
4613			"extends past the end of the file)", i);
4614		    goto return_bad;
4615		}
4616		break;
4617
4618	    case LC_ID_DYLINKER:
4619		cmd_name = "LC_ID_DYLINKER";
4620		goto check_dylinker_command;
4621	    case LC_LOAD_DYLINKER:
4622		cmd_name = "LC_LOAD_DYLINKER";
4623		goto check_dylinker_command;
4624	    case LC_DYLD_ENVIRONMENT:
4625		cmd_name = "LC_DYLD_ENVIRONMENT";
4626		goto check_dylinker_command;
4627check_dylinker_command:
4628		if(l.cmdsize < sizeof(struct dylinker_command)){
4629		    Mach_O_error(ofile, "malformed object (%s cmdsize "
4630			         "too small) in command %u", cmd_name, i);
4631		    goto return_bad;
4632		}
4633		dyld = (struct dylinker_command *)lc;
4634		if(swapped)
4635		    swap_dylinker_command(dyld, host_byte_sex);
4636		if(dyld->cmdsize < sizeof(struct dylinker_command)){
4637		    Mach_O_error(ofile, "malformed object (%s command %u has "
4638			"too small cmdsize field)", cmd_name, i);
4639		    goto return_bad;
4640		}
4641		if(dyld->name.offset >= dyld->cmdsize){
4642		    Mach_O_error(ofile, "truncated or malformed object (name."
4643			"offset field of %s command %u extends past the end "
4644			"of the file)", cmd_name, i);
4645		    goto return_bad;
4646		}
4647		break;
4648
4649	    case LC_UNIXTHREAD:
4650	    case LC_THREAD:
4651		if(l.cmdsize < sizeof(struct thread_command)){
4652		    Mach_O_error(ofile, "malformed object (%s cmdsize "
4653			         "too small) in command %u", l.cmd ==
4654				 LC_UNIXTHREAD ? "LC_UNIXTHREAD" :
4655				 "LC_THREAD", i);
4656		    goto return_bad;
4657		}
4658		ut = (struct thread_command *)lc;
4659		if(swapped)
4660		    swap_thread_command(ut, host_byte_sex);
4661		state = (char *)ut + sizeof(struct thread_command);
4662
4663	    	if(cputype == CPU_TYPE_MC680x0){
4664		    struct m68k_thread_state_regs *cpu;
4665		    struct m68k_thread_state_68882 *fpu;
4666		    struct m68k_thread_state_user_reg *user_reg;
4667
4668		    nflavor = 0;
4669		    p = (char *)ut + ut->cmdsize;
4670		    while(state < p){
4671			if(state +  sizeof(uint32_t) >
4672			   (char *)ut + ut->cmdsize){
4673			    Mach_O_error(ofile, "malformed object (flavor in "
4674				"%s command %u extends past end of command)",
4675				ut->cmd == LC_UNIXTHREAD ?  "LC_UNIXTHREAD" :
4676				"LC_THREAD", i);
4677			    goto return_bad;
4678			}
4679			flavor = *((uint32_t *)state);
4680			if(swapped){
4681			    flavor = SWAP_INT(flavor);
4682			    *((uint32_t *)state) = flavor;
4683			}
4684			state += sizeof(uint32_t);
4685			if(state +  sizeof(uint32_t) >
4686			   (char *)ut + ut->cmdsize){
4687			    Mach_O_error(ofile, "malformed object (count in "
4688				"%s command %u extends past end of command)",
4689				ut->cmd == LC_UNIXTHREAD ?  "LC_UNIXTHREAD" :
4690				"LC_THREAD", i);
4691			    goto return_bad;
4692			}
4693			count = *((uint32_t *)state);
4694			if(swapped){
4695			    count = SWAP_INT(count);
4696			    *((uint32_t *)state) = count;
4697			}
4698			state += sizeof(uint32_t);
4699			switch(flavor){
4700			case M68K_THREAD_STATE_REGS:
4701			    if(count != M68K_THREAD_STATE_REGS_COUNT){
4702				Mach_O_error(ofile, "malformed object (count "
4703				    "not M68K_THREAD_STATE_REGS_COUNT for "
4704				    "flavor number %u which is a M68K_THREAD_"
4705				    "STATE_REGS flavor in %s command %u)",
4706				    nflavor, ut->cmd == LC_UNIXTHREAD ?
4707				    "LC_UNIXTHREAD" : "LC_THREAD", i);
4708				goto return_bad;
4709			    }
4710			    cpu = (struct m68k_thread_state_regs *)state;
4711			    if(state + sizeof(struct m68k_thread_state_regs) >
4712			       (char *)ut + ut->cmdsize){
4713				Mach_O_error(ofile, "malformed object ("
4714				    "M68K_THREAD_STATE_REGS in %s command %u "
4715				    "extends past end of command)", ut->cmd ==
4716				    LC_UNIXTHREAD ?  "LC_UNIXTHREAD" :
4717				    "LC_THREAD", i);
4718				goto return_bad;
4719			    }
4720			    if(swapped)
4721				swap_m68k_thread_state_regs(cpu, host_byte_sex);
4722			    state += sizeof(struct m68k_thread_state_regs);
4723			    break;
4724			case M68K_THREAD_STATE_68882:
4725			    if(count != M68K_THREAD_STATE_68882_COUNT){
4726				Mach_O_error(ofile, "malformed object (count "
4727				    "not M68K_THREAD_STATE_68882_COUNT for "
4728				    "flavor number %u which is a M68K_THREAD_"
4729				    "STATE_68882 flavor in %s command %u)",
4730				    nflavor, ut->cmd == LC_UNIXTHREAD ?
4731				    "LC_UNIXTHREAD" : "LC_THREAD", i);
4732				goto return_bad;
4733			    }
4734			    fpu = (struct m68k_thread_state_68882 *)state;
4735			    if(state + sizeof(struct m68k_thread_state_68882) >
4736			       (char *)ut + ut->cmdsize){
4737				Mach_O_error(ofile, "malformed object ("
4738				    "M68K_THREAD_STATE_68882 in %s command %u "
4739				    "extends past end of command)", ut->cmd ==
4740				    LC_UNIXTHREAD ?  "LC_UNIXTHREAD" :
4741				    "LC_THREAD", i);
4742				goto return_bad;
4743			    }
4744			    if(swapped)
4745				swap_m68k_thread_state_68882(fpu,host_byte_sex);
4746			    state += sizeof(struct m68k_thread_state_68882);
4747			    break;
4748			case M68K_THREAD_STATE_USER_REG:
4749			    if(count != M68K_THREAD_STATE_USER_REG_COUNT){
4750				Mach_O_error(ofile, "malformed object (count "
4751				    "not M68K_THREAD_STATE_USER_REG_COUNT for "
4752				    "flavor number %u which is a M68K_THREAD_"
4753				    "STATE_USER_REG flavor in %s command %u)",
4754				    nflavor, ut->cmd == LC_UNIXTHREAD ?
4755				    "LC_UNIXTHREAD" : "LC_THREAD", i);
4756				goto return_bad;
4757			    }
4758			    user_reg =
4759				(struct m68k_thread_state_user_reg *)state;
4760			    if(state+sizeof(struct m68k_thread_state_user_reg) >
4761			       (char *)ut + ut->cmdsize){
4762				Mach_O_error(ofile, "malformed object ("
4763				    "M68K_THREAD_STATE_USER_REG in %s command "
4764				    "%u extends past end of command)", ut->cmd==
4765				    LC_UNIXTHREAD ?  "LC_UNIXTHREAD" :
4766				    "LC_THREAD", i);
4767				goto return_bad;
4768			    }
4769			    if(swapped)
4770				swap_m68k_thread_state_user_reg(user_reg,
4771								host_byte_sex);
4772			    state += sizeof(struct m68k_thread_state_user_reg);
4773			    break;
4774			default:
4775			    if(swapped){
4776				Mach_O_error(ofile, "malformed object (unknown "
4777				    "flavor for flavor number %u in %s command"
4778				    " %u can't byte swap it)", nflavor,
4779				    ut->cmd == LC_UNIXTHREAD ? "LC_UNIXTHREAD" :
4780				    "LC_THREAD", i);
4781				goto return_bad;
4782			    }
4783			    state += count * sizeof(uint32_t);
4784			    break;
4785			}
4786			nflavor++;
4787		    }
4788		    break;
4789		}
4790	    	if(cputype == CPU_TYPE_POWERPC ||
4791	    	   cputype == CPU_TYPE_VEO){
4792		    ppc_thread_state_t *nrw_cpu;
4793
4794		    nflavor = 0;
4795		    p = (char *)ut + ut->cmdsize;
4796		    while(state < p){
4797			if(state +  sizeof(uint32_t) >
4798			   (char *)ut + ut->cmdsize){
4799			    Mach_O_error(ofile, "malformed object (flavor in "
4800				"%s command %u extends past end of command)",
4801				ut->cmd == LC_UNIXTHREAD ?  "LC_UNIXTHREAD" :
4802				"LC_THREAD", i);
4803			    goto return_bad;
4804			}
4805			flavor = *((uint32_t *)state);
4806			if(swapped){
4807			    flavor = SWAP_INT(flavor);
4808			    *((uint32_t *)state) = flavor;
4809			}
4810			state += sizeof(uint32_t);
4811			if(state +  sizeof(uint32_t) >
4812			   (char *)ut + ut->cmdsize){
4813			    Mach_O_error(ofile, "malformed object (count in "
4814				"%s command %u extends past end of command)",
4815				ut->cmd == LC_UNIXTHREAD ?  "LC_UNIXTHREAD" :
4816				"LC_THREAD", i);
4817			    goto return_bad;
4818			}
4819			count = *((uint32_t *)state);
4820			if(swapped){
4821			    count = SWAP_INT(count);
4822			    *((uint32_t *)state) = count;
4823			}
4824			state += sizeof(uint32_t);
4825			switch(flavor){
4826			case PPC_THREAD_STATE:
4827			    if(count != PPC_THREAD_STATE_COUNT){
4828				Mach_O_error(ofile, "malformed object (count "
4829				    "not PPC_THREAD_STATE_COUNT for "
4830				    "flavor number %u which is a PPC_THREAD_"
4831				    "STATE flavor in %s command %u)",
4832				    nflavor, ut->cmd == LC_UNIXTHREAD ?
4833				    "LC_UNIXTHREAD" : "LC_THREAD", i);
4834				goto return_bad;
4835			    }
4836			    nrw_cpu = (ppc_thread_state_t *)state;
4837			    if(state + sizeof(ppc_thread_state_t) >
4838			       (char *)ut + ut->cmdsize){
4839				Mach_O_error(ofile, "malformed object ("
4840				    "PPC_THREAD_STATE in %s command %u extends"
4841				    " past end of command)", ut->cmd ==
4842				    LC_UNIXTHREAD ?  "LC_UNIXTHREAD" :
4843				    "LC_THREAD", i);
4844				goto return_bad;
4845			    }
4846			    if(swapped)
4847				swap_ppc_thread_state_t(nrw_cpu,
4848							     host_byte_sex);
4849			    state += sizeof(ppc_thread_state_t);
4850			    break;
4851			default:
4852			    if(swapped){
4853				Mach_O_error(ofile, "malformed object (unknown "
4854				    "flavor for flavor number %u in %s command"
4855				    " %u can't byte swap it)", nflavor,
4856				    ut->cmd == LC_UNIXTHREAD ? "LC_UNIXTHREAD" :
4857				    "LC_THREAD", i);
4858				goto return_bad;
4859			    }
4860			    state += count * sizeof(uint32_t);
4861			    break;
4862			}
4863			nflavor++;
4864		    }
4865		    break;
4866		}
4867#ifdef PPC_THREAD_STATE64_COUNT
4868	    	if(cputype == CPU_TYPE_POWERPC64){
4869		    ppc_thread_state64_t *cpu;
4870
4871		    nflavor = 0;
4872		    p = (char *)ut + ut->cmdsize;
4873		    while(state < p){
4874			if(state +  sizeof(uint32_t) >
4875			   (char *)ut + ut->cmdsize){
4876			    Mach_O_error(ofile, "malformed object (flavor in "
4877				"%s command %u extends past end of command)",
4878				ut->cmd == LC_UNIXTHREAD ?  "LC_UNIXTHREAD" :
4879				"LC_THREAD", i);
4880			    goto return_bad;
4881			}
4882			flavor = *((uint32_t *)state);
4883			if(swapped){
4884			    flavor = SWAP_INT(flavor);
4885			    *((uint32_t *)state) = flavor;
4886			}
4887			state += sizeof(uint32_t);
4888			if(state +  sizeof(uint32_t) >
4889			   (char *)ut + ut->cmdsize){
4890			    Mach_O_error(ofile, "malformed object (count in "
4891				"%s command %u extends past end of command)",
4892				ut->cmd == LC_UNIXTHREAD ?  "LC_UNIXTHREAD" :
4893				"LC_THREAD", i);
4894			    goto return_bad;
4895			}
4896			count = *((uint32_t *)state);
4897			if(swapped){
4898			    count = SWAP_INT(count);
4899			    *((uint32_t *)state) = count;
4900			}
4901			state += sizeof(uint32_t);
4902			switch(flavor){
4903			case PPC_THREAD_STATE64:
4904			    if(count != PPC_THREAD_STATE64_COUNT){
4905				Mach_O_error(ofile, "malformed object (count "
4906				    "not PPC_THREAD_STATE64_COUNT for "
4907				    "flavor number %u which is a PPC_THREAD_"
4908				    "STATE64 flavor in %s command %u)",
4909				    nflavor, ut->cmd == LC_UNIXTHREAD ?
4910				    "LC_UNIXTHREAD" : "LC_THREAD", i);
4911				goto return_bad;
4912			    }
4913			    cpu = (ppc_thread_state64_t *)state;
4914			    if(state + sizeof(ppc_thread_state64_t) >
4915			       (char *)ut + ut->cmdsize){
4916				Mach_O_error(ofile, "malformed object ("
4917				    "PPC_THREAD_STATE64 in %s command %u "
4918				    "extends past end of command)", ut->cmd ==
4919				    LC_UNIXTHREAD ?  "LC_UNIXTHREAD" :
4920				    "LC_THREAD", i);
4921				goto return_bad;
4922			    }
4923			    if(swapped)
4924				swap_ppc_thread_state64_t(cpu, host_byte_sex);
4925			    state += sizeof(ppc_thread_state64_t);
4926			    break;
4927			default:
4928			    if(swapped){
4929				Mach_O_error(ofile, "malformed object (unknown "
4930				    "flavor for flavor number %u in %s command"
4931				    " %u can't byte swap it)", nflavor,
4932				    ut->cmd == LC_UNIXTHREAD ? "LC_UNIXTHREAD" :
4933				    "LC_THREAD", i);
4934				goto return_bad;
4935			    }
4936			    state += count * sizeof(uint32_t);
4937			    break;
4938			}
4939			nflavor++;
4940		    }
4941		    break;
4942		}
4943#endif /* PPC_THREAD_STATE64_COUNT */
4944	    	if(cputype == CPU_TYPE_MC88000){
4945		    m88k_thread_state_grf_t *cpu;
4946		    m88k_thread_state_xrf_t *fpu;
4947		    m88k_thread_state_user_t *user;
4948		    m88110_thread_state_impl_t *spu;
4949
4950		    nflavor = 0;
4951		    p = (char *)ut + ut->cmdsize;
4952		    while(state < p){
4953			if(state +  sizeof(uint32_t) >
4954			   (char *)ut + ut->cmdsize){
4955			    Mach_O_error(ofile, "malformed object (flavor in "
4956				"%s command %u extends past end of command)",
4957				ut->cmd == LC_UNIXTHREAD ?  "LC_UNIXTHREAD" :
4958				"LC_THREAD", i);
4959			    goto return_bad;
4960			}
4961			flavor = *((uint32_t *)state);
4962			if(swapped){
4963			    flavor = SWAP_INT(flavor);
4964			    *((uint32_t *)state) = flavor;
4965			}
4966			state += sizeof(uint32_t);
4967			if(state +  sizeof(uint32_t) >
4968			   (char *)ut + ut->cmdsize){
4969			    Mach_O_error(ofile, "malformed object (count in "
4970				"%s command %u extends past end of command)",
4971				ut->cmd == LC_UNIXTHREAD ?  "LC_UNIXTHREAD" :
4972				"LC_THREAD", i);
4973			    goto return_bad;
4974			}
4975			count = *((uint32_t *)state);
4976			if(swapped){
4977			    count = SWAP_INT(count);
4978			    *((uint32_t *)state) = count;
4979			}
4980			state += sizeof(uint32_t);
4981			switch(flavor){
4982			case M88K_THREAD_STATE_GRF:
4983			    if(count != M88K_THREAD_STATE_GRF_COUNT){
4984				Mach_O_error(ofile, "malformed object (count "
4985				    "not M88K_THREAD_STATE_GRF_COUNT for "
4986				    "flavor number %u which is a M88K_THREAD_"
4987				    "STATE_GRF flavor in %s command %u)",
4988				    nflavor, ut->cmd == LC_UNIXTHREAD ?
4989				    "LC_UNIXTHREAD" : "LC_THREAD", i);
4990				goto return_bad;
4991			    }
4992			    cpu = (m88k_thread_state_grf_t *)state;
4993			    if(state + sizeof(m88k_thread_state_grf_t) >
4994			       (char *)ut + ut->cmdsize){
4995				Mach_O_error(ofile, "malformed object ("
4996				    "M88K_THREAD_STATE_GRF in %s command %u "
4997				    "extends past end of command)", ut->cmd ==
4998				    LC_UNIXTHREAD ?  "LC_UNIXTHREAD" :
4999				    "LC_THREAD", i);
5000				goto return_bad;
5001			    }
5002			    if(swapped)
5003				swap_m88k_thread_state_grf_t(cpu,
5004							     host_byte_sex);
5005			    state += sizeof(m88k_thread_state_grf_t);
5006			    break;
5007			case M88K_THREAD_STATE_XRF:
5008			    if(count != M88K_THREAD_STATE_XRF_COUNT){
5009				Mach_O_error(ofile, "malformed object (count "
5010				    "not M88K_THREAD_STATE_XRF_COUNT for "
5011				    "flavor number %u which is a M88K_THREAD_"
5012				    "STATE_XRF flavor in %s command %u)",
5013				    nflavor, ut->cmd == LC_UNIXTHREAD ?
5014				    "LC_UNIXTHREAD" : "LC_THREAD", i);
5015				goto return_bad;
5016			    }
5017			    fpu = (m88k_thread_state_xrf_t *)state;
5018			    if(state + sizeof(m88k_thread_state_xrf_t) >
5019			       (char *)ut + ut->cmdsize){
5020				Mach_O_error(ofile, "malformed object ("
5021				    "M88K_THREAD_STATE_XRF in %s command %u "
5022				    "extends past end of command)", ut->cmd ==
5023				    LC_UNIXTHREAD ?  "LC_UNIXTHREAD" :
5024				    "LC_THREAD", i);
5025				goto return_bad;
5026			    }
5027			    if(swapped)
5028				swap_m88k_thread_state_xrf_t(fpu,
5029							     host_byte_sex);
5030			    state += sizeof(m88k_thread_state_xrf_t);
5031			    break;
5032			case M88K_THREAD_STATE_USER:
5033			    if(count != M88K_THREAD_STATE_USER_COUNT){
5034				Mach_O_error(ofile, "malformed object (count "
5035				    "not M88K_THREAD_STATE_USER_COUNT for "
5036				    "flavor number %u which is a M88K_THREAD_"
5037				    "STATE_USER flavor in %s command %u)",
5038				    nflavor, ut->cmd == LC_UNIXTHREAD ?
5039				    "LC_UNIXTHREAD" : "LC_THREAD", i);
5040				goto return_bad;
5041			    }
5042			    user = (m88k_thread_state_user_t *)state;
5043			    if(state + sizeof(m88k_thread_state_user_t) >
5044			       (char *)ut + ut->cmdsize){
5045				Mach_O_error(ofile, "malformed object ("
5046				    "M88K_THREAD_STATE_USER in %s command %u "
5047				    "extends past end of command)", ut->cmd ==
5048				    LC_UNIXTHREAD ?  "LC_UNIXTHREAD" :
5049				    "LC_THREAD", i);
5050				goto return_bad;
5051			    }
5052			    if(swapped)
5053				swap_m88k_thread_state_user_t(user,
5054							      host_byte_sex);
5055			    state += sizeof(m88k_thread_state_user_t);
5056			    break;
5057			case M88110_THREAD_STATE_IMPL:
5058			    if(count != M88110_THREAD_STATE_IMPL_COUNT){
5059				Mach_O_error(ofile, "malformed object (count "
5060				    "not M88110_THREAD_STATE_IMPL_COUNT for "
5061				    "flavor number %u which is a M88110_THREAD"
5062				    "_STATE_IMPL flavor in %s command %u)",
5063				    nflavor, ut->cmd == LC_UNIXTHREAD ?
5064				    "LC_UNIXTHREAD" : "LC_THREAD", i);
5065				goto return_bad;
5066			    }
5067			    spu = (m88110_thread_state_impl_t *)state;
5068			    if(state + sizeof(m88110_thread_state_impl_t) >
5069			       (char *)ut + ut->cmdsize){
5070				Mach_O_error(ofile, "malformed object ("
5071				    "M88110_THREAD_STATE_IMPL in %s command %u "
5072				    "extends past end of command)", ut->cmd ==
5073				    LC_UNIXTHREAD ?  "LC_UNIXTHREAD" :
5074				    "LC_THREAD", i);
5075				goto return_bad;
5076			    }
5077			    if(swapped)
5078				swap_m88110_thread_state_impl_t(spu,
5079							      host_byte_sex);
5080			    state += sizeof(m88110_thread_state_impl_t);
5081			    break;
5082			default:
5083			    if(swapped){
5084				Mach_O_error(ofile, "malformed object (unknown "
5085				    "flavor for flavor number %u in %s command"
5086				    " %u can't byte swap it)", nflavor,
5087				    ut->cmd == LC_UNIXTHREAD ? "LC_UNIXTHREAD" :
5088				    "LC_THREAD", i);
5089				goto return_bad;
5090			    }
5091			    state += count * sizeof(uint32_t);
5092			    break;
5093			}
5094			nflavor++;
5095		    }
5096		    break;
5097		}
5098	    	if(cputype == CPU_TYPE_I860){
5099#ifdef m68k
5100		    struct i860_thread_state_regs *cpu;
5101#endif
5102
5103		    nflavor = 0;
5104		    p = (char *)ut + ut->cmdsize;
5105		    while(state < p){
5106			if(state +  sizeof(uint32_t) >
5107			   (char *)ut + ut->cmdsize){
5108			    Mach_O_error(ofile, "malformed object (flavor in "
5109				"%s command %u extends past end of command)",
5110				ut->cmd == LC_UNIXTHREAD ?  "LC_UNIXTHREAD" :
5111				"LC_THREAD", i);
5112			    goto return_bad;
5113			}
5114			flavor = *((uint32_t *)state);
5115			if(swapped){
5116			    flavor = SWAP_INT(flavor);
5117			    *((uint32_t *)state) = flavor;
5118			}
5119			state += sizeof(uint32_t);
5120			if(state +  sizeof(uint32_t) >
5121			   (char *)ut + ut->cmdsize){
5122			    Mach_O_error(ofile, "malformed object (count in "
5123				"%s command %u extends past end of command)",
5124				ut->cmd == LC_UNIXTHREAD ?  "LC_UNIXTHREAD" :
5125				"LC_THREAD", i);
5126			    return(CHECK_BAD);
5127			}
5128			count = *((uint32_t *)state);
5129			if(swapped){
5130			    count = SWAP_INT(count);
5131			    *((uint32_t *)state) = count;
5132			}
5133			state += sizeof(uint32_t);
5134			switch(flavor){
5135			case I860_THREAD_STATE_REGS:
5136#ifdef m68k
5137			    if(count != I860_THREAD_STATE_REGS_COUNT){
5138				Mach_O_error(ofile, "malformed object (count "
5139				    "not I860_THREAD_STATE_REGS_COUNT for "
5140				    "flavor number %u which is a I860_THREAD_"
5141				    "STATE_REGS flavor in %s command %u)",
5142				    nflavor, ut->cmd == LC_UNIXTHREAD ?
5143				    "LC_UNIXTHREAD" : "LC_THREAD", i);
5144				goto return_bad;
5145			    }
5146			    cpu = (struct i860_thread_state_regs *)state;
5147			    if(state + sizeof(struct i860_thread_state_regs) >
5148			       (char *)ut + ut->cmdsize){
5149				Mach_O_error(ofile, "malformed object ("
5150				    "I860_THREAD_STATE_REGS in %s command %u "
5151				    "extends past end of command)", ut->cmd ==
5152				    LC_UNIXTHREAD ?  "LC_UNIXTHREAD" :
5153				    "LC_THREAD", i);
5154				goto return_bad;
5155			    }
5156			    if(swapped)
5157				swap_i860_thread_state_regs(cpu, host_byte_sex);
5158			    state += sizeof(struct i860_thread_state_regs);
5159#else
5160			    state += count * sizeof(int);
5161#endif
5162			    break;
5163			default:
5164			    if(swapped){
5165				Mach_O_error(ofile, "malformed object (unknown "
5166				    "flavor for flavor number %u in %s command"
5167				    " %u can't byte swap it)", nflavor,
5168				    ut->cmd == LC_UNIXTHREAD ? "LC_UNIXTHREAD" :
5169				    "LC_THREAD", i);
5170				goto return_bad;
5171			    }
5172			    state += count * sizeof(uint32_t);
5173			    break;
5174			}
5175			nflavor++;
5176		    }
5177		    break;
5178		}
5179	    	if(cputype == CPU_TYPE_I386){
5180		    i386_thread_state_t *cpu;
5181/* current i386 thread states */
5182#if i386_THREAD_STATE == 1
5183		    struct i386_float_state *fpu;
5184		    i386_exception_state_t *exc;
5185#endif /* i386_THREAD_STATE == 1 */
5186
5187/* i386 thread states on older releases */
5188#if i386_THREAD_STATE == -1
5189		    i386_thread_fpstate_t *fpu;
5190		    i386_thread_exceptstate_t *exc;
5191		    i386_thread_cthreadstate_t *user;
5192#endif /* i386_THREAD_STATE == -1 */
5193
5194		    nflavor = 0;
5195		    p = (char *)ut + ut->cmdsize;
5196		    while(state < p){
5197			if(state +  sizeof(uint32_t) >
5198			   (char *)ut + ut->cmdsize){
5199			    Mach_O_error(ofile, "malformed object (flavor in "
5200				"%s command %u extends past end of command)",
5201				ut->cmd == LC_UNIXTHREAD ?  "LC_UNIXTHREAD" :
5202				"LC_THREAD", i);
5203			    goto return_bad;
5204			}
5205			flavor = *((uint32_t *)state);
5206			if(swapped){
5207			    flavor = SWAP_INT(flavor);
5208			    *((uint32_t *)state) = flavor;
5209			}
5210			state += sizeof(uint32_t);
5211			if(state +  sizeof(uint32_t) >
5212			   (char *)ut + ut->cmdsize){
5213			    Mach_O_error(ofile, "malformed object (count in "
5214				"%s command %u extends past end of command)",
5215				ut->cmd == LC_UNIXTHREAD ?  "LC_UNIXTHREAD" :
5216				"LC_THREAD", i);
5217			    goto return_bad;
5218			}
5219			count = *((uint32_t *)state);
5220			if(swapped){
5221			    count = SWAP_INT(count);
5222			    *((uint32_t *)state) = count;
5223			}
5224			state += sizeof(uint32_t);
5225			switch((int)flavor){
5226			case i386_THREAD_STATE:
5227#if i386_THREAD_STATE == 1
5228			case -1:
5229#endif /* i386_THREAD_STATE == 1 */
5230/* i386 thread states on older releases */
5231#if i386_THREAD_STATE == -1
5232			case 1:
5233#endif /* i386_THREAD_STATE == -1 */
5234			    if(count != i386_THREAD_STATE_COUNT){
5235				Mach_O_error(ofile, "malformed object (count "
5236				    "not i386_THREAD_STATE_COUNT for flavor "
5237				    "number %u which is a i386_THREAD_STATE "
5238				    "flavor in %s command %u)", nflavor,
5239				    ut->cmd == LC_UNIXTHREAD ? "LC_UNIXTHREAD" :
5240				    "LC_THREAD", i);
5241				goto return_bad;
5242			    }
5243			    cpu = (i386_thread_state_t *)state;
5244			    if(state + sizeof(i386_thread_state_t) >
5245			       (char *)ut + ut->cmdsize){
5246				Mach_O_error(ofile, "malformed object ("
5247				    "i386_THREAD_STATE in %s command %u "
5248				    "extends past end of command)", ut->cmd ==
5249				    LC_UNIXTHREAD ?  "LC_UNIXTHREAD" :
5250				    "LC_THREAD", i);
5251				goto return_bad;
5252			    }
5253			    if(swapped)
5254				swap_i386_thread_state(cpu, host_byte_sex);
5255			    state += sizeof(i386_thread_state_t);
5256			    break;
5257/* current i386 thread states */
5258#if i386_THREAD_STATE == 1
5259			case i386_FLOAT_STATE:
5260			    if(count != i386_FLOAT_STATE_COUNT){
5261				Mach_O_error(ofile, "malformed object (count "
5262				    "not i386_FLOAT_STATE_COUNT for flavor "
5263				    "number %u which is a i386_FLOAT_STATE "
5264				    "flavor in %s command %u)", nflavor,
5265				    ut->cmd == LC_UNIXTHREAD ? "LC_UNIXTHREAD" :
5266				    "LC_THREAD", i);
5267				goto return_bad;
5268			    }
5269			    fpu = (struct i386_float_state *)state;
5270			    if(state + sizeof(struct i386_float_state) >
5271			       (char *)ut + ut->cmdsize){
5272				Mach_O_error(ofile, "malformed object ("
5273				    "i386_FLOAT_STATE in %s command %u "
5274				    "extends past end of command)", ut->cmd ==
5275				    LC_UNIXTHREAD ?  "LC_UNIXTHREAD" :
5276				    "LC_THREAD", i);
5277				goto return_bad;
5278			    }
5279			    if(swapped)
5280				swap_i386_float_state(fpu, host_byte_sex);
5281			    state += sizeof(struct i386_float_state);
5282			    break;
5283			case i386_EXCEPTION_STATE:
5284			    if(count != I386_EXCEPTION_STATE_COUNT){
5285				Mach_O_error(ofile, "malformed object (count "
5286				    "not I386_EXCEPTION_STATE_COUNT for "
5287				    "flavor number %u which is a i386_"
5288				    "EXCEPTION_STATE flavor in %s command %u)",
5289				    nflavor,
5290				    ut->cmd == LC_UNIXTHREAD ? "LC_UNIXTHREAD" :
5291				    "LC_THREAD", i);
5292				goto return_bad;
5293			    }
5294			    exc = (i386_exception_state_t *)state;
5295			    if(state + sizeof(i386_exception_state_t) >
5296			       (char *)ut + ut->cmdsize){
5297				Mach_O_error(ofile, "malformed object ("
5298				    "i386_EXCEPTION_STATE in %s command %u "
5299				    "extends past end of command)", ut->cmd ==
5300				    LC_UNIXTHREAD ?  "LC_UNIXTHREAD" :
5301				    "LC_THREAD", i);
5302				goto return_bad;
5303			    }
5304			    if(swapped)
5305				swap_i386_exception_state(exc,host_byte_sex);
5306			    state += sizeof(i386_exception_state_t);
5307			    break;
5308#endif /* i386_THREAD_STATE == 1 */
5309
5310/* i386 thread states on older releases */
5311#if i386_THREAD_STATE == -1
5312			case i386_THREAD_FPSTATE:
5313			    if(count != i386_THREAD_FPSTATE_COUNT){
5314				Mach_O_error(ofile, "malformed object (count "
5315				    "not i386_THREAD_FPSTATE_COUNT for flavor "
5316				    "number %u which is a i386_THREAD_FPSTATE "
5317				    "flavor in %s command %u)", nflavor,
5318				    ut->cmd == LC_UNIXTHREAD ? "LC_UNIXTHREAD" :
5319				    "LC_THREAD", i);
5320				goto return_bad;
5321			    }
5322			    fpu = (i386_thread_fpstate_t *)state;
5323			    if(state + sizeof(i386_thread_fpstate_t) >
5324			       (char *)ut + ut->cmdsize){
5325				Mach_O_error(ofile, "malformed object ("
5326				    "i386_THREAD_FPSTATE in %s command %u "
5327				    "extends past end of command)", ut->cmd ==
5328				    LC_UNIXTHREAD ?  "LC_UNIXTHREAD" :
5329				    "LC_THREAD", i);
5330				goto return_bad;
5331			    }
5332			    if(swapped)
5333				swap_i386_thread_fpstate(fpu, host_byte_sex);
5334			    state += sizeof(i386_thread_fpstate_t);
5335			    break;
5336			case i386_THREAD_EXCEPTSTATE:
5337			    if(count != i386_THREAD_EXCEPTSTATE_COUNT){
5338				Mach_O_error(ofile, "malformed object (count "
5339				    "not i386_THREAD_EXCEPTSTATE_COUNT for "
5340				    "flavor number %u which is a i386_THREAD_"
5341				    "EXCEPTSTATE flavor in %s command %u)",
5342				    nflavor,
5343				    ut->cmd == LC_UNIXTHREAD ? "LC_UNIXTHREAD" :
5344				    "LC_THREAD", i);
5345				goto return_bad;
5346			    }
5347			    exc = (i386_thread_exceptstate_t *)state;
5348			    if(state + sizeof(i386_thread_exceptstate_t) >
5349			       (char *)ut + ut->cmdsize){
5350				Mach_O_error(ofile, "malformed object ("
5351				    "i386_THREAD_EXCEPTSTATE in %s command %u "
5352				    "extends past end of command)", ut->cmd ==
5353				    LC_UNIXTHREAD ?  "LC_UNIXTHREAD" :
5354				    "LC_THREAD", i);
5355				goto return_bad;
5356			    }
5357			    if(swapped)
5358				swap_i386_thread_exceptstate(exc,host_byte_sex);
5359			    state += sizeof(i386_thread_exceptstate_t);
5360			    break;
5361			case i386_THREAD_CTHREADSTATE:
5362			    if(count != i386_THREAD_CTHREADSTATE_COUNT){
5363				Mach_O_error(ofile, "malformed object (count "
5364				    "not i386_THREAD_CTHREADSTATE_COUNT for "
5365				    "flavor number %u which is a i386_THREAD_"
5366				    "CTHREADSTATE flavor in %s command %u)",
5367				    nflavor,
5368				    ut->cmd == LC_UNIXTHREAD ? "LC_UNIXTHREAD" :
5369				    "LC_THREAD", i);
5370				goto return_bad;
5371			    }
5372			    user = (i386_thread_cthreadstate_t *)state;
5373			    if(state + sizeof(i386_thread_cthreadstate_t) >
5374			       (char *)ut + ut->cmdsize){
5375				Mach_O_error(ofile, "malformed object ("
5376				    "i386_THREAD_CTHREADSTATE in %s command %u "
5377				    "extends past end of command)", ut->cmd ==
5378				    LC_UNIXTHREAD ?  "LC_UNIXTHREAD" :
5379				    "LC_THREAD", i);
5380				goto return_bad;
5381			    }
5382			    if(swapped)
5383				swap_i386_thread_cthreadstate(user,
5384							      host_byte_sex);
5385			    state += sizeof(i386_thread_cthreadstate_t);
5386			    break;
5387#endif /* i386_THREAD_STATE == -1 */
5388			default:
5389			    if(swapped){
5390				Mach_O_error(ofile, "malformed object (unknown "
5391				    "flavor for flavor number %u in %s command"
5392				    " %u can't byte swap it)", nflavor,
5393				    ut->cmd == LC_UNIXTHREAD ? "LC_UNIXTHREAD" :
5394				    "LC_THREAD", i);
5395				goto return_bad;
5396			    }
5397			    state += count * sizeof(uint32_t);
5398			    break;
5399			}
5400			nflavor++;
5401		    }
5402		    break;
5403		}
5404#ifdef x86_THREAD_STATE64_COUNT
5405	    	if(cputype == CPU_TYPE_X86_64){
5406		    x86_thread_state64_t *cpu;
5407
5408		    nflavor = 0;
5409		    p = (char *)ut + ut->cmdsize;
5410		    while(state < p){
5411			if(state +  sizeof(uint32_t) >
5412			   (char *)ut + ut->cmdsize){
5413			    Mach_O_error(ofile, "malformed object (flavor in "
5414				"%s command %u extends past end of command)",
5415				ut->cmd == LC_UNIXTHREAD ?  "LC_UNIXTHREAD" :
5416				"LC_THREAD", i);
5417			    goto return_bad;
5418			}
5419			flavor = *((uint32_t *)state);
5420			if(swapped){
5421			    flavor = SWAP_INT(flavor);
5422			    *((uint32_t *)state) = flavor;
5423			}
5424			state += sizeof(uint32_t);
5425			if(state +  sizeof(uint32_t) >
5426			   (char *)ut + ut->cmdsize){
5427			    Mach_O_error(ofile, "malformed object (count in "
5428				"%s command %u extends past end of command)",
5429				ut->cmd == LC_UNIXTHREAD ?  "LC_UNIXTHREAD" :
5430				"LC_THREAD", i);
5431			    goto return_bad;
5432			}
5433			count = *((uint32_t *)state);
5434			if(swapped){
5435			    count = SWAP_INT(count);
5436			    *((uint32_t *)state) = count;
5437			}
5438			state += sizeof(uint32_t);
5439			switch(flavor){
5440			case x86_THREAD_STATE64:
5441			    if(count != x86_THREAD_STATE64_COUNT){
5442				Mach_O_error(ofile, "malformed object (count "
5443				    "not x86_THREAD_STATE64_COUNT for "
5444				    "flavor number %u which is a x86_THREAD_"
5445				    "STATE64 flavor in %s command %u)",
5446				    nflavor, ut->cmd == LC_UNIXTHREAD ?
5447				    "LC_UNIXTHREAD" : "LC_THREAD", i);
5448				goto return_bad;
5449			    }
5450			    cpu = (x86_thread_state64_t *)state;
5451			    if(state + sizeof(x86_thread_state64_t) >
5452			       (char *)ut + ut->cmdsize){
5453				Mach_O_error(ofile, "malformed object ("
5454				    "x86_THREAD_STATE64 in %s command %u "
5455				    "extends past end of command)", ut->cmd ==
5456				    LC_UNIXTHREAD ?  "LC_UNIXTHREAD" :
5457				    "LC_THREAD", i);
5458				goto return_bad;
5459			    }
5460			    if(swapped)
5461				swap_x86_thread_state64(cpu, host_byte_sex);
5462			    state += sizeof(x86_thread_state64_t);
5463			    break;
5464			default:
5465			    if(swapped){
5466				Mach_O_error(ofile, "malformed object (unknown "
5467				    "flavor for flavor number %u in %s command"
5468				    " %u can't byte swap it)", nflavor,
5469				    ut->cmd == LC_UNIXTHREAD ? "LC_UNIXTHREAD" :
5470				    "LC_THREAD", i);
5471				goto return_bad;
5472			    }
5473			    state += count * sizeof(uint32_t);
5474			    break;
5475			}
5476			nflavor++;
5477		    }
5478		    break;
5479		}
5480#endif /* x86_THREAD_STATE64_COUNT */
5481	    	if(cputype == CPU_TYPE_HPPA){
5482		    struct hp_pa_integer_thread_state *cpu;
5483		    struct hp_pa_frame_thread_state *frame;
5484		    struct hp_pa_fp_thread_state *fpu;
5485
5486		    nflavor = 0;
5487		    p = (char *)ut + ut->cmdsize;
5488		    while(state < p){
5489			if(state +  sizeof(uint32_t) >
5490			   (char *)ut + ut->cmdsize){
5491			    Mach_O_error(ofile, "malformed object (flavor in "
5492				"%s command %u extends past end of command)",
5493				ut->cmd == LC_UNIXTHREAD ?  "LC_UNIXTHREAD" :
5494				"LC_THREAD", i);
5495			    goto return_bad;
5496			}
5497			flavor = *((uint32_t *)state);
5498			if(swapped){
5499			    flavor = SWAP_INT(flavor);
5500			    *((uint32_t *)state) = flavor;
5501			}
5502			state += sizeof(uint32_t);
5503			if(state +  sizeof(uint32_t) >
5504			   (char *)ut + ut->cmdsize){
5505			    Mach_O_error(ofile, "malformed object (count in "
5506				"%s command %u extends past end of command)",
5507				ut->cmd == LC_UNIXTHREAD ?  "LC_UNIXTHREAD" :
5508				"LC_THREAD", i);
5509			    goto return_bad;
5510			}
5511			count = *((uint32_t *)state);
5512			if(swapped){
5513			    count = SWAP_INT(count);
5514			    *((uint32_t *)state) = count;
5515			}
5516			state += sizeof(uint32_t);
5517			switch(flavor){
5518			case HPPA_INTEGER_THREAD_STATE:
5519			    if(count != HPPA_INTEGER_THREAD_STATE_COUNT){
5520				Mach_O_error(ofile, "malformed object (count "
5521				    "not HPPA_INTEGER_THREAD_STATE_COUNT for "
5522				    "flavor number %u which is a "
5523				    "HPPA_INTEGER_THREAD_STATE "
5524				    "flavor in %s command %u)", nflavor,
5525				    ut->cmd == LC_UNIXTHREAD ? "LC_UNIXTHREAD" :
5526				    "LC_THREAD", i);
5527				goto return_bad;
5528			    }
5529			    cpu = (struct hp_pa_integer_thread_state *)state;
5530			    if(state+sizeof(struct hp_pa_integer_thread_state) >
5531			       (char *)ut + ut->cmdsize){
5532				Mach_O_error(ofile, "malformed object ("
5533				    "HPPA_INTEGER_THREAD_STATE in %s command "
5534				    "%u extends past end of command)",
5535				    ut->cmd == LC_UNIXTHREAD ? "LC_UNIXTHREAD" :
5536				    "LC_THREAD", i);
5537				goto return_bad;
5538			    }
5539			    if(swapped)
5540				swap_hppa_integer_thread_state(cpu,
5541							       host_byte_sex);
5542			    state += sizeof(struct hp_pa_integer_thread_state);
5543			    break;
5544			case HPPA_FRAME_THREAD_STATE:
5545			    if(count != HPPA_FRAME_THREAD_STATE_COUNT){
5546				Mach_O_error(ofile, "malformed object (count "
5547				    "not HPPA_FRAME_THREAD_STATE_COUNT for "
5548				    "flavor number %u which is a HPPA_FRAME_"
5549				    "THREAD_STATE flavor in %s command %u)",
5550				    nflavor,
5551				    ut->cmd == LC_UNIXTHREAD ? "LC_UNIXTHREAD" :
5552				    "LC_THREAD", i);
5553				goto return_bad;
5554			    }
5555			    frame = (struct hp_pa_frame_thread_state *)state;
5556			    if(state + sizeof(struct hp_pa_frame_thread_state) >
5557			       (char *)ut + ut->cmdsize){
5558				Mach_O_error(ofile, "malformed object ("
5559				    "HPPA_FRAME_THREAD_STATE in %s command "
5560				    "%u extends past end of command)",
5561				    ut->cmd == LC_UNIXTHREAD ? "LC_UNIXTHREAD" :
5562				    "LC_THREAD", i);
5563				goto return_bad;
5564			    }
5565			    if(swapped)
5566				swap_hppa_frame_thread_state(frame,host_byte_sex);
5567			    state += sizeof(struct hp_pa_frame_thread_state);
5568			    break;
5569			case HPPA_FP_THREAD_STATE:
5570			    if(count != HPPA_FP_THREAD_STATE_COUNT){
5571				Mach_O_error(ofile, "malformed object (count "
5572				    "not HPPA_FP_THREAD_STATE_COUNT for "
5573				    "flavor number %u which is a HPPA_FP_"
5574				    "THREAD_STATE flavor in %s command %u)",
5575				    nflavor,
5576				    ut->cmd == LC_UNIXTHREAD ? "LC_UNIXTHREAD" :
5577				    "LC_THREAD", i);
5578				goto return_bad;
5579			    }
5580			    fpu = (struct hp_pa_fp_thread_state *)state;
5581			    if(state + sizeof(struct hp_pa_fp_thread_state) >
5582			       (char *)ut + ut->cmdsize){
5583				Mach_O_error(ofile, "malformed object ("
5584				    "HPPA_FP_THREAD_STATE in %s command "
5585				    "%u extends past end of command)",
5586				    ut->cmd == LC_UNIXTHREAD ? "LC_UNIXTHREAD" :
5587				    "LC_THREAD", i);
5588				goto return_bad;
5589			    }
5590			    if(swapped)
5591				swap_hppa_fp_thread_state(fpu,host_byte_sex);
5592			    state += sizeof(struct hp_pa_fp_thread_state);
5593			    break;
5594			default:
5595			    if(swapped){
5596				Mach_O_error(ofile, "malformed object (unknown "
5597				    "flavor for flavor number %u in %s command"
5598				    " %u can't byte swap it)", nflavor,
5599				    ut->cmd == LC_UNIXTHREAD ? "LC_UNIXTHREAD" :
5600				    "LC_THREAD", i);
5601				goto return_bad;
5602			    }
5603			    state += count * sizeof(uint32_t);
5604			    break;
5605			}
5606			nflavor++;
5607		    }
5608		    break;
5609		}
5610	    	if(cputype == CPU_TYPE_SPARC){
5611		    struct sparc_thread_state_regs *cpu;
5612		    struct sparc_thread_state_fpu *fpu;
5613
5614		    nflavor = 0;
5615		    p = (char *)ut + ut->cmdsize;
5616		    while(state < p){
5617			if(state +  sizeof(uint32_t) >
5618			   (char *)ut + ut->cmdsize){
5619			    Mach_O_error(ofile, "malformed object (flavor in "
5620				"%s command %u extends past end of command)",
5621				ut->cmd == LC_UNIXTHREAD ?  "LC_UNIXTHREAD" :
5622				"LC_THREAD", i);
5623			    goto return_bad;
5624			}
5625			flavor = *((uint32_t *)state);
5626			if(swapped){
5627			    flavor = SWAP_INT(flavor);
5628			    *((uint32_t *)state) = flavor;
5629			}
5630			state += sizeof(uint32_t);
5631			if(state +  sizeof(uint32_t) >
5632			   (char *)ut + ut->cmdsize){
5633			    Mach_O_error(ofile, "malformed object (count in "
5634				"%s command %u extends past end of command)",
5635				ut->cmd == LC_UNIXTHREAD ?  "LC_UNIXTHREAD" :
5636				"LC_THREAD", i);
5637			    goto return_bad;
5638			}
5639			count = *((uint32_t *)state);
5640			if(swapped){
5641			    count = SWAP_INT(count);
5642			    *((uint32_t *)state) = count;
5643			}
5644			state += sizeof(uint32_t);
5645			switch(flavor){
5646			case SPARC_THREAD_STATE_REGS:
5647			    if(count != SPARC_THREAD_STATE_REGS_COUNT){
5648				Mach_O_error(ofile, "malformed object (count "
5649				    "not SPARC_THREAD_STATE_REGS_COUNT for "
5650				    "flavor number %u which is a SPARC_THREAD_"
5651				    "STATE_REGS flavor in %s command %u)",
5652				    nflavor, ut->cmd == LC_UNIXTHREAD ?
5653				    "LC_UNIXTHREAD" : "LC_THREAD", i);
5654				goto return_bad;
5655			    }
5656			    cpu = (struct sparc_thread_state_regs *)state;
5657			    if(state + sizeof(struct sparc_thread_state_regs) >
5658			       (char *)ut + ut->cmdsize){
5659				Mach_O_error(ofile, "malformed object ("
5660				    "SPARC_THREAD_STATE_REGS in %s command %u "
5661				    "extends past end of command)", ut->cmd ==
5662				    LC_UNIXTHREAD ?  "LC_UNIXTHREAD" :
5663				    "LC_THREAD", i);
5664				goto return_bad;
5665			    }
5666			    if(swapped)
5667				swap_sparc_thread_state_regs(cpu, host_byte_sex);
5668			    state += sizeof(struct sparc_thread_state_regs);
5669			    break;
5670			  case SPARC_THREAD_STATE_FPU:
5671			    if(count != SPARC_THREAD_STATE_FPU_COUNT){
5672				Mach_O_error(ofile, "malformed object (count "
5673				    "not SPARC_THREAD_STATE_FPU_COUNT for "
5674				    "flavor number %u which is a SPARC_THREAD_"
5675				    "STATE_FPU flavor in %s command %u)",
5676				    nflavor, ut->cmd == LC_UNIXTHREAD ?
5677				    "LC_UNIXTHREAD" : "LC_THREAD", i);
5678				goto return_bad;
5679			    }
5680			    fpu = (struct sparc_thread_state_fpu *)state;
5681			    if(state + sizeof(struct sparc_thread_state_fpu) >
5682			       (char *)ut + ut->cmdsize){
5683				Mach_O_error(ofile, "malformed object ("
5684				    "SPARC_THREAD_STATE_FPU in %s command %u "
5685				    "extends past end of command)", ut->cmd ==
5686				    LC_UNIXTHREAD ?  "LC_UNIXTHREAD" :
5687				    "LC_THREAD", i);
5688				goto return_bad;
5689			    }
5690			    if(swapped)
5691				swap_sparc_thread_state_fpu(fpu, host_byte_sex);
5692			    state += sizeof(struct sparc_thread_state_fpu);
5693			    break;
5694			default:
5695			    if(swapped){
5696				Mach_O_error(ofile, "malformed object (unknown "
5697				    "flavor for flavor number %u in %s command"
5698				    " %u can't byte swap it)", nflavor,
5699				    ut->cmd == LC_UNIXTHREAD ? "LC_UNIXTHREAD" :
5700				    "LC_THREAD", i);
5701				goto return_bad;
5702			    }
5703			    state += count * sizeof(uint32_t);
5704			    break;
5705			}
5706			nflavor++;
5707		    }
5708		    break;
5709		}
5710	    	if(cputype == CPU_TYPE_ARM){
5711		    arm_thread_state_t *cpu;
5712
5713		    nflavor = 0;
5714		    p = (char *)ut + ut->cmdsize;
5715		    while(state < p){
5716			if(state +  sizeof(uint32_t) >
5717			   (char *)ut + ut->cmdsize){
5718			    Mach_O_error(ofile, "malformed object (flavor in "
5719				"%s command %u extends past end of command)",
5720				ut->cmd == LC_UNIXTHREAD ?  "LC_UNIXTHREAD" :
5721				"LC_THREAD", i);
5722			    goto return_bad;
5723			}
5724			flavor = *((uint32_t *)state);
5725			if(swapped){
5726			    flavor = SWAP_INT(flavor);
5727			    *((uint32_t *)state) = flavor;
5728			}
5729			state += sizeof(uint32_t);
5730			if(state +  sizeof(uint32_t) >
5731			   (char *)ut + ut->cmdsize){
5732			    Mach_O_error(ofile, "malformed object (count in "
5733				"%s command %u extends past end of command)",
5734				ut->cmd == LC_UNIXTHREAD ?  "LC_UNIXTHREAD" :
5735				"LC_THREAD", i);
5736			    goto return_bad;
5737			}
5738			count = *((uint32_t *)state);
5739			if(swapped){
5740			    count = SWAP_INT(count);
5741			    *((uint32_t *)state) = count;
5742			}
5743			state += sizeof(uint32_t);
5744			switch(flavor){
5745			case ARM_THREAD_STATE:
5746			    if(count != ARM_THREAD_STATE_COUNT){
5747				Mach_O_error(ofile, "malformed object (count "
5748				    "not ARM_THREAD_STATE_COUNT for "
5749				    "flavor number %u which is a ARM_THREAD_"
5750				    "STATE flavor in %s command %u)",
5751				    nflavor, ut->cmd == LC_UNIXTHREAD ?
5752				    "LC_UNIXTHREAD" : "LC_THREAD", i);
5753				goto return_bad;
5754			    }
5755			    cpu = (arm_thread_state_t *)state;
5756			    if(state + sizeof(arm_thread_state_t) >
5757			       (char *)ut + ut->cmdsize){
5758				Mach_O_error(ofile, "malformed object ("
5759				    "ARM_THREAD_STATE in %s command %u "
5760				    "extends past end of command)", ut->cmd ==
5761				    LC_UNIXTHREAD ?  "LC_UNIXTHREAD" :
5762				    "LC_THREAD", i);
5763				goto return_bad;
5764			    }
5765			    if(swapped)
5766				swap_arm_thread_state_t(cpu, host_byte_sex);
5767			    state += sizeof(arm_thread_state_t);
5768			    break;
5769			default:
5770			    if(swapped){
5771				Mach_O_error(ofile, "malformed object (unknown "
5772				    "flavor for flavor number %u in %s command"
5773				    " %u can't byte swap it)", nflavor,
5774				    ut->cmd == LC_UNIXTHREAD ? "LC_UNIXTHREAD" :
5775				    "LC_THREAD", i);
5776				goto return_bad;
5777			    }
5778			    state += count * sizeof(uint32_t);
5779			    break;
5780			}
5781			nflavor++;
5782		    }
5783		    break;
5784		}
5785		if(swapped){
5786		    Mach_O_error(ofile, "malformed object (unknown cputype and "
5787			"cpusubtype of object and can't byte swap and check %s "
5788			"command %u)", ut->cmd == LC_UNIXTHREAD ?
5789			"LC_UNIXTHREAD" : "LC_THREAD", i);
5790		    goto return_bad;
5791		}
5792		break;
5793	    case LC_MAIN:
5794		if(l.cmdsize < sizeof(struct entry_point_command)){
5795		    Mach_O_error(ofile, "malformed object (LC_MAIN cmdsize "
5796			         "too small) in command %u", i);
5797		    goto return_bad;
5798		}
5799		ep = (struct entry_point_command *)lc;
5800		if(swapped)
5801		    swap_entry_point_command(ep, host_byte_sex);
5802		/*
5803		 * If we really wanted we could check that the entryoff field
5804		 * really is an offset into the __TEXT segment.  But since it
5805		 * is not used here, we won't needlessly check it.
5806		 */
5807		break;
5808	    case LC_SOURCE_VERSION:
5809		if(l.cmdsize < sizeof(struct source_version_command)){
5810		    Mach_O_error(ofile, "malformed object (LC_SOURCE_VERSION "
5811				 "cmdsize too small) in command %u", i);
5812		    goto return_bad;
5813		}
5814		sv = (struct source_version_command *)lc;
5815		if(swapped)
5816		    swap_source_version_command(sv, host_byte_sex);
5817	    case LC_IDENT:
5818		if(l.cmdsize < sizeof(struct ident_command)){
5819		    Mach_O_error(ofile, "malformed object (LC_IDENT cmdsize "
5820			         "too small) in command %u", i);
5821		    goto return_bad;
5822		}
5823		id = (struct ident_command *)lc;
5824		if(swapped)
5825		    swap_ident_command(id, host_byte_sex);
5826		/*
5827		 * Note the cmdsize field if the LC_IDENT command was checked
5828		 * as part of checking all load commands cmdsize field before
5829		 * the switch statement on the cmd field of the load command.
5830		 */
5831		break;
5832	    case LC_RPATH:
5833		if(l.cmdsize < sizeof(struct rpath_command)){
5834		    Mach_O_error(ofile, "malformed object (LC_RPATH: cmdsize "
5835			         "too small) in command %u", i);
5836		    goto return_bad;
5837		}
5838		rpath = (struct rpath_command *)lc;
5839		if(swapped)
5840		    swap_rpath_command(rpath, host_byte_sex);
5841		if(rpath->cmdsize < sizeof(struct rpath_command)){
5842		    Mach_O_error(ofile, "malformed object (LC_RPATH command "
5843			"%u has too small cmdsize field)", i);
5844		    goto return_bad;
5845		}
5846		if(rpath->path.offset >= rpath->cmdsize){
5847		    Mach_O_error(ofile, "truncated or malformed object (path."
5848			"offset field of LC_RPATH command %u extends past the "
5849			"end of the file)", i);
5850		    goto return_bad;
5851		}
5852		break;
5853
5854#ifndef OFI
5855	    default:
5856		Mach_O_error(ofile, "malformed object (unknown load command "
5857			     "%u)", i);
5858		goto return_bad;
5859#endif /* !defined(OFI) */
5860	    }
5861
5862	    lc = (struct load_command *)((char *)lc + l.cmdsize);
5863	    /* check that next load command does not extends past the end */
5864	    if((char *)lc > (char *)load_commands + sizeofcmds){
5865		Mach_O_error(ofile, "truncated or malformed object (load "
5866			     "command %u extends past the end of the file)",
5867			     i + 1);
5868		goto return_bad;
5869	    }
5870	}
5871	if(st == NULL){
5872	    if(dyst != NULL){
5873		Mach_O_error(ofile, "truncated or malformed object (contains "
5874		  "LC_DYSYMTAB load command without a LC_SYMTAB load command)");
5875		goto return_bad;
5876	    }
5877	}
5878	else{
5879	    if(dyst != NULL){
5880		if(dyst->nlocalsym != 0 &&
5881		   dyst->ilocalsym > st->nsyms){
5882		    Mach_O_error(ofile, "truncated or malformed object "
5883			"(ilocalsym in LC_DYSYMTAB load command extends past "
5884			"the end of the symbol table)");
5885		    goto return_bad;
5886		}
5887		big_size = dyst->ilocalsym;
5888		big_size += dyst->nlocalsym;
5889		if(dyst->nlocalsym != 0 && big_size > st->nsyms){
5890		    Mach_O_error(ofile, "truncated or malformed object "
5891			"(ilocalsym plus nlocalsym in LC_DYSYMTAB load command "
5892			"extends past the end of the symbol table)");
5893		    goto return_bad;
5894		}
5895
5896		if(dyst->nextdefsym != 0 &&
5897		   dyst->iextdefsym > st->nsyms){
5898		    Mach_O_error(ofile, "truncated or malformed object "
5899			"(iextdefsym in LC_DYSYMTAB load command extends past "
5900			"the end of the symbol table)");
5901		    goto return_bad;
5902		}
5903		big_size = dyst->iextdefsym;
5904		big_size += dyst->nextdefsym;
5905		if(dyst->nextdefsym != 0 && big_size > st->nsyms){
5906		    Mach_O_error(ofile, "truncated or malformed object "
5907			"(iextdefsym plus nextdefsym in LC_DYSYMTAB load "
5908			"command extends past the end of the symbol table)");
5909		    goto return_bad;
5910		}
5911
5912		if(dyst->nundefsym != 0 &&
5913		   dyst->iundefsym > st->nsyms){
5914		    Mach_O_error(ofile, "truncated or malformed object "
5915			"(iundefsym in LC_DYSYMTAB load command extends past "
5916			"the end of the symbol table)");
5917		    goto return_bad;
5918		}
5919		big_size = dyst->iundefsym;
5920		big_size += dyst->nundefsym;
5921		if(dyst->nundefsym != 0 && big_size > st->nsyms){
5922		    Mach_O_error(ofile, "truncated or malformed object "
5923			"(iundefsym plus nundefsym in LC_DYSYMTAB load command "
5924			"extends past the end of the symbol table)");
5925		    goto return_bad;
5926		}
5927		if(rc != NULL){
5928		    if(rc->init_module > dyst->nmodtab){
5929			Mach_O_error(ofile, "malformed object (init_module in "
5930			    "LC_ROUTINES load command extends past the "
5931			    "end of the module table)");
5932			goto return_bad;
5933		    }
5934		}
5935		if(rc64 != NULL){
5936		    if(rc64->init_module > dyst->nmodtab){
5937			Mach_O_error(ofile, "malformed object (init_module in "
5938			    "LC_ROUTINES_64 load command extends past the "
5939			    "end of the module table)");
5940			goto return_bad;
5941		    }
5942		}
5943		if(hints != NULL){
5944		    if(hints->nhints != dyst->nundefsym){
5945			Mach_O_error(ofile, "malformed object (nhints in "
5946			    "LC_TWOLEVEL_HINTS load command not the same as "
5947			    "nundefsym in LC_DYSYMTAB load command)");
5948			goto return_bad;
5949		    }
5950		}
5951	    }
5952	}
5953	/* check for an inconsistent size of the load commands */
5954	if((char *)load_commands + sizeofcmds != (char *)lc){
5955	    Mach_O_error(ofile, "malformed object (inconsistent sizeofcmds "
5956			 "field in mach header)");
5957	    goto return_bad;
5958	}
5959
5960	/*
5961	 * Mark this ofile so we know its headers have been swapped.  We do this
5962	 * in case we don't process it the first time so we can swap them back
5963	 * in case we loop back to it in a fat file to process it later.
5964	 */
5965	if(swapped == TRUE)
5966	    ofile->headers_swapped = TRUE;
5967
5968	/* looks good return ok */
5969	free_elements(&elements);
5970	return(CHECK_GOOD);
5971
5972return_bad:
5973	free_elements(&elements);
5974	return(CHECK_BAD);
5975#endif /* OTOOL */
5976}
5977
5978/*
5979 * swap_back_Mach_O() is called after the ofile has been processed to swap back
5980 * the mach header and load commands if check_Mach_O() above swapped them.
5981 */
5982static
5983void
5984swap_back_Mach_O(
5985struct ofile *ofile)
5986{
5987	if(ofile->headers_swapped == TRUE){
5988	    ofile->headers_swapped = FALSE;
5989	    if(ofile->mh != NULL)
5990		swap_object_headers(ofile->mh, ofile->load_commands);
5991	    else if(ofile->mh64 != NULL)
5992		swap_object_headers(ofile->mh64, ofile->load_commands);
5993	}
5994}
5995
5996#ifndef OTOOL
5997/*
5998 * check_overlaping_element() checks that the element in the ofile described by
5999 * offset, size and name does not overlap in list of elements in head.  If it
6000 * does CHECK_BAD is returned and an error message is generated.  If it doesn't
6001 * then an element is added in the ordered list and CHECK_GOOD is returned
6002 */
6003static
6004enum check_type
6005check_overlaping_element(
6006struct ofile *ofile,
6007struct element *head,
6008uint32_t offset,
6009uint32_t size,
6010char *name)
6011{
6012    struct element *e, *p, *n;
6013
6014	if(size == 0)
6015	    return(CHECK_GOOD);
6016
6017	if(head->next == NULL){
6018	    n = allocate(sizeof(struct element));
6019	    n->offset = offset;
6020	    n->size = size;
6021	    n->name = name;
6022	    n->next = NULL;
6023	    head->next = n;
6024	    return(CHECK_GOOD);
6025	}
6026
6027	p = NULL;
6028	e = head;
6029	while(e->next != NULL){
6030	    p = e;
6031	    e = e->next;
6032	    if((offset >= e->offset &&
6033		offset < e->offset + e->size) ||
6034	       (offset + size > e->offset &&
6035		offset + size < e->offset + e->size) ||
6036	       (offset <= e->offset &&
6037		offset + size >= e->offset + e->size)){
6038		Mach_O_error(ofile, "malformed object (%s at offset %u with a "
6039		    "size of %u, overlaps %s at offset %u with a size of %u)",
6040		    name, offset, size, e->name, e->offset, e->size);
6041		return(CHECK_BAD);
6042	    }
6043	    if(e->next != NULL && offset + size <= e->next->offset){
6044		n = allocate(sizeof(struct element));
6045		n->offset = offset;
6046		n->size = size;
6047		n->name = name;
6048		n->next = e;
6049		p->next = n;
6050		return(CHECK_GOOD);
6051	    }
6052	}
6053	n = allocate(sizeof(struct element));
6054	n->offset = offset;
6055	n->size = size;
6056	n->name = name;
6057	n->next = NULL;
6058	e->next = n;
6059	return(CHECK_GOOD);
6060}
6061
6062/*
6063 * free_elements() frees the list of elements on the list head.
6064 */
6065static
6066void
6067free_elements(
6068struct element *head)
6069{
6070    struct element *e, *e_next;
6071
6072	e = head->next;
6073	while(e != NULL){
6074	    e_next = e->next;
6075	    free(e);
6076	    e = e_next;
6077	}
6078}
6079#endif /* !defined(OTOOL) */
6080
6081/*
6082 * check_dylib_module() checks the object file's dylib_module as referenced
6083 * by the dylib_module field in the ofile for correctness.
6084 */
6085static
6086enum check_type
6087check_dylib_module(
6088struct ofile *ofile,
6089struct symtab_command *st,
6090struct dysymtab_command *dyst,
6091char *strings,
6092uint32_t module_index)
6093{
6094#ifdef OTOOL
6095	return(CHECK_GOOD);
6096#else /* !defined OTOOL */
6097    uint32_t i;
6098    enum byte_sex host_byte_sex;
6099    enum bool swapped;
6100    struct dylib_module m;
6101    struct dylib_module_64 m64;
6102    uint32_t module_name, nextdefsym, iextdefsym, nlocalsym, ilocalsym, nrefsym;
6103    uint32_t irefsym, nextrel, iextrel;
6104
6105	host_byte_sex = get_host_byte_sex();
6106	swapped = (enum bool)(host_byte_sex != ofile->object_byte_sex);
6107	if(ofile->mh != NULL){
6108	    m = *ofile->dylib_module;
6109	    if(swapped)
6110		swap_dylib_module(&m, 1, host_byte_sex);
6111	    module_name = m.module_name;
6112	    nextdefsym = m.nextdefsym;
6113	    iextdefsym = m.iextdefsym;
6114	    nlocalsym = m.nlocalsym;
6115	    ilocalsym = m.ilocalsym;
6116	    nrefsym = m.nrefsym;
6117	    irefsym = m.irefsym;
6118	    nextrel = m.nextrel;
6119	    iextrel = m.iextrel;
6120	}
6121	else{
6122	    m64 = *ofile->dylib_module64;
6123	    if(swapped)
6124		swap_dylib_module_64(&m64, 1, host_byte_sex);
6125	    module_name = m64.module_name;
6126	    nextdefsym = m64.nextdefsym;
6127	    iextdefsym = m64.iextdefsym;
6128	    nlocalsym = m64.nlocalsym;
6129	    ilocalsym = m64.ilocalsym;
6130	    nrefsym = m64.nrefsym;
6131	    irefsym = m64.irefsym;
6132	    nextrel = m64.nextrel;
6133	    iextrel = m64.iextrel;
6134	}
6135
6136	if(module_name > st->strsize){
6137	    Mach_O_error(ofile, "truncated or malformed object (module_name "
6138		"of module table entry %u past the end of the string table)",
6139		module_index);
6140	    return(CHECK_BAD);
6141	}
6142	for(i = module_name; i < st->strsize && strings[i] != '\0'; i++)
6143		;
6144	if(i >= st->strsize){
6145	    Mach_O_error(ofile, "truncated or malformed object (module_name "
6146		"of module table entry %u extends past the end of the string "
6147		"table)", module_index);
6148	    return(CHECK_BAD);
6149	}
6150
6151	if(nextdefsym != 0){
6152	    if(iextdefsym > st->nsyms){
6153		Mach_O_error(ofile, "truncated or malformed object (iextdefsym "
6154		    "field of module table entry %u past the end of the "
6155		    "symbol table", module_index);
6156		return(CHECK_BAD);
6157	    }
6158	    if(iextdefsym + nextdefsym > st->nsyms){
6159		Mach_O_error(ofile, "truncated or malformed object (iextdefsym "
6160		    "field of module table entry %u plus nextdefsym field "
6161		    "extends past the end of the symbol table", module_index);
6162		return(CHECK_BAD);
6163	    }
6164	}
6165	if(nlocalsym != 0){
6166	    if(ilocalsym > st->nsyms){
6167		Mach_O_error(ofile, "truncated or malformed object (ilocalsym "
6168		    "field of module table entry %u past the end of the "
6169		    "symbol table", module_index);
6170		return(CHECK_BAD);
6171	    }
6172	    if(ilocalsym + nlocalsym > st->nsyms){
6173		Mach_O_error(ofile, "truncated or malformed object (ilocalsym "
6174		    "field of module table entry %u plus nlocalsym field "
6175		    "extends past the end of the symbol table", module_index);
6176		return(CHECK_BAD);
6177	    }
6178	}
6179	if(nrefsym != 0){
6180	    if(irefsym > dyst->nextrefsyms){
6181		Mach_O_error(ofile, "truncated or malformed object (irefsym "
6182		    "field of module table entry %u past the end of the "
6183		    "reference table", module_index);
6184		return(CHECK_BAD);
6185	    }
6186	    if(irefsym + nrefsym > dyst->nextrefsyms){
6187		Mach_O_error(ofile, "truncated or malformed object (irefsym "
6188		    "field of module table entry %u plus nrefsym field "
6189		    "extends past the end of the reference table",module_index);
6190		return(CHECK_BAD);
6191	    }
6192	}
6193	if(nextrel != 0){
6194	    if(iextrel > dyst->extreloff){
6195		Mach_O_error(ofile, "truncated or malformed object (iextrel "
6196		    "field of module table entry %u past the end of the "
6197		    "external relocation enrties", module_index);
6198		return(CHECK_BAD);
6199	    }
6200	    if(iextrel + nextrel > dyst->extreloff){
6201		Mach_O_error(ofile, "truncated or malformed object (iextrel "
6202		    "field of module table entry %u plus nextrel field "
6203		    "extends past the end of the external relocation enrties",
6204		    module_index);
6205		return(CHECK_BAD);
6206	    }
6207	}
6208	return(CHECK_GOOD);
6209#endif /* OTOOL */
6210}
6211
6212__private_extern__
6213uint32_t
6214size_ar_name(
6215const struct ar_hdr *ar_hdr)
6216{
6217    int32_t i;
6218
6219	i = sizeof(ar_hdr->ar_name) - 1;
6220	if(ar_hdr->ar_name[i] == ' '){
6221	    do{
6222		if(ar_hdr->ar_name[i] != ' ')
6223		    break;
6224		i--;
6225	    }while(i > 0);
6226	}
6227	return(i + 1);
6228}
6229#endif /* !defined(RLD) */
6230