Fix null sessions in HttpContextWrapper.Session
[mono.git] / mcs / class / PEAPI / PEAPI.cs
1 using System;
2 using System.IO;
3 using System.Collections;
4 using System.Text;
5
6 namespace PEAPI {
7
8         /**************************************************************************/  
9         /// <summary>
10         /// Image for a PEFile
11         /// File Structure
12         ///     DOS Header (128 bytes) 
13         ///     PE Signature ("PE\0\0") 
14         ///     PEFileHeader (20 bytes)
15         ///     PEOptionalHeader (224 bytes) 
16         ///     SectionHeaders (40 bytes * NumSections)
17         ///
18         ///     Sections .text (always present - contains metadata)
19         ///              .sdata (contains any initialised data in the file - may not be present)
20         ///                     (for ilams /debug this contains the Debug table)
21         ///              .reloc (always present - in pure CIL only has one fixup)
22         ///               others???  c# produces .rsrc section containing a Resource Table
23         ///
24         /// .text layout
25         ///     IAT (single entry 8 bytes for pure CIL)
26         ///     CLIHeader (72 bytes)
27         ///     CIL instructions for all methods (variable size)
28         ///     MetaData 
29         ///       Root (20 bytes + UTF-8 Version String + quad align padding)
30         ///       StreamHeaders (8 bytes + null terminated name string + quad align padding)
31         ///       Streams 
32         ///         #~        (always present - holds metadata tables)
33         ///         #Strings  (always present - holds identifier strings)
34         ///         #US       (Userstring heap)
35         ///         #Blob     (signature blobs)
36         ///         #GUID     (guids for assemblies or Modules)
37         ///    ImportTable (40 bytes)
38         ///    ImportLookupTable(8 bytes) (same as IAT for standard CIL files)
39         ///    Hint/Name Tables with entry "_CorExeMain" for .exe file and "_CorDllMain" for .dll (14 bytes)
40         ///    ASCII string "mscoree.dll" referenced in ImportTable (+ padding = 16 bytes)
41         ///    Entry Point  (0xFF25 followed by 4 bytes 0x400000 + RVA of .text)
42         ///
43         ///  #~ stream structure
44         ///    Header (24 bytes)
45         ///    Rows   (4 bytes * numTables)
46         ///    Tables
47         /// </summary>
48         internal class FileImage : BinaryWriter {
49
50                 internal readonly static uint[] iByteMask = {0x000000FF, 0x0000FF00, 0x00FF0000, 0xFF000000};
51                 internal readonly static ulong[] lByteMask = {0x00000000000000FF, 0x000000000000FF00,
52                         0x0000000000FF0000, 0x00000000FF000000,
53                         0x000000FF00000000, 0x0000FF0000000000,
54                         0x00FF000000000000, 0xFF00000000000000 };
55                 internal readonly static uint nibble0Mask = 0x0000000F;
56                 internal readonly static uint nibble1Mask = 0x000000F0;
57
58                 private static readonly byte[] DOSHeader = { 0x4d,0x5a,0x90,0x00,0x03,0x00,0x00,0x00,
59                         0x04,0x00,0x00,0x00,0xff,0xff,0x00,0x00,
60                         0xb8,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
61                         0x40,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
62                         0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
63                         0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
64                         0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
65                         0x00,0x00,0x00,0x00,0x80,0x00,0x00,0x00,
66                         0x0e,0x1f,0xba,0x0e,0x00,0xb4,0x09,0xcd,
67                         0x21,0xb8,0x01,0x4c,0xcd,0x21,0x54,0x68,
68                         0x69,0x73,0x20,0x70,0x72,0x6f,0x67,0x72,
69                         0x61,0x6d,0x20,0x63,0x61,0x6e,0x6e,0x6f,
70                         0x74,0x20,0x62,0x65,0x20,0x72,0x75,0x6e,
71                         0x20,0x69,0x6e,0x20,0x44,0x4f,0x53,0x20,
72                         0x6d,0x6f,0x64,0x65,0x2e,0x0d,0x0d,0x0a,
73                         0x24,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
74                         0x50,0x45,0x00,0x00};
75                 private static byte[] PEHeader = { 0x4c, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
76                         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
77                         0xE0, 0x00, 0x0E, 0x01, // PE Header Standard Fields
78                         0x0B, 0x01, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 
79                         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
80                         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
81                 };
82
83                 private static readonly uint minFileAlign = 0x200;
84                 private static readonly uint maxFileAlign = 0x1000;
85                 private static readonly uint fileHeaderSize = 0x178;
86                 private static readonly uint sectionHeaderSize = 40;
87                 private static readonly uint SectionAlignment = 0x2000;
88                 private static readonly uint ImageBase = 0x400000;
89                 private static readonly uint ImportTableSize = 40;
90                 private static readonly uint IATSize = 8;
91                 private static readonly uint CLIHeaderSize = 72;
92                 private uint runtimeFlags = 0x01;  // COMIMAGE_FLAGS_ILONLY
93                 // 32BITREQUIRED 0x02, STRONGNAMESIGNED 0x08, TRACKDEBUGDATA 0x10000
94                 private static readonly uint StrongNameSignatureSize = 128;
95                 private bool reserveStrongNameSignatureSpace = false;
96
97                 private static readonly uint relocFlags = 0x42000040;
98                 private static readonly ushort exeCharacteristics = 0x010E;
99                 private static readonly ushort dllCharacteristics = 0x210E;
100                 // section names are all 8 bytes
101                 private static readonly string textName = ".text\0\0\0";
102                 private static readonly string sdataName = ".sdata\0\0";
103                 private static readonly string relocName = ".reloc\0\0";
104                 private static readonly string rsrcName = ".rsrc\0\0\0";
105                 private static readonly string exeHintNameTable = "\0\0_CorExeMain\0";
106                 private static readonly string dllHintNameTable = "\0\0_CorDllMain\0";
107                 private static readonly string runtimeEngineName = "mscoree.dll\0\0";
108
109                 private Section text, sdata, rsrc;
110                 ArrayList data;
111                 BinaryWriter reloc = new BinaryWriter(new MemoryStream());
112                 uint dateStamp = 0;
113                 DateTime origin = new DateTime(1970,1,1);
114                 uint numSections = 2; // always have .text  and .reloc sections
115                 internal SubSystem subSys = SubSystem.Windows_CUI;  // default is Windows Console mode
116                 internal long stackReserve = 0x100000; // default is 1Mb 
117                 internal uint fileAlign = minFileAlign;
118                 uint entryPointOffset, entryPointPadding, imageSize, headerSize, headerPadding, entryPointToken = 0;
119                 uint relocOffset, relocRVA, relocSize, relocPadding, relocTide, hintNameTableOffset;
120                 uint metaDataOffset, runtimeEngineOffset, initDataSize = 0, importTablePadding;
121                 uint resourcesSize, resourcesOffset;
122                 uint strongNameSigOffset;
123                 uint importTableOffset, importLookupTableOffset, totalImportTableSize;
124                 MetaData metaData;
125                 char[] runtimeEngine = runtimeEngineName.ToCharArray(), hintNameTable;
126                 bool doDLL, largeStrings, largeGUID, largeUS, largeBlob;
127                 ushort characteristics;
128
129                 internal FileImage(bool makeDLL, string fileName) : base(new FileStream(fileName,FileMode.Create)) 
130                 {
131                         InitFileImage(makeDLL);
132                         TimeSpan tmp = System.IO.File.GetCreationTime(fileName).Subtract(origin);
133                         dateStamp = Convert.ToUInt32(tmp.TotalSeconds);
134                 }
135
136                 internal FileImage(bool makeDLL, Stream str) : base(str) 
137                 {
138                         InitFileImage(makeDLL);
139                         TimeSpan tmp = DateTime.Now.Subtract(origin);
140                         dateStamp = Convert.ToUInt32(tmp.TotalSeconds);
141                 }
142
143                 private void InitFileImage(bool makeDLL) 
144                 {
145                         doDLL = makeDLL;
146                         if (doDLL) {
147                                 hintNameTable = dllHintNameTable.ToCharArray();
148                                 characteristics = dllCharacteristics;
149                         } else {
150                                 hintNameTable = exeHintNameTable.ToCharArray();
151                                 characteristics = exeCharacteristics;
152                         }
153                         text = new Section(textName,0x60000020);     // IMAGE_SCN_CNT  CODE, EXECUTE, READ
154                         //                      rsrc = new Section(rsrcName,0x40000040);     // IMAGE_SCN_CNT  INITIALIZED_DATA, READ
155                         metaData = new MetaData(this);
156                 }
157
158                 internal MetaData GetMetaData() 
159                 {
160                         return metaData;
161                 }
162
163                 private uint GetNextSectStart(uint rva, uint tide) 
164                 {
165                         uint c = tide / SectionAlignment;
166                         if ((tide % SectionAlignment) != 0)
167                                 c++;
168                         return rva + (c * SectionAlignment);
169                 }
170
171                 private void BuildTextSection() 
172                 {
173                         // .text layout
174                         //    IAT (single entry 8 bytes for pure CIL)
175                         //    CLIHeader (72 bytes)
176                         //    CIL instructions for all methods (variable size)
177                         //    MetaData 
178                         //    ImportTable (40 bytes)
179                         //    ImportLookupTable(8 bytes) (same as IAT for standard CIL files)
180                         //    Hint/Name Tables with entry "_CorExeMain" for .exe file and "_CorDllMain" for .dll (14 bytes)
181                         //    ASCII string "mscoree.dll" referenced in ImportTable (+ padding = 16 bytes)
182                         //    Entry Point  (0xFF25 followed by 4 bytes 0x400000 + RVA of .text)
183                         metaData.BuildMetaData(IATSize + CLIHeaderSize);
184                         metaDataOffset = IATSize + CLIHeaderSize;
185                         // Console.WriteLine("Code starts at " + metaDataOffset);
186                         metaDataOffset += metaData.CodeSize();
187                         // resourcesStart =
188                         resourcesOffset = metaDataOffset + metaData.Size ();
189                         resourcesSize = metaData.GetResourcesSize ();
190                         if (reserveStrongNameSignatureSpace) {
191                                 strongNameSigOffset = resourcesOffset + resourcesSize;
192                                 // fixUps = RVA for vtable
193                                 importTableOffset = strongNameSigOffset + StrongNameSignatureSize;
194                         } else {
195                                 strongNameSigOffset = 0;
196                                 // fixUps = RVA for vtable
197                                 importTableOffset = resourcesOffset + resourcesSize;
198                         }
199                         importTablePadding = NumToAlign(importTableOffset,16);
200                         importTableOffset += importTablePadding;
201                         importLookupTableOffset = importTableOffset + ImportTableSize;
202                         hintNameTableOffset = importLookupTableOffset + IATSize;
203                         runtimeEngineOffset = hintNameTableOffset + (uint)hintNameTable.Length;
204                         entryPointOffset = runtimeEngineOffset + (uint)runtimeEngine.Length;
205                         totalImportTableSize = entryPointOffset - importTableOffset;
206                         // Console.WriteLine("total import table size = " + totalImportTableSize);
207                         // Console.WriteLine("entrypoint offset = " + entryPointOffset);
208                         entryPointPadding = NumToAlign(entryPointOffset,4) + 2;
209                         entryPointOffset += entryPointPadding;
210                         text.AddReloc(entryPointOffset+2);
211                         text.IncTide(entryPointOffset + 6);
212                         //if (text.Tide() < fileAlign) fileAlign = minFileAlign;
213                         text.SetSize(NumToAlign(text.Tide(),fileAlign));
214                         // Console.WriteLine("text size = " + text.Size() + " text tide = " + text.Tide() + " text padding = " + text.Padding());
215                         // Console.WriteLine("metaDataOffset = " + Hex.Int(metaDataOffset));
216                         // Console.WriteLine("importTableOffset = " + Hex.Int(importTableOffset));
217                         // Console.WriteLine("importLookupTableOffset = " + Hex.Int(importLookupTableOffset));
218                         // Console.WriteLine("hintNameTableOffset = " + Hex.Int(hintNameTableOffset));
219                         // Console.WriteLine("runtimeEngineOffset = " + Hex.Int(runtimeEngineOffset));
220                         // Console.WriteLine("entryPointOffset = " + Hex.Int(entryPointOffset));
221                         // Console.WriteLine("entryPointPadding = " + Hex.Int(entryPointPadding));
222
223                 }
224
225                 internal void BuildRelocSection() 
226                 {
227                         text.DoRelocs(reloc);
228                         if (sdata != null) sdata.DoRelocs(reloc);
229                         if (rsrc != null) rsrc.DoRelocs(reloc);
230                         relocTide = (uint)reloc.Seek(0,SeekOrigin.Current);
231                         relocPadding = NumToAlign(relocTide,fileAlign);
232                         relocSize = relocTide + relocPadding;
233                         imageSize = relocRVA + SectionAlignment;
234                         initDataSize += relocSize;
235                 }
236
237                 private void CalcOffsets() 
238                 {
239                         if (sdata != null)
240                                 numSections++;
241                         if (rsrc != null)
242                                 numSections++;
243                         headerSize = fileHeaderSize + (numSections * sectionHeaderSize);
244                         headerPadding = NumToAlign(headerSize,fileAlign);
245                         headerSize += headerPadding;
246                         uint offset = headerSize;
247                         uint rva = SectionAlignment;
248                         text.SetOffset(offset);
249                         text.SetRVA(rva);
250                         offset += text.Size();
251                         rva  = GetNextSectStart(rva,text.Tide());
252                         // Console.WriteLine("headerSize = " + headerSize);
253                         // Console.WriteLine("headerPadding = " + headerPadding);
254                         // Console.WriteLine("textOffset = " + Hex.Int(text.Offset()));
255                         if (sdata != null) { 
256                                 sdata.SetSize(NumToAlign(sdata.Tide(),fileAlign));
257                                 sdata.SetOffset(offset);
258                                 sdata.SetRVA(rva);
259                                 offset += sdata.Size();
260                                 rva = GetNextSectStart(rva,sdata.Tide());
261                                 initDataSize += sdata.Size();
262                         }
263                         if (rsrc != null) { 
264                                 rsrc.SetSize(NumToAlign(rsrc.Tide(),fileAlign));
265                                 rsrc.SetOffset(offset);
266                                 rsrc.SetRVA(rva);
267                                 offset += rsrc.Size();
268                                 rva = GetNextSectStart(rva,rsrc.Tide());
269                                 initDataSize += rsrc.Size();
270                         }
271                         relocOffset = offset;
272                         relocRVA = rva;
273                 }
274
275                 internal void MakeFile() 
276                 {
277                         if (doDLL) hintNameTable = dllHintNameTable.ToCharArray();
278                         else hintNameTable = exeHintNameTable.ToCharArray();
279                         BuildTextSection();
280                         CalcOffsets();
281                         BuildRelocSection();
282                         // now write it out
283                         WriteHeader();
284                         WriteSections();
285                         Flush();
286                         Close();
287                 }
288
289                 private void WriteHeader() 
290                 {
291                         Write(DOSHeader);
292                         // Console.WriteLine("Writing PEHeader at offset " + Seek(0,SeekOrigin.Current));
293                         WritePEHeader();
294                         // Console.WriteLine("Writing text section header at offset " + Hex.Long(Seek(0,SeekOrigin.Current)));
295                         text.WriteHeader(this,relocRVA);
296                         if (sdata != null) sdata.WriteHeader(this,relocRVA);
297                         if (rsrc != null) rsrc.WriteHeader(this,relocRVA);
298                         // Console.WriteLine("Writing reloc section header at offset " + Seek(0,SeekOrigin.Current));
299                         WriteRelocSectionHeader();
300                         // Console.WriteLine("Writing padding at offset " + Seek(0,SeekOrigin.Current));
301                         WriteZeros(headerPadding);
302                 }
303
304                 private void WriteSections() 
305                 {
306                         // Console.WriteLine("Writing text section at offset " + Seek(0,SeekOrigin.Current));
307                         WriteTextSection();
308                         if (sdata != null) WriteSDataSection();
309                         if (rsrc != null) WriteRsrcSection();
310                         WriteRelocSection();
311                 }
312
313                 private void WriteIAT() 
314                 {
315                         Write(text.RVA() + hintNameTableOffset);
316                         Write(0);
317                 }
318
319                 private void WriteImportTables() 
320                 {
321                         // Import Table
322                         WriteZeros(importTablePadding);
323                         // Console.WriteLine("Writing import tables at offset " + Hex.Long(Seek(0,SeekOrigin.Current)));
324                         Write(importLookupTableOffset + text.RVA());
325                         WriteZeros(8); 
326                         Write(runtimeEngineOffset + text.RVA());
327                         Write(text.RVA());    // IAT is at the beginning of the text section
328                         WriteZeros(20);
329                         // Import Lookup Table
330                         WriteIAT();                // lookup table and IAT are the same
331                         // Hint/Name Table
332                         // Console.WriteLine("Writing hintname table at " + Hex.Long(Seek(0,SeekOrigin.Current)));
333                         Write(hintNameTable);
334                         Write(runtimeEngineName.ToCharArray());
335                 }
336
337                 private void WriteTextSection() 
338                 {
339                         WriteIAT();
340                         WriteCLIHeader();
341                         // Console.WriteLine("Writing code at " + Hex.Long(Seek(0,SeekOrigin.Current)));
342                         metaData.WriteByteCodes(this);
343                         // Console.WriteLine("Finished writing code at " + Hex.Long(Seek(0,SeekOrigin.Current)));
344                         largeStrings = metaData.LargeStringsIndex();
345                         largeGUID = metaData.LargeGUIDIndex();
346                         largeUS = metaData.LargeUSIndex();
347                         largeBlob = metaData.LargeBlobIndex();
348                         metaData.WriteMetaData(this);
349                         metaData.WriteResources (this);
350                         if (reserveStrongNameSignatureSpace) {
351                                 WriteZeros(StrongNameSignatureSize);
352                         }
353                         WriteImportTables();
354                         WriteZeros(entryPointPadding);
355                         Write((ushort)0x25FF);
356                         Write(ImageBase + text.RVA());
357                         WriteZeros(text.Padding());
358                 }
359
360                 private void WriteCLIHeader() 
361                 {
362                         Write(CLIHeaderSize);       // Cb
363                         Write((short)2);            // Major runtime version
364                         Write((short)0);            // Minor runtime version
365                         Write(text.RVA() + metaDataOffset);
366                         Write(metaData.Size());
367                         Write(runtimeFlags);
368                         Write(entryPointToken);
369                         if (resourcesSize > 0) {
370                                 Write (text.RVA () + resourcesOffset);
371                                 Write (resourcesSize);
372                         } else {
373                                 WriteZeros (8);
374                         }
375                         // Strong Name Signature (RVA, size)
376                         if (reserveStrongNameSignatureSpace) {
377                                 Write(text.RVA() + strongNameSigOffset); 
378                                 Write(StrongNameSignatureSize);
379                         } else {
380                                 WriteZeros(8);
381                         }
382                         WriteZeros(8);                     // CodeManagerTable
383                         WriteZeros(8);                     // VTableFixups NYI
384                         WriteZeros(16);                    // ExportAddressTableJumps, ManagedNativeHeader
385                 }
386
387                 private void WriteSDataSection() 
388                 {
389                         long size = sdata.Size ();
390                         long start = BaseStream.Position;
391                         for (int i=0; i < data.Count; i++) {
392                                 ((DataConstant)data[i]).Write(this);
393                         }
394                         while (BaseStream.Position < (start + size))
395                                 Write ((byte) 0);
396                 }
397
398                 private void WriteRsrcSection() 
399                 {
400                 }
401
402                 private void WriteRelocSection() 
403                 {
404                         // Console.WriteLine("Writing reloc section at " + Seek(0,SeekOrigin.Current) + " = " + relocOffset);
405                         MemoryStream str = (MemoryStream)reloc.BaseStream;
406                         Write(str.ToArray());
407                         WriteZeros(NumToAlign((uint)str.Position,fileAlign));
408                 }
409
410                 internal void SetEntryPoint(uint entryPoint) 
411                 {
412                         entryPointToken = entryPoint;
413                 }
414
415                 internal void AddInitData(DataConstant cVal) 
416                 {
417                         if (sdata == null) {                    
418                                 sdata = new Section(sdataName,0xC0000040);   // IMAGE_SCN_CNT  INITIALIZED_DATA, READ, WRITE
419                                 data = new ArrayList(); 
420                         }
421                         data.Add(cVal);
422                         cVal.DataOffset = sdata.Tide();
423                         sdata.IncTide(cVal.GetSize());
424                 }
425
426                 internal void WriteZeros(uint numZeros) 
427                 {
428                         for (int i=0; i < numZeros; i++) {
429                                 Write((byte)0);
430                         }
431                 }
432
433                 internal void WritePEHeader() 
434                 {
435                         Write((ushort)0x014C);  // Machine - always 0x14C for Managed PE Files (allow others??)
436                         Write((ushort)numSections);
437                         Write(dateStamp);
438                         WriteZeros(8); // Pointer to Symbol Table and Number of Symbols (always zero for ECMA CLI files)
439                         Write((ushort)0x00E0);  // Size of Optional Header
440                         Write(characteristics);
441                         // PE Optional Header
442                         Write((ushort)0x010B);   // Magic
443                         Write((byte)0x6);        // LMajor pure-IL = 6   C++ = 7
444                         Write((byte)0x0);        // LMinor
445                         Write(text.Size());
446                         Write(initDataSize);
447                         Write(0);                // Check other sections here!!
448                         Write(text.RVA() + entryPointOffset);
449                         Write(text.RVA());
450                         uint dataBase = 0;
451                         if (sdata != null) dataBase = sdata.RVA();
452                         else if (rsrc != null) dataBase = rsrc.RVA();
453                         else dataBase = relocRVA;
454                         Write(dataBase);
455                         Write(ImageBase);
456                         Write(SectionAlignment);
457                         Write(fileAlign);
458                         Write((ushort)0x04);     // OS Major
459                         WriteZeros(6);                  // OS Minor, User Major, User Minor
460                         Write((ushort)0x04);     // SubSys Major
461                         WriteZeros(6);           // SybSys Minor, Reserved
462                         Write(imageSize);
463                         Write(headerSize);
464                         Write((int)0);           // File Checksum
465                         Write((ushort)subSys);
466                         Write((short)0);         // DLL Flags
467                         Write((uint)stackReserve);   // Stack Reserve Size
468                         Write((uint)0x1000);     // Stack Commit Size
469                         Write((uint)0x100000);   // Heap Reserve Size
470                         Write((uint)0x1000);     // Heap Commit Size
471                         Write(0);                // Loader Flags
472                         Write(0x10);             // Number of Data Directories
473                         WriteZeros(8);                  // Export Table
474                         Write(importTableOffset + text.RVA());
475                         Write(totalImportTableSize);
476                         WriteZeros(24);            // Resource, Exception and Certificate Tables
477                         Write(relocRVA);
478                         Write(relocTide);
479                         WriteZeros(48);            // Debug, Copyright, Global Ptr, TLS, Load Config and Bound Import Tables
480                         Write(text.RVA());         // IATRVA - IAT is at start of .text Section
481                         Write(IATSize);
482                         WriteZeros(8);             // Delay Import Descriptor
483                         Write(text.RVA()+IATSize); // CLIHeader immediately follows IAT
484                         Write(CLIHeaderSize);    
485                         WriteZeros(8);             // Reserved
486                 }
487
488                 internal void WriteRelocSectionHeader() 
489                 {
490                         Write(relocName.ToCharArray());
491                         Write(relocTide);
492                         Write(relocRVA);
493                         Write(relocSize);
494                         Write(relocOffset);
495                         WriteZeros(12);
496                         Write(relocFlags);
497                 }
498
499                 private void Align (MemoryStream str, int val) 
500                 {
501                         if ((str.Position % val) != 0) {
502                                 for (int i=val - (int)(str.Position % val); i > 0; i--) {
503                                         str.WriteByte(0);
504                                 }
505                         }
506                 }
507
508                 private uint Align(uint val, uint alignVal) 
509                 {
510                         if ((val % alignVal) != 0) {
511                                 val += alignVal - (val % alignVal);
512                         }
513                         return val;
514                 }
515
516                 private uint NumToAlign(uint val, uint alignVal) 
517                 {
518                         if ((val % alignVal) == 0) return 0;
519                         return alignVal - (val % alignVal);
520                 }
521
522                 internal void StringsIndex(uint ix) 
523                 {
524                         if (largeStrings) Write(ix);
525                         else Write((ushort)ix);
526                 }
527
528                 internal void GUIDIndex(uint ix) 
529                 {
530                         if (largeGUID) Write(ix);
531                         else Write((ushort)ix);
532                 }
533
534                 internal void USIndex(uint ix) 
535                 {
536                         if (largeUS) Write(ix);
537                         else Write((ushort)ix);
538                 }
539
540                 internal void BlobIndex(uint ix) 
541                 {
542                         if (largeBlob) Write(ix);
543                         else Write((ushort)ix);
544                 }
545
546                 internal void WriteIndex(MDTable tabIx,uint ix) 
547                 {
548                         if (metaData.LargeIx(tabIx)) Write(ix);
549                         else Write((ushort)ix);
550                 }
551
552                 internal void WriteCodedIndex(CIx code, MetaDataElement elem) 
553                 {
554                         metaData.WriteCodedIndex(code,elem,this);
555                 }
556
557                 internal void WriteCodeRVA(uint offs) 
558                 {
559                         Write(text.RVA() + offs);
560                 }
561
562                 internal void WriteDataRVA(uint offs) 
563                 {
564                         Write(sdata.RVA() + offs);
565                 }
566
567                 internal void Write3Bytes(uint val) 
568                 {
569                         byte b3 = (byte)((val & FileImage.iByteMask[2]) >> 16);
570                         byte b2 = (byte)((val & FileImage.iByteMask[1]) >> 8);;
571                         byte b1 = (byte)(val & FileImage.iByteMask[0]);
572                         Write(b1);
573                         Write(b2);
574                         Write(b3);
575                 }
576
577                 internal bool ReserveStrongNameSignatureSpace {
578                         get { return reserveStrongNameSignatureSpace; }
579                         set { reserveStrongNameSignatureSpace = value; }
580                 }
581
582         }
583
584         /**************************************************************************/  
585         /// <summary>
586         /// Base class for the PEFile (starting point)
587         /// </summary>
588         public class PEFile {
589
590                 private static readonly string mscorlibName = "mscorlib";
591                 private Module thisMod;
592                 private ClassDef moduleClass;
593                 private ArrayList resources = new ArrayList ();
594                 private Assembly thisAssembly;
595                 private static bool isMSCorlib;
596                 private int corFlags = 1;
597                 FileImage fileImage;
598                 MetaData metaData;
599
600                 /// <summary>
601                 /// Create a new PEFile.  Each PEFile is a module.
602                 /// </summary>
603                 /// <param name="name">module name, also used for the file name</param>
604                 /// <param name="isDLL">create a .dll or .exe file</param>
605                 /// <param name="hasAssembly">this file is an assembly and 
606                 /// will contain the assembly manifest.  The assembly name is the 
607                 /// same as the module name</param>
608                 public PEFile(string name, bool isDLL, bool hasAssembly)
609                         : this (name, null, isDLL, hasAssembly, null, null) 
610                 {
611                         // Console.WriteLine(Hex.Byte(0x12));
612                         // Console.WriteLine(Hex.Short(0x1234));
613                         // Console.WriteLine(Hex.Int(0x12345678));
614                 }
615
616                 /// <summary>
617                 /// Create a new PEFile.  Each PEFile is a module.
618                 /// </summary>
619                 /// <param name="name">module name, also used for the file name</param>
620                 /// <param name="isDLL">create a .dll or .exe file</param>
621                 /// <param name="hasAssembly">this file is an assembly and 
622                 /// will contain the assembly manifest.  The assembly name is the 
623                 /// same as the module name</param>
624                 /// <param name="outputDir">write the PEFile to this directory.  If this
625                 /// string is null then the output will be to the current directory</param>
626                 public PEFile(string name, bool isDLL, bool hasAssembly, string outputDir)
627                         : this (name, null, isDLL, hasAssembly, outputDir, null) 
628                 {
629                         // Console.WriteLine(Hex.Byte(0x12));
630                         // Console.WriteLine(Hex.Short(0x1234));
631                         // Console.WriteLine(Hex.Int(0x12345678));
632                 }
633
634                 /// <summary>
635                 /// Create a new PEFile
636                 /// </summary>
637                 /// <param name="name">module name</param>
638                 /// <param name="isDLL">create a .dll or .exe</param>
639                 /// <param name="hasAssembly">this PEfile is an assembly and
640                 /// will contain the assemly manifest.  The assembly name is the
641                 /// same as the module name</param>
642                 /// <param name="outStream">write the PEFile to this stream instead
643                 /// of to a new file</param>
644                 public PEFile(string name, bool isDLL, bool hasAssembly, Stream outStream)
645                         : this (name, null, isDLL, hasAssembly, null, outStream) 
646                 {
647                 }
648
649                 public PEFile(string name, string module_name, bool isDLL, bool hasAssembly, Stream outStream)
650                         : this (name, module_name, isDLL, hasAssembly, null, outStream) 
651                 {
652                 }  
653
654                 public PEFile(string name, string module_name, bool isDLL, bool hasAssembly, string outputDir, Stream outStream) 
655                 {
656                         SetName (name);
657                         string fname = module_name == null ? MakeFileName (outputDir, name, isDLL) : module_name;
658                         if (outStream == null)
659                                 fileImage = new FileImage (isDLL, fname);
660                         else  
661                                 fileImage = new FileImage (isDLL, outStream);
662
663                         InitPEFile (name, fname, hasAssembly);
664                 }
665
666                 private void SetName (string name)
667                 {
668                         if (name == "mscorlib")
669                                 isMSCorlib = true;
670                 }
671
672                 private void InitPEFile(string name, string fName, bool hasAssembly) 
673                 {
674                         metaData = fileImage.GetMetaData();
675                         thisMod = new Module(fName,metaData);
676                         if (hasAssembly) {
677                                 thisAssembly = new Assembly(name,metaData);
678                                 metaData.AddToTable(MDTable.Assembly,thisAssembly);      
679                         }
680                         moduleClass = AddClass(TypeAttr.Private,"","<Module>");
681                         moduleClass.SpecialNoSuper();
682                         metaData.AddToTable(MDTable.Module,thisMod);
683                 }
684
685                 internal static bool IsMSCorlib {
686                         get { return isMSCorlib; }
687                 }
688
689                 public ClassDef ModuleClass {
690                         get { return moduleClass; }
691                 }
692
693                 /// <summary>
694                 /// Set the subsystem (.subsystem) (Default is Windows Console mode)
695                 /// </summary>
696                 /// <param name="subS">subsystem value</param>
697                 public void SetSubSystem(SubSystem subS) 
698                 {
699                         fileImage.subSys = subS;
700                 }
701
702                 /// <summary>
703                 /// Set the flags (.corflags)
704                 /// </summary>
705                 /// <param name="flags">the flags value</param>
706                 public void SetCorFlags(int flags) 
707                 {
708                         corFlags = flags;
709                 }
710
711                 public void SetStackReserve (long stackReserve)
712                 {
713                         fileImage.stackReserve = stackReserve;
714                 }
715
716                 private string MakeFileName(string dirName, string name, bool isDLL) 
717                 {
718                         string result = "";
719                         if ((dirName != null) && (dirName.CompareTo("") != 0)) {
720                                 result = dirName;
721                                 if (!dirName.EndsWith("\\")) result += "\\";
722                         }
723                         result += name;
724
725                         // if (isDLL) result += ".dll";  else result += ".exe";
726
727                         return result;
728                 }
729
730                 /// <summary>
731                 /// Add an external assembly to this PEFile (.assembly extern)
732                 /// </summary>
733                 /// <param name="assemName">the external assembly name</param>
734                 /// <returns>a descriptor for this external assembly</returns>
735                 public AssemblyRef AddExternAssembly(string assemName) 
736                 {
737                         if (assemName.CompareTo(mscorlibName) == 0) return metaData.mscorlib;
738                         AssemblyRef anAssem = new AssemblyRef(metaData,assemName);
739                         metaData.AddToTable(MDTable.AssemblyRef,anAssem);
740                         // Console.WriteLine("Adding assembly " + assemName);
741                         return anAssem;
742                 }
743
744                 /// <summary>
745                 /// Add an external module to this PEFile (.module extern)
746                 /// </summary>
747                 /// <param name="name">the external module name</param>
748                 /// <returns>a descriptor for this external module</returns>
749                 public ModuleRef AddExternModule(string name) 
750                 {
751                         ModuleRef modRef = new ModuleRef(metaData,name);
752                         metaData.AddToTable(MDTable.ModuleRef,modRef);
753                         return modRef;
754                 }
755
756                 /// <summary>
757                 /// Add a "global" method to this module
758                 /// </summary>
759                 /// <param name="name">method name</param>
760                 /// <param name="retType">return type</param>
761                 /// <param name="pars">method parameters</param>
762                 /// <returns>a descriptor for this new "global" method</returns>
763                 public MethodDef AddMethod (string name, Param ret_param, Param [] pars) 
764                 {
765                         return moduleClass.AddMethod (name, ret_param, pars);
766                 }
767                 
768                 public MethodDef AddMethod(string name, Type retType, Param[] pars) 
769                 {
770                         return AddMethod (name, new Param (ParamAttr.Default, "", retType), pars);
771                 }
772
773                 /// <summary>
774                 /// Add a "global" method to this module
775                 /// </summary>
776                 /// <param name="mAtts">method attributes</param>
777                 /// <param name="iAtts">method implementation attributes</param>
778                 /// <param name="name">method name</param>
779                 /// <param name="retType">return type</param>
780                 /// <param name="pars">method parameters</param>
781                 /// <returns>a descriptor for this new "global" method</returns>
782                 public MethodDef AddMethod (MethAttr mAtts, ImplAttr iAtts, string name, Param ret_param, Param [] pars) 
783                 {
784                         return moduleClass.AddMethod (mAtts, iAtts, name, ret_param, pars);
785                 }
786
787                 public MethodDef AddMethod(MethAttr mAtts, ImplAttr iAtts, string name, Type retType, Param[] pars) 
788                 {
789                         return AddMethod (mAtts, iAtts, name, new Param (ParamAttr.Default, "", retType), pars);
790                 }
791
792                 public MethodRef AddMethodToTypeSpec (Type item, string name, Type retType, Type[] pars) 
793                 {
794                         return AddMethodToTypeSpec (item, name, retType, pars, 0);
795                 }
796                 
797                 public MethodRef AddMethodToTypeSpec (Type item, string name, Type retType, Type[] pars, int gen_param_count) 
798                 {
799                         MethodRef meth = new MethodRef (item.GetTypeSpec (metaData), name, retType, pars, false, null, gen_param_count);
800                         metaData.AddToTable (MDTable.MemberRef,meth);
801                         return meth;
802                 }
803
804                 public MethodRef AddVarArgMethodToTypeSpec (Type item, string name, Type retType,
805                                 Type[] pars, Type[] optPars) {
806                         MethodRef meth = new MethodRef(item.GetTypeSpec (metaData), name,retType,pars,true,optPars, 0);
807                         metaData.AddToTable(MDTable.MemberRef,meth);
808                         return meth;
809                 }
810
811                 public FieldRef AddFieldToTypeSpec (Type item, string name, Type fType) 
812                 {
813                         FieldRef field = new FieldRef (item.GetTypeSpec (metaData), name,fType);
814                         metaData.AddToTable (MDTable.MemberRef,field);
815                         return field;
816                 }
817
818                 public Method AddMethodSpec (Method m, GenericMethodSig g_sig)
819                 {
820                         MethodSpec ms = new MethodSpec (m, g_sig);
821                         metaData.AddToTable (MDTable.MethodSpec, ms);
822                         return ms;
823                 }
824
825                 /// <summary>
826                 /// Add a "global" field to this module
827                 /// </summary>
828                 /// <param name="name">field name</param>
829                 /// <param name="fType">field type</param>
830                 /// <returns>a descriptor for this new "global" field</returns>
831                 public FieldDef AddField(string name, Type fType) 
832                 {
833                         return moduleClass.AddField(name,fType);
834                 }
835
836                 /// <summary>
837                 /// Add a "global" field to this module
838                 /// </summary>
839                 /// <param name="attrSet">attributes of this field</param>
840                 /// <param name="name">field name</param>
841                 /// <param name="fType">field type</param>
842                 /// <returns>a descriptor for this new "global" field</returns>
843                 public FieldDef AddField(FieldAttr attrSet, string name, Type fType) 
844                 {
845                         return moduleClass.AddField(attrSet,name,fType);
846                 }
847
848                 /// <summary>
849                 /// Add a class to this module
850                 /// </summary>
851                 /// <param name="attrSet">attributes of this class</param>
852                 /// <param name="nsName">name space name</param>
853                 /// <param name="name">class name</param>
854                 /// <returns>a descriptor for this new class</returns>
855                 public ClassDef AddClass(TypeAttr attrSet, string nsName, string name) 
856                 {
857                         return AddClass (attrSet, nsName, name, null);
858                 }
859
860                 /// <summary>
861                 /// Add a class which extends System.ValueType to this module
862                 /// </summary>
863                 /// <param name="attrSet">attributes of this class</param>
864                 /// <param name="nsName">name space name</param>
865                 /// <param name="name">class name</param>
866                 /// <returns>a descriptor for this new class</returns>
867                 public ClassDef AddValueClass(TypeAttr attrSet, string nsName, string name, ValueClass vClass) 
868                 {
869                         ClassDef aClass = new ClassDef(attrSet,nsName,name,metaData);
870                         if (!ClassDef.IsValueType (nsName, name) && !ClassDef.IsEnum (nsName, name)) {
871                                 aClass.MakeValueClass(vClass);
872                         } else {
873                                 if (ClassDef.IsEnum (nsName, name))
874                                         aClass.SetSuper (metaData.mscorlib.ValueType ());
875                                 else
876                                         aClass.SetSuper (metaData.mscorlib.GetSpecialSystemClass (PrimitiveType.Object));
877
878                                 metaData.mscorlib.SetSpecialSystemClass (nsName, name, aClass);
879                         }
880                         aClass.SetTypeIndex (PrimitiveType.ValueType.GetTypeIndex ());
881                         metaData.AddToTable(MDTable.TypeDef,aClass);
882                         return aClass;
883                 }
884
885                 /// <summary>
886                 /// Add a class to this module
887                 /// </summary>
888                 /// <param name="attrSet">attributes of this class</param>
889                 /// <param name="nsName">name space name</param>
890                 /// <param name="name">class name</param>
891                 /// <param name="superType">super type of this class (extends)</param>
892                 /// <returns>a descriptor for this new class</returns>
893                 public ClassDef AddClass(TypeAttr attrSet, string nsName, string name, Class superType) 
894                 {
895                         ClassDef aClass = new ClassDef(attrSet,nsName,name,metaData);
896                         if (superType != null)
897                                 aClass.SetSuper(superType);
898                         if (PEFile.IsMSCorlib)
899                                 metaData.mscorlib.SetSpecialSystemClass (nsName, name, aClass);
900                         metaData.AddToTable(MDTable.TypeDef,aClass);
901                         return aClass;
902                 }
903
904                 public void  AddGenericClass (GenericTypeInst gti)
905                 {
906                         metaData.AddToTable (MDTable.TypeSpec, gti);
907                 }
908
909                 public void AddGenericParam (GenParam param)
910                 {
911                         metaData.AddToTable (MDTable.TypeSpec, param);
912                 }
913
914                 public FileRef AddFile(string fName, byte[] hashBytes, bool hasMetaData, bool entryPoint) 
915                 {
916                         FileRef file = new FileRef(fName,hashBytes,hasMetaData,entryPoint,metaData);
917                         metaData.AddToTable(MDTable.File,file);
918                         return file;
919                 }
920
921                 /// <summary>
922                 /// Add a manifest resource to this PEFile NOT YET IMPLEMENTED
923                 /// </summary>
924                 /// <param name="mr"></param>
925                 public void AddManifestResource(ManifestResource mr) 
926                 {
927                         metaData.AddToTable(MDTable.ManifestResource,mr);
928                         resources.Add (mr);
929                         //mr.FixName(metaData);
930                 }
931
932                 public void AddCustomAttribute (Method meth, byte [] data, MetaDataElement element)
933                 {
934                         metaData.AddCustomAttribute (new CustomAttribute (element, meth, data));
935                         element.HasCustomAttr = true;
936                 }
937
938                 public void AddDeclSecurity (SecurityAction sec_action, byte [] data, MetaDataElement element)
939                 {
940                         metaData.AddDeclSecurity (new DeclSecurity (element, (ushort) sec_action, data));
941                 }
942
943                 public void AddDeclSecurity (SecurityAction sec_action, PEAPI.PermissionSet ps, MetaDataElement element)
944                 {
945                         metaData.AddDeclSecurity (new DeclSecurity_20 (element, (ushort) sec_action, ps));
946                 }
947
948                 /// <summary>
949                 /// Add a managed resource from another assembly.
950                 /// </summary>
951                 /// <param name="resName">The name of the resource</param>
952                 /// <param name="assem">The assembly where the resource is</param>
953                 /// <param name="isPublic">Access for the resource</param>
954                 public void AddExternalManagedResource (string resName, AssemblyRef assem, uint flags) 
955                 {
956                         resources.Add (new ManifestResource (resName, flags, assem));
957                 }
958
959                 /// <summary>
960                 /// Add a managed resource from another assembly.
961                 /// </summary>
962                 /// <param name="mr"></param>
963                 /// <param name="isPublic"></param>
964                 public void AddExternalManagedResource (ManifestResource mr) 
965                 {
966                         resources.Add (new ManifestResource (mr));
967                 }
968                 /// <summary>
969                 /// Find a resource
970                 /// </summary>
971                 /// <param name="name">The name of the resource</param>
972                 /// <returns>The resource with the name "name" or null </returns>
973                 public ManifestResource GetResource (string name) 
974                 {
975                         for (int i = 0; i < resources.Count; i ++) {
976                                 if (((ManifestResource) resources [i]).Name == name)
977                                         return (ManifestResource) resources [i];
978                         }
979                         return null;
980                 }
981
982                 public ManifestResource [] GetResources() 
983                 {
984                         return (ManifestResource []) resources.ToArray (typeof (ManifestResource));
985                 }
986
987                 /// <summary>
988                 /// Write out the PEFile (the "bake" function)
989                 /// </summary>
990                 public void WritePEFile() { /* the "bake" function */
991                         if (thisAssembly != null)
992                                 fileImage.ReserveStrongNameSignatureSpace = thisAssembly.HasPublicKey;
993                         fileImage.MakeFile();
994                 }
995
996                 /// <summary>
997                 /// Get the descriptor of this module
998                 /// </summary>
999                 /// <returns>the descriptor for this module</returns>
1000                 public Module GetThisModule() 
1001                 {
1002                         return thisMod;
1003                 }
1004
1005                 /// <summary>
1006                 /// Get the descriptor for this assembly.  The PEFile must have been
1007                 /// created with hasAssembly = true
1008                 /// </summary>
1009                 /// <returns>the descriptor for this assembly</returns>
1010                 public Assembly GetThisAssembly() 
1011                 {
1012                         return thisAssembly;
1013                 }
1014
1015         }
1016
1017         /**************************************************************************/  
1018         /// <summary>
1019         /// Descriptor for a Section in a PEFile  eg .text, .sdata
1020         /// </summary>
1021         internal class Section {
1022                 private static readonly uint relocPageSize = 4096;  // 4K pages for fixups
1023
1024                 char[] name; 
1025                 uint offset = 0, tide = 0, size = 0, rva = 0, relocTide = 0;
1026                 //uint relocOff = 0;
1027                 uint flags = 0, padding = 0;
1028                 uint[] relocs; 
1029
1030                 internal Section(string sName, uint sFlags) 
1031                 {
1032                         name = sName.ToCharArray();
1033                         flags = sFlags;
1034                 }
1035
1036                 internal uint Tide() { return tide; }
1037
1038                 internal void IncTide(uint incVal) { tide += incVal; }
1039
1040                 internal uint Padding() { return padding; }
1041
1042                 internal uint Size() { return size; }
1043
1044                 internal void SetSize(uint pad) 
1045                 {
1046                         padding = pad;
1047                         size = tide + padding;
1048                 }
1049
1050                 internal uint RVA() { return rva; }
1051
1052                 internal void SetRVA(uint rva) { this.rva = rva; }
1053
1054                 internal uint Offset() { return offset; }
1055
1056                 internal void SetOffset(uint offs) { offset = offs; }
1057
1058                 internal void DoBlock(BinaryWriter reloc, uint page, int start, int end) 
1059                 {
1060                         //Console.WriteLine("rva = " + rva + "  page = " + page);
1061                         reloc.Write(rva + page);
1062                         reloc.Write((uint)(((end-start+1)*2) + 8));
1063                         for (int j=start; j < end; j++) {
1064                                 //Console.WriteLine("reloc offset = " + relocs[j]);
1065                                 reloc.Write((ushort)((0x3 << 12) | (relocs[j] - page)));
1066                         }
1067                         reloc.Write((ushort)0);
1068                 }
1069
1070                 internal void DoRelocs(BinaryWriter reloc) 
1071                 {
1072                         if (relocTide > 0) {
1073                                 //relocOff = (uint)reloc.Seek(0,SeekOrigin.Current);
1074                                 uint block = (relocs[0]/relocPageSize + 1) * relocPageSize;
1075                                 int start = 0;
1076                                 for (int i=1; i < relocTide; i++) {
1077                                         if (relocs[i] >= block) {
1078                                                 DoBlock(reloc,block-relocPageSize,start,i);
1079                                                 start = i;
1080                                                 block = (relocs[i]/relocPageSize + 1) * relocPageSize;
1081                                         }
1082                                 }
1083                                 DoBlock(reloc,block-relocPageSize,start,(int)relocTide);
1084                         }
1085                 }
1086
1087                 internal void AddReloc(uint offs) 
1088                 {
1089                         int pos = 0;
1090                         if (relocs == null) {
1091                                 relocs = new uint[5];
1092                         } else {
1093                                 if (relocTide >= relocs.Length) {
1094                                         uint[] tmp = relocs;
1095                                         relocs = new uint[tmp.Length + 5];
1096                                         for (int i=0; i < relocTide; i++) {
1097                                                 relocs[i] = tmp[i];
1098                                         }
1099                                 }
1100                                 while ((pos < relocTide) && (relocs[pos] < offs)) pos++;
1101                                 for (int i=pos; i < relocTide; i++) {
1102                                         relocs[i+1] = relocs[i];
1103                                 }
1104                         }
1105                         relocs[pos] = offs;
1106                         relocTide++;    
1107                 }
1108
1109                 internal void WriteHeader(BinaryWriter output, uint relocRVA) 
1110                 {
1111                         output.Write(name);
1112                         output.Write(tide);
1113                         output.Write(rva);
1114                         output.Write(size);
1115                         output.Write(offset);
1116                         output.Write(0);
1117                         //output.Write(relocRVA + relocOff);
1118                         output.Write(0);
1119                         output.Write(0);
1120                         //output.Write((ushort)relocTide);
1121                         //output.Write((ushort)0);
1122                         output.Write(flags);
1123                 }
1124
1125         }
1126
1127         public class Hex {
1128                 readonly static char[] hexDigit = {'0','1','2','3','4','5','6','7',
1129                         '8','9','A','B','C','D','E','F'};
1130                 readonly static uint[] iByteMask = {0x000000FF, 0x0000FF00, 0x00FF0000, 0xFF000000};
1131                 readonly static ulong[] lByteMask = {0x00000000000000FF, 0x000000000000FF00, 
1132                         0x0000000000FF0000, 0x00000000FF000000,
1133                         0x000000FF00000000, 0x0000FF0000000000,
1134                         0x00FF000000000000, 0xFF00000000000000 };
1135                 readonly static uint nibble0Mask = 0x0000000F;
1136                 readonly static uint nibble1Mask = 0x000000F0;
1137
1138                 public static String Byte(int b) 
1139                 {
1140                         char[] str = new char[2];
1141                         uint num = (uint)b;
1142                         uint b1 = num & nibble0Mask;
1143                         uint b2 = (num & nibble1Mask) >> 4;
1144                         str[0] = hexDigit[b2];
1145                         str[1] = hexDigit[b1];
1146                         return new String(str);
1147                 }
1148
1149                 public static String Short(int b) 
1150                 {
1151                         char[] str = new char[4];
1152                         uint num1 = (uint)b & iByteMask[0];
1153                         uint num2 = ((uint)b & iByteMask[1]) >> 8;
1154                         uint b1 = num1 & nibble0Mask;
1155                         uint b2 = (num1 & nibble1Mask) >> 4;
1156                         uint b3 = num2 & nibble0Mask;
1157                         uint b4 = (num2 & nibble1Mask) >> 4;
1158                         str[0] = hexDigit[b4];
1159                         str[1] = hexDigit[b3];
1160                         str[2] = hexDigit[b2];
1161                         str[3] = hexDigit[b1];
1162                         return new String(str);
1163                 }
1164
1165                 public static String Int(int val) 
1166                 {
1167                         char[] str = new char[8];
1168                         uint num = (uint)val;
1169                         int strIx = 7;
1170                         for (int i=0; i < iByteMask.Length; i++) {
1171                                 uint b = num & iByteMask[i];
1172                                 b >>= (i*8);
1173                                 uint b1 = b & nibble0Mask;
1174                                 uint b2 = (b & nibble1Mask) >> 4;
1175                                 str[strIx--] = hexDigit[b1];
1176                                 str[strIx--] = hexDigit[b2];
1177                         }
1178                         return new String(str);
1179                 }
1180
1181                 public static String Int(uint num) 
1182                 {
1183                         char[] str = new char[8];
1184                         int strIx = 7;
1185                         for (int i=0; i < iByteMask.Length; i++) {
1186                                 uint b = num & iByteMask[i];
1187                                 b >>= (i*8);
1188                                 uint b1 = b & nibble0Mask;
1189                                 uint b2 = (b & nibble1Mask) >> 4;
1190                                 str[strIx--] = hexDigit[b1];
1191                                 str[strIx--] = hexDigit[b2];
1192                         }
1193                         return new String(str);
1194                 }
1195
1196                 public static String Long(long lnum) 
1197                 {
1198                         ulong num = (ulong)lnum;
1199                         char[] str = new char[16];
1200                         int strIx = 15;
1201                         for (int i=0; i < lByteMask.Length; i++) {
1202                                 ulong b = num & lByteMask[i];
1203                                 b >>= (i*8);
1204                                 ulong b1 = b & nibble0Mask;
1205                                 ulong b2 = (b & nibble1Mask) >> 4;
1206                                 str[strIx--] = hexDigit[b1];
1207                                 str[strIx--] = hexDigit[b2];
1208                         }
1209                         return new String(str);
1210                 }
1211         }
1212
1213         /// <summary>
1214         /// Error for invalid PE file
1215         /// </summary>
1216         public class PEFileException : System.Exception {
1217                 public PEFileException(string msg) : base(msg) { }
1218         }
1219
1220         public class NotYetImplementedException : System.Exception  {
1221                 public NotYetImplementedException(string msg) : base(msg + " Not Yet Implemented") { }
1222         }
1223
1224         public class TypeSignatureException : System.Exception {
1225                 public TypeSignatureException(string msg) : base(msg) { }
1226         }
1227
1228 }