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;
30 using IMAGE_DATA_DIRECTORY = IKVM.Reflection.Reader.IMAGE_DATA_DIRECTORY;
32 namespace IKVM.Reflection.Writer
36 private readonly BinaryWriter bw;
37 private readonly IMAGE_NT_HEADERS hdr = new IMAGE_NT_HEADERS();
39 internal PEWriter(Stream stream)
41 bw = new BinaryWriter(stream);
45 public IMAGE_NT_HEADERS Headers
50 public uint HeaderSize
55 ((8 * 16) + // MSDOS header
57 20 + // IMAGE_FILE_HEADER
58 hdr.FileHeader.SizeOfOptionalHeader +
59 hdr.FileHeader.NumberOfSections * 40);
63 private void WriteMSDOSHeader()
66 0x4D, 0x5A, 0x90, 0x00, 0x03, 0x00, 0x00, 0x00,
67 0x04, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0x00, 0x00,
68 0xB8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
69 0x40, 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, 0x00, 0x00, 0x00, 0x00,
73 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00,
74 0x0E, 0x1F, 0xBA, 0x0E, 0x00, 0xB4, 0x09, 0xCD,
75 0x21, 0xB8, 0x01, 0x4C, 0xCD, 0x21, 0x54, 0x68,
76 0x69, 0x73, 0x20, 0x70, 0x72, 0x6F, 0x67, 0x72,
77 0x61, 0x6D, 0x20, 0x63, 0x61, 0x6E, 0x6E, 0x6F,
78 0x74, 0x20, 0x62, 0x65, 0x20, 0x72, 0x75, 0x6E,
79 0x20, 0x69, 0x6E, 0x20, 0x44, 0x4F, 0x53, 0x20,
80 0x6D, 0x6F, 0x64, 0x65, 0x2E, 0x0D, 0x0D, 0x0A,
81 0x24, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
85 internal void WritePEHeaders()
87 bw.Write(hdr.Signature);
90 bw.Write(hdr.FileHeader.Machine);
91 bw.Write(hdr.FileHeader.NumberOfSections);
92 bw.Write(hdr.FileHeader.TimeDateStamp);
93 bw.Write(hdr.FileHeader.PointerToSymbolTable);
94 bw.Write(hdr.FileHeader.NumberOfSymbols);
95 bw.Write(hdr.FileHeader.SizeOfOptionalHeader);
96 bw.Write(hdr.FileHeader.Characteristics);
98 // IMAGE_OPTIONAL_HEADER
99 hdr.OptionalHeader.Write(bw);
102 internal void WriteSectionHeader(SectionHeader sectionHeader)
104 byte[] name = new byte[8];
105 System.Text.Encoding.UTF8.GetBytes(sectionHeader.Name, 0, sectionHeader.Name.Length, name, 0);
107 bw.Write(sectionHeader.VirtualSize);
108 bw.Write(sectionHeader.VirtualAddress);
109 bw.Write(sectionHeader.SizeOfRawData);
110 bw.Write(sectionHeader.PointerToRawData);
111 bw.Write(sectionHeader.PointerToRelocations);
112 bw.Write(sectionHeader.PointerToLinenumbers);
113 bw.Write(sectionHeader.NumberOfRelocations);
114 bw.Write(sectionHeader.NumberOfLinenumbers);
115 bw.Write(sectionHeader.Characteristics);
118 internal uint ToFileAlignment(uint p)
120 return (p + (Headers.OptionalHeader.FileAlignment - 1)) & ~(Headers.OptionalHeader.FileAlignment - 1);
123 internal uint ToSectionAlignment(uint p)
125 return (p + (Headers.OptionalHeader.SectionAlignment - 1)) & ~(Headers.OptionalHeader.SectionAlignment - 1);
129 sealed class IMAGE_NT_HEADERS
131 public DWORD Signature = 0x00004550; // "PE\0\0"
132 public IMAGE_FILE_HEADER FileHeader = new IMAGE_FILE_HEADER();
133 public IMAGE_OPTIONAL_HEADER OptionalHeader = new IMAGE_OPTIONAL_HEADER();
136 sealed class IMAGE_FILE_HEADER
138 public const WORD IMAGE_FILE_MACHINE_I386 = 0x014c;
139 public const WORD IMAGE_FILE_MACHINE_ARM = 0x01c4;
140 public const WORD IMAGE_FILE_MACHINE_IA64 = 0x0200;
141 public const WORD IMAGE_FILE_MACHINE_AMD64 = 0x8664;
143 public const WORD IMAGE_FILE_32BIT_MACHINE = 0x0100;
144 public const WORD IMAGE_FILE_EXECUTABLE_IMAGE = 0x0002;
145 public const WORD IMAGE_FILE_LARGE_ADDRESS_AWARE = 0x0020;
146 public const WORD IMAGE_FILE_DLL = 0x2000;
149 public WORD NumberOfSections;
150 public DWORD TimeDateStamp = (uint)(DateTime.UtcNow - new DateTime(1970, 1, 1, 0, 0, 0, DateTimeKind.Utc)).TotalSeconds;
151 public DWORD PointerToSymbolTable = 0;
152 public DWORD NumberOfSymbols = 0;
153 public WORD SizeOfOptionalHeader = 0xE0;
154 public WORD Characteristics = IMAGE_FILE_EXECUTABLE_IMAGE;
157 sealed class IMAGE_OPTIONAL_HEADER
159 public const WORD IMAGE_NT_OPTIONAL_HDR32_MAGIC = 0x10b;
160 public const WORD IMAGE_NT_OPTIONAL_HDR64_MAGIC = 0x20b;
162 public const WORD IMAGE_SUBSYSTEM_WINDOWS_GUI = 2;
163 public const WORD IMAGE_SUBSYSTEM_WINDOWS_CUI = 3;
165 public WORD Magic = IMAGE_NT_OPTIONAL_HDR32_MAGIC;
166 public BYTE MajorLinkerVersion = 8;
167 public BYTE MinorLinkerVersion = 0;
168 public DWORD SizeOfCode;
169 public DWORD SizeOfInitializedData;
170 public DWORD SizeOfUninitializedData;
171 public DWORD AddressOfEntryPoint;
172 public DWORD BaseOfCode;
173 public DWORD BaseOfData;
174 public ULONGLONG ImageBase;
175 public DWORD SectionAlignment = 0x2000;
176 public DWORD FileAlignment;
177 public WORD MajorOperatingSystemVersion = 4;
178 public WORD MinorOperatingSystemVersion = 0;
179 public WORD MajorImageVersion = 0;
180 public WORD MinorImageVersion = 0;
181 public WORD MajorSubsystemVersion = 4;
182 public WORD MinorSubsystemVersion = 0;
183 public DWORD Win32VersionValue = 0;
184 public DWORD SizeOfImage;
185 public DWORD SizeOfHeaders;
186 public DWORD CheckSum = 0;
187 public WORD Subsystem;
188 public WORD DllCharacteristics;
189 public ULONGLONG SizeOfStackReserve;
190 public ULONGLONG SizeOfStackCommit = 0x1000;
191 public ULONGLONG SizeOfHeapReserve = 0x100000;
192 public ULONGLONG SizeOfHeapCommit = 0x1000;
193 public DWORD LoaderFlags = 0;
194 public DWORD NumberOfRvaAndSizes = 16;
195 public IMAGE_DATA_DIRECTORY[] DataDirectory = new IMAGE_DATA_DIRECTORY[16];
197 internal void Write(BinaryWriter bw)
200 bw.Write(MajorLinkerVersion);
201 bw.Write(MinorLinkerVersion);
202 bw.Write(SizeOfCode);
203 bw.Write(SizeOfInitializedData);
204 bw.Write(SizeOfUninitializedData);
205 bw.Write(AddressOfEntryPoint);
206 bw.Write(BaseOfCode);
207 if (Magic == IMAGE_NT_OPTIONAL_HDR32_MAGIC)
209 bw.Write(BaseOfData);
210 bw.Write((DWORD)ImageBase);
216 bw.Write(SectionAlignment);
217 bw.Write(FileAlignment);
218 bw.Write(MajorOperatingSystemVersion);
219 bw.Write(MinorOperatingSystemVersion);
220 bw.Write(MajorImageVersion);
221 bw.Write(MinorImageVersion);
222 bw.Write(MajorSubsystemVersion);
223 bw.Write(MinorSubsystemVersion);
224 bw.Write(Win32VersionValue);
225 bw.Write(SizeOfImage);
226 bw.Write(SizeOfHeaders);
229 bw.Write(DllCharacteristics);
230 if (Magic == IMAGE_NT_OPTIONAL_HDR32_MAGIC)
232 bw.Write((DWORD)SizeOfStackReserve);
236 bw.Write(SizeOfStackReserve);
238 if (Magic == IMAGE_NT_OPTIONAL_HDR32_MAGIC)
240 bw.Write((DWORD)SizeOfStackCommit);
244 bw.Write(SizeOfStackCommit);
246 if (Magic == IMAGE_NT_OPTIONAL_HDR32_MAGIC)
248 bw.Write((DWORD)SizeOfHeapReserve);
252 bw.Write(SizeOfHeapReserve);
254 if (Magic == IMAGE_NT_OPTIONAL_HDR32_MAGIC)
256 bw.Write((DWORD)SizeOfHeapCommit);
260 bw.Write(SizeOfHeapCommit);
262 bw.Write(LoaderFlags);
263 bw.Write(NumberOfRvaAndSizes);
264 for (int i = 0; i < DataDirectory.Length; i++)
266 bw.Write(DataDirectory[i].VirtualAddress);
267 bw.Write(DataDirectory[i].Size);
274 public const DWORD IMAGE_SCN_CNT_CODE = 0x00000020;
275 public const DWORD IMAGE_SCN_CNT_INITIALIZED_DATA = 0x00000040;
276 public const DWORD IMAGE_SCN_MEM_DISCARDABLE = 0x02000000;
277 public const DWORD IMAGE_SCN_MEM_EXECUTE = 0x20000000;
278 public const DWORD IMAGE_SCN_MEM_READ = 0x40000000;
279 public const DWORD IMAGE_SCN_MEM_WRITE = 0x80000000;
281 public string Name; // 8 byte UTF8 encoded 0-padded
282 public DWORD VirtualSize;
283 public DWORD VirtualAddress;
284 public DWORD SizeOfRawData;
285 public DWORD PointerToRawData;
286 #pragma warning disable 649 // the follow fields are never assigned to
287 public DWORD PointerToRelocations;
288 public DWORD PointerToLinenumbers;
289 public WORD NumberOfRelocations;
290 public WORD NumberOfLinenumbers;
291 #pragma warning restore 649
292 public DWORD Characteristics;