Added SiteMapDataSourceTest.cs
[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                         if (tide < SectionAlignment) return rva + SectionAlignment;
166                         return rva + ((tide / SectionAlignment) + 1) * SectionAlignment;
167                 }
168
169                 private void BuildTextSection() 
170                 {
171                         // .text layout
172                         //    IAT (single entry 8 bytes for pure CIL)
173                         //    CLIHeader (72 bytes)
174                         //    CIL instructions for all methods (variable size)
175                         //    MetaData 
176                         //    ImportTable (40 bytes)
177                         //    ImportLookupTable(8 bytes) (same as IAT for standard CIL files)
178                         //    Hint/Name Tables with entry "_CorExeMain" for .exe file and "_CorDllMain" for .dll (14 bytes)
179                         //    ASCII string "mscoree.dll" referenced in ImportTable (+ padding = 16 bytes)
180                         //    Entry Point  (0xFF25 followed by 4 bytes 0x400000 + RVA of .text)
181                         metaData.BuildMetaData(IATSize + CLIHeaderSize);
182                         metaDataOffset = IATSize + CLIHeaderSize;
183                         // Console.WriteLine("Code starts at " + metaDataOffset);
184                         metaDataOffset += metaData.CodeSize();
185                         // resourcesStart =
186                         resourcesOffset = metaDataOffset + metaData.Size ();
187                         resourcesSize = metaData.GetResourcesSize ();
188                         if (reserveStrongNameSignatureSpace) {
189                                 strongNameSigOffset = resourcesOffset + resourcesSize;
190                                 // fixUps = RVA for vtable
191                                 importTableOffset = strongNameSigOffset + StrongNameSignatureSize;
192                         } else {
193                                 strongNameSigOffset = 0;
194                                 // fixUps = RVA for vtable
195                                 importTableOffset = resourcesOffset + resourcesSize;
196                         }
197                         importTablePadding = NumToAlign(importTableOffset,16);
198                         importTableOffset += importTablePadding;
199                         importLookupTableOffset = importTableOffset + ImportTableSize;
200                         hintNameTableOffset = importLookupTableOffset + IATSize;
201                         runtimeEngineOffset = hintNameTableOffset + (uint)hintNameTable.Length;
202                         entryPointOffset = runtimeEngineOffset + (uint)runtimeEngine.Length;
203                         totalImportTableSize = entryPointOffset - importTableOffset;
204                         // Console.WriteLine("total import table size = " + totalImportTableSize);
205                         // Console.WriteLine("entrypoint offset = " + entryPointOffset);
206                         entryPointPadding = NumToAlign(entryPointOffset,4) + 2;
207                         entryPointOffset += entryPointPadding;
208                         text.AddReloc(entryPointOffset+2);
209                         text.IncTide(entryPointOffset + 6);
210                         //if (text.Tide() < fileAlign) fileAlign = minFileAlign;
211                         text.SetSize(NumToAlign(text.Tide(),fileAlign));
212                         // Console.WriteLine("text size = " + text.Size() + " text tide = " + text.Tide() + " text padding = " + text.Padding());
213                         // Console.WriteLine("metaDataOffset = " + Hex.Int(metaDataOffset));
214                         // Console.WriteLine("importTableOffset = " + Hex.Int(importTableOffset));
215                         // Console.WriteLine("importLookupTableOffset = " + Hex.Int(importLookupTableOffset));
216                         // Console.WriteLine("hintNameTableOffset = " + Hex.Int(hintNameTableOffset));
217                         // Console.WriteLine("runtimeEngineOffset = " + Hex.Int(runtimeEngineOffset));
218                         // Console.WriteLine("entryPointOffset = " + Hex.Int(entryPointOffset));
219                         // Console.WriteLine("entryPointPadding = " + Hex.Int(entryPointPadding));
220
221                 }
222
223                 internal void BuildRelocSection() 
224                 {
225                         text.DoRelocs(reloc);
226                         if (sdata != null) sdata.DoRelocs(reloc);
227                         if (rsrc != null) rsrc.DoRelocs(reloc);
228                         relocTide = (uint)reloc.Seek(0,SeekOrigin.Current);
229                         relocPadding = NumToAlign(relocTide,fileAlign);
230                         relocSize = relocTide + relocPadding;
231                         imageSize = relocRVA + SectionAlignment;
232                         initDataSize += relocSize;
233                 }
234
235                 private void CalcOffsets() 
236                 {
237                         if (sdata != null)
238                                 numSections++;
239                         if (rsrc != null)
240                                 numSections++;
241                         headerSize = fileHeaderSize + (numSections * sectionHeaderSize);
242                         headerPadding = NumToAlign(headerSize,fileAlign);
243                         headerSize += headerPadding;
244                         uint offset = headerSize;
245                         uint rva = SectionAlignment;
246                         text.SetOffset(offset);
247                         text.SetRVA(rva);
248                         offset += text.Size();
249                         rva  = GetNextSectStart(rva,text.Tide());
250                         // Console.WriteLine("headerSize = " + headerSize);
251                         // Console.WriteLine("headerPadding = " + headerPadding);
252                         // Console.WriteLine("textOffset = " + Hex.Int(text.Offset()));
253                         if (sdata != null) { 
254                                 sdata.SetSize(NumToAlign(sdata.Tide(),fileAlign));
255                                 sdata.SetOffset(offset);
256                                 sdata.SetRVA(rva);
257                                 offset += sdata.Size();
258                                 rva = GetNextSectStart(rva,sdata.Tide());
259                                 initDataSize += sdata.Size();
260                         }
261                         if (rsrc != null) { 
262                                 rsrc.SetSize(NumToAlign(rsrc.Tide(),fileAlign));
263                                 rsrc.SetOffset(offset);
264                                 rsrc.SetRVA(rva);
265                                 offset += rsrc.Size();
266                                 rva = GetNextSectStart(rva,rsrc.Tide());
267                                 initDataSize += rsrc.Size();
268                         }
269                         relocOffset = offset;
270                         relocRVA = rva;
271                 }
272
273                 internal void MakeFile() 
274                 {
275                         if (doDLL) hintNameTable = dllHintNameTable.ToCharArray();
276                         else hintNameTable = exeHintNameTable.ToCharArray();
277                         BuildTextSection();
278                         CalcOffsets();
279                         BuildRelocSection();
280                         // now write it out
281                         WriteHeader();
282                         WriteSections();
283                         Flush();
284                         Close();
285                 }
286
287                 private void WriteHeader() 
288                 {
289                         Write(DOSHeader);
290                         // Console.WriteLine("Writing PEHeader at offset " + Seek(0,SeekOrigin.Current));
291                         WritePEHeader();
292                         // Console.WriteLine("Writing text section header at offset " + Hex.Long(Seek(0,SeekOrigin.Current)));
293                         text.WriteHeader(this,relocRVA);
294                         if (sdata != null) sdata.WriteHeader(this,relocRVA);
295                         if (rsrc != null) rsrc.WriteHeader(this,relocRVA);
296                         // Console.WriteLine("Writing reloc section header at offset " + Seek(0,SeekOrigin.Current));
297                         WriteRelocSectionHeader();
298                         // Console.WriteLine("Writing padding at offset " + Seek(0,SeekOrigin.Current));
299                         WriteZeros(headerPadding);
300                 }
301
302                 private void WriteSections() 
303                 {
304                         // Console.WriteLine("Writing text section at offset " + Seek(0,SeekOrigin.Current));
305                         WriteTextSection();
306                         if (sdata != null) WriteSDataSection();
307                         if (rsrc != null) WriteRsrcSection();
308                         WriteRelocSection();
309                 }
310
311                 private void WriteIAT() 
312                 {
313                         Write(text.RVA() + hintNameTableOffset);
314                         Write(0);
315                 }
316
317                 private void WriteImportTables() 
318                 {
319                         // Import Table
320                         WriteZeros(importTablePadding);
321                         // Console.WriteLine("Writing import tables at offset " + Hex.Long(Seek(0,SeekOrigin.Current)));
322                         Write(importLookupTableOffset + text.RVA());
323                         WriteZeros(8); 
324                         Write(runtimeEngineOffset + text.RVA());
325                         Write(text.RVA());    // IAT is at the beginning of the text section
326                         WriteZeros(20);
327                         // Import Lookup Table
328                         WriteIAT();                // lookup table and IAT are the same
329                         // Hint/Name Table
330                         // Console.WriteLine("Writing hintname table at " + Hex.Long(Seek(0,SeekOrigin.Current)));
331                         Write(hintNameTable);
332                         Write(runtimeEngineName.ToCharArray());
333                 }
334
335                 private void WriteTextSection() 
336                 {
337                         WriteIAT();
338                         WriteCLIHeader();
339                         // Console.WriteLine("Writing code at " + Hex.Long(Seek(0,SeekOrigin.Current)));
340                         metaData.WriteByteCodes(this);
341                         // Console.WriteLine("Finished writing code at " + Hex.Long(Seek(0,SeekOrigin.Current)));
342                         largeStrings = metaData.LargeStringsIndex();
343                         largeGUID = metaData.LargeGUIDIndex();
344                         largeUS = metaData.LargeUSIndex();
345                         largeBlob = metaData.LargeBlobIndex();
346                         metaData.WriteMetaData(this);
347                         metaData.WriteResources (this);
348                         if (reserveStrongNameSignatureSpace) {
349                                 WriteZeros(StrongNameSignatureSize);
350                         }
351                         WriteImportTables();
352                         WriteZeros(entryPointPadding);
353                         Write((ushort)0x25FF);
354                         Write(ImageBase + text.RVA());
355                         WriteZeros(text.Padding());
356                 }
357
358                 private void WriteCLIHeader() 
359                 {
360                         Write(CLIHeaderSize);       // Cb
361                         Write((short)2);            // Major runtime version
362                         Write((short)0);            // Minor runtime version
363                         Write(text.RVA() + metaDataOffset);
364                         Write(metaData.Size());
365                         Write(runtimeFlags);
366                         Write(entryPointToken);
367                         if (resourcesSize > 0) {
368                                 Write (text.RVA () + resourcesOffset);
369                                 Write (resourcesSize);
370                         } else {
371                                 WriteZeros (8);
372                         }
373                         // Strong Name Signature (RVA, size)
374                         if (reserveStrongNameSignatureSpace) {
375                                 Write(text.RVA() + strongNameSigOffset); 
376                                 Write(StrongNameSignatureSize);
377                         } else {
378                                 WriteZeros(8);
379                         }
380                         WriteZeros(8);                     // CodeManagerTable
381                         WriteZeros(8);                     // VTableFixups NYI
382                         WriteZeros(16);                    // ExportAddressTableJumps, ManagedNativeHeader
383                 }
384
385                 private void WriteSDataSection() 
386                 {
387                         long size = sdata.Size ();
388                         long start = BaseStream.Position;
389                         for (int i=0; i < data.Count; i++) {
390                                 ((DataConstant)data[i]).Write(this);
391                         }
392                         while (BaseStream.Position < (start + size))
393                                 Write ((byte) 0);
394                 }
395
396                 private void WriteRsrcSection() 
397                 {
398                 }
399
400                 private void WriteRelocSection() 
401                 {
402                         // Console.WriteLine("Writing reloc section at " + Seek(0,SeekOrigin.Current) + " = " + relocOffset);
403                         MemoryStream str = (MemoryStream)reloc.BaseStream;
404                         Write(str.ToArray());
405                         WriteZeros(NumToAlign((uint)str.Position,fileAlign));
406                 }
407
408                 internal void SetEntryPoint(uint entryPoint) 
409                 {
410                         entryPointToken = entryPoint;
411                 }
412
413                 internal void AddInitData(DataConstant cVal) 
414                 {
415                         if (sdata == null) {                    
416                                 sdata = new Section(sdataName,0xC0000040);   // IMAGE_SCN_CNT  INITIALIZED_DATA, READ, WRITE
417                                 data = new ArrayList(); 
418                         }
419                         data.Add(cVal);
420                         cVal.DataOffset = sdata.Tide();
421                         sdata.IncTide(cVal.GetSize());
422                 }
423
424                 internal void WriteZeros(uint numZeros) 
425                 {
426                         for (int i=0; i < numZeros; i++) {
427                                 Write((byte)0);
428                         }
429                 }
430
431                 internal void WritePEHeader() 
432                 {
433                         Write((ushort)0x014C);  // Machine - always 0x14C for Managed PE Files (allow others??)
434                         Write((ushort)numSections);
435                         Write(dateStamp);
436                         WriteZeros(8); // Pointer to Symbol Table and Number of Symbols (always zero for ECMA CLI files)
437                         Write((ushort)0x00E0);  // Size of Optional Header
438                         Write(characteristics);
439                         // PE Optional Header
440                         Write((ushort)0x010B);   // Magic
441                         Write((byte)0x6);        // LMajor pure-IL = 6   C++ = 7
442                         Write((byte)0x0);        // LMinor
443                         Write(text.Size());
444                         Write(initDataSize);
445                         Write(0);                // Check other sections here!!
446                         Write(text.RVA() + entryPointOffset);
447                         Write(text.RVA());
448                         uint dataBase = 0;
449                         if (sdata != null) dataBase = sdata.RVA();
450                         else if (rsrc != null) dataBase = rsrc.RVA();
451                         else dataBase = relocRVA;
452                         Write(dataBase);
453                         Write(ImageBase);
454                         Write(SectionAlignment);
455                         Write(fileAlign);
456                         Write((ushort)0x04);     // OS Major
457                         WriteZeros(6);                  // OS Minor, User Major, User Minor
458                         Write((ushort)0x04);     // SubSys Major
459                         WriteZeros(6);           // SybSys Minor, Reserved
460                         Write(imageSize);
461                         Write(headerSize);
462                         Write((int)0);           // File Checksum
463                         Write((ushort)subSys);
464                         Write((short)0);         // DLL Flags
465                         Write((uint)stackReserve);   // Stack Reserve Size
466                         Write((uint)0x1000);     // Stack Commit Size
467                         Write((uint)0x100000);   // Heap Reserve Size
468                         Write((uint)0x1000);     // Heap Commit Size
469                         Write(0);                // Loader Flags
470                         Write(0x10);             // Number of Data Directories
471                         WriteZeros(8);                  // Export Table
472                         Write(importTableOffset + text.RVA());
473                         Write(totalImportTableSize);
474                         WriteZeros(24);            // Resource, Exception and Certificate Tables
475                         Write(relocRVA);
476                         Write(relocTide);
477                         WriteZeros(48);            // Debug, Copyright, Global Ptr, TLS, Load Config and Bound Import Tables
478                         Write(text.RVA());         // IATRVA - IAT is at start of .text Section
479                         Write(IATSize);
480                         WriteZeros(8);             // Delay Import Descriptor
481                         Write(text.RVA()+IATSize); // CLIHeader immediately follows IAT
482                         Write(CLIHeaderSize);    
483                         WriteZeros(8);             // Reserved
484                 }
485
486                 internal void WriteRelocSectionHeader() 
487                 {
488                         Write(relocName.ToCharArray());
489                         Write(relocTide);
490                         Write(relocRVA);
491                         Write(relocSize);
492                         Write(relocOffset);
493                         WriteZeros(12);
494                         Write(relocFlags);
495                 }
496
497                 private void Align (MemoryStream str, int val) 
498                 {
499                         if ((str.Position % val) != 0) {
500                                 for (int i=val - (int)(str.Position % val); i > 0; i--) {
501                                         str.WriteByte(0);
502                                 }
503                         }
504                 }
505
506                 private uint Align(uint val, uint alignVal) 
507                 {
508                         if ((val % alignVal) != 0) {
509                                 val += alignVal - (val % alignVal);
510                         }
511                         return val;
512                 }
513
514                 private uint NumToAlign(uint val, uint alignVal) 
515                 {
516                         if ((val % alignVal) == 0) return 0;
517                         return alignVal - (val % alignVal);
518                 }
519
520                 internal void StringsIndex(uint ix) 
521                 {
522                         if (largeStrings) Write(ix);
523                         else Write((ushort)ix);
524                 }
525
526                 internal void GUIDIndex(uint ix) 
527                 {
528                         if (largeGUID) Write(ix);
529                         else Write((ushort)ix);
530                 }
531
532                 internal void USIndex(uint ix) 
533                 {
534                         if (largeUS) Write(ix);
535                         else Write((ushort)ix);
536                 }
537
538                 internal void BlobIndex(uint ix) 
539                 {
540                         if (largeBlob) Write(ix);
541                         else Write((ushort)ix);
542                 }
543
544                 internal void WriteIndex(MDTable tabIx,uint ix) 
545                 {
546                         if (metaData.LargeIx(tabIx)) Write(ix);
547                         else Write((ushort)ix);
548                 }
549
550                 internal void WriteCodedIndex(CIx code, MetaDataElement elem) 
551                 {
552                         metaData.WriteCodedIndex(code,elem,this);
553                 }
554
555                 internal void WriteCodeRVA(uint offs) 
556                 {
557                         Write(text.RVA() + offs);
558                 }
559
560                 internal void WriteDataRVA(uint offs) 
561                 {
562                         Write(sdata.RVA() + offs);
563                 }
564
565                 internal void Write3Bytes(uint val) 
566                 {
567                         byte b3 = (byte)((val & FileImage.iByteMask[2]) >> 16);
568                         byte b2 = (byte)((val & FileImage.iByteMask[1]) >> 8);;
569                         byte b1 = (byte)(val & FileImage.iByteMask[0]);
570                         Write(b1);
571                         Write(b2);
572                         Write(b3);
573                 }
574
575                 internal bool ReserveStrongNameSignatureSpace {
576                         get { return reserveStrongNameSignatureSpace; }
577                         set { reserveStrongNameSignatureSpace = value; }
578                 }
579
580         }
581
582         /**************************************************************************/  
583         /// <summary>
584         /// Base class for the PEFile (starting point)
585         /// </summary>
586         public class PEFile {
587
588                 private static readonly string mscorlibName = "mscorlib";
589                 private Module thisMod;
590                 private ClassDef moduleClass;
591                 private ArrayList classRefList = new ArrayList();
592                 private ArrayList classDefList = new ArrayList();
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, Type retType, Param[] pars) 
764                 {
765                         return moduleClass.AddMethod(name,retType,pars);
766                 }
767
768                 /// <summary>
769                 /// Add a "global" method to this module
770                 /// </summary>
771                 /// <param name="mAtts">method attributes</param>
772                 /// <param name="iAtts">method implementation attributes</param>
773                 /// <param name="name">method name</param>
774                 /// <param name="retType">return type</param>
775                 /// <param name="pars">method parameters</param>
776                 /// <returns>a descriptor for this new "global" method</returns>
777                 public MethodDef AddMethod(MethAttr mAtts, ImplAttr iAtts, string name, Type retType, Param[] pars) 
778                 {
779                         return moduleClass.AddMethod(mAtts,iAtts,name,retType,pars);
780                 }
781
782                 public MethodRef AddMethodToTypeSpec (Type item, string name, Type retType, Type[] pars) 
783                 {
784                         return AddMethodToTypeSpec (item, name, retType, pars, 0);
785                 }
786                 
787                 public MethodRef AddMethodToTypeSpec (Type item, string name, Type retType, Type[] pars, int gen_param_count) 
788                 {
789                         MethodRef meth = new MethodRef (item.GetTypeSpec (metaData), name, retType, pars, false, null, gen_param_count);
790                         metaData.AddToTable (MDTable.MemberRef,meth);
791                         return meth;
792                 }
793
794                 public MethodRef AddVarArgMethodToTypeSpec (Type item, string name, Type retType,
795                                 Type[] pars, Type[] optPars) {
796                         MethodRef meth = new MethodRef(item.GetTypeSpec (metaData), name,retType,pars,true,optPars, 0);
797                         metaData.AddToTable(MDTable.MemberRef,meth);
798                         return meth;
799                 }
800
801                 public FieldRef AddFieldToTypeSpec (Type item, string name, Type fType) 
802                 {
803                         FieldRef field = new FieldRef (item.GetTypeSpec (metaData), name,fType);
804                         metaData.AddToTable (MDTable.MemberRef,field);
805                         return field;
806                 }
807
808                 public Method AddMethodSpec (Method m, GenericMethodSig g_sig)
809                 {
810                         MethodSpec ms = new MethodSpec (m, g_sig);
811                         metaData.AddToTable (MDTable.MethodSpec, ms);
812                         return ms;
813                 }
814
815                 /// <summary>
816                 /// Add a "global" field to this module
817                 /// </summary>
818                 /// <param name="name">field name</param>
819                 /// <param name="fType">field type</param>
820                 /// <returns>a descriptor for this new "global" field</returns>
821                 public FieldDef AddField(string name, Type fType) 
822                 {
823                         return moduleClass.AddField(name,fType);
824                 }
825
826                 /// <summary>
827                 /// Add a "global" field to this module
828                 /// </summary>
829                 /// <param name="attrSet">attributes of this field</param>
830                 /// <param name="name">field name</param>
831                 /// <param name="fType">field type</param>
832                 /// <returns>a descriptor for this new "global" field</returns>
833                 public FieldDef AddField(FieldAttr attrSet, string name, Type fType) 
834                 {
835                         return moduleClass.AddField(attrSet,name,fType);
836                 }
837
838                 /// <summary>
839                 /// Add a class to this module
840                 /// </summary>
841                 /// <param name="attrSet">attributes of this class</param>
842                 /// <param name="nsName">name space name</param>
843                 /// <param name="name">class name</param>
844                 /// <returns>a descriptor for this new class</returns>
845                 public ClassDef AddClass(TypeAttr attrSet, string nsName, string name) 
846                 {
847                         return AddClass (attrSet, nsName, name, null);
848                 }
849
850                 /// <summary>
851                 /// Add a class which extends System.ValueType to this module
852                 /// </summary>
853                 /// <param name="attrSet">attributes of this class</param>
854                 /// <param name="nsName">name space name</param>
855                 /// <param name="name">class name</param>
856                 /// <returns>a descriptor for this new class</returns>
857                 public ClassDef AddValueClass(TypeAttr attrSet, string nsName, string name, ValueClass vClass) 
858                 {
859                         ClassDef aClass = new ClassDef(attrSet,nsName,name,metaData);
860                         if (!ClassDef.IsValueType (nsName, name) && !ClassDef.IsEnum (nsName, name)) {
861                                 aClass.MakeValueClass(vClass);
862                         } else {
863                                 if (ClassDef.IsEnum (nsName, name))
864                                         aClass.SetSuper (metaData.mscorlib.ValueType ());
865                                 else
866                                         aClass.SetSuper (metaData.mscorlib.GetSpecialSystemClass (PrimitiveType.Object));
867
868                                 metaData.mscorlib.SetSpecialSystemClass (nsName, name, aClass);
869                         }
870                         aClass.SetTypeIndex (PrimitiveType.ValueType.GetTypeIndex ());
871                         metaData.AddToTable(MDTable.TypeDef,aClass);
872                         return aClass;
873                 }
874
875                 /// <summary>
876                 /// Add a class to this module
877                 /// </summary>
878                 /// <param name="attrSet">attributes of this class</param>
879                 /// <param name="nsName">name space name</param>
880                 /// <param name="name">class name</param>
881                 /// <param name="superType">super type of this class (extends)</param>
882                 /// <returns>a descriptor for this new class</returns>
883                 public ClassDef AddClass(TypeAttr attrSet, string nsName, string name, Class superType) 
884                 {
885                         ClassDef aClass = new ClassDef(attrSet,nsName,name,metaData);
886                         if (superType != null)
887                                 aClass.SetSuper(superType);
888                         if (PEFile.IsMSCorlib)
889                                 metaData.mscorlib.SetSpecialSystemClass (nsName, name, aClass);
890                         metaData.AddToTable(MDTable.TypeDef,aClass);
891                         return aClass;
892                 }
893
894                 public void  AddGenericClass (GenericTypeInst gti)
895                 {
896                         metaData.AddToTable (MDTable.TypeSpec, gti);
897                 }
898
899                 public void AddGenericParam (GenParam param)
900                 {
901                         metaData.AddToTable (MDTable.TypeSpec, param);
902                 }
903
904                 public FileRef AddFile(string fName, byte[] hashBytes, bool hasMetaData, bool entryPoint) 
905                 {
906                         FileRef file = new FileRef(fName,hashBytes,hasMetaData,entryPoint,metaData);
907                         metaData.AddToTable(MDTable.File,file);
908                         return file;
909                 }
910
911                 /// <summary>
912                 /// Add a manifest resource to this PEFile NOT YET IMPLEMENTED
913                 /// </summary>
914                 /// <param name="mr"></param>
915                 public void AddManifestResource(ManifestResource mr) 
916                 {
917                         metaData.AddToTable(MDTable.ManifestResource,mr);
918                         resources.Add (mr);
919                         //mr.FixName(metaData);
920                 }
921
922                 public void AddCustomAttribute (Method meth, byte [] data, MetaDataElement element)
923                 {
924                         metaData.AddCustomAttribute (new CustomAttribute (element, meth, data));
925                 }
926
927                 public void AddDeclSecurity (SecurityAction sec_action, byte [] data, MetaDataElement element)
928                 {
929                         metaData.AddDeclSecurity (new DeclSecurity (element, (ushort) sec_action, data));
930                 }
931
932                 /// <summary>
933                 /// Add a managed resource from another assembly.
934                 /// </summary>
935                 /// <param name="resName">The name of the resource</param>
936                 /// <param name="assem">The assembly where the resource is</param>
937                 /// <param name="isPublic">Access for the resource</param>
938                 public void AddExternalManagedResource (string resName, AssemblyRef assem, uint flags) 
939                 {
940                         resources.Add (new ManifestResource (resName, flags, assem));
941                 }
942
943                 /// <summary>
944                 /// Add a managed resource from another assembly.
945                 /// </summary>
946                 /// <param name="mr"></param>
947                 /// <param name="isPublic"></param>
948                 public void AddExternalManagedResource (ManifestResource mr) 
949                 {
950                         resources.Add (new ManifestResource (mr));
951                 }
952                 /// <summary>
953                 /// Find a resource
954                 /// </summary>
955                 /// <param name="name">The name of the resource</param>
956                 /// <returns>The resource with the name "name" or null </returns>
957                 public ManifestResource GetResource (string name) 
958                 {
959                         for (int i = 0; i < resources.Count; i ++) {
960                                 if (((ManifestResource) resources [i]).Name == name)
961                                         return (ManifestResource) resources [i];
962                         }
963                         return null;
964                 }
965
966                 public ManifestResource [] GetResources() 
967                 {
968                         return (ManifestResource []) resources.ToArray (typeof (ManifestResource));
969                 }
970
971                 /// <summary>
972                 /// Write out the PEFile (the "bake" function)
973                 /// </summary>
974                 public void WritePEFile() { /* the "bake" function */
975                         if (thisAssembly != null)
976                                 fileImage.ReserveStrongNameSignatureSpace = thisAssembly.HasPublicKey;
977                         fileImage.MakeFile();
978                 }
979
980                 /// <summary>
981                 /// Get the descriptor of this module
982                 /// </summary>
983                 /// <returns>the descriptor for this module</returns>
984                 public Module GetThisModule() 
985                 {
986                         return thisMod;
987                 }
988
989                 /// <summary>
990                 /// Get the descriptor for this assembly.  The PEFile must have been
991                 /// created with hasAssembly = true
992                 /// </summary>
993                 /// <returns>the descriptor for this assembly</returns>
994                 public Assembly GetThisAssembly() 
995                 {
996                         return thisAssembly;
997                 }
998
999         }
1000
1001         /**************************************************************************/  
1002         /// <summary>
1003         /// Descriptor for a Section in a PEFile  eg .text, .sdata
1004         /// </summary>
1005         internal class Section {
1006                 private static readonly uint relocPageSize = 4096;  // 4K pages for fixups
1007
1008                 char[] name; 
1009                 uint offset = 0, tide = 0, size = 0, rva = 0, relocTide = 0;
1010                 //uint relocOff = 0;
1011                 uint flags = 0, padding = 0;
1012                 uint[] relocs; 
1013
1014                 internal Section(string sName, uint sFlags) 
1015                 {
1016                         name = sName.ToCharArray();
1017                         flags = sFlags;
1018                 }
1019
1020                 internal uint Tide() { return tide; }
1021
1022                 internal void IncTide(uint incVal) { tide += incVal; }
1023
1024                 internal uint Padding() { return padding; }
1025
1026                 internal uint Size() { return size; }
1027
1028                 internal void SetSize(uint pad) 
1029                 {
1030                         padding = pad;
1031                         size = tide + padding;
1032                 }
1033
1034                 internal uint RVA() { return rva; }
1035
1036                 internal void SetRVA(uint rva) { this.rva = rva; }
1037
1038                 internal uint Offset() { return offset; }
1039
1040                 internal void SetOffset(uint offs) { offset = offs; }
1041
1042                 internal void DoBlock(BinaryWriter reloc, uint page, int start, int end) 
1043                 {
1044                         //Console.WriteLine("rva = " + rva + "  page = " + page);
1045                         reloc.Write(rva + page);
1046                         reloc.Write((uint)(((end-start+1)*2) + 8));
1047                         for (int j=start; j < end; j++) {
1048                                 //Console.WriteLine("reloc offset = " + relocs[j]);
1049                                 reloc.Write((ushort)((0x3 << 12) | (relocs[j] - page)));
1050                         }
1051                         reloc.Write((ushort)0);
1052                 }
1053
1054                 internal void DoRelocs(BinaryWriter reloc) 
1055                 {
1056                         if (relocTide > 0) {
1057                                 //relocOff = (uint)reloc.Seek(0,SeekOrigin.Current);
1058                                 uint block = (relocs[0]/relocPageSize + 1) * relocPageSize;
1059                                 int start = 0;
1060                                 for (int i=1; i < relocTide; i++) {
1061                                         if (relocs[i] >= block) {
1062                                                 DoBlock(reloc,block-relocPageSize,start,i);
1063                                                 start = i;
1064                                                 block = (relocs[i]/relocPageSize + 1) * relocPageSize;
1065                                         }
1066                                 }
1067                                 DoBlock(reloc,block-relocPageSize,start,(int)relocTide);
1068                         }
1069                 }
1070
1071                 internal void AddReloc(uint offs) 
1072                 {
1073                         int pos = 0;
1074                         if (relocs == null) {
1075                                 relocs = new uint[5];
1076                         } else {
1077                                 if (relocTide >= relocs.Length) {
1078                                         uint[] tmp = relocs;
1079                                         relocs = new uint[tmp.Length + 5];
1080                                         for (int i=0; i < relocTide; i++) {
1081                                                 relocs[i] = tmp[i];
1082                                         }
1083                                 }
1084                                 while ((pos < relocTide) && (relocs[pos] < offs)) pos++;
1085                                 for (int i=pos; i < relocTide; i++) {
1086                                         relocs[i+1] = relocs[i];
1087                                 }
1088                         }
1089                         relocs[pos] = offs;
1090                         relocTide++;    
1091                 }
1092
1093                 internal void WriteHeader(BinaryWriter output, uint relocRVA) 
1094                 {
1095                         output.Write(name);
1096                         output.Write(tide);
1097                         output.Write(rva);
1098                         output.Write(size);
1099                         output.Write(offset);
1100                         output.Write(0);
1101                         //output.Write(relocRVA + relocOff);
1102                         output.Write(0);
1103                         output.Write(0);
1104                         //output.Write((ushort)relocTide);
1105                         //output.Write((ushort)0);
1106                         output.Write(flags);
1107                 }
1108
1109         }
1110
1111         public class Hex {
1112                 readonly static char[] hexDigit = {'0','1','2','3','4','5','6','7',
1113                         '8','9','A','B','C','D','E','F'};
1114                 readonly static uint[] iByteMask = {0x000000FF, 0x0000FF00, 0x00FF0000, 0xFF000000};
1115                 readonly static ulong[] lByteMask = {0x00000000000000FF, 0x000000000000FF00, 
1116                         0x0000000000FF0000, 0x00000000FF000000,
1117                         0x000000FF00000000, 0x0000FF0000000000,
1118                         0x00FF000000000000, 0xFF00000000000000 };
1119                 readonly static uint nibble0Mask = 0x0000000F;
1120                 readonly static uint nibble1Mask = 0x000000F0;
1121
1122                 public static String Byte(int b) 
1123                 {
1124                         char[] str = new char[2];
1125                         uint num = (uint)b;
1126                         uint b1 = num & nibble0Mask;
1127                         uint b2 = (num & nibble1Mask) >> 4;
1128                         str[0] = hexDigit[b2];
1129                         str[1] = hexDigit[b1];
1130                         return new String(str);
1131                 }
1132
1133                 public static String Short(int b) 
1134                 {
1135                         char[] str = new char[4];
1136                         uint num1 = (uint)b & iByteMask[0];
1137                         uint num2 = ((uint)b & iByteMask[1]) >> 8;
1138                         uint b1 = num1 & nibble0Mask;
1139                         uint b2 = (num1 & nibble1Mask) >> 4;
1140                         uint b3 = num2 & nibble0Mask;
1141                         uint b4 = (num2 & nibble1Mask) >> 4;
1142                         str[0] = hexDigit[b4];
1143                         str[1] = hexDigit[b3];
1144                         str[2] = hexDigit[b2];
1145                         str[3] = hexDigit[b1];
1146                         return new String(str);
1147                 }
1148
1149                 public static String Int(int val) 
1150                 {
1151                         char[] str = new char[8];
1152                         uint num = (uint)val;
1153                         int strIx = 7;
1154                         for (int i=0; i < iByteMask.Length; i++) {
1155                                 uint b = num & iByteMask[i];
1156                                 b >>= (i*8);
1157                                 uint b1 = b & nibble0Mask;
1158                                 uint b2 = (b & nibble1Mask) >> 4;
1159                                 str[strIx--] = hexDigit[b1];
1160                                 str[strIx--] = hexDigit[b2];
1161                         }
1162                         return new String(str);
1163                 }
1164
1165                 public static String Int(uint num) 
1166                 {
1167                         char[] str = new char[8];
1168                         int strIx = 7;
1169                         for (int i=0; i < iByteMask.Length; i++) {
1170                                 uint b = num & iByteMask[i];
1171                                 b >>= (i*8);
1172                                 uint b1 = b & nibble0Mask;
1173                                 uint b2 = (b & nibble1Mask) >> 4;
1174                                 str[strIx--] = hexDigit[b1];
1175                                 str[strIx--] = hexDigit[b2];
1176                         }
1177                         return new String(str);
1178                 }
1179
1180                 public static String Long(long lnum) 
1181                 {
1182                         ulong num = (ulong)lnum;
1183                         char[] str = new char[16];
1184                         int strIx = 15;
1185                         for (int i=0; i < lByteMask.Length; i++) {
1186                                 ulong b = num & lByteMask[i];
1187                                 b >>= (i*8);
1188                                 ulong b1 = b & nibble0Mask;
1189                                 ulong b2 = (b & nibble1Mask) >> 4;
1190                                 str[strIx--] = hexDigit[b1];
1191                                 str[strIx--] = hexDigit[b2];
1192                         }
1193                         return new String(str);
1194                 }
1195         }
1196
1197         /// <summary>
1198         /// Error for invalid PE file
1199         /// </summary>
1200         public class PEFileException : System.Exception {
1201                 public PEFileException(string msg) : base(msg) { }
1202         }
1203
1204         public class NotYetImplementedException : System.Exception  {
1205                 public NotYetImplementedException(string msg) : base(msg + " Not Yet Implemented") { }
1206         }
1207
1208         public class TypeSignatureException : System.Exception {
1209                 public TypeSignatureException(string msg) : base(msg) { }
1210         }
1211
1212 }