1/* 2 * Copyright (c) 1999-2003 Apple Computer, Inc. All Rights Reserved. 3 * 4 * @APPLE_LICENSE_HEADER_START@ 5 * 6 * This file contains Original Code and/or Modifications of Original Code 7 * as defined in and that are subject to the Apple Public Source License 8 * Version 2.0 (the 'License'). You may not use this file except in 9 * compliance with the License. Please obtain a copy of the License at 10 * http://www.opensource.apple.com/apsl/ and read it before using this 11 * file. 12 * 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. 20 * 21 * @APPLE_LICENSE_HEADER_END@ 22 */ 23/* 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. 27 */ 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 */ 54 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 61 62/* 63 * This is used internally to build the table of contents. 64 */ 65struct toc { 66 char *name; /* symbol defined by */ 67 int32_t index1; /* library member at this index plus 1 */ 68}; 69 70/* used by error routines as the name of the program */ 71char *progname = NULL; 72 73/* the bytesex of the host this program is running on */ 74static enum byte_sex host_byte_sex = UNKNOWN_BYTE_SEX; 75 76/* 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. 79 */ 80static time_t toc_time = 0; 81 82/* 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. 86 */ 87static enum bool zero_ar_date = FALSE; 88 89/* 90 * The mode of the table of contents member (S_IFREG | (0666 & ~umask)) 91 */ 92static u_short toc_mode = 0; 93 94/* flags set from the command line arguments */ 95struct 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}; 151static struct cmd_flags cmd_flags = { 0 }; 152 153/* The value of the environment variable NEXT_ROOT */ 154static char *next_root = NULL; 155 156/* the standard directories to search for -lx names */ 157char *standard_dirs[] = { 158 "/lib/", 159 "/usr/lib/", 160 "/usr/local/lib/", 161 NULL 162}; 163 164/* 165 * The input files are broken down in to their object files and then placed in 166 * these structures. They are sorted by architecture type and then each object 167 * has a member struct created for it in one of the arch structs. All of these 168 * structs hang off of 'archs'. 169 */ 170static struct arch *archs = NULL; 171static uint32_t narchs = 0; 172 173struct arch { 174 struct arch_flag arch_flag; /* the identifing info of this architecture */ 175 uint64_t size; /* current working size and final size */ 176 177 /* the table of contents (toc) stuff for this architecture in the library */ 178 uint32_t toc_size; /* total size of the toc including ar_hdr */ 179 struct ar_hdr toc_ar_hdr; /* the archive header for this member */ 180 enum bool toc_long_name; /* use the long name in the output */ 181 char *toc_name; /* name of toc member */ 182 uint32_t toc_name_size;/* size of name of toc member */ 183 struct toc *tocs; /* internal table of contents */ 184 struct ranlib *toc_ranlibs; /* ranlib structs for output */ 185 uint32_t toc_nranlibs;/* number of ranlib structs */ 186 char *toc_strings; /* strings of symbol names for ranlib structs */ 187 uint32_t toc_strsize; /* number of bytes for the strings above */ 188 189 /* the members of this architecture in the library */ 190 struct member *members; /* the members of the library for this arch */ 191 uint32_t nmembers; /* the number of the above members */ 192}; 193 194struct member { 195 uint32_t offset; /* current working offset and final offset*/ 196 struct ar_hdr ar_hdr; /* the archive header for this member */ 197 char null_byte; /* space to write '\0' for ar_hdr */ 198 char *object_addr; /* the address of the object file */ 199 uint32_t object_size; /* the size of the object file */ 200 enum byte_sex object_byte_sex; /* the byte sex of the object file */ 201 struct mach_header *mh; /* the mach_header of 32-bit object files */ 202 struct mach_header_64 *mh64; /* the mach_header of 64-bit object files */ 203 struct load_command /* the start of the load commands */ 204 *load_commands; 205 struct symtab_command *st; /* the symbol table command */ 206 struct section **sections; /* array of section structs for 32-bit */ 207 struct section_64 **sections64; /* array of section structs for 64-bit */ 208#ifdef LTO_SUPPORT 209 void *lto; /* lto module */ 210#endif /* LTO_SUPPORT */ 211 212 /* the name of the member in the output */ 213 char *member_name; /* the member name */ 214 uint32_t member_name_size; /* the size of the member name */ 215 enum bool output_long_name; /* use the extended format #1 for the 216 member name in the output */ 217 218 /* info recorded from the input file this member came from */ 219 char *input_file_name; /* the input file name */ 220 char *input_base_name; /* the base name in the input file */ 221 uint32_t input_base_name_size; /* the size of the base name */ 222 struct ar_hdr *input_ar_hdr; 223 uint32_t input_member_offset; /* if from a thin archive */ 224}; 225 226static void usage( 227 void); 228static void process( 229 void); 230static char *file_name_from_l_flag( 231 char *l_flag); 232static char *search_for_file( 233 char *base_name); 234static char * search_paths_for_lname( 235 const char *lname_argument); 236static char * search_path_for_lname( 237 const char *dir, 238 const char *lname_argument); 239static void add_member( 240 struct ofile *ofile); 241static void free_archs( 242 void); 243static void create_library( 244 char *output, 245 struct ofile *ofile); 246static enum byte_sex get_target_byte_sex( 247 struct arch *arch, 248 enum byte_sex host_byte_sex); 249static char *put_toc_member( 250 char *p, 251 struct arch *arch, 252 enum byte_sex host_byte_sex, 253 enum byte_sex target_byte_sex); 254static void create_dynamic_shared_library( 255 char *output); 256static void create_dynamic_shared_library_cleanup( 257 int sig); 258static void make_table_of_contents( 259 struct arch *arch, 260 char *output); 261static int toc_name_qsort( 262 const struct toc *toc1, 263 const struct toc *toc2); 264static int toc_index1_qsort( 265 const struct toc *toc1, 266 const struct toc *toc2); 267static enum bool toc_symbol( 268 struct nlist *symbol, 269 struct section **sections); 270static enum bool toc_symbol_64( 271 struct nlist_64 *symbol64, 272 struct section_64 **sections64); 273static enum bool toc( 274 uint32_t n_strx, 275 uint8_t n_type, 276 uint64_t n_value, 277 enum bool attr_no_toc); 278static enum bool check_sort_tocs( 279 struct arch *arch, 280 char *output, 281 enum bool library_warnings); 282static void warn_duplicate_member_names( 283 void); 284static int member_name_qsort( 285 const struct member *member1, 286 const struct member *member2); 287static int member_offset_qsort( 288 const struct member *member1, 289 const struct member *member2); 290static void warn_member( 291 struct arch *arch, 292 struct member *member, 293 const char *format, ...) __attribute__ ((format (printf, 3, 4))); 294static void ld_trace( 295 const char *format, ...) __attribute__ ((format (printf, 1, 2))); 296 297/* 298 * This structure is used to describe blocks of the output file that are flushed 299 * to the disk file with output_flush. It is kept in an ordered list starting 300 * with output_blocks. 301 */ 302static struct block { 303 uint64_t offset; /* starting offset of this block */ 304 uint64_t size; /* size of this block */ 305 uint64_t written_offset;/* first page offset after starting offset */ 306 uint64_t written_size; /* size of written area from written_offset */ 307 struct block *next; /* next block in the list */ 308} *output_blocks; 309 310static void output_flush( 311 char *library, 312 uint64_t library_size, 313 int fd, 314 uint64_t offset, 315 uint64_t size); 316static void final_output_flush( 317 char *library, 318 int fd); 319#ifdef DEBUG 320static void print_block_list(void); 321#endif /* DEBUG */ 322static struct block *get_block(void); 323static void remove_block( 324 struct block *block); 325static uint32_t trnc( 326 uint32_t v, 327 uint32_t r); 328 329/* apple_version is in vers.c which is created by the libstuff/Makefile */ 330extern char apple_version[]; 331 332int 333main( 334int argc, 335char **argv, 336char **envp) 337{ 338 char *p, *endp, *filelist, *dirname, *addr; 339 int fd, i; 340 struct stat stat_buf; 341 uint32_t j, nfiles, maxfiles; 342 uint32_t temp; 343 int oumask, numask; 344 enum bool lflags_seen, bad_flag_seen, Vflag; 345 346 lflags_seen = FALSE; 347 Vflag = FALSE; 348 progname = argv[0]; 349 350 host_byte_sex = get_host_byte_sex(); 351 352 /* 353 * The environment variable ZERO_AR_DATE is used here and other 354 * places that write archives to allow testing and comparing 355 * things for exact binary equality. 356 */ 357 if(getenv("ZERO_AR_DATE") == NULL) 358 zero_ar_date = FALSE; 359 else 360 zero_ar_date = TRUE; 361 if(zero_ar_date == FALSE) 362 toc_time = time(0); 363 else 364 toc_time = 0; 365 366 numask = 0; 367 oumask = umask(numask); 368 toc_mode = S_IFREG | (0666 & ~oumask); 369 (void)umask(oumask); 370 371 /* see if this is being run as ranlib */ 372 p = strrchr(argv[0], '/'); 373 if(p != NULL) 374 p++; 375 else 376 p = argv[0]; 377 if(strncmp(p, "ranlib", sizeof("ranlib") - 1) == 0) 378 cmd_flags.ranlib = TRUE; 379 380 /* The default is to used long names */ 381 cmd_flags.use_long_names = TRUE; 382 383 /* process the command line arguments and collect the files */ 384 maxfiles = argc; 385 cmd_flags.files = allocate(sizeof(char *) * maxfiles); 386 cmd_flags.filelist = allocate(sizeof(char *) * maxfiles); 387 memset(cmd_flags.filelist, '\0', sizeof(char *) * maxfiles); 388 for(i = 1; i < argc; i++){ 389 if(argv[i][0] == '-'){ 390 if(argv[i][1] == '\0'){ 391 for(i += 1 ; i < argc; i++) 392 cmd_flags.files[cmd_flags.nfiles++] = argv[i]; 393 break; 394 } 395 if(strcmp(argv[i], "-o") == 0){ 396 if(cmd_flags.ranlib == TRUE){ 397 error("unknown option: %s", argv[i]); 398 usage(); 399 } 400 if(i + 1 == argc){ 401 error("missing argument to: %s option", argv[i]); 402 usage(); 403 } 404 if(cmd_flags.output != NULL){ 405 error("more than one: %s option specified", argv[i]); 406 usage(); 407 } 408 cmd_flags.output = argv[i+1]; 409 i++; 410 } 411 else if(strcmp(argv[i], "-arch_only") == 0){ 412 if(cmd_flags.ranlib == TRUE){ 413 error("unknown option: %s", argv[i]); 414 usage(); 415 } 416 if(i + 1 == argc){ 417 error("missing argument to %s option", argv[i]); 418 usage(); 419 } 420 if(cmd_flags.arch_only_flag.name != NULL){ 421 error("more than one: %s option specified", argv[i]); 422 usage(); 423 } 424 else{ 425 if(get_arch_from_flag(argv[i+1], 426 &cmd_flags.arch_only_flag) == 0){ 427 error("unknown architecture specification flag: " 428 "%s %s", argv[i], argv[i+1]); 429 arch_usage(); 430 usage(); 431 } 432 } 433 i++; 434 } 435 else if(strcmp(argv[i], "-dynamic") == 0){ 436 if(cmd_flags.ranlib == TRUE){ 437 error("unknown option: %s", argv[i]); 438 usage(); 439 } 440 cmd_flags.dynamic = TRUE; 441 } 442 else if(strcmp(argv[i], "-static") == 0){ 443 if(cmd_flags.ranlib == TRUE){ 444 error("unknown option: %s", argv[i]); 445 usage(); 446 } 447 cmd_flags.dynamic = FALSE; 448 } 449 else if(strcmp(argv[i], "-filelist") == 0){ 450 if(cmd_flags.ranlib == TRUE){ 451 error("unknown option: %s", argv[i]); 452 usage(); 453 } 454 if(i + 1 == argc){ 455 error("missing argument to: %s option", argv[i]); 456 usage(); 457 } 458 filelist = argv[i + 1]; 459 dirname = strrchr(filelist, ','); 460 if(dirname != NULL){ 461 *dirname = '\0'; 462 dirname++; 463 } 464 else 465 dirname = ""; 466 if((fd = open(filelist, O_RDONLY, 0)) == -1) 467 system_fatal("can't open file list file: %s", filelist); 468 if(fstat(fd, &stat_buf) == -1) 469 system_fatal("can't stat file list file: %s", filelist); 470 /* 471 * For some reason mapping files with zero size fails 472 * so it has to be handled specially. 473 */ 474 addr = NULL; 475 if(stat_buf.st_size != 0){ 476 addr = mmap(0, stat_buf.st_size, PROT_READ|PROT_WRITE, 477 MAP_FILE|MAP_PRIVATE, fd, 0); 478 if((intptr_t)addr == -1) 479 system_error("can't map file list file: %s", 480 filelist); 481 } 482 else{ 483 fatal("file list file: %s is empty", filelist); 484 } 485 if(*dirname != '\0') 486 dirname[-1] = ','; 487 close(fd); 488 nfiles = 0; 489 for(j = 0; j < stat_buf.st_size; j++){ 490 if(addr[j] == '\n') 491 nfiles++; 492 } 493 if(addr[stat_buf.st_size - 1] != '\n') 494 nfiles++; 495 p = allocate((strlen(dirname) + 1) * nfiles + 496 stat_buf.st_size); 497 cmd_flags.files = reallocate(cmd_flags.files, 498 sizeof(char *) * (maxfiles + nfiles)); 499 cmd_flags.filelist = reallocate(cmd_flags.filelist, 500 sizeof(char *) * (maxfiles + nfiles)); 501 memset(cmd_flags.filelist + maxfiles, '\0', 502 sizeof(char *) * nfiles); 503 maxfiles += nfiles; 504 505 cmd_flags.files[cmd_flags.nfiles] = p; 506 cmd_flags.filelist[cmd_flags.nfiles] = filelist; 507 cmd_flags.nfiles++; 508 if(*dirname != '\0'){ 509 strcpy(p, dirname); 510 p += strlen(dirname); 511 *p++ = '/'; 512 } 513 for(j = 0; j < stat_buf.st_size; j++){ 514 if(addr[j] != '\n') 515 *p++ = addr[j]; 516 else{ 517 *p++ = '\0'; 518 if(j != stat_buf.st_size - 1){ 519 cmd_flags.files[cmd_flags.nfiles] = p; 520 cmd_flags.filelist[cmd_flags.nfiles] =argv[i+1]; 521 cmd_flags.nfiles++; 522 if(*dirname != '\0'){ 523 strcpy(p, dirname); 524 p += strlen(dirname); 525 *p++ = '/'; 526 } 527 } 528 } 529 } 530 if(addr[stat_buf.st_size - 1] != '\n') 531 *p = '\0'; 532 i++; 533 } 534 else if(strcmp(argv[i], "-compatibility_version") == 0){ 535 if(cmd_flags.ranlib == TRUE){ 536 error("unknown option: %s", argv[i]); 537 usage(); 538 } 539 if(i + 1 == argc){ 540 error("missing argument to: %s option", argv[i]); 541 usage(); 542 } 543 if(cmd_flags.compatibility != NULL){ 544 error("more than one: %s option specified", argv[i]); 545 usage(); 546 } 547 if(get_version_number(argv[i], argv[i+1], &temp) == FALSE){ 548 usage(); 549 } 550 cmd_flags.compatibility = argv[i+1]; 551 i++; 552 } 553 else if(strcmp(argv[i], "-current_version") == 0){ 554 if(cmd_flags.ranlib == TRUE){ 555 error("unknown option: %s", argv[i]); 556 usage(); 557 } 558 if(i + 1 == argc){ 559 error("missing argument to: %s option", argv[i]); 560 usage(); 561 } 562 if(cmd_flags.current != NULL){ 563 error("more than one: %s option specified", argv[i]); 564 usage(); 565 } 566 if(get_version_number(argv[i], argv[i+1], &temp) == FALSE){ 567 usage(); 568 } 569 cmd_flags.current = argv[i+1]; 570 i++; 571 } 572 else if(strcmp(argv[i], "-install_name") == 0){ 573 if(cmd_flags.ranlib == TRUE){ 574 error("unknown option: %s", argv[i]); 575 usage(); 576 } 577 if(i + 1 == argc){ 578 error("missing argument to: %s option", argv[i]); 579 usage(); 580 } 581 if(cmd_flags.install_name != NULL){ 582 error("more than one: %s option specified", argv[i]); 583 usage(); 584 } 585 cmd_flags.install_name = argv[i+1]; 586 i++; 587 } 588 else if(strcmp(argv[i], "-seg1addr") == 0 || 589 strcmp(argv[i], "-image_base") == 0){ 590 if(cmd_flags.ranlib == TRUE){ 591 error("unknown option: %s", argv[i]); 592 usage(); 593 } 594 if(i + 1 == argc){ 595 error("missing argument to: %s option", argv[i]); 596 usage(); 597 } 598 if(cmd_flags.seg1addr != NULL){ 599 error("more than one: %s option specified", argv[i]); 600 usage(); 601 } 602 temp = strtoul(argv[i + 1], &endp, 16); 603 if(*endp != '\0'){ 604 error("address for -seg1addr %s not a proper " 605 "hexadecimal number", argv[i+1]); 606 usage(); 607 } 608 cmd_flags.seg1addr = argv[i+1]; 609 i++; 610 } 611 else if(strcmp(argv[i], "-segs_read_only_addr") == 0){ 612 if(cmd_flags.ranlib == TRUE){ 613 error("unknown option: %s", argv[i]); 614 usage(); 615 } 616 if(i + 1 == argc){ 617 error("missing argument to: %s option", argv[i]); 618 usage(); 619 } 620 if(cmd_flags.segs_read_only_addr != NULL){ 621 error("more than one: %s option specified", argv[i]); 622 usage(); 623 } 624 temp = strtoul(argv[i + 1], &endp, 16); 625 if(*endp != '\0'){ 626 error("address for -segs_read_only_addr %s not a " 627 "proper hexadecimal number", argv[i+1]); 628 usage(); 629 } 630 cmd_flags.segs_read_only_addr = argv[i+1]; 631 i++; 632 } 633 else if(strcmp(argv[i], "-segs_read_write_addr") == 0){ 634 if(cmd_flags.ranlib == TRUE){ 635 error("unknown option: %s", argv[i]); 636 usage(); 637 } 638 if(i + 1 == argc){ 639 error("missing argument to: %s option", argv[i]); 640 usage(); 641 } 642 if(cmd_flags.segs_read_write_addr != NULL){ 643 error("more than one: %s option specified", argv[i]); 644 usage(); 645 } 646 temp = strtoul(argv[i + 1], &endp, 16); 647 if(*endp != '\0'){ 648 error("address for -segs_read_write_addr %s not a " 649 "proper hexadecimal number", argv[i+1]); 650 usage(); 651 } 652 cmd_flags.segs_read_write_addr = argv[i+1]; 653 i++; 654 } 655 else if(strcmp(argv[i], "-seg_addr_table") == 0){ 656 if(cmd_flags.ranlib == TRUE){ 657 error("unknown option: %s", argv[i]); 658 usage(); 659 } 660 if(i + 1 == argc){ 661 error("missing argument to: %s option", argv[i]); 662 usage(); 663 } 664 if(cmd_flags.seg_addr_table != NULL){ 665 error("more than one: %s option specified", argv[i]); 666 usage(); 667 } 668 cmd_flags.seg_addr_table = argv[i+1]; 669 i++; 670 } 671 else if(strcmp(argv[i], "-seg_addr_table_filename") == 0){ 672 if(cmd_flags.ranlib == TRUE){ 673 error("unknown option: %s", argv[i]); 674 usage(); 675 } 676 if(i + 1 == argc){ 677 error("missing argument to: %s option", argv[i]); 678 usage(); 679 } 680 if(cmd_flags.seg_addr_table_filename != NULL){ 681 error("more than one: %s option specified", argv[i]); 682 usage(); 683 } 684 cmd_flags.seg_addr_table_filename = argv[i+1]; 685 i++; 686 } 687 else if(strcmp(argv[i], "-syslibroot") == 0){ 688 if(cmd_flags.ranlib == TRUE){ 689 error("unknown option: %s", argv[i]); 690 usage(); 691 } 692 if(i + 1 == argc){ 693 error("missing argument to: %s option", argv[i]); 694 usage(); 695 } 696 if(next_root != NULL && strcmp(next_root, argv[i+1]) != 0){ 697 error("more than one: %s option specified", argv[i]); 698 usage(); 699 } 700 next_root = argv[i+1]; 701 cmd_flags.ldflags = reallocate(cmd_flags.ldflags, 702 sizeof(char *) * (cmd_flags.nldflags + 2)); 703 cmd_flags.ldflags[cmd_flags.nldflags++] = argv[i]; 704 cmd_flags.ldflags[cmd_flags.nldflags++] = argv[i+1]; 705 i++; 706 } 707 else if(strcmp(argv[i], "-sectcreate") == 0 || 708 strcmp(argv[i], "-segcreate") == 0 || 709 strcmp(argv[i], "-sectorder") == 0 || 710 strcmp(argv[i], "-sectalign") == 0 || 711 strcmp(argv[i], "-segprot") == 0){ 712 if(cmd_flags.ranlib == TRUE){ 713 error("unknown option: %s", argv[i]); 714 usage(); 715 } 716 if(i + 3 >= argc){ 717 error("not enough arguments follow %s", argv[i]); 718 usage(); 719 } 720 cmd_flags.ldflags = reallocate(cmd_flags.ldflags, 721 sizeof(char *) * (cmd_flags.nldflags + 4)); 722 cmd_flags.ldflags[cmd_flags.nldflags++] = argv[i]; 723 cmd_flags.ldflags[cmd_flags.nldflags++] = argv[i+1]; 724 cmd_flags.ldflags[cmd_flags.nldflags++] = argv[i+2]; 725 cmd_flags.ldflags[cmd_flags.nldflags++] = argv[i+3]; 726 if(strcmp(argv[i], "-sectcreate") == 0 || 727 strcmp(argv[i], "-segcreate") == 0) 728 cmd_flags.no_files_ok = TRUE; 729 i += 3; 730 } 731 else if(strcmp(argv[i], "-segalign") == 0 || 732 strcmp(argv[i], "-undefined") == 0 || 733 strcmp(argv[i], "-macosx_version_min") == 0 || 734 strcmp(argv[i], "-multiply_defined") == 0 || 735 strcmp(argv[i], "-multiply_defined_unused") == 0 || 736 strcmp(argv[i], "-umbrella") == 0 || 737 strcmp(argv[i], "-sub_umbrella") == 0 || 738 strcmp(argv[i], "-sub_library") == 0 || 739 strcmp(argv[i], "-allowable_client") == 0 || 740 strcmp(argv[i], "-read_only_relocs") == 0 || 741 strcmp(argv[i], "-init") == 0 || 742 strcmp(argv[i], "-U") == 0 || 743 strcmp(argv[i], "-Y") == 0 || 744 strcmp(argv[i], "-dylib_file") == 0 || 745 strcmp(argv[i], "-final_output") == 0 || 746 strcmp(argv[i], "-headerpad") == 0 || 747 strcmp(argv[i], "-weak_reference_mismatches") == 0 || 748 strcmp(argv[i], "-u") == 0 || 749 strcmp(argv[i], "-exported_symbols_list") == 0 || 750 strcmp(argv[i], "-unexported_symbols_list") == 0 || 751 strcmp(argv[i], "-executable_path") == 0){ 752 if(cmd_flags.ranlib == TRUE){ 753 error("unknown option: %s", argv[i]); 754 usage(); 755 } 756 if(i + 1 >= argc){ 757 error("not enough arguments follow %s", argv[i]); 758 usage(); 759 } 760 cmd_flags.ldflags = reallocate(cmd_flags.ldflags, 761 sizeof(char *) * (cmd_flags.nldflags + 2)); 762 cmd_flags.ldflags[cmd_flags.nldflags++] = argv[i]; 763 cmd_flags.ldflags[cmd_flags.nldflags++] = argv[i+1]; 764 if(strcmp(argv[i], "-final_output") == 0) 765 cmd_flags.final_output_specified = TRUE; 766 i += 1; 767 } 768 else if(strcmp(argv[i], "-sectorder_detail") == 0 || 769 strcmp(argv[i], "-Sn") == 0 || 770 strcmp(argv[i], "-Si") == 0 || 771 strcmp(argv[i], "-Sp") == 0 || 772 strcmp(argv[i], "-S") == 0 || 773 strcmp(argv[i], "-X") == 0 || 774 strcmp(argv[i], "-x") == 0 || 775 strcmp(argv[i], "-whatsloaded") == 0 || 776 strcmp(argv[i], "-whyload") == 0 || 777 strcmp(argv[i], "-arch_errors_fatal") == 0 || 778 strcmp(argv[i], "-run_init_lazily") == 0 || 779 strcmp(argv[i], "-twolevel_namespace") == 0 || 780 strcmp(argv[i], "-twolevel_namespace_hints") == 0 || 781 strcmp(argv[i], "-flat_namespace") == 0 || 782 strcmp(argv[i], "-nomultidefs") == 0 || 783 strcmp(argv[i], "-headerpad_max_install_names") == 0 || 784 strcmp(argv[i], "-prebind_all_twolevel_modules") == 0 || 785 strcmp(argv[i], "-prebind_allow_overlap") == 0 || 786 strcmp(argv[i], "-ObjC") == 0 || 787 strcmp(argv[i], "-M") == 0 || 788 strcmp(argv[i], "-t") == 0 || 789 strcmp(argv[i], "-single_module") == 0 || 790 strcmp(argv[i], "-multi_module") == 0 || 791 strcmp(argv[i], "-m") == 0 || 792 strcmp(argv[i], "-dead_strip") == 0 || 793 strcmp(argv[i], "-no_uuid") == 0 || 794 strcmp(argv[i], "-no_dead_strip_inits_and_terms") == 0){ 795 if(cmd_flags.ranlib == TRUE){ 796 error("unknown option: %s", argv[i]); 797 usage(); 798 } 799 cmd_flags.ldflags = reallocate(cmd_flags.ldflags, 800 sizeof(char *) * (cmd_flags.nldflags + 1)); 801 cmd_flags.ldflags[cmd_flags.nldflags++] = argv[i]; 802 } 803 else if(strcmp(argv[i], "-no_arch_warnings") == 0){ 804 if(cmd_flags.ranlib == TRUE){ 805 error("unknown option: %s", argv[i]); 806 usage(); 807 } 808 /* ignore this flag */ 809 } 810 else if(strcmp(argv[i], "-prebind") == 0){ 811 if(cmd_flags.ranlib == TRUE){ 812 error("unknown option: %s", argv[i]); 813 usage(); 814 } 815 if(cmd_flags.prebinding_flag_specified == TRUE && 816 cmd_flags.prebinding == FALSE){ 817 error("both -prebind and -noprebind can't be " 818 "specified"); 819 usage(); 820 } 821 cmd_flags.prebinding_flag_specified = TRUE; 822 cmd_flags.prebinding = TRUE; 823 cmd_flags.ldflags = reallocate(cmd_flags.ldflags, 824 sizeof(char *) * (cmd_flags.nldflags + 1)); 825 cmd_flags.ldflags[cmd_flags.nldflags++] = argv[i]; 826 } 827 else if(strcmp(argv[i], "-noprebind") == 0){ 828 if(cmd_flags.ranlib == TRUE){ 829 error("unknown option: %s", argv[i]); 830 usage(); 831 } 832 if(cmd_flags.prebinding_flag_specified == TRUE && 833 cmd_flags.prebinding == TRUE){ 834 error("both -prebind and -noprebind can't be " 835 "specified"); 836 usage(); 837 } 838 cmd_flags.prebinding_flag_specified = TRUE; 839 cmd_flags.prebinding = FALSE; 840 cmd_flags.ldflags = reallocate(cmd_flags.ldflags, 841 sizeof(char *) * (cmd_flags.nldflags + 1)); 842 cmd_flags.ldflags[cmd_flags.nldflags++] = argv[i]; 843 } 844 else if(strcmp(argv[i], "-all_load") == 0){ 845 if(cmd_flags.ranlib == TRUE){ 846 error("unknown option: %s", argv[i]); 847 usage(); 848 } 849 if(cmd_flags.all_load_flag_specified == TRUE && 850 cmd_flags.all_load == FALSE){ 851 error("both -all_load and -noall_load can't be " 852 "specified"); 853 usage(); 854 } 855 cmd_flags.all_load_flag_specified = TRUE; 856 cmd_flags.all_load = TRUE; 857 } 858 else if(strcmp(argv[i], "-noall_load") == 0){ 859 if(cmd_flags.ranlib == TRUE){ 860 error("unknown option: %s", argv[i]); 861 usage(); 862 } 863 if(cmd_flags.all_load_flag_specified == TRUE && 864 cmd_flags.all_load == TRUE){ 865 error("both -all_load and -noall_load can't be " 866 "specified"); 867 usage(); 868 } 869 cmd_flags.all_load_flag_specified = TRUE; 870 cmd_flags.all_load = FALSE; 871 } 872 else if(strncmp(argv[i], "-y", 2) == 0 || 873 strncmp(argv[i], "-i", 2) == 0){ 874 if(cmd_flags.ranlib == TRUE){ 875 error("unknown option: %s", argv[i]); 876 usage(); 877 } 878 if(strncmp(argv[i], "-i", 2) == 0) 879 cmd_flags.no_files_ok = TRUE; 880 cmd_flags.ldflags = reallocate(cmd_flags.ldflags, 881 sizeof(char *) * (cmd_flags.nldflags + 1)); 882 cmd_flags.ldflags[cmd_flags.nldflags++] = argv[i]; 883 } 884 else if(argv[i][1] == 'l'){ 885 if(cmd_flags.ranlib == TRUE){ 886 error("unknown option: %s", argv[i]); 887 usage(); 888 } 889 if(argv[i][2] == '\0'){ 890 error("-l: name missing"); 891 usage(); 892 } 893 cmd_flags.files[cmd_flags.nfiles++] = argv[i]; 894 lflags_seen = TRUE; 895 } 896 else if(strncmp(argv[i], "-weak-l", 7) == 0){ 897 if(cmd_flags.ranlib == TRUE){ 898 error("unknown option: %s", argv[i]); 899 usage(); 900 } 901 if(argv[i][7] == '\0'){ 902 error("-weak-l: name missing"); 903 usage(); 904 } 905 cmd_flags.files[cmd_flags.nfiles++] = argv[i]; 906 lflags_seen = TRUE; 907 } 908 else if(strcmp(argv[i], "-framework") == 0 || 909 strcmp(argv[i], "-weak_framework") == 0 || 910 strcmp(argv[i], "-weak_library") == 0){ 911 if(cmd_flags.ranlib == TRUE){ 912 error("unknown option: %s", argv[i]); 913 usage(); 914 } 915 if(i + 1 >= argc){ 916 error("not enough arguments follow %s", argv[i]); 917 usage(); 918 } 919 cmd_flags.files[cmd_flags.nfiles++] = argv[i]; 920 cmd_flags.files[cmd_flags.nfiles++] = argv[i+1]; 921 lflags_seen = TRUE; 922 i += 1; 923 } 924 else if(strcmp(argv[i], "-T") == 0){ 925 if(cmd_flags.L_or_T_specified == TRUE){ 926 error("both -T and -L can't be specified"); 927 usage(); 928 } 929 cmd_flags.L_or_T_specified = TRUE; 930 cmd_flags.use_long_names = FALSE; 931 } 932 else if(argv[i][1] == 'L' || argv[i][1] == 'F'){ 933 if(argv[i][1] == 'L' && argv[i][2] == '\0'){ 934 if(cmd_flags.L_or_T_specified == TRUE){ 935 error("both -T and -L can't be specified"); 936 usage(); 937 } 938 cmd_flags.L_or_T_specified = TRUE; 939 cmd_flags.use_long_names = TRUE; 940 } 941 else{ 942 if(cmd_flags.ranlib == TRUE){ 943 error("unknown option: %s", argv[i]); 944 usage(); 945 } 946 cmd_flags.Ldirs = realloc(cmd_flags.Ldirs, 947 sizeof(char *) * (cmd_flags.nLdirs + 1)); 948 cmd_flags.Ldirs[cmd_flags.nLdirs++] = argv[i]; 949 } 950 } 951 else if(argv[i][1] == 'g'){ 952 if(cmd_flags.ranlib == TRUE){ 953 error("unknown option: %s", argv[i]); 954 usage(); 955 } 956 /* We need to ignore -g[gdb,codeview,stab][number] flags */ 957 ; 958 } 959 else if(strcmp(argv[i], "-pg") == 0){ 960 if(cmd_flags.ranlib == TRUE){ 961 error("unknown option: %s", argv[i]); 962 usage(); 963 } 964 /* We need to ignore -pg */ 965 ; 966 } 967 else if(strcmp(argv[i], "-search_paths_first") == 0){ 968 if(cmd_flags.ranlib == TRUE){ 969 error("unknown option: %s", argv[i]); 970 usage(); 971 } 972 cmd_flags.search_paths_first = TRUE; 973 cmd_flags.ldflags = reallocate(cmd_flags.ldflags, 974 sizeof(char *) * (cmd_flags.nldflags + 1)); 975 cmd_flags.ldflags[cmd_flags.nldflags++] = argv[i]; 976 } 977 else if(strcmp(argv[i], "-noflush") == 0){ 978 cmd_flags.noflush = TRUE; 979 } 980#ifdef DEBUG 981 else if(strcmp(argv[i], "-debug") == 0){ 982 if(i + 1 >= argc){ 983 error("not enough arguments follow %s", argv[i]); 984 usage(); 985 } 986 i++; 987 cmd_flags.debug |= 1 << strtoul(argv[i], &endp, 10); 988 if(*endp != '\0' || strtoul(argv[i], &endp, 10) > 32) 989 fatal("argument for -debug %s not a proper " 990 "decimal number less than 32", argv[i]); 991 } 992#endif /* DEBUG */ 993 else{ 994 for(j = 1; argv[i][j] != '\0'; j++){ 995 switch(argv[i][j]){ 996 case 's': 997 cmd_flags.s = TRUE; 998 break; 999 case 'a': 1000 cmd_flags.a = TRUE; 1001 break; 1002 case 'c': 1003 cmd_flags.c = TRUE; 1004 break; 1005 case 'v': 1006 if(cmd_flags.ranlib == TRUE){ 1007 error("unknown option character `%c' in: %s", 1008 argv[i][j], argv[i]); 1009 usage(); 1010 } 1011 cmd_flags.verbose= TRUE; 1012 break; 1013 case 'V': 1014 printf("Apple Inc. version %s\n", apple_version); 1015 Vflag = TRUE; 1016 break; 1017 case 't': 1018 if(cmd_flags.ranlib == TRUE){ 1019 warning("touch option (`%c' in: %s) ignored " 1020 "(table of contents rebuilt anyway)", 1021 argv[i][j], argv[i]); 1022 cmd_flags.t = TRUE; 1023 break; 1024 } 1025 else { 1026 error("unknown option character `%c' in: %s", 1027 argv[i][j], argv[i]); 1028 usage(); 1029 } 1030 case 'f': 1031 if(cmd_flags.ranlib == TRUE){ 1032 cmd_flags.f = TRUE; 1033 break; 1034 } 1035 else { 1036 error("unknown option character `%c' in: %s", 1037 argv[i][j], argv[i]); 1038 usage(); 1039 } 1040 case 'q': 1041 if(cmd_flags.ranlib == TRUE){ 1042 cmd_flags.q = TRUE; 1043 break; 1044 } 1045 else { 1046 error("unknown option character `%c' in: %s", 1047 argv[i][j], argv[i]); 1048 usage(); 1049 } 1050 default: 1051 error("unknown option character `%c' in: %s", 1052 argv[i][j], argv[i]); 1053 usage(); 1054 } 1055 } 1056 } 1057 } 1058 else 1059 cmd_flags.files[cmd_flags.nfiles++] = argv[i]; 1060 } 1061 /* 1062 * Test to see if the environment variable LD_TRACE_ARCHIVES is set. 1063 */ 1064 if((getenv("RC_TRACE_ARCHIVES") != NULL) || 1065 (getenv("LD_TRACE_ARCHIVES") != NULL)) { 1066 cmd_flags.ld_trace_archives = TRUE; 1067 cmd_flags.trace_file_path = getenv("LD_TRACE_FILE"); 1068 } 1069 1070 /* 1071 * If either -syslibroot or the environment variable NEXT_ROOT is set 1072 * prepend it to the standard paths for library searches. This was 1073 * added to ease cross build environments. 1074 */ 1075 if(next_root != NULL){ 1076 if(getenv("NEXT_ROOT") != NULL) 1077 warning("NEXT_ROOT environment variable ignored because " 1078 "-syslibroot specified"); 1079 } 1080 else{ 1081 next_root = getenv("NEXT_ROOT"); 1082 } 1083 if(next_root != NULL){ 1084 for(i = 0; standard_dirs[i] != NULL; i++){ 1085 p = allocate(strlen(next_root) + 1086 strlen(standard_dirs[i]) + 1); 1087 strcpy(p, next_root); 1088 strcat(p, standard_dirs[i]); 1089 standard_dirs[i] = p; 1090 } 1091 for(i = 0; i < cmd_flags.nLdirs ; i++){ 1092 if(cmd_flags.Ldirs[i][1] != 'L') 1093 continue; 1094 if(cmd_flags.Ldirs[i][2] == '/'){ 1095 p = makestr(next_root, cmd_flags.Ldirs[i] + 2, NULL); 1096 if(access(p, F_OK) != -1){ 1097 free(p); 1098 p = makestr("-L", next_root, cmd_flags.Ldirs[i] + 2, 1099 NULL); 1100 cmd_flags.Ldirs[i] = p; 1101 } 1102 else{ 1103 free(p); 1104 } 1105 } 1106 } 1107 } 1108 1109 /* check the command line arguments for correctness */ 1110 if(cmd_flags.ranlib == FALSE && cmd_flags.dynamic == TRUE){ 1111 if(cmd_flags.s == TRUE){ 1112 warning("-static not specified, -s invalid"); 1113 } 1114 if(cmd_flags.a == TRUE){ 1115 warning("-static not specified, -a invalid"); 1116 } 1117 if(cmd_flags.c == TRUE){ 1118 warning("-static not specified, -c invalid"); 1119 } 1120 if(cmd_flags.L_or_T_specified == TRUE){ 1121 if(cmd_flags.use_long_names == TRUE) 1122 warning("-static not specified, -L invalid"); 1123 else 1124 warning("-static not specified, -T invalid"); 1125 } 1126 } 1127 if(cmd_flags.s == TRUE && cmd_flags.a == TRUE){ 1128 error("only one of -s or -a can be specified"); 1129 usage(); 1130 } 1131 if(cmd_flags.ranlib == FALSE && cmd_flags.output == NULL){ 1132 if(Vflag == TRUE) 1133 exit(EXIT_SUCCESS); 1134 error("no output file specified (specify with -o output)"); 1135 usage(); 1136 } 1137 if(cmd_flags.dynamic == FALSE){ 1138 if(cmd_flags.compatibility != NULL){ 1139 warning("-dynamic not specified, -compatibility_version %s " 1140 "invalid", cmd_flags.compatibility); 1141 } 1142 if(cmd_flags.current != NULL){ 1143 warning("-dynamic not specified, -current_version %s invalid", 1144 cmd_flags.current); 1145 } 1146 if(cmd_flags.install_name != NULL){ 1147 warning("-dynamic not specified, -install_name %s invalid", 1148 cmd_flags.install_name); 1149 } 1150 if(cmd_flags.seg1addr != NULL){ 1151 warning("-dynamic not specified, -seg1addr %s invalid", 1152 cmd_flags.seg1addr); 1153 } 1154 if(cmd_flags.segs_read_only_addr != NULL){ 1155 warning("-dynamic not specified, -segs_read_only_addr %s " 1156 "invalid", cmd_flags.segs_read_only_addr); 1157 } 1158 if(cmd_flags.segs_read_write_addr != NULL){ 1159 warning("-dynamic not specified, -segs_read_write_addr %s " 1160 "invalid", cmd_flags.segs_read_write_addr); 1161 } 1162 if(cmd_flags.seg_addr_table != NULL){ 1163 warning("-dynamic not specified, -seg_addr_table %s " 1164 "invalid", cmd_flags.seg_addr_table); 1165 } 1166 if(cmd_flags.seg_addr_table_filename != NULL){ 1167 warning("-dynamic not specified, -seg_addr_table_filename %s " 1168 "invalid", cmd_flags.seg_addr_table_filename); 1169 } 1170 if(cmd_flags.all_load_flag_specified == TRUE){ 1171 if(cmd_flags.all_load == TRUE) 1172 warning("-dynamic not specified, -all_load invalid"); 1173 else 1174 warning("-dynamic not specified, -noall_load invalid"); 1175 } 1176 if(cmd_flags.nldflags != 0){ 1177 bad_flag_seen = FALSE; 1178 for(j = 0; j < cmd_flags.nldflags; j++){ 1179 if(strcmp(cmd_flags.ldflags[j], "-syslibroot") == 0){ 1180 j++; 1181 continue; 1182 } 1183 if(bad_flag_seen == FALSE){ 1184 fprintf(stderr, "%s: -dynamic not specified the " 1185 "following flags are invalid: ", progname); 1186 bad_flag_seen = TRUE; 1187 } 1188 fprintf(stderr, "%s ", cmd_flags.ldflags[j]); 1189 } 1190 if(bad_flag_seen == TRUE) 1191 fprintf(stderr, "\n"); 1192 } 1193 if(cmd_flags.nLdirs != 0){ 1194 /* Note: both -L and -F flags are in cmd_flags.Ldirs to keep the 1195 search order right. */ 1196 bad_flag_seen = FALSE; 1197 for(j = 0; j < cmd_flags.nLdirs; j++){ 1198 if(strncmp(cmd_flags.Ldirs[j], "-L", 2) == 0) 1199 continue; 1200 if(bad_flag_seen == FALSE){ 1201 fprintf(stderr, "%s: -dynamic not specified the " 1202 "following flags are invalid: ", progname); 1203 bad_flag_seen = TRUE; 1204 } 1205 fprintf(stderr, "%s ", cmd_flags.Ldirs[j]); 1206 } 1207 if(bad_flag_seen == TRUE) 1208 fprintf(stderr, "\n"); 1209 } 1210 } 1211 else{ 1212 /* 1213 * The -prebind flag can also be specified with the LD_PREBIND 1214 * environment variable. 1215 */ 1216 if(getenv("LD_PREBIND") != NULL){ 1217 if(cmd_flags.prebinding_flag_specified == TRUE && 1218 cmd_flags.prebinding == FALSE){ 1219 warning("LD_PREBIND environment variable ignored because " 1220 "-noprebind specified"); 1221 } 1222 else{ 1223 cmd_flags.prebinding_flag_specified = TRUE; 1224 cmd_flags.prebinding = TRUE; 1225 } 1226 } 1227 } 1228 if(cmd_flags.nfiles == 0){ 1229 if(cmd_flags.ranlib == TRUE){ 1230 error("no archives specified"); 1231 usage(); 1232 } 1233 else{ 1234 if(cmd_flags.dynamic == TRUE && cmd_flags.no_files_ok == TRUE) 1235 warning("warning no files specified"); 1236 else{ 1237 error("no files specified"); 1238 usage(); 1239 } 1240 } 1241 } 1242 1243 /* set the defaults if not specified */ 1244 if(cmd_flags.a == FALSE) 1245 cmd_flags.s = TRUE; /* sort table of contents by default */ 1246 1247 process(); 1248 1249 if(errors == 0) 1250 return(EXIT_SUCCESS); 1251 else 1252 return(EXIT_FAILURE); 1253} 1254 1255/* 1256 * usage() prints the current usage message and exits indicating failure. 1257 */ 1258static 1259void 1260usage( 1261void) 1262{ 1263 if(cmd_flags.ranlib) 1264 fprintf(stderr, "Usage: %s [-sactfqLT] [-] archive [...]\n", 1265 progname); 1266 else{ 1267 fprintf(stderr, "Usage: %s -static [-] file [...] " 1268 "[-filelist listfile[,dirname]] [-arch_only arch] " 1269 "[-sacLT]\n", progname); 1270 fprintf(stderr, "Usage: %s -dynamic [-] file [...] " 1271 "[-filelist listfile[,dirname]] [-arch_only arch] " 1272 "[-o output] [-install_name name] " 1273 "[-compatibility_version #] [-current_version #] " 1274 "[-seg1addr 0x#] [-segs_read_only_addr 0x#] " 1275 "[-segs_read_write_addr 0x#] [-seg_addr_table <filename>] " 1276 "[-seg_addr_table_filename <file_system_path>] " 1277 "[-all_load] [-noall_load]\n", 1278 progname); 1279 } 1280 exit(EXIT_FAILURE); 1281} 1282 1283/* 1284 * process() the input files into libraries based on the command flags. 1285 */ 1286static 1287void 1288process( 1289void) 1290{ 1291 uint32_t i, j, k, previous_errors; 1292 struct ofile *ofiles; 1293 char *file_name; 1294 enum bool flag, ld_trace_archive_printed; 1295 1296 /* 1297 * For libtool processing put all input files in the specified output 1298 * file. For ranlib processing all input files should be archives or 1299 * fat files with archives in them and each is processed by itself and 1300 * not combined with anything else. The format of fat object files in 1301 * a thin archive is supported here also. 1302 */ 1303 ofiles = allocate(sizeof(struct ofile) * cmd_flags.nfiles); 1304 for(i = 0; i < cmd_flags.nfiles; i++){ 1305 if(strncmp(cmd_flags.files[i], "-l", 2) == 0 || 1306 strncmp(cmd_flags.files[i], "-weak-l", 7) == 0){ 1307 file_name = file_name_from_l_flag(cmd_flags.files[i]); 1308 if(file_name != NULL) 1309 if(ofile_map(file_name, NULL, NULL, ofiles + i, TRUE) == 1310 FALSE) 1311 continue; 1312 } 1313 else if(strcmp(cmd_flags.files[i], "-framework") == 0 || 1314 strcmp(cmd_flags.files[i], "-weak_framework") == 0 || 1315 strcmp(cmd_flags.files[i], "-weak_library") == 0){ 1316 i++; 1317 continue; 1318 } 1319 else{ 1320 if(ofile_map(cmd_flags.files[i], NULL, NULL, ofiles + i, 1321 TRUE) == FALSE) 1322 continue; 1323 } 1324 1325 previous_errors = errors; 1326 errors = 0; 1327 ld_trace_archive_printed = FALSE; 1328 1329 if(ofiles[i].file_type == OFILE_FAT){ 1330 (void)ofile_first_arch(ofiles + i); 1331 do{ 1332 if(ofiles[i].arch_type == OFILE_ARCHIVE){ 1333 if(cmd_flags.ld_trace_archives == TRUE && 1334 cmd_flags.dynamic == FALSE && 1335 ld_trace_archive_printed == FALSE){ 1336 char resolvedname[MAXPATHLEN]; 1337 if(realpath(ofiles[i].file_name, resolvedname) != 1338 NULL) 1339 ld_trace("[Logging for XBS] Used static " 1340 "archive: %s\n", resolvedname); 1341 else 1342 ld_trace("[Logging for XBS] Used static " 1343 "archive: %s\n", ofiles[i].file_name); 1344 ld_trace_archive_printed = TRUE; 1345 } 1346 /* loop through archive */ 1347 if((flag = ofile_first_member(ofiles + i)) == TRUE){ 1348 if(ofiles[i].member_ar_hdr != NULL && 1349 strncmp(ofiles[i].member_name, SYMDEF, 1350 sizeof(SYMDEF) - 1) == 0) 1351 flag = ofile_next_member(ofiles + i); 1352 while(flag == TRUE){ 1353 /* No fat members in a fat file */ 1354 if(ofiles[i].mh != NULL || 1355 ofiles[i].mh64 != NULL || 1356 ofiles[i].lto != NULL || 1357 cmd_flags.ranlib == TRUE) 1358 add_member(ofiles + i); 1359 else{ 1360 error("for architecture: %s file: %s(%.*s) " 1361 "is not an object file (not allowed " 1362 "in a library)", 1363 ofiles[i].arch_flag.name, 1364 cmd_flags.files[i], 1365 (int)ofiles[i].member_name_size, 1366 ofiles[i].member_name); 1367 } 1368 flag = ofile_next_member(ofiles + i); 1369 } 1370 } 1371 } 1372 else if(ofiles[i].arch_type == OFILE_Mach_O || 1373 ofiles[i].arch_type == OFILE_LLVM_BITCODE){ 1374 if(cmd_flags.ranlib == TRUE){ 1375 error("for architecture: %s file: %s is not an " 1376 "archive (no processing done on this file)", 1377 ofiles[i].arch_flag.name, cmd_flags.files[i]); 1378 goto ranlib_fat_error; 1379 } 1380 else 1381 add_member(ofiles + i); 1382 } 1383 else if(ofiles[i].arch_type == OFILE_UNKNOWN){ 1384 if(cmd_flags.ranlib == TRUE){ 1385 error("for architecture: %s file: %s is not an " 1386 "archive (no processing done on this file)", 1387 ofiles[i].arch_flag.name, cmd_flags.files[i]); 1388 goto ranlib_fat_error; 1389 } 1390 else{ 1391 error("for architecture: %s file: %s is not an " 1392 "object file (not allowed in a library)", 1393 ofiles[i].arch_flag.name, cmd_flags.files[i]); 1394 } 1395 } 1396 }while(ofile_next_arch(ofiles + i) == TRUE); 1397 } 1398 else if(ofiles[i].file_type == OFILE_ARCHIVE){ 1399 if(cmd_flags.ld_trace_archives == TRUE && 1400 cmd_flags.dynamic == FALSE && 1401 ld_trace_archive_printed == FALSE){ 1402 char resolvedname[MAXPATHLEN]; 1403 if(realpath(ofiles[i].file_name, resolvedname) != NULL) 1404 ld_trace("[Logging for XBS] Used static archive: " 1405 "%s\n", resolvedname); 1406 else 1407 ld_trace("[Logging for XBS] Used static archive: " 1408 "%s\n", ofiles[i].file_name); 1409 ld_trace_archive_printed = TRUE; 1410 } 1411 /* loop through archive */ 1412 if((flag = ofile_first_member(ofiles + i)) == TRUE){ 1413 if(ofiles[i].member_ar_hdr != NULL && 1414 strncmp(ofiles[i].member_name, SYMDEF, 1415 sizeof(SYMDEF) - 1) == 0){ 1416 flag = ofile_next_member(ofiles + i); 1417 } 1418 while(flag == TRUE){ 1419 /* incorrect form: archive with fat object members */ 1420 if(ofiles[i].member_type == OFILE_FAT){ 1421 (void)ofile_first_arch(ofiles + i); 1422 do{ 1423 if(ofiles[i].mh != NULL || 1424 ofiles[i].mh64 != NULL || 1425 ofiles[i].lto != NULL || 1426 cmd_flags.ranlib == TRUE){ 1427 add_member(ofiles + i); 1428 } 1429 else{ 1430 /* 1431 * Can't really get here because ofile_*() 1432 * routines will refuse to process this 1433 * type of file (but I'll leave it here). 1434 */ 1435 error("file: %s(%.*s) for architecture: %s " 1436 "is not an object file (not allowed in " 1437 "a library)", cmd_flags.files[i], 1438 (int)ofiles[i].member_name_size, 1439 ofiles[i].member_name, 1440 ofiles[i].arch_flag.name); 1441 } 1442 1443 }while(ofile_next_arch(ofiles + i) == TRUE); 1444 } 1445 else if(ofiles[i].mh != NULL || 1446 ofiles[i].mh64 != NULL || 1447#ifdef LTO_SUPPORT 1448 ofiles[i].lto != NULL || 1449#endif /* LTO_SUPPORT */ 1450 cmd_flags.ranlib == TRUE){ 1451 add_member(ofiles + i); 1452 } 1453 else{ 1454 error("file: %s(%.*s) is not an object file (not " 1455 "allowed in a library)", cmd_flags.files[i], 1456 (int)ofiles[i].member_name_size, 1457 ofiles[i].member_name); 1458 } 1459 flag = ofile_next_member(ofiles + i); 1460 } 1461 } 1462 } 1463 else if(ofiles[i].file_type == OFILE_Mach_O){ 1464 if(cmd_flags.ranlib == TRUE){ 1465 error("file: %s is not an archive", cmd_flags.files[i]); 1466 continue; 1467 } 1468 add_member(ofiles + i); 1469 } 1470#ifdef LTO_SUPPORT 1471 else if(ofiles[i].file_type == OFILE_LLVM_BITCODE){ 1472 if(cmd_flags.ranlib == TRUE){ 1473 error("file: %s is not an archive", cmd_flags.files[i]); 1474 continue; 1475 } 1476 add_member(ofiles + i); 1477 } 1478#endif /* LTO_SUPPORT */ 1479 else{ /* ofiles[i].file_type == OFILE_UNKNOWN */ 1480 if(cmd_flags.ranlib == TRUE){ 1481 error("file: %s is not an archive", cmd_flags.files[i]); 1482 continue; 1483 } 1484 else{ 1485 error("file: %s is not an object file (not allowed in a " 1486 "library)", cmd_flags.files[i]); 1487 } 1488 } 1489 1490 if(cmd_flags.ranlib == TRUE){ 1491 /* 1492 * In the case where ranlib is being used on an archive that 1493 * contains fat object files with multiple members and non- 1494 * object members this has to be treated as an error because 1495 * it is not known which architecture(s) the non-object file 1496 * belong to. 1497 */ 1498 if(narchs > 1){ 1499 for(j = 0; j < narchs; j++){ 1500 for(k = 0; k < archs[j].nmembers; k++){ 1501 if(archs[j].members[k].mh == NULL && 1502#ifdef LTO_SUPPORT 1503 archs[j].members[k].lto == NULL && 1504#endif /* LTO_SUPPORT */ 1505 archs[j].members[k].mh64 == NULL){ 1506 error("library member: %s(%.*s) is not an " 1507 "object file (not allowed in a library " 1508 "with multiple architectures)", 1509 cmd_flags.files[i], 1510 (int)archs[j].members[k]. 1511 input_base_name_size, 1512 archs[j].members[k].input_base_name); 1513 } 1514 } 1515 } 1516 } 1517 if(errors == 0) 1518 create_library(cmd_flags.files[i], ofiles + i); 1519 if(cmd_flags.nfiles > 1){ 1520ranlib_fat_error: 1521 free_archs(); 1522 ofile_unmap(ofiles + i); 1523 } 1524 } 1525 errors += previous_errors; 1526 } 1527 if(cmd_flags.ranlib == FALSE && errors == 0) 1528 create_library(cmd_flags.output, NULL); 1529 1530 /* 1531 * Clean-up of ofiles[] and archs could be done here but since this 1532 * program is now done it is faster to just exit. 1533 */ 1534} 1535 1536/* 1537 * file_name_from_l_flag() is passed a "-lx" or "-weak-lx" flag and returns a 1538 * name of a file for this flag. The flag "-lx" and "-weak-lx" are the same 1539 * flags as used in the link editor to refer to file names. If it can't find a 1540 * file name for the flag it prints an error and returns NULL. 1541 */ 1542static 1543char * 1544file_name_from_l_flag( 1545char *l_flag) 1546{ 1547 char *file_name, *p, *start; 1548 1549 if(strncmp(l_flag, "-weak-l", 7) == 0) 1550 start = &l_flag[7]; 1551 else 1552 start = &l_flag[2]; 1553 p = strrchr(start, '.'); 1554 if(p != NULL && strcmp(p, ".o") == 0){ 1555 p = start; 1556 file_name = search_for_file(p); 1557 } 1558 else{ 1559 file_name = NULL; 1560 if(cmd_flags.dynamic == TRUE){ 1561 if(cmd_flags.search_paths_first == TRUE){ 1562 file_name = search_paths_for_lname(start); 1563 } 1564 else{ 1565 p = makestr("lib", start, ".dylib", NULL); 1566 file_name = search_for_file(p); 1567 free(p); 1568 if(file_name == NULL){ 1569 p = makestr("lib", start, ".a", NULL); 1570 file_name = search_for_file(p); 1571 free(p); 1572 } 1573 } 1574 } 1575 else{ 1576 p = makestr("lib", start, ".a", NULL); 1577 file_name = search_for_file(p); 1578 free(p); 1579 } 1580 } 1581 if(file_name == NULL) 1582 error("can't locate file for: %s", l_flag); 1583 return(file_name); 1584} 1585 1586/* 1587 * search_for_file() takes base_name and trys to find a file with that base name 1588 * is the -L search directories and in the standard directories. If it is 1589 * sucessful it returns a pointer to the file name else it returns NULL. 1590 */ 1591static 1592char * 1593search_for_file( 1594char *base_name) 1595{ 1596 uint32_t i; 1597 char *file_name; 1598 1599 for(i = 0; i < cmd_flags.nLdirs ; i++){ 1600 if(cmd_flags.Ldirs[i][1] != 'L') 1601 continue; 1602 file_name = makestr(cmd_flags.Ldirs[i] + 2, "/", base_name, NULL); 1603 if(access(file_name, R_OK) != -1) 1604 return(file_name); 1605 free(file_name); 1606 } 1607 for(i = 0; standard_dirs[i] != NULL ; i++){ 1608 file_name = makestr(standard_dirs[i], base_name, NULL); 1609 if(access(file_name, R_OK) != -1) 1610 return(file_name); 1611 free(file_name); 1612 } 1613 return(NULL); 1614} 1615 1616/* 1617 * search_paths_for_lname() takes the argument to a -lx option and and trys to 1618 * find a file with the name libx.dylib or libx.a. This routine is only used 1619 * when the -search_paths_first option is specified and -dynamic is in effect. 1620 * And looks for a file name ending in .dylib then .a in each directory before 1621 * looking in the next directory. The list of the -L search directories and in 1622 * the standard directories are searched in that order. If this is sucessful 1623 * it returns a pointer to the file name else NULL. 1624 */ 1625static 1626char * 1627search_paths_for_lname( 1628const char *lname_argument) 1629{ 1630 uint32_t i; 1631 char *file_name, *dir; 1632 1633 for(i = 0; i < cmd_flags.nLdirs ; i++){ 1634 if(cmd_flags.Ldirs[i][1] != 'L') 1635 continue; 1636 dir = makestr(cmd_flags.Ldirs[i] + 2, "/", NULL); 1637 file_name = search_path_for_lname(dir, lname_argument); 1638 free(dir); 1639 if(file_name != NULL) 1640 return(file_name); 1641 } 1642 for(i = 0; standard_dirs[i] != NULL ; i++){ 1643 file_name = search_path_for_lname(standard_dirs[i], lname_argument); 1644 if(file_name != NULL) 1645 return(file_name); 1646 } 1647 return(NULL); 1648} 1649 1650/* 1651 * search_path_for_lname() takes the argument to a -lx option and and trys to 1652 * find a file with the name libx.dylib then libx.a in the specified directory 1653 * name. This routine is only used when the -search_paths_first option is 1654 * specified and -dynamic is in effect. If this is sucessful it returns a 1655 * pointer to the file name else NULL. 1656 */ 1657static 1658char * 1659search_path_for_lname( 1660const char *dir, 1661const char *lname_argument) 1662{ 1663 char *file_name; 1664 1665 file_name = makestr(dir, "/", "lib", lname_argument, ".dylib", NULL); 1666 if(access(file_name, R_OK) != -1) 1667 return(file_name); 1668 free(file_name); 1669 1670 file_name = makestr(dir, "/", "lib", lname_argument, ".a", NULL); 1671 if(access(file_name, R_OK) != -1) 1672 return(file_name); 1673 free(file_name); 1674 1675 return(NULL); 1676} 1677 1678/* 1679 * add_member() add the specified ofile as a member to the library. The 1680 * specified ofile must be either an object file (libtool or ranlib) or an 1681 * archive member with an unknown file type (ranlib only). 1682 */ 1683static 1684void 1685add_member( 1686struct ofile *ofile) 1687{ 1688 uint32_t i, j, size, ar_name_size; 1689 struct arch *arch; 1690 struct member *member; 1691 struct stat stat_buf; 1692 char *p, c, ar_name_buf[sizeof(ofile->member_ar_hdr->ar_name) + 1]; 1693 char ar_size_buf[sizeof(ofile->member_ar_hdr->ar_size) + 1]; 1694 const struct arch_flag *family_arch_flag; 1695 1696 /* 1697 * If this did not come from an archive get the stat info which is 1698 * needed to fill in the archive header for this member. 1699 */ 1700 if(ofile->member_ar_hdr == NULL){ 1701 if(stat(ofile->file_name, &stat_buf) == -1){ 1702 system_error("can't stat file: %s", ofile->file_name); 1703 return; 1704 } 1705 } 1706 1707 /* 1708 * Determine the size this member will have in the library which 1709 * includes the padding as a result of rounding the size of the 1710 * member. To get all members on an 8 byte boundary (so that mapping 1711 * in object files can be used directly) the size of the member is 1712 * CHANGED to reflect this padding. In the UNIX definition of archives 1713 * the size of the member is never changed but the offset to the next 1714 * member is defined to be the offset of the previous member plus 1715 * the size of the previous member rounded to 2. So to get 8 byte 1716 * boundaries without breaking the UNIX definition of archives the 1717 * size is changed here. As with the UNIX ar(1) program the padded 1718 * bytes are set to the character '\n'. 1719 */ 1720 if(ofile->mh != NULL || ofile->mh64 != NULL) 1721 size = rnd(ofile->object_size, 8); 1722#ifdef LTO_SUPPORT 1723 else if(ofile->lto != NULL && ofile->file_type == OFILE_LLVM_BITCODE) 1724 size = rnd(ofile->file_size, 8); 1725#endif /* LTO_SUPPORT */ 1726 else 1727 size = rnd(ofile->member_size, 8); 1728 1729 /* select or create an arch type to put this in */ 1730 i = 0; 1731 if(ofile->mh != NULL || 1732 ofile->mh64 != NULL){ 1733 if(ofile->mh_cputype == 0){ 1734 if(ofile->member_ar_hdr != NULL){ 1735 error("file: %s(%.*s) cputype is zero (a reserved value)", 1736 ofile->file_name, (int)ofile->member_name_size, 1737 ofile->member_name); 1738 } 1739 else 1740 error("file: %s cputype is zero (a reserved value)", 1741 ofile->file_name); 1742 return; 1743 } 1744 /* 1745 * If we are building a dynamic library then don't add dynamic 1746 * shared libraries to the archs. This is so that a dependent 1747 * dynamic shared library that happens to be fat will not cause the 1748 * library to be created fat unless there are object going into 1749 * the library that are fat. 1750 */ 1751 if(ofile->mh_filetype == MH_DYLIB || 1752 ofile->mh_filetype == MH_DYLIB_STUB){ 1753 /* 1754 * If we are building a static library we should not put a 1755 * dynamic library Mach-O file into the static library. This 1756 * can happen if a libx.a file is really a dynamic library and 1757 * someone is using -lx when creating a static library. 1758 */ 1759 if(cmd_flags.dynamic != TRUE){ 1760 if(ofile->member_ar_hdr != NULL){ 1761 warning("file: %s(%.*s) is a dynamic library, not " 1762 "added to the static library", 1763 ofile->file_name, (int)ofile->member_name_size, 1764 ofile->member_name); 1765 } 1766 else 1767 warning("file: %s is a dynamic library, not added to " 1768 "the static library", ofile->file_name); 1769 } 1770 return; 1771 } 1772 /* 1773 * If -arch_only is specified then only add this file if it matches 1774 * the architecture specified. 1775 */ 1776 if(cmd_flags.arch_only_flag.name != NULL){ 1777 if(cmd_flags.arch_only_flag.cputype != ofile->mh_cputype) 1778 return; 1779 if(cmd_flags.arch_only_flag.cputype == CPU_TYPE_ARM){ 1780 if(cmd_flags.arch_only_flag.cpusubtype != 1781 ofile->mh_cpusubtype) 1782 return; 1783 } 1784 } 1785 1786 for( ; i < narchs; i++){ 1787 if(archs[i].arch_flag.cputype == ofile->mh_cputype){ 1788 if(archs[i].arch_flag.cputype == CPU_TYPE_ARM && 1789 archs[i].arch_flag.cpusubtype != ofile->mh_cpusubtype) 1790 continue; 1791 break; 1792 } 1793 } 1794 } 1795#ifdef LTO_SUPPORT 1796 else if(ofile->lto != NULL){ 1797 /* 1798 * If -arch_only is specified then only add this file if it matches 1799 * the architecture specified. 1800 */ 1801 if(cmd_flags.arch_only_flag.name != NULL && 1802 cmd_flags.arch_only_flag.cputype != ofile->lto_cputype) 1803 return; 1804 1805 for( ; i < narchs; i++){ 1806 if(archs[i].arch_flag.cputype == ofile->lto_cputype){ 1807 if(archs[i].arch_flag.cputype == CPU_TYPE_ARM && 1808 archs[i].arch_flag.cpusubtype != ofile->lto_cpusubtype) 1809 continue; 1810 break; 1811 } 1812 } 1813 } 1814#endif /* LTO_SUPPORT */ 1815 if(narchs == 1 && archs[0].arch_flag.cputype == 0){ 1816 i = 0; 1817 } 1818 else if(i == narchs){ 1819 archs = reallocate(archs, sizeof(struct arch) * (narchs+1)); 1820 memset(archs + narchs, '\0', sizeof(struct arch)); 1821 if(ofile->mh != NULL || 1822 ofile->mh64 != NULL){ 1823 if(ofile->mh_cputype == CPU_TYPE_ARM){ 1824 archs[narchs].arch_flag.name = (char *) 1825 get_arch_name_from_types( 1826 ofile->mh_cputype, ofile->mh_cpusubtype); 1827 archs[narchs].arch_flag.cputype = ofile->mh_cputype; 1828 archs[narchs].arch_flag.cpusubtype = ofile->mh_cpusubtype; 1829 } 1830 else{ 1831 family_arch_flag = 1832 get_arch_family_from_cputype(ofile->mh_cputype); 1833 if(family_arch_flag != NULL) 1834 archs[narchs].arch_flag = *family_arch_flag; 1835 } 1836 } 1837#ifdef LTO_SUPPORT 1838 else if(ofile->lto != NULL){ 1839 if(ofile->lto_cputype == CPU_TYPE_ARM){ 1840 archs[narchs].arch_flag.name = (char *) 1841 get_arch_name_from_types( 1842 ofile->lto_cputype, ofile->lto_cpusubtype); 1843 archs[narchs].arch_flag.cputype = ofile->lto_cputype; 1844 archs[narchs].arch_flag.cpusubtype = ofile->lto_cpusubtype; 1845 } 1846 else{ 1847 family_arch_flag = 1848 get_arch_family_from_cputype(ofile->lto_cputype); 1849 if(family_arch_flag != NULL) 1850 archs[narchs].arch_flag = *family_arch_flag; 1851 } 1852 } 1853#endif /* LTO_SUPPORT */ 1854 else 1855 archs[narchs].arch_flag.name = "unknown"; 1856 narchs++; 1857 } 1858 arch = archs + i; 1859 1860 /* 1861 * If the cputype of this arch is not yet known then see if this new 1862 * member can determine it. 1863 */ 1864 if(arch->arch_flag.cputype == 0 && 1865 (ofile->mh != NULL || ofile->mh64 != NULL)){ 1866 family_arch_flag = get_arch_family_from_cputype(ofile->mh_cputype); 1867 if(family_arch_flag != NULL){ 1868 arch->arch_flag = *family_arch_flag; 1869 } 1870 else{ 1871 arch->arch_flag.name = 1872 savestr("cputype 1234567890 cpusubtype 1234567890"); 1873 if(arch->arch_flag.name != NULL) 1874 sprintf(arch->arch_flag.name, "cputype %u cpusubtype %u", 1875 ofile->mh_cputype, ofile->mh_cpusubtype & 1876 ~CPU_SUBTYPE_MASK); 1877 arch->arch_flag.cputype = ofile->mh_cputype; 1878 arch->arch_flag.cpusubtype = ofile->mh_cpusubtype; 1879 } 1880 } 1881#ifdef LTO_SUPPORT 1882 if(arch->arch_flag.cputype == 0 && 1883 (ofile->lto != NULL)){ 1884 family_arch_flag = get_arch_family_from_cputype(ofile->lto_cputype); 1885 if(family_arch_flag != NULL){ 1886 arch->arch_flag = *family_arch_flag; 1887 } 1888 else{ 1889 arch->arch_flag.name = 1890 savestr("cputype 1234567890 cpusubtype 1234567890"); 1891 if(arch->arch_flag.name != NULL) 1892 sprintf(arch->arch_flag.name, "cputype %u cpusubtype %u", 1893 ofile->lto_cputype, ofile->lto_cpusubtype & 1894 ~CPU_SUBTYPE_MASK); 1895 arch->arch_flag.cputype = ofile->lto_cputype; 1896 arch->arch_flag.cpusubtype = ofile->lto_cpusubtype; 1897 } 1898 } 1899#endif /* LTO_SUPPORT */ 1900 1901 /* create a member in this arch type for this member */ 1902 arch->members = reallocate(arch->members, sizeof(struct member) * 1903 (arch->nmembers + 1)); 1904 member = arch->members + arch->nmembers; 1905 memset(member, '\0', sizeof(struct member)); 1906 arch->nmembers++; 1907 1908 /* fill in the member for this ofile */ 1909 member->input_file_name = ofile->file_name; 1910 1911 if(ofile->member_ar_hdr == NULL){ 1912 /* 1913 * We are creating an archive member in the output file from a 1914 * file (that is not archive member in an input file). First get 1915 * the base name the file_name for the member name. 1916 */ 1917 p = strrchr(ofile->file_name, '/'); 1918 if(p != NULL) 1919 p++; 1920 else 1921 p = ofile->file_name; 1922 member->input_base_name = p; 1923 member->input_base_name_size = strlen(p); 1924 member->member_name = member->input_base_name; 1925 /* 1926 * If we can use long names then force using them to allow 64-bit 1927 * objects to be aligned on an 8 byte boundary. This is needed 1928 * since the struct ar_hdr is not a multiple of 8. This is normally 1929 * done if the name does not fit in the archive header or contains 1930 * a space character then we use the extened format #1. The size 1931 * of the name is rounded up so the object file after the name will 1932 * be on an 8 byte boundary (including rounding the size of the 1933 * struct ar_hdr). The name will be padded with '\0's when it is 1934 * written out. 1935 */ 1936 if(cmd_flags.use_long_names == TRUE){ 1937 member->output_long_name = TRUE; 1938 member->member_name_size = member->input_base_name_size; 1939 ar_name_size = rnd(member->input_base_name_size, 8) + 1940 (rnd(sizeof(struct ar_hdr), 8) - 1941 sizeof(struct ar_hdr)); 1942 sprintf(ar_name_buf, "%s%-*lu", AR_EFMT1, 1943 (int)(sizeof(member->ar_hdr.ar_name) - 1944 (sizeof(AR_EFMT1) - 1)), 1945 (long unsigned int)ar_name_size); 1946 memcpy(member->ar_hdr.ar_name, ar_name_buf, 1947 sizeof(member->ar_hdr.ar_name)); 1948 } 1949 else{ 1950 ar_name_size = 0; 1951 member->output_long_name = FALSE; 1952 /* 1953 * Truncate the file_name if needed and place in archive header. 1954 */ 1955 c = '\0'; 1956 if(strlen(p) > sizeof(member->ar_hdr.ar_name)){ 1957 c = p[sizeof(member->ar_hdr.ar_name)]; 1958 p[sizeof(member->ar_hdr.ar_name)] = '\0'; 1959 } 1960 sprintf((char *)(&member->ar_hdr), "%-*s", 1961 (int)sizeof(member->ar_hdr.ar_name), p); 1962 if(c != '\0') 1963 p[sizeof(member->ar_hdr.ar_name)] = c; 1964 member->member_name_size = size_ar_name(&member->ar_hdr); 1965 } 1966 if(zero_ar_date == TRUE) 1967 stat_buf.st_mtime = 0; 1968 /* 1969 * Create the rest of the archive header after the name. 1970 */ 1971 sprintf((char *)(&member->ar_hdr) + sizeof(member->ar_hdr.ar_name), 1972 "%-*ld%-*u%-*u%-*o%-*ld%-*s", 1973 (int)sizeof(member->ar_hdr.ar_date), 1974 (long int)stat_buf.st_mtime, 1975 (int)sizeof(member->ar_hdr.ar_uid), 1976 (unsigned short)stat_buf.st_uid, 1977 (int)sizeof(member->ar_hdr.ar_gid), 1978 (unsigned short)stat_buf.st_gid, 1979 (int)sizeof(member->ar_hdr.ar_mode), 1980 (unsigned int)stat_buf.st_mode, 1981 (int)sizeof(member->ar_hdr.ar_size), 1982 (long)size + ar_name_size, 1983 (int)sizeof(member->ar_hdr.ar_fmag), 1984 ARFMAG); 1985 } 1986 else{ 1987 /* 1988 * We are creating an archive member in the output file from an 1989 * archive member in an input file. There can be some changes to 1990 * the contents. First the size might be changed and the contents 1991 * padded with '\n's to round it to a multiple of 8 1992 * Second we may take a member using extended format #1 1993 * for it's name and truncate it then place the name in the archive 1994 * header. Or we may round the name size to a multiple of 8. 1995 */ 1996 member->input_ar_hdr = ofile->member_ar_hdr; 1997 member->input_base_name = ofile->member_name; 1998 member->input_base_name_size = ofile->member_name_size; 1999 member->input_member_offset = ofile->member_offset - 2000 sizeof(struct ar_hdr); 2001 if(strncmp(ofile->member_ar_hdr->ar_name, AR_EFMT1, 2002 sizeof(AR_EFMT1) - 1) == 0) 2003 member->input_member_offset -= ofile->member_name_size; 2004 2005 member->ar_hdr = *(ofile->member_ar_hdr); 2006 member->member_name = ofile->member_name; 2007 2008 if(cmd_flags.use_long_names == TRUE){ 2009 /* 2010 * We can use long names. So if the input ofile is using the 2011 * extended format #1 we need make sure the size of the name and 2012 * the size of struct ar_hdr are rounded to 8 bytes. And write 2013 * that size into the ar_name with the AR_EFMT1 string. To 2014 * avoid growing the size of names first trim the long name size 2015 * before rounding up. 2016 */ 2017 if(ofile->member_name != ofile->member_ar_hdr->ar_name){ 2018 member->output_long_name = TRUE; 2019 member->member_name_size = ofile->member_name_size; 2020 for(ar_name_size = member->member_name_size; 2021 ar_name_size > 1 ; 2022 ar_name_size--){ 2023 if(ofile->member_name[ar_name_size - 1] != '\0') 2024 break; 2025 } 2026 member->member_name_size = ar_name_size; 2027 ar_name_size = rnd(ar_name_size, 8) + 2028 (rnd(sizeof(struct ar_hdr), 8) - 2029 sizeof(struct ar_hdr)); 2030 sprintf(ar_name_buf, "%s%-*lu", AR_EFMT1, 2031 (int)(sizeof(member->ar_hdr.ar_name) - 2032 (sizeof(AR_EFMT1) - 1)), 2033 (long unsigned int)ar_name_size); 2034 memcpy(member->ar_hdr.ar_name, ar_name_buf, 2035 sizeof(member->ar_hdr.ar_name)); 2036 } 2037 else{ 2038 /* 2039 * Since we can use long names force this to use extended 2040 * format #1. And round the name size to 8 plus the size of 2041 * struct ar_hdr rounded to 8 bytes. 2042 */ 2043 member->member_name_size = size_ar_name(&member->ar_hdr); 2044 ar_name_size = rnd(ofile->member_name_size, 8) + 2045 (rnd(sizeof(struct ar_hdr), 8) - 2046 sizeof(struct ar_hdr)); 2047 member->output_long_name = TRUE; 2048 sprintf(ar_name_buf, "%s%-*lu", AR_EFMT1, 2049 (int)(sizeof(member->ar_hdr.ar_name) - 2050 (sizeof(AR_EFMT1) - 1)), 2051 (long unsigned int)ar_name_size); 2052 memcpy(member->ar_hdr.ar_name, ar_name_buf, 2053 sizeof(member->ar_hdr.ar_name)); 2054 } 2055 } 2056 else{ 2057 /* 2058 * We can't use long names. So if the input ofile is using the 2059 * extended format #1 we need to truncate the name and write it 2060 * into the ar_name field. Note the extended format is also 2061 * used it the name has a space in it so it may be shorter than 2062 * sizeof(ar_hdr.ar_name) . 2063 */ 2064 ar_name_size = 0; 2065 member->output_long_name = FALSE; 2066 if(ofile->member_name != ofile->member_ar_hdr->ar_name){ 2067 for(j = 0; j < sizeof(member->ar_hdr.ar_name) && 2068 j < ofile->member_name_size && 2069 ofile->member_name[j] != '\0'; j++) 2070 member->ar_hdr.ar_name[j] = ofile->member_name[j]; 2071 for( ; j < sizeof(member->ar_hdr.ar_name); j++) 2072 member->ar_hdr.ar_name[j] = ' '; 2073 } 2074 member->member_name_size = size_ar_name(&member->ar_hdr); 2075 } 2076 /* 2077 * Since sprintf() writes a '\0' at the end of the string the 2078 * memcpy is needed to preserve the ARFMAG string that follows. 2079 */ 2080 sprintf(ar_size_buf, "%-*ld", 2081 (int)sizeof(member->ar_hdr.ar_size), 2082 (long)size + ar_name_size); 2083 memcpy(member->ar_hdr.ar_size, ar_size_buf, 2084 sizeof(member->ar_hdr.ar_size)); 2085 } 2086 2087 member->offset = arch->size; 2088 arch->size += sizeof(struct ar_hdr) + size + ar_name_size; 2089 2090 if(ofile->mh != NULL || 2091 ofile->mh64 != NULL){ 2092 member->object_addr = ofile->object_addr; 2093 member->object_size = ofile->object_size; 2094 member->object_byte_sex = ofile->object_byte_sex; 2095 member->mh = ofile->mh; 2096 member->mh64 = ofile->mh64; 2097 member->load_commands = ofile->load_commands; 2098 } 2099#ifdef LTO_SUPPORT 2100 else if(ofile->file_type == OFILE_LLVM_BITCODE){ 2101 member->object_addr = ofile->file_addr; 2102 member->object_size = ofile->file_size; 2103 member->lto = ofile->lto; 2104 member->object_byte_sex = get_byte_sex_from_flag(&arch->arch_flag); 2105 } 2106#endif /* LTO_SUPPORT */ 2107 else{ 2108 member->object_addr = ofile->member_addr; 2109 member->object_size = ofile->member_size; 2110#ifdef LTO_SUPPORT 2111 if(ofile->lto != NULL){ 2112 member->lto = ofile->lto; 2113 member->object_byte_sex = get_byte_sex_from_flag( 2114 &arch->arch_flag); 2115 } 2116#endif /* LTO_SUPPORT */ 2117 } 2118} 2119 2120/* 2121 * free_archs() frees the memory allocated that is pointed to by archs. 2122 */ 2123static 2124void 2125free_archs( 2126void) 2127{ 2128 uint32_t i; 2129 2130 for(i = 0 ; i < narchs; i++){ 2131 /* 2132 * Just leak memory on the arch_flag.name in some cases 2133 * (unknown archiectures only where the space is malloced and 2134 * a sprintf() is done into the memory) 2135 */ 2136 if(archs[i].tocs != NULL) 2137 free(archs[i].tocs); 2138 if(archs[i].toc_ranlibs != NULL) 2139 free(archs[i].toc_ranlibs); 2140 if(archs[i].toc_strings != NULL) 2141 free(archs[i].toc_strings); 2142 if(archs[i].members != NULL) 2143 free(archs[i].members); 2144 } 2145 if(archs != NULL) 2146 free(archs); 2147 archs = NULL; 2148 narchs = 0; 2149} 2150 2151/* 2152 * create_library() creates a library from the data structure pointed to by 2153 * archs into the specified output file. Only when more than one architecture 2154 * is in archs will a fat file be created. 2155 * 2156 * In the case of cmd_flags.ranlib == TRUE the ofile may not be NULL if it 2157 * from a thin archive. If so and the toc_* fields are set and we may update 2158 * the table of contents in place if the new one fits where the old table of 2159 * contents was. 2160 */ 2161static 2162void 2163create_library( 2164char *output, 2165struct ofile *ofile) 2166{ 2167 uint32_t i, j, k, pad, *time_offsets; 2168 uint64_t library_size, offset; 2169 enum byte_sex target_byte_sex; 2170 char *library, *p, *flush_start; 2171 kern_return_t r; 2172 struct arch *arch; 2173 struct fat_header *fat_header; 2174 struct fat_arch *fat_arch; 2175 int fd; 2176#ifndef __OPENSTEP__ 2177 struct utimbuf timep; 2178#else 2179 time_t timep[2]; 2180#endif 2181 struct stat stat_buf; 2182 struct ar_hdr toc_ar_hdr; 2183 enum bool some_tocs, same_toc, different_offsets; 2184 2185 if(narchs == 0){ 2186 if(cmd_flags.ranlib == TRUE){ 2187 if(cmd_flags.q == FALSE) 2188 warning("empty library: %s (no table of contents added)", 2189 output); 2190 return; 2191 } 2192 else{ 2193 if(cmd_flags.dynamic == FALSE || 2194 cmd_flags.no_files_ok == FALSE){ 2195 if(cmd_flags.arch_only_flag.name != NULL) 2196 error("no library created (no object files in input " 2197 "files matching -arch_only %s)", 2198 cmd_flags.arch_only_flag.name); 2199 else 2200 error("no library created (no object files in input " 2201 "files)"); 2202 return; 2203 } 2204 } 2205 } 2206 2207 if(cmd_flags.dynamic == TRUE){ 2208 create_dynamic_shared_library(output); 2209 return; 2210 } 2211 2212 /* if this is libtool warn about duplicate member names */ 2213 if(cmd_flags.ranlib == FALSE) 2214 warn_duplicate_member_names(); 2215 2216 /* 2217 * Calculate the total size of the library and the final size of each 2218 * architecture. 2219 */ 2220 if(narchs > 1){ 2221 library_size = sizeof(struct fat_header) + 2222 sizeof(struct fat_arch) * narchs; 2223 /* 2224 * The ar(1) program uses the -q flag to ranlib(1) to add a table 2225 * of contents only of the output is not a fat file. This is done 2226 * by default for UNIX standards conformance when the files are 2227 * thin .o files. 2228 */ 2229 if(cmd_flags.q == TRUE) 2230 exit(EXIT_SUCCESS); 2231 /* 2232 * The ar(1) program uses the -f to ranlib(1) when it see the 's' 2233 * option. And if we are creating a fat file issue a warning that 2234 * ar(1) will not be able to use it. 2235 */ 2236 if(cmd_flags.f == TRUE) 2237 warning("archive library: %s will be fat and ar(1) will not " 2238 "be able to operate on it", output); 2239 } 2240 else 2241 library_size = 0; 2242 some_tocs = FALSE; 2243 for(i = 0; i < narchs; i++){ 2244 make_table_of_contents(archs + i, output); 2245 if(errors != 0) 2246 return; 2247 if(archs[i].toc_nranlibs != 0) 2248 some_tocs = TRUE; 2249 archs[i].size += SARMAG + archs[i].toc_size; 2250 library_size += archs[i].size; 2251 } 2252 /* 2253 * The ar(1) program uses the -q flag to ranlib(1) to add a table of 2254 * contents only of the output contains some object files. This is 2255 * done for UNIX standards conformance. 2256 */ 2257 if(cmd_flags.q == TRUE && some_tocs == FALSE) 2258 exit(EXIT_SUCCESS); 2259 2260 /* 2261 * If this is ranlib(1) and we are running in UNIX standard mode and 2262 * the file is not writeable just print and error message and return. 2263 */ 2264 if(cmd_flags.ranlib == TRUE && 2265 get_unix_standard_mode() == TRUE && 2266 access(output, W_OK) == -1){ 2267 system_error("file: %s is not writable", output); 2268 return; 2269 } 2270 2271 /* 2272 * If this is ranlib(1) and we have a thin archive that has an existing 2273 * table of contents see if we have enough room to update it in place. 2274 * Actually we check to see that we have the exact same number of 2275 * ranlib structs and string size, as this is the most common case that 2276 * the defined global symbols have not changed when rebuilding and it 2277 * will just be the offset to archive members that will have changed. 2278 */ 2279 if(cmd_flags.ranlib == TRUE && narchs == 1 && 2280 ofile != NULL && ofile->toc_addr != NULL && 2281 ofile->toc_bad == FALSE && 2282 archs[0].toc_nranlibs == ofile->toc_nranlibs && 2283 archs[0].toc_strsize == ofile->toc_strsize){ 2284 2285 /* 2286 * If the table of contents in the input does have a long name and 2287 * the one we built does not (or vice a versa) then don't update it 2288 * in place. 2289 */ 2290 if(strcmp(ofile->toc_ar_hdr->ar_name, AR_EFMT1) == 0){ 2291 if(archs[0].toc_long_name != TRUE) 2292 goto fail_to_update_toc_in_place; 2293 } 2294 else{ 2295 if(archs[0].toc_long_name == TRUE) 2296 goto fail_to_update_toc_in_place; 2297 } 2298 2299 /* 2300 * The existing thin archive may not be laid out the same way as 2301 * libtool(1) would do it. As ar(1) does not know to pad things 2302 * so object files are on their natural alignment. So check to 2303 * see if the offsets are not the same and if the alignment is OK. 2304 */ 2305 different_offsets = FALSE; 2306 for(i = 0; i < archs[0].nmembers; i++){ 2307 if(archs[0].members[i].input_member_offset != 2308 archs[0].members[i].offset){ 2309 different_offsets = TRUE; 2310 /* 2311 * For now we will allow alignments of 4 bytes offsets even 2312 * though we would produce 8 byte alignments. 2313 */ 2314 if(archs[0].members[i].input_member_offset % 4 != 0){ 2315 goto fail_to_update_toc_in_place; 2316 } 2317 } 2318 } 2319 2320 /* 2321 * The time_offsets array records the offsets to the table of 2322 * contents archive header's ar_date fields. In this case we just 2323 * have one since this is a thin file (non-fat) file. 2324 */ 2325 time_offsets = allocate(1 * sizeof(uint32_t)); 2326 /* 2327 * Calculate the offset to the archive header's time field for the 2328 * table of contents. 2329 */ 2330 time_offsets[0] = SARMAG + 2331 ((char *)&toc_ar_hdr.ar_date - (char *)&toc_ar_hdr); 2332 2333 /* 2334 * If we had different member offsets in the input thin archive 2335 * we adjust the ranlib structs ran_off to use them. 2336 */ 2337 if(different_offsets == TRUE){ 2338 same_toc = FALSE; 2339 for(i = 0; i < archs[0].toc_nranlibs; i++){ 2340 for(j = 0; j < archs[0].nmembers; j++){ 2341 if(archs[0].members[j].offset == 2342 archs[0].toc_ranlibs[i].ran_off){ 2343 archs[0].toc_ranlibs[i].ran_off = 2344 archs[0].members[j].input_member_offset; 2345 break; 2346 } 2347 } 2348 } 2349 } 2350 else{ 2351 /* 2352 * If the new table of contents and the new string table are the 2353 * same as the old then the archive only needs to be "touched" 2354 * and the time field of the toc needs to be updated. 2355 */ 2356 same_toc = TRUE; 2357 for(i = 0; i < archs[0].toc_nranlibs; i++){ 2358 if(archs[0].toc_ranlibs[i].ran_un.ran_strx != 2359 ofile->toc_ranlibs[i].ran_un.ran_strx || 2360 archs[0].toc_ranlibs[i].ran_off != 2361 ofile->toc_ranlibs[i].ran_off){ 2362 same_toc = FALSE; 2363 break; 2364 } 2365 } 2366 if(same_toc == TRUE){ 2367 for(i = 0; i < archs[0].toc_strsize; i++){ 2368 if(archs[0].toc_strings[i] != ofile->toc_strings[i]){ 2369 same_toc = FALSE; 2370 break; 2371 } 2372 } 2373 } 2374 } 2375 2376 library_size = SARMAG; 2377 if(same_toc == FALSE) 2378 library_size += archs[0].toc_size; 2379 if((r = vm_allocate(mach_task_self(), (vm_address_t *)&library, 2380 library_size, TRUE)) != KERN_SUCCESS) 2381 mach_fatal(r, "can't vm_allocate() buffer for output file: %s " 2382 "of size %llu", output, library_size); 2383 2384 2385 /* put in the archive magic string in the buffer */ 2386 p = library; 2387 memcpy(p, ARMAG, SARMAG); 2388 p += SARMAG; 2389 2390 /* put the table of contents in the buffer if needed */ 2391 target_byte_sex = get_target_byte_sex(archs + 0, host_byte_sex); 2392 if(same_toc == FALSE) 2393 p = put_toc_member(p, archs+0, host_byte_sex, target_byte_sex); 2394 2395 if((fd = open(output, O_WRONLY, 0)) == -1){ 2396 system_error("can't open output file: %s", output); 2397 return; 2398 } 2399 if(write(fd, library, library_size) != (int)library_size){ 2400 system_error("can't write output file: %s", output); 2401 return; 2402 } 2403 if(close(fd) == -1){ 2404 system_fatal("can't close output file: %s", output); 2405 return; 2406 } 2407 goto update_toc_ar_dates; 2408 } 2409fail_to_update_toc_in_place: 2410 2411 /* 2412 * This buffer is vm_allocate'ed to make sure all holes are filled with 2413 * zero bytes. 2414 */ 2415 if((r = vm_allocate(mach_task_self(), (vm_address_t *)&library, 2416 library_size, TRUE)) != KERN_SUCCESS) 2417 mach_fatal(r, "can't vm_allocate() buffer for output file: %s of " 2418 "size %llu", output, library_size); 2419 2420 /* 2421 * Create the output file. The unlink() is done to handle the problem 2422 * when the outputfile is not writable but the directory allows the 2423 * file to be removed (since the file may not be there the return code 2424 * of the unlink() is ignored). 2425 */ 2426 (void)unlink(output); 2427 if((fd = open(output, O_WRONLY | O_CREAT | O_TRUNC, 0666)) == -1){ 2428 system_error("can't create output file: %s", output); 2429 return; 2430 } 2431#ifdef F_NOCACHE 2432 /* tell filesystem to NOT cache the file when reading or writing */ 2433 (void)fcntl(fd, F_NOCACHE, 1); 2434#endif 2435 2436 /* 2437 * If there is more than one architecture then fill in the fat file 2438 * header and the fat_arch structures in the buffer. 2439 */ 2440 if(narchs > 1){ 2441 fat_header = (struct fat_header *)library; 2442 fat_header->magic = FAT_MAGIC; 2443 fat_header->nfat_arch = narchs; 2444 offset = sizeof(struct fat_header) + 2445 sizeof(struct fat_arch) * narchs; 2446 fat_arch = (struct fat_arch *)(library + sizeof(struct fat_header)); 2447 for(i = 0; i < narchs; i++){ 2448 fat_arch[i].cputype = archs[i].arch_flag.cputype; 2449 fat_arch[i].cpusubtype = archs[i].arch_flag.cpusubtype; 2450 if(offset > UINT32_MAX) 2451 error("file too large to create as a fat file because " 2452 "offset field in struct fat_arch is only 32-bits and " 2453 "offset (%llu) to architecture %s exceeds that", 2454 offset, archs[i].arch_flag.name); 2455 fat_arch[i].offset = offset; 2456 if(archs[i].size > UINT32_MAX) 2457 error("file too large to create as a fat file because " 2458 "size field in struct fat_arch is only 32-bits and " 2459 "size (%llu) of architecture %s exceeds that", 2460 archs[i].size, archs[i].arch_flag.name); 2461 fat_arch[i].size = archs[i].size; 2462 fat_arch[i].align = 2; 2463 offset += archs[i].size; 2464 } 2465 if(errors != 0){ 2466 (void)unlink(output); 2467 return; 2468 } 2469#ifdef __LITTLE_ENDIAN__ 2470 swap_fat_header(fat_header, BIG_ENDIAN_BYTE_SEX); 2471 swap_fat_arch(fat_arch, narchs, BIG_ENDIAN_BYTE_SEX); 2472#endif /* __LITTLE_ENDIAN__ */ 2473 offset = sizeof(struct fat_header) + 2474 sizeof(struct fat_arch) * narchs; 2475 } 2476 else 2477 offset = 0; 2478 2479 /* flush out the fat headers if any */ 2480 output_flush(library, library_size, fd, 0, offset); 2481 2482 /* 2483 * The time_offsets array records the offsets to the table of conternts 2484 * archive header's ar_date fields. 2485 */ 2486 time_offsets = allocate(narchs * sizeof(uint32_t)); 2487 2488 /* 2489 * Now put each arch in the buffer. 2490 */ 2491 for(i = 0; i < narchs; i++){ 2492 p = library + offset; 2493 flush_start = p; 2494 arch = archs + i; 2495 2496 /* 2497 * If the input files only contains non-object files then the 2498 * byte sex of the output can't be determined which is needed for 2499 * the two binary long's of the table of contents. But since these 2500 * will be zero (the same in both byte sexes) because there are no 2501 * symbols in the table of contents if there are no object files. 2502 */ 2503 2504 /* put in the archive magic string */ 2505 memcpy(p, ARMAG, SARMAG); 2506 p += SARMAG; 2507 2508 /* 2509 * Warn for what really is a bad library that has an empty table of 2510 * contents but this is allowed in the original ranlib. 2511 */ 2512 if(arch->toc_nranlibs == 0 && cmd_flags.q == FALSE){ 2513 if(narchs > 1) 2514 warning("warning for library: %s for architecture: %s the " 2515 "table of contents is empty (no object file members" 2516 " in the library define global symbols)", output, 2517 arch->arch_flag.name); 2518 else 2519 warning("warning for library: %s the table of contents is " 2520 "empty (no object file members in the library " 2521 "define global symbols)", output); 2522 } 2523 2524 /* 2525 * Pick the byte sex to write the table of contents in. 2526 */ 2527 target_byte_sex = get_target_byte_sex(arch, host_byte_sex); 2528 2529 /* 2530 * Remember the offset to the archive header's time field for this 2531 * arch's table of contents member. 2532 */ 2533 time_offsets[i] = 2534 (p - library) + 2535 ((char *)&toc_ar_hdr.ar_date - (char *)&toc_ar_hdr); 2536 2537 /* 2538 * Put in the table of contents member in the output buffer. 2539 */ 2540 p = put_toc_member(p, arch, host_byte_sex, target_byte_sex); 2541 2542 output_flush(library, library_size, fd, flush_start - library, 2543 p - flush_start); 2544 2545 /* 2546 * Put in the archive header and member contents for each member. 2547 */ 2548 for(j = 0; j < arch->nmembers; j++){ 2549 flush_start = p; 2550 memcpy(p, (char *)&(arch->members[j].ar_hdr), 2551 sizeof(struct ar_hdr)); 2552 p += sizeof(struct ar_hdr); 2553 2554 /* 2555 * If we are using extended format #1 for long names write out 2556 * the name. Note the name is padded with '\0' and the 2557 * member_name_size is the unrounded size. 2558 */ 2559 if(arch->members[j].output_long_name == TRUE){ 2560 strncpy(p, arch->members[j].member_name, 2561 arch->members[j].member_name_size); 2562 p += rnd(arch->members[j].member_name_size, 8) + 2563 (rnd(sizeof(struct ar_hdr), 8) - 2564 sizeof(struct ar_hdr)); 2565 } 2566 2567 /* 2568 * ofile_map swaps the headers to the host_byte_sex if the 2569 * object's byte sex is not the same as the host byte sex so 2570 * if this is the case swap them back before writing them out. 2571 */ 2572 if(arch->members[j].mh != NULL && 2573 arch->members[j].object_byte_sex != host_byte_sex){ 2574 if(swap_object_headers(arch->members[j].mh, 2575 arch->members[j].load_commands) == FALSE) 2576 fatal("internal error: swap_object_headers() failed"); 2577 } 2578 else if(arch->members[j].mh64 != NULL && 2579 arch->members[j].object_byte_sex != host_byte_sex){ 2580 if(swap_object_headers(arch->members[j].mh64, 2581 arch->members[j].load_commands) == FALSE) 2582 fatal("internal error: swap_object_headers() failed"); 2583 } 2584 memcpy(p, arch->members[j].object_addr, 2585 arch->members[j].object_size); 2586#ifdef VM_SYNC_DEACTIVATE 2587 vm_msync(mach_task_self(), 2588 (vm_address_t)arch->members[j].object_addr, 2589 (vm_size_t)arch->members[j].object_size, 2590 VM_SYNC_DEACTIVATE); 2591#endif /* VM_SYNC_DEACTIVATE */ 2592 p += arch->members[j].object_size; 2593 pad = rnd(arch->members[j].object_size, 8) - 2594 arch->members[j].object_size; 2595 /* as with the UNIX ar(1) program pad with '\n' characters */ 2596 for(k = 0; k < pad; k++) 2597 *p++ = '\n'; 2598 2599 output_flush(library, library_size, fd, flush_start - library, 2600 p - flush_start); 2601 } 2602 offset += arch->size; 2603 } 2604 2605 /* 2606 * Write the library to the file or flush the remaining buffer to the 2607 * file. 2608 */ 2609 if(cmd_flags.noflush == TRUE){ 2610 if(write(fd, library, library_size) != (int)library_size){ 2611 system_error("can't write output file: %s", output); 2612 return; 2613 } 2614 } 2615 else{ 2616 final_output_flush(library, fd); 2617 } 2618 if(close(fd) == -1){ 2619 system_fatal("can't close output file: %s", output); 2620 return; 2621 } 2622 2623update_toc_ar_dates: 2624 /* 2625 * Now that the library is created on the file system it is written 2626 * to get the time for the file on that file system. 2627 */ 2628 if(stat(output, &stat_buf) == -1){ 2629 system_fatal("can't stat file output file: %s", output); 2630 return; 2631 } 2632 if((fd = open(output, O_WRONLY, 0)) == -1){ 2633 system_error("can't open output file: %s", output); 2634 return; 2635 } 2636 if(zero_ar_date == TRUE) 2637 stat_buf.st_mtime = 0; 2638 /* 2639 * With the time from the file system the library is on set the ar_date 2640 * using the modification time returned by stat. Then write this into 2641 * all the ar_date's in the file. 2642 */ 2643 sprintf((char *)(&toc_ar_hdr), "%-*s%-*ld", 2644 (int)sizeof(toc_ar_hdr.ar_name), 2645 SYMDEF, 2646 (int)sizeof(toc_ar_hdr.ar_date), 2647 (long int)stat_buf.st_mtime + 5); 2648 for(i = 0; i < narchs; i++){ 2649 if(lseek(fd, time_offsets[i], L_SET) == -1){ 2650 system_error("can't lseek in output file: %s", output); 2651 return; 2652 } 2653 if(write(fd, &toc_ar_hdr.ar_date, sizeof(toc_ar_hdr.ar_date)) != 2654 sizeof(toc_ar_hdr.ar_date)){ 2655 system_error("can't write to output file: %s", output); 2656 return; 2657 } 2658 } 2659 if(close(fd) == -1){ 2660 system_fatal("can't close output file: %s", output); 2661 return; 2662 } 2663 /* 2664 * Now set the modtime of the created library back to it's stat time 2665 * when we first closed it. 2666 */ 2667#ifndef __OPENSTEP__ 2668 timep.actime = stat_buf.st_mtime; 2669 timep.modtime = stat_buf.st_mtime; 2670 if(utime(output, &timep) == -1) 2671#else 2672 timep[0] = stat_buf.st_mtime; 2673 timep[1] = stat_buf.st_mtime; 2674 if(utime(output, timep) == -1) 2675#endif 2676 { 2677 system_fatal("can't set the modifiy times in output file: %s", 2678 output); 2679 return; 2680 } 2681 if((r = vm_deallocate(mach_task_self(), (vm_address_t)library, 2682 library_size)) != KERN_SUCCESS){ 2683 my_mach_error(r, "can't vm_deallocate() buffer for output file"); 2684 return; 2685 } 2686} 2687 2688/* 2689 * get_target_byte_sex() pick the byte sex to write the table of contents in 2690 * for the arch. 2691 */ 2692static 2693enum byte_sex 2694get_target_byte_sex( 2695struct arch *arch, 2696enum byte_sex host_byte_sex) 2697{ 2698 uint32_t i; 2699 enum byte_sex target_byte_sex; 2700 2701 target_byte_sex = UNKNOWN_BYTE_SEX; 2702 for(i = 0; 2703 i < arch->nmembers && target_byte_sex == UNKNOWN_BYTE_SEX; 2704 i++){ 2705 target_byte_sex = arch->members[i].object_byte_sex; 2706 } 2707 if(target_byte_sex == UNKNOWN_BYTE_SEX) 2708 target_byte_sex = host_byte_sex; 2709 return(target_byte_sex); 2710} 2711 2712/* 2713 * put_toc_member() put the contents member for arch into the buffer p and 2714 * returns the pointer to the buffer after the table of contents. 2715 * The table of contents member is: 2716 * the archive header 2717 * the archive member name (if using a long name) 2718 * a uint32_t for the number of bytes of the ranlib structs 2719 * the ranlib structs 2720 * a uint32_t for the number of bytes of the strings for the 2721 * ranlibs 2722 * the strings for the ranlib structs 2723 */ 2724static 2725char * 2726put_toc_member( 2727char *p, 2728struct arch *arch, 2729enum byte_sex host_byte_sex, 2730enum byte_sex target_byte_sex) 2731{ 2732 uint32_t l; 2733 2734 memcpy(p, (char *)&arch->toc_ar_hdr, sizeof(struct ar_hdr)); 2735 p += sizeof(struct ar_hdr); 2736 2737 if(arch->toc_long_name == TRUE){ 2738 memcpy(p, arch->toc_name, arch->toc_name_size); 2739 p += arch->toc_name_size + 2740 (rnd(sizeof(struct ar_hdr), 8) - 2741 sizeof(struct ar_hdr)); 2742 } 2743 2744 l = arch->toc_nranlibs * sizeof(struct ranlib); 2745 if(target_byte_sex != host_byte_sex) 2746 l = SWAP_INT(l); 2747 memcpy(p, (char *)&l, sizeof(uint32_t)); 2748 p += sizeof(uint32_t); 2749 2750 if(target_byte_sex != host_byte_sex) 2751 swap_ranlib(arch->toc_ranlibs, arch->toc_nranlibs, 2752 target_byte_sex); 2753 memcpy(p, (char *)arch->toc_ranlibs, 2754 arch->toc_nranlibs * sizeof(struct ranlib)); 2755 p += arch->toc_nranlibs * sizeof(struct ranlib); 2756 2757 l = arch->toc_strsize; 2758 if(target_byte_sex != host_byte_sex) 2759 l = SWAP_INT(l); 2760 memcpy(p, (char *)&l, sizeof(uint32_t)); 2761 p += sizeof(uint32_t); 2762 2763 memcpy(p, (char *)arch->toc_strings, arch->toc_strsize); 2764 p += arch->toc_strsize; 2765 2766 return(p); 2767} 2768 2769/* 2770 * output_flush() takes an offset and a size of part of the output library, 2771 * known in the comments as the new area, and causes any fully flushed pages to 2772 * be written to the library file the new area in combination with previous 2773 * areas created. The data structure output_blocks has ordered blocks of areas 2774 * that have been flushed which are maintained by this routine. Any area can 2775 * only be flushed once and an error will result is the new area overlaps with a 2776 * previously flushed area. 2777 */ 2778static 2779void 2780output_flush( 2781char *library, 2782uint64_t library_size, 2783int fd, 2784uint64_t offset, 2785uint64_t size) 2786{ 2787 uint64_t write_offset, write_size, host_pagesize; 2788 struct block **p, *block, *before, *after; 2789 kern_return_t r; 2790 2791 host_pagesize = 0x2000; 2792 2793 if(cmd_flags.noflush == TRUE) 2794 return; 2795 2796 if(offset + size > library_size) 2797 fatal("internal error: output_flush(offset = %llu, size = %llu) " 2798 "out of range for library_size = %llu", offset, size, 2799 library_size); 2800 2801#ifdef DEBUG 2802 if(cmd_flags.debug & (1 << 2)) 2803 print_block_list(); 2804 if(cmd_flags.debug & (1 << 1)) 2805 printf("output_flush(offset = %llu, size %llu)", offset, size); 2806#endif /* DEBUG */ 2807 2808 if(size == 0){ 2809#ifdef DEBUG 2810 if(cmd_flags.debug & (1 << 1)) 2811 printf("\n"); 2812#endif /* DEBUG */ 2813 return; 2814 } 2815 2816 /* 2817 * Search through the ordered output blocks to find the block before the 2818 * new area and after the new area if any exist. 2819 */ 2820 before = NULL; 2821 after = NULL; 2822 p = &(output_blocks); 2823 while(*p){ 2824 block = *p; 2825 if(offset < block->offset){ 2826 after = block; 2827 break; 2828 } 2829 else{ 2830 before = block; 2831 } 2832 p = &(block->next); 2833 } 2834 2835 /* 2836 * Check for overlap of the new area with the block before and after the 2837 * new area if there are such blocks. 2838 */ 2839 if(before != NULL){ 2840 if(before->offset + before->size > offset){ 2841 warning("internal error: output_flush(offset = %llu, size = " 2842 "%llu) overlaps with flushed block(offset = %llu, " 2843 "size = %llu)", offset, size, before->offset, 2844 before->size); 2845 printf("calling abort()\n"); 2846 abort(); 2847 } 2848 } 2849 if(after != NULL){ 2850 if(offset + size > after->offset){ 2851 warning("internal error: output_flush(offset = %llu, size = " 2852 "%llu) overlaps with flushed block(offset = %llu, " 2853 "size = %llu)", offset, size, after->offset, 2854 after->size); 2855 printf("calling abort()\n"); 2856 abort(); 2857 } 2858 } 2859 2860 /* 2861 * Now see how the new area fits in with the blocks before and after it 2862 * (that is does it touch both, one or the other or neither blocks). 2863 * For each case first the offset and size to write (write_offset and 2864 * write_size) are set for the area of full pages that can now be 2865 * written from the block. Then the area written in the block 2866 * (->written_offset and ->written_size) are set to reflect the total 2867 * area in the block now written. Then offset and size the block 2868 * refers to (->offset and ->size) are set to total area of the block. 2869 * Finally the links to others blocks in the list are adjusted if a 2870 * block is added or removed. 2871 * 2872 * See if there is a block before the new area and the new area 2873 * starts at the end of that block. 2874 */ 2875 if(before != NULL && before->offset + before->size == offset){ 2876 /* 2877 * See if there is also a block after the new area and the new area 2878 * ends at the start of that block. 2879 */ 2880 if(after != NULL && offset + size == after->offset){ 2881 /* 2882 * This is the case where the new area exactly fill the area 2883 * between two existing blocks. The total area is folded into 2884 * the block before the new area and the block after the new 2885 * area is removed from the list. 2886 */ 2887 if(before->offset == 0 && before->written_size == 0){ 2888 write_offset = 0; 2889 before->written_offset = 0; 2890 } 2891 else 2892 write_offset =before->written_offset + before->written_size; 2893 if(after->written_size == 0) 2894 write_size = trnc(after->offset + after->size - 2895 write_offset, host_pagesize); 2896 else 2897 write_size = trnc(after->written_offset - write_offset, 2898 host_pagesize); 2899 if(write_size != 0){ 2900 before->written_size += write_size; 2901 } 2902 if(after->written_size != 0) 2903 before->written_size += after->written_size; 2904 before->size += size + after->size; 2905 2906 /* remove the block after the new area */ 2907 before->next = after->next; 2908 remove_block(after); 2909 } 2910 else{ 2911 /* 2912 * This is the case where the new area starts at the end of the 2913 * block just before it but does not end where the block after 2914 * it (if any) starts. The new area is folded into the block 2915 * before the new area. 2916 */ 2917 write_offset = before->written_offset + before->written_size; 2918 write_size = trnc(offset + size - write_offset, host_pagesize); 2919 if(write_size != 0) 2920 before->written_size += write_size; 2921 before->size += size; 2922 } 2923 } 2924 /* 2925 * See if the new area and the new area ends at the start of the block 2926 * after it (if any). 2927 */ 2928 else if(after != NULL && offset + size == after->offset){ 2929 /* 2930 * This is the case where the new area ends at the begining of the 2931 * block just after it but does not start where the block before it. 2932 * (if any) ends. The new area is folded into this block after the 2933 * new area. 2934 */ 2935 write_offset = rnd(offset, host_pagesize); 2936 if(after->written_size == 0) 2937 write_size = trnc(after->offset + after->size - write_offset, 2938 host_pagesize); 2939 else 2940 write_size = trnc(after->written_offset - write_offset, 2941 host_pagesize); 2942 if(write_size != 0){ 2943 after->written_offset = write_offset; 2944 after->written_size += write_size; 2945 } 2946 else if(write_offset != after->written_offset){ 2947 after->written_offset = write_offset; 2948 } 2949 after->offset = offset; 2950 after->size += size; 2951 } 2952 else{ 2953 /* 2954 * This is the case where the new area neither starts at the end of 2955 * the block just before it (if any) or ends where the block after 2956 * it (if any) starts. A new block is created and the new area is 2957 * is placed in it. 2958 */ 2959 write_offset = rnd(offset, host_pagesize); 2960 write_size = trnc(offset + size - write_offset, host_pagesize); 2961 block = get_block(); 2962 block->offset = offset; 2963 block->size = size; 2964 block->written_offset = write_offset; 2965 block->written_size = write_size; 2966 /* 2967 * Insert this block in the ordered list in the correct place. 2968 */ 2969 if(before != NULL){ 2970 block->next = before->next; 2971 before->next = block; 2972 } 2973 else{ 2974 block->next = output_blocks; 2975 output_blocks = block; 2976 } 2977 } 2978 2979 /* 2980 * Now if there are full pages to write write them to the output file. 2981 */ 2982 if(write_size != 0){ 2983#ifdef DEBUG 2984 if((cmd_flags.debug & (1 << 1)) || (cmd_flags.debug & (1 << 0))) 2985 printf(" writing (write_offset = %llu write_size = %llu)\n", 2986 write_offset, write_size); 2987#endif /* DEBUG */ 2988 lseek(fd, write_offset, L_SET); 2989 if(write(fd, library + write_offset, write_size) != 2990 (int)write_size) 2991 system_fatal("can't write to output file"); 2992 if((r = vm_deallocate(mach_task_self(), (vm_address_t)(library + 2993 write_offset), write_size)) != KERN_SUCCESS) 2994 mach_fatal(r, "can't vm_deallocate() buffer for output file"); 2995 } 2996#ifdef DEBUG 2997 else{ 2998 if(cmd_flags.debug & (1 << 1)) 2999 printf(" no write\n"); 3000 } 3001#endif /* DEBUG */ 3002} 3003 3004/* 3005 * final_output_flush() flushes the last part of the last page of the object 3006 * file if it does not round out to exactly a page. 3007 */ 3008static 3009void 3010final_output_flush( 3011char *library, 3012int fd) 3013{ 3014 struct block *block; 3015 uint64_t write_offset, write_size; 3016 kern_return_t r; 3017 3018#ifdef DEBUG 3019 /* The compiler "warning: `write_offset' may be used uninitialized in */ 3020 /* this function" can safely be ignored */ 3021 write_offset = 0; 3022 if((cmd_flags.debug & (1 << 1)) || (cmd_flags.debug & (1 << 0))){ 3023 printf("final_output_flush block_list:\n"); 3024 print_block_list(); 3025 } 3026#endif /* DEBUG */ 3027 3028 write_size = 0; 3029 block = output_blocks; 3030 if(block != NULL){ 3031 if(block->offset != 0) 3032 fatal("internal error: first block not at offset 0"); 3033 if(block->written_size != 0){ 3034 if(block->written_offset != 0) 3035 fatal("internal error: first block written_offset not 0"); 3036 write_offset = block->written_size; 3037 write_size = block->size - block->written_size; 3038 } 3039 else{ 3040 write_offset = block->offset; 3041 write_size = block->size; 3042 } 3043 if(block->next != NULL) 3044 fatal("internal error: more than one block in final list"); 3045 } 3046 if(write_size != 0){ 3047#ifdef DEBUG 3048 if((cmd_flags.debug & (1 << 1)) || (cmd_flags.debug & (1 << 1))) 3049 printf(" writing (write_offset = %llu write_size = %llu)\n", 3050 write_offset, write_size); 3051#endif /* DEBUG */ 3052 lseek(fd, write_offset, L_SET); 3053 if(write(fd, library + write_offset, write_size) != 3054 (int)write_size) 3055 system_fatal("can't write to output file"); 3056 if((r = vm_deallocate(mach_task_self(), (vm_address_t)(library + 3057 write_offset), write_size)) != KERN_SUCCESS) 3058 mach_fatal(r, "can't vm_deallocate() buffer for output file"); 3059 } 3060 output_blocks = NULL; 3061} 3062 3063#ifdef DEBUG 3064/* 3065 * print_block_list() prints the list of blocks. Used for debugging. 3066 */ 3067static 3068void 3069print_block_list(void) 3070{ 3071 struct block **p, *block; 3072 3073 p = &(output_blocks); 3074 if(*p == NULL) 3075 printf("Empty block list\n"); 3076 while(*p){ 3077 block = *p; 3078 printf("block 0x%x\n", (unsigned int)block); 3079 printf(" offset %llu\n", block->offset); 3080 printf(" size %llu\n", block->size); 3081 printf(" written_offset %llu\n", block->written_offset); 3082 printf(" written_size %llu\n", block->written_size); 3083 printf(" next 0x%x\n", (unsigned int)(block->next)); 3084 p = &(block->next); 3085 } 3086} 3087#endif /* DEBUG */ 3088 3089/* 3090 * get_block() returns a pointer to a new block. This could be done by 3091 * allocating block of these placing them on a free list and and handing them 3092 * out. For the initial release of this code this number is typicly low and not 3093 * a big win so each block just allocated and free'ed. 3094 */ 3095static 3096struct block * 3097get_block(void) 3098{ 3099 struct block *block; 3100 3101 block = allocate(sizeof(struct block)); 3102 return(block); 3103} 3104 3105/* 3106 * remove_block() throws away the block specified. See comments in get_block(). 3107 */ 3108static 3109void 3110remove_block( 3111struct block *block) 3112{ 3113 free(block); 3114} 3115 3116/* 3117 * trnc() truncates the value 'v' to the power of two value 'r'. If v is 3118 * less than zero it returns zero. 3119 */ 3120static 3121uint32_t 3122trnc( 3123uint32_t v, 3124uint32_t r) 3125{ 3126 if(((int32_t)v) < 0) 3127 return(0); 3128 return(v & ~(r - 1)); 3129} 3130 3131/* 3132 * create_dynamic_shared_library() creates a dynamic shared library from the 3133 * data structure pointed to by archs into the specified output file. Only 3134 * when more than one architecture is in archs will a fat file be created. 3135 */ 3136static 3137void 3138create_dynamic_shared_library( 3139char *output) 3140{ 3141 uint32_t i, j; 3142 char *p, *filelist; 3143 struct stat stat_buf; 3144 enum bool use_force_cpusubtype_ALL; 3145 const struct arch_flag *family_arch_flag; 3146 3147 /* 3148 * If there is more than one architecture setup a signal handler to 3149 * clean up the temporary files in case we get a signal. 3150 */ 3151 if(narchs > 1) 3152 signal(SIGINT, create_dynamic_shared_library_cleanup); 3153 3154 /* 3155 * If -arch_only is specified with a specific cpusubtype other than the 3156 * family cpusubtype do not use -force_cpusubtype_ALL as the user wants 3157 * the output to be tagged with that cpusubtype. 3158 */ 3159 use_force_cpusubtype_ALL = TRUE; 3160 if(cmd_flags.arch_only_flag.name != NULL){ 3161 family_arch_flag = get_arch_family_from_cputype( 3162 cmd_flags.arch_only_flag.cputype); 3163 if(family_arch_flag != NULL){ 3164 if((family_arch_flag->cpusubtype & ~CPU_SUBTYPE_MASK) != 3165 (cmd_flags.arch_only_flag.cpusubtype & ~CPU_SUBTYPE_MASK)) 3166 use_force_cpusubtype_ALL = FALSE; 3167 } 3168 } 3169 3170 /* 3171 * For each architecture run ld(1) -dylib to create the dynamic shared 3172 * library. 3173 */ 3174 for(i = 0; i < narchs || (i == 0 && narchs == 0); i++){ 3175 reset_execute_list(); 3176 add_execute_list_with_prefix("ld"); 3177 if(narchs != 0 && cmd_flags.arch_only_flag.name == NULL) 3178 add_execute_list("-arch_multiple"); 3179 if(archs != NULL){ 3180 add_execute_list("-arch"); 3181 if(use_force_cpusubtype_ALL == TRUE) 3182 add_execute_list(archs[i].arch_flag.name); 3183 else 3184 add_execute_list(cmd_flags.arch_only_flag.name); 3185 } 3186 add_execute_list("-dylib"); 3187 add_execute_list("-dynamic"); 3188 if(cmd_flags.all_load_flag_specified == FALSE || 3189 cmd_flags.all_load == TRUE) 3190 add_execute_list("-all_load"); 3191 if(use_force_cpusubtype_ALL == TRUE) 3192 add_execute_list("-force_cpusubtype_ALL"); 3193 add_execute_list("-no_arch_warnings"); 3194 if(cmd_flags.seg1addr != NULL){ 3195 add_execute_list("-seg1addr"); 3196 add_execute_list(cmd_flags.seg1addr); 3197 } 3198 if(cmd_flags.segs_read_only_addr != NULL){ 3199 add_execute_list("-segs_read_only_addr"); 3200 add_execute_list(cmd_flags.segs_read_only_addr); 3201 } 3202 if(cmd_flags.segs_read_write_addr != NULL){ 3203 add_execute_list("-segs_read_write_addr"); 3204 add_execute_list(cmd_flags.segs_read_write_addr); 3205 } 3206 if(cmd_flags.seg_addr_table != NULL){ 3207 add_execute_list("-seg_addr_table"); 3208 add_execute_list(cmd_flags.seg_addr_table); 3209 } 3210 if(cmd_flags.seg_addr_table_filename != NULL){ 3211 add_execute_list("-seg_addr_table_filename"); 3212 add_execute_list(cmd_flags.seg_addr_table_filename); 3213 } 3214 if(cmd_flags.compatibility != NULL){ 3215 add_execute_list("-dylib_compatibility_version"); 3216 add_execute_list(cmd_flags.compatibility); 3217 } 3218 if(cmd_flags.current != NULL){ 3219 add_execute_list("-dylib_current_version"); 3220 add_execute_list(cmd_flags.current); 3221 } 3222 if(cmd_flags.install_name != NULL){ 3223 add_execute_list("-dylib_install_name"); 3224 add_execute_list(cmd_flags.install_name); 3225 } 3226 else{ 3227 if(narchs > 1){ 3228 add_execute_list("-dylib_install_name"); 3229 add_execute_list(cmd_flags.output); 3230 } 3231 } 3232 for(j = 0; j < cmd_flags.nldflags; j++) 3233 add_execute_list(cmd_flags.ldflags[j]); 3234 for(j = 0; j < cmd_flags.nLdirs; j++) 3235 add_execute_list(cmd_flags.Ldirs[j]); 3236 add_execute_list("-ldylib1.o"); 3237 filelist = NULL; 3238 for(j = 0; j < cmd_flags.nfiles; j++){ 3239 if(cmd_flags.filelist[j] == NULL){ 3240 add_execute_list(cmd_flags.files[j]); 3241 } 3242 else{ 3243 if(cmd_flags.filelist[j] != filelist){ 3244 add_execute_list("-filelist"); 3245 add_execute_list(cmd_flags.filelist[j]); 3246 filelist = cmd_flags.filelist[j]; 3247 } 3248 } 3249 } 3250 if(narchs <= 1){ 3251 add_execute_list("-o"); 3252 add_execute_list(cmd_flags.output); 3253 } 3254 else{ 3255 add_execute_list("-o"); 3256 add_execute_list(makestr(cmd_flags.output, ".libtool.", 3257 archs[i].arch_flag.name, NULL)); 3258 if(cmd_flags.final_output_specified == FALSE){ 3259 add_execute_list("-final_output"); 3260 add_execute_list(cmd_flags.output); 3261 } 3262 } 3263 if(execute_list(cmd_flags.verbose) == 0) 3264 fatal("internal link edit command failed"); 3265 } 3266 /* 3267 * If there is more than one architecture then run lipo to put them 3268 * in a fat file. 3269 */ 3270 if(narchs > 1){ 3271 reset_execute_list(); 3272 add_execute_list_with_prefix("lipo"); 3273 add_execute_list("-create"); 3274 add_execute_list("-output"); 3275 add_execute_list(cmd_flags.output); 3276 for(i = 0; i < narchs; i++){ 3277 add_execute_list(makestr(cmd_flags.output, ".libtool.", 3278 archs[i].arch_flag.name, NULL)); 3279 } 3280 if(execute_list(cmd_flags.verbose) == 0) 3281 fatal("internal lipo command failed"); 3282 for(i = 0; i < narchs; i++){ 3283 p = makestr(cmd_flags.output, ".libtool.", 3284 archs[i].arch_flag.name, NULL); 3285 if(unlink(p) == -1){ 3286 error("can't remove temporary file: %s", p); 3287 } 3288 } 3289 } 3290 /* 3291 * If we are doing prebinding then run objcunique on the 3292 * output. 3293 */ 3294 if(cmd_flags.prebinding == TRUE){ 3295 if(stat("/usr/bin/objcunique", &stat_buf) != -1){ 3296 reset_execute_list(); 3297 add_execute_list_with_prefix("objcunique"); 3298 add_execute_list(cmd_flags.output); 3299 add_execute_list("-prebind"); 3300 for(j = 0; j < cmd_flags.nLdirs; j++) 3301 add_execute_list(cmd_flags.Ldirs[j]); 3302 if(execute_list(cmd_flags.verbose) == 0) 3303 fatal("internal objcunique command failed"); 3304 } 3305 } 3306} 3307 3308/* 3309 * create_dynamic_shared_library_cleanup() is the signal handler to remove the 3310 * temporary files if more than one arch is being used. 3311 */ 3312static 3313void 3314create_dynamic_shared_library_cleanup( 3315int sig) 3316{ 3317 uint32_t i; 3318 3319 for(i = 0; i < narchs; i++){ 3320 (void)unlink(makestr(cmd_flags.output, ".libtool.", 3321 archs[i].arch_flag.name, NULL)); 3322 } 3323 exit(EXIT_FAILURE); 3324} 3325 3326/* 3327 * make_table_of_contents() make the table of contents for the specified arch 3328 * and fills in the toc_* fields in the arch. Output is the name of the output 3329 * file for error messages. 3330 */ 3331static 3332void 3333make_table_of_contents( 3334struct arch *arch, 3335char *output) 3336{ 3337 uint32_t i, j, k, r, s, nsects, ncmds, n_strx; 3338 struct member *member; 3339 struct load_command *lc; 3340 struct segment_command *sg; 3341 struct segment_command_64 *sg64; 3342 struct nlist *symbols; 3343 struct nlist_64 *symbols64; 3344 char *strings; 3345 enum bool sorted, is_toc_symbol; 3346 char *ar_name; 3347 struct section *section; 3348 struct section_64 *section64; 3349 uint8_t n_type, n_sect; 3350#ifdef LTO_SUPPORT 3351 uint32_t nsyms; 3352#endif /* LTO_SUPPORT */ 3353 3354 symbols = NULL; 3355 symbols64 = NULL; 3356 /* 3357 * First pass over the members to count how many ranlib structs are 3358 * needed and the size of the strings in the toc that are needed. 3359 */ 3360 for(i = 0; i < arch->nmembers; i++){ 3361 member = arch->members + i; 3362 if(member->mh != NULL || member->mh64 != NULL){ 3363 nsects = 0; 3364 lc = member->load_commands; 3365 if(member->mh != NULL) 3366 ncmds = member->mh->ncmds; 3367 else 3368 ncmds = member->mh64->ncmds; 3369 for(j = 0; j < ncmds; j++){ 3370 if(lc->cmd == LC_SYMTAB){ 3371 if(member->st == NULL) 3372 member->st = (struct symtab_command *)lc; 3373 } 3374 else if(lc->cmd == LC_SEGMENT){ 3375 sg = (struct segment_command *)lc; 3376 nsects += sg->nsects; 3377 } 3378 else if(lc->cmd == LC_SEGMENT_64){ 3379 sg64 = (struct segment_command_64 *)lc; 3380 nsects += sg64->nsects; 3381 } 3382 lc = (struct load_command *)((char *)lc + lc->cmdsize); 3383 } 3384 if(member->mh != NULL) 3385 member->sections = allocate(nsects * 3386 sizeof(struct section *)); 3387 else 3388 member->sections64 = allocate(nsects * 3389 sizeof(struct section_64 *)); 3390 nsects = 0; 3391 lc = member->load_commands; 3392 for(j = 0; j < ncmds; j++){ 3393 if(lc->cmd == LC_SEGMENT){ 3394 sg = (struct segment_command *)lc; 3395 section = (struct section *) 3396 ((char *)sg + sizeof(struct segment_command)); 3397 for(k = 0; k < sg->nsects; k++){ 3398 member->sections[nsects++] = section++; 3399 } 3400 } 3401 else if(lc->cmd == LC_SEGMENT_64){ 3402 sg64 = (struct segment_command_64 *)lc; 3403 section64 = (struct section_64 *) 3404 ((char *)sg64 + sizeof(struct segment_command_64)); 3405 for(k = 0; k < sg64->nsects; k++){ 3406 member->sections64[nsects++] = section64++; 3407 } 3408 } 3409 lc = (struct load_command *)((char *)lc + lc->cmdsize); 3410 } 3411 if(member->st != NULL && member->st->nsyms != 0){ 3412 if(member->mh != NULL){ 3413 symbols = (struct nlist *)(member->object_addr + 3414 member->st->symoff); 3415 if(member->object_byte_sex != get_host_byte_sex()) 3416 swap_nlist(symbols, member->st->nsyms, 3417 get_host_byte_sex()); 3418 } 3419 else{ 3420 symbols64 = (struct nlist_64 *)(member->object_addr + 3421 member->st->symoff); 3422 if(member->object_byte_sex != get_host_byte_sex()) 3423 swap_nlist_64(symbols64, member->st->nsyms, 3424 get_host_byte_sex()); 3425 } 3426 strings = member->object_addr + member->st->stroff; 3427 for(j = 0; j < member->st->nsyms; j++){ 3428 if(member->mh != NULL){ 3429 n_strx = symbols[j].n_un.n_strx; 3430 n_type = symbols[j].n_type; 3431 n_sect = symbols[j].n_sect; 3432 } 3433 else{ 3434 n_strx = symbols64[j].n_un.n_strx; 3435 n_type = symbols64[j].n_type; 3436 n_sect = symbols64[j].n_sect; 3437 } 3438 if(n_strx > member->st->strsize){ 3439 warn_member(arch, member, "malformed object " 3440 "(symbol %u n_strx field extends past the " 3441 "end of the string table)", j); 3442 errors++; 3443 continue; 3444 } 3445 if((n_type & N_TYPE) == N_SECT){ 3446 if(n_sect == NO_SECT){ 3447 warn_member(arch, member, "malformed object " 3448 "(symbol %u must not have NO_SECT for its " 3449 "n_sect field given its type (N_SECT))", j); 3450 errors++; 3451 continue; 3452 } 3453 if(n_sect > nsects){ 3454 warn_member(arch, member, "malformed object " 3455 "(symbol %u n_sect field greater than the " 3456 "number of sections in the file)", j); 3457 errors++; 3458 continue; 3459 } 3460 } 3461 if(member->mh != NULL) 3462 is_toc_symbol = toc_symbol(symbols + j, 3463 member->sections); 3464 else 3465 is_toc_symbol = toc_symbol_64(symbols64 + j, 3466 member->sections64); 3467 if(is_toc_symbol == TRUE){ 3468 arch->toc_nranlibs++; 3469 arch->toc_strsize += strlen(strings + n_strx) + 1; 3470 } 3471 } 3472 } 3473 else 3474 warn_member(arch, member, "has no symbols"); 3475 } 3476#ifdef LTO_SUPPORT 3477 else if(member->lto != NULL){ 3478 nsyms = lto_get_nsyms(member->lto); 3479 for(j = 0; j < nsyms; j++){ 3480 if(lto_toc_symbol(member->lto, j, cmd_flags.c) == TRUE){ 3481 arch->toc_nranlibs++; 3482 arch->toc_strsize += 3483 strlen(lto_symbol_name(member->lto, j)) + 1; 3484 } 3485 } 3486 } 3487#endif /* LTO_SUPPORT */ 3488 else{ 3489 if(cmd_flags.ranlib == FALSE){ 3490 warn_member(arch, member, "is not an object file"); 3491 errors++; 3492 } 3493 } 3494 } 3495 if(errors != 0) 3496 return; 3497 3498 /* 3499 * Allocate the space for the ranlib structs and strings for the 3500 * table of contents. 3501 */ 3502 arch->toc_ranlibs = allocate(sizeof(struct ranlib) *arch->toc_nranlibs); 3503 arch->tocs = allocate(sizeof(struct toc) * arch->toc_nranlibs); 3504 arch->toc_strsize = rnd(arch->toc_strsize, 8); 3505 arch->toc_strings = allocate(arch->toc_strsize); 3506 3507 /* 3508 * Second pass over the members to fill in the ranlib structs and 3509 * the strings for the table of contents. The ran_name field is 3510 * filled in with a pointer to a string contained in arch->toc_strings 3511 * for easy sorting and conversion to an index. The ran_off field is 3512 * filled in with the member index plus one to allow marking with it's 3513 * negative value by check_sort_tocs() and easy conversion to the 3514 * real offset. 3515 */ 3516 r = 0; 3517 s = 0; 3518 for(i = 0; i < arch->nmembers; i++){ 3519 member = arch->members + i; 3520 if(member->mh != NULL || member->mh64 != NULL){ 3521 if(member->st != NULL && member->st->nsyms != 0){ 3522 if(member->mh != NULL) 3523 symbols = (struct nlist *)(member->object_addr + 3524 member->st->symoff); 3525 else 3526 symbols64 = (struct nlist_64 *)(member->object_addr + 3527 member->st->symoff); 3528 strings = member->object_addr + member->st->stroff; 3529 for(j = 0; j < member->st->nsyms; j++){ 3530 if(member->mh != NULL) 3531 n_strx = symbols[j].n_un.n_strx; 3532 else 3533 n_strx = symbols64[j].n_un.n_strx; 3534 if(n_strx > member->st->strsize) 3535 continue; 3536 if(member->mh != NULL) 3537 is_toc_symbol = toc_symbol(symbols + j, 3538 member->sections); 3539 else 3540 is_toc_symbol = toc_symbol_64(symbols64 + j, 3541 member->sections64); 3542 if(is_toc_symbol == TRUE){ 3543 strcpy(arch->toc_strings + s, 3544 strings + n_strx); 3545 arch->tocs[r].name = arch->toc_strings + s; 3546 arch->tocs[r].index1 = i + 1; 3547 r++; 3548 s += strlen(strings + n_strx) + 1; 3549 } 3550 } 3551 if(member->object_byte_sex != get_host_byte_sex()){ 3552 if(member->mh != NULL) 3553 swap_nlist(symbols, member->st->nsyms, 3554 member->object_byte_sex); 3555 else 3556 swap_nlist_64(symbols64, member->st->nsyms, 3557 member->object_byte_sex); 3558 } 3559 } 3560 } 3561#ifdef LTO_SUPPORT 3562 else if(member->lto != NULL){ 3563 nsyms = lto_get_nsyms(member->lto); 3564 for(j = 0; j < nsyms; j++){ 3565 if(lto_toc_symbol(member->lto, j, cmd_flags.c) == TRUE){ 3566 strcpy(arch->toc_strings + s, 3567 lto_symbol_name(member->lto, j)); 3568 arch->tocs[r].name = arch->toc_strings + s; 3569 arch->tocs[r].index1 = i + 1; 3570 r++; 3571 s += strlen(lto_symbol_name(member->lto, j)) + 1; 3572 } 3573 } 3574 } 3575#endif /* LTO_SUPPORT */ 3576 } 3577 3578 /* 3579 * If the table of contents is to be sorted by symbol name then try to 3580 * sort it and leave it sorted if no duplicates. 3581 */ 3582 if(cmd_flags.s == TRUE){ 3583 qsort(arch->tocs, arch->toc_nranlibs, sizeof(struct toc), 3584 (int (*)(const void *, const void *))toc_name_qsort); 3585 sorted = check_sort_tocs(arch, output, FALSE); 3586 if(sorted == FALSE){ 3587 qsort(arch->tocs, arch->toc_nranlibs, sizeof(struct toc), 3588 (int (*)(const void *, const void *))toc_index1_qsort); 3589 arch->toc_name = SYMDEF; 3590 arch->toc_name_size = sizeof(SYMDEF) - 1; 3591 if(cmd_flags.use_long_names == TRUE){ 3592 arch->toc_long_name = TRUE; 3593 /* 3594 * This assumes that "__.SYMDEF\0\0\0\0\0\0\0" is 16 bytes 3595 * and 3596 * (rnd(sizeof(struct ar_hdr), 8) - sizeof(struct ar_hdr) 3597 * is 4 bytes. 3598 */ 3599 ar_name = AR_EFMT1 "20"; 3600 arch->toc_name_size = 16; 3601 arch->toc_name = SYMDEF "\0\0\0\0\0\0\0"; 3602 } 3603 else{ 3604 arch->toc_long_name = FALSE; 3605 ar_name = arch->toc_name; 3606 } 3607 } 3608 else{ 3609 /* 3610 * Since the SYMDEF_SORTED is "__.SYMDEF SORTED" which contains 3611 * a space, it should use extended format #1 if we can use long 3612 * names. 3613 */ 3614 arch->toc_name = SYMDEF_SORTED; 3615 arch->toc_name_size = sizeof(SYMDEF_SORTED) - 1; 3616 if(cmd_flags.use_long_names == TRUE){ 3617 arch->toc_long_name = TRUE; 3618 /* 3619 * This assumes that "__.SYMDEF SORTED" is 16 bytes and 3620 * (rnd(sizeof(struct ar_hdr), 8) - sizeof(struct ar_hdr) 3621 * is 4 bytes. 3622 */ 3623 ar_name = AR_EFMT1 "20"; 3624 } 3625 else{ 3626 arch->toc_long_name = FALSE; 3627 ar_name = arch->toc_name; 3628 } 3629 } 3630 } 3631 else{ 3632 sorted = FALSE; 3633 arch->toc_name = SYMDEF; 3634 arch->toc_name_size = sizeof(SYMDEF) - 1; 3635 if(cmd_flags.use_long_names == TRUE){ 3636 arch->toc_long_name = TRUE; 3637 /* 3638 * This assumes that "__.SYMDEF\0\0\0\0\0\0\0" is 16 bytes and 3639 * (rnd(sizeof(struct ar_hdr), 8) - sizeof(struct ar_hdr) 3640 * is 4 bytes. 3641 */ 3642 ar_name = AR_EFMT1 "20"; 3643 arch->toc_name_size = 16; 3644 arch->toc_name = SYMDEF "\0\0\0\0\0\0\0"; 3645 } 3646 else{ 3647 arch->toc_long_name = FALSE; 3648 ar_name = arch->toc_name; 3649 } 3650 } 3651 3652 /* 3653 * Now set the ran_off and ran_un.ran_strx fields of the ranlib structs. 3654 * To do this the size of the toc member must be know because it comes 3655 * first in the library. The size of the toc member is made up of the 3656 * sizeof an archive header struct (the size of the name if a long name 3657 * is used) then the toc which is (as defined in ranlib.h): 3658 * a uint32_t for the number of bytes of the ranlib structs 3659 * the ranlib structures 3660 * a uint32_t for the number of bytes of the strings 3661 * the strings 3662 */ 3663 arch->toc_size = sizeof(struct ar_hdr) + 3664 sizeof(uint32_t) + 3665 arch->toc_nranlibs * sizeof(struct ranlib) + 3666 sizeof(uint32_t) + 3667 arch->toc_strsize; 3668 /* add the size of the name is a long name is used */ 3669 if(arch->toc_long_name == TRUE) 3670 arch->toc_size += arch->toc_name_size + 3671 (rnd(sizeof(struct ar_hdr), 8) - 3672 sizeof(struct ar_hdr)); 3673 for(i = 0; i < arch->nmembers; i++) 3674 arch->members[i].offset += SARMAG + arch->toc_size; 3675 for(i = 0; i < arch->toc_nranlibs; i++){ 3676 arch->toc_ranlibs[i].ran_un.ran_strx = 3677 arch->tocs[i].name - arch->toc_strings; 3678 arch->toc_ranlibs[i].ran_off = 3679 arch->members[arch->tocs[i].index1 - 1].offset; 3680 } 3681 3682 sprintf((char *)(&arch->toc_ar_hdr), "%-*s%-*ld%-*u%-*u%-*o%-*ld", 3683 (int)sizeof(arch->toc_ar_hdr.ar_name), 3684 ar_name, 3685 (int)sizeof(arch->toc_ar_hdr.ar_date), 3686 toc_time, 3687 (int)sizeof(arch->toc_ar_hdr.ar_uid), 3688 (unsigned short)getuid(), 3689 (int)sizeof(arch->toc_ar_hdr.ar_gid), 3690 (unsigned short)getgid(), 3691 (int)sizeof(arch->toc_ar_hdr.ar_mode), 3692 (unsigned int)toc_mode, 3693 (int)sizeof(arch->toc_ar_hdr.ar_size), 3694 (long)(arch->toc_size - sizeof(struct ar_hdr))); 3695 /* 3696 * This has to be done by hand because sprintf puts a null 3697 * at the end of the buffer. 3698 */ 3699 memcpy(arch->toc_ar_hdr.ar_fmag, ARFMAG, 3700 (int)sizeof(arch->toc_ar_hdr.ar_fmag)); 3701} 3702 3703/* 3704 * Function for qsort() for comparing toc structures by name. 3705 */ 3706static 3707int 3708toc_name_qsort( 3709const struct toc *toc1, 3710const struct toc *toc2) 3711{ 3712 return(strcmp(toc1->name, toc2->name)); 3713} 3714 3715/* 3716 * Function for qsort() for comparing toc structures by index1. 3717 */ 3718static 3719int 3720toc_index1_qsort( 3721const struct toc *toc1, 3722const struct toc *toc2) 3723{ 3724 if(toc1->index1 < toc2->index1) 3725 return(-1); 3726 if(toc1->index1 > toc2->index1) 3727 return(1); 3728 /* toc1->index1 == toc2->index1 */ 3729 return(0); 3730} 3731 3732/* 3733 * toc_symbol() returns TRUE if the symbol is to be included in the table of 3734 * contents otherwise it returns FALSE. 3735 */ 3736static 3737enum bool 3738toc_symbol( 3739struct nlist *symbol, 3740struct section **sections) 3741{ 3742 return(toc(symbol->n_un.n_strx, 3743 symbol->n_type, 3744 symbol->n_value, 3745 (symbol->n_type & N_TYPE) == N_SECT && 3746 sections[symbol->n_sect - 1]->flags & S_ATTR_NO_TOC)); 3747} 3748 3749static 3750enum bool 3751toc_symbol_64( 3752struct nlist_64 *symbol64, 3753struct section_64 **sections64) 3754{ 3755 return(toc(symbol64->n_un.n_strx, 3756 symbol64->n_type, 3757 symbol64->n_value, 3758 (symbol64->n_type & N_TYPE) == N_SECT && 3759 sections64[symbol64->n_sect-1]->flags & S_ATTR_NO_TOC)); 3760} 3761 3762static 3763enum bool 3764toc( 3765uint32_t n_strx, 3766uint8_t n_type, 3767uint64_t n_value, 3768enum bool attr_no_toc) 3769{ 3770 /* if the name is NULL then it won't be in the table of contents */ 3771 if(n_strx == 0) 3772 return(FALSE); 3773 /* if symbol is not external then it won't be in the toc */ 3774 if((n_type & N_EXT) == 0) 3775 return(FALSE); 3776 /* if symbol is undefined then it won't be in the toc */ 3777 if((n_type & N_TYPE) == N_UNDF && n_value == 0) 3778 return(FALSE); 3779 /* if symbol is common and the -c flag is not specified then ... */ 3780 if((n_type & N_TYPE) == N_UNDF && n_value != 0 && 3781 cmd_flags.c == FALSE) 3782 return(FALSE); 3783 /* if the symbols is in a section marked NO_TOC then ... */ 3784 if(attr_no_toc != 0) 3785 return(FALSE); 3786 3787 return(TRUE); 3788} 3789 3790/* 3791 * check_sort_tocs() checks the table of contents for the specified arch 3792 * which is sorted by name for more then one object defining the same symbol. 3793 * It this is the case it prints each symbol that is defined in more than one 3794 * object along with the object it is defined in. It returns TRUE if there are 3795 * no multiple definitions and FALSE otherwise. 3796 */ 3797static 3798enum bool 3799check_sort_tocs( 3800struct arch *arch, 3801char *output, 3802enum bool library_warnings) 3803{ 3804 uint32_t i; 3805 enum bool multiple_defs; 3806 struct member *member; 3807 3808 if(arch->toc_nranlibs == 0) 3809 return(TRUE); 3810 /* 3811 * Since the symbol table is sorted by name look to any two adjcent 3812 * entries with the same name. If such entries are found print them 3813 * only once (marked by changing the sign of their ran_off). 3814 */ 3815 multiple_defs = FALSE; 3816 for(i = 0; i < arch->toc_nranlibs - 1; i++){ 3817 if(strcmp(arch->tocs[i].name, arch->tocs[i+1].name) == 0){ 3818 if(multiple_defs == FALSE){ 3819 if(library_warnings == FALSE) 3820 return(FALSE); 3821 fprintf(stderr, "%s: same symbol defined in more than one " 3822 "member ", progname); 3823 if(narchs > 1) 3824 fprintf(stderr, "for architecture: %s ", 3825 arch->arch_flag.name); 3826 fprintf(stderr, "in: %s (table of contents will not be " 3827 "sorted)\n", output); 3828 multiple_defs = TRUE; 3829 } 3830 if((int)(arch->tocs[i].index1) > 0){ 3831 member = arch->members + arch->tocs[i].index1 - 1; 3832 warn_member(arch, member, "defines symbol: %s", 3833 arch->tocs[i].name); 3834 arch->tocs[i].index1 = 3835 -(arch->tocs[i].index1); 3836 } 3837 if((int)(arch->tocs[i+1].index1) > 0){ 3838 member = arch->members + arch->tocs[i+1].index1 - 1; 3839 warn_member(arch, member, "defines symbol: %s", 3840 arch->tocs[i+1].name); 3841 arch->tocs[i+1].index1 = 3842 -(arch->tocs[i+1].index1); 3843 } 3844 } 3845 } 3846 3847 if(multiple_defs == FALSE) 3848 return(TRUE); 3849 else{ 3850 for(i = 0; i < arch->toc_nranlibs; i++) 3851 if(((int)arch->tocs[i].index1) < 0) 3852 arch->tocs[i].index1 = 3853 -(arch->tocs[i].index1); 3854 return(FALSE); 3855 } 3856} 3857 3858/* 3859 * warn_duplicate_member_names() generates a warning if two members end up with 3860 * the same ar_name. This is only a warning because ld(1) and this program 3861 * has no problems with it. Only if ar(1) were used to extract the files 3862 * would this be a problem (even the 4.4bsd ar(1) using long names can 3863 * get hosed by base names, the 4.3bsd ar(1) can't handle full 16 character 3864 * ar_names). 3865 */ 3866static 3867void 3868warn_duplicate_member_names( 3869void) 3870{ 3871 uint32_t i, j, len, len1, len2; 3872 3873 for(i = 0; i < narchs; i++){ 3874 /* sort in order of ar_names */ 3875 qsort(archs[i].members, archs[i].nmembers, sizeof(struct member), 3876 (int (*)(const void *, const void *))member_name_qsort); 3877 3878 /* check for duplicate names */ 3879 for(j = 0; j < archs[i].nmembers - 1; j++){ 3880 len1 = archs[i].members[j].member_name_size; 3881 len2 = archs[i].members[j+1].member_name_size; 3882 len = len1 > len2 ? len1 : len2; 3883 if(strncmp(archs[i].members[j].member_name, 3884 archs[i].members[j+1].member_name, 3885 len) == 0){ 3886 fprintf(stderr, "%s: warning ", progname); 3887 if(narchs > 1) 3888 fprintf(stderr, "for architecture: %s ", 3889 archs[i].arch_flag.name); 3890 fprintf(stderr, "same member name (%.*s) in output file " 3891 "used for input files: ", (int)len1, 3892 archs[i].members[j].member_name); 3893 3894 if(archs[i].members[j].input_ar_hdr != NULL){ 3895 len = archs[i].members[j].input_base_name_size; 3896 fprintf(stderr, "%s(%.*s) and: ", 3897 archs[i].members[j].input_file_name, (int)len, 3898 archs[i].members[j].input_base_name); 3899 } 3900 else 3901 fprintf(stderr, "%s and: ", 3902 archs[i].members[j].input_file_name); 3903 3904 if(archs[i].members[j+1].input_ar_hdr != NULL){ 3905 len = archs[i].members[j+1].input_base_name_size; 3906 fprintf(stderr, "%s(%.*s) due to use of basename, " 3907 "truncation and blank padding\n", 3908 archs[i].members[j+1].input_file_name, (int)len, 3909 archs[i].members[j+1].input_base_name); 3910 } 3911 else 3912 fprintf(stderr, "%s (due to use of basename, truncation" 3913 ", blank padding or duplicate input files)\n", 3914 archs[i].members[j+1].input_file_name); 3915 } 3916 } 3917 3918 /* sort back in order of offset */ 3919 qsort(archs[i].members, archs[i].nmembers, sizeof(struct member), 3920 (int (*)(const void *, const void *))member_offset_qsort); 3921 } 3922} 3923 3924/* 3925 * Function for qsort() for comparing member structures by ar_hdr.ar_name. 3926 */ 3927static 3928int 3929member_name_qsort( 3930const struct member *member1, 3931const struct member *member2) 3932{ 3933 uint32_t len, len1, len2; 3934 3935 len1 = member1->member_name_size; 3936 len2 = member2->member_name_size; 3937 len = len1 > len2 ? len1 : len2; 3938 return(strncmp(member1->member_name, member2->member_name, len)); 3939} 3940 3941/* 3942 * Function for qsort() for comparing member structures by offset. 3943 */ 3944static 3945int 3946member_offset_qsort( 3947const struct member *member1, 3948const struct member *member2) 3949{ 3950 if(member1->offset < member2->offset) 3951 return(-1); 3952 if(member1->offset > member2->offset) 3953 return(1); 3954 /* member1->offset == member2->offset */ 3955 return(0); 3956} 3957 3958/* 3959 * warn_member() is like the error routines it prints the program name the 3960 * member name specified and message specified. 3961 */ 3962static 3963void 3964warn_member( 3965struct arch *arch, 3966struct member *member, 3967const char *format, ...) 3968{ 3969 va_list ap; 3970 3971 fprintf(stderr, "%s: ", progname); 3972 if(narchs > 1) 3973 fprintf(stderr, "for architecture: %s ", arch->arch_flag.name); 3974 3975 if(member->input_ar_hdr != NULL){ 3976 fprintf(stderr, "file: %s(%.*s) ", member->input_file_name, 3977 (int)member->input_base_name_size, member->input_base_name); 3978 } 3979 else 3980 fprintf(stderr, "file: %s ", member->input_file_name); 3981 3982 va_start(ap, format); 3983 vfprintf(stderr, format, ap); 3984 fprintf(stderr, "\n"); 3985 va_end(ap); 3986} 3987 3988/* 3989 * Prints the message to cmd_flags.trace_file_path, or stderr if that 3990 * isn't set. 3991 */ 3992static 3993void 3994ld_trace( 3995const char *format, ...) 3996{ 3997 static int trace_file = -1; 3998 char trace_buffer[MAXPATHLEN * 2]; 3999 char *buffer_ptr; 4000 int length; 4001 ssize_t amount_written; 4002 4003 if(trace_file == -1){ 4004 if(cmd_flags.trace_file_path != NULL){ 4005 trace_file = open(cmd_flags.trace_file_path, O_WRONLY | O_APPEND | O_CREAT, 0666); 4006 if(trace_file == -1) 4007 error("Could not open or create trace file: %s\n", cmd_flags.trace_file_path); 4008 } 4009 else{ 4010 trace_file = fileno(stderr); 4011 } 4012 } 4013 va_list ap; 4014 4015 va_start(ap, format); 4016 length = vsnprintf(trace_buffer, sizeof(trace_buffer), format, ap); 4017 va_end(ap); 4018 buffer_ptr = trace_buffer; 4019 while(length > 0){ 4020 amount_written = write(trace_file, buffer_ptr, length); 4021 if(amount_written == -1) 4022 /* Failure to write shouldn't fail the build. */ 4023 return; 4024 buffer_ptr += amount_written; 4025 length -= amount_written; 4026 } 4027} 4028