886
[darwin-xtools.git] / cctools / misc / libtool.c
blob9a0a61503f6e1f09aa1b9e0eb088acf260b3ff59
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 #include <servers/bootstrap.h>
60 #endif
63 * This is used internally to build the table of contents.
65 struct toc {
66 char *name; /* symbol defined by */
67 int32_t index1; /* library member at this index plus 1 */
70 /* used by error routines as the name of the program */
71 char *progname = NULL;
73 /* the bytesex of the host this program is running on */
74 static enum byte_sex host_byte_sex = UNKNOWN_BYTE_SEX;
77 * The time the table of contents' are set to and the time to base the
78 * modification time of the output file to be set to.
80 static time_t toc_time = 0;
83 * The environment variable ZERO_AR_DATE is used here and other places that
84 * write archives to allow testing and comparing things for exact binary
85 * equality.
87 static enum bool zero_ar_date = FALSE;
90 * The mode of the table of contents member (S_IFREG | (0666 & ~umask))
92 static u_short toc_mode = 0;
94 /* flags set from the command line arguments */
95 struct cmd_flags {
96 char **files; /* array of file name arguments */
97 uint32_t
98 nfiles; /* number of file name arguments */
99 char **filelist; /* filelist argument the file name argument came from */
100 enum bool
101 no_files_ok; /* ok to see no files */
102 enum bool ranlib; /* set if this is run as ranlib not libtool */
103 enum bool s; /* sort the table of contents */
104 enum bool a; /* don't sort the table of contents (original form) */
105 enum bool c; /* include commmon symbols in the table of contents */
106 enum bool t; /* just "touch" the archives to get the date right */
107 enum bool f; /* warn if the output archive is fat,used by ar(1) -s */
108 enum bool q; /* only write archive if NOT fat, used by ar(1) */
109 char *output; /* the output file specified by -o */
110 enum bool final_output_specified; /* if -final_output is specified */
111 enum bool dynamic; /* create a dynamic shared library, static by default */
112 char *compatibility;/* compatibility version if specified, NULL otherwise */
113 char *current; /* current version if specified, NULL otherwise */
114 char *install_name; /* install name if specified, NULL otherwise */
115 char *seg1addr; /* seg1addr if specified, NULL otherwise */
116 char *segs_read_only_addr; /* segs_read_only_addr if specified, or NULL */
117 char *segs_read_write_addr; /* segs_read_write_addr if specified, or NULL */
118 char *seg_addr_table; /* seg_addr_table if specified, or NULL */
119 char *seg_addr_table_filename;
120 /* seg_addr_table_filename if specified, or NULL */
121 char **Ldirs; /* array of -Ldir arguments */
122 uint32_t
123 nLdirs; /* number of -Ldir arguments */
124 char **ldflags; /* other ld(1) flags to pass */
125 uint32_t
126 nldflags; /* number of ld(1) flags for above */
127 enum bool verbose; /* print exec(2) commands run */
128 struct arch_flag
129 arch_only_flag; /* the -arch_only flag if specified */
130 enum bool /* set if either -prebind or -noprebind is seen */
131 prebinding_flag_specified;
132 enum bool /* set if -prebind is seen or the LD_PREBIND */
133 prebinding; /* environment variable is set (and -noprebind isn't)*/
134 enum bool /* set if either -all_load or -noall_load is seen */
135 all_load_flag_specified;
136 enum bool /* set if -all_load is seen (and -noall_load isn't) */
137 all_load;
138 enum bool /* set with -L (the default) off with -T, for -static */
139 use_long_names; /* use 4.4bsd extended format 1 for long names */
140 enum bool L_or_T_specified;
141 enum bool /* set if the environ var LD_TRACE_ARCHIVES is set */
142 ld_trace_archives;
143 const char * /* LD_TRACE_FILE if set and LD_TRACE_ARCHIVES is set, or NULL */
144 trace_file_path;
145 enum bool /* set if -search_paths_first is specified */
146 search_paths_first;
147 enum bool noflush; /* don't use the output_flush routine to flush the
148 static library output file by pages */
149 uint32_t debug; /* debug value to debug output_flush() routine */
150 enum bool /* don't warn if members have no symbols */
151 no_warning_for_no_symbols;
153 static struct cmd_flags cmd_flags = { 0 };
155 /* The value of the environment variable NEXT_ROOT */
156 static char *next_root = NULL;
158 /* the standard directories to search for -lx names */
159 char *standard_dirs[] = {
160 "/lib/",
161 "/usr/lib/",
162 "/usr/local/lib/",
163 NULL
167 * The input files are broken down in to their object files and then placed in
168 * these structures. They are sorted by architecture type and then each object
169 * has a member struct created for it in one of the arch structs. All of these
170 * structs hang off of 'archs'.
172 static struct arch *archs = NULL;
173 static uint32_t narchs = 0;
175 struct arch {
176 struct arch_flag arch_flag; /* the identifing info of this architecture */
177 uint64_t size; /* current working size and final size */
179 /* the table of contents (toc) stuff for this architecture in the library */
180 uint32_t toc_size; /* total size of the toc including ar_hdr */
181 struct ar_hdr toc_ar_hdr; /* the archive header for this member */
182 enum bool toc_long_name; /* use the long name in the output */
183 char *toc_name; /* name of toc member */
184 uint32_t toc_name_size;/* size of name of toc member */
185 struct toc *tocs; /* internal table of contents */
186 struct ranlib *toc_ranlibs; /* ranlib structs for output */
187 uint32_t toc_nranlibs;/* number of ranlib structs */
188 char *toc_strings; /* strings of symbol names for ranlib structs */
189 uint32_t toc_strsize; /* number of bytes for the strings above */
191 /* the members of this architecture in the library */
192 struct member *members; /* the members of the library for this arch */
193 uint32_t nmembers; /* the number of the above members */
196 struct member {
197 uint64_t offset; /* current working offset and final offset*/
198 struct ar_hdr ar_hdr; /* the archive header for this member */
199 char null_byte; /* space to write '\0' for ar_hdr */
200 char *object_addr; /* the address of the object file */
201 uint32_t object_size; /* the size of the object file */
202 enum byte_sex object_byte_sex; /* the byte sex of the object file */
203 struct mach_header *mh; /* the mach_header of 32-bit object files */
204 struct mach_header_64 *mh64; /* the mach_header of 64-bit object files */
205 struct load_command /* the start of the load commands */
206 *load_commands;
207 struct symtab_command *st; /* the symbol table command */
208 struct section **sections; /* array of section structs for 32-bit */
209 struct section_64 **sections64; /* array of section structs for 64-bit */
210 #ifdef LTO_SUPPORT
211 enum bool lto_contents; /* TRUE if this member has lto contents */
212 uint32_t lto_toc_nsyms; /* number of symbols for the toc */
213 uint32_t lto_toc_strsize; /* the size of the strings for the toc */
214 char *lto_toc_strings; /* the strings of the symbols for the toc */
215 #endif /* LTO_SUPPORT */
217 /* the name of the member in the output */
218 char *member_name; /* the member name */
219 uint32_t member_name_size; /* the size of the member name */
220 enum bool output_long_name; /* use the extended format #1 for the
221 member name in the output */
223 /* info recorded from the input file this member came from */
224 char *input_file_name; /* the input file name */
225 char *input_base_name; /* the base name in the input file */
226 uint32_t input_base_name_size; /* the size of the base name */
227 struct ar_hdr *input_ar_hdr;
228 uint64_t input_member_offset; /* if from a thin archive */
231 static void usage(
232 void);
233 static void process(
234 void);
235 static char *file_name_from_l_flag(
236 char *l_flag);
237 static char *search_for_file(
238 char *base_name);
239 static char * search_paths_for_lname(
240 const char *lname_argument);
241 static char * search_path_for_lname(
242 const char *dir,
243 const char *lname_argument);
244 static void add_member(
245 struct ofile *ofile);
246 static void free_archs(
247 void);
248 static void create_library(
249 char *output,
250 struct ofile *ofile);
251 static enum byte_sex get_target_byte_sex(
252 struct arch *arch,
253 enum byte_sex host_byte_sex);
254 static char *put_toc_member(
255 char *p,
256 struct arch *arch,
257 enum byte_sex host_byte_sex,
258 enum byte_sex target_byte_sex);
259 static void create_dynamic_shared_library(
260 char *output);
261 static void create_dynamic_shared_library_cleanup(
262 int sig);
263 static void make_table_of_contents(
264 struct arch *arch,
265 char *output);
266 #ifdef LTO_SUPPORT
267 static void save_lto_member_toc_info(
268 struct member *member,
269 void *mod);
270 #endif /* LTO_SUPPORT */
271 static int toc_name_qsort(
272 const struct toc *toc1,
273 const struct toc *toc2);
274 static int toc_index1_qsort(
275 const struct toc *toc1,
276 const struct toc *toc2);
277 static enum bool toc_symbol(
278 struct nlist *symbol,
279 struct section **sections);
280 static enum bool toc_symbol_64(
281 struct nlist_64 *symbol64,
282 struct section_64 **sections64);
283 static enum bool toc(
284 uint32_t n_strx,
285 uint8_t n_type,
286 uint64_t n_value,
287 enum bool attr_no_toc);
288 static enum bool check_sort_tocs(
289 struct arch *arch,
290 char *output,
291 enum bool library_warnings);
292 static void warn_duplicate_member_names(
293 void);
294 static int member_name_qsort(
295 const struct member *member1,
296 const struct member *member2);
297 static int member_offset_qsort(
298 const struct member *member1,
299 const struct member *member2);
300 static void warn_member(
301 struct arch *arch,
302 struct member *member,
303 const char *format, ...) __attribute__ ((format (printf, 3, 4)));
304 static void ld_trace(
305 const char *format, ...) __attribute__ ((format (printf, 1, 2)));
308 * This structure is used to describe blocks of the output file that are flushed
309 * to the disk file with output_flush. It is kept in an ordered list starting
310 * with output_blocks.
312 static struct block {
313 uint64_t offset; /* starting offset of this block */
314 uint64_t size; /* size of this block */
315 uint64_t written_offset;/* first page offset after starting offset */
316 uint64_t written_size; /* size of written area from written_offset */
317 struct block *next; /* next block in the list */
318 } *output_blocks;
320 static void output_flush(
321 char *library,
322 uint64_t library_size,
323 int fd,
324 uint64_t offset,
325 uint64_t size);
326 static void final_output_flush(
327 char *library,
328 int fd);
329 #ifdef DEBUG
330 static void print_block_list(void);
331 #endif /* DEBUG */
332 static struct block *get_block(void);
333 static void remove_block(
334 struct block *block);
335 static uint32_t trnc(
336 uint32_t v,
337 uint32_t r);
339 /* apple_version is in vers.c which is created by the libstuff/Makefile */
340 extern char apple_version[];
343 main(
344 int argc,
345 char **argv,
346 char **envp)
348 char *p, *endp, *filelist, *dirname, *addr;
349 int fd, i;
350 struct stat stat_buf;
351 uint32_t j, nfiles, maxfiles;
352 uint32_t temp;
353 int oumask, numask;
354 enum bool lflags_seen, bad_flag_seen, Vflag;
356 lflags_seen = FALSE;
357 Vflag = FALSE;
358 progname = argv[0];
360 host_byte_sex = get_host_byte_sex();
363 * The environment variable ZERO_AR_DATE is used here and other
364 * places that write archives to allow testing and comparing
365 * things for exact binary equality.
367 if(getenv("ZERO_AR_DATE") == NULL)
368 zero_ar_date = FALSE;
369 else
370 zero_ar_date = TRUE;
371 if(zero_ar_date == FALSE)
372 toc_time = time(0);
373 else
374 toc_time = 0;
376 numask = 0;
377 oumask = umask(numask);
378 toc_mode = S_IFREG | (0666 & ~oumask);
379 (void)umask(oumask);
381 /* see if this is being run as ranlib */
382 p = strrchr(argv[0], '/');
383 if(p != NULL)
384 p++;
385 else
386 p = argv[0];
387 if(strncmp(p, "ranlib", sizeof("ranlib") - 1) == 0)
388 cmd_flags.ranlib = TRUE;
390 /* The default is to used long names */
391 cmd_flags.use_long_names = TRUE;
393 /* process the command line arguments and collect the files */
394 maxfiles = argc;
395 cmd_flags.files = allocate(sizeof(char *) * maxfiles);
396 cmd_flags.filelist = allocate(sizeof(char *) * maxfiles);
397 memset(cmd_flags.filelist, '\0', sizeof(char *) * maxfiles);
398 for(i = 1; i < argc; i++){
399 if(argv[i][0] == '-'){
400 if(argv[i][1] == '\0'){
401 for(i += 1 ; i < argc; i++)
402 cmd_flags.files[cmd_flags.nfiles++] = argv[i];
403 break;
405 if(strcmp(argv[i], "-o") == 0){
406 if(cmd_flags.ranlib == TRUE){
407 error("unknown option: %s", argv[i]);
408 usage();
410 if(i + 1 == argc){
411 error("missing argument to: %s option", argv[i]);
412 usage();
414 if(cmd_flags.output != NULL){
415 error("more than one: %s option specified", argv[i]);
416 usage();
418 cmd_flags.output = argv[i+1];
419 i++;
421 else if(strcmp(argv[i], "-arch_only") == 0){
422 if(cmd_flags.ranlib == TRUE){
423 error("unknown option: %s", argv[i]);
424 usage();
426 if(i + 1 == argc){
427 error("missing argument to %s option", argv[i]);
428 usage();
430 if(cmd_flags.arch_only_flag.name != NULL){
431 error("more than one: %s option specified", argv[i]);
432 usage();
434 else{
435 if(get_arch_from_flag(argv[i+1],
436 &cmd_flags.arch_only_flag) == 0){
437 error("unknown architecture specification flag: "
438 "%s %s", argv[i], argv[i+1]);
439 arch_usage();
440 usage();
443 i++;
445 else if(strcmp(argv[i], "-dynamic") == 0){
446 if(cmd_flags.ranlib == TRUE){
447 error("unknown option: %s", argv[i]);
448 usage();
450 cmd_flags.dynamic = TRUE;
452 else if(strcmp(argv[i], "-static") == 0){
453 if(cmd_flags.ranlib == TRUE){
454 error("unknown option: %s", argv[i]);
455 usage();
457 cmd_flags.dynamic = FALSE;
459 else if(strcmp(argv[i], "-filelist") == 0){
460 if(cmd_flags.ranlib == TRUE){
461 error("unknown option: %s", argv[i]);
462 usage();
464 if(i + 1 == argc){
465 error("missing argument to: %s option", argv[i]);
466 usage();
468 filelist = argv[i + 1];
469 dirname = strrchr(filelist, ',');
470 if(dirname != NULL){
471 *dirname = '\0';
472 dirname++;
474 else
475 dirname = "";
476 if((fd = open(filelist, O_RDONLY, 0)) == -1)
477 system_fatal("can't open file list file: %s", filelist);
478 if(fstat(fd, &stat_buf) == -1)
479 system_fatal("can't stat file list file: %s", filelist);
481 * For some reason mapping files with zero size fails
482 * so it has to be handled specially.
484 addr = NULL;
485 if(stat_buf.st_size != 0){
486 addr = mmap(0, stat_buf.st_size, PROT_READ|PROT_WRITE,
487 MAP_FILE|MAP_PRIVATE, fd, 0);
488 if((intptr_t)addr == -1)
489 system_error("can't map file list file: %s",
490 filelist);
492 else{
493 fatal("file list file: %s is empty", filelist);
495 if(*dirname != '\0')
496 dirname[-1] = ',';
497 close(fd);
498 nfiles = 0;
499 for(j = 0; j < stat_buf.st_size; j++){
500 if(addr[j] == '\n')
501 nfiles++;
503 if(addr[stat_buf.st_size - 1] != '\n')
504 nfiles++;
505 p = allocate((strlen(dirname) + 1) * nfiles +
506 stat_buf.st_size);
507 cmd_flags.files = reallocate(cmd_flags.files,
508 sizeof(char *) * (maxfiles + nfiles));
509 cmd_flags.filelist = reallocate(cmd_flags.filelist,
510 sizeof(char *) * (maxfiles + nfiles));
511 memset(cmd_flags.filelist + maxfiles, '\0',
512 sizeof(char *) * nfiles);
513 maxfiles += nfiles;
515 cmd_flags.files[cmd_flags.nfiles] = p;
516 cmd_flags.filelist[cmd_flags.nfiles] = filelist;
517 cmd_flags.nfiles++;
518 if(*dirname != '\0'){
519 strcpy(p, dirname);
520 p += strlen(dirname);
521 *p++ = '/';
523 for(j = 0; j < stat_buf.st_size; j++){
524 if(addr[j] != '\n')
525 *p++ = addr[j];
526 else{
527 *p++ = '\0';
528 if(j != stat_buf.st_size - 1){
529 cmd_flags.files[cmd_flags.nfiles] = p;
530 cmd_flags.filelist[cmd_flags.nfiles] =argv[i+1];
531 cmd_flags.nfiles++;
532 if(*dirname != '\0'){
533 strcpy(p, dirname);
534 p += strlen(dirname);
535 *p++ = '/';
540 if(addr[stat_buf.st_size - 1] != '\n')
541 *p = '\0';
542 i++;
544 else if(strcmp(argv[i], "-compatibility_version") == 0){
545 if(cmd_flags.ranlib == TRUE){
546 error("unknown option: %s", argv[i]);
547 usage();
549 if(i + 1 == argc){
550 error("missing argument to: %s option", argv[i]);
551 usage();
553 if(cmd_flags.compatibility != NULL){
554 error("more than one: %s option specified", argv[i]);
555 usage();
557 if(get_version_number(argv[i], argv[i+1], &temp) == FALSE){
558 usage();
560 cmd_flags.compatibility = argv[i+1];
561 i++;
563 else if(strcmp(argv[i], "-current_version") == 0){
564 if(cmd_flags.ranlib == TRUE){
565 error("unknown option: %s", argv[i]);
566 usage();
568 if(i + 1 == argc){
569 error("missing argument to: %s option", argv[i]);
570 usage();
572 if(cmd_flags.current != NULL){
573 error("more than one: %s option specified", argv[i]);
574 usage();
576 if(get_version_number(argv[i], argv[i+1], &temp) == FALSE){
577 usage();
579 cmd_flags.current = argv[i+1];
580 i++;
582 else if(strcmp(argv[i], "-install_name") == 0){
583 if(cmd_flags.ranlib == TRUE){
584 error("unknown option: %s", argv[i]);
585 usage();
587 if(i + 1 == argc){
588 error("missing argument to: %s option", argv[i]);
589 usage();
591 if(cmd_flags.install_name != NULL){
592 error("more than one: %s option specified", argv[i]);
593 usage();
595 cmd_flags.install_name = argv[i+1];
596 i++;
598 else if(strcmp(argv[i], "-seg1addr") == 0 ||
599 strcmp(argv[i], "-image_base") == 0){
600 if(cmd_flags.ranlib == TRUE){
601 error("unknown option: %s", argv[i]);
602 usage();
604 if(i + 1 == argc){
605 error("missing argument to: %s option", argv[i]);
606 usage();
608 if(cmd_flags.seg1addr != NULL){
609 error("more than one: %s option specified", argv[i]);
610 usage();
612 temp = strtoul(argv[i + 1], &endp, 16);
613 if(*endp != '\0'){
614 error("address for -seg1addr %s not a proper "
615 "hexadecimal number", argv[i+1]);
616 usage();
618 cmd_flags.seg1addr = argv[i+1];
619 i++;
621 else if(strcmp(argv[i], "-segs_read_only_addr") == 0){
622 if(cmd_flags.ranlib == TRUE){
623 error("unknown option: %s", argv[i]);
624 usage();
626 if(i + 1 == argc){
627 error("missing argument to: %s option", argv[i]);
628 usage();
630 if(cmd_flags.segs_read_only_addr != NULL){
631 error("more than one: %s option specified", argv[i]);
632 usage();
634 temp = strtoul(argv[i + 1], &endp, 16);
635 if(*endp != '\0'){
636 error("address for -segs_read_only_addr %s not a "
637 "proper hexadecimal number", argv[i+1]);
638 usage();
640 cmd_flags.segs_read_only_addr = argv[i+1];
641 i++;
643 else if(strcmp(argv[i], "-segs_read_write_addr") == 0){
644 if(cmd_flags.ranlib == TRUE){
645 error("unknown option: %s", argv[i]);
646 usage();
648 if(i + 1 == argc){
649 error("missing argument to: %s option", argv[i]);
650 usage();
652 if(cmd_flags.segs_read_write_addr != NULL){
653 error("more than one: %s option specified", argv[i]);
654 usage();
656 temp = strtoul(argv[i + 1], &endp, 16);
657 if(*endp != '\0'){
658 error("address for -segs_read_write_addr %s not a "
659 "proper hexadecimal number", argv[i+1]);
660 usage();
662 cmd_flags.segs_read_write_addr = argv[i+1];
663 i++;
665 else if(strcmp(argv[i], "-seg_addr_table") == 0){
666 if(cmd_flags.ranlib == TRUE){
667 error("unknown option: %s", argv[i]);
668 usage();
670 if(i + 1 == argc){
671 error("missing argument to: %s option", argv[i]);
672 usage();
674 if(cmd_flags.seg_addr_table != NULL){
675 error("more than one: %s option specified", argv[i]);
676 usage();
678 cmd_flags.seg_addr_table = argv[i+1];
679 i++;
681 else if(strcmp(argv[i], "-seg_addr_table_filename") == 0){
682 if(cmd_flags.ranlib == TRUE){
683 error("unknown option: %s", argv[i]);
684 usage();
686 if(i + 1 == argc){
687 error("missing argument to: %s option", argv[i]);
688 usage();
690 if(cmd_flags.seg_addr_table_filename != NULL){
691 error("more than one: %s option specified", argv[i]);
692 usage();
694 cmd_flags.seg_addr_table_filename = argv[i+1];
695 i++;
697 else if(strcmp(argv[i], "-syslibroot") == 0){
698 if(cmd_flags.ranlib == TRUE){
699 error("unknown option: %s", argv[i]);
700 usage();
702 if(i + 1 == argc){
703 error("missing argument to: %s option", argv[i]);
704 usage();
706 if(next_root != NULL && strcmp(next_root, argv[i+1]) != 0){
707 error("more than one: %s option specified", argv[i]);
708 usage();
710 next_root = argv[i+1];
711 cmd_flags.ldflags = reallocate(cmd_flags.ldflags,
712 sizeof(char *) * (cmd_flags.nldflags + 2));
713 cmd_flags.ldflags[cmd_flags.nldflags++] = argv[i];
714 cmd_flags.ldflags[cmd_flags.nldflags++] = argv[i+1];
715 i++;
717 else if(strcmp(argv[i], "-sectcreate") == 0 ||
718 strcmp(argv[i], "-segcreate") == 0 ||
719 strcmp(argv[i], "-sectorder") == 0 ||
720 strcmp(argv[i], "-sectalign") == 0 ||
721 strcmp(argv[i], "-segprot") == 0){
722 if(cmd_flags.ranlib == TRUE){
723 error("unknown option: %s", argv[i]);
724 usage();
726 if(i + 3 >= argc){
727 error("not enough arguments follow %s", argv[i]);
728 usage();
730 cmd_flags.ldflags = reallocate(cmd_flags.ldflags,
731 sizeof(char *) * (cmd_flags.nldflags + 4));
732 cmd_flags.ldflags[cmd_flags.nldflags++] = argv[i];
733 cmd_flags.ldflags[cmd_flags.nldflags++] = argv[i+1];
734 cmd_flags.ldflags[cmd_flags.nldflags++] = argv[i+2];
735 cmd_flags.ldflags[cmd_flags.nldflags++] = argv[i+3];
736 if(strcmp(argv[i], "-sectcreate") == 0 ||
737 strcmp(argv[i], "-segcreate") == 0)
738 cmd_flags.no_files_ok = TRUE;
739 i += 3;
741 else if(strcmp(argv[i], "-segalign") == 0 ||
742 strcmp(argv[i], "-undefined") == 0 ||
743 strcmp(argv[i], "-macosx_version_min") == 0 ||
744 strcmp(argv[i], "-ios_version_min") == 0 ||
745 strcmp(argv[i], "-ios_simulator_version_min") == 0 ||
746 strcmp(argv[i], "-watchos_version_min") == 0 ||
747 strcmp(argv[i], "-watchos_simulator_version_min") == 0 ||
748 strcmp(argv[i], "-tvos_version_min") == 0 ||
749 strcmp(argv[i], "-tvos_simulator_version_min") == 0 ||
750 strcmp(argv[i], "-multiply_defined") == 0 ||
751 strcmp(argv[i], "-multiply_defined_unused") == 0 ||
752 strcmp(argv[i], "-umbrella") == 0 ||
753 strcmp(argv[i], "-sub_umbrella") == 0 ||
754 strcmp(argv[i], "-sub_library") == 0 ||
755 strcmp(argv[i], "-allowable_client") == 0 ||
756 strcmp(argv[i], "-read_only_relocs") == 0 ||
757 strcmp(argv[i], "-init") == 0 ||
758 strcmp(argv[i], "-U") == 0 ||
759 strcmp(argv[i], "-Y") == 0 ||
760 strcmp(argv[i], "-dylib_file") == 0 ||
761 strcmp(argv[i], "-final_output") == 0 ||
762 strcmp(argv[i], "-headerpad") == 0 ||
763 strcmp(argv[i], "-weak_reference_mismatches") == 0 ||
764 strcmp(argv[i], "-u") == 0 ||
765 strcmp(argv[i], "-exported_symbols_list") == 0 ||
766 strcmp(argv[i], "-unexported_symbols_list") == 0 ||
767 strcmp(argv[i], "-executable_path") == 0){
768 if(cmd_flags.ranlib == TRUE){
769 error("unknown option: %s", argv[i]);
770 usage();
772 if(i + 1 >= argc){
773 error("not enough arguments follow %s", argv[i]);
774 usage();
776 cmd_flags.ldflags = reallocate(cmd_flags.ldflags,
777 sizeof(char *) * (cmd_flags.nldflags + 2));
778 cmd_flags.ldflags[cmd_flags.nldflags++] = argv[i];
779 cmd_flags.ldflags[cmd_flags.nldflags++] = argv[i+1];
780 if(strcmp(argv[i], "-final_output") == 0)
781 cmd_flags.final_output_specified = TRUE;
782 i += 1;
784 else if(strcmp(argv[i], "-sectorder_detail") == 0 ||
785 strcmp(argv[i], "-Sn") == 0 ||
786 strcmp(argv[i], "-Si") == 0 ||
787 strcmp(argv[i], "-Sp") == 0 ||
788 strcmp(argv[i], "-S") == 0 ||
789 strcmp(argv[i], "-X") == 0 ||
790 strcmp(argv[i], "-x") == 0 ||
791 strcmp(argv[i], "-whatsloaded") == 0 ||
792 strcmp(argv[i], "-whyload") == 0 ||
793 strcmp(argv[i], "-arch_errors_fatal") == 0 ||
794 strcmp(argv[i], "-run_init_lazily") == 0 ||
795 strcmp(argv[i], "-twolevel_namespace") == 0 ||
796 strcmp(argv[i], "-twolevel_namespace_hints") == 0 ||
797 strcmp(argv[i], "-flat_namespace") == 0 ||
798 strcmp(argv[i], "-nomultidefs") == 0 ||
799 strcmp(argv[i], "-headerpad_max_install_names") == 0 ||
800 strcmp(argv[i], "-prebind_all_twolevel_modules") == 0 ||
801 strcmp(argv[i], "-prebind_allow_overlap") == 0 ||
802 strcmp(argv[i], "-ObjC") == 0 ||
803 strcmp(argv[i], "-M") == 0 ||
804 strcmp(argv[i], "-t") == 0 ||
805 strcmp(argv[i], "-single_module") == 0 ||
806 strcmp(argv[i], "-multi_module") == 0 ||
807 strcmp(argv[i], "-m") == 0 ||
808 strcmp(argv[i], "-dead_strip") == 0 ||
809 strcmp(argv[i], "-no_uuid") == 0 ||
810 strcmp(argv[i], "-no_dead_strip_inits_and_terms") == 0){
811 if(cmd_flags.ranlib == TRUE){
812 error("unknown option: %s", argv[i]);
813 usage();
815 cmd_flags.ldflags = reallocate(cmd_flags.ldflags,
816 sizeof(char *) * (cmd_flags.nldflags + 1));
817 cmd_flags.ldflags[cmd_flags.nldflags++] = argv[i];
819 else if(strcmp(argv[i], "-no_arch_warnings") == 0){
820 if(cmd_flags.ranlib == TRUE){
821 error("unknown option: %s", argv[i]);
822 usage();
824 /* ignore this flag */
826 else if(strcmp(argv[i], "-prebind") == 0){
827 if(cmd_flags.ranlib == TRUE){
828 error("unknown option: %s", argv[i]);
829 usage();
831 if(cmd_flags.prebinding_flag_specified == TRUE &&
832 cmd_flags.prebinding == FALSE){
833 error("both -prebind and -noprebind can't be "
834 "specified");
835 usage();
837 cmd_flags.prebinding_flag_specified = TRUE;
838 cmd_flags.prebinding = TRUE;
839 cmd_flags.ldflags = reallocate(cmd_flags.ldflags,
840 sizeof(char *) * (cmd_flags.nldflags + 1));
841 cmd_flags.ldflags[cmd_flags.nldflags++] = argv[i];
843 else if(strcmp(argv[i], "-noprebind") == 0){
844 if(cmd_flags.ranlib == TRUE){
845 error("unknown option: %s", argv[i]);
846 usage();
848 if(cmd_flags.prebinding_flag_specified == TRUE &&
849 cmd_flags.prebinding == TRUE){
850 error("both -prebind and -noprebind can't be "
851 "specified");
852 usage();
854 cmd_flags.prebinding_flag_specified = TRUE;
855 cmd_flags.prebinding = FALSE;
856 cmd_flags.ldflags = reallocate(cmd_flags.ldflags,
857 sizeof(char *) * (cmd_flags.nldflags + 1));
858 cmd_flags.ldflags[cmd_flags.nldflags++] = argv[i];
860 else if(strcmp(argv[i], "-all_load") == 0){
861 if(cmd_flags.ranlib == TRUE){
862 error("unknown option: %s", argv[i]);
863 usage();
865 if(cmd_flags.all_load_flag_specified == TRUE &&
866 cmd_flags.all_load == FALSE){
867 error("both -all_load and -noall_load can't be "
868 "specified");
869 usage();
871 cmd_flags.all_load_flag_specified = TRUE;
872 cmd_flags.all_load = TRUE;
874 else if(strcmp(argv[i], "-noall_load") == 0){
875 if(cmd_flags.ranlib == TRUE){
876 error("unknown option: %s", argv[i]);
877 usage();
879 if(cmd_flags.all_load_flag_specified == TRUE &&
880 cmd_flags.all_load == TRUE){
881 error("both -all_load and -noall_load can't be "
882 "specified");
883 usage();
885 cmd_flags.all_load_flag_specified = TRUE;
886 cmd_flags.all_load = FALSE;
888 else if(strncmp(argv[i], "-y", 2) == 0 ||
889 strncmp(argv[i], "-i", 2) == 0){
890 if(cmd_flags.ranlib == TRUE){
891 error("unknown option: %s", argv[i]);
892 usage();
894 if(strncmp(argv[i], "-i", 2) == 0)
895 cmd_flags.no_files_ok = TRUE;
896 cmd_flags.ldflags = reallocate(cmd_flags.ldflags,
897 sizeof(char *) * (cmd_flags.nldflags + 1));
898 cmd_flags.ldflags[cmd_flags.nldflags++] = argv[i];
900 else if(argv[i][1] == 'l'){
901 if(cmd_flags.ranlib == TRUE){
902 error("unknown option: %s", argv[i]);
903 usage();
905 if(argv[i][2] == '\0'){
906 error("-l: name missing");
907 usage();
909 cmd_flags.files[cmd_flags.nfiles++] = argv[i];
910 lflags_seen = TRUE;
912 else if(strncmp(argv[i], "-weak-l", 7) == 0){
913 if(cmd_flags.ranlib == TRUE){
914 error("unknown option: %s", argv[i]);
915 usage();
917 if(argv[i][7] == '\0'){
918 error("-weak-l: name missing");
919 usage();
921 cmd_flags.files[cmd_flags.nfiles++] = argv[i];
922 lflags_seen = TRUE;
924 else if(strcmp(argv[i], "-framework") == 0 ||
925 strcmp(argv[i], "-weak_framework") == 0 ||
926 strcmp(argv[i], "-weak_library") == 0){
927 if(cmd_flags.ranlib == TRUE){
928 error("unknown option: %s", argv[i]);
929 usage();
931 if(i + 1 >= argc){
932 error("not enough arguments follow %s", argv[i]);
933 usage();
935 cmd_flags.files[cmd_flags.nfiles++] = argv[i];
936 cmd_flags.files[cmd_flags.nfiles++] = argv[i+1];
937 lflags_seen = TRUE;
938 i += 1;
940 else if(strcmp(argv[i], "-T") == 0){
941 if(cmd_flags.L_or_T_specified == TRUE){
942 error("both -T and -L can't be specified");
943 usage();
945 cmd_flags.L_or_T_specified = TRUE;
946 cmd_flags.use_long_names = FALSE;
948 else if(argv[i][1] == 'L' || argv[i][1] == 'F'){
949 if(argv[i][1] == 'L' && argv[i][2] == '\0'){
950 if(cmd_flags.L_or_T_specified == TRUE){
951 error("both -T and -L can't be specified");
952 usage();
954 cmd_flags.L_or_T_specified = TRUE;
955 cmd_flags.use_long_names = TRUE;
957 else{
958 if(cmd_flags.ranlib == TRUE){
959 error("unknown option: %s", argv[i]);
960 usage();
962 cmd_flags.Ldirs = realloc(cmd_flags.Ldirs,
963 sizeof(char *) * (cmd_flags.nLdirs + 1));
964 cmd_flags.Ldirs[cmd_flags.nLdirs++] = argv[i];
967 else if(argv[i][1] == 'g'){
968 if(cmd_flags.ranlib == TRUE){
969 error("unknown option: %s", argv[i]);
970 usage();
972 /* We need to ignore -g[gdb,codeview,stab][number] flags */
975 else if(strcmp(argv[i], "-pg") == 0){
976 if(cmd_flags.ranlib == TRUE){
977 error("unknown option: %s", argv[i]);
978 usage();
980 /* We need to ignore -pg */
983 else if(strcmp(argv[i], "-search_paths_first") == 0){
984 if(cmd_flags.ranlib == TRUE){
985 error("unknown option: %s", argv[i]);
986 usage();
988 cmd_flags.search_paths_first = TRUE;
989 cmd_flags.ldflags = reallocate(cmd_flags.ldflags,
990 sizeof(char *) * (cmd_flags.nldflags + 1));
991 cmd_flags.ldflags[cmd_flags.nldflags++] = argv[i];
993 else if(strcmp(argv[i], "-noflush") == 0){
994 cmd_flags.noflush = TRUE;
996 else if(strcmp(argv[i], "-no_warning_for_no_symbols") == 0){
997 cmd_flags.no_warning_for_no_symbols = TRUE;
999 #ifdef DEBUG
1000 else if(strcmp(argv[i], "-debug") == 0){
1001 if(i + 1 >= argc){
1002 error("not enough arguments follow %s", argv[i]);
1003 usage();
1005 i++;
1006 cmd_flags.debug |= 1 << strtoul(argv[i], &endp, 10);
1007 if(*endp != '\0' || strtoul(argv[i], &endp, 10) > 32)
1008 fatal("argument for -debug %s not a proper "
1009 "decimal number less than 32", argv[i]);
1011 #endif /* DEBUG */
1012 else{
1013 for(j = 1; argv[i][j] != '\0'; j++){
1014 switch(argv[i][j]){
1015 case 's':
1016 cmd_flags.s = TRUE;
1017 break;
1018 case 'a':
1019 cmd_flags.a = TRUE;
1020 break;
1021 case 'c':
1022 cmd_flags.c = TRUE;
1023 break;
1024 case 'v':
1025 if(cmd_flags.ranlib == TRUE){
1026 error("unknown option character `%c' in: %s",
1027 argv[i][j], argv[i]);
1028 usage();
1030 cmd_flags.verbose= TRUE;
1031 break;
1032 case 'V':
1033 printf("Apple Inc. version %s\n", apple_version);
1034 Vflag = TRUE;
1035 break;
1036 case 't':
1037 if(cmd_flags.ranlib == TRUE){
1038 warning("touch option (`%c' in: %s) ignored "
1039 "(table of contents rebuilt anyway)",
1040 argv[i][j], argv[i]);
1041 cmd_flags.t = TRUE;
1042 break;
1044 else {
1045 error("unknown option character `%c' in: %s",
1046 argv[i][j], argv[i]);
1047 usage();
1049 case 'f':
1050 if(cmd_flags.ranlib == TRUE){
1051 cmd_flags.f = TRUE;
1052 break;
1054 else {
1055 error("unknown option character `%c' in: %s",
1056 argv[i][j], argv[i]);
1057 usage();
1059 case 'q':
1060 if(cmd_flags.ranlib == TRUE){
1061 cmd_flags.q = TRUE;
1062 break;
1064 else {
1065 error("unknown option character `%c' in: %s",
1066 argv[i][j], argv[i]);
1067 usage();
1069 default:
1070 error("unknown option character `%c' in: %s",
1071 argv[i][j], argv[i]);
1072 usage();
1077 else
1078 cmd_flags.files[cmd_flags.nfiles++] = argv[i];
1081 * Test to see if the environment variable LD_TRACE_ARCHIVES is set.
1083 if((getenv("RC_TRACE_ARCHIVES") != NULL) ||
1084 (getenv("LD_TRACE_ARCHIVES") != NULL)) {
1085 cmd_flags.ld_trace_archives = TRUE;
1086 cmd_flags.trace_file_path = getenv("LD_TRACE_FILE");
1090 * If either -syslibroot or the environment variable NEXT_ROOT is set
1091 * prepend it to the standard paths for library searches. This was
1092 * added to ease cross build environments.
1094 if(next_root != NULL){
1095 if(getenv("NEXT_ROOT") != NULL)
1096 warning("NEXT_ROOT environment variable ignored because "
1097 "-syslibroot specified");
1099 else{
1100 next_root = getenv("NEXT_ROOT");
1102 if(next_root != NULL){
1103 for(i = 0; standard_dirs[i] != NULL; i++){
1104 p = allocate(strlen(next_root) +
1105 strlen(standard_dirs[i]) + 1);
1106 strcpy(p, next_root);
1107 strcat(p, standard_dirs[i]);
1108 standard_dirs[i] = p;
1110 for(i = 0; i < cmd_flags.nLdirs ; i++){
1111 if(cmd_flags.Ldirs[i][1] != 'L')
1112 continue;
1113 if(cmd_flags.Ldirs[i][2] == '/'){
1114 p = makestr(next_root, cmd_flags.Ldirs[i] + 2, NULL);
1115 if(access(p, F_OK) != -1){
1116 free(p);
1117 p = makestr("-L", next_root, cmd_flags.Ldirs[i] + 2,
1118 NULL);
1119 cmd_flags.Ldirs[i] = p;
1121 else{
1122 free(p);
1128 /* check the command line arguments for correctness */
1129 if(cmd_flags.ranlib == FALSE && cmd_flags.dynamic == TRUE){
1130 if(cmd_flags.s == TRUE){
1131 warning("-static not specified, -s invalid");
1133 if(cmd_flags.a == TRUE){
1134 warning("-static not specified, -a invalid");
1136 if(cmd_flags.c == TRUE){
1137 warning("-static not specified, -c invalid");
1139 if(cmd_flags.L_or_T_specified == TRUE){
1140 if(cmd_flags.use_long_names == TRUE)
1141 warning("-static not specified, -L invalid");
1142 else
1143 warning("-static not specified, -T invalid");
1146 if(cmd_flags.s == TRUE && cmd_flags.a == TRUE){
1147 error("only one of -s or -a can be specified");
1148 usage();
1150 if(cmd_flags.ranlib == FALSE && cmd_flags.output == NULL){
1151 if(Vflag == TRUE)
1152 exit(EXIT_SUCCESS);
1153 error("no output file specified (specify with -o output)");
1154 usage();
1156 if(cmd_flags.dynamic == FALSE){
1157 if(cmd_flags.compatibility != NULL){
1158 warning("-dynamic not specified, -compatibility_version %s "
1159 "invalid", cmd_flags.compatibility);
1161 if(cmd_flags.current != NULL){
1162 warning("-dynamic not specified, -current_version %s invalid",
1163 cmd_flags.current);
1165 if(cmd_flags.install_name != NULL){
1166 warning("-dynamic not specified, -install_name %s invalid",
1167 cmd_flags.install_name);
1169 if(cmd_flags.seg1addr != NULL){
1170 warning("-dynamic not specified, -seg1addr %s invalid",
1171 cmd_flags.seg1addr);
1173 if(cmd_flags.segs_read_only_addr != NULL){
1174 warning("-dynamic not specified, -segs_read_only_addr %s "
1175 "invalid", cmd_flags.segs_read_only_addr);
1177 if(cmd_flags.segs_read_write_addr != NULL){
1178 warning("-dynamic not specified, -segs_read_write_addr %s "
1179 "invalid", cmd_flags.segs_read_write_addr);
1181 if(cmd_flags.seg_addr_table != NULL){
1182 warning("-dynamic not specified, -seg_addr_table %s "
1183 "invalid", cmd_flags.seg_addr_table);
1185 if(cmd_flags.seg_addr_table_filename != NULL){
1186 warning("-dynamic not specified, -seg_addr_table_filename %s "
1187 "invalid", cmd_flags.seg_addr_table_filename);
1189 if(cmd_flags.all_load_flag_specified == TRUE){
1190 if(cmd_flags.all_load == TRUE)
1191 warning("-dynamic not specified, -all_load invalid");
1192 else
1193 warning("-dynamic not specified, -noall_load invalid");
1195 if(cmd_flags.nldflags != 0){
1196 bad_flag_seen = FALSE;
1197 for(j = 0; j < cmd_flags.nldflags; j++){
1198 if(strcmp(cmd_flags.ldflags[j], "-syslibroot") == 0){
1199 j++;
1200 continue;
1202 if(bad_flag_seen == FALSE){
1203 fprintf(stderr, "%s: -dynamic not specified the "
1204 "following flags are invalid: ", progname);
1205 bad_flag_seen = TRUE;
1207 fprintf(stderr, "%s ", cmd_flags.ldflags[j]);
1209 if(bad_flag_seen == TRUE)
1210 fprintf(stderr, "\n");
1212 if(cmd_flags.nLdirs != 0){
1213 /* Note: both -L and -F flags are in cmd_flags.Ldirs to keep the
1214 search order right. */
1215 bad_flag_seen = FALSE;
1216 for(j = 0; j < cmd_flags.nLdirs; j++){
1217 if(strncmp(cmd_flags.Ldirs[j], "-L", 2) == 0)
1218 continue;
1219 if(bad_flag_seen == FALSE){
1220 fprintf(stderr, "%s: -dynamic not specified the "
1221 "following flags are invalid: ", progname);
1222 bad_flag_seen = TRUE;
1224 fprintf(stderr, "%s ", cmd_flags.Ldirs[j]);
1226 if(bad_flag_seen == TRUE)
1227 fprintf(stderr, "\n");
1230 else{
1232 * The -prebind flag can also be specified with the LD_PREBIND
1233 * environment variable.
1235 if(getenv("LD_PREBIND") != NULL){
1236 if(cmd_flags.prebinding_flag_specified == TRUE &&
1237 cmd_flags.prebinding == FALSE){
1238 warning("LD_PREBIND environment variable ignored because "
1239 "-noprebind specified");
1241 else{
1242 cmd_flags.prebinding_flag_specified = TRUE;
1243 cmd_flags.prebinding = TRUE;
1247 if(cmd_flags.nfiles == 0){
1248 if(cmd_flags.ranlib == TRUE){
1249 error("no archives specified");
1250 usage();
1252 else{
1253 if(cmd_flags.dynamic == TRUE && cmd_flags.no_files_ok == TRUE)
1254 warning("warning no files specified");
1255 else{
1256 error("no files specified");
1257 usage();
1262 /* set the defaults if not specified */
1263 if(cmd_flags.a == FALSE)
1264 cmd_flags.s = TRUE; /* sort table of contents by default */
1266 process();
1268 if(errors == 0)
1269 return(EXIT_SUCCESS);
1270 else
1271 return(EXIT_FAILURE);
1275 * usage() prints the current usage message and exits indicating failure.
1277 static
1278 void
1279 usage(
1280 void)
1282 if(cmd_flags.ranlib)
1283 fprintf(stderr, "Usage: %s [-sactfqLT] [-] archive [...]\n",
1284 progname);
1285 else{
1286 fprintf(stderr, "Usage: %s -static [-] file [...] "
1287 "[-filelist listfile[,dirname]] [-arch_only arch] "
1288 "[-sacLT] [-no_warning_for_no_symbols]\n", progname);
1289 fprintf(stderr, "Usage: %s -dynamic [-] file [...] "
1290 "[-filelist listfile[,dirname]] [-arch_only arch] "
1291 "[-o output] [-install_name name] "
1292 "[-compatibility_version #] [-current_version #] "
1293 "[-seg1addr 0x#] [-segs_read_only_addr 0x#] "
1294 "[-segs_read_write_addr 0x#] [-seg_addr_table <filename>] "
1295 "[-seg_addr_table_filename <file_system_path>] "
1296 "[-all_load] [-noall_load]\n",
1297 progname);
1299 exit(EXIT_FAILURE);
1303 * process() the input files into libraries based on the command flags.
1305 static
1306 void
1307 process(
1308 void)
1310 uint32_t i, j, k, previous_errors;
1311 struct ofile *ofiles;
1312 char *file_name;
1313 enum bool flag, ld_trace_archive_printed;
1316 * For libtool processing put all input files in the specified output
1317 * file. For ranlib processing all input files should be archives or
1318 * fat files with archives in them and each is processed by itself and
1319 * not combined with anything else. The format of fat object files in
1320 * a thin archive is supported here also.
1322 ofiles = allocate(sizeof(struct ofile) * cmd_flags.nfiles);
1323 for(i = 0; i < cmd_flags.nfiles; i++){
1324 if(strncmp(cmd_flags.files[i], "-l", 2) == 0 ||
1325 strncmp(cmd_flags.files[i], "-weak-l", 7) == 0){
1326 file_name = file_name_from_l_flag(cmd_flags.files[i]);
1327 if(file_name != NULL)
1328 if(ofile_map(file_name, NULL, NULL, ofiles + i, TRUE) ==
1329 FALSE)
1330 continue;
1332 else if(strcmp(cmd_flags.files[i], "-framework") == 0 ||
1333 strcmp(cmd_flags.files[i], "-weak_framework") == 0 ||
1334 strcmp(cmd_flags.files[i], "-weak_library") == 0){
1335 i++;
1336 continue;
1338 else{
1339 if(ofile_map(cmd_flags.files[i], NULL, NULL, ofiles + i,
1340 TRUE) == FALSE)
1341 continue;
1344 previous_errors = errors;
1345 errors = 0;
1346 ld_trace_archive_printed = FALSE;
1348 if(ofiles[i].file_type == OFILE_FAT){
1349 (void)ofile_first_arch(ofiles + i);
1351 if(ofiles[i].arch_type == OFILE_ARCHIVE){
1352 if(cmd_flags.ld_trace_archives == TRUE &&
1353 cmd_flags.dynamic == FALSE &&
1354 ld_trace_archive_printed == FALSE){
1355 char resolvedname[MAXPATHLEN];
1356 if(realpath(ofiles[i].file_name, resolvedname) !=
1357 NULL)
1358 ld_trace("[Logging for XBS] Used static "
1359 "archive: %s\n", resolvedname);
1360 else
1361 ld_trace("[Logging for XBS] Used static "
1362 "archive: %s\n", ofiles[i].file_name);
1363 ld_trace_archive_printed = TRUE;
1365 /* loop through archive */
1366 if((flag = ofile_first_member(ofiles + i)) == TRUE){
1367 if(ofiles[i].member_ar_hdr != NULL &&
1368 strncmp(ofiles[i].member_name, SYMDEF,
1369 sizeof(SYMDEF) - 1) == 0)
1370 flag = ofile_next_member(ofiles + i);
1371 while(flag == TRUE){
1372 /* No fat members in a fat file */
1373 if(ofiles[i].mh != NULL ||
1374 ofiles[i].mh64 != NULL ||
1375 #ifdef LTO_SUPPORT
1376 ofiles[i].lto != NULL ||
1377 #endif /* LTO_SUPPORT */
1378 cmd_flags.ranlib == TRUE)
1379 add_member(ofiles + i);
1380 else{
1381 error("for architecture: %s file: %s(%.*s) "
1382 "is not an object file (not allowed "
1383 "in a library)",
1384 ofiles[i].arch_flag.name,
1385 cmd_flags.files[i],
1386 (int)ofiles[i].member_name_size,
1387 ofiles[i].member_name);
1389 flag = ofile_next_member(ofiles + i);
1393 else if(ofiles[i].arch_type == OFILE_Mach_O
1394 #ifdef LTO_SUPPORT
1395 || ofiles[i].arch_type == OFILE_LLVM_BITCODE
1396 #endif
1398 if(cmd_flags.ranlib == TRUE){
1399 error("for architecture: %s file: %s is not an "
1400 "archive (no processing done on this file)",
1401 ofiles[i].arch_flag.name, cmd_flags.files[i]);
1402 goto ranlib_fat_error;
1404 else
1405 add_member(ofiles + i);
1407 else if(ofiles[i].arch_type == OFILE_UNKNOWN){
1408 if(cmd_flags.ranlib == TRUE){
1409 error("for architecture: %s file: %s is not an "
1410 "archive (no processing done on this file)",
1411 ofiles[i].arch_flag.name, cmd_flags.files[i]);
1412 goto ranlib_fat_error;
1414 else{
1415 error("for architecture: %s file: %s is not an "
1416 "object file (not allowed in a library)",
1417 ofiles[i].arch_flag.name, cmd_flags.files[i]);
1420 }while(ofile_next_arch(ofiles + i) == TRUE);
1422 else if(ofiles[i].file_type == OFILE_ARCHIVE){
1423 if(cmd_flags.ld_trace_archives == TRUE &&
1424 cmd_flags.dynamic == FALSE &&
1425 ld_trace_archive_printed == FALSE){
1426 char resolvedname[MAXPATHLEN];
1427 if(realpath(ofiles[i].file_name, resolvedname) != NULL)
1428 ld_trace("[Logging for XBS] Used static archive: "
1429 "%s\n", resolvedname);
1430 else
1431 ld_trace("[Logging for XBS] Used static archive: "
1432 "%s\n", ofiles[i].file_name);
1433 ld_trace_archive_printed = TRUE;
1435 /* loop through archive */
1436 if((flag = ofile_first_member(ofiles + i)) == TRUE){
1437 if(ofiles[i].member_ar_hdr != NULL &&
1438 strncmp(ofiles[i].member_name, SYMDEF,
1439 sizeof(SYMDEF) - 1) == 0){
1440 flag = ofile_next_member(ofiles + i);
1442 while(flag == TRUE){
1443 /* incorrect form: archive with fat object members */
1444 if(ofiles[i].member_type == OFILE_FAT){
1445 (void)ofile_first_arch(ofiles + i);
1447 if(ofiles[i].mh != NULL ||
1448 ofiles[i].mh64 != NULL ||
1449 ofiles[i].lto != NULL ||
1450 cmd_flags.ranlib == TRUE){
1451 add_member(ofiles + i);
1453 else{
1455 * Can't really get here because ofile_*()
1456 * routines will refuse to process this
1457 * type of file (but I'll leave it here).
1459 error("file: %s(%.*s) for architecture: %s "
1460 "is not an object file (not allowed in "
1461 "a library)", cmd_flags.files[i],
1462 (int)ofiles[i].member_name_size,
1463 ofiles[i].member_name,
1464 ofiles[i].arch_flag.name);
1467 }while(ofile_next_arch(ofiles + i) == TRUE);
1469 else if(ofiles[i].mh != NULL ||
1470 ofiles[i].mh64 != NULL ||
1471 #ifdef LTO_SUPPORT
1472 ofiles[i].lto != NULL ||
1473 #endif /* LTO_SUPPORT */
1474 cmd_flags.ranlib == TRUE){
1475 add_member(ofiles + i);
1477 else{
1478 error("file: %s(%.*s) is not an object file (not "
1479 "allowed in a library)", cmd_flags.files[i],
1480 (int)ofiles[i].member_name_size,
1481 ofiles[i].member_name);
1483 flag = ofile_next_member(ofiles + i);
1487 else if(ofiles[i].file_type == OFILE_Mach_O){
1488 if(cmd_flags.ranlib == TRUE){
1489 error("file: %s is not an archive", cmd_flags.files[i]);
1490 continue;
1492 add_member(ofiles + i);
1494 #ifdef LTO_SUPPORT
1495 else if(ofiles[i].file_type == OFILE_LLVM_BITCODE){
1496 if(cmd_flags.ranlib == TRUE){
1497 error("file: %s is not an archive", cmd_flags.files[i]);
1498 continue;
1500 add_member(ofiles + i);
1502 #endif /* LTO_SUPPORT */
1503 else{ /* ofiles[i].file_type == OFILE_UNKNOWN */
1504 if(cmd_flags.ranlib == TRUE){
1505 error("file: %s is not an archive", cmd_flags.files[i]);
1506 continue;
1508 else{
1509 error("file: %s is not an object file (not allowed in a "
1510 "library)", cmd_flags.files[i]);
1514 if(cmd_flags.ranlib == TRUE){
1516 * In the case where ranlib is being used on an archive that
1517 * contains fat object files with multiple members and non-
1518 * object members this has to be treated as an error because
1519 * it is not known which architecture(s) the non-object file
1520 * belong to.
1522 if(narchs > 1){
1523 for(j = 0; j < narchs; j++){
1524 for(k = 0; k < archs[j].nmembers; k++){
1525 if(archs[j].members[k].mh == NULL &&
1526 #ifdef LTO_SUPPORT
1527 archs[j].members[k].lto_contents == FALSE &&
1528 #endif /* LTO_SUPPORT */
1529 archs[j].members[k].mh64 == NULL){
1530 error("library member: %s(%.*s) is not an "
1531 "object file (not allowed in a library "
1532 "with multiple architectures)",
1533 cmd_flags.files[i],
1534 (int)archs[j].members[k].
1535 input_base_name_size,
1536 archs[j].members[k].input_base_name);
1541 if(errors == 0)
1542 create_library(cmd_flags.files[i], ofiles + i);
1543 if(cmd_flags.nfiles > 1){
1544 ranlib_fat_error:
1545 free_archs();
1546 ofile_unmap(ofiles + i);
1549 errors += previous_errors;
1551 if(cmd_flags.ranlib == FALSE && errors == 0)
1552 create_library(cmd_flags.output, NULL);
1555 * Clean-up of ofiles[] and archs could be done here but since this
1556 * program is now done it is faster to just exit.
1561 * file_name_from_l_flag() is passed a "-lx" or "-weak-lx" flag and returns a
1562 * name of a file for this flag. The flag "-lx" and "-weak-lx" are the same
1563 * flags as used in the link editor to refer to file names. If it can't find a
1564 * file name for the flag it prints an error and returns NULL.
1566 static
1567 char *
1568 file_name_from_l_flag(
1569 char *l_flag)
1571 char *file_name, *p, *start;
1573 if(strncmp(l_flag, "-weak-l", 7) == 0)
1574 start = &l_flag[7];
1575 else
1576 start = &l_flag[2];
1577 p = strrchr(start, '.');
1578 if(p != NULL && strcmp(p, ".o") == 0){
1579 p = start;
1580 file_name = search_for_file(p);
1582 else{
1583 file_name = NULL;
1584 if(cmd_flags.dynamic == TRUE){
1585 if(cmd_flags.search_paths_first == TRUE){
1586 file_name = search_paths_for_lname(start);
1588 else{
1589 p = makestr("lib", start, ".dylib", NULL);
1590 file_name = search_for_file(p);
1591 free(p);
1592 if(file_name == NULL){
1593 p = makestr("lib", start, ".a", NULL);
1594 file_name = search_for_file(p);
1595 free(p);
1599 else{
1600 p = makestr("lib", start, ".a", NULL);
1601 file_name = search_for_file(p);
1602 free(p);
1605 if(file_name == NULL)
1606 error("can't locate file for: %s", l_flag);
1607 return(file_name);
1611 * search_for_file() takes base_name and trys to find a file with that base name
1612 * is the -L search directories and in the standard directories. If it is
1613 * sucessful it returns a pointer to the file name else it returns NULL.
1615 static
1616 char *
1617 search_for_file(
1618 char *base_name)
1620 uint32_t i;
1621 char *file_name;
1623 for(i = 0; i < cmd_flags.nLdirs ; i++){
1624 if(cmd_flags.Ldirs[i][1] != 'L')
1625 continue;
1626 file_name = makestr(cmd_flags.Ldirs[i] + 2, "/", base_name, NULL);
1627 if(access(file_name, R_OK) != -1)
1628 return(file_name);
1629 free(file_name);
1631 for(i = 0; standard_dirs[i] != NULL ; i++){
1632 file_name = makestr(standard_dirs[i], base_name, NULL);
1633 if(access(file_name, R_OK) != -1)
1634 return(file_name);
1635 free(file_name);
1637 return(NULL);
1641 * search_paths_for_lname() takes the argument to a -lx option and and trys to
1642 * find a file with the name libx.dylib or libx.a. This routine is only used
1643 * when the -search_paths_first option is specified and -dynamic is in effect.
1644 * And looks for a file name ending in .dylib then .a in each directory before
1645 * looking in the next directory. The list of the -L search directories and in
1646 * the standard directories are searched in that order. If this is sucessful
1647 * it returns a pointer to the file name else NULL.
1649 static
1650 char *
1651 search_paths_for_lname(
1652 const char *lname_argument)
1654 uint32_t i;
1655 char *file_name, *dir;
1657 for(i = 0; i < cmd_flags.nLdirs ; i++){
1658 if(cmd_flags.Ldirs[i][1] != 'L')
1659 continue;
1660 dir = makestr(cmd_flags.Ldirs[i] + 2, "/", NULL);
1661 file_name = search_path_for_lname(dir, lname_argument);
1662 free(dir);
1663 if(file_name != NULL)
1664 return(file_name);
1666 for(i = 0; standard_dirs[i] != NULL ; i++){
1667 file_name = search_path_for_lname(standard_dirs[i], lname_argument);
1668 if(file_name != NULL)
1669 return(file_name);
1671 return(NULL);
1675 * search_path_for_lname() takes the argument to a -lx option and and trys to
1676 * find a file with the name libx.dylib then libx.a in the specified directory
1677 * name. This routine is only used when the -search_paths_first option is
1678 * specified and -dynamic is in effect. If this is sucessful it returns a
1679 * pointer to the file name else NULL.
1681 static
1682 char *
1683 search_path_for_lname(
1684 const char *dir,
1685 const char *lname_argument)
1687 char *file_name;
1689 file_name = makestr(dir, "/", "lib", lname_argument, ".dylib", NULL);
1690 if(access(file_name, R_OK) != -1)
1691 return(file_name);
1692 free(file_name);
1694 file_name = makestr(dir, "/", "lib", lname_argument, ".a", NULL);
1695 if(access(file_name, R_OK) != -1)
1696 return(file_name);
1697 free(file_name);
1699 return(NULL);
1703 * add_member() add the specified ofile as a member to the library. The
1704 * specified ofile must be either an object file (libtool or ranlib) or an
1705 * archive member with an unknown file type (ranlib only).
1707 static
1708 void
1709 add_member(
1710 struct ofile *ofile)
1712 uint32_t i, j, size, ar_name_size;
1713 struct arch *arch;
1714 struct member *member;
1715 struct stat stat_buf;
1716 char *p, c, ar_name_buf[sizeof(ofile->member_ar_hdr->ar_name) + 1];
1717 char ar_size_buf[sizeof(ofile->member_ar_hdr->ar_size) + 1];
1718 const struct arch_flag *family_arch_flag;
1721 * If this did not come from an archive get the stat info which is
1722 * needed to fill in the archive header for this member.
1724 if(ofile->member_ar_hdr == NULL){
1725 if(stat(ofile->file_name, &stat_buf) == -1){
1726 system_error("can't stat file: %s", ofile->file_name);
1727 return;
1732 * Determine the size this member will have in the library which
1733 * includes the padding as a result of rounding the size of the
1734 * member. To get all members on an 8 byte boundary (so that mapping
1735 * in object files can be used directly) the size of the member is
1736 * CHANGED to reflect this padding. In the UNIX definition of archives
1737 * the size of the member is never changed but the offset to the next
1738 * member is defined to be the offset of the previous member plus
1739 * the size of the previous member rounded to 2. So to get 8 byte
1740 * boundaries without breaking the UNIX definition of archives the
1741 * size is changed here. As with the UNIX ar(1) program the padded
1742 * bytes are set to the character '\n'.
1744 if(ofile->mh != NULL || ofile->mh64 != NULL)
1745 size = rnd(ofile->object_size, 8);
1746 #ifdef LTO_SUPPORT
1747 else if(ofile->lto != NULL){
1748 if(ofile->file_type == OFILE_LLVM_BITCODE)
1749 size = rnd(ofile->file_size, 8);
1750 else if(ofile->file_type == OFILE_FAT ||
1751 (ofile->file_type == OFILE_ARCHIVE &&
1752 ofile->member_type == OFILE_FAT))
1753 size = rnd(ofile->object_size, 8);
1754 else
1755 size = rnd(ofile->member_size, 8);
1757 #endif /* LTO_SUPPORT */
1758 else
1759 size = rnd(ofile->member_size, 8);
1761 /* select or create an arch type to put this in */
1762 i = 0;
1763 if(ofile->mh != NULL ||
1764 ofile->mh64 != NULL){
1765 if(ofile->mh_cputype == 0){
1766 if(ofile->member_ar_hdr != NULL){
1767 error("file: %s(%.*s) cputype is zero (a reserved value)",
1768 ofile->file_name, (int)ofile->member_name_size,
1769 ofile->member_name);
1771 else
1772 error("file: %s cputype is zero (a reserved value)",
1773 ofile->file_name);
1774 return;
1777 * If we are building a dynamic library then don't add dynamic
1778 * shared libraries to the archs. This is so that a dependent
1779 * dynamic shared library that happens to be fat will not cause the
1780 * library to be created fat unless there are object going into
1781 * the library that are fat.
1783 if(ofile->mh_filetype == MH_DYLIB ||
1784 ofile->mh_filetype == MH_DYLIB_STUB){
1786 * If we are building a static library we should not put a
1787 * dynamic library Mach-O file into the static library. This
1788 * can happen if a libx.a file is really a dynamic library and
1789 * someone is using -lx when creating a static library.
1791 if(cmd_flags.dynamic != TRUE){
1792 if(ofile->member_ar_hdr != NULL){
1793 warning("file: %s(%.*s) is a dynamic library, not "
1794 "added to the static library",
1795 ofile->file_name, (int)ofile->member_name_size,
1796 ofile->member_name);
1798 else
1799 warning("file: %s is a dynamic library, not added to "
1800 "the static library", ofile->file_name);
1802 return;
1805 * If -arch_only is specified then only add this file if it matches
1806 * the architecture specified.
1808 if(cmd_flags.arch_only_flag.name != NULL){
1809 if(cmd_flags.arch_only_flag.cputype != ofile->mh_cputype)
1810 return;
1811 if(cmd_flags.arch_only_flag.cputype == CPU_TYPE_ARM ||
1812 cmd_flags.arch_only_flag.cputype == CPU_TYPE_X86_64){
1813 if(cmd_flags.arch_only_flag.cpusubtype !=
1814 ofile->mh_cpusubtype)
1815 return;
1817 if(cmd_flags.arch_only_flag.cputype == CPU_TYPE_ARM64){
1818 if(cmd_flags.arch_only_flag.cpusubtype ==
1819 CPU_SUBTYPE_ARM64_ALL){
1820 if(ofile->mh_cpusubtype != CPU_SUBTYPE_ARM64_ALL &&
1821 ofile->mh_cpusubtype != CPU_SUBTYPE_ARM64_V8)
1822 return;
1824 else if(cmd_flags.arch_only_flag.cpusubtype !=
1825 ofile->mh_cpusubtype)
1826 return;
1830 for( ; i < narchs; i++){
1831 if(archs[i].arch_flag.cputype == ofile->mh_cputype){
1832 if((archs[i].arch_flag.cputype == CPU_TYPE_ARM ||
1833 archs[i].arch_flag.cputype == CPU_TYPE_X86_64) &&
1834 archs[i].arch_flag.cpusubtype != ofile->mh_cpusubtype)
1835 continue;
1836 if(cmd_flags.arch_only_flag.cputype == CPU_TYPE_ARM64){
1837 if(cmd_flags.arch_only_flag.cpusubtype ==
1838 CPU_SUBTYPE_ARM64_ALL){
1839 if(ofile->mh_cpusubtype != CPU_SUBTYPE_ARM64_ALL &&
1840 ofile->mh_cpusubtype != CPU_SUBTYPE_ARM64_V8)
1841 continue;
1843 else if(cmd_flags.arch_only_flag.cpusubtype !=
1844 ofile->mh_cpusubtype)
1845 continue;
1847 break;
1851 #ifdef LTO_SUPPORT
1852 else if(ofile->lto != NULL){
1854 * If -arch_only is specified then only add this file if it matches
1855 * the architecture specified.
1857 if(cmd_flags.arch_only_flag.name != NULL){
1858 if(cmd_flags.arch_only_flag.cputype != ofile->lto_cputype)
1859 return;
1860 if(cmd_flags.arch_only_flag.cputype == CPU_TYPE_ARM ||
1861 cmd_flags.arch_only_flag.cputype == CPU_TYPE_X86_64){
1862 if(cmd_flags.arch_only_flag.cpusubtype !=
1863 ofile->lto_cpusubtype)
1864 return;
1866 if(cmd_flags.arch_only_flag.cputype == CPU_TYPE_ARM64){
1867 if(cmd_flags.arch_only_flag.cpusubtype ==
1868 CPU_SUBTYPE_ARM64_ALL){
1869 if(ofile->lto_cpusubtype != CPU_SUBTYPE_ARM64_ALL &&
1870 ofile->lto_cpusubtype != CPU_SUBTYPE_ARM64_V8)
1871 return;
1873 else if(cmd_flags.arch_only_flag.cpusubtype !=
1874 ofile->lto_cpusubtype)
1875 return;
1879 for( ; i < narchs; i++){
1880 if(archs[i].arch_flag.cputype == ofile->lto_cputype){
1881 if((archs[i].arch_flag.cputype == CPU_TYPE_ARM ||
1882 archs[i].arch_flag.cputype == CPU_TYPE_X86_64) &&
1883 archs[i].arch_flag.cpusubtype != ofile->lto_cpusubtype)
1884 continue;
1885 if(cmd_flags.arch_only_flag.cputype == CPU_TYPE_ARM64){
1886 if(cmd_flags.arch_only_flag.cpusubtype ==
1887 CPU_SUBTYPE_ARM64_ALL &&
1888 (ofile->lto_cpusubtype != CPU_SUBTYPE_ARM64_ALL &&
1889 ofile->lto_cpusubtype != CPU_SUBTYPE_ARM64_V8))
1890 continue;
1891 else if(cmd_flags.arch_only_flag.cpusubtype !=
1892 ofile->lto_cpusubtype)
1893 continue;
1895 break;
1899 #endif /* LTO_SUPPORT */
1900 if(narchs == 1 && archs[0].arch_flag.cputype == 0){
1901 i = 0;
1903 else if(i == narchs){
1904 archs = reallocate(archs, sizeof(struct arch) * (narchs+1));
1905 memset(archs + narchs, '\0', sizeof(struct arch));
1906 if(ofile->mh != NULL ||
1907 ofile->mh64 != NULL){
1908 if(ofile->mh_cputype == CPU_TYPE_ARM ||
1909 ofile->mh_cputype == CPU_TYPE_ARM64 ||
1910 ofile->mh_cputype == CPU_TYPE_X86_64){
1911 archs[narchs].arch_flag.name = (char *)
1912 get_arch_name_from_types(
1913 ofile->mh_cputype, ofile->mh_cpusubtype);
1914 archs[narchs].arch_flag.cputype = ofile->mh_cputype;
1915 archs[narchs].arch_flag.cpusubtype = ofile->mh_cpusubtype;
1917 else{
1918 family_arch_flag =
1919 get_arch_family_from_cputype(ofile->mh_cputype);
1920 if(family_arch_flag != NULL)
1921 archs[narchs].arch_flag = *family_arch_flag;
1924 #ifdef LTO_SUPPORT
1925 else if(ofile->lto != NULL){
1926 if(ofile->lto_cputype == CPU_TYPE_ARM ||
1927 ofile->lto_cputype == CPU_TYPE_ARM64 ||
1928 ofile->lto_cputype == CPU_TYPE_X86_64){
1929 archs[narchs].arch_flag.name = (char *)
1930 get_arch_name_from_types(
1931 ofile->lto_cputype, ofile->lto_cpusubtype);
1932 archs[narchs].arch_flag.cputype = ofile->lto_cputype;
1933 archs[narchs].arch_flag.cpusubtype = ofile->lto_cpusubtype;
1935 else{
1936 family_arch_flag =
1937 get_arch_family_from_cputype(ofile->lto_cputype);
1938 if(family_arch_flag != NULL)
1939 archs[narchs].arch_flag = *family_arch_flag;
1942 #endif /* LTO_SUPPORT */
1943 else
1944 archs[narchs].arch_flag.name = "unknown";
1945 narchs++;
1947 arch = archs + i;
1950 * If the cputype of this arch is not yet known then see if this new
1951 * member can determine it.
1953 if(arch->arch_flag.cputype == 0 &&
1954 (ofile->mh != NULL || ofile->mh64 != NULL)){
1955 family_arch_flag = get_arch_family_from_cputype(ofile->mh_cputype);
1956 if(family_arch_flag != NULL){
1957 arch->arch_flag = *family_arch_flag;
1959 else{
1960 arch->arch_flag.name =
1961 savestr("cputype 1234567890 cpusubtype 1234567890");
1962 if(arch->arch_flag.name != NULL)
1963 sprintf(arch->arch_flag.name, "cputype %u cpusubtype %u",
1964 ofile->mh_cputype, ofile->mh_cpusubtype &
1965 ~CPU_SUBTYPE_MASK);
1966 arch->arch_flag.cputype = ofile->mh_cputype;
1967 arch->arch_flag.cpusubtype = ofile->mh_cpusubtype;
1970 #ifdef LTO_SUPPORT
1971 if(arch->arch_flag.cputype == 0 &&
1972 (ofile->lto != NULL)){
1973 family_arch_flag = get_arch_family_from_cputype(ofile->lto_cputype);
1974 if(family_arch_flag != NULL){
1975 arch->arch_flag = *family_arch_flag;
1977 else{
1978 arch->arch_flag.name =
1979 savestr("cputype 1234567890 cpusubtype 1234567890");
1980 if(arch->arch_flag.name != NULL)
1981 sprintf(arch->arch_flag.name, "cputype %u cpusubtype %u",
1982 ofile->lto_cputype, ofile->lto_cpusubtype &
1983 ~CPU_SUBTYPE_MASK);
1984 arch->arch_flag.cputype = ofile->lto_cputype;
1985 arch->arch_flag.cpusubtype = ofile->lto_cpusubtype;
1988 #endif /* LTO_SUPPORT */
1990 /* create a member in this arch type for this member */
1991 arch->members = reallocate(arch->members, sizeof(struct member) *
1992 (arch->nmembers + 1));
1993 member = arch->members + arch->nmembers;
1994 memset(member, '\0', sizeof(struct member));
1995 arch->nmembers++;
1997 /* fill in the member for this ofile */
1998 member->input_file_name = ofile->file_name;
2000 if(ofile->member_ar_hdr == NULL){
2002 * We are creating an archive member in the output file from a
2003 * file (that is not archive member in an input file). First get
2004 * the base name the file_name for the member name.
2006 p = strrchr(ofile->file_name, '/');
2007 if(p != NULL)
2008 p++;
2009 else
2010 p = ofile->file_name;
2011 member->input_base_name = p;
2012 member->input_base_name_size = strlen(p);
2013 member->member_name = member->input_base_name;
2015 * If we can use long names then force using them to allow 64-bit
2016 * objects to be aligned on an 8 byte boundary. This is needed
2017 * since the struct ar_hdr is not a multiple of 8. This is normally
2018 * done if the name does not fit in the archive header or contains
2019 * a space character then we use the extened format #1. The size
2020 * of the name is rounded up so the object file after the name will
2021 * be on an 8 byte boundary (including rounding the size of the
2022 * struct ar_hdr). The name will be padded with '\0's when it is
2023 * written out.
2025 if(cmd_flags.use_long_names == TRUE){
2026 member->output_long_name = TRUE;
2027 member->member_name_size = member->input_base_name_size;
2028 ar_name_size = rnd(member->input_base_name_size, 8) +
2029 (rnd(sizeof(struct ar_hdr), 8) -
2030 sizeof(struct ar_hdr));
2031 sprintf(ar_name_buf, "%s%-*lu", AR_EFMT1,
2032 (int)(sizeof(member->ar_hdr.ar_name) -
2033 (sizeof(AR_EFMT1) - 1)),
2034 (long unsigned int)ar_name_size);
2035 memcpy(member->ar_hdr.ar_name, ar_name_buf,
2036 sizeof(member->ar_hdr.ar_name));
2038 else{
2039 ar_name_size = 0;
2040 member->output_long_name = FALSE;
2042 * Truncate the file_name if needed and place in archive header.
2044 c = '\0';
2045 if(strlen(p) > sizeof(member->ar_hdr.ar_name)){
2046 c = p[sizeof(member->ar_hdr.ar_name)];
2047 p[sizeof(member->ar_hdr.ar_name)] = '\0';
2049 sprintf((char *)(&member->ar_hdr), "%-*s",
2050 (int)sizeof(member->ar_hdr.ar_name), p);
2051 if(c != '\0')
2052 p[sizeof(member->ar_hdr.ar_name)] = c;
2053 member->member_name_size = size_ar_name(&member->ar_hdr);
2055 if(zero_ar_date == TRUE)
2056 stat_buf.st_mtime = 0;
2058 * Create the rest of the archive header after the name.
2060 sprintf((char *)(&member->ar_hdr) + sizeof(member->ar_hdr.ar_name),
2061 "%-*ld%-*u%-*u%-*o%-*ld%-*s",
2062 (int)sizeof(member->ar_hdr.ar_date),
2063 (long int)stat_buf.st_mtime,
2064 (int)sizeof(member->ar_hdr.ar_uid),
2065 (unsigned short)stat_buf.st_uid,
2066 (int)sizeof(member->ar_hdr.ar_gid),
2067 (unsigned short)stat_buf.st_gid,
2068 (int)sizeof(member->ar_hdr.ar_mode),
2069 (unsigned int)stat_buf.st_mode,
2070 (int)sizeof(member->ar_hdr.ar_size),
2071 (long)size + ar_name_size,
2072 (int)sizeof(member->ar_hdr.ar_fmag),
2073 ARFMAG);
2075 else{
2077 * We are creating an archive member in the output file from an
2078 * archive member in an input file. There can be some changes to
2079 * the contents. First the size might be changed and the contents
2080 * padded with '\n's to round it to a multiple of 8
2081 * Second we may take a member using extended format #1
2082 * for it's name and truncate it then place the name in the archive
2083 * header. Or we may round the name size to a multiple of 8.
2085 member->input_ar_hdr = ofile->member_ar_hdr;
2086 member->input_base_name = ofile->member_name;
2087 member->input_base_name_size = ofile->member_name_size;
2088 member->input_member_offset = ofile->member_offset -
2089 sizeof(struct ar_hdr);
2090 if(strncmp(ofile->member_ar_hdr->ar_name, AR_EFMT1,
2091 sizeof(AR_EFMT1) - 1) == 0)
2092 member->input_member_offset -= ofile->member_name_size;
2094 member->ar_hdr = *(ofile->member_ar_hdr);
2095 member->member_name = ofile->member_name;
2097 if(cmd_flags.use_long_names == TRUE){
2099 * We can use long names. So if the input ofile is using the
2100 * extended format #1 we need make sure the size of the name and
2101 * the size of struct ar_hdr are rounded to 8 bytes. And write
2102 * that size into the ar_name with the AR_EFMT1 string. To
2103 * avoid growing the size of names first trim the long name size
2104 * before rounding up.
2106 if(ofile->member_name != ofile->member_ar_hdr->ar_name){
2107 member->output_long_name = TRUE;
2108 member->member_name_size = ofile->member_name_size;
2109 for(ar_name_size = member->member_name_size;
2110 ar_name_size > 1 ;
2111 ar_name_size--){
2112 if(ofile->member_name[ar_name_size - 1] != '\0')
2113 break;
2115 member->member_name_size = ar_name_size;
2116 ar_name_size = rnd(ar_name_size, 8) +
2117 (rnd(sizeof(struct ar_hdr), 8) -
2118 sizeof(struct ar_hdr));
2119 sprintf(ar_name_buf, "%s%-*lu", AR_EFMT1,
2120 (int)(sizeof(member->ar_hdr.ar_name) -
2121 (sizeof(AR_EFMT1) - 1)),
2122 (long unsigned int)ar_name_size);
2123 memcpy(member->ar_hdr.ar_name, ar_name_buf,
2124 sizeof(member->ar_hdr.ar_name));
2126 else{
2128 * Since we can use long names force this to use extended
2129 * format #1. And round the name size to 8 plus the size of
2130 * struct ar_hdr rounded to 8 bytes.
2132 member->member_name_size = size_ar_name(&member->ar_hdr);
2133 ar_name_size = rnd(ofile->member_name_size, 8) +
2134 (rnd(sizeof(struct ar_hdr), 8) -
2135 sizeof(struct ar_hdr));
2136 member->output_long_name = TRUE;
2137 sprintf(ar_name_buf, "%s%-*lu", AR_EFMT1,
2138 (int)(sizeof(member->ar_hdr.ar_name) -
2139 (sizeof(AR_EFMT1) - 1)),
2140 (long unsigned int)ar_name_size);
2141 memcpy(member->ar_hdr.ar_name, ar_name_buf,
2142 sizeof(member->ar_hdr.ar_name));
2145 else{
2147 * We can't use long names. So if the input ofile is using the
2148 * extended format #1 we need to truncate the name and write it
2149 * into the ar_name field. Note the extended format is also
2150 * used it the name has a space in it so it may be shorter than
2151 * sizeof(ar_hdr.ar_name) .
2153 ar_name_size = 0;
2154 member->output_long_name = FALSE;
2155 if(ofile->member_name != ofile->member_ar_hdr->ar_name){
2156 for(j = 0; j < sizeof(member->ar_hdr.ar_name) &&
2157 j < ofile->member_name_size &&
2158 ofile->member_name[j] != '\0'; j++)
2159 member->ar_hdr.ar_name[j] = ofile->member_name[j];
2160 for( ; j < sizeof(member->ar_hdr.ar_name); j++)
2161 member->ar_hdr.ar_name[j] = ' ';
2163 member->member_name_size = size_ar_name(&member->ar_hdr);
2166 * Since sprintf() writes a '\0' at the end of the string the
2167 * memcpy is needed to preserve the ARFMAG string that follows.
2169 sprintf(ar_size_buf, "%-*ld",
2170 (int)sizeof(member->ar_hdr.ar_size),
2171 (long)size + ar_name_size);
2172 memcpy(member->ar_hdr.ar_size, ar_size_buf,
2173 sizeof(member->ar_hdr.ar_size));
2176 member->offset = arch->size;
2177 arch->size += sizeof(struct ar_hdr) + size + ar_name_size;
2179 if(ofile->mh != NULL ||
2180 ofile->mh64 != NULL){
2181 member->object_addr = ofile->object_addr;
2182 member->object_size = ofile->object_size;
2183 member->object_byte_sex = ofile->object_byte_sex;
2184 member->mh = ofile->mh;
2185 member->mh64 = ofile->mh64;
2186 member->load_commands = ofile->load_commands;
2188 #ifdef LTO_SUPPORT
2189 else if(ofile->file_type == OFILE_LLVM_BITCODE){
2190 member->object_addr = ofile->file_addr;
2191 member->object_size = ofile->file_size;
2192 member->lto_contents = TRUE;
2193 save_lto_member_toc_info(member, ofile->lto);
2194 lto_free(ofile->lto);
2195 ofile->lto = NULL;
2196 member->object_byte_sex = get_byte_sex_from_flag(&arch->arch_flag);
2198 else if((ofile->file_type == OFILE_FAT &&
2199 ofile->arch_type == OFILE_LLVM_BITCODE) ||
2200 (ofile->file_type == OFILE_ARCHIVE &&
2201 ofile->member_type == OFILE_FAT &&
2202 ofile->arch_type == OFILE_LLVM_BITCODE)){
2203 member->object_addr = ofile->object_addr;
2204 member->object_size = ofile->object_size;
2205 member->lto_contents = TRUE;
2206 save_lto_member_toc_info(member, ofile->lto);
2207 lto_free(ofile->lto);
2208 ofile->lto = NULL;
2209 member->object_byte_sex = get_byte_sex_from_flag(&arch->arch_flag);
2211 #endif /* LTO_SUPPORT */
2212 else{
2213 member->object_addr = ofile->member_addr;
2214 member->object_size = ofile->member_size;
2215 #ifdef LTO_SUPPORT
2216 if(ofile->lto != NULL){
2217 member->lto_contents = TRUE;
2218 save_lto_member_toc_info(member, ofile->lto);
2219 lto_free(ofile->lto);
2220 ofile->lto = NULL;
2221 member->object_byte_sex = get_byte_sex_from_flag(
2222 &arch->arch_flag);
2224 #endif /* LTO_SUPPORT */
2229 * free_archs() frees the memory allocated that is pointed to by archs.
2231 static
2232 void
2233 free_archs(
2234 void)
2236 uint32_t i;
2238 for(i = 0 ; i < narchs; i++){
2240 * Just leak memory on the arch_flag.name in some cases
2241 * (unknown archiectures only where the space is malloced and
2242 * a sprintf() is done into the memory)
2244 if(archs[i].tocs != NULL)
2245 free(archs[i].tocs);
2246 if(archs[i].toc_ranlibs != NULL)
2247 free(archs[i].toc_ranlibs);
2248 if(archs[i].toc_strings != NULL)
2249 free(archs[i].toc_strings);
2250 if(archs[i].members != NULL)
2251 free(archs[i].members);
2253 if(archs != NULL)
2254 free(archs);
2255 archs = NULL;
2256 narchs = 0;
2260 * create_library() creates a library from the data structure pointed to by
2261 * archs into the specified output file. Only when more than one architecture
2262 * is in archs will a fat file be created.
2264 * In the case of cmd_flags.ranlib == TRUE the ofile may not be NULL if it
2265 * from a thin archive. If so and the toc_* fields are set and we may update
2266 * the table of contents in place if the new one fits where the old table of
2267 * contents was.
2269 static
2270 void
2271 create_library(
2272 char *output,
2273 struct ofile *ofile)
2275 uint32_t i, j, k, pad;
2276 uint64_t library_size, offset, *time_offsets;
2277 enum byte_sex target_byte_sex;
2278 char *library, *p, *flush_start;
2279 kern_return_t r;
2280 struct arch *arch;
2281 struct fat_header *fat_header;
2282 struct fat_arch *fat_arch;
2283 int fd;
2284 #ifndef __OPENSTEP__
2285 struct utimbuf timep;
2286 #else
2287 time_t timep[2];
2288 #endif
2289 struct stat stat_buf;
2290 struct ar_hdr toc_ar_hdr;
2291 enum bool some_tocs, same_toc, different_offsets;
2293 if(narchs == 0){
2294 if(cmd_flags.ranlib == TRUE){
2295 if(cmd_flags.q == FALSE)
2296 warning("empty library: %s (no table of contents added)",
2297 output);
2298 return;
2300 else{
2301 if(cmd_flags.dynamic == FALSE ||
2302 cmd_flags.no_files_ok == FALSE){
2303 if(cmd_flags.arch_only_flag.name != NULL)
2304 error("no library created (no object files in input "
2305 "files matching -arch_only %s)",
2306 cmd_flags.arch_only_flag.name);
2307 else
2308 error("no library created (no object files in input "
2309 "files)");
2310 return;
2315 if(cmd_flags.dynamic == TRUE){
2316 create_dynamic_shared_library(output);
2317 return;
2320 /* if this is libtool warn about duplicate member names */
2321 if(cmd_flags.ranlib == FALSE)
2322 warn_duplicate_member_names();
2325 * Calculate the total size of the library and the final size of each
2326 * architecture.
2328 if(narchs > 1){
2329 library_size = sizeof(struct fat_header) +
2330 sizeof(struct fat_arch) * narchs;
2332 * The ar(1) program uses the -q flag to ranlib(1) to add a table
2333 * of contents only of the output is not a fat file. This is done
2334 * by default for UNIX standards conformance when the files are
2335 * thin .o files.
2337 if(cmd_flags.q == TRUE)
2338 exit(EXIT_SUCCESS);
2340 * The ar(1) program uses the -f to ranlib(1) when it see the 's'
2341 * option. And if we are creating a fat file issue a warning that
2342 * ar(1) will not be able to use it.
2344 if(cmd_flags.f == TRUE)
2345 warning("archive library: %s will be fat and ar(1) will not "
2346 "be able to operate on it", output);
2348 else
2349 library_size = 0;
2350 some_tocs = FALSE;
2351 for(i = 0; i < narchs; i++){
2352 if(narchs > 1 && (archs[i].arch_flag.cputype & CPU_ARCH_ABI64))
2353 library_size = rnd(library_size, 1 << 3);
2354 make_table_of_contents(archs + i, output);
2355 if(errors != 0)
2356 return;
2357 if(archs[i].toc_nranlibs != 0)
2358 some_tocs = TRUE;
2359 archs[i].size += SARMAG + archs[i].toc_size;
2360 library_size += archs[i].size;
2363 * The ar(1) program uses the -q flag to ranlib(1) to add a table of
2364 * contents only of the output contains some object files. This is
2365 * done for UNIX standards conformance.
2367 if(cmd_flags.q == TRUE && some_tocs == FALSE)
2368 exit(EXIT_SUCCESS);
2371 * If this is ranlib(1) and we are running in UNIX standard mode and
2372 * the file is not writeable just print and error message and return.
2374 if(cmd_flags.ranlib == TRUE &&
2375 get_unix_standard_mode() == TRUE &&
2376 access(output, W_OK) == -1){
2377 system_error("file: %s is not writable", output);
2378 return;
2382 * If this is ranlib(1) and we have a thin archive that has an existing
2383 * table of contents see if we have enough room to update it in place.
2384 * Actually we check to see that we have the exact same number of
2385 * ranlib structs and string size, as this is the most common case that
2386 * the defined global symbols have not changed when rebuilding and it
2387 * will just be the offset to archive members that will have changed.
2389 if(cmd_flags.ranlib == TRUE && narchs == 1 &&
2390 ofile != NULL && ofile->toc_addr != NULL &&
2391 ofile->toc_bad == FALSE &&
2392 archs[0].toc_nranlibs == ofile->toc_nranlibs &&
2393 archs[0].toc_strsize == ofile->toc_strsize){
2396 * If the table of contents in the input does have a long name and
2397 * the one we built does not (or vice a versa) then don't update it
2398 * in place.
2400 if(strcmp(ofile->toc_ar_hdr->ar_name, AR_EFMT1) == 0){
2401 if(archs[0].toc_long_name != TRUE)
2402 goto fail_to_update_toc_in_place;
2404 else{
2405 if(archs[0].toc_long_name == TRUE)
2406 goto fail_to_update_toc_in_place;
2410 * The existing thin archive may not be laid out the same way as
2411 * libtool(1) would do it. As ar(1) does not know to pad things
2412 * so object files are on their natural alignment. So check to
2413 * see if the offsets are not the same and if the alignment is OK.
2415 different_offsets = FALSE;
2416 for(i = 0; i < archs[0].nmembers; i++){
2417 if(archs[0].members[i].input_member_offset !=
2418 archs[0].members[i].offset){
2419 different_offsets = TRUE;
2421 * For now we will allow alignments of 4 bytes offsets even
2422 * though we would produce 8 byte alignments.
2424 if(archs[0].members[i].input_member_offset % 4 != 0){
2425 goto fail_to_update_toc_in_place;
2431 * The time_offsets array records the offsets to the table of
2432 * contents archive header's ar_date fields. In this case we just
2433 * have one since this is a thin file (non-fat) file.
2435 time_offsets = allocate(1 * sizeof(uint64_t));
2437 * Calculate the offset to the archive header's time field for the
2438 * table of contents.
2440 time_offsets[0] = SARMAG +
2441 ((char *)&toc_ar_hdr.ar_date - (char *)&toc_ar_hdr);
2444 * If we had different member offsets in the input thin archive
2445 * we adjust the ranlib structs ran_off to use them.
2447 if(different_offsets == TRUE){
2448 same_toc = FALSE;
2449 for(i = 0; i < archs[0].toc_nranlibs; i++){
2450 for(j = 0; j < archs[0].nmembers; j++){
2451 if(archs[0].members[j].offset ==
2452 archs[0].toc_ranlibs[i].ran_off){
2453 archs[0].toc_ranlibs[i].ran_off =
2454 archs[0].members[j].input_member_offset;
2455 break;
2460 else{
2462 * If the new table of contents and the new string table are the
2463 * same as the old then the archive only needs to be "touched"
2464 * and the time field of the toc needs to be updated.
2466 same_toc = TRUE;
2467 for(i = 0; i < archs[0].toc_nranlibs; i++){
2468 if(archs[0].toc_ranlibs[i].ran_un.ran_strx !=
2469 ofile->toc_ranlibs[i].ran_un.ran_strx ||
2470 archs[0].toc_ranlibs[i].ran_off !=
2471 ofile->toc_ranlibs[i].ran_off){
2472 same_toc = FALSE;
2473 break;
2476 if(same_toc == TRUE){
2477 for(i = 0; i < archs[0].toc_strsize; i++){
2478 if(archs[0].toc_strings[i] != ofile->toc_strings[i]){
2479 same_toc = FALSE;
2480 break;
2486 library_size = SARMAG;
2487 if(same_toc == FALSE)
2488 library_size += archs[0].toc_size;
2489 if((r = vm_allocate(mach_task_self(), (vm_address_t *)&library,
2490 library_size, TRUE)) != KERN_SUCCESS)
2491 mach_fatal(r, "can't vm_allocate() buffer for output file: %s "
2492 "of size %llu", output, library_size);
2495 /* put in the archive magic string in the buffer */
2496 p = library;
2497 memcpy(p, ARMAG, SARMAG);
2498 p += SARMAG;
2500 /* put the table of contents in the buffer if needed */
2501 target_byte_sex = get_target_byte_sex(archs + 0, host_byte_sex);
2502 if(same_toc == FALSE)
2503 p = put_toc_member(p, archs+0, host_byte_sex, target_byte_sex);
2505 if((fd = open(output, O_WRONLY, 0)) == -1){
2506 system_error("can't open output file: %s", output);
2507 return;
2509 if(write(fd, library, library_size) != (int)library_size){
2510 system_error("can't write output file: %s", output);
2511 return;
2513 if(close(fd) == -1){
2514 system_fatal("can't close output file: %s", output);
2515 return;
2517 goto update_toc_ar_dates;
2519 fail_to_update_toc_in_place:
2522 * This buffer is vm_allocate'ed to make sure all holes are filled with
2523 * zero bytes.
2525 if((r = vm_allocate(mach_task_self(), (vm_address_t *)&library,
2526 library_size, TRUE)) != KERN_SUCCESS)
2527 mach_fatal(r, "can't vm_allocate() buffer for output file: %s of "
2528 "size %llu", output, library_size);
2531 * Create the output file. The unlink() is done to handle the problem
2532 * when the outputfile is not writable but the directory allows the
2533 * file to be removed (since the file may not be there the return code
2534 * of the unlink() is ignored).
2536 (void)unlink(output);
2537 if((fd = open(output, O_WRONLY | O_CREAT | O_TRUNC, 0666)) == -1){
2538 system_error("can't create output file: %s", output);
2539 return;
2541 #ifdef F_NOCACHE
2542 /* tell filesystem to NOT cache the file when reading or writing */
2543 (void)fcntl(fd, F_NOCACHE, 1);
2544 #endif
2547 * If there is more than one architecture then fill in the fat file
2548 * header and the fat_arch structures in the buffer.
2550 if(narchs > 1){
2551 fat_header = (struct fat_header *)library;
2552 fat_header->magic = FAT_MAGIC;
2553 fat_header->nfat_arch = narchs;
2554 offset = sizeof(struct fat_header) +
2555 sizeof(struct fat_arch) * narchs;
2556 fat_arch = (struct fat_arch *)(library + sizeof(struct fat_header));
2557 for(i = 0; i < narchs; i++){
2558 fat_arch[i].cputype = archs[i].arch_flag.cputype;
2559 fat_arch[i].cpusubtype = archs[i].arch_flag.cpusubtype;
2560 if(offset > UINT32_MAX)
2561 error("file too large to create as a fat file because "
2562 "offset field in struct fat_arch is only 32-bits and "
2563 "offset (%llu) to architecture %s exceeds that",
2564 offset, archs[i].arch_flag.name);
2565 if(fat_arch[i].cputype & CPU_ARCH_ABI64)
2566 fat_arch[i].align = 3;
2567 else
2568 fat_arch[i].align = 2;
2569 offset = rnd(offset, 1 << fat_arch[i].align);
2570 fat_arch[i].offset = offset;
2571 if(archs[i].size > UINT32_MAX)
2572 error("file too large to create as a fat file because "
2573 "size field in struct fat_arch is only 32-bits and "
2574 "size (%llu) of architecture %s exceeds that",
2575 archs[i].size, archs[i].arch_flag.name);
2576 fat_arch[i].size = archs[i].size;
2577 offset += archs[i].size;
2579 if(errors != 0){
2580 (void)unlink(output);
2581 return;
2583 #ifdef __LITTLE_ENDIAN__
2584 swap_fat_header(fat_header, BIG_ENDIAN_BYTE_SEX);
2585 swap_fat_arch(fat_arch, narchs, BIG_ENDIAN_BYTE_SEX);
2586 #endif /* __LITTLE_ENDIAN__ */
2587 offset = sizeof(struct fat_header) +
2588 sizeof(struct fat_arch) * narchs;
2590 else
2591 offset = 0;
2593 /* flush out the fat headers if any */
2594 output_flush(library, library_size, fd, 0, offset);
2597 * The time_offsets array records the offsets to the table of conternts
2598 * archive header's ar_date fields.
2600 time_offsets = allocate(narchs * sizeof(uint64_t));
2603 * Now put each arch in the buffer.
2605 for(i = 0; i < narchs; i++){
2606 arch = archs + i;
2607 if(narchs > 1 && (arch->arch_flag.cputype & CPU_ARCH_ABI64)){
2608 pad = rnd(offset, 1 << 3) - offset;
2609 output_flush(library, library_size, fd, offset, pad);
2610 offset = rnd(offset, 1 << 3);
2612 p = library + offset;
2613 flush_start = p;
2616 * If the input files only contains non-object files then the
2617 * byte sex of the output can't be determined which is needed for
2618 * the two binary long's of the table of contents. But since these
2619 * will be zero (the same in both byte sexes) because there are no
2620 * symbols in the table of contents if there are no object files.
2623 /* put in the archive magic string */
2624 memcpy(p, ARMAG, SARMAG);
2625 p += SARMAG;
2628 * Warn for what really is a bad library that has an empty table of
2629 * contents but this is allowed in the original ranlib.
2631 if(arch->toc_nranlibs == 0 && cmd_flags.q == FALSE){
2632 if(narchs > 1)
2633 warning("warning for library: %s for architecture: %s the "
2634 "table of contents is empty (no object file members"
2635 " in the library define global symbols)", output,
2636 arch->arch_flag.name);
2637 else
2638 warning("warning for library: %s the table of contents is "
2639 "empty (no object file members in the library "
2640 "define global symbols)", output);
2644 * Pick the byte sex to write the table of contents in.
2646 target_byte_sex = get_target_byte_sex(arch, host_byte_sex);
2649 * Remember the offset to the archive header's time field for this
2650 * arch's table of contents member.
2652 time_offsets[i] =
2653 (p - library) +
2654 ((char *)&toc_ar_hdr.ar_date - (char *)&toc_ar_hdr);
2657 * Put in the table of contents member in the output buffer.
2659 p = put_toc_member(p, arch, host_byte_sex, target_byte_sex);
2661 output_flush(library, library_size, fd, flush_start - library,
2662 p - flush_start);
2665 * Put in the archive header and member contents for each member.
2667 for(j = 0; j < arch->nmembers; j++){
2668 flush_start = p;
2669 memcpy(p, (char *)&(arch->members[j].ar_hdr),
2670 sizeof(struct ar_hdr));
2671 p += sizeof(struct ar_hdr);
2674 * If we are using extended format #1 for long names write out
2675 * the name. Note the name is padded with '\0' and the
2676 * member_name_size is the unrounded size.
2678 if(arch->members[j].output_long_name == TRUE){
2679 strncpy(p, arch->members[j].member_name,
2680 arch->members[j].member_name_size);
2681 p += rnd(arch->members[j].member_name_size, 8) +
2682 (rnd(sizeof(struct ar_hdr), 8) -
2683 sizeof(struct ar_hdr));
2687 * ofile_map swaps the headers to the host_byte_sex if the
2688 * object's byte sex is not the same as the host byte sex so
2689 * if this is the case swap them back before writing them out.
2691 if(arch->members[j].mh != NULL &&
2692 arch->members[j].object_byte_sex != host_byte_sex){
2693 if(swap_object_headers(arch->members[j].mh,
2694 arch->members[j].load_commands) == FALSE)
2695 fatal("internal error: swap_object_headers() failed");
2697 else if(arch->members[j].mh64 != NULL &&
2698 arch->members[j].object_byte_sex != host_byte_sex){
2699 if(swap_object_headers(arch->members[j].mh64,
2700 arch->members[j].load_commands) == FALSE)
2701 fatal("internal error: swap_object_headers() failed");
2703 memcpy(p, arch->members[j].object_addr,
2704 arch->members[j].object_size);
2705 #ifdef VM_SYNC_DEACTIVATE
2706 vm_msync(mach_task_self(),
2707 (vm_address_t)arch->members[j].object_addr,
2708 (vm_size_t)arch->members[j].object_size,
2709 VM_SYNC_DEACTIVATE);
2710 #endif /* VM_SYNC_DEACTIVATE */
2711 p += arch->members[j].object_size;
2712 pad = rnd(arch->members[j].object_size, 8) -
2713 arch->members[j].object_size;
2714 /* as with the UNIX ar(1) program pad with '\n' characters */
2715 for(k = 0; k < pad; k++)
2716 *p++ = '\n';
2718 output_flush(library, library_size, fd, flush_start - library,
2719 p - flush_start);
2721 offset += arch->size;
2725 * Write the library to the file or flush the remaining buffer to the
2726 * file.
2728 if(cmd_flags.noflush == TRUE){
2729 if(write(fd, library, library_size) != (int)library_size){
2730 system_error("can't write output file: %s", output);
2731 return;
2734 else{
2735 final_output_flush(library, fd);
2737 if(close(fd) == -1){
2738 system_fatal("can't close output file: %s", output);
2739 return;
2742 update_toc_ar_dates:
2744 * Now that the library is created on the file system it is written
2745 * to get the time for the file on that file system.
2747 if(stat(output, &stat_buf) == -1){
2748 system_fatal("can't stat file output file: %s", output);
2749 return;
2751 if((fd = open(output, O_WRONLY, 0)) == -1){
2752 system_error("can't open output file: %s", output);
2753 return;
2755 if(zero_ar_date == TRUE)
2756 stat_buf.st_mtime = 0;
2758 * With the time from the file system the library is on set the ar_date
2759 * using the modification time returned by stat. Then write this into
2760 * all the ar_date's in the file.
2762 sprintf((char *)(&toc_ar_hdr), "%-*s%-*ld",
2763 (int)sizeof(toc_ar_hdr.ar_name),
2764 SYMDEF,
2765 (int)sizeof(toc_ar_hdr.ar_date),
2766 (long int)stat_buf.st_mtime + 5);
2767 for(i = 0; i < narchs; i++){
2768 if(lseek(fd, time_offsets[i], L_SET) == -1){
2769 system_error("can't lseek in output file: %s", output);
2770 return;
2772 if(write(fd, &toc_ar_hdr.ar_date, sizeof(toc_ar_hdr.ar_date)) !=
2773 sizeof(toc_ar_hdr.ar_date)){
2774 system_error("can't write to output file: %s", output);
2775 return;
2778 if(close(fd) == -1){
2779 system_fatal("can't close output file: %s", output);
2780 return;
2783 * Now set the modtime of the created library back to it's stat time
2784 * when we first closed it.
2786 #ifndef __OPENSTEP__
2787 timep.actime = stat_buf.st_mtime;
2788 timep.modtime = stat_buf.st_mtime;
2789 if(utime(output, &timep) == -1)
2790 #else
2791 timep[0] = stat_buf.st_mtime;
2792 timep[1] = stat_buf.st_mtime;
2793 if(utime(output, timep) == -1)
2794 #endif
2796 system_fatal("can't set the modifiy times in output file: %s",
2797 output);
2798 return;
2800 if((r = vm_deallocate(mach_task_self(), (vm_address_t)library,
2801 library_size)) != KERN_SUCCESS){
2802 my_mach_error(r, "can't vm_deallocate() buffer for output file");
2803 return;
2808 * get_target_byte_sex() pick the byte sex to write the table of contents in
2809 * for the arch.
2811 static
2812 enum byte_sex
2813 get_target_byte_sex(
2814 struct arch *arch,
2815 enum byte_sex host_byte_sex)
2817 uint32_t i;
2818 enum byte_sex target_byte_sex;
2820 target_byte_sex = UNKNOWN_BYTE_SEX;
2821 for(i = 0;
2822 i < arch->nmembers && target_byte_sex == UNKNOWN_BYTE_SEX;
2823 i++){
2824 target_byte_sex = arch->members[i].object_byte_sex;
2826 if(target_byte_sex == UNKNOWN_BYTE_SEX)
2827 target_byte_sex = host_byte_sex;
2828 return(target_byte_sex);
2832 * put_toc_member() put the contents member for arch into the buffer p and
2833 * returns the pointer to the buffer after the table of contents.
2834 * The table of contents member is:
2835 * the archive header
2836 * the archive member name (if using a long name)
2837 * a uint32_t for the number of bytes of the ranlib structs
2838 * the ranlib structs
2839 * a uint32_t for the number of bytes of the strings for the
2840 * ranlibs
2841 * the strings for the ranlib structs
2843 static
2844 char *
2845 put_toc_member(
2846 char *p,
2847 struct arch *arch,
2848 enum byte_sex host_byte_sex,
2849 enum byte_sex target_byte_sex)
2851 uint32_t l;
2853 memcpy(p, (char *)&arch->toc_ar_hdr, sizeof(struct ar_hdr));
2854 p += sizeof(struct ar_hdr);
2856 if(arch->toc_long_name == TRUE){
2857 memcpy(p, arch->toc_name, arch->toc_name_size);
2858 p += arch->toc_name_size +
2859 (rnd(sizeof(struct ar_hdr), 8) -
2860 sizeof(struct ar_hdr));
2863 l = arch->toc_nranlibs * sizeof(struct ranlib);
2864 if(target_byte_sex != host_byte_sex)
2865 l = SWAP_INT(l);
2866 memcpy(p, (char *)&l, sizeof(uint32_t));
2867 p += sizeof(uint32_t);
2869 if(target_byte_sex != host_byte_sex)
2870 swap_ranlib(arch->toc_ranlibs, arch->toc_nranlibs,
2871 target_byte_sex);
2872 memcpy(p, (char *)arch->toc_ranlibs,
2873 arch->toc_nranlibs * sizeof(struct ranlib));
2874 p += arch->toc_nranlibs * sizeof(struct ranlib);
2876 l = arch->toc_strsize;
2877 if(target_byte_sex != host_byte_sex)
2878 l = SWAP_INT(l);
2879 memcpy(p, (char *)&l, sizeof(uint32_t));
2880 p += sizeof(uint32_t);
2882 memcpy(p, (char *)arch->toc_strings, arch->toc_strsize);
2883 p += arch->toc_strsize;
2885 return(p);
2889 * output_flush() takes an offset and a size of part of the output library,
2890 * known in the comments as the new area, and causes any fully flushed pages to
2891 * be written to the library file the new area in combination with previous
2892 * areas created. The data structure output_blocks has ordered blocks of areas
2893 * that have been flushed which are maintained by this routine. Any area can
2894 * only be flushed once and an error will result is the new area overlaps with a
2895 * previously flushed area.
2897 static
2898 void
2899 output_flush(
2900 char *library,
2901 uint64_t library_size,
2902 int fd,
2903 uint64_t offset,
2904 uint64_t size)
2906 uint64_t write_offset, write_size, host_pagesize;
2907 struct block **p, *block, *before, *after;
2908 kern_return_t r;
2910 host_pagesize = 0x2000;
2912 if(cmd_flags.noflush == TRUE)
2913 return;
2915 if(offset + size > library_size)
2916 fatal("internal error: output_flush(offset = %llu, size = %llu) "
2917 "out of range for library_size = %llu", offset, size,
2918 library_size);
2920 #ifdef DEBUG
2921 if(cmd_flags.debug & (1 << 2))
2922 print_block_list();
2923 if(cmd_flags.debug & (1 << 1))
2924 printf("output_flush(offset = %llu, size %llu)", offset, size);
2925 #endif /* DEBUG */
2927 if(size == 0){
2928 #ifdef DEBUG
2929 if(cmd_flags.debug & (1 << 1))
2930 printf("\n");
2931 #endif /* DEBUG */
2932 return;
2936 * Search through the ordered output blocks to find the block before the
2937 * new area and after the new area if any exist.
2939 before = NULL;
2940 after = NULL;
2941 p = &(output_blocks);
2942 while(*p){
2943 block = *p;
2944 if(offset < block->offset){
2945 after = block;
2946 break;
2948 else{
2949 before = block;
2951 p = &(block->next);
2955 * Check for overlap of the new area with the block before and after the
2956 * new area if there are such blocks.
2958 if(before != NULL){
2959 if(before->offset + before->size > offset){
2960 warning("internal error: output_flush(offset = %llu, size = "
2961 "%llu) overlaps with flushed block(offset = %llu, "
2962 "size = %llu)", offset, size, before->offset,
2963 before->size);
2964 printf("calling abort()\n");
2965 abort();
2968 if(after != NULL){
2969 if(offset + size > after->offset){
2970 warning("internal error: output_flush(offset = %llu, size = "
2971 "%llu) overlaps with flushed block(offset = %llu, "
2972 "size = %llu)", offset, size, after->offset,
2973 after->size);
2974 printf("calling abort()\n");
2975 abort();
2980 * Now see how the new area fits in with the blocks before and after it
2981 * (that is does it touch both, one or the other or neither blocks).
2982 * For each case first the offset and size to write (write_offset and
2983 * write_size) are set for the area of full pages that can now be
2984 * written from the block. Then the area written in the block
2985 * (->written_offset and ->written_size) are set to reflect the total
2986 * area in the block now written. Then offset and size the block
2987 * refers to (->offset and ->size) are set to total area of the block.
2988 * Finally the links to others blocks in the list are adjusted if a
2989 * block is added or removed.
2991 * See if there is a block before the new area and the new area
2992 * starts at the end of that block.
2994 if(before != NULL && before->offset + before->size == offset){
2996 * See if there is also a block after the new area and the new area
2997 * ends at the start of that block.
2999 if(after != NULL && offset + size == after->offset){
3001 * This is the case where the new area exactly fill the area
3002 * between two existing blocks. The total area is folded into
3003 * the block before the new area and the block after the new
3004 * area is removed from the list.
3006 if(before->offset == 0 && before->written_size == 0){
3007 write_offset = 0;
3008 before->written_offset = 0;
3010 else
3011 write_offset =before->written_offset + before->written_size;
3012 if(after->written_size == 0)
3013 write_size = trnc(after->offset + after->size -
3014 write_offset, host_pagesize);
3015 else
3016 write_size = trnc(after->written_offset - write_offset,
3017 host_pagesize);
3018 if(write_size != 0){
3019 before->written_size += write_size;
3021 if(after->written_size != 0)
3022 before->written_size += after->written_size;
3023 before->size += size + after->size;
3025 /* remove the block after the new area */
3026 before->next = after->next;
3027 remove_block(after);
3029 else{
3031 * This is the case where the new area starts at the end of the
3032 * block just before it but does not end where the block after
3033 * it (if any) starts. The new area is folded into the block
3034 * before the new area.
3036 write_offset = before->written_offset + before->written_size;
3037 write_size = trnc(offset + size - write_offset, host_pagesize);
3038 if(write_size != 0)
3039 before->written_size += write_size;
3040 before->size += size;
3044 * See if the new area and the new area ends at the start of the block
3045 * after it (if any).
3047 else if(after != NULL && offset + size == after->offset){
3049 * This is the case where the new area ends at the begining of the
3050 * block just after it but does not start where the block before it.
3051 * (if any) ends. The new area is folded into this block after the
3052 * new area.
3054 write_offset = rnd(offset, host_pagesize);
3055 if(after->written_size == 0)
3056 write_size = trnc(after->offset + after->size - write_offset,
3057 host_pagesize);
3058 else
3059 write_size = trnc(after->written_offset - write_offset,
3060 host_pagesize);
3061 if(write_size != 0){
3062 after->written_offset = write_offset;
3063 after->written_size += write_size;
3065 else if(write_offset != after->written_offset){
3066 after->written_offset = write_offset;
3068 after->offset = offset;
3069 after->size += size;
3071 else{
3073 * This is the case where the new area neither starts at the end of
3074 * the block just before it (if any) or ends where the block after
3075 * it (if any) starts. A new block is created and the new area is
3076 * is placed in it.
3078 write_offset = rnd(offset, host_pagesize);
3079 write_size = trnc(offset + size - write_offset, host_pagesize);
3080 block = get_block();
3081 block->offset = offset;
3082 block->size = size;
3083 block->written_offset = write_offset;
3084 block->written_size = write_size;
3086 * Insert this block in the ordered list in the correct place.
3088 if(before != NULL){
3089 block->next = before->next;
3090 before->next = block;
3092 else{
3093 block->next = output_blocks;
3094 output_blocks = block;
3099 * Now if there are full pages to write write them to the output file.
3101 if(write_size != 0){
3102 #ifdef DEBUG
3103 if((cmd_flags.debug & (1 << 1)) || (cmd_flags.debug & (1 << 0)))
3104 printf(" writing (write_offset = %llu write_size = %llu)\n",
3105 write_offset, write_size);
3106 #endif /* DEBUG */
3107 lseek(fd, write_offset, L_SET);
3108 if(write(fd, library + write_offset, write_size) !=
3109 (int)write_size)
3110 system_fatal("can't write to output file");
3111 if((r = vm_deallocate(mach_task_self(), (vm_address_t)(library +
3112 write_offset), write_size)) != KERN_SUCCESS)
3113 mach_fatal(r, "can't vm_deallocate() buffer for output file");
3115 #ifdef DEBUG
3116 else{
3117 if(cmd_flags.debug & (1 << 1))
3118 printf(" no write\n");
3120 #endif /* DEBUG */
3124 * final_output_flush() flushes the last part of the last page of the object
3125 * file if it does not round out to exactly a page.
3127 static
3128 void
3129 final_output_flush(
3130 char *library,
3131 int fd)
3133 struct block *block;
3134 uint64_t write_offset, write_size;
3135 kern_return_t r;
3137 #ifdef DEBUG
3138 /* The compiler "warning: `write_offset' may be used uninitialized in */
3139 /* this function" can safely be ignored */
3140 write_offset = 0;
3141 if((cmd_flags.debug & (1 << 1)) || (cmd_flags.debug & (1 << 0))){
3142 printf("final_output_flush block_list:\n");
3143 print_block_list();
3145 #endif /* DEBUG */
3147 write_size = 0;
3148 block = output_blocks;
3149 if(block != NULL){
3150 if(block->offset != 0)
3151 fatal("internal error: first block not at offset 0");
3152 if(block->written_size != 0){
3153 if(block->written_offset != 0)
3154 fatal("internal error: first block written_offset not 0");
3155 write_offset = block->written_size;
3156 write_size = block->size - block->written_size;
3158 else{
3159 write_offset = block->offset;
3160 write_size = block->size;
3162 if(block->next != NULL)
3163 fatal("internal error: more than one block in final list");
3165 if(write_size != 0){
3166 #ifdef DEBUG
3167 if((cmd_flags.debug & (1 << 1)) || (cmd_flags.debug & (1 << 1)))
3168 printf(" writing (write_offset = %llu write_size = %llu)\n",
3169 write_offset, write_size);
3170 #endif /* DEBUG */
3171 lseek(fd, write_offset, L_SET);
3172 if(write(fd, library + write_offset, write_size) !=
3173 (int)write_size)
3174 system_fatal("can't write to output file");
3175 if((r = vm_deallocate(mach_task_self(), (vm_address_t)(library +
3176 write_offset), write_size)) != KERN_SUCCESS)
3177 mach_fatal(r, "can't vm_deallocate() buffer for output file");
3179 output_blocks = NULL;
3182 #ifdef DEBUG
3184 * print_block_list() prints the list of blocks. Used for debugging.
3186 static
3187 void
3188 print_block_list(void)
3190 struct block **p, *block;
3192 p = &(output_blocks);
3193 if(*p == NULL)
3194 printf("Empty block list\n");
3195 while(*p){
3196 block = *p;
3197 printf("block 0x%x\n", (unsigned int)block);
3198 printf(" offset %llu\n", block->offset);
3199 printf(" size %llu\n", block->size);
3200 printf(" written_offset %llu\n", block->written_offset);
3201 printf(" written_size %llu\n", block->written_size);
3202 printf(" next 0x%x\n", (unsigned int)(block->next));
3203 p = &(block->next);
3206 #endif /* DEBUG */
3209 * get_block() returns a pointer to a new block. This could be done by
3210 * allocating block of these placing them on a free list and and handing them
3211 * out. For the initial release of this code this number is typicly low and not
3212 * a big win so each block just allocated and free'ed.
3214 static
3215 struct block *
3216 get_block(void)
3218 struct block *block;
3220 block = allocate(sizeof(struct block));
3221 return(block);
3225 * remove_block() throws away the block specified. See comments in get_block().
3227 static
3228 void
3229 remove_block(
3230 struct block *block)
3232 free(block);
3236 * trnc() truncates the value 'v' to the power of two value 'r'. If v is
3237 * less than zero it returns zero.
3239 static
3240 uint32_t
3241 trnc(
3242 uint32_t v,
3243 uint32_t r)
3245 if(((int32_t)v) < 0)
3246 return(0);
3247 return(v & ~(r - 1));
3251 * create_dynamic_shared_library() creates a dynamic shared library from the
3252 * data structure pointed to by archs into the specified output file. Only
3253 * when more than one architecture is in archs will a fat file be created.
3255 static
3256 void
3257 create_dynamic_shared_library(
3258 char *output)
3260 uint32_t i, j;
3261 char *p, *filelist;
3262 struct stat stat_buf;
3263 enum bool use_force_cpusubtype_ALL;
3264 const struct arch_flag *family_arch_flag;
3267 * If there is more than one architecture setup a signal handler to
3268 * clean up the temporary files in case we get a signal.
3270 if(narchs > 1)
3271 signal(SIGINT, create_dynamic_shared_library_cleanup);
3274 * If -arch_only is specified with a specific cpusubtype other than the
3275 * family cpusubtype do not use -force_cpusubtype_ALL as the user wants
3276 * the output to be tagged with that cpusubtype.
3278 use_force_cpusubtype_ALL = TRUE;
3279 if(cmd_flags.arch_only_flag.name != NULL){
3280 family_arch_flag = get_arch_family_from_cputype(
3281 cmd_flags.arch_only_flag.cputype);
3282 if(family_arch_flag != NULL){
3283 if((family_arch_flag->cpusubtype & ~CPU_SUBTYPE_MASK) !=
3284 (cmd_flags.arch_only_flag.cpusubtype & ~CPU_SUBTYPE_MASK))
3285 use_force_cpusubtype_ALL = FALSE;
3290 * For each architecture run ld(1) -dylib to create the dynamic shared
3291 * library.
3293 for(i = 0; i < narchs || (i == 0 && narchs == 0); i++){
3294 reset_execute_list();
3295 add_execute_list_with_prefix("ld");
3296 if(narchs != 0 && cmd_flags.arch_only_flag.name == NULL)
3297 add_execute_list("-arch_multiple");
3298 if(archs != NULL){
3299 add_execute_list("-arch");
3300 if(use_force_cpusubtype_ALL == TRUE)
3301 add_execute_list(archs[i].arch_flag.name);
3302 else
3303 add_execute_list(cmd_flags.arch_only_flag.name);
3305 add_execute_list("-dylib");
3306 add_execute_list("-dynamic");
3307 if(cmd_flags.all_load_flag_specified == FALSE ||
3308 cmd_flags.all_load == TRUE)
3309 add_execute_list("-all_load");
3310 if(use_force_cpusubtype_ALL == TRUE)
3311 add_execute_list("-force_cpusubtype_ALL");
3312 add_execute_list("-no_arch_warnings");
3313 if(cmd_flags.seg1addr != NULL){
3314 add_execute_list("-seg1addr");
3315 add_execute_list(cmd_flags.seg1addr);
3317 if(cmd_flags.segs_read_only_addr != NULL){
3318 add_execute_list("-segs_read_only_addr");
3319 add_execute_list(cmd_flags.segs_read_only_addr);
3321 if(cmd_flags.segs_read_write_addr != NULL){
3322 add_execute_list("-segs_read_write_addr");
3323 add_execute_list(cmd_flags.segs_read_write_addr);
3325 if(cmd_flags.seg_addr_table != NULL){
3326 add_execute_list("-seg_addr_table");
3327 add_execute_list(cmd_flags.seg_addr_table);
3329 if(cmd_flags.seg_addr_table_filename != NULL){
3330 add_execute_list("-seg_addr_table_filename");
3331 add_execute_list(cmd_flags.seg_addr_table_filename);
3333 if(cmd_flags.compatibility != NULL){
3334 add_execute_list("-dylib_compatibility_version");
3335 add_execute_list(cmd_flags.compatibility);
3337 if(cmd_flags.current != NULL){
3338 add_execute_list("-dylib_current_version");
3339 add_execute_list(cmd_flags.current);
3341 if(cmd_flags.install_name != NULL){
3342 add_execute_list("-dylib_install_name");
3343 add_execute_list(cmd_flags.install_name);
3345 else{
3346 if(narchs > 1){
3347 add_execute_list("-dylib_install_name");
3348 add_execute_list(cmd_flags.output);
3351 for(j = 0; j < cmd_flags.nldflags; j++)
3352 add_execute_list(cmd_flags.ldflags[j]);
3353 for(j = 0; j < cmd_flags.nLdirs; j++)
3354 add_execute_list(cmd_flags.Ldirs[j]);
3356 // Support using libtool on a systems without the SDK in '/'. This
3357 // works because the shims that are included in 10.9 and forwards
3358 // automatically inject SDKROOT into the environment of the actual
3359 // tools. See <rdar://problem/14264125>.
3360 const char *sdkroot = getenv("SDKROOT");
3362 // If the SDKROOT environment variable is set and is an absolute
3363 // path, then see if we can find dylib1.o inside it and use that if
3364 // so.
3365 enum bool use_dashl_dylib1o = TRUE;
3366 if (sdkroot && sdkroot[0] == '/') {
3367 // Construct the path to the object file.
3368 char *sdk_dylib1o_path;
3369 int res = asprintf(&sdk_dylib1o_path, "%s/usr/lib/dylib1.o",
3370 sdkroot);
3371 if (res > 0 && sdk_dylib1o_path) {
3372 struct stat s;
3373 // Add the full path if it exists.
3374 if (stat(sdk_dylib1o_path, &s) == 0) {
3375 add_execute_list(sdk_dylib1o_path);
3376 use_dashl_dylib1o = FALSE;
3378 free(sdk_dylib1o_path);
3382 filelist = NULL;
3383 for(j = 0; j < cmd_flags.nfiles; j++){
3384 if(cmd_flags.filelist[j] == NULL){
3385 add_execute_list(cmd_flags.files[j]);
3387 else{
3388 if(cmd_flags.filelist[j] != filelist){
3389 add_execute_list("-filelist");
3390 add_execute_list(cmd_flags.filelist[j]);
3391 filelist = cmd_flags.filelist[j];
3395 if(narchs <= 1){
3396 add_execute_list("-o");
3397 add_execute_list(cmd_flags.output);
3399 else{
3400 add_execute_list("-o");
3401 add_execute_list(makestr(cmd_flags.output, ".libtool.",
3402 archs[i].arch_flag.name, NULL));
3403 if(cmd_flags.final_output_specified == FALSE){
3404 add_execute_list("-final_output");
3405 add_execute_list(cmd_flags.output);
3408 if(execute_list(cmd_flags.verbose) == 0)
3409 fatal("internal link edit command failed");
3412 * If there is more than one architecture then run lipo to put them
3413 * in a fat file.
3415 if(narchs > 1){
3416 reset_execute_list();
3417 add_execute_list_with_prefix("lipo");
3418 add_execute_list("-create");
3419 add_execute_list("-output");
3420 add_execute_list(cmd_flags.output);
3421 for(i = 0; i < narchs; i++){
3422 add_execute_list(makestr(cmd_flags.output, ".libtool.",
3423 archs[i].arch_flag.name, NULL));
3425 if(execute_list(cmd_flags.verbose) == 0)
3426 fatal("internal lipo command failed");
3427 for(i = 0; i < narchs; i++){
3428 p = makestr(cmd_flags.output, ".libtool.",
3429 archs[i].arch_flag.name, NULL);
3430 if(unlink(p) == -1){
3431 error("can't remove temporary file: %s", p);
3436 * If we are doing prebinding then run objcunique on the
3437 * output.
3439 if(cmd_flags.prebinding == TRUE){
3440 if(stat("/usr/bin/objcunique", &stat_buf) != -1){
3441 reset_execute_list();
3442 add_execute_list_with_prefix("objcunique");
3443 add_execute_list(cmd_flags.output);
3444 add_execute_list("-prebind");
3445 for(j = 0; j < cmd_flags.nLdirs; j++)
3446 add_execute_list(cmd_flags.Ldirs[j]);
3447 if(execute_list(cmd_flags.verbose) == 0)
3448 fatal("internal objcunique command failed");
3454 * create_dynamic_shared_library_cleanup() is the signal handler to remove the
3455 * temporary files if more than one arch is being used.
3457 static
3458 void
3459 create_dynamic_shared_library_cleanup(
3460 int sig)
3462 uint32_t i;
3464 for(i = 0; i < narchs; i++){
3465 (void)unlink(makestr(cmd_flags.output, ".libtool.",
3466 archs[i].arch_flag.name, NULL));
3468 exit(EXIT_FAILURE);
3472 * make_table_of_contents() make the table of contents for the specified arch
3473 * and fills in the toc_* fields in the arch. Output is the name of the output
3474 * file for error messages.
3476 static
3477 void
3478 make_table_of_contents(
3479 struct arch *arch,
3480 char *output)
3482 uint32_t i, j, k, r, s, nsects, ncmds, n_strx;
3483 struct member *member;
3484 struct load_command *lc;
3485 struct segment_command *sg;
3486 struct segment_command_64 *sg64;
3487 struct nlist *symbols;
3488 struct nlist_64 *symbols64;
3489 char *strings;
3490 enum bool sorted, is_toc_symbol;
3491 char *ar_name;
3492 struct section *section;
3493 struct section_64 *section64;
3494 uint8_t n_type, n_sect;
3495 #ifdef LTO_SUPPORT
3496 char *lto_toc_string;
3497 #endif /* LTO_SUPPORT */
3499 symbols = NULL;
3500 symbols64 = NULL;
3502 * First pass over the members to count how many ranlib structs are
3503 * needed and the size of the strings in the toc that are needed.
3505 for(i = 0; i < arch->nmembers; i++){
3506 member = arch->members + i;
3507 if(member->mh != NULL || member->mh64 != NULL){
3508 nsects = 0;
3509 lc = member->load_commands;
3510 if(member->mh != NULL)
3511 ncmds = member->mh->ncmds;
3512 else
3513 ncmds = member->mh64->ncmds;
3514 for(j = 0; j < ncmds; j++){
3515 if(lc->cmd == LC_SYMTAB){
3516 if(member->st == NULL)
3517 member->st = (struct symtab_command *)lc;
3519 else if(lc->cmd == LC_SEGMENT){
3520 sg = (struct segment_command *)lc;
3521 nsects += sg->nsects;
3523 else if(lc->cmd == LC_SEGMENT_64){
3524 sg64 = (struct segment_command_64 *)lc;
3525 nsects += sg64->nsects;
3527 lc = (struct load_command *)((char *)lc + lc->cmdsize);
3529 if(member->mh != NULL)
3530 member->sections = allocate(nsects *
3531 sizeof(struct section *));
3532 else
3533 member->sections64 = allocate(nsects *
3534 sizeof(struct section_64 *));
3535 nsects = 0;
3536 lc = member->load_commands;
3537 for(j = 0; j < ncmds; j++){
3538 if(lc->cmd == LC_SEGMENT){
3539 sg = (struct segment_command *)lc;
3540 section = (struct section *)
3541 ((char *)sg + sizeof(struct segment_command));
3542 for(k = 0; k < sg->nsects; k++){
3543 member->sections[nsects++] = section++;
3546 else if(lc->cmd == LC_SEGMENT_64){
3547 sg64 = (struct segment_command_64 *)lc;
3548 section64 = (struct section_64 *)
3549 ((char *)sg64 + sizeof(struct segment_command_64));
3550 for(k = 0; k < sg64->nsects; k++){
3551 member->sections64[nsects++] = section64++;
3554 lc = (struct load_command *)((char *)lc + lc->cmdsize);
3556 if(member->st != NULL && member->st->nsyms != 0){
3557 if(member->mh != NULL){
3558 symbols = (struct nlist *)(member->object_addr +
3559 member->st->symoff);
3560 if(member->object_byte_sex != get_host_byte_sex())
3561 swap_nlist(symbols, member->st->nsyms,
3562 get_host_byte_sex());
3564 else{
3565 symbols64 = (struct nlist_64 *)(member->object_addr +
3566 member->st->symoff);
3567 if(member->object_byte_sex != get_host_byte_sex())
3568 swap_nlist_64(symbols64, member->st->nsyms,
3569 get_host_byte_sex());
3571 strings = member->object_addr + member->st->stroff;
3572 for(j = 0; j < member->st->nsyms; j++){
3573 if(member->mh != NULL){
3574 n_strx = symbols[j].n_un.n_strx;
3575 n_type = symbols[j].n_type;
3576 n_sect = symbols[j].n_sect;
3578 else{
3579 n_strx = symbols64[j].n_un.n_strx;
3580 n_type = symbols64[j].n_type;
3581 n_sect = symbols64[j].n_sect;
3583 if(n_strx > member->st->strsize){
3584 warn_member(arch, member, "malformed object "
3585 "(symbol %u n_strx field extends past the "
3586 "end of the string table)", j);
3587 errors++;
3588 continue;
3590 if((n_type & N_TYPE) == N_SECT){
3591 if(n_sect == NO_SECT){
3592 warn_member(arch, member, "malformed object "
3593 "(symbol %u must not have NO_SECT for its "
3594 "n_sect field given its type (N_SECT))", j);
3595 errors++;
3596 continue;
3598 if(n_sect > nsects){
3599 warn_member(arch, member, "malformed object "
3600 "(symbol %u n_sect field greater than the "
3601 "number of sections in the file)", j);
3602 errors++;
3603 continue;
3606 if(member->mh != NULL)
3607 is_toc_symbol = toc_symbol(symbols + j,
3608 member->sections);
3609 else
3610 is_toc_symbol = toc_symbol_64(symbols64 + j,
3611 member->sections64);
3612 if(is_toc_symbol == TRUE){
3613 arch->toc_nranlibs++;
3614 arch->toc_strsize += strlen(strings + n_strx) + 1;
3618 else{
3619 if(cmd_flags.no_warning_for_no_symbols == FALSE)
3620 warn_member(arch, member, "has no symbols");
3623 #ifdef LTO_SUPPORT
3624 else if(member->lto_contents == TRUE){
3625 arch->toc_nranlibs += member->lto_toc_nsyms;
3626 arch->toc_strsize += member->lto_toc_strsize;
3628 #endif /* LTO_SUPPORT */
3629 else{
3630 if(cmd_flags.ranlib == FALSE){
3631 warn_member(arch, member, "is not an object file");
3632 errors++;
3636 if(errors != 0)
3637 return;
3640 * Allocate the space for the ranlib structs and strings for the
3641 * table of contents.
3643 arch->toc_ranlibs = allocate(sizeof(struct ranlib) *arch->toc_nranlibs);
3644 arch->tocs = allocate(sizeof(struct toc) * arch->toc_nranlibs);
3645 arch->toc_strsize = rnd(arch->toc_strsize, 8);
3646 arch->toc_strings = allocate(arch->toc_strsize);
3649 * Second pass over the members to fill in the ranlib structs and
3650 * the strings for the table of contents. The ran_name field is
3651 * filled in with a pointer to a string contained in arch->toc_strings
3652 * for easy sorting and conversion to an index. The ran_off field is
3653 * filled in with the member index plus one to allow marking with it's
3654 * negative value by check_sort_tocs() and easy conversion to the
3655 * real offset.
3657 r = 0;
3658 s = 0;
3659 for(i = 0; i < arch->nmembers; i++){
3660 member = arch->members + i;
3661 if(member->mh != NULL || member->mh64 != NULL){
3662 if(member->st != NULL && member->st->nsyms != 0){
3663 if(member->mh != NULL)
3664 symbols = (struct nlist *)(member->object_addr +
3665 member->st->symoff);
3666 else
3667 symbols64 = (struct nlist_64 *)(member->object_addr +
3668 member->st->symoff);
3669 strings = member->object_addr + member->st->stroff;
3670 for(j = 0; j < member->st->nsyms; j++){
3671 if(member->mh != NULL)
3672 n_strx = symbols[j].n_un.n_strx;
3673 else
3674 n_strx = symbols64[j].n_un.n_strx;
3675 if(n_strx > member->st->strsize)
3676 continue;
3677 if(member->mh != NULL)
3678 is_toc_symbol = toc_symbol(symbols + j,
3679 member->sections);
3680 else
3681 is_toc_symbol = toc_symbol_64(symbols64 + j,
3682 member->sections64);
3683 if(is_toc_symbol == TRUE){
3684 strcpy(arch->toc_strings + s,
3685 strings + n_strx);
3686 arch->tocs[r].name = arch->toc_strings + s;
3687 arch->tocs[r].index1 = i + 1;
3688 r++;
3689 s += strlen(strings + n_strx) + 1;
3692 if(member->object_byte_sex != get_host_byte_sex()){
3693 if(member->mh != NULL)
3694 swap_nlist(symbols, member->st->nsyms,
3695 member->object_byte_sex);
3696 else
3697 swap_nlist_64(symbols64, member->st->nsyms,
3698 member->object_byte_sex);
3702 #ifdef LTO_SUPPORT
3703 else if(member->lto_contents == TRUE){
3704 lto_toc_string = member->lto_toc_strings;
3705 for(j = 0; j < member->lto_toc_nsyms; j++){
3706 strcpy(arch->toc_strings + s, lto_toc_string);
3707 arch->tocs[r].name = arch->toc_strings + s;
3708 arch->tocs[r].index1 = i + 1;
3709 r++;
3710 s += strlen(lto_toc_string) + 1;
3711 lto_toc_string += strlen(lto_toc_string) + 1;
3714 #endif /* LTO_SUPPORT */
3718 * If the table of contents is to be sorted by symbol name then try to
3719 * sort it and leave it sorted if no duplicates.
3721 if(cmd_flags.s == TRUE){
3722 qsort(arch->tocs, arch->toc_nranlibs, sizeof(struct toc),
3723 (int (*)(const void *, const void *))toc_name_qsort);
3724 sorted = check_sort_tocs(arch, output, FALSE);
3725 if(sorted == FALSE){
3726 qsort(arch->tocs, arch->toc_nranlibs, sizeof(struct toc),
3727 (int (*)(const void *, const void *))toc_index1_qsort);
3728 arch->toc_name = SYMDEF;
3729 arch->toc_name_size = sizeof(SYMDEF) - 1;
3730 if(cmd_flags.use_long_names == TRUE){
3731 arch->toc_long_name = TRUE;
3733 * This assumes that "__.SYMDEF\0\0\0\0\0\0\0" is 16 bytes
3734 * and
3735 * (rnd(sizeof(struct ar_hdr), 8) - sizeof(struct ar_hdr)
3736 * is 4 bytes.
3738 ar_name = AR_EFMT1 "20";
3739 arch->toc_name_size = 16;
3740 arch->toc_name = SYMDEF "\0\0\0\0\0\0\0";
3742 else{
3743 arch->toc_long_name = FALSE;
3744 ar_name = arch->toc_name;
3747 else{
3749 * Since the SYMDEF_SORTED is "__.SYMDEF SORTED" which contains
3750 * a space, it should use extended format #1 if we can use long
3751 * names.
3753 arch->toc_name = SYMDEF_SORTED;
3754 arch->toc_name_size = sizeof(SYMDEF_SORTED) - 1;
3755 if(cmd_flags.use_long_names == TRUE){
3756 arch->toc_long_name = TRUE;
3758 * This assumes that "__.SYMDEF SORTED" is 16 bytes and
3759 * (rnd(sizeof(struct ar_hdr), 8) - sizeof(struct ar_hdr)
3760 * is 4 bytes.
3762 ar_name = AR_EFMT1 "20";
3764 else{
3765 arch->toc_long_name = FALSE;
3766 ar_name = arch->toc_name;
3770 else{
3771 sorted = FALSE;
3772 arch->toc_name = SYMDEF;
3773 arch->toc_name_size = sizeof(SYMDEF) - 1;
3774 if(cmd_flags.use_long_names == TRUE){
3775 arch->toc_long_name = TRUE;
3777 * This assumes that "__.SYMDEF\0\0\0\0\0\0\0" is 16 bytes and
3778 * (rnd(sizeof(struct ar_hdr), 8) - sizeof(struct ar_hdr)
3779 * is 4 bytes.
3781 ar_name = AR_EFMT1 "20";
3782 arch->toc_name_size = 16;
3783 arch->toc_name = SYMDEF "\0\0\0\0\0\0\0";
3785 else{
3786 arch->toc_long_name = FALSE;
3787 ar_name = arch->toc_name;
3792 * Now set the ran_off and ran_un.ran_strx fields of the ranlib structs.
3793 * To do this the size of the toc member must be know because it comes
3794 * first in the library. The size of the toc member is made up of the
3795 * sizeof an archive header struct (the size of the name if a long name
3796 * is used) then the toc which is (as defined in ranlib.h):
3797 * a uint32_t for the number of bytes of the ranlib structs
3798 * the ranlib structures
3799 * a uint32_t for the number of bytes of the strings
3800 * the strings
3802 arch->toc_size = sizeof(struct ar_hdr) +
3803 sizeof(uint32_t) +
3804 arch->toc_nranlibs * sizeof(struct ranlib) +
3805 sizeof(uint32_t) +
3806 arch->toc_strsize;
3807 /* add the size of the name is a long name is used */
3808 if(arch->toc_long_name == TRUE)
3809 arch->toc_size += arch->toc_name_size +
3810 (rnd(sizeof(struct ar_hdr), 8) -
3811 sizeof(struct ar_hdr));
3812 for(i = 0; i < arch->nmembers; i++)
3813 arch->members[i].offset += SARMAG + arch->toc_size;
3814 for(i = 0; i < arch->toc_nranlibs; i++){
3815 arch->toc_ranlibs[i].ran_un.ran_strx =
3816 arch->tocs[i].name - arch->toc_strings;
3817 arch->toc_ranlibs[i].ran_off =
3818 arch->members[arch->tocs[i].index1 - 1].offset;
3821 sprintf((char *)(&arch->toc_ar_hdr), "%-*s%-*ld%-*u%-*u%-*o%-*ld",
3822 (int)sizeof(arch->toc_ar_hdr.ar_name),
3823 ar_name,
3824 (int)sizeof(arch->toc_ar_hdr.ar_date),
3825 toc_time,
3826 (int)sizeof(arch->toc_ar_hdr.ar_uid),
3827 (unsigned short)getuid(),
3828 (int)sizeof(arch->toc_ar_hdr.ar_gid),
3829 (unsigned short)getgid(),
3830 (int)sizeof(arch->toc_ar_hdr.ar_mode),
3831 (unsigned int)toc_mode,
3832 (int)sizeof(arch->toc_ar_hdr.ar_size),
3833 (long)(arch->toc_size - sizeof(struct ar_hdr)));
3835 * This has to be done by hand because sprintf puts a null
3836 * at the end of the buffer.
3838 memcpy(arch->toc_ar_hdr.ar_fmag, ARFMAG,
3839 (int)sizeof(arch->toc_ar_hdr.ar_fmag));
3842 #ifdef LTO_SUPPORT
3844 * save_lto_member_toc_info() saves away the table of contents info for a
3845 * member that has lto_content. This allows the lto module to be disposed of
3846 * after reading to keep only on in memory at a time. As these turn out to
3847 * use a lot of memory.
3849 static
3850 void
3851 save_lto_member_toc_info(
3852 struct member *member,
3853 void *mod)
3855 uint32_t i, nsyms;
3856 char *s;
3858 member->lto_toc_nsyms = 0;
3859 nsyms = lto_get_nsyms(mod);
3860 for(i = 0; i < nsyms; i++){
3861 if(lto_toc_symbol(mod, i, cmd_flags.c) == TRUE){
3862 member->lto_toc_nsyms++;
3863 member->lto_toc_strsize += strlen(lto_symbol_name(mod, i)) + 1;
3866 member->lto_toc_strings = allocate(member->lto_toc_strsize);
3867 s = member->lto_toc_strings;
3868 for(i = 0; i < nsyms; i++){
3869 if(lto_toc_symbol(mod, i, cmd_flags.c) == TRUE){
3870 strcpy(s, lto_symbol_name(mod, i));
3871 s += strlen(lto_symbol_name(mod, i)) + 1;
3875 #endif /* LTO_SUPPORT */
3878 * Function for qsort() for comparing toc structures by name.
3880 static
3882 toc_name_qsort(
3883 const struct toc *toc1,
3884 const struct toc *toc2)
3886 return(strcmp(toc1->name, toc2->name));
3890 * Function for qsort() for comparing toc structures by index1.
3892 static
3894 toc_index1_qsort(
3895 const struct toc *toc1,
3896 const struct toc *toc2)
3898 if(toc1->index1 < toc2->index1)
3899 return(-1);
3900 if(toc1->index1 > toc2->index1)
3901 return(1);
3902 /* toc1->index1 == toc2->index1 */
3903 return(0);
3907 * toc_symbol() returns TRUE if the symbol is to be included in the table of
3908 * contents otherwise it returns FALSE.
3910 static
3911 enum bool
3912 toc_symbol(
3913 struct nlist *symbol,
3914 struct section **sections)
3916 return(toc(symbol->n_un.n_strx,
3917 symbol->n_type,
3918 symbol->n_value,
3919 (symbol->n_type & N_TYPE) == N_SECT &&
3920 sections[symbol->n_sect - 1]->flags & S_ATTR_NO_TOC));
3923 static
3924 enum bool
3925 toc_symbol_64(
3926 struct nlist_64 *symbol64,
3927 struct section_64 **sections64)
3929 return(toc(symbol64->n_un.n_strx,
3930 symbol64->n_type,
3931 symbol64->n_value,
3932 (symbol64->n_type & N_TYPE) == N_SECT &&
3933 sections64[symbol64->n_sect-1]->flags & S_ATTR_NO_TOC));
3936 static
3937 enum bool
3938 toc(
3939 uint32_t n_strx,
3940 uint8_t n_type,
3941 uint64_t n_value,
3942 enum bool attr_no_toc)
3944 /* if the name is NULL then it won't be in the table of contents */
3945 if(n_strx == 0)
3946 return(FALSE);
3947 /* if symbol is not external then it won't be in the toc */
3948 if((n_type & N_EXT) == 0)
3949 return(FALSE);
3950 /* if symbol is undefined then it won't be in the toc */
3951 if((n_type & N_TYPE) == N_UNDF && n_value == 0)
3952 return(FALSE);
3953 /* if symbol is common and the -c flag is not specified then ... */
3954 if((n_type & N_TYPE) == N_UNDF && n_value != 0 &&
3955 cmd_flags.c == FALSE)
3956 return(FALSE);
3957 /* if the symbols is in a section marked NO_TOC then ... */
3958 if(attr_no_toc != 0)
3959 return(FALSE);
3961 return(TRUE);
3965 * check_sort_tocs() checks the table of contents for the specified arch
3966 * which is sorted by name for more then one object defining the same symbol.
3967 * It this is the case it prints each symbol that is defined in more than one
3968 * object along with the object it is defined in. It returns TRUE if there are
3969 * no multiple definitions and FALSE otherwise.
3971 static
3972 enum bool
3973 check_sort_tocs(
3974 struct arch *arch,
3975 char *output,
3976 enum bool library_warnings)
3978 uint32_t i;
3979 enum bool multiple_defs;
3980 struct member *member;
3982 if(arch->toc_nranlibs == 0)
3983 return(TRUE);
3985 * Since the symbol table is sorted by name look to any two adjcent
3986 * entries with the same name. If such entries are found print them
3987 * only once (marked by changing the sign of their ran_off).
3989 multiple_defs = FALSE;
3990 for(i = 0; i < arch->toc_nranlibs - 1; i++){
3991 if(strcmp(arch->tocs[i].name, arch->tocs[i+1].name) == 0){
3992 if(multiple_defs == FALSE){
3993 if(library_warnings == FALSE)
3994 return(FALSE);
3995 fprintf(stderr, "%s: same symbol defined in more than one "
3996 "member ", progname);
3997 if(narchs > 1)
3998 fprintf(stderr, "for architecture: %s ",
3999 arch->arch_flag.name);
4000 fprintf(stderr, "in: %s (table of contents will not be "
4001 "sorted)\n", output);
4002 multiple_defs = TRUE;
4004 if((int)(arch->tocs[i].index1) > 0){
4005 member = arch->members + arch->tocs[i].index1 - 1;
4006 warn_member(arch, member, "defines symbol: %s",
4007 arch->tocs[i].name);
4008 arch->tocs[i].index1 =
4009 -(arch->tocs[i].index1);
4011 if((int)(arch->tocs[i+1].index1) > 0){
4012 member = arch->members + arch->tocs[i+1].index1 - 1;
4013 warn_member(arch, member, "defines symbol: %s",
4014 arch->tocs[i+1].name);
4015 arch->tocs[i+1].index1 =
4016 -(arch->tocs[i+1].index1);
4021 if(multiple_defs == FALSE)
4022 return(TRUE);
4023 else{
4024 for(i = 0; i < arch->toc_nranlibs; i++)
4025 if(((int)arch->tocs[i].index1) < 0)
4026 arch->tocs[i].index1 =
4027 -(arch->tocs[i].index1);
4028 return(FALSE);
4033 * warn_duplicate_member_names() generates a warning if two members end up with
4034 * the same ar_name. This is only a warning because ld(1) and this program
4035 * has no problems with it. Only if ar(1) were used to extract the files
4036 * would this be a problem (even the 4.4bsd ar(1) using long names can
4037 * get hosed by base names, the 4.3bsd ar(1) can't handle full 16 character
4038 * ar_names).
4040 static
4041 void
4042 warn_duplicate_member_names(
4043 void)
4045 uint32_t i, j, len, len1, len2;
4047 for(i = 0; i < narchs; i++){
4048 /* sort in order of ar_names */
4049 qsort(archs[i].members, archs[i].nmembers, sizeof(struct member),
4050 (int (*)(const void *, const void *))member_name_qsort);
4052 /* check for duplicate names */
4053 for(j = 0; j < archs[i].nmembers - 1; j++){
4054 len1 = archs[i].members[j].member_name_size;
4055 len2 = archs[i].members[j+1].member_name_size;
4056 len = len1 > len2 ? len1 : len2;
4057 if(strncmp(archs[i].members[j].member_name,
4058 archs[i].members[j+1].member_name,
4059 len) == 0){
4060 fprintf(stderr, "%s: warning ", progname);
4061 if(narchs > 1)
4062 fprintf(stderr, "for architecture: %s ",
4063 archs[i].arch_flag.name);
4064 fprintf(stderr, "same member name (%.*s) in output file "
4065 "used for input files: ", (int)len1,
4066 archs[i].members[j].member_name);
4068 if(archs[i].members[j].input_ar_hdr != NULL){
4069 len = archs[i].members[j].input_base_name_size;
4070 fprintf(stderr, "%s(%.*s) and: ",
4071 archs[i].members[j].input_file_name, (int)len,
4072 archs[i].members[j].input_base_name);
4074 else
4075 fprintf(stderr, "%s and: ",
4076 archs[i].members[j].input_file_name);
4078 if(archs[i].members[j+1].input_ar_hdr != NULL){
4079 len = archs[i].members[j+1].input_base_name_size;
4080 fprintf(stderr, "%s(%.*s) due to use of basename, "
4081 "truncation and blank padding\n",
4082 archs[i].members[j+1].input_file_name, (int)len,
4083 archs[i].members[j+1].input_base_name);
4085 else
4086 fprintf(stderr, "%s (due to use of basename, truncation"
4087 ", blank padding or duplicate input files)\n",
4088 archs[i].members[j+1].input_file_name);
4092 /* sort back in order of offset */
4093 qsort(archs[i].members, archs[i].nmembers, sizeof(struct member),
4094 (int (*)(const void *, const void *))member_offset_qsort);
4099 * Function for qsort() for comparing member structures by ar_hdr.ar_name.
4101 static
4103 member_name_qsort(
4104 const struct member *member1,
4105 const struct member *member2)
4107 uint32_t len, len1, len2;
4109 len1 = member1->member_name_size;
4110 len2 = member2->member_name_size;
4111 len = len1 > len2 ? len1 : len2;
4112 return(strncmp(member1->member_name, member2->member_name, len));
4116 * Function for qsort() for comparing member structures by offset.
4118 static
4120 member_offset_qsort(
4121 const struct member *member1,
4122 const struct member *member2)
4124 if(member1->offset < member2->offset)
4125 return(-1);
4126 if(member1->offset > member2->offset)
4127 return(1);
4128 /* member1->offset == member2->offset */
4129 return(0);
4133 * warn_member() is like the error routines it prints the program name the
4134 * member name specified and message specified.
4136 static
4137 void
4138 warn_member(
4139 struct arch *arch,
4140 struct member *member,
4141 const char *format, ...)
4143 va_list ap;
4145 fprintf(stderr, "%s: ", progname);
4146 if(narchs > 1)
4147 fprintf(stderr, "for architecture: %s ", arch->arch_flag.name);
4149 if(member->input_ar_hdr != NULL){
4150 fprintf(stderr, "file: %s(%.*s) ", member->input_file_name,
4151 (int)member->input_base_name_size, member->input_base_name);
4153 else
4154 fprintf(stderr, "file: %s ", member->input_file_name);
4156 va_start(ap, format);
4157 vfprintf(stderr, format, ap);
4158 fprintf(stderr, "\n");
4159 va_end(ap);
4163 * Prints the message to cmd_flags.trace_file_path, or stderr if that
4164 * isn't set.
4166 static
4167 void
4168 ld_trace(
4169 const char *format, ...)
4171 static int trace_file = -1;
4172 char trace_buffer[MAXPATHLEN * 2];
4173 char *buffer_ptr;
4174 int length;
4175 ssize_t amount_written;
4177 if(trace_file == -1){
4178 if(cmd_flags.trace_file_path != NULL){
4179 trace_file = open(cmd_flags.trace_file_path, O_WRONLY | O_APPEND | O_CREAT, 0666);
4180 if(trace_file == -1)
4181 error("Could not open or create trace file: %s\n", cmd_flags.trace_file_path);
4183 else{
4184 trace_file = fileno(stderr);
4187 va_list ap;
4189 va_start(ap, format);
4190 length = vsnprintf(trace_buffer, sizeof(trace_buffer), format, ap);
4191 va_end(ap);
4192 buffer_ptr = trace_buffer;
4193 while(length > 0){
4194 amount_written = write(trace_file, buffer_ptr, length);
4195 if(amount_written == -1)
4196 /* Failure to write shouldn't fail the build. */
4197 return;
4198 buffer_ptr += amount_written;
4199 length -= amount_written;