1/*
2 * Copyright (c) 2007 Apple Inc. All rights reserved.
3 *
4 * @APPLE_LICENSE_HEADER_START@
5 *
6 * This file contains Original Code and/or Modifications of Original Code
7 * as defined in and that are subject to the Apple Public Source License
8 * Version 2.0 (the 'License'). You may not use this file except in
9 * compliance with the License. Please obtain a copy of the License at
10 * http://www.opensource.apple.com/apsl/ and read it before using this
11 * file.
12 *
13 * The Original Code and all software distributed under the License are
14 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
15 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
16 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
17 * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
18 * Please see the License for the specific language governing rights and
19 * limitations under the License.
20 *
21 * @APPLE_LICENSE_HEADER_END@
22 */
23#define __eip eip
24#define __rip rip
25
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"
38
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"
45
46#include "coff/base_relocs.h"
47#include "mach-o/x86_64/reloc.h"
48
49/* used by error routines as the name of this program */
50char *progname = NULL;
51
52/* the bytesex of our target object file and of this host machine */
53static enum byte_sex target_byte_sex;
54static enum byte_sex host_byte_sex;
55static enum bool swapped;
56
57/* the size of the pecoff output file */
58static uint32_t output_size = 0;
59
60/*
61 * The headers, and elements of them in the pecoff output file.
62 */
63static struct ms_dos_stub ms_dos_stub;
64static char signature[4];
65static struct filehdr filehdr;
66static struct aouthdr aouthdr;
67static struct aouthdr_64 aouthdr64;
68uint32_t entry = 0; /* the entry point */
69uint32_t nscns = 0; /* the number of section headers and contents pointers */
70static struct scnhdr *scnhdrs = NULL;  /* the section headers */
71static char **scn_contents = NULL; /* pointers to the section contents */
72
73/*
74 * The value of the -subsystem argument to then set in the PECOFF aouthdr.
75 */
76static uint16_t Subsystem = IMAGE_SUBSYSTEM_EFI_APPLICATION;
77
78struct subsystem_argument {
79    char *name;
80    uint16_t value;
81};
82
83struct 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 },
88
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 },
108
109    { "runtime",		IMAGE_SUBSYSTEM_EFI_RUNTIME_DRIVER },
110    { "rtdrv",			IMAGE_SUBSYSTEM_EFI_RUNTIME_DRIVER },
111    { "DXE_RUNTIME_DRIVER",	IMAGE_SUBSYSTEM_EFI_RUNTIME_DRIVER },
112
113    { NULL, 0 }
114};
115
116/*
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.
119 */
120static uint32_t section_alignment = SECTIONALIGNMENT;
121
122/*
123 * The value of the -align argument to layout the PECOFF file.
124 */
125static uint32_t file_alignment = FILEALIGNMENT;
126
127/* The maximum alignment allowed to be specified, in hex */
128#define MAXALIGN		0x8000
129
130/* Static routine to help parse arguments */
131static enum bool ispoweroftwo(uint32_t x);
132
133/*
134 * The string for the -d argument.
135 */
136char *debug_filename = NULL;
137
138/*
139 * The string for the -u argument.
140 */
141char *debug_uuid = NULL;
142
143/*
144 * Format specifier for scanf() to convert UUID to individual bytes
145 */
146#define UUID_FORMAT_STRING "%02hhx%02hhx%02hhx%02hhx-%02hhx%02hhx-%02hhx%02hhx-%02hhx%02hhx-%02hhx%02hhx%02hhx%02hhx%02hhx%02hhx"
147
148/*
149 * The string for the entry point symbol name.
150 */
151char *entry_point = NULL;
152
153#ifdef HACK_TO_MATCH_TEST_CASE
154/*
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.
158 */
159static uint32_t common_scnum = 0;
160static uint32_t bss_scnum = 0;
161#endif
162
163/*
164 * These are for the .reloc section that contains the base relocations.
165 */
166static struct scnhdr *reloc_scnhdr = NULL;
167static uint32_t reloc_size = 0;
168static char *reloc_contents = NULL;
169
170/*
171 * These are for the pecoff symbol table and string table.
172 */
173static uint32_t nsyments = 0;		/* number of symbols */
174static struct syment *syments = NULL;	/* pointer to symbol table elements */
175static uint32_t syment_offset = 0;	/* file offset of the symbol table */
176static uint32_t strsize = 0;		/* size of the string table */
177static char *strings = NULL;		/* pointer to the string table */
178static uint32_t section_names_size = 0;	/* size of the section names */
179static char *section_names = NULL;	/* pointer to section names */
180static uint32_t string_offset = 0;	/* file offset of the string table */
181
182/*
183 * These are for the .debug section that contains the -d filename information.
184 */
185static struct scnhdr *debug_scnhdr = NULL;
186static uint32_t debug_size = 0;
187static char *debug_contents = NULL;
188static struct debug_directory_entry *dde = NULL;
189static struct mtoc_debug_info *mdi = NULL;
190
191static void process_arch(
192    struct arch *archs,
193    uint32_t narchs);
194static void process_32bit_arch(
195    struct arch *arch);
196static void process_64bit_arch(
197    struct arch *arch);
198static void layout_output(
199    struct ofile *ofile);
200static void create_output(
201    struct ofile *ofile,
202    char *out);
203static void create_ms_dos_stub(
204    struct ms_dos_stub *p);
205static void usage(
206    void);
207
208static void create_32bit_symbol_table(
209    struct arch *arch);
210static void create_64bit_symbol_table(
211    struct arch *arch);
212
213/*
214 * This is the internal structure that we gather the base relocation in from
215 * the Mach-O relocation entries.
216 */
217struct base_reloc {
218    uint64_t addr;
219    uint32_t type;
220};
221struct base_reloc *base_relocs = NULL;
222uint32_t nbase_reloc = 0;
223
224static void create_base_reloc(
225    struct arch *arch);
226static 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);
234static void add_base_reloc(
235    uint64_t addr,
236    uint32_t type);
237static void make_base_relocs(
238    void);
239static int cmp_base_relocs(
240    struct base_reloc *x1,
241    struct base_reloc *x2);
242static uint32_t checksum(
243    unsigned char *buf);
244static void string_to_uuid(
245    char *string,
246    uint8_t *uuid);
247
248static void create_debug(
249    struct arch *arch);
250static void set_debug_addrs_and_offsets(
251    void);
252
253/* apple_version is created by the libstuff/Makefile */
254extern char apple_version[];
255char *version = apple_version;
256
257/*
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).
260 *
261 *	mtoc [-subsystem type] [-section_alignment hexvalue] [-align hexvalue]
262 *	     [-d filename] input_Mach-O output_pecoff
263 */
264int
265main(
266int argc,
267char **argv,
268char **envp)
269{
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;
277
278	progname = argv[0];
279	host_byte_sex = get_host_byte_sex();
280
281	input = NULL;
282	output = NULL;
283
284	section_alignment_specified = FALSE;
285	align_specified = FALSE;
286
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();
292		}
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;
297		    }
298		}
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();
305		}
306		i++;
307	    }
308	    else if(strcmp(argv[i], "-d") == 0){
309		if(i + 1 >= argc){
310		    warning("no argument specified for -d option");
311		    usage();
312		}
313		debug_filename = argv[i+1];
314		i++;
315	    }
316	    else if(strcmp(argv[i], "-e") == 0){
317		if(i + 1 >= argc){
318		    warning("no argument specified for -e option");
319		    usage();
320		}
321		entry_point = argv[i+1];
322		i++;
323	    }
324	    else if(strcmp(argv[i], "-u") == 0){
325		if(i + 1 >= argc){
326		    warning("no argument specified for -u option");
327		    usage();
328		}
329		if(debug_filename == NULL) {
330		    fatal("-u option requires -d option");
331		}
332		debug_uuid = argv[i+1];
333		i++;
334	    }
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();
340		}
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++;
359	    }
360	    else if(strcmp(argv[i], "-align") == 0){
361		if(i + 1 >= argc){
362		    warning("no argument specified for -align option");
363		    usage();
364		}
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++;
384	    }
385	    else if(input == NULL)
386		input = argv[i];
387	    else if(output == NULL)
388		output = argv[i];
389	    else
390		usage();
391	}
392	if(input == NULL){
393	    warning("no input file specified");
394	    usage();
395	}
396	if(output == NULL){
397	    warning("no output file specified");
398	    usage();
399	}
400
401	/* breakout the file for processing */
402	ofile = breakout(input, &archs, &narchs, FALSE);
403	if(errors)
404	    return(EXIT_FAILURE);
405
406	/* checkout the file for symbol table replacement processing */
407	checkout(archs, narchs);
408
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);
415	}
416
417	/*
418	 * Layout the pecoff output file from the information gathered from
419	 * the input file creating the needed headers, relocs, etc.
420	 */
421	layout_output(ofile);
422
423	create_output(ofile, output);
424
425	if(errors == 0)
426	    return(EXIT_SUCCESS);
427	else
428	    return(EXIT_FAILURE);
429}
430
431/*
432 * usage() prints the current usage message and exits indicating failure.
433 */
434static
435void
436usage(
437void)
438{
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);
443}
444
445/*
446 * ispoweroftwo() returns TRUE or FALSE depending if x is a power of two.
447 */
448static
449enum
450bool
451ispoweroftwo(
452uint32_t x)
453{
454	if(x == 0)
455	    return(TRUE);
456	while((x & 0x1) != 0x1){
457	    x >>= 1;
458	}
459	if((x & ~0x1) != 0)
460	    return(FALSE);
461	else
462	    return(TRUE);
463}
464
465/*
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.
469 */
470static
471void
472process_arch(
473struct arch *archs,
474uint32_t narchs)
475{
476	/*
477	 * Check to see the input file is something this program can convert to
478	 * a pecoff file.
479	 */
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);
497	    }
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);
502	    }
503	}
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);
513	    }
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);
521	    }
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);
526	}
527
528	target_byte_sex = archs->object->object_byte_sex;
529	swapped = host_byte_sex != target_byte_sex;
530
531	/*
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.
535	 */
536	create_base_reloc(archs);
537
538	/*
539	 * If there is a -d flag create the information that will be in .debug
540	 * section for it.
541	 */
542	if(debug_filename != NULL)
543	    create_debug(archs);
544
545	if(archs->object->mh != NULL)
546	    process_32bit_arch(archs);
547	else
548	    process_64bit_arch(archs);
549}
550
551/*
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.
555 */
556static
557void
558process_32bit_arch(
559struct arch *arch)
560{
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
572
573	/*
574	 * Determine the number of sections in the pecoff output file.
575	 *
576#ifdef HACK_TO_MATCH_TEST_CASE
577	 *
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:
582	 *
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
589	 *
590#else
591	 *
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.
595	 *
596#endif
597	 */
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++;
618			}
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);
625		    }
626#endif /* HACK_TO_MATCH_TEST_CASE */
627		}
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++;
638			}
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);
644		    }
645
646#endif /* HACK_TO_MATCH_TEST_CASE */
647		}
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);
653		}
654	    }
655	    /*
656	     * Also while processing the Mach-O file pick up the entry point.
657	     */
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;
686			}
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;
699			}
700		        break;
701		    default:
702			break;
703		    }
704		}
705	    }
706	    lc = (struct load_command *)((char *)lc + lc->cmdsize);
707	}
708	if(reloc_size != 0){
709	    /* add one for the .reloc section to contain the base relocations */
710	    nscns++;
711	}
712
713	/*
714	 * If there is a -d flag add one for the .debug section to contain
715	 * the information.
716	 */
717	if(debug_filename != NULL)
718	    nscns++;
719
720	/*
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.
725	 */
726	strsize = sizeof(uint32_t);
727
728	/*
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.
732	 */
733	section_names = allocate(section_names_size);
734	section_name = section_names;
735	if(section_names_size != 0)
736	    *section_name = '\0';
737
738	/*
739	 * Allocate space for the section headers and fill in everything but
740	 * their file offsets.
741	 *
742#ifndef HACK_TO_MATCH_TEST_CASE
743	 *
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
750	 *
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
759	 */
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++;
786		}
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;
823			}
824			else if(strcmp(s->sectname, SECT_COMMON) == 0){
825			    strcpy(scnhdrs[j].s_name, ".common");
826			    common_scnum = j + 1;
827			}
828			else if(strcmp(s->sectname, SECT_BSS) == 0){
829			    strcpy(scnhdrs[j].s_name, ".bss");
830			    bss_scnum = j + 1;
831			}
832			scn_contents[j] = NULL;
833			j++;
834		    }
835#endif /* HACK_TO_MATCH_TEST_CASE */
836		}
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;
871			}
872			scn_contents[j] = object_addr + s->offset;
873			j++;
874		    }
875#endif /* HACK_TO_MATCH_TEST_CASE */
876		}
877	    }
878	    lc = (struct load_command *)((char *)lc + lc->cmdsize);
879	}
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;
896	}
897	else{
898	    debug_addr = rnd(reloc_addr, section_alignment);
899	}
900
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++;
915	}
916
917	/*
918	 * Create the pecoff symbol and string table from this Mach-O file.
919	 */
920	create_32bit_symbol_table(arch);
921}
922
923/*
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.
927 */
928static
929void
930process_64bit_arch(
931struct arch *arch)
932{
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
945
946	/*
947	 * Determine the number of sections in the pecoff output file.
948	 *
949#ifdef HACK_TO_MATCH_TEST_CASE
950	 *
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.
959	 *
960#else
961	 *
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.
965	 *
966#endif
967	 */
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);
986		}
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++;
997		}
998#endif /* HACK_TO_MATCH_TEST_CASE */
999	    }
1000	    /*
1001	     * Also while process the Mach-O file pick up the entry point.
1002	     */
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;
1025			}
1026			break;
1027#endif /* x86_THREAD_STATE64 */
1028		    }
1029		}
1030	    }
1031	    lc = (struct load_command *)((char *)lc + lc->cmdsize);
1032	}
1033	if(reloc_size != 0){
1034	    /* add one for the .reloc section to contain the base relocations */
1035	    nscns++;
1036	}
1037
1038	/*
1039	 * If there is a -d flag add one for the .debug section to contain
1040	 * the information.
1041	 */
1042	if(debug_filename != NULL)
1043	    nscns++;
1044
1045	/*
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.
1050	 */
1051	strsize = sizeof(uint32_t);
1052
1053	/*
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.
1057	 */
1058	section_names = allocate(section_names_size) + 1;
1059	section_name = section_names;
1060	if(section_names_size != 0)
1061	    *section_name = '\0';
1062
1063	/*
1064	 * Allocate space for the section headers and fill in everything but
1065	 * their file offsets.
1066	 *
1067#ifndef HACK_TO_MATCH_TEST_CASE
1068	 *
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
1075	 *
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
1084	 */
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++;
1108		}
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++;
1124		}
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 */
1138
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++;
1153		}
1154#endif /* HACK_TO_MATCH_TEST_CASE */
1155	    }
1156	    lc = (struct load_command *)((char *)lc + lc->cmdsize);
1157	}
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;
1176	}
1177	else{
1178	    debug_addr = rnd(reloc_addr, section_alignment);
1179	}
1180
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++;
1197	}
1198
1199	/*
1200	 * Create the pecoff symbol and string table from this Mach-O file.
1201	 */
1202	create_64bit_symbol_table(arch);
1203}
1204
1205/*
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.
1210 */
1211static
1212void
1213layout_output(
1214struct ofile *ofile)
1215{
1216    uint32_t i, header_size, offset, least_vaddr;
1217
1218	/*
1219	 * Determine the size of the output file and where each element will be
1220	 * in the output file.
1221	 */
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
1236	/*
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.
1241	 */
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;
1246	}
1247	if(least_vaddr > header_size)
1248	    header_size = least_vaddr;
1249
1250	offset = header_size;
1251	for(i = 0; i < nscns; i++){
1252	    if((scnhdrs[i].s_flags & IMAGE_SCN_CNT_UNINITIALIZED_DATA) == 0){
1253		/*
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.
1258		 */
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);
1263		/*
1264		 * The s_scnptr is set to the offset and then the offset is
1265		 * incremented by the SizeOfRawData field (s_vsize).
1266		 */
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
1280		    /*
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.
1285		     */
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);
1298		}
1299#endif
1300	    }
1301	}
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;
1312
1313	output_size = offset;
1314
1315	/*
1316	 * Now with all the sizes and placement of things know fill in headers
1317	 * of the pecoff file for this Mach-O file.
1318	 */
1319
1320	/* first in the pecoff file is the MS-DOS stub */
1321	create_ms_dos_stub(&ms_dos_stub);
1322
1323	/*
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).
1327	 */
1328	signature[0] = 'P';
1329	signature[1] = 'E';
1330	signature[2] = '\0';
1331	signature[3] = '\0';
1332
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;
1339	}
1340	else{
1341	    if(ofile->mh64->cputype == CPU_TYPE_X86_64)
1342		filehdr.f_magic = IMAGE_FILE_MACHINE_AMD64;
1343	}
1344	filehdr.f_nscns = nscns;
1345#ifdef HACK_TO_MATCH_TEST_CASE
1346	if(ofile->mh != NULL){
1347	    filehdr.f_timdat = 0x46cb5980;
1348	}
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;
1366
1367	/* next is the aouthdr */
1368	if(ofile->mh != NULL){
1369	    aouthdr.magic = PE32MAGIC;
1370	    aouthdr.vstamp = VSTAMP;
1371
1372      /*
1373       * EFI does not use t, d, or b size.
1374       * EFI uses SizeOfImage to errorcheck vaddrs in the image
1375       */
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);
1382		}
1383
1384	    aouthdr.entry = entry;
1385
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;
1393		    }
1394		    else{
1395			if(aouthdr.data_start == 0)
1396			    aouthdr.data_start = scnhdrs[i].s_vaddr;
1397		    }
1398		}
1399	    }
1400
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;
1411
1412
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;
1427	    }
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;
1432	    }
1433	}
1434	else{
1435	    aouthdr64.magic = PE32PMAGIC;
1436	    aouthdr64.vstamp = VSTAMP;
1437
1438      /*
1439       * EFI does not use t, d, or b size.
1440       * EFI uses SizeOfImage to errorcheck vaddrs in the image
1441       */
1442	    aouthdr64.tsize = 0;
1443	    aouthdr64.dsize = 0;
1444	    aouthdr64.bsize = 0;
1445
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);
1449	    }
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
1455
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;
1466		    }
1467		}
1468	    }
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
1474
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;
1485
1486
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;
1509	    }
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;
1514	    }
1515	}
1516
1517	/*
1518 	 * If there is a debug directory entry set the address and offsets in
1519	 * it now that the values are known.
1520	 */
1521	if(debug_filename != NULL)
1522	    set_debug_addrs_and_offsets();
1523}
1524
1525/*
1526 * create_output() takes the info gathered from the input Mach-O file and
1527 * creates the pecoff output file.
1528 */
1529static
1530void
1531create_output(
1532struct ofile *ofile,
1533char *out)
1534{
1535    int i, f;
1536    unsigned char *buf, *p, *p_aouthdr;
1537
1538	/*
1539	 * Allocate the buffer to place the pecoff file in.
1540	 */
1541	buf = calloc(1, output_size);
1542	if(buf == NULL)
1543	    fatal("Can't allocate buffer for output file (size = %u)",
1544		  output_size);
1545
1546	/*
1547	 * Copy the parts of the pecoff file into the buffer.
1548	 */
1549	p = buf;
1550
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);
1555
1556	memcpy(p, signature, sizeof(signature));
1557	p += sizeof(signature);
1558
1559	memcpy(p, &filehdr, sizeof(struct filehdr));
1560	if(swapped)
1561	    swap_filehdr((struct filehdr *)p, target_byte_sex);
1562	p += sizeof(struct filehdr);
1563
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);
1570	}
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);
1576	}
1577
1578	/*
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.
1582	 */
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
1592
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
1598	    }
1599	}
1600
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);
1605
1606	/*
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.
1610	 */
1611	memcpy(buf + syment_offset, syments, nsyments * sizeof(struct syment));
1612	memcpy(buf + string_offset, strings, strsize);
1613
1614	/*
1615	 * Now with the file contents complete compute the CheckSum in the
1616	 * optional header and update that in the output buffer.
1617	 */
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);
1623	}
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);
1629	}
1630
1631	/*
1632	 * Create the pecoff file and write the buffer to the file.
1633	 */
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);
1637
1638	if(write(f, buf, output_size) != output_size)
1639	    system_fatal("Can't write output file: %s", out);
1640
1641	if(close(f) == -1)
1642	    system_fatal("Can't close output file: %s", out);
1643}
1644
1645/*
1646 * create_ms_dos_stub() is pass a pointer to the buffer where to fill in the
1647 * MS-DOS stub.
1648 */
1649static
1650void
1651create_ms_dos_stub(
1652struct ms_dos_stub *p)
1653{
1654    int i;
1655
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;
1670
1671	for(i = 0; i < 4; i++)
1672	    p->e_res[i] = 0x0;
1673
1674	p->e_oemid   = 0x0;
1675	p->e_oeminfo = 0x0;
1676
1677	for(i = 0; i < 10; i++)
1678	    p->e_res2[i] = 0x0;
1679
1680	p->e_lfanew = 0x80;
1681
1682	/*
1683	 * The sub dos program that prints "This program cannot be run in DOS
1684	 * mode".
1685	 */
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;
1750}
1751
1752
1753/*
1754 * create_32bit_symbol_table() is called to process the input Mach-O file and
1755 * create the pecoff symbol and string table.
1756 */
1757static
1758void
1759create_32bit_symbol_table(
1760struct arch *arch)
1761{
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;
1776
1777	/*
1778	 * No symbols are actually needed in the pecoff file from the Mach-O
1779	 * file so create an empty symbol table.
1780	 */
1781	nsyments = 0;
1782
1783	/*
1784	 * Make sure the Mach-O file does not have any undefined symbols.
1785	 */
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);
1800		}
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);
1807	    }
1808	}
1809	if(found_undef == TRUE)
1810	    fatal("undefined symbols are unsupported for conversion to a "
1811		  "pecoff file");
1812
1813#ifdef HACK_TO_MATCH_TEST_CASE
1814	/*
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.
1819	 *
1820	 */
1821
1822	/*
1823	 * First figure out the section number of the common and bss sections
1824	 * and address of those sections.
1825	 */
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;
1842			}
1843			else if(strcmp(s->sectname, SECT_COMMON) == 0){
1844			    common_n_sect = n_sect;
1845			    common_addr = s->addr;
1846			}
1847			s++;
1848			n_sect++;
1849		    }
1850		}
1851		else{
1852		    n_sect += sg->nsects;
1853		}
1854	    }
1855	    lc = (struct load_command *)((char *)lc + lc->cmdsize);
1856	}
1857
1858	/*
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().
1862	 */
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;
1873		}
1874	    }
1875	}
1876#endif /* HACK_TO_MATCH_TEST_CASE */
1877
1878	/*
1879	 * Allocate space for the pecoff symbol table and string table.
1880	 */
1881	syments = allocate(nsyments * sizeof(struct syment));
1882	memset(syments, '\0', nsyments * sizeof(struct syment));
1883	strings = allocate(strsize);
1884
1885	/*
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.
1888	 */
1889	p = strings;
1890
1891	i = strsize;
1892	if(swapped)
1893	    i = SWAP_INT(i);
1894	memcpy(p, &i, sizeof(uint32_t));
1895	p += sizeof(uint32_t);
1896
1897	memcpy(p, section_names, section_names_size);
1898	p += section_names_size;
1899
1900#ifdef HACK_TO_MATCH_TEST_CASE
1901	/*
1902	 * First put in the bss symbols, again to match what is done by
1903	 * objcopy.
1904	 */
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;
1917		    }
1918		    else{
1919			strncpy(syments[j].e.e_name,
1920				strs + syms[i].n_un.n_strx, E_SYMNMLEN);
1921		    }
1922		}
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++;
1929	    }
1930	}
1931	/*
1932	 * Next put in the common symbols, again to match what is done by
1933	 * objcopy.
1934	 */
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;
1946		    }
1947		    else{
1948			strncpy(syments[j].e.e_name,
1949				strs + syms[i].n_un.n_strx, E_SYMNMLEN);
1950		    }
1951		}
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++;
1958	    }
1959	}
1960
1961	if(swapped)
1962	    swap_syment(syments, nsyments, target_byte_sex);
1963
1964#endif /* HACK_TO_MATCH_TEST_CASE */
1965}
1966
1967/*
1968 * create_64bit_symbol_table() is called to process the input Mach-O file and
1969 * create the pecoff symbol and string table.
1970 */
1971static
1972void
1973create_64bit_symbol_table(
1974struct arch *arch)
1975{
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;
1983
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);
1990	/*
1991	 * If the entry point option was specified then look for that symbol
1992	 * and set the entry point value.
1993	 */
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;
2001		}
2002	    }
2003	    if(i == st->nsyms)
2004		fatal("can't find symbol for -e %s in input file: %s",
2005		      entry_point, arch->file_name);
2006	}
2007
2008	/*
2009	 * Make sure the Mach-O file does not have any undefined symbols.
2010	 */
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);
2019		}
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);
2026	    }
2027	}
2028	if(found_undef == TRUE)
2029	    fatal("undefined symbols are unsupported for conversion to a "
2030		  "pecoff file");
2031
2032	/*
2033	 * No symbols are actually needed in the pecoff file from the Mach-O
2034	 * file so create an empty symbol table.
2035	 *
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().
2039	 */
2040	nsyments = 0;
2041	strings = allocate(strsize);
2042
2043	/*
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.
2046	 */
2047	p = strings;
2048
2049	i = strsize;
2050	if(swapped)
2051	    i = SWAP_INT(i);
2052	memcpy(p, &i, sizeof(uint32_t));
2053	p += sizeof(uint32_t);
2054
2055	memcpy(p, section_names, section_names_size);
2056}
2057
2058/*
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.
2061 */
2062static
2063void
2064create_base_reloc(
2065struct arch *arch)
2066{
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;
2075
2076    char *object_addr;
2077    struct dysymtab_command *dyst;
2078
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;
2085
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);
2115			}
2116		    }
2117		}
2118	    }
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) {
2122		    /*
2123		     * X86_64 relocations are relative to the first writable
2124		     * segment.
2125		     */
2126		    if((first_addr == 0) &&
2127		       ((sg64->initprot & VM_PROT_WRITE) != 0)) {
2128		      first_addr = sg64->vmaddr;
2129		    }
2130		} else {
2131		if(first_addr == 0)
2132		    first_addr = sg64->vmaddr;
2133		}
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);
2152			}
2153		    }
2154		}
2155	    }
2156	    lc = (struct load_command *)((char *)lc + lc->cmdsize);
2157	}
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);
2175	}
2176	/*
2177	if(dyst != NULL && dyst->nextrel != 0)
2178	    ; TODO error if there are external relocation entries */
2179
2180	/*
2181	 * Now with all the info gathered make the base relocation entries.
2182	 */
2183	make_base_relocs();
2184}
2185
2186/*
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.
2190 */
2191static
2192void
2193gather_base_reloc_info(
2194uint32_t addr,
2195struct relocation_info *relocs,
2196uint32_t nreloc,
2197cpu_type_t cpu_type,
2198uint32_t length,
2199int macho_reloc_type,
2200int base_reloc_type)
2201{
2202    uint32_t i, r_address, r_pcrel, r_length, r_extern, r_type;
2203    struct scattered_relocation_info *sreloc;
2204
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;
2213	    }
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;
2220	    }
2221
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 */
2227
2228	    if((relocs[i].r_address & R_SCATTERED) == 0){
2229		if(reloc_has_pair(cpu_type, relocs[i].r_type))
2230		    i++;
2231	    }
2232	    else{
2233		sreloc = (struct scattered_relocation_info *)relocs + i;
2234		if(reloc_has_pair(cpu_type, sreloc->r_type))
2235		    i++;
2236	    }
2237	}
2238}
2239
2240/*
2241 * add_base_reloc() is passed a addr and a type for a base relocation entry to
2242 * add to the list.
2243 */
2244static
2245void
2246add_base_reloc(
2247uint64_t addr,
2248uint32_t type)
2249{
2250    static int max = 0;
2251    struct base_reloc *new_base_relocs;
2252
2253	if(!max){
2254	    max = 128;
2255	    base_relocs = (struct base_reloc *)
2256			  malloc(max * sizeof(struct base_reloc));
2257	}
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;
2265	}
2266	base_relocs[nbase_reloc].addr = addr;
2267        base_relocs[nbase_reloc].type = type;
2268	nbase_reloc++;
2269}
2270
2271/*
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.
2276 */
2277#define MAX_BLOCK_OFFSET 0x1000
2278#define BLOCK_MASK (MAX_BLOCK_OFFSET-1)
2279
2280/*
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.
2285 */
2286static
2287void
2288make_base_relocs(
2289void)
2290{
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;
2299
2300	blockcnt = 0;
2301
2302	/*
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.
2306	 */
2307	reloc_size = 0;
2308	reloc_contents = NULL;
2309
2310	/*
2311	 * If there are no base relocation entries return so we don't create a
2312	 * base relocation block with 0 entries.
2313	 */
2314	if(nbase_reloc == 0)
2315	    return;
2316
2317	qsort(base_relocs, nbase_reloc, sizeof(struct base_reloc),
2318	      (int (*)(const void *, const void *))cmp_base_relocs);
2319
2320	/*
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.
2326	 */
2327	size = sizeof(struct base_relocation_block_header) +
2328	       (nbase_reloc + 1) * sizeof(struct base_relocation_entry);
2329	fb = malloc(size);
2330
2331
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++;
2345		}
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);
2355		}
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;
2360
2361		entries = 0;
2362		blockcnt++;
2363		base = base_relocs[i].addr & ~BLOCK_MASK;
2364		offset = base_relocs[i].addr - base;
2365	    }
2366	    b[entries].type = base_relocs[i].type;
2367	    b[entries].offset = offset;
2368	    entries++;
2369	}
2370
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++;
2376	}
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);
2384	}
2385
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;
2390
2391	blockcnt++;
2392	free(fb);
2393}
2394
2395static
2396int
2397cmp_base_relocs(
2398struct base_reloc *x1,
2399struct base_reloc *x2)
2400{
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);
2407}
2408
2409/*
2410 * create_debug() is called to create the .debug section contents from
2411 * the -d filename argument.
2412 */
2413static
2414void
2415create_debug(
2416struct arch *arch)
2417{
2418    char *p;
2419    uint32_t i, ncmds;
2420    struct load_command *lc;
2421    struct uuid_command *uuid;
2422
2423	/*
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.
2428	 */
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);
2434	/*
2435	 * Set up pointers to all the parts to be filled in.
2436	 */
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);
2442
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;
2450	/*
2451	 * These two will be filled in later when address and offsets
2452	 * are known.
2453	 */
2454	dde->AddressOfRawData = 0;
2455	dde->PointerToRawData = 0;
2456
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);
2468		}
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;
2486	    }
2487	    lc = (struct load_command *)((char *)lc + lc->cmdsize);
2488	}
2489
2490	strcpy(p, debug_filename);
2491}
2492
2493/*
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.
2498 */
2499static
2500void
2501set_debug_addrs_and_offsets(
2502void)
2503{
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);
2511	}
2512}
2513
2514/*
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.
2518 */
2519static
2520uint32_t
2521checksum(
2522unsigned char *buf)
2523{
2524    uint32_t i, v, t;
2525
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));
2534	}
2535	return(0xffff & (t + (t >> 0x10)));
2536}
2537
2538/*
2539 * string_to_uuid() creates a 128-bit uuid from a well-formatted UUID string
2540 * (i.e. aabbccdd-eeff-gghh-iijj-kkllmmnnoopp)
2541 */
2542static
2543void
2544string_to_uuid(
2545char *string,
2546uint8_t *uuid)
2547{
2548    uint8_t count;
2549
2550	/*
2551	* scanned bytewise to ensure correct endianness of fields
2552	*/
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]);
2559
2560	if (count != 16) {
2561	    fatal ("invalid UUID specified for -u option");
2562	}
2563}
2564