2
Copyright (C) 2009 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.
25
using BYTE = System.Byte;
26
using WORD = System.UInt16;
27
using DWORD = System.UInt32;
28
using ULONGLONG = System.UInt64;
31
namespace IKVM.Reflection.Reader
33
sealed class MSDOS_HEADER
35
internal const WORD MAGIC_MZ = 0x5A4D;
37
internal WORD signature; // 'MZ'
39
internal DWORD peSignatureOffset;
42
sealed class IMAGE_NT_HEADERS
44
public const DWORD MAGIC_SIGNATURE = 0x00004550; // "PE\0\0"
46
public DWORD Signature;
47
public IMAGE_FILE_HEADER FileHeader = new IMAGE_FILE_HEADER();
48
public IMAGE_OPTIONAL_HEADER OptionalHeader = new IMAGE_OPTIONAL_HEADER();
50
internal void Read(BinaryReader br)
52
Signature = br.ReadUInt32();
53
if (Signature != IMAGE_NT_HEADERS.MAGIC_SIGNATURE)
55
throw new BadImageFormatException();
58
OptionalHeader.Read(br);
62
sealed class IMAGE_FILE_HEADER
64
public const WORD IMAGE_FILE_MACHINE_I386 = 0x014c;
65
public const WORD IMAGE_FILE_MACHINE_IA64 = 0x0200;
66
public const WORD IMAGE_FILE_MACHINE_AMD64 = 0x8664;
68
public const WORD IMAGE_FILE_32BIT_MACHINE = 0x0100;
69
public const WORD IMAGE_FILE_EXECUTABLE_IMAGE = 0x0002;
70
public const WORD IMAGE_FILE_LARGE_ADDRESS_AWARE = 0x0020;
71
public const WORD IMAGE_FILE_DLL = 0x2000;
74
public WORD NumberOfSections;
75
public DWORD TimeDateStamp;
76
public DWORD PointerToSymbolTable;
77
public DWORD NumberOfSymbols;
78
public WORD SizeOfOptionalHeader;
79
public WORD Characteristics;
81
internal void Read(BinaryReader br)
83
Machine = br.ReadUInt16();
84
NumberOfSections = br.ReadUInt16();
85
TimeDateStamp = br.ReadUInt32();
86
PointerToSymbolTable = br.ReadUInt32();
87
NumberOfSymbols = br.ReadUInt32();
88
SizeOfOptionalHeader = br.ReadUInt16();
89
Characteristics = br.ReadUInt16();
93
sealed class IMAGE_OPTIONAL_HEADER
95
public const WORD IMAGE_NT_OPTIONAL_HDR32_MAGIC = 0x10b;
96
public const WORD IMAGE_NT_OPTIONAL_HDR64_MAGIC = 0x20b;
98
public const WORD IMAGE_SUBSYSTEM_WINDOWS_GUI = 2;
99
public const WORD IMAGE_SUBSYSTEM_WINDOWS_CUI = 3;
102
public BYTE MajorLinkerVersion;
103
public BYTE MinorLinkerVersion;
104
public DWORD SizeOfCode;
105
public DWORD SizeOfInitializedData;
106
public DWORD SizeOfUninitializedData;
107
public DWORD AddressOfEntryPoint;
108
public DWORD BaseOfCode;
109
public DWORD BaseOfData;
110
public ULONGLONG ImageBase;
111
public DWORD SectionAlignment;
112
public DWORD FileAlignment;
113
public WORD MajorOperatingSystemVersion;
114
public WORD MinorOperatingSystemVersion;
115
public WORD MajorImageVersion;
116
public WORD MinorImageVersion;
117
public WORD MajorSubsystemVersion;
118
public WORD MinorSubsystemVersion;
119
public DWORD Win32VersionValue;
120
public DWORD SizeOfImage;
121
public DWORD SizeOfHeaders;
122
public DWORD CheckSum;
123
public WORD Subsystem;
124
public WORD DllCharacteristics;
125
public ULONGLONG SizeOfStackReserve;
126
public ULONGLONG SizeOfStackCommit;
127
public ULONGLONG SizeOfHeapReserve;
128
public ULONGLONG SizeOfHeapCommit;
129
public DWORD LoaderFlags;
130
public DWORD NumberOfRvaAndSizes;
131
public IMAGE_DATA_DIRECTORY[] DataDirectory;
133
internal void Read(BinaryReader br)
135
Magic = br.ReadUInt16();
136
if (Magic != IMAGE_NT_OPTIONAL_HDR32_MAGIC && Magic != IMAGE_NT_OPTIONAL_HDR64_MAGIC)
138
throw new BadImageFormatException();
140
MajorLinkerVersion = br.ReadByte();
141
MinorLinkerVersion = br.ReadByte();
142
SizeOfCode = br.ReadUInt32();
143
SizeOfInitializedData = br.ReadUInt32();
144
SizeOfUninitializedData = br.ReadUInt32();
145
AddressOfEntryPoint = br.ReadUInt32();
146
BaseOfCode = br.ReadUInt32();
147
if (Magic == IMAGE_NT_OPTIONAL_HDR32_MAGIC)
149
BaseOfData = br.ReadUInt32();
150
ImageBase = br.ReadUInt32();
154
ImageBase = br.ReadUInt64();
156
SectionAlignment = br.ReadUInt32();
157
FileAlignment = br.ReadUInt32();
158
MajorOperatingSystemVersion = br.ReadUInt16();
159
MinorOperatingSystemVersion = br.ReadUInt16();
160
MajorImageVersion = br.ReadUInt16();
161
MinorImageVersion = br.ReadUInt16();
162
MajorSubsystemVersion = br.ReadUInt16();
163
MinorSubsystemVersion = br.ReadUInt16();
164
Win32VersionValue = br.ReadUInt32();
165
SizeOfImage = br.ReadUInt32();
166
SizeOfHeaders = br.ReadUInt32();
167
CheckSum = br.ReadUInt32();
168
Subsystem = br.ReadUInt16();
169
DllCharacteristics = br.ReadUInt16();
170
if (Magic == IMAGE_NT_OPTIONAL_HDR32_MAGIC)
172
SizeOfStackReserve = br.ReadUInt32();
173
SizeOfStackCommit = br.ReadUInt32();
174
SizeOfHeapReserve = br.ReadUInt32();
175
SizeOfHeapCommit = br.ReadUInt32();
179
SizeOfStackReserve = br.ReadUInt64();
180
SizeOfStackCommit = br.ReadUInt64();
181
SizeOfHeapReserve = br.ReadUInt64();
182
SizeOfHeapCommit = br.ReadUInt64();
184
LoaderFlags = br.ReadUInt32();
185
NumberOfRvaAndSizes = br.ReadUInt32();
186
DataDirectory = new IMAGE_DATA_DIRECTORY[NumberOfRvaAndSizes];
187
for (uint i = 0; i < NumberOfRvaAndSizes; i++)
189
DataDirectory[i] = new IMAGE_DATA_DIRECTORY();
190
DataDirectory[i].Read(br);
195
struct IMAGE_DATA_DIRECTORY
197
public DWORD VirtualAddress;
200
internal void Read(BinaryReader br)
202
VirtualAddress = br.ReadUInt32();
203
Size = br.ReadUInt32();
209
public const DWORD IMAGE_SCN_CNT_CODE = 0x00000020;
210
public const DWORD IMAGE_SCN_CNT_INITIALIZED_DATA = 0x00000040;
211
public const DWORD IMAGE_SCN_MEM_DISCARDABLE = 0x02000000;
212
public const DWORD IMAGE_SCN_MEM_EXECUTE = 0x20000000;
213
public const DWORD IMAGE_SCN_MEM_READ = 0x40000000;
214
public const DWORD IMAGE_SCN_MEM_WRITE = 0x80000000;
216
public string Name; // 8 byte UTF8 encoded 0-padded
217
public DWORD VirtualSize;
218
public DWORD VirtualAddress;
219
public DWORD SizeOfRawData;
220
public DWORD PointerToRawData;
221
public DWORD PointerToRelocations;
222
public DWORD PointerToLinenumbers;
223
public WORD NumberOfRelocations;
224
public WORD NumberOfLinenumbers;
225
public DWORD Characteristics;
227
internal void Read(BinaryReader br)
229
char[] name = new char[8];
231
for (int i = 0; i < 8; i++)
233
byte b = br.ReadByte();
235
if (b == 0 && len == 8)
240
Name = new String(name, 0, len);
241
VirtualSize = br.ReadUInt32();
242
VirtualAddress = br.ReadUInt32();
243
SizeOfRawData = br.ReadUInt32();
244
PointerToRawData = br.ReadUInt32();
245
PointerToRelocations = br.ReadUInt32();
246
PointerToLinenumbers = br.ReadUInt32();
247
NumberOfRelocations = br.ReadUInt16();
248
NumberOfLinenumbers = br.ReadUInt16();
249
Characteristics = br.ReadUInt32();
253
sealed class PEReader
255
private MSDOS_HEADER msdos = new MSDOS_HEADER();
256
private IMAGE_NT_HEADERS headers = new IMAGE_NT_HEADERS();
257
private SectionHeader[] sections;
259
internal void Read(BinaryReader br)
261
msdos.signature = br.ReadUInt16();
262
br.BaseStream.Seek(58, SeekOrigin.Current);
263
msdos.peSignatureOffset = br.ReadUInt32();
265
if (msdos.signature != MSDOS_HEADER.MAGIC_MZ)
267
throw new BadImageFormatException();
270
br.BaseStream.Seek(msdos.peSignatureOffset, SeekOrigin.Begin);
272
sections = new SectionHeader[headers.FileHeader.NumberOfSections];
273
for (int i = 0; i < sections.Length; i++)
275
sections[i] = new SectionHeader();
276
sections[i].Read(br);
280
internal IMAGE_FILE_HEADER FileHeader
282
get { return headers.FileHeader; }
285
internal IMAGE_OPTIONAL_HEADER OptionalHeader
287
get { return headers.OptionalHeader; }
290
internal DWORD GetComDescriptorVirtualAddress()
292
return headers.OptionalHeader.DataDirectory[14].VirtualAddress;
295
internal void GetDataDirectoryEntry(int index, out int rva, out int length)
297
rva = (int)headers.OptionalHeader.DataDirectory[index].VirtualAddress;
298
length = (int)headers.OptionalHeader.DataDirectory[index].Size;
301
internal long RvaToFileOffset(DWORD rva)
303
for (int i = 0; i < sections.Length; i++)
305
if (rva >= sections[i].VirtualAddress && rva < sections[i].VirtualAddress + sections[i].VirtualSize)
307
return sections[i].PointerToRawData + rva - sections[i].VirtualAddress;
310
throw new BadImageFormatException();
313
internal bool GetSectionInfo(int rva, out string name, out int characteristics)
315
for (int i = 0; i < sections.Length; i++)
317
if (rva >= sections[i].VirtualAddress && rva < sections[i].VirtualAddress + sections[i].VirtualSize)
319
name = sections[i].Name;
320
characteristics = (int)sections[i].Characteristics;