2 * Copyright (c) 2007 Apple 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@
30 #include <sys/types.h>
33 #include "stuff/breakout.h"
34 #include "stuff/errors.h"
35 #include "stuff/allocate.h"
36 #include "stuff/reloc.h"
37 #include "stuff/rnd.h"
39 #include "coff/ms_dos_stub.h"
40 #include "coff/filehdr.h"
41 #include "coff/aouthdr.h"
42 #include "coff/scnhdr.h"
43 #include "coff/syment.h"
44 #include "coff/bytesex.h"
46 #include "coff/base_relocs.h"
47 #include "mach-o/x86_64/reloc.h"
49 /* used by error routines as the name of this program */
50 char *progname
= NULL
;
52 /* the bytesex of our target object file and of this host machine */
53 static enum byte_sex target_byte_sex
;
54 static enum byte_sex host_byte_sex
;
55 static enum bool swapped
;
57 /* the size of the pecoff output file */
58 static uint32_t output_size
= 0;
61 * The headers, and elements of them in the pecoff output file.
63 static struct ms_dos_stub ms_dos_stub
;
64 static char signature
[4];
65 static struct filehdr filehdr
;
66 static struct aouthdr aouthdr
;
67 static struct aouthdr_64 aouthdr64
;
68 uint32_t entry
= 0; /* the entry point */
69 uint32_t nscns
= 0; /* the number of section headers and contents pointers */
70 static struct scnhdr
*scnhdrs
= NULL
; /* the section headers */
71 static char **scn_contents
= NULL
; /* pointers to the section contents */
74 * The value of the -subsystem argument to then set in the PECOFF aouthdr.
76 static uint16_t Subsystem
= IMAGE_SUBSYSTEM_EFI_APPLICATION
;
78 struct subsystem_argument
{
83 struct subsystem_argument subsystem_arguments
[] = {
84 { "application", IMAGE_SUBSYSTEM_EFI_APPLICATION
},
85 { "app", IMAGE_SUBSYSTEM_EFI_APPLICATION
},
86 { "UEFI_APPLICATION", IMAGE_SUBSYSTEM_EFI_APPLICATION
},
87 { "APPLICATION", IMAGE_SUBSYSTEM_EFI_APPLICATION
},
89 { "boot", IMAGE_SUBSYSTEM_EFI_BOOT_SERVICE_DRIVER
},
90 { "bsdrv", IMAGE_SUBSYSTEM_EFI_BOOT_SERVICE_DRIVER
},
91 { "DXE_DRIVER", IMAGE_SUBSYSTEM_EFI_BOOT_SERVICE_DRIVER
},
92 { "SEC", IMAGE_SUBSYSTEM_EFI_BOOT_SERVICE_DRIVER
},
93 { "peim", IMAGE_SUBSYSTEM_EFI_BOOT_SERVICE_DRIVER
},
94 { "BASE", IMAGE_SUBSYSTEM_EFI_BOOT_SERVICE_DRIVER
},
95 { "PEI_CORE", IMAGE_SUBSYSTEM_EFI_BOOT_SERVICE_DRIVER
},
96 { "PEIM", IMAGE_SUBSYSTEM_EFI_BOOT_SERVICE_DRIVER
},
97 { "DXE_SMM_DRIVER", IMAGE_SUBSYSTEM_EFI_BOOT_SERVICE_DRIVER
},
98 { "TOOL", IMAGE_SUBSYSTEM_EFI_BOOT_SERVICE_DRIVER
},
99 { "USER_DEFINED", IMAGE_SUBSYSTEM_EFI_BOOT_SERVICE_DRIVER
},
100 { "UEFI_DRIVER", IMAGE_SUBSYSTEM_EFI_BOOT_SERVICE_DRIVER
},
101 { "DXE_CORE", IMAGE_SUBSYSTEM_EFI_BOOT_SERVICE_DRIVER
},
102 { "SECURITY_CORE", IMAGE_SUBSYSTEM_EFI_BOOT_SERVICE_DRIVER
},
103 { "COMBINED_PEIM_DRIVER", IMAGE_SUBSYSTEM_EFI_BOOT_SERVICE_DRIVER
},
104 { "PIC_PEIM", IMAGE_SUBSYSTEM_EFI_BOOT_SERVICE_DRIVER
},
105 { "RELOCATABLE_PEIM", IMAGE_SUBSYSTEM_EFI_BOOT_SERVICE_DRIVER
},
106 { "BS_DRIVER", IMAGE_SUBSYSTEM_EFI_BOOT_SERVICE_DRIVER
},
107 { "SMM_CORE", IMAGE_SUBSYSTEM_EFI_BOOT_SERVICE_DRIVER
},
109 { "runtime", IMAGE_SUBSYSTEM_EFI_RUNTIME_DRIVER
},
110 { "rtdrv", IMAGE_SUBSYSTEM_EFI_RUNTIME_DRIVER
},
111 { "DXE_RUNTIME_DRIVER", IMAGE_SUBSYSTEM_EFI_RUNTIME_DRIVER
},
117 * The value of the -section_alignment argument (or the -align argument) to
118 * layout the added PECOFF sections and set into the PECOFF aouthdr.
120 static uint32_t section_alignment
= SECTIONALIGNMENT
;
123 * The value of the -align argument to layout the PECOFF file.
125 static uint32_t file_alignment
= FILEALIGNMENT
;
127 /* The maximum alignment allowed to be specified, in hex */
128 #define MAXALIGN 0x8000
130 /* Static routine to help parse arguments */
131 static enum bool ispoweroftwo(uint32_t x
);
134 * The string for the -d argument.
136 char *debug_filename
= NULL
;
139 * The string for the -u argument.
141 char *debug_uuid
= NULL
;
144 * Format specifier for scanf() to convert UUID to individual bytes
146 #define UUID_FORMAT_STRING "%02hhx%02hhx%02hhx%02hhx-%02hhx%02hhx-%02hhx%02hhx-%02hhx%02hhx-%02hhx%02hhx%02hhx%02hhx%02hhx%02hhx"
149 * The string for the entry point symbol name.
151 char *entry_point
= NULL
;
153 #ifdef HACK_TO_MATCH_TEST_CASE
155 * These are are used for the HACK to get the symbol table for 32-bit files to
156 * match the one produced by objcopy. They are the pecoff section numbers of
157 * the .common and .bss sections.
159 static uint32_t common_scnum
= 0;
160 static uint32_t bss_scnum
= 0;
164 * These are for the .reloc section that contains the base relocations.
166 static struct scnhdr
*reloc_scnhdr
= NULL
;
167 static uint32_t reloc_size
= 0;
168 static char *reloc_contents
= NULL
;
171 * These are for the pecoff symbol table and string table.
173 static uint32_t nsyments
= 0; /* number of symbols */
174 static struct syment
*syments
= NULL
; /* pointer to symbol table elements */
175 static uint32_t syment_offset
= 0; /* file offset of the symbol table */
176 static uint32_t strsize
= 0; /* size of the string table */
177 static char *strings
= NULL
; /* pointer to the string table */
178 static uint32_t section_names_size
= 0; /* size of the section names */
179 static char *section_names
= NULL
; /* pointer to section names */
180 static uint32_t string_offset
= 0; /* file offset of the string table */
183 * These are for the .debug section that contains the -d filename information.
185 static struct scnhdr
*debug_scnhdr
= NULL
;
186 static uint32_t debug_size
= 0;
187 static char *debug_contents
= NULL
;
188 static struct debug_directory_entry
*dde
= NULL
;
189 static struct mtoc_debug_info
*mdi
= NULL
;
191 static void process_arch(
194 static void process_32bit_arch(
196 static void process_64bit_arch(
198 static void layout_output(
199 struct ofile
*ofile
);
200 static void create_output(
203 static void create_ms_dos_stub(
204 struct ms_dos_stub
*p
);
208 static void create_32bit_symbol_table(
210 static void create_64bit_symbol_table(
214 * This is the internal structure that we gather the base relocation in from
215 * the Mach-O relocation entries.
221 struct base_reloc
*base_relocs
= NULL
;
222 uint32_t nbase_reloc
= 0;
224 static void create_base_reloc(
226 static void gather_base_reloc_info(
228 struct relocation_info
*relocs
,
232 int macho_reloc_type
,
233 int base_reloc_type
);
234 static void add_base_reloc(
237 static void make_base_relocs(
239 static int cmp_base_relocs(
240 struct base_reloc
*x1
,
241 struct base_reloc
*x2
);
242 static uint32_t checksum(
244 static void string_to_uuid(
248 static void create_debug(
250 static void set_debug_addrs_and_offsets(
253 /* apple_version is created by the libstuff/Makefile */
254 extern char apple_version
[];
255 char *version
= apple_version
;
258 * The mtoc(1) tool makes a PECOFF file from a fully linked Mach-O file
259 * compiled with dynamic code gen and relocation entries saved (linked with -r).
261 * mtoc [-subsystem type] [-section_alignment hexvalue] [-align hexvalue]
262 * [-d filename] input_Mach-O output_pecoff
271 char *input
, *output
;
276 enum bool section_alignment_specified
, align_specified
;
279 host_byte_sex
= get_host_byte_sex();
284 section_alignment_specified
= FALSE
;
285 align_specified
= FALSE
;
287 for(i
= 1; i
< argc
; i
++){
288 if(strcmp(argv
[i
], "-subsystem") == 0){
290 warning("no argument specified for -subsystem option");
293 for(j
= 0; subsystem_arguments
[j
].name
!= NULL
; j
++){
294 if(strcmp(argv
[i
+1], subsystem_arguments
[j
].name
) == 0){
295 Subsystem
= subsystem_arguments
[j
].value
;
299 if(subsystem_arguments
[j
].name
== NULL
){
300 warning("unknown argument: %s specified for -subsystem "
301 "argument can be:", argv
[i
+1]);
302 for(j
= 0; subsystem_arguments
[j
].name
!= NULL
; j
++)
303 fprintf(stderr
, "%s\n", subsystem_arguments
[j
].name
);
308 else if(strcmp(argv
[i
], "-d") == 0){
310 warning("no argument specified for -d option");
313 debug_filename
= argv
[i
+1];
316 else if(strcmp(argv
[i
], "-e") == 0){
318 warning("no argument specified for -e option");
321 entry_point
= argv
[i
+1];
324 else if(strcmp(argv
[i
], "-u") == 0){
326 warning("no argument specified for -u option");
329 if(debug_filename
== NULL
) {
330 fatal("-u option requires -d option");
332 debug_uuid
= argv
[i
+1];
335 else if(strcmp(argv
[i
], "-section_alignment") == 0){
337 warning("no argument specified for -section_alignment "
341 section_alignment
= strtoul(argv
[i
+1], &endp
, 16);
343 fatal("argument for -section_alignment %s not a proper "
344 "hexadecimal number", argv
[i
+1]);
345 if(!ispoweroftwo(section_alignment
) || section_alignment
== 0)
346 fatal("argument to -section_alignment: %x (hex) must be a "
347 "non-zero power of two", section_alignment
);
348 if(section_alignment
> MAXALIGN
)
349 fatal("argument to -section_alignment: %x (hex) must "
350 "equal to or less than %x (hex)", section_alignment
,
351 (unsigned int)MAXALIGN
);
352 section_alignment_specified
= TRUE
;
353 if(align_specified
== TRUE
&&
354 section_alignment
!= file_alignment
)
355 fatal("can't specifiy a -section_alignment value %x (hex) "
356 "different from the -align value %x (hex)",
357 section_alignment
, file_alignment
);
360 else if(strcmp(argv
[i
], "-align") == 0){
362 warning("no argument specified for -align option");
365 file_alignment
= strtoul(argv
[i
+1], &endp
, 16);
367 fatal("argument for -align %s not a proper hexadecimal "
368 "number", argv
[i
+1]);
369 if(!ispoweroftwo(file_alignment
) || file_alignment
== 0)
370 fatal("argument to -align: %x (hex) must be a non-zero "
371 "power of two", file_alignment
);
372 if(file_alignment
> MAXALIGN
)
373 fatal("argument to -file_alignment: %x (hex) must "
374 "equal to or less than %x (hex)", file_alignment
,
375 (unsigned int)MAXALIGN
);
376 align_specified
= TRUE
;
377 if(section_alignment_specified
== TRUE
&&
378 section_alignment
!= file_alignment
)
379 fatal("can't specifiy a -section_alignment value %x (hex) "
380 "different from the -align value %x (hex)",
381 section_alignment
, file_alignment
);
382 section_alignment
= file_alignment
;
385 else if(input
== NULL
)
387 else if(output
== NULL
)
393 warning("no input file specified");
397 warning("no output file specified");
401 /* breakout the file for processing */
402 ofile
= breakout(input
, &archs
, &narchs
, FALSE
);
404 return(EXIT_FAILURE
);
406 /* checkout the file for symbol table replacement processing */
407 checkout(archs
, narchs
);
409 /* process the input file */
410 process_arch(archs
, narchs
);
412 free_archs(archs
, narchs
);
414 return(EXIT_FAILURE
);
418 * Layout the pecoff output file from the information gathered from
419 * the input file creating the needed headers, relocs, etc.
421 layout_output(ofile
);
423 create_output(ofile
, output
);
426 return(EXIT_SUCCESS
);
428 return(EXIT_FAILURE
);
432 * usage() prints the current usage message and exits indicating failure.
439 fprintf(stderr
, "Usage: %s [-subsystem type] "
440 "[-section_alignment hexvalue] [-align hexvalue] [-d debug_filename] "
441 "[-u debug_guid] input_Mach-O output_pecoff\n", progname
);
446 * ispoweroftwo() returns TRUE or FALSE depending if x is a power of two.
456 while((x
& 0x1) != 0x1){
466 * process_arch() is the routine that process the broken out ofile to gather
467 * the info to create the pecoff file. This routine basically counts and adds
468 * up the sizes of the elements that will be in the pecoff output file.
477 * Check to see the input file is something this program can convert to
481 fatal("input file: %s must only have one architecture",
483 if(archs
->type
!= OFILE_Mach_O
)
484 fatal("input file: %s must be a Mach-O file", archs
->file_name
);
485 if(archs
->object
->mh_cputype
!= CPU_TYPE_I386
&&
486 archs
->object
->mh_cputype
!= CPU_TYPE_ARM
&&
487 archs
->object
->mh_cputype
!= CPU_TYPE_X86_64
)
488 fatal("input file: %s must be an i386 or ARM architecture",
490 if(archs
->object
->mh
!= NULL
){
491 if(archs
->object
->mh
->filetype
== MH_PRELOAD
||
492 (archs
->object
->mh
->filetype
== MH_EXECUTE
&&
493 (archs
->object
->mh
->flags
& MH_PIE
) == MH_PIE
)){
494 if(entry_point
!= NULL
)
495 fatal("entry point option, -e %s, not allowed with "
496 "MH_PRELOAD or MH_EXECUTE file types", entry_point
);
499 fatal("input file: %s must be an MH_PRELOAD file type or "
500 "MH_EXECUTE file type with MH_PIE flag",
505 if(archs
->object
->mh64
->filetype
== MH_DYLIB
||
506 (archs
->object
->mh64
->filetype
== MH_EXECUTE
&&
507 (archs
->object
->mh64
->flags
& MH_PIE
) == MH_PIE
)){
508 if(entry_point
== NULL
&&
509 archs
->object
->mh64
->filetype
== MH_DYLIB
)
510 fatal("input file: %s is a MH_DYLIB file type, so entry "
511 "point option, -e name, must be specified",
514 else if(archs
->object
->mh64
->filetype
== MH_PRELOAD
||
515 (archs
->object
->mh64
->filetype
== MH_EXECUTE
&&
516 (archs
->object
->mh64
->flags
& MH_PIE
) == MH_PIE
)){
517 if(entry_point
!= NULL
)
518 fatal("entry point option, -e %s, not allowed with "
519 "MH_PRELOAD or MH_EXECUTE file types",
523 fatal("input file: %s must be an MH_PRELOAD or MH_DYLIB file "
524 "type or MH_EXECUTE file type with MH_PIE flag",
528 target_byte_sex
= archs
->object
->object_byte_sex
;
529 swapped
= host_byte_sex
!= target_byte_sex
;
532 * Create base relocation entries for this Mach-O file. This is done
533 * before the sections are created as this produces the contents for
534 * the .reloc section and determines it size.
536 create_base_reloc(archs
);
539 * If there is a -d flag create the information that will be in .debug
542 if(debug_filename
!= NULL
)
545 if(archs
->object
->mh
!= NULL
)
546 process_32bit_arch(archs
);
548 process_64bit_arch(archs
);
552 * process_32bit_arch() is the routine that processes a 32-bit broken out ofile
553 * to gather the info to create the pecoff file. This routine basically counts
554 * and adds up the sizes of the elements that will be in the pecoff output file.
561 uint32_t i
, j
, reloc_addr
, debug_addr
;
562 struct load_command
*lc
;
563 struct segment_command
*sg
;
564 struct thread_command
*ut
;
566 uint32_t flavor
, count
;
567 char *object_addr
, *section_name
;
568 #ifdef HACK_TO_MATCH_TEST_CASE
574 * Determine the number of sections in the pecoff output file.
576 #ifdef HACK_TO_MATCH_TEST_CASE
578 * The hack implementation of this routine is done to match the
579 * current ld_efi(1) script that uses objcopy(1) to make the pecoff
580 * file. So for 32-bit file the contents of the Mach-O file gets
581 * placed into pecoff sections as follows:
583 * the entire __TEXT segment becomes the .text section
584 * the entire __DATA segment becomes the .data section
585 * the zero fill section (__DATA,__common) becomes .common
586 * the zero fill section (__DATA,__bss) becomes .bss
587 * the (__IMPORT,__pointers) section becomes .pointers
588 * the base relocation entries go into the .reloc section
592 * The whole Mach-O segments __TEXT, __DATA and __IMPORT are placed in
593 * the pecoff file from the Mach-O file. And then the .reloc section
594 * added for the base relocations.
600 lc
= arch
->object
->load_commands
;
601 for(i
= 0; i
< arch
->object
->mh
->ncmds
; i
++){
602 if(lc
->cmd
== LC_SEGMENT
){
603 sg
= (struct segment_command
*)lc
;
604 if(strcmp(sg
->segname
, SEG_LINKEDIT
) != 0 &&
605 sg
->vmaddr
+ sg
->vmsize
> reloc_addr
)
606 reloc_addr
= sg
->vmaddr
+ sg
->vmsize
;
607 if(strcmp(sg
->segname
, SEG_TEXT
) == 0)
609 else if(strcmp(sg
->segname
, SEG_DATA
) == 0){
611 #ifdef HACK_TO_MATCH_TEST_CASE
612 s
= (struct section
*)
613 ((char *)sg
+ sizeof(struct segment_command
));
614 for(j
= 0; j
< sg
->nsects
; j
++, s
++){
615 if(strcmp(s
->sectname
, SECT_COMMON
) == 0 ||
616 strcmp(s
->sectname
, SECT_BSS
) == 0){
619 else if(s
->size
!= 0 &&
620 strcmp(s
->sectname
, SECT_DATA
) != 0)
621 fatal("input file: %s contains Mach-O section "
622 "(%.16s,%.16s) unsupported for conversion "
623 "to a pecoff file", arch
->file_name
,
624 s
->segname
, s
->sectname
);
626 #endif /* HACK_TO_MATCH_TEST_CASE */
628 else if(strcmp(sg
->segname
, SEG_IMPORT
) == 0){
629 #ifndef HACK_TO_MATCH_TEST_CASE
632 s
= (struct section
*)
633 ((char *)sg
+ sizeof(struct segment_command
));
634 for(j
= 0; j
< sg
->nsects
; j
++, s
++){
635 if(strcmp(s
->sectname
, "__pointers") == 0){
636 section_names_size
+= strlen(".pointers") + 1;
639 else if(s
->size
!= 0)
640 fatal("input file: %s contains Mach-O section "
641 "(%.16s,%.16s) unsupported for conversion "
642 "to a pecoff file", arch
->file_name
,
643 s
->segname
, s
->sectname
);
646 #endif /* HACK_TO_MATCH_TEST_CASE */
648 else if((arch
->object
->mh
->flags
& MH_PIE
) != MH_PIE
||
649 strcmp(sg
->segname
, SEG_LINKEDIT
) != 0){
650 fatal("input file: %s contains Mach-O segment %.16s "
651 "unsupported for conversion to a pecoff file",
652 arch
->file_name
, sg
->segname
);
656 * Also while processing the Mach-O file pick up the entry point.
658 else if(lc
->cmd
== LC_UNIXTHREAD
){
659 ut
= (struct thread_command
*)lc
;
660 state
= (char *)ut
+ sizeof(struct thread_command
);
661 p
= (char *)ut
+ ut
->cmdsize
;
663 flavor
= *((uint32_t *)state
);
664 state
+= sizeof(uint32_t);
665 count
= *((uint32_t *)state
);
666 state
+= sizeof(uint32_t);
667 switch(arch
->object
->mh_cputype
){
670 i386_thread_state_t
*cpu
;
671 case i386_THREAD_STATE
:
672 #if i386_THREAD_STATE == 1
674 #endif /* i386_THREAD_STATE == 1 */
675 /* i386 thread states on older releases */
676 #if i386_THREAD_STATE == -1
678 #endif /* i386_THREAD_STATE == -1 */
679 cpu
= (i386_thread_state_t
*)state
;
681 state
+= sizeof(i386_thread_state_t
);
684 state
+= count
* sizeof(uint32_t);
690 arm_thread_state_t
*cpu
;
691 case ARM_THREAD_STATE
:
692 cpu
= (arm_thread_state_t
*)state
;
694 state
+= sizeof(arm_thread_state_t
);
697 state
+= count
* sizeof(uint32_t);
706 lc
= (struct load_command
*)((char *)lc
+ lc
->cmdsize
);
709 /* add one for the .reloc section to contain the base relocations */
714 * If there is a -d flag add one for the .debug section to contain
717 if(debug_filename
!= NULL
)
721 * At the beginning of the COFF string table are 4 bytes that contain
722 * the total size (in bytes) of the rest of the string table. This size
723 * includes the size field itself, so that the value in this location
724 * would be 4 if no strings were present.
726 strsize
= sizeof(uint32_t);
729 * Section names longer than 8 bytes are placed in the string table.
730 * So here we allocate memory to put them into, which later will be
731 * copied to the start of the string table.
733 section_names
= allocate(section_names_size
);
734 section_name
= section_names
;
735 if(section_names_size
!= 0)
736 *section_name
= '\0';
739 * Allocate space for the section headers and fill in everything but
740 * their file offsets.
742 #ifndef HACK_TO_MATCH_TEST_CASE
744 * We use the SizeOfRawData field (s_size) as the unrounded value of
745 * the size of the initialized section contents coming from the
746 * segment's filesize. The VirtualSize field s_vsize may be bigger
747 * with the remaining space zero filled coming from the segment's
751 * Note to match what objcopy(1) does the s_vsize is an unrounded value
752 * of the size (more like the actual size) and the s_size is a value
753 * rounded to the file_alignment. So the s_vsize can be smaller than
754 * the s_size, as in the case of pecoff sections created from Mach-O
755 * sections (and not segments). This seems to volate the spec where
756 * s_vsize can be bigger than s_size with the remaining space zero
757 * filled but does NOT allow the s_vsize to be smaller than the s_size.
760 scnhdrs
= allocate(nscns
* sizeof(struct scnhdr
));
761 memset(scnhdrs
, '\0', nscns
* sizeof(struct scnhdr
));
762 scn_contents
= allocate(nscns
* sizeof(char *));
763 object_addr
= arch
->object
->object_addr
;
765 lc
= arch
->object
->load_commands
;
766 for(i
= 0; i
< arch
->object
->mh
->ncmds
; i
++){
767 if(lc
->cmd
== LC_SEGMENT
){
768 sg
= (struct segment_command
*)lc
;
769 if(strcmp(sg
->segname
, SEG_TEXT
) == 0){
770 strcpy(scnhdrs
[j
].s_name
, ".text");
771 #ifdef HACK_TO_MATCH_TEST_CASE
772 scnhdrs
[j
].s_vsize
= sg
->filesize
;
774 scnhdrs
[j
].s_vsize
= sg
->vmsize
;
776 scnhdrs
[j
].s_vaddr
= sg
->vmaddr
;
777 scnhdrs
[j
].s_size
= rnd(sg
->filesize
, file_alignment
);
778 scnhdrs
[j
].s_relptr
= 0;
779 scnhdrs
[j
].s_lnnoptr
= 0;
780 scnhdrs
[j
].s_nlnno
= 0;
781 scnhdrs
[j
].s_flags
= IMAGE_SCN_MEM_EXECUTE
|
784 scn_contents
[j
] = object_addr
+ sg
->fileoff
;
787 else if(strcmp(sg
->segname
, SEG_DATA
) == 0){
788 strcpy(scnhdrs
[j
].s_name
, ".data");
789 #ifdef HACK_TO_MATCH_TEST_CASE
790 scnhdrs
[j
].s_vsize
= sg
->filesize
;
792 scnhdrs
[j
].s_vsize
= sg
->vmsize
;
794 scnhdrs
[j
].s_vaddr
= sg
->vmaddr
;
795 scnhdrs
[j
].s_size
= rnd(sg
->filesize
, file_alignment
);
796 scnhdrs
[j
].s_relptr
= 0;
797 scnhdrs
[j
].s_lnnoptr
= 0;
798 scnhdrs
[j
].s_nlnno
= 0;
799 scnhdrs
[j
].s_flags
= IMAGE_SCN_MEM_READ
|
800 IMAGE_SCN_MEM_WRITE
|
802 IMAGE_SCN_CNT_INITIALIZED_DATA
|
803 IMAGE_SCN_MEM_EXECUTE
;
804 scn_contents
[j
] = object_addr
+ sg
->fileoff
;
806 #ifdef HACK_TO_MATCH_TEST_CASE
807 s
= (struct section
*)
808 ((char *)sg
+ sizeof(struct segment_command
));
809 for(i
= 0; i
< sg
->nsects
; i
++, s
++){
812 scnhdrs
[j
].s_vsize
= s
->size
;
813 scnhdrs
[j
].s_vaddr
= s
->addr
;
814 scnhdrs
[j
].s_size
= 0;
815 scnhdrs
[j
].s_relptr
= 0;
816 scnhdrs
[j
].s_lnnoptr
= 0;
817 scnhdrs
[j
].s_nlnno
= 0;
818 scnhdrs
[j
].s_flags
= IMAGE_SCN_MEM_READ
|
819 IMAGE_SCN_MEM_WRITE
|
820 IMAGE_SCN_CNT_UNINITIALIZED_DATA
;
821 if(strcmp(s
->sectname
, SECT_DATA
) == 0){
824 else if(strcmp(s
->sectname
, SECT_COMMON
) == 0){
825 strcpy(scnhdrs
[j
].s_name
, ".common");
826 common_scnum
= j
+ 1;
828 else if(strcmp(s
->sectname
, SECT_BSS
) == 0){
829 strcpy(scnhdrs
[j
].s_name
, ".bss");
832 scn_contents
[j
] = NULL
;
835 #endif /* HACK_TO_MATCH_TEST_CASE */
837 else if(strcmp(sg
->segname
, SEG_IMPORT
) == 0){
838 #ifndef HACK_TO_MATCH_TEST_CASE
839 strcpy(scnhdrs
[j
].s_name
, ".import");
840 scnhdrs
[j
].s_vsize
= sg
->vmsize
;
841 scnhdrs
[j
].s_vaddr
= sg
->vmaddr
;
842 scnhdrs
[j
].s_size
= rnd(sg
->filesize
, file_alignment
);
843 scnhdrs
[j
].s_relptr
= 0;
844 scnhdrs
[j
].s_lnnoptr
= 0;
845 scnhdrs
[j
].s_nlnno
= 0;
846 scnhdrs
[j
].s_flags
= IMAGE_SCN_MEM_READ
|
847 IMAGE_SCN_MEM_WRITE
|
848 IMAGE_SCN_CNT_INITIALIZED_DATA
;
849 scn_contents
[j
] = object_addr
+ sg
->fileoff
;
851 #else /* defined(HACK_TO_MATCH_TEST_CASE) */
852 s
= (struct section
*)
853 ((char *)sg
+ sizeof(struct segment_command
));
854 for(i
= 0; i
< sg
->nsects
; i
++, s
++){
857 scnhdrs
[j
].s_vsize
= s
->size
;
858 scnhdrs
[j
].s_vaddr
= s
->addr
;
859 scnhdrs
[j
].s_size
= rnd(s
->size
, file_alignment
);
860 scnhdrs
[j
].s_relptr
= 0;
861 scnhdrs
[j
].s_lnnoptr
= 0;
862 scnhdrs
[j
].s_nlnno
= 0;
863 scnhdrs
[j
].s_flags
= IMAGE_SCN_MEM_READ
|
864 IMAGE_SCN_MEM_WRITE
|
865 IMAGE_SCN_CNT_INITIALIZED_DATA
;
866 if(strcmp(s
->sectname
, "__pointers") == 0){
867 sprintf(scnhdrs
[j
].s_name
, "/%d", strsize
);
868 strcat(section_name
, ".pointers");
869 len
= strlen(section_name
) + 1;
872 scn_contents
[j
] = object_addr
+ s
->offset
;
875 #endif /* HACK_TO_MATCH_TEST_CASE */
878 lc
= (struct load_command
*)((char *)lc
+ lc
->cmdsize
);
881 strcpy(scnhdrs
[j
].s_name
, ".reloc");
882 scnhdrs
[j
].s_vsize
= reloc_size
;
883 reloc_addr
= rnd(reloc_addr
, section_alignment
);
884 scnhdrs
[j
].s_vaddr
= reloc_addr
;
885 scnhdrs
[j
].s_size
= rnd(reloc_size
, file_alignment
);
886 scnhdrs
[j
].s_relptr
= 0;
887 scnhdrs
[j
].s_lnnoptr
= 0;
888 scnhdrs
[j
].s_nlnno
= 0;
889 scnhdrs
[j
].s_flags
= IMAGE_SCN_MEM_READ
|
890 IMAGE_SCN_CNT_INITIALIZED_DATA
|
891 IMAGE_SCN_MEM_DISCARDABLE
;
892 reloc_scnhdr
= scnhdrs
+ j
;
893 scn_contents
[j
] = reloc_contents
;
895 debug_addr
= reloc_addr
+ reloc_scnhdr
->s_size
;
898 debug_addr
= rnd(reloc_addr
, section_alignment
);
901 if(debug_filename
!= NULL
){
902 strcpy(scnhdrs
[j
].s_name
, ".debug");
903 scnhdrs
[j
].s_vsize
= debug_size
;
904 scnhdrs
[j
].s_vaddr
= debug_addr
;
905 scnhdrs
[j
].s_size
= rnd(debug_size
, file_alignment
);
906 scnhdrs
[j
].s_relptr
= 0;
907 scnhdrs
[j
].s_lnnoptr
= 0;
908 scnhdrs
[j
].s_nlnno
= 0;
909 scnhdrs
[j
].s_flags
= IMAGE_SCN_MEM_READ
|
910 IMAGE_SCN_CNT_INITIALIZED_DATA
|
911 IMAGE_SCN_MEM_DISCARDABLE
;
912 debug_scnhdr
= scnhdrs
+ j
;
913 scn_contents
[j
] = debug_contents
;
918 * Create the pecoff symbol and string table from this Mach-O file.
920 create_32bit_symbol_table(arch
);
924 * process_64bit_arch() is the routine that processes a 64-bit broken out ofile
925 * to gather the info to create the pecoff file. This routine basically counts
926 * and adds up the sizes of the elements that will be in the pecoff output file.
934 uint64_t reloc_addr
, debug_addr
;
935 struct load_command
*lc
;
936 struct segment_command_64
*sg64
;
937 struct thread_command
*ut
;
939 uint32_t flavor
, count
;
940 char *object_addr
, *section_name
;
941 #ifdef HACK_TO_MATCH_TEST_CASE
942 struct section_64
*s64
;
947 * Determine the number of sections in the pecoff output file.
949 #ifdef HACK_TO_MATCH_TEST_CASE
951 * The hack implementation of this routine is done to match the
952 * current ld_efi(1) script that uses objcopy(1) to make the pecoff
953 * file. So for 64-bit files the contents of the Mach-O sections get
954 * placed into pecoff sections with a section name made up of the
955 * strings "LC_SEGMENT" the segment and section names separated with
956 * a dot, '.', character. So the Mach-O (__TEXT,__text) section becomes
957 * a pecoff section with the name "LC_SEGMENT.__TEXT.__text". The base
958 * relocation entries go into a ".reloc" section.
962 * The whole Mach-O __TEXT and __DATA segments are placed in the
963 * pecoff file from the Mach-O file. And then the .reloc section added
964 * for the base relocations.
970 lc
= arch
->object
->load_commands
;
971 for(i
= 0; i
< arch
->object
->mh64
->ncmds
; i
++){
972 if(lc
->cmd
== LC_SEGMENT_64
){
973 sg64
= (struct segment_command_64
*)lc
;
974 #ifndef HACK_TO_MATCH_TEST_CASE
975 if(strcmp(sg64
->segname
, SEG_LINKEDIT
) != 0 &&
976 sg64
->vmaddr
+ sg64
->vmsize
> reloc_addr
)
977 reloc_addr
= sg64
->vmaddr
+ sg64
->vmsize
;
978 if(strcmp(sg64
->segname
, SEG_TEXT
) == 0)
980 else if(strcmp(sg64
->segname
, SEG_DATA
) == 0)
982 else if(strcmp(sg64
->segname
, SEG_LINKEDIT
) != 0){
983 fatal("input file: %s contains Mach-O segment %.16s "
984 "unsupported for conversion to a pecoff file",
985 arch
->file_name
, sg64
->segname
);
987 #else /* defined(HACK_TO_MATCH_TEST_CASE) */
988 s64
= (struct section_64
*)
989 ((char *)sg64
+ sizeof(struct segment_command_64
));
990 for(i
= 0; i
< sg64
->nsects
; i
++, s64
++){
991 if(s64
->addr
+ s64
->size
> reloc_addr
)
992 reloc_addr
= s64
->addr
+ s64
->size
;
993 section_names_size
+= strlen("LC_SEGMENT.") +
994 strlen(s64
->segname
) + 1 +
995 strlen(s64
->sectname
) + 1;
998 #endif /* HACK_TO_MATCH_TEST_CASE */
1001 * Also while process the Mach-O file pick up the entry point.
1003 else if(lc
->cmd
== LC_UNIXTHREAD
){
1004 ut
= (struct thread_command
*)lc
;
1005 state
= (char *)ut
+ sizeof(struct thread_command
);
1006 p
= (char *)ut
+ ut
->cmdsize
;
1008 flavor
= *((uint32_t *)state
);
1009 state
+= sizeof(uint32_t);
1010 count
= *((uint32_t *)state
);
1011 state
+= sizeof(uint32_t);
1012 switch(arch
->object
->mh_cputype
){
1013 #ifdef x86_THREAD_STATE64
1014 case CPU_TYPE_X86_64
:
1016 x86_thread_state64_t
*cpu64
;
1017 case x86_THREAD_STATE64
:
1018 cpu64
= (x86_thread_state64_t
*)state
;
1020 state
+= sizeof(x86_thread_state64_t
);
1023 state
+= count
* sizeof(uint32_t);
1027 #endif /* x86_THREAD_STATE64 */
1031 lc
= (struct load_command
*)((char *)lc
+ lc
->cmdsize
);
1033 if(reloc_size
!= 0){
1034 /* add one for the .reloc section to contain the base relocations */
1039 * If there is a -d flag add one for the .debug section to contain
1042 if(debug_filename
!= NULL
)
1046 * At the beginning of the COFF string table are 4 bytes that contain
1047 * the total size (in bytes) of the rest of the string table. This size
1048 * includes the size field itself, so that the value in this location
1049 * would be 4 if no strings were present.
1051 strsize
= sizeof(uint32_t);
1054 * Section names longer than 8 bytes are placed in the string table.
1055 * So here we allocate memory to put them into, which later will be
1056 * copied to the start of the string table.
1058 section_names
= allocate(section_names_size
) + 1;
1059 section_name
= section_names
;
1060 if(section_names_size
!= 0)
1061 *section_name
= '\0';
1064 * Allocate space for the section headers and fill in everything but
1065 * their file offsets.
1067 #ifndef HACK_TO_MATCH_TEST_CASE
1069 * We use the SizeOfRawData field (s_size) as the unrounded value of
1070 * the size of the initialized section contents coming from the
1071 * segment's filesize. The VirtualSize field s_vsize may be bigger
1072 * with the remaining space zero filled coming from the segment's
1076 * Note to match what objcopy(1) does the s_vsize is an unrounded value
1077 * of the size (more like the actual size) and the s_size is a value
1078 * rounded to the file_alignment. So the s_vsize can be smaller than
1079 * the s_size, as in the case of pecoff sections created from Mach-O
1080 * sections (and not segments). This seems to volate the spec where
1081 * s_vsize can be bigger than s_size with the remaining space zero
1082 * filled but does NOT allow the s_vsize to be smaller than the s_size.
1085 scnhdrs
= allocate(nscns
* sizeof(struct scnhdr
));
1086 memset(scnhdrs
, '\0', nscns
* sizeof(struct scnhdr
));
1087 scn_contents
= allocate(nscns
* sizeof(char *));
1088 object_addr
= arch
->object
->object_addr
;
1090 lc
= arch
->object
->load_commands
;
1091 for(i
= 0; i
< arch
->object
->mh64
->ncmds
; i
++){
1092 if(lc
->cmd
== LC_SEGMENT_64
){
1093 sg64
= (struct segment_command_64
*)lc
;
1094 #ifndef HACK_TO_MATCH_TEST_CASE
1095 if(strcmp(sg64
->segname
, SEG_TEXT
) == 0){
1096 strcpy(scnhdrs
[j
].s_name
, ".text");
1097 scnhdrs
[j
].s_vsize
= sg64
->vmsize
;
1098 scnhdrs
[j
].s_vaddr
= sg64
->vmaddr
;
1099 scnhdrs
[j
].s_size
= rnd(sg64
->filesize
, file_alignment
);
1100 scnhdrs
[j
].s_relptr
= 0;
1101 scnhdrs
[j
].s_lnnoptr
= 0;
1102 scnhdrs
[j
].s_nlnno
= 0;
1103 scnhdrs
[j
].s_flags
= IMAGE_SCN_MEM_EXECUTE
|
1104 IMAGE_SCN_MEM_READ
|
1106 scn_contents
[j
] = object_addr
+ sg64
->fileoff
;
1109 else if(strcmp(sg64
->segname
, SEG_DATA
) == 0){
1110 strcpy(scnhdrs
[j
].s_name
, ".data");
1111 scnhdrs
[j
].s_vsize
= sg64
->vmsize
;
1112 scnhdrs
[j
].s_vaddr
= sg64
->vmaddr
;
1113 scnhdrs
[j
].s_size
= rnd(sg64
->filesize
, file_alignment
);
1114 scnhdrs
[j
].s_relptr
= 0;
1115 scnhdrs
[j
].s_lnnoptr
= 0;
1116 scnhdrs
[j
].s_nlnno
= 0;
1117 scnhdrs
[j
].s_flags
= IMAGE_SCN_MEM_READ
|
1118 IMAGE_SCN_MEM_WRITE
|
1119 IMAGE_SCN_CNT_CODE
|
1120 IMAGE_SCN_CNT_INITIALIZED_DATA
|
1121 IMAGE_SCN_MEM_EXECUTE
;
1122 scn_contents
[j
] = object_addr
+ sg64
->fileoff
;
1125 #else /* defined(HACK_TO_MATCH_TEST_CASE) */
1126 s64
= (struct section_64
*)
1127 ((char *)sg64
+ sizeof(struct segment_command_64
));
1128 for(i
= 0; i
< sg64
->nsects
; i
++, s64
++){
1129 sprintf(scnhdrs
[j
].s_name
, "/%d", strsize
);
1130 strcat(section_name
, "LC_SEGMENT.");
1131 strcat(section_name
, s64
->segname
);
1132 strcat(section_name
, ".");
1133 strcat(section_name
, s64
->sectname
);
1134 len
= strlen(section_name
);
1136 section_name
+= len
+ 1;
1137 *section_name
= '\0'; /* start of next section name */
1139 /* NOTE zerofill sections are not handled */
1140 scnhdrs
[j
].s_vsize
= s64
->size
;
1141 scnhdrs
[j
].s_vaddr
= s64
->addr
;
1142 scnhdrs
[j
].s_size
= rnd(s64
->size
, file_alignment
);
1143 scnhdrs
[j
].s_relptr
= 0;
1144 scnhdrs
[j
].s_lnnoptr
= 0;
1145 scnhdrs
[j
].s_nlnno
= 0;
1146 scnhdrs
[j
].s_flags
= IMAGE_SCN_MEM_EXECUTE
|
1147 IMAGE_SCN_CNT_CODE
|
1148 IMAGE_SCN_MEM_WRITE
;
1149 if(sg64
->initprot
& VM_PROT_READ
)
1150 scnhdrs
[j
].s_flags
|= IMAGE_SCN_MEM_READ
;
1151 scn_contents
[j
] = object_addr
+ s64
->offset
;
1154 #endif /* HACK_TO_MATCH_TEST_CASE */
1156 lc
= (struct load_command
*)((char *)lc
+ lc
->cmdsize
);
1158 if(reloc_size
!= 0){
1159 strcpy(scnhdrs
[j
].s_name
, ".reloc");
1160 scnhdrs
[j
].s_vsize
= reloc_size
;
1161 reloc_addr
= rnd(reloc_addr
, section_alignment
);
1162 scnhdrs
[j
].s_vaddr
= reloc_addr
;
1163 scnhdrs
[j
].s_size
= rnd(reloc_size
, file_alignment
);
1164 scnhdrs
[j
].s_relptr
= 0;
1165 scnhdrs
[j
].s_lnnoptr
= 0;
1166 scnhdrs
[j
].s_nlnno
= 0;
1167 scnhdrs
[j
].s_flags
= IMAGE_SCN_MEM_READ
|
1168 IMAGE_SCN_CNT_INITIALIZED_DATA
|
1169 IMAGE_SCN_MEM_DISCARDABLE
|
1170 IMAGE_SCN_CNT_CODE
|
1171 IMAGE_SCN_MEM_EXECUTE
;
1172 reloc_scnhdr
= scnhdrs
+ j
;
1173 scn_contents
[j
] = reloc_contents
;
1175 debug_addr
= reloc_addr
+ reloc_scnhdr
->s_size
;
1178 debug_addr
= rnd(reloc_addr
, section_alignment
);
1181 if(debug_filename
!= NULL
){
1182 strcpy(scnhdrs
[j
].s_name
, ".debug");
1183 scnhdrs
[j
].s_vsize
= debug_size
;
1184 scnhdrs
[j
].s_vaddr
= debug_addr
;
1185 scnhdrs
[j
].s_size
= rnd(debug_size
, file_alignment
);
1186 scnhdrs
[j
].s_relptr
= 0;
1187 scnhdrs
[j
].s_lnnoptr
= 0;
1188 scnhdrs
[j
].s_nlnno
= 0;
1189 scnhdrs
[j
].s_flags
= IMAGE_SCN_MEM_READ
|
1190 IMAGE_SCN_CNT_INITIALIZED_DATA
|
1191 IMAGE_SCN_MEM_DISCARDABLE
|
1192 IMAGE_SCN_CNT_CODE
|
1193 IMAGE_SCN_MEM_EXECUTE
;
1194 debug_scnhdr
= scnhdrs
+ j
;
1195 scn_contents
[j
] = debug_contents
;
1200 * Create the pecoff symbol and string table from this Mach-O file.
1202 create_64bit_symbol_table(arch
);
1206 * layout_output() takes the info gathered from the input Mach-O file and
1207 * layouts the pecoff output file and creates and fills in the elements of
1208 * the coff file. This routine basically sets of the offsets of the elements
1209 * of the output file from the previously determined sizes.
1214 struct ofile
*ofile
)
1216 uint32_t i
, header_size
, offset
, least_vaddr
;
1219 * Determine the size of the output file and where each element will be
1220 * in the output file.
1222 header_size
= sizeof(struct ms_dos_stub
) +
1224 sizeof(struct filehdr
) +
1225 nscns
* sizeof(struct scnhdr
);
1226 if(ofile
->mh
!= NULL
)
1227 header_size
+= sizeof(struct aouthdr
);
1229 header_size
+= sizeof(struct aouthdr_64
);
1230 header_size
= rnd(header_size
, file_alignment
);
1231 #ifdef HACK_TO_MATCH_TEST_CASE
1232 /* for some unknown reason the header size is 0x488 not 0x400 */
1233 if(ofile
->mh64
!= NULL
)
1234 header_size
+= 0x88;
1237 * If the lowest section virtual address is greater than the header
1238 * size, pad the header up to the virtual address. This modification
1239 * will make the file offset and virtual address equal, and fixes
1240 * problems with XIP rebasing in the EFI tools.
1242 least_vaddr
= 0xffffffff;
1243 for(i
= 0; i
< nscns
; i
++){
1244 if(scnhdrs
[i
].s_vaddr
< least_vaddr
)
1245 least_vaddr
= scnhdrs
[i
].s_vaddr
;
1247 if(least_vaddr
> header_size
)
1248 header_size
= least_vaddr
;
1250 offset
= header_size
;
1251 for(i
= 0; i
< nscns
; i
++){
1252 if((scnhdrs
[i
].s_flags
& IMAGE_SCN_CNT_UNINITIALIZED_DATA
) == 0){
1254 * We need to check that the headers can be mapped starting at
1255 * the ImageBase, fixed at zero in this program, and fit before
1256 * the Virtual Address of the first section (really any section)
1257 * and if it doesn't then we need the Mach-O file relinked.
1259 if(scnhdrs
[i
].s_vaddr
< header_size
)
1260 fatal("input file: %s must be relinked so PECOFF headers "
1261 "can be mapped before its sections (use a -seg1addr "
1262 "0x%x or greater)", ofile
->file_name
, header_size
);
1264 * The s_scnptr is set to the offset and then the offset is
1265 * incremented by the SizeOfRawData field (s_vsize).
1267 scnhdrs
[i
].s_scnptr
= offset
;
1268 #ifndef HACK_TO_MATCH_TEST_CASE
1269 offset
+= scnhdrs
[i
].s_vsize
;
1271 /* for some unknown reason the offset after the __dyld section
1272 is changed from 0x10 bytes to 0x20 bytes */
1273 if(ofile
->mh64
!= NULL
&& scnhdrs
[i
].s_vsize
< 0x20)
1275 /* for some unknown reason the offset after the __data section
1276 is changed from 0x380 bytes to 0x3e0 bytes */
1277 else if(ofile
->mh64
!= NULL
&& scnhdrs
[i
].s_vsize
== 0x380)
1278 offset
+= scnhdrs
[i
].s_vsize
+ 0x60;
1281 * Note to match what objcopy(1) does the offset is
1282 * incremented by the VirtualSize field (s_vsize) not the
1283 * SizeOfRawData field (s_size) field as that is what was
1284 * previously set up.
1286 offset
+= scnhdrs
[i
].s_vsize
;
1288 #ifdef HACK_TO_MATCH_TEST_CASE
1289 if(ofile
->mh
!= NULL
)
1291 offset
= rnd(offset
, file_alignment
);
1292 #ifdef HACK_TO_MATCH_TEST_CASE
1294 /* for some unknown reason the next offset is moved up
1295 0x200 then rounded to 8 bytes */
1297 offset
= rnd(offset
, 8);
1302 #ifdef HACK_TO_MATCH_TEST_CASE
1303 /* for some unknown reason the offset of the symbol is moved back 0x58
1305 if(ofile
->mh64
!= NULL
)
1308 syment_offset
= offset
;
1309 offset
+= nsyments
* sizeof(struct syment
);
1310 string_offset
= offset
;
1313 output_size
= offset
;
1316 * Now with all the sizes and placement of things know fill in headers
1317 * of the pecoff file for this Mach-O file.
1320 /* first in the pecoff file is the MS-DOS stub */
1321 create_ms_dos_stub(&ms_dos_stub
);
1324 * Second in the pecoff file is the PE format image file signature.
1325 * This signature is PE\0\0 (the letters P and E followed by two null
1330 signature
[2] = '\0';
1331 signature
[3] = '\0';
1333 /* next is the filehdr */
1334 if(ofile
->mh
!= NULL
){
1335 if(ofile
->mh
->cputype
== CPU_TYPE_I386
)
1336 filehdr
.f_magic
= IMAGE_FILE_MACHINE_I386
;
1338 filehdr
.f_magic
= IMAGE_FILE_MACHINE_ARM
;
1341 if(ofile
->mh64
->cputype
== CPU_TYPE_X86_64
)
1342 filehdr
.f_magic
= IMAGE_FILE_MACHINE_AMD64
;
1344 filehdr
.f_nscns
= nscns
;
1345 #ifdef HACK_TO_MATCH_TEST_CASE
1346 if(ofile
->mh
!= NULL
){
1347 filehdr
.f_timdat
= 0x46cb5980;
1350 filehdr
.f_timdat
= 0x47671e62;
1352 filehdr
.f_timdat
= time(NULL
);
1354 filehdr
.f_symptr
= syment_offset
;
1355 filehdr
.f_nsyms
= nsyments
;
1356 if(ofile
->mh
!= NULL
)
1357 filehdr
.f_opthdr
= sizeof(struct aouthdr
);
1359 filehdr
.f_opthdr
= sizeof(struct aouthdr_64
);
1360 filehdr
.f_flags
= IMAGE_FILE_EXECUTABLE_IMAGE
|
1361 IMAGE_FILE_LINE_NUMS_STRIPPED
|
1362 IMAGE_FILE_32BIT_MACHINE
|
1363 IMAGE_FILE_DEBUG_STRIPPED
;
1364 if(ofile
->mh64
!= NULL
)
1365 filehdr
.f_flags
|= IMAGE_FILE_LOCAL_SYMS_STRIPPED
;
1367 /* next is the aouthdr */
1368 if(ofile
->mh
!= NULL
){
1369 aouthdr
.magic
= PE32MAGIC
;
1370 aouthdr
.vstamp
= VSTAMP
;
1373 * EFI does not use t, d, or b size.
1374 * EFI uses SizeOfImage to errorcheck vaddrs in the image
1379 aouthdr
.SizeOfImage
= rnd(header_size
, section_alignment
);
1380 for(i
= 0; i
< nscns
; i
++){
1381 aouthdr
.SizeOfImage
+= rnd(scnhdrs
[i
].s_vsize
, section_alignment
);
1384 aouthdr
.entry
= entry
;
1386 aouthdr
.text_start
= 0;
1387 aouthdr
.data_start
= 0;
1388 for(i
= 0; i
< nscns
; i
++){
1389 if((scnhdrs
[i
].s_flags
& IMAGE_SCN_CNT_UNINITIALIZED_DATA
) ==0){
1390 if((scnhdrs
[i
].s_flags
& IMAGE_SCN_MEM_WRITE
) == 0){
1391 if(aouthdr
.text_start
== 0)
1392 aouthdr
.text_start
= scnhdrs
[i
].s_vaddr
;
1395 if(aouthdr
.data_start
== 0)
1396 aouthdr
.data_start
= scnhdrs
[i
].s_vaddr
;
1401 aouthdr
.ImageBase
= 0;
1402 aouthdr
.SectionAlignment
= section_alignment
;
1403 aouthdr
.FileAlignment
= file_alignment
;
1404 aouthdr
.MajorOperatingSystemVersion
= 0;
1405 aouthdr
.MinorOperatingSystemVersion
= 0;
1406 aouthdr
.MajorImageVersion
= 0;
1407 aouthdr
.MinorImageVersion
= 0;
1408 aouthdr
.MajorSubsystemVersion
= 0;
1409 aouthdr
.MinorSubsystemVersion
= 0;
1410 aouthdr
.Win32VersionValue
= 0;
1413 aouthdr
.SizeOfHeaders
= header_size
;
1414 aouthdr
.CheckSum
= 0;
1415 aouthdr
.Subsystem
= Subsystem
;
1416 aouthdr
.DllCharacteristics
= 0;
1417 aouthdr
.SizeOfStackReserve
= 0;
1418 aouthdr
.SizeOfStackCommit
= 0;
1419 aouthdr
.SizeOfHeapReserve
= 0;
1420 aouthdr
.SizeOfHeapCommit
= 0;
1421 aouthdr
.LoaderFlags
= 0;
1422 aouthdr
.NumberOfRvaAndSizes
= 16;
1423 /* Entry 5, Base Relocation Directory [.reloc] address & size */
1424 if(reloc_size
!= 0){
1425 aouthdr
.DataDirectory
[5][0] = reloc_scnhdr
->s_vaddr
;
1426 aouthdr
.DataDirectory
[5][1] = reloc_scnhdr
->s_vsize
;
1428 /* Entry 6, Debug Directory [.debug] address & size */
1429 if(debug_filename
!= NULL
){
1430 aouthdr
.DataDirectory
[6][0] = debug_scnhdr
->s_vaddr
;
1431 aouthdr
.DataDirectory
[6][1] = debug_scnhdr
->s_vsize
;
1435 aouthdr64
.magic
= PE32PMAGIC
;
1436 aouthdr64
.vstamp
= VSTAMP
;
1439 * EFI does not use t, d, or b size.
1440 * EFI uses SizeOfImage to errorcheck vaddrs in the image
1442 aouthdr64
.tsize
= 0;
1443 aouthdr64
.dsize
= 0;
1444 aouthdr64
.bsize
= 0;
1446 aouthdr64
.SizeOfImage
= rnd(header_size
, section_alignment
);
1447 for(i
= 0; i
< nscns
; i
++){
1448 aouthdr64
.SizeOfImage
+= rnd(scnhdrs
[i
].s_vsize
, section_alignment
);
1450 #ifdef HACK_TO_MATCH_TEST_CASE
1451 /* with the IMAGE_SCN_CNT_CODE flag set on all sections this is
1452 just a quick hack to match the PECOFF file */
1453 aouthdr64
.dsize
= 0x200;
1456 aouthdr64
.entry
= entry
;
1457 #ifdef HACK_TO_MATCH_TEST_CASE
1458 aouthdr64
.entry
= 0x4a2;
1460 aouthdr64
.text_start
= 0;
1461 for(i
= 0; i
< nscns
; i
++){
1462 if((scnhdrs
[i
].s_flags
& IMAGE_SCN_CNT_UNINITIALIZED_DATA
) ==0){
1463 if((scnhdrs
[i
].s_flags
& IMAGE_SCN_MEM_WRITE
) == 0){
1464 if(aouthdr64
.text_start
== 0)
1465 aouthdr64
.text_start
= scnhdrs
[i
].s_vaddr
;
1469 #ifdef HACK_TO_MATCH_TEST_CASE
1470 /* this is a hack as the start of the text for 64-bit Mach-O files
1471 built with -dylib does not have the text section starting at 0 */
1472 aouthdr64
.text_start
= 0;
1475 aouthdr64
.ImageBase
= 0;
1476 aouthdr64
.SectionAlignment
= section_alignment
;
1477 aouthdr64
.FileAlignment
= file_alignment
;
1478 aouthdr64
.MajorOperatingSystemVersion
= 0;
1479 aouthdr64
.MinorOperatingSystemVersion
= 0;
1480 aouthdr64
.MajorImageVersion
= 0;
1481 aouthdr64
.MinorImageVersion
= 0;
1482 aouthdr64
.MajorSubsystemVersion
= 0;
1483 aouthdr64
.MinorSubsystemVersion
= 0;
1484 aouthdr64
.Win32VersionValue
= 0;
1487 #ifdef HACK_TO_MATCH_TEST_CASE
1488 /* this is a hack as it seams that the minimum size is 0x10000 */
1489 if(aouthdr64
.SizeOfImage
< 0x10000)
1490 aouthdr64
.SizeOfImage
= 0x10000;
1492 aouthdr64
.SizeOfHeaders
= header_size
;
1493 aouthdr64
.CheckSum
= 0;
1494 aouthdr64
.Subsystem
= Subsystem
;
1495 #ifdef HACK_TO_MATCH_TEST_CASE
1496 aouthdr64
.Subsystem
= IMAGE_SUBSYSTEM_EFI_BOOT_SERVICE_DRIVER
;
1498 aouthdr64
.DllCharacteristics
= 0;
1499 aouthdr64
.SizeOfStackReserve
= 0;
1500 aouthdr64
.SizeOfStackCommit
= 0;
1501 aouthdr64
.SizeOfHeapReserve
= 0;
1502 aouthdr64
.SizeOfHeapCommit
= 0;
1503 aouthdr64
.LoaderFlags
= 0;
1504 aouthdr64
.NumberOfRvaAndSizes
= 16;
1505 /* Entry 5, Base Relocation Directory [.reloc] address & size */
1506 if(reloc_size
!= 0){
1507 aouthdr64
.DataDirectory
[5][0] = reloc_scnhdr
->s_vaddr
;
1508 aouthdr64
.DataDirectory
[5][1] = reloc_scnhdr
->s_vsize
;
1510 /* Entry 6, Debug Directory [.debug] address & size */
1511 if(debug_filename
!= NULL
){
1512 aouthdr64
.DataDirectory
[6][0] = debug_scnhdr
->s_vaddr
;
1513 aouthdr64
.DataDirectory
[6][1] = debug_scnhdr
->s_vsize
;
1518 * If there is a debug directory entry set the address and offsets in
1519 * it now that the values are known.
1521 if(debug_filename
!= NULL
)
1522 set_debug_addrs_and_offsets();
1526 * create_output() takes the info gathered from the input Mach-O file and
1527 * creates the pecoff output file.
1532 struct ofile
*ofile
,
1536 unsigned char *buf
, *p
, *p_aouthdr
;
1539 * Allocate the buffer to place the pecoff file in.
1541 buf
= calloc(1, output_size
);
1543 fatal("Can't allocate buffer for output file (size = %u)",
1547 * Copy the parts of the pecoff file into the buffer.
1551 memcpy(p
, &ms_dos_stub
, sizeof(struct ms_dos_stub
));
1553 swap_ms_dos_stub((struct ms_dos_stub
*)p
, target_byte_sex
);
1554 p
+= sizeof(struct ms_dos_stub
);
1556 memcpy(p
, signature
, sizeof(signature
));
1557 p
+= sizeof(signature
);
1559 memcpy(p
, &filehdr
, sizeof(struct filehdr
));
1561 swap_filehdr((struct filehdr
*)p
, target_byte_sex
);
1562 p
+= sizeof(struct filehdr
);
1565 if(ofile
->mh
!= NULL
){
1566 memcpy(p
, &aouthdr
, sizeof(struct aouthdr
));
1568 swap_aouthdr((struct aouthdr
*)p
, target_byte_sex
);
1569 p
+= sizeof(struct aouthdr
);
1572 memcpy(p
, &aouthdr64
, sizeof(struct aouthdr_64
));
1574 swap_aouthdr_64((struct aouthdr_64
*)p
, target_byte_sex
);
1575 p
+= sizeof(struct aouthdr_64
);
1579 * Now copy in the section contents. Note the base relocations
1580 * (the contents of the .reloc section) has already been swapped if
1583 for(i
= 0; i
< nscns
; i
++){
1584 if((scnhdrs
[i
].s_flags
& IMAGE_SCN_CNT_UNINITIALIZED_DATA
) == 0){
1585 memcpy(buf
+ scnhdrs
[i
].s_scnptr
,
1587 #ifndef HACK_TO_MATCH_TEST_CASE
1590 scnhdrs
[i
].s_vsize
);
1593 #ifdef HACK_TO_MATCH_TEST_CASE
1594 /* this is a hack as this is zero in 64-bit file */
1595 if(ofile
->mh64
!= NULL
)
1596 scnhdrs
[i
].s_vsize
= 0;
1601 memcpy(p
, scnhdrs
, nscns
* sizeof(struct scnhdr
));
1603 swap_scnhdr((struct scnhdr
*)p
, nscns
, target_byte_sex
);
1604 p
+= nscns
* sizeof(struct scnhdr
);
1607 * Note the base relocations (the contents of the reloc section),
1608 * the symbol table and string table all have already been swapped if
1611 memcpy(buf
+ syment_offset
, syments
, nsyments
* sizeof(struct syment
));
1612 memcpy(buf
+ string_offset
, strings
, strsize
);
1615 * Now with the file contents complete compute the CheckSum in the
1616 * optional header and update that in the output buffer.
1618 if(ofile
->mh
!= NULL
){
1619 aouthdr
.CheckSum
= checksum(buf
) + output_size
;
1620 memcpy(p_aouthdr
, &aouthdr
, sizeof(struct aouthdr
));
1622 swap_aouthdr((struct aouthdr
*)p_aouthdr
, target_byte_sex
);
1625 aouthdr64
.CheckSum
= checksum(buf
) + output_size
;
1626 memcpy(p_aouthdr
, &aouthdr64
, sizeof(struct aouthdr_64
));
1628 swap_aouthdr_64((struct aouthdr_64
*)p_aouthdr
,target_byte_sex
);
1632 * Create the pecoff file and write the buffer to the file.
1634 f
= open(out
, O_WRONLY
|O_CREAT
|O_TRUNC
, 0644);
1636 system_fatal("Can't create output file: %s", out
);
1638 if(write(f
, buf
, output_size
) != output_size
)
1639 system_fatal("Can't write output file: %s", out
);
1642 system_fatal("Can't close output file: %s", out
);
1646 * create_ms_dos_stub() is pass a pointer to the buffer where to fill in the
1652 struct ms_dos_stub
*p
)
1656 p
->e_magic
= DOSMAGIC
;
1661 p
->e_minalloc
= 0x0;
1662 p
->e_maxalloc
= 0xffff;
1671 for(i
= 0; i
< 4; i
++)
1677 for(i
= 0; i
< 10; i
++)
1683 * The sub dos program that prints "This program cannot be run in DOS
1686 p
->dos_program
[0] = 0x0e;
1687 p
->dos_program
[1] = 0x1f;
1688 p
->dos_program
[2] = 0xba;
1689 p
->dos_program
[3] = 0x0e;
1690 p
->dos_program
[4] = 0x00;
1691 p
->dos_program
[5] = 0xb4;
1692 p
->dos_program
[6] = 0x09;
1693 p
->dos_program
[7] = 0xcd;
1694 p
->dos_program
[8] = 0x21;
1695 p
->dos_program
[9] = 0xb8;
1696 p
->dos_program
[10] = 0x01;
1697 p
->dos_program
[11] = 0x4c;
1698 p
->dos_program
[12] = 0xcd;
1699 p
->dos_program
[13] = 0x21;
1700 p
->dos_program
[14] = 0x54;
1701 p
->dos_program
[15] = 0x68;
1702 p
->dos_program
[16] = 0x69;
1703 p
->dos_program
[17] = 0x73;
1704 p
->dos_program
[18] = 0x20;
1705 p
->dos_program
[19] = 0x70;
1706 p
->dos_program
[20] = 0x72;
1707 p
->dos_program
[21] = 0x6f;
1708 p
->dos_program
[22] = 0x67;
1709 p
->dos_program
[23] = 0x72;
1710 p
->dos_program
[24] = 0x61;
1711 p
->dos_program
[25] = 0x6d;
1712 p
->dos_program
[26] = 0x20;
1713 p
->dos_program
[27] = 0x63;
1714 p
->dos_program
[28] = 0x61;
1715 p
->dos_program
[29] = 0x6e;
1716 p
->dos_program
[30] = 0x6e;
1717 p
->dos_program
[31] = 0x6f;
1718 p
->dos_program
[32] = 0x74;
1719 p
->dos_program
[33] = 0x20;
1720 p
->dos_program
[34] = 0x62;
1721 p
->dos_program
[35] = 0x65;
1722 p
->dos_program
[36] = 0x20;
1723 p
->dos_program
[37] = 0x72;
1724 p
->dos_program
[38] = 0x75;
1725 p
->dos_program
[39] = 0x6e;
1726 p
->dos_program
[40] = 0x20;
1727 p
->dos_program
[41] = 0x69;
1728 p
->dos_program
[42] = 0x6e;
1729 p
->dos_program
[43] = 0x20;
1730 p
->dos_program
[44] = 0x44;
1731 p
->dos_program
[45] = 0x4f;
1732 p
->dos_program
[46] = 0x53;
1733 p
->dos_program
[47] = 0x20;
1734 p
->dos_program
[48] = 0x6d;
1735 p
->dos_program
[49] = 0x6f;
1736 p
->dos_program
[50] = 0x64;
1737 p
->dos_program
[51] = 0x65;
1738 p
->dos_program
[52] = 0x2e;
1739 p
->dos_program
[53] = 0x0d;
1740 p
->dos_program
[54] = 0x0d;
1741 p
->dos_program
[55] = 0x0a;
1742 p
->dos_program
[56] = 0x24;
1743 p
->dos_program
[57] = 0x0;
1744 p
->dos_program
[58] = 0x0;
1745 p
->dos_program
[59] = 0x0;
1746 p
->dos_program
[60] = 0x0;
1747 p
->dos_program
[61] = 0x0;
1748 p
->dos_program
[62] = 0x0;
1749 p
->dos_program
[63] = 0x0;
1754 * create_32bit_symbol_table() is called to process the input Mach-O file and
1755 * create the pecoff symbol and string table.
1759 create_32bit_symbol_table(
1763 struct symtab_command
*st
;
1766 enum bool found_undef
;
1767 #ifdef HACK_TO_MATCH_TEST_CASE
1768 uint32_t j
, n_sect
, bss_n_sect
, common_n_sect
,
1769 bss_addr
, common_addr
, size
;
1770 struct load_command
*lc
;
1771 struct segment_command
*sg
;
1773 #endif /* HACK_TO_MATCH_TEST_CASE */
1778 * No symbols are actually needed in the pecoff file from the Mach-O
1779 * file so create an empty symbol table.
1784 * Make sure the Mach-O file does not have any undefined symbols.
1786 st
= arch
->object
->st
;
1787 object_addr
= arch
->object
->object_addr
;
1788 syms
= (struct nlist
*)(object_addr
+ st
->symoff
);
1789 strs
= object_addr
+ st
->stroff
;
1791 swap_nlist(syms
, st
->nsyms
, host_byte_sex
);
1792 found_undef
= FALSE
;
1793 for(i
= 0; i
< st
->nsyms
; i
++){
1794 if((syms
[i
].n_type
& N_STAB
) != 0)
1796 if((syms
[i
].n_type
& N_TYPE
) == N_UNDF
){
1797 if(found_undef
== FALSE
){
1798 error("input file: %s contains undefined symbols:",
1802 if(syms
[i
].n_un
.n_strx
!= 0)
1803 printf("%s\n", strs
+ syms
[i
].n_un
.n_strx
);
1805 printf("symbol at index %u is undefined but has NULL "
1806 "name (like a malformed Mach-O file)\n", i
);
1809 if(found_undef
== TRUE
)
1810 fatal("undefined symbols are unsupported for conversion to a "
1813 #ifdef HACK_TO_MATCH_TEST_CASE
1815 * The hack implementation of this routine exist only in order to
1816 * match the current ld_efi(1) script that uses objcopy(1) to make the
1817 * pecoff file. So for that only the common symbols and bss symbols
1818 * make it into the output pecoff file.
1823 * First figure out the section number of the common and bss sections
1824 * and address of those sections.
1831 lc
= arch
->object
->load_commands
;
1832 for(i
= 0; i
< arch
->object
->mh
->ncmds
; i
++){
1833 if(lc
->cmd
== LC_SEGMENT
){
1834 sg
= (struct segment_command
*)lc
;
1835 if(strcmp(sg
->segname
, SEG_DATA
) == 0){
1836 s
= (struct section
*)
1837 ((char *)sg
+ sizeof(struct segment_command
));
1838 for(j
= 0; j
< sg
->nsects
; j
++){
1839 if(strcmp(s
->sectname
, SECT_BSS
) == 0){
1840 bss_n_sect
= n_sect
;
1843 else if(strcmp(s
->sectname
, SECT_COMMON
) == 0){
1844 common_n_sect
= n_sect
;
1845 common_addr
= s
->addr
;
1852 n_sect
+= sg
->nsects
;
1855 lc
= (struct load_command
*)((char *)lc
+ lc
->cmdsize
);
1859 * Count the number of the common and bss sections symbols and add up
1860 * the size of their strings. Note the size of long section names is
1861 * already accounted for in strsize by the code in process_32bit_arch().
1863 for(i
= 0; i
< st
->nsyms
; i
++){
1864 if((syms
[i
].n_type
& N_STAB
) == 0 &&
1865 (syms
[i
].n_type
& N_TYPE
) == N_SECT
&&
1866 (syms
[i
].n_sect
== bss_n_sect
||
1867 syms
[i
].n_sect
== common_n_sect
)){
1869 if(syms
[i
].n_un
.n_strx
!= 0){
1870 size
= strlen(strs
+ syms
[i
].n_un
.n_strx
);
1871 if(size
> E_SYMNMLEN
)
1872 strsize
+= strlen(strs
+ syms
[i
].n_un
.n_strx
) + 1;
1876 #endif /* HACK_TO_MATCH_TEST_CASE */
1879 * Allocate space for the pecoff symbol table and string table.
1881 syments
= allocate(nsyments
* sizeof(struct syment
));
1882 memset(syments
, '\0', nsyments
* sizeof(struct syment
));
1883 strings
= allocate(strsize
);
1886 * Put the size of the string table in the string table first. Then
1887 * the strings for the long section names right after the size.
1894 memcpy(p
, &i
, sizeof(uint32_t));
1895 p
+= sizeof(uint32_t);
1897 memcpy(p
, section_names
, section_names_size
);
1898 p
+= section_names_size
;
1900 #ifdef HACK_TO_MATCH_TEST_CASE
1902 * First put in the bss symbols, again to match what is done by
1906 for(i
= 0; i
< st
->nsyms
; i
++){
1907 if((syms
[i
].n_type
& N_STAB
) == 0 &&
1908 (syms
[i
].n_type
& N_TYPE
) == N_SECT
&&
1909 syms
[i
].n_sect
== bss_n_sect
){
1910 if(syms
[i
].n_un
.n_strx
!= 0){
1911 size
= strlen(strs
+ syms
[i
].n_un
.n_strx
);
1912 if(size
> E_SYMNMLEN
){
1913 syments
[j
].e
.e
.e_zeroes
= 0;
1914 syments
[j
].e
.e
.e_offset
= p
- strings
;
1915 strcpy(p
, strs
+ syms
[i
].n_un
.n_strx
);
1916 p
+= strlen(strs
+ syms
[i
].n_un
.n_strx
) + 1;
1919 strncpy(syments
[j
].e
.e_name
,
1920 strs
+ syms
[i
].n_un
.n_strx
, E_SYMNMLEN
);
1923 syments
[j
].e_value
= syms
[i
].n_value
- bss_addr
;
1924 syments
[j
].e_scnum
= bss_scnum
;
1925 syments
[j
].e_type
= 0;
1926 syments
[j
].e_sclass
= IMAGE_SYM_CLASS_EXTERNAL
;
1927 syments
[j
].e_numaux
= 0;
1932 * Next put in the common symbols, again to match what is done by
1935 for(i
= 0; i
< st
->nsyms
; i
++){
1936 if((syms
[i
].n_type
& N_STAB
) == 0 &&
1937 (syms
[i
].n_type
& N_TYPE
) == N_SECT
&&
1938 syms
[i
].n_sect
== common_n_sect
){
1939 if(syms
[i
].n_un
.n_strx
!= 0){
1940 size
= strlen(strs
+ syms
[i
].n_un
.n_strx
);
1941 if(size
> E_SYMNMLEN
){
1942 syments
[j
].e
.e
.e_zeroes
= 0;
1943 syments
[j
].e
.e
.e_offset
= p
- strings
;
1944 strcpy(p
, strs
+ syms
[i
].n_un
.n_strx
);
1945 p
+= strlen(strs
+ syms
[i
].n_un
.n_strx
) + 1;
1948 strncpy(syments
[j
].e
.e_name
,
1949 strs
+ syms
[i
].n_un
.n_strx
, E_SYMNMLEN
);
1952 syments
[j
].e_value
= syms
[i
].n_value
- common_addr
;
1953 syments
[j
].e_scnum
= common_scnum
;
1954 syments
[j
].e_type
= 0;
1955 syments
[j
].e_sclass
= IMAGE_SYM_CLASS_EXTERNAL
;
1956 syments
[j
].e_numaux
= 0;
1962 swap_syment(syments
, nsyments
, target_byte_sex
);
1964 #endif /* HACK_TO_MATCH_TEST_CASE */
1968 * create_64bit_symbol_table() is called to process the input Mach-O file and
1969 * create the pecoff symbol and string table.
1973 create_64bit_symbol_table(
1979 struct symtab_command
*st
;
1980 struct nlist_64
*syms64
;
1982 enum bool found_undef
;
1984 st
= arch
->object
->st
;
1985 object_addr
= arch
->object
->object_addr
;
1986 syms64
= (struct nlist_64
*)(object_addr
+ st
->symoff
);
1987 strs
= object_addr
+ st
->stroff
;
1989 swap_nlist_64(syms64
, st
->nsyms
, host_byte_sex
);
1991 * If the entry point option was specified then look for that symbol
1992 * and set the entry point value.
1994 if(entry_point
!= NULL
){
1995 for(i
= 0; i
< st
->nsyms
; i
++){
1996 if((syms64
[i
].n_type
& N_STAB
) == 0 &&
1997 syms64
[i
].n_un
.n_strx
!= 0 &&
1998 strcmp(strs
+ syms64
[i
].n_un
.n_strx
, entry_point
) == 0){
1999 entry
= syms64
[i
].n_value
;
2004 fatal("can't find symbol for -e %s in input file: %s",
2005 entry_point
, arch
->file_name
);
2009 * Make sure the Mach-O file does not have any undefined symbols.
2011 found_undef
= FALSE
;
2012 for(i
= 0; i
< st
->nsyms
; i
++){
2013 if((syms64
[i
].n_type
& N_STAB
) != 0)
2015 if((syms64
[i
].n_type
& N_TYPE
) == N_UNDF
){
2016 if(found_undef
== FALSE
){
2017 error("input file: %s contains undefined symbols:",
2021 if(syms64
[i
].n_un
.n_strx
!= 0)
2022 printf("%s\n", strs
+ syms64
[i
].n_un
.n_strx
);
2024 printf("symbol at index %u is undefined but has NULL "
2025 "name (like a malformed Mach-O file)\n", i
);
2028 if(found_undef
== TRUE
)
2029 fatal("undefined symbols are unsupported for conversion to a "
2033 * No symbols are actually needed in the pecoff file from the Mach-O
2034 * file so create an empty symbol table.
2036 * Set the number of symbols to zero and allocate the string table.
2037 * Note the size of long section names is already accounted for in
2038 * strsize by the code in process_64bit_arch().
2041 strings
= allocate(strsize
);
2044 * Put the size of the string table in the string table first. Then
2045 * the strings for the long section names right after the size.
2052 memcpy(p
, &i
, sizeof(uint32_t));
2053 p
+= sizeof(uint32_t);
2055 memcpy(p
, section_names
, section_names_size
);
2059 * create_base_reloc() is called to process the input Mach-O file and gather
2060 * the info needed and then to create the base relocation entries.
2067 uint32_t ncmds
, i
, j
;
2068 uint64_t addr
, first_addr
;
2069 struct load_command
*lc
;
2070 struct segment_command
*sg
;
2071 struct segment_command_64
*sg64
;
2073 struct section_64
*s64
;
2074 struct relocation_info
*relocs
;
2077 struct dysymtab_command
*dyst
;
2079 if(arch
->object
->mh
!= NULL
)
2080 ncmds
= arch
->object
->mh
->ncmds
;
2082 ncmds
= arch
->object
->mh64
->ncmds
;
2083 dyst
= arch
->object
->dyst
;
2084 object_addr
= arch
->object
->object_addr
;
2087 lc
= arch
->object
->load_commands
;
2088 for(i
= 0; i
< ncmds
; i
++){
2089 if(lc
->cmd
== LC_SEGMENT
){
2090 sg
= (struct segment_command
*)lc
;
2092 first_addr
= sg
->vmaddr
;
2093 s
= (struct section
*)
2094 ((char *)sg
+ sizeof(struct segment_command
));
2095 for(j
= 0; j
< sg
->nsects
; j
++){
2096 relocs
= (struct relocation_info
*)(object_addr
+
2099 swap_relocation_info(relocs
, s
[j
].nreloc
,
2101 if(arch
->object
->mh_cputype
== CPU_TYPE_I386
)
2102 gather_base_reloc_info(s
[j
].addr
, relocs
, s
[j
].nreloc
,
2103 CPU_TYPE_I386
, 2, GENERIC_RELOC_VANILLA
,
2104 IMAGE_REL_BASED_HIGHLOW
);
2105 else if(arch
->object
->mh_cputype
== CPU_TYPE_ARM
)
2106 gather_base_reloc_info(s
[j
].addr
, relocs
, s
[j
].nreloc
,
2107 CPU_TYPE_ARM
, 2, GENERIC_RELOC_VANILLA
,
2108 IMAGE_REL_BASED_HIGHLOW
);
2109 if((s
[j
].flags
& SECTION_TYPE
) ==
2110 S_NON_LAZY_SYMBOL_POINTERS
){
2111 for(addr
= s
[j
].addr
;
2112 addr
< s
[j
].addr
+ s
[j
].size
;
2114 add_base_reloc(addr
, IMAGE_REL_BASED_HIGHLOW
);
2119 else if(lc
->cmd
== LC_SEGMENT_64
){
2120 sg64
= (struct segment_command_64
*)lc
;
2121 if(arch
->object
->mh_cputype
== CPU_TYPE_X86_64
) {
2123 * X86_64 relocations are relative to the first writable
2126 if((first_addr
== 0) &&
2127 ((sg64
->initprot
& VM_PROT_WRITE
) != 0)) {
2128 first_addr
= sg64
->vmaddr
;
2132 first_addr
= sg64
->vmaddr
;
2134 s64
= (struct section_64
*)
2135 ((char *)sg64
+ sizeof(struct segment_command_64
));
2136 for(j
= 0; j
< sg64
->nsects
; j
++){
2137 relocs
= (struct relocation_info
*)(object_addr
+
2140 swap_relocation_info(relocs
, s64
[j
].nreloc
,
2142 if(arch
->object
->mh_cputype
== CPU_TYPE_X86_64
)
2143 gather_base_reloc_info(s64
[j
].addr
, relocs
,
2144 s64
[j
].nreloc
, CPU_TYPE_X86_64
, 3,
2145 X86_64_RELOC_UNSIGNED
, IMAGE_REL_BASED_DIR64
);
2146 if((s64
[j
].flags
& SECTION_TYPE
) ==
2147 S_NON_LAZY_SYMBOL_POINTERS
){
2148 for(addr
= s64
[j
].addr
;
2149 addr
< s64
[j
].addr
+ s64
[j
].size
;
2151 add_base_reloc(addr
, IMAGE_REL_BASED_DIR64
);
2156 lc
= (struct load_command
*)((char *)lc
+ lc
->cmdsize
);
2158 if(dyst
!= NULL
&& dyst
->nlocrel
!= 0){
2159 relocs
= (struct relocation_info
*)(object_addr
+
2162 swap_relocation_info(relocs
, dyst
->nlocrel
, host_byte_sex
);
2163 if(arch
->object
->mh_cputype
== CPU_TYPE_I386
)
2164 gather_base_reloc_info(first_addr
, relocs
, dyst
->nlocrel
,
2165 CPU_TYPE_I386
, 2, GENERIC_RELOC_VANILLA
,
2166 IMAGE_REL_BASED_HIGHLOW
);
2167 else if(arch
->object
->mh_cputype
== CPU_TYPE_ARM
)
2168 gather_base_reloc_info(first_addr
, relocs
, dyst
->nlocrel
,
2169 CPU_TYPE_ARM
, 2, GENERIC_RELOC_VANILLA
,
2170 IMAGE_REL_BASED_HIGHLOW
);
2171 else if(arch
->object
->mh_cputype
== CPU_TYPE_X86_64
)
2172 gather_base_reloc_info(first_addr
, relocs
, dyst
->nlocrel
,
2173 CPU_TYPE_X86_64
, 3, X86_64_RELOC_UNSIGNED
,
2174 IMAGE_REL_BASED_DIR64
);
2177 if(dyst != NULL && dyst->nextrel != 0)
2178 ; TODO error if there are external relocation entries */
2181 * Now with all the info gathered make the base relocation entries.
2187 * gather_base_reloc_info() is passed the base address for the set of Mach-O
2188 * relocation entries. And is passed the cpu_type, length and macho_reloc_type
2189 * to look for and the base_reloc_type to create if found.
2193 gather_base_reloc_info(
2195 struct relocation_info
*relocs
,
2197 cpu_type_t cpu_type
,
2199 int macho_reloc_type
,
2200 int base_reloc_type
)
2202 uint32_t i
, r_address
, r_pcrel
, r_length
, r_extern
, r_type
;
2203 struct scattered_relocation_info
*sreloc
;
2205 for(i
= 0; i
< nreloc
; i
++){
2206 if((relocs
[i
].r_address
& R_SCATTERED
) != 0){
2207 sreloc
= (struct scattered_relocation_info
*)(relocs
+ i
);
2208 r_address
= sreloc
->r_address
;
2209 r_pcrel
= sreloc
->r_pcrel
;
2210 r_length
= sreloc
->r_length
;
2211 r_type
= (enum reloc_type_generic
)sreloc
->r_type
;
2215 r_address
= relocs
[i
].r_address
;
2216 r_pcrel
= relocs
[i
].r_pcrel
;
2217 r_length
= relocs
[i
].r_length
;
2218 r_extern
= relocs
[i
].r_extern
;
2219 r_type
= (enum reloc_type_generic
)relocs
[i
].r_type
;
2222 if(r_extern
== 0 && r_pcrel
== 0 &&
2223 r_length
== length
&& r_type
== macho_reloc_type
)
2224 add_base_reloc(addr
+ r_address
, base_reloc_type
);
2226 ; /* TODO add checking and error messages here */
2228 if((relocs
[i
].r_address
& R_SCATTERED
) == 0){
2229 if(reloc_has_pair(cpu_type
, relocs
[i
].r_type
))
2233 sreloc
= (struct scattered_relocation_info
*)relocs
+ i
;
2234 if(reloc_has_pair(cpu_type
, sreloc
->r_type
))
2241 * add_base_reloc() is passed a addr and a type for a base relocation entry to
2251 struct base_reloc
*new_base_relocs
;
2255 base_relocs
= (struct base_reloc
*)
2256 malloc(max
* sizeof(struct base_reloc
));
2258 if(nbase_reloc
>= max
){
2259 new_base_relocs
= malloc(2 * max
* sizeof(struct base_reloc
));
2260 memcpy(new_base_relocs
, base_relocs
,
2261 max
* sizeof(struct base_reloc
));
2264 base_relocs
= new_base_relocs
;
2266 base_relocs
[nbase_reloc
].addr
= addr
;
2267 base_relocs
[nbase_reloc
].type
= type
;
2272 * The base relocation table in a PECOFF file is divided into blocks. Each
2273 * block represents the base relocations for a 4K page. Each block must start
2274 * on a 32-bit boundary. Which is why one "nop" base relocation entry may be
2275 * be added as padding in a block.
2277 #define MAX_BLOCK_OFFSET 0x1000
2278 #define BLOCK_MASK (MAX_BLOCK_OFFSET-1)
2281 * make_base_relocs() takes the info for the base relocation entries gathered
2282 * and creates the fixup blocks as they would be in a PECOFF file and sets the
2283 * static variables reloc_contents and reloc_size to the pointer to contents
2284 * and the size of that contents.
2296 struct base_relocation_block_header
*h
;
2297 struct base_relocation_entry
*b
;
2303 * After we create each base relocation block we will allocate space
2304 * for it in the .reloc section contents buffer and copy it into the
2308 reloc_contents
= NULL
;
2311 * If there are no base relocation entries return so we don't create a
2312 * base relocation block with 0 entries.
2314 if(nbase_reloc
== 0)
2317 qsort(base_relocs
, nbase_reloc
, sizeof(struct base_reloc
),
2318 (int (*)(const void *, const void *))cmp_base_relocs
);
2321 * The size of the base relocation tables must be a multiple of 4 bytes.
2322 * so we may need to add one relocation entry as padding. We make this
2323 * fixup block large enought to hold all the base relocation entries.
2324 * But it will be broken up for the base relocation entries for each
2325 * each group that refers to the same 4K page.
2327 size
= sizeof(struct base_relocation_block_header
) +
2328 (nbase_reloc
+ 1) * sizeof(struct base_relocation_entry
);
2333 base
= base_relocs
[0].addr
& ~BLOCK_MASK
;
2334 h
= (struct base_relocation_block_header
*)fb
;
2335 b
= (struct base_relocation_entry
*)
2336 (fb
+ sizeof(struct base_relocation_block_header
));
2337 for(i
= 0; i
< nbase_reloc
; i
++){
2338 offset
= base_relocs
[i
].addr
- base
;
2339 if(offset
>= MAX_BLOCK_OFFSET
) {
2340 /* add padding if needed */
2341 if((entries
% 2) != 0){
2342 b
[entries
].type
= IMAGE_REL_BASED_ABSOLUTE
;
2343 b
[entries
].offset
= 0;
2347 size
= sizeof(struct base_relocation_block_header
) +
2348 entries
* sizeof(struct base_relocation_entry
);
2349 h
->block_size
= size
;
2351 swap_base_relocation_block_header(h
,
2353 swap_base_relocation_entry(b
, entries
,
2356 /* copy this finished block into the .reloc contents buffer */
2357 reloc_contents
= reallocate(reloc_contents
, reloc_size
+ size
);
2358 memcpy(reloc_contents
+ reloc_size
, fb
, size
);
2363 base
= base_relocs
[i
].addr
& ~BLOCK_MASK
;
2364 offset
= base_relocs
[i
].addr
- base
;
2366 b
[entries
].type
= base_relocs
[i
].type
;
2367 b
[entries
].offset
= offset
;
2371 /* add padding if needed */
2372 if((entries
% 2) != 0){
2373 b
[entries
].type
= IMAGE_REL_BASED_ABSOLUTE
;
2374 b
[entries
].offset
= 0;
2378 size
= sizeof(struct base_relocation_block_header
) +
2379 entries
* sizeof(struct base_relocation_entry
);
2380 h
->block_size
= size
;
2382 swap_base_relocation_block_header(h
, target_byte_sex
);
2383 swap_base_relocation_entry(b
, entries
, target_byte_sex
);
2386 /* copy this last block into the .reloc contents buffer */
2387 reloc_contents
= reallocate(reloc_contents
, reloc_size
+ size
);
2388 memcpy(reloc_contents
+ reloc_size
, fb
, size
);
2398 struct base_reloc
*x1
,
2399 struct base_reloc
*x2
)
2401 if(x1
->addr
< x2
->addr
)
2403 if(x1
->addr
== x2
->addr
)
2405 /* x1->addr > x2->addr */
2410 * create_debug() is called to create the .debug section contents from
2411 * the -d filename argument.
2420 struct load_command
*lc
;
2421 struct uuid_command
*uuid
;
2424 * Allocate space for everything that will be in the .debug section:
2425 * the debug_directory_entry struct
2426 * the mtoc_debug_info struct
2427 * the name of the -d filename argument null terminated.
2429 debug_size
= sizeof(struct debug_directory_entry
) +
2430 sizeof(struct mtoc_debug_info
) +
2431 strlen(debug_filename
) + 1;
2432 debug_contents
= allocate(debug_size
);
2433 memset(debug_contents
, '\0', debug_size
);
2435 * Set up pointers to all the parts to be filled in.
2438 dde
= (struct debug_directory_entry
*)p
;
2439 p
+= sizeof(struct debug_directory_entry
);
2440 mdi
= (struct mtoc_debug_info
*)p
;
2441 p
+= sizeof(struct mtoc_debug_info
);
2443 dde
->Characteristics
= 0;
2444 dde
->TimeDateStamp
= time(NULL
);
2445 dde
->MajorVersion
= 0;
2446 dde
->MinorVersion
= 0;
2447 dde
->Type
= IMAGE_DEBUG_TYPE_CODEVIEW
;
2448 dde
->SizeOfData
= sizeof(struct mtoc_debug_info
) +
2449 strlen(debug_filename
) + 1;
2451 * These two will be filled in later when address and offsets
2454 dde
->AddressOfRawData
= 0;
2455 dde
->PointerToRawData
= 0;
2457 mdi
->Signature
= MTOC_SIGNATURE
;
2458 if(arch
->object
->mh
!= NULL
)
2459 ncmds
= arch
->object
->mh
->ncmds
;
2461 ncmds
= arch
->object
->mh64
->ncmds
;
2462 lc
= arch
->object
->load_commands
;
2463 for(i
= 0; i
< ncmds
; i
++){
2464 if(lc
->cmd
== LC_UUID
){
2465 uuid
= (struct uuid_command
*)lc
;
2466 if (debug_uuid
!= NULL
) {
2467 string_to_uuid (debug_uuid
, uuid
->uuid
);
2469 mdi
->uuid
[0] = uuid
->uuid
[0];
2470 mdi
->uuid
[1] = uuid
->uuid
[1];
2471 mdi
->uuid
[2] = uuid
->uuid
[2];
2472 mdi
->uuid
[3] = uuid
->uuid
[3];
2473 mdi
->uuid
[4] = uuid
->uuid
[4];
2474 mdi
->uuid
[5] = uuid
->uuid
[5];
2475 mdi
->uuid
[6] = uuid
->uuid
[6];
2476 mdi
->uuid
[7] = uuid
->uuid
[7];
2477 mdi
->uuid
[8] = uuid
->uuid
[8];
2478 mdi
->uuid
[9] = uuid
->uuid
[9];
2479 mdi
->uuid
[10] = uuid
->uuid
[10];
2480 mdi
->uuid
[11] = uuid
->uuid
[11];
2481 mdi
->uuid
[12] = uuid
->uuid
[12];
2482 mdi
->uuid
[13] = uuid
->uuid
[13];
2483 mdi
->uuid
[14] = uuid
->uuid
[14];
2484 mdi
->uuid
[15] = uuid
->uuid
[15];
2487 lc
= (struct load_command
*)((char *)lc
+ lc
->cmdsize
);
2490 strcpy(p
, debug_filename
);
2494 * set_debug_addrs_and_offsets() is called after the .debug section's address
2495 * and offset has been set and this routine sets the other needed addresses
2496 * and offsets in the section contents. And swaps the section contents if
2497 * needed for output.
2501 set_debug_addrs_and_offsets(
2504 dde
->AddressOfRawData
= debug_scnhdr
->s_vaddr
+
2505 sizeof(struct debug_directory_entry
);
2506 dde
->PointerToRawData
= debug_scnhdr
->s_scnptr
+
2507 sizeof(struct debug_directory_entry
);
2509 swap_debug_directory_entry(dde
, target_byte_sex
);
2510 swap_mtoc_debug_info(mdi
, target_byte_sex
);
2515 * checksum() calculates the value for the CheckSum field in the optional
2516 * header from the bytes in the output buffer passed to it which has the
2527 for(i
= 0; i
< output_size
; i
+= 2){
2528 if(output_size
- i
== 1)
2531 v
= buf
[i
] + (buf
[i
+1] << 8);
2533 t
= 0xffff & (t
+ (t
>> 0x10));
2535 return(0xffff & (t
+ (t
>> 0x10)));
2539 * string_to_uuid() creates a 128-bit uuid from a well-formatted UUID string
2540 * (i.e. aabbccdd-eeff-gghh-iijj-kkllmmnnoopp)
2551 * scanned bytewise to ensure correct endianness of fields
2553 count
= sscanf (string
, UUID_FORMAT_STRING
,
2554 &uuid
[3], &uuid
[2], &uuid
[1], &uuid
[0],
2557 &uuid
[8], &uuid
[9], &uuid
[10], &uuid
[11],
2558 &uuid
[12], &uuid
[13], &uuid
[14], &uuid
[15]);
2561 fatal ("invalid UUID specified for -u option");