99#include <stdio.h>
1010#include <stdlib.h>
1111#include <string.h>
12+ #include <errno.h>
1213
1314// host_includes
1415#include <typedefs.h>
@@ -33,14 +34,14 @@ FindFileHeaderFromDosHeader(PIMAGE_DOS_HEADER PeBase)
3334{
3435 PIMAGE_FILE_HEADER FileHeader ;
3536 PUINT Signature ;
36-
37+
3738 Signature = (PUINT ) (((PUCHAR ) PeBase ) + PeBase -> e_lfanew );
38-
39+
3940 if (* Signature != IMAGE_NT_SIGNATURE )
4041 {
4142 return NULL ;
4243 }
43-
44+
4445 FileHeader = (PIMAGE_FILE_HEADER ) (Signature + 1 );
4546 return FileHeader ;
4647}
@@ -50,84 +51,93 @@ PIMAGE_OPTIONAL_HEADER32
5051FindOptionalHeaderFromFileHeader (PIMAGE_FILE_HEADER FileHeader )
5152{
5253 PIMAGE_OPTIONAL_HEADER32 OptionalHeader ;
53-
54- OptionalHeader = (PIMAGE_OPTIONAL_HEADER32 ) (((PUCHAR ) FileHeader ) + sizeof (IMAGE_FILE_HEADER ));
54+
55+ OptionalHeader = (PIMAGE_OPTIONAL_HEADER32 ) (((PUCHAR ) FileHeader )
56+ + sizeof (IMAGE_FILE_HEADER ));
5557 if (OptionalHeader -> Magic != IMAGE_NT_OPTIONAL_HDR32_MAGIC )
5658 {
5759 return NULL ;
5860 }
61+
5962 return OptionalHeader ;
6063}
6164
6265static
6366PMACHO_HEADER
6467CreateMachOHeaderFromPeHeader (PIMAGE_OPTIONAL_HEADER32 OptionalHeader ,
65- UINT32 PeSize ,
66- PUINT MachoHeaderSize )
68+ UINT32 PeSize ,
69+ PUINT MachoHeaderSize )
6770{
6871 PMACHO_HEADER MachoHeader ;
6972 PMACHO_SEGMENT_COMMAND MachoSegmentCommand ;
70- PMACHO_THREAD_COMMAND_X86 MachoUnixThread ;
71-
73+ PMACHO_THREAD_COMMAND_I386 MachoUnixThread ;
74+
7275 * MachoHeaderSize = sizeof (MACHO_HEADER )
73- + sizeof (MACHO_SEGMENT_COMMAND )
74- + sizeof (MACHO_THREAD_COMMAND_X86 );
75-
76+ + sizeof (MACHO_SEGMENT_COMMAND )
77+ + sizeof (MACHO_THREAD_COMMAND_I386 );
78+
7679 MachoHeader = calloc (1 , * MachoHeaderSize );
7780 if (!MachoHeader )
7881 {
79- fprintf (stderr , "Could not allocate %d bytes for Mach-O info\n" , * MachoHeaderSize );
82+ fprintf (stderr , "Could not allocate %d bytes for Mach-O info\n" ,
83+ * MachoHeaderSize );
8084 return NULL ;
8185 }
82-
86+
8387 // Fill out Mach-O header.
8488 MachoHeader -> MagicNumber = MACHO_MAGIC ;
85-
89+
8690 MachoHeader -> CpuType = 7 ; // x86
8791 MachoHeader -> CpuSubtype = 3 ; // all x86
88-
92+
8993 MachoHeader -> FileType = 2 ; // kernel (static linked)
90-
94+
9195 MachoHeader -> NumberOfCmds = 2 ;
9296 MachoHeader -> SizeOfCmds = * MachoHeaderSize - sizeof (MACHO_HEADER );
93-
97+
9498 MachoHeader -> Flags = 1 ;
95-
99+
96100 // Fill out first load command.
97- MachoSegmentCommand = (PMACHO_SEGMENT_COMMAND ) (((PUCHAR ) MachoHeader ) + sizeof (MACHO_HEADER ));
98-
101+ MachoSegmentCommand = (PMACHO_SEGMENT_COMMAND ) (((PUCHAR ) MachoHeader )
102+ + sizeof (MACHO_HEADER ));
103+
99104 MachoSegmentCommand -> Command = MACHO_LC_SEGMENT ;
100105 MachoSegmentCommand -> CommandSize = sizeof (MACHO_SEGMENT_COMMAND );
101-
106+
102107 strcpy (MachoSegmentCommand -> SegmentName , "__PE_FILE__" );
103-
108+
104109 MachoSegmentCommand -> VMAddress = OptionalHeader -> ImageBase ;
105-
106- /*
107- * SizeOfImage should always be a multiple of SectionAlignment, but it isn't on GCC and boot.efi wants it to
108- * also be aligned to the EFI page size (0x1000), plus one so that BootArgs is allocated correctly.
110+
111+ /*
112+ * SizeOfImage should always be a multiple of SectionAlignment, but it isn't on GCC and
113+ * boot.efi wants it to also be aligned to the EFI page size (0x1000), plus one so that
114+ * BootArgs is allocated correctly.
109115 */
110- MachoSegmentCommand -> VMSize = ROUND_UP (OptionalHeader -> SizeOfImage , EFI_PAGE_SIZE ) + 1 ;
111-
116+
117+ MachoSegmentCommand -> VMSize = ROUND_UP (OptionalHeader -> SizeOfImage ,
118+ EFI_PAGE_SIZE ) + 1 ;
119+
112120 MachoSegmentCommand -> FileOffset = HEADER_ADDITIONAL_BYTES ;
113121 MachoSegmentCommand -> FileSize = PeSize ;
114-
122+
115123 MachoSegmentCommand -> MaximumProtection = 7 ; // ???
116124 MachoSegmentCommand -> InitialProtection = 5 ; // ???
117-
125+
118126 MachoSegmentCommand -> NumberOfSections = 0 ;
119127 MachoSegmentCommand -> Flags = 0 ;
120-
121- MachoUnixThread = (PMACHO_THREAD_COMMAND_X86 ) (((PUCHAR ) MachoSegmentCommand ) + sizeof (MACHO_SEGMENT_COMMAND ));
122-
123- MachoUnixThread -> Command = MACHO_LC_UNIXTHREAD ;
124- MachoUnixThread -> CommandSize = sizeof (MACHO_THREAD_COMMAND_X86 );
125- MachoUnixThread -> Flavor = i386_THREAD_STATE ;
126- MachoUnixThread -> Count = i386_THREAD_STATE_COUNT ;
127-
128+
129+ MachoUnixThread = (PMACHO_THREAD_COMMAND_I386 ) (((PUCHAR ) MachoSegmentCommand )
130+ + sizeof (MACHO_SEGMENT_COMMAND ));
131+
132+ MachoUnixThread -> Command = MACHO_LC_UNIXTHREAD ;
133+ MachoUnixThread -> CommandSize = sizeof (MACHO_THREAD_COMMAND_I386 );
134+ MachoUnixThread -> Flavor = i386_THREAD_STATE ;
135+ MachoUnixThread -> Count = i386_THREAD_STATE_COUNT ;
136+
128137 // all registers are blank except for EIP, which is the entry point!
129- MachoUnixThread -> State .Eip = OptionalHeader -> ImageBase + OptionalHeader -> AddressOfEntryPoint ;
130-
138+ MachoUnixThread -> State .Eip = OptionalHeader -> ImageBase +
139+ OptionalHeader -> AddressOfEntryPoint ;
140+
131141 return MachoHeader ;
132142}
133143
@@ -138,83 +148,85 @@ main(INT argc, PCHAR argv[])
138148 UINT32 InputFileLength , OutputFileLength ;
139149 PUCHAR InputFileBuffer , OutputFileBuffer ;
140150 UINT32 ObjectsWritten ;
141-
151+
142152 PIMAGE_FILE_HEADER PeFileHeader ;
143153 PIMAGE_OPTIONAL_HEADER32 PeOptionalHeader ;
144-
154+
145155 PMACHO_HEADER MachoHeader ;
146156 UINT32 MachoHeaderSize ;
147-
148-
157+
158+
149159 // Check arguments
150160 if (argc != 3 )
151161 {
152162 fprintf (stderr , "Usage: pe2macho [input file] [output file]\n" );
153163 return 1 ;
154164 }
155-
165+
156166 // Open file
157167 InputFile = fopen (argv [1 ], "rb" );
158168 if (!InputFile )
159169 {
160- fprintf (stderr , "Cannot find input file!\n" );
170+ fprintf (stderr , "Cannot find input file '%s': %s\n" ,
171+ argv [1 ], strerror (errno ));
161172 return 2 ;
162173 }
163-
174+
164175 // Find end of file
165176 fseek (InputFile , 0 , SEEK_END );
166177 InputFileLength = ftell (InputFile );
167178 fseek (InputFile , 0 , SEEK_SET );
168-
179+
169180 InputFileBuffer = malloc (InputFileLength + 1 );
170181 if (!InputFileBuffer )
171182 {
172183 fprintf (stderr , "Could not allocate %d bytes for input file\n" , InputFileLength + 1 );
173184 fclose (InputFile );
174185 return 3 ;
175186 }
176-
187+
177188 // Read contents of file into buffer and then close file
178189 fread (InputFileBuffer , InputFileLength , 1 , InputFile );
179190 fclose (InputFile );
180-
191+
181192 // Find DOS header
182193 if (((PIMAGE_DOS_HEADER ) InputFileBuffer )-> e_magic != IMAGE_DOS_MAGIC )
183194 {
184- fprintf (stderr , "Input file not a valid MZ image. (expected 0x%X, got 0x%X)\n" , IMAGE_DOS_MAGIC , ((PIMAGE_DOS_HEADER )InputFileBuffer )-> e_magic );
195+ fprintf (stderr , "Input file not a valid MZ image. (expected 0x%X, got 0x%X)\n" ,
196+ IMAGE_DOS_MAGIC , ((PIMAGE_DOS_HEADER )InputFileBuffer )-> e_magic );
185197 return 4 ;
186198 }
187-
199+
188200 // Find PE/COFF file header
189201 PeFileHeader = FindFileHeaderFromDosHeader ((PIMAGE_DOS_HEADER ) InputFileBuffer );
190202 if (!PeFileHeader )
191203 {
192204 fprintf (stderr , "Input file not a valid PE/COFF image!\n" );
193205 return 5 ;
194206 }
195-
207+
196208 // Check arch
197209 if (PeFileHeader -> Machine != IMAGE_FILE_MACHINE_I386 )
198210 {
199- fprintf (stderr , "Only 32 bit x86 executables are supported at this time.\n" );
211+ fprintf (stderr , "Only i386 executables are supported at this time.\n" );
200212 return 6 ;
201213 }
202-
214+
203215 // Make sure there's an optional header
204216 if (!PeFileHeader -> SizeOfOptionalHeader )
205217 {
206218 fprintf (stderr , "No optional header found!\n" );
207219 return 7 ;
208220 }
209-
221+
210222 // Find optional header
211223 PeOptionalHeader = FindOptionalHeaderFromFileHeader (PeFileHeader );
212224 if (!PeOptionalHeader )
213225 {
214226 fprintf (stderr , "Invalid optional header!\n" );
215227 return 8 ;
216228 }
217-
229+
218230 // Convert PE executable header to Mach-O
219231 MachoHeader = CreateMachOHeaderFromPeHeader (PeOptionalHeader ,
220232 InputFileLength ,
@@ -224,40 +236,48 @@ main(INT argc, PCHAR argv[])
224236 fprintf (stderr , "Failed to create Mach-O header!\n" );
225237 return 9 ;
226238 }
227-
239+
228240 // Allocate new buffer for output file
229241 OutputFileLength = InputFileLength + HEADER_ADDITIONAL_BYTES ;
230242 OutputFileBuffer = calloc (1 , OutputFileLength );
231243 if (!OutputFileBuffer )
232244 {
233- fprintf (stderr , "Failed to allocate %d bytes for output file\n" , OutputFileLength );
245+ fprintf (stderr , "Failed to allocate %d bytes for output file\n" ,
246+ OutputFileLength );
234247 return 10 ;
235248 }
236-
249+
237250 // Copy Mach-O header to top of buffer
238- memcpy (OutputFileBuffer , MachoHeader , MachoHeaderSize );
239-
251+ memcpy (OutputFileBuffer ,
252+ MachoHeader ,
253+ MachoHeaderSize );
254+
240255 // Copy output file 4096 bytes in
241256 // It will be loaded at its original load addr
242- memcpy (OutputFileBuffer + HEADER_ADDITIONAL_BYTES , InputFileBuffer , InputFileLength );
243-
257+ memcpy (OutputFileBuffer + HEADER_ADDITIONAL_BYTES ,
258+ InputFileBuffer ,
259+ InputFileLength );
260+
244261 // Open output file
245262 OutputFile = fopen (argv [2 ], "wb" );
246263 if (!OutputFile )
247264 {
248- fprintf (stderr , "Cannot open output file: %s\n" , argv [2 ]);
265+ fprintf (stderr , "Cannot open output file %s: %s\n" ,
266+ argv [2 ], strerror (errno ));
249267 return 11 ;
250268 }
251-
269+
252270 ObjectsWritten = fwrite (OutputFileBuffer , OutputFileLength , 1 , OutputFile );
253271 if (!ObjectsWritten )
254272 {
255- fprintf (stderr , "Cannot write to output file: %s\n" , argv [2 ]);
273+ fprintf (stderr , "Cannot write to output file %s: %s\n" ,
274+ argv [2 ], strerror (errno ));
256275 fclose (OutputFile );
257276 return 12 ;
258277 }
259-
278+
260279 fclose (OutputFile );
261- printf ("Successfully converted PE image %s to Mach-O image %s\n" , argv [1 ], argv [2 ]);
280+ printf ("Successfully converted PE image %s to Mach-O image %s\n" ,
281+ argv [1 ], argv [2 ]);
262282 return 0 ;
263283}
0 commit comments