1/* 2 * Copyright (c) 1999 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#ifndef RLD 24#include <sys/time.h> 25#include <mach/mach.h> 26#include "stuff/openstep_mach.h" 27#include <libc.h> 28#ifndef __OPENSTEP__ 29#include <utime.h> 30#endif 31#include "stuff/ofile.h" 32#include "stuff/breakout.h" 33#include "stuff/allocate.h" 34#include "stuff/rnd.h" 35#include "stuff/errors.h" 36 37static void copy_new_symbol_info( 38 char *p, 39 uint32_t *size, 40 struct dysymtab_command *dyst, 41 struct dysymtab_command *old_dyst, 42 struct twolevel_hints_command *hints_cmd, 43 struct twolevel_hints_command *old_hints_cmd, 44 struct object *object); 45 46static void make_table_of_contents( 47 struct arch *archs, 48 char *output, 49 time_t toc_time, 50 enum bool sort_toc, 51 enum bool commons_in_toc, 52 enum bool library_warnings); 53 54static enum bool toc_symbol( 55 struct nlist *symbol, 56 enum bool commons_in_toc, 57 struct section **sections); 58 59static enum bool toc_symbol_64( 60 struct nlist_64 *symbol64, 61 enum bool commons_in_toc, 62 struct section_64 **sections64); 63 64static enum bool toc( 65 uint32_t n_strx, 66 uint8_t n_type, 67 uint64_t n_value, 68 enum bool commons_in_toc, 69 enum bool attr_no_toc); 70 71static int toc_entry_name_qsort( 72 const struct toc_entry *toc1, 73 const struct toc_entry *toc2); 74 75static int toc_entry_index_qsort( 76 const struct toc_entry *toc1, 77 const struct toc_entry *toc2); 78 79static enum bool check_sort_toc_entries( 80 struct arch *arch, 81 char *output, 82 enum bool library_warnings); 83 84static void warn_member( 85 struct arch *arch, 86 struct member *member, 87 const char *format, ...) 88#ifndef __MWERKS__ 89 __attribute__ ((format (printf, 3, 4))) 90#endif 91 ; 92 93/* 94 * writeout() creates an ofile from the data structure pointed to by 95 * archs (of narchs size) into the specified output file (output). The file is 96 * created with the mode, mode. If there are libraries in the data structures 97 * a new table of contents is created and is sorted if sort_toc is TRUE and 98 * commons symbols are included in the table of contents if commons_in_toc is 99 * TRUE. The normal use will have sort_toc == TRUE and commons_in_toc == FALSE. 100 * If warnings about unusual libraries are printed if library_warnings == TRUE. 101 */ 102__private_extern__ 103void 104writeout( 105struct arch *archs, 106uint32_t narchs, 107char *output, 108unsigned short mode, 109enum bool sort_toc, 110enum bool commons_in_toc, 111enum bool library_warnings, 112uint32_t *throttle) 113{ 114 uint32_t fsync; 115 int fd; 116#ifndef __OPENSTEP__ 117 struct utimbuf timep; 118#else 119 time_t timep[2]; 120#endif 121 mach_port_t my_mach_host_self; 122 char *file, *p; 123 uint32_t file_size; 124 time_t toc_time; 125 enum bool seen_archive; 126 kern_return_t r; 127 128 seen_archive = FALSE; 129 toc_time = time(0); 130 131 writeout_to_mem(archs, narchs, output, (void **)&file, &file_size, 132 sort_toc, commons_in_toc, library_warnings, 133 &seen_archive); 134 135 /* 136 * Create the output file. The unlink() is done to handle the problem 137 * when the outputfile is not writable but the directory allows the 138 * file to be removed (since the file may not be there the return code 139 * of the unlink() is ignored). 140 */ 141 (void)unlink(output); 142 if(throttle != NULL) 143 fsync = O_FSYNC; 144 else 145 fsync = 0; 146 if(output != NULL){ 147 if((fd = open(output, O_WRONLY|O_CREAT|O_TRUNC|fsync, mode)) == -1){ 148 system_error("can't create output file: %s", output); 149 goto cleanup; 150 } 151#ifdef F_NOCACHE 152 /* tell filesystem to NOT cache the file when reading or writing */ 153 (void)fcntl(fd, F_NOCACHE, 1); 154#endif 155 } 156 else{ 157 throttle = NULL; 158 fd = fileno(stdout); 159 } 160 if(throttle != NULL){ 161#define WRITE_SIZE (32 * 1024) 162 struct timeval start, end; 163 struct timezone tz; 164 uint32_t bytes_written, bytes_per_second, write_size; 165 double time_used, time_should_have_took, usecs_to_kill; 166 static struct host_sched_info info = { 0 }; 167 unsigned int count; 168 kern_return_t r; 169 170 p = file; 171 bytes_written = 0; 172 bytes_per_second = 0; 173 count = HOST_SCHED_INFO_COUNT; 174 my_mach_host_self = mach_host_self(); 175 if((r = host_info(my_mach_host_self, HOST_SCHED_INFO, (host_info_t) 176 (&info), &count)) != KERN_SUCCESS){ 177 mach_port_deallocate(mach_task_self(), my_mach_host_self); 178 my_mach_error(r, "can't get host sched info"); 179 } 180 mach_port_deallocate(mach_task_self(), my_mach_host_self); 181 if(gettimeofday(&start, &tz) == -1) 182 goto no_throttle; 183#undef THROTTLE_DEBUG 184 do { 185 if((file + file_size) - p < WRITE_SIZE) 186 write_size = (file + file_size) - p; 187 else 188 write_size = WRITE_SIZE; 189 if(write(fd, p, write_size) != (int)write_size){ 190 system_error("can't write output file: %s", output); 191 goto cleanup; 192 } 193 p += write_size; 194 if(p < file + file_size || *throttle == UINT_MAX){ 195 bytes_written += write_size; 196 (void)gettimeofday(&end, &tz); 197#ifdef THROTTLE_DEBUG 198 printf("start sec = %u usec = %u\n", start.tv_sec, 199 start.tv_usec); 200 printf("end sec = %u usec = %u\n", end.tv_sec, 201 end.tv_usec); 202#endif 203 time_used = end.tv_sec - start.tv_sec; 204 if(end.tv_usec >= start.tv_usec) 205 time_used += 206 ((double)(end.tv_usec - start.tv_usec)) / 1000000.0; 207 else 208 time_used += -1.0 + 209 ((double)(1000000 + end.tv_usec - start.tv_usec) / 210 1000000.0); 211 bytes_per_second = ((double)bytes_written / time_used); 212#ifdef THROTTLE_DEBUG 213 printf("time_used = %f bytes_written = %lu bytes_per_second" 214 " = %lu throttle = %lu\n", time_used, bytes_written, 215 bytes_per_second, *throttle); 216#endif 217 if(bytes_per_second > *throttle){ 218 time_should_have_took = 219 (double)bytes_written * (1.0/(double)(*throttle)); 220 usecs_to_kill = 221 (time_should_have_took - time_used) * 1000000.0; 222#ifdef THROTTLE_DEBUG 223 printf("time should have taken = %f usecs to kill %f\n", 224 time_should_have_took, usecs_to_kill); 225#endif 226 usleep((u_int)usecs_to_kill); 227 bytes_written = 0; 228 bytes_per_second = 0; 229 (void)gettimeofday(&start, &tz); 230 } 231 } 232 } while(p < file + file_size); 233 if(*throttle == UINT_MAX) 234 *throttle = bytes_per_second; 235 } 236 else{ 237no_throttle: 238 if(write(fd, file, file_size) != (int)file_size){ 239 system_error("can't write output file: %s", output); 240 goto cleanup; 241 } 242 } 243 if(output != NULL && close(fd) == -1){ 244 system_fatal("can't close output file: %s", output); 245 goto cleanup; 246 } 247 if(seen_archive == TRUE){ 248#ifndef __OPENSTEP__ 249 timep.actime = toc_time - 5; 250 timep.modtime = toc_time - 5; 251 if(utime(output, &timep) == -1) 252#else 253 timep[0] = toc_time - 5; 254 timep[1] = toc_time - 5; 255 if(utime(output, timep) == -1) 256#endif 257 { 258 system_fatal("can't set the modifiy times in output file: %s", 259 output); 260 goto cleanup; 261 } 262 } 263cleanup: 264 if((r = vm_deallocate(mach_task_self(), (vm_address_t)file, 265 file_size)) != KERN_SUCCESS){ 266 my_mach_error(r, "can't vm_deallocate() buffer for output file"); 267 return; 268 } 269} 270 271 272/* 273 * writeout_to_mem() creates an ofile in memory from the data structure pointed 274 * to by archs (of narchs size). Upon successful return, *outputbuf will point 275 * to a vm_allocate'd buffer representing the ofile which should be 276 * vm_deallocated when it is no longer needed. length will point to the length 277 * of the outputbuf buffer. The filename parameter is used for error reporting 278 * - if filename is NULL, a dummy file name is used. If there are libraries in 279 * the data structures a new table of contents is created and is sorted if 280 * sort_toc is TRUE and commons symbols are included in the table of contents 281 * if commons_in_toc is TRUE. The normal use will have sort_toc == TRUE and 282 * commons_in_toc == FALSE. If warnings about unusual libraries are printed if 283 * library_warnings == TRUE. 284 */ 285__private_extern__ 286void 287writeout_to_mem( 288struct arch *archs, 289uint32_t narchs, 290char *filename, 291void **outputbuf, 292uint32_t *length, 293enum bool sort_toc, 294enum bool commons_in_toc, 295enum bool library_warnings, 296enum bool *seen_archive) 297{ 298 uint32_t i, j, k, file_size, offset, pad, size; 299 uint32_t i32; 300 enum byte_sex target_byte_sex, host_byte_sex; 301 char *file, *p; 302 kern_return_t r; 303 struct fat_header *fat_header; 304 struct fat_arch *fat_arch; 305 struct dysymtab_command dyst; 306 struct twolevel_hints_command hints_cmd; 307 struct load_command lc, *lcp; 308 struct dylib_command dl, *dlp; 309 time_t toc_time; 310 int32_t timestamp, index; 311 uint32_t ncmds; 312 enum bool swapped; 313 314 /* 315 * If filename is NULL, we use a dummy file name. 316 */ 317 if(filename == NULL) 318 filename = "(file written out to memory)"; 319 320 /* 321 * The time the table of contents' are set to and the time to base the 322 * modification time of the output file to be set to. 323 */ 324 *seen_archive = FALSE; 325 toc_time = time(0); 326 327 fat_arch = NULL; /* here to quite compiler maybe warning message */ 328 fat_header = NULL; 329 330 if(narchs == 0){ 331 error("no contents for file: %s (not created)", filename); 332 return; 333 } 334 335 host_byte_sex = get_host_byte_sex(); 336 337 /* 338 * Calculate the total size of the file and the final size of each 339 * architecture. 340 */ 341 if(narchs > 1 || archs[0].fat_arch != NULL) 342 file_size = sizeof(struct fat_header) + 343 sizeof(struct fat_arch) * narchs; 344 else 345 file_size = 0; 346 for(i = 0; i < narchs; i++){ 347 /* 348 * For each arch that is an archive recreate the table of contents. 349 */ 350 if(archs[i].type == OFILE_ARCHIVE){ 351 *seen_archive = TRUE; 352 make_table_of_contents(archs + i, filename, toc_time, sort_toc, 353 commons_in_toc, library_warnings); 354 archs[i].library_size += SARMAG + archs[i].toc_size; 355 if(archs[i].fat_arch != NULL) 356 file_size = rnd(file_size, 1 << archs[i].fat_arch->align); 357 file_size += archs[i].library_size; 358 if(archs[i].fat_arch != NULL) 359 archs[i].fat_arch->size = archs[i].library_size; 360 } 361 else if(archs[i].type == OFILE_Mach_O){ 362 size = archs[i].object->object_size 363 - archs[i].object->input_sym_info_size 364 + archs[i].object->output_new_content_size 365 + archs[i].object->output_sym_info_size; 366 if(archs[i].fat_arch != NULL) 367 file_size = rnd(file_size, 1 << archs[i].fat_arch->align); 368 file_size += size; 369 if(archs[i].fat_arch != NULL) 370 archs[i].fat_arch->size = size; 371 } 372 else{ /* archs[i].type == OFILE_UNKNOWN */ 373 if(archs[i].fat_arch != NULL) 374 file_size = rnd(file_size, 1 << archs[i].fat_arch->align); 375 file_size += archs[i].unknown_size; 376 if(archs[i].fat_arch != NULL) 377 archs[i].fat_arch->size = archs[i].unknown_size; 378 } 379 } 380 381 /* 382 * This buffer is vm_allocate'ed to make sure all holes are filled with 383 * zero bytes. 384 */ 385 if((r = vm_allocate(mach_task_self(), (vm_address_t *)&file, 386 file_size, TRUE)) != KERN_SUCCESS) 387 mach_fatal(r, "can't vm_allocate() buffer for output file: %s of " 388 "size %u", filename, file_size); 389 390 /* 391 * If there is more than one architecture then fill in the fat file 392 * header and the fat_arch structures in the buffer. 393 */ 394 if(narchs > 1 || archs[0].fat_arch != NULL){ 395 fat_header = (struct fat_header *)file; 396 fat_header->magic = FAT_MAGIC; 397 fat_header->nfat_arch = narchs; 398 offset = sizeof(struct fat_header) + 399 sizeof(struct fat_arch) * narchs; 400 fat_arch = (struct fat_arch *)(file + sizeof(struct fat_header)); 401 for(i = 0; i < narchs; i++){ 402 fat_arch[i].cputype = archs[i].fat_arch->cputype; 403 fat_arch[i].cpusubtype = archs[i].fat_arch->cpusubtype; 404 offset = rnd(offset, 1 << archs[i].fat_arch->align); 405 fat_arch[i].offset = offset; 406 fat_arch[i].size = archs[i].fat_arch->size; 407 fat_arch[i].align = archs[i].fat_arch->align; 408 offset += archs[i].fat_arch->size; 409 } 410 } 411 412 /* 413 * Now put each arch in the buffer. 414 */ 415 for(i = 0; i < narchs; i++){ 416 if(archs[i].fat_arch != NULL) 417 p = file + fat_arch[i].offset; 418 else 419 p = file; 420 421 if(archs[i].type == OFILE_ARCHIVE){ 422 *seen_archive = TRUE; 423 /* 424 * If the input files only contains non-object files then the 425 * byte sex of the output can't be determined which is needed 426 * for the two binary long's of the table of contents. But 427 * since these will be zero (the same in both byte sexes) 428 * because there are no symbols in the table of contents if 429 * there are no object files. 430 */ 431 432 /* put in the archive magic string */ 433 memcpy(p, ARMAG, SARMAG); 434 p += SARMAG; 435 436 /* 437 * Warn for what really is a bad library that has an empty 438 * table of contents but this is allowed in the original 439 * bsd4.3 ranlib(1) implementation. 440 */ 441 if(library_warnings == TRUE && archs[i].ntocs == 0){ 442 if(narchs > 1 || archs[i].fat_arch != NULL) 443 warning("warning library: %s for architecture: %s the " 444 "table of contents is empty (no object file " 445 "members in the library)", filename, 446 archs[i].fat_arch_name); 447 else 448 warning("warning for library: %s the table of contents " 449 "is empty (no object file members in the " 450 "library)", filename); 451 } 452 453 /* 454 * Pick the byte sex to write the table of contents in. 455 */ 456 target_byte_sex = UNKNOWN_BYTE_SEX; 457 for(j = 0; 458 j < archs[i].nmembers && target_byte_sex ==UNKNOWN_BYTE_SEX; 459 j++){ 460 if(archs[i].members[j].type == OFILE_Mach_O) 461 target_byte_sex = 462 archs[i].members[j].object->object_byte_sex; 463 } 464 if(target_byte_sex == UNKNOWN_BYTE_SEX) 465 target_byte_sex = host_byte_sex; 466 467 /* 468 * Put in the table of contents member: 469 * the archive header 470 * a 32-bit for the number of bytes of the ranlib structs 471 * the ranlib structs 472 * a 32-bit for the number of bytes of the ranlib strings 473 * the strings for the ranlib structs 474 */ 475 memcpy(p, (char *)(&archs[i].toc_ar_hdr),sizeof(struct ar_hdr)); 476 p += sizeof(struct ar_hdr); 477 478 if(archs[i].toc_long_name == TRUE){ 479 memcpy(p, archs[i].toc_name, archs[i].toc_name_size); 480 p += archs[i].toc_name_size + 481 (rnd(sizeof(struct ar_hdr), 8) - 482 sizeof(struct ar_hdr)); 483 } 484 485 i32 = archs[i].ntocs * sizeof(struct ranlib); 486 if(target_byte_sex != host_byte_sex) 487 i32 = SWAP_INT(i32); 488 memcpy(p, (char *)&i32, sizeof(uint32_t)); 489 p += sizeof(uint32_t); 490 491 if(target_byte_sex != host_byte_sex) 492 swap_ranlib(archs[i].toc_ranlibs, archs[i].ntocs, 493 target_byte_sex); 494 memcpy(p, (char *)archs[i].toc_ranlibs, 495 archs[i].ntocs * sizeof(struct ranlib)); 496 p += archs[i].ntocs * sizeof(struct ranlib); 497 498 i32 = archs[i].toc_strsize; 499 if(target_byte_sex != host_byte_sex) 500 i32 = SWAP_INT(i32); 501 memcpy(p, (char *)&i32, sizeof(uint32_t)); 502 p += sizeof(uint32_t); 503 504 memcpy(p, (char *)archs[i].toc_strings, archs[i].toc_strsize); 505 p += archs[i].toc_strsize; 506 507 /* 508 * Put in the archive header and member contents for each 509 * member in the buffer. 510 */ 511 for(j = 0; j < archs[i].nmembers; j++){ 512 memcpy(p, (char *)(archs[i].members[j].ar_hdr), 513 sizeof(struct ar_hdr)); 514 p += sizeof(struct ar_hdr); 515 516 if(archs[i].members[j].member_long_name == TRUE){ 517 memcpy(p, archs[i].members[j].member_name, 518 archs[i].members[j].member_name_size); 519 p += rnd(archs[i].members[j].member_name_size, 8) + 520 (rnd(sizeof(struct ar_hdr), 8) - 521 sizeof(struct ar_hdr)); 522 } 523 524 if(archs[i].members[j].type == OFILE_Mach_O){ 525 /* 526 * ofile_map swaps the headers to the host_byte_sex if 527 * the object's byte sex is not the same as the host 528 * byte sex so if this is the case swap them back 529 * before writing them out. 530 */ 531 memset(&dyst, '\0', sizeof(struct dysymtab_command)); 532 if(archs[i].members[j].object->dyst != NULL) 533 dyst = *(archs[i].members[j].object->dyst); 534 if(archs[i].members[j].object->hints_cmd != NULL) 535 hints_cmd = *(archs[i].members[j].object->hints_cmd); 536 if(archs[i].members[j].object->object_byte_sex != 537 host_byte_sex){ 538 if(archs[i].members[j].object->mh != NULL){ 539 if(swap_object_headers( 540 archs[i].members[j].object->mh, 541 archs[i].members[j].object->load_commands) 542 == FALSE) 543 fatal("internal error: " 544 "swap_object_headers() failed"); 545 if(archs[i].members[j].object->output_nsymbols 546 != 0) 547 swap_nlist( 548 archs[i].members[j].object-> 549 output_symbols, 550 archs[i].members[j].object-> 551 output_nsymbols, 552 archs[i].members[j].object-> 553 object_byte_sex); 554 } 555 else{ 556 if(swap_object_headers( 557 archs[i].members[j].object->mh64, 558 archs[i].members[j].object->load_commands) 559 == FALSE) 560 fatal("internal error: " 561 "swap_object_headers() failed"); 562 if(archs[i].members[j].object->output_nsymbols 563 != 0) 564 swap_nlist_64( 565 archs[i].members[j].object-> 566 output_symbols64, 567 archs[i].members[j].object-> 568 output_nsymbols, 569 archs[i].members[j].object-> 570 object_byte_sex); 571 } 572 } 573 if(archs[i].members[j].object-> 574 output_sym_info_size == 0 && 575 archs[i].members[j].object-> 576 input_sym_info_size == 0){ 577 size = archs[i].members[j].object->object_size; 578 memcpy(p, archs[i].members[j].object->object_addr, 579 size); 580 } 581 else{ 582 size = archs[i].members[j].object->object_size 583 - archs[i].members[j].object-> 584 input_sym_info_size; 585 memcpy(p, archs[i].members[j].object->object_addr, 586 size); 587 copy_new_symbol_info(p, &size, &dyst, 588 archs[i].members[j].object->dyst, &hints_cmd, 589 archs[i].members[j].object->hints_cmd, 590 archs[i].members[j].object); 591 } 592 p += size; 593 pad = rnd(size, 8) - size; 594 } 595 else{ 596 memcpy(p, archs[i].members[j].unknown_addr, 597 archs[i].members[j].unknown_size); 598 p += archs[i].members[j].unknown_size; 599 pad = rnd(archs[i].members[j].unknown_size, 8) - 600 archs[i].members[j].unknown_size; 601 } 602 /* as with the UNIX ar(1) program pad with '\n' chars */ 603 for(k = 0; k < pad; k++) 604 *p++ = '\n'; 605 } 606 } 607 else if(archs[i].type == OFILE_Mach_O){ 608 memset(&dyst, '\0', sizeof(struct dysymtab_command)); 609 if(archs[i].object->dyst != NULL) 610 dyst = *(archs[i].object->dyst); 611 if(archs[i].object->hints_cmd != NULL) 612 hints_cmd = *(archs[i].object->hints_cmd); 613 if(archs[i].object->mh_filetype == MH_DYLIB){ 614 /* 615 * To avoid problems with prebinding and multiple 616 * cpusubtypes we stager the time stamps of fat dylibs 617 * that have more than one cpusubtype. 618 */ 619 timestamp = 0; 620 for(index = i - 1; timestamp == 0 && index >= 0; index--){ 621 if(archs[index].type == OFILE_Mach_O && 622 archs[index].object->mh_filetype == MH_DYLIB && 623 archs[index].object->mh_cputype == 624 archs[i].object->mh_cputype){ 625 if(archs[index].object->mh != NULL) 626 ncmds = archs[index].object->mh->ncmds; 627 else 628 ncmds = archs[index].object->mh64->ncmds; 629 lcp = archs[index].object->load_commands; 630 swapped = archs[index].object->object_byte_sex != 631 host_byte_sex; 632 if(swapped) 633 ncmds = SWAP_INT(ncmds); 634 for(j = 0; j < ncmds; j++){ 635 lc = *lcp; 636 if(swapped) 637 swap_load_command(&lc, host_byte_sex); 638 if(lc.cmd == LC_ID_DYLIB){ 639 dlp = (struct dylib_command *)lcp; 640 dl = *dlp; 641 if(swapped) 642 swap_dylib_command(&dl, host_byte_sex); 643 timestamp = dl.dylib.timestamp - 1; 644 break; 645 } 646 lcp = (struct load_command *) 647 ((char *)lcp + lc.cmdsize); 648 } 649 } 650 } 651 if(timestamp == 0) 652 timestamp = toc_time; 653 lcp = archs[i].object->load_commands; 654 if(archs[i].object->mh != NULL) 655 ncmds = archs[i].object->mh->ncmds; 656 else 657 ncmds = archs[i].object->mh64->ncmds; 658 for(j = 0; j < ncmds; j++){ 659 if(lcp->cmd == LC_ID_DYLIB){ 660 dlp = (struct dylib_command *)lcp; 661 if(archs[i].dont_update_LC_ID_DYLIB_timestamp == 662 FALSE) 663 dlp->dylib.timestamp = timestamp; 664 break; 665 } 666 lcp = (struct load_command *)((char *)lcp + 667 lcp->cmdsize); 668 } 669 } 670 if(archs[i].object->object_byte_sex != host_byte_sex){ 671 if(archs[i].object->mh != NULL){ 672 if(swap_object_headers(archs[i].object->mh, 673 archs[i].object->load_commands) == FALSE) 674 fatal("internal error: swap_object_headers() " 675 "failed"); 676 if(archs[i].object->output_nsymbols != 0) 677 swap_nlist(archs[i].object->output_symbols, 678 archs[i].object->output_nsymbols, 679 archs[i].object->object_byte_sex); 680 } 681 else{ 682 if(swap_object_headers(archs[i].object->mh64, 683 archs[i].object->load_commands) == FALSE) 684 fatal("internal error: swap_object_headers() " 685 "failed"); 686 if(archs[i].object->output_nsymbols != 0) 687 swap_nlist_64(archs[i].object->output_symbols64, 688 archs[i].object->output_nsymbols, 689 archs[i].object->object_byte_sex); 690 } 691 } 692 if(archs[i].object->output_sym_info_size == 0 && 693 archs[i].object->input_sym_info_size == 0){ 694 size = archs[i].object->object_size; 695 memcpy(p, archs[i].object->object_addr, size); 696 } 697 else{ 698 size = archs[i].object->object_size 699 - archs[i].object->input_sym_info_size; 700 memcpy(p, archs[i].object->object_addr, size); 701 if(archs[i].object->output_new_content_size != 0){ 702 memcpy(p + size, archs[i].object->output_new_content, 703 archs[i].object->output_new_content_size); 704 size += archs[i].object->output_new_content_size; 705 } 706 copy_new_symbol_info(p, &size, &dyst, 707 archs[i].object->dyst, &hints_cmd, 708 archs[i].object->hints_cmd, 709 archs[i].object); 710 } 711 } 712 else{ /* archs[i].type == OFILE_UNKNOWN */ 713 memcpy(p, archs[i].unknown_addr, archs[i].unknown_size); 714 } 715 } 716#ifdef __LITTLE_ENDIAN__ 717 if(narchs > 1 || archs[0].fat_arch != NULL){ 718 swap_fat_header(fat_header, BIG_ENDIAN_BYTE_SEX); 719 swap_fat_arch(fat_arch, narchs, BIG_ENDIAN_BYTE_SEX); 720 } 721#endif /* __LITTLE_ENDIAN__ */ 722 *outputbuf = file; 723 *length = file_size; 724} 725 726/* 727 * copy_new_symbol_info() copies the new and updated symbolic information into 728 * the buffer for the object. 729 */ 730static 731void 732copy_new_symbol_info( 733char *p, 734uint32_t *size, 735struct dysymtab_command *dyst, 736struct dysymtab_command *old_dyst, 737struct twolevel_hints_command *hints_cmd, 738struct twolevel_hints_command *old_hints_cmd, 739struct object *object) 740{ 741 if(old_dyst != NULL){ 742 if(object->output_dyld_info_size != 0){ 743 if(object->output_dyld_info != NULL) 744 memcpy(p + *size, object->output_dyld_info, 745 object->output_dyld_info_size); 746 *size += object->output_dyld_info_size; 747 } 748 memcpy(p + *size, object->output_loc_relocs, 749 dyst->nlocrel * sizeof(struct relocation_info)); 750 *size += dyst->nlocrel * 751 sizeof(struct relocation_info); 752 if(object->output_split_info_data_size != 0){ 753 if(object->output_split_info_data != NULL) 754 memcpy(p + *size, object->output_split_info_data, 755 object->output_split_info_data_size); 756 *size += object->output_split_info_data_size; 757 } 758 if(object->output_func_start_info_data_size != 0){ 759 if(object->output_func_start_info_data != NULL) 760 memcpy(p + *size, object->output_func_start_info_data, 761 object->output_func_start_info_data_size); 762 *size += object->output_func_start_info_data_size; 763 } 764 if(object->output_data_in_code_info_data_size != 0){ 765 if(object->output_data_in_code_info_data != NULL) 766 memcpy(p + *size, object->output_data_in_code_info_data, 767 object->output_data_in_code_info_data_size); 768 *size += object->output_data_in_code_info_data_size; 769 } 770 if(object->output_code_sign_drs_info_data_size != 0){ 771 if(object->output_code_sign_drs_info_data != NULL) 772 memcpy(p + *size, object->output_code_sign_drs_info_data, 773 object->output_code_sign_drs_info_data_size); 774 *size += object->output_code_sign_drs_info_data_size; 775 } 776 if(object->mh != NULL){ 777 memcpy(p + *size, object->output_symbols, 778 object->output_nsymbols * sizeof(struct nlist)); 779 *size += object->output_nsymbols * 780 sizeof(struct nlist); 781 } 782 else{ 783 memcpy(p + *size, object->output_symbols64, 784 object->output_nsymbols * sizeof(struct nlist_64)); 785 *size += object->output_nsymbols * 786 sizeof(struct nlist_64); 787 } 788 if(old_hints_cmd != NULL){ 789 memcpy(p + *size, object->output_hints, 790 hints_cmd->nhints * sizeof(struct twolevel_hint)); 791 *size += hints_cmd->nhints * 792 sizeof(struct twolevel_hint); 793 } 794 memcpy(p + *size, object->output_ext_relocs, 795 dyst->nextrel * sizeof(struct relocation_info)); 796 *size += dyst->nextrel * 797 sizeof(struct relocation_info); 798 memcpy(p + *size, object->output_indirect_symtab, 799 dyst->nindirectsyms * sizeof(uint32_t)); 800 *size += dyst->nindirectsyms * sizeof(uint32_t) + 801 object->input_indirectsym_pad; 802 memcpy(p + *size, object->output_tocs, 803 object->output_ntoc *sizeof(struct dylib_table_of_contents)); 804 *size += object->output_ntoc * 805 sizeof(struct dylib_table_of_contents); 806 if(object->mh != NULL){ 807 memcpy(p + *size, object->output_mods, 808 object->output_nmodtab * sizeof(struct dylib_module)); 809 *size += object->output_nmodtab * 810 sizeof(struct dylib_module); 811 } 812 else{ 813 memcpy(p + *size, object->output_mods64, 814 object->output_nmodtab * sizeof(struct dylib_module_64)); 815 *size += object->output_nmodtab * 816 sizeof(struct dylib_module_64); 817 } 818 memcpy(p + *size, object->output_refs, 819 object->output_nextrefsyms * sizeof(struct dylib_reference)); 820 *size += object->output_nextrefsyms * 821 sizeof(struct dylib_reference); 822 memcpy(p + *size, object->output_strings, 823 object->output_strings_size); 824 *size += object->output_strings_size; 825 if(object->output_code_sig_data_size != 0){ 826 *size = rnd(*size, 16); 827 if(object->output_code_sig_data != NULL) 828 memcpy(p + *size, object->output_code_sig_data, 829 object->output_code_sig_data_size); 830 *size += object->output_code_sig_data_size; 831 } 832 } 833 else{ 834 if(object->output_func_start_info_data_size != 0){ 835 if(object->output_func_start_info_data != NULL) 836 memcpy(p + *size, object->output_func_start_info_data, 837 object->output_func_start_info_data_size); 838 *size += object->output_func_start_info_data_size; 839 } 840 if(object->output_data_in_code_info_data_size != 0){ 841 if(object->output_data_in_code_info_data != NULL) 842 memcpy(p + *size, object->output_data_in_code_info_data, 843 object->output_data_in_code_info_data_size); 844 *size += object->output_data_in_code_info_data_size; 845 } 846 if(object->mh != NULL){ 847 memcpy(p + *size, object->output_symbols, 848 object->output_nsymbols * sizeof(struct nlist)); 849 *size += object->output_nsymbols * 850 sizeof(struct nlist); 851 } 852 else{ 853 memcpy(p + *size, object->output_symbols64, 854 object->output_nsymbols * sizeof(struct nlist_64)); 855 *size += object->output_nsymbols * 856 sizeof(struct nlist_64); 857 } 858 memcpy(p + *size, object->output_strings, 859 object->output_strings_size); 860 *size += object->output_strings_size; 861 if(object->output_code_sig_data_size != 0){ 862 *size = rnd(*size, 16); 863 if(object->output_code_sig_data != NULL) 864 memcpy(p + *size, object->output_code_sig_data, 865 object->output_code_sig_data_size); 866 *size += object->output_code_sig_data_size; 867 } 868 } 869} 870 871/* 872 * make_table_of_contents() make the table of contents for the specified arch 873 * and fills in the toc_* fields in the arch. Output is the name of the output 874 * file for error messages. 875 */ 876static 877void 878make_table_of_contents( 879struct arch *arch, 880char *output, 881time_t toc_time, 882enum bool sort_toc, 883enum bool commons_in_toc, 884enum bool library_warnings) 885{ 886 uint32_t i, j, k, r, s, nsects; 887 struct member *member; 888 struct object *object; 889 struct load_command *lc; 890 struct segment_command *sg; 891 struct segment_command_64 *sg64; 892 struct nlist *symbols; 893 struct nlist_64 *symbols64; 894 uint32_t nsymbols; 895 char *strings; 896 uint32_t strings_size; 897 enum bool sorted; 898 unsigned short toc_mode; 899 int oumask, numask; 900 char *ar_name; 901 struct section *section; 902 struct section_64 *section64; 903 uint32_t ncmds; 904 905 symbols = NULL; /* here to quite compiler maybe warning message */ 906 symbols64 = NULL; 907 strings = NULL; /* here to quite compiler maybe warning message */ 908 909 /* 910 * First pass over the members to count how many ranlib structs are 911 * needed and the size of the strings in the toc that are needed. 912 */ 913 for(i = 0; i < arch->nmembers; i++){ 914 member = arch->members + i; 915 if(member->type == OFILE_Mach_O){ 916 object = member->object; 917 nsymbols = 0; 918 nsects = 0; 919 lc = object->load_commands; 920 if(object->mh != NULL) 921 ncmds = object->mh->ncmds; 922 else 923 ncmds = object->mh64->ncmds; 924 for(j = 0; j < ncmds; j++){ 925 if(lc->cmd == LC_SEGMENT){ 926 sg = (struct segment_command *)lc; 927 nsects += sg->nsects; 928 } 929 else if(lc->cmd == LC_SEGMENT_64){ 930 sg64 = (struct segment_command_64 *)lc; 931 nsects += sg64->nsects; 932 } 933 lc = (struct load_command *)((char *)lc + lc->cmdsize); 934 } 935 if(object->mh != NULL){ 936 object->sections = allocate(nsects * 937 sizeof(struct section *)); 938 object->sections64 = NULL; 939 } 940 else{ 941 object->sections = NULL; 942 object->sections64 = allocate(nsects * 943 sizeof(struct section_64 *)); 944 } 945 nsects = 0; 946 lc = object->load_commands; 947 for(j = 0; j < ncmds; j++){ 948 if(lc->cmd == LC_SEGMENT){ 949 sg = (struct segment_command *)lc; 950 section = (struct section *) 951 ((char *)sg + sizeof(struct segment_command)); 952 for(k = 0; k < sg->nsects; k++){ 953 object->sections[nsects++] = section++; 954 } 955 } 956 else if(lc->cmd == LC_SEGMENT_64){ 957 sg64 = (struct segment_command_64 *)lc; 958 section64 = (struct section_64 *) 959 ((char *)sg64 + sizeof(struct segment_command_64)); 960 for(k = 0; k < sg64->nsects; k++){ 961 object->sections64[nsects++] = section64++; 962 } 963 } 964 lc = (struct load_command *)((char *)lc + lc->cmdsize); 965 } 966 if(object->output_sym_info_size == 0){ 967 lc = object->load_commands; 968 for(j = 0; j < ncmds; j++){ 969 if(lc->cmd == LC_SYMTAB){ 970 object->st = (struct symtab_command *)lc; 971 break; 972 } 973 lc = (struct load_command *)((char *)lc + lc->cmdsize); 974 } 975 if(object->st != NULL && object->st->nsyms != 0){ 976 if(object->mh != NULL){ 977 symbols = (struct nlist *)(object->object_addr + 978 object->st->symoff); 979 if(object->object_byte_sex != get_host_byte_sex()) 980 swap_nlist(symbols, object->st->nsyms, 981 get_host_byte_sex()); 982 } 983 else{ 984 symbols64 = (struct nlist_64 *) 985 (object->object_addr + object->st->symoff); 986 if(object->object_byte_sex != get_host_byte_sex()) 987 swap_nlist_64(symbols64, object->st->nsyms, 988 get_host_byte_sex()); 989 } 990 nsymbols = object->st->nsyms; 991 strings = object->object_addr + object->st->stroff; 992 strings_size = object->st->strsize; 993 } 994 } 995 else /* object->output_sym_info_size != 0 */ { 996 if(object->mh != NULL) 997 symbols = object->output_symbols; 998 else 999 symbols64 = object->output_symbols64; 1000 nsymbols = object->output_nsymbols; 1001 strings = object->output_strings; 1002 strings_size = object->output_strings_size; 1003 } 1004 for(j = 0; j < nsymbols; j++){ 1005 if(object->mh != NULL){ 1006 if(toc_symbol(symbols + j, commons_in_toc, 1007 object->sections) == TRUE){ 1008 arch->ntocs++; 1009 arch->toc_strsize += 1010 strlen(strings + symbols[j].n_un.n_strx) + 1; 1011 } 1012 } 1013 else{ 1014 if(toc_symbol_64(symbols64 + j, commons_in_toc, 1015 object->sections64) == TRUE){ 1016 arch->ntocs++; 1017 arch->toc_strsize += 1018 strlen(strings + symbols64[j].n_un.n_strx) + 1; 1019 } 1020 } 1021 } 1022 } 1023 } 1024 1025 /* 1026 * Allocate the space for the table of content entries, the ranlib 1027 * structs and strings for the table of contents. 1028 */ 1029 arch->toc_entries = allocate(sizeof(struct toc_entry) * arch->ntocs); 1030 arch->toc_ranlibs = allocate(sizeof(struct ranlib) * arch->ntocs); 1031 arch->toc_strsize = rnd(arch->toc_strsize, 8); 1032 arch->toc_strings = allocate(arch->toc_strsize); 1033 1034 /* 1035 * Second pass over the members to fill in the toc_entry structs and 1036 * the strings for the table of contents. The symbol_name field is 1037 * filled in with a pointer to a string contained in arch->toc_strings 1038 * for easy sorting and conversion to an index. The member_index field 1039 * is filled in with the member index plus one to allow marking with 1040 * its negative value by check_sort_toc_entries() and easy conversion to 1041 * the real offset. 1042 */ 1043 r = 0; 1044 s = 0; 1045 for(i = 0; i < arch->nmembers; i++){ 1046 member = arch->members + i; 1047 if(member->type == OFILE_Mach_O){ 1048 object = member->object; 1049 nsymbols = 0; 1050 if(object->output_sym_info_size == 0){ 1051 if(object->st != NULL){ 1052 if(object->mh != NULL) 1053 symbols = (struct nlist *) 1054 (object->object_addr + object->st->symoff); 1055 else 1056 symbols64 = (struct nlist_64 *) 1057 (object->object_addr + object->st->symoff); 1058 nsymbols = object->st->nsyms; 1059 strings = object->object_addr + object->st->stroff; 1060 strings_size = object->st->strsize; 1061 } 1062 else{ 1063 symbols = NULL; 1064 nsymbols = 0; 1065 strings = NULL; 1066 strings_size = 0; 1067 } 1068 } 1069 else{ 1070 if(object->mh != NULL) 1071 symbols = object->output_symbols; 1072 else 1073 symbols64 = object->output_symbols64; 1074 nsymbols = object->output_nsymbols; 1075 strings = object->output_strings; 1076 strings_size = object->output_strings_size; 1077 } 1078 for(j = 0; j < nsymbols; j++){ 1079 if(object->mh != NULL){ 1080 if((uint32_t)symbols[j].n_un.n_strx > strings_size) 1081 continue; 1082 if(toc_symbol(symbols + j, commons_in_toc, 1083 object->sections) == TRUE){ 1084 strcpy(arch->toc_strings + s, 1085 strings + symbols[j].n_un.n_strx); 1086 arch->toc_entries[r].symbol_name = 1087 arch->toc_strings + s; 1088 arch->toc_entries[r].member_index = i + 1; 1089 r++; 1090 s += strlen(strings + symbols[j].n_un.n_strx) + 1; 1091 } 1092 } 1093 else{ 1094 if((uint32_t)symbols64[j].n_un.n_strx > 1095 strings_size) 1096 continue; 1097 if(toc_symbol_64(symbols64 + j, commons_in_toc, 1098 object->sections64) == TRUE){ 1099 strcpy(arch->toc_strings + s, 1100 strings + symbols64[j].n_un.n_strx); 1101 arch->toc_entries[r].symbol_name = 1102 arch->toc_strings + s; 1103 arch->toc_entries[r].member_index = i + 1; 1104 r++; 1105 s += strlen(strings + symbols64[j].n_un.n_strx) + 1; 1106 } 1107 } 1108 } 1109 if(object->output_sym_info_size == 0){ 1110 if(object->object_byte_sex != get_host_byte_sex()){ 1111 if(object->mh != NULL) 1112 swap_nlist(symbols, nsymbols, 1113 object->object_byte_sex); 1114 else 1115 swap_nlist_64(symbols64, nsymbols, 1116 object->object_byte_sex); 1117 } 1118 } 1119 } 1120 } 1121 1122 /* 1123 * If the table of contents is to be sorted by symbol name then try to 1124 * sort it and leave it sorted if no duplicates. 1125 */ 1126 if(sort_toc == TRUE){ 1127 qsort(arch->toc_entries, arch->ntocs, sizeof(struct toc_entry), 1128 (int (*)(const void *, const void *))toc_entry_name_qsort); 1129 sorted = check_sort_toc_entries(arch, output, library_warnings); 1130 if(sorted == FALSE){ 1131 qsort(arch->toc_entries, arch->ntocs, sizeof(struct toc_entry), 1132 (int (*)(const void *, const void *)) 1133 toc_entry_index_qsort); 1134 } 1135 } 1136 else{ 1137 sorted = FALSE; 1138 } 1139 1140 /* 1141 * Now set the ran_off and ran_un.ran_strx fields of the ranlib structs. 1142 * To do this the size of the toc member must be know because it comes 1143 * first in the library. The size of the toc member is made up of the 1144 * sizeof an archive header struct, plus the sizeof the name if we are 1145 * using extended format #1 for the long name, then the toc which is 1146 * (as defined in ranlib.h): 1147 * a 32-bit int for the number of bytes of the ranlib structs 1148 * the ranlib structures 1149 * a 32-bit int for the number of bytes of the strings 1150 * the strings 1151 */ 1152 /* 1153 * We use a long name for the table of contents for both the sorted 1154 * and non-sorted case because it is needed to get the 8 byte alignment 1155 * of the first archive member by padding the long name since 1156 * sizeof(struct ar_hdr) is not a mutiple of 8. 1157 */ 1158 if(arch->toc_long_name == FALSE) 1159 fatal("internal error: make_table_of_contents() called with " 1160 "arch->toc_long_name == FALSE"); 1161 1162 if(sorted == TRUE){ 1163 /* 1164 * This assumes that "__.SYMDEF SORTED" is 16 bytes and 1165 * (rnd(sizeof(struct ar_hdr), 8) - sizeof(struct ar_hdr) 1166 * is 4 bytes. 1167 */ 1168 ar_name = AR_EFMT1 "20"; 1169 arch->toc_name_size = sizeof(SYMDEF_SORTED) - 1; 1170 arch->toc_name = SYMDEF_SORTED; 1171 } 1172 else{ 1173 /* 1174 * This assumes that "__.SYMDEF\0\0\0\0\0\0\0" is 16 bytes and 1175 * (rnd(sizeof(struct ar_hdr), 8) - sizeof(struct ar_hdr) 1176 * is 4 bytes. 1177 */ 1178 ar_name = AR_EFMT1 "20"; 1179 arch->toc_name_size = 16; 1180 arch->toc_name = SYMDEF "\0\0\0\0\0\0\0"; 1181 } 1182 arch->toc_size = sizeof(struct ar_hdr) + 1183 sizeof(uint32_t) + 1184 arch->ntocs * sizeof(struct ranlib) + 1185 sizeof(uint32_t) + 1186 arch->toc_strsize; 1187 if(arch->toc_long_name == TRUE) 1188 arch->toc_size += arch->toc_name_size + 1189 (rnd(sizeof(struct ar_hdr), 8) - 1190 sizeof(struct ar_hdr)); 1191 for(i = 0; i < arch->nmembers; i++) 1192 arch->members[i].offset += SARMAG + arch->toc_size; 1193 for(i = 0; i < arch->ntocs; i++){ 1194 arch->toc_ranlibs[i].ran_un.ran_strx = 1195 arch->toc_entries[i].symbol_name - arch->toc_strings; 1196 arch->toc_ranlibs[i].ran_off = 1197 arch->members[arch->toc_entries[i].member_index - 1].offset; 1198 } 1199 1200 numask = 0; 1201 oumask = umask(numask); 1202 toc_mode = S_IFREG | (0666 & ~oumask); 1203 (void)umask(oumask); 1204 1205 sprintf((char *)(&arch->toc_ar_hdr), "%-*s%-*ld%-*u%-*u%-*o%-*ld", 1206 (int)sizeof(arch->toc_ar_hdr.ar_name), 1207 ar_name, 1208 (int)sizeof(arch->toc_ar_hdr.ar_date), 1209 toc_time, 1210 (int)sizeof(arch->toc_ar_hdr.ar_uid), 1211 (unsigned short)getuid(), 1212 (int)sizeof(arch->toc_ar_hdr.ar_gid), 1213 (unsigned short)getgid(), 1214 (int)sizeof(arch->toc_ar_hdr.ar_mode), 1215 (unsigned int)toc_mode, 1216 (int)sizeof(arch->toc_ar_hdr.ar_size), 1217 (long)(arch->toc_size - sizeof(struct ar_hdr))); 1218 /* 1219 * This has to be done by hand because sprintf puts a null 1220 * at the end of the buffer. 1221 */ 1222 memcpy(arch->toc_ar_hdr.ar_fmag, ARFMAG, 1223 (int)sizeof(arch->toc_ar_hdr.ar_fmag)); 1224} 1225 1226/* 1227 * toc_symbol() returns TRUE if the symbol is to be included in the table of 1228 * contents otherwise it returns FALSE. 1229 */ 1230static 1231enum bool 1232toc_symbol( 1233struct nlist *symbol, 1234enum bool commons_in_toc, 1235struct section **sections) 1236{ 1237 return(toc(symbol->n_un.n_strx, 1238 symbol->n_type, 1239 symbol->n_value, 1240 commons_in_toc, 1241 (symbol->n_type & N_TYPE) == N_SECT && 1242 sections[symbol->n_sect - 1]->flags & S_ATTR_NO_TOC)); 1243} 1244 1245static 1246enum bool 1247toc_symbol_64( 1248struct nlist_64 *symbol64, 1249enum bool commons_in_toc, 1250struct section_64 **sections64) 1251{ 1252 return(toc(symbol64->n_un.n_strx, 1253 symbol64->n_type, 1254 symbol64->n_value, 1255 commons_in_toc, 1256 (symbol64->n_type & N_TYPE) == N_SECT && 1257 sections64[symbol64->n_sect-1]->flags & S_ATTR_NO_TOC)); 1258} 1259 1260static 1261enum bool 1262toc( 1263uint32_t n_strx, 1264uint8_t n_type, 1265uint64_t n_value, 1266enum bool commons_in_toc, 1267enum bool attr_no_toc) 1268{ 1269 /* if the name is NULL then it won't be in the table of contents */ 1270 if(n_strx == 0) 1271 return(FALSE); 1272 /* if symbol is not external then it won't be in the toc */ 1273 if((n_type & N_EXT) == 0) 1274 return(FALSE); 1275 /* if symbol is undefined then it won't be in the toc */ 1276 if((n_type & N_TYPE) == N_UNDF && n_value == 0) 1277 return(FALSE); 1278 /* if symbol is common and the commons are not to be in the toc */ 1279 if((n_type & N_TYPE) == N_UNDF && n_value != 0 && 1280 commons_in_toc == FALSE) 1281 return(FALSE); 1282 /* if the symbols is in a section marked NO_TOC then ... */ 1283 if(attr_no_toc != 0) 1284 return(FALSE); 1285 1286 return(TRUE); 1287} 1288 1289/* 1290 * Function for qsort() for comparing toc_entry structures by name. 1291 */ 1292static 1293int 1294toc_entry_name_qsort( 1295const struct toc_entry *toc1, 1296const struct toc_entry *toc2) 1297{ 1298 return(strcmp(toc1->symbol_name, toc2->symbol_name)); 1299} 1300 1301/* 1302 * Function for qsort() for comparing toc_entry structures by index. 1303 */ 1304static 1305int 1306toc_entry_index_qsort( 1307const struct toc_entry *toc1, 1308const struct toc_entry *toc2) 1309{ 1310 if(toc1->member_index < toc2->member_index) 1311 return(-1); 1312 if(toc1->member_index > toc2->member_index) 1313 return(1); 1314 /* toc1->member_index == toc2->member_index */ 1315 return(0); 1316} 1317 1318/* 1319 * check_sort_toc_entries() checks the table of contents for the specified arch 1320 * which is sorted by name for more then one object defining the same symbol. 1321 * If this is the case it prints each symbol that is defined in more than one 1322 * object along with the object it is defined in. It returns TRUE if there are 1323 * no multiple definitions and FALSE otherwise. 1324 */ 1325static 1326enum bool 1327check_sort_toc_entries( 1328struct arch *arch, 1329char *output, 1330enum bool library_warnings) 1331{ 1332 uint32_t i; 1333 enum bool multiple_defs; 1334 struct member *member; 1335 1336 if(arch->ntocs == 0 || arch->ntocs == 1) 1337 return(TRUE); 1338 1339 /* 1340 * Since the symbol table is sorted by name look to any two adjcent 1341 * entries with the same name. If such entries are found print them 1342 * only once (marked by changing the sign of their member_index). 1343 */ 1344 multiple_defs = FALSE; 1345 for(i = 0; i < arch->ntocs - 1; i++){ 1346 if(strcmp(arch->toc_entries[i].symbol_name, 1347 arch->toc_entries[i+1].symbol_name) == 0){ 1348 if(multiple_defs == FALSE){ 1349 if(library_warnings == FALSE) 1350 return(FALSE); 1351 fprintf(stderr, "%s: same symbol defined in more than one " 1352 "member ", progname); 1353 if(arch->fat_arch != NULL) 1354 fprintf(stderr, "for architecture: %s ", 1355 arch->fat_arch_name); 1356 fprintf(stderr, "in: %s (table of contents will not be " 1357 "sorted)\n", output); 1358 multiple_defs = TRUE; 1359 } 1360 if(arch->toc_entries[i].member_index > 0){ 1361 member = arch->members + 1362 arch->toc_entries[i].member_index - 1; 1363 warn_member(arch, member, "defines symbol: %s", 1364 arch->toc_entries[i].symbol_name); 1365 arch->toc_entries[i].member_index = 1366 -(arch->toc_entries[i].member_index); 1367 } 1368 if(arch->toc_entries[i+1].member_index > 0){ 1369 member = arch->members + 1370 arch->toc_entries[i+1].member_index - 1; 1371 warn_member(arch, member, "defines symbol: %s", 1372 arch->toc_entries[i+1].symbol_name); 1373 arch->toc_entries[i+1].member_index = 1374 -(arch->toc_entries[i+1].member_index); 1375 } 1376 } 1377 } 1378 1379 if(multiple_defs == FALSE) 1380 return(TRUE); 1381 else{ 1382 for(i = 0; i < arch->ntocs; i++) 1383 if(arch->toc_entries[i].member_index < 0) 1384 arch->toc_entries[i].member_index = 1385 -(arch->toc_entries[i].member_index); 1386 return(FALSE); 1387 } 1388} 1389 1390/* 1391 * warn_member() is like the error routines it prints the program name the 1392 * member name specified and message specified. 1393 */ 1394static 1395void 1396warn_member( 1397struct arch *arch, 1398struct member *member, 1399const char *format, ...) 1400{ 1401 va_list ap; 1402 1403 fprintf(stderr, "%s: ", progname); 1404 if(arch->fat_arch != NULL) 1405 fprintf(stderr, "for architecture: %s ", arch->fat_arch_name); 1406 1407 if(member->input_ar_hdr != NULL){ 1408 fprintf(stderr, "file: %s(%.*s) ", member->input_file_name, 1409 (int)member->member_name_size, member->member_name); 1410 } 1411 else 1412 fprintf(stderr, "file: %s ", member->input_file_name); 1413 1414 va_start(ap, format); 1415 vfprintf(stderr, format, ap); 1416 fprintf(stderr, "\n"); 1417 va_end(ap); 1418} 1419#endif /* !defined(RLD) */ 1420