~ubuntu-branches/ubuntu/trusty/monodevelop/trusty-proposed

« back to all changes in this revision

Viewing changes to external/ikvm/reflect/Reader/PEReader.cs

  • Committer: Package Import Robot
  • Author(s): Jo Shields
  • Date: 2013-05-12 09:46:03 UTC
  • mto: This revision was merged to the branch mainline in revision 29.
  • Revision ID: package-import@ubuntu.com-20130512094603-mad323bzcxvmcam0
Tags: upstream-4.0.5+dfsg
ImportĀ upstreamĀ versionĀ 4.0.5+dfsg

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*
 
2
  Copyright (C) 2009 Jeroen Frijters
 
3
 
 
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.
 
7
 
 
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:
 
11
 
 
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.
 
19
 
 
20
  Jeroen Frijters
 
21
  jeroen@frijters.net
 
22
  
 
23
*/
 
24
using System;
 
25
using BYTE = System.Byte;
 
26
using WORD = System.UInt16;
 
27
using DWORD = System.UInt32;
 
28
using ULONGLONG = System.UInt64;
 
29
using System.IO;
 
30
 
 
31
namespace IKVM.Reflection.Reader
 
32
{
 
33
        sealed class MSDOS_HEADER
 
34
        {
 
35
                internal const WORD MAGIC_MZ = 0x5A4D;
 
36
 
 
37
                internal WORD signature;        // 'MZ'
 
38
                // skip 58 bytes
 
39
                internal DWORD peSignatureOffset;
 
40
        }
 
41
 
 
42
        sealed class IMAGE_NT_HEADERS
 
43
        {
 
44
                public const DWORD MAGIC_SIGNATURE = 0x00004550;        // "PE\0\0"
 
45
 
 
46
                public DWORD Signature;
 
47
                public IMAGE_FILE_HEADER FileHeader = new IMAGE_FILE_HEADER();
 
48
                public IMAGE_OPTIONAL_HEADER OptionalHeader = new IMAGE_OPTIONAL_HEADER();
 
49
 
 
50
                internal void Read(BinaryReader br)
 
51
                {
 
52
                        Signature = br.ReadUInt32();
 
53
                        if (Signature != IMAGE_NT_HEADERS.MAGIC_SIGNATURE)
 
54
                        {
 
55
                                throw new BadImageFormatException();
 
56
                        }
 
57
                        FileHeader.Read(br);
 
58
                        OptionalHeader.Read(br);
 
59
                }
 
60
        }
 
61
 
 
62
        sealed class IMAGE_FILE_HEADER
 
63
        {
 
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;
 
67
 
 
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;
 
72
 
 
73
                public WORD Machine;
 
74
                public WORD NumberOfSections;
 
75
                public DWORD TimeDateStamp;
 
76
                public DWORD PointerToSymbolTable;
 
77
                public DWORD NumberOfSymbols;
 
78
                public WORD SizeOfOptionalHeader;
 
79
                public WORD Characteristics;
 
80
 
 
81
                internal void Read(BinaryReader br)
 
82
                {
 
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();
 
90
                }
 
91
        }
 
92
 
 
93
        sealed class IMAGE_OPTIONAL_HEADER
 
94
        {
 
95
                public const WORD IMAGE_NT_OPTIONAL_HDR32_MAGIC = 0x10b;
 
96
                public const WORD IMAGE_NT_OPTIONAL_HDR64_MAGIC = 0x20b;
 
97
 
 
98
                public const WORD IMAGE_SUBSYSTEM_WINDOWS_GUI = 2;
 
99
                public const WORD IMAGE_SUBSYSTEM_WINDOWS_CUI = 3;
 
100
 
 
101
                public WORD Magic;
 
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;
 
132
 
 
133
                internal void Read(BinaryReader br)
 
134
                {
 
135
                        Magic = br.ReadUInt16();
 
136
                        if (Magic != IMAGE_NT_OPTIONAL_HDR32_MAGIC && Magic != IMAGE_NT_OPTIONAL_HDR64_MAGIC)
 
137
                        {
 
138
                                throw new BadImageFormatException();
 
139
                        }
 
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)
 
148
                        {
 
149
                                BaseOfData = br.ReadUInt32();
 
150
                                ImageBase = br.ReadUInt32();
 
151
                        }
 
152
                        else
 
153
                        {
 
154
                                ImageBase = br.ReadUInt64();
 
155
                        }
 
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)
 
171
                        {
 
172
                                SizeOfStackReserve = br.ReadUInt32();
 
173
                                SizeOfStackCommit = br.ReadUInt32();
 
174
                                SizeOfHeapReserve = br.ReadUInt32();
 
175
                                SizeOfHeapCommit = br.ReadUInt32();
 
176
                        }
 
177
                        else
 
178
                        {
 
179
                                SizeOfStackReserve = br.ReadUInt64();
 
180
                                SizeOfStackCommit = br.ReadUInt64();
 
181
                                SizeOfHeapReserve = br.ReadUInt64();
 
182
                                SizeOfHeapCommit = br.ReadUInt64();
 
183
                        }
 
184
                        LoaderFlags = br.ReadUInt32();
 
185
                        NumberOfRvaAndSizes = br.ReadUInt32();
 
186
                        DataDirectory = new IMAGE_DATA_DIRECTORY[NumberOfRvaAndSizes];
 
187
                        for (uint i = 0; i < NumberOfRvaAndSizes; i++)
 
188
                        {
 
189
                                DataDirectory[i] = new IMAGE_DATA_DIRECTORY();
 
190
                                DataDirectory[i].Read(br);
 
191
                        }
 
192
                }
 
