2 Copyright (C) 2008 Jeroen Frijters
4 This software is provided 'as-is', without any express or implied
5 warranty. In no event will the authors be held liable for any damages
6 arising from the use of this software.
8 Permission is granted to anyone to use this software for any purpose,
9 including commercial applications, and to alter it and redistribute it
10 freely, subject to the following restrictions:
12 1. The origin of this software must not be misrepresented; you must not
13 claim that you wrote the original software. If you use this software
14 in a product, an acknowledgment in the product documentation would be
15 appreciated but is not required.
16 2. Altered source versions must be plainly marked as such, and must not be
17 misrepresented as being the original software.
18 3. This notice may not be removed or altered from any source distribution.
26 using BYTE = System.Byte;
27 using WORD = System.UInt16;
28 using DWORD = System.UInt32;
29 using ULONGLONG = System.UInt64;
31 namespace IKVM.Reflection.Writer
35 private readonly BinaryWriter bw;
36 private readonly IMAGE_NT_HEADERS hdr = new IMAGE_NT_HEADERS();
38 internal PEWriter(Stream stream)
40 bw = new BinaryWriter(stream);
44 public IMAGE_NT_HEADERS Headers
49 public uint HeaderSize
54 ((8 * 16) + // MSDOS header
56 20 + // IMAGE_FILE_HEADER
57 hdr.FileHeader.SizeOfOptionalHeader +
58 hdr.FileHeader.NumberOfSections * 40);
62 private void WriteMSDOSHeader()
65 0x4D, 0x5A, 0x90, 0x00, 0x03, 0x00, 0x00, 0x00,
66 0x04, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0x00, 0x00,
67 0xB8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
68 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
69 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
70 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
71 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
72 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00,
73 0x0E, 0x1F, 0xBA, 0x0E, 0x00, 0xB4, 0x09, 0xCD,
74 0x21, 0xB8, 0x01, 0x4C, 0xCD, 0x21, 0x54, 0x68,
75 0x69, 0x73, 0x20, 0x70, 0x72, 0x6F, 0x67, 0x72,
76 0x61, 0x6D, 0x20, 0x63, 0x61, 0x6E, 0x6E, 0x6F,
77 0x74, 0x20, 0x62, 0x65, 0x20, 0x72, 0x75, 0x6E,
78 0x20, 0x69, 0x6E, 0x20, 0x44, 0x4F, 0x53, 0x20,
79 0x6D, 0x6F, 0x64, 0x65, 0x2E, 0x0D, 0x0D, 0x0A,
80 0x24, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
84 internal void WritePEHeaders()
86 bw.Write(hdr.Signature);
89 bw.Write(hdr.FileHeader.Machine);
90 bw.Write(hdr.FileHeader.NumberOfSections);
91 bw.Write(hdr.FileHeader.TimeDateStamp);
92 bw.Write(hdr.FileHeader.PointerToSymbolTable);
93 bw.Write(hdr.FileHeader.NumberOfSymbols);
94 bw.Write(hdr.FileHeader.SizeOfOptionalHeader);
95 bw.Write(hdr.FileHeader.Characteristics);
97 // IMAGE_OPTIONAL_HEADER
98 hdr.OptionalHeader.Write(bw);
101 internal void WriteSectionHeader(SectionHeader sectionHeader)
103 byte[] name = new byte[8];
104 System.Text.Encoding.UTF8.GetBytes(sectionHeader.Name, 0, sectionHeader.Name.Length, name, 0);
106 bw.Write(sectionHeader.VirtualSize);
107 bw.Write(sectionHeader.VirtualAddress);
108 bw.Write(sectionHeader.SizeOfRawData);
109 bw.Write(sectionHeader.PointerToRawData);
110 bw.Write(sectionHeader.PointerToRelocations);
111 bw.Write(sectionHeader.PointerToLinenumbers);
112 bw.Write(sectionHeader.NumberOfRelocations);
113 bw.Write(sectionHeader.NumberOfLinenumbers);
114 bw.Write(sectionHeader.Characteristics);
117 internal uint ToFileAlignment(uint p)
119 return (p + (Headers.OptionalHeader.FileAlignment - 1)) & ~(Headers.OptionalHeader.FileAlignment - 1);
122 internal uint ToSectionAlignment(uint p)
124 return (p + (Headers.OptionalHeader.SectionAlignment - 1)) & ~(Headers.OptionalHeader.SectionAlignment - 1);
128 sealed class IMAGE_NT_HEADERS
130 public DWORD Signature = 0x00004550; // "PE\0\0"
131 public IMAGE_FILE_HEADER FileHeader = new IMAGE_FILE_HEADER();
132 public IMAGE_OPTIONAL_HEADER OptionalHeader = new IMAGE_OPTIONAL_HEADER();
135 sealed class IMAGE_FILE_HEADER
137 public const WORD IMAGE_FILE_MACHINE_I386 = 0x014c;
138 public const WORD IMAGE_FILE_MACHINE_IA64 = 0x0200;
139 public const WORD IMAGE_FILE_MACHINE_AMD64 = 0x8664;
141 public const WORD IMAGE_FILE_32BIT_MACHINE = 0x0100;
142 public const WORD IMAGE_FILE_EXECUTABLE_IMAGE = 0x0002;
143 public const WORD IMAGE_FILE_LARGE_ADDRESS_AWARE = 0x0020;
144 public const WORD IMAGE_FILE_DLL = 0x2000;
147 public WORD NumberOfSections;
148 public DWORD TimeDateStamp = (uint)(DateTime.UtcNow - new DateTime(1970, 1, 1, 0, 0, 0, DateTimeKind.Utc)).TotalSeconds;
149 public DWORD PointerToSymbolTable = 0;
150 public DWORD NumberOfSymbols = 0;
151 public WORD SizeOfOptionalHeader = 0xE0;
152 public WORD Characteristics = IMAGE_FILE_EXECUTABLE_IMAGE;
155 sealed class IMAGE_OPTIONAL_HEADER
157 public const WORD IMAGE_NT_OPTIONAL_HDR32_MAGIC = 0x10b;
158 public const WORD IMAGE_NT_OPTIONAL_HDR64_MAGIC = 0x20b;
160 public const WORD IMAGE_SUBSYSTEM_WINDOWS_GUI = 2;
161 public const WORD IMAGE_SUBSYSTEM_WINDOWS_CUI = 3;
163 public const WORD IMAGE_DLLCHARACTERISTICS_DYNAMIC_BASE = 0x0040;
164 public const WORD IMAGE_DLLCHARACTERISTICS_NX_COMPAT = 0x0100;
165 public const WORD IMAGE_DLLCHARACTERISTICS_NO_SEH = 0x0400;
166 public const WORD IMAGE_DLLCHARACTERISTICS_TERMINAL_SERVER_AWARE = 0x8000;
168 public WORD Magic = IMAGE_NT_OPTIONAL_HDR32_MAGIC;
169 public BYTE MajorLinkerVersion = 8;
170 public BYTE MinorLinkerVersion = 0;
171 public DWORD SizeOfCode;
172 public DWORD SizeOfInitializedData;
173 public DWORD SizeOfUninitializedData;
174 public DWORD AddressOfEntryPoint;
175 public DWORD BaseOfCode;
176 public DWORD BaseOfData;
177 public ULONGLONG ImageBase;
178 public DWORD SectionAlignment = 0x2000;
179 public DWORD FileAlignment = 0x200;
180 public WORD MajorOperatingSystemVersion = 4;
181 public WORD MinorOperatingSystemVersion = 0;
182 public WORD MajorImageVersion = 0;
183 public WORD MinorImageVersion = 0;
184 public WORD MajorSubsystemVersion = 4;
185 public WORD MinorSubsystemVersion = 0;
186 public DWORD Win32VersionValue = 0;
187 public DWORD SizeOfImage;
188 public DWORD SizeOfHeaders;
189 public DWORD CheckSum = 0;
190 public WORD Subsystem;
191 public WORD DllCharacteristics;
192 public ULONGLONG SizeOfStackReserve;
193 public ULONGLONG SizeOfStackCommit = 0x1000;
194 public ULONGLONG SizeOfHeapReserve = 0x100000;
195 public ULONGLONG SizeOfHeapCommit = 0x1000;
196 public DWORD LoaderFlags = 0;
197 public DWORD NumberOfRvaAndSizes = 16;
198 public IMAGE_DATA_DIRECTORY[] DataDirectory = new IMAGE_DATA_DIRECTORY[16];
200 internal void Write(BinaryWriter bw)
203 bw.Write(MajorLinkerVersion);
204 bw.Write(MinorLinkerVersion);
205 bw.Write(SizeOfCode);
206 bw.Write(SizeOfInitializedData);
207 bw.Write(SizeOfUninitializedData);
208 bw.Write(AddressOfEntryPoint);
209 bw.Write(BaseOfCode);
210 if (Magic == IMAGE_NT_OPTIONAL_HDR32_MAGIC)
212 bw.Write(BaseOfData);
213 bw.Write((DWORD)ImageBase);
219 bw.Write(SectionAlignment);
220 bw.Write(FileAlignment);
221 bw.Write(MajorOperatingSystemVersion);
222 bw.Write(MinorOperatingSystemVersion);
223 bw.Write(MajorImageVersion);
224 bw.Write(MinorImageVersion);
225 bw.Write(MajorSubsystemVersion);
226 bw.Write(MinorSubsystemVersion);
227 bw.Write(Win32VersionValue);
228 bw.Write(SizeOfImage);
229 bw.Write(SizeOfHeaders);
232 bw.Write(DllCharacteristics);
233 if (Magic == IMAGE_NT_OPTIONAL_HDR32_MAGIC)
235 bw.Write((DWORD)SizeOfStackReserve);
239 bw.Write(SizeOfStackReserve);
241 if (Magic == IMAGE_NT_OPTIONAL_HDR32_MAGIC)
243 bw.Write((DWORD)SizeOfStackCommit);
247 bw.Write(SizeOfStackCommit);
249 if (Magic == IMAGE_NT_OPTIONAL_HDR32_MAGIC)
251 bw.Write((DWORD)SizeOfHeapReserve);
255 bw.Write(SizeOfHeapReserve);
257 if (Magic == IMAGE_NT_OPTIONAL_HDR32_MAGIC)
259 bw.Write((DWORD)SizeOfHeapCommit);
263 bw.Write(SizeOfHeapCommit);
265 bw.Write(LoaderFlags);
266 bw.Write(NumberOfRvaAndSizes);
267 for (int i = 0; i < DataDirectory.Length; i++)
269 bw.Write(DataDirectory[i].VirtualAddress);
270 bw.Write(DataDirectory[i].Size);
275 struct IMAGE_DATA_DIRECTORY
277 public DWORD VirtualAddress;
283 public const DWORD IMAGE_SCN_CNT_CODE = 0x00000020;
284 public const DWORD IMAGE_SCN_CNT_INITIALIZED_DATA = 0x00000040;
285 public const DWORD IMAGE_SCN_MEM_DISCARDABLE = 0x02000000;
286 public const DWORD IMAGE_SCN_MEM_EXECUTE = 0x20000000;
287 public const DWORD IMAGE_SCN_MEM_READ = 0x40000000;
288 public const DWORD IMAGE_SCN_MEM_WRITE = 0x80000000;
290 public string Name; // 8 byte UTF8 encoded 0-padded
291 public DWORD VirtualSize;
292 public DWORD VirtualAddress;
293 public DWORD SizeOfRawData;
294 public DWORD PointerToRawData;
295 #pragma warning disable 649 // the follow fields are never assigned to
296 public DWORD PointerToRelocations;
297 public DWORD PointerToLinenumbers;
298 public WORD NumberOfRelocations;
299 public WORD NumberOfLinenumbers;
300 #pragma warning restore 649
301 public DWORD Characteristics;