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
;
839 magic
= 0; /* to shut up the compiler warning message */
840 memset(ofile
, '\0', sizeof(struct ofile
));
842 /* Open the file and map it in */
843 if((fd
= open(file_name
, O_RDONLY
)) == -1){
845 return(NSObjectFileImageAccess
);
847 system_error("can't open file: %s", file_name
);
851 if(fstat(fd
, &stat_buf
) == -1){
854 return(NSObjectFileImageAccess
);
856 system_error("can't stat file: %s", file_name
);
860 size
= stat_buf
.st_size
;
864 addr
= mmap(0, size
, PROT_READ
|PROT_WRITE
, MAP_FILE
|MAP_PRIVATE
, fd
,
866 if((intptr_t)addr
== -1){
867 system_error("can't map file: %s", file_name
);
874 if(otool_first_ofile_map
&& Wflag
)
875 printf("Modification time = %ld\n", (long int)stat_buf
.st_mtime
);
878 return(ofile_map_from_memory(addr
, size
, file_name
, stat_buf
.st_mtime
,
879 arch_flag
, object_name
, ofile
, archives_with_fat_objects
));
883 * ofile_map_from_memory() is the guts of ofile_map() but with an interface
884 * to pass the address and size of the file already mapped in.
888 NSObjectFileImageReturnCode
892 ofile_map_from_memory(
895 const char *file_name
,
897 const struct arch_flag
*arch_flag
, /* can be NULL */
898 const char *object_name
, /* can be NULL */
900 enum bool archives_with_fat_objects
)
904 enum byte_sex host_byte_sex
;
905 struct arch_flag host_arch_flag
;
907 const struct arch_flag
*family_arch_flag
;
910 uint32_t small_nfat_arch
;
913 /* fill in the start of the ofile structure */
914 ofile
->file_name
= savestr(file_name
);
915 if(ofile
->file_name
== NULL
)
917 ofile
->file_addr
= addr
;
918 ofile
->file_size
= size
;
919 ofile
->file_mtime
= mtime
;
921 /* Try to figure out what kind of file this is */
923 if(size
>= sizeof(uint32_t)){
924 magic
= *((uint32_t *)addr
);
926 host_byte_sex
= get_host_byte_sex();
928 /* see if this file is a fat file (always in big endian byte sex) */
929 #ifdef __BIG_ENDIAN__
930 if(size
>= sizeof(struct fat_header
) && magic
== FAT_MAGIC
)
931 #endif /* __BIG_ENDIAN__ */
932 #ifdef __LITTLE_ENDIAN__
933 if(size
>= sizeof(struct fat_header
) && SWAP_INT(magic
) == FAT_MAGIC
)
934 #endif /* __LITTLE_ENDIAN__ */
936 ofile
->file_type
= OFILE_FAT
;
937 ofile
->fat_header
= (struct fat_header
*)addr
;
938 #ifdef __LITTLE_ENDIAN__
939 swap_fat_header(ofile
->fat_header
, host_byte_sex
);
940 #endif /* __LITTLE_ENDIAN__ */
942 if(otool_first_ofile_map
&& fflag
)
943 printf("Fat headers\n");
945 big_size
= ofile
->fat_header
->nfat_arch
;
946 big_size
*= sizeof(struct fat_arch
);
947 big_size
+= sizeof(struct fat_header
);
950 error("fat file: %s truncated or malformed (fat_arch structs "
951 "would extend past the end of the file)", file_name
);
952 ofile
->fat_archs
= allocate(size
- sizeof(struct fat_header
));
953 memset(ofile
->fat_archs
, '\0',
954 size
- sizeof(struct fat_header
));
955 memcpy(ofile
->fat_archs
,
956 addr
+ sizeof(struct fat_header
),
957 size
- sizeof(struct fat_header
));
958 small_nfat_arch
= (size
- sizeof(struct fat_header
)) /
959 sizeof(struct fat_arch
);
960 #ifdef __LITTLE_ENDIAN__
961 swap_fat_arch(ofile
->fat_archs
, small_nfat_arch
,
963 #endif /* __LITTLE_ENDIAN__ */
964 if(otool_first_ofile_map
&& fflag
)
965 print_fat_headers(ofile
->fat_header
, ofile
->fat_archs
,
967 free(ofile
->fat_archs
);
970 #else /* !defined(OTOOL) */
974 ofile
->fat_archs
= (struct fat_arch
*)(addr
+
975 sizeof(struct fat_header
));
976 #ifdef __LITTLE_ENDIAN__
977 swap_fat_arch(ofile
->fat_archs
, ofile
->fat_header
->nfat_arch
,
979 #endif /* __LITTLE_ENDIAN__ */
981 if(otool_first_ofile_map
&& fflag
)
982 print_fat_headers(ofile
->fat_header
, ofile
->fat_archs
,
985 if(check_fat(ofile
) == CHECK_BAD
){
988 return(NSObjectFileImageFormat
);
994 * Now that the fat file is mapped fill in the ofile to the level
995 * the caller wants based on the arch_flag and object_name passed.
996 * If the caller did not specify an arch_flag or an object_name
997 * then everything the caller wants is done.
999 if(arch_flag
== NULL
&& object_name
== NULL
)
1001 if(arch_flag
== NULL
){
1002 if(get_arch_from_host(&host_arch_flag
, NULL
) == 0){
1003 error("can't determine the host architecture (specify an "
1004 "arch_flag or fix get_arch_from_host() )");
1007 ofile
->arch_flag
.name
= savestr(host_arch_flag
.name
);
1008 if(ofile
->arch_flag
.name
== NULL
)
1010 ofile
->arch_flag
.cputype
= host_arch_flag
.cputype
;
1011 ofile
->arch_flag
.cpusubtype
= host_arch_flag
.cpusubtype
;
1014 ofile
->arch_flag
.name
= savestr(arch_flag
->name
);
1015 if(ofile
->arch_flag
.name
== NULL
)
1017 ofile
->arch_flag
.cputype
= arch_flag
->cputype
;
1018 ofile
->arch_flag
.cpusubtype
= arch_flag
->cpusubtype
;
1021 ofile
->narch
= UINT_MAX
;
1022 for(i
= 0; i
< ofile
->fat_header
->nfat_arch
; i
++){
1023 if(ofile
->fat_archs
[i
].cputype
==
1024 ofile
->arch_flag
.cputype
&&
1025 (ofile
->fat_archs
[i
].cpusubtype
& ~CPU_SUBTYPE_MASK
) ==
1026 (ofile
->arch_flag
.cpusubtype
& ~CPU_SUBTYPE_MASK
)){
1031 if(ofile
->narch
== UINT_MAX
){
1034 get_arch_family_from_cputype(ofile
->arch_flag
.cputype
);
1035 if(family_arch_flag
!= NULL
)
1036 family
= (enum bool)
1037 ((family_arch_flag
->cpusubtype
& ~CPU_SUBTYPE_MASK
) ==
1038 (ofile
->arch_flag
.cpusubtype
& ~CPU_SUBTYPE_MASK
));
1039 ofile
->narch
= UINT_MAX
;
1040 for(i
= 0; i
< ofile
->fat_header
->nfat_arch
; i
++){
1041 if(ofile
->fat_archs
[i
].cputype
==
1042 ofile
->arch_flag
.cputype
&&
1044 (ofile
->fat_archs
[i
].cpusubtype
& ~CPU_SUBTYPE_MASK
) ==
1045 (ofile
->arch_flag
.cpusubtype
& ~CPU_SUBTYPE_MASK
))){
1046 ofile
->arch_flag
.cpusubtype
=
1047 ofile
->fat_archs
[i
].cpusubtype
;
1053 if(ofile
->narch
== UINT_MAX
){
1056 return(NSObjectFileImageArch
);
1058 error("fat file: %s does not contain architecture %s",
1059 ofile
->file_name
, arch_flag
->name
);
1064 /* Now determine the file type for this specific architecture */
1065 size
= ofile
->fat_archs
[i
].size
;
1066 addr
= addr
+ ofile
->fat_archs
[i
].offset
;
1067 if(size
>= sizeof(struct mach_header
))
1068 memcpy(&magic
, addr
, sizeof(uint32_t));
1069 /* see if this file is a 32-bit Mach-O file */
1070 if(size
>= sizeof(struct mach_header
) &&
1071 (magic
== MH_MAGIC
||
1072 magic
== SWAP_INT(MH_MAGIC
))){
1073 #ifdef ALIGNMENT_CHECKS
1074 if(ofile
->fat_archs
[i
].offset
% 4 != 0){
1075 error("fat file: %s architecture %s malformed for a 32-bit "
1076 "object file (offset is not a multiple of 4)",
1077 ofile
->file_name
, arch_flag
->name
);
1080 return(NSObjectFileImageFormat
);
1085 #endif /* ALIGNMENT_CHECKS */
1086 ofile
->arch_type
= OFILE_Mach_O
;
1087 ofile
->object_addr
= addr
;
1088 ofile
->object_size
= size
;
1089 if(magic
== MH_MAGIC
)
1090 ofile
->object_byte_sex
= host_byte_sex
;
1092 ofile
->object_byte_sex
=
1093 host_byte_sex
== BIG_ENDIAN_BYTE_SEX
?
1094 LITTLE_ENDIAN_BYTE_SEX
: BIG_ENDIAN_BYTE_SEX
;
1095 ofile
->mh
= (struct mach_header
*)addr
;
1096 ofile
->load_commands
= (struct load_command
*)(addr
+
1097 sizeof(struct mach_header
));
1098 if(check_Mach_O(ofile
) == CHECK_BAD
){
1101 return(NSObjectFileImageFormat
);
1106 if(object_name
!= NULL
){
1107 error("fat file: %s architecture %s is not an archive "
1108 "(object_name to ofile_map() can't be specified to "
1109 "be other than NULL)", ofile
->file_name
,
1114 /* see if this file is a 64-bit Mach-O file */
1115 else if(size
>= sizeof(struct mach_header_64
) &&
1116 (magic
== MH_MAGIC_64
||
1117 magic
== SWAP_INT(MH_MAGIC_64
))){
1118 #ifdef ALIGNMENT_CHECKS
1119 if(ofile
->fat_archs
[i
].offset
% 8 != 0){
1120 error("fat file: %s architecture %s malformed for a 64-bit "
1121 "object file (offset is not a multiple of 8)",
1122 ofile
->file_name
, arch_flag
->name
);
1125 return(NSObjectFileImageFormat
);
1130 #endif /* ALIGNMENT_CHECKS */
1131 ofile
->arch_type
= OFILE_Mach_O
;
1132 ofile
->object_addr
= addr
;
1133 ofile
->object_size
= size
;
1134 if(magic
== MH_MAGIC_64
)
1135 ofile
->object_byte_sex
= host_byte_sex
;
1137 ofile
->object_byte_sex
=
1138 host_byte_sex
== BIG_ENDIAN_BYTE_SEX
?
1139 LITTLE_ENDIAN_BYTE_SEX
: BIG_ENDIAN_BYTE_SEX
;
1140 ofile
->mh64
= (struct mach_header_64
*)addr
;
1141 ofile
->load_commands
= (struct load_command
*)(addr
+
1142 sizeof(struct mach_header_64
));
1143 if(check_Mach_O(ofile
) == CHECK_BAD
){
1146 return(NSObjectFileImageFormat
);
1151 if(object_name
!= NULL
){
1152 error("fat file: %s architecture %s is not an archive "
1153 "(object_name to ofile_map() can't be specified to "
1154 "be other than NULL)", ofile
->file_name
,
1159 /* see if this file is an archive file */
1160 else if(size
>= SARMAG
&& strncmp(addr
, ARMAG
, SARMAG
) == 0){
1161 ofile
->arch_type
= OFILE_ARCHIVE
;
1162 if(check_archive(ofile
, FALSE
) == CHECK_BAD
){
1165 return(NSObjectFileImageInappropriateFile
);
1170 #ifdef ALIGNMENT_CHECKS
1171 if(ofile
->archive_cputype
!= 0 &&
1172 ofile
->fat_archs
[i
].offset
% sizeof(uint32_t) != 0){
1173 error("fat file: %s architecture %s malformed archive that "
1174 "contains object files (offset to archive is not a "
1175 "multiple of sizeof(uint32_t))",
1176 ofile
->file_name
, arch_flag
->name
);
1179 return(NSObjectFileImageInappropriateFile
);
1184 #endif /* ALIGNMENT_CHECKS */
1185 if(object_name
!= NULL
){
1186 if(ofile_specific_member(object_name
, ofile
) == FALSE
)
1190 /* this file type is now known to be unknown to this program */
1192 ofile
->file_type
= OFILE_UNKNOWN
;
1193 if(object_name
!= NULL
){
1194 error("fat file: %s architecture %s is not an archive "
1195 "(object_name to ofile_map() can't be specified to "
1196 "be other than NULL)", ofile
->file_name
,
1202 /* see if this file is a 32-bit Mach-O file */
1203 else if(size
>= sizeof(struct mach_header
) &&
1204 (magic
== MH_MAGIC
||
1205 magic
== SWAP_INT(MH_MAGIC
))){
1206 ofile
->file_type
= OFILE_Mach_O
;
1207 ofile
->object_addr
= addr
;
1208 ofile
->object_size
= size
;
1209 if(magic
== MH_MAGIC
)
1210 ofile
->object_byte_sex
= host_byte_sex
;
1212 ofile
->object_byte_sex
= host_byte_sex
== BIG_ENDIAN_BYTE_SEX
?
1213 LITTLE_ENDIAN_BYTE_SEX
: BIG_ENDIAN_BYTE_SEX
;
1214 ofile
->mh
= (struct mach_header
*)addr
;
1215 ofile
->load_commands
= (struct load_command
*)(addr
+
1216 sizeof(struct mach_header
));
1217 if(check_Mach_O(ofile
) == CHECK_BAD
){
1220 return(NSObjectFileImageFormat
);
1225 if(object_name
!= NULL
){
1226 error("file: %s is not an archive (object_name to ofile_map() "
1227 "can't be specified to be other than NULL)",
1231 if(arch_flag
!= NULL
){
1232 if(arch_flag
->cputype
!= ofile
->mh_cputype
&&
1233 (arch_flag
->cpusubtype
& ~CPU_SUBTYPE_MASK
) !=
1234 (ofile
->mh_cpusubtype
& ~CPU_SUBTYPE_MASK
)){
1237 return(NSObjectFileImageArch
);
1239 error("object file: %s does not match specified arch_flag: "
1240 "%s passed to ofile_map()", ofile
->file_name
,
1249 /* see if this file is a 64-bit Mach-O file */
1250 else if(size
>= sizeof(struct mach_header_64
) &&
1251 (magic
== MH_MAGIC_64
||
1252 magic
== SWAP_INT(MH_MAGIC_64
))){
1253 ofile
->file_type
= OFILE_Mach_O
;
1254 ofile
->object_addr
= addr
;
1255 ofile
->object_size
= size
;
1256 if(magic
== MH_MAGIC_64
)
1257 ofile
->object_byte_sex
= host_byte_sex
;
1259 ofile
->object_byte_sex
= host_byte_sex
== BIG_ENDIAN_BYTE_SEX
?
1260 LITTLE_ENDIAN_BYTE_SEX
: BIG_ENDIAN_BYTE_SEX
;
1261 ofile
->mh64
= (struct mach_header_64
*)addr
;
1262 ofile
->load_commands
= (struct load_command
*)(addr
+
1263 sizeof(struct mach_header_64
));
1264 if(check_Mach_O(ofile
) == CHECK_BAD
){
1267 return(NSObjectFileImageFormat
);
1272 if(object_name
!= NULL
){
1273 error("file: %s is not an archive (object_name to ofile_map() "
1274 "can't be specified to be other than NULL)",
1278 if(arch_flag
!= NULL
){
1279 if(arch_flag
->cputype
!= ofile
->mh_cputype
&&
1280 (arch_flag
->cpusubtype
& ~CPU_SUBTYPE_MASK
) !=
1281 (ofile
->mh_cpusubtype
& ~CPU_SUBTYPE_MASK
)){
1284 return(NSObjectFileImageArch
);
1286 error("object file: %s does not match specified arch_flag: "
1287 "%s passed to ofile_map()", ofile
->file_name
,
1296 /* see if this file is an archive file */
1297 else if(size
>= SARMAG
&& strncmp(addr
, ARMAG
, SARMAG
) == 0){
1298 ofile
->file_type
= OFILE_ARCHIVE
;
1299 if(check_archive(ofile
, archives_with_fat_objects
) == CHECK_BAD
)
1301 if(object_name
!= NULL
){
1302 if(ofile_specific_member(object_name
, ofile
) == FALSE
)
1304 if(arch_flag
!= NULL
){
1305 if(arch_flag
->cputype
!= ofile
->mh_cputype
&&
1306 (arch_flag
->cpusubtype
& ~CPU_SUBTYPE_MASK
) !=
1307 (ofile
->mh_cpusubtype
& ~CPU_SUBTYPE_MASK
)){
1308 error("object file: %s(%.*s) does not match specified "
1309 "arch_flag: %s passed to ofile_map()",
1310 ofile
->file_name
, (int)ofile
->member_name_size
,
1311 ofile
->member_name
, arch_flag
->name
);
1317 if(arch_flag
!= NULL
){
1318 if(arch_flag
->cputype
!= ofile
->archive_cputype
&&
1319 (arch_flag
->cpusubtype
& ~CPU_SUBTYPE_MASK
) !=
1320 (ofile
->archive_cpusubtype
& ~CPU_SUBTYPE_MASK
)){
1321 error("archive file: %s objects do not match specified "
1322 "arch_flag: %s passed to ofile_map()",
1323 ofile
->file_name
, arch_flag
->name
);
1329 /* this file type is now known to be unknown to this program */
1336 if(is_llvm_bitcode(ofile
, ofile
->file_addr
, ofile
->file_size
) ==
1338 ofile
->file_type
= OFILE_LLVM_BITCODE
;
1339 if(arch_flag
!= NULL
){
1340 if(arch_flag
->cputype
!= ofile
->lto_cputype
&&
1341 (arch_flag
->cpusubtype
& ~CPU_SUBTYPE_MASK
) !=
1342 (ofile
->lto_cpusubtype
& ~CPU_SUBTYPE_MASK
)){
1343 error("llvm bitcode file: %s does not match specified "
1344 "arch_flag: %s passed to ofile_map()",
1345 ofile
->file_name
, arch_flag
->name
);
1349 if(object_name
!= NULL
){
1350 error("file: %s is not an archive (object_name to "
1351 "ofile_map() can't be specified to be other than "
1352 "NULL)", ofile
->file_name
);
1358 #endif /* LTO_SUPPORT */
1360 ofile
->file_type
= OFILE_UNKNOWN
;
1361 if(arch_flag
!= NULL
){
1364 return(NSObjectFileImageInappropriateFile
);
1366 error("file: %s is unknown type (arch_flag to ofile_map() "
1367 "can't be specified to be other than NULL)",
1373 if(object_name
!= NULL
){
1374 error("file: %s is not an archive (object_name to ofile_map() "
1375 "can't be specified to be other than NULL)",
1389 * ofile_unmap() deallocates the memory associated with the specified ofile
1395 struct ofile
*ofile
)
1399 if(ofile
->file_addr
!= NULL
){
1400 if((r
= vm_deallocate(mach_task_self(),
1401 (vm_address_t
)ofile
->file_addr
,
1402 (vm_size_t
)ofile
->file_size
)) != KERN_SUCCESS
){
1403 my_mach_error(r
, "Can't vm_deallocate mapped memory for file: "
1404 "%s", ofile
->file_name
);
1407 if(ofile
->file_name
!= NULL
)
1408 free(ofile
->file_name
);
1409 if(ofile
->arch_flag
.name
!= NULL
)
1410 free(ofile
->arch_flag
.name
);
1411 memset(ofile
, '\0', sizeof(struct ofile
));
1415 * ofile_first_arch() sets up the ofile struct for a fat file to the first arch
1421 struct ofile
*ofile
)
1423 if(ofile
->file_type
== OFILE_FAT
||
1424 (ofile
->file_type
== OFILE_ARCHIVE
&&
1425 ofile
->member_type
== OFILE_FAT
) )
1426 return(ofile_specific_arch(ofile
, 0));
1428 error("ofile_first_arch() called and file type of: %s is not a fat "
1429 "file\n", ofile
->file_name
);
1435 * ofile_next_arch() sets up the ofile struct for a fat file to the next arch
1441 struct ofile
*ofile
)
1443 if(ofile
->file_type
== OFILE_FAT
||
1444 (ofile
->file_type
== OFILE_ARCHIVE
&&
1445 ofile
->member_type
== OFILE_FAT
) ){
1446 if(ofile
->narch
+ 1 < ofile
->fat_header
->nfat_arch
)
1447 return(ofile_specific_arch(ofile
, ofile
->narch
+ 1));
1452 error("ofile_next_arch() called and file type of: %s is not a fat "
1453 "file\n", ofile
->file_name
);
1459 * ofile_specific_arch() sets up the ofile struct for the fat file for the
1464 ofile_specific_arch(
1465 struct ofile
*ofile
,
1471 enum byte_sex host_byte_sex
;
1473 ofile
->narch
= narch
;
1474 ofile
->arch_type
= OFILE_UNKNOWN
;
1475 if(ofile
->arch_flag
.name
!= NULL
)
1476 free(ofile
->arch_flag
.name
);
1477 ofile
->arch_flag
.name
= NULL
;
1478 ofile
->arch_flag
.cputype
= 0;
1479 ofile
->arch_flag
.cpusubtype
= 0;
1480 ofile
->archive_cputype
= 0;
1481 ofile
->archive_cpusubtype
= 0;
1482 ofile
->object_addr
= NULL
;
1483 ofile
->object_size
= 0;
1484 ofile
->object_byte_sex
= UNKNOWN_BYTE_SEX
;
1487 ofile
->load_commands
= NULL
;
1489 ofile
->arch_flag
.cputype
= ofile
->fat_archs
[ofile
->narch
].cputype
;
1490 ofile
->arch_flag
.cpusubtype
= ofile
->fat_archs
[ofile
->narch
].cpusubtype
;
1491 set_arch_flag_name(&(ofile
->arch_flag
));
1494 /* Now determine the file type for this specific architecture */
1495 if(ofile
->file_type
== OFILE_FAT
){
1496 ofile
->member_offset
= 0;
1497 ofile
->member_addr
= NULL
;
1498 ofile
->member_size
= 0;
1499 ofile
->member_ar_hdr
= NULL
;
1500 ofile
->member_type
= OFILE_UNKNOWN
;
1502 size
= ofile
->fat_archs
[ofile
->narch
].size
;
1503 addr
= ofile
->file_addr
+ ofile
->fat_archs
[ofile
->narch
].offset
;
1506 if(ofile
->file_type
!= OFILE_ARCHIVE
||
1507 ofile
->member_type
!= OFILE_FAT
){
1508 error("internal error. ofile_specific_arch() called but file "
1509 "is not a fat file or an archive with a fat member ");
1511 size
= ofile
->fat_archs
[ofile
->narch
].size
;
1512 addr
= ofile
->file_addr
+
1513 ofile
->member_offset
+
1514 ofile
->fat_archs
[ofile
->narch
].offset
;
1518 if(addr
- ofile
->file_addr
> (ptrdiff_t)ofile
->file_size
){
1519 error("fat file: %s offset to architecture %s extends past end "
1520 "of file", ofile
->file_name
, ofile
->arch_flag
.name
);
1523 if(addr
+ size
> ofile
->file_addr
+ ofile
->file_size
)
1524 size
= (ofile
->file_addr
+ ofile
->file_size
) - addr
;
1527 if(size
>= sizeof(struct mach_header
))
1528 memcpy(&magic
, addr
, sizeof(uint32_t));
1529 /* see if this file is a 32-bit Mach-O file */
1530 if(size
>= sizeof(struct mach_header
) &&
1531 (magic
== MH_MAGIC
|| magic
== SWAP_INT(MH_MAGIC
))){
1532 #ifdef ALIGNMENT_CHECKS
1533 if(ofile
->fat_archs
[ofile
->narch
].offset
% 4 != 0){
1534 if(ofile
->file_type
== OFILE_ARCHIVE
){
1535 error("fat file: %s(%.*s) architecture %s malformed for a "
1536 "32-bit object file (offset is not a multiple of 4)",
1537 ofile
->file_name
, (int)ofile
->member_name_size
,
1538 ofile
->member_name
, ofile
->arch_flag
.name
);
1541 error("fat file: %s architecture %s malformed for a 32-bit "
1542 "object file (offset is not a multiple of 4)",
1543 ofile
->file_name
, ofile
->arch_flag
.name
);
1546 #endif /* ALIGNMENT_CHECKS */
1547 ofile
->arch_type
= OFILE_Mach_O
;
1548 ofile
->object_addr
= addr
;
1549 ofile
->object_size
= size
;
1550 host_byte_sex
= get_host_byte_sex();
1551 if(magic
== MH_MAGIC
)
1552 ofile
->object_byte_sex
= host_byte_sex
;
1554 ofile
->object_byte_sex
=
1555 host_byte_sex
== BIG_ENDIAN_BYTE_SEX
?
1556 LITTLE_ENDIAN_BYTE_SEX
: BIG_ENDIAN_BYTE_SEX
;
1557 ofile
->mh
= (struct mach_header
*)addr
;
1558 ofile
->load_commands
= (struct load_command
*)(addr
+
1559 sizeof(struct mach_header
));
1560 if(check_Mach_O(ofile
) == CHECK_BAD
)
1563 /* see if this file is a 64-bit Mach-O file */
1564 else if(size
>= sizeof(struct mach_header_64
) &&
1565 (magic
== MH_MAGIC_64
|| magic
== SWAP_INT(MH_MAGIC_64
))){
1566 #ifdef ALIGNMENT_CHECKS
1567 if(ofile
->fat_archs
[ofile
->narch
].offset
% 8 != 0){
1568 if(ofile
->file_type
== OFILE_ARCHIVE
){
1569 error("fat file: %s(%.*s) architecture %s malformed for an "
1570 "object file (offset is not a multiple of 8)",
1571 ofile
->file_name
, (int)ofile
->member_name_size
,
1572 ofile
->member_name
, ofile
->arch_flag
.name
);
1575 error("fat file: %s architecture %s malformed for a 64-bit "
1576 "object file (offset is not a multiple of 8",
1577 ofile
->file_name
, ofile
->arch_flag
.name
);
1580 #endif /* ALIGNMENT_CHECKS */
1581 ofile
->arch_type
= OFILE_Mach_O
;
1582 ofile
->object_addr
= addr
;
1583 ofile
->object_size
= size
;
1584 host_byte_sex
= get_host_byte_sex();
1585 if(magic
== MH_MAGIC_64
)
1586 ofile
->object_byte_sex
= host_byte_sex
;
1588 ofile
->object_byte_sex
=
1589 host_byte_sex
== BIG_ENDIAN_BYTE_SEX
?
1590 LITTLE_ENDIAN_BYTE_SEX
: BIG_ENDIAN_BYTE_SEX
;
1591 ofile
->mh64
= (struct mach_header_64
*)addr
;
1592 ofile
->load_commands
= (struct load_command
*)(addr
+
1593 sizeof(struct mach_header_64
));
1594 if(check_Mach_O(ofile
) == CHECK_BAD
)
1597 /* see if this file is an archive file */
1598 else if(size
>= SARMAG
&& strncmp(addr
, ARMAG
, SARMAG
) == 0){
1599 ofile
->arch_type
= OFILE_ARCHIVE
;
1600 if(check_archive(ofile
, FALSE
) == CHECK_BAD
)
1602 #ifdef ALIGNMENT_CHECKS
1603 if(ofile
->archive_cputype
!= 0 &&
1604 ofile
->fat_archs
[ofile
->narch
].offset
%
1605 sizeof(uint32_t) != 0){
1606 error("fat file: %s architecture %s malformed archive that "
1607 "contains object files (offset to archive is not a "
1608 "multiple of sizeof(uint32_t))",
1609 ofile
->file_name
, ofile
->arch_flag
.name
);
1612 #endif /* ALIGNMENT_CHECKS */
1615 * This type for this architecture is now known to be unknown to this
1620 if(is_llvm_bitcode(ofile
, addr
, size
) == TRUE
){
1621 ofile
->arch_type
= OFILE_LLVM_BITCODE
;
1622 ofile
->object_addr
= addr
;
1623 ofile
->object_size
= size
;
1626 #endif /* LTO_SUPPORT */
1627 ofile
->arch_type
= OFILE_UNKNOWN
;
1632 ofile
->arch_type
= OFILE_UNKNOWN
;
1633 if(ofile
->arch_flag
.name
!= NULL
)
1634 free(ofile
->arch_flag
.name
);
1635 ofile
->arch_flag
.name
= NULL
;
1636 ofile
->arch_flag
.cputype
= 0;
1637 ofile
->arch_flag
.cpusubtype
= 0;
1638 if(ofile
->file_type
!= OFILE_ARCHIVE
){
1639 ofile
->member_offset
= 0;
1640 ofile
->member_addr
= NULL
;
1641 ofile
->member_size
= 0;
1642 ofile
->member_ar_hdr
= NULL
;
1643 ofile
->member_type
= OFILE_UNKNOWN
;
1645 ofile
->archive_cputype
= 0;
1646 ofile
->archive_cpusubtype
= 0;
1647 ofile
->object_addr
= NULL
;
1648 ofile
->object_size
= 0;
1649 ofile
->object_byte_sex
= UNKNOWN_BYTE_SEX
;
1652 ofile
->load_commands
= NULL
;
1657 * ofile_first_member() set up the ofile structure (the member_* fields and
1658 * the object file fields if the first member is an object file) for the first
1664 struct ofile
*ofile
)
1667 uint64_t size
, offset
;
1669 enum byte_sex host_byte_sex
;
1670 struct ar_hdr
*ar_hdr
;
1671 uint32_t ar_name_size
;
1673 /* These fields are to be filled in by this routine, clear them first */
1674 ofile
->member_offset
= 0;
1675 ofile
->member_addr
= NULL
;
1676 ofile
->member_size
= 0;
1677 ofile
->member_ar_hdr
= NULL
;
1678 ofile
->member_name
= NULL
;
1679 ofile
->member_name_size
= 0;
1680 ofile
->member_type
= OFILE_UNKNOWN
;
1681 ofile
->object_addr
= NULL
;
1682 ofile
->object_size
= 0;
1683 ofile
->object_byte_sex
= UNKNOWN_BYTE_SEX
;
1686 ofile
->load_commands
= NULL
;
1689 * Note: it is up to the caller if they want to call free_lto() on this
1690 * when iterating through the members of an archive.
1693 #endif /* LTO_SUPPORT */
1696 * Get the address and size of the archive.
1698 if(ofile
->file_type
== OFILE_FAT
){
1699 if(ofile
->arch_type
!= OFILE_ARCHIVE
){
1700 error("ofile_first_member() called on fat file: %s with a "
1701 "non-archive architecture or no architecture selected\n",
1705 addr
= ofile
->file_addr
+ ofile
->fat_archs
[ofile
->narch
].offset
;
1706 size
= ofile
->fat_archs
[ofile
->narch
].size
;
1708 else if(ofile
->file_type
== OFILE_ARCHIVE
){
1709 addr
= ofile
->file_addr
;
1710 size
= ofile
->file_size
;
1713 error("ofile_first_member() called and file type of %s is "
1714 "OFILE_UNKNOWN\n", ofile
->file_name
);
1718 if((addr
+ SARMAG
) - ofile
->file_addr
> (ptrdiff_t)ofile
->file_size
){
1719 archive_error(ofile
, "offset to first member extends past the end "
1723 if(addr
+ size
> ofile
->file_addr
+ ofile
->file_size
)
1724 size
= (ofile
->file_addr
+ ofile
->file_size
) - addr
;
1726 if(size
< SARMAG
|| strncmp(addr
, ARMAG
, SARMAG
) != 0){
1727 archive_error(ofile
, "internal error. ofile_first_member() "
1728 "called but file does not have an archive magic "
1734 if(offset
!= size
&& offset
+ sizeof(struct ar_hdr
) > size
){
1735 archive_error(ofile
, "truncated or malformed (archive header of "
1736 "first member extends past the end of the file)");
1740 /* check for empty archive */
1744 /* now we know there is a first member so set it up */
1745 ar_hdr
= (struct ar_hdr
*)(addr
+ offset
);
1746 offset
+= sizeof(struct ar_hdr
);
1747 ofile
->member_offset
= offset
;
1748 ofile
->member_addr
= addr
+ offset
;
1749 ofile
->member_size
= strtoul(ar_hdr
->ar_size
, NULL
, 10);
1750 ofile
->member_ar_hdr
= ar_hdr
;
1751 ofile
->member_type
= OFILE_UNKNOWN
;
1752 ofile
->member_name
= ar_hdr
->ar_name
;
1753 if(strncmp(ofile
->member_name
, AR_EFMT1
, sizeof(AR_EFMT1
) - 1) == 0){
1754 ofile
->member_name
= ar_hdr
->ar_name
+ sizeof(struct ar_hdr
);
1755 ar_name_size
= strtoul(ar_hdr
->ar_name
+ sizeof(AR_EFMT1
) - 1,
1757 ofile
->member_name_size
= ar_name_size
;
1758 ofile
->member_offset
+= ar_name_size
;
1759 ofile
->member_addr
+= ar_name_size
;
1760 ofile
->member_size
-= ar_name_size
;
1763 ofile
->member_name_size
= size_ar_name(ar_hdr
);
1766 /* Clear these in case there is no table of contents */
1767 ofile
->toc_addr
= NULL
;
1768 ofile
->toc_size
= 0;
1769 ofile
->toc_ar_hdr
= NULL
;
1770 ofile
->toc_name
= NULL
;
1771 ofile
->toc_name_size
= 0;
1772 ofile
->toc_ranlibs
= NULL
;
1773 ofile
->toc_nranlibs
= 0;
1774 ofile
->toc_strings
= NULL
;
1775 ofile
->toc_strsize
= 0;
1776 ofile
->toc_bad
= FALSE
;
1778 host_byte_sex
= get_host_byte_sex();
1780 if(ofile
->member_size
> sizeof(uint32_t)){
1781 memcpy(&magic
, ofile
->member_addr
, sizeof(uint32_t));
1782 #ifdef __BIG_ENDIAN__
1783 if(magic
== FAT_MAGIC
)
1784 #endif /* __BIG_ENDIAN__ */
1785 #ifdef __LITTLE_ENDIAN__
1786 if(magic
== SWAP_INT(FAT_MAGIC
))
1787 #endif /* __LITTLE_ENDIAN__ */
1789 ofile
->member_type
= OFILE_FAT
;
1791 (struct fat_header
*)(ofile
->member_addr
);
1792 #ifdef __LITTLE_ENDIAN__
1793 swap_fat_header(ofile
->fat_header
, host_byte_sex
);
1794 #endif /* __LITTLE_ENDIAN__ */
1795 if(sizeof(struct fat_header
) +
1796 ofile
->fat_header
->nfat_arch
*
1797 sizeof(struct fat_arch
) > ofile
->member_size
){
1798 archive_member_error(ofile
, "fat file truncated or "
1799 "malformed (fat_arch structs would extend past "
1800 "the end of the archive member)");
1803 ofile
->fat_archs
= (struct fat_arch
*)
1804 (ofile
->member_addr
+ sizeof(struct fat_header
));
1805 #ifdef __LITTLE_ENDIAN__
1806 swap_fat_arch(ofile
->fat_archs
,
1807 ofile
->fat_header
->nfat_arch
, host_byte_sex
);
1808 #endif /* __LITTLE_ENDIAN__ */
1809 if(check_fat_object_in_archive(ofile
) == FALSE
)
1812 else if(size
- (offset
+ ar_name_size
) >=
1813 sizeof(struct mach_header
) &&
1814 (magic
== MH_MAGIC
|| magic
== SWAP_INT(MH_MAGIC
))){
1815 #ifdef ALIGNMENT_CHECKS
1816 if((offset
+ ar_name_size
) % 4 != 0){
1817 archive_member_error(ofile
, "offset in archive not a "
1818 "multiple of 4 (must be since member is a 32-bit "
1822 #endif /* ALIGNMENT_CHECKS */
1823 ofile
->member_type
= OFILE_Mach_O
;
1824 ofile
->object_addr
= ofile
->member_addr
;
1825 ofile
->object_size
= ofile
->member_size
;
1826 if(magic
== MH_MAGIC
)
1827 ofile
->object_byte_sex
= host_byte_sex
;
1829 ofile
->object_byte_sex
=
1830 host_byte_sex
== BIG_ENDIAN_BYTE_SEX
?
1831 LITTLE_ENDIAN_BYTE_SEX
: BIG_ENDIAN_BYTE_SEX
;
1832 ofile
->mh
= (struct mach_header
*)(ofile
->object_addr
);
1833 ofile
->load_commands
= (struct load_command
*)
1834 (ofile
->object_addr
+ sizeof(struct mach_header
));
1835 if(check_Mach_O(ofile
) == CHECK_BAD
)
1838 else if(size
- (offset
+ ar_name_size
) >=
1839 sizeof(struct mach_header_64
) &&
1840 (magic
== MH_MAGIC_64
|| magic
== SWAP_INT(MH_MAGIC_64
))){
1841 #ifdef ALIGNMENT_CHECKS_ARCHIVE_64_BIT
1842 if(archive_64_bit_align_warning
== FALSE
&&
1843 (offset
+ ar_name_size
) % 8 != 0){
1844 temporary_archive_member_warning(ofile
, "offset in archive "
1845 "not a multiple of 8 (must be since member is an "
1846 "64-bit object file)");
1847 archive_64_bit_align_warning
= TRUE
;
1850 #endif /* ALIGNMENT_CHECKS_ARCHIVE_64_BIT */
1851 ofile
->member_type
= OFILE_Mach_O
;
1852 ofile
->object_addr
= ofile
->member_addr
;
1853 ofile
->object_size
= ofile
->member_size
;
1854 if(magic
== MH_MAGIC_64
)
1855 ofile
->object_byte_sex
= host_byte_sex
;
1857 ofile
->object_byte_sex
=
1858 host_byte_sex
== BIG_ENDIAN_BYTE_SEX
?
1859 LITTLE_ENDIAN_BYTE_SEX
: BIG_ENDIAN_BYTE_SEX
;
1860 ofile
->mh64
= (struct mach_header_64
*)(ofile
->object_addr
);
1861 ofile
->load_commands
= (struct load_command
*)
1862 (ofile
->object_addr
+ sizeof(struct mach_header_64
));
1863 if(check_Mach_O(ofile
) == CHECK_BAD
)
1866 if(ofile
->member_type
== OFILE_UNKNOWN
&&
1867 (strncmp(ofile
->member_name
, SYMDEF_SORTED
,
1868 sizeof(SYMDEF_SORTED
) - 1) == 0 ||
1869 strncmp(ofile
->member_name
, SYMDEF
,
1870 sizeof(SYMDEF
) - 1) == 0)){
1871 ofile
->toc_addr
= ofile
->member_addr
;
1872 ofile
->toc_size
= ofile
->member_size
;
1873 ofile
->toc_ar_hdr
= ofile
->member_ar_hdr
;
1874 ofile
->toc_name
= ofile
->member_name
;
1875 ofile
->toc_name_size
= ofile
->member_name_size
;
1876 if(check_archive_toc(ofile
) == CHECK_BAD
)
1880 if(ofile
->member_type
== OFILE_UNKNOWN
&&
1881 strncmp(ofile
->member_name
, SYMDEF_SORTED
,
1882 sizeof(SYMDEF_SORTED
) - 1) != 0 &&
1883 strncmp(ofile
->member_name
, SYMDEF
,
1884 sizeof(SYMDEF
) - 1) != 0 &&
1885 is_llvm_bitcode(ofile
, ofile
->member_addr
, ofile
->member_size
) ==
1887 ofile
->member_type
= OFILE_LLVM_BITCODE
;
1888 ofile
->object_addr
= ofile
->member_addr
;
1889 ofile
->object_size
= ofile
->member_size
;
1891 #endif /* LTO_SUPPORT */
1896 ofile
->fat_header
= NULL
;
1897 ofile
->fat_archs
= NULL
;
1899 ofile
->member_offset
= 0;
1900 ofile
->member_addr
= 0;
1901 ofile
->member_size
= 0;
1902 ofile
->member_ar_hdr
= NULL
;
1903 ofile
->member_name
= NULL
;
1904 ofile
->member_name_size
= 0;
1905 ofile
->member_type
= OFILE_UNKNOWN
;
1906 ofile
->object_addr
= NULL
;
1907 ofile
->object_size
= 0;
1908 ofile
->object_byte_sex
= UNKNOWN_BYTE_SEX
;
1911 ofile
->load_commands
= NULL
;
1914 ofile
->lto_cputype
= 0;
1915 ofile
->lto_cpusubtype
= 0;
1916 #endif /* LTO_SUPPORT */
1921 * ofile_next_member() set up the ofile structure (the member_* fields and
1922 * the object file fields if the next member is an object file) for the next
1928 struct ofile
*ofile
)
1931 uint64_t size
, offset
;
1933 enum byte_sex host_byte_sex
;
1934 struct ar_hdr
*ar_hdr
;
1935 uint32_t ar_name_size
;
1938 * Get the address and size of the archive.
1940 if(ofile
->file_type
== OFILE_FAT
){
1941 if(ofile
->arch_type
!= OFILE_ARCHIVE
){
1942 error("ofile_next_member() called on fat file: %s with a "
1943 "non-archive architecture or no architecture selected\n",
1947 addr
= ofile
->file_addr
+ ofile
->fat_archs
[ofile
->narch
].offset
;
1948 size
= ofile
->fat_archs
[ofile
->narch
].size
;
1950 else if(ofile
->file_type
== OFILE_ARCHIVE
){
1951 addr
= ofile
->file_addr
;
1952 size
= ofile
->file_size
;
1955 error("ofile_next_member() called and file type of %s is "
1956 "OFILE_UNKNOWN\n", ofile
->file_name
);
1959 if(size
< SARMAG
|| strncmp(addr
, ARMAG
, SARMAG
) != 0){
1960 archive_error(ofile
, "internal error. ofile_next_member() "
1961 "called but file does not have an archive magic "
1965 if(ofile
->member_ar_hdr
== NULL
){
1966 archive_error(ofile
, "internal error. ofile_next_member() called "
1967 "but the ofile struct does not have an archive "
1972 /* figure out the offset to the next member */
1973 offset
= ofile
->member_offset
+ rnd(ofile
->member_size
,sizeof(short));
1975 if((addr
- ofile
->file_addr
) + offset
> ofile
->file_size
){
1976 archive_error(ofile
, "offset to next member extends past the end "
1981 /* if now at the end of the file then no more members */
1985 archive_error(ofile
, "truncated or malformed (archive header of "
1986 "next member extends past the end of the file)");
1990 /* now we know there is a next member so set it up */
1991 ar_hdr
= (struct ar_hdr
*)(addr
+ offset
);
1992 offset
+= sizeof(struct ar_hdr
);
1993 ofile
->member_offset
= offset
;
1994 ofile
->member_addr
= addr
+ offset
;
1995 ofile
->member_size
= strtoul(ar_hdr
->ar_size
, NULL
, 10);
1996 ofile
->member_ar_hdr
= ar_hdr
;
1997 ofile
->member_name
= ar_hdr
->ar_name
;
1998 if(strncmp(ofile
->member_name
, AR_EFMT1
, sizeof(AR_EFMT1
) - 1) == 0){
1999 ofile
->member_name
= ar_hdr
->ar_name
+ sizeof(struct ar_hdr
);
2000 ar_name_size
= strtoul(ar_hdr
->ar_name
+ sizeof(AR_EFMT1
) - 1,
2002 ofile
->member_name_size
= ar_name_size
;
2003 ofile
->member_offset
+= ar_name_size
;
2004 ofile
->member_addr
+= ar_name_size
;
2005 ofile
->member_size
-= ar_name_size
;
2008 ofile
->member_name_size
= size_ar_name(ar_hdr
);
2011 ofile
->member_type
= OFILE_UNKNOWN
;
2012 ofile
->object_addr
= NULL
;
2013 ofile
->object_size
= 0;
2014 ofile
->object_byte_sex
= UNKNOWN_BYTE_SEX
;
2017 ofile
->load_commands
= NULL
;
2019 host_byte_sex
= get_host_byte_sex();
2021 if(ofile
->member_size
> sizeof(uint32_t)){
2022 memcpy(&magic
, ofile
->member_addr
, sizeof(uint32_t));
2023 #ifdef __BIG_ENDIAN__
2024 if(magic
== FAT_MAGIC
)
2025 #endif /* __BIG_ENDIAN__ */
2026 #ifdef __LITTLE_ENDIAN__
2027 if(magic
== SWAP_INT(FAT_MAGIC
))
2028 #endif /* __LITTLE_ENDIAN__ */
2030 ofile
->member_type
= OFILE_FAT
;
2031 ofile
->fat_header
= (struct fat_header
*)(ofile
->member_addr
);
2032 #ifdef __LITTLE_ENDIAN__
2033 swap_fat_header(ofile
->fat_header
, host_byte_sex
);
2034 #endif /* __LITTLE_ENDIAN__ */
2035 if(sizeof(struct fat_header
) +
2036 ofile
->fat_header
->nfat_arch
*
2037 sizeof(struct fat_arch
) > ofile
->member_size
){
2038 archive_member_error(ofile
, "fat file truncated or "
2039 "malformed (fat_arch structs would extend past "
2040 "the end of the archive member)");
2043 ofile
->fat_archs
= (struct fat_arch
*)(ofile
->member_addr
+
2044 sizeof(struct fat_header
));
2045 #ifdef __LITTLE_ENDIAN__
2046 swap_fat_arch(ofile
->fat_archs
,
2047 ofile
->fat_header
->nfat_arch
, host_byte_sex
);
2048 #endif /* __LITTLE_ENDIAN__ */
2049 if(check_fat_object_in_archive(ofile
) == FALSE
)
2052 else if(size
- (offset
+ ar_name_size
) >=
2053 sizeof(struct mach_header
) &&
2054 (magic
== MH_MAGIC
||
2055 magic
== SWAP_INT(MH_MAGIC
))){
2056 #ifdef ALIGNMENT_CHECKS
2057 if((offset
+ ar_name_size
) % 4 != 0){
2058 archive_member_error(ofile
, "offset in archive not "
2059 "a multiple of 4 (must be since member is an 32-bit "
2063 #endif /* ALIGNMENT_CHECKS */
2064 ofile
->member_type
= OFILE_Mach_O
;
2065 ofile
->object_addr
= ofile
->member_addr
;
2066 ofile
->object_size
= ofile
->member_size
;
2067 if(magic
== MH_MAGIC
)
2068 ofile
->object_byte_sex
= host_byte_sex
;
2070 ofile
->object_byte_sex
=
2071 host_byte_sex
== BIG_ENDIAN_BYTE_SEX
?
2072 LITTLE_ENDIAN_BYTE_SEX
: BIG_ENDIAN_BYTE_SEX
;
2073 ofile
->mh
= (struct mach_header
*)ofile
->object_addr
;
2074 ofile
->load_commands
= (struct load_command
*)
2075 (ofile
->object_addr
+ sizeof(struct mach_header
));
2076 if(check_Mach_O(ofile
) == CHECK_BAD
)
2079 else if(size
- (offset
+ ar_name_size
) >=
2080 sizeof(struct mach_header_64
) &&
2081 (magic
== MH_MAGIC_64
||
2082 magic
== SWAP_INT(MH_MAGIC_64
))){
2083 #ifdef ALIGNMENT_CHECKS_ARCHIVE_64_BIT
2084 if(archive_64_bit_align_warning
== FALSE
&&
2085 (offset
+ ar_name_size
) % 8 != 0){
2086 temporary_archive_member_warning(ofile
, "offset in archive "
2087 "not a multiple of 8 (must be since member is an "
2088 "64-bit object file)");
2089 archive_64_bit_align_warning
= TRUE
;
2092 #endif /* ALIGNMENT_CHECKS_ARCHIVE_64_BIT */
2093 ofile
->member_type
= OFILE_Mach_O
;
2094 ofile
->object_addr
= ofile
->member_addr
;
2095 ofile
->object_size
= ofile
->member_size
;
2096 if(magic
== MH_MAGIC_64
)
2097 ofile
->object_byte_sex
= host_byte_sex
;
2099 ofile
->object_byte_sex
=
2100 host_byte_sex
== BIG_ENDIAN_BYTE_SEX
?
2101 LITTLE_ENDIAN_BYTE_SEX
: BIG_ENDIAN_BYTE_SEX
;
2102 ofile
->mh64
= (struct mach_header_64
*)ofile
->object_addr
;
2103 ofile
->load_commands
= (struct load_command
*)
2104 (ofile
->object_addr
+ sizeof(struct mach_header_64
));
2105 if(check_Mach_O(ofile
) == CHECK_BAD
)
2109 if(ofile
->member_type
== OFILE_UNKNOWN
&&
2110 is_llvm_bitcode(ofile
, ofile
->member_addr
, ofile
->member_size
) ==
2112 ofile
->member_type
= OFILE_LLVM_BITCODE
;
2113 ofile
->object_addr
= ofile
->member_addr
;
2114 ofile
->object_size
= ofile
->member_size
;
2116 #endif /* LTO_SUPPORT */
2121 if(ofile
->member_type
== OFILE_FAT
){
2122 ofile
->fat_header
= NULL
;
2123 ofile
->fat_archs
= NULL
;
2125 ofile
->member_offset
= 0;
2126 ofile
->member_addr
= NULL
;
2127 ofile
->member_size
= 0;
2128 ofile
->member_ar_hdr
= NULL
;
2129 ofile
->member_name
= NULL
;
2130 ofile
->member_name_size
= 0;
2131 ofile
->member_type
= OFILE_UNKNOWN
;
2132 ofile
->object_addr
= NULL
;
2133 ofile
->object_size
= 0;
2134 ofile
->object_byte_sex
= UNKNOWN_BYTE_SEX
;
2137 ofile
->load_commands
= NULL
;
2140 ofile
->lto_cputype
= 0;
2141 ofile
->lto_cpusubtype
= 0;
2142 #endif /* LTO_SUPPORT */
2147 * ofile_specific_member() set up the ofile structure (the member_* fields and
2148 * the object file fields if the member is an object file) for the specified
2149 * member member_name.
2153 ofile_specific_member(
2154 const char *member_name
,
2155 struct ofile
*ofile
)
2159 uint64_t size
, offset
;
2161 enum byte_sex host_byte_sex
;
2163 uint32_t ar_name_size
;
2164 struct ar_hdr
*ar_hdr
;
2166 /* These fields are to be filled in by this routine, clear them first */
2167 ofile
->member_offset
= 0;
2168 ofile
->member_addr
= NULL
;
2169 ofile
->member_size
= 0;
2170 ofile
->member_ar_hdr
= NULL
;
2171 ofile
->member_name
= NULL
;
2172 ofile
->member_name_size
= 0;
2173 ofile
->member_type
= OFILE_UNKNOWN
;
2174 ofile
->object_addr
= NULL
;
2175 ofile
->object_size
= 0;
2176 ofile
->object_byte_sex
= UNKNOWN_BYTE_SEX
;
2179 ofile
->load_commands
= NULL
;
2182 * Get the address and size of the archive.
2184 if(ofile
->file_type
== OFILE_FAT
){
2185 if(ofile
->arch_type
!= OFILE_ARCHIVE
){
2186 error("ofile_specific_member() called on fat file: %s with a "
2187 "non-archive architecture or no architecture selected\n",
2191 addr
= ofile
->file_addr
+ ofile
->fat_archs
[ofile
->narch
].offset
;
2192 size
= ofile
->fat_archs
[ofile
->narch
].size
;
2194 else if(ofile
->file_type
== OFILE_ARCHIVE
){
2195 addr
= ofile
->file_addr
;
2196 size
= ofile
->file_size
;
2199 error("ofile_specific_member() called and file type of %s is "
2200 "OFILE_UNKNOWN\n", ofile
->file_name
);
2203 if(size
< SARMAG
|| strncmp(addr
, ARMAG
, SARMAG
) != 0){
2204 archive_error(ofile
, "internal error. ofile_specific_member() "
2205 "called but file does not have an archive magic "
2211 if(offset
!= size
&& offset
+ sizeof(struct ar_hdr
) > size
){
2212 archive_error(ofile
, "truncated or malformed (archive header of "
2213 "first member extends past the end of the file)");
2216 while(size
> offset
){
2217 ar_hdr
= (struct ar_hdr
*)(addr
+ offset
);
2218 offset
+= sizeof(struct ar_hdr
);
2219 if(strncmp(ar_hdr
->ar_name
, AR_EFMT1
, sizeof(AR_EFMT1
) - 1) == 0){
2221 if(check_extend_format_1(ofile
, ar_hdr
, size
- offset
,
2222 &ar_name_size
) == CHECK_BAD
){
2223 i
= size_ar_name(ar_hdr
);
2224 ar_name
= ar_hdr
->ar_name
;
2230 i
= strtoul(ar_hdr
->ar_name
+ sizeof(AR_EFMT1
) - 1,NULL
,10);
2231 ar_name
= ar_hdr
->ar_name
+ sizeof(struct ar_hdr
);
2236 i
= size_ar_name(ar_hdr
);
2237 ar_name
= ar_hdr
->ar_name
;
2240 if(i
> 0 && strncmp(ar_name
, member_name
, i
) == 0){
2242 ofile
->member_name
= ar_name
;
2243 ofile
->member_name_size
= i
;
2244 ofile
->member_offset
= offset
+ ar_name_size
;
2245 ofile
->member_addr
= addr
+ offset
+ ar_name_size
;
2246 ofile
->member_size
= strtoul(ar_hdr
->ar_size
, NULL
, 10) -
2248 ofile
->member_ar_hdr
= ar_hdr
;
2249 ofile
->member_type
= OFILE_UNKNOWN
;
2251 host_byte_sex
= get_host_byte_sex();
2253 if(ofile
->member_size
> sizeof(uint32_t)){
2254 memcpy(&magic
, addr
+ offset
+ ar_name_size
,
2256 #ifdef __BIG_ENDIAN__
2257 if(magic
== FAT_MAGIC
)
2258 #endif /* __BIG_ENDIAN__ */
2259 #ifdef __LITTLE_ENDIAN__
2260 if(magic
== SWAP_INT(FAT_MAGIC
))
2261 #endif /* __LITTLE_ENDIAN__ */
2263 ofile
->member_type
= OFILE_FAT
;
2265 (struct fat_header
*)(addr
+ offset
+ ar_name_size
);
2266 #ifdef __LITTLE_ENDIAN__
2267 swap_fat_header(ofile
->fat_header
, host_byte_sex
);
2268 #endif /* __LITTLE_ENDIAN__ */
2269 if(sizeof(struct fat_header
) +
2270 ofile
->fat_header
->nfat_arch
*
2271 sizeof(struct fat_arch
) > ofile
->member_size
){
2272 archive_member_error(ofile
, "fat file truncated or "
2273 "malformed (fat_arch structs would extend "
2274 "past the end of the archive member)");
2278 (struct fat_arch
*)(addr
+ offset
+ ar_name_size
+
2279 sizeof(struct fat_header
));
2280 #ifdef __LITTLE_ENDIAN__
2281 swap_fat_arch(ofile
->fat_archs
,
2282 ofile
->fat_header
->nfat_arch
,
2284 #endif /* __LITTLE_ENDIAN__ */
2285 if(check_fat_object_in_archive(ofile
) == FALSE
)
2288 else if(size
- (offset
+ ar_name_size
) >=
2289 sizeof(struct mach_header
) &&
2290 (magic
== MH_MAGIC
||
2291 magic
== SWAP_INT(MH_MAGIC
))){
2292 #ifdef ALIGNMENT_CHECKS
2293 if((offset
+ ar_name_size
) % 4 != 0){
2294 archive_member_error(ofile
, "offset in archive not "
2295 "a multiple of 4) (must be since member is a "
2296 "32-bit object file)");
2299 #endif /* ALIGNMENT_CHECKS */
2300 ofile
->member_type
= OFILE_Mach_O
;
2301 ofile
->object_addr
= ofile
->member_addr
;
2302 ofile
->object_size
= ofile
->member_size
;
2303 if(magic
== MH_MAGIC
)
2304 ofile
->object_byte_sex
= host_byte_sex
;
2306 ofile
->object_byte_sex
=
2307 host_byte_sex
== BIG_ENDIAN_BYTE_SEX
?
2308 LITTLE_ENDIAN_BYTE_SEX
: BIG_ENDIAN_BYTE_SEX
;
2309 ofile
->mh
= (struct mach_header
*)ofile
->object_addr
;
2310 ofile
->load_commands
= (struct load_command
*)
2311 (ofile
->object_addr
+ sizeof(struct mach_header
));
2312 if(check_Mach_O(ofile
) == CHECK_BAD
)
2315 else if(size
- (offset
+ ar_name_size
) >=
2316 sizeof(struct mach_header_64
) &&
2317 (magic
== MH_MAGIC_64
||
2318 magic
== SWAP_INT(MH_MAGIC_64
))){
2319 #ifdef ALIGNMENT_CHECKS_ARCHIVE_64_BIT
2320 if(archive_64_bit_align_warning
== FALSE
&&
2321 (offset
+ ar_name_size
) % 8 != 0){
2322 temporary_archive_member_warning(ofile
, "offset in "
2323 "archive not a multiple of 8) (must be since "
2324 "member is a 64-bit object file)");
2325 archive_64_bit_align_warning
= TRUE
;
2328 #endif /* ALIGNMENT_CHECKS_ARCHIVE_64_BIT */
2329 ofile
->member_type
= OFILE_Mach_O
;
2330 ofile
->object_addr
= ofile
->member_addr
;
2331 ofile
->object_size
= ofile
->member_size
;
2332 if(magic
== MH_MAGIC_64
)
2333 ofile
->object_byte_sex
= host_byte_sex
;
2335 ofile
->object_byte_sex
=
2336 host_byte_sex
== BIG_ENDIAN_BYTE_SEX
?
2337 LITTLE_ENDIAN_BYTE_SEX
: BIG_ENDIAN_BYTE_SEX
;
2338 ofile
->mh64
= (struct mach_header_64
*)
2340 ofile
->load_commands
= (struct load_command
*)
2341 (ofile
->object_addr
+sizeof(struct mach_header_64
));
2342 if(check_Mach_O(ofile
) == CHECK_BAD
)
2347 if(ofile
->member_type
== OFILE_UNKNOWN
&&
2348 is_llvm_bitcode(ofile
, ofile
->member_addr
,
2349 ofile
->member_size
) == TRUE
){
2350 ofile
->member_type
= OFILE_LLVM_BITCODE
;
2351 ofile
->object_addr
= ofile
->member_addr
;
2352 ofile
->object_size
= ofile
->member_size
;
2354 #endif /* LTO_SUPPORT */
2357 offset
+= rnd(strtoul(ar_hdr
->ar_size
, NULL
, 10),
2360 archive_error(ofile
, "does not contain a member named: %s",
2363 ofile
->fat_header
= NULL
;
2364 ofile
->fat_archs
= NULL
;
2366 ofile
->member_offset
= 0;
2367 ofile
->member_addr
= NULL
;
2368 ofile
->member_size
= 0;
2369 ofile
->member_ar_hdr
= NULL
;
2370 ofile
->member_name
= NULL
;
2371 ofile
->member_name_size
= 0;
2372 ofile
->member_type
= OFILE_UNKNOWN
;
2373 ofile
->object_addr
= NULL
;
2374 ofile
->object_size
= 0;
2375 ofile
->object_byte_sex
= UNKNOWN_BYTE_SEX
;
2378 ofile
->load_commands
= NULL
;
2381 ofile
->lto_cputype
= 0;
2382 ofile
->lto_cpusubtype
= 0;
2383 #endif /* LTO_SUPPORT */
2388 * ofile_first_module() set up the ofile structure (the dylib_module field)
2389 * for the first module of an MH_DYLIB or MH_DYLIB_STUB file.
2394 struct ofile
*ofile
)
2397 struct symtab_command
*st
;
2398 struct dysymtab_command
*dyst
;
2399 struct load_command
*lc
;
2401 enum byte_sex host_byte_sex
;
2402 struct dylib_module m
;
2403 struct dylib_module_64 m64
;
2406 /* These fields are to be filled in by this routine, clear them first */
2407 ofile
->modtab
= NULL
;
2408 ofile
->modtab64
= NULL
;
2410 ofile
->dylib_module
= NULL
;
2411 ofile
->dylib_module64
= NULL
;
2412 ofile
->dylib_module_name
= NULL
;
2414 if(ofile
->file_type
== OFILE_FAT
){
2415 if(ofile
->arch_type
!= OFILE_Mach_O
&&
2416 (ofile
->mh_filetype
!= MH_DYLIB
&&
2417 ofile
->mh_filetype
!= MH_DYLIB_STUB
)){
2418 error("ofile_first_module() called on fat file: %s with a "
2419 "non-MH_DYLIB architecture or no architecture selected\n",
2424 else if(ofile
->arch_type
!= OFILE_Mach_O
&&
2425 (ofile
->mh_filetype
!= MH_DYLIB
&&
2426 ofile
->mh_filetype
!= MH_DYLIB_STUB
)){
2427 error("ofile_first_module() called and file type of %s is "
2428 "non-MH_DYLIB\n", ofile
->file_name
);
2434 lc
= ofile
->load_commands
;
2435 if(ofile
->mh
!= NULL
)
2436 ncmds
= ofile
->mh
->ncmds
;
2438 ncmds
= ofile
->mh64
->ncmds
;
2439 for(i
= 0; i
< ncmds
; i
++){
2440 if(st
== NULL
&& lc
->cmd
== LC_SYMTAB
){
2441 st
= (struct symtab_command
*)lc
;
2443 else if(lc
->cmd
== LC_DYSYMTAB
){
2444 dyst
= (struct dysymtab_command
*)lc
;
2446 lc
= (struct load_command
*)((char *)lc
+ lc
->cmdsize
);
2448 if(st
== NULL
|| dyst
== NULL
){
2450 Mach_O_error(ofile
, "MH_DYLIB format error (does not have a symbol "
2451 "table and/or a dynamic symbol table)");
2455 if(dyst
->nmodtab
== 0)
2458 ofile
->nmodtab
= dyst
->nmodtab
;
2459 host_byte_sex
= get_host_byte_sex();
2460 swapped
= (enum bool)(host_byte_sex
!= ofile
->object_byte_sex
);
2461 strings
= (char *)(ofile
->object_addr
+ st
->stroff
);
2463 if(ofile
->mh
!= NULL
){
2464 ofile
->modtab
= (struct dylib_module
*)(ofile
->object_addr
+
2466 ofile
->dylib_module
= ofile
->modtab
;
2467 m
= *ofile
->dylib_module
;
2469 swap_dylib_module(&m
, 1, host_byte_sex
);
2470 ofile
->dylib_module_name
= strings
+ m
.module_name
;
2473 ofile
->modtab64
= (struct dylib_module_64
*)(ofile
->object_addr
+
2475 ofile
->dylib_module64
= ofile
->modtab64
;
2476 m64
= *ofile
->dylib_module64
;
2478 swap_dylib_module_64(&m64
, 1, host_byte_sex
);
2479 ofile
->dylib_module_name
= strings
+ m64
.module_name
;
2482 if(check_dylib_module(ofile
, st
, dyst
, strings
, 0) == CHECK_BAD
)
2488 * ofile_next_module() set up the ofile structure (the dylib_module field)
2489 * for the next module of an MH_DYLIB or MH_DYLIB_STUB file.
2494 struct ofile
*ofile
)
2496 uint32_t i
, module_index
, ncmds
;
2497 struct symtab_command
*st
;
2498 struct dysymtab_command
*dyst
;
2499 struct load_command
*lc
;
2501 enum byte_sex host_byte_sex
;
2502 struct dylib_module m
;
2503 struct dylib_module_64 m64
;
2506 if(ofile
->file_type
== OFILE_FAT
){
2507 if(ofile
->arch_type
!= OFILE_Mach_O
&&
2508 (ofile
->mh_filetype
!= MH_DYLIB
&&
2509 ofile
->mh_filetype
!= MH_DYLIB_STUB
)){
2510 error("ofile_next_module() called on fat file: %s with a "
2511 "non-MH_DYLIB architecture or no architecture selected\n",
2516 else if(ofile
->arch_type
!= OFILE_Mach_O
&&
2517 (ofile
->mh_filetype
!= MH_DYLIB
&&
2518 ofile
->mh_filetype
!= MH_DYLIB_STUB
)){
2519 error("ofile_next_module() called and file type of %s is "
2520 "non-MH_DYLIB\n", ofile
->file_name
);
2525 lc
= ofile
->load_commands
;
2526 if(ofile
->mh
!= NULL
)
2527 ncmds
= ofile
->mh
->ncmds
;
2529 ncmds
= ofile
->mh64
->ncmds
;
2530 for(i
= 0; i
< ncmds
; i
++){
2531 if(st
== NULL
&& lc
->cmd
== LC_SYMTAB
){
2532 st
= (struct symtab_command
*)lc
;
2534 else if(lc
->cmd
== LC_DYSYMTAB
){
2535 dyst
= (struct dysymtab_command
*)lc
;
2537 lc
= (struct load_command
*)((char *)lc
+ lc
->cmdsize
);
2539 if(st
== NULL
|| dyst
== NULL
){
2541 Mach_O_error(ofile
, "MH_DYLIB format error (does not have a symbol "
2542 "table and/or a dynamic symbol table)");
2547 if(ofile
->mh
!= NULL
)
2548 module_index
= (ofile
->dylib_module
+ 1) - ofile
->modtab
;
2550 module_index
= (ofile
->dylib_module64
+ 1) - ofile
->modtab64
;
2551 if(module_index
>= ofile
->nmodtab
)
2554 host_byte_sex
= get_host_byte_sex();
2555 swapped
= (enum bool)(host_byte_sex
!= ofile
->object_byte_sex
);
2556 strings
= (char *)(ofile
->object_addr
+ st
->stroff
);
2558 if(ofile
->mh
!= NULL
){
2559 ofile
->dylib_module
++;
2560 m
= *ofile
->dylib_module
;
2562 swap_dylib_module(&m
, 1, host_byte_sex
);
2563 ofile
->dylib_module_name
= strings
+ m
.module_name
;
2566 ofile
->dylib_module64
++;
2567 m64
= *ofile
->dylib_module64
;
2569 swap_dylib_module_64(&m64
, 1, host_byte_sex
);
2570 ofile
->dylib_module_name
= strings
+ m64
.module_name
;
2572 if(check_dylib_module(ofile
, st
, dyst
, strings
, module_index
) ==
2579 * ofile_specific_module() set up the ofile structure (the dylib_module fields)
2580 * for the specified module, module_name, of an MH_DYLIB or an MH_DYLIB_STUB
2585 ofile_specific_module(
2586 const char *module_name
,
2587 struct ofile
*ofile
)
2591 enum byte_sex host_byte_sex
;
2592 struct symtab_command
*st
;
2593 struct dysymtab_command
*dyst
;
2594 struct load_command
*lc
;
2595 struct dylib_module
*p
, m
;
2596 struct dylib_module_64
*p64
, m64
;
2599 /* These fields are to be filled in by this routine, clear them first */
2600 ofile
->modtab
= NULL
;
2601 ofile
->modtab64
= NULL
;
2603 ofile
->dylib_module
= NULL
;
2604 ofile
->dylib_module64
= NULL
;
2605 ofile
->dylib_module_name
= NULL
;
2607 if(ofile
->file_type
== OFILE_FAT
){
2608 if(ofile
->arch_type
!= OFILE_Mach_O
&&
2609 (ofile
->mh_filetype
!= MH_DYLIB
&&
2610 ofile
->mh_filetype
!= MH_DYLIB_STUB
)){
2611 error("ofile_specific_module() called on fat file: %s with a "
2612 "non-MH_DYLIB architecture or no architecture selected\n",
2617 else if(ofile
->arch_type
!= OFILE_Mach_O
&&
2618 (ofile
->mh_filetype
!= MH_DYLIB
&&
2619 ofile
->mh_filetype
!= MH_DYLIB_STUB
)){
2620 error("ofile_specific_module() called and file type of %s is "
2621 "non-MH_DYLIB\n", ofile
->file_name
);
2627 lc
= ofile
->load_commands
;
2628 if(ofile
->mh
!= NULL
)
2629 ncmds
= ofile
->mh
->ncmds
;
2631 ncmds
= ofile
->mh64
->ncmds
;
2632 for(i
= 0; i
< ncmds
; i
++){
2633 if(st
== NULL
&& lc
->cmd
== LC_SYMTAB
){
2634 st
= (struct symtab_command
*)lc
;
2636 else if(lc
->cmd
== LC_DYSYMTAB
){
2637 dyst
= (struct dysymtab_command
*)lc
;
2639 lc
= (struct load_command
*)((char *)lc
+ lc
->cmdsize
);
2641 if(st
== NULL
|| dyst
== NULL
){
2643 Mach_O_error(ofile
, "MH_DYLIB format error (does not have a symbol "
2644 "table and/or a dynamic symbol table)");
2648 if(dyst
->nmodtab
== 0)
2651 host_byte_sex
= get_host_byte_sex();
2652 swapped
= (enum bool)(host_byte_sex
!= ofile
->object_byte_sex
);
2653 strings
= (char *)(ofile
->object_addr
+ st
->stroff
);
2655 if(ofile
->mh
!= NULL
){
2656 ofile
->nmodtab
= dyst
->nmodtab
;
2657 ofile
->modtab
= (struct dylib_module
*)(ofile
->object_addr
+
2660 for(i
= 0; i
< dyst
->nmodtab
; i
++){
2663 swap_dylib_module(&m
, 1, host_byte_sex
);
2664 ofile
->dylib_module
= p
;
2665 if(check_dylib_module(ofile
, st
, dyst
, strings
, i
) == CHECK_BAD
)
2667 if(strcmp(module_name
, strings
+ m
.module_name
) == 0){
2668 ofile
->dylib_module_name
= strings
+ m
.module_name
;
2673 m
= *ofile
->dylib_module
;
2675 swap_dylib_module(&m
, 1, host_byte_sex
);
2676 ofile
->dylib_module_name
= strings
+ m
.module_name
;
2679 ofile
->nmodtab
= dyst
->nmodtab
;
2680 ofile
->modtab64
= (struct dylib_module_64
*)(ofile
->object_addr
+
2682 p64
= ofile
->modtab64
;
2683 for(i
= 0; i
< dyst
->nmodtab
; i
++){
2686 swap_dylib_module_64(&m64
, 1, host_byte_sex
);
2687 ofile
->dylib_module64
= p64
;
2688 if(check_dylib_module(ofile
, st
, dyst
, strings
, i
) == CHECK_BAD
)
2690 if(strcmp(module_name
, strings
+ m64
.module_name
) == 0){
2691 ofile
->dylib_module_name
= strings
+ m64
.module_name
;
2696 m64
= *ofile
->dylib_module64
;
2698 swap_dylib_module_64(&m64
, 1, host_byte_sex
);
2699 ofile
->dylib_module_name
= strings
+ m64
.module_name
;
2702 Mach_O_error(ofile
, "does not contain a module named: %s", module_name
);
2704 ofile
->modtab
= NULL
;
2706 ofile
->dylib_module
= NULL
;
2707 ofile
->dylib_module_name
= NULL
;
2715 struct ofile
*ofile
)
2717 printf("file_name = %s\n", ofile
->file_name
);
2718 printf("file_addr = 0x%x\n", (unsigned int)ofile
->file_addr
);
2719 printf("file_size = 0x%x\n", (unsigned int)ofile
->file_size
);
2720 printf("file_type = 0x%x\n", (unsigned int)ofile
->file_type
);
2721 printf("fat_header = 0x%x\n", (unsigned int)ofile
->fat_header
);
2722 printf("fat_archs = 0x%x\n", (unsigned int)ofile
->fat_archs
);
2723 printf("narch = 0x%x\n", (unsigned int)ofile
->narch
);
2724 printf("arch_type = 0x%x\n", (unsigned int)ofile
->arch_type
);
2725 printf("arch_flag.name = %s\n", ofile
->arch_flag
.name
);
2726 printf("arch_flag.cputype = 0x%x\n",
2727 (unsigned int)ofile
->arch_flag
.cputype
);
2728 printf("arch_flag.cpusubtype = 0x%x\n",
2729 (unsigned int)ofile
->arch_flag
.cpusubtype
);
2730 printf("member_offset = 0x%x\n", (unsigned int)ofile
->member_offset
);
2731 printf("member_addr = 0x%x\n", (unsigned int)ofile
->member_addr
);
2732 printf("member_size = 0x%x\n", (unsigned int)ofile
->member_size
);
2733 printf("member_ar_hdr = 0x%x\n", (unsigned int)ofile
->member_ar_hdr
);
2734 printf("member_type = 0x%x\n", (unsigned int)ofile
->member_type
);
2735 printf("archive_cputype = 0x%x\n",
2736 (unsigned int)ofile
->archive_cputype
);
2737 printf("archive_cpusubtype = 0x%x\n",
2738 (unsigned int)ofile
->archive_cpusubtype
);
2739 printf("object_addr = 0x%x\n", (unsigned int)ofile
->object_addr
);
2740 printf("object_size = 0x%x\n", (unsigned int)ofile
->object_size
);
2741 printf("object_byte_sex = 0x%x\n",
2742 (unsigned int)ofile
->object_byte_sex
);
2743 printf("mh = 0x%x\n", (unsigned int)ofile
->mh
);
2744 printf("mh64 = 0x%x\n", (unsigned int)ofile
->mh64
);
2745 printf("load_commands = 0x%x\n", (unsigned int)ofile
->load_commands
);
2750 * check_fat() checks the fat ofile for correctness (the fat_header and
2751 * fat_archs are assumed to be in the host byte sex).
2756 struct ofile
*ofile
)
2760 #else /* !defined OTOOL */
2765 if(ofile
->file_type
!= OFILE_FAT
){
2766 error("internal error. check_fat() call and file type of: %s is "
2767 "not OFILE_FAT\n", ofile
->file_name
);
2770 if(ofile
->fat_header
->nfat_arch
== 0){
2771 error("fat file: %s malformed (contains zero architecture types)",
2775 for(i
= 0; i
< ofile
->fat_header
->nfat_arch
; i
++){
2776 big_size
= ofile
->fat_archs
[i
].offset
;
2777 big_size
+= ofile
->fat_archs
[i
].size
;
2778 if(big_size
> ofile
->file_size
){
2779 error("fat file: %s truncated or malformed (offset plus size "
2780 "of cputype (%d) cpusubtype (%d) extends past the "
2781 "end of the file)", ofile
->file_name
,
2782 ofile
->fat_archs
[i
].cputype
,
2783 ofile
->fat_archs
[i
].cpusubtype
& ~CPU_SUBTYPE_MASK
);
2786 if(ofile
->fat_archs
[i
].align
> MAXSECTALIGN
){
2787 error("fat file: %s align (2^%u) too large for cputype (%d) "
2788 "cpusubtype (%d) (maximum 2^%d)", ofile
->file_name
,
2789 ofile
->fat_archs
[i
].align
, ofile
->fat_archs
[i
].cputype
,
2790 ofile
->fat_archs
[i
].cpusubtype
& ~CPU_SUBTYPE_MASK
,
2794 if(ofile
->fat_archs
[i
].offset
%
2795 (1 << ofile
->fat_archs
[i
].align
) != 0){
2796 error("fat file: %s offset: %u for cputype (%d) cpusubtype "
2797 "(%d)) not aligned on it's alignment (2^%u)",
2799 ofile
->fat_archs
[i
].offset
,
2800 ofile
->fat_archs
[i
].cputype
,
2801 ofile
->fat_archs
[i
].cpusubtype
& ~CPU_SUBTYPE_MASK
,
2802 ofile
->fat_archs
[i
].align
);
2806 for(i
= 0; i
< ofile
->fat_header
->nfat_arch
; i
++){
2807 for(j
= i
+ 1; j
< ofile
->fat_header
->nfat_arch
; j
++){
2808 if(ofile
->fat_archs
[i
].cputype
==
2809 ofile
->fat_archs
[j
].cputype
&&
2810 (ofile
->fat_archs
[i
].cpusubtype
& ~CPU_SUBTYPE_MASK
) ==
2811 (ofile
->fat_archs
[j
].cpusubtype
& ~CPU_SUBTYPE_MASK
)){
2812 error("fat file: %s contains two of the same "
2813 "architecture (cputype (%d) cpusubtype (%d))",
2814 ofile
->file_name
, ofile
->fat_archs
[i
].cputype
,
2815 ofile
->fat_archs
[i
].cpusubtype
& ~CPU_SUBTYPE_MASK
);
2825 * check_fat_object_in_archive() checks the fat object file which is a member
2826 * of a thin archive for correctness (the fat_header and fat_archs are assumed
2827 * to be in the host byte sex). This is not a legal form but allowed when
2828 * archives_with_fat_objects is TRUE when ofile_map() is called.
2832 check_fat_object_in_archive(
2833 struct ofile
*ofile
)
2838 if(ofile
->file_type
!= OFILE_ARCHIVE
){
2839 error("internal error. check_fat_object_in_archive() called and "
2840 "file type of: %s is not OFILE_ARCHIVE\n", ofile
->file_name
);
2843 if(ofile
->fat_header
->nfat_arch
== 0){
2844 archive_member_error(ofile
, "fat file malformed (contains zero "
2845 "architecture types)");
2848 for(i
= 0; i
< ofile
->fat_header
->nfat_arch
; i
++){
2849 if(ofile
->fat_archs
[i
].offset
+ ofile
->fat_archs
[i
].size
>
2850 ofile
->member_size
){
2851 archive_member_error(ofile
, "fat file truncated or malformed "
2852 "(offset plus size of cputype (%d) cpusubtype (%d) "
2853 "extends past the end of the file)",
2854 ofile
->fat_archs
[i
].cputype
,
2855 ofile
->fat_archs
[i
].cpusubtype
& ~CPU_SUBTYPE_MASK
);
2858 if(ofile
->fat_archs
[i
].align
> MAXSECTALIGN
){
2859 archive_member_error(ofile
, "fat file's align (2^%u) too "
2860 "large for cputype (%d) cpusubtype (%d) (maximum 2^%d)",
2861 ofile
->fat_archs
[i
].align
, ofile
->fat_archs
[i
].cputype
,
2862 ofile
->fat_archs
[i
].cpusubtype
& ~CPU_SUBTYPE_MASK
,
2866 if(ofile
->fat_archs
[i
].offset
%
2867 (1 << ofile
->fat_archs
[i
].align
) != 0){
2868 archive_member_error(ofile
, "fat file's offset: %u for "
2869 "cputype (%d) cpusubtype (%d) not aligned on it's "
2870 "alignment (2^%u)", ofile
->fat_archs
[i
].offset
,
2871 ofile
->fat_archs
[i
].cputype
,
2872 ofile
->fat_archs
[i
].cpusubtype
& ~CPU_SUBTYPE_MASK
,
2873 ofile
->fat_archs
[i
].align
);
2878 * The only supported format where fat files are allowed to appear
2879 * in archives is when the fat file contains only object files.
2881 if(ofile
->fat_archs
[i
].size
< sizeof(struct mach_header
)){
2882 archive_member_error(ofile
, "fat file for cputype (%d) "
2883 "cpusubtype (%d) is not an object file (size too small "
2884 "to be an object file)", ofile
->fat_archs
[i
].cputype
,
2885 ofile
->fat_archs
[i
].cpusubtype
& ~CPU_SUBTYPE_MASK
);
2889 ofile
->file_addr
+ ofile
->member_offset
+
2890 ofile
->fat_archs
[i
].offset
,
2892 if(magic
== MH_MAGIC
|| magic
== SWAP_INT(MH_MAGIC
)){
2893 #ifdef ALIGNMENT_CHECKS
2894 if((ofile
->member_offset
+ ofile
->fat_archs
[i
].offset
) %
2896 archive_member_error(ofile
, "fat object file's offset in "
2897 "archive not a multiple of 4) (must be since "
2898 "member is a 32-bit object file)");
2901 #endif /* ALIGNMENT_CHECKS */
2903 else if(magic
== MH_MAGIC_64
|| magic
== SWAP_INT(MH_MAGIC_64
)){
2904 #ifdef ALIGNMENT_CHECKS_ARCHIVE_64_BIT
2905 if(archive_64_bit_align_warning
== FALSE
&&
2906 (ofile
->member_offset
+ ofile
->fat_archs
[i
].offset
) %
2908 temporary_archive_member_warning(ofile
, "fat object file's "
2909 "offset in archive not a multiple of 8) (must be since "
2910 "member is a 64-bit object file)");
2911 archive_64_bit_align_warning
= TRUE
;
2912 /* return(CHECK_BAD); */
2914 #endif /* ALIGNMENT_CHECKS_ARCHIVE_64_BIT */
2918 if(is_llvm_bitcode(ofile
, ofile
->file_addr
+
2919 ofile
->member_offset
+ ofile
->fat_archs
[i
].offset
,
2920 ofile
->fat_archs
[i
].size
) == TRUE
){
2921 ofile
->member_type
= OFILE_LLVM_BITCODE
;
2922 ofile
->object_addr
= ofile
->member_addr
;
2923 ofile
->object_size
= ofile
->member_size
;
2926 #endif /* LTO_SUPPORT */
2928 archive_member_error(ofile
, "fat file for cputype (%d) "
2929 "cpusubtype (%d) is not an object file (bad magic "
2930 "number)", ofile
->fat_archs
[i
].cputype
,
2931 ofile
->fat_archs
[i
].cpusubtype
& ~CPU_SUBTYPE_MASK
);
2936 for(i
= 0; i
< ofile
->fat_header
->nfat_arch
; i
++){
2937 for(j
= i
+ 1; j
< ofile
->fat_header
->nfat_arch
; j
++){
2938 if(ofile
->fat_archs
[i
].cputype
==
2939 ofile
->fat_archs
[j
].cputype
&&
2940 (ofile
->fat_archs
[i
].cpusubtype
& ~CPU_SUBTYPE_MASK
) ==
2941 (ofile
->fat_archs
[j
].cpusubtype
& ~CPU_SUBTYPE_MASK
)){
2942 archive_member_error(ofile
, "fat file contains two of the "
2943 "same architecture (cputype (%d) cpusubtype (%d))",
2944 ofile
->fat_archs
[i
].cputype
,
2945 ofile
->fat_archs
[i
].cpusubtype
& ~CPU_SUBTYPE_MASK
);
2954 * check_archive() checks the archive referenced in the ofile for correctness.
2959 struct ofile
*ofile
,
2960 enum bool archives_with_fat_objects
)
2964 #else /* !defined OTOOL */
2966 uint64_t size
, offset
;
2969 enum byte_sex host_byte_sex
;
2971 struct mach_header mh
;
2972 struct mach_header_64 mh64
;
2973 struct ar_hdr
*ar_hdr
;
2974 uint32_t ar_name_size
;
2977 * Get the address and size of the archive (as well as the cputype and
2978 * cpusubtype if known) and make sure it is an archive.
2980 if(ofile
->file_type
== OFILE_FAT
){
2981 addr
= ofile
->file_addr
+ ofile
->fat_archs
[ofile
->narch
].offset
;
2982 size
= ofile
->fat_archs
[ofile
->narch
].size
;
2983 ofile
->archive_cputype
= ofile
->fat_archs
[ofile
->narch
].cputype
;
2984 ofile
->archive_cpusubtype
=
2985 ofile
->fat_archs
[ofile
->narch
].cpusubtype
;
2987 else if(ofile
->file_type
== OFILE_ARCHIVE
){
2988 addr
= ofile
->file_addr
;
2989 size
= ofile
->file_size
;
2990 ofile
->archive_cputype
= 0;
2991 ofile
->archive_cpusubtype
= 0;
2994 error("internal error. check_archive() call and file type of %s is "
2995 "OFILE_UNKNOWN\n", ofile
->file_name
);
2998 if(size
< SARMAG
|| strncmp(addr
, ARMAG
, SARMAG
) != 0){
2999 error("internal error. check_archive() call for file %s which does "
3000 "not have an archive magic string", ofile
->file_name
);
3004 host_byte_sex
= get_host_byte_sex();
3006 * Check this archive out to make sure that it does not contain
3007 * any fat files and that all object files it contains have the
3008 * same cputype and subsubtype.
3013 if(offset
!= size
&& offset
+ sizeof(struct ar_hdr
) > size
){
3014 archive_error(ofile
, "truncated or malformed (archive header of "
3015 "first member extends past the end of the file)");
3018 while(size
> offset
){
3019 ar_hdr
= (struct ar_hdr
*)(addr
+ offset
);
3020 ofile
->member_offset
= offset
;
3021 ofile
->member_addr
= addr
+ offset
;
3022 ofile
->member_size
= strtoul(ar_hdr
->ar_size
, NULL
, 10);
3023 ofile
->member_ar_hdr
= ar_hdr
;
3024 ofile
->member_name
= ar_hdr
->ar_name
;
3025 ofile
->member_name_size
= size_ar_name(ofile
->member_ar_hdr
);
3026 offset
+= sizeof(struct ar_hdr
);
3028 * See if this archive member is using extend format #1 where
3029 * the size of the name is in ar_name and the name follows the
3033 if(strncmp(ofile
->member_name
,AR_EFMT1
, sizeof(AR_EFMT1
) - 1) == 0){
3034 if(check_extend_format_1(ofile
, ar_hdr
, size
- offset
,
3035 &ar_name_size
) == CHECK_BAD
)
3037 ofile
->member_name
= ar_hdr
->ar_name
+ sizeof(struct ar_hdr
);
3038 ofile
->member_name_size
= ar_name_size
;
3039 offset
+= ar_name_size
;
3040 ofile
->member_offset
+= ar_name_size
;
3041 ofile
->member_addr
+= ar_name_size
;
3042 ofile
->member_size
-= ar_name_size
;
3044 big_size
= rnd(ofile
->member_size
, sizeof(short));
3046 if(big_size
> size
){
3047 archive_member_error(ofile
, "size too large (archive "
3048 "member extends past the end of the file)");
3051 if(size
- offset
> sizeof(uint32_t)){
3052 memcpy(&magic
, addr
+ offset
, sizeof(uint32_t));
3053 #ifdef __BIG_ENDIAN__
3054 if(magic
== FAT_MAGIC
)
3055 #endif /* __BIG_ENDIAN__ */
3056 #ifdef __LITTLE_ENDIAN__
3057 if(magic
== SWAP_INT(FAT_MAGIC
))
3058 #endif /* __LITTLE_ENDIAN__ */
3060 if(archives_with_fat_objects
== FALSE
||
3061 ofile
->file_type
!= OFILE_ARCHIVE
){
3062 archive_member_error(ofile
, "is a fat file (not "
3063 "allowed in an archive)");
3068 if(size
- offset
>= sizeof(struct mach_header
) &&
3069 (magic
== MH_MAGIC
|| magic
== SWAP_INT(MH_MAGIC
))){
3070 memcpy(&mh
, addr
+ offset
, sizeof(struct mach_header
));
3071 if(magic
== SWAP_INT(MH_MAGIC
)){
3074 swap_mach_header(&mh
, host_byte_sex
);
3078 else if(size
- offset
>= sizeof(struct mach_header_64
) &&
3079 (magic
== MH_MAGIC_64
||
3080 magic
== SWAP_INT(MH_MAGIC_64
))){
3081 memcpy(&mh64
, addr
+ offset
,
3082 sizeof(struct mach_header_64
));
3083 if(magic
== SWAP_INT(MH_MAGIC_64
)){
3084 magic
= MH_MAGIC_64
;
3086 swap_mach_header_64(&mh64
, host_byte_sex
);
3090 if(magic
== MH_MAGIC
){
3091 if(ofile
->archive_cputype
== 0){
3092 ofile
->archive_cputype
= mh
.cputype
;
3093 ofile
->archive_cpusubtype
= mh
.cpusubtype
;
3095 else if(ofile
->archive_cputype
!= mh
.cputype
){
3096 archive_member_error(ofile
, "cputype (%d) does not "
3097 "match previous archive members cputype (%d) "
3098 "(all members must match)", mh
.cputype
,
3099 ofile
->archive_cputype
);
3102 else if(magic
== MH_MAGIC_64
){
3103 if(ofile
->archive_cputype
== 0){
3104 ofile
->archive_cputype
= mh64
.cputype
;
3105 ofile
->archive_cpusubtype
= mh64
.cpusubtype
;
3107 else if(ofile
->archive_cputype
!= mh64
.cputype
){
3108 archive_member_error(ofile
, "cputype (%d) does not "
3109 "match previous archive members cputype (%d) "
3110 "(all members must match)", mh64
.cputype
,
3111 ofile
->archive_cputype
);
3116 offset
+= rnd(ofile
->member_size
, sizeof(short));
3118 ofile
->member_offset
= 0;
3119 ofile
->member_addr
= NULL
;
3120 ofile
->member_size
= 0;
3121 ofile
->member_ar_hdr
= NULL
;;
3122 ofile
->member_name
= NULL
;
3123 ofile
->member_name_size
= 0;
3129 * check_extend_format_1() checks the archive header for extended format #1.
3133 check_extend_format_1(
3134 struct ofile
*ofile
,
3135 struct ar_hdr
*ar_hdr
,
3137 uint32_t *member_name_size
)
3139 char *p
, *endp
, buf
[sizeof(ar_hdr
->ar_name
)+1];
3140 uint32_t ar_name_size
;
3142 *member_name_size
= 0;
3144 buf
[sizeof(ar_hdr
->ar_name
)] = '\0';
3145 memcpy(buf
, ar_hdr
->ar_name
, sizeof(ar_hdr
->ar_name
));
3146 p
= buf
+ sizeof(AR_EFMT1
) - 1;
3147 if(isdigit(*p
) == 0){
3148 archive_error(ofile
, "malformed (ar_name: %.*s for archive "
3149 "extend format #1 starts with non-digit)",
3150 (int)sizeof(ar_hdr
->ar_name
), ar_hdr
->ar_name
);
3153 ar_name_size
= strtoul(p
, &endp
, 10);
3154 if(ar_name_size
== UINT_MAX
&& errno
== ERANGE
){
3155 archive_error(ofile
, "malformed (size in ar_name: %.*s for "
3156 "archive extend format #1 overflows uint32_t)",
3157 (int)sizeof(ar_hdr
->ar_name
), ar_hdr
->ar_name
);
3160 while(*endp
== ' ' && *endp
!= '\0')
3163 archive_error(ofile
, "malformed (size in ar_name: %.*s for "
3164 "archive extend format #1 contains non-digit and "
3165 "non-space characters)", (int)sizeof(ar_hdr
->ar_name
),
3169 if(ar_name_size
> size_left
){
3170 archive_error(ofile
, "truncated or malformed (archive name "
3171 "of member extends past the end of the file)");
3174 *member_name_size
= ar_name_size
;
3179 * check_archive_toc() checks the archive table of contents referenced in the
3180 * thin archive via the ofile for correctness and if bad sets the bad_toc field
3181 * in the ofile struct to TRUE. If not it sets the other toc_* fields that
3182 * ranlib(1) uses to know it can't update the table of contents and doesn't
3183 * have to totally rebuild it. And by this always returning CHECK_GOOD it
3184 * allows otool(1) to print messed up tables of contents for debugging.
3189 struct ofile
*ofile
)
3191 uint32_t i
, symdef_length
, offset
, nranlibs
, strsize
;
3192 enum byte_sex host_byte_sex
, toc_byte_sex
;
3193 struct ranlib
*ranlibs
;
3196 ofile
->toc_ranlibs
= NULL
;
3197 ofile
->toc_nranlibs
= 0;
3198 ofile
->toc_strings
= NULL
;
3199 ofile
->toc_strsize
= 0;
3202 * Note this can only be called when the whole file is a thin archive.
3204 if(ofile
->file_type
!= OFILE_ARCHIVE
)
3207 symdef_length
= ofile
->toc_size
;
3209 * The contents of a __.SYMDEF file is begins with a 32-bit word giving
3210 * the size in bytes of ranlib structures which immediately follow, and
3211 * then continues with a string table consisting of a 32-bit word giving
3212 * the number of bytes of strings which follow and then the strings
3213 * themselves. So the smallest valid size is two 32-bit words long.
3215 if(symdef_length
< 2 * sizeof(uint32_t)){
3217 * Size of table of contents for archive too small to be a valid
3218 * table of contents.
3220 ofile
->toc_bad
= TRUE
;
3223 host_byte_sex
= get_host_byte_sex();
3224 toc_byte_sex
= get_toc_byte_sex(ofile
->file_addr
, ofile
->file_size
);
3225 if(toc_byte_sex
== UNKNOWN_BYTE_SEX
){
3227 * Can't determine the byte order of table of contents as it
3228 * contains no Mach-O files.
3230 ofile
->toc_bad
= TRUE
;
3234 nranlibs
= *((uint32_t *)(ofile
->toc_addr
+ offset
));
3235 if(toc_byte_sex
!= host_byte_sex
)
3236 nranlibs
= SWAP_INT(nranlibs
);
3237 nranlibs
= nranlibs
/ sizeof(struct ranlib
);
3238 offset
+= sizeof(uint32_t);
3239 ranlibs
= (struct ranlib
*)(ofile
->toc_addr
+ offset
);
3240 offset
+= sizeof(struct ranlib
) * nranlibs
;
3243 if(offset
- (2 * sizeof(uint32_t)) > symdef_length
){
3245 * Truncated or malformed archive. The ranlib structures in table
3246 * of contents extends past the end of the table of contents.
3248 ofile
->toc_bad
= TRUE
;
3251 strsize
= *((uint32_t *)(ofile
->toc_addr
+ offset
));
3252 if(toc_byte_sex
!= host_byte_sex
)
3253 strsize
= SWAP_INT(strsize
);
3254 offset
+= sizeof(uint32_t);
3255 strings
= ofile
->toc_addr
+ offset
;
3257 if(offset
- (2 * sizeof(uint32_t)) > symdef_length
){
3259 * Truncated or malformed archive. The ranlib strings in table of
3260 * contents extends past the end of the table of contents.
3262 ofile
->toc_bad
= TRUE
;
3265 if(symdef_length
== 2 * sizeof(uint32_t))
3269 * Check the string offset and the member offsets of the ranlib structs.
3271 if(toc_byte_sex
!= host_byte_sex
)
3272 swap_ranlib(ranlibs
, nranlibs
, host_byte_sex
);
3273 for(i
= 0; i
< nranlibs
; i
++){
3274 if(ranlibs
[i
].ran_un
.ran_strx
>= strsize
){
3276 * Malformed table of contents. The ranlib struct at this index
3277 * has a bad string index field.
3279 ofile
->toc_bad
= TRUE
;
3282 if(ranlibs
[i
].ran_off
>= ofile
->file_size
){
3284 * Malformed table of contents. The ranlib struct at this index
3285 * has a bad library member offset field.
3287 ofile
->toc_bad
= TRUE
;
3291 * These should be on 4 byte boundaries because the maximum
3292 * alignment of the header structures and relocation are 4 bytes.
3293 * But this is has to be 2 bytes because that's the way ar(1) has
3294 * worked historicly in the past. Fortunately this works on the
3295 * 68k machines but will have to change when this is on a real
3298 #if defined(mc68000) || defined(__i386__)
3299 if(ranlibs
[i
].ran_off
% sizeof(short) != 0){
3301 * Malformed table of contents. This ranlib struct library
3302 * member offset not a multiple 2 bytes.
3304 ofile
->toc_bad
= TRUE
;
3308 if(ranlibs
[i
].ran_off
% sizeof(uint32_t) != 0){
3310 * Malformed table of contents. This ranlib struct library
3311 * member offset not a multiple of 4 bytes.
3313 ofile
->toc_bad
= TRUE
;
3318 ofile
->toc_ranlibs
= ranlibs
;
3319 ofile
->toc_nranlibs
= nranlibs
;
3320 ofile
->toc_strings
= strings
;
3321 ofile
->toc_strsize
= strsize
;
3326 * check_Mach_O() checks the object file's mach header and load commands
3327 * referenced in the ofile for correctness (this also swaps the mach header
3328 * and load commands into the host byte sex if needed).
3333 struct ofile
*ofile
)
3337 #else /* !defined OTOOL */
3338 uint32_t size
, i
, j
, ncmds
, sizeofcmds
, load_command_multiple
, sizeofhdrs
;
3340 char *addr
, *cmd_name
, *element_name
;
3341 enum byte_sex host_byte_sex
;
3343 struct mach_header
*mh
;
3344 struct mach_header_64
*mh64
;
3345 struct load_command
*load_commands
, *lc
, l
;
3346 struct segment_command
*sg
;
3347 struct segment_command_64
*sg64
;
3349 struct section_64
*s64
;
3350 struct symtab_command
*st
;
3351 struct dysymtab_command
*dyst
;
3352 struct symseg_command
*ss
;
3353 struct fvmlib_command
*fl
;
3354 struct dylib_command
*dl
;
3355 struct sub_framework_command
*sub
;
3356 struct sub_umbrella_command
*usub
;
3357 struct sub_library_command
*lsub
;
3358 struct sub_client_command
*csub
;
3359 struct prebound_dylib_command
*pbdylib
;
3360 struct dylinker_command
*dyld
;
3361 struct thread_command
*ut
;
3362 struct ident_command
*id
;
3363 struct routines_command
*rc
;
3364 struct routines_command_64
*rc64
;
3365 struct twolevel_hints_command
*hints
;
3366 struct linkedit_data_command
*code_sig
, *split_info
, *func_starts
,
3367 *data_in_code
, *code_sign_drs
, *linkedit_data
;
3368 struct version_min_command
*vers
;
3369 struct prebind_cksum_command
*cs
;
3370 struct encryption_info_command
*encrypt_info
;
3371 struct encryption_info_command_64
*encrypt_info64
;
3372 struct dyld_info_command
*dyld_info
;
3373 struct uuid_command
*uuid
;
3374 struct rpath_command
*rpath
;
3375 struct entry_point_command
*ep
;
3376 struct source_version_command
*sv
;
3377 uint32_t flavor
, count
, nflavor
;
3379 uint32_t sizeof_nlist
, sizeof_dylib_module
;
3380 char *struct_dylib_module_name
, *struct_nlist_name
;
3381 uint64_t big_size
, big_end
, big_load_end
;
3382 struct element elements
;
3384 elements
.offset
= 0;
3386 elements
.name
= NULL
;
3387 elements
.next
= NULL
;
3389 addr
= ofile
->object_addr
;
3390 size
= ofile
->object_size
;
3393 load_commands
= ofile
->load_commands
;
3394 host_byte_sex
= get_host_byte_sex();
3395 swapped
= (enum bool)(host_byte_sex
!= ofile
->object_byte_sex
);
3397 if(ofile
->mh
!= NULL
){
3399 swap_mach_header(mh
, host_byte_sex
);
3400 big_size
= mh
->sizeofcmds
;
3401 big_size
+= sizeof(struct mach_header
);
3402 if(big_size
> size
){
3403 Mach_O_error(ofile
, "truncated or malformed object (load "
3404 "commands extend past the end of the file)");
3407 sizeofhdrs
= big_size
;
3408 ofile
->mh_cputype
= mh
->cputype
;
3409 ofile
->mh_cpusubtype
= mh
->cpusubtype
;
3410 ofile
->mh_filetype
= mh
->filetype
;
3412 sizeofcmds
= mh
->sizeofcmds
;
3413 cputype
= mh
->cputype
;
3414 load_command_multiple
= 4;
3415 sizeof_nlist
= sizeof(struct nlist
);
3416 struct_nlist_name
= "struct nlist";
3417 sizeof_dylib_module
= sizeof(struct dylib_module
);
3418 struct_dylib_module_name
= "struct dylib_module";
3422 swap_mach_header_64(mh64
, host_byte_sex
);
3423 big_size
= mh64
->sizeofcmds
;
3424 big_size
+= sizeof(struct mach_header_64
);
3425 if(big_size
> size
){
3426 Mach_O_error(ofile
, "truncated or malformed object (load "
3427 "commands extend past the end of the file)");
3430 sizeofhdrs
= big_size
;
3431 ofile
->mh_cputype
= mh64
->cputype
;
3432 ofile
->mh_cpusubtype
= mh64
->cpusubtype
;
3433 ofile
->mh_filetype
= mh64
->filetype
;
3434 ncmds
= mh64
->ncmds
;
3435 sizeofcmds
= mh64
->sizeofcmds
;
3436 cputype
= mh64
->cputype
;
3437 load_command_multiple
= 8;
3438 sizeof_nlist
= sizeof(struct nlist_64
);
3439 struct_nlist_name
= "struct nlist_64";
3440 sizeof_dylib_module
= sizeof(struct dylib_module_64
);
3441 struct_dylib_module_name
= "struct dylib_module_64";
3443 if(check_overlaping_element(ofile
, &elements
, 0, sizeofhdrs
,
3444 "Mach-O headers") == CHECK_BAD
)
3446 if(ofile
->file_type
== OFILE_FAT
){
3447 if(ofile
->fat_archs
[ofile
->narch
].cputype
!= ofile
->mh_cputype
){
3448 Mach_O_error(ofile
, "malformed fat file (fat header "
3449 "architecture: %u's cputype does not match "
3450 "object file's mach header)", ofile
->narch
);
3455 * Make a pass through the load commands checking them to the level
3456 * that they can be parsed and all fields with offsets and sizes do
3457 * not extend past the end of the file.
3466 data_in_code
= NULL
;
3467 code_sign_drs
= NULL
;
3471 encrypt_info
= NULL
;
3475 for(i
= 0, lc
= load_commands
; i
< ncmds
; i
++){
3478 swap_load_command(&l
, host_byte_sex
);
3480 * Check load command size for a multiple of load_command_multiple.
3482 if(l
.cmdsize
% load_command_multiple
!= 0){
3484 * We have a hack here to allow 64-bit Mach-O core files to
3485 * have LC_THREAD commands that are only a multiple of 4 and
3486 * not 8 to be allowed since the kernel produces them.
3488 if(ofile
->mh64
== NULL
||
3489 ofile
->mh64
->filetype
!= MH_CORE
||
3490 l
.cmd
!= LC_THREAD
||
3491 l
.cmdsize
% 4 != 0){
3492 Mach_O_error(ofile
, "malformed object (load command %u "
3493 "cmdsize not a multiple of %u)", i
,
3494 load_command_multiple
);
3498 /* check that load command does not extends past end of commands */
3499 big_load_end
+= l
.cmdsize
;
3500 if(big_load_end
> sizeofcmds
){
3501 Mach_O_error(ofile
, "truncated or malformed object (load "
3502 "command %u extends past the end of the file)",i
);
3505 /* check that the load command size is not zero */
3507 Mach_O_error(ofile
, "malformed object (load command %u cmdsize"
3513 if(l
.cmdsize
< sizeof(struct segment_command
)){
3514 Mach_O_error(ofile
, "malformed object (LC_SEGMENT cmdsize "
3515 "too small) in command %u", i
);
3518 sg
= (struct segment_command
*)lc
;
3520 swap_segment_command(sg
, host_byte_sex
);
3521 big_size
= sg
->nsects
;
3522 big_size
*= sizeof(struct section
);
3523 big_size
+= sizeof(struct segment_command
);
3524 if(sg
->cmdsize
!= big_size
){
3525 Mach_O_error(ofile
, "malformed object (inconsistent "
3526 "cmdsize in LC_SEGMENT command %u for the "
3527 "number of sections)", i
);
3530 if(sg
->fileoff
> size
){
3531 Mach_O_error(ofile
, "truncated or malformed object ("
3532 "LC_SEGMENT command %u fileoff field "
3533 "extends past the end of the file)", i
);
3536 big_size
= sg
->fileoff
;
3537 big_size
+= sg
->filesize
;
3538 if(big_size
> size
){
3539 Mach_O_error(ofile
, "truncated or malformed object ("
3540 "LC_SEGMENT command %u fileoff field "
3541 "plus filesize field extends past the end of "
3545 if(sg
->vmsize
!= 0 && sg
->filesize
> sg
->vmsize
){
3546 Mach_O_error(ofile
, "malformed object (LC_SEGMENT command "
3547 "%u filesize field greater than vmsize field)",
3551 s
= (struct section
*)
3552 ((char *)sg
+ sizeof(struct segment_command
));
3554 swap_section(s
, sg
->nsects
, host_byte_sex
);
3555 for(j
= 0 ; j
< sg
->nsects
; j
++){
3556 if(mh
->filetype
!= MH_DYLIB_STUB
&&
3557 s
->flags
!= S_ZEROFILL
&&
3558 s
->flags
!= S_THREAD_LOCAL_ZEROFILL
&& s
->offset
> size
){
3559 Mach_O_error(ofile
, "truncated or malformed object "
3560 "(offset field of section %u in LC_SEGMENT "
3561 "command %u extends past the end of the file)",
3565 if(mh
->filetype
!= MH_DYLIB_STUB
&&
3566 s
->flags
!= S_ZEROFILL
&&
3567 s
->flags
!= S_THREAD_LOCAL_ZEROFILL
&&
3568 sg
->fileoff
== 0 && s
->offset
< sizeofhdrs
&&
3570 Mach_O_error(ofile
, "malformed object (offset field of "
3571 "section %u in LC_SEGMENT command %u not "
3572 "past the headers of the file)", j
, i
);
3575 big_size
= s
->offset
;
3576 big_size
+= s
->size
;
3577 if(mh
->filetype
!= MH_DYLIB_STUB
&&
3578 s
->flags
!= S_ZEROFILL
&&
3579 s
->flags
!= S_THREAD_LOCAL_ZEROFILL
&& big_size
> size
){
3580 Mach_O_error(ofile
, "truncated or malformed object "
3581 "(offset field plus size field of section %u "
3582 "in LC_SEGMENT command %u extends "
3583 "past the end of the file)", j
, i
);
3586 if(mh
->filetype
!= MH_DYLIB_STUB
&&
3587 s
->flags
!= S_ZEROFILL
&&
3588 s
->flags
!= S_THREAD_LOCAL_ZEROFILL
&&
3589 s
->size
> sg
->filesize
){
3590 Mach_O_error(ofile
, "malformed object (size field of "
3591 "section %u in LC_SEGMENT command %u greater "
3592 "than the segment)", j
, i
);
3595 if(mh
->filetype
!= MH_DYLIB_STUB
&&
3596 s
->size
!= 0 && s
->addr
< sg
->vmaddr
){
3597 Mach_O_error(ofile
, "malformed object (addr field of "
3598 "section %u in LC_SEGMENT command %u less than "
3599 "the segment's vmaddr)", j
, i
);
3603 big_size
+= s
->size
;
3604 big_end
= sg
->vmaddr
;
3605 big_end
+= sg
->vmsize
;
3606 if(sg
->vmsize
!= 0 && s
->size
!= 0 && big_size
> big_end
){
3607 Mach_O_error(ofile
, "malformed object (addr field plus "
3608 "size of section %u in LC_SEGMENT command %u "
3609 "greater than than the segment's vmaddr plus "
3613 if(mh
->filetype
!= MH_DYLIB_STUB
&&
3614 mh
->filetype
!= MH_DSYM
&&
3615 s
->flags
!= S_ZEROFILL
&&
3616 s
->flags
!= S_THREAD_LOCAL_ZEROFILL
&&
3617 check_overlaping_element(ofile
, &elements
, s
->offset
,
3618 s
->size
, "section contents") == CHECK_BAD
)
3620 if(s
->reloff
> size
){
3621 Mach_O_error(ofile
, "truncated or malformed object "
3622 "(reloff field of section %u in LC_SEGMENT "
3623 "command %u extends past the end of the file)",
3627 big_size
= s
->nreloc
;
3628 big_size
*= sizeof(struct relocation_info
);
3629 big_size
+= s
->reloff
;
3630 if(big_size
> size
){
3631 Mach_O_error(ofile
, "truncated or malformed object "
3632 "(reloff field plus nreloc field times sizeof("
3633 "struct relocation_info) of section %u in "
3634 "LC_SEGMENT command %u extends past the "
3635 "end of the file)", j
, i
);
3638 if(check_overlaping_element(ofile
, &elements
, s
->reloff
,
3639 s
->nreloc
* sizeof(struct relocation_info
),
3640 "section relocation entries") == CHECK_BAD
)
3647 if(l
.cmdsize
< sizeof(struct segment_command_64
)){
3648 Mach_O_error(ofile
, "malformed object (LC_SEGMENT_64 "
3649 "cmdsize too small) in command %u", i
);
3652 sg64
= (struct segment_command_64
*)lc
;
3654 swap_segment_command_64(sg64
, host_byte_sex
);
3655 big_size
= sg64
->nsects
;
3656 big_size
*= sizeof(struct section_64
);
3657 big_size
+= sizeof(struct segment_command_64
);
3658 if(sg64
->cmdsize
!= big_size
){
3659 Mach_O_error(ofile
, "malformed object (inconsistent "
3660 "cmdsize in LC_SEGMENT_64 command %u for "
3661 "the number of sections)", i
);
3664 if(sg64
->fileoff
> size
){
3665 Mach_O_error(ofile
, "truncated or malformed object ("
3666 "LC_SEGMENT_64 command %u fileoff field "
3667 "extends past the end of the file)", i
);
3670 big_size
= sg64
->fileoff
;
3671 big_size
+= sg64
->filesize
;
3672 if(big_size
> size
){
3673 Mach_O_error(ofile
, "truncated or malformed object ("
3674 "LC_SEGMENT_64 command %u fileoff field "
3675 "plus filesize field extends past the end of "
3679 s64
= (struct section_64
*)
3680 ((char *)sg64
+ sizeof(struct segment_command_64
));
3682 swap_section_64(s64
, sg64
->nsects
, host_byte_sex
);
3683 for(j
= 0 ; j
< sg64
->nsects
; j
++){
3684 if(mh64
->filetype
!= MH_DYLIB_STUB
&&
3685 s64
->flags
!= S_ZEROFILL
&&
3686 s64
->flags
!= S_THREAD_LOCAL_ZEROFILL
&&
3687 s64
->offset
> size
){
3688 Mach_O_error(ofile
, "truncated or malformed object "
3689 "(offset field of section %u in LC_SEGMENT_64 "
3690 "command %u extends past the end of the file)",
3694 big_size
= s64
->offset
;
3695 big_size
+= s64
->size
;
3696 if(mh64
->filetype
!= MH_DYLIB_STUB
&&
3697 s64
->flags
!= S_ZEROFILL
&&
3698 s64
->flags
!= S_THREAD_LOCAL_ZEROFILL
&&
3700 Mach_O_error(ofile
, "truncated or malformed object "
3701 "(offset field plus size field of section %u "
3702 "in LC_SEGMENT_64 command %u extends "
3703 "past the end of the file)", j
, i
);
3706 if(mh64
->filetype
!= MH_DYLIB_STUB
&&
3707 mh64
->filetype
!= MH_DSYM
&&
3708 s64
->flags
!= S_ZEROFILL
&&
3709 s64
->flags
!= S_THREAD_LOCAL_ZEROFILL
&&
3710 check_overlaping_element(ofile
, &elements
, s64
->offset
,
3711 s64
->size
, "section contents") == CHECK_BAD
)
3713 if(s64
->reloff
> size
){
3714 Mach_O_error(ofile
, "truncated or malformed object "
3715 "(reloff field of section %u in LC_SEGMENT_64 "
3716 "command %u extends past the end of the file)",
3720 big_size
= s64
->nreloc
;
3721 big_size
*= sizeof(struct relocation_info
);
3722 big_size
+= s64
->reloff
;
3723 if(big_size
> size
){
3724 Mach_O_error(ofile
, "truncated or malformed object "
3725 "(reloff field plus nreloc field times sizeof("
3726 "struct relocation_info) of section %u in "
3727 "LC_SEGMENT_64 command %u extends past the "
3728 "end of the file)", j
, i
);
3731 if(check_overlaping_element(ofile
, &elements
, s64
->reloff
,
3732 s64
->nreloc
* sizeof(struct relocation_info
),
3733 "section relocation entries") == CHECK_BAD
)
3740 if(l
.cmdsize
< sizeof(struct symtab_command
)){
3741 Mach_O_error(ofile
, "malformed object (LC_SYMTAB cmdsize "
3742 "too small) in command %u", i
);
3746 Mach_O_error(ofile
, "malformed object (more than one "
3747 "LC_SYMTAB command)");
3750 st
= (struct symtab_command
*)lc
;
3752 swap_symtab_command(st
, host_byte_sex
);
3753 if(st
->cmdsize
!= sizeof(struct symtab_command
)){
3754 Mach_O_error(ofile
, "malformed object (LC_SYMTAB command "
3755 "%u has incorrect cmdsize)", i
);
3758 if(st
->symoff
> size
){
3759 Mach_O_error(ofile
, "truncated or malformed object (symoff "
3760 "field of LC_SYMTAB command %u extends past the end "
3764 big_size
= st
->nsyms
;
3765 big_size
*= sizeof_nlist
;
3766 big_size
+= st
->symoff
;
3767 if(big_size
> size
){
3768 Mach_O_error(ofile
, "truncated or malformed object (symoff "
3769 "field plus nsyms field times sizeof(%s) of LC_SYMTAB "
3770 "command %u extends past the end of the file)",
3771 struct_nlist_name
, i
);
3774 if(check_overlaping_element(ofile
, &elements
, st
->symoff
,
3775 st
->nsyms
* sizeof_nlist
, "symbol table") == CHECK_BAD
)
3777 if(st
->stroff
> size
){
3778 Mach_O_error(ofile
, "truncated or malformed object (stroff "
3779 "field of LC_SYMTAB command %u extends past the end "
3783 big_size
= st
->stroff
;
3784 big_size
+= st
->strsize
;
3785 if(big_size
> size
){
3786 Mach_O_error(ofile
, "truncated or malformed object (stroff "
3787 "field plus strsize field of LC_SYMTAB command %u "
3788 "extends past the end of the file)", i
);
3791 if(check_overlaping_element(ofile
, &elements
, st
->stroff
,
3792 st
->strsize
, "string table") == CHECK_BAD
)
3797 if(l
.cmdsize
< sizeof(struct dysymtab_command
)){
3798 Mach_O_error(ofile
, "malformed object (LC_DYSYMTAB cmdsize "
3799 "too small) in command %u", i
);
3803 Mach_O_error(ofile
, "malformed object (more than one "
3804 "LC_DYSYMTAB command)");
3807 dyst
= (struct dysymtab_command
*)lc
;
3809 swap_dysymtab_command(dyst
, host_byte_sex
);
3810 if(dyst
->cmdsize
!= sizeof(struct dysymtab_command
)){
3811 Mach_O_error(ofile
, "malformed object (LC_DYSYMTAB command "
3812 "%u has incorrect cmdsize)", i
);
3815 if(dyst
->tocoff
> size
){
3816 Mach_O_error(ofile
, "truncated or malformed object (tocoff "
3817 "field of LC_DYSYMTAB command %u extends past the end "
3821 big_size
= dyst
->ntoc
;
3822 big_size
*= sizeof(struct dylib_table_of_contents
);
3823 big_size
+= dyst
->tocoff
;
3824 if(big_size
> size
){
3825 Mach_O_error(ofile
, "truncated or malformed object (tocoff "
3826 "field plus ntoc field times sizeof(struct dylib_table"
3827 "_of_contents) of LC_DYSYMTAB command %u extends past "
3828 "the end of the file)", i
);
3831 if(check_overlaping_element(ofile
, &elements
, dyst
->tocoff
,
3832 dyst
->ntoc
* sizeof(struct dylib_table_of_contents
),
3833 "table of contents") == CHECK_BAD
)
3835 if(dyst
->modtaboff
> size
){
3836 Mach_O_error(ofile
, "truncated or malformed object "
3837 "(modtaboff field of LC_DYSYMTAB command %u extends "
3838 "past the end of the file)", i
);
3841 big_size
= dyst
->nmodtab
;
3842 big_size
*= sizeof_dylib_module
;
3843 big_size
+= dyst
->modtaboff
;
3844 if(big_size
> size
){
3845 Mach_O_error(ofile
, "truncated or malformed object "
3846 "(modtaboff field plus nmodtab field times sizeof(%s) "
3847 "of LC_DYSYMTAB command %u extends past the end of "
3848 "the file)", struct_dylib_module_name
, i
);
3851 if(check_overlaping_element(ofile
, &elements
, dyst
->modtaboff
,
3852 dyst
->nmodtab
* sizeof_dylib_module
, "module table") ==
3855 if(dyst
->extrefsymoff
> size
){
3856 Mach_O_error(ofile
, "truncated or malformed object "
3857 "(extrefsymoff field of LC_DYSYMTAB command %u "
3858 "extends past the end of the file)", i
);
3861 big_size
= dyst
->nextrefsyms
;
3862 big_size
*= sizeof(struct dylib_reference
);
3863 big_size
+= dyst
->extrefsymoff
;
3864 if(big_size
> size
){
3865 Mach_O_error(ofile
, "truncated or malformed object "
3866 "(extrefsymoff field plus nextrefsyms field times "
3867 "sizeof(struct dylib_reference) of LC_DYSYMTAB command "
3868 "%u extends past the end of the file)", i
);
3871 if(check_overlaping_element(ofile
, &elements
,dyst
->extrefsymoff
,
3872 dyst
->nextrefsyms
* sizeof(struct dylib_reference
),
3873 "reference table") == CHECK_BAD
)
3875 if(dyst
->indirectsymoff
> size
){
3876 Mach_O_error(ofile
, "truncated or malformed object "
3877 "(indirectsymoff field of LC_DYSYMTAB command %u "
3878 "extends past the end of the file)", i
);
3881 big_size
= dyst
->nindirectsyms
;
3882 big_size
*= sizeof(uint32_t);
3883 big_size
+= dyst
->indirectsymoff
;
3884 if(big_size
> size
){
3885 Mach_O_error(ofile
, "truncated or malformed object "
3886 "(indirectsymoff field plus nindirectsyms field times "
3887 "sizeof(uint32_t) of LC_DYSYMTAB command "
3888 "%u extends past the end of the file)", i
);
3891 if(check_overlaping_element(ofile
, &elements
,
3892 dyst
->indirectsymoff
, dyst
->nindirectsyms
*
3893 sizeof(uint32_t), "indirect table") == CHECK_BAD
)
3895 if(dyst
->extreloff
> size
){
3896 Mach_O_error(ofile
, "truncated or malformed object "
3897 "(extreloff field of LC_DYSYMTAB command %u "
3898 "extends past the end of the file)", i
);
3901 big_size
= dyst
->nextrel
;
3902 big_size
*= sizeof(struct relocation_info
);
3903 big_size
+= dyst
->extreloff
;
3904 if(big_size
> size
){
3905 Mach_O_error(ofile
, "truncated or malformed object "
3906 "(extreloff field plus nextrel field times "
3907 "sizeof(struct relocation_info) of LC_DYSYMTAB command "
3908 "%u extends past the end of the file)", i
);
3911 if(check_overlaping_element(ofile
, &elements
, dyst
->extreloff
,
3912 dyst
->nextrel
* sizeof(struct relocation_info
),
3913 "external relocation table") == CHECK_BAD
)
3915 if(dyst
->locreloff
> size
){
3916 Mach_O_error(ofile
, "truncated or malformed object "
3917 "(locreloff field of LC_DYSYMTAB command %u "
3918 "extends past the end of the file)", i
);
3921 big_size
= dyst
->nlocrel
;
3922 big_size
*= sizeof(struct relocation_info
);
3923 big_size
+= dyst
->locreloff
;
3924 if(big_size
> size
){
3925 Mach_O_error(ofile
, "truncated or malformed object "
3926 "(locreloff field plus nlocrel field times "
3927 "sizeof(struct relocation_info) of LC_DYSYMTAB command "
3928 "%u extends past the end of the file)", i
);
3931 if(check_overlaping_element(ofile
, &elements
, dyst
->locreloff
,
3932 dyst
->nlocrel
* sizeof(struct relocation_info
),
3933 "local relocation table") == CHECK_BAD
)
3938 if(l
.cmdsize
< sizeof(struct routines_command
)){
3939 Mach_O_error(ofile
, "malformed object (LC_ROUTINES cmdsize "
3940 "too small) in command %u", i
);
3944 Mach_O_error(ofile
, "malformed object (more than one "
3945 "LC_ROUTINES command)");
3948 rc
= (struct routines_command
*)lc
;
3950 swap_routines_command(rc
, host_byte_sex
);
3951 if(rc
->cmdsize
!= sizeof(struct routines_command
)){
3952 Mach_O_error(ofile
, "malformed object (LC_ROUTINES "
3953 "command %u has incorrect cmdsize)", i
);
3958 case LC_ROUTINES_64
:
3959 if(l
.cmdsize
< sizeof(struct routines_command_64
)){
3960 Mach_O_error(ofile
, "malformed object (LC_ROUTINES_64 "
3961 "cmdsize too small) in command %u", i
);
3965 Mach_O_error(ofile
, "malformed object (more than one "
3966 "LC_ROUTINES_64 command)");
3969 rc64
= (struct routines_command_64
*)lc
;
3971 swap_routines_command_64(rc64
, host_byte_sex
);
3972 if(rc64
->cmdsize
!= sizeof(struct routines_command_64
)){
3973 Mach_O_error(ofile
, "malformed object (LC_ROUTINES_64 "
3974 "command %u has incorrect cmdsize)", i
);
3979 case LC_TWOLEVEL_HINTS
:
3980 if(l
.cmdsize
< sizeof(struct twolevel_hints_command
)){
3981 Mach_O_error(ofile
, "malformed object (LC_TWOLEVEL_HINTS "
3982 "cmdsize too small) in command %u", i
);
3986 Mach_O_error(ofile
, "malformed object (more than one "
3987 "LC_TWOLEVEL_HINTS command)");
3990 hints
= (struct twolevel_hints_command
*)lc
;
3992 swap_twolevel_hints_command(hints
, host_byte_sex
);
3993 if(hints
->cmdsize
!= sizeof(struct twolevel_hints_command
)){
3994 Mach_O_error(ofile
, "malformed object (LC_TWOLEVEL_HINTS "
3995 "command %u has incorrect cmdsize)", i
);
3998 if(hints
->offset
> size
){
3999 Mach_O_error(ofile
, "truncated or malformed object "
4000 "(offset field of LC_TWOLEVEL_HINTS command %u "
4001 "extends past the end of the file)", i
);
4004 big_size
= hints
->nhints
;
4005 big_size
*= sizeof(struct twolevel_hint
);
4006 big_size
+= hints
->offset
;
4007 if(big_size
> size
){
4008 Mach_O_error(ofile
, "truncated or malformed object "
4009 "(offset field plus nhints field times "
4010 "sizeof(struct twolevel_hint) of LC_TWOLEVEL_HINTS "
4011 " command %u extends past the end of the file)", i
);
4014 if(check_overlaping_element(ofile
, &elements
, hints
->offset
,
4015 hints
->nhints
* sizeof(struct twolevel_hint
),
4016 "two level hints") == CHECK_BAD
)
4020 case LC_SEGMENT_SPLIT_INFO
:
4021 cmd_name
= "LC_SEGMENT_SPLIT_INFO";
4022 element_name
= "split info data";
4023 if(split_info
!= NULL
){
4024 Mach_O_error(ofile
, "malformed object (more than one "
4025 "%s command)", cmd_name
);
4028 split_info
= (struct linkedit_data_command
*)lc
;
4029 goto check_linkedit_data_command
;
4031 case LC_CODE_SIGNATURE
:
4032 cmd_name
= "LC_CODE_SIGNATURE";
4033 element_name
= "code signature data";
4034 if(code_sig
!= NULL
){
4035 Mach_O_error(ofile
, "malformed object (more than one "
4036 "%s command)", cmd_name
);
4039 code_sig
= (struct linkedit_data_command
*)lc
;
4040 goto check_linkedit_data_command
;
4042 case LC_FUNCTION_STARTS
:
4043 cmd_name
= "LC_FUNCTION_STARTS";
4044 element_name
= "function starts data";
4045 if(func_starts
!= NULL
){
4046 Mach_O_error(ofile
, "malformed object (more than one "
4047 "%s command)", cmd_name
);
4050 func_starts
= (struct linkedit_data_command
*)lc
;
4051 goto check_linkedit_data_command
;
4053 case LC_DATA_IN_CODE
:
4054 cmd_name
= "LC_DATA_IN_CODE";
4055 element_name
= "date in code info";
4056 if(data_in_code
!= NULL
){
4057 Mach_O_error(ofile
, "malformed object (more than one "
4058 "%s command)", cmd_name
);
4061 data_in_code
= (struct linkedit_data_command
*)lc
;
4062 goto check_linkedit_data_command
;
4064 case LC_DYLIB_CODE_SIGN_DRS
:
4065 cmd_name
= "LC_DYLIB_CODE_SIGN_DRS";
4066 element_name
= "code signing RDs data";
4067 if(code_sign_drs
!= NULL
){
4068 Mach_O_error(ofile
, "malformed object (more than one "
4069 "%s command)", cmd_name
);
4072 code_sign_drs
= (struct linkedit_data_command
*)lc
;
4073 goto check_linkedit_data_command
;
4075 check_linkedit_data_command
:
4076 if(l
.cmdsize
< sizeof(struct linkedit_data_command
)){
4077 Mach_O_error(ofile
, "malformed object (%s cmdsize too "
4078 "small) in command %u", cmd_name
, i
);
4081 linkedit_data
= (struct linkedit_data_command
*)lc
;
4083 swap_linkedit_data_command(linkedit_data
, host_byte_sex
);
4084 if(linkedit_data
->cmdsize
!=
4085 sizeof(struct linkedit_data_command
)){
4086 Mach_O_error(ofile
, "malformed object (%s command %u has "
4087 "incorrect cmdsize)", cmd_name
, i
);
4090 if(linkedit_data
->dataoff
> size
){
4091 Mach_O_error(ofile
, "truncated or malformed object "
4092 "(dataoff field of %s command %u extends past the end "
4093 "of the file)", cmd_name
, i
);
4096 big_size
= linkedit_data
->dataoff
;
4097 big_size
+= linkedit_data
->datasize
;
4098 if(big_size
> size
){
4099 Mach_O_error(ofile
, "truncated or malformed object "
4100 "(dataoff field plus datasize field of "
4101 "%s command %u extends past the end of "
4102 "the file)", cmd_name
, i
);
4105 if(check_overlaping_element(ofile
, &elements
,
4106 linkedit_data
->dataoff
, linkedit_data
->datasize
,
4107 element_name
) == CHECK_BAD
)
4111 case LC_VERSION_MIN_MACOSX
:
4112 if(l
.cmdsize
< sizeof(struct version_min_command
)){
4113 Mach_O_error(ofile
, "malformed object (LC_VERSION_MIN_"
4114 "MACOSX cmdsize too small) in command %u", i
);
4118 Mach_O_error(ofile
, "malformed object (more than one "
4119 "LC_VERSION_MIN_IPHONEOS or LC_VERSION_MIN_MACOSX "
4123 vers
= (struct version_min_command
*)lc
;
4125 swap_version_min_command(vers
, host_byte_sex
);
4126 if(vers
->cmdsize
< sizeof(struct version_min_command
)){
4127 Mach_O_error(ofile
, "malformed object (LC_VERSION_MIN_"
4128 "MACOSX command %u has too small cmdsize field)", i
);
4133 case LC_VERSION_MIN_IPHONEOS
:
4134 if(l
.cmdsize
< sizeof(struct version_min_command
)){
4135 Mach_O_error(ofile
, "malformed object (LC_VERSION_MIN_"
4136 "IPHONEOS cmdsize too small) in command %u",i
);
4140 Mach_O_error(ofile
, "malformed object (more than one "
4141 "LC_VERSION_MIN_IPHONEOS or LC_VERSION_MIN_MACOSX "
4145 vers
= (struct version_min_command
*)lc
;
4147 swap_version_min_command(vers
, host_byte_sex
);
4148 if(vers
->cmdsize
< sizeof(struct version_min_command
)){
4149 Mach_O_error(ofile
, "malformed object (LC_VERSION_MIN_"
4150 "IPHONEOS command %u has too small cmdsize field)", i
);
4155 case LC_ENCRYPTION_INFO
:
4156 if(l
.cmdsize
< sizeof(struct encryption_info_command
)){
4157 Mach_O_error(ofile
, "malformed object (LC_ENCRYPTION_INFO "
4158 "cmdsize too small) in command %u", i
);
4161 encrypt_info
= (struct encryption_info_command
*)lc
;
4163 swap_encryption_command(encrypt_info
, host_byte_sex
);
4164 if(encrypt_info
->cmdsize
!=
4165 sizeof(struct encryption_info_command
)){
4166 Mach_O_error(ofile
, "malformed object (LC_ENCRYPTION_INFO"
4167 "command %u has incorrect cmdsize)", i
);
4170 if(encrypt_info
->cryptoff
> size
){
4171 Mach_O_error(ofile
, "truncated or malformed object (cryptoff "
4172 "field of LC_ENCRYPTION_INFO command %u extends "
4173 "past the end of the file)", i
);
4176 big_size
= encrypt_info
->cryptoff
;
4177 big_size
+= encrypt_info
->cryptsize
;
4178 if(big_size
> size
){
4179 Mach_O_error(ofile
, "truncated or malformed object "
4180 "(cryptoff field plus cryptsize field of "
4181 "LC_ENCRYPTION_INFO command %u extends past "
4182 "the end of the file)", i
);
4187 case LC_ENCRYPTION_INFO_64
:
4188 if(l
.cmdsize
< sizeof(struct encryption_info_command_64
)){
4189 Mach_O_error(ofile
, "malformed object (LC_ENCRYPTION_INFO"
4190 "_64 cmdsize too small) in command %u", i
);
4193 encrypt_info64
= (struct encryption_info_command_64
*)lc
;
4195 swap_encryption_command_64(encrypt_info64
, host_byte_sex
);
4196 if(encrypt_info64
->cmdsize
!=
4197 sizeof(struct encryption_info_command_64
)){
4198 Mach_O_error(ofile
, "malformed object (LC_ENCRYPTION_INFO"
4199 "_64 command %u has incorrect cmdsize)", i
);
4202 if(encrypt_info64
->cryptoff
> size
){
4203 Mach_O_error(ofile
, "truncated or malformed object (cryptoff "
4204 "field of LC_ENCRYPTION_INFO_64 command %u extends"
4205 " past the end of the file)", i
);
4208 big_size
= encrypt_info64
->cryptoff
;
4209 big_size
+= encrypt_info64
->cryptsize
;
4210 if(big_size
> size
){
4211 Mach_O_error(ofile
, "truncated or malformed object "
4212 "(cryptoff field plus cryptsize field of "
4213 "LC_ENCRYPTION_INFO_64 command %u extends past"
4214 " the end of the file)", i
);
4220 case LC_DYLD_INFO_ONLY
:
4221 if(l
.cmdsize
< sizeof(struct dyld_info_command
)){
4222 Mach_O_error(ofile
, "malformed object (%s cmdsize "
4223 "too small) in command %u", l
.cmd
==
4224 LC_DYLD_INFO
? "LC_DYLD_INFO" :
4225 "LC_DYLD_INFO_ONLY", i
);
4228 dyld_info
= (struct dyld_info_command
*)lc
;
4230 swap_dyld_info_command(dyld_info
, host_byte_sex
);
4231 if(dyld_info
->cmdsize
!=
4232 sizeof(struct dyld_info_command
)){
4233 Mach_O_error(ofile
, "malformed object (LC_DYLD_INFO"
4234 "command %u has incorrect cmdsize)", i
);
4237 if(dyld_info
->rebase_off
!= 0 && dyld_info
->rebase_off
> size
){
4238 Mach_O_error(ofile
, "truncated or malformed object "
4239 "(rebase_off field of LC_DYLD_INFO command %u "
4240 "extends past the end of the file)", i
);
4243 if(dyld_info
->rebase_off
!= 0){
4244 big_size
= dyld_info
->rebase_off
;
4245 big_size
+= dyld_info
->rebase_size
;
4246 if(big_size
> size
){
4247 Mach_O_error(ofile
, "truncated or malformed object "
4248 "(rebase_off plus rebase_size of LC_DYLD_INFO "
4249 "command %u extends past the end of the file)", i
);
4253 if(check_overlaping_element(ofile
, &elements
,
4254 dyld_info
->rebase_off
, dyld_info
->rebase_size
,
4255 "dyld rebase info") == CHECK_BAD
)
4257 if(dyld_info
->bind_off
!= 0 && dyld_info
->bind_off
> size
){
4258 Mach_O_error(ofile
, "truncated or malformed object "
4259 "(bind_off field of LC_DYLD_INFO command %u "
4260 "extends past the end of the file)", i
);
4263 if(dyld_info
->bind_off
!= 0){
4264 big_size
= dyld_info
->bind_off
;
4265 big_size
+= dyld_info
->bind_size
;
4266 if(big_size
> size
){
4267 Mach_O_error(ofile
, "truncated or malformed object "
4268 "(bind_off plus bind_size of LC_DYLD_INFO command "
4269 "%u extends past the end of the file)", i
);
4273 if(check_overlaping_element(ofile
, &elements
,
4274 dyld_info
->bind_off
, dyld_info
->bind_size
,
4275 "dyld bind info") == CHECK_BAD
)
4277 if(dyld_info
->weak_bind_off
!= 0 &&
4278 dyld_info
->weak_bind_off
> size
){
4279 Mach_O_error(ofile
, "truncated or malformed object "
4280 "(weak_bind_off field of LC_DYLD_INFO command %u "
4281 "extends past the end of the file)", i
);
4284 if(dyld_info
->weak_bind_off
!= 0){
4285 big_size
= dyld_info
->weak_bind_off
;
4286 big_size
+= dyld_info
->weak_bind_size
;
4287 if(big_size
> size
){
4288 Mach_O_error(ofile
, "truncated or malformed object "
4289 "(weak_bind_off plus weak_bind_size of LC_DYLD_INFO"
4290 " command %u extends past the end of the file)", i
);
4294 if(check_overlaping_element(ofile
, &elements
,
4295 dyld_info
->weak_bind_off
, dyld_info
->weak_bind_size
,
4296 "dyld bind info") == CHECK_BAD
)
4298 if(dyld_info
->lazy_bind_off
!= 0 &&
4299 dyld_info
->lazy_bind_off
> size
){
4300 Mach_O_error(ofile
, "truncated or malformed object "
4301 "(lazy_bind_off field of LC_DYLD_INFO command %u "
4302 "extends past the end of the file)", i
);
4305 if(dyld_info
->lazy_bind_off
!= 0){
4306 big_size
= dyld_info
->lazy_bind_off
;
4307 big_size
+= dyld_info
->lazy_bind_size
;
4308 if(big_size
> size
){
4309 Mach_O_error(ofile
, "truncated or malformed object "
4310 "(lazy_bind_off plus lazy_bind_size of LC_DYLD_INFO"
4311 " command %u extends past the end of the file)", i
);
4315 if(check_overlaping_element(ofile
, &elements
,
4316 dyld_info
->lazy_bind_off
, dyld_info
->lazy_bind_size
,
4317 "dyld lazy bind info") == CHECK_BAD
)
4319 if(dyld_info
->export_off
!= 0 && dyld_info
->export_off
> size
){
4320 Mach_O_error(ofile
, "truncated or malformed object "
4321 "(export_off field of LC_DYLD_INFO command %u "
4322 "extends past the end of the file)", i
);
4325 if(dyld_info
->export_off
!= 0){
4326 big_size
= dyld_info
->export_off
;
4327 big_size
+= dyld_info
->export_size
;
4328 if(big_size
> size
){
4329 Mach_O_error(ofile
, "truncated or malformed object "
4330 "(export_off plus export_size of LC_DYLD_INFO "
4331 "command %u extends past the end of the file)", i
);
4335 if(check_overlaping_element(ofile
, &elements
,
4336 dyld_info
->export_off
, dyld_info
->export_size
,
4337 "dyld export info") == CHECK_BAD
)
4343 case LC_PREBIND_CKSUM
:
4344 if(l
.cmdsize
< sizeof(struct prebind_cksum_command
)){
4345 Mach_O_error(ofile
, "malformed object (LC_PREBIND_CKSUM "
4346 "cmdsize too small) in command %u", i
);
4350 Mach_O_error(ofile
, "malformed object (more than one "
4351 "LC_PREBIND_CKSUM command)");
4354 cs
= (struct prebind_cksum_command
*)lc
;
4356 swap_prebind_cksum_command(cs
, host_byte_sex
);
4357 if(cs
->cmdsize
!= sizeof(struct prebind_cksum_command
)){
4358 Mach_O_error(ofile
, "malformed object (LC_PREBIND_CKSUM "
4359 "command %u has incorrect cmdsize)", i
);
4365 if(l
.cmdsize
< sizeof(struct uuid_command
)){
4366 Mach_O_error(ofile
, "malformed object (LC_UUID cmdsize "
4367 "too small) in command %u", i
);
4371 Mach_O_error(ofile
, "malformed object (more than one "
4372 "LC_UUID command)");
4375 uuid
= (struct uuid_command
*)lc
;
4377 swap_uuid_command(uuid
, host_byte_sex
);
4378 if(uuid
->cmdsize
!= sizeof(struct uuid_command
)){
4379 Mach_O_error(ofile
, "malformed object (LC_UUID command %u " "has incorrect cmdsize)", i
);
4385 if(l
.cmdsize
< sizeof(struct symseg_command
)){
4386 Mach_O_error(ofile
, "malformed object (LC_SYMSEG cmdsize "
4387 "too small) in command %u", i
);
4390 ss
= (struct symseg_command
*)lc
;
4392 swap_symseg_command(ss
, host_byte_sex
);
4393 if(ss
->cmdsize
!= sizeof(struct symseg_command
)){
4394 Mach_O_error(ofile
, "malformed object (LC_SYMSEG command "
4395 "%u has incorrect cmdsize)", i
);
4398 if(ss
->offset
> size
){
4399 Mach_O_error(ofile
, "truncated or malformed object (offset "
4400 "field of LC_SYMSEG command %u extends past the end "
4404 big_size
= ss
->offset
;
4405 big_size
+= ss
->size
;
4406 if(big_size
> size
){
4407 Mach_O_error(ofile
, "truncated or malformed object (offset "
4408 "field plus size field of LC_SYMTAB command %u "
4409 "extends past the end of the file)", i
);
4412 if(check_overlaping_element(ofile
, &elements
, ss
->offset
,
4413 ss
->size
, "symseg info") == CHECK_BAD
)
4419 if(l
.cmdsize
< sizeof(struct fvmlib_command
)){
4420 Mach_O_error(ofile
, "malformed object (%s cmdsize "
4421 "too small) in command %u", l
.cmd
==
4422 LC_IDFVMLIB
? "LC_IDFVMLIB" :
4423 "LC_LOADFVMLIB", i
);
4426 fl
= (struct fvmlib_command
*)lc
;
4428 swap_fvmlib_command(fl
, host_byte_sex
);
4429 if(fl
->cmdsize
< sizeof(struct fvmlib_command
)){
4430 Mach_O_error(ofile
, "malformed object (%s command %u has "
4431 "too small cmdsize field)", fl
->cmd
== LC_IDFVMLIB
?
4432 "LC_IDFVMLIB" : "LC_LOADFVMLIB", i
);
4435 if(fl
->fvmlib
.name
.offset
>= fl
->cmdsize
){
4436 Mach_O_error(ofile
, "truncated or malformed object (name."
4437 "offset field of %s command %u extends past the end "
4438 "of the file)", fl
->cmd
== LC_IDFVMLIB
? "LC_IDFVMLIB"
4439 : "LC_LOADFVMLIB", i
);
4445 cmd_name
= "LC_ID_DYLIB";
4446 goto check_dylib_command
;
4448 cmd_name
= "LC_LOAD_DYLIB";
4449 goto check_dylib_command
;
4450 case LC_LOAD_WEAK_DYLIB
:
4451 cmd_name
= "LC_LOAD_WEAK_DYLIB";
4452 goto check_dylib_command
;
4453 case LC_REEXPORT_DYLIB
:
4454 cmd_name
= "LC_REEXPORT_DYLIB";
4455 goto check_dylib_command
;
4456 case LC_LOAD_UPWARD_DYLIB
:
4457 cmd_name
= "LC_LOAD_UPWARD_DYLIB";
4458 goto check_dylib_command
;
4459 case LC_LAZY_LOAD_DYLIB
:
4460 cmd_name
= "LC_LAZY_LOAD_DYLIB";
4461 goto check_dylib_command
;
4462 check_dylib_command
:
4463 if(l
.cmdsize
< sizeof(struct dylib_command
)){
4464 Mach_O_error(ofile
, "malformed object (%s cmdsize too "
4465 "small) in command %u", cmd_name
, i
);
4468 dl
= (struct dylib_command
*)lc
;
4470 swap_dylib_command(dl
, host_byte_sex
);
4471 if(dl
->cmdsize
< sizeof(struct dylib_command
)){
4472 Mach_O_error(ofile
, "malformed object (%s command %u has "
4473 "too small cmdsize field)", cmd_name
, i
);
4476 if(dl
->dylib
.name
.offset
>= dl
->cmdsize
){
4477 Mach_O_error(ofile
, "truncated or malformed object (name."
4478 "offset field of %s command %u extends past the end "
4479 "of the file)", cmd_name
, i
);
4484 case LC_SUB_FRAMEWORK
:
4485 if(l
.cmdsize
< sizeof(struct sub_framework_command
)){
4486 Mach_O_error(ofile
, "malformed object (LC_SUB_FRAMEWORK "
4487 "cmdsize too small) in command %u", i
);
4490 sub
= (struct sub_framework_command
*)lc
;
4492 swap_sub_framework_command(sub
, host_byte_sex
);
4493 if(sub
->cmdsize
< sizeof(struct sub_framework_command
)){
4494 Mach_O_error(ofile
, "malformed object (LC_SUB_FRAMEWORK "
4495 "command %u has too small cmdsize field)", i
);
4498 if(sub
->umbrella
.offset
>= sub
->cmdsize
){
4499 Mach_O_error(ofile
, "truncated or malformed object "
4500 "(umbrella.offset field of LC_SUB_FRAMEWORK command "
4501 "%u extends past the end of the file)", i
);
4506 case LC_SUB_UMBRELLA
:
4507 if(l
.cmdsize
< sizeof(struct sub_umbrella_command
)){
4508 Mach_O_error(ofile
, "malformed object (LC_SUB_UMBRELLA "
4509 "cmdsize too small) in command %u", i
);
4512 usub
= (struct sub_umbrella_command
*)lc
;
4514 swap_sub_umbrella_command(usub
, host_byte_sex
);
4515 if(usub
->cmdsize
< sizeof(struct sub_umbrella_command
)){
4516 Mach_O_error(ofile
, "malformed object (LC_SUB_UMBRELLA "
4517 "command %u has too small cmdsize field)", i
);
4520 if(usub
->sub_umbrella
.offset
>= usub
->cmdsize
){
4521 Mach_O_error(ofile
, "truncated or malformed object "
4522 "(sub_umbrella.offset field of LC_SUB_UMBRELLA command "
4523 "%u extends past the end of the file)", i
);
4528 case LC_SUB_LIBRARY
:
4529 if(l
.cmdsize
< sizeof(struct sub_library_command
)){
4530 Mach_O_error(ofile
, "malformed object (LC_SUB_LIBRARY "
4531 "cmdsize too small) in command %u", i
);
4534 lsub
= (struct sub_library_command
*)lc
;
4536 swap_sub_library_command(lsub
, host_byte_sex
);
4537 if(lsub
->cmdsize
< sizeof(struct sub_library_command
)){
4538 Mach_O_error(ofile
, "malformed object (LC_SUB_LIBRARY "
4539 "command %u has too small cmdsize field)", i
);
4542 if(lsub
->sub_library
.offset
>= lsub
->cmdsize
){
4543 Mach_O_error(ofile
, "truncated or malformed object "
4544 "(sub_library.offset field of LC_SUB_LIBRARY command "
4545 "%u extends past the end of the file)", i
);
4551 if(l
.cmdsize
< sizeof(struct sub_client_command
)){
4552 Mach_O_error(ofile
, "malformed object (LC_SUB_CLIENT "
4553 "cmdsize too small) in command %u", i
);
4556 csub
= (struct sub_client_command
*)lc
;
4558 swap_sub_client_command(csub
, host_byte_sex
);
4559 if(csub
->cmdsize
< sizeof(struct sub_client_command
)){
4560 Mach_O_error(ofile
, "malformed object (LC_SUB_CLIENT "
4561 "command %u has too small cmdsize field)", i
);
4564 if(csub
->client
.offset
>= csub
->cmdsize
){
4565 Mach_O_error(ofile
, "truncated or malformed object "
4566 "(cleient.offset field of LC_SUB_CLIENT command "
4567 "%u extends past the end of the file)", i
);
4572 case LC_PREBOUND_DYLIB
:
4573 if(l
.cmdsize
< sizeof(struct prebound_dylib_command
)){
4574 Mach_O_error(ofile
, "malformed object (LC_PREBOUND_DYLIB "
4575 "cmdsize too small) in command %u", i
);
4578 pbdylib
= (struct prebound_dylib_command
*)lc
;
4580 swap_prebound_dylib_command(pbdylib
, host_byte_sex
);
4581 if(pbdylib
->cmdsize
< sizeof(struct dylib_command
)){
4582 Mach_O_error(ofile
, "malformed object (LC_PREBIND_DYLIB "
4583 "command %u has too small cmdsize field)", i
);
4586 if(pbdylib
->name
.offset
>= pbdylib
->cmdsize
){
4587 Mach_O_error(ofile
, "truncated or malformed object (name."
4588 "offset field of LC_PREBIND_DYLIB command %u extends "
4589 "past the end of the file)", i
);
4592 if(pbdylib
->linked_modules
.offset
>= pbdylib
->cmdsize
){
4593 Mach_O_error(ofile
, "truncated or malformed object (linked_"
4594 "modules.offset field of LC_PREBIND_DYLIB command %u "
4595 "extends past the end of the file)", i
);
4600 case LC_ID_DYLINKER
:
4601 cmd_name
= "LC_ID_DYLINKER";
4602 goto check_dylinker_command
;
4603 case LC_LOAD_DYLINKER
:
4604 cmd_name
= "LC_LOAD_DYLINKER";
4605 goto check_dylinker_command
;
4606 case LC_DYLD_ENVIRONMENT
:
4607 cmd_name
= "LC_DYLD_ENVIRONMENT";
4608 goto check_dylinker_command
;
4609 check_dylinker_command
:
4610 if(l
.cmdsize
< sizeof(struct dylinker_command
)){
4611 Mach_O_error(ofile
, "malformed object (%s cmdsize "
4612 "too small) in command %u", cmd_name
, i
);
4615 dyld
= (struct dylinker_command
*)lc
;
4617 swap_dylinker_command(dyld
, host_byte_sex
);
4618 if(dyld
->cmdsize
< sizeof(struct dylinker_command
)){
4619 Mach_O_error(ofile
, "malformed object (%s command %u has "
4620 "too small cmdsize field)", cmd_name
, i
);
4623 if(dyld
->name
.offset
>= dyld
->cmdsize
){
4624 Mach_O_error(ofile
, "truncated or malformed object (name."
4625 "offset field of %s command %u extends past the end "
4626 "of the file)", cmd_name
, i
);
4633 if(l
.cmdsize
< sizeof(struct thread_command
)){
4634 Mach_O_error(ofile
, "malformed object (%s cmdsize "
4635 "too small) in command %u", l
.cmd
==
4636 LC_UNIXTHREAD
? "LC_UNIXTHREAD" :
4640 ut
= (struct thread_command
*)lc
;
4642 swap_thread_command(ut
, host_byte_sex
);
4643 state
= (char *)ut
+ sizeof(struct thread_command
);
4645 if(cputype
== CPU_TYPE_MC680x0
){
4646 struct m68k_thread_state_regs
*cpu
;
4647 struct m68k_thread_state_68882
*fpu
;
4648 struct m68k_thread_state_user_reg
*user_reg
;
4651 p
= (char *)ut
+ ut
->cmdsize
;
4653 if(state
+ sizeof(uint32_t) >
4654 (char *)ut
+ ut
->cmdsize
){
4655 Mach_O_error(ofile
, "malformed object (flavor in "
4656 "%s command %u extends past end of command)",
4657 ut
->cmd
== LC_UNIXTHREAD
? "LC_UNIXTHREAD" :
4661 flavor
= *((uint32_t *)state
);
4663 flavor
= SWAP_INT(flavor
);
4664 *((uint32_t *)state
) = flavor
;
4666 state
+= sizeof(uint32_t);
4667 if(state
+ sizeof(uint32_t) >
4668 (char *)ut
+ ut
->cmdsize
){
4669 Mach_O_error(ofile
, "malformed object (count in "
4670 "%s command %u extends past end of command)",
4671 ut
->cmd
== LC_UNIXTHREAD
? "LC_UNIXTHREAD" :
4675 count
= *((uint32_t *)state
);
4677 count
= SWAP_INT(count
);
4678 *((uint32_t *)state
) = count
;
4680 state
+= sizeof(uint32_t);
4682 case M68K_THREAD_STATE_REGS
:
4683 if(count
!= M68K_THREAD_STATE_REGS_COUNT
){
4684 Mach_O_error(ofile
, "malformed object (count "
4685 "not M68K_THREAD_STATE_REGS_COUNT for "
4686 "flavor number %u which is a M68K_THREAD_"
4687 "STATE_REGS flavor in %s command %u)",
4688 nflavor
, ut
->cmd
== LC_UNIXTHREAD
?
4689 "LC_UNIXTHREAD" : "LC_THREAD", i
);
4692 cpu
= (struct m68k_thread_state_regs
*)state
;
4693 if(state
+ sizeof(struct m68k_thread_state_regs
) >
4694 (char *)ut
+ ut
->cmdsize
){
4695 Mach_O_error(ofile
, "malformed object ("
4696 "M68K_THREAD_STATE_REGS in %s command %u "
4697 "extends past end of command)", ut
->cmd
==
4698 LC_UNIXTHREAD
? "LC_UNIXTHREAD" :
4703 swap_m68k_thread_state_regs(cpu
, host_byte_sex
);
4704 state
+= sizeof(struct m68k_thread_state_regs
);
4706 case M68K_THREAD_STATE_68882
:
4707 if(count
!= M68K_THREAD_STATE_68882_COUNT
){
4708 Mach_O_error(ofile
, "malformed object (count "
4709 "not M68K_THREAD_STATE_68882_COUNT for "
4710 "flavor number %u which is a M68K_THREAD_"
4711 "STATE_68882 flavor in %s command %u)",
4712 nflavor
, ut
->cmd
== LC_UNIXTHREAD
?
4713 "LC_UNIXTHREAD" : "LC_THREAD", i
);
4716 fpu
= (struct m68k_thread_state_68882
*)state
;
4717 if(state
+ sizeof(struct m68k_thread_state_68882
) >
4718 (char *)ut
+ ut
->cmdsize
){
4719 Mach_O_error(ofile
, "malformed object ("
4720 "M68K_THREAD_STATE_68882 in %s command %u "
4721 "extends past end of command)", ut
->cmd
==
4722 LC_UNIXTHREAD
? "LC_UNIXTHREAD" :
4727 swap_m68k_thread_state_68882(fpu
,host_byte_sex
);
4728 state
+= sizeof(struct m68k_thread_state_68882
);
4730 case M68K_THREAD_STATE_USER_REG
:
4731 if(count
!= M68K_THREAD_STATE_USER_REG_COUNT
){
4732 Mach_O_error(ofile
, "malformed object (count "
4733 "not M68K_THREAD_STATE_USER_REG_COUNT for "
4734 "flavor number %u which is a M68K_THREAD_"
4735 "STATE_USER_REG flavor in %s command %u)",
4736 nflavor
, ut
->cmd
== LC_UNIXTHREAD
?
4737 "LC_UNIXTHREAD" : "LC_THREAD", i
);
4741 (struct m68k_thread_state_user_reg
*)state
;
4742 if(state
+sizeof(struct m68k_thread_state_user_reg
) >
4743 (char *)ut
+ ut
->cmdsize
){
4744 Mach_O_error(ofile
, "malformed object ("
4745 "M68K_THREAD_STATE_USER_REG in %s command "
4746 "%u extends past end of command)", ut
->cmd
==
4747 LC_UNIXTHREAD
? "LC_UNIXTHREAD" :
4752 swap_m68k_thread_state_user_reg(user_reg
,
4754 state
+= sizeof(struct m68k_thread_state_user_reg
);
4758 Mach_O_error(ofile
, "malformed object (unknown "
4759 "flavor for flavor number %u in %s command"
4760 " %u can't byte swap it)", nflavor
,
4761 ut
->cmd
== LC_UNIXTHREAD
? "LC_UNIXTHREAD" :
4765 state
+= count
* sizeof(uint32_t);
4772 if(cputype
== CPU_TYPE_POWERPC
||
4773 cputype
== CPU_TYPE_VEO
){
4774 ppc_thread_state_t
*nrw_cpu
;
4777 p
= (char *)ut
+ ut
->cmdsize
;
4779 if(state
+ sizeof(uint32_t) >
4780 (char *)ut
+ ut
->cmdsize
){
4781 Mach_O_error(ofile
, "malformed object (flavor in "
4782 "%s command %u extends past end of command)",
4783 ut
->cmd
== LC_UNIXTHREAD
? "LC_UNIXTHREAD" :
4787 flavor
= *((uint32_t *)state
);
4789 flavor
= SWAP_INT(flavor
);
4790 *((uint32_t *)state
) = flavor
;
4792 state
+= sizeof(uint32_t);
4793 if(state
+ sizeof(uint32_t) >
4794 (char *)ut
+ ut
->cmdsize
){
4795 Mach_O_error(ofile
, "malformed object (count in "
4796 "%s command %u extends past end of command)",
4797 ut
->cmd
== LC_UNIXTHREAD
? "LC_UNIXTHREAD" :
4801 count
= *((uint32_t *)state
);
4803 count
= SWAP_INT(count
);
4804 *((uint32_t *)state
) = count
;
4806 state
+= sizeof(uint32_t);
4808 case PPC_THREAD_STATE
:
4809 if(count
!= PPC_THREAD_STATE_COUNT
){
4810 Mach_O_error(ofile
, "malformed object (count "
4811 "not PPC_THREAD_STATE_COUNT for "
4812 "flavor number %u which is a PPC_THREAD_"
4813 "STATE flavor in %s command %u)",
4814 nflavor
, ut
->cmd
== LC_UNIXTHREAD
?
4815 "LC_UNIXTHREAD" : "LC_THREAD", i
);
4818 nrw_cpu
= (ppc_thread_state_t
*)state
;
4819 if(state
+ sizeof(ppc_thread_state_t
) >
4820 (char *)ut
+ ut
->cmdsize
){
4821 Mach_O_error(ofile
, "malformed object ("
4822 "PPC_THREAD_STATE in %s command %u extends"
4823 " past end of command)", ut
->cmd
==
4824 LC_UNIXTHREAD
? "LC_UNIXTHREAD" :
4829 swap_ppc_thread_state_t(nrw_cpu
,
4831 state
+= sizeof(ppc_thread_state_t
);
4835 Mach_O_error(ofile
, "malformed object (unknown "
4836 "flavor for flavor number %u in %s command"
4837 " %u can't byte swap it)", nflavor
,
4838 ut
->cmd
== LC_UNIXTHREAD
? "LC_UNIXTHREAD" :
4842 state
+= count
* sizeof(uint32_t);
4849 #ifdef PPC_THREAD_STATE64_COUNT
4850 if(cputype
== CPU_TYPE_POWERPC64
){
4851 ppc_thread_state64_t
*cpu
;
4854 p
= (char *)ut
+ ut
->cmdsize
;
4856 if(state
+ sizeof(uint32_t) >
4857 (char *)ut
+ ut
->cmdsize
){
4858 Mach_O_error(ofile
, "malformed object (flavor in "
4859 "%s command %u extends past end of command)",
4860 ut
->cmd
== LC_UNIXTHREAD
? "LC_UNIXTHREAD" :
4864 flavor
= *((uint32_t *)state
);
4866 flavor
= SWAP_INT(flavor
);
4867 *((uint32_t *)state
) = flavor
;
4869 state
+= sizeof(uint32_t);
4870 if(state
+ sizeof(uint32_t) >
4871 (char *)ut
+ ut
->cmdsize
){
4872 Mach_O_error(ofile
, "malformed object (count in "
4873 "%s command %u extends past end of command)",
4874 ut
->cmd
== LC_UNIXTHREAD
? "LC_UNIXTHREAD" :
4878 count
= *((uint32_t *)state
);
4880 count
= SWAP_INT(count
);
4881 *((uint32_t *)state
) = count
;
4883 state
+= sizeof(uint32_t);
4885 case PPC_THREAD_STATE64
:
4886 if(count
!= PPC_THREAD_STATE64_COUNT
){
4887 Mach_O_error(ofile
, "malformed object (count "
4888 "not PPC_THREAD_STATE64_COUNT for "
4889 "flavor number %u which is a PPC_THREAD_"
4890 "STATE64 flavor in %s command %u)",
4891 nflavor
, ut
->cmd
== LC_UNIXTHREAD
?
4892 "LC_UNIXTHREAD" : "LC_THREAD", i
);
4895 cpu
= (ppc_thread_state64_t
*)state
;
4896 if(state
+ sizeof(ppc_thread_state64_t
) >
4897 (char *)ut
+ ut
->cmdsize
){
4898 Mach_O_error(ofile
, "malformed object ("
4899 "PPC_THREAD_STATE64 in %s command %u "
4900 "extends past end of command)", ut
->cmd
==
4901 LC_UNIXTHREAD
? "LC_UNIXTHREAD" :
4906 swap_ppc_thread_state64_t(cpu
, host_byte_sex
);
4907 state
+= sizeof(ppc_thread_state64_t
);
4911 Mach_O_error(ofile
, "malformed object (unknown "
4912 "flavor for flavor number %u in %s command"
4913 " %u can't byte swap it)", nflavor
,
4914 ut
->cmd
== LC_UNIXTHREAD
? "LC_UNIXTHREAD" :
4918 state
+= count
* sizeof(uint32_t);
4925 #endif /* PPC_THREAD_STATE64_COUNT */
4926 if(cputype
== CPU_TYPE_MC88000
){
4927 m88k_thread_state_grf_t
*cpu
;
4928 m88k_thread_state_xrf_t
*fpu
;
4929 m88k_thread_state_user_t
*user
;
4930 m88110_thread_state_impl_t
*spu
;
4933 p
= (char *)ut
+ ut
->cmdsize
;
4935 if(state
+ sizeof(uint32_t) >
4936 (char *)ut
+ ut
->cmdsize
){
4937 Mach_O_error(ofile
, "malformed object (flavor in "
4938 "%s command %u extends past end of command)",
4939 ut
->cmd
== LC_UNIXTHREAD
? "LC_UNIXTHREAD" :
4943 flavor
= *((uint32_t *)state
);
4945 flavor
= SWAP_INT(flavor
);
4946 *((uint32_t *)state
) = flavor
;
4948 state
+= sizeof(uint32_t);
4949 if(state
+ sizeof(uint32_t) >
4950 (char *)ut
+ ut
->cmdsize
){
4951 Mach_O_error(ofile
, "malformed object (count in "
4952 "%s command %u extends past end of command)",
4953 ut
->cmd
== LC_UNIXTHREAD
? "LC_UNIXTHREAD" :
4957 count
= *((uint32_t *)state
);
4959 count
= SWAP_INT(count
);
4960 *((uint32_t *)state
) = count
;
4962 state
+= sizeof(uint32_t);
4964 case M88K_THREAD_STATE_GRF
:
4965 if(count
!= M88K_THREAD_STATE_GRF_COUNT
){
4966 Mach_O_error(ofile
, "malformed object (count "
4967 "not M88K_THREAD_STATE_GRF_COUNT for "
4968 "flavor number %u which is a M88K_THREAD_"
4969 "STATE_GRF flavor in %s command %u)",
4970 nflavor
, ut
->cmd
== LC_UNIXTHREAD
?
4971 "LC_UNIXTHREAD" : "LC_THREAD", i
);
4974 cpu
= (m88k_thread_state_grf_t
*)state
;
4975 if(state
+ sizeof(m88k_thread_state_grf_t
) >
4976 (char *)ut
+ ut
->cmdsize
){
4977 Mach_O_error(ofile
, "malformed object ("
4978 "M88K_THREAD_STATE_GRF in %s command %u "
4979 "extends past end of command)", ut
->cmd
==
4980 LC_UNIXTHREAD
? "LC_UNIXTHREAD" :
4985 swap_m88k_thread_state_grf_t(cpu
,
4987 state
+= sizeof(m88k_thread_state_grf_t
);
4989 case M88K_THREAD_STATE_XRF
:
4990 if(count
!= M88K_THREAD_STATE_XRF_COUNT
){
4991 Mach_O_error(ofile
, "malformed object (count "
4992 "not M88K_THREAD_STATE_XRF_COUNT for "
4993 "flavor number %u which is a M88K_THREAD_"
4994 "STATE_XRF flavor in %s command %u)",
4995 nflavor
, ut
->cmd
== LC_UNIXTHREAD
?
4996 "LC_UNIXTHREAD" : "LC_THREAD", i
);
4999 fpu
= (m88k_thread_state_xrf_t
*)state
;
5000 if(state
+ sizeof(m88k_thread_state_xrf_t
) >
5001 (char *)ut
+ ut
->cmdsize
){
5002 Mach_O_error(ofile
, "malformed object ("
5003 "M88K_THREAD_STATE_XRF in %s command %u "
5004 "extends past end of command)", ut
->cmd
==
5005 LC_UNIXTHREAD
? "LC_UNIXTHREAD" :
5010 swap_m88k_thread_state_xrf_t(fpu
,
5012 state
+= sizeof(m88k_thread_state_xrf_t
);
5014 case M88K_THREAD_STATE_USER
:
5015 if(count
!= M88K_THREAD_STATE_USER_COUNT
){
5016 Mach_O_error(ofile
, "malformed object (count "
5017 "not M88K_THREAD_STATE_USER_COUNT for "
5018 "flavor number %u which is a M88K_THREAD_"
5019 "STATE_USER flavor in %s command %u)",
5020 nflavor
, ut
->cmd
== LC_UNIXTHREAD
?
5021 "LC_UNIXTHREAD" : "LC_THREAD", i
);
5024 user
= (m88k_thread_state_user_t
*)state
;
5025 if(state
+ sizeof(m88k_thread_state_user_t
) >
5026 (char *)ut
+ ut
->cmdsize
){
5027 Mach_O_error(ofile
, "malformed object ("
5028 "M88K_THREAD_STATE_USER in %s command %u "
5029 "extends past end of command)", ut
->cmd
==
5030 LC_UNIXTHREAD
? "LC_UNIXTHREAD" :
5035 swap_m88k_thread_state_user_t(user
,
5037 state
+= sizeof(m88k_thread_state_user_t
);
5039 case M88110_THREAD_STATE_IMPL
:
5040 if(count
!= M88110_THREAD_STATE_IMPL_COUNT
){
5041 Mach_O_error(ofile
, "malformed object (count "
5042 "not M88110_THREAD_STATE_IMPL_COUNT for "
5043 "flavor number %u which is a M88110_THREAD"
5044 "_STATE_IMPL flavor in %s command %u)",
5045 nflavor
, ut
->cmd
== LC_UNIXTHREAD
?
5046 "LC_UNIXTHREAD" : "LC_THREAD", i
);
5049 spu
= (m88110_thread_state_impl_t
*)state
;
5050 if(state
+ sizeof(m88110_thread_state_impl_t
) >
5051 (char *)ut
+ ut
->cmdsize
){
5052 Mach_O_error(ofile
, "malformed object ("
5053 "M88110_THREAD_STATE_IMPL in %s command %u "
5054 "extends past end of command)", ut
->cmd
==
5055 LC_UNIXTHREAD
? "LC_UNIXTHREAD" :
5060 swap_m88110_thread_state_impl_t(spu
,
5062 state
+= sizeof(m88110_thread_state_impl_t
);
5066 Mach_O_error(ofile
, "malformed object (unknown "
5067 "flavor for flavor number %u in %s command"
5068 " %u can't byte swap it)", nflavor
,
5069 ut
->cmd
== LC_UNIXTHREAD
? "LC_UNIXTHREAD" :
5073 state
+= count
* sizeof(uint32_t);
5080 if(cputype
== CPU_TYPE_I860
){
5082 struct i860_thread_state_regs
*cpu
;
5086 p
= (char *)ut
+ ut
->cmdsize
;
5088 if(state
+ sizeof(uint32_t) >
5089 (char *)ut
+ ut
->cmdsize
){
5090 Mach_O_error(ofile
, "malformed object (flavor in "
5091 "%s command %u extends past end of command)",
5092 ut
->cmd
== LC_UNIXTHREAD
? "LC_UNIXTHREAD" :
5096 flavor
= *((uint32_t *)state
);
5098 flavor
= SWAP_INT(flavor
);
5099 *((uint32_t *)state
) = flavor
;
5101 state
+= sizeof(uint32_t);
5102 if(state
+ sizeof(uint32_t) >
5103 (char *)ut
+ ut
->cmdsize
){
5104 Mach_O_error(ofile
, "malformed object (count in "
5105 "%s command %u extends past end of command)",
5106 ut
->cmd
== LC_UNIXTHREAD
? "LC_UNIXTHREAD" :
5110 count
= *((uint32_t *)state
);
5112 count
= SWAP_INT(count
);
5113 *((uint32_t *)state
) = count
;
5115 state
+= sizeof(uint32_t);
5117 case I860_THREAD_STATE_REGS
:
5119 if(count
!= I860_THREAD_STATE_REGS_COUNT
){
5120 Mach_O_error(ofile
, "malformed object (count "
5121 "not I860_THREAD_STATE_REGS_COUNT for "
5122 "flavor number %u which is a I860_THREAD_"
5123 "STATE_REGS flavor in %s command %u)",
5124 nflavor
, ut
->cmd
== LC_UNIXTHREAD
?
5125 "LC_UNIXTHREAD" : "LC_THREAD", i
);
5128 cpu
= (struct i860_thread_state_regs
*)state
;
5129 if(state
+ sizeof(struct i860_thread_state_regs
) >
5130 (char *)ut
+ ut
->cmdsize
){
5131 Mach_O_error(ofile
, "malformed object ("
5132 "I860_THREAD_STATE_REGS in %s command %u "
5133 "extends past end of command)", ut
->cmd
==
5134 LC_UNIXTHREAD
? "LC_UNIXTHREAD" :
5139 swap_i860_thread_state_regs(cpu
, host_byte_sex
);
5140 state
+= sizeof(struct i860_thread_state_regs
);
5142 state
+= count
* sizeof(int);
5147 Mach_O_error(ofile
, "malformed object (unknown "
5148 "flavor for flavor number %u in %s command"
5149 " %u can't byte swap it)", nflavor
,
5150 ut
->cmd
== LC_UNIXTHREAD
? "LC_UNIXTHREAD" :
5154 state
+= count
* sizeof(uint32_t);
5161 if(cputype
== CPU_TYPE_I386
){
5162 i386_thread_state_t
*cpu
;
5163 /* current i386 thread states */
5164 #if i386_THREAD_STATE == 1
5165 struct i386_float_state
*fpu
;
5166 i386_exception_state_t
*exc
;
5167 #endif /* i386_THREAD_STATE == 1 */
5169 /* i386 thread states on older releases */
5170 #if i386_THREAD_STATE == -1
5171 i386_thread_fpstate_t
*fpu
;
5172 i386_thread_exceptstate_t
*exc
;
5173 i386_thread_cthreadstate_t
*user
;
5174 #endif /* i386_THREAD_STATE == -1 */
5177 p
= (char *)ut
+ ut
->cmdsize
;
5179 if(state
+ sizeof(uint32_t) >
5180 (char *)ut
+ ut
->cmdsize
){
5181 Mach_O_error(ofile
, "malformed object (flavor in "
5182 "%s command %u extends past end of command)",
5183 ut
->cmd
== LC_UNIXTHREAD
? "LC_UNIXTHREAD" :
5187 flavor
= *((uint32_t *)state
);
5189 flavor
= SWAP_INT(flavor
);
5190 *((uint32_t *)state
) = flavor
;
5192 state
+= sizeof(uint32_t);
5193 if(state
+ sizeof(uint32_t) >
5194 (char *)ut
+ ut
->cmdsize
){
5195 Mach_O_error(ofile
, "malformed object (count in "
5196 "%s command %u extends past end of command)",
5197 ut
->cmd
== LC_UNIXTHREAD
? "LC_UNIXTHREAD" :
5201 count
= *((uint32_t *)state
);
5203 count
= SWAP_INT(count
);
5204 *((uint32_t *)state
) = count
;
5206 state
+= sizeof(uint32_t);
5207 switch((int)flavor
){
5208 case i386_THREAD_STATE
:
5209 #if i386_THREAD_STATE == 1
5211 #endif /* i386_THREAD_STATE == 1 */
5212 /* i386 thread states on older releases */
5213 #if i386_THREAD_STATE == -1
5215 #endif /* i386_THREAD_STATE == -1 */
5216 if(count
!= i386_THREAD_STATE_COUNT
){
5217 Mach_O_error(ofile
, "malformed object (count "
5218 "not i386_THREAD_STATE_COUNT for flavor "
5219 "number %u which is a i386_THREAD_STATE "
5220 "flavor in %s command %u)", nflavor
,
5221 ut
->cmd
== LC_UNIXTHREAD
? "LC_UNIXTHREAD" :
5225 cpu
= (i386_thread_state_t
*)state
;
5226 if(state
+ sizeof(i386_thread_state_t
) >
5227 (char *)ut
+ ut
->cmdsize
){
5228 Mach_O_error(ofile
, "malformed object ("
5229 "i386_THREAD_STATE in %s command %u "
5230 "extends past end of command)", ut
->cmd
==
5231 LC_UNIXTHREAD
? "LC_UNIXTHREAD" :
5236 swap_i386_thread_state(cpu
, host_byte_sex
);
5237 state
+= sizeof(i386_thread_state_t
);
5239 /* current i386 thread states */
5240 #if i386_THREAD_STATE == 1
5241 case i386_FLOAT_STATE
:
5242 if(count
!= i386_FLOAT_STATE_COUNT
){
5243 Mach_O_error(ofile
, "malformed object (count "
5244 "not i386_FLOAT_STATE_COUNT for flavor "
5245 "number %u which is a i386_FLOAT_STATE "
5246 "flavor in %s command %u)", nflavor
,
5247 ut
->cmd
== LC_UNIXTHREAD
? "LC_UNIXTHREAD" :
5251 fpu
= (struct i386_float_state
*)state
;
5252 if(state
+ sizeof(struct i386_float_state
) >
5253 (char *)ut
+ ut
->cmdsize
){
5254 Mach_O_error(ofile
, "malformed object ("
5255 "i386_FLOAT_STATE in %s command %u "
5256 "extends past end of command)", ut
->cmd
==
5257 LC_UNIXTHREAD
? "LC_UNIXTHREAD" :
5262 swap_i386_float_state(fpu
, host_byte_sex
);
5263 state
+= sizeof(struct i386_float_state
);
5265 case i386_EXCEPTION_STATE
:
5266 if(count
!= I386_EXCEPTION_STATE_COUNT
){
5267 Mach_O_error(ofile
, "malformed object (count "
5268 "not I386_EXCEPTION_STATE_COUNT for "
5269 "flavor number %u which is a i386_"
5270 "EXCEPTION_STATE flavor in %s command %u)",
5272 ut
->cmd
== LC_UNIXTHREAD
? "LC_UNIXTHREAD" :
5276 exc
= (i386_exception_state_t
*)state
;
5277 if(state
+ sizeof(i386_exception_state_t
) >
5278 (char *)ut
+ ut
->cmdsize
){
5279 Mach_O_error(ofile
, "malformed object ("
5280 "i386_EXCEPTION_STATE in %s command %u "
5281 "extends past end of command)", ut
->cmd
==
5282 LC_UNIXTHREAD
? "LC_UNIXTHREAD" :
5287 swap_i386_exception_state(exc
,host_byte_sex
);
5288 state
+= sizeof(i386_exception_state_t
);
5290 #endif /* i386_THREAD_STATE == 1 */
5292 /* i386 thread states on older releases */
5293 #if i386_THREAD_STATE == -1
5294 case i386_THREAD_FPSTATE
:
5295 if(count
!= i386_THREAD_FPSTATE_COUNT
){
5296 Mach_O_error(ofile
, "malformed object (count "
5297 "not i386_THREAD_FPSTATE_COUNT for flavor "
5298 "number %u which is a i386_THREAD_FPSTATE "
5299 "flavor in %s command %u)", nflavor
,
5300 ut
->cmd
== LC_UNIXTHREAD
? "LC_UNIXTHREAD" :
5304 fpu
= (i386_thread_fpstate_t
*)state
;
5305 if(state
+ sizeof(i386_thread_fpstate_t
) >
5306 (char *)ut
+ ut
->cmdsize
){
5307 Mach_O_error(ofile
, "malformed object ("
5308 "i386_THREAD_FPSTATE in %s command %u "
5309 "extends past end of command)", ut
->cmd
==
5310 LC_UNIXTHREAD
? "LC_UNIXTHREAD" :
5315 swap_i386_thread_fpstate(fpu
, host_byte_sex
);
5316 state
+= sizeof(i386_thread_fpstate_t
);
5318 case i386_THREAD_EXCEPTSTATE
:
5319 if(count
!= i386_THREAD_EXCEPTSTATE_COUNT
){
5320 Mach_O_error(ofile
, "malformed object (count "
5321 "not i386_THREAD_EXCEPTSTATE_COUNT for "
5322 "flavor number %u which is a i386_THREAD_"
5323 "EXCEPTSTATE flavor in %s command %u)",
5325 ut
->cmd
== LC_UNIXTHREAD
? "LC_UNIXTHREAD" :
5329 exc
= (i386_thread_exceptstate_t
*)state
;
5330 if(state
+ sizeof(i386_thread_exceptstate_t
) >
5331 (char *)ut
+ ut
->cmdsize
){
5332 Mach_O_error(ofile
, "malformed object ("
5333 "i386_THREAD_EXCEPTSTATE in %s command %u "
5334 "extends past end of command)", ut
->cmd
==
5335 LC_UNIXTHREAD
? "LC_UNIXTHREAD" :
5340 swap_i386_thread_exceptstate(exc
,host_byte_sex
);
5341 state
+= sizeof(i386_thread_exceptstate_t
);
5343 case i386_THREAD_CTHREADSTATE
:
5344 if(count
!= i386_THREAD_CTHREADSTATE_COUNT
){
5345 Mach_O_error(ofile
, "malformed object (count "
5346 "not i386_THREAD_CTHREADSTATE_COUNT for "
5347 "flavor number %u which is a i386_THREAD_"
5348 "CTHREADSTATE flavor in %s command %u)",
5350 ut
->cmd
== LC_UNIXTHREAD
? "LC_UNIXTHREAD" :
5354 user
= (i386_thread_cthreadstate_t
*)state
;
5355 if(state
+ sizeof(i386_thread_cthreadstate_t
) >
5356 (char *)ut
+ ut
->cmdsize
){
5357 Mach_O_error(ofile
, "malformed object ("
5358 "i386_THREAD_CTHREADSTATE in %s command %u "
5359 "extends past end of command)", ut
->cmd
==
5360 LC_UNIXTHREAD
? "LC_UNIXTHREAD" :
5365 swap_i386_thread_cthreadstate(user
,
5367 state
+= sizeof(i386_thread_cthreadstate_t
);
5369 #endif /* i386_THREAD_STATE == -1 */
5372 Mach_O_error(ofile
, "malformed object (unknown "
5373 "flavor for flavor number %u in %s command"
5374 " %u can't byte swap it)", nflavor
,
5375 ut
->cmd
== LC_UNIXTHREAD
? "LC_UNIXTHREAD" :
5379 state
+= count
* sizeof(uint32_t);
5386 #ifdef x86_THREAD_STATE64_COUNT
5387 if(cputype
== CPU_TYPE_X86_64
){
5388 x86_thread_state64_t
*cpu
;
5391 p
= (char *)ut
+ ut
->cmdsize
;
5393 if(state
+ sizeof(uint32_t) >
5394 (char *)ut
+ ut
->cmdsize
){
5395 Mach_O_error(ofile
, "malformed object (flavor in "
5396 "%s command %u extends past end of command)",
5397 ut
->cmd
== LC_UNIXTHREAD
? "LC_UNIXTHREAD" :
5401 flavor
= *((uint32_t *)state
);
5403 flavor
= SWAP_INT(flavor
);
5404 *((uint32_t *)state
) = flavor
;
5406 state
+= sizeof(uint32_t);
5407 if(state
+ sizeof(uint32_t) >
5408 (char *)ut
+ ut
->cmdsize
){
5409 Mach_O_error(ofile
, "malformed object (count in "
5410 "%s command %u extends past end of command)",
5411 ut
->cmd
== LC_UNIXTHREAD
? "LC_UNIXTHREAD" :
5415 count
= *((uint32_t *)state
);
5417 count
= SWAP_INT(count
);
5418 *((uint32_t *)state
) = count
;
5420 state
+= sizeof(uint32_t);
5422 case x86_THREAD_STATE64
:
5423 if(count
!= x86_THREAD_STATE64_COUNT
){
5424 Mach_O_error(ofile
, "malformed object (count "
5425 "not x86_THREAD_STATE64_COUNT for "
5426 "flavor number %u which is a x86_THREAD_"
5427 "STATE64 flavor in %s command %u)",
5428 nflavor
, ut
->cmd
== LC_UNIXTHREAD
?
5429 "LC_UNIXTHREAD" : "LC_THREAD", i
);
5432 cpu
= (x86_thread_state64_t
*)state
;
5433 if(state
+ sizeof(x86_thread_state64_t
) >
5434 (char *)ut
+ ut
->cmdsize
){
5435 Mach_O_error(ofile
, "malformed object ("
5436 "x86_THREAD_STATE64 in %s command %u "
5437 "extends past end of command)", ut
->cmd
==
5438 LC_UNIXTHREAD
? "LC_UNIXTHREAD" :
5443 swap_x86_thread_state64(cpu
, host_byte_sex
);
5444 state
+= sizeof(x86_thread_state64_t
);
5448 Mach_O_error(ofile
, "malformed object (unknown "
5449 "flavor for flavor number %u in %s command"
5450 " %u can't byte swap it)", nflavor
,
5451 ut
->cmd
== LC_UNIXTHREAD
? "LC_UNIXTHREAD" :
5455 state
+= count
* sizeof(uint32_t);
5462 #endif /* x86_THREAD_STATE64_COUNT */
5463 if(cputype
== CPU_TYPE_HPPA
){
5464 struct hp_pa_integer_thread_state
*cpu
;
5465 struct hp_pa_frame_thread_state
*frame
;
5466 struct hp_pa_fp_thread_state
*fpu
;
5469 p
= (char *)ut
+ ut
->cmdsize
;
5471 if(state
+ sizeof(uint32_t) >
5472 (char *)ut
+ ut
->cmdsize
){
5473 Mach_O_error(ofile
, "malformed object (flavor in "
5474 "%s command %u extends past end of command)",
5475 ut
->cmd
== LC_UNIXTHREAD
? "LC_UNIXTHREAD" :
5479 flavor
= *((uint32_t *)state
);
5481 flavor
= SWAP_INT(flavor
);
5482 *((uint32_t *)state
) = flavor
;
5484 state
+= sizeof(uint32_t);
5485 if(state
+ sizeof(uint32_t) >
5486 (char *)ut
+ ut
->cmdsize
){
5487 Mach_O_error(ofile
, "malformed object (count in "
5488 "%s command %u extends past end of command)",
5489 ut
->cmd
== LC_UNIXTHREAD
? "LC_UNIXTHREAD" :
5493 count
= *((uint32_t *)state
);
5495 count
= SWAP_INT(count
);
5496 *((uint32_t *)state
) = count
;
5498 state
+= sizeof(uint32_t);
5500 case HPPA_INTEGER_THREAD_STATE
:
5501 if(count
!= HPPA_INTEGER_THREAD_STATE_COUNT
){
5502 Mach_O_error(ofile
, "malformed object (count "
5503 "not HPPA_INTEGER_THREAD_STATE_COUNT for "
5504 "flavor number %u which is a "
5505 "HPPA_INTEGER_THREAD_STATE "
5506 "flavor in %s command %u)", nflavor
,
5507 ut
->cmd
== LC_UNIXTHREAD
? "LC_UNIXTHREAD" :
5511 cpu
= (struct hp_pa_integer_thread_state
*)state
;
5512 if(state
+sizeof(struct hp_pa_integer_thread_state
) >
5513 (char *)ut
+ ut
->cmdsize
){
5514 Mach_O_error(ofile
, "malformed object ("
5515 "HPPA_INTEGER_THREAD_STATE in %s command "
5516 "%u extends past end of command)",
5517 ut
->cmd
== LC_UNIXTHREAD
? "LC_UNIXTHREAD" :
5522 swap_hppa_integer_thread_state(cpu
,
5524 state
+= sizeof(struct hp_pa_integer_thread_state
);
5526 case HPPA_FRAME_THREAD_STATE
:
5527 if(count
!= HPPA_FRAME_THREAD_STATE_COUNT
){
5528 Mach_O_error(ofile
, "malformed object (count "
5529 "not HPPA_FRAME_THREAD_STATE_COUNT for "
5530 "flavor number %u which is a HPPA_FRAME_"
5531 "THREAD_STATE flavor in %s command %u)",
5533 ut
->cmd
== LC_UNIXTHREAD
? "LC_UNIXTHREAD" :
5537 frame
= (struct hp_pa_frame_thread_state
*)state
;
5538 if(state
+ sizeof(struct hp_pa_frame_thread_state
) >
5539 (char *)ut
+ ut
->cmdsize
){
5540 Mach_O_error(ofile
, "malformed object ("
5541 "HPPA_FRAME_THREAD_STATE in %s command "
5542 "%u extends past end of command)",
5543 ut
->cmd
== LC_UNIXTHREAD
? "LC_UNIXTHREAD" :
5548 swap_hppa_frame_thread_state(frame
,host_byte_sex
);
5549 state
+= sizeof(struct hp_pa_frame_thread_state
);
5551 case HPPA_FP_THREAD_STATE
:
5552 if(count
!= HPPA_FP_THREAD_STATE_COUNT
){
5553 Mach_O_error(ofile
, "malformed object (count "
5554 "not HPPA_FP_THREAD_STATE_COUNT for "
5555 "flavor number %u which is a HPPA_FP_"
5556 "THREAD_STATE flavor in %s command %u)",
5558 ut
->cmd
== LC_UNIXTHREAD
? "LC_UNIXTHREAD" :
5562 fpu
= (struct hp_pa_fp_thread_state
*)state
;
5563 if(state
+ sizeof(struct hp_pa_fp_thread_state
) >
5564 (char *)ut
+ ut
->cmdsize
){
5565 Mach_O_error(ofile
, "malformed object ("
5566 "HPPA_FP_THREAD_STATE in %s command "
5567 "%u extends past end of command)",
5568 ut
->cmd
== LC_UNIXTHREAD
? "LC_UNIXTHREAD" :
5573 swap_hppa_fp_thread_state(fpu
,host_byte_sex
);
5574 state
+= sizeof(struct hp_pa_fp_thread_state
);
5578 Mach_O_error(ofile
, "malformed object (unknown "
5579 "flavor for flavor number %u in %s command"
5580 " %u can't byte swap it)", nflavor
,
5581 ut
->cmd
== LC_UNIXTHREAD
? "LC_UNIXTHREAD" :
5585 state
+= count
* sizeof(uint32_t);
5592 if(cputype
== CPU_TYPE_SPARC
){
5593 struct sparc_thread_state_regs
*cpu
;
5594 struct sparc_thread_state_fpu
*fpu
;
5597 p
= (char *)ut
+ ut
->cmdsize
;
5599 if(state
+ sizeof(uint32_t) >
5600 (char *)ut
+ ut
->cmdsize
){
5601 Mach_O_error(ofile
, "malformed object (flavor in "
5602 "%s command %u extends past end of command)",
5603 ut
->cmd
== LC_UNIXTHREAD
? "LC_UNIXTHREAD" :
5607 flavor
= *((uint32_t *)state
);
5609 flavor
= SWAP_INT(flavor
);
5610 *((uint32_t *)state
) = flavor
;
5612 state
+= sizeof(uint32_t);
5613 if(state
+ sizeof(uint32_t) >
5614 (char *)ut
+ ut
->cmdsize
){
5615 Mach_O_error(ofile
, "malformed object (count in "
5616 "%s command %u extends past end of command)",
5617 ut
->cmd
== LC_UNIXTHREAD
? "LC_UNIXTHREAD" :
5621 count
= *((uint32_t *)state
);
5623 count
= SWAP_INT(count
);
5624 *((uint32_t *)state
) = count
;
5626 state
+= sizeof(uint32_t);
5628 case SPARC_THREAD_STATE_REGS
:
5629 if(count
!= SPARC_THREAD_STATE_REGS_COUNT
){
5630 Mach_O_error(ofile
, "malformed object (count "
5631 "not SPARC_THREAD_STATE_REGS_COUNT for "
5632 "flavor number %u which is a SPARC_THREAD_"
5633 "STATE_REGS flavor in %s command %u)",
5634 nflavor
, ut
->cmd
== LC_UNIXTHREAD
?
5635 "LC_UNIXTHREAD" : "LC_THREAD", i
);
5638 cpu
= (struct sparc_thread_state_regs
*)state
;
5639 if(state
+ sizeof(struct sparc_thread_state_regs
) >
5640 (char *)ut
+ ut
->cmdsize
){
5641 Mach_O_error(ofile
, "malformed object ("
5642 "SPARC_THREAD_STATE_REGS in %s command %u "
5643 "extends past end of command)", ut
->cmd
==
5644 LC_UNIXTHREAD
? "LC_UNIXTHREAD" :
5649 swap_sparc_thread_state_regs(cpu
, host_byte_sex
);
5650 state
+= sizeof(struct sparc_thread_state_regs
);
5652 case SPARC_THREAD_STATE_FPU
:
5653 if(count
!= SPARC_THREAD_STATE_FPU_COUNT
){
5654 Mach_O_error(ofile
, "malformed object (count "
5655 "not SPARC_THREAD_STATE_FPU_COUNT for "
5656 "flavor number %u which is a SPARC_THREAD_"
5657 "STATE_FPU flavor in %s command %u)",
5658 nflavor
, ut
->cmd
== LC_UNIXTHREAD
?
5659 "LC_UNIXTHREAD" : "LC_THREAD", i
);
5662 fpu
= (struct sparc_thread_state_fpu
*)state
;
5663 if(state
+ sizeof(struct sparc_thread_state_fpu
) >
5664 (char *)ut
+ ut
->cmdsize
){
5665 Mach_O_error(ofile
, "malformed object ("
5666 "SPARC_THREAD_STATE_FPU in %s command %u "
5667 "extends past end of command)", ut
->cmd
==
5668 LC_UNIXTHREAD
? "LC_UNIXTHREAD" :
5673 swap_sparc_thread_state_fpu(fpu
, host_byte_sex
);
5674 state
+= sizeof(struct sparc_thread_state_fpu
);
5678 Mach_O_error(ofile
, "malformed object (unknown "
5679 "flavor for flavor number %u in %s command"
5680 " %u can't byte swap it)", nflavor
,
5681 ut
->cmd
== LC_UNIXTHREAD
? "LC_UNIXTHREAD" :
5685 state
+= count
* sizeof(uint32_t);
5692 if(cputype
== CPU_TYPE_ARM
){
5693 arm_thread_state_t
*cpu
;
5696 p
= (char *)ut
+ ut
->cmdsize
;
5698 if(state
+ sizeof(uint32_t) >
5699 (char *)ut
+ ut
->cmdsize
){
5700 Mach_O_error(ofile
, "malformed object (flavor in "
5701 "%s command %u extends past end of command)",
5702 ut
->cmd
== LC_UNIXTHREAD
? "LC_UNIXTHREAD" :
5706 flavor
= *((uint32_t *)state
);
5708 flavor
= SWAP_INT(flavor
);
5709 *((uint32_t *)state
) = flavor
;
5711 state
+= sizeof(uint32_t);
5712 if(state
+ sizeof(uint32_t) >
5713 (char *)ut
+ ut
->cmdsize
){
5714 Mach_O_error(ofile
, "malformed object (count in "
5715 "%s command %u extends past end of command)",
5716 ut
->cmd
== LC_UNIXTHREAD
? "LC_UNIXTHREAD" :
5720 count
= *((uint32_t *)state
);
5722 count
= SWAP_INT(count
);
5723 *((uint32_t *)state
) = count
;
5725 state
+= sizeof(uint32_t);
5727 case ARM_THREAD_STATE
:
5728 if(count
!= ARM_THREAD_STATE_COUNT
){
5729 Mach_O_error(ofile
, "malformed object (count "
5730 "not ARM_THREAD_STATE_COUNT for "
5731 "flavor number %u which is a ARM_THREAD_"
5732 "STATE flavor in %s command %u)",
5733 nflavor
, ut
->cmd
== LC_UNIXTHREAD
?
5734 "LC_UNIXTHREAD" : "LC_THREAD", i
);
5737 cpu
= (arm_thread_state_t
*)state
;
5738 if(state
+ sizeof(arm_thread_state_t
) >
5739 (char *)ut
+ ut
->cmdsize
){
5740 Mach_O_error(ofile
, "malformed object ("
5741 "ARM_THREAD_STATE in %s command %u "
5742 "extends past end of command)", ut
->cmd
==
5743 LC_UNIXTHREAD
? "LC_UNIXTHREAD" :
5748 swap_arm_thread_state_t(cpu
, host_byte_sex
);
5749 state
+= sizeof(arm_thread_state_t
);
5753 Mach_O_error(ofile
, "malformed object (unknown "
5754 "flavor for flavor number %u in %s command"
5755 " %u can't byte swap it)", nflavor
,
5756 ut
->cmd
== LC_UNIXTHREAD
? "LC_UNIXTHREAD" :
5760 state
+= count
* sizeof(uint32_t);
5768 Mach_O_error(ofile
, "malformed object (unknown cputype and "
5769 "cpusubtype of object and can't byte swap and check %s "
5770 "command %u)", ut
->cmd
== LC_UNIXTHREAD
?
5771 "LC_UNIXTHREAD" : "LC_THREAD", i
);
5776 if(l
.cmdsize
< sizeof(struct entry_point_command
)){
5777 Mach_O_error(ofile
, "malformed object (LC_MAIN cmdsize "
5778 "too small) in command %u", i
);
5781 ep
= (struct entry_point_command
*)lc
;
5783 swap_entry_point_command(ep
, host_byte_sex
);
5785 * If we really wanted we could check that the entryoff field
5786 * really is an offset into the __TEXT segment. But since it
5787 * is not used here, we won't needlessly check it.
5790 case LC_SOURCE_VERSION
:
5791 if(l
.cmdsize
< sizeof(struct source_version_command
)){
5792 Mach_O_error(ofile
, "malformed object (LC_SOURCE_VERSION "
5793 "cmdsize too small) in command %u", i
);
5796 sv
= (struct source_version_command
*)lc
;
5798 swap_source_version_command(sv
, host_byte_sex
);
5800 if(l
.cmdsize
< sizeof(struct ident_command
)){
5801 Mach_O_error(ofile
, "malformed object (LC_IDENT cmdsize "
5802 "too small) in command %u", i
);
5805 id
= (struct ident_command
*)lc
;
5807 swap_ident_command(id
, host_byte_sex
);
5809 * Note the cmdsize field if the LC_IDENT command was checked
5810 * as part of checking all load commands cmdsize field before
5811 * the switch statement on the cmd field of the load command.
5815 if(l
.cmdsize
< sizeof(struct rpath_command
)){
5816 Mach_O_error(ofile
, "malformed object (LC_RPATH: cmdsize "
5817 "too small) in command %u", i
);
5820 rpath
= (struct rpath_command
*)lc
;
5822 swap_rpath_command(rpath
, host_byte_sex
);
5823 if(rpath
->cmdsize
< sizeof(struct rpath_command
)){
5824 Mach_O_error(ofile
, "malformed object (LC_RPATH command "
5825 "%u has too small cmdsize field)", i
);
5828 if(rpath
->path
.offset
>= rpath
->cmdsize
){
5829 Mach_O_error(ofile
, "truncated or malformed object (path."
5830 "offset field of LC_RPATH command %u extends past the "
5831 "end of the file)", i
);
5838 Mach_O_error(ofile
, "malformed object (unknown load command "
5841 #endif /* !defined(OFI) */
5844 lc
= (struct load_command
*)((char *)lc
+ l
.cmdsize
);
5845 /* check that next load command does not extends past the end */
5846 if((char *)lc
> (char *)load_commands
+ sizeofcmds
){
5847 Mach_O_error(ofile
, "truncated or malformed object (load "
5848 "command %u extends past the end of the file)",
5855 Mach_O_error(ofile
, "truncated or malformed object (contains "
5856 "LC_DYSYMTAB load command without a LC_SYMTAB load command)");
5862 if(dyst
->nlocalsym
!= 0 &&
5863 dyst
->ilocalsym
> st
->nsyms
){
5864 Mach_O_error(ofile
, "truncated or malformed object "
5865 "(ilocalsym in LC_DYSYMTAB load command extends past "
5866 "the end of the symbol table)");
5869 big_size
= dyst
->ilocalsym
;
5870 big_size
+= dyst
->nlocalsym
;
5871 if(dyst
->nlocalsym
!= 0 && big_size
> st
->nsyms
){
5872 Mach_O_error(ofile
, "truncated or malformed object "
5873 "(ilocalsym plus nlocalsym in LC_DYSYMTAB load command "
5874 "extends past the end of the symbol table)");
5878 if(dyst
->nextdefsym
!= 0 &&
5879 dyst
->iextdefsym
> st
->nsyms
){
5880 Mach_O_error(ofile
, "truncated or malformed object "
5881 "(iextdefsym in LC_DYSYMTAB load command extends past "
5882 "the end of the symbol table)");
5885 big_size
= dyst
->iextdefsym
;
5886 big_size
+= dyst
->nextdefsym
;
5887 if(dyst
->nextdefsym
!= 0 && big_size
> st
->nsyms
){
5888 Mach_O_error(ofile
, "truncated or malformed object "
5889 "(iextdefsym plus nextdefsym in LC_DYSYMTAB load "
5890 "command extends past the end of the symbol table)");
5894 if(dyst
->nundefsym
!= 0 &&
5895 dyst
->iundefsym
> st
->nsyms
){
5896 Mach_O_error(ofile
, "truncated or malformed object "
5897 "(iundefsym in LC_DYSYMTAB load command extends past "
5898 "the end of the symbol table)");
5901 big_size
= dyst
->iundefsym
;
5902 big_size
+= dyst
->nundefsym
;
5903 if(dyst
->nundefsym
!= 0 && big_size
> st
->nsyms
){
5904 Mach_O_error(ofile
, "truncated or malformed object "
5905 "(iundefsym plus nundefsym in LC_DYSYMTAB load command "
5906 "extends past the end of the symbol table)");
5910 if(rc
->init_module
> dyst
->nmodtab
){
5911 Mach_O_error(ofile
, "malformed object (init_module in "
5912 "LC_ROUTINES load command extends past the "
5913 "end of the module table)");
5918 if(rc64
->init_module
> dyst
->nmodtab
){
5919 Mach_O_error(ofile
, "malformed object (init_module in "
5920 "LC_ROUTINES_64 load command extends past the "
5921 "end of the module table)");
5926 if(hints
->nhints
!= dyst
->nundefsym
){
5927 Mach_O_error(ofile
, "malformed object (nhints in "
5928 "LC_TWOLEVEL_HINTS load command not the same as "
5929 "nundefsym in LC_DYSYMTAB load command)");
5935 /* check for an inconsistent size of the load commands */
5936 if((char *)load_commands
+ sizeofcmds
!= (char *)lc
){
5937 Mach_O_error(ofile
, "malformed object (inconsistent sizeofcmds "
5938 "field in mach header)");
5943 * Mark this ofile so we know its headers have been swapped. We do this
5944 * in case we don't process it the first time so we can swap them back
5945 * in case we loop back to it in a fat file to process it later.
5948 ofile
->headers_swapped
= TRUE
;
5950 /* looks good return ok */
5951 free_elements(&elements
);
5955 free_elements(&elements
);
5961 * swap_back_Mach_O() is called after the ofile has been processed to swap back
5962 * the mach header and load commands if check_Mach_O() above swapped them.
5967 struct ofile
*ofile
)
5969 if(ofile
->headers_swapped
== TRUE
){
5970 ofile
->headers_swapped
= FALSE
;
5971 if(ofile
->mh
!= NULL
)
5972 swap_object_headers(ofile
->mh
, ofile
->load_commands
);
5973 else if(ofile
->mh64
!= NULL
)
5974 swap_object_headers(ofile
->mh64
, ofile
->load_commands
);
5980 * check_overlaping_element() checks that the element in the ofile described by
5981 * offset, size and name does not overlap in list of elements in head. If it
5982 * does CHECK_BAD is returned and an error message is generated. If it doesn't
5983 * then an element is added in the ordered list and CHECK_GOOD is returned
5987 check_overlaping_element(
5988 struct ofile
*ofile
,
5989 struct element
*head
,
5994 struct element
*e
, *p
, *n
;
5999 if(head
->next
== NULL
){
6000 n
= allocate(sizeof(struct element
));
6011 while(e
->next
!= NULL
){
6014 if((offset
>= e
->offset
&&
6015 offset
< e
->offset
+ e
->size
) ||
6016 (offset
+ size
> e
->offset
&&
6017 offset
+ size
< e
->offset
+ e
->size
) ||
6018 (offset
<= e
->offset
&&
6019 offset
+ size
>= e
->offset
+ e
->size
)){
6020 Mach_O_error(ofile
, "malformed object (%s at offset %u with a "
6021 "size of %u, overlaps %s at offset %u with a size of %u)",
6022 name
, offset
, size
, e
->name
, e
->offset
, e
->size
);
6025 if(e
->next
!= NULL
&& offset
+ size
<= e
->next
->offset
){
6026 n
= allocate(sizeof(struct element
));
6035 n
= allocate(sizeof(struct element
));
6045 * free_elements() frees the list of elements on the list head.
6050 struct element
*head
)
6052 struct element
*e
, *e_next
;
6061 #endif /* !defined(OTOOL) */
6064 * check_dylib_module() checks the object file's dylib_module as referenced
6065 * by the dylib_module field in the ofile for correctness.
6070 struct ofile
*ofile
,
6071 struct symtab_command
*st
,
6072 struct dysymtab_command
*dyst
,
6074 uint32_t module_index
)
6078 #else /* !defined OTOOL */
6080 enum byte_sex host_byte_sex
;
6082 struct dylib_module m
;
6083 struct dylib_module_64 m64
;
6084 uint32_t module_name
, nextdefsym
, iextdefsym
, nlocalsym
, ilocalsym
, nrefsym
;
6085 uint32_t irefsym
, nextrel
, iextrel
;
6087 host_byte_sex
= get_host_byte_sex();
6088 swapped
= (enum bool)(host_byte_sex
!= ofile
->object_byte_sex
);
6089 if(ofile
->mh
!= NULL
){
6090 m
= *ofile
->dylib_module
;
6092 swap_dylib_module(&m
, 1, host_byte_sex
);
6093 module_name
= m
.module_name
;
6094 nextdefsym
= m
.nextdefsym
;
6095 iextdefsym
= m
.iextdefsym
;
6096 nlocalsym
= m
.nlocalsym
;
6097 ilocalsym
= m
.ilocalsym
;
6098 nrefsym
= m
.nrefsym
;
6099 irefsym
= m
.irefsym
;
6100 nextrel
= m
.nextrel
;
6101 iextrel
= m
.iextrel
;
6104 m64
= *ofile
->dylib_module64
;
6106 swap_dylib_module_64(&m64
, 1, host_byte_sex
);
6107 module_name
= m64
.module_name
;
6108 nextdefsym
= m64
.nextdefsym
;
6109 iextdefsym
= m64
.iextdefsym
;
6110 nlocalsym
= m64
.nlocalsym
;
6111 ilocalsym
= m64
.ilocalsym
;
6112 nrefsym
= m64
.nrefsym
;
6113 irefsym
= m64
.irefsym
;
6114 nextrel
= m64
.nextrel
;
6115 iextrel
= m64
.iextrel
;
6118 if(module_name
> st
->strsize
){
6119 Mach_O_error(ofile
, "truncated or malformed object (module_name "
6120 "of module table entry %u past the end of the string table)",
6124 for(i
= module_name
; i
< st
->strsize
&& strings
[i
] != '\0'; i
++)
6126 if(i
>= st
->strsize
){
6127 Mach_O_error(ofile
, "truncated or malformed object (module_name "
6128 "of module table entry %u extends past the end of the string "
6129 "table)", module_index
);
6133 if(nextdefsym
!= 0){
6134 if(iextdefsym
> st
->nsyms
){
6135 Mach_O_error(ofile
, "truncated or malformed object (iextdefsym "
6136 "field of module table entry %u past the end of the "
6137 "symbol table", module_index
);
6140 if(iextdefsym
+ nextdefsym
> st
->nsyms
){
6141 Mach_O_error(ofile
, "truncated or malformed object (iextdefsym "
6142 "field of module table entry %u plus nextdefsym field "
6143 "extends past the end of the symbol table", module_index
);
6148 if(ilocalsym
> st
->nsyms
){
6149 Mach_O_error(ofile
, "truncated or malformed object (ilocalsym "
6150 "field of module table entry %u past the end of the "
6151 "symbol table", module_index
);
6154 if(ilocalsym
+ nlocalsym
> st
->nsyms
){
6155 Mach_O_error(ofile
, "truncated or malformed object (ilocalsym "
6156 "field of module table entry %u plus nlocalsym field "
6157 "extends past the end of the symbol table", module_index
);
6162 if(irefsym
> dyst
->nextrefsyms
){
6163 Mach_O_error(ofile
, "truncated or malformed object (irefsym "
6164 "field of module table entry %u past the end of the "
6165 "reference table", module_index
);
6168 if(irefsym
+ nrefsym
> dyst
->nextrefsyms
){
6169 Mach_O_error(ofile
, "truncated or malformed object (irefsym "
6170 "field of module table entry %u plus nrefsym field "
6171 "extends past the end of the reference table",module_index
);
6176 if(iextrel
> dyst
->extreloff
){
6177 Mach_O_error(ofile
, "truncated or malformed object (iextrel "
6178 "field of module table entry %u past the end of the "
6179 "external relocation enrties", module_index
);
6182 if(iextrel
+ nextrel
> dyst
->extreloff
){
6183 Mach_O_error(ofile
, "truncated or malformed object (iextrel "
6184 "field of module table entry %u plus nextrel field "
6185 "extends past the end of the external relocation enrties",
6197 const struct ar_hdr
*ar_hdr
)
6201 i
= sizeof(ar_hdr
->ar_name
) - 1;
6202 if(ar_hdr
->ar_name
[i
] == ' '){
6204 if(ar_hdr
->ar_name
[i
] != ' ')
6211 #endif /* !defined(RLD) */