Merge pull request #8 from biergaizi/upstream
[darwin-xtools.git] / cctools / misc / libtool.c
blobeef4175129ce517e21c83b870fad2b8c589101aa
1 /*
2 * Copyright (c) 1999-2003 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
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 NeXT Computer, Inc. libtool(1) program that handles fat files, archives
25 * and Mach-O objects files (no 4.3bsd a.out files). This is also the ranlib(1)
26 * program.
28 #include <mach/mach.h>
29 #include "stuff/openstep_mach.h"
30 #include <libc.h>
31 #ifndef __OPENSTEP__
32 #include <utime.h>
33 #endif
34 #include <stdio.h>
35 #include <stdlib.h>
36 #include <string.h>
37 #include <signal.h>
38 #include <ar.h>
39 #include <mach-o/ranlib.h>
40 #include <sys/types.h>
41 #include <sys/stat.h>
42 #include <sys/mman.h>
43 #include "stuff/bool.h"
44 #include "stuff/ofile.h"
45 #include "stuff/rnd.h"
46 #include "stuff/errors.h"
47 #include "stuff/allocate.h"
48 #include "stuff/execute.h"
49 #include "stuff/version_number.h"
50 #include "stuff/unix_standard_mode.h"
51 #ifdef LTO_SUPPORT
52 #include "stuff/lto.h"
53 #endif /* LTO_SUPPORT */
55 #include <mach/mach_init.h>
56 #if defined(__OPENSTEP__) || defined(__GONZO_BUNSEN_BEAKER__)
57 #include <servers/netname.h>
58 #else
59 #ifndef __has_extension
60 # define __has_extension(x) 0
61 #endif
62 #ifndef __has_feature
63 #define __has_feature(x) 0
64 #endif
65 #include <servers/bootstrap.h>
66 #endif
69 * This is used internally to build the table of contents.
71 struct toc {
72 char *name; /* symbol defined by */
73 int64_t index1; /* library member at this index plus 1 */
76 /* used by error routines as the name of the program */
77 char *progname = NULL;
78 /* .. as above but without the path, if any was used in the invocation. */
79 char *pnam = NULL;
81 /* the bytesex of the host this program is running on */
82 static enum byte_sex host_byte_sex = UNKNOWN_BYTE_SEX;
85 * The time the table of contents' are set to and the time to base the
86 * modification time of the output file to be set to.
88 static time_t toc_time = 0;
91 * The environment variable ZERO_AR_DATE is used here and other places that
92 * write archives to allow testing and comparing things for exact binary
93 * equality.
95 static enum bool zero_ar_date = FALSE;
98 * The mode of the table of contents member (S_IFREG | (0666 & ~umask))
100 static u_short toc_mode = 0;
102 /* flags set from the command line arguments */
103 struct cmd_flags {
104 char **files; /* array of file name arguments */
105 uint32_t
106 nfiles; /* number of file name arguments */
107 char **filelist; /* filelist argument the file name argument came from */
108 enum bool
109 no_files_ok; /* ok to see no files */
110 enum bool ranlib; /* set if this is run as ranlib not libtool */
111 enum bool s; /* sort the table of contents */
112 enum bool a; /* don't sort the table of contents (original form) */
113 enum bool c; /* include commmon symbols in the table of contents */
114 enum bool t; /* just "touch" the archives to get the date right */
115 enum bool f; /* warn if the output archive is fat,used by ar(1) -s */
116 enum bool q; /* only write archive if NOT fat, used by ar(1) */
117 char *output; /* the output file specified by -o */
118 enum bool final_output_specified; /* if -final_output is specified */
119 enum bool dynamic; /* create a dynamic shared library, static by default */
120 char *compatibility;/* compatibility version if specified, NULL otherwise */
121 char *current; /* current version if specified, NULL otherwise */
122 char *install_name; /* install name if specified, NULL otherwise */
123 char *seg1addr; /* seg1addr if specified, NULL otherwise */
124 char *segs_read_only_addr; /* segs_read_only_addr if specified, or NULL */
125 char *segs_read_write_addr; /* segs_read_write_addr if specified, or NULL */
126 char *seg_addr_table; /* seg_addr_table if specified, or NULL */
127 char *seg_addr_table_filename;
128 /* seg_addr_table_filename if specified, or NULL */
129 char **Ldirs; /* array of -Ldir arguments */
130 uint32_t
131 nLdirs; /* number of -Ldir arguments */
132 char **ldflags; /* other ld(1) flags to pass */
133 uint32_t
134 nldflags; /* number of ld(1) flags for above */
135 enum bool verbose; /* print exec(2) commands run */
136 struct arch_flag
137 arch_only_flag; /* the -arch_only flag if specified */
138 enum bool /* set if either -prebind or -noprebind is seen */
139 prebinding_flag_specified;
140 enum bool /* set if -prebind is seen or the LD_PREBIND */
141 prebinding; /* environment variable is set (and -noprebind isn't)*/
142 enum bool /* set if either -all_load or -noall_load is seen */
143 all_load_flag_specified;
144 enum bool /* set if -all_load is seen (and -noall_load isn't) */
145 all_load;
146 enum bool /* set with -L (the default) off with -T, for -static */
147 use_long_names; /* use 4.4bsd extended format 1 for long names */
148 enum bool L_or_T_specified;
149 enum bool /* set if the environ var LD_TRACE_ARCHIVES is set */
150 ld_trace_archives;
151 const char * /* LD_TRACE_FILE if set and LD_TRACE_ARCHIVES is set, or NULL */
152 trace_file_path;
153 enum bool /* set if -search_paths_first is specified */
154 search_paths_first;
155 enum bool noflush; /* don't use the output_flush routine to flush the
156 static library output file by pages */
157 uint32_t debug; /* debug value to debug output_flush() routine */
158 enum bool /* don't warn if members have no symbols */
159 no_warning_for_no_symbols;
160 enum bool toc64; /* force the use of the 64-bit toc */
161 enum bool fat64; /* force the use of 64-bit fat files
162 when a fat is to be created */
164 static struct cmd_flags cmd_flags = { 0 };
166 /* The value of the environment variable NEXT_ROOT */
167 static char *next_root = NULL;
169 /* the standard directories to search for -lx names */
170 char *standard_dirs[] = {
171 "/lib/",
172 "/usr/lib/",
173 "/usr/local/lib/",
174 NULL
178 * The input files are broken down in to their object files and then placed in
179 * these structures. They are sorted by architecture type and then each object
180 * has a member struct created for it in one of the arch structs. All of these
181 * structs hang off of 'archs'.
183 static struct arch *archs = NULL;
184 static uint32_t narchs = 0;
186 struct arch {
187 struct arch_flag arch_flag; /* the identifing info of this architecture */
188 uint64_t size; /* current working size and final size */
190 /* the table of contents (toc) stuff for this architecture in the library */
191 uint32_t toc_size; /* total size of the toc including ar_hdr */
192 struct ar_hdr toc_ar_hdr; /* the archive header for this member */
193 enum bool toc_long_name; /* use the long name in the output */
194 char *toc_name; /* name of toc member */
195 uint32_t toc_name_size;/* size of name of toc member */
196 struct toc *tocs; /* internal table of contents */
197 enum bool using_64toc; /* TRUE if we are using a 64-bit toc */
198 struct ranlib *toc_ranlibs; /* 32-bit ranlib structs for output */
199 struct ranlib_64 *toc_ranlibs64; /* 64-bit ranlib structs for output */
200 uint64_t toc_nranlibs;/* number of ranlib structs */
201 char *toc_strings; /* strings of symbol names for ranlib structs */
202 uint64_t toc_strsize; /* number of bytes for the strings above */
204 /* the members of this architecture in the library */
205 struct member *members; /* the members of the library for this arch */
206 uint32_t nmembers; /* the number of the above members */
209 struct member {
210 uint64_t offset; /* current working offset and final offset*/
211 struct ar_hdr ar_hdr; /* the archive header for this member */
212 char null_byte; /* space to write '\0' for ar_hdr */
213 char *object_addr; /* the address of the object file */
214 uint32_t object_size; /* the size of the object file */
215 enum byte_sex object_byte_sex; /* the byte sex of the object file */
216 struct mach_header *mh; /* the mach_header of 32-bit object files */
217 struct mach_header_64 *mh64; /* the mach_header of 64-bit object files */
218 struct load_command /* the start of the load commands */
219 *load_commands;
220 struct symtab_command *st; /* the symbol table command */
221 struct section **sections; /* array of section structs for 32-bit */
222 struct section_64 **sections64; /* array of section structs for 64-bit */
223 #ifdef LTO_SUPPORT
224 enum bool lto_contents; /* TRUE if this member has lto contents */
225 uint32_t lto_toc_nsyms; /* number of symbols for the toc */
226 uint32_t lto_toc_strsize; /* the size of the strings for the toc */
227 char *lto_toc_strings; /* the strings of the symbols for the toc */
228 #endif /* LTO_SUPPORT */
230 /* the name of the member in the output */
231 char *member_name; /* the member name */
232 uint32_t member_name_size; /* the size of the member name */
233 enum bool output_long_name; /* use the extended format #1 for the
234 member name in the output */
236 /* info recorded from the input file this member came from */
237 char *input_file_name; /* the input file name */
238 char *input_base_name; /* the base name in the input file */
239 uint32_t input_base_name_size; /* the size of the base name */
240 struct ar_hdr *input_ar_hdr;
241 uint64_t input_member_offset; /* if from a thin archive */
244 static void usage(
245 int);
246 static void process(
247 void);
248 static char *file_name_from_l_flag(
249 char *l_flag);
250 static char *search_for_file(
251 char *base_name);
252 static char * search_paths_for_lname(
253 const char *lname_argument);
254 static char * search_path_for_lname(
255 const char *dir,
256 const char *lname_argument);
257 static void add_member(
258 struct ofile *ofile);
259 static void free_archs(
260 void);
261 static void create_library(
262 char *output,
263 struct ofile *ofile);
264 static enum byte_sex get_target_byte_sex(
265 struct arch *arch,
266 enum byte_sex host_byte_sex);
267 static char *put_toc_member(
268 char *p,
269 struct arch *arch,
270 enum byte_sex host_byte_sex,
271 enum byte_sex target_byte_sex);
272 static void create_dynamic_shared_library(
273 char *output);
274 static void create_dynamic_shared_library_cleanup(
275 int sig);
276 static void make_table_of_contents(
277 struct arch *arch,
278 char *output);
279 #ifdef LTO_SUPPORT
280 static void save_lto_member_toc_info(
281 struct member *member,
282 void *mod);
283 #endif /* LTO_SUPPORT */
284 static int toc_name_qsort(
285 const struct toc *toc1,
286 const struct toc *toc2);
287 static int toc_index1_qsort(
288 const struct toc *toc1,
289 const struct toc *toc2);
290 static enum bool toc_symbol(
291 struct nlist *symbol,
292 struct section **sections);
293 static enum bool toc_symbol_64(
294 struct nlist_64 *symbol64,
295 struct section_64 **sections64);
296 static enum bool toc(
297 uint32_t n_strx,
298 uint8_t n_type,
299 uint64_t n_value,
300 enum bool attr_no_toc);
301 static enum bool check_sort_tocs(
302 struct arch *arch,
303 char *output,
304 enum bool library_warnings);
305 static void warn_duplicate_member_names(
306 void);
307 static int member_name_qsort(
308 const struct member *member1,
309 const struct member *member2);
310 static int member_offset_qsort(
311 const struct member *member1,
312 const struct member *member2);
313 static void warn_member(
314 struct arch *arch,
315 struct member *member,
316 const char *format, ...) __attribute__ ((format (printf, 3, 4)));
317 static void ld_trace(
318 const char *format, ...) __attribute__ ((format (printf, 1, 2)));
321 * This structure is used to describe blocks of the output file that are flushed
322 * to the disk file with output_flush. It is kept in an ordered list starting
323 * with output_blocks.
325 static struct block {
326 uint64_t offset; /* starting offset of this block */
327 uint64_t size; /* size of this block */
328 uint64_t written_offset;/* first page offset after starting offset */
329 uint64_t written_size; /* size of written area from written_offset */
330 struct block *next; /* next block in the list */
331 } *output_blocks;
333 static void output_flush(
334 char *library,
335 uint64_t library_size,
336 int fd,
337 uint64_t offset,
338 uint64_t size);
339 static void final_output_flush(
340 char *library,
341 int fd);
342 #ifdef DEBUG
343 static void print_block_list(void);
344 #endif /* DEBUG */
345 static struct block *get_block(void);
346 static void remove_block(
347 struct block *block);
348 static uint32_t trnc(
349 uint32_t v,
350 uint32_t r);
352 /* apple_version is in vers.c which is created by the libstuff/Makefile */
353 extern char apple_version[];
355 /* likewise xtools_version, lto_suport and support_url. */
356 extern char xtools_version[];
357 extern char package_version[];
358 extern char support_url[];
359 extern char lto_support[];
361 #define RSZ (sizeof("ranlib")-1)
363 main(
364 int argc,
365 char **argv,
366 char **envp)
368 char *p, *endp, *filelist, *dirname, *addr;
369 int fd, i, len, sz;
370 struct stat stat_buf;
371 uint32_t j, nfiles, maxfiles;
372 uint32_t temp;
373 int oumask, numask;
374 enum bool lflags_seen, bad_flag_seen, Vflag;
376 lflags_seen = FALSE;
377 Vflag = FALSE;
378 progname = argv[0];
380 host_byte_sex = get_host_byte_sex();
383 * The environment variable ZERO_AR_DATE is used here and other
384 * places that write archives to allow testing and comparing
385 * things for exact binary equality.
387 if(getenv("ZERO_AR_DATE") == NULL)
388 zero_ar_date = FALSE;
389 else
390 zero_ar_date = TRUE;
391 if(zero_ar_date == FALSE)
392 toc_time = time(0);
393 else
394 toc_time = 0;
396 numask = 0;
397 oumask = umask(numask);
398 toc_mode = S_IFREG | (0666 & ~oumask);
399 (void)umask(oumask);
401 /* see if this is being run as ranlib */
402 pnam = strrchr(argv[0], '/');
403 if(pnam != NULL)
404 pnam++;
405 else
406 pnam = argv[0];
408 len = strlen(pnam);
409 /* If the name by which this was invoked ends in 'ranlib' then we are in
410 ranlib mode. */
411 if(len >= RSZ && strncmp(pnam+len-RSZ, "ranlib", RSZ) == 0)
412 cmd_flags.ranlib = TRUE;
414 /* The default is to used long names */
415 cmd_flags.use_long_names = TRUE;
417 /* process the command line arguments and collect the files */
418 maxfiles = argc;
419 cmd_flags.files = allocate(sizeof(char *) * maxfiles);
420 cmd_flags.filelist = allocate(sizeof(char *) * maxfiles);
421 memset(cmd_flags.filelist, '\0', sizeof(char *) * maxfiles);
422 for(i = 1; i < argc; i++){
423 if(argv[i][0] == '-'){
424 if(strcmp(argv[i], "--version") == 0){
425 /* Implement a gnu-style --version. */
426 fprintf(stdout, "xtools-%s %s %s\nBased on Apple Inc. %s%s\n",
427 xtools_version, pnam, package_version,
428 apple_version, lto_support);
429 exit(0);
430 } else if(strcmp(argv[i], "--help") == 0){
431 usage(0);
432 fprintf(stdout, "Please report bugs to %s\n", support_url);
433 exit(0);
435 if(argv[i][1] == '\0'){
436 for(i += 1 ; i < argc; i++)
437 cmd_flags.files[cmd_flags.nfiles++] = argv[i];
438 break;
440 if(strcmp(argv[i], "-o") == 0){
441 if(cmd_flags.ranlib == TRUE){
442 error("unknown option: %s", argv[i]);
443 usage(EXIT_FAILURE);
445 if(i + 1 == argc){
446 error("missing argument to: %s option", argv[i]);
447 usage(EXIT_FAILURE);
449 if(cmd_flags.output != NULL){
450 error("more than one: %s option specified", argv[i]);
451 usage(EXIT_FAILURE);
453 cmd_flags.output = argv[i+1];
454 i++;
456 else if(strcmp(argv[i], "-arch_only") == 0){
457 if(cmd_flags.ranlib == TRUE){
458 error("unknown option: %s", argv[i]);
459 usage(EXIT_FAILURE);
461 if(i + 1 == argc){
462 error("missing argument to %s option", argv[i]);
463 usage(EXIT_FAILURE);
465 if(cmd_flags.arch_only_flag.name != NULL){
466 error("more than one: %s option specified", argv[i]);
467 usage(EXIT_FAILURE);
469 else{
470 if(get_arch_from_flag(argv[i+1],
471 &cmd_flags.arch_only_flag) == 0){
472 error("unknown architecture specification flag: "
473 "%s %s", argv[i], argv[i+1]);
474 arch_usage();
475 usage(EXIT_FAILURE);
478 i++;
480 else if(strcmp(argv[i], "-dynamic") == 0){
481 if(cmd_flags.ranlib == TRUE){
482 error("unknown option: %s", argv[i]);
483 usage(EXIT_FAILURE);
485 cmd_flags.dynamic = TRUE;
487 else if(strcmp(argv[i], "-static") == 0){
488 if(cmd_flags.ranlib == TRUE){
489 error("unknown option: %s", argv[i]);
490 usage(EXIT_FAILURE);
492 cmd_flags.dynamic = FALSE;
494 else if(strcmp(argv[i], "-filelist") == 0){
495 if(cmd_flags.ranlib == TRUE){
496 error("unknown option: %s", argv[i]);
497 usage(EXIT_FAILURE);
499 if(i + 1 == argc){
500 error("missing argument to: %s option", argv[i]);
501 usage(EXIT_FAILURE);
503 filelist = argv[i + 1];
504 dirname = strrchr(filelist, ',');
505 if(dirname != NULL){
506 *dirname = '\0';
507 dirname++;
509 else
510 dirname = "";
511 if((fd = open(filelist, O_RDONLY, 0)) == -1)
512 system_fatal("can't open file list file: %s", filelist);
513 if(fstat(fd, &stat_buf) == -1)
514 system_fatal("can't stat file list file: %s", filelist);
516 * For some reason mapping files with zero size fails
517 * so it has to be handled specially.
519 addr = NULL;
520 if(stat_buf.st_size != 0){
521 addr = mmap(0, stat_buf.st_size, PROT_READ|PROT_WRITE,
522 MAP_FILE|MAP_PRIVATE, fd, 0);
523 if((intptr_t)addr == -1)
524 system_error("can't map file list file: %s",
525 filelist);
527 else{
528 fatal("file list file: %s is empty", filelist);
530 if(*dirname != '\0')
531 dirname[-1] = ',';
532 close(fd);
533 nfiles = 0;
534 for(j = 0; j < stat_buf.st_size; j++){
535 if(addr[j] == '\n')
536 nfiles++;
538 if(addr[stat_buf.st_size - 1] != '\n')
539 nfiles++;
540 p = allocate((strlen(dirname) + 1) * nfiles +
541 stat_buf.st_size);
542 cmd_flags.files = reallocate(cmd_flags.files,
543 sizeof(char *) * (maxfiles + nfiles));
544 cmd_flags.filelist = reallocate(cmd_flags.filelist,
545 sizeof(char *) * (maxfiles + nfiles));
546 memset(cmd_flags.filelist + maxfiles, '\0',
547 sizeof(char *) * nfiles);
548 maxfiles += nfiles;
550 cmd_flags.files[cmd_flags.nfiles] = p;
551 cmd_flags.filelist[cmd_flags.nfiles] = filelist;
552 cmd_flags.nfiles++;
553 if(*dirname != '\0'){
554 strcpy(p, dirname);
555 p += strlen(dirname);
556 *p++ = '/';
558 for(j = 0; j < stat_buf.st_size; j++){
559 if(addr[j] != '\n')
560 *p++ = addr[j];
561 else{
562 *p++ = '\0';
563 if(j != stat_buf.st_size - 1){
564 cmd_flags.files[cmd_flags.nfiles] = p;
565 cmd_flags.filelist[cmd_flags.nfiles] =argv[i+1];
566 cmd_flags.nfiles++;
567 if(*dirname != '\0'){
568 strcpy(p, dirname);
569 p += strlen(dirname);
570 *p++ = '/';
575 if(addr[stat_buf.st_size - 1] != '\n')
576 *p = '\0';
577 i++;
579 else if(strcmp(argv[i], "-compatibility_version") == 0){
580 if(cmd_flags.ranlib == TRUE){
581 error("unknown option: %s", argv[i]);
582 usage(EXIT_FAILURE);
584 if(i + 1 == argc){
585 error("missing argument to: %s option", argv[i]);
586 usage(EXIT_FAILURE);
588 if(cmd_flags.compatibility != NULL){
589 error("more than one: %s option specified", argv[i]);
590 usage(EXIT_FAILURE);
592 if(get_version_number(argv[i], argv[i+1], &temp) == FALSE){
593 usage(EXIT_FAILURE);
595 cmd_flags.compatibility = argv[i+1];
596 i++;
598 else if(strcmp(argv[i], "-current_version") == 0){
599 if(cmd_flags.ranlib == TRUE){
600 error("unknown option: %s", argv[i]);
601 usage(EXIT_FAILURE);
603 if(i + 1 == argc){
604 error("missing argument to: %s option", argv[i]);
605 usage(EXIT_FAILURE);
607 if(cmd_flags.current != NULL){
608 error("more than one: %s option specified", argv[i]);
609 usage(EXIT_FAILURE);
611 if(get_version_number(argv[i], argv[i+1], &temp) == FALSE){
612 usage(EXIT_FAILURE);
614 cmd_flags.current = argv[i+1];
615 i++;
617 else if(strcmp(argv[i], "-install_name") == 0){
618 if(cmd_flags.ranlib == TRUE){
619 error("unknown option: %s", argv[i]);
620 usage(EXIT_FAILURE);
622 if(i + 1 == argc){
623 error("missing argument to: %s option", argv[i]);
624 usage(EXIT_FAILURE);
626 if(cmd_flags.install_name != NULL){
627 error("more than one: %s option specified", argv[i]);
628 usage(EXIT_FAILURE);
630 cmd_flags.install_name = argv[i+1];
631 i++;
633 else if(strcmp(argv[i], "-seg1addr") == 0 ||
634 strcmp(argv[i], "-image_base") == 0){
635 if(cmd_flags.ranlib == TRUE){
636 error("unknown option: %s", argv[i]);
637 usage(EXIT_FAILURE);
639 if(i + 1 == argc){
640 error("missing argument to: %s option", argv[i]);
641 usage(EXIT_FAILURE);
643 if(cmd_flags.seg1addr != NULL){
644 error("more than one: %s option specified", argv[i]);
645 usage(EXIT_FAILURE);
647 temp = strtoul(argv[i + 1], &endp, 16);
648 if(*endp != '\0'){
649 error("address for -seg1addr %s not a proper "
650 "hexadecimal number", argv[i+1]);
651 usage(EXIT_FAILURE);
653 cmd_flags.seg1addr = argv[i+1];
654 i++;
656 else if(strcmp(argv[i], "-segs_read_only_addr") == 0){
657 if(cmd_flags.ranlib == TRUE){
658 error("unknown option: %s", argv[i]);
659 usage(EXIT_FAILURE);
661 if(i + 1 == argc){
662 error("missing argument to: %s option", argv[i]);
663 usage(EXIT_FAILURE);
665 if(cmd_flags.segs_read_only_addr != NULL){
666 error("more than one: %s option specified", argv[i]);
667 usage(EXIT_FAILURE);
669 temp = strtoul(argv[i + 1], &endp, 16);
670 if(*endp != '\0'){
671 error("address for -segs_read_only_addr %s not a "
672 "proper hexadecimal number", argv[i+1]);
673 usage(EXIT_FAILURE);
675 cmd_flags.segs_read_only_addr = argv[i+1];
676 i++;
678 else if(strcmp(argv[i], "-segs_read_write_addr") == 0){
679 if(cmd_flags.ranlib == TRUE){
680 error("unknown option: %s", argv[i]);
681 usage(EXIT_FAILURE);
683 if(i + 1 == argc){
684 error("missing argument to: %s option", argv[i]);
685 usage(EXIT_FAILURE);
687 if(cmd_flags.segs_read_write_addr != NULL){
688 error("more than one: %s option specified", argv[i]);
689 usage(EXIT_FAILURE);
691 temp = strtoul(argv[i + 1], &endp, 16);
692 if(*endp != '\0'){
693 error("address for -segs_read_write_addr %s not a "
694 "proper hexadecimal number", argv[i+1]);
695 usage(EXIT_FAILURE);
697 cmd_flags.segs_read_write_addr = argv[i+1];
698 i++;
700 else if(strcmp(argv[i], "-seg_addr_table") == 0){
701 if(cmd_flags.ranlib == TRUE){
702 error("unknown option: %s", argv[i]);
703 usage(EXIT_FAILURE);
705 if(i + 1 == argc){
706 error("missing argument to: %s option", argv[i]);
707 usage(EXIT_FAILURE);
709 if(cmd_flags.seg_addr_table != NULL){
710 error("more than one: %s option specified", argv[i]);
711 usage(EXIT_FAILURE);
713 cmd_flags.seg_addr_table = argv[i+1];
714 i++;
716 else if(strcmp(argv[i], "-seg_addr_table_filename") == 0){
717 if(cmd_flags.ranlib == TRUE){
718 error("unknown option: %s", argv[i]);
719 usage(EXIT_FAILURE);
721 if(i + 1 == argc){
722 error("missing argument to: %s option", argv[i]);
723 usage(EXIT_FAILURE);
725 if(cmd_flags.seg_addr_table_filename != NULL){
726 error("more than one: %s option specified", argv[i]);
727 usage(EXIT_FAILURE);
729 cmd_flags.seg_addr_table_filename = argv[i+1];
730 i++;
732 else if(strcmp(argv[i], "-syslibroot") == 0){
733 if(cmd_flags.ranlib == TRUE){
734 error("unknown option: %s", argv[i]);
735 usage(EXIT_FAILURE);
737 if(i + 1 == argc){
738 error("missing argument to: %s option", argv[i]);
739 usage(EXIT_FAILURE);
741 if(next_root != NULL && strcmp(next_root, argv[i+1]) != 0){
742 error("more than one: %s option specified", argv[i]);
743 usage(EXIT_FAILURE);
745 next_root = argv[i+1];
746 cmd_flags.ldflags = reallocate(cmd_flags.ldflags,
747 sizeof(char *) * (cmd_flags.nldflags + 2));
748 cmd_flags.ldflags[cmd_flags.nldflags++] = argv[i];
749 cmd_flags.ldflags[cmd_flags.nldflags++] = argv[i+1];
750 i++;
752 else if(strcmp(argv[i], "-sectcreate") == 0 ||
753 strcmp(argv[i], "-segcreate") == 0 ||
754 strcmp(argv[i], "-sectorder") == 0 ||
755 strcmp(argv[i], "-sectalign") == 0 ||
756 strcmp(argv[i], "-segprot") == 0){
757 if(cmd_flags.ranlib == TRUE){
758 error("unknown option: %s", argv[i]);
759 usage(EXIT_FAILURE);
761 if(i + 3 >= argc){
762 error("not enough arguments follow %s", argv[i]);
763 usage(EXIT_FAILURE);
765 cmd_flags.ldflags = reallocate(cmd_flags.ldflags,
766 sizeof(char *) * (cmd_flags.nldflags + 4));
767 cmd_flags.ldflags[cmd_flags.nldflags++] = argv[i];
768 cmd_flags.ldflags[cmd_flags.nldflags++] = argv[i+1];
769 cmd_flags.ldflags[cmd_flags.nldflags++] = argv[i+2];
770 cmd_flags.ldflags[cmd_flags.nldflags++] = argv[i+3];
771 if(strcmp(argv[i], "-sectcreate") == 0 ||
772 strcmp(argv[i], "-segcreate") == 0)
773 cmd_flags.no_files_ok = TRUE;
774 i += 3;
776 else if(strcmp(argv[i], "-segalign") == 0 ||
777 strcmp(argv[i], "-undefined") == 0 ||
778 strcmp(argv[i], "-macosx_version_min") == 0 ||
779 strcmp(argv[i], "-ios_version_min") == 0 ||
780 strcmp(argv[i], "-ios_simulator_version_min") == 0 ||
781 strcmp(argv[i], "-watchos_version_min") == 0 ||
782 strcmp(argv[i], "-watchos_simulator_version_min") == 0 ||
783 strcmp(argv[i], "-tvos_version_min") == 0 ||
784 strcmp(argv[i], "-tvos_simulator_version_min") == 0 ||
785 strcmp(argv[i], "-multiply_defined") == 0 ||
786 strcmp(argv[i], "-multiply_defined_unused") == 0 ||
787 strcmp(argv[i], "-umbrella") == 0 ||
788 strcmp(argv[i], "-sub_umbrella") == 0 ||
789 strcmp(argv[i], "-sub_library") == 0 ||
790 strcmp(argv[i], "-allowable_client") == 0 ||
791 strcmp(argv[i], "-read_only_relocs") == 0 ||
792 strcmp(argv[i], "-init") == 0 ||
793 strcmp(argv[i], "-U") == 0 ||
794 strcmp(argv[i], "-Y") == 0 ||
795 strcmp(argv[i], "-dylib_file") == 0 ||
796 strcmp(argv[i], "-final_output") == 0 ||
797 strcmp(argv[i], "-headerpad") == 0 ||
798 strcmp(argv[i], "-weak_reference_mismatches") == 0 ||
799 strcmp(argv[i], "-u") == 0 ||
800 strcmp(argv[i], "-exported_symbols_list") == 0 ||
801 strcmp(argv[i], "-unexported_symbols_list") == 0 ||
802 strcmp(argv[i], "-executable_path") == 0){
803 if(cmd_flags.ranlib == TRUE){
804 error("unknown option: %s", argv[i]);
805 usage(EXIT_FAILURE);
807 if(i + 1 >= argc){
808 error("not enough arguments follow %s", argv[i]);
809 usage(EXIT_FAILURE);
811 cmd_flags.ldflags = reallocate(cmd_flags.ldflags,
812 sizeof(char *) * (cmd_flags.nldflags + 2));
813 cmd_flags.ldflags[cmd_flags.nldflags++] = argv[i];
814 cmd_flags.ldflags[cmd_flags.nldflags++] = argv[i+1];
815 if(strcmp(argv[i], "-final_output") == 0)
816 cmd_flags.final_output_specified = TRUE;
817 i += 1;
819 else if(strcmp(argv[i], "-sectorder_detail") == 0 ||
820 strcmp(argv[i], "-Sn") == 0 ||
821 strcmp(argv[i], "-Si") == 0 ||
822 strcmp(argv[i], "-Sp") == 0 ||
823 strcmp(argv[i], "-S") == 0 ||
824 strcmp(argv[i], "-X") == 0 ||
825 strcmp(argv[i], "-x") == 0 ||
826 strcmp(argv[i], "-whatsloaded") == 0 ||
827 strcmp(argv[i], "-whyload") == 0 ||
828 strcmp(argv[i], "-arch_errors_fatal") == 0 ||
829 strcmp(argv[i], "-run_init_lazily") == 0 ||
830 strcmp(argv[i], "-twolevel_namespace") == 0 ||
831 strcmp(argv[i], "-twolevel_namespace_hints") == 0 ||
832 strcmp(argv[i], "-flat_namespace") == 0 ||
833 strcmp(argv[i], "-nomultidefs") == 0 ||
834 strcmp(argv[i], "-headerpad_max_install_names") == 0 ||
835 strcmp(argv[i], "-prebind_all_twolevel_modules") == 0 ||
836 strcmp(argv[i], "-prebind_allow_overlap") == 0 ||
837 strcmp(argv[i], "-ObjC") == 0 ||
838 strcmp(argv[i], "-M") == 0 ||
839 strcmp(argv[i], "-t") == 0 ||
840 strcmp(argv[i], "-single_module") == 0 ||
841 strcmp(argv[i], "-multi_module") == 0 ||
842 strcmp(argv[i], "-m") == 0 ||
843 strcmp(argv[i], "-dead_strip") == 0 ||
844 strcmp(argv[i], "-no_uuid") == 0 ||
845 strcmp(argv[i], "-no_dead_strip_inits_and_terms") == 0){
846 if(cmd_flags.ranlib == TRUE){
847 error("unknown option: %s", argv[i]);
848 usage(EXIT_FAILURE);
850 cmd_flags.ldflags = reallocate(cmd_flags.ldflags,
851 sizeof(char *) * (cmd_flags.nldflags + 1));
852 cmd_flags.ldflags[cmd_flags.nldflags++] = argv[i];
854 else if(strcmp(argv[i], "-no_arch_warnings") == 0){
855 if(cmd_flags.ranlib == TRUE){
856 error("unknown option: %s", argv[i]);
857 usage(EXIT_FAILURE);
859 /* ignore this flag */
861 else if(strcmp(argv[i], "-prebind") == 0){
862 if(cmd_flags.ranlib == TRUE){
863 error("unknown option: %s", argv[i]);
864 usage(EXIT_FAILURE);
866 if(cmd_flags.prebinding_flag_specified == TRUE &&
867 cmd_flags.prebinding == FALSE){
868 error("both -prebind and -noprebind can't be "
869 "specified");
870 usage(EXIT_FAILURE);
872 cmd_flags.prebinding_flag_specified = TRUE;
873 cmd_flags.prebinding = TRUE;
874 cmd_flags.ldflags = reallocate(cmd_flags.ldflags,
875 sizeof(char *) * (cmd_flags.nldflags + 1));
876 cmd_flags.ldflags[cmd_flags.nldflags++] = argv[i];
878 else if(strcmp(argv[i], "-noprebind") == 0){
879 if(cmd_flags.ranlib == TRUE){
880 error("unknown option: %s", argv[i]);
881 usage(EXIT_FAILURE);
883 if(cmd_flags.prebinding_flag_specified == TRUE &&
884 cmd_flags.prebinding == TRUE){
885 error("both -prebind and -noprebind can't be "
886 "specified");
887 usage(EXIT_FAILURE);
889 cmd_flags.prebinding_flag_specified = TRUE;
890 cmd_flags.prebinding = FALSE;
891 cmd_flags.ldflags = reallocate(cmd_flags.ldflags,
892 sizeof(char *) * (cmd_flags.nldflags + 1));
893 cmd_flags.ldflags[cmd_flags.nldflags++] = argv[i];
895 else if(strcmp(argv[i], "-all_load") == 0){
896 if(cmd_flags.ranlib == TRUE){
897 error("unknown option: %s", argv[i]);
898 usage(EXIT_FAILURE);
900 if(cmd_flags.all_load_flag_specified == TRUE &&
901 cmd_flags.all_load == FALSE){
902 error("both -all_load and -noall_load can't be "
903 "specified");
904 usage(EXIT_FAILURE);
906 cmd_flags.all_load_flag_specified = TRUE;
907 cmd_flags.all_load = TRUE;
909 else if(strcmp(argv[i], "-noall_load") == 0){
910 if(cmd_flags.ranlib == TRUE){
911 error("unknown option: %s", argv[i]);
912 usage(EXIT_FAILURE);
914 if(cmd_flags.all_load_flag_specified == TRUE &&
915 cmd_flags.all_load == TRUE){
916 error("both -all_load and -noall_load can't be "
917 "specified");
918 usage(EXIT_FAILURE);
920 cmd_flags.all_load_flag_specified = TRUE;
921 cmd_flags.all_load = FALSE;
923 else if(strncmp(argv[i], "-y", 2) == 0 ||
924 strncmp(argv[i], "-i", 2) == 0){
925 if(cmd_flags.ranlib == TRUE){
926 error("unknown option: %s", argv[i]);
927 usage(EXIT_FAILURE);
929 if(strncmp(argv[i], "-i", 2) == 0)
930 cmd_flags.no_files_ok = TRUE;
931 cmd_flags.ldflags = reallocate(cmd_flags.ldflags,
932 sizeof(char *) * (cmd_flags.nldflags + 1));
933 cmd_flags.ldflags[cmd_flags.nldflags++] = argv[i];
935 else if(argv[i][1] == 'l'){
936 if(cmd_flags.ranlib == TRUE){
937 error("unknown option: %s", argv[i]);
938 usage(EXIT_FAILURE);
940 if(argv[i][2] == '\0'){
941 error("-l: name missing");
942 usage(EXIT_FAILURE);
944 cmd_flags.files[cmd_flags.nfiles++] = argv[i];
945 lflags_seen = TRUE;
947 else if(strncmp(argv[i], "-weak-l", 7) == 0){
948 if(cmd_flags.ranlib == TRUE){
949 error("unknown option: %s", argv[i]);
950 usage(EXIT_FAILURE);
952 if(argv[i][7] == '\0'){
953 error("-weak-l: name missing");
954 usage(EXIT_FAILURE);
956 cmd_flags.files[cmd_flags.nfiles++] = argv[i];
957 lflags_seen = TRUE;
959 else if(strcmp(argv[i], "-framework") == 0 ||
960 strcmp(argv[i], "-weak_framework") == 0 ||
961 strcmp(argv[i], "-weak_library") == 0){
962 if(cmd_flags.ranlib == TRUE){
963 error("unknown option: %s", argv[i]);
964 usage(EXIT_FAILURE);
966 if(i + 1 >= argc){
967 error("not enough arguments follow %s", argv[i]);
968 usage(EXIT_FAILURE);
970 cmd_flags.files[cmd_flags.nfiles++] = argv[i];
971 cmd_flags.files[cmd_flags.nfiles++] = argv[i+1];
972 lflags_seen = TRUE;
973 i += 1;
975 else if(strcmp(argv[i], "-T") == 0){
976 if(cmd_flags.L_or_T_specified == TRUE){
977 error("both -T and -L can't be specified");
978 usage(EXIT_FAILURE);
980 cmd_flags.L_or_T_specified = TRUE;
981 cmd_flags.use_long_names = FALSE;
983 else if(argv[i][1] == 'L' || argv[i][1] == 'F'){
984 if(argv[i][1] == 'L' && argv[i][2] == '\0'){
985 if(cmd_flags.L_or_T_specified == TRUE){
986 error("both -T and -L can't be specified");
987 usage(EXIT_FAILURE);
989 cmd_flags.L_or_T_specified = TRUE;
990 cmd_flags.use_long_names = TRUE;
992 else{
993 if(cmd_flags.ranlib == TRUE){
994 error("unknown option: %s", argv[i]);
995 usage(EXIT_FAILURE);
997 cmd_flags.Ldirs = realloc(cmd_flags.Ldirs,
998 sizeof(char *) * (cmd_flags.nLdirs + 1));
999 cmd_flags.Ldirs[cmd_flags.nLdirs++] = argv[i];
1002 else if(argv[i][1] == 'g'){
1003 if(cmd_flags.ranlib == TRUE){
1004 error("unknown option: %s", argv[i]);
1005 usage(EXIT_FAILURE);
1007 /* We need to ignore -g[gdb,codeview,stab][number] flags */
1010 else if(strcmp(argv[i], "-pg") == 0){
1011 if(cmd_flags.ranlib == TRUE){
1012 error("unknown option: %s", argv[i]);
1013 usage(EXIT_FAILURE);
1015 /* We need to ignore -pg */
1018 else if(strcmp(argv[i], "-search_paths_first") == 0){
1019 if(cmd_flags.ranlib == TRUE){
1020 error("unknown option: %s", argv[i]);
1021 usage(EXIT_FAILURE);
1023 cmd_flags.search_paths_first = TRUE;
1024 cmd_flags.ldflags = reallocate(cmd_flags.ldflags,
1025 sizeof(char *) * (cmd_flags.nldflags + 1));
1026 cmd_flags.ldflags[cmd_flags.nldflags++] = argv[i];
1028 else if(strcmp(argv[i], "-noflush") == 0){
1029 cmd_flags.noflush = TRUE;
1031 else if(strcmp(argv[i], "-no_warning_for_no_symbols") == 0){
1032 cmd_flags.no_warning_for_no_symbols = TRUE;
1034 else if(strcmp(argv[i], "-toc64") == 0){
1035 cmd_flags.toc64 = TRUE;
1037 else if(strcmp(argv[i], "-fat64") == 0){
1038 cmd_flags.fat64 = TRUE;
1040 #ifdef DEBUG
1041 else if(strcmp(argv[i], "-debug") == 0){
1042 if(i + 1 >= argc){
1043 error("not enough arguments follow %s", argv[i]);
1044 usage(EXIT_FAILURE);
1046 i++;
1047 cmd_flags.debug |= 1 << strtoul(argv[i], &endp, 10);
1048 if(*endp != '\0' || strtoul(argv[i], &endp, 10) > 32)
1049 fatal("argument for -debug %s not a proper "
1050 "decimal number less than 32", argv[i]);
1052 #endif /* DEBUG */
1053 else{
1054 for(j = 1; argv[i][j] != '\0'; j++){
1055 switch(argv[i][j]){
1056 case 's':
1057 cmd_flags.s = TRUE;
1058 break;
1059 case 'a':
1060 cmd_flags.a = TRUE;
1061 break;
1062 case 'c':
1063 cmd_flags.c = TRUE;
1064 break;
1065 case 'v':
1066 if(cmd_flags.ranlib == TRUE){
1067 error("unknown option character `%c' in: %s",
1068 argv[i][j], argv[i]);
1069 usage(EXIT_FAILURE);
1071 cmd_flags.verbose= TRUE;
1072 break;
1073 case 'V':
1074 printf("Apple Inc. version %s\n", apple_version);
1075 Vflag = TRUE;
1076 break;
1077 case 't':
1078 if(cmd_flags.ranlib == TRUE){
1079 warning("touch option (`%c' in: %s) ignored "
1080 "(table of contents rebuilt anyway)",
1081 argv[i][j], argv[i]);
1082 cmd_flags.t = TRUE;
1083 break;
1085 else {
1086 error("unknown option character `%c' in: %s",
1087 argv[i][j], argv[i]);
1088 usage(EXIT_FAILURE);
1090 case 'f':
1091 if(cmd_flags.ranlib == TRUE){
1092 cmd_flags.f = TRUE;
1093 break;
1095 else {
1096 error("unknown option character `%c' in: %s",
1097 argv[i][j], argv[i]);
1098 usage(EXIT_FAILURE);
1100 case 'q':
1101 if(cmd_flags.ranlib == TRUE){
1102 cmd_flags.q = TRUE;
1103 break;
1105 else {
1106 error("unknown option character `%c' in: %s",
1107 argv[i][j], argv[i]);
1108 usage(EXIT_FAILURE);
1110 default:
1111 error("unknown option character `%c' in: %s",
1112 argv[i][j], argv[i]);
1113 usage(EXIT_FAILURE);
1118 else
1119 cmd_flags.files[cmd_flags.nfiles++] = argv[i];
1122 * Test to see if the environment variable LD_TRACE_ARCHIVES is set.
1124 if((getenv("RC_TRACE_ARCHIVES") != NULL) ||
1125 (getenv("LD_TRACE_ARCHIVES") != NULL)) {
1126 cmd_flags.ld_trace_archives = TRUE;
1127 cmd_flags.trace_file_path = getenv("LD_TRACE_FILE");
1131 * If either -syslibroot or the environment variable NEXT_ROOT is set
1132 * prepend it to the standard paths for library searches. This was
1133 * added to ease cross build environments.
1135 if(next_root != NULL){
1136 if(getenv("NEXT_ROOT") != NULL)
1137 warning("NEXT_ROOT environment variable ignored because "
1138 "-syslibroot specified");
1140 else{
1141 next_root = getenv("NEXT_ROOT");
1143 if(next_root != NULL){
1144 for(i = 0; standard_dirs[i] != NULL; i++){
1145 p = allocate(strlen(next_root) +
1146 strlen(standard_dirs[i]) + 1);
1147 strcpy(p, next_root);
1148 strcat(p, standard_dirs[i]);
1149 standard_dirs[i] = p;
1151 for(i = 0; i < cmd_flags.nLdirs ; i++){
1152 if(cmd_flags.Ldirs[i][1] != 'L')
1153 continue;
1154 if(cmd_flags.Ldirs[i][2] == '/'){
1155 p = makestr(next_root, cmd_flags.Ldirs[i] + 2, NULL);
1156 if(access(p, F_OK) != -1){
1157 free(p);
1158 p = makestr("-L", next_root, cmd_flags.Ldirs[i] + 2,
1159 NULL);
1160 cmd_flags.Ldirs[i] = p;
1162 else{
1163 free(p);
1169 /* check the command line arguments for correctness */
1170 if(cmd_flags.ranlib == FALSE && cmd_flags.dynamic == TRUE){
1171 if(cmd_flags.s == TRUE){
1172 warning("-static not specified, -s invalid");
1174 if(cmd_flags.a == TRUE){
1175 warning("-static not specified, -a invalid");
1177 if(cmd_flags.c == TRUE){
1178 warning("-static not specified, -c invalid");
1180 if(cmd_flags.L_or_T_specified == TRUE){
1181 if(cmd_flags.use_long_names == TRUE)
1182 warning("-static not specified, -L invalid");
1183 else
1184 warning("-static not specified, -T invalid");
1187 if(cmd_flags.s == TRUE && cmd_flags.a == TRUE){
1188 error("only one of -s or -a can be specified");
1189 usage(EXIT_FAILURE);
1191 if(cmd_flags.ranlib == FALSE && cmd_flags.output == NULL){
1192 if(Vflag == TRUE)
1193 exit(EXIT_SUCCESS);
1194 error("no output file specified (specify with -o output)");
1195 usage(EXIT_FAILURE);
1197 if(cmd_flags.dynamic == FALSE){
1198 if(cmd_flags.compatibility != NULL){
1199 warning("-dynamic not specified, -compatibility_version %s "
1200 "invalid", cmd_flags.compatibility);
1202 if(cmd_flags.current != NULL){
1203 warning("-dynamic not specified, -current_version %s invalid",
1204 cmd_flags.current);
1206 if(cmd_flags.install_name != NULL){
1207 warning("-dynamic not specified, -install_name %s invalid",
1208 cmd_flags.install_name);
1210 if(cmd_flags.seg1addr != NULL){
1211 warning("-dynamic not specified, -seg1addr %s invalid",
1212 cmd_flags.seg1addr);
1214 if(cmd_flags.segs_read_only_addr != NULL){
1215 warning("-dynamic not specified, -segs_read_only_addr %s "
1216 "invalid", cmd_flags.segs_read_only_addr);
1218 if(cmd_flags.segs_read_write_addr != NULL){
1219 warning("-dynamic not specified, -segs_read_write_addr %s "
1220 "invalid", cmd_flags.segs_read_write_addr);
1222 if(cmd_flags.seg_addr_table != NULL){
1223 warning("-dynamic not specified, -seg_addr_table %s "
1224 "invalid", cmd_flags.seg_addr_table);
1226 if(cmd_flags.seg_addr_table_filename != NULL){
1227 warning("-dynamic not specified, -seg_addr_table_filename %s "
1228 "invalid", cmd_flags.seg_addr_table_filename);
1230 if(cmd_flags.all_load_flag_specified == TRUE){
1231 if(cmd_flags.all_load == TRUE)
1232 warning("-dynamic not specified, -all_load invalid");
1233 else
1234 warning("-dynamic not specified, -noall_load invalid");
1236 if(cmd_flags.nldflags != 0){
1237 bad_flag_seen = FALSE;
1238 for(j = 0; j < cmd_flags.nldflags; j++){
1239 if(strcmp(cmd_flags.ldflags[j], "-syslibroot") == 0){
1240 j++;
1241 continue;
1243 if(bad_flag_seen == FALSE){
1244 fprintf(stderr, "%s: -dynamic not specified the "
1245 "following flags are invalid: ", pnam);
1246 bad_flag_seen = TRUE;
1248 fprintf(stderr, "%s ", cmd_flags.ldflags[j]);
1250 if(bad_flag_seen == TRUE)
1251 fprintf(stderr, "\n");
1253 if(cmd_flags.nLdirs != 0){
1254 /* Note: both -L and -F flags are in cmd_flags.Ldirs to keep the
1255 search order right. */
1256 bad_flag_seen = FALSE;
1257 for(j = 0; j < cmd_flags.nLdirs; j++){
1258 if(strncmp(cmd_flags.Ldirs[j], "-L", 2) == 0)
1259 continue;
1260 if(bad_flag_seen == FALSE){
1261 fprintf(stderr, "%s: -dynamic not specified the "
1262 "following flags are invalid: ", pnam);
1263 bad_flag_seen = TRUE;
1265 fprintf(stderr, "%s ", cmd_flags.Ldirs[j]);
1267 if(bad_flag_seen == TRUE)
1268 fprintf(stderr, "\n");
1271 else{
1273 * The -prebind flag can also be specified with the LD_PREBIND
1274 * environment variable.
1276 if(getenv("LD_PREBIND") != NULL){
1277 if(cmd_flags.prebinding_flag_specified == TRUE &&
1278 cmd_flags.prebinding == FALSE){
1279 warning("LD_PREBIND environment variable ignored because "
1280 "-noprebind specified");
1282 else{
1283 cmd_flags.prebinding_flag_specified = TRUE;
1284 cmd_flags.prebinding = TRUE;
1288 if(cmd_flags.nfiles == 0){
1289 if(cmd_flags.ranlib == TRUE){
1290 error("no archives specified");
1291 usage(EXIT_FAILURE);
1293 else{
1294 if(cmd_flags.dynamic == TRUE && cmd_flags.no_files_ok == TRUE)
1295 warning("warning no files specified");
1296 else{
1297 error("no files specified");
1298 usage(EXIT_FAILURE);
1303 /* set the defaults if not specified */
1304 if(cmd_flags.a == FALSE)
1305 cmd_flags.s = TRUE; /* sort table of contents by default */
1307 process();
1309 if(errors == 0)
1310 return(EXIT_SUCCESS);
1311 else
1312 return(EXIT_FAILURE);
1316 * usage(EXIT_FAILURE) prints the current usage message and exits indicating failure.
1318 static void
1319 usage(int exit_with_code)
1321 FILE *out = exit_with_code ? stderr : stdout;
1322 if(cmd_flags.ranlib)
1323 fprintf(out, "Usage: %s [-sactfqLT] [-] archive [...]\n",
1324 pnam);
1325 else{
1326 fprintf(out, "Usage: %s -static [-] file [...] "
1327 "[-filelist listfile[,dirname]] [-arch_only arch] "
1328 "[-sacLT] [-no_warning_for_no_symbols]\n", pnam);
1329 fprintf(out, "Usage: %s -dynamic [-] file [...] "
1330 "[-filelist listfile[,dirname]] [-arch_only arch] "
1331 "[-o output] [-install_name name] "
1332 "[-compatibility_version #] [-current_version #] "
1333 "[-seg1addr 0x#] [-segs_read_only_addr 0x#] "
1334 "[-segs_read_write_addr 0x#] [-seg_addr_table <filename>] "
1335 "[-seg_addr_table_filename <file_system_path>] "
1336 "[-all_load] [-noall_load]\n",
1337 pnam);
1339 if (exit_with_code)
1340 exit(exit_with_code);
1344 * process() the input files into libraries based on the command flags.
1346 static
1347 void
1348 process(
1349 void)
1351 uint32_t i, j, k, previous_errors;
1352 struct ofile *ofiles;
1353 char *file_name;
1354 enum bool flag, ld_trace_archive_printed;
1357 * For libtool processing put all input files in the specified output
1358 * file. For ranlib processing all input files should be archives or
1359 * fat files with archives in them and each is processed by itself and
1360 * not combined with anything else. The format of fat object files in
1361 * a thin archive is supported here also.
1363 ofiles = allocate(sizeof(struct ofile) * cmd_flags.nfiles);
1364 for(i = 0; i < cmd_flags.nfiles; i++){
1365 if(strncmp(cmd_flags.files[i], "-l", 2) == 0 ||
1366 strncmp(cmd_flags.files[i], "-weak-l", 7) == 0){
1367 if(cmd_flags.dynamic == TRUE)
1368 continue;
1369 file_name = file_name_from_l_flag(cmd_flags.files[i]);
1370 if(file_name != NULL)
1371 if(ofile_map(file_name, NULL, NULL, ofiles + i, TRUE) ==
1372 FALSE)
1373 continue;
1375 else if(strcmp(cmd_flags.files[i], "-framework") == 0 ||
1376 strcmp(cmd_flags.files[i], "-weak_framework") == 0 ||
1377 strcmp(cmd_flags.files[i], "-weak_library") == 0){
1378 i++;
1379 continue;
1381 else{
1382 if(ofile_map(cmd_flags.files[i], NULL, NULL, ofiles + i,
1383 TRUE) == FALSE)
1384 continue;
1387 previous_errors = errors;
1388 errors = 0;
1389 ld_trace_archive_printed = FALSE;
1391 if(ofiles[i].file_type == OFILE_FAT){
1392 (void)ofile_first_arch(ofiles + i);
1394 if(ofiles[i].arch_type == OFILE_ARCHIVE){
1395 if(cmd_flags.ld_trace_archives == TRUE &&
1396 cmd_flags.dynamic == FALSE &&
1397 ld_trace_archive_printed == FALSE){
1398 char resolvedname[MAXPATHLEN];
1399 if(realpath(ofiles[i].file_name, resolvedname) !=
1400 NULL)
1401 ld_trace("[Logging for XBS] Used static "
1402 "archive: %s\n", resolvedname);
1403 else
1404 ld_trace("[Logging for XBS] Used static "
1405 "archive: %s\n", ofiles[i].file_name);
1406 ld_trace_archive_printed = TRUE;
1408 /* loop through archive */
1409 if((flag = ofile_first_member(ofiles + i)) == TRUE){
1410 if(ofiles[i].member_ar_hdr != NULL &&
1411 strncmp(ofiles[i].member_name, SYMDEF,
1412 sizeof(SYMDEF) - 1) == 0)
1413 flag = ofile_next_member(ofiles + i);
1414 while(flag == TRUE){
1415 /* No fat members in a fat file */
1416 if(ofiles[i].mh != NULL ||
1417 ofiles[i].mh64 != NULL ||
1418 #ifdef LTO_SUPPORT
1419 ofiles[i].lto != NULL ||
1420 #endif /* LTO_SUPPORT */
1421 cmd_flags.ranlib == TRUE)
1422 add_member(ofiles + i);
1423 else{
1424 error("for architecture: %s file: %s(%.*s) "
1425 "is not an object file (not allowed "
1426 "in a library)",
1427 ofiles[i].arch_flag.name,
1428 cmd_flags.files[i],
1429 (int)ofiles[i].member_name_size,
1430 ofiles[i].member_name);
1432 flag = ofile_next_member(ofiles + i);
1436 else if(ofiles[i].arch_type == OFILE_Mach_O
1437 #ifdef LTO_SUPPORT
1438 || ofiles[i].arch_type == OFILE_LLVM_BITCODE
1439 #endif
1441 if(cmd_flags.ranlib == TRUE){
1442 error("for architecture: %s file: %s is not an "
1443 "archive (no processing done on this file)",
1444 ofiles[i].arch_flag.name, cmd_flags.files[i]);
1445 goto ranlib_fat_error;
1447 else
1448 add_member(ofiles + i);
1450 else if(ofiles[i].arch_type == OFILE_UNKNOWN){
1451 if(cmd_flags.ranlib == TRUE){
1452 error("for architecture: %s file: %s is not an "
1453 "archive (no processing done on this file)",
1454 ofiles[i].arch_flag.name, cmd_flags.files[i]);
1455 goto ranlib_fat_error;
1457 else{
1458 error("for architecture: %s file: %s is not an "
1459 "object file (not allowed in a library)",
1460 ofiles[i].arch_flag.name, cmd_flags.files[i]);
1463 }while(ofile_next_arch(ofiles + i) == TRUE);
1465 else if(ofiles[i].file_type == OFILE_ARCHIVE){
1466 if(cmd_flags.ld_trace_archives == TRUE &&
1467 cmd_flags.dynamic == FALSE &&
1468 ld_trace_archive_printed == FALSE){
1469 char resolvedname[MAXPATHLEN];
1470 if(realpath(ofiles[i].file_name, resolvedname) != NULL)
1471 ld_trace("[Logging for XBS] Used static archive: "
1472 "%s\n", resolvedname);
1473 else
1474 ld_trace("[Logging for XBS] Used static archive: "
1475 "%s\n", ofiles[i].file_name);
1476 ld_trace_archive_printed = TRUE;
1478 /* loop through archive */
1479 if((flag = ofile_first_member(ofiles + i)) == TRUE){
1480 if(ofiles[i].member_ar_hdr != NULL &&
1481 strncmp(ofiles[i].member_name, SYMDEF,
1482 sizeof(SYMDEF) - 1) == 0){
1483 flag = ofile_next_member(ofiles + i);
1485 while(flag == TRUE){
1486 /* incorrect form: archive with fat object members */
1487 if(ofiles[i].member_type == OFILE_FAT){
1488 (void)ofile_first_arch(ofiles + i);
1490 if(ofiles[i].mh != NULL ||
1491 ofiles[i].mh64 != NULL ||
1492 #ifdef LTO_SUPPORT
1493 ofiles[i].lto != NULL ||
1494 #endif
1495 cmd_flags.ranlib == TRUE){
1496 add_member(ofiles + i);
1498 else{
1500 * Can't really get here because ofile_*()
1501 * routines will refuse to process this
1502 * type of file (but I'll leave it here).
1504 error("file: %s(%.*s) for architecture: %s "
1505 "is not an object file (not allowed in "
1506 "a library)", cmd_flags.files[i],
1507 (int)ofiles[i].member_name_size,
1508 ofiles[i].member_name,
1509 ofiles[i].arch_flag.name);
1512 }while(ofile_next_arch(ofiles + i) == TRUE);
1514 else if(ofiles[i].mh != NULL ||
1515 ofiles[i].mh64 != NULL ||
1516 #ifdef LTO_SUPPORT
1517 ofiles[i].lto != NULL ||
1518 #endif /* LTO_SUPPORT */
1519 cmd_flags.ranlib == TRUE){
1520 add_member(ofiles + i);
1522 else{
1523 error("file: %s(%.*s) is not an object file (not "
1524 "allowed in a library)", cmd_flags.files[i],
1525 (int)ofiles[i].member_name_size,
1526 ofiles[i].member_name);
1528 flag = ofile_next_member(ofiles + i);
1532 else if(ofiles[i].file_type == OFILE_Mach_O){
1533 if(cmd_flags.ranlib == TRUE){
1534 error("file: %s is not an archive", cmd_flags.files[i]);
1535 continue;
1537 add_member(ofiles + i);
1539 #ifdef LTO_SUPPORT
1540 else if(ofiles[i].file_type == OFILE_LLVM_BITCODE){
1541 if(cmd_flags.ranlib == TRUE){
1542 error("file: %s is not an archive", cmd_flags.files[i]);
1543 continue;
1545 add_member(ofiles + i);
1547 #endif /* LTO_SUPPORT */
1548 else{ /* ofiles[i].file_type == OFILE_UNKNOWN */
1549 if(cmd_flags.ranlib == TRUE){
1550 error("file: %s is not an archive", cmd_flags.files[i]);
1551 continue;
1553 else{
1554 error("file: %s is not an object file (not allowed in a "
1555 "library)", cmd_flags.files[i]);
1559 if(cmd_flags.ranlib == TRUE){
1561 * In the case where ranlib is being used on an archive that
1562 * contains fat object files with multiple members and non-
1563 * object members this has to be treated as an error because
1564 * it is not known which architecture(s) the non-object file
1565 * belong to.
1567 if(narchs > 1){
1568 for(j = 0; j < narchs; j++){
1569 for(k = 0; k < archs[j].nmembers; k++){
1570 if(archs[j].members[k].mh == NULL &&
1571 #ifdef LTO_SUPPORT
1572 archs[j].members[k].lto_contents == FALSE &&
1573 #endif /* LTO_SUPPORT */
1574 archs[j].members[k].mh64 == NULL){
1575 error("library member: %s(%.*s) is not an "
1576 "object file (not allowed in a library "
1577 "with multiple architectures)",
1578 cmd_flags.files[i],
1579 (int)archs[j].members[k].
1580 input_base_name_size,
1581 archs[j].members[k].input_base_name);
1586 if(errors == 0)
1587 create_library(cmd_flags.files[i], ofiles + i);
1588 if(cmd_flags.nfiles > 1){
1589 ranlib_fat_error:
1590 free_archs();
1591 ofile_unmap(ofiles + i);
1594 errors += previous_errors;
1596 if(cmd_flags.ranlib == FALSE && errors == 0)
1597 create_library(cmd_flags.output, NULL);
1600 * Clean-up of ofiles[] and archs could be done here but since this
1601 * program is now done it is faster to just exit.
1606 * file_name_from_l_flag() is passed a "-lx" or "-weak-lx" flag and returns a
1607 * name of a file for this flag. The flag "-lx" and "-weak-lx" are the same
1608 * flags as used in the link editor to refer to file names. If it can't find a
1609 * file name for the flag it prints an error and returns NULL.
1611 static
1612 char *
1613 file_name_from_l_flag(
1614 char *l_flag)
1616 char *file_name, *p, *start;
1618 if(strncmp(l_flag, "-weak-l", 7) == 0)
1619 start = &l_flag[7];
1620 else
1621 start = &l_flag[2];
1622 p = strrchr(start, '.');
1623 if(p != NULL && strcmp(p, ".o") == 0){
1624 p = start;
1625 file_name = search_for_file(p);
1627 else{
1628 file_name = NULL;
1629 if(cmd_flags.dynamic == TRUE){
1630 if(cmd_flags.search_paths_first == TRUE){
1631 file_name = search_paths_for_lname(start);
1633 else{
1634 p = makestr("lib", start, ".dylib", NULL);
1635 file_name = search_for_file(p);
1636 free(p);
1637 if(file_name == NULL){
1638 p = makestr("lib", start, ".a", NULL);
1639 file_name = search_for_file(p);
1640 free(p);
1644 else{
1645 p = makestr("lib", start, ".a", NULL);
1646 file_name = search_for_file(p);
1647 free(p);
1650 if(file_name == NULL)
1651 error("can't locate file for: %s", l_flag);
1652 return(file_name);
1656 * search_for_file() takes base_name and trys to find a file with that base name
1657 * is the -L search directories and in the standard directories. If it is
1658 * sucessful it returns a pointer to the file name else it returns NULL.
1660 static
1661 char *
1662 search_for_file(
1663 char *base_name)
1665 uint32_t i;
1666 char *file_name;
1668 for(i = 0; i < cmd_flags.nLdirs ; i++){
1669 if(cmd_flags.Ldirs[i][1] != 'L')
1670 continue;
1671 file_name = makestr(cmd_flags.Ldirs[i] + 2, "/", base_name, NULL);
1672 if(access(file_name, R_OK) != -1)
1673 return(file_name);
1674 free(file_name);
1676 for(i = 0; standard_dirs[i] != NULL ; i++){
1677 file_name = makestr(standard_dirs[i], base_name, NULL);
1678 if(access(file_name, R_OK) != -1)
1679 return(file_name);
1680 free(file_name);
1682 return(NULL);
1686 * search_paths_for_lname() takes the argument to a -lx option and and trys to
1687 * find a file with the name libx.dylib or libx.a. This routine is only used
1688 * when the -search_paths_first option is specified and -dynamic is in effect.
1689 * And looks for a file name ending in .dylib then .a in each directory before
1690 * looking in the next directory. The list of the -L search directories and in
1691 * the standard directories are searched in that order. If this is sucessful
1692 * it returns a pointer to the file name else NULL.
1694 static
1695 char *
1696 search_paths_for_lname(
1697 const char *lname_argument)
1699 uint32_t i;
1700 char *file_name, *dir;
1702 for(i = 0; i < cmd_flags.nLdirs ; i++){
1703 if(cmd_flags.Ldirs[i][1] != 'L')
1704 continue;
1705 dir = makestr(cmd_flags.Ldirs[i] + 2, "/", NULL);
1706 file_name = search_path_for_lname(dir, lname_argument);
1707 free(dir);
1708 if(file_name != NULL)
1709 return(file_name);
1711 for(i = 0; standard_dirs[i] != NULL ; i++){
1712 file_name = search_path_for_lname(standard_dirs[i], lname_argument);
1713 if(file_name != NULL)
1714 return(file_name);
1716 return(NULL);
1720 * search_path_for_lname() takes the argument to a -lx option and and trys to
1721 * find a file with the name libx.dylib then libx.a in the specified directory
1722 * name. This routine is only used when the -search_paths_first option is
1723 * specified and -dynamic is in effect. If this is sucessful it returns a
1724 * pointer to the file name else NULL.
1726 static
1727 char *
1728 search_path_for_lname(
1729 const char *dir,
1730 const char *lname_argument)
1732 char *file_name;
1734 file_name = makestr(dir, "/", "lib", lname_argument, ".dylib", NULL);
1735 if(access(file_name, R_OK) != -1)
1736 return(file_name);
1737 free(file_name);
1739 file_name = makestr(dir, "/", "lib", lname_argument, ".a", NULL);
1740 if(access(file_name, R_OK) != -1)
1741 return(file_name);
1742 free(file_name);
1744 return(NULL);
1748 * add_member() add the specified ofile as a member to the library. The
1749 * specified ofile must be either an object file (libtool or ranlib) or an
1750 * archive member with an unknown file type (ranlib only).
1752 static
1753 void
1754 add_member(
1755 struct ofile *ofile)
1757 uint32_t i, j, size, ar_name_size;
1758 struct arch *arch;
1759 struct member *member;
1760 struct stat stat_buf;
1761 char *p, c, ar_name_buf[sizeof(ofile->member_ar_hdr->ar_name) + 1];
1762 char ar_size_buf[sizeof(ofile->member_ar_hdr->ar_size) + 1];
1763 const struct arch_flag *family_arch_flag;
1766 * If this did not come from an archive get the stat info which is
1767 * needed to fill in the archive header for this member.
1769 if(ofile->member_ar_hdr == NULL){
1770 if(stat(ofile->file_name, &stat_buf) == -1){
1771 system_error("can't stat file: %s", ofile->file_name);
1772 return;
1777 * Determine the size this member will have in the library which
1778 * includes the padding as a result of rounding the size of the
1779 * member. To get all members on an 8 byte boundary (so that mapping
1780 * in object files can be used directly) the size of the member is
1781 * CHANGED to reflect this padding. In the UNIX definition of archives
1782 * the size of the member is never changed but the offset to the next
1783 * member is defined to be the offset of the previous member plus
1784 * the size of the previous member rounded to 2. So to get 8 byte
1785 * boundaries without breaking the UNIX definition of archives the
1786 * size is changed here. As with the UNIX ar(1) program the padded
1787 * bytes are set to the character '\n'.
1789 if(ofile->mh != NULL || ofile->mh64 != NULL)
1790 size = rnd(ofile->object_size, 8);
1791 #ifdef LTO_SUPPORT
1792 else if(ofile->lto != NULL){
1793 if(ofile->file_type == OFILE_LLVM_BITCODE)
1794 size = rnd(ofile->file_size, 8);
1795 else if(ofile->file_type == OFILE_FAT ||
1796 (ofile->file_type == OFILE_ARCHIVE &&
1797 ofile->member_type == OFILE_FAT))
1798 size = rnd(ofile->object_size, 8);
1799 else
1800 size = rnd(ofile->member_size, 8);
1802 #endif /* LTO_SUPPORT */
1803 else
1804 size = rnd(ofile->member_size, 8);
1806 /* select or create an arch type to put this in */
1807 i = 0;
1808 if(ofile->mh != NULL ||
1809 ofile->mh64 != NULL){
1810 if(ofile->mh_cputype == 0){
1811 if(ofile->member_ar_hdr != NULL){
1812 error("file: %s(%.*s) cputype is zero (a reserved value)",
1813 ofile->file_name, (int)ofile->member_name_size,
1814 ofile->member_name);
1816 else
1817 error("file: %s cputype is zero (a reserved value)",
1818 ofile->file_name);
1819 return;
1822 * If we are building a dynamic library then don't add dynamic
1823 * shared libraries to the archs. This is so that a dependent
1824 * dynamic shared library that happens to be fat will not cause the
1825 * library to be created fat unless there are object going into
1826 * the library that are fat.
1828 if(ofile->mh_filetype == MH_DYLIB ||
1829 ofile->mh_filetype == MH_DYLIB_STUB){
1831 * If we are building a static library we should not put a
1832 * dynamic library Mach-O file into the static library. This
1833 * can happen if a libx.a file is really a dynamic library and
1834 * someone is using -lx when creating a static library.
1836 if(cmd_flags.dynamic != TRUE){
1837 if(ofile->member_ar_hdr != NULL){
1838 warning("file: %s(%.*s) is a dynamic library, not "
1839 "added to the static library",
1840 ofile->file_name, (int)ofile->member_name_size,
1841 ofile->member_name);
1843 else
1844 warning("file: %s is a dynamic library, not added to "
1845 "the static library", ofile->file_name);
1847 return;
1850 * If -arch_only is specified then only add this file if it matches
1851 * the architecture specified.
1853 if(cmd_flags.arch_only_flag.name != NULL){
1854 if(cmd_flags.arch_only_flag.cputype != ofile->mh_cputype)
1855 return;
1856 if(cmd_flags.arch_only_flag.cputype == CPU_TYPE_ARM ||
1857 cmd_flags.arch_only_flag.cputype == CPU_TYPE_X86_64){
1858 if(cmd_flags.arch_only_flag.cpusubtype !=
1859 ofile->mh_cpusubtype)
1860 return;
1862 if(cmd_flags.arch_only_flag.cputype == CPU_TYPE_ARM64){
1863 if(cmd_flags.arch_only_flag.cpusubtype ==
1864 CPU_SUBTYPE_ARM64_ALL){
1865 if(ofile->mh_cpusubtype != CPU_SUBTYPE_ARM64_ALL &&
1866 ofile->mh_cpusubtype != CPU_SUBTYPE_ARM64_V8)
1867 return;
1869 else if(cmd_flags.arch_only_flag.cpusubtype !=
1870 ofile->mh_cpusubtype)
1871 return;
1875 for( ; i < narchs; i++){
1876 if(archs[i].arch_flag.cputype == ofile->mh_cputype){
1877 if((archs[i].arch_flag.cputype == CPU_TYPE_ARM ||
1878 archs[i].arch_flag.cputype == CPU_TYPE_X86_64) &&
1879 archs[i].arch_flag.cpusubtype != ofile->mh_cpusubtype)
1880 continue;
1881 if(cmd_flags.arch_only_flag.cputype == CPU_TYPE_ARM64){
1882 if(cmd_flags.arch_only_flag.cpusubtype ==
1883 CPU_SUBTYPE_ARM64_ALL){
1884 if(ofile->mh_cpusubtype != CPU_SUBTYPE_ARM64_ALL &&
1885 ofile->mh_cpusubtype != CPU_SUBTYPE_ARM64_V8)
1886 continue;
1888 else if(cmd_flags.arch_only_flag.cpusubtype !=
1889 ofile->mh_cpusubtype)
1890 continue;
1892 break;
1896 #ifdef LTO_SUPPORT
1897 else if(ofile->lto != NULL){
1899 * If -arch_only is specified then only add this file if it matches
1900 * the architecture specified.
1902 if(cmd_flags.arch_only_flag.name != NULL){
1903 if(cmd_flags.arch_only_flag.cputype != ofile->lto_cputype)
1904 return;
1905 if(cmd_flags.arch_only_flag.cputype == CPU_TYPE_ARM ||
1906 cmd_flags.arch_only_flag.cputype == CPU_TYPE_X86_64){
1907 if(cmd_flags.arch_only_flag.cpusubtype !=
1908 ofile->lto_cpusubtype)
1909 return;
1911 if(cmd_flags.arch_only_flag.cputype == CPU_TYPE_ARM64){
1912 if(cmd_flags.arch_only_flag.cpusubtype ==
1913 CPU_SUBTYPE_ARM64_ALL){
1914 if(ofile->lto_cpusubtype != CPU_SUBTYPE_ARM64_ALL &&
1915 ofile->lto_cpusubtype != CPU_SUBTYPE_ARM64_V8)
1916 return;
1918 else if(cmd_flags.arch_only_flag.cpusubtype !=
1919 ofile->lto_cpusubtype)
1920 return;
1924 for( ; i < narchs; i++){
1925 if(archs[i].arch_flag.cputype == ofile->lto_cputype){
1926 if((archs[i].arch_flag.cputype == CPU_TYPE_ARM ||
1927 archs[i].arch_flag.cputype == CPU_TYPE_X86_64) &&
1928 archs[i].arch_flag.cpusubtype != ofile->lto_cpusubtype)
1929 continue;
1930 if(cmd_flags.arch_only_flag.cputype == CPU_TYPE_ARM64){
1931 if(cmd_flags.arch_only_flag.cpusubtype ==
1932 CPU_SUBTYPE_ARM64_ALL &&
1933 (ofile->lto_cpusubtype != CPU_SUBTYPE_ARM64_ALL &&
1934 ofile->lto_cpusubtype != CPU_SUBTYPE_ARM64_V8))
1935 continue;
1936 else if(cmd_flags.arch_only_flag.cpusubtype !=
1937 ofile->lto_cpusubtype)
1938 continue;
1940 break;
1944 #endif /* LTO_SUPPORT */
1945 if(narchs == 1 && archs[0].arch_flag.cputype == 0){
1946 i = 0;
1948 else if(i == narchs){
1949 archs = reallocate(archs, sizeof(struct arch) * (narchs+1));
1950 memset(archs + narchs, '\0', sizeof(struct arch));
1951 if(ofile->mh != NULL ||
1952 ofile->mh64 != NULL){
1953 if(ofile->mh_cputype == CPU_TYPE_ARM ||
1954 ofile->mh_cputype == CPU_TYPE_ARM64 ||
1955 ofile->mh_cputype == CPU_TYPE_X86_64){
1956 archs[narchs].arch_flag.name = (char *)
1957 get_arch_name_from_types(
1958 ofile->mh_cputype, ofile->mh_cpusubtype);
1959 archs[narchs].arch_flag.cputype = ofile->mh_cputype;
1960 archs[narchs].arch_flag.cpusubtype = ofile->mh_cpusubtype;
1962 else{
1963 family_arch_flag =
1964 get_arch_family_from_cputype(ofile->mh_cputype);
1965 if(family_arch_flag != NULL)
1966 archs[narchs].arch_flag = *family_arch_flag;
1969 #ifdef LTO_SUPPORT
1970 else if(ofile->lto != NULL){
1971 if(ofile->lto_cputype == CPU_TYPE_ARM ||
1972 ofile->lto_cputype == CPU_TYPE_ARM64 ||
1973 ofile->lto_cputype == CPU_TYPE_X86_64){
1974 archs[narchs].arch_flag.name = (char *)
1975 get_arch_name_from_types(
1976 ofile->lto_cputype, ofile->lto_cpusubtype);
1977 archs[narchs].arch_flag.cputype = ofile->lto_cputype;
1978 archs[narchs].arch_flag.cpusubtype = ofile->lto_cpusubtype;
1980 else{
1981 family_arch_flag =
1982 get_arch_family_from_cputype(ofile->lto_cputype);
1983 if(family_arch_flag != NULL)
1984 archs[narchs].arch_flag = *family_arch_flag;
1987 #endif /* LTO_SUPPORT */
1988 else
1989 archs[narchs].arch_flag.name = "unknown";
1990 narchs++;
1992 arch = archs + i;
1995 * If the cputype of this arch is not yet known then see if this new
1996 * member can determine it.
1998 if(arch->arch_flag.cputype == 0 &&
1999 (ofile->mh != NULL || ofile->mh64 != NULL)){
2000 family_arch_flag = get_arch_family_from_cputype(ofile->mh_cputype);
2001 if(family_arch_flag != NULL){
2002 arch->arch_flag = *family_arch_flag;
2004 else{
2005 arch->arch_flag.name =
2006 savestr("cputype 1234567890 cpusubtype 1234567890");
2007 if(arch->arch_flag.name != NULL)
2008 sprintf(arch->arch_flag.name, "cputype %u cpusubtype %u",
2009 ofile->mh_cputype, ofile->mh_cpusubtype &
2010 ~CPU_SUBTYPE_MASK);
2011 arch->arch_flag.cputype = ofile->mh_cputype;
2012 arch->arch_flag.cpusubtype = ofile->mh_cpusubtype;
2015 #ifdef LTO_SUPPORT
2016 if(arch->arch_flag.cputype == 0 &&
2017 (ofile->lto != NULL)){
2018 family_arch_flag = get_arch_family_from_cputype(ofile->lto_cputype);
2019 if(family_arch_flag != NULL){
2020 arch->arch_flag = *family_arch_flag;
2022 else{
2023 arch->arch_flag.name =
2024 savestr("cputype 1234567890 cpusubtype 1234567890");
2025 if(arch->arch_flag.name != NULL)
2026 sprintf(arch->arch_flag.name, "cputype %u cpusubtype %u",
2027 ofile->lto_cputype, ofile->lto_cpusubtype &
2028 ~CPU_SUBTYPE_MASK);
2029 arch->arch_flag.cputype = ofile->lto_cputype;
2030 arch->arch_flag.cpusubtype = ofile->lto_cpusubtype;
2033 #endif /* LTO_SUPPORT */
2035 /* create a member in this arch type for this member */
2036 arch->members = reallocate(arch->members, sizeof(struct member) *
2037 (arch->nmembers + 1));
2038 member = arch->members + arch->nmembers;
2039 memset(member, '\0', sizeof(struct member));
2040 arch->nmembers++;
2042 /* fill in the member for this ofile */
2043 member->input_file_name = ofile->file_name;
2045 if(ofile->member_ar_hdr == NULL){
2047 * We are creating an archive member in the output file from a
2048 * file (that is not archive member in an input file). First get
2049 * the base name the file_name for the member name.
2051 p = strrchr(ofile->file_name, '/');
2052 if(p != NULL)
2053 p++;
2054 else
2055 p = ofile->file_name;
2056 member->input_base_name = p;
2057 member->input_base_name_size = strlen(p);
2058 member->member_name = member->input_base_name;
2060 * If we can use long names then force using them to allow 64-bit
2061 * objects to be aligned on an 8 byte boundary. This is needed
2062 * since the struct ar_hdr is not a multiple of 8. This is normally
2063 * done if the name does not fit in the archive header or contains
2064 * a space character then we use the extened format #1. The size
2065 * of the name is rounded up so the object file after the name will
2066 * be on an 8 byte boundary (including rounding the size of the
2067 * struct ar_hdr). The name will be padded with '\0's when it is
2068 * written out.
2070 if(cmd_flags.use_long_names == TRUE){
2071 member->output_long_name = TRUE;
2072 member->member_name_size = member->input_base_name_size;
2073 ar_name_size = rnd(member->input_base_name_size, 8) +
2074 (rnd(sizeof(struct ar_hdr), 8) -
2075 sizeof(struct ar_hdr));
2076 sprintf(ar_name_buf, "%s%-*lu", AR_EFMT1,
2077 (int)(sizeof(member->ar_hdr.ar_name) -
2078 (sizeof(AR_EFMT1) - 1)),
2079 (long unsigned int)ar_name_size);
2080 memcpy(member->ar_hdr.ar_name, ar_name_buf,
2081 sizeof(member->ar_hdr.ar_name));
2083 else{
2084 ar_name_size = 0;
2085 member->output_long_name = FALSE;
2087 * Truncate the file_name if needed and place in archive header.
2089 c = '\0';
2090 if(strlen(p) > sizeof(member->ar_hdr.ar_name)){
2091 c = p[sizeof(member->ar_hdr.ar_name)];
2092 p[sizeof(member->ar_hdr.ar_name)] = '\0';
2094 sprintf((char *)(&member->ar_hdr), "%-*s",
2095 (int)sizeof(member->ar_hdr.ar_name), p);
2096 if(c != '\0')
2097 p[sizeof(member->ar_hdr.ar_name)] = c;
2098 member->member_name_size = size_ar_name(&member->ar_hdr);
2100 if(zero_ar_date == TRUE)
2101 stat_buf.st_mtime = 0;
2103 * Create the rest of the archive header after the name.
2105 sprintf((char *)(&member->ar_hdr) + sizeof(member->ar_hdr.ar_name),
2106 "%-*ld%-*u%-*u%-*o%-*ld%-*s",
2107 (int)sizeof(member->ar_hdr.ar_date),
2108 (long int)stat_buf.st_mtime,
2109 (int)sizeof(member->ar_hdr.ar_uid),
2110 (unsigned short)stat_buf.st_uid,
2111 (int)sizeof(member->ar_hdr.ar_gid),
2112 (unsigned short)stat_buf.st_gid,
2113 (int)sizeof(member->ar_hdr.ar_mode),
2114 (unsigned int)stat_buf.st_mode,
2115 (int)sizeof(member->ar_hdr.ar_size),
2116 (long)size + ar_name_size,
2117 (int)sizeof(member->ar_hdr.ar_fmag),
2118 ARFMAG);
2120 else{
2122 * We are creating an archive member in the output file from an
2123 * archive member in an input file. There can be some changes to
2124 * the contents. First the size might be changed and the contents
2125 * padded with '\n's to round it to a multiple of 8
2126 * Second we may take a member using extended format #1
2127 * for it's name and truncate it then place the name in the archive
2128 * header. Or we may round the name size to a multiple of 8.
2130 member->input_ar_hdr = ofile->member_ar_hdr;
2131 member->input_base_name = ofile->member_name;
2132 member->input_base_name_size = ofile->member_name_size;
2133 member->input_member_offset = ofile->member_offset -
2134 sizeof(struct ar_hdr);
2135 if(strncmp(ofile->member_ar_hdr->ar_name, AR_EFMT1,
2136 sizeof(AR_EFMT1) - 1) == 0)
2137 member->input_member_offset -= ofile->member_name_size;
2139 member->ar_hdr = *(ofile->member_ar_hdr);
2140 member->member_name = ofile->member_name;
2142 if(cmd_flags.use_long_names == TRUE){
2144 * We can use long names. So if the input ofile is using the
2145 * extended format #1 we need make sure the size of the name and
2146 * the size of struct ar_hdr are rounded to 8 bytes. And write
2147 * that size into the ar_name with the AR_EFMT1 string. To
2148 * avoid growing the size of names first trim the long name size
2149 * before rounding up.
2151 if(ofile->member_name != ofile->member_ar_hdr->ar_name){
2152 member->output_long_name = TRUE;
2153 member->member_name_size = ofile->member_name_size;
2154 for(ar_name_size = member->member_name_size;
2155 ar_name_size > 1 ;
2156 ar_name_size--){
2157 if(ofile->member_name[ar_name_size - 1] != '\0')
2158 break;
2160 member->member_name_size = ar_name_size;
2161 ar_name_size = rnd(ar_name_size, 8) +
2162 (rnd(sizeof(struct ar_hdr), 8) -
2163 sizeof(struct ar_hdr));
2164 sprintf(ar_name_buf, "%s%-*lu", AR_EFMT1,
2165 (int)(sizeof(member->ar_hdr.ar_name) -
2166 (sizeof(AR_EFMT1) - 1)),
2167 (long unsigned int)ar_name_size);
2168 memcpy(member->ar_hdr.ar_name, ar_name_buf,
2169 sizeof(member->ar_hdr.ar_name));
2171 else{
2173 * Since we can use long names force this to use extended
2174 * format #1. And round the name size to 8 plus the size of
2175 * struct ar_hdr rounded to 8 bytes.
2177 member->member_name_size = size_ar_name(&member->ar_hdr);
2178 ar_name_size = rnd(ofile->member_name_size, 8) +
2179 (rnd(sizeof(struct ar_hdr), 8) -
2180 sizeof(struct ar_hdr));
2181 member->output_long_name = TRUE;
2182 sprintf(ar_name_buf, "%s%-*lu", AR_EFMT1,
2183 (int)(sizeof(member->ar_hdr.ar_name) -
2184 (sizeof(AR_EFMT1) - 1)),
2185 (long unsigned int)ar_name_size);
2186 memcpy(member->ar_hdr.ar_name, ar_name_buf,
2187 sizeof(member->ar_hdr.ar_name));
2190 else{
2192 * We can't use long names. So if the input ofile is using the
2193 * extended format #1 we need to truncate the name and write it
2194 * into the ar_name field. Note the extended format is also
2195 * used it the name has a space in it so it may be shorter than
2196 * sizeof(ar_hdr.ar_name) .
2198 ar_name_size = 0;
2199 member->output_long_name = FALSE;
2200 if(ofile->member_name != ofile->member_ar_hdr->ar_name){
2201 for(j = 0; j < sizeof(member->ar_hdr.ar_name) &&
2202 j < ofile->member_name_size &&
2203 ofile->member_name[j] != '\0'; j++)
2204 member->ar_hdr.ar_name[j] = ofile->member_name[j];
2205 for( ; j < sizeof(member->ar_hdr.ar_name); j++)
2206 member->ar_hdr.ar_name[j] = ' ';
2208 member->member_name_size = size_ar_name(&member->ar_hdr);
2211 * Since sprintf() writes a '\0' at the end of the string the
2212 * memcpy is needed to preserve the ARFMAG string that follows.
2214 sprintf(ar_size_buf, "%-*ld",
2215 (int)sizeof(member->ar_hdr.ar_size),
2216 (long)size + ar_name_size);
2217 memcpy(member->ar_hdr.ar_size, ar_size_buf,
2218 sizeof(member->ar_hdr.ar_size));
2221 member->offset = arch->size;
2222 arch->size += sizeof(struct ar_hdr) + size + ar_name_size;
2224 if(ofile->mh != NULL ||
2225 ofile->mh64 != NULL){
2226 member->object_addr = ofile->object_addr;
2227 member->object_size = ofile->object_size;
2228 member->object_byte_sex = ofile->object_byte_sex;
2229 member->mh = ofile->mh;
2230 member->mh64 = ofile->mh64;
2231 member->load_commands = ofile->load_commands;
2233 #ifdef LTO_SUPPORT
2234 else if(ofile->file_type == OFILE_LLVM_BITCODE){
2235 member->object_addr = ofile->file_addr;
2236 member->object_size = ofile->file_size;
2237 member->lto_contents = TRUE;
2238 save_lto_member_toc_info(member, ofile->lto);
2239 lto_free(ofile->lto);
2240 ofile->lto = NULL;
2241 member->object_byte_sex = get_byte_sex_from_flag(&arch->arch_flag);
2243 else if((ofile->file_type == OFILE_FAT &&
2244 ofile->arch_type == OFILE_LLVM_BITCODE) ||
2245 (ofile->file_type == OFILE_ARCHIVE &&
2246 ofile->member_type == OFILE_FAT &&
2247 ofile->arch_type == OFILE_LLVM_BITCODE)){
2248 member->object_addr = ofile->object_addr;
2249 member->object_size = ofile->object_size;
2250 member->lto_contents = TRUE;
2251 save_lto_member_toc_info(member, ofile->lto);
2252 lto_free(ofile->lto);
2253 ofile->lto = NULL;
2254 member->object_byte_sex = get_byte_sex_from_flag(&arch->arch_flag);
2256 #endif /* LTO_SUPPORT */
2257 else{
2258 member->object_addr = ofile->member_addr;
2259 member->object_size = ofile->member_size;
2260 #ifdef LTO_SUPPORT
2261 if(ofile->lto != NULL){
2262 member->lto_contents = TRUE;
2263 save_lto_member_toc_info(member, ofile->lto);
2264 lto_free(ofile->lto);
2265 ofile->lto = NULL;
2266 member->object_byte_sex = get_byte_sex_from_flag(
2267 &arch->arch_flag);
2269 #endif /* LTO_SUPPORT */
2274 * free_archs() frees the memory allocated that is pointed to by archs.
2276 static
2277 void
2278 free_archs(
2279 void)
2281 uint32_t i;
2283 for(i = 0 ; i < narchs; i++){
2285 * Just leak memory on the arch_flag.name in some cases
2286 * (unknown archiectures only where the space is malloced and
2287 * a sprintf() is done into the memory)
2289 if(archs[i].tocs != NULL)
2290 free(archs[i].tocs);
2291 if(archs[i].toc_ranlibs != NULL)
2292 free(archs[i].toc_ranlibs);
2293 if(archs[i].toc_ranlibs64 != NULL)
2294 free(archs[i].toc_ranlibs64);
2295 if(archs[i].toc_strings != NULL)
2296 free(archs[i].toc_strings);
2297 if(archs[i].members != NULL)
2298 free(archs[i].members);
2300 if(archs != NULL)
2301 free(archs);
2302 archs = NULL;
2303 narchs = 0;
2307 * create_library() creates a library from the data structure pointed to by
2308 * archs into the specified output file. Only when more than one architecture
2309 * is in archs will a fat file be created.
2311 * In the case of cmd_flags.ranlib == TRUE the ofile may not be NULL if it
2312 * from a thin archive. If so and the toc_* fields are set and we may update
2313 * the table of contents in place if the new one fits where the old table of
2314 * contents was.
2316 static
2317 void
2318 create_library(
2319 char *output,
2320 struct ofile *ofile)
2322 uint32_t i, j, k, pad;
2323 uint64_t library_size, offset, *time_offsets;
2324 enum byte_sex target_byte_sex;
2325 char *library, *p, *flush_start;
2326 kern_return_t r;
2327 struct arch *arch;
2328 struct fat_header *fat_header;
2329 struct fat_arch *fat_arch;
2330 struct fat_arch_64 *fat_arch64;
2331 int fd;
2332 #ifndef __OPENSTEP__
2333 struct utimbuf timep;
2334 #else
2335 time_t timep[2];
2336 #endif
2337 struct stat stat_buf;
2338 struct ar_hdr toc_ar_hdr;
2339 enum bool some_tocs, same_toc, different_offsets;
2341 if(narchs == 0){
2342 if(cmd_flags.ranlib == TRUE){
2343 if(cmd_flags.q == FALSE)
2344 warning("empty library: %s (no table of contents added)",
2345 output);
2346 return;
2348 else{
2349 if(cmd_flags.dynamic == FALSE ||
2350 cmd_flags.no_files_ok == FALSE){
2351 if(cmd_flags.arch_only_flag.name != NULL)
2352 error("no library created (no object files in input "
2353 "files matching -arch_only %s)",
2354 cmd_flags.arch_only_flag.name);
2355 else
2356 error("no library created (no object files in input "
2357 "files)");
2358 return;
2363 if(cmd_flags.dynamic == TRUE){
2364 create_dynamic_shared_library(output);
2365 return;
2368 /* if this is libtool warn about duplicate member names */
2369 if(cmd_flags.ranlib == FALSE)
2370 warn_duplicate_member_names();
2373 * Calculate the total size of the library and the final size of each
2374 * architecture.
2376 if(narchs > 1){
2377 library_size = sizeof(struct fat_header);
2378 if(cmd_flags.fat64 == TRUE)
2379 library_size += sizeof(struct fat_arch_64) * narchs;
2380 else
2381 library_size += sizeof(struct fat_arch) * narchs;
2383 * The ar(1) program uses the -q flag to ranlib(1) to add a table
2384 * of contents only of the output is not a fat file. This is done
2385 * by default for UNIX standards conformance when the files are
2386 * thin .o files.
2388 if(cmd_flags.q == TRUE)
2389 exit(EXIT_SUCCESS);
2391 * The ar(1) program uses the -f to ranlib(1) when it see the 's'
2392 * option. And if we are creating a fat file issue a warning that
2393 * ar(1) will not be able to use it.
2395 if(cmd_flags.f == TRUE)
2396 warning("archive library: %s will be fat and ar(1) will not "
2397 "be able to operate on it", output);
2399 else
2400 library_size = 0;
2401 some_tocs = FALSE;
2402 for(i = 0; i < narchs; i++){
2403 if(narchs > 1 && (archs[i].arch_flag.cputype & CPU_ARCH_ABI64))
2404 library_size = rnd(library_size, 1 << 3);
2405 make_table_of_contents(archs + i, output);
2406 if(errors != 0)
2407 return;
2408 if(archs[i].toc_nranlibs != 0)
2409 some_tocs = TRUE;
2410 archs[i].size += SARMAG + archs[i].toc_size;
2411 library_size += archs[i].size;
2414 * The ar(1) program uses the -q flag to ranlib(1) to add a table of
2415 * contents only of the output contains some object files. This is
2416 * done for UNIX standards conformance.
2418 if(cmd_flags.q == TRUE && some_tocs == FALSE)
2419 exit(EXIT_SUCCESS);
2422 * If this is ranlib(1) and we are running in UNIX standard mode and
2423 * the file is not writeable just print and error message and return.
2425 if(cmd_flags.ranlib == TRUE &&
2426 get_unix_standard_mode() == TRUE &&
2427 access(output, W_OK) == -1){
2428 system_error("file: %s is not writable", output);
2429 return;
2433 * If this is ranlib(1) and we have a thin archive that has an existing
2434 * table of contents see if we have enough room to update it in place.
2435 * Actually we check to see that we have the exact same number of
2436 * ranlib structs and string size, as this is the most common case that
2437 * the defined global symbols have not changed when rebuilding and it
2438 * will just be the offset to archive members that will have changed.
2440 if(cmd_flags.ranlib == TRUE && narchs == 1 &&
2441 ofile != NULL && ofile->toc_addr != NULL &&
2442 ofile->toc_bad == FALSE &&
2443 archs[0].using_64toc != ofile->toc_is_32bit &&
2444 archs[0].toc_nranlibs == ofile->toc_nranlibs &&
2445 archs[0].toc_strsize == ofile->toc_strsize){
2448 * If the table of contents in the input does have a long name and
2449 * the one we built does not (or vice a versa) then don't update it
2450 * in place.
2452 if(strncmp(ofile->toc_ar_hdr->ar_name, AR_EFMT1,
2453 sizeof(AR_EFMT1) - 1) == 0){
2454 if(archs[0].toc_long_name != TRUE)
2455 goto fail_to_update_toc_in_place;
2457 else{
2458 if(archs[0].toc_long_name == TRUE)
2459 goto fail_to_update_toc_in_place;
2463 * The existing thin archive may not be laid out the same way as
2464 * libtool(1) would do it. As ar(1) does not know to pad things
2465 * so object files are on their natural alignment. So check to
2466 * see if the offsets are not the same and if the alignment is OK.
2468 different_offsets = FALSE;
2469 for(i = 0; i < archs[0].nmembers; i++){
2470 if(archs[0].members[i].input_member_offset !=
2471 archs[0].members[i].offset){
2472 different_offsets = TRUE;
2474 * For now we will allow alignments of 4 bytes offsets even
2475 * though we would produce 8 byte alignments.
2477 if(archs[0].members[i].input_member_offset % 4 != 0){
2478 goto fail_to_update_toc_in_place;
2484 * The time_offsets array records the offsets to the table of
2485 * contents archive header's ar_date fields. In this case we just
2486 * have one since this is a thin file (non-fat) file.
2488 time_offsets = allocate(1 * sizeof(uint64_t));
2490 * Calculate the offset to the archive header's time field for the
2491 * table of contents.
2493 time_offsets[0] = SARMAG +
2494 ((char *)&toc_ar_hdr.ar_date - (char *)&toc_ar_hdr);
2497 * If we had different member offsets in the input thin archive
2498 * we adjust the ranlib structs ran_off to use them.
2500 if(different_offsets == TRUE){
2501 same_toc = FALSE;
2502 if(archs[0].using_64toc == FALSE){
2503 for(i = 0; i < archs[0].toc_nranlibs; i++){
2504 for(j = 0; j < archs[0].nmembers; j++){
2505 if(archs[0].members[j].offset ==
2506 archs[0].toc_ranlibs[i].ran_off){
2507 archs[0].toc_ranlibs[i].ran_off =
2508 archs[0].members[j].input_member_offset;
2509 break;
2514 else{
2515 for(i = 0; i < archs[0].toc_nranlibs; i++){
2516 for(j = 0; j < archs[0].nmembers; j++){
2517 if(archs[0].members[j].offset ==
2518 archs[0].toc_ranlibs64[i].ran_off){
2519 archs[0].toc_ranlibs64[i].ran_off =
2520 archs[0].members[j].input_member_offset;
2521 break;
2527 else{
2529 * If the new table of contents and the new string table are the
2530 * same as the old then the archive only needs to be "touched"
2531 * and the time field of the toc needs to be updated.
2533 same_toc = TRUE;
2534 for(i = 0; i < archs[0].toc_nranlibs; i++){
2535 if(archs[0].using_64toc == FALSE){
2536 if(archs[0].toc_ranlibs[i].ran_un.ran_strx !=
2537 ofile->toc_ranlibs[i].ran_un.ran_strx ||
2538 archs[0].toc_ranlibs[i].ran_off !=
2539 ofile->toc_ranlibs[i].ran_off){
2540 same_toc = FALSE;
2541 break;
2544 else{
2545 if(archs[0].toc_ranlibs64[i].ran_un.ran_strx !=
2546 ofile->toc_ranlibs64[i].ran_un.ran_strx ||
2547 archs[0].toc_ranlibs64[i].ran_off !=
2548 ofile->toc_ranlibs64[i].ran_off){
2549 same_toc = FALSE;
2550 break;
2554 if(same_toc == TRUE){
2555 for(i = 0; i < archs[0].toc_strsize; i++){
2556 if(archs[0].toc_strings[i] != ofile->toc_strings[i]){
2557 same_toc = FALSE;
2558 break;
2564 library_size = SARMAG;
2565 if(same_toc == FALSE)
2566 library_size += archs[0].toc_size;
2567 if((r = vm_allocate(mach_task_self(), (vm_address_t *)&library,
2568 library_size, TRUE)) != KERN_SUCCESS)
2569 mach_fatal(r, "can't vm_allocate() buffer for output file: %s "
2570 "of size %llu", output, library_size);
2573 /* put in the archive magic string in the buffer */
2574 p = library;
2575 memcpy(p, ARMAG, SARMAG);
2576 p += SARMAG;
2578 /* put the table of contents in the buffer if needed */
2579 target_byte_sex = get_target_byte_sex(archs + 0, host_byte_sex);
2580 if(same_toc == FALSE)
2581 p = put_toc_member(p, archs+0, host_byte_sex, target_byte_sex);
2583 if((fd = open(output, O_WRONLY, 0)) == -1){
2584 system_error("can't open output file: %s", output);
2585 return;
2587 if(write(fd, library, library_size) != (int)library_size){
2588 system_error("can't write output file: %s", output);
2589 return;
2591 if(close(fd) == -1){
2592 system_fatal("can't close output file: %s", output);
2593 return;
2595 goto update_toc_ar_dates;
2597 fail_to_update_toc_in_place:
2600 * This buffer is vm_allocate'ed to make sure all holes are filled with
2601 * zero bytes.
2603 if((r = vm_allocate(mach_task_self(), (vm_address_t *)&library,
2604 library_size, TRUE)) != KERN_SUCCESS)
2605 mach_fatal(r, "can't vm_allocate() buffer for output file: %s of "
2606 "size %llu", output, library_size);
2609 * Create the output file. The unlink() is done to handle the problem
2610 * when the outputfile is not writable but the directory allows the
2611 * file to be removed (since the file may not be there the return code
2612 * of the unlink() is ignored).
2614 (void)unlink(output);
2615 if((fd = open(output, O_WRONLY | O_CREAT | O_TRUNC, 0666)) == -1){
2616 system_error("can't create output file: %s", output);
2617 return;
2619 #ifdef F_NOCACHE
2620 /* tell filesystem to NOT cache the file when reading or writing */
2621 (void)fcntl(fd, F_NOCACHE, 1);
2622 #endif
2625 * If there is more than one architecture then fill in the fat file
2626 * header and the fat_arch or fat_arch64 structures in the buffer.
2628 if(narchs > 1){
2629 fat_header = (struct fat_header *)library;
2630 if(cmd_flags.fat64 == TRUE)
2631 fat_header->magic = FAT_MAGIC_64;
2632 else
2633 fat_header->magic = FAT_MAGIC;
2634 fat_header->nfat_arch = narchs;
2635 offset = sizeof(struct fat_header);
2636 if(cmd_flags.fat64 == TRUE){
2637 offset += sizeof(struct fat_arch_64) * narchs;
2638 fat_arch64 = (struct fat_arch_64 *)
2639 (library + sizeof(struct fat_header));
2640 fat_arch = NULL;
2642 else{
2643 offset += sizeof(struct fat_arch) * narchs;
2644 fat_arch = (struct fat_arch *)
2645 (library + sizeof(struct fat_header));
2646 fat_arch64 = NULL;
2648 for(i = 0; i < narchs; i++){
2649 if(cmd_flags.fat64 == TRUE){
2650 fat_arch64[i].cputype = archs[i].arch_flag.cputype;
2651 fat_arch64[i].cpusubtype = archs[i].arch_flag.cpusubtype;
2653 else{
2654 fat_arch[i].cputype = archs[i].arch_flag.cputype;
2655 fat_arch[i].cpusubtype = archs[i].arch_flag.cpusubtype;
2657 if(cmd_flags.fat64 == FALSE && offset > UINT32_MAX)
2658 error("file too large to create as a fat file because "
2659 "offset field in struct fat_arch is only 32-bits and "
2660 "offset (%llu) to architecture %s exceeds that",
2661 offset, archs[i].arch_flag.name);
2662 if(archs[i].arch_flag.cputype & CPU_ARCH_ABI64){
2663 if(cmd_flags.fat64 == TRUE)
2664 fat_arch64[i].align = 3;
2665 else
2666 fat_arch[i].align = 3;
2668 else{
2669 if(cmd_flags.fat64 == TRUE)
2670 fat_arch64[i].align = 2;
2671 else
2672 fat_arch[i].align = 2;
2674 if(cmd_flags.fat64 == TRUE)
2675 offset = rnd(offset, 1 << fat_arch64[i].align);
2676 else
2677 offset = rnd(offset, 1 << fat_arch[i].align);
2678 if(cmd_flags.fat64 == TRUE)
2679 fat_arch64[i].offset = offset;
2680 else
2681 fat_arch[i].offset = offset;
2682 if(cmd_flags.fat64 == FALSE && archs[i].size > UINT32_MAX)
2683 error("file too large to create as a fat file because "
2684 "size field in struct fat_arch is only 32-bits and "
2685 "size (%llu) of architecture %s exceeds that",
2686 archs[i].size, archs[i].arch_flag.name);
2687 if(cmd_flags.fat64 == TRUE)
2688 fat_arch64[i].size = archs[i].size;
2689 else
2690 fat_arch[i].size = archs[i].size;
2691 offset += archs[i].size;
2693 if(errors != 0){
2694 (void)unlink(output);
2695 return;
2697 #ifdef __LITTLE_ENDIAN__
2698 swap_fat_header(fat_header, BIG_ENDIAN_BYTE_SEX);
2699 if(cmd_flags.fat64 == TRUE)
2700 swap_fat_arch_64(fat_arch64, narchs, BIG_ENDIAN_BYTE_SEX);
2701 else
2702 swap_fat_arch(fat_arch, narchs, BIG_ENDIAN_BYTE_SEX);
2703 #endif /* __LITTLE_ENDIAN__ */
2704 offset = sizeof(struct fat_header);
2705 if(cmd_flags.fat64 == TRUE)
2706 offset += sizeof(struct fat_arch_64) * narchs;
2707 else
2708 offset += sizeof(struct fat_arch) * narchs;
2710 else
2711 offset = 0;
2713 /* flush out the fat headers if any */
2714 output_flush(library, library_size, fd, 0, offset);
2717 * The time_offsets array records the offsets to the table of conternts
2718 * archive header's ar_date fields.
2720 time_offsets = allocate(narchs * sizeof(uint64_t));
2723 * Now put each arch in the buffer.
2725 for(i = 0; i < narchs; i++){
2726 arch = archs + i;
2727 if(narchs > 1 && (arch->arch_flag.cputype & CPU_ARCH_ABI64)){
2728 pad = rnd(offset, 1 << 3) - offset;
2729 output_flush(library, library_size, fd, offset, pad);
2730 offset = rnd(offset, 1 << 3);
2732 p = library + offset;
2733 flush_start = p;
2736 * If the input files only contains non-object files then the
2737 * byte sex of the output can't be determined which is needed for
2738 * the two binary long's of the table of contents. But since these
2739 * will be zero (the same in both byte sexes) because there are no
2740 * symbols in the table of contents if there are no object files.
2743 /* put in the archive magic string */
2744 memcpy(p, ARMAG, SARMAG);
2745 p += SARMAG;
2748 * Warn for what really is a bad library that has an empty table of
2749 * contents but this is allowed in the original ranlib.
2751 if(arch->toc_nranlibs == 0 && cmd_flags.q == FALSE){
2752 if(narchs > 1)
2753 warning("warning for library: %s for architecture: %s the "
2754 "table of contents is empty (no object file members"
2755 " in the library define global symbols)", output,
2756 arch->arch_flag.name);
2757 else
2758 warning("warning for library: %s the table of contents is "
2759 "empty (no object file members in the library "
2760 "define global symbols)", output);
2764 * Pick the byte sex to write the table of contents in.
2766 target_byte_sex = get_target_byte_sex(arch, host_byte_sex);
2769 * Remember the offset to the archive header's time field for this
2770 * arch's table of contents member.
2772 time_offsets[i] =
2773 (p - library) +
2774 ((char *)&toc_ar_hdr.ar_date - (char *)&toc_ar_hdr);
2777 * Put in the table of contents member in the output buffer.
2779 p = put_toc_member(p, arch, host_byte_sex, target_byte_sex);
2781 output_flush(library, library_size, fd, flush_start - library,
2782 p - flush_start);
2785 * Put in the archive header and member contents for each member.
2787 for(j = 0; j < arch->nmembers; j++){
2788 flush_start = p;
2789 memcpy(p, (char *)&(arch->members[j].ar_hdr),
2790 sizeof(struct ar_hdr));
2791 p += sizeof(struct ar_hdr);
2794 * If we are using extended format #1 for long names write out
2795 * the name. Note the name is padded with '\0' and the
2796 * member_name_size is the unrounded size.
2798 if(arch->members[j].output_long_name == TRUE){
2799 strncpy(p, arch->members[j].member_name,
2800 arch->members[j].member_name_size);
2801 p += rnd(arch->members[j].member_name_size, 8) +
2802 (rnd(sizeof(struct ar_hdr), 8) -
2803 sizeof(struct ar_hdr));
2807 * ofile_map swaps the headers to the host_byte_sex if the
2808 * object's byte sex is not the same as the host byte sex so
2809 * if this is the case swap them back before writing them out.
2811 if(arch->members[j].mh != NULL &&
2812 arch->members[j].object_byte_sex != host_byte_sex){
2813 if(swap_object_headers(arch->members[j].mh,
2814 arch->members[j].load_commands) == FALSE)
2815 fatal("internal error: swap_object_headers() failed");
2817 else if(arch->members[j].mh64 != NULL &&
2818 arch->members[j].object_byte_sex != host_byte_sex){
2819 if(swap_object_headers(arch->members[j].mh64,
2820 arch->members[j].load_commands) == FALSE)
2821 fatal("internal error: swap_object_headers() failed");
2823 memcpy(p, arch->members[j].object_addr,
2824 arch->members[j].object_size);
2825 #ifdef VM_SYNC_DEACTIVATE
2826 vm_msync(mach_task_self(),
2827 (vm_address_t)arch->members[j].object_addr,
2828 (vm_size_t)arch->members[j].object_size,
2829 VM_SYNC_DEACTIVATE);
2830 #endif /* VM_SYNC_DEACTIVATE */
2831 p += arch->members[j].object_size;
2832 pad = rnd(arch->members[j].object_size, 8) -
2833 arch->members[j].object_size;
2834 /* as with the UNIX ar(1) program pad with '\n' characters */
2835 for(k = 0; k < pad; k++)
2836 *p++ = '\n';
2838 output_flush(library, library_size, fd, flush_start - library,
2839 p - flush_start);
2841 offset += arch->size;
2845 * Write the library to the file or flush the remaining buffer to the
2846 * file.
2848 if(cmd_flags.noflush == TRUE){
2849 if(write(fd, library, library_size) != (int)library_size){
2850 system_error("can't write output file: %s", output);
2851 return;
2854 else{
2855 final_output_flush(library, fd);
2857 if(close(fd) == -1){
2858 system_fatal("can't close output file: %s", output);
2859 return;
2862 update_toc_ar_dates:
2864 * Now that the library is created on the file system it is written
2865 * to get the time for the file on that file system.
2867 if(stat(output, &stat_buf) == -1){
2868 system_fatal("can't stat file output file: %s", output);
2869 return;
2871 if((fd = open(output, O_WRONLY, 0)) == -1){
2872 system_error("can't open output file: %s", output);
2873 return;
2875 if(zero_ar_date == TRUE)
2876 stat_buf.st_mtime = 0;
2878 * With the time from the file system the library is on set the ar_date
2879 * using the modification time returned by stat. Then write this into
2880 * all the ar_date's in the file.
2882 sprintf((char *)(&toc_ar_hdr), "%-*s%-*ld",
2883 (int)sizeof(toc_ar_hdr.ar_name),
2884 SYMDEF,
2885 (int)sizeof(toc_ar_hdr.ar_date),
2886 (long int)stat_buf.st_mtime + 5);
2887 for(i = 0; i < narchs; i++){
2888 if(lseek(fd, time_offsets[i], L_SET) == -1){
2889 system_error("can't lseek in output file: %s", output);
2890 return;
2892 if(write(fd, &toc_ar_hdr.ar_date, sizeof(toc_ar_hdr.ar_date)) !=
2893 sizeof(toc_ar_hdr.ar_date)){
2894 system_error("can't write to output file: %s", output);
2895 return;
2898 if(close(fd) == -1){
2899 system_fatal("can't close output file: %s", output);
2900 return;
2903 * Now set the modtime of the created library back to it's stat time
2904 * when we first closed it.
2906 #ifndef __OPENSTEP__
2907 timep.actime = stat_buf.st_mtime;
2908 timep.modtime = stat_buf.st_mtime;
2909 if(utime(output, &timep) == -1)
2910 #else
2911 timep[0] = stat_buf.st_mtime;
2912 timep[1] = stat_buf.st_mtime;
2913 if(utime(output, timep) == -1)
2914 #endif
2916 system_fatal("can't set the modifiy times in output file: %s",
2917 output);
2918 return;
2920 if((r = vm_deallocate(mach_task_self(), (vm_address_t)library,
2921 library_size)) != KERN_SUCCESS){
2922 my_mach_error(r, "can't vm_deallocate() buffer for output file");
2923 return;
2928 * get_target_byte_sex() pick the byte sex to write the table of contents in
2929 * for the arch.
2931 static
2932 enum byte_sex
2933 get_target_byte_sex(
2934 struct arch *arch,
2935 enum byte_sex host_byte_sex)
2937 uint32_t i;
2938 enum byte_sex target_byte_sex;
2940 target_byte_sex = UNKNOWN_BYTE_SEX;
2941 for(i = 0;
2942 i < arch->nmembers && target_byte_sex == UNKNOWN_BYTE_SEX;
2943 i++){
2944 target_byte_sex = arch->members[i].object_byte_sex;
2946 if(target_byte_sex == UNKNOWN_BYTE_SEX)
2947 target_byte_sex = host_byte_sex;
2948 return(target_byte_sex);
2952 * put_toc_member() put the contents member for arch into the buffer p and
2953 * returns the pointer to the buffer after the table of contents.
2954 * The table of contents member uses either a 32-bit toc or a 64-bit toc.
2955 * Both forms start with:
2956 * the archive header
2957 * the archive member name (if using a long name)
2958 * then for a 32-bit toc the rest is this:
2959 * a uint32_t for the number of bytes of the ranlib structs
2960 * the ranlib structs
2961 * a uint32_t for the number of bytes of the strings for the ranlibs
2962 * the strings for the ranlib structs
2963 * and for a 64-bit toc the rest is this:
2964 * a uint64_t for the number of bytes of the ranlib structs
2965 * the ranlib_64 structs
2966 * a uint64_t for the number of bytes of the strings for the ranlibs
2967 * the strings for the ranlib structs
2969 static
2970 char *
2971 put_toc_member(
2972 char *p,
2973 struct arch *arch,
2974 enum byte_sex host_byte_sex,
2975 enum byte_sex target_byte_sex)
2977 uint32_t l;
2978 uint64_t l64;
2980 memcpy(p, (char *)&arch->toc_ar_hdr, sizeof(struct ar_hdr));
2981 p += sizeof(struct ar_hdr);
2983 if(arch->toc_long_name == TRUE){
2984 memcpy(p, arch->toc_name, arch->toc_name_size);
2985 p += arch->toc_name_size +
2986 (rnd(sizeof(struct ar_hdr), 8) -
2987 sizeof(struct ar_hdr));
2990 if(arch->using_64toc == FALSE){
2991 l = arch->toc_nranlibs * sizeof(struct ranlib);
2992 if(target_byte_sex != host_byte_sex)
2993 l = SWAP_INT(l);
2994 memcpy(p, (char *)&l, sizeof(uint32_t));
2995 p += sizeof(uint32_t);
2997 if(target_byte_sex != host_byte_sex)
2998 swap_ranlib(arch->toc_ranlibs, arch->toc_nranlibs,
2999 target_byte_sex);
3000 memcpy(p, (char *)arch->toc_ranlibs,
3001 arch->toc_nranlibs * sizeof(struct ranlib));
3002 p += arch->toc_nranlibs * sizeof(struct ranlib);
3004 l = arch->toc_strsize;
3005 if(target_byte_sex != host_byte_sex)
3006 l = SWAP_INT(l);
3007 memcpy(p, (char *)&l, sizeof(uint32_t));
3008 p += sizeof(uint32_t);
3010 memcpy(p, (char *)arch->toc_strings, arch->toc_strsize);
3011 p += arch->toc_strsize;
3013 else{
3014 l64 = arch->toc_nranlibs * sizeof(struct ranlib_64);
3015 if(target_byte_sex != host_byte_sex)
3016 l64 = SWAP_LONG_LONG(l64);
3017 memcpy(p, (char *)&l64, sizeof(uint64_t));
3018 p += sizeof(uint64_t);
3020 if(target_byte_sex != host_byte_sex)
3021 swap_ranlib_64(arch->toc_ranlibs64, arch->toc_nranlibs,
3022 target_byte_sex);
3023 memcpy(p, (char *)arch->toc_ranlibs64,
3024 arch->toc_nranlibs * sizeof(struct ranlib_64));
3025 p += arch->toc_nranlibs * sizeof(struct ranlib_64);
3027 l64 = arch->toc_strsize;
3028 if(target_byte_sex != host_byte_sex)
3029 l64 = SWAP_LONG_LONG(l64);
3030 memcpy(p, (char *)&l64, sizeof(uint64_t));
3031 p += sizeof(uint64_t);
3033 memcpy(p, (char *)arch->toc_strings, arch->toc_strsize);
3034 p += arch->toc_strsize;
3037 return(p);
3041 * output_flush() takes an offset and a size of part of the output library,
3042 * known in the comments as the new area, and causes any fully flushed pages to
3043 * be written to the library file the new area in combination with previous
3044 * areas created. The data structure output_blocks has ordered blocks of areas
3045 * that have been flushed which are maintained by this routine. Any area can
3046 * only be flushed once and an error will result is the new area overlaps with a
3047 * previously flushed area.
3049 static
3050 void
3051 output_flush(
3052 char *library,
3053 uint64_t library_size,
3054 int fd,
3055 uint64_t offset,
3056 uint64_t size)
3058 uint64_t write_offset, write_size, host_pagesize;
3059 struct block **p, *block, *before, *after;
3060 kern_return_t r;
3062 host_pagesize = 0x2000;
3064 if(cmd_flags.noflush == TRUE)
3065 return;
3067 if(offset + size > library_size)
3068 fatal("internal error: output_flush(offset = %llu, size = %llu) "
3069 "out of range for library_size = %llu", offset, size,
3070 library_size);
3072 #ifdef DEBUG
3073 if(cmd_flags.debug & (1 << 2))
3074 print_block_list();
3075 if(cmd_flags.debug & (1 << 1))
3076 printf("output_flush(offset = %llu, size %llu)", offset, size);
3077 #endif /* DEBUG */
3079 if(size == 0){
3080 #ifdef DEBUG
3081 if(cmd_flags.debug & (1 << 1))
3082 printf("\n");
3083 #endif /* DEBUG */
3084 return;
3088 * Search through the ordered output blocks to find the block before the
3089 * new area and after the new area if any exist.
3091 before = NULL;
3092 after = NULL;
3093 p = &(output_blocks);
3094 while(*p){
3095 block = *p;
3096 if(offset < block->offset){
3097 after = block;
3098 break;
3100 else{
3101 before = block;
3103 p = &(block->next);
3107 * Check for overlap of the new area with the block before and after the
3108 * new area if there are such blocks.
3110 if(before != NULL){
3111 if(before->offset + before->size > offset){
3112 warning("internal error: output_flush(offset = %llu, size = "
3113 "%llu) overlaps with flushed block(offset = %llu, "
3114 "size = %llu)", offset, size, before->offset,
3115 before->size);
3116 printf("calling abort()\n");
3117 abort();
3120 if(after != NULL){
3121 if(offset + size > after->offset){
3122 warning("internal error: output_flush(offset = %llu, size = "
3123 "%llu) overlaps with flushed block(offset = %llu, "
3124 "size = %llu)", offset, size, after->offset,
3125 after->size);
3126 printf("calling abort()\n");
3127 abort();
3132 * Now see how the new area fits in with the blocks before and after it
3133 * (that is does it touch both, one or the other or neither blocks).
3134 * For each case first the offset and size to write (write_offset and
3135 * write_size) are set for the area of full pages that can now be
3136 * written from the block. Then the area written in the block
3137 * (->written_offset and ->written_size) are set to reflect the total
3138 * area in the block now written. Then offset and size the block
3139 * refers to (->offset and ->size) are set to total area of the block.
3140 * Finally the links to others blocks in the list are adjusted if a
3141 * block is added or removed.
3143 * See if there is a block before the new area and the new area
3144 * starts at the end of that block.
3146 if(before != NULL && before->offset + before->size == offset){
3148 * See if there is also a block after the new area and the new area
3149 * ends at the start of that block.
3151 if(after != NULL && offset + size == after->offset){
3153 * This is the case where the new area exactly fill the area
3154 * between two existing blocks. The total area is folded into
3155 * the block before the new area and the block after the new
3156 * area is removed from the list.
3158 if(before->offset == 0 && before->written_size == 0){
3159 write_offset = 0;
3160 before->written_offset = 0;
3162 else
3163 write_offset =before->written_offset + before->written_size;
3164 if(after->written_size == 0)
3165 write_size = trnc(after->offset + after->size -
3166 write_offset, host_pagesize);
3167 else
3168 write_size = trnc(after->written_offset - write_offset,
3169 host_pagesize);
3170 if(write_size != 0){
3171 before->written_size += write_size;
3173 if(after->written_size != 0)
3174 before->written_size += after->written_size;
3175 before->size += size + after->size;
3177 /* remove the block after the new area */
3178 before->next = after->next;
3179 remove_block(after);
3181 else{
3183 * This is the case where the new area starts at the end of the
3184 * block just before it but does not end where the block after
3185 * it (if any) starts. The new area is folded into the block
3186 * before the new area.
3188 write_offset = before->written_offset + before->written_size;
3189 write_size = trnc(offset + size - write_offset, host_pagesize);
3190 if(write_size != 0)
3191 before->written_size += write_size;
3192 before->size += size;
3196 * See if the new area and the new area ends at the start of the block
3197 * after it (if any).
3199 else if(after != NULL && offset + size == after->offset){
3201 * This is the case where the new area ends at the begining of the
3202 * block just after it but does not start where the block before it.
3203 * (if any) ends. The new area is folded into this block after the
3204 * new area.
3206 write_offset = rnd(offset, host_pagesize);
3207 if(after->written_size == 0)
3208 write_size = trnc(after->offset + after->size - write_offset,
3209 host_pagesize);
3210 else
3211 write_size = trnc(after->written_offset - write_offset,
3212 host_pagesize);
3213 if(write_size != 0){
3214 after->written_offset = write_offset;
3215 after->written_size += write_size;
3217 else if(write_offset != after->written_offset){
3218 after->written_offset = write_offset;
3220 after->offset = offset;
3221 after->size += size;
3223 else{
3225 * This is the case where the new area neither starts at the end of
3226 * the block just before it (if any) or ends where the block after
3227 * it (if any) starts. A new block is created and the new area is
3228 * is placed in it.
3230 write_offset = rnd(offset, host_pagesize);
3231 write_size = trnc(offset + size - write_offset, host_pagesize);
3232 block = get_block();
3233 block->offset = offset;
3234 block->size = size;
3235 block->written_offset = write_offset;
3236 block->written_size = write_size;
3238 * Insert this block in the ordered list in the correct place.
3240 if(before != NULL){
3241 block->next = before->next;
3242 before->next = block;
3244 else{
3245 block->next = output_blocks;
3246 output_blocks = block;
3251 * Now if there are full pages to write write them to the output file.
3253 if(write_size != 0){
3254 #ifdef DEBUG
3255 if((cmd_flags.debug & (1 << 1)) || (cmd_flags.debug & (1 << 0)))
3256 printf(" writing (write_offset = %llu write_size = %llu)\n",
3257 write_offset, write_size);
3258 #endif /* DEBUG */
3259 lseek(fd, write_offset, L_SET);
3260 if(write(fd, library + write_offset, write_size) !=
3261 (int)write_size)
3262 system_fatal("can't write to output file");
3263 if((r = vm_deallocate(mach_task_self(), (vm_address_t)(library +
3264 write_offset), write_size)) != KERN_SUCCESS)
3265 mach_fatal(r, "can't vm_deallocate() buffer for output file");
3267 #ifdef DEBUG
3268 else{
3269 if(cmd_flags.debug & (1 << 1))
3270 printf(" no write\n");
3272 #endif /* DEBUG */
3276 * final_output_flush() flushes the last part of the last page of the object
3277 * file if it does not round out to exactly a page.
3279 static
3280 void
3281 final_output_flush(
3282 char *library,
3283 int fd)
3285 struct block *block;
3286 uint64_t write_offset, write_size;
3287 kern_return_t r;
3289 #ifdef DEBUG
3290 /* The compiler "warning: `write_offset' may be used uninitialized in */
3291 /* this function" can safely be ignored */
3292 write_offset = 0;
3293 if((cmd_flags.debug & (1 << 1)) || (cmd_flags.debug & (1 << 0))){
3294 printf("final_output_flush block_list:\n");
3295 print_block_list();
3297 #endif /* DEBUG */
3299 write_size = 0;
3300 block = output_blocks;
3301 if(block != NULL){
3302 if(block->offset != 0)
3303 fatal("internal error: first block not at offset 0");
3304 if(block->written_size != 0){
3305 if(block->written_offset != 0)
3306 fatal("internal error: first block written_offset not 0");
3307 write_offset = block->written_size;
3308 write_size = block->size - block->written_size;
3310 else{
3311 write_offset = block->offset;
3312 write_size = block->size;
3314 if(block->next != NULL)
3315 fatal("internal error: more than one block in final list");
3317 if(write_size != 0){
3318 #ifdef DEBUG
3319 if((cmd_flags.debug & (1 << 1)) || (cmd_flags.debug & (1 << 1)))
3320 printf(" writing (write_offset = %llu write_size = %llu)\n",
3321 write_offset, write_size);
3322 #endif /* DEBUG */
3323 lseek(fd, write_offset, L_SET);
3324 if(write(fd, library + write_offset, write_size) !=
3325 (int)write_size)
3326 system_fatal("can't write to output file");
3327 if((r = vm_deallocate(mach_task_self(), (vm_address_t)(library +
3328 write_offset), write_size)) != KERN_SUCCESS)
3329 mach_fatal(r, "can't vm_deallocate() buffer for output file");
3331 output_blocks = NULL;
3334 #ifdef DEBUG
3336 * print_block_list() prints the list of blocks. Used for debugging.
3338 static
3339 void
3340 print_block_list(void)
3342 struct block **p, *block;
3344 p = &(output_blocks);
3345 if(*p == NULL)
3346 printf("Empty block list\n");
3347 while(*p){
3348 block = *p;
3349 printf("block 0x%x\n", (unsigned long)block);
3350 printf(" offset %llu\n", block->offset);
3351 printf(" size %llu\n", block->size);
3352 printf(" written_offset %llu\n", block->written_offset);
3353 printf(" written_size %llu\n", block->written_size);
3354 printf(" next 0x%x\n", (unsigned long)(block->next));
3355 p = &(block->next);
3358 #endif /* DEBUG */
3361 * get_block() returns a pointer to a new block. This could be done by
3362 * allocating block of these placing them on a free list and and handing them
3363 * out. For the initial release of this code this number is typicly low and not
3364 * a big win so each block just allocated and free'ed.
3366 static
3367 struct block *
3368 get_block(void)
3370 struct block *block;
3372 block = allocate(sizeof(struct block));
3373 return(block);
3377 * remove_block() throws away the block specified. See comments in get_block().
3379 static
3380 void
3381 remove_block(
3382 struct block *block)
3384 free(block);
3388 * trnc() truncates the value 'v' to the power of two value 'r'. If v is
3389 * less than zero it returns zero.
3391 static
3392 uint32_t
3393 trnc(
3394 uint32_t v,
3395 uint32_t r)
3397 if(((int32_t)v) < 0)
3398 return(0);
3399 return(v & ~(r - 1));
3403 * create_dynamic_shared_library() creates a dynamic shared library from the
3404 * data structure pointed to by archs into the specified output file. Only
3405 * when more than one architecture is in archs will a fat file be created.
3407 static
3408 void
3409 create_dynamic_shared_library(
3410 char *output)
3412 uint32_t i, j;
3413 char *p, *filelist;
3414 struct stat stat_buf;
3415 enum bool use_force_cpusubtype_ALL;
3416 const struct arch_flag *family_arch_flag;
3419 * If there is more than one architecture setup a signal handler to
3420 * clean up the temporary files in case we get a signal.
3422 if(narchs > 1)
3423 signal(SIGINT, create_dynamic_shared_library_cleanup);
3426 * If -arch_only is specified with a specific cpusubtype other than the
3427 * family cpusubtype do not use -force_cpusubtype_ALL as the user wants
3428 * the output to be tagged with that cpusubtype.
3430 use_force_cpusubtype_ALL = TRUE;
3431 if(cmd_flags.arch_only_flag.name != NULL){
3432 family_arch_flag = get_arch_family_from_cputype(
3433 cmd_flags.arch_only_flag.cputype);
3434 if(family_arch_flag != NULL){
3435 if((family_arch_flag->cpusubtype & ~CPU_SUBTYPE_MASK) !=
3436 (cmd_flags.arch_only_flag.cpusubtype & ~CPU_SUBTYPE_MASK))
3437 use_force_cpusubtype_ALL = FALSE;
3442 * For each architecture run ld(1) -dylib to create the dynamic shared
3443 * library.
3445 for(i = 0; i < narchs || (i == 0 && narchs == 0); i++){
3446 reset_execute_list();
3447 add_execute_list_with_prefix("ld");
3448 if(narchs != 0 && cmd_flags.arch_only_flag.name == NULL)
3449 add_execute_list("-arch_multiple");
3450 if(archs != NULL){
3451 add_execute_list("-arch");
3452 if(use_force_cpusubtype_ALL == TRUE)
3453 add_execute_list(archs[i].arch_flag.name);
3454 else
3455 add_execute_list(cmd_flags.arch_only_flag.name);
3457 add_execute_list("-dylib");
3458 add_execute_list("-dynamic");
3459 if(cmd_flags.all_load_flag_specified == FALSE ||
3460 cmd_flags.all_load == TRUE)
3461 add_execute_list("-all_load");
3462 if(use_force_cpusubtype_ALL == TRUE)
3463 add_execute_list("-force_cpusubtype_ALL");
3464 add_execute_list("-no_arch_warnings");
3465 if(cmd_flags.seg1addr != NULL){
3466 add_execute_list("-seg1addr");
3467 add_execute_list(cmd_flags.seg1addr);
3469 if(cmd_flags.segs_read_only_addr != NULL){
3470 add_execute_list("-segs_read_only_addr");
3471 add_execute_list(cmd_flags.segs_read_only_addr);
3473 if(cmd_flags.segs_read_write_addr != NULL){
3474 add_execute_list("-segs_read_write_addr");
3475 add_execute_list(cmd_flags.segs_read_write_addr);
3477 if(cmd_flags.seg_addr_table != NULL){
3478 add_execute_list("-seg_addr_table");
3479 add_execute_list(cmd_flags.seg_addr_table);
3481 if(cmd_flags.seg_addr_table_filename != NULL){
3482 add_execute_list("-seg_addr_table_filename");
3483 add_execute_list(cmd_flags.seg_addr_table_filename);
3485 if(cmd_flags.compatibility != NULL){
3486 add_execute_list("-dylib_compatibility_version");
3487 add_execute_list(cmd_flags.compatibility);
3489 if(cmd_flags.current != NULL){
3490 add_execute_list("-dylib_current_version");
3491 add_execute_list(cmd_flags.current);
3493 if(cmd_flags.install_name != NULL){
3494 add_execute_list("-dylib_install_name");
3495 add_execute_list(cmd_flags.install_name);
3497 else{
3498 if(narchs > 1){
3499 add_execute_list("-dylib_install_name");
3500 add_execute_list(cmd_flags.output);
3503 for(j = 0; j < cmd_flags.nldflags; j++)
3504 add_execute_list(cmd_flags.ldflags[j]);
3505 for(j = 0; j < cmd_flags.nLdirs; j++)
3506 add_execute_list(cmd_flags.Ldirs[j]);
3508 // Support using libtool on a systems without the SDK in '/'. This
3509 // works because the shims that are included in 10.9 and forwards
3510 // automatically inject SDKROOT into the environment of the actual
3511 // tools. See <rdar://problem/14264125>.
3512 const char *sdkroot = getenv("SDKROOT");
3514 // If the SDKROOT environment variable is set and is an absolute
3515 // path, then see if we can find dylib1.o inside it and use that if
3516 // so.
3517 enum bool use_dashl_dylib1o = TRUE;
3518 if (sdkroot && sdkroot[0] == '/') {
3519 // Construct the path to the object file.
3520 char *sdk_dylib1o_path;
3521 int res = asprintf(&sdk_dylib1o_path, "%s/usr/lib/dylib1.o",
3522 sdkroot);
3523 if (res > 0 && sdk_dylib1o_path) {
3524 struct stat s;
3525 // Add the full path if it exists.
3526 if (stat(sdk_dylib1o_path, &s) == 0) {
3527 add_execute_list(sdk_dylib1o_path);
3528 use_dashl_dylib1o = FALSE;
3530 free(sdk_dylib1o_path);
3534 filelist = NULL;
3535 for(j = 0; j < cmd_flags.nfiles; j++){
3536 if(cmd_flags.filelist[j] == NULL){
3537 add_execute_list(cmd_flags.files[j]);
3539 else{
3540 if(cmd_flags.filelist[j] != filelist){
3541 add_execute_list("-filelist");
3542 add_execute_list(cmd_flags.filelist[j]);
3543 filelist = cmd_flags.filelist[j];
3547 if(narchs <= 1){
3548 add_execute_list("-o");
3549 add_execute_list(cmd_flags.output);
3551 else{
3552 add_execute_list("-o");
3553 add_execute_list(makestr(cmd_flags.output, ".libtool.",
3554 archs[i].arch_flag.name, NULL));
3555 if(cmd_flags.final_output_specified == FALSE){
3556 add_execute_list("-final_output");
3557 add_execute_list(cmd_flags.output);
3560 if(execute_list(cmd_flags.verbose) == 0)
3561 fatal("internal link edit command failed");
3564 * If there is more than one architecture then run lipo to put them
3565 * in a fat file.
3567 if(narchs > 1){
3568 reset_execute_list();
3569 add_execute_list_with_prefix("lipo");
3570 add_execute_list("-create");
3571 add_execute_list("-output");
3572 add_execute_list(cmd_flags.output);
3573 for(i = 0; i < narchs; i++){
3574 add_execute_list(makestr(cmd_flags.output, ".libtool.",
3575 archs[i].arch_flag.name, NULL));
3577 if(execute_list(cmd_flags.verbose) == 0)
3578 fatal("internal lipo command failed");
3579 for(i = 0; i < narchs; i++){
3580 p = makestr(cmd_flags.output, ".libtool.",
3581 archs[i].arch_flag.name, NULL);
3582 if(unlink(p) == -1){
3583 error("can't remove temporary file: %s", p);
3588 * If we are doing prebinding then run objcunique on the
3589 * output.
3591 if(cmd_flags.prebinding == TRUE){
3592 if(stat("/usr/bin/objcunique", &stat_buf) != -1){
3593 reset_execute_list();
3594 add_execute_list_with_prefix("objcunique");
3595 add_execute_list(cmd_flags.output);
3596 add_execute_list("-prebind");
3597 for(j = 0; j < cmd_flags.nLdirs; j++)
3598 add_execute_list(cmd_flags.Ldirs[j]);
3599 if(execute_list(cmd_flags.verbose) == 0)
3600 fatal("internal objcunique command failed");
3606 * create_dynamic_shared_library_cleanup() is the signal handler to remove the
3607 * temporary files if more than one arch is being used.
3609 static
3610 void
3611 create_dynamic_shared_library_cleanup(
3612 int sig)
3614 uint32_t i;
3616 for(i = 0; i < narchs; i++){
3617 (void)unlink(makestr(cmd_flags.output, ".libtool.",
3618 archs[i].arch_flag.name, NULL));
3620 exit(EXIT_FAILURE);
3624 * make_table_of_contents() make the table of contents for the specified arch
3625 * and fills in the toc_* fields in the arch. Output is the name of the output
3626 * file for error messages.
3628 static
3629 void
3630 make_table_of_contents(
3631 struct arch *arch,
3632 char *output)
3634 uint32_t i, j, k, r, s, nsects, ncmds, n_strx;
3635 struct member *member;
3636 struct load_command *lc;
3637 struct segment_command *sg;
3638 struct segment_command_64 *sg64;
3639 struct nlist *symbols;
3640 struct nlist_64 *symbols64;
3641 char *strings;
3642 enum bool sorted, is_toc_symbol;
3643 char *ar_name;
3644 struct section *section;
3645 struct section_64 *section64;
3646 uint8_t n_type, n_sect;
3647 #ifdef LTO_SUPPORT
3648 char *lto_toc_string;
3649 #endif /* LTO_SUPPORT */
3651 symbols = NULL;
3652 symbols64 = NULL;
3654 * First pass over the members to count how many ranlib structs are
3655 * needed and the size of the strings in the toc that are needed.
3657 for(i = 0; i < arch->nmembers; i++){
3658 member = arch->members + i;
3659 if(member->mh != NULL || member->mh64 != NULL){
3660 nsects = 0;
3661 lc = member->load_commands;
3662 if(member->mh != NULL)
3663 ncmds = member->mh->ncmds;
3664 else
3665 ncmds = member->mh64->ncmds;
3666 for(j = 0; j < ncmds; j++){
3667 if(lc->cmd == LC_SYMTAB){
3668 if(member->st == NULL)
3669 member->st = (struct symtab_command *)lc;
3671 else if(lc->cmd == LC_SEGMENT){
3672 sg = (struct segment_command *)lc;
3673 nsects += sg->nsects;
3675 else if(lc->cmd == LC_SEGMENT_64){
3676 sg64 = (struct segment_command_64 *)lc;
3677 nsects += sg64->nsects;
3679 lc = (struct load_command *)((char *)lc + lc->cmdsize);
3681 if(member->mh != NULL)
3682 member->sections = allocate(nsects *
3683 sizeof(struct section *));
3684 else
3685 member->sections64 = allocate(nsects *
3686 sizeof(struct section_64 *));
3687 nsects = 0;
3688 lc = member->load_commands;
3689 for(j = 0; j < ncmds; j++){
3690 if(lc->cmd == LC_SEGMENT){
3691 sg = (struct segment_command *)lc;
3692 section = (struct section *)
3693 ((char *)sg + sizeof(struct segment_command));
3694 for(k = 0; k < sg->nsects; k++){
3695 member->sections[nsects++] = section++;
3698 else if(lc->cmd == LC_SEGMENT_64){
3699 sg64 = (struct segment_command_64 *)lc;
3700 section64 = (struct section_64 *)
3701 ((char *)sg64 + sizeof(struct segment_command_64));
3702 for(k = 0; k < sg64->nsects; k++){
3703 member->sections64[nsects++] = section64++;
3706 lc = (struct load_command *)((char *)lc + lc->cmdsize);
3708 if(member->st != NULL && member->st->nsyms != 0){
3709 if(member->mh != NULL){
3710 symbols = (struct nlist *)(member->object_addr +
3711 member->st->symoff);
3712 if(member->object_byte_sex != get_host_byte_sex())
3713 swap_nlist(symbols, member->st->nsyms,
3714 get_host_byte_sex());
3716 else{
3717 symbols64 = (struct nlist_64 *)(member->object_addr +
3718 member->st->symoff);
3719 if(member->object_byte_sex != get_host_byte_sex())
3720 swap_nlist_64(symbols64, member->st->nsyms,
3721 get_host_byte_sex());
3723 strings = member->object_addr + member->st->stroff;
3724 for(j = 0; j < member->st->nsyms; j++){
3725 if(member->mh != NULL){
3726 n_strx = symbols[j].n_un.n_strx;
3727 n_type = symbols[j].n_type;
3728 n_sect = symbols[j].n_sect;
3730 else{
3731 n_strx = symbols64[j].n_un.n_strx;
3732 n_type = symbols64[j].n_type;
3733 n_sect = symbols64[j].n_sect;
3735 if(n_strx > member->st->strsize){
3736 warn_member(arch, member, "malformed object "
3737 "(symbol %u n_strx field extends past the "
3738 "end of the string table)", j);
3739 errors++;
3740 continue;
3742 if((n_type & N_TYPE) == N_SECT){
3743 if(n_sect == NO_SECT){
3744 warn_member(arch, member, "malformed object "
3745 "(symbol %u must not have NO_SECT for its "
3746 "n_sect field given its type (N_SECT))", j);
3747 errors++;
3748 continue;
3750 if(n_sect > nsects){
3751 warn_member(arch, member, "malformed object "
3752 "(symbol %u n_sect field greater than the "
3753 "number of sections in the file)", j);
3754 errors++;
3755 continue;
3758 if(member->mh != NULL)
3759 is_toc_symbol = toc_symbol(symbols + j,
3760 member->sections);
3761 else
3762 is_toc_symbol = toc_symbol_64(symbols64 + j,
3763 member->sections64);
3764 if(is_toc_symbol == TRUE){
3765 arch->toc_nranlibs++;
3766 arch->toc_strsize += strlen(strings + n_strx) + 1;
3770 else{
3771 if(cmd_flags.no_warning_for_no_symbols == FALSE)
3772 warn_member(arch, member, "has no symbols");
3775 #ifdef LTO_SUPPORT
3776 else if(member->lto_contents == TRUE){
3777 arch->toc_nranlibs += member->lto_toc_nsyms;
3778 arch->toc_strsize += member->lto_toc_strsize;
3780 #endif /* LTO_SUPPORT */
3781 else{
3782 if(cmd_flags.ranlib == FALSE){
3783 warn_member(arch, member, "is not an object file");
3784 errors++;
3788 if(errors != 0)
3789 return;
3792 * Allocate the space for the ranlib structs and strings for the
3793 * table of contents.
3795 arch->toc_ranlibs = allocate(sizeof(struct ranlib) *arch->toc_nranlibs);
3796 arch->tocs = allocate(sizeof(struct toc) * arch->toc_nranlibs);
3797 arch->toc_strsize = rnd(arch->toc_strsize, 8);
3798 arch->toc_strings = allocate(arch->toc_strsize);
3799 if(arch->toc_strsize >= 8)
3800 memset(arch->toc_strings + arch->toc_strsize - 7, '\0', 7);
3803 * Second pass over the members to fill in the toc structs and
3804 * the strings for the table of contents. The toc name field is
3805 * filled in with a pointer to a string contained in arch->toc_strings
3806 * for easy sorting and conversion to an index. The toc index1 field is
3807 * filled in with the member index plus one to allow marking with it's
3808 * negative value by check_sort_tocs() and easy conversion to the
3809 * real offset.
3811 r = 0;
3812 s = 0;
3813 for(i = 0; i < arch->nmembers; i++){
3814 member = arch->members + i;
3815 if(member->mh != NULL || member->mh64 != NULL){
3816 if(member->st != NULL && member->st->nsyms != 0){
3817 if(member->mh != NULL)
3818 symbols = (struct nlist *)(member->object_addr +
3819 member->st->symoff);
3820 else
3821 symbols64 = (struct nlist_64 *)(member->object_addr +
3822 member->st->symoff);
3823 strings = member->object_addr + member->st->stroff;
3824 for(j = 0; j < member->st->nsyms; j++){
3825 if(member->mh != NULL)
3826 n_strx = symbols[j].n_un.n_strx;
3827 else
3828 n_strx = symbols64[j].n_un.n_strx;
3829 if(n_strx > member->st->strsize)
3830 continue;
3831 if(member->mh != NULL)
3832 is_toc_symbol = toc_symbol(symbols + j,
3833 member->sections);
3834 else
3835 is_toc_symbol = toc_symbol_64(symbols64 + j,
3836 member->sections64);
3837 if(is_toc_symbol == TRUE){
3838 strcpy(arch->toc_strings + s,
3839 strings + n_strx);
3840 arch->tocs[r].name = arch->toc_strings + s;
3841 arch->tocs[r].index1 = i + 1;
3842 r++;
3843 s += strlen(strings + n_strx) + 1;
3846 if(member->object_byte_sex != get_host_byte_sex()){
3847 if(member->mh != NULL)
3848 swap_nlist(symbols, member->st->nsyms,
3849 member->object_byte_sex);
3850 else
3851 swap_nlist_64(symbols64, member->st->nsyms,
3852 member->object_byte_sex);
3856 #ifdef LTO_SUPPORT
3857 else if(member->lto_contents == TRUE){
3858 lto_toc_string = member->lto_toc_strings;
3859 for(j = 0; j < member->lto_toc_nsyms; j++){
3860 strcpy(arch->toc_strings + s, lto_toc_string);
3861 arch->tocs[r].name = arch->toc_strings + s;
3862 arch->tocs[r].index1 = i + 1;
3863 r++;
3864 s += strlen(lto_toc_string) + 1;
3865 lto_toc_string += strlen(lto_toc_string) + 1;
3868 #endif /* LTO_SUPPORT */
3872 * If the table of contents is to be sorted by symbol name then try to
3873 * sort it and leave it sorted if no duplicates.
3875 if(cmd_flags.s == TRUE){
3876 qsort(arch->tocs, arch->toc_nranlibs, sizeof(struct toc),
3877 (int (*)(const void *, const void *))toc_name_qsort);
3878 sorted = check_sort_tocs(arch, output, FALSE);
3879 if(sorted == FALSE){
3880 qsort(arch->tocs, arch->toc_nranlibs, sizeof(struct toc),
3881 (int (*)(const void *, const void *))toc_index1_qsort);
3882 arch->toc_name = SYMDEF;
3883 arch->toc_name_size = sizeof(SYMDEF) - 1;
3884 if(cmd_flags.use_long_names == TRUE){
3885 arch->toc_long_name = TRUE;
3887 * This assumes that "__.SYMDEF\0\0\0\0\0\0\0" is 16 bytes
3888 * and
3889 * (rnd(sizeof(struct ar_hdr), 8) - sizeof(struct ar_hdr)
3890 * is 4 bytes.
3892 ar_name = AR_EFMT1 "20";
3893 arch->toc_name_size = 16;
3894 arch->toc_name = SYMDEF "\0\0\0\0\0\0\0";
3896 else{
3897 arch->toc_long_name = FALSE;
3898 ar_name = arch->toc_name;
3901 else{
3903 * Since the SYMDEF_SORTED is "__.SYMDEF SORTED" which contains
3904 * a space, it should use extended format #1 if we can use long
3905 * names.
3907 arch->toc_name = SYMDEF_SORTED;
3908 arch->toc_name_size = sizeof(SYMDEF_SORTED) - 1;
3909 if(cmd_flags.use_long_names == TRUE){
3910 arch->toc_long_name = TRUE;
3912 * This assumes that "__.SYMDEF SORTED" is 16 bytes and
3913 * (rnd(sizeof(struct ar_hdr), 8) - sizeof(struct ar_hdr)
3914 * is 4 bytes.
3916 ar_name = AR_EFMT1 "20";
3918 else{
3919 arch->toc_long_name = FALSE;
3920 ar_name = arch->toc_name;
3924 else{
3925 sorted = FALSE;
3926 arch->toc_name = SYMDEF;
3927 arch->toc_name_size = sizeof(SYMDEF) - 1;
3928 if(cmd_flags.use_long_names == TRUE){
3929 arch->toc_long_name = TRUE;
3931 * This assumes that "__.SYMDEF\0\0\0\0\0\0\0" is 16 bytes and
3932 * (rnd(sizeof(struct ar_hdr), 8) - sizeof(struct ar_hdr)
3933 * is 4 bytes.
3935 ar_name = AR_EFMT1 "20";
3936 arch->toc_name_size = 16;
3937 arch->toc_name = SYMDEF "\0\0\0\0\0\0\0";
3939 else{
3940 arch->toc_long_name = FALSE;
3941 ar_name = arch->toc_name;
3946 * Now set the ran_off and ran_un.ran_strx fields of the ranlib structs.
3947 * To do this the size of the toc member must be know because it comes
3948 * first in the library. The size of the toc member is made up of the
3949 * sizeof an archive header struct (the size of the name if a long name
3950 * is used) then the toc which is (as defined in ranlib.h):
3951 * a uint32_t for the number of bytes of the ranlib structs
3952 * the ranlib structures
3953 * a uint32_t for the number of bytes of the strings
3954 * the strings
3956 arch->toc_size = sizeof(struct ar_hdr) +
3957 sizeof(uint32_t) +
3958 arch->toc_nranlibs * sizeof(struct ranlib) +
3959 sizeof(uint32_t) +
3960 arch->toc_strsize;
3961 /* add the size of the name is a long name is used */
3962 if(arch->toc_long_name == TRUE)
3963 arch->toc_size += arch->toc_name_size +
3964 (rnd(sizeof(struct ar_hdr), 8) -
3965 sizeof(struct ar_hdr));
3968 * Now with the size of the 32-bit toc known we can now see if it will
3969 * work or if we have offsets to members that are more than 32-bits and
3970 * we need to switch to the 64-bit toc, or switch to that if we are
3971 * forcing a 64-bit toc via the command line option.
3973 if(cmd_flags.toc64 == TRUE)
3974 arch->using_64toc = TRUE;
3975 else{
3976 arch->using_64toc = FALSE;
3977 for(i = 0; i < arch->nmembers; i++){
3978 if(arch->members[i].offset + SARMAG + arch->toc_size >
3979 UINT32_MAX){
3980 arch->using_64toc = TRUE;
3981 break;
3985 if(arch->using_64toc){
3986 if(cmd_flags.use_long_names == FALSE &&
3987 cmd_flags.L_or_T_specified == TRUE)
3988 fatal("archive requires a 64-bit toc that must be aligned so "
3989 "-T can't be specified");
3990 arch->toc_long_name = TRUE;
3991 if(sorted == FALSE){
3993 * This assumes that "__.SYMDEF_64\0\0\0\0" is 16 bytes
3994 * and
3995 * (rnd(sizeof(struct ar_hdr), 8) - sizeof(struct ar_hdr)
3996 * is 4 bytes.
3998 ar_name = AR_EFMT1 "20";
3999 arch->toc_name_size = 16;
4000 arch->toc_name = SYMDEF_64 "\0\0\0\0";
4002 else{
4003 arch->toc_name = SYMDEF_64_SORTED;
4004 arch->toc_name_size = sizeof(SYMDEF_64_SORTED) - 1;
4006 * This assumes that "__.SYMDEF_64 SORTED\0\0\0\0\0" is 24 bytes
4007 * and
4008 * (rnd(sizeof(struct ar_hdr), 8) - sizeof(struct ar_hdr)
4009 * is 4 bytes.
4011 ar_name = AR_EFMT1 "28";
4012 arch->toc_name_size = 24;
4013 arch->toc_name = SYMDEF_64_SORTED "\0\0\0\0\0";
4016 * Free the space for the 32-bit ranlib structs and allocate space
4017 * for the 64-bit ranlib structs.
4019 free(arch->toc_ranlibs);
4020 arch->toc_ranlibs = NULL;
4021 arch->toc_ranlibs64 = allocate(sizeof(struct ranlib_64) *
4022 arch->toc_nranlibs);
4024 * Now the size of the toc member when it is a 64-bit toc can be
4025 * set. It is made up of the sizeof an archive header struct (the
4026 * size of the name which is always a long name to get 8-byte
4027 * alignment then the toc which is (as defined in ranlib.h):
4028 * a uint64_t for the number of bytes of the ranlib_64 structs
4029 * the ranlib_64 structures
4030 * a uint64_t for the number of bytes of the strings
4031 * the strings
4033 arch->toc_size = sizeof(struct ar_hdr) +
4034 sizeof(uint64_t) +
4035 arch->toc_nranlibs * sizeof(struct ranlib_64) +
4036 sizeof(uint64_t) +
4037 arch->toc_strsize;
4038 /* add the size of the name as a long name is always used */
4039 arch->toc_size += arch->toc_name_size +
4040 (rnd(sizeof(struct ar_hdr), 8) -
4041 sizeof(struct ar_hdr));
4044 for(i = 0; i < arch->nmembers; i++)
4045 arch->members[i].offset += SARMAG + arch->toc_size;
4047 for(i = 0; i < arch->toc_nranlibs; i++){
4048 if(arch->using_64toc){
4049 arch->toc_ranlibs64[i].ran_un.ran_strx =
4050 arch->tocs[i].name - arch->toc_strings;
4051 arch->toc_ranlibs64[i].ran_off =
4052 arch->members[arch->tocs[i].index1 - 1].offset;
4054 else{
4055 arch->toc_ranlibs[i].ran_un.ran_strx =
4056 arch->tocs[i].name - arch->toc_strings;
4057 arch->toc_ranlibs[i].ran_off =
4058 arch->members[arch->tocs[i].index1 - 1].offset;
4062 sprintf((char *)(&arch->toc_ar_hdr), "%-*s%-*ld%-*u%-*u%-*o%-*ld",
4063 (int)sizeof(arch->toc_ar_hdr.ar_name),
4064 ar_name,
4065 (int)sizeof(arch->toc_ar_hdr.ar_date),
4066 toc_time,
4067 (int)sizeof(arch->toc_ar_hdr.ar_uid),
4068 (unsigned short)getuid(),
4069 (int)sizeof(arch->toc_ar_hdr.ar_gid),
4070 (unsigned short)getgid(),
4071 (int)sizeof(arch->toc_ar_hdr.ar_mode),
4072 (unsigned int)toc_mode,
4073 (int)sizeof(arch->toc_ar_hdr.ar_size),
4074 (long)(arch->toc_size - sizeof(struct ar_hdr)));
4076 * This has to be done by hand because sprintf puts a null
4077 * at the end of the buffer.
4079 memcpy(arch->toc_ar_hdr.ar_fmag, ARFMAG,
4080 (int)sizeof(arch->toc_ar_hdr.ar_fmag));
4083 #ifdef LTO_SUPPORT
4085 * save_lto_member_toc_info() saves away the table of contents info for a
4086 * member that has lto_content. This allows the lto module to be disposed of
4087 * after reading to keep only on in memory at a time. As these turn out to
4088 * use a lot of memory.
4090 static
4091 void
4092 save_lto_member_toc_info(
4093 struct member *member,
4094 void *mod)
4096 uint32_t i, nsyms;
4097 char *s;
4099 member->lto_toc_nsyms = 0;
4100 nsyms = lto_get_nsyms(mod);
4101 for(i = 0; i < nsyms; i++){
4102 if(lto_toc_symbol(mod, i, cmd_flags.c) == TRUE){
4103 member->lto_toc_nsyms++;
4104 member->lto_toc_strsize += strlen(lto_symbol_name(mod, i)) + 1;
4107 member->lto_toc_strings = allocate(member->lto_toc_strsize);
4108 s = member->lto_toc_strings;
4109 for(i = 0; i < nsyms; i++){
4110 if(lto_toc_symbol(mod, i, cmd_flags.c) == TRUE){
4111 strcpy(s, lto_symbol_name(mod, i));
4112 s += strlen(lto_symbol_name(mod, i)) + 1;
4116 #endif /* LTO_SUPPORT */
4119 * Function for qsort() for comparing toc structures by name.
4121 static
4123 toc_name_qsort(
4124 const struct toc *toc1,
4125 const struct toc *toc2)
4127 return(strcmp(toc1->name, toc2->name));
4131 * Function for qsort() for comparing toc structures by index1.
4133 static
4135 toc_index1_qsort(
4136 const struct toc *toc1,
4137 const struct toc *toc2)
4139 if(toc1->index1 < toc2->index1)
4140 return(-1);
4141 if(toc1->index1 > toc2->index1)
4142 return(1);
4143 /* toc1->index1 == toc2->index1 */
4144 return(0);
4148 * toc_symbol() returns TRUE if the symbol is to be included in the table of
4149 * contents otherwise it returns FALSE.
4151 static
4152 enum bool
4153 toc_symbol(
4154 struct nlist *symbol,
4155 struct section **sections)
4157 return(toc(symbol->n_un.n_strx,
4158 symbol->n_type,
4159 symbol->n_value,
4160 (symbol->n_type & N_TYPE) == N_SECT &&
4161 sections[symbol->n_sect - 1]->flags & S_ATTR_NO_TOC));
4164 static
4165 enum bool
4166 toc_symbol_64(
4167 struct nlist_64 *symbol64,
4168 struct section_64 **sections64)
4170 return(toc(symbol64->n_un.n_strx,
4171 symbol64->n_type,
4172 symbol64->n_value,
4173 (symbol64->n_type & N_TYPE) == N_SECT &&
4174 sections64[symbol64->n_sect-1]->flags & S_ATTR_NO_TOC));
4177 static
4178 enum bool
4179 toc(
4180 uint32_t n_strx,
4181 uint8_t n_type,
4182 uint64_t n_value,
4183 enum bool attr_no_toc)
4185 /* if the name is NULL then it won't be in the table of contents */
4186 if(n_strx == 0)
4187 return(FALSE);
4188 /* if symbol is not external then it won't be in the toc */
4189 if((n_type & N_EXT) == 0)
4190 return(FALSE);
4191 /* if symbol is undefined then it won't be in the toc */
4192 if((n_type & N_TYPE) == N_UNDF && n_value == 0)
4193 return(FALSE);
4194 /* if symbol is common and the -c flag is not specified then ... */
4195 if((n_type & N_TYPE) == N_UNDF && n_value != 0 &&
4196 cmd_flags.c == FALSE)
4197 return(FALSE);
4198 /* if the symbols is in a section marked NO_TOC then ... */
4199 if(attr_no_toc != 0)
4200 return(FALSE);
4202 return(TRUE);
4206 * check_sort_tocs() checks the table of contents for the specified arch
4207 * which is sorted by name for more then one object defining the same symbol.
4208 * It this is the case it prints each symbol that is defined in more than one
4209 * object along with the object it is defined in. It returns TRUE if there are
4210 * no multiple definitions and FALSE otherwise.
4212 static
4213 enum bool
4214 check_sort_tocs(
4215 struct arch *arch,
4216 char *output,
4217 enum bool library_warnings)
4219 uint32_t i;
4220 enum bool multiple_defs;
4221 struct member *member;
4223 if(arch->toc_nranlibs == 0)
4224 return(TRUE);
4226 * Since the symbol table is sorted by name look to any two adjcent
4227 * entries with the same name. If such entries are found print them
4228 * only once (marked by changing the sign of their ran_off).
4230 multiple_defs = FALSE;
4231 for(i = 0; i < arch->toc_nranlibs - 1; i++){
4232 if(strcmp(arch->tocs[i].name, arch->tocs[i+1].name) == 0){
4233 if(multiple_defs == FALSE){
4234 if(library_warnings == FALSE)
4235 return(FALSE);
4236 fprintf(stderr, "%s: same symbol defined in more than one "
4237 "member ", pnam);
4238 if(narchs > 1)
4239 fprintf(stderr, "for architecture: %s ",
4240 arch->arch_flag.name);
4241 fprintf(stderr, "in: %s (table of contents will not be "
4242 "sorted)\n", output);
4243 multiple_defs = TRUE;
4245 if((int)(arch->tocs[i].index1) > 0){
4246 member = arch->members + arch->tocs[i].index1 - 1;
4247 warn_member(arch, member, "defines symbol: %s",
4248 arch->tocs[i].name);
4249 arch->tocs[i].index1 =
4250 -(arch->tocs[i].index1);
4252 if((int)(arch->tocs[i+1].index1) > 0){
4253 member = arch->members + arch->tocs[i+1].index1 - 1;
4254 warn_member(arch, member, "defines symbol: %s",
4255 arch->tocs[i+1].name);
4256 arch->tocs[i+1].index1 =
4257 -(arch->tocs[i+1].index1);
4262 if(multiple_defs == FALSE)
4263 return(TRUE);
4264 else{
4265 for(i = 0; i < arch->toc_nranlibs; i++)
4266 if(((int)arch->tocs[i].index1) < 0)
4267 arch->tocs[i].index1 =
4268 -(arch->tocs[i].index1);
4269 return(FALSE);
4274 * warn_duplicate_member_names() generates a warning if two members end up with
4275 * the same ar_name. This is only a warning because ld(1) and this program
4276 * has no problems with it. Only if ar(1) were used to extract the files
4277 * would this be a problem (even the 4.4bsd ar(1) using long names can
4278 * get hosed by base names, the 4.3bsd ar(1) can't handle full 16 character
4279 * ar_names).
4281 static
4282 void
4283 warn_duplicate_member_names(
4284 void)
4286 uint32_t i, j, len, len1, len2;
4288 for(i = 0; i < narchs; i++){
4289 /* sort in order of ar_names */
4290 qsort(archs[i].members, archs[i].nmembers, sizeof(struct member),
4291 (int (*)(const void *, const void *))member_name_qsort);
4293 /* check for duplicate names */
4294 for(j = 0; j < archs[i].nmembers - 1; j++){
4295 len1 = archs[i].members[j].member_name_size;
4296 len2 = archs[i].members[j+1].member_name_size;
4297 len = len1 > len2 ? len1 : len2;
4298 if(strncmp(archs[i].members[j].member_name,
4299 archs[i].members[j+1].member_name,
4300 len) == 0){
4301 fprintf(stderr, "%s: warning ", pnam);
4302 if(narchs > 1)
4303 fprintf(stderr, "for architecture: %s ",
4304 archs[i].arch_flag.name);
4305 fprintf(stderr, "same member name (%.*s) in output file "
4306 "used for input files: ", (int)len1,
4307 archs[i].members[j].member_name);
4309 if(archs[i].members[j].input_ar_hdr != NULL){
4310 len = archs[i].members[j].input_base_name_size;
4311 fprintf(stderr, "%s(%.*s) and: ",
4312 archs[i].members[j].input_file_name, (int)len,
4313 archs[i].members[j].input_base_name);
4315 else
4316 fprintf(stderr, "%s and: ",
4317 archs[i].members[j].input_file_name);
4319 if(archs[i].members[j+1].input_ar_hdr != NULL){
4320 len = archs[i].members[j+1].input_base_name_size;
4321 fprintf(stderr, "%s(%.*s) due to use of basename, "
4322 "truncation and blank padding\n",
4323 archs[i].members[j+1].input_file_name, (int)len,
4324 archs[i].members[j+1].input_base_name);
4326 else
4327 fprintf(stderr, "%s (due to use of basename, truncation"
4328 ", blank padding or duplicate input files)\n",
4329 archs[i].members[j+1].input_file_name);
4333 /* sort back in order of offset */
4334 qsort(archs[i].members, archs[i].nmembers, sizeof(struct member),
4335 (int (*)(const void *, const void *))member_offset_qsort);
4340 * Function for qsort() for comparing member structures by ar_hdr.ar_name.
4342 static
4344 member_name_qsort(
4345 const struct member *member1,
4346 const struct member *member2)
4348 uint32_t len, len1, len2;
4350 len1 = member1->member_name_size;
4351 len2 = member2->member_name_size;
4352 len = len1 > len2 ? len1 : len2;
4353 return(strncmp(member1->member_name, member2->member_name, len));
4357 * Function for qsort() for comparing member structures by offset.
4359 static
4361 member_offset_qsort(
4362 const struct member *member1,
4363 const struct member *member2)
4365 if(member1->offset < member2->offset)
4366 return(-1);
4367 if(member1->offset > member2->offset)
4368 return(1);
4369 /* member1->offset == member2->offset */
4370 return(0);
4374 * warn_member() is like the error routines it prints the program name the
4375 * member name specified and message specified.
4377 static
4378 void
4379 warn_member(
4380 struct arch *arch,
4381 struct member *member,
4382 const char *format, ...)
4384 va_list ap;
4386 fprintf(stderr, "%s: ", pnam);
4387 if(narchs > 1)
4388 fprintf(stderr, "for architecture: %s ", arch->arch_flag.name);
4390 if(member->input_ar_hdr != NULL){
4391 fprintf(stderr, "file: %s(%.*s) ", member->input_file_name,
4392 (int)member->input_base_name_size, member->input_base_name);
4394 else
4395 fprintf(stderr, "file: %s ", member->input_file_name);
4397 va_start(ap, format);
4398 vfprintf(stderr, format, ap);
4399 fprintf(stderr, "\n");
4400 va_end(ap);
4404 * Prints the message to cmd_flags.trace_file_path, or stderr if that
4405 * isn't set.
4407 static
4408 void
4409 ld_trace(
4410 const char *format, ...)
4412 static int trace_file = -1;
4413 char trace_buffer[MAXPATHLEN * 2];
4414 char *buffer_ptr;
4415 int length;
4416 ssize_t amount_written;
4418 if(trace_file == -1){
4419 if(cmd_flags.trace_file_path != NULL){
4420 trace_file = open(cmd_flags.trace_file_path, O_WRONLY | O_APPEND | O_CREAT, 0666);
4421 if(trace_file == -1)
4422 error("Could not open or create trace file: %s\n", cmd_flags.trace_file_path);
4424 else{
4425 trace_file = fileno(stderr);
4428 va_list ap;
4430 va_start(ap, format);
4431 length = vsnprintf(trace_buffer, sizeof(trace_buffer), format, ap);
4432 va_end(ap);
4433 buffer_ptr = trace_buffer;
4434 while(length > 0){
4435 amount_written = write(trace_file, buffer_ptr, length);
4436 if(amount_written == -1)
4437 /* Failure to write shouldn't fail the build. */
4438 return;
4439 buffer_ptr += amount_written;
4440 length -= amount_written;