[sgen] Evacuate from emptier blocks to fuller ones
[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                 public PrimitiveTypeRef AddPrimitiveType (PrimitiveType type)
927                 {
928                         return new PrimitiveTypeRef (type, metaData);
929                 }
930
931                 /// <summary>
932                 /// Add a manifest resource to this PEFile NOT YET IMPLEMENTED
933                 /// </summary>
934                 /// <param name="mr"></param>
935                 public void AddManifestResource(ManifestResource mr) 
936                 {
937                         metaData.AddToTable(MDTable.ManifestResource,mr);
938                         resources.Add (mr);
939                         //mr.FixName(metaData);
940                 }
941
942                 public void AddCustomAttribute (Method meth, byte [] data, MetaDataElement element)
943                 {
944                         metaData.AddCustomAttribute (new CustomAttribute (element, meth, data));
945                         element.HasCustomAttr = true;
946                 }
947
948                 public void AddCustomAttribute (Method meth, Constant constant, MetaDataElement element)
949                 {
950                         metaData.AddCustomAttribute (new CustomAttribute (element, meth, constant));
951                         element.HasCustomAttr = true;
952                 }
953
954                 public void AddDeclSecurity (SecurityAction sec_action, byte [] data, MetaDataElement element)
955                 {
956                         metaData.AddDeclSecurity (new DeclSecurity (element, (ushort) sec_action, data));
957                 }
958
959                 public void AddDeclSecurity (SecurityAction sec_action, PEAPI.PermissionSet ps, MetaDataElement element)
960                 {
961                         metaData.AddDeclSecurity (new DeclSecurity_20 (element, (ushort) sec_action, ps));
962                 }
963
964                 /// <summary>
965                 /// Add a managed resource from another assembly.
966                 /// </summary>
967                 /// <param name="resName">The name of the resource</param>
968                 /// <param name="assem">The assembly where the resource is</param>
969                 /// <param name="isPublic">Access for the resource</param>
970                 public void AddExternalManagedResource (string resName, AssemblyRef assem, uint flags) 
971                 {
972                         resources.Add (new ManifestResource (resName, flags, assem));
973                 }
974
975                 /// <summary>
976                 /// Add a managed resource from another assembly.
977                 /// </summary>
978                 /// <param name="mr"></param>
979                 /// <param name="isPublic"></param>
980                 public void AddExternalManagedResource (ManifestResource mr) 
981                 {
982                         resources.Add (new ManifestResource (mr));
983                 }
984                 /// <summary>
985                 /// Find a resource
986                 /// </summary>
987                 /// <param name="name">The name of the resource</param>
988                 /// <returns>The resource with the name "name" or null </returns>
989                 public ManifestResource GetResource (string name) 
990                 {
991                         for (int i = 0; i < resources.Count; i ++) {
992                                 if (((ManifestResource) resources [i]).Name == name)
993                                         return (ManifestResource) resources [i];
994                         }
995                         return null;
996                 }
997
998                 public ManifestResource [] GetResources() 
999                 {
1000                         return (ManifestResource []) resources.ToArray (typeof (ManifestResource));
1001                 }
1002
1003                 /// <summary>
1004                 /// Write out the PEFile (the "bake" function)
1005                 /// </summary>
1006                 public void WritePEFile() { /* the "bake" function */
1007                         if (thisAssembly != null)
1008                                 fileImage.ReserveStrongNameSignatureSpace = thisAssembly.HasPublicKey;
1009                         fileImage.MakeFile();
1010                 }
1011
1012                 /// <summary>
1013                 /// Get the descriptor of this module
1014                 /// </summary>
1015                 /// <returns>the descriptor for this module</returns>
1016                 public Module GetThisModule() 
1017                 {
1018                         return thisMod;
1019                 }
1020
1021                 /// <summary>
1022                 /// Get the descriptor for this assembly.  The PEFile must have been
1023                 /// created with hasAssembly = true
1024                 /// </summary>
1025                 /// <returns>the descriptor for this assembly</returns>
1026                 public Assembly GetThisAssembly() 
1027                 {
1028                         return thisAssembly;
1029                 }
1030
1031         }
1032
1033         /**************************************************************************/  
1034         /// <summary>
1035         /// Descriptor for a Section in a PEFile  eg .text, .sdata
1036         /// </summary>
1037         internal class Section {
1038                 private static readonly uint relocPageSize = 4096;  // 4K pages for fixups
1039
1040                 char[] name; 
1041                 uint offset = 0, tide = 0, size = 0, rva = 0, relocTide = 0;
1042                 //uint relocOff = 0;
1043                 uint flags = 0, padding = 0;
1044                 uint[] relocs; 
1045
1046                 internal Section(string sName, uint sFlags) 
1047                 {
1048                         name = sName.ToCharArray();
1049                         flags = sFlags;
1050                 }
1051
1052                 internal uint Tide() { return tide; }
1053
1054                 internal void IncTide(uint incVal) { tide += incVal; }
1055
1056                 internal uint Padding() { return padding; }
1057
1058                 internal uint Size() { return size; }
1059
1060                 internal void SetSize(uint pad) 
1061                 {
1062                         padding = pad;
1063                         size = tide + padding;
1064                 }
1065
1066                 internal uint RVA() { return rva; }
1067
1068                 internal void SetRVA(uint rva) { this.rva = rva; }
1069
1070                 internal uint Offset() { return offset; }
1071
1072                 internal void SetOffset(uint offs) { offset = offs; }
1073
1074                 internal void DoBlock(BinaryWriter reloc, uint page, int start, int end) 
1075                 {
1076                         //Console.WriteLine("rva = " + rva + "  page = " + page);
1077                         reloc.Write(rva + page);
1078                         reloc.Write((uint)(((end-start+1)*2) + 8));
1079                         for (int j=start; j < end; j++) {
1080                                 //Console.WriteLine("reloc offset = " + relocs[j]);
1081                                 reloc.Write((ushort)((0x3 << 12) | (relocs[j] - page)));
1082                         }
1083                         reloc.Write((ushort)0);
1084                 }
1085
1086                 internal void DoRelocs(BinaryWriter reloc) 
1087                 {
1088                         if (relocTide > 0) {
1089                                 //relocOff = (uint)reloc.Seek(0,SeekOrigin.Current);
1090                                 uint block = (relocs[0]/relocPageSize + 1) * relocPageSize;
1091                                 int start = 0;
1092                                 for (int i=1; i < relocTide; i++) {
1093                                         if (relocs[i] >= block) {
1094                                                 DoBlock(reloc,block-relocPageSize,start,i);
1095                                                 start = i;
1096                                                 block = (relocs[i]/relocPageSize + 1) * relocPageSize;
1097                                         }
1098                                 }
1099                                 DoBlock(reloc,block-relocPageSize,start,(int)relocTide);
1100                         }
1101                 }
1102
1103                 internal void AddReloc(uint offs) 
1104                 {
1105                         int pos = 0;
1106                         if (relocs == null) {
1107                                 relocs = new uint[5];
1108                         } else {
1109                                 if (relocTide >= relocs.Length) {
1110                                         uint[] tmp = relocs;
1111                                         relocs = new uint[tmp.Length + 5];
1112                                         for (int i=0; i < relocTide; i++) {
1113                                                 relocs[i] = tmp[i];
1114                                         }
1115                                 }
1116                                 while ((pos < relocTide) && (relocs[pos] < offs)) pos++;
1117                                 for (int i=pos; i < relocTide; i++) {
1118                                         relocs[i+1] = relocs[i];
1119                                 }
1120                         }
1121                         relocs[pos] = offs;
1122                         relocTide++;    
1123                 }
1124
1125                 internal void WriteHeader(BinaryWriter output, uint relocRVA) 
1126                 {
1127                         output.Write(name);
1128                         output.Write(tide);
1129                         output.Write(rva);
1130                         output.Write(size);
1131                         output.Write(offset);
1132                         output.Write(0);
1133                         //output.Write(relocRVA + relocOff);
1134                         output.Write(0);
1135                         output.Write(0);
1136                         //output.Write((ushort)relocTide);
1137                         //output.Write((ushort)0);
1138                         output.Write(flags);
1139                 }
1140
1141         }
1142
1143         public class Hex {
1144                 readonly static char[] hexDigit = {'0','1','2','3','4','5','6','7',
1145                         '8','9','A','B','C','D','E','F'};
1146                 readonly static uint[] iByteMask = {0x000000FF, 0x0000FF00, 0x00FF0000, 0xFF000000};
1147                 readonly static ulong[] lByteMask = {0x00000000000000FF, 0x000000000000FF00, 
1148                         0x0000000000FF0000, 0x00000000FF000000,
1149                         0x000000FF00000000, 0x0000FF0000000000,
1150                         0x00FF000000000000, 0xFF00000000000000 };
1151                 readonly static uint nibble0Mask = 0x0000000F;
1152                 readonly static uint nibble1Mask = 0x000000F0;
1153
1154                 public static String Byte(int b) 
1155                 {
1156                         char[] str = new char[2];
1157                         uint num = (uint)b;
1158                         uint b1 = num & nibble0Mask;
1159                         uint b2 = (num & nibble1Mask) >> 4;
1160                         str[0] = hexDigit[b2];
1161                         str[1] = hexDigit[b1];
1162                         return new String(str);
1163                 }
1164
1165                 public static String Short(int b) 
1166                 {
1167                         char[] str = new char[4];
1168                         uint num1 = (uint)b & iByteMask[0];
1169                         uint num2 = ((uint)b & iByteMask[1]) >> 8;
1170                         uint b1 = num1 & nibble0Mask;
1171                         uint b2 = (num1 & nibble1Mask) >> 4;
1172                         uint b3 = num2 & nibble0Mask;
1173                         uint b4 = (num2 & nibble1Mask) >> 4;
1174                         str[0] = hexDigit[b4];
1175                         str[1] = hexDigit[b3];
1176                         str[2] = hexDigit[b2];
1177                         str[3] = hexDigit[b1];
1178                         return new String(str);
1179                 }
1180
1181                 public static String Int(int val) 
1182                 {
1183                         char[] str = new char[8];
1184                         uint num = (uint)val;
1185                         int strIx = 7;
1186                         for (int i=0; i < iByteMask.Length; i++) {
1187                                 uint b = num & iByteMask[i];
1188                                 b >>= (i*8);
1189                                 uint b1 = b & nibble0Mask;
1190                                 uint b2 = (b & nibble1Mask) >> 4;
1191                                 str[strIx--] = hexDigit[b1];
1192                                 str[strIx--] = hexDigit[b2];
1193                         }
1194                         return new String(str);
1195                 }
1196
1197                 public static String Int(uint num) 
1198                 {
1199                         char[] str = new char[8];
1200                         int strIx = 7;
1201                         for (int i=0; i < iByteMask.Length; i++) {
1202                                 uint b = num & iByteMask[i];
1203                                 b >>= (i*8);
1204                                 uint b1 = b & nibble0Mask;
1205                                 uint b2 = (b & nibble1Mask) >> 4;
1206                                 str[strIx--] = hexDigit[b1];
1207                                 str[strIx--] = hexDigit[b2];
1208                         }
1209                         return new String(str);
1210                 }
1211
1212                 public static String Long(long lnum) 
1213                 {
1214                         ulong num = (ulong)lnum;
1215                         char[] str = new char[16];
1216                         int strIx = 15;
1217                         for (int i=0; i < lByteMask.Length; i++) {
1218                                 ulong b = num & lByteMask[i];
1219                                 b >>= (i*8);
1220                                 ulong b1 = b & nibble0Mask;
1221                                 ulong b2 = (b & nibble1Mask) >> 4;
1222                                 str[strIx--] = hexDigit[b1];
1223                                 str[strIx--] = hexDigit[b2];
1224                         }
1225                         return new String(str);
1226                 }
1227         }
1228
1229         /// <summary>
1230         /// Error for invalid PE file
1231         /// </summary>
1232         public class PEFileException : System.Exception {
1233                 public PEFileException(string msg) : base(msg) { }
1234         }
1235
1236         public class NotYetImplementedException : System.Exception  {
1237                 public NotYetImplementedException(string msg) : base(msg + " Not Yet Implemented") { }
1238         }
1239
1240         public class TypeSignatureException : System.Exception {
1241                 public TypeSignatureException(string msg) : base(msg) { }
1242         }
1243
1244 }