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 "dyld_bind_info.h"
84 #include "ofile_print.h"
85 static enum bool otool_first_ofile_map
= TRUE
;
86 #else /* !define(OTOOL) */
88 #if (!defined(m68k) && !defined(__i386__) && !defined(__x86_64__) && !defined(__ppc__) && !defined(__arm__))
89 #define ALIGNMENT_CHECKS_ARCHIVE_64_BIT
90 static enum bool archive_64_bit_align_warning
= FALSE
;
91 #endif /* (!defined(m68k) && !defined(__i386__) && !defined(__x86_64__) && !defined(__ppc__) && !defined(__arm__)) */
96 /* The maximum section alignment allowed to be specified, as a power of two */
97 #define MAXSECTALIGN 15 /* 2**15 or 0x8000 */
109 struct element
*next
;
111 #endif /* !defined(OTOOL) */
113 static enum bool ofile_specific_arch(
116 static enum check_type
check_fat(
117 struct ofile
*ofile
);
118 static enum check_type
check_fat_object_in_archive(
119 struct ofile
*ofile
);
120 static enum check_type
check_archive(
122 enum bool archives_with_fat_objects
);
123 static enum check_type
check_extend_format_1(
125 struct ar_hdr
*ar_hdr
,
127 uint32_t *member_name_size
);
128 static enum check_type
check_archive_toc(
129 struct ofile
*ofile
);
130 static enum check_type
check_Mach_O(
131 struct ofile
*ofile
);
132 static void swap_back_Mach_O(
133 struct ofile
*ofile
);
135 static enum check_type
check_overlaping_element(
137 struct element
*head
,
141 static void free_elements(
142 struct element
*head
);
143 #endif /* !defined(OTOOL) */
144 static enum check_type
check_dylib_module(
146 struct symtab_command
*st
,
147 struct dysymtab_command
*dyst
,
149 uint32_t module_index
);
152 #if defined(ALIGNMENT_CHECKS) || defined(ALIGNMENT_CHECKS_ARCHIVE_64_BIT)
155 temporary_archive_member_warning(
157 const char *format
, ...)
161 va_start(ap
, format
);
162 if(ofile
->file_type
== OFILE_FAT
){
163 print("%s: for architecture %s archive member: %s(%.*s) ",
164 progname
, ofile
->arch_flag
.name
, ofile
->file_name
,
165 (int)ofile
->member_name_size
, ofile
->member_name
);
168 print("%s: archive member: %s(%.*s) ", progname
, ofile
->file_name
,
169 (int)ofile
->member_name_size
, ofile
->member_name
);
175 #endif /* defined(ALIGNMENT_CHECKS) */
176 #endif /* !defined(OTOOL) */
180 * ofile_process() processes the specified file name can calls the routine
181 * processor on the ofiles in it. arch_flags is an array of architectures
182 * containing narch_flags which are the only architectures to process if
183 * narch_flags is non-zero. If all_archs is TRUE then all architectures of
184 * the specified file are processed. The specified file name can be of the
185 * form "archive(member)" which is taken to mean that member in that archive
186 * (or that module of a dynamic library if dylib_flat is not FALSE).
187 * For each ofile that is to be processed the routine processor is called with
188 * the corresponding ofile struct, the arch_name pass to it is either NULL or
189 * an architecture name (when it should be printed or show by processor) and
190 * cookie is the same value as passed to ofile_process.
196 struct arch_flag
*arch_flags
,
197 uint32_t narch_flags
,
199 enum bool process_non_objects
,
200 enum bool dylib_flat
,
201 enum bool use_member_syntax
,
202 void (*processor
)(struct ofile
*ofile
, char *arch_name
, void *cookie
),
205 char *member_name
, *p
, *arch_name
;
208 enum bool flag
, hostflag
, arch_found
, family
;
209 struct arch_flag host_arch_flag
, specific_arch_flag
;
210 const struct arch_flag
*family_arch_flag
;
213 * If use_member_syntax is TRUE look for a name of the form
214 * "archive(member)" which is to mean a member in that archive (the
215 * member name must be at least one character long to be recognized as
219 if(use_member_syntax
== TRUE
){
221 if(len
>= 4 && name
[len
-1] == ')'){
222 p
= strrchr(name
, '(');
223 if(p
!= NULL
&& p
!= name
){
232 otool_first_ofile_map
= TRUE
;
234 if(ofile_map(name
, NULL
, NULL
, &ofile
, FALSE
) == FALSE
)
237 otool_first_ofile_map
= FALSE
;
240 if(ofile
.file_type
== OFILE_FAT
){
242 * This is a fat file so see if a list of architecture is
243 * specified and process only those.
245 if(all_archs
== FALSE
&& narch_flags
!= 0){
246 for(i
= 0; i
< narch_flags
; i
++){
247 if(ofile_first_arch(&ofile
) == FALSE
){
254 get_arch_family_from_cputype(arch_flags
[i
].cputype
);
255 if(family_arch_flag
!= NULL
)
257 ((family_arch_flag
->cpusubtype
& ~CPU_SUBTYPE_MASK
) ==
258 (arch_flags
[i
].cpusubtype
& ~CPU_SUBTYPE_MASK
));
260 arch_name
= ofile
.arch_flag
.name
;
264 if(ofile
.arch_flag
.cputype
==
265 arch_flags
[i
].cputype
&&
266 ((ofile
.arch_flag
.cpusubtype
& ~CPU_SUBTYPE_MASK
) ==
267 (arch_flags
[i
].cpusubtype
& ~CPU_SUBTYPE_MASK
) ||
270 if(ofile
.arch_type
== OFILE_ARCHIVE
){
271 if(member_name
!= NULL
){
272 if(ofile_specific_member(member_name
,
274 processor(&ofile
, arch_name
, cookie
);
275 if(ofile
.headers_swapped
== TRUE
)
276 swap_back_Mach_O(&ofile
);
280 /* loop through archive */
282 printf("Archive : %s", ofile
.file_name
);
283 if(arch_name
!= NULL
)
284 printf(" (architecture %s)",
288 if(ofile_first_member(&ofile
) == TRUE
){
291 if(process_non_objects
== TRUE
||
294 processor(&ofile
, arch_name
,
296 if(ofile
.headers_swapped
==TRUE
)
297 swap_back_Mach_O(&ofile
);
300 }while(ofile_next_member(&ofile
) ==
303 error("for architecture: %s "
304 "archive: %s contains no "
305 "members that are object "
306 "files", ofile
.arch_flag
.name
,
311 error("for architecture: %s archive: "
312 "%s contains no members",
313 ofile
.arch_flag
.name
,
318 else if(process_non_objects
== TRUE
||
319 ofile
.arch_type
== OFILE_Mach_O
){
320 if(ofile
.arch_type
== OFILE_Mach_O
&&
321 (ofile
.mh_filetype
== MH_DYLIB
||
322 ofile
.mh_filetype
== MH_DYLIB_STUB
)){
323 if(dylib_flat
== TRUE
){
324 processor(&ofile
, arch_name
, cookie
);
325 if(ofile
.headers_swapped
== TRUE
)
326 swap_back_Mach_O(&ofile
);
329 if(member_name
!= NULL
){
330 if(ofile_specific_module(
331 member_name
, &ofile
) == TRUE
){
332 processor(&ofile
, arch_name
,
334 if(ofile
.headers_swapped
==TRUE
)
335 swap_back_Mach_O(&ofile
);
339 /*loop through the dynamic library*/
340 if(ofile_first_module(&ofile
)){
342 processor(&ofile
, arch_name
,
344 }while(ofile_next_module(
348 processor(&ofile
, arch_name
,
353 if(ofile
.headers_swapped
== TRUE
)
354 swap_back_Mach_O(&ofile
);
357 if(member_name
!= NULL
)
358 error("for architecture: %s file: %s "
359 "is not an archive and thus does "
360 "not contain member: %s",
361 ofile
.arch_flag
.name
,
365 processor(&ofile
, arch_name
, cookie
);
366 if(ofile
.headers_swapped
== TRUE
)
367 swap_back_Mach_O(&ofile
);
371 else if(ofile
.arch_type
== OFILE_UNKNOWN
){
372 error("for architecture: %s file: %s is "
373 "not an object file",
374 ofile
.arch_flag
.name
,ofile
.file_name
);
376 if(ofile
.headers_swapped
== TRUE
)
377 swap_back_Mach_O(&ofile
);
381 if(ofile
.headers_swapped
== TRUE
)
382 swap_back_Mach_O(&ofile
);
384 }while(ofile_next_arch(&ofile
) == TRUE
);
385 if(arch_found
== FALSE
)
386 error("file: %s does not contain architecture: %s",
387 ofile
.file_name
, arch_flags
[i
].name
);
394 * This is a fat file and no architectures has been specified
395 * so if it contains the host architecture process only that
396 * architecture but if not process all architectures
399 if(all_archs
== FALSE
){
400 (void)get_arch_from_host(&host_arch_flag
, &specific_arch_flag
);
403 * If runing as a 64-bit binary and on an Intel x86 host
406 if(host_arch_flag
.cputype
== CPU_TYPE_I386
)
408 *get_arch_family_from_cputype(CPU_TYPE_X86_64
);
409 #endif /* __LP64__ */
414 get_arch_family_from_cputype(host_arch_flag
.cputype
);
416 if(family_arch_flag
!= NULL
)
418 ((family_arch_flag
->cpusubtype
& ~CPU_SUBTYPE_MASK
) ==
419 (host_arch_flag
.cpusubtype
& ~CPU_SUBTYPE_MASK
));
423 if(ofile_map(name
, NULL
, NULL
, &ofile
, FALSE
) == FALSE
)
425 if(ofile_first_arch(&ofile
) == FALSE
){
430 if(ofile
.arch_flag
.cputype
==
431 host_arch_flag
.cputype
&&
432 ((ofile
.arch_flag
.cpusubtype
& ~CPU_SUBTYPE_MASK
) ==
434 (specific_arch_flag
.cpusubtype
& ~CPU_SUBTYPE_MASK
) ||
436 (host_arch_flag
.cpusubtype
& ~CPU_SUBTYPE_MASK
) ||
440 if(ofile
.arch_type
== OFILE_ARCHIVE
){
441 if(member_name
!= NULL
){
442 if(ofile_specific_member(member_name
,
444 processor(&ofile
, NULL
, cookie
);
445 if(ofile
.headers_swapped
== TRUE
)
446 swap_back_Mach_O(&ofile
);
450 /* loop through archive */
452 printf("Archive : %s\n", ofile
.file_name
);
454 if(ofile_first_member(&ofile
) == TRUE
){
457 if(process_non_objects
== TRUE
||
458 ofile
.member_type
== OFILE_Mach_O
){
459 processor(&ofile
, NULL
, cookie
);
460 if(ofile
.headers_swapped
== TRUE
)
461 swap_back_Mach_O(&ofile
);
464 }while(ofile_next_member(&ofile
) ==
467 error("archive: %s contains no "
468 "members that are object "
469 "files", ofile
.file_name
);
473 error("archive: %s contains no "
474 "members", ofile
.file_name
);
478 else if(process_non_objects
== TRUE
||
479 ofile
.arch_type
== OFILE_Mach_O
){
480 if(ofile
.arch_type
== OFILE_Mach_O
&&
481 (ofile
.mh_filetype
== MH_DYLIB
||
482 ofile
.mh_filetype
== MH_DYLIB_STUB
)){
483 if(dylib_flat
== TRUE
){
484 processor(&ofile
, NULL
, cookie
);
487 if(member_name
!= NULL
){
488 if(ofile_specific_module(member_name
,
490 processor(&ofile
, NULL
, cookie
);
493 /* loop through the dynamic library */
494 if(ofile_first_module(&ofile
) == TRUE
){
496 processor(&ofile
, NULL
, cookie
);
497 }while(ofile_next_module(&ofile
));
500 processor(&ofile
, NULL
, cookie
);
504 if(ofile
.headers_swapped
== TRUE
)
505 swap_back_Mach_O(&ofile
);
508 if(member_name
!= NULL
)
509 error("for architecture: %s file: %s is "
510 "not an archive and thus does not "
511 "contain member: %s",
512 ofile
.arch_flag
.name
, ofile
.file_name
,
515 processor(&ofile
, NULL
, cookie
);
516 if(ofile
.headers_swapped
== TRUE
)
517 swap_back_Mach_O(&ofile
);
521 else if(ofile
.arch_type
== OFILE_UNKNOWN
){
522 error("file: %s is not an object file",
527 if(ofile
.headers_swapped
== TRUE
)
528 swap_back_Mach_O(&ofile
);
530 }while(hostflag
== FALSE
&& ofile_next_arch(&ofile
) == TRUE
);
531 if(hostflag
== TRUE
){
538 * Either all architectures have been specified or none have
539 * been specified and it does not contain the host architecture
540 * so do all the architectures in the fat file
543 if(ofile_map(name
, NULL
, NULL
, &ofile
, FALSE
) == FALSE
)
545 if(ofile_first_arch(&ofile
) == FALSE
){
550 if(ofile
.arch_type
== OFILE_ARCHIVE
){
551 if(member_name
!= NULL
){
552 if(ofile_specific_member(member_name
, &ofile
) == TRUE
)
553 processor(&ofile
, ofile
.arch_flag
.name
, cookie
);
556 /* loop through archive */
558 printf("Archive : %s (architecture %s)\n",
559 ofile
.file_name
, ofile
.arch_flag
.name
);
561 if(ofile_first_member(&ofile
) == TRUE
){
564 if(process_non_objects
== TRUE
||
565 ofile
.member_type
== OFILE_Mach_O
){
566 processor(&ofile
, ofile
.arch_flag
.name
,
570 }while(ofile_next_member(&ofile
) == TRUE
);
572 error("for architecture: %s archive: %s "
573 "contains no members that are object "
574 "files", ofile
.arch_flag
.name
,
579 error("for architecture: %s archive: %s "
580 "contains no members",
581 ofile
.arch_flag
.name
, ofile
.file_name
);
585 else if(process_non_objects
== TRUE
||
586 ofile
.arch_type
== OFILE_Mach_O
){
587 if(ofile
.arch_type
== OFILE_Mach_O
&&
588 (ofile
.mh_filetype
== MH_DYLIB
||
589 ofile
.mh_filetype
== MH_DYLIB_STUB
)){
590 if(dylib_flat
== TRUE
){
591 processor(&ofile
, ofile
.arch_flag
.name
, cookie
);
594 if(member_name
!= NULL
){
595 if(ofile_specific_module(member_name
, &ofile
)
597 processor(&ofile
, ofile
.arch_flag
.name
,
601 /* loop through the dynamic library */
602 if(ofile_first_module(&ofile
) == TRUE
){
604 processor(&ofile
, ofile
.arch_flag
.name
,
606 }while(ofile_next_module(&ofile
) == TRUE
);
609 processor(&ofile
, ofile
.arch_flag
.name
,
616 if(member_name
!= NULL
)
617 error("for architecture: %s file: %s is not an "
618 "archive and thus does not contain member: "
619 "%s", ofile
.arch_flag
.name
, ofile
.file_name
,
622 processor(&ofile
, ofile
.arch_flag
.name
, cookie
);
625 else if(ofile
.arch_type
== OFILE_UNKNOWN
){
626 error("for architecture: %s file: %s is not an "
627 "object file", ofile
.arch_flag
.name
,
630 }while(ofile_next_arch(&ofile
) == TRUE
);
632 else if(ofile
.file_type
== OFILE_ARCHIVE
){
633 if(narch_flags
!= 0){
635 for(i
= 0; i
< narch_flags
; i
++){
637 if(narch_flags
== 1){
639 get_arch_family_from_cputype(arch_flags
[0].cputype
);
640 if(family_arch_flag
!= NULL
)
642 ((family_arch_flag
->cpusubtype
&
643 ~CPU_SUBTYPE_MASK
) ==
644 (arch_flags
[0].cpusubtype
&
647 if(ofile
.archive_cputype
== arch_flags
[i
].cputype
&&
648 ((ofile
.archive_cpusubtype
& ~CPU_SUBTYPE_MASK
) ==
649 (arch_flags
[i
].cpusubtype
& ~CPU_SUBTYPE_MASK
) ||
654 error("file: %s does not contain architecture: %s",
655 ofile
.file_name
, arch_flags
[i
].name
);
658 if(arch_found
== FALSE
){
663 if(member_name
!= NULL
){
664 if(ofile_specific_member(member_name
, &ofile
) == TRUE
)
665 processor(&ofile
, NULL
, cookie
);
668 /* loop through archive */
670 printf("Archive : %s\n", ofile
.file_name
);
672 if(ofile_first_member(&ofile
) == TRUE
){
675 if(process_non_objects
== TRUE
||
676 ofile
.member_type
== OFILE_Mach_O
){
677 processor(&ofile
, NULL
, cookie
);
680 }while(ofile_next_member(&ofile
) == TRUE
);
682 error("archive: %s contains no members that are "
683 "object files", ofile
.file_name
);
687 error("archive: %s contains no members",
692 else if(ofile
.file_type
== OFILE_Mach_O
){
693 if(narch_flags
!= 0){
695 for(i
= 0; i
< narch_flags
; i
++){
697 if(narch_flags
== 1){
699 get_arch_family_from_cputype(arch_flags
[0].cputype
);
700 if(family_arch_flag
!= NULL
)
702 ((family_arch_flag
->cpusubtype
&
703 ~CPU_SUBTYPE_MASK
) ==
704 (arch_flags
[0].cpusubtype
&
708 if(ofile
.mh
!= NULL
){
709 if(ofile
.mh
->magic
== MH_MAGIC
&&
710 ofile
.mh
->cputype
== arch_flags
[i
].cputype
&&
711 ((ofile
.mh
->cpusubtype
& ~CPU_SUBTYPE_MASK
) ==
712 (arch_flags
[i
].cpusubtype
& ~CPU_SUBTYPE_MASK
) ||
716 if(ofile
.mh
->magic
== SWAP_INT(MH_MAGIC
) &&
717 (cpu_type_t
)SWAP_INT(ofile
.mh
->cputype
) ==
718 arch_flags
[i
].cputype
&&
719 ((cpu_subtype_t
)SWAP_INT(ofile
.mh
->cpusubtype
&
720 ~CPU_SUBTYPE_MASK
) ==
721 (arch_flags
[i
].cpusubtype
&
722 ~CPU_SUBTYPE_MASK
) ||
727 else if(ofile
.mh64
!= NULL
){
728 if(ofile
.mh64
->magic
== MH_MAGIC_64
&&
729 ofile
.mh64
->cputype
== arch_flags
[i
].cputype
&&
730 ((ofile
.mh64
->cpusubtype
& ~CPU_SUBTYPE_MASK
) ==
731 (arch_flags
[i
].cpusubtype
& ~CPU_SUBTYPE_MASK
) ||
735 if(ofile
.mh64
->magic
== SWAP_INT(MH_MAGIC_64
) &&
736 (cpu_type_t
)SWAP_INT(ofile
.mh64
->cputype
) ==
737 arch_flags
[i
].cputype
&&
738 ((cpu_subtype_t
)SWAP_INT((ofile
.mh64
->cpusubtype
&
739 ~CPU_SUBTYPE_MASK
)) ==
740 (arch_flags
[i
].cpusubtype
& ~CPU_SUBTYPE_MASK
) ||
747 if(ofile
.mh_cputype
== arch_flags
[i
].cputype
&&
748 ((ofile
.mh_cpusubtype
& ~CPU_SUBTYPE_MASK
) ==
749 (arch_flags
[i
].cpusubtype
& ~CPU_SUBTYPE_MASK
) ||
754 error("file: %s does not contain architecture: %s",
755 ofile
.file_name
, arch_flags
[i
].name
);
758 if(arch_found
== FALSE
){
763 if(ofile
.mh_filetype
== MH_DYLIB
||
764 ofile
.mh_filetype
== MH_DYLIB_STUB
){
765 if(dylib_flat
== TRUE
){
766 processor(&ofile
, NULL
, cookie
);
769 if(member_name
!= NULL
){
770 if(ofile_specific_module(member_name
, &ofile
) == TRUE
)
771 processor(&ofile
, NULL
, cookie
);
774 /* loop through the dynamic library */
775 if(ofile_first_module(&ofile
) == TRUE
){
777 processor(&ofile
, NULL
, cookie
);
778 }while(ofile_next_module(&ofile
) == TRUE
);
781 processor(&ofile
, NULL
, cookie
);
787 if(member_name
!= NULL
)
788 error("file: %s is not an archive and thus does not contain"
789 " member: %s", ofile
.file_name
, member_name
);
791 processor(&ofile
, NULL
, cookie
);
795 if(process_non_objects
== TRUE
)
796 processor(&ofile
, NULL
, cookie
);
797 else if(member_name
!= NULL
)
798 error("file: %s(%s) is not an object file", name
,
801 error("file: %s is not an object file", name
);
805 #endif /* !defined(OFI) */
808 * ofile_map maps in the object file specified by file_name, arch_flag and
809 * object_name and fills in the ofile struct pointed to by ofile for it.
810 * When arch_flag and object_name are both NULL, the file is just set up into
811 * ofile (if the file can be opened and mapped in, if not this call fails
812 * are error routnes are called). If arch_flag is not NULL and object_file is
813 * NULL, then the file must be a Mach-O file or a fat file with the architecture
814 * specified in the arch_flag, if not this call fails and error routines are
815 * called. When arch_flag and object_name are both not NULL, then the file must
816 * be an archive or a fat file containing archives for the specified architec-
817 * ture and contain an archive member object file with the name object_name,
818 * otherwise this call fails and error routines are called. If arch_flag is
819 * NULL and object_file is not NULL, then the file name must be an archive (not
820 * a fat file containing archives) and contain an archive member object file
821 * with the name object_name, otherwise this call fails and calls error
822 * routines. If this call suceeds then it returns non-zero and the ofile
823 * structure pointed to by ofile is filled in. If this call fails it returns 0
824 * and calls error routines to print error messages and clears the
825 * ofile structure pointed to by ofile.
829 NSObjectFileImageReturnCode
834 const char *file_name
,
835 const struct arch_flag
*arch_flag
, /* can be NULL */
836 const char *object_name
, /* can be NULL */
838 enum bool archives_with_fat_objects
)
841 struct stat stat_buf
;
846 magic
= 0; /* to shut up the compiler warning message */
847 memset(ofile
, '\0', sizeof(struct ofile
));
849 /* Open the file and map it in */
850 if((fd
= open(file_name
, O_RDONLY
)) == -1){
852 return(NSObjectFileImageAccess
);
854 system_error("can't open file: %s", file_name
);
858 if(fstat(fd
, &stat_buf
) == -1){
861 return(NSObjectFileImageAccess
);
863 system_error("can't stat file: %s", file_name
);
867 size
= stat_buf
.st_size
;
871 addr
= mmap(0, size
, PROT_READ
|PROT_WRITE
, MAP_FILE
|MAP_PRIVATE
, fd
,
873 if((intptr_t)addr
== -1){
874 system_error("can't map file: %s", file_name
);
881 if(otool_first_ofile_map
&& Wflag
)
882 printf("Modification time = %ld\n", (long int)stat_buf
.st_mtime
);
885 return(ofile_map_from_memory(addr
, size
, file_name
, stat_buf
.st_mtime
,
886 arch_flag
, object_name
, ofile
, archives_with_fat_objects
));
890 * ofile_map_from_memory() is the guts of ofile_map() but with an interface
891 * to pass the address and size of the file already mapped in.
895 NSObjectFileImageReturnCode
899 ofile_map_from_memory(
902 const char *file_name
,
904 const struct arch_flag
*arch_flag
, /* can be NULL */
905 const char *object_name
, /* can be NULL */
907 enum bool archives_with_fat_objects
)
911 enum byte_sex host_byte_sex
;
912 struct arch_flag host_arch_flag
;
914 const struct arch_flag
*family_arch_flag
;
917 uint32_t small_nfat_arch
;
922 /* fill in the start of the ofile structure */
923 ofile
->file_name
= savestr(file_name
);
924 if(ofile
->file_name
== NULL
)
926 ofile
->file_addr
= addr
;
927 ofile
->file_size
= size
;
928 ofile
->file_mtime
= mtime
;
930 /* Try to figure out what kind of file this is */
932 if(size
>= sizeof(uint32_t)){
933 magic
= *((uint32_t *)addr
);
935 host_byte_sex
= get_host_byte_sex();
937 /* see if this file is a fat file (always in big endian byte sex) */
938 #ifdef __BIG_ENDIAN__
939 if(size
>= sizeof(struct fat_header
) &&
940 (magic
== FAT_MAGIC
|| magic
== FAT_MAGIC_64
))
941 #endif /* __BIG_ENDIAN__ */
942 #ifdef __LITTLE_ENDIAN__
943 if(size
>= sizeof(struct fat_header
) &&
944 (SWAP_INT(magic
) == FAT_MAGIC
|| SWAP_INT(magic
) == FAT_MAGIC_64
))
945 #endif /* __LITTLE_ENDIAN__ */
947 ofile
->file_type
= OFILE_FAT
;
948 ofile
->fat_header
= (struct fat_header
*)addr
;
949 #ifdef __LITTLE_ENDIAN__
950 swap_fat_header(ofile
->fat_header
, host_byte_sex
);
951 #endif /* __LITTLE_ENDIAN__ */
953 if(otool_first_ofile_map
&& fflag
)
954 printf("Fat headers\n");
956 big_size
= ofile
->fat_header
->nfat_arch
;
957 if(ofile
->fat_header
->magic
== FAT_MAGIC_64
)
958 big_size
*= sizeof(struct fat_arch_64
);
960 big_size
*= sizeof(struct fat_arch
);
961 big_size
+= sizeof(struct fat_header
);
964 error("fat file: %s truncated or malformed (fat_arch%s structs "
965 "would extend past the end of the file)", file_name
,
966 ofile
->fat_header
->magic
== FAT_MAGIC_64
? "_64" : "");
967 if(ofile
->fat_header
->magic
== FAT_MAGIC_64
){
968 ofile
->fat_archs64
= allocate(size
-
969 sizeof(struct fat_header
));
970 memset(ofile
->fat_archs64
, '\0',
971 size
- sizeof(struct fat_header
));
972 memcpy(ofile
->fat_archs64
,
973 addr
+ sizeof(struct fat_header
),
974 size
- sizeof(struct fat_header
));
975 small_nfat_arch
= (size
- sizeof(struct fat_header
)) /
976 sizeof(struct fat_arch_64
);
977 #ifdef __LITTLE_ENDIAN__
978 swap_fat_arch_64(ofile
->fat_archs64
, small_nfat_arch
,
980 #endif /* __LITTLE_ENDIAN__ */
983 ofile
->fat_archs
= allocate(size
-
984 sizeof(struct fat_header
));
985 memset(ofile
->fat_archs
, '\0',
986 size
- sizeof(struct fat_header
));
987 memcpy(ofile
->fat_archs
,
988 addr
+ sizeof(struct fat_header
),
989 size
- sizeof(struct fat_header
));
990 small_nfat_arch
= (size
- sizeof(struct fat_header
)) /
991 sizeof(struct fat_arch
);
992 #ifdef __LITTLE_ENDIAN__
993 swap_fat_arch(ofile
->fat_archs
, small_nfat_arch
,
995 #endif /* __LITTLE_ENDIAN__ */
997 if(otool_first_ofile_map
&& fflag
)
998 print_fat_headers(ofile
->fat_header
, ofile
->fat_archs
,
999 ofile
->fat_archs64
, size
, vflag
);
1000 if(ofile
->fat_header
->magic
== FAT_MAGIC_64
)
1001 free(ofile
->fat_archs64
);
1003 free(ofile
->fat_archs
);
1006 #else /* !defined(OTOOL) */
1010 if(ofile
->fat_header
->magic
== FAT_MAGIC_64
){
1011 ofile
->fat_archs64
= (struct fat_arch_64
*)
1012 (addr
+ sizeof(struct fat_header
));
1013 #ifdef __LITTLE_ENDIAN__
1014 swap_fat_arch_64(ofile
->fat_archs64
,
1015 ofile
->fat_header
->nfat_arch
, host_byte_sex
);
1016 #endif /* __LITTLE_ENDIAN__ */
1019 ofile
->fat_archs
= (struct fat_arch
*)
1020 (addr
+ sizeof(struct fat_header
));
1021 #ifdef __LITTLE_ENDIAN__
1022 swap_fat_arch(ofile
->fat_archs
, ofile
->fat_header
->nfat_arch
,
1024 #endif /* __LITTLE_ENDIAN__ */
1027 if(otool_first_ofile_map
&& fflag
)
1028 print_fat_headers(ofile
->fat_header
, ofile
->fat_archs
,
1029 ofile
->fat_archs64
, size
, vflag
);
1031 if(check_fat(ofile
) == CHECK_BAD
){
1034 return(NSObjectFileImageFormat
);
1040 * Now that the fat file is mapped fill in the ofile to the level
1041 * the caller wants based on the arch_flag and object_name passed.
1042 * If the caller did not specify an arch_flag or an object_name
1043 * then everything the caller wants is done.
1045 if(arch_flag
== NULL
&& object_name
== NULL
)
1047 if(arch_flag
== NULL
){
1048 if(get_arch_from_host(&host_arch_flag
, NULL
) == 0){
1049 error("can't determine the host architecture (specify an "
1050 "arch_flag or fix get_arch_from_host() )");
1053 ofile
->arch_flag
.name
= savestr(host_arch_flag
.name
);
1054 if(ofile
->arch_flag
.name
== NULL
)
1056 ofile
->arch_flag
.cputype
= host_arch_flag
.cputype
;
1057 ofile
->arch_flag
.cpusubtype
= host_arch_flag
.cpusubtype
;
1060 ofile
->arch_flag
.name
= savestr(arch_flag
->name
);
1061 if(ofile
->arch_flag
.name
== NULL
)
1063 ofile
->arch_flag
.cputype
= arch_flag
->cputype
;
1064 ofile
->arch_flag
.cpusubtype
= arch_flag
->cpusubtype
;
1067 ofile
->narch
= UINT_MAX
;
1068 for(i
= 0; i
< ofile
->fat_header
->nfat_arch
; i
++){
1069 if(ofile
->fat_header
->magic
== FAT_MAGIC_64
){
1070 if(ofile
->fat_archs64
[i
].cputype
==
1071 ofile
->arch_flag
.cputype
&&
1072 (ofile
->fat_archs64
[i
].cpusubtype
& ~CPU_SUBTYPE_MASK
) ==
1073 (ofile
->arch_flag
.cpusubtype
& ~CPU_SUBTYPE_MASK
)){
1079 if(ofile
->fat_archs
[i
].cputype
==
1080 ofile
->arch_flag
.cputype
&&
1081 (ofile
->fat_archs
[i
].cpusubtype
& ~CPU_SUBTYPE_MASK
) ==
1082 (ofile
->arch_flag
.cpusubtype
& ~CPU_SUBTYPE_MASK
)){
1088 if(ofile
->narch
== UINT_MAX
){
1091 get_arch_family_from_cputype(ofile
->arch_flag
.cputype
);
1092 if(family_arch_flag
!= NULL
)
1093 family
= (enum bool)
1094 ((family_arch_flag
->cpusubtype
& ~CPU_SUBTYPE_MASK
) ==
1095 (ofile
->arch_flag
.cpusubtype
& ~CPU_SUBTYPE_MASK
));
1096 ofile
->narch
= UINT_MAX
;
1097 for(i
= 0; i
< ofile
->fat_header
->nfat_arch
; i
++){
1098 if(ofile
->fat_header
->magic
== FAT_MAGIC_64
){
1099 if(ofile
->fat_archs64
[i
].cputype
==
1100 ofile
->arch_flag
.cputype
&&
1102 (ofile
->fat_archs64
[i
].cpusubtype
&
1103 ~CPU_SUBTYPE_MASK
) ==
1104 (ofile
->arch_flag
.cpusubtype
&
1105 ~CPU_SUBTYPE_MASK
))){
1106 ofile
->arch_flag
.cpusubtype
=
1107 ofile
->fat_archs64
[i
].cpusubtype
;
1113 if(ofile
->fat_archs
[i
].cputype
==
1114 ofile
->arch_flag
.cputype
&&
1116 (ofile
->fat_archs
[i
].cpusubtype
&
1117 ~CPU_SUBTYPE_MASK
) ==
1118 (ofile
->arch_flag
.cpusubtype
&
1119 ~CPU_SUBTYPE_MASK
))){
1120 ofile
->arch_flag
.cpusubtype
=
1121 ofile
->fat_archs
[i
].cpusubtype
;
1128 if(ofile
->narch
== UINT_MAX
){
1131 return(NSObjectFileImageArch
);
1133 error("fat file: %s does not contain architecture %s",
1134 ofile
->file_name
, arch_flag
->name
);
1139 /* Now determine the file type for this specific architecture */
1140 if(ofile
->fat_header
->magic
== FAT_MAGIC_64
){
1141 size
= ofile
->fat_archs64
[i
].size
;
1142 addr
= addr
+ ofile
->fat_archs64
[i
].offset
;
1143 offset
= ofile
->fat_archs64
[i
].offset
;
1144 align
= ofile
->fat_archs64
[i
].align
;
1147 size
= ofile
->fat_archs
[i
].size
;
1148 addr
= addr
+ ofile
->fat_archs
[i
].offset
;
1149 offset
= ofile
->fat_archs
[i
].offset
;
1150 align
= ofile
->fat_archs
[i
].align
;
1152 if(size
>= sizeof(struct mach_header
))
1153 memcpy(&magic
, addr
, sizeof(uint32_t));
1154 /* see if this file is a 32-bit Mach-O file */
1155 if(size
>= sizeof(struct mach_header
) &&
1156 (magic
== MH_MAGIC
||
1157 magic
== SWAP_INT(MH_MAGIC
))){
1158 #ifdef ALIGNMENT_CHECKS
1159 if(offset
% 4 != 0){
1160 error("fat file: %s architecture %s malformed for a 32-bit "
1161 "object file (offset is not a multiple of 4)",
1162 ofile
->file_name
, arch_flag
->name
);
1165 return(NSObjectFileImageFormat
);
1170 #endif /* ALIGNMENT_CHECKS */
1171 ofile
->arch_type
= OFILE_Mach_O
;
1172 ofile
->object_addr
= addr
;
1173 ofile
->object_size
= size
;
1174 if(magic
== MH_MAGIC
)
1175 ofile
->object_byte_sex
= host_byte_sex
;
1177 ofile
->object_byte_sex
=
1178 host_byte_sex
== BIG_ENDIAN_BYTE_SEX
?
1179 LITTLE_ENDIAN_BYTE_SEX
: BIG_ENDIAN_BYTE_SEX
;
1180 ofile
->mh
= (struct mach_header
*)addr
;
1181 ofile
->load_commands
= (struct load_command
*)(addr
+
1182 sizeof(struct mach_header
));
1183 if(check_Mach_O(ofile
) == CHECK_BAD
){
1186 return(NSObjectFileImageFormat
);
1191 if(object_name
!= NULL
){
1192 error("fat file: %s architecture %s is not an archive "
1193 "(object_name to ofile_map() can't be specified to "
1194 "be other than NULL)", ofile
->file_name
,
1199 /* see if this file is a 64-bit Mach-O file */
1200 else if(size
>= sizeof(struct mach_header_64
) &&
1201 (magic
== MH_MAGIC_64
||
1202 magic
== SWAP_INT(MH_MAGIC_64
))){
1203 #ifdef ALIGNMENT_CHECKS
1204 if(offset
% 8 != 0){
1205 error("fat file: %s architecture %s malformed for a 64-bit "
1206 "object file (offset is not a multiple of 8)",
1207 ofile
->file_name
, arch_flag
->name
);
1210 return(NSObjectFileImageFormat
);
1215 #endif /* ALIGNMENT_CHECKS */
1216 ofile
->arch_type
= OFILE_Mach_O
;
1217 ofile
->object_addr
= addr
;
1218 ofile
->object_size
= size
;
1219 if(magic
== MH_MAGIC_64
)
1220 ofile
->object_byte_sex
= host_byte_sex
;
1222 ofile
->object_byte_sex
=
1223 host_byte_sex
== BIG_ENDIAN_BYTE_SEX
?
1224 LITTLE_ENDIAN_BYTE_SEX
: BIG_ENDIAN_BYTE_SEX
;
1225 ofile
->mh64
= (struct mach_header_64
*)addr
;
1226 ofile
->load_commands
= (struct load_command
*)(addr
+
1227 sizeof(struct mach_header_64
));
1228 if(check_Mach_O(ofile
) == CHECK_BAD
){
1231 return(NSObjectFileImageFormat
);
1236 if(object_name
!= NULL
){
1237 error("fat file: %s architecture %s is not an archive "
1238 "(object_name to ofile_map() can't be specified to "
1239 "be other than NULL)", ofile
->file_name
,
1244 /* see if this file is an archive file */
1245 else if(size
>= SARMAG
&& strncmp(addr
, ARMAG
, SARMAG
) == 0){
1246 ofile
->arch_type
= OFILE_ARCHIVE
;
1247 if(check_archive(ofile
, FALSE
) == CHECK_BAD
){
1250 return(NSObjectFileImageInappropriateFile
);
1255 #ifdef ALIGNMENT_CHECKS
1256 if(ofile
->archive_cputype
!= 0 &&
1257 offset
% sizeof(uint32_t) != 0){
1258 error("fat file: %s architecture %s malformed archive that "
1259 "contains object files (offset to archive is not a "
1260 "multiple of sizeof(uint32_t))",
1261 ofile
->file_name
, arch_flag
->name
);
1264 return(NSObjectFileImageInappropriateFile
);
1269 #endif /* ALIGNMENT_CHECKS */
1270 if(object_name
!= NULL
){
1271 if(ofile_specific_member(object_name
, ofile
) == FALSE
)
1275 /* this file type is now known to be unknown to this program */
1277 ofile
->file_type
= OFILE_UNKNOWN
;
1278 if(object_name
!= NULL
){
1279 error("fat file: %s architecture %s is not an archive "
1280 "(object_name to ofile_map() can't be specified to "
1281 "be other than NULL)", ofile
->file_name
,
1287 /* see if this file is a 32-bit Mach-O file */
1288 else if(size
>= sizeof(struct mach_header
) &&
1289 (magic
== MH_MAGIC
||
1290 magic
== SWAP_INT(MH_MAGIC
))){
1291 ofile
->file_type
= OFILE_Mach_O
;
1292 ofile
->object_addr
= addr
;
1293 ofile
->object_size
= size
;
1294 if(magic
== MH_MAGIC
)
1295 ofile
->object_byte_sex
= host_byte_sex
;
1297 ofile
->object_byte_sex
= host_byte_sex
== BIG_ENDIAN_BYTE_SEX
?
1298 LITTLE_ENDIAN_BYTE_SEX
: BIG_ENDIAN_BYTE_SEX
;
1299 ofile
->mh
= (struct mach_header
*)addr
;
1300 ofile
->load_commands
= (struct load_command
*)(addr
+
1301 sizeof(struct mach_header
));
1302 if(check_Mach_O(ofile
) == CHECK_BAD
){
1305 return(NSObjectFileImageFormat
);
1310 if(object_name
!= NULL
){
1311 error("file: %s is not an archive (object_name to ofile_map() "
1312 "can't be specified to be other than NULL)",
1316 if(arch_flag
!= NULL
){
1317 if(arch_flag
->cputype
!= ofile
->mh_cputype
&&
1318 (arch_flag
->cpusubtype
& ~CPU_SUBTYPE_MASK
) !=
1319 (ofile
->mh_cpusubtype
& ~CPU_SUBTYPE_MASK
)){
1322 return(NSObjectFileImageArch
);
1324 error("object file: %s does not match specified arch_flag: "
1325 "%s passed to ofile_map()", ofile
->file_name
,
1334 /* see if this file is a 64-bit Mach-O file */
1335 else if(size
>= sizeof(struct mach_header_64
) &&
1336 (magic
== MH_MAGIC_64
||
1337 magic
== SWAP_INT(MH_MAGIC_64
))){
1338 ofile
->file_type
= OFILE_Mach_O
;
1339 ofile
->object_addr
= addr
;
1340 ofile
->object_size
= size
;
1341 if(magic
== MH_MAGIC_64
)
1342 ofile
->object_byte_sex
= host_byte_sex
;
1344 ofile
->object_byte_sex
= host_byte_sex
== BIG_ENDIAN_BYTE_SEX
?
1345 LITTLE_ENDIAN_BYTE_SEX
: BIG_ENDIAN_BYTE_SEX
;
1346 ofile
->mh64
= (struct mach_header_64
*)addr
;
1347 ofile
->load_commands
= (struct load_command
*)(addr
+
1348 sizeof(struct mach_header_64
));
1349 if(check_Mach_O(ofile
) == CHECK_BAD
){
1352 return(NSObjectFileImageFormat
);
1357 if(object_name
!= NULL
){
1358 error("file: %s is not an archive (object_name to ofile_map() "
1359 "can't be specified to be other than NULL)",
1363 if(arch_flag
!= NULL
){
1364 if(arch_flag
->cputype
!= ofile
->mh_cputype
&&
1365 (arch_flag
->cpusubtype
& ~CPU_SUBTYPE_MASK
) !=
1366 (ofile
->mh_cpusubtype
& ~CPU_SUBTYPE_MASK
)){
1369 return(NSObjectFileImageArch
);
1371 error("object file: %s does not match specified arch_flag: "
1372 "%s passed to ofile_map()", ofile
->file_name
,
1381 /* see if this file is an archive file */
1382 else if(size
>= SARMAG
&& strncmp(addr
, ARMAG
, SARMAG
) == 0){
1383 ofile
->file_type
= OFILE_ARCHIVE
;
1384 if(check_archive(ofile
, archives_with_fat_objects
) == CHECK_BAD
)
1386 if(object_name
!= NULL
){
1387 if(ofile_specific_member(object_name
, ofile
) == FALSE
)
1389 if(arch_flag
!= NULL
){
1390 if(arch_flag
->cputype
!= ofile
->mh_cputype
&&
1391 (arch_flag
->cpusubtype
& ~CPU_SUBTYPE_MASK
) !=
1392 (ofile
->mh_cpusubtype
& ~CPU_SUBTYPE_MASK
)){
1393 error("object file: %s(%.*s) does not match specified "
1394 "arch_flag: %s passed to ofile_map()",
1395 ofile
->file_name
, (int)ofile
->member_name_size
,
1396 ofile
->member_name
, arch_flag
->name
);
1402 if(arch_flag
!= NULL
){
1403 if(arch_flag
->cputype
!= ofile
->archive_cputype
&&
1404 (arch_flag
->cpusubtype
& ~CPU_SUBTYPE_MASK
) !=
1405 (ofile
->archive_cpusubtype
& ~CPU_SUBTYPE_MASK
)){
1406 error("archive file: %s objects do not match specified "
1407 "arch_flag: %s passed to ofile_map()",
1408 ofile
->file_name
, arch_flag
->name
);
1414 /* this file type is now known to be unknown to this program */
1421 if(is_llvm_bitcode(ofile
, ofile
->file_addr
, ofile
->file_size
) ==
1423 ofile
->file_type
= OFILE_LLVM_BITCODE
;
1424 if(arch_flag
!= NULL
){
1425 if(arch_flag
->cputype
!= ofile
->lto_cputype
&&
1426 (arch_flag
->cpusubtype
& ~CPU_SUBTYPE_MASK
) !=
1427 (ofile
->lto_cpusubtype
& ~CPU_SUBTYPE_MASK
)){
1428 error("llvm bitcode file: %s does not match specified "
1429 "arch_flag: %s passed to ofile_map()",
1430 ofile
->file_name
, arch_flag
->name
);
1434 if(object_name
!= NULL
){
1435 error("file: %s is not an archive (object_name to "
1436 "ofile_map() can't be specified to be other than "
1437 "NULL)", ofile
->file_name
);
1443 #endif /* LTO_SUPPORT */
1445 ofile
->file_type
= OFILE_UNKNOWN
;
1446 if(arch_flag
!= NULL
){
1449 return(NSObjectFileImageInappropriateFile
);
1451 error("file: %s is unknown type (arch_flag to ofile_map() "
1452 "can't be specified to be other than NULL)",
1458 if(object_name
!= NULL
){
1459 error("file: %s is not an archive (object_name to ofile_map() "
1460 "can't be specified to be other than NULL)",
1474 * ofile_unmap() deallocates the memory associated with the specified ofile
1480 struct ofile
*ofile
)
1484 if(ofile
->file_addr
!= NULL
){
1485 if((r
= vm_deallocate(mach_task_self(),
1486 (vm_address_t
)ofile
->file_addr
,
1487 (vm_size_t
)ofile
->file_size
)) != KERN_SUCCESS
){
1488 my_mach_error(r
, "Can't vm_deallocate mapped memory for file: "
1489 "%s", ofile
->file_name
);
1492 if(ofile
->file_name
!= NULL
)
1493 free(ofile
->file_name
);
1494 if(ofile
->arch_flag
.name
!= NULL
)
1495 free(ofile
->arch_flag
.name
);
1496 memset(ofile
, '\0', sizeof(struct ofile
));
1500 * ofile_first_arch() sets up the ofile struct for a fat file to the first arch
1506 struct ofile
*ofile
)
1508 if(ofile
->file_type
== OFILE_FAT
||
1509 (ofile
->file_type
== OFILE_ARCHIVE
&&
1510 ofile
->member_type
== OFILE_FAT
) )
1511 return(ofile_specific_arch(ofile
, 0));
1513 error("ofile_first_arch() called and file type of: %s is not a fat "
1514 "file\n", ofile
->file_name
);
1520 * ofile_next_arch() sets up the ofile struct for a fat file to the next arch
1526 struct ofile
*ofile
)
1528 if(ofile
->file_type
== OFILE_FAT
||
1529 (ofile
->file_type
== OFILE_ARCHIVE
&&
1530 ofile
->member_type
== OFILE_FAT
) ){
1531 if(ofile
->narch
+ 1 < ofile
->fat_header
->nfat_arch
)
1532 return(ofile_specific_arch(ofile
, ofile
->narch
+ 1));
1537 error("ofile_next_arch() called and file type of: %s is not a fat "
1538 "file\n", ofile
->file_name
);
1544 * ofile_specific_arch() sets up the ofile struct for the fat file for the
1549 ofile_specific_arch(
1550 struct ofile
*ofile
,
1554 uint64_t size
, offset
;
1556 enum byte_sex host_byte_sex
;
1558 ofile
->narch
= narch
;
1559 ofile
->arch_type
= OFILE_UNKNOWN
;
1560 if(ofile
->arch_flag
.name
!= NULL
)
1561 free(ofile
->arch_flag
.name
);
1562 ofile
->arch_flag
.name
= NULL
;
1563 ofile
->arch_flag
.cputype
= 0;
1564 ofile
->arch_flag
.cpusubtype
= 0;
1565 ofile
->archive_cputype
= 0;
1566 ofile
->archive_cpusubtype
= 0;
1567 ofile
->object_addr
= NULL
;
1568 ofile
->object_size
= 0;
1569 ofile
->object_byte_sex
= UNKNOWN_BYTE_SEX
;
1572 ofile
->load_commands
= NULL
;
1574 if(ofile
->fat_header
->magic
== FAT_MAGIC_64
){
1575 ofile
->arch_flag
.cputype
=
1576 ofile
->fat_archs64
[ofile
->narch
].cputype
;
1577 ofile
->arch_flag
.cpusubtype
=
1578 ofile
->fat_archs64
[ofile
->narch
].cpusubtype
;
1581 ofile
->arch_flag
.cputype
=
1582 ofile
->fat_archs
[ofile
->narch
].cputype
;
1583 ofile
->arch_flag
.cpusubtype
=
1584 ofile
->fat_archs
[ofile
->narch
].cpusubtype
;
1586 set_arch_flag_name(&(ofile
->arch_flag
));
1589 /* Now determine the file type for this specific architecture */
1590 if(ofile
->file_type
== OFILE_FAT
){
1591 ofile
->member_offset
= 0;
1592 ofile
->member_addr
= NULL
;
1593 ofile
->member_size
= 0;
1594 ofile
->member_ar_hdr
= NULL
;
1595 ofile
->member_type
= OFILE_UNKNOWN
;
1597 if(ofile
->fat_header
->magic
== FAT_MAGIC_64
){
1598 size
= ofile
->fat_archs64
[ofile
->narch
].size
;
1599 addr
= ofile
->file_addr
+
1600 ofile
->fat_archs64
[ofile
->narch
].offset
;
1603 size
= ofile
->fat_archs
[ofile
->narch
].size
;
1604 addr
= ofile
->file_addr
+
1605 ofile
->fat_archs
[ofile
->narch
].offset
;
1609 if(ofile
->file_type
!= OFILE_ARCHIVE
||
1610 ofile
->member_type
!= OFILE_FAT
){
1611 error("internal error. ofile_specific_arch() called but file "
1612 "is not a fat file or an archive with a fat member ");
1614 if(ofile
->fat_header
->magic
== FAT_MAGIC_64
){
1615 size
= ofile
->fat_archs64
[ofile
->narch
].size
;
1616 addr
= ofile
->file_addr
+
1617 ofile
->member_offset
+
1618 ofile
->fat_archs64
[ofile
->narch
].offset
;
1621 size
= ofile
->fat_archs
[ofile
->narch
].size
;
1622 addr
= ofile
->file_addr
+
1623 ofile
->member_offset
+
1624 ofile
->fat_archs
[ofile
->narch
].offset
;
1629 if(addr
- ofile
->file_addr
> (ptrdiff_t)ofile
->file_size
){
1630 error("fat file: %s offset to architecture %s extends past end "
1631 "of file", ofile
->file_name
, ofile
->arch_flag
.name
);
1634 if(addr
+ size
> ofile
->file_addr
+ ofile
->file_size
)
1635 size
= (ofile
->file_addr
+ ofile
->file_size
) - addr
;
1637 if(ofile
->fat_header
->magic
== FAT_MAGIC_64
)
1638 offset
= ofile
->fat_archs64
[ofile
->narch
].offset
;
1640 offset
= ofile
->fat_archs
[ofile
->narch
].offset
;
1642 if(size
>= sizeof(struct mach_header
))
1643 memcpy(&magic
, addr
, sizeof(uint32_t));
1644 /* see if this file is a 32-bit Mach-O file */
1645 if(size
>= sizeof(struct mach_header
) &&
1646 (magic
== MH_MAGIC
|| magic
== SWAP_INT(MH_MAGIC
))){
1647 #ifdef ALIGNMENT_CHECKS
1648 if(offset
% 4 != 0){
1649 if(ofile
->file_type
== OFILE_ARCHIVE
){
1650 error("fat file: %s(%.*s) architecture %s malformed for a "
1651 "32-bit object file (offset is not a multiple of 4)",
1652 ofile
->file_name
, (int)ofile
->member_name_size
,
1653 ofile
->member_name
, ofile
->arch_flag
.name
);
1656 error("fat file: %s architecture %s malformed for a 32-bit "
1657 "object file (offset is not a multiple of 4)",
1658 ofile
->file_name
, ofile
->arch_flag
.name
);
1661 #endif /* ALIGNMENT_CHECKS */
1662 ofile
->arch_type
= OFILE_Mach_O
;
1663 ofile
->object_addr
= addr
;
1664 ofile
->object_size
= size
;
1665 host_byte_sex
= get_host_byte_sex();
1666 if(magic
== MH_MAGIC
)
1667 ofile
->object_byte_sex
= host_byte_sex
;
1669 ofile
->object_byte_sex
=
1670 host_byte_sex
== BIG_ENDIAN_BYTE_SEX
?
1671 LITTLE_ENDIAN_BYTE_SEX
: BIG_ENDIAN_BYTE_SEX
;
1672 ofile
->mh
= (struct mach_header
*)addr
;
1673 ofile
->load_commands
= (struct load_command
*)(addr
+
1674 sizeof(struct mach_header
));
1675 if(check_Mach_O(ofile
) == CHECK_BAD
)
1678 /* see if this file is a 64-bit Mach-O file */
1679 else if(size
>= sizeof(struct mach_header_64
) &&
1680 (magic
== MH_MAGIC_64
|| magic
== SWAP_INT(MH_MAGIC_64
))){
1681 #ifdef ALIGNMENT_CHECKS
1682 if(offset
% 8 != 0){
1683 if(ofile
->file_type
== OFILE_ARCHIVE
){
1684 error("fat file: %s(%.*s) architecture %s malformed for an "
1685 "object file (offset is not a multiple of 8)",
1686 ofile
->file_name
, (int)ofile
->member_name_size
,
1687 ofile
->member_name
, ofile
->arch_flag
.name
);
1690 error("fat file: %s architecture %s malformed for a 64-bit "
1691 "object file (offset is not a multiple of 8",
1692 ofile
->file_name
, ofile
->arch_flag
.name
);
1695 #endif /* ALIGNMENT_CHECKS */
1696 ofile
->arch_type
= OFILE_Mach_O
;
1697 ofile
->object_addr
= addr
;
1698 ofile
->object_size
= size
;
1699 host_byte_sex
= get_host_byte_sex();
1700 if(magic
== MH_MAGIC_64
)
1701 ofile
->object_byte_sex
= host_byte_sex
;
1703 ofile
->object_byte_sex
=
1704 host_byte_sex
== BIG_ENDIAN_BYTE_SEX
?
1705 LITTLE_ENDIAN_BYTE_SEX
: BIG_ENDIAN_BYTE_SEX
;
1706 ofile
->mh64
= (struct mach_header_64
*)addr
;
1707 ofile
->load_commands
= (struct load_command
*)(addr
+
1708 sizeof(struct mach_header_64
));
1709 if(check_Mach_O(ofile
) == CHECK_BAD
)
1712 /* see if this file is an archive file */
1713 else if(size
>= SARMAG
&& strncmp(addr
, ARMAG
, SARMAG
) == 0){
1714 ofile
->arch_type
= OFILE_ARCHIVE
;
1715 if(check_archive(ofile
, FALSE
) == CHECK_BAD
)
1717 #ifdef ALIGNMENT_CHECKS
1718 if(ofile
->archive_cputype
!= 0 && offset
% sizeof(uint32_t) != 0){
1719 error("fat file: %s architecture %s malformed archive that "
1720 "contains object files (offset to archive is not a "
1721 "multiple of sizeof(uint32_t))",
1722 ofile
->file_name
, ofile
->arch_flag
.name
);
1725 #endif /* ALIGNMENT_CHECKS */
1728 * This type for this architecture is now known to be unknown to this
1733 if(is_llvm_bitcode(ofile
, addr
, size
) == TRUE
){
1734 ofile
->arch_type
= OFILE_LLVM_BITCODE
;
1735 ofile
->object_addr
= addr
;
1736 ofile
->object_size
= size
;
1739 #endif /* LTO_SUPPORT */
1740 ofile
->arch_type
= OFILE_UNKNOWN
;
1745 ofile
->arch_type
= OFILE_UNKNOWN
;
1746 if(ofile
->arch_flag
.name
!= NULL
)
1747 free(ofile
->arch_flag
.name
);
1748 ofile
->arch_flag
.name
= NULL
;
1749 ofile
->arch_flag
.cputype
= 0;
1750 ofile
->arch_flag
.cpusubtype
= 0;
1751 if(ofile
->file_type
!= OFILE_ARCHIVE
){
1752 ofile
->member_offset
= 0;
1753 ofile
->member_addr
= NULL
;
1754 ofile
->member_size
= 0;
1755 ofile
->member_ar_hdr
= NULL
;
1756 ofile
->member_type
= OFILE_UNKNOWN
;
1758 ofile
->archive_cputype
= 0;
1759 ofile
->archive_cpusubtype
= 0;
1760 ofile
->object_addr
= NULL
;
1761 ofile
->object_size
= 0;
1762 ofile
->object_byte_sex
= UNKNOWN_BYTE_SEX
;
1765 ofile
->load_commands
= NULL
;
1770 * ofile_first_member() set up the ofile structure (the member_* fields and
1771 * the object file fields if the first member is an object file) for the first
1777 struct ofile
*ofile
)
1780 uint64_t size
, offset
;
1782 enum byte_sex host_byte_sex
;
1783 struct ar_hdr
*ar_hdr
;
1784 uint32_t ar_name_size
;
1785 uint32_t sizeof_fat_archs
;
1787 /* These fields are to be filled in by this routine, clear them first */
1788 ofile
->member_offset
= 0;
1789 ofile
->member_addr
= NULL
;
1790 ofile
->member_size
= 0;
1791 ofile
->member_ar_hdr
= NULL
;
1792 ofile
->member_name
= NULL
;
1793 ofile
->member_name_size
= 0;
1794 ofile
->member_type
= OFILE_UNKNOWN
;
1795 ofile
->object_addr
= NULL
;
1796 ofile
->object_size
= 0;
1797 ofile
->object_byte_sex
= UNKNOWN_BYTE_SEX
;
1800 ofile
->load_commands
= NULL
;
1803 * Note: it is up to the caller if they want to call free_lto() on this
1804 * when iterating through the members of an archive.
1807 #endif /* LTO_SUPPORT */
1810 * Get the address and size of the archive.
1812 if(ofile
->file_type
== OFILE_FAT
){
1813 if(ofile
->arch_type
!= OFILE_ARCHIVE
){
1814 error("ofile_first_member() called on fat file: %s with a "
1815 "non-archive architecture or no architecture selected\n",
1819 if(ofile
->fat_header
->magic
== FAT_MAGIC_64
){
1820 addr
= ofile
->file_addr
+
1821 ofile
->fat_archs64
[ofile
->narch
].offset
;
1822 size
= ofile
->fat_archs64
[ofile
->narch
].size
;
1825 addr
= ofile
->file_addr
+
1826 ofile
->fat_archs
[ofile
->narch
].offset
;
1827 size
= ofile
->fat_archs
[ofile
->narch
].size
;
1830 else if(ofile
->file_type
== OFILE_ARCHIVE
){
1831 addr
= ofile
->file_addr
;
1832 size
= ofile
->file_size
;
1835 error("ofile_first_member() called and file type of %s is "
1836 "OFILE_UNKNOWN\n", ofile
->file_name
);
1840 if((addr
+ SARMAG
) - ofile
->file_addr
> (ptrdiff_t)ofile
->file_size
){
1841 archive_error(ofile
, "offset to first member extends past the end "
1845 if(addr
+ size
> ofile
->file_addr
+ ofile
->file_size
)
1846 size
= (ofile
->file_addr
+ ofile
->file_size
) - addr
;
1848 if(size
< SARMAG
|| strncmp(addr
, ARMAG
, SARMAG
) != 0){
1849 archive_error(ofile
, "internal error. ofile_first_member() "
1850 "called but file does not have an archive magic "
1856 if(offset
!= size
&& offset
+ sizeof(struct ar_hdr
) > size
){
1857 archive_error(ofile
, "truncated or malformed (archive header of "
1858 "first member extends past the end of the file)");
1862 /* check for empty archive */
1866 /* now we know there is a first member so set it up */
1867 ar_hdr
= (struct ar_hdr
*)(addr
+ offset
);
1868 offset
+= sizeof(struct ar_hdr
);
1869 ofile
->member_offset
= offset
;
1870 ofile
->member_addr
= addr
+ offset
;
1871 ofile
->member_size
= strtoul(ar_hdr
->ar_size
, NULL
, 10);
1872 if(ofile
->member_size
> size
- sizeof(struct ar_hdr
)){
1873 archive_error(ofile
, "size of first archive member extends past "
1874 "the end of the archive");
1875 ofile
->member_size
= size
- sizeof(struct ar_hdr
);
1877 ofile
->member_ar_hdr
= ar_hdr
;
1878 ofile
->member_type
= OFILE_UNKNOWN
;
1879 ofile
->member_name
= ar_hdr
->ar_name
;
1880 if(strncmp(ofile
->member_name
, AR_EFMT1
, sizeof(AR_EFMT1
) - 1) == 0){
1881 ofile
->member_name
= ar_hdr
->ar_name
+ sizeof(struct ar_hdr
);
1882 ar_name_size
= strtoul(ar_hdr
->ar_name
+ sizeof(AR_EFMT1
) - 1,
1884 if(ar_name_size
> ofile
->member_size
){
1885 archive_error(ofile
, "size of first archive member name "
1886 "extends past the end of the archive");
1887 ar_name_size
= ofile
->member_size
;
1889 ofile
->member_name_size
= ar_name_size
;
1890 ofile
->member_offset
+= ar_name_size
;
1891 ofile
->member_addr
+= ar_name_size
;
1892 ofile
->member_size
-= ar_name_size
;
1895 ofile
->member_name_size
= size_ar_name(ar_hdr
);
1898 /* Clear these in case there is no table of contents */
1899 ofile
->toc_addr
= NULL
;
1900 ofile
->toc_size
= 0;
1901 ofile
->toc_ar_hdr
= NULL
;
1902 ofile
->toc_name
= NULL
;
1903 ofile
->toc_name_size
= 0;
1904 ofile
->toc_ranlibs
= NULL
;
1905 ofile
->toc_ranlibs64
= NULL
;
1906 ofile
->toc_nranlibs
= 0;
1907 ofile
->toc_strings
= NULL
;
1908 ofile
->toc_strsize
= 0;
1909 ofile
->toc_bad
= FALSE
;
1911 /* Clear these until we find a System V "//" named archive member */
1912 ofile
->sysv_ar_strtab
= NULL
;
1913 ofile
->sysv_ar_strtab_size
= 0;
1915 host_byte_sex
= get_host_byte_sex();
1917 if(ofile
->member_size
> sizeof(uint32_t)){
1918 memcpy(&magic
, ofile
->member_addr
, sizeof(uint32_t));
1919 #ifdef __BIG_ENDIAN__
1920 if(magic
== FAT_MAGIC
|| magic
== FAT_MAGIC_64
)
1921 #endif /* __BIG_ENDIAN__ */
1922 #ifdef __LITTLE_ENDIAN__
1923 if(magic
== SWAP_INT(FAT_MAGIC
) || magic
== SWAP_INT(FAT_MAGIC_64
))
1924 #endif /* __LITTLE_ENDIAN__ */
1926 ofile
->member_type
= OFILE_FAT
;
1928 (struct fat_header
*)(ofile
->member_addr
);
1929 #ifdef __LITTLE_ENDIAN__
1930 swap_fat_header(ofile
->fat_header
, host_byte_sex
);
1931 #endif /* __LITTLE_ENDIAN__ */
1932 if(ofile
->fat_header
->magic
== FAT_MAGIC_64
)
1933 sizeof_fat_archs
= ofile
->fat_header
->nfat_arch
*
1934 sizeof(struct fat_arch_64
);
1936 sizeof_fat_archs
= ofile
->fat_header
->nfat_arch
*
1937 sizeof(struct fat_arch
);
1938 if(sizeof(struct fat_header
) + sizeof_fat_archs
>
1939 ofile
->member_size
){
1940 archive_member_error(ofile
, "fat file truncated or "
1941 "malformed (fat_arch%s structs would extend past "
1942 "the end of the archive member)",
1943 ofile
->fat_header
->magic
== FAT_MAGIC_64
?
1947 if(ofile
->fat_header
->magic
== FAT_MAGIC_64
){
1948 ofile
->fat_archs64
= (struct fat_arch_64
*)
1949 (ofile
->member_addr
+ sizeof(struct fat_header
));
1950 #ifdef __LITTLE_ENDIAN__
1951 swap_fat_arch_64(ofile
->fat_archs64
,
1952 ofile
->fat_header
->nfat_arch
,
1954 #endif /* __LITTLE_ENDIAN__ */
1957 ofile
->fat_archs
= (struct fat_arch
*)
1958 (ofile
->member_addr
+ sizeof(struct fat_header
));
1959 #ifdef __LITTLE_ENDIAN__
1960 swap_fat_arch(ofile
->fat_archs
,
1961 ofile
->fat_header
->nfat_arch
, host_byte_sex
);
1962 #endif /* __LITTLE_ENDIAN__ */
1964 if(check_fat_object_in_archive(ofile
) == FALSE
)
1967 else if(size
- (offset
+ ar_name_size
) >=
1968 sizeof(struct mach_header
) &&
1969 (magic
== MH_MAGIC
|| magic
== SWAP_INT(MH_MAGIC
))){
1970 #ifdef ALIGNMENT_CHECKS
1971 if((offset
+ ar_name_size
) % 4 != 0){
1972 archive_member_error(ofile
, "offset in archive not a "
1973 "multiple of 4 (must be since member is a 32-bit "
1977 #endif /* ALIGNMENT_CHECKS */
1978 ofile
->member_type
= OFILE_Mach_O
;
1979 ofile
->object_addr
= ofile
->member_addr
;
1980 ofile
->object_size
= ofile
->member_size
;
1981 if(magic
== MH_MAGIC
)
1982 ofile
->object_byte_sex
= host_byte_sex
;
1984 ofile
->object_byte_sex
=
1985 host_byte_sex
== BIG_ENDIAN_BYTE_SEX
?
1986 LITTLE_ENDIAN_BYTE_SEX
: BIG_ENDIAN_BYTE_SEX
;
1987 ofile
->mh
= (struct mach_header
*)(ofile
->object_addr
);
1988 ofile
->load_commands
= (struct load_command
*)
1989 (ofile
->object_addr
+ sizeof(struct mach_header
));
1990 if(check_Mach_O(ofile
) == CHECK_BAD
)
1993 else if(size
- (offset
+ ar_name_size
) >=
1994 sizeof(struct mach_header_64
) &&
1995 (magic
== MH_MAGIC_64
|| magic
== SWAP_INT(MH_MAGIC_64
))){
1996 #ifdef ALIGNMENT_CHECKS_ARCHIVE_64_BIT
1997 if(archive_64_bit_align_warning
== FALSE
&&
1998 (offset
+ ar_name_size
) % 8 != 0){
1999 temporary_archive_member_warning(ofile
, "offset in archive "
2000 "not a multiple of 8 (must be since member is an "
2001 "64-bit object file)");
2002 archive_64_bit_align_warning
= TRUE
;
2005 #endif /* ALIGNMENT_CHECKS_ARCHIVE_64_BIT */
2006 ofile
->member_type
= OFILE_Mach_O
;
2007 ofile
->object_addr
= ofile
->member_addr
;
2008 ofile
->object_size
= ofile
->member_size
;
2009 if(magic
== MH_MAGIC_64
)
2010 ofile
->object_byte_sex
= host_byte_sex
;
2012 ofile
->object_byte_sex
=
2013 host_byte_sex
== BIG_ENDIAN_BYTE_SEX
?
2014 LITTLE_ENDIAN_BYTE_SEX
: BIG_ENDIAN_BYTE_SEX
;
2015 ofile
->mh64
= (struct mach_header_64
*)(ofile
->object_addr
);
2016 ofile
->load_commands
= (struct load_command
*)
2017 (ofile
->object_addr
+ sizeof(struct mach_header_64
));
2018 if(check_Mach_O(ofile
) == CHECK_BAD
)
2021 if(ofile
->member_type
== OFILE_UNKNOWN
&&
2022 (strncmp(ofile
->member_name
, SYMDEF_SORTED
,
2023 sizeof(SYMDEF_SORTED
) - 1) == 0 ||
2024 strncmp(ofile
->member_name
, SYMDEF
,
2025 sizeof(SYMDEF
) - 1) == 0 ||
2026 strncmp(ofile
->member_name
, SYMDEF_64_SORTED
,
2027 sizeof(SYMDEF_64_SORTED
) - 1) == 0 ||
2028 strncmp(ofile
->member_name
, SYMDEF_64
,
2029 sizeof(SYMDEF_64
) - 1) == 0)){
2030 ofile
->toc_addr
= ofile
->member_addr
;
2031 ofile
->toc_size
= ofile
->member_size
;
2032 ofile
->toc_ar_hdr
= ofile
->member_ar_hdr
;
2033 ofile
->toc_name
= ofile
->member_name
;
2034 ofile
->toc_name_size
= ofile
->member_name_size
;
2035 if(check_archive_toc(ofile
) == CHECK_BAD
)
2038 else if(ofile
->member_type
== OFILE_UNKNOWN
&&
2039 strcmp(ofile
->member_name
, "// ") == 0){
2040 ofile
->sysv_ar_strtab
= ofile
->member_addr
;
2041 ofile
->sysv_ar_strtab_size
= ofile
->member_size
;
2044 if(ofile
->member_type
== OFILE_UNKNOWN
&&
2045 strncmp(ofile
->member_name
, SYMDEF_SORTED
,
2046 sizeof(SYMDEF_SORTED
) - 1) != 0 &&
2047 strncmp(ofile
->member_name
, SYMDEF
,
2048 sizeof(SYMDEF
) - 1) != 0 &&
2049 is_llvm_bitcode(ofile
, ofile
->member_addr
, ofile
->member_size
) ==
2051 ofile
->member_type
= OFILE_LLVM_BITCODE
;
2052 ofile
->object_addr
= ofile
->member_addr
;
2053 ofile
->object_size
= ofile
->member_size
;
2055 #endif /* LTO_SUPPORT */
2060 ofile
->fat_header
= NULL
;
2061 ofile
->fat_archs
= NULL
;
2062 ofile
->fat_archs64
= NULL
;
2064 ofile
->member_offset
= 0;
2065 ofile
->member_addr
= 0;
2066 ofile
->member_size
= 0;
2067 ofile
->member_ar_hdr
= NULL
;
2068 ofile
->member_name
= NULL
;
2069 ofile
->member_name_size
= 0;
2070 ofile
->member_type
= OFILE_UNKNOWN
;
2071 ofile
->object_addr
= NULL
;
2072 ofile
->object_size
= 0;
2073 ofile
->object_byte_sex
= UNKNOWN_BYTE_SEX
;
2076 ofile
->load_commands
= NULL
;
2079 ofile
->lto_cputype
= 0;
2080 ofile
->lto_cpusubtype
= 0;
2081 #endif /* LTO_SUPPORT */
2086 * ofile_next_member() set up the ofile structure (the member_* fields and
2087 * the object file fields if the next member is an object file) for the next
2093 struct ofile
*ofile
)
2096 uint64_t size
, offset
;
2098 enum byte_sex host_byte_sex
;
2099 struct ar_hdr
*ar_hdr
;
2100 uint32_t ar_name_size
, member_name_offset
, n
;
2101 uint32_t sizeof_fat_archs
;
2104 * Get the address and size of the archive.
2106 if(ofile
->file_type
== OFILE_FAT
){
2107 if(ofile
->arch_type
!= OFILE_ARCHIVE
){
2108 error("ofile_next_member() called on fat file: %s with a "
2109 "non-archive architecture or no architecture selected\n",
2113 if(ofile
->fat_header
->magic
== FAT_MAGIC_64
){
2114 addr
= ofile
->file_addr
+
2115 ofile
->fat_archs64
[ofile
->narch
].offset
;
2116 size
= ofile
->fat_archs64
[ofile
->narch
].size
;
2119 addr
= ofile
->file_addr
+
2120 ofile
->fat_archs
[ofile
->narch
].offset
;
2121 size
= ofile
->fat_archs
[ofile
->narch
].size
;
2124 else if(ofile
->file_type
== OFILE_ARCHIVE
){
2125 addr
= ofile
->file_addr
;
2126 size
= ofile
->file_size
;
2129 error("ofile_next_member() called and file type of %s is "
2130 "OFILE_UNKNOWN\n", ofile
->file_name
);
2133 if(size
< SARMAG
|| strncmp(addr
, ARMAG
, SARMAG
) != 0){
2134 archive_error(ofile
, "internal error. ofile_next_member() "
2135 "called but file does not have an archive magic "
2139 if(ofile
->member_ar_hdr
== NULL
){
2140 archive_error(ofile
, "internal error. ofile_next_member() called "
2141 "but the ofile struct does not have an archive "
2146 /* figure out the offset to the next member */
2147 offset
= ofile
->member_offset
+ rnd(ofile
->member_size
,sizeof(short));
2149 if((addr
- ofile
->file_addr
) + offset
> ofile
->file_size
){
2150 archive_error(ofile
, "offset to next member extends past the end "
2155 /* if now at the end of the file then no more members */
2159 archive_error(ofile
, "truncated or malformed (archive header of "
2160 "next member extends past the end of the file)");
2164 /* now we know there is a next member so set it up */
2165 ar_hdr
= (struct ar_hdr
*)(addr
+ offset
);
2166 offset
+= sizeof(struct ar_hdr
);
2167 ofile
->member_offset
= offset
;
2168 ofile
->member_addr
= addr
+ offset
;
2169 ofile
->member_size
= strtoul(ar_hdr
->ar_size
, NULL
, 10);
2170 if(ofile
->member_size
> size
- sizeof(struct ar_hdr
)){
2171 archive_error(ofile
, "size of archive member extends past "
2172 "the end of the archive");
2173 ofile
->member_size
= size
- sizeof(struct ar_hdr
);
2175 ofile
->member_ar_hdr
= ar_hdr
;
2176 ofile
->member_name
= ar_hdr
->ar_name
;
2177 if(ofile
->sysv_ar_strtab
== NULL
&& ofile
->sysv_ar_strtab_size
== 0 &&
2178 strncmp(ofile
->member_name
, "// ", sizeof("// ") - 1) == 0){
2179 ofile
->sysv_ar_strtab
= ofile
->member_addr
;
2180 ofile
->sysv_ar_strtab_size
= ofile
->member_size
;
2182 if(ofile
->member_name
[0] == '/' &&
2183 (ofile
->member_name
[1] != ' ' && ofile
->member_name
[1] != '/')){
2184 member_name_offset
= strtoul(ar_hdr
->ar_name
+ 1, NULL
, 10);
2185 if(member_name_offset
< ofile
->sysv_ar_strtab_size
){
2186 ofile
->member_name
= ofile
->sysv_ar_strtab
+ member_name_offset
;
2187 ofile
->member_name_size
= 0;
2188 for(n
= member_name_offset
;
2189 n
< ofile
->sysv_ar_strtab_size
; n
++){
2190 if(ofile
->sysv_ar_strtab
[n
] == '/')
2192 ofile
->member_name_size
++;
2196 ofile
->member_name_size
= size_ar_name(ar_hdr
);
2198 else if(strncmp(ofile
->member_name
, AR_EFMT1
,
2199 sizeof(AR_EFMT1
) - 1) == 0){
2200 ofile
->member_name
= ar_hdr
->ar_name
+ sizeof(struct ar_hdr
);
2201 ar_name_size
= strtoul(ar_hdr
->ar_name
+ sizeof(AR_EFMT1
) - 1,
2203 if(ar_name_size
> ofile
->member_size
){
2204 archive_error(ofile
, "size of archive member name "
2205 "extends past the end of the archive");
2206 ar_name_size
= ofile
->member_size
;
2208 ofile
->member_name_size
= ar_name_size
;
2209 ofile
->member_offset
+= ar_name_size
;
2210 ofile
->member_addr
+= ar_name_size
;
2211 ofile
->member_size
-= ar_name_size
;
2214 ofile
->member_name_size
= size_ar_name(ar_hdr
);
2217 ofile
->member_type
= OFILE_UNKNOWN
;
2218 ofile
->object_addr
= NULL
;
2219 ofile
->object_size
= 0;
2220 ofile
->object_byte_sex
= UNKNOWN_BYTE_SEX
;
2223 ofile
->load_commands
= NULL
;
2225 host_byte_sex
= get_host_byte_sex();
2227 if(ofile
->member_size
> sizeof(uint32_t)){
2228 memcpy(&magic
, ofile
->member_addr
, sizeof(uint32_t));
2229 #ifdef __BIG_ENDIAN__
2230 if(magic
== FAT_MAGIC
|| magic
== FAT_MAGIC_64
)
2231 #endif /* __BIG_ENDIAN__ */
2232 #ifdef __LITTLE_ENDIAN__
2233 if(magic
== SWAP_INT(FAT_MAGIC
) || magic
== SWAP_INT(FAT_MAGIC_64
))
2234 #endif /* __LITTLE_ENDIAN__ */
2236 ofile
->member_type
= OFILE_FAT
;
2237 ofile
->fat_header
= (struct fat_header
*)(ofile
->member_addr
);
2238 #ifdef __LITTLE_ENDIAN__
2239 swap_fat_header(ofile
->fat_header
, host_byte_sex
);
2240 #endif /* __LITTLE_ENDIAN__ */
2241 if(ofile
->fat_header
->magic
== FAT_MAGIC_64
)
2242 sizeof_fat_archs
= ofile
->fat_header
->nfat_arch
*
2243 sizeof(struct fat_arch_64
);
2245 sizeof_fat_archs
= ofile
->fat_header
->nfat_arch
*
2246 sizeof(struct fat_arch
);
2247 if(sizeof(struct fat_header
) + sizeof_fat_archs
>
2248 ofile
->member_size
){
2249 archive_member_error(ofile
, "fat file truncated or "
2250 "malformed (fat_arch%s structs would extend past "
2251 "the end of the archive member)",
2252 ofile
->fat_header
->magic
== FAT_MAGIC_64
?
2256 if(ofile
->fat_header
->magic
== FAT_MAGIC_64
){
2257 ofile
->fat_archs64
= (struct fat_arch_64
*)
2258 (ofile
->member_addr
+ sizeof(struct fat_header
));
2259 #ifdef __LITTLE_ENDIAN__
2260 swap_fat_arch_64(ofile
->fat_archs64
,
2261 ofile
->fat_header
->nfat_arch
,
2263 #endif /* __LITTLE_ENDIAN__ */
2266 ofile
->fat_archs
= (struct fat_arch
*)
2267 (ofile
->member_addr
+ sizeof(struct fat_header
));
2268 #ifdef __LITTLE_ENDIAN__
2269 swap_fat_arch(ofile
->fat_archs
,
2270 ofile
->fat_header
->nfat_arch
, host_byte_sex
);
2271 #endif /* __LITTLE_ENDIAN__ */
2273 if(check_fat_object_in_archive(ofile
) == FALSE
)
2276 else if(size
- (offset
+ ar_name_size
) >=
2277 sizeof(struct mach_header
) &&
2278 (magic
== MH_MAGIC
||
2279 magic
== SWAP_INT(MH_MAGIC
))){
2280 #ifdef ALIGNMENT_CHECKS
2281 if((offset
+ ar_name_size
) % 4 != 0){
2282 archive_member_error(ofile
, "offset in archive not "
2283 "a multiple of 4 (must be since member is an 32-bit "
2287 #endif /* ALIGNMENT_CHECKS */
2288 ofile
->member_type
= OFILE_Mach_O
;
2289 ofile
->object_addr
= ofile
->member_addr
;
2290 ofile
->object_size
= ofile
->member_size
;
2291 if(magic
== MH_MAGIC
)
2292 ofile
->object_byte_sex
= host_byte_sex
;
2294 ofile
->object_byte_sex
=
2295 host_byte_sex
== BIG_ENDIAN_BYTE_SEX
?
2296 LITTLE_ENDIAN_BYTE_SEX
: BIG_ENDIAN_BYTE_SEX
;
2297 ofile
->mh
= (struct mach_header
*)ofile
->object_addr
;
2298 ofile
->load_commands
= (struct load_command
*)
2299 (ofile
->object_addr
+ sizeof(struct mach_header
));
2300 if(check_Mach_O(ofile
) == CHECK_BAD
)
2303 else if(size
- (offset
+ ar_name_size
) >=
2304 sizeof(struct mach_header_64
) &&
2305 (magic
== MH_MAGIC_64
||
2306 magic
== SWAP_INT(MH_MAGIC_64
))){
2307 #ifdef ALIGNMENT_CHECKS_ARCHIVE_64_BIT
2308 if(archive_64_bit_align_warning
== FALSE
&&
2309 (offset
+ ar_name_size
) % 8 != 0){
2310 temporary_archive_member_warning(ofile
, "offset in archive "
2311 "not a multiple of 8 (must be since member is an "
2312 "64-bit object file)");
2313 archive_64_bit_align_warning
= TRUE
;
2316 #endif /* ALIGNMENT_CHECKS_ARCHIVE_64_BIT */
2317 ofile
->member_type
= OFILE_Mach_O
;
2318 ofile
->object_addr
= ofile
->member_addr
;
2319 ofile
->object_size
= ofile
->member_size
;
2320 if(magic
== MH_MAGIC_64
)
2321 ofile
->object_byte_sex
= host_byte_sex
;
2323 ofile
->object_byte_sex
=
2324 host_byte_sex
== BIG_ENDIAN_BYTE_SEX
?
2325 LITTLE_ENDIAN_BYTE_SEX
: BIG_ENDIAN_BYTE_SEX
;
2326 ofile
->mh64
= (struct mach_header_64
*)ofile
->object_addr
;
2327 ofile
->load_commands
= (struct load_command
*)
2328 (ofile
->object_addr
+ sizeof(struct mach_header_64
));
2329 if(check_Mach_O(ofile
) == CHECK_BAD
)
2333 if(ofile
->member_type
== OFILE_UNKNOWN
&&
2334 is_llvm_bitcode(ofile
, ofile
->member_addr
, ofile
->member_size
) ==
2336 ofile
->member_type
= OFILE_LLVM_BITCODE
;
2337 ofile
->object_addr
= ofile
->member_addr
;
2338 ofile
->object_size
= ofile
->member_size
;
2340 #endif /* LTO_SUPPORT */
2345 if(ofile
->member_type
== OFILE_FAT
){
2346 ofile
->fat_header
= NULL
;
2347 ofile
->fat_archs
= NULL
;
2348 ofile
->fat_archs64
= NULL
;
2350 ofile
->member_offset
= 0;
2351 ofile
->member_addr
= NULL
;
2352 ofile
->member_size
= 0;
2353 ofile
->member_ar_hdr
= NULL
;
2354 ofile
->member_name
= NULL
;
2355 ofile
->member_name_size
= 0;
2356 ofile
->member_type
= OFILE_UNKNOWN
;
2357 ofile
->object_addr
= NULL
;
2358 ofile
->object_size
= 0;
2359 ofile
->object_byte_sex
= UNKNOWN_BYTE_SEX
;
2362 ofile
->load_commands
= NULL
;
2365 ofile
->lto_cputype
= 0;
2366 ofile
->lto_cpusubtype
= 0;
2367 #endif /* LTO_SUPPORT */
2372 * ofile_specific_member() set up the ofile structure (the member_* fields and
2373 * the object file fields if the member is an object file) for the specified
2374 * member member_name.
2378 ofile_specific_member(
2379 const char *member_name
,
2380 struct ofile
*ofile
)
2384 uint64_t size
, offset
;
2386 enum byte_sex host_byte_sex
;
2388 uint32_t ar_name_size
, member_name_offset
;
2389 struct ar_hdr
*ar_hdr
;
2390 uint32_t sizeof_fat_archs
;
2392 /* These fields are to be filled in by this routine, clear them first */
2393 ofile
->member_offset
= 0;
2394 ofile
->member_addr
= NULL
;
2395 ofile
->member_size
= 0;
2396 ofile
->member_ar_hdr
= NULL
;
2397 ofile
->member_name
= NULL
;
2398 ofile
->member_name_size
= 0;
2399 ofile
->member_type
= OFILE_UNKNOWN
;
2400 ofile
->object_addr
= NULL
;
2401 ofile
->object_size
= 0;
2402 ofile
->object_byte_sex
= UNKNOWN_BYTE_SEX
;
2405 ofile
->load_commands
= NULL
;
2408 * Get the address and size of the archive.
2410 if(ofile
->file_type
== OFILE_FAT
){
2411 if(ofile
->arch_type
!= OFILE_ARCHIVE
){
2412 error("ofile_specific_member() called on fat file: %s with a "
2413 "non-archive architecture or no architecture selected\n",
2417 if(ofile
->fat_header
->magic
== FAT_MAGIC_64
){
2418 addr
= ofile
->file_addr
+
2419 ofile
->fat_archs64
[ofile
->narch
].offset
;
2420 size
= ofile
->fat_archs64
[ofile
->narch
].size
;
2423 addr
= ofile
->file_addr
+
2424 ofile
->fat_archs
[ofile
->narch
].offset
;
2425 size
= ofile
->fat_archs
[ofile
->narch
].size
;
2428 else if(ofile
->file_type
== OFILE_ARCHIVE
){
2429 addr
= ofile
->file_addr
;
2430 size
= ofile
->file_size
;
2433 error("ofile_specific_member() called and file type of %s is "
2434 "OFILE_UNKNOWN\n", ofile
->file_name
);
2437 if(size
< SARMAG
|| strncmp(addr
, ARMAG
, SARMAG
) != 0){
2438 archive_error(ofile
, "internal error. ofile_specific_member() "
2439 "called but file does not have an archive magic "
2444 /* Clear these until we find a System V "//" named archive member */
2445 ofile
->sysv_ar_strtab
= NULL
;
2446 ofile
->sysv_ar_strtab_size
= 0;
2449 if(offset
!= size
&& offset
+ sizeof(struct ar_hdr
) > size
){
2450 archive_error(ofile
, "truncated or malformed (archive header of "
2451 "first member extends past the end of the file)");
2454 while(size
> offset
){
2455 ar_hdr
= (struct ar_hdr
*)(addr
+ offset
);
2456 offset
+= sizeof(struct ar_hdr
);
2458 if(ofile
->sysv_ar_strtab
== NULL
&&
2459 ofile
->sysv_ar_strtab_size
== 0 &&
2460 strncmp(ar_hdr
->ar_name
, "// ", sizeof("// ") - 1) == 0){
2461 ofile
->sysv_ar_strtab
= addr
+ offset
;
2462 ofile
->sysv_ar_strtab_size
= strtoul(ar_hdr
->ar_size
, NULL
, 10);
2465 if(ar_hdr
->ar_name
[0] == '/' &&
2466 (ar_hdr
->ar_name
[1] != ' ' && ar_hdr
->ar_name
[1] != '/')){
2467 member_name_offset
= strtoul(ar_hdr
->ar_name
+ 1, NULL
, 10);
2468 if(member_name_offset
< ofile
->sysv_ar_strtab_size
){
2469 ar_name
= ofile
->sysv_ar_strtab
+ member_name_offset
;
2471 for(n
= member_name_offset
;
2472 n
< ofile
->sysv_ar_strtab_size
; n
++){
2473 if(ofile
->sysv_ar_strtab
[n
] == '/')
2480 i
= size_ar_name(ar_hdr
);
2481 ar_name
= ar_hdr
->ar_name
;
2485 else if(strncmp(ar_hdr
->ar_name
, AR_EFMT1
,
2486 sizeof(AR_EFMT1
) - 1) == 0){
2488 if(check_extend_format_1(ofile
, ar_hdr
, size
- offset
,
2489 &ar_name_size
) == CHECK_BAD
){
2490 i
= size_ar_name(ar_hdr
);
2491 ar_name
= ar_hdr
->ar_name
;
2497 i
= strtoul(ar_hdr
->ar_name
+ sizeof(AR_EFMT1
) - 1,NULL
,10);
2498 ar_name
= ar_hdr
->ar_name
+ sizeof(struct ar_hdr
);
2503 i
= size_ar_name(ar_hdr
);
2504 ar_name
= ar_hdr
->ar_name
;
2507 if(i
> 0 && strncmp(ar_name
, member_name
, i
) == 0){
2509 ofile
->member_name
= ar_name
;
2510 ofile
->member_name_size
= i
;
2511 ofile
->member_offset
= offset
+ ar_name_size
;
2512 ofile
->member_addr
= addr
+ offset
+ ar_name_size
;
2513 ofile
->member_size
= strtoul(ar_hdr
->ar_size
, NULL
, 10) -
2515 ofile
->member_ar_hdr
= ar_hdr
;
2516 ofile
->member_type
= OFILE_UNKNOWN
;
2518 host_byte_sex
= get_host_byte_sex();
2520 if(ofile
->member_size
> sizeof(uint32_t)){
2521 memcpy(&magic
, addr
+ offset
+ ar_name_size
,
2523 #ifdef __BIG_ENDIAN__
2524 if(magic
== FAT_MAGIC
|| magic
== FAT_MAGIC_64
)
2525 #endif /* __BIG_ENDIAN__ */
2526 #ifdef __LITTLE_ENDIAN__
2527 if(magic
== SWAP_INT(FAT_MAGIC
) ||
2528 magic
== SWAP_INT(FAT_MAGIC_64
))
2529 #endif /* __LITTLE_ENDIAN__ */
2531 ofile
->member_type
= OFILE_FAT
;
2533 (struct fat_header
*)(addr
+ offset
+ ar_name_size
);
2534 #ifdef __LITTLE_ENDIAN__
2535 swap_fat_header(ofile
->fat_header
, host_byte_sex
);
2536 #endif /* __LITTLE_ENDIAN__ */
2537 if(ofile
->fat_header
->magic
== FAT_MAGIC_64
)
2538 sizeof_fat_archs
= ofile
->fat_header
->nfat_arch
*
2539 sizeof(struct fat_arch_64
);
2541 sizeof_fat_archs
= ofile
->fat_header
->nfat_arch
*
2542 sizeof(struct fat_arch
);
2543 if(sizeof(struct fat_header
) + sizeof_fat_archs
>
2544 ofile
->member_size
){
2545 archive_member_error(ofile
, "fat file truncated or "
2546 "malformed (fat_arch%s structs would extend"
2547 " past the end of the archive member)",
2548 ofile
->fat_header
->magic
== FAT_MAGIC_64
?
2552 if(ofile
->fat_header
->magic
== FAT_MAGIC_64
){
2553 ofile
->fat_archs64
=
2554 (struct fat_arch_64
*)
2555 (addr
+ offset
+ ar_name_size
+
2556 sizeof(struct fat_header
));
2557 #ifdef __LITTLE_ENDIAN__
2558 swap_fat_arch_64(ofile
->fat_archs64
,
2559 ofile
->fat_header
->nfat_arch
,
2561 #endif /* __LITTLE_ENDIAN__ */
2566 (addr
+ offset
+ ar_name_size
+
2567 sizeof(struct fat_header
));
2568 #ifdef __LITTLE_ENDIAN__
2569 swap_fat_arch(ofile
->fat_archs
,
2570 ofile
->fat_header
->nfat_arch
,
2572 #endif /* __LITTLE_ENDIAN__ */
2574 if(check_fat_object_in_archive(ofile
) == FALSE
)
2577 else if(size
- (offset
+ ar_name_size
) >=
2578 sizeof(struct mach_header
) &&
2579 (magic
== MH_MAGIC
||
2580 magic
== SWAP_INT(MH_MAGIC
))){
2581 #ifdef ALIGNMENT_CHECKS
2582 if((offset
+ ar_name_size
) % 4 != 0){
2583 archive_member_error(ofile
, "offset in archive not "
2584 "a multiple of 4) (must be since member is a "
2585 "32-bit object file)");
2588 #endif /* ALIGNMENT_CHECKS */
2589 ofile
->member_type
= OFILE_Mach_O
;
2590 ofile
->object_addr
= ofile
->member_addr
;
2591 ofile
->object_size
= ofile
->member_size
;
2592 if(magic
== MH_MAGIC
)
2593 ofile
->object_byte_sex
= host_byte_sex
;
2595 ofile
->object_byte_sex
=
2596 host_byte_sex
== BIG_ENDIAN_BYTE_SEX
?
2597 LITTLE_ENDIAN_BYTE_SEX
: BIG_ENDIAN_BYTE_SEX
;
2598 ofile
->mh
= (struct mach_header
*)ofile
->object_addr
;
2599 ofile
->load_commands
= (struct load_command
*)
2600 (ofile
->object_addr
+ sizeof(struct mach_header
));
2601 if(check_Mach_O(ofile
) == CHECK_BAD
)
2604 else if(size
- (offset
+ ar_name_size
) >=
2605 sizeof(struct mach_header_64
) &&
2606 (magic
== MH_MAGIC_64
||
2607 magic
== SWAP_INT(MH_MAGIC_64
))){
2608 #ifdef ALIGNMENT_CHECKS_ARCHIVE_64_BIT
2609 if(archive_64_bit_align_warning
== FALSE
&&
2610 (offset
+ ar_name_size
) % 8 != 0){
2611 temporary_archive_member_warning(ofile
, "offset in "
2612 "archive not a multiple of 8) (must be since "
2613 "member is a 64-bit object file)");
2614 archive_64_bit_align_warning
= TRUE
;
2617 #endif /* ALIGNMENT_CHECKS_ARCHIVE_64_BIT */
2618 ofile
->member_type
= OFILE_Mach_O
;
2619 ofile
->object_addr
= ofile
->member_addr
;
2620 ofile
->object_size
= ofile
->member_size
;
2621 if(magic
== MH_MAGIC_64
)
2622 ofile
->object_byte_sex
= host_byte_sex
;
2624 ofile
->object_byte_sex
=
2625 host_byte_sex
== BIG_ENDIAN_BYTE_SEX
?
2626 LITTLE_ENDIAN_BYTE_SEX
: BIG_ENDIAN_BYTE_SEX
;
2627 ofile
->mh64
= (struct mach_header_64
*)
2629 ofile
->load_commands
= (struct load_command
*)
2630 (ofile
->object_addr
+sizeof(struct mach_header_64
));
2631 if(check_Mach_O(ofile
) == CHECK_BAD
)
2636 if(ofile
->member_type
== OFILE_UNKNOWN
&&
2637 is_llvm_bitcode(ofile
, ofile
->member_addr
,
2638 ofile
->member_size
) == TRUE
){
2639 ofile
->member_type
= OFILE_LLVM_BITCODE
;
2640 ofile
->object_addr
= ofile
->member_addr
;
2641 ofile
->object_size
= ofile
->member_size
;
2643 #endif /* LTO_SUPPORT */
2646 offset
+= rnd(strtoul(ar_hdr
->ar_size
, NULL
, 10),
2649 archive_error(ofile
, "does not contain a member named: %s",
2652 ofile
->fat_header
= NULL
;
2653 ofile
->fat_archs
= NULL
;
2654 ofile
->fat_archs64
= NULL
;
2656 ofile
->member_offset
= 0;
2657 ofile
->member_addr
= NULL
;
2658 ofile
->member_size
= 0;
2659 ofile
->member_ar_hdr
= NULL
;
2660 ofile
->member_name
= NULL
;
2661 ofile
->member_name_size
= 0;
2662 ofile
->member_type
= OFILE_UNKNOWN
;
2663 ofile
->object_addr
= NULL
;
2664 ofile
->object_size
= 0;
2665 ofile
->object_byte_sex
= UNKNOWN_BYTE_SEX
;
2668 ofile
->load_commands
= NULL
;
2671 ofile
->lto_cputype
= 0;
2672 ofile
->lto_cpusubtype
= 0;
2673 #endif /* LTO_SUPPORT */
2678 * ofile_first_module() set up the ofile structure (the dylib_module field)
2679 * for the first module of an MH_DYLIB or MH_DYLIB_STUB file.
2684 struct ofile
*ofile
)
2687 struct symtab_command
*st
;
2688 struct dysymtab_command
*dyst
;
2689 struct load_command
*lc
;
2691 enum byte_sex host_byte_sex
;
2692 struct dylib_module m
;
2693 struct dylib_module_64 m64
;
2696 /* These fields are to be filled in by this routine, clear them first */
2697 ofile
->modtab
= NULL
;
2698 ofile
->modtab64
= NULL
;
2700 ofile
->dylib_module
= NULL
;
2701 ofile
->dylib_module64
= NULL
;
2702 ofile
->dylib_module_name
= NULL
;
2704 if(ofile
->file_type
== OFILE_FAT
){
2705 if(ofile
->arch_type
!= OFILE_Mach_O
&&
2706 (ofile
->mh_filetype
!= MH_DYLIB
&&
2707 ofile
->mh_filetype
!= MH_DYLIB_STUB
)){
2708 error("ofile_first_module() called on fat file: %s with a "
2709 "non-MH_DYLIB architecture or no architecture selected\n",
2714 else if(ofile
->arch_type
!= OFILE_Mach_O
&&
2715 (ofile
->mh_filetype
!= MH_DYLIB
&&
2716 ofile
->mh_filetype
!= MH_DYLIB_STUB
)){
2717 error("ofile_first_module() called and file type of %s is "
2718 "non-MH_DYLIB\n", ofile
->file_name
);
2724 lc
= ofile
->load_commands
;
2725 if(ofile
->mh
!= NULL
)
2726 ncmds
= ofile
->mh
->ncmds
;
2728 ncmds
= ofile
->mh64
->ncmds
;
2729 for(i
= 0; i
< ncmds
; i
++){
2730 if(st
== NULL
&& lc
->cmd
== LC_SYMTAB
){
2731 st
= (struct symtab_command
*)lc
;
2733 else if(lc
->cmd
== LC_DYSYMTAB
){
2734 dyst
= (struct dysymtab_command
*)lc
;
2736 lc
= (struct load_command
*)((char *)lc
+ lc
->cmdsize
);
2738 if(st
== NULL
|| dyst
== NULL
){
2740 Mach_O_error(ofile
, "MH_DYLIB format error (does not have a symbol "
2741 "table and/or a dynamic symbol table)");
2745 if(dyst
->nmodtab
== 0)
2748 ofile
->nmodtab
= dyst
->nmodtab
;
2749 host_byte_sex
= get_host_byte_sex();
2750 swapped
= (enum bool)(host_byte_sex
!= ofile
->object_byte_sex
);
2751 strings
= (char *)(ofile
->object_addr
+ st
->stroff
);
2753 if(ofile
->mh
!= NULL
){
2754 ofile
->modtab
= (struct dylib_module
*)(ofile
->object_addr
+
2756 ofile
->dylib_module
= ofile
->modtab
;
2757 m
= *ofile
->dylib_module
;
2759 swap_dylib_module(&m
, 1, host_byte_sex
);
2760 ofile
->dylib_module_name
= strings
+ m
.module_name
;
2763 ofile
->modtab64
= (struct dylib_module_64
*)(ofile
->object_addr
+
2765 ofile
->dylib_module64
= ofile
->modtab64
;
2766 m64
= *ofile
->dylib_module64
;
2768 swap_dylib_module_64(&m64
, 1, host_byte_sex
);
2769 ofile
->dylib_module_name
= strings
+ m64
.module_name
;
2772 if(check_dylib_module(ofile
, st
, dyst
, strings
, 0) == CHECK_BAD
)
2778 * ofile_next_module() set up the ofile structure (the dylib_module field)
2779 * for the next module of an MH_DYLIB or MH_DYLIB_STUB file.
2784 struct ofile
*ofile
)
2786 uint32_t i
, module_index
, ncmds
;
2787 struct symtab_command
*st
;
2788 struct dysymtab_command
*dyst
;
2789 struct load_command
*lc
;
2791 enum byte_sex host_byte_sex
;
2792 struct dylib_module m
;
2793 struct dylib_module_64 m64
;
2796 if(ofile
->file_type
== OFILE_FAT
){
2797 if(ofile
->arch_type
!= OFILE_Mach_O
&&
2798 (ofile
->mh_filetype
!= MH_DYLIB
&&
2799 ofile
->mh_filetype
!= MH_DYLIB_STUB
)){
2800 error("ofile_next_module() called on fat file: %s with a "
2801 "non-MH_DYLIB architecture or no architecture selected\n",
2806 else if(ofile
->arch_type
!= OFILE_Mach_O
&&
2807 (ofile
->mh_filetype
!= MH_DYLIB
&&
2808 ofile
->mh_filetype
!= MH_DYLIB_STUB
)){
2809 error("ofile_next_module() called and file type of %s is "
2810 "non-MH_DYLIB\n", ofile
->file_name
);
2815 lc
= ofile
->load_commands
;
2816 if(ofile
->mh
!= NULL
)
2817 ncmds
= ofile
->mh
->ncmds
;
2819 ncmds
= ofile
->mh64
->ncmds
;
2820 for(i
= 0; i
< ncmds
; i
++){
2821 if(st
== NULL
&& lc
->cmd
== LC_SYMTAB
){
2822 st
= (struct symtab_command
*)lc
;
2824 else if(lc
->cmd
== LC_DYSYMTAB
){
2825 dyst
= (struct dysymtab_command
*)lc
;
2827 lc
= (struct load_command
*)((char *)lc
+ lc
->cmdsize
);
2829 if(st
== NULL
|| dyst
== NULL
){
2831 Mach_O_error(ofile
, "MH_DYLIB format error (does not have a symbol "
2832 "table and/or a dynamic symbol table)");
2837 if(ofile
->mh
!= NULL
)
2838 module_index
= (ofile
->dylib_module
+ 1) - ofile
->modtab
;
2840 module_index
= (ofile
->dylib_module64
+ 1) - ofile
->modtab64
;
2841 if(module_index
>= ofile
->nmodtab
)
2844 host_byte_sex
= get_host_byte_sex();
2845 swapped
= (enum bool)(host_byte_sex
!= ofile
->object_byte_sex
);
2846 strings
= (char *)(ofile
->object_addr
+ st
->stroff
);
2848 if(ofile
->mh
!= NULL
){
2849 ofile
->dylib_module
++;
2850 m
= *ofile
->dylib_module
;
2852 swap_dylib_module(&m
, 1, host_byte_sex
);
2853 ofile
->dylib_module_name
= strings
+ m
.module_name
;
2856 ofile
->dylib_module64
++;
2857 m64
= *ofile
->dylib_module64
;
2859 swap_dylib_module_64(&m64
, 1, host_byte_sex
);
2860 ofile
->dylib_module_name
= strings
+ m64
.module_name
;
2862 if(check_dylib_module(ofile
, st
, dyst
, strings
, module_index
) ==
2869 * ofile_specific_module() set up the ofile structure (the dylib_module fields)
2870 * for the specified module, module_name, of an MH_DYLIB or an MH_DYLIB_STUB
2875 ofile_specific_module(
2876 const char *module_name
,
2877 struct ofile
*ofile
)
2881 enum byte_sex host_byte_sex
;
2882 struct symtab_command
*st
;
2883 struct dysymtab_command
*dyst
;
2884 struct load_command
*lc
;
2885 struct dylib_module
*p
, m
;
2886 struct dylib_module_64
*p64
, m64
;
2889 /* These fields are to be filled in by this routine, clear them first */
2890 ofile
->modtab
= NULL
;
2891 ofile
->modtab64
= NULL
;
2893 ofile
->dylib_module
= NULL
;
2894 ofile
->dylib_module64
= NULL
;
2895 ofile
->dylib_module_name
= NULL
;
2897 if(ofile
->file_type
== OFILE_FAT
){
2898 if(ofile
->arch_type
!= OFILE_Mach_O
&&
2899 (ofile
->mh_filetype
!= MH_DYLIB
&&
2900 ofile
->mh_filetype
!= MH_DYLIB_STUB
)){
2901 error("ofile_specific_module() called on fat file: %s with a "
2902 "non-MH_DYLIB architecture or no architecture selected\n",
2907 else if(ofile
->arch_type
!= OFILE_Mach_O
&&
2908 (ofile
->mh_filetype
!= MH_DYLIB
&&
2909 ofile
->mh_filetype
!= MH_DYLIB_STUB
)){
2910 error("ofile_specific_module() called and file type of %s is "
2911 "non-MH_DYLIB\n", ofile
->file_name
);
2917 lc
= ofile
->load_commands
;
2918 if(ofile
->mh
!= NULL
)
2919 ncmds
= ofile
->mh
->ncmds
;
2921 ncmds
= ofile
->mh64
->ncmds
;
2922 for(i
= 0; i
< ncmds
; i
++){
2923 if(st
== NULL
&& lc
->cmd
== LC_SYMTAB
){
2924 st
= (struct symtab_command
*)lc
;
2926 else if(lc
->cmd
== LC_DYSYMTAB
){
2927 dyst
= (struct dysymtab_command
*)lc
;
2929 lc
= (struct load_command
*)((char *)lc
+ lc
->cmdsize
);
2931 if(st
== NULL
|| dyst
== NULL
){
2933 Mach_O_error(ofile
, "MH_DYLIB format error (does not have a symbol "
2934 "table and/or a dynamic symbol table)");
2938 if(dyst
->nmodtab
== 0)
2941 host_byte_sex
= get_host_byte_sex();
2942 swapped
= (enum bool)(host_byte_sex
!= ofile
->object_byte_sex
);
2943 strings
= (char *)(ofile
->object_addr
+ st
->stroff
);
2945 if(ofile
->mh
!= NULL
){
2946 ofile
->nmodtab
= dyst
->nmodtab
;
2947 ofile
->modtab
= (struct dylib_module
*)(ofile
->object_addr
+
2950 for(i
= 0; i
< dyst
->nmodtab
; i
++){
2953 swap_dylib_module(&m
, 1, host_byte_sex
);
2954 ofile
->dylib_module
= p
;
2955 if(check_dylib_module(ofile
, st
, dyst
, strings
, i
) == CHECK_BAD
)
2957 if(strcmp(module_name
, strings
+ m
.module_name
) == 0){
2958 ofile
->dylib_module_name
= strings
+ m
.module_name
;
2963 m
= *ofile
->dylib_module
;
2965 swap_dylib_module(&m
, 1, host_byte_sex
);
2966 ofile
->dylib_module_name
= strings
+ m
.module_name
;
2969 ofile
->nmodtab
= dyst
->nmodtab
;
2970 ofile
->modtab64
= (struct dylib_module_64
*)(ofile
->object_addr
+
2972 p64
= ofile
->modtab64
;
2973 for(i
= 0; i
< dyst
->nmodtab
; i
++){
2976 swap_dylib_module_64(&m64
, 1, host_byte_sex
);
2977 ofile
->dylib_module64
= p64
;
2978 if(check_dylib_module(ofile
, st
, dyst
, strings
, i
) == CHECK_BAD
)
2980 if(strcmp(module_name
, strings
+ m64
.module_name
) == 0){
2981 ofile
->dylib_module_name
= strings
+ m64
.module_name
;
2986 m64
= *ofile
->dylib_module64
;
2988 swap_dylib_module_64(&m64
, 1, host_byte_sex
);
2989 ofile
->dylib_module_name
= strings
+ m64
.module_name
;
2992 Mach_O_error(ofile
, "does not contain a module named: %s", module_name
);
2994 ofile
->modtab
= NULL
;
2996 ofile
->dylib_module
= NULL
;
2997 ofile
->dylib_module_name
= NULL
;
3005 struct ofile
*ofile
)
3007 printf("file_name = %s\n", ofile
->file_name
);
3008 printf("file_addr = 0x%x\n", (unsigned int)ofile
->file_addr
);
3009 printf("file_size = 0x%x\n", (unsigned int)ofile
->file_size
);
3010 printf("file_type = 0x%x\n", (unsigned int)ofile
->file_type
);
3011 printf("fat_header = 0x%x\n", (unsigned int)ofile
->fat_header
);
3012 printf("fat_archs = 0x%x\n", (unsigned int)ofile
->fat_archs
);
3013 printf("fat_archs64 = 0x%x\n", (unsigned int)ofile
->fat_archs64
);
3014 printf("narch = 0x%x\n", (unsigned int)ofile
->narch
);
3015 printf("arch_type = 0x%x\n", (unsigned int)ofile
->arch_type
);
3016 printf("arch_flag.name = %s\n", ofile
->arch_flag
.name
);
3017 printf("arch_flag.cputype = 0x%x\n",
3018 (unsigned int)ofile
->arch_flag
.cputype
);
3019 printf("arch_flag.cpusubtype = 0x%x\n",
3020 (unsigned int)ofile
->arch_flag
.cpusubtype
);
3021 printf("member_offset = 0x%x\n", (unsigned int)ofile
->member_offset
);
3022 printf("member_addr = 0x%x\n", (unsigned int)ofile
->member_addr
);
3023 printf("member_size = 0x%x\n", (unsigned int)ofile
->member_size
);
3024 printf("member_ar_hdr = 0x%x\n", (unsigned int)ofile
->member_ar_hdr
);
3025 printf("member_type = 0x%x\n", (unsigned int)ofile
->member_type
);
3026 printf("archive_cputype = 0x%x\n",
3027 (unsigned int)ofile
->archive_cputype
);
3028 printf("archive_cpusubtype = 0x%x\n",
3029 (unsigned int)ofile
->archive_cpusubtype
);
3030 printf("object_addr = 0x%x\n", (unsigned int)ofile
->object_addr
);
3031 printf("object_size = 0x%x\n", (unsigned int)ofile
->object_size
);
3032 printf("object_byte_sex = 0x%x\n",
3033 (unsigned int)ofile
->object_byte_sex
);
3034 printf("mh = 0x%x\n", (unsigned int)ofile
->mh
);
3035 printf("mh64 = 0x%x\n", (unsigned int)ofile
->mh64
);
3036 printf("load_commands = 0x%x\n", (unsigned int)ofile
->load_commands
);
3041 * check_fat() checks the fat ofile for correctness (the fat_header and
3042 * fat_archs or fat_archs64 are assumed to be in the host byte sex).
3047 struct ofile
*ofile
)
3051 #else /* !defined OTOOL */
3056 cpu_subtype_t cpusubtype
;
3061 if(ofile
->file_type
!= OFILE_FAT
){
3062 error("internal error. check_fat() call and file type of: %s is "
3063 "not OFILE_FAT\n", ofile
->file_name
);
3066 if(ofile
->fat_header
->nfat_arch
== 0){
3067 error("fat file: %s malformed (contains zero architecture types)",
3071 for(i
= 0; i
< ofile
->fat_header
->nfat_arch
; i
++){
3072 if(ofile
->fat_header
->magic
== FAT_MAGIC_64
){
3073 cputype
= ofile
->fat_archs64
[i
].cputype
;
3074 cpusubtype
= ofile
->fat_archs64
[i
].cpusubtype
;
3075 offset
= ofile
->fat_archs64
[i
].offset
;
3076 size
= ofile
->fat_archs64
[i
].size
;
3077 align
= ofile
->fat_archs64
[i
].align
;
3080 cputype
= ofile
->fat_archs
[i
].cputype
;
3081 cpusubtype
= ofile
->fat_archs
[i
].cpusubtype
;
3082 offset
= ofile
->fat_archs
[i
].offset
;
3083 size
= ofile
->fat_archs
[i
].size
;
3084 align
= ofile
->fat_archs
[i
].align
;
3088 if(big_size
> ofile
->file_size
){
3089 error("fat file: %s truncated or malformed (offset plus size "
3090 "of cputype (%d) cpusubtype (%d) extends past the "
3091 "end of the file)", ofile
->file_name
,
3092 cputype
, cpusubtype
& ~CPU_SUBTYPE_MASK
);
3095 if(align
> MAXSECTALIGN
){
3096 error("fat file: %s align (2^%u) too large for cputype (%d) "
3097 "cpusubtype (%d) (maximum 2^%d)", ofile
->file_name
,
3098 align
, cputype
, cpusubtype
& ~CPU_SUBTYPE_MASK
,
3104 error("fat file: %s offset: %llu for cputype (%d) cpusubtype "
3105 "(%d)) not aligned on it's alignment (2^%u)",
3106 ofile
->file_name
, offset
, cputype
,
3107 cpusubtype
& ~CPU_SUBTYPE_MASK
, align
);
3111 for(i
= 0; i
< ofile
->fat_header
->nfat_arch
; i
++){
3112 for(j
= i
+ 1; j
< ofile
->fat_header
->nfat_arch
; j
++){
3113 if(ofile
->fat_header
->magic
== FAT_MAGIC_64
){
3114 if(ofile
->fat_archs64
[i
].cputype
==
3115 ofile
->fat_archs64
[j
].cputype
&&
3116 (ofile
->fat_archs64
[i
].cpusubtype
& ~CPU_SUBTYPE_MASK
) ==
3117 (ofile
->fat_archs64
[j
].cpusubtype
&
3118 ~CPU_SUBTYPE_MASK
)){
3119 error("fat file: %s contains two of the same "
3120 "architecture (cputype (%d) cpusubtype (%d))",
3121 ofile
->file_name
, ofile
->fat_archs64
[i
].cputype
,
3122 ofile
->fat_archs64
[i
].cpusubtype
&
3128 if(ofile
->fat_archs
[i
].cputype
==
3129 ofile
->fat_archs
[j
].cputype
&&
3130 (ofile
->fat_archs
[i
].cpusubtype
& ~CPU_SUBTYPE_MASK
) ==
3131 (ofile
->fat_archs
[j
].cpusubtype
& ~CPU_SUBTYPE_MASK
)){
3132 error("fat file: %s contains two of the same "
3133 "architecture (cputype (%d) cpusubtype (%d))",
3134 ofile
->file_name
, ofile
->fat_archs
[i
].cputype
,
3135 ofile
->fat_archs
[i
].cpusubtype
&
3147 * check_fat_object_in_archive() checks the fat object file which is a member
3148 * of a thin archive for correctness (the fat_header and fat_archs or
3149 * fat_archs64 are assumed to be in the host byte sex). This is not a legal
3150 * form but allowed when archives_with_fat_objects is TRUE when ofile_map() is
3155 check_fat_object_in_archive(
3156 struct ofile
*ofile
)
3161 cpu_subtype_t cpusubtype
;
3166 if(ofile
->file_type
!= OFILE_ARCHIVE
){
3167 error("internal error. check_fat_object_in_archive() called and "
3168 "file type of: %s is not OFILE_ARCHIVE\n", ofile
->file_name
);
3171 if(ofile
->fat_header
->nfat_arch
== 0){
3172 archive_member_error(ofile
, "fat file malformed (contains zero "
3173 "architecture types)");
3176 for(i
= 0; i
< ofile
->fat_header
->nfat_arch
; i
++){
3177 if(ofile
->fat_header
->magic
== FAT_MAGIC_64
){
3178 cputype
= ofile
->fat_archs64
[i
].cputype
;
3179 cpusubtype
= ofile
->fat_archs64
[i
].cpusubtype
;
3180 offset
= ofile
->fat_archs64
[i
].offset
;
3181 size
= ofile
->fat_archs64
[i
].size
;
3182 align
= ofile
->fat_archs64
[i
].align
;
3185 cputype
= ofile
->fat_archs
[i
].cputype
;
3186 cpusubtype
= ofile
->fat_archs
[i
].cpusubtype
;
3187 offset
= ofile
->fat_archs
[i
].offset
;
3188 size
= ofile
->fat_archs
[i
].size
;
3189 align
= ofile
->fat_archs
[i
].align
;
3191 if(offset
+ size
> ofile
->member_size
){
3192 archive_member_error(ofile
, "fat file truncated or malformed "
3193 "(offset plus size of cputype (%d) cpusubtype (%d) "
3194 "extends past the end of the file)",
3195 cputype
, cpusubtype
& ~CPU_SUBTYPE_MASK
);
3198 if(align
> MAXSECTALIGN
){
3199 archive_member_error(ofile
, "fat file's align (2^%u) too "
3200 "large for cputype (%d) cpusubtype (%d) (maximum 2^%d)",
3201 align
, cputype
, cpusubtype
& ~CPU_SUBTYPE_MASK
,
3205 if(offset
% (1 << align
) != 0){
3206 archive_member_error(ofile
, "fat file's offset: %llu for "
3207 "cputype (%d) cpusubtype (%d) not aligned on it's "
3208 "alignment (2^%u)", offset
, cputype
,
3209 cpusubtype
& ~CPU_SUBTYPE_MASK
, align
);
3214 * The only supported format where fat files are allowed to appear
3215 * in archives is when the fat file contains only object files.
3217 if(size
< sizeof(struct mach_header
)){
3218 archive_member_error(ofile
, "fat file for cputype (%d) "
3219 "cpusubtype (%d) is not an object file (size too small "
3220 "to be an object file)", cputype
,
3221 cpusubtype
& ~CPU_SUBTYPE_MASK
);
3225 ofile
->file_addr
+ ofile
->member_offset
+
3228 if(magic
== MH_MAGIC
|| magic
== SWAP_INT(MH_MAGIC
)){
3229 #ifdef ALIGNMENT_CHECKS
3230 if((ofile
->member_offset
+ offset
) %
3232 archive_member_error(ofile
, "fat object file's offset in "
3233 "archive not a multiple of 4) (must be since "
3234 "member is a 32-bit object file)");
3237 #endif /* ALIGNMENT_CHECKS */
3239 else if(magic
== MH_MAGIC_64
|| magic
== SWAP_INT(MH_MAGIC_64
)){
3240 #ifdef ALIGNMENT_CHECKS_ARCHIVE_64_BIT
3241 if(archive_64_bit_align_warning
== FALSE
&&
3242 (ofile
->member_offset
+ offset
) %
3244 temporary_archive_member_warning(ofile
, "fat object file's "
3245 "offset in archive not a multiple of 8) (must be since "
3246 "member is a 64-bit object file)");
3247 archive_64_bit_align_warning
= TRUE
;
3248 /* return(CHECK_BAD); */
3250 #endif /* ALIGNMENT_CHECKS_ARCHIVE_64_BIT */
3254 if(is_llvm_bitcode(ofile
, ofile
->file_addr
+
3255 ofile
->member_offset
+ offset
,
3257 #ifdef ALIGNMENT_CHECKS_ARCHIVE_64_BIT
3258 if(archive_64_bit_align_warning
== FALSE
&&
3259 (ofile
->member_offset
+ offset
) %
3261 temporary_archive_member_warning(ofile
, "fat object "
3262 "file's offset in archive not a multiple of 8) "
3263 "(must be since member is a 64-bit object file)");
3264 archive_64_bit_align_warning
= TRUE
;
3265 /* return(CHECK_BAD); */
3270 #endif /* LTO_SUPPORT */
3272 archive_member_error(ofile
, "fat file for cputype (%d) "
3273 "cpusubtype (%d) is not an object file (bad magic "
3275 cpusubtype
& ~CPU_SUBTYPE_MASK
);
3280 for(i
= 0; i
< ofile
->fat_header
->nfat_arch
; i
++){
3281 for(j
= i
+ 1; j
< ofile
->fat_header
->nfat_arch
; j
++){
3282 if(ofile
->fat_header
->magic
== FAT_MAGIC_64
){
3283 if(ofile
->fat_archs64
[i
].cputype
==
3284 ofile
->fat_archs64
[j
].cputype
&&
3285 (ofile
->fat_archs64
[i
].cpusubtype
& ~CPU_SUBTYPE_MASK
) ==
3286 (ofile
->fat_archs64
[j
].cpusubtype
&
3287 ~CPU_SUBTYPE_MASK
)){
3288 error("fat file: %s contains two of the same "
3289 "architecture (cputype (%d) cpusubtype (%d))",
3290 ofile
->file_name
, ofile
->fat_archs64
[i
].cputype
,
3291 ofile
->fat_archs64
[i
].cpusubtype
&
3297 if(ofile
->fat_archs
[i
].cputype
==
3298 ofile
->fat_archs
[j
].cputype
&&
3299 (ofile
->fat_archs
[i
].cpusubtype
& ~CPU_SUBTYPE_MASK
) ==
3300 (ofile
->fat_archs
[j
].cpusubtype
& ~CPU_SUBTYPE_MASK
)){
3301 error("fat file: %s contains two of the same "
3302 "architecture (cputype (%d) cpusubtype (%d))",
3303 ofile
->file_name
, ofile
->fat_archs
[i
].cputype
,
3304 ofile
->fat_archs
[i
].cpusubtype
&
3315 * check_archive() checks the archive referenced in the ofile for correctness.
3320 struct ofile
*ofile
,
3321 enum bool archives_with_fat_objects
)
3325 #else /* !defined OTOOL */
3327 uint64_t size
, offset
;
3330 enum byte_sex host_byte_sex
;
3332 struct mach_header mh
;
3333 struct mach_header_64 mh64
;
3334 struct ar_hdr
*ar_hdr
;
3335 uint32_t ar_name_size
;
3338 * Get the address and size of the archive (as well as the cputype and
3339 * cpusubtype if known) and make sure it is an archive.
3341 if(ofile
->file_type
== OFILE_FAT
){
3342 if(ofile
->fat_header
->magic
== FAT_MAGIC_64
){
3343 addr
= ofile
->file_addr
+
3344 ofile
->fat_archs64
[ofile
->narch
].offset
;
3345 size
= ofile
->fat_archs64
[ofile
->narch
].size
;
3346 ofile
->archive_cputype
=
3347 ofile
->fat_archs64
[ofile
->narch
].cputype
;
3348 ofile
->archive_cpusubtype
=
3349 ofile
->fat_archs64
[ofile
->narch
].cpusubtype
;
3352 addr
= ofile
->file_addr
+ ofile
->fat_archs
[ofile
->narch
].offset
;
3353 size
= ofile
->fat_archs
[ofile
->narch
].size
;
3354 ofile
->archive_cputype
= ofile
->fat_archs
[ofile
->narch
].cputype
;
3355 ofile
->archive_cpusubtype
=
3356 ofile
->fat_archs
[ofile
->narch
].cpusubtype
;
3359 else if(ofile
->file_type
== OFILE_ARCHIVE
){
3360 addr
= ofile
->file_addr
;
3361 size
= ofile
->file_size
;
3362 ofile
->archive_cputype
= 0;
3363 ofile
->archive_cpusubtype
= 0;
3366 error("internal error. check_archive() call and file type of %s is "
3367 "OFILE_UNKNOWN\n", ofile
->file_name
);
3370 if(size
< SARMAG
|| strncmp(addr
, ARMAG
, SARMAG
) != 0){
3371 error("internal error. check_archive() call for file %s which does "
3372 "not have an archive magic string", ofile
->file_name
);
3376 host_byte_sex
= get_host_byte_sex();
3378 * Check this archive out to make sure that it does not contain
3379 * any fat files and that all object files it contains have the
3380 * same cputype and subsubtype.
3385 if(offset
!= size
&& offset
+ sizeof(struct ar_hdr
) > size
){
3386 archive_error(ofile
, "truncated or malformed (archive header of "
3387 "first member extends past the end of the file)");
3390 while(size
> offset
){
3391 ar_hdr
= (struct ar_hdr
*)(addr
+ offset
);
3392 ofile
->member_offset
= offset
;
3393 ofile
->member_addr
= addr
+ offset
;
3394 ofile
->member_size
= strtoul(ar_hdr
->ar_size
, NULL
, 10);
3395 ofile
->member_ar_hdr
= ar_hdr
;
3396 ofile
->member_name
= ar_hdr
->ar_name
;
3397 ofile
->member_name_size
= size_ar_name(ofile
->member_ar_hdr
);
3398 offset
+= sizeof(struct ar_hdr
);
3400 * See if this archive member is using extend format #1 where
3401 * the size of the name is in ar_name and the name follows the
3405 if(strncmp(ofile
->member_name
,AR_EFMT1
, sizeof(AR_EFMT1
) - 1) == 0){
3406 if(check_extend_format_1(ofile
, ar_hdr
, size
- offset
,
3407 &ar_name_size
) == CHECK_BAD
)
3409 ofile
->member_name
= ar_hdr
->ar_name
+ sizeof(struct ar_hdr
);
3410 ofile
->member_name_size
= ar_name_size
;
3411 offset
+= ar_name_size
;
3412 ofile
->member_offset
+= ar_name_size
;
3413 ofile
->member_addr
+= ar_name_size
;
3414 ofile
->member_size
-= ar_name_size
;
3416 big_size
= rnd(ofile
->member_size
, sizeof(short));
3418 if(big_size
> size
){
3419 archive_member_error(ofile
, "size too large (archive "
3420 "member extends past the end of the file)");
3423 if(size
- offset
> sizeof(uint32_t)){
3424 memcpy(&magic
, addr
+ offset
, sizeof(uint32_t));
3425 #ifdef __BIG_ENDIAN__
3426 if(magic
== FAT_MAGIC
|| (magic
== FAT_MAGIC_64
))
3427 #endif /* __BIG_ENDIAN__ */
3428 #ifdef __LITTLE_ENDIAN__
3429 if(magic
== SWAP_INT(FAT_MAGIC
) ||
3430 magic
== SWAP_INT(FAT_MAGIC_64
))
3431 #endif /* __LITTLE_ENDIAN__ */
3433 if(archives_with_fat_objects
== FALSE
||
3434 ofile
->file_type
!= OFILE_ARCHIVE
){
3435 archive_member_error(ofile
, "is a fat file (not "
3436 "allowed in an archive)");
3441 if(size
- offset
>= sizeof(struct mach_header
) &&
3442 (magic
== MH_MAGIC
|| magic
== SWAP_INT(MH_MAGIC
))){
3443 memcpy(&mh
, addr
+ offset
, sizeof(struct mach_header
));
3444 if(magic
== SWAP_INT(MH_MAGIC
)){
3447 swap_mach_header(&mh
, host_byte_sex
);
3451 else if(size
- offset
>= sizeof(struct mach_header_64
) &&
3452 (magic
== MH_MAGIC_64
||
3453 magic
== SWAP_INT(MH_MAGIC_64
))){
3454 memcpy(&mh64
, addr
+ offset
,
3455 sizeof(struct mach_header_64
));
3456 if(magic
== SWAP_INT(MH_MAGIC_64
)){
3457 magic
= MH_MAGIC_64
;
3459 swap_mach_header_64(&mh64
, host_byte_sex
);
3463 if(magic
== MH_MAGIC
){
3464 if(ofile
->archive_cputype
== 0){
3465 ofile
->archive_cputype
= mh
.cputype
;
3466 ofile
->archive_cpusubtype
= mh
.cpusubtype
;
3468 else if(ofile
->archive_cputype
!= mh
.cputype
){
3469 archive_member_error(ofile
, "cputype (%d) does not "
3470 "match previous archive members cputype (%d) "
3471 "(all members must match)", mh
.cputype
,
3472 ofile
->archive_cputype
);
3475 else if(magic
== MH_MAGIC_64
){
3476 if(ofile
->archive_cputype
== 0){
3477 ofile
->archive_cputype
= mh64
.cputype
;
3478 ofile
->archive_cpusubtype
= mh64
.cpusubtype
;
3480 else if(ofile
->archive_cputype
!= mh64
.cputype
){
3481 archive_member_error(ofile
, "cputype (%d) does not "
3482 "match previous archive members cputype (%d) "
3483 "(all members must match)", mh64
.cputype
,
3484 ofile
->archive_cputype
);
3489 offset
+= rnd(ofile
->member_size
, sizeof(short));
3491 ofile
->member_offset
= 0;
3492 ofile
->member_addr
= NULL
;
3493 ofile
->member_size
= 0;
3494 ofile
->member_ar_hdr
= NULL
;;
3495 ofile
->member_name
= NULL
;
3496 ofile
->member_name_size
= 0;
3502 * check_extend_format_1() checks the archive header for extended format #1.
3506 check_extend_format_1(
3507 struct ofile
*ofile
,
3508 struct ar_hdr
*ar_hdr
,
3510 uint32_t *member_name_size
)
3512 char *p
, *endp
, buf
[sizeof(ar_hdr
->ar_name
)+1];
3513 uint32_t ar_name_size
;
3515 *member_name_size
= 0;
3517 buf
[sizeof(ar_hdr
->ar_name
)] = '\0';
3518 memcpy(buf
, ar_hdr
->ar_name
, sizeof(ar_hdr
->ar_name
));
3519 p
= buf
+ sizeof(AR_EFMT1
) - 1;
3520 if(isdigit(*p
) == 0){
3521 archive_error(ofile
, "malformed (ar_name: %.*s for archive "
3522 "extend format #1 starts with non-digit)",
3523 (int)sizeof(ar_hdr
->ar_name
), ar_hdr
->ar_name
);
3526 ar_name_size
= strtoul(p
, &endp
, 10);
3527 if(ar_name_size
== UINT_MAX
&& errno
== ERANGE
){
3528 archive_error(ofile
, "malformed (size in ar_name: %.*s for "
3529 "archive extend format #1 overflows uint32_t)",
3530 (int)sizeof(ar_hdr
->ar_name
), ar_hdr
->ar_name
);
3533 while(*endp
== ' ' && *endp
!= '\0')
3536 archive_error(ofile
, "malformed (size in ar_name: %.*s for "
3537 "archive extend format #1 contains non-digit and "
3538 "non-space characters)", (int)sizeof(ar_hdr
->ar_name
),
3542 if(ar_name_size
> size_left
){
3543 archive_error(ofile
, "truncated or malformed (archive name "
3544 "of member extends past the end of the file)");
3547 *member_name_size
= ar_name_size
;
3552 * check_archive_toc() checks the archive table of contents referenced in the
3553 * thin archive via the ofile for correctness and if bad sets the bad_toc field
3554 * in the ofile struct to TRUE. If not it sets the other toc_* fields that
3555 * ranlib(1) uses to know it can't update the table of contents and doesn't
3556 * have to totally rebuild it. And by this always returning CHECK_GOOD it
3557 * allows otool(1) to print messed up tables of contents for debugging.
3562 struct ofile
*ofile
)
3564 uint32_t symdef_length
, nranlibs
, strsize
;
3565 uint64_t i
, n
, offset
, ran_off
, nranlibs64
, strsize64
;
3566 enum byte_sex host_byte_sex
, toc_byte_sex
;
3567 struct ranlib
*ranlibs
;
3568 struct ranlib_64
*ranlibs64
;
3570 enum bool toc_is_32bit
;
3572 ofile
->toc_is_32bit
= TRUE
;
3573 ofile
->toc_ranlibs
= NULL
;
3574 ofile
->toc_ranlibs64
= NULL
;
3575 ofile
->toc_nranlibs
= 0;
3576 ofile
->toc_strings
= NULL
;
3577 ofile
->toc_strsize
= 0;
3580 * Note this can only be called when the whole file is a thin archive.
3582 if(ofile
->file_type
!= OFILE_ARCHIVE
)
3585 symdef_length
= ofile
->toc_size
;
3586 if(strncmp(ofile
->member_name
, SYMDEF_64_SORTED
,
3587 ofile
->member_name_size
) == 0 ||
3588 strncmp(ofile
->member_name
, SYMDEF_64
,
3589 ofile
->member_name_size
) == 0)
3590 toc_is_32bit
= FALSE
;
3592 toc_is_32bit
= TRUE
;
3593 if(toc_is_32bit
== TRUE
){
3595 * The contents of a __.SYMDEF file is begins with a 32-bit word
3596 * giving the size in bytes of ranlib structures which immediately
3597 * follow, and then continues with a string table consisting of a
3598 * 32-bit word giving the number of bytes of strings which follow
3599 * and then the strings themselves. So the smallest valid size is
3600 * two 32-bit words long.
3602 if(symdef_length
< 2 * sizeof(uint32_t)){
3604 * Size of table of contents for archive too small to be a valid
3605 * table of contents.
3607 ofile
->toc_bad
= TRUE
;
3612 * The contents of a __.SYMDEF_64 file is begins with a 64-bit word
3613 * giving the size in bytes of ranlib structures which immediately
3614 * follow, and then continues with a string table consisting of a
3615 * 64-bit word giving the number of bytes of strings which follow
3616 * and then the strings themselves. So the smallest valid size is
3617 * two 64-bit words long.
3619 if(symdef_length
< 2 * sizeof(uint64_t)){
3621 * Size of table of contents for archive too small to be a valid
3622 * table of contents.
3624 ofile
->toc_bad
= TRUE
;
3628 host_byte_sex
= get_host_byte_sex();
3629 toc_byte_sex
= get_toc_byte_sex(ofile
->file_addr
, ofile
->file_size
);
3630 if(toc_byte_sex
== UNKNOWN_BYTE_SEX
){
3632 * Can't determine the byte order of table of contents as it
3633 * contains no Mach-O files.
3635 ofile
->toc_bad
= TRUE
;
3639 if(toc_is_32bit
== TRUE
){
3640 nranlibs
= *((uint32_t *)(ofile
->toc_addr
+ offset
));
3641 if(toc_byte_sex
!= host_byte_sex
)
3642 nranlibs
= SWAP_INT(nranlibs
);
3643 nranlibs
= nranlibs
/ sizeof(struct ranlib
);
3645 offset
+= sizeof(uint32_t);
3647 ranlibs
= (struct ranlib
*)(ofile
->toc_addr
+ offset
);
3648 offset
+= sizeof(struct ranlib
) * nranlibs
;
3651 if(offset
- (2 * sizeof(uint32_t)) > symdef_length
){
3653 * Truncated or malformed archive. The ranlib structures in
3654 * table of contents extends past the end of the table of
3657 ofile
->toc_bad
= TRUE
;
3661 strsize
= *((uint32_t *)(ofile
->toc_addr
+ offset
));
3662 if(toc_byte_sex
!= host_byte_sex
)
3663 strsize
= SWAP_INT(strsize
);
3664 offset
+= sizeof(uint32_t);
3666 strings
= ofile
->toc_addr
+ offset
;
3668 if(offset
- (2 * sizeof(uint32_t)) > symdef_length
){
3670 * Truncated or malformed archive. The ranlib strings in table
3671 * of contents extends past the end of the table of contents.
3673 ofile
->toc_bad
= TRUE
;
3676 if(symdef_length
== 2 * sizeof(uint32_t))
3679 nranlibs64
= *((uint64_t *)(ofile
->toc_addr
+ offset
));
3680 if(toc_byte_sex
!= host_byte_sex
)
3681 nranlibs64
= SWAP_LONG_LONG(nranlibs64
);
3682 nranlibs64
= nranlibs64
/ sizeof(struct ranlib_64
);
3684 offset
+= sizeof(uint64_t);
3686 ranlibs64
= (struct ranlib_64
*)(ofile
->toc_addr
+ offset
);
3687 offset
+= sizeof(struct ranlib_64
) * nranlibs64
;
3690 if(offset
- (2 * sizeof(uint64_t)) > symdef_length
){
3692 * Truncated or malformed archive. The ranlib structures in
3693 * table of contents extends past the end of the table of
3696 ofile
->toc_bad
= TRUE
;
3700 strsize64
= *((uint64_t *)(ofile
->toc_addr
+ offset
));
3701 if(toc_byte_sex
!= host_byte_sex
)
3702 strsize64
= SWAP_LONG_LONG(strsize64
);
3703 offset
+= sizeof(uint64_t);
3705 strings
= ofile
->toc_addr
+ offset
;
3706 offset
+= strsize64
;
3707 if(offset
- (2 * sizeof(uint64_t)) > symdef_length
){
3709 * Truncated or malformed archive. The ranlib strings in table
3710 * of contents extends past the end of the table of contents.
3712 ofile
->toc_bad
= TRUE
;
3715 if(symdef_length
== 2 * sizeof(uint64_t))
3720 * Check the string offset and the member offsets of the ranlib structs.
3722 if(toc_byte_sex
!= host_byte_sex
){
3723 if(toc_is_32bit
== TRUE
)
3724 swap_ranlib(ranlibs
, nranlibs
, host_byte_sex
);
3726 swap_ranlib_64(ranlibs64
, nranlibs64
, host_byte_sex
);
3728 for(i
= 0; i
< n
; i
++){
3729 if(toc_is_32bit
== TRUE
){
3730 if(ranlibs
[i
].ran_un
.ran_strx
>= strsize
){
3732 * Malformed table of contents. The ranlib struct at this
3733 * index has a bad string index field.
3735 ofile
->toc_bad
= TRUE
;
3738 if(ranlibs
[i
].ran_off
>= ofile
->file_size
){
3740 * Malformed table of contents. The ranlib struct at this
3741 * index has a bad library member offset field.
3743 ofile
->toc_bad
= TRUE
;
3746 ran_off
= ranlibs
[i
].ran_off
;
3748 if(ranlibs64
[i
].ran_un
.ran_strx
>= strsize64
){
3750 * Malformed table of contents. The ranlib struct at this
3751 * index has a bad string index field.
3753 ofile
->toc_bad
= TRUE
;
3756 if(ranlibs64
[i
].ran_off
>= ofile
->file_size
){
3758 * Malformed table of contents. The ranlib struct at this
3759 * index has a bad library member offset field.
3761 ofile
->toc_bad
= TRUE
;
3764 ran_off
= ranlibs64
[i
].ran_off
;
3768 * These should be on 4 byte boundaries because the maximum
3769 * alignment of the header structures and relocation are 4 bytes.
3770 * But this is has to be 2 bytes because that's the way ar(1) has
3771 * worked historicly in the past. Fortunately this works on the
3772 * 68k machines but will have to change when this is on a real
3775 #if defined(mc68000) || defined(__i386__)
3776 if(ran_off
% sizeof(short) != 0){
3778 * Malformed table of contents. This ranlib struct library
3779 * member offset not a multiple 2 bytes.
3781 ofile
->toc_bad
= TRUE
;
3785 if(toc_is_32bit
== TRUE
){
3786 if(ran_off
% sizeof(uint32_t) != 0){
3788 * Malformed table of contents. This ranlib struct library
3789 * member offset not a multiple of 4 bytes.
3791 ofile
->toc_bad
= TRUE
;
3795 if(ran_off
% sizeof(uint64_t) != 0){
3797 * Malformed table of contents. This ranlib struct library
3798 * member offset not a multiple of 8 bytes.
3800 ofile
->toc_bad
= TRUE
;
3806 ofile
->toc_is_32bit
= toc_is_32bit
;
3807 ofile
->toc_ranlibs
= ranlibs
;
3808 ofile
->toc_ranlibs64
= ranlibs64
;
3809 ofile
->toc_strings
= strings
;
3810 if(toc_is_32bit
== TRUE
){
3811 ofile
->toc_nranlibs
= nranlibs
;
3812 ofile
->toc_strsize
= strsize
;
3814 ofile
->toc_nranlibs
= nranlibs64
;
3815 ofile
->toc_strsize
= strsize64
;
3821 * check_Mach_O() checks the object file's mach header and load commands
3822 * referenced in the ofile for correctness (this also swaps the mach header
3823 * and load commands into the host byte sex if needed).
3828 struct ofile
*ofile
)
3832 #else /* !defined OTOOL */
3833 uint32_t size
, i
, j
, ncmds
, sizeofcmds
, load_command_multiple
, sizeofhdrs
;
3835 char *addr
, *cmd_name
, *element_name
;
3836 enum byte_sex host_byte_sex
;
3838 struct mach_header
*mh
;
3839 struct mach_header_64
*mh64
;
3840 struct load_command
*load_commands
, *lc
, l
;
3841 struct segment_command
*sg
;
3842 struct segment_command_64
*sg64
;
3844 struct section_64
*s64
;
3845 struct symtab_command
*st
;
3846 struct dysymtab_command
*dyst
;
3847 struct symseg_command
*ss
;
3848 struct fvmlib_command
*fl
;
3849 struct dylib_command
*dl
;
3850 struct sub_framework_command
*sub
;
3851 struct sub_umbrella_command
*usub
;
3852 struct sub_library_command
*lsub
;
3853 struct sub_client_command
*csub
;
3854 struct prebound_dylib_command
*pbdylib
;
3855 struct dylinker_command
*dyld
;
3856 struct thread_command
*ut
;
3857 struct ident_command
*id
;
3858 struct routines_command
*rc
;
3859 struct routines_command_64
*rc64
;
3860 struct twolevel_hints_command
*hints
;
3861 struct linkedit_data_command
*code_sig
, *split_info
, *func_starts
,
3862 *data_in_code
, *code_sign_drs
, *linkedit_data
;
3863 struct linkedit_data_command
*link_opt_hint
;
3864 struct version_min_command
*vers
;
3865 struct prebind_cksum_command
*cs
;
3866 struct encryption_info_command
*encrypt_info
;
3867 struct encryption_info_command_64
*encrypt_info64
;
3868 struct linker_option_command
*lo
;
3869 struct dyld_info_command
*dyld_info
;
3870 struct uuid_command
*uuid
;
3871 struct rpath_command
*rpath
;
3872 struct entry_point_command
*ep
;
3873 struct source_version_command
*sv
;
3874 uint32_t flavor
, count
, nflavor
;
3876 uint32_t sizeof_nlist
, sizeof_dylib_module
;
3877 char *struct_dylib_module_name
, *struct_nlist_name
;
3878 uint64_t big_size
, big_end
, big_load_end
;
3879 struct element elements
;
3880 cpu_type_t fat_cputype
;
3882 elements
.offset
= 0;
3884 elements
.name
= NULL
;
3885 elements
.next
= NULL
;
3887 addr
= ofile
->object_addr
;
3888 size
= ofile
->object_size
;
3891 load_commands
= ofile
->load_commands
;
3892 host_byte_sex
= get_host_byte_sex();
3893 swapped
= (enum bool)(host_byte_sex
!= ofile
->object_byte_sex
);
3895 if(ofile
->mh
!= NULL
){
3897 swap_mach_header(mh
, host_byte_sex
);
3898 big_size
= mh
->sizeofcmds
;
3899 big_size
+= sizeof(struct mach_header
);
3900 if(big_size
> size
){
3901 Mach_O_error(ofile
, "truncated or malformed object (load "
3902 "commands extend past the end of the file)");
3905 sizeofhdrs
= big_size
;
3906 ofile
->mh_cputype
= mh
->cputype
;
3907 ofile
->mh_cpusubtype
= mh
->cpusubtype
;
3908 ofile
->mh_filetype
= mh
->filetype
;
3910 sizeofcmds
= mh
->sizeofcmds
;
3911 cputype
= mh
->cputype
;
3912 load_command_multiple
= 4;
3913 sizeof_nlist
= sizeof(struct nlist
);
3914 struct_nlist_name
= "struct nlist";
3915 sizeof_dylib_module
= sizeof(struct dylib_module
);
3916 struct_dylib_module_name
= "struct dylib_module";
3920 swap_mach_header_64(mh64
, host_byte_sex
);
3921 big_size
= mh64
->sizeofcmds
;
3922 big_size
+= sizeof(struct mach_header_64
);
3923 if(big_size
> size
){
3924 Mach_O_error(ofile
, "truncated or malformed object (load "
3925 "commands extend past the end of the file)");
3928 sizeofhdrs
= big_size
;
3929 ofile
->mh_cputype
= mh64
->cputype
;
3930 ofile
->mh_cpusubtype
= mh64
->cpusubtype
;
3931 ofile
->mh_filetype
= mh64
->filetype
;
3932 ncmds
= mh64
->ncmds
;
3933 sizeofcmds
= mh64
->sizeofcmds
;
3934 cputype
= mh64
->cputype
;
3935 load_command_multiple
= 8;
3936 sizeof_nlist
= sizeof(struct nlist_64
);
3937 struct_nlist_name
= "struct nlist_64";
3938 sizeof_dylib_module
= sizeof(struct dylib_module_64
);
3939 struct_dylib_module_name
= "struct dylib_module_64";
3941 if(check_overlaping_element(ofile
, &elements
, 0, sizeofhdrs
,
3942 "Mach-O headers") == CHECK_BAD
)
3944 if(ofile
->file_type
== OFILE_FAT
){
3945 if(ofile
->fat_header
->magic
== FAT_MAGIC_64
)
3946 fat_cputype
= ofile
->fat_archs64
[ofile
->narch
].cputype
;
3948 fat_cputype
= ofile
->fat_archs
[ofile
->narch
].cputype
;
3949 if(fat_cputype
!= ofile
->mh_cputype
){
3950 Mach_O_error(ofile
, "malformed fat file (fat header "
3951 "architecture: %u's cputype does not match "
3952 "object file's mach header)", ofile
->narch
);
3957 * Make a pass through the load commands checking them to the level
3958 * that they can be parsed and all fields with offsets and sizes do
3959 * not extend past the end of the file.
3968 data_in_code
= NULL
;
3969 code_sign_drs
= NULL
;
3970 link_opt_hint
= NULL
;
3974 encrypt_info
= NULL
;
3978 for(i
= 0, lc
= load_commands
; i
< ncmds
; i
++){
3979 if(big_load_end
+ sizeof(struct load_command
) > sizeofcmds
){
3980 Mach_O_error(ofile
, "truncated or malformed object (load "
3981 "command %u extends past the end all load "
3982 "commands in the file)", i
);
3987 swap_load_command(&l
, host_byte_sex
);
3989 * Check load command size for a multiple of load_command_multiple.
3991 if(l
.cmdsize
% load_command_multiple
!= 0){
3993 * We have a hack here to allow 64-bit Mach-O core files to
3994 * have LC_THREAD commands that are only a multiple of 4 and
3995 * not 8 to be allowed since the kernel produces them.
3997 if(ofile
->mh64
== NULL
||
3998 ofile
->mh64
->filetype
!= MH_CORE
||
3999 l
.cmd
!= LC_THREAD
||
4000 l
.cmdsize
% 4 != 0){
4001 Mach_O_error(ofile
, "malformed object (load command %u "
4002 "cmdsize not a multiple of %u)", i
,
4003 load_command_multiple
);
4007 /* check that load command does not extends past end of commands */
4008 big_load_end
+= l
.cmdsize
;
4009 if(big_load_end
> sizeofcmds
){
4010 Mach_O_error(ofile
, "truncated or malformed object (load "
4011 "command %u extends past the end of the file)",i
);
4014 /* check that the load command size is not zero */
4016 Mach_O_error(ofile
, "malformed object (load command %u cmdsize"
4022 if(l
.cmdsize
< sizeof(struct segment_command
)){
4023 Mach_O_error(ofile
, "malformed object (LC_SEGMENT cmdsize "
4024 "too small) in command %u", i
);
4027 sg
= (struct segment_command
*)lc
;
4029 swap_segment_command(sg
, host_byte_sex
);
4030 big_size
= sg
->nsects
;
4031 big_size
*= sizeof(struct section
);
4032 big_size
+= sizeof(struct segment_command
);
4033 if(sg
->cmdsize
!= big_size
){
4034 Mach_O_error(ofile
, "malformed object (inconsistent "
4035 "cmdsize in LC_SEGMENT command %u for the "
4036 "number of sections)", i
);
4039 if(sg
->fileoff
> size
){
4040 Mach_O_error(ofile
, "truncated or malformed object ("
4041 "LC_SEGMENT command %u fileoff field "
4042 "extends past the end of the file)", i
);
4045 big_size
= sg
->fileoff
;
4046 big_size
+= sg
->filesize
;
4047 if(big_size
> size
){
4048 Mach_O_error(ofile
, "truncated or malformed object ("
4049 "LC_SEGMENT command %u fileoff field "
4050 "plus filesize field extends past the end of "
4054 if(sg
->vmsize
!= 0 && sg
->filesize
> sg
->vmsize
){
4055 Mach_O_error(ofile
, "malformed object (LC_SEGMENT command "
4056 "%u filesize field greater than vmsize field)",
4060 s
= (struct section
*)
4061 ((char *)sg
+ sizeof(struct segment_command
));
4063 swap_section(s
, sg
->nsects
, host_byte_sex
);
4064 for(j
= 0 ; j
< sg
->nsects
; j
++){
4065 if(mh
->filetype
!= MH_DYLIB_STUB
&&
4066 mh
->filetype
!= MH_DSYM
&&
4067 s
->flags
!= S_ZEROFILL
&&
4068 s
->flags
!= S_THREAD_LOCAL_ZEROFILL
&& s
->offset
> size
){
4069 Mach_O_error(ofile
, "truncated or malformed object "
4070 "(offset field of section %u in LC_SEGMENT "
4071 "command %u extends past the end of the file)",
4075 if(mh
->filetype
!= MH_DYLIB_STUB
&&
4076 mh
->filetype
!= MH_DSYM
&&
4077 s
->flags
!= S_ZEROFILL
&&
4078 s
->flags
!= S_THREAD_LOCAL_ZEROFILL
&&
4079 sg
->fileoff
== 0 && s
->offset
< sizeofhdrs
&&
4081 Mach_O_error(ofile
, "malformed object (offset field of "
4082 "section %u in LC_SEGMENT command %u not "
4083 "past the headers of the file)", j
, i
);
4086 big_size
= s
->offset
;
4087 big_size
+= s
->size
;
4088 if(mh
->filetype
!= MH_DYLIB_STUB
&&
4089 mh
->filetype
!= MH_DSYM
&&
4090 s
->flags
!= S_ZEROFILL
&&
4091 s
->flags
!= S_THREAD_LOCAL_ZEROFILL
&& big_size
> size
){
4092 Mach_O_error(ofile
, "truncated or malformed object "
4093 "(offset field plus size field of section %u "
4094 "in LC_SEGMENT command %u extends "
4095 "past the end of the file)", j
, i
);
4098 if(mh
->filetype
!= MH_DYLIB_STUB
&&
4099 mh
->filetype
!= MH_DSYM
&&
4100 s
->flags
!= S_ZEROFILL
&&
4101 s
->flags
!= S_THREAD_LOCAL_ZEROFILL
&&
4102 s
->size
> sg
->filesize
){
4103 Mach_O_error(ofile
, "malformed object (size field of "
4104 "section %u in LC_SEGMENT command %u greater "
4105 "than the segment)", j
, i
);
4108 if(mh
->filetype
!= MH_DYLIB_STUB
&&
4109 mh
->filetype
!= MH_DSYM
&&
4110 s
->size
!= 0 && s
->addr
< sg
->vmaddr
){
4111 Mach_O_error(ofile
, "malformed object (addr field of "
4112 "section %u in LC_SEGMENT command %u less than "
4113 "the segment's vmaddr)", j
, i
);
4117 big_size
+= s
->size
;
4118 big_end
= sg
->vmaddr
;
4119 big_end
+= sg
->vmsize
;
4120 if(sg
->vmsize
!= 0 && s
->size
!= 0 && big_size
> big_end
){
4121 Mach_O_error(ofile
, "malformed object (addr field plus "
4122 "size of section %u in LC_SEGMENT command %u "
4123 "greater than than the segment's vmaddr plus "
4127 if(mh
->filetype
!= MH_DYLIB_STUB
&&
4128 mh
->filetype
!= MH_DSYM
&&
4129 s
->flags
!= S_ZEROFILL
&&
4130 s
->flags
!= S_THREAD_LOCAL_ZEROFILL
&&
4131 check_overlaping_element(ofile
, &elements
, s
->offset
,
4132 s
->size
, "section contents") == CHECK_BAD
)
4134 if(s
->reloff
> size
){
4135 Mach_O_error(ofile
, "truncated or malformed object "
4136 "(reloff field of section %u in LC_SEGMENT "
4137 "command %u extends past the end of the file)",
4141 big_size
= s
->nreloc
;
4142 big_size
*= sizeof(struct relocation_info
);
4143 big_size
+= s
->reloff
;
4144 if(big_size
> size
){
4145 Mach_O_error(ofile
, "truncated or malformed object "
4146 "(reloff field plus nreloc field times sizeof("
4147 "struct relocation_info) of section %u in "
4148 "LC_SEGMENT command %u extends past the "
4149 "end of the file)", j
, i
);
4152 if(check_overlaping_element(ofile
, &elements
, s
->reloff
,
4153 s
->nreloc
* sizeof(struct relocation_info
),
4154 "section relocation entries") == CHECK_BAD
)
4161 if(l
.cmdsize
< sizeof(struct segment_command_64
)){
4162 Mach_O_error(ofile
, "malformed object (LC_SEGMENT_64 "
4163 "cmdsize too small) in command %u", i
);
4166 sg64
= (struct segment_command_64
*)lc
;
4168 swap_segment_command_64(sg64
, host_byte_sex
);
4169 big_size
= sg64
->nsects
;
4170 big_size
*= sizeof(struct section_64
);
4171 big_size
+= sizeof(struct segment_command_64
);
4172 if(sg64
->cmdsize
!= big_size
){
4173 Mach_O_error(ofile
, "malformed object (inconsistent "
4174 "cmdsize in LC_SEGMENT_64 command %u for "
4175 "the number of sections)", i
);
4178 if(sg64
->fileoff
> size
){
4179 Mach_O_error(ofile
, "truncated or malformed object ("
4180 "LC_SEGMENT_64 command %u fileoff field "
4181 "extends past the end of the file)", i
);
4184 big_size
= sg64
->fileoff
;
4185 big_size
+= sg64
->filesize
;
4186 if(big_size
> size
){
4187 Mach_O_error(ofile
, "truncated or malformed object ("
4188 "LC_SEGMENT_64 command %u fileoff field "
4189 "plus filesize field extends past the end of "
4193 s64
= (struct section_64
*)
4194 ((char *)sg64
+ sizeof(struct segment_command_64
));
4196 swap_section_64(s64
, sg64
->nsects
, host_byte_sex
);
4197 for(j
= 0 ; j
< sg64
->nsects
; j
++){
4198 if(mh64
->filetype
!= MH_DYLIB_STUB
&&
4199 mh64
->filetype
!= MH_DSYM
&&
4200 s64
->flags
!= S_ZEROFILL
&&
4201 s64
->flags
!= S_THREAD_LOCAL_ZEROFILL
&&
4202 s64
->offset
> size
){
4203 Mach_O_error(ofile
, "truncated or malformed object "
4204 "(offset field of section %u in LC_SEGMENT_64 "
4205 "command %u extends past the end of the file)",
4209 if(mh64
->filetype
!= MH_DYLIB_STUB
&&
4210 mh64
->filetype
!= MH_DSYM
&&
4211 s64
->flags
!= S_ZEROFILL
&&
4212 s64
->flags
!= S_THREAD_LOCAL_ZEROFILL
&&
4213 sg64
->fileoff
== 0 && s64
->offset
< sizeofhdrs
&&
4215 Mach_O_error(ofile
, "malformed object (offset field of "
4216 "section %u in LC_SEGMENT command %u not "
4217 "past the headers of the file)", j
, i
);
4220 big_size
= s64
->offset
;
4221 big_size
+= s64
->size
;
4222 if(mh64
->filetype
!= MH_DYLIB_STUB
&&
4223 mh64
->filetype
!= MH_DSYM
&&
4224 s64
->flags
!= S_ZEROFILL
&&
4225 s64
->flags
!= S_THREAD_LOCAL_ZEROFILL
&&
4227 Mach_O_error(ofile
, "truncated or malformed object "
4228 "(offset field plus size field of section %u "
4229 "in LC_SEGMENT_64 command %u extends "
4230 "past the end of the file)", j
, i
);
4233 if(mh64
->filetype
!= MH_DYLIB_STUB
&&
4234 mh64
->filetype
!= MH_DSYM
&&
4235 s64
->flags
!= S_ZEROFILL
&&
4236 s64
->flags
!= S_THREAD_LOCAL_ZEROFILL
&&
4237 check_overlaping_element(ofile
, &elements
, s64
->offset
,
4238 s64
->size
, "section contents") == CHECK_BAD
)
4240 if(s64
->reloff
> size
){
4241 Mach_O_error(ofile
, "truncated or malformed object "
4242 "(reloff field of section %u in LC_SEGMENT_64 "
4243 "command %u extends past the end of the file)",
4247 big_size
= s64
->nreloc
;
4248 big_size
*= sizeof(struct relocation_info
);
4249 big_size
+= s64
->reloff
;
4250 if(big_size
> size
){
4251 Mach_O_error(ofile
, "truncated or malformed object "
4252 "(reloff field plus nreloc field times sizeof("
4253 "struct relocation_info) of section %u in "
4254 "LC_SEGMENT_64 command %u extends past the "
4255 "end of the file)", j
, i
);
4258 if(check_overlaping_element(ofile
, &elements
, s64
->reloff
,
4259 s64
->nreloc
* sizeof(struct relocation_info
),
4260 "section relocation entries") == CHECK_BAD
)
4267 if(l
.cmdsize
< sizeof(struct symtab_command
)){
4268 Mach_O_error(ofile
, "malformed object (LC_SYMTAB cmdsize "
4269 "too small) in command %u", i
);
4273 Mach_O_error(ofile
, "malformed object (more than one "
4274 "LC_SYMTAB command)");
4277 st
= (struct symtab_command
*)lc
;
4279 swap_symtab_command(st
, host_byte_sex
);
4280 if(st
->cmdsize
!= sizeof(struct symtab_command
)){
4281 Mach_O_error(ofile
, "malformed object (LC_SYMTAB command "
4282 "%u has incorrect cmdsize)", i
);
4285 if(st
->symoff
> size
){
4286 Mach_O_error(ofile
, "truncated or malformed object (symoff "
4287 "field of LC_SYMTAB command %u extends past the end "
4291 big_size
= st
->nsyms
;
4292 big_size
*= sizeof_nlist
;
4293 big_size
+= st
->symoff
;
4294 if(big_size
> size
){
4295 Mach_O_error(ofile
, "truncated or malformed object (symoff "
4296 "field plus nsyms field times sizeof(%s) of LC_SYMTAB "
4297 "command %u extends past the end of the file)",
4298 struct_nlist_name
, i
);
4301 if(check_overlaping_element(ofile
, &elements
, st
->symoff
,
4302 st
->nsyms
* sizeof_nlist
, "symbol table") == CHECK_BAD
)
4304 if(st
->stroff
> size
){
4305 Mach_O_error(ofile
, "truncated or malformed object (stroff "
4306 "field of LC_SYMTAB command %u extends past the end "
4310 big_size
= st
->stroff
;
4311 big_size
+= st
->strsize
;
4312 if(big_size
> size
){
4313 Mach_O_error(ofile
, "truncated or malformed object (stroff "
4314 "field plus strsize field of LC_SYMTAB command %u "
4315 "extends past the end of the file)", i
);
4318 if(check_overlaping_element(ofile
, &elements
, st
->stroff
,
4319 st
->strsize
, "string table") == CHECK_BAD
)
4324 if(l
.cmdsize
< sizeof(struct dysymtab_command
)){
4325 Mach_O_error(ofile
, "malformed object (LC_DYSYMTAB cmdsize "
4326 "too small) in command %u", i
);
4330 Mach_O_error(ofile
, "malformed object (more than one "
4331 "LC_DYSYMTAB command)");
4334 dyst
= (struct dysymtab_command
*)lc
;
4336 swap_dysymtab_command(dyst
, host_byte_sex
);
4337 if(dyst
->cmdsize
!= sizeof(struct dysymtab_command
)){
4338 Mach_O_error(ofile
, "malformed object (LC_DYSYMTAB command "
4339 "%u has incorrect cmdsize)", i
);
4342 if(dyst
->tocoff
> size
){
4343 Mach_O_error(ofile
, "truncated or malformed object (tocoff "
4344 "field of LC_DYSYMTAB command %u extends past the end "
4348 big_size
= dyst
->ntoc
;
4349 big_size
*= sizeof(struct dylib_table_of_contents
);
4350 big_size
+= dyst
->tocoff
;
4351 if(big_size
> size
){
4352 Mach_O_error(ofile
, "truncated or malformed object (tocoff "
4353 "field plus ntoc field times sizeof(struct dylib_table"
4354 "_of_contents) of LC_DYSYMTAB command %u extends past "
4355 "the end of the file)", i
);
4358 if(check_overlaping_element(ofile
, &elements
, dyst
->tocoff
,
4359 dyst
->ntoc
* sizeof(struct dylib_table_of_contents
),
4360 "table of contents") == CHECK_BAD
)
4362 if(dyst
->modtaboff
> size
){
4363 Mach_O_error(ofile
, "truncated or malformed object "
4364 "(modtaboff field of LC_DYSYMTAB command %u extends "
4365 "past the end of the file)", i
);
4368 big_size
= dyst
->nmodtab
;
4369 big_size
*= sizeof_dylib_module
;
4370 big_size
+= dyst
->modtaboff
;
4371 if(big_size
> size
){
4372 Mach_O_error(ofile
, "truncated or malformed object "
4373 "(modtaboff field plus nmodtab field times sizeof(%s) "
4374 "of LC_DYSYMTAB command %u extends past the end of "
4375 "the file)", struct_dylib_module_name
, i
);
4378 if(check_overlaping_element(ofile
, &elements
, dyst
->modtaboff
,
4379 dyst
->nmodtab
* sizeof_dylib_module
, "module table") ==
4382 if(dyst
->extrefsymoff
> size
){
4383 Mach_O_error(ofile
, "truncated or malformed object "
4384 "(extrefsymoff field of LC_DYSYMTAB command %u "
4385 "extends past the end of the file)", i
);
4388 big_size
= dyst
->nextrefsyms
;
4389 big_size
*= sizeof(struct dylib_reference
);
4390 big_size
+= dyst
->extrefsymoff
;
4391 if(big_size
> size
){
4392 Mach_O_error(ofile
, "truncated or malformed object "
4393 "(extrefsymoff field plus nextrefsyms field times "
4394 "sizeof(struct dylib_reference) of LC_DYSYMTAB command "
4395 "%u extends past the end of the file)", i
);
4398 if(check_overlaping_element(ofile
, &elements
,dyst
->extrefsymoff
,
4399 dyst
->nextrefsyms
* sizeof(struct dylib_reference
),
4400 "reference table") == CHECK_BAD
)
4402 if(dyst
->indirectsymoff
> size
){
4403 Mach_O_error(ofile
, "truncated or malformed object "
4404 "(indirectsymoff field of LC_DYSYMTAB command %u "
4405 "extends past the end of the file)", i
);
4408 big_size
= dyst
->nindirectsyms
;
4409 big_size
*= sizeof(uint32_t);
4410 big_size
+= dyst
->indirectsymoff
;
4411 if(big_size
> size
){
4412 Mach_O_error(ofile
, "truncated or malformed object "
4413 "(indirectsymoff field plus nindirectsyms field times "
4414 "sizeof(uint32_t) of LC_DYSYMTAB command "
4415 "%u extends past the end of the file)", i
);
4418 if(check_overlaping_element(ofile
, &elements
,
4419 dyst
->indirectsymoff
, dyst
->nindirectsyms
*
4420 sizeof(uint32_t), "indirect table") == CHECK_BAD
)
4422 if(dyst
->extreloff
> size
){
4423 Mach_O_error(ofile
, "truncated or malformed object "
4424 "(extreloff field of LC_DYSYMTAB command %u "
4425 "extends past the end of the file)", i
);
4428 big_size
= dyst
->nextrel
;
4429 big_size
*= sizeof(struct relocation_info
);
4430 big_size
+= dyst
->extreloff
;
4431 if(big_size
> size
){
4432 Mach_O_error(ofile
, "truncated or malformed object "
4433 "(extreloff field plus nextrel field times "
4434 "sizeof(struct relocation_info) of LC_DYSYMTAB command "
4435 "%u extends past the end of the file)", i
);
4438 if(check_overlaping_element(ofile
, &elements
, dyst
->extreloff
,
4439 dyst
->nextrel
* sizeof(struct relocation_info
),
4440 "external relocation table") == CHECK_BAD
)
4442 if(dyst
->locreloff
> size
){
4443 Mach_O_error(ofile
, "truncated or malformed object "
4444 "(locreloff field of LC_DYSYMTAB command %u "
4445 "extends past the end of the file)", i
);
4448 big_size
= dyst
->nlocrel
;
4449 big_size
*= sizeof(struct relocation_info
);
4450 big_size
+= dyst
->locreloff
;
4451 if(big_size
> size
){
4452 Mach_O_error(ofile
, "truncated or malformed object "
4453 "(locreloff field plus nlocrel field times "
4454 "sizeof(struct relocation_info) of LC_DYSYMTAB command "
4455 "%u extends past the end of the file)", i
);
4458 if(check_overlaping_element(ofile
, &elements
, dyst
->locreloff
,
4459 dyst
->nlocrel
* sizeof(struct relocation_info
),
4460 "local relocation table") == CHECK_BAD
)
4465 if(l
.cmdsize
< sizeof(struct routines_command
)){
4466 Mach_O_error(ofile
, "malformed object (LC_ROUTINES cmdsize "
4467 "too small) in command %u", i
);
4471 Mach_O_error(ofile
, "malformed object (more than one "
4472 "LC_ROUTINES command)");
4475 rc
= (struct routines_command
*)lc
;
4477 swap_routines_command(rc
, host_byte_sex
);
4478 if(rc
->cmdsize
!= sizeof(struct routines_command
)){
4479 Mach_O_error(ofile
, "malformed object (LC_ROUTINES "
4480 "command %u has incorrect cmdsize)", i
);
4485 case LC_ROUTINES_64
:
4486 if(l
.cmdsize
< sizeof(struct routines_command_64
)){
4487 Mach_O_error(ofile
, "malformed object (LC_ROUTINES_64 "
4488 "cmdsize too small) in command %u", i
);
4492 Mach_O_error(ofile
, "malformed object (more than one "
4493 "LC_ROUTINES_64 command)");
4496 rc64
= (struct routines_command_64
*)lc
;
4498 swap_routines_command_64(rc64
, host_byte_sex
);
4499 if(rc64
->cmdsize
!= sizeof(struct routines_command_64
)){
4500 Mach_O_error(ofile
, "malformed object (LC_ROUTINES_64 "
4501 "command %u has incorrect cmdsize)", i
);
4506 case LC_TWOLEVEL_HINTS
:
4507 if(l
.cmdsize
< sizeof(struct twolevel_hints_command
)){
4508 Mach_O_error(ofile
, "malformed object (LC_TWOLEVEL_HINTS "
4509 "cmdsize too small) in command %u", i
);
4513 Mach_O_error(ofile
, "malformed object (more than one "
4514 "LC_TWOLEVEL_HINTS command)");
4517 hints
= (struct twolevel_hints_command
*)lc
;
4519 swap_twolevel_hints_command(hints
, host_byte_sex
);
4520 if(hints
->cmdsize
!= sizeof(struct twolevel_hints_command
)){
4521 Mach_O_error(ofile
, "malformed object (LC_TWOLEVEL_HINTS "
4522 "command %u has incorrect cmdsize)", i
);
4525 if(hints
->offset
> size
){
4526 Mach_O_error(ofile
, "truncated or malformed object "
4527 "(offset field of LC_TWOLEVEL_HINTS command %u "
4528 "extends past the end of the file)", i
);
4531 big_size
= hints
->nhints
;
4532 big_size
*= sizeof(struct twolevel_hint
);
4533 big_size
+= hints
->offset
;
4534 if(big_size
> size
){
4535 Mach_O_error(ofile
, "truncated or malformed object "
4536 "(offset field plus nhints field times "
4537 "sizeof(struct twolevel_hint) of LC_TWOLEVEL_HINTS "
4538 " command %u extends past the end of the file)", i
);
4541 if(check_overlaping_element(ofile
, &elements
, hints
->offset
,
4542 hints
->nhints
* sizeof(struct twolevel_hint
),
4543 "two level hints") == CHECK_BAD
)
4547 case LC_SEGMENT_SPLIT_INFO
:
4548 cmd_name
= "LC_SEGMENT_SPLIT_INFO";
4549 element_name
= "split info data";
4550 if(split_info
!= NULL
){
4551 Mach_O_error(ofile
, "malformed object (more than one "
4552 "%s command)", cmd_name
);
4555 split_info
= (struct linkedit_data_command
*)lc
;
4556 goto check_linkedit_data_command
;
4558 case LC_CODE_SIGNATURE
:
4559 cmd_name
= "LC_CODE_SIGNATURE";
4560 element_name
= "code signature data";
4561 if(code_sig
!= NULL
){
4562 Mach_O_error(ofile
, "malformed object (more than one "
4563 "%s command)", cmd_name
);
4566 code_sig
= (struct linkedit_data_command
*)lc
;
4567 goto check_linkedit_data_command
;
4569 case LC_FUNCTION_STARTS
:
4570 cmd_name
= "LC_FUNCTION_STARTS";
4571 element_name
= "function starts data";
4572 if(func_starts
!= NULL
){
4573 Mach_O_error(ofile
, "malformed object (more than one "
4574 "%s command)", cmd_name
);
4577 func_starts
= (struct linkedit_data_command
*)lc
;
4578 goto check_linkedit_data_command
;
4580 case LC_DATA_IN_CODE
:
4581 cmd_name
= "LC_DATA_IN_CODE";
4582 element_name
= "date in code info";
4583 if(data_in_code
!= NULL
){
4584 Mach_O_error(ofile
, "malformed object (more than one "
4585 "%s command)", cmd_name
);
4588 data_in_code
= (struct linkedit_data_command
*)lc
;
4589 goto check_linkedit_data_command
;
4591 case LC_DYLIB_CODE_SIGN_DRS
:
4592 cmd_name
= "LC_DYLIB_CODE_SIGN_DRS";
4593 element_name
= "code signing RDs data";
4594 if(code_sign_drs
!= NULL
){
4595 Mach_O_error(ofile
, "malformed object (more than one "
4596 "%s command)", cmd_name
);
4599 code_sign_drs
= (struct linkedit_data_command
*)lc
;
4600 goto check_linkedit_data_command
;
4602 case LC_LINKER_OPTIMIZATION_HINT
:
4603 cmd_name
= "LC_LINKER_OPTIMIZATION_HINT";
4604 element_name
= "linker optimization hint";
4605 if(link_opt_hint
!= NULL
){
4606 Mach_O_error(ofile
, "malformed object (more than one "
4607 "%s command)", cmd_name
);
4610 link_opt_hint
= (struct linkedit_data_command
*)lc
;
4611 goto check_linkedit_data_command
;
4613 check_linkedit_data_command
:
4614 if(l
.cmdsize
< sizeof(struct linkedit_data_command
)){
4615 Mach_O_error(ofile
, "malformed object (%s cmdsize too "
4616 "small) in command %u", cmd_name
, i
);
4619 linkedit_data
= (struct linkedit_data_command
*)lc
;
4621 swap_linkedit_data_command(linkedit_data
, host_byte_sex
);
4622 if(linkedit_data
->cmdsize
!=
4623 sizeof(struct linkedit_data_command
)){
4624 Mach_O_error(ofile
, "malformed object (%s command %u has "
4625 "incorrect cmdsize)", cmd_name
, i
);
4628 if(linkedit_data
->dataoff
> size
){
4629 Mach_O_error(ofile
, "truncated or malformed object "
4630 "(dataoff field of %s command %u extends past the end "
4631 "of the file)", cmd_name
, i
);
4634 big_size
= linkedit_data
->dataoff
;
4635 big_size
+= linkedit_data
->datasize
;
4636 if(big_size
> size
){
4637 Mach_O_error(ofile
, "truncated or malformed object "
4638 "(dataoff field plus datasize field of "
4639 "%s command %u extends past the end of "
4640 "the file)", cmd_name
, i
);
4643 if(check_overlaping_element(ofile
, &elements
,
4644 linkedit_data
->dataoff
, linkedit_data
->datasize
,
4645 element_name
) == CHECK_BAD
)
4649 case LC_VERSION_MIN_MACOSX
:
4650 if(l
.cmdsize
< sizeof(struct version_min_command
)){
4651 Mach_O_error(ofile
, "malformed object (LC_VERSION_MIN_"
4652 "MACOSX cmdsize too small) in command %u", i
);
4656 Mach_O_error(ofile
, "malformed object (more than one "
4657 "LC_VERSION_MIN_IPHONEOS or LC_VERSION_MIN_MACOSX "
4661 vers
= (struct version_min_command
*)lc
;
4663 swap_version_min_command(vers
, host_byte_sex
);
4664 if(vers
->cmdsize
< sizeof(struct version_min_command
)){
4665 Mach_O_error(ofile
, "malformed object (LC_VERSION_MIN_"
4666 "MACOSX command %u has too small cmdsize field)", i
);
4671 case LC_VERSION_MIN_IPHONEOS
:
4672 if(l
.cmdsize
< sizeof(struct version_min_command
)){
4673 Mach_O_error(ofile
, "malformed object (LC_VERSION_MIN_"
4674 "IPHONEOS cmdsize too small) in command %u",i
);
4678 Mach_O_error(ofile
, "malformed object (more than one "
4679 "LC_VERSION_MIN_IPHONEOS or LC_VERSION_MIN_MACOSX "
4683 vers
= (struct version_min_command
*)lc
;
4685 swap_version_min_command(vers
, host_byte_sex
);
4686 if(vers
->cmdsize
< sizeof(struct version_min_command
)){
4687 Mach_O_error(ofile
, "malformed object (LC_VERSION_MIN_"
4688 "IPHONEOS command %u has too small cmdsize field)", i
);
4693 case LC_VERSION_MIN_TVOS
:
4694 if(l
.cmdsize
< sizeof(struct version_min_command
)){
4695 Mach_O_error(ofile
, "malformed object (LC_VERSION_MIN_"
4696 " cmdsize too small) in command %u",i
);
4700 Mach_O_error(ofile
, "malformed object (more than one "
4701 "LC_VERSION_MIN_ command)");
4704 vers
= (struct version_min_command
*)lc
;
4706 swap_version_min_command(vers
, host_byte_sex
);
4707 if(vers
->cmdsize
< sizeof(struct version_min_command
)){
4708 Mach_O_error(ofile
, "malformed object (LC_VERSION_MIN_"
4709 " command %u has too small cmdsize field)", i
);
4714 case LC_VERSION_MIN_WATCHOS
:
4715 if(l
.cmdsize
< sizeof(struct version_min_command
)){
4716 Mach_O_error(ofile
, "malformed object (LC_VERSION_MIN_"
4717 "WATCHOS cmdsize too small) in command %u",i
);
4721 Mach_O_error(ofile
, "malformed object (more than one "
4722 "LC_VERSION_MIN_IPHONEOS, LC_VERSION_MIN_MACOSX or "
4723 "LC_VERSION_MIN_WATCHOS command)");
4726 vers
= (struct version_min_command
*)lc
;
4728 swap_version_min_command(vers
, host_byte_sex
);
4729 if(vers
->cmdsize
< sizeof(struct version_min_command
)){
4730 Mach_O_error(ofile
, "malformed object (LC_VERSION_MIN_"
4731 "WATCHOS command %u has too small cmdsize field)", i
);
4736 case LC_ENCRYPTION_INFO
:
4737 if(l
.cmdsize
< sizeof(struct encryption_info_command
)){
4738 Mach_O_error(ofile
, "malformed object (LC_ENCRYPTION_INFO "
4739 "cmdsize too small) in command %u", i
);
4742 encrypt_info
= (struct encryption_info_command
*)lc
;
4744 swap_encryption_command(encrypt_info
, host_byte_sex
);
4745 if(encrypt_info
->cmdsize
!=
4746 sizeof(struct encryption_info_command
)){
4747 Mach_O_error(ofile
, "malformed object (LC_ENCRYPTION_INFO"
4748 "command %u has incorrect cmdsize)", i
);
4751 if(encrypt_info
->cryptoff
> size
){
4752 Mach_O_error(ofile
, "truncated or malformed object (cryptoff "
4753 "field of LC_ENCRYPTION_INFO command %u extends "
4754 "past the end of the file)", i
);
4757 big_size
= encrypt_info
->cryptoff
;
4758 big_size
+= encrypt_info
->cryptsize
;
4759 if(big_size
> size
){
4760 Mach_O_error(ofile
, "truncated or malformed object "
4761 "(cryptoff field plus cryptsize field of "
4762 "LC_ENCRYPTION_INFO command %u extends past "
4763 "the end of the file)", i
);
4768 case LC_ENCRYPTION_INFO_64
:
4769 if(l
.cmdsize
< sizeof(struct encryption_info_command_64
)){
4770 Mach_O_error(ofile
, "malformed object (LC_ENCRYPTION_INFO"
4771 "_64 cmdsize too small) in command %u", i
);
4774 encrypt_info64
= (struct encryption_info_command_64
*)lc
;
4776 swap_encryption_command_64(encrypt_info64
, host_byte_sex
);
4777 if(encrypt_info64
->cmdsize
!=
4778 sizeof(struct encryption_info_command_64
)){
4779 Mach_O_error(ofile
, "malformed object (LC_ENCRYPTION_INFO"
4780 "_64 command %u has incorrect cmdsize)", i
);
4783 if(encrypt_info64
->cryptoff
> size
){
4784 Mach_O_error(ofile
, "truncated or malformed object (cryptoff "
4785 "field of LC_ENCRYPTION_INFO_64 command %u extends"
4786 " past the end of the file)", i
);
4789 big_size
= encrypt_info64
->cryptoff
;
4790 big_size
+= encrypt_info64
->cryptsize
;
4791 if(big_size
> size
){
4792 Mach_O_error(ofile
, "truncated or malformed object "
4793 "(cryptoff field plus cryptsize field of "
4794 "LC_ENCRYPTION_INFO_64 command %u extends past"
4795 " the end of the file)", i
);
4800 case LC_LINKER_OPTION
:
4801 if(l
.cmdsize
< sizeof(struct linker_option_command
)){
4802 Mach_O_error(ofile
, "malformed object (LC_LINKER_OPTION "
4803 "cmdsize too small) in command %u", i
);
4806 lo
= (struct linker_option_command
*)lc
;
4808 swap_linker_option_command(lo
, host_byte_sex
);
4810 sizeof(struct linker_option_command
)){
4811 Mach_O_error(ofile
, "malformed object (LC_LINKER_OPTION "
4812 " command %u cmdsize too small)", i
);
4818 case LC_DYLD_INFO_ONLY
:
4819 if(l
.cmdsize
< sizeof(struct dyld_info_command
)){
4820 Mach_O_error(ofile
, "malformed object (%s cmdsize "
4821 "too small) in command %u", l
.cmd
==
4822 LC_DYLD_INFO
? "LC_DYLD_INFO" :
4823 "LC_DYLD_INFO_ONLY", i
);
4826 dyld_info
= (struct dyld_info_command
*)lc
;
4828 swap_dyld_info_command(dyld_info
, host_byte_sex
);
4829 if(dyld_info
->cmdsize
!=
4830 sizeof(struct dyld_info_command
)){
4831 Mach_O_error(ofile
, "malformed object (LC_DYLD_INFO"
4832 "command %u has incorrect cmdsize)", i
);
4835 if(dyld_info
->rebase_off
!= 0 && dyld_info
->rebase_off
> size
){
4836 Mach_O_error(ofile
, "truncated or malformed object "
4837 "(rebase_off field of LC_DYLD_INFO command %u "
4838 "extends past the end of the file)", i
);
4841 if(dyld_info
->rebase_off
!= 0){
4842 big_size
= dyld_info
->rebase_off
;
4843 big_size
+= dyld_info
->rebase_size
;
4844 if(big_size
> size
){
4845 Mach_O_error(ofile
, "truncated or malformed object "
4846 "(rebase_off plus rebase_size of LC_DYLD_INFO "
4847 "command %u extends past the end of the file)", i
);
4851 if(check_overlaping_element(ofile
, &elements
,
4852 dyld_info
->rebase_off
, dyld_info
->rebase_size
,
4853 "dyld rebase info") == CHECK_BAD
)
4855 if(dyld_info
->bind_off
!= 0 && dyld_info
->bind_off
> size
){
4856 Mach_O_error(ofile
, "truncated or malformed object "
4857 "(bind_off field of LC_DYLD_INFO command %u "
4858 "extends past the end of the file)", i
);
4861 if(dyld_info
->bind_off
!= 0){
4862 big_size
= dyld_info
->bind_off
;
4863 big_size
+= dyld_info
->bind_size
;
4864 if(big_size
> size
){
4865 Mach_O_error(ofile
, "truncated or malformed object "
4866 "(bind_off plus bind_size of LC_DYLD_INFO command "
4867 "%u extends past the end of the file)", i
);
4871 if(check_overlaping_element(ofile
, &elements
,
4872 dyld_info
->bind_off
, dyld_info
->bind_size
,
4873 "dyld bind info") == CHECK_BAD
)
4875 if(dyld_info
->weak_bind_off
!= 0 &&
4876 dyld_info
->weak_bind_off
> size
){
4877 Mach_O_error(ofile
, "truncated or malformed object "
4878 "(weak_bind_off field of LC_DYLD_INFO command %u "
4879 "extends past the end of the file)", i
);
4882 if(dyld_info
->weak_bind_off
!= 0){
4883 big_size
= dyld_info
->weak_bind_off
;
4884 big_size
+= dyld_info
->weak_bind_size
;
4885 if(big_size
> size
){
4886 Mach_O_error(ofile
, "truncated or malformed object "
4887 "(weak_bind_off plus weak_bind_size of LC_DYLD_INFO"
4888 " command %u extends past the end of the file)", i
);
4892 if(check_overlaping_element(ofile
, &elements
,
4893 dyld_info
->weak_bind_off
, dyld_info
->weak_bind_size
,
4894 "dyld bind info") == CHECK_BAD
)
4896 if(dyld_info
->lazy_bind_off
!= 0 &&
4897 dyld_info
->lazy_bind_off
> size
){
4898 Mach_O_error(ofile
, "truncated or malformed object "
4899 "(lazy_bind_off field of LC_DYLD_INFO command %u "
4900 "extends past the end of the file)", i
);
4903 if(dyld_info
->lazy_bind_off
!= 0){
4904 big_size
= dyld_info
->lazy_bind_off
;
4905 big_size
+= dyld_info
->lazy_bind_size
;
4906 if(big_size
> size
){
4907 Mach_O_error(ofile
, "truncated or malformed object "
4908 "(lazy_bind_off plus lazy_bind_size of LC_DYLD_INFO"
4909 " command %u extends past the end of the file)", i
);
4913 if(check_overlaping_element(ofile
, &elements
,
4914 dyld_info
->lazy_bind_off
, dyld_info
->lazy_bind_size
,
4915 "dyld lazy bind info") == CHECK_BAD
)
4917 if(dyld_info
->export_off
!= 0 && dyld_info
->export_off
> size
){
4918 Mach_O_error(ofile
, "truncated or malformed object "
4919 "(export_off field of LC_DYLD_INFO command %u "
4920 "extends past the end of the file)", i
);
4923 if(dyld_info
->export_off
!= 0){
4924 big_size
= dyld_info
->export_off
;
4925 big_size
+= dyld_info
->export_size
;
4926 if(big_size
> size
){
4927 Mach_O_error(ofile
, "truncated or malformed object "
4928 "(export_off plus export_size of LC_DYLD_INFO "
4929 "command %u extends past the end of the file)", i
);
4933 if(check_overlaping_element(ofile
, &elements
,
4934 dyld_info
->export_off
, dyld_info
->export_size
,
4935 "dyld export info") == CHECK_BAD
)
4941 case LC_PREBIND_CKSUM
:
4942 if(l
.cmdsize
< sizeof(struct prebind_cksum_command
)){
4943 Mach_O_error(ofile
, "malformed object (LC_PREBIND_CKSUM "
4944 "cmdsize too small) in command %u", i
);
4948 Mach_O_error(ofile
, "malformed object (more than one "
4949 "LC_PREBIND_CKSUM command)");
4952 cs
= (struct prebind_cksum_command
*)lc
;
4954 swap_prebind_cksum_command(cs
, host_byte_sex
);
4955 if(cs
->cmdsize
!= sizeof(struct prebind_cksum_command
)){
4956 Mach_O_error(ofile
, "malformed object (LC_PREBIND_CKSUM "
4957 "command %u has incorrect cmdsize)", i
);
4963 if(l
.cmdsize
< sizeof(struct uuid_command
)){
4964 Mach_O_error(ofile
, "malformed object (LC_UUID cmdsize "
4965 "too small) in command %u", i
);
4969 Mach_O_error(ofile
, "malformed object (more than one "
4970 "LC_UUID command)");
4973 uuid
= (struct uuid_command
*)lc
;
4975 swap_uuid_command(uuid
, host_byte_sex
);
4976 if(uuid
->cmdsize
!= sizeof(struct uuid_command
)){
4977 Mach_O_error(ofile
, "malformed object (LC_UUID command %u " "has incorrect cmdsize)", i
);
4983 if(l
.cmdsize
< sizeof(struct symseg_command
)){
4984 Mach_O_error(ofile
, "malformed object (LC_SYMSEG cmdsize "
4985 "too small) in command %u", i
);
4988 ss
= (struct symseg_command
*)lc
;
4990 swap_symseg_command(ss
, host_byte_sex
);
4991 if(ss
->cmdsize
!= sizeof(struct symseg_command
)){
4992 Mach_O_error(ofile
, "malformed object (LC_SYMSEG command "
4993 "%u has incorrect cmdsize)", i
);
4996 if(ss
->offset
> size
){
4997 Mach_O_error(ofile
, "truncated or malformed object (offset "
4998 "field of LC_SYMSEG command %u extends past the end "
5002 big_size
= ss
->offset
;
5003 big_size
+= ss
->size
;
5004 if(big_size
> size
){
5005 Mach_O_error(ofile
, "truncated or malformed object (offset "
5006 "field plus size field of LC_SYMTAB command %u "
5007 "extends past the end of the file)", i
);
5010 if(check_overlaping_element(ofile
, &elements
, ss
->offset
,
5011 ss
->size
, "symseg info") == CHECK_BAD
)
5017 if(l
.cmdsize
< sizeof(struct fvmlib_command
)){
5018 Mach_O_error(ofile
, "malformed object (%s cmdsize "
5019 "too small) in command %u", l
.cmd
==
5020 LC_IDFVMLIB
? "LC_IDFVMLIB" :
5021 "LC_LOADFVMLIB", i
);
5024 fl
= (struct fvmlib_command
*)lc
;
5026 swap_fvmlib_command(fl
, host_byte_sex
);
5027 if(fl
->cmdsize
< sizeof(struct fvmlib_command
)){
5028 Mach_O_error(ofile
, "malformed object (%s command %u has "
5029 "too small cmdsize field)", fl
->cmd
== LC_IDFVMLIB
?
5030 "LC_IDFVMLIB" : "LC_LOADFVMLIB", i
);
5033 if(fl
->fvmlib
.name
.offset
>= fl
->cmdsize
){
5034 Mach_O_error(ofile
, "truncated or malformed object (name."
5035 "offset field of %s command %u extends past the end "
5036 "of the file)", fl
->cmd
== LC_IDFVMLIB
? "LC_IDFVMLIB"
5037 : "LC_LOADFVMLIB", i
);
5043 cmd_name
= "LC_ID_DYLIB";
5044 goto check_dylib_command
;
5046 cmd_name
= "LC_LOAD_DYLIB";
5047 goto check_dylib_command
;
5048 case LC_LOAD_WEAK_DYLIB
:
5049 cmd_name
= "LC_LOAD_WEAK_DYLIB";
5050 goto check_dylib_command
;
5051 case LC_REEXPORT_DYLIB
:
5052 cmd_name
= "LC_REEXPORT_DYLIB";
5053 goto check_dylib_command
;
5054 case LC_LOAD_UPWARD_DYLIB
:
5055 cmd_name
= "LC_LOAD_UPWARD_DYLIB";
5056 goto check_dylib_command
;
5057 case LC_LAZY_LOAD_DYLIB
:
5058 cmd_name
= "LC_LAZY_LOAD_DYLIB";
5059 goto check_dylib_command
;
5060 check_dylib_command
:
5061 if(l
.cmdsize
< sizeof(struct dylib_command
)){
5062 Mach_O_error(ofile
, "malformed object (%s cmdsize too "
5063 "small) in command %u", cmd_name
, i
);
5066 dl
= (struct dylib_command
*)lc
;
5068 swap_dylib_command(dl
, host_byte_sex
);
5069 if(dl
->cmdsize
< sizeof(struct dylib_command
)){
5070 Mach_O_error(ofile
, "malformed object (%s command %u has "
5071 "too small cmdsize field)", cmd_name
, i
);
5074 if(dl
->dylib
.name
.offset
>= dl
->cmdsize
){
5075 Mach_O_error(ofile
, "truncated or malformed object (name."
5076 "offset field of %s command %u extends past the end "
5077 "of the file)", cmd_name
, i
);
5082 case LC_SUB_FRAMEWORK
:
5083 if(l
.cmdsize
< sizeof(struct sub_framework_command
)){
5084 Mach_O_error(ofile
, "malformed object (LC_SUB_FRAMEWORK "
5085 "cmdsize too small) in command %u", i
);
5088 sub
= (struct sub_framework_command
*)lc
;
5090 swap_sub_framework_command(sub
, host_byte_sex
);
5091 if(sub
->cmdsize
< sizeof(struct sub_framework_command
)){
5092 Mach_O_error(ofile
, "malformed object (LC_SUB_FRAMEWORK "
5093 "command %u has too small cmdsize field)", i
);
5096 if(sub
->umbrella
.offset
>= sub
->cmdsize
){
5097 Mach_O_error(ofile
, "truncated or malformed object "
5098 "(umbrella.offset field of LC_SUB_FRAMEWORK command "
5099 "%u extends past the end of the file)", i
);
5104 case LC_SUB_UMBRELLA
:
5105 if(l
.cmdsize
< sizeof(struct sub_umbrella_command
)){
5106 Mach_O_error(ofile
, "malformed object (LC_SUB_UMBRELLA "
5107 "cmdsize too small) in command %u", i
);
5110 usub
= (struct sub_umbrella_command
*)lc
;
5112 swap_sub_umbrella_command(usub
, host_byte_sex
);
5113 if(usub
->cmdsize
< sizeof(struct sub_umbrella_command
)){
5114 Mach_O_error(ofile
, "malformed object (LC_SUB_UMBRELLA "
5115 "command %u has too small cmdsize field)", i
);
5118 if(usub
->sub_umbrella
.offset
>= usub
->cmdsize
){
5119 Mach_O_error(ofile
, "truncated or malformed object "
5120 "(sub_umbrella.offset field of LC_SUB_UMBRELLA command "
5121 "%u extends past the end of the file)", i
);
5126 case LC_SUB_LIBRARY
:
5127 if(l
.cmdsize
< sizeof(struct sub_library_command
)){
5128 Mach_O_error(ofile
, "malformed object (LC_SUB_LIBRARY "
5129 "cmdsize too small) in command %u", i
);
5132 lsub
= (struct sub_library_command
*)lc
;
5134 swap_sub_library_command(lsub
, host_byte_sex
);
5135 if(lsub
->cmdsize
< sizeof(struct sub_library_command
)){
5136 Mach_O_error(ofile
, "malformed object (LC_SUB_LIBRARY "
5137 "command %u has too small cmdsize field)", i
);
5140 if(lsub
->sub_library
.offset
>= lsub
->cmdsize
){
5141 Mach_O_error(ofile
, "truncated or malformed object "
5142 "(sub_library.offset field of LC_SUB_LIBRARY command "
5143 "%u extends past the end of the file)", i
);
5149 if(l
.cmdsize
< sizeof(struct sub_client_command
)){
5150 Mach_O_error(ofile
, "malformed object (LC_SUB_CLIENT "
5151 "cmdsize too small) in command %u", i
);
5154 csub
= (struct sub_client_command
*)lc
;
5156 swap_sub_client_command(csub
, host_byte_sex
);
5157 if(csub
->cmdsize
< sizeof(struct sub_client_command
)){
5158 Mach_O_error(ofile
, "malformed object (LC_SUB_CLIENT "
5159 "command %u has too small cmdsize field)", i
);
5162 if(csub
->client
.offset
>= csub
->cmdsize
){
5163 Mach_O_error(ofile
, "truncated or malformed object "
5164 "(cleient.offset field of LC_SUB_CLIENT command "
5165 "%u extends past the end of the file)", i
);
5170 case LC_PREBOUND_DYLIB
:
5171 if(l
.cmdsize
< sizeof(struct prebound_dylib_command
)){
5172 Mach_O_error(ofile
, "malformed object (LC_PREBOUND_DYLIB "
5173 "cmdsize too small) in command %u", i
);
5176 pbdylib
= (struct prebound_dylib_command
*)lc
;
5178 swap_prebound_dylib_command(pbdylib
, host_byte_sex
);
5179 if(pbdylib
->cmdsize
< sizeof(struct dylib_command
)){
5180 Mach_O_error(ofile
, "malformed object (LC_PREBIND_DYLIB "
5181 "command %u has too small cmdsize field)", i
);
5184 if(pbdylib
->name
.offset
>= pbdylib
->cmdsize
){
5185 Mach_O_error(ofile
, "truncated or malformed object (name."
5186 "offset field of LC_PREBIND_DYLIB command %u extends "
5187 "past the end of the file)", i
);
5190 if(pbdylib
->linked_modules
.offset
>= pbdylib
->cmdsize
){
5191 Mach_O_error(ofile
, "truncated or malformed object (linked_"
5192 "modules.offset field of LC_PREBIND_DYLIB command %u "
5193 "extends past the end of the file)", i
);
5198 case LC_ID_DYLINKER
:
5199 cmd_name
= "LC_ID_DYLINKER";
5200 goto check_dylinker_command
;
5201 case LC_LOAD_DYLINKER
:
5202 cmd_name
= "LC_LOAD_DYLINKER";
5203 goto check_dylinker_command
;
5204 case LC_DYLD_ENVIRONMENT
:
5205 cmd_name
= "LC_DYLD_ENVIRONMENT";
5206 goto check_dylinker_command
;
5207 check_dylinker_command
:
5208 if(l
.cmdsize
< sizeof(struct dylinker_command
)){
5209 Mach_O_error(ofile
, "malformed object (%s cmdsize "
5210 "too small) in command %u", cmd_name
, i
);
5213 dyld
= (struct dylinker_command
*)lc
;
5215 swap_dylinker_command(dyld
, host_byte_sex
);
5216 if(dyld
->cmdsize
< sizeof(struct dylinker_command
)){
5217 Mach_O_error(ofile
, "malformed object (%s command %u has "
5218 "too small cmdsize field)", cmd_name
, i
);
5221 if(dyld
->name
.offset
>= dyld
->cmdsize
){
5222 Mach_O_error(ofile
, "truncated or malformed object (name."
5223 "offset field of %s command %u extends past the end "
5224 "of the file)", cmd_name
, i
);
5231 if(l
.cmdsize
< sizeof(struct thread_command
)){
5232 Mach_O_error(ofile
, "malformed object (%s cmdsize "
5233 "too small) in command %u", l
.cmd
==
5234 LC_UNIXTHREAD
? "LC_UNIXTHREAD" :
5238 ut
= (struct thread_command
*)lc
;
5240 swap_thread_command(ut
, host_byte_sex
);
5241 state
= (char *)ut
+ sizeof(struct thread_command
);
5243 if(cputype
== CPU_TYPE_MC680x0
){
5244 struct m68k_thread_state_regs
*cpu
;
5245 struct m68k_thread_state_68882
*fpu
;
5246 struct m68k_thread_state_user_reg
*user_reg
;
5249 p
= (char *)ut
+ ut
->cmdsize
;
5251 if(state
+ sizeof(uint32_t) >
5252 (char *)ut
+ ut
->cmdsize
){
5253 Mach_O_error(ofile
, "malformed object (flavor in "
5254 "%s command %u extends past end of command)",
5255 ut
->cmd
== LC_UNIXTHREAD
? "LC_UNIXTHREAD" :
5259 flavor
= *((uint32_t *)state
);
5261 flavor
= SWAP_INT(flavor
);
5262 *((uint32_t *)state
) = flavor
;
5264 state
+= sizeof(uint32_t);
5265 if(state
+ sizeof(uint32_t) >
5266 (char *)ut
+ ut
->cmdsize
){
5267 Mach_O_error(ofile
, "malformed object (count in "
5268 "%s command %u extends past end of command)",
5269 ut
->cmd
== LC_UNIXTHREAD
? "LC_UNIXTHREAD" :
5273 count
= *((uint32_t *)state
);
5275 count
= SWAP_INT(count
);
5276 *((uint32_t *)state
) = count
;
5278 state
+= sizeof(uint32_t);
5280 case M68K_THREAD_STATE_REGS
:
5281 if(count
!= M68K_THREAD_STATE_REGS_COUNT
){
5282 Mach_O_error(ofile
, "malformed object (count "
5283 "not M68K_THREAD_STATE_REGS_COUNT for "
5284 "flavor number %u which is a M68K_THREAD_"
5285 "STATE_REGS flavor in %s command %u)",
5286 nflavor
, ut
->cmd
== LC_UNIXTHREAD
?
5287 "LC_UNIXTHREAD" : "LC_THREAD", i
);
5290 cpu
= (struct m68k_thread_state_regs
*)state
;
5291 if(state
+ sizeof(struct m68k_thread_state_regs
) >
5292 (char *)ut
+ ut
->cmdsize
){
5293 Mach_O_error(ofile
, "malformed object ("
5294 "M68K_THREAD_STATE_REGS in %s command %u "
5295 "extends past end of command)", ut
->cmd
==
5296 LC_UNIXTHREAD
? "LC_UNIXTHREAD" :
5301 swap_m68k_thread_state_regs(cpu
, host_byte_sex
);
5302 state
+= sizeof(struct m68k_thread_state_regs
);
5304 case M68K_THREAD_STATE_68882
:
5305 if(count
!= M68K_THREAD_STATE_68882_COUNT
){
5306 Mach_O_error(ofile
, "malformed object (count "
5307 "not M68K_THREAD_STATE_68882_COUNT for "
5308 "flavor number %u which is a M68K_THREAD_"
5309 "STATE_68882 flavor in %s command %u)",
5310 nflavor
, ut
->cmd
== LC_UNIXTHREAD
?
5311 "LC_UNIXTHREAD" : "LC_THREAD", i
);
5314 fpu
= (struct m68k_thread_state_68882
*)state
;
5315 if(state
+ sizeof(struct m68k_thread_state_68882
) >
5316 (char *)ut
+ ut
->cmdsize
){
5317 Mach_O_error(ofile
, "malformed object ("
5318 "M68K_THREAD_STATE_68882 in %s command %u "
5319 "extends past end of command)", ut
->cmd
==
5320 LC_UNIXTHREAD
? "LC_UNIXTHREAD" :
5325 swap_m68k_thread_state_68882(fpu
,host_byte_sex
);
5326 state
+= sizeof(struct m68k_thread_state_68882
);
5328 case M68K_THREAD_STATE_USER_REG
:
5329 if(count
!= M68K_THREAD_STATE_USER_REG_COUNT
){
5330 Mach_O_error(ofile
, "malformed object (count "
5331 "not M68K_THREAD_STATE_USER_REG_COUNT for "
5332 "flavor number %u which is a M68K_THREAD_"
5333 "STATE_USER_REG flavor in %s command %u)",
5334 nflavor
, ut
->cmd
== LC_UNIXTHREAD
?
5335 "LC_UNIXTHREAD" : "LC_THREAD", i
);
5339 (struct m68k_thread_state_user_reg
*)state
;
5340 if(state
+sizeof(struct m68k_thread_state_user_reg
) >
5341 (char *)ut
+ ut
->cmdsize
){
5342 Mach_O_error(ofile
, "malformed object ("
5343 "M68K_THREAD_STATE_USER_REG in %s command "
5344 "%u extends past end of command)", ut
->cmd
==
5345 LC_UNIXTHREAD
? "LC_UNIXTHREAD" :
5350 swap_m68k_thread_state_user_reg(user_reg
,
5352 state
+= sizeof(struct m68k_thread_state_user_reg
);
5356 Mach_O_error(ofile
, "malformed object (unknown "
5357 "flavor for flavor number %u in %s command"
5358 " %u can't byte swap it)", nflavor
,
5359 ut
->cmd
== LC_UNIXTHREAD
? "LC_UNIXTHREAD" :
5363 state
+= count
* sizeof(uint32_t);
5370 if(cputype
== CPU_TYPE_POWERPC
||
5371 cputype
== CPU_TYPE_VEO
){
5372 ppc_thread_state_t
*nrw_cpu
;
5375 p
= (char *)ut
+ ut
->cmdsize
;
5377 if(state
+ sizeof(uint32_t) >
5378 (char *)ut
+ ut
->cmdsize
){
5379 Mach_O_error(ofile
, "malformed object (flavor in "
5380 "%s command %u extends past end of command)",
5381 ut
->cmd
== LC_UNIXTHREAD
? "LC_UNIXTHREAD" :
5385 flavor
= *((uint32_t *)state
);
5387 flavor
= SWAP_INT(flavor
);
5388 *((uint32_t *)state
) = flavor
;
5390 state
+= sizeof(uint32_t);
5391 if(state
+ sizeof(uint32_t) >
5392 (char *)ut
+ ut
->cmdsize
){
5393 Mach_O_error(ofile
, "malformed object (count in "
5394 "%s command %u extends past end of command)",
5395 ut
->cmd
== LC_UNIXTHREAD
? "LC_UNIXTHREAD" :
5399 count
= *((uint32_t *)state
);
5401 count
= SWAP_INT(count
);
5402 *((uint32_t *)state
) = count
;
5404 state
+= sizeof(uint32_t);
5406 case PPC_THREAD_STATE
:
5407 if(count
!= PPC_THREAD_STATE_COUNT
){
5408 Mach_O_error(ofile
, "malformed object (count "
5409 "not PPC_THREAD_STATE_COUNT for "
5410 "flavor number %u which is a PPC_THREAD_"
5411 "STATE flavor in %s command %u)",
5412 nflavor
, ut
->cmd
== LC_UNIXTHREAD
?
5413 "LC_UNIXTHREAD" : "LC_THREAD", i
);
5416 nrw_cpu
= (ppc_thread_state_t
*)state
;
5417 if(state
+ sizeof(ppc_thread_state_t
) >
5418 (char *)ut
+ ut
->cmdsize
){
5419 Mach_O_error(ofile
, "malformed object ("
5420 "PPC_THREAD_STATE in %s command %u extends"
5421 " past end of command)", ut
->cmd
==
5422 LC_UNIXTHREAD
? "LC_UNIXTHREAD" :
5427 swap_ppc_thread_state_t(nrw_cpu
,
5429 state
+= sizeof(ppc_thread_state_t
);
5433 Mach_O_error(ofile
, "malformed object (unknown "
5434 "flavor for flavor number %u in %s command"
5435 " %u can't byte swap it)", nflavor
,
5436 ut
->cmd
== LC_UNIXTHREAD
? "LC_UNIXTHREAD" :
5440 state
+= count
* sizeof(uint32_t);
5447 #ifdef PPC_THREAD_STATE64_COUNT
5448 if(cputype
== CPU_TYPE_POWERPC64
){
5449 ppc_thread_state64_t
*cpu
;
5452 p
= (char *)ut
+ ut
->cmdsize
;
5454 if(state
+ sizeof(uint32_t) >
5455 (char *)ut
+ ut
->cmdsize
){
5456 Mach_O_error(ofile
, "malformed object (flavor in "
5457 "%s command %u extends past end of command)",
5458 ut
->cmd
== LC_UNIXTHREAD
? "LC_UNIXTHREAD" :
5462 flavor
= *((uint32_t *)state
);
5464 flavor
= SWAP_INT(flavor
);
5465 *((uint32_t *)state
) = flavor
;
5467 state
+= sizeof(uint32_t);
5468 if(state
+ sizeof(uint32_t) >
5469 (char *)ut
+ ut
->cmdsize
){
5470 Mach_O_error(ofile
, "malformed object (count in "
5471 "%s command %u extends past end of command)",
5472 ut
->cmd
== LC_UNIXTHREAD
? "LC_UNIXTHREAD" :
5476 count
= *((uint32_t *)state
);
5478 count
= SWAP_INT(count
);
5479 *((uint32_t *)state
) = count
;
5481 state
+= sizeof(uint32_t);
5483 case PPC_THREAD_STATE64
:
5484 if(count
!= PPC_THREAD_STATE64_COUNT
){
5485 Mach_O_error(ofile
, "malformed object (count "
5486 "not PPC_THREAD_STATE64_COUNT for "
5487 "flavor number %u which is a PPC_THREAD_"
5488 "STATE64 flavor in %s command %u)",
5489 nflavor
, ut
->cmd
== LC_UNIXTHREAD
?
5490 "LC_UNIXTHREAD" : "LC_THREAD", i
);
5493 cpu
= (ppc_thread_state64_t
*)state
;
5494 if(state
+ sizeof(ppc_thread_state64_t
) >
5495 (char *)ut
+ ut
->cmdsize
){
5496 Mach_O_error(ofile
, "malformed object ("
5497 "PPC_THREAD_STATE64 in %s command %u "
5498 "extends past end of command)", ut
->cmd
==
5499 LC_UNIXTHREAD
? "LC_UNIXTHREAD" :
5504 swap_ppc_thread_state64_t(cpu
, host_byte_sex
);
5505 state
+= sizeof(ppc_thread_state64_t
);
5509 Mach_O_error(ofile
, "malformed object (unknown "
5510 "flavor for flavor number %u in %s command"
5511 " %u can't byte swap it)", nflavor
,
5512 ut
->cmd
== LC_UNIXTHREAD
? "LC_UNIXTHREAD" :
5516 state
+= count
* sizeof(uint32_t);
5523 #endif /* PPC_THREAD_STATE64_COUNT */
5524 if(cputype
== CPU_TYPE_MC88000
){
5525 m88k_thread_state_grf_t
*cpu
;
5526 m88k_thread_state_xrf_t
*fpu
;
5527 m88k_thread_state_user_t
*user
;
5528 m88110_thread_state_impl_t
*spu
;
5531 p
= (char *)ut
+ ut
->cmdsize
;
5533 if(state
+ sizeof(uint32_t) >
5534 (char *)ut
+ ut
->cmdsize
){
5535 Mach_O_error(ofile
, "malformed object (flavor in "
5536 "%s command %u extends past end of command)",
5537 ut
->cmd
== LC_UNIXTHREAD
? "LC_UNIXTHREAD" :
5541 flavor
= *((uint32_t *)state
);
5543 flavor
= SWAP_INT(flavor
);
5544 *((uint32_t *)state
) = flavor
;
5546 state
+= sizeof(uint32_t);
5547 if(state
+ sizeof(uint32_t) >
5548 (char *)ut
+ ut
->cmdsize
){
5549 Mach_O_error(ofile
, "malformed object (count in "
5550 "%s command %u extends past end of command)",
5551 ut
->cmd
== LC_UNIXTHREAD
? "LC_UNIXTHREAD" :
5555 count
= *((uint32_t *)state
);
5557 count
= SWAP_INT(count
);
5558 *((uint32_t *)state
) = count
;
5560 state
+= sizeof(uint32_t);
5562 case M88K_THREAD_STATE_GRF
:
5563 if(count
!= M88K_THREAD_STATE_GRF_COUNT
){
5564 Mach_O_error(ofile
, "malformed object (count "
5565 "not M88K_THREAD_STATE_GRF_COUNT for "
5566 "flavor number %u which is a M88K_THREAD_"
5567 "STATE_GRF flavor in %s command %u)",
5568 nflavor
, ut
->cmd
== LC_UNIXTHREAD
?
5569 "LC_UNIXTHREAD" : "LC_THREAD", i
);
5572 cpu
= (m88k_thread_state_grf_t
*)state
;
5573 if(state
+ sizeof(m88k_thread_state_grf_t
) >
5574 (char *)ut
+ ut
->cmdsize
){
5575 Mach_O_error(ofile
, "malformed object ("
5576 "M88K_THREAD_STATE_GRF in %s command %u "
5577 "extends past end of command)", ut
->cmd
==
5578 LC_UNIXTHREAD
? "LC_UNIXTHREAD" :
5583 swap_m88k_thread_state_grf_t(cpu
,
5585 state
+= sizeof(m88k_thread_state_grf_t
);
5587 case M88K_THREAD_STATE_XRF
:
5588 if(count
!= M88K_THREAD_STATE_XRF_COUNT
){
5589 Mach_O_error(ofile
, "malformed object (count "
5590 "not M88K_THREAD_STATE_XRF_COUNT for "
5591 "flavor number %u which is a M88K_THREAD_"
5592 "STATE_XRF flavor in %s command %u)",
5593 nflavor
, ut
->cmd
== LC_UNIXTHREAD
?
5594 "LC_UNIXTHREAD" : "LC_THREAD", i
);
5597 fpu
= (m88k_thread_state_xrf_t
*)state
;
5598 if(state
+ sizeof(m88k_thread_state_xrf_t
) >
5599 (char *)ut
+ ut
->cmdsize
){
5600 Mach_O_error(ofile
, "malformed object ("
5601 "M88K_THREAD_STATE_XRF in %s command %u "
5602 "extends past end of command)", ut
->cmd
==
5603 LC_UNIXTHREAD
? "LC_UNIXTHREAD" :
5608 swap_m88k_thread_state_xrf_t(fpu
,
5610 state
+= sizeof(m88k_thread_state_xrf_t
);
5612 case M88K_THREAD_STATE_USER
:
5613 if(count
!= M88K_THREAD_STATE_USER_COUNT
){
5614 Mach_O_error(ofile
, "malformed object (count "
5615 "not M88K_THREAD_STATE_USER_COUNT for "
5616 "flavor number %u which is a M88K_THREAD_"
5617 "STATE_USER flavor in %s command %u)",
5618 nflavor
, ut
->cmd
== LC_UNIXTHREAD
?
5619 "LC_UNIXTHREAD" : "LC_THREAD", i
);
5622 user
= (m88k_thread_state_user_t
*)state
;
5623 if(state
+ sizeof(m88k_thread_state_user_t
) >
5624 (char *)ut
+ ut
->cmdsize
){
5625 Mach_O_error(ofile
, "malformed object ("
5626 "M88K_THREAD_STATE_USER in %s command %u "
5627 "extends past end of command)", ut
->cmd
==
5628 LC_UNIXTHREAD
? "LC_UNIXTHREAD" :
5633 swap_m88k_thread_state_user_t(user
,
5635 state
+= sizeof(m88k_thread_state_user_t
);
5637 case M88110_THREAD_STATE_IMPL
:
5638 if(count
!= M88110_THREAD_STATE_IMPL_COUNT
){
5639 Mach_O_error(ofile
, "malformed object (count "
5640 "not M88110_THREAD_STATE_IMPL_COUNT for "
5641 "flavor number %u which is a M88110_THREAD"
5642 "_STATE_IMPL flavor in %s command %u)",
5643 nflavor
, ut
->cmd
== LC_UNIXTHREAD
?
5644 "LC_UNIXTHREAD" : "LC_THREAD", i
);
5647 spu
= (m88110_thread_state_impl_t
*)state
;
5648 if(state
+ sizeof(m88110_thread_state_impl_t
) >
5649 (char *)ut
+ ut
->cmdsize
){
5650 Mach_O_error(ofile
, "malformed object ("
5651 "M88110_THREAD_STATE_IMPL in %s command %u "
5652 "extends past end of command)", ut
->cmd
==
5653 LC_UNIXTHREAD
? "LC_UNIXTHREAD" :
5658 swap_m88110_thread_state_impl_t(spu
,
5660 state
+= sizeof(m88110_thread_state_impl_t
);
5664 Mach_O_error(ofile
, "malformed object (unknown "
5665 "flavor for flavor number %u in %s command"
5666 " %u can't byte swap it)", nflavor
,
5667 ut
->cmd
== LC_UNIXTHREAD
? "LC_UNIXTHREAD" :
5671 state
+= count
* sizeof(uint32_t);
5678 if(cputype
== CPU_TYPE_I860
){
5680 struct i860_thread_state_regs
*cpu
;
5684 p
= (char *)ut
+ ut
->cmdsize
;
5686 if(state
+ sizeof(uint32_t) >
5687 (char *)ut
+ ut
->cmdsize
){
5688 Mach_O_error(ofile
, "malformed object (flavor in "
5689 "%s command %u extends past end of command)",
5690 ut
->cmd
== LC_UNIXTHREAD
? "LC_UNIXTHREAD" :
5694 flavor
= *((uint32_t *)state
);
5696 flavor
= SWAP_INT(flavor
);
5697 *((uint32_t *)state
) = flavor
;
5699 state
+= sizeof(uint32_t);
5700 if(state
+ sizeof(uint32_t) >
5701 (char *)ut
+ ut
->cmdsize
){
5702 Mach_O_error(ofile
, "malformed object (count in "
5703 "%s command %u extends past end of command)",
5704 ut
->cmd
== LC_UNIXTHREAD
? "LC_UNIXTHREAD" :
5708 count
= *((uint32_t *)state
);
5710 count
= SWAP_INT(count
);
5711 *((uint32_t *)state
) = count
;
5713 state
+= sizeof(uint32_t);
5715 case I860_THREAD_STATE_REGS
:
5717 if(count
!= I860_THREAD_STATE_REGS_COUNT
){
5718 Mach_O_error(ofile
, "malformed object (count "
5719 "not I860_THREAD_STATE_REGS_COUNT for "
5720 "flavor number %u which is a I860_THREAD_"
5721 "STATE_REGS flavor in %s command %u)",
5722 nflavor
, ut
->cmd
== LC_UNIXTHREAD
?
5723 "LC_UNIXTHREAD" : "LC_THREAD", i
);
5726 cpu
= (struct i860_thread_state_regs
*)state
;
5727 if(state
+ sizeof(struct i860_thread_state_regs
) >
5728 (char *)ut
+ ut
->cmdsize
){
5729 Mach_O_error(ofile
, "malformed object ("
5730 "I860_THREAD_STATE_REGS in %s command %u "
5731 "extends past end of command)", ut
->cmd
==
5732 LC_UNIXTHREAD
? "LC_UNIXTHREAD" :
5737 swap_i860_thread_state_regs(cpu
, host_byte_sex
);
5738 state
+= sizeof(struct i860_thread_state_regs
);
5740 state
+= count
* sizeof(int);
5745 Mach_O_error(ofile
, "malformed object (unknown "
5746 "flavor for flavor number %u in %s command"
5747 " %u can't byte swap it)", nflavor
,
5748 ut
->cmd
== LC_UNIXTHREAD
? "LC_UNIXTHREAD" :
5752 state
+= count
* sizeof(uint32_t);
5759 if(cputype
== CPU_TYPE_I386
){
5760 i386_thread_state_t
*cpu
;
5761 /* current i386 thread states */
5762 #if i386_THREAD_STATE == 1
5763 struct i386_float_state
*fpu
;
5764 i386_exception_state_t
*exc
;
5765 #endif /* i386_THREAD_STATE == 1 */
5767 /* i386 thread states on older releases */
5768 #if i386_THREAD_STATE == -1
5769 i386_thread_fpstate_t
*fpu
;
5770 i386_thread_exceptstate_t
*exc
;
5771 i386_thread_cthreadstate_t
*user
;
5772 #endif /* i386_THREAD_STATE == -1 */
5775 p
= (char *)ut
+ ut
->cmdsize
;
5777 if(state
+ sizeof(uint32_t) >
5778 (char *)ut
+ ut
->cmdsize
){
5779 Mach_O_error(ofile
, "malformed object (flavor in "
5780 "%s command %u extends past end of command)",
5781 ut
->cmd
== LC_UNIXTHREAD
? "LC_UNIXTHREAD" :
5785 flavor
= *((uint32_t *)state
);
5787 flavor
= SWAP_INT(flavor
);
5788 *((uint32_t *)state
) = flavor
;
5790 state
+= sizeof(uint32_t);
5791 if(state
+ sizeof(uint32_t) >
5792 (char *)ut
+ ut
->cmdsize
){
5793 Mach_O_error(ofile
, "malformed object (count in "
5794 "%s command %u extends past end of command)",
5795 ut
->cmd
== LC_UNIXTHREAD
? "LC_UNIXTHREAD" :
5799 count
= *((uint32_t *)state
);
5801 count
= SWAP_INT(count
);
5802 *((uint32_t *)state
) = count
;
5804 state
+= sizeof(uint32_t);
5805 switch((int)flavor
){
5806 case i386_THREAD_STATE
:
5807 #if i386_THREAD_STATE == 1
5809 #endif /* i386_THREAD_STATE == 1 */
5810 /* i386 thread states on older releases */
5811 #if i386_THREAD_STATE == -1
5813 #endif /* i386_THREAD_STATE == -1 */
5814 if(count
!= i386_THREAD_STATE_COUNT
){
5815 Mach_O_error(ofile
, "malformed object (count "
5816 "not i386_THREAD_STATE_COUNT for flavor "
5817 "number %u which is a i386_THREAD_STATE "
5818 "flavor in %s command %u)", nflavor
,
5819 ut
->cmd
== LC_UNIXTHREAD
? "LC_UNIXTHREAD" :
5823 cpu
= (i386_thread_state_t
*)state
;
5824 if(state
+ sizeof(i386_thread_state_t
) >
5825 (char *)ut
+ ut
->cmdsize
){
5826 Mach_O_error(ofile
, "malformed object ("
5827 "i386_THREAD_STATE in %s command %u "
5828 "extends past end of command)", ut
->cmd
==
5829 LC_UNIXTHREAD
? "LC_UNIXTHREAD" :
5834 swap_i386_thread_state(cpu
, host_byte_sex
);
5835 state
+= sizeof(i386_thread_state_t
);
5837 /* current i386 thread states */
5838 #if i386_THREAD_STATE == 1
5839 case i386_FLOAT_STATE
:
5840 if(count
!= i386_FLOAT_STATE_COUNT
){
5841 Mach_O_error(ofile
, "malformed object (count "
5842 "not i386_FLOAT_STATE_COUNT for flavor "
5843 "number %u which is a i386_FLOAT_STATE "
5844 "flavor in %s command %u)", nflavor
,
5845 ut
->cmd
== LC_UNIXTHREAD
? "LC_UNIXTHREAD" :
5849 fpu
= (struct i386_float_state
*)state
;
5850 if(state
+ sizeof(struct i386_float_state
) >
5851 (char *)ut
+ ut
->cmdsize
){
5852 Mach_O_error(ofile
, "malformed object ("
5853 "i386_FLOAT_STATE in %s command %u "
5854 "extends past end of command)", ut
->cmd
==
5855 LC_UNIXTHREAD
? "LC_UNIXTHREAD" :
5860 swap_i386_float_state(fpu
, host_byte_sex
);
5861 state
+= sizeof(struct i386_float_state
);
5863 case i386_EXCEPTION_STATE
:
5864 if(count
!= I386_EXCEPTION_STATE_COUNT
){
5865 Mach_O_error(ofile
, "malformed object (count "
5866 "not I386_EXCEPTION_STATE_COUNT for "
5867 "flavor number %u which is a i386_"
5868 "EXCEPTION_STATE flavor in %s command %u)",
5870 ut
->cmd
== LC_UNIXTHREAD
? "LC_UNIXTHREAD" :
5874 exc
= (i386_exception_state_t
*)state
;
5875 if(state
+ sizeof(i386_exception_state_t
) >
5876 (char *)ut
+ ut
->cmdsize
){
5877 Mach_O_error(ofile
, "malformed object ("
5878 "i386_EXCEPTION_STATE in %s command %u "
5879 "extends past end of command)", ut
->cmd
==
5880 LC_UNIXTHREAD
? "LC_UNIXTHREAD" :
5885 swap_i386_exception_state(exc
,host_byte_sex
);
5886 state
+= sizeof(i386_exception_state_t
);
5888 #endif /* i386_THREAD_STATE == 1 */
5890 /* i386 thread states on older releases */
5891 #if i386_THREAD_STATE == -1
5892 case i386_THREAD_FPSTATE
:
5893 if(count
!= i386_THREAD_FPSTATE_COUNT
){
5894 Mach_O_error(ofile
, "malformed object (count "
5895 "not i386_THREAD_FPSTATE_COUNT for flavor "
5896 "number %u which is a i386_THREAD_FPSTATE "
5897 "flavor in %s command %u)", nflavor
,
5898 ut
->cmd
== LC_UNIXTHREAD
? "LC_UNIXTHREAD" :
5902 fpu
= (i386_thread_fpstate_t
*)state
;
5903 if(state
+ sizeof(i386_thread_fpstate_t
) >
5904 (char *)ut
+ ut
->cmdsize
){
5905 Mach_O_error(ofile
, "malformed object ("
5906 "i386_THREAD_FPSTATE in %s command %u "
5907 "extends past end of command)", ut
->cmd
==
5908 LC_UNIXTHREAD
? "LC_UNIXTHREAD" :
5913 swap_i386_thread_fpstate(fpu
, host_byte_sex
);
5914 state
+= sizeof(i386_thread_fpstate_t
);
5916 case i386_THREAD_EXCEPTSTATE
:
5917 if(count
!= i386_THREAD_EXCEPTSTATE_COUNT
){
5918 Mach_O_error(ofile
, "malformed object (count "
5919 "not i386_THREAD_EXCEPTSTATE_COUNT for "
5920 "flavor number %u which is a i386_THREAD_"
5921 "EXCEPTSTATE flavor in %s command %u)",
5923 ut
->cmd
== LC_UNIXTHREAD
? "LC_UNIXTHREAD" :
5927 exc
= (i386_thread_exceptstate_t
*)state
;
5928 if(state
+ sizeof(i386_thread_exceptstate_t
) >
5929 (char *)ut
+ ut
->cmdsize
){
5930 Mach_O_error(ofile
, "malformed object ("
5931 "i386_THREAD_EXCEPTSTATE in %s command %u "
5932 "extends past end of command)", ut
->cmd
==
5933 LC_UNIXTHREAD
? "LC_UNIXTHREAD" :
5938 swap_i386_thread_exceptstate(exc
,host_byte_sex
);
5939 state
+= sizeof(i386_thread_exceptstate_t
);
5941 case i386_THREAD_CTHREADSTATE
:
5942 if(count
!= i386_THREAD_CTHREADSTATE_COUNT
){
5943 Mach_O_error(ofile
, "malformed object (count "
5944 "not i386_THREAD_CTHREADSTATE_COUNT for "
5945 "flavor number %u which is a i386_THREAD_"
5946 "CTHREADSTATE flavor in %s command %u)",
5948 ut
->cmd
== LC_UNIXTHREAD
? "LC_UNIXTHREAD" :
5952 user
= (i386_thread_cthreadstate_t
*)state
;
5953 if(state
+ sizeof(i386_thread_cthreadstate_t
) >
5954 (char *)ut
+ ut
->cmdsize
){
5955 Mach_O_error(ofile
, "malformed object ("
5956 "i386_THREAD_CTHREADSTATE in %s command %u "
5957 "extends past end of command)", ut
->cmd
==
5958 LC_UNIXTHREAD
? "LC_UNIXTHREAD" :
5963 swap_i386_thread_cthreadstate(user
,
5965 state
+= sizeof(i386_thread_cthreadstate_t
);
5967 #endif /* i386_THREAD_STATE == -1 */
5970 Mach_O_error(ofile
, "malformed object (unknown "
5971 "flavor for flavor number %u in %s command"
5972 " %u can't byte swap it)", nflavor
,
5973 ut
->cmd
== LC_UNIXTHREAD
? "LC_UNIXTHREAD" :
5977 state
+= count
* sizeof(uint32_t);
5984 #ifdef x86_THREAD_STATE64_COUNT
5985 if(cputype
== CPU_TYPE_X86_64
){
5986 x86_thread_state64_t
*cpu
;
5989 p
= (char *)ut
+ ut
->cmdsize
;
5991 if(state
+ sizeof(uint32_t) >
5992 (char *)ut
+ ut
->cmdsize
){
5993 Mach_O_error(ofile
, "malformed object (flavor in "
5994 "%s command %u extends past end of command)",
5995 ut
->cmd
== LC_UNIXTHREAD
? "LC_UNIXTHREAD" :
5999 flavor
= *((uint32_t *)state
);
6001 flavor
= SWAP_INT(flavor
);
6002 *((uint32_t *)state
) = flavor
;
6004 state
+= sizeof(uint32_t);
6005 if(state
+ sizeof(uint32_t) >
6006 (char *)ut
+ ut
->cmdsize
){
6007 Mach_O_error(ofile
, "malformed object (count in "
6008 "%s command %u extends past end of command)",
6009 ut
->cmd
== LC_UNIXTHREAD
? "LC_UNIXTHREAD" :
6013 count
= *((uint32_t *)state
);
6015 count
= SWAP_INT(count
);
6016 *((uint32_t *)state
) = count
;
6018 state
+= sizeof(uint32_t);
6020 case x86_THREAD_STATE64
:
6021 if(count
!= x86_THREAD_STATE64_COUNT
){
6022 Mach_O_error(ofile
, "malformed object (count "
6023 "not x86_THREAD_STATE64_COUNT for "
6024 "flavor number %u which is a x86_THREAD_"
6025 "STATE64 flavor in %s command %u)",
6026 nflavor
, ut
->cmd
== LC_UNIXTHREAD
?
6027 "LC_UNIXTHREAD" : "LC_THREAD", i
);
6030 cpu
= (x86_thread_state64_t
*)state
;
6031 if(state
+ sizeof(x86_thread_state64_t
) >
6032 (char *)ut
+ ut
->cmdsize
){
6033 Mach_O_error(ofile
, "malformed object ("
6034 "x86_THREAD_STATE64 in %s command %u "
6035 "extends past end of command)", ut
->cmd
==
6036 LC_UNIXTHREAD
? "LC_UNIXTHREAD" :
6041 swap_x86_thread_state64(cpu
, host_byte_sex
);
6042 state
+= sizeof(x86_thread_state64_t
);
6046 Mach_O_error(ofile
, "malformed object (unknown "
6047 "flavor for flavor number %u in %s command"
6048 " %u can't byte swap it)", nflavor
,
6049 ut
->cmd
== LC_UNIXTHREAD
? "LC_UNIXTHREAD" :
6053 state
+= count
* sizeof(uint32_t);
6060 #endif /* x86_THREAD_STATE64_COUNT */
6061 if(cputype
== CPU_TYPE_HPPA
){
6062 struct hp_pa_integer_thread_state
*cpu
;
6063 struct hp_pa_frame_thread_state
*frame
;
6064 struct hp_pa_fp_thread_state
*fpu
;
6067 p
= (char *)ut
+ ut
->cmdsize
;
6069 if(state
+ sizeof(uint32_t) >
6070 (char *)ut
+ ut
->cmdsize
){
6071 Mach_O_error(ofile
, "malformed object (flavor in "
6072 "%s command %u extends past end of command)",
6073 ut
->cmd
== LC_UNIXTHREAD
? "LC_UNIXTHREAD" :
6077 flavor
= *((uint32_t *)state
);
6079 flavor
= SWAP_INT(flavor
);
6080 *((uint32_t *)state
) = flavor
;
6082 state
+= sizeof(uint32_t);
6083 if(state
+ sizeof(uint32_t) >
6084 (char *)ut
+ ut
->cmdsize
){
6085 Mach_O_error(ofile
, "malformed object (count in "
6086 "%s command %u extends past end of command)",
6087 ut
->cmd
== LC_UNIXTHREAD
? "LC_UNIXTHREAD" :
6091 count
= *((uint32_t *)state
);
6093 count
= SWAP_INT(count
);
6094 *((uint32_t *)state
) = count
;
6096 state
+= sizeof(uint32_t);
6098 case HPPA_INTEGER_THREAD_STATE
:
6099 if(count
!= HPPA_INTEGER_THREAD_STATE_COUNT
){
6100 Mach_O_error(ofile
, "malformed object (count "
6101 "not HPPA_INTEGER_THREAD_STATE_COUNT for "
6102 "flavor number %u which is a "
6103 "HPPA_INTEGER_THREAD_STATE "
6104 "flavor in %s command %u)", nflavor
,
6105 ut
->cmd
== LC_UNIXTHREAD
? "LC_UNIXTHREAD" :
6109 cpu
= (struct hp_pa_integer_thread_state
*)state
;
6110 if(state
+sizeof(struct hp_pa_integer_thread_state
) >
6111 (char *)ut
+ ut
->cmdsize
){
6112 Mach_O_error(ofile
, "malformed object ("
6113 "HPPA_INTEGER_THREAD_STATE in %s command "
6114 "%u extends past end of command)",
6115 ut
->cmd
== LC_UNIXTHREAD
? "LC_UNIXTHREAD" :
6120 swap_hppa_integer_thread_state(cpu
,
6122 state
+= sizeof(struct hp_pa_integer_thread_state
);
6124 case HPPA_FRAME_THREAD_STATE
:
6125 if(count
!= HPPA_FRAME_THREAD_STATE_COUNT
){
6126 Mach_O_error(ofile
, "malformed object (count "
6127 "not HPPA_FRAME_THREAD_STATE_COUNT for "
6128 "flavor number %u which is a HPPA_FRAME_"
6129 "THREAD_STATE flavor in %s command %u)",
6131 ut
->cmd
== LC_UNIXTHREAD
? "LC_UNIXTHREAD" :
6135 frame
= (struct hp_pa_frame_thread_state
*)state
;
6136 if(state
+ sizeof(struct hp_pa_frame_thread_state
) >
6137 (char *)ut
+ ut
->cmdsize
){
6138 Mach_O_error(ofile
, "malformed object ("
6139 "HPPA_FRAME_THREAD_STATE in %s command "
6140 "%u extends past end of command)",
6141 ut
->cmd
== LC_UNIXTHREAD
? "LC_UNIXTHREAD" :
6146 swap_hppa_frame_thread_state(frame
,host_byte_sex
);
6147 state
+= sizeof(struct hp_pa_frame_thread_state
);
6149 case HPPA_FP_THREAD_STATE
:
6150 if(count
!= HPPA_FP_THREAD_STATE_COUNT
){
6151 Mach_O_error(ofile
, "malformed object (count "
6152 "not HPPA_FP_THREAD_STATE_COUNT for "
6153 "flavor number %u which is a HPPA_FP_"
6154 "THREAD_STATE flavor in %s command %u)",
6156 ut
->cmd
== LC_UNIXTHREAD
? "LC_UNIXTHREAD" :
6160 fpu
= (struct hp_pa_fp_thread_state
*)state
;
6161 if(state
+ sizeof(struct hp_pa_fp_thread_state
) >
6162 (char *)ut
+ ut
->cmdsize
){
6163 Mach_O_error(ofile
, "malformed object ("
6164 "HPPA_FP_THREAD_STATE in %s command "
6165 "%u extends past end of command)",
6166 ut
->cmd
== LC_UNIXTHREAD
? "LC_UNIXTHREAD" :
6171 swap_hppa_fp_thread_state(fpu
,host_byte_sex
);
6172 state
+= sizeof(struct hp_pa_fp_thread_state
);
6176 Mach_O_error(ofile
, "malformed object (unknown "
6177 "flavor for flavor number %u in %s command"
6178 " %u can't byte swap it)", nflavor
,
6179 ut
->cmd
== LC_UNIXTHREAD
? "LC_UNIXTHREAD" :
6183 state
+= count
* sizeof(uint32_t);
6190 if(cputype
== CPU_TYPE_SPARC
){
6191 struct sparc_thread_state_regs
*cpu
;
6192 struct sparc_thread_state_fpu
*fpu
;
6195 p
= (char *)ut
+ ut
->cmdsize
;
6197 if(state
+ sizeof(uint32_t) >
6198 (char *)ut
+ ut
->cmdsize
){
6199 Mach_O_error(ofile
, "malformed object (flavor in "
6200 "%s command %u extends past end of command)",
6201 ut
->cmd
== LC_UNIXTHREAD
? "LC_UNIXTHREAD" :
6205 flavor
= *((uint32_t *)state
);
6207 flavor
= SWAP_INT(flavor
);
6208 *((uint32_t *)state
) = flavor
;
6210 state
+= sizeof(uint32_t);
6211 if(state
+ sizeof(uint32_t) >
6212 (char *)ut
+ ut
->cmdsize
){
6213 Mach_O_error(ofile
, "malformed object (count in "
6214 "%s command %u extends past end of command)",
6215 ut
->cmd
== LC_UNIXTHREAD
? "LC_UNIXTHREAD" :
6219 count
= *((uint32_t *)state
);
6221 count
= SWAP_INT(count
);
6222 *((uint32_t *)state
) = count
;
6224 state
+= sizeof(uint32_t);
6226 case SPARC_THREAD_STATE_REGS
:
6227 if(count
!= SPARC_THREAD_STATE_REGS_COUNT
){
6228 Mach_O_error(ofile
, "malformed object (count "
6229 "not SPARC_THREAD_STATE_REGS_COUNT for "
6230 "flavor number %u which is a SPARC_THREAD_"
6231 "STATE_REGS flavor in %s command %u)",
6232 nflavor
, ut
->cmd
== LC_UNIXTHREAD
?
6233 "LC_UNIXTHREAD" : "LC_THREAD", i
);
6236 cpu
= (struct sparc_thread_state_regs
*)state
;
6237 if(state
+ sizeof(struct sparc_thread_state_regs
) >
6238 (char *)ut
+ ut
->cmdsize
){
6239 Mach_O_error(ofile
, "malformed object ("
6240 "SPARC_THREAD_STATE_REGS in %s command %u "
6241 "extends past end of command)", ut
->cmd
==
6242 LC_UNIXTHREAD
? "LC_UNIXTHREAD" :
6247 swap_sparc_thread_state_regs(cpu
, host_byte_sex
);
6248 state
+= sizeof(struct sparc_thread_state_regs
);
6250 case SPARC_THREAD_STATE_FPU
:
6251 if(count
!= SPARC_THREAD_STATE_FPU_COUNT
){
6252 Mach_O_error(ofile
, "malformed object (count "
6253 "not SPARC_THREAD_STATE_FPU_COUNT for "
6254 "flavor number %u which is a SPARC_THREAD_"
6255 "STATE_FPU flavor in %s command %u)",
6256 nflavor
, ut
->cmd
== LC_UNIXTHREAD
?
6257 "LC_UNIXTHREAD" : "LC_THREAD", i
);
6260 fpu
= (struct sparc_thread_state_fpu
*)state
;
6261 if(state
+ sizeof(struct sparc_thread_state_fpu
) >
6262 (char *)ut
+ ut
->cmdsize
){
6263 Mach_O_error(ofile
, "malformed object ("
6264 "SPARC_THREAD_STATE_FPU in %s command %u "
6265 "extends past end of command)", ut
->cmd
==
6266 LC_UNIXTHREAD
? "LC_UNIXTHREAD" :
6271 swap_sparc_thread_state_fpu(fpu
, host_byte_sex
);
6272 state
+= sizeof(struct sparc_thread_state_fpu
);
6276 Mach_O_error(ofile
, "malformed object (unknown "
6277 "flavor for flavor number %u in %s command"
6278 " %u can't byte swap it)", nflavor
,
6279 ut
->cmd
== LC_UNIXTHREAD
? "LC_UNIXTHREAD" :
6283 state
+= count
* sizeof(uint32_t);
6290 if(cputype
== CPU_TYPE_ARM
){
6291 arm_thread_state_t
*cpu
;
6294 p
= (char *)ut
+ ut
->cmdsize
;
6296 if(state
+ sizeof(uint32_t) >
6297 (char *)ut
+ ut
->cmdsize
){
6298 Mach_O_error(ofile
, "malformed object (flavor in "
6299 "%s command %u extends past end of command)",
6300 ut
->cmd
== LC_UNIXTHREAD
? "LC_UNIXTHREAD" :
6304 flavor
= *((uint32_t *)state
);
6306 flavor
= SWAP_INT(flavor
);
6307 *((uint32_t *)state
) = flavor
;
6309 state
+= sizeof(uint32_t);
6310 if(state
+ sizeof(uint32_t) >
6311 (char *)ut
+ ut
->cmdsize
){
6312 Mach_O_error(ofile
, "malformed object (count in "
6313 "%s command %u extends past end of command)",
6314 ut
->cmd
== LC_UNIXTHREAD
? "LC_UNIXTHREAD" :
6318 count
= *((uint32_t *)state
);
6320 count
= SWAP_INT(count
);
6321 *((uint32_t *)state
) = count
;
6323 state
+= sizeof(uint32_t);
6325 case ARM_THREAD_STATE
:
6326 if(count
!= ARM_THREAD_STATE_COUNT
){
6327 Mach_O_error(ofile
, "malformed object (count "
6328 "not ARM_THREAD_STATE_COUNT for "
6329 "flavor number %u which is a ARM_THREAD_"
6330 "STATE flavor in %s command %u)",
6331 nflavor
, ut
->cmd
== LC_UNIXTHREAD
?
6332 "LC_UNIXTHREAD" : "LC_THREAD", i
);
6335 cpu
= (arm_thread_state_t
*)state
;
6336 if(state
+ sizeof(arm_thread_state_t
) >
6337 (char *)ut
+ ut
->cmdsize
){
6338 Mach_O_error(ofile
, "malformed object ("
6339 "ARM_THREAD_STATE in %s command %u "
6340 "extends past end of command)", ut
->cmd
==
6341 LC_UNIXTHREAD
? "LC_UNIXTHREAD" :
6346 swap_arm_thread_state_t(cpu
, host_byte_sex
);
6347 state
+= sizeof(arm_thread_state_t
);
6351 Mach_O_error(ofile
, "malformed object (unknown "
6352 "flavor for flavor number %u in %s command"
6353 " %u can't byte swap it)", nflavor
,
6354 ut
->cmd
== LC_UNIXTHREAD
? "LC_UNIXTHREAD" :
6358 state
+= count
* sizeof(uint32_t);
6365 if(cputype
== CPU_TYPE_ARM64
){
6366 arm_thread_state64_t
*cpu
;
6369 p
= (char *)ut
+ ut
->cmdsize
;
6371 if(state
+ sizeof(uint32_t) >
6372 (char *)ut
+ ut
->cmdsize
){
6373 Mach_O_error(ofile
, "malformed object (flavor in "
6374 "%s command %u extends past end of command)",
6375 ut
->cmd
== LC_UNIXTHREAD
? "LC_UNIXTHREAD" :
6379 flavor
= *((uint32_t *)state
);
6381 flavor
= SWAP_INT(flavor
);
6382 *((uint32_t *)state
) = flavor
;
6384 state
+= sizeof(uint32_t);
6385 if(state
+ sizeof(uint32_t) >
6386 (char *)ut
+ ut
->cmdsize
){
6387 Mach_O_error(ofile
, "malformed object (count in "
6388 "%s command %u extends past end of command)",
6389 ut
->cmd
== LC_UNIXTHREAD
? "LC_UNIXTHREAD" :
6393 count
= *((uint32_t *)state
);
6395 count
= SWAP_INT(count
);
6396 *((uint32_t *)state
) = count
;
6398 state
+= sizeof(uint32_t);
6400 case ARM_THREAD_STATE64
:
6401 if(count
!= ARM_THREAD_STATE64_COUNT
){
6402 Mach_O_error(ofile
, "malformed object (count "
6403 "not ARM_THREAD_STATE64_COUNT for "
6404 "flavor number %u which is a ARM_THREAD_"
6405 "STATE64 flavor in %s command %u)",
6406 nflavor
, ut
->cmd
== LC_UNIXTHREAD
?
6407 "LC_UNIXTHREAD" : "LC_THREAD", i
);
6410 cpu
= (arm_thread_state64_t
*)state
;
6411 if(state
+ sizeof(arm_thread_state64_t
) >
6412 (char *)ut
+ ut
->cmdsize
){
6413 Mach_O_error(ofile
, "malformed object ("
6414 "ARM_THREAD_STATE64 in %s command %u "
6415 "extends past end of command)", ut
->cmd
==
6416 LC_UNIXTHREAD
? "LC_UNIXTHREAD" :
6421 swap_arm_thread_state64_t(cpu
, host_byte_sex
);
6422 state
+= sizeof(arm_thread_state64_t
);
6426 Mach_O_error(ofile
, "malformed object (unknown "
6427 "flavor for flavor number %u in %s command"
6428 " %u can't byte swap it)", nflavor
,
6429 ut
->cmd
== LC_UNIXTHREAD
? "LC_UNIXTHREAD" :
6433 state
+= count
* sizeof(uint32_t);
6441 Mach_O_error(ofile
, "malformed object (unknown cputype and "
6442 "cpusubtype of object and can't byte swap and check %s "
6443 "command %u)", ut
->cmd
== LC_UNIXTHREAD
?
6444 "LC_UNIXTHREAD" : "LC_THREAD", i
);
6449 if(l
.cmdsize
< sizeof(struct entry_point_command
)){
6450 Mach_O_error(ofile
, "malformed object (LC_MAIN cmdsize "
6451 "too small) in command %u", i
);
6454 ep
= (struct entry_point_command
*)lc
;
6456 swap_entry_point_command(ep
, host_byte_sex
);
6458 * If we really wanted we could check that the entryoff field
6459 * really is an offset into the __TEXT segment. But since it
6460 * is not used here, we won't needlessly check it.
6463 case LC_SOURCE_VERSION
:
6464 if(l
.cmdsize
< sizeof(struct source_version_command
)){
6465 Mach_O_error(ofile
, "malformed object (LC_SOURCE_VERSION "
6466 "cmdsize too small) in command %u", i
);
6469 sv
= (struct source_version_command
*)lc
;
6471 swap_source_version_command(sv
, host_byte_sex
);
6473 if(l
.cmdsize
< sizeof(struct ident_command
)){
6474 Mach_O_error(ofile
, "malformed object (LC_IDENT cmdsize "
6475 "too small) in command %u", i
);
6478 id
= (struct ident_command
*)lc
;
6480 swap_ident_command(id
, host_byte_sex
);
6482 * Note the cmdsize field if the LC_IDENT command was checked
6483 * as part of checking all load commands cmdsize field before
6484 * the switch statement on the cmd field of the load command.
6488 if(l
.cmdsize
< sizeof(struct rpath_command
)){
6489 Mach_O_error(ofile
, "malformed object (LC_RPATH: cmdsize "
6490 "too small) in command %u", i
);
6493 rpath
= (struct rpath_command
*)lc
;
6495 swap_rpath_command(rpath
, host_byte_sex
);
6496 if(rpath
->cmdsize
< sizeof(struct rpath_command
)){
6497 Mach_O_error(ofile
, "malformed object (LC_RPATH command "
6498 "%u has too small cmdsize field)", i
);
6501 if(rpath
->path
.offset
>= rpath
->cmdsize
){
6502 Mach_O_error(ofile
, "truncated or malformed object (path."
6503 "offset field of LC_RPATH command %u extends past the "
6504 "end of the file)", i
);
6511 Mach_O_error(ofile
, "malformed object (unknown load command "
6514 #endif /* !defined(OFI) */
6517 lc
= (struct load_command
*)((char *)lc
+ l
.cmdsize
);
6518 /* check that next load command does not extends past the end */
6519 if((char *)lc
> (char *)load_commands
+ sizeofcmds
){
6520 Mach_O_error(ofile
, "truncated or malformed object (load "
6521 "command %u extends past the end of the file)",
6528 Mach_O_error(ofile
, "truncated or malformed object (contains "
6529 "LC_DYSYMTAB load command without a LC_SYMTAB load command)");
6535 if(dyst
->nlocalsym
!= 0 &&
6536 dyst
->ilocalsym
> st
->nsyms
){
6537 Mach_O_error(ofile
, "truncated or malformed object "
6538 "(ilocalsym in LC_DYSYMTAB load command extends past "
6539 "the end of the symbol table)");
6542 big_size
= dyst
->ilocalsym
;
6543 big_size
+= dyst
->nlocalsym
;
6544 if(dyst
->nlocalsym
!= 0 && big_size
> st
->nsyms
){
6545 Mach_O_error(ofile
, "truncated or malformed object "
6546 "(ilocalsym plus nlocalsym in LC_DYSYMTAB load command "
6547 "extends past the end of the symbol table)");
6551 if(dyst
->nextdefsym
!= 0 &&
6552 dyst
->iextdefsym
> st
->nsyms
){
6553 Mach_O_error(ofile
, "truncated or malformed object "
6554 "(iextdefsym in LC_DYSYMTAB load command extends past "
6555 "the end of the symbol table)");
6558 big_size
= dyst
->iextdefsym
;
6559 big_size
+= dyst
->nextdefsym
;
6560 if(dyst
->nextdefsym
!= 0 && big_size
> st
->nsyms
){
6561 Mach_O_error(ofile
, "truncated or malformed object "
6562 "(iextdefsym plus nextdefsym in LC_DYSYMTAB load "
6563 "command extends past the end of the symbol table)");
6567 if(dyst
->nundefsym
!= 0 &&
6568 dyst
->iundefsym
> st
->nsyms
){
6569 Mach_O_error(ofile
, "truncated or malformed object "
6570 "(iundefsym in LC_DYSYMTAB load command extends past "
6571 "the end of the symbol table)");
6574 big_size
= dyst
->iundefsym
;
6575 big_size
+= dyst
->nundefsym
;
6576 if(dyst
->nundefsym
!= 0 && big_size
> st
->nsyms
){
6577 Mach_O_error(ofile
, "truncated or malformed object "
6578 "(iundefsym plus nundefsym in LC_DYSYMTAB load command "
6579 "extends past the end of the symbol table)");
6583 if(rc
->init_module
> dyst
->nmodtab
){
6584 Mach_O_error(ofile
, "malformed object (init_module in "
6585 "LC_ROUTINES load command extends past the "
6586 "end of the module table)");
6591 if(rc64
->init_module
> dyst
->nmodtab
){
6592 Mach_O_error(ofile
, "malformed object (init_module in "
6593 "LC_ROUTINES_64 load command extends past the "
6594 "end of the module table)");
6599 if(hints
->nhints
!= dyst
->nundefsym
){
6600 Mach_O_error(ofile
, "malformed object (nhints in "
6601 "LC_TWOLEVEL_HINTS load command not the same as "
6602 "nundefsym in LC_DYSYMTAB load command)");
6608 /* check for an inconsistent size of the load commands */
6609 if((char *)load_commands
+ sizeofcmds
!= (char *)lc
){
6610 Mach_O_error(ofile
, "malformed object (inconsistent sizeofcmds "
6611 "field in mach header)");
6616 * Mark this ofile so we know its headers have been swapped. We do this
6617 * in case we don't process it the first time so we can swap them back
6618 * in case we loop back to it in a fat file to process it later.
6621 ofile
->headers_swapped
= TRUE
;
6623 /* looks good return ok */
6624 free_elements(&elements
);
6628 free_elements(&elements
);
6634 * swap_back_Mach_O() is called after the ofile has been processed to swap back
6635 * the mach header and load commands if check_Mach_O() above swapped them.
6640 struct ofile
*ofile
)
6642 if(ofile
->headers_swapped
== TRUE
){
6643 ofile
->headers_swapped
= FALSE
;
6644 if(ofile
->mh
!= NULL
)
6645 swap_object_headers(ofile
->mh
, ofile
->load_commands
);
6646 else if(ofile
->mh64
!= NULL
)
6647 swap_object_headers(ofile
->mh64
, ofile
->load_commands
);
6653 * check_overlaping_element() checks that the element in the ofile described by
6654 * offset, size and name does not overlap in list of elements in head. If it
6655 * does CHECK_BAD is returned and an error message is generated. If it doesn't
6656 * then an element is added in the ordered list and CHECK_GOOD is returned
6660 check_overlaping_element(
6661 struct ofile
*ofile
,
6662 struct element
*head
,
6667 struct element
*e
, *p
, *n
;
6672 if(head
->next
== NULL
){
6673 n
= allocate(sizeof(struct element
));
6684 while(e
->next
!= NULL
){
6687 if((offset
>= e
->offset
&&
6688 offset
< e
->offset
+ e
->size
) ||
6689 (offset
+ size
> e
->offset
&&
6690 offset
+ size
< e
->offset
+ e
->size
) ||
6691 (offset
<= e
->offset
&&
6692 offset
+ size
>= e
->offset
+ e
->size
)){
6693 Mach_O_error(ofile
, "malformed object (%s at offset %u with a "
6694 "size of %u, overlaps %s at offset %u with a size of %u)",
6695 name
, offset
, size
, e
->name
, e
->offset
, e
->size
);
6698 if(e
->next
!= NULL
&& offset
+ size
<= e
->next
->offset
){
6699 n
= allocate(sizeof(struct element
));
6708 n
= allocate(sizeof(struct element
));
6718 * free_elements() frees the list of elements on the list head.
6723 struct element
*head
)
6725 struct element
*e
, *e_next
;
6734 #endif /* !defined(OTOOL) */
6737 * check_dylib_module() checks the object file's dylib_module as referenced
6738 * by the dylib_module field in the ofile for correctness.
6743 struct ofile
*ofile
,
6744 struct symtab_command
*st
,
6745 struct dysymtab_command
*dyst
,
6747 uint32_t module_index
)
6751 #else /* !defined OTOOL */
6753 enum byte_sex host_byte_sex
;
6755 struct dylib_module m
;
6756 struct dylib_module_64 m64
;
6757 uint32_t module_name
, nextdefsym
, iextdefsym
, nlocalsym
, ilocalsym
, nrefsym
;
6758 uint32_t irefsym
, nextrel
, iextrel
;
6760 host_byte_sex
= get_host_byte_sex();
6761 swapped
= (enum bool)(host_byte_sex
!= ofile
->object_byte_sex
);
6762 if(ofile
->mh
!= NULL
){
6763 m
= *ofile
->dylib_module
;
6765 swap_dylib_module(&m
, 1, host_byte_sex
);
6766 module_name
= m
.module_name
;
6767 nextdefsym
= m
.nextdefsym
;
6768 iextdefsym
= m
.iextdefsym
;
6769 nlocalsym
= m
.nlocalsym
;
6770 ilocalsym
= m
.ilocalsym
;
6771 nrefsym
= m
.nrefsym
;
6772 irefsym
= m
.irefsym
;
6773 nextrel
= m
.nextrel
;
6774 iextrel
= m
.iextrel
;
6777 m64
= *ofile
->dylib_module64
;
6779 swap_dylib_module_64(&m64
, 1, host_byte_sex
);
6780 module_name
= m64
.module_name
;
6781 nextdefsym
= m64
.nextdefsym
;
6782 iextdefsym
= m64
.iextdefsym
;
6783 nlocalsym
= m64
.nlocalsym
;
6784 ilocalsym
= m64
.ilocalsym
;
6785 nrefsym
= m64
.nrefsym
;
6786 irefsym
= m64
.irefsym
;
6787 nextrel
= m64
.nextrel
;
6788 iextrel
= m64
.iextrel
;
6791 if(module_name
> st
->strsize
){
6792 Mach_O_error(ofile
, "truncated or malformed object (module_name "
6793 "of module table entry %u past the end of the string table)",
6797 for(i
= module_name
; i
< st
->strsize
&& strings
[i
] != '\0'; i
++)
6799 if(i
>= st
->strsize
){
6800 Mach_O_error(ofile
, "truncated or malformed object (module_name "
6801 "of module table entry %u extends past the end of the string "
6802 "table)", module_index
);
6806 if(nextdefsym
!= 0){
6807 if(iextdefsym
> st
->nsyms
){
6808 Mach_O_error(ofile
, "truncated or malformed object (iextdefsym "
6809 "field of module table entry %u past the end of the "
6810 "symbol table", module_index
);
6813 if(iextdefsym
+ nextdefsym
> st
->nsyms
){
6814 Mach_O_error(ofile
, "truncated or malformed object (iextdefsym "
6815 "field of module table entry %u plus nextdefsym field "
6816 "extends past the end of the symbol table", module_index
);
6821 if(ilocalsym
> st
->nsyms
){
6822 Mach_O_error(ofile
, "truncated or malformed object (ilocalsym "
6823 "field of module table entry %u past the end of the "
6824 "symbol table", module_index
);
6827 if(ilocalsym
+ nlocalsym
> st
->nsyms
){
6828 Mach_O_error(ofile
, "truncated or malformed object (ilocalsym "
6829 "field of module table entry %u plus nlocalsym field "
6830 "extends past the end of the symbol table", module_index
);
6835 if(irefsym
> dyst
->nextrefsyms
){
6836 Mach_O_error(ofile
, "truncated or malformed object (irefsym "
6837 "field of module table entry %u past the end of the "
6838 "reference table", module_index
);
6841 if(irefsym
+ nrefsym
> dyst
->nextrefsyms
){
6842 Mach_O_error(ofile
, "truncated or malformed object (irefsym "
6843 "field of module table entry %u plus nrefsym field "
6844 "extends past the end of the reference table",module_index
);
6849 if(iextrel
> dyst
->extreloff
){
6850 Mach_O_error(ofile
, "truncated or malformed object (iextrel "
6851 "field of module table entry %u past the end of the "
6852 "external relocation enrties", module_index
);
6855 if(iextrel
+ nextrel
> dyst
->extreloff
){
6856 Mach_O_error(ofile
, "truncated or malformed object (iextrel "
6857 "field of module table entry %u plus nextrel field "
6858 "extends past the end of the external relocation enrties",
6870 const struct ar_hdr
*ar_hdr
)
6874 i
= sizeof(ar_hdr
->ar_name
) - 1;
6875 if(ar_hdr
->ar_name
[i
] == ' '){
6877 if(ar_hdr
->ar_name
[i
] != ' ')
6883 * For System V archives names ends in a '/' which are not part of the
6884 * name. Except for the table of contents member named "/" and archive
6885 * string table member name which has the name "//".
6887 if(i
> 1 && ar_hdr
->ar_name
[i
] == '/')
6891 #endif /* !defined(RLD) */