Terminate the nasty build warnings
[striptease.git] / libstuff / writeout.c
blob82cf3176929cd4d9195c5f7816856f0523af488a
1 /*
2 * Copyright (c) 1999 Apple Computer, Inc. All rights reserved.
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.
13 * The Original Code and all software distributed under the License are
14 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
15 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
16 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
17 * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
18 * Please see the License for the specific language governing rights and
19 * limitations under the License.
21 * @APPLE_LICENSE_HEADER_END@
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"
37 static 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);
46 static 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);
54 static enum bool toc_symbol(
55 struct nlist *symbol,
56 enum bool commons_in_toc,
57 struct section **sections);
59 static enum bool toc_symbol_64(
60 struct nlist_64 *symbol64,
61 enum bool commons_in_toc,
62 struct section_64 **sections64);
64 static 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);
71 static int toc_entry_name_qsort(
72 const struct toc_entry *toc1,
73 const struct toc_entry *toc2);
75 static int toc_entry_index_qsort(
76 const struct toc_entry *toc1,
77 const struct toc_entry *toc2);
79 static enum bool check_sort_toc_entries(
80 struct arch *arch,
81 char *output,
82 enum bool library_warnings);
84 static 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
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.
102 __private_extern__
103 void
104 writeout(
105 struct arch *archs,
106 uint32_t narchs,
107 char *output,
108 unsigned short mode,
109 enum bool sort_toc,
110 enum bool commons_in_toc,
111 enum bool library_warnings,
112 uint32_t *throttle)
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;
128 seen_archive = FALSE;
129 toc_time = time(0);
131 writeout_to_mem(archs, narchs, output, (void **)&file, &file_size,
132 sort_toc, commons_in_toc, library_warnings,
133 &seen_archive);
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).
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;
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
156 else{
157 throttle = NULL;
158 fd = fileno(stdout);
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;
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");
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;
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);
232 } while(p < file + file_size);
233 if(*throttle == UINT_MAX)
234 *throttle = bytes_per_second;
236 else{
237 no_throttle:
238 if(write(fd, file, file_size) != (int)file_size){
239 system_error("can't write output file: %s", output);
240 goto cleanup;
243 if(output != NULL && close(fd) == -1){
244 system_fatal("can't close output file: %s", output);
245 goto cleanup;
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
258 system_fatal("can't set the modifiy times in output file: %s",
259 output);
260 goto cleanup;
263 cleanup:
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;
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.
285 __private_extern__
286 void
287 writeout_to_mem(
288 struct arch *archs,
289 uint32_t narchs,
290 char *filename,
291 void **outputbuf,
292 uint32_t *length,
293 enum bool sort_toc,
294 enum bool commons_in_toc,
295 enum bool library_warnings,
296 enum bool *seen_archive)
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;
315 * If filename is NULL, we use a dummy file name.
317 if(filename == NULL)
318 filename = "(file written out to memory)";
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.
324 *seen_archive = FALSE;
325 toc_time = time(0);
327 fat_arch = NULL; /* here to quite compiler maybe warning message */
328 fat_header = NULL;
330 if(narchs == 0){
331 error("no contents for file: %s (not created)", filename);
332 return;
335 host_byte_sex = get_host_byte_sex();
338 * Calculate the total size of the file and the final size of each
339 * architecture.
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++){
348 * For each arch that is an archive recreate the table of contents.
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;
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;
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;
382 * This buffer is vm_allocate'ed to make sure all holes are filled with
383 * zero bytes.
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);
391 * If there is more than one architecture then fill in the fat file
392 * header and the fat_arch structures in the buffer.
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;
413 * Now put each arch in the buffer.
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;
421 if(archs[i].type == OFILE_ARCHIVE){
422 *seen_archive = TRUE;
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.
432 /* put in the archive magic string */
433 memcpy(p, ARMAG, SARMAG);
434 p += SARMAG;
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.
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);
454 * Pick the byte sex to write the table of contents in.
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;
464 if(target_byte_sex == UNKNOWN_BYTE_SEX)
465 target_byte_sex = host_byte_sex;
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
475 memcpy(p, (char *)(&archs[i].toc_ar_hdr),sizeof(struct ar_hdr));
476 p += sizeof(struct ar_hdr);
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));
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);
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);
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);
504 memcpy(p, (char *)archs[i].toc_strings, archs[i].toc_strsize);
505 p += archs[i].toc_strsize;
508 * Put in the archive header and member contents for each
509 * member in the buffer.
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);
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));
524 if(archs[i].members[j].type == OFILE_Mach_O){
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.
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);
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);
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);
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);
592 p += size;
593 pad = rnd(size, 8) - size;
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;
602 /* as with the UNIX ar(1) program pad with '\n' chars */
603 for(k = 0; k < pad; k++)
604 *p++ = '\n';
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){
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.
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;
646 lcp = (struct load_command *)
647 ((char *)lcp + lc.cmdsize);
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;
666 lcp = (struct load_command *)((char *)lcp +
667 lcp->cmdsize);
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);
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);
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);
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;
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);
712 else{ /* archs[i].type == OFILE_UNKNOWN */
713 memcpy(p, archs[i].unknown_addr, archs[i].unknown_size);
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);
721 #endif /* __LITTLE_ENDIAN__ */
722 *outputbuf = file;
723 *length = file_size;
727 * copy_new_symbol_info() copies the new and updated symbolic information into
728 * the buffer for the object.
730 static
731 void
732 copy_new_symbol_info(
733 char *p,
734 uint32_t *size,
735 struct dysymtab_command *dyst,
736 struct dysymtab_command *old_dyst,
737 struct twolevel_hints_command *hints_cmd,
738 struct twolevel_hints_command *old_hints_cmd,
739 struct object *object)
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;
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;
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;
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;
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;
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);
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);
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);
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);
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);
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;
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;
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;
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);
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);
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;
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.
876 static
877 void
878 make_table_of_contents(
879 struct arch *arch,
880 char *output,
881 time_t toc_time,
882 enum bool sort_toc,
883 enum bool commons_in_toc,
884 enum bool library_warnings)
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;
905 symbols = NULL; /* here to quite compiler maybe warning message */
906 symbols64 = NULL;
907 strings = NULL; /* here to quite compiler maybe warning message */
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.
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;
929 else if(lc->cmd == LC_SEGMENT_64){
930 sg64 = (struct segment_command_64 *)lc;
931 nsects += sg64->nsects;
933 lc = (struct load_command *)((char *)lc + lc->cmdsize);
935 if(object->mh != NULL){
936 object->sections = allocate(nsects *
937 sizeof(struct section *));
938 object->sections64 = NULL;
940 else{
941 object->sections = NULL;
942 object->sections64 = allocate(nsects *
943 sizeof(struct section_64 *));
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++;
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++;
964 lc = (struct load_command *)((char *)lc + lc->cmdsize);
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;
973 lc = (struct load_command *)((char *)lc + lc->cmdsize);
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());
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());
990 nsymbols = object->st->nsyms;
991 strings = object->object_addr + object->st->stroff;
992 strings_size = object->st->strsize;
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;
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;
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;
1026 * Allocate the space for the table of content entries, the ranlib
1027 * structs and strings for the table of contents.
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);
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.
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;
1062 else{
1063 symbols = NULL;
1064 nsymbols = 0;
1065 strings = NULL;
1066 strings_size = 0;
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;
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;
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;
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);
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.
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);
1136 else{
1137 sorted = FALSE;
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
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.
1158 if(arch->toc_long_name == FALSE)
1159 fatal("internal error: make_table_of_contents() called with "
1160 "arch->toc_long_name == FALSE");
1162 if(sorted == TRUE){
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.
1168 ar_name = AR_EFMT1 "20";
1169 arch->toc_name_size = sizeof(SYMDEF_SORTED) - 1;
1170 arch->toc_name = SYMDEF_SORTED;
1172 else{
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.
1178 ar_name = AR_EFMT1 "20";
1179 arch->toc_name_size = 16;
1180 arch->toc_name = SYMDEF "\0\0\0\0\0\0\0";
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;
1200 numask = 0;
1201 oumask = umask(numask);
1202 toc_mode = S_IFREG | (0666 & ~oumask);
1203 (void)umask(oumask);
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)));
1219 * This has to be done by hand because sprintf puts a null
1220 * at the end of the buffer.
1222 memcpy(arch->toc_ar_hdr.ar_fmag, ARFMAG,
1223 (int)sizeof(arch->toc_ar_hdr.ar_fmag));
1227 * toc_symbol() returns TRUE if the symbol is to be included in the table of
1228 * contents otherwise it returns FALSE.
1230 static
1231 enum bool
1232 toc_symbol(
1233 struct nlist *symbol,
1234 enum bool commons_in_toc,
1235 struct section **sections)
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));
1245 static
1246 enum bool
1247 toc_symbol_64(
1248 struct nlist_64 *symbol64,
1249 enum bool commons_in_toc,
1250 struct section_64 **sections64)
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));
1260 static
1261 enum bool
1262 toc(
1263 uint32_t n_strx,
1264 uint8_t n_type,
1265 uint64_t n_value,
1266 enum bool commons_in_toc,
1267 enum bool attr_no_toc)
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);
1286 return(TRUE);
1290 * Function for qsort() for comparing toc_entry structures by name.
1292 static
1294 toc_entry_name_qsort(
1295 const struct toc_entry *toc1,
1296 const struct toc_entry *toc2)
1298 return(strcmp(toc1->symbol_name, toc2->symbol_name));
1302 * Function for qsort() for comparing toc_entry structures by index.
1304 static
1306 toc_entry_index_qsort(
1307 const struct toc_entry *toc1,
1308 const struct toc_entry *toc2)
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);
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.
1325 static
1326 enum bool
1327 check_sort_toc_entries(
1328 struct arch *arch,
1329 char *output,
1330 enum bool library_warnings)
1332 uint32_t i;
1333 enum bool multiple_defs;
1334 struct member *member;
1336 if(arch->ntocs == 0 || arch->ntocs == 1)
1337 return(TRUE);
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).
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;
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);
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);
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);
1391 * warn_member() is like the error routines it prints the program name the
1392 * member name specified and message specified.
1394 static
1395 void
1396 warn_member(
1397 struct arch *arch,
1398 struct member *member,
1399 const char *format, ...)
1401 va_list ap;
1403 fprintf(stderr, "%s: ", progname);
1404 if(arch->fat_arch != NULL)
1405 fprintf(stderr, "for architecture: %s ", arch->fat_arch_name);
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);
1411 else
1412 fprintf(stderr, "file: %s ", member->input_file_name);
1414 va_start(ap, format);
1415 vfprintf(stderr, format, ap);
1416 fprintf(stderr, "\n");
1417 va_end(ap);
1419 #endif /* !defined(RLD) */