ranlib: fix it
[odcctools-svp.git] / mkshlib / host.c
blobc49275e9bc4a238947685222f664e806663e2812
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 #undef HOST_DEBUG
24 #include <stdlib.h>
25 #include <stdio.h>
26 #include <sys/file.h>
27 #include <mach-o/loader.h>
28 #include <mach-o/nlist.h>
29 #include <mach-o/reloc.h>
30 #include <mach-o/ranlib.h>
31 #include <ar.h>
32 #include <ctype.h>
33 #include <strings.h>
34 #include <mach/mach.h>
35 #include "stuff/openstep_mach.h"
36 #include <libc.h>
37 #include <sys/types.h>
38 #include <sys/stat.h>
39 #include "stuff/ofile.h"
40 #include "stuff/errors.h"
41 #include "stuff/allocate.h"
42 #include "stuff/hash_string.h"
44 #include "libgcc.h"
45 #include "mkshlib.h"
47 extern char *mktemp();
50 * The prefix to the file definition symbol names. The base name of the
51 * object file is the rest of the name. The user should never need to link
52 * to this symbol thus it should not be accessable from a high level language.
54 #define FILEDEF_NAME ".file_definition_"
57 * This is used to mark private undefined externals inside the scan_objects()
58 * routine. It is assigned to the n_type field of a nlist structure. It is
59 * a bit hopefull that this will never become a leagal value of an n_type.
61 #define N_PRIVATE_UNDF 0xff
64 * This structure holds the information of an external symbol. The value is
65 * the value from the target shared library. If bp is not zero then it points
66 * at the branch structure for this symbol and the value of the branch table
67 * entry is in branch_value.
69 struct ext {
70 char *name; /* name of the symbol */
71 long value; /* absolute value of the symbol */
72 struct branch *bp; /* if non-zero the branch table slot for this sym */
73 long branch_value; /* value of branch table slot if above is non-zero */
74 struct object *op; /* object this symbol is defined in */
75 struct ext *alias; /* if non-zero the real symbol for this alias */
76 long private; /* This symbol to to be private, not put in host */
77 struct ext *next; /* next ext on the hash chain */
79 #define EXT_HASH_SIZE 251
80 struct ext *ext_hash[EXT_HASH_SIZE];
83 * This structure notes a reference from one object file to another. It is
84 * pointed to by the refs field in the object structure and is a linked list.
85 * The name is the file definition symbol for the object that hold the
86 * definining reference for the reference the object makes. This linked list
87 * of references is built by make_references.
89 struct ref {
90 char *name;
91 struct ref *next;
95 * The mach header of the target shared library. This is read in make_exthash()
96 * The segment commands from this information are used in write_lib_obj() to
97 * build the library definition object. There sections are removed and their
98 * flags are set to SG_FVMLIB.
100 static struct mach_header target_mh;
101 static struct load_command *load_commands;
104 * The information of the library definition object. This information is
105 * calculated in build_lib_obj() and then used in write_lib_obj().
107 static struct lib_object {
108 long object_size; /* size of the object file */
109 long nfvmsegs; /* the number of segment commands */
110 long fvmlib_name_size; /* the size of the name in the LC_LOADFVMLIB */
111 long string_size; /* the size of the string table */
112 } lib_object = { 0 };
115 * The information of the library full reference object. This information is
116 * calculated in build_ref_obj() and then used in write_ref_obj().
118 static struct ref_object {
119 unsigned long object_size; /* size of the object file */
120 unsigned long string_size; /* the size of the string table */
121 } ref_object = { 0 };
124 * The information for the table of contents of the host shared library. The
125 * number of ranlib structures and the size of their strings are calulated as
126 * objects going into the host library are built. Then the ranlib structs and
127 * their string are set in build_archive() .
129 static struct toc_object {
130 unsigned long object_size; /* size of the object file */
131 unsigned long nranlibs; /* number of ranlib structs */
132 struct ranlib *ranlibs; /* the ranlib structs */
133 unsigned long ranlib_string_size;/* size of the strings for the structs */
134 char *ranlib_strings; /* the strings for the ranlib structs */
135 } toc_object = { 0 };
138 * The size of the host shared library. Calculated in build_archive() .
140 static long host_lib_size = 0;
142 static void make_exthash(
143 void);
144 static void scan_objects(
145 void);
146 static void scan_objects_processor(
147 struct ofile *ofile,
148 char *arch_name,
149 void *cookie);
150 static void make_references(
151 void);
153 static void build_archive(
154 void);
155 static int ranlib_qsort(
156 const struct ranlib *ran1,
157 const struct ranlib *ran2);
158 static void build_lib_object(
159 void);
160 static void build_ref_object(
161 void);
162 static void build_host_objects(
163 void);
164 static void init_symbol(
165 struct object *op,
166 char *name,
167 struct relocation_info *reloc,
168 long *value,
169 long *defined,
170 long symbolnum,
171 long address);
172 static void write_archive(
173 void);
174 static void write_lib_obj(
175 char *buffer);
176 static void write_ref_obj(
177 char *buffer);
178 static void write_object(
179 struct object *op,
180 char *buffer);
183 * Build the host shared library.
185 void
186 host()
189 * Make the hash table for all external symbols in the library.
191 make_exthash();
194 * Scan all the objects and collect their base symbol tables.
196 scan_objects();
199 * Make all the references between the host objects.
201 make_references();
204 * Build the components of the archive which is the host shared library.
206 build_archive();
209 * Write the components of the archive which is the host shared library.
211 write_archive();
215 * make_exthash() builds the hash table of all the external symbols in the
216 * target shared library.
218 static
219 void
220 make_exthash(void)
222 struct ofile ofile;
223 unsigned int string_size, hash_key, i, nsyms;
224 struct nlist *symbols;
225 char *strings, *p;
226 struct ext *extp, *bextp;
227 struct branch *bp;
228 struct alias *ap;
229 struct load_command *lc;
230 struct symtab_command *st;
231 struct oddball *obp;
235 * Map the target shared library and check to see if is is a shared
236 * library and has a symbol table.
238 if(ofile_map(target_filename, NULL, NULL, &ofile, FALSE) == FALSE)
239 exit(1);
241 if(ofile.file_type != OFILE_Mach_O || ofile.mh->filetype != MH_FVMLIB)
242 fatal("file: %s is not a target shared library", target_name);
244 target_mh = *(ofile.mh);
245 load_commands = ofile.load_commands;
247 /* Get the load command for the symbol table */
248 lc = ofile.load_commands;
249 st = (struct symtab_command *)0;
250 for(i = 0; i < ofile.mh->ncmds; i++){
251 switch(lc->cmd){
252 case LC_SYMTAB:
253 if(st != (struct symtab_command *)0)
254 fatal("More than one symtab_command in: %s", target_name);
255 else
256 st = (struct symtab_command *)lc;
257 break;
259 lc = (struct load_command *)((char *)lc + lc->cmdsize);
261 /* Check to see if the symbol table load command is good */
262 if(st == (struct symtab_command *)0)
263 fatal("No symtab_command in: %s", target_name);
264 if(st->nsyms == 0)
265 fatal("No symbol table in: %s", target_name);
266 if(st->strsize == 0)
267 fatal("No string table in: %s", target_name);
268 symbols = (struct nlist *)(ofile.object_addr + st->symoff);
269 nsyms = st->nsyms;
270 if(ofile.object_byte_sex != host_byte_sex)
271 swap_nlist(symbols, nsyms, host_byte_sex);
272 strings = (char *)(ofile.object_addr + st->stroff);
273 string_size = st->strsize;
276 * Now enter each external symbol in the external hash table.
278 for(i = 0; i < nsyms; i++){
279 /* if it is not an external symbol skip it */
280 if((symbols[i].n_type & N_EXT) == 0)
281 continue;
282 if(symbols[i].n_un.n_strx < 0 ||
283 (unsigned long)symbols[i].n_un.n_strx > string_size)
284 fatal("bad string index for symbol %d in target shared "
285 "library: %s", i, target_filename);
286 symbols[i].n_un.n_name = strings + symbols[i].n_un.n_strx;
287 hash_key = hash_string(symbols[i].n_un.n_name) % EXT_HASH_SIZE;
288 extp = ext_hash[hash_key];
289 while(extp != (struct ext *)0){
290 if(strcmp(symbols[i].n_un.n_name, extp->name) == 0)
291 fatal("symbol %s appears more than once in target shared "
292 "library: %s", extp->name, target_filename);
293 extp = extp->next;
295 extp = allocate(sizeof(struct ext));
296 extp->name = savestr(symbols[i].n_un.n_name);
297 extp->value = symbols[i].n_value;
298 extp->bp = (struct branch *)0;
299 extp->branch_value = BAD_ADDRESS;
300 extp->op = (struct object *)0;
301 extp->alias = (struct ext *)0;
302 extp->private = 0;
303 extp->next = ext_hash[hash_key];
304 ext_hash[hash_key] = extp;
307 * If this symbol itself is not a branch slot symbol or the library
308 * definition symbol then see if this symbol has a branch table
309 * entry and record it.
311 if(is_branch_slot_symbol(extp->name))
312 continue;
313 if(is_libdef_symbol(extp->name))
314 continue;
315 hash_key = hash_string(extp->name) % BRANCH_HASH_SIZE;
316 bp = branch_hash[hash_key];
317 while(bp != (struct branch *)0){
318 if(strcmp(bp->name, extp->name) == 0)
319 break;
320 bp = bp->next;
322 extp->bp = bp;
324 hash_key = hash_string(extp->name) % ODDBALL_HASH_SIZE;
325 obp = oddball_hash[hash_key];
326 while(obp != (struct oddball *)0){
327 if(strcmp(obp->name, extp->name) == 0)
328 break;
329 obp = obp->next;
331 if(obp != (struct oddball *)0 && obp->private)
332 extp->private = 1;
335 * The text section is always section 1 because the branch table
336 * object is loaded first and contains only text.
338 if((symbols[i].n_type & N_TYPE) == N_SECT &&
339 symbols[i].n_sect == 1){
340 if(extp->bp == (struct branch *)0 &&
341 (obp == (struct oddball *)0 ||
342 (obp != (struct oddball *)0 &&
343 (obp->private == 0 && obp->nobranch == 0)) ) )
344 error("external text symbol: %s does not have an entry in "
345 "the branch table", extp->name);
347 else{
348 if(extp->bp != (struct branch *)0)
349 error("non external text symbol: %s has an entry in "
350 "the branch table", extp->name);
355 * Put the aliased symbols in the external hash table and look up
356 * their real symbols.
358 ap = aliases;
359 while(ap != (struct alias *)0){
360 hash_key = hash_string(ap->alias_name) % EXT_HASH_SIZE;
361 extp = ext_hash[hash_key];
362 while(extp != (struct ext *)0){
363 if(strcmp(ap->alias_name, extp->name) == 0)
364 break;
365 extp = extp->next;
367 if(extp == (struct ext *)0)
368 fatal("aliased symbol %s does not appears (that should) in "
369 "target shared library: %s", extp->name, target_filename);
371 hash_key = hash_string(ap->real_name) % EXT_HASH_SIZE;
372 extp->alias = ext_hash[hash_key];
373 while(extp->alias != (struct ext *)0){
374 if(strcmp(ap->real_name, extp->alias->name) == 0)
375 break;
376 extp->alias = extp->alias->next;
378 if(extp->alias == (struct ext *)0)
379 fatal("real symbol %s for aliased symbol %s not found in "
380 "target shared library\n", ap->real_name,
381 extp->alias->name);
383 ap = ap->next;
387 * For all external symbols with branch table entries look up the
388 * branch slot symbol and record its value.
390 for(i = 0; i < EXT_HASH_SIZE; i++){
391 extp = ext_hash[i];
392 while(extp != (struct ext *)0){
393 if(extp->bp != (struct branch *)0){
394 p = branch_slot_symbol(extp->bp->max_slotnum);
395 hash_key = hash_string(p) % EXT_HASH_SIZE;
396 bextp = ext_hash[hash_key];
397 while(bextp != (struct ext *)0){
398 if(strcmp(p, bextp->name) == 0)
399 break;
400 bextp = bextp->next;
402 if(bextp == (struct ext *)0)
403 fatal("branch table symbol for: %s not found in target "
404 "shared library: %s", extp->name,target_filename);
405 extp->branch_value = bextp->value;
407 extp = extp->next;
411 #ifdef HOST_DEBUG
412 printf("Just after building external symbol table\n");
413 for(i = 0; i < EXT_HASH_SIZE; i++){
414 extp = ext_hash[i];
415 while(extp != (struct ext *)0){
416 printf("\textp = 0x%x { %s, 0x%x, 0x%x, 0x%x, 0x%x }\n", extp,
417 extp->name, extp->value, extp->bp, extp->branch_value,
418 extp->next);
419 if(extp->bp != (struct branch *)0)
420 printf("\t\tbp = 0x%x { %s, %d, 0x%x }\n", extp->bp,
421 extp->bp->name, extp->bp->max_slotnum,
422 extp->bp->next);
423 extp = extp->next;
426 #endif /* HOST_DEBUG */
430 * This routine reads each object and creates a symbol table for the
431 * basis of the host object file for each object. Only external symbols
432 * are put in the symbol table.
434 static
435 void
436 scan_objects(void)
439 unsigned long i;
441 for(i = 0; i < nobject_list; i++){
442 ofile_process(object_list[i]->name, &arch_flag, 1, FALSE, FALSE,
443 TRUE, FALSE, scan_objects_processor, (void *)&i);
447 static
448 void
449 scan_objects_processor(
450 struct ofile *ofile,
451 char *arch_name,
452 void *cookie)
454 unsigned long i, j, k, l, nsyms, string_size, hash_key;
455 struct load_command *lc;
456 struct symtab_command *st;
457 struct nlist *symbols;
458 char *strings, *p, *q;
459 struct ext *extp;
461 i = *((long *)cookie);
462 st = NULL;
463 lc = ofile->load_commands;
464 for(j = 0; j < ofile->mh->ncmds; j++){
465 if(lc->cmd == LC_SYMTAB){
466 if(st != NULL)
467 fatal("more than one symtab command in object file: %s",
468 ofile->file_name);
469 st = (struct symtab_command *)lc;
471 lc = (struct load_command *)((char *)lc + lc->cmdsize);
473 if(st == NULL)
474 return;
477 * Size the number of external symbols and their strings. The first
478 * byte of the string table can't be used for a non-null named
479 * symbol so the string table size starts with one byte.
481 object_list[i]->nsymbols = 0;
482 object_list[i]->string_size = 1;
484 if(st->nsyms == 0){
485 return;
488 /* read the symbol table */
489 symbols = (struct nlist *)(ofile->object_addr + st->symoff);
490 nsyms = st->nsyms;
491 if(ofile->object_byte_sex != host_byte_sex)
492 swap_nlist(symbols, nsyms, host_byte_sex);
494 /* read the string table */
495 strings = ofile->object_addr + st->stroff;
496 string_size = st->strsize;
498 printf("processing object = %s\n", ofile->file_name);
500 for(j = 0; j < nsyms; j++){
501 /* if it is not an external symbol skip it */
502 if((symbols[j].n_type & N_EXT) == 0)
503 continue;
504 if(symbols[j].n_un.n_strx < 0 ||
505 (unsigned long)symbols[j].n_un.n_strx > string_size)
506 fatal("bad string index for symbol %ld in object file: %s ",
507 j, ofile->file_name);
508 symbols[j].n_un.n_name = strings + symbols[j].n_un.n_strx;
511 * If this symbol is aliased to another symbol then change
512 * it's name to the real symbol.
514 p = symbols[j].n_un.n_name;
515 hash_key = hash_string(p) % EXT_HASH_SIZE;
516 extp = ext_hash[hash_key];
517 while(extp != (struct ext *)0){
518 if(strcmp(p, extp->name) == 0)
519 break;
520 extp = extp->next;
522 if(extp == (struct ext *)0)
523 fatal("symbol: %s in object: %s not found in target "
524 "shared library: %s", p, ofile->file_name,
525 target_filename);
526 if(extp->alias != (struct ext *)0){
527 symbols[j].n_un.n_name = extp->alias->name;
529 else{
531 * This is the real symbol and not an alias so record
532 * which object it is defined in. That is set op field
533 * in the external symbol table.
535 if((symbols[j].n_type & N_TYPE) != N_UNDF){
536 if(extp->op != (struct object *)0)
537 fatal("symbol: %s defined in both: %s and %s", p,
538 ofile->file_name, extp->op->name);
539 extp->op = object_list[i];
544 * See if this symbol is listed as a private extern. If it is
545 * also an undefined symbol then mark it by changing the type
546 * to N_PRIVATE_UNDF and added it to the size of the private
547 * undefined exteral symbol table. If it is not undefined just
548 * turn off the extern bit so the next loop will not put in in
549 * the host shared library's symbol table.
551 if(extp->private ||
552 (extp->alias != (struct ext *)0 && extp->alias->private) ){
553 if(symbols[j].n_type == (N_UNDF|N_EXT)){
554 object_list[i]->pu_nsymbols++;
555 object_list[i]->pu_string_size +=
556 strlen(symbols[j].n_un.n_name) + 1;
558 printf("private undefined = %s\n", symbols[j].n_un.n_name);
560 symbols[j].n_type = N_PRIVATE_UNDF;
562 else{
564 printf("private defined = %s\n", symbols[j].n_un.n_name);
566 symbols[j].n_type &= ~N_EXT;
568 continue;
571 object_list[i]->nsymbols++;
572 object_list[i]->string_size +=
573 strlen(symbols[j].n_un.n_name) + 1;
577 * Save the of external symbols and their strings to be used
578 * as the basis of the host object file for this object file.
580 object_list[i]->symbols = allocate(object_list[i]->nsymbols *
581 sizeof(struct nlist));
582 object_list[i]->strings = allocate(object_list[i]->string_size);
583 object_list[i]->pu_symbols = allocate(object_list[i]->pu_nsymbols *
584 sizeof(struct nlist));
585 object_list[i]->pu_strings =
586 allocate(object_list[i]->pu_string_size);
587 k = 0;
588 p = object_list[i]->strings;
589 *p++ = '\0'; /* the first byte */
590 l = 0;
591 q = object_list[i]->pu_strings;
592 for(j = 0; j < nsyms; j++){
593 if(symbols[j].n_type == N_PRIVATE_UNDF){
594 object_list[i]->pu_symbols[l] = symbols[j];
595 strcpy(q, symbols[j].n_un.n_name);
596 object_list[i]->pu_symbols[l].n_un.n_name = q;
598 printf("recording private undefined = %s value = 0x%x\n",
599 object_list[i]->pu_symbols[l].n_un.n_name,
600 object_list[i]->pu_symbols[l].n_value);
602 l++;
603 q += strlen(symbols[j].n_un.n_name) + 1;
604 continue;
606 /* again if it is not an external symbol skip it */
607 if((symbols[j].n_type & N_EXT) == 0)
608 continue;
609 object_list[i]->symbols[k] = symbols[j];
610 strcpy(p, symbols[j].n_un.n_name);
611 object_list[i]->symbols[k].n_un.n_name = p;
612 k++;
613 p += strlen(symbols[j].n_un.n_name) + 1;
616 #ifdef HOST_DEBUG
617 printf("Symbol tables of host objects\n");
618 for(i = 0; i < nobject_list; i++){
619 printf("\tobject = %s\n", ofile->file_name);
620 for(j = 0;
621 j < object_list[i]->nsymbols;
622 j++){
623 printf("\t\tsymbol = %s value = 0x%x\n",
624 object_list[i]->symbols[j].n_un.n_name,
625 object_list[i]->symbols[j].n_value);
627 for(j = 0;
628 j < object_list[i]->pu_nsymbols;
629 j++){
630 printf("\t\tprivate undefined = %s value = 0x%x\n",
631 object_list[i]->pu_symbols[j].n_un.n_name,
632 object_list[i]->pu_symbols[j].n_value);
635 #endif /* HOST_DEBUG */
639 * This routine records the references between objects. It creates a file
640 * definition symbol name for each file and builds a reference to that for
641 * objects that references symbols in other objects. In this way it will
642 * guarentee that those objects get loaded and cause any multiply defined
643 * error thus to avoid building an executable that uses two different things
644 * for the same symbol.
646 static
647 void
648 make_references(void)
650 unsigned long i, j, hash_key;
651 struct ext *extp;
652 struct ref *refp;
653 char *p;
655 #ifdef HOST_DEBUG
656 printf("External symbol table with defining references\n");
657 for(i = 0; i < nobject_list; i++){
658 extp = ext_hash[i];
659 while(extp != (struct ext *)0){
660 if(extp->op != (struct object *)0)
661 printf("\text = %s defined in %s\n",
662 extp->name, extp->op->name);
663 else
664 printf("\text = %s not defined in any object\n",
665 extp->name);
666 extp = extp->next;
669 #endif /* HOST_DEBUG */
672 * Create a file definition symbol name for each host object file.
674 for(i = 0; i < nobject_list; i++){
675 object_list[i]->filedef_name =
676 makestr(FILEDEF_NAME, target_base_name, "_",
677 object_list[i]->base_name, (char *)0);
681 * Build a linked list of references for each object file that has
682 * undefined references that are defined in other objects in the
683 * shared library.
685 for(i = 0; i < nobject_list; i++){
686 for(j = 0;
687 j < object_list[i]->nsymbols;
688 j++){
689 if((object_list[i]->symbols[j].n_type & N_TYPE) == N_UNDF){
690 p = object_list[i]->symbols[j].n_un.n_name;
691 hash_key = hash_string(p) % EXT_HASH_SIZE;
692 extp = ext_hash[hash_key];
693 while(extp != (struct ext *)0){
694 if(strcmp(p, extp->name) == 0)
695 break;
696 extp = extp->next;
698 if(extp == (struct ext *)0)
699 fatal("symbol: %s in object: %s not found in target "
700 "shared library: %s", p, object_list[i]->name,
701 target_filename);
703 * If this symbol is an alias then uses the real symbol
704 * for this symbol.
706 if(extp->alias != (struct ext *)0)
707 extp = extp->alias;
710 * If this symbol is defined in a object in the shared
711 * library make sure there that object's file definition
712 * symbol name is on the reference list. If not add it.
714 if(extp->op != (struct object *)0){
715 refp = object_list[i]->refs;
716 while(refp != (struct ref *)0){
717 if(strcmp(refp->name, extp->op->filedef_name) == 0)
718 break;
719 refp = refp->next;
721 if(refp == (struct ref *)0){
722 refp = allocate(sizeof(struct ref));
723 refp->name = extp->op->filedef_name;
724 refp->next = object_list[i]->refs;
725 object_list[i]->refs = refp;
730 for(j = 0;
731 j < object_list[i]->pu_nsymbols;
732 j++){
733 p = object_list[i]->pu_symbols[j].n_un.n_name;
734 hash_key = hash_string(p) % EXT_HASH_SIZE;
735 extp = ext_hash[hash_key];
736 while(extp != (struct ext *)0){
737 if(strcmp(p, extp->name) == 0)
738 break;
739 extp = extp->next;
741 if(extp == (struct ext *)0)
742 fatal("symbol: %s in object: %s not found in target "
743 "shared library: %s", p, object_list[i]->name,
744 target_filename);
746 * If this symbol is an alias then uses the real symbol
747 * for this symbol.
749 if(extp->alias != (struct ext *)0)
750 extp = extp->alias;
753 * If this symbol is defined in a object in the shared
754 * library make sure there that object's file definition
755 * symbol name is on the reference list. If not add it.
757 if(extp->op != (struct object *)0){
758 refp = object_list[i]->refs;
759 while(refp != (struct ref *)0){
760 if(strcmp(refp->name, extp->op->filedef_name) == 0)
761 break;
762 refp = refp->next;
764 if(refp == (struct ref *)0){
765 refp = allocate(sizeof(struct ref));
766 refp->name = extp->op->filedef_name;
767 refp->next = object_list[i]->refs;
768 object_list[i]->refs = refp;
774 #ifdef HOST_DEBUG
775 printf("References from host objects to each other\n");
776 for(i = 0; i < nobject_list; i++){
777 printf("\tObject: %s references:\n", object_list[i]->name);
778 refp = object_list[i]->refs;
779 while(refp != (struct ref *)0){
780 printf("\t\t%s\n", refp->name);
781 refp = refp->next;
784 #endif /* HOST_DEBUG */
788 * build_archive causes all the component parts of the archive that is the
789 * host shared library to be built.
791 static
792 void
793 build_archive(void)
795 unsigned long ran_index, ran_strx, ran_off, i, j;
796 struct object *op;
797 char *symbol_name;
800 * Build the componets of the object that contains library definition
801 * symbol.
803 build_lib_object();
806 * Build the componets of the object that contains library full
807 * reference symbol.
809 build_ref_object();
812 * Build the components of the host object files.
814 build_host_objects();
817 * The rest of this routine builds the last part of the host library
818 * that needs to be built after all it's object's are built. This is
819 * the table of contents. After this is built then the size of the
820 * host library `host_lib_size' can be calculated and is set at the end.
822 toc_object.ranlibs = allocate(toc_object.nranlibs *
823 sizeof(struct ranlib));
824 toc_object.ranlib_strings =
825 allocate(round(toc_object.ranlib_string_size, sizeof(long)));
826 /* make sure the rounded area allways has the same value */
827 memset(toc_object.ranlib_strings + toc_object.ranlib_string_size, '\0',
828 round(toc_object.ranlib_string_size, sizeof(long)) -
829 toc_object.ranlib_string_size);
830 toc_object.object_size =
831 sizeof(long) +
832 toc_object.nranlibs * sizeof(struct ranlib) +
833 sizeof(long) +
834 round(toc_object.ranlib_string_size, sizeof(long));
836 ran_index = 0;
837 ran_strx = 0;
838 ran_off = SARMAG + sizeof(struct ar_hdr) + toc_object.object_size;
841 * The library definition symbol is defined in the library definition
842 * object (which is the first member of the archive after the table
843 * of contents).
845 toc_object.ranlibs[ran_index].ran_un.ran_strx = ran_strx;
846 toc_object.ranlibs[ran_index].ran_off = ran_off;
847 strcpy(toc_object.ranlib_strings + ran_strx, shlib_symbol_name);
848 ran_index++;
849 ran_strx += strlen(shlib_symbol_name) + 1;
850 ran_off += sizeof(struct ar_hdr) + lib_object.object_size;
853 * The library reference symbol is defined in the library reference
854 * object (which is the second member of the archive after the table
855 * of contents).
857 toc_object.ranlibs[ran_index].ran_un.ran_strx = ran_strx;
858 toc_object.ranlibs[ran_index].ran_off = ran_off;
859 strcpy(toc_object.ranlib_strings + ran_strx, shlib_reference_name);
860 ran_index++;
861 ran_strx += strlen(shlib_reference_name) + 1;
862 ran_off += sizeof(struct ar_hdr) + ref_object.object_size;
865 * For each defined symbol in each object file add it to the table of
866 * contents. Note there are only undefined and absolute symbols in the
867 * symbol tables.
869 for(i = 0; i < nobject_list; i++){
870 op = object_list[i];
871 for(j = 0; j < op->nsymbols; j++){
872 if((op->symbols[j].n_type & N_TYPE) != N_UNDF){
873 symbol_name = op->strings + op->symbols[j].n_un.n_strx;
874 toc_object.ranlibs[ran_index].ran_un.ran_strx = ran_strx;
875 toc_object.ranlibs[ran_index].ran_off = ran_off;
876 strcpy(toc_object.ranlib_strings + ran_strx, symbol_name);
877 ran_index++;
878 ran_strx += strlen(symbol_name) + 1;
881 ran_off += sizeof(struct ar_hdr) + op->object_size;
883 host_lib_size = ran_off;
885 if(ran_index != toc_object.nranlibs)
886 fatal("internal error: ran_index (%ld) not equal to "
887 "toc_object.nranlibs (%ld)", ran_index, toc_object.nranlibs);
888 if(ran_strx != toc_object.ranlib_string_size)
889 fatal("internal error: ran_strx (%ld) not equal to "
890 "toc_object.ranlib_string_size (%ld)", ran_strx,
891 toc_object.ranlib_string_size);
892 toc_object.ranlib_string_size = round(toc_object.ranlib_string_size,
893 sizeof(long));
896 * This can be sorted without fear of having the same symbol defined
897 * in more than one object file because these symbols come from the
898 * target library and there can't be multiply defined symbols.
900 qsort(toc_object.ranlibs, toc_object.nranlibs, sizeof(struct ranlib),
901 (int (*)(const void *, const void *))ranlib_qsort);
905 * Function for qsort() for comparing ranlib structures by name.
907 static
909 ranlib_qsort(
910 const struct ranlib *ran1,
911 const struct ranlib *ran2)
913 return(strcmp(toc_object.ranlib_strings + ran1->ran_un.ran_strx,
914 toc_object.ranlib_strings + ran2->ran_un.ran_strx));
918 * build_lib_object builds the object file that contains the shared library
919 * definition symbol. It is later put in the host shared library archive.
921 static
922 void
923 build_lib_object(void)
925 unsigned long i;
926 struct load_command *lc;
929 * This object file has segment commands for the segments of the
930 * shared library (marked with SG_FLAGS). These are so the Mach-O
931 * link editor can check the segments for overlap.
933 lib_object.nfvmsegs = 0;
934 lc = (struct load_command *)load_commands;
935 for(i = 0; i < target_mh.ncmds; i++){
936 if(lc->cmd == LC_SEGMENT){
937 lib_object.nfvmsegs++;
939 lc = (struct load_command *)((char *)lc + lc->cmdsize);
942 * This object file also has the load fvmlib command which the link
943 * editor will propagate to its output so the library gets loaded when
944 * the output file is executed.
946 lib_object.fvmlib_name_size = round(strlen(target_name) + 1,
947 sizeof(long));
949 * This object file has one symbol. It is the defining occurence of
950 * the shared library definition symbol. So this is added to the table
951 * of contents. Since symbol name is the only string in the string
952 * table it starts at byte 1 (because not null symbol names can't be
953 * at byte 0).
955 toc_object.nranlibs++;
956 toc_object.ranlib_string_size += strlen(shlib_symbol_name) + 1;
957 lib_object.string_size = round(strlen(shlib_symbol_name) + 2,
958 sizeof(long));
960 lib_object.object_size =
961 sizeof(struct mach_header) +
962 lib_object.nfvmsegs * sizeof(struct segment_command) +
963 sizeof(struct symtab_command) +
964 sizeof(struct fvmlib_command) +
965 lib_object.fvmlib_name_size +
966 sizeof(struct nlist) +
967 lib_object.string_size;
971 * build_ref_object builds the object file that contains the shared library
972 * reference symbol. It is later put in the host shared library archive.
974 static
975 void
976 build_ref_object(void)
978 unsigned long i;
981 * This object file has one defined symbol. It is the defining
982 * occurence of the shared library reference symbol. So this is added
983 * to the table of contents.
985 toc_object.nranlibs++;
986 toc_object.ranlib_string_size += strlen(shlib_reference_name) + 1;
989 * This object contains an undefined reference to all of the object's
990 * file definition symbols. So the string table is sized here.
991 * Non-null symbol names start at byte 1 thus the starting size of 1.
993 ref_object.string_size = 1;
994 ref_object.string_size += strlen(shlib_reference_name) + 2;
995 for(i = 0; i < nobject_list; i++)
996 ref_object.string_size += strlen(object_list[i]->filedef_name) + 1;
997 ref_object.string_size = round(ref_object.string_size, sizeof(long));
999 ref_object.object_size =
1000 sizeof(struct mach_header) +
1001 sizeof(struct symtab_command) +
1002 sizeof(struct nlist) * (1 + nobject_list) +
1003 ref_object.string_size;
1007 * This routine builds the parts of the host shared library objects. There will
1008 * be an object in the host library for each object specified in the #objects
1009 * list. These objects have the same global symbols but with their values
1010 * changed to the absolute value the symbol has in the target shared library.
1011 * If the symbol has a branch table slot that value is used as the symbol's
1012 * value. The other symbols a host object are the it's file definition symbol
1013 * and references to them and a reference to the library definition symbol.
1015 static
1016 void
1017 build_host_objects(void)
1019 unsigned long i, j, strx, hash_key, len, new_symbols, new_string_size;
1020 char *p;
1021 struct object *op;
1022 struct ref *refp;
1023 struct ext *extp;
1024 struct init *ip;
1027 * Build the peices of the host object for each object specified.
1029 for(i = 0; i < nobject_list; i++){
1030 op = object_list[i];
1033 * If the symbol is not undefined then change it to an absolute
1034 * symbol of the value in the target. If it has a branch table
1035 * entry used the branch value. Also convert all symbols' names
1036 * to string table offsets. Their strings have been allocated
1037 * contiguiously and is used directly as the string table for
1038 * the base symbols.
1040 strx = 1; /* room for the first zero byte */
1041 for(j = 0; j < op->nsymbols; j++){
1042 len = strlen(op->symbols[j].n_un.n_name) + 1;
1043 if((op->symbols[j].n_type & N_TYPE) != N_UNDF){
1044 p = op->symbols[j].n_un.n_name;
1045 hash_key = hash_string(p) % EXT_HASH_SIZE;
1046 extp = ext_hash[hash_key];
1047 while(extp != (struct ext *)0){
1048 if(strcmp(p, extp->name) == 0)
1049 break;
1050 extp = extp->next;
1052 if(extp == (struct ext *)0)
1053 fatal("symbol: %s in object: %s not found in target "
1054 "shared library: %s", p, object_list[i]->name,
1055 target_filename);
1056 if(extp->bp != (struct branch *)0)
1057 op->symbols[j].n_value = extp->branch_value;
1058 else
1059 op->symbols[j].n_value = extp->value;
1060 op->symbols[j].n_type = N_ABS | N_EXT;
1061 op->symbols[j].n_sect = NO_SECT;
1062 toc_object.nranlibs++;
1063 toc_object.ranlib_string_size += len;
1065 op->symbols[j].n_un.n_strx = strx;
1066 strx += len;
1070 * Now count the number of new symbols to be added to the base
1071 * symbols and the size of their strings. The symbols for the
1072 * initialization are place just after the base symbols and any
1073 * external relocation entries for them use this fact so to set
1074 * the symbol index (op->nsymbols + new_symbols). So after the
1075 * the size of the new symbol is determined these new symbols must
1076 * be added in this order.
1078 new_symbols = 0;
1080 * If the object has no strings then the first byte of the string
1081 * table is allocated here.
1083 if(object_list[i]->string_size == 0)
1084 new_string_size = 1;
1085 else
1086 new_string_size = 0;
1087 op->ninit = 0;
1088 if(op->inits != (struct init *)0){
1089 ip = op->inits;
1090 while(ip != (struct init *)0){
1091 init_symbol(op, ip->sinit, &(ip->sreloc), &(ip->svalue),
1092 &(ip->sdefined), op->nsymbols + new_symbols,
1093 (op->ninit * 2) * sizeof(long));
1094 if(!ip->sdefined){
1095 new_symbols++;
1096 new_string_size += strlen(ip->sinit) + 1;
1098 init_symbol(op, ip->pinit, &(ip->preloc), &(ip->pvalue),
1099 &(ip->pdefined), op->nsymbols + new_symbols,
1100 (op->ninit * 2 + 1) * sizeof(long));
1101 if(!ip->pdefined){
1102 new_symbols++;
1103 new_string_size += strlen(ip->pinit) + 1;
1105 op->ninit++;
1106 ip = ip->next;
1110 * Count the number of symbols for the references and the
1111 * size their strings.
1113 refp = op->refs;
1114 while(refp != (struct ref *)0){
1115 new_symbols++;
1116 new_string_size += strlen(refp->name) + 1;
1117 refp = refp->next;
1120 * Count and size the file definition symbol (this will be defined).
1122 new_symbols++;
1123 len = strlen(op->filedef_name) + 1;
1124 new_string_size += len;
1125 toc_object.nranlibs++;
1126 toc_object.ranlib_string_size += len;
1128 * Count and size the shared library definition symbol.
1130 new_symbols++;
1131 new_string_size += strlen(shlib_symbol_name) + 1;
1135 * Allocate additional room for the new symbols and their strings.
1137 object_list[i]->symbols =
1138 reallocate(object_list[i]->symbols,
1139 (object_list[i]->nsymbols + new_symbols) *
1140 sizeof(struct nlist));
1141 object_list[i]->strings =
1142 reallocate(object_list[i]->strings,
1143 round(object_list[i]->string_size +
1144 new_string_size, sizeof(long)));
1145 /* zero the rounded area */
1146 memset(object_list[i]->strings +
1147 object_list[i]->string_size + new_string_size, '\0',
1148 round(object_list[i]->string_size + new_string_size,
1149 sizeof(long)) -
1150 (object_list[i]->string_size + new_string_size) );
1152 object_list[i]->string_size = round(object_list[i]->string_size +
1153 new_string_size, sizeof(long));
1155 * Add the new symbols and their strings to the symbol and string
1156 * table. The init symbol must be added first and in this order
1157 * because relocation entries are depending on the symbol indexes.
1158 * See comments above where the new symbols are counted.
1160 if(op->inits != (struct init *)0){
1161 ip = op->inits;
1162 while(ip != (struct init *)0){
1163 if(!ip->sdefined){
1164 op->symbols[op->nsymbols].n_un.n_strx = strx;
1165 op->symbols[op->nsymbols].n_type = N_UNDF | N_EXT;
1166 op->symbols[op->nsymbols].n_sect = NO_SECT;
1167 op->symbols[op->nsymbols].n_desc = 0;
1168 op->symbols[op->nsymbols].n_value = 0;
1169 strcpy(op->strings + strx, ip->sinit);
1170 op->nsymbols++;
1171 strx += strlen(ip->sinit) + 1;
1173 if(!ip->pdefined){
1174 op->symbols[op->nsymbols].n_un.n_strx = strx;
1175 op->symbols[op->nsymbols].n_type = N_UNDF | N_EXT;
1176 op->symbols[op->nsymbols].n_sect = NO_SECT;
1177 op->symbols[op->nsymbols].n_desc = 0;
1178 op->symbols[op->nsymbols].n_value = 0;
1179 strcpy(op->strings + strx, ip->pinit);
1180 op->nsymbols++;
1181 strx += strlen(ip->pinit) + 1;
1183 ip = ip->next;
1187 * Add the symbols for the references.
1189 refp = op->refs;
1190 while(refp != (struct ref *)0){
1191 op->symbols[op->nsymbols].n_un.n_strx = strx;
1192 op->symbols[op->nsymbols].n_type = N_UNDF | N_EXT;
1193 op->symbols[op->nsymbols].n_sect = NO_SECT;
1194 op->symbols[op->nsymbols].n_desc = 0;
1195 op->symbols[op->nsymbols].n_value = 0;
1196 strcpy(op->strings + strx, refp->name);
1197 op->nsymbols++;
1198 strx += strlen(refp->name) + 1;
1199 refp = refp->next;
1202 * Add the file definition symbol (this is defined).
1204 op->symbols[op->nsymbols].n_un.n_strx = strx;
1205 op->symbols[op->nsymbols].n_type = N_ABS | N_EXT;
1206 op->symbols[op->nsymbols].n_sect = NO_SECT;
1207 op->symbols[op->nsymbols].n_desc = 0;
1208 op->symbols[op->nsymbols].n_value = 0;
1209 strcpy(op->strings + strx, op->filedef_name);
1210 op->nsymbols++;
1211 strx += strlen(op->filedef_name) + 1;
1213 * Count and size the shared library definition symbol.
1215 op->symbols[op->nsymbols].n_un.n_strx = strx;
1216 op->symbols[op->nsymbols].n_type = N_UNDF | N_EXT;
1217 op->symbols[op->nsymbols].n_sect = NO_SECT;
1218 op->symbols[op->nsymbols].n_desc = 0;
1219 op->symbols[op->nsymbols].n_value = 0;
1220 strcpy(op->strings + strx, shlib_symbol_name);
1221 op->nsymbols++;
1222 strx += strlen(shlib_symbol_name) + 1;
1225 * Calculate the size of this object file. It will look like:
1226 * Mach header
1227 * LC_SEGMENT load command
1228 * the section header (for initialization section)
1229 * LC_SYMTAB load command
1230 * The contents of the initialization section
1231 * The relocation entries for the initialization section
1232 * The symbol table
1233 * The string table
1235 op->object_size = sizeof(struct mach_header) +
1236 sizeof(struct segment_command) +
1237 sizeof(struct section) +
1238 sizeof(struct symtab_command) +
1239 op->ninit * 2 * sizeof(long) +
1240 op->ninit * 2 * sizeof(struct relocation_info) +
1241 op->nsymbols * sizeof(struct nlist) +
1242 op->string_size;
1247 * init_symbol() sets a bunch of things for the specified symbol `name' of an
1248 * #init directive for the object pointed to by `op'. How the fields get set
1249 * depends on if the symbol is defined in the object. The things that get set
1250 * are the fields of the relocation entry pointed to by 'reloc', the value of
1251 * the symbol gets set into what is pointed by `value', if the symbol is defined
1252 * then what is pointed to by `defined' is set to 1 (otherwise set to 0). To
1253 * set the symbolnum field of an external relocation entry for a symbol that is
1254 * not defined the symbol index into the symbol table for the symbol table is
1255 * needed. The value of `symbolnum' is the symbol index used. The caller
1256 * passes the next symbol after the last symbol index and after init_symbol()
1257 * returns and `defined' is not set will create a symbol table entry for this
1258 * symbol at that symbol index. The value of `address' is the section offset
1259 * (in bytes) to where the value of the symbol will be in that section.
1261 static
1262 void
1263 init_symbol(
1264 struct object *op,
1265 char *name,
1266 struct relocation_info *reloc,
1267 long *value,
1268 long *defined,
1269 long symbolnum,
1270 long address)
1272 long hash_key;
1273 struct ext *extp;
1276 * Look up the symbol to see if it is defined and what object file it is
1277 * defined in.
1279 hash_key = hash_string(name) % EXT_HASH_SIZE;
1280 extp = ext_hash[hash_key];
1281 while(extp != (struct ext *)0){
1282 if(strcmp(name, extp->name) == 0)
1283 break;
1284 extp = extp->next;
1287 * See if this symbol is defined in this object.
1289 if(extp == (struct ext *)0 || extp->op != op){
1291 * It not is defined in this object so an external relocation entry
1292 * will be created.
1294 reloc->r_address = address;
1295 reloc->r_symbolnum = symbolnum;
1296 reloc->r_pcrel = 0; /* FALSE */
1297 reloc->r_length = 2; /* long */
1298 reloc->r_extern = 1; /* TRUE */
1299 reloc->r_type = 0;
1300 *value = 0;
1301 *defined = 0;
1303 else{
1305 * It is defined in this object so a local relocation entry
1306 * will be created.
1308 reloc->r_address = address;
1309 reloc->r_symbolnum = R_ABS;
1310 reloc->r_pcrel = 0; /* FALSE */
1311 reloc->r_length = 2; /* long */
1312 reloc->r_extern = 0; /* FALSE */
1313 reloc->r_type = 0;
1314 if(extp->bp != (struct branch *)0)
1315 *value = extp->branch_value;
1316 else
1317 *value = extp->value;
1318 *defined = 1;
1323 * write_archive() causes the host shared library to be written to the host
1324 * library file.
1326 static
1327 void
1328 write_archive(void)
1330 int fd;
1331 kern_return_t r;
1332 char *buffer;
1333 unsigned long offset;
1334 struct stat stat;
1335 long mtime, symdef_mtime, mode;
1336 uid_t uid;
1337 gid_t gid;
1338 struct ar_hdr ar_hdr;
1339 unsigned long i, l;
1340 struct object *op;
1341 struct ranlib *ranlibs;
1344 * Create the file for the host archive and the buffer for it's
1345 * contents.
1347 (void)unlink(host_filename);
1348 if((fd = open(host_filename, O_WRONLY | O_CREAT | O_TRUNC, 0666)) == -1)
1349 system_fatal("can't create file: %s", host_filename);
1350 if((r = vm_allocate(mach_task_self(), (vm_address_t *)&buffer,
1351 host_lib_size, TRUE)) != KERN_SUCCESS)
1352 mach_fatal(r, "can't vm_allocate() buffer for host library of size "
1353 "%ld", host_lib_size);
1356 * Set the variables needed for the archive headers.
1358 if(fstat(fd, &stat) == -1)
1359 system_fatal("can't stat host library file: %s", host_filename);
1360 mtime = time(0);
1361 symdef_mtime = (mtime > stat.st_mtime) ? mtime + 5 : stat.st_mtime + 5;
1362 uid = getuid();
1363 gid = getgid();
1364 mode = stat.st_mode & 0777;
1367 * Now start putting the contents of the host library into the buffer.
1368 * First goes the archive magic string.
1370 offset = 0;
1371 memcpy(buffer + offset, ARMAG, SARMAG);
1372 offset += SARMAG;
1374 * The first member of the archive is the table of contents. Put
1375 * its archive header in the buffer.
1377 sprintf(buffer + offset, "%-*.*s%-*ld%-*u%-*u%-*o%-*ld%-*s",
1378 (int)sizeof(ar_hdr.ar_name),
1379 (int)sizeof(ar_hdr.ar_name),
1380 SYMDEF_SORTED,
1381 (int)sizeof(ar_hdr.ar_date),
1382 symdef_mtime,
1383 (int)sizeof(ar_hdr.ar_uid),
1384 (unsigned int)uid,
1385 (int)sizeof(ar_hdr.ar_gid),
1386 (unsigned int)gid,
1387 (int)sizeof(ar_hdr.ar_mode),
1388 (unsigned int)mode,
1389 (int)sizeof(ar_hdr.ar_size),
1390 toc_object.object_size,
1391 (int)sizeof(ar_hdr.ar_fmag),
1392 ARFMAG);
1393 offset += sizeof(struct ar_hdr);
1395 * Now put the table of contents itself into the buffer
1397 l = toc_object.nranlibs * sizeof(struct ranlib);
1398 if(host_byte_sex != target_byte_sex)
1399 l = SWAP_LONG(l);
1400 *((long *)(buffer + offset)) = l;
1401 offset += sizeof(long);
1402 ranlibs = (struct ranlib *)(buffer + offset);
1403 memcpy(buffer + offset, toc_object.ranlibs,
1404 toc_object.nranlibs * sizeof(struct ranlib));
1405 if(host_byte_sex != target_byte_sex)
1406 swap_ranlib(ranlibs, toc_object.nranlibs, target_byte_sex);
1407 offset += toc_object.nranlibs * sizeof(struct ranlib);
1408 l = toc_object.ranlib_string_size;
1409 if(host_byte_sex != target_byte_sex)
1410 l = SWAP_LONG(l);
1411 *((long *)(buffer + offset)) = l;
1412 offset += sizeof(long);
1413 memcpy(buffer + offset, toc_object.ranlib_strings,
1414 toc_object.ranlib_string_size);
1415 offset += toc_object.ranlib_string_size;
1418 * The second member of the archive is the library definition object.
1419 * Put its archive header in the buffer.
1421 sprintf(buffer + offset, "%-*.*s%-*ld%-*u%-*u%-*o%-*ld%-*s",
1422 (int)sizeof(ar_hdr.ar_name),
1423 (int)sizeof(ar_hdr.ar_name),
1424 "__.FVMLIB",
1425 (int)sizeof(ar_hdr.ar_date),
1426 mtime,
1427 (int)sizeof(ar_hdr.ar_uid),
1428 (unsigned int)uid,
1429 (int)sizeof(ar_hdr.ar_gid),
1430 (unsigned int)gid,
1431 (int)sizeof(ar_hdr.ar_mode),
1432 (unsigned int)mode,
1433 (int)sizeof(ar_hdr.ar_size),
1434 lib_object.object_size,
1435 (int)sizeof(ar_hdr.ar_fmag),
1436 ARFMAG);
1437 offset += sizeof(struct ar_hdr);
1439 * Call write_lib_obj() to write the library definition object into the
1440 * buffer address it is passed.
1442 write_lib_obj(buffer + offset);
1443 offset += lib_object.object_size;
1446 * The third member of the archive is the library reference object.
1447 * Put its archive header in the buffer.
1449 sprintf(buffer + offset, "%-*.*s%-*ld%-*u%-*u%-*o%-*ld%-*s",
1450 (int)sizeof(ar_hdr.ar_name),
1451 (int)sizeof(ar_hdr.ar_name),
1452 "__.FVMLIB_REF",
1453 (int)sizeof(ar_hdr.ar_date),
1454 mtime,
1455 (int)sizeof(ar_hdr.ar_uid),
1456 (unsigned int)uid,
1457 (int)sizeof(ar_hdr.ar_gid),
1458 (unsigned int)gid,
1459 (int)sizeof(ar_hdr.ar_mode),
1460 (unsigned int)mode,
1461 (int)sizeof(ar_hdr.ar_size),
1462 ref_object.object_size,
1463 (int)sizeof(ar_hdr.ar_fmag),
1464 ARFMAG);
1465 offset += sizeof(struct ar_hdr);
1467 * Call write_ref_obj() to write the library reference object into the
1468 * buffer address it is passed.
1470 write_ref_obj(buffer + offset);
1471 offset += ref_object.object_size;
1474 * The remaining members of the archive are the host objects.
1476 for(i = 0; i < nobject_list; i++){
1477 op = object_list[i];
1479 * Put this object's archive header in the buffer.
1481 sprintf(buffer + offset, "%-*.*s%-*ld%-*u%-*u%-*o%-*ld%-*s",
1482 (int)sizeof(ar_hdr.ar_name),
1483 (int)sizeof(ar_hdr.ar_name),
1484 op->base_name,
1485 (int)sizeof(ar_hdr.ar_date),
1486 mtime,
1487 (int)sizeof(ar_hdr.ar_uid),
1488 (unsigned int)uid,
1489 (int)sizeof(ar_hdr.ar_gid),
1490 (unsigned int)gid,
1491 (int)sizeof(ar_hdr.ar_mode),
1492 (unsigned int)mode,
1493 (int)sizeof(ar_hdr.ar_size),
1494 op->object_size,
1495 (int)sizeof(ar_hdr.ar_fmag),
1496 ARFMAG);
1497 offset += sizeof(struct ar_hdr);
1499 * Call write_object() to write the host object into the
1500 * buffer at the address passed to it.
1502 write_object(op, buffer + offset);
1503 offset += op->object_size;
1507 * Write the buffer to the host archive file and deallocate the buffer.
1509 if(write(fd, buffer, host_lib_size) != host_lib_size)
1510 system_fatal("can't write host library file: %s", host_filename);
1511 #ifdef OS_BUG
1512 fsync(fd);
1513 #endif
1514 if(close(fd) == -1)
1515 system_fatal("can't close file: %s", host_filename);
1516 if((r = vm_deallocate(mach_task_self(), (vm_address_t)buffer,
1517 host_lib_size)) != KERN_SUCCESS)
1518 mach_fatal(r, "can't vm_deallocate() buffer for host library");
1522 * write_lib_obj() writes the library definition object into the buffer passed
1523 * to it.
1525 static
1526 void
1527 write_lib_obj(
1528 char *buffer)
1530 unsigned long offset, i;
1531 struct mach_header *mh;
1532 struct load_command *lc, *lib_obj_load_commands;
1533 struct segment_command *sg;
1534 struct fvmlib_command *fvmlib;
1535 struct symtab_command *st;
1536 struct nlist *symbol;
1538 offset = 0;
1541 * This file is made up of the following:
1542 * mach header
1543 * one LC_SEGMENT for each one in the target marked with SG_FVMLIB
1544 * an LC_LOADFVMLIB command for the library
1545 * an LC_SYMTAB command
1546 * one symbol (the library definition symbol)
1547 * the string table (with one string in it)
1549 mh = (struct mach_header *)(buffer + offset);
1550 mh->magic = MH_MAGIC;
1551 mh->cputype = arch_flag.cputype;
1552 mh->cpusubtype = arch_flag.cpusubtype;
1553 mh->filetype = MH_OBJECT;
1554 mh->ncmds = 2 + lib_object.nfvmsegs;
1555 mh->sizeofcmds = lib_object.nfvmsegs * sizeof(struct segment_command) +
1556 sizeof(struct symtab_command) +
1557 sizeof(struct fvmlib_command) +
1558 lib_object.fvmlib_name_size;
1559 mh->flags = MH_NOUNDEFS;
1560 offset += sizeof(struct mach_header);
1563 * This object file has segment commands for the segments of the
1564 * shared library (marked with SG_FLAGS). These are so the Mach-O
1565 * link editor can check the segments for overlap.
1567 lc = (struct load_command *)load_commands;
1568 lib_obj_load_commands = (struct load_command *)(buffer + offset);
1569 for(i = 0; i < target_mh.ncmds; i++){
1570 if(lc->cmd == LC_SEGMENT){
1571 sg = (struct segment_command *)(buffer + offset);
1572 *sg = *((struct segment_command *)lc);
1573 if(strcmp(sg->segname, SEG_LINKEDIT) == 0)
1574 sg->vmsize = 0;
1575 sg->cmdsize = sizeof(struct segment_command);
1576 sg->fileoff = 0;
1577 sg->filesize = 0;
1578 sg->nsects = 0;
1579 sg->flags = SG_FVMLIB;
1580 offset += sizeof(struct segment_command);
1582 lc = (struct load_command *)((char *)lc + lc->cmdsize);
1586 * The LC_LOADFVMLIB command for the library. This appearing in an
1587 * object is what causes the target library to be mapped in when it
1588 * is executed. The link editor collects these into the output file
1589 * it builds from the input files. Since every object in the host
1590 * library refers to the library definition symbol defined in here
1591 * this object is always linked with anything that uses this library.
1593 fvmlib = (struct fvmlib_command *)(buffer + offset);
1594 fvmlib->cmd = LC_LOADFVMLIB;
1595 fvmlib->cmdsize = sizeof(struct fvmlib_command) +
1596 lib_object.fvmlib_name_size;
1597 fvmlib->fvmlib.name.offset = sizeof(struct fvmlib_command);
1598 fvmlib->fvmlib.minor_version = minor_version;
1599 fvmlib->fvmlib.header_addr = text_addr;
1600 offset += sizeof(struct fvmlib_command);
1601 strcpy(buffer + offset, target_name);
1602 offset += lib_object.fvmlib_name_size;
1604 st = (struct symtab_command *)(buffer + offset);
1605 st->cmd = LC_SYMTAB;
1606 st->cmdsize = sizeof(struct symtab_command);
1607 st->symoff = sizeof(struct mach_header) + mh->sizeofcmds;
1608 st->nsyms = 1;
1609 st->stroff = st->symoff + sizeof(struct nlist);
1610 st->strsize = lib_object.string_size;
1611 offset += sizeof(struct symtab_command);
1614 * This is the library definition symbol.
1615 * For the first (and only) string is place at index 1 rather than
1616 * index 0. An index of zero is assumed to have the symbol name of "".
1618 symbol = (struct nlist *)(buffer + offset);
1619 symbol->n_un.n_strx = 1;
1620 symbol->n_type = N_ABS | N_EXT;
1621 symbol->n_sect = NO_SECT;
1622 symbol->n_desc = 0;
1623 symbol->n_value = 0;
1624 offset += sizeof(struct nlist);
1626 strcpy(buffer + offset + 1, shlib_symbol_name);
1627 offset += lib_object.string_size;
1629 if(host_byte_sex != target_byte_sex){
1630 if(swap_object_headers(mh, lib_obj_load_commands) == FALSE)
1631 fatal("internal error: swap_object_headers() failed");
1632 swap_nlist(symbol, 1, target_byte_sex);
1637 * write_ref_obj() writes the library reference object into the buffer passed
1638 * to it.
1640 static
1641 void
1642 write_ref_obj(
1643 char *buffer)
1645 unsigned long offset, strx, i;
1646 struct mach_header *mh;
1647 struct symtab_command *st;
1648 struct nlist *symbols, *first_symbol;
1649 char *strings;
1651 offset = 0;
1654 * This file is made up of the following:
1655 * mach header
1656 * an LC_SYMTAB command
1657 * the symbol table
1658 * the string table
1660 mh = (struct mach_header *)(buffer + offset);
1661 mh->magic = MH_MAGIC;
1662 mh->cputype = arch_flag.cputype;
1663 mh->cpusubtype = arch_flag.cpusubtype;
1664 mh->filetype = MH_OBJECT;
1665 mh->ncmds = 1;
1666 mh->sizeofcmds = sizeof(struct symtab_command);
1667 mh->flags = 0;
1668 offset += sizeof(struct mach_header);
1670 st = (struct symtab_command *)(buffer + offset);
1671 st->cmd = LC_SYMTAB;
1672 st->cmdsize = sizeof(struct symtab_command);
1673 st->symoff = sizeof(struct mach_header) + mh->sizeofcmds;
1674 st->nsyms = 1 + nobject_list;
1675 st->stroff = st->symoff + (st->nsyms * sizeof(struct nlist));
1676 st->strsize = ref_object.string_size;
1677 offset += sizeof(struct symtab_command);
1680 * Setup to put all the symbols and strings in the buffer. The first
1681 * string is place at index 1 rather than index 0. An index of zero is
1682 * assumed to have the symbol name of "" (or NULL).
1684 strings = (char *)(buffer + st->stroff);
1685 symbols = (struct nlist *)(buffer + st->symoff);
1686 first_symbol = symbols;
1687 strx = 1;
1689 /* The first symbol is the library reference symbol which is defined. */
1690 symbols->n_un.n_strx = strx;
1691 strcpy(strings + strx, shlib_reference_name);
1692 strx += strlen(shlib_reference_name) + 1;
1693 symbols->n_type = N_ABS | N_EXT;
1694 symbols->n_sect = NO_SECT;
1695 symbols->n_desc = 0;
1696 symbols->n_value = 0;
1697 symbols++;
1700 * All the other symbols are undefined references to the file definition
1701 * symbols of each object.
1703 for(i = 0; i < nobject_list; i++){
1704 symbols->n_un.n_strx = strx;
1705 strcpy(strings + strx, object_list[i]->filedef_name);
1706 strx += strlen(object_list[i]->filedef_name) + 1;
1707 symbols->n_type = N_UNDF | N_EXT;
1708 symbols->n_sect = NO_SECT;
1709 symbols->n_desc = 0;
1710 symbols->n_value = 0;
1711 symbols++;
1714 if(host_byte_sex != target_byte_sex){
1715 swap_mach_header(mh, target_byte_sex);
1716 swap_symtab_command(st, target_byte_sex);
1717 swap_nlist(first_symbol, 1 + nobject_list, target_byte_sex);
1722 * write_object() writes the host object specified by `op' into the buffer
1723 * specified.
1725 static
1726 void
1727 write_object(
1728 struct object *op,
1729 char *buffer)
1731 long offset;
1732 struct mach_header *mh;
1733 struct segment_command *sg;
1734 struct section *s;
1735 struct symtab_command *st;
1736 struct init *ip;
1737 long *contents;
1738 struct nlist *symbols;
1739 struct relocation_info *reloc, *relocs;
1741 offset = 0;
1744 * Each host object file contains:
1745 * mach header
1746 * one LC_SEGMENT
1747 * a section header for the initialization section
1748 * an LC_SYMTAB command
1749 * the contents of the initialization section
1750 * the relocation entries for the initialization section
1751 * the symbol table
1752 * the string table
1754 mh = (struct mach_header *)(buffer + offset);
1755 mh->magic = MH_MAGIC;
1756 mh->cputype = arch_flag.cputype;
1757 mh->cpusubtype = arch_flag.cpusubtype;
1758 mh->filetype = MH_OBJECT;
1759 mh->ncmds = 2;
1760 mh->sizeofcmds = sizeof(struct segment_command) +
1761 sizeof(struct section) +
1762 sizeof(struct symtab_command);
1763 mh->flags = 0;
1764 offset += sizeof(struct mach_header);
1766 sg = (struct segment_command *)(buffer + offset);
1767 sg->cmd = LC_SEGMENT;
1768 sg->cmdsize = sizeof(struct segment_command) + sizeof(struct section);
1770 * This could be done but since the buffer is vm_allocate()'ed it has
1771 * zeros in it already
1772 * memset(sg->segname, '\0', sizeof(sg->segname));
1774 sg->vmaddr = 0;
1775 sg->vmsize = op->ninit * 2 * sizeof(long);
1776 sg->fileoff = sizeof(struct mach_header) + mh->sizeofcmds;
1777 sg->filesize = op->ninit * 2 * sizeof(long);
1778 sg->maxprot = VM_PROT_READ | VM_PROT_WRITE | VM_PROT_EXECUTE;
1779 sg->initprot = VM_PROT_READ | VM_PROT_WRITE | VM_PROT_EXECUTE;
1780 sg->nsects = 1;
1781 sg->flags = 0;
1782 offset += sizeof(struct segment_command);
1784 s = (struct section *)(buffer + offset);
1785 strcpy(s->sectname, SECT_FVMLIB_INIT0);
1786 strcpy(s->segname, SEG_TEXT);
1787 s->addr = 0;
1788 s->size = op->ninit * 2 * sizeof(long);
1789 s->offset = sizeof(struct mach_header) + mh->sizeofcmds;
1790 s->align = 2;
1791 s->reloff = sizeof(struct mach_header) + mh->sizeofcmds +
1792 op->ninit * 2 * sizeof(long);
1793 s->nreloc = op->ninit * 2;
1794 s->flags = 0;
1795 s->reserved1 = 0;
1796 s->reserved2 = 0;
1797 offset += sizeof(struct section);
1799 st = (struct symtab_command *)(buffer + offset);
1800 st->cmd = LC_SYMTAB;
1801 st->cmdsize = sizeof(struct symtab_command);
1802 st->symoff = sizeof(struct mach_header) +
1803 mh->sizeofcmds +
1804 op->ninit * 2 * sizeof(long) +
1805 op->ninit * 2 * sizeof(struct relocation_info);
1806 st->nsyms = op->nsymbols;
1807 st->stroff = sizeof(struct mach_header) +
1808 mh->sizeofcmds +
1809 op->ninit * 2 * sizeof(long) +
1810 op->ninit * 2 * sizeof(struct relocation_info) +
1811 op->nsymbols * sizeof(struct nlist);
1812 st->strsize = op->string_size;
1813 offset += sizeof(struct symtab_command);
1816 * Put the contents of the initialization section in the buffer.
1818 if(op->inits != (struct init *)0){
1819 ip = op->inits;
1820 while(ip != (struct init *)0){
1821 contents = (long *)(buffer + offset);
1822 if(host_byte_sex != target_byte_sex)
1823 *contents = SWAP_LONG(ip->svalue);
1824 else
1825 *contents = ip->svalue;
1826 offset += sizeof(long);
1828 contents = (long *)(buffer + offset);
1829 if(host_byte_sex != target_byte_sex)
1830 *contents = SWAP_LONG(ip->pvalue);
1831 else
1832 *contents = ip->pvalue;
1833 offset += sizeof(long);
1835 ip = ip->next;
1840 * Put the relocation entries for the initialization section in the
1841 * buffer.
1843 relocs = (struct relocation_info *)(buffer + offset);
1844 if(op->inits != (struct init *)0){
1845 ip = op->inits;
1846 while(ip != (struct init *)0){
1847 reloc = (struct relocation_info *)(buffer + offset);
1848 *reloc = ip->sreloc;
1849 offset += sizeof(struct relocation_info);
1851 reloc = (struct relocation_info *)(buffer + offset);
1852 *reloc = ip->preloc;
1853 offset += sizeof(struct relocation_info);
1855 ip = ip->next;
1860 * Copy the symbols into the buffer.
1862 symbols = (struct nlist *)(buffer + offset);
1863 memcpy(buffer + offset, op->symbols,
1864 op->nsymbols * sizeof(struct nlist));
1865 offset += op->nsymbols * sizeof(struct nlist);
1868 * Copy the strings into the buffer.
1870 memcpy(buffer + offset, op->strings, op->string_size);
1871 offset += op->string_size;
1873 if(host_byte_sex != target_byte_sex){
1874 swap_mach_header(mh, target_byte_sex);
1875 swap_segment_command(sg, target_byte_sex);
1876 swap_section(s, 1, target_byte_sex);
1877 swap_symtab_command(st, target_byte_sex);
1878 swap_relocation_info(relocs, op->ninit * 2, target_byte_sex);
1879 swap_nlist(symbols, op->nsymbols, target_byte_sex);