2 * Copyright (c) 2002 Sergey Chaban <serge@wildwestsoftware.com>
\r
7 using System.Runtime.InteropServices;
\r
9 namespace Mono.PEToolkit {
\r
11 // IMAGE_OPTIONAL_HEADER
\r
12 public class PEHeader {
\r
15 /// Standard PE/COFF fields.
\r
17 public class StdFields {
\r
18 internal short magic; // always 0x10B?
\r
19 internal byte lMajor;
\r
20 internal byte lMinor;
\r
21 internal uint codeSize;
\r
22 internal uint initDataSize;
\r
23 internal uint uninitDataSize;
\r
24 internal RVA entryRVA;
\r
25 internal RVA codeBase;
\r
26 internal RVA dataBase;
\r
33 public StdFields (BinaryReader reader)
\r
38 public void Read (BinaryReader reader)
\r
40 magic = reader.ReadInt16 ();
\r
41 lMajor = reader.ReadByte ();
\r
42 lMinor = reader.ReadByte ();
\r
43 codeSize = reader.ReadUInt32 ();
\r
44 initDataSize = reader.ReadUInt32 ();
\r
45 uninitDataSize = reader.ReadUInt32 ();
\r
46 entryRVA = new RVA (reader.ReadUInt32 ());
\r
47 codeBase = new RVA (reader.ReadUInt32 ());
\r
48 dataBase = new RVA (reader.ReadUInt32 ());
\r
51 public void Write (BinaryWriter writer)
\r
53 writer.Write (magic);
\r
54 writer.Write (lMajor);
\r
55 writer.Write (lMinor);
\r
56 writer.Write (codeSize);
\r
57 writer.Write (initDataSize);
\r
58 writer.Write (uninitDataSize);
\r
59 entryRVA.Write (writer);
\r
60 codeBase.Write (writer);
\r
61 dataBase.Write (writer);
\r
64 public string LinkerVersion {
\r
66 return String.Format("{0}.{1}", lMajor, lMinor);
\r
70 public override string ToString() {
\r
71 return String.Format(
\r
72 "Magic : 0x{0}" + Environment.NewLine +
\r
73 "Linker ver. : {1}" + Environment.NewLine +
\r
74 "Size of code : {2}" + Environment.NewLine +
\r
75 "Size of initialized data : {3}" + Environment.NewLine +
\r
76 "Size of uinitialized data (BSS) : {4}" + Environment.NewLine,
\r
77 magic.ToString("X"), LinkerVersion,
\r
78 codeSize, initDataSize, uninitDataSize
\r
85 /// Windows-specific fields.
\r
88 /// See Partition II, 24.2.3.2
\r
90 public class NTFields {
\r
91 internal uint imgBase;
\r
92 internal uint sectAlign;
\r
93 internal uint fileAlign;
\r
94 internal short osMaj;
\r
95 internal short osMin;
\r
96 internal short imgMaj;
\r
97 internal short imgMin;
\r
98 internal short subSysMaj;
\r
99 internal short subSysMin;
\r
100 internal int reserved_win32ver;
\r
101 internal uint imgSize;
\r
102 internal uint hdrSize;
\r
103 internal uint chksum;
\r
104 internal Subsystem subSys;
\r
105 internal short dllFlags;
\r
106 internal uint stackRes;
\r
107 internal uint stackCommit;
\r
108 internal uint heapRes;
\r
109 internal uint heapCommit;
\r
110 internal uint ldrFlags;
\r
111 internal uint numDirs;
\r
118 public NTFields (BinaryReader reader)
\r
123 public void Read (BinaryReader reader)
\r
125 imgBase = reader.ReadUInt32 ();
\r
126 sectAlign = reader.ReadUInt32 ();
\r
127 fileAlign = reader.ReadUInt32 ();
\r
128 osMaj = reader.ReadInt16 ();
\r
129 osMin = reader.ReadInt16 ();
\r
130 imgMaj = reader.ReadInt16 ();
\r
131 imgMin = reader.ReadInt16 ();
\r
132 subSysMaj = reader.ReadInt16 ();
\r
133 subSysMin = reader.ReadInt16 ();
\r
134 reserved_win32ver = reader.ReadInt32 ();
\r
135 imgSize = reader.ReadUInt32 ();
\r
136 hdrSize = reader.ReadUInt32 ();
\r
137 chksum = reader.ReadUInt32 ();
\r
138 subSys = (Subsystem) reader.ReadInt16 ();
\r
139 dllFlags = reader.ReadInt16 ();
\r
140 stackRes = reader.ReadUInt32 ();
\r
141 stackCommit = reader.ReadUInt32 ();
\r
142 heapRes = reader.ReadUInt32 ();
\r
143 heapCommit = reader.ReadUInt32 ();
\r
144 ldrFlags = reader.ReadUInt32 ();
\r
145 numDirs = reader.ReadUInt32 ();
\r
148 public void Write (BinaryWriter writer)
\r
150 writer.Write (imgBase);
\r
151 writer.Write (sectAlign);
\r
152 writer.Write (fileAlign);
\r
153 writer.Write (osMaj);
\r
154 writer.Write (osMin);
\r
155 writer.Write (imgMaj);
\r
156 writer.Write (imgMin);
\r
157 writer.Write (subSysMaj);
\r
158 writer.Write (subSysMin);
\r
159 writer.Write (reserved_win32ver);
\r
160 writer.Write (imgSize);
\r
161 writer.Write (hdrSize);
\r
162 writer.Write (chksum);
\r
163 writer.Write ((short)subSys);
\r
164 writer.Write (dllFlags);
\r
165 writer.Write (stackRes);
\r
166 writer.Write (stackCommit);
\r
167 writer.Write (heapRes);
\r
168 writer.Write (heapCommit);
\r
169 writer.Write (ldrFlags);
\r
170 writer.Write (numDirs);
\r
173 public string OSVersion {
\r
175 return String.Format("{0}.{1}", osMaj, osMin);
\r
179 public string ImageVersion {
\r
181 return String.Format("{0}.{1}", imgMaj, imgMin);
\r
185 public string SubsysVersion {
\r
187 return String.Format("{0}.{1}", subSysMaj, subSysMin);
\r
194 /// <returns></returns>
\r
195 public override string ToString() {
\r
196 return String.Format(
\r
197 "Image Base : 0x{0}" + Environment.NewLine +
\r
198 "Section Alignment : 0x{1}" + Environment.NewLine +
\r
199 "File Alignment : 0x{2}" + Environment.NewLine +
\r
200 "OS Version : {3}" + Environment.NewLine +
\r
201 "Image Version : {4}" + Environment.NewLine +
\r
202 "Subsystem Version : {5}" + Environment.NewLine +
\r
203 "Reserved/Win32Ver : {6}" + Environment.NewLine +
\r
204 "Image Size : {7}" + Environment.NewLine +
\r
205 "Header Size : {8}" + Environment.NewLine +
\r
206 "Checksum : 0x{9}" + Environment.NewLine +
\r
207 "Subsystem : {10}" + Environment.NewLine +
\r
208 "DLL Flags : {11}" + Environment.NewLine +
\r
209 "Stack Reserve Size : 0x{12}" + Environment.NewLine +
\r
210 "Stack Commit Size : 0x{13}" + Environment.NewLine +
\r
211 "Heap Reserve Size : 0x{14}" + Environment.NewLine +
\r
212 "Heap Commit Size : 0x{15}" + Environment.NewLine +
\r
213 "Loader Flags : {16}" + Environment.NewLine +
\r
214 "Number of Directories : {17}" + Environment.NewLine,
\r
215 imgBase.ToString("X"), sectAlign.ToString("X"), fileAlign.ToString("X"),
\r
216 OSVersion, ImageVersion, SubsysVersion,
\r
218 imgSize, hdrSize, chksum.ToString("X"), subSys, dllFlags,
\r
219 stackRes.ToString("X"), stackCommit.ToString("X"), heapRes.ToString("X"), heapCommit.ToString ("X"),
\r
226 internal StdFields stdFlds;
\r
227 internal NTFields ntFlds;
\r
229 internal DataDir exportDir;
\r
230 internal DataDir importDir;
\r
231 internal DataDir resourceDir;
\r
232 internal DataDir exceptionDir;
\r
233 internal DataDir securityDir;
\r
234 internal DataDir baseRelocDir;
\r
235 internal DataDir debugDir;
\r
236 internal DataDir copyrightDir;
\r
237 internal DataDir GPDir;
\r
238 internal DataDir TLSDir;
\r
239 internal DataDir loadCfgDir;
\r
240 internal DataDir boundImpDir;
\r
241 internal DataDir IATDir;
\r
242 internal DataDir delayImpDir;
\r
243 internal DataDir CLIHdrDir;
\r
244 internal DataDir reservedDir;
\r
247 public bool IsCLIImage {
\r
249 return (CLIHdrDir.virtAddr.Value != 0);
\r
255 // Accessors for standard COFF fields.
\r
258 public short Magic {
\r
260 return stdFlds.magic;
\r
263 stdFlds.magic = value;
\r
267 public byte MajorLinkerVersion {
\r
269 return stdFlds.lMajor;
\r
272 stdFlds.lMajor = value;
\r
276 public byte MinorLinkerVersion {
\r
278 return stdFlds.lMinor;
\r
281 stdFlds.lMinor = value;
\r
285 public uint SizeOfCode {
\r
287 return stdFlds.codeSize;
\r
290 stdFlds.codeSize = value;
\r
294 public uint SizeOfInitializedData {
\r
296 return stdFlds.initDataSize;
\r
299 stdFlds.initDataSize = value;
\r
303 public uint SizeOfUninitializedData {
\r
305 return stdFlds.uninitDataSize;
\r
308 stdFlds.uninitDataSize = value;
\r
312 public RVA AddressOfEntryPoint {
\r
314 return stdFlds.entryRVA;
\r
317 stdFlds.entryRVA.value = value.value;
\r
321 public RVA BaseOfCode {
\r
323 return stdFlds.codeBase;
\r
326 stdFlds.codeBase.value = value.value;
\r
330 public RVA BaseOfData {
\r
332 return stdFlds.dataBase;
\r
335 stdFlds.dataBase.value = value.value;
\r
341 // Accessors for Windows-specific fields.
\r
346 /// Preferred address of image when loaded into memory.
\r
350 /// This is a linear address and not RVA,
\r
351 /// and must be a multiple of 64K.
\r
354 /// Table in the Partition II states that for CIL images
\r
355 /// it must be 0x400000.
\r
358 public uint ImageBase {
\r
360 return ntFlds.imgBase;
\r
363 ntFlds.imgBase = value;
\r
368 /// Alignment of section when loaded into memory.
\r
371 /// Must be greater or equal to FileAlignment.
\r
372 /// Default is the native page size.
\r
373 /// According to specs for CIL images it must be set to 8K.
\r
375 public uint SectionAlignment {
\r
377 return ntFlds.sectAlign;
\r
380 ntFlds.sectAlign = value;
\r
385 /// Byte alignment of pages in image file.
\r
388 /// Valid values are powers of 2 between 512 and 64K.
\r
389 /// For CIL images it must be either 512 or 4K.
\r
391 public uint FileAlignment {
\r
393 return ntFlds.fileAlign;
\r
396 ntFlds.fileAlign = value;
\r
401 public short MajorOperatingSystemVersion {
\r
403 return ntFlds.osMaj;
\r
406 ntFlds.osMaj = value;
\r
410 public short MinorOperatingSystemVersion {
\r
412 return ntFlds.osMin;
\r
415 ntFlds.osMin = value;
\r
419 public short MajorImageVersion {
\r
421 return ntFlds.imgMaj;
\r
424 ntFlds.imgMaj = value;
\r
428 public short MinorImageVersion {
\r
430 return ntFlds.imgMin;
\r
433 ntFlds.imgMin = value;
\r
437 public short MajorSubsystemVersion {
\r
439 return ntFlds.subSysMaj;
\r
442 ntFlds.subSysMaj = value;
\r
446 public short MinorSubsystemVersion {
\r
448 return ntFlds.subSysMin;
\r
451 ntFlds.subSysMin = value;
\r
455 public int Win32VersionValue {
\r
457 return ntFlds.reserved_win32ver;
\r
460 ntFlds.reserved_win32ver = value;
\r
464 public int Reserved {
\r
466 return ntFlds.reserved_win32ver;
\r
469 ntFlds.reserved_win32ver = value;
\r
473 public uint SizeOfImage {
\r
475 return ntFlds.imgSize;
\r
478 ntFlds.imgSize = value;
\r
482 public uint SizeOfHeaders {
\r
484 return ntFlds.hdrSize;
\r
487 ntFlds.hdrSize = value;
\r
491 public uint CheckSum {
\r
493 return ntFlds.chksum;
\r
496 ntFlds.chksum = value;
\r
500 public Subsystem Subsystem {
\r
502 return ntFlds.subSys;
\r
505 ntFlds.subSys = value;
\r
509 public short DllCharacteristics {
\r
511 return ntFlds.dllFlags;
\r
514 ntFlds.dllFlags = value;
\r
519 public uint SizeOfStackReserve {
\r
521 return ntFlds.stackRes;
\r
524 ntFlds.stackRes = value;
\r
528 public uint SizeOfStackCommit {
\r
530 return ntFlds.stackCommit;
\r
533 ntFlds.stackCommit = value;
\r
537 public uint SizeOfHeapReserve {
\r
539 return ntFlds.heapRes;
\r
542 ntFlds.heapRes = value;
\r
546 public uint SizeOfHeapCommit {
\r
548 return ntFlds.heapCommit;
\r
551 ntFlds.heapCommit = value;
\r
555 public uint LoaderFlags {
\r
557 return ntFlds.ldrFlags;
\r
560 ntFlds.ldrFlags = value;
\r
564 public uint NumberOfRvaAndSizes {
\r
566 return ntFlds.numDirs;
\r
569 ntFlds.numDirs = value;
\r
579 public void Read(BinaryReader reader)
\r
581 stdFlds = new StdFields (reader);
\r
582 ntFlds = new NTFields (reader);
\r
584 exportDir = new DataDir (reader);
\r
585 importDir = new DataDir (reader);
\r
586 resourceDir = new DataDir (reader);
\r
587 exceptionDir = new DataDir (reader);
\r
588 securityDir = new DataDir (reader);
\r
589 baseRelocDir = new DataDir (reader);
\r
590 debugDir = new DataDir (reader);
\r
591 copyrightDir = new DataDir (reader);
\r
592 GPDir = new DataDir (reader);
\r
593 TLSDir = new DataDir (reader);
\r
594 loadCfgDir = new DataDir (reader);
\r
595 boundImpDir = new DataDir (reader);
\r
596 IATDir = new DataDir (reader);
\r
597 delayImpDir = new DataDir (reader);
\r
598 CLIHdrDir = new DataDir (reader);
\r
599 reservedDir = new DataDir (reader);
\r
603 public void Write (BinaryWriter writer)
\r
605 stdFlds.Write (writer);
\r
606 ntFlds.Write (writer);
\r
608 exportDir.Write (writer);
\r
609 importDir.Write (writer);
\r
610 resourceDir.Write (writer);
\r
611 exceptionDir.Write (writer);
\r
612 securityDir.Write (writer);
\r
613 baseRelocDir.Write (writer);
\r
614 debugDir.Write (writer);
\r
615 copyrightDir.Write (writer);
\r
616 GPDir.Write (writer);
\r
617 TLSDir.Write (writer);
\r
618 loadCfgDir.Write (writer);
\r
619 boundImpDir.Write (writer);
\r
620 IATDir.Write (writer);
\r
621 delayImpDir.Write (writer);
\r
622 CLIHdrDir.Write (writer);
\r
623 reservedDir.Write (writer);
\r
628 public void Dump(TextWriter writer)
\r
630 string dirs = String.Format(
\r
631 "Export Table : {0}" + Environment.NewLine +
\r
632 "Import Table : {1}" + Environment.NewLine +
\r
633 "Win32 Resource Table : {2}" + Environment.NewLine +
\r
634 "Exception Table : {3}" + Environment.NewLine +
\r
635 "Certificate Table : {4}" + Environment.NewLine +
\r
636 "Base Relocation Table : {5}" + Environment.NewLine +
\r
637 "Debug Table : {6}" + Environment.NewLine +
\r
638 "Copyright : {7}" + Environment.NewLine +
\r
639 "MIPS Global Ptr : {8}" + Environment.NewLine +
\r
640 "TLS Table : {9}" + Environment.NewLine +
\r
641 "Load Config Table : {10}" + Environment.NewLine +
\r
642 "Bound Import : {11}" + Environment.NewLine +
\r
643 "IAT : {12}" + Environment.NewLine +
\r
644 "Delay Import Descriptor : {13}" + Environment.NewLine +
\r
645 "CLI Header : {14}" + Environment.NewLine +
\r
646 "Reserved : {15}" + Environment.NewLine,
\r
647 exportDir, importDir, resourceDir, exceptionDir,
\r
648 securityDir, baseRelocDir, debugDir, copyrightDir,
\r
649 GPDir, TLSDir, loadCfgDir, boundImpDir, IATDir, delayImpDir,
\r
650 CLIHdrDir, reservedDir
\r
654 "Standard Fields:" + Environment.NewLine +
\r
655 stdFlds.ToString() + Environment.NewLine +
\r
656 "NT Fields:" + Environment.NewLine +
\r
657 ntFlds.ToString() + Environment.NewLine +
\r
658 "Directories: "+ Environment.NewLine +
\r
666 /// <returns></returns>
\r
667 public override string ToString()
\r
669 StringWriter sw = new StringWriter();
\r
671 return sw.ToString();
\r