cctools (lib), libtool, lipo, nm, otool - Add build support for LTO
[darwin-xtools.git] / cctools / misc / lipo.c
blob086882e1bf9a44985306067019624e8d59a61448
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 struct fat_arch_64 *fat_arches64;
83 enum bool is_thin;
85 static struct input_file *input_files = NULL;
86 static uint32_t ninput_files = 0;
88 /* Thin files from the input files to operate on */
89 struct thin_file {
90 char *name;
91 char *addr;
92 cpu_type_t cputype;
93 cpu_subtype_t cpusubtype;
94 uint64_t offset;
95 uint64_t size;
96 uint32_t align;
97 enum bool from_fat;
98 enum bool extract;
99 enum bool remove;
100 enum bool replace;
102 static struct thin_file *thin_files = NULL;
103 static uint32_t nthin_files = 0;
105 /* The specified output file */
106 static char *output_file = NULL;
107 static uint32_t output_filemode = 0;
108 #ifndef __OPENSTEP__
109 static struct utimbuf output_timep = { 0 };
110 #else
111 static time_t output_timep[2] = { 0 };
112 #endif
113 static enum bool archives_in_input = FALSE;
115 /* flags set from command line arguments to specify the operation */
116 static enum bool create_flag = FALSE;
117 static enum bool info_flag = FALSE;
118 static enum bool detailed_info_flag = FALSE;
120 static enum bool thin_flag = FALSE;
121 static struct arch_flag thin_arch_flag = { 0 };
123 static enum bool remove_flag = FALSE;
124 static struct arch_flag *remove_arch_flags = NULL;
125 static uint32_t nremove_arch_flags = 0;
127 static enum bool extract_flag = FALSE;
128 static struct arch_flag *extract_arch_flags = NULL;
129 static uint32_t nextract_arch_flags = 0;
130 static enum bool extract_family_flag = FALSE;
132 static enum bool replace_flag = FALSE;
133 struct replace {
134 struct arch_flag arch_flag;
135 struct thin_file thin_file;
137 static struct replace *replaces = NULL;
138 static uint32_t nreplaces = 0;
140 struct segalign {
141 struct arch_flag arch_flag;
142 uint32_t align;
144 static struct segalign *segaligns = NULL;
145 static uint32_t nsegaligns = 0;
147 static enum bool arch_blank_flag = FALSE;
149 static struct fat_header fat_header = { 0 };
151 static struct thin_file *arm64_arch = NULL;
152 static struct thin_file *get_arm64_arch(
153 void);
155 static struct thin_file *x86_64h_arch = NULL;
156 static struct thin_file *get_x86_64h_arch(
157 void);
159 static enum bool verify_flag = FALSE;
160 static struct arch_flag *verify_archs = NULL;
161 static uint32_t nverify_archs = 0;
163 static enum bool fat64_flag = FALSE;
165 static void create_fat(
166 void);
167 static void process_input_file(
168 struct input_file *input);
169 static void process_replace_file(
170 struct replace *replace);
171 static void check_archive(
172 char *name,
173 char *addr,
174 uint64_t size,
175 cpu_type_t *cputype,
176 cpu_subtype_t *cpusubtype);
177 static void check_extend_format_1(
178 char *name,
179 struct ar_hdr *ar_hdr,
180 uint64_t size_left,
181 uint32_t *member_name_size);
182 static uint32_t get_align(
183 struct mach_header *mhp,
184 struct load_command *load_commands,
185 uint64_t size,
186 char *name,
187 enum bool swapped);
188 static uint32_t get_align_64(
189 struct mach_header_64 *mhp64,
190 struct load_command *load_commands,
191 uint64_t size,
192 char *name,
193 enum bool swapped);
194 static uint32_t guess_align(
195 uint64_t vmaddr);
196 static void print_arch(
197 cpu_type_t cputype,
198 cpu_subtype_t cpusubtype);
199 static void print_cputype(
200 cpu_type_t cputype,
201 cpu_subtype_t cpusubtype);
202 static int size_ar_name(
203 char *ar_name);
204 static struct input_file *new_input(
205 void);
206 static struct thin_file *new_thin(
207 void);
208 static struct arch_flag *new_arch_flag(
209 struct arch_flag **arch_flags,
210 uint32_t *narch_flags);
211 static struct replace *new_replace(
212 void);
213 static struct segalign *new_segalign(
214 void);
215 static int cmp_qsort(
216 const struct thin_file *thin1,
217 const struct thin_file *thin2);
218 static uint64_t rnd(
219 uint64_t v,
220 uint64_t r);
221 static enum bool ispoweroftwo(
222 uint32_t x);
223 static void check_arch(
224 struct input_file *input,
225 struct thin_file *thin);
226 static void usage(
227 void);
228 static struct thin_file *new_blank_dylib(
229 struct arch_flag *arch);
231 /* apple_version is created by the libstuff/Makefile */
232 extern char apple_version[];
233 char *version = apple_version;
234 /* likewise lto_suport */
235 extern char lto_support[];
238 main(
239 int argc,
240 char *argv[],
241 char *envp[])
243 int fd, a;
244 uint32_t i, j, k, value;
245 char *p, *endp;
246 struct input_file *input;
247 struct arch_flag *arch_flag;
248 struct replace *replace;
249 struct segalign *segalign;
250 const struct arch_flag *arch_flags;
251 enum bool found;
252 struct arch_flag blank_arch;
253 uint64_t nbytes_to_write, nbytes_written;
255 input = NULL;
257 * Process the command line arguments.
259 progname = argv[0];
260 for(a = 1; a < argc; a++){
261 if(argv[a][0] == '-'){
262 p = &(argv[a][1]);
263 switch(*p){
264 case 'a':
265 if(strcmp(p, "arch") == 0 || strcmp(p, "a") == 0){
266 if(a + 2 >= argc){
267 error("missing argument(s) to %s option", argv[a]);
268 usage();
270 input = new_input();
271 if(get_arch_from_flag(argv[a+1],
272 &(input->arch_flag)) == 0){
273 error("unknown architecture specification flag: %s "
274 "in specifying input file %s %s %s", argv[a+1],
275 argv[a], argv[a+1], argv[a+2]);
276 arch_usage();
277 usage();
279 input->name = argv[a+2];
280 a += 2;
282 else if(strcmp(p, "arch_blank") == 0){
283 arch_blank_flag = TRUE;
284 if(a + 1 >= argc){
285 error("missing argument(s) to %s option", argv[a]);
286 usage();
288 if(get_arch_from_flag(argv[a+1], &blank_arch) == 0){
289 error("unknown architecture specification flag: %s "
290 "in specifying input file %s %s", argv[a+1],
291 argv[a], argv[a+1]);
292 arch_usage();
293 usage();
295 new_blank_dylib(&blank_arch);
296 a += 1;
298 else
299 goto unknown_flag;
300 break;
301 case 'c':
302 if(strcmp(p, "create") == 0 || strcmp(p, "c") == 0){
303 create_flag = TRUE;
305 else
306 goto unknown_flag;
307 break;
308 case 'd':
309 if(strcmp(p, "detailed_info") == 0 || strcmp(p, "d") == 0){
310 detailed_info_flag = TRUE;
312 else
313 goto unknown_flag;
314 break;
315 case 'e':
316 if(strcmp(p, "extract") == 0 ||
317 strcmp(p, "extract_family") == 0 ||
318 strcmp(p, "e") == 0){
319 extract_flag = TRUE;
320 if(strcmp(p, "extract_family") == 0)
321 extract_family_flag = TRUE;
322 if(a + 1 >= argc){
323 error("missing argument to %s option", argv[a]);
324 usage();
326 arch_flag = new_arch_flag(&extract_arch_flags,
327 &nextract_arch_flags);
328 if(get_arch_from_flag(argv[a+1], arch_flag) == 0){
329 error("unknown architecture specification flag: "
330 "%s in specifying extract operation: %s %s",
331 argv[a+1], argv[a], argv[a+1]);
332 arch_usage();
333 usage();
335 a++;
337 else
338 goto unknown_flag;
339 break;
340 case 'i':
341 if(strcmp(p, "info") == 0 || strcmp(p, "i") == 0){
342 info_flag = TRUE;
344 else
345 goto unknown_flag;
346 break;
347 case 'o':
348 if(strcmp(p, "output") == 0 || strcmp(p, "o") == 0){
349 if(a + 1 >= argc){
350 error("missing argument to %s option", argv[a]);
351 usage();
353 if(output_file != NULL)
354 fatal("more than one %s option specified", argv[a]);
355 output_file = argv[a + 1];
356 a++;
358 else
359 goto unknown_flag;
360 break;
361 case 'r':
362 if(strcmp(p, "remove") == 0 || strcmp(p, "rem") == 0){
363 remove_flag = TRUE;
364 if(a + 1 >= argc){
365 error("missing argument to %s option", argv[a]);
366 usage();
368 arch_flag = new_arch_flag(&remove_arch_flags,
369 &nremove_arch_flags);
370 if(get_arch_from_flag(argv[a+1], arch_flag) == 0){
371 error("unknown architecture specification flag: "
372 "%s in specifying remove operation: %s %s",
373 argv[a+1], argv[a], argv[a+1]);
374 arch_usage();
375 usage();
377 a++;
379 else if(strcmp(p, "replace") == 0 || strcmp(p, "rep") == 0){
380 replace_flag = TRUE;
381 if(a + 2 >= argc){
382 error("missing argument(s) to %s option", argv[a]);
383 usage();
385 replace = new_replace();
386 if(get_arch_from_flag(argv[a+1],
387 &(replace->arch_flag)) == 0){
388 error("unknown architecture specification flag: "
389 "%s in specifying replace operation: %s %s %s",
390 argv[a+1], argv[a], argv[a+1], argv[a+2]);
391 arch_usage();
392 usage();
394 replace->thin_file.name = argv[a+2];
395 a += 2;
397 else
398 goto unknown_flag;
399 break;
400 case 's':
401 if(strcmp(p, "segalign") == 0 || strcmp(p, "s") == 0){
402 if(a + 2 >= argc){
403 error("missing argument(s) to %s option", argv[a]);
404 usage();
406 segalign = new_segalign();
407 if(get_arch_from_flag(argv[a+1],
408 &(segalign->arch_flag)) == 0){
409 error("unknown architecture specification flag: "
410 "%s in specifying segment alignment: %s %s %s",
411 argv[a+1], argv[a], argv[a+1], argv[a+2]);
412 arch_usage();
413 usage();
415 value = strtoul(argv[a+2], &endp, 16);
416 if(*endp != '\0')
417 fatal("argument for -segalign <arch_type> %s not a "
418 "proper hexadecimal number", argv[a+2]);
419 if(!ispoweroftwo(value) || value == 0)
420 fatal("argument to -segalign <arch_type> %x (hex) "
421 "must be a non-zero power of two", value);
422 if(value > (1 << MAXSECTALIGN))
423 fatal("argument to -segalign <arch_type> %x (hex) "
424 "must equal to or less than %x (hex)",
425 value, (unsigned int)(1 << MAXSECTALIGN));
426 segalign->align = 0;
427 while((value & 0x1) != 1){
428 value >>= 1;
429 segalign->align++;
431 a += 2;
433 else
434 goto unknown_flag;
435 break;
436 case 't':
437 if(strcmp(p, "thin") == 0 || strcmp(p, "t") == 0){
438 if(thin_flag == TRUE)
439 fatal("more than one %s option specified", argv[a]);
440 thin_flag = TRUE;
441 if(a + 1 >= argc){
442 error("missing argument to %s option", argv[a]);
443 usage();
445 if(get_arch_from_flag(argv[a+1], &thin_arch_flag) == 0){
446 error("unknown architecture specification flag: "
447 "%s in specifying thin operation: %s %s",
448 argv[a+1], argv[a], argv[a+1]);
449 arch_usage();
450 usage();
452 a++;
454 else
455 goto unknown_flag;
456 break;
457 case 'v':
458 if(strcmp(p, "verify_arch") == 0){
459 verify_flag = TRUE;
460 if(a + 1 >= argc){
461 error("missing argument(s) to %s option", argv[a]);
462 usage();
464 a++;
465 nverify_archs = argc - a;
466 verify_archs = (struct arch_flag *)allocate(
467 sizeof(struct arch_flag) * nverify_archs);
468 for(i = 0; a < argc; a++, i++){
469 if(get_arch_from_flag(argv[a],
470 verify_archs + i) == 0){
471 error("unknown architecture specification "
472 "flag: %s in specifying -verify_arch "
473 "operation", argv[a]);
474 arch_usage();
475 usage();
479 else
480 goto unknown_flag;
481 break;
482 case 'f':
483 if(strcmp(p, "fat64") == 0)
484 fat64_flag = TRUE;
485 else
486 goto unknown_flag;
487 break;
488 default:
489 unknown_flag:
490 fatal("unknown flag: %s", argv[a]);
493 else{
494 input = new_input();
495 input->name = argv[a];
500 * Check to see the specified arguments are valid.
502 if(info_flag == FALSE && detailed_info_flag == FALSE &&
503 create_flag == FALSE && thin_flag == FALSE &&
504 extract_flag == FALSE && remove_flag == FALSE &&
505 replace_flag == FALSE && verify_flag == FALSE){
506 error("one of -create, -thin <arch_type>, -extract <arch_type>, "
507 "-remove <arch_type>, -replace <arch_type> <file_name>, "
508 "-verify_arch <arch_type> ... , "
509 "-info or -detailed_info must be specified");
510 usage();
512 if((create_flag == TRUE || thin_flag == TRUE || extract_flag == TRUE ||
513 remove_flag == TRUE || replace_flag == TRUE) &&
514 output_file == NULL){
515 error("no output file specified");
516 usage();
518 if(ninput_files == 0){
519 error("no input files specified");
520 usage();
522 if(verify_flag == TRUE && ninput_files != 1){
523 error("only one input file allowed with -verify_arch");
524 usage();
526 if(create_flag + thin_flag + extract_flag + remove_flag + replace_flag +
527 info_flag + detailed_info_flag + verify_flag > 1){
528 error("only one of -create, -thin <arch_type>, -extract <arch_type>"
529 ", -remove <arch_type>, -replace <arch_type> <file_name>, "
530 "-verify_arch <arch_type> ..., "
531 "-info or -detailed_info can be specified");
532 usage();
534 if(arch_blank_flag == TRUE && create_flag == FALSE){
535 error("-arch_blank may only be used with -create");
536 usage();
540 * Determine the types of the input files.
542 for(i = 0; i < ninput_files; i++)
543 process_input_file(input_files + i);
546 * Do the specified operation.
549 if(create_flag){
550 /* check to make sure no two files have the same architectures */
551 for(i = 0; i < nthin_files; i++)
552 for(j = i + 1; j < nthin_files; j++)
553 if(thin_files[i].cputype ==
554 thin_files[j].cputype &&
555 (thin_files[i].cpusubtype & ~CPU_SUBTYPE_MASK)==
556 (thin_files[j].cpusubtype & ~CPU_SUBTYPE_MASK)){
557 arch_flags = get_arch_flags();
558 for(k = 0; arch_flags[k].name != NULL; k++){
559 if(arch_flags[k].cputype ==
560 thin_files[j].cputype &&
561 (arch_flags[k].cpusubtype &
562 ~CPU_SUBTYPE_MASK) ==
563 (thin_files[j].cpusubtype &
564 ~CPU_SUBTYPE_MASK))
565 fatal("%s and %s have the same architectures (%s) "
566 "and can't be in the same fat output file",
567 thin_files[i].name, thin_files[j].name,
568 arch_flags[k].name);
570 fatal("%s and %s have the same architectures (cputype "
571 "(%d) and cpusubtype (%d)) and can't be in the "
572 "same fat output file", thin_files[i].name,
573 thin_files[j].name,thin_files[i].cputype,
574 thin_files[i].cpusubtype &
575 ~CPU_SUBTYPE_MASK);
577 create_fat();
580 if(thin_flag){
581 if(ninput_files != 1)
582 fatal("only one input file can be specified with the -thin "
583 "option");
584 if(input_files[0].fat_header == NULL)
585 fatal("input file (%s) must be a fat file when the -thin "
586 "option is specified", input_files[0].name);
587 for(i = 0; i < nthin_files; i++){
588 if(thin_files[i].cputype == thin_arch_flag.cputype &&
589 (thin_files[i].cpusubtype & ~CPU_SUBTYPE_MASK) ==
590 (thin_arch_flag.cpusubtype & ~CPU_SUBTYPE_MASK)){
591 (void)unlink(output_file);
592 if((fd = open(output_file, O_WRONLY | O_CREAT | O_TRUNC,
593 output_filemode)) == -1)
594 system_fatal("can't create output file: %s",
595 output_file);
597 nbytes_written = 0;
599 #define MAX_WRITE 0x10000000
600 if(thin_files[i].size - nbytes_written > MAX_WRITE)
601 nbytes_to_write = MAX_WRITE;
602 else
603 nbytes_to_write = thin_files[i].size -
604 nbytes_written;
605 if(write(fd, thin_files[i].addr + nbytes_written,
606 nbytes_to_write) != nbytes_to_write)
607 system_fatal("can't write thin file to output "
608 "file: %s", output_file);
609 nbytes_written += nbytes_to_write;
610 }while(nbytes_written != thin_files[i].size);
611 if(close(fd) == -1)
612 system_fatal("can't close output file: %s",output_file);
613 if(utime(output_file,
614 #ifndef __OPENSTEP__
615 &output_timep) == -1)
616 #else
617 output_timep) == -1)
618 #endif
619 system_fatal("can't set the modify times for "
620 "output file: %s", output_file);
621 break;
624 if(i == nthin_files)
625 fatal("fat input file (%s) does not contain the specified "
626 "architecture (%s) to thin it to", input->name,
627 thin_arch_flag.name);
630 if(extract_flag){
631 if(ninput_files != 1)
632 fatal("only one input file can be specified with the -extract "
633 "option");
634 if(input_files[0].fat_header == NULL)
635 fatal("input file (%s) must be a fat file when the -extract "
636 "option is specified", input_files[0].name);
637 if(input_files[0].fat_header->magic == FAT_MAGIC_64)
638 fat64_flag = TRUE;
640 for(i = 0; i < nextract_arch_flags; i++){
641 for(j = i + 1; j < nextract_arch_flags; j++){
642 if(extract_arch_flags[i].cputype ==
643 extract_arch_flags[j].cputype &&
644 (extract_arch_flags[i].cpusubtype & ~CPU_SUBTYPE_MASK) ==
645 (extract_arch_flags[j].cpusubtype & ~CPU_SUBTYPE_MASK))
646 fatal("-extract %s specified multiple times",
647 extract_arch_flags[i].name);
650 /* mark those thin files for extraction */
651 for(i = 0; i < nextract_arch_flags; i++){
652 found = FALSE;
653 for(j = 0; j < nthin_files; j++){
654 if(extract_arch_flags[i].cputype ==
655 thin_files[j].cputype &&
656 ((extract_arch_flags[i].cpusubtype &
657 ~CPU_SUBTYPE_MASK)==
658 (thin_files[j].cpusubtype &
659 ~CPU_SUBTYPE_MASK) ||
660 extract_family_flag == TRUE)){
661 thin_files[j].extract = TRUE;
662 found = TRUE;
665 if(found == FALSE)
666 fatal("-extract %s specified but fat file: %s does not "
667 "contain that architecture",
668 extract_arch_flags[i].name, input_files[0].name);
670 /* remove those thin files not marked for extraction */
671 for(i = 0; i < nthin_files; ){
672 if(thin_files[i].extract == FALSE){
673 for(j = i; j < nthin_files - 1; j++)
674 thin_files[j] = thin_files[j + 1];
675 nthin_files--;
677 else
678 i++;
680 create_fat();
683 if(remove_flag){
684 if(ninput_files != 1)
685 fatal("only one input file can be specified with the -remove "
686 "option");
687 if(input_files[0].fat_header == NULL)
688 fatal("input file (%s) must be a fat file when the -remove "
689 "option is specified", input_files[0].name);
690 if(input_files[0].fat_header->magic == FAT_MAGIC_64)
691 fat64_flag = TRUE;
692 for(i = 0; i < nremove_arch_flags; i++){
693 for(j = i + 1; j < nremove_arch_flags; j++){
694 if(remove_arch_flags[i].cputype ==
695 remove_arch_flags[j].cputype &&
696 (remove_arch_flags[i].cpusubtype & ~CPU_SUBTYPE_MASK) ==
697 (remove_arch_flags[j].cpusubtype & ~CPU_SUBTYPE_MASK))
698 fatal("-remove %s specified multiple times",
699 remove_arch_flags[i].name);
702 /* mark those thin files for removal */
703 for(i = 0; i < nremove_arch_flags; i++){
704 for(j = 0; j < nthin_files; j++){
705 if(remove_arch_flags[i].cputype ==
706 thin_files[j].cputype &&
707 (remove_arch_flags[i].cpusubtype &
708 ~CPU_SUBTYPE_MASK) ==
709 (thin_files[j].cpusubtype &
710 ~CPU_SUBTYPE_MASK)){
711 thin_files[j].remove = TRUE;
712 break;
715 if(j == nthin_files)
716 fatal("-remove %s specified but fat file: %s does not "
717 "contain that architecture",
718 remove_arch_flags[i].name, input_files[0].name);
720 /* remove those thin files marked for removal */
721 for(i = 0; i < nthin_files; ){
722 if(thin_files[i].remove == TRUE){
723 for(j = i; j < nthin_files; j++)
724 thin_files[j] = thin_files[j + 1];
725 nthin_files--;
727 else
728 i++;
730 if(nthin_files == 0)
731 fatal("-remove's specified would result in an empty fat file");
732 create_fat();
735 if(replace_flag){
736 if(ninput_files != 1)
737 fatal("only one input file can be specified with the -replace "
738 "option");
739 if(input_files[0].fat_header == NULL)
740 fatal("input file (%s) must be a fat file when the -replace "
741 "option is specified", input_files[0].name);
742 if(input_files[0].fat_header->magic == FAT_MAGIC_64)
743 fat64_flag = TRUE;
744 for(i = 0; i < nreplaces; i++){
745 for(j = i + 1; j < nreplaces; j++){
746 if(replaces[i].arch_flag.cputype ==
747 replaces[j].arch_flag.cputype &&
748 (replaces[i].arch_flag.cpusubtype & ~CPU_SUBTYPE_MASK) ==
749 (replaces[j].arch_flag.cpusubtype & ~CPU_SUBTYPE_MASK))
750 fatal("-replace %s <file_name> specified multiple times",
751 replaces[j].arch_flag.name);
754 for(i = 0; i < nreplaces; i++){
755 process_replace_file(replaces + i);
756 for(j = 0; j < nthin_files; j++){
757 if(replaces[i].arch_flag.cputype ==
758 thin_files[j].cputype &&
759 (replaces[i].arch_flag.cpusubtype & ~CPU_SUBTYPE_MASK) ==
760 (thin_files[j].cpusubtype & ~CPU_SUBTYPE_MASK)){
761 thin_files[j] = replaces[i].thin_file;
762 break;
765 if(j == nthin_files)
766 fatal("-replace %s <file_name> specified but fat file: %s "
767 "does not contain that architecture",
768 replaces[i].arch_flag.name, input_files[0].name);
770 create_fat();
773 if(info_flag){
774 for(i = 0; i < ninput_files; i++){
775 if(input_files[i].fat_header != NULL){
776 printf("Architectures in the fat file: %s are: ",
777 input_files[i].name);
778 if(input_files[i].fat_arches != NULL){
779 for(j = 0; j < input_files[i].fat_header->nfat_arch;
780 j++){
781 print_arch(input_files[i].fat_arches[j].cputype,
782 input_files[i].fat_arches[j].cpusubtype);
783 printf(" ");
786 else{
787 for(j = 0; j < input_files[i].fat_header->nfat_arch;
788 j++){
789 print_arch(input_files[i].fat_arches64[j].cputype,
790 input_files[i].fat_arches64[j].cpusubtype);
791 printf(" ");
794 printf("\n");
796 else{
797 if(input_files[i].is_thin == FALSE)
798 printf("input file %s is not a fat file\n",
799 input_files[i].name);
802 for(i = 0; i < nthin_files; i++){
803 if(thin_files[i].from_fat == TRUE)
804 continue;
805 printf("Non-fat file: %s is architecture: %s\n",
806 thin_files[i].name,
807 get_arch_name_from_types(thin_files[i].cputype,
808 thin_files[i].cpusubtype & ~CPU_SUBTYPE_MASK));
812 if(detailed_info_flag){
813 for(i = 0; i < ninput_files; i++){
814 if(input_files[i].fat_header != NULL){
815 printf("Fat header in: %s\n", input_files[i].name);
816 printf("fat_magic 0x%x\n",
817 (unsigned int)(input_files[i].fat_header->magic));
818 printf("nfat_arch %u\n",
819 input_files[i].fat_header->nfat_arch);
820 for(j = 0; j < input_files[i].fat_header->nfat_arch; j++){
821 printf("architecture ");
822 if(input_files[i].fat_arches != NULL){
823 print_arch(input_files[i].fat_arches[j].cputype,
824 input_files[i].fat_arches[j].cpusubtype);
825 printf("\n");
826 print_cputype(input_files[i].fat_arches[j].cputype,
827 input_files[i].fat_arches[j].cpusubtype &
828 ~CPU_SUBTYPE_MASK);
829 printf(" offset %u\n",
830 input_files[i].fat_arches[j].offset);
831 printf(" size %u\n",
832 input_files[i].fat_arches[j].size);
833 printf(" align 2^%u (%d)\n",
834 input_files[i].fat_arches[j].align,
835 1 << input_files[i].fat_arches[j].align);
837 else{
838 print_arch(input_files[i].fat_arches64[j].cputype,
839 input_files[i].fat_arches64[j].cpusubtype);
840 printf("\n");
841 print_cputype(
842 input_files[i].fat_arches64[j].cputype,
843 input_files[i].fat_arches64[j].cpusubtype &
844 ~CPU_SUBTYPE_MASK);
845 printf(" offset %llu\n",
846 input_files[i].fat_arches64[j].offset);
847 printf(" size %llu\n",
848 input_files[i].fat_arches64[j].size);
849 printf(" align 2^%u (%d)\n",
850 input_files[i].fat_arches64[j].align,
851 1 << input_files[i].fat_arches64[j].align);
855 else{
856 printf("input file %s is not a fat file\n",
857 input_files[i].name);
860 for(i = 0; i < nthin_files; i++){
861 if(thin_files[i].from_fat == TRUE)
862 continue;
863 printf("Non-fat file: %s is architecture: %s\n",
864 thin_files[i].name,
865 get_arch_name_from_types(thin_files[i].cputype,
866 thin_files[i].cpusubtype & ~CPU_SUBTYPE_MASK));
870 if(verify_flag == TRUE){
871 for(i = 0; i < nverify_archs; i++){
872 found = FALSE;
873 for(j = 0; j < nthin_files; j++){
874 if(verify_archs[i].cputype ==
875 thin_files[j].cputype &&
876 (verify_archs[i].cpusubtype & ~CPU_SUBTYPE_MASK) ==
877 (thin_files[j].cpusubtype & ~CPU_SUBTYPE_MASK)){
878 found = TRUE;
879 break;
882 if(found == FALSE)
883 exit(1);
887 return(0);
891 * create_fat() creates a fat output file from the thin files.
893 static
894 void
895 create_fat(void)
897 uint32_t i, j;
898 uint64_t offset;
899 char *rename_file;
900 int fd;
901 struct fat_arch fat_arch;
902 struct fat_arch_64 fat_arch64;
903 uint64_t nbytes_to_write, nbytes_written;
905 /* fold in specified segment alignments */
906 for(i = 0; i < nsegaligns; i++){
907 for(j = i + 1; j < nsegaligns; j++){
908 if(segaligns[i].arch_flag.cputype ==
909 segaligns[j].arch_flag.cputype &&
910 (segaligns[i].arch_flag.cpusubtype & ~CPU_SUBTYPE_MASK) ==
911 (segaligns[j].arch_flag.cpusubtype & ~CPU_SUBTYPE_MASK))
912 fatal("-segalign %s <value> specified multiple times",
913 segaligns[j].arch_flag.name);
916 for(i = 0; i < nsegaligns; i++){
917 for(j = 0; j < nthin_files; j++){
918 if(segaligns[i].arch_flag.cputype ==
919 thin_files[j].cputype &&
920 (segaligns[i].arch_flag.cpusubtype & ~CPU_SUBTYPE_MASK) ==
921 (thin_files[j].cpusubtype & ~CPU_SUBTYPE_MASK)){
923 Since this program has to guess at alignments and guesses high when unsure this
924 check shouldn't be used so the the correct alignment can be specified by the
925 the user.
926 if(thin_files[j].align > segaligns[i].align)
927 fatal("specified segment alignment: %d for "
928 "architecture %s is less than the alignment: %d "
929 "required from the input file",
930 1 << segaligns[i].align,
931 segaligns[i].arch_flag.name,
932 1 << thin_files[j].align);
934 thin_files[j].align = segaligns[i].align;
935 break;
938 if(j == nthin_files)
939 fatal("-segalign %s <value> specified but resulting fat "
940 "file does not contain that architecture",
941 segaligns[i].arch_flag.name);
944 /* sort the files by alignment to save space in the output file */
945 qsort(thin_files, nthin_files, sizeof(struct thin_file),
946 (int (*)(const void *, const void *))cmp_qsort);
948 /* We will order the ARM64 slice last. */
949 arm64_arch = get_arm64_arch();
951 /* We will order the x86_64h slice last too. */
952 x86_64h_arch = get_x86_64h_arch();
954 /* Fill in the fat header and the fat_arch's offsets. */
955 if(fat64_flag == TRUE)
956 fat_header.magic = FAT_MAGIC_64;
957 else
958 fat_header.magic = FAT_MAGIC;
959 fat_header.nfat_arch = nthin_files;
960 offset = sizeof(struct fat_header);
961 if(fat64_flag == TRUE)
962 offset += nthin_files * sizeof(struct fat_arch_64);
963 else
964 offset += nthin_files * sizeof(struct fat_arch);
965 for(i = 0; i < nthin_files; i++){
966 offset = rnd(offset, 1 << thin_files[i].align);
967 if(fat64_flag == FALSE && offset > UINT32_MAX)
968 fatal("fat file too large to be created because the offset "
969 "field in struct fat_arch is only 32-bits and the offset "
970 "(%llu) for %s for architecture %s exceeds that",
971 offset, thin_files[i].name,
972 get_arch_name_from_types(thin_files[i].cputype,
973 thin_files[i].cpusubtype & ~CPU_SUBTYPE_MASK));
974 thin_files[i].offset = offset;
975 offset += thin_files[i].size;
978 rename_file = makestr(output_file, ".lipo", NULL);
979 if((fd = open(rename_file, O_WRONLY | O_CREAT | O_TRUNC,
980 output_filemode)) == -1)
981 system_fatal("can't create temporary output file: %s", rename_file);
984 * If this is an extract_family_flag operation and the is just one
985 * thin file on the list don't create a fat file.
987 if(extract_family_flag != TRUE || nthin_files != 1){
988 #ifdef __LITTLE_ENDIAN__
989 swap_fat_header(&fat_header, BIG_ENDIAN_BYTE_SEX);
990 #endif /* __LITTLE_ENDIAN__ */
991 if(write(fd, &fat_header, sizeof(struct fat_header)) !=
992 sizeof(struct fat_header))
993 system_fatal("can't write fat header to output file: %s",
994 rename_file);
995 #ifdef __LITTLE_ENDIAN__
996 swap_fat_header(&fat_header, LITTLE_ENDIAN_BYTE_SEX);
997 #endif /* __LITTLE_ENDIAN__ */
998 for(i = 0; i < nthin_files; i++){
1000 * If we are ordering the ARM64 slice last of the fat_arch
1001 * structs, so skip it in this loop.
1003 if(arm64_arch == thin_files + i)
1004 continue;
1006 * If we are ordering the x86_64h slice last too of the fat_arch
1007 * structs, so skip it in this loop.
1009 if(x86_64h_arch == thin_files + i)
1010 continue;
1011 if(fat64_flag == TRUE){
1012 fat_arch64.cputype = thin_files[i].cputype;
1013 fat_arch64.cpusubtype = thin_files[i].cpusubtype;
1014 fat_arch64.offset = thin_files[i].offset;
1015 fat_arch64.size = thin_files[i].size;
1016 fat_arch64.align = thin_files[i].align;
1018 else{
1019 fat_arch.cputype = thin_files[i].cputype;
1020 fat_arch.cpusubtype = thin_files[i].cpusubtype;
1021 fat_arch.offset = thin_files[i].offset;
1022 fat_arch.size = thin_files[i].size;
1023 fat_arch.align = thin_files[i].align;
1025 if(fat64_flag == TRUE){
1026 #ifdef __LITTLE_ENDIAN__
1027 swap_fat_arch_64(&fat_arch64, 1, BIG_ENDIAN_BYTE_SEX);
1028 #endif /* __LITTLE_ENDIAN__ */
1029 if(write(fd, &fat_arch64, sizeof(struct fat_arch_64)) !=
1030 sizeof(struct fat_arch_64))
1031 system_fatal("can't write fat arch to output file: %s",
1032 rename_file);
1034 else{
1035 #ifdef __LITTLE_ENDIAN__
1036 swap_fat_arch(&fat_arch, 1, BIG_ENDIAN_BYTE_SEX);
1037 #endif /* __LITTLE_ENDIAN__ */
1038 if(write(fd, &fat_arch, sizeof(struct fat_arch)) !=
1039 sizeof(struct fat_arch))
1040 system_fatal("can't write fat arch to output file: %s",
1041 rename_file);
1046 * We are ordering the ARM64 slice so it gets written last of the
1047 * fat_arch structs, so write it out here as it was skipped above.
1049 if(arm64_arch){
1050 if(fat64_flag == TRUE){
1051 fat_arch64.cputype = arm64_arch->cputype;
1052 fat_arch64.cpusubtype = arm64_arch->cpusubtype;
1053 fat_arch64.offset = arm64_arch->offset;
1054 fat_arch64.size = arm64_arch->size;
1055 fat_arch64.align = arm64_arch->align;
1056 #ifdef __LITTLE_ENDIAN__
1057 swap_fat_arch_64(&fat_arch64, 1, BIG_ENDIAN_BYTE_SEX);
1058 #endif /* __LITTLE_ENDIAN__ */
1059 if(write(fd, &fat_arch64, sizeof(struct fat_arch_64)) !=
1060 sizeof(struct fat_arch_64))
1061 system_fatal("can't write fat arch to output file: %s",
1062 rename_file);
1064 else{
1065 fat_arch.cputype = arm64_arch->cputype;
1066 fat_arch.cpusubtype = arm64_arch->cpusubtype;
1067 fat_arch.offset = arm64_arch->offset;
1068 fat_arch.size = arm64_arch->size;
1069 fat_arch.align = arm64_arch->align;
1070 #ifdef __LITTLE_ENDIAN__
1071 swap_fat_arch(&fat_arch, 1, BIG_ENDIAN_BYTE_SEX);
1072 #endif /* __LITTLE_ENDIAN__ */
1073 if(write(fd, &fat_arch,
1074 sizeof(struct fat_arch)) != sizeof(struct fat_arch))
1075 system_fatal("can't write fat arch to output file: %s",
1076 rename_file);
1080 * We are ordering the x86_64h slice so it gets written last too of the
1081 * fat_arch structs, so write it out here as it was skipped above.
1083 if(x86_64h_arch){
1084 if(fat64_flag == TRUE){
1085 fat_arch64.cputype = x86_64h_arch->cputype;
1086 fat_arch64.cpusubtype = x86_64h_arch->cpusubtype;
1087 fat_arch64.offset = x86_64h_arch->offset;
1088 fat_arch64.size = x86_64h_arch->size;
1089 fat_arch64.align = x86_64h_arch->align;
1090 #ifdef __LITTLE_ENDIAN__
1091 swap_fat_arch_64(&fat_arch64, 1, BIG_ENDIAN_BYTE_SEX);
1092 #endif /* __LITTLE_ENDIAN__ */
1093 if(write(fd, &fat_arch64, sizeof(struct fat_arch_64)) !=
1094 sizeof(struct fat_arch_64))
1095 system_fatal("can't write fat arch to output file: %s",
1096 rename_file);
1098 else{
1099 fat_arch.cputype = x86_64h_arch->cputype;
1100 fat_arch.cpusubtype = x86_64h_arch->cpusubtype;
1101 fat_arch.offset = x86_64h_arch->offset;
1102 fat_arch.size = x86_64h_arch->size;
1103 fat_arch.align = x86_64h_arch->align;
1104 #ifdef __LITTLE_ENDIAN__
1105 swap_fat_arch(&fat_arch, 1, BIG_ENDIAN_BYTE_SEX);
1106 #endif /* __LITTLE_ENDIAN__ */
1107 if(write(fd, &fat_arch, sizeof(struct fat_arch)) !=
1108 sizeof(struct fat_arch))
1109 system_fatal("can't write fat arch to output file: %s",
1110 rename_file);
1113 for(i = 0; i < nthin_files; i++){
1114 if(extract_family_flag == FALSE || nthin_files > 1)
1115 if(lseek(fd, thin_files[i].offset, L_SET) == -1)
1116 system_fatal("can't lseek in output file: %s", rename_file);
1117 nbytes_written = 0;
1119 if(thin_files[i].size - nbytes_written > MAX_WRITE)
1120 nbytes_to_write = MAX_WRITE;
1121 else
1122 nbytes_to_write = thin_files[i].size - nbytes_written;
1123 if(write(fd, thin_files[i].addr + nbytes_written,
1124 nbytes_to_write) != nbytes_to_write)
1125 system_fatal("can't write to output file: %s", rename_file);
1126 nbytes_written += nbytes_to_write;
1127 }while(nbytes_written != thin_files[i].size);
1129 if(close(fd) == -1)
1130 system_fatal("can't close output file: %s", rename_file);
1131 if(rename(rename_file, output_file) == -1)
1132 system_error("can't move temporary file: %s to file: %s",
1133 output_file, rename_file);
1134 free(rename_file);
1138 * process_input_file() checks input file and breaks it down into thin files
1139 * for later operations.
1141 static
1142 void
1143 process_input_file(
1144 struct input_file *input)
1146 int fd;
1147 struct stat stat_buf, stat_buf2;
1148 uint32_t i, j;
1149 uint64_t size;
1150 char *addr;
1151 struct thin_file *thin;
1152 struct mach_header *mhp, mh;
1153 struct mach_header_64 *mhp64, mh64;
1154 struct load_command *lcp;
1155 cpu_type_t cputype;
1156 cpu_subtype_t cpusubtype;
1157 enum bool swapped;
1158 uint64_t big_size;
1160 /* Open the input file and map it in */
1161 if((fd = open(input->name, O_RDONLY)) == -1)
1162 system_fatal("can't open input file: %s", input->name);
1163 if(fstat(fd, &stat_buf) == -1)
1164 system_fatal("can't stat input file: %s", input->name);
1165 size = stat_buf.st_size;
1166 /* pick up set uid, set gid and sticky text bits */
1167 output_filemode = stat_buf.st_mode & 07777;
1169 * Select the eariliest modify time so that if the output file
1170 * contains archives with table of contents lipo will not make them
1171 * out of date. This logic however could make an out of date table of
1172 * contents appear up todate if another file is combined with it that
1173 * has a date early enough.
1175 #ifndef __OPENSTEP__
1176 if(output_timep.modtime == 0 ||
1177 output_timep.modtime > stat_buf.st_mtime){
1178 output_timep.actime = stat_buf.st_atime;
1179 output_timep.modtime = stat_buf.st_mtime;
1181 #else
1182 if(output_timep[1] == 0 || output_timep[1] > stat_buf.st_mtime){
1183 output_timep[0] = stat_buf.st_atime;
1184 output_timep[1] = stat_buf.st_mtime;
1186 #endif
1188 * mmap() can't handle mapping regular files with zero size. So this
1189 * is handled separately.
1191 if((stat_buf.st_mode & S_IFREG) == S_IFREG && size == 0)
1192 addr = NULL;
1193 else
1194 addr = mmap(0, size, PROT_READ|PROT_WRITE, MAP_FILE|MAP_PRIVATE,
1195 fd, 0);
1196 if((intptr_t)addr == -1)
1197 system_fatal("can't map input file: %s", input->name);
1200 * Because of rdar://8087586 we do a second stat to see if the file
1201 * is still there and the same file.
1203 if(fstat(fd, &stat_buf2) == -1)
1204 system_fatal("can't stat input file: %s", input->name);
1205 if(stat_buf2.st_size != size ||
1206 stat_buf2.st_mtime != stat_buf.st_mtime)
1207 system_fatal("Input file: %s changed since opened", input->name);
1209 close(fd);
1211 /* Try to figure out what kind of file this is */
1213 /* see if this file is a 32-bit fat file */
1214 if(size >= sizeof(struct fat_header) &&
1215 #ifdef __BIG_ENDIAN__
1216 *((uint32_t *)addr) == FAT_MAGIC)
1217 #endif /* __BIG_ENDIAN__ */
1218 #ifdef __LITTLE_ENDIAN__
1219 *((uint32_t *)addr) == SWAP_INT(FAT_MAGIC))
1220 #endif /* __LITTLE_ENDIAN__ */
1223 if(input->arch_flag.name != NULL)
1224 fatal("architecture specifed for fat input file: %s "
1225 "(architectures can't be specifed for fat input files)",
1226 input->name);
1228 input->fat_header = (struct fat_header *)addr;
1229 #ifdef __LITTLE_ENDIAN__
1230 swap_fat_header(input->fat_header, LITTLE_ENDIAN_BYTE_SEX);
1231 #endif /* __LITTLE_ENDIAN__ */
1232 big_size = input->fat_header->nfat_arch;
1233 big_size *= sizeof(struct fat_arch);
1234 big_size += sizeof(struct fat_header);
1235 if(big_size > size)
1236 fatal("truncated or malformed fat file (fat_arch structs would "
1237 "extend past the end of the file) %s", input->name);
1238 input->fat_arches = (struct fat_arch *)
1239 (addr + sizeof(struct fat_header));
1240 #ifdef __LITTLE_ENDIAN__
1241 swap_fat_arch(input->fat_arches, input->fat_header->nfat_arch,
1242 LITTLE_ENDIAN_BYTE_SEX);
1243 #endif /* __LITTLE_ENDIAN__ */
1244 for(i = 0; i < input->fat_header->nfat_arch; i++){
1245 if(input->fat_arches[i].offset + input->fat_arches[i].size >
1246 size)
1247 fatal("truncated or malformed fat file (offset plus size "
1248 "of cputype (%d) cpusubtype (%d) extends past the "
1249 "end of the file) %s", input->fat_arches[i].cputype,
1250 input->fat_arches[i].cpusubtype & ~CPU_SUBTYPE_MASK,
1251 input->name);
1252 if(input->fat_arches[i].align > MAXSECTALIGN)
1253 fatal("align (2^%u) too large of fat file %s (cputype (%d)"
1254 " cpusubtype (%d)) (maximum 2^%d)",
1255 input->fat_arches[i].align, input->name,
1256 input->fat_arches[i].cputype,
1257 input->fat_arches[i].cpusubtype & ~CPU_SUBTYPE_MASK,
1258 MAXSECTALIGN);
1259 if(input->fat_arches[i].offset %
1260 (1 << input->fat_arches[i].align) != 0)
1261 fatal("offset %u of fat file %s (cputype (%d) cpusubtype "
1262 "(%d)) not aligned on its alignment (2^%u)",
1263 input->fat_arches[i].offset, input->name,
1264 input->fat_arches[i].cputype,
1265 input->fat_arches[i].cpusubtype & ~CPU_SUBTYPE_MASK,
1266 input->fat_arches[i].align);
1268 for(i = 0; i < input->fat_header->nfat_arch; i++){
1269 for(j = i + 1; j < input->fat_header->nfat_arch; j++){
1270 if(input->fat_arches[i].cputype ==
1271 input->fat_arches[j].cputype &&
1272 (input->fat_arches[i].cpusubtype & ~CPU_SUBTYPE_MASK) ==
1273 (input->fat_arches[j].cpusubtype & ~CPU_SUBTYPE_MASK))
1274 fatal("fat file %s contains two of the same architecture "
1275 "(cputype (%d) cpusubtype (%d))", input->name,
1276 input->fat_arches[i].cputype,
1277 input->fat_arches[i].cpusubtype & ~CPU_SUBTYPE_MASK);
1281 /* create a thin file struct for each arch in the fat file */
1282 for(i = 0; i < input->fat_header->nfat_arch; i++){
1283 thin = new_thin();
1284 thin->name = input->name;
1285 thin->addr = addr + input->fat_arches[i].offset;
1286 thin->cputype = input->fat_arches[i].cputype;
1287 thin->cpusubtype = input->fat_arches[i].cpusubtype;
1288 thin->offset = input->fat_arches[i].offset;
1289 thin->size = input->fat_arches[i].size;
1290 thin->align = input->fat_arches[i].align;
1291 thin->from_fat = TRUE;
1292 if(input->fat_arches[i].size >= SARMAG &&
1293 strncmp(thin->addr, ARMAG, SARMAG) == 0)
1294 archives_in_input = TRUE;
1297 /* see if this file is a 64-bit fat file */
1298 else if(size >= sizeof(struct fat_header) &&
1299 #ifdef __BIG_ENDIAN__
1300 *((uint32_t *)addr) == FAT_MAGIC_64)
1301 #endif /* __BIG_ENDIAN__ */
1302 #ifdef __LITTLE_ENDIAN__
1303 *((uint32_t *)addr) == SWAP_INT(FAT_MAGIC_64))
1304 #endif /* __LITTLE_ENDIAN__ */
1307 if(input->arch_flag.name != NULL)
1308 fatal("architecture specifed for fat input file: %s "
1309 "(architectures can't be specifed for fat input files)",
1310 input->name);
1312 input->fat_header = (struct fat_header *)addr;
1313 #ifdef __LITTLE_ENDIAN__
1314 swap_fat_header(input->fat_header, LITTLE_ENDIAN_BYTE_SEX);
1315 #endif /* __LITTLE_ENDIAN__ */
1316 big_size = input->fat_header->nfat_arch;
1317 big_size *= sizeof(struct fat_arch_64);
1318 big_size += sizeof(struct fat_header);
1319 if(big_size > size)
1320 fatal("truncated or malformed fat file (fat_arch_64 structs "
1321 "would extend past the end of the file) %s", input->name);
1322 input->fat_arches64 = (struct fat_arch_64 *)
1323 (addr + sizeof(struct fat_header));
1324 #ifdef __LITTLE_ENDIAN__
1325 swap_fat_arch_64(input->fat_arches64, input->fat_header->nfat_arch,
1326 LITTLE_ENDIAN_BYTE_SEX);
1327 #endif /* __LITTLE_ENDIAN__ */
1328 for(i = 0; i < input->fat_header->nfat_arch; i++){
1329 if(input->fat_arches64[i].offset + input->fat_arches64[i].size >
1330 size)
1331 fatal("truncated or malformed fat file (offset plus size "
1332 "of cputype (%d) cpusubtype (%d) extends past the "
1333 "end of the file) %s", input->fat_arches64[i].cputype,
1334 input->fat_arches64[i].cpusubtype & ~CPU_SUBTYPE_MASK,
1335 input->name);
1336 if(input->fat_arches64[i].align > MAXSECTALIGN)
1337 fatal("align (2^%u) too large of fat file %s (cputype (%d)"
1338 " cpusubtype (%d)) (maximum 2^%d)",
1339 input->fat_arches64[i].align, input->name,
1340 input->fat_arches64[i].cputype,
1341 input->fat_arches64[i].cpusubtype & ~CPU_SUBTYPE_MASK,
1342 MAXSECTALIGN);
1343 if(input->fat_arches64[i].offset %
1344 (1 << input->fat_arches64[i].align) != 0)
1345 fatal("offset %llu of fat file %s (cputype (%d) cpusubtype "
1346 "(%d)) not aligned on its alignment (2^%u)",
1347 input->fat_arches64[i].offset, input->name,
1348 input->fat_arches64[i].cputype,
1349 input->fat_arches64[i].cpusubtype & ~CPU_SUBTYPE_MASK,
1350 input->fat_arches64[i].align);
1352 for(i = 0; i < input->fat_header->nfat_arch; i++){
1353 for(j = i + 1; j < input->fat_header->nfat_arch; j++){
1354 if(input->fat_arches64[i].cputype ==
1355 input->fat_arches64[j].cputype &&
1356 (input->fat_arches64[i].cpusubtype &
1357 ~CPU_SUBTYPE_MASK) ==
1358 (input->fat_arches64[j].cpusubtype &
1359 ~CPU_SUBTYPE_MASK))
1360 fatal("fat file %s contains two of the same architecture "
1361 "(cputype (%d) cpusubtype (%d))", input->name,
1362 input->fat_arches64[i].cputype,
1363 input->fat_arches64[i].cpusubtype &
1364 ~CPU_SUBTYPE_MASK);
1368 /* create a thin file struct for each arch in the fat file */
1369 for(i = 0; i < input->fat_header->nfat_arch; i++){
1370 thin = new_thin();
1371 thin->name = input->name;
1372 thin->addr = addr + input->fat_arches64[i].offset;
1373 thin->cputype = input->fat_arches64[i].cputype;
1374 thin->cpusubtype = input->fat_arches64[i].cpusubtype;
1375 thin->offset = input->fat_arches64[i].offset;
1376 thin->size = input->fat_arches64[i].size;
1377 thin->align = input->fat_arches64[i].align;
1378 thin->from_fat = TRUE;
1379 if(input->fat_arches64[i].size >= SARMAG &&
1380 strncmp(thin->addr, ARMAG, SARMAG) == 0)
1381 archives_in_input = TRUE;
1384 /* see if this file is Mach-O file for 32-bit architectures */
1385 else if(size >= sizeof(struct mach_header) &&
1386 (*((uint32_t *)addr) == MH_MAGIC ||
1387 *((uint32_t *)addr) == SWAP_INT(MH_MAGIC))){
1389 /* this is a Mach-O file so create a thin file struct for it */
1390 thin = new_thin();
1391 input->is_thin = TRUE;
1392 thin->name = input->name;
1393 thin->addr = addr;
1394 mhp = (struct mach_header *)addr;
1395 lcp = (struct load_command *)((char *)mhp +
1396 sizeof(struct mach_header));
1397 if(mhp->magic == SWAP_INT(MH_MAGIC)){
1398 swapped = TRUE;
1399 mh = *mhp;
1400 swap_mach_header(&mh, get_host_byte_sex());
1401 mhp = &mh;
1403 else
1404 swapped = FALSE;
1405 if(fat64_flag == FALSE && size > UINT32_MAX)
1406 fatal("file too large to be in a fat file because the size "
1407 "field in struct fat_arch is only 32-bits and the size "
1408 "(%llu) of %s exceeds that", size, input->name);
1409 thin->cputype = mhp->cputype;
1410 thin->cpusubtype = mhp->cpusubtype;
1411 thin->offset = 0;
1412 thin->size = size;
1413 thin->align = get_align(mhp, lcp, size, input->name, swapped);
1415 /* if the arch type is specified make sure it matches the object */
1416 if(input->arch_flag.name != NULL)
1417 check_arch(input, thin);
1419 /* see if this file is Mach-O file for 64-bit architectures */
1420 else if(size >= sizeof(struct mach_header_64) &&
1421 (*((uint32_t *)addr) == MH_MAGIC_64 ||
1422 *((uint32_t *)addr) == SWAP_INT(MH_MAGIC_64))){
1424 /* this is a Mach-O file so create a thin file struct for it */
1425 thin = new_thin();
1426 input->is_thin = TRUE;
1427 thin->name = input->name;
1428 thin->addr = addr;
1429 mhp64 = (struct mach_header_64 *)addr;
1430 lcp = (struct load_command *)((char *)mhp64 +
1431 sizeof(struct mach_header_64));
1432 if(mhp64->magic == SWAP_INT(MH_MAGIC_64)){
1433 swapped = TRUE;
1434 mh64 = *mhp64;
1435 swap_mach_header_64(&mh64, get_host_byte_sex());
1436 mhp64 = &mh64;
1438 else
1439 swapped = FALSE;
1440 if(fat64_flag == FALSE && size > UINT32_MAX)
1441 fatal("file too large to be in a fat file because the size "
1442 "field in struct fat_arch is only 32-bits and the size "
1443 "(%llu) of %s exceeds that", size, input->name);
1444 thin->cputype = mhp64->cputype;
1445 thin->cpusubtype = mhp64->cpusubtype;
1446 thin->offset = 0;
1447 thin->size = size;
1448 thin->align = get_align_64(mhp64, lcp, size, input->name, swapped);
1450 /* if the arch type is specified make sure it matches the object */
1451 if(input->arch_flag.name != NULL)
1452 check_arch(input, thin);
1454 /* see if this file is an archive file */
1455 else if(size >= SARMAG && strncmp(addr, ARMAG, SARMAG) == 0){
1457 check_archive(input->name, addr, size, &cputype, &cpusubtype);
1458 archives_in_input = TRUE;
1460 /* create a thin file struct for this archive */
1461 thin = new_thin();
1462 thin->name = input->name;
1463 thin->addr = addr;
1464 if(fat64_flag == FALSE && size > UINT32_MAX)
1465 fatal("file too large to be in a fat file because the size "
1466 "field in struct fat_arch is only 32-bits and the size "
1467 "(%llu) of %s exceeds that", size, input->name);
1468 thin->cputype = cputype;
1469 thin->cpusubtype = cpusubtype;
1470 thin->offset = 0;
1471 thin->size = size;
1472 if(thin->cputype & CPU_ARCH_ABI64)
1473 thin->align = 3; /* 2^3, alignof(uint64_t) */
1474 else
1475 thin->align = 2; /* 2^2, alignof(uint32_t) */
1477 /* if the arch type is specified make sure it matches the object */
1478 if(input->arch_flag.name != NULL){
1479 if(cputype == 0){
1480 thin->cputype = input->arch_flag.cputype;
1481 thin->cpusubtype = input->arch_flag.cpusubtype;
1483 else
1484 check_arch(input, thin);
1486 else{
1487 if(cputype == 0)
1488 fatal("archive with no architecture specification: %s "
1489 "(can't determine architecture for it)", input->name);
1492 /* this file type is now known to be unknown to this program */
1493 else{
1495 if(input->arch_flag.name != NULL){
1496 /* create a thin file struct for it */
1497 thin = new_thin();
1498 thin->name = input->name;
1499 thin->addr = addr;
1500 if(fat64_flag == FALSE && size > UINT32_MAX)
1501 fatal("file too large to be in a fat file because the size "
1502 "field in struct fat_arch is only 32-bits and the "
1503 "size (%llu) of %s exceeds that", size, input->name);
1504 thin->cputype = input->arch_flag.cputype;
1505 thin->cpusubtype = input->arch_flag.cpusubtype;
1506 thin->offset = 0;
1507 thin->size = size;
1508 thin->align = 0;
1510 else{
1511 #ifdef LTO_SUPPORT
1512 if(is_llvm_bitcode_from_memory(addr, size, &input->arch_flag,
1513 NULL) != 0){
1514 /* create a thin file struct for it */
1515 thin = new_thin();
1516 thin->name = input->name;
1517 thin->addr = addr;
1518 if(fat64_flag == FALSE && size > UINT32_MAX)
1519 fatal("file too large to be in a fat file because the "
1520 "size field in struct fat_arch is only 32-bits "
1521 "and the size (%llu) of %s exceeds that", size,
1522 input->name);
1523 thin->cputype = input->arch_flag.cputype;
1524 thin->cpusubtype = input->arch_flag.cpusubtype;
1525 thin->offset = 0;
1526 thin->size = size;
1527 thin->align = 0;
1529 else
1530 #endif /* LTO_SUPPORT */
1531 fatal("can't figure out the architecture type of: %s",
1532 input->name);
1538 * process_replace_file() checks the replacement file and maps it in for later
1539 * processing.
1541 static
1542 void
1543 process_replace_file(
1544 struct replace *replace)
1546 int fd;
1547 struct stat stat_buf;
1548 uint64_t size;
1549 char *addr;
1550 struct mach_header *mhp, mh;
1551 struct mach_header_64 *mhp64, mh64;
1552 struct load_command *lcp;
1553 cpu_type_t cputype;
1554 cpu_subtype_t cpusubtype;
1555 enum bool swapped;
1557 /* Open the replacement file and map it in */
1558 if((fd = open(replace->thin_file.name, O_RDONLY)) == -1)
1559 system_fatal("can't open replacement file: %s",
1560 replace->thin_file.name);
1561 if(fstat(fd, &stat_buf) == -1)
1562 system_fatal("can't stat replacement file: %s",
1563 replace->thin_file.name);
1564 size = stat_buf.st_size;
1566 * mmap() can't handle mapping regular files with zero size. So this
1567 * is handled separately.
1569 if((stat_buf.st_mode & S_IFREG) == S_IFREG && size == 0)
1570 addr = NULL;
1571 else
1572 addr = mmap(0, size, PROT_READ|PROT_WRITE, MAP_FILE|MAP_PRIVATE,
1573 fd, 0);
1574 if((intptr_t)addr == -1)
1575 system_error("can't map replacement file: %s",
1576 replace->thin_file.name);
1577 close(fd);
1579 /* Try to figure out what kind of file this is */
1581 /* see if this file is a fat file */
1582 if(size >= sizeof(struct fat_header) &&
1583 #ifdef __BIG_ENDIAN__
1584 (*((uint32_t *)addr) == FAT_MAGIC ||
1585 *((uint32_t *)addr) == FAT_MAGIC_64))
1586 #endif /* __BIG_ENDIAN__ */
1587 #ifdef __LITTLE_ENDIAN__
1588 (*((uint32_t *)addr) == SWAP_INT(FAT_MAGIC) ||
1589 *((uint32_t *)addr) == SWAP_INT(FAT_MAGIC_64)))
1590 #endif /* __LITTLE_ENDIAN__ */
1593 fatal("replacement file: %s is a fat file (must be a thin file)",
1594 replace->thin_file.name);
1596 /* see if this file is Mach-O file for 32-bit architectures */
1597 else if(size >= sizeof(struct mach_header) &&
1598 (*((uint32_t *)addr) == MH_MAGIC ||
1599 *((uint32_t *)addr) == SWAP_INT(MH_MAGIC))){
1601 /* this is a Mach-O file so fill in the thin file struct for it */
1602 replace->thin_file.addr = addr;
1603 mhp = (struct mach_header *)addr;
1604 lcp = (struct load_command *)((char *)mhp +
1605 sizeof(struct mach_header));
1606 if(mhp->magic == SWAP_INT(MH_MAGIC)){
1607 swapped = TRUE;
1608 mh = *mhp;
1609 swap_mach_header(&mh, get_host_byte_sex());
1610 mhp = &mh;
1612 else
1613 swapped = FALSE;
1614 if(fat64_flag == FALSE && size > UINT32_MAX)
1615 fatal("file too large to be in a fat file because the "
1616 "size field in struct fat_arch is only 32-bits "
1617 "and the size (%llu) of %s exceeds that", size,
1618 replace->thin_file.name);
1619 replace->thin_file.cputype = mhp->cputype;
1620 replace->thin_file.cpusubtype = mhp->cpusubtype;
1621 replace->thin_file.offset = 0;
1622 replace->thin_file.size = size;
1623 replace->thin_file.align =
1624 get_align(mhp, lcp, size, replace->thin_file.name, swapped);
1626 /* see if this file is Mach-O file for 64-bit architectures */
1627 else if(size >= sizeof(struct mach_header_64) &&
1628 (*((uint32_t *)addr) == MH_MAGIC_64 ||
1629 *((uint32_t *)addr) == SWAP_INT(MH_MAGIC_64))){
1631 /* this is a Mach-O file so fill in the thin file struct for it */
1632 replace->thin_file.addr = addr;
1633 mhp64 = (struct mach_header_64 *)addr;
1634 lcp = (struct load_command *)((char *)mhp64 +
1635 sizeof(struct mach_header_64));
1636 if(mhp64->magic == SWAP_INT(MH_MAGIC_64)){
1637 swapped = TRUE;
1638 mh64 = *mhp64;
1639 swap_mach_header_64(&mh64, get_host_byte_sex());
1640 mhp64 = &mh64;
1642 else
1643 swapped = FALSE;
1644 if(fat64_flag == FALSE && size > UINT32_MAX)
1645 fatal("file too large to be in a fat file because the "
1646 "size field in struct fat_arch is only 32-bits "
1647 "and the size (%llu) of %s exceeds that", size,
1648 replace->thin_file.name);
1649 replace->thin_file.cputype = mhp64->cputype;
1650 replace->thin_file.cpusubtype = mhp64->cpusubtype;
1651 replace->thin_file.offset = 0;
1652 replace->thin_file.size = size;
1653 replace->thin_file.align =
1654 get_align_64(mhp64, lcp, size, replace->thin_file.name, swapped);
1656 /* see if this file is an archive file */
1657 else if(size >= SARMAG && strncmp(addr, ARMAG, SARMAG) == 0){
1659 check_archive(replace->thin_file.name, addr, size,
1660 &cputype, &cpusubtype);
1662 if(fat64_flag == FALSE && size > UINT32_MAX)
1663 fatal("file too large to be in a fat file because the "
1664 "size field in struct fat_arch is only 32-bits "
1665 "and the size (%llu) of %s exceeds that", size,
1666 replace->thin_file.name);
1667 /* fill in the thin file struct for this archive */
1668 replace->thin_file.addr = addr;
1669 replace->thin_file.cputype = cputype;
1670 replace->thin_file.cpusubtype = cpusubtype;
1671 replace->thin_file.offset = 0;
1672 replace->thin_file.size = size;
1673 replace->thin_file.align = 2; /* 2^2, sizeof(uint32_t) */
1675 else{
1676 if(fat64_flag == FALSE && size > UINT32_MAX)
1677 fatal("file too large to be in a fat file because the "
1678 "size field in struct fat_arch is only 32-bits "
1679 "and the size (%llu) of %s exceeds that", size,
1680 replace->thin_file.name);
1681 /* fill in the thin file struct for it */
1682 replace->thin_file.addr = addr;
1683 replace->thin_file.cputype = replace->arch_flag.cputype;
1684 replace->thin_file.cpusubtype = replace->arch_flag.cpusubtype;
1685 replace->thin_file.offset = 0;
1686 replace->thin_file.size = size;
1687 replace->thin_file.align = 0;
1690 if(replace->thin_file.cputype != replace->arch_flag.cputype ||
1691 (replace->thin_file.cpusubtype & ~CPU_SUBTYPE_MASK) !=
1692 (replace->arch_flag.cpusubtype & ~CPU_SUBTYPE_MASK))
1693 fatal("specified architecture: %s for replacement file: %s does "
1694 "not match the file's architecture", replace->arch_flag.name,
1695 replace->thin_file.name);
1699 * check_archive() checks an archive (mapped in at 'addr' of size 'size') to
1700 * make sure it can be included in a fat file (all members are the same
1701 * architecture, no fat files, etc). It returns the cputype and cpusubtype.
1703 static
1704 void
1705 check_archive(
1706 char *name,
1707 char *addr,
1708 uint64_t size,
1709 cpu_type_t *cputype,
1710 cpu_subtype_t *cpusubtype)
1712 uint64_t offset;
1713 uint32_t magic, i, ar_name_size, ar_size;
1714 struct mach_header mh;
1715 struct mach_header_64 mh64;
1716 struct ar_hdr *ar_hdr;
1717 char *ar_name, *ar_addr;
1718 struct arch_flag arch_flag;
1721 * Check this archive out to make sure that it does not contain
1722 * any fat files and that all object files it contains have the
1723 * same cputype and subsubtype.
1725 *cputype = 0;
1726 *cpusubtype = 0;
1727 offset = SARMAG;
1728 if(offset == size)
1729 fatal("empty archive with no architecture specification: %s "
1730 "(can't determine architecture for it)", name);
1731 if(offset != size && offset + sizeof(struct ar_hdr) > size)
1732 fatal("truncated or malformed archive: %s (archive header of "
1733 "first member extends past the end of the file)", name);
1734 while(size > offset){
1735 ar_hdr = (struct ar_hdr *)(addr + offset);
1736 offset += sizeof(struct ar_hdr);
1737 if(strncmp(ar_hdr->ar_name, AR_EFMT1, sizeof(AR_EFMT1) - 1) == 0){
1738 check_extend_format_1(name, ar_hdr, size-offset, &ar_name_size);
1739 i = ar_name_size;
1740 ar_name = ar_hdr->ar_name + sizeof(struct ar_hdr);
1742 else{
1743 i = size_ar_name(ar_hdr->ar_name);
1744 ar_name = ar_hdr->ar_name;
1745 ar_name_size = 0;
1747 if(size + ar_name_size - offset > sizeof(uint32_t)){
1748 memcpy(&magic, addr + offset + ar_name_size,
1749 sizeof(uint32_t));
1750 #ifdef __BIG_ENDIAN__
1751 if(magic == FAT_MAGIC || magic == FAT_MAGIC_64)
1752 #endif /* __BIG_ENDIAN__ */
1753 #ifdef __LITTLE_ENDIAN__
1754 if(magic == SWAP_INT(FAT_MAGIC) ||
1755 magic == SWAP_INT(FAT_MAGIC_64))
1756 #endif /* __LITTLE_ENDIAN__ */
1757 fatal("archive member %s(%.*s) is a fat file (not "
1758 "allowed in an archive)", name, (int)i, ar_name);
1759 if((size - ar_name_size) - offset >=
1760 sizeof(struct mach_header) &&
1761 (magic == MH_MAGIC || magic == SWAP_INT(MH_MAGIC))){
1762 memcpy(&mh, addr + offset + ar_name_size,
1763 sizeof(struct mach_header));
1764 if(mh.magic == SWAP_INT(MH_MAGIC))
1765 swap_mach_header(&mh, get_host_byte_sex());
1766 if(*cputype == 0){
1767 *cputype = mh.cputype;
1768 *cpusubtype = mh.cpusubtype;
1770 else if(*cputype != mh.cputype){
1771 fatal("archive member %s(%.*s) cputype (%d) and "
1772 "cpusubtype (%d) does not match previous "
1773 "archive members cputype (%d) and cpusubtype"
1774 " (%d) (all members must match)", name,
1775 (int)i, ar_name, mh.cputype, mh.cpusubtype &
1776 ~CPU_SUBTYPE_MASK, *cputype, (*cpusubtype) &
1777 ~CPU_SUBTYPE_MASK);
1780 else if((size - ar_name_size) - offset >=
1781 sizeof(struct mach_header_64) &&
1782 (magic == MH_MAGIC_64 || magic == SWAP_INT(MH_MAGIC_64))){
1783 memcpy(&mh64, addr + offset + ar_name_size,
1784 sizeof(struct mach_header_64));
1785 if(mh64.magic == SWAP_INT(MH_MAGIC_64))
1786 swap_mach_header_64(&mh64, get_host_byte_sex());
1787 if(*cputype == 0){
1788 *cputype = mh64.cputype;
1789 *cpusubtype = mh64.cpusubtype;
1791 else if(*cputype != mh64.cputype){
1792 fatal("archive member %s(%.*s) cputype (%d) and "
1793 "cpusubtype (%d) does not match previous "
1794 "archive members cputype (%d) and cpusubtype"
1795 " (%d) (all members must match)", name,
1796 (int)i, ar_name, mh64.cputype, mh64.cpusubtype &
1797 ~CPU_SUBTYPE_MASK, *cputype, (*cpusubtype) &
1798 ~CPU_SUBTYPE_MASK);
1801 else{
1802 if(strncmp(ar_name, SYMDEF, sizeof(SYMDEF) - 1) != 0){
1803 ar_addr = addr + offset + ar_name_size;
1804 ar_size = strtoul(ar_hdr->ar_size, NULL, 10);
1805 #ifdef LTO_SUPPORT
1806 if(is_llvm_bitcode_from_memory(ar_addr, ar_size,
1807 &arch_flag, NULL) != 0){
1808 if(*cputype == 0){
1809 *cputype = arch_flag.cputype;
1810 *cpusubtype = arch_flag.cpusubtype;
1812 else if(*cputype != arch_flag.cputype){
1813 fatal("archive member %s(%.*s) cputype (%d) "
1814 "and cpusubtype (%d) does not match "
1815 "previous archive members cputype (%d) "
1816 "and cpusubtype (%d) (all members must "
1817 "match)", name, (int)i, ar_name,
1818 arch_flag.cputype, arch_flag.cpusubtype &
1819 ~CPU_SUBTYPE_MASK, *cputype,
1820 (*cpusubtype) & ~CPU_SUBTYPE_MASK);
1823 #endif /* LTO_SUPPORT */
1827 offset += rnd(strtoul(ar_hdr->ar_size, NULL, 10),
1828 sizeof(short));
1832 * check_extend_format_1() checks the archive header for extened format1.
1834 static
1835 void
1836 check_extend_format_1(
1837 char *name,
1838 struct ar_hdr *ar_hdr,
1839 uint64_t size_left,
1840 uint32_t *member_name_size)
1842 char *p, *endp, buf[sizeof(ar_hdr->ar_name)+1];
1843 uint32_t ar_name_size;
1845 *member_name_size = 0;
1847 buf[sizeof(ar_hdr->ar_name)] = '\0';
1848 memcpy(buf, ar_hdr->ar_name, sizeof(ar_hdr->ar_name));
1849 p = buf + sizeof(AR_EFMT1) - 1;
1850 if(isdigit(*p) == 0)
1851 fatal("archive: %s malformed (ar_name: %.*s for archive extend "
1852 "format #1 starts with non-digit)", name,
1853 (int)sizeof(ar_hdr->ar_name), ar_hdr->ar_name);
1854 ar_name_size = strtoul(p, &endp, 10);
1855 if(ar_name_size == UINT_MAX && errno == ERANGE)
1856 fatal("archive: %s malformed (size in ar_name: %.*s for archive "
1857 "extend format #1 overflows uint32_t)", name,
1858 (int)sizeof(ar_hdr->ar_name), ar_hdr->ar_name);
1859 while(*endp == ' ' && *endp != '\0')
1860 endp++;
1861 if(*endp != '\0')
1862 fatal("archive: %s malformed (size in ar_name: %.*s for archive "
1863 "extend format #1 contains non-digit and non-space "
1864 "characters)", name, (int)sizeof(ar_hdr->ar_name),
1865 ar_hdr->ar_name);
1866 if(ar_name_size > size_left)
1867 fatal("archive: %s truncated or malformed (archive name "
1868 "of member extends past the end of the file)", name);
1869 *member_name_size = ar_name_size;
1873 * get_arm64_arch() will return a pointer to the thin_file struct for the
1874 * 64-bit arm slice in the thin_files[i] if it is present. Else it returns
1875 * NULL.
1877 static
1878 struct thin_file *
1879 get_arm64_arch(
1880 void)
1882 uint32_t i;
1885 * Look for a 64-bit arm slice.
1887 for(i = 0; i < nthin_files; i++){
1888 if(thin_files[i].cputype == CPU_TYPE_ARM64){
1889 return(thin_files + i);
1892 return(NULL);
1896 * get_x86_64h_arch() will return a pointer to the thin_file struct for the
1897 * x86_64h slice in the thin_files[i] if it is present. Else it returns
1898 * NULL.
1900 static
1901 struct thin_file *
1902 get_x86_64h_arch(
1903 void)
1905 uint32_t i;
1908 * Look for a x86_64h slice.
1910 for(i = 0; i < nthin_files; i++){
1911 if(thin_files[i].cputype == CPU_TYPE_X86_64 &&
1912 (thin_files[i].cpusubtype & ~CPU_SUBTYPE_MASK) ==
1913 CPU_SUBTYPE_X86_64_H){
1914 return(thin_files + i);
1917 return(NULL);
1921 * get_align is passed a pointer to a mach header and size of the object. It
1922 * returns the segment alignment the object was created with. It guesses but
1923 * it is conservative. The maximum alignment is that the link editor will allow
1924 * MAXSECTALIGN and the minimum is the conserative alignment for a uint32_t
1925 * which appears in a mach object files (2^2 worst case for all current 32-bit
1926 * machines).
1928 static
1929 uint32_t
1930 get_align(
1931 struct mach_header *mhp,
1932 struct load_command *load_commands,
1933 uint64_t size,
1934 char *name,
1935 enum bool swapped)
1937 uint32_t i, j, cur_align, align;
1938 struct load_command *lcp, l;
1939 struct segment_command *sgp, sg;
1940 struct section *sp, s;
1941 enum byte_sex host_byte_sex;
1944 * Special case ppc and i386 architectures and return 12.
1945 * We know that with those architectures that the kernel and mmap only
1946 * need file offsets to be page (4096 byte) aligned.
1948 if(mhp->cputype == CPU_TYPE_POWERPC ||
1949 mhp->cputype == CPU_TYPE_I386)
1950 return(12);
1952 * Special case ARM and return 14. As it has 16k pages.
1954 if(mhp->cputype == CPU_TYPE_ARM)
1955 return(14);
1957 host_byte_sex = get_host_byte_sex();
1959 /* set worst case the link editor uses first */
1960 cur_align = MAXSECTALIGN;
1961 if(mhp->sizeofcmds + sizeof(struct mach_header) > size)
1962 fatal("truncated or malformed object (load commands would "
1963 "extend past the end of the file) in: %s", name);
1964 lcp = load_commands;
1965 for(i = 0; i < mhp->ncmds; i++){
1966 l = *lcp;
1967 if(swapped)
1968 swap_load_command(&l, host_byte_sex);
1969 if(l.cmdsize % sizeof(uint32_t) != 0)
1970 error("load command %u size not a multiple of "
1971 "sizeof(uint32_t) in: %s", i, name);
1972 if(l.cmdsize <= 0)
1973 fatal("load command %u size is less than or equal to zero "
1974 "in: %s", i, name);
1975 if((char *)lcp + l.cmdsize >
1976 (char *)load_commands + mhp->sizeofcmds)
1977 fatal("load command %u extends past end of all load "
1978 "commands in: %s", i, name);
1979 if(l.cmd == LC_SEGMENT){
1980 sgp = (struct segment_command *)lcp;
1981 sg = *sgp;
1982 if(swapped)
1983 swap_segment_command(&sg, host_byte_sex);
1984 if(mhp->filetype == MH_OBJECT){
1985 /* this is the minimum alignment, then take largest */
1986 align = 2; /* 2^2 sizeof(uint32_t) */
1987 sp = (struct section *)((char *)sgp +
1988 sizeof(struct segment_command));
1989 for(j = 0; j < sg.nsects; j++){
1990 s = *sp;
1991 if(swapped)
1992 swap_section(&s, 1, host_byte_sex);
1993 if(s.align > align)
1994 align = s.align;
1995 sp++;
1997 if(align < cur_align)
1998 cur_align = align;
2000 else{
2001 /* guess the smallest alignment and use that */
2002 align = guess_align(sg.vmaddr);
2003 if(align < cur_align)
2004 cur_align = align;
2007 lcp = (struct load_command *)((char *)lcp + l.cmdsize);
2009 return(cur_align);
2013 * get_align_64 is passed a pointer to a mach_header_64 and size of the object.
2014 * It returns the segment alignment the object was created with. It guesses but
2015 * it is conservative. The maximum alignment is that the link editor will allow
2016 * MAXSECTALIGN and the minimum is the conserative alignment for a long long
2017 * which appears in a mach object files (2^3 worst case for all 64-bit
2018 * machines).
2020 static
2021 uint32_t
2022 get_align_64(
2023 struct mach_header_64 *mhp64,
2024 struct load_command *load_commands,
2025 uint64_t size,
2026 char *name,
2027 enum bool swapped)
2029 uint32_t i, j, cur_align, align;
2030 struct load_command *lcp, l;
2031 struct segment_command_64 *sgp, sg;
2032 struct section_64 *sp, s;
2033 enum byte_sex host_byte_sex;
2036 * Special case ppc64 and x86_64 architectures and return 12.
2037 * We know that with those architectures that the kernel and mmap only
2038 * need file offsets to be page (4096 byte) aligned.
2040 if(mhp64->cputype == CPU_TYPE_POWERPC64 ||
2041 mhp64->cputype == CPU_TYPE_X86_64)
2042 return(12);
2044 * Special case ARM64 and return 14. As it has 16k pages.
2046 if(mhp64->cputype == CPU_TYPE_ARM64)
2047 return(14);
2049 host_byte_sex = get_host_byte_sex();
2051 /* set worst case the link editor uses first */
2052 cur_align = MAXSECTALIGN;
2053 if(mhp64->sizeofcmds + sizeof(struct mach_header_64) > size)
2054 fatal("truncated or malformed object (load commands would "
2055 "extend past the end of the file) in: %s", name);
2056 lcp = load_commands;
2057 for(i = 0; i < mhp64->ncmds; i++){
2058 l = *lcp;
2059 if(swapped)
2060 swap_load_command(&l, host_byte_sex);
2061 if(l.cmdsize % sizeof(long long) != 0)
2062 error("load command %u size not a multiple of "
2063 "sizeof(long long) in: %s", i, name);
2064 if(l.cmdsize <= 0)
2065 fatal("load command %u size is less than or equal to zero "
2066 "in: %s", i, name);
2067 if((char *)lcp + l.cmdsize >
2068 (char *)load_commands + mhp64->sizeofcmds)
2069 fatal("load command %u extends past end of all load "
2070 "commands in: %s", i, name);
2071 if(l.cmd == LC_SEGMENT_64){
2072 sgp = (struct segment_command_64 *)lcp;
2073 sg = *sgp;
2074 if(swapped)
2075 swap_segment_command_64(&sg, host_byte_sex);
2076 if(mhp64->filetype == MH_OBJECT){
2077 /* this is the minimum alignment, then take largest */
2078 align = 3; /* 2^3 sizeof(long long) */
2079 sp = (struct section_64 *)((char *)sgp +
2080 sizeof(struct segment_command_64));
2081 for(j = 0; j < sg.nsects; j++){
2082 s = *sp;
2083 if(swapped)
2084 swap_section_64(&s, 1, host_byte_sex);
2085 if(s.align > align)
2086 align = s.align;
2087 sp++;
2089 if(align < cur_align)
2090 cur_align = align;
2092 else{
2093 /* guess the smallest alignment and use that */
2094 align = guess_align(sg.vmaddr);
2095 if(align < cur_align)
2096 cur_align = align;
2099 lcp = (struct load_command *)((char *)lcp + l.cmdsize);
2101 return(cur_align);
2105 * guess_align is passed a vmaddr of a segment and guesses what the segment
2106 * alignment was. It uses the most conservative guess up to the maximum
2107 * alignment that the link editor uses.
2109 static
2110 uint32_t
2111 guess_align(
2112 uint64_t vmaddr)
2114 uint32_t align;
2115 uint64_t segalign;
2117 if(vmaddr == 0)
2118 return(MAXSECTALIGN);
2120 align = 0;
2121 segalign = 1;
2122 while((segalign & vmaddr) == 0){
2123 segalign = segalign << 1;
2124 align++;
2127 if(align < 2)
2128 return(2);
2129 if(align > MAXSECTALIGN)
2130 return(MAXSECTALIGN);
2132 return(align);
2136 * print_arch() helps implement -info and -detailed_info by printing the
2137 * architecture name for the cputype and cpusubtype.
2139 static
2140 void
2141 print_arch(
2142 cpu_type_t cputype,
2143 cpu_subtype_t cpusubtype)
2145 switch(cputype){
2146 case CPU_TYPE_MC680x0:
2147 switch(cpusubtype & ~CPU_SUBTYPE_MASK){
2148 case CPU_SUBTYPE_MC680x0_ALL:
2149 printf("m68k");
2150 break;
2151 case CPU_SUBTYPE_MC68030_ONLY:
2152 printf("m68030");
2153 break;
2154 case CPU_SUBTYPE_MC68040:
2155 printf("m68040");
2156 break;
2157 default:
2158 goto print_arch_unknown;
2160 break;
2161 case CPU_TYPE_POWERPC:
2162 switch(cpusubtype & ~CPU_SUBTYPE_MASK){
2163 case CPU_SUBTYPE_POWERPC_ALL:
2164 printf("ppc");
2165 break;
2166 case CPU_SUBTYPE_POWERPC_601:
2167 printf("ppc601");
2168 break;
2169 case CPU_SUBTYPE_POWERPC_603:
2170 printf("ppc603");
2171 break;
2172 case CPU_SUBTYPE_POWERPC_603e:
2173 printf("ppc603e");
2174 break;
2175 case CPU_SUBTYPE_POWERPC_603ev:
2176 printf("ppc603ev");
2177 break;
2178 case CPU_SUBTYPE_POWERPC_604:
2179 printf("ppc604");
2180 break;
2181 case CPU_SUBTYPE_POWERPC_604e:
2182 printf("ppc604e");
2183 break;
2184 case CPU_SUBTYPE_POWERPC_750:
2185 printf("ppc750");
2186 break;
2187 case CPU_SUBTYPE_POWERPC_7400:
2188 printf("ppc7400");
2189 break;
2190 case CPU_SUBTYPE_POWERPC_7450:
2191 printf("ppc7450");
2192 break;
2193 case CPU_SUBTYPE_POWERPC_970:
2194 printf("ppc970");
2195 break;
2196 default:
2197 goto print_arch_unknown;
2199 break;
2200 case CPU_TYPE_POWERPC64:
2201 switch(cpusubtype & ~CPU_SUBTYPE_MASK){
2202 case CPU_SUBTYPE_POWERPC_ALL:
2203 printf("ppc64");
2204 break;
2205 case CPU_SUBTYPE_POWERPC_970:
2206 printf("ppc970-64");
2207 break;
2208 default:
2209 goto print_arch_unknown;
2211 break;
2212 case CPU_TYPE_VEO:
2213 switch(cpusubtype & ~CPU_SUBTYPE_MASK){
2214 case CPU_SUBTYPE_VEO_1:
2215 printf("veo1");
2216 break;
2217 case CPU_SUBTYPE_VEO_2:
2218 printf("veo2");
2219 break;
2220 case CPU_SUBTYPE_VEO_3:
2221 printf("veo3");
2222 break;
2223 case CPU_SUBTYPE_VEO_4:
2224 printf("veo4");
2225 break;
2226 default:
2227 goto print_arch_unknown;
2229 break;
2230 case CPU_TYPE_MC88000:
2231 switch(cpusubtype & ~CPU_SUBTYPE_MASK){
2232 case CPU_SUBTYPE_MC88000_ALL:
2233 case CPU_SUBTYPE_MC88110:
2234 printf("m88k");
2235 break;
2236 default:
2237 goto print_arch_unknown;
2239 break;
2240 case CPU_TYPE_I386:
2241 switch(cpusubtype & ~CPU_SUBTYPE_MASK){
2242 case CPU_SUBTYPE_I386_ALL:
2243 /* case CPU_SUBTYPE_386: same as above */
2244 printf("i386");
2245 break;
2246 case CPU_SUBTYPE_486:
2247 printf("i486");
2248 break;
2249 case CPU_SUBTYPE_486SX:
2250 printf("i486SX");
2251 break;
2252 case CPU_SUBTYPE_PENT: /* same as 586 */
2253 printf("pentium");
2254 break;
2255 case CPU_SUBTYPE_PENTPRO:
2256 printf("pentpro");
2257 break;
2258 case CPU_SUBTYPE_PENTII_M3:
2259 printf("pentIIm3");
2260 break;
2261 case CPU_SUBTYPE_PENTII_M5:
2262 printf("pentIIm5");
2263 break;
2264 default:
2265 goto print_arch_unknown;
2267 break;
2268 case CPU_TYPE_X86_64:
2269 switch(cpusubtype & ~CPU_SUBTYPE_MASK){
2270 case CPU_SUBTYPE_X86_64_ALL:
2271 printf("x86_64");
2272 break;
2273 case CPU_SUBTYPE_X86_64_H:
2274 printf("x86_64h");
2275 break;
2276 default:
2277 goto print_arch_unknown;
2279 break;
2280 case CPU_TYPE_I860:
2281 switch(cpusubtype & ~CPU_SUBTYPE_MASK){
2282 case CPU_SUBTYPE_I860_ALL:
2283 case CPU_SUBTYPE_I860_860:
2284 printf("i860");
2285 break;
2286 default:
2287 goto print_arch_unknown;
2289 break;
2290 case CPU_TYPE_HPPA:
2291 switch(cpusubtype & ~CPU_SUBTYPE_MASK){
2292 case CPU_SUBTYPE_HPPA_ALL:
2293 case CPU_SUBTYPE_HPPA_7100LC:
2294 printf("hppa");
2295 break;
2296 default:
2297 goto print_arch_unknown;
2299 break;
2300 case CPU_TYPE_SPARC:
2301 switch(cpusubtype & ~CPU_SUBTYPE_MASK){
2302 case CPU_SUBTYPE_SPARC_ALL:
2303 printf("sparc");
2304 break;
2305 default:
2306 goto print_arch_unknown;
2308 break;
2309 case CPU_TYPE_ARM:
2310 switch(cpusubtype){
2311 case CPU_SUBTYPE_ARM_ALL:
2312 printf("arm");
2313 break;
2314 case CPU_SUBTYPE_ARM_V4T:
2315 printf("armv4t");
2316 break;
2317 case CPU_SUBTYPE_ARM_V5TEJ:
2318 printf("armv5");
2319 break;
2320 case CPU_SUBTYPE_ARM_XSCALE:
2321 printf("xscale");
2322 break;
2323 case CPU_SUBTYPE_ARM_V6:
2324 printf("armv6");
2325 break;
2326 case CPU_SUBTYPE_ARM_V6M:
2327 printf("armv6m");
2328 break;
2329 case CPU_SUBTYPE_ARM_V7:
2330 printf("armv7");
2331 break;
2332 case CPU_SUBTYPE_ARM_V7F:
2333 printf("armv7f");
2334 break;
2335 case CPU_SUBTYPE_ARM_V7S:
2336 printf("armv7s");
2337 break;
2338 case CPU_SUBTYPE_ARM_V7K:
2339 printf("armv7k");
2340 break;
2341 case CPU_SUBTYPE_ARM_V7M:
2342 printf("armv7m");
2343 break;
2344 case CPU_SUBTYPE_ARM_V7EM:
2345 printf("armv7em");
2346 break;
2347 default:
2348 goto print_arch_unknown;
2350 break;
2351 case CPU_TYPE_ARM64:
2352 switch(cpusubtype & ~CPU_SUBTYPE_MASK){
2353 case CPU_SUBTYPE_ARM64_ALL:
2354 printf("arm64");
2355 break;
2356 case CPU_SUBTYPE_ARM64_V8:
2357 printf("arm64v8");
2358 break;
2359 default:
2360 goto print_arch_unknown;
2362 break;
2363 case CPU_TYPE_ANY:
2364 switch(cpusubtype & ~CPU_SUBTYPE_MASK){
2365 case CPU_SUBTYPE_MULTIPLE:
2366 printf("any");
2367 break;
2368 case CPU_SUBTYPE_LITTLE_ENDIAN:
2369 printf("little");
2370 break;
2371 case CPU_SUBTYPE_BIG_ENDIAN:
2372 printf("big");
2373 break;
2374 default:
2375 goto print_arch_unknown;
2377 break;
2378 print_arch_unknown:
2379 default:
2380 printf("(cputype (%d) cpusubtype (%d))", cputype,
2381 cpusubtype & ~CPU_SUBTYPE_MASK);
2382 break;
2387 * print_cputype() helps implement -detailed_info by printing the cputype and
2388 * cpusubtype (symbolicly for the one's it knows about).
2390 static
2391 void
2392 print_cputype(
2393 cpu_type_t cputype,
2394 cpu_subtype_t cpusubtype)
2396 switch(cputype){
2397 case CPU_TYPE_MC680x0:
2398 switch(cpusubtype & ~CPU_SUBTYPE_MASK){
2399 case CPU_SUBTYPE_MC680x0_ALL:
2400 printf(" cputype CPU_TYPE_MC680x0\n"
2401 " cpusubtype CPU_SUBTYPE_MC680x0_ALL\n");
2402 break;
2403 case CPU_SUBTYPE_MC68030_ONLY:
2404 printf(" cputype CPU_TYPE_MC680x0\n"
2405 " cpusubtype CPU_SUBTYPE_MC68030_ONLY\n");
2406 break;
2407 case CPU_SUBTYPE_MC68040:
2408 printf(" cputype CPU_TYPE_MC680x0\n"
2409 " cpusubtype CPU_SUBTYPE_MC68040\n");
2410 break;
2411 default:
2412 goto print_arch_unknown;
2414 break;
2415 case CPU_TYPE_POWERPC:
2416 switch(cpusubtype & ~CPU_SUBTYPE_MASK){
2417 case CPU_SUBTYPE_POWERPC_ALL:
2418 printf(" cputype CPU_TYPE_POWERPC\n"
2419 " cpusubtype CPU_SUBTYPE_POWERPC_ALL\n");
2420 break;
2421 case CPU_SUBTYPE_POWERPC_601:
2422 printf(" cputype CPU_TYPE_POWERPC\n"
2423 " cpusubtype CPU_SUBTYPE_POWERPC_601\n");
2424 break;
2425 case CPU_SUBTYPE_POWERPC_603:
2426 printf(" cputype CPU_TYPE_POWERPC\n"
2427 " cpusubtype CPU_SUBTYPE_POWERPC_603\n");
2428 break;
2429 case CPU_SUBTYPE_POWERPC_603e:
2430 printf(" cputype CPU_TYPE_POWERPC\n"
2431 " cpusubtype CPU_SUBTYPE_POWERPC_603e\n");
2432 break;
2433 case CPU_SUBTYPE_POWERPC_603ev:
2434 printf(" cputype CPU_TYPE_POWERPC\n"
2435 " cpusubtype CPU_SUBTYPE_POWERPC_603ev\n");
2436 break;
2437 case CPU_SUBTYPE_POWERPC_604:
2438 printf(" cputype CPU_TYPE_POWERPC\n"
2439 " cpusubtype CPU_SUBTYPE_POWERPC_604\n");
2440 break;
2441 case CPU_SUBTYPE_POWERPC_604e:
2442 printf(" cputype CPU_TYPE_POWERPC\n"
2443 " cpusubtype CPU_SUBTYPE_POWERPC_604e\n");
2444 break;
2445 case CPU_SUBTYPE_POWERPC_750:
2446 printf(" cputype CPU_TYPE_POWERPC\n"
2447 " cpusubtype CPU_SUBTYPE_POWERPC_750\n");
2448 break;
2449 case CPU_SUBTYPE_POWERPC_7400:
2450 printf(" cputype CPU_TYPE_POWERPC\n"
2451 " cpusubtype CPU_SUBTYPE_POWERPC_7400\n");
2452 break;
2453 case CPU_SUBTYPE_POWERPC_7450:
2454 printf(" cputype CPU_TYPE_POWERPC\n"
2455 " cpusubtype CPU_SUBTYPE_POWERPC_7450\n");
2456 break;
2457 case CPU_SUBTYPE_POWERPC_970:
2458 printf(" cputype CPU_TYPE_POWERPC\n"
2459 " cpusubtype CPU_SUBTYPE_POWERPC_970\n");
2460 break;
2461 default:
2462 goto print_arch_unknown;
2464 break;
2465 case CPU_TYPE_POWERPC64:
2466 switch(cpusubtype & ~CPU_SUBTYPE_MASK){
2467 case CPU_SUBTYPE_POWERPC_ALL:
2468 printf(" cputype CPU_TYPE_POWERPC64\n"
2469 " cpusubtype CPU_SUBTYPE_POWERPC_ALL\n");
2470 break;
2471 case CPU_SUBTYPE_POWERPC_970:
2472 printf(" cputype CPU_TYPE_POWERPC64\n"
2473 " cpusubtype CPU_SUBTYPE_POWERPC_970\n");
2474 break;
2475 default:
2476 goto print_arch_unknown;
2478 break;
2479 case CPU_TYPE_VEO:
2480 switch(cpusubtype & ~CPU_SUBTYPE_MASK){
2481 case CPU_SUBTYPE_VEO_1:
2482 printf(" cputype CPU_TYPE_VEO\n"
2483 " cpusubtype CPU_SUBTYPE_VEO_1\n");
2484 break;
2485 case CPU_SUBTYPE_VEO_2:
2486 printf(" cputype CPU_TYPE_VEO\n"
2487 " cpusubtype CPU_SUBTYPE_VEO_2\n");
2488 break;
2489 case CPU_SUBTYPE_VEO_3:
2490 printf(" cputype CPU_TYPE_VEO\n"
2491 " cpusubtype CPU_SUBTYPE_VEO_3\n");
2492 break;
2493 case CPU_SUBTYPE_VEO_4:
2494 printf(" cputype CPU_TYPE_VEO\n"
2495 " cpusubtype CPU_SUBTYPE_VEO_4\n");
2496 break;
2497 default:
2498 goto print_arch_unknown;
2500 break;
2501 case CPU_TYPE_MC88000:
2502 switch(cpusubtype & ~CPU_SUBTYPE_MASK){
2503 case CPU_SUBTYPE_MC88000_ALL:
2504 printf(" cputype CPU_TYPE_MC88000\n"
2505 " cpusubtype CPU_SUBTYPE_MC88000_ALL\n");
2506 break;
2507 case CPU_SUBTYPE_MC88110:
2508 printf(" cputype CPU_TYPE_MC88000\n"
2509 " cpusubtype CPU_SUBTYPE_MC88110\n");
2510 break;
2511 default:
2512 goto print_arch_unknown;
2514 break;
2515 case CPU_TYPE_I386:
2516 switch(cpusubtype & ~CPU_SUBTYPE_MASK){
2517 case CPU_SUBTYPE_I386_ALL:
2518 /* case CPU_SUBTYPE_386: same as above */
2519 printf(" cputype CPU_TYPE_I386\n"
2520 " cpusubtype CPU_SUBTYPE_I386_ALL\n");
2521 break;
2522 case CPU_SUBTYPE_486:
2523 printf(" cputype CPU_TYPE_I386\n"
2524 " cpusubtype CPU_SUBTYPE_486\n");
2525 break;
2526 case CPU_SUBTYPE_486SX:
2527 printf(" cputype CPU_TYPE_I386\n"
2528 " cpusubtype CPU_SUBTYPE_486SX\n");
2529 break;
2530 case CPU_SUBTYPE_PENT: /* same as 586 */
2531 printf(" cputype CPU_TYPE_I386\n"
2532 " cpusubtype CPU_SUBTYPE_PENT\n");
2533 break;
2534 case CPU_SUBTYPE_PENTPRO:
2535 printf(" cputype CPU_TYPE_I386\n"
2536 " cpusubtype CPU_SUBTYPE_PENTPRO\n");
2537 break;
2538 case CPU_SUBTYPE_PENTII_M3:
2539 printf(" cputype CPU_TYPE_I386\n"
2540 " cpusubtype CPU_SUBTYPE_PENTII_M3\n");
2541 break;
2542 case CPU_SUBTYPE_PENTII_M5:
2543 printf(" cputype CPU_TYPE_I386\n"
2544 " cpusubtype CPU_SUBTYPE_PENTII_M5\n");
2545 break;
2546 default:
2547 goto print_arch_unknown;
2549 break;
2550 case CPU_TYPE_X86_64:
2551 switch(cpusubtype & ~CPU_SUBTYPE_MASK){
2552 case CPU_SUBTYPE_X86_64_ALL:
2553 printf(" cputype CPU_TYPE_X86_64\n"
2554 " cpusubtype CPU_SUBTYPE_X86_64_ALL\n");
2555 break;
2556 case CPU_SUBTYPE_X86_64_H:
2557 printf(" cputype CPU_TYPE_X86_64\n"
2558 " cpusubtype CPU_SUBTYPE_X86_64_H\n");
2559 break;
2560 default:
2561 goto print_arch_unknown;
2563 break;
2564 case CPU_TYPE_I860:
2565 switch(cpusubtype & ~CPU_SUBTYPE_MASK){
2566 case CPU_SUBTYPE_I860_ALL:
2567 printf(" cputype CPU_TYPE_I860\n"
2568 " cpusubtype CPU_SUBTYPE_I860_ALL\n");
2569 break;
2570 case CPU_SUBTYPE_I860_860:
2571 printf(" cputype CPU_TYPE_I860\n"
2572 " cpusubtype CPU_SUBTYPE_I860_860\n");
2573 break;
2574 default:
2575 goto print_arch_unknown;
2577 break;
2578 case CPU_TYPE_HPPA:
2579 switch(cpusubtype & ~CPU_SUBTYPE_MASK){
2580 case CPU_SUBTYPE_HPPA_ALL:
2581 printf(" cputype CPU_TYPE_HPPA\n"
2582 " cpusubtype CPU_SUBTYPE_HPPA_ALL\n");
2583 break;
2584 case CPU_SUBTYPE_HPPA_7100LC:
2585 printf(" cputype CPU_TYPE_HPPA\n"
2586 " cpusubtype CPU_SUBTYPE_HPPA_7100LC\n");
2587 break;
2588 default:
2589 goto print_arch_unknown;
2591 break;
2592 case CPU_TYPE_SPARC:
2593 switch(cpusubtype & ~CPU_SUBTYPE_MASK){
2594 case CPU_SUBTYPE_SPARC_ALL:
2595 printf(" cputype CPU_TYPE_SPARC\n"
2596 " cpusubtype CPU_SUBTYPE_SPARC_ALL\n");
2597 break;
2598 default:
2599 goto print_arch_unknown;
2601 break;
2602 case CPU_TYPE_ARM:
2603 switch(cpusubtype){
2604 case CPU_SUBTYPE_ARM_V4T:
2605 printf(" cputype CPU_TYPE_ARM\n"
2606 " cpusubtype CPU_SUBTYPE_ARM_V4T\n");
2607 break;
2608 case CPU_SUBTYPE_ARM_V5TEJ:
2609 printf(" cputype CPU_TYPE_ARM\n"
2610 " cpusubtype CPU_SUBTYPE_ARM_V5TEJ\n");
2611 break;
2612 case CPU_SUBTYPE_ARM_XSCALE:
2613 printf(" cputype CPU_TYPE_ARM\n"
2614 " cpusubtype CPU_SUBTYPE_ARM_XSCALE\n");
2615 break;
2616 case CPU_SUBTYPE_ARM_V6:
2617 printf(" cputype CPU_TYPE_ARM\n"
2618 " cpusubtype CPU_SUBTYPE_ARM_V6\n");
2619 break;
2620 case CPU_SUBTYPE_ARM_V6M:
2621 printf(" cputype CPU_TYPE_ARM\n"
2622 " cpusubtype CPU_SUBTYPE_ARM_V6M\n");
2623 break;
2624 case CPU_SUBTYPE_ARM_V7:
2625 printf(" cputype CPU_TYPE_ARM\n"
2626 " cpusubtype CPU_SUBTYPE_ARM_V7\n");
2627 break;
2628 case CPU_SUBTYPE_ARM_V7F:
2629 printf(" cputype CPU_TYPE_ARM\n"
2630 " cpusubtype CPU_SUBTYPE_ARM_V7F\n");
2631 break;
2632 case CPU_SUBTYPE_ARM_V7S:
2633 printf(" cputype CPU_TYPE_ARM\n"
2634 " cpusubtype CPU_SUBTYPE_ARM_V7S\n");
2635 break;
2636 case CPU_SUBTYPE_ARM_V7K:
2637 printf(" cputype CPU_TYPE_ARM\n"
2638 " cpusubtype CPU_SUBTYPE_ARM_V7K\n");
2639 break;
2640 case CPU_SUBTYPE_ARM_V7M:
2641 printf(" cputype CPU_TYPE_ARM\n"
2642 " cpusubtype CPU_SUBTYPE_ARM_V7M\n");
2643 break;
2644 case CPU_SUBTYPE_ARM_V7EM:
2645 printf(" cputype CPU_TYPE_ARM\n"
2646 " cpusubtype CPU_SUBTYPE_ARM_V7EM\n");
2647 break;
2648 case CPU_SUBTYPE_ARM_ALL:
2649 printf(" cputype CPU_TYPE_ARM\n"
2650 " cpusubtype CPU_SUBTYPE_ARM_ALL\n");
2651 break;
2652 default:
2653 goto print_arch_unknown;
2655 break;
2656 case CPU_TYPE_ARM64:
2657 switch(cpusubtype & ~CPU_SUBTYPE_MASK){
2658 case CPU_SUBTYPE_ARM64_ALL:
2659 printf(" cputype CPU_TYPE_ARM64\n"
2660 " cpusubtype CPU_SUBTYPE_ARM64_ALL\n");
2661 break;
2662 case CPU_SUBTYPE_ARM64_V8:
2663 printf(" cputype CPU_TYPE_ARM64\n"
2664 " cpusubtype CPU_SUBTYPE_ARM64_V8\n");
2665 break;
2666 default:
2667 goto print_arch_unknown;
2669 break;
2670 case CPU_TYPE_ANY:
2671 switch(cpusubtype & ~CPU_SUBTYPE_MASK){
2672 case CPU_SUBTYPE_MULTIPLE:
2673 printf(" cputype CPU_TYPE_ANY\n"
2674 " cpusubtype CPU_SUBTYPE_MULTIPLE\n");
2675 break;
2676 case CPU_SUBTYPE_LITTLE_ENDIAN:
2677 printf(" cputype CPU_TYPE_ANY\n"
2678 " cpusubtype CPU_SUBTYPE_LITTLE_ENDIAN\n");
2679 break;
2680 case CPU_SUBTYPE_BIG_ENDIAN:
2681 printf(" cputype CPU_TYPE_ANY\n"
2682 " cpusubtype CPU_SUBTYPE_BIG_ENDIAN\n");
2683 break;
2684 default:
2685 goto print_arch_unknown;
2687 break;
2688 print_arch_unknown:
2689 default:
2690 printf(" cputype (%d)\n"
2691 " cpusubtype cpusubtype (%d)\n", cputype,
2692 cpusubtype & ~CPU_SUBTYPE_MASK);
2693 break;
2698 * size_ar_name is used to return the size of the name of an archive member
2699 * for printing it without blanks (with printf string "%.*s").
2701 static
2703 size_ar_name(
2704 char *ar_name)
2706 uint32_t j;
2707 struct ar_hdr ar_hdr;
2709 for(j = 0; j < sizeof(ar_hdr.ar_name); j++){
2710 if(ar_name[j] == ' ')
2711 break;
2713 return(j);
2717 * Create a new input file struct, clear it and return it.
2719 static
2720 struct input_file *
2721 new_input(void)
2723 struct input_file *input;
2725 input_files = reallocate(input_files,
2726 (ninput_files + 1) * sizeof(struct input_file));
2727 input = input_files + ninput_files;
2728 ninput_files++;
2729 memset(input, '\0', sizeof(struct input_file));
2730 return(input);
2734 * Create a new thin file struct, clear it and return it.
2736 static
2737 struct thin_file *
2738 new_thin(void)
2740 struct thin_file *thin;
2742 thin_files = reallocate(thin_files,
2743 (nthin_files + 1) * sizeof(struct thin_file));
2744 thin = thin_files + nthin_files;
2745 nthin_files++;
2746 memset(thin, '\0', sizeof(struct thin_file));
2747 return(thin);
2751 * Create a new arch_flag struct on the specified list, clear it and return it.
2753 static
2754 struct arch_flag *
2755 new_arch_flag(
2756 struct arch_flag **arch_flags,
2757 uint32_t *narch_flags)
2759 struct arch_flag *arch_flag;
2761 *arch_flags = reallocate(*arch_flags,
2762 (*narch_flags + 1) * sizeof(struct arch_flag));
2763 arch_flag = *arch_flags + *narch_flags;
2764 *narch_flags = *narch_flags + 1;
2765 memset(arch_flag, '\0', sizeof(struct arch_flag));
2766 return(arch_flag);
2770 * Create a new replace struct, clear it and return it.
2772 static
2773 struct replace *
2774 new_replace(void)
2776 struct replace *replace;
2778 replaces = reallocate(replaces,
2779 (nreplaces + 1) * sizeof(struct replace));
2780 replace = replaces + nreplaces;
2781 nreplaces++;
2782 memset(replace, '\0', sizeof(struct replace));
2783 return(replace);
2787 * Create a new segalign struct, clear it and return it.
2789 static
2790 struct segalign *
2791 new_segalign(void)
2793 struct segalign *segalign;
2795 segaligns = reallocate(segaligns,
2796 (nsegaligns + 1) * sizeof(struct segalign));
2797 segalign = segaligns + nsegaligns;
2798 nsegaligns++;
2799 memset(segalign, '\0', sizeof(struct segalign));
2800 return(segalign);
2804 * Function for qsort for comparing thin file's alignment
2806 static
2808 cmp_qsort(
2809 const struct thin_file *thin1,
2810 const struct thin_file *thin2)
2812 return(thin1->align - thin2->align);
2816 * rnd() rounds v to a multiple of r.
2818 static
2819 uint64_t
2820 rnd(
2821 uint64_t v,
2822 uint64_t r)
2824 r--;
2825 v += r;
2826 v &= ~(int64_t)r;
2827 return(v);
2831 * ispoweroftwo() returns TRUE or FALSE depending if x is a power of two.
2833 static
2834 enum
2835 bool
2836 ispoweroftwo(
2837 uint32_t x)
2839 if(x == 0)
2840 return(TRUE);
2841 while((x & 0x1) != 0x1){
2842 x >>= 1;
2844 if((x & ~0x1) != 0)
2845 return(FALSE);
2846 else
2847 return(TRUE);
2851 * check_arch is called when an input file is specified with a -arch flag input
2852 * and that the architecture can be determined from the input to check that
2853 * both architectures match.
2855 static
2856 void
2857 check_arch(
2858 struct input_file *input,
2859 struct thin_file *thin)
2861 if(input->arch_flag.cputype != thin->cputype)
2862 fatal("specifed architecture type (%s) for file (%s) does "
2863 "not match its cputype (%d) and cpusubtype (%d) "
2864 "(should be cputype (%d) and cpusubtype (%d))",
2865 input->arch_flag.name, input->name,
2866 thin->cputype, thin->cpusubtype &
2867 ~CPU_SUBTYPE_MASK, input->arch_flag.cputype,
2868 input->arch_flag.cpusubtype & ~CPU_SUBTYPE_MASK);
2872 * Create a blank dylib. This is a stub dylib with no load commands.
2873 * It is a target page size block of bytes of zero except for the mach_header.
2875 static
2876 struct thin_file *
2877 new_blank_dylib(
2878 struct arch_flag *arch)
2880 uint32_t target_page_size, align, onebit;
2881 struct thin_file *file;
2882 enum byte_sex host_byte_sex, target_byte_sex;
2883 struct mach_header *mh;
2884 struct mach_header_64 *mh64;
2886 file = new_thin();
2887 file->name = "blank dylib";
2888 target_page_size = get_segalign_from_flag(arch);
2889 file->addr = allocate(target_page_size);
2890 memset(file->addr, '\0', target_page_size);
2891 file->cputype = arch->cputype;
2892 file->cpusubtype = arch->cpusubtype;
2893 file->offset = 0;
2894 file->size = target_page_size;
2895 onebit = 1;
2896 for(align = 1; (target_page_size & onebit) != onebit; align++)
2897 onebit = onebit << 1;
2898 file->align = align;
2900 host_byte_sex = get_host_byte_sex();
2901 target_byte_sex = get_byte_sex_from_flag(arch);
2903 if((arch->cputype & CPU_ARCH_ABI64) == CPU_ARCH_ABI64){
2904 mh64 = (struct mach_header_64 *)file->addr;
2905 mh64->magic = MH_MAGIC_64;
2906 mh64->cputype = arch->cputype;
2907 mh64->cpusubtype = arch->cpusubtype;
2908 mh64->filetype = MH_DYLIB_STUB;
2909 if(target_byte_sex != host_byte_sex)
2910 swap_mach_header_64(mh64, target_byte_sex);
2912 else{
2913 mh = (struct mach_header *)file->addr;
2914 mh->magic = MH_MAGIC;
2915 mh->cputype = arch->cputype;
2916 mh->cpusubtype = arch->cpusubtype;
2917 mh->filetype = MH_DYLIB_STUB;
2918 if(target_byte_sex != host_byte_sex)
2919 swap_mach_header(mh, target_byte_sex);
2921 return(file);
2925 * Print the current usage line and exit (by calling fatal).
2927 static
2928 void
2929 usage(void)
2931 fatal("Usage: %s [input_file] ... [-arch <arch_type> input_file] ... "
2932 "[-info] [-detailed_info] [-output output_file] [-create] "
2933 "[-arch_blank <arch_type>] [-thin <arch_type>] "
2934 "[-remove <arch_type>] ... [-extract <arch_type>] ... "
2935 "[-extract_family <arch_type>] ... "
2936 "[-verify_arch <arch_type> ...] "
2937 "[-replace <arch_type> <file_name>] ...", progname);