2 * Copyright (c) 1999 Apple Computer, Inc. All rights reserved.
4 * @APPLE_LICENSE_HEADER_START@
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
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@
27 #include <mach-o/loader.h>
28 #include <mach-o/nlist.h>
29 #include <mach-o/reloc.h>
30 #include <mach-o/ranlib.h>
34 #include <mach/mach.h>
35 #include "stuff/openstep_mach.h"
37 #include <sys/types.h>
39 #include "stuff/ofile.h"
40 #include "stuff/errors.h"
41 #include "stuff/allocate.h"
42 #include "stuff/hash_string.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.
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.
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(
144 static void scan_objects(
146 static void scan_objects_processor(
150 static void make_references(
153 static void build_archive(
155 static int ranlib_qsort(
156 const struct ranlib
*ran1
,
157 const struct ranlib
*ran2
);
158 static void build_lib_object(
160 static void build_ref_object(
162 static void build_host_objects(
164 static void init_symbol(
167 struct relocation_info
*reloc
,
172 static void write_archive(
174 static void write_lib_obj(
176 static void write_ref_obj(
178 static void write_object(
183 * Build the host shared library.
189 * Make the hash table for all external symbols in the library.
194 * Scan all the objects and collect their base symbol tables.
199 * Make all the references between the host objects.
204 * Build the components of the archive which is the host shared library.
209 * Write the components of the archive which is the host shared library.
215 * make_exthash() builds the hash table of all the external symbols in the
216 * target shared library.
223 unsigned int string_size
, hash_key
, i
, nsyms
;
224 struct nlist
*symbols
;
226 struct ext
*extp
, *bextp
;
229 struct load_command
*lc
;
230 struct symtab_command
*st
;
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
)
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
++){
253 if(st
!= (struct symtab_command
*)0)
254 fatal("More than one symtab_command in: %s", target_name
);
256 st
= (struct symtab_command
*)lc
;
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
);
265 fatal("No symbol table in: %s", target_name
);
267 fatal("No string table in: %s", target_name
);
268 symbols
= (struct nlist
*)(ofile
.object_addr
+ st
->symoff
);
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)
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
);
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;
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
))
313 if(is_libdef_symbol(extp
->name
))
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)
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)
331 if(obp
!= (struct oddball
*)0 && obp
->private)
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
);
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.
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)
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)
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
,
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
++){
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)
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
;
412 printf("Just after building external symbol table\n");
413 for(i
= 0; i
< EXT_HASH_SIZE
; 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
,
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
,
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.
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
);
449 scan_objects_processor(
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
;
461 i
= *((long *)cookie
);
463 lc
= ofile
->load_commands
;
464 for(j
= 0; j
< ofile
->mh
->ncmds
; j
++){
465 if(lc
->cmd
== LC_SYMTAB
){
467 fatal("more than one symtab command in object file: %s",
469 st
= (struct symtab_command
*)lc
;
471 lc
= (struct load_command
*)((char *)lc
+ lc
->cmdsize
);
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;
488 /* read the symbol table */
489 symbols
= (struct nlist
*)(ofile
->object_addr
+ st
->symoff
);
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)
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)
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
,
526 if(extp
->alias
!= (struct ext
*)0){
527 symbols
[j
].n_un
.n_name
= extp
->alias
->name
;
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.
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
;
564 printf("private defined = %s\n", symbols[j].n_un.n_name);
566 symbols
[j
].n_type
&= ~N_EXT
;
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
);
588 p
= object_list
[i
]->strings
;
589 *p
++ = '\0'; /* the first byte */
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);
603 q
+= strlen(symbols
[j
].n_un
.n_name
) + 1;
606 /* again if it is not an external symbol skip it */
607 if((symbols
[j
].n_type
& N_EXT
) == 0)
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
;
613 p
+= strlen(symbols
[j
].n_un
.n_name
) + 1;
617 printf("Symbol tables of host objects\n");
618 for(i
= 0; i
< nobject_list
; i
++){
619 printf("\tobject = %s\n", ofile
->file_name
);
621 j
< object_list
[i
]->nsymbols
;
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
);
628 j
< object_list
[i
]->pu_nsymbols
;
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.
648 make_references(void)
650 unsigned long i
, j
, hash_key
;
656 printf("External symbol table with defining references\n");
657 for(i
= 0; i
< nobject_list
; 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
);
664 printf("\text = %s not defined in any object\n",
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
685 for(i
= 0; i
< nobject_list
; i
++){
687 j
< object_list
[i
]->nsymbols
;
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)
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
,
703 * If this symbol is an alias then uses the real symbol
706 if(extp
->alias
!= (struct ext
*)0)
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)
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
;
731 j
< object_list
[i
]->pu_nsymbols
;
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)
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
,
746 * If this symbol is an alias then uses the real symbol
749 if(extp
->alias
!= (struct ext
*)0)
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)
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
;
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
);
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.
795 unsigned long ran_index
, ran_strx
, ran_off
, i
, j
;
800 * Build the componets of the object that contains library definition
806 * Build the componets of the object that contains library full
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
=
832 toc_object
.nranlibs
* sizeof(struct ranlib
) +
834 round(toc_object
.ranlib_string_size
, sizeof(long));
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
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
);
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
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
);
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
869 for(i
= 0; i
< nobject_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
);
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
,
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.
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.
923 build_lib_object(void)
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,
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
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,
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.
976 build_ref_object(void)
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.
1017 build_host_objects(void)
1019 unsigned long i
, j
, strx
, hash_key
, len
, new_symbols
, new_string_size
;
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
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)
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
,
1056 if(extp
->bp
!= (struct branch
*)0)
1057 op
->symbols
[j
].n_value
= extp
->branch_value
;
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
;
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.
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;
1086 new_string_size
= 0;
1088 if(op
->inits
!= (struct init
*)0){
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));
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));
1103 new_string_size
+= strlen(ip
->pinit
) + 1;
1110 * Count the number of symbols for the references and the
1111 * size their strings.
1114 while(refp
!= (struct ref
*)0){
1116 new_string_size
+= strlen(refp
->name
) + 1;
1120 * Count and size the file definition symbol (this will be defined).
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.
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
,
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){
1162 while(ip
!= (struct init
*)0){
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
);
1171 strx
+= strlen(ip
->sinit
) + 1;
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
);
1181 strx
+= strlen(ip
->pinit
) + 1;
1187 * Add the symbols for the references.
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
);
1198 strx
+= strlen(refp
->name
) + 1;
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
);
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
);
1222 strx
+= strlen(shlib_symbol_name
) + 1;
1225 * Calculate the size of this object file. It will look like:
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
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
) +
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.
1266 struct relocation_info
*reloc
,
1276 * Look up the symbol to see if it is defined and what object file it is
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)
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
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 */
1305 * It is defined in this object so a local relocation entry
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 */
1314 if(extp
->bp
!= (struct branch
*)0)
1315 *value
= extp
->branch_value
;
1317 *value
= extp
->value
;
1323 * write_archive() causes the host shared library to be written to the host
1333 unsigned long offset
;
1335 long mtime
, symdef_mtime
, mode
;
1338 struct ar_hdr ar_hdr
;
1341 struct ranlib
*ranlibs
;
1344 * Create the file for the host archive and the buffer for it's
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
);
1361 symdef_mtime
= (mtime
> stat
.st_mtime
) ? mtime
+ 5 : stat
.st_mtime
+ 5;
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.
1371 memcpy(buffer
+ offset
, ARMAG
, 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
),
1381 (int)sizeof(ar_hdr
.ar_date
),
1383 (int)sizeof(ar_hdr
.ar_uid
),
1385 (int)sizeof(ar_hdr
.ar_gid
),
1387 (int)sizeof(ar_hdr
.ar_mode
),
1389 (int)sizeof(ar_hdr
.ar_size
),
1390 toc_object
.object_size
,
1391 (int)sizeof(ar_hdr
.ar_fmag
),
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
)
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
)
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
),
1425 (int)sizeof(ar_hdr
.ar_date
),
1427 (int)sizeof(ar_hdr
.ar_uid
),
1429 (int)sizeof(ar_hdr
.ar_gid
),
1431 (int)sizeof(ar_hdr
.ar_mode
),
1433 (int)sizeof(ar_hdr
.ar_size
),
1434 lib_object
.object_size
,
1435 (int)sizeof(ar_hdr
.ar_fmag
),
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
),
1453 (int)sizeof(ar_hdr
.ar_date
),
1455 (int)sizeof(ar_hdr
.ar_uid
),
1457 (int)sizeof(ar_hdr
.ar_gid
),
1459 (int)sizeof(ar_hdr
.ar_mode
),
1461 (int)sizeof(ar_hdr
.ar_size
),
1462 ref_object
.object_size
,
1463 (int)sizeof(ar_hdr
.ar_fmag
),
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
),
1485 (int)sizeof(ar_hdr
.ar_date
),
1487 (int)sizeof(ar_hdr
.ar_uid
),
1489 (int)sizeof(ar_hdr
.ar_gid
),
1491 (int)sizeof(ar_hdr
.ar_mode
),
1493 (int)sizeof(ar_hdr
.ar_size
),
1495 (int)sizeof(ar_hdr
.ar_fmag
),
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
);
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
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
;
1541 * This file is made up of the following:
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)
1575 sg
->cmdsize
= sizeof(struct segment_command
);
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
;
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
;
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
1645 unsigned long offset
, strx
, i
;
1646 struct mach_header
*mh
;
1647 struct symtab_command
*st
;
1648 struct nlist
*symbols
, *first_symbol
;
1654 * This file is made up of the following:
1656 * an LC_SYMTAB command
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
;
1666 mh
->sizeofcmds
= sizeof(struct symtab_command
);
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
;
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;
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;
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
1732 struct mach_header
*mh
;
1733 struct segment_command
*sg
;
1735 struct symtab_command
*st
;
1738 struct nlist
*symbols
;
1739 struct relocation_info
*reloc
, *relocs
;
1744 * Each host object file contains:
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
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
;
1760 mh
->sizeofcmds
= sizeof(struct segment_command
) +
1761 sizeof(struct section
) +
1762 sizeof(struct symtab_command
);
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));
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
;
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
);
1788 s
->size
= op
->ninit
* 2 * sizeof(long);
1789 s
->offset
= sizeof(struct mach_header
) + mh
->sizeofcmds
;
1791 s
->reloff
= sizeof(struct mach_header
) + mh
->sizeofcmds
+
1792 op
->ninit
* 2 * sizeof(long);
1793 s
->nreloc
= op
->ninit
* 2;
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
) +
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
) +
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){
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
);
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
);
1832 *contents
= ip
->pvalue
;
1833 offset
+= sizeof(long);
1840 * Put the relocation entries for the initialization section in the
1843 relocs
= (struct relocation_info
*)(buffer
+ offset
);
1844 if(op
->inits
!= (struct init
*)0){
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
);
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
);