3 // Permission is hereby granted, free of charge, to any person obtaining
\r
4 // a copy of this software and associated documentation files (the
\r
5 // "Software"), to deal in the Software without restriction, including
\r
6 // without limitation the rights to use, copy, modify, merge, publish,
\r
7 // distribute, sublicense, and/or sell copies of the Software, and to
\r
8 // permit persons to whom the Software is furnished to do so, subject to
\r
9 // the following conditions:
\r
11 // The above copyright notice and this permission notice shall be
\r
12 // included in all copies or substantial portions of the Software.
\r
14 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
\r
15 // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
\r
16 // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
\r
17 // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
\r
18 // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
\r
19 // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
\r
20 // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
\r
23 * Copyright (c) 2002 Sergey Chaban <serge@wildwestsoftware.com>
\r
28 using System.Runtime.InteropServices;
\r
30 namespace Mono.PEToolkit {
\r
32 // IMAGE_OPTIONAL_HEADER
\r
33 public class PEHeader {
\r
36 /// Standard PE/COFF fields.
\r
38 public class StdFields {
\r
39 internal short magic; // always 0x10B?
\r
40 internal byte lMajor;
\r
41 internal byte lMinor;
\r
42 internal uint codeSize;
\r
43 internal uint initDataSize;
\r
44 internal uint uninitDataSize;
\r
45 internal RVA entryRVA;
\r
46 internal RVA codeBase;
\r
47 internal RVA dataBase;
\r
54 public StdFields (BinaryReader reader)
\r
59 public void Read (BinaryReader reader)
\r
61 magic = reader.ReadInt16 ();
\r
62 lMajor = reader.ReadByte ();
\r
63 lMinor = reader.ReadByte ();
\r
64 codeSize = reader.ReadUInt32 ();
\r
65 initDataSize = reader.ReadUInt32 ();
\r
66 uninitDataSize = reader.ReadUInt32 ();
\r
67 entryRVA = new RVA (reader.ReadUInt32 ());
\r
68 codeBase = new RVA (reader.ReadUInt32 ());
\r
69 dataBase = new RVA (reader.ReadUInt32 ());
\r
72 public void Write (BinaryWriter writer)
\r
74 writer.Write (magic);
\r
75 writer.Write (lMajor);
\r
76 writer.Write (lMinor);
\r
77 writer.Write (codeSize);
\r
78 writer.Write (initDataSize);
\r
79 writer.Write (uninitDataSize);
\r
80 entryRVA.Write (writer);
\r
81 codeBase.Write (writer);
\r
82 dataBase.Write (writer);
\r
85 public string LinkerVersion {
\r
87 return String.Format("{0}.{1}", lMajor, lMinor);
\r
91 public override string ToString() {
\r
92 return String.Format(
\r
93 "Magic : 0x{0}" + Environment.NewLine +
\r
94 "Linker ver. : {1}" + Environment.NewLine +
\r
95 "Size of code : {2}" + Environment.NewLine +
\r
96 "Size of initialized data : {3}" + Environment.NewLine +
\r
97 "Size of uinitialized data (BSS) : {4}" + Environment.NewLine,
\r
98 magic.ToString("X"), LinkerVersion,
\r
99 codeSize, initDataSize, uninitDataSize
\r
106 /// Windows-specific fields.
\r
109 /// See Partition II, 24.2.3.2
\r
111 public class NTFields {
\r
112 internal uint imgBase;
\r
113 internal uint sectAlign;
\r
114 internal uint fileAlign;
\r
115 internal short osMaj;
\r
116 internal short osMin;
\r
117 internal short imgMaj;
\r
118 internal short imgMin;
\r
119 internal short subSysMaj;
\r
120 internal short subSysMin;
\r
121 internal int reserved_win32ver;
\r
122 internal uint imgSize;
\r
123 internal uint hdrSize;
\r
124 internal uint chksum;
\r
125 internal Subsystem subSys;
\r
126 internal short dllFlags;
\r
127 internal uint stackRes;
\r
128 internal uint stackCommit;
\r
129 internal uint heapRes;
\r
130 internal uint heapCommit;
\r
131 internal uint ldrFlags;
\r
132 internal uint numDirs;
\r
139 public NTFields (BinaryReader reader)
\r
144 public void Read (BinaryReader reader)
\r
146 imgBase = reader.ReadUInt32 ();
\r
147 sectAlign = reader.ReadUInt32 ();
\r
148 fileAlign = reader.ReadUInt32 ();
\r
149 osMaj = reader.ReadInt16 ();
\r
150 osMin = reader.ReadInt16 ();
\r
151 imgMaj = reader.ReadInt16 ();
\r
152 imgMin = reader.ReadInt16 ();
\r
153 subSysMaj = reader.ReadInt16 ();
\r
154 subSysMin = reader.ReadInt16 ();
\r
155 reserved_win32ver = reader.ReadInt32 ();
\r
156 imgSize = reader.ReadUInt32 ();
\r
157 hdrSize = reader.ReadUInt32 ();
\r
158 chksum = reader.ReadUInt32 ();
\r
159 subSys = (Subsystem) reader.ReadInt16 ();
\r
160 dllFlags = reader.ReadInt16 ();
\r
161 stackRes = reader.ReadUInt32 ();
\r
162 stackCommit = reader.ReadUInt32 ();
\r
163 heapRes = reader.ReadUInt32 ();
\r
164 heapCommit = reader.ReadUInt32 ();
\r
165 ldrFlags = reader.ReadUInt32 ();
\r
166 numDirs = reader.ReadUInt32 ();
\r
169 public void Write (BinaryWriter writer)
\r
171 writer.Write (imgBase);
\r
172 writer.Write (sectAlign);
\r
173 writer.Write (fileAlign);
\r
174 writer.Write (osMaj);
\r
175 writer.Write (osMin);
\r
176 writer.Write (imgMaj);
\r
177 writer.Write (imgMin);
\r
178 writer.Write (subSysMaj);
\r
179 writer.Write (subSysMin);
\r
180 writer.Write (reserved_win32ver);
\r
181 writer.Write (imgSize);
\r
182 writer.Write (hdrSize);
\r
183 writer.Write (chksum);
\r
184 writer.Write ((short)subSys);
\r
185 writer.Write (dllFlags);
\r
186 writer.Write (stackRes);
\r
187 writer.Write (stackCommit);
\r
188 writer.Write (heapRes);
\r
189 writer.Write (heapCommit);
\r
190 writer.Write (ldrFlags);
\r
191 writer.Write (numDirs);
\r
194 public string OSVersion {
\r
196 return String.Format("{0}.{1}", osMaj, osMin);
\r
200 public string ImageVersion {
\r
202 return String.Format("{0}.{1}", imgMaj, imgMin);
\r
206 public string SubsysVersion {
\r
208 return String.Format("{0}.{1}", subSysMaj, subSysMin);
\r
215 /// <returns></returns>
\r
216 public override string ToString() {
\r
217 return String.Format(
\r
218 "Image Base : 0x{0}" + Environment.NewLine +
\r
219 "Section Alignment : 0x{1}" + Environment.NewLine +
\r
220 "File Alignment : 0x{2}" + Environment.NewLine +
\r
221 "OS Version : {3}" + Environment.NewLine +
\r
222 "Image Version : {4}" + Environment.NewLine +
\r
223 "Subsystem Version : {5}" + Environment.NewLine +
\r
224 "Reserved/Win32Ver : {6}" + Environment.NewLine +
\r
225 "Image Size : {7}" + Environment.NewLine +
\r
226 "Header Size : {8}" + Environment.NewLine +
\r
227 "Checksum : 0x{9}" + Environment.NewLine +
\r
228 "Subsystem : {10}" + Environment.NewLine +
\r
229 "DLL Flags : {11}" + Environment.NewLine +
\r
230 "Stack Reserve Size : 0x{12}" + Environment.NewLine +
\r
231 "Stack Commit Size : 0x{13}" + Environment.NewLine +
\r
232 "Heap Reserve Size : 0x{14}" + Environment.NewLine +
\r
233 "Heap Commit Size : 0x{15}" + Environment.NewLine +
\r
234 "Loader Flags : {16}" + Environment.NewLine +
\r
235 "Number of Directories : {17}" + Environment.NewLine,
\r
236 imgBase.ToString("X"), sectAlign.ToString("X"), fileAlign.ToString("X"),
\r
237 OSVersion, ImageVersion, SubsysVersion,
\r
239 imgSize, hdrSize, chksum.ToString("X"), subSys, dllFlags,
\r
240 stackRes.ToString("X"), stackCommit.ToString("X"), heapRes.ToString("X"), heapCommit.ToString ("X"),
\r
247 internal StdFields stdFlds;
\r
248 internal NTFields ntFlds;
\r
250 internal DataDir exportDir;
\r
251 internal DataDir importDir;
\r
252 internal DataDir resourceDir;
\r
253 internal DataDir exceptionDir;
\r
254 internal DataDir securityDir;
\r
255 internal DataDir baseRelocDir;
\r
256 internal DataDir debugDir;
\r
257 internal DataDir copyrightDir;
\r
258 internal DataDir GPDir;
\r
259 internal DataDir TLSDir;
\r
260 internal DataDir loadCfgDir;
\r
261 internal DataDir boundImpDir;
\r
262 internal DataDir IATDir;
\r
263 internal DataDir delayImpDir;
\r
264 internal DataDir CLIHdrDir;
\r
265 internal DataDir reservedDir;
\r
268 public bool IsCLIImage {
\r
270 return (CLIHdrDir.virtAddr.Value != 0);
\r
276 // Accessors for standard COFF fields.
\r
279 public short Magic {
\r
281 return stdFlds.magic;
\r
284 stdFlds.magic = value;
\r
288 public byte MajorLinkerVersion {
\r
290 return stdFlds.lMajor;
\r
293 stdFlds.lMajor = value;
\r
297 public byte MinorLinkerVersion {
\r
299 return stdFlds.lMinor;
\r
302 stdFlds.lMinor = value;
\r
306 public uint SizeOfCode {
\r
308 return stdFlds.codeSize;
\r
311 stdFlds.codeSize = value;
\r
315 public uint SizeOfInitializedData {
\r
317 return stdFlds.initDataSize;
\r
320 stdFlds.initDataSize = value;
\r
324 public uint SizeOfUninitializedData {
\r
326 return stdFlds.uninitDataSize;
\r
329 stdFlds.uninitDataSize = value;
\r
333 public RVA AddressOfEntryPoint {
\r
335 return stdFlds.entryRVA;
\r
338 stdFlds.entryRVA.value = value.value;
\r
342 public RVA BaseOfCode {
\r
344 return stdFlds.codeBase;
\r
347 stdFlds.codeBase.value = value.value;
\r
351 public RVA BaseOfData {
\r
353 return stdFlds.dataBase;
\r
356 stdFlds.dataBase.value = value.value;
\r
362 // Accessors for Windows-specific fields.
\r
367 /// Preferred address of image when loaded into memory.
\r
371 /// This is a linear address and not RVA,
\r
372 /// and must be a multiple of 64K.
\r
375 /// Table in the Partition II states that for CIL images
\r
376 /// it must be 0x400000.
\r
379 public uint ImageBase {
\r
381 return ntFlds.imgBase;
\r
384 ntFlds.imgBase = value;
\r
389 /// Alignment of section when loaded into memory.
\r
392 /// Must be greater or equal to FileAlignment.
\r
393 /// Default is the native page size.
\r
394 /// According to specs for CIL images it must be set to 8K.
\r
396 public uint SectionAlignment {
\r
398 return ntFlds.sectAlign;
\r
401 ntFlds.sectAlign = value;
\r
406 /// Byte alignment of pages in image file.
\r
409 /// Valid values are powers of 2 between 512 and 64K.
\r
410 /// For CIL images it must be either 512 or 4K.
\r
412 public uint FileAlignment {
\r
414 return ntFlds.fileAlign;
\r
417 ntFlds.fileAlign = value;
\r
422 public short MajorOperatingSystemVersion {
\r
424 return ntFlds.osMaj;
\r
427 ntFlds.osMaj = value;
\r
431 public short MinorOperatingSystemVersion {
\r
433 return ntFlds.osMin;
\r
436 ntFlds.osMin = value;
\r
440 public short MajorImageVersion {
\r
442 return ntFlds.imgMaj;
\r
445 ntFlds.imgMaj = value;
\r
449 public short MinorImageVersion {
\r
451 return ntFlds.imgMin;
\r
454 ntFlds.imgMin = value;
\r
458 public short MajorSubsystemVersion {
\r
460 return ntFlds.subSysMaj;
\r
463 ntFlds.subSysMaj = value;
\r
467 public short MinorSubsystemVersion {
\r
469 return ntFlds.subSysMin;
\r
472 ntFlds.subSysMin = value;
\r
476 public int Win32VersionValue {
\r
478 return ntFlds.reserved_win32ver;
\r
481 ntFlds.reserved_win32ver = value;
\r
485 public int Reserved {
\r
487 return ntFlds.reserved_win32ver;
\r
490 ntFlds.reserved_win32ver = value;
\r
494 public uint SizeOfImage {
\r
496 return ntFlds.imgSize;
\r
499 ntFlds.imgSize = value;
\r
503 public uint SizeOfHeaders {
\r
505 return ntFlds.hdrSize;
\r
508 ntFlds.hdrSize = value;
\r
512 public uint CheckSum {
\r
514 return ntFlds.chksum;
\r
517 ntFlds.chksum = value;
\r
521 public Subsystem Subsystem {
\r
523 return ntFlds.subSys;
\r
526 ntFlds.subSys = value;
\r
530 public short DllCharacteristics {
\r
532 return ntFlds.dllFlags;
\r
535 ntFlds.dllFlags = value;
\r
540 public uint SizeOfStackReserve {
\r
542 return ntFlds.stackRes;
\r
545 ntFlds.stackRes = value;
\r
549 public uint SizeOfStackCommit {
\r
551 return ntFlds.stackCommit;
\r
554 ntFlds.stackCommit = value;
\r
558 public uint SizeOfHeapReserve {
\r
560 return ntFlds.heapRes;
\r
563 ntFlds.heapRes = value;
\r
567 public uint SizeOfHeapCommit {
\r
569 return ntFlds.heapCommit;
\r
572 ntFlds.heapCommit = value;
\r
576 public uint LoaderFlags {
\r
578 return ntFlds.ldrFlags;
\r
581 ntFlds.ldrFlags = value;
\r
585 public uint NumberOfRvaAndSizes {
\r
587 return ntFlds.numDirs;
\r
590 ntFlds.numDirs = value;
\r
600 public void Read(BinaryReader reader)
\r
602 stdFlds = new StdFields (reader);
\r
603 ntFlds = new NTFields (reader);
\r
605 exportDir = new DataDir (reader);
\r
606 importDir = new DataDir (reader);
\r
607 resourceDir = new DataDir (reader);
\r
608 exceptionDir = new DataDir (reader);
\r
609 securityDir = new DataDir (reader);
\r
610 baseRelocDir = new DataDir (reader);
\r
611 debugDir = new DataDir (reader);
\r
612 copyrightDir = new DataDir (reader);
\r
613 GPDir = new DataDir (reader);
\r
614 TLSDir = new DataDir (reader);
\r
615 loadCfgDir = new DataDir (reader);
\r
616 boundImpDir = new DataDir (reader);
\r
617 IATDir = new DataDir (reader);
\r
618 delayImpDir = new DataDir (reader);
\r
619 CLIHdrDir = new DataDir (reader);
\r
620 reservedDir = new DataDir (reader);
\r
624 public void Write (BinaryWriter writer)
\r
626 stdFlds.Write (writer);
\r
627 ntFlds.Write (writer);
\r
629 exportDir.Write (writer);
\r
630 importDir.Write (writer);
\r
631 resourceDir.Write (writer);
\r
632 exceptionDir.Write (writer);
\r
633 securityDir.Write (writer);
\r
634 baseRelocDir.Write (writer);
\r
635 debugDir.Write (writer);
\r
636 copyrightDir.Write (writer);
\r
637 GPDir.Write (writer);
\r
638 TLSDir.Write (writer);
\r
639 loadCfgDir.Write (writer);
\r
640 boundImpDir.Write (writer);
\r
641 IATDir.Write (writer);
\r
642 delayImpDir.Write (writer);
\r
643 CLIHdrDir.Write (writer);
\r
644 reservedDir.Write (writer);
\r
649 public void Dump(TextWriter writer)
\r
651 string dirs = String.Format(
\r
652 "Export Table : {0}" + Environment.NewLine +
\r
653 "Import Table : {1}" + Environment.NewLine +
\r
654 "Win32 Resource Table : {2}" + Environment.NewLine +
\r
655 "Exception Table : {3}" + Environment.NewLine +
\r
656 "Certificate Table : {4}" + Environment.NewLine +
\r
657 "Base Relocation Table : {5}" + Environment.NewLine +
\r
658 "Debug Table : {6}" + Environment.NewLine +
\r
659 "Copyright : {7}" + Environment.NewLine +
\r
660 "MIPS Global Ptr : {8}" + Environment.NewLine +
\r
661 "TLS Table : {9}" + Environment.NewLine +
\r
662 "Load Config Table : {10}" + Environment.NewLine +
\r
663 "Bound Import : {11}" + Environment.NewLine +
\r
664 "IAT : {12}" + Environment.NewLine +
\r
665 "Delay Import Descriptor : {13}" + Environment.NewLine +
\r
666 "CLI Header : {14}" + Environment.NewLine +
\r
667 "Reserved : {15}" + Environment.NewLine,
\r
668 exportDir, importDir, resourceDir, exceptionDir,
\r
669 securityDir, baseRelocDir, debugDir, copyrightDir,
\r
670 GPDir, TLSDir, loadCfgDir, boundImpDir, IATDir, delayImpDir,
\r
671 CLIHdrDir, reservedDir
\r
675 "Standard Fields:" + Environment.NewLine +
\r
676 stdFlds.ToString() + Environment.NewLine +
\r
677 "NT Fields:" + Environment.NewLine +
\r
678 ntFlds.ToString() + Environment.NewLine +
\r
679 "Directories: "+ Environment.NewLine +
\r
687 /// <returns></returns>
\r
688 public override string ToString()
\r
690 StringWriter sw = new StringWriter();
\r
692 return sw.ToString();
\r