2 * Copyright (c) 1999 Apple Computer, Inc. All rights reserved.
4 * @APPLE_LICENSE_HEADER_START@
6 * This file contains Original Code and/or Modifications of Original Code
7 * as defined in and that are subject to the Apple Public Source License
8 * Version 2.0 (the 'License'). You may not use this file except in
9 * compliance with the License. Please obtain a copy of the License at
10 * http://www.opensource.apple.com/apsl/ and read it before using this
13 * The Original Code and all software distributed under the License are
14 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
15 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
16 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
17 * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
18 * Please see the License for the specific language governing rights and
19 * limitations under the License.
21 * @APPLE_LICENSE_HEADER_END@
24 * The lipo(1) program. This program creates, thins and operates on fat files.
25 * This program takes the following options:
31 * -arch <arch_type> <input_file>
32 * -arch_blank <arch_type>
34 * -extract <arch_type>
36 * -replace <arch_type> <file_name>
37 * -segalign <arch_type> <value>
38 * -verify_arch <arch_type> ...
45 #define AR_EFMT1 "#1/" /* extended format #1 */
55 #include <sys/types.h>
58 #include <mach/mach.h>
59 #include <mach-o/loader.h>
60 #include <mach-o/fat.h>
61 #include "stuff/arch.h"
62 #include "stuff/errors.h"
63 #include "stuff/allocate.h"
64 #include "stuff/lto.h"
66 /* The maximum section alignment allowed to be specified, as a power of two */
67 #define MAXSECTALIGN 15 /* 2**15 or 0x8000 */
69 /* These #undef's are because of the #define's in <mach.h> */
73 /* name of the program for error messages (argv[0]) */
74 char *progname
= NULL
;
76 /* names and types (if any) of input file specified on the commmand line */
79 struct arch_flag arch_flag
;
80 struct fat_header
*fat_header
;
81 struct fat_arch
*fat_arches
;
84 static struct input_file
*input_files
= NULL
;
85 static uint32_t ninput_files
= 0;
87 /* Thin files from the input files to operate on */
91 struct fat_arch fat_arch
;
97 static struct thin_file
*thin_files
= NULL
;
98 static uint32_t nthin_files
= 0;
100 /* The specified output file */
101 static char *output_file
= NULL
;
102 static uint32_t output_filemode
= 0;
104 static struct utimbuf output_timep
= { 0 };
106 static time_t output_timep
[2] = { 0 };
108 static enum bool archives_in_input
= FALSE
;
110 /* flags set from command line arguments to specify the operation */
111 static enum bool create_flag
= FALSE
;
112 static enum bool info_flag
= FALSE
;
113 static enum bool detailed_info_flag
= FALSE
;
115 static enum bool thin_flag
= FALSE
;
116 static struct arch_flag thin_arch_flag
= { 0 };
118 static enum bool remove_flag
= FALSE
;
119 static struct arch_flag
*remove_arch_flags
= NULL
;
120 static uint32_t nremove_arch_flags
= 0;
122 static enum bool extract_flag
= FALSE
;
123 static struct arch_flag
*extract_arch_flags
= NULL
;
124 static uint32_t nextract_arch_flags
= 0;
125 static enum bool extract_family_flag
= FALSE
;
127 static enum bool replace_flag
= FALSE
;
129 struct arch_flag arch_flag
;
130 struct thin_file thin_file
;
132 static struct replace
*replaces
= NULL
;
133 static uint32_t nreplaces
= 0;
136 struct arch_flag arch_flag
;
139 static struct segalign
*segaligns
= NULL
;
140 static uint32_t nsegaligns
= 0;
142 static enum bool arch_blank_flag
= FALSE
;
144 static struct fat_header fat_header
= { 0 };
146 static struct fat_arch
*arm64_fat_arch
= NULL
;
147 static struct fat_arch
*get_arm64_fat_arch(
150 static enum bool verify_flag
= FALSE
;
151 static struct arch_flag
*verify_archs
= NULL
;
152 static uint32_t nverify_archs
= 0;
154 static void create_fat(
156 static void process_input_file(
157 struct input_file
*input
);
158 static void process_replace_file(
159 struct replace
*replace
);
160 static void check_archive(
165 cpu_subtype_t
*cpusubtype
);
166 static void check_extend_format_1(
168 struct ar_hdr
*ar_hdr
,
170 uint32_t *member_name_size
);
171 static uint32_t get_align(
172 struct mach_header
*mhp
,
173 struct load_command
*load_commands
,
177 static uint32_t get_align_64(
178 struct mach_header_64
*mhp64
,
179 struct load_command
*load_commands
,
183 static uint32_t guess_align(
185 static void print_arch(
186 struct fat_arch
*fat_arch
);
187 static void print_cputype(
189 cpu_subtype_t cpusubtype
);
190 static int size_ar_name(
192 static struct input_file
*new_input(
194 static struct thin_file
*new_thin(
196 static struct arch_flag
*new_arch_flag(
197 struct arch_flag
**arch_flags
,
198 uint32_t *narch_flags
);
199 static struct replace
*new_replace(
201 static struct segalign
*new_segalign(
203 static int cmp_qsort(
204 const struct thin_file
*thin1
,
205 const struct thin_file
*thin2
);
209 static enum bool ispoweroftwo(
211 static void check_arch(
212 struct input_file
*input
,
213 struct thin_file
*thin
);
216 static struct thin_file
*new_blank_dylib(
217 struct arch_flag
*arch
);
219 /* apple_version is created by the libstuff/Makefile */
220 extern char apple_version
[];
221 char *version
= apple_version
;
230 uint32_t i
, j
, k
, value
;
232 struct input_file
*input
;
233 struct arch_flag
*arch_flag
;
234 struct replace
*replace
;
235 struct segalign
*segalign
;
236 const struct arch_flag
*arch_flags
;
238 struct arch_flag blank_arch
;
242 * Process the command line arguments.
245 for(a
= 1; a
< argc
; a
++){
246 if(argv
[a
][0] == '-'){
250 if(strcmp(p
, "arch") == 0 || strcmp(p
, "a") == 0){
252 error("missing argument(s) to %s option", argv
[a
]);
256 if(get_arch_from_flag(argv
[a
+1],
257 &(input
->arch_flag
)) == 0){
258 error("unknown architecture specification flag: %s "
259 "in specifying input file %s %s %s", argv
[a
+1],
260 argv
[a
], argv
[a
+1], argv
[a
+2]);
264 input
->name
= argv
[a
+2];
267 else if(strcmp(p
, "arch_blank") == 0){
268 arch_blank_flag
= TRUE
;
270 error("missing argument(s) to %s option", argv
[a
]);
273 if(get_arch_from_flag(argv
[a
+1], &blank_arch
) == 0){
274 error("unknown architecture specification flag: %s "
275 "in specifying input file %s %s", argv
[a
+1],
280 new_blank_dylib(&blank_arch
);
287 if(strcmp(p
, "create") == 0 || strcmp(p
, "c") == 0){
294 if(strcmp(p
, "detailed_info") == 0 || strcmp(p
, "d") == 0){
295 detailed_info_flag
= TRUE
;
301 if(strcmp(p
, "extract") == 0 ||
302 strcmp(p
, "extract_family") == 0 ||
303 strcmp(p
, "e") == 0){
305 if(strcmp(p
, "extract_family") == 0)
306 extract_family_flag
= TRUE
;
308 error("missing argument to %s option", argv
[a
]);
311 arch_flag
= new_arch_flag(&extract_arch_flags
,
312 &nextract_arch_flags
);
313 if(get_arch_from_flag(argv
[a
+1], arch_flag
) == 0){
314 error("unknown architecture specification flag: "
315 "%s in specifying extract operation: %s %s",
316 argv
[a
+1], argv
[a
], argv
[a
+1]);
326 if(strcmp(p
, "info") == 0 || strcmp(p
, "i") == 0){
333 if(strcmp(p
, "output") == 0 || strcmp(p
, "o") == 0){
335 error("missing argument to %s option", argv
[a
]);
338 if(output_file
!= NULL
)
339 fatal("more than one %s option specified", argv
[a
]);
340 output_file
= argv
[a
+ 1];
347 if(strcmp(p
, "remove") == 0 || strcmp(p
, "rem") == 0){
350 error("missing argument to %s option", argv
[a
]);
353 arch_flag
= new_arch_flag(&remove_arch_flags
,
354 &nremove_arch_flags
);
355 if(get_arch_from_flag(argv
[a
+1], arch_flag
) == 0){
356 error("unknown architecture specification flag: "
357 "%s in specifying remove operation: %s %s",
358 argv
[a
+1], argv
[a
], argv
[a
+1]);
364 else if(strcmp(p
, "replace") == 0 || strcmp(p
, "rep") == 0){
367 error("missing argument(s) to %s option", argv
[a
]);
370 replace
= new_replace();
371 if(get_arch_from_flag(argv
[a
+1],
372 &(replace
->arch_flag
)) == 0){
373 error("unknown architecture specification flag: "
374 "%s in specifying replace operation: %s %s %s",
375 argv
[a
+1], argv
[a
], argv
[a
+1], argv
[a
+2]);
379 replace
->thin_file
.name
= argv
[a
+2];
386 if(strcmp(p
, "segalign") == 0 || strcmp(p
, "s") == 0){
388 error("missing argument(s) to %s option", argv
[a
]);
391 segalign
= new_segalign();
392 if(get_arch_from_flag(argv
[a
+1],
393 &(segalign
->arch_flag
)) == 0){
394 error("unknown architecture specification flag: "
395 "%s in specifying segment alignment: %s %s %s",
396 argv
[a
+1], argv
[a
], argv
[a
+1], argv
[a
+2]);
400 value
= strtoul(argv
[a
+2], &endp
, 16);
402 fatal("argument for -segalign <arch_type> %s not a "
403 "proper hexadecimal number", argv
[a
+2]);
404 if(!ispoweroftwo(value
) || value
== 0)
405 fatal("argument to -segalign <arch_type> %x (hex) "
406 "must be a non-zero power of two", value
);
407 if(value
> (1 << MAXSECTALIGN
))
408 fatal("argument to -segalign <arch_type> %x (hex) "
409 "must equal to or less than %x (hex)",
410 value
, (unsigned int)(1 << MAXSECTALIGN
));
412 while((value
& 0x1) != 1){
422 if(strcmp(p
, "thin") == 0 || strcmp(p
, "t") == 0){
423 if(thin_flag
== TRUE
)
424 fatal("more than one %s option specified", argv
[a
]);
427 error("missing argument to %s option", argv
[a
]);
430 if(get_arch_from_flag(argv
[a
+1], &thin_arch_flag
) == 0){
431 error("unknown architecture specification flag: "
432 "%s in specifying thin operation: %s %s",
433 argv
[a
+1], argv
[a
], argv
[a
+1]);
443 if(strcmp(p
, "verify_arch") == 0){
446 error("missing argument(s) to %s option", argv
[a
]);
450 nverify_archs
= argc
- a
;
451 verify_archs
= (struct arch_flag
*)allocate(
452 sizeof(struct arch_flag
) * nverify_archs
);
453 for(i
= 0; a
< argc
; a
++, i
++){
454 if(get_arch_from_flag(argv
[a
],
455 verify_archs
+ i
) == 0){
456 error("unknown architecture specification "
457 "flag: %s in specifying -verify_arch "
458 "operation", argv
[a
]);
469 fatal("unknown flag: %s", argv
[a
]);
474 input
->name
= argv
[a
];
479 * Check to see the specified arguments are valid.
481 if(info_flag
== FALSE
&& detailed_info_flag
== FALSE
&&
482 create_flag
== FALSE
&& thin_flag
== FALSE
&&
483 extract_flag
== FALSE
&& remove_flag
== FALSE
&&
484 replace_flag
== FALSE
&& verify_flag
== FALSE
){
485 error("one of -create, -thin <arch_type>, -extract <arch_type>, "
486 "-remove <arch_type>, -replace <arch_type> <file_name>, "
487 "-verify_arch <arch_type> ... , "
488 "-info or -detailed_info must be specified");
491 if((create_flag
== TRUE
|| thin_flag
== TRUE
|| extract_flag
== TRUE
||
492 remove_flag
== TRUE
|| replace_flag
== TRUE
) &&
493 output_file
== NULL
){
494 error("no output file specified");
497 if(ninput_files
== 0){
498 error("no input files specified");
501 if(verify_flag
== TRUE
&& ninput_files
!= 1){
502 error("only one input file allowed with -verify_arch");
505 if(create_flag
+ thin_flag
+ extract_flag
+ remove_flag
+ replace_flag
+
506 info_flag
+ detailed_info_flag
+ verify_flag
> 1){
507 error("only one of -create, -thin <arch_type>, -extract <arch_type>"
508 ", -remove <arch_type>, -replace <arch_type> <file_name>, "
509 "-verify_arch <arch_type> ..., "
510 "-info or -detailed_info can be specified");
513 if(arch_blank_flag
== TRUE
&& create_flag
== FALSE
){
514 error("-arch_blank may only be used with -create");
519 * Determine the types of the input files.
521 for(i
= 0; i
< ninput_files
; i
++)
522 process_input_file(input_files
+ i
);
525 * Do the specified operation.
529 /* check to make sure no two files have the same architectures */
530 for(i
= 0; i
< nthin_files
; i
++)
531 for(j
= i
+ 1; j
< nthin_files
; j
++)
532 if(thin_files
[i
].fat_arch
.cputype
==
533 thin_files
[j
].fat_arch
.cputype
&&
534 (thin_files
[i
].fat_arch
.cpusubtype
& ~CPU_SUBTYPE_MASK
)==
535 (thin_files
[j
].fat_arch
.cpusubtype
& ~CPU_SUBTYPE_MASK
)){
536 arch_flags
= get_arch_flags();
537 for(k
= 0; arch_flags
[k
].name
!= NULL
; k
++){
538 if(arch_flags
[k
].cputype
==
539 thin_files
[j
].fat_arch
.cputype
&&
540 (arch_flags
[k
].cpusubtype
&
541 ~CPU_SUBTYPE_MASK
) ==
542 (thin_files
[j
].fat_arch
.cpusubtype
&
544 fatal("%s and %s have the same architectures (%s) "
545 "and can't be in the same fat output file",
546 thin_files
[i
].name
, thin_files
[j
].name
,
549 fatal("%s and %s have the same architectures (cputype "
550 "(%d) and cpusubtype (%d)) and can't be in the "
551 "same fat output file", thin_files
[i
].name
,
552 thin_files
[j
].name
,thin_files
[i
].fat_arch
.cputype
,
553 thin_files
[i
].fat_arch
.cpusubtype
&
560 if(ninput_files
!= 1)
561 fatal("only one input file can be specified with the -thin "
563 if(input_files
[0].fat_header
== NULL
)
564 fatal("input file (%s) must be a fat file when the -thin "
565 "option is specified", input_files
[0].name
);
566 for(i
= 0; i
< nthin_files
; i
++){
567 if(thin_files
[i
].fat_arch
.cputype
== thin_arch_flag
.cputype
&&
568 (thin_files
[i
].fat_arch
.cpusubtype
& ~CPU_SUBTYPE_MASK
) ==
569 (thin_arch_flag
.cpusubtype
& ~CPU_SUBTYPE_MASK
)){
570 (void)unlink(output_file
);
571 if((fd
= open(output_file
, O_WRONLY
| O_CREAT
| O_TRUNC
,
572 output_filemode
)) == -1)
573 system_fatal("can't create output file: %s",
576 if(write(fd
, thin_files
[i
].addr
,thin_files
[i
].fat_arch
.size
)
577 != (int)(thin_files
[i
].fat_arch
.size
))
578 system_fatal("can't write thin file to output file: %s",
581 system_fatal("can't close output file: %s",output_file
);
582 if(utime(output_file
,
584 &output_timep
) == -1)
588 system_fatal("can't set the modify times for "
589 "output file: %s", output_file
);
594 fatal("fat input file (%s) does not contain the specified "
595 "architecture (%s) to thin it to", input
->name
,
596 thin_arch_flag
.name
);
600 if(ninput_files
!= 1)
601 fatal("only one input file can be specified with the -extract "
603 if(input_files
[0].fat_header
== NULL
)
604 fatal("input file (%s) must be a fat file when the -extract "
605 "option is specified", input_files
[0].name
);
606 for(i
= 0; i
< nextract_arch_flags
; i
++){
607 for(j
= i
+ 1; j
< nextract_arch_flags
; j
++){
608 if(extract_arch_flags
[i
].cputype
==
609 extract_arch_flags
[j
].cputype
&&
610 (extract_arch_flags
[i
].cpusubtype
& ~CPU_SUBTYPE_MASK
) ==
611 (thin_files
[j
].fat_arch
.cpusubtype
& ~CPU_SUBTYPE_MASK
))
612 fatal("-extract %s specified multiple times",
613 extract_arch_flags
[i
].name
);
616 /* mark those thin files for extraction */
617 for(i
= 0; i
< nextract_arch_flags
; i
++){
619 for(j
= 0; j
< nthin_files
; j
++){
620 if(extract_arch_flags
[i
].cputype
==
621 thin_files
[j
].fat_arch
.cputype
&&
622 ((extract_arch_flags
[i
].cpusubtype
&
624 (thin_files
[j
].fat_arch
.cpusubtype
&
625 ~CPU_SUBTYPE_MASK
) ||
626 extract_family_flag
== TRUE
)){
627 thin_files
[j
].extract
= TRUE
;
632 fatal("-extract %s specified but fat file: %s does not "
633 "contain that architecture",
634 extract_arch_flags
[i
].name
, input_files
[0].name
);
636 /* remove those thin files not marked for extraction */
637 for(i
= 0; i
< nthin_files
; ){
638 if(thin_files
[i
].extract
== FALSE
){
639 for(j
= i
; j
< nthin_files
- 1; j
++)
640 thin_files
[j
] = thin_files
[j
+ 1];
650 if(ninput_files
!= 1)
651 fatal("only one input file can be specified with the -remove "
653 if(input_files
[0].fat_header
== NULL
)
654 fatal("input file (%s) must be a fat file when the -remove "
655 "option is specified", input_files
[0].name
);
656 for(i
= 0; i
< nremove_arch_flags
; i
++){
657 for(j
= i
+ 1; j
< nremove_arch_flags
; j
++){
658 if(remove_arch_flags
[i
].cputype
==
659 remove_arch_flags
[j
].cputype
&&
660 (remove_arch_flags
[i
].cpusubtype
& ~CPU_SUBTYPE_MASK
) ==
661 (remove_arch_flags
[j
].cpusubtype
& ~CPU_SUBTYPE_MASK
))
662 fatal("-remove %s specified multiple times",
663 remove_arch_flags
[i
].name
);
666 /* mark those thin files for removal */
667 for(i
= 0; i
< nremove_arch_flags
; i
++){
668 for(j
= 0; j
< nthin_files
; j
++){
669 if(remove_arch_flags
[i
].cputype
==
670 thin_files
[j
].fat_arch
.cputype
&&
671 (remove_arch_flags
[i
].cpusubtype
&
672 ~CPU_SUBTYPE_MASK
) ==
673 (thin_files
[j
].fat_arch
.cpusubtype
&
675 thin_files
[j
].remove
= TRUE
;
680 fatal("-remove %s specified but fat file: %s does not "
681 "contain that architecture",
682 remove_arch_flags
[i
].name
, input_files
[0].name
);
684 /* remove those thin files marked for removal */
685 for(i
= 0; i
< nthin_files
; ){
686 if(thin_files
[i
].remove
== TRUE
){
687 for(j
= i
; j
< nthin_files
; j
++)
688 thin_files
[j
] = thin_files
[j
+ 1];
695 fatal("-remove's specified would result in an empty fat file");
700 if(ninput_files
!= 1)
701 fatal("only one input file can be specified with the -replace "
703 if(input_files
[0].fat_header
== NULL
)
704 fatal("input file (%s) must be a fat file when the -replace "
705 "option is specified", input_files
[0].name
);
706 for(i
= 0; i
< nreplaces
; i
++){
707 for(j
= i
+ 1; j
< nreplaces
; j
++){
708 if(replaces
[i
].arch_flag
.cputype
==
709 replaces
[j
].arch_flag
.cputype
&&
710 (replaces
[i
].arch_flag
.cpusubtype
& ~CPU_SUBTYPE_MASK
) ==
711 (replaces
[j
].arch_flag
.cpusubtype
& ~CPU_SUBTYPE_MASK
))
712 fatal("-replace %s <file_name> specified multiple times",
713 replaces
[j
].arch_flag
.name
);
716 for(i
= 0; i
< nreplaces
; i
++){
717 process_replace_file(replaces
+ i
);
718 for(j
= 0; j
< nthin_files
; j
++){
719 if(replaces
[i
].arch_flag
.cputype
==
720 thin_files
[j
].fat_arch
.cputype
&&
721 (replaces
[i
].arch_flag
.cpusubtype
& ~CPU_SUBTYPE_MASK
) ==
722 (thin_files
[j
].fat_arch
.cpusubtype
& ~CPU_SUBTYPE_MASK
)){
723 thin_files
[j
] = replaces
[i
].thin_file
;
728 fatal("-replace %s <file_name> specified but fat file: %s "
729 "does not contain that architecture",
730 replaces
[i
].arch_flag
.name
, input_files
[0].name
);
736 for(i
= 0; i
< ninput_files
; i
++){
737 if(input_files
[i
].fat_header
!= NULL
){
738 printf("Architectures in the fat file: %s are: ",
739 input_files
[i
].name
);
740 for(j
= 0; j
< input_files
[i
].fat_header
->nfat_arch
; j
++){
741 print_arch(&(input_files
[i
].fat_arches
[j
]));
747 if(input_files
[i
].is_thin
== FALSE
)
748 printf("input file %s is not a fat file\n",
749 input_files
[i
].name
);
752 for(i
= 0; i
< nthin_files
; i
++){
753 if(thin_files
[i
].from_fat
== TRUE
)
755 printf("Non-fat file: %s is architecture: %s\n",
757 get_arch_name_from_types(thin_files
[i
].fat_arch
.cputype
,
758 thin_files
[i
].fat_arch
.cpusubtype
& ~CPU_SUBTYPE_MASK
));
762 if(detailed_info_flag
){
763 for(i
= 0; i
< ninput_files
; i
++){
764 if(input_files
[i
].fat_header
!= NULL
){
765 printf("Fat header in: %s\n", input_files
[i
].name
);
766 printf("fat_magic 0x%x\n",
767 (unsigned int)(input_files
[i
].fat_header
->magic
));
768 printf("nfat_arch %u\n",
769 input_files
[i
].fat_header
->nfat_arch
);
770 for(j
= 0; j
< input_files
[i
].fat_header
->nfat_arch
; j
++){
771 printf("architecture ");
772 print_arch(&(input_files
[i
].fat_arches
[j
]));
774 print_cputype(input_files
[i
].fat_arches
[j
].cputype
,
775 input_files
[i
].fat_arches
[j
].cpusubtype
&
777 printf(" offset %u\n",
778 input_files
[i
].fat_arches
[j
].offset
);
780 input_files
[i
].fat_arches
[j
].size
);
781 printf(" align 2^%u (%d)\n",
782 input_files
[i
].fat_arches
[j
].align
,
783 1 << input_files
[i
].fat_arches
[j
].align
);
787 printf("input file %s is not a fat file\n",
788 input_files
[i
].name
);
791 for(i
= 0; i
< nthin_files
; i
++){
792 if(thin_files
[i
].from_fat
== TRUE
)
794 printf("Non-fat file: %s is architecture: %s\n",
796 get_arch_name_from_types(thin_files
[i
].fat_arch
.cputype
,
797 thin_files
[i
].fat_arch
.cpusubtype
& ~CPU_SUBTYPE_MASK
));
801 if(verify_flag
== TRUE
){
802 for(i
= 0; i
< nverify_archs
; i
++){
804 for(j
= 0; j
< nthin_files
; j
++){
805 if(verify_archs
[i
].cputype
==
806 thin_files
[j
].fat_arch
.cputype
&&
807 (verify_archs
[i
].cpusubtype
& ~CPU_SUBTYPE_MASK
) ==
808 (thin_files
[j
].fat_arch
.cpusubtype
& ~CPU_SUBTYPE_MASK
)){
822 * create_fat() creates a fat output file from the thin files.
828 uint32_t i
, j
, offset
;
832 /* fold in specified segment alignments */
833 for(i
= 0; i
< nsegaligns
; i
++){
834 for(j
= i
+ 1; j
< nsegaligns
; j
++){
835 if(segaligns
[i
].arch_flag
.cputype
==
836 segaligns
[j
].arch_flag
.cputype
&&
837 (segaligns
[i
].arch_flag
.cpusubtype
& ~CPU_SUBTYPE_MASK
) ==
838 (segaligns
[j
].arch_flag
.cpusubtype
& ~CPU_SUBTYPE_MASK
))
839 fatal("-segalign %s <value> specified multiple times",
840 segaligns
[j
].arch_flag
.name
);
843 for(i
= 0; i
< nsegaligns
; i
++){
844 for(j
= 0; j
< nthin_files
; j
++){
845 if(segaligns
[i
].arch_flag
.cputype
==
846 thin_files
[j
].fat_arch
.cputype
&&
847 (segaligns
[i
].arch_flag
.cpusubtype
& ~CPU_SUBTYPE_MASK
) ==
848 (thin_files
[j
].fat_arch
.cpusubtype
& ~CPU_SUBTYPE_MASK
)){
850 Since this program has to guess at alignments and guesses high when unsure this
851 check shouldn't be used so the the correct alignment can be specified by the
853 if(thin_files[j].fat_arch.align > segaligns[i].align)
854 fatal("specified segment alignment: %d for "
855 "architecture %s is less than the alignment: %d "
856 "required from the input file",
857 1 << segaligns[i].align,
858 segaligns[i].arch_flag.name,
859 1 << thin_files[j].fat_arch.align);
861 thin_files
[j
].fat_arch
.align
= segaligns
[i
].align
;
866 fatal("-segalign %s <value> specified but resulting fat "
867 "file does not contain that architecture",
868 segaligns
[i
].arch_flag
.name
);
871 /* sort the files by alignment to save space in the output file */
872 qsort(thin_files
, nthin_files
, sizeof(struct thin_file
),
873 (int (*)(const void *, const void *))cmp_qsort
);
875 /* We will order the ARM64 slice last. */
876 arm64_fat_arch
= get_arm64_fat_arch();
878 /* Fill in the fat header and the fat_arch's offsets. */
879 fat_header
.magic
= FAT_MAGIC
;
880 fat_header
.nfat_arch
= nthin_files
;
881 offset
= sizeof(struct fat_header
) +
882 nthin_files
* sizeof(struct fat_arch
);
883 for(i
= 0; i
< nthin_files
; i
++){
884 offset
= rnd(offset
, 1 << thin_files
[i
].fat_arch
.align
);
885 thin_files
[i
].fat_arch
.offset
= offset
;
886 offset
+= thin_files
[i
].fat_arch
.size
;
889 rename_file
= makestr(output_file
, ".lipo", NULL
);
890 if((fd
= open(rename_file
, O_WRONLY
| O_CREAT
| O_TRUNC
,
891 output_filemode
)) == -1)
892 system_fatal("can't create temporary output file: %s", rename_file
);
895 * If this is an extract_family_flag operation and the is just one
896 * thin file on the list don't create a fat file.
898 if(extract_family_flag
!= TRUE
|| nthin_files
!= 1){
899 #ifdef __LITTLE_ENDIAN__
900 swap_fat_header(&fat_header
, BIG_ENDIAN_BYTE_SEX
);
901 #endif /* __LITTLE_ENDIAN__ */
902 if(write(fd
, &fat_header
, sizeof(struct fat_header
)) !=
903 sizeof(struct fat_header
))
904 system_fatal("can't write fat header to output file: %s",
906 #ifdef __LITTLE_ENDIAN__
907 swap_fat_header(&fat_header
, LITTLE_ENDIAN_BYTE_SEX
);
908 #endif /* __LITTLE_ENDIAN__ */
909 for(i
= 0; i
< nthin_files
; i
++){
911 * If we are ordering the ARM64 slice last of the fat_arch
912 * structs, so skip it in this loop.
914 if(arm64_fat_arch
== &(thin_files
[i
].fat_arch
))
916 #ifdef __LITTLE_ENDIAN__
917 swap_fat_arch(&(thin_files
[i
].fat_arch
), 1,BIG_ENDIAN_BYTE_SEX
);
918 #endif /* __LITTLE_ENDIAN__ */
919 if(write(fd
, &(thin_files
[i
].fat_arch
),
920 sizeof(struct fat_arch
)) != sizeof(struct fat_arch
))
921 system_fatal("can't write fat arch to output file: %s",
923 #ifdef __LITTLE_ENDIAN__
924 swap_fat_arch(&(thin_files
[i
].fat_arch
), 1,
925 LITTLE_ENDIAN_BYTE_SEX
);
926 #endif /* __LITTLE_ENDIAN__ */
930 * We are ordering the ARM64 slice so it gets written last of the
931 * fat_arch structs, so write it out here as it was skipped above.
934 #ifdef __LITTLE_ENDIAN__
935 swap_fat_arch(arm64_fat_arch
, 1, BIG_ENDIAN_BYTE_SEX
);
936 #endif /* __LITTLE_ENDIAN__ */
937 if(write(fd
, arm64_fat_arch
,
938 sizeof(struct fat_arch
)) != sizeof(struct fat_arch
))
939 system_fatal("can't write fat arch to output file: %s",
941 #ifdef __LITTLE_ENDIAN__
942 swap_fat_arch(arm64_fat_arch
, 1, LITTLE_ENDIAN_BYTE_SEX
);
943 #endif /* __LITTLE_ENDIAN__ */
945 for(i
= 0; i
< nthin_files
; i
++){
946 if(extract_family_flag
== FALSE
|| nthin_files
> 1)
947 if(lseek(fd
, thin_files
[i
].fat_arch
.offset
, L_SET
) == -1)
948 system_fatal("can't lseek in output file: %s", rename_file
);
949 if(write(fd
, thin_files
[i
].addr
, thin_files
[i
].fat_arch
.size
)
950 != (int)(thin_files
[i
].fat_arch
.size
))
951 system_fatal("can't write to output file: %s", rename_file
);
954 system_fatal("can't close output file: %s", rename_file
);
955 if(rename(rename_file
, output_file
) == -1)
956 system_error("can't move temporary file: %s to file: %s",
957 output_file
, rename_file
);
962 * process_input_file() checks input file and breaks it down into thin files
963 * for later operations.
968 struct input_file
*input
)
971 struct stat stat_buf
, stat_buf2
;
974 struct thin_file
*thin
;
975 struct mach_header
*mhp
, mh
;
976 struct mach_header_64
*mhp64
, mh64
;
977 struct load_command
*lcp
;
979 cpu_subtype_t cpusubtype
;
983 /* Open the input file and map it in */
984 if((fd
= open(input
->name
, O_RDONLY
)) == -1)
985 system_fatal("can't open input file: %s", input
->name
);
986 if(fstat(fd
, &stat_buf
) == -1)
987 system_fatal("can't stat input file: %s", input
->name
);
988 size
= stat_buf
.st_size
;
989 /* pick up set uid, set gid and sticky text bits */
990 output_filemode
= stat_buf
.st_mode
& 07777;
992 * Select the eariliest modify time so that if the output file
993 * contains archives with table of contents lipo will not make them
994 * out of date. This logic however could make an out of date table of
995 * contents appear up todate if another file is combined with it that
996 * has a date early enough.
999 if(output_timep
.modtime
== 0 ||
1000 output_timep
.modtime
> stat_buf
.st_mtime
){
1001 output_timep
.actime
= stat_buf
.st_atime
;
1002 output_timep
.modtime
= stat_buf
.st_mtime
;
1005 if(output_timep
[1] == 0 || output_timep
[1] > stat_buf
.st_mtime
){
1006 output_timep
[0] = stat_buf
.st_atime
;
1007 output_timep
[1] = stat_buf
.st_mtime
;
1011 * mmap() can't handle mapping regular files with zero size. So this
1012 * is handled separately.
1014 if((stat_buf
.st_mode
& S_IFREG
) == S_IFREG
&& size
== 0)
1017 addr
= mmap(0, size
, PROT_READ
|PROT_WRITE
, MAP_FILE
|MAP_PRIVATE
,
1019 if((intptr_t)addr
== -1)
1020 system_fatal("can't map input file: %s", input
->name
);
1023 * Because of rdar://8087586 we do a second stat to see if the file
1024 * is still there and the same file.
1026 if(fstat(fd
, &stat_buf2
) == -1)
1027 system_fatal("can't stat input file: %s", input
->name
);
1028 if(stat_buf2
.st_size
!= size
||
1029 stat_buf2
.st_mtime
!= stat_buf
.st_mtime
)
1030 system_fatal("Input file: %s changed since opened", input
->name
);
1034 /* Try to figure out what kind of file this is */
1036 /* see if this file is a fat file */
1037 if(size
>= sizeof(struct fat_header
) &&
1038 #ifdef __BIG_ENDIAN__
1039 *((uint32_t *)addr
) == FAT_MAGIC
)
1040 #endif /* __BIG_ENDIAN__ */
1041 #ifdef __LITTLE_ENDIAN__
1042 *((uint32_t *)addr
) == SWAP_INT(FAT_MAGIC
))
1043 #endif /* __LITTLE_ENDIAN__ */
1046 if(input
->arch_flag
.name
!= NULL
)
1047 fatal("architecture specifed for fat input file: %s "
1048 "(architectures can't be specifed for fat input files)",
1051 input
->fat_header
= (struct fat_header
*)addr
;
1052 #ifdef __LITTLE_ENDIAN__
1053 swap_fat_header(input
->fat_header
, LITTLE_ENDIAN_BYTE_SEX
);
1054 #endif /* __LITTLE_ENDIAN__ */
1055 big_size
= input
->fat_header
->nfat_arch
;
1056 big_size
*= sizeof(struct fat_arch
);
1057 big_size
+= sizeof(struct fat_header
);
1059 fatal("truncated or malformed fat file (fat_arch structs would "
1060 "extend past the end of the file) %s", input
->name
);
1061 input
->fat_arches
= (struct fat_arch
*)(addr
+
1062 sizeof(struct fat_header
));
1063 #ifdef __LITTLE_ENDIAN__
1064 swap_fat_arch(input
->fat_arches
, input
->fat_header
->nfat_arch
,
1065 LITTLE_ENDIAN_BYTE_SEX
);
1066 #endif /* __LITTLE_ENDIAN__ */
1067 for(i
= 0; i
< input
->fat_header
->nfat_arch
; i
++){
1068 if(input
->fat_arches
[i
].offset
+ input
->fat_arches
[i
].size
>
1070 fatal("truncated or malformed fat file (offset plus size "
1071 "of cputype (%d) cpusubtype (%d) extends past the "
1072 "end of the file) %s", input
->fat_arches
[i
].cputype
,
1073 input
->fat_arches
[i
].cpusubtype
& ~CPU_SUBTYPE_MASK
,
1075 if(input
->fat_arches
[i
].align
> MAXSECTALIGN
)
1076 fatal("align (2^%u) too large of fat file %s (cputype (%d)"
1077 " cpusubtype (%d)) (maximum 2^%d)",
1078 input
->fat_arches
[i
].align
, input
->name
,
1079 input
->fat_arches
[i
].cputype
,
1080 input
->fat_arches
[i
].cpusubtype
& ~CPU_SUBTYPE_MASK
,
1082 if(input
->fat_arches
[i
].offset
%
1083 (1 << input
->fat_arches
[i
].align
) != 0)
1084 fatal("offset %u of fat file %s (cputype (%d) cpusubtype "
1085 "(%d)) not aligned on its alignment (2^%u)",
1086 input
->fat_arches
[i
].offset
, input
->name
,
1087 input
->fat_arches
[i
].cputype
,
1088 input
->fat_arches
[i
].cpusubtype
& ~CPU_SUBTYPE_MASK
,
1089 input
->fat_arches
[i
].align
);
1091 for(i
= 0; i
< input
->fat_header
->nfat_arch
; i
++){
1092 for(j
= i
+ 1; j
< input
->fat_header
->nfat_arch
; j
++){
1093 if(input
->fat_arches
[i
].cputype
==
1094 input
->fat_arches
[j
].cputype
&&
1095 (input
->fat_arches
[i
].cpusubtype
& ~CPU_SUBTYPE_MASK
) ==
1096 (input
->fat_arches
[j
].cpusubtype
& ~CPU_SUBTYPE_MASK
))
1097 fatal("fat file %s contains two of the same architecture "
1098 "(cputype (%d) cpusubtype (%d))", input
->name
,
1099 input
->fat_arches
[i
].cputype
,
1100 input
->fat_arches
[i
].cpusubtype
& ~CPU_SUBTYPE_MASK
);
1104 /* create a thin file struct for each arch in the fat file */
1105 for(i
= 0; i
< input
->fat_header
->nfat_arch
; i
++){
1107 thin
->name
= input
->name
;
1108 thin
->addr
= addr
+ input
->fat_arches
[i
].offset
;
1109 thin
->fat_arch
= input
->fat_arches
[i
];
1110 thin
->from_fat
= TRUE
;
1111 if(input
->fat_arches
[i
].size
>= SARMAG
&&
1112 strncmp(thin
->addr
, ARMAG
, SARMAG
) == 0)
1113 archives_in_input
= TRUE
;
1116 /* see if this file is Mach-O file for 32-bit architectures */
1117 else if(size
>= sizeof(struct mach_header
) &&
1118 (*((uint32_t *)addr
) == MH_MAGIC
||
1119 *((uint32_t *)addr
) == SWAP_INT(MH_MAGIC
))){
1121 /* this is a Mach-O file so create a thin file struct for it */
1123 input
->is_thin
= TRUE
;
1124 thin
->name
= input
->name
;
1126 mhp
= (struct mach_header
*)addr
;
1127 lcp
= (struct load_command
*)((char *)mhp
+
1128 sizeof(struct mach_header
));
1129 if(mhp
->magic
== SWAP_INT(MH_MAGIC
)){
1132 swap_mach_header(&mh
, get_host_byte_sex());
1137 thin
->fat_arch
.cputype
= mhp
->cputype
;
1138 thin
->fat_arch
.cpusubtype
= mhp
->cpusubtype
;
1139 thin
->fat_arch
.offset
= 0;
1140 thin
->fat_arch
.size
= size
;
1141 thin
->fat_arch
.align
= get_align(mhp
, lcp
, size
, input
->name
,
1144 /* if the arch type is specified make sure it matches the object */
1145 if(input
->arch_flag
.name
!= NULL
)
1146 check_arch(input
, thin
);
1148 /* see if this file is Mach-O file for 64-bit architectures */
1149 else if(size
>= sizeof(struct mach_header_64
) &&
1150 (*((uint32_t *)addr
) == MH_MAGIC_64
||
1151 *((uint32_t *)addr
) == SWAP_INT(MH_MAGIC_64
))){
1153 /* this is a Mach-O file so create a thin file struct for it */
1155 input
->is_thin
= TRUE
;
1156 thin
->name
= input
->name
;
1158 mhp64
= (struct mach_header_64
*)addr
;
1159 lcp
= (struct load_command
*)((char *)mhp64
+
1160 sizeof(struct mach_header_64
));
1161 if(mhp64
->magic
== SWAP_INT(MH_MAGIC_64
)){
1164 swap_mach_header_64(&mh64
, get_host_byte_sex());
1169 thin
->fat_arch
.cputype
= mhp64
->cputype
;
1170 thin
->fat_arch
.cpusubtype
= mhp64
->cpusubtype
;
1171 thin
->fat_arch
.offset
= 0;
1172 thin
->fat_arch
.size
= size
;
1173 thin
->fat_arch
.align
= get_align_64(mhp64
, lcp
, size
, input
->name
,
1176 /* if the arch type is specified make sure it matches the object */
1177 if(input
->arch_flag
.name
!= NULL
)
1178 check_arch(input
, thin
);
1180 /* see if this file is an archive file */
1181 else if(size
>= SARMAG
&& strncmp(addr
, ARMAG
, SARMAG
) == 0){
1183 check_archive(input
->name
, addr
, size
, &cputype
, &cpusubtype
);
1184 archives_in_input
= TRUE
;
1186 /* create a thin file struct for this archive */
1188 thin
->name
= input
->name
;
1190 thin
->fat_arch
.cputype
= cputype
;
1191 thin
->fat_arch
.cpusubtype
= cpusubtype
;
1192 thin
->fat_arch
.offset
= 0;
1193 thin
->fat_arch
.size
= size
;
1194 thin
->fat_arch
.align
= 2; /* 2^2, sizeof(uint32_t) */
1196 /* if the arch type is specified make sure it matches the object */
1197 if(input
->arch_flag
.name
!= NULL
){
1199 thin
->fat_arch
.cputype
= input
->arch_flag
.cputype
;
1200 thin
->fat_arch
.cpusubtype
= input
->arch_flag
.cpusubtype
;
1203 check_arch(input
, thin
);
1207 fatal("archive with no architecture specification: %s "
1208 "(can't determine architecture for it)", input
->name
);
1211 /* this file type is now known to be unknown to this program */
1214 if(input
->arch_flag
.name
!= NULL
){
1215 /* create a thin file struct for it */
1217 thin
->name
= input
->name
;
1219 thin
->fat_arch
.cputype
= input
->arch_flag
.cputype
;
1220 thin
->fat_arch
.cpusubtype
= input
->arch_flag
.cpusubtype
;
1221 thin
->fat_arch
.offset
= 0;
1222 thin
->fat_arch
.size
= size
;
1223 thin
->fat_arch
.align
= 0;
1227 if(is_llvm_bitcode_from_memory(addr
, size
, &input
->arch_flag
,
1229 /* create a thin file struct for it */
1231 thin
->name
= input
->name
;
1233 thin
->fat_arch
.cputype
= input
->arch_flag
.cputype
;
1234 thin
->fat_arch
.cpusubtype
= input
->arch_flag
.cpusubtype
;
1235 thin
->fat_arch
.offset
= 0;
1236 thin
->fat_arch
.size
= size
;
1237 thin
->fat_arch
.align
= 0;
1240 #endif /* LTO_SUPPORT */
1241 fatal("can't figure out the architecture type of: %s",
1248 * process_replace_file() checks the replacement file and maps it in for later
1253 process_replace_file(
1254 struct replace
*replace
)
1257 struct stat stat_buf
;
1260 struct mach_header
*mhp
, mh
;
1261 struct mach_header_64
*mhp64
, mh64
;
1262 struct load_command
*lcp
;
1264 cpu_subtype_t cpusubtype
;
1267 /* Open the replacement file and map it in */
1268 if((fd
= open(replace
->thin_file
.name
, O_RDONLY
)) == -1)
1269 system_fatal("can't open replacement file: %s",
1270 replace
->thin_file
.name
);
1271 if(fstat(fd
, &stat_buf
) == -1)
1272 system_fatal("can't stat replacement file: %s",
1273 replace
->thin_file
.name
);
1274 size
= stat_buf
.st_size
;
1276 * mmap() can't handle mapping regular files with zero size. So this
1277 * is handled separately.
1279 if((stat_buf
.st_mode
& S_IFREG
) == S_IFREG
&& size
== 0)
1282 addr
= mmap(0, size
, PROT_READ
|PROT_WRITE
, MAP_FILE
|MAP_PRIVATE
,
1284 if((intptr_t)addr
== -1)
1285 system_error("can't map replacement file: %s",
1286 replace
->thin_file
.name
);
1289 /* Try to figure out what kind of file this is */
1291 /* see if this file is a fat file */
1292 if(size
>= sizeof(struct fat_header
) &&
1293 *((uint32_t *)addr
) == FAT_MAGIC
){
1295 fatal("replacement file: %s is a fat file (must be a thin file)",
1296 replace
->thin_file
.name
);
1298 /* see if this file is Mach-O file for 32-bit architectures */
1299 else if(size
>= sizeof(struct mach_header
) &&
1300 (*((uint32_t *)addr
) == MH_MAGIC
||
1301 *((uint32_t *)addr
) == SWAP_INT(MH_MAGIC
))){
1303 /* this is a Mach-O file so fill in the thin file struct for it */
1304 replace
->thin_file
.addr
= addr
;
1305 mhp
= (struct mach_header
*)addr
;
1306 lcp
= (struct load_command
*)((char *)mhp
+
1307 sizeof(struct mach_header
));
1308 if(mhp
->magic
== SWAP_INT(MH_MAGIC
)){
1311 swap_mach_header(&mh
, get_host_byte_sex());
1316 replace
->thin_file
.fat_arch
.cputype
= mhp
->cputype
;
1317 replace
->thin_file
.fat_arch
.cpusubtype
= mhp
->cpusubtype
;
1318 replace
->thin_file
.fat_arch
.offset
= 0;
1319 replace
->thin_file
.fat_arch
.size
= size
;
1320 replace
->thin_file
.fat_arch
.align
=
1321 get_align(mhp
, lcp
, size
, replace
->thin_file
.name
, swapped
);
1323 /* see if this file is Mach-O file for 64-bit architectures */
1324 else if(size
>= sizeof(struct mach_header_64
) &&
1325 (*((uint32_t *)addr
) == MH_MAGIC_64
||
1326 *((uint32_t *)addr
) == SWAP_INT(MH_MAGIC_64
))){
1328 /* this is a Mach-O file so fill in the thin file struct for it */
1329 replace
->thin_file
.addr
= addr
;
1330 mhp64
= (struct mach_header_64
*)addr
;
1331 lcp
= (struct load_command
*)((char *)mhp64
+
1332 sizeof(struct mach_header_64
));
1333 if(mhp64
->magic
== SWAP_INT(MH_MAGIC_64
)){
1336 swap_mach_header_64(&mh64
, get_host_byte_sex());
1341 replace
->thin_file
.fat_arch
.cputype
= mhp64
->cputype
;
1342 replace
->thin_file
.fat_arch
.cpusubtype
= mhp64
->cpusubtype
;
1343 replace
->thin_file
.fat_arch
.offset
= 0;
1344 replace
->thin_file
.fat_arch
.size
= size
;
1345 replace
->thin_file
.fat_arch
.align
=
1346 get_align_64(mhp64
, lcp
, size
, replace
->thin_file
.name
, swapped
);
1348 /* see if this file is an archive file */
1349 else if(size
>= SARMAG
&& strncmp(addr
, ARMAG
, SARMAG
) == 0){
1351 check_archive(replace
->thin_file
.name
, addr
, size
,
1352 &cputype
, &cpusubtype
);
1354 /* fill in the thin file struct for this archive */
1355 replace
->thin_file
.addr
= addr
;
1356 replace
->thin_file
.fat_arch
.cputype
= cputype
;
1357 replace
->thin_file
.fat_arch
.cpusubtype
= cpusubtype
;
1358 replace
->thin_file
.fat_arch
.offset
= 0;
1359 replace
->thin_file
.fat_arch
.size
= size
;
1360 replace
->thin_file
.fat_arch
.align
= 2; /* 2^2, sizeof(uint32_t) */
1363 /* fill in the thin file struct for it */
1364 replace
->thin_file
.addr
= addr
;
1365 replace
->thin_file
.fat_arch
.cputype
= replace
->arch_flag
.cputype
;
1366 replace
->thin_file
.fat_arch
.cpusubtype
=
1367 replace
->arch_flag
.cpusubtype
;
1368 replace
->thin_file
.fat_arch
.offset
= 0;
1369 replace
->thin_file
.fat_arch
.size
= size
;
1370 replace
->thin_file
.fat_arch
.align
= 0;
1373 if(replace
->thin_file
.fat_arch
.cputype
!= replace
->arch_flag
.cputype
||
1374 (replace
->thin_file
.fat_arch
.cpusubtype
& ~CPU_SUBTYPE_MASK
) !=
1375 (replace
->arch_flag
.cpusubtype
& ~CPU_SUBTYPE_MASK
))
1376 fatal("specified architecture: %s for replacement file: %s does "
1377 "not match the file's architecture", replace
->arch_flag
.name
,
1378 replace
->thin_file
.name
);
1382 * check_archive() checks an archive (mapped in at 'addr' of size 'size') to
1383 * make sure it can be included in a fat file (all members are the same
1384 * architecture, no fat files, etc). It returns the cputype and cpusubtype.
1392 cpu_type_t
*cputype
,
1393 cpu_subtype_t
*cpusubtype
)
1395 uint32_t offset
, magic
, i
, ar_name_size
, ar_size
;
1396 struct mach_header mh
;
1397 struct mach_header_64 mh64
;
1398 struct ar_hdr
*ar_hdr
;
1399 char *ar_name
, *ar_addr
;
1400 struct arch_flag arch_flag
;
1403 * Check this archive out to make sure that it does not contain
1404 * any fat files and that all object files it contains have the
1405 * same cputype and subsubtype.
1411 fatal("empty archive with no architecture specification: %s "
1412 "(can't determine architecture for it)", name
);
1413 if(offset
!= size
&& offset
+ sizeof(struct ar_hdr
) > size
)
1414 fatal("truncated or malformed archive: %s (archive header of "
1415 "first member extends past the end of the file)", name
);
1416 while(size
> offset
){
1417 ar_hdr
= (struct ar_hdr
*)(addr
+ offset
);
1418 offset
+= sizeof(struct ar_hdr
);
1419 if(strncmp(ar_hdr
->ar_name
, AR_EFMT1
, sizeof(AR_EFMT1
) - 1) == 0){
1420 check_extend_format_1(name
, ar_hdr
, size
-offset
, &ar_name_size
);
1422 ar_name
= ar_hdr
->ar_name
+ sizeof(struct ar_hdr
);
1425 i
= size_ar_name(ar_hdr
->ar_name
);
1426 ar_name
= ar_hdr
->ar_name
;
1429 if(size
+ ar_name_size
- offset
> sizeof(uint32_t)){
1430 memcpy(&magic
, addr
+ offset
+ ar_name_size
,
1432 if(magic
== FAT_MAGIC
)
1433 fatal("archive member %s(%.*s) is a fat file (not "
1434 "allowed in an archive)", name
, (int)i
, ar_name
);
1435 if((size
- ar_name_size
) - offset
>=
1436 sizeof(struct mach_header
) &&
1437 (magic
== MH_MAGIC
|| magic
== SWAP_INT(MH_MAGIC
))){
1438 memcpy(&mh
, addr
+ offset
+ ar_name_size
,
1439 sizeof(struct mach_header
));
1440 if(mh
.magic
== SWAP_INT(MH_MAGIC
))
1441 swap_mach_header(&mh
, get_host_byte_sex());
1443 *cputype
= mh
.cputype
;
1444 *cpusubtype
= mh
.cpusubtype
;
1446 else if(*cputype
!= mh
.cputype
){
1447 fatal("archive member %s(%.*s) cputype (%d) and "
1448 "cpusubtype (%d) does not match previous "
1449 "archive members cputype (%d) and cpusubtype"
1450 " (%d) (all members must match)", name
,
1451 (int)i
, ar_name
, mh
.cputype
, mh
.cpusubtype
&
1452 ~CPU_SUBTYPE_MASK
, *cputype
, (*cpusubtype
) &
1456 else if((size
- ar_name_size
) - offset
>=
1457 sizeof(struct mach_header_64
) &&
1458 (magic
== MH_MAGIC_64
|| magic
== SWAP_INT(MH_MAGIC_64
))){
1459 memcpy(&mh64
, addr
+ offset
+ ar_name_size
,
1460 sizeof(struct mach_header_64
));
1461 if(mh64
.magic
== SWAP_INT(MH_MAGIC_64
))
1462 swap_mach_header_64(&mh64
, get_host_byte_sex());
1464 *cputype
= mh64
.cputype
;
1465 *cpusubtype
= mh64
.cpusubtype
;
1467 else if(*cputype
!= mh64
.cputype
){
1468 fatal("archive member %s(%.*s) cputype (%d) and "
1469 "cpusubtype (%d) does not match previous "
1470 "archive members cputype (%d) and cpusubtype"
1471 " (%d) (all members must match)", name
,
1472 (int)i
, ar_name
, mh64
.cputype
, mh64
.cpusubtype
&
1473 ~CPU_SUBTYPE_MASK
, *cputype
, (*cpusubtype
) &
1478 if(strncmp(ar_name
, SYMDEF
, sizeof(SYMDEF
) - 1) != 0){
1479 ar_addr
= addr
+ offset
+ ar_name_size
;
1480 ar_size
= strtoul(ar_hdr
->ar_size
, NULL
, 10);
1482 if(is_llvm_bitcode_from_memory(ar_addr
, ar_size
,
1483 &arch_flag
, NULL
) != 0){
1485 *cputype
= arch_flag
.cputype
;
1486 *cpusubtype
= arch_flag
.cpusubtype
;
1488 else if(*cputype
!= arch_flag
.cputype
){
1489 fatal("archive member %s(%.*s) cputype (%d) "
1490 "and cpusubtype (%d) does not match "
1491 "previous archive members cputype (%d) "
1492 "and cpusubtype (%d) (all members must "
1493 "match)", name
, (int)i
, ar_name
,
1494 arch_flag
.cputype
, arch_flag
.cpusubtype
&
1495 ~CPU_SUBTYPE_MASK
, *cputype
,
1496 (*cpusubtype
) & ~CPU_SUBTYPE_MASK
);
1499 #endif /* LTO_SUPPORT */
1503 offset
+= rnd(strtoul(ar_hdr
->ar_size
, NULL
, 10),
1508 * check_extend_format_1() checks the archive header for extened format1.
1512 check_extend_format_1(
1514 struct ar_hdr
*ar_hdr
,
1516 uint32_t *member_name_size
)
1518 char *p
, *endp
, buf
[sizeof(ar_hdr
->ar_name
)+1];
1519 uint32_t ar_name_size
;
1521 *member_name_size
= 0;
1523 buf
[sizeof(ar_hdr
->ar_name
)] = '\0';
1524 memcpy(buf
, ar_hdr
->ar_name
, sizeof(ar_hdr
->ar_name
));
1525 p
= buf
+ sizeof(AR_EFMT1
) - 1;
1526 if(isdigit(*p
) == 0)
1527 fatal("archive: %s malformed (ar_name: %.*s for archive extend "
1528 "format #1 starts with non-digit)", name
,
1529 (int)sizeof(ar_hdr
->ar_name
), ar_hdr
->ar_name
);
1530 ar_name_size
= strtoul(p
, &endp
, 10);
1531 if(ar_name_size
== UINT_MAX
&& errno
== ERANGE
)
1532 fatal("archive: %s malformed (size in ar_name: %.*s for archive "
1533 "extend format #1 overflows uint32_t)", name
,
1534 (int)sizeof(ar_hdr
->ar_name
), ar_hdr
->ar_name
);
1535 while(*endp
== ' ' && *endp
!= '\0')
1538 fatal("archive: %s malformed (size in ar_name: %.*s for archive "
1539 "extend format #1 contains non-digit and non-space "
1540 "characters)", name
, (int)sizeof(ar_hdr
->ar_name
),
1542 if(ar_name_size
> size_left
)
1543 fatal("archive: %s truncated or malformed (archive name "
1544 "of member extends past the end of the file)", name
);
1545 *member_name_size
= ar_name_size
;
1549 * get_arm64_fat_arch() will return a pointer to the fat_arch struct for the
1550 * 64-bit arm slice in the thin_files[i] if it is present. Else it returns
1559 struct fat_arch
*arm64_fat_arch
;
1562 * Look for a 64-bit arm slice.
1564 arm64_fat_arch
= NULL
;
1565 for(i
= 0; i
< nthin_files
; i
++){
1566 if(thin_files
[i
].fat_arch
.cputype
== CPU_TYPE_ARM64
){
1567 arm64_fat_arch
= &(thin_files
[i
].fat_arch
);
1568 return(arm64_fat_arch
);
1575 * get_align is passed a pointer to a mach header and size of the object. It
1576 * returns the segment alignment the object was created with. It guesses but
1577 * it is conservative. The maximum alignment is that the link editor will allow
1578 * MAXSECTALIGN and the minimum is the conserative alignment for a uint32_t
1579 * which appears in a mach object files (2^2 worst case for all current 32-bit
1585 struct mach_header
*mhp
,
1586 struct load_command
*load_commands
,
1591 uint32_t i
, j
, cur_align
, align
;
1592 struct load_command
*lcp
, l
;
1593 struct segment_command
*sgp
, sg
;
1594 struct section
*sp
, s
;
1595 enum byte_sex host_byte_sex
;
1598 * Special case ppc and i386 architectures and return 12.
1599 * We know that with those architectures that the kernel and mmap only
1600 * need file offsets to be page (4096 byte) aligned.
1602 if(mhp
->cputype
== CPU_TYPE_POWERPC
||
1603 mhp
->cputype
== CPU_TYPE_I386
)
1606 * Special case ARM and return 14. As it has 16k pages.
1608 if(mhp
->cputype
== CPU_TYPE_ARM
)
1611 host_byte_sex
= get_host_byte_sex();
1613 /* set worst case the link editor uses first */
1614 cur_align
= MAXSECTALIGN
;
1615 if(mhp
->sizeofcmds
+ sizeof(struct mach_header
) > size
)
1616 fatal("truncated or malformed object (load commands would "
1617 "extend past the end of the file) in: %s", name
);
1618 lcp
= load_commands
;
1619 for(i
= 0; i
< mhp
->ncmds
; i
++){
1622 swap_load_command(&l
, host_byte_sex
);
1623 if(l
.cmdsize
% sizeof(uint32_t) != 0)
1624 error("load command %u size not a multiple of "
1625 "sizeof(uint32_t) in: %s", i
, name
);
1627 fatal("load command %u size is less than or equal to zero "
1629 if((char *)lcp
+ l
.cmdsize
>
1630 (char *)load_commands
+ mhp
->sizeofcmds
)
1631 fatal("load command %u extends past end of all load "
1632 "commands in: %s", i
, name
);
1633 if(l
.cmd
== LC_SEGMENT
){
1634 sgp
= (struct segment_command
*)lcp
;
1637 swap_segment_command(&sg
, host_byte_sex
);
1638 if(mhp
->filetype
== MH_OBJECT
){
1639 /* this is the minimum alignment, then take largest */
1640 align
= 2; /* 2^2 sizeof(uint32_t) */
1641 sp
= (struct section
*)((char *)sgp
+
1642 sizeof(struct segment_command
));
1643 for(j
= 0; j
< sg
.nsects
; j
++){
1646 swap_section(&s
, 1, host_byte_sex
);
1651 if(align
< cur_align
)
1655 /* guess the smallest alignment and use that */
1656 align
= guess_align(sg
.vmaddr
);
1657 if(align
< cur_align
)
1661 lcp
= (struct load_command
*)((char *)lcp
+ l
.cmdsize
);
1667 * get_align_64 is passed a pointer to a mach_header_64 and size of the object.
1668 * It returns the segment alignment the object was created with. It guesses but
1669 * it is conservative. The maximum alignment is that the link editor will allow
1670 * MAXSECTALIGN and the minimum is the conserative alignment for a long long
1671 * which appears in a mach object files (2^3 worst case for all 64-bit
1677 struct mach_header_64
*mhp64
,
1678 struct load_command
*load_commands
,
1683 uint32_t i
, j
, cur_align
, align
;
1684 struct load_command
*lcp
, l
;
1685 struct segment_command_64
*sgp
, sg
;
1686 struct section_64
*sp
, s
;
1687 enum byte_sex host_byte_sex
;
1690 * Special case ppc64 and x86_64 architectures and return 12.
1691 * We know that with those architectures that the kernel and mmap only
1692 * need file offsets to be page (4096 byte) aligned.
1694 if(mhp64
->cputype
== CPU_TYPE_POWERPC64
||
1695 mhp64
->cputype
== CPU_TYPE_X86_64
)
1698 * Special case ARM64 and return 14. As it has 16k pages.
1700 if(mhp64
->cputype
== CPU_TYPE_ARM64
)
1703 host_byte_sex
= get_host_byte_sex();
1705 /* set worst case the link editor uses first */
1706 cur_align
= MAXSECTALIGN
;
1707 if(mhp64
->sizeofcmds
+ sizeof(struct mach_header_64
) > size
)
1708 fatal("truncated or malformed object (load commands would "
1709 "extend past the end of the file) in: %s", name
);
1710 lcp
= load_commands
;
1711 for(i
= 0; i
< mhp64
->ncmds
; i
++){
1714 swap_load_command(&l
, host_byte_sex
);
1715 if(l
.cmdsize
% sizeof(long long) != 0)
1716 error("load command %u size not a multiple of "
1717 "sizeof(long long) in: %s", i
, name
);
1719 fatal("load command %u size is less than or equal to zero "
1721 if((char *)lcp
+ l
.cmdsize
>
1722 (char *)load_commands
+ mhp64
->sizeofcmds
)
1723 fatal("load command %u extends past end of all load "
1724 "commands in: %s", i
, name
);
1725 if(l
.cmd
== LC_SEGMENT_64
){
1726 sgp
= (struct segment_command_64
*)lcp
;
1729 swap_segment_command_64(&sg
, host_byte_sex
);
1730 if(mhp64
->filetype
== MH_OBJECT
){
1731 /* this is the minimum alignment, then take largest */
1732 align
= 3; /* 2^3 sizeof(long long) */
1733 sp
= (struct section_64
*)((char *)sgp
+
1734 sizeof(struct segment_command_64
));
1735 for(j
= 0; j
< sg
.nsects
; j
++){
1738 swap_section_64(&s
, 1, host_byte_sex
);
1743 if(align
< cur_align
)
1747 /* guess the smallest alignment and use that */
1748 align
= guess_align(sg
.vmaddr
);
1749 if(align
< cur_align
)
1753 lcp
= (struct load_command
*)((char *)lcp
+ l
.cmdsize
);
1759 * guess_align is passed a vmaddr of a segment and guesses what the segment
1760 * alignment was. It uses the most conservative guess up to the maximum
1761 * alignment that the link editor uses.
1768 uint32_t align
, segalign
;
1771 return(MAXSECTALIGN
);
1775 while((segalign
& vmaddr
) == 0){
1776 segalign
= segalign
<< 1;
1782 if(align
> MAXSECTALIGN
)
1783 return(MAXSECTALIGN
);
1789 * print_arch() helps implement -info and -detailed_info by printing the
1790 * architecture name for the cputype and cpusubtype.
1795 struct fat_arch
*fat_arch
)
1797 switch(fat_arch
->cputype
){
1798 case CPU_TYPE_MC680x0
:
1799 switch(fat_arch
->cpusubtype
& ~CPU_SUBTYPE_MASK
){
1800 case CPU_SUBTYPE_MC680x0_ALL
:
1803 case CPU_SUBTYPE_MC68030_ONLY
:
1806 case CPU_SUBTYPE_MC68040
:
1810 goto print_arch_unknown
;
1813 case CPU_TYPE_POWERPC
:
1814 switch(fat_arch
->cpusubtype
& ~CPU_SUBTYPE_MASK
){
1815 case CPU_SUBTYPE_POWERPC_ALL
:
1818 case CPU_SUBTYPE_POWERPC_601
:
1821 case CPU_SUBTYPE_POWERPC_603
:
1824 case CPU_SUBTYPE_POWERPC_603e
:
1827 case CPU_SUBTYPE_POWERPC_603ev
:
1830 case CPU_SUBTYPE_POWERPC_604
:
1833 case CPU_SUBTYPE_POWERPC_604e
:
1836 case CPU_SUBTYPE_POWERPC_750
:
1839 case CPU_SUBTYPE_POWERPC_7400
:
1842 case CPU_SUBTYPE_POWERPC_7450
:
1845 case CPU_SUBTYPE_POWERPC_970
:
1849 goto print_arch_unknown
;
1852 case CPU_TYPE_POWERPC64
:
1853 switch(fat_arch
->cpusubtype
& ~CPU_SUBTYPE_MASK
){
1854 case CPU_SUBTYPE_POWERPC_ALL
:
1857 case CPU_SUBTYPE_POWERPC_970
:
1858 printf("ppc970-64");
1861 goto print_arch_unknown
;
1865 switch(fat_arch
->cpusubtype
& ~CPU_SUBTYPE_MASK
){
1866 case CPU_SUBTYPE_VEO_1
:
1869 case CPU_SUBTYPE_VEO_2
:
1872 case CPU_SUBTYPE_VEO_3
:
1875 case CPU_SUBTYPE_VEO_4
:
1879 goto print_arch_unknown
;
1882 case CPU_TYPE_MC88000
:
1883 switch(fat_arch
->cpusubtype
& ~CPU_SUBTYPE_MASK
){
1884 case CPU_SUBTYPE_MC88000_ALL
:
1885 case CPU_SUBTYPE_MC88110
:
1889 goto print_arch_unknown
;
1893 switch(fat_arch
->cpusubtype
& ~CPU_SUBTYPE_MASK
){
1894 case CPU_SUBTYPE_I386_ALL
:
1895 /* case CPU_SUBTYPE_386: same as above */
1898 case CPU_SUBTYPE_486
:
1901 case CPU_SUBTYPE_486SX
:
1904 case CPU_SUBTYPE_PENT
: /* same as 586 */
1907 case CPU_SUBTYPE_PENTPRO
:
1910 case CPU_SUBTYPE_PENTII_M3
:
1913 case CPU_SUBTYPE_PENTII_M5
:
1917 goto print_arch_unknown
;
1920 case CPU_TYPE_X86_64
:
1921 switch(fat_arch
->cpusubtype
& ~CPU_SUBTYPE_MASK
){
1922 case CPU_SUBTYPE_X86_64_ALL
:
1925 case CPU_SUBTYPE_X86_64_H
:
1929 goto print_arch_unknown
;
1933 switch(fat_arch
->cpusubtype
& ~CPU_SUBTYPE_MASK
){
1934 case CPU_SUBTYPE_I860_ALL
:
1935 case CPU_SUBTYPE_I860_860
:
1939 goto print_arch_unknown
;
1943 switch(fat_arch
->cpusubtype
& ~CPU_SUBTYPE_MASK
){
1944 case CPU_SUBTYPE_HPPA_ALL
:
1945 case CPU_SUBTYPE_HPPA_7100LC
:
1949 goto print_arch_unknown
;
1952 case CPU_TYPE_SPARC
:
1953 switch(fat_arch
->cpusubtype
& ~CPU_SUBTYPE_MASK
){
1954 case CPU_SUBTYPE_SPARC_ALL
:
1958 goto print_arch_unknown
;
1962 switch(fat_arch
->cpusubtype
){
1963 case CPU_SUBTYPE_ARM_ALL
:
1966 case CPU_SUBTYPE_ARM_V4T
:
1969 case CPU_SUBTYPE_ARM_V5TEJ
:
1972 case CPU_SUBTYPE_ARM_XSCALE
:
1975 case CPU_SUBTYPE_ARM_V6
:
1978 case CPU_SUBTYPE_ARM_V6M
:
1981 case CPU_SUBTYPE_ARM_V7
:
1984 case CPU_SUBTYPE_ARM_V7F
:
1987 case CPU_SUBTYPE_ARM_V7S
:
1990 case CPU_SUBTYPE_ARM_V7K
:
1993 case CPU_SUBTYPE_ARM_V7M
:
1996 case CPU_SUBTYPE_ARM_V7EM
:
2000 goto print_arch_unknown
;
2003 case CPU_TYPE_ARM64
:
2004 switch(fat_arch
->cpusubtype
& ~CPU_SUBTYPE_MASK
){
2005 case CPU_SUBTYPE_ARM64_ALL
:
2008 case CPU_SUBTYPE_ARM64_V8
:
2012 goto print_arch_unknown
;
2016 switch(fat_arch
->cpusubtype
& ~CPU_SUBTYPE_MASK
){
2017 case CPU_SUBTYPE_MULTIPLE
:
2020 case CPU_SUBTYPE_LITTLE_ENDIAN
:
2023 case CPU_SUBTYPE_BIG_ENDIAN
:
2027 goto print_arch_unknown
;
2032 printf("(cputype (%d) cpusubtype (%d))", fat_arch
->cputype
,
2033 fat_arch
->cpusubtype
& ~CPU_SUBTYPE_MASK
);
2039 * print_cputype() helps implement -detailed_info by printing the cputype and
2040 * cpusubtype (symbolicly for the one's it knows about).
2046 cpu_subtype_t cpusubtype
)
2049 case CPU_TYPE_MC680x0
:
2050 switch(cpusubtype
& ~CPU_SUBTYPE_MASK
){
2051 case CPU_SUBTYPE_MC680x0_ALL
:
2052 printf(" cputype CPU_TYPE_MC680x0\n"
2053 " cpusubtype CPU_SUBTYPE_MC680x0_ALL\n");
2055 case CPU_SUBTYPE_MC68030_ONLY
:
2056 printf(" cputype CPU_TYPE_MC680x0\n"
2057 " cpusubtype CPU_SUBTYPE_MC68030_ONLY\n");
2059 case CPU_SUBTYPE_MC68040
:
2060 printf(" cputype CPU_TYPE_MC680x0\n"
2061 " cpusubtype CPU_SUBTYPE_MC68040\n");
2064 goto print_arch_unknown
;
2067 case CPU_TYPE_POWERPC
:
2068 switch(cpusubtype
& ~CPU_SUBTYPE_MASK
){
2069 case CPU_SUBTYPE_POWERPC_ALL
:
2070 printf(" cputype CPU_TYPE_POWERPC\n"
2071 " cpusubtype CPU_SUBTYPE_POWERPC_ALL\n");
2073 case CPU_SUBTYPE_POWERPC_601
:
2074 printf(" cputype CPU_TYPE_POWERPC\n"
2075 " cpusubtype CPU_SUBTYPE_POWERPC_601\n");
2077 case CPU_SUBTYPE_POWERPC_603
:
2078 printf(" cputype CPU_TYPE_POWERPC\n"
2079 " cpusubtype CPU_SUBTYPE_POWERPC_603\n");
2081 case CPU_SUBTYPE_POWERPC_603e
:
2082 printf(" cputype CPU_TYPE_POWERPC\n"
2083 " cpusubtype CPU_SUBTYPE_POWERPC_603e\n");
2085 case CPU_SUBTYPE_POWERPC_603ev
:
2086 printf(" cputype CPU_TYPE_POWERPC\n"
2087 " cpusubtype CPU_SUBTYPE_POWERPC_603ev\n");
2089 case CPU_SUBTYPE_POWERPC_604
:
2090 printf(" cputype CPU_TYPE_POWERPC\n"
2091 " cpusubtype CPU_SUBTYPE_POWERPC_604\n");
2093 case CPU_SUBTYPE_POWERPC_604e
:
2094 printf(" cputype CPU_TYPE_POWERPC\n"
2095 " cpusubtype CPU_SUBTYPE_POWERPC_604e\n");
2097 case CPU_SUBTYPE_POWERPC_750
:
2098 printf(" cputype CPU_TYPE_POWERPC\n"
2099 " cpusubtype CPU_SUBTYPE_POWERPC_750\n");
2101 case CPU_SUBTYPE_POWERPC_7400
:
2102 printf(" cputype CPU_TYPE_POWERPC\n"
2103 " cpusubtype CPU_SUBTYPE_POWERPC_7400\n");
2105 case CPU_SUBTYPE_POWERPC_7450
:
2106 printf(" cputype CPU_TYPE_POWERPC\n"
2107 " cpusubtype CPU_SUBTYPE_POWERPC_7450\n");
2109 case CPU_SUBTYPE_POWERPC_970
:
2110 printf(" cputype CPU_TYPE_POWERPC\n"
2111 " cpusubtype CPU_SUBTYPE_POWERPC_970\n");
2114 goto print_arch_unknown
;
2117 case CPU_TYPE_POWERPC64
:
2118 switch(cpusubtype
& ~CPU_SUBTYPE_MASK
){
2119 case CPU_SUBTYPE_POWERPC_ALL
:
2120 printf(" cputype CPU_TYPE_POWERPC64\n"
2121 " cpusubtype CPU_SUBTYPE_POWERPC_ALL\n");
2123 case CPU_SUBTYPE_POWERPC_970
:
2124 printf(" cputype CPU_TYPE_POWERPC64\n"
2125 " cpusubtype CPU_SUBTYPE_POWERPC_970\n");
2128 goto print_arch_unknown
;
2132 switch(cpusubtype
& ~CPU_SUBTYPE_MASK
){
2133 case CPU_SUBTYPE_VEO_1
:
2134 printf(" cputype CPU_TYPE_VEO\n"
2135 " cpusubtype CPU_SUBTYPE_VEO_1\n");
2137 case CPU_SUBTYPE_VEO_2
:
2138 printf(" cputype CPU_TYPE_VEO\n"
2139 " cpusubtype CPU_SUBTYPE_VEO_2\n");
2141 case CPU_SUBTYPE_VEO_3
:
2142 printf(" cputype CPU_TYPE_VEO\n"
2143 " cpusubtype CPU_SUBTYPE_VEO_3\n");
2145 case CPU_SUBTYPE_VEO_4
:
2146 printf(" cputype CPU_TYPE_VEO\n"
2147 " cpusubtype CPU_SUBTYPE_VEO_4\n");
2150 goto print_arch_unknown
;
2153 case CPU_TYPE_MC88000
:
2154 switch(cpusubtype
& ~CPU_SUBTYPE_MASK
){
2155 case CPU_SUBTYPE_MC88000_ALL
:
2156 printf(" cputype CPU_TYPE_MC88000\n"
2157 " cpusubtype CPU_SUBTYPE_MC88000_ALL\n");
2159 case CPU_SUBTYPE_MC88110
:
2160 printf(" cputype CPU_TYPE_MC88000\n"
2161 " cpusubtype CPU_SUBTYPE_MC88110\n");
2164 goto print_arch_unknown
;
2168 switch(cpusubtype
& ~CPU_SUBTYPE_MASK
){
2169 case CPU_SUBTYPE_I386_ALL
:
2170 /* case CPU_SUBTYPE_386: same as above */
2171 printf(" cputype CPU_TYPE_I386\n"
2172 " cpusubtype CPU_SUBTYPE_I386_ALL\n");
2174 case CPU_SUBTYPE_486
:
2175 printf(" cputype CPU_TYPE_I386\n"
2176 " cpusubtype CPU_SUBTYPE_486\n");
2178 case CPU_SUBTYPE_486SX
:
2179 printf(" cputype CPU_TYPE_I386\n"
2180 " cpusubtype CPU_SUBTYPE_486SX\n");
2182 case CPU_SUBTYPE_PENT
: /* same as 586 */
2183 printf(" cputype CPU_TYPE_I386\n"
2184 " cpusubtype CPU_SUBTYPE_PENT\n");
2186 case CPU_SUBTYPE_PENTPRO
:
2187 printf(" cputype CPU_TYPE_I386\n"
2188 " cpusubtype CPU_SUBTYPE_PENTPRO\n");
2190 case CPU_SUBTYPE_PENTII_M3
:
2191 printf(" cputype CPU_TYPE_I386\n"
2192 " cpusubtype CPU_SUBTYPE_PENTII_M3\n");
2194 case CPU_SUBTYPE_PENTII_M5
:
2195 printf(" cputype CPU_TYPE_I386\n"
2196 " cpusubtype CPU_SUBTYPE_PENTII_M5\n");
2199 goto print_arch_unknown
;
2202 case CPU_TYPE_X86_64
:
2203 switch(cpusubtype
& ~CPU_SUBTYPE_MASK
){
2204 case CPU_SUBTYPE_X86_64_ALL
:
2205 printf(" cputype CPU_TYPE_X86_64\n"
2206 " cpusubtype CPU_SUBTYPE_X86_64_ALL\n");
2208 case CPU_SUBTYPE_X86_64_H
:
2209 printf(" cputype CPU_TYPE_X86_64\n"
2210 " cpusubtype CPU_SUBTYPE_X86_64_H\n");
2213 goto print_arch_unknown
;
2217 switch(cpusubtype
& ~CPU_SUBTYPE_MASK
){
2218 case CPU_SUBTYPE_I860_ALL
:
2219 printf(" cputype CPU_TYPE_I860\n"
2220 " cpusubtype CPU_SUBTYPE_I860_ALL\n");
2222 case CPU_SUBTYPE_I860_860
:
2223 printf(" cputype CPU_TYPE_I860\n"
2224 " cpusubtype CPU_SUBTYPE_I860_860\n");
2227 goto print_arch_unknown
;
2231 switch(cpusubtype
& ~CPU_SUBTYPE_MASK
){
2232 case CPU_SUBTYPE_HPPA_ALL
:
2233 printf(" cputype CPU_TYPE_HPPA\n"
2234 " cpusubtype CPU_SUBTYPE_HPPA_ALL\n");
2236 case CPU_SUBTYPE_HPPA_7100LC
:
2237 printf(" cputype CPU_TYPE_HPPA\n"
2238 " cpusubtype CPU_SUBTYPE_HPPA_7100LC\n");
2241 goto print_arch_unknown
;
2244 case CPU_TYPE_SPARC
:
2245 switch(cpusubtype
& ~CPU_SUBTYPE_MASK
){
2246 case CPU_SUBTYPE_SPARC_ALL
:
2247 printf(" cputype CPU_TYPE_SPARC\n"
2248 " cpusubtype CPU_SUBTYPE_SPARC_ALL\n");
2251 goto print_arch_unknown
;
2256 case CPU_SUBTYPE_ARM_V4T
:
2257 printf(" cputype CPU_TYPE_ARM\n"
2258 " cpusubtype CPU_SUBTYPE_ARM_V4T\n");
2260 case CPU_SUBTYPE_ARM_V5TEJ
:
2261 printf(" cputype CPU_TYPE_ARM\n"
2262 " cpusubtype CPU_SUBTYPE_ARM_V5TEJ\n");
2264 case CPU_SUBTYPE_ARM_XSCALE
:
2265 printf(" cputype CPU_TYPE_ARM\n"
2266 " cpusubtype CPU_SUBTYPE_ARM_XSCALE\n");
2268 case CPU_SUBTYPE_ARM_V6
:
2269 printf(" cputype CPU_TYPE_ARM\n"
2270 " cpusubtype CPU_SUBTYPE_ARM_V6\n");
2272 case CPU_SUBTYPE_ARM_V6M
:
2273 printf(" cputype CPU_TYPE_ARM\n"
2274 " cpusubtype CPU_SUBTYPE_ARM_V6M\n");
2276 case CPU_SUBTYPE_ARM_V7
:
2277 printf(" cputype CPU_TYPE_ARM\n"
2278 " cpusubtype CPU_SUBTYPE_ARM_V7\n");
2280 case CPU_SUBTYPE_ARM_V7F
:
2281 printf(" cputype CPU_TYPE_ARM\n"
2282 " cpusubtype CPU_SUBTYPE_ARM_V7F\n");
2284 case CPU_SUBTYPE_ARM_V7S
:
2285 printf(" cputype CPU_TYPE_ARM\n"
2286 " cpusubtype CPU_SUBTYPE_ARM_V7S\n");
2288 case CPU_SUBTYPE_ARM_V7K
:
2289 printf(" cputype CPU_TYPE_ARM\n"
2290 " cpusubtype CPU_SUBTYPE_ARM_V7K\n");
2292 case CPU_SUBTYPE_ARM_V7M
:
2293 printf(" cputype CPU_TYPE_ARM\n"
2294 " cpusubtype CPU_SUBTYPE_ARM_V7M\n");
2296 case CPU_SUBTYPE_ARM_V7EM
:
2297 printf(" cputype CPU_TYPE_ARM\n"
2298 " cpusubtype CPU_SUBTYPE_ARM_V7EM\n");
2300 case CPU_SUBTYPE_ARM_ALL
:
2301 printf(" cputype CPU_TYPE_ARM\n"
2302 " cpusubtype CPU_SUBTYPE_ARM_ALL\n");
2305 goto print_arch_unknown
;
2308 case CPU_TYPE_ARM64
:
2309 switch(cpusubtype
& ~CPU_SUBTYPE_MASK
){
2310 case CPU_SUBTYPE_ARM64_ALL
:
2311 printf(" cputype CPU_TYPE_ARM64\n"
2312 " cpusubtype CPU_SUBTYPE_ARM64_ALL\n");
2314 case CPU_SUBTYPE_ARM64_V8
:
2315 printf(" cputype CPU_TYPE_ARM64\n"
2316 " cpusubtype CPU_SUBTYPE_ARM64_V8\n");
2319 goto print_arch_unknown
;
2323 switch(cpusubtype
& ~CPU_SUBTYPE_MASK
){
2324 case CPU_SUBTYPE_MULTIPLE
:
2325 printf(" cputype CPU_TYPE_ANY\n"
2326 " cpusubtype CPU_SUBTYPE_MULTIPLE\n");
2328 case CPU_SUBTYPE_LITTLE_ENDIAN
:
2329 printf(" cputype CPU_TYPE_ANY\n"
2330 " cpusubtype CPU_SUBTYPE_LITTLE_ENDIAN\n");
2332 case CPU_SUBTYPE_BIG_ENDIAN
:
2333 printf(" cputype CPU_TYPE_ANY\n"
2334 " cpusubtype CPU_SUBTYPE_BIG_ENDIAN\n");
2337 goto print_arch_unknown
;
2342 printf(" cputype (%d)\n"
2343 " cpusubtype cpusubtype (%d)\n", cputype
,
2344 cpusubtype
& ~CPU_SUBTYPE_MASK
);
2350 * size_ar_name is used to return the size of the name of an archive member
2351 * for printing it without blanks (with printf string "%.*s").
2359 struct ar_hdr ar_hdr
;
2361 for(j
= 0; j
< sizeof(ar_hdr
.ar_name
); j
++){
2362 if(ar_name
[j
] == ' ')
2369 * Create a new input file struct, clear it and return it.
2375 struct input_file
*input
;
2377 input_files
= reallocate(input_files
,
2378 (ninput_files
+ 1) * sizeof(struct input_file
));
2379 input
= input_files
+ ninput_files
;
2381 memset(input
, '\0', sizeof(struct input_file
));
2386 * Create a new thin file struct, clear it and return it.
2392 struct thin_file
*thin
;
2394 thin_files
= reallocate(thin_files
,
2395 (nthin_files
+ 1) * sizeof(struct thin_file
));
2396 thin
= thin_files
+ nthin_files
;
2398 memset(thin
, '\0', sizeof(struct thin_file
));
2403 * Create a new arch_flag struct on the specified list, clear it and return it.
2408 struct arch_flag
**arch_flags
,
2409 uint32_t *narch_flags
)
2411 struct arch_flag
*arch_flag
;
2413 *arch_flags
= reallocate(*arch_flags
,
2414 (*narch_flags
+ 1) * sizeof(struct arch_flag
));
2415 arch_flag
= *arch_flags
+ *narch_flags
;
2416 *narch_flags
= *narch_flags
+ 1;
2417 memset(arch_flag
, '\0', sizeof(struct arch_flag
));
2422 * Create a new replace struct, clear it and return it.
2428 struct replace
*replace
;
2430 replaces
= reallocate(replaces
,
2431 (nreplaces
+ 1) * sizeof(struct replace
));
2432 replace
= replaces
+ nreplaces
;
2434 memset(replace
, '\0', sizeof(struct replace
));
2439 * Create a new segalign struct, clear it and return it.
2445 struct segalign
*segalign
;
2447 segaligns
= reallocate(segaligns
,
2448 (nsegaligns
+ 1) * sizeof(struct segalign
));
2449 segalign
= segaligns
+ nsegaligns
;
2451 memset(segalign
, '\0', sizeof(struct segalign
));
2456 * Function for qsort for comparing thin file's alignment
2461 const struct thin_file
*thin1
,
2462 const struct thin_file
*thin2
)
2464 return(thin1
->fat_arch
.align
- thin2
->fat_arch
.align
);
2468 * rnd() rounds v to a multiple of r.
2483 * ispoweroftwo() returns TRUE or FALSE depending if x is a power of two.
2493 while((x
& 0x1) != 0x1){
2503 * check_arch is called when an input file is specified with a -arch flag input
2504 * and that the architecture can be determined from the input to check that
2505 * both architectures match.
2510 struct input_file
*input
,
2511 struct thin_file
*thin
)
2513 if(input
->arch_flag
.cputype
!= thin
->fat_arch
.cputype
)
2514 fatal("specifed architecture type (%s) for file (%s) does "
2515 "not match its cputype (%d) and cpusubtype (%d) "
2516 "(should be cputype (%d) and cpusubtype (%d))",
2517 input
->arch_flag
.name
, input
->name
,
2518 thin
->fat_arch
.cputype
, thin
->fat_arch
.cpusubtype
&
2519 ~CPU_SUBTYPE_MASK
, input
->arch_flag
.cputype
,
2520 input
->arch_flag
.cpusubtype
& ~CPU_SUBTYPE_MASK
);
2524 * Create a blank dylib. This is a stub dylib with no load commands.
2525 * It is a target page size block of bytes of zero except for the mach_header.
2530 struct arch_flag
*arch
)
2532 uint32_t target_page_size
, align
, onebit
;
2533 struct thin_file
*file
;
2534 enum byte_sex host_byte_sex
, target_byte_sex
;
2535 struct mach_header
*mh
;
2536 struct mach_header_64
*mh64
;
2539 file
->name
= "blank dylib";
2540 target_page_size
= get_segalign_from_flag(arch
);
2541 file
->addr
= allocate(target_page_size
);
2542 memset(file
->addr
, '\0', target_page_size
);
2543 file
->fat_arch
.cputype
= arch
->cputype
;
2544 file
->fat_arch
.cpusubtype
= arch
->cpusubtype
;
2545 file
->fat_arch
.offset
= 0;
2546 file
->fat_arch
.size
= target_page_size
;
2548 for(align
= 1; (target_page_size
& onebit
) != onebit
; align
++)
2549 onebit
= onebit
<< 1;
2550 file
->fat_arch
.align
= align
;
2552 host_byte_sex
= get_host_byte_sex();
2553 target_byte_sex
= get_byte_sex_from_flag(arch
);
2555 if((arch
->cputype
& CPU_ARCH_ABI64
) == CPU_ARCH_ABI64
){
2556 mh64
= (struct mach_header_64
*)file
->addr
;
2557 mh64
->magic
= MH_MAGIC_64
;
2558 mh64
->cputype
= arch
->cputype
;
2559 mh64
->cpusubtype
= arch
->cpusubtype
;
2560 mh64
->filetype
= MH_DYLIB_STUB
;
2561 if(target_byte_sex
!= host_byte_sex
)
2562 swap_mach_header_64(mh64
, target_byte_sex
);
2565 mh
= (struct mach_header
*)file
->addr
;
2566 mh
->magic
= MH_MAGIC
;
2567 mh
->cputype
= arch
->cputype
;
2568 mh
->cpusubtype
= arch
->cpusubtype
;
2569 mh
->filetype
= MH_DYLIB_STUB
;
2570 if(target_byte_sex
!= host_byte_sex
)
2571 swap_mach_header(mh
, target_byte_sex
);
2577 * Print the current usage line and exit (by calling fatal).
2583 fatal("Usage: %s [input_file] ... [-arch <arch_type> input_file] ... "
2584 "[-info] [-detailed_info] [-output output_file] [-create] "
2585 "[-arch_blank <arch_type>] [-thin <arch_type>] "
2586 "[-remove <arch_type>] ... [-extract <arch_type>] ... "
2587 "[-extract_family <arch_type>] ... "
2588 "[-verify_arch <arch_type> ...] "
2589 "[-replace <arch_type> <file_name>] ...", progname
);