2003-01-13 Ville Palo <vi64pa@koti.soon.fi>
[mono.git] / mcs / class / Mono.PEToolkit / PEHeader.cs
1 /*\r
2  * Copyright (c) 2002 Sergey Chaban <serge@wildwestsoftware.com>\r
3  */\r
4 \r
5 using System;\r
6 using System.IO;\r
7 using System.Runtime.InteropServices;\r
8 \r
9 namespace Mono.PEToolkit {\r
10 \r
11         // IMAGE_OPTIONAL_HEADER\r
12 \r
13         [StructLayoutAttribute(LayoutKind.Sequential)]\r
14         public struct PEHeader {\r
15 \r
16                 /// <summary>\r
17                 /// Standard PE/COFF fields.\r
18                 /// </summary>\r
19                 [StructLayoutAttribute(LayoutKind.Sequential)]\r
20                 public struct StdFields {\r
21                         internal short magic; // always 0x10B?\r
22                         internal byte lMajor;\r
23                         internal byte lMinor;\r
24                         internal uint codeSize;\r
25                         internal uint initDataSize;\r
26                         internal uint uninitDataSize;\r
27                         internal RVA  entryRVA;\r
28                         internal RVA  codeBase;\r
29                         internal RVA  dataBase;\r
30 \r
31 \r
32                         /// <summary>\r
33                         /// </summary>\r
34                         public string LinkerVersion {\r
35                                 get {\r
36                                         return String.Format("{0}.{1}", lMajor, lMinor);\r
37                                 }\r
38                         }\r
39                         \r
40 \r
41                         /// <summary>\r
42                         /// </summary>\r
43                         /// <returns></returns>\r
44                         public override string ToString() {\r
45                                 return String.Format(\r
46                                         "Magic                           : 0x{0}" + Environment.NewLine +\r
47                                         "Linker ver.                     : {1}" + Environment.NewLine +\r
48                                         "Size of code                    : {2}" + Environment.NewLine +\r
49                                         "Size of initialized data        : {3}" + Environment.NewLine +\r
50                                         "Size of uinitialized data (BSS) : {4}" + Environment.NewLine,\r
51                                         magic.ToString("X"), LinkerVersion,\r
52                                         codeSize, initDataSize, uninitDataSize\r
53                                 );\r
54                         }\r
55                 }\r
56                 \r
57 \r
58                 /// <summary>\r
59                 /// Windows-specific fields.\r
60                 /// </summary>\r
61                 /// <remarks>\r
62                 /// See Partition II, 24.2.3.2\r
63                 /// </remarks>\r
64                 [StructLayoutAttribute(LayoutKind.Sequential)]\r
65                 public struct NTFields {\r
66                         internal uint      imgBase;\r
67                         internal uint      sectAlign;\r
68                         internal uint      fileAlign;\r
69                         internal short     osMaj;\r
70                         internal short     osMin;\r
71                         internal short     imgMaj;\r
72                         internal short     imgMin;\r
73                         internal short     subSysMaj;\r
74                         internal short     subSysMin;\r
75                         internal int       reserved_win32ver;\r
76                         internal uint      imgSize;\r
77                         internal uint      hdrSize;\r
78                         internal uint      chksum;\r
79                         internal Subsystem subSys;\r
80                         internal short     dllFlags;\r
81                         internal uint      stackRes;\r
82                         internal uint      stackCommit;\r
83                         internal uint      heapRes;\r
84                         internal uint      heapCommit;\r
85                         internal uint      ldrFlags;\r
86                         internal uint      numDirs;\r
87 \r
88                         public string OSVersion {\r
89                                 get {\r
90                                         return String.Format("{0}.{1}", osMaj, osMin);\r
91                                 }\r
92                         }\r
93 \r
94                         public string ImageVersion {\r
95                                 get {\r
96                                         return String.Format("{0}.{1}", imgMaj, imgMin);\r
97                                 }\r
98                         }\r
99 \r
100                         public string SubsysVersion {\r
101                                 get {\r
102                                         return String.Format("{0}.{1}", subSysMaj, subSysMin);\r
103                                 }\r
104                         }\r
105 \r
106 \r
107                         /// <summary>\r
108                         /// </summary>\r
109                         /// <returns></returns>\r
110                         public override string ToString() {\r
111                                 return String.Format(\r
112                                         "Image Base            : 0x{0}" + Environment.NewLine +\r
113                                         "Section Alignment     : 0x{1}" + Environment.NewLine +\r
114                                         "File Alignment        : 0x{2}" + Environment.NewLine +\r
115                                         "OS Version            : {3}" + Environment.NewLine +\r
116                                         "Image Version         : {4}" + Environment.NewLine +\r
117                                         "Subsystem Version     : {5}" + Environment.NewLine +\r
118                                         "Reserved/Win32Ver     : {6}" + Environment.NewLine +\r
119                                         "Image Size            : {7}" + Environment.NewLine +\r
120                                         "Header Size           : {8}" + Environment.NewLine +\r
121                                         "Checksum              : 0x{9}" + Environment.NewLine +\r
122                                         "Subsystem             : {10}" + Environment.NewLine +\r
123                                         "DLL Flags             : {11}" + Environment.NewLine +\r
124                                         "Stack Reserve Size    : 0x{12}" + Environment.NewLine +\r
125                                         "Stack Commit Size     : 0x{13}" + Environment.NewLine +\r
126                                         "Heap Reserve Size     : 0x{14}" + Environment.NewLine +\r
127                                         "Heap Commit Size      : 0x{15}" + Environment.NewLine +\r
128                                         "Loader Flags          : {16}" + Environment.NewLine +\r
129                                         "Number of Directories : {17}" + Environment.NewLine,\r
130                                         imgBase.ToString("X"), sectAlign.ToString("X"), fileAlign.ToString("X"),\r
131                                         OSVersion, ImageVersion, SubsysVersion,\r
132                                         reserved_win32ver,\r
133                                         imgSize, hdrSize, chksum.ToString("X"), subSys, dllFlags,\r
134                                         stackRes.ToString("X"), stackCommit.ToString("X"), heapRes.ToString("X"), heapCommit.ToString ("X"),\r
135                                         ldrFlags, numDirs\r
136                                         );\r
137                         }\r
138                 }\r
139 \r
140 \r
141                 internal StdFields stdFlds;\r
142                 internal NTFields ntFlds;\r
143 \r
144                 internal DataDir exportDir;\r
145                 internal DataDir importDir;\r
146                 internal DataDir resourceDir;\r
147                 internal DataDir exceptionDir;\r
148                 internal DataDir securityDir;\r
149                 internal DataDir baseRelocDir;\r
150                 internal DataDir debugDir;\r
151                 internal DataDir copyrightDir;\r
152                 internal DataDir GPDir;\r
153                 internal DataDir TLSDir;\r
154                 internal DataDir loadCfgDir;\r
155                 internal DataDir boundImpDir;\r
156                 internal DataDir IATDir;\r
157                 internal DataDir delayImpDir;\r
158                 internal DataDir CLIHdrDir;\r
159                 internal DataDir reservedDir;\r
160 \r
161 \r
162                 public bool IsCLIImage {\r
163                         get {\r
164                                 return (CLIHdrDir.virtAddr.Value != 0);\r
165                         }\r
166                 }\r
167 \r
168 \r
169                 //\r
170                 // Accessors for standard COFF fields.\r
171                 //\r
172                 \r
173                 public short Magic {\r
174                         get {\r
175                                 return stdFlds.magic;\r
176                         }\r
177                         set {\r
178                                 stdFlds.magic = value;\r
179                         }\r
180                 }\r
181 \r
182                 public byte MajorLinkerVersion {\r
183                         get {\r
184                                 return stdFlds.lMajor;\r
185                         }\r
186                         set {\r
187                                 stdFlds.lMajor = value;\r
188                         }\r
189                 }\r
190 \r
191                 public byte MinorLinkerVersion {\r
192                         get {\r
193                                 return stdFlds.lMinor;\r
194                         }\r
195                         set {\r
196                                 stdFlds.lMinor = value;\r
197                         }\r
198                 }\r
199 \r
200                 public uint SizeOfCode {\r
201                         get {\r
202                                 return stdFlds.codeSize;\r
203                         }\r
204                         set {\r
205                                 stdFlds.codeSize = value;\r
206                         }\r
207                 }\r
208 \r
209                 public uint SizeOfInitializedData {\r
210                         get {\r
211                                 return stdFlds.initDataSize;\r
212                         }\r
213                         set {\r
214                                 stdFlds.initDataSize = value;\r
215                         }\r
216                 }\r
217 \r
218                 public uint SizeOfUninitializedData {\r
219                         get {\r
220                                 return stdFlds.uninitDataSize;\r
221                         }\r
222                         set {\r
223                                 stdFlds.uninitDataSize = value;\r
224                         }\r
225                 }\r
226 \r
227                 public RVA AddressOfEntryPoint {\r
228                         get {\r
229                                 return stdFlds.entryRVA;\r
230                         }\r
231                         set {\r
232                                 stdFlds.entryRVA.value = value.value;\r
233                         }\r
234                 }\r
235 \r
236                 public RVA BaseOfCode {\r
237                         get {\r
238                                 return stdFlds.codeBase;\r
239                         }\r
240                         set {\r
241                                 stdFlds.codeBase.value = value.value;\r
242                         }\r
243                 }\r
244 \r
245                 public RVA BaseOfData {\r
246                         get {\r
247                                 return stdFlds.dataBase;\r
248                         }\r
249                         set {\r
250                                 stdFlds.dataBase.value = value.value;\r
251                         }\r
252                 }\r
253 \r
254 \r
255                 //\r
256                 // Accessors for Windows-specific fields.\r
257                 //\r
258 \r
259 \r
260                 /// <summary>\r
261                 /// Preferred address of image when loaded into memory.\r
262                 /// </summary>\r
263                 /// <remarks>\r
264                 ///  <para>\r
265                 ///  This is a linear address and not RVA,\r
266                 ///  and must be a multiple of 64K.\r
267                 ///  </para>\r
268                 ///  <para>\r
269                 ///  Table in the Partition II states that for CIL images\r
270                 ///  it must be 0x400000.\r
271                 ///  </para>\r
272                 /// </remarks>\r
273                 public uint ImageBase {\r
274                         get {\r
275                                 return ntFlds.imgBase;\r
276                         }\r
277                         set {\r
278                                 ntFlds.imgBase = value;\r
279                         }\r
280                 }\r
281 \r
282                 /// <summary>\r
283                 ///  Alignment of section when loaded into memory.\r
284                 /// </summary>\r
285                 /// <remarks>\r
286                 ///  Must be greater or equal to FileAlignment.\r
287                 ///  Default is the native page size.\r
288                 ///  According to specs for CIL images it must be set to 8K.\r
289                 /// </remarks>\r
290                 public uint SectionAlignment {\r
291                         get {\r
292                                 return ntFlds.sectAlign;\r
293                         }\r
294                         set {\r
295                                 ntFlds.sectAlign = value;\r
296                         }\r
297                 }\r
298 \r
299                 /// <summary>\r
300                 ///  Byte alignment of pages in image file.\r
301                 /// </summary>\r
302                 /// <remarks>\r
303                 ///  Valid values are powers of 2 between 512 and 64K.\r
304                 ///  For CIL images it must be either 512 or 4K.\r
305                 /// </remarks>\r
306                 public uint FileAlignment {\r
307                         get {\r
308                                 return ntFlds.fileAlign;\r
309                         }\r
310                         set {\r
311                                 ntFlds.fileAlign = value;\r
312                         }\r
313                 }\r
314 \r
315 \r
316                 public short MajorOperatingSystemVersion {\r
317                         get {\r
318                                 return ntFlds.osMaj;\r
319                         }\r
320                         set {\r
321                                 ntFlds.osMaj = value;\r
322                         }\r
323                 }\r
324 \r
325                 public short MinorOperatingSystemVersion {\r
326                         get {\r
327                                 return ntFlds.osMin;\r
328                         }\r
329                         set {\r
330                                 ntFlds.osMin = value;\r
331                         }\r
332                 }\r
333 \r
334                 public short MajorImageVersion {\r
335                         get {\r
336                                 return ntFlds.imgMaj;\r
337                         }\r
338                         set {\r
339                                 ntFlds.imgMaj = value;\r
340                         }\r
341                 }\r
342 \r
343                 public short MinorImageVersion {\r
344                         get {\r
345                                 return ntFlds.imgMin;\r
346                         }\r
347                         set {\r
348                                 ntFlds.imgMin = value;\r
349                         }\r
350                 }\r
351 \r
352                 public short MajorSubsystemVersion {\r
353                         get {\r
354                                 return ntFlds.subSysMaj;\r
355                         }\r
356                         set {\r
357                                 ntFlds.subSysMaj = value;\r
358                         }\r
359                 }\r
360 \r
361                 public short MinorSubsystemVersion {\r
362                         get {\r
363                                 return ntFlds.subSysMin;\r
364                         }\r
365                         set {\r
366                                 ntFlds.subSysMin = value;\r
367                         }\r
368                 }\r
369 \r
370                 public int Win32VersionValue {\r
371                         get {\r
372                                 return ntFlds.reserved_win32ver;\r
373                         }\r
374                         set {\r
375                                 ntFlds.reserved_win32ver = value;\r
376                         }\r
377                 }\r
378 \r
379                 public int Reserved {\r
380                         get {\r
381                                 return ntFlds.reserved_win32ver;\r
382                         }\r
383                         set {\r
384                                 ntFlds.reserved_win32ver = value;\r
385                         }\r
386                 }\r
387 \r
388                 public uint SizeOfImage {\r
389                         get {\r
390                                 return ntFlds.imgSize;\r
391                         }\r
392                         set {\r
393                                 ntFlds.imgSize = value;\r
394                         }\r
395                 }\r
396 \r
397                 public uint SizeOfHeaders {\r
398                         get {\r
399                                 return ntFlds.hdrSize;\r
400                         }\r
401                         set {\r
402                                 ntFlds.hdrSize = value;\r
403                         }\r
404                 }\r
405 \r
406                 public uint CheckSum {\r
407                         get {\r
408                                 return ntFlds.chksum;\r
409                         }\r
410                         set {\r
411                                 ntFlds.chksum = value;\r
412                         }\r
413                 }\r
414 \r
415                 public Subsystem Subsystem {\r
416                         get {\r
417                                 return ntFlds.subSys;\r
418                         }\r
419                         set {\r
420                                 ntFlds.subSys = value;\r
421                         }\r
422                 }\r
423 \r
424                 public short DllCharacteristics {\r
425                         get {\r
426                                 return ntFlds.dllFlags;\r
427                         }\r
428                         set {\r
429                                 ntFlds.dllFlags = value;\r
430                         }\r
431                 }\r
432 \r
433 \r
434                 public uint SizeOfStackReserve {\r
435                         get {\r
436                                 return ntFlds.stackRes;\r
437                         }\r
438                         set {\r
439                                 ntFlds.stackRes = value;\r
440                         }\r
441                 }\r
442 \r
443                 public uint SizeOfStackCommit {\r
444                         get {\r
445                                 return ntFlds.stackCommit;\r
446                         }\r
447                         set {\r
448                                 ntFlds.stackCommit = value;\r
449                         }\r
450                 }\r
451 \r
452                 public uint SizeOfHeapReserve {\r
453                         get {\r
454                                 return ntFlds.heapRes;\r
455                         }\r
456                         set {\r
457                                 ntFlds.heapRes = value;\r
458                         }\r
459                 }\r
460 \r
461                 public uint SizeOfHeapCommit {\r
462                         get {\r
463                                 return ntFlds.heapCommit;\r
464                         }\r
465                         set {\r
466                                 ntFlds.heapCommit = value;\r
467                         }\r
468                 }\r
469 \r
470                 public uint LoaderFlags {\r
471                         get {\r
472                                 return ntFlds.ldrFlags;\r
473                         }\r
474                         set {\r
475                                 ntFlds.ldrFlags = value;\r
476                         }\r
477                 }\r
478 \r
479                 public uint NumberOfRvaAndSizes {\r
480                         get {\r
481                                 return ntFlds.numDirs;\r
482                         }\r
483                         set {\r
484                                 ntFlds.numDirs = value;\r
485                         }\r
486                 }\r
487 \r
488 \r
489 \r
490 \r
491 \r
492                 /// <summary>\r
493                 /// </summary>\r
494                 unsafe public void Read(BinaryReader reader)\r
495                 {\r
496                         fixed (void* pThis = &this) {\r
497                                 int hdrSize = sizeof (StdFields) + sizeof (NTFields);\r
498                                 PEUtils.ReadStruct(reader, pThis, hdrSize);\r
499                                 PEUtils.ReadStruct(reader, (byte*)pThis + hdrSize, (int) NumberOfRvaAndSizes * sizeof (DataDir));\r
500 \r
501                                 if (!System.BitConverter.IsLittleEndian) {\r
502                                         PEUtils.ChangeStructEndianess(pThis, typeof (PEHeader));\r
503                                 }\r
504                         }\r
505                 }\r
506 \r
507 \r
508 \r
509                 /// <summary>\r
510                 /// </summary>\r
511                 public void Dump(TextWriter writer)\r
512                 {\r
513                         string dirs = String.Format(\r
514                                 "Export Table            : {0}"  + Environment.NewLine +\r
515                                 "Import Table            : {1}"  + Environment.NewLine +\r
516                                 "Win32 Resource Table    : {2}"  + Environment.NewLine +\r
517                                 "Exception Table         : {3}"  + Environment.NewLine +\r
518                                 "Certificate Table       : {4}"  + Environment.NewLine +\r
519                                 "Base Relocation Table   : {5}"  + Environment.NewLine +\r
520                                 "Debug Table             : {6}"  + Environment.NewLine +\r
521                                 "Copyright               : {7}"  + Environment.NewLine +\r
522                                 "MIPS Global Ptr         : {8}"  + Environment.NewLine +\r
523                                 "TLS Table               : {9}"  + Environment.NewLine +\r
524                                 "Load Config Table       : {10}"  + Environment.NewLine +\r
525                                 "Bound Import            : {11}"  + Environment.NewLine +\r
526                                 "IAT                     : {12}"  + Environment.NewLine +\r
527                                 "Delay Import Descriptor : {13}"  + Environment.NewLine +\r
528                                 "CLI Header              : {14}"  + Environment.NewLine +\r
529                                 "Reserved                : {15}"  + Environment.NewLine,\r
530                                 exportDir, importDir, resourceDir, exceptionDir,\r
531                                 securityDir, baseRelocDir, debugDir, copyrightDir,\r
532                                 GPDir, TLSDir, loadCfgDir, boundImpDir, IATDir, delayImpDir,\r
533                                 CLIHdrDir, reservedDir\r
534                         );\r
535 \r
536                         writer.WriteLine(\r
537                                 stdFlds.ToString() + Environment.NewLine +\r
538                                 ntFlds.ToString() + Environment.NewLine +\r
539                                 "Directories: "+ Environment.NewLine +\r
540                                 dirs\r
541                         );\r
542                 }\r
543 \r
544 \r
545                 /// <summary>\r
546                 /// </summary>\r
547                 /// <returns></returns>\r
548                 public override string ToString()\r
549                 {\r
550                         StringWriter sw = new StringWriter();\r
551                         Dump(sw);\r
552                         return sw.ToString();\r
553                 }\r
554 \r
555         }\r
556 \r
557 }\r
558 \r