Skip to content

Commit 72f8ff4

Browse files
[PE2MACHO] Refactor pe2macho
1 parent 99783df commit 72f8ff4

2 files changed

Lines changed: 104 additions & 79 deletions

File tree

sdk/tools/pe2macho/macho.h

Lines changed: 14 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,8 @@
1818
#define i386_THREAD_STATE 1
1919

2020
/* Mach-O header */
21-
typedef struct {
21+
typedef struct
22+
{
2223
UINT32 MagicNumber; /* Mach-O magic number. */
2324

2425
INT32 CpuType; /* CPU type */
@@ -32,7 +33,8 @@ typedef struct {
3233
UINT32 Flags; /* Executable flags */
3334
} MACHO_HEADER, *PMACHO_HEADER;
3435

35-
typedef struct {
36+
typedef struct
37+
{
3638
UINT32 Command; /* LC_SEGMENT */
3739
UINT32 CommandSize; /* Size of segment command */
3840

@@ -52,7 +54,8 @@ typedef struct {
5254
UINT32 Flags; /* Segment flags */
5355
} MACHO_SEGMENT_COMMAND, *PMACHO_SEGMENT_COMMAND;
5456

55-
typedef struct {
57+
typedef struct
58+
{
5659
UINT32 Eax;
5760
UINT32 Ebx;
5861
UINT32 Ecx;
@@ -69,20 +72,22 @@ typedef struct {
6972
UINT32 Es;
7073
UINT32 Fs;
7174
UINT32 Gs;
72-
} MACHO_THREAD_STATE_32;
75+
} MACHO_THREAD_STATE_I386;
7376

74-
typedef struct {
77+
typedef struct
78+
{
7579
UINT32 Command; /* LC_UNIXTHREAD */
7680
UINT32 CommandSize; /* Size of segment command */
7781
UINT32 Flavor; /* Architecture of thread state */
7882
UINT32 Count; /* Size of saved state */
79-
80-
MACHO_THREAD_STATE_32 State; /* State */
81-
} MACHO_THREAD_COMMAND_X86, *PMACHO_THREAD_COMMAND_X86;
83+
84+
MACHO_THREAD_STATE_I386 State; /* State */
85+
} MACHO_THREAD_COMMAND_I386, *PMACHO_THREAD_COMMAND_I386;
8286

8387
#define i386_THREAD_STATE_COUNT 16
8488

85-
typedef struct {
89+
typedef struct
90+
{
8691
char SectionName[16]; /* Name of this section */
8792
char SegmentName[16]; /* Segment this section goes in */
8893

sdk/tools/pe2macho/pe2macho.c

Lines changed: 90 additions & 70 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
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
5051
FindOptionalHeaderFromFileHeader(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

6265
static
6366
PMACHO_HEADER
6467
CreateMachOHeaderFromPeHeader(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

Comments
 (0)