2 * Copyright (c) 1999 Apple Computer, Inc. All rights reserved.
4 * @APPLE_LICENSE_HEADER_START@
6 * This file contains Original Code and/or Modifications of Original Code
7 * as defined in and that are subject to the Apple Public Source License
8 * Version 2.0 (the 'License'). You may not use this file except in
9 * compliance with the License. Please obtain a copy of the License at
10 * http://www.opensource.apple.com/apsl/ and read it before using this
13 * The Original Code and all software distributed under the License are
14 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
15 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
16 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
17 * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
18 * Please see the License for the specific language governing rights and
19 * limitations under the License.
21 * @APPLE_LICENSE_HEADER_END@
24 * The lipo(1) program. This program creates, thins and operates on fat files.
25 * This program takes the following options:
31 * -arch <arch_type> <input_file>
32 * -arch_blank <arch_type>
34 * -extract <arch_type>
36 * -replace <arch_type> <file_name>
37 * -segalign <arch_type> <value>
38 * -verify_arch <arch_type> ...
45 #define AR_EFMT1 "#1/" /* extended format #1 */
55 #include <sys/types.h>
58 #include <mach/mach.h>
59 #include <mach-o/loader.h>
60 #include <mach-o/fat.h>
61 #include "stuff/arch.h"
62 #include "stuff/errors.h"
63 #include "stuff/allocate.h"
65 /* The maximum section alignment allowed to be specified, as a power of two */
66 #define MAXSECTALIGN 15 /* 2**15 or 0x8000 */
68 /* These #undef's are because of the #define's in <mach.h> */
72 /* name of the program for error messages (argv[0]) */
73 char *progname
= NULL
;
75 /* names and types (if any) of input file specified on the commmand line */
78 struct arch_flag arch_flag
;
79 struct fat_header
*fat_header
;
80 struct fat_arch
*fat_arches
;
83 static struct input_file
*input_files
= NULL
;
84 static uint32_t ninput_files
= 0;
86 /* Thin files from the input files to operate on */
90 struct fat_arch fat_arch
;
96 static struct thin_file
*thin_files
= NULL
;
97 static uint32_t nthin_files
= 0;
99 /* The specified output file */
100 static char *output_file
= NULL
;
101 static uint32_t output_filemode
= 0;
103 static struct utimbuf output_timep
= { 0 };
105 static time_t output_timep
[2] = { 0 };
107 static enum bool archives_in_input
= FALSE
;
109 /* flags set from command line arguments to specify the operation */
110 static enum bool create_flag
= FALSE
;
111 static enum bool info_flag
= FALSE
;
112 static enum bool detailed_info_flag
= FALSE
;
114 static enum bool thin_flag
= FALSE
;
115 static struct arch_flag thin_arch_flag
= { 0 };
117 static enum bool remove_flag
= FALSE
;
118 static struct arch_flag
*remove_arch_flags
= NULL
;
119 static uint32_t nremove_arch_flags
= 0;
121 static enum bool extract_flag
= FALSE
;
122 static struct arch_flag
*extract_arch_flags
= NULL
;
123 static uint32_t nextract_arch_flags
= 0;
124 static enum bool extract_family_flag
= FALSE
;
126 static enum bool replace_flag
= FALSE
;
128 struct arch_flag arch_flag
;
129 struct thin_file thin_file
;
131 static struct replace
*replaces
= NULL
;
132 static uint32_t nreplaces
= 0;
135 struct arch_flag arch_flag
;
138 static struct segalign
*segaligns
= NULL
;
139 static uint32_t nsegaligns
= 0;
141 static enum bool arch_blank_flag
= FALSE
;
143 static struct fat_header fat_header
= { 0 };
145 static enum bool verify_flag
= FALSE
;
146 static struct arch_flag
*verify_archs
= NULL
;
147 static uint32_t nverify_archs
= 0;
149 static void create_fat(
151 static void process_input_file(
152 struct input_file
*input
);
153 static void process_replace_file(
154 struct replace
*replace
);
155 static void check_archive(
160 cpu_subtype_t
*cpusubtype
);
161 static void check_extend_format_1(
163 struct ar_hdr
*ar_hdr
,
165 uint32_t *member_name_size
);
166 static uint32_t get_align(
167 struct mach_header
*mhp
,
168 struct load_command
*load_commands
,
172 static uint32_t get_align_64(
173 struct mach_header_64
*mhp64
,
174 struct load_command
*load_commands
,
178 static uint32_t guess_align(
180 static void print_arch(
181 struct fat_arch
*fat_arch
);
182 static void print_cputype(
184 cpu_subtype_t cpusubtype
);
185 static int size_ar_name(
187 static struct input_file
*new_input(
189 static struct thin_file
*new_thin(
191 static struct arch_flag
*new_arch_flag(
192 struct arch_flag
**arch_flags
,
193 uint32_t *narch_flags
);
194 static struct replace
*new_replace(
196 static struct segalign
*new_segalign(
198 static int cmp_qsort(
199 const struct thin_file
*thin1
,
200 const struct thin_file
*thin2
);
201 static uint32_t round(
204 static enum bool ispoweroftwo(
206 static void check_arch(
207 struct input_file
*input
,
208 struct thin_file
*thin
);
211 static struct thin_file
*new_blank_dylib(
212 struct arch_flag
*arch
);
221 uint32_t i
, j
, k
, value
;
223 struct input_file
*input
;
224 struct arch_flag
*arch_flag
;
225 struct replace
*replace
;
226 struct segalign
*segalign
;
227 const struct arch_flag
*arch_flags
;
229 struct arch_flag blank_arch
;
233 * Process the command line arguments.
236 for(a
= 1; a
< argc
; a
++){
237 if(argv
[a
][0] == '-'){
241 if(strcmp(p
, "arch") == 0 || strcmp(p
, "a") == 0){
243 error("missing argument(s) to %s option", argv
[a
]);
247 if(get_arch_from_flag(argv
[a
+1],
248 &(input
->arch_flag
)) == 0){
249 error("unknown architecture specification flag: %s "
250 "in specifying input file %s %s %s", argv
[a
+1],
251 argv
[a
], argv
[a
+1], argv
[a
+2]);
255 input
->name
= argv
[a
+2];
258 else if(strcmp(p
, "arch_blank") == 0){
259 arch_blank_flag
= TRUE
;
261 error("missing argument(s) to %s option", argv
[a
]);
264 if(get_arch_from_flag(argv
[a
+1], &blank_arch
) == 0){
265 error("unknown architecture specification flag: %s "
266 "in specifying input file %s %s", argv
[a
+1],
271 new_blank_dylib(&blank_arch
);
278 if(strcmp(p
, "create") == 0 || strcmp(p
, "c") == 0){
285 if(strcmp(p
, "detailed_info") == 0 || strcmp(p
, "d") == 0){
286 detailed_info_flag
= TRUE
;
292 if(strcmp(p
, "extract") == 0 ||
293 strcmp(p
, "extract_family") == 0 ||
294 strcmp(p
, "e") == 0){
296 if(strcmp(p
, "extract_family") == 0)
297 extract_family_flag
= TRUE
;
299 error("missing argument to %s option", argv
[a
]);
302 arch_flag
= new_arch_flag(&extract_arch_flags
,
303 &nextract_arch_flags
);
304 if(get_arch_from_flag(argv
[a
+1], arch_flag
) == 0){
305 error("unknown architecture specification flag: "
306 "%s in specifying extract operation: %s %s",
307 argv
[a
+1], argv
[a
], argv
[a
+1]);
317 if(strcmp(p
, "info") == 0 || strcmp(p
, "i") == 0){
324 if(strcmp(p
, "output") == 0 || strcmp(p
, "o") == 0){
326 error("missing argument to %s option", argv
[a
]);
329 if(output_file
!= NULL
)
330 fatal("more than one %s option specified", argv
[a
]);
331 output_file
= argv
[a
+ 1];
338 if(strcmp(p
, "remove") == 0 || strcmp(p
, "rem") == 0){
341 error("missing argument to %s option", argv
[a
]);
344 arch_flag
= new_arch_flag(&remove_arch_flags
,
345 &nremove_arch_flags
);
346 if(get_arch_from_flag(argv
[a
+1], arch_flag
) == 0){
347 error("unknown architecture specification flag: "
348 "%s in specifying remove operation: %s %s",
349 argv
[a
+1], argv
[a
], argv
[a
+1]);
355 else if(strcmp(p
, "replace") == 0 || strcmp(p
, "rep") == 0){
358 error("missing argument(s) to %s option", argv
[a
]);
361 replace
= new_replace();
362 if(get_arch_from_flag(argv
[a
+1],
363 &(replace
->arch_flag
)) == 0){
364 error("unknown architecture specification flag: "
365 "%s in specifying replace operation: %s %s %s",
366 argv
[a
+1], argv
[a
], argv
[a
+1], argv
[a
+2]);
370 replace
->thin_file
.name
= argv
[a
+2];
377 if(strcmp(p
, "segalign") == 0 || strcmp(p
, "s") == 0){
379 error("missing argument(s) to %s option", argv
[a
]);
382 segalign
= new_segalign();
383 if(get_arch_from_flag(argv
[a
+1],
384 &(segalign
->arch_flag
)) == 0){
385 error("unknown architecture specification flag: "
386 "%s in specifying segment alignment: %s %s %s",
387 argv
[a
+1], argv
[a
], argv
[a
+1], argv
[a
+2]);
391 value
= strtoul(argv
[a
+2], &endp
, 16);
393 fatal("argument for -segalign <arch_type> %s not a "
394 "proper hexadecimal number", argv
[a
+2]);
395 if(!ispoweroftwo(value
) || value
== 0)
396 fatal("argument to -segalign <arch_type> %x (hex) "
397 "must be a non-zero power of two", value
);
398 if(value
> (1 << MAXSECTALIGN
))
399 fatal("argument to -segalign <arch_type> %x (hex) "
400 "must equal to or less than %x (hex)",
401 value
, (unsigned int)(1 << MAXSECTALIGN
));
403 while((value
& 0x1) != 1){
413 if(strcmp(p
, "thin") == 0 || strcmp(p
, "t") == 0){
414 if(thin_flag
== TRUE
)
415 fatal("more than one %s option specified", argv
[a
]);
418 error("missing argument to %s option", argv
[a
]);
421 if(get_arch_from_flag(argv
[a
+1], &thin_arch_flag
) == 0){
422 error("unknown architecture specification flag: "
423 "%s in specifying thin operation: %s %s",
424 argv
[a
+1], argv
[a
], argv
[a
+1]);
434 if(strcmp(p
, "verify_arch") == 0){
437 error("missing argument(s) to %s option", argv
[a
]);
441 nverify_archs
= argc
- a
;
442 verify_archs
= (struct arch_flag
*)allocate(
443 sizeof(struct arch_flag
) * nverify_archs
);
444 for(i
= 0; a
< argc
; a
++, i
++){
445 if(get_arch_from_flag(argv
[a
],
446 verify_archs
+ i
) == 0){
447 error("unknown architecture specification "
448 "flag: %s in specifying -verify_arch "
449 "operation", argv
[a
]);
460 fatal("unknown flag: %s", argv
[a
]);
465 input
->name
= argv
[a
];
470 * Check to see the specified arguments are valid.
472 if(info_flag
== FALSE
&& detailed_info_flag
== FALSE
&&
473 create_flag
== FALSE
&& thin_flag
== FALSE
&&
474 extract_flag
== FALSE
&& remove_flag
== FALSE
&&
475 replace_flag
== FALSE
&& verify_flag
== FALSE
){
476 error("one of -create, -thin <arch_type>, -extract <arch_type>, "
477 "-remove <arch_type>, -replace <arch_type> <file_name>, "
478 "-verify_arch <arch_type> ... , "
479 "-info or -detailed_info must be specified");
482 if((create_flag
== TRUE
|| thin_flag
== TRUE
|| extract_flag
== TRUE
||
483 remove_flag
== TRUE
|| replace_flag
== TRUE
) &&
484 output_file
== NULL
){
485 error("no output file specified");
488 if(ninput_files
== 0){
489 error("no input files specified");
492 if(verify_flag
== TRUE
&& ninput_files
!= 1){
493 error("only one input file allowed with -verify_arch");
496 if(create_flag
+ thin_flag
+ extract_flag
+ remove_flag
+ replace_flag
+
497 info_flag
+ detailed_info_flag
+ verify_flag
> 1){
498 error("only one of -create, -thin <arch_type>, -extract <arch_type>"
499 ", -remove <arch_type>, -replace <arch_type> <file_name>, "
500 "-verify_arch <arch_type> ..., "
501 "-info or -detailed_info can be specified");
504 if(arch_blank_flag
== TRUE
&& create_flag
== FALSE
){
505 error("-arch_blank may only be used with -create");
510 * Determine the types of the input files.
512 for(i
= 0; i
< ninput_files
; i
++)
513 process_input_file(input_files
+ i
);
516 * Do the specified operation.
520 /* check to make sure no two files have the same architectures */
521 for(i
= 0; i
< nthin_files
; i
++)
522 for(j
= i
+ 1; j
< nthin_files
; j
++)
523 if(thin_files
[i
].fat_arch
.cputype
==
524 thin_files
[j
].fat_arch
.cputype
&&
525 (thin_files
[i
].fat_arch
.cpusubtype
& ~CPU_SUBTYPE_MASK
)==
526 (thin_files
[j
].fat_arch
.cpusubtype
& ~CPU_SUBTYPE_MASK
)){
527 arch_flags
= get_arch_flags();
528 for(k
= 0; arch_flags
[k
].name
!= NULL
; k
++){
529 if(arch_flags
[k
].cputype
==
530 thin_files
[j
].fat_arch
.cputype
&&
531 (arch_flags
[k
].cpusubtype
&
532 ~CPU_SUBTYPE_MASK
) ==
533 (thin_files
[j
].fat_arch
.cpusubtype
&
535 fatal("%s and %s have the same architectures (%s) "
536 "and can't be in the same fat output file",
537 thin_files
[i
].name
, thin_files
[j
].name
,
540 fatal("%s and %s have the same architectures (cputype "
541 "(%d) and cpusubtype (%d)) and can't be in the "
542 "same fat output file", thin_files
[i
].name
,
543 thin_files
[j
].name
,thin_files
[i
].fat_arch
.cputype
,
544 thin_files
[i
].fat_arch
.cpusubtype
&
551 if(ninput_files
!= 1)
552 fatal("only one input file can be specified with the -thin "
554 if(input_files
[0].fat_header
== NULL
)
555 fatal("input file (%s) must be a fat file when the -thin "
556 "option is specified", input_files
[0].name
);
557 for(i
= 0; i
< nthin_files
; i
++){
558 if(thin_files
[i
].fat_arch
.cputype
== thin_arch_flag
.cputype
&&
559 (thin_files
[i
].fat_arch
.cpusubtype
& ~CPU_SUBTYPE_MASK
) ==
560 (thin_arch_flag
.cpusubtype
& ~CPU_SUBTYPE_MASK
)){
561 (void)unlink(output_file
);
562 if((fd
= open(output_file
, O_WRONLY
| O_CREAT
| O_TRUNC
,
563 output_filemode
)) == -1)
564 system_fatal("can't create output file: %s",
567 if(write(fd
, thin_files
[i
].addr
,thin_files
[i
].fat_arch
.size
)
568 != (int)(thin_files
[i
].fat_arch
.size
))
569 system_fatal("can't write thin file to output file: %s",
572 system_fatal("can't close output file: %s",output_file
);
573 if(utime(output_file
,
575 &output_timep
) == -1)
579 system_fatal("can't set the modifiy times for "
580 "output file: %s", output_file
);
585 fatal("fat input file (%s) does not contain the specified "
586 "architecture (%s) to thin it to", input
->name
,
587 thin_arch_flag
.name
);
591 if(ninput_files
!= 1)
592 fatal("only one input file can be specified with the -extract "
594 if(input_files
[0].fat_header
== NULL
)
595 fatal("input file (%s) must be a fat file when the -extract "
596 "option is specified", input_files
[0].name
);
597 for(i
= 0; i
< nextract_arch_flags
; i
++){
598 for(j
= i
+ 1; j
< nextract_arch_flags
; j
++){
599 if(extract_arch_flags
[i
].cputype
==
600 extract_arch_flags
[j
].cputype
&&
601 (extract_arch_flags
[i
].cpusubtype
& ~CPU_SUBTYPE_MASK
) ==
602 (thin_files
[j
].fat_arch
.cpusubtype
& ~CPU_SUBTYPE_MASK
))
603 fatal("-extract %s specified multiple times",
604 extract_arch_flags
[i
].name
);
607 /* mark those thin files for extraction */
608 for(i
= 0; i
< nextract_arch_flags
; i
++){
610 for(j
= 0; j
< nthin_files
; j
++){
611 if(extract_arch_flags
[i
].cputype
==
612 thin_files
[j
].fat_arch
.cputype
&&
613 ((extract_arch_flags
[i
].cpusubtype
&
615 (thin_files
[j
].fat_arch
.cpusubtype
&
616 ~CPU_SUBTYPE_MASK
) ||
617 extract_family_flag
== TRUE
)){
618 thin_files
[j
].extract
= TRUE
;
623 fatal("-extract %s specified but fat file: %s does not "
624 "contain that architecture",
625 extract_arch_flags
[i
].name
, input_files
[0].name
);
627 /* remove those thin files not marked for extraction */
628 for(i
= 0; i
< nthin_files
; ){
629 if(thin_files
[i
].extract
== FALSE
){
630 for(j
= i
; j
< nthin_files
- 1; j
++)
631 thin_files
[j
] = thin_files
[j
+ 1];
641 if(ninput_files
!= 1)
642 fatal("only one input file can be specified with the -remove "
644 if(input_files
[0].fat_header
== NULL
)
645 fatal("input file (%s) must be a fat file when the -remove "
646 "option is specified", input_files
[0].name
);
647 for(i
= 0; i
< nremove_arch_flags
; i
++){
648 for(j
= i
+ 1; j
< nremove_arch_flags
; j
++){
649 if(remove_arch_flags
[i
].cputype
==
650 remove_arch_flags
[j
].cputype
&&
651 (remove_arch_flags
[i
].cpusubtype
& ~CPU_SUBTYPE_MASK
) ==
652 (remove_arch_flags
[j
].cpusubtype
& ~CPU_SUBTYPE_MASK
))
653 fatal("-remove %s specified multiple times",
654 remove_arch_flags
[i
].name
);
657 /* mark those thin files for removal */
658 for(i
= 0; i
< nremove_arch_flags
; i
++){
659 for(j
= 0; j
< nthin_files
; j
++){
660 if(remove_arch_flags
[i
].cputype
==
661 thin_files
[j
].fat_arch
.cputype
&&
662 (remove_arch_flags
[i
].cpusubtype
&
663 ~CPU_SUBTYPE_MASK
) ==
664 (thin_files
[j
].fat_arch
.cpusubtype
&
666 thin_files
[j
].remove
= TRUE
;
671 fatal("-remove %s specified but fat file: %s does not "
672 "contain that architecture",
673 remove_arch_flags
[i
].name
, input_files
[0].name
);
675 /* remove those thin files marked for removal */
676 for(i
= 0; i
< nthin_files
; ){
677 if(thin_files
[i
].remove
== TRUE
){
678 for(j
= i
; j
< nthin_files
; j
++)
679 thin_files
[j
] = thin_files
[j
+ 1];
686 fatal("-remove's specified would result in an empty fat file");
691 if(ninput_files
!= 1)
692 fatal("only one input file can be specified with the -replace "
694 if(input_files
[0].fat_header
== NULL
)
695 fatal("input file (%s) must be a fat file when the -replace "
696 "option is specified", input_files
[0].name
);
697 for(i
= 0; i
< nreplaces
; i
++){
698 for(j
= i
+ 1; j
< nreplaces
; j
++){
699 if(replaces
[i
].arch_flag
.cputype
==
700 replaces
[j
].arch_flag
.cputype
&&
701 (replaces
[i
].arch_flag
.cpusubtype
& ~CPU_SUBTYPE_MASK
) ==
702 (replaces
[j
].arch_flag
.cpusubtype
& ~CPU_SUBTYPE_MASK
))
703 fatal("-replace %s <file_name> specified multiple times",
704 replaces
[j
].arch_flag
.name
);
707 for(i
= 0; i
< nreplaces
; i
++){
708 process_replace_file(replaces
+ i
);
709 for(j
= 0; j
< nthin_files
; j
++){
710 if(replaces
[i
].arch_flag
.cputype
==
711 thin_files
[j
].fat_arch
.cputype
&&
712 (replaces
[i
].arch_flag
.cpusubtype
& ~CPU_SUBTYPE_MASK
) ==
713 (thin_files
[j
].fat_arch
.cpusubtype
& ~CPU_SUBTYPE_MASK
)){
714 thin_files
[j
] = replaces
[i
].thin_file
;
719 fatal("-replace %s <file_name> specified but fat file: %s "
720 "does not contain that architecture",
721 replaces
[i
].arch_flag
.name
, input_files
[0].name
);
727 for(i
= 0; i
< ninput_files
; i
++){
728 if(input_files
[i
].fat_header
!= NULL
){
729 printf("Architectures in the fat file: %s are: ",
730 input_files
[i
].name
);
731 for(j
= 0; j
< input_files
[i
].fat_header
->nfat_arch
; j
++){
732 print_arch(&(input_files
[i
].fat_arches
[j
]));
738 if(input_files
[i
].is_thin
== FALSE
)
739 printf("input file %s is not a fat file\n",
740 input_files
[i
].name
);
743 for(i
= 0; i
< nthin_files
; i
++){
744 if(thin_files
[i
].from_fat
== TRUE
)
746 printf("Non-fat file: %s is architecture: %s\n",
748 get_arch_name_from_types(thin_files
[i
].fat_arch
.cputype
,
749 thin_files
[i
].fat_arch
.cpusubtype
& ~CPU_SUBTYPE_MASK
));
753 if(detailed_info_flag
){
754 for(i
= 0; i
< ninput_files
; i
++){
755 if(input_files
[i
].fat_header
!= NULL
){
756 printf("Fat header in: %s\n", input_files
[i
].name
);
757 printf("fat_magic 0x%x\n",
758 (unsigned int)(input_files
[i
].fat_header
->magic
));
759 printf("nfat_arch %u\n",
760 input_files
[i
].fat_header
->nfat_arch
);
761 for(j
= 0; j
< input_files
[i
].fat_header
->nfat_arch
; j
++){
762 printf("architecture ");
763 print_arch(&(input_files
[i
].fat_arches
[j
]));
765 print_cputype(input_files
[i
].fat_arches
[j
].cputype
,
766 input_files
[i
].fat_arches
[j
].cpusubtype
&
768 printf(" offset %u\n",
769 input_files
[i
].fat_arches
[j
].offset
);
771 input_files
[i
].fat_arches
[j
].size
);
772 printf(" align 2^%u (%d)\n",
773 input_files
[i
].fat_arches
[j
].align
,
774 1 << input_files
[i
].fat_arches
[j
].align
);
778 printf("input file %s is not a fat file\n",
779 input_files
[i
].name
);
782 for(i
= 0; i
< nthin_files
; i
++){
783 if(thin_files
[i
].from_fat
== TRUE
)
785 printf("Non-fat file: %s is architecture: %s\n",
787 get_arch_name_from_types(thin_files
[i
].fat_arch
.cputype
,
788 thin_files
[i
].fat_arch
.cpusubtype
& ~CPU_SUBTYPE_MASK
));
792 if(verify_flag
== TRUE
){
793 for(i
= 0; i
< nverify_archs
; i
++){
795 for(j
= 0; j
< nthin_files
; j
++){
796 if(verify_archs
[i
].cputype
==
797 thin_files
[j
].fat_arch
.cputype
&&
798 (verify_archs
[i
].cpusubtype
& ~CPU_SUBTYPE_MASK
) ==
799 (thin_files
[j
].fat_arch
.cpusubtype
& ~CPU_SUBTYPE_MASK
)){
813 * create_fat() creates a fat output file from the thin files.
819 uint32_t i
, j
, offset
;
822 /* fold in specified segment alignments */
823 for(i
= 0; i
< nsegaligns
; i
++){
824 for(j
= i
+ 1; j
< nsegaligns
; j
++){
825 if(segaligns
[i
].arch_flag
.cputype
==
826 segaligns
[j
].arch_flag
.cputype
&&
827 (segaligns
[i
].arch_flag
.cpusubtype
& ~CPU_SUBTYPE_MASK
) ==
828 (segaligns
[j
].arch_flag
.cpusubtype
& ~CPU_SUBTYPE_MASK
))
829 fatal("-segalign %s <value> specified multiple times",
830 segaligns
[j
].arch_flag
.name
);
833 for(i
= 0; i
< nsegaligns
; i
++){
834 for(j
= 0; j
< nthin_files
; j
++){
835 if(segaligns
[i
].arch_flag
.cputype
==
836 thin_files
[j
].fat_arch
.cputype
&&
837 (segaligns
[i
].arch_flag
.cpusubtype
& ~CPU_SUBTYPE_MASK
) ==
838 (thin_files
[j
].fat_arch
.cpusubtype
& ~CPU_SUBTYPE_MASK
)){
840 Since this program has to guess at alignments and guesses high when unsure this
841 check shouldn't be used so the the correct alignment can be specified by the
843 if(thin_files[j].fat_arch.align > segaligns[i].align)
844 fatal("specified segment alignment: %d for "
845 "architecture %s is less than the alignment: %d "
846 "required from the input file",
847 1 << segaligns[i].align,
848 segaligns[i].arch_flag.name,
849 1 << thin_files[j].fat_arch.align);
851 thin_files
[j
].fat_arch
.align
= segaligns
[i
].align
;
856 fatal("-segalign %s <value> specified but resulting fat "
857 "file does not contain that architecture",
858 segaligns
[i
].arch_flag
.name
);
861 /* sort the files by alignment to save space in the output file */
862 qsort(thin_files
, nthin_files
, sizeof(struct thin_file
),
863 (int (*)(const void *, const void *))cmp_qsort
);
865 /* Fill in the fat header and the fat_arch's offsets. */
866 fat_header
.magic
= FAT_MAGIC
;
867 fat_header
.nfat_arch
= nthin_files
;
868 offset
= sizeof(struct fat_header
) +
869 nthin_files
* sizeof(struct fat_arch
);
870 for(i
= 0; i
< nthin_files
; i
++){
871 offset
= round(offset
, 1 << thin_files
[i
].fat_arch
.align
);
872 thin_files
[i
].fat_arch
.offset
= offset
;
873 offset
+= thin_files
[i
].fat_arch
.size
;
877 * Create the output file. The unlink() is done to handle the
878 * problem when the outputfile is not writable but the directory
879 * allows the file to be removed and thus created (since the file
880 * may not be there the return code of the unlink() is ignored).
882 (void)unlink(output_file
);
883 if((fd
= open(output_file
, O_WRONLY
| O_CREAT
| O_TRUNC
,
884 output_filemode
)) == -1)
885 system_fatal("can't create output file: %s", output_file
);
888 * If this is an extract_family_flag operation and the is just one
889 * thin file on the list don't create a fat file.
891 if(extract_family_flag
!= TRUE
|| nthin_files
!= 1){
892 #ifdef __LITTLE_ENDIAN__
893 swap_fat_header(&fat_header
, BIG_ENDIAN_BYTE_SEX
);
894 #endif /* __LITTLE_ENDIAN__ */
895 if(write(fd
, &fat_header
, sizeof(struct fat_header
)) !=
896 sizeof(struct fat_header
))
897 system_fatal("can't wtite fat header to output file: %s",
899 #ifdef __LITTLE_ENDIAN__
900 swap_fat_header(&fat_header
, LITTLE_ENDIAN_BYTE_SEX
);
901 #endif /* __LITTLE_ENDIAN__ */
902 for(i
= 0; i
< nthin_files
; i
++){
903 #ifdef __LITTLE_ENDIAN__
904 swap_fat_arch(&(thin_files
[i
].fat_arch
), 1,BIG_ENDIAN_BYTE_SEX
);
905 #endif /* __LITTLE_ENDIAN__ */
906 if(write(fd
, &(thin_files
[i
].fat_arch
),
907 sizeof(struct fat_arch
)) != sizeof(struct fat_arch
))
908 system_fatal("can't write fat arch to output file: %s",
910 #ifdef __LITTLE_ENDIAN__
911 swap_fat_arch(&(thin_files
[i
].fat_arch
), 1,
912 LITTLE_ENDIAN_BYTE_SEX
);
913 #endif /* __LITTLE_ENDIAN__ */
916 for(i
= 0; i
< nthin_files
; i
++){
917 if(extract_family_flag
== FALSE
|| nthin_files
> 1)
918 if(lseek(fd
, thin_files
[i
].fat_arch
.offset
, L_SET
) == -1)
919 system_fatal("can't lseek in output file: %s", output_file
);
920 if(write(fd
, thin_files
[i
].addr
, thin_files
[i
].fat_arch
.size
)
921 != (int)(thin_files
[i
].fat_arch
.size
))
922 system_fatal("can't write to output file: %s", output_file
);
925 system_fatal("can't close output file: %s", output_file
);
929 * process_input_file() checks input file and breaks it down into thin files
930 * for later operations.
935 struct input_file
*input
)
938 struct stat stat_buf
;
941 struct thin_file
*thin
;
942 struct mach_header
*mhp
, mh
;
943 struct mach_header_64
*mhp64
, mh64
;
944 struct load_command
*lcp
;
946 cpu_subtype_t cpusubtype
;
950 /* Open the input file and map it in */
951 if((fd
= open(input
->name
, O_RDONLY
)) == -1)
952 system_fatal("can't open input file: %s", input
->name
);
953 if(fstat(fd
, &stat_buf
) == -1)
954 system_fatal("Can't stat input file: %s", input
->name
);
955 size
= stat_buf
.st_size
;
956 /* pick up set uid, set gid and sticky text bits */
957 output_filemode
= stat_buf
.st_mode
& 07777;
959 * Select the eariliest modifiy time so that if the output file
960 * contains archives with table of contents lipo will not make them
961 * out of date. This logic however could make an out of date table of
962 * contents appear up todate if another file is combined with it that
963 * has a date early enough.
966 if(output_timep
.modtime
== 0 ||
967 output_timep
.modtime
> stat_buf
.st_mtime
){
968 output_timep
.actime
= stat_buf
.st_atime
;
969 output_timep
.modtime
= stat_buf
.st_mtime
;
972 if(output_timep
[1] == 0 || output_timep
[1] > stat_buf
.st_mtime
){
973 output_timep
[0] = stat_buf
.st_atime
;
974 output_timep
[1] = stat_buf
.st_mtime
;
978 * mmap() can't handle mapping regular files with zero size. So this
979 * is handled separately.
981 if((stat_buf
.st_mode
& S_IFREG
) == S_IFREG
&& size
== 0)
984 addr
= mmap(0, size
, PROT_READ
|PROT_WRITE
, MAP_FILE
|MAP_PRIVATE
,
986 if((intptr_t)addr
== -1)
987 system_fatal("Can't map input file: %s", input
->name
);
990 /* Try to figure out what kind of file this is */
992 /* see if this file is a fat file */
993 if(size
>= sizeof(struct fat_header
) &&
994 #ifdef __BIG_ENDIAN__
995 *((uint32_t *)addr
) == FAT_MAGIC
)
996 #endif /* __BIG_ENDIAN__ */
997 #ifdef __LITTLE_ENDIAN__
998 *((uint32_t *)addr
) == SWAP_INT(FAT_MAGIC
))
999 #endif /* __LITTLE_ENDIAN__ */
1002 if(input
->arch_flag
.name
!= NULL
)
1003 fatal("architecture specifed for fat input file: %s "
1004 "(architectures can't be specifed for fat input files)",
1007 input
->fat_header
= (struct fat_header
*)addr
;
1008 #ifdef __LITTLE_ENDIAN__
1009 swap_fat_header(input
->fat_header
, LITTLE_ENDIAN_BYTE_SEX
);
1010 #endif /* __LITTLE_ENDIAN__ */
1011 big_size
= input
->fat_header
->nfat_arch
;
1012 big_size
*= sizeof(struct fat_arch
);
1013 big_size
+= sizeof(struct fat_header
);
1015 fatal("truncated or malformed fat file (fat_arch structs would "
1016 "extend past the end of the file) %s", input
->name
);
1017 input
->fat_arches
= (struct fat_arch
*)(addr
+
1018 sizeof(struct fat_header
));
1019 #ifdef __LITTLE_ENDIAN__
1020 swap_fat_arch(input
->fat_arches
, input
->fat_header
->nfat_arch
,
1021 LITTLE_ENDIAN_BYTE_SEX
);
1022 #endif /* __LITTLE_ENDIAN__ */
1023 for(i
= 0; i
< input
->fat_header
->nfat_arch
; i
++){
1024 if(input
->fat_arches
[i
].offset
+ input
->fat_arches
[i
].size
>
1026 fatal("truncated or malformed fat file (offset plus size "
1027 "of cputype (%d) cpusubtype (%d) extends past the "
1028 "end of the file) %s", input
->fat_arches
[i
].cputype
,
1029 input
->fat_arches
[i
].cpusubtype
& ~CPU_SUBTYPE_MASK
,
1031 if(input
->fat_arches
[i
].align
> MAXSECTALIGN
)
1032 fatal("align (2^%u) too large of fat file %s (cputype (%d)"
1033 " cpusubtype (%d)) (maximum 2^%d)",
1034 input
->fat_arches
[i
].align
, input
->name
,
1035 input
->fat_arches
[i
].cputype
,
1036 input
->fat_arches
[i
].cpusubtype
& ~CPU_SUBTYPE_MASK
,
1038 if(input
->fat_arches
[i
].offset
%
1039 (1 << input
->fat_arches
[i
].align
) != 0)
1040 fatal("offset %u of fat file %s (cputype (%d) cpusubtype "
1041 "(%d)) not aligned on its alignment (2^%u)",
1042 input
->fat_arches
[i
].offset
, input
->name
,
1043 input
->fat_arches
[i
].cputype
,
1044 input
->fat_arches
[i
].cpusubtype
& ~CPU_SUBTYPE_MASK
,
1045 input
->fat_arches
[i
].align
);
1047 for(i
= 0; i
< input
->fat_header
->nfat_arch
; i
++){
1048 for(j
= i
+ 1; j
< input
->fat_header
->nfat_arch
; j
++){
1049 if(input
->fat_arches
[i
].cputype
==
1050 input
->fat_arches
[j
].cputype
&&
1051 (input
->fat_arches
[i
].cpusubtype
& ~CPU_SUBTYPE_MASK
) ==
1052 (input
->fat_arches
[j
].cpusubtype
& ~CPU_SUBTYPE_MASK
))
1053 fatal("fat file %s contains two of the same architecture "
1054 "(cputype (%d) cpusubtype (%d))", input
->name
,
1055 input
->fat_arches
[i
].cputype
,
1056 input
->fat_arches
[i
].cpusubtype
& ~CPU_SUBTYPE_MASK
);
1060 /* create a thin file struct for each arch in the fat file */
1061 for(i
= 0; i
< input
->fat_header
->nfat_arch
; i
++){
1063 thin
->name
= input
->name
;
1064 thin
->addr
= addr
+ input
->fat_arches
[i
].offset
;
1065 thin
->fat_arch
= input
->fat_arches
[i
];
1066 thin
->from_fat
= TRUE
;
1067 if(input
->fat_arches
[i
].size
>= SARMAG
&&
1068 strncmp(thin
->addr
, ARMAG
, SARMAG
) == 0)
1069 archives_in_input
= TRUE
;
1072 /* see if this file is Mach-O file for 32-bit architectures */
1073 else if(size
>= sizeof(struct mach_header
) &&
1074 (*((uint32_t *)addr
) == MH_MAGIC
||
1075 *((uint32_t *)addr
) == SWAP_INT(MH_MAGIC
))){
1077 /* this is a Mach-O file so create a thin file struct for it */
1079 input
->is_thin
= TRUE
;
1080 thin
->name
= input
->name
;
1082 mhp
= (struct mach_header
*)addr
;
1083 lcp
= (struct load_command
*)((char *)mhp
+
1084 sizeof(struct mach_header
));
1085 if(mhp
->magic
== SWAP_INT(MH_MAGIC
)){
1088 swap_mach_header(&mh
, get_host_byte_sex());
1093 thin
->fat_arch
.cputype
= mhp
->cputype
;
1094 thin
->fat_arch
.cpusubtype
= mhp
->cpusubtype
;
1095 thin
->fat_arch
.offset
= 0;
1096 thin
->fat_arch
.size
= size
;
1097 thin
->fat_arch
.align
= get_align(mhp
, lcp
, size
, input
->name
,
1100 /* if the arch type is specified make sure it matches the object */
1101 if(input
->arch_flag
.name
!= NULL
)
1102 check_arch(input
, thin
);
1104 /* see if this file is Mach-O file for 64-bit architectures */
1105 else if(size
>= sizeof(struct mach_header_64
) &&
1106 (*((uint32_t *)addr
) == MH_MAGIC_64
||
1107 *((uint32_t *)addr
) == SWAP_INT(MH_MAGIC_64
))){
1109 /* this is a Mach-O file so create a thin file struct for it */
1111 input
->is_thin
= TRUE
;
1112 thin
->name
= input
->name
;
1114 mhp64
= (struct mach_header_64
*)addr
;
1115 lcp
= (struct load_command
*)((char *)mhp64
+
1116 sizeof(struct mach_header_64
));
1117 if(mhp64
->magic
== SWAP_INT(MH_MAGIC_64
)){
1120 swap_mach_header_64(&mh64
, get_host_byte_sex());
1125 thin
->fat_arch
.cputype
= mhp64
->cputype
;
1126 thin
->fat_arch
.cpusubtype
= mhp64
->cpusubtype
;
1127 thin
->fat_arch
.offset
= 0;
1128 thin
->fat_arch
.size
= size
;
1129 thin
->fat_arch
.align
= get_align_64(mhp64
, lcp
, size
, input
->name
,
1132 /* if the arch type is specified make sure it matches the object */
1133 if(input
->arch_flag
.name
!= NULL
)
1134 check_arch(input
, thin
);
1136 /* see if this file is an archive file */
1137 else if(size
>= SARMAG
&& strncmp(addr
, ARMAG
, SARMAG
) == 0){
1139 check_archive(input
->name
, addr
, size
, &cputype
, &cpusubtype
);
1140 archives_in_input
= TRUE
;
1142 /* create a thin file struct for this archive */
1144 thin
->name
= input
->name
;
1146 thin
->fat_arch
.cputype
= cputype
;
1147 thin
->fat_arch
.cpusubtype
= cpusubtype
;
1148 thin
->fat_arch
.offset
= 0;
1149 thin
->fat_arch
.size
= size
;
1150 thin
->fat_arch
.align
= 2; /* 2^2, sizeof(uint32_t) */
1152 /* if the arch type is specified make sure it matches the object */
1153 if(input
->arch_flag
.name
!= NULL
){
1155 thin
->fat_arch
.cputype
= input
->arch_flag
.cputype
;
1156 thin
->fat_arch
.cpusubtype
= input
->arch_flag
.cpusubtype
;
1159 check_arch(input
, thin
);
1163 fatal("archive with no architecture specification: %s "
1164 "(can't determine architecture for it)", input
->name
);
1167 /* this file type is now known to be unknown to this program */
1170 if(input
->arch_flag
.name
!= NULL
){
1171 /* create a thin file struct for it */
1173 thin
->name
= input
->name
;
1175 thin
->fat_arch
.cputype
= input
->arch_flag
.cputype
;
1176 thin
->fat_arch
.cpusubtype
= input
->arch_flag
.cpusubtype
;
1177 thin
->fat_arch
.offset
= 0;
1178 thin
->fat_arch
.size
= size
;
1179 thin
->fat_arch
.align
= 0;
1182 fatal("can't figure out the architecture type of: %s",
1189 * process_replace_file() checks the replacement file and maps it in for later
1194 process_replace_file(
1195 struct replace
*replace
)
1198 struct stat stat_buf
;
1201 struct mach_header
*mhp
, mh
;
1202 struct mach_header_64
*mhp64
, mh64
;
1203 struct load_command
*lcp
;
1205 cpu_subtype_t cpusubtype
;
1208 /* Open the replacement file and map it in */
1209 if((fd
= open(replace
->thin_file
.name
, O_RDONLY
)) == -1)
1210 system_fatal("can't open replacement file: %s",
1211 replace
->thin_file
.name
);
1212 if(fstat(fd
, &stat_buf
) == -1)
1213 system_fatal("Can't stat replacement file: %s",
1214 replace
->thin_file
.name
);
1215 size
= stat_buf
.st_size
;
1217 * mmap() can't handle mapping regular files with zero size. So this
1218 * is handled separately.
1220 if((stat_buf
.st_mode
& S_IFREG
) == S_IFREG
&& size
== 0)
1223 addr
= mmap(0, size
, PROT_READ
|PROT_WRITE
, MAP_FILE
|MAP_PRIVATE
,
1225 if((intptr_t)addr
== -1)
1226 system_error("Can't map replacement file: %s",
1227 replace
->thin_file
.name
);
1230 /* Try to figure out what kind of file this is */
1232 /* see if this file is a fat file */
1233 if(size
>= sizeof(struct fat_header
) &&
1234 *((uint32_t *)addr
) == FAT_MAGIC
){
1236 fatal("replacement file: %s is a fat file (must be a thin file)",
1237 replace
->thin_file
.name
);
1239 /* see if this file is Mach-O file for 32-bit architectures */
1240 else if(size
>= sizeof(struct mach_header
) &&
1241 (*((uint32_t *)addr
) == MH_MAGIC
||
1242 *((uint32_t *)addr
) == SWAP_INT(MH_MAGIC
))){
1244 /* this is a Mach-O file so fill in the thin file struct for it */
1245 replace
->thin_file
.addr
= addr
;
1246 mhp
= (struct mach_header
*)addr
;
1247 lcp
= (struct load_command
*)((char *)mhp
+
1248 sizeof(struct mach_header
));
1249 if(mhp
->magic
== SWAP_INT(MH_MAGIC
)){
1252 swap_mach_header(&mh
, get_host_byte_sex());
1257 replace
->thin_file
.fat_arch
.cputype
= mhp
->cputype
;
1258 replace
->thin_file
.fat_arch
.cpusubtype
= mhp
->cpusubtype
;
1259 replace
->thin_file
.fat_arch
.offset
= 0;
1260 replace
->thin_file
.fat_arch
.size
= size
;
1261 replace
->thin_file
.fat_arch
.align
=
1262 get_align(mhp
, lcp
, size
, replace
->thin_file
.name
, swapped
);
1264 /* see if this file is Mach-O file for 64-bit architectures */
1265 else if(size
>= sizeof(struct mach_header_64
) &&
1266 (*((uint32_t *)addr
) == MH_MAGIC_64
||
1267 *((uint32_t *)addr
) == SWAP_INT(MH_MAGIC_64
))){
1269 /* this is a Mach-O file so fill in the thin file struct for it */
1270 replace
->thin_file
.addr
= addr
;
1271 mhp64
= (struct mach_header_64
*)addr
;
1272 lcp
= (struct load_command
*)((char *)mhp64
+
1273 sizeof(struct mach_header_64
));
1274 if(mhp64
->magic
== SWAP_INT(MH_MAGIC_64
)){
1277 swap_mach_header_64(&mh64
, get_host_byte_sex());
1282 replace
->thin_file
.fat_arch
.cputype
= mhp64
->cputype
;
1283 replace
->thin_file
.fat_arch
.cpusubtype
= mhp64
->cpusubtype
;
1284 replace
->thin_file
.fat_arch
.offset
= 0;
1285 replace
->thin_file
.fat_arch
.size
= size
;
1286 replace
->thin_file
.fat_arch
.align
=
1287 get_align_64(mhp64
, lcp
, size
, replace
->thin_file
.name
, swapped
);
1289 /* see if this file is an archive file */
1290 else if(size
>= SARMAG
&& strncmp(addr
, ARMAG
, SARMAG
) == 0){
1292 check_archive(replace
->thin_file
.name
, addr
, size
,
1293 &cputype
, &cpusubtype
);
1295 /* fill in the thin file struct for this archive */
1296 replace
->thin_file
.addr
= addr
;
1297 replace
->thin_file
.fat_arch
.cputype
= cputype
;
1298 replace
->thin_file
.fat_arch
.cpusubtype
= cpusubtype
;
1299 replace
->thin_file
.fat_arch
.offset
= 0;
1300 replace
->thin_file
.fat_arch
.size
= size
;
1301 replace
->thin_file
.fat_arch
.align
= 2; /* 2^2, sizeof(uint32_t) */
1304 /* fill in the thin file struct for it */
1305 replace
->thin_file
.addr
= addr
;
1306 replace
->thin_file
.fat_arch
.cputype
= replace
->arch_flag
.cputype
;
1307 replace
->thin_file
.fat_arch
.cpusubtype
=
1308 replace
->arch_flag
.cpusubtype
;
1309 replace
->thin_file
.fat_arch
.offset
= 0;
1310 replace
->thin_file
.fat_arch
.size
= size
;
1311 replace
->thin_file
.fat_arch
.align
= 0;
1314 if(replace
->thin_file
.fat_arch
.cputype
!= replace
->arch_flag
.cputype
||
1315 (replace
->thin_file
.fat_arch
.cpusubtype
& ~CPU_SUBTYPE_MASK
) !=
1316 (replace
->arch_flag
.cpusubtype
& ~CPU_SUBTYPE_MASK
))
1317 fatal("specified architecture: %s for replacement file: %s does "
1318 "not match the file's architecture", replace
->arch_flag
.name
,
1319 replace
->thin_file
.name
);
1323 * check_archive() checks an archive (mapped in at 'addr' of size 'size') to
1324 * make sure it can be included in a fat file (all members are the same
1325 * architecture, no fat files, etc). It returns the cputype and cpusubtype.
1333 cpu_type_t
*cputype
,
1334 cpu_subtype_t
*cpusubtype
)
1336 uint32_t offset
, magic
, i
, ar_name_size
;
1337 struct mach_header mh
;
1338 struct mach_header_64 mh64
;
1339 struct ar_hdr
*ar_hdr
;
1343 * Check this archive out to make sure that it does not contain
1344 * any fat files and that all object files it contains have the
1345 * same cputype and subsubtype.
1351 fatal("empty archive with no architecture specification: %s "
1352 "(can't determine architecture for it)", name
);
1353 if(offset
!= size
&& offset
+ sizeof(struct ar_hdr
) > size
)
1354 fatal("truncated or malformed archive: %s (archive header of "
1355 "first member extends past the end of the file)", name
);
1356 while(size
> offset
){
1357 ar_hdr
= (struct ar_hdr
*)(addr
+ offset
);
1358 offset
+= sizeof(struct ar_hdr
);
1359 if(strncmp(ar_hdr
->ar_name
, AR_EFMT1
, sizeof(AR_EFMT1
) - 1) == 0){
1360 check_extend_format_1(name
, ar_hdr
, size
-offset
, &ar_name_size
);
1362 ar_name
= ar_hdr
->ar_name
+ sizeof(struct ar_hdr
);
1365 i
= size_ar_name(ar_hdr
->ar_name
);
1366 ar_name
= ar_hdr
->ar_name
;
1369 if(size
+ ar_name_size
- offset
> sizeof(uint32_t)){
1370 memcpy(&magic
, addr
+ offset
+ ar_name_size
,
1372 if(magic
== FAT_MAGIC
)
1373 fatal("archive member %s(%.*s) is a fat file (not "
1374 "allowed in an archive)", name
, (int)i
, ar_name
);
1375 if((size
- ar_name_size
) - offset
>=
1376 sizeof(struct mach_header
) &&
1377 (magic
== MH_MAGIC
|| magic
== SWAP_INT(MH_MAGIC
))){
1378 memcpy(&mh
, addr
+ offset
+ ar_name_size
,
1379 sizeof(struct mach_header
));
1380 if(mh
.magic
== SWAP_INT(MH_MAGIC
))
1381 swap_mach_header(&mh
, get_host_byte_sex());
1383 *cputype
= mh
.cputype
;
1384 *cpusubtype
= mh
.cpusubtype
;
1386 else if(*cputype
!= mh
.cputype
){
1387 fatal("archive member %s(%.*s) cputype (%d) and "
1388 "cpusubtype (%d) does not match previous "
1389 "archive members cputype (%d) and cpusubtype"
1390 " (%d) (all members must match)", name
,
1391 (int)i
, ar_name
, mh
.cputype
, mh
.cpusubtype
&
1392 ~CPU_SUBTYPE_MASK
, *cputype
, (*cpusubtype
) &
1396 else if((size
- ar_name_size
) - offset
>=
1397 sizeof(struct mach_header_64
) &&
1398 (magic
== MH_MAGIC_64
|| magic
== SWAP_INT(MH_MAGIC_64
))){
1399 memcpy(&mh64
, addr
+ offset
+ ar_name_size
,
1400 sizeof(struct mach_header_64
));
1401 if(mh64
.magic
== SWAP_INT(MH_MAGIC_64
))
1402 swap_mach_header_64(&mh64
, get_host_byte_sex());
1404 *cputype
= mh64
.cputype
;
1405 *cpusubtype
= mh64
.cpusubtype
;
1407 else if(*cputype
!= mh64
.cputype
){
1408 fatal("archive member %s(%.*s) cputype (%d) and "
1409 "cpusubtype (%d) does not match previous "
1410 "archive members cputype (%d) and cpusubtype"
1411 " (%d) (all members must match)", name
,
1412 (int)i
, ar_name
, mh64
.cputype
, mh64
.cpusubtype
&
1413 ~CPU_SUBTYPE_MASK
, *cputype
, (*cpusubtype
) &
1418 offset
+= round(strtoul(ar_hdr
->ar_size
, NULL
, 10),
1423 * check_extend_format_1() checks the archive header for extened format1.
1427 check_extend_format_1(
1429 struct ar_hdr
*ar_hdr
,
1431 uint32_t *member_name_size
)
1433 char *p
, *endp
, buf
[sizeof(ar_hdr
->ar_name
)+1];
1434 uint32_t ar_name_size
;
1436 *member_name_size
= 0;
1438 buf
[sizeof(ar_hdr
->ar_name
)] = '\0';
1439 memcpy(buf
, ar_hdr
->ar_name
, sizeof(ar_hdr
->ar_name
));
1440 p
= buf
+ sizeof(AR_EFMT1
) - 1;
1441 if(isdigit(*p
) == 0)
1442 fatal("archive: %s malformed (ar_name: %.*s for archive extend "
1443 "format #1 starts with non-digit)", name
,
1444 (int)sizeof(ar_hdr
->ar_name
), ar_hdr
->ar_name
);
1445 ar_name_size
= strtoul(p
, &endp
, 10);
1446 if(ar_name_size
== UINT_MAX
&& errno
== ERANGE
)
1447 fatal("archive: %s malformed (size in ar_name: %.*s for archive "
1448 "extend format #1 overflows uint32_t)", name
,
1449 (int)sizeof(ar_hdr
->ar_name
), ar_hdr
->ar_name
);
1450 while(*endp
== ' ' && *endp
!= '\0')
1453 fatal("archive: %s malformed (size in ar_name: %.*s for archive "
1454 "extend format #1 contains non-digit and non-space "
1455 "characters)", name
, (int)sizeof(ar_hdr
->ar_name
),
1457 if(ar_name_size
> size_left
)
1458 fatal("archive: %s truncated or malformed (archive name "
1459 "of member extends past the end of the file)", name
);
1460 *member_name_size
= ar_name_size
;
1464 * get_align is passed a pointer to a mach header and size of the object. It
1465 * returns the segment alignment the object was created with. It guesses but
1466 * it is conservative. The maximum alignment is that the link editor will allow
1467 * MAXSECTALIGN and the minimum is the conserative alignment for a uint32_t
1468 * which appears in a mach object files (2^2 worst case for all current 32-bit
1474 struct mach_header
*mhp
,
1475 struct load_command
*load_commands
,
1480 uint32_t i
, j
, cur_align
, align
;
1481 struct load_command
*lcp
, l
;
1482 struct segment_command
*sgp
, sg
;
1483 struct section
*sp
, s
;
1484 enum byte_sex host_byte_sex
;
1487 * Special case ppc, ppc64, i386 and x86_64 architectures and return 12.
1488 * We know that with those architectures that the kernel and mmap only
1489 * need file offsets to be page (4096 byte) aligned.
1491 if(mhp
->cputype
== CPU_TYPE_POWERPC
||
1492 mhp
->cputype
== CPU_TYPE_POWERPC64
||
1493 mhp
->cputype
== CPU_TYPE_I386
||
1494 mhp
->cputype
== CPU_TYPE_X86_64
)
1497 host_byte_sex
= get_host_byte_sex();
1499 /* set worst case the link editor uses first */
1500 cur_align
= MAXSECTALIGN
;
1501 if(mhp
->sizeofcmds
+ sizeof(struct mach_header
) > size
)
1502 fatal("truncated or malformed object (load commands would "
1503 "extend past the end of the file) in: %s", name
);
1504 lcp
= load_commands
;
1505 for(i
= 0; i
< mhp
->ncmds
; i
++){
1508 swap_load_command(&l
, host_byte_sex
);
1509 if(l
.cmdsize
% sizeof(uint32_t) != 0)
1510 error("load command %u size not a multiple of "
1511 "sizeof(uint32_t) in: %s", i
, name
);
1513 fatal("load command %u size is less than or equal to zero "
1515 if((char *)lcp
+ l
.cmdsize
>
1516 (char *)load_commands
+ mhp
->sizeofcmds
)
1517 fatal("load command %u extends past end of all load "
1518 "commands in: %s", i
, name
);
1519 if(l
.cmd
== LC_SEGMENT
){
1520 sgp
= (struct segment_command
*)lcp
;
1523 swap_segment_command(&sg
, host_byte_sex
);
1524 if(mhp
->filetype
== MH_OBJECT
){
1525 /* this is the minimum alignment, then take largest */
1526 align
= 2; /* 2^2 sizeof(uint32_t) */
1527 sp
= (struct section
*)((char *)sgp
+
1528 sizeof(struct segment_command
));
1529 for(j
= 0; j
< sg
.nsects
; j
++){
1532 swap_section(&s
, 1, host_byte_sex
);
1537 if(align
< cur_align
)
1541 /* guess the smallest alignment and use that */
1542 align
= guess_align(sg
.vmaddr
);
1543 if(align
< cur_align
)
1547 lcp
= (struct load_command
*)((char *)lcp
+ l
.cmdsize
);
1553 * get_align_64 is passed a pointer to a mach_header_64 and size of the object.
1554 * It returns the segment alignment the object was created with. It guesses but
1555 * it is conservative. The maximum alignment is that the link editor will allow
1556 * MAXSECTALIGN and the minimum is the conserative alignment for a long long
1557 * which appears in a mach object files (2^3 worst case for all 64-bit
1563 struct mach_header_64
*mhp64
,
1564 struct load_command
*load_commands
,
1569 uint32_t i
, j
, cur_align
, align
;
1570 struct load_command
*lcp
, l
;
1571 struct segment_command_64
*sgp
, sg
;
1572 struct section_64
*sp
, s
;
1573 enum byte_sex host_byte_sex
;
1576 * Special case ppc, ppc64, i386 and x86_64 architectures and return 12.
1577 * We know that with those architectures that the kernel and mmap only
1578 * need file offsets to be page (4096 byte) aligned.
1580 if(mhp64
->cputype
== CPU_TYPE_POWERPC
||
1581 mhp64
->cputype
== CPU_TYPE_POWERPC64
||
1582 mhp64
->cputype
== CPU_TYPE_I386
||
1583 mhp64
->cputype
== CPU_TYPE_X86_64
)
1586 host_byte_sex
= get_host_byte_sex();
1588 /* set worst case the link editor uses first */
1589 cur_align
= MAXSECTALIGN
;
1590 if(mhp64
->sizeofcmds
+ sizeof(struct mach_header_64
) > size
)
1591 fatal("truncated or malformed object (load commands would "
1592 "extend past the end of the file) in: %s", name
);
1593 lcp
= load_commands
;
1594 for(i
= 0; i
< mhp64
->ncmds
; i
++){
1597 swap_load_command(&l
, host_byte_sex
);
1598 if(l
.cmdsize
% sizeof(long long) != 0)
1599 error("load command %u size not a multiple of "
1600 "sizeof(long long) in: %s", i
, name
);
1602 fatal("load command %u size is less than or equal to zero "
1604 if((char *)lcp
+ l
.cmdsize
>
1605 (char *)load_commands
+ mhp64
->sizeofcmds
)
1606 fatal("load command %u extends past end of all load "
1607 "commands in: %s", i
, name
);
1608 if(l
.cmd
== LC_SEGMENT_64
){
1609 sgp
= (struct segment_command_64
*)lcp
;
1612 swap_segment_command_64(&sg
, host_byte_sex
);
1613 if(mhp64
->filetype
== MH_OBJECT
){
1614 /* this is the minimum alignment, then take largest */
1615 align
= 3; /* 2^3 sizeof(long long) */
1616 sp
= (struct section_64
*)((char *)sgp
+
1617 sizeof(struct segment_command_64
));
1618 for(j
= 0; j
< sg
.nsects
; j
++){
1621 swap_section_64(&s
, 1, host_byte_sex
);
1626 if(align
< cur_align
)
1630 /* guess the smallest alignment and use that */
1631 align
= guess_align(sg
.vmaddr
);
1632 if(align
< cur_align
)
1636 lcp
= (struct load_command
*)((char *)lcp
+ l
.cmdsize
);
1642 * guess_align is passed a vmaddr of a segment and guesses what the segment
1643 * alignment was. It uses the most conservative guess up to the maximum
1644 * alignment that the link editor uses.
1651 uint32_t align
, segalign
;
1654 return(MAXSECTALIGN
);
1658 while((segalign
& vmaddr
) == 0){
1659 segalign
= segalign
<< 1;
1665 if(align
> MAXSECTALIGN
)
1666 return(MAXSECTALIGN
);
1672 * print_arch() helps implement -info and -detailed_info by printing the
1673 * architecture name for the cputype and cpusubtype.
1678 struct fat_arch
*fat_arch
)
1680 switch(fat_arch
->cputype
){
1681 case CPU_TYPE_MC680x0
:
1682 switch(fat_arch
->cpusubtype
& ~CPU_SUBTYPE_MASK
){
1683 case CPU_SUBTYPE_MC680x0_ALL
:
1686 case CPU_SUBTYPE_MC68030_ONLY
:
1689 case CPU_SUBTYPE_MC68040
:
1693 goto print_arch_unknown
;
1696 case CPU_TYPE_POWERPC
:
1697 switch(fat_arch
->cpusubtype
& ~CPU_SUBTYPE_MASK
){
1698 case CPU_SUBTYPE_POWERPC_ALL
:
1701 case CPU_SUBTYPE_POWERPC_601
:
1704 case CPU_SUBTYPE_POWERPC_603
:
1707 case CPU_SUBTYPE_POWERPC_603e
:
1710 case CPU_SUBTYPE_POWERPC_603ev
:
1713 case CPU_SUBTYPE_POWERPC_604
:
1716 case CPU_SUBTYPE_POWERPC_604e
:
1719 case CPU_SUBTYPE_POWERPC_750
:
1722 case CPU_SUBTYPE_POWERPC_7400
:
1725 case CPU_SUBTYPE_POWERPC_7450
:
1728 case CPU_SUBTYPE_POWERPC_970
:
1732 goto print_arch_unknown
;
1735 case CPU_TYPE_POWERPC64
:
1736 switch(fat_arch
->cpusubtype
& ~CPU_SUBTYPE_MASK
){
1737 case CPU_SUBTYPE_POWERPC_ALL
:
1740 case CPU_SUBTYPE_POWERPC_970
:
1741 printf("ppc970-64");
1744 goto print_arch_unknown
;
1748 switch(fat_arch
->cpusubtype
& ~CPU_SUBTYPE_MASK
){
1749 case CPU_SUBTYPE_VEO_1
:
1752 case CPU_SUBTYPE_VEO_2
:
1755 case CPU_SUBTYPE_VEO_3
:
1758 case CPU_SUBTYPE_VEO_4
:
1762 goto print_arch_unknown
;
1765 case CPU_TYPE_MC88000
:
1766 switch(fat_arch
->cpusubtype
& ~CPU_SUBTYPE_MASK
){
1767 case CPU_SUBTYPE_MC88000_ALL
:
1768 case CPU_SUBTYPE_MC88110
:
1772 goto print_arch_unknown
;
1776 switch(fat_arch
->cpusubtype
& ~CPU_SUBTYPE_MASK
){
1777 case CPU_SUBTYPE_I386_ALL
:
1778 /* case CPU_SUBTYPE_386: same as above */
1781 case CPU_SUBTYPE_486
:
1784 case CPU_SUBTYPE_486SX
:
1787 case CPU_SUBTYPE_PENT
: /* same as 586 */
1790 case CPU_SUBTYPE_PENTPRO
:
1793 case CPU_SUBTYPE_PENTII_M3
:
1796 case CPU_SUBTYPE_PENTII_M5
:
1800 goto print_arch_unknown
;
1803 case CPU_TYPE_X86_64
:
1804 switch(fat_arch
->cpusubtype
& ~CPU_SUBTYPE_MASK
){
1805 case CPU_SUBTYPE_X86_64_ALL
:
1809 goto print_arch_unknown
;
1813 switch(fat_arch
->cpusubtype
& ~CPU_SUBTYPE_MASK
){
1814 case CPU_SUBTYPE_I860_ALL
:
1815 case CPU_SUBTYPE_I860_860
:
1819 goto print_arch_unknown
;
1823 switch(fat_arch
->cpusubtype
& ~CPU_SUBTYPE_MASK
){
1824 case CPU_SUBTYPE_HPPA_ALL
:
1825 case CPU_SUBTYPE_HPPA_7100LC
:
1829 goto print_arch_unknown
;
1832 case CPU_TYPE_SPARC
:
1833 switch(fat_arch
->cpusubtype
& ~CPU_SUBTYPE_MASK
){
1834 case CPU_SUBTYPE_SPARC_ALL
:
1838 goto print_arch_unknown
;
1842 switch(fat_arch
->cpusubtype
){
1843 case CPU_SUBTYPE_ARM_ALL
:
1846 case CPU_SUBTYPE_ARM_V4T
:
1849 case CPU_SUBTYPE_ARM_V5TEJ
:
1852 case CPU_SUBTYPE_ARM_XSCALE
:
1855 case CPU_SUBTYPE_ARM_V6
:
1858 case CPU_SUBTYPE_ARM_V7
:
1862 goto print_arch_unknown
;
1866 switch(fat_arch
->cpusubtype
& ~CPU_SUBTYPE_MASK
){
1867 case CPU_SUBTYPE_MULTIPLE
:
1870 case CPU_SUBTYPE_LITTLE_ENDIAN
:
1873 case CPU_SUBTYPE_BIG_ENDIAN
:
1877 goto print_arch_unknown
;
1882 printf("(cputype (%d) cpusubtype (%d))", fat_arch
->cputype
,
1883 fat_arch
->cpusubtype
& ~CPU_SUBTYPE_MASK
);
1889 * print_cputype() helps implement -detailed_info by printing the cputype and
1890 * cpusubtype (symbolicly for the one's it knows about).
1896 cpu_subtype_t cpusubtype
)
1899 case CPU_TYPE_MC680x0
:
1900 switch(cpusubtype
& ~CPU_SUBTYPE_MASK
){
1901 case CPU_SUBTYPE_MC680x0_ALL
:
1902 printf(" cputype CPU_TYPE_MC680x0\n"
1903 " cpusubtype CPU_SUBTYPE_MC680x0_ALL\n");
1905 case CPU_SUBTYPE_MC68030_ONLY
:
1906 printf(" cputype CPU_TYPE_MC680x0\n"
1907 " cpusubtype CPU_SUBTYPE_MC68030_ONLY\n");
1909 case CPU_SUBTYPE_MC68040
:
1910 printf(" cputype CPU_TYPE_MC680x0\n"
1911 " cpusubtype CPU_SUBTYPE_MC68040\n");
1914 goto print_arch_unknown
;
1917 case CPU_TYPE_POWERPC
:
1918 switch(cpusubtype
& ~CPU_SUBTYPE_MASK
){
1919 case CPU_SUBTYPE_POWERPC_ALL
:
1920 printf(" cputype CPU_TYPE_POWERPC\n"
1921 " cpusubtype CPU_SUBTYPE_POWERPC_ALL\n");
1923 case CPU_SUBTYPE_POWERPC_601
:
1924 printf(" cputype CPU_TYPE_POWERPC\n"
1925 " cpusubtype CPU_SUBTYPE_POWERPC_601\n");
1927 case CPU_SUBTYPE_POWERPC_603
:
1928 printf(" cputype CPU_TYPE_POWERPC\n"
1929 " cpusubtype CPU_SUBTYPE_POWERPC_603\n");
1931 case CPU_SUBTYPE_POWERPC_603e
:
1932 printf(" cputype CPU_TYPE_POWERPC\n"
1933 " cpusubtype CPU_SUBTYPE_POWERPC_603e\n");
1935 case CPU_SUBTYPE_POWERPC_603ev
:
1936 printf(" cputype CPU_TYPE_POWERPC\n"
1937 " cpusubtype CPU_SUBTYPE_POWERPC_603ev\n");
1939 case CPU_SUBTYPE_POWERPC_604
:
1940 printf(" cputype CPU_TYPE_POWERPC\n"
1941 " cpusubtype CPU_SUBTYPE_POWERPC_604\n");
1943 case CPU_SUBTYPE_POWERPC_604e
:
1944 printf(" cputype CPU_TYPE_POWERPC\n"
1945 " cpusubtype CPU_SUBTYPE_POWERPC_604e\n");
1947 case CPU_SUBTYPE_POWERPC_750
:
1948 printf(" cputype CPU_TYPE_POWERPC\n"
1949 " cpusubtype CPU_SUBTYPE_POWERPC_750\n");
1951 case CPU_SUBTYPE_POWERPC_7400
:
1952 printf(" cputype CPU_TYPE_POWERPC\n"
1953 " cpusubtype CPU_SUBTYPE_POWERPC_7400\n");
1955 case CPU_SUBTYPE_POWERPC_7450
:
1956 printf(" cputype CPU_TYPE_POWERPC\n"
1957 " cpusubtype CPU_SUBTYPE_POWERPC_7450\n");
1959 case CPU_SUBTYPE_POWERPC_970
:
1960 printf(" cputype CPU_TYPE_POWERPC\n"
1961 " cpusubtype CPU_SUBTYPE_POWERPC_970\n");
1964 goto print_arch_unknown
;
1967 case CPU_TYPE_POWERPC64
:
1968 switch(cpusubtype
& ~CPU_SUBTYPE_MASK
){
1969 case CPU_SUBTYPE_POWERPC_ALL
:
1970 printf(" cputype CPU_TYPE_POWERPC64\n"
1971 " cpusubtype CPU_SUBTYPE_POWERPC_ALL\n");
1973 case CPU_SUBTYPE_POWERPC_970
:
1974 printf(" cputype CPU_TYPE_POWERPC64\n"
1975 " cpusubtype CPU_SUBTYPE_POWERPC_970\n");
1978 goto print_arch_unknown
;
1982 switch(cpusubtype
& ~CPU_SUBTYPE_MASK
){
1983 case CPU_SUBTYPE_VEO_1
:
1984 printf(" cputype CPU_TYPE_VEO\n"
1985 " cpusubtype CPU_SUBTYPE_VEO_1\n");
1987 case CPU_SUBTYPE_VEO_2
:
1988 printf(" cputype CPU_TYPE_VEO\n"
1989 " cpusubtype CPU_SUBTYPE_VEO_2\n");
1991 case CPU_SUBTYPE_VEO_3
:
1992 printf(" cputype CPU_TYPE_VEO\n"
1993 " cpusubtype CPU_SUBTYPE_VEO_3\n");
1995 case CPU_SUBTYPE_VEO_4
:
1996 printf(" cputype CPU_TYPE_VEO\n"
1997 " cpusubtype CPU_SUBTYPE_VEO_4\n");
2000 goto print_arch_unknown
;
2003 case CPU_TYPE_MC88000
:
2004 switch(cpusubtype
& ~CPU_SUBTYPE_MASK
){
2005 case CPU_SUBTYPE_MC88000_ALL
:
2006 printf(" cputype CPU_TYPE_MC88000\n"
2007 " cpusubtype CPU_SUBTYPE_MC88000_ALL\n");
2009 case CPU_SUBTYPE_MC88110
:
2010 printf(" cputype CPU_TYPE_MC88000\n"
2011 " cpusubtype CPU_SUBTYPE_MC88110\n");
2014 goto print_arch_unknown
;
2018 switch(cpusubtype
& ~CPU_SUBTYPE_MASK
){
2019 case CPU_SUBTYPE_I386_ALL
:
2020 /* case CPU_SUBTYPE_386: same as above */
2021 printf(" cputype CPU_TYPE_I386\n"
2022 " cpusubtype CPU_SUBTYPE_I386_ALL\n");
2024 case CPU_SUBTYPE_486
:
2025 printf(" cputype CPU_TYPE_I386\n"
2026 " cpusubtype CPU_SUBTYPE_486\n");
2028 case CPU_SUBTYPE_486SX
:
2029 printf(" cputype CPU_TYPE_I386\n"
2030 " cpusubtype CPU_SUBTYPE_486SX\n");
2032 case CPU_SUBTYPE_PENT
: /* same as 586 */
2033 printf(" cputype CPU_TYPE_I386\n"
2034 " cpusubtype CPU_SUBTYPE_PENT\n");
2036 case CPU_SUBTYPE_PENTPRO
:
2037 printf(" cputype CPU_TYPE_I386\n"
2038 " cpusubtype CPU_SUBTYPE_PENTPRO\n");
2040 case CPU_SUBTYPE_PENTII_M3
:
2041 printf(" cputype CPU_TYPE_I386\n"
2042 " cpusubtype CPU_SUBTYPE_PENTII_M3\n");
2044 case CPU_SUBTYPE_PENTII_M5
:
2045 printf(" cputype CPU_TYPE_I386\n"
2046 " cpusubtype CPU_SUBTYPE_PENTII_M5\n");
2049 goto print_arch_unknown
;
2052 case CPU_TYPE_X86_64
:
2053 switch(cpusubtype
& ~CPU_SUBTYPE_MASK
){
2054 case CPU_SUBTYPE_X86_64_ALL
:
2055 printf(" cputype CPU_TYPE_X86_64\n"
2056 " cpusubtype CPU_SUBTYPE_X86_64_ALL\n");
2059 goto print_arch_unknown
;
2063 switch(cpusubtype
& ~CPU_SUBTYPE_MASK
){
2064 case CPU_SUBTYPE_I860_ALL
:
2065 printf(" cputype CPU_TYPE_I860\n"
2066 " cpusubtype CPU_SUBTYPE_I860_ALL\n");
2068 case CPU_SUBTYPE_I860_860
:
2069 printf(" cputype CPU_TYPE_I860\n"
2070 " cpusubtype CPU_SUBTYPE_I860_860\n");
2073 goto print_arch_unknown
;
2077 switch(cpusubtype
& ~CPU_SUBTYPE_MASK
){
2078 case CPU_SUBTYPE_HPPA_ALL
:
2079 printf(" cputype CPU_TYPE_HPPA\n"
2080 " cpusubtype CPU_SUBTYPE_HPPA_ALL\n");
2082 case CPU_SUBTYPE_HPPA_7100LC
:
2083 printf(" cputype CPU_TYPE_HPPA\n"
2084 " cpusubtype CPU_SUBTYPE_HPPA_7100LC\n");
2087 goto print_arch_unknown
;
2090 case CPU_TYPE_SPARC
:
2091 switch(cpusubtype
& ~CPU_SUBTYPE_MASK
){
2092 case CPU_SUBTYPE_SPARC_ALL
:
2093 printf(" cputype CPU_TYPE_SPARC\n"
2094 " cpusubtype CPU_SUBTYPE_SPARC_ALL\n");
2097 goto print_arch_unknown
;
2102 case CPU_SUBTYPE_ARM_V4T
:
2103 printf(" cputype CPU_TYPE_ARM\n"
2104 " cpusubtype CPU_SUBTYPE_ARM_V4T\n");
2106 case CPU_SUBTYPE_ARM_V5TEJ
:
2107 printf(" cputype CPU_TYPE_ARM\n"
2108 " cpusubtype CPU_SUBTYPE_ARM_V5TEJ\n");
2110 case CPU_SUBTYPE_ARM_XSCALE
:
2111 printf(" cputype CPU_TYPE_ARM\n"
2112 " cpusubtype CPU_SUBTYPE_ARM_XSCALE\n");
2114 case CPU_SUBTYPE_ARM_V6
:
2115 printf(" cputype CPU_TYPE_ARM\n"
2116 " cpusubtype CPU_SUBTYPE_ARM_V6\n");
2118 case CPU_SUBTYPE_ARM_ALL
:
2119 printf(" cputype CPU_TYPE_ARM\n"
2120 " cpusubtype CPU_SUBTYPE_ARM_ALL\n");
2123 goto print_arch_unknown
;
2127 switch(cpusubtype
& ~CPU_SUBTYPE_MASK
){
2128 case CPU_SUBTYPE_MULTIPLE
:
2129 printf(" cputype CPU_TYPE_ANY\n"
2130 " cpusubtype CPU_SUBTYPE_MULTIPLE\n");
2132 case CPU_SUBTYPE_LITTLE_ENDIAN
:
2133 printf(" cputype CPU_TYPE_ANY\n"
2134 " cpusubtype CPU_SUBTYPE_LITTLE_ENDIAN\n");
2136 case CPU_SUBTYPE_BIG_ENDIAN
:
2137 printf(" cputype CPU_TYPE_ANY\n"
2138 " cpusubtype CPU_SUBTYPE_BIG_ENDIAN\n");
2141 goto print_arch_unknown
;
2146 printf(" cputype (%d)\n"
2147 " cpusubtype cpusubtype (%d)\n", cputype
,
2148 cpusubtype
& ~CPU_SUBTYPE_MASK
);
2154 * size_ar_name is used to return the size of the name of an archive member
2155 * for printing it without blanks (with printf string "%.*s").
2163 struct ar_hdr ar_hdr
;
2165 for(j
= 0; j
< sizeof(ar_hdr
.ar_name
); j
++){
2166 if(ar_name
[j
] == ' ')
2173 * Create a new input file struct, clear it and return it.
2179 struct input_file
*input
;
2181 input_files
= reallocate(input_files
,
2182 (ninput_files
+ 1) * sizeof(struct input_file
));
2183 input
= input_files
+ ninput_files
;
2185 memset(input
, '\0', sizeof(struct input_file
));
2190 * Create a new thin file struct, clear it and return it.
2196 struct thin_file
*thin
;
2198 thin_files
= reallocate(thin_files
,
2199 (nthin_files
+ 1) * sizeof(struct thin_file
));
2200 thin
= thin_files
+ nthin_files
;
2202 memset(thin
, '\0', sizeof(struct thin_file
));
2207 * Create a new arch_flag struct on the specified list, clear it and return it.
2212 struct arch_flag
**arch_flags
,
2213 uint32_t *narch_flags
)
2215 struct arch_flag
*arch_flag
;
2217 *arch_flags
= reallocate(*arch_flags
,
2218 (*narch_flags
+ 1) * sizeof(struct arch_flag
));
2219 arch_flag
= *arch_flags
+ *narch_flags
;
2220 *narch_flags
= *narch_flags
+ 1;
2221 memset(arch_flag
, '\0', sizeof(struct arch_flag
));
2226 * Create a new replace struct, clear it and return it.
2232 struct replace
*replace
;
2234 replaces
= reallocate(replaces
,
2235 (nreplaces
+ 1) * sizeof(struct replace
));
2236 replace
= replaces
+ nreplaces
;
2238 memset(replace
, '\0', sizeof(struct replace
));
2243 * Create a new segalign struct, clear it and return it.
2249 struct segalign
*segalign
;
2251 segaligns
= reallocate(segaligns
,
2252 (nsegaligns
+ 1) * sizeof(struct segalign
));
2253 segalign
= segaligns
+ nsegaligns
;
2255 memset(segalign
, '\0', sizeof(struct segalign
));
2260 * Function for qsort for comparing thin file's alignment
2265 const struct thin_file
*thin1
,
2266 const struct thin_file
*thin2
)
2268 return(thin1
->fat_arch
.align
- thin2
->fat_arch
.align
);
2272 * round() rounds v to a multiple of r.
2287 * ispoweroftwo() returns TRUE or FALSE depending if x is a power of two.
2297 while((x
& 0x1) != 0x1){
2307 * check_arch is called when an input file is specified with a -arch flag input
2308 * and that the architecture can be determined from the input to check that
2309 * both architectures match.
2314 struct input_file
*input
,
2315 struct thin_file
*thin
)
2317 if(input
->arch_flag
.cputype
!= thin
->fat_arch
.cputype
)
2318 fatal("specifed architecture type (%s) for file (%s) does "
2319 "not match its cputype (%d) and cpusubtype (%d) "
2320 "(should be cputype (%d) and cpusubtype (%d))",
2321 input
->arch_flag
.name
, input
->name
,
2322 thin
->fat_arch
.cputype
, thin
->fat_arch
.cpusubtype
&
2323 ~CPU_SUBTYPE_MASK
, input
->arch_flag
.cputype
,
2324 input
->arch_flag
.cpusubtype
& ~CPU_SUBTYPE_MASK
);
2328 * Create a blank dylib. This is a stub dylib with no load commands.
2329 * It is a target page size block of bytes of zero except for the mach_header.
2334 struct arch_flag
*arch
)
2336 uint32_t target_page_size
, align
, onebit
;
2337 struct thin_file
*file
;
2338 enum byte_sex host_byte_sex
, target_byte_sex
;
2339 struct mach_header
*mh
;
2340 struct mach_header_64
*mh64
;
2343 file
->name
= "blank dylib";
2344 target_page_size
= get_segalign_from_flag(arch
);
2345 file
->addr
= allocate(target_page_size
);
2346 memset(file
->addr
, '\0', target_page_size
);
2347 file
->fat_arch
.cputype
= arch
->cputype
;
2348 file
->fat_arch
.cpusubtype
= arch
->cpusubtype
;
2349 file
->fat_arch
.offset
= 0;
2350 file
->fat_arch
.size
= target_page_size
;
2352 for(align
= 1; (target_page_size
& onebit
) != onebit
; align
++)
2353 onebit
= onebit
<< 1;
2354 file
->fat_arch
.align
= align
;
2356 host_byte_sex
= get_host_byte_sex();
2357 target_byte_sex
= get_byte_sex_from_flag(arch
);
2359 if((arch
->cputype
& CPU_ARCH_ABI64
) == CPU_ARCH_ABI64
){
2360 mh64
= (struct mach_header_64
*)file
->addr
;
2361 mh64
->magic
= MH_MAGIC_64
;
2362 mh64
->cputype
= arch
->cputype
;
2363 mh64
->cpusubtype
= arch
->cpusubtype
;
2364 mh64
->filetype
= MH_DYLIB_STUB
;
2365 if(target_byte_sex
!= host_byte_sex
)
2366 swap_mach_header_64(mh64
, target_byte_sex
);
2369 mh
= (struct mach_header
*)file
->addr
;
2370 mh
->magic
= MH_MAGIC
;
2371 mh
->cputype
= arch
->cputype
;
2372 mh
->cpusubtype
= arch
->cpusubtype
;
2373 mh
->filetype
= MH_DYLIB_STUB
;
2374 if(target_byte_sex
!= host_byte_sex
)
2375 swap_mach_header(mh
, target_byte_sex
);
2381 * Print the current usage line and exit (by calling fatal).
2387 fatal("Usage: %s [input_file] ... [-arch <arch_type> input_file] ... "
2388 "[-info] [-detailed_info] [-output output_file] [-create] "
2389 "[-arch_blank <arch_type>] [-thin <arch_type>] "
2390 "[-remove <arch_type>] ... [-extract <arch_type>] ... "
2391 "[-extract_family <arch_type>] ... "
2392 "[-verify_arch <arch_type> ...] "
2393 "[-replace <arch_type> <file_name>] ...", progname
);