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 #undef MACHINE_THREAD_STATE /* need to undef these to avoid warnings */
64 #undef MACHINE_THREAD_STATE_COUNT
65 #undef THREAD_STATE_NONE
66 #undef VALID_THREAD_STATE_FLAVOR
67 #import <mach/arm/thread_status.h>
68 #include <mach-o/nlist.h>
69 #include <mach-o/reloc.h>
70 #include "stuff/bool.h"
72 #include <mach-o/dyld.h>
74 #include "stuff/lto.h"
76 #include "stuff/bytesex.h"
77 #include "stuff/arch.h"
78 #include "stuff/rnd.h"
79 #include "stuff/errors.h"
80 #include "stuff/allocate.h"
81 #include "stuff/ofile.h"
82 #include "stuff/print.h"
85 #undef ALIGNMENT_CHECKS
87 #include "ofile_print.h"
88 static enum bool otool_first_ofile_map
= TRUE
;
89 #else /* !define(OTOOL) */
91 #if (!defined(m68k) && !defined(__i386__) && !defined(__x86_64__) && !defined(__ppc__) && !defined(__arm__))
92 #define ALIGNMENT_CHECKS_ARCHIVE_64_BIT
93 static enum bool archive_64_bit_align_warning
= FALSE
;
94 #endif /* (!defined(m68k) && !defined(__i386__) && !defined(__x86_64__) && !defined(__ppc__) && !defined(__arm__)) */
99 /* The maximum section alignment allowed to be specified, as a power of two */
100 #define MAXSECTALIGN 15 /* 2**15 or 0x8000 */
112 struct element
*next
;
114 #endif /* !defined(OTOOL) */
116 static enum bool ofile_specific_arch(
119 static enum check_type
check_fat(
120 struct ofile
*ofile
);
121 static enum check_type
check_fat_object_in_archive(
122 struct ofile
*ofile
);
123 static enum check_type
check_archive(
125 enum bool archives_with_fat_objects
);
126 static enum check_type
check_extend_format_1(
128 struct ar_hdr
*ar_hdr
,
130 uint32_t *member_name_size
);
131 static enum check_type
check_archive_toc(
132 struct ofile
*ofile
);
133 static enum check_type
check_Mach_O(
134 struct ofile
*ofile
);
135 static void swap_back_Mach_O(
136 struct ofile
*ofile
);
138 static enum check_type
check_overlaping_element(
140 struct element
*head
,
144 static void free_elements(
145 struct element
*head
);
146 #endif /* !defined(OTOOL) */
147 static enum check_type
check_dylib_module(
149 struct symtab_command
*st
,
150 struct dysymtab_command
*dyst
,
152 uint32_t module_index
);
155 #if defined(ALIGNMENT_CHECKS) || defined(ALIGNMENT_CHECKS_ARCHIVE_64_BIT)
158 temporary_archive_member_warning(
160 const char *format
, ...)
164 va_start(ap
, format
);
165 if(ofile
->file_type
== OFILE_FAT
){
166 print("%s: for architecture %s archive member: %s(%.*s) ",
167 progname
, ofile
->arch_flag
.name
, ofile
->file_name
,
168 (int)ofile
->member_name_size
, ofile
->member_name
);
171 print("%s: archive member: %s(%.*s) ", progname
, ofile
->file_name
,
172 (int)ofile
->member_name_size
, ofile
->member_name
);
178 #endif /* defined(ALIGNMENT_CHECKS) */
179 #endif /* !defined(OTOOL) */
183 * ofile_process() processes the specified file name can calls the routine
184 * processor on the ofiles in it. arch_flags is an array of architectures
185 * containing narch_flags which are the only architectures to process if
186 * narch_flags is non-zero. If all_archs is TRUE then all architectures of
187 * the specified file are processed. The specified file name can be of the
188 * form "archive(member)" which is taken to mean that member in that archive
189 * (or that module of a dynamic library if dylib_flat is not FALSE).
190 * For each ofile that is to be processed the routine processor is called with
191 * the corresponding ofile struct, the arch_name pass to it is either NULL or
192 * an architecture name (when it should be printed or show by processor) and
193 * cookie is the same value as passed to ofile_process.
199 struct arch_flag
*arch_flags
,
200 uint32_t narch_flags
,
202 enum bool process_non_objects
,
203 enum bool dylib_flat
,
204 enum bool use_member_syntax
,
205 void (*processor
)(struct ofile
*ofile
, char *arch_name
, void *cookie
),
208 char *member_name
, *p
, *arch_name
;
211 enum bool flag
, hostflag
, arch_found
, family
;
212 struct arch_flag host_arch_flag
;
213 const struct arch_flag
*family_arch_flag
;
216 * If use_member_syntax is TRUE look for a name of the form
217 * "archive(member)" which is to mean a member in that archive (the
218 * member name must be at least one character long to be recognized as
222 if(use_member_syntax
== TRUE
){
224 if(len
>= 4 && name
[len
-1] == ')'){
225 p
= strrchr(name
, '(');
226 if(p
!= NULL
&& p
!= name
){
235 otool_first_ofile_map
= TRUE
;
237 if(ofile_map(name
, NULL
, NULL
, &ofile
, FALSE
) == FALSE
)
240 otool_first_ofile_map
= FALSE
;
243 if(ofile
.file_type
== OFILE_FAT
){
245 * This is a fat file so see if a list of architecture is
246 * specified and process only those.
248 if(all_archs
== FALSE
&& narch_flags
!= 0){
249 for(i
= 0; i
< narch_flags
; i
++){
250 if(ofile_first_arch(&ofile
) == FALSE
){
257 get_arch_family_from_cputype(arch_flags
[i
].cputype
);
258 if(family_arch_flag
!= NULL
)
260 ((family_arch_flag
->cpusubtype
& ~CPU_SUBTYPE_MASK
) ==
261 (arch_flags
[i
].cpusubtype
& ~CPU_SUBTYPE_MASK
));
263 arch_name
= ofile
.arch_flag
.name
;
267 if(ofile
.arch_flag
.cputype
==
268 arch_flags
[i
].cputype
&&
269 ((ofile
.arch_flag
.cpusubtype
& ~CPU_SUBTYPE_MASK
) ==
270 (arch_flags
[i
].cpusubtype
& ~CPU_SUBTYPE_MASK
) ||
273 if(ofile
.arch_type
== OFILE_ARCHIVE
){
274 if(member_name
!= NULL
){
275 if(ofile_specific_member(member_name
,
277 processor(&ofile
, arch_name
, cookie
);
278 if(ofile
.headers_swapped
== TRUE
)
279 swap_back_Mach_O(&ofile
);
283 /* loop through archive */
285 printf("Archive : %s", ofile
.file_name
);
286 if(arch_name
!= NULL
)
287 printf(" (architecture %s)",
291 if(ofile_first_member(&ofile
) == TRUE
){
294 if(process_non_objects
== TRUE
||
297 processor(&ofile
, arch_name
,
299 if(ofile
.headers_swapped
==TRUE
)
300 swap_back_Mach_O(&ofile
);
303 }while(ofile_next_member(&ofile
) ==
306 error("for architecture: %s "
307 "archive: %s contains no "
308 "members that are object "
309 "files", ofile
.arch_flag
.name
,
314 error("for architecture: %s archive: "
315 "%s contains no members",
316 ofile
.arch_flag
.name
,
321 else if(process_non_objects
== TRUE
||
322 ofile
.arch_type
== OFILE_Mach_O
){
323 if(ofile
.arch_type
== OFILE_Mach_O
&&
324 (ofile
.mh_filetype
== MH_DYLIB
||
325 ofile
.mh_filetype
== MH_DYLIB_STUB
)){
326 if(dylib_flat
== TRUE
){
327 processor(&ofile
, arch_name
, cookie
);
328 if(ofile
.headers_swapped
== TRUE
)
329 swap_back_Mach_O(&ofile
);
332 if(member_name
!= NULL
){
333 if(ofile_specific_module(
334 member_name
, &ofile
) == TRUE
){
335 processor(&ofile
, arch_name
,
337 if(ofile
.headers_swapped
==TRUE
)
338 swap_back_Mach_O(&ofile
);
342 /*loop through the dynamic library*/
343 if(ofile_first_module(&ofile
)){
345 processor(&ofile
, arch_name
,
347 }while(ofile_next_module(
351 processor(&ofile
, arch_name
,
356 if(ofile
.headers_swapped
== TRUE
)
357 swap_back_Mach_O(&ofile
);
360 if(member_name
!= NULL
)
361 error("for architecture: %s file: %s "
362 "is not an archive and thus does "
363 "not contain member: %s",
364 ofile
.arch_flag
.name
,
368 processor(&ofile
, arch_name
, cookie
);
369 if(ofile
.headers_swapped
== TRUE
)
370 swap_back_Mach_O(&ofile
);
374 else if(ofile
.arch_type
== OFILE_UNKNOWN
){
375 error("for architecture: %s file: %s is "
376 "not an object file",
377 ofile
.arch_flag
.name
,ofile
.file_name
);
379 if(ofile
.headers_swapped
== TRUE
)
380 swap_back_Mach_O(&ofile
);
384 if(ofile
.headers_swapped
== TRUE
)
385 swap_back_Mach_O(&ofile
);
387 }while(ofile_next_arch(&ofile
) == TRUE
);
388 if(arch_found
== FALSE
)
389 error("file: %s does not contain architecture: %s",
390 ofile
.file_name
, arch_flags
[i
].name
);
397 * This is a fat file and no architectures has been specified
398 * so if it contains the host architecture process only that
399 * architecture but if not process all architectures
402 if(all_archs
== FALSE
){
403 (void)get_arch_from_host(&host_arch_flag
, NULL
);
406 * If runing as a 64-bit binary and on an Intel x86 host
409 if(host_arch_flag
.cputype
== CPU_TYPE_I386
)
411 *get_arch_family_from_cputype(CPU_TYPE_X86_64
);
412 #endif /* __LP64__ */
417 get_arch_family_from_cputype(host_arch_flag
.cputype
);
418 if(family_arch_flag
!= NULL
)
420 ((family_arch_flag
->cpusubtype
& ~CPU_SUBTYPE_MASK
) ==
421 (host_arch_flag
.cpusubtype
& ~CPU_SUBTYPE_MASK
));
424 if(ofile_map(name
, NULL
, NULL
, &ofile
, FALSE
) == FALSE
)
426 if(ofile_first_arch(&ofile
) == FALSE
){
431 if(ofile
.arch_flag
.cputype
==
432 host_arch_flag
.cputype
&&
433 ((ofile
.arch_flag
.cpusubtype
& ~CPU_SUBTYPE_MASK
) ==
434 (host_arch_flag
.cpusubtype
& ~CPU_SUBTYPE_MASK
) ||
437 if(ofile
.arch_type
== OFILE_ARCHIVE
){
438 if(member_name
!= NULL
){
439 if(ofile_specific_member(member_name
,
441 processor(&ofile
, NULL
, cookie
);
442 if(ofile
.headers_swapped
== TRUE
)
443 swap_back_Mach_O(&ofile
);
447 /* loop through archive */
449 printf("Archive : %s\n", ofile
.file_name
);
451 if(ofile_first_member(&ofile
) == TRUE
){
454 if(process_non_objects
== TRUE
||
455 ofile
.member_type
== OFILE_Mach_O
){
456 processor(&ofile
, NULL
, cookie
);
457 if(ofile
.headers_swapped
== TRUE
)
458 swap_back_Mach_O(&ofile
);
461 }while(ofile_next_member(&ofile
) ==
464 error("archive: %s contains no "
465 "members that are object "
466 "files", ofile
.file_name
);
470 error("archive: %s contains no "
471 "members", ofile
.file_name
);
475 else if(process_non_objects
== TRUE
||
476 ofile
.arch_type
== OFILE_Mach_O
){
477 if(ofile
.arch_type
== OFILE_Mach_O
&&
478 (ofile
.mh_filetype
== MH_DYLIB
||
479 ofile
.mh_filetype
== MH_DYLIB_STUB
)){
480 if(dylib_flat
== TRUE
){
481 processor(&ofile
, NULL
, cookie
);
484 if(member_name
!= NULL
){
485 if(ofile_specific_module(member_name
,
487 processor(&ofile
, NULL
, cookie
);
490 /* loop through the dynamic library */
491 if(ofile_first_module(&ofile
) == TRUE
){
493 processor(&ofile
, NULL
, cookie
);
494 }while(ofile_next_module(&ofile
));
497 processor(&ofile
, NULL
, cookie
);
501 if(ofile
.headers_swapped
== TRUE
)
502 swap_back_Mach_O(&ofile
);
505 if(member_name
!= NULL
)
506 error("for architecture: %s file: %s is "
507 "not an archive and thus does not "
508 "contain member: %s",
509 ofile
.arch_flag
.name
, ofile
.file_name
,
512 processor(&ofile
, NULL
, cookie
);
513 if(ofile
.headers_swapped
== TRUE
)
514 swap_back_Mach_O(&ofile
);
518 else if(ofile
.arch_type
== OFILE_UNKNOWN
){
519 error("file: %s is not an object file",
524 if(ofile
.headers_swapped
== TRUE
)
525 swap_back_Mach_O(&ofile
);
527 }while(hostflag
== FALSE
&& ofile_next_arch(&ofile
) == TRUE
);
528 if(hostflag
== TRUE
){
535 * Either all architectures have been specified or none have
536 * been specified and it does not contain the host architecture
537 * so do all the architectures in the fat file
540 if(ofile_map(name
, NULL
, NULL
, &ofile
, FALSE
) == FALSE
)
542 if(ofile_first_arch(&ofile
) == FALSE
){
547 if(ofile
.arch_type
== OFILE_ARCHIVE
){
548 if(member_name
!= NULL
){
549 if(ofile_specific_member(member_name
, &ofile
) == TRUE
)
550 processor(&ofile
, ofile
.arch_flag
.name
, cookie
);
553 /* loop through archive */
555 printf("Archive : %s (architecture %s)\n",
556 ofile
.file_name
, ofile
.arch_flag
.name
);
558 if(ofile_first_member(&ofile
) == TRUE
){
561 if(process_non_objects
== TRUE
||
562 ofile
.member_type
== OFILE_Mach_O
){
563 processor(&ofile
, ofile
.arch_flag
.name
,
567 }while(ofile_next_member(&ofile
) == TRUE
);
569 error("for architecture: %s archive: %s "
570 "contains no members that are object "
571 "files", ofile
.arch_flag
.name
,
576 error("for architecture: %s archive: %s "
577 "contains no members",
578 ofile
.arch_flag
.name
, ofile
.file_name
);
582 else if(process_non_objects
== TRUE
||
583 ofile
.arch_type
== OFILE_Mach_O
){
584 if(ofile
.arch_type
== OFILE_Mach_O
&&
585 (ofile
.mh_filetype
== MH_DYLIB
||
586 ofile
.mh_filetype
== MH_DYLIB_STUB
)){
587 if(dylib_flat
== TRUE
){
588 processor(&ofile
, ofile
.arch_flag
.name
, cookie
);
591 if(member_name
!= NULL
){
592 if(ofile_specific_module(member_name
, &ofile
)
594 processor(&ofile
, ofile
.arch_flag
.name
,
598 /* loop through the dynamic library */
599 if(ofile_first_module(&ofile
) == TRUE
){
601 processor(&ofile
, ofile
.arch_flag
.name
,
603 }while(ofile_next_module(&ofile
) == TRUE
);
606 processor(&ofile
, ofile
.arch_flag
.name
,
613 if(member_name
!= NULL
)
614 error("for architecture: %s file: %s is not an "
615 "archive and thus does not contain member: "
616 "%s", ofile
.arch_flag
.name
, ofile
.file_name
,
619 processor(&ofile
, ofile
.arch_flag
.name
, cookie
);
622 else if(ofile
.arch_type
== OFILE_UNKNOWN
){
623 error("for architecture: %s file: %s is not an "
624 "object file", ofile
.arch_flag
.name
,
627 }while(ofile_next_arch(&ofile
) == TRUE
);
629 else if(ofile
.file_type
== OFILE_ARCHIVE
){
630 if(narch_flags
!= 0){
632 for(i
= 0; i
< narch_flags
; i
++){
634 if(narch_flags
== 1){
636 get_arch_family_from_cputype(arch_flags
[0].cputype
);
637 if(family_arch_flag
!= NULL
)
639 ((family_arch_flag
->cpusubtype
&
640 ~CPU_SUBTYPE_MASK
) ==
641 (arch_flags
[0].cpusubtype
&
644 if(ofile
.archive_cputype
== arch_flags
[i
].cputype
&&
645 ((ofile
.archive_cpusubtype
& ~CPU_SUBTYPE_MASK
) ==
646 (arch_flags
[i
].cpusubtype
& ~CPU_SUBTYPE_MASK
) ||
651 error("file: %s does not contain architecture: %s",
652 ofile
.file_name
, arch_flags
[i
].name
);
655 if(arch_found
== FALSE
){
660 if(member_name
!= NULL
){
661 if(ofile_specific_member(member_name
, &ofile
) == TRUE
)
662 processor(&ofile
, NULL
, cookie
);
665 /* loop through archive */
667 printf("Archive : %s\n", ofile
.file_name
);
669 if(ofile_first_member(&ofile
) == TRUE
){
672 if(process_non_objects
== TRUE
||
673 ofile
.member_type
== OFILE_Mach_O
){
674 processor(&ofile
, NULL
, cookie
);
677 }while(ofile_next_member(&ofile
) == TRUE
);
679 error("archive: %s contains no members that are "
680 "object files", ofile
.file_name
);
684 error("archive: %s contains no members",
689 else if(ofile
.file_type
== OFILE_Mach_O
){
690 if(narch_flags
!= 0){
692 for(i
= 0; i
< narch_flags
; i
++){
694 if(narch_flags
== 1){
696 get_arch_family_from_cputype(arch_flags
[0].cputype
);
697 if(family_arch_flag
!= NULL
)
699 ((family_arch_flag
->cpusubtype
&
700 ~CPU_SUBTYPE_MASK
) ==
701 (arch_flags
[0].cpusubtype
&
705 if(ofile
.mh
!= NULL
){
706 if(ofile
.mh
->magic
== MH_MAGIC
&&
707 ofile
.mh
->cputype
== arch_flags
[i
].cputype
&&
708 ((ofile
.mh
->cpusubtype
& ~CPU_SUBTYPE_MASK
) ==
709 (arch_flags
[i
].cpusubtype
& ~CPU_SUBTYPE_MASK
) ||
713 if(ofile
.mh
->magic
== SWAP_INT(MH_MAGIC
) &&
714 (cpu_type_t
)SWAP_INT(ofile
.mh
->cputype
) ==
715 arch_flags
[i
].cputype
&&
716 ((cpu_subtype_t
)SWAP_INT(ofile
.mh
->cpusubtype
&
717 ~CPU_SUBTYPE_MASK
) ==
718 (arch_flags
[i
].cpusubtype
&
719 ~CPU_SUBTYPE_MASK
) ||
724 else if(ofile
.mh64
!= NULL
){
725 if(ofile
.mh64
->magic
== MH_MAGIC_64
&&
726 ofile
.mh64
->cputype
== arch_flags
[i
].cputype
&&
727 ((ofile
.mh64
->cpusubtype
& ~CPU_SUBTYPE_MASK
) ==
728 (arch_flags
[i
].cpusubtype
& ~CPU_SUBTYPE_MASK
) ||
732 if(ofile
.mh64
->magic
== SWAP_INT(MH_MAGIC_64
) &&
733 (cpu_type_t
)SWAP_INT(ofile
.mh64
->cputype
) ==
734 arch_flags
[i
].cputype
&&
735 ((cpu_subtype_t
)SWAP_INT((ofile
.mh64
->cpusubtype
&
736 ~CPU_SUBTYPE_MASK
)) ==
737 (arch_flags
[i
].cpusubtype
& ~CPU_SUBTYPE_MASK
) ||
744 if(ofile
.mh_cputype
== arch_flags
[i
].cputype
&&
745 ((ofile
.mh_cpusubtype
& ~CPU_SUBTYPE_MASK
) ==
746 (arch_flags
[i
].cpusubtype
& ~CPU_SUBTYPE_MASK
) ||
751 error("file: %s does not contain architecture: %s",
752 ofile
.file_name
, arch_flags
[i
].name
);
755 if(arch_found
== FALSE
){
760 if(ofile
.mh_filetype
== MH_DYLIB
||
761 ofile
.mh_filetype
== MH_DYLIB_STUB
){
762 if(dylib_flat
== TRUE
){
763 processor(&ofile
, NULL
, cookie
);
766 if(member_name
!= NULL
){
767 if(ofile_specific_module(member_name
, &ofile
) == TRUE
)
768 processor(&ofile
, NULL
, cookie
);
771 /* loop through the dynamic library */
772 if(ofile_first_module(&ofile
) == TRUE
){
774 processor(&ofile
, NULL
, cookie
);
775 }while(ofile_next_module(&ofile
) == TRUE
);
778 processor(&ofile
, NULL
, cookie
);
784 if(member_name
!= NULL
)
785 error("file: %s is not an archive and thus does not contain"
786 " member: %s", ofile
.file_name
, member_name
);
788 processor(&ofile
, NULL
, cookie
);
792 if(process_non_objects
== TRUE
)
793 processor(&ofile
, NULL
, cookie
);
794 else if(member_name
!= NULL
)
795 error("file: %s(%s) is not an object file", name
,
798 error("file: %s is not an object file", name
);
802 #endif /* !defined(OFI) */
805 * ofile_map maps in the object file specified by file_name, arch_flag and
806 * object_name and fills in the ofile struct pointed to by ofile for it.
807 * When arch_flag and object_name are both NULL, the file is just set up into
808 * ofile (if the file can be opened and mapped in, if not this call fails
809 * are error routnes are called). If arch_flag is not NULL and object_file is
810 * NULL, then the file must be a Mach-O file or a fat file with the architecture
811 * specified in the arch_flag, if not this call fails and error routines are
812 * called. When arch_flag and object_name are both not NULL, then the file must
813 * be an archive or a fat file containing archives for the specified architec-
814 * ture and contain an archive member object file with the name object_name,
815 * otherwise this call fails and error routines are called. If arch_flag is
816 * NULL and object_file is not NULL, then the file name must be an archive (not
817 * a fat file containing archives) and contain an archive member object file
818 * with the name object_name, otherwise this call fails and calls error
819 * routines. If this call suceeds then it returns non-zero and the ofile
820 * structure pointed to by ofile is filled in. If this call fails it returns 0
821 * and calls error routines to print error messages and clears the
822 * ofile structure pointed to by ofile.
826 NSObjectFileImageReturnCode
831 const char *file_name
,
832 const struct arch_flag
*arch_flag
, /* can be NULL */
833 const char *object_name
, /* can be NULL */
835 enum bool archives_with_fat_objects
)
838 struct stat stat_buf
;
839 uint32_t size
, magic
;
842 magic
= 0; /* to shut up the compiler warning message */
843 memset(ofile
, '\0', sizeof(struct ofile
));
845 /* Open the file and map it in */
846 if((fd
= open(file_name
, O_RDONLY
)) == -1){
848 return(NSObjectFileImageAccess
);
850 system_error("can't open file: %s", file_name
);
854 if(fstat(fd
, &stat_buf
) == -1){
857 return(NSObjectFileImageAccess
);
859 system_error("can't stat file: %s", file_name
);
863 size
= stat_buf
.st_size
;
867 addr
= mmap(0, size
, PROT_READ
|PROT_WRITE
, MAP_FILE
|MAP_PRIVATE
, fd
,
869 if((intptr_t)addr
== -1){
870 system_error("can't map file: %s", file_name
);
877 if(otool_first_ofile_map
&& Wflag
)
878 printf("Modification time = %ld\n", (long int)stat_buf
.st_mtime
);
881 return(ofile_map_from_memory(addr
, size
, file_name
, stat_buf
.st_mtime
,
882 arch_flag
, object_name
, ofile
, archives_with_fat_objects
));
886 * ofile_map_from_memory() is the guts of ofile_map() but with an interface
887 * to pass the address and size of the file already mapped in.
891 NSObjectFileImageReturnCode
895 ofile_map_from_memory(
898 const char *file_name
,
900 const struct arch_flag
*arch_flag
, /* can be NULL */
901 const char *object_name
, /* can be NULL */
903 enum bool archives_with_fat_objects
)
907 enum byte_sex host_byte_sex
;
908 struct arch_flag host_arch_flag
;
910 const struct arch_flag
*family_arch_flag
;
913 uint32_t small_nfat_arch
;
916 /* fill in the start of the ofile structure */
917 ofile
->file_name
= savestr(file_name
);
918 if(ofile
->file_name
== NULL
)
920 ofile
->file_addr
= addr
;
921 ofile
->file_size
= size
;
922 ofile
->file_mtime
= mtime
;
924 /* Try to figure out what kind of file this is */
926 if(size
>= sizeof(uint32_t)){
927 magic
= *((uint32_t *)addr
);
929 host_byte_sex
= get_host_byte_sex();
931 /* see if this file is a fat file (always in big endian byte sex) */
932 #ifdef __BIG_ENDIAN__
933 if(size
>= sizeof(struct fat_header
) && magic
== FAT_MAGIC
)
934 #endif /* __BIG_ENDIAN__ */
935 #ifdef __LITTLE_ENDIAN__
936 if(size
>= sizeof(struct fat_header
) && SWAP_INT(magic
) == FAT_MAGIC
)
937 #endif /* __LITTLE_ENDIAN__ */
939 ofile
->file_type
= OFILE_FAT
;
940 ofile
->fat_header
= (struct fat_header
*)addr
;
941 #ifdef __LITTLE_ENDIAN__
942 swap_fat_header(ofile
->fat_header
, host_byte_sex
);
943 #endif /* __LITTLE_ENDIAN__ */
945 if(otool_first_ofile_map
&& fflag
)
946 printf("Fat headers\n");
948 big_size
= ofile
->fat_header
->nfat_arch
;
949 big_size
*= sizeof(struct fat_arch
);
950 big_size
+= sizeof(struct fat_header
);
953 error("fat file: %s truncated or malformed (fat_arch structs "
954 "would extend past the end of the file)", file_name
);
955 ofile
->fat_archs
= allocate(size
- sizeof(struct fat_header
));
956 memset(ofile
->fat_archs
, '\0',
957 size
- sizeof(struct fat_header
));
958 memcpy(ofile
->fat_archs
,
959 addr
+ sizeof(struct fat_header
),
960 size
- sizeof(struct fat_header
));
961 small_nfat_arch
= (size
- sizeof(struct fat_header
)) /
962 sizeof(struct fat_arch
);
963 #ifdef __LITTLE_ENDIAN__
964 swap_fat_arch(ofile
->fat_archs
, small_nfat_arch
,
966 #endif /* __LITTLE_ENDIAN__ */
967 if(otool_first_ofile_map
&& fflag
)
968 print_fat_headers(ofile
->fat_header
, ofile
->fat_archs
,
970 free(ofile
->fat_archs
);
973 #else /* !defined(OTOOL) */
977 ofile
->fat_archs
= (struct fat_arch
*)(addr
+
978 sizeof(struct fat_header
));
979 #ifdef __LITTLE_ENDIAN__
980 swap_fat_arch(ofile
->fat_archs
, ofile
->fat_header
->nfat_arch
,
982 #endif /* __LITTLE_ENDIAN__ */
984 if(otool_first_ofile_map
&& fflag
)
985 print_fat_headers(ofile
->fat_header
, ofile
->fat_archs
,
988 if(check_fat(ofile
) == CHECK_BAD
){
991 return(NSObjectFileImageFormat
);
997 * Now that the fat file is mapped fill in the ofile to the level
998 * the caller wants based on the arch_flag and object_name passed.
999 * If the caller did not specify an arch_flag or an object_name
1000 * then everything the caller wants is done.
1002 if(arch_flag
== NULL
&& object_name
== NULL
)
1004 if(arch_flag
== NULL
){
1005 if(get_arch_from_host(&host_arch_flag
, NULL
) == 0){
1006 error("can't determine the host architecture (specify an "
1007 "arch_flag or fix get_arch_from_host() )");
1010 ofile
->arch_flag
.name
= savestr(host_arch_flag
.name
);
1011 if(ofile
->arch_flag
.name
== NULL
)
1013 ofile
->arch_flag
.cputype
= host_arch_flag
.cputype
;
1014 ofile
->arch_flag
.cpusubtype
= host_arch_flag
.cpusubtype
;
1017 ofile
->arch_flag
.name
= savestr(arch_flag
->name
);
1018 if(ofile
->arch_flag
.name
== NULL
)
1020 ofile
->arch_flag
.cputype
= arch_flag
->cputype
;
1021 ofile
->arch_flag
.cpusubtype
= arch_flag
->cpusubtype
;
1024 ofile
->narch
= UINT_MAX
;
1025 for(i
= 0; i
< ofile
->fat_header
->nfat_arch
; i
++){
1026 if(ofile
->fat_archs
[i
].cputype
==
1027 ofile
->arch_flag
.cputype
&&
1028 (ofile
->fat_archs
[i
].cpusubtype
& ~CPU_SUBTYPE_MASK
) ==
1029 (ofile
->arch_flag
.cpusubtype
& ~CPU_SUBTYPE_MASK
)){
1034 if(ofile
->narch
== UINT_MAX
){
1037 get_arch_family_from_cputype(ofile
->arch_flag
.cputype
);
1038 if(family_arch_flag
!= NULL
)
1039 family
= (enum bool)
1040 ((family_arch_flag
->cpusubtype
& ~CPU_SUBTYPE_MASK
) ==
1041 (ofile
->arch_flag
.cpusubtype
& ~CPU_SUBTYPE_MASK
));
1042 ofile
->narch
= UINT_MAX
;
1043 for(i
= 0; i
< ofile
->fat_header
->nfat_arch
; i
++){
1044 if(ofile
->fat_archs
[i
].cputype
==
1045 ofile
->arch_flag
.cputype
&&
1047 (ofile
->fat_archs
[i
].cpusubtype
& ~CPU_SUBTYPE_MASK
) ==
1048 (ofile
->arch_flag
.cpusubtype
& ~CPU_SUBTYPE_MASK
))){
1049 ofile
->arch_flag
.cpusubtype
=
1050 ofile
->fat_archs
[i
].cpusubtype
;
1056 if(ofile
->narch
== UINT_MAX
){
1059 return(NSObjectFileImageArch
);
1061 error("fat file: %s does not contain architecture %s",
1062 ofile
->file_name
, arch_flag
->name
);
1067 /* Now determine the file type for this specific architecture */
1068 size
= ofile
->fat_archs
[i
].size
;
1069 addr
= addr
+ ofile
->fat_archs
[i
].offset
;
1070 if(size
>= sizeof(struct mach_header
))
1071 memcpy(&magic
, addr
, sizeof(uint32_t));
1072 /* see if this file is a 32-bit Mach-O file */
1073 if(size
>= sizeof(struct mach_header
) &&
1074 (magic
== MH_MAGIC
||
1075 magic
== SWAP_INT(MH_MAGIC
))){
1076 #ifdef ALIGNMENT_CHECKS
1077 if(ofile
->fat_archs
[i
].offset
% 4 != 0){
1078 error("fat file: %s architecture %s malformed for a 32-bit "
1079 "object file (offset is not a multiple of 4)",
1080 ofile
->file_name
, arch_flag
->name
);
1083 return(NSObjectFileImageFormat
);
1088 #endif /* ALIGNMENT_CHECKS */
1089 ofile
->arch_type
= OFILE_Mach_O
;
1090 ofile
->object_addr
= addr
;
1091 ofile
->object_size
= size
;
1092 if(magic
== MH_MAGIC
)
1093 ofile
->object_byte_sex
= host_byte_sex
;
1095 ofile
->object_byte_sex
=
1096 host_byte_sex
== BIG_ENDIAN_BYTE_SEX
?
1097 LITTLE_ENDIAN_BYTE_SEX
: BIG_ENDIAN_BYTE_SEX
;
1098 ofile
->mh
= (struct mach_header
*)addr
;
1099 ofile
->load_commands
= (struct load_command
*)(addr
+
1100 sizeof(struct mach_header
));
1101 if(check_Mach_O(ofile
) == CHECK_BAD
){
1104 return(NSObjectFileImageFormat
);
1109 if(object_name
!= NULL
){
1110 error("fat file: %s architecture %s is not an archive "
1111 "(object_name to ofile_map() can't be specified to "
1112 "be other than NULL)", ofile
->file_name
,
1117 /* see if this file is a 64-bit Mach-O file */
1118 else if(size
>= sizeof(struct mach_header_64
) &&
1119 (magic
== MH_MAGIC_64
||
1120 magic
== SWAP_INT(MH_MAGIC_64
))){
1121 #ifdef ALIGNMENT_CHECKS
1122 if(ofile
->fat_archs
[i
].offset
% 8 != 0){
1123 error("fat file: %s architecture %s malformed for a 64-bit "
1124 "object file (offset is not a multiple of 8)",
1125 ofile
->file_name
, arch_flag
->name
);
1128 return(NSObjectFileImageFormat
);
1133 #endif /* ALIGNMENT_CHECKS */
1134 ofile
->arch_type
= OFILE_Mach_O
;
1135 ofile
->object_addr
= addr
;
1136 ofile
->object_size
= size
;
1137 if(magic
== MH_MAGIC_64
)
1138 ofile
->object_byte_sex
= host_byte_sex
;
1140 ofile
->object_byte_sex
=
1141 host_byte_sex
== BIG_ENDIAN_BYTE_SEX
?
1142 LITTLE_ENDIAN_BYTE_SEX
: BIG_ENDIAN_BYTE_SEX
;
1143 ofile
->mh64
= (struct mach_header_64
*)addr
;
1144 ofile
->load_commands
= (struct load_command
*)(addr
+
1145 sizeof(struct mach_header_64
));
1146 if(check_Mach_O(ofile
) == CHECK_BAD
){
1149 return(NSObjectFileImageFormat
);
1154 if(object_name
!= NULL
){
1155 error("fat file: %s architecture %s is not an archive "
1156 "(object_name to ofile_map() can't be specified to "
1157 "be other than NULL)", ofile
->file_name
,
1162 /* see if this file is an archive file */
1163 else if(size
>= SARMAG
&& strncmp(addr
, ARMAG
, SARMAG
) == 0){
1164 ofile
->arch_type
= OFILE_ARCHIVE
;
1165 if(check_archive(ofile
, FALSE
) == CHECK_BAD
){
1168 return(NSObjectFileImageInappropriateFile
);
1173 #ifdef ALIGNMENT_CHECKS
1174 if(ofile
->archive_cputype
!= 0 &&
1175 ofile
->fat_archs
[i
].offset
% sizeof(uint32_t) != 0){
1176 error("fat file: %s architecture %s malformed archive that "
1177 "contains object files (offset to archive is not a "
1178 "multiple of sizeof(uint32_t))",
1179 ofile
->file_name
, arch_flag
->name
);
1182 return(NSObjectFileImageInappropriateFile
);
1187 #endif /* ALIGNMENT_CHECKS */
1188 if(object_name
!= NULL
){
1189 if(ofile_specific_member(object_name
, ofile
) == FALSE
)
1193 /* this file type is now known to be unknown to this program */
1195 ofile
->file_type
= OFILE_UNKNOWN
;
1196 if(object_name
!= NULL
){
1197 error("fat file: %s architecture %s is not an archive "
1198 "(object_name to ofile_map() can't be specified to "
1199 "be other than NULL)", ofile
->file_name
,
1205 /* see if this file is a 32-bit Mach-O file */
1206 else if(size
>= sizeof(struct mach_header
) &&
1207 (magic
== MH_MAGIC
||
1208 magic
== SWAP_INT(MH_MAGIC
))){
1209 ofile
->file_type
= OFILE_Mach_O
;
1210 ofile
->object_addr
= addr
;
1211 ofile
->object_size
= size
;
1212 if(magic
== MH_MAGIC
)
1213 ofile
->object_byte_sex
= host_byte_sex
;
1215 ofile
->object_byte_sex
= host_byte_sex
== BIG_ENDIAN_BYTE_SEX
?
1216 LITTLE_ENDIAN_BYTE_SEX
: BIG_ENDIAN_BYTE_SEX
;
1217 ofile
->mh
= (struct mach_header
*)addr
;
1218 ofile
->load_commands
= (struct load_command
*)(addr
+
1219 sizeof(struct mach_header
));
1220 if(check_Mach_O(ofile
) == CHECK_BAD
){
1223 return(NSObjectFileImageFormat
);
1228 if(object_name
!= NULL
){
1229 error("file: %s is not an archive (object_name to ofile_map() "
1230 "can't be specified to be other than NULL)",
1234 if(arch_flag
!= NULL
){
1235 if(arch_flag
->cputype
!= ofile
->mh_cputype
&&
1236 (arch_flag
->cpusubtype
& ~CPU_SUBTYPE_MASK
) !=
1237 (ofile
->mh_cpusubtype
& ~CPU_SUBTYPE_MASK
)){
1240 return(NSObjectFileImageArch
);
1242 error("object file: %s does not match specified arch_flag: "
1243 "%s passed to ofile_map()", ofile
->file_name
,
1252 /* see if this file is a 64-bit Mach-O file */
1253 else if(size
>= sizeof(struct mach_header_64
) &&
1254 (magic
== MH_MAGIC_64
||
1255 magic
== SWAP_INT(MH_MAGIC_64
))){
1256 ofile
->file_type
= OFILE_Mach_O
;
1257 ofile
->object_addr
= addr
;
1258 ofile
->object_size
= size
;
1259 if(magic
== MH_MAGIC_64
)
1260 ofile
->object_byte_sex
= host_byte_sex
;
1262 ofile
->object_byte_sex
= host_byte_sex
== BIG_ENDIAN_BYTE_SEX
?
1263 LITTLE_ENDIAN_BYTE_SEX
: BIG_ENDIAN_BYTE_SEX
;
1264 ofile
->mh64
= (struct mach_header_64
*)addr
;
1265 ofile
->load_commands
= (struct load_command
*)(addr
+
1266 sizeof(struct mach_header_64
));
1267 if(check_Mach_O(ofile
) == CHECK_BAD
){
1270 return(NSObjectFileImageFormat
);
1275 if(object_name
!= NULL
){
1276 error("file: %s is not an archive (object_name to ofile_map() "
1277 "can't be specified to be other than NULL)",
1281 if(arch_flag
!= NULL
){
1282 if(arch_flag
->cputype
!= ofile
->mh_cputype
&&
1283 (arch_flag
->cpusubtype
& ~CPU_SUBTYPE_MASK
) !=
1284 (ofile
->mh_cpusubtype
& ~CPU_SUBTYPE_MASK
)){
1287 return(NSObjectFileImageArch
);
1289 error("object file: %s does not match specified arch_flag: "
1290 "%s passed to ofile_map()", ofile
->file_name
,
1299 /* see if this file is an archive file */
1300 else if(size
>= SARMAG
&& strncmp(addr
, ARMAG
, SARMAG
) == 0){
1301 ofile
->file_type
= OFILE_ARCHIVE
;
1302 if(check_archive(ofile
, archives_with_fat_objects
) == CHECK_BAD
)
1304 if(object_name
!= NULL
){
1305 if(ofile_specific_member(object_name
, ofile
) == FALSE
)
1307 if(arch_flag
!= NULL
){
1308 if(arch_flag
->cputype
!= ofile
->mh_cputype
&&
1309 (arch_flag
->cpusubtype
& ~CPU_SUBTYPE_MASK
) !=
1310 (ofile
->mh_cpusubtype
& ~CPU_SUBTYPE_MASK
)){
1311 error("object file: %s(%.*s) does not match specified "
1312 "arch_flag: %s passed to ofile_map()",
1313 ofile
->file_name
, (int)ofile
->member_name_size
,
1314 ofile
->member_name
, arch_flag
->name
);
1320 if(arch_flag
!= NULL
){
1321 if(arch_flag
->cputype
!= ofile
->archive_cputype
&&
1322 (arch_flag
->cpusubtype
& ~CPU_SUBTYPE_MASK
) !=
1323 (ofile
->archive_cpusubtype
& ~CPU_SUBTYPE_MASK
)){
1324 error("archive file: %s objects do not match specified "
1325 "arch_flag: %s passed to ofile_map()",
1326 ofile
->file_name
, arch_flag
->name
);
1332 /* this file type is now known to be unknown to this program */
1339 if(is_llvm_bitcode(ofile
, ofile
->file_addr
, ofile
->file_size
) ==
1341 ofile
->file_type
= OFILE_LLVM_BITCODE
;
1342 if(arch_flag
!= NULL
){
1343 if(arch_flag
->cputype
!= ofile
->lto_cputype
&&
1344 (arch_flag
->cpusubtype
& ~CPU_SUBTYPE_MASK
) !=
1345 (ofile
->lto_cpusubtype
& ~CPU_SUBTYPE_MASK
)){
1346 error("llvm bitcode file: %s does not match specified "
1347 "arch_flag: %s passed to ofile_map()",
1348 ofile
->file_name
, arch_flag
->name
);
1352 if(object_name
!= NULL
){
1353 error("file: %s is not an archive (object_name to "
1354 "ofile_map() can't be specified to be other than "
1355 "NULL)", ofile
->file_name
);
1361 #endif /* LTO_SUPPORT */
1363 ofile
->file_type
= OFILE_UNKNOWN
;
1364 if(arch_flag
!= NULL
){
1367 return(NSObjectFileImageInappropriateFile
);
1369 error("file: %s is unknown type (arch_flag to ofile_map() "
1370 "can't be specified to be other than NULL)",
1376 if(object_name
!= NULL
){
1377 error("file: %s is not an archive (object_name to ofile_map() "
1378 "can't be specified to be other than NULL)",
1392 * ofile_unmap() deallocates the memory associated with the specified ofile
1398 struct ofile
*ofile
)
1402 if(ofile
->file_addr
!= NULL
){
1403 if((r
= vm_deallocate(mach_task_self(),
1404 (vm_address_t
)ofile
->file_addr
,
1405 (vm_size_t
)ofile
->file_size
)) != KERN_SUCCESS
){
1406 my_mach_error(r
, "Can't vm_deallocate mapped memory for file: "
1407 "%s", ofile
->file_name
);
1410 if(ofile
->file_name
!= NULL
)
1411 free(ofile
->file_name
);
1412 if(ofile
->arch_flag
.name
!= NULL
)
1413 free(ofile
->arch_flag
.name
);
1414 memset(ofile
, '\0', sizeof(struct ofile
));
1418 * ofile_first_arch() sets up the ofile struct for a fat file to the first arch
1424 struct ofile
*ofile
)
1426 if(ofile
->file_type
== OFILE_FAT
||
1427 (ofile
->file_type
== OFILE_ARCHIVE
&&
1428 ofile
->member_type
== OFILE_FAT
) )
1429 return(ofile_specific_arch(ofile
, 0));
1431 error("ofile_first_arch() called and file type of: %s is not a fat "
1432 "file\n", ofile
->file_name
);
1438 * ofile_next_arch() sets up the ofile struct for a fat file to the next arch
1444 struct ofile
*ofile
)
1446 if(ofile
->file_type
== OFILE_FAT
||
1447 (ofile
->file_type
== OFILE_ARCHIVE
&&
1448 ofile
->member_type
== OFILE_FAT
) ){
1449 if(ofile
->narch
+ 1 < ofile
->fat_header
->nfat_arch
)
1450 return(ofile_specific_arch(ofile
, ofile
->narch
+ 1));
1455 error("ofile_next_arch() called and file type of: %s is not a fat "
1456 "file\n", ofile
->file_name
);
1462 * ofile_specific_arch() sets up the ofile struct for the fat file for the
1467 ofile_specific_arch(
1468 struct ofile
*ofile
,
1474 enum byte_sex host_byte_sex
;
1476 ofile
->narch
= narch
;
1477 ofile
->arch_type
= OFILE_UNKNOWN
;
1478 if(ofile
->arch_flag
.name
!= NULL
)
1479 free(ofile
->arch_flag
.name
);
1480 ofile
->arch_flag
.name
= NULL
;
1481 ofile
->arch_flag
.cputype
= 0;
1482 ofile
->arch_flag
.cpusubtype
= 0;
1483 ofile
->archive_cputype
= 0;
1484 ofile
->archive_cpusubtype
= 0;
1485 ofile
->object_addr
= NULL
;
1486 ofile
->object_size
= 0;
1487 ofile
->object_byte_sex
= UNKNOWN_BYTE_SEX
;
1490 ofile
->load_commands
= NULL
;
1492 ofile
->arch_flag
.cputype
= ofile
->fat_archs
[ofile
->narch
].cputype
;
1493 ofile
->arch_flag
.cpusubtype
= ofile
->fat_archs
[ofile
->narch
].cpusubtype
;
1494 set_arch_flag_name(&(ofile
->arch_flag
));
1497 /* Now determine the file type for this specific architecture */
1498 if(ofile
->file_type
== OFILE_FAT
){
1499 ofile
->member_offset
= 0;
1500 ofile
->member_addr
= NULL
;
1501 ofile
->member_size
= 0;
1502 ofile
->member_ar_hdr
= NULL
;
1503 ofile
->member_type
= OFILE_UNKNOWN
;
1505 size
= ofile
->fat_archs
[ofile
->narch
].size
;
1506 addr
= ofile
->file_addr
+ ofile
->fat_archs
[ofile
->narch
].offset
;
1509 if(ofile
->file_type
!= OFILE_ARCHIVE
||
1510 ofile
->member_type
!= OFILE_FAT
){
1511 error("internal error. ofile_specific_arch() called but file "
1512 "is not a fat file or an archive with a fat member ");
1514 size
= ofile
->fat_archs
[ofile
->narch
].size
;
1515 addr
= ofile
->file_addr
+
1516 ofile
->member_offset
+
1517 ofile
->fat_archs
[ofile
->narch
].offset
;
1521 if(addr
- ofile
->file_addr
> (ptrdiff_t)ofile
->file_size
){
1522 error("fat file: %s offset to architecture %s extends past end "
1523 "of file", ofile
->file_name
, ofile
->arch_flag
.name
);
1526 if(addr
+ size
> ofile
->file_addr
+ ofile
->file_size
)
1527 size
= (ofile
->file_addr
+ ofile
->file_size
) - addr
;
1530 if(size
>= sizeof(struct mach_header
))
1531 memcpy(&magic
, addr
, sizeof(uint32_t));
1532 /* see if this file is a 32-bit Mach-O file */
1533 if(size
>= sizeof(struct mach_header
) &&
1534 (magic
== MH_MAGIC
|| magic
== SWAP_INT(MH_MAGIC
))){
1535 #ifdef ALIGNMENT_CHECKS
1536 if(ofile
->fat_archs
[ofile
->narch
].offset
% 4 != 0){
1537 if(ofile
->file_type
== OFILE_ARCHIVE
){
1538 error("fat file: %s(%.*s) architecture %s malformed for a "
1539 "32-bit object file (offset is not a multiple of 4)",
1540 ofile
->file_name
, (int)ofile
->member_name_size
,
1541 ofile
->member_name
, ofile
->arch_flag
.name
);
1544 error("fat file: %s architecture %s malformed for a 32-bit "
1545 "object file (offset is not a multiple of 4)",
1546 ofile
->file_name
, ofile
->arch_flag
.name
);
1549 #endif /* ALIGNMENT_CHECKS */
1550 ofile
->arch_type
= OFILE_Mach_O
;
1551 ofile
->object_addr
= addr
;
1552 ofile
->object_size
= size
;
1553 host_byte_sex
= get_host_byte_sex();
1554 if(magic
== MH_MAGIC
)
1555 ofile
->object_byte_sex
= host_byte_sex
;
1557 ofile
->object_byte_sex
=
1558 host_byte_sex
== BIG_ENDIAN_BYTE_SEX
?
1559 LITTLE_ENDIAN_BYTE_SEX
: BIG_ENDIAN_BYTE_SEX
;
1560 ofile
->mh
= (struct mach_header
*)addr
;
1561 ofile
->load_commands
= (struct load_command
*)(addr
+
1562 sizeof(struct mach_header
));
1563 if(check_Mach_O(ofile
) == CHECK_BAD
)
1566 /* see if this file is a 64-bit Mach-O file */
1567 else if(size
>= sizeof(struct mach_header_64
) &&
1568 (magic
== MH_MAGIC_64
|| magic
== SWAP_INT(MH_MAGIC_64
))){
1569 #ifdef ALIGNMENT_CHECKS
1570 if(ofile
->fat_archs
[ofile
->narch
].offset
% 8 != 0){
1571 if(ofile
->file_type
== OFILE_ARCHIVE
){
1572 error("fat file: %s(%.*s) architecture %s malformed for an "
1573 "object file (offset is not a multiple of 8)",
1574 ofile
->file_name
, (int)ofile
->member_name_size
,
1575 ofile
->member_name
, ofile
->arch_flag
.name
);
1578 error("fat file: %s architecture %s malformed for a 64-bit "
1579 "object file (offset is not a multiple of 8",
1580 ofile
->file_name
, ofile
->arch_flag
.name
);
1583 #endif /* ALIGNMENT_CHECKS */
1584 ofile
->arch_type
= OFILE_Mach_O
;
1585 ofile
->object_addr
= addr
;
1586 ofile
->object_size
= size
;
1587 host_byte_sex
= get_host_byte_sex();
1588 if(magic
== MH_MAGIC_64
)
1589 ofile
->object_byte_sex
= host_byte_sex
;
1591 ofile
->object_byte_sex
=
1592 host_byte_sex
== BIG_ENDIAN_BYTE_SEX
?
1593 LITTLE_ENDIAN_BYTE_SEX
: BIG_ENDIAN_BYTE_SEX
;
1594 ofile
->mh64
= (struct mach_header_64
*)addr
;
1595 ofile
->load_commands
= (struct load_command
*)(addr
+
1596 sizeof(struct mach_header_64
));
1597 if(check_Mach_O(ofile
) == CHECK_BAD
)
1600 /* see if this file is an archive file */
1601 else if(size
>= SARMAG
&& strncmp(addr
, ARMAG
, SARMAG
) == 0){
1602 ofile
->arch_type
= OFILE_ARCHIVE
;
1603 if(check_archive(ofile
, FALSE
) == CHECK_BAD
)
1605 #ifdef ALIGNMENT_CHECKS
1606 if(ofile
->archive_cputype
!= 0 &&
1607 ofile
->fat_archs
[ofile
->narch
].offset
%
1608 sizeof(uint32_t) != 0){
1609 error("fat file: %s architecture %s malformed archive that "
1610 "contains object files (offset to archive is not a "
1611 "multiple of sizeof(uint32_t))",
1612 ofile
->file_name
, ofile
->arch_flag
.name
);
1615 #endif /* ALIGNMENT_CHECKS */
1618 * This type for this architecture is now known to be unknown to this
1622 ofile
->arch_type
= OFILE_UNKNOWN
;
1627 ofile
->arch_type
= OFILE_UNKNOWN
;
1628 if(ofile
->arch_flag
.name
!= NULL
)
1629 free(ofile
->arch_flag
.name
);
1630 ofile
->arch_flag
.name
= NULL
;
1631 ofile
->arch_flag
.cputype
= 0;
1632 ofile
->arch_flag
.cpusubtype
= 0;
1633 if(ofile
->file_type
!= OFILE_ARCHIVE
){
1634 ofile
->member_offset
= 0;
1635 ofile
->member_addr
= NULL
;
1636 ofile
->member_size
= 0;
1637 ofile
->member_ar_hdr
= NULL
;
1638 ofile
->member_type
= OFILE_UNKNOWN
;
1640 ofile
->archive_cputype
= 0;
1641 ofile
->archive_cpusubtype
= 0;
1642 ofile
->object_addr
= NULL
;
1643 ofile
->object_size
= 0;
1644 ofile
->object_byte_sex
= UNKNOWN_BYTE_SEX
;
1647 ofile
->load_commands
= NULL
;
1652 * ofile_first_member() set up the ofile structure (the member_* fields and
1653 * the object file fields if the first member is an object file) for the first
1659 struct ofile
*ofile
)
1662 uint32_t size
, offset
;
1664 enum byte_sex host_byte_sex
;
1665 struct ar_hdr
*ar_hdr
;
1666 uint32_t ar_name_size
;
1668 /* These fields are to be filled in by this routine, clear them first */
1669 ofile
->member_offset
= 0;
1670 ofile
->member_addr
= NULL
;
1671 ofile
->member_size
= 0;
1672 ofile
->member_ar_hdr
= NULL
;
1673 ofile
->member_name
= NULL
;
1674 ofile
->member_name_size
= 0;
1675 ofile
->member_type
= OFILE_UNKNOWN
;
1676 ofile
->object_addr
= NULL
;
1677 ofile
->object_size
= 0;
1678 ofile
->object_byte_sex
= UNKNOWN_BYTE_SEX
;
1681 ofile
->load_commands
= NULL
;
1684 * Note: it is up to the caller if they want to call free_lto() on this
1685 * when iterating through the members of an archive.
1688 #endif /* LTO_SUPPORT */
1691 * Get the address and size of the archive.
1693 if(ofile
->file_type
== OFILE_FAT
){
1694 if(ofile
->arch_type
!= OFILE_ARCHIVE
){
1695 error("ofile_first_member() called on fat file: %s with a "
1696 "non-archive architecture or no architecture selected\n",
1700 addr
= ofile
->file_addr
+ ofile
->fat_archs
[ofile
->narch
].offset
;
1701 size
= ofile
->fat_archs
[ofile
->narch
].size
;
1703 else if(ofile
->file_type
== OFILE_ARCHIVE
){
1704 addr
= ofile
->file_addr
;
1705 size
= ofile
->file_size
;
1708 error("ofile_first_member() called and file type of %s is "
1709 "OFILE_UNKNOWN\n", ofile
->file_name
);
1713 if((addr
+ SARMAG
) - ofile
->file_addr
> (ptrdiff_t)ofile
->file_size
){
1714 archive_error(ofile
, "offset to first member extends past the end "
1718 if(addr
+ size
> ofile
->file_addr
+ ofile
->file_size
)
1719 size
= (ofile
->file_addr
+ ofile
->file_size
) - addr
;
1721 if(size
< SARMAG
|| strncmp(addr
, ARMAG
, SARMAG
) != 0){
1722 archive_error(ofile
, "internal error. ofile_first_member() "
1723 "called but file does not have an archive magic "
1729 if(offset
!= size
&& offset
+ sizeof(struct ar_hdr
) > size
){
1730 archive_error(ofile
, "truncated or malformed (archive header of "
1731 "first member extends past the end of the file)");
1735 /* check for empty archive */
1739 /* now we know there is a first member so set it up */
1740 ar_hdr
= (struct ar_hdr
*)(addr
+ offset
);
1741 offset
+= sizeof(struct ar_hdr
);
1742 ofile
->member_offset
= offset
;
1743 ofile
->member_addr
= addr
+ offset
;
1744 ofile
->member_size
= strtoul(ar_hdr
->ar_size
, NULL
, 10);
1745 ofile
->member_ar_hdr
= ar_hdr
;
1746 ofile
->member_type
= OFILE_UNKNOWN
;
1747 ofile
->member_name
= ar_hdr
->ar_name
;
1748 if(strncmp(ofile
->member_name
, AR_EFMT1
, sizeof(AR_EFMT1
) - 1) == 0){
1749 ofile
->member_name
= ar_hdr
->ar_name
+ sizeof(struct ar_hdr
);
1750 ar_name_size
= strtoul(ar_hdr
->ar_name
+ sizeof(AR_EFMT1
) - 1,
1752 ofile
->member_name_size
= ar_name_size
;
1753 ofile
->member_offset
+= ar_name_size
;
1754 ofile
->member_addr
+= ar_name_size
;
1755 ofile
->member_size
-= ar_name_size
;
1758 ofile
->member_name_size
= size_ar_name(ar_hdr
);
1761 /* Clear these in case there is no table of contents */
1762 ofile
->toc_addr
= NULL
;
1763 ofile
->toc_size
= 0;
1764 ofile
->toc_ar_hdr
= NULL
;
1765 ofile
->toc_name
= NULL
;
1766 ofile
->toc_name_size
= 0;
1767 ofile
->toc_ranlibs
= NULL
;
1768 ofile
->toc_nranlibs
= 0;
1769 ofile
->toc_strings
= NULL
;
1770 ofile
->toc_strsize
= 0;
1771 ofile
->toc_bad
= FALSE
;
1773 host_byte_sex
= get_host_byte_sex();
1775 if(ofile
->member_size
> sizeof(uint32_t)){
1776 memcpy(&magic
, ofile
->member_addr
, sizeof(uint32_t));
1777 #ifdef __BIG_ENDIAN__
1778 if(magic
== FAT_MAGIC
)
1779 #endif /* __BIG_ENDIAN__ */
1780 #ifdef __LITTLE_ENDIAN__
1781 if(magic
== SWAP_INT(FAT_MAGIC
))
1782 #endif /* __LITTLE_ENDIAN__ */
1784 ofile
->member_type
= OFILE_FAT
;
1786 (struct fat_header
*)(ofile
->member_addr
);
1787 #ifdef __LITTLE_ENDIAN__
1788 swap_fat_header(ofile
->fat_header
, host_byte_sex
);
1789 #endif /* __LITTLE_ENDIAN__ */
1790 if(sizeof(struct fat_header
) +
1791 ofile
->fat_header
->nfat_arch
*
1792 sizeof(struct fat_arch
) > ofile
->member_size
){
1793 archive_member_error(ofile
, "fat file truncated or "
1794 "malformed (fat_arch structs would extend past "
1795 "the end of the archive member)");
1798 ofile
->fat_archs
= (struct fat_arch
*)
1799 (ofile
->member_addr
+ sizeof(struct fat_header
));
1800 #ifdef __LITTLE_ENDIAN__
1801 swap_fat_arch(ofile
->fat_archs
,
1802 ofile
->fat_header
->nfat_arch
, host_byte_sex
);
1803 #endif /* __LITTLE_ENDIAN__ */
1804 if(check_fat_object_in_archive(ofile
) == FALSE
)
1807 else if(size
- (offset
+ ar_name_size
) >=
1808 sizeof(struct mach_header
) &&
1809 (magic
== MH_MAGIC
|| magic
== SWAP_INT(MH_MAGIC
))){
1810 #ifdef ALIGNMENT_CHECKS
1811 if((offset
+ ar_name_size
) % 4 != 0){
1812 archive_member_error(ofile
, "offset in archive not a "
1813 "multiple of 4 (must be since member is a 32-bit "
1817 #endif /* ALIGNMENT_CHECKS */
1818 ofile
->member_type
= OFILE_Mach_O
;
1819 ofile
->object_addr
= ofile
->member_addr
;
1820 ofile
->object_size
= ofile
->member_size
;
1821 if(magic
== MH_MAGIC
)
1822 ofile
->object_byte_sex
= host_byte_sex
;
1824 ofile
->object_byte_sex
=
1825 host_byte_sex
== BIG_ENDIAN_BYTE_SEX
?
1826 LITTLE_ENDIAN_BYTE_SEX
: BIG_ENDIAN_BYTE_SEX
;
1827 ofile
->mh
= (struct mach_header
*)(ofile
->object_addr
);
1828 ofile
->load_commands
= (struct load_command
*)
1829 (ofile
->object_addr
+ sizeof(struct mach_header
));
1830 if(check_Mach_O(ofile
) == CHECK_BAD
)
1833 else if(size
- (offset
+ ar_name_size
) >=
1834 sizeof(struct mach_header_64
) &&
1835 (magic
== MH_MAGIC_64
|| magic
== SWAP_INT(MH_MAGIC_64
))){
1836 #ifdef ALIGNMENT_CHECKS_ARCHIVE_64_BIT
1837 if(archive_64_bit_align_warning
== FALSE
&&
1838 (offset
+ ar_name_size
) % 8 != 0){
1839 temporary_archive_member_warning(ofile
, "offset in archive "
1840 "not a multiple of 8 (must be since member is an "
1841 "64-bit object file)");
1842 archive_64_bit_align_warning
= TRUE
;
1845 #endif /* ALIGNMENT_CHECKS_ARCHIVE_64_BIT */
1846 ofile
->member_type
= OFILE_Mach_O
;
1847 ofile
->object_addr
= ofile
->member_addr
;
1848 ofile
->object_size
= ofile
->member_size
;
1849 if(magic
== MH_MAGIC_64
)
1850 ofile
->object_byte_sex
= host_byte_sex
;
1852 ofile
->object_byte_sex
=
1853 host_byte_sex
== BIG_ENDIAN_BYTE_SEX
?
1854 LITTLE_ENDIAN_BYTE_SEX
: BIG_ENDIAN_BYTE_SEX
;
1855 ofile
->mh64
= (struct mach_header_64
*)(ofile
->object_addr
);
1856 ofile
->load_commands
= (struct load_command
*)
1857 (ofile
->object_addr
+ sizeof(struct mach_header_64
));
1858 if(check_Mach_O(ofile
) == CHECK_BAD
)
1861 if(ofile
->member_type
== OFILE_UNKNOWN
&&
1862 (strncmp(ofile
->member_name
, SYMDEF_SORTED
,
1863 sizeof(SYMDEF_SORTED
) - 1) == 0 ||
1864 strncmp(ofile
->member_name
, SYMDEF
,
1865 sizeof(SYMDEF
) - 1) == 0)){
1866 ofile
->toc_addr
= ofile
->member_addr
;
1867 ofile
->toc_size
= ofile
->member_size
;
1868 ofile
->toc_ar_hdr
= ofile
->member_ar_hdr
;
1869 ofile
->toc_name
= ofile
->member_name
;
1870 ofile
->toc_name_size
= ofile
->member_name_size
;
1871 if(check_archive_toc(ofile
) == CHECK_BAD
)
1875 if(ofile
->member_type
== OFILE_UNKNOWN
&&
1876 strncmp(ofile
->member_name
, SYMDEF_SORTED
,
1877 sizeof(SYMDEF_SORTED
) - 1) != 0 &&
1878 strncmp(ofile
->member_name
, SYMDEF
,
1879 sizeof(SYMDEF
) - 1) != 0 &&
1880 is_llvm_bitcode(ofile
, ofile
->member_addr
, ofile
->member_size
) ==
1882 ofile
->member_type
= OFILE_LLVM_BITCODE
;
1883 ofile
->object_addr
= ofile
->member_addr
;
1884 ofile
->object_size
= ofile
->member_size
;
1886 #endif /* LTO_SUPPORT */
1891 ofile
->fat_header
= NULL
;
1892 ofile
->fat_archs
= NULL
;
1894 ofile
->member_offset
= 0;
1895 ofile
->member_addr
= 0;
1896 ofile
->member_size
= 0;
1897 ofile
->member_ar_hdr
= NULL
;
1898 ofile
->member_name
= NULL
;
1899 ofile
->member_name_size
= 0;
1900 ofile
->member_type
= OFILE_UNKNOWN
;
1901 ofile
->object_addr
= NULL
;
1902 ofile
->object_size
= 0;
1903 ofile
->object_byte_sex
= UNKNOWN_BYTE_SEX
;
1906 ofile
->load_commands
= NULL
;
1909 ofile
->lto_cputype
= 0;
1910 ofile
->lto_cpusubtype
= 0;
1911 #endif /* LTO_SUPPORT */
1916 * ofile_next_member() set up the ofile structure (the member_* fields and
1917 * the object file fields if the next member is an object file) for the next
1923 struct ofile
*ofile
)
1926 uint32_t size
, offset
;
1928 enum byte_sex host_byte_sex
;
1929 struct ar_hdr
*ar_hdr
;
1930 uint32_t ar_name_size
;
1933 * Get the address and size of the archive.
1935 if(ofile
->file_type
== OFILE_FAT
){
1936 if(ofile
->arch_type
!= OFILE_ARCHIVE
){
1937 error("ofile_next_member() called on fat file: %s with a "
1938 "non-archive architecture or no architecture selected\n",
1942 addr
= ofile
->file_addr
+ ofile
->fat_archs
[ofile
->narch
].offset
;
1943 size
= ofile
->fat_archs
[ofile
->narch
].size
;
1945 else if(ofile
->file_type
== OFILE_ARCHIVE
){
1946 addr
= ofile
->file_addr
;
1947 size
= ofile
->file_size
;
1950 error("ofile_next_member() called and file type of %s is "
1951 "OFILE_UNKNOWN\n", ofile
->file_name
);
1954 if(size
< SARMAG
|| strncmp(addr
, ARMAG
, SARMAG
) != 0){
1955 archive_error(ofile
, "internal error. ofile_next_member() "
1956 "called but file does not have an archive magic "
1960 if(ofile
->member_ar_hdr
== NULL
){
1961 archive_error(ofile
, "internal error. ofile_next_member() called "
1962 "but the ofile struct does not have an archive "
1967 /* figure out the offset to the next member */
1968 offset
= ofile
->member_offset
+ rnd(ofile
->member_size
,sizeof(short));
1970 if((addr
- ofile
->file_addr
) + offset
> ofile
->file_size
){
1971 archive_error(ofile
, "offset to next member extends past the end "
1976 /* if now at the end of the file then no more members */
1980 archive_error(ofile
, "truncated or malformed (archive header of "
1981 "next member extends past the end of the file)");
1985 /* now we know there is a next member so set it up */
1986 ar_hdr
= (struct ar_hdr
*)(addr
+ offset
);
1987 offset
+= sizeof(struct ar_hdr
);
1988 ofile
->member_offset
= offset
;
1989 ofile
->member_addr
= addr
+ offset
;
1990 ofile
->member_size
= strtoul(ar_hdr
->ar_size
, NULL
, 10);
1991 ofile
->member_ar_hdr
= ar_hdr
;
1992 ofile
->member_name
= ar_hdr
->ar_name
;
1993 if(strncmp(ofile
->member_name
, AR_EFMT1
, sizeof(AR_EFMT1
) - 1) == 0){
1994 ofile
->member_name
= ar_hdr
->ar_name
+ sizeof(struct ar_hdr
);
1995 ar_name_size
= strtoul(ar_hdr
->ar_name
+ sizeof(AR_EFMT1
) - 1,
1997 ofile
->member_name_size
= ar_name_size
;
1998 ofile
->member_offset
+= ar_name_size
;
1999 ofile
->member_addr
+= ar_name_size
;
2000 ofile
->member_size
-= ar_name_size
;
2003 ofile
->member_name_size
= size_ar_name(ar_hdr
);
2006 ofile
->member_type
= OFILE_UNKNOWN
;
2007 ofile
->object_addr
= NULL
;
2008 ofile
->object_size
= 0;
2009 ofile
->object_byte_sex
= UNKNOWN_BYTE_SEX
;
2012 ofile
->load_commands
= NULL
;
2014 host_byte_sex
= get_host_byte_sex();
2016 if(ofile
->member_size
> sizeof(uint32_t)){
2017 memcpy(&magic
, ofile
->member_addr
, sizeof(uint32_t));
2018 #ifdef __BIG_ENDIAN__
2019 if(magic
== FAT_MAGIC
)
2020 #endif /* __BIG_ENDIAN__ */
2021 #ifdef __LITTLE_ENDIAN__
2022 if(magic
== SWAP_INT(FAT_MAGIC
))
2023 #endif /* __LITTLE_ENDIAN__ */
2025 ofile
->member_type
= OFILE_FAT
;
2026 ofile
->fat_header
= (struct fat_header
*)(ofile
->member_addr
);
2027 #ifdef __LITTLE_ENDIAN__
2028 swap_fat_header(ofile
->fat_header
, host_byte_sex
);
2029 #endif /* __LITTLE_ENDIAN__ */
2030 if(sizeof(struct fat_header
) +
2031 ofile
->fat_header
->nfat_arch
*
2032 sizeof(struct fat_arch
) > ofile
->member_size
){
2033 archive_member_error(ofile
, "fat file truncated or "
2034 "malformed (fat_arch structs would extend past "
2035 "the end of the archive member)");
2038 ofile
->fat_archs
= (struct fat_arch
*)(ofile
->member_addr
+
2039 sizeof(struct fat_header
));
2040 #ifdef __LITTLE_ENDIAN__
2041 swap_fat_arch(ofile
->fat_archs
,
2042 ofile
->fat_header
->nfat_arch
, host_byte_sex
);
2043 #endif /* __LITTLE_ENDIAN__ */
2044 if(check_fat_object_in_archive(ofile
) == FALSE
)
2047 else if(size
- (offset
+ ar_name_size
) >=
2048 sizeof(struct mach_header
) &&
2049 (magic
== MH_MAGIC
||
2050 magic
== SWAP_INT(MH_MAGIC
))){
2051 #ifdef ALIGNMENT_CHECKS
2052 if((offset
+ ar_name_size
) % 4 != 0){
2053 archive_member_error(ofile
, "offset in archive not "
2054 "a multiple of 4 (must be since member is an 32-bit "
2058 #endif /* ALIGNMENT_CHECKS */
2059 ofile
->member_type
= OFILE_Mach_O
;
2060 ofile
->object_addr
= ofile
->member_addr
;
2061 ofile
->object_size
= ofile
->member_size
;
2062 if(magic
== MH_MAGIC
)
2063 ofile
->object_byte_sex
= host_byte_sex
;
2065 ofile
->object_byte_sex
=
2066 host_byte_sex
== BIG_ENDIAN_BYTE_SEX
?
2067 LITTLE_ENDIAN_BYTE_SEX
: BIG_ENDIAN_BYTE_SEX
;
2068 ofile
->mh
= (struct mach_header
*)ofile
->object_addr
;
2069 ofile
->load_commands
= (struct load_command
*)
2070 (ofile
->object_addr
+ sizeof(struct mach_header
));
2071 if(check_Mach_O(ofile
) == CHECK_BAD
)
2074 else if(size
- (offset
+ ar_name_size
) >=
2075 sizeof(struct mach_header_64
) &&
2076 (magic
== MH_MAGIC_64
||
2077 magic
== SWAP_INT(MH_MAGIC_64
))){
2078 #ifdef ALIGNMENT_CHECKS_ARCHIVE_64_BIT
2079 if(archive_64_bit_align_warning
== FALSE
&&
2080 (offset
+ ar_name_size
) % 8 != 0){
2081 temporary_archive_member_warning(ofile
, "offset in archive "
2082 "not a multiple of 8 (must be since member is an "
2083 "64-bit object file)");
2084 archive_64_bit_align_warning
= TRUE
;
2087 #endif /* ALIGNMENT_CHECKS_ARCHIVE_64_BIT */
2088 ofile
->member_type
= OFILE_Mach_O
;
2089 ofile
->object_addr
= ofile
->member_addr
;
2090 ofile
->object_size
= ofile
->member_size
;
2091 if(magic
== MH_MAGIC_64
)
2092 ofile
->object_byte_sex
= host_byte_sex
;
2094 ofile
->object_byte_sex
=
2095 host_byte_sex
== BIG_ENDIAN_BYTE_SEX
?
2096 LITTLE_ENDIAN_BYTE_SEX
: BIG_ENDIAN_BYTE_SEX
;
2097 ofile
->mh64
= (struct mach_header_64
*)ofile
->object_addr
;
2098 ofile
->load_commands
= (struct load_command
*)
2099 (ofile
->object_addr
+ sizeof(struct mach_header_64
));
2100 if(check_Mach_O(ofile
) == CHECK_BAD
)
2104 if(ofile
->member_type
== OFILE_UNKNOWN
&&
2105 is_llvm_bitcode(ofile
, ofile
->member_addr
, ofile
->member_size
) ==
2107 ofile
->member_type
= OFILE_LLVM_BITCODE
;
2108 ofile
->object_addr
= ofile
->member_addr
;
2109 ofile
->object_size
= ofile
->member_size
;
2111 #endif /* LTO_SUPPORT */
2116 if(ofile
->member_type
== OFILE_FAT
){
2117 ofile
->fat_header
= NULL
;
2118 ofile
->fat_archs
= NULL
;
2120 ofile
->member_offset
= 0;
2121 ofile
->member_addr
= NULL
;
2122 ofile
->member_size
= 0;
2123 ofile
->member_ar_hdr
= NULL
;
2124 ofile
->member_name
= NULL
;
2125 ofile
->member_name_size
= 0;
2126 ofile
->member_type
= OFILE_UNKNOWN
;
2127 ofile
->object_addr
= NULL
;
2128 ofile
->object_size
= 0;
2129 ofile
->object_byte_sex
= UNKNOWN_BYTE_SEX
;
2132 ofile
->load_commands
= NULL
;
2135 ofile
->lto_cputype
= 0;
2136 ofile
->lto_cpusubtype
= 0;
2137 #endif /* LTO_SUPPORT */
2142 * ofile_specific_member() set up the ofile structure (the member_* fields and
2143 * the object file fields if the member is an object file) for the specified
2144 * member member_name.
2148 ofile_specific_member(
2149 const char *member_name
,
2150 struct ofile
*ofile
)
2154 uint32_t size
, offset
;
2156 enum byte_sex host_byte_sex
;
2158 uint32_t ar_name_size
;
2159 struct ar_hdr
*ar_hdr
;
2161 /* These fields are to be filled in by this routine, clear them first */
2162 ofile
->member_offset
= 0;
2163 ofile
->member_addr
= NULL
;
2164 ofile
->member_size
= 0;
2165 ofile
->member_ar_hdr
= NULL
;
2166 ofile
->member_name
= NULL
;
2167 ofile
->member_name_size
= 0;
2168 ofile
->member_type
= OFILE_UNKNOWN
;
2169 ofile
->object_addr
= NULL
;
2170 ofile
->object_size
= 0;
2171 ofile
->object_byte_sex
= UNKNOWN_BYTE_SEX
;
2174 ofile
->load_commands
= NULL
;
2177 * Get the address and size of the archive.
2179 if(ofile
->file_type
== OFILE_FAT
){
2180 if(ofile
->arch_type
!= OFILE_ARCHIVE
){
2181 error("ofile_specific_member() called on fat file: %s with a "
2182 "non-archive architecture or no architecture selected\n",
2186 addr
= ofile
->file_addr
+ ofile
->fat_archs
[ofile
->narch
].offset
;
2187 size
= ofile
->fat_archs
[ofile
->narch
].size
;
2189 else if(ofile
->file_type
== OFILE_ARCHIVE
){
2190 addr
= ofile
->file_addr
;
2191 size
= ofile
->file_size
;
2194 error("ofile_specific_member() called and file type of %s is "
2195 "OFILE_UNKNOWN\n", ofile
->file_name
);
2198 if(size
< SARMAG
|| strncmp(addr
, ARMAG
, SARMAG
) != 0){
2199 archive_error(ofile
, "internal error. ofile_specific_member() "
2200 "called but file does not have an archive magic "
2206 if(offset
!= size
&& offset
+ sizeof(struct ar_hdr
) > size
){
2207 archive_error(ofile
, "truncated or malformed (archive header of "
2208 "first member extends past the end of the file)");
2211 while(size
> offset
){
2212 ar_hdr
= (struct ar_hdr
*)(addr
+ offset
);
2213 offset
+= sizeof(struct ar_hdr
);
2214 if(strncmp(ar_hdr
->ar_name
, AR_EFMT1
, sizeof(AR_EFMT1
) - 1) == 0){
2216 if(check_extend_format_1(ofile
, ar_hdr
, size
- offset
,
2217 &ar_name_size
) == CHECK_BAD
){
2218 i
= size_ar_name(ar_hdr
);
2219 ar_name
= ar_hdr
->ar_name
;
2225 i
= strtoul(ar_hdr
->ar_name
+ sizeof(AR_EFMT1
) - 1,NULL
,10);
2226 ar_name
= ar_hdr
->ar_name
+ sizeof(struct ar_hdr
);
2231 i
= size_ar_name(ar_hdr
);
2232 ar_name
= ar_hdr
->ar_name
;
2235 if(i
> 0 && strncmp(ar_name
, member_name
, i
) == 0){
2237 ofile
->member_name
= ar_name
;
2238 ofile
->member_name_size
= i
;
2239 ofile
->member_offset
= offset
+ ar_name_size
;
2240 ofile
->member_addr
= addr
+ offset
+ ar_name_size
;
2241 ofile
->member_size
= strtoul(ar_hdr
->ar_size
, NULL
, 10) -
2243 ofile
->member_ar_hdr
= ar_hdr
;
2244 ofile
->member_type
= OFILE_UNKNOWN
;
2246 host_byte_sex
= get_host_byte_sex();
2248 if(ofile
->member_size
> sizeof(uint32_t)){
2249 memcpy(&magic
, addr
+ offset
+ ar_name_size
,
2251 #ifdef __BIG_ENDIAN__
2252 if(magic
== FAT_MAGIC
)
2253 #endif /* __BIG_ENDIAN__ */
2254 #ifdef __LITTLE_ENDIAN__
2255 if(magic
== SWAP_INT(FAT_MAGIC
))
2256 #endif /* __LITTLE_ENDIAN__ */
2258 ofile
->member_type
= OFILE_FAT
;
2260 (struct fat_header
*)(addr
+ offset
+ ar_name_size
);
2261 #ifdef __LITTLE_ENDIAN__
2262 swap_fat_header(ofile
->fat_header
, host_byte_sex
);
2263 #endif /* __LITTLE_ENDIAN__ */
2264 if(sizeof(struct fat_header
) +
2265 ofile
->fat_header
->nfat_arch
*
2266 sizeof(struct fat_arch
) > ofile
->member_size
){
2267 archive_member_error(ofile
, "fat file truncated or "
2268 "malformed (fat_arch structs would extend "
2269 "past the end of the archive member)");
2273 (struct fat_arch
*)(addr
+ offset
+ ar_name_size
+
2274 sizeof(struct fat_header
));
2275 #ifdef __LITTLE_ENDIAN__
2276 swap_fat_arch(ofile
->fat_archs
,
2277 ofile
->fat_header
->nfat_arch
,
2279 #endif /* __LITTLE_ENDIAN__ */
2280 if(check_fat_object_in_archive(ofile
) == FALSE
)
2283 else if(size
- (offset
+ ar_name_size
) >=
2284 sizeof(struct mach_header
) &&
2285 (magic
== MH_MAGIC
||
2286 magic
== SWAP_INT(MH_MAGIC
))){
2287 #ifdef ALIGNMENT_CHECKS
2288 if((offset
+ ar_name_size
) % 4 != 0){
2289 archive_member_error(ofile
, "offset in archive not "
2290 "a multiple of 4) (must be since member is a "
2291 "32-bit object file)");
2294 #endif /* ALIGNMENT_CHECKS */
2295 ofile
->member_type
= OFILE_Mach_O
;
2296 ofile
->object_addr
= ofile
->member_addr
;
2297 ofile
->object_size
= ofile
->member_size
;
2298 if(magic
== MH_MAGIC
)
2299 ofile
->object_byte_sex
= host_byte_sex
;
2301 ofile
->object_byte_sex
=
2302 host_byte_sex
== BIG_ENDIAN_BYTE_SEX
?
2303 LITTLE_ENDIAN_BYTE_SEX
: BIG_ENDIAN_BYTE_SEX
;
2304 ofile
->mh
= (struct mach_header
*)ofile
->object_addr
;
2305 ofile
->load_commands
= (struct load_command
*)
2306 (ofile
->object_addr
+ sizeof(struct mach_header
));
2307 if(check_Mach_O(ofile
) == CHECK_BAD
)
2310 else if(size
- (offset
+ ar_name_size
) >=
2311 sizeof(struct mach_header_64
) &&
2312 (magic
== MH_MAGIC_64
||
2313 magic
== SWAP_INT(MH_MAGIC_64
))){
2314 #ifdef ALIGNMENT_CHECKS_ARCHIVE_64_BIT
2315 if(archive_64_bit_align_warning
== FALSE
&&
2316 (offset
+ ar_name_size
) % 8 != 0){
2317 temporary_archive_member_warning(ofile
, "offset in "
2318 "archive not a multiple of 8) (must be since "
2319 "member is a 64-bit object file)");
2320 archive_64_bit_align_warning
= TRUE
;
2323 #endif /* ALIGNMENT_CHECKS_ARCHIVE_64_BIT */
2324 ofile
->member_type
= OFILE_Mach_O
;
2325 ofile
->object_addr
= ofile
->member_addr
;
2326 ofile
->object_size
= ofile
->member_size
;
2327 if(magic
== MH_MAGIC_64
)
2328 ofile
->object_byte_sex
= host_byte_sex
;
2330 ofile
->object_byte_sex
=
2331 host_byte_sex
== BIG_ENDIAN_BYTE_SEX
?
2332 LITTLE_ENDIAN_BYTE_SEX
: BIG_ENDIAN_BYTE_SEX
;
2333 ofile
->mh64
= (struct mach_header_64
*)
2335 ofile
->load_commands
= (struct load_command
*)
2336 (ofile
->object_addr
+sizeof(struct mach_header_64
));
2337 if(check_Mach_O(ofile
) == CHECK_BAD
)
2342 if(ofile
->member_type
== OFILE_UNKNOWN
&&
2343 is_llvm_bitcode(ofile
, ofile
->member_addr
,
2344 ofile
->member_size
) == TRUE
){
2345 ofile
->member_type
= OFILE_LLVM_BITCODE
;
2346 ofile
->object_addr
= ofile
->member_addr
;
2347 ofile
->object_size
= ofile
->member_size
;
2349 #endif /* LTO_SUPPORT */
2352 offset
+= rnd(strtoul(ar_hdr
->ar_size
, NULL
, 10),
2355 archive_error(ofile
, "does not contain a member named: %s",
2358 ofile
->fat_header
= NULL
;
2359 ofile
->fat_archs
= NULL
;
2361 ofile
->member_offset
= 0;
2362 ofile
->member_addr
= NULL
;
2363 ofile
->member_size
= 0;
2364 ofile
->member_ar_hdr
= NULL
;
2365 ofile
->member_name
= NULL
;
2366 ofile
->member_name_size
= 0;
2367 ofile
->member_type
= OFILE_UNKNOWN
;
2368 ofile
->object_addr
= NULL
;
2369 ofile
->object_size
= 0;
2370 ofile
->object_byte_sex
= UNKNOWN_BYTE_SEX
;
2373 ofile
->load_commands
= NULL
;
2376 ofile
->lto_cputype
= 0;
2377 ofile
->lto_cpusubtype
= 0;
2378 #endif /* LTO_SUPPORT */
2383 * ofile_first_module() set up the ofile structure (the dylib_module field)
2384 * for the first module of an MH_DYLIB or MH_DYLIB_STUB file.
2389 struct ofile
*ofile
)
2392 struct symtab_command
*st
;
2393 struct dysymtab_command
*dyst
;
2394 struct load_command
*lc
;
2396 enum byte_sex host_byte_sex
;
2397 struct dylib_module m
;
2398 struct dylib_module_64 m64
;
2401 /* These fields are to be filled in by this routine, clear them first */
2402 ofile
->modtab
= NULL
;
2403 ofile
->modtab64
= NULL
;
2405 ofile
->dylib_module
= NULL
;
2406 ofile
->dylib_module64
= NULL
;
2407 ofile
->dylib_module_name
= NULL
;
2409 if(ofile
->file_type
== OFILE_FAT
){
2410 if(ofile
->arch_type
!= OFILE_Mach_O
&&
2411 (ofile
->mh_filetype
!= MH_DYLIB
&&
2412 ofile
->mh_filetype
!= MH_DYLIB_STUB
)){
2413 error("ofile_first_module() called on fat file: %s with a "
2414 "non-MH_DYLIB architecture or no architecture selected\n",
2419 else if(ofile
->arch_type
!= OFILE_Mach_O
&&
2420 (ofile
->mh_filetype
!= MH_DYLIB
&&
2421 ofile
->mh_filetype
!= MH_DYLIB_STUB
)){
2422 error("ofile_first_module() called and file type of %s is "
2423 "non-MH_DYLIB\n", ofile
->file_name
);
2429 lc
= ofile
->load_commands
;
2430 if(ofile
->mh
!= NULL
)
2431 ncmds
= ofile
->mh
->ncmds
;
2433 ncmds
= ofile
->mh64
->ncmds
;
2434 for(i
= 0; i
< ncmds
; i
++){
2435 if(st
== NULL
&& lc
->cmd
== LC_SYMTAB
){
2436 st
= (struct symtab_command
*)lc
;
2438 else if(lc
->cmd
== LC_DYSYMTAB
){
2439 dyst
= (struct dysymtab_command
*)lc
;
2441 lc
= (struct load_command
*)((char *)lc
+ lc
->cmdsize
);
2443 if(st
== NULL
|| dyst
== NULL
){
2445 Mach_O_error(ofile
, "MH_DYLIB format error (does not have a symbol "
2446 "table and/or a dynamic symbol table)");
2450 if(dyst
->nmodtab
== 0)
2453 ofile
->nmodtab
= dyst
->nmodtab
;
2454 host_byte_sex
= get_host_byte_sex();
2455 swapped
= (enum bool)(host_byte_sex
!= ofile
->object_byte_sex
);
2456 strings
= (char *)(ofile
->object_addr
+ st
->stroff
);
2458 if(ofile
->mh
!= NULL
){
2459 ofile
->modtab
= (struct dylib_module
*)(ofile
->object_addr
+
2461 ofile
->dylib_module
= ofile
->modtab
;
2462 m
= *ofile
->dylib_module
;
2464 swap_dylib_module(&m
, 1, host_byte_sex
);
2465 ofile
->dylib_module_name
= strings
+ m
.module_name
;
2468 ofile
->modtab64
= (struct dylib_module_64
*)(ofile
->object_addr
+
2470 ofile
->dylib_module64
= ofile
->modtab64
;
2471 m64
= *ofile
->dylib_module64
;
2473 swap_dylib_module_64(&m64
, 1, host_byte_sex
);
2474 ofile
->dylib_module_name
= strings
+ m64
.module_name
;
2477 if(check_dylib_module(ofile
, st
, dyst
, strings
, 0) == CHECK_BAD
)
2483 * ofile_next_module() set up the ofile structure (the dylib_module field)
2484 * for the next module of an MH_DYLIB or MH_DYLIB_STUB file.
2489 struct ofile
*ofile
)
2491 uint32_t i
, module_index
, ncmds
;
2492 struct symtab_command
*st
;
2493 struct dysymtab_command
*dyst
;
2494 struct load_command
*lc
;
2496 enum byte_sex host_byte_sex
;
2497 struct dylib_module m
;
2498 struct dylib_module_64 m64
;
2501 if(ofile
->file_type
== OFILE_FAT
){
2502 if(ofile
->arch_type
!= OFILE_Mach_O
&&
2503 (ofile
->mh_filetype
!= MH_DYLIB
&&
2504 ofile
->mh_filetype
!= MH_DYLIB_STUB
)){
2505 error("ofile_next_module() called on fat file: %s with a "
2506 "non-MH_DYLIB architecture or no architecture selected\n",
2511 else if(ofile
->arch_type
!= OFILE_Mach_O
&&
2512 (ofile
->mh_filetype
!= MH_DYLIB
&&
2513 ofile
->mh_filetype
!= MH_DYLIB_STUB
)){
2514 error("ofile_next_module() called and file type of %s is "
2515 "non-MH_DYLIB\n", ofile
->file_name
);
2520 lc
= ofile
->load_commands
;
2521 if(ofile
->mh
!= NULL
)
2522 ncmds
= ofile
->mh
->ncmds
;
2524 ncmds
= ofile
->mh64
->ncmds
;
2525 for(i
= 0; i
< ncmds
; i
++){
2526 if(st
== NULL
&& lc
->cmd
== LC_SYMTAB
){
2527 st
= (struct symtab_command
*)lc
;
2529 else if(lc
->cmd
== LC_DYSYMTAB
){
2530 dyst
= (struct dysymtab_command
*)lc
;
2532 lc
= (struct load_command
*)((char *)lc
+ lc
->cmdsize
);
2534 if(st
== NULL
|| dyst
== NULL
){
2536 Mach_O_error(ofile
, "MH_DYLIB format error (does not have a symbol "
2537 "table and/or a dynamic symbol table)");
2542 if(ofile
->mh
!= NULL
)
2543 module_index
= (ofile
->dylib_module
+ 1) - ofile
->modtab
;
2545 module_index
= (ofile
->dylib_module64
+ 1) - ofile
->modtab64
;
2546 if(module_index
>= ofile
->nmodtab
)
2549 host_byte_sex
= get_host_byte_sex();
2550 swapped
= (enum bool)(host_byte_sex
!= ofile
->object_byte_sex
);
2551 strings
= (char *)(ofile
->object_addr
+ st
->stroff
);
2553 if(ofile
->mh
!= NULL
){
2554 ofile
->dylib_module
++;
2555 m
= *ofile
->dylib_module
;
2557 swap_dylib_module(&m
, 1, host_byte_sex
);
2558 ofile
->dylib_module_name
= strings
+ m
.module_name
;
2561 ofile
->dylib_module64
++;
2562 m64
= *ofile
->dylib_module64
;
2564 swap_dylib_module_64(&m64
, 1, host_byte_sex
);
2565 ofile
->dylib_module_name
= strings
+ m64
.module_name
;
2567 if(check_dylib_module(ofile
, st
, dyst
, strings
, module_index
) ==
2574 * ofile_specific_module() set up the ofile structure (the dylib_module fields)
2575 * for the specified module, module_name, of an MH_DYLIB or an MH_DYLIB_STUB
2580 ofile_specific_module(
2581 const char *module_name
,
2582 struct ofile
*ofile
)
2586 enum byte_sex host_byte_sex
;
2587 struct symtab_command
*st
;
2588 struct dysymtab_command
*dyst
;
2589 struct load_command
*lc
;
2590 struct dylib_module
*p
, m
;
2591 struct dylib_module_64
*p64
, m64
;
2594 /* These fields are to be filled in by this routine, clear them first */
2595 ofile
->modtab
= NULL
;
2596 ofile
->modtab64
= NULL
;
2598 ofile
->dylib_module
= NULL
;
2599 ofile
->dylib_module64
= NULL
;
2600 ofile
->dylib_module_name
= NULL
;
2602 if(ofile
->file_type
== OFILE_FAT
){
2603 if(ofile
->arch_type
!= OFILE_Mach_O
&&
2604 (ofile
->mh_filetype
!= MH_DYLIB
&&
2605 ofile
->mh_filetype
!= MH_DYLIB_STUB
)){
2606 error("ofile_specific_module() called on fat file: %s with a "
2607 "non-MH_DYLIB architecture or no architecture selected\n",
2612 else if(ofile
->arch_type
!= OFILE_Mach_O
&&
2613 (ofile
->mh_filetype
!= MH_DYLIB
&&
2614 ofile
->mh_filetype
!= MH_DYLIB_STUB
)){
2615 error("ofile_specific_module() called and file type of %s is "
2616 "non-MH_DYLIB\n", ofile
->file_name
);
2622 lc
= ofile
->load_commands
;
2623 if(ofile
->mh
!= NULL
)
2624 ncmds
= ofile
->mh
->ncmds
;
2626 ncmds
= ofile
->mh64
->ncmds
;
2627 for(i
= 0; i
< ncmds
; i
++){
2628 if(st
== NULL
&& lc
->cmd
== LC_SYMTAB
){
2629 st
= (struct symtab_command
*)lc
;
2631 else if(lc
->cmd
== LC_DYSYMTAB
){
2632 dyst
= (struct dysymtab_command
*)lc
;
2634 lc
= (struct load_command
*)((char *)lc
+ lc
->cmdsize
);
2636 if(st
== NULL
|| dyst
== NULL
){
2638 Mach_O_error(ofile
, "MH_DYLIB format error (does not have a symbol "
2639 "table and/or a dynamic symbol table)");
2643 if(dyst
->nmodtab
== 0)
2646 host_byte_sex
= get_host_byte_sex();
2647 swapped
= (enum bool)(host_byte_sex
!= ofile
->object_byte_sex
);
2648 strings
= (char *)(ofile
->object_addr
+ st
->stroff
);
2650 if(ofile
->mh
!= NULL
){
2651 ofile
->nmodtab
= dyst
->nmodtab
;
2652 ofile
->modtab
= (struct dylib_module
*)(ofile
->object_addr
+
2655 for(i
= 0; i
< dyst
->nmodtab
; i
++){
2658 swap_dylib_module(&m
, 1, host_byte_sex
);
2659 ofile
->dylib_module
= p
;
2660 if(check_dylib_module(ofile
, st
, dyst
, strings
, i
) == CHECK_BAD
)
2662 if(strcmp(module_name
, strings
+ m
.module_name
) == 0){
2663 ofile
->dylib_module_name
= strings
+ m
.module_name
;
2668 m
= *ofile
->dylib_module
;
2670 swap_dylib_module(&m
, 1, host_byte_sex
);
2671 ofile
->dylib_module_name
= strings
+ m
.module_name
;
2674 ofile
->nmodtab
= dyst
->nmodtab
;
2675 ofile
->modtab64
= (struct dylib_module_64
*)(ofile
->object_addr
+
2677 p64
= ofile
->modtab64
;
2678 for(i
= 0; i
< dyst
->nmodtab
; i
++){
2681 swap_dylib_module_64(&m64
, 1, host_byte_sex
);
2682 ofile
->dylib_module64
= p64
;
2683 if(check_dylib_module(ofile
, st
, dyst
, strings
, i
) == CHECK_BAD
)
2685 if(strcmp(module_name
, strings
+ m64
.module_name
) == 0){
2686 ofile
->dylib_module_name
= strings
+ m64
.module_name
;
2691 m64
= *ofile
->dylib_module64
;
2693 swap_dylib_module_64(&m64
, 1, host_byte_sex
);
2694 ofile
->dylib_module_name
= strings
+ m64
.module_name
;
2697 Mach_O_error(ofile
, "does not contain a module named: %s", module_name
);
2699 ofile
->modtab
= NULL
;
2701 ofile
->dylib_module
= NULL
;
2702 ofile
->dylib_module_name
= NULL
;
2710 struct ofile
*ofile
)
2712 printf("file_name = %s\n", ofile
->file_name
);
2713 printf("file_addr = 0x%x\n", (unsigned int)ofile
->file_addr
);
2714 printf("file_size = 0x%x\n", (unsigned int)ofile
->file_size
);
2715 printf("file_type = 0x%x\n", (unsigned int)ofile
->file_type
);
2716 printf("fat_header = 0x%x\n", (unsigned int)ofile
->fat_header
);
2717 printf("fat_archs = 0x%x\n", (unsigned int)ofile
->fat_archs
);
2718 printf("narch = 0x%x\n", (unsigned int)ofile
->narch
);
2719 printf("arch_type = 0x%x\n", (unsigned int)ofile
->arch_type
);
2720 printf("arch_flag.name = %s\n", ofile
->arch_flag
.name
);
2721 printf("arch_flag.cputype = 0x%x\n",
2722 (unsigned int)ofile
->arch_flag
.cputype
);
2723 printf("arch_flag.cpusubtype = 0x%x\n",
2724 (unsigned int)ofile
->arch_flag
.cpusubtype
);
2725 printf("member_offset = 0x%x\n", (unsigned int)ofile
->member_offset
);
2726 printf("member_addr = 0x%x\n", (unsigned int)ofile
->member_addr
);
2727 printf("member_size = 0x%x\n", (unsigned int)ofile
->member_size
);
2728 printf("member_ar_hdr = 0x%x\n", (unsigned int)ofile
->member_ar_hdr
);
2729 printf("member_type = 0x%x\n", (unsigned int)ofile
->member_type
);
2730 printf("archive_cputype = 0x%x\n",
2731 (unsigned int)ofile
->archive_cputype
);
2732 printf("archive_cpusubtype = 0x%x\n",
2733 (unsigned int)ofile
->archive_cpusubtype
);
2734 printf("object_addr = 0x%x\n", (unsigned int)ofile
->object_addr
);
2735 printf("object_size = 0x%x\n", (unsigned int)ofile
->object_size
);
2736 printf("object_byte_sex = 0x%x\n",
2737 (unsigned int)ofile
->object_byte_sex
);
2738 printf("mh = 0x%x\n", (unsigned int)ofile
->mh
);
2739 printf("mh64 = 0x%x\n", (unsigned int)ofile
->mh64
);
2740 printf("load_commands = 0x%x\n", (unsigned int)ofile
->load_commands
);
2745 * check_fat() checks the fat ofile for correctness (the fat_header and
2746 * fat_archs are assumed to be in the host byte sex).
2751 struct ofile
*ofile
)
2755 #else /* !defined OTOOL */
2760 if(ofile
->file_type
!= OFILE_FAT
){
2761 error("internal error. check_fat() call and file type of: %s is "
2762 "not OFILE_FAT\n", ofile
->file_name
);
2765 if(ofile
->fat_header
->nfat_arch
== 0){
2766 error("fat file: %s malformed (contains zero architecture types)",
2770 for(i
= 0; i
< ofile
->fat_header
->nfat_arch
; i
++){
2771 big_size
= ofile
->fat_archs
[i
].offset
;
2772 big_size
+= ofile
->fat_archs
[i
].size
;
2773 if(big_size
> ofile
->file_size
){
2774 error("fat file: %s truncated or malformed (offset plus size "
2775 "of cputype (%d) cpusubtype (%d) extends past the "
2776 "end of the file)", ofile
->file_name
,
2777 ofile
->fat_archs
[i
].cputype
,
2778 ofile
->fat_archs
[i
].cpusubtype
& ~CPU_SUBTYPE_MASK
);
2781 if(ofile
->fat_archs
[i
].align
> MAXSECTALIGN
){
2782 error("fat file: %s align (2^%u) too large for cputype (%d) "
2783 "cpusubtype (%d) (maximum 2^%d)", ofile
->file_name
,
2784 ofile
->fat_archs
[i
].align
, ofile
->fat_archs
[i
].cputype
,
2785 ofile
->fat_archs
[i
].cpusubtype
& ~CPU_SUBTYPE_MASK
,
2789 if(ofile
->fat_archs
[i
].offset
%
2790 (1 << ofile
->fat_archs
[i
].align
) != 0){
2791 error("fat file: %s offset: %u for cputype (%d) cpusubtype "
2792 "(%d)) not aligned on it's alignment (2^%u)",
2794 ofile
->fat_archs
[i
].offset
,
2795 ofile
->fat_archs
[i
].cputype
,
2796 ofile
->fat_archs
[i
].cpusubtype
& ~CPU_SUBTYPE_MASK
,
2797 ofile
->fat_archs
[i
].align
);
2801 for(i
= 0; i
< ofile
->fat_header
->nfat_arch
; i
++){
2802 for(j
= i
+ 1; j
< ofile
->fat_header
->nfat_arch
; j
++){
2803 if(ofile
->fat_archs
[i
].cputype
==
2804 ofile
->fat_archs
[j
].cputype
&&
2805 (ofile
->fat_archs
[i
].cpusubtype
& ~CPU_SUBTYPE_MASK
) ==
2806 (ofile
->fat_archs
[j
].cpusubtype
& ~CPU_SUBTYPE_MASK
)){
2807 error("fat file: %s contains two of the same "
2808 "architecture (cputype (%d) cpusubtype (%d))",
2809 ofile
->file_name
, ofile
->fat_archs
[i
].cputype
,
2810 ofile
->fat_archs
[i
].cpusubtype
& ~CPU_SUBTYPE_MASK
);
2820 * check_fat_object_in_archive() checks the fat object file which is a member
2821 * of a thin archive for correctness (the fat_header and fat_archs are assumed
2822 * to be in the host byte sex). This is not a legal form but allowed when
2823 * archives_with_fat_objects is TRUE when ofile_map() is called.
2827 check_fat_object_in_archive(
2828 struct ofile
*ofile
)
2833 if(ofile
->file_type
!= OFILE_ARCHIVE
){
2834 error("internal error. check_fat_object_in_archive() called and "
2835 "file type of: %s is not OFILE_ARCHIVE\n", ofile
->file_name
);
2838 if(ofile
->fat_header
->nfat_arch
== 0){
2839 archive_member_error(ofile
, "fat file malformed (contains zero "
2840 "architecture types)");
2843 for(i
= 0; i
< ofile
->fat_header
->nfat_arch
; i
++){
2844 if(ofile
->fat_archs
[i
].offset
+ ofile
->fat_archs
[i
].size
>
2845 ofile
->member_size
){
2846 archive_member_error(ofile
, "fat file truncated or malformed "
2847 "(offset plus size of cputype (%d) cpusubtype (%d) "
2848 "extends past the end of the file)",
2849 ofile
->fat_archs
[i
].cputype
,
2850 ofile
->fat_archs
[i
].cpusubtype
& ~CPU_SUBTYPE_MASK
);
2853 if(ofile
->fat_archs
[i
].align
> MAXSECTALIGN
){
2854 archive_member_error(ofile
, "fat file's align (2^%u) too "
2855 "large for cputype (%d) cpusubtype (%d) (maximum 2^%d)",
2856 ofile
->fat_archs
[i
].align
, ofile
->fat_archs
[i
].cputype
,
2857 ofile
->fat_archs
[i
].cpusubtype
& ~CPU_SUBTYPE_MASK
,
2861 if(ofile
->fat_archs
[i
].offset
%
2862 (1 << ofile
->fat_archs
[i
].align
) != 0){
2863 archive_member_error(ofile
, "fat file's offset: %u for "
2864 "cputype (%d) cpusubtype (%d) not aligned on it's "
2865 "alignment (2^%u)", ofile
->fat_archs
[i
].offset
,
2866 ofile
->fat_archs
[i
].cputype
,
2867 ofile
->fat_archs
[i
].cpusubtype
& ~CPU_SUBTYPE_MASK
,
2868 ofile
->fat_archs
[i
].align
);
2873 * The only supported format where fat files are allowed to appear
2874 * in archives is when the fat file contains only object files.
2876 if(ofile
->fat_archs
[i
].size
< sizeof(struct mach_header
)){
2877 archive_member_error(ofile
, "fat file for cputype (%d) "
2878 "cpusubtype (%d) is not an object file (size too small "
2879 "to be an object file)", ofile
->fat_archs
[i
].cputype
,
2880 ofile
->fat_archs
[i
].cpusubtype
& ~CPU_SUBTYPE_MASK
);
2884 ofile
->file_addr
+ ofile
->member_offset
+
2885 ofile
->fat_archs
[i
].offset
,
2887 if(magic
== MH_MAGIC
|| magic
== SWAP_INT(MH_MAGIC
)){
2888 #ifdef ALIGNMENT_CHECKS
2889 if((ofile
->member_offset
+ ofile
->fat_archs
[i
].offset
) %
2891 archive_member_error(ofile
, "fat object file's offset in "
2892 "archive not a multiple of 4) (must be since "
2893 "member is a 32-bit object file)");
2896 #endif /* ALIGNMENT_CHECKS */
2898 else if(magic
== MH_MAGIC_64
|| magic
== SWAP_INT(MH_MAGIC_64
)){
2899 #ifdef ALIGNMENT_CHECKS_ARCHIVE_64_BIT
2900 if(archive_64_bit_align_warning
== FALSE
&&
2901 (ofile
->member_offset
+ ofile
->fat_archs
[i
].offset
) %
2903 temporary_archive_member_warning(ofile
, "fat object file's "
2904 "offset in archive not a multiple of 8) (must be since "
2905 "member is a 64-bit object file)");
2906 archive_64_bit_align_warning
= TRUE
;
2907 /* return(CHECK_BAD); */
2909 #endif /* ALIGNMENT_CHECKS_ARCHIVE_64_BIT */
2912 archive_member_error(ofile
, "fat file for cputype (%d) "
2913 "cpusubtype (%d) is not an object file (bad magic "
2914 "number)", ofile
->fat_archs
[i
].cputype
,
2915 ofile
->fat_archs
[i
].cpusubtype
& ~CPU_SUBTYPE_MASK
);
2919 for(i
= 0; i
< ofile
->fat_header
->nfat_arch
; i
++){
2920 for(j
= i
+ 1; j
< ofile
->fat_header
->nfat_arch
; j
++){
2921 if(ofile
->fat_archs
[i
].cputype
==
2922 ofile
->fat_archs
[j
].cputype
&&
2923 (ofile
->fat_archs
[i
].cpusubtype
& ~CPU_SUBTYPE_MASK
) ==
2924 (ofile
->fat_archs
[j
].cpusubtype
& ~CPU_SUBTYPE_MASK
)){
2925 archive_member_error(ofile
, "fat file contains two of the "
2926 "same architecture (cputype (%d) cpusubtype (%d))",
2927 ofile
->fat_archs
[i
].cputype
,
2928 ofile
->fat_archs
[i
].cpusubtype
& ~CPU_SUBTYPE_MASK
);
2937 * check_archive() checks the archive referenced in the ofile for correctness.
2942 struct ofile
*ofile
,
2943 enum bool archives_with_fat_objects
)
2947 #else /* !defined OTOOL */
2949 uint32_t size
, offset
;
2952 enum byte_sex host_byte_sex
;
2954 struct mach_header mh
;
2955 struct mach_header_64 mh64
;
2956 struct ar_hdr
*ar_hdr
;
2957 uint32_t ar_name_size
;
2960 * Get the address and size of the archive (as well as the cputype and
2961 * cpusubtype if known) and make sure it is an archive.
2963 if(ofile
->file_type
== OFILE_FAT
){
2964 addr
= ofile
->file_addr
+ ofile
->fat_archs
[ofile
->narch
].offset
;
2965 size
= ofile
->fat_archs
[ofile
->narch
].size
;
2966 ofile
->archive_cputype
= ofile
->fat_archs
[ofile
->narch
].cputype
;
2967 ofile
->archive_cpusubtype
=
2968 ofile
->fat_archs
[ofile
->narch
].cpusubtype
;
2970 else if(ofile
->file_type
== OFILE_ARCHIVE
){
2971 addr
= ofile
->file_addr
;
2972 size
= ofile
->file_size
;
2973 ofile
->archive_cputype
= 0;
2974 ofile
->archive_cpusubtype
= 0;
2977 error("internal error. check_archive() call and file type of %s is "
2978 "OFILE_UNKNOWN\n", ofile
->file_name
);
2981 if(size
< SARMAG
|| strncmp(addr
, ARMAG
, SARMAG
) != 0){
2982 error("internal error. check_archive() call for file %s which does "
2983 "not have an archive magic string", ofile
->file_name
);
2987 host_byte_sex
= get_host_byte_sex();
2989 * Check this archive out to make sure that it does not contain
2990 * any fat files and that all object files it contains have the
2991 * same cputype and subsubtype.
2996 if(offset
!= size
&& offset
+ sizeof(struct ar_hdr
) > size
){
2997 archive_error(ofile
, "truncated or malformed (archive header of "
2998 "first member extends past the end of the file)");
3001 while(size
> offset
){
3002 ar_hdr
= (struct ar_hdr
*)(addr
+ offset
);
3003 ofile
->member_offset
= offset
;
3004 ofile
->member_addr
= addr
+ offset
;
3005 ofile
->member_size
= strtoul(ar_hdr
->ar_size
, NULL
, 10);
3006 ofile
->member_ar_hdr
= ar_hdr
;
3007 ofile
->member_name
= ar_hdr
->ar_name
;
3008 ofile
->member_name_size
= size_ar_name(ofile
->member_ar_hdr
);
3009 offset
+= sizeof(struct ar_hdr
);
3011 * See if this archive member is using extend format #1 where
3012 * the size of the name is in ar_name and the name follows the
3016 if(strncmp(ofile
->member_name
,AR_EFMT1
, sizeof(AR_EFMT1
) - 1) == 0){
3017 if(check_extend_format_1(ofile
, ar_hdr
, size
- offset
,
3018 &ar_name_size
) == CHECK_BAD
)
3020 ofile
->member_name
= ar_hdr
->ar_name
+ sizeof(struct ar_hdr
);
3021 ofile
->member_name_size
= ar_name_size
;
3022 offset
+= ar_name_size
;
3023 ofile
->member_offset
+= ar_name_size
;
3024 ofile
->member_addr
+= ar_name_size
;
3025 ofile
->member_size
-= ar_name_size
;
3027 big_size
= rnd(ofile
->member_size
, sizeof(short));
3029 if(big_size
> size
){
3030 archive_member_error(ofile
, "size too large (archive "
3031 "member extends past the end of the file)");
3034 if(size
- offset
> sizeof(uint32_t)){
3035 memcpy(&magic
, addr
+ offset
, sizeof(uint32_t));
3036 #ifdef __BIG_ENDIAN__
3037 if(magic
== FAT_MAGIC
)
3038 #endif /* __BIG_ENDIAN__ */
3039 #ifdef __LITTLE_ENDIAN__
3040 if(magic
== SWAP_INT(FAT_MAGIC
))
3041 #endif /* __LITTLE_ENDIAN__ */
3043 if(archives_with_fat_objects
== FALSE
||
3044 ofile
->file_type
!= OFILE_ARCHIVE
){
3045 archive_member_error(ofile
, "is a fat file (not "
3046 "allowed in an archive)");
3051 if(size
- offset
>= sizeof(struct mach_header
) &&
3052 (magic
== MH_MAGIC
|| magic
== SWAP_INT(MH_MAGIC
))){
3053 memcpy(&mh
, addr
+ offset
, sizeof(struct mach_header
));
3054 if(magic
== SWAP_INT(MH_MAGIC
)){
3057 swap_mach_header(&mh
, host_byte_sex
);
3061 else if(size
- offset
>= sizeof(struct mach_header_64
) &&
3062 (magic
== MH_MAGIC_64
||
3063 magic
== SWAP_INT(MH_MAGIC_64
))){
3064 memcpy(&mh64
, addr
+ offset
,
3065 sizeof(struct mach_header_64
));
3066 if(magic
== SWAP_INT(MH_MAGIC_64
)){
3067 magic
= MH_MAGIC_64
;
3069 swap_mach_header_64(&mh64
, host_byte_sex
);
3073 if(magic
== MH_MAGIC
){
3074 if(ofile
->archive_cputype
== 0){
3075 ofile
->archive_cputype
= mh
.cputype
;
3076 ofile
->archive_cpusubtype
= mh
.cpusubtype
;
3078 else if(ofile
->archive_cputype
!= mh
.cputype
){
3079 archive_member_error(ofile
, "cputype (%d) does not "
3080 "match previous archive members cputype (%d) "
3081 "(all members must match)", mh
.cputype
,
3082 ofile
->archive_cputype
);
3085 else if(magic
== MH_MAGIC_64
){
3086 if(ofile
->archive_cputype
== 0){
3087 ofile
->archive_cputype
= mh64
.cputype
;
3088 ofile
->archive_cpusubtype
= mh64
.cpusubtype
;
3090 else if(ofile
->archive_cputype
!= mh64
.cputype
){
3091 archive_member_error(ofile
, "cputype (%d) does not "
3092 "match previous archive members cputype (%d) "
3093 "(all members must match)", mh64
.cputype
,
3094 ofile
->archive_cputype
);
3099 offset
+= rnd(ofile
->member_size
, sizeof(short));
3101 ofile
->member_offset
= 0;
3102 ofile
->member_addr
= NULL
;
3103 ofile
->member_size
= 0;
3104 ofile
->member_ar_hdr
= NULL
;;
3105 ofile
->member_name
= NULL
;
3106 ofile
->member_name_size
= 0;
3112 * check_extend_format_1() checks the archive header for extended format #1.
3116 check_extend_format_1(
3117 struct ofile
*ofile
,
3118 struct ar_hdr
*ar_hdr
,
3120 uint32_t *member_name_size
)
3122 char *p
, *endp
, buf
[sizeof(ar_hdr
->ar_name
)+1];
3123 uint32_t ar_name_size
;
3125 *member_name_size
= 0;
3127 buf
[sizeof(ar_hdr
->ar_name
)] = '\0';
3128 memcpy(buf
, ar_hdr
->ar_name
, sizeof(ar_hdr
->ar_name
));
3129 p
= buf
+ sizeof(AR_EFMT1
) - 1;
3130 if(isdigit(*p
) == 0){
3131 archive_error(ofile
, "malformed (ar_name: %.*s for archive "
3132 "extend format #1 starts with non-digit)",
3133 (int)sizeof(ar_hdr
->ar_name
), ar_hdr
->ar_name
);
3136 ar_name_size
= strtoul(p
, &endp
, 10);
3137 if(ar_name_size
== UINT_MAX
&& errno
== ERANGE
){
3138 archive_error(ofile
, "malformed (size in ar_name: %.*s for "
3139 "archive extend format #1 overflows uint32_t)",
3140 (int)sizeof(ar_hdr
->ar_name
), ar_hdr
->ar_name
);
3143 while(*endp
== ' ' && *endp
!= '\0')
3146 archive_error(ofile
, "malformed (size in ar_name: %.*s for "
3147 "archive extend format #1 contains non-digit and "
3148 "non-space characters)", (int)sizeof(ar_hdr
->ar_name
),
3152 if(ar_name_size
> size_left
){
3153 archive_error(ofile
, "truncated or malformed (archive name "
3154 "of member extends past the end of the file)");
3157 *member_name_size
= ar_name_size
;
3162 * check_archive_toc() checks the archive table of contents referenced in the
3163 * thin archive via the ofile for correctness and if bad sets the bad_toc field
3164 * in the ofile struct to TRUE. If not it sets the other toc_* fields that
3165 * ranlib(1) uses to know it can't update the table of contents and doesn't
3166 * have to totally rebuild it. And by this always returning CHECK_GOOD it
3167 * allows otool(1) to print messed up tables of contents for debugging.
3172 struct ofile
*ofile
)
3174 uint32_t i
, symdef_length
, offset
, nranlibs
, strsize
;
3175 enum byte_sex host_byte_sex
, toc_byte_sex
;
3176 struct ranlib
*ranlibs
;
3179 ofile
->toc_ranlibs
= NULL
;
3180 ofile
->toc_nranlibs
= 0;
3181 ofile
->toc_strings
= NULL
;
3182 ofile
->toc_strsize
= 0;
3185 * Note this can only be called when the whole file is a thin archive.
3187 if(ofile
->file_type
!= OFILE_ARCHIVE
)
3190 symdef_length
= ofile
->toc_size
;
3192 * The contents of a __.SYMDEF file is begins with a 32-bit word giving
3193 * the size in bytes of ranlib structures which immediately follow, and
3194 * then continues with a string table consisting of a 32-bit word giving
3195 * the number of bytes of strings which follow and then the strings
3196 * themselves. So the smallest valid size is two 32-bit words long.
3198 if(symdef_length
< 2 * sizeof(uint32_t)){
3200 * Size of table of contents for archive too small to be a valid
3201 * table of contents.
3203 ofile
->toc_bad
= TRUE
;
3206 host_byte_sex
= get_host_byte_sex();
3207 toc_byte_sex
= get_toc_byte_sex(ofile
->file_addr
, ofile
->file_size
);
3208 if(toc_byte_sex
== UNKNOWN_BYTE_SEX
){
3210 * Can't determine the byte order of table of contents as it
3211 * contains no Mach-O files.
3213 ofile
->toc_bad
= TRUE
;
3217 nranlibs
= *((uint32_t *)(ofile
->toc_addr
+ offset
));
3218 if(toc_byte_sex
!= host_byte_sex
)
3219 nranlibs
= SWAP_INT(nranlibs
);
3220 nranlibs
= nranlibs
/ sizeof(struct ranlib
);
3221 offset
+= sizeof(uint32_t);
3222 ranlibs
= (struct ranlib
*)(ofile
->toc_addr
+ offset
);
3223 offset
+= sizeof(struct ranlib
) * nranlibs
;
3226 if(offset
- (2 * sizeof(uint32_t)) > symdef_length
){
3228 * Truncated or malformed archive. The ranlib structures in table
3229 * of contents extends past the end of the table of contents.
3231 ofile
->toc_bad
= TRUE
;
3234 strsize
= *((uint32_t *)(ofile
->toc_addr
+ offset
));
3235 if(toc_byte_sex
!= host_byte_sex
)
3236 strsize
= SWAP_INT(strsize
);
3237 offset
+= sizeof(uint32_t);
3238 strings
= ofile
->toc_addr
+ offset
;
3240 if(offset
- (2 * sizeof(uint32_t)) > symdef_length
){
3242 * Truncated or malformed archive. The ranlib strings in table of
3243 * contents extends past the end of the table of contents.
3245 ofile
->toc_bad
= TRUE
;
3248 if(symdef_length
== 2 * sizeof(uint32_t))
3252 * Check the string offset and the member offsets of the ranlib structs.
3254 if(toc_byte_sex
!= host_byte_sex
)
3255 swap_ranlib(ranlibs
, nranlibs
, host_byte_sex
);
3256 for(i
= 0; i
< nranlibs
; i
++){
3257 if(ranlibs
[i
].ran_un
.ran_strx
>= strsize
){
3259 * Malformed table of contents. The ranlib struct at this index
3260 * has a bad string index field.
3262 ofile
->toc_bad
= TRUE
;
3265 if(ranlibs
[i
].ran_off
>= ofile
->file_size
){
3267 * Malformed table of contents. The ranlib struct at this index
3268 * has a bad library member offset field.
3270 ofile
->toc_bad
= TRUE
;
3274 * These should be on 4 byte boundaries because the maximum
3275 * alignment of the header structures and relocation are 4 bytes.
3276 * But this is has to be 2 bytes because that's the way ar(1) has
3277 * worked historicly in the past. Fortunately this works on the
3278 * 68k machines but will have to change when this is on a real
3281 #if defined(mc68000) || defined(__i386__)
3282 if(ranlibs
[i
].ran_off
% sizeof(short) != 0){
3284 * Malformed table of contents. This ranlib struct library
3285 * member offset not a multiple 2 bytes.
3287 ofile
->toc_bad
= TRUE
;
3291 if(ranlibs
[i
].ran_off
% sizeof(uint32_t) != 0){
3293 * Malformed table of contents. This ranlib struct library
3294 * member offset not a multiple of 4 bytes.
3296 ofile
->toc_bad
= TRUE
;
3301 ofile
->toc_ranlibs
= ranlibs
;
3302 ofile
->toc_nranlibs
= nranlibs
;
3303 ofile
->toc_strings
= strings
;
3304 ofile
->toc_strsize
= strsize
;
3309 * check_Mach_O() checks the object file's mach header and load commands
3310 * referenced in the ofile for correctness (this also swaps the mach header
3311 * and load commands into the host byte sex if needed).
3316 struct ofile
*ofile
)
3320 #else /* !defined OTOOL */
3321 uint32_t size
, i
, j
, ncmds
, sizeofcmds
, load_command_multiple
, sizeofhdrs
;
3323 char *addr
, *cmd_name
, *element_name
;
3324 enum byte_sex host_byte_sex
;
3326 struct mach_header
*mh
;
3327 struct mach_header_64
*mh64
;
3328 struct load_command
*load_commands
, *lc
, l
;
3329 struct segment_command
*sg
;
3330 struct segment_command_64
*sg64
;
3332 struct section_64
*s64
;
3333 struct symtab_command
*st
;
3334 struct dysymtab_command
*dyst
;
3335 struct symseg_command
*ss
;
3336 struct fvmlib_command
*fl
;
3337 struct dylib_command
*dl
;
3338 struct sub_framework_command
*sub
;
3339 struct sub_umbrella_command
*usub
;
3340 struct sub_library_command
*lsub
;
3341 struct sub_client_command
*csub
;
3342 struct prebound_dylib_command
*pbdylib
;
3343 struct dylinker_command
*dyld
;
3344 struct thread_command
*ut
;
3345 struct ident_command
*id
;
3346 struct routines_command
*rc
;
3347 struct routines_command_64
*rc64
;
3348 struct twolevel_hints_command
*hints
;
3349 struct linkedit_data_command
*code_sig
, *split_info
, *func_starts
,
3350 *data_in_code
, *code_sign_drs
, *linkedit_data
;
3351 struct version_min_command
*vers
;
3352 struct prebind_cksum_command
*cs
;
3353 struct encryption_info_command
*encrypt_info
;
3354 struct dyld_info_command
*dyld_info
;
3355 struct uuid_command
*uuid
;
3356 struct rpath_command
*rpath
;
3357 struct entry_point_command
*ep
;
3358 struct source_version_command
*sv
;
3359 uint32_t flavor
, count
, nflavor
;
3361 uint32_t sizeof_nlist
, sizeof_dylib_module
;
3362 char *struct_dylib_module_name
, *struct_nlist_name
;
3363 uint64_t big_size
, big_end
, big_load_end
;
3364 struct element elements
;
3366 elements
.offset
= 0;
3368 elements
.name
= NULL
;
3369 elements
.next
= NULL
;
3371 addr
= ofile
->object_addr
;
3372 size
= ofile
->object_size
;
3375 load_commands
= ofile
->load_commands
;
3376 host_byte_sex
= get_host_byte_sex();
3377 swapped
= (enum bool)(host_byte_sex
!= ofile
->object_byte_sex
);
3379 if(ofile
->mh
!= NULL
){
3381 swap_mach_header(mh
, host_byte_sex
);
3382 big_size
= mh
->sizeofcmds
;
3383 big_size
+= sizeof(struct mach_header
);
3384 if(big_size
> size
){
3385 Mach_O_error(ofile
, "truncated or malformed object (load "
3386 "commands extend past the end of the file)");
3389 sizeofhdrs
= big_size
;
3390 ofile
->mh_cputype
= mh
->cputype
;
3391 ofile
->mh_cpusubtype
= mh
->cpusubtype
;
3392 ofile
->mh_filetype
= mh
->filetype
;
3394 sizeofcmds
= mh
->sizeofcmds
;
3395 cputype
= mh
->cputype
;
3396 load_command_multiple
= 4;
3397 sizeof_nlist
= sizeof(struct nlist
);
3398 struct_nlist_name
= "struct nlist";
3399 sizeof_dylib_module
= sizeof(struct dylib_module
);
3400 struct_dylib_module_name
= "struct dylib_module";
3404 swap_mach_header_64(mh64
, host_byte_sex
);
3405 big_size
= mh64
->sizeofcmds
;
3406 big_size
+= sizeof(struct mach_header_64
);
3407 if(big_size
> size
){
3408 Mach_O_error(ofile
, "truncated or malformed object (load "
3409 "commands extend past the end of the file)");
3412 sizeofhdrs
= big_size
;
3413 ofile
->mh_cputype
= mh64
->cputype
;
3414 ofile
->mh_cpusubtype
= mh64
->cpusubtype
;
3415 ofile
->mh_filetype
= mh64
->filetype
;
3416 ncmds
= mh64
->ncmds
;
3417 sizeofcmds
= mh64
->sizeofcmds
;
3418 cputype
= mh64
->cputype
;
3419 load_command_multiple
= 8;
3420 sizeof_nlist
= sizeof(struct nlist_64
);
3421 struct_nlist_name
= "struct nlist_64";
3422 sizeof_dylib_module
= sizeof(struct dylib_module_64
);
3423 struct_dylib_module_name
= "struct dylib_module_64";
3425 if(check_overlaping_element(ofile
, &elements
, 0, sizeofhdrs
,
3426 "Mach-O headers") == CHECK_BAD
)
3428 if(ofile
->file_type
== OFILE_FAT
){
3429 if(ofile
->fat_archs
[ofile
->narch
].cputype
!= ofile
->mh_cputype
){
3430 Mach_O_error(ofile
, "malformed fat file (fat header "
3431 "architecture: %u's cputype does not match "
3432 "object file's mach header)", ofile
->narch
);
3437 * Make a pass through the load commands checking them to the level
3438 * that they can be parsed and all fields with offsets and sizes do
3439 * not extend past the end of the file.
3448 data_in_code
= NULL
;
3449 code_sign_drs
= NULL
;
3453 encrypt_info
= NULL
;
3457 for(i
= 0, lc
= load_commands
; i
< ncmds
; i
++){
3460 swap_load_command(&l
, host_byte_sex
);
3462 * Check load command size for a multiple of load_command_multiple.
3464 if(l
.cmdsize
% load_command_multiple
!= 0){
3466 * We have a hack here to allow 64-bit Mach-O core files to
3467 * have LC_THREAD commands that are only a multiple of 4 and
3468 * not 8 to be allowed since the kernel produces them.
3470 if(ofile
->mh64
== NULL
||
3471 ofile
->mh64
->filetype
!= MH_CORE
||
3472 l
.cmd
!= LC_THREAD
||
3473 l
.cmdsize
% 4 != 0){
3474 Mach_O_error(ofile
, "malformed object (load command %u "
3475 "cmdsize not a multiple of %u)", i
,
3476 load_command_multiple
);
3480 /* check that load command does not extends past end of commands */
3481 big_load_end
+= l
.cmdsize
;
3482 if(big_load_end
> sizeofcmds
){
3483 Mach_O_error(ofile
, "truncated or malformed object (load "
3484 "command %u extends past the end of the file)",i
);
3487 /* check that the load command size is not zero */
3489 Mach_O_error(ofile
, "malformed object (load command %u cmdsize"
3495 if(l
.cmdsize
< sizeof(struct segment_command
)){
3496 Mach_O_error(ofile
, "malformed object (LC_SEGMENT cmdsize "
3497 "too small) in command %u", i
);
3500 sg
= (struct segment_command
*)lc
;
3502 swap_segment_command(sg
, host_byte_sex
);
3503 big_size
= sg
->nsects
;
3504 big_size
*= sizeof(struct section
);
3505 big_size
+= sizeof(struct segment_command
);
3506 if(sg
->cmdsize
!= big_size
){
3507 Mach_O_error(ofile
, "malformed object (inconsistent "
3508 "cmdsize in LC_SEGMENT command %u for the "
3509 "number of sections)", i
);
3512 if(sg
->fileoff
> size
){
3513 Mach_O_error(ofile
, "truncated or malformed object ("
3514 "LC_SEGMENT command %u fileoff field "
3515 "extends past the end of the file)", i
);
3518 big_size
= sg
->fileoff
;
3519 big_size
+= sg
->filesize
;
3520 if(big_size
> size
){
3521 Mach_O_error(ofile
, "truncated or malformed object ("
3522 "LC_SEGMENT command %u fileoff field "
3523 "plus filesize field extends past the end of "
3527 if(sg
->vmsize
!= 0 && sg
->filesize
> sg
->vmsize
){
3528 Mach_O_error(ofile
, "malformed object (LC_SEGMENT command "
3529 "%u filesize field greater than vmsize field)",
3533 s
= (struct section
*)
3534 ((char *)sg
+ sizeof(struct segment_command
));
3536 swap_section(s
, sg
->nsects
, host_byte_sex
);
3537 for(j
= 0 ; j
< sg
->nsects
; j
++){
3538 if(mh
->filetype
!= MH_DYLIB_STUB
&&
3539 s
->flags
!= S_ZEROFILL
&&
3540 s
->flags
!= S_THREAD_LOCAL_ZEROFILL
&& s
->offset
> size
){
3541 Mach_O_error(ofile
, "truncated or malformed object "
3542 "(offset field of section %u in LC_SEGMENT "
3543 "command %u extends past the end of the file)",
3547 if(mh
->filetype
!= MH_DYLIB_STUB
&&
3548 s
->flags
!= S_ZEROFILL
&&
3549 s
->flags
!= S_THREAD_LOCAL_ZEROFILL
&&
3550 sg
->fileoff
== 0 && s
->offset
< sizeofhdrs
){
3551 Mach_O_error(ofile
, "malformed object (offset field of "
3552 "section %u in LC_SEGMENT command %u not "
3553 "past the headers of the file)", j
, i
);
3556 big_size
= s
->offset
;
3557 big_size
+= s
->size
;
3558 if(mh
->filetype
!= MH_DYLIB_STUB
&&
3559 s
->flags
!= S_ZEROFILL
&&
3560 s
->flags
!= S_THREAD_LOCAL_ZEROFILL
&& big_size
> size
){
3561 Mach_O_error(ofile
, "truncated or malformed object "
3562 "(offset field plus size field of section %u "
3563 "in LC_SEGMENT command %u extends "
3564 "past the end of the file)", j
, i
);
3567 if(mh
->filetype
!= MH_DYLIB_STUB
&&
3568 s
->flags
!= S_ZEROFILL
&&
3569 s
->flags
!= S_THREAD_LOCAL_ZEROFILL
&&
3570 s
->size
> sg
->filesize
){
3571 Mach_O_error(ofile
, "malformed object (size field of "
3572 "section %u in LC_SEGMENT command %u greater "
3573 "than the segment)", j
, i
);
3576 if(mh
->filetype
!= MH_DYLIB_STUB
&&
3577 s
->size
!= 0 && s
->addr
< sg
->vmaddr
){
3578 Mach_O_error(ofile
, "malformed object (addr field of "
3579 "section %u in LC_SEGMENT command %u less than "
3580 "the segment's vmaddr)", j
, i
);
3584 big_size
+= s
->size
;
3585 big_end
= sg
->vmaddr
;
3586 big_end
+= sg
->vmsize
;
3587 if(sg
->vmsize
!= 0 && s
->size
!= 0 && big_size
> big_end
){
3588 Mach_O_error(ofile
, "malformed object (addr field plus "
3589 "size of section %u in LC_SEGMENT command %u "
3590 "greater than than the segment's vmaddr plus "
3594 if(mh
->filetype
!= MH_DYLIB_STUB
&&
3595 s
->flags
!= S_ZEROFILL
&&
3596 s
->flags
!= S_THREAD_LOCAL_ZEROFILL
&&
3597 check_overlaping_element(ofile
, &elements
, s
->offset
,
3598 s
->size
, "section contents") == CHECK_BAD
)
3600 if(s
->reloff
> size
){
3601 Mach_O_error(ofile
, "truncated or malformed object "
3602 "(reloff field of section %u in LC_SEGMENT "
3603 "command %u extends past the end of the file)",
3607 big_size
= s
->nreloc
;
3608 big_size
*= sizeof(struct relocation_info
);
3609 big_size
+= s
->reloff
;
3610 if(big_size
> size
){
3611 Mach_O_error(ofile
, "truncated or malformed object "
3612 "(reloff field plus nreloc field times sizeof("
3613 "struct relocation_info) of section %u in "
3614 "LC_SEGMENT command %u extends past the "
3615 "end of the file)", j
, i
);
3618 if(check_overlaping_element(ofile
, &elements
, s
->reloff
,
3619 s
->nreloc
* sizeof(struct relocation_info
),
3620 "section relocation entries") == CHECK_BAD
)
3627 if(l
.cmdsize
< sizeof(struct segment_command_64
)){
3628 Mach_O_error(ofile
, "malformed object (LC_SEGMENT_64 "
3629 "cmdsize too small) in command %u", i
);
3632 sg64
= (struct segment_command_64
*)lc
;
3634 swap_segment_command_64(sg64
, host_byte_sex
);
3635 big_size
= sg64
->nsects
;
3636 big_size
*= sizeof(struct section_64
);
3637 big_size
+= sizeof(struct segment_command_64
);
3638 if(sg64
->cmdsize
!= big_size
){
3639 Mach_O_error(ofile
, "malformed object (inconsistent "
3640 "cmdsize in LC_SEGMENT_64 command %u for "
3641 "the number of sections)", i
);
3644 if(sg64
->fileoff
> size
){
3645 Mach_O_error(ofile
, "truncated or malformed object ("
3646 "LC_SEGMENT_64 command %u fileoff field "
3647 "extends past the end of the file)", i
);
3650 big_size
= sg64
->fileoff
;
3651 big_size
+= sg64
->filesize
;
3652 if(big_size
> size
){
3653 Mach_O_error(ofile
, "truncated or malformed object ("
3654 "LC_SEGMENT_64 command %u fileoff field "
3655 "plus filesize field extends past the end of "
3659 s64
= (struct section_64
*)
3660 ((char *)sg64
+ sizeof(struct segment_command_64
));
3662 swap_section_64(s64
, sg64
->nsects
, host_byte_sex
);
3663 for(j
= 0 ; j
< sg64
->nsects
; j
++){
3664 if(mh64
->filetype
!= MH_DYLIB_STUB
&&
3665 s64
->flags
!= S_ZEROFILL
&&
3666 s64
->flags
!= S_THREAD_LOCAL_ZEROFILL
&&
3667 s64
->offset
> size
){
3668 Mach_O_error(ofile
, "truncated or malformed object "
3669 "(offset field of section %u in LC_SEGMENT_64 "
3670 "command %u extends past the end of the file)",
3674 big_size
= s64
->offset
;
3675 big_size
+= s64
->size
;
3676 if(mh64
->filetype
!= MH_DYLIB_STUB
&&
3677 s64
->flags
!= S_ZEROFILL
&&
3678 s64
->flags
!= S_THREAD_LOCAL_ZEROFILL
&&
3680 Mach_O_error(ofile
, "truncated or malformed object "
3681 "(offset field plus size field of section %u "
3682 "in LC_SEGMENT_64 command %u extends "
3683 "past the end of the file)", j
, i
);
3686 if(mh64
->filetype
!= MH_DYLIB_STUB
&&
3687 s64
->flags
!= S_ZEROFILL
&&
3688 s64
->flags
!= S_THREAD_LOCAL_ZEROFILL
&&
3689 check_overlaping_element(ofile
, &elements
, s64
->offset
,
3690 s64
->size
, "section contents") == CHECK_BAD
)
3692 if(s64
->reloff
> size
){
3693 Mach_O_error(ofile
, "truncated or malformed object "
3694 "(reloff field of section %u in LC_SEGMENT_64 "
3695 "command %u extends past the end of the file)",
3699 big_size
= s64
->nreloc
;
3700 big_size
*= sizeof(struct relocation_info
);
3701 big_size
+= s64
->reloff
;
3702 if(big_size
> size
){
3703 Mach_O_error(ofile
, "truncated or malformed object "
3704 "(reloff field plus nreloc field times sizeof("
3705 "struct relocation_info) of section %u in "
3706 "LC_SEGMENT_64 command %u extends past the "
3707 "end of the file)", j
, i
);
3710 if(check_overlaping_element(ofile
, &elements
, s64
->reloff
,
3711 s64
->nreloc
* sizeof(struct relocation_info
),
3712 "section relocation entries") == CHECK_BAD
)
3719 if(l
.cmdsize
< sizeof(struct symtab_command
)){
3720 Mach_O_error(ofile
, "malformed object (LC_SYMTAB cmdsize "
3721 "too small) in command %u", i
);
3725 Mach_O_error(ofile
, "malformed object (more than one "
3726 "LC_SYMTAB command)");
3729 st
= (struct symtab_command
*)lc
;
3731 swap_symtab_command(st
, host_byte_sex
);
3732 if(st
->cmdsize
!= sizeof(struct symtab_command
)){
3733 Mach_O_error(ofile
, "malformed object (LC_SYMTAB command "
3734 "%u has incorrect cmdsize)", i
);
3737 if(st
->symoff
> size
){
3738 Mach_O_error(ofile
, "truncated or malformed object (symoff "
3739 "field of LC_SYMTAB command %u extends past the end "
3743 big_size
= st
->nsyms
;
3744 big_size
*= sizeof_nlist
;
3745 big_size
+= st
->symoff
;
3746 if(big_size
> size
){
3747 Mach_O_error(ofile
, "truncated or malformed object (symoff "
3748 "field plus nsyms field times sizeof(%s) of LC_SYMTAB "
3749 "command %u extends past the end of the file)",
3750 struct_nlist_name
, i
);
3753 if(check_overlaping_element(ofile
, &elements
, st
->symoff
,
3754 st
->nsyms
* sizeof_nlist
, "symbol table") == CHECK_BAD
)
3756 if(st
->stroff
> size
){
3757 Mach_O_error(ofile
, "truncated or malformed object (stroff "
3758 "field of LC_SYMTAB command %u extends past the end "
3762 big_size
= st
->stroff
;
3763 big_size
+= st
->strsize
;
3764 if(big_size
> size
){
3765 Mach_O_error(ofile
, "truncated or malformed object (stroff "
3766 "field plus strsize field of LC_SYMTAB command %u "
3767 "extends past the end of the file)", i
);
3770 if(check_overlaping_element(ofile
, &elements
, st
->stroff
,
3771 st
->strsize
, "string table") == CHECK_BAD
)
3776 if(l
.cmdsize
< sizeof(struct dysymtab_command
)){
3777 Mach_O_error(ofile
, "malformed object (LC_DYSYMTAB cmdsize "
3778 "too small) in command %u", i
);
3782 Mach_O_error(ofile
, "malformed object (more than one "
3783 "LC_DYSYMTAB command)");
3786 dyst
= (struct dysymtab_command
*)lc
;
3788 swap_dysymtab_command(dyst
, host_byte_sex
);
3789 if(dyst
->cmdsize
!= sizeof(struct dysymtab_command
)){
3790 Mach_O_error(ofile
, "malformed object (LC_DYSYMTAB command "
3791 "%u has incorrect cmdsize)", i
);
3794 if(dyst
->tocoff
> size
){
3795 Mach_O_error(ofile
, "truncated or malformed object (tocoff "
3796 "field of LC_DYSYMTAB command %u extends past the end "
3800 big_size
= dyst
->ntoc
;
3801 big_size
*= sizeof(struct dylib_table_of_contents
);
3802 big_size
+= dyst
->tocoff
;
3803 if(big_size
> size
){
3804 Mach_O_error(ofile
, "truncated or malformed object (tocoff "
3805 "field plus ntoc field times sizeof(struct dylib_table"
3806 "_of_contents) of LC_DYSYMTAB command %u extends past "
3807 "the end of the file)", i
);
3810 if(check_overlaping_element(ofile
, &elements
, dyst
->tocoff
,
3811 dyst
->ntoc
* sizeof(struct dylib_table_of_contents
),
3812 "table of contents") == CHECK_BAD
)
3814 if(dyst
->modtaboff
> size
){
3815 Mach_O_error(ofile
, "truncated or malformed object "
3816 "(modtaboff field of LC_DYSYMTAB command %u extends "
3817 "past the end of the file)", i
);
3820 big_size
= dyst
->nmodtab
;
3821 big_size
*= sizeof_dylib_module
;
3822 big_size
+= dyst
->modtaboff
;
3823 if(big_size
> size
){
3824 Mach_O_error(ofile
, "truncated or malformed object "
3825 "(modtaboff field plus nmodtab field times sizeof(%s) "
3826 "of LC_DYSYMTAB command %u extends past the end of "
3827 "the file)", struct_dylib_module_name
, i
);
3830 if(check_overlaping_element(ofile
, &elements
, dyst
->modtaboff
,
3831 dyst
->nmodtab
* sizeof_dylib_module
, "module table") ==
3834 if(dyst
->extrefsymoff
> size
){
3835 Mach_O_error(ofile
, "truncated or malformed object "
3836 "(extrefsymoff field of LC_DYSYMTAB command %u "
3837 "extends past the end of the file)", i
);
3840 big_size
= dyst
->nextrefsyms
;
3841 big_size
*= sizeof(struct dylib_reference
);
3842 big_size
+= dyst
->extrefsymoff
;
3843 if(big_size
> size
){
3844 Mach_O_error(ofile
, "truncated or malformed object "
3845 "(extrefsymoff field plus nextrefsyms field times "
3846 "sizeof(struct dylib_reference) of LC_DYSYMTAB command "
3847 "%u extends past the end of the file)", i
);
3850 if(check_overlaping_element(ofile
, &elements
,dyst
->extrefsymoff
,
3851 dyst
->nextrefsyms
* sizeof(struct dylib_reference
),
3852 "reference table") == CHECK_BAD
)
3854 if(dyst
->indirectsymoff
> size
){
3855 Mach_O_error(ofile
, "truncated or malformed object "
3856 "(indirectsymoff field of LC_DYSYMTAB command %u "
3857 "extends past the end of the file)", i
);
3860 big_size
= dyst
->nindirectsyms
;
3861 big_size
*= sizeof(uint32_t);
3862 big_size
+= dyst
->indirectsymoff
;
3863 if(big_size
> size
){
3864 Mach_O_error(ofile
, "truncated or malformed object "
3865 "(indirectsymoff field plus nindirectsyms field times "
3866 "sizeof(uint32_t) of LC_DYSYMTAB command "
3867 "%u extends past the end of the file)", i
);
3870 if(check_overlaping_element(ofile
, &elements
,
3871 dyst
->indirectsymoff
, dyst
->nindirectsyms
*
3872 sizeof(uint32_t), "indirect table") == CHECK_BAD
)
3874 if(dyst
->extreloff
> size
){
3875 Mach_O_error(ofile
, "truncated or malformed object "
3876 "(extreloff field of LC_DYSYMTAB command %u "
3877 "extends past the end of the file)", i
);
3880 big_size
= dyst
->nextrel
;
3881 big_size
*= sizeof(struct relocation_info
);
3882 big_size
+= dyst
->extreloff
;
3883 if(big_size
> size
){
3884 Mach_O_error(ofile
, "truncated or malformed object "
3885 "(extreloff field plus nextrel field times "
3886 "sizeof(struct relocation_info) of LC_DYSYMTAB command "
3887 "%u extends past the end of the file)", i
);
3890 if(check_overlaping_element(ofile
, &elements
, dyst
->extreloff
,
3891 dyst
->nextrel
* sizeof(struct relocation_info
),
3892 "external relocation table") == CHECK_BAD
)
3894 if(dyst
->locreloff
> size
){
3895 Mach_O_error(ofile
, "truncated or malformed object "
3896 "(locreloff field of LC_DYSYMTAB command %u "
3897 "extends past the end of the file)", i
);
3900 big_size
= dyst
->nlocrel
;
3901 big_size
*= sizeof(struct relocation_info
);
3902 big_size
+= dyst
->locreloff
;
3903 if(big_size
> size
){
3904 Mach_O_error(ofile
, "truncated or malformed object "
3905 "(locreloff field plus nlocrel field times "
3906 "sizeof(struct relocation_info) of LC_DYSYMTAB command "
3907 "%u extends past the end of the file)", i
);
3910 if(check_overlaping_element(ofile
, &elements
, dyst
->locreloff
,
3911 dyst
->nlocrel
* sizeof(struct relocation_info
),
3912 "local relocation table") == CHECK_BAD
)
3917 if(l
.cmdsize
< sizeof(struct routines_command
)){
3918 Mach_O_error(ofile
, "malformed object (LC_ROUTINES cmdsize "
3919 "too small) in command %u", i
);
3923 Mach_O_error(ofile
, "malformed object (more than one "
3924 "LC_ROUTINES command)");
3927 rc
= (struct routines_command
*)lc
;
3929 swap_routines_command(rc
, host_byte_sex
);
3930 if(rc
->cmdsize
!= sizeof(struct routines_command
)){
3931 Mach_O_error(ofile
, "malformed object (LC_ROUTINES "
3932 "command %u has incorrect cmdsize)", i
);
3937 case LC_ROUTINES_64
:
3938 if(l
.cmdsize
< sizeof(struct routines_command_64
)){
3939 Mach_O_error(ofile
, "malformed object (LC_ROUTINES_64 "
3940 "cmdsize too small) in command %u", i
);
3944 Mach_O_error(ofile
, "malformed object (more than one "
3945 "LC_ROUTINES_64 command)");
3948 rc64
= (struct routines_command_64
*)lc
;
3950 swap_routines_command_64(rc64
, host_byte_sex
);
3951 if(rc64
->cmdsize
!= sizeof(struct routines_command_64
)){
3952 Mach_O_error(ofile
, "malformed object (LC_ROUTINES_64 "
3953 "command %u has incorrect cmdsize)", i
);
3958 case LC_TWOLEVEL_HINTS
:
3959 if(l
.cmdsize
< sizeof(struct twolevel_hints_command
)){
3960 Mach_O_error(ofile
, "malformed object (LC_TWOLEVEL_HINTS "
3961 "cmdsize too small) in command %u", i
);
3965 Mach_O_error(ofile
, "malformed object (more than one "
3966 "LC_TWOLEVEL_HINTS command)");
3969 hints
= (struct twolevel_hints_command
*)lc
;
3971 swap_twolevel_hints_command(hints
, host_byte_sex
);
3972 if(hints
->cmdsize
!= sizeof(struct twolevel_hints_command
)){
3973 Mach_O_error(ofile
, "malformed object (LC_TWOLEVEL_HINTS "
3974 "command %u has incorrect cmdsize)", i
);
3977 if(hints
->offset
> size
){
3978 Mach_O_error(ofile
, "truncated or malformed object "
3979 "(offset field of LC_TWOLEVEL_HINTS command %u "
3980 "extends past the end of the file)", i
);
3983 big_size
= hints
->nhints
;
3984 big_size
*= sizeof(struct twolevel_hint
);
3985 big_size
+= hints
->offset
;
3986 if(big_size
> size
){
3987 Mach_O_error(ofile
, "truncated or malformed object "
3988 "(offset field plus nhints field times "
3989 "sizeof(struct twolevel_hint) of LC_TWOLEVEL_HINTS "
3990 " command %u extends past the end of the file)", i
);
3993 if(check_overlaping_element(ofile
, &elements
, hints
->offset
,
3994 hints
->nhints
* sizeof(struct twolevel_hint
),
3995 "two level hints") == CHECK_BAD
)
3999 case LC_SEGMENT_SPLIT_INFO
:
4000 cmd_name
= "LC_SEGMENT_SPLIT_INFO";
4001 element_name
= "split info data";
4002 if(split_info
!= NULL
){
4003 Mach_O_error(ofile
, "malformed object (more than one "
4004 "%s command)", cmd_name
);
4007 split_info
= (struct linkedit_data_command
*)lc
;
4008 goto check_linkedit_data_command
;
4010 case LC_CODE_SIGNATURE
:
4011 cmd_name
= "LC_CODE_SIGNATURE";
4012 element_name
= "code signature data";
4013 if(code_sig
!= NULL
){
4014 Mach_O_error(ofile
, "malformed object (more than one "
4015 "%s command)", cmd_name
);
4018 code_sig
= (struct linkedit_data_command
*)lc
;
4019 goto check_linkedit_data_command
;
4021 case LC_FUNCTION_STARTS
:
4022 cmd_name
= "LC_FUNCTION_STARTS";
4023 element_name
= "function starts data";
4024 if(func_starts
!= NULL
){
4025 Mach_O_error(ofile
, "malformed object (more than one "
4026 "%s command)", cmd_name
);
4029 func_starts
= (struct linkedit_data_command
*)lc
;
4030 goto check_linkedit_data_command
;
4032 case LC_DATA_IN_CODE
:
4033 cmd_name
= "LC_DATA_IN_CODE";
4034 element_name
= "date in code info";
4035 if(data_in_code
!= NULL
){
4036 Mach_O_error(ofile
, "malformed object (more than one "
4037 "%s command)", cmd_name
);
4040 data_in_code
= (struct linkedit_data_command
*)lc
;
4041 goto check_linkedit_data_command
;
4043 case LC_DYLIB_CODE_SIGN_DRS
:
4044 cmd_name
= "LC_DYLIB_CODE_SIGN_DRS";
4045 element_name
= "code signing RDs data";
4046 if(code_sign_drs
!= NULL
){
4047 Mach_O_error(ofile
, "malformed object (more than one "
4048 "%s command)", cmd_name
);
4051 code_sign_drs
= (struct linkedit_data_command
*)lc
;
4052 goto check_linkedit_data_command
;
4054 check_linkedit_data_command
:
4055 if(l
.cmdsize
< sizeof(struct linkedit_data_command
)){
4056 Mach_O_error(ofile
, "malformed object (%s cmdsize too "
4057 "small) in command %u", cmd_name
, i
);
4060 linkedit_data
= (struct linkedit_data_command
*)lc
;
4062 swap_linkedit_data_command(linkedit_data
, host_byte_sex
);
4063 if(linkedit_data
->cmdsize
!=
4064 sizeof(struct linkedit_data_command
)){
4065 Mach_O_error(ofile
, "malformed object (%s command %u has "
4066 "incorrect cmdsize)", cmd_name
, i
);
4069 if(linkedit_data
->dataoff
> size
){
4070 Mach_O_error(ofile
, "truncated or malformed object "
4071 "(dataoff field of %s command %u extends past the end "
4072 "of the file)", cmd_name
, i
);
4075 big_size
= linkedit_data
->dataoff
;
4076 big_size
+= linkedit_data
->datasize
;
4077 if(big_size
> size
){
4078 Mach_O_error(ofile
, "truncated or malformed object "
4079 "(dataoff field plus datasize field of "
4080 "%s command %u extends past the end of "
4081 "the file)", cmd_name
, i
);
4084 if(check_overlaping_element(ofile
, &elements
,
4085 linkedit_data
->dataoff
, linkedit_data
->datasize
,
4086 element_name
) == CHECK_BAD
)
4090 case LC_VERSION_MIN_MACOSX
:
4091 if(l
.cmdsize
< sizeof(struct version_min_command
)){
4092 Mach_O_error(ofile
, "malformed object (LC_VERSION_MIN_"
4093 "MACOSX cmdsize too small) in command %u", i
);
4097 Mach_O_error(ofile
, "malformed object (more than one "
4098 "LC_VERSION_MIN_IPHONEOS or LC_VERSION_MIN_MACOSX "
4102 vers
= (struct version_min_command
*)lc
;
4104 swap_version_min_command(vers
, host_byte_sex
);
4105 if(vers
->cmdsize
< sizeof(struct version_min_command
)){
4106 Mach_O_error(ofile
, "malformed object (LC_VERSION_MIN_"
4107 "MACOSX command %u has too small cmdsize field)", i
);
4112 case LC_VERSION_MIN_IPHONEOS
:
4113 if(l
.cmdsize
< sizeof(struct version_min_command
)){
4114 Mach_O_error(ofile
, "malformed object (LC_VERSION_MIN_"
4115 "IPHONEOS cmdsize too small) in command %u",i
);
4119 Mach_O_error(ofile
, "malformed object (more than one "
4120 "LC_VERSION_MIN_IPHONEOS or LC_VERSION_MIN_MACOSX "
4124 vers
= (struct version_min_command
*)lc
;
4126 swap_version_min_command(vers
, host_byte_sex
);
4127 if(vers
->cmdsize
< sizeof(struct version_min_command
)){
4128 Mach_O_error(ofile
, "malformed object (LC_VERSION_MIN_"
4129 "IPHONEOS command %u has too small cmdsize field)", i
);
4134 case LC_ENCRYPTION_INFO
:
4135 if(l
.cmdsize
< sizeof(struct encryption_info_command
)){
4136 Mach_O_error(ofile
, "malformed object (LC_ENCRYPTION_INFO "
4137 "cmdsize too small) in command %u", i
);
4140 encrypt_info
= (struct encryption_info_command
*)lc
;
4142 swap_encryption_command(encrypt_info
, host_byte_sex
);
4143 if(encrypt_info
->cmdsize
!=
4144 sizeof(struct encryption_info_command
)){
4145 Mach_O_error(ofile
, "malformed object (LC_ENCRYPTION_INFO"
4146 "command %u has incorrect cmdsize)", i
);
4149 if(encrypt_info
->cryptoff
> size
){
4150 Mach_O_error(ofile
, "truncated or malformed object (cryptoff "
4151 "field of LC_ENCRYPTION_INFO command %u extends "
4152 "past the end of the file)", i
);
4155 big_size
= encrypt_info
->cryptoff
;
4156 big_size
+= encrypt_info
->cryptsize
;
4157 if(big_size
> size
){
4158 Mach_O_error(ofile
, "truncated or malformed object "
4159 "(cryptoff field plus cryptsize field of "
4160 "LC_ENCRYPTION_INFO command %u extends past "
4161 "the end of the file)", i
);
4167 case LC_DYLD_INFO_ONLY
:
4168 if(l
.cmdsize
< sizeof(struct dyld_info_command
)){
4169 Mach_O_error(ofile
, "malformed object (%s cmdsize "
4170 "too small) in command %u", l
.cmd
==
4171 LC_DYLD_INFO
? "LC_DYLD_INFO" :
4172 "LC_DYLD_INFO_ONLY", i
);
4175 dyld_info
= (struct dyld_info_command
*)lc
;
4177 swap_dyld_info_command(dyld_info
, host_byte_sex
);
4178 if(dyld_info
->cmdsize
!=
4179 sizeof(struct dyld_info_command
)){
4180 Mach_O_error(ofile
, "malformed object (LC_DYLD_INFO"
4181 "command %u has incorrect cmdsize)", i
);
4184 if(dyld_info
->rebase_off
!= 0 && dyld_info
->rebase_off
> size
){
4185 Mach_O_error(ofile
, "truncated or malformed object "
4186 "(rebase_off field of LC_DYLD_INFO command %u "
4187 "extends past the end of the file)", i
);
4190 if(dyld_info
->rebase_off
!= 0){
4191 big_size
= dyld_info
->rebase_off
;
4192 big_size
+= dyld_info
->rebase_size
;
4193 if(big_size
> size
){
4194 Mach_O_error(ofile
, "truncated or malformed object "
4195 "(rebase_off plus rebase_size of LC_DYLD_INFO "
4196 "command %u extends past the end of the file)", i
);
4200 if(check_overlaping_element(ofile
, &elements
,
4201 dyld_info
->rebase_off
, dyld_info
->rebase_size
,
4202 "dyld rebase info") == CHECK_BAD
)
4204 if(dyld_info
->bind_off
!= 0 && dyld_info
->bind_off
> size
){
4205 Mach_O_error(ofile
, "truncated or malformed object "
4206 "(bind_off field of LC_DYLD_INFO command %u "
4207 "extends past the end of the file)", i
);
4210 if(dyld_info
->bind_off
!= 0){
4211 big_size
= dyld_info
->bind_off
;
4212 big_size
+= dyld_info
->bind_size
;
4213 if(big_size
> size
){
4214 Mach_O_error(ofile
, "truncated or malformed object "
4215 "(bind_off plus bind_size of LC_DYLD_INFO command "
4216 "%u extends past the end of the file)", i
);
4220 if(check_overlaping_element(ofile
, &elements
,
4221 dyld_info
->bind_off
, dyld_info
->bind_size
,
4222 "dyld bind info") == CHECK_BAD
)
4224 if(dyld_info
->weak_bind_off
!= 0 &&
4225 dyld_info
->weak_bind_off
> size
){
4226 Mach_O_error(ofile
, "truncated or malformed object "
4227 "(weak_bind_off field of LC_DYLD_INFO command %u "
4228 "extends past the end of the file)", i
);
4231 if(dyld_info
->weak_bind_off
!= 0){
4232 big_size
= dyld_info
->weak_bind_off
;
4233 big_size
+= dyld_info
->weak_bind_size
;
4234 if(big_size
> size
){
4235 Mach_O_error(ofile
, "truncated or malformed object "
4236 "(weak_bind_off plus weak_bind_size of LC_DYLD_INFO"
4237 " command %u extends past the end of the file)", i
);
4241 if(check_overlaping_element(ofile
, &elements
,
4242 dyld_info
->weak_bind_off
, dyld_info
->weak_bind_size
,
4243 "dyld bind info") == CHECK_BAD
)
4245 if(dyld_info
->lazy_bind_off
!= 0 &&
4246 dyld_info
->lazy_bind_off
> size
){
4247 Mach_O_error(ofile
, "truncated or malformed object "
4248 "(lazy_bind_off field of LC_DYLD_INFO command %u "
4249 "extends past the end of the file)", i
);
4252 if(dyld_info
->lazy_bind_off
!= 0){
4253 big_size
= dyld_info
->lazy_bind_off
;
4254 big_size
+= dyld_info
->lazy_bind_size
;
4255 if(big_size
> size
){
4256 Mach_O_error(ofile
, "truncated or malformed object "
4257 "(lazy_bind_off plus lazy_bind_size of LC_DYLD_INFO"
4258 " command %u extends past the end of the file)", i
);
4262 if(check_overlaping_element(ofile
, &elements
,
4263 dyld_info
->lazy_bind_off
, dyld_info
->lazy_bind_size
,
4264 "dyld lazy bind info") == CHECK_BAD
)
4266 if(dyld_info
->export_off
!= 0 && dyld_info
->export_off
> size
){
4267 Mach_O_error(ofile
, "truncated or malformed object "
4268 "(export_off field of LC_DYLD_INFO command %u "
4269 "extends past the end of the file)", i
);
4272 if(dyld_info
->export_off
!= 0){
4273 big_size
= dyld_info
->export_off
;
4274 big_size
+= dyld_info
->export_size
;
4275 if(big_size
> size
){
4276 Mach_O_error(ofile
, "truncated or malformed object "
4277 "(export_off plus export_size of LC_DYLD_INFO "
4278 "command %u extends past the end of the file)", i
);
4282 if(check_overlaping_element(ofile
, &elements
,
4283 dyld_info
->export_off
, dyld_info
->export_size
,
4284 "dyld export info") == CHECK_BAD
)
4290 case LC_PREBIND_CKSUM
:
4291 if(l
.cmdsize
< sizeof(struct prebind_cksum_command
)){
4292 Mach_O_error(ofile
, "malformed object (LC_PREBIND_CKSUM "
4293 "cmdsize too small) in command %u", i
);
4297 Mach_O_error(ofile
, "malformed object (more than one "
4298 "LC_PREBIND_CKSUM command)");
4301 cs
= (struct prebind_cksum_command
*)lc
;
4303 swap_prebind_cksum_command(cs
, host_byte_sex
);
4304 if(cs
->cmdsize
!= sizeof(struct prebind_cksum_command
)){
4305 Mach_O_error(ofile
, "malformed object (LC_PREBIND_CKSUM "
4306 "command %u has incorrect cmdsize)", i
);
4312 if(l
.cmdsize
< sizeof(struct uuid_command
)){
4313 Mach_O_error(ofile
, "malformed object (LC_UUID cmdsize "
4314 "too small) in command %u", i
);
4318 Mach_O_error(ofile
, "malformed object (more than one "
4319 "LC_UUID command)");
4322 uuid
= (struct uuid_command
*)lc
;
4324 swap_uuid_command(uuid
, host_byte_sex
);
4325 if(uuid
->cmdsize
!= sizeof(struct uuid_command
)){
4326 Mach_O_error(ofile
, "malformed object (LC_UUID command %u " "has incorrect cmdsize)", i
);
4332 if(l
.cmdsize
< sizeof(struct symseg_command
)){
4333 Mach_O_error(ofile
, "malformed object (LC_SYMSEG cmdsize "
4334 "too small) in command %u", i
);
4337 ss
= (struct symseg_command
*)lc
;
4339 swap_symseg_command(ss
, host_byte_sex
);
4340 if(ss
->cmdsize
!= sizeof(struct symseg_command
)){
4341 Mach_O_error(ofile
, "malformed object (LC_SYMSEG command "
4342 "%u has incorrect cmdsize)", i
);
4345 if(ss
->offset
> size
){
4346 Mach_O_error(ofile
, "truncated or malformed object (offset "
4347 "field of LC_SYMSEG command %u extends past the end "
4351 big_size
= ss
->offset
;
4352 big_size
+= ss
->size
;
4353 if(big_size
> size
){
4354 Mach_O_error(ofile
, "truncated or malformed object (offset "
4355 "field plus size field of LC_SYMTAB command %u "
4356 "extends past the end of the file)", i
);
4359 if(check_overlaping_element(ofile
, &elements
, ss
->offset
,
4360 ss
->size
, "symseg info") == CHECK_BAD
)
4366 if(l
.cmdsize
< sizeof(struct fvmlib_command
)){
4367 Mach_O_error(ofile
, "malformed object (%s cmdsize "
4368 "too small) in command %u", l
.cmd
==
4369 LC_IDFVMLIB
? "LC_IDFVMLIB" :
4370 "LC_LOADFVMLIB", i
);
4373 fl
= (struct fvmlib_command
*)lc
;
4375 swap_fvmlib_command(fl
, host_byte_sex
);
4376 if(fl
->cmdsize
< sizeof(struct fvmlib_command
)){
4377 Mach_O_error(ofile
, "malformed object (%s command %u has "
4378 "too small cmdsize field)", fl
->cmd
== LC_IDFVMLIB
?
4379 "LC_IDFVMLIB" : "LC_LOADFVMLIB", i
);
4382 if(fl
->fvmlib
.name
.offset
>= fl
->cmdsize
){
4383 Mach_O_error(ofile
, "truncated or malformed object (name."
4384 "offset field of %s command %u extends past the end "
4385 "of the file)", fl
->cmd
== LC_IDFVMLIB
? "LC_IDFVMLIB"
4386 : "LC_LOADFVMLIB", i
);
4392 cmd_name
= "LC_ID_DYLIB";
4393 goto check_dylib_command
;
4395 cmd_name
= "LC_LOAD_DYLIB";
4396 goto check_dylib_command
;
4397 case LC_LOAD_WEAK_DYLIB
:
4398 cmd_name
= "LC_LOAD_WEAK_DYLIB";
4399 goto check_dylib_command
;
4400 case LC_REEXPORT_DYLIB
:
4401 cmd_name
= "LC_REEXPORT_DYLIB";
4402 goto check_dylib_command
;
4403 case LC_LOAD_UPWARD_DYLIB
:
4404 cmd_name
= "LC_LOAD_UPWARD_DYLIB";
4405 goto check_dylib_command
;
4406 case LC_LAZY_LOAD_DYLIB
:
4407 cmd_name
= "LC_LAZY_LOAD_DYLIB";
4408 goto check_dylib_command
;
4409 check_dylib_command
:
4410 if(l
.cmdsize
< sizeof(struct dylib_command
)){
4411 Mach_O_error(ofile
, "malformed object (%s cmdsize too "
4412 "small) in command %u", cmd_name
, i
);
4415 dl
= (struct dylib_command
*)lc
;
4417 swap_dylib_command(dl
, host_byte_sex
);
4418 if(dl
->cmdsize
< sizeof(struct dylib_command
)){
4419 Mach_O_error(ofile
, "malformed object (%s command %u has "
4420 "too small cmdsize field)", cmd_name
, i
);
4423 if(dl
->dylib
.name
.offset
>= dl
->cmdsize
){
4424 Mach_O_error(ofile
, "truncated or malformed object (name."
4425 "offset field of %s command %u extends past the end "
4426 "of the file)", cmd_name
, i
);
4431 case LC_SUB_FRAMEWORK
:
4432 if(l
.cmdsize
< sizeof(struct sub_framework_command
)){
4433 Mach_O_error(ofile
, "malformed object (LC_SUB_FRAMEWORK "
4434 "cmdsize too small) in command %u", i
);
4437 sub
= (struct sub_framework_command
*)lc
;
4439 swap_sub_framework_command(sub
, host_byte_sex
);
4440 if(sub
->cmdsize
< sizeof(struct sub_framework_command
)){
4441 Mach_O_error(ofile
, "malformed object (LC_SUB_FRAMEWORK "
4442 "command %u has too small cmdsize field)", i
);
4445 if(sub
->umbrella
.offset
>= sub
->cmdsize
){
4446 Mach_O_error(ofile
, "truncated or malformed object "
4447 "(umbrella.offset field of LC_SUB_FRAMEWORK command "
4448 "%u extends past the end of the file)", i
);
4453 case LC_SUB_UMBRELLA
:
4454 if(l
.cmdsize
< sizeof(struct sub_umbrella_command
)){
4455 Mach_O_error(ofile
, "malformed object (LC_SUB_UMBRELLA "
4456 "cmdsize too small) in command %u", i
);
4459 usub
= (struct sub_umbrella_command
*)lc
;
4461 swap_sub_umbrella_command(usub
, host_byte_sex
);
4462 if(usub
->cmdsize
< sizeof(struct sub_umbrella_command
)){
4463 Mach_O_error(ofile
, "malformed object (LC_SUB_UMBRELLA "
4464 "command %u has too small cmdsize field)", i
);
4467 if(usub
->sub_umbrella
.offset
>= usub
->cmdsize
){
4468 Mach_O_error(ofile
, "truncated or malformed object "
4469 "(sub_umbrella.offset field of LC_SUB_UMBRELLA command "
4470 "%u extends past the end of the file)", i
);
4475 case LC_SUB_LIBRARY
:
4476 if(l
.cmdsize
< sizeof(struct sub_library_command
)){
4477 Mach_O_error(ofile
, "malformed object (LC_SUB_LIBRARY "
4478 "cmdsize too small) in command %u", i
);
4481 lsub
= (struct sub_library_command
*)lc
;
4483 swap_sub_library_command(lsub
, host_byte_sex
);
4484 if(lsub
->cmdsize
< sizeof(struct sub_library_command
)){
4485 Mach_O_error(ofile
, "malformed object (LC_SUB_LIBRARY "
4486 "command %u has too small cmdsize field)", i
);
4489 if(lsub
->sub_library
.offset
>= lsub
->cmdsize
){
4490 Mach_O_error(ofile
, "truncated or malformed object "
4491 "(sub_library.offset field of LC_SUB_LIBRARY command "
4492 "%u extends past the end of the file)", i
);
4498 if(l
.cmdsize
< sizeof(struct sub_client_command
)){
4499 Mach_O_error(ofile
, "malformed object (LC_SUB_CLIENT "
4500 "cmdsize too small) in command %u", i
);
4503 csub
= (struct sub_client_command
*)lc
;
4505 swap_sub_client_command(csub
, host_byte_sex
);
4506 if(csub
->cmdsize
< sizeof(struct sub_client_command
)){
4507 Mach_O_error(ofile
, "malformed object (LC_SUB_CLIENT "
4508 "command %u has too small cmdsize field)", i
);
4511 if(csub
->client
.offset
>= csub
->cmdsize
){
4512 Mach_O_error(ofile
, "truncated or malformed object "
4513 "(cleient.offset field of LC_SUB_CLIENT command "
4514 "%u extends past the end of the file)", i
);
4519 case LC_PREBOUND_DYLIB
:
4520 if(l
.cmdsize
< sizeof(struct prebound_dylib_command
)){
4521 Mach_O_error(ofile
, "malformed object (LC_PREBOUND_DYLIB "
4522 "cmdsize too small) in command %u", i
);
4525 pbdylib
= (struct prebound_dylib_command
*)lc
;
4527 swap_prebound_dylib_command(pbdylib
, host_byte_sex
);
4528 if(pbdylib
->cmdsize
< sizeof(struct dylib_command
)){
4529 Mach_O_error(ofile
, "malformed object (LC_PREBIND_DYLIB "
4530 "command %u has too small cmdsize field)", i
);
4533 if(pbdylib
->name
.offset
>= pbdylib
->cmdsize
){
4534 Mach_O_error(ofile
, "truncated or malformed object (name."
4535 "offset field of LC_PREBIND_DYLIB command %u extends "
4536 "past the end of the file)", i
);
4539 if(pbdylib
->linked_modules
.offset
>= pbdylib
->cmdsize
){
4540 Mach_O_error(ofile
, "truncated or malformed object (linked_"
4541 "modules.offset field of LC_PREBIND_DYLIB command %u "
4542 "extends past the end of the file)", i
);
4547 case LC_ID_DYLINKER
:
4548 cmd_name
= "LC_ID_DYLINKER";
4549 goto check_dylinker_command
;
4550 case LC_LOAD_DYLINKER
:
4551 cmd_name
= "LC_LOAD_DYLINKER";
4552 goto check_dylinker_command
;
4553 case LC_DYLD_ENVIRONMENT
:
4554 cmd_name
= "LC_DYLD_ENVIRONMENT";
4555 goto check_dylinker_command
;
4556 check_dylinker_command
:
4557 if(l
.cmdsize
< sizeof(struct dylinker_command
)){
4558 Mach_O_error(ofile
, "malformed object (%s cmdsize "
4559 "too small) in command %u", cmd_name
, i
);
4562 dyld
= (struct dylinker_command
*)lc
;
4564 swap_dylinker_command(dyld
, host_byte_sex
);
4565 if(dyld
->cmdsize
< sizeof(struct dylinker_command
)){
4566 Mach_O_error(ofile
, "malformed object (%s command %u has "
4567 "too small cmdsize field)", cmd_name
, i
);
4570 if(dyld
->name
.offset
>= dyld
->cmdsize
){
4571 Mach_O_error(ofile
, "truncated or malformed object (name."
4572 "offset field of %s command %u extends past the end "
4573 "of the file)", cmd_name
, i
);
4580 if(l
.cmdsize
< sizeof(struct thread_command
)){
4581 Mach_O_error(ofile
, "malformed object (%s cmdsize "
4582 "too small) in command %u", l
.cmd
==
4583 LC_UNIXTHREAD
? "LC_UNIXTHREAD" :
4587 ut
= (struct thread_command
*)lc
;
4589 swap_thread_command(ut
, host_byte_sex
);
4590 state
= (char *)ut
+ sizeof(struct thread_command
);
4592 if(cputype
== CPU_TYPE_MC680x0
){
4593 struct m68k_thread_state_regs
*cpu
;
4594 struct m68k_thread_state_68882
*fpu
;
4595 struct m68k_thread_state_user_reg
*user_reg
;
4598 p
= (char *)ut
+ ut
->cmdsize
;
4600 if(state
+ sizeof(uint32_t) >
4601 (char *)ut
+ ut
->cmdsize
){
4602 Mach_O_error(ofile
, "malformed object (flavor in "
4603 "%s command %u extends past end of command)",
4604 ut
->cmd
== LC_UNIXTHREAD
? "LC_UNIXTHREAD" :
4608 flavor
= *((uint32_t *)state
);
4610 flavor
= SWAP_INT(flavor
);
4611 *((uint32_t *)state
) = flavor
;
4613 state
+= sizeof(uint32_t);
4614 if(state
+ sizeof(uint32_t) >
4615 (char *)ut
+ ut
->cmdsize
){
4616 Mach_O_error(ofile
, "malformed object (count in "
4617 "%s command %u extends past end of command)",
4618 ut
->cmd
== LC_UNIXTHREAD
? "LC_UNIXTHREAD" :
4622 count
= *((uint32_t *)state
);
4624 count
= SWAP_INT(count
);
4625 *((uint32_t *)state
) = count
;
4627 state
+= sizeof(uint32_t);
4629 case M68K_THREAD_STATE_REGS
:
4630 if(count
!= M68K_THREAD_STATE_REGS_COUNT
){
4631 Mach_O_error(ofile
, "malformed object (count "
4632 "not M68K_THREAD_STATE_REGS_COUNT for "
4633 "flavor number %u which is a M68K_THREAD_"
4634 "STATE_REGS flavor in %s command %u)",
4635 nflavor
, ut
->cmd
== LC_UNIXTHREAD
?
4636 "LC_UNIXTHREAD" : "LC_THREAD", i
);
4639 cpu
= (struct m68k_thread_state_regs
*)state
;
4640 if(state
+ sizeof(struct m68k_thread_state_regs
) >
4641 (char *)ut
+ ut
->cmdsize
){
4642 Mach_O_error(ofile
, "malformed object ("
4643 "M68K_THREAD_STATE_REGS in %s command %u "
4644 "extends past end of command)", ut
->cmd
==
4645 LC_UNIXTHREAD
? "LC_UNIXTHREAD" :
4650 swap_m68k_thread_state_regs(cpu
, host_byte_sex
);
4651 state
+= sizeof(struct m68k_thread_state_regs
);
4653 case M68K_THREAD_STATE_68882
:
4654 if(count
!= M68K_THREAD_STATE_68882_COUNT
){
4655 Mach_O_error(ofile
, "malformed object (count "
4656 "not M68K_THREAD_STATE_68882_COUNT for "
4657 "flavor number %u which is a M68K_THREAD_"
4658 "STATE_68882 flavor in %s command %u)",
4659 nflavor
, ut
->cmd
== LC_UNIXTHREAD
?
4660 "LC_UNIXTHREAD" : "LC_THREAD", i
);
4663 fpu
= (struct m68k_thread_state_68882
*)state
;
4664 if(state
+ sizeof(struct m68k_thread_state_68882
) >
4665 (char *)ut
+ ut
->cmdsize
){
4666 Mach_O_error(ofile
, "malformed object ("
4667 "M68K_THREAD_STATE_68882 in %s command %u "
4668 "extends past end of command)", ut
->cmd
==
4669 LC_UNIXTHREAD
? "LC_UNIXTHREAD" :
4674 swap_m68k_thread_state_68882(fpu
,host_byte_sex
);
4675 state
+= sizeof(struct m68k_thread_state_68882
);
4677 case M68K_THREAD_STATE_USER_REG
:
4678 if(count
!= M68K_THREAD_STATE_USER_REG_COUNT
){
4679 Mach_O_error(ofile
, "malformed object (count "
4680 "not M68K_THREAD_STATE_USER_REG_COUNT for "
4681 "flavor number %u which is a M68K_THREAD_"
4682 "STATE_USER_REG flavor in %s command %u)",
4683 nflavor
, ut
->cmd
== LC_UNIXTHREAD
?
4684 "LC_UNIXTHREAD" : "LC_THREAD", i
);
4688 (struct m68k_thread_state_user_reg
*)state
;
4689 if(state
+sizeof(struct m68k_thread_state_user_reg
) >
4690 (char *)ut
+ ut
->cmdsize
){
4691 Mach_O_error(ofile
, "malformed object ("
4692 "M68K_THREAD_STATE_USER_REG in %s command "
4693 "%u extends past end of command)", ut
->cmd
==
4694 LC_UNIXTHREAD
? "LC_UNIXTHREAD" :
4699 swap_m68k_thread_state_user_reg(user_reg
,
4701 state
+= sizeof(struct m68k_thread_state_user_reg
);
4705 Mach_O_error(ofile
, "malformed object (unknown "
4706 "flavor for flavor number %u in %s command"
4707 " %u can't byte swap it)", nflavor
,
4708 ut
->cmd
== LC_UNIXTHREAD
? "LC_UNIXTHREAD" :
4712 state
+= count
* sizeof(uint32_t);
4719 if(cputype
== CPU_TYPE_POWERPC
||
4720 cputype
== CPU_TYPE_VEO
){
4721 ppc_thread_state_t
*nrw_cpu
;
4724 p
= (char *)ut
+ ut
->cmdsize
;
4726 if(state
+ sizeof(uint32_t) >
4727 (char *)ut
+ ut
->cmdsize
){
4728 Mach_O_error(ofile
, "malformed object (flavor in "
4729 "%s command %u extends past end of command)",
4730 ut
->cmd
== LC_UNIXTHREAD
? "LC_UNIXTHREAD" :
4734 flavor
= *((uint32_t *)state
);
4736 flavor
= SWAP_INT(flavor
);
4737 *((uint32_t *)state
) = flavor
;
4739 state
+= sizeof(uint32_t);
4740 if(state
+ sizeof(uint32_t) >
4741 (char *)ut
+ ut
->cmdsize
){
4742 Mach_O_error(ofile
, "malformed object (count in "
4743 "%s command %u extends past end of command)",
4744 ut
->cmd
== LC_UNIXTHREAD
? "LC_UNIXTHREAD" :
4748 count
= *((uint32_t *)state
);
4750 count
= SWAP_INT(count
);
4751 *((uint32_t *)state
) = count
;
4753 state
+= sizeof(uint32_t);
4755 case PPC_THREAD_STATE
:
4756 if(count
!= PPC_THREAD_STATE_COUNT
){
4757 Mach_O_error(ofile
, "malformed object (count "
4758 "not PPC_THREAD_STATE_COUNT for "
4759 "flavor number %u which is a PPC_THREAD_"
4760 "STATE flavor in %s command %u)",
4761 nflavor
, ut
->cmd
== LC_UNIXTHREAD
?
4762 "LC_UNIXTHREAD" : "LC_THREAD", i
);
4765 nrw_cpu
= (ppc_thread_state_t
*)state
;
4766 if(state
+ sizeof(ppc_thread_state_t
) >
4767 (char *)ut
+ ut
->cmdsize
){
4768 Mach_O_error(ofile
, "malformed object ("
4769 "PPC_THREAD_STATE in %s command %u extends"
4770 " past end of command)", ut
->cmd
==
4771 LC_UNIXTHREAD
? "LC_UNIXTHREAD" :
4776 swap_ppc_thread_state_t(nrw_cpu
,
4778 state
+= sizeof(ppc_thread_state_t
);
4782 Mach_O_error(ofile
, "malformed object (unknown "
4783 "flavor for flavor number %u in %s command"
4784 " %u can't byte swap it)", nflavor
,
4785 ut
->cmd
== LC_UNIXTHREAD
? "LC_UNIXTHREAD" :
4789 state
+= count
* sizeof(uint32_t);
4796 #ifdef PPC_THREAD_STATE64_COUNT
4797 if(cputype
== CPU_TYPE_POWERPC64
){
4798 ppc_thread_state64_t
*cpu
;
4801 p
= (char *)ut
+ ut
->cmdsize
;
4803 if(state
+ sizeof(uint32_t) >
4804 (char *)ut
+ ut
->cmdsize
){
4805 Mach_O_error(ofile
, "malformed object (flavor in "
4806 "%s command %u extends past end of command)",
4807 ut
->cmd
== LC_UNIXTHREAD
? "LC_UNIXTHREAD" :
4811 flavor
= *((uint32_t *)state
);
4813 flavor
= SWAP_INT(flavor
);
4814 *((uint32_t *)state
) = flavor
;
4816 state
+= sizeof(uint32_t);
4817 if(state
+ sizeof(uint32_t) >
4818 (char *)ut
+ ut
->cmdsize
){
4819 Mach_O_error(ofile
, "malformed object (count in "
4820 "%s command %u extends past end of command)",
4821 ut
->cmd
== LC_UNIXTHREAD
? "LC_UNIXTHREAD" :
4825 count
= *((uint32_t *)state
);
4827 count
= SWAP_INT(count
);
4828 *((uint32_t *)state
) = count
;
4830 state
+= sizeof(uint32_t);
4832 case PPC_THREAD_STATE64
:
4833 if(count
!= PPC_THREAD_STATE64_COUNT
){
4834 Mach_O_error(ofile
, "malformed object (count "
4835 "not PPC_THREAD_STATE64_COUNT for "
4836 "flavor number %u which is a PPC_THREAD_"
4837 "STATE64 flavor in %s command %u)",
4838 nflavor
, ut
->cmd
== LC_UNIXTHREAD
?
4839 "LC_UNIXTHREAD" : "LC_THREAD", i
);
4842 cpu
= (ppc_thread_state64_t
*)state
;
4843 if(state
+ sizeof(ppc_thread_state64_t
) >
4844 (char *)ut
+ ut
->cmdsize
){
4845 Mach_O_error(ofile
, "malformed object ("
4846 "PPC_THREAD_STATE64 in %s command %u "
4847 "extends past end of command)", ut
->cmd
==
4848 LC_UNIXTHREAD
? "LC_UNIXTHREAD" :
4853 swap_ppc_thread_state64_t(cpu
, host_byte_sex
);
4854 state
+= sizeof(ppc_thread_state64_t
);
4858 Mach_O_error(ofile
, "malformed object (unknown "
4859 "flavor for flavor number %u in %s command"
4860 " %u can't byte swap it)", nflavor
,
4861 ut
->cmd
== LC_UNIXTHREAD
? "LC_UNIXTHREAD" :
4865 state
+= count
* sizeof(uint32_t);
4872 #endif /* PPC_THREAD_STATE64_COUNT */
4873 if(cputype
== CPU_TYPE_MC88000
){
4874 m88k_thread_state_grf_t
*cpu
;
4875 m88k_thread_state_xrf_t
*fpu
;
4876 m88k_thread_state_user_t
*user
;
4877 m88110_thread_state_impl_t
*spu
;
4880 p
= (char *)ut
+ ut
->cmdsize
;
4882 if(state
+ sizeof(uint32_t) >
4883 (char *)ut
+ ut
->cmdsize
){
4884 Mach_O_error(ofile
, "malformed object (flavor in "
4885 "%s command %u extends past end of command)",
4886 ut
->cmd
== LC_UNIXTHREAD
? "LC_UNIXTHREAD" :
4890 flavor
= *((uint32_t *)state
);
4892 flavor
= SWAP_INT(flavor
);
4893 *((uint32_t *)state
) = flavor
;
4895 state
+= sizeof(uint32_t);
4896 if(state
+ sizeof(uint32_t) >
4897 (char *)ut
+ ut
->cmdsize
){
4898 Mach_O_error(ofile
, "malformed object (count in "
4899 "%s command %u extends past end of command)",
4900 ut
->cmd
== LC_UNIXTHREAD
? "LC_UNIXTHREAD" :
4904 count
= *((uint32_t *)state
);
4906 count
= SWAP_INT(count
);
4907 *((uint32_t *)state
) = count
;
4909 state
+= sizeof(uint32_t);
4911 case M88K_THREAD_STATE_GRF
:
4912 if(count
!= M88K_THREAD_STATE_GRF_COUNT
){
4913 Mach_O_error(ofile
, "malformed object (count "
4914 "not M88K_THREAD_STATE_GRF_COUNT for "
4915 "flavor number %u which is a M88K_THREAD_"
4916 "STATE_GRF flavor in %s command %u)",
4917 nflavor
, ut
->cmd
== LC_UNIXTHREAD
?
4918 "LC_UNIXTHREAD" : "LC_THREAD", i
);
4921 cpu
= (m88k_thread_state_grf_t
*)state
;
4922 if(state
+ sizeof(m88k_thread_state_grf_t
) >
4923 (char *)ut
+ ut
->cmdsize
){
4924 Mach_O_error(ofile
, "malformed object ("
4925 "M88K_THREAD_STATE_GRF in %s command %u "
4926 "extends past end of command)", ut
->cmd
==
4927 LC_UNIXTHREAD
? "LC_UNIXTHREAD" :
4932 swap_m88k_thread_state_grf_t(cpu
,
4934 state
+= sizeof(m88k_thread_state_grf_t
);
4936 case M88K_THREAD_STATE_XRF
:
4937 if(count
!= M88K_THREAD_STATE_XRF_COUNT
){
4938 Mach_O_error(ofile
, "malformed object (count "
4939 "not M88K_THREAD_STATE_XRF_COUNT for "
4940 "flavor number %u which is a M88K_THREAD_"
4941 "STATE_XRF flavor in %s command %u)",
4942 nflavor
, ut
->cmd
== LC_UNIXTHREAD
?
4943 "LC_UNIXTHREAD" : "LC_THREAD", i
);
4946 fpu
= (m88k_thread_state_xrf_t
*)state
;
4947 if(state
+ sizeof(m88k_thread_state_xrf_t
) >
4948 (char *)ut
+ ut
->cmdsize
){
4949 Mach_O_error(ofile
, "malformed object ("
4950 "M88K_THREAD_STATE_XRF in %s command %u "
4951 "extends past end of command)", ut
->cmd
==
4952 LC_UNIXTHREAD
? "LC_UNIXTHREAD" :
4957 swap_m88k_thread_state_xrf_t(fpu
,
4959 state
+= sizeof(m88k_thread_state_xrf_t
);
4961 case M88K_THREAD_STATE_USER
:
4962 if(count
!= M88K_THREAD_STATE_USER_COUNT
){
4963 Mach_O_error(ofile
, "malformed object (count "
4964 "not M88K_THREAD_STATE_USER_COUNT for "
4965 "flavor number %u which is a M88K_THREAD_"
4966 "STATE_USER flavor in %s command %u)",
4967 nflavor
, ut
->cmd
== LC_UNIXTHREAD
?
4968 "LC_UNIXTHREAD" : "LC_THREAD", i
);
4971 user
= (m88k_thread_state_user_t
*)state
;
4972 if(state
+ sizeof(m88k_thread_state_user_t
) >
4973 (char *)ut
+ ut
->cmdsize
){
4974 Mach_O_error(ofile
, "malformed object ("
4975 "M88K_THREAD_STATE_USER in %s command %u "
4976 "extends past end of command)", ut
->cmd
==
4977 LC_UNIXTHREAD
? "LC_UNIXTHREAD" :
4982 swap_m88k_thread_state_user_t(user
,
4984 state
+= sizeof(m88k_thread_state_user_t
);
4986 case M88110_THREAD_STATE_IMPL
:
4987 if(count
!= M88110_THREAD_STATE_IMPL_COUNT
){
4988 Mach_O_error(ofile
, "malformed object (count "
4989 "not M88110_THREAD_STATE_IMPL_COUNT for "
4990 "flavor number %u which is a M88110_THREAD"
4991 "_STATE_IMPL flavor in %s command %u)",
4992 nflavor
, ut
->cmd
== LC_UNIXTHREAD
?
4993 "LC_UNIXTHREAD" : "LC_THREAD", i
);
4996 spu
= (m88110_thread_state_impl_t
*)state
;
4997 if(state
+ sizeof(m88110_thread_state_impl_t
) >
4998 (char *)ut
+ ut
->cmdsize
){
4999 Mach_O_error(ofile
, "malformed object ("
5000 "M88110_THREAD_STATE_IMPL in %s command %u "
5001 "extends past end of command)", ut
->cmd
==
5002 LC_UNIXTHREAD
? "LC_UNIXTHREAD" :
5007 swap_m88110_thread_state_impl_t(spu
,
5009 state
+= sizeof(m88110_thread_state_impl_t
);
5013 Mach_O_error(ofile
, "malformed object (unknown "
5014 "flavor for flavor number %u in %s command"
5015 " %u can't byte swap it)", nflavor
,
5016 ut
->cmd
== LC_UNIXTHREAD
? "LC_UNIXTHREAD" :
5020 state
+= count
* sizeof(uint32_t);
5027 if(cputype
== CPU_TYPE_I860
){
5029 struct i860_thread_state_regs
*cpu
;
5033 p
= (char *)ut
+ ut
->cmdsize
;
5035 if(state
+ sizeof(uint32_t) >
5036 (char *)ut
+ ut
->cmdsize
){
5037 Mach_O_error(ofile
, "malformed object (flavor in "
5038 "%s command %u extends past end of command)",
5039 ut
->cmd
== LC_UNIXTHREAD
? "LC_UNIXTHREAD" :
5043 flavor
= *((uint32_t *)state
);
5045 flavor
= SWAP_INT(flavor
);
5046 *((uint32_t *)state
) = flavor
;
5048 state
+= sizeof(uint32_t);
5049 if(state
+ sizeof(uint32_t) >
5050 (char *)ut
+ ut
->cmdsize
){
5051 Mach_O_error(ofile
, "malformed object (count in "
5052 "%s command %u extends past end of command)",
5053 ut
->cmd
== LC_UNIXTHREAD
? "LC_UNIXTHREAD" :
5057 count
= *((uint32_t *)state
);
5059 count
= SWAP_INT(count
);
5060 *((uint32_t *)state
) = count
;
5062 state
+= sizeof(uint32_t);
5064 case I860_THREAD_STATE_REGS
:
5066 if(count
!= I860_THREAD_STATE_REGS_COUNT
){
5067 Mach_O_error(ofile
, "malformed object (count "
5068 "not I860_THREAD_STATE_REGS_COUNT for "
5069 "flavor number %u which is a I860_THREAD_"
5070 "STATE_REGS flavor in %s command %u)",
5071 nflavor
, ut
->cmd
== LC_UNIXTHREAD
?
5072 "LC_UNIXTHREAD" : "LC_THREAD", i
);
5075 cpu
= (struct i860_thread_state_regs
*)state
;
5076 if(state
+ sizeof(struct i860_thread_state_regs
) >
5077 (char *)ut
+ ut
->cmdsize
){
5078 Mach_O_error(ofile
, "malformed object ("
5079 "I860_THREAD_STATE_REGS in %s command %u "
5080 "extends past end of command)", ut
->cmd
==
5081 LC_UNIXTHREAD
? "LC_UNIXTHREAD" :
5086 swap_i860_thread_state_regs(cpu
, host_byte_sex
);
5087 state
+= sizeof(struct i860_thread_state_regs
);
5089 state
+= count
* sizeof(int);
5094 Mach_O_error(ofile
, "malformed object (unknown "
5095 "flavor for flavor number %u in %s command"
5096 " %u can't byte swap it)", nflavor
,
5097 ut
->cmd
== LC_UNIXTHREAD
? "LC_UNIXTHREAD" :
5101 state
+= count
* sizeof(uint32_t);
5108 if(cputype
== CPU_TYPE_I386
){
5109 i386_thread_state_t
*cpu
;
5110 /* current i386 thread states */
5111 #if i386_THREAD_STATE == 1
5112 struct i386_float_state
*fpu
;
5113 i386_exception_state_t
*exc
;
5114 #endif /* i386_THREAD_STATE == 1 */
5116 /* i386 thread states on older releases */
5117 #if i386_THREAD_STATE == -1
5118 i386_thread_fpstate_t
*fpu
;
5119 i386_thread_exceptstate_t
*exc
;
5120 i386_thread_cthreadstate_t
*user
;
5121 #endif /* i386_THREAD_STATE == -1 */
5124 p
= (char *)ut
+ ut
->cmdsize
;
5126 if(state
+ sizeof(uint32_t) >
5127 (char *)ut
+ ut
->cmdsize
){
5128 Mach_O_error(ofile
, "malformed object (flavor in "
5129 "%s command %u extends past end of command)",
5130 ut
->cmd
== LC_UNIXTHREAD
? "LC_UNIXTHREAD" :
5134 flavor
= *((uint32_t *)state
);
5136 flavor
= SWAP_INT(flavor
);
5137 *((uint32_t *)state
) = flavor
;
5139 state
+= sizeof(uint32_t);
5140 if(state
+ sizeof(uint32_t) >
5141 (char *)ut
+ ut
->cmdsize
){
5142 Mach_O_error(ofile
, "malformed object (count in "
5143 "%s command %u extends past end of command)",
5144 ut
->cmd
== LC_UNIXTHREAD
? "LC_UNIXTHREAD" :
5148 count
= *((uint32_t *)state
);
5150 count
= SWAP_INT(count
);
5151 *((uint32_t *)state
) = count
;
5153 state
+= sizeof(uint32_t);
5154 switch((int)flavor
){
5155 case i386_THREAD_STATE
:
5156 #if i386_THREAD_STATE == 1
5158 #endif /* i386_THREAD_STATE == 1 */
5159 /* i386 thread states on older releases */
5160 #if i386_THREAD_STATE == -1
5162 #endif /* i386_THREAD_STATE == -1 */
5163 if(count
!= i386_THREAD_STATE_COUNT
){
5164 Mach_O_error(ofile
, "malformed object (count "
5165 "not i386_THREAD_STATE_COUNT for flavor "
5166 "number %u which is a i386_THREAD_STATE "
5167 "flavor in %s command %u)", nflavor
,
5168 ut
->cmd
== LC_UNIXTHREAD
? "LC_UNIXTHREAD" :
5172 cpu
= (i386_thread_state_t
*)state
;
5173 if(state
+ sizeof(i386_thread_state_t
) >
5174 (char *)ut
+ ut
->cmdsize
){
5175 Mach_O_error(ofile
, "malformed object ("
5176 "i386_THREAD_STATE in %s command %u "
5177 "extends past end of command)", ut
->cmd
==
5178 LC_UNIXTHREAD
? "LC_UNIXTHREAD" :
5183 swap_i386_thread_state(cpu
, host_byte_sex
);
5184 state
+= sizeof(i386_thread_state_t
);
5186 /* current i386 thread states */
5187 #if i386_THREAD_STATE == 1
5188 case i386_FLOAT_STATE
:
5189 if(count
!= i386_FLOAT_STATE_COUNT
){
5190 Mach_O_error(ofile
, "malformed object (count "
5191 "not i386_FLOAT_STATE_COUNT for flavor "
5192 "number %u which is a i386_FLOAT_STATE "
5193 "flavor in %s command %u)", nflavor
,
5194 ut
->cmd
== LC_UNIXTHREAD
? "LC_UNIXTHREAD" :
5198 fpu
= (struct i386_float_state
*)state
;
5199 if(state
+ sizeof(struct i386_float_state
) >
5200 (char *)ut
+ ut
->cmdsize
){
5201 Mach_O_error(ofile
, "malformed object ("
5202 "i386_FLOAT_STATE in %s command %u "
5203 "extends past end of command)", ut
->cmd
==
5204 LC_UNIXTHREAD
? "LC_UNIXTHREAD" :
5209 swap_i386_float_state(fpu
, host_byte_sex
);
5210 state
+= sizeof(struct i386_float_state
);
5212 case i386_EXCEPTION_STATE
:
5213 if(count
!= I386_EXCEPTION_STATE_COUNT
){
5214 Mach_O_error(ofile
, "malformed object (count "
5215 "not I386_EXCEPTION_STATE_COUNT for "
5216 "flavor number %u which is a i386_"
5217 "EXCEPTION_STATE flavor in %s command %u)",
5219 ut
->cmd
== LC_UNIXTHREAD
? "LC_UNIXTHREAD" :
5223 exc
= (i386_exception_state_t
*)state
;
5224 if(state
+ sizeof(i386_exception_state_t
) >
5225 (char *)ut
+ ut
->cmdsize
){
5226 Mach_O_error(ofile
, "malformed object ("
5227 "i386_EXCEPTION_STATE in %s command %u "
5228 "extends past end of command)", ut
->cmd
==
5229 LC_UNIXTHREAD
? "LC_UNIXTHREAD" :
5234 swap_i386_exception_state(exc
,host_byte_sex
);
5235 state
+= sizeof(i386_exception_state_t
);
5237 #endif /* i386_THREAD_STATE == 1 */
5239 /* i386 thread states on older releases */
5240 #if i386_THREAD_STATE == -1
5241 case i386_THREAD_FPSTATE
:
5242 if(count
!= i386_THREAD_FPSTATE_COUNT
){
5243 Mach_O_error(ofile
, "malformed object (count "
5244 "not i386_THREAD_FPSTATE_COUNT for flavor "
5245 "number %u which is a i386_THREAD_FPSTATE "
5246 "flavor in %s command %u)", nflavor
,
5247 ut
->cmd
== LC_UNIXTHREAD
? "LC_UNIXTHREAD" :
5251 fpu
= (i386_thread_fpstate_t
*)state
;
5252 if(state
+ sizeof(i386_thread_fpstate_t
) >
5253 (char *)ut
+ ut
->cmdsize
){
5254 Mach_O_error(ofile
, "malformed object ("
5255 "i386_THREAD_FPSTATE in %s command %u "
5256 "extends past end of command)", ut
->cmd
==
5257 LC_UNIXTHREAD
? "LC_UNIXTHREAD" :
5262 swap_i386_thread_fpstate(fpu
, host_byte_sex
);
5263 state
+= sizeof(i386_thread_fpstate_t
);
5265 case i386_THREAD_EXCEPTSTATE
:
5266 if(count
!= i386_THREAD_EXCEPTSTATE_COUNT
){
5267 Mach_O_error(ofile
, "malformed object (count "
5268 "not i386_THREAD_EXCEPTSTATE_COUNT for "
5269 "flavor number %u which is a i386_THREAD_"
5270 "EXCEPTSTATE flavor in %s command %u)",
5272 ut
->cmd
== LC_UNIXTHREAD
? "LC_UNIXTHREAD" :
5276 exc
= (i386_thread_exceptstate_t
*)state
;
5277 if(state
+ sizeof(i386_thread_exceptstate_t
) >
5278 (char *)ut
+ ut
->cmdsize
){
5279 Mach_O_error(ofile
, "malformed object ("
5280 "i386_THREAD_EXCEPTSTATE in %s command %u "
5281 "extends past end of command)", ut
->cmd
==
5282 LC_UNIXTHREAD
? "LC_UNIXTHREAD" :
5287 swap_i386_thread_exceptstate(exc
,host_byte_sex
);
5288 state
+= sizeof(i386_thread_exceptstate_t
);
5290 case i386_THREAD_CTHREADSTATE
:
5291 if(count
!= i386_THREAD_CTHREADSTATE_COUNT
){
5292 Mach_O_error(ofile
, "malformed object (count "
5293 "not i386_THREAD_CTHREADSTATE_COUNT for "
5294 "flavor number %u which is a i386_THREAD_"
5295 "CTHREADSTATE flavor in %s command %u)",
5297 ut
->cmd
== LC_UNIXTHREAD
? "LC_UNIXTHREAD" :
5301 user
= (i386_thread_cthreadstate_t
*)state
;
5302 if(state
+ sizeof(i386_thread_cthreadstate_t
) >
5303 (char *)ut
+ ut
->cmdsize
){
5304 Mach_O_error(ofile
, "malformed object ("
5305 "i386_THREAD_CTHREADSTATE in %s command %u "
5306 "extends past end of command)", ut
->cmd
==
5307 LC_UNIXTHREAD
? "LC_UNIXTHREAD" :
5312 swap_i386_thread_cthreadstate(user
,
5314 state
+= sizeof(i386_thread_cthreadstate_t
);
5316 #endif /* i386_THREAD_STATE == -1 */
5319 Mach_O_error(ofile
, "malformed object (unknown "
5320 "flavor for flavor number %u in %s command"
5321 " %u can't byte swap it)", nflavor
,
5322 ut
->cmd
== LC_UNIXTHREAD
? "LC_UNIXTHREAD" :
5326 state
+= count
* sizeof(uint32_t);
5333 #ifdef x86_THREAD_STATE64_COUNT
5334 if(cputype
== CPU_TYPE_X86_64
){
5335 x86_thread_state64_t
*cpu
;
5338 p
= (char *)ut
+ ut
->cmdsize
;
5340 if(state
+ sizeof(uint32_t) >
5341 (char *)ut
+ ut
->cmdsize
){
5342 Mach_O_error(ofile
, "malformed object (flavor in "
5343 "%s command %u extends past end of command)",
5344 ut
->cmd
== LC_UNIXTHREAD
? "LC_UNIXTHREAD" :
5348 flavor
= *((uint32_t *)state
);
5350 flavor
= SWAP_INT(flavor
);
5351 *((uint32_t *)state
) = flavor
;
5353 state
+= sizeof(uint32_t);
5354 if(state
+ sizeof(uint32_t) >
5355 (char *)ut
+ ut
->cmdsize
){
5356 Mach_O_error(ofile
, "malformed object (count in "
5357 "%s command %u extends past end of command)",
5358 ut
->cmd
== LC_UNIXTHREAD
? "LC_UNIXTHREAD" :
5362 count
= *((uint32_t *)state
);
5364 count
= SWAP_INT(count
);
5365 *((uint32_t *)state
) = count
;
5367 state
+= sizeof(uint32_t);
5369 case x86_THREAD_STATE64
:
5370 if(count
!= x86_THREAD_STATE64_COUNT
){
5371 Mach_O_error(ofile
, "malformed object (count "
5372 "not x86_THREAD_STATE64_COUNT for "
5373 "flavor number %u which is a x86_THREAD_"
5374 "STATE64 flavor in %s command %u)",
5375 nflavor
, ut
->cmd
== LC_UNIXTHREAD
?
5376 "LC_UNIXTHREAD" : "LC_THREAD", i
);
5379 cpu
= (x86_thread_state64_t
*)state
;
5380 if(state
+ sizeof(x86_thread_state64_t
) >
5381 (char *)ut
+ ut
->cmdsize
){
5382 Mach_O_error(ofile
, "malformed object ("
5383 "x86_THREAD_STATE64 in %s command %u "
5384 "extends past end of command)", ut
->cmd
==
5385 LC_UNIXTHREAD
? "LC_UNIXTHREAD" :
5390 swap_x86_thread_state64(cpu
, host_byte_sex
);
5391 state
+= sizeof(x86_thread_state64_t
);
5395 Mach_O_error(ofile
, "malformed object (unknown "
5396 "flavor for flavor number %u in %s command"
5397 " %u can't byte swap it)", nflavor
,
5398 ut
->cmd
== LC_UNIXTHREAD
? "LC_UNIXTHREAD" :
5402 state
+= count
* sizeof(uint32_t);
5409 #endif /* x86_THREAD_STATE64_COUNT */
5410 if(cputype
== CPU_TYPE_HPPA
){
5411 struct hp_pa_integer_thread_state
*cpu
;
5412 struct hp_pa_frame_thread_state
*frame
;
5413 struct hp_pa_fp_thread_state
*fpu
;
5416 p
= (char *)ut
+ ut
->cmdsize
;
5418 if(state
+ sizeof(uint32_t) >
5419 (char *)ut
+ ut
->cmdsize
){
5420 Mach_O_error(ofile
, "malformed object (flavor in "
5421 "%s command %u extends past end of command)",
5422 ut
->cmd
== LC_UNIXTHREAD
? "LC_UNIXTHREAD" :
5426 flavor
= *((uint32_t *)state
);
5428 flavor
= SWAP_INT(flavor
);
5429 *((uint32_t *)state
) = flavor
;
5431 state
+= sizeof(uint32_t);
5432 if(state
+ sizeof(uint32_t) >
5433 (char *)ut
+ ut
->cmdsize
){
5434 Mach_O_error(ofile
, "malformed object (count in "
5435 "%s command %u extends past end of command)",
5436 ut
->cmd
== LC_UNIXTHREAD
? "LC_UNIXTHREAD" :
5440 count
= *((uint32_t *)state
);
5442 count
= SWAP_INT(count
);
5443 *((uint32_t *)state
) = count
;
5445 state
+= sizeof(uint32_t);
5447 case HPPA_INTEGER_THREAD_STATE
:
5448 if(count
!= HPPA_INTEGER_THREAD_STATE_COUNT
){
5449 Mach_O_error(ofile
, "malformed object (count "
5450 "not HPPA_INTEGER_THREAD_STATE_COUNT for "
5451 "flavor number %u which is a "
5452 "HPPA_INTEGER_THREAD_STATE "
5453 "flavor in %s command %u)", nflavor
,
5454 ut
->cmd
== LC_UNIXTHREAD
? "LC_UNIXTHREAD" :
5458 cpu
= (struct hp_pa_integer_thread_state
*)state
;
5459 if(state
+sizeof(struct hp_pa_integer_thread_state
) >
5460 (char *)ut
+ ut
->cmdsize
){
5461 Mach_O_error(ofile
, "malformed object ("
5462 "HPPA_INTEGER_THREAD_STATE in %s command "
5463 "%u extends past end of command)",
5464 ut
->cmd
== LC_UNIXTHREAD
? "LC_UNIXTHREAD" :
5469 swap_hppa_integer_thread_state(cpu
,
5471 state
+= sizeof(struct hp_pa_integer_thread_state
);
5473 case HPPA_FRAME_THREAD_STATE
:
5474 if(count
!= HPPA_FRAME_THREAD_STATE_COUNT
){
5475 Mach_O_error(ofile
, "malformed object (count "
5476 "not HPPA_FRAME_THREAD_STATE_COUNT for "
5477 "flavor number %u which is a HPPA_FRAME_"
5478 "THREAD_STATE flavor in %s command %u)",
5480 ut
->cmd
== LC_UNIXTHREAD
? "LC_UNIXTHREAD" :
5484 frame
= (struct hp_pa_frame_thread_state
*)state
;
5485 if(state
+ sizeof(struct hp_pa_frame_thread_state
) >
5486 (char *)ut
+ ut
->cmdsize
){
5487 Mach_O_error(ofile
, "malformed object ("
5488 "HPPA_FRAME_THREAD_STATE in %s command "
5489 "%u extends past end of command)",
5490 ut
->cmd
== LC_UNIXTHREAD
? "LC_UNIXTHREAD" :
5495 swap_hppa_frame_thread_state(frame
,host_byte_sex
);
5496 state
+= sizeof(struct hp_pa_frame_thread_state
);
5498 case HPPA_FP_THREAD_STATE
:
5499 if(count
!= HPPA_FP_THREAD_STATE_COUNT
){
5500 Mach_O_error(ofile
, "malformed object (count "
5501 "not HPPA_FP_THREAD_STATE_COUNT for "
5502 "flavor number %u which is a HPPA_FP_"
5503 "THREAD_STATE flavor in %s command %u)",
5505 ut
->cmd
== LC_UNIXTHREAD
? "LC_UNIXTHREAD" :
5509 fpu
= (struct hp_pa_fp_thread_state
*)state
;
5510 if(state
+ sizeof(struct hp_pa_fp_thread_state
) >
5511 (char *)ut
+ ut
->cmdsize
){
5512 Mach_O_error(ofile
, "malformed object ("
5513 "HPPA_FP_THREAD_STATE in %s command "
5514 "%u extends past end of command)",
5515 ut
->cmd
== LC_UNIXTHREAD
? "LC_UNIXTHREAD" :
5520 swap_hppa_fp_thread_state(fpu
,host_byte_sex
);
5521 state
+= sizeof(struct hp_pa_fp_thread_state
);
5525 Mach_O_error(ofile
, "malformed object (unknown "
5526 "flavor for flavor number %u in %s command"
5527 " %u can't byte swap it)", nflavor
,
5528 ut
->cmd
== LC_UNIXTHREAD
? "LC_UNIXTHREAD" :
5532 state
+= count
* sizeof(uint32_t);
5539 if(cputype
== CPU_TYPE_SPARC
){
5540 struct sparc_thread_state_regs
*cpu
;
5541 struct sparc_thread_state_fpu
*fpu
;
5544 p
= (char *)ut
+ ut
->cmdsize
;
5546 if(state
+ sizeof(uint32_t) >
5547 (char *)ut
+ ut
->cmdsize
){
5548 Mach_O_error(ofile
, "malformed object (flavor in "
5549 "%s command %u extends past end of command)",
5550 ut
->cmd
== LC_UNIXTHREAD
? "LC_UNIXTHREAD" :
5554 flavor
= *((uint32_t *)state
);
5556 flavor
= SWAP_INT(flavor
);
5557 *((uint32_t *)state
) = flavor
;
5559 state
+= sizeof(uint32_t);
5560 if(state
+ sizeof(uint32_t) >
5561 (char *)ut
+ ut
->cmdsize
){
5562 Mach_O_error(ofile
, "malformed object (count in "
5563 "%s command %u extends past end of command)",
5564 ut
->cmd
== LC_UNIXTHREAD
? "LC_UNIXTHREAD" :
5568 count
= *((uint32_t *)state
);
5570 count
= SWAP_INT(count
);
5571 *((uint32_t *)state
) = count
;
5573 state
+= sizeof(uint32_t);
5575 case SPARC_THREAD_STATE_REGS
:
5576 if(count
!= SPARC_THREAD_STATE_REGS_COUNT
){
5577 Mach_O_error(ofile
, "malformed object (count "
5578 "not SPARC_THREAD_STATE_REGS_COUNT for "
5579 "flavor number %u which is a SPARC_THREAD_"
5580 "STATE_REGS flavor in %s command %u)",
5581 nflavor
, ut
->cmd
== LC_UNIXTHREAD
?
5582 "LC_UNIXTHREAD" : "LC_THREAD", i
);
5585 cpu
= (struct sparc_thread_state_regs
*)state
;
5586 if(state
+ sizeof(struct sparc_thread_state_regs
) >
5587 (char *)ut
+ ut
->cmdsize
){
5588 Mach_O_error(ofile
, "malformed object ("
5589 "SPARC_THREAD_STATE_REGS in %s command %u "
5590 "extends past end of command)", ut
->cmd
==
5591 LC_UNIXTHREAD
? "LC_UNIXTHREAD" :
5596 swap_sparc_thread_state_regs(cpu
, host_byte_sex
);
5597 state
+= sizeof(struct sparc_thread_state_regs
);
5599 case SPARC_THREAD_STATE_FPU
:
5600 if(count
!= SPARC_THREAD_STATE_FPU_COUNT
){
5601 Mach_O_error(ofile
, "malformed object (count "
5602 "not SPARC_THREAD_STATE_FPU_COUNT for "
5603 "flavor number %u which is a SPARC_THREAD_"
5604 "STATE_FPU flavor in %s command %u)",
5605 nflavor
, ut
->cmd
== LC_UNIXTHREAD
?
5606 "LC_UNIXTHREAD" : "LC_THREAD", i
);
5609 fpu
= (struct sparc_thread_state_fpu
*)state
;
5610 if(state
+ sizeof(struct sparc_thread_state_fpu
) >
5611 (char *)ut
+ ut
->cmdsize
){
5612 Mach_O_error(ofile
, "malformed object ("
5613 "SPARC_THREAD_STATE_FPU in %s command %u "
5614 "extends past end of command)", ut
->cmd
==
5615 LC_UNIXTHREAD
? "LC_UNIXTHREAD" :
5620 swap_sparc_thread_state_fpu(fpu
, host_byte_sex
);
5621 state
+= sizeof(struct sparc_thread_state_fpu
);
5625 Mach_O_error(ofile
, "malformed object (unknown "
5626 "flavor for flavor number %u in %s command"
5627 " %u can't byte swap it)", nflavor
,
5628 ut
->cmd
== LC_UNIXTHREAD
? "LC_UNIXTHREAD" :
5632 state
+= count
* sizeof(uint32_t);
5639 if(cputype
== CPU_TYPE_ARM
){
5640 arm_thread_state_t
*cpu
;
5643 p
= (char *)ut
+ ut
->cmdsize
;
5645 if(state
+ sizeof(uint32_t) >
5646 (char *)ut
+ ut
->cmdsize
){
5647 Mach_O_error(ofile
, "malformed object (flavor in "
5648 "%s command %u extends past end of command)",
5649 ut
->cmd
== LC_UNIXTHREAD
? "LC_UNIXTHREAD" :
5653 flavor
= *((uint32_t *)state
);
5655 flavor
= SWAP_INT(flavor
);
5656 *((uint32_t *)state
) = flavor
;
5658 state
+= sizeof(uint32_t);
5659 if(state
+ sizeof(uint32_t) >
5660 (char *)ut
+ ut
->cmdsize
){
5661 Mach_O_error(ofile
, "malformed object (count in "
5662 "%s command %u extends past end of command)",
5663 ut
->cmd
== LC_UNIXTHREAD
? "LC_UNIXTHREAD" :
5667 count
= *((uint32_t *)state
);
5669 count
= SWAP_INT(count
);
5670 *((uint32_t *)state
) = count
;
5672 state
+= sizeof(uint32_t);
5674 case ARM_THREAD_STATE
:
5675 if(count
!= ARM_THREAD_STATE_COUNT
){
5676 Mach_O_error(ofile
, "malformed object (count "
5677 "not ARM_THREAD_STATE_COUNT for "
5678 "flavor number %u which is a ARM_THREAD_"
5679 "STATE flavor in %s command %u)",
5680 nflavor
, ut
->cmd
== LC_UNIXTHREAD
?
5681 "LC_UNIXTHREAD" : "LC_THREAD", i
);
5684 cpu
= (arm_thread_state_t
*)state
;
5685 if(state
+ sizeof(arm_thread_state_t
) >
5686 (char *)ut
+ ut
->cmdsize
){
5687 Mach_O_error(ofile
, "malformed object ("
5688 "ARM_THREAD_STATE in %s command %u "
5689 "extends past end of command)", ut
->cmd
==
5690 LC_UNIXTHREAD
? "LC_UNIXTHREAD" :
5695 swap_arm_thread_state_t(cpu
, host_byte_sex
);
5696 state
+= sizeof(arm_thread_state_t
);
5700 Mach_O_error(ofile
, "malformed object (unknown "
5701 "flavor for flavor number %u in %s command"
5702 " %u can't byte swap it)", nflavor
,
5703 ut
->cmd
== LC_UNIXTHREAD
? "LC_UNIXTHREAD" :
5707 state
+= count
* sizeof(uint32_t);
5715 Mach_O_error(ofile
, "malformed object (unknown cputype and "
5716 "cpusubtype of object and can't byte swap and check %s "
5717 "command %u)", ut
->cmd
== LC_UNIXTHREAD
?
5718 "LC_UNIXTHREAD" : "LC_THREAD", i
);
5723 if(l
.cmdsize
< sizeof(struct entry_point_command
)){
5724 Mach_O_error(ofile
, "malformed object (LC_MAIN cmdsize "
5725 "too small) in command %u", i
);
5728 ep
= (struct entry_point_command
*)lc
;
5730 swap_entry_point_command(ep
, host_byte_sex
);
5732 * If we really wanted we could check that the entryoff field
5733 * really is an offset into the __TEXT segment. But since it
5734 * is not used here, we won't needlessly check it.
5737 case LC_SOURCE_VERSION
:
5738 if(l
.cmdsize
< sizeof(struct source_version_command
)){
5739 Mach_O_error(ofile
, "malformed object (LC_SOURCE_VERSION "
5740 "cmdsize too small) in command %u", i
);
5743 sv
= (struct source_version_command
*)lc
;
5745 swap_source_version_command(sv
, host_byte_sex
);
5747 if(l
.cmdsize
< sizeof(struct ident_command
)){
5748 Mach_O_error(ofile
, "malformed object (LC_IDENT cmdsize "
5749 "too small) in command %u", i
);
5752 id
= (struct ident_command
*)lc
;
5754 swap_ident_command(id
, host_byte_sex
);
5756 * Note the cmdsize field if the LC_IDENT command was checked
5757 * as part of checking all load commands cmdsize field before
5758 * the switch statement on the cmd field of the load command.
5762 if(l
.cmdsize
< sizeof(struct rpath_command
)){
5763 Mach_O_error(ofile
, "malformed object (LC_RPATH: cmdsize "
5764 "too small) in command %u", i
);
5767 rpath
= (struct rpath_command
*)lc
;
5769 swap_rpath_command(rpath
, host_byte_sex
);
5770 if(rpath
->cmdsize
< sizeof(struct rpath_command
)){
5771 Mach_O_error(ofile
, "malformed object (LC_RPATH command "
5772 "%u has too small cmdsize field)", i
);
5775 if(rpath
->path
.offset
>= rpath
->cmdsize
){
5776 Mach_O_error(ofile
, "truncated or malformed object (path."
5777 "offset field of LC_RPATH command %u extends past the "
5778 "end of the file)", i
);
5785 Mach_O_error(ofile
, "malformed object (unknown load command "
5788 #endif /* !defined(OFI) */
5791 lc
= (struct load_command
*)((char *)lc
+ l
.cmdsize
);
5792 /* check that next load command does not extends past the end */
5793 if((char *)lc
> (char *)load_commands
+ sizeofcmds
){
5794 Mach_O_error(ofile
, "truncated or malformed object (load "
5795 "command %u extends past the end of the file)",
5802 Mach_O_error(ofile
, "truncated or malformed object (contains "
5803 "LC_DYSYMTAB load command without a LC_SYMTAB load command)");
5809 if(dyst
->nlocalsym
!= 0 &&
5810 dyst
->ilocalsym
> st
->nsyms
){
5811 Mach_O_error(ofile
, "truncated or malformed object "
5812 "(ilocalsym in LC_DYSYMTAB load command extends past "
5813 "the end of the symbol table)");
5816 big_size
= dyst
->ilocalsym
;
5817 big_size
+= dyst
->nlocalsym
;
5818 if(dyst
->nlocalsym
!= 0 && big_size
> st
->nsyms
){
5819 Mach_O_error(ofile
, "truncated or malformed object "
5820 "(ilocalsym plus nlocalsym in LC_DYSYMTAB load command "
5821 "extends past the end of the symbol table)");
5825 if(dyst
->nextdefsym
!= 0 &&
5826 dyst
->iextdefsym
> st
->nsyms
){
5827 Mach_O_error(ofile
, "truncated or malformed object "
5828 "(iextdefsym in LC_DYSYMTAB load command extends past "
5829 "the end of the symbol table)");
5832 big_size
= dyst
->iextdefsym
;
5833 big_size
+= dyst
->nextdefsym
;
5834 if(dyst
->nextdefsym
!= 0 && big_size
> st
->nsyms
){
5835 Mach_O_error(ofile
, "truncated or malformed object "
5836 "(iextdefsym plus nextdefsym in LC_DYSYMTAB load "
5837 "command extends past the end of the symbol table)");
5841 if(dyst
->nundefsym
!= 0 &&
5842 dyst
->iundefsym
> st
->nsyms
){
5843 Mach_O_error(ofile
, "truncated or malformed object "
5844 "(iundefsym in LC_DYSYMTAB load command extends past "
5845 "the end of the symbol table)");
5848 big_size
= dyst
->iundefsym
;
5849 big_size
+= dyst
->nundefsym
;
5850 if(dyst
->nundefsym
!= 0 && big_size
> st
->nsyms
){
5851 Mach_O_error(ofile
, "truncated or malformed object "
5852 "(iundefsym plus nundefsym in LC_DYSYMTAB load command "
5853 "extends past the end of the symbol table)");
5857 if(rc
->init_module
> dyst
->nmodtab
){
5858 Mach_O_error(ofile
, "malformed object (init_module in "
5859 "LC_ROUTINES load command extends past the "
5860 "end of the module table)");
5865 if(rc64
->init_module
> dyst
->nmodtab
){
5866 Mach_O_error(ofile
, "malformed object (init_module in "
5867 "LC_ROUTINES_64 load command extends past the "
5868 "end of the module table)");
5873 if(hints
->nhints
!= dyst
->nundefsym
){
5874 Mach_O_error(ofile
, "malformed object (nhints in "
5875 "LC_TWOLEVEL_HINTS load command not the same as "
5876 "nundefsym in LC_DYSYMTAB load command)");
5882 /* check for an inconsistent size of the load commands */
5883 if((char *)load_commands
+ sizeofcmds
!= (char *)lc
){
5884 Mach_O_error(ofile
, "malformed object (inconsistent sizeofcmds "
5885 "field in mach header)");
5890 * Mark this ofile so we know its headers have been swapped. We do this
5891 * in case we don't process it the first time so we can swap them back
5892 * in case we loop back to it in a fat file to process it later.
5895 ofile
->headers_swapped
= TRUE
;
5897 /* looks good return ok */
5898 free_elements(&elements
);
5902 free_elements(&elements
);
5908 * swap_back_Mach_O() is called after the ofile has been processed to swap back
5909 * the mach header and load commands if check_Mach_O() above swapped them.
5914 struct ofile
*ofile
)
5916 if(ofile
->headers_swapped
== TRUE
){
5917 ofile
->headers_swapped
= FALSE
;
5918 if(ofile
->mh
!= NULL
)
5919 swap_object_headers(ofile
->mh
, ofile
->load_commands
);
5920 else if(ofile
->mh64
!= NULL
)
5921 swap_object_headers(ofile
->mh64
, ofile
->load_commands
);
5927 * check_overlaping_element() checks that the element in the ofile described by
5928 * offset, size and name does not overlap in list of elements in head. If it
5929 * does CHECK_BAD is returned and an error message is generated. If it doesn't
5930 * then an element is added in the ordered list and CHECK_GOOD is returned
5934 check_overlaping_element(
5935 struct ofile
*ofile
,
5936 struct element
*head
,
5941 struct element
*e
, *p
, *n
;
5946 if(head
->next
== NULL
){
5947 n
= allocate(sizeof(struct element
));
5958 while(e
->next
!= NULL
){
5961 if((offset
>= e
->offset
&&
5962 offset
< e
->offset
+ e
->size
) ||
5963 (offset
+ size
> e
->offset
&&
5964 offset
+ size
< e
->offset
+ e
->size
) ||
5965 (offset
<= e
->offset
&&
5966 offset
+ size
>= e
->offset
+ e
->size
)){
5967 Mach_O_error(ofile
, "malformed object (%s at offset %u with a "
5968 "size of %u, overlaps %s at offset %u with a size of %u)",
5969 name
, offset
, size
, e
->name
, e
->offset
, e
->size
);
5972 if(e
->next
!= NULL
&& offset
+ size
<= e
->next
->offset
){
5973 n
= allocate(sizeof(struct element
));
5982 n
= allocate(sizeof(struct element
));
5992 * free_elements() frees the list of elements on the list head.
5997 struct element
*head
)
5999 struct element
*e
, *e_next
;
6008 #endif /* !defined(OTOOL) */
6011 * check_dylib_module() checks the object file's dylib_module as referenced
6012 * by the dylib_module field in the ofile for correctness.
6017 struct ofile
*ofile
,
6018 struct symtab_command
*st
,
6019 struct dysymtab_command
*dyst
,
6021 uint32_t module_index
)
6025 #else /* !defined OTOOL */
6027 enum byte_sex host_byte_sex
;
6029 struct dylib_module m
;
6030 struct dylib_module_64 m64
;
6031 uint32_t module_name
, nextdefsym
, iextdefsym
, nlocalsym
, ilocalsym
, nrefsym
;
6032 uint32_t irefsym
, nextrel
, iextrel
;
6034 host_byte_sex
= get_host_byte_sex();
6035 swapped
= (enum bool)(host_byte_sex
!= ofile
->object_byte_sex
);
6036 if(ofile
->mh
!= NULL
){
6037 m
= *ofile
->dylib_module
;
6039 swap_dylib_module(&m
, 1, host_byte_sex
);
6040 module_name
= m
.module_name
;
6041 nextdefsym
= m
.nextdefsym
;
6042 iextdefsym
= m
.iextdefsym
;
6043 nlocalsym
= m
.nlocalsym
;
6044 ilocalsym
= m
.ilocalsym
;
6045 nrefsym
= m
.nrefsym
;
6046 irefsym
= m
.irefsym
;
6047 nextrel
= m
.nextrel
;
6048 iextrel
= m
.iextrel
;
6051 m64
= *ofile
->dylib_module64
;
6053 swap_dylib_module_64(&m64
, 1, host_byte_sex
);
6054 module_name
= m64
.module_name
;
6055 nextdefsym
= m64
.nextdefsym
;
6056 iextdefsym
= m64
.iextdefsym
;
6057 nlocalsym
= m64
.nlocalsym
;
6058 ilocalsym
= m64
.ilocalsym
;
6059 nrefsym
= m64
.nrefsym
;
6060 irefsym
= m64
.irefsym
;
6061 nextrel
= m64
.nextrel
;
6062 iextrel
= m64
.iextrel
;
6065 if(module_name
> st
->strsize
){
6066 Mach_O_error(ofile
, "truncated or malformed object (module_name "
6067 "of module table entry %u past the end of the string table)",
6071 for(i
= module_name
; i
< st
->strsize
&& strings
[i
] != '\0'; i
++)
6073 if(i
>= st
->strsize
){
6074 Mach_O_error(ofile
, "truncated or malformed object (module_name "
6075 "of module table entry %u extends past the end of the string "
6076 "table)", module_index
);
6080 if(nextdefsym
!= 0){
6081 if(iextdefsym
> st
->nsyms
){
6082 Mach_O_error(ofile
, "truncated or malformed object (iextdefsym "
6083 "field of module table entry %u past the end of the "
6084 "symbol table", module_index
);
6087 if(iextdefsym
+ nextdefsym
> st
->nsyms
){
6088 Mach_O_error(ofile
, "truncated or malformed object (iextdefsym "
6089 "field of module table entry %u plus nextdefsym field "
6090 "extends past the end of the symbol table", module_index
);
6095 if(ilocalsym
> st
->nsyms
){
6096 Mach_O_error(ofile
, "truncated or malformed object (ilocalsym "
6097 "field of module table entry %u past the end of the "
6098 "symbol table", module_index
);
6101 if(ilocalsym
+ nlocalsym
> st
->nsyms
){
6102 Mach_O_error(ofile
, "truncated or malformed object (ilocalsym "
6103 "field of module table entry %u plus nlocalsym field "
6104 "extends past the end of the symbol table", module_index
);
6109 if(irefsym
> dyst
->nextrefsyms
){
6110 Mach_O_error(ofile
, "truncated or malformed object (irefsym "
6111 "field of module table entry %u past the end of the "
6112 "reference table", module_index
);
6115 if(irefsym
+ nrefsym
> dyst
->nextrefsyms
){
6116 Mach_O_error(ofile
, "truncated or malformed object (irefsym "
6117 "field of module table entry %u plus nrefsym field "
6118 "extends past the end of the reference table",module_index
);
6123 if(iextrel
> dyst
->extreloff
){
6124 Mach_O_error(ofile
, "truncated or malformed object (iextrel "
6125 "field of module table entry %u past the end of the "
6126 "external relocation enrties", module_index
);
6129 if(iextrel
+ nextrel
> dyst
->extreloff
){
6130 Mach_O_error(ofile
, "truncated or malformed object (iextrel "
6131 "field of module table entry %u plus nextrel field "
6132 "extends past the end of the external relocation enrties",
6144 const struct ar_hdr
*ar_hdr
)
6148 i
= sizeof(ar_hdr
->ar_name
) - 1;
6149 if(ar_hdr
->ar_name
[i
] == ' '){
6151 if(ar_hdr
->ar_name
[i
] != ' ')
6158 #endif /* !defined(RLD) */