[MSBuild] Fix minor assembly resolution issue
[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                 public ClassRef AddExternClass(string ns, string name, TypeAttr attrs, MetaDataElement declRef)
757                 {
758                         return new ExternClassRef (attrs, ns, name, declRef, metaData);
759                 }
760                 
761                 /// <summary>
762                 /// Add a "global" method to this module
763                 /// </summary>
764                 /// <param name="name">method name</param>
765                 /// <param name="retType">return type</param>
766                 /// <param name="pars">method parameters</param>
767                 /// <returns>a descriptor for this new "global" method</returns>
768                 public MethodDef AddMethod (string name, Param ret_param, Param [] pars) 
769                 {
770                         return moduleClass.AddMethod (name, ret_param, pars);
771                 }
772                 
773                 public MethodDef AddMethod(string name, Type retType, Param[] pars) 
774                 {
775                         return AddMethod (name, new Param (ParamAttr.Default, "", retType), pars);
776                 }
777
778                 /// <summary>
779                 /// Add a "global" method to this module
780                 /// </summary>
781                 /// <param name="mAtts">method attributes</param>
782                 /// <param name="iAtts">method implementation attributes</param>
783                 /// <param name="name">method name</param>
784                 /// <param name="retType">return type</param>
785                 /// <param name="pars">method parameters</param>
786                 /// <returns>a descriptor for this new "global" method</returns>
787                 public MethodDef AddMethod (MethAttr mAtts, ImplAttr iAtts, string name, Param ret_param, Param [] pars) 
788                 {
789                         return moduleClass.AddMethod (mAtts, iAtts, name, ret_param, pars);
790                 }
791
792                 public MethodDef AddMethod(MethAttr mAtts, ImplAttr iAtts, string name, Type retType, Param[] pars) 
793                 {
794                         return AddMethod (mAtts, iAtts, name, new Param (ParamAttr.Default, "", retType), pars);
795                 }
796
797                 public MethodRef AddMethodToTypeSpec (Type item, string name, Type retType, Type[] pars) 
798                 {
799                         return AddMethodToTypeSpec (item, name, retType, pars, 0);
800                 }
801                 
802                 public MethodRef AddMethodToTypeSpec (Type item, string name, Type retType, Type[] pars, int gen_param_count) 
803                 {
804                         MethodRef meth = new MethodRef (item.GetTypeSpec (metaData), name, retType, pars, false, null, gen_param_count);
805                         metaData.AddToTable (MDTable.MemberRef,meth);
806                         return meth;
807                 }
808
809                 public MethodRef AddVarArgMethodToTypeSpec (Type item, string name, Type retType,
810                                 Type[] pars, Type[] optPars) {
811                         MethodRef meth = new MethodRef(item.GetTypeSpec (metaData), name,retType,pars,true,optPars, 0);
812                         metaData.AddToTable(MDTable.MemberRef,meth);
813                         return meth;
814                 }
815
816                 public FieldRef AddFieldToTypeSpec (Type item, string name, Type fType) 
817                 {
818                         FieldRef field = new FieldRef (item.GetTypeSpec (metaData), name,fType);
819                         metaData.AddToTable (MDTable.MemberRef,field);
820                         return field;
821                 }
822
823                 public Method AddMethodSpec (Method m, GenericMethodSig g_sig)
824                 {
825                         MethodSpec ms = new MethodSpec (m, g_sig);
826                         metaData.AddToTable (MDTable.MethodSpec, ms);
827                         return ms;
828                 }
829
830                 /// <summary>
831                 /// Add a "global" field to this module
832                 /// </summary>
833                 /// <param name="name">field name</param>
834                 /// <param name="fType">field type</param>
835                 /// <returns>a descriptor for this new "global" field</returns>
836                 public FieldDef AddField(string name, Type fType) 
837                 {
838                         return moduleClass.AddField(name,fType);
839                 }
840
841                 /// <summary>
842                 /// Add a "global" field to this module
843                 /// </summary>
844                 /// <param name="attrSet">attributes of this field</param>
845                 /// <param name="name">field name</param>
846                 /// <param name="fType">field type</param>
847                 /// <returns>a descriptor for this new "global" field</returns>
848                 public FieldDef AddField(FieldAttr attrSet, string name, Type fType) 
849                 {
850                         return moduleClass.AddField(attrSet,name,fType);
851                 }
852
853                 /// <summary>
854                 /// Add a class to this module
855                 /// </summary>
856                 /// <param name="attrSet">attributes of this class</param>
857                 /// <param name="nsName">name space name</param>
858                 /// <param name="name">class name</param>
859                 /// <returns>a descriptor for this new class</returns>
860                 public ClassDef AddClass(TypeAttr attrSet, string nsName, string name) 
861                 {
862                         return AddClass (attrSet, nsName, name, null);
863                 }
864
865                 /// <summary>
866                 /// Add a class which extends System.ValueType to this module
867                 /// </summary>
868                 /// <param name="attrSet">attributes of this class</param>
869                 /// <param name="nsName">name space name</param>
870                 /// <param name="name">class name</param>
871                 /// <returns>a descriptor for this new class</returns>
872                 public ClassDef AddValueClass(TypeAttr attrSet, string nsName, string name, ValueClass vClass) 
873                 {
874                         ClassDef aClass = new ClassDef(attrSet,nsName,name,metaData);
875                         if (!ClassDef.IsValueType (nsName, name) && !ClassDef.IsEnum (nsName, name)) {
876                                 aClass.MakeValueClass(vClass);
877                         } else {
878                                 if (ClassDef.IsEnum (nsName, name))
879                                         aClass.SetSuper (metaData.mscorlib.ValueType ());
880                                 else
881                                         aClass.SetSuper (metaData.mscorlib.GetSpecialSystemClass (PrimitiveType.Object));
882
883                                 metaData.mscorlib.SetSpecialSystemClass (nsName, name, aClass);
884                         }
885                         aClass.SetTypeIndex (PrimitiveType.ValueType.GetTypeIndex ());
886                         metaData.AddToTable(MDTable.TypeDef,aClass);
887                         return aClass;
888                 }
889
890                 /// <summary>
891                 /// Add a class to this module
892                 /// </summary>
893                 /// <param name="attrSet">attributes of this class</param>
894                 /// <param name="nsName">name space name</param>
895                 /// <param name="name">class name</param>
896                 /// <param name="superType">super type of this class (extends)</param>
897                 /// <returns>a descriptor for this new class</returns>
898                 public ClassDef AddClass(TypeAttr attrSet, string nsName, string name, Class superType) 
899                 {
900                         ClassDef aClass = new ClassDef(attrSet,nsName,name,metaData);
901                         if (superType != null)
902                                 aClass.SetSuper(superType);
903                         if (PEFile.IsMSCorlib)
904                                 metaData.mscorlib.SetSpecialSystemClass (nsName, name, aClass);
905                         metaData.AddToTable(MDTable.TypeDef,aClass);
906                         return aClass;
907                 }
908
909                 public void  AddGenericClass (GenericTypeInst gti)
910                 {
911                         metaData.AddToTable (MDTable.TypeSpec, gti);
912                 }
913
914                 public void AddGenericParam (GenParam param)
915                 {
916                         metaData.AddToTable (MDTable.TypeSpec, param);
917                 }
918
919                 public FileRef AddFile(string fName, byte[] hashBytes, bool hasMetaData, bool entryPoint) 
920                 {
921                         FileRef file = new FileRef(fName,hashBytes,hasMetaData,entryPoint,metaData);
922                         metaData.AddToTable(MDTable.File,file);
923                         return file;
924                 }
925
926                 /// <summary>
927                 /// Add a manifest resource to this PEFile NOT YET IMPLEMENTED
928                 /// </summary>
929                 /// <param name="mr"></param>
930                 public void AddManifestResource(ManifestResource mr) 
931                 {
932                         metaData.AddToTable(MDTable.ManifestResource,mr);
933                         resources.Add (mr);
934                         //mr.FixName(metaData);
935                 }
936
937                 public void AddCustomAttribute (Method meth, byte [] data, MetaDataElement element)
938                 {
939                         metaData.AddCustomAttribute (new CustomAttribute (element, meth, data));
940                         element.HasCustomAttr = true;
941                 }
942
943                 public void AddDeclSecurity (SecurityAction sec_action, byte [] data, MetaDataElement element)
944                 {
945                         metaData.AddDeclSecurity (new DeclSecurity (element, (ushort) sec_action, data));
946                 }
947
948                 public void AddDeclSecurity (SecurityAction sec_action, PEAPI.PermissionSet ps, MetaDataElement element)
949                 {
950                         metaData.AddDeclSecurity (new DeclSecurity_20 (element, (ushort) sec_action, ps));
951                 }
952
953                 /// <summary>
954                 /// Add a managed resource from another assembly.
955                 /// </summary>
956                 /// <param name="resName">The name of the resource</param>
957                 /// <param name="assem">The assembly where the resource is</param>
958                 /// <param name="isPublic">Access for the resource</param>
959                 public void AddExternalManagedResource (string resName, AssemblyRef assem, uint flags) 
960                 {
961                         resources.Add (new ManifestResource (resName, flags, assem));
962                 }
963
964                 /// <summary>
965                 /// Add a managed resource from another assembly.
966                 /// </summary>
967                 /// <param name="mr"></param>
968                 /// <param name="isPublic"></param>
969                 public void AddExternalManagedResource (ManifestResource mr) 
970                 {
971                         resources.Add (new ManifestResource (mr));
972                 }
973                 /// <summary>
974                 /// Find a resource
975                 /// </summary>
976                 /// <param name="name">The name of the resource</param>
977                 /// <returns>The resource with the name "name" or null </returns>
978                 public ManifestResource GetResource (string name) 
979                 {
980                         for (int i = 0; i < resources.Count; i ++) {
981                                 if (((ManifestResource) resources [i]).Name == name)
982                                         return (ManifestResource) resources [i];
983                         }
984                         return null;
985                 }
986
987                 public ManifestResource [] GetResources() 
988                 {
989                         return (ManifestResource []) resources.ToArray (typeof (ManifestResource));
990                 }
991
992                 /// <summary>
993                 /// Write out the PEFile (the "bake" function)
994                 /// </summary>
995                 public void WritePEFile() { /* the "bake" function */
996                         if (thisAssembly != null)
997                                 fileImage.ReserveStrongNameSignatureSpace = thisAssembly.HasPublicKey;
998                         fileImage.MakeFile();
999                 }
1000
1001                 /// <summary>
1002                 /// Get the descriptor of this module
1003                 /// </summary>
1004                 /// <returns>the descriptor for this module</returns>
1005                 public Module GetThisModule() 
1006                 {
1007                         return thisMod;
1008                 }
1009
1010                 /// <summary>
1011                 /// Get the descriptor for this assembly.  The PEFile must have been
1012                 /// created with hasAssembly = true
1013                 /// </summary>
1014                 /// <returns>the descriptor for this assembly</returns>
1015                 public Assembly GetThisAssembly() 
1016                 {
1017                         return thisAssembly;
1018                 }
1019
1020         }
1021
1022         /**************************************************************************/  
1023         /// <summary>
1024         /// Descriptor for a Section in a PEFile  eg .text, .sdata
1025         /// </summary>
1026         internal class Section {
1027                 private static readonly uint relocPageSize = 4096;  // 4K pages for fixups
1028
1029                 char[] name; 
1030                 uint offset = 0, tide = 0, size = 0, rva = 0, relocTide = 0;
1031                 //uint relocOff = 0;
1032                 uint flags = 0, padding = 0;
1033                 uint[] relocs; 
1034
1035                 internal Section(string sName, uint sFlags) 
1036                 {
1037                         name = sName.ToCharArray();
1038                         flags = sFlags;
1039                 }
1040
1041                 internal uint Tide() { return tide; }
1042
1043                 internal void IncTide(uint incVal) { tide += incVal; }
1044
1045                 internal uint Padding() { return padding; }
1046
1047                 internal uint Size() { return size; }
1048
1049                 internal void SetSize(uint pad) 
1050                 {
1051                         padding = pad;
1052                         size = tide + padding;
1053                 }
1054
1055                 internal uint RVA() { return rva; }
1056
1057                 internal void SetRVA(uint rva) { this.rva = rva; }
1058
1059                 internal uint Offset() { return offset; }
1060
1061                 internal void SetOffset(uint offs) { offset = offs; }
1062
1063                 internal void DoBlock(BinaryWriter reloc, uint page, int start, int end) 
1064                 {
1065                         //Console.WriteLine("rva = " + rva + "  page = " + page);
1066                         reloc.Write(rva + page);
1067                         reloc.Write((uint)(((end-start+1)*2) + 8));
1068                         for (int j=start; j < end; j++) {
1069                                 //Console.WriteLine("reloc offset = " + relocs[j]);
1070                                 reloc.Write((ushort)((0x3 << 12) | (relocs[j] - page)));
1071                         }
1072                         reloc.Write((ushort)0);
1073                 }
1074
1075                 internal void DoRelocs(BinaryWriter reloc) 
1076                 {
1077                         if (relocTide > 0) {
1078                                 //relocOff = (uint)reloc.Seek(0,SeekOrigin.Current);
1079                                 uint block = (relocs[0]/relocPageSize + 1) * relocPageSize;
1080                                 int start = 0;
1081                                 for (int i=1; i < relocTide; i++) {
1082                                         if (relocs[i] >= block) {
1083                                                 DoBlock(reloc,block-relocPageSize,start,i);
1084                                                 start = i;
1085                                                 block = (relocs[i]/relocPageSize + 1) * relocPageSize;
1086                                         }
1087                                 }
1088                                 DoBlock(reloc,block-relocPageSize,start,(int)relocTide);
1089                         }
1090                 }
1091
1092                 internal void AddReloc(uint offs) 
1093                 {
1094                         int pos = 0;
1095                         if (relocs == null) {
1096                                 relocs = new uint[5];
1097                         } else {
1098                                 if (relocTide >= relocs.Length) {
1099                                         uint[] tmp = relocs;
1100                                         relocs = new uint[tmp.Length + 5];
1101                                         for (int i=0; i < relocTide; i++) {
1102                                                 relocs[i] = tmp[i];
1103                                         }
1104                                 }
1105                                 while ((pos < relocTide) && (relocs[pos] < offs)) pos++;
1106                                 for (int i=pos; i < relocTide; i++) {
1107                                         relocs[i+1] = relocs[i];
1108                                 }
1109                         }
1110                         relocs[pos] = offs;
1111                         relocTide++;    
1112                 }
1113
1114                 internal void WriteHeader(BinaryWriter output, uint relocRVA) 
1115                 {
1116                         output.Write(name);
1117                         output.Write(tide);
1118                         output.Write(rva);
1119                         output.Write(size);
1120                         output.Write(offset);
1121                         output.Write(0);
1122                         //output.Write(relocRVA + relocOff);
1123                         output.Write(0);
1124                         output.Write(0);
1125                         //output.Write((ushort)relocTide);
1126                         //output.Write((ushort)0);
1127                         output.Write(flags);
1128                 }
1129
1130         }
1131
1132         public class Hex {
1133                 readonly static char[] hexDigit = {'0','1','2','3','4','5','6','7',
1134                         '8','9','A','B','C','D','E','F'};
1135                 readonly static uint[] iByteMask = {0x000000FF, 0x0000FF00, 0x00FF0000, 0xFF000000};
1136                 readonly static ulong[] lByteMask = {0x00000000000000FF, 0x000000000000FF00, 
1137                         0x0000000000FF0000, 0x00000000FF000000,
1138                         0x000000FF00000000, 0x0000FF0000000000,
1139                         0x00FF000000000000, 0xFF00000000000000 };
1140                 readonly static uint nibble0Mask = 0x0000000F;
1141                 readonly static uint nibble1Mask = 0x000000F0;
1142
1143                 public static String Byte(int b) 
1144                 {
1145                         char[] str = new char[2];
1146                         uint num = (uint)b;
1147                         uint b1 = num & nibble0Mask;
1148                         uint b2 = (num & nibble1Mask) >> 4;
1149                         str[0] = hexDigit[b2];
1150                         str[1] = hexDigit[b1];
1151                         return new String(str);
1152                 }
1153
1154                 public static String Short(int b) 
1155                 {
1156                         char[] str = new char[4];
1157                         uint num1 = (uint)b & iByteMask[0];
1158                         uint num2 = ((uint)b & iByteMask[1]) >> 8;
1159                         uint b1 = num1 & nibble0Mask;
1160                         uint b2 = (num1 & nibble1Mask) >> 4;
1161                         uint b3 = num2 & nibble0Mask;
1162                         uint b4 = (num2 & nibble1Mask) >> 4;
1163                         str[0] = hexDigit[b4];
1164                         str[1] = hexDigit[b3];
1165                         str[2] = hexDigit[b2];
1166                         str[3] = hexDigit[b1];
1167                         return new String(str);
1168                 }
1169
1170                 public static String Int(int val) 
1171                 {
1172                         char[] str = new char[8];
1173                         uint num = (uint)val;
1174                         int strIx = 7;
1175                         for (int i=0; i < iByteMask.Length; i++) {
1176                                 uint b = num & iByteMask[i];
1177                                 b >>= (i*8);
1178                                 uint b1 = b & nibble0Mask;
1179                                 uint b2 = (b & nibble1Mask) >> 4;
1180                                 str[strIx--] = hexDigit[b1];
1181                                 str[strIx--] = hexDigit[b2];
1182                         }
1183                         return new String(str);
1184                 }
1185
1186                 public static String Int(uint num) 
1187                 {
1188                         char[] str = new char[8];
1189                         int strIx = 7;
1190                         for (int i=0; i < iByteMask.Length; i++) {
1191                                 uint b = num & iByteMask[i];
1192                                 b >>= (i*8);
1193                                 uint b1 = b & nibble0Mask;
1194                                 uint b2 = (b & nibble1Mask) >> 4;
1195                                 str[strIx--] = hexDigit[b1];
1196                                 str[strIx--] = hexDigit[b2];
1197                         }
1198                         return new String(str);
1199                 }
1200
1201                 public static String Long(long lnum) 
1202                 {
1203                         ulong num = (ulong)lnum;
1204                         char[] str = new char[16];
1205                         int strIx = 15;
1206                         for (int i=0; i < lByteMask.Length; i++) {
1207                                 ulong b = num & lByteMask[i];
1208                                 b >>= (i*8);
1209                                 ulong b1 = b & nibble0Mask;
1210                                 ulong b2 = (b & nibble1Mask) >> 4;
1211                                 str[strIx--] = hexDigit[b1];
1212                                 str[strIx--] = hexDigit[b2];
1213                         }
1214                         return new String(str);
1215                 }
1216         }
1217
1218         /// <summary>
1219         /// Error for invalid PE file
1220         /// </summary>
1221         public class PEFileException : System.Exception {
1222                 public PEFileException(string msg) : base(msg) { }
1223         }
1224
1225         public class NotYetImplementedException : System.Exception  {
1226                 public NotYetImplementedException(string msg) : base(msg + " Not Yet Implemented") { }
1227         }
1228
1229         public class TypeSignatureException : System.Exception {
1230                 public TypeSignatureException(string msg) : base(msg) { }
1231         }
1232
1233 }