193
        }
 
194
 
 
195
        struct IMAGE_DATA_DIRECTORY
 
196
        {
 
197
                public DWORD VirtualAddress;
 
198
                public DWORD Size;
 
199
 
 
200
                internal void Read(BinaryReader br)
 
201
                {
 
202
                        VirtualAddress = br.ReadUInt32();
 
203
                        Size = br.ReadUInt32();
 
204
                }
 
205
        }
 
206
 
 
207
        class SectionHeader
 
208
        {
 
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;
 
215
 
 
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;
 
226
 
 
227
                internal void Read(BinaryReader br)
 
228
                {
 
229
                        char[] name = new char[8];
 
230
                        int len = 8;
 
231
                        for (int i = 0; i < 8; i++)
 
232
                        {
 
233
                                byte b = br.ReadByte();
 
234
                                name[i] = (char)b;
 
235
                                if (b == 0 && len == 8)
 
236
                                {
 
237
                                        len = i;
 
238
                                }
 
239
                        }
 
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();
 
250
                }
 
251
        }
 
252
 
 
253
        sealed class PEReader
 
254
        {
 
255
                private MSDOS_HEADER msdos = new MSDOS_HEADER();
 
256
                private IMAGE_NT_HEADERS headers = new IMAGE_NT_HEADERS();
 
257
                private SectionHeader[] sections;
 
258
 
 
259
                internal void Read(BinaryReader br)
 
260
                {
 
261
                        msdos.signature = br.ReadUInt16();
 
262
                        br.BaseStream.Seek(58, SeekOrigin.Current);
 
263
                        msdos.peSignatureOffset = br.ReadUInt32();
 
264
 
 
265
                        if (msdos.signature != MSDOS_HEADER.MAGIC_MZ)
 
266
                        {
 
267
                                throw new BadImageFormatException();
 
268
                        }
 
269
 
 
270
                        br.BaseStream.Seek(msdos.peSignatureOffset, SeekOrigin.Begin);
 
271
                        headers.Read(br);
 
272
                        sections = new SectionHeader[headers.FileHeader.NumberOfSections];
 
273
                        for (int i = 0; i < sections.Length; i++)
 
274
                        {
 
275
                                sections[i] = new SectionHeader();
 
276
                                sections[i].Read(br);
 
277
                        }
 
278
                }
 
279
 
 
280
                internal IMAGE_FILE_HEADER FileHeader
 
281
                {
 
282
                        get { return headers.FileHeader; }
 
283
                }
 
284
 
 
285
                internal IMAGE_OPTIONAL_HEADER OptionalHeader
 
286
                {
 
287
                        get { return headers.OptionalHeader; }
 
288
                }
 
289
 
 
290
                internal DWORD GetComDescriptorVirtualAddress()
 
291
                {
 
292
                        return headers.OptionalHeader.DataDirectory[14].VirtualAddress;
 
293
                }
 
294
 
 
295
                internal void GetDataDirectoryEntry(int index, out int rva, out int length)
 
296
                {
 
297
                        rva = (int)headers.OptionalHeader.DataDirectory[index].VirtualAddress;
 
298
                        length = (int)headers.OptionalHeader.DataDirectory[index].Size;
 
299
                }
 
300
 
 
301
                internal long RvaToFileOffset(DWORD rva)
 
302
                {
 
303
                        for (int i = 0; i < sections.Length; i++)
 
304
                        {
 
305
                                if (rva >= sections[i].VirtualAddress && rva < sections[i].VirtualAddress + sections[i].VirtualSize)
 
306
                                {
 
307
                                        return sections[i].PointerToRawData + rva - sections[i].VirtualAddress;
 
308
                                }
 
309
                        }
 
310
                        throw new BadImageFormatException();
 
311
                }
 
312
 
 
313
                internal bool GetSectionInfo(int rva, out string name, out int characteristics)
 
314
                {
 
315
                        for (int i = 0; i < sections.Length; i++)
 
316
                        {
 
317
                                if (rva >= sections[i].VirtualAddress && rva < sections[i].VirtualAddress + sections[i].VirtualSize)
 
318
                                {
 
319
                                        name = sections[i].Name;
 
320
                                        characteristics = (int)sections[i].Characteristics;
 
321
                                        return true;
 
322
                                }
 
323
                        }
 
324
                        name = null;
 
325
                        characteristics = 0;
 
326
                        return false;
 
327
                }
 
328
        }
 
329
}