2 * Copyright © 2009 Apple Inc. All rights reserved.
4 * @APPLE_LICENSE_HEADER_START@
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions are met:
9 * 1. Redistributions of source code must retain the above copyright notice,
10 * this list of conditions and the following disclaimer.
11 * 2. Redistributions in binary form must reproduce the above copyright notice,
12 * this list of conditions and the following disclaimer in the documentation
13 * and/or other materials provided with the distribution.
14 * 3. Neither the name of Apple Inc. ("Apple") nor the names of its
15 * contributors may be used to endorse or promote products derived from this
16 * software without specific prior written permission.
18 * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY
19 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
20 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
21 * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY
22 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
23 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
24 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
25 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
26 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
27 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
29 * @APPLE_LICENSE_HEADER_END@
31 #define __darwin_i386_exception_state i386_exception_state
32 #define __darwin_i386_float_state i386_float_state
33 #define __darwin_i386_thread_state i386_thread_state
40 #include <mach/mach.h>
41 #include "stuff/openstep_mach.h"
49 #include <sys/types.h>
51 #include <mach-o/fat.h>
52 #include <mach-o/loader.h>
53 #import <mach/m68k/thread_status.h>
54 #import <mach/ppc/thread_status.h>
55 #undef MACHINE_THREAD_STATE /* need to undef these to avoid warnings */
56 #undef MACHINE_THREAD_STATE_COUNT
57 #undef THREAD_STATE_NONE
58 #undef VALID_THREAD_STATE_FLAVOR
59 #import <mach/m88k/thread_status.h>
60 #import <mach/i860/thread_status.h>
61 #import <mach/i386/thread_status.h>
62 #import <mach/sparc/thread_status.h>
63 #import <mach/arm/thread_status.h>
64 #include <mach-o/nlist.h>
65 #include <mach-o/reloc.h>
66 #include "stuff/bool.h"
68 #include <mach-o/dyld.h>
70 #include "stuff/lto.h"
72 #include "stuff/bytesex.h"
73 #include "stuff/arch.h"
74 #include "stuff/rnd.h"
75 #include "stuff/errors.h"
76 #include "stuff/allocate.h"
77 #include "stuff/ofile.h"
78 #include "stuff/print.h"
81 #undef ALIGNMENT_CHECKS
83 #include "ofile_print.h"
84 static enum bool otool_first_ofile_map
= TRUE
;
85 #else /* !define(OTOOL) */
87 #if (!defined(m68k) && !defined(__i386__) && !defined(__x86_64__) && !defined(__ppc__) && !defined(__arm__))
88 #define ALIGNMENT_CHECKS_ARCHIVE_64_BIT
89 static enum bool archive_64_bit_align_warning
= FALSE
;
90 #endif /* (!defined(m68k) && !defined(__i386__) && !defined(__x86_64__) && !defined(__ppc__) && !defined(__arm__)) */
95 /* The maximum section alignment allowed to be specified, as a power of two */
96 #define MAXSECTALIGN 15 /* 2**15 or 0x8000 */
108 struct element
*next
;
110 #endif /* !defined(OTOOL) */
112 static enum bool ofile_specific_arch(
115 static enum check_type
check_fat(
116 struct ofile
*ofile
);
117 static enum check_type
check_fat_object_in_archive(
118 struct ofile
*ofile
);
119 static enum check_type
check_archive(
121 enum bool archives_with_fat_objects
);
122 static enum check_type
check_extend_format_1(
124 struct ar_hdr
*ar_hdr
,
126 uint32_t *member_name_size
);
127 static enum check_type
check_archive_toc(
128 struct ofile
*ofile
);
129 static enum check_type
check_Mach_O(
130 struct ofile
*ofile
);
131 static void swap_back_Mach_O(
132 struct ofile
*ofile
);
134 static enum check_type
check_overlaping_element(
136 struct element
*head
,
140 static void free_elements(
141 struct element
*head
);
142 #endif /* !defined(OTOOL) */
143 static enum check_type
check_dylib_module(
145 struct symtab_command
*st
,
146 struct dysymtab_command
*dyst
,
148 uint32_t module_index
);
151 #if defined(ALIGNMENT_CHECKS) || defined(ALIGNMENT_CHECKS_ARCHIVE_64_BIT)
154 temporary_archive_member_warning(
156 const char *format
, ...)
160 va_start(ap
, format
);
161 if(ofile
->file_type
== OFILE_FAT
){
162 print("%s: for architecture %s archive member: %s(%.*s) ",
163 progname
, ofile
->arch_flag
.name
, ofile
->file_name
,
164 (int)ofile
->member_name_size
, ofile
->member_name
);
167 print("%s: archive member: %s(%.*s) ", progname
, ofile
->file_name
,
168 (int)ofile
->member_name_size
, ofile
->member_name
);
174 #endif /* defined(ALIGNMENT_CHECKS) */
175 #endif /* !defined(OTOOL) */
179 * ofile_process() processes the specified file name can calls the routine
180 * processor on the ofiles in it. arch_flags is an array of architectures
181 * containing narch_flags which are the only architectures to process if
182 * narch_flags is non-zero. If all_archs is TRUE then all architectures of
183 * the specified file are processed. The specified file name can be of the
184 * form "archive(member)" which is taken to mean that member in that archive
185 * (or that module of a dynamic library if dylib_flat is not FALSE).
186 * For each ofile that is to be processed the routine processor is called with
187 * the corresponding ofile struct, the arch_name pass to it is either NULL or
188 * an architecture name (when it should be printed or show by processor) and
189 * cookie is the same value as passed to ofile_process.
195 struct arch_flag
*arch_flags
,
196 uint32_t narch_flags
,
198 enum bool process_non_objects
,
199 enum bool dylib_flat
,
200 enum bool use_member_syntax
,
201 void (*processor
)(struct ofile
*ofile
, char *arch_name
, void *cookie
),
204 char *member_name
, *p
, *arch_name
;
207 enum bool flag
, hostflag
, arch_found
, family
;
208 struct arch_flag host_arch_flag
;
209 const struct arch_flag
*family_arch_flag
;
212 * If use_member_syntax is TRUE look for a name of the form
213 * "archive(member)" which is to mean a member in that archive (the
214 * member name must be at least one character long to be recognized as
218 if(use_member_syntax
== TRUE
){
220 if(len
>= 4 && name
[len
-1] == ')'){
221 p
= strrchr(name
, '(');
222 if(p
!= NULL
&& p
!= name
){
231 otool_first_ofile_map
= TRUE
;
233 if(ofile_map(name
, NULL
, NULL
, &ofile
, FALSE
) == FALSE
)
236 otool_first_ofile_map
= FALSE
;
239 if(ofile
.file_type
== OFILE_FAT
){
241 * This is a fat file so see if a list of architecture is
242 * specified and process only those.
244 if(all_archs
== FALSE
&& narch_flags
!= 0){
245 for(i
= 0; i
< narch_flags
; i
++){
246 if(ofile_first_arch(&ofile
) == FALSE
){
253 get_arch_family_from_cputype(arch_flags
[i
].cputype
);
254 if(family_arch_flag
!= NULL
)
256 ((family_arch_flag
->cpusubtype
& ~CPU_SUBTYPE_MASK
) ==
257 (arch_flags
[i
].cpusubtype
& ~CPU_SUBTYPE_MASK
));
259 arch_name
= ofile
.arch_flag
.name
;
263 if(ofile
.arch_flag
.cputype
==
264 arch_flags
[i
].cputype
&&
265 ((ofile
.arch_flag
.cpusubtype
& ~CPU_SUBTYPE_MASK
) ==
266 (arch_flags
[i
].cpusubtype
& ~CPU_SUBTYPE_MASK
) ||
269 if(ofile
.arch_type
== OFILE_ARCHIVE
){
270 if(member_name
!= NULL
){
271 if(ofile_specific_member(member_name
,
273 processor(&ofile
, arch_name
, cookie
);
274 if(ofile
.headers_swapped
== TRUE
)
275 swap_back_Mach_O(&ofile
);
279 /* loop through archive */
281 printf("Archive : %s", ofile
.file_name
);
282 if(arch_name
!= NULL
)
283 printf(" (architecture %s)",
287 if(ofile_first_member(&ofile
) == TRUE
){
290 if(process_non_objects
== TRUE
||
293 processor(&ofile
, arch_name
,
295 if(ofile
.headers_swapped
==TRUE
)
296 swap_back_Mach_O(&ofile
);
299 }while(ofile_next_member(&ofile
) ==
302 error("for architecture: %s "
303 "archive: %s contains no "
304 "members that are object "
305 "files", ofile
.arch_flag
.name
,
310 error("for architecture: %s archive: "
311 "%s contains no members",
312 ofile
.arch_flag
.name
,
317 else if(process_non_objects
== TRUE
||
318 ofile
.arch_type
== OFILE_Mach_O
){
319 if(ofile
.arch_type
== OFILE_Mach_O
&&
320 (ofile
.mh_filetype
== MH_DYLIB
||
321 ofile
.mh_filetype
== MH_DYLIB_STUB
)){
322 if(dylib_flat
== TRUE
){
323 processor(&ofile
, arch_name
, cookie
);
324 if(ofile
.headers_swapped
== TRUE
)
325 swap_back_Mach_O(&ofile
);
328 if(member_name
!= NULL
){
329 if(ofile_specific_module(
330 member_name
, &ofile
) == TRUE
){
331 processor(&ofile
, arch_name
,
333 if(ofile
.headers_swapped
==TRUE
)
334 swap_back_Mach_O(&ofile
);
338 /*loop through the dynamic library*/
339 if(ofile_first_module(&ofile
)){
341 processor(&ofile
, arch_name
,
343 }while(ofile_next_module(
347 processor(&ofile
, arch_name
,
352 if(ofile
.headers_swapped
== TRUE
)
353 swap_back_Mach_O(&ofile
);
356 if(member_name
!= NULL
)
357 error("for architecture: %s file: %s "
358 "is not an archive and thus does "
359 "not contain member: %s",
360 ofile
.arch_flag
.name
,
364 processor(&ofile
, arch_name
, cookie
);
365 if(ofile
.headers_swapped
== TRUE
)
366 swap_back_Mach_O(&ofile
);
370 else if(ofile
.arch_type
== OFILE_UNKNOWN
){
371 error("for architecture: %s file: %s is "
372 "not an object file",
373 ofile
.arch_flag
.name
,ofile
.file_name
);
375 if(ofile
.headers_swapped
== TRUE
)
376 swap_back_Mach_O(&ofile
);
380 if(ofile
.headers_swapped
== TRUE
)
381 swap_back_Mach_O(&ofile
);
383 }while(ofile_next_arch(&ofile
) == TRUE
);
384 if(arch_found
== FALSE
)
385 error("file: %s does not contain architecture: %s",
386 ofile
.file_name
, arch_flags
[i
].name
);
393 * This is a fat file and no architectures has been specified
394 * so if it contains the host architecture process only that
395 * architecture but if not process all architectures
398 if(all_archs
== FALSE
){
399 (void)get_arch_from_host(&host_arch_flag
, NULL
);
402 * If runing as a 64-bit binary and on an Intel x86 host
405 if(host_arch_flag
.cputype
== CPU_TYPE_I386
)
407 *get_arch_family_from_cputype(CPU_TYPE_X86_64
);
408 #endif /* __LP64__ */
413 get_arch_family_from_cputype(host_arch_flag
.cputype
);
414 if(family_arch_flag
!= NULL
)
416 ((family_arch_flag
->cpusubtype
& ~CPU_SUBTYPE_MASK
) ==
417 (host_arch_flag
.cpusubtype
& ~CPU_SUBTYPE_MASK
));
420 if(ofile_map(name
, NULL
, NULL
, &ofile
, FALSE
) == FALSE
)
422 if(ofile_first_arch(&ofile
) == FALSE
){
427 if(ofile
.arch_flag
.cputype
==
428 host_arch_flag
.cputype
&&
429 ((ofile
.arch_flag
.cpusubtype
& ~CPU_SUBTYPE_MASK
) ==
430 (host_arch_flag
.cpusubtype
& ~CPU_SUBTYPE_MASK
) ||
433 if(ofile
.arch_type
== OFILE_ARCHIVE
){
434 if(member_name
!= NULL
){
435 if(ofile_specific_member(member_name
,
437 processor(&ofile
, NULL
, cookie
);
438 if(ofile
.headers_swapped
== TRUE
)
439 swap_back_Mach_O(&ofile
);
443 /* loop through archive */
445 printf("Archive : %s\n", ofile
.file_name
);
447 if(ofile_first_member(&ofile
) == TRUE
){
450 if(process_non_objects
== TRUE
||
451 ofile
.member_type
== OFILE_Mach_O
){
452 processor(&ofile
, NULL
, cookie
);
453 if(ofile
.headers_swapped
== TRUE
)
454 swap_back_Mach_O(&ofile
);
457 }while(ofile_next_member(&ofile
) ==
460 error("archive: %s contains no "
461 "members that are object "
462 "files", ofile
.file_name
);
466 error("archive: %s contains no "
467 "members", ofile
.file_name
);
471 else if(process_non_objects
== TRUE
||
472 ofile
.arch_type
== OFILE_Mach_O
){
473 if(ofile
.arch_type
== OFILE_Mach_O
&&
474 (ofile
.mh_filetype
== MH_DYLIB
||
475 ofile
.mh_filetype
== MH_DYLIB_STUB
)){
476 if(dylib_flat
== TRUE
){
477 processor(&ofile
, NULL
, cookie
);
480 if(member_name
!= NULL
){
481 if(ofile_specific_module(member_name
,
483 processor(&ofile
, NULL
, cookie
);
486 /* loop through the dynamic library */
487 if(ofile_first_module(&ofile
) == TRUE
){
489 processor(&ofile
, NULL
, cookie
);
490 }while(ofile_next_module(&ofile
));
493 processor(&ofile
, NULL
, cookie
);
497 if(ofile
.headers_swapped
== TRUE
)
498 swap_back_Mach_O(&ofile
);
501 if(member_name
!= NULL
)
502 error("for architecture: %s file: %s is "
503 "not an archive and thus does not "
504 "contain member: %s",
505 ofile
.arch_flag
.name
, ofile
.file_name
,
508 processor(&ofile
, NULL
, cookie
);
509 if(ofile
.headers_swapped
== TRUE
)
510 swap_back_Mach_O(&ofile
);
514 else if(ofile
.arch_type
== OFILE_UNKNOWN
){
515 error("file: %s is not an object file",
520 if(ofile
.headers_swapped
== TRUE
)
521 swap_back_Mach_O(&ofile
);
523 }while(hostflag
== FALSE
&& ofile_next_arch(&ofile
) == TRUE
);
524 if(hostflag
== TRUE
){
531 * Either all architectures have been specified or none have
532 * been specified and it does not contain the host architecture
533 * so do all the architectures in the fat file
536 if(ofile_map(name
, NULL
, NULL
, &ofile
, FALSE
) == FALSE
)
538 if(ofile_first_arch(&ofile
) == FALSE
){
543 if(ofile
.arch_type
== OFILE_ARCHIVE
){
544 if(member_name
!= NULL
){
545 if(ofile_specific_member(member_name
, &ofile
) == TRUE
)
546 processor(&ofile
, ofile
.arch_flag
.name
, cookie
);
549 /* loop through archive */
551 printf("Archive : %s (architecture %s)\n",
552 ofile
.file_name
, ofile
.arch_flag
.name
);
554 if(ofile_first_member(&ofile
) == TRUE
){
557 if(process_non_objects
== TRUE
||
558 ofile
.member_type
== OFILE_Mach_O
){
559 processor(&ofile
, ofile
.arch_flag
.name
,
563 }while(ofile_next_member(&ofile
) == TRUE
);
565 error("for architecture: %s archive: %s "
566 "contains no members that are object "
567 "files", ofile
.arch_flag
.name
,
572 error("for architecture: %s archive: %s "
573 "contains no members",
574 ofile
.arch_flag
.name
, ofile
.file_name
);
578 else if(process_non_objects
== TRUE
||
579 ofile
.arch_type
== OFILE_Mach_O
){
580 if(ofile
.arch_type
== OFILE_Mach_O
&&
581 (ofile
.mh_filetype
== MH_DYLIB
||
582 ofile
.mh_filetype
== MH_DYLIB_STUB
)){
583 if(dylib_flat
== TRUE
){
584 processor(&ofile
, ofile
.arch_flag
.name
, cookie
);
587 if(member_name
!= NULL
){
588 if(ofile_specific_module(member_name
, &ofile
)
590 processor(&ofile
, ofile
.arch_flag
.name
,
594 /* loop through the dynamic library */
595 if(ofile_first_module(&ofile
) == TRUE
){
597 processor(&ofile
, ofile
.arch_flag
.name
,
599 }while(ofile_next_module(&ofile
) == TRUE
);
602 processor(&ofile
, ofile
.arch_flag
.name
,
609 if(member_name
!= NULL
)
610 error("for architecture: %s file: %s is not an "
611 "archive and thus does not contain member: "
612 "%s", ofile
.arch_flag
.name
, ofile
.file_name
,
615 processor(&ofile
, ofile
.arch_flag
.name
, cookie
);
618 else if(ofile
.arch_type
== OFILE_UNKNOWN
){
619 error("for architecture: %s file: %s is not an "
620 "object file", ofile
.arch_flag
.name
,
623 }while(ofile_next_arch(&ofile
) == TRUE
);
625 else if(ofile
.file_type
== OFILE_ARCHIVE
){
626 if(narch_flags
!= 0){
628 for(i
= 0; i
< narch_flags
; i
++){
630 if(narch_flags
== 1){
632 get_arch_family_from_cputype(arch_flags
[0].cputype
);
633 if(family_arch_flag
!= NULL
)
635 ((family_arch_flag
->cpusubtype
&
636 ~CPU_SUBTYPE_MASK
) ==
637 (arch_flags
[0].cpusubtype
&
640 if(ofile
.archive_cputype
== arch_flags
[i
].cputype
&&
641 ((ofile
.archive_cpusubtype
& ~CPU_SUBTYPE_MASK
) ==
642 (arch_flags
[i
].cpusubtype
& ~CPU_SUBTYPE_MASK
) ||
647 error("file: %s does not contain architecture: %s",
648 ofile
.file_name
, arch_flags
[i
].name
);
651 if(arch_found
== FALSE
){
656 if(member_name
!= NULL
){
657 if(ofile_specific_member(member_name
, &ofile
) == TRUE
)
658 processor(&ofile
, NULL
, cookie
);
661 /* loop through archive */
663 printf("Archive : %s\n", ofile
.file_name
);
665 if(ofile_first_member(&ofile
) == TRUE
){
668 if(process_non_objects
== TRUE
||
669 ofile
.member_type
== OFILE_Mach_O
){
670 processor(&ofile
, NULL
, cookie
);
673 }while(ofile_next_member(&ofile
) == TRUE
);
675 error("archive: %s contains no members that are "
676 "object files", ofile
.file_name
);
680 error("archive: %s contains no members",
685 else if(ofile
.file_type
== OFILE_Mach_O
){
686 if(narch_flags
!= 0){
688 for(i
= 0; i
< narch_flags
; i
++){
690 if(narch_flags
== 1){
692 get_arch_family_from_cputype(arch_flags
[0].cputype
);
693 if(family_arch_flag
!= NULL
)
695 ((family_arch_flag
->cpusubtype
&
696 ~CPU_SUBTYPE_MASK
) ==
697 (arch_flags
[0].cpusubtype
&
701 if(ofile
.mh
!= NULL
){
702 if(ofile
.mh
->magic
== MH_MAGIC
&&
703 ofile
.mh
->cputype
== arch_flags
[i
].cputype
&&
704 ((ofile
.mh
->cpusubtype
& ~CPU_SUBTYPE_MASK
) ==
705 (arch_flags
[i
].cpusubtype
& ~CPU_SUBTYPE_MASK
) ||
709 if(ofile
.mh
->magic
== SWAP_INT(MH_MAGIC
) &&
710 (cpu_type_t
)SWAP_INT(ofile
.mh
->cputype
) ==
711 arch_flags
[i
].cputype
&&
712 ((cpu_subtype_t
)SWAP_INT(ofile
.mh
->cpusubtype
&
713 ~CPU_SUBTYPE_MASK
) ==
714 (arch_flags
[i
].cpusubtype
&
715 ~CPU_SUBTYPE_MASK
) ||
720 else if(ofile
.mh64
!= NULL
){
721 if(ofile
.mh64
->magic
== MH_MAGIC_64
&&
722 ofile
.mh64
->cputype
== arch_flags
[i
].cputype
&&
723 ((ofile
.mh64
->cpusubtype
& ~CPU_SUBTYPE_MASK
) ==
724 (arch_flags
[i
].cpusubtype
& ~CPU_SUBTYPE_MASK
) ||
728 if(ofile
.mh64
->magic
== SWAP_INT(MH_MAGIC_64
) &&
729 (cpu_type_t
)SWAP_INT(ofile
.mh64
->cputype
) ==
730 arch_flags
[i
].cputype
&&
731 ((cpu_subtype_t
)SWAP_INT((ofile
.mh64
->cpusubtype
&
732 ~CPU_SUBTYPE_MASK
)) ==
733 (arch_flags
[i
].cpusubtype
& ~CPU_SUBTYPE_MASK
) ||
740 if(ofile
.mh_cputype
== arch_flags
[i
].cputype
&&
741 ((ofile
.mh_cpusubtype
& ~CPU_SUBTYPE_MASK
) ==
742 (arch_flags
[i
].cpusubtype
& ~CPU_SUBTYPE_MASK
) ||
747 error("file: %s does not contain architecture: %s",
748 ofile
.file_name
, arch_flags
[i
].name
);
751 if(arch_found
== FALSE
){
756 if(ofile
.mh_filetype
== MH_DYLIB
||
757 ofile
.mh_filetype
== MH_DYLIB_STUB
){
758 if(dylib_flat
== TRUE
){
759 processor(&ofile
, NULL
, cookie
);
762 if(member_name
!= NULL
){
763 if(ofile_specific_module(member_name
, &ofile
) == TRUE
)
764 processor(&ofile
, NULL
, cookie
);
767 /* loop through the dynamic library */
768 if(ofile_first_module(&ofile
) == TRUE
){
770 processor(&ofile
, NULL
, cookie
);
771 }while(ofile_next_module(&ofile
) == TRUE
);
774 processor(&ofile
, NULL
, cookie
);
780 if(member_name
!= NULL
)
781 error("file: %s is not an archive and thus does not contain"
782 " member: %s", ofile
.file_name
, member_name
);
784 processor(&ofile
, NULL
, cookie
);
788 if(process_non_objects
== TRUE
)
789 processor(&ofile
, NULL
, cookie
);
790 else if(member_name
!= NULL
)
791 error("file: %s(%s) is not an object file", name
,
794 error("file: %s is not an object file", name
);
798 #endif /* !defined(OFI) */
801 * ofile_map maps in the object file specified by file_name, arch_flag and
802 * object_name and fills in the ofile struct pointed to by ofile for it.
803 * When arch_flag and object_name are both NULL, the file is just set up into
804 * ofile (if the file can be opened and mapped in, if not this call fails
805 * are error routnes are called). If arch_flag is not NULL and object_file is
806 * NULL, then the file must be a Mach-O file or a fat file with the architecture
807 * specified in the arch_flag, if not this call fails and error routines are
808 * called. When arch_flag and object_name are both not NULL, then the file must
809 * be an archive or a fat file containing archives for the specified architec-
810 * ture and contain an archive member object file with the name object_name,
811 * otherwise this call fails and error routines are called. If arch_flag is
812 * NULL and object_file is not NULL, then the file name must be an archive (not
813 * a fat file containing archives) and contain an archive member object file
814 * with the name object_name, otherwise this call fails and calls error
815 * routines. If this call suceeds then it returns non-zero and the ofile
816 * structure pointed to by ofile is filled in. If this call fails it returns 0
817 * and calls error routines to print error messages and clears the
818 * ofile structure pointed to by ofile.
822 NSObjectFileImageReturnCode
827 const char *file_name
,
828 const struct arch_flag
*arch_flag
, /* can be NULL */
829 const char *object_name
, /* can be NULL */
831 enum bool archives_with_fat_objects
)
834 struct stat stat_buf
;
835 uint32_t size
, magic
;
838 magic
= 0; /* to shut up the compiler warning message */
839 memset(ofile
, '\0', sizeof(struct ofile
));
841 /* Open the file and map it in */
842 if((fd
= open(file_name
, O_RDONLY
)) == -1){
844 return(NSObjectFileImageAccess
);
846 system_error("can't open file: %s", file_name
);
850 if(fstat(fd
, &stat_buf
) == -1){
853 return(NSObjectFileImageAccess
);
855 system_error("can't stat file: %s", file_name
);
859 size
= stat_buf
.st_size
;
863 addr
= mmap(0, size
, PROT_READ
|PROT_WRITE
, MAP_FILE
|MAP_PRIVATE
, fd
,
865 if((intptr_t)addr
== -1){
866 system_error("can't map file: %s", file_name
);
873 if(otool_first_ofile_map
&& Wflag
)
874 printf("Modification time = %ld\n", (long int)stat_buf
.st_mtime
);
877 return(ofile_map_from_memory(addr
, size
, file_name
, stat_buf
.st_mtime
,
878 arch_flag
, object_name
, ofile
, archives_with_fat_objects
));
882 * ofile_map_from_memory() is the guts of ofile_map() but with an interface
883 * to pass the address and size of the file already mapped in.
887 NSObjectFileImageReturnCode
891 ofile_map_from_memory(
894 const char *file_name
,
896 const struct arch_flag
*arch_flag
, /* can be NULL */
897 const char *object_name
, /* can be NULL */
899 enum bool archives_with_fat_objects
)
903 enum byte_sex host_byte_sex
;
904 struct arch_flag host_arch_flag
;
906 const struct arch_flag
*family_arch_flag
;
909 uint32_t small_nfat_arch
;
912 /* fill in the start of the ofile structure */
913 ofile
->file_name
= savestr(file_name
);
914 if(ofile
->file_name
== NULL
)
916 ofile
->file_addr
= addr
;
917 ofile
->file_size
= size
;
918 ofile
->file_mtime
= mtime
;
920 /* Try to figure out what kind of file this is */
922 if(size
>= sizeof(uint32_t)){
923 magic
= *((uint32_t *)addr
);
925 host_byte_sex
= get_host_byte_sex();
927 /* see if this file is a fat file (always in big endian byte sex) */
928 #ifdef __BIG_ENDIAN__
929 if(size
>= sizeof(struct fat_header
) && magic
== FAT_MAGIC
)
930 #endif /* __BIG_ENDIAN__ */
931 #ifdef __LITTLE_ENDIAN__
932 if(size
>= sizeof(struct fat_header
) && SWAP_INT(magic
) == FAT_MAGIC
)
933 #endif /* __LITTLE_ENDIAN__ */
935 ofile
->file_type
= OFILE_FAT
;
936 ofile
->fat_header
= (struct fat_header
*)addr
;
937 #ifdef __LITTLE_ENDIAN__
938 swap_fat_header(ofile
->fat_header
, host_byte_sex
);
939 #endif /* __LITTLE_ENDIAN__ */
941 if(otool_first_ofile_map
&& fflag
)
942 printf("Fat headers\n");
944 big_size
= ofile
->fat_header
->nfat_arch
;
945 big_size
*= sizeof(struct fat_arch
);
946 big_size
+= sizeof(struct fat_header
);
949 error("fat file: %s truncated or malformed (fat_arch structs "
950 "would extend past the end of the file)", file_name
);
951 ofile
->fat_archs
= allocate(size
- sizeof(struct fat_header
));
952 memset(ofile
->fat_archs
, '\0',
953 size
- sizeof(struct fat_header
));
954 memcpy(ofile
->fat_archs
,
955 addr
+ sizeof(struct fat_header
),
956 size
- sizeof(struct fat_header
));
957 small_nfat_arch
= (size
- sizeof(struct fat_header
)) /
958 sizeof(struct fat_arch
);
959 #ifdef __LITTLE_ENDIAN__
960 swap_fat_arch(ofile
->fat_archs
, small_nfat_arch
,
962 #endif /* __LITTLE_ENDIAN__ */
963 if(otool_first_ofile_map
&& fflag
)
964 print_fat_headers(ofile
->fat_header
, ofile
->fat_archs
,
966 free(ofile
->fat_archs
);
969 #else /* !defined(OTOOL) */
973 ofile
->fat_archs
= (struct fat_arch
*)(addr
+
974 sizeof(struct fat_header
));
975 #ifdef __LITTLE_ENDIAN__
976 swap_fat_arch(ofile
->fat_archs
, ofile
->fat_header
->nfat_arch
,
978 #endif /* __LITTLE_ENDIAN__ */
980 if(otool_first_ofile_map
&& fflag
)
981 print_fat_headers(ofile
->fat_header
, ofile
->fat_archs
,
984 if(check_fat(ofile
) == CHECK_BAD
){
987 return(NSObjectFileImageFormat
);
993 * Now that the fat file is mapped fill in the ofile to the level
994 * the caller wants based on the arch_flag and object_name passed.
995 * If the caller did not specify an arch_flag or an object_name
996 * then everything the caller wants is done.
998 if(arch_flag
== NULL
&& object_name
== NULL
)
1000 if(arch_flag
== NULL
){
1001 if(get_arch_from_host(&host_arch_flag
, NULL
) == 0){
1002 error("can't determine the host architecture (specify an "
1003 "arch_flag or fix get_arch_from_host() )");
1006 ofile
->arch_flag
.name
= savestr(host_arch_flag
.name
);
1007 if(ofile
->arch_flag
.name
== NULL
)
1009 ofile
->arch_flag
.cputype
= host_arch_flag
.cputype
;
1010 ofile
->arch_flag
.cpusubtype
= host_arch_flag
.cpusubtype
;
1013 ofile
->arch_flag
.name
= savestr(arch_flag
->name
);
1014 if(ofile
->arch_flag
.name
== NULL
)
1016 ofile
->arch_flag
.cputype
= arch_flag
->cputype
;
1017 ofile
->arch_flag
.cpusubtype
= arch_flag
->cpusubtype
;
1020 ofile
->narch
= UINT_MAX
;
1021 for(i
= 0; i
< ofile
->fat_header
->nfat_arch
; i
++){
1022 if(ofile
->fat_archs
[i
].cputype
==
1023 ofile
->arch_flag
.cputype
&&
1024 (ofile
->fat_archs
[i
].cpusubtype
& ~CPU_SUBTYPE_MASK
) ==
1025 (ofile
->arch_flag
.cpusubtype
& ~CPU_SUBTYPE_MASK
)){
1030 if(ofile
->narch
== UINT_MAX
){
1033 get_arch_family_from_cputype(ofile
->arch_flag
.cputype
);
1034 if(family_arch_flag
!= NULL
)
1035 family
= (enum bool)
1036 ((family_arch_flag
->cpusubtype
& ~CPU_SUBTYPE_MASK
) ==
1037 (ofile
->arch_flag
.cpusubtype
& ~CPU_SUBTYPE_MASK
));
1038 ofile
->narch
= UINT_MAX
;
1039 for(i
= 0; i
< ofile
->fat_header
->nfat_arch
; i
++){
1040 if(ofile
->fat_archs
[i
].cputype
==
1041 ofile
->arch_flag
.cputype
&&
1043 (ofile
->fat_archs
[i
].cpusubtype
& ~CPU_SUBTYPE_MASK
) ==
1044 (ofile
->arch_flag
.cpusubtype
& ~CPU_SUBTYPE_MASK
))){
1045 ofile
->arch_flag
.cpusubtype
=
1046 ofile
->fat_archs
[i
].cpusubtype
;
1052 if(ofile
->narch
== UINT_MAX
){
1055 return(NSObjectFileImageArch
);
1057 error("fat file: %s does not contain architecture %s",
1058 ofile
->file_name
, arch_flag
->name
);
1063 /* Now determine the file type for this specific architecture */
1064 size
= ofile
->fat_archs
[i
].size
;
1065 addr
= addr
+ ofile
->fat_archs
[i
].offset
;
1066 if(size
>= sizeof(struct mach_header
))
1067 memcpy(&magic
, addr
, sizeof(uint32_t));
1068 /* see if this file is a 32-bit Mach-O file */
1069 if(size
>= sizeof(struct mach_header
) &&
1070 (magic
== MH_MAGIC
||
1071 magic
== SWAP_INT(MH_MAGIC
))){
1072 #ifdef ALIGNMENT_CHECKS
1073 if(ofile
->fat_archs
[i
].offset
% 4 != 0){
1074 error("fat file: %s architecture %s malformed for a 32-bit "
1075 "object file (offset is not a multiple of 4)",
1076 ofile
->file_name
, arch_flag
->name
);
1079 return(NSObjectFileImageFormat
);
1084 #endif /* ALIGNMENT_CHECKS */
1085 ofile
->arch_type
= OFILE_Mach_O
;
1086 ofile
->object_addr
= addr
;
1087 ofile
->object_size
= size
;
1088 if(magic
== MH_MAGIC
)
1089 ofile
->object_byte_sex
= host_byte_sex
;
1091 ofile
->object_byte_sex
=
1092 host_byte_sex
== BIG_ENDIAN_BYTE_SEX
?
1093 LITTLE_ENDIAN_BYTE_SEX
: BIG_ENDIAN_BYTE_SEX
;
1094 ofile
->mh
= (struct mach_header
*)addr
;
1095 ofile
->load_commands
= (struct load_command
*)(addr
+
1096 sizeof(struct mach_header
));
1097 if(check_Mach_O(ofile
) == CHECK_BAD
){
1100 return(NSObjectFileImageFormat
);
1105 if(object_name
!= NULL
){
1106 error("fat file: %s architecture %s is not an archive "
1107 "(object_name to ofile_map() can't be specified to "
1108 "be other than NULL)", ofile
->file_name
,
1113 /* see if this file is a 64-bit Mach-O file */
1114 else if(size
>= sizeof(struct mach_header_64
) &&
1115 (magic
== MH_MAGIC_64
||
1116 magic
== SWAP_INT(MH_MAGIC_64
))){
1117 #ifdef ALIGNMENT_CHECKS
1118 if(ofile
->fat_archs
[i
].offset
% 8 != 0){
1119 error("fat file: %s architecture %s malformed for a 64-bit "
1120 "object file (offset is not a multiple of 8)",
1121 ofile
->file_name
, arch_flag
->name
);
1124 return(NSObjectFileImageFormat
);
1129 #endif /* ALIGNMENT_CHECKS */
1130 ofile
->arch_type
= OFILE_Mach_O
;
1131 ofile
->object_addr
= addr
;
1132 ofile
->object_size
= size
;
1133 if(magic
== MH_MAGIC_64
)
1134 ofile
->object_byte_sex
= host_byte_sex
;
1136 ofile
->object_byte_sex
=
1137 host_byte_sex
== BIG_ENDIAN_BYTE_SEX
?
1138 LITTLE_ENDIAN_BYTE_SEX
: BIG_ENDIAN_BYTE_SEX
;
1139 ofile
->mh64
= (struct mach_header_64
*)addr
;
1140 ofile
->load_commands
= (struct load_command
*)(addr
+
1141 sizeof(struct mach_header_64
));
1142 if(check_Mach_O(ofile
) == CHECK_BAD
){
1145 return(NSObjectFileImageFormat
);
1150 if(object_name
!= NULL
){
1151 error("fat file: %s architecture %s is not an archive "
1152 "(object_name to ofile_map() can't be specified to "
1153 "be other than NULL)", ofile
->file_name
,
1158 /* see if this file is an archive file */
1159 else if(size
>= SARMAG
&& strncmp(addr
, ARMAG
, SARMAG
) == 0){
1160 ofile
->arch_type
= OFILE_ARCHIVE
;
1161 if(check_archive(ofile
, FALSE
) == CHECK_BAD
){
1164 return(NSObjectFileImageInappropriateFile
);
1169 #ifdef ALIGNMENT_CHECKS
1170 if(ofile
->archive_cputype
!= 0 &&
1171 ofile
->fat_archs
[i
].offset
% sizeof(uint32_t) != 0){
1172 error("fat file: %s architecture %s malformed archive that "
1173 "contains object files (offset to archive is not a "
1174 "multiple of sizeof(uint32_t))",
1175 ofile
->file_name
, arch_flag
->name
);
1178 return(NSObjectFileImageInappropriateFile
);
1183 #endif /* ALIGNMENT_CHECKS */
1184 if(object_name
!= NULL
){
1185 if(ofile_specific_member(object_name
, ofile
) == FALSE
)
1189 /* this file type is now known to be unknown to this program */
1191 ofile
->file_type
= OFILE_UNKNOWN
;
1192 if(object_name
!= NULL
){
1193 error("fat file: %s architecture %s is not an archive "
1194 "(object_name to ofile_map() can't be specified to "
1195 "be other than NULL)", ofile
->file_name
,
1201 /* see if this file is a 32-bit Mach-O file */
1202 else if(size
>= sizeof(struct mach_header
) &&
1203 (magic
== MH_MAGIC
||
1204 magic
== SWAP_INT(MH_MAGIC
))){
1205 ofile
->file_type
= OFILE_Mach_O
;
1206 ofile
->object_addr
= addr
;
1207 ofile
->object_size
= size
;
1208 if(magic
== MH_MAGIC
)
1209 ofile
->object_byte_sex
= host_byte_sex
;
1211 ofile
->object_byte_sex
= host_byte_sex
== BIG_ENDIAN_BYTE_SEX
?
1212 LITTLE_ENDIAN_BYTE_SEX
: BIG_ENDIAN_BYTE_SEX
;
1213 ofile
->mh
= (struct mach_header
*)addr
;
1214 ofile
->load_commands
= (struct load_command
*)(addr
+
1215 sizeof(struct mach_header
));
1216 if(check_Mach_O(ofile
) == CHECK_BAD
){
1219 return(NSObjectFileImageFormat
);
1224 if(object_name
!= NULL
){
1225 error("file: %s is not an archive (object_name to ofile_map() "
1226 "can't be specified to be other than NULL)",
1230 if(arch_flag
!= NULL
){
1231 if(arch_flag
->cputype
!= ofile
->mh_cputype
&&
1232 (arch_flag
->cpusubtype
& ~CPU_SUBTYPE_MASK
) !=
1233 (ofile
->mh_cpusubtype
& ~CPU_SUBTYPE_MASK
)){
1236 return(NSObjectFileImageArch
);
1238 error("object file: %s does not match specified arch_flag: "
1239 "%s passed to ofile_map()", ofile
->file_name
,
1248 /* see if this file is a 64-bit Mach-O file */
1249 else if(size
>= sizeof(struct mach_header_64
) &&
1250 (magic
== MH_MAGIC_64
||
1251 magic
== SWAP_INT(MH_MAGIC_64
))){
1252 ofile
->file_type
= OFILE_Mach_O
;
1253 ofile
->object_addr
= addr
;
1254 ofile
->object_size
= size
;
1255 if(magic
== MH_MAGIC_64
)
1256 ofile
->object_byte_sex
= host_byte_sex
;
1258 ofile
->object_byte_sex
= host_byte_sex
== BIG_ENDIAN_BYTE_SEX
?
1259 LITTLE_ENDIAN_BYTE_SEX
: BIG_ENDIAN_BYTE_SEX
;
1260 ofile
->mh64
= (struct mach_header_64
*)addr
;
1261 ofile
->load_commands
= (struct load_command
*)(addr
+
1262 sizeof(struct mach_header_64
));
1263 if(check_Mach_O(ofile
) == CHECK_BAD
){
1266 return(NSObjectFileImageFormat
);
1271 if(object_name
!= NULL
){
1272 error("file: %s is not an archive (object_name to ofile_map() "
1273 "can't be specified to be other than NULL)",
1277 if(arch_flag
!= NULL
){
1278 if(arch_flag
->cputype
!= ofile
->mh_cputype
&&
1279 (arch_flag
->cpusubtype
& ~CPU_SUBTYPE_MASK
) !=
1280 (ofile
->mh_cpusubtype
& ~CPU_SUBTYPE_MASK
)){
1283 return(NSObjectFileImageArch
);
1285 error("object file: %s does not match specified arch_flag: "
1286 "%s passed to ofile_map()", ofile
->file_name
,
1295 /* see if this file is an archive file */
1296 else if(size
>= SARMAG
&& strncmp(addr
, ARMAG
, SARMAG
) == 0){
1297 ofile
->file_type
= OFILE_ARCHIVE
;
1298 if(check_archive(ofile
, archives_with_fat_objects
) == CHECK_BAD
)
1300 if(object_name
!= NULL
){
1301 if(ofile_specific_member(object_name
, ofile
) == FALSE
)
1303 if(arch_flag
!= NULL
){
1304 if(arch_flag
->cputype
!= ofile
->mh_cputype
&&
1305 (arch_flag
->cpusubtype
& ~CPU_SUBTYPE_MASK
) !=
1306 (ofile
->mh_cpusubtype
& ~CPU_SUBTYPE_MASK
)){
1307 error("object file: %s(%.*s) does not match specified "
1308 "arch_flag: %s passed to ofile_map()",
1309 ofile
->file_name
, (int)ofile
->member_name_size
,
1310 ofile
->member_name
, arch_flag
->name
);
1316 if(arch_flag
!= NULL
){
1317 if(arch_flag
->cputype
!= ofile
->archive_cputype
&&
1318 (arch_flag
->cpusubtype
& ~CPU_SUBTYPE_MASK
) !=
1319 (ofile
->archive_cpusubtype
& ~CPU_SUBTYPE_MASK
)){
1320 error("archive file: %s objects do not match specified "
1321 "arch_flag: %s passed to ofile_map()",
1322 ofile
->file_name
, arch_flag
->name
);
1328 /* this file type is now known to be unknown to this program */
1335 if(is_llvm_bitcode(ofile
, ofile
->file_addr
, ofile
->file_size
) ==
1337 ofile
->file_type
= OFILE_LLVM_BITCODE
;
1338 if(arch_flag
!= NULL
){
1339 if(arch_flag
->cputype
!= ofile
->lto_cputype
&&
1340 (arch_flag
->cpusubtype
& ~CPU_SUBTYPE_MASK
) !=
1341 (ofile
->lto_cpusubtype
& ~CPU_SUBTYPE_MASK
)){
1342 error("llvm bitcode file: %s does not match specified "
1343 "arch_flag: %s passed to ofile_map()",
1344 ofile
->file_name
, arch_flag
->name
);
1348 if(object_name
!= NULL
){
1349 error("file: %s is not an archive (object_name to "
1350 "ofile_map() can't be specified to be other than "
1351 "NULL)", ofile
->file_name
);
1357 #endif /* LTO_SUPPORT */
1359 ofile
->file_type
= OFILE_UNKNOWN
;
1360 if(arch_flag
!= NULL
){
1363 return(NSObjectFileImageInappropriateFile
);
1365 error("file: %s is unknown type (arch_flag to ofile_map() "
1366 "can't be specified to be other than NULL)",
1372 if(object_name
!= NULL
){
1373 error("file: %s is not an archive (object_name to ofile_map() "
1374 "can't be specified to be other than NULL)",
1388 * ofile_unmap() deallocates the memory associated with the specified ofile
1394 struct ofile
*ofile
)
1398 if(ofile
->file_addr
!= NULL
){
1399 if((r
= vm_deallocate(mach_task_self(),
1400 (vm_address_t
)ofile
->file_addr
,
1401 (vm_size_t
)ofile
->file_size
)) != KERN_SUCCESS
){
1402 my_mach_error(r
, "Can't vm_deallocate mapped memory for file: "
1403 "%s", ofile
->file_name
);
1406 if(ofile
->file_name
!= NULL
)
1407 free(ofile
->file_name
);
1408 if(ofile
->arch_flag
.name
!= NULL
)
1409 free(ofile
->arch_flag
.name
);
1410 memset(ofile
, '\0', sizeof(struct ofile
));
1414 * ofile_first_arch() sets up the ofile struct for a fat file to the first arch
1420 struct ofile
*ofile
)
1422 if(ofile
->file_type
== OFILE_FAT
||
1423 (ofile
->file_type
== OFILE_ARCHIVE
&&
1424 ofile
->member_type
== OFILE_FAT
) )
1425 return(ofile_specific_arch(ofile
, 0));
1427 error("ofile_first_arch() called and file type of: %s is not a fat "
1428 "file\n", ofile
->file_name
);
1434 * ofile_next_arch() sets up the ofile struct for a fat file to the next arch
1440 struct ofile
*ofile
)
1442 if(ofile
->file_type
== OFILE_FAT
||
1443 (ofile
->file_type
== OFILE_ARCHIVE
&&
1444 ofile
->member_type
== OFILE_FAT
) ){
1445 if(ofile
->narch
+ 1 < ofile
->fat_header
->nfat_arch
)
1446 return(ofile_specific_arch(ofile
, ofile
->narch
+ 1));
1451 error("ofile_next_arch() called and file type of: %s is not a fat "
1452 "file\n", ofile
->file_name
);
1458 * ofile_specific_arch() sets up the ofile struct for the fat file for the
1463 ofile_specific_arch(
1464 struct ofile
*ofile
,
1470 enum byte_sex host_byte_sex
;
1472 ofile
->narch
= narch
;
1473 ofile
->arch_type
= OFILE_UNKNOWN
;
1474 if(ofile
->arch_flag
.name
!= NULL
)
1475 free(ofile
->arch_flag
.name
);
1476 ofile
->arch_flag
.name
= NULL
;
1477 ofile
->arch_flag
.cputype
= 0;
1478 ofile
->arch_flag
.cpusubtype
= 0;
1479 ofile
->archive_cputype
= 0;
1480 ofile
->archive_cpusubtype
= 0;
1481 ofile
->object_addr
= NULL
;
1482 ofile
->object_size
= 0;
1483 ofile
->object_byte_sex
= UNKNOWN_BYTE_SEX
;
1486 ofile
->load_commands
= NULL
;
1488 ofile
->arch_flag
.cputype
= ofile
->fat_archs
[ofile
->narch
].cputype
;
1489 ofile
->arch_flag
.cpusubtype
= ofile
->fat_archs
[ofile
->narch
].cpusubtype
;
1490 set_arch_flag_name(&(ofile
->arch_flag
));
1493 /* Now determine the file type for this specific architecture */
1494 if(ofile
->file_type
== OFILE_FAT
){
1495 ofile
->member_offset
= 0;
1496 ofile
->member_addr
= NULL
;
1497 ofile
->member_size
= 0;
1498 ofile
->member_ar_hdr
= NULL
;
1499 ofile
->member_type
= OFILE_UNKNOWN
;
1501 size
= ofile
->fat_archs
[ofile
->narch
].size
;
1502 addr
= ofile
->file_addr
+ ofile
->fat_archs
[ofile
->narch
].offset
;
1505 if(ofile
->file_type
!= OFILE_ARCHIVE
||
1506 ofile
->member_type
!= OFILE_FAT
){
1507 error("internal error. ofile_specific_arch() called but file "
1508 "is not a fat file or an archive with a fat member ");
1510 size
= ofile
->fat_archs
[ofile
->narch
].size
;
1511 addr
= ofile
->file_addr
+
1512 ofile
->member_offset
+
1513 ofile
->fat_archs
[ofile
->narch
].offset
;
1517 if(addr
- ofile
->file_addr
> (ptrdiff_t)ofile
->file_size
){
1518 error("fat file: %s offset to architecture %s extends past end "
1519 "of file", ofile
->file_name
, ofile
->arch_flag
.name
);
1522 if(addr
+ size
> ofile
->file_addr
+ ofile
->file_size
)
1523 size
= (ofile
->file_addr
+ ofile
->file_size
) - addr
;
1526 if(size
>= sizeof(struct mach_header
))
1527 memcpy(&magic
, addr
, sizeof(uint32_t));
1528 /* see if this file is a 32-bit Mach-O file */
1529 if(size
>= sizeof(struct mach_header
) &&
1530 (magic
== MH_MAGIC
|| magic
== SWAP_INT(MH_MAGIC
))){
1531 #ifdef ALIGNMENT_CHECKS
1532 if(ofile
->fat_archs
[ofile
->narch
].offset
% 4 != 0){
1533 if(ofile
->file_type
== OFILE_ARCHIVE
){
1534 error("fat file: %s(%.*s) architecture %s malformed for a "
1535 "32-bit object file (offset is not a multiple of 4)",
1536 ofile
->file_name
, (int)ofile
->member_name_size
,
1537 ofile
->member_name
, ofile
->arch_flag
.name
);
1540 error("fat file: %s architecture %s malformed for a 32-bit "
1541 "object file (offset is not a multiple of 4)",
1542 ofile
->file_name
, ofile
->arch_flag
.name
);
1545 #endif /* ALIGNMENT_CHECKS */
1546 ofile
->arch_type
= OFILE_Mach_O
;
1547 ofile
->object_addr
= addr
;
1548 ofile
->object_size
= size
;
1549 host_byte_sex
= get_host_byte_sex();
1550 if(magic
== MH_MAGIC
)
1551 ofile
->object_byte_sex
= host_byte_sex
;
1553 ofile
->object_byte_sex
=
1554 host_byte_sex
== BIG_ENDIAN_BYTE_SEX
?
1555 LITTLE_ENDIAN_BYTE_SEX
: BIG_ENDIAN_BYTE_SEX
;
1556 ofile
->mh
= (struct mach_header
*)addr
;
1557 ofile
->load_commands
= (struct load_command
*)(addr
+
1558 sizeof(struct mach_header
));
1559 if(check_Mach_O(ofile
) == CHECK_BAD
)
1562 /* see if this file is a 64-bit Mach-O file */
1563 else if(size
>= sizeof(struct mach_header_64
) &&
1564 (magic
== MH_MAGIC_64
|| magic
== SWAP_INT(MH_MAGIC_64
))){
1565 #ifdef ALIGNMENT_CHECKS
1566 if(ofile
->fat_archs
[ofile
->narch
].offset
% 8 != 0){
1567 if(ofile
->file_type
== OFILE_ARCHIVE
){
1568 error("fat file: %s(%.*s) architecture %s malformed for an "
1569 "object file (offset is not a multiple of 8)",
1570 ofile
->file_name
, (int)ofile
->member_name_size
,
1571 ofile
->member_name
, ofile
->arch_flag
.name
);
1574 error("fat file: %s architecture %s malformed for a 64-bit "
1575 "object file (offset is not a multiple of 8",
1576 ofile
->file_name
, ofile
->arch_flag
.name
);
1579 #endif /* ALIGNMENT_CHECKS */
1580 ofile
->arch_type
= OFILE_Mach_O
;
1581 ofile
->object_addr
= addr
;
1582 ofile
->object_size
= size
;
1583 host_byte_sex
= get_host_byte_sex();
1584 if(magic
== MH_MAGIC_64
)
1585 ofile
->object_byte_sex
= host_byte_sex
;
1587 ofile
->object_byte_sex
=
1588 host_byte_sex
== BIG_ENDIAN_BYTE_SEX
?
1589 LITTLE_ENDIAN_BYTE_SEX
: BIG_ENDIAN_BYTE_SEX
;
1590 ofile
->mh64
= (struct mach_header_64
*)addr
;
1591 ofile
->load_commands
= (struct load_command
*)(addr
+
1592 sizeof(struct mach_header_64
));
1593 if(check_Mach_O(ofile
) == CHECK_BAD
)
1596 /* see if this file is an archive file */
1597 else if(size
>= SARMAG
&& strncmp(addr
, ARMAG
, SARMAG
) == 0){
1598 ofile
->arch_type
= OFILE_ARCHIVE
;
1599 if(check_archive(ofile
, FALSE
) == CHECK_BAD
)
1601 #ifdef ALIGNMENT_CHECKS
1602 if(ofile
->archive_cputype
!= 0 &&
1603 ofile
->fat_archs
[ofile
->narch
].offset
%
1604 sizeof(uint32_t) != 0){
1605 error("fat file: %s architecture %s malformed archive that "
1606 "contains object files (offset to archive is not a "
1607 "multiple of sizeof(uint32_t))",
1608 ofile
->file_name
, ofile
->arch_flag
.name
);
1611 #endif /* ALIGNMENT_CHECKS */
1614 * This type for this architecture is now known to be unknown to this
1618 ofile
->arch_type
= OFILE_UNKNOWN
;
1623 ofile
->arch_type
= OFILE_UNKNOWN
;
1624 if(ofile
->arch_flag
.name
!= NULL
)
1625 free(ofile
->arch_flag
.name
);
1626 ofile
->arch_flag
.name
= NULL
;
1627 ofile
->arch_flag
.cputype
= 0;
1628 ofile
->arch_flag
.cpusubtype
= 0;
1629 if(ofile
->file_type
!= OFILE_ARCHIVE
){
1630 ofile
->member_offset
= 0;
1631 ofile
->member_addr
= NULL
;
1632 ofile
->member_size
= 0;
1633 ofile
->member_ar_hdr
= NULL
;
1634 ofile
->member_type
= OFILE_UNKNOWN
;
1636 ofile
->archive_cputype
= 0;
1637 ofile
->archive_cpusubtype
= 0;
1638 ofile
->object_addr
= NULL
;
1639 ofile
->object_size
= 0;
1640 ofile
->object_byte_sex
= UNKNOWN_BYTE_SEX
;
1643 ofile
->load_commands
= NULL
;
1648 * ofile_first_member() set up the ofile structure (the member_* fields and
1649 * the object file fields if the first member is an object file) for the first
1655 struct ofile
*ofile
)
1658 uint32_t size
, offset
;
1660 enum byte_sex host_byte_sex
;
1661 struct ar_hdr
*ar_hdr
;
1662 uint32_t ar_name_size
;
1664 /* These fields are to be filled in by this routine, clear them first */
1665 ofile
->member_offset
= 0;
1666 ofile
->member_addr
= NULL
;
1667 ofile
->member_size
= 0;
1668 ofile
->member_ar_hdr
= NULL
;
1669 ofile
->member_name
= NULL
;
1670 ofile
->member_name_size
= 0;
1671 ofile
->member_type
= OFILE_UNKNOWN
;
1672 ofile
->object_addr
= NULL
;
1673 ofile
->object_size
= 0;
1674 ofile
->object_byte_sex
= UNKNOWN_BYTE_SEX
;
1677 ofile
->load_commands
= NULL
;
1680 * Note: it is up to the caller if they want to call free_lto() on this
1681 * when iterating through the members of an archive.
1684 #endif /* LTO_SUPPORT */
1687 * Get the address and size of the archive.
1689 if(ofile
->file_type
== OFILE_FAT
){
1690 if(ofile
->arch_type
!= OFILE_ARCHIVE
){
1691 error("ofile_first_member() called on fat file: %s with a "
1692 "non-archive architecture or no architecture selected\n",
1696 addr
= ofile
->file_addr
+ ofile
->fat_archs
[ofile
->narch
].offset
;
1697 size
= ofile
->fat_archs
[ofile
->narch
].size
;
1699 else if(ofile
->file_type
== OFILE_ARCHIVE
){
1700 addr
= ofile
->file_addr
;
1701 size
= ofile
->file_size
;
1704 error("ofile_first_member() called and file type of %s is "
1705 "OFILE_UNKNOWN\n", ofile
->file_name
);
1709 if((addr
+ SARMAG
) - ofile
->file_addr
> (ptrdiff_t)ofile
->file_size
){
1710 archive_error(ofile
, "offset to first member extends past the end "
1714 if(addr
+ size
> ofile
->file_addr
+ ofile
->file_size
)
1715 size
= (ofile
->file_addr
+ ofile
->file_size
) - addr
;
1717 if(size
< SARMAG
|| strncmp(addr
, ARMAG
, SARMAG
) != 0){
1718 archive_error(ofile
, "internal error. ofile_first_member() "
1719 "called but file does not have an archive magic "
1725 if(offset
!= size
&& offset
+ sizeof(struct ar_hdr
) > size
){
1726 archive_error(ofile
, "truncated or malformed (archive header of "
1727 "first member extends past the end of the file)");
1731 /* check for empty archive */
1735 /* now we know there is a first member so set it up */
1736 ar_hdr
= (struct ar_hdr
*)(addr
+ offset
);
1737 offset
+= sizeof(struct ar_hdr
);
1738 ofile
->member_offset
= offset
;
1739 ofile
->member_addr
= addr
+ offset
;
1740 ofile
->member_size
= strtoul(ar_hdr
->ar_size
, NULL
, 10);
1741 ofile
->member_ar_hdr
= ar_hdr
;
1742 ofile
->member_type
= OFILE_UNKNOWN
;
1743 ofile
->member_name
= ar_hdr
->ar_name
;
1744 if(strncmp(ofile
->member_name
, AR_EFMT1
, sizeof(AR_EFMT1
) - 1) == 0){
1745 ofile
->member_name
= ar_hdr
->ar_name
+ sizeof(struct ar_hdr
);
1746 ar_name_size
= strtoul(ar_hdr
->ar_name
+ sizeof(AR_EFMT1
) - 1,
1748 ofile
->member_name_size
= ar_name_size
;
1749 ofile
->member_offset
+= ar_name_size
;
1750 ofile
->member_addr
+= ar_name_size
;
1751 ofile
->member_size
-= ar_name_size
;
1754 ofile
->member_name_size
= size_ar_name(ar_hdr
);
1757 /* Clear these in case there is no table of contents */
1758 ofile
->toc_addr
= NULL
;
1759 ofile
->toc_size
= 0;
1760 ofile
->toc_ar_hdr
= NULL
;
1761 ofile
->toc_name
= NULL
;
1762 ofile
->toc_name_size
= 0;
1763 ofile
->toc_ranlibs
= NULL
;
1764 ofile
->toc_nranlibs
= 0;
1765 ofile
->toc_strings
= NULL
;
1766 ofile
->toc_strsize
= 0;
1767 ofile
->toc_bad
= FALSE
;
1769 host_byte_sex
= get_host_byte_sex();
1771 if(ofile
->member_size
> sizeof(uint32_t)){
1772 memcpy(&magic
, ofile
->member_addr
, sizeof(uint32_t));
1773 #ifdef __BIG_ENDIAN__
1774 if(magic
== FAT_MAGIC
)
1775 #endif /* __BIG_ENDIAN__ */
1776 #ifdef __LITTLE_ENDIAN__
1777 if(magic
== SWAP_INT(FAT_MAGIC
))
1778 #endif /* __LITTLE_ENDIAN__ */
1780 ofile
->member_type
= OFILE_FAT
;
1782 (struct fat_header
*)(ofile
->member_addr
);
1783 #ifdef __LITTLE_ENDIAN__
1784 swap_fat_header(ofile
->fat_header
, host_byte_sex
);
1785 #endif /* __LITTLE_ENDIAN__ */
1786 if(sizeof(struct fat_header
) +
1787 ofile
->fat_header
->nfat_arch
*
1788 sizeof(struct fat_arch
) > ofile
->member_size
){
1789 archive_member_error(ofile
, "fat file truncated or "
1790 "malformed (fat_arch structs would extend past "
1791 "the end of the archive member)");
1794 ofile
->fat_archs
= (struct fat_arch
*)
1795 (ofile
->member_addr
+ sizeof(struct fat_header
));
1796 #ifdef __LITTLE_ENDIAN__
1797 swap_fat_arch(ofile
->fat_archs
,
1798 ofile
->fat_header
->nfat_arch
, host_byte_sex
);
1799 #endif /* __LITTLE_ENDIAN__ */
1800 if(check_fat_object_in_archive(ofile
) == FALSE
)
1803 else if(size
- (offset
+ ar_name_size
) >=
1804 sizeof(struct mach_header
) &&
1805 (magic
== MH_MAGIC
|| magic
== SWAP_INT(MH_MAGIC
))){
1806 #ifdef ALIGNMENT_CHECKS
1807 if((offset
+ ar_name_size
) % 4 != 0){
1808 archive_member_error(ofile
, "offset in archive not a "
1809 "multiple of 4 (must be since member is a 32-bit "
1813 #endif /* ALIGNMENT_CHECKS */
1814 ofile
->member_type
= OFILE_Mach_O
;
1815 ofile
->object_addr
= ofile
->member_addr
;
1816 ofile
->object_size
= ofile
->member_size
;
1817 if(magic
== MH_MAGIC
)
1818 ofile
->object_byte_sex
= host_byte_sex
;
1820 ofile
->object_byte_sex
=
1821 host_byte_sex
== BIG_ENDIAN_BYTE_SEX
?
1822 LITTLE_ENDIAN_BYTE_SEX
: BIG_ENDIAN_BYTE_SEX
;
1823 ofile
->mh
= (struct mach_header
*)(ofile
->object_addr
);
1824 ofile
->load_commands
= (struct load_command
*)
1825 (ofile
->object_addr
+ sizeof(struct mach_header
));
1826 if(check_Mach_O(ofile
) == CHECK_BAD
)
1829 else if(size
- (offset
+ ar_name_size
) >=
1830 sizeof(struct mach_header_64
) &&
1831 (magic
== MH_MAGIC_64
|| magic
== SWAP_INT(MH_MAGIC_64
))){
1832 #ifdef ALIGNMENT_CHECKS_ARCHIVE_64_BIT
1833 if(archive_64_bit_align_warning
== FALSE
&&
1834 (offset
+ ar_name_size
) % 8 != 0){
1835 temporary_archive_member_warning(ofile
, "offset in archive "
1836 "not a multiple of 8 (must be since member is an "
1837 "64-bit object file)");
1838 archive_64_bit_align_warning
= TRUE
;
1841 #endif /* ALIGNMENT_CHECKS_ARCHIVE_64_BIT */
1842 ofile
->member_type
= OFILE_Mach_O
;
1843 ofile
->object_addr
= ofile
->member_addr
;
1844 ofile
->object_size
= ofile
->member_size
;
1845 if(magic
== MH_MAGIC_64
)
1846 ofile
->object_byte_sex
= host_byte_sex
;
1848 ofile
->object_byte_sex
=
1849 host_byte_sex
== BIG_ENDIAN_BYTE_SEX
?
1850 LITTLE_ENDIAN_BYTE_SEX
: BIG_ENDIAN_BYTE_SEX
;
1851 ofile
->mh64
= (struct mach_header_64
*)(ofile
->object_addr
);
1852 ofile
->load_commands
= (struct load_command
*)
1853 (ofile
->object_addr
+ sizeof(struct mach_header_64
));
1854 if(check_Mach_O(ofile
) == CHECK_BAD
)
1857 if(ofile
->member_type
== OFILE_UNKNOWN
&&
1858 (strncmp(ofile
->member_name
, SYMDEF_SORTED
,
1859 sizeof(SYMDEF_SORTED
) - 1) == 0 ||
1860 strncmp(ofile
->member_name
, SYMDEF
,
1861 sizeof(SYMDEF
) - 1) == 0)){
1862 ofile
->toc_addr
= ofile
->member_addr
;
1863 ofile
->toc_size
= ofile
->member_size
;
1864 ofile
->toc_ar_hdr
= ofile
->member_ar_hdr
;
1865 ofile
->toc_name
= ofile
->member_name
;
1866 ofile
->toc_name_size
= ofile
->member_name_size
;
1867 if(check_archive_toc(ofile
) == CHECK_BAD
)
1871 if(ofile
->member_type
== OFILE_UNKNOWN
&&
1872 strncmp(ofile
->member_name
, SYMDEF_SORTED
,
1873 sizeof(SYMDEF_SORTED
) - 1) != 0 &&
1874 strncmp(ofile
->member_name
, SYMDEF
,
1875 sizeof(SYMDEF
) - 1) != 0 &&
1876 is_llvm_bitcode(ofile
, ofile
->member_addr
, ofile
->member_size
) ==
1878 ofile
->member_type
= OFILE_LLVM_BITCODE
;
1879 ofile
->object_addr
= ofile
->member_addr
;
1880 ofile
->object_size
= ofile
->member_size
;
1882 #endif /* LTO_SUPPORT */
1887 ofile
->fat_header
= NULL
;
1888 ofile
->fat_archs
= NULL
;
1890 ofile
->member_offset
= 0;
1891 ofile
->member_addr
= 0;
1892 ofile
->member_size
= 0;
1893 ofile
->member_ar_hdr
= NULL
;
1894 ofile
->member_name
= NULL
;
1895 ofile
->member_name_size
= 0;
1896 ofile
->member_type
= OFILE_UNKNOWN
;
1897 ofile
->object_addr
= NULL
;
1898 ofile
->object_size
= 0;
1899 ofile
->object_byte_sex
= UNKNOWN_BYTE_SEX
;
1902 ofile
->load_commands
= NULL
;
1905 ofile
->lto_cputype
= 0;
1906 ofile
->lto_cpusubtype
= 0;
1907 #endif /* LTO_SUPPORT */
1912 * ofile_next_member() set up the ofile structure (the member_* fields and
1913 * the object file fields if the next member is an object file) for the next
1919 struct ofile
*ofile
)
1922 uint32_t size
, offset
;
1924 enum byte_sex host_byte_sex
;
1925 struct ar_hdr
*ar_hdr
;
1926 uint32_t ar_name_size
;
1929 * Get the address and size of the archive.
1931 if(ofile
->file_type
== OFILE_FAT
){
1932 if(ofile
->arch_type
!= OFILE_ARCHIVE
){
1933 error("ofile_next_member() called on fat file: %s with a "
1934 "non-archive architecture or no architecture selected\n",
1938 addr
= ofile
->file_addr
+ ofile
->fat_archs
[ofile
->narch
].offset
;
1939 size
= ofile
->fat_archs
[ofile
->narch
].size
;
1941 else if(ofile
->file_type
== OFILE_ARCHIVE
){
1942 addr
= ofile
->file_addr
;
1943 size
= ofile
->file_size
;
1946 error("ofile_next_member() called and file type of %s is "
1947 "OFILE_UNKNOWN\n", ofile
->file_name
);
1950 if(size
< SARMAG
|| strncmp(addr
, ARMAG
, SARMAG
) != 0){
1951 archive_error(ofile
, "internal error. ofile_next_member() "
1952 "called but file does not have an archive magic "
1956 if(ofile
->member_ar_hdr
== NULL
){
1957 archive_error(ofile
, "internal error. ofile_next_member() called "
1958 "but the ofile struct does not have an archive "
1963 /* figure out the offset to the next member */
1964 offset
= ofile
->member_offset
+ rnd(ofile
->member_size
,sizeof(short));
1966 if((addr
- ofile
->file_addr
) + offset
> ofile
->file_size
){
1967 archive_error(ofile
, "offset to next member extends past the end "
1972 /* if now at the end of the file then no more members */
1976 archive_error(ofile
, "truncated or malformed (archive header of "
1977 "next member extends past the end of the file)");
1981 /* now we know there is a next member so set it up */
1982 ar_hdr
= (struct ar_hdr
*)(addr
+ offset
);
1983 offset
+= sizeof(struct ar_hdr
);
1984 ofile
->member_offset
= offset
;
1985 ofile
->member_addr
= addr
+ offset
;
1986 ofile
->member_size
= strtoul(ar_hdr
->ar_size
, NULL
, 10);
1987 ofile
->member_ar_hdr
= ar_hdr
;
1988 ofile
->member_name
= ar_hdr
->ar_name
;
1989 if(strncmp(ofile
->member_name
, AR_EFMT1
, sizeof(AR_EFMT1
) - 1) == 0){
1990 ofile
->member_name
= ar_hdr
->ar_name
+ sizeof(struct ar_hdr
);
1991 ar_name_size
= strtoul(ar_hdr
->ar_name
+ sizeof(AR_EFMT1
) - 1,
1993 ofile
->member_name_size
= ar_name_size
;
1994 ofile
->member_offset
+= ar_name_size
;
1995 ofile
->member_addr
+= ar_name_size
;
1996 ofile
->member_size
-= ar_name_size
;
1999 ofile
->member_name_size
= size_ar_name(ar_hdr
);
2002 ofile
->member_type
= OFILE_UNKNOWN
;
2003 ofile
->object_addr
= NULL
;
2004 ofile
->object_size
= 0;
2005 ofile
->object_byte_sex
= UNKNOWN_BYTE_SEX
;
2008 ofile
->load_commands
= NULL
;
2010 host_byte_sex
= get_host_byte_sex();
2012 if(ofile
->member_size
> sizeof(uint32_t)){
2013 memcpy(&magic
, ofile
->member_addr
, sizeof(uint32_t));
2014 #ifdef __BIG_ENDIAN__
2015 if(magic
== FAT_MAGIC
)
2016 #endif /* __BIG_ENDIAN__ */
2017 #ifdef __LITTLE_ENDIAN__
2018 if(magic
== SWAP_INT(FAT_MAGIC
))
2019 #endif /* __LITTLE_ENDIAN__ */
2021 ofile
->member_type
= OFILE_FAT
;
2022 ofile
->fat_header
= (struct fat_header
*)(ofile
->member_addr
);
2023 #ifdef __LITTLE_ENDIAN__
2024 swap_fat_header(ofile
->fat_header
, host_byte_sex
);
2025 #endif /* __LITTLE_ENDIAN__ */
2026 if(sizeof(struct fat_header
) +
2027 ofile
->fat_header
->nfat_arch
*
2028 sizeof(struct fat_arch
) > ofile
->member_size
){
2029 archive_member_error(ofile
, "fat file truncated or "
2030 "malformed (fat_arch structs would extend past "
2031 "the end of the archive member)");
2034 ofile
->fat_archs
= (struct fat_arch
*)(ofile
->member_addr
+
2035 sizeof(struct fat_header
));
2036 #ifdef __LITTLE_ENDIAN__
2037 swap_fat_arch(ofile
->fat_archs
,
2038 ofile
->fat_header
->nfat_arch
, host_byte_sex
);
2039 #endif /* __LITTLE_ENDIAN__ */
2040 if(check_fat_object_in_archive(ofile
) == FALSE
)
2043 else if(size
- (offset
+ ar_name_size
) >=
2044 sizeof(struct mach_header
) &&
2045 (magic
== MH_MAGIC
||
2046 magic
== SWAP_INT(MH_MAGIC
))){
2047 #ifdef ALIGNMENT_CHECKS
2048 if((offset
+ ar_name_size
) % 4 != 0){
2049 archive_member_error(ofile
, "offset in archive not "
2050 "a multiple of 4 (must be since member is an 32-bit "
2054 #endif /* ALIGNMENT_CHECKS */
2055 ofile
->member_type
= OFILE_Mach_O
;
2056 ofile
->object_addr
= ofile
->member_addr
;
2057 ofile
->object_size
= ofile
->member_size
;
2058 if(magic
== MH_MAGIC
)
2059 ofile
->object_byte_sex
= host_byte_sex
;
2061 ofile
->object_byte_sex
=
2062 host_byte_sex
== BIG_ENDIAN_BYTE_SEX
?
2063 LITTLE_ENDIAN_BYTE_SEX
: BIG_ENDIAN_BYTE_SEX
;
2064 ofile
->mh
= (struct mach_header
*)ofile
->object_addr
;
2065 ofile
->load_commands
= (struct load_command
*)
2066 (ofile
->object_addr
+ sizeof(struct mach_header
));
2067 if(check_Mach_O(ofile
) == CHECK_BAD
)
2070 else if(size
- (offset
+ ar_name_size
) >=
2071 sizeof(struct mach_header_64
) &&
2072 (magic
== MH_MAGIC_64
||
2073 magic
== SWAP_INT(MH_MAGIC_64
))){
2074 #ifdef ALIGNMENT_CHECKS_ARCHIVE_64_BIT
2075 if(archive_64_bit_align_warning
== FALSE
&&
2076 (offset
+ ar_name_size
) % 8 != 0){
2077 temporary_archive_member_warning(ofile
, "offset in archive "
2078 "not a multiple of 8 (must be since member is an "
2079 "64-bit object file)");
2080 archive_64_bit_align_warning
= TRUE
;
2083 #endif /* ALIGNMENT_CHECKS_ARCHIVE_64_BIT */
2084 ofile
->member_type
= OFILE_Mach_O
;
2085 ofile
->object_addr
= ofile
->member_addr
;
2086 ofile
->object_size
= ofile
->member_size
;
2087 if(magic
== MH_MAGIC_64
)
2088 ofile
->object_byte_sex
= host_byte_sex
;
2090 ofile
->object_byte_sex
=
2091 host_byte_sex
== BIG_ENDIAN_BYTE_SEX
?
2092 LITTLE_ENDIAN_BYTE_SEX
: BIG_ENDIAN_BYTE_SEX
;
2093 ofile
->mh64
= (struct mach_header_64
*)ofile
->object_addr
;
2094 ofile
->load_commands
= (struct load_command
*)
2095 (ofile
->object_addr
+ sizeof(struct mach_header_64
));
2096 if(check_Mach_O(ofile
) == CHECK_BAD
)
2100 if(ofile
->member_type
== OFILE_UNKNOWN
&&
2101 is_llvm_bitcode(ofile
, ofile
->member_addr
, ofile
->member_size
) ==
2103 ofile
->member_type
= OFILE_LLVM_BITCODE
;
2104 ofile
->object_addr
= ofile
->member_addr
;
2105 ofile
->object_size
= ofile
->member_size
;
2107 #endif /* LTO_SUPPORT */
2112 if(ofile
->member_type
== OFILE_FAT
){
2113 ofile
->fat_header
= NULL
;
2114 ofile
->fat_archs
= NULL
;
2116 ofile
->member_offset
= 0;
2117 ofile
->member_addr
= NULL
;
2118 ofile
->member_size
= 0;
2119 ofile
->member_ar_hdr
= NULL
;
2120 ofile
->member_name
= NULL
;
2121 ofile
->member_name_size
= 0;
2122 ofile
->member_type
= OFILE_UNKNOWN
;
2123 ofile
->object_addr
= NULL
;
2124 ofile
->object_size
= 0;
2125 ofile
->object_byte_sex
= UNKNOWN_BYTE_SEX
;
2128 ofile
->load_commands
= NULL
;
2131 ofile
->lto_cputype
= 0;
2132 ofile
->lto_cpusubtype
= 0;
2133 #endif /* LTO_SUPPORT */
2138 * ofile_specific_member() set up the ofile structure (the member_* fields and
2139 * the object file fields if the member is an object file) for the specified
2140 * member member_name.
2144 ofile_specific_member(
2145 const char *member_name
,
2146 struct ofile
*ofile
)
2150 uint32_t size
, offset
;
2152 enum byte_sex host_byte_sex
;
2154 uint32_t ar_name_size
;
2155 struct ar_hdr
*ar_hdr
;
2157 /* These fields are to be filled in by this routine, clear them first */
2158 ofile
->member_offset
= 0;
2159 ofile
->member_addr
= NULL
;
2160 ofile
->member_size
= 0;
2161 ofile
->member_ar_hdr
= NULL
;
2162 ofile
->member_name
= NULL
;
2163 ofile
->member_name_size
= 0;
2164 ofile
->member_type
= OFILE_UNKNOWN
;
2165 ofile
->object_addr
= NULL
;
2166 ofile
->object_size
= 0;
2167 ofile
->object_byte_sex
= UNKNOWN_BYTE_SEX
;
2170 ofile
->load_commands
= NULL
;
2173 * Get the address and size of the archive.
2175 if(ofile
->file_type
== OFILE_FAT
){
2176 if(ofile
->arch_type
!= OFILE_ARCHIVE
){
2177 error("ofile_specific_member() called on fat file: %s with a "
2178 "non-archive architecture or no architecture selected\n",
2182 addr
= ofile
->file_addr
+ ofile
->fat_archs
[ofile
->narch
].offset
;
2183 size
= ofile
->fat_archs
[ofile
->narch
].size
;
2185 else if(ofile
->file_type
== OFILE_ARCHIVE
){
2186 addr
= ofile
->file_addr
;
2187 size
= ofile
->file_size
;
2190 error("ofile_specific_member() called and file type of %s is "
2191 "OFILE_UNKNOWN\n", ofile
->file_name
);
2194 if(size
< SARMAG
|| strncmp(addr
, ARMAG
, SARMAG
) != 0){
2195 archive_error(ofile
, "internal error. ofile_specific_member() "
2196 "called but file does not have an archive magic "
2202 if(offset
!= size
&& offset
+ sizeof(struct ar_hdr
) > size
){
2203 archive_error(ofile
, "truncated or malformed (archive header of "
2204 "first member extends past the end of the file)");
2207 while(size
> offset
){
2208 ar_hdr
= (struct ar_hdr
*)(addr
+ offset
);
2209 offset
+= sizeof(struct ar_hdr
);
2210 if(strncmp(ar_hdr
->ar_name
, AR_EFMT1
, sizeof(AR_EFMT1
) - 1) == 0){
2212 if(check_extend_format_1(ofile
, ar_hdr
, size
- offset
,
2213 &ar_name_size
) == CHECK_BAD
){
2214 i
= size_ar_name(ar_hdr
);
2215 ar_name
= ar_hdr
->ar_name
;
2221 i
= strtoul(ar_hdr
->ar_name
+ sizeof(AR_EFMT1
) - 1,NULL
,10);
2222 ar_name
= ar_hdr
->ar_name
+ sizeof(struct ar_hdr
);
2227 i
= size_ar_name(ar_hdr
);
2228 ar_name
= ar_hdr
->ar_name
;
2231 if(i
> 0 && strncmp(ar_name
, member_name
, i
) == 0){
2233 ofile
->member_name
= ar_name
;
2234 ofile
->member_name_size
= i
;
2235 ofile
->member_offset
= offset
+ ar_name_size
;
2236 ofile
->member_addr
= addr
+ offset
+ ar_name_size
;
2237 ofile
->member_size
= strtoul(ar_hdr
->ar_size
, NULL
, 10) -
2239 ofile
->member_ar_hdr
= ar_hdr
;
2240 ofile
->member_type
= OFILE_UNKNOWN
;
2242 host_byte_sex
= get_host_byte_sex();
2244 if(ofile
->member_size
> sizeof(uint32_t)){
2245 memcpy(&magic
, addr
+ offset
+ ar_name_size
,
2247 #ifdef __BIG_ENDIAN__
2248 if(magic
== FAT_MAGIC
)
2249 #endif /* __BIG_ENDIAN__ */
2250 #ifdef __LITTLE_ENDIAN__
2251 if(magic
== SWAP_INT(FAT_MAGIC
))
2252 #endif /* __LITTLE_ENDIAN__ */
2254 ofile
->member_type
= OFILE_FAT
;
2256 (struct fat_header
*)(addr
+ offset
+ ar_name_size
);
2257 #ifdef __LITTLE_ENDIAN__
2258 swap_fat_header(ofile
->fat_header
, host_byte_sex
);
2259 #endif /* __LITTLE_ENDIAN__ */
2260 if(sizeof(struct fat_header
) +
2261 ofile
->fat_header
->nfat_arch
*
2262 sizeof(struct fat_arch
) > ofile
->member_size
){
2263 archive_member_error(ofile
, "fat file truncated or "
2264 "malformed (fat_arch structs would extend "
2265 "past the end of the archive member)");
2269 (struct fat_arch
*)(addr
+ offset
+ ar_name_size
+
2270 sizeof(struct fat_header
));
2271 #ifdef __LITTLE_ENDIAN__
2272 swap_fat_arch(ofile
->fat_archs
,
2273 ofile
->fat_header
->nfat_arch
,
2275 #endif /* __LITTLE_ENDIAN__ */
2276 if(check_fat_object_in_archive(ofile
) == FALSE
)
2279 else if(size
- (offset
+ ar_name_size
) >=
2280 sizeof(struct mach_header
) &&
2281 (magic
== MH_MAGIC
||
2282 magic
== SWAP_INT(MH_MAGIC
))){
2283 #ifdef ALIGNMENT_CHECKS
2284 if((offset
+ ar_name_size
) % 4 != 0){
2285 archive_member_error(ofile
, "offset in archive not "
2286 "a multiple of 4) (must be since member is a "
2287 "32-bit object file)");
2290 #endif /* ALIGNMENT_CHECKS */
2291 ofile
->member_type
= OFILE_Mach_O
;
2292 ofile
->object_addr
= ofile
->member_addr
;
2293 ofile
->object_size
= ofile
->member_size
;
2294 if(magic
== MH_MAGIC
)
2295 ofile
->object_byte_sex
= host_byte_sex
;
2297 ofile
->object_byte_sex
=
2298 host_byte_sex
== BIG_ENDIAN_BYTE_SEX
?
2299 LITTLE_ENDIAN_BYTE_SEX
: BIG_ENDIAN_BYTE_SEX
;
2300 ofile
->mh
= (struct mach_header
*)ofile
->object_addr
;
2301 ofile
->load_commands
= (struct load_command
*)
2302 (ofile
->object_addr
+ sizeof(struct mach_header
));
2303 if(check_Mach_O(ofile
) == CHECK_BAD
)
2306 else if(size
- (offset
+ ar_name_size
) >=
2307 sizeof(struct mach_header_64
) &&
2308 (magic
== MH_MAGIC_64
||
2309 magic
== SWAP_INT(MH_MAGIC_64
))){
2310 #ifdef ALIGNMENT_CHECKS_ARCHIVE_64_BIT
2311 if(archive_64_bit_align_warning
== FALSE
&&
2312 (offset
+ ar_name_size
) % 8 != 0){
2313 temporary_archive_member_warning(ofile
, "offset in "
2314 "archive not a multiple of 8) (must be since "
2315 "member is a 64-bit object file)");
2316 archive_64_bit_align_warning
= TRUE
;
2319 #endif /* ALIGNMENT_CHECKS_ARCHIVE_64_BIT */
2320 ofile
->member_type
= OFILE_Mach_O
;
2321 ofile
->object_addr
= ofile
->member_addr
;
2322 ofile
->object_size
= ofile
->member_size
;
2323 if(magic
== MH_MAGIC_64
)
2324 ofile
->object_byte_sex
= host_byte_sex
;
2326 ofile
->object_byte_sex
=
2327 host_byte_sex
== BIG_ENDIAN_BYTE_SEX
?
2328 LITTLE_ENDIAN_BYTE_SEX
: BIG_ENDIAN_BYTE_SEX
;
2329 ofile
->mh64
= (struct mach_header_64
*)
2331 ofile
->load_commands
= (struct load_command
*)
2332 (ofile
->object_addr
+sizeof(struct mach_header_64
));
2333 if(check_Mach_O(ofile
) == CHECK_BAD
)
2338 if(ofile
->member_type
== OFILE_UNKNOWN
&&
2339 is_llvm_bitcode(ofile
, ofile
->member_addr
,
2340 ofile
->member_size
) == TRUE
){
2341 ofile
->member_type
= OFILE_LLVM_BITCODE
;
2342 ofile
->object_addr
= ofile
->member_addr
;
2343 ofile
->object_size
= ofile
->member_size
;
2345 #endif /* LTO_SUPPORT */
2348 offset
+= rnd(strtoul(ar_hdr
->ar_size
, NULL
, 10),
2351 archive_error(ofile
, "does not contain a member named: %s",
2354 ofile
->fat_header
= NULL
;
2355 ofile
->fat_archs
= NULL
;
2357 ofile
->member_offset
= 0;
2358 ofile
->member_addr
= NULL
;
2359 ofile
->member_size
= 0;
2360 ofile
->member_ar_hdr
= NULL
;
2361 ofile
->member_name
= NULL
;
2362 ofile
->member_name_size
= 0;
2363 ofile
->member_type
= OFILE_UNKNOWN
;
2364 ofile
->object_addr
= NULL
;
2365 ofile
->object_size
= 0;
2366 ofile
->object_byte_sex
= UNKNOWN_BYTE_SEX
;
2369 ofile
->load_commands
= NULL
;
2372 ofile
->lto_cputype
= 0;
2373 ofile
->lto_cpusubtype
= 0;
2374 #endif /* LTO_SUPPORT */
2379 * ofile_first_module() set up the ofile structure (the dylib_module field)
2380 * for the first module of an MH_DYLIB or MH_DYLIB_STUB file.
2385 struct ofile
*ofile
)
2388 struct symtab_command
*st
;
2389 struct dysymtab_command
*dyst
;
2390 struct load_command
*lc
;
2392 enum byte_sex host_byte_sex
;
2393 struct dylib_module m
;
2394 struct dylib_module_64 m64
;
2397 /* These fields are to be filled in by this routine, clear them first */
2398 ofile
->modtab
= NULL
;
2399 ofile
->modtab64
= NULL
;
2401 ofile
->dylib_module
= NULL
;
2402 ofile
->dylib_module64
= NULL
;
2403 ofile
->dylib_module_name
= NULL
;
2405 if(ofile
->file_type
== OFILE_FAT
){
2406 if(ofile
->arch_type
!= OFILE_Mach_O
&&
2407 (ofile
->mh_filetype
!= MH_DYLIB
&&
2408 ofile
->mh_filetype
!= MH_DYLIB_STUB
)){
2409 error("ofile_first_module() called on fat file: %s with a "
2410 "non-MH_DYLIB architecture or no architecture selected\n",
2415 else if(ofile
->arch_type
!= OFILE_Mach_O
&&
2416 (ofile
->mh_filetype
!= MH_DYLIB
&&
2417 ofile
->mh_filetype
!= MH_DYLIB_STUB
)){
2418 error("ofile_first_module() called and file type of %s is "
2419 "non-MH_DYLIB\n", ofile
->file_name
);
2425 lc
= ofile
->load_commands
;
2426 if(ofile
->mh
!= NULL
)
2427 ncmds
= ofile
->mh
->ncmds
;
2429 ncmds
= ofile
->mh64
->ncmds
;
2430 for(i
= 0; i
< ncmds
; i
++){
2431 if(st
== NULL
&& lc
->cmd
== LC_SYMTAB
){
2432 st
= (struct symtab_command
*)lc
;
2434 else if(lc
->cmd
== LC_DYSYMTAB
){
2435 dyst
= (struct dysymtab_command
*)lc
;
2437 lc
= (struct load_command
*)((char *)lc
+ lc
->cmdsize
);
2439 if(st
== NULL
|| dyst
== NULL
){
2441 Mach_O_error(ofile
, "MH_DYLIB format error (does not have a symbol "
2442 "table and/or a dynamic symbol table)");
2446 if(dyst
->nmodtab
== 0)
2449 ofile
->nmodtab
= dyst
->nmodtab
;
2450 host_byte_sex
= get_host_byte_sex();
2451 swapped
= (enum bool)(host_byte_sex
!= ofile
->object_byte_sex
);
2452 strings
= (char *)(ofile
->object_addr
+ st
->stroff
);
2454 if(ofile
->mh
!= NULL
){
2455 ofile
->modtab
= (struct dylib_module
*)(ofile
->object_addr
+
2457 ofile
->dylib_module
= ofile
->modtab
;
2458 m
= *ofile
->dylib_module
;
2460 swap_dylib_module(&m
, 1, host_byte_sex
);
2461 ofile
->dylib_module_name
= strings
+ m
.module_name
;
2464 ofile
->modtab64
= (struct dylib_module_64
*)(ofile
->object_addr
+
2466 ofile
->dylib_module64
= ofile
->modtab64
;
2467 m64
= *ofile
->dylib_module64
;
2469 swap_dylib_module_64(&m64
, 1, host_byte_sex
);
2470 ofile
->dylib_module_name
= strings
+ m64
.module_name
;
2473 if(check_dylib_module(ofile
, st
, dyst
, strings
, 0) == CHECK_BAD
)
2479 * ofile_next_module() set up the ofile structure (the dylib_module field)
2480 * for the next module of an MH_DYLIB or MH_DYLIB_STUB file.
2485 struct ofile
*ofile
)
2487 uint32_t i
, module_index
, ncmds
;
2488 struct symtab_command
*st
;
2489 struct dysymtab_command
*dyst
;
2490 struct load_command
*lc
;
2492 enum byte_sex host_byte_sex
;
2493 struct dylib_module m
;
2494 struct dylib_module_64 m64
;
2497 if(ofile
->file_type
== OFILE_FAT
){
2498 if(ofile
->arch_type
!= OFILE_Mach_O
&&
2499 (ofile
->mh_filetype
!= MH_DYLIB
&&
2500 ofile
->mh_filetype
!= MH_DYLIB_STUB
)){
2501 error("ofile_next_module() called on fat file: %s with a "
2502 "non-MH_DYLIB architecture or no architecture selected\n",
2507 else if(ofile
->arch_type
!= OFILE_Mach_O
&&
2508 (ofile
->mh_filetype
!= MH_DYLIB
&&
2509 ofile
->mh_filetype
!= MH_DYLIB_STUB
)){
2510 error("ofile_next_module() called and file type of %s is "
2511 "non-MH_DYLIB\n", ofile
->file_name
);
2516 lc
= ofile
->load_commands
;
2517 if(ofile
->mh
!= NULL
)
2518 ncmds
= ofile
->mh
->ncmds
;
2520 ncmds
= ofile
->mh64
->ncmds
;
2521 for(i
= 0; i
< ncmds
; i
++){
2522 if(st
== NULL
&& lc
->cmd
== LC_SYMTAB
){
2523 st
= (struct symtab_command
*)lc
;
2525 else if(lc
->cmd
== LC_DYSYMTAB
){
2526 dyst
= (struct dysymtab_command
*)lc
;
2528 lc
= (struct load_command
*)((char *)lc
+ lc
->cmdsize
);
2530 if(st
== NULL
|| dyst
== NULL
){
2532 Mach_O_error(ofile
, "MH_DYLIB format error (does not have a symbol "
2533 "table and/or a dynamic symbol table)");
2538 if(ofile
->mh
!= NULL
)
2539 module_index
= (ofile
->dylib_module
+ 1) - ofile
->modtab
;
2541 module_index
= (ofile
->dylib_module64
+ 1) - ofile
->modtab64
;
2542 if(module_index
>= ofile
->nmodtab
)
2545 host_byte_sex
= get_host_byte_sex();
2546 swapped
= (enum bool)(host_byte_sex
!= ofile
->object_byte_sex
);
2547 strings
= (char *)(ofile
->object_addr
+ st
->stroff
);
2549 if(ofile
->mh
!= NULL
){
2550 ofile
->dylib_module
++;
2551 m
= *ofile
->dylib_module
;
2553 swap_dylib_module(&m
, 1, host_byte_sex
);
2554 ofile
->dylib_module_name
= strings
+ m
.module_name
;
2557 ofile
->dylib_module64
++;
2558 m64
= *ofile
->dylib_module64
;
2560 swap_dylib_module_64(&m64
, 1, host_byte_sex
);
2561 ofile
->dylib_module_name
= strings
+ m64
.module_name
;
2563 if(check_dylib_module(ofile
, st
, dyst
, strings
, module_index
) ==
2570 * ofile_specific_module() set up the ofile structure (the dylib_module fields)
2571 * for the specified module, module_name, of an MH_DYLIB or an MH_DYLIB_STUB
2576 ofile_specific_module(
2577 const char *module_name
,
2578 struct ofile
*ofile
)
2582 enum byte_sex host_byte_sex
;
2583 struct symtab_command
*st
;
2584 struct dysymtab_command
*dyst
;
2585 struct load_command
*lc
;
2586 struct dylib_module
*p
, m
;
2587 struct dylib_module_64
*p64
, m64
;
2590 /* These fields are to be filled in by this routine, clear them first */
2591 ofile
->modtab
= NULL
;
2592 ofile
->modtab64
= NULL
;
2594 ofile
->dylib_module
= NULL
;
2595 ofile
->dylib_module64
= NULL
;
2596 ofile
->dylib_module_name
= NULL
;
2598 if(ofile
->file_type
== OFILE_FAT
){
2599 if(ofile
->arch_type
!= OFILE_Mach_O
&&
2600 (ofile
->mh_filetype
!= MH_DYLIB
&&
2601 ofile
->mh_filetype
!= MH_DYLIB_STUB
)){
2602 error("ofile_specific_module() called on fat file: %s with a "
2603 "non-MH_DYLIB architecture or no architecture selected\n",
2608 else if(ofile
->arch_type
!= OFILE_Mach_O
&&
2609 (ofile
->mh_filetype
!= MH_DYLIB
&&
2610 ofile
->mh_filetype
!= MH_DYLIB_STUB
)){
2611 error("ofile_specific_module() called and file type of %s is "
2612 "non-MH_DYLIB\n", ofile
->file_name
);
2618 lc
= ofile
->load_commands
;
2619 if(ofile
->mh
!= NULL
)
2620 ncmds
= ofile
->mh
->ncmds
;
2622 ncmds
= ofile
->mh64
->ncmds
;
2623 for(i
= 0; i
< ncmds
; i
++){
2624 if(st
== NULL
&& lc
->cmd
== LC_SYMTAB
){
2625 st
= (struct symtab_command
*)lc
;
2627 else if(lc
->cmd
== LC_DYSYMTAB
){
2628 dyst
= (struct dysymtab_command
*)lc
;
2630 lc
= (struct load_command
*)((char *)lc
+ lc
->cmdsize
);
2632 if(st
== NULL
|| dyst
== NULL
){
2634 Mach_O_error(ofile
, "MH_DYLIB format error (does not have a symbol "
2635 "table and/or a dynamic symbol table)");
2639 if(dyst
->nmodtab
== 0)
2642 host_byte_sex
= get_host_byte_sex();
2643 swapped
= (enum bool)(host_byte_sex
!= ofile
->object_byte_sex
);
2644 strings
= (char *)(ofile
->object_addr
+ st
->stroff
);
2646 if(ofile
->mh
!= NULL
){
2647 ofile
->nmodtab
= dyst
->nmodtab
;
2648 ofile
->modtab
= (struct dylib_module
*)(ofile
->object_addr
+
2651 for(i
= 0; i
< dyst
->nmodtab
; i
++){
2654 swap_dylib_module(&m
, 1, host_byte_sex
);
2655 ofile
->dylib_module
= p
;
2656 if(check_dylib_module(ofile
, st
, dyst
, strings
, i
) == CHECK_BAD
)
2658 if(strcmp(module_name
, strings
+ m
.module_name
) == 0){
2659 ofile
->dylib_module_name
= strings
+ m
.module_name
;
2664 m
= *ofile
->dylib_module
;
2666 swap_dylib_module(&m
, 1, host_byte_sex
);
2667 ofile
->dylib_module_name
= strings
+ m
.module_name
;
2670 ofile
->nmodtab
= dyst
->nmodtab
;
2671 ofile
->modtab64
= (struct dylib_module_64
*)(ofile
->object_addr
+
2673 p64
= ofile
->modtab64
;
2674 for(i
= 0; i
< dyst
->nmodtab
; i
++){
2677 swap_dylib_module_64(&m64
, 1, host_byte_sex
);
2678 ofile
->dylib_module64
= p64
;
2679 if(check_dylib_module(ofile
, st
, dyst
, strings
, i
) == CHECK_BAD
)
2681 if(strcmp(module_name
, strings
+ m64
.module_name
) == 0){
2682 ofile
->dylib_module_name
= strings
+ m64
.module_name
;
2687 m64
= *ofile
->dylib_module64
;
2689 swap_dylib_module_64(&m64
, 1, host_byte_sex
);
2690 ofile
->dylib_module_name
= strings
+ m64
.module_name
;
2693 Mach_O_error(ofile
, "does not contain a module named: %s", module_name
);
2695 ofile
->modtab
= NULL
;
2697 ofile
->dylib_module
= NULL
;
2698 ofile
->dylib_module_name
= NULL
;
2706 struct ofile
*ofile
)
2708 printf("file_name = %s\n", ofile
->file_name
);
2709 printf("file_addr = 0x%x\n", (unsigned int)ofile
->file_addr
);
2710 printf("file_size = 0x%x\n", (unsigned int)ofile
->file_size
);
2711 printf("file_type = 0x%x\n", (unsigned int)ofile
->file_type
);
2712 printf("fat_header = 0x%x\n", (unsigned int)ofile
->fat_header
);
2713 printf("fat_archs = 0x%x\n", (unsigned int)ofile
->fat_archs
);
2714 printf("narch = 0x%x\n", (unsigned int)ofile
->narch
);
2715 printf("arch_type = 0x%x\n", (unsigned int)ofile
->arch_type
);
2716 printf("arch_flag.name = %s\n", ofile
->arch_flag
.name
);
2717 printf("arch_flag.cputype = 0x%x\n",
2718 (unsigned int)ofile
->arch_flag
.cputype
);
2719 printf("arch_flag.cpusubtype = 0x%x\n",
2720 (unsigned int)ofile
->arch_flag
.cpusubtype
);
2721 printf("member_offset = 0x%x\n", (unsigned int)ofile
->member_offset
);
2722 printf("member_addr = 0x%x\n", (unsigned int)ofile
->member_addr
);
2723 printf("member_size = 0x%x\n", (unsigned int)ofile
->member_size
);
2724 printf("member_ar_hdr = 0x%x\n", (unsigned int)ofile
->member_ar_hdr
);
2725 printf("member_type = 0x%x\n", (unsigned int)ofile
->member_type
);
2726 printf("archive_cputype = 0x%x\n",
2727 (unsigned int)ofile
->archive_cputype
);
2728 printf("archive_cpusubtype = 0x%x\n",
2729 (unsigned int)ofile
->archive_cpusubtype
);
2730 printf("object_addr = 0x%x\n", (unsigned int)ofile
->object_addr
);
2731 printf("object_size = 0x%x\n", (unsigned int)ofile
->object_size
);
2732 printf("object_byte_sex = 0x%x\n",
2733 (unsigned int)ofile
->object_byte_sex
);
2734 printf("mh = 0x%x\n", (unsigned int)ofile
->mh
);
2735 printf("mh64 = 0x%x\n", (unsigned int)ofile
->mh64
);
2736 printf("load_commands = 0x%x\n", (unsigned int)ofile
->load_commands
);
2741 * check_fat() checks the fat ofile for correctness (the fat_header and
2742 * fat_archs are assumed to be in the host byte sex).
2747 struct ofile
*ofile
)
2751 #else /* !defined OTOOL */
2756 if(ofile
->file_type
!= OFILE_FAT
){
2757 error("internal error. check_fat() call and file type of: %s is "
2758 "not OFILE_FAT\n", ofile
->file_name
);
2761 if(ofile
->fat_header
->nfat_arch
== 0){
2762 error("fat file: %s malformed (contains zero architecture types)",
2766 for(i
= 0; i
< ofile
->fat_header
->nfat_arch
; i
++){
2767 big_size
= ofile
->fat_archs
[i
].offset
;
2768 big_size
+= ofile
->fat_archs
[i
].size
;
2769 if(big_size
> ofile
->file_size
){
2770 error("fat file: %s truncated or malformed (offset plus size "
2771 "of cputype (%d) cpusubtype (%d) extends past the "
2772 "end of the file)", ofile
->file_name
,
2773 ofile
->fat_archs
[i
].cputype
,
2774 ofile
->fat_archs
[i
].cpusubtype
& ~CPU_SUBTYPE_MASK
);
2777 if(ofile
->fat_archs
[i
].align
> MAXSECTALIGN
){
2778 error("fat file: %s align (2^%u) too large for cputype (%d) "
2779 "cpusubtype (%d) (maximum 2^%d)", ofile
->file_name
,
2780 ofile
->fat_archs
[i
].align
, ofile
->fat_archs
[i
].cputype
,
2781 ofile
->fat_archs
[i
].cpusubtype
& ~CPU_SUBTYPE_MASK
,
2785 if(ofile
->fat_archs
[i
].offset
%
2786 (1 << ofile
->fat_archs
[i
].align
) != 0){
2787 error("fat file: %s offset: %u for cputype (%d) cpusubtype "
2788 "(%d)) not aligned on it's alignment (2^%u)",
2790 ofile
->fat_archs
[i
].offset
,
2791 ofile
->fat_archs
[i
].cputype
,
2792 ofile
->fat_archs
[i
].cpusubtype
& ~CPU_SUBTYPE_MASK
,
2793 ofile
->fat_archs
[i
].align
);
2797 for(i
= 0; i
< ofile
->fat_header
->nfat_arch
; i
++){
2798 for(j
= i
+ 1; j
< ofile
->fat_header
->nfat_arch
; j
++){
2799 if(ofile
->fat_archs
[i
].cputype
==
2800 ofile
->fat_archs
[j
].cputype
&&
2801 (ofile
->fat_archs
[i
].cpusubtype
& ~CPU_SUBTYPE_MASK
) ==
2802 (ofile
->fat_archs
[j
].cpusubtype
& ~CPU_SUBTYPE_MASK
)){
2803 error("fat file: %s contains two of the same "
2804 "architecture (cputype (%d) cpusubtype (%d))",
2805 ofile
->file_name
, ofile
->fat_archs
[i
].cputype
,
2806 ofile
->fat_archs
[i
].cpusubtype
& ~CPU_SUBTYPE_MASK
);
2816 * check_fat_object_in_archive() checks the fat object file which is a member
2817 * of a thin archive for correctness (the fat_header and fat_archs are assumed
2818 * to be in the host byte sex). This is not a legal form but allowed when
2819 * archives_with_fat_objects is TRUE when ofile_map() is called.
2823 check_fat_object_in_archive(
2824 struct ofile
*ofile
)
2829 if(ofile
->file_type
!= OFILE_ARCHIVE
){
2830 error("internal error. check_fat_object_in_archive() called and "
2831 "file type of: %s is not OFILE_ARCHIVE\n", ofile
->file_name
);
2834 if(ofile
->fat_header
->nfat_arch
== 0){
2835 archive_member_error(ofile
, "fat file malformed (contains zero "
2836 "architecture types)");
2839 for(i
= 0; i
< ofile
->fat_header
->nfat_arch
; i
++){
2840 if(ofile
->fat_archs
[i
].offset
+ ofile
->fat_archs
[i
].size
>
2841 ofile
->member_size
){
2842 archive_member_error(ofile
, "fat file truncated or malformed "
2843 "(offset plus size of cputype (%d) cpusubtype (%d) "
2844 "extends past the end of the file)",
2845 ofile
->fat_archs
[i
].cputype
,
2846 ofile
->fat_archs
[i
].cpusubtype
& ~CPU_SUBTYPE_MASK
);
2849 if(ofile
->fat_archs
[i
].align
> MAXSECTALIGN
){
2850 archive_member_error(ofile
, "fat file's align (2^%u) too "
2851 "large for cputype (%d) cpusubtype (%d) (maximum 2^%d)",
2852 ofile
->fat_archs
[i
].align
, ofile
->fat_archs
[i
].cputype
,
2853 ofile
->fat_archs
[i
].cpusubtype
& ~CPU_SUBTYPE_MASK
,
2857 if(ofile
->fat_archs
[i
].offset
%
2858 (1 << ofile
->fat_archs
[i
].align
) != 0){
2859 archive_member_error(ofile
, "fat file's offset: %u for "
2860 "cputype (%d) cpusubtype (%d) not aligned on it's "
2861 "alignment (2^%u)", ofile
->fat_archs
[i
].offset
,
2862 ofile
->fat_archs
[i
].cputype
,
2863 ofile
->fat_archs
[i
].cpusubtype
& ~CPU_SUBTYPE_MASK
,
2864 ofile
->fat_archs
[i
].align
);
2869 * The only supported format where fat files are allowed to appear
2870 * in archives is when the fat file contains only object files.
2872 if(ofile
->fat_archs
[i
].size
< sizeof(struct mach_header
)){
2873 archive_member_error(ofile
, "fat file for cputype (%d) "
2874 "cpusubtype (%d) is not an object file (size too small "
2875 "to be an object file)", ofile
->fat_archs
[i
].cputype
,
2876 ofile
->fat_archs
[i
].cpusubtype
& ~CPU_SUBTYPE_MASK
);
2880 ofile
->file_addr
+ ofile
->member_offset
+
2881 ofile
->fat_archs
[i
].offset
,
2883 if(magic
== MH_MAGIC
|| magic
== SWAP_INT(MH_MAGIC
)){
2884 #ifdef ALIGNMENT_CHECKS
2885 if((ofile
->member_offset
+ ofile
->fat_archs
[i
].offset
) %
2887 archive_member_error(ofile
, "fat object file's offset in "
2888 "archive not a multiple of 4) (must be since "
2889 "member is a 32-bit object file)");
2892 #endif /* ALIGNMENT_CHECKS */
2894 else if(magic
== MH_MAGIC_64
|| magic
== SWAP_INT(MH_MAGIC_64
)){
2895 #ifdef ALIGNMENT_CHECKS_ARCHIVE_64_BIT
2896 if(archive_64_bit_align_warning
== FALSE
&&
2897 (ofile
->member_offset
+ ofile
->fat_archs
[i
].offset
) %
2899 temporary_archive_member_warning(ofile
, "fat object file's "
2900 "offset in archive not a multiple of 8) (must be since "
2901 "member is a 64-bit object file)");
2902 archive_64_bit_align_warning
= TRUE
;
2903 /* return(CHECK_BAD); */
2905 #endif /* ALIGNMENT_CHECKS_ARCHIVE_64_BIT */
2908 archive_member_error(ofile
, "fat file for cputype (%d) "
2909 "cpusubtype (%d) is not an object file (bad magic "
2910 "number)", ofile
->fat_archs
[i
].cputype
,
2911 ofile
->fat_archs
[i
].cpusubtype
& ~CPU_SUBTYPE_MASK
);
2915 for(i
= 0; i
< ofile
->fat_header
->nfat_arch
; i
++){
2916 for(j
= i
+ 1; j
< ofile
->fat_header
->nfat_arch
; j
++){
2917 if(ofile
->fat_archs
[i
].cputype
==
2918 ofile
->fat_archs
[j
].cputype
&&
2919 (ofile
->fat_archs
[i
].cpusubtype
& ~CPU_SUBTYPE_MASK
) ==
2920 (ofile
->fat_archs
[j
].cpusubtype
& ~CPU_SUBTYPE_MASK
)){
2921 archive_member_error(ofile
, "fat file contains two of the "
2922 "same architecture (cputype (%d) cpusubtype (%d))",
2923 ofile
->fat_archs
[i
].cputype
,
2924 ofile
->fat_archs
[i
].cpusubtype
& ~CPU_SUBTYPE_MASK
);
2933 * check_archive() checks the archive referenced in the ofile for correctness.
2938 struct ofile
*ofile
,
2939 enum bool archives_with_fat_objects
)
2943 #else /* !defined OTOOL */
2945 uint32_t size
, offset
;
2948 enum byte_sex host_byte_sex
;
2950 struct mach_header mh
;
2951 struct mach_header_64 mh64
;
2952 struct ar_hdr
*ar_hdr
;
2953 uint32_t ar_name_size
;
2956 * Get the address and size of the archive (as well as the cputype and
2957 * cpusubtype if known) and make sure it is an archive.
2959 if(ofile
->file_type
== OFILE_FAT
){
2960 addr
= ofile
->file_addr
+ ofile
->fat_archs
[ofile
->narch
].offset
;
2961 size
= ofile
->fat_archs
[ofile
->narch
].size
;
2962 ofile
->archive_cputype
= ofile
->fat_archs
[ofile
->narch
].cputype
;
2963 ofile
->archive_cpusubtype
=
2964 ofile
->fat_archs
[ofile
->narch
].cpusubtype
;
2966 else if(ofile
->file_type
== OFILE_ARCHIVE
){
2967 addr
= ofile
->file_addr
;
2968 size
= ofile
->file_size
;
2969 ofile
->archive_cputype
= 0;
2970 ofile
->archive_cpusubtype
= 0;
2973 error("internal error. check_archive() call and file type of %s is "
2974 "OFILE_UNKNOWN\n", ofile
->file_name
);
2977 if(size
< SARMAG
|| strncmp(addr
, ARMAG
, SARMAG
) != 0){
2978 error("internal error. check_archive() call for file %s which does "
2979 "not have an archive magic string", ofile
->file_name
);
2983 host_byte_sex
= get_host_byte_sex();
2985 * Check this archive out to make sure that it does not contain
2986 * any fat files and that all object files it contains have the
2987 * same cputype and subsubtype.
2992 if(offset
!= size
&& offset
+ sizeof(struct ar_hdr
) > size
){
2993 archive_error(ofile
, "truncated or malformed (archive header of "
2994 "first member extends past the end of the file)");
2997 while(size
> offset
){
2998 ar_hdr
= (struct ar_hdr
*)(addr
+ offset
);
2999 ofile
->member_offset
= offset
;
3000 ofile
->member_addr
= addr
+ offset
;
3001 ofile
->member_size
= strtoul(ar_hdr
->ar_size
, NULL
, 10);
3002 ofile
->member_ar_hdr
= ar_hdr
;
3003 ofile
->member_name
= ar_hdr
->ar_name
;
3004 ofile
->member_name_size
= size_ar_name(ofile
->member_ar_hdr
);
3005 offset
+= sizeof(struct ar_hdr
);
3007 * See if this archive member is using extend format #1 where
3008 * the size of the name is in ar_name and the name follows the
3012 if(strncmp(ofile
->member_name
,AR_EFMT1
, sizeof(AR_EFMT1
) - 1) == 0){
3013 if(check_extend_format_1(ofile
, ar_hdr
, size
- offset
,
3014 &ar_name_size
) == CHECK_BAD
)
3016 ofile
->member_name
= ar_hdr
->ar_name
+ sizeof(struct ar_hdr
);
3017 ofile
->member_name_size
= ar_name_size
;
3018 offset
+= ar_name_size
;
3019 ofile
->member_offset
+= ar_name_size
;
3020 ofile
->member_addr
+= ar_name_size
;
3021 ofile
->member_size
-= ar_name_size
;
3023 big_size
= rnd(ofile
->member_size
, sizeof(short));
3025 if(big_size
> size
){
3026 archive_member_error(ofile
, "size too large (archive "
3027 "member extends past the end of the file)");
3030 if(size
- offset
> sizeof(uint32_t)){
3031 memcpy(&magic
, addr
+ offset
, sizeof(uint32_t));
3032 #ifdef __BIG_ENDIAN__
3033 if(magic
== FAT_MAGIC
)
3034 #endif /* __BIG_ENDIAN__ */
3035 #ifdef __LITTLE_ENDIAN__
3036 if(magic
== SWAP_INT(FAT_MAGIC
))
3037 #endif /* __LITTLE_ENDIAN__ */
3039 if(archives_with_fat_objects
== FALSE
||
3040 ofile
->file_type
!= OFILE_ARCHIVE
){
3041 archive_member_error(ofile
, "is a fat file (not "
3042 "allowed in an archive)");
3047 if(size
- offset
>= sizeof(struct mach_header
) &&
3048 (magic
== MH_MAGIC
|| magic
== SWAP_INT(MH_MAGIC
))){
3049 memcpy(&mh
, addr
+ offset
, sizeof(struct mach_header
));
3050 if(magic
== SWAP_INT(MH_MAGIC
)){
3053 swap_mach_header(&mh
, host_byte_sex
);
3057 else if(size
- offset
>= sizeof(struct mach_header_64
) &&
3058 (magic
== MH_MAGIC_64
||
3059 magic
== SWAP_INT(MH_MAGIC_64
))){
3060 memcpy(&mh64
, addr
+ offset
,
3061 sizeof(struct mach_header_64
));
3062 if(magic
== SWAP_INT(MH_MAGIC_64
)){
3063 magic
= MH_MAGIC_64
;
3065 swap_mach_header_64(&mh64
, host_byte_sex
);
3069 if(magic
== MH_MAGIC
){
3070 if(ofile
->archive_cputype
== 0){
3071 ofile
->archive_cputype
= mh
.cputype
;
3072 ofile
->archive_cpusubtype
= mh
.cpusubtype
;
3074 else if(ofile
->archive_cputype
!= mh
.cputype
){
3075 archive_member_error(ofile
, "cputype (%d) does not "
3076 "match previous archive members cputype (%d) "
3077 "(all members must match)", mh
.cputype
,
3078 ofile
->archive_cputype
);
3081 else if(magic
== MH_MAGIC_64
){
3082 if(ofile
->archive_cputype
== 0){
3083 ofile
->archive_cputype
= mh64
.cputype
;
3084 ofile
->archive_cpusubtype
= mh64
.cpusubtype
;
3086 else if(ofile
->archive_cputype
!= mh64
.cputype
){
3087 archive_member_error(ofile
, "cputype (%d) does not "
3088 "match previous archive members cputype (%d) "
3089 "(all members must match)", mh64
.cputype
,
3090 ofile
->archive_cputype
);
3095 offset
+= rnd(ofile
->member_size
, sizeof(short));
3097 ofile
->member_offset
= 0;
3098 ofile
->member_addr
= NULL
;
3099 ofile
->member_size
= 0;
3100 ofile
->member_ar_hdr
= NULL
;;
3101 ofile
->member_name
= NULL
;
3102 ofile
->member_name_size
= 0;
3108 * check_extend_format_1() checks the archive header for extended format #1.
3112 check_extend_format_1(
3113 struct ofile
*ofile
,
3114 struct ar_hdr
*ar_hdr
,
3116 uint32_t *member_name_size
)
3118 char *p
, *endp
, buf
[sizeof(ar_hdr
->ar_name
)+1];
3119 uint32_t ar_name_size
;
3121 *member_name_size
= 0;
3123 buf
[sizeof(ar_hdr
->ar_name
)] = '\0';
3124 memcpy(buf
, ar_hdr
->ar_name
, sizeof(ar_hdr
->ar_name
));
3125 p
= buf
+ sizeof(AR_EFMT1
) - 1;
3126 if(isdigit(*p
) == 0){
3127 archive_error(ofile
, "malformed (ar_name: %.*s for archive "
3128 "extend format #1 starts with non-digit)",
3129 (int)sizeof(ar_hdr
->ar_name
), ar_hdr
->ar_name
);
3132 ar_name_size
= strtoul(p
, &endp
, 10);
3133 if(ar_name_size
== UINT_MAX
&& errno
== ERANGE
){
3134 archive_error(ofile
, "malformed (size in ar_name: %.*s for "
3135 "archive extend format #1 overflows uint32_t)",
3136 (int)sizeof(ar_hdr
->ar_name
), ar_hdr
->ar_name
);
3139 while(*endp
== ' ' && *endp
!= '\0')
3142 archive_error(ofile
, "malformed (size in ar_name: %.*s for "
3143 "archive extend format #1 contains non-digit and "
3144 "non-space characters)", (int)sizeof(ar_hdr
->ar_name
),
3148 if(ar_name_size
> size_left
){
3149 archive_error(ofile
, "truncated or malformed (archive name "
3150 "of member extends past the end of the file)");
3153 *member_name_size
= ar_name_size
;
3158 * check_archive_toc() checks the archive table of contents referenced in the
3159 * thin archive via the ofile for correctness and if bad sets the bad_toc field
3160 * in the ofile struct to TRUE. If not it sets the other toc_* fields that
3161 * ranlib(1) uses to know it can't update the table of contents and doesn't
3162 * have to totally rebuild it. And by this always returning CHECK_GOOD it
3163 * allows otool(1) to print messed up tables of contents for debugging.
3168 struct ofile
*ofile
)
3170 uint32_t i
, symdef_length
, offset
, nranlibs
, strsize
;
3171 enum byte_sex host_byte_sex
, toc_byte_sex
;
3172 struct ranlib
*ranlibs
;
3175 ofile
->toc_ranlibs
= NULL
;
3176 ofile
->toc_nranlibs
= 0;
3177 ofile
->toc_strings
= NULL
;
3178 ofile
->toc_strsize
= 0;
3181 * Note this can only be called when the whole file is a thin archive.
3183 if(ofile
->file_type
!= OFILE_ARCHIVE
)
3186 symdef_length
= ofile
->toc_size
;
3188 * The contents of a __.SYMDEF file is begins with a 32-bit word giving
3189 * the size in bytes of ranlib structures which immediately follow, and
3190 * then continues with a string table consisting of a 32-bit word giving
3191 * the number of bytes of strings which follow and then the strings
3192 * themselves. So the smallest valid size is two 32-bit words long.
3194 if(symdef_length
< 2 * sizeof(uint32_t)){
3196 * Size of table of contents for archive too small to be a valid
3197 * table of contents.
3199 ofile
->toc_bad
= TRUE
;
3202 host_byte_sex
= get_host_byte_sex();
3203 toc_byte_sex
= get_toc_byte_sex(ofile
->file_addr
, ofile
->file_size
);
3204 if(toc_byte_sex
== UNKNOWN_BYTE_SEX
){
3206 * Can't determine the byte order of table of contents as it
3207 * contains no Mach-O files.
3209 ofile
->toc_bad
= TRUE
;
3213 nranlibs
= *((uint32_t *)(ofile
->toc_addr
+ offset
));
3214 if(toc_byte_sex
!= host_byte_sex
)
3215 nranlibs
= SWAP_INT(nranlibs
);
3216 nranlibs
= nranlibs
/ sizeof(struct ranlib
);
3217 offset
+= sizeof(uint32_t);
3218 ranlibs
= (struct ranlib
*)(ofile
->toc_addr
+ offset
);
3219 offset
+= sizeof(struct ranlib
) * nranlibs
;
3222 if(offset
- (2 * sizeof(uint32_t)) > symdef_length
){
3224 * Truncated or malformed archive. The ranlib structures in table
3225 * of contents extends past the end of the table of contents.
3227 ofile
->toc_bad
= TRUE
;
3230 strsize
= *((uint32_t *)(ofile
->toc_addr
+ offset
));
3231 if(toc_byte_sex
!= host_byte_sex
)
3232 strsize
= SWAP_INT(strsize
);
3233 offset
+= sizeof(uint32_t);
3234 strings
= ofile
->toc_addr
+ offset
;
3236 if(offset
- (2 * sizeof(uint32_t)) > symdef_length
){
3238 * Truncated or malformed archive. The ranlib strings in table of
3239 * contents extends past the end of the table of contents.
3241 ofile
->toc_bad
= TRUE
;
3244 if(symdef_length
== 2 * sizeof(uint32_t))
3248 * Check the string offset and the member offsets of the ranlib structs.
3250 if(toc_byte_sex
!= host_byte_sex
)
3251 swap_ranlib(ranlibs
, nranlibs
, host_byte_sex
);
3252 for(i
= 0; i
< nranlibs
; i
++){
3253 if(ranlibs
[i
].ran_un
.ran_strx
>= strsize
){
3255 * Malformed table of contents. The ranlib struct at this index
3256 * has a bad string index field.
3258 ofile
->toc_bad
= TRUE
;
3261 if(ranlibs
[i
].ran_off
>= ofile
->file_size
){
3263 * Malformed table of contents. The ranlib struct at this index
3264 * has a bad library member offset field.
3266 ofile
->toc_bad
= TRUE
;
3270 * These should be on 4 byte boundaries because the maximum
3271 * alignment of the header structures and relocation are 4 bytes.
3272 * But this is has to be 2 bytes because that's the way ar(1) has
3273 * worked historicly in the past. Fortunately this works on the
3274 * 68k machines but will have to change when this is on a real
3277 #if defined(mc68000) || defined(__i386__)
3278 if(ranlibs
[i
].ran_off
% sizeof(short) != 0){
3280 * Malformed table of contents. This ranlib struct library
3281 * member offset not a multiple 2 bytes.
3283 ofile
->toc_bad
= TRUE
;
3287 if(ranlibs
[i
].ran_off
% sizeof(uint32_t) != 0){
3289 * Malformed table of contents. This ranlib struct library
3290 * member offset not a multiple of 4 bytes.
3292 ofile
->toc_bad
= TRUE
;
3297 ofile
->toc_ranlibs
= ranlibs
;
3298 ofile
->toc_nranlibs
= nranlibs
;
3299 ofile
->toc_strings
= strings
;
3300 ofile
->toc_strsize
= strsize
;
3305 * check_Mach_O() checks the object file's mach header and load commands
3306 * referenced in the ofile for correctness (this also swaps the mach header
3307 * and load commands into the host byte sex if needed).
3312 struct ofile
*ofile
)
3316 #else /* !defined OTOOL */
3317 uint32_t size
, i
, j
, ncmds
, sizeofcmds
, load_command_multiple
, sizeofhdrs
;
3319 char *addr
, *cmd_name
, *element_name
;
3320 enum byte_sex host_byte_sex
;
3322 struct mach_header
*mh
;
3323 struct mach_header_64
*mh64
;
3324 struct load_command
*load_commands
, *lc
, l
;
3325 struct segment_command
*sg
;
3326 struct segment_command_64
*sg64
;
3328 struct section_64
*s64
;
3329 struct symtab_command
*st
;
3330 struct dysymtab_command
*dyst
;
3331 struct symseg_command
*ss
;
3332 struct fvmlib_command
*fl
;
3333 struct dylib_command
*dl
;
3334 struct sub_framework_command
*sub
;
3335 struct sub_umbrella_command
*usub
;
3336 struct sub_library_command
*lsub
;
3337 struct sub_client_command
*csub
;
3338 struct prebound_dylib_command
*pbdylib
;
3339 struct dylinker_command
*dyld
;
3340 struct thread_command
*ut
;
3341 struct ident_command
*id
;
3342 struct routines_command
*rc
;
3343 struct routines_command_64
*rc64
;
3344 struct twolevel_hints_command
*hints
;
3345 struct linkedit_data_command
*code_sig
, *split_info
, *func_starts
,
3346 *data_in_code
, *code_sign_drs
, *linkedit_data
;
3347 struct version_min_command
*vers
;
3348 struct prebind_cksum_command
*cs
;
3349 struct encryption_info_command
*encrypt_info
;
3350 struct dyld_info_command
*dyld_info
;
3351 struct uuid_command
*uuid
;
3352 struct rpath_command
*rpath
;
3353 struct entry_point_command
*ep
;
3354 struct source_version_command
*sv
;
3355 uint32_t flavor
, count
, nflavor
;
3357 uint32_t sizeof_nlist
, sizeof_dylib_module
;
3358 char *struct_dylib_module_name
, *struct_nlist_name
;
3359 uint64_t big_size
, big_end
, big_load_end
;
3360 struct element elements
;
3362 elements
.offset
= 0;
3364 elements
.name
= NULL
;
3365 elements
.next
= NULL
;
3367 addr
= ofile
->object_addr
;
3368 size
= ofile
->object_size
;
3371 load_commands
= ofile
->load_commands
;
3372 host_byte_sex
= get_host_byte_sex();
3373 swapped
= (enum bool)(host_byte_sex
!= ofile
->object_byte_sex
);
3375 if(ofile
->mh
!= NULL
){
3377 swap_mach_header(mh
, host_byte_sex
);
3378 big_size
= mh
->sizeofcmds
;
3379 big_size
+= sizeof(struct mach_header
);
3380 if(big_size
> size
){
3381 Mach_O_error(ofile
, "truncated or malformed object (load "
3382 "commands extend past the end of the file)");
3385 sizeofhdrs
= big_size
;
3386 ofile
->mh_cputype
= mh
->cputype
;
3387 ofile
->mh_cpusubtype
= mh
->cpusubtype
;
3388 ofile
->mh_filetype
= mh
->filetype
;
3390 sizeofcmds
= mh
->sizeofcmds
;
3391 cputype
= mh
->cputype
;
3392 load_command_multiple
= 4;
3393 sizeof_nlist
= sizeof(struct nlist
);
3394 struct_nlist_name
= "struct nlist";
3395 sizeof_dylib_module
= sizeof(struct dylib_module
);
3396 struct_dylib_module_name
= "struct dylib_module";
3400 swap_mach_header_64(mh64
, host_byte_sex
);
3401 big_size
= mh64
->sizeofcmds
;
3402 big_size
+= sizeof(struct mach_header_64
);
3403 if(big_size
> size
){
3404 Mach_O_error(ofile
, "truncated or malformed object (load "
3405 "commands extend past the end of the file)");
3408 sizeofhdrs
= big_size
;
3409 ofile
->mh_cputype
= mh64
->cputype
;
3410 ofile
->mh_cpusubtype
= mh64
->cpusubtype
;
3411 ofile
->mh_filetype
= mh64
->filetype
;
3412 ncmds
= mh64
->ncmds
;
3413 sizeofcmds
= mh64
->sizeofcmds
;
3414 cputype
= mh64
->cputype
;
3415 load_command_multiple
= 8;
3416 sizeof_nlist
= sizeof(struct nlist_64
);
3417 struct_nlist_name
= "struct nlist_64";
3418 sizeof_dylib_module
= sizeof(struct dylib_module_64
);
3419 struct_dylib_module_name
= "struct dylib_module_64";
3421 if(check_overlaping_element(ofile
, &elements
, 0, sizeofhdrs
,
3422 "Mach-O headers") == CHECK_BAD
)
3424 if(ofile
->file_type
== OFILE_FAT
){
3425 if(ofile
->fat_archs
[ofile
->narch
].cputype
!= ofile
->mh_cputype
){
3426 Mach_O_error(ofile
, "malformed fat file (fat header "
3427 "architecture: %u's cputype does not match "
3428 "object file's mach header)", ofile
->narch
);
3433 * Make a pass through the load commands checking them to the level
3434 * that they can be parsed and all fields with offsets and sizes do
3435 * not extend past the end of the file.
3444 data_in_code
= NULL
;
3445 code_sign_drs
= NULL
;
3449 encrypt_info
= NULL
;
3453 for(i
= 0, lc
= load_commands
; i
< ncmds
; i
++){
3456 swap_load_command(&l
, host_byte_sex
);
3458 * Check load command size for a multiple of load_command_multiple.
3460 if(l
.cmdsize
% load_command_multiple
!= 0){
3462 * We have a hack here to allow 64-bit Mach-O core files to
3463 * have LC_THREAD commands that are only a multiple of 4 and
3464 * not 8 to be allowed since the kernel produces them.
3466 if(ofile
->mh64
== NULL
||
3467 ofile
->mh64
->filetype
!= MH_CORE
||
3468 l
.cmd
!= LC_THREAD
||
3469 l
.cmdsize
% 4 != 0){
3470 Mach_O_error(ofile
, "malformed object (load command %u "
3471 "cmdsize not a multiple of %u)", i
,
3472 load_command_multiple
);
3476 /* check that load command does not extends past end of commands */
3477 big_load_end
+= l
.cmdsize
;
3478 if(big_load_end
> sizeofcmds
){
3479 Mach_O_error(ofile
, "truncated or malformed object (load "
3480 "command %u extends past the end of the file)",i
);
3483 /* check that the load command size is not zero */
3485 Mach_O_error(ofile
, "malformed object (load command %u cmdsize"
3491 if(l
.cmdsize
< sizeof(struct segment_command
)){
3492 Mach_O_error(ofile
, "malformed object (LC_SEGMENT cmdsize "
3493 "too small) in command %u", i
);
3496 sg
= (struct segment_command
*)lc
;
3498 swap_segment_command(sg
, host_byte_sex
);
3499 big_size
= sg
->nsects
;
3500 big_size
*= sizeof(struct section
);
3501 big_size
+= sizeof(struct segment_command
);
3502 if(sg
->cmdsize
!= big_size
){
3503 Mach_O_error(ofile
, "malformed object (inconsistent "
3504 "cmdsize in LC_SEGMENT command %u for the "
3505 "number of sections)", i
);
3508 if(sg
->fileoff
> size
){
3509 Mach_O_error(ofile
, "truncated or malformed object ("
3510 "LC_SEGMENT command %u fileoff field "
3511 "extends past the end of the file)", i
);
3514 big_size
= sg
->fileoff
;
3515 big_size
+= sg
->filesize
;
3516 if(big_size
> size
){
3517 Mach_O_error(ofile
, "truncated or malformed object ("
3518 "LC_SEGMENT command %u fileoff field "
3519 "plus filesize field extends past the end of "
3523 if(sg
->vmsize
!= 0 && sg
->filesize
> sg
->vmsize
){
3524 Mach_O_error(ofile
, "malformed object (LC_SEGMENT command "
3525 "%u filesize field greater than vmsize field)",
3529 s
= (struct section
*)
3530 ((char *)sg
+ sizeof(struct segment_command
));
3532 swap_section(s
, sg
->nsects
, host_byte_sex
);
3533 for(j
= 0 ; j
< sg
->nsects
; j
++){
3534 if(mh
->filetype
!= MH_DYLIB_STUB
&&
3535 s
->flags
!= S_ZEROFILL
&&
3536 s
->flags
!= S_THREAD_LOCAL_ZEROFILL
&& s
->offset
> size
){
3537 Mach_O_error(ofile
, "truncated or malformed object "
3538 "(offset field of section %u in LC_SEGMENT "
3539 "command %u extends past the end of the file)",
3543 if(mh
->filetype
!= MH_DYLIB_STUB
&&
3544 s
->flags
!= S_ZEROFILL
&&
3545 s
->flags
!= S_THREAD_LOCAL_ZEROFILL
&&
3546 sg
->fileoff
== 0 && s
->offset
< sizeofhdrs
){
3547 Mach_O_error(ofile
, "malformed object (offset field of "
3548 "section %u in LC_SEGMENT command %u not "
3549 "past the headers of the file)", j
, i
);
3552 big_size
= s
->offset
;
3553 big_size
+= s
->size
;
3554 if(mh
->filetype
!= MH_DYLIB_STUB
&&
3555 s
->flags
!= S_ZEROFILL
&&
3556 s
->flags
!= S_THREAD_LOCAL_ZEROFILL
&& big_size
> size
){
3557 Mach_O_error(ofile
, "truncated or malformed object "
3558 "(offset field plus size field of section %u "
3559 "in LC_SEGMENT command %u extends "
3560 "past the end of the file)", j
, i
);
3563 if(mh
->filetype
!= MH_DYLIB_STUB
&&
3564 s
->flags
!= S_ZEROFILL
&&
3565 s
->flags
!= S_THREAD_LOCAL_ZEROFILL
&&
3566 s
->size
> sg
->filesize
){
3567 Mach_O_error(ofile
, "malformed object (size field of "
3568 "section %u in LC_SEGMENT command %u greater "
3569 "than the segment)", j
, i
);
3572 if(mh
->filetype
!= MH_DYLIB_STUB
&&
3573 s
->size
!= 0 && s
->addr
< sg
->vmaddr
){
3574 Mach_O_error(ofile
, "malformed object (addr field of "
3575 "section %u in LC_SEGMENT command %u less than "
3576 "the segment's vmaddr)", j
, i
);
3580 big_size
+= s
->size
;
3581 big_end
= sg
->vmaddr
;
3582 big_end
+= sg
->vmsize
;
3583 if(sg
->vmsize
!= 0 && s
->size
!= 0 && big_size
> big_end
){
3584 Mach_O_error(ofile
, "malformed object (addr field plus "
3585 "size of section %u in LC_SEGMENT command %u "
3586 "greater than than the segment's vmaddr plus "
3590 if(mh
->filetype
!= MH_DYLIB_STUB
&&
3591 s
->flags
!= S_ZEROFILL
&&
3592 s
->flags
!= S_THREAD_LOCAL_ZEROFILL
&&
3593 check_overlaping_element(ofile
, &elements
, s
->offset
,
3594 s
->size
, "section contents") == CHECK_BAD
)
3596 if(s
->reloff
> size
){
3597 Mach_O_error(ofile
, "truncated or malformed object "
3598 "(reloff field of section %u in LC_SEGMENT "
3599 "command %u extends past the end of the file)",
3603 big_size
= s
->nreloc
;
3604 big_size
*= sizeof(struct relocation_info
);
3605 big_size
+= s
->reloff
;
3606 if(big_size
> size
){
3607 Mach_O_error(ofile
, "truncated or malformed object "
3608 "(reloff field plus nreloc field times sizeof("
3609 "struct relocation_info) of section %u in "
3610 "LC_SEGMENT command %u extends past the "
3611 "end of the file)", j
, i
);
3614 if(check_overlaping_element(ofile
, &elements
, s
->reloff
,
3615 s
->nreloc
* sizeof(struct relocation_info
),
3616 "section relocation entries") == CHECK_BAD
)
3623 if(l
.cmdsize
< sizeof(struct segment_command_64
)){
3624 Mach_O_error(ofile
, "malformed object (LC_SEGMENT_64 "
3625 "cmdsize too small) in command %u", i
);
3628 sg64
= (struct segment_command_64
*)lc
;
3630 swap_segment_command_64(sg64
, host_byte_sex
);
3631 big_size
= sg64
->nsects
;
3632 big_size
*= sizeof(struct section_64
);
3633 big_size
+= sizeof(struct segment_command_64
);
3634 if(sg64
->cmdsize
!= big_size
){
3635 Mach_O_error(ofile
, "malformed object (inconsistent "
3636 "cmdsize in LC_SEGMENT_64 command %u for "
3637 "the number of sections)", i
);
3640 if(sg64
->fileoff
> size
){
3641 Mach_O_error(ofile
, "truncated or malformed object ("
3642 "LC_SEGMENT_64 command %u fileoff field "
3643 "extends past the end of the file)", i
);
3646 big_size
= sg64
->fileoff
;
3647 big_size
+= sg64
->filesize
;
3648 if(big_size
> size
){
3649 Mach_O_error(ofile
, "truncated or malformed object ("
3650 "LC_SEGMENT_64 command %u fileoff field "
3651 "plus filesize field extends past the end of "
3655 s64
= (struct section_64
*)
3656 ((char *)sg64
+ sizeof(struct segment_command_64
));
3658 swap_section_64(s64
, sg64
->nsects
, host_byte_sex
);
3659 for(j
= 0 ; j
< sg64
->nsects
; j
++){
3660 if(mh64
->filetype
!= MH_DYLIB_STUB
&&
3661 s64
->flags
!= S_ZEROFILL
&&
3662 s64
->flags
!= S_THREAD_LOCAL_ZEROFILL
&&
3663 s64
->offset
> size
){
3664 Mach_O_error(ofile
, "truncated or malformed object "
3665 "(offset field of section %u in LC_SEGMENT_64 "
3666 "command %u extends past the end of the file)",
3670 big_size
= s64
->offset
;
3671 big_size
+= s64
->size
;
3672 if(mh64
->filetype
!= MH_DYLIB_STUB
&&
3673 s64
->flags
!= S_ZEROFILL
&&
3674 s64
->flags
!= S_THREAD_LOCAL_ZEROFILL
&&
3676 Mach_O_error(ofile
, "truncated or malformed object "
3677 "(offset field plus size field of section %u "
3678 "in LC_SEGMENT_64 command %u extends "
3679 "past the end of the file)", j
, i
);
3682 if(mh64
->filetype
!= MH_DYLIB_STUB
&&
3683 s64
->flags
!= S_ZEROFILL
&&
3684 s64
->flags
!= S_THREAD_LOCAL_ZEROFILL
&&
3685 check_overlaping_element(ofile
, &elements
, s64
->offset
,
3686 s64
->size
, "section contents") == CHECK_BAD
)
3688 if(s64
->reloff
> size
){
3689 Mach_O_error(ofile
, "truncated or malformed object "
3690 "(reloff field of section %u in LC_SEGMENT_64 "
3691 "command %u extends past the end of the file)",
3695 big_size
= s64
->nreloc
;
3696 big_size
*= sizeof(struct relocation_info
);
3697 big_size
+= s64
->reloff
;
3698 if(big_size
> size
){
3699 Mach_O_error(ofile
, "truncated or malformed object "
3700 "(reloff field plus nreloc field times sizeof("
3701 "struct relocation_info) of section %u in "
3702 "LC_SEGMENT_64 command %u extends past the "
3703 "end of the file)", j
, i
);
3706 if(check_overlaping_element(ofile
, &elements
, s64
->reloff
,
3707 s64
->nreloc
* sizeof(struct relocation_info
),
3708 "section relocation entries") == CHECK_BAD
)
3715 if(l
.cmdsize
< sizeof(struct symtab_command
)){
3716 Mach_O_error(ofile
, "malformed object (LC_SYMTAB cmdsize "
3717 "too small) in command %u", i
);
3721 Mach_O_error(ofile
, "malformed object (more than one "
3722 "LC_SYMTAB command)");
3725 st
= (struct symtab_command
*)lc
;
3727 swap_symtab_command(st
, host_byte_sex
);
3728 if(st
->cmdsize
!= sizeof(struct symtab_command
)){
3729 Mach_O_error(ofile
, "malformed object (LC_SYMTAB command "
3730 "%u has incorrect cmdsize)", i
);
3733 if(st
->symoff
> size
){
3734 Mach_O_error(ofile
, "truncated or malformed object (symoff "
3735 "field of LC_SYMTAB command %u extends past the end "
3739 big_size
= st
->nsyms
;
3740 big_size
*= sizeof_nlist
;
3741 big_size
+= st
->symoff
;
3742 if(big_size
> size
){
3743 Mach_O_error(ofile
, "truncated or malformed object (symoff "
3744 "field plus nsyms field times sizeof(%s) of LC_SYMTAB "
3745 "command %u extends past the end of the file)",
3746 struct_nlist_name
, i
);
3749 if(check_overlaping_element(ofile
, &elements
, st
->symoff
,
3750 st
->nsyms
* sizeof_nlist
, "symbol table") == CHECK_BAD
)
3752 if(st
->stroff
> size
){
3753 Mach_O_error(ofile
, "truncated or malformed object (stroff "
3754 "field of LC_SYMTAB command %u extends past the end "
3758 big_size
= st
->stroff
;
3759 big_size
+= st
->strsize
;
3760 if(big_size
> size
){
3761 Mach_O_error(ofile
, "truncated or malformed object (stroff "
3762 "field plus strsize field of LC_SYMTAB command %u "
3763 "extends past the end of the file)", i
);
3766 if(check_overlaping_element(ofile
, &elements
, st
->stroff
,
3767 st
->strsize
, "string table") == CHECK_BAD
)
3772 if(l
.cmdsize
< sizeof(struct dysymtab_command
)){
3773 Mach_O_error(ofile
, "malformed object (LC_DYSYMTAB cmdsize "
3774 "too small) in command %u", i
);
3778 Mach_O_error(ofile
, "malformed object (more than one "
3779 "LC_DYSYMTAB command)");
3782 dyst
= (struct dysymtab_command
*)lc
;
3784 swap_dysymtab_command(dyst
, host_byte_sex
);
3785 if(dyst
->cmdsize
!= sizeof(struct dysymtab_command
)){
3786 Mach_O_error(ofile
, "malformed object (LC_DYSYMTAB command "
3787 "%u has incorrect cmdsize)", i
);
3790 if(dyst
->tocoff
> size
){
3791 Mach_O_error(ofile
, "truncated or malformed object (tocoff "
3792 "field of LC_DYSYMTAB command %u extends past the end "
3796 big_size
= dyst
->ntoc
;
3797 big_size
*= sizeof(struct dylib_table_of_contents
);
3798 big_size
+= dyst
->tocoff
;
3799 if(big_size
> size
){
3800 Mach_O_error(ofile
, "truncated or malformed object (tocoff "
3801 "field plus ntoc field times sizeof(struct dylib_table"
3802 "_of_contents) of LC_DYSYMTAB command %u extends past "
3803 "the end of the file)", i
);
3806 if(check_overlaping_element(ofile
, &elements
, dyst
->tocoff
,
3807 dyst
->ntoc
* sizeof(struct dylib_table_of_contents
),
3808 "table of contents") == CHECK_BAD
)
3810 if(dyst
->modtaboff
> size
){
3811 Mach_O_error(ofile
, "truncated or malformed object "
3812 "(modtaboff field of LC_DYSYMTAB command %u extends "
3813 "past the end of the file)", i
);
3816 big_size
= dyst
->nmodtab
;
3817 big_size
*= sizeof_dylib_module
;
3818 big_size
+= dyst
->modtaboff
;
3819 if(big_size
> size
){
3820 Mach_O_error(ofile
, "truncated or malformed object "
3821 "(modtaboff field plus nmodtab field times sizeof(%s) "
3822 "of LC_DYSYMTAB command %u extends past the end of "
3823 "the file)", struct_dylib_module_name
, i
);
3826 if(check_overlaping_element(ofile
, &elements
, dyst
->modtaboff
,
3827 dyst
->nmodtab
* sizeof_dylib_module
, "module table") ==
3830 if(dyst
->extrefsymoff
> size
){
3831 Mach_O_error(ofile
, "truncated or malformed object "
3832 "(extrefsymoff field of LC_DYSYMTAB command %u "
3833 "extends past the end of the file)", i
);
3836 big_size
= dyst
->nextrefsyms
;
3837 big_size
*= sizeof(struct dylib_reference
);
3838 big_size
+= dyst
->extrefsymoff
;
3839 if(big_size
> size
){
3840 Mach_O_error(ofile
, "truncated or malformed object "
3841 "(extrefsymoff field plus nextrefsyms field times "
3842 "sizeof(struct dylib_reference) of LC_DYSYMTAB command "
3843 "%u extends past the end of the file)", i
);
3846 if(check_overlaping_element(ofile
, &elements
,dyst
->extrefsymoff
,
3847 dyst
->nextrefsyms
* sizeof(struct dylib_reference
),
3848 "reference table") == CHECK_BAD
)
3850 if(dyst
->indirectsymoff
> size
){
3851 Mach_O_error(ofile
, "truncated or malformed object "
3852 "(indirectsymoff field of LC_DYSYMTAB command %u "
3853 "extends past the end of the file)", i
);
3856 big_size
= dyst
->nindirectsyms
;
3857 big_size
*= sizeof(uint32_t);
3858 big_size
+= dyst
->indirectsymoff
;
3859 if(big_size
> size
){
3860 Mach_O_error(ofile
, "truncated or malformed object "
3861 "(indirectsymoff field plus nindirectsyms field times "
3862 "sizeof(uint32_t) of LC_DYSYMTAB command "
3863 "%u extends past the end of the file)", i
);
3866 if(check_overlaping_element(ofile
, &elements
,
3867 dyst
->indirectsymoff
, dyst
->nindirectsyms
*
3868 sizeof(uint32_t), "indirect table") == CHECK_BAD
)
3870 if(dyst
->extreloff
> size
){
3871 Mach_O_error(ofile
, "truncated or malformed object "
3872 "(extreloff field of LC_DYSYMTAB command %u "
3873 "extends past the end of the file)", i
);
3876 big_size
= dyst
->nextrel
;
3877 big_size
*= sizeof(struct relocation_info
);
3878 big_size
+= dyst
->extreloff
;
3879 if(big_size
> size
){
3880 Mach_O_error(ofile
, "truncated or malformed object "
3881 "(extreloff field plus nextrel field times "
3882 "sizeof(struct relocation_info) of LC_DYSYMTAB command "
3883 "%u extends past the end of the file)", i
);
3886 if(check_overlaping_element(ofile
, &elements
, dyst
->extreloff
,
3887 dyst
->nextrel
* sizeof(struct relocation_info
),
3888 "external relocation table") == CHECK_BAD
)
3890 if(dyst
->locreloff
> size
){
3891 Mach_O_error(ofile
, "truncated or malformed object "
3892 "(locreloff field of LC_DYSYMTAB command %u "
3893 "extends past the end of the file)", i
);
3896 big_size
= dyst
->nlocrel
;
3897 big_size
*= sizeof(struct relocation_info
);
3898 big_size
+= dyst
->locreloff
;
3899 if(big_size
> size
){
3900 Mach_O_error(ofile
, "truncated or malformed object "
3901 "(locreloff field plus nlocrel field times "
3902 "sizeof(struct relocation_info) of LC_DYSYMTAB command "
3903 "%u extends past the end of the file)", i
);
3906 if(check_overlaping_element(ofile
, &elements
, dyst
->locreloff
,
3907 dyst
->nlocrel
* sizeof(struct relocation_info
),
3908 "local relocation table") == CHECK_BAD
)
3913 if(l
.cmdsize
< sizeof(struct routines_command
)){
3914 Mach_O_error(ofile
, "malformed object (LC_ROUTINES cmdsize "
3915 "too small) in command %u", i
);
3919 Mach_O_error(ofile
, "malformed object (more than one "
3920 "LC_ROUTINES command)");
3923 rc
= (struct routines_command
*)lc
;
3925 swap_routines_command(rc
, host_byte_sex
);
3926 if(rc
->cmdsize
!= sizeof(struct routines_command
)){
3927 Mach_O_error(ofile
, "malformed object (LC_ROUTINES "
3928 "command %u has incorrect cmdsize)", i
);
3933 case LC_ROUTINES_64
:
3934 if(l
.cmdsize
< sizeof(struct routines_command_64
)){
3935 Mach_O_error(ofile
, "malformed object (LC_ROUTINES_64 "
3936 "cmdsize too small) in command %u", i
);
3940 Mach_O_error(ofile
, "malformed object (more than one "
3941 "LC_ROUTINES_64 command)");
3944 rc64
= (struct routines_command_64
*)lc
;
3946 swap_routines_command_64(rc64
, host_byte_sex
);
3947 if(rc64
->cmdsize
!= sizeof(struct routines_command_64
)){
3948 Mach_O_error(ofile
, "malformed object (LC_ROUTINES_64 "
3949 "command %u has incorrect cmdsize)", i
);
3954 case LC_TWOLEVEL_HINTS
:
3955 if(l
.cmdsize
< sizeof(struct twolevel_hints_command
)){
3956 Mach_O_error(ofile
, "malformed object (LC_TWOLEVEL_HINTS "
3957 "cmdsize too small) in command %u", i
);
3961 Mach_O_error(ofile
, "malformed object (more than one "
3962 "LC_TWOLEVEL_HINTS command)");
3965 hints
= (struct twolevel_hints_command
*)lc
;
3967 swap_twolevel_hints_command(hints
, host_byte_sex
);
3968 if(hints
->cmdsize
!= sizeof(struct twolevel_hints_command
)){
3969 Mach_O_error(ofile
, "malformed object (LC_TWOLEVEL_HINTS "
3970 "command %u has incorrect cmdsize)", i
);
3973 if(hints
->offset
> size
){
3974 Mach_O_error(ofile
, "truncated or malformed object "
3975 "(offset field of LC_TWOLEVEL_HINTS command %u "
3976 "extends past the end of the file)", i
);
3979 big_size
= hints
->nhints
;
3980 big_size
*= sizeof(struct twolevel_hint
);
3981 big_size
+= hints
->offset
;
3982 if(big_size
> size
){
3983 Mach_O_error(ofile
, "truncated or malformed object "
3984 "(offset field plus nhints field times "
3985 "sizeof(struct twolevel_hint) of LC_TWOLEVEL_HINTS "
3986 " command %u extends past the end of the file)", i
);
3989 if(check_overlaping_element(ofile
, &elements
, hints
->offset
,
3990 hints
->nhints
* sizeof(struct twolevel_hint
),
3991 "two level hints") == CHECK_BAD
)
3995 case LC_SEGMENT_SPLIT_INFO
:
3996 cmd_name
= "LC_SEGMENT_SPLIT_INFO";
3997 element_name
= "split info data";
3998 if(split_info
!= NULL
){
3999 Mach_O_error(ofile
, "malformed object (more than one "
4000 "%s command)", cmd_name
);
4003 split_info
= (struct linkedit_data_command
*)lc
;
4004 goto check_linkedit_data_command
;
4006 case LC_CODE_SIGNATURE
:
4007 cmd_name
= "LC_CODE_SIGNATURE";
4008 element_name
= "code signature data";
4009 if(code_sig
!= NULL
){
4010 Mach_O_error(ofile
, "malformed object (more than one "
4011 "%s command)", cmd_name
);
4014 code_sig
= (struct linkedit_data_command
*)lc
;
4015 goto check_linkedit_data_command
;
4017 case LC_FUNCTION_STARTS
:
4018 cmd_name
= "LC_FUNCTION_STARTS";
4019 element_name
= "function starts data";
4020 if(func_starts
!= NULL
){
4021 Mach_O_error(ofile
, "malformed object (more than one "
4022 "%s command)", cmd_name
);
4025 func_starts
= (struct linkedit_data_command
*)lc
;
4026 goto check_linkedit_data_command
;
4028 case LC_DATA_IN_CODE
:
4029 cmd_name
= "LC_DATA_IN_CODE";
4030 element_name
= "date in code info";
4031 if(data_in_code
!= NULL
){
4032 Mach_O_error(ofile
, "malformed object (more than one "
4033 "%s command)", cmd_name
);
4036 data_in_code
= (struct linkedit_data_command
*)lc
;
4037 goto check_linkedit_data_command
;
4039 case LC_DYLIB_CODE_SIGN_DRS
:
4040 cmd_name
= "LC_DYLIB_CODE_SIGN_DRS";
4041 element_name
= "code signing RDs data";
4042 if(code_sign_drs
!= NULL
){
4043 Mach_O_error(ofile
, "malformed object (more than one "
4044 "%s command)", cmd_name
);
4047 code_sign_drs
= (struct linkedit_data_command
*)lc
;
4048 goto check_linkedit_data_command
;
4050 check_linkedit_data_command
:
4051 if(l
.cmdsize
< sizeof(struct linkedit_data_command
)){
4052 Mach_O_error(ofile
, "malformed object (%s cmdsize too "
4053 "small) in command %u", cmd_name
, i
);
4056 linkedit_data
= (struct linkedit_data_command
*)lc
;
4058 swap_linkedit_data_command(linkedit_data
, host_byte_sex
);
4059 if(linkedit_data
->cmdsize
!=
4060 sizeof(struct linkedit_data_command
)){
4061 Mach_O_error(ofile
, "malformed object (%s command %u has "
4062 "incorrect cmdsize)", cmd_name
, i
);
4065 if(linkedit_data
->dataoff
> size
){
4066 Mach_O_error(ofile
, "truncated or malformed object "
4067 "(dataoff field of %s command %u extends past the end "
4068 "of the file)", cmd_name
, i
);
4071 big_size
= linkedit_data
->dataoff
;
4072 big_size
+= linkedit_data
->datasize
;
4073 if(big_size
> size
){
4074 Mach_O_error(ofile
, "truncated or malformed object "
4075 "(dataoff field plus datasize field of "
4076 "%s command %u extends past the end of "
4077 "the file)", cmd_name
, i
);
4080 if(check_overlaping_element(ofile
, &elements
,
4081 linkedit_data
->dataoff
, linkedit_data
->datasize
,
4082 element_name
) == CHECK_BAD
)
4086 case LC_VERSION_MIN_MACOSX
:
4087 if(l
.cmdsize
< sizeof(struct version_min_command
)){
4088 Mach_O_error(ofile
, "malformed object (LC_VERSION_MIN_"
4089 "MACOSX cmdsize too small) in command %u", i
);
4093 Mach_O_error(ofile
, "malformed object (more than one "
4094 "LC_VERSION_MIN_IPHONEOS or LC_VERSION_MIN_MACOSX "
4098 vers
= (struct version_min_command
*)lc
;
4100 swap_version_min_command(vers
, host_byte_sex
);
4101 if(vers
->cmdsize
< sizeof(struct version_min_command
)){
4102 Mach_O_error(ofile
, "malformed object (LC_VERSION_MIN_"
4103 "MACOSX command %u has too small cmdsize field)", i
);
4108 case LC_VERSION_MIN_IPHONEOS
:
4109 if(l
.cmdsize
< sizeof(struct version_min_command
)){
4110 Mach_O_error(ofile
, "malformed object (LC_VERSION_MIN_"
4111 "IPHONEOS cmdsize too small) in command %u",i
);
4115 Mach_O_error(ofile
, "malformed object (more than one "
4116 "LC_VERSION_MIN_IPHONEOS or LC_VERSION_MIN_MACOSX "
4120 vers
= (struct version_min_command
*)lc
;
4122 swap_version_min_command(vers
, host_byte_sex
);
4123 if(vers
->cmdsize
< sizeof(struct version_min_command
)){
4124 Mach_O_error(ofile
, "malformed object (LC_VERSION_MIN_"
4125 "IPHONEOS command %u has too small cmdsize field)", i
);
4130 case LC_ENCRYPTION_INFO
:
4131 if(l
.cmdsize
< sizeof(struct encryption_info_command
)){
4132 Mach_O_error(ofile
, "malformed object (LC_ENCRYPTION_INFO "
4133 "cmdsize too small) in command %u", i
);
4136 encrypt_info
= (struct encryption_info_command
*)lc
;
4138 swap_encryption_command(encrypt_info
, host_byte_sex
);
4139 if(encrypt_info
->cmdsize
!=
4140 sizeof(struct encryption_info_command
)){
4141 Mach_O_error(ofile
, "malformed object (LC_ENCRYPTION_INFO"
4142 "command %u has incorrect cmdsize)", i
);
4145 if(encrypt_info
->cryptoff
> size
){
4146 Mach_O_error(ofile
, "truncated or malformed object (cryptoff "
4147 "field of LC_ENCRYPTION_INFO command %u extends "
4148 "past the end of the file)", i
);
4151 big_size
= encrypt_info
->cryptoff
;
4152 big_size
+= encrypt_info
->cryptsize
;
4153 if(big_size
> size
){
4154 Mach_O_error(ofile
, "truncated or malformed object "
4155 "(cryptoff field plus cryptsize field of "
4156 "LC_ENCRYPTION_INFO command %u extends past "
4157 "the end of the file)", i
);
4163 case LC_DYLD_INFO_ONLY
:
4164 if(l
.cmdsize
< sizeof(struct dyld_info_command
)){
4165 Mach_O_error(ofile
, "malformed object (%s cmdsize "
4166 "too small) in command %u", l
.cmd
==
4167 LC_DYLD_INFO
? "LC_DYLD_INFO" :
4168 "LC_DYLD_INFO_ONLY", i
);
4171 dyld_info
= (struct dyld_info_command
*)lc
;
4173 swap_dyld_info_command(dyld_info
, host_byte_sex
);
4174 if(dyld_info
->cmdsize
!=
4175 sizeof(struct dyld_info_command
)){
4176 Mach_O_error(ofile
, "malformed object (LC_DYLD_INFO"
4177 "command %u has incorrect cmdsize)", i
);
4180 if(dyld_info
->rebase_off
!= 0 && dyld_info
->rebase_off
> size
){
4181 Mach_O_error(ofile
, "truncated or malformed object "
4182 "(rebase_off field of LC_DYLD_INFO command %u "
4183 "extends past the end of the file)", i
);
4186 if(dyld_info
->rebase_off
!= 0){
4187 big_size
= dyld_info
->rebase_off
;
4188 big_size
+= dyld_info
->rebase_size
;
4189 if(big_size
> size
){
4190 Mach_O_error(ofile
, "truncated or malformed object "
4191 "(rebase_off plus rebase_size of LC_DYLD_INFO "
4192 "command %u extends past the end of the file)", i
);
4196 if(check_overlaping_element(ofile
, &elements
,
4197 dyld_info
->rebase_off
, dyld_info
->rebase_size
,
4198 "dyld rebase info") == CHECK_BAD
)
4200 if(dyld_info
->bind_off
!= 0 && dyld_info
->bind_off
> size
){
4201 Mach_O_error(ofile
, "truncated or malformed object "
4202 "(bind_off field of LC_DYLD_INFO command %u "
4203 "extends past the end of the file)", i
);
4206 if(dyld_info
->bind_off
!= 0){
4207 big_size
= dyld_info
->bind_off
;
4208 big_size
+= dyld_info
->bind_size
;
4209 if(big_size
> size
){
4210 Mach_O_error(ofile
, "truncated or malformed object "
4211 "(bind_off plus bind_size of LC_DYLD_INFO command "
4212 "%u extends past the end of the file)", i
);
4216 if(check_overlaping_element(ofile
, &elements
,
4217 dyld_info
->bind_off
, dyld_info
->bind_size
,
4218 "dyld bind info") == CHECK_BAD
)
4220 if(dyld_info
->weak_bind_off
!= 0 &&
4221 dyld_info
->weak_bind_off
> size
){
4222 Mach_O_error(ofile
, "truncated or malformed object "
4223 "(weak_bind_off field of LC_DYLD_INFO command %u "
4224 "extends past the end of the file)", i
);
4227 if(dyld_info
->weak_bind_off
!= 0){
4228 big_size
= dyld_info
->weak_bind_off
;
4229 big_size
+= dyld_info
->weak_bind_size
;
4230 if(big_size
> size
){
4231 Mach_O_error(ofile
, "truncated or malformed object "
4232 "(weak_bind_off plus weak_bind_size of LC_DYLD_INFO"
4233 " command %u extends past the end of the file)", i
);
4237 if(check_overlaping_element(ofile
, &elements
,
4238 dyld_info
->weak_bind_off
, dyld_info
->weak_bind_size
,
4239 "dyld bind info") == CHECK_BAD
)
4241 if(dyld_info
->lazy_bind_off
!= 0 &&
4242 dyld_info
->lazy_bind_off
> size
){
4243 Mach_O_error(ofile
, "truncated or malformed object "
4244 "(lazy_bind_off field of LC_DYLD_INFO command %u "
4245 "extends past the end of the file)", i
);
4248 if(dyld_info
->lazy_bind_off
!= 0){
4249 big_size
= dyld_info
->lazy_bind_off
;
4250 big_size
+= dyld_info
->lazy_bind_size
;
4251 if(big_size
> size
){
4252 Mach_O_error(ofile
, "truncated or malformed object "
4253 "(lazy_bind_off plus lazy_bind_size of LC_DYLD_INFO"
4254 " command %u extends past the end of the file)", i
);
4258 if(check_overlaping_element(ofile
, &elements
,
4259 dyld_info
->lazy_bind_off
, dyld_info
->lazy_bind_size
,
4260 "dyld lazy bind info") == CHECK_BAD
)
4262 if(dyld_info
->export_off
!= 0 && dyld_info
->export_off
> size
){
4263 Mach_O_error(ofile
, "truncated or malformed object "
4264 "(export_off field of LC_DYLD_INFO command %u "
4265 "extends past the end of the file)", i
);
4268 if(dyld_info
->export_off
!= 0){
4269 big_size
= dyld_info
->export_off
;
4270 big_size
+= dyld_info
->export_size
;
4271 if(big_size
> size
){
4272 Mach_O_error(ofile
, "truncated or malformed object "
4273 "(export_off plus export_size of LC_DYLD_INFO "
4274 "command %u extends past the end of the file)", i
);
4278 if(check_overlaping_element(ofile
, &elements
,
4279 dyld_info
->export_off
, dyld_info
->export_size
,
4280 "dyld export info") == CHECK_BAD
)
4286 case LC_PREBIND_CKSUM
:
4287 if(l
.cmdsize
< sizeof(struct prebind_cksum_command
)){
4288 Mach_O_error(ofile
, "malformed object (LC_PREBIND_CKSUM "
4289 "cmdsize too small) in command %u", i
);
4293 Mach_O_error(ofile
, "malformed object (more than one "
4294 "LC_PREBIND_CKSUM command)");
4297 cs
= (struct prebind_cksum_command
*)lc
;
4299 swap_prebind_cksum_command(cs
, host_byte_sex
);
4300 if(cs
->cmdsize
!= sizeof(struct prebind_cksum_command
)){
4301 Mach_O_error(ofile
, "malformed object (LC_PREBIND_CKSUM "
4302 "command %u has incorrect cmdsize)", i
);
4308 if(l
.cmdsize
< sizeof(struct uuid_command
)){
4309 Mach_O_error(ofile
, "malformed object (LC_UUID cmdsize "
4310 "too small) in command %u", i
);
4314 Mach_O_error(ofile
, "malformed object (more than one "
4315 "LC_UUID command)");
4318 uuid
= (struct uuid_command
*)lc
;
4320 swap_uuid_command(uuid
, host_byte_sex
);
4321 if(uuid
->cmdsize
!= sizeof(struct uuid_command
)){
4322 Mach_O_error(ofile
, "malformed object (LC_UUID command %u " "has incorrect cmdsize)", i
);
4328 if(l
.cmdsize
< sizeof(struct symseg_command
)){
4329 Mach_O_error(ofile
, "malformed object (LC_SYMSEG cmdsize "
4330 "too small) in command %u", i
);
4333 ss
= (struct symseg_command
*)lc
;
4335 swap_symseg_command(ss
, host_byte_sex
);
4336 if(ss
->cmdsize
!= sizeof(struct symseg_command
)){
4337 Mach_O_error(ofile
, "malformed object (LC_SYMSEG command "
4338 "%u has incorrect cmdsize)", i
);
4341 if(ss
->offset
> size
){
4342 Mach_O_error(ofile
, "truncated or malformed object (offset "
4343 "field of LC_SYMSEG command %u extends past the end "
4347 big_size
= ss
->offset
;
4348 big_size
+= ss
->size
;
4349 if(big_size
> size
){
4350 Mach_O_error(ofile
, "truncated or malformed object (offset "
4351 "field plus size field of LC_SYMTAB command %u "
4352 "extends past the end of the file)", i
);
4355 if(check_overlaping_element(ofile
, &elements
, ss
->offset
,
4356 ss
->size
, "symseg info") == CHECK_BAD
)
4362 if(l
.cmdsize
< sizeof(struct fvmlib_command
)){
4363 Mach_O_error(ofile
, "malformed object (%s cmdsize "
4364 "too small) in command %u", l
.cmd
==
4365 LC_IDFVMLIB
? "LC_IDFVMLIB" :
4366 "LC_LOADFVMLIB", i
);
4369 fl
= (struct fvmlib_command
*)lc
;
4371 swap_fvmlib_command(fl
, host_byte_sex
);
4372 if(fl
->cmdsize
< sizeof(struct fvmlib_command
)){
4373 Mach_O_error(ofile
, "malformed object (%s command %u has "
4374 "too small cmdsize field)", fl
->cmd
== LC_IDFVMLIB
?
4375 "LC_IDFVMLIB" : "LC_LOADFVMLIB", i
);
4378 if(fl
->fvmlib
.name
.offset
>= fl
->cmdsize
){
4379 Mach_O_error(ofile
, "truncated or malformed object (name."
4380 "offset field of %s command %u extends past the end "
4381 "of the file)", fl
->cmd
== LC_IDFVMLIB
? "LC_IDFVMLIB"
4382 : "LC_LOADFVMLIB", i
);
4388 cmd_name
= "LC_ID_DYLIB";
4389 goto check_dylib_command
;
4391 cmd_name
= "LC_LOAD_DYLIB";
4392 goto check_dylib_command
;
4393 case LC_LOAD_WEAK_DYLIB
:
4394 cmd_name
= "LC_LOAD_WEAK_DYLIB";
4395 goto check_dylib_command
;
4396 case LC_REEXPORT_DYLIB
:
4397 cmd_name
= "LC_REEXPORT_DYLIB";
4398 goto check_dylib_command
;
4399 case LC_LOAD_UPWARD_DYLIB
:
4400 cmd_name
= "LC_LOAD_UPWARD_DYLIB";
4401 goto check_dylib_command
;
4402 case LC_LAZY_LOAD_DYLIB
:
4403 cmd_name
= "LC_LAZY_LOAD_DYLIB";
4404 goto check_dylib_command
;
4405 check_dylib_command
:
4406 if(l
.cmdsize
< sizeof(struct dylib_command
)){
4407 Mach_O_error(ofile
, "malformed object (%s cmdsize too "
4408 "small) in command %u", cmd_name
, i
);
4411 dl
= (struct dylib_command
*)lc
;
4413 swap_dylib_command(dl
, host_byte_sex
);
4414 if(dl
->cmdsize
< sizeof(struct dylib_command
)){
4415 Mach_O_error(ofile
, "malformed object (%s command %u has "
4416 "too small cmdsize field)", cmd_name
, i
);
4419 if(dl
->dylib
.name
.offset
>= dl
->cmdsize
){
4420 Mach_O_error(ofile
, "truncated or malformed object (name."
4421 "offset field of %s command %u extends past the end "
4422 "of the file)", cmd_name
, i
);
4427 case LC_SUB_FRAMEWORK
:
4428 if(l
.cmdsize
< sizeof(struct sub_framework_command
)){
4429 Mach_O_error(ofile
, "malformed object (LC_SUB_FRAMEWORK "
4430 "cmdsize too small) in command %u", i
);
4433 sub
= (struct sub_framework_command
*)lc
;
4435 swap_sub_framework_command(sub
, host_byte_sex
);
4436 if(sub
->cmdsize
< sizeof(struct sub_framework_command
)){
4437 Mach_O_error(ofile
, "malformed object (LC_SUB_FRAMEWORK "
4438 "command %u has too small cmdsize field)", i
);
4441 if(sub
->umbrella
.offset
>= sub
->cmdsize
){
4442 Mach_O_error(ofile
, "truncated or malformed object "
4443 "(umbrella.offset field of LC_SUB_FRAMEWORK command "
4444 "%u extends past the end of the file)", i
);
4449 case LC_SUB_UMBRELLA
:
4450 if(l
.cmdsize
< sizeof(struct sub_umbrella_command
)){
4451 Mach_O_error(ofile
, "malformed object (LC_SUB_UMBRELLA "
4452 "cmdsize too small) in command %u", i
);
4455 usub
= (struct sub_umbrella_command
*)lc
;
4457 swap_sub_umbrella_command(usub
, host_byte_sex
);
4458 if(usub
->cmdsize
< sizeof(struct sub_umbrella_command
)){
4459 Mach_O_error(ofile
, "malformed object (LC_SUB_UMBRELLA "
4460 "command %u has too small cmdsize field)", i
);
4463 if(usub
->sub_umbrella
.offset
>= usub
->cmdsize
){
4464 Mach_O_error(ofile
, "truncated or malformed object "
4465 "(sub_umbrella.offset field of LC_SUB_UMBRELLA command "
4466 "%u extends past the end of the file)", i
);
4471 case LC_SUB_LIBRARY
:
4472 if(l
.cmdsize
< sizeof(struct sub_library_command
)){
4473 Mach_O_error(ofile
, "malformed object (LC_SUB_LIBRARY "
4474 "cmdsize too small) in command %u", i
);
4477 lsub
= (struct sub_library_command
*)lc
;
4479 swap_sub_library_command(lsub
, host_byte_sex
);
4480 if(lsub
->cmdsize
< sizeof(struct sub_library_command
)){
4481 Mach_O_error(ofile
, "malformed object (LC_SUB_LIBRARY "
4482 "command %u has too small cmdsize field)", i
);
4485 if(lsub
->sub_library
.offset
>= lsub
->cmdsize
){
4486 Mach_O_error(ofile
, "truncated or malformed object "
4487 "(sub_library.offset field of LC_SUB_LIBRARY command "
4488 "%u extends past the end of the file)", i
);
4494 if(l
.cmdsize
< sizeof(struct sub_client_command
)){
4495 Mach_O_error(ofile
, "malformed object (LC_SUB_CLIENT "
4496 "cmdsize too small) in command %u", i
);
4499 csub
= (struct sub_client_command
*)lc
;
4501 swap_sub_client_command(csub
, host_byte_sex
);
4502 if(csub
->cmdsize
< sizeof(struct sub_client_command
)){
4503 Mach_O_error(ofile
, "malformed object (LC_SUB_CLIENT "
4504 "command %u has too small cmdsize field)", i
);
4507 if(csub
->client
.offset
>= csub
->cmdsize
){
4508 Mach_O_error(ofile
, "truncated or malformed object "
4509 "(cleient.offset field of LC_SUB_CLIENT command "
4510 "%u extends past the end of the file)", i
);
4515 case LC_PREBOUND_DYLIB
:
4516 if(l
.cmdsize
< sizeof(struct prebound_dylib_command
)){
4517 Mach_O_error(ofile
, "malformed object (LC_PREBOUND_DYLIB "
4518 "cmdsize too small) in command %u", i
);
4521 pbdylib
= (struct prebound_dylib_command
*)lc
;
4523 swap_prebound_dylib_command(pbdylib
, host_byte_sex
);
4524 if(pbdylib
->cmdsize
< sizeof(struct dylib_command
)){
4525 Mach_O_error(ofile
, "malformed object (LC_PREBIND_DYLIB "
4526 "command %u has too small cmdsize field)", i
);
4529 if(pbdylib
->name
.offset
>= pbdylib
->cmdsize
){
4530 Mach_O_error(ofile
, "truncated or malformed object (name."
4531 "offset field of LC_PREBIND_DYLIB command %u extends "
4532 "past the end of the file)", i
);
4535 if(pbdylib
->linked_modules
.offset
>= pbdylib
->cmdsize
){
4536 Mach_O_error(ofile
, "truncated or malformed object (linked_"
4537 "modules.offset field of LC_PREBIND_DYLIB command %u "
4538 "extends past the end of the file)", i
);
4543 case LC_ID_DYLINKER
:
4544 cmd_name
= "LC_ID_DYLINKER";
4545 goto check_dylinker_command
;
4546 case LC_LOAD_DYLINKER
:
4547 cmd_name
= "LC_LOAD_DYLINKER";
4548 goto check_dylinker_command
;
4549 case LC_DYLD_ENVIRONMENT
:
4550 cmd_name
= "LC_DYLD_ENVIRONMENT";
4551 goto check_dylinker_command
;
4552 check_dylinker_command
:
4553 if(l
.cmdsize
< sizeof(struct dylinker_command
)){
4554 Mach_O_error(ofile
, "malformed object (%s cmdsize "
4555 "too small) in command %u", cmd_name
, i
);
4558 dyld
= (struct dylinker_command
*)lc
;
4560 swap_dylinker_command(dyld
, host_byte_sex
);
4561 if(dyld
->cmdsize
< sizeof(struct dylinker_command
)){
4562 Mach_O_error(ofile
, "malformed object (%s command %u has "
4563 "too small cmdsize field)", cmd_name
, i
);
4566 if(dyld
->name
.offset
>= dyld
->cmdsize
){
4567 Mach_O_error(ofile
, "truncated or malformed object (name."
4568 "offset field of %s command %u extends past the end "
4569 "of the file)", cmd_name
, i
);
4576 if(l
.cmdsize
< sizeof(struct thread_command
)){
4577 Mach_O_error(ofile
, "malformed object (%s cmdsize "
4578 "too small) in command %u", l
.cmd
==
4579 LC_UNIXTHREAD
? "LC_UNIXTHREAD" :
4583 ut
= (struct thread_command
*)lc
;
4585 swap_thread_command(ut
, host_byte_sex
);
4586 state
= (char *)ut
+ sizeof(struct thread_command
);
4588 if(cputype
== CPU_TYPE_MC680x0
){
4589 struct m68k_thread_state_regs
*cpu
;
4590 struct m68k_thread_state_68882
*fpu
;
4591 struct m68k_thread_state_user_reg
*user_reg
;
4594 p
= (char *)ut
+ ut
->cmdsize
;
4596 if(state
+ sizeof(uint32_t) >
4597 (char *)ut
+ ut
->cmdsize
){
4598 Mach_O_error(ofile
, "malformed object (flavor in "
4599 "%s command %u extends past end of command)",
4600 ut
->cmd
== LC_UNIXTHREAD
? "LC_UNIXTHREAD" :
4604 flavor
= *((uint32_t *)state
);
4606 flavor
= SWAP_INT(flavor
);
4607 *((uint32_t *)state
) = flavor
;
4609 state
+= sizeof(uint32_t);
4610 if(state
+ sizeof(uint32_t) >
4611 (char *)ut
+ ut
->cmdsize
){
4612 Mach_O_error(ofile
, "malformed object (count in "
4613 "%s command %u extends past end of command)",
4614 ut
->cmd
== LC_UNIXTHREAD
? "LC_UNIXTHREAD" :
4618 count
= *((uint32_t *)state
);
4620 count
= SWAP_INT(count
);
4621 *((uint32_t *)state
) = count
;
4623 state
+= sizeof(uint32_t);
4625 case M68K_THREAD_STATE_REGS
:
4626 if(count
!= M68K_THREAD_STATE_REGS_COUNT
){
4627 Mach_O_error(ofile
, "malformed object (count "
4628 "not M68K_THREAD_STATE_REGS_COUNT for "
4629 "flavor number %u which is a M68K_THREAD_"
4630 "STATE_REGS flavor in %s command %u)",
4631 nflavor
, ut
->cmd
== LC_UNIXTHREAD
?
4632 "LC_UNIXTHREAD" : "LC_THREAD", i
);
4635 cpu
= (struct m68k_thread_state_regs
*)state
;
4636 if(state
+ sizeof(struct m68k_thread_state_regs
) >
4637 (char *)ut
+ ut
->cmdsize
){
4638 Mach_O_error(ofile
, "malformed object ("
4639 "M68K_THREAD_STATE_REGS in %s command %u "
4640 "extends past end of command)", ut
->cmd
==
4641 LC_UNIXTHREAD
? "LC_UNIXTHREAD" :
4646 swap_m68k_thread_state_regs(cpu
, host_byte_sex
);
4647 state
+= sizeof(struct m68k_thread_state_regs
);
4649 case M68K_THREAD_STATE_68882
:
4650 if(count
!= M68K_THREAD_STATE_68882_COUNT
){
4651 Mach_O_error(ofile
, "malformed object (count "
4652 "not M68K_THREAD_STATE_68882_COUNT for "
4653 "flavor number %u which is a M68K_THREAD_"
4654 "STATE_68882 flavor in %s command %u)",
4655 nflavor
, ut
->cmd
== LC_UNIXTHREAD
?
4656 "LC_UNIXTHREAD" : "LC_THREAD", i
);
4659 fpu
= (struct m68k_thread_state_68882
*)state
;
4660 if(state
+ sizeof(struct m68k_thread_state_68882
) >
4661 (char *)ut
+ ut
->cmdsize
){
4662 Mach_O_error(ofile
, "malformed object ("
4663 "M68K_THREAD_STATE_68882 in %s command %u "
4664 "extends past end of command)", ut
->cmd
==
4665 LC_UNIXTHREAD
? "LC_UNIXTHREAD" :
4670 swap_m68k_thread_state_68882(fpu
,host_byte_sex
);
4671 state
+= sizeof(struct m68k_thread_state_68882
);
4673 case M68K_THREAD_STATE_USER_REG
:
4674 if(count
!= M68K_THREAD_STATE_USER_REG_COUNT
){
4675 Mach_O_error(ofile
, "malformed object (count "
4676 "not M68K_THREAD_STATE_USER_REG_COUNT for "
4677 "flavor number %u which is a M68K_THREAD_"
4678 "STATE_USER_REG flavor in %s command %u)",
4679 nflavor
, ut
->cmd
== LC_UNIXTHREAD
?
4680 "LC_UNIXTHREAD" : "LC_THREAD", i
);
4684 (struct m68k_thread_state_user_reg
*)state
;
4685 if(state
+sizeof(struct m68k_thread_state_user_reg
) >
4686 (char *)ut
+ ut
->cmdsize
){
4687 Mach_O_error(ofile
, "malformed object ("
4688 "M68K_THREAD_STATE_USER_REG in %s command "
4689 "%u extends past end of command)", ut
->cmd
==
4690 LC_UNIXTHREAD
? "LC_UNIXTHREAD" :
4695 swap_m68k_thread_state_user_reg(user_reg
,
4697 state
+= sizeof(struct m68k_thread_state_user_reg
);
4701 Mach_O_error(ofile
, "malformed object (unknown "
4702 "flavor for flavor number %u in %s command"
4703 " %u can't byte swap it)", nflavor
,
4704 ut
->cmd
== LC_UNIXTHREAD
? "LC_UNIXTHREAD" :
4708 state
+= count
* sizeof(uint32_t);
4715 if(cputype
== CPU_TYPE_POWERPC
||
4716 cputype
== CPU_TYPE_VEO
){
4717 ppc_thread_state_t
*nrw_cpu
;
4720 p
= (char *)ut
+ ut
->cmdsize
;
4722 if(state
+ sizeof(uint32_t) >
4723 (char *)ut
+ ut
->cmdsize
){
4724 Mach_O_error(ofile
, "malformed object (flavor in "
4725 "%s command %u extends past end of command)",
4726 ut
->cmd
== LC_UNIXTHREAD
? "LC_UNIXTHREAD" :
4730 flavor
= *((uint32_t *)state
);
4732 flavor
= SWAP_INT(flavor
);
4733 *((uint32_t *)state
) = flavor
;
4735 state
+= sizeof(uint32_t);
4736 if(state
+ sizeof(uint32_t) >
4737 (char *)ut
+ ut
->cmdsize
){
4738 Mach_O_error(ofile
, "malformed object (count in "
4739 "%s command %u extends past end of command)",
4740 ut
->cmd
== LC_UNIXTHREAD
? "LC_UNIXTHREAD" :
4744 count
= *((uint32_t *)state
);
4746 count
= SWAP_INT(count
);
4747 *((uint32_t *)state
) = count
;
4749 state
+= sizeof(uint32_t);
4751 case PPC_THREAD_STATE
:
4752 if(count
!= PPC_THREAD_STATE_COUNT
){
4753 Mach_O_error(ofile
, "malformed object (count "
4754 "not PPC_THREAD_STATE_COUNT for "
4755 "flavor number %u which is a PPC_THREAD_"
4756 "STATE flavor in %s command %u)",
4757 nflavor
, ut
->cmd
== LC_UNIXTHREAD
?
4758 "LC_UNIXTHREAD" : "LC_THREAD", i
);
4761 nrw_cpu
= (ppc_thread_state_t
*)state
;
4762 if(state
+ sizeof(ppc_thread_state_t
) >
4763 (char *)ut
+ ut
->cmdsize
){
4764 Mach_O_error(ofile
, "malformed object ("
4765 "PPC_THREAD_STATE in %s command %u extends"
4766 " past end of command)", ut
->cmd
==
4767 LC_UNIXTHREAD
? "LC_UNIXTHREAD" :
4772 swap_ppc_thread_state_t(nrw_cpu
,
4774 state
+= sizeof(ppc_thread_state_t
);
4778 Mach_O_error(ofile
, "malformed object (unknown "
4779 "flavor for flavor number %u in %s command"
4780 " %u can't byte swap it)", nflavor
,
4781 ut
->cmd
== LC_UNIXTHREAD
? "LC_UNIXTHREAD" :
4785 state
+= count
* sizeof(uint32_t);
4792 #ifdef PPC_THREAD_STATE64_COUNT
4793 if(cputype
== CPU_TYPE_POWERPC64
){
4794 ppc_thread_state64_t
*cpu
;
4797 p
= (char *)ut
+ ut
->cmdsize
;
4799 if(state
+ sizeof(uint32_t) >
4800 (char *)ut
+ ut
->cmdsize
){
4801 Mach_O_error(ofile
, "malformed object (flavor in "
4802 "%s command %u extends past end of command)",
4803 ut
->cmd
== LC_UNIXTHREAD
? "LC_UNIXTHREAD" :
4807 flavor
= *((uint32_t *)state
);
4809 flavor
= SWAP_INT(flavor
);
4810 *((uint32_t *)state
) = flavor
;
4812 state
+= sizeof(uint32_t);
4813 if(state
+ sizeof(uint32_t) >
4814 (char *)ut
+ ut
->cmdsize
){
4815 Mach_O_error(ofile
, "malformed object (count in "
4816 "%s command %u extends past end of command)",
4817 ut
->cmd
== LC_UNIXTHREAD
? "LC_UNIXTHREAD" :
4821 count
= *((uint32_t *)state
);
4823 count
= SWAP_INT(count
);
4824 *((uint32_t *)state
) = count
;
4826 state
+= sizeof(uint32_t);
4828 case PPC_THREAD_STATE64
:
4829 if(count
!= PPC_THREAD_STATE64_COUNT
){
4830 Mach_O_error(ofile
, "malformed object (count "
4831 "not PPC_THREAD_STATE64_COUNT for "
4832 "flavor number %u which is a PPC_THREAD_"
4833 "STATE64 flavor in %s command %u)",
4834 nflavor
, ut
->cmd
== LC_UNIXTHREAD
?
4835 "LC_UNIXTHREAD" : "LC_THREAD", i
);
4838 cpu
= (ppc_thread_state64_t
*)state
;
4839 if(state
+ sizeof(ppc_thread_state64_t
) >
4840 (char *)ut
+ ut
->cmdsize
){
4841 Mach_O_error(ofile
, "malformed object ("
4842 "PPC_THREAD_STATE64 in %s command %u "
4843 "extends past end of command)", ut
->cmd
==
4844 LC_UNIXTHREAD
? "LC_UNIXTHREAD" :
4849 swap_ppc_thread_state64_t(cpu
, host_byte_sex
);
4850 state
+= sizeof(ppc_thread_state64_t
);
4854 Mach_O_error(ofile
, "malformed object (unknown "
4855 "flavor for flavor number %u in %s command"
4856 " %u can't byte swap it)", nflavor
,
4857 ut
->cmd
== LC_UNIXTHREAD
? "LC_UNIXTHREAD" :
4861 state
+= count
* sizeof(uint32_t);
4868 #endif /* PPC_THREAD_STATE64_COUNT */
4869 if(cputype
== CPU_TYPE_MC88000
){
4870 m88k_thread_state_grf_t
*cpu
;
4871 m88k_thread_state_xrf_t
*fpu
;
4872 m88k_thread_state_user_t
*user
;
4873 m88110_thread_state_impl_t
*spu
;
4876 p
= (char *)ut
+ ut
->cmdsize
;
4878 if(state
+ sizeof(uint32_t) >
4879 (char *)ut
+ ut
->cmdsize
){
4880 Mach_O_error(ofile
, "malformed object (flavor in "
4881 "%s command %u extends past end of command)",
4882 ut
->cmd
== LC_UNIXTHREAD
? "LC_UNIXTHREAD" :
4886 flavor
= *((uint32_t *)state
);
4888 flavor
= SWAP_INT(flavor
);
4889 *((uint32_t *)state
) = flavor
;
4891 state
+= sizeof(uint32_t);
4892 if(state
+ sizeof(uint32_t) >
4893 (char *)ut
+ ut
->cmdsize
){
4894 Mach_O_error(ofile
, "malformed object (count in "
4895 "%s command %u extends past end of command)",
4896 ut
->cmd
== LC_UNIXTHREAD
? "LC_UNIXTHREAD" :
4900 count
= *((uint32_t *)state
);
4902 count
= SWAP_INT(count
);
4903 *((uint32_t *)state
) = count
;
4905 state
+= sizeof(uint32_t);
4907 case M88K_THREAD_STATE_GRF
:
4908 if(count
!= M88K_THREAD_STATE_GRF_COUNT
){
4909 Mach_O_error(ofile
, "malformed object (count "
4910 "not M88K_THREAD_STATE_GRF_COUNT for "
4911 "flavor number %u which is a M88K_THREAD_"
4912 "STATE_GRF flavor in %s command %u)",
4913 nflavor
, ut
->cmd
== LC_UNIXTHREAD
?
4914 "LC_UNIXTHREAD" : "LC_THREAD", i
);
4917 cpu
= (m88k_thread_state_grf_t
*)state
;
4918 if(state
+ sizeof(m88k_thread_state_grf_t
) >
4919 (char *)ut
+ ut
->cmdsize
){
4920 Mach_O_error(ofile
, "malformed object ("
4921 "M88K_THREAD_STATE_GRF in %s command %u "
4922 "extends past end of command)", ut
->cmd
==
4923 LC_UNIXTHREAD
? "LC_UNIXTHREAD" :
4928 swap_m88k_thread_state_grf_t(cpu
,
4930 state
+= sizeof(m88k_thread_state_grf_t
);
4932 case M88K_THREAD_STATE_XRF
:
4933 if(count
!= M88K_THREAD_STATE_XRF_COUNT
){
4934 Mach_O_error(ofile
, "malformed object (count "
4935 "not M88K_THREAD_STATE_XRF_COUNT for "
4936 "flavor number %u which is a M88K_THREAD_"
4937 "STATE_XRF flavor in %s command %u)",
4938 nflavor
, ut
->cmd
== LC_UNIXTHREAD
?
4939 "LC_UNIXTHREAD" : "LC_THREAD", i
);
4942 fpu
= (m88k_thread_state_xrf_t
*)state
;
4943 if(state
+ sizeof(m88k_thread_state_xrf_t
) >
4944 (char *)ut
+ ut
->cmdsize
){
4945 Mach_O_error(ofile
, "malformed object ("
4946 "M88K_THREAD_STATE_XRF in %s command %u "
4947 "extends past end of command)", ut
->cmd
==
4948 LC_UNIXTHREAD
? "LC_UNIXTHREAD" :
4953 swap_m88k_thread_state_xrf_t(fpu
,
4955 state
+= sizeof(m88k_thread_state_xrf_t
);
4957 case M88K_THREAD_STATE_USER
:
4958 if(count
!= M88K_THREAD_STATE_USER_COUNT
){
4959 Mach_O_error(ofile
, "malformed object (count "
4960 "not M88K_THREAD_STATE_USER_COUNT for "
4961 "flavor number %u which is a M88K_THREAD_"
4962 "STATE_USER flavor in %s command %u)",
4963 nflavor
, ut
->cmd
== LC_UNIXTHREAD
?
4964 "LC_UNIXTHREAD" : "LC_THREAD", i
);
4967 user
= (m88k_thread_state_user_t
*)state
;
4968 if(state
+ sizeof(m88k_thread_state_user_t
) >
4969 (char *)ut
+ ut
->cmdsize
){
4970 Mach_O_error(ofile
, "malformed object ("
4971 "M88K_THREAD_STATE_USER in %s command %u "
4972 "extends past end of command)", ut
->cmd
==
4973 LC_UNIXTHREAD
? "LC_UNIXTHREAD" :
4978 swap_m88k_thread_state_user_t(user
,
4980 state
+= sizeof(m88k_thread_state_user_t
);
4982 case M88110_THREAD_STATE_IMPL
:
4983 if(count
!= M88110_THREAD_STATE_IMPL_COUNT
){
4984 Mach_O_error(ofile
, "malformed object (count "
4985 "not M88110_THREAD_STATE_IMPL_COUNT for "
4986 "flavor number %u which is a M88110_THREAD"
4987 "_STATE_IMPL flavor in %s command %u)",
4988 nflavor
, ut
->cmd
== LC_UNIXTHREAD
?
4989 "LC_UNIXTHREAD" : "LC_THREAD", i
);
4992 spu
= (m88110_thread_state_impl_t
*)state
;
4993 if(state
+ sizeof(m88110_thread_state_impl_t
) >
4994 (char *)ut
+ ut
->cmdsize
){
4995 Mach_O_error(ofile
, "malformed object ("
4996 "M88110_THREAD_STATE_IMPL in %s command %u "
4997 "extends past end of command)", ut
->cmd
==
4998 LC_UNIXTHREAD
? "LC_UNIXTHREAD" :
5003 swap_m88110_thread_state_impl_t(spu
,
5005 state
+= sizeof(m88110_thread_state_impl_t
);
5009 Mach_O_error(ofile
, "malformed object (unknown "
5010 "flavor for flavor number %u in %s command"
5011 " %u can't byte swap it)", nflavor
,
5012 ut
->cmd
== LC_UNIXTHREAD
? "LC_UNIXTHREAD" :
5016 state
+= count
* sizeof(uint32_t);
5023 if(cputype
== CPU_TYPE_I860
){
5025 struct i860_thread_state_regs
*cpu
;
5029 p
= (char *)ut
+ ut
->cmdsize
;
5031 if(state
+ sizeof(uint32_t) >
5032 (char *)ut
+ ut
->cmdsize
){
5033 Mach_O_error(ofile
, "malformed object (flavor in "
5034 "%s command %u extends past end of command)",
5035 ut
->cmd
== LC_UNIXTHREAD
? "LC_UNIXTHREAD" :
5039 flavor
= *((uint32_t *)state
);
5041 flavor
= SWAP_INT(flavor
);
5042 *((uint32_t *)state
) = flavor
;
5044 state
+= sizeof(uint32_t);
5045 if(state
+ sizeof(uint32_t) >
5046 (char *)ut
+ ut
->cmdsize
){
5047 Mach_O_error(ofile
, "malformed object (count in "
5048 "%s command %u extends past end of command)",
5049 ut
->cmd
== LC_UNIXTHREAD
? "LC_UNIXTHREAD" :
5053 count
= *((uint32_t *)state
);
5055 count
= SWAP_INT(count
);
5056 *((uint32_t *)state
) = count
;
5058 state
+= sizeof(uint32_t);
5060 case I860_THREAD_STATE_REGS
:
5062 if(count
!= I860_THREAD_STATE_REGS_COUNT
){
5063 Mach_O_error(ofile
, "malformed object (count "
5064 "not I860_THREAD_STATE_REGS_COUNT for "
5065 "flavor number %u which is a I860_THREAD_"
5066 "STATE_REGS flavor in %s command %u)",
5067 nflavor
, ut
->cmd
== LC_UNIXTHREAD
?
5068 "LC_UNIXTHREAD" : "LC_THREAD", i
);
5071 cpu
= (struct i860_thread_state_regs
*)state
;
5072 if(state
+ sizeof(struct i860_thread_state_regs
) >
5073 (char *)ut
+ ut
->cmdsize
){
5074 Mach_O_error(ofile
, "malformed object ("
5075 "I860_THREAD_STATE_REGS in %s command %u "
5076 "extends past end of command)", ut
->cmd
==
5077 LC_UNIXTHREAD
? "LC_UNIXTHREAD" :
5082 swap_i860_thread_state_regs(cpu
, host_byte_sex
);
5083 state
+= sizeof(struct i860_thread_state_regs
);
5085 state
+= count
* sizeof(int);
5090 Mach_O_error(ofile
, "malformed object (unknown "
5091 "flavor for flavor number %u in %s command"
5092 " %u can't byte swap it)", nflavor
,
5093 ut
->cmd
== LC_UNIXTHREAD
? "LC_UNIXTHREAD" :
5097 state
+= count
* sizeof(uint32_t);
5104 if(cputype
== CPU_TYPE_I386
){
5105 i386_thread_state_t
*cpu
;
5106 /* current i386 thread states */
5107 #if i386_THREAD_STATE == 1
5108 struct i386_float_state
*fpu
;
5109 i386_exception_state_t
*exc
;
5110 #endif /* i386_THREAD_STATE == 1 */
5112 /* i386 thread states on older releases */
5113 #if i386_THREAD_STATE == -1
5114 i386_thread_fpstate_t
*fpu
;
5115 i386_thread_exceptstate_t
*exc
;
5116 i386_thread_cthreadstate_t
*user
;
5117 #endif /* i386_THREAD_STATE == -1 */
5120 p
= (char *)ut
+ ut
->cmdsize
;
5122 if(state
+ sizeof(uint32_t) >
5123 (char *)ut
+ ut
->cmdsize
){
5124 Mach_O_error(ofile
, "malformed object (flavor in "
5125 "%s command %u extends past end of command)",
5126 ut
->cmd
== LC_UNIXTHREAD
? "LC_UNIXTHREAD" :
5130 flavor
= *((uint32_t *)state
);
5132 flavor
= SWAP_INT(flavor
);
5133 *((uint32_t *)state
) = flavor
;
5135 state
+= sizeof(uint32_t);
5136 if(state
+ sizeof(uint32_t) >
5137 (char *)ut
+ ut
->cmdsize
){
5138 Mach_O_error(ofile
, "malformed object (count in "
5139 "%s command %u extends past end of command)",
5140 ut
->cmd
== LC_UNIXTHREAD
? "LC_UNIXTHREAD" :
5144 count
= *((uint32_t *)state
);
5146 count
= SWAP_INT(count
);
5147 *((uint32_t *)state
) = count
;
5149 state
+= sizeof(uint32_t);
5150 switch((int)flavor
){
5151 case i386_THREAD_STATE
:
5152 #if i386_THREAD_STATE == 1
5154 #endif /* i386_THREAD_STATE == 1 */
5155 /* i386 thread states on older releases */
5156 #if i386_THREAD_STATE == -1
5158 #endif /* i386_THREAD_STATE == -1 */
5159 if(count
!= i386_THREAD_STATE_COUNT
){
5160 Mach_O_error(ofile
, "malformed object (count "
5161 "not i386_THREAD_STATE_COUNT for flavor "
5162 "number %u which is a i386_THREAD_STATE "
5163 "flavor in %s command %u)", nflavor
,
5164 ut
->cmd
== LC_UNIXTHREAD
? "LC_UNIXTHREAD" :
5168 cpu
= (i386_thread_state_t
*)state
;
5169 if(state
+ sizeof(i386_thread_state_t
) >
5170 (char *)ut
+ ut
->cmdsize
){
5171 Mach_O_error(ofile
, "malformed object ("
5172 "i386_THREAD_STATE in %s command %u "
5173 "extends past end of command)", ut
->cmd
==
5174 LC_UNIXTHREAD
? "LC_UNIXTHREAD" :
5179 swap_i386_thread_state(cpu
, host_byte_sex
);
5180 state
+= sizeof(i386_thread_state_t
);
5182 /* current i386 thread states */
5183 #if i386_THREAD_STATE == 1
5184 case i386_FLOAT_STATE
:
5185 if(count
!= i386_FLOAT_STATE_COUNT
){
5186 Mach_O_error(ofile
, "malformed object (count "
5187 "not i386_FLOAT_STATE_COUNT for flavor "
5188 "number %u which is a i386_FLOAT_STATE "
5189 "flavor in %s command %u)", nflavor
,
5190 ut
->cmd
== LC_UNIXTHREAD
? "LC_UNIXTHREAD" :
5194 fpu
= (struct i386_float_state
*)state
;
5195 if(state
+ sizeof(struct i386_float_state
) >
5196 (char *)ut
+ ut
->cmdsize
){
5197 Mach_O_error(ofile
, "malformed object ("
5198 "i386_FLOAT_STATE in %s command %u "
5199 "extends past end of command)", ut
->cmd
==
5200 LC_UNIXTHREAD
? "LC_UNIXTHREAD" :
5205 swap_i386_float_state(fpu
, host_byte_sex
);
5206 state
+= sizeof(struct i386_float_state
);
5208 case i386_EXCEPTION_STATE
:
5209 if(count
!= I386_EXCEPTION_STATE_COUNT
){
5210 Mach_O_error(ofile
, "malformed object (count "
5211 "not I386_EXCEPTION_STATE_COUNT for "
5212 "flavor number %u which is a i386_"
5213 "EXCEPTION_STATE flavor in %s command %u)",
5215 ut
->cmd
== LC_UNIXTHREAD
? "LC_UNIXTHREAD" :
5219 exc
= (i386_exception_state_t
*)state
;
5220 if(state
+ sizeof(i386_exception_state_t
) >
5221 (char *)ut
+ ut
->cmdsize
){
5222 Mach_O_error(ofile
, "malformed object ("
5223 "i386_EXCEPTION_STATE in %s command %u "
5224 "extends past end of command)", ut
->cmd
==
5225 LC_UNIXTHREAD
? "LC_UNIXTHREAD" :
5230 swap_i386_exception_state(exc
,host_byte_sex
);
5231 state
+= sizeof(i386_exception_state_t
);
5233 #endif /* i386_THREAD_STATE == 1 */
5235 /* i386 thread states on older releases */
5236 #if i386_THREAD_STATE == -1
5237 case i386_THREAD_FPSTATE
:
5238 if(count
!= i386_THREAD_FPSTATE_COUNT
){
5239 Mach_O_error(ofile
, "malformed object (count "
5240 "not i386_THREAD_FPSTATE_COUNT for flavor "
5241 "number %u which is a i386_THREAD_FPSTATE "
5242 "flavor in %s command %u)", nflavor
,
5243 ut
->cmd
== LC_UNIXTHREAD
? "LC_UNIXTHREAD" :
5247 fpu
= (i386_thread_fpstate_t
*)state
;
5248 if(state
+ sizeof(i386_thread_fpstate_t
) >
5249 (char *)ut
+ ut
->cmdsize
){
5250 Mach_O_error(ofile
, "malformed object ("
5251 "i386_THREAD_FPSTATE in %s command %u "
5252 "extends past end of command)", ut
->cmd
==
5253 LC_UNIXTHREAD
? "LC_UNIXTHREAD" :
5258 swap_i386_thread_fpstate(fpu
, host_byte_sex
);
5259 state
+= sizeof(i386_thread_fpstate_t
);
5261 case i386_THREAD_EXCEPTSTATE
:
5262 if(count
!= i386_THREAD_EXCEPTSTATE_COUNT
){
5263 Mach_O_error(ofile
, "malformed object (count "
5264 "not i386_THREAD_EXCEPTSTATE_COUNT for "
5265 "flavor number %u which is a i386_THREAD_"
5266 "EXCEPTSTATE flavor in %s command %u)",
5268 ut
->cmd
== LC_UNIXTHREAD
? "LC_UNIXTHREAD" :
5272 exc
= (i386_thread_exceptstate_t
*)state
;
5273 if(state
+ sizeof(i386_thread_exceptstate_t
) >
5274 (char *)ut
+ ut
->cmdsize
){
5275 Mach_O_error(ofile
, "malformed object ("
5276 "i386_THREAD_EXCEPTSTATE in %s command %u "
5277 "extends past end of command)", ut
->cmd
==
5278 LC_UNIXTHREAD
? "LC_UNIXTHREAD" :
5283 swap_i386_thread_exceptstate(exc
,host_byte_sex
);
5284 state
+= sizeof(i386_thread_exceptstate_t
);
5286 case i386_THREAD_CTHREADSTATE
:
5287 if(count
!= i386_THREAD_CTHREADSTATE_COUNT
){
5288 Mach_O_error(ofile
, "malformed object (count "
5289 "not i386_THREAD_CTHREADSTATE_COUNT for "
5290 "flavor number %u which is a i386_THREAD_"
5291 "CTHREADSTATE flavor in %s command %u)",
5293 ut
->cmd
== LC_UNIXTHREAD
? "LC_UNIXTHREAD" :
5297 user
= (i386_thread_cthreadstate_t
*)state
;
5298 if(state
+ sizeof(i386_thread_cthreadstate_t
) >
5299 (char *)ut
+ ut
->cmdsize
){
5300 Mach_O_error(ofile
, "malformed object ("
5301 "i386_THREAD_CTHREADSTATE in %s command %u "
5302 "extends past end of command)", ut
->cmd
==
5303 LC_UNIXTHREAD
? "LC_UNIXTHREAD" :
5308 swap_i386_thread_cthreadstate(user
,
5310 state
+= sizeof(i386_thread_cthreadstate_t
);
5312 #endif /* i386_THREAD_STATE == -1 */
5315 Mach_O_error(ofile
, "malformed object (unknown "
5316 "flavor for flavor number %u in %s command"
5317 " %u can't byte swap it)", nflavor
,
5318 ut
->cmd
== LC_UNIXTHREAD
? "LC_UNIXTHREAD" :
5322 state
+= count
* sizeof(uint32_t);
5329 #ifdef x86_THREAD_STATE64_COUNT
5330 if(cputype
== CPU_TYPE_X86_64
){
5331 x86_thread_state64_t
*cpu
;
5334 p
= (char *)ut
+ ut
->cmdsize
;
5336 if(state
+ sizeof(uint32_t) >
5337 (char *)ut
+ ut
->cmdsize
){
5338 Mach_O_error(ofile
, "malformed object (flavor in "
5339 "%s command %u extends past end of command)",
5340 ut
->cmd
== LC_UNIXTHREAD
? "LC_UNIXTHREAD" :
5344 flavor
= *((uint32_t *)state
);
5346 flavor
= SWAP_INT(flavor
);
5347 *((uint32_t *)state
) = flavor
;
5349 state
+= sizeof(uint32_t);
5350 if(state
+ sizeof(uint32_t) >
5351 (char *)ut
+ ut
->cmdsize
){
5352 Mach_O_error(ofile
, "malformed object (count in "
5353 "%s command %u extends past end of command)",
5354 ut
->cmd
== LC_UNIXTHREAD
? "LC_UNIXTHREAD" :
5358 count
= *((uint32_t *)state
);
5360 count
= SWAP_INT(count
);
5361 *((uint32_t *)state
) = count
;
5363 state
+= sizeof(uint32_t);
5365 case x86_THREAD_STATE64
:
5366 if(count
!= x86_THREAD_STATE64_COUNT
){
5367 Mach_O_error(ofile
, "malformed object (count "
5368 "not x86_THREAD_STATE64_COUNT for "
5369 "flavor number %u which is a x86_THREAD_"
5370 "STATE64 flavor in %s command %u)",
5371 nflavor
, ut
->cmd
== LC_UNIXTHREAD
?
5372 "LC_UNIXTHREAD" : "LC_THREAD", i
);
5375 cpu
= (x86_thread_state64_t
*)state
;
5376 if(state
+ sizeof(x86_thread_state64_t
) >
5377 (char *)ut
+ ut
->cmdsize
){
5378 Mach_O_error(ofile
, "malformed object ("
5379 "x86_THREAD_STATE64 in %s command %u "
5380 "extends past end of command)", ut
->cmd
==
5381 LC_UNIXTHREAD
? "LC_UNIXTHREAD" :
5386 swap_x86_thread_state64(cpu
, host_byte_sex
);
5387 state
+= sizeof(x86_thread_state64_t
);
5391 Mach_O_error(ofile
, "malformed object (unknown "
5392 "flavor for flavor number %u in %s command"
5393 " %u can't byte swap it)", nflavor
,
5394 ut
->cmd
== LC_UNIXTHREAD
? "LC_UNIXTHREAD" :
5398 state
+= count
* sizeof(uint32_t);
5405 #endif /* x86_THREAD_STATE64_COUNT */
5406 if(cputype
== CPU_TYPE_HPPA
){
5407 struct hp_pa_integer_thread_state
*cpu
;
5408 struct hp_pa_frame_thread_state
*frame
;
5409 struct hp_pa_fp_thread_state
*fpu
;
5412 p
= (char *)ut
+ ut
->cmdsize
;
5414 if(state
+ sizeof(uint32_t) >
5415 (char *)ut
+ ut
->cmdsize
){
5416 Mach_O_error(ofile
, "malformed object (flavor in "
5417 "%s command %u extends past end of command)",
5418 ut
->cmd
== LC_UNIXTHREAD
? "LC_UNIXTHREAD" :
5422 flavor
= *((uint32_t *)state
);
5424 flavor
= SWAP_INT(flavor
);
5425 *((uint32_t *)state
) = flavor
;
5427 state
+= sizeof(uint32_t);
5428 if(state
+ sizeof(uint32_t) >
5429 (char *)ut
+ ut
->cmdsize
){
5430 Mach_O_error(ofile
, "malformed object (count in "
5431 "%s command %u extends past end of command)",
5432 ut
->cmd
== LC_UNIXTHREAD
? "LC_UNIXTHREAD" :
5436 count
= *((uint32_t *)state
);
5438 count
= SWAP_INT(count
);
5439 *((uint32_t *)state
) = count
;
5441 state
+= sizeof(uint32_t);
5443 case HPPA_INTEGER_THREAD_STATE
:
5444 if(count
!= HPPA_INTEGER_THREAD_STATE_COUNT
){
5445 Mach_O_error(ofile
, "malformed object (count "
5446 "not HPPA_INTEGER_THREAD_STATE_COUNT for "
5447 "flavor number %u which is a "
5448 "HPPA_INTEGER_THREAD_STATE "
5449 "flavor in %s command %u)", nflavor
,
5450 ut
->cmd
== LC_UNIXTHREAD
? "LC_UNIXTHREAD" :
5454 cpu
= (struct hp_pa_integer_thread_state
*)state
;
5455 if(state
+sizeof(struct hp_pa_integer_thread_state
) >
5456 (char *)ut
+ ut
->cmdsize
){
5457 Mach_O_error(ofile
, "malformed object ("
5458 "HPPA_INTEGER_THREAD_STATE in %s command "
5459 "%u extends past end of command)",
5460 ut
->cmd
== LC_UNIXTHREAD
? "LC_UNIXTHREAD" :
5465 swap_hppa_integer_thread_state(cpu
,
5467 state
+= sizeof(struct hp_pa_integer_thread_state
);
5469 case HPPA_FRAME_THREAD_STATE
:
5470 if(count
!= HPPA_FRAME_THREAD_STATE_COUNT
){
5471 Mach_O_error(ofile
, "malformed object (count "
5472 "not HPPA_FRAME_THREAD_STATE_COUNT for "
5473 "flavor number %u which is a HPPA_FRAME_"
5474 "THREAD_STATE flavor in %s command %u)",
5476 ut
->cmd
== LC_UNIXTHREAD
? "LC_UNIXTHREAD" :
5480 frame
= (struct hp_pa_frame_thread_state
*)state
;
5481 if(state
+ sizeof(struct hp_pa_frame_thread_state
) >
5482 (char *)ut
+ ut
->cmdsize
){
5483 Mach_O_error(ofile
, "malformed object ("
5484 "HPPA_FRAME_THREAD_STATE in %s command "
5485 "%u extends past end of command)",
5486 ut
->cmd
== LC_UNIXTHREAD
? "LC_UNIXTHREAD" :
5491 swap_hppa_frame_thread_state(frame
,host_byte_sex
);
5492 state
+= sizeof(struct hp_pa_frame_thread_state
);
5494 case HPPA_FP_THREAD_STATE
:
5495 if(count
!= HPPA_FP_THREAD_STATE_COUNT
){
5496 Mach_O_error(ofile
, "malformed object (count "
5497 "not HPPA_FP_THREAD_STATE_COUNT for "
5498 "flavor number %u which is a HPPA_FP_"
5499 "THREAD_STATE flavor in %s command %u)",
5501 ut
->cmd
== LC_UNIXTHREAD
? "LC_UNIXTHREAD" :
5505 fpu
= (struct hp_pa_fp_thread_state
*)state
;
5506 if(state
+ sizeof(struct hp_pa_fp_thread_state
) >
5507 (char *)ut
+ ut
->cmdsize
){
5508 Mach_O_error(ofile
, "malformed object ("
5509 "HPPA_FP_THREAD_STATE in %s command "
5510 "%u extends past end of command)",
5511 ut
->cmd
== LC_UNIXTHREAD
? "LC_UNIXTHREAD" :
5516 swap_hppa_fp_thread_state(fpu
,host_byte_sex
);
5517 state
+= sizeof(struct hp_pa_fp_thread_state
);
5521 Mach_O_error(ofile
, "malformed object (unknown "
5522 "flavor for flavor number %u in %s command"
5523 " %u can't byte swap it)", nflavor
,
5524 ut
->cmd
== LC_UNIXTHREAD
? "LC_UNIXTHREAD" :
5528 state
+= count
* sizeof(uint32_t);
5535 if(cputype
== CPU_TYPE_SPARC
){
5536 struct sparc_thread_state_regs
*cpu
;
5537 struct sparc_thread_state_fpu
*fpu
;
5540 p
= (char *)ut
+ ut
->cmdsize
;
5542 if(state
+ sizeof(uint32_t) >
5543 (char *)ut
+ ut
->cmdsize
){
5544 Mach_O_error(ofile
, "malformed object (flavor in "
5545 "%s command %u extends past end of command)",
5546 ut
->cmd
== LC_UNIXTHREAD
? "LC_UNIXTHREAD" :
5550 flavor
= *((uint32_t *)state
);
5552 flavor
= SWAP_INT(flavor
);
5553 *((uint32_t *)state
) = flavor
;
5555 state
+= sizeof(uint32_t);
5556 if(state
+ sizeof(uint32_t) >
5557 (char *)ut
+ ut
->cmdsize
){
5558 Mach_O_error(ofile
, "malformed object (count in "
5559 "%s command %u extends past end of command)",
5560 ut
->cmd
== LC_UNIXTHREAD
? "LC_UNIXTHREAD" :
5564 count
= *((uint32_t *)state
);
5566 count
= SWAP_INT(count
);
5567 *((uint32_t *)state
) = count
;
5569 state
+= sizeof(uint32_t);
5571 case SPARC_THREAD_STATE_REGS
:
5572 if(count
!= SPARC_THREAD_STATE_REGS_COUNT
){
5573 Mach_O_error(ofile
, "malformed object (count "
5574 "not SPARC_THREAD_STATE_REGS_COUNT for "
5575 "flavor number %u which is a SPARC_THREAD_"
5576 "STATE_REGS flavor in %s command %u)",
5577 nflavor
, ut
->cmd
== LC_UNIXTHREAD
?
5578 "LC_UNIXTHREAD" : "LC_THREAD", i
);
5581 cpu
= (struct sparc_thread_state_regs
*)state
;
5582 if(state
+ sizeof(struct sparc_thread_state_regs
) >
5583 (char *)ut
+ ut
->cmdsize
){
5584 Mach_O_error(ofile
, "malformed object ("
5585 "SPARC_THREAD_STATE_REGS in %s command %u "
5586 "extends past end of command)", ut
->cmd
==
5587 LC_UNIXTHREAD
? "LC_UNIXTHREAD" :
5592 swap_sparc_thread_state_regs(cpu
, host_byte_sex
);
5593 state
+= sizeof(struct sparc_thread_state_regs
);
5595 case SPARC_THREAD_STATE_FPU
:
5596 if(count
!= SPARC_THREAD_STATE_FPU_COUNT
){
5597 Mach_O_error(ofile
, "malformed object (count "
5598 "not SPARC_THREAD_STATE_FPU_COUNT for "
5599 "flavor number %u which is a SPARC_THREAD_"
5600 "STATE_FPU flavor in %s command %u)",
5601 nflavor
, ut
->cmd
== LC_UNIXTHREAD
?
5602 "LC_UNIXTHREAD" : "LC_THREAD", i
);
5605 fpu
= (struct sparc_thread_state_fpu
*)state
;
5606 if(state
+ sizeof(struct sparc_thread_state_fpu
) >
5607 (char *)ut
+ ut
->cmdsize
){
5608 Mach_O_error(ofile
, "malformed object ("
5609 "SPARC_THREAD_STATE_FPU in %s command %u "
5610 "extends past end of command)", ut
->cmd
==
5611 LC_UNIXTHREAD
? "LC_UNIXTHREAD" :
5616 swap_sparc_thread_state_fpu(fpu
, host_byte_sex
);
5617 state
+= sizeof(struct sparc_thread_state_fpu
);
5621 Mach_O_error(ofile
, "malformed object (unknown "
5622 "flavor for flavor number %u in %s command"
5623 " %u can't byte swap it)", nflavor
,
5624 ut
->cmd
== LC_UNIXTHREAD
? "LC_UNIXTHREAD" :
5628 state
+= count
* sizeof(uint32_t);
5635 if(cputype
== CPU_TYPE_ARM
){
5636 arm_thread_state_t
*cpu
;
5639 p
= (char *)ut
+ ut
->cmdsize
;
5641 if(state
+ sizeof(uint32_t) >
5642 (char *)ut
+ ut
->cmdsize
){
5643 Mach_O_error(ofile
, "malformed object (flavor in "
5644 "%s command %u extends past end of command)",
5645 ut
->cmd
== LC_UNIXTHREAD
? "LC_UNIXTHREAD" :
5649 flavor
= *((uint32_t *)state
);
5651 flavor
= SWAP_INT(flavor
);
5652 *((uint32_t *)state
) = flavor
;
5654 state
+= sizeof(uint32_t);
5655 if(state
+ sizeof(uint32_t) >
5656 (char *)ut
+ ut
->cmdsize
){
5657 Mach_O_error(ofile
, "malformed object (count in "
5658 "%s command %u extends past end of command)",
5659 ut
->cmd
== LC_UNIXTHREAD
? "LC_UNIXTHREAD" :
5663 count
= *((uint32_t *)state
);
5665 count
= SWAP_INT(count
);
5666 *((uint32_t *)state
) = count
;
5668 state
+= sizeof(uint32_t);
5670 case ARM_THREAD_STATE
:
5671 if(count
!= ARM_THREAD_STATE_COUNT
){
5672 Mach_O_error(ofile
, "malformed object (count "
5673 "not ARM_THREAD_STATE_COUNT for "
5674 "flavor number %u which is a ARM_THREAD_"
5675 "STATE flavor in %s command %u)",
5676 nflavor
, ut
->cmd
== LC_UNIXTHREAD
?
5677 "LC_UNIXTHREAD" : "LC_THREAD", i
);
5680 cpu
= (arm_thread_state_t
*)state
;
5681 if(state
+ sizeof(arm_thread_state_t
) >
5682 (char *)ut
+ ut
->cmdsize
){
5683 Mach_O_error(ofile
, "malformed object ("
5684 "ARM_THREAD_STATE in %s command %u "
5685 "extends past end of command)", ut
->cmd
==
5686 LC_UNIXTHREAD
? "LC_UNIXTHREAD" :
5691 swap_arm_thread_state_t(cpu
, host_byte_sex
);
5692 state
+= sizeof(arm_thread_state_t
);
5696 Mach_O_error(ofile
, "malformed object (unknown "
5697 "flavor for flavor number %u in %s command"
5698 " %u can't byte swap it)", nflavor
,
5699 ut
->cmd
== LC_UNIXTHREAD
? "LC_UNIXTHREAD" :
5703 state
+= count
* sizeof(uint32_t);
5711 Mach_O_error(ofile
, "malformed object (unknown cputype and "
5712 "cpusubtype of object and can't byte swap and check %s "
5713 "command %u)", ut
->cmd
== LC_UNIXTHREAD
?
5714 "LC_UNIXTHREAD" : "LC_THREAD", i
);
5719 if(l
.cmdsize
< sizeof(struct entry_point_command
)){
5720 Mach_O_error(ofile
, "malformed object (LC_MAIN cmdsize "
5721 "too small) in command %u", i
);
5724 ep
= (struct entry_point_command
*)lc
;
5726 swap_entry_point_command(ep
, host_byte_sex
);
5728 * If we really wanted we could check that the entryoff field
5729 * really is an offset into the __TEXT segment. But since it
5730 * is not used here, we won't needlessly check it.
5733 case LC_SOURCE_VERSION
:
5734 if(l
.cmdsize
< sizeof(struct source_version_command
)){
5735 Mach_O_error(ofile
, "malformed object (LC_SOURCE_VERSION "
5736 "cmdsize too small) in command %u", i
);
5739 sv
= (struct source_version_command
*)lc
;
5741 swap_source_version_command(sv
, host_byte_sex
);
5743 if(l
.cmdsize
< sizeof(struct ident_command
)){
5744 Mach_O_error(ofile
, "malformed object (LC_IDENT cmdsize "
5745 "too small) in command %u", i
);
5748 id
= (struct ident_command
*)lc
;
5750 swap_ident_command(id
, host_byte_sex
);
5752 * Note the cmdsize field if the LC_IDENT command was checked
5753 * as part of checking all load commands cmdsize field before
5754 * the switch statement on the cmd field of the load command.
5758 if(l
.cmdsize
< sizeof(struct rpath_command
)){
5759 Mach_O_error(ofile
, "malformed object (LC_RPATH: cmdsize "
5760 "too small) in command %u", i
);
5763 rpath
= (struct rpath_command
*)lc
;
5765 swap_rpath_command(rpath
, host_byte_sex
);
5766 if(rpath
->cmdsize
< sizeof(struct rpath_command
)){
5767 Mach_O_error(ofile
, "malformed object (LC_RPATH command "
5768 "%u has too small cmdsize field)", i
);
5771 if(rpath
->path
.offset
>= rpath
->cmdsize
){
5772 Mach_O_error(ofile
, "truncated or malformed object (path."
5773 "offset field of LC_RPATH command %u extends past the "
5774 "end of the file)", i
);
5781 Mach_O_error(ofile
, "malformed object (unknown load command "
5784 #endif /* !defined(OFI) */
5787 lc
= (struct load_command
*)((char *)lc
+ l
.cmdsize
);
5788 /* check that next load command does not extends past the end */
5789 if((char *)lc
> (char *)load_commands
+ sizeofcmds
){
5790 Mach_O_error(ofile
, "truncated or malformed object (load "
5791 "command %u extends past the end of the file)",
5798 Mach_O_error(ofile
, "truncated or malformed object (contains "
5799 "LC_DYSYMTAB load command without a LC_SYMTAB load command)");
5805 if(dyst
->nlocalsym
!= 0 &&
5806 dyst
->ilocalsym
> st
->nsyms
){
5807 Mach_O_error(ofile
, "truncated or malformed object "
5808 "(ilocalsym in LC_DYSYMTAB load command extends past "
5809 "the end of the symbol table)");
5812 big_size
= dyst
->ilocalsym
;
5813 big_size
+= dyst
->nlocalsym
;
5814 if(dyst
->nlocalsym
!= 0 && big_size
> st
->nsyms
){
5815 Mach_O_error(ofile
, "truncated or malformed object "
5816 "(ilocalsym plus nlocalsym in LC_DYSYMTAB load command "
5817 "extends past the end of the symbol table)");
5821 if(dyst
->nextdefsym
!= 0 &&
5822 dyst
->iextdefsym
> st
->nsyms
){
5823 Mach_O_error(ofile
, "truncated or malformed object "
5824 "(iextdefsym in LC_DYSYMTAB load command extends past "
5825 "the end of the symbol table)");
5828 big_size
= dyst
->iextdefsym
;
5829 big_size
+= dyst
->nextdefsym
;
5830 if(dyst
->nextdefsym
!= 0 && big_size
> st
->nsyms
){
5831 Mach_O_error(ofile
, "truncated or malformed object "
5832 "(iextdefsym plus nextdefsym in LC_DYSYMTAB load "
5833 "command extends past the end of the symbol table)");
5837 if(dyst
->nundefsym
!= 0 &&
5838 dyst
->iundefsym
> st
->nsyms
){
5839 Mach_O_error(ofile
, "truncated or malformed object "
5840 "(iundefsym in LC_DYSYMTAB load command extends past "
5841 "the end of the symbol table)");
5844 big_size
= dyst
->iundefsym
;
5845 big_size
+= dyst
->nundefsym
;
5846 if(dyst
->nundefsym
!= 0 && big_size
> st
->nsyms
){
5847 Mach_O_error(ofile
, "truncated or malformed object "
5848 "(iundefsym plus nundefsym in LC_DYSYMTAB load command "
5849 "extends past the end of the symbol table)");
5853 if(rc
->init_module
> dyst
->nmodtab
){
5854 Mach_O_error(ofile
, "malformed object (init_module in "
5855 "LC_ROUTINES load command extends past the "
5856 "end of the module table)");
5861 if(rc64
->init_module
> dyst
->nmodtab
){
5862 Mach_O_error(ofile
, "malformed object (init_module in "
5863 "LC_ROUTINES_64 load command extends past the "
5864 "end of the module table)");
5869 if(hints
->nhints
!= dyst
->nundefsym
){
5870 Mach_O_error(ofile
, "malformed object (nhints in "
5871 "LC_TWOLEVEL_HINTS load command not the same as "
5872 "nundefsym in LC_DYSYMTAB load command)");
5878 /* check for an inconsistent size of the load commands */
5879 if((char *)load_commands
+ sizeofcmds
!= (char *)lc
){
5880 Mach_O_error(ofile
, "malformed object (inconsistent sizeofcmds "
5881 "field in mach header)");
5886 * Mark this ofile so we know its headers have been swapped. We do this
5887 * in case we don't process it the first time so we can swap them back
5888 * in case we loop back to it in a fat file to process it later.
5891 ofile
->headers_swapped
= TRUE
;
5893 /* looks good return ok */
5894 free_elements(&elements
);
5898 free_elements(&elements
);
5904 * swap_back_Mach_O() is called after the ofile has been processed to swap back
5905 * the mach header and load commands if check_Mach_O() above swapped them.
5910 struct ofile
*ofile
)
5912 if(ofile
->headers_swapped
== TRUE
){
5913 ofile
->headers_swapped
= FALSE
;
5914 if(ofile
->mh
!= NULL
)
5915 swap_object_headers(ofile
->mh
, ofile
->load_commands
);
5916 else if(ofile
->mh64
!= NULL
)
5917 swap_object_headers(ofile
->mh64
, ofile
->load_commands
);
5923 * check_overlaping_element() checks that the element in the ofile described by
5924 * offset, size and name does not overlap in list of elements in head. If it
5925 * does CHECK_BAD is returned and an error message is generated. If it doesn't
5926 * then an element is added in the ordered list and CHECK_GOOD is returned
5930 check_overlaping_element(
5931 struct ofile
*ofile
,
5932 struct element
*head
,
5937 struct element
*e
, *p
, *n
;
5942 if(head
->next
== NULL
){
5943 n
= allocate(sizeof(struct element
));
5954 while(e
->next
!= NULL
){
5957 if((offset
>= e
->offset
&&
5958 offset
< e
->offset
+ e
->size
) ||
5959 (offset
+ size
> e
->offset
&&
5960 offset
+ size
< e
->offset
+ e
->size
) ||
5961 (offset
<= e
->offset
&&
5962 offset
+ size
>= e
->offset
+ e
->size
)){
5963 Mach_O_error(ofile
, "malformed object (%s at offset %u with a "
5964 "size of %u, overlaps %s at offset %u with a size of %u)",
5965 name
, offset
, size
, e
->name
, e
->offset
, e
->size
);
5968 if(e
->next
!= NULL
&& offset
+ size
<= e
->next
->offset
){
5969 n
= allocate(sizeof(struct element
));
5978 n
= allocate(sizeof(struct element
));
5988 * free_elements() frees the list of elements on the list head.
5993 struct element
*head
)
5995 struct element
*e
, *e_next
;
6004 #endif /* !defined(OTOOL) */
6007 * check_dylib_module() checks the object file's dylib_module as referenced
6008 * by the dylib_module field in the ofile for correctness.
6013 struct ofile
*ofile
,
6014 struct symtab_command
*st
,
6015 struct dysymtab_command
*dyst
,
6017 uint32_t module_index
)
6021 #else /* !defined OTOOL */
6023 enum byte_sex host_byte_sex
;
6025 struct dylib_module m
;
6026 struct dylib_module_64 m64
;
6027 uint32_t module_name
, nextdefsym
, iextdefsym
, nlocalsym
, ilocalsym
, nrefsym
;
6028 uint32_t irefsym
, nextrel
, iextrel
;
6030 host_byte_sex
= get_host_byte_sex();
6031 swapped
= (enum bool)(host_byte_sex
!= ofile
->object_byte_sex
);
6032 if(ofile
->mh
!= NULL
){
6033 m
= *ofile
->dylib_module
;
6035 swap_dylib_module(&m
, 1, host_byte_sex
);
6036 module_name
= m
.module_name
;
6037 nextdefsym
= m
.nextdefsym
;
6038 iextdefsym
= m
.iextdefsym
;
6039 nlocalsym
= m
.nlocalsym
;
6040 ilocalsym
= m
.ilocalsym
;
6041 nrefsym
= m
.nrefsym
;
6042 irefsym
= m
.irefsym
;
6043 nextrel
= m
.nextrel
;
6044 iextrel
= m
.iextrel
;
6047 m64
= *ofile
->dylib_module64
;
6049 swap_dylib_module_64(&m64
, 1, host_byte_sex
);
6050 module_name
= m64
.module_name
;
6051 nextdefsym
= m64
.nextdefsym
;
6052 iextdefsym
= m64
.iextdefsym
;
6053 nlocalsym
= m64
.nlocalsym
;
6054 ilocalsym
= m64
.ilocalsym
;
6055 nrefsym
= m64
.nrefsym
;
6056 irefsym
= m64
.irefsym
;
6057 nextrel
= m64
.nextrel
;
6058 iextrel
= m64
.iextrel
;
6061 if(module_name
> st
->strsize
){
6062 Mach_O_error(ofile
, "truncated or malformed object (module_name "
6063 "of module table entry %u past the end of the string table)",
6067 for(i
= module_name
; i
< st
->strsize
&& strings
[i
] != '\0'; i
++)
6069 if(i
>= st
->strsize
){
6070 Mach_O_error(ofile
, "truncated or malformed object (module_name "
6071 "of module table entry %u extends past the end of the string "
6072 "table)", module_index
);
6076 if(nextdefsym
!= 0){
6077 if(iextdefsym
> st
->nsyms
){
6078 Mach_O_error(ofile
, "truncated or malformed object (iextdefsym "
6079 "field of module table entry %u past the end of the "
6080 "symbol table", module_index
);
6083 if(iextdefsym
+ nextdefsym
> st
->nsyms
){
6084 Mach_O_error(ofile
, "truncated or malformed object (iextdefsym "
6085 "field of module table entry %u plus nextdefsym field "
6086 "extends past the end of the symbol table", module_index
);
6091 if(ilocalsym
> st
->nsyms
){
6092 Mach_O_error(ofile
, "truncated or malformed object (ilocalsym "
6093 "field of module table entry %u past the end of the "
6094 "symbol table", module_index
);
6097 if(ilocalsym
+ nlocalsym
> st
->nsyms
){
6098 Mach_O_error(ofile
, "truncated or malformed object (ilocalsym "
6099 "field of module table entry %u plus nlocalsym field "
6100 "extends past the end of the symbol table", module_index
);
6105 if(irefsym
> dyst
->nextrefsyms
){
6106 Mach_O_error(ofile
, "truncated or malformed object (irefsym "
6107 "field of module table entry %u past the end of the "
6108 "reference table", module_index
);
6111 if(irefsym
+ nrefsym
> dyst
->nextrefsyms
){
6112 Mach_O_error(ofile
, "truncated or malformed object (irefsym "
6113 "field of module table entry %u plus nrefsym field "
6114 "extends past the end of the reference table",module_index
);
6119 if(iextrel
> dyst
->extreloff
){
6120 Mach_O_error(ofile
, "truncated or malformed object (iextrel "
6121 "field of module table entry %u past the end of the "
6122 "external relocation enrties", module_index
);
6125 if(iextrel
+ nextrel
> dyst
->extreloff
){
6126 Mach_O_error(ofile
, "truncated or malformed object (iextrel "
6127 "field of module table entry %u plus nextrel field "
6128 "extends past the end of the external relocation enrties",
6140 const struct ar_hdr
*ar_hdr
)
6144 i
= sizeof(ar_hdr
->ar_name
) - 1;
6145 if(ar_hdr
->ar_name
[i
] == ' '){
6147 if(ar_hdr
->ar_name
[i
] != ' ')
6154 #endif /* !defined(RLD) */