836
[darwin-xtools.git] / cctools / efitools / mtoc.c
blobc24f795c9ceb12eba8c191302424e2b826d5111d
1 /*
2 * Copyright (c) 2007 Apple Inc. All rights reserved.
4 * @APPLE_LICENSE_HEADER_START@
5 *
6 * This file contains Original Code and/or Modifications of Original Code
7 * as defined in and that are subject to the Apple Public Source License
8 * Version 2.0 (the 'License'). You may not use this file except in
9 * compliance with the License. Please obtain a copy of the License at
10 * http://www.opensource.apple.com/apsl/ and read it before using this
11 * file.
13 * The Original Code and all software distributed under the License are
14 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
15 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
16 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
17 * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
18 * Please see the License for the specific language governing rights and
19 * limitations under the License.
21 * @APPLE_LICENSE_HEADER_END@
23 #define __eip eip
24 #define __rip rip
26 #include <stdio.h>
27 #include <stdlib.h>
28 #include <fcntl.h>
29 #include <time.h>
30 #include <sys/types.h>
31 #include <sys/uio.h>
32 #include <unistd.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 {
79 char *name;
80 uint16_t value;
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 },
113 { NULL, 0 }
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;
161 #endif
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(
192 struct arch *archs,
193 uint32_t narchs);
194 static void process_32bit_arch(
195 struct arch *arch);
196 static void process_64bit_arch(
197 struct arch *arch);
198 static void layout_output(
199 struct ofile *ofile);
200 static void create_output(
201 struct ofile *ofile,
202 char *out);
203 static void create_ms_dos_stub(
204 struct ms_dos_stub *p);
205 static void usage(
206 void);
208 static void create_32bit_symbol_table(
209 struct arch *arch);
210 static void create_64bit_symbol_table(
211 struct arch *arch);
214 * This is the internal structure that we gather the base relocation in from
215 * the Mach-O relocation entries.
217 struct base_reloc {
218 uint64_t addr;
219 uint32_t type;
221 struct base_reloc *base_relocs = NULL;
222 uint32_t nbase_reloc = 0;
224 static void create_base_reloc(
225 struct arch *arch);
226 static void gather_base_reloc_info(
227 uint32_t addr,
228 struct relocation_info *relocs,
229 uint32_t nreloc,
230 cpu_type_t cpu_type,
231 uint32_t length,
232 int macho_reloc_type,
233 int base_reloc_type);
234 static void add_base_reloc(
235 uint64_t addr,
236 uint32_t type);
237 static void make_base_relocs(
238 void);
239 static int cmp_base_relocs(
240 struct base_reloc *x1,
241 struct base_reloc *x2);
242 static uint32_t checksum(
243 unsigned char *buf);
244 static void string_to_uuid(
245 char *string,
246 uint8_t *uuid);
248 static void create_debug(
249 struct arch *arch);
250 static void set_debug_addrs_and_offsets(
251 void);
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
265 main(
266 int argc,
267 char **argv,
268 char **envp)
270 int i, j;
271 char *input, *output;
272 struct ofile *ofile;
273 struct arch *archs;
274 uint32_t narchs;
275 char *endp;
276 enum bool section_alignment_specified, align_specified;
278 progname = argv[0];
279 host_byte_sex = get_host_byte_sex();
281 input = NULL;
282 output = NULL;
284 section_alignment_specified = FALSE;
285 align_specified = FALSE;
287 for(i = 1; i < argc; i++){
288 if(strcmp(argv[i], "-subsystem") == 0){
289 if(i + 1 >= argc){
290 warning("no argument specified for -subsystem option");
291 usage();
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;
296 break;
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);
304 usage();
306 i++;
308 else if(strcmp(argv[i], "-d") == 0){
309 if(i + 1 >= argc){
310 warning("no argument specified for -d option");
311 usage();
313 debug_filename = argv[i+1];
314 i++;
316 else if(strcmp(argv[i], "-e") == 0){
317 if(i + 1 >= argc){
318 warning("no argument specified for -e option");
319 usage();
321 entry_point = argv[i+1];
322 i++;
324 else if(strcmp(argv[i], "-u") == 0){
325 if(i + 1 >= argc){
326 warning("no argument specified for -u option");
327 usage();
329 if(debug_filename == NULL) {
330 fatal("-u option requires -d option");
332 debug_uuid = argv[i+1];
333 i++;
335 else if(strcmp(argv[i], "-section_alignment") == 0){
336 if(i + 1 >= argc){
337 warning("no argument specified for -section_alignment "
338 "option");
339 usage();
341 section_alignment = strtoul(argv[i+1], &endp, 16);
342 if(*endp != '\0')
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);
358 i++;
360 else if(strcmp(argv[i], "-align") == 0){
361 if(i + 1 >= argc){
362 warning("no argument specified for -align option");
363 usage();
365 file_alignment = strtoul(argv[i+1], &endp, 16);
366 if(*endp != '\0')
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;
383 i++;
385 else if(input == NULL)
386 input = argv[i];
387 else if(output == NULL)
388 output = argv[i];
389 else
390 usage();
392 if(input == NULL){
393 warning("no input file specified");
394 usage();
396 if(output == NULL){
397 warning("no output file specified");
398 usage();
401 /* breakout the file for processing */
402 ofile = breakout(input, &archs, &narchs, FALSE);
403 if(errors)
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);
411 if(errors){
412 free_archs(archs, narchs);
413 ofile_unmap(ofile);
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);
425 if(errors == 0)
426 return(EXIT_SUCCESS);
427 else
428 return(EXIT_FAILURE);
432 * usage() prints the current usage message and exits indicating failure.
434 static
435 void
436 usage(
437 void)
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);
442 exit(EXIT_FAILURE);
446 * ispoweroftwo() returns TRUE or FALSE depending if x is a power of two.
448 static
449 enum
450 bool
451 ispoweroftwo(
452 uint32_t x)
454 if(x == 0)
455 return(TRUE);
456 while((x & 0x1) != 0x1){
457 x >>= 1;
459 if((x & ~0x1) != 0)
460 return(FALSE);
461 else
462 return(TRUE);
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.
470 static
471 void
472 process_arch(
473 struct arch *archs,
474 uint32_t narchs)
477 * Check to see the input file is something this program can convert to
478 * a pecoff file.
480 if(narchs != 1)
481 fatal("input file: %s must only have one architecture",
482 archs->file_name);
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",
489 archs->file_name);
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);
498 else{
499 fatal("input file: %s must be an MH_PRELOAD file type or "
500 "MH_EXECUTE file type with MH_PIE flag",
501 archs->file_name);
504 else{
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",
512 archs->file_name);
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",
520 archs->file_name);
522 else
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",
525 archs->file_name);
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
540 * section for it.
542 if(debug_filename != NULL)
543 create_debug(archs);
545 if(archs->object->mh != NULL)
546 process_32bit_arch(archs);
547 else
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.
556 static
557 void
558 process_32bit_arch(
559 struct arch *arch)
561 uint32_t i, j, reloc_addr, debug_addr;
562 struct load_command *lc;
563 struct segment_command *sg;
564 struct thread_command *ut;
565 char *p, *state;
566 uint32_t flavor, count;
567 char *object_addr, *section_name;
568 #ifdef HACK_TO_MATCH_TEST_CASE
569 uint32_t len;
570 struct section *s;
571 #endif
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
590 #else
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.
596 #endif
598 nscns = 0;
599 reloc_addr = 0;
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)
608 nscns++;
609 else if(strcmp(sg->segname, SEG_DATA) == 0){
610 nscns++;
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){
617 nscns++;
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
630 nscns++;
631 #else
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;
637 nscns++;
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;
662 while(state < p){
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){
668 case CPU_TYPE_I386:
669 switch((int)flavor){
670 i386_thread_state_t *cpu;
671 case i386_THREAD_STATE:
672 #if i386_THREAD_STATE == 1
673 case -1:
674 #endif /* i386_THREAD_STATE == 1 */
675 /* i386 thread states on older releases */
676 #if i386_THREAD_STATE == -1
677 case 1:
678 #endif /* i386_THREAD_STATE == -1 */
679 cpu = (i386_thread_state_t *)state;
680 entry = cpu->eip;
681 state += sizeof(i386_thread_state_t);
682 break;
683 default:
684 state += count * sizeof(uint32_t);
685 break;
687 break;
688 case CPU_TYPE_ARM:
689 switch(flavor){
690 arm_thread_state_t *cpu;
691 case ARM_THREAD_STATE:
692 cpu = (arm_thread_state_t *)state;
693 entry = cpu->__pc;
694 state += sizeof(arm_thread_state_t);
695 break;
696 default:
697 state += count * sizeof(uint32_t);
698 break;
700 break;
701 default:
702 break;
706 lc = (struct load_command *)((char *)lc + lc->cmdsize);
708 if(reloc_size != 0){
709 /* add one for the .reloc section to contain the base relocations */
710 nscns++;
714 * If there is a -d flag add one for the .debug section to contain
715 * the information.
717 if(debug_filename != NULL)
718 nscns++;
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
748 * vmsize.
749 #else
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.
758 #endif
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;
764 j = 0;
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;
773 #else
774 scnhdrs[j].s_vsize = sg->vmsize;
775 #endif
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 |
782 IMAGE_SCN_MEM_READ |
783 IMAGE_SCN_CNT_CODE;
784 scn_contents[j] = object_addr + sg->fileoff;
785 j++;
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;
791 #else
792 scnhdrs[j].s_vsize = sg->vmsize;
793 #endif
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 |
801 IMAGE_SCN_CNT_CODE |
802 IMAGE_SCN_CNT_INITIALIZED_DATA |
803 IMAGE_SCN_MEM_EXECUTE;
804 scn_contents[j] = object_addr + sg->fileoff;
805 j++;
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++){
810 if(s->size == 0)
811 continue;
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){
822 continue;
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");
830 bss_scnum = j + 1;
832 scn_contents[j] = NULL;
833 j++;
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;
850 j++;
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++){
855 if(s->size == 0)
856 continue;
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;
870 strsize += len;
872 scn_contents[j] = object_addr + s->offset;
873 j++;
875 #endif /* HACK_TO_MATCH_TEST_CASE */
878 lc = (struct load_command *)((char *)lc + lc->cmdsize);
880 if(reloc_size != 0){
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;
894 j++;
895 debug_addr = reloc_addr + reloc_scnhdr->s_size;
897 else{
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;
914 j++;
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.
928 static
929 void
930 process_64bit_arch(
931 struct arch *arch)
933 uint32_t i, j;
934 uint64_t reloc_addr, debug_addr;
935 struct load_command *lc;
936 struct segment_command_64 *sg64;
937 struct thread_command *ut;
938 char *p, *state;
939 uint32_t flavor, count;
940 char *object_addr, *section_name;
941 #ifdef HACK_TO_MATCH_TEST_CASE
942 struct section_64 *s64;
943 uint32_t len;
944 #endif
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.
960 #else
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.
966 #endif
968 nscns = 0;
969 reloc_addr = 0;
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)
979 nscns++;
980 else if(strcmp(sg64->segname, SEG_DATA) == 0)
981 nscns++;
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;
996 nscns++;
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;
1007 while(state < p){
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:
1015 switch(flavor){
1016 x86_thread_state64_t *cpu64;
1017 case x86_THREAD_STATE64:
1018 cpu64 = (x86_thread_state64_t *)state;
1019 entry = cpu64->rip;
1020 state += sizeof(x86_thread_state64_t);
1021 break;
1022 default:
1023 state += count * sizeof(uint32_t);
1024 break;
1026 break;
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 */
1035 nscns++;
1039 * If there is a -d flag add one for the .debug section to contain
1040 * the information.
1042 if(debug_filename != NULL)
1043 nscns++;
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
1073 * vmsize.
1074 #else
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.
1083 #endif
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;
1089 j = 0;
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 |
1105 IMAGE_SCN_CNT_CODE;
1106 scn_contents[j] = object_addr + sg64->fileoff;
1107 j++;
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;
1123 j++;
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);
1135 strsize += len + 1;
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;
1152 j++;
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;
1174 j++;
1175 debug_addr = reloc_addr + reloc_scnhdr->s_size;
1177 else{
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;
1196 j++;
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.
1211 static
1212 void
1213 layout_output(
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) +
1223 sizeof(signature) +
1224 sizeof(struct filehdr) +
1225 nscns * sizeof(struct scnhdr);
1226 if(ofile->mh != NULL)
1227 header_size += sizeof(struct aouthdr);
1228 else
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;
1235 #endif
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;
1270 #else
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)
1274 offset += 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;
1279 else
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;
1287 #endif
1288 #ifdef HACK_TO_MATCH_TEST_CASE
1289 if(ofile->mh != NULL)
1290 #endif
1291 offset = rnd(offset, file_alignment);
1292 #ifdef HACK_TO_MATCH_TEST_CASE
1293 else{
1294 /* for some unknown reason the next offset is moved up
1295 0x200 then rounded to 8 bytes */
1296 offset += 0x200;
1297 offset = rnd(offset, 8);
1299 #endif
1302 #ifdef HACK_TO_MATCH_TEST_CASE
1303 /* for some unknown reason the offset of the symbol is moved back 0x58
1304 bytes */
1305 if(ofile->mh64 != NULL)
1306 offset -= 0x58;
1307 #endif
1308 syment_offset = offset;
1309 offset += nsyments * sizeof(struct syment);
1310 string_offset = offset;
1311 offset += strsize;
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
1326 * bytes).
1328 signature[0] = 'P';
1329 signature[1] = 'E';
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;
1337 else
1338 filehdr.f_magic = IMAGE_FILE_MACHINE_ARM;
1340 else{
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;
1349 else
1350 filehdr.f_timdat = 0x47671e62;
1351 #else
1352 filehdr.f_timdat = time(NULL);
1353 #endif
1354 filehdr.f_symptr = syment_offset;
1355 filehdr.f_nsyms = nsyments;
1356 if(ofile->mh != NULL)
1357 filehdr.f_opthdr = sizeof(struct aouthdr);
1358 else
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
1376 aouthdr.tsize = 0;
1377 aouthdr.dsize = 0;
1378 aouthdr.bsize = 0;
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;
1394 else{
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;
1434 else{
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;
1454 #endif
1456 aouthdr64.entry = entry;
1457 #ifdef HACK_TO_MATCH_TEST_CASE
1458 aouthdr64.entry = 0x4a2;
1459 #endif
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;
1473 #endif
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;
1491 #endif
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;
1497 #endif
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.
1529 static
1530 void
1531 create_output(
1532 struct ofile *ofile,
1533 char *out)
1535 int i, f;
1536 unsigned char *buf, *p, *p_aouthdr;
1539 * Allocate the buffer to place the pecoff file in.
1541 buf = calloc(1, output_size);
1542 if(buf == NULL)
1543 fatal("Can't allocate buffer for output file (size = %u)",
1544 output_size);
1547 * Copy the parts of the pecoff file into the buffer.
1549 p = buf;
1551 memcpy(p, &ms_dos_stub, sizeof(struct ms_dos_stub));
1552 if(swapped)
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));
1560 if(swapped)
1561 swap_filehdr((struct filehdr *)p, target_byte_sex);
1562 p += sizeof(struct filehdr);
1564 p_aouthdr = p;
1565 if(ofile->mh != NULL){
1566 memcpy(p, &aouthdr, sizeof(struct aouthdr));
1567 if(swapped)
1568 swap_aouthdr((struct aouthdr *)p, target_byte_sex);
1569 p += sizeof(struct aouthdr);
1571 else{
1572 memcpy(p, &aouthdr64, sizeof(struct aouthdr_64));
1573 if(swapped)
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
1581 * that was needed.
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,
1586 scn_contents[i],
1587 #ifndef HACK_TO_MATCH_TEST_CASE
1588 scnhdrs[i].s_size);
1589 #else
1590 scnhdrs[i].s_vsize);
1591 #endif
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;
1597 #endif
1601 memcpy(p, scnhdrs, nscns * sizeof(struct scnhdr));
1602 if(swapped)
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
1609 * that was needed.
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));
1621 if(swapped)
1622 swap_aouthdr((struct aouthdr *)p_aouthdr, target_byte_sex);
1624 else{
1625 aouthdr64.CheckSum = checksum(buf) + output_size;
1626 memcpy(p_aouthdr, &aouthdr64, sizeof(struct aouthdr_64));
1627 if(swapped)
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);
1635 if(f == -1)
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);
1641 if(close(f) == -1)
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
1647 * MS-DOS stub.
1649 static
1650 void
1651 create_ms_dos_stub(
1652 struct ms_dos_stub *p)
1654 int i;
1656 p->e_magic = DOSMAGIC;
1657 p->e_cblp = 0x90;
1658 p->e_cp = 0x3;
1659 p->e_crlc = 0x0;
1660 p->e_cparhdr = 0x4;
1661 p->e_minalloc = 0x0;
1662 p->e_maxalloc = 0xffff;
1663 p->e_ss = 0x0;
1664 p->e_sp = 0xb8;
1665 p->e_csum = 0x0;
1666 p->e_ip = 0x0;
1667 p->e_cs = 0x0;
1668 p->e_lfarlc = 0x40;
1669 p->e_ovno = 0x0;
1671 for(i = 0; i < 4; i++)
1672 p->e_res[i] = 0x0;
1674 p->e_oemid = 0x0;
1675 p->e_oeminfo = 0x0;
1677 for(i = 0; i < 10; i++)
1678 p->e_res2[i] = 0x0;
1680 p->e_lfanew = 0x80;
1683 * The sub dos program that prints "This program cannot be run in DOS
1684 * mode".
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.
1757 static
1758 void
1759 create_32bit_symbol_table(
1760 struct arch *arch)
1762 char *object_addr;
1763 struct symtab_command *st;
1764 struct nlist *syms;
1765 char *strs;
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;
1772 struct section *s;
1773 #endif /* HACK_TO_MATCH_TEST_CASE */
1774 uint32_t i;
1775 char *p;
1778 * No symbols are actually needed in the pecoff file from the Mach-O
1779 * file so create an empty symbol table.
1781 nsyments = 0;
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;
1790 if(swapped)
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)
1795 continue;
1796 if((syms[i].n_type & N_TYPE) == N_UNDF){
1797 if(found_undef == FALSE){
1798 error("input file: %s contains undefined symbols:",
1799 arch->file_name);
1801 found_undef = TRUE;
1802 if(syms[i].n_un.n_strx != 0)
1803 printf("%s\n", strs + syms[i].n_un.n_strx);
1804 else
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 "
1811 "pecoff file");
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.
1826 n_sect = 1;
1827 bss_n_sect = 0;
1828 bss_addr = 0;
1829 common_n_sect = 0;
1830 common_addr = 0;
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;
1841 bss_addr = s->addr;
1843 else if(strcmp(s->sectname, SECT_COMMON) == 0){
1844 common_n_sect = n_sect;
1845 common_addr = s->addr;
1847 s++;
1848 n_sect++;
1851 else{
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)){
1868 nsyments++;
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.
1889 p = strings;
1891 i = strsize;
1892 if(swapped)
1893 i = SWAP_INT(i);
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
1903 * objcopy.
1905 j = 0;
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;
1918 else{
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;
1928 j++;
1932 * Next put in the common symbols, again to match what is done by
1933 * objcopy.
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;
1947 else{
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;
1957 j++;
1961 if(swapped)
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.
1971 static
1972 void
1973 create_64bit_symbol_table(
1974 struct arch *arch)
1976 char *p;
1977 uint32_t i;
1978 char *object_addr;
1979 struct symtab_command *st;
1980 struct nlist_64 *syms64;
1981 char *strs;
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;
1988 if(swapped)
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;
2000 break;
2003 if(i == st->nsyms)
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)
2014 continue;
2015 if((syms64[i].n_type & N_TYPE) == N_UNDF){
2016 if(found_undef == FALSE){
2017 error("input file: %s contains undefined symbols:",
2018 arch->file_name);
2020 found_undef = TRUE;
2021 if(syms64[i].n_un.n_strx != 0)
2022 printf("%s\n", strs + syms64[i].n_un.n_strx);
2023 else
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 "
2030 "pecoff file");
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().
2040 nsyments = 0;
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.
2047 p = strings;
2049 i = strsize;
2050 if(swapped)
2051 i = SWAP_INT(i);
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.
2062 static
2063 void
2064 create_base_reloc(
2065 struct arch *arch)
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;
2072 struct section *s;
2073 struct section_64 *s64;
2074 struct relocation_info *relocs;
2076 char *object_addr;
2077 struct dysymtab_command *dyst;
2079 if(arch->object->mh != NULL)
2080 ncmds = arch->object->mh->ncmds;
2081 else
2082 ncmds = arch->object->mh64->ncmds;
2083 dyst = arch->object->dyst;
2084 object_addr = arch->object->object_addr;
2086 first_addr = 0;
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;
2091 if(first_addr == 0)
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 +
2097 s[j].reloff);
2098 if(swapped)
2099 swap_relocation_info(relocs, s[j].nreloc,
2100 host_byte_sex);
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;
2113 addr += 4) {
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
2124 * segment.
2126 if((first_addr == 0) &&
2127 ((sg64->initprot & VM_PROT_WRITE) != 0)) {
2128 first_addr = sg64->vmaddr;
2130 } else {
2131 if(first_addr == 0)
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 +
2138 s64[j].reloff);
2139 if(swapped)
2140 swap_relocation_info(relocs, s64[j].nreloc,
2141 host_byte_sex);
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;
2150 addr += 8) {
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 +
2160 dyst->locreloff);
2161 if(swapped)
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.
2183 make_base_relocs();
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.
2191 static
2192 void
2193 gather_base_reloc_info(
2194 uint32_t addr,
2195 struct relocation_info *relocs,
2196 uint32_t nreloc,
2197 cpu_type_t cpu_type,
2198 uint32_t length,
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;
2212 r_extern = 0;
2214 else{
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);
2225 else
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))
2230 i++;
2232 else{
2233 sreloc = (struct scattered_relocation_info *)relocs + i;
2234 if(reloc_has_pair(cpu_type, sreloc->r_type))
2235 i++;
2241 * add_base_reloc() is passed a addr and a type for a base relocation entry to
2242 * add to the list.
2244 static
2245 void
2246 add_base_reloc(
2247 uint64_t addr,
2248 uint32_t type)
2250 static int max = 0;
2251 struct base_reloc *new_base_relocs;
2253 if(!max){
2254 max = 128;
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));
2262 max *= 2;
2263 free(base_relocs);
2264 base_relocs = new_base_relocs;
2266 base_relocs[nbase_reloc].addr = addr;
2267 base_relocs[nbase_reloc].type = type;
2268 nbase_reloc++;
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.
2286 static
2287 void
2288 make_base_relocs(
2289 void)
2291 int blockcnt;
2292 int i, entries;
2293 uint64_t base;
2294 int size;
2295 char *fb;
2296 struct base_relocation_block_header *h;
2297 struct base_relocation_entry *b;
2298 uint32_t offset;
2300 blockcnt = 0;
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
2305 * buffer.
2307 reloc_size = 0;
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)
2315 return;
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);
2329 fb = malloc(size);
2332 entries = 0;
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;
2344 entries++;
2346 h->page_rva = base;
2347 size = sizeof(struct base_relocation_block_header) +
2348 entries * sizeof(struct base_relocation_entry);
2349 h->block_size = size;
2350 if(swapped){
2351 swap_base_relocation_block_header(h,
2352 target_byte_sex);
2353 swap_base_relocation_entry(b, entries,
2354 target_byte_sex);
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);
2359 reloc_size += size;
2361 entries = 0;
2362 blockcnt++;
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;
2368 entries++;
2371 /* add padding if needed */
2372 if((entries % 2) != 0){
2373 b[entries].type = IMAGE_REL_BASED_ABSOLUTE;
2374 b[entries].offset = 0;
2375 entries++;
2377 h->page_rva = base;
2378 size = sizeof(struct base_relocation_block_header) +
2379 entries * sizeof(struct base_relocation_entry);
2380 h->block_size = size;
2381 if(swapped){
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);
2389 reloc_size += size;
2391 blockcnt++;
2392 free(fb);
2395 static
2397 cmp_base_relocs(
2398 struct base_reloc *x1,
2399 struct base_reloc *x2)
2401 if(x1->addr < x2->addr)
2402 return(-1);
2403 if(x1->addr == x2->addr)
2404 return(0);
2405 /* x1->addr > x2->addr */
2406 return(1);
2410 * create_debug() is called to create the .debug section contents from
2411 * the -d filename argument.
2413 static
2414 void
2415 create_debug(
2416 struct arch *arch)
2418 char *p;
2419 uint32_t i, ncmds;
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.
2437 p = debug_contents;
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
2452 * are known.
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;
2460 else
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];
2485 break;
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.
2499 static
2500 void
2501 set_debug_addrs_and_offsets(
2502 void)
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);
2508 if(swapped){
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
2517 * size output_size.
2519 static
2520 uint32_t
2521 checksum(
2522 unsigned char *buf)
2524 uint32_t i, v, t;
2526 t = 0;
2527 for(i = 0; i < output_size; i += 2){
2528 if(output_size - i == 1)
2529 v = buf[i];
2530 else
2531 v = buf[i] + (buf[i+1] << 8);
2532 t += v;
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)
2542 static
2543 void
2544 string_to_uuid(
2545 char *string,
2546 uint8_t *uuid)
2548 uint8_t count;
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],
2555 &uuid[5], &uuid[4],
2556 &uuid[7], &uuid[6],
2557 &uuid[8], &uuid[9], &uuid[10], &uuid[11],
2558 &uuid[12], &uuid[13], &uuid[14], &uuid[15]);
2560 if (count != 16) {
2561 fatal ("invalid UUID specified for -u option");