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