855
[darwin-xtools.git] / cctools / misc / lipo.c
blob6c1dd8e0a9aac91b3f746c4926174113e68b5c92
1 /*
2 * Copyright (c) 1999 Apple Computer, Inc. All rights reserved.
4 * @APPLE_LICENSE_HEADER_START@
5 *
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
11 * file.
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:
26 * <input_file>
27 * -output <filename>
28 * -create
29 * -info
30 * -detailed_info
31 * -arch <arch_type> <input_file>
32 * -arch_blank <arch_type>
33 * -thin <arch_type>
34 * -extract <arch_type>
35 * -remove <arch_type>
36 * -replace <arch_type> <file_name>
37 * -segalign <arch_type> <value>
38 * -verify_arch <arch_type> ...
40 #include <stdio.h>
41 #include <string.h>
42 #include <stdlib.h>
43 #include <ar.h>
44 #ifndef AR_EFMT1
45 #define AR_EFMT1 "#1/" /* extended format #1 */
46 #endif
47 #include <limits.h>
48 #include <errno.h>
49 #include <ctype.h>
50 #include <libc.h>
51 #ifndef __OPENSTEP__
52 #include <utime.h>
53 #endif
54 #include <sys/file.h>
55 #include <sys/types.h>
56 #include <sys/stat.h>
57 #include <sys/mman.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> */
70 #undef TRUE
71 #undef FALSE
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 */
77 struct input_file {
78 char *name;
79 struct arch_flag arch_flag;
80 struct fat_header *fat_header;
81 struct fat_arch *fat_arches;
82 enum bool is_thin;
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 */
88 struct thin_file {
89 char *name;
90 char *addr;
91 struct fat_arch fat_arch;
92 enum bool from_fat;
93 enum bool extract;
94 enum bool remove;
95 enum bool replace;
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;
103 #ifndef __OPENSTEP__
104 static struct utimbuf output_timep = { 0 };
105 #else
106 static time_t output_timep[2] = { 0 };
107 #endif
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;
128 struct replace {
129 struct arch_flag arch_flag;
130 struct thin_file thin_file;
132 static struct replace *replaces = NULL;
133 static uint32_t nreplaces = 0;
135 struct segalign {
136 struct arch_flag arch_flag;
137 uint32_t align;
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(
148 void);
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(
155 void);
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(
161 char *name,
162 char *addr,
163 uint32_t size,
164 cpu_type_t *cputype,
165 cpu_subtype_t *cpusubtype);
166 static void check_extend_format_1(
167 char *name,
168 struct ar_hdr *ar_hdr,
169 uint32_t size_left,
170 uint32_t *member_name_size);
171 static uint32_t get_align(
172 struct mach_header *mhp,
173 struct load_command *load_commands,
174 uint32_t size,
175 char *name,
176 enum bool swapped);
177 static uint32_t get_align_64(
178 struct mach_header_64 *mhp64,
179 struct load_command *load_commands,
180 uint32_t size,
181 char *name,
182 enum bool swapped);
183 static uint32_t guess_align(
184 uint32_t vmaddr);
185 static void print_arch(
186 struct fat_arch *fat_arch);
187 static void print_cputype(
188 cpu_type_t cputype,
189 cpu_subtype_t cpusubtype);
190 static int size_ar_name(
191 char *ar_name);
192 static struct input_file *new_input(
193 void);
194 static struct thin_file *new_thin(
195 void);
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(
200 void);
201 static struct segalign *new_segalign(
202 void);
203 static int cmp_qsort(
204 const struct thin_file *thin1,
205 const struct thin_file *thin2);
206 static uint32_t rnd(
207 uint32_t v,
208 uint32_t r);
209 static enum bool ispoweroftwo(
210 uint32_t x);
211 static void check_arch(
212 struct input_file *input,
213 struct thin_file *thin);
214 static void usage(
215 void);
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;
224 main(
225 int argc,
226 char *argv[],
227 char *envp[])
229 int fd, a;
230 uint32_t i, j, k, value;
231 char *p, *endp;
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;
237 enum bool found;
238 struct arch_flag blank_arch;
240 input = NULL;
242 * Process the command line arguments.
244 progname = argv[0];
245 for(a = 1; a < argc; a++){
246 if(argv[a][0] == '-'){
247 p = &(argv[a][1]);
248 switch(*p){
249 case 'a':
250 if(strcmp(p, "arch") == 0 || strcmp(p, "a") == 0){
251 if(a + 2 >= argc){
252 error("missing argument(s) to %s option", argv[a]);
253 usage();
255 input = new_input();
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]);
261 arch_usage();
262 usage();
264 input->name = argv[a+2];
265 a += 2;
267 else if(strcmp(p, "arch_blank") == 0){
268 arch_blank_flag = TRUE;
269 if(a + 1 >= argc){
270 error("missing argument(s) to %s option", argv[a]);
271 usage();
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],
276 argv[a], argv[a+1]);
277 arch_usage();
278 usage();
280 new_blank_dylib(&blank_arch);
281 a += 1;
283 else
284 goto unknown_flag;
285 break;
286 case 'c':
287 if(strcmp(p, "create") == 0 || strcmp(p, "c") == 0){
288 create_flag = TRUE;
290 else
291 goto unknown_flag;
292 break;
293 case 'd':
294 if(strcmp(p, "detailed_info") == 0 || strcmp(p, "d") == 0){
295 detailed_info_flag = TRUE;
297 else
298 goto unknown_flag;
299 break;
300 case 'e':
301 if(strcmp(p, "extract") == 0 ||
302 strcmp(p, "extract_family") == 0 ||
303 strcmp(p, "e") == 0){
304 extract_flag = TRUE;
305 if(strcmp(p, "extract_family") == 0)
306 extract_family_flag = TRUE;
307 if(a + 1 >= argc){
308 error("missing argument to %s option", argv[a]);
309 usage();
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]);
317 arch_usage();
318 usage();
320 a++;
322 else
323 goto unknown_flag;
324 break;
325 case 'i':
326 if(strcmp(p, "info") == 0 || strcmp(p, "i") == 0){
327 info_flag = TRUE;
329 else
330 goto unknown_flag;
331 break;
332 case 'o':
333 if(strcmp(p, "output") == 0 || strcmp(p, "o") == 0){
334 if(a + 1 >= argc){
335 error("missing argument to %s option", argv[a]);
336 usage();
338 if(output_file != NULL)
339 fatal("more than one %s option specified", argv[a]);
340 output_file = argv[a + 1];
341 a++;
343 else
344 goto unknown_flag;
345 break;
346 case 'r':
347 if(strcmp(p, "remove") == 0 || strcmp(p, "rem") == 0){
348 remove_flag = TRUE;
349 if(a + 1 >= argc){
350 error("missing argument to %s option", argv[a]);
351 usage();
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]);
359 arch_usage();
360 usage();
362 a++;
364 else if(strcmp(p, "replace") == 0 || strcmp(p, "rep") == 0){
365 replace_flag = TRUE;
366 if(a + 2 >= argc){
367 error("missing argument(s) to %s option", argv[a]);
368 usage();
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]);
376 arch_usage();
377 usage();
379 replace->thin_file.name = argv[a+2];
380 a += 2;
382 else
383 goto unknown_flag;
384 break;
385 case 's':
386 if(strcmp(p, "segalign") == 0 || strcmp(p, "s") == 0){
387 if(a + 2 >= argc){
388 error("missing argument(s) to %s option", argv[a]);
389 usage();
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]);
397 arch_usage();
398 usage();
400 value = strtoul(argv[a+2], &endp, 16);
401 if(*endp != '\0')
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));
411 segalign->align = 0;
412 while((value & 0x1) != 1){
413 value >>= 1;
414 segalign->align++;
416 a += 2;
418 else
419 goto unknown_flag;
420 break;
421 case 't':
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]);
425 thin_flag = TRUE;
426 if(a + 1 >= argc){
427 error("missing argument to %s option", argv[a]);
428 usage();
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]);
434 arch_usage();
435 usage();
437 a++;
439 else
440 goto unknown_flag;
441 break;
442 case 'v':
443 if(strcmp(p, "verify_arch") == 0){
444 verify_flag = TRUE;
445 if(a + 1 >= argc){
446 error("missing argument(s) to %s option", argv[a]);
447 usage();
449 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]);
459 arch_usage();
460 usage();
464 else
465 goto unknown_flag;
466 break;
467 default:
468 unknown_flag:
469 fatal("unknown flag: %s", argv[a]);
472 else{
473 input = new_input();
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");
489 usage();
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");
495 usage();
497 if(ninput_files == 0){
498 error("no input files specified");
499 usage();
501 if(verify_flag == TRUE && ninput_files != 1){
502 error("only one input file allowed with -verify_arch");
503 usage();
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");
511 usage();
513 if(arch_blank_flag == TRUE && create_flag == FALSE){
514 error("-arch_blank may only be used with -create");
515 usage();
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.
528 if(create_flag){
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 &
543 ~CPU_SUBTYPE_MASK))
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,
547 arch_flags[k].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 &
554 ~CPU_SUBTYPE_MASK);
556 create_fat();
559 if(thin_flag){
560 if(ninput_files != 1)
561 fatal("only one input file can be specified with the -thin "
562 "option");
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",
574 output_file);
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",
579 output_file);
580 if(close(fd) == -1)
581 system_fatal("can't close output file: %s",output_file);
582 if(utime(output_file,
583 #ifndef __OPENSTEP__
584 &output_timep) == -1)
585 #else
586 output_timep) == -1)
587 #endif
588 system_fatal("can't set the modify times for "
589 "output file: %s", output_file);
590 break;
593 if(i == nthin_files)
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);
599 if(extract_flag){
600 if(ninput_files != 1)
601 fatal("only one input file can be specified with the -extract "
602 "option");
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++){
618 found = FALSE;
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 &
623 ~CPU_SUBTYPE_MASK)==
624 (thin_files[j].fat_arch.cpusubtype &
625 ~CPU_SUBTYPE_MASK) ||
626 extract_family_flag == TRUE)){
627 thin_files[j].extract = TRUE;
628 found = TRUE;
631 if(found == FALSE)
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];
641 nthin_files--;
643 else
644 i++;
646 create_fat();
649 if(remove_flag){
650 if(ninput_files != 1)
651 fatal("only one input file can be specified with the -remove "
652 "option");
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 &
674 ~CPU_SUBTYPE_MASK)){
675 thin_files[j].remove = TRUE;
676 break;
679 if(j == nthin_files)
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];
689 nthin_files--;
691 else
692 i++;
694 if(nthin_files == 0)
695 fatal("-remove's specified would result in an empty fat file");
696 create_fat();
699 if(replace_flag){
700 if(ninput_files != 1)
701 fatal("only one input file can be specified with the -replace "
702 "option");
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;
724 break;
727 if(j == nthin_files)
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);
732 create_fat();
735 if(info_flag){
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]));
742 printf(" ");
744 printf("\n");
746 else{
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)
754 continue;
755 printf("Non-fat file: %s is architecture: %s\n",
756 thin_files[i].name,
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]));
773 printf("\n");
774 print_cputype(input_files[i].fat_arches[j].cputype,
775 input_files[i].fat_arches[j].cpusubtype &
776 ~CPU_SUBTYPE_MASK);
777 printf(" offset %u\n",
778 input_files[i].fat_arches[j].offset);
779 printf(" size %u\n",
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);
786 else{
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)
793 continue;
794 printf("Non-fat file: %s is architecture: %s\n",
795 thin_files[i].name,
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++){
803 found = FALSE;
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)){
809 found = TRUE;
810 break;
813 if(found == FALSE)
814 exit(1);
818 return(0);
822 * create_fat() creates a fat output file from the thin files.
824 static
825 void
826 create_fat(void)
828 uint32_t i, j, offset;
829 char *rename_file;
830 int fd;
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
852 the user.
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;
862 break;
865 if(j == nthin_files)
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",
905 rename_file);
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))
915 continue;
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",
922 rename_file);
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.
933 if(arm64_fat_arch){
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",
940 rename_file);
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);
953 if(close(fd) == -1)
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);
958 free(rename_file);
962 * process_input_file() checks input file and breaks it down into thin files
963 * for later operations.
965 static
966 void
967 process_input_file(
968 struct input_file *input)
970 int fd;
971 struct stat stat_buf, stat_buf2;
972 uint32_t size, i, j;
973 char *addr;
974 struct thin_file *thin;
975 struct mach_header *mhp, mh;
976 struct mach_header_64 *mhp64, mh64;
977 struct load_command *lcp;
978 cpu_type_t cputype;
979 cpu_subtype_t cpusubtype;
980 enum bool swapped;
981 uint64_t big_size;
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.
998 #ifndef __OPENSTEP__
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;
1004 #else
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;
1009 #endif
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)
1015 addr = NULL;
1016 else
1017 addr = mmap(0, size, PROT_READ|PROT_WRITE, MAP_FILE|MAP_PRIVATE,
1018 fd, 0);
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);
1032 close(fd);
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)",
1049 input->name);
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);
1058 if(big_size > size)
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 >
1069 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,
1074 input->name);
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,
1081 MAXSECTALIGN);
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++){
1106 thin = new_thin();
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 */
1122 thin = new_thin();
1123 input->is_thin = TRUE;
1124 thin->name = input->name;
1125 thin->addr = addr;
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)){
1130 swapped = TRUE;
1131 mh = *mhp;
1132 swap_mach_header(&mh, get_host_byte_sex());
1133 mhp = &mh;
1135 else
1136 swapped = FALSE;
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,
1142 swapped);
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 */
1154 thin = new_thin();
1155 input->is_thin = TRUE;
1156 thin->name = input->name;
1157 thin->addr = addr;
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)){
1162 swapped = TRUE;
1163 mh64 = *mhp64;
1164 swap_mach_header_64(&mh64, get_host_byte_sex());
1165 mhp64 = &mh64;
1167 else
1168 swapped = FALSE;
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,
1174 swapped);
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 */
1187 thin = new_thin();
1188 thin->name = input->name;
1189 thin->addr = addr;
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){
1198 if(cputype == 0){
1199 thin->fat_arch.cputype = input->arch_flag.cputype;
1200 thin->fat_arch.cpusubtype = input->arch_flag.cpusubtype;
1202 else
1203 check_arch(input, thin);
1205 else{
1206 if(cputype == 0)
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 */
1212 else{
1214 if(input->arch_flag.name != NULL){
1215 /* create a thin file struct for it */
1216 thin = new_thin();
1217 thin->name = input->name;
1218 thin->addr = addr;
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;
1225 else{
1226 #ifdef LTO_SUPPORT
1227 if(is_llvm_bitcode_from_memory(addr, size, &input->arch_flag,
1228 NULL) != 0){
1229 /* create a thin file struct for it */
1230 thin = new_thin();
1231 thin->name = input->name;
1232 thin->addr = addr;
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;
1239 else
1240 #endif /* LTO_SUPPORT */
1241 fatal("can't figure out the architecture type of: %s",
1242 input->name);
1248 * process_replace_file() checks the replacement file and maps it in for later
1249 * processing.
1251 static
1252 void
1253 process_replace_file(
1254 struct replace *replace)
1256 int fd;
1257 struct stat stat_buf;
1258 uint32_t size;
1259 char *addr;
1260 struct mach_header *mhp, mh;
1261 struct mach_header_64 *mhp64, mh64;
1262 struct load_command *lcp;
1263 cpu_type_t cputype;
1264 cpu_subtype_t cpusubtype;
1265 enum bool swapped;
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)
1280 addr = NULL;
1281 else
1282 addr = mmap(0, size, PROT_READ|PROT_WRITE, MAP_FILE|MAP_PRIVATE,
1283 fd, 0);
1284 if((intptr_t)addr == -1)
1285 system_error("can't map replacement file: %s",
1286 replace->thin_file.name);
1287 close(fd);
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)){
1309 swapped = TRUE;
1310 mh = *mhp;
1311 swap_mach_header(&mh, get_host_byte_sex());
1312 mhp = &mh;
1314 else
1315 swapped = FALSE;
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)){
1334 swapped = TRUE;
1335 mh64 = *mhp64;
1336 swap_mach_header_64(&mh64, get_host_byte_sex());
1337 mhp64 = &mh64;
1339 else
1340 swapped = FALSE;
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) */
1362 else{
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.
1386 static
1387 void
1388 check_archive(
1389 char *name,
1390 char *addr,
1391 uint32_t size,
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.
1407 *cputype = 0;
1408 *cpusubtype = 0;
1409 offset = SARMAG;
1410 if(offset == size)
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);
1421 i = ar_name_size;
1422 ar_name = ar_hdr->ar_name + sizeof(struct ar_hdr);
1424 else{
1425 i = size_ar_name(ar_hdr->ar_name);
1426 ar_name = ar_hdr->ar_name;
1427 ar_name_size = 0;
1429 if(size + ar_name_size - offset > sizeof(uint32_t)){
1430 memcpy(&magic, addr + offset + ar_name_size,
1431 sizeof(uint32_t));
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());
1442 if(*cputype == 0){
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) &
1453 ~CPU_SUBTYPE_MASK);
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());
1463 if(*cputype == 0){
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) &
1474 ~CPU_SUBTYPE_MASK);
1477 else{
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);
1481 #ifdef LTO_SUPPORT
1482 if(is_llvm_bitcode_from_memory(ar_addr, ar_size,
1483 &arch_flag, NULL) != 0){
1484 if(*cputype == 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),
1504 sizeof(short));
1508 * check_extend_format_1() checks the archive header for extened format1.
1510 static
1511 void
1512 check_extend_format_1(
1513 char *name,
1514 struct ar_hdr *ar_hdr,
1515 uint32_t size_left,
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')
1536 endp++;
1537 if(*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),
1541 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
1551 * NULL.
1553 static
1554 struct fat_arch *
1555 get_arm64_fat_arch(
1556 void)
1558 uint32_t i;
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);
1571 return(NULL);
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
1580 * machines).
1582 static
1583 uint32_t
1584 get_align(
1585 struct mach_header *mhp,
1586 struct load_command *load_commands,
1587 uint32_t size,
1588 char *name,
1589 enum bool swapped)
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)
1604 return(12);
1606 * Special case ARM and return 14. As it has 16k pages.
1608 if(mhp->cputype == CPU_TYPE_ARM)
1609 return(14);
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++){
1620 l = *lcp;
1621 if(swapped)
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);
1626 if(l.cmdsize <= 0)
1627 fatal("load command %u size is less than or equal to zero "
1628 "in: %s", i, name);
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;
1635 sg = *sgp;
1636 if(swapped)
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++){
1644 s = *sp;
1645 if(swapped)
1646 swap_section(&s, 1, host_byte_sex);
1647 if(s.align > align)
1648 align = s.align;
1649 sp++;
1651 if(align < cur_align)
1652 cur_align = align;
1654 else{
1655 /* guess the smallest alignment and use that */
1656 align = guess_align(sg.vmaddr);
1657 if(align < cur_align)
1658 cur_align = align;
1661 lcp = (struct load_command *)((char *)lcp + l.cmdsize);
1663 return(cur_align);
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
1672 * machines).
1674 static
1675 uint32_t
1676 get_align_64(
1677 struct mach_header_64 *mhp64,
1678 struct load_command *load_commands,
1679 uint32_t size,
1680 char *name,
1681 enum bool swapped)
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)
1696 return(12);
1698 * Special case ARM64 and return 14. As it has 16k pages.
1700 if(mhp64->cputype == CPU_TYPE_ARM64)
1701 return(14);
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++){
1712 l = *lcp;
1713 if(swapped)
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);
1718 if(l.cmdsize <= 0)
1719 fatal("load command %u size is less than or equal to zero "
1720 "in: %s", i, name);
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;
1727 sg = *sgp;
1728 if(swapped)
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++){
1736 s = *sp;
1737 if(swapped)
1738 swap_section_64(&s, 1, host_byte_sex);
1739 if(s.align > align)
1740 align = s.align;
1741 sp++;
1743 if(align < cur_align)
1744 cur_align = align;
1746 else{
1747 /* guess the smallest alignment and use that */
1748 align = guess_align(sg.vmaddr);
1749 if(align < cur_align)
1750 cur_align = align;
1753 lcp = (struct load_command *)((char *)lcp + l.cmdsize);
1755 return(cur_align);
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.
1763 static
1764 uint32_t
1765 guess_align(
1766 uint32_t vmaddr)
1768 uint32_t align, segalign;
1770 if(vmaddr == 0)
1771 return(MAXSECTALIGN);
1773 align = 0;
1774 segalign = 1;
1775 while((segalign & vmaddr) == 0){
1776 segalign = segalign << 1;
1777 align++;
1780 if(align < 2)
1781 return(2);
1782 if(align > MAXSECTALIGN)
1783 return(MAXSECTALIGN);
1785 return(align);
1789 * print_arch() helps implement -info and -detailed_info by printing the
1790 * architecture name for the cputype and cpusubtype.
1792 static
1793 void
1794 print_arch(
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:
1801 printf("m68k");
1802 break;
1803 case CPU_SUBTYPE_MC68030_ONLY:
1804 printf("m68030");
1805 break;
1806 case CPU_SUBTYPE_MC68040:
1807 printf("m68040");
1808 break;
1809 default:
1810 goto print_arch_unknown;
1812 break;
1813 case CPU_TYPE_POWERPC:
1814 switch(fat_arch->cpusubtype & ~CPU_SUBTYPE_MASK){
1815 case CPU_SUBTYPE_POWERPC_ALL:
1816 printf("ppc");
1817 break;
1818 case CPU_SUBTYPE_POWERPC_601:
1819 printf("ppc601");
1820 break;
1821 case CPU_SUBTYPE_POWERPC_603:
1822 printf("ppc603");
1823 break;
1824 case CPU_SUBTYPE_POWERPC_603e:
1825 printf("ppc603e");
1826 break;
1827 case CPU_SUBTYPE_POWERPC_603ev:
1828 printf("ppc603ev");
1829 break;
1830 case CPU_SUBTYPE_POWERPC_604:
1831 printf("ppc604");
1832 break;
1833 case CPU_SUBTYPE_POWERPC_604e:
1834 printf("ppc604e");
1835 break;
1836 case CPU_SUBTYPE_POWERPC_750:
1837 printf("ppc750");
1838 break;
1839 case CPU_SUBTYPE_POWERPC_7400:
1840 printf("ppc7400");
1841 break;
1842 case CPU_SUBTYPE_POWERPC_7450:
1843 printf("ppc7450");
1844 break;
1845 case CPU_SUBTYPE_POWERPC_970:
1846 printf("ppc970");
1847 break;
1848 default:
1849 goto print_arch_unknown;
1851 break;
1852 case CPU_TYPE_POWERPC64:
1853 switch(fat_arch->cpusubtype & ~CPU_SUBTYPE_MASK){
1854 case CPU_SUBTYPE_POWERPC_ALL:
1855 printf("ppc64");
1856 break;
1857 case CPU_SUBTYPE_POWERPC_970:
1858 printf("ppc970-64");
1859 break;
1860 default:
1861 goto print_arch_unknown;
1863 break;
1864 case CPU_TYPE_VEO:
1865 switch(fat_arch->cpusubtype & ~CPU_SUBTYPE_MASK){
1866 case CPU_SUBTYPE_VEO_1:
1867 printf("veo1");
1868 break;
1869 case CPU_SUBTYPE_VEO_2:
1870 printf("veo2");
1871 break;
1872 case CPU_SUBTYPE_VEO_3:
1873 printf("veo3");
1874 break;
1875 case CPU_SUBTYPE_VEO_4:
1876 printf("veo4");
1877 break;
1878 default:
1879 goto print_arch_unknown;
1881 break;
1882 case CPU_TYPE_MC88000:
1883 switch(fat_arch->cpusubtype & ~CPU_SUBTYPE_MASK){
1884 case CPU_SUBTYPE_MC88000_ALL:
1885 case CPU_SUBTYPE_MC88110:
1886 printf("m88k");
1887 break;
1888 default:
1889 goto print_arch_unknown;
1891 break;
1892 case CPU_TYPE_I386:
1893 switch(fat_arch->cpusubtype & ~CPU_SUBTYPE_MASK){
1894 case CPU_SUBTYPE_I386_ALL:
1895 /* case CPU_SUBTYPE_386: same as above */
1896 printf("i386");
1897 break;
1898 case CPU_SUBTYPE_486:
1899 printf("i486");
1900 break;
1901 case CPU_SUBTYPE_486SX:
1902 printf("i486SX");
1903 break;
1904 case CPU_SUBTYPE_PENT: /* same as 586 */
1905 printf("pentium");
1906 break;
1907 case CPU_SUBTYPE_PENTPRO:
1908 printf("pentpro");
1909 break;
1910 case CPU_SUBTYPE_PENTII_M3:
1911 printf("pentIIm3");
1912 break;
1913 case CPU_SUBTYPE_PENTII_M5:
1914 printf("pentIIm5");
1915 break;
1916 default:
1917 goto print_arch_unknown;
1919 break;
1920 case CPU_TYPE_X86_64:
1921 switch(fat_arch->cpusubtype & ~CPU_SUBTYPE_MASK){
1922 case CPU_SUBTYPE_X86_64_ALL:
1923 printf("x86_64");
1924 break;
1925 case CPU_SUBTYPE_X86_64_H:
1926 printf("x86_64h");
1927 break;
1928 default:
1929 goto print_arch_unknown;
1931 break;
1932 case CPU_TYPE_I860:
1933 switch(fat_arch->cpusubtype & ~CPU_SUBTYPE_MASK){
1934 case CPU_SUBTYPE_I860_ALL:
1935 case CPU_SUBTYPE_I860_860:
1936 printf("i860");
1937 break;
1938 default:
1939 goto print_arch_unknown;
1941 break;
1942 case CPU_TYPE_HPPA:
1943 switch(fat_arch->cpusubtype & ~CPU_SUBTYPE_MASK){
1944 case CPU_SUBTYPE_HPPA_ALL:
1945 case CPU_SUBTYPE_HPPA_7100LC:
1946 printf("hppa");
1947 break;
1948 default:
1949 goto print_arch_unknown;
1951 break;
1952 case CPU_TYPE_SPARC:
1953 switch(fat_arch->cpusubtype & ~CPU_SUBTYPE_MASK){
1954 case CPU_SUBTYPE_SPARC_ALL:
1955 printf("sparc");
1956 break;
1957 default:
1958 goto print_arch_unknown;
1960 break;
1961 case CPU_TYPE_ARM:
1962 switch(fat_arch->cpusubtype){
1963 case CPU_SUBTYPE_ARM_ALL:
1964 printf("arm");
1965 break;
1966 case CPU_SUBTYPE_ARM_V4T:
1967 printf("armv4t");
1968 break;
1969 case CPU_SUBTYPE_ARM_V5TEJ:
1970 printf("armv5");
1971 break;
1972 case CPU_SUBTYPE_ARM_XSCALE:
1973 printf("xscale");
1974 break;
1975 case CPU_SUBTYPE_ARM_V6:
1976 printf("armv6");
1977 break;
1978 case CPU_SUBTYPE_ARM_V6M:
1979 printf("armv6m");
1980 break;
1981 case CPU_SUBTYPE_ARM_V7:
1982 printf("armv7");
1983 break;
1984 case CPU_SUBTYPE_ARM_V7F:
1985 printf("armv7f");
1986 break;
1987 case CPU_SUBTYPE_ARM_V7S:
1988 printf("armv7s");
1989 break;
1990 case CPU_SUBTYPE_ARM_V7K:
1991 printf("armv7k");
1992 break;
1993 case CPU_SUBTYPE_ARM_V7M:
1994 printf("armv7m");
1995 break;
1996 case CPU_SUBTYPE_ARM_V7EM:
1997 printf("armv7em");
1998 break;
1999 default:
2000 goto print_arch_unknown;
2002 break;
2003 case CPU_TYPE_ARM64:
2004 switch(fat_arch->cpusubtype & ~CPU_SUBTYPE_MASK){
2005 case CPU_SUBTYPE_ARM64_ALL:
2006 printf("arm64");
2007 break;
2008 case CPU_SUBTYPE_ARM64_V8:
2009 printf("arm64v8");
2010 break;
2011 default:
2012 goto print_arch_unknown;
2014 break;
2015 case CPU_TYPE_ANY:
2016 switch(fat_arch->cpusubtype & ~CPU_SUBTYPE_MASK){
2017 case CPU_SUBTYPE_MULTIPLE:
2018 printf("any");
2019 break;
2020 case CPU_SUBTYPE_LITTLE_ENDIAN:
2021 printf("little");
2022 break;
2023 case CPU_SUBTYPE_BIG_ENDIAN:
2024 printf("big");
2025 break;
2026 default:
2027 goto print_arch_unknown;
2029 break;
2030 print_arch_unknown:
2031 default:
2032 printf("(cputype (%d) cpusubtype (%d))", fat_arch->cputype,
2033 fat_arch->cpusubtype & ~CPU_SUBTYPE_MASK);
2034 break;
2039 * print_cputype() helps implement -detailed_info by printing the cputype and
2040 * cpusubtype (symbolicly for the one's it knows about).
2042 static
2043 void
2044 print_cputype(
2045 cpu_type_t cputype,
2046 cpu_subtype_t cpusubtype)
2048 switch(cputype){
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");
2054 break;
2055 case CPU_SUBTYPE_MC68030_ONLY:
2056 printf(" cputype CPU_TYPE_MC680x0\n"
2057 " cpusubtype CPU_SUBTYPE_MC68030_ONLY\n");
2058 break;
2059 case CPU_SUBTYPE_MC68040:
2060 printf(" cputype CPU_TYPE_MC680x0\n"
2061 " cpusubtype CPU_SUBTYPE_MC68040\n");
2062 break;
2063 default:
2064 goto print_arch_unknown;
2066 break;
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");
2072 break;
2073 case CPU_SUBTYPE_POWERPC_601:
2074 printf(" cputype CPU_TYPE_POWERPC\n"
2075 " cpusubtype CPU_SUBTYPE_POWERPC_601\n");
2076 break;
2077 case CPU_SUBTYPE_POWERPC_603:
2078 printf(" cputype CPU_TYPE_POWERPC\n"
2079 " cpusubtype CPU_SUBTYPE_POWERPC_603\n");
2080 break;
2081 case CPU_SUBTYPE_POWERPC_603e:
2082 printf(" cputype CPU_TYPE_POWERPC\n"
2083 " cpusubtype CPU_SUBTYPE_POWERPC_603e\n");
2084 break;
2085 case CPU_SUBTYPE_POWERPC_603ev:
2086 printf(" cputype CPU_TYPE_POWERPC\n"
2087 " cpusubtype CPU_SUBTYPE_POWERPC_603ev\n");
2088 break;
2089 case CPU_SUBTYPE_POWERPC_604:
2090 printf(" cputype CPU_TYPE_POWERPC\n"
2091 " cpusubtype CPU_SUBTYPE_POWERPC_604\n");
2092 break;
2093 case CPU_SUBTYPE_POWERPC_604e:
2094 printf(" cputype CPU_TYPE_POWERPC\n"
2095 " cpusubtype CPU_SUBTYPE_POWERPC_604e\n");
2096 break;
2097 case CPU_SUBTYPE_POWERPC_750:
2098 printf(" cputype CPU_TYPE_POWERPC\n"
2099 " cpusubtype CPU_SUBTYPE_POWERPC_750\n");
2100 break;
2101 case CPU_SUBTYPE_POWERPC_7400:
2102 printf(" cputype CPU_TYPE_POWERPC\n"
2103 " cpusubtype CPU_SUBTYPE_POWERPC_7400\n");
2104 break;
2105 case CPU_SUBTYPE_POWERPC_7450:
2106 printf(" cputype CPU_TYPE_POWERPC\n"
2107 " cpusubtype CPU_SUBTYPE_POWERPC_7450\n");
2108 break;
2109 case CPU_SUBTYPE_POWERPC_970:
2110 printf(" cputype CPU_TYPE_POWERPC\n"
2111 " cpusubtype CPU_SUBTYPE_POWERPC_970\n");
2112 break;
2113 default:
2114 goto print_arch_unknown;
2116 break;
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");
2122 break;
2123 case CPU_SUBTYPE_POWERPC_970:
2124 printf(" cputype CPU_TYPE_POWERPC64\n"
2125 " cpusubtype CPU_SUBTYPE_POWERPC_970\n");
2126 break;
2127 default:
2128 goto print_arch_unknown;
2130 break;
2131 case CPU_TYPE_VEO:
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");
2136 break;
2137 case CPU_SUBTYPE_VEO_2:
2138 printf(" cputype CPU_TYPE_VEO\n"
2139 " cpusubtype CPU_SUBTYPE_VEO_2\n");
2140 break;
2141 case CPU_SUBTYPE_VEO_3:
2142 printf(" cputype CPU_TYPE_VEO\n"
2143 " cpusubtype CPU_SUBTYPE_VEO_3\n");
2144 break;
2145 case CPU_SUBTYPE_VEO_4:
2146 printf(" cputype CPU_TYPE_VEO\n"
2147 " cpusubtype CPU_SUBTYPE_VEO_4\n");
2148 break;
2149 default:
2150 goto print_arch_unknown;
2152 break;
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");
2158 break;
2159 case CPU_SUBTYPE_MC88110:
2160 printf(" cputype CPU_TYPE_MC88000\n"
2161 " cpusubtype CPU_SUBTYPE_MC88110\n");
2162 break;
2163 default:
2164 goto print_arch_unknown;
2166 break;
2167 case CPU_TYPE_I386:
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");
2173 break;
2174 case CPU_SUBTYPE_486:
2175 printf(" cputype CPU_TYPE_I386\n"
2176 " cpusubtype CPU_SUBTYPE_486\n");
2177 break;
2178 case CPU_SUBTYPE_486SX:
2179 printf(" cputype CPU_TYPE_I386\n"
2180 " cpusubtype CPU_SUBTYPE_486SX\n");
2181 break;
2182 case CPU_SUBTYPE_PENT: /* same as 586 */
2183 printf(" cputype CPU_TYPE_I386\n"
2184 " cpusubtype CPU_SUBTYPE_PENT\n");
2185 break;
2186 case CPU_SUBTYPE_PENTPRO:
2187 printf(" cputype CPU_TYPE_I386\n"
2188 " cpusubtype CPU_SUBTYPE_PENTPRO\n");
2189 break;
2190 case CPU_SUBTYPE_PENTII_M3:
2191 printf(" cputype CPU_TYPE_I386\n"
2192 " cpusubtype CPU_SUBTYPE_PENTII_M3\n");
2193 break;
2194 case CPU_SUBTYPE_PENTII_M5:
2195 printf(" cputype CPU_TYPE_I386\n"
2196 " cpusubtype CPU_SUBTYPE_PENTII_M5\n");
2197 break;
2198 default:
2199 goto print_arch_unknown;
2201 break;
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");
2207 break;
2208 case CPU_SUBTYPE_X86_64_H:
2209 printf(" cputype CPU_TYPE_X86_64\n"
2210 " cpusubtype CPU_SUBTYPE_X86_64_H\n");
2211 break;
2212 default:
2213 goto print_arch_unknown;
2215 break;
2216 case CPU_TYPE_I860:
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");
2221 break;
2222 case CPU_SUBTYPE_I860_860:
2223 printf(" cputype CPU_TYPE_I860\n"
2224 " cpusubtype CPU_SUBTYPE_I860_860\n");
2225 break;
2226 default:
2227 goto print_arch_unknown;
2229 break;
2230 case CPU_TYPE_HPPA:
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");
2235 break;
2236 case CPU_SUBTYPE_HPPA_7100LC:
2237 printf(" cputype CPU_TYPE_HPPA\n"
2238 " cpusubtype CPU_SUBTYPE_HPPA_7100LC\n");
2239 break;
2240 default:
2241 goto print_arch_unknown;
2243 break;
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");
2249 break;
2250 default:
2251 goto print_arch_unknown;
2253 break;
2254 case CPU_TYPE_ARM:
2255 switch(cpusubtype){
2256 case CPU_SUBTYPE_ARM_V4T:
2257 printf(" cputype CPU_TYPE_ARM\n"
2258 " cpusubtype CPU_SUBTYPE_ARM_V4T\n");
2259 break;
2260 case CPU_SUBTYPE_ARM_V5TEJ:
2261 printf(" cputype CPU_TYPE_ARM\n"
2262 " cpusubtype CPU_SUBTYPE_ARM_V5TEJ\n");
2263 break;
2264 case CPU_SUBTYPE_ARM_XSCALE:
2265 printf(" cputype CPU_TYPE_ARM\n"
2266 " cpusubtype CPU_SUBTYPE_ARM_XSCALE\n");
2267 break;
2268 case CPU_SUBTYPE_ARM_V6:
2269 printf(" cputype CPU_TYPE_ARM\n"
2270 " cpusubtype CPU_SUBTYPE_ARM_V6\n");
2271 break;
2272 case CPU_SUBTYPE_ARM_V6M:
2273 printf(" cputype CPU_TYPE_ARM\n"
2274 " cpusubtype CPU_SUBTYPE_ARM_V6M\n");
2275 break;
2276 case CPU_SUBTYPE_ARM_V7:
2277 printf(" cputype CPU_TYPE_ARM\n"
2278 " cpusubtype CPU_SUBTYPE_ARM_V7\n");
2279 break;
2280 case CPU_SUBTYPE_ARM_V7F:
2281 printf(" cputype CPU_TYPE_ARM\n"
2282 " cpusubtype CPU_SUBTYPE_ARM_V7F\n");
2283 break;
2284 case CPU_SUBTYPE_ARM_V7S:
2285 printf(" cputype CPU_TYPE_ARM\n"
2286 " cpusubtype CPU_SUBTYPE_ARM_V7S\n");
2287 break;
2288 case CPU_SUBTYPE_ARM_V7K:
2289 printf(" cputype CPU_TYPE_ARM\n"
2290 " cpusubtype CPU_SUBTYPE_ARM_V7K\n");
2291 break;
2292 case CPU_SUBTYPE_ARM_V7M:
2293 printf(" cputype CPU_TYPE_ARM\n"
2294 " cpusubtype CPU_SUBTYPE_ARM_V7M\n");
2295 break;
2296 case CPU_SUBTYPE_ARM_V7EM:
2297 printf(" cputype CPU_TYPE_ARM\n"
2298 " cpusubtype CPU_SUBTYPE_ARM_V7EM\n");
2299 break;
2300 case CPU_SUBTYPE_ARM_ALL:
2301 printf(" cputype CPU_TYPE_ARM\n"
2302 " cpusubtype CPU_SUBTYPE_ARM_ALL\n");
2303 break;
2304 default:
2305 goto print_arch_unknown;
2307 break;
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");
2313 break;
2314 case CPU_SUBTYPE_ARM64_V8:
2315 printf(" cputype CPU_TYPE_ARM64\n"
2316 " cpusubtype CPU_SUBTYPE_ARM64_V8\n");
2317 break;
2318 default:
2319 goto print_arch_unknown;
2321 break;
2322 case CPU_TYPE_ANY:
2323 switch(cpusubtype & ~CPU_SUBTYPE_MASK){
2324 case CPU_SUBTYPE_MULTIPLE:
2325 printf(" cputype CPU_TYPE_ANY\n"
2326 " cpusubtype CPU_SUBTYPE_MULTIPLE\n");
2327 break;
2328 case CPU_SUBTYPE_LITTLE_ENDIAN:
2329 printf(" cputype CPU_TYPE_ANY\n"
2330 " cpusubtype CPU_SUBTYPE_LITTLE_ENDIAN\n");
2331 break;
2332 case CPU_SUBTYPE_BIG_ENDIAN:
2333 printf(" cputype CPU_TYPE_ANY\n"
2334 " cpusubtype CPU_SUBTYPE_BIG_ENDIAN\n");
2335 break;
2336 default:
2337 goto print_arch_unknown;
2339 break;
2340 print_arch_unknown:
2341 default:
2342 printf(" cputype (%d)\n"
2343 " cpusubtype cpusubtype (%d)\n", cputype,
2344 cpusubtype & ~CPU_SUBTYPE_MASK);
2345 break;
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").
2353 static
2355 size_ar_name(
2356 char *ar_name)
2358 uint32_t j;
2359 struct ar_hdr ar_hdr;
2361 for(j = 0; j < sizeof(ar_hdr.ar_name); j++){
2362 if(ar_name[j] == ' ')
2363 break;
2365 return(j);
2369 * Create a new input file struct, clear it and return it.
2371 static
2372 struct input_file *
2373 new_input(void)
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;
2380 ninput_files++;
2381 memset(input, '\0', sizeof(struct input_file));
2382 return(input);
2386 * Create a new thin file struct, clear it and return it.
2388 static
2389 struct thin_file *
2390 new_thin(void)
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;
2397 nthin_files++;
2398 memset(thin, '\0', sizeof(struct thin_file));
2399 return(thin);
2403 * Create a new arch_flag struct on the specified list, clear it and return it.
2405 static
2406 struct arch_flag *
2407 new_arch_flag(
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));
2418 return(arch_flag);
2422 * Create a new replace struct, clear it and return it.
2424 static
2425 struct replace *
2426 new_replace(void)
2428 struct replace *replace;
2430 replaces = reallocate(replaces,
2431 (nreplaces + 1) * sizeof(struct replace));
2432 replace = replaces + nreplaces;
2433 nreplaces++;
2434 memset(replace, '\0', sizeof(struct replace));
2435 return(replace);
2439 * Create a new segalign struct, clear it and return it.
2441 static
2442 struct segalign *
2443 new_segalign(void)
2445 struct segalign *segalign;
2447 segaligns = reallocate(segaligns,
2448 (nsegaligns + 1) * sizeof(struct segalign));
2449 segalign = segaligns + nsegaligns;
2450 nsegaligns++;
2451 memset(segalign, '\0', sizeof(struct segalign));
2452 return(segalign);
2456 * Function for qsort for comparing thin file's alignment
2458 static
2460 cmp_qsort(
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.
2470 static
2471 uint32_t
2472 rnd(
2473 uint32_t v,
2474 uint32_t r)
2476 r--;
2477 v += r;
2478 v &= ~(int32_t)r;
2479 return(v);
2483 * ispoweroftwo() returns TRUE or FALSE depending if x is a power of two.
2485 static
2486 enum
2487 bool
2488 ispoweroftwo(
2489 uint32_t x)
2491 if(x == 0)
2492 return(TRUE);
2493 while((x & 0x1) != 0x1){
2494 x >>= 1;
2496 if((x & ~0x1) != 0)
2497 return(FALSE);
2498 else
2499 return(TRUE);
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.
2507 static
2508 void
2509 check_arch(
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.
2527 static
2528 struct thin_file *
2529 new_blank_dylib(
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;
2538 file = new_thin();
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;
2547 onebit = 1;
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);
2564 else{
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);
2573 return(file);
2577 * Print the current usage line and exit (by calling fatal).
2579 static
2580 void
2581 usage(void)
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);