2 * Copyright © 2009 Apple Inc. All rights reserved.
4 * @APPLE_LICENSE_HEADER_START@
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions are met:
9 * 1. Redistributions of source code must retain the above copyright notice,
10 * this list of conditions and the following disclaimer.
11 * 2. Redistributions in binary form must reproduce the above copyright notice,
12 * this list of conditions and the following disclaimer in the documentation
13 * and/or other materials provided with the distribution.
14 * 3. Neither the name of Apple Inc. ("Apple") nor the names of its
15 * contributors may be used to endorse or promote products derived from this
16 * software without specific prior written permission.
18 * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY
19 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
20 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
21 * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY
22 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
23 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
24 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
25 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
26 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
27 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
29 * @APPLE_LICENSE_HEADER_END@
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
40 #include <mach/mach.h>
41 #include "stuff/openstep_mach.h"
49 #include <sys/types.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"
68 #include <mach-o/dyld.h>
70 #include "stuff/lto.h"
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"
81 #undef ALIGNMENT_CHECKS
83 #include "ofile_print.h"
84 static enum bool otool_first_ofile_map
= TRUE
;
85 #else /* !define(OTOOL) */
87 #if (!defined(m68k) && !defined(__i386__) && !defined(__x86_64__) && !defined(__ppc__) && !defined(__arm__))
88 #define ALIGNMENT_CHECKS_ARCHIVE_64_BIT
89 static enum bool archive_64_bit_align_warning
= FALSE
;
90 #endif /* (!defined(m68k) && !defined(__i386__) && !defined(__x86_64__) && !defined(__ppc__) && !defined(__arm__)) */
95 /* The maximum section alignment allowed to be specified, as a power of two */
96 #define MAXSECTALIGN 15 /* 2**15 or 0x8000 */
108 struct element
*next
;
110 #endif /* !defined(OTOOL) */
112 static enum bool ofile_specific_arch(
115 static enum check_type
check_fat(
116 struct ofile
*ofile
);
117 static enum check_type
check_fat_object_in_archive(
118 struct ofile
*ofile
);
119 static enum check_type
check_archive(
121 enum bool archives_with_fat_objects
);
122 static enum check_type
check_extend_format_1(
124 struct ar_hdr
*ar_hdr
,
126 uint32_t *member_name_size
);
127 static enum check_type
check_archive_toc(
128 struct ofile
*ofile
);
129 static enum check_type
check_Mach_O(
130 struct ofile
*ofile
);
131 static void swap_back_Mach_O(
132 struct ofile
*ofile
);
134 static enum check_type
check_overlaping_element(
136 struct element
*head
,
140 static void free_elements(
141 struct element
*head
);
142 #endif /* !defined(OTOOL) */
143 static enum check_type
check_dylib_module(
145 struct symtab_command
*st
,
146 struct dysymtab_command
*dyst
,
148 uint32_t module_index
);
151 #if defined(ALIGNMENT_CHECKS) || defined(ALIGNMENT_CHECKS_ARCHIVE_64_BIT)
154 temporary_archive_member_warning(
156 const char *format
, ...)
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
);
167 print("%s: archive member: %s(%.*s) ", progname
, ofile
->file_name
,
168 (int)ofile
->member_name_size
, ofile
->member_name
);
174 #endif /* defined(ALIGNMENT_CHECKS) */
175 #endif /* !defined(OTOOL) */
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.
195 struct arch_flag
*arch_flags
,
196 uint32_t narch_flags
,
198 enum bool process_non_objects
,
199 enum bool dylib_flat
,
200 enum bool use_member_syntax
,
201 void (*processor
)(struct ofile
*ofile
, char *arch_name
, void *cookie
),
204 char *member_name
, *p
, *arch_name
;
207 enum bool flag
, hostflag
, arch_found
, family
;
208 struct arch_flag host_arch_flag
;
209 const struct arch_flag
*family_arch_flag
;
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
218 if(use_member_syntax
== TRUE
){
220 if(len
>= 4 && name
[len
-1] == ')'){
221 p
= strrchr(name
, '(');
222 if(p
!= NULL
&& p
!= name
){
231 otool_first_ofile_map
= TRUE
;
233 if(ofile_map(name
, NULL
, NULL
, &ofile
, FALSE
) == FALSE
)
236 otool_first_ofile_map
= FALSE
;
239 if(ofile
.file_type
== OFILE_FAT
){
241 * This is a fat file so see if a list of architecture is
242 * specified and process only those.
244 if(all_archs
== FALSE
&& narch_flags
!= 0){
245 for(i
= 0; i
< narch_flags
; i
++){
246 if(ofile_first_arch(&ofile
) == FALSE
){
253 get_arch_family_from_cputype(arch_flags
[i
].cputype
);
254 if(family_arch_flag
!= NULL
)
256 ((family_arch_flag
->cpusubtype
& ~CPU_SUBTYPE_MASK
) ==
257 (arch_flags
[i
].cpusubtype
& ~CPU_SUBTYPE_MASK
));
259 arch_name
= ofile
.arch_flag
.name
;
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
) ||
269 if(ofile
.arch_type
== OFILE_ARCHIVE
){
270 if(member_name
!= NULL
){
271 if(ofile_specific_member(member_name
,
273 processor(&ofile
, arch_name
, cookie
);
274 if(ofile
.headers_swapped
== TRUE
)
275 swap_back_Mach_O(&ofile
);
279 /* loop through archive */
281 printf("Archive : %s", ofile
.file_name
);
282 if(arch_name
!= NULL
)
283 printf(" (architecture %s)",
287 if(ofile_first_member(&ofile
) == TRUE
){
290 if(process_non_objects
== TRUE
||
293 processor(&ofile
, arch_name
,
295 if(ofile
.headers_swapped
==TRUE
)
296 swap_back_Mach_O(&ofile
);
299 }while(ofile_next_member(&ofile
) ==
302 error("for architecture: %s "
303 "archive: %s contains no "
304 "members that are object "
305 "files", ofile
.arch_flag
.name
,
310 error("for architecture: %s archive: "
311 "%s contains no members",
312 ofile
.arch_flag
.name
,
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
);
328 if(member_name
!= NULL
){
329 if(ofile_specific_module(
330 member_name
, &ofile
) == TRUE
){
331 processor(&ofile
, arch_name
,
333 if(ofile
.headers_swapped
==TRUE
)
334 swap_back_Mach_O(&ofile
);
338 /*loop through the dynamic library*/
339 if(ofile_first_module(&ofile
)){
341 processor(&ofile
, arch_name
,
343 }while(ofile_next_module(
347 processor(&ofile
, arch_name
,
352 if(ofile
.headers_swapped
== TRUE
)
353 swap_back_Mach_O(&ofile
);
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
,
364 processor(&ofile
, arch_name
, cookie
);
365 if(ofile
.headers_swapped
== TRUE
)
366 swap_back_Mach_O(&ofile
);
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
);
375 if(ofile
.headers_swapped
== TRUE
)
376 swap_back_Mach_O(&ofile
);
380 if(ofile
.headers_swapped
== TRUE
)
381 swap_back_Mach_O(&ofile
);
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
);
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
398 if(all_archs
== FALSE
){
399 (void)get_arch_from_host(&host_arch_flag
, NULL
);
402 * If runing as a 64-bit binary and on an Intel x86 host
405 if(host_arch_flag
.cputype
== CPU_TYPE_I386
)
407 *get_arch_family_from_cputype(CPU_TYPE_X86_64
);
408 #endif /* __LP64__ */
413 get_arch_family_from_cputype(host_arch_flag
.cputype
);
414 if(family_arch_flag
!= NULL
)
416 ((family_arch_flag
->cpusubtype
& ~CPU_SUBTYPE_MASK
) ==
417 (host_arch_flag
.cpusubtype
& ~CPU_SUBTYPE_MASK
));
420 if(ofile_map(name
, NULL
, NULL
, &ofile
, FALSE
) == FALSE
)
422 if(ofile_first_arch(&ofile
) == FALSE
){
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
) ||
433 if(ofile
.arch_type
== OFILE_ARCHIVE
){
434 if(member_name
!= NULL
){
435 if(ofile_specific_member(member_name
,
437 processor(&ofile
, NULL
, cookie
);
438 if(ofile
.headers_swapped
== TRUE
)
439 swap_back_Mach_O(&ofile
);
443 /* loop through archive */
445 printf("Archive : %s\n", ofile
.file_name
);
447 if(ofile_first_member(&ofile
) == TRUE
){
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
);
457 }while(ofile_next_member(&ofile
) ==
460 error("archive: %s contains no "
461 "members that are object "
462 "files", ofile
.file_name
);
466 error("archive: %s contains no "
467 "members", ofile
.file_name
);
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
);
480 if(member_name
!= NULL
){
481 if(ofile_specific_module(member_name
,
483 processor(&ofile
, NULL
, cookie
);
486 /* loop through the dynamic library */
487 if(ofile_first_module(&ofile
) == TRUE
){
489 processor(&ofile
, NULL
, cookie
);
490 }while(ofile_next_module(&ofile
));
493 processor(&ofile
, NULL
, cookie
);
497 if(ofile
.headers_swapped
== TRUE
)
498 swap_back_Mach_O(&ofile
);
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
,
508 processor(&ofile
, NULL
, cookie
);
509 if(ofile
.headers_swapped
== TRUE
)
510 swap_back_Mach_O(&ofile
);
514 else if(ofile
.arch_type
== OFILE_UNKNOWN
){
515 error("file: %s is not an object file",
520 if(ofile
.headers_swapped
== TRUE
)
521 swap_back_Mach_O(&ofile
);
523 }while(hostflag
== FALSE
&& ofile_next_arch(&ofile
) == TRUE
);
524 if(hostflag
== TRUE
){
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
536 if(ofile_map(name
, NULL
, NULL
, &ofile
, FALSE
) == FALSE
)
538 if(ofile_first_arch(&ofile
) == FALSE
){
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
);
549 /* loop through archive */
551 printf("Archive : %s (architecture %s)\n",
552 ofile
.file_name
, ofile
.arch_flag
.name
);
554 if(ofile_first_member(&ofile
) == TRUE
){
557 if(process_non_objects
== TRUE
||
558 ofile
.member_type
== OFILE_Mach_O
){
559 processor(&ofile
, ofile
.arch_flag
.name
,
563 }while(ofile_next_member(&ofile
) == TRUE
);
565 error("for architecture: %s archive: %s "
566 "contains no members that are object "
567 "files", ofile
.arch_flag
.name
,
572 error("for architecture: %s archive: %s "
573 "contains no members",
574 ofile
.arch_flag
.name
, ofile
.file_name
);
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
);
587 if(member_name
!= NULL
){
588 if(ofile_specific_module(member_name
, &ofile
)
590 processor(&ofile
, ofile
.arch_flag
.name
,
594 /* loop through the dynamic library */
595 if(ofile_first_module(&ofile
) == TRUE
){
597 processor(&ofile
, ofile
.arch_flag
.name
,
599 }while(ofile_next_module(&ofile
) == TRUE
);
602 processor(&ofile
, ofile
.arch_flag
.name
,
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
,
615 processor(&ofile
, ofile
.arch_flag
.name
, cookie
);
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
,
623 }while(ofile_next_arch(&ofile
) == TRUE
);
625 else if(ofile
.file_type
== OFILE_ARCHIVE
){
626 if(narch_flags
!= 0){
628 for(i
= 0; i
< narch_flags
; i
++){
630 if(narch_flags
== 1){
632 get_arch_family_from_cputype(arch_flags
[0].cputype
);
633 if(family_arch_flag
!= NULL
)
635 ((family_arch_flag
->cpusubtype
&
636 ~CPU_SUBTYPE_MASK
) ==
637 (arch_flags
[0].cpusubtype
&
640 if(ofile
.archive_cputype
== arch_flags
[i
].cputype
&&
641 ((ofile
.archive_cpusubtype
& ~CPU_SUBTYPE_MASK
) ==
642 (arch_flags
[i
].cpusubtype
& ~CPU_SUBTYPE_MASK
) ||
647 error("file: %s does not contain architecture: %s",
648 ofile
.file_name
, arch_flags
[i
].name
);
651 if(arch_found
== FALSE
){
656 if(member_name
!= NULL
){
657 if(ofile_specific_member(member_name
, &ofile
) == TRUE
)
658 processor(&ofile
, NULL
, cookie
);
661 /* loop through archive */
663 printf("Archive : %s\n", ofile
.file_name
);
665 if(ofile_first_member(&ofile
) == TRUE
){
668 if(process_non_objects
== TRUE
||
669 ofile
.member_type
== OFILE_Mach_O
){
670 processor(&ofile
, NULL
, cookie
);
673 }while(ofile_next_member(&ofile
) == TRUE
);
675 error("archive: %s contains no members that are "
676 "object files", ofile
.file_name
);
680 error("archive: %s contains no members",
685 else if(ofile
.file_type
== OFILE_Mach_O
){
686 if(narch_flags
!= 0){
688 for(i
= 0; i
< narch_flags
; i
++){
690 if(narch_flags
== 1){
692 get_arch_family_from_cputype(arch_flags
[0].cputype
);
693 if(family_arch_flag
!= NULL
)
695 ((family_arch_flag
->cpusubtype
&
696 ~CPU_SUBTYPE_MASK
) ==
697 (arch_flags
[0].cpusubtype
&
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
) ||
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
) ||
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
) ||
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
) ||
740 if(ofile
.mh_cputype
== arch_flags
[i
].cputype
&&
741 ((ofile
.mh_cpusubtype
& ~CPU_SUBTYPE_MASK
) ==
742 (arch_flags
[i
].cpusubtype
& ~CPU_SUBTYPE_MASK
) ||
747 error("file: %s does not contain architecture: %s",
748 ofile
.file_name
, arch_flags
[i
].name
);
751 if(arch_found
== FALSE
){
756 if(ofile
.mh_filetype
== MH_DYLIB
||
757 ofile
.mh_filetype
== MH_DYLIB_STUB
){
758 if(dylib_flat
== TRUE
){
759 processor(&ofile
, NULL
, cookie
);
762 if(member_name
!= NULL
){
763 if(ofile_specific_module(member_name
, &ofile
) == TRUE
)
764 processor(&ofile
, NULL
, cookie
);
767 /* loop through the dynamic library */
768 if(ofile_first_module(&ofile
) == TRUE
){
770 processor(&ofile
, NULL
, cookie
);
771 }while(ofile_next_module(&ofile
) == TRUE
);
774 processor(&ofile
, NULL
, cookie
);
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
);
784 processor(&ofile
, NULL
, cookie
);
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
,
794 error("file: %s is not an object file", name
);
798 #endif /* !defined(OFI) */
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.
822 NSObjectFileImageReturnCode
827 const char *file_name
,
828 const struct arch_flag
*arch_flag
, /* can be NULL */
829 const char *object_name
, /* can be NULL */
831 enum bool archives_with_fat_objects
)
834 struct stat stat_buf
;
835 uint32_t size
, magic
;
838 magic
= 0; /* to shut up the compiler warning message */
839 memset(ofile
, '\0', sizeof(struct ofile
));
841 /* Open the file and map it in */
842 if((fd
= open(file_name
, O_RDONLY
)) == -1){
844 return(NSObjectFileImageAccess
);
846 system_error("can't open file: %s", file_name
);
850 if(fstat(fd
, &stat_buf
) == -1){
853 return(NSObjectFileImageAccess
);
855 system_error("can't stat file: %s", file_name
);
859 size
= stat_buf
.st_size
;
863 addr
= mmap(0, size
, PROT_READ
|PROT_WRITE
, MAP_FILE
|MAP_PRIVATE
, fd
,
865 if((intptr_t)addr
== -1){
866 system_error("can't map file: %s", file_name
);
873 if(otool_first_ofile_map
&& Wflag
)
874 printf("Modification time = %ld\n", (long int)stat_buf
.st_mtime
);
877 return(ofile_map_from_memory(addr
, size
, file_name
, stat_buf
.st_mtime
,
878 arch_flag
, object_name
, ofile
, archives_with_fat_objects
));
882 * ofile_map_from_memory() is the guts of ofile_map() but with an interface
883 * to pass the address and size of the file already mapped in.
887 NSObjectFileImageReturnCode
891 ofile_map_from_memory(
894 const char *file_name
,
896 const struct arch_flag
*arch_flag
, /* can be NULL */
897 const char *object_name
, /* can be NULL */
899 enum bool archives_with_fat_objects
)
903 enum byte_sex host_byte_sex
;
904 struct arch_flag host_arch_flag
;
906 const struct arch_flag
*family_arch_flag
;
909 uint32_t small_nfat_arch
;
912 /* fill in the start of the ofile structure */
913 ofile
->file_name
= savestr(file_name
);
914 if(ofile
->file_name
== NULL
)
916 ofile
->file_addr
= addr
;
917 ofile
->file_size
= size
;
918 ofile
->file_mtime
= mtime
;
920 /* Try to figure out what kind of file this is */
922 if(size
>= sizeof(uint32_t)){
923 magic
= *((uint32_t *)addr
);
925 host_byte_sex
= get_host_byte_sex();
927 /* see if this file is a fat file (always in big endian byte sex) */
928 #ifdef __BIG_ENDIAN__
929 if(size
>= sizeof(struct fat_header
) && magic
== FAT_MAGIC
)
930 #endif /* __BIG_ENDIAN__ */
931 #ifdef __LITTLE_ENDIAN__
932 if(size
>= sizeof(struct fat_header
) && SWAP_INT(magic
) == FAT_MAGIC
)
933 #endif /* __LITTLE_ENDIAN__ */
935 ofile
->file_type
= OFILE_FAT
;
936 ofile
->fat_header
= (struct fat_header
*)addr
;
937 #ifdef __LITTLE_ENDIAN__
938 swap_fat_header(ofile
->fat_header
, host_byte_sex
);
939 #endif /* __LITTLE_ENDIAN__ */
941 if(otool_first_ofile_map
&& fflag
)
942 printf("Fat headers\n");
944 big_size
= ofile
->fat_header
->nfat_arch
;
945 big_size
*= sizeof(struct fat_arch
);
946 big_size
+= sizeof(struct fat_header
);
949 error("fat file: %s truncated or malformed (fat_arch structs "
950 "would extend past the end of the file)", file_name
);
951 ofile
->fat_archs
= allocate(size
- sizeof(struct fat_header
));
952 memset(ofile
->fat_archs
, '\0',
953 size
- sizeof(struct fat_header
));
954 memcpy(ofile
->fat_archs
,
955 addr
+ sizeof(struct fat_header
),
956 size
- sizeof(struct fat_header
));
957 small_nfat_arch
= (size
- sizeof(struct fat_header
)) /
958 sizeof(struct fat_arch
);
959 #ifdef __LITTLE_ENDIAN__
960 swap_fat_arch(ofile
->fat_archs
, small_nfat_arch
,
962 #endif /* __LITTLE_ENDIAN__ */
963 if(otool_first_ofile_map
&& fflag
)
964 print_fat_headers(ofile
->fat_header
, ofile
->fat_archs
,
966 free(ofile
->fat_archs
);
969 #else /* !defined(OTOOL) */
973 ofile
->fat_archs
= (struct fat_arch
*)(addr
+
974 sizeof(struct fat_header
));
975 #ifdef __LITTLE_ENDIAN__
976 swap_fat_arch(ofile
->fat_archs
, ofile
->fat_header
->nfat_arch
,
978 #endif /* __LITTLE_ENDIAN__ */
980 if(otool_first_ofile_map
&& fflag
)
981 print_fat_headers(ofile
->fat_header
, ofile
->fat_archs
,
984 if(check_fat(ofile
) == CHECK_BAD
){
987 return(NSObjectFileImageFormat
);
993 * Now that the fat file is mapped fill in the ofile to the level
994 * the caller wants based on the arch_flag and object_name passed.
995 * If the caller did not specify an arch_flag or an object_name
996 * then everything the caller wants is done.
998 if(arch_flag
== NULL
&& object_name
== NULL
)
1000 if(arch_flag
== NULL
){
1001 if(get_arch_from_host(&host_arch_flag
, NULL
) == 0){
1002 error("can't determine the host architecture (specify an "
1003 "arch_flag or fix get_arch_from_host() )");
1006 ofile
->arch_flag
.name
= savestr(host_arch_flag
.name
);
1007 if(ofile
->arch_flag
.name
== NULL
)
1009 ofile
->arch_flag
.cputype
= host_arch_flag
.cputype
;
1010 ofile
->arch_flag
.cpusubtype
= host_arch_flag
.cpusubtype
;
1013 ofile
->arch_flag
.name
= savestr(arch_flag
->name
);
1014 if(ofile
->arch_flag
.name
== NULL
)
1016 ofile
->arch_flag
.cputype
= arch_flag
->cputype
;
1017 ofile
->arch_flag
.cpusubtype
= arch_flag
->cpusubtype
;
1020 ofile
->narch
= UINT_MAX
;
1021 for(i
= 0; i
< ofile
->fat_header
->nfat_arch
; i
++){
1022 if(ofile
->fat_archs
[i
].cputype
==
1023 ofile
->arch_flag
.cputype
&&
1024 (ofile
->fat_archs
[i
].cpusubtype
& ~CPU_SUBTYPE_MASK
) ==
1025 (ofile
->arch_flag
.cpusubtype
& ~CPU_SUBTYPE_MASK
)){
1030 if(ofile
->narch
== UINT_MAX
){
1033 get_arch_family_from_cputype(ofile
->arch_flag
.cputype
);
1034 if(family_arch_flag
!= NULL
)
1035 family
= (enum bool)
1036 ((family_arch_flag
->cpusubtype
& ~CPU_SUBTYPE_MASK
) ==
1037 (ofile
->arch_flag
.cpusubtype
& ~CPU_SUBTYPE_MASK
));
1038 ofile
->narch
= UINT_MAX
;
1039 for(i
= 0; i
< ofile
->fat_header
->nfat_arch
; i
++){
1040 if(ofile
->fat_archs
[i
].cputype
==
1041 ofile
->arch_flag
.cputype
&&
1043 (ofile
->fat_archs
[i
].cpusubtype
& ~CPU_SUBTYPE_MASK
) ==
1044 (ofile
->arch_flag
.cpusubtype
& ~CPU_SUBTYPE_MASK
))){
1045 ofile
->arch_flag
.cpusubtype
=
1046 ofile
->fat_archs
[i
].cpusubtype
;
1052 if(ofile
->narch
== UINT_MAX
){
1055 return(NSObjectFileImageArch
);
1057 error("fat file: %s does not contain architecture %s",
1058 ofile
->file_name
, arch_flag
->name
);
1063 /* Now determine the file type for this specific architecture */
1064 size
= ofile
->fat_archs
[i
].size
;
1065 addr
= addr
+ ofile
->fat_archs
[i
].offset
;
1066 if(size
>= sizeof(struct mach_header
))
1067 memcpy(&magic
, addr
, sizeof(uint32_t));
1068 /* see if this file is a 32-bit Mach-O file */
1069 if(size
>= sizeof(struct mach_header
) &&
1070 (magic
== MH_MAGIC
||
1071 magic
== SWAP_INT(MH_MAGIC
))){
1072 #ifdef ALIGNMENT_CHECKS
1073 if(ofile
->fat_archs
[i
].offset
% 4 != 0){
1074 error("fat file: %s architecture %s malformed for a 32-bit "
1075 "object file (offset is not a multiple of 4)",
1076 ofile
->file_name
, arch_flag
->name
);
1079 return(NSObjectFileImageFormat
);
1084 #endif /* ALIGNMENT_CHECKS */
1085 ofile
->arch_type
= OFILE_Mach_O
;
1086 ofile
->object_addr
= addr
;
1087 ofile
->object_size
= size
;
1088 if(magic
== MH_MAGIC
)
1089 ofile
->object_byte_sex
= host_byte_sex
;
1091 ofile
->object_byte_sex
=
1092 host_byte_sex
== BIG_ENDIAN_BYTE_SEX
?
1093 LITTLE_ENDIAN_BYTE_SEX
: BIG_ENDIAN_BYTE_SEX
;
1094 ofile
->mh
= (struct mach_header
*)addr
;
1095 ofile
->load_commands
= (struct load_command
*)(addr
+
1096 sizeof(struct mach_header
));
1097 if(check_Mach_O(ofile
) == CHECK_BAD
){
1100 return(NSObjectFileImageFormat
);
1105 if(object_name
!= NULL
){
1106 error("fat file: %s architecture %s is not an archive "
1107 "(object_name to ofile_map() can't be specified to "
1108 "be other than NULL)", ofile
->file_name
,
1113 /* see if this file is a 64-bit Mach-O file */
1114 else if(size
>= sizeof(struct mach_header_64
) &&
1115 (magic
== MH_MAGIC_64
||
1116 magic
== SWAP_INT(MH_MAGIC_64
))){
1117 #ifdef ALIGNMENT_CHECKS
1118 if(ofile
->fat_archs
[i
].offset
% 8 != 0){
1119 error("fat file: %s architecture %s malformed for a 64-bit "
1120 "object file (offset is not a multiple of 8)",
1121 ofile
->file_name
, arch_flag
->name
);
1124 return(NSObjectFileImageFormat
);
1129 #endif /* ALIGNMENT_CHECKS */
1130 ofile
->arch_type
= OFILE_Mach_O
;
1131 ofile
->object_addr
= addr
;
1132 ofile
->object_size
= size
;
1133 if(magic
== MH_MAGIC_64
)
1134 ofile
->object_byte_sex
= host_byte_sex
;
1136 ofile
->object_byte_sex
=
1137 host_byte_sex
== BIG_ENDIAN_BYTE_SEX
?
1138 LITTLE_ENDIAN_BYTE_SEX
: BIG_ENDIAN_BYTE_SEX
;
1139 ofile
->mh64
= (struct mach_header_64
*)addr
;
1140 ofile
->load_commands
= (struct load_command
*)(addr
+
1141 sizeof(struct mach_header_64
));
1142 if(check_Mach_O(ofile
) == CHECK_BAD
){
1145 return(NSObjectFileImageFormat
);
1150 if(object_name
!= NULL
){
1151 error("fat file: %s architecture %s is not an archive "
1152 "(object_name to ofile_map() can't be specified to "
1153 "be other than NULL)", ofile
->file_name
,
1158 /* see if this file is an archive file */
1159 else if(size
>= SARMAG
&& strncmp(addr
, ARMAG
, SARMAG
) == 0){
1160 ofile
->arch_type
= OFILE_ARCHIVE
;
1161 if(check_archive(ofile
, FALSE
) == CHECK_BAD
){
1164 return(NSObjectFileImageInappropriateFile
);
1169 #ifdef ALIGNMENT_CHECKS
1170 if(ofile
->archive_cputype
!= 0 &&
1171 ofile
->fat_archs
[i
].offset
% sizeof(uint32_t) != 0){
1172 error("fat file: %s architecture %s malformed archive that "
1173 "contains object files (offset to archive is not a "
1174 "multiple of sizeof(uint32_t))",
1175 ofile
->file_name
, arch_flag
->name
);
1178 return(NSObjectFileImageInappropriateFile
);
1183 #endif /* ALIGNMENT_CHECKS */
1184 if(object_name
!= NULL
){
1185 if(ofile_specific_member(object_name
, ofile
) == FALSE
)
1189 /* this file type is now known to be unknown to this program */
1191 ofile
->file_type
= OFILE_UNKNOWN
;
1192 if(object_name
!= NULL
){
1193 error("fat file: %s architecture %s is not an archive "
1194 "(object_name to ofile_map() can't be specified to "
1195 "be other than NULL)", ofile
->file_name
,
1201 /* see if this file is a 32-bit Mach-O file */
1202 else if(size
>= sizeof(struct mach_header
) &&
1203 (magic
== MH_MAGIC
||
1204 magic
== SWAP_INT(MH_MAGIC
))){
1205 ofile
->file_type
= OFILE_Mach_O
;
1206 ofile
->object_addr
= addr
;
1207 ofile
->object_size
= size
;
1208 if(magic
== MH_MAGIC
)
1209 ofile
->object_byte_sex
= host_byte_sex
;
1211 ofile
->object_byte_sex
= host_byte_sex
== BIG_ENDIAN_BYTE_SEX
?
1212 LITTLE_ENDIAN_BYTE_SEX
: BIG_ENDIAN_BYTE_SEX
;
1213 ofile
->mh
= (struct mach_header
*)addr
;
1214 ofile
->load_commands
= (struct load_command
*)(addr
+
1215 sizeof(struct mach_header
));
1216 if(check_Mach_O(ofile
) == CHECK_BAD
){
1219 return(NSObjectFileImageFormat
);
1224 if(object_name
!= NULL
){
1225 error("file: %s is not an archive (object_name to ofile_map() "
1226 "can't be specified to be other than NULL)",
1230 if(arch_flag
!= NULL
){
1231 if(arch_flag
->cputype
!= ofile
->mh_cputype
&&
1232 (arch_flag
->cpusubtype
& ~CPU_SUBTYPE_MASK
) !=
1233 (ofile
->mh_cpusubtype
& ~CPU_SUBTYPE_MASK
)){
1236 return(NSObjectFileImageArch
);
1238 error("object file: %s does not match specified arch_flag: "
1239 "%s passed to ofile_map()", ofile
->file_name
,
1248 /* see if this file is a 64-bit Mach-O file */
1249 else if(size
>= sizeof(struct mach_header_64
) &&
1250 (magic
== MH_MAGIC_64
||
1251 magic
== SWAP_INT(MH_MAGIC_64
))){
1252 ofile
->file_type
= OFILE_Mach_O
;
1253 ofile
->object_addr
= addr
;
1254 ofile
->object_size
= size
;
1255 if(magic
== MH_MAGIC_64
)
1256 ofile
->object_byte_sex
= host_byte_sex
;
1258 ofile
->object_byte_sex
= host_byte_sex
== BIG_ENDIAN_BYTE_SEX
?
1259 LITTLE_ENDIAN_BYTE_SEX
: BIG_ENDIAN_BYTE_SEX
;
1260 ofile
->mh64
= (struct mach_header_64
*)addr
;
1261 ofile
->load_commands
= (struct load_command
*)(addr
+
1262 sizeof(struct mach_header_64
));
1263 if(check_Mach_O(ofile
) == CHECK_BAD
){
1266 return(NSObjectFileImageFormat
);
1271 if(object_name
!= NULL
){
1272 error("file: %s is not an archive (object_name to ofile_map() "
1273 "can't be specified to be other than NULL)",
1277 if(arch_flag
!= NULL
){
1278 if(arch_flag
->cputype
!= ofile
->mh_cputype
&&
1279 (arch_flag
->cpusubtype
& ~CPU_SUBTYPE_MASK
) !=
1280 (ofile
->mh_cpusubtype
& ~CPU_SUBTYPE_MASK
)){
1283 return(NSObjectFileImageArch
);
1285 error("object file: %s does not match specified arch_flag: "
1286 "%s passed to ofile_map()", ofile
->file_name
,
1295 /* see if this file is an archive file */
1296 else if(size
>= SARMAG
&& strncmp(addr
, ARMAG
, SARMAG
) == 0){
1297 ofile
->file_type
= OFILE_ARCHIVE
;
1298 if(check_archive(ofile
, archives_with_fat_objects
) == CHECK_BAD
)
1300 if(object_name
!= NULL
){
1301 if(ofile_specific_member(object_name
, ofile
) == FALSE
)
1303 if(arch_flag
!= NULL
){
1304 if(arch_flag
->cputype
!= ofile
->mh_cputype
&&
1305 (arch_flag
->cpusubtype
& ~CPU_SUBTYPE_MASK
) !=
1306 (ofile
->mh_cpusubtype
& ~CPU_SUBTYPE_MASK
)){
1307 error("object file: %s(%.*s) does not match specified "
1308 "arch_flag: %s passed to ofile_map()",
1309 ofile
->file_name
, (int)ofile
->member_name_size
,
1310 ofile
->member_name
, arch_flag
->name
);
1316 if(arch_flag
!= NULL
){
1317 if(arch_flag
->cputype
!= ofile
->archive_cputype
&&
1318 (arch_flag
->cpusubtype
& ~CPU_SUBTYPE_MASK
) !=
1319 (ofile
->archive_cpusubtype
& ~CPU_SUBTYPE_MASK
)){
1320 error("archive file: %s objects do not match specified "
1321 "arch_flag: %s passed to ofile_map()",
1322 ofile
->file_name
, arch_flag
->name
);
1328 /* this file type is now known to be unknown to this program */
1335 if(is_llvm_bitcode(ofile
, ofile
->file_addr
, ofile
->file_size
) ==
1337 ofile
->file_type
= OFILE_LLVM_BITCODE
;
1338 if(arch_flag
!= NULL
){
1339 if(arch_flag
->cputype
!= ofile
->lto_cputype
&&
1340 (arch_flag
->cpusubtype
& ~CPU_SUBTYPE_MASK
) !=
1341 (ofile
->lto_cpusubtype
& ~CPU_SUBTYPE_MASK
)){
1342 error("llvm bitcode file: %s does not match specified "
1343 "arch_flag: %s passed to ofile_map()",
1344 ofile
->file_name
, arch_flag
->name
);
1348 if(object_name
!= NULL
){
1349 error("file: %s is not an archive (object_name to "
1350 "ofile_map() can't be specified to be other than "
1351 "NULL)", ofile
->file_name
);
1357 #endif /* LTO_SUPPORT */
1359 ofile
->file_type
= OFILE_UNKNOWN
;
1360 if(arch_flag
!= NULL
){
1363 return(NSObjectFileImageInappropriateFile
);
1365 error("file: %s is unknown type (arch_flag to ofile_map() "
1366 "can't be specified to be other than NULL)",
1372 if(object_name
!= NULL
){
1373 error("file: %s is not an archive (object_name to ofile_map() "
1374 "can't be specified to be other than NULL)",
1388 * ofile_unmap() deallocates the memory associated with the specified ofile
1394 struct ofile
*ofile
)
1398 if(ofile
->file_addr
!= NULL
){
1399 if((r
= vm_deallocate(mach_task_self(),
1400 (vm_address_t
)ofile
->file_addr
,
1401 (vm_size_t
)ofile
->file_size
)) != KERN_SUCCESS
){
1402 my_mach_error(r
, "Can't vm_deallocate mapped memory for file: "
1403 "%s", ofile
->file_name
);
1406 if(ofile
->file_name
!= NULL
)
1407 free(ofile
->file_name
);
1408 if(ofile
->arch_flag
.name
!= NULL
)
1409 free(ofile
->arch_flag
.name
);
1410 memset(ofile
, '\0', sizeof(struct ofile
));
1414 * ofile_first_arch() sets up the ofile struct for a fat file to the first arch
1420 struct ofile
*ofile
)
1422 if(ofile
->file_type
== OFILE_FAT
||
1423 (ofile
->file_type
== OFILE_ARCHIVE
&&
1424 ofile
->member_type
== OFILE_FAT
) )
1425 return(ofile_specific_arch(ofile
, 0));
1427 error("ofile_first_arch() called and file type of: %s is not a fat "
1428 "file\n", ofile
->file_name
);
1434 * ofile_next_arch() sets up the ofile struct for a fat file to the next arch
1440 struct ofile
*ofile
)
1442 if(ofile
->file_type
== OFILE_FAT
||
1443 (ofile
->file_type
== OFILE_ARCHIVE
&&
1444 ofile
->member_type
== OFILE_FAT
) ){
1445 if(ofile
->narch
+ 1 < ofile
->fat_header
->nfat_arch
)
1446 return(ofile_specific_arch(ofile
, ofile
->narch
+ 1));
1451 error("ofile_next_arch() called and file type of: %s is not a fat "
1452 "file\n", ofile
->file_name
);
1458 * ofile_specific_arch() sets up the ofile struct for the fat file for the
1463 ofile_specific_arch(
1464 struct ofile
*ofile
,
1470 enum byte_sex host_byte_sex
;
1472 ofile
->narch
= narch
;
1473 ofile
->arch_type
= OFILE_UNKNOWN
;
1474 if(ofile
->arch_flag
.name
!= NULL
)
1475 free(ofile
->arch_flag
.name
);
1476 ofile
->arch_flag
.name
= NULL
;
1477 ofile
->arch_flag
.cputype
= 0;
1478 ofile
->arch_flag
.cpusubtype
= 0;
1479 ofile
->archive_cputype
= 0;
1480 ofile
->archive_cpusubtype
= 0;
1481 ofile
->object_addr
= NULL
;
1482 ofile
->object_size
= 0;
1483 ofile
->object_byte_sex
= UNKNOWN_BYTE_SEX
;
1486 ofile
->load_commands
= NULL
;
1488 ofile
->arch_flag
.cputype
= ofile
->fat_archs
[ofile
->narch
].cputype
;
1489 ofile
->arch_flag
.cpusubtype
= ofile
->fat_archs
[ofile
->narch
].cpusubtype
;
1490 set_arch_flag_name(&(ofile
->arch_flag
));
1493 /* Now determine the file type for this specific architecture */
1494 if(ofile
->file_type
== OFILE_FAT
){
1495 ofile
->member_offset
= 0;
1496 ofile
->member_addr
= NULL
;
1497 ofile
->member_size
= 0;
1498 ofile
->member_ar_hdr
= NULL
;
1499 ofile
->member_type
= OFILE_UNKNOWN
;
1501 size
= ofile
->fat_archs
[ofile
->narch
].size
;
1502 addr
= ofile
->file_addr
+ ofile
->fat_archs
[ofile
->narch
].offset
;
1505 if(ofile
->file_type
!= OFILE_ARCHIVE
||
1506 ofile
->member_type
!= OFILE_FAT
){
1507 error("internal error. ofile_specific_arch() called but file "
1508 "is not a fat file or an archive with a fat member ");
1510 size
= ofile
->fat_archs
[ofile
->narch
].size
;
1511 addr
= ofile
->file_addr
+
1512 ofile
->member_offset
+
1513 ofile
->fat_archs
[ofile
->narch
].offset
;
1517 if(addr
- ofile
->file_addr
> (ptrdiff_t)ofile
->file_size
){
1518 error("fat file: %s offset to architecture %s extends past end "
1519 "of file", ofile
->file_name
, ofile
->arch_flag
.name
);
1522 if(addr
+ size
> ofile
->file_addr
+ ofile
->file_size
)
1523 size
= (ofile
->file_addr
+ ofile
->file_size
) - addr
;
1526 if(size
>= sizeof(struct mach_header
))
1527 memcpy(&magic
, addr
, sizeof(uint32_t));
1528 /* see if this file is a 32-bit Mach-O file */
1529 if(size
>= sizeof(struct mach_header
) &&
1530 (magic
== MH_MAGIC
|| magic
== SWAP_INT(MH_MAGIC
))){
1531 #ifdef ALIGNMENT_CHECKS
1532 if(ofile
->fat_archs
[ofile
->narch
].offset
% 4 != 0){
1533 if(ofile
->file_type
== OFILE_ARCHIVE
){
1534 error("fat file: %s(%.*s) architecture %s malformed for a "
1535 "32-bit object file (offset is not a multiple of 4)",
1536 ofile
->file_name
, (int)ofile
->member_name_size
,
1537 ofile
->member_name
, ofile
->arch_flag
.name
);
1540 error("fat file: %s architecture %s malformed for a 32-bit "
1541 "object file (offset is not a multiple of 4)",
1542 ofile
->file_name
, ofile
->arch_flag
.name
);
1545 #endif /* ALIGNMENT_CHECKS */
1546 ofile
->arch_type
= OFILE_Mach_O
;
1547 ofile
->object_addr
= addr
;
1548 ofile
->object_size
= size
;
1549 host_byte_sex
= get_host_byte_sex();
1550 if(magic
== MH_MAGIC
)
1551 ofile
->object_byte_sex
= host_byte_sex
;
1553 ofile
->object_byte_sex
=
1554 host_byte_sex
== BIG_ENDIAN_BYTE_SEX
?
1555 LITTLE_ENDIAN_BYTE_SEX
: BIG_ENDIAN_BYTE_SEX
;
1556 ofile
->mh
= (struct mach_header
*)addr
;
1557 ofile
->load_commands
= (struct load_command
*)(addr
+
1558 sizeof(struct mach_header
));
1559 if(check_Mach_O(ofile
) == CHECK_BAD
)
1562 /* see if this file is a 64-bit Mach-O file */
1563 else if(size
>= sizeof(struct mach_header_64
) &&
1564 (magic
== MH_MAGIC_64
|| magic
== SWAP_INT(MH_MAGIC_64
))){
1565 #ifdef ALIGNMENT_CHECKS
1566 if(ofile
->fat_archs
[ofile
->narch
].offset
% 8 != 0){
1567 if(ofile
->file_type
== OFILE_ARCHIVE
){
1568 error("fat file: %s(%.*s) architecture %s malformed for an "
1569 "object file (offset is not a multiple of 8)",
1570 ofile
->file_name
, (int)ofile
->member_name_size
,
1571 ofile
->member_name
, ofile
->arch_flag
.name
);
1574 error("fat file: %s architecture %s malformed for a 64-bit "
1575 "object file (offset is not a multiple of 8",
1576 ofile
->file_name
, ofile
->arch_flag
.name
);
1579 #endif /* ALIGNMENT_CHECKS */
1580 ofile
->arch_type
= OFILE_Mach_O
;
1581 ofile
->object_addr
= addr
;
1582 ofile
->object_size
= size
;
1583 host_byte_sex
= get_host_byte_sex();
1584 if(magic
== MH_MAGIC_64
)
1585 ofile
->object_byte_sex
= host_byte_sex
;
1587 ofile
->object_byte_sex
=
1588 host_byte_sex
== BIG_ENDIAN_BYTE_SEX
?
1589 LITTLE_ENDIAN_BYTE_SEX
: BIG_ENDIAN_BYTE_SEX
;
1590 ofile
->mh64
= (struct mach_header_64
*)addr
;
1591 ofile
->load_commands
= (struct load_command
*)(addr
+
1592 sizeof(struct mach_header_64
));
1593 if(check_Mach_O(ofile
) == CHECK_BAD
)
1596 /* see if this file is an archive file */
1597 else if(size
>= SARMAG
&& strncmp(addr
, ARMAG
, SARMAG
) == 0){
1598 ofile
->arch_type
= OFILE_ARCHIVE
;
1599 if(check_archive(ofile
, FALSE
) == CHECK_BAD
)
1601 #ifdef ALIGNMENT_CHECKS
1602 if(ofile
->archive_cputype
!= 0 &&
1603 ofile
->fat_archs
[ofile
->narch
].offset
%
1604 sizeof(uint32_t) != 0){
1605 error("fat file: %s architecture %s malformed archive that "
1606 "contains object files (offset to archive is not a "
1607 "multiple of sizeof(uint32_t))",
1608 ofile
->file_name
, ofile
->arch_flag
.name
);
1611 #endif /* ALIGNMENT_CHECKS */
1614 * This type for this architecture is now known to be unknown to this
1618 ofile
->arch_type
= OFILE_UNKNOWN
;
1623 ofile
->arch_type
= OFILE_UNKNOWN
;
1624 if(ofile
->arch_flag
.name
!= NULL
)
1625 free(ofile
->arch_flag
.name
);
1626 ofile
->arch_flag
.name
= NULL
;
1627 ofile
->arch_flag
.cputype
= 0;
1628 ofile
->arch_flag
.cpusubtype
= 0;
1629 if(ofile
->file_type
!= OFILE_ARCHIVE
){
1630 ofile
->member_offset
= 0;
1631 ofile
->member_addr
= NULL
;
1632 ofile
->member_size
= 0;
1633 ofile
->member_ar_hdr
= NULL
;
1634 ofile
->member_type
= OFILE_UNKNOWN
;
1636 ofile
->archive_cputype
= 0;
1637 ofile
->archive_cpusubtype
= 0;
1638 ofile
->object_addr
= NULL
;
1639 ofile
->object_size
= 0;
1640 ofile
->object_byte_sex
= UNKNOWN_BYTE_SEX
;
1643 ofile
->load_commands
= NULL
;
1648 * ofile_first_member() set up the ofile structure (the member_* fields and
1649 * the object file fields if the first member is an object file) for the first
1655 struct ofile
*ofile
)
1658 uint32_t size
, offset
;
1660 enum byte_sex host_byte_sex
;
1661 struct ar_hdr
*ar_hdr
;
1662 uint32_t ar_name_size
;
1664 /* These fields are to be filled in by this routine, clear them first */
1665 ofile
->member_offset
= 0;
1666 ofile
->member_addr
= NULL
;
1667 ofile
->member_size
= 0;
1668 ofile
->member_ar_hdr
= NULL
;
1669 ofile
->member_name
= NULL
;
1670 ofile
->member_name_size
= 0;
1671 ofile
->member_type
= OFILE_UNKNOWN
;
1672 ofile
->object_addr
= NULL
;
1673 ofile
->object_size
= 0;
1674 ofile
->object_byte_sex
= UNKNOWN_BYTE_SEX
;
1677 ofile
->load_commands
= NULL
;
1680 * Note: it is up to the caller if they want to call free_lto() on this
1681 * when iterating through the members of an archive.
1684 #endif /* LTO_SUPPORT */
1687 * Get the address and size of the archive.
1689 if(ofile
->file_type
== OFILE_FAT
){
1690 if(ofile
->arch_type
!= OFILE_ARCHIVE
){
1691 error("ofile_first_member() called on fat file: %s with a "
1692 "non-archive architecture or no architecture selected\n",
1696 addr
= ofile
->file_addr
+ ofile
->fat_archs
[ofile
->narch
].offset
;
1697 size
= ofile
->fat_archs
[ofile
->narch
].size
;
1699 else if(ofile
->file_type
== OFILE_ARCHIVE
){
1700 addr
= ofile
->file_addr
;
1701 size
= ofile
->file_size
;
1704 error("ofile_first_member() called and file type of %s is "
1705 "OFILE_UNKNOWN\n", ofile
->file_name
);
1709 if((addr
+ SARMAG
) - ofile
->file_addr
> (ptrdiff_t)ofile
->file_size
){
1710 archive_error(ofile
, "offset to first member extends past the end "
1714 if(addr
+ size
> ofile
->file_addr
+ ofile
->file_size
)
1715 size
= (ofile
->file_addr
+ ofile
->file_size
) - addr
;
1717 if(size
< SARMAG
|| strncmp(addr
, ARMAG
, SARMAG
) != 0){
1718 archive_error(ofile
, "internal error. ofile_first_member() "
1719 "called but file does not have an archive magic "
1725 if(offset
!= size
&& offset
+ sizeof(struct ar_hdr
) > size
){
1726 archive_error(ofile
, "truncated or malformed (archive header of "
1727 "first member extends past the end of the file)");
1731 /* check for empty archive */
1735 /* now we know there is a first member so set it up */
1736 ar_hdr
= (struct ar_hdr
*)(addr
+ offset
);
1737 offset
+= sizeof(struct ar_hdr
);
1738 ofile
->member_offset
= offset
;
1739 ofile
->member_addr
= addr
+ offset
;
1740 ofile
->member_size
= strtoul(ar_hdr
->ar_size
, NULL
, 10);
1741 ofile
->member_ar_hdr
= ar_hdr
;
1742 ofile
->member_type
= OFILE_UNKNOWN
;
1743 ofile
->member_name
= ar_hdr
->ar_name
;
1744 if(strncmp(ofile
->member_name
, AR_EFMT1
, sizeof(AR_EFMT1
) - 1) == 0){
1745 ofile
->member_name
= ar_hdr
->ar_name
+ sizeof(struct ar_hdr
);
1746 ar_name_size
= strtoul(ar_hdr
->ar_name
+ sizeof(AR_EFMT1
) - 1,
1748 ofile
->member_name_size
= ar_name_size
;
1749 ofile
->member_offset
+= ar_name_size
;
1750 ofile
->member_addr
+= ar_name_size
;
1751 ofile
->member_size
-= ar_name_size
;
1754 ofile
->member_name_size
= size_ar_name(ar_hdr
);
1757 /* Clear these in case there is no table of contents */
1758 ofile
->toc_addr
= NULL
;
1759 ofile
->toc_size
= 0;
1760 ofile
->toc_ar_hdr
= NULL
;
1761 ofile
->toc_name
= NULL
;
1762 ofile
->toc_name_size
= 0;
1763 ofile
->toc_ranlibs
= NULL
;
1764 ofile
->toc_nranlibs
= 0;
1765 ofile
->toc_strings
= NULL
;
1766 ofile
->toc_strsize
= 0;
1767 ofile
->toc_bad
= FALSE
;
1769 host_byte_sex
= get_host_byte_sex();
1771 if(ofile
->member_size
> sizeof(uint32_t)){
1772 memcpy(&magic
, ofile
->member_addr
, sizeof(uint32_t));
1773 #ifdef __BIG_ENDIAN__
1774 if(magic
== FAT_MAGIC
)
1775 #endif /* __BIG_ENDIAN__ */
1776 #ifdef __LITTLE_ENDIAN__
1777 if(magic
== SWAP_INT(FAT_MAGIC
))
1778 #endif /* __LITTLE_ENDIAN__ */
1780 ofile
->member_type
= OFILE_FAT
;
1782 (struct fat_header
*)(ofile
->member_addr
);
1783 #ifdef __LITTLE_ENDIAN__
1784 swap_fat_header(ofile
->fat_header
, host_byte_sex
);
1785 #endif /* __LITTLE_ENDIAN__ */
1786 if(sizeof(struct fat_header
) +
1787 ofile
->fat_header
->nfat_arch
*
1788 sizeof(struct fat_arch
) > ofile
->member_size
){
1789 archive_member_error(ofile
, "fat file truncated or "
1790 "malformed (fat_arch structs would extend past "
1791 "the end of the archive member)");
1794 ofile
->fat_archs
= (struct fat_arch
*)
1795 (ofile
->member_addr
+ sizeof(struct fat_header
));
1796 #ifdef __LITTLE_ENDIAN__
1797 swap_fat_arch(ofile
->fat_archs
,
1798 ofile
->fat_header
->nfat_arch
, host_byte_sex
);
1799 #endif /* __LITTLE_ENDIAN__ */
1800 if(check_fat_object_in_archive(ofile
) == FALSE
)
1803 else if(size
- (offset
+ ar_name_size
) >=
1804 sizeof(struct mach_header
) &&
1805 (magic
== MH_MAGIC
|| magic
== SWAP_INT(MH_MAGIC
))){
1806 #ifdef ALIGNMENT_CHECKS
1807 if((offset
+ ar_name_size
) % 4 != 0){
1808 archive_member_error(ofile
, "offset in archive not a "
1809 "multiple of 4 (must be since member is a 32-bit "
1813 #endif /* ALIGNMENT_CHECKS */
1814 ofile
->member_type
= OFILE_Mach_O
;
1815 ofile
->object_addr
= ofile
->member_addr
;
1816 ofile
->object_size
= ofile
->member_size
;
1817 if(magic
== MH_MAGIC
)
1818 ofile
->object_byte_sex
= host_byte_sex
;
1820 ofile
->object_byte_sex
=
1821 host_byte_sex
== BIG_ENDIAN_BYTE_SEX
?
1822 LITTLE_ENDIAN_BYTE_SEX
: BIG_ENDIAN_BYTE_SEX
;
1823 ofile
->mh
= (struct mach_header
*)(ofile
->object_addr
);
1824 ofile
->load_commands
= (struct load_command
*)
1825 (ofile
->object_addr
+ sizeof(struct mach_header
));
1826 if(check_Mach_O(ofile
) == CHECK_BAD
)
1829 else if(size
- (offset
+ ar_name_size
) >=
1830 sizeof(struct mach_header_64
) &&
1831 (magic
== MH_MAGIC_64
|| magic
== SWAP_INT(MH_MAGIC_64
))){
1832 #ifdef ALIGNMENT_CHECKS_ARCHIVE_64_BIT
1833 if(archive_64_bit_align_warning
== FALSE
&&
1834 (offset
+ ar_name_size
) % 8 != 0){
1835 temporary_archive_member_warning(ofile
, "offset in archive "
1836 "not a multiple of 8 (must be since member is an "
1837 "64-bit object file)");
1838 archive_64_bit_align_warning
= TRUE
;
1841 #endif /* ALIGNMENT_CHECKS_ARCHIVE_64_BIT */
1842 ofile
->member_type
= OFILE_Mach_O
;
1843 ofile
->object_addr
= ofile
->member_addr
;
1844 ofile
->object_size
= ofile
->member_size
;
1845 if(magic
== MH_MAGIC_64
)
1846 ofile
->object_byte_sex
= host_byte_sex
;
1848 ofile
->object_byte_sex
=
1849 host_byte_sex
== BIG_ENDIAN_BYTE_SEX
?
1850 LITTLE_ENDIAN_BYTE_SEX
: BIG_ENDIAN_BYTE_SEX
;
1851 ofile
->mh64
= (struct mach_header_64
*)(ofile
->object_addr
);
1852 ofile
->load_commands
= (struct load_command
*)
1853 (ofile
->object_addr
+ sizeof(struct mach_header_64
));
1854 if(check_Mach_O(ofile
) == CHECK_BAD
)
1857 if(ofile
->member_type
== OFILE_UNKNOWN
&&
1858 (strncmp(ofile
->member_name
, SYMDEF_SORTED
,
1859 sizeof(SYMDEF_SORTED
) - 1) == 0 ||
1860 strncmp(ofile
->member_name
, SYMDEF
,
1861 sizeof(SYMDEF
) - 1) == 0)){
1862 ofile
->toc_addr
= ofile
->member_addr
;
1863 ofile
->toc_size
= ofile
->member_size
;
1864 ofile
->toc_ar_hdr
= ofile
->member_ar_hdr
;
1865 ofile
->toc_name
= ofile
->member_name
;
1866 ofile
->toc_name_size
= ofile
->member_name_size
;
1867 if(check_archive_toc(ofile
) == CHECK_BAD
)
1871 if(ofile
->member_type
== OFILE_UNKNOWN
&&
1872 strncmp(ofile
->member_name
, SYMDEF_SORTED
,
1873 sizeof(SYMDEF_SORTED
) - 1) != 0 &&
1874 strncmp(ofile
->member_name
, SYMDEF
,
1875 sizeof(SYMDEF
) - 1) != 0 &&
1876 is_llvm_bitcode(ofile
, ofile
->member_addr
, ofile
->member_size
) ==
1878 ofile
->member_type
= OFILE_LLVM_BITCODE
;
1879 ofile
->object_addr
= ofile
->member_addr
;
1880 ofile
->object_size
= ofile
->member_size
;
1882 #endif /* LTO_SUPPORT */
1887 ofile
->fat_header
= NULL
;
1888 ofile
->fat_archs
= NULL
;
1890 ofile
->member_offset
= 0;
1891 ofile
->member_addr
= 0;
1892 ofile
->member_size
= 0;
1893 ofile
->member_ar_hdr
= NULL
;
1894 ofile
->member_name
= NULL
;
1895 ofile
->member_name_size
= 0;
1896 ofile
->member_type
= OFILE_UNKNOWN
;
1897 ofile
->object_addr
= NULL
;
1898 ofile
->object_size
= 0;
1899 ofile
->object_byte_sex
= UNKNOWN_BYTE_SEX
;
1902 ofile
->load_commands
= NULL
;
1905 ofile
->lto_cputype
= 0;
1906 ofile
->lto_cpusubtype
= 0;
1907 #endif /* LTO_SUPPORT */
1912 * ofile_next_member() set up the ofile structure (the member_* fields and
1913 * the object file fields if the next member is an object file) for the next
1919 struct ofile
*ofile
)
1922 uint32_t size
, offset
;
1924 enum byte_sex host_byte_sex
;
1925 struct ar_hdr
*ar_hdr
;
1926 uint32_t ar_name_size
;
1929 * Get the address and size of the archive.
1931 if(ofile
->file_type
== OFILE_FAT
){
1932 if(ofile
->arch_type
!= OFILE_ARCHIVE
){
1933 error("ofile_next_member() called on fat file: %s with a "
1934 "non-archive architecture or no architecture selected\n",
1938 addr
= ofile
->file_addr
+ ofile
->fat_archs
[ofile
->narch
].offset
;
1939 size
= ofile
->fat_archs
[ofile
->narch
].size
;
1941 else if(ofile
->file_type
== OFILE_ARCHIVE
){
1942 addr
= ofile
->file_addr
;
1943 size
= ofile
->file_size
;
1946 error("ofile_next_member() called and file type of %s is "
1947 "OFILE_UNKNOWN\n", ofile
->file_name
);
1950 if(size
< SARMAG
|| strncmp(addr
, ARMAG
, SARMAG
) != 0){
1951 archive_error(ofile
, "internal error. ofile_next_member() "
1952 "called but file does not have an archive magic "
1956 if(ofile
->member_ar_hdr
== NULL
){
1957 archive_error(ofile
, "internal error. ofile_next_member() called "
1958 "but the ofile struct does not have an archive "
1963 /* figure out the offset to the next member */
1964 offset
= ofile
->member_offset
+ rnd(ofile
->member_size
,sizeof(short));
1966 if((addr
- ofile
->file_addr
) + offset
> ofile
->file_size
){
1967 archive_error(ofile
, "offset to next member extends past the end "
1972 /* if now at the end of the file then no more members */
1976 archive_error(ofile
, "truncated or malformed (archive header of "
1977 "next member extends past the end of the file)");
1981 /* now we know there is a next member so set it up */
1982 ar_hdr
= (struct ar_hdr
*)(addr
+ offset
);
1983 offset
+= sizeof(struct ar_hdr
);
1984 ofile
->member_offset
= offset
;
1985 ofile
->member_addr
= addr
+ offset
;
1986 ofile
->member_size
= strtoul(ar_hdr
->ar_size
, NULL
, 10);
1987 ofile
->member_ar_hdr
= ar_hdr
;
1988 ofile
->member_name
= ar_hdr
->ar_name
;
1989 if(strncmp(ofile
->member_name
, AR_EFMT1
, sizeof(AR_EFMT1
) - 1) == 0){
1990 ofile
->member_name
= ar_hdr
->ar_name
+ sizeof(struct ar_hdr
);
1991 ar_name_size
= strtoul(ar_hdr
->ar_name
+ sizeof(AR_EFMT1
) - 1,
1993 ofile
->member_name_size
= ar_name_size
;
1994 ofile
->member_offset
+= ar_name_size
;
1995 ofile
->member_addr
+= ar_name_size
;
1996 ofile
->member_size
-= ar_name_size
;
1999 ofile
->member_name_size
= size_ar_name(ar_hdr
);
2002 ofile
->member_type
= OFILE_UNKNOWN
;
2003 ofile
->object_addr
= NULL
;
2004 ofile
->object_size
= 0;
2005 ofile
->object_byte_sex
= UNKNOWN_BYTE_SEX
;
2008 ofile
->load_commands
= NULL
;
2010 host_byte_sex
= get_host_byte_sex();
2012 if(ofile
->member_size
> sizeof(uint32_t)){
2013 memcpy(&magic
, ofile
->member_addr
, sizeof(uint32_t));
2014 #ifdef __BIG_ENDIAN__
2015 if(magic
== FAT_MAGIC
)
2016 #endif /* __BIG_ENDIAN__ */
2017 #ifdef __LITTLE_ENDIAN__
2018 if(magic
== SWAP_INT(FAT_MAGIC
))
2019 #endif /* __LITTLE_ENDIAN__ */
2021 ofile
->member_type
= OFILE_FAT
;
2022 ofile
->fat_header
= (struct fat_header
*)(ofile
->member_addr
);
2023 #ifdef __LITTLE_ENDIAN__
2024 swap_fat_header(ofile
->fat_header
, host_byte_sex
);
2025 #endif /* __LITTLE_ENDIAN__ */
2026 if(sizeof(struct fat_header
) +
2027 ofile
->fat_header
->nfat_arch
*
2028 sizeof(struct fat_arch
) > ofile
->member_size
){
2029 archive_member_error(ofile
, "fat file truncated or "
2030 "malformed (fat_arch structs would extend past "
2031 "the end of the archive member)");
2034 ofile
->fat_archs
= (struct fat_arch
*)(ofile
->member_addr
+
2035 sizeof(struct fat_header
));
2036 #ifdef __LITTLE_ENDIAN__
2037 swap_fat_arch(ofile
->fat_archs
,
2038 ofile
->fat_header
->nfat_arch
, host_byte_sex
);
2039 #endif /* __LITTLE_ENDIAN__ */
2040 if(check_fat_object_in_archive(ofile
) == FALSE
)
2043 else if(size
- (offset
+ ar_name_size
) >=
2044 sizeof(struct mach_header
) &&
2045 (magic
== MH_MAGIC
||
2046 magic
== SWAP_INT(MH_MAGIC
))){
2047 #ifdef ALIGNMENT_CHECKS
2048 if((offset
+ ar_name_size
) % 4 != 0){
2049 archive_member_error(ofile
, "offset in archive not "
2050 "a multiple of 4 (must be since member is an 32-bit "
2054 #endif /* ALIGNMENT_CHECKS */
2055 ofile
->member_type
= OFILE_Mach_O
;
2056 ofile
->object_addr
= ofile
->member_addr
;
2057 ofile
->object_size
= ofile
->member_size
;
2058 if(magic
== MH_MAGIC
)
2059 ofile
->object_byte_sex
= host_byte_sex
;
2061 ofile
->object_byte_sex
=
2062 host_byte_sex
== BIG_ENDIAN_BYTE_SEX
?
2063 LITTLE_ENDIAN_BYTE_SEX
: BIG_ENDIAN_BYTE_SEX
;
2064 ofile
->mh
= (struct mach_header
*)ofile
->object_addr
;
2065 ofile
->load_commands
= (struct load_command
*)
2066 (ofile
->object_addr
+ sizeof(struct mach_header
));
2067 if(check_Mach_O(ofile
) == CHECK_BAD
)
2070 else if(size
- (offset
+ ar_name_size
) >=
2071 sizeof(struct mach_header_64
) &&
2072 (magic
== MH_MAGIC_64
||
2073 magic
== SWAP_INT(MH_MAGIC_64
))){
2074 #ifdef ALIGNMENT_CHECKS_ARCHIVE_64_BIT
2075 if(archive_64_bit_align_warning
== FALSE
&&
2076 (offset
+ ar_name_size
) % 8 != 0){
2077 temporary_archive_member_warning(ofile
, "offset in archive "
2078 "not a multiple of 8 (must be since member is an "
2079 "64-bit object file)");
2080 archive_64_bit_align_warning
= TRUE
;
2083 #endif /* ALIGNMENT_CHECKS_ARCHIVE_64_BIT */
2084 ofile
->member_type
= OFILE_Mach_O
;
2085 ofile
->object_addr
= ofile
->member_addr
;
2086 ofile
->object_size
= ofile
->member_size
;
2087 if(magic
== MH_MAGIC_64
)
2088 ofile
->object_byte_sex
= host_byte_sex
;
2090 ofile
->object_byte_sex
=
2091 host_byte_sex
== BIG_ENDIAN_BYTE_SEX
?
2092 LITTLE_ENDIAN_BYTE_SEX
: BIG_ENDIAN_BYTE_SEX
;
2093 ofile
->mh64
= (struct mach_header_64
*)ofile
->object_addr
;
2094 ofile
->load_commands
= (struct load_command
*)
2095 (ofile
->object_addr
+ sizeof(struct mach_header_64
));
2096 if(check_Mach_O(ofile
) == CHECK_BAD
)
2100 if(ofile
->member_type
== OFILE_UNKNOWN
&&
2101 is_llvm_bitcode(ofile
, ofile
->member_addr
, ofile
->member_size
) ==
2103 ofile
->member_type
= OFILE_LLVM_BITCODE
;
2104 ofile
->object_addr
= ofile
->member_addr
;
2105 ofile
->object_size
= ofile
->member_size
;
2107 #endif /* LTO_SUPPORT */
2112 if(ofile
->member_type
== OFILE_FAT
){
2113 ofile
->fat_header
= NULL
;
2114 ofile
->fat_archs
= NULL
;
2116 ofile
->member_offset
= 0;
2117 ofile
->member_addr
= NULL
;
2118 ofile
->member_size
= 0;
2119 ofile
->member_ar_hdr
= NULL
;
2120 ofile
->member_name
= NULL
;
2121 ofile
->member_name_size
= 0;
2122 ofile
->member_type
= OFILE_UNKNOWN
;
2123 ofile
->object_addr
= NULL
;
2124 ofile
->object_size
= 0;
2125 ofile
->object_byte_sex
= UNKNOWN_BYTE_SEX
;
2128 ofile
->load_commands
= NULL
;
2131 ofile
->lto_cputype
= 0;
2132 ofile
->lto_cpusubtype
= 0;
2133 #endif /* LTO_SUPPORT */
2138 * ofile_specific_member() set up the ofile structure (the member_* fields and
2139 * the object file fields if the member is an object file) for the specified
2140 * member member_name.
2144 ofile_specific_member(
2145 const char *member_name
,
2146 struct ofile
*ofile
)
2150 uint32_t size
, offset
;
2152 enum byte_sex host_byte_sex
;
2154 uint32_t ar_name_size
;
2155 struct ar_hdr
*ar_hdr
;
2157 /* These fields are to be filled in by this routine, clear them first */
2158 ofile
->member_offset
= 0;
2159 ofile
->member_addr
= NULL
;
2160 ofile
->member_size
= 0;
2161 ofile
->member_ar_hdr
= NULL
;
2162 ofile
->member_name
= NULL
;
2163 ofile
->member_name_size
= 0;
2164 ofile
->member_type
= OFILE_UNKNOWN
;
2165 ofile
->object_addr
= NULL
;
2166 ofile
->object_size
= 0;
2167 ofile
->object_byte_sex
= UNKNOWN_BYTE_SEX
;
2170 ofile
->load_commands
= NULL
;
2173 * Get the address and size of the archive.
2175 if(ofile
->file_type
== OFILE_FAT
){
2176 if(ofile
->arch_type
!= OFILE_ARCHIVE
){
2177 error("ofile_specific_member() called on fat file: %s with a "
2178 "non-archive architecture or no architecture selected\n",
2182 addr
= ofile
->file_addr
+ ofile
->fat_archs
[ofile
->narch
].offset
;
2183 size
= ofile
->fat_archs
[ofile
->narch
].size
;
2185 else if(ofile
->file_type
== OFILE_ARCHIVE
){
2186 addr
= ofile
->file_addr
;
2187 size
= ofile
->file_size
;
2190 error("ofile_specific_member() called and file type of %s is "
2191 "OFILE_UNKNOWN\n", ofile
->file_name
);
2194 if(size
< SARMAG
|| strncmp(addr
, ARMAG
, SARMAG
) != 0){
2195 archive_error(ofile
, "internal error. ofile_specific_member() "
2196 "called but file does not have an archive magic "
2202 if(offset
!= size
&& offset
+ sizeof(struct ar_hdr
) > size
){
2203 archive_error(ofile
, "truncated or malformed (archive header of "
2204 "first member extends past the end of the file)");
2207 while(size
> offset
){
2208 ar_hdr
= (struct ar_hdr
*)(addr
+ offset
);
2209 offset
+= sizeof(struct ar_hdr
);
2210 if(strncmp(ar_hdr
->ar_name
, AR_EFMT1
, sizeof(AR_EFMT1
) - 1) == 0){
2212 if(check_extend_format_1(ofile
, ar_hdr
, size
- offset
,
2213 &ar_name_size
) == CHECK_BAD
){
2214 i
= size_ar_name(ar_hdr
);
2215 ar_name
= ar_hdr
->ar_name
;
2221 i
= strtoul(ar_hdr
->ar_name
+ sizeof(AR_EFMT1
) - 1,NULL
,10);
2222 ar_name
= ar_hdr
->ar_name
+ sizeof(struct ar_hdr
);
2227 i
= size_ar_name(ar_hdr
);
2228 ar_name
= ar_hdr
->ar_name
;
2231 if(i
> 0 && strncmp(ar_name
, member_name
, i
) == 0){
2233 ofile
->member_name
= ar_name
;
2234 ofile
->member_name_size
= i
;
2235 ofile
->member_offset
= offset
+ ar_name_size
;
2236 ofile
->member_addr
= addr
+ offset
+ ar_name_size
;
2237 ofile
->member_size
= strtoul(ar_hdr
->ar_size
, NULL
, 10) -
2239 ofile
->member_ar_hdr
= ar_hdr
;
2240 ofile
->member_type
= OFILE_UNKNOWN
;
2242 host_byte_sex
= get_host_byte_sex();
2244 if(ofile
->member_size
> sizeof(uint32_t)){
2245 memcpy(&magic
, addr
+ offset
+ ar_name_size
,
2247 #ifdef __BIG_ENDIAN__
2248 if(magic
== FAT_MAGIC
)
2249 #endif /* __BIG_ENDIAN__ */
2250 #ifdef __LITTLE_ENDIAN__
2251 if(magic
== SWAP_INT(FAT_MAGIC
))
2252 #endif /* __LITTLE_ENDIAN__ */
2254 ofile
->member_type
= OFILE_FAT
;
2256 (struct fat_header
*)(addr
+ offset
+ ar_name_size
);
2257 #ifdef __LITTLE_ENDIAN__
2258 swap_fat_header(ofile
->fat_header
, host_byte_sex
);
2259 #endif /* __LITTLE_ENDIAN__ */
2260 if(sizeof(struct fat_header
) +
2261 ofile
->fat_header
->nfat_arch
*
2262 sizeof(struct fat_arch
) > ofile
->member_size
){
2263 archive_member_error(ofile
, "fat file truncated or "
2264 "malformed (fat_arch structs would extend "
2265 "past the end of the archive member)");
2269 (struct fat_arch
*)(addr
+ offset
+ ar_name_size
+
2270 sizeof(struct fat_header
));
2271 #ifdef __LITTLE_ENDIAN__
2272 swap_fat_arch(ofile
->fat_archs
,
2273 ofile
->fat_header
->nfat_arch
,
2275 #endif /* __LITTLE_ENDIAN__ */
2276 if(check_fat_object_in_archive(ofile
) == FALSE
)
2279 else if(size
- (offset
+ ar_name_size
) >=
2280 sizeof(struct mach_header
) &&
2281 (magic
== MH_MAGIC
||
2282 magic
== SWAP_INT(MH_MAGIC
))){
2283 #ifdef ALIGNMENT_CHECKS
2284 if((offset
+ ar_name_size
) % 4 != 0){
2285 archive_member_error(ofile
, "offset in archive not "
2286 "a multiple of 4) (must be since member is a "
2287 "32-bit object file)");
2290 #endif /* ALIGNMENT_CHECKS */
2291 ofile
->member_type
= OFILE_Mach_O
;
2292 ofile
->object_addr
= ofile
->member_addr
;
2293 ofile
->object_size
= ofile
->member_size
;
2294 if(magic
== MH_MAGIC
)
2295 ofile
->object_byte_sex
= host_byte_sex
;
2297 ofile
->object_byte_sex
=
2298 host_byte_sex
== BIG_ENDIAN_BYTE_SEX
?
2299 LITTLE_ENDIAN_BYTE_SEX
: BIG_ENDIAN_BYTE_SEX
;
2300 ofile
->mh
= (struct mach_header
*)ofile
->object_addr
;
2301 ofile
->load_commands
= (struct load_command
*)
2302 (ofile
->object_addr
+ sizeof(struct mach_header
));
2303 if(check_Mach_O(ofile
) == CHECK_BAD
)
2306 else if(size
- (offset
+ ar_name_size
) >=
2307 sizeof(struct mach_header_64
) &&
2308 (magic
== MH_MAGIC_64
||
2309 magic
== SWAP_INT(MH_MAGIC_64
))){
2310 #ifdef ALIGNMENT_CHECKS_ARCHIVE_64_BIT
2311 if(archive_64_bit_align_warning
== FALSE
&&
2312 (offset
+ ar_name_size
) % 8 != 0){
2313 temporary_archive_member_warning(ofile
, "offset in "
2314 "archive not a multiple of 8) (must be since "
2315 "member is a 64-bit object file)");
2316 archive_64_bit_align_warning
= TRUE
;
2319 #endif /* ALIGNMENT_CHECKS_ARCHIVE_64_BIT */
2320 ofile
->member_type
= OFILE_Mach_O
;
2321 ofile
->object_addr
= ofile
->member_addr
;
2322 ofile
->object_size
= ofile
->member_size
;
2323 if(magic
== MH_MAGIC_64
)
2324 ofile
->object_byte_sex
= host_byte_sex
;
2326 ofile
->object_byte_sex
=
2327 host_byte_sex
== BIG_ENDIAN_BYTE_SEX
?
2328 LITTLE_ENDIAN_BYTE_SEX
: BIG_ENDIAN_BYTE_SEX
;
2329 ofile
->mh64
= (struct mach_header_64
*)
2331 ofile
->load_commands
= (struct load_command
*)
2332 (ofile
->object_addr
+sizeof(struct mach_header_64
));
2333 if(check_Mach_O(ofile
) == CHECK_BAD
)
2338 if(ofile
->member_type
== OFILE_UNKNOWN
&&
2339 is_llvm_bitcode(ofile
, ofile
->member_addr
,
2340 ofile
->member_size
) == TRUE
){
2341 ofile
->member_type
= OFILE_LLVM_BITCODE
;
2342 ofile
->object_addr
= ofile
->member_addr
;
2343 ofile
->object_size
= ofile
->member_size
;
2345 #endif /* LTO_SUPPORT */
2348 offset
+= rnd(strtoul(ar_hdr
->ar_size
, NULL
, 10),
2351 archive_error(ofile
, "does not contain a member named: %s",
2354 ofile
->fat_header
= NULL
;
2355 ofile
->fat_archs
= NULL
;
2357 ofile
->member_offset
= 0;
2358 ofile
->member_addr
= NULL
;
2359 ofile
->member_size
= 0;
2360 ofile
->member_ar_hdr
= NULL
;
2361 ofile
->member_name
= NULL
;
2362 ofile
->member_name_size
= 0;
2363 ofile
->member_type
= OFILE_UNKNOWN
;
2364 ofile
->object_addr
= NULL
;
2365 ofile
->object_size
= 0;
2366 ofile
->object_byte_sex
= UNKNOWN_BYTE_SEX
;
2369 ofile
->load_commands
= NULL
;
2372 ofile
->lto_cputype
= 0;
2373 ofile
->lto_cpusubtype
= 0;
2374 #endif /* LTO_SUPPORT */
2379 * ofile_first_module() set up the ofile structure (the dylib_module field)
2380 * for the first module of an MH_DYLIB or MH_DYLIB_STUB file.
2385 struct ofile
*ofile
)
2388 struct symtab_command
*st
;
2389 struct dysymtab_command
*dyst
;
2390 struct load_command
*lc
;
2392 enum byte_sex host_byte_sex
;
2393 struct dylib_module m
;
2394 struct dylib_module_64 m64
;
2397 /* These fields are to be filled in by this routine, clear them first */
2398 ofile
->modtab
= NULL
;
2399 ofile
->modtab64
= NULL
;
2401 ofile
->dylib_module
= NULL
;
2402 ofile
->dylib_module64
= NULL
;
2403 ofile
->dylib_module_name
= NULL
;
2405 if(ofile
->file_type
== OFILE_FAT
){
2406 if(ofile
->arch_type
!= OFILE_Mach_O
&&
2407 (ofile
->mh_filetype
!= MH_DYLIB
&&
2408 ofile
->mh_filetype
!= MH_DYLIB_STUB
)){
2409 error("ofile_first_module() called on fat file: %s with a "
2410 "non-MH_DYLIB architecture or no architecture selected\n",
2415 else 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 and file type of %s is "
2419 "non-MH_DYLIB\n", ofile
->file_name
);
2425 lc
= ofile
->load_commands
;
2426 if(ofile
->mh
!= NULL
)
2427 ncmds
= ofile
->mh
->ncmds
;
2429 ncmds
= ofile
->mh64
->ncmds
;
2430 for(i
= 0; i
< ncmds
; i
++){
2431 if(st
== NULL
&& lc
->cmd
== LC_SYMTAB
){
2432 st
= (struct symtab_command
*)lc
;
2434 else if(lc
->cmd
== LC_DYSYMTAB
){
2435 dyst
= (struct dysymtab_command
*)lc
;
2437 lc
= (struct load_command
*)((char *)lc
+ lc
->cmdsize
);
2439 if(st
== NULL
|| dyst
== NULL
){
2441 Mach_O_error(ofile
, "MH_DYLIB format error (does not have a symbol "
2442 "table and/or a dynamic symbol table)");
2446 if(dyst
->nmodtab
== 0)
2449 ofile
->nmodtab
= dyst
->nmodtab
;
2450 host_byte_sex
= get_host_byte_sex();
2451 swapped
= (enum bool)(host_byte_sex
!= ofile
->object_byte_sex
);
2452 strings
= (char *)(ofile
->object_addr
+ st
->stroff
);
2454 if(ofile
->mh
!= NULL
){
2455 ofile
->modtab
= (struct dylib_module
*)(ofile
->object_addr
+
2457 ofile
->dylib_module
= ofile
->modtab
;
2458 m
= *ofile
->dylib_module
;
2460 swap_dylib_module(&m
, 1, host_byte_sex
);
2461 ofile
->dylib_module_name
= strings
+ m
.module_name
;
2464 ofile
->modtab64
= (struct dylib_module_64
*)(ofile
->object_addr
+
2466 ofile
->dylib_module64
= ofile
->modtab64
;
2467 m64
= *ofile
->dylib_module64
;
2469 swap_dylib_module_64(&m64
, 1, host_byte_sex
);
2470 ofile
->dylib_module_name
= strings
+ m64
.module_name
;
2473 if(check_dylib_module(ofile
, st
, dyst
, strings
, 0) == CHECK_BAD
)
2479 * ofile_next_module() set up the ofile structure (the dylib_module field)
2480 * for the next module of an MH_DYLIB or MH_DYLIB_STUB file.
2485 struct ofile
*ofile
)
2487 uint32_t i
, module_index
, ncmds
;
2488 struct symtab_command
*st
;
2489 struct dysymtab_command
*dyst
;
2490 struct load_command
*lc
;
2492 enum byte_sex host_byte_sex
;
2493 struct dylib_module m
;
2494 struct dylib_module_64 m64
;
2497 if(ofile
->file_type
== OFILE_FAT
){
2498 if(ofile
->arch_type
!= OFILE_Mach_O
&&
2499 (ofile
->mh_filetype
!= MH_DYLIB
&&
2500 ofile
->mh_filetype
!= MH_DYLIB_STUB
)){
2501 error("ofile_next_module() called on fat file: %s with a "
2502 "non-MH_DYLIB architecture or no architecture selected\n",
2507 else 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 and file type of %s is "
2511 "non-MH_DYLIB\n", ofile
->file_name
);
2516 lc
= ofile
->load_commands
;
2517 if(ofile
->mh
!= NULL
)
2518 ncmds
= ofile
->mh
->ncmds
;
2520 ncmds
= ofile
->mh64
->ncmds
;
2521 for(i
= 0; i
< ncmds
; i
++){
2522 if(st
== NULL
&& lc
->cmd
== LC_SYMTAB
){
2523 st
= (struct symtab_command
*)lc
;
2525 else if(lc
->cmd
== LC_DYSYMTAB
){
2526 dyst
= (struct dysymtab_command
*)lc
;
2528 lc
= (struct load_command
*)((char *)lc
+ lc
->cmdsize
);
2530 if(st
== NULL
|| dyst
== NULL
){
2532 Mach_O_error(ofile
, "MH_DYLIB format error (does not have a symbol "
2533 "table and/or a dynamic symbol table)");
2538 if(ofile
->mh
!= NULL
)
2539 module_index
= (ofile
->dylib_module
+ 1) - ofile
->modtab
;
2541 module_index
= (ofile
->dylib_module64
+ 1) - ofile
->modtab64
;
2542 if(module_index
>= ofile
->nmodtab
)
2545 host_byte_sex
= get_host_byte_sex();
2546 swapped
= (enum bool)(host_byte_sex
!= ofile
->object_byte_sex
);
2547 strings
= (char *)(ofile
->object_addr
+ st
->stroff
);
2549 if(ofile
->mh
!= NULL
){
2550 ofile
->dylib_module
++;
2551 m
= *ofile
->dylib_module
;
2553 swap_dylib_module(&m
, 1, host_byte_sex
);
2554 ofile
->dylib_module_name
= strings
+ m
.module_name
;
2557 ofile
->dylib_module64
++;
2558 m64
= *ofile
->dylib_module64
;
2560 swap_dylib_module_64(&m64
, 1, host_byte_sex
);
2561 ofile
->dylib_module_name
= strings
+ m64
.module_name
;
2563 if(check_dylib_module(ofile
, st
, dyst
, strings
, module_index
) ==
2570 * ofile_specific_module() set up the ofile structure (the dylib_module fields)
2571 * for the specified module, module_name, of an MH_DYLIB or an MH_DYLIB_STUB
2576 ofile_specific_module(
2577 const char *module_name
,
2578 struct ofile
*ofile
)
2582 enum byte_sex host_byte_sex
;
2583 struct symtab_command
*st
;
2584 struct dysymtab_command
*dyst
;
2585 struct load_command
*lc
;
2586 struct dylib_module
*p
, m
;
2587 struct dylib_module_64
*p64
, m64
;
2590 /* These fields are to be filled in by this routine, clear them first */
2591 ofile
->modtab
= NULL
;
2592 ofile
->modtab64
= NULL
;
2594 ofile
->dylib_module
= NULL
;
2595 ofile
->dylib_module64
= NULL
;
2596 ofile
->dylib_module_name
= NULL
;
2598 if(ofile
->file_type
== OFILE_FAT
){
2599 if(ofile
->arch_type
!= OFILE_Mach_O
&&
2600 (ofile
->mh_filetype
!= MH_DYLIB
&&
2601 ofile
->mh_filetype
!= MH_DYLIB_STUB
)){
2602 error("ofile_specific_module() called on fat file: %s with a "
2603 "non-MH_DYLIB architecture or no architecture selected\n",
2608 else 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 and file type of %s is "
2612 "non-MH_DYLIB\n", ofile
->file_name
);
2618 lc
= ofile
->load_commands
;
2619 if(ofile
->mh
!= NULL
)
2620 ncmds
= ofile
->mh
->ncmds
;
2622 ncmds
= ofile
->mh64
->ncmds
;
2623 for(i
= 0; i
< ncmds
; i
++){
2624 if(st
== NULL
&& lc
->cmd
== LC_SYMTAB
){
2625 st
= (struct symtab_command
*)lc
;
2627 else if(lc
->cmd
== LC_DYSYMTAB
){
2628 dyst
= (struct dysymtab_command
*)lc
;
2630 lc
= (struct load_command
*)((char *)lc
+ lc
->cmdsize
);
2632 if(st
== NULL
|| dyst
== NULL
){
2634 Mach_O_error(ofile
, "MH_DYLIB format error (does not have a symbol "
2635 "table and/or a dynamic symbol table)");
2639 if(dyst
->nmodtab
== 0)
2642 host_byte_sex
= get_host_byte_sex();
2643 swapped
= (enum bool)(host_byte_sex
!= ofile
->object_byte_sex
);
2644 strings
= (char *)(ofile
->object_addr
+ st
->stroff
);
2646 if(ofile
->mh
!= NULL
){
2647 ofile
->nmodtab
= dyst
->nmodtab
;
2648 ofile
->modtab
= (struct dylib_module
*)(ofile
->object_addr
+
2651 for(i
= 0; i
< dyst
->nmodtab
; i
++){
2654 swap_dylib_module(&m
, 1, host_byte_sex
);
2655 ofile
->dylib_module
= p
;
2656 if(check_dylib_module(ofile
, st
, dyst
, strings
, i
) == CHECK_BAD
)
2658 if(strcmp(module_name
, strings
+ m
.module_name
) == 0){
2659 ofile
->dylib_module_name
= strings
+ m
.module_name
;
2664 m
= *ofile
->dylib_module
;
2666 swap_dylib_module(&m
, 1, host_byte_sex
);
2667 ofile
->dylib_module_name
= strings
+ m
.module_name
;
2670 ofile
->nmodtab
= dyst
->nmodtab
;
2671 ofile
->modtab64
= (struct dylib_module_64
*)(ofile
->object_addr
+
2673 p64
= ofile
->modtab64
;
2674 for(i
= 0; i
< dyst
->nmodtab
; i
++){
2677 swap_dylib_module_64(&m64
, 1, host_byte_sex
);
2678 ofile
->dylib_module64
= p64
;
2679 if(check_dylib_module(ofile
, st
, dyst
, strings
, i
) == CHECK_BAD
)
2681 if(strcmp(module_name
, strings
+ m64
.module_name
) == 0){
2682 ofile
->dylib_module_name
= strings
+ m64
.module_name
;
2687 m64
= *ofile
->dylib_module64
;
2689 swap_dylib_module_64(&m64
, 1, host_byte_sex
);
2690 ofile
->dylib_module_name
= strings
+ m64
.module_name
;
2693 Mach_O_error(ofile
, "does not contain a module named: %s", module_name
);
2695 ofile
->modtab
= NULL
;
2697 ofile
->dylib_module
= NULL
;
2698 ofile
->dylib_module_name
= NULL
;
2706 struct ofile
*ofile
)
2708 printf("file_name = %s\n", ofile
->file_name
);
2709 printf("file_addr = 0x%x\n", (unsigned int)ofile
->file_addr
);
2710 printf("file_size = 0x%x\n", (unsigned int)ofile
->file_size
);
2711 printf("file_type = 0x%x\n", (unsigned int)ofile
->file_type
);
2712 printf("fat_header = 0x%x\n", (unsigned int)ofile
->fat_header
);
2713 printf("fat_archs = 0x%x\n", (unsigned int)ofile
->fat_archs
);
2714 printf("narch = 0x%x\n", (unsigned int)ofile
->narch
);
2715 printf("arch_type = 0x%x\n", (unsigned int)ofile
->arch_type
);
2716 printf("arch_flag.name = %s\n", ofile
->arch_flag
.name
);
2717 printf("arch_flag.cputype = 0x%x\n",
2718 (unsigned int)ofile
->arch_flag
.cputype
);
2719 printf("arch_flag.cpusubtype = 0x%x\n",
2720 (unsigned int)ofile
->arch_flag
.cpusubtype
);
2721 printf("member_offset = 0x%x\n", (unsigned int)ofile
->member_offset
);
2722 printf("member_addr = 0x%x\n", (unsigned int)ofile
->member_addr
);
2723 printf("member_size = 0x%x\n", (unsigned int)ofile
->member_size
);
2724 printf("member_ar_hdr = 0x%x\n", (unsigned int)ofile
->member_ar_hdr
);
2725 printf("member_type = 0x%x\n", (unsigned int)ofile
->member_type
);
2726 printf("archive_cputype = 0x%x\n",
2727 (unsigned int)ofile
->archive_cputype
);
2728 printf("archive_cpusubtype = 0x%x\n",
2729 (unsigned int)ofile
->archive_cpusubtype
);
2730 printf("object_addr = 0x%x\n", (unsigned int)ofile
->object_addr
);
2731 printf("object_size = 0x%x\n", (unsigned int)ofile
->object_size
);
2732 printf("object_byte_sex = 0x%x\n",
2733 (unsigned int)ofile
->object_byte_sex
);
2734 printf("mh = 0x%x\n", (unsigned int)ofile
->mh
);
2735 printf("mh64 = 0x%x\n", (unsigned int)ofile
->mh64
);
2736 printf("load_commands = 0x%x\n", (unsigned int)ofile
->load_commands
);
2741 * check_fat() checks the fat ofile for correctness (the fat_header and
2742 * fat_archs are assumed to be in the host byte sex).
2747 struct ofile
*ofile
)
2751 #else /* !defined OTOOL */
2756 if(ofile
->file_type
!= OFILE_FAT
){
2757 error("internal error. check_fat() call and file type of: %s is "
2758 "not OFILE_FAT\n", ofile
->file_name
);
2761 if(ofile
->fat_header
->nfat_arch
== 0){
2762 error("fat file: %s malformed (contains zero architecture types)",
2766 for(i
= 0; i
< ofile
->fat_header
->nfat_arch
; i
++){
2767 big_size
= ofile
->fat_archs
[i
].offset
;
2768 big_size
+= ofile
->fat_archs
[i
].size
;
2769 if(big_size
> ofile
->file_size
){
2770 error("fat file: %s truncated or malformed (offset plus size "
2771 "of cputype (%d) cpusubtype (%d) extends past the "
2772 "end of the file)", ofile
->file_name
,
2773 ofile
->fat_archs
[i
].cputype
,
2774 ofile
->fat_archs
[i
].cpusubtype
& ~CPU_SUBTYPE_MASK
);
2777 if(ofile
->fat_archs
[i
].align
> MAXSECTALIGN
){
2778 error("fat file: %s align (2^%u) too large for cputype (%d) "
2779 "cpusubtype (%d) (maximum 2^%d)", ofile
->file_name
,
2780 ofile
->fat_archs
[i
].align
, ofile
->fat_archs
[i
].cputype
,
2781 ofile
->fat_archs
[i
].cpusubtype
& ~CPU_SUBTYPE_MASK
,
2785 if(ofile
->fat_archs
[i
].offset
%
2786 (1 << ofile
->fat_archs
[i
].align
) != 0){
2787 error("fat file: %s offset: %u for cputype (%d) cpusubtype "
2788 "(%d)) not aligned on it's alignment (2^%u)",
2790 ofile
->fat_archs
[i
].offset
,
2791 ofile
->fat_archs
[i
].cputype
,
2792 ofile
->fat_archs
[i
].cpusubtype
& ~CPU_SUBTYPE_MASK
,
2793 ofile
->fat_archs
[i
].align
);
2797 for(i
= 0; i
< ofile
->fat_header
->nfat_arch
; i
++){
2798 for(j
= i
+ 1; j
< ofile
->fat_header
->nfat_arch
; j
++){
2799 if(ofile
->fat_archs
[i
].cputype
==
2800 ofile
->fat_archs
[j
].cputype
&&
2801 (ofile
->fat_archs
[i
].cpusubtype
& ~CPU_SUBTYPE_MASK
) ==
2802 (ofile
->fat_archs
[j
].cpusubtype
& ~CPU_SUBTYPE_MASK
)){
2803 error("fat file: %s contains two of the same "
2804 "architecture (cputype (%d) cpusubtype (%d))",
2805 ofile
->file_name
, ofile
->fat_archs
[i
].cputype
,
2806 ofile
->fat_archs
[i
].cpusubtype
& ~CPU_SUBTYPE_MASK
);
2816 * check_fat_object_in_archive() checks the fat object file which is a member
2817 * of a thin archive for correctness (the fat_header and fat_archs are assumed
2818 * to be in the host byte sex). This is not a legal form but allowed when
2819 * archives_with_fat_objects is TRUE when ofile_map() is called.
2823 check_fat_object_in_archive(
2824 struct ofile
*ofile
)
2829 if(ofile
->file_type
!= OFILE_ARCHIVE
){
2830 error("internal error. check_fat_object_in_archive() called and "
2831 "file type of: %s is not OFILE_ARCHIVE\n", ofile
->file_name
);
2834 if(ofile
->fat_header
->nfat_arch
== 0){
2835 archive_member_error(ofile
, "fat file malformed (contains zero "
2836 "architecture types)");
2839 for(i
= 0; i
< ofile
->fat_header
->nfat_arch
; i
++){
2840 if(ofile
->fat_archs
[i
].offset
+ ofile
->fat_archs
[i
].size
>
2841 ofile
->member_size
){
2842 archive_member_error(ofile
, "fat file truncated or malformed "
2843 "(offset plus size of cputype (%d) cpusubtype (%d) "
2844 "extends past the end of the file)",
2845 ofile
->fat_archs
[i
].cputype
,
2846 ofile
->fat_archs
[i
].cpusubtype
& ~CPU_SUBTYPE_MASK
);
2849 if(ofile
->fat_archs
[i
].align
> MAXSECTALIGN
){
2850 archive_member_error(ofile
, "fat file's align (2^%u) too "
2851 "large for cputype (%d) cpusubtype (%d) (maximum 2^%d)",
2852 ofile
->fat_archs
[i
].align
, ofile
->fat_archs
[i
].cputype
,
2853 ofile
->fat_archs
[i
].cpusubtype
& ~CPU_SUBTYPE_MASK
,
2857 if(ofile
->fat_archs
[i
].offset
%
2858 (1 << ofile
->fat_archs
[i
].align
) != 0){
2859 archive_member_error(ofile
, "fat file's offset: %u for "
2860 "cputype (%d) cpusubtype (%d) not aligned on it's "
2861 "alignment (2^%u)", ofile
->fat_archs
[i
].offset
,
2862 ofile
->fat_archs
[i
].cputype
,
2863 ofile
->fat_archs
[i
].cpusubtype
& ~CPU_SUBTYPE_MASK
,
2864 ofile
->fat_archs
[i
].align
);
2869 * The only supported format where fat files are allowed to appear
2870 * in archives is when the fat file contains only object files.
2872 if(ofile
->fat_archs
[i
].size
< sizeof(struct mach_header
)){
2873 archive_member_error(ofile
, "fat file for cputype (%d) "
2874 "cpusubtype (%d) is not an object file (size too small "
2875 "to be an object file)", ofile
->fat_archs
[i
].cputype
,
2876 ofile
->fat_archs
[i
].cpusubtype
& ~CPU_SUBTYPE_MASK
);
2880 ofile
->file_addr
+ ofile
->member_offset
+
2881 ofile
->fat_archs
[i
].offset
,
2883 if(magic
== MH_MAGIC
|| magic
== SWAP_INT(MH_MAGIC
)){
2884 #ifdef ALIGNMENT_CHECKS
2885 if((ofile
->member_offset
+ ofile
->fat_archs
[i
].offset
) %
2887 archive_member_error(ofile
, "fat object file's offset in "
2888 "archive not a multiple of 4) (must be since "
2889 "member is a 32-bit object file)");
2892 #endif /* ALIGNMENT_CHECKS */
2894 else if(magic
== MH_MAGIC_64
|| magic
== SWAP_INT(MH_MAGIC_64
)){
2895 #ifdef ALIGNMENT_CHECKS_ARCHIVE_64_BIT
2896 if(archive_64_bit_align_warning
== FALSE
&&
2897 (ofile
->member_offset
+ ofile
->fat_archs
[i
].offset
) %
2899 temporary_archive_member_warning(ofile
, "fat object file's "
2900 "offset in archive not a multiple of 8) (must be since "
2901 "member is a 64-bit object file)");
2902 archive_64_bit_align_warning
= TRUE
;
2903 /* return(CHECK_BAD); */
2905 #endif /* ALIGNMENT_CHECKS_ARCHIVE_64_BIT */
2908 archive_member_error(ofile
, "fat file for cputype (%d) "
2909 "cpusubtype (%d) is not an object file (bad magic "
2910 "number)", ofile
->fat_archs
[i
].cputype
,
2911 ofile
->fat_archs
[i
].cpusubtype
& ~CPU_SUBTYPE_MASK
);
2915 for(i
= 0; i
< ofile
->fat_header
->nfat_arch
; i
++){
2916 for(j
= i
+ 1; j
< ofile
->fat_header
->nfat_arch
; j
++){
2917 if(ofile
->fat_archs
[i
].cputype
==
2918 ofile
->fat_archs
[j
].cputype
&&
2919 (ofile
->fat_archs
[i
].cpusubtype
& ~CPU_SUBTYPE_MASK
) ==
2920 (ofile
->fat_archs
[j
].cpusubtype
& ~CPU_SUBTYPE_MASK
)){
2921 archive_member_error(ofile
, "fat file contains two of the "
2922 "same architecture (cputype (%d) cpusubtype (%d))",
2923 ofile
->fat_archs
[i
].cputype
,
2924 ofile
->fat_archs
[i
].cpusubtype
& ~CPU_SUBTYPE_MASK
);
2933 * check_archive() checks the archive referenced in the ofile for correctness.
2938 struct ofile
*ofile
,
2939 enum bool archives_with_fat_objects
)
2943 #else /* !defined OTOOL */
2945 uint32_t size
, offset
;
2948 enum byte_sex host_byte_sex
;
2950 struct mach_header mh
;
2951 struct mach_header_64 mh64
;
2952 struct ar_hdr
*ar_hdr
;
2953 uint32_t ar_name_size
;
2956 * Get the address and size of the archive (as well as the cputype and
2957 * cpusubtype if known) and make sure it is an archive.
2959 if(ofile
->file_type
== OFILE_FAT
){
2960 addr
= ofile
->file_addr
+ ofile
->fat_archs
[ofile
->narch
].offset
;
2961 size
= ofile
->fat_archs
[ofile
->narch
].size
;
2962 ofile
->archive_cputype
= ofile
->fat_archs
[ofile
->narch
].cputype
;
2963 ofile
->archive_cpusubtype
=
2964 ofile
->fat_archs
[ofile
->narch
].cpusubtype
;
2966 else if(ofile
->file_type
== OFILE_ARCHIVE
){
2967 addr
= ofile
->file_addr
;
2968 size
= ofile
->file_size
;
2969 ofile
->archive_cputype
= 0;
2970 ofile
->archive_cpusubtype
= 0;
2973 error("internal error. check_archive() call and file type of %s is "
2974 "OFILE_UNKNOWN\n", ofile
->file_name
);
2977 if(size
< SARMAG
|| strncmp(addr
, ARMAG
, SARMAG
) != 0){
2978 error("internal error. check_archive() call for file %s which does "
2979 "not have an archive magic string", ofile
->file_name
);
2983 host_byte_sex
= get_host_byte_sex();
2985 * Check this archive out to make sure that it does not contain
2986 * any fat files and that all object files it contains have the
2987 * same cputype and subsubtype.
2992 if(offset
!= size
&& offset
+ sizeof(struct ar_hdr
) > size
){
2993 archive_error(ofile
, "truncated or malformed (archive header of "
2994 "first member extends past the end of the file)");
2997 while(size
> offset
){
2998 ar_hdr
= (struct ar_hdr
*)(addr
+ offset
);
2999 ofile
->member_offset
= offset
;
3000 ofile
->member_addr
= addr
+ offset
;
3001 ofile
->member_size
= strtoul(ar_hdr
->ar_size
, NULL
, 10);
3002 ofile
->member_ar_hdr
= ar_hdr
;
3003 ofile
->member_name
= ar_hdr
->ar_name
;
3004 ofile
->member_name_size
= size_ar_name(ofile
->member_ar_hdr
);
3005 offset
+= sizeof(struct ar_hdr
);
3007 * See if this archive member is using extend format #1 where
3008 * the size of the name is in ar_name and the name follows the
3012 if(strncmp(ofile
->member_name
,AR_EFMT1
, sizeof(AR_EFMT1
) - 1) == 0){
3013 if(check_extend_format_1(ofile
, ar_hdr
, size
- offset
,
3014 &ar_name_size
) == CHECK_BAD
)
3016 ofile
->member_name
= ar_hdr
->ar_name
+ sizeof(struct ar_hdr
);
3017 ofile
->member_name_size
= ar_name_size
;
3018 offset
+= ar_name_size
;
3019 ofile
->member_offset
+= ar_name_size
;
3020 ofile
->member_addr
+= ar_name_size
;
3021 ofile
->member_size
-= ar_name_size
;
3023 big_size
= rnd(ofile
->member_size
, sizeof(short));
3025 if(big_size
> size
){
3026 archive_member_error(ofile
, "size too large (archive "
3027 "member extends past the end of the file)");
3030 if(size
- offset
> sizeof(uint32_t)){
3031 memcpy(&magic
, addr
+ offset
, sizeof(uint32_t));
3032 #ifdef __BIG_ENDIAN__
3033 if(magic
== FAT_MAGIC
)
3034 #endif /* __BIG_ENDIAN__ */
3035 #ifdef __LITTLE_ENDIAN__
3036 if(magic
== SWAP_INT(FAT_MAGIC
))
3037 #endif /* __LITTLE_ENDIAN__ */
3039 if(archives_with_fat_objects
== FALSE
||
3040 ofile
->file_type
!= OFILE_ARCHIVE
){
3041 archive_member_error(ofile
, "is a fat file (not "
3042 "allowed in an archive)");
3047 if(size
- offset
>= sizeof(struct mach_header
) &&
3048 (magic
== MH_MAGIC
|| magic
== SWAP_INT(MH_MAGIC
))){
3049 memcpy(&mh
, addr
+ offset
, sizeof(struct mach_header
));
3050 if(magic
== SWAP_INT(MH_MAGIC
)){
3053 swap_mach_header(&mh
, host_byte_sex
);
3057 else if(size
- offset
>= sizeof(struct mach_header_64
) &&
3058 (magic
== MH_MAGIC_64
||
3059 magic
== SWAP_INT(MH_MAGIC_64
))){
3060 memcpy(&mh64
, addr
+ offset
,
3061 sizeof(struct mach_header_64
));
3062 if(magic
== SWAP_INT(MH_MAGIC_64
)){
3063 magic
= MH_MAGIC_64
;
3065 swap_mach_header_64(&mh64
, host_byte_sex
);
3069 if(magic
== MH_MAGIC
){
3070 if(ofile
->archive_cputype
== 0){
3071 ofile
->archive_cputype
= mh
.cputype
;
3072 ofile
->archive_cpusubtype
= mh
.cpusubtype
;
3074 else if(ofile
->archive_cputype
!= mh
.cputype
){
3075 archive_member_error(ofile
, "cputype (%d) does not "
3076 "match previous archive members cputype (%d) "
3077 "(all members must match)", mh
.cputype
,
3078 ofile
->archive_cputype
);
3081 else if(magic
== MH_MAGIC_64
){
3082 if(ofile
->archive_cputype
== 0){
3083 ofile
->archive_cputype
= mh64
.cputype
;
3084 ofile
->archive_cpusubtype
= mh64
.cpusubtype
;
3086 else if(ofile
->archive_cputype
!= mh64
.cputype
){
3087 archive_member_error(ofile
, "cputype (%d) does not "
3088 "match previous archive members cputype (%d) "
3089 "(all members must match)", mh64
.cputype
,
3090 ofile
->archive_cputype
);
3095 offset
+= rnd(ofile
->member_size
, sizeof(short));
3097 ofile
->member_offset
= 0;
3098 ofile
->member_addr
= NULL
;
3099 ofile
->member_size
= 0;
3100 ofile
->member_ar_hdr
= NULL
;;
3101 ofile
->member_name
= NULL
;
3102 ofile
->member_name_size
= 0;
3108 * check_extend_format_1() checks the archive header for extended format #1.
3112 check_extend_format_1(
3113 struct ofile
*ofile
,
3114 struct ar_hdr
*ar_hdr
,
3116 uint32_t *member_name_size
)
3118 char *p
, *endp
, buf
[sizeof(ar_hdr
->ar_name
)+1];
3119 uint32_t ar_name_size
;
3121 *member_name_size
= 0;
3123 buf
[sizeof(ar_hdr
->ar_name
)] = '\0';
3124 memcpy(buf
, ar_hdr
->ar_name
, sizeof(ar_hdr
->ar_name
));
3125 p
= buf
+ sizeof(AR_EFMT1
) - 1;
3126 if(isdigit(*p
) == 0){
3127 archive_error(ofile
, "malformed (ar_name: %.*s for archive "
3128 "extend format #1 starts with non-digit)",
3129 (int)sizeof(ar_hdr
->ar_name
), ar_hdr
->ar_name
);
3132 ar_name_size
= strtoul(p
, &endp
, 10);
3133 if(ar_name_size
== UINT_MAX
&& errno
== ERANGE
){
3134 archive_error(ofile
, "malformed (size in ar_name: %.*s for "
3135 "archive extend format #1 overflows uint32_t)",
3136 (int)sizeof(ar_hdr
->ar_name
), ar_hdr
->ar_name
);
3139 while(*endp
== ' ' && *endp
!= '\0')
3142 archive_error(ofile
, "malformed (size in ar_name: %.*s for "
3143 "archive extend format #1 contains non-digit and "
3144 "non-space characters)", (int)sizeof(ar_hdr
->ar_name
),
3148 if(ar_name_size
> size_left
){
3149 archive_error(ofile
, "truncated or malformed (archive name "
3150 "of member extends past the end of the file)");
3153 *member_name_size
= ar_name_size
;
3158 * check_archive_toc() checks the archive table of contents referenced in the
3159 * thin archive via the ofile for correctness and if bad sets the bad_toc field
3160 * in the ofile struct to TRUE. If not it sets the other toc_* fields that
3161 * ranlib(1) uses to know it can't update the table of contents and doesn't
3162 * have to totally rebuild it. And by this always returning CHECK_GOOD it
3163 * allows otool(1) to print messed up tables of contents for debugging.
3168 struct ofile
*ofile
)
3170 uint32_t i
, symdef_length
, offset
, nranlibs
, strsize
;
3171 enum byte_sex host_byte_sex
, toc_byte_sex
;
3172 struct ranlib
*ranlibs
;
3175 ofile
->toc_ranlibs
= NULL
;
3176 ofile
->toc_nranlibs
= 0;
3177 ofile
->toc_strings
= NULL
;
3178 ofile
->toc_strsize
= 0;
3181 * Note this can only be called when the whole file is a thin archive.
3183 if(ofile
->file_type
!= OFILE_ARCHIVE
)
3186 symdef_length
= ofile
->toc_size
;
3188 * The contents of a __.SYMDEF file is begins with a 32-bit word giving
3189 * the size in bytes of ranlib structures which immediately follow, and
3190 * then continues with a string table consisting of a 32-bit word giving
3191 * the number of bytes of strings which follow and then the strings
3192 * themselves. So the smallest valid size is two 32-bit words long.
3194 if(symdef_length
< 2 * sizeof(uint32_t)){
3196 * Size of table of contents for archive too small to be a valid
3197 * table of contents.
3199 ofile
->toc_bad
= TRUE
;
3202 host_byte_sex
= get_host_byte_sex();
3203 toc_byte_sex
= get_toc_byte_sex(ofile
->file_addr
, ofile
->file_size
);
3204 if(toc_byte_sex
== UNKNOWN_BYTE_SEX
){
3206 * Can't determine the byte order of table of contents as it
3207 * contains no Mach-O files.
3209 ofile
->toc_bad
= TRUE
;
3213 nranlibs
= *((uint32_t *)(ofile
->toc_addr
+ offset
));
3214 if(toc_byte_sex
!= host_byte_sex
)
3215 nranlibs
= SWAP_INT(nranlibs
);
3216 nranlibs
= nranlibs
/ sizeof(struct ranlib
);
3217 offset
+= sizeof(uint32_t);
3218 ranlibs
= (struct ranlib
*)(ofile
->toc_addr
+ offset
);
3219 offset
+= sizeof(struct ranlib
) * nranlibs
;
3222 if(offset
- (2 * sizeof(uint32_t)) > symdef_length
){
3224 * Truncated or malformed archive. The ranlib structures in table
3225 * of contents extends past the end of the table of contents.
3227 ofile
->toc_bad
= TRUE
;
3230 strsize
= *((uint32_t *)(ofile
->toc_addr
+ offset
));
3231 if(toc_byte_sex
!= host_byte_sex
)
3232 strsize
= SWAP_INT(strsize
);
3233 offset
+= sizeof(uint32_t);
3234 strings
= ofile
->toc_addr
+ offset
;
3236 if(offset
- (2 * sizeof(uint32_t)) > symdef_length
){
3238 * Truncated or malformed archive. The ranlib strings in table of
3239 * contents extends past the end of the table of contents.
3241 ofile
->toc_bad
= TRUE
;
3244 if(symdef_length
== 2 * sizeof(uint32_t))
3248 * Check the string offset and the member offsets of the ranlib structs.
3250 if(toc_byte_sex
!= host_byte_sex
)
3251 swap_ranlib(ranlibs
, nranlibs
, host_byte_sex
);
3252 for(i
= 0; i
< nranlibs
; i
++){
3253 if(ranlibs
[i
].ran_un
.ran_strx
>= strsize
){
3255 * Malformed table of contents. The ranlib struct at this index
3256 * has a bad string index field.
3258 ofile
->toc_bad
= TRUE
;
3261 if(ranlibs
[i
].ran_off
>= ofile
->file_size
){
3263 * Malformed table of contents. The ranlib struct at this index
3264 * has a bad library member offset field.
3266 ofile
->toc_bad
= TRUE
;
3270 * These should be on 4 byte boundaries because the maximum
3271 * alignment of the header structures and relocation are 4 bytes.
3272 * But this is has to be 2 bytes because that's the way ar(1) has
3273 * worked historicly in the past. Fortunately this works on the
3274 * 68k machines but will have to change when this is on a real
3277 #if defined(mc68000) || defined(__i386__)
3278 if(ranlibs
[i
].ran_off
% sizeof(short) != 0){
3280 * Malformed table of contents. This ranlib struct library
3281 * member offset not a multiple 2 bytes.
3283 ofile
->toc_bad
= TRUE
;
3287 if(ranlibs
[i
].ran_off
% sizeof(uint32_t) != 0){
3289 * Malformed table of contents. This ranlib struct library
3290 * member offset not a multiple of 4 bytes.
3292 ofile
->toc_bad
= TRUE
;
3297 ofile
->toc_ranlibs
= ranlibs
;
3298 ofile
->toc_nranlibs
= nranlibs
;
3299 ofile
->toc_strings
= strings
;
3300 ofile
->toc_strsize
= strsize
;
3305 * check_Mach_O() checks the object file's mach header and load commands
3306 * referenced in the ofile for correctness (this also swaps the mach header
3307 * and load commands into the host byte sex if needed).
3312 struct ofile
*ofile
)
3316 #else /* !defined OTOOL */
3317 uint32_t size
, i
, j
, ncmds
, sizeofcmds
, load_command_multiple
, sizeofhdrs
;
3319 char *addr
, *cmd_name
;
3320 enum byte_sex host_byte_sex
;
3322 struct mach_header
*mh
;
3323 struct mach_header_64
*mh64
;
3324 struct load_command
*load_commands
, *lc
, l
;
3325 struct segment_command
*sg
;
3326 struct segment_command_64
*sg64
;
3328 struct section_64
*s64
;
3329 struct symtab_command
*st
;
3330 struct dysymtab_command
*dyst
;
3331 struct symseg_command
*ss
;
3332 struct fvmlib_command
*fl
;
3333 struct dylib_command
*dl
;
3334 struct sub_framework_command
*sub
;
3335 struct sub_umbrella_command
*usub
;
3336 struct sub_library_command
*lsub
;
3337 struct sub_client_command
*csub
;
3338 struct prebound_dylib_command
*pbdylib
;
3339 struct dylinker_command
*dyld
;
3340 struct thread_command
*ut
;
3341 struct ident_command
*id
;
3342 struct routines_command
*rc
;
3343 struct routines_command_64
*rc64
;
3344 struct twolevel_hints_command
*hints
;
3345 struct linkedit_data_command
*code_sig
, *split_info
, *func_starts
;
3346 struct version_min_command
*vers
;
3347 struct prebind_cksum_command
*cs
;
3348 struct encryption_info_command
*encrypt_info
;
3349 struct dyld_info_command
*dyld_info
;
3350 struct uuid_command
*uuid
;
3351 struct rpath_command
*rpath
;
3352 uint32_t flavor
, count
, nflavor
;
3354 uint32_t sizeof_nlist
, sizeof_dylib_module
;
3355 char *struct_dylib_module_name
, *struct_nlist_name
;
3356 uint64_t big_size
, big_end
, big_load_end
;
3357 struct element elements
;
3359 elements
.offset
= 0;
3361 elements
.name
= NULL
;
3362 elements
.next
= NULL
;
3364 addr
= ofile
->object_addr
;
3365 size
= ofile
->object_size
;
3368 load_commands
= ofile
->load_commands
;
3369 host_byte_sex
= get_host_byte_sex();
3370 swapped
= (enum bool)(host_byte_sex
!= ofile
->object_byte_sex
);
3372 if(ofile
->mh
!= NULL
){
3374 swap_mach_header(mh
, host_byte_sex
);
3375 big_size
= mh
->sizeofcmds
;
3376 big_size
+= sizeof(struct mach_header
);
3377 if(big_size
> size
){
3378 Mach_O_error(ofile
, "truncated or malformed object (load "
3379 "commands extend past the end of the file)");
3382 sizeofhdrs
= big_size
;
3383 ofile
->mh_cputype
= mh
->cputype
;
3384 ofile
->mh_cpusubtype
= mh
->cpusubtype
;
3385 ofile
->mh_filetype
= mh
->filetype
;
3387 sizeofcmds
= mh
->sizeofcmds
;
3388 cputype
= mh
->cputype
;
3389 load_command_multiple
= 4;
3390 sizeof_nlist
= sizeof(struct nlist
);
3391 struct_nlist_name
= "struct nlist";
3392 sizeof_dylib_module
= sizeof(struct dylib_module
);
3393 struct_dylib_module_name
= "struct dylib_module";
3397 swap_mach_header_64(mh64
, host_byte_sex
);
3398 big_size
= mh64
->sizeofcmds
;
3399 big_size
+= sizeof(struct mach_header_64
);
3400 if(big_size
> size
){
3401 Mach_O_error(ofile
, "truncated or malformed object (load "
3402 "commands extend past the end of the file)");
3405 sizeofhdrs
= big_size
;
3406 ofile
->mh_cputype
= mh64
->cputype
;
3407 ofile
->mh_cpusubtype
= mh64
->cpusubtype
;
3408 ofile
->mh_filetype
= mh64
->filetype
;
3409 ncmds
= mh64
->ncmds
;
3410 sizeofcmds
= mh64
->sizeofcmds
;
3411 cputype
= mh64
->cputype
;
3412 load_command_multiple
= 8;
3413 sizeof_nlist
= sizeof(struct nlist_64
);
3414 struct_nlist_name
= "struct nlist_64";
3415 sizeof_dylib_module
= sizeof(struct dylib_module_64
);
3416 struct_dylib_module_name
= "struct dylib_module_64";
3418 if(check_overlaping_element(ofile
, &elements
, 0, sizeofhdrs
,
3419 "Mach-O headers") == CHECK_BAD
)
3421 if(ofile
->file_type
== OFILE_FAT
){
3422 if(ofile
->fat_archs
[ofile
->narch
].cputype
!= ofile
->mh_cputype
){
3423 Mach_O_error(ofile
, "malformed fat file (fat header "
3424 "architecture: %u's cputype does not match "
3425 "object file's mach header)", ofile
->narch
);
3430 * Make a pass through the load commands checking them to the level
3431 * that they can be parsed and all fields with offsets and sizes do
3432 * not extend past the end of the file.
3444 encrypt_info
= NULL
;
3448 for(i
= 0, lc
= load_commands
; i
< ncmds
; i
++){
3451 swap_load_command(&l
, host_byte_sex
);
3453 * Check load command size for a multiple of load_command_multiple.
3455 if(l
.cmdsize
% load_command_multiple
!= 0){
3457 * We have a hack here to allow 64-bit Mach-O core files to
3458 * have LC_THREAD commands that are only a multiple of 4 and
3459 * not 8 to be allowed since the kernel produces them.
3461 if(ofile
->mh64
== NULL
||
3462 ofile
->mh64
->filetype
!= MH_CORE
||
3463 l
.cmd
!= LC_THREAD
||
3464 l
.cmdsize
% 4 != 0){
3465 Mach_O_error(ofile
, "malformed object (load command %u "
3466 "cmdsize not a multiple of %u)", i
,
3467 load_command_multiple
);
3471 /* check that load command does not extends past end of commands */
3472 big_load_end
+= l
.cmdsize
;
3473 if(big_load_end
> sizeofcmds
){
3474 Mach_O_error(ofile
, "truncated or malformed object (load "
3475 "command %u extends past the end of the file)",i
);
3478 /* check that the load command size is not zero */
3480 Mach_O_error(ofile
, "malformed object (load command %u cmdsize"
3486 if(l
.cmdsize
< sizeof(struct segment_command
)){
3487 Mach_O_error(ofile
, "malformed object (LC_SEGMENT cmdsize "
3488 "too small) in command %u", i
);
3491 sg
= (struct segment_command
*)lc
;
3493 swap_segment_command(sg
, host_byte_sex
);
3494 big_size
= sg
->nsects
;
3495 big_size
*= sizeof(struct section
);
3496 big_size
+= sizeof(struct segment_command
);
3497 if(sg
->cmdsize
!= big_size
){
3498 Mach_O_error(ofile
, "malformed object (inconsistent "
3499 "cmdsize in LC_SEGMENT command %u for the "
3500 "number of sections)", i
);
3503 if(sg
->fileoff
> size
){
3504 Mach_O_error(ofile
, "truncated or malformed object ("
3505 "LC_SEGMENT command %u fileoff field "
3506 "extends past the end of the file)", i
);
3509 big_size
= sg
->fileoff
;
3510 big_size
+= sg
->filesize
;
3511 if(big_size
> size
){
3512 Mach_O_error(ofile
, "truncated or malformed object ("
3513 "LC_SEGMENT command %u fileoff field "
3514 "plus filesize field extends past the end of "
3518 if(sg
->vmsize
!= 0 && sg
->filesize
> sg
->vmsize
){
3519 Mach_O_error(ofile
, "malformed object (LC_SEGMENT command "
3520 "%u filesize field greater than vmsize field)",
3524 s
= (struct section
*)
3525 ((char *)sg
+ sizeof(struct segment_command
));
3527 swap_section(s
, sg
->nsects
, host_byte_sex
);
3528 for(j
= 0 ; j
< sg
->nsects
; j
++){
3529 if(mh
->filetype
!= MH_DYLIB_STUB
&&
3530 s
->flags
!= S_ZEROFILL
&&
3531 s
->flags
!= S_THREAD_LOCAL_ZEROFILL
&& s
->offset
> size
){
3532 Mach_O_error(ofile
, "truncated or malformed object "
3533 "(offset field of section %u in LC_SEGMENT "
3534 "command %u extends past the end of the file)",
3538 if(mh
->filetype
!= MH_DYLIB_STUB
&&
3539 s
->flags
!= S_ZEROFILL
&&
3540 s
->flags
!= S_THREAD_LOCAL_ZEROFILL
&&
3541 sg
->fileoff
== 0 && s
->offset
< sizeofhdrs
){
3542 Mach_O_error(ofile
, "malformed object (offset field of "
3543 "section %u in LC_SEGMENT command %u not "
3544 "past the headers of the file)", j
, i
);
3547 big_size
= s
->offset
;
3548 big_size
+= s
->size
;
3549 if(mh
->filetype
!= MH_DYLIB_STUB
&&
3550 s
->flags
!= S_ZEROFILL
&&
3551 s
->flags
!= S_THREAD_LOCAL_ZEROFILL
&& big_size
> size
){
3552 Mach_O_error(ofile
, "truncated or malformed object "
3553 "(offset field plus size field of section %u "
3554 "in LC_SEGMENT command %u extends "
3555 "past the end of the file)", j
, i
);
3558 if(mh
->filetype
!= MH_DYLIB_STUB
&&
3559 s
->flags
!= S_ZEROFILL
&&
3560 s
->flags
!= S_THREAD_LOCAL_ZEROFILL
&&
3561 s
->size
> sg
->filesize
){
3562 Mach_O_error(ofile
, "malformed object (size field of "
3563 "section %u in LC_SEGMENT command %u greater "
3564 "than the segment)", j
, i
);
3567 if(mh
->filetype
!= MH_DYLIB_STUB
&&
3568 s
->size
!= 0 && s
->addr
< sg
->vmaddr
){
3569 Mach_O_error(ofile
, "malformed object (addr field of "
3570 "section %u in LC_SEGMENT command %u less than "
3571 "the segment's vmaddr)", j
, i
);
3575 big_size
+= s
->size
;
3576 big_end
= sg
->vmaddr
;
3577 big_end
+= sg
->vmsize
;
3578 if(sg
->vmsize
!= 0 && s
->size
!= 0 && big_size
> big_end
){
3579 Mach_O_error(ofile
, "malformed object (addr field plus "
3580 "size of section %u in LC_SEGMENT command %u "
3581 "greater than than the segment's vmaddr plus "
3585 if(mh
->filetype
!= MH_DYLIB_STUB
&&
3586 s
->flags
!= S_ZEROFILL
&&
3587 s
->flags
!= S_THREAD_LOCAL_ZEROFILL
&&
3588 check_overlaping_element(ofile
, &elements
, s
->offset
,
3589 s
->size
, "section contents") == CHECK_BAD
)
3591 if(s
->reloff
> size
){
3592 Mach_O_error(ofile
, "truncated or malformed object "
3593 "(reloff field of section %u in LC_SEGMENT "
3594 "command %u extends past the end of the file)",
3598 big_size
= s
->nreloc
;
3599 big_size
*= sizeof(struct relocation_info
);
3600 big_size
+= s
->reloff
;
3601 if(big_size
> size
){
3602 Mach_O_error(ofile
, "truncated or malformed object "
3603 "(reloff field plus nreloc field times sizeof("
3604 "struct relocation_info) of section %u in "
3605 "LC_SEGMENT command %u extends past the "
3606 "end of the file)", j
, i
);
3609 if(check_overlaping_element(ofile
, &elements
, s
->reloff
,
3610 s
->nreloc
* sizeof(struct relocation_info
),
3611 "section relocation entries") == CHECK_BAD
)
3618 if(l
.cmdsize
< sizeof(struct segment_command_64
)){
3619 Mach_O_error(ofile
, "malformed object (LC_SEGMENT_64 "
3620 "cmdsize too small) in command %u", i
);
3623 sg64
= (struct segment_command_64
*)lc
;
3625 swap_segment_command_64(sg64
, host_byte_sex
);
3626 big_size
= sg64
->nsects
;
3627 big_size
*= sizeof(struct section_64
);
3628 big_size
+= sizeof(struct segment_command_64
);
3629 if(sg64
->cmdsize
!= big_size
){
3630 Mach_O_error(ofile
, "malformed object (inconsistent "
3631 "cmdsize in LC_SEGMENT_64 command %u for "
3632 "the number of sections)", i
);
3635 if(sg64
->fileoff
> size
){
3636 Mach_O_error(ofile
, "truncated or malformed object ("
3637 "LC_SEGMENT_64 command %u fileoff field "
3638 "extends past the end of the file)", i
);
3641 big_size
= sg64
->fileoff
;
3642 big_size
+= sg64
->filesize
;
3643 if(big_size
> size
){
3644 Mach_O_error(ofile
, "truncated or malformed object ("
3645 "LC_SEGMENT_64 command %u fileoff field "
3646 "plus filesize field extends past the end of "
3650 s64
= (struct section_64
*)
3651 ((char *)sg64
+ sizeof(struct segment_command_64
));
3653 swap_section_64(s64
, sg64
->nsects
, host_byte_sex
);
3654 for(j
= 0 ; j
< sg64
->nsects
; j
++){
3655 if(mh64
->filetype
!= MH_DYLIB_STUB
&&
3656 s64
->flags
!= S_ZEROFILL
&&
3657 s64
->flags
!= S_THREAD_LOCAL_ZEROFILL
&&
3658 s64
->offset
> size
){
3659 Mach_O_error(ofile
, "truncated or malformed object "
3660 "(offset field of section %u in LC_SEGMENT_64 "
3661 "command %u extends past the end of the file)",
3665 big_size
= s64
->offset
;
3666 big_size
+= s64
->size
;
3667 if(mh64
->filetype
!= MH_DYLIB_STUB
&&
3668 s64
->flags
!= S_ZEROFILL
&&
3669 s64
->flags
!= S_THREAD_LOCAL_ZEROFILL
&&
3671 Mach_O_error(ofile
, "truncated or malformed object "
3672 "(offset field plus size field of section %u "
3673 "in LC_SEGMENT_64 command %u extends "
3674 "past the end of the file)", j
, i
);
3677 if(mh64
->filetype
!= MH_DYLIB_STUB
&&
3678 s64
->flags
!= S_ZEROFILL
&&
3679 s64
->flags
!= S_THREAD_LOCAL_ZEROFILL
&&
3680 check_overlaping_element(ofile
, &elements
, s64
->offset
,
3681 s64
->size
, "section contents") == CHECK_BAD
)
3683 if(s64
->reloff
> size
){
3684 Mach_O_error(ofile
, "truncated or malformed object "
3685 "(reloff field of section %u in LC_SEGMENT_64 "
3686 "command %u extends past the end of the file)",
3690 big_size
= s64
->nreloc
;
3691 big_size
*= sizeof(struct relocation_info
);
3692 big_size
+= s64
->reloff
;
3693 if(big_size
> size
){
3694 Mach_O_error(ofile
, "truncated or malformed object "
3695 "(reloff field plus nreloc field times sizeof("
3696 "struct relocation_info) of section %u in "
3697 "LC_SEGMENT_64 command %u extends past the "
3698 "end of the file)", j
, i
);
3701 if(check_overlaping_element(ofile
, &elements
, s64
->reloff
,
3702 s64
->nreloc
* sizeof(struct relocation_info
),
3703 "section relocation entries") == CHECK_BAD
)
3710 if(l
.cmdsize
< sizeof(struct symtab_command
)){
3711 Mach_O_error(ofile
, "malformed object (LC_SYMTAB cmdsize "
3712 "too small) in command %u", i
);
3716 Mach_O_error(ofile
, "malformed object (more than one "
3717 "LC_SYMTAB command)");
3720 st
= (struct symtab_command
*)lc
;
3722 swap_symtab_command(st
, host_byte_sex
);
3723 if(st
->cmdsize
!= sizeof(struct symtab_command
)){
3724 Mach_O_error(ofile
, "malformed object (LC_SYMTAB command "
3725 "%u has incorrect cmdsize)", i
);
3728 if(st
->symoff
> size
){
3729 Mach_O_error(ofile
, "truncated or malformed object (symoff "
3730 "field of LC_SYMTAB command %u extends past the end "
3734 big_size
= st
->nsyms
;
3735 big_size
*= sizeof_nlist
;
3736 big_size
+= st
->symoff
;
3737 if(big_size
> size
){
3738 Mach_O_error(ofile
, "truncated or malformed object (symoff "
3739 "field plus nsyms field times sizeof(%s) of LC_SYMTAB "
3740 "command %u extends past the end of the file)",
3741 struct_nlist_name
, i
);
3744 if(check_overlaping_element(ofile
, &elements
, st
->symoff
,
3745 st
->nsyms
* sizeof_nlist
, "symbol table") == CHECK_BAD
)
3747 if(st
->stroff
> size
){
3748 Mach_O_error(ofile
, "truncated or malformed object (stroff "
3749 "field of LC_SYMTAB command %u extends past the end "
3753 big_size
= st
->stroff
;
3754 big_size
+= st
->strsize
;
3755 if(big_size
> size
){
3756 Mach_O_error(ofile
, "truncated or malformed object (stroff "
3757 "field plus strsize field of LC_SYMTAB command %u "
3758 "extends past the end of the file)", i
);
3761 if(check_overlaping_element(ofile
, &elements
, st
->stroff
,
3762 st
->strsize
, "string table") == CHECK_BAD
)
3767 if(l
.cmdsize
< sizeof(struct dysymtab_command
)){
3768 Mach_O_error(ofile
, "malformed object (LC_DYSYMTAB cmdsize "
3769 "too small) in command %u", i
);
3773 Mach_O_error(ofile
, "malformed object (more than one "
3774 "LC_DYSYMTAB command)");
3777 dyst
= (struct dysymtab_command
*)lc
;
3779 swap_dysymtab_command(dyst
, host_byte_sex
);
3780 if(dyst
->cmdsize
!= sizeof(struct dysymtab_command
)){
3781 Mach_O_error(ofile
, "malformed object (LC_DYSYMTAB command "
3782 "%u has incorrect cmdsize)", i
);
3785 if(dyst
->tocoff
> size
){
3786 Mach_O_error(ofile
, "truncated or malformed object (tocoff "
3787 "field of LC_DYSYMTAB command %u extends past the end "
3791 big_size
= dyst
->ntoc
;
3792 big_size
*= sizeof(struct dylib_table_of_contents
);
3793 big_size
+= dyst
->tocoff
;
3794 if(big_size
> size
){
3795 Mach_O_error(ofile
, "truncated or malformed object (tocoff "
3796 "field plus ntoc field times sizeof(struct dylib_table"
3797 "_of_contents) of LC_DYSYMTAB command %u extends past "
3798 "the end of the file)", i
);
3801 if(check_overlaping_element(ofile
, &elements
, dyst
->tocoff
,
3802 dyst
->ntoc
* sizeof(struct dylib_table_of_contents
),
3803 "table of contents") == CHECK_BAD
)
3805 if(dyst
->modtaboff
> size
){
3806 Mach_O_error(ofile
, "truncated or malformed object "
3807 "(modtaboff field of LC_DYSYMTAB command %u extends "
3808 "past the end of the file)", i
);
3811 big_size
= dyst
->nmodtab
;
3812 big_size
*= sizeof_dylib_module
;
3813 big_size
+= dyst
->modtaboff
;
3814 if(big_size
> size
){
3815 Mach_O_error(ofile
, "truncated or malformed object "
3816 "(modtaboff field plus nmodtab field times sizeof(%s) "
3817 "of LC_DYSYMTAB command %u extends past the end of "
3818 "the file)", struct_dylib_module_name
, i
);
3821 if(check_overlaping_element(ofile
, &elements
, dyst
->modtaboff
,
3822 dyst
->nmodtab
* sizeof_dylib_module
, "module table") ==
3825 if(dyst
->extrefsymoff
> size
){
3826 Mach_O_error(ofile
, "truncated or malformed object "
3827 "(extrefsymoff field of LC_DYSYMTAB command %u "
3828 "extends past the end of the file)", i
);
3831 big_size
= dyst
->nextrefsyms
;
3832 big_size
*= sizeof(struct dylib_reference
);
3833 big_size
+= dyst
->extrefsymoff
;
3834 if(big_size
> size
){
3835 Mach_O_error(ofile
, "truncated or malformed object "
3836 "(extrefsymoff field plus nextrefsyms field times "
3837 "sizeof(struct dylib_reference) of LC_DYSYMTAB command "
3838 "%u extends past the end of the file)", i
);
3841 if(check_overlaping_element(ofile
, &elements
,dyst
->extrefsymoff
,
3842 dyst
->nextrefsyms
* sizeof(struct dylib_reference
),
3843 "reference table") == CHECK_BAD
)
3845 if(dyst
->indirectsymoff
> size
){
3846 Mach_O_error(ofile
, "truncated or malformed object "
3847 "(indirectsymoff field of LC_DYSYMTAB command %u "
3848 "extends past the end of the file)", i
);
3851 big_size
= dyst
->nindirectsyms
;
3852 big_size
*= sizeof(uint32_t);
3853 big_size
+= dyst
->indirectsymoff
;
3854 if(big_size
> size
){
3855 Mach_O_error(ofile
, "truncated or malformed object "
3856 "(indirectsymoff field plus nindirectsyms field times "
3857 "sizeof(uint32_t) of LC_DYSYMTAB command "
3858 "%u extends past the end of the file)", i
);
3861 if(check_overlaping_element(ofile
, &elements
,
3862 dyst
->indirectsymoff
, dyst
->nindirectsyms
*
3863 sizeof(uint32_t), "indirect table") == CHECK_BAD
)
3865 if(dyst
->extreloff
> size
){
3866 Mach_O_error(ofile
, "truncated or malformed object "
3867 "(extreloff field of LC_DYSYMTAB command %u "
3868 "extends past the end of the file)", i
);
3871 big_size
= dyst
->nextrel
;
3872 big_size
*= sizeof(struct relocation_info
);
3873 big_size
+= dyst
->extreloff
;
3874 if(big_size
> size
){
3875 Mach_O_error(ofile
, "truncated or malformed object "
3876 "(extreloff field plus nextrel field times "
3877 "sizeof(struct relocation_info) of LC_DYSYMTAB command "
3878 "%u extends past the end of the file)", i
);
3881 if(check_overlaping_element(ofile
, &elements
, dyst
->extreloff
,
3882 dyst
->nextrel
* sizeof(struct relocation_info
),
3883 "external relocation table") == CHECK_BAD
)
3885 if(dyst
->locreloff
> size
){
3886 Mach_O_error(ofile
, "truncated or malformed object "
3887 "(locreloff field of LC_DYSYMTAB command %u "
3888 "extends past the end of the file)", i
);
3891 big_size
= dyst
->nlocrel
;
3892 big_size
*= sizeof(struct relocation_info
);
3893 big_size
+= dyst
->locreloff
;
3894 if(big_size
> size
){
3895 Mach_O_error(ofile
, "truncated or malformed object "
3896 "(locreloff field plus nlocrel field times "
3897 "sizeof(struct relocation_info) of LC_DYSYMTAB command "
3898 "%u extends past the end of the file)", i
);
3901 if(check_overlaping_element(ofile
, &elements
, dyst
->locreloff
,
3902 dyst
->nlocrel
* sizeof(struct relocation_info
),
3903 "local relocation table") == CHECK_BAD
)
3908 if(l
.cmdsize
< sizeof(struct routines_command
)){
3909 Mach_O_error(ofile
, "malformed object (LC_ROUTINES cmdsize "
3910 "too small) in command %u", i
);
3914 Mach_O_error(ofile
, "malformed object (more than one "
3915 "LC_ROUTINES command)");
3918 rc
= (struct routines_command
*)lc
;
3920 swap_routines_command(rc
, host_byte_sex
);
3921 if(rc
->cmdsize
!= sizeof(struct routines_command
)){
3922 Mach_O_error(ofile
, "malformed object (LC_ROUTINES "
3923 "command %u has incorrect cmdsize)", i
);
3928 case LC_ROUTINES_64
:
3929 if(l
.cmdsize
< sizeof(struct routines_command_64
)){
3930 Mach_O_error(ofile
, "malformed object (LC_ROUTINES_64 "
3931 "cmdsize too small) in command %u", i
);
3935 Mach_O_error(ofile
, "malformed object (more than one "
3936 "LC_ROUTINES_64 command)");
3939 rc64
= (struct routines_command_64
*)lc
;
3941 swap_routines_command_64(rc64
, host_byte_sex
);
3942 if(rc64
->cmdsize
!= sizeof(struct routines_command_64
)){
3943 Mach_O_error(ofile
, "malformed object (LC_ROUTINES_64 "
3944 "command %u has incorrect cmdsize)", i
);
3949 case LC_TWOLEVEL_HINTS
:
3950 if(l
.cmdsize
< sizeof(struct twolevel_hints_command
)){
3951 Mach_O_error(ofile
, "malformed object (LC_TWOLEVEL_HINTS "
3952 "cmdsize too small) in command %u", i
);
3956 Mach_O_error(ofile
, "malformed object (more than one "
3957 "LC_TWOLEVEL_HINTS command)");
3960 hints
= (struct twolevel_hints_command
*)lc
;
3962 swap_twolevel_hints_command(hints
, host_byte_sex
);
3963 if(hints
->cmdsize
!= sizeof(struct twolevel_hints_command
)){
3964 Mach_O_error(ofile
, "malformed object (LC_TWOLEVEL_HINTS "
3965 "command %u has incorrect cmdsize)", i
);
3968 if(hints
->offset
> size
){
3969 Mach_O_error(ofile
, "truncated or malformed object "
3970 "(offset field of LC_TWOLEVEL_HINTS command %u "
3971 "extends past the end of the file)", i
);
3974 big_size
= hints
->nhints
;
3975 big_size
*= sizeof(struct twolevel_hint
);
3976 big_size
+= hints
->offset
;
3977 if(big_size
> size
){
3978 Mach_O_error(ofile
, "truncated or malformed object "
3979 "(offset field plus nhints field times "
3980 "sizeof(struct twolevel_hint) of LC_TWOLEVEL_HINTS "
3981 " command %u extends past the end of the file)", i
);
3984 if(check_overlaping_element(ofile
, &elements
, hints
->offset
,
3985 hints
->nhints
* sizeof(struct twolevel_hint
),
3986 "two level hints") == CHECK_BAD
)
3990 case LC_CODE_SIGNATURE
:
3991 if(l
.cmdsize
< sizeof(struct linkedit_data_command
)){
3992 Mach_O_error(ofile
, "malformed object (LC_CODE_SIGNATURE "
3993 "cmdsize too small) in command %u", i
);
3996 if(code_sig
!= NULL
){
3997 Mach_O_error(ofile
, "malformed object (more than one "
3998 "LC_CODE_SIGNATURE command)");
4001 code_sig
= (struct linkedit_data_command
*)lc
;
4003 swap_linkedit_data_command(code_sig
, host_byte_sex
);
4004 if(code_sig
->cmdsize
!= sizeof(struct linkedit_data_command
)){
4005 Mach_O_error(ofile
, "malformed object (LC_CODE_SIGNATURE "
4006 "command %u has incorrect cmdsize)", i
);
4009 if(code_sig
->dataoff
> size
){
4010 Mach_O_error(ofile
, "truncated or malformed object "
4011 "(dataoff field of LC_CODE_SIGNATURE command %u "
4012 "extends past the end of the file)", i
);
4015 big_size
= code_sig
->dataoff
;
4016 big_size
+= code_sig
->datasize
;
4017 if(big_size
> size
){
4018 Mach_O_error(ofile
, "truncated or malformed object "
4019 "(dataoff field plus datasize field of "
4020 "LC_CODE_SIGNATURE command %u extends past the end of "
4024 if(check_overlaping_element(ofile
, &elements
, code_sig
->dataoff
,
4025 code_sig
->datasize
, "code signature data") == CHECK_BAD
)
4029 case LC_SEGMENT_SPLIT_INFO
:
4030 if(l
.cmdsize
< sizeof(struct linkedit_data_command
)){
4031 Mach_O_error(ofile
, "malformed object (LC_SEGMENT_SPLIT_"
4032 "INFO cmdsize too small) in command %u", i
);
4035 if(split_info
!= NULL
){
4036 Mach_O_error(ofile
, "malformed object (more than one "
4037 "LC_SEGMENT_SPLIT_INFO command)");
4040 split_info
= (struct linkedit_data_command
*)lc
;
4042 swap_linkedit_data_command(split_info
, host_byte_sex
);
4043 if(split_info
->cmdsize
!= sizeof(struct linkedit_data_command
)){
4044 Mach_O_error(ofile
, "malformed object (LC_SEGMENT_SPLIT_"
4045 "INFO command %u has incorrect cmdsize)", i
);
4048 if(split_info
->dataoff
> size
){
4049 Mach_O_error(ofile
, "truncated or malformed object "
4050 "(dataoff field of LC_SEGMENT_SPLIT_INFO command %u "
4051 "extends past the end of the file)", i
);
4054 big_size
= split_info
->dataoff
;
4055 big_size
+= split_info
->datasize
;
4056 if(big_size
> size
){
4057 Mach_O_error(ofile
, "truncated or malformed object "
4058 "(dataoff field plus datasize field of LC_SEGMENT_"
4059 "SPLIT_INFO command %u extends past the end of "
4063 if((split_info
->datasize
% load_command_multiple
) != 0){
4064 Mach_O_error(ofile
, "truncated or malformed object "
4065 "(datasize field of LC_SEGMENT_SPLIT_INFO command %u "
4066 "is not a multple of %u)", i
, load_command_multiple
);
4069 if(check_overlaping_element(ofile
, &elements
,
4070 split_info
->dataoff
, split_info
->datasize
,
4071 "split info data") == CHECK_BAD
)
4075 case LC_FUNCTION_STARTS
:
4076 if(l
.cmdsize
< sizeof(struct linkedit_data_command
)){
4077 Mach_O_error(ofile
, "malformed object (LC_FUNCTION_STARTS "
4078 "cmdsize too small) in command %u", i
);
4081 if(func_starts
!= NULL
){
4082 Mach_O_error(ofile
, "malformed object (more than one "
4083 "LC_FUNCTION_STARTS command)");
4086 func_starts
= (struct linkedit_data_command
*)lc
;
4088 swap_linkedit_data_command(func_starts
, host_byte_sex
);
4089 if(func_starts
->cmdsize
!=
4090 sizeof(struct linkedit_data_command
)){
4091 Mach_O_error(ofile
, "malformed object (LC_FUNCTION_STARTS "
4092 "command %u has incorrect cmdsize)", i
);
4095 if(func_starts
->dataoff
> size
){
4096 Mach_O_error(ofile
, "truncated or malformed object "
4097 "(dataoff field of LC_FUNCTION_STARTS command %u "
4098 "extends past the end of the file)", i
);
4101 big_size
= func_starts
->dataoff
;
4102 big_size
+= func_starts
->datasize
;
4103 if(big_size
> size
){
4104 Mach_O_error(ofile
, "truncated or malformed object "
4105 "(dataoff field plus datasize field of "
4106 "LC_FUNCTION_STARTS command %u extends past the end of "
4110 if(check_overlaping_element(ofile
, &elements
,
4111 func_starts
->dataoff
, func_starts
->datasize
,
4112 "function starts data") == CHECK_BAD
)
4116 case LC_VERSION_MIN_MACOSX
:
4117 if(l
.cmdsize
< sizeof(struct version_min_command
)){
4118 Mach_O_error(ofile
, "malformed object (LC_VERSION_MIN_"
4119 "MACOSX cmdsize too small) in command %u", i
);
4123 Mach_O_error(ofile
, "malformed object (more than one "
4124 "LC_VERSION_MIN_IPHONEOS or LC_VERSION_MIN_MACOSX "
4128 vers
= (struct version_min_command
*)lc
;
4130 swap_version_min_command(vers
, host_byte_sex
);
4131 if(vers
->cmdsize
< sizeof(struct version_min_command
)){
4132 Mach_O_error(ofile
, "malformed object (LC_VERSION_MIN_"
4133 "MACOSX command %u has too small cmdsize field)", i
);
4138 case LC_VERSION_MIN_IPHONEOS
:
4139 if(l
.cmdsize
< sizeof(struct version_min_command
)){
4140 Mach_O_error(ofile
, "malformed object (LC_VERSION_MIN_"
4141 "IPHONEOS cmdsize too small) in command %u",i
);
4145 Mach_O_error(ofile
, "malformed object (more than one "
4146 "LC_VERSION_MIN_IPHONEOS or LC_VERSION_MIN_MACOSX "
4150 vers
= (struct version_min_command
*)lc
;
4152 swap_version_min_command(vers
, host_byte_sex
);
4153 if(vers
->cmdsize
< sizeof(struct version_min_command
)){
4154 Mach_O_error(ofile
, "malformed object (LC_VERSION_MIN_"
4155 "IPHONEOS command %u has too small cmdsize field)", i
);
4160 case LC_ENCRYPTION_INFO
:
4161 if(l
.cmdsize
< sizeof(struct encryption_info_command
)){
4162 Mach_O_error(ofile
, "malformed object (LC_ENCRYPTION_INFO "
4163 "cmdsize too small) in command %u", i
);
4166 encrypt_info
= (struct encryption_info_command
*)lc
;
4168 swap_encryption_command(encrypt_info
, host_byte_sex
);
4169 if(encrypt_info
->cmdsize
!=
4170 sizeof(struct encryption_info_command
)){
4171 Mach_O_error(ofile
, "malformed object (LC_ENCRYPTION_INFO"
4172 "command %u has incorrect cmdsize)", i
);
4175 if(encrypt_info
->cryptoff
> size
){
4176 Mach_O_error(ofile
, "truncated or malformed object (cryptoff "
4177 "field of LC_ENCRYPTION_INFO command %u extends "
4178 "past the end of the file)", i
);
4181 big_size
= encrypt_info
->cryptoff
;
4182 big_size
+= encrypt_info
->cryptsize
;
4183 if(big_size
> size
){
4184 Mach_O_error(ofile
, "truncated or malformed object "
4185 "(cryptoff field plus cryptsize field of "
4186 "LC_ENCRYPTION_INFO command %u extends past "
4187 "the end of the file)", i
);
4193 case LC_DYLD_INFO_ONLY
:
4194 if(l
.cmdsize
< sizeof(struct dyld_info_command
)){
4195 Mach_O_error(ofile
, "malformed object (%s cmdsize "
4196 "too small) in command %u", l
.cmd
==
4197 LC_DYLD_INFO
? "LC_DYLD_INFO" :
4198 "LC_DYLD_INFO_ONLY", i
);
4201 dyld_info
= (struct dyld_info_command
*)lc
;
4203 swap_dyld_info_command(dyld_info
, host_byte_sex
);
4204 if(dyld_info
->cmdsize
!=
4205 sizeof(struct dyld_info_command
)){
4206 Mach_O_error(ofile
, "malformed object (LC_DYLD_INFO"
4207 "command %u has incorrect cmdsize)", i
);
4210 if(dyld_info
->rebase_off
!= 0 && dyld_info
->rebase_off
> size
){
4211 Mach_O_error(ofile
, "truncated or malformed object "
4212 "(rebase_off field of LC_DYLD_INFO command %u "
4213 "extends past the end of the file)", i
);
4216 if(dyld_info
->rebase_off
!= 0){
4217 big_size
= dyld_info
->rebase_off
;
4218 big_size
+= dyld_info
->rebase_size
;
4219 if(big_size
> size
){
4220 Mach_O_error(ofile
, "truncated or malformed object "
4221 "(rebase_off plus rebase_size of LC_DYLD_INFO "
4222 "command %u extends past the end of the file)", i
);
4226 if(check_overlaping_element(ofile
, &elements
,
4227 dyld_info
->rebase_off
, dyld_info
->rebase_size
,
4228 "dyld rebase info") == CHECK_BAD
)
4230 if(dyld_info
->bind_off
!= 0 && dyld_info
->bind_off
> size
){
4231 Mach_O_error(ofile
, "truncated or malformed object "
4232 "(bind_off field of LC_DYLD_INFO command %u "
4233 "extends past the end of the file)", i
);
4236 if(dyld_info
->bind_off
!= 0){
4237 big_size
= dyld_info
->bind_off
;
4238 big_size
+= dyld_info
->bind_size
;
4239 if(big_size
> size
){
4240 Mach_O_error(ofile
, "truncated or malformed object "
4241 "(bind_off plus bind_size of LC_DYLD_INFO command "
4242 "%u extends past the end of the file)", i
);
4246 if(check_overlaping_element(ofile
, &elements
,
4247 dyld_info
->bind_off
, dyld_info
->bind_size
,
4248 "dyld bind info") == CHECK_BAD
)
4250 if(dyld_info
->weak_bind_off
!= 0 &&
4251 dyld_info
->weak_bind_off
> size
){
4252 Mach_O_error(ofile
, "truncated or malformed object "
4253 "(weak_bind_off field of LC_DYLD_INFO command %u "
4254 "extends past the end of the file)", i
);
4257 if(dyld_info
->weak_bind_off
!= 0){
4258 big_size
= dyld_info
->weak_bind_off
;
4259 big_size
+= dyld_info
->weak_bind_size
;
4260 if(big_size
> size
){
4261 Mach_O_error(ofile
, "truncated or malformed object "
4262 "(weak_bind_off plus weak_bind_size of LC_DYLD_INFO"
4263 " command %u extends past the end of the file)", i
);
4267 if(check_overlaping_element(ofile
, &elements
,
4268 dyld_info
->weak_bind_off
, dyld_info
->weak_bind_size
,
4269 "dyld bind info") == CHECK_BAD
)
4271 if(dyld_info
->lazy_bind_off
!= 0 &&
4272 dyld_info
->lazy_bind_off
> size
){
4273 Mach_O_error(ofile
, "truncated or malformed object "
4274 "(lazy_bind_off field of LC_DYLD_INFO command %u "
4275 "extends past the end of the file)", i
);
4278 if(dyld_info
->lazy_bind_off
!= 0){
4279 big_size
= dyld_info
->lazy_bind_off
;
4280 big_size
+= dyld_info
->lazy_bind_size
;
4281 if(big_size
> size
){
4282 Mach_O_error(ofile
, "truncated or malformed object "
4283 "(lazy_bind_off plus lazy_bind_size of LC_DYLD_INFO"
4284 " command %u extends past the end of the file)", i
);
4288 if(check_overlaping_element(ofile
, &elements
,
4289 dyld_info
->lazy_bind_off
, dyld_info
->lazy_bind_size
,
4290 "dyld lazy bind info") == CHECK_BAD
)
4292 if(dyld_info
->export_off
!= 0 && dyld_info
->export_off
> size
){
4293 Mach_O_error(ofile
, "truncated or malformed object "
4294 "(export_off field of LC_DYLD_INFO command %u "
4295 "extends past the end of the file)", i
);
4298 if(dyld_info
->export_off
!= 0){
4299 big_size
= dyld_info
->export_off
;
4300 big_size
+= dyld_info
->export_size
;
4301 if(big_size
> size
){
4302 Mach_O_error(ofile
, "truncated or malformed object "
4303 "(export_off plus export_size of LC_DYLD_INFO "
4304 "command %u extends past the end of the file)", i
);
4308 if(check_overlaping_element(ofile
, &elements
,
4309 dyld_info
->export_off
, dyld_info
->export_size
,
4310 "dyld export info") == CHECK_BAD
)
4316 case LC_PREBIND_CKSUM
:
4317 if(l
.cmdsize
< sizeof(struct prebind_cksum_command
)){
4318 Mach_O_error(ofile
, "malformed object (LC_PREBIND_CKSUM "
4319 "cmdsize too small) in command %u", i
);
4323 Mach_O_error(ofile
, "malformed object (more than one "
4324 "LC_PREBIND_CKSUM command)");
4327 cs
= (struct prebind_cksum_command
*)lc
;
4329 swap_prebind_cksum_command(cs
, host_byte_sex
);
4330 if(cs
->cmdsize
!= sizeof(struct prebind_cksum_command
)){
4331 Mach_O_error(ofile
, "malformed object (LC_PREBIND_CKSUM "
4332 "command %u has incorrect cmdsize)", i
);
4338 if(l
.cmdsize
< sizeof(struct uuid_command
)){
4339 Mach_O_error(ofile
, "malformed object (LC_UUID cmdsize "
4340 "too small) in command %u", i
);
4344 Mach_O_error(ofile
, "malformed object (more than one "
4345 "LC_UUID command)");
4348 uuid
= (struct uuid_command
*)lc
;
4350 swap_uuid_command(uuid
, host_byte_sex
);
4351 if(uuid
->cmdsize
!= sizeof(struct uuid_command
)){
4352 Mach_O_error(ofile
, "malformed object (LC_UUID command %u " "has incorrect cmdsize)", i
);
4358 if(l
.cmdsize
< sizeof(struct symseg_command
)){
4359 Mach_O_error(ofile
, "malformed object (LC_SYMSEG cmdsize "
4360 "too small) in command %u", i
);
4363 ss
= (struct symseg_command
*)lc
;
4365 swap_symseg_command(ss
, host_byte_sex
);
4366 if(ss
->cmdsize
!= sizeof(struct symseg_command
)){
4367 Mach_O_error(ofile
, "malformed object (LC_SYMSEG command "
4368 "%u has incorrect cmdsize)", i
);
4371 if(ss
->offset
> size
){
4372 Mach_O_error(ofile
, "truncated or malformed object (offset "
4373 "field of LC_SYMSEG command %u extends past the end "
4377 big_size
= ss
->offset
;
4378 big_size
+= ss
->size
;
4379 if(big_size
> size
){
4380 Mach_O_error(ofile
, "truncated or malformed object (offset "
4381 "field plus size field of LC_SYMTAB command %u "
4382 "extends past the end of the file)", i
);
4385 if(check_overlaping_element(ofile
, &elements
, ss
->offset
,
4386 ss
->size
, "symseg info") == CHECK_BAD
)
4392 if(l
.cmdsize
< sizeof(struct fvmlib_command
)){
4393 Mach_O_error(ofile
, "malformed object (%s cmdsize "
4394 "too small) in command %u", l
.cmd
==
4395 LC_IDFVMLIB
? "LC_IDFVMLIB" :
4396 "LC_LOADFVMLIB", i
);
4399 fl
= (struct fvmlib_command
*)lc
;
4401 swap_fvmlib_command(fl
, host_byte_sex
);
4402 if(fl
->cmdsize
< sizeof(struct fvmlib_command
)){
4403 Mach_O_error(ofile
, "malformed object (%s command %u has "
4404 "too small cmdsize field)", fl
->cmd
== LC_IDFVMLIB
?
4405 "LC_IDFVMLIB" : "LC_LOADFVMLIB", i
);
4408 if(fl
->fvmlib
.name
.offset
>= fl
->cmdsize
){
4409 Mach_O_error(ofile
, "truncated or malformed object (name."
4410 "offset field of %s command %u extends past the end "
4411 "of the file)", fl
->cmd
== LC_IDFVMLIB
? "LC_IDFVMLIB"
4412 : "LC_LOADFVMLIB", i
);
4418 cmd_name
= "LC_ID_DYLIB";
4419 goto check_dylib_command
;
4421 cmd_name
= "LC_LOAD_DYLIB";
4422 goto check_dylib_command
;
4423 case LC_LOAD_WEAK_DYLIB
:
4424 cmd_name
= "LC_LOAD_WEAK_DYLIB";
4425 goto check_dylib_command
;
4426 case LC_REEXPORT_DYLIB
:
4427 cmd_name
= "LC_REEXPORT_DYLIB";
4428 goto check_dylib_command
;
4429 case LC_LOAD_UPWARD_DYLIB
:
4430 cmd_name
= "LC_LOAD_UPWARD_DYLIB";
4431 goto check_dylib_command
;
4432 case LC_LAZY_LOAD_DYLIB
:
4433 cmd_name
= "LC_LAZY_LOAD_DYLIB";
4434 goto check_dylib_command
;
4435 check_dylib_command
:
4436 if(l
.cmdsize
< sizeof(struct dylib_command
)){
4437 Mach_O_error(ofile
, "malformed object (%s cmdsize too "
4438 "small) in command %u", cmd_name
, i
);
4441 dl
= (struct dylib_command
*)lc
;
4443 swap_dylib_command(dl
, host_byte_sex
);
4444 if(dl
->cmdsize
< sizeof(struct dylib_command
)){
4445 Mach_O_error(ofile
, "malformed object (%s command %u has "
4446 "too small cmdsize field)", cmd_name
, i
);
4449 if(dl
->dylib
.name
.offset
>= dl
->cmdsize
){
4450 Mach_O_error(ofile
, "truncated or malformed object (name."
4451 "offset field of %s command %u extends past the end "
4452 "of the file)", cmd_name
, i
);
4457 case LC_SUB_FRAMEWORK
:
4458 if(l
.cmdsize
< sizeof(struct sub_framework_command
)){
4459 Mach_O_error(ofile
, "malformed object (LC_SUB_FRAMEWORK "
4460 "cmdsize too small) in command %u", i
);
4463 sub
= (struct sub_framework_command
*)lc
;
4465 swap_sub_framework_command(sub
, host_byte_sex
);
4466 if(sub
->cmdsize
< sizeof(struct sub_framework_command
)){
4467 Mach_O_error(ofile
, "malformed object (LC_SUB_FRAMEWORK "
4468 "command %u has too small cmdsize field)", i
);
4471 if(sub
->umbrella
.offset
>= sub
->cmdsize
){
4472 Mach_O_error(ofile
, "truncated or malformed object "
4473 "(umbrella.offset field of LC_SUB_FRAMEWORK command "
4474 "%u extends past the end of the file)", i
);
4479 case LC_SUB_UMBRELLA
:
4480 if(l
.cmdsize
< sizeof(struct sub_umbrella_command
)){
4481 Mach_O_error(ofile
, "malformed object (LC_SUB_UMBRELLA "
4482 "cmdsize too small) in command %u", i
);
4485 usub
= (struct sub_umbrella_command
*)lc
;
4487 swap_sub_umbrella_command(usub
, host_byte_sex
);
4488 if(usub
->cmdsize
< sizeof(struct sub_umbrella_command
)){
4489 Mach_O_error(ofile
, "malformed object (LC_SUB_UMBRELLA "
4490 "command %u has too small cmdsize field)", i
);
4493 if(usub
->sub_umbrella
.offset
>= usub
->cmdsize
){
4494 Mach_O_error(ofile
, "truncated or malformed object "
4495 "(sub_umbrella.offset field of LC_SUB_UMBRELLA command "
4496 "%u extends past the end of the file)", i
);
4501 case LC_SUB_LIBRARY
:
4502 if(l
.cmdsize
< sizeof(struct sub_library_command
)){
4503 Mach_O_error(ofile
, "malformed object (LC_SUB_LIBRARY "
4504 "cmdsize too small) in command %u", i
);
4507 lsub
= (struct sub_library_command
*)lc
;
4509 swap_sub_library_command(lsub
, host_byte_sex
);
4510 if(lsub
->cmdsize
< sizeof(struct sub_library_command
)){
4511 Mach_O_error(ofile
, "malformed object (LC_SUB_LIBRARY "
4512 "command %u has too small cmdsize field)", i
);
4515 if(lsub
->sub_library
.offset
>= lsub
->cmdsize
){
4516 Mach_O_error(ofile
, "truncated or malformed object "
4517 "(sub_library.offset field of LC_SUB_LIBRARY command "
4518 "%u extends past the end of the file)", i
);
4524 if(l
.cmdsize
< sizeof(struct sub_client_command
)){
4525 Mach_O_error(ofile
, "malformed object (LC_SUB_CLIENT "
4526 "cmdsize too small) in command %u", i
);
4529 csub
= (struct sub_client_command
*)lc
;
4531 swap_sub_client_command(csub
, host_byte_sex
);
4532 if(csub
->cmdsize
< sizeof(struct sub_client_command
)){
4533 Mach_O_error(ofile
, "malformed object (LC_SUB_CLIENT "
4534 "command %u has too small cmdsize field)", i
);
4537 if(csub
->client
.offset
>= csub
->cmdsize
){
4538 Mach_O_error(ofile
, "truncated or malformed object "
4539 "(cleient.offset field of LC_SUB_CLIENT command "
4540 "%u extends past the end of the file)", i
);
4545 case LC_PREBOUND_DYLIB
:
4546 if(l
.cmdsize
< sizeof(struct prebound_dylib_command
)){
4547 Mach_O_error(ofile
, "malformed object (LC_PREBOUND_DYLIB "
4548 "cmdsize too small) in command %u", i
);
4551 pbdylib
= (struct prebound_dylib_command
*)lc
;
4553 swap_prebound_dylib_command(pbdylib
, host_byte_sex
);
4554 if(pbdylib
->cmdsize
< sizeof(struct dylib_command
)){
4555 Mach_O_error(ofile
, "malformed object (LC_PREBIND_DYLIB "
4556 "command %u has too small cmdsize field)", i
);
4559 if(pbdylib
->name
.offset
>= pbdylib
->cmdsize
){
4560 Mach_O_error(ofile
, "truncated or malformed object (name."
4561 "offset field of LC_PREBIND_DYLIB command %u extends "
4562 "past the end of the file)", i
);
4565 if(pbdylib
->linked_modules
.offset
>= pbdylib
->cmdsize
){
4566 Mach_O_error(ofile
, "truncated or malformed object (linked_"
4567 "modules.offset field of LC_PREBIND_DYLIB command %u "
4568 "extends past the end of the file)", i
);
4573 case LC_ID_DYLINKER
:
4574 cmd_name
= "LC_ID_DYLINKER";
4575 goto check_dylinker_command
;
4576 case LC_LOAD_DYLINKER
:
4577 cmd_name
= "LC_LOAD_DYLINKER";
4578 goto check_dylinker_command
;
4579 case LC_DYLD_ENVIRONMENT
:
4580 cmd_name
= "LC_DYLD_ENVIRONMENT";
4581 goto check_dylinker_command
;
4582 check_dylinker_command
:
4583 if(l
.cmdsize
< sizeof(struct dylinker_command
)){
4584 Mach_O_error(ofile
, "malformed object (%s cmdsize "
4585 "too small) in command %u", cmd_name
, i
);
4588 dyld
= (struct dylinker_command
*)lc
;
4590 swap_dylinker_command(dyld
, host_byte_sex
);
4591 if(dyld
->cmdsize
< sizeof(struct dylinker_command
)){
4592 Mach_O_error(ofile
, "malformed object (%s command %u has "
4593 "too small cmdsize field)", cmd_name
, i
);
4596 if(dyld
->name
.offset
>= dyld
->cmdsize
){
4597 Mach_O_error(ofile
, "truncated or malformed object (name."
4598 "offset field of %s command %u extends past the end "
4599 "of the file)", cmd_name
, i
);
4606 if(l
.cmdsize
< sizeof(struct thread_command
)){
4607 Mach_O_error(ofile
, "malformed object (%s cmdsize "
4608 "too small) in command %u", l
.cmd
==
4609 LC_UNIXTHREAD
? "LC_UNIXTHREAD" :
4613 ut
= (struct thread_command
*)lc
;
4615 swap_thread_command(ut
, host_byte_sex
);
4616 state
= (char *)ut
+ sizeof(struct thread_command
);
4618 if(cputype
== CPU_TYPE_MC680x0
){
4619 struct m68k_thread_state_regs
*cpu
;
4620 struct m68k_thread_state_68882
*fpu
;
4621 struct m68k_thread_state_user_reg
*user_reg
;
4624 p
= (char *)ut
+ ut
->cmdsize
;
4626 if(state
+ sizeof(uint32_t) >
4627 (char *)ut
+ ut
->cmdsize
){
4628 Mach_O_error(ofile
, "malformed object (flavor in "
4629 "%s command %u extends past end of command)",
4630 ut
->cmd
== LC_UNIXTHREAD
? "LC_UNIXTHREAD" :
4634 flavor
= *((uint32_t *)state
);
4636 flavor
= SWAP_INT(flavor
);
4637 *((uint32_t *)state
) = flavor
;
4639 state
+= sizeof(uint32_t);
4640 if(state
+ sizeof(uint32_t) >
4641 (char *)ut
+ ut
->cmdsize
){
4642 Mach_O_error(ofile
, "malformed object (count in "
4643 "%s command %u extends past end of command)",
4644 ut
->cmd
== LC_UNIXTHREAD
? "LC_UNIXTHREAD" :
4648 count
= *((uint32_t *)state
);
4650 count
= SWAP_INT(count
);
4651 *((uint32_t *)state
) = count
;
4653 state
+= sizeof(uint32_t);
4655 case M68K_THREAD_STATE_REGS
:
4656 if(count
!= M68K_THREAD_STATE_REGS_COUNT
){
4657 Mach_O_error(ofile
, "malformed object (count "
4658 "not M68K_THREAD_STATE_REGS_COUNT for "
4659 "flavor number %u which is a M68K_THREAD_"
4660 "STATE_REGS flavor in %s command %u)",
4661 nflavor
, ut
->cmd
== LC_UNIXTHREAD
?
4662 "LC_UNIXTHREAD" : "LC_THREAD", i
);
4665 cpu
= (struct m68k_thread_state_regs
*)state
;
4666 if(state
+ sizeof(struct m68k_thread_state_regs
) >
4667 (char *)ut
+ ut
->cmdsize
){
4668 Mach_O_error(ofile
, "malformed object ("
4669 "M68K_THREAD_STATE_REGS in %s command %u "
4670 "extends past end of command)", ut
->cmd
==
4671 LC_UNIXTHREAD
? "LC_UNIXTHREAD" :
4676 swap_m68k_thread_state_regs(cpu
, host_byte_sex
);
4677 state
+= sizeof(struct m68k_thread_state_regs
);
4679 case M68K_THREAD_STATE_68882
:
4680 if(count
!= M68K_THREAD_STATE_68882_COUNT
){
4681 Mach_O_error(ofile
, "malformed object (count "
4682 "not M68K_THREAD_STATE_68882_COUNT for "
4683 "flavor number %u which is a M68K_THREAD_"
4684 "STATE_68882 flavor in %s command %u)",
4685 nflavor
, ut
->cmd
== LC_UNIXTHREAD
?
4686 "LC_UNIXTHREAD" : "LC_THREAD", i
);
4689 fpu
= (struct m68k_thread_state_68882
*)state
;
4690 if(state
+ sizeof(struct m68k_thread_state_68882
) >
4691 (char *)ut
+ ut
->cmdsize
){
4692 Mach_O_error(ofile
, "malformed object ("
4693 "M68K_THREAD_STATE_68882 in %s command %u "
4694 "extends past end of command)", ut
->cmd
==
4695 LC_UNIXTHREAD
? "LC_UNIXTHREAD" :
4700 swap_m68k_thread_state_68882(fpu
,host_byte_sex
);
4701 state
+= sizeof(struct m68k_thread_state_68882
);
4703 case M68K_THREAD_STATE_USER_REG
:
4704 if(count
!= M68K_THREAD_STATE_USER_REG_COUNT
){
4705 Mach_O_error(ofile
, "malformed object (count "
4706 "not M68K_THREAD_STATE_USER_REG_COUNT for "
4707 "flavor number %u which is a M68K_THREAD_"
4708 "STATE_USER_REG flavor in %s command %u)",
4709 nflavor
, ut
->cmd
== LC_UNIXTHREAD
?
4710 "LC_UNIXTHREAD" : "LC_THREAD", i
);
4714 (struct m68k_thread_state_user_reg
*)state
;
4715 if(state
+sizeof(struct m68k_thread_state_user_reg
) >
4716 (char *)ut
+ ut
->cmdsize
){
4717 Mach_O_error(ofile
, "malformed object ("
4718 "M68K_THREAD_STATE_USER_REG in %s command "
4719 "%u extends past end of command)", ut
->cmd
==
4720 LC_UNIXTHREAD
? "LC_UNIXTHREAD" :
4725 swap_m68k_thread_state_user_reg(user_reg
,
4727 state
+= sizeof(struct m68k_thread_state_user_reg
);
4731 Mach_O_error(ofile
, "malformed object (unknown "
4732 "flavor for flavor number %u in %s command"
4733 " %u can't byte swap it)", nflavor
,
4734 ut
->cmd
== LC_UNIXTHREAD
? "LC_UNIXTHREAD" :
4738 state
+= count
* sizeof(uint32_t);
4745 if(cputype
== CPU_TYPE_POWERPC
||
4746 cputype
== CPU_TYPE_VEO
){
4747 ppc_thread_state_t
*nrw_cpu
;
4750 p
= (char *)ut
+ ut
->cmdsize
;
4752 if(state
+ sizeof(uint32_t) >
4753 (char *)ut
+ ut
->cmdsize
){
4754 Mach_O_error(ofile
, "malformed object (flavor in "
4755 "%s command %u extends past end of command)",
4756 ut
->cmd
== LC_UNIXTHREAD
? "LC_UNIXTHREAD" :
4760 flavor
= *((uint32_t *)state
);
4762 flavor
= SWAP_INT(flavor
);
4763 *((uint32_t *)state
) = flavor
;
4765 state
+= sizeof(uint32_t);
4766 if(state
+ sizeof(uint32_t) >
4767 (char *)ut
+ ut
->cmdsize
){
4768 Mach_O_error(ofile
, "malformed object (count in "
4769 "%s command %u extends past end of command)",
4770 ut
->cmd
== LC_UNIXTHREAD
? "LC_UNIXTHREAD" :
4774 count
= *((uint32_t *)state
);
4776 count
= SWAP_INT(count
);
4777 *((uint32_t *)state
) = count
;
4779 state
+= sizeof(uint32_t);
4781 case PPC_THREAD_STATE
:
4782 if(count
!= PPC_THREAD_STATE_COUNT
){
4783 Mach_O_error(ofile
, "malformed object (count "
4784 "not PPC_THREAD_STATE_COUNT for "
4785 "flavor number %u which is a PPC_THREAD_"
4786 "STATE flavor in %s command %u)",
4787 nflavor
, ut
->cmd
== LC_UNIXTHREAD
?
4788 "LC_UNIXTHREAD" : "LC_THREAD", i
);
4791 nrw_cpu
= (ppc_thread_state_t
*)state
;
4792 if(state
+ sizeof(ppc_thread_state_t
) >
4793 (char *)ut
+ ut
->cmdsize
){
4794 Mach_O_error(ofile
, "malformed object ("
4795 "PPC_THREAD_STATE in %s command %u extends"
4796 " past end of command)", ut
->cmd
==
4797 LC_UNIXTHREAD
? "LC_UNIXTHREAD" :
4802 swap_ppc_thread_state_t(nrw_cpu
,
4804 state
+= sizeof(ppc_thread_state_t
);
4808 Mach_O_error(ofile
, "malformed object (unknown "
4809 "flavor for flavor number %u in %s command"
4810 " %u can't byte swap it)", nflavor
,
4811 ut
->cmd
== LC_UNIXTHREAD
? "LC_UNIXTHREAD" :
4815 state
+= count
* sizeof(uint32_t);
4822 #ifdef PPC_THREAD_STATE64_COUNT
4823 if(cputype
== CPU_TYPE_POWERPC64
){
4824 ppc_thread_state64_t
*cpu
;
4827 p
= (char *)ut
+ ut
->cmdsize
;
4829 if(state
+ sizeof(uint32_t) >
4830 (char *)ut
+ ut
->cmdsize
){
4831 Mach_O_error(ofile
, "malformed object (flavor in "
4832 "%s command %u extends past end of command)",
4833 ut
->cmd
== LC_UNIXTHREAD
? "LC_UNIXTHREAD" :
4837 flavor
= *((uint32_t *)state
);
4839 flavor
= SWAP_INT(flavor
);
4840 *((uint32_t *)state
) = flavor
;
4842 state
+= sizeof(uint32_t);
4843 if(state
+ sizeof(uint32_t) >
4844 (char *)ut
+ ut
->cmdsize
){
4845 Mach_O_error(ofile
, "malformed object (count in "
4846 "%s command %u extends past end of command)",
4847 ut
->cmd
== LC_UNIXTHREAD
? "LC_UNIXTHREAD" :
4851 count
= *((uint32_t *)state
);
4853 count
= SWAP_INT(count
);
4854 *((uint32_t *)state
) = count
;
4856 state
+= sizeof(uint32_t);
4858 case PPC_THREAD_STATE64
:
4859 if(count
!= PPC_THREAD_STATE64_COUNT
){
4860 Mach_O_error(ofile
, "malformed object (count "
4861 "not PPC_THREAD_STATE64_COUNT for "
4862 "flavor number %u which is a PPC_THREAD_"
4863 "STATE64 flavor in %s command %u)",
4864 nflavor
, ut
->cmd
== LC_UNIXTHREAD
?
4865 "LC_UNIXTHREAD" : "LC_THREAD", i
);
4868 cpu
= (ppc_thread_state64_t
*)state
;
4869 if(state
+ sizeof(ppc_thread_state64_t
) >
4870 (char *)ut
+ ut
->cmdsize
){
4871 Mach_O_error(ofile
, "malformed object ("
4872 "PPC_THREAD_STATE64 in %s command %u "
4873 "extends past end of command)", ut
->cmd
==
4874 LC_UNIXTHREAD
? "LC_UNIXTHREAD" :
4879 swap_ppc_thread_state64_t(cpu
, host_byte_sex
);
4880 state
+= sizeof(ppc_thread_state64_t
);
4884 Mach_O_error(ofile
, "malformed object (unknown "
4885 "flavor for flavor number %u in %s command"
4886 " %u can't byte swap it)", nflavor
,
4887 ut
->cmd
== LC_UNIXTHREAD
? "LC_UNIXTHREAD" :
4891 state
+= count
* sizeof(uint32_t);
4898 #endif /* PPC_THREAD_STATE64_COUNT */
4899 if(cputype
== CPU_TYPE_MC88000
){
4900 m88k_thread_state_grf_t
*cpu
;
4901 m88k_thread_state_xrf_t
*fpu
;
4902 m88k_thread_state_user_t
*user
;
4903 m88110_thread_state_impl_t
*spu
;
4906 p
= (char *)ut
+ ut
->cmdsize
;
4908 if(state
+ sizeof(uint32_t) >
4909 (char *)ut
+ ut
->cmdsize
){
4910 Mach_O_error(ofile
, "malformed object (flavor in "
4911 "%s command %u extends past end of command)",
4912 ut
->cmd
== LC_UNIXTHREAD
? "LC_UNIXTHREAD" :
4916 flavor
= *((uint32_t *)state
);
4918 flavor
= SWAP_INT(flavor
);
4919 *((uint32_t *)state
) = flavor
;
4921 state
+= sizeof(uint32_t);
4922 if(state
+ sizeof(uint32_t) >
4923 (char *)ut
+ ut
->cmdsize
){
4924 Mach_O_error(ofile
, "malformed object (count in "
4925 "%s command %u extends past end of command)",
4926 ut
->cmd
== LC_UNIXTHREAD
? "LC_UNIXTHREAD" :
4930 count
= *((uint32_t *)state
);
4932 count
= SWAP_INT(count
);
4933 *((uint32_t *)state
) = count
;
4935 state
+= sizeof(uint32_t);
4937 case M88K_THREAD_STATE_GRF
:
4938 if(count
!= M88K_THREAD_STATE_GRF_COUNT
){
4939 Mach_O_error(ofile
, "malformed object (count "
4940 "not M88K_THREAD_STATE_GRF_COUNT for "
4941 "flavor number %u which is a M88K_THREAD_"
4942 "STATE_GRF flavor in %s command %u)",
4943 nflavor
, ut
->cmd
== LC_UNIXTHREAD
?
4944 "LC_UNIXTHREAD" : "LC_THREAD", i
);
4947 cpu
= (m88k_thread_state_grf_t
*)state
;
4948 if(state
+ sizeof(m88k_thread_state_grf_t
) >
4949 (char *)ut
+ ut
->cmdsize
){
4950 Mach_O_error(ofile
, "malformed object ("
4951 "M88K_THREAD_STATE_GRF in %s command %u "
4952 "extends past end of command)", ut
->cmd
==
4953 LC_UNIXTHREAD
? "LC_UNIXTHREAD" :
4958 swap_m88k_thread_state_grf_t(cpu
,
4960 state
+= sizeof(m88k_thread_state_grf_t
);
4962 case M88K_THREAD_STATE_XRF
:
4963 if(count
!= M88K_THREAD_STATE_XRF_COUNT
){
4964 Mach_O_error(ofile
, "malformed object (count "
4965 "not M88K_THREAD_STATE_XRF_COUNT for "
4966 "flavor number %u which is a M88K_THREAD_"
4967 "STATE_XRF flavor in %s command %u)",
4968 nflavor
, ut
->cmd
== LC_UNIXTHREAD
?
4969 "LC_UNIXTHREAD" : "LC_THREAD", i
);
4972 fpu
= (m88k_thread_state_xrf_t
*)state
;
4973 if(state
+ sizeof(m88k_thread_state_xrf_t
) >
4974 (char *)ut
+ ut
->cmdsize
){
4975 Mach_O_error(ofile
, "malformed object ("
4976 "M88K_THREAD_STATE_XRF in %s command %u "
4977 "extends past end of command)", ut
->cmd
==
4978 LC_UNIXTHREAD
? "LC_UNIXTHREAD" :
4983 swap_m88k_thread_state_xrf_t(fpu
,
4985 state
+= sizeof(m88k_thread_state_xrf_t
);
4987 case M88K_THREAD_STATE_USER
:
4988 if(count
!= M88K_THREAD_STATE_USER_COUNT
){
4989 Mach_O_error(ofile
, "malformed object (count "
4990 "not M88K_THREAD_STATE_USER_COUNT for "
4991 "flavor number %u which is a M88K_THREAD_"
4992 "STATE_USER flavor in %s command %u)",
4993 nflavor
, ut
->cmd
== LC_UNIXTHREAD
?
4994 "LC_UNIXTHREAD" : "LC_THREAD", i
);
4997 user
= (m88k_thread_state_user_t
*)state
;
4998 if(state
+ sizeof(m88k_thread_state_user_t
) >
4999 (char *)ut
+ ut
->cmdsize
){
5000 Mach_O_error(ofile
, "malformed object ("
5001 "M88K_THREAD_STATE_USER in %s command %u "
5002 "extends past end of command)", ut
->cmd
==
5003 LC_UNIXTHREAD
? "LC_UNIXTHREAD" :
5008 swap_m88k_thread_state_user_t(user
,
5010 state
+= sizeof(m88k_thread_state_user_t
);
5012 case M88110_THREAD_STATE_IMPL
:
5013 if(count
!= M88110_THREAD_STATE_IMPL_COUNT
){
5014 Mach_O_error(ofile
, "malformed object (count "
5015 "not M88110_THREAD_STATE_IMPL_COUNT for "
5016 "flavor number %u which is a M88110_THREAD"
5017 "_STATE_IMPL flavor in %s command %u)",
5018 nflavor
, ut
->cmd
== LC_UNIXTHREAD
?
5019 "LC_UNIXTHREAD" : "LC_THREAD", i
);
5022 spu
= (m88110_thread_state_impl_t
*)state
;
5023 if(state
+ sizeof(m88110_thread_state_impl_t
) >
5024 (char *)ut
+ ut
->cmdsize
){
5025 Mach_O_error(ofile
, "malformed object ("
5026 "M88110_THREAD_STATE_IMPL in %s command %u "
5027 "extends past end of command)", ut
->cmd
==
5028 LC_UNIXTHREAD
? "LC_UNIXTHREAD" :
5033 swap_m88110_thread_state_impl_t(spu
,
5035 state
+= sizeof(m88110_thread_state_impl_t
);
5039 Mach_O_error(ofile
, "malformed object (unknown "
5040 "flavor for flavor number %u in %s command"
5041 " %u can't byte swap it)", nflavor
,
5042 ut
->cmd
== LC_UNIXTHREAD
? "LC_UNIXTHREAD" :
5046 state
+= count
* sizeof(uint32_t);
5053 if(cputype
== CPU_TYPE_I860
){
5055 struct i860_thread_state_regs
*cpu
;
5059 p
= (char *)ut
+ ut
->cmdsize
;
5061 if(state
+ sizeof(uint32_t) >
5062 (char *)ut
+ ut
->cmdsize
){
5063 Mach_O_error(ofile
, "malformed object (flavor in "
5064 "%s command %u extends past end of command)",
5065 ut
->cmd
== LC_UNIXTHREAD
? "LC_UNIXTHREAD" :
5069 flavor
= *((uint32_t *)state
);
5071 flavor
= SWAP_INT(flavor
);
5072 *((uint32_t *)state
) = flavor
;
5074 state
+= sizeof(uint32_t);
5075 if(state
+ sizeof(uint32_t) >
5076 (char *)ut
+ ut
->cmdsize
){
5077 Mach_O_error(ofile
, "malformed object (count in "
5078 "%s command %u extends past end of command)",
5079 ut
->cmd
== LC_UNIXTHREAD
? "LC_UNIXTHREAD" :
5083 count
= *((uint32_t *)state
);
5085 count
= SWAP_INT(count
);
5086 *((uint32_t *)state
) = count
;
5088 state
+= sizeof(uint32_t);
5090 case I860_THREAD_STATE_REGS
:
5092 if(count
!= I860_THREAD_STATE_REGS_COUNT
){
5093 Mach_O_error(ofile
, "malformed object (count "
5094 "not I860_THREAD_STATE_REGS_COUNT for "
5095 "flavor number %u which is a I860_THREAD_"
5096 "STATE_REGS flavor in %s command %u)",
5097 nflavor
, ut
->cmd
== LC_UNIXTHREAD
?
5098 "LC_UNIXTHREAD" : "LC_THREAD", i
);
5101 cpu
= (struct i860_thread_state_regs
*)state
;
5102 if(state
+ sizeof(struct i860_thread_state_regs
) >
5103 (char *)ut
+ ut
->cmdsize
){
5104 Mach_O_error(ofile
, "malformed object ("
5105 "I860_THREAD_STATE_REGS in %s command %u "
5106 "extends past end of command)", ut
->cmd
==
5107 LC_UNIXTHREAD
? "LC_UNIXTHREAD" :
5112 swap_i860_thread_state_regs(cpu
, host_byte_sex
);
5113 state
+= sizeof(struct i860_thread_state_regs
);
5115 state
+= count
* sizeof(int);
5120 Mach_O_error(ofile
, "malformed object (unknown "
5121 "flavor for flavor number %u in %s command"
5122 " %u can't byte swap it)", nflavor
,
5123 ut
->cmd
== LC_UNIXTHREAD
? "LC_UNIXTHREAD" :
5127 state
+= count
* sizeof(uint32_t);
5134 if(cputype
== CPU_TYPE_I386
){
5135 i386_thread_state_t
*cpu
;
5136 /* current i386 thread states */
5137 #if i386_THREAD_STATE == 1
5138 struct i386_float_state
*fpu
;
5139 i386_exception_state_t
*exc
;
5140 #endif /* i386_THREAD_STATE == 1 */
5142 /* i386 thread states on older releases */
5143 #if i386_THREAD_STATE == -1
5144 i386_thread_fpstate_t
*fpu
;
5145 i386_thread_exceptstate_t
*exc
;
5146 i386_thread_cthreadstate_t
*user
;
5147 #endif /* i386_THREAD_STATE == -1 */
5150 p
= (char *)ut
+ ut
->cmdsize
;
5152 if(state
+ sizeof(uint32_t) >
5153 (char *)ut
+ ut
->cmdsize
){
5154 Mach_O_error(ofile
, "malformed object (flavor in "
5155 "%s command %u extends past end of command)",
5156 ut
->cmd
== LC_UNIXTHREAD
? "LC_UNIXTHREAD" :
5160 flavor
= *((uint32_t *)state
);
5162 flavor
= SWAP_INT(flavor
);
5163 *((uint32_t *)state
) = flavor
;
5165 state
+= sizeof(uint32_t);
5166 if(state
+ sizeof(uint32_t) >
5167 (char *)ut
+ ut
->cmdsize
){
5168 Mach_O_error(ofile
, "malformed object (count in "
5169 "%s command %u extends past end of command)",
5170 ut
->cmd
== LC_UNIXTHREAD
? "LC_UNIXTHREAD" :
5174 count
= *((uint32_t *)state
);
5176 count
= SWAP_INT(count
);
5177 *((uint32_t *)state
) = count
;
5179 state
+= sizeof(uint32_t);
5180 switch((int)flavor
){
5181 case i386_THREAD_STATE
:
5182 #if i386_THREAD_STATE == 1
5184 #endif /* i386_THREAD_STATE == 1 */
5185 /* i386 thread states on older releases */
5186 #if i386_THREAD_STATE == -1
5188 #endif /* i386_THREAD_STATE == -1 */
5189 if(count
!= i386_THREAD_STATE_COUNT
){
5190 Mach_O_error(ofile
, "malformed object (count "
5191 "not i386_THREAD_STATE_COUNT for flavor "
5192 "number %u which is a i386_THREAD_STATE "
5193 "flavor in %s command %u)", nflavor
,
5194 ut
->cmd
== LC_UNIXTHREAD
? "LC_UNIXTHREAD" :
5198 cpu
= (i386_thread_state_t
*)state
;
5199 if(state
+ sizeof(i386_thread_state_t
) >
5200 (char *)ut
+ ut
->cmdsize
){
5201 Mach_O_error(ofile
, "malformed object ("
5202 "i386_THREAD_STATE in %s command %u "
5203 "extends past end of command)", ut
->cmd
==
5204 LC_UNIXTHREAD
? "LC_UNIXTHREAD" :
5209 swap_i386_thread_state(cpu
, host_byte_sex
);
5210 state
+= sizeof(i386_thread_state_t
);
5212 /* current i386 thread states */
5213 #if i386_THREAD_STATE == 1
5214 case i386_FLOAT_STATE
:
5215 if(count
!= i386_FLOAT_STATE_COUNT
){
5216 Mach_O_error(ofile
, "malformed object (count "
5217 "not i386_FLOAT_STATE_COUNT for flavor "
5218 "number %u which is a i386_FLOAT_STATE "
5219 "flavor in %s command %u)", nflavor
,
5220 ut
->cmd
== LC_UNIXTHREAD
? "LC_UNIXTHREAD" :
5224 fpu
= (struct i386_float_state
*)state
;
5225 if(state
+ sizeof(struct i386_float_state
) >
5226 (char *)ut
+ ut
->cmdsize
){
5227 Mach_O_error(ofile
, "malformed object ("
5228 "i386_FLOAT_STATE in %s command %u "
5229 "extends past end of command)", ut
->cmd
==
5230 LC_UNIXTHREAD
? "LC_UNIXTHREAD" :
5235 swap_i386_float_state(fpu
, host_byte_sex
);
5236 state
+= sizeof(struct i386_float_state
);
5238 case i386_EXCEPTION_STATE
:
5239 if(count
!= I386_EXCEPTION_STATE_COUNT
){
5240 Mach_O_error(ofile
, "malformed object (count "
5241 "not I386_EXCEPTION_STATE_COUNT for "
5242 "flavor number %u which is a i386_"
5243 "EXCEPTION_STATE flavor in %s command %u)",
5245 ut
->cmd
== LC_UNIXTHREAD
? "LC_UNIXTHREAD" :
5249 exc
= (i386_exception_state_t
*)state
;
5250 if(state
+ sizeof(i386_exception_state_t
) >
5251 (char *)ut
+ ut
->cmdsize
){
5252 Mach_O_error(ofile
, "malformed object ("
5253 "i386_EXCEPTION_STATE in %s command %u "
5254 "extends past end of command)", ut
->cmd
==
5255 LC_UNIXTHREAD
? "LC_UNIXTHREAD" :
5260 swap_i386_exception_state(exc
,host_byte_sex
);
5261 state
+= sizeof(i386_exception_state_t
);
5263 #endif /* i386_THREAD_STATE == 1 */
5265 /* i386 thread states on older releases */
5266 #if i386_THREAD_STATE == -1
5267 case i386_THREAD_FPSTATE
:
5268 if(count
!= i386_THREAD_FPSTATE_COUNT
){
5269 Mach_O_error(ofile
, "malformed object (count "
5270 "not i386_THREAD_FPSTATE_COUNT for flavor "
5271 "number %u which is a i386_THREAD_FPSTATE "
5272 "flavor in %s command %u)", nflavor
,
5273 ut
->cmd
== LC_UNIXTHREAD
? "LC_UNIXTHREAD" :
5277 fpu
= (i386_thread_fpstate_t
*)state
;
5278 if(state
+ sizeof(i386_thread_fpstate_t
) >
5279 (char *)ut
+ ut
->cmdsize
){
5280 Mach_O_error(ofile
, "malformed object ("
5281 "i386_THREAD_FPSTATE in %s command %u "
5282 "extends past end of command)", ut
->cmd
==
5283 LC_UNIXTHREAD
? "LC_UNIXTHREAD" :
5288 swap_i386_thread_fpstate(fpu
, host_byte_sex
);
5289 state
+= sizeof(i386_thread_fpstate_t
);
5291 case i386_THREAD_EXCEPTSTATE
:
5292 if(count
!= i386_THREAD_EXCEPTSTATE_COUNT
){
5293 Mach_O_error(ofile
, "malformed object (count "
5294 "not i386_THREAD_EXCEPTSTATE_COUNT for "
5295 "flavor number %u which is a i386_THREAD_"
5296 "EXCEPTSTATE flavor in %s command %u)",
5298 ut
->cmd
== LC_UNIXTHREAD
? "LC_UNIXTHREAD" :
5302 exc
= (i386_thread_exceptstate_t
*)state
;
5303 if(state
+ sizeof(i386_thread_exceptstate_t
) >
5304 (char *)ut
+ ut
->cmdsize
){
5305 Mach_O_error(ofile
, "malformed object ("
5306 "i386_THREAD_EXCEPTSTATE in %s command %u "
5307 "extends past end of command)", ut
->cmd
==
5308 LC_UNIXTHREAD
? "LC_UNIXTHREAD" :
5313 swap_i386_thread_exceptstate(exc
,host_byte_sex
);
5314 state
+= sizeof(i386_thread_exceptstate_t
);
5316 case i386_THREAD_CTHREADSTATE
:
5317 if(count
!= i386_THREAD_CTHREADSTATE_COUNT
){
5318 Mach_O_error(ofile
, "malformed object (count "
5319 "not i386_THREAD_CTHREADSTATE_COUNT for "
5320 "flavor number %u which is a i386_THREAD_"
5321 "CTHREADSTATE flavor in %s command %u)",
5323 ut
->cmd
== LC_UNIXTHREAD
? "LC_UNIXTHREAD" :
5327 user
= (i386_thread_cthreadstate_t
*)state
;
5328 if(state
+ sizeof(i386_thread_cthreadstate_t
) >
5329 (char *)ut
+ ut
->cmdsize
){
5330 Mach_O_error(ofile
, "malformed object ("
5331 "i386_THREAD_CTHREADSTATE in %s command %u "
5332 "extends past end of command)", ut
->cmd
==
5333 LC_UNIXTHREAD
? "LC_UNIXTHREAD" :
5338 swap_i386_thread_cthreadstate(user
,
5340 state
+= sizeof(i386_thread_cthreadstate_t
);
5342 #endif /* i386_THREAD_STATE == -1 */
5345 Mach_O_error(ofile
, "malformed object (unknown "
5346 "flavor for flavor number %u in %s command"
5347 " %u can't byte swap it)", nflavor
,
5348 ut
->cmd
== LC_UNIXTHREAD
? "LC_UNIXTHREAD" :
5352 state
+= count
* sizeof(uint32_t);
5359 #ifdef x86_THREAD_STATE64_COUNT
5360 if(cputype
== CPU_TYPE_X86_64
){
5361 x86_thread_state64_t
*cpu
;
5364 p
= (char *)ut
+ ut
->cmdsize
;
5366 if(state
+ sizeof(uint32_t) >
5367 (char *)ut
+ ut
->cmdsize
){
5368 Mach_O_error(ofile
, "malformed object (flavor in "
5369 "%s command %u extends past end of command)",
5370 ut
->cmd
== LC_UNIXTHREAD
? "LC_UNIXTHREAD" :
5374 flavor
= *((uint32_t *)state
);
5376 flavor
= SWAP_INT(flavor
);
5377 *((uint32_t *)state
) = flavor
;
5379 state
+= sizeof(uint32_t);
5380 if(state
+ sizeof(uint32_t) >
5381 (char *)ut
+ ut
->cmdsize
){
5382 Mach_O_error(ofile
, "malformed object (count in "
5383 "%s command %u extends past end of command)",
5384 ut
->cmd
== LC_UNIXTHREAD
? "LC_UNIXTHREAD" :
5388 count
= *((uint32_t *)state
);
5390 count
= SWAP_INT(count
);
5391 *((uint32_t *)state
) = count
;
5393 state
+= sizeof(uint32_t);
5395 case x86_THREAD_STATE64
:
5396 if(count
!= x86_THREAD_STATE64_COUNT
){
5397 Mach_O_error(ofile
, "malformed object (count "
5398 "not x86_THREAD_STATE64_COUNT for "
5399 "flavor number %u which is a x86_THREAD_"
5400 "STATE64 flavor in %s command %u)",
5401 nflavor
, ut
->cmd
== LC_UNIXTHREAD
?
5402 "LC_UNIXTHREAD" : "LC_THREAD", i
);
5405 cpu
= (x86_thread_state64_t
*)state
;
5406 if(state
+ sizeof(x86_thread_state64_t
) >
5407 (char *)ut
+ ut
->cmdsize
){
5408 Mach_O_error(ofile
, "malformed object ("
5409 "x86_THREAD_STATE64 in %s command %u "
5410 "extends past end of command)", ut
->cmd
==
5411 LC_UNIXTHREAD
? "LC_UNIXTHREAD" :
5416 swap_x86_thread_state64(cpu
, host_byte_sex
);
5417 state
+= sizeof(x86_thread_state64_t
);
5421 Mach_O_error(ofile
, "malformed object (unknown "
5422 "flavor for flavor number %u in %s command"
5423 " %u can't byte swap it)", nflavor
,
5424 ut
->cmd
== LC_UNIXTHREAD
? "LC_UNIXTHREAD" :
5428 state
+= count
* sizeof(uint32_t);
5435 #endif /* x86_THREAD_STATE64_COUNT */
5436 if(cputype
== CPU_TYPE_HPPA
){
5437 struct hp_pa_integer_thread_state
*cpu
;
5438 struct hp_pa_frame_thread_state
*frame
;
5439 struct hp_pa_fp_thread_state
*fpu
;
5442 p
= (char *)ut
+ ut
->cmdsize
;
5444 if(state
+ sizeof(uint32_t) >
5445 (char *)ut
+ ut
->cmdsize
){
5446 Mach_O_error(ofile
, "malformed object (flavor in "
5447 "%s command %u extends past end of command)",
5448 ut
->cmd
== LC_UNIXTHREAD
? "LC_UNIXTHREAD" :
5452 flavor
= *((uint32_t *)state
);
5454 flavor
= SWAP_INT(flavor
);
5455 *((uint32_t *)state
) = flavor
;
5457 state
+= sizeof(uint32_t);
5458 if(state
+ sizeof(uint32_t) >
5459 (char *)ut
+ ut
->cmdsize
){
5460 Mach_O_error(ofile
, "malformed object (count in "
5461 "%s command %u extends past end of command)",
5462 ut
->cmd
== LC_UNIXTHREAD
? "LC_UNIXTHREAD" :
5466 count
= *((uint32_t *)state
);
5468 count
= SWAP_INT(count
);
5469 *((uint32_t *)state
) = count
;
5471 state
+= sizeof(uint32_t);
5473 case HPPA_INTEGER_THREAD_STATE
:
5474 if(count
!= HPPA_INTEGER_THREAD_STATE_COUNT
){
5475 Mach_O_error(ofile
, "malformed object (count "
5476 "not HPPA_INTEGER_THREAD_STATE_COUNT for "
5477 "flavor number %u which is a "
5478 "HPPA_INTEGER_THREAD_STATE "
5479 "flavor in %s command %u)", nflavor
,
5480 ut
->cmd
== LC_UNIXTHREAD
? "LC_UNIXTHREAD" :
5484 cpu
= (struct hp_pa_integer_thread_state
*)state
;
5485 if(state
+sizeof(struct hp_pa_integer_thread_state
) >
5486 (char *)ut
+ ut
->cmdsize
){
5487 Mach_O_error(ofile
, "malformed object ("
5488 "HPPA_INTEGER_THREAD_STATE in %s command "
5489 "%u extends past end of command)",
5490 ut
->cmd
== LC_UNIXTHREAD
? "LC_UNIXTHREAD" :
5495 swap_hppa_integer_thread_state(cpu
,
5497 state
+= sizeof(struct hp_pa_integer_thread_state
);
5499 case HPPA_FRAME_THREAD_STATE
:
5500 if(count
!= HPPA_FRAME_THREAD_STATE_COUNT
){
5501 Mach_O_error(ofile
, "malformed object (count "
5502 "not HPPA_FRAME_THREAD_STATE_COUNT for "
5503 "flavor number %u which is a HPPA_FRAME_"
5504 "THREAD_STATE flavor in %s command %u)",
5506 ut
->cmd
== LC_UNIXTHREAD
? "LC_UNIXTHREAD" :
5510 frame
= (struct hp_pa_frame_thread_state
*)state
;
5511 if(state
+ sizeof(struct hp_pa_frame_thread_state
) >
5512 (char *)ut
+ ut
->cmdsize
){
5513 Mach_O_error(ofile
, "malformed object ("
5514 "HPPA_FRAME_THREAD_STATE in %s command "
5515 "%u extends past end of command)",
5516 ut
->cmd
== LC_UNIXTHREAD
? "LC_UNIXTHREAD" :
5521 swap_hppa_frame_thread_state(frame
,host_byte_sex
);
5522 state
+= sizeof(struct hp_pa_frame_thread_state
);
5524 case HPPA_FP_THREAD_STATE
:
5525 if(count
!= HPPA_FP_THREAD_STATE_COUNT
){
5526 Mach_O_error(ofile
, "malformed object (count "
5527 "not HPPA_FP_THREAD_STATE_COUNT for "
5528 "flavor number %u which is a HPPA_FP_"
5529 "THREAD_STATE flavor in %s command %u)",
5531 ut
->cmd
== LC_UNIXTHREAD
? "LC_UNIXTHREAD" :
5535 fpu
= (struct hp_pa_fp_thread_state
*)state
;
5536 if(state
+ sizeof(struct hp_pa_fp_thread_state
) >
5537 (char *)ut
+ ut
->cmdsize
){
5538 Mach_O_error(ofile
, "malformed object ("
5539 "HPPA_FP_THREAD_STATE in %s command "
5540 "%u extends past end of command)",
5541 ut
->cmd
== LC_UNIXTHREAD
? "LC_UNIXTHREAD" :
5546 swap_hppa_fp_thread_state(fpu
,host_byte_sex
);
5547 state
+= sizeof(struct hp_pa_fp_thread_state
);
5551 Mach_O_error(ofile
, "malformed object (unknown "
5552 "flavor for flavor number %u in %s command"
5553 " %u can't byte swap it)", nflavor
,
5554 ut
->cmd
== LC_UNIXTHREAD
? "LC_UNIXTHREAD" :
5558 state
+= count
* sizeof(uint32_t);
5565 if(cputype
== CPU_TYPE_SPARC
){
5566 struct sparc_thread_state_regs
*cpu
;
5567 struct sparc_thread_state_fpu
*fpu
;
5570 p
= (char *)ut
+ ut
->cmdsize
;
5572 if(state
+ sizeof(uint32_t) >
5573 (char *)ut
+ ut
->cmdsize
){
5574 Mach_O_error(ofile
, "malformed object (flavor in "
5575 "%s command %u extends past end of command)",
5576 ut
->cmd
== LC_UNIXTHREAD
? "LC_UNIXTHREAD" :
5580 flavor
= *((uint32_t *)state
);
5582 flavor
= SWAP_INT(flavor
);
5583 *((uint32_t *)state
) = flavor
;
5585 state
+= sizeof(uint32_t);
5586 if(state
+ sizeof(uint32_t) >
5587 (char *)ut
+ ut
->cmdsize
){
5588 Mach_O_error(ofile
, "malformed object (count in "
5589 "%s command %u extends past end of command)",
5590 ut
->cmd
== LC_UNIXTHREAD
? "LC_UNIXTHREAD" :
5594 count
= *((uint32_t *)state
);
5596 count
= SWAP_INT(count
);
5597 *((uint32_t *)state
) = count
;
5599 state
+= sizeof(uint32_t);
5601 case SPARC_THREAD_STATE_REGS
:
5602 if(count
!= SPARC_THREAD_STATE_REGS_COUNT
){
5603 Mach_O_error(ofile
, "malformed object (count "
5604 "not SPARC_THREAD_STATE_REGS_COUNT for "
5605 "flavor number %u which is a SPARC_THREAD_"
5606 "STATE_REGS flavor in %s command %u)",
5607 nflavor
, ut
->cmd
== LC_UNIXTHREAD
?
5608 "LC_UNIXTHREAD" : "LC_THREAD", i
);
5611 cpu
= (struct sparc_thread_state_regs
*)state
;
5612 if(state
+ sizeof(struct sparc_thread_state_regs
) >
5613 (char *)ut
+ ut
->cmdsize
){
5614 Mach_O_error(ofile
, "malformed object ("
5615 "SPARC_THREAD_STATE_REGS in %s command %u "
5616 "extends past end of command)", ut
->cmd
==
5617 LC_UNIXTHREAD
? "LC_UNIXTHREAD" :
5622 swap_sparc_thread_state_regs(cpu
, host_byte_sex
);
5623 state
+= sizeof(struct sparc_thread_state_regs
);
5625 case SPARC_THREAD_STATE_FPU
:
5626 if(count
!= SPARC_THREAD_STATE_FPU_COUNT
){
5627 Mach_O_error(ofile
, "malformed object (count "
5628 "not SPARC_THREAD_STATE_FPU_COUNT for "
5629 "flavor number %u which is a SPARC_THREAD_"
5630 "STATE_FPU flavor in %s command %u)",
5631 nflavor
, ut
->cmd
== LC_UNIXTHREAD
?
5632 "LC_UNIXTHREAD" : "LC_THREAD", i
);
5635 fpu
= (struct sparc_thread_state_fpu
*)state
;
5636 if(state
+ sizeof(struct sparc_thread_state_fpu
) >
5637 (char *)ut
+ ut
->cmdsize
){
5638 Mach_O_error(ofile
, "malformed object ("
5639 "SPARC_THREAD_STATE_FPU in %s command %u "
5640 "extends past end of command)", ut
->cmd
==
5641 LC_UNIXTHREAD
? "LC_UNIXTHREAD" :
5646 swap_sparc_thread_state_fpu(fpu
, host_byte_sex
);
5647 state
+= sizeof(struct sparc_thread_state_fpu
);
5651 Mach_O_error(ofile
, "malformed object (unknown "
5652 "flavor for flavor number %u in %s command"
5653 " %u can't byte swap it)", nflavor
,
5654 ut
->cmd
== LC_UNIXTHREAD
? "LC_UNIXTHREAD" :
5658 state
+= count
* sizeof(uint32_t);
5665 if(cputype
== CPU_TYPE_ARM
){
5666 arm_thread_state_t
*cpu
;
5669 p
= (char *)ut
+ ut
->cmdsize
;
5671 if(state
+ sizeof(uint32_t) >
5672 (char *)ut
+ ut
->cmdsize
){
5673 Mach_O_error(ofile
, "malformed object (flavor in "
5674 "%s command %u extends past end of command)",
5675 ut
->cmd
== LC_UNIXTHREAD
? "LC_UNIXTHREAD" :
5679 flavor
= *((uint32_t *)state
);
5681 flavor
= SWAP_INT(flavor
);
5682 *((uint32_t *)state
) = flavor
;
5684 state
+= sizeof(uint32_t);
5685 if(state
+ sizeof(uint32_t) >
5686 (char *)ut
+ ut
->cmdsize
){
5687 Mach_O_error(ofile
, "malformed object (count in "
5688 "%s command %u extends past end of command)",
5689 ut
->cmd
== LC_UNIXTHREAD
? "LC_UNIXTHREAD" :
5693 count
= *((uint32_t *)state
);
5695 count
= SWAP_INT(count
);
5696 *((uint32_t *)state
) = count
;
5698 state
+= sizeof(uint32_t);
5700 case ARM_THREAD_STATE
:
5701 if(count
!= ARM_THREAD_STATE_COUNT
){
5702 Mach_O_error(ofile
, "malformed object (count "
5703 "not ARM_THREAD_STATE_COUNT for "
5704 "flavor number %u which is a ARM_THREAD_"
5705 "STATE flavor in %s command %u)",
5706 nflavor
, ut
->cmd
== LC_UNIXTHREAD
?
5707 "LC_UNIXTHREAD" : "LC_THREAD", i
);
5710 cpu
= (arm_thread_state_t
*)state
;
5711 if(state
+ sizeof(arm_thread_state_t
) >
5712 (char *)ut
+ ut
->cmdsize
){
5713 Mach_O_error(ofile
, "malformed object ("
5714 "ARM_THREAD_STATE in %s command %u "
5715 "extends past end of command)", ut
->cmd
==
5716 LC_UNIXTHREAD
? "LC_UNIXTHREAD" :
5721 swap_arm_thread_state_t(cpu
, host_byte_sex
);
5722 state
+= sizeof(arm_thread_state_t
);
5726 Mach_O_error(ofile
, "malformed object (unknown "
5727 "flavor for flavor number %u in %s command"
5728 " %u can't byte swap it)", nflavor
,
5729 ut
->cmd
== LC_UNIXTHREAD
? "LC_UNIXTHREAD" :
5733 state
+= count
* sizeof(uint32_t);
5741 Mach_O_error(ofile
, "malformed object (unknown cputype and "
5742 "cpusubtype of object and can't byte swap and check %s "
5743 "command %u)", ut
->cmd
== LC_UNIXTHREAD
?
5744 "LC_UNIXTHREAD" : "LC_THREAD", i
);
5749 if(l
.cmdsize
< sizeof(struct ident_command
)){
5750 Mach_O_error(ofile
, "malformed object (LC_IDENT cmdsize "
5751 "too small) in command %u", i
);
5754 id
= (struct ident_command
*)lc
;
5756 swap_ident_command(id
, host_byte_sex
);
5758 * Note the cmdsize field if the LC_IDENT command was checked
5759 * as part of checking all load commands cmdsize field before
5760 * the switch statement on the cmd field of the load command.
5764 if(l
.cmdsize
< sizeof(struct rpath_command
)){
5765 Mach_O_error(ofile
, "malformed object (LC_RPATH: cmdsize "
5766 "too small) in command %u", i
);
5769 rpath
= (struct rpath_command
*)lc
;
5771 swap_rpath_command(rpath
, host_byte_sex
);
5772 if(rpath
->cmdsize
< sizeof(struct rpath_command
)){
5773 Mach_O_error(ofile
, "malformed object (LC_RPATH command "
5774 "%u has too small cmdsize field)", i
);
5777 if(rpath
->path
.offset
>= rpath
->cmdsize
){
5778 Mach_O_error(ofile
, "truncated or malformed object (path."
5779 "offset field of LC_RPATH command %u extends past the "
5780 "end of the file)", i
);
5787 Mach_O_error(ofile
, "malformed object (unknown load command "
5790 #endif /* !defined(OFI) */
5793 lc
= (struct load_command
*)((char *)lc
+ l
.cmdsize
);
5794 /* check that next load command does not extends past the end */
5795 if((char *)lc
> (char *)load_commands
+ sizeofcmds
){
5796 Mach_O_error(ofile
, "truncated or malformed object (load "
5797 "command %u extends past the end of the file)",
5804 Mach_O_error(ofile
, "truncated or malformed object (contains "
5805 "LC_DYSYMTAB load command without a LC_SYMTAB load command)");
5811 if(dyst
->nlocalsym
!= 0 &&
5812 dyst
->ilocalsym
> st
->nsyms
){
5813 Mach_O_error(ofile
, "truncated or malformed object "
5814 "(ilocalsym in LC_DYSYMTAB load command extends past "
5815 "the end of the symbol table)");
5818 big_size
= dyst
->ilocalsym
;
5819 big_size
+= dyst
->nlocalsym
;
5820 if(dyst
->nlocalsym
!= 0 && big_size
> st
->nsyms
){
5821 Mach_O_error(ofile
, "truncated or malformed object "
5822 "(ilocalsym plus nlocalsym in LC_DYSYMTAB load command "
5823 "extends past the end of the symbol table)");
5827 if(dyst
->nextdefsym
!= 0 &&
5828 dyst
->iextdefsym
> st
->nsyms
){
5829 Mach_O_error(ofile
, "truncated or malformed object "
5830 "(iextdefsym in LC_DYSYMTAB load command extends past "
5831 "the end of the symbol table)");
5834 big_size
= dyst
->iextdefsym
;
5835 big_size
+= dyst
->nextdefsym
;
5836 if(dyst
->nextdefsym
!= 0 && big_size
> st
->nsyms
){
5837 Mach_O_error(ofile
, "truncated or malformed object "
5838 "(iextdefsym plus nextdefsym in LC_DYSYMTAB load "
5839 "command extends past the end of the symbol table)");
5843 if(dyst
->nundefsym
!= 0 &&
5844 dyst
->iundefsym
> st
->nsyms
){
5845 Mach_O_error(ofile
, "truncated or malformed object "
5846 "(iundefsym in LC_DYSYMTAB load command extends past "
5847 "the end of the symbol table)");
5850 big_size
= dyst
->iundefsym
;
5851 big_size
+= dyst
->nundefsym
;
5852 if(dyst
->nundefsym
!= 0 && big_size
> st
->nsyms
){
5853 Mach_O_error(ofile
, "truncated or malformed object "
5854 "(iundefsym plus nundefsym in LC_DYSYMTAB load command "
5855 "extends past the end of the symbol table)");
5859 if(rc
->init_module
> dyst
->nmodtab
){
5860 Mach_O_error(ofile
, "malformed object (init_module in "
5861 "LC_ROUTINES load command extends past the "
5862 "end of the module table)");
5867 if(rc64
->init_module
> dyst
->nmodtab
){
5868 Mach_O_error(ofile
, "malformed object (init_module in "
5869 "LC_ROUTINES_64 load command extends past the "
5870 "end of the module table)");
5875 if(hints
->nhints
!= dyst
->nundefsym
){
5876 Mach_O_error(ofile
, "malformed object (nhints in "
5877 "LC_TWOLEVEL_HINTS load command not the same as "
5878 "nundefsym in LC_DYSYMTAB load command)");
5884 /* check for an inconsistent size of the load commands */
5885 if((char *)load_commands
+ sizeofcmds
!= (char *)lc
){
5886 Mach_O_error(ofile
, "malformed object (inconsistent sizeofcmds "
5887 "field in mach header)");
5892 * Mark this ofile so we know its headers have been swapped. We do this
5893 * in case we don't process it the first time so we can swap them back
5894 * in case we loop back to it in a fat file to process it later.
5897 ofile
->headers_swapped
= TRUE
;
5899 /* looks good return ok */
5900 free_elements(&elements
);
5904 free_elements(&elements
);
5910 * swap_back_Mach_O() is called after the ofile has been processed to swap back
5911 * the mach header and load commands if check_Mach_O() above swapped them.
5916 struct ofile
*ofile
)
5918 if(ofile
->headers_swapped
== TRUE
){
5919 ofile
->headers_swapped
= FALSE
;
5920 if(ofile
->mh
!= NULL
)
5921 swap_object_headers(ofile
->mh
, ofile
->load_commands
);
5922 else if(ofile
->mh64
!= NULL
)
5923 swap_object_headers(ofile
->mh64
, ofile
->load_commands
);
5929 * check_overlaping_element() checks that the element in the ofile described by
5930 * offset, size and name does not overlap in list of elements in head. If it
5931 * does CHECK_BAD is returned and an error message is generated. If it doesn't
5932 * then an element is added in the ordered list and CHECK_GOOD is returned
5936 check_overlaping_element(
5937 struct ofile
*ofile
,
5938 struct element
*head
,
5943 struct element
*e
, *p
, *n
;
5948 if(head
->next
== NULL
){
5949 n
= allocate(sizeof(struct element
));
5960 while(e
->next
!= NULL
){
5963 if((offset
>= e
->offset
&&
5964 offset
< e
->offset
+ e
->size
) ||
5965 (offset
+ size
> e
->offset
&&
5966 offset
+ size
< e
->offset
+ e
->size
) ||
5967 (offset
<= e
->offset
&&
5968 offset
+ size
>= e
->offset
+ e
->size
)){
5969 Mach_O_error(ofile
, "malformed object (%s at offset %u with a "
5970 "size of %u, overlaps %s at offset %u with a size of %u)",
5971 name
, offset
, size
, e
->name
, e
->offset
, e
->size
);
5974 if(e
->next
!= NULL
&& offset
+ size
<= e
->next
->offset
){
5975 n
= allocate(sizeof(struct element
));
5984 n
= allocate(sizeof(struct element
));
5994 * free_elements() frees the list of elements on the list head.
5999 struct element
*head
)
6001 struct element
*e
, *e_next
;
6010 #endif /* !defined(OTOOL) */
6013 * check_dylib_module() checks the object file's dylib_module as referenced
6014 * by the dylib_module field in the ofile for correctness.
6019 struct ofile
*ofile
,
6020 struct symtab_command
*st
,
6021 struct dysymtab_command
*dyst
,
6023 uint32_t module_index
)
6027 #else /* !defined OTOOL */
6029 enum byte_sex host_byte_sex
;
6031 struct dylib_module m
;
6032 struct dylib_module_64 m64
;
6033 uint32_t module_name
, nextdefsym
, iextdefsym
, nlocalsym
, ilocalsym
, nrefsym
;
6034 uint32_t irefsym
, nextrel
, iextrel
;
6036 host_byte_sex
= get_host_byte_sex();
6037 swapped
= (enum bool)(host_byte_sex
!= ofile
->object_byte_sex
);
6038 if(ofile
->mh
!= NULL
){
6039 m
= *ofile
->dylib_module
;
6041 swap_dylib_module(&m
, 1, host_byte_sex
);
6042 module_name
= m
.module_name
;
6043 nextdefsym
= m
.nextdefsym
;
6044 iextdefsym
= m
.iextdefsym
;
6045 nlocalsym
= m
.nlocalsym
;
6046 ilocalsym
= m
.ilocalsym
;
6047 nrefsym
= m
.nrefsym
;
6048 irefsym
= m
.irefsym
;
6049 nextrel
= m
.nextrel
;
6050 iextrel
= m
.iextrel
;
6053 m64
= *ofile
->dylib_module64
;
6055 swap_dylib_module_64(&m64
, 1, host_byte_sex
);
6056 module_name
= m64
.module_name
;
6057 nextdefsym
= m64
.nextdefsym
;
6058 iextdefsym
= m64
.iextdefsym
;
6059 nlocalsym
= m64
.nlocalsym
;
6060 ilocalsym
= m64
.ilocalsym
;
6061 nrefsym
= m64
.nrefsym
;
6062 irefsym
= m64
.irefsym
;
6063 nextrel
= m64
.nextrel
;
6064 iextrel
= m64
.iextrel
;
6067 if(module_name
> st
->strsize
){
6068 Mach_O_error(ofile
, "truncated or malformed object (module_name "
6069 "of module table entry %u past the end of the string table)",
6073 for(i
= module_name
; i
< st
->strsize
&& strings
[i
] != '\0'; i
++)
6075 if(i
>= st
->strsize
){
6076 Mach_O_error(ofile
, "truncated or malformed object (module_name "
6077 "of module table entry %u extends past the end of the string "
6078 "table)", module_index
);
6082 if(nextdefsym
!= 0){
6083 if(iextdefsym
> st
->nsyms
){
6084 Mach_O_error(ofile
, "truncated or malformed object (iextdefsym "
6085 "field of module table entry %u past the end of the "
6086 "symbol table", module_index
);
6089 if(iextdefsym
+ nextdefsym
> st
->nsyms
){
6090 Mach_O_error(ofile
, "truncated or malformed object (iextdefsym "
6091 "field of module table entry %u plus nextdefsym field "
6092 "extends past the end of the symbol table", module_index
);
6097 if(ilocalsym
> st
->nsyms
){
6098 Mach_O_error(ofile
, "truncated or malformed object (ilocalsym "
6099 "field of module table entry %u past the end of the "
6100 "symbol table", module_index
);
6103 if(ilocalsym
+ nlocalsym
> st
->nsyms
){
6104 Mach_O_error(ofile
, "truncated or malformed object (ilocalsym "
6105 "field of module table entry %u plus nlocalsym field "
6106 "extends past the end of the symbol table", module_index
);
6111 if(irefsym
> dyst
->nextrefsyms
){
6112 Mach_O_error(ofile
, "truncated or malformed object (irefsym "
6113 "field of module table entry %u past the end of the "
6114 "reference table", module_index
);
6117 if(irefsym
+ nrefsym
> dyst
->nextrefsyms
){
6118 Mach_O_error(ofile
, "truncated or malformed object (irefsym "
6119 "field of module table entry %u plus nrefsym field "
6120 "extends past the end of the reference table",module_index
);
6125 if(iextrel
> dyst
->extreloff
){
6126 Mach_O_error(ofile
, "truncated or malformed object (iextrel "
6127 "field of module table entry %u past the end of the "
6128 "external relocation enrties", module_index
);
6131 if(iextrel
+ nextrel
> dyst
->extreloff
){
6132 Mach_O_error(ofile
, "truncated or malformed object (iextrel "
6133 "field of module table entry %u plus nextrel field "
6134 "extends past the end of the external relocation enrties",
6146 const struct ar_hdr
*ar_hdr
)
6150 i
= sizeof(ar_hdr
->ar_name
) - 1;
6151 if(ar_hdr
->ar_name
[i
] == ' '){
6153 if(ar_hdr
->ar_name
[i
] != ' ')
6160 #endif /* !defined(RLD) */