-using System;\r
-using System.IO;\r
-using System.Collections;\r
-using System.Text;\r
-\r
-namespace PEAPI \r
-{\r
- public class Hex {\r
- readonly static char[] hexDigit = {'0','1','2','3','4','5','6','7',\r
- '8','9','A','B','C','D','E','F'};\r
- readonly static uint[] iByteMask = {0x000000FF, 0x0000FF00, 0x00FF0000, 0xFF000000};\r
- readonly static ulong[] lByteMask = {0x00000000000000FF, 0x000000000000FF00, \r
- 0x0000000000FF0000, 0x00000000FF000000,\r
- 0x000000FF00000000, 0x0000FF0000000000,\r
- 0x00FF000000000000, 0xFF00000000000000 };\r
- readonly static uint nibble0Mask = 0x0000000F;\r
- readonly static uint nibble1Mask = 0x000000F0;\r
-\r
- public static String Byte(int b) {\r
- char[] str = new char[2];\r
- uint num = (uint)b;\r
- uint b1 = num & nibble0Mask;\r
- uint b2 = (num & nibble1Mask) >> 4;\r
- str[0] = hexDigit[b2];\r
- str[1] = hexDigit[b1];\r
- return new String(str);\r
- }\r
-\r
- public static String Short(int b) {\r
- char[] str = new char[4];\r
- uint num1 = (uint)b & iByteMask[0];\r
- uint num2 = ((uint)b & iByteMask[1]) >> 8;\r
- uint b1 = num1 & nibble0Mask;\r
- uint b2 = (num1 & nibble1Mask) >> 4;\r
- uint b3 = num2 & nibble0Mask;\r
- uint b4 = (num2 & nibble1Mask) >> 4;\r
- str[0] = hexDigit[b4];\r
- str[1] = hexDigit[b3];\r
- str[2] = hexDigit[b2];\r
- str[3] = hexDigit[b1];\r
- return new String(str);\r
- }\r
-\r
- public static String Int(int val) {\r
- char[] str = new char[8];\r
- uint num = (uint)val;\r
- int strIx = 7;\r
- for (int i=0; i < iByteMask.Length; i++) {\r
- uint b = num & iByteMask[i];\r
- b >>= (i*8);\r
- uint b1 = b & nibble0Mask;\r
- uint b2 = (b & nibble1Mask) >> 4;\r
- str[strIx--] = hexDigit[b1];\r
- str[strIx--] = hexDigit[b2];\r
- }\r
- return new String(str);\r
- }\r
- \r
- public static String Int(uint num) {\r
- char[] str = new char[8];\r
- int strIx = 7;\r
- for (int i=0; i < iByteMask.Length; i++) {\r
- uint b = num & iByteMask[i];\r
- b >>= (i*8);\r
- uint b1 = b & nibble0Mask;\r
- uint b2 = (b & nibble1Mask) >> 4;\r
- str[strIx--] = hexDigit[b1];\r
- str[strIx--] = hexDigit[b2];\r
- }\r
- return new String(str);\r
- }\r
-\r
- public static String Long(long lnum) {\r
- ulong num = (ulong)lnum;\r
- char[] str = new char[16];\r
- int strIx = 15;\r
- for (int i=0; i < lByteMask.Length; i++) {\r
- ulong b = num & lByteMask[i];\r
- b >>= (i*8);\r
- ulong b1 = b & nibble0Mask;\r
- ulong b2 = (b & nibble1Mask) >> 4;\r
- str[strIx--] = hexDigit[b1];\r
- str[strIx--] = hexDigit[b2];\r
- }\r
- return new String(str);\r
- }\r
- }\r
-\r
- public class NotYetImplementedException : System.Exception \r
- {\r
- public NotYetImplementedException(string msg) : base(msg + " Not Yet Implemented") { }\r
- }\r
-\r
- public class TypeSignatureException : System.Exception {\r
- public TypeSignatureException(string msg) : base(msg) { }\r
- }\r
-\r
- public class ClassRefInst : Type {\r
+using System;
+using System.IO;
+using System.Collections;
+using System.Text;
+
+namespace PEAPI {
+
+ /**************************************************************************/
+ /// <summary>
+ /// Image for a PEFile
+ /// File Structure
+ /// DOS Header (128 bytes)
+ /// PE Signature ("PE\0\0")
+ /// PEFileHeader (20 bytes)
+ /// PEOptionalHeader (224 bytes)
+ /// SectionHeaders (40 bytes * NumSections)
+ ///
+ /// Sections .text (always present - contains metadata)
+ /// .sdata (contains any initialised data in the file - may not be present)
+ /// (for ilams /debug this contains the Debug table)
+ /// .reloc (always present - in pure CIL only has one fixup)
+ /// others??? c# produces .rsrc section containing a Resource Table
+ ///
+ /// .text layout
+ /// IAT (single entry 8 bytes for pure CIL)
+ /// CLIHeader (72 bytes)
+ /// CIL instructions for all methods (variable size)
+ /// MetaData
+ /// Root (20 bytes + UTF-8 Version String + quad align padding)
+ /// StreamHeaders (8 bytes + null terminated name string + quad align padding)
+ /// Streams
+ /// #~ (always present - holds metadata tables)
+ /// #Strings (always present - holds identifier strings)
+ /// #US (Userstring heap)
+ /// #Blob (signature blobs)
+ /// #GUID (guids for assemblies or Modules)
+ /// ImportTable (40 bytes)
+ /// ImportLookupTable(8 bytes) (same as IAT for standard CIL files)
+ /// Hint/Name Tables with entry "_CorExeMain" for .exe file and "_CorDllMain" for .dll (14 bytes)
+ /// ASCII string "mscoree.dll" referenced in ImportTable (+ padding = 16 bytes)
+ /// Entry Point (0xFF25 followed by 4 bytes 0x400000 + RVA of .text)
+ ///
+ /// #~ stream structure
+ /// Header (24 bytes)
+ /// Rows (4 bytes * numTables)
+ /// Tables
+ /// </summary>
+ internal class FileImage : BinaryWriter {
+
+ internal readonly static uint[] iByteMask = {0x000000FF, 0x0000FF00, 0x00FF0000, 0xFF000000};
+ internal readonly static ulong[] lByteMask = {0x00000000000000FF, 0x000000000000FF00,
+ 0x0000000000FF0000, 0x00000000FF000000,
+ 0x000000FF00000000, 0x0000FF0000000000,
+ 0x00FF000000000000, 0xFF00000000000000 };
+ internal readonly static uint nibble0Mask = 0x0000000F;
+ internal readonly static uint nibble1Mask = 0x000000F0;
+
+ private static readonly byte[] DOSHeader = { 0x4d,0x5a,0x90,0x00,0x03,0x00,0x00,0x00,
+ 0x04,0x00,0x00,0x00,0xff,0xff,0x00,0x00,
+ 0xb8,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x40,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x80,0x00,0x00,0x00,
+ 0x0e,0x1f,0xba,0x0e,0x00,0xb4,0x09,0xcd,
+ 0x21,0xb8,0x01,0x4c,0xcd,0x21,0x54,0x68,
+ 0x69,0x73,0x20,0x70,0x72,0x6f,0x67,0x72,
+ 0x61,0x6d,0x20,0x63,0x61,0x6e,0x6e,0x6f,
+ 0x74,0x20,0x62,0x65,0x20,0x72,0x75,0x6e,
+ 0x20,0x69,0x6e,0x20,0x44,0x4f,0x53,0x20,
+ 0x6d,0x6f,0x64,0x65,0x2e,0x0d,0x0d,0x0a,
+ 0x24,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x50,0x45,0x00,0x00};
+ private static byte[] PEHeader = { 0x4c, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0xE0, 0x00, 0x0E, 0x01, // PE Header Standard Fields
+ 0x0B, 0x01, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+ };
+
+ private static readonly uint minFileAlign = 0x200;
+ private static readonly uint maxFileAlign = 0x1000;
+ private static readonly uint fileHeaderSize = 0x178;
+ private static readonly uint sectionHeaderSize = 40;
+ private static readonly uint SectionAlignment = 0x2000;
+ private static readonly uint ImageBase = 0x400000;
+ private static readonly uint ImportTableSize = 40;
+ private static readonly uint IATSize = 8;
+ private static readonly uint CLIHeaderSize = 72;
+ private uint runtimeFlags = 0x01; // COMIMAGE_FLAGS_ILONLY
+ // 32BITREQUIRED 0x02, STRONGNAMESIGNED 0x08, TRACKDEBUGDATA 0x10000
+ private static readonly uint StrongNameSignatureSize = 128;
+ private bool reserveStrongNameSignatureSpace = false;
+
+ private static readonly uint relocFlags = 0x42000040;
+ private static readonly ushort exeCharacteristics = 0x010E;
+ private static readonly ushort dllCharacteristics = 0x210E;
+ // section names are all 8 bytes
+ private static readonly string textName = ".text\0\0\0";
+ private static readonly string sdataName = ".sdata\0\0";
+ private static readonly string relocName = ".reloc\0\0";
+ private static readonly string rsrcName = ".rsrc\0\0\0";
+ private static readonly string exeHintNameTable = "\0\0_CorExeMain\0";
+ private static readonly string dllHintNameTable = "\0\0_CorDllMain\0";
+ private static readonly string runtimeEngineName = "mscoree.dll\0\0";
+
+ private Section text, sdata, rsrc;
+ ArrayList data;
+ BinaryWriter reloc = new BinaryWriter(new MemoryStream());
+ uint dateStamp = 0;
+ DateTime origin = new DateTime(1970,1,1);
+ uint numSections = 2; // always have .text and .reloc sections
+ internal SubSystem subSys = SubSystem.Windows_CUI; // default is Windows Console mode
+ internal long stackReserve = 0x100000; // default is 1Mb
+ internal uint fileAlign = minFileAlign;
+ uint entryPointOffset, entryPointPadding, imageSize, headerSize, headerPadding, entryPointToken = 0;
+ uint relocOffset, relocRVA, relocSize, relocPadding, relocTide, hintNameTableOffset;
+ uint metaDataOffset, runtimeEngineOffset, initDataSize = 0, importTablePadding;
+ uint resourcesSize, resourcesOffset;
+ uint strongNameSigOffset;
+ uint importTableOffset, importLookupTableOffset, totalImportTableSize;
+ MetaData metaData;
+ char[] runtimeEngine = runtimeEngineName.ToCharArray(), hintNameTable;
+ bool doDLL, largeStrings, largeGUID, largeUS, largeBlob;
+ ushort characteristics;
+
+ internal FileImage(bool makeDLL, string fileName) : base(new FileStream(fileName,FileMode.Create))
+ {
+ InitFileImage(makeDLL);
+ TimeSpan tmp = System.IO.File.GetCreationTime(fileName).Subtract(origin);
+ dateStamp = Convert.ToUInt32(tmp.TotalSeconds);
+ }
- private Type type;
- private bool is_value;
-\r
- public ClassRefInst (Type type, bool is_value) : base (0x12) {\r
- this.type = type;
- this.is_value = is_value;
- if (is_value)
- type.SetTypeIndex (0x11);
- tabIx = MDTable.TypeSpec;\r
- }\r
-\r
- internal sealed override void TypeSig(MemoryStream str) {
- type.TypeSig (str);
- }
- }\r
-
- public class MVar : Type {\r
-\r
- private int index;\r
-\r
- public MVar (int index) : base (0x1E) {\r
- this.index = index;\r
- tabIx = MDTable.TypeSpec;\r
- }\r
-\r
- internal sealed override void TypeSig(MemoryStream str) {\r
- str.WriteByte(typeIndex);\r
- MetaData.CompressNum ((uint) index, str);\r
- }\r
- }\r
-\r
- public class GenericTypeSpec : Type {\r
-\r
- private int index;\r
-\r
- public GenericTypeSpec (int index) : base (0x13) {\r
- this.index = index;\r
- tabIx = MDTable.TypeSpec;\r
- }\r
-\r
- internal sealed override void TypeSig(MemoryStream str) {\r
- str.WriteByte(typeIndex);\r
- MetaData.CompressNum ((uint) index, str);\r
- }\r
- }\r
-\r
- public class GenericTypeInst : Type {\r
-\r
- private Type gen_type;\r
- private Type[] gen_param;\r
-\r
- public GenericTypeInst (Type gen_type, Type[] gen_param) : base (0x15)\r
- {\r
- typeIndex = 0x15;\r
- this.gen_type = gen_type;\r
- this.gen_param = gen_param;\r
- tabIx = MDTable.TypeSpec;\r
- }\r
-\r
- internal sealed override void TypeSig(MemoryStream str) {\r
- str.WriteByte(typeIndex);\r
- gen_type.TypeSig (str);\r
- MetaData.CompressNum ((uint) gen_param.Length, str);\r
- foreach (Type param in gen_param)\r
- param.TypeSig (str);\r
- }\r
- }\r
+ internal FileImage(bool makeDLL, Stream str) : base(str)
+ {
+ InitFileImage(makeDLL);
+ TimeSpan tmp = DateTime.Now.Subtract(origin);
+ dateStamp = Convert.ToUInt32(tmp.TotalSeconds);
+ }
- public class GenericMethodSig {
+ private void InitFileImage(bool makeDLL)
+ {
+ doDLL = makeDLL;
+ if (doDLL) {
+ hintNameTable = dllHintNameTable.ToCharArray();
+ characteristics = dllCharacteristics;
+ } else {
+ hintNameTable = exeHintNameTable.ToCharArray();
+ characteristics = exeCharacteristics;
+ }
+ text = new Section(textName,0x60000020); // IMAGE_SCN_CNT CODE, EXECUTE, READ
+ // rsrc = new Section(rsrcName,0x40000040); // IMAGE_SCN_CNT INITIALIZED_DATA, READ
+ metaData = new MetaData(this);
+ }
- private Type[] gen_param;
+ internal MetaData GetMetaData()
+ {
+ return metaData;
+ }
- public GenericMethodSig (Type[] gen_param)
- {
- this.gen_param = gen_param;
- }
+ private uint GetNextSectStart(uint rva, uint tide)
+ {
+ if (tide < SectionAlignment) return rva + SectionAlignment;
+ return rva + ((tide / SectionAlignment) + 1) * SectionAlignment;
+ }
- internal void TypeSig (MemoryStream str)
- {
- MetaData.CompressNum ((uint) gen_param.Length, str); // THIS IS NOT RIGHT, but works
- MetaData.CompressNum ((uint) gen_param.Length, str);
- foreach (Type param in gen_param)
- param.TypeSig (str);
- }
+ private void BuildTextSection()
+ {
+ // .text layout
+ // IAT (single entry 8 bytes for pure CIL)
+ // CLIHeader (72 bytes)
+ // CIL instructions for all methods (variable size)
+ // MetaData
+ // ImportTable (40 bytes)
+ // ImportLookupTable(8 bytes) (same as IAT for standard CIL files)
+ // Hint/Name Tables with entry "_CorExeMain" for .exe file and "_CorDllMain" for .dll (14 bytes)
+ // ASCII string "mscoree.dll" referenced in ImportTable (+ padding = 16 bytes)
+ // Entry Point (0xFF25 followed by 4 bytes 0x400000 + RVA of .text)
+ metaData.BuildMetaData(IATSize + CLIHeaderSize);
+ metaDataOffset = IATSize + CLIHeaderSize;
+ // Console.WriteLine("Code starts at " + metaDataOffset);
+ metaDataOffset += metaData.CodeSize();
+ // resourcesStart =
+ resourcesOffset = metaDataOffset + metaData.Size ();
+ resourcesSize = metaData.GetResourcesSize ();
+ if (reserveStrongNameSignatureSpace) {
+ strongNameSigOffset = resourcesOffset + resourcesSize;
+ // fixUps = RVA for vtable
+ importTableOffset = strongNameSigOffset + StrongNameSignatureSize;
+ } else {
+ strongNameSigOffset = 0;
+ // fixUps = RVA for vtable
+ importTableOffset = resourcesOffset + resourcesSize;
+ }
+ importTablePadding = NumToAlign(importTableOffset,16);
+ importTableOffset += importTablePadding;
+ importLookupTableOffset = importTableOffset + ImportTableSize;
+ hintNameTableOffset = importLookupTableOffset + IATSize;
+ runtimeEngineOffset = hintNameTableOffset + (uint)hintNameTable.Length;
+ entryPointOffset = runtimeEngineOffset + (uint)runtimeEngine.Length;
+ totalImportTableSize = entryPointOffset - importTableOffset;
+ // Console.WriteLine("total import table size = " + totalImportTableSize);
+ // Console.WriteLine("entrypoint offset = " + entryPointOffset);
+ entryPointPadding = NumToAlign(entryPointOffset,4) + 2;
+ entryPointOffset += entryPointPadding;
+ text.AddReloc(entryPointOffset+2);
+ text.IncTide(entryPointOffset + 6);
+ //if (text.Tide() < fileAlign) fileAlign = minFileAlign;
+ text.SetSize(NumToAlign(text.Tide(),fileAlign));
+ // Console.WriteLine("text size = " + text.Size() + " text tide = " + text.Tide() + " text padding = " + text.Padding());
+ // Console.WriteLine("metaDataOffset = " + Hex.Int(metaDataOffset));
+ // Console.WriteLine("importTableOffset = " + Hex.Int(importTableOffset));
+ // Console.WriteLine("importLookupTableOffset = " + Hex.Int(importLookupTableOffset));
+ // Console.WriteLine("hintNameTableOffset = " + Hex.Int(hintNameTableOffset));
+ // Console.WriteLine("runtimeEngineOffset = " + Hex.Int(runtimeEngineOffset));
+ // Console.WriteLine("entryPointOffset = " + Hex.Int(entryPointOffset));
+ // Console.WriteLine("entryPointPadding = " + Hex.Int(entryPointPadding));
- internal uint GetSigIx (MetaData md)
- {
- MemoryStream sig = new MemoryStream();
- TypeSig (sig);
- return md.AddToBlobHeap (sig.ToArray());
- }
- }
+ }
- public class Sentinel : Type {
+ internal void BuildRelocSection()
+ {
+ text.DoRelocs(reloc);
+ if (sdata != null) sdata.DoRelocs(reloc);
+ if (rsrc != null) rsrc.DoRelocs(reloc);
+ relocTide = (uint)reloc.Seek(0,SeekOrigin.Current);
+ relocPadding = NumToAlign(relocTide,fileAlign);
+ relocSize = relocTide + relocPadding;
+ imageSize = relocRVA + SectionAlignment;
+ initDataSize += relocSize;
+ }
- public Sentinel () : base (0x41) { }
+ private void CalcOffsets()
+ {
+ if (sdata != null)
+ numSections++;
+ if (rsrc != null)
+ numSections++;
+ headerSize = fileHeaderSize + (numSections * sectionHeaderSize);
+ headerPadding = NumToAlign(headerSize,fileAlign);
+ headerSize += headerPadding;
+ uint offset = headerSize;
+ uint rva = SectionAlignment;
+ text.SetOffset(offset);
+ text.SetRVA(rva);
+ offset += text.Size();
+ rva = GetNextSectStart(rva,text.Tide());
+ // Console.WriteLine("headerSize = " + headerSize);
+ // Console.WriteLine("headerPadding = " + headerPadding);
+ // Console.WriteLine("textOffset = " + Hex.Int(text.Offset()));
+ if (sdata != null) {
+ sdata.SetSize(NumToAlign(sdata.Tide(),fileAlign));
+ sdata.SetOffset(offset);
+ sdata.SetRVA(rva);
+ offset += sdata.Size();
+ rva = GetNextSectStart(rva,sdata.Tide());
+ initDataSize += sdata.Size();
+ }
+ if (rsrc != null) {
+ rsrc.SetSize(NumToAlign(rsrc.Tide(),fileAlign));
+ rsrc.SetOffset(offset);
+ rsrc.SetRVA(rva);
+ offset += rsrc.Size();
+ rva = GetNextSectStart(rva,rsrc.Tide());
+ initDataSize += rsrc.Size();
+ }
+ relocOffset = offset;
+ relocRVA = rva;
+ }
- internal sealed override void TypeSig(MemoryStream str) {
- str.WriteByte(typeIndex);
- }
- }
+ internal void MakeFile()
+ {
+ if (doDLL) hintNameTable = dllHintNameTable.ToCharArray();
+ else hintNameTable = exeHintNameTable.ToCharArray();
+ BuildTextSection();
+ CalcOffsets();
+ BuildRelocSection();
+ // now write it out
+ WriteHeader();
+ WriteSections();
+ Flush();
+ Close();
+ }
- /// <summary>\r
- /// The IL Array type\r
- /// </summary>\r
- public abstract class Array : Type\r
- {\r
-\r
- protected Type elemType;\r
- protected MetaData metaData;\r
- protected string cnameSpace, cname;\r
-\r
- internal Array(Type eType, byte TypeId) : base(TypeId) {\r
- elemType = eType;\r
- tabIx = MDTable.TypeSpec;\r
- }\r
-\r
- }\r
-\r
- /**************************************************************************/ \r
- \r
- /// <summary>\r
- /// Single dimensional array with zero lower bound\r
- /// </summary>\r
- public class ZeroBasedArray : Array {\r
-\r
- /// <summary>\r
- /// Create a new array - elementType[]\r
- /// </summary>\r
- /// <param name="elementType">the type of the array elements</param>\r
- public ZeroBasedArray(Type elementType) : base (elementType,0x1D) { }\r
-\r
- internal sealed override void TypeSig(MemoryStream str) {\r
- str.WriteByte(typeIndex);\r
- elemType.TypeSig(str); \r
- }\r
-\r
- }\r
-\r
-\r
- /**************************************************************************/ \r
-\r
- /// <summary>\r
- /// Multi dimensional array with explicit bounds\r
- /// </summary>\r
- public class BoundArray : Array {\r
- int[] lowerBounds;\r
- int[] sizes;\r
- uint numDims;\r
-\r
- /// <summary>\r
- /// Create a new multi dimensional array type \r
- /// eg. elemType[1..5,3..10,5,,] would be \r
- /// new BoundArray(elemType,5,[1,3,0],[5,10,4])\r
- /// </summary>\r
- /// <param name="elementType">the type of the elements</param>\r
- /// <param name="dimensions">the number of dimensions</param>\r
- /// <param name="loBounds">lower bounds of dimensions</param>\r
- /// <param name="upBounds">upper bounds of dimensions</param>\r
- public BoundArray(Type elementType, uint dimensions, int[] loBounds, \r
- int[] upBounds) : base (elementType,0x14) {\r
- numDims = dimensions;\r
- lowerBounds = loBounds;\r
- sizes = new int[loBounds.Length];\r
- for (int i=0; i < loBounds.Length; i++) {\r
- sizes[i] = upBounds[i] - loBounds[i] + 1;\r
- }\r
- }\r
-\r
- /// <summary>\r
- /// Create a new multi dimensional array type \r
- /// eg. elemType[5,10,20] would be new BoundArray(elemType,3,[5,10,20])\r
- /// </summary>\r
- /// <param name="elementType">the type of the elements</param>\r
- /// <param name="dimensions">the number of dimensions</param>\r
- /// <param name="size">the sizes of the dimensions</param>\r
- public BoundArray(Type elementType, uint dimensions, int[] size) \r
- : base (elementType,0x14) {\r
- numDims = dimensions;\r
- sizes = size;\r
- }\r
-\r
- /// <summary>\r
- /// Create a new multi dimensional array type \r
- /// eg. elemType[,,] would be new BoundArray(elemType,3)\r
- /// </summary>\r
- /// <param name="elementType">the type of the elements</param>\r
- /// <param name="dimensions">the number of dimensions</param>\r
- public BoundArray(Type elementType, uint dimensions)\r
- : base (elementType,0x14) {\r
- numDims = dimensions;\r
- }\r
-\r
- internal sealed override void TypeSig(MemoryStream str) {\r
- str.WriteByte(typeIndex);\r
- elemType.TypeSig(str);\r
- MetaData.CompressNum(numDims,str);\r
- if ((sizes != null) && (sizes.Length > 0)) {\r
- MetaData.CompressNum((uint)sizes.Length,str);\r
- for (int i=0; i < sizes.Length; i++) {\r
- MetaData.CompressNum((uint)sizes[i],str);\r
- }\r
- } else str.WriteByte(0);\r
- if ((lowerBounds != null) && (lowerBounds.Length > 0)) {\r
- MetaData.CompressNum((uint)lowerBounds.Length,str);\r
- for (int i=0; i < lowerBounds.Length; i++) {\r
- MetaData.CompressNum((uint)lowerBounds[i],str);\r
- }\r
- } else str.WriteByte(0);\r
- }\r
- \r
- }\r
- /**************************************************************************/ \r
- /// <summary>\r
- /// Descriptor for THIS assembly (.assembly)\r
- /// </summary>\r
- public class Assembly : ResolutionScope \r
- {\r
- ushort majorVer, minorVer, buildNo, revisionNo;\r
- uint flags;\r
- uint hashAlgId;
- uint keyIx = 0, cultIx = 0;\r
- \r
- internal Assembly(string name, MetaData md) : base(name,md) {\r
- tabIx = MDTable.Assembly;\r
- }\r
-\r
- /// <summary>\r
- /// Add details about THIS assembly\r
- /// </summary>\r
- /// <param name="majVer">Major Version</param>\r
- /// <param name="minVer">Minor Version</param>\r
- /// <param name="bldNo">Build Number</param>\r
- /// <param name="revNo">Revision Number</param>\r
- /// <param name="key">Hash Key</param>\r
- /// <param name="hash">Hash Algorithm</param>\r
- /// <param name="cult">Culture</param>\r
- public void AddAssemblyInfo(int majVer, int minVer, int bldNo, int revNo, \r
- byte[] key, uint hash, string cult) {\r
- majorVer = (ushort)majVer;\r
- minorVer = (ushort)minVer;\r
- buildNo = (ushort)bldNo;\r
- revisionNo = (ushort)revNo;\r
- hashAlgId = hash;\r
- keyIx = metaData.AddToBlobHeap(key);\r
- cultIx = metaData.AddToStringsHeap(cult);\r
- }\r
-\r
- /// <summary>\r
- /// Add an attribute to THIS assembly\r
- /// </summary>\r
- /// <param name="aa">assembly attribute</param>\r
- public void AddAssemblyAttr(AssemAttr aa) {\r
- flags |= (uint)aa;\r
- }\r
-\r
- internal sealed override uint Size(MetaData md) {\r
- return 16 + md.BlobIndexSize() + 2 * md.StringsIndexSize();\r
- }\r
-\r
- internal sealed override void Write(FileImage output) {\r
-// Console.WriteLine("Writing assembly element with nameIx of " + nameIx + " at file offset " + output.Seek(0,SeekOrigin.Current));\r
- output.Write((uint)hashAlgId);\r
- output.Write(majorVer);\r
- output.Write(minorVer);\r
- output.Write(buildNo);\r
- output.Write(revisionNo);\r
- output.Write(flags);\r
- output.BlobIndex(keyIx);\r
- output.StringsIndex(nameIx);\r
- output.StringsIndex(cultIx);\r
- }\r
-\r
- internal sealed override uint GetCodedIx(CIx code) {\r
- switch (code) {\r
- case (CIx.HasCustomAttr) : return 14; \r
- case (CIx.HasDeclSecurity) : return 2; \r
- }\r
- return 0;\r
- }\r
-\r
- } \r
- /**************************************************************************/ \r
+ private void WriteHeader()
+ {
+ Write(DOSHeader);
+ // Console.WriteLine("Writing PEHeader at offset " + Seek(0,SeekOrigin.Current));
+ WritePEHeader();
+ // Console.WriteLine("Writing text section header at offset " + Hex.Long(Seek(0,SeekOrigin.Current)));
+ text.WriteHeader(this,relocRVA);
+ if (sdata != null) sdata.WriteHeader(this,relocRVA);
+ if (rsrc != null) rsrc.WriteHeader(this,relocRVA);
+ // Console.WriteLine("Writing reloc section header at offset " + Seek(0,SeekOrigin.Current));
+ WriteRelocSectionHeader();
+ // Console.WriteLine("Writing padding at offset " + Seek(0,SeekOrigin.Current));
+ WriteZeros(headerPadding);
+ }
- public interface IExternRef {
- ClassRef AddClass(string nsName, string name);
- ClassRef AddValueClass(string nsName, string name);
- }
-
- /// <summary>\r
- /// A reference to an external assembly (.assembly extern)\r
- /// </summary>\r
- public class AssemblyRef : ResolutionScope, IExternRef
- {\r
- private ushort major, minor, build, revision;\r
- uint flags, keyIx, hashIx, cultIx;\r
- bool hasVersion = false, isKeyToken = false;\r
- byte[] keyBytes;\r
- string culture;\r
-\r
- internal AssemblyRef(MetaData md, string name) : base(name,md) {\r
- tabIx = MDTable.AssemblyRef;\r
- }\r
-\r
- /// <summary>\r
- /// Add version information about this external assembly\r
- /// </summary>\r
- /// <param name="majVer">Major Version</param>\r
- /// <param name="minVer">Minor Version</param>\r
- /// <param name="bldNo">Build Number</param>\r
- /// <param name="revNo">Revision Number</param>\r
- public void AddVersionInfo(int majVer, int minVer, int bldNo, int revNo) {\r
- major = (ushort)majVer;\r
- minor = (ushort)minVer;\r
- build = (ushort)bldNo;\r
- revision = (ushort)revNo;\r
- hasVersion = true;\r
- }\r
-\r
- /// <summary>\r
- /// Add the hash value for this external assembly\r
- /// </summary>\r
- /// <param name="hash">bytes of the hash value</param>\r
- public void AddHash(byte[] hash) {\r
- hashIx = metaData.AddToBlobHeap(hash); \r
- }\r
-\r
- /// <summary>\r
- /// Set the culture for this external assembly\r
- /// </summary>\r
- /// <param name="cult">the culture string</param>\r
- public void AddCulture(string cult) {\r
- cultIx = metaData.AddToStringsHeap(cult);\r
- culture = cult;\r
- }\r
-\r
- /// <summary>\r
- /// Add the full public key for this external assembly\r
- /// </summary>\r
- /// <param name="key">bytes of the public key</param>\r
- public void AddKey(byte[] key) {\r
- flags |= 0x0001; // full public key\r
- keyBytes = key;\r
- keyIx = metaData.AddToBlobHeap(key); \r
- }\r
-\r
- /// <summary>\r
- /// Add the public key token (low 8 bytes of the public key)\r
- /// </summary>\r
- /// <param name="key">low 8 bytes of public key</param>\r
- public void AddKeyToken(byte[] key) {\r
- keyIx = metaData.AddToBlobHeap(key); \r
- keyBytes = key;\r
- isKeyToken = true;\r
- }\r
-\r
- /// <summary>\r
- /// Add a class to this external assembly\r
- /// </summary>\r
- /// <param name="nsName">name space name</param>\r
- /// <param name="name">class name</param>\r
- /// <returns></returns>\r
- public virtual ClassRef AddClass(string nsName, string name) {\r
- ClassRef aClass = new ClassRef(nsName,name,metaData);\r
- metaData.AddToTable(MDTable.TypeRef,aClass);\r
- aClass.SetParent(this);\r
- return aClass;\r
- }\r
-\r
- /// <summary>\r
- /// Add a value class to this external assembly\r
- /// </summary>\r
- /// <param name="nsName">name space name</param>\r
- /// <param name="name">class name</param>\r
- /// <returns></returns>\r
- public virtual ClassRef AddValueClass(string nsName, string name) {\r
- ClassRef aClass = new ClassRef(nsName,name,metaData);\r
- metaData.AddToTable(MDTable.TypeRef,aClass);\r
- aClass.SetParent(this);\r
- aClass.MakeValueClass();\r
- return aClass;\r
- }\r
-\r
- internal string TypeName() {\r
- string result = name;\r
- if (hasVersion) \r
- result = result + ", Version=" + major + "." + minor + "." + \r
- build + "." + revision;\r
- if (keyBytes != null) {\r
- string tokenStr = "=";\r
- if (isKeyToken) tokenStr = "Token=";\r
- result = result + ", PublicKey" + tokenStr;\r
- for (int i=0; i < keyBytes.Length; i++) {\r
- result = result + Hex.Byte(keyBytes[i]);\r
- }\r
- }\r
- if (culture != null) \r
- result = result + ", Culture=" + culture;\r
- return result;\r
- }\r
-\r
- internal sealed override uint Size(MetaData md) {\r
- return 12 + 2 * md.StringsIndexSize() + 2 * md.BlobIndexSize();\r
- }\r
-\r
- internal sealed override void Write(FileImage output) {\r
- output.Write(major);\r
- output.Write(minor);\r
- output.Write(build);\r
- output.Write(revision);\r
- output.Write(flags);\r
- output.BlobIndex(keyIx);\r
- output.StringsIndex(nameIx);\r
- output.StringsIndex(cultIx);\r
- output.BlobIndex(hashIx);\r
- }\r
-\r
- internal sealed override uint GetCodedIx(CIx code) {\r
- switch (code) {\r
- case (CIx.ResolutionScope) : return 2; \r
- case (CIx.HasCustomAttr) : return 15; \r
- case (CIx.Implementation) : return 1; \r
- }\r
- return 0;\r
- }\r
+ private void WriteSections()
+ {
+ // Console.WriteLine("Writing text section at offset " + Seek(0,SeekOrigin.Current));
+ WriteTextSection();
+ if (sdata != null) WriteSDataSection();
+ if (rsrc != null) WriteRsrcSection();
+ WriteRelocSection();
+ }
- }\r
- /**************************************************************************/ \r
-\r
- /// <summary>\r
- /// flags for the assembly (.corflags)\r
- /// </summary>\r
- public enum CorFlags {CF_IL_ONLY, CF_32_BITREQUIRED, CF_STRONGNAMESIGNED, \r
- CF_TRACKDEBUGDATA}\r
-\r
- /// <summary>\r
- /// subsystem for the assembly (.subsystem)\r
- /// </summary>\r
- public enum SubSystem { Native = 1, Windows_GUI = 2, \r
- Windows_CUI = 3, OS2_CUI = 5, POSIX_CUI = 7, Native_Windows = 8, \r
- Windows_CE_GUI = 9}\r
- \r
- /// <summary>\r
- /// Hash algorithms for the assembly\r
- /// </summary>\r
- public enum HashAlgorithm { None, SHA1 }\r
-\r
- /// <summary>\r
- /// Attributes for this assembly\r
- /// </summary>\r
- public enum AssemAttr { EnableJITCompileTracking = 0x8000, \r
- DisableJITCompileOptimizer = 0x4000}\r
-\r
- /// <summary>\r
- /// Method call conventions\r
- /// </summary>\r
- public enum CallConv { Default, Cdecl, Stdcall, Thiscall, \r
- Fastcall, Vararg, Instance = 0x20, Generic = 0x10, InstanceExplicit = 0x60 }\r
-\r
- /// <summary>\r
- /// Type custom modifier\r
- /// </summary>\r
- public enum CustomModifier { modreq = 0x1F, modopt };\r
-\r
- /// <summary>\r
- /// Attibutes for a class\r
- /// </summary>\r
- public enum TypeAttr {Private, Public, NestedPublic, NestedPrivate, \r
- NestedFamily, NestedAssembly, NestedFamAndAssem, NestedFamOrAssem, \r
- SequentialLayout, ExplicitLayout = 0x10, Interface = 0x20, \r
- Abstract = 0x80, PublicAbstract = 0x81, Sealed = 0x100, \r
- PublicSealed = 0x101, SpecialName = 0x400, RTSpecialName = 0x800, \r
- Import = 0x1000, Serializable = 0x2000, UnicodeClass = 0x10000,\r
- AutoClass = 0x20000, BeforeFieldInit = 0x100000 }\r
-\r
- /// <summary>\r
- /// Attributes for a field\r
- /// </summary>\r
- public enum FieldAttr {Default, Private, FamAndAssem, Assembly, \r
- Family, FamOrAssem, Public, Static = 0x10, PublicStatic = 0x16, \r
- Initonly = 0x20, Literal = 0x40, Notserialized = 0x80, \r
- SpecialName = 0x200, RTSpecialName = 0x400 }\r
- \r
- /// <summary>\r
- /// Attributes for a method\r
- /// </summary>\r
- public enum MethAttr { Default, Private, FamAndAssem, Assembly,\r
- Family, FamOrAssem, Public, Static = 0x0010, PublicStatic = 0x16, \r
- Final = 0x0020, PublicStaticFinal = 0x36, Virtual = 0x0040, \r
- PrivateVirtual, PublicVirtual = 0x0046, HideBySig = 0x0080, \r
- NewSlot = 0x0100, Abstract = 0x0400, SpecialName = 0x0800,\r
- RTSpecialName = 0x1000, SpecialRTSpecialName = 0x1800, \r
- RequireSecObject = 0x8000}\r
-\r
- /// <summary>\r
- /// Attributes for .pinvokeimpl method declarations\r
- /// </summary>\r
- public enum PInvokeAttr { nomangle = 1, ansi = 2, unicode = 4, autochar = 6,
- lasterr = 0x0040, winapi = 0x0100, cdecl = 0x0200,
- stdcall = 0x0300, thiscall = 0x0400, fastcall = 0x0500 }\r
-\r
- /// <summary>\r
- /// Implementation attributes for a method\r
- /// </summary>\r
- public enum ImplAttr { IL, Native, Runtime = 0x03, Unmanaged = 0x04,\r
- ForwardRef = 0x10, PreserveSig = 0x0080, InternalCall = 0x1000, \r
- Synchronised = 0x0020, Synchronized = 0x0020, NoInLining = 0x0008, Optil = 0x0002}\r
-\r
- /// <summary>\r
- /// Modes for a parameter\r
- /// </summary>\r
- public enum ParamAttr { Default, In, Out, Opt = 4 }\r
-\r
- /// <summary>\r
- /// CIL instructions\r
- /// </summary>\r
- public enum Op { nop, breakOp, ldarg_0, ldarg_1, ldarg_2, ldarg_3,\r
- ldloc_0, ldloc_1, ldloc_2, ldloc_3, stloc_0, stloc_1, stloc_2, stloc_3, \r
- ldnull = 0x14, ldc_i4_m1, ldc_i4_0, ldc_i4_1, ldc_i4_2, ldc_i4_3, \r
- ldc_i4_4, ldc_i4_5, ldc_i4_6, ldc_i4_7, ldc_i4_8, dup = 0x25, pop, \r
- ret = 0x2A, ldind_i1 = 0x46, ldind_u1, ldind_i2, ldind_u2, ldind_i4, \r
- ldind_u4, ldind_i8, ldind_i, ldind_r4, ldind_r8, ldind_ref, stind_ref, \r
- stind_i1, stind_i2, stind_i4, stind_i8, stind_r4, stind_r8, add, sub, mul,\r
- div, div_un, rem, rem_un, and, or, xor, shl, shr, shr_un, neg, not, \r
- conv_i1, conv_i2, conv_i4, conv_i8, conv_r4, conv_r8, conv_u4, conv_u8, \r
- conv_r_un = 0x76, throwOp = 0x7A, conv_ovf_i1_un = 0x82, conv_ovf_i2_un,\r
- conv_ovf_i4_un, conv_ovf_i8_un, conf_ovf_u1_un, conv_ovf_u2_un, \r
- conv_ovf_u4_un, conv_ovf_u8_un, conv_ovf_i_un, conv_ovf_u_un, \r
- ldlen = 0x8E, ldelem_i1 = 0x90, ldelem_u1, ldelem_i2, ldelem_u2, \r
- ldelem_i4, ldelem_u4, ldelem_i8, ldelem_i, ldelem_r4, ldelem_r8, \r
- ldelem_ref, stelem_i, stelem_i1, stelem_i2, stelem_i4, stelem_i8, stelem_r4 = 0xA0, stelem_r8,\r
- stelem_ref, conv_ovf_i1 = 0xb3, conv_ovf_u1, conv_ovf_i2, conv_ovf_u2, \r
- conv_ovf_i4, conv_ovf_u4, conv_ovf_i8, conv_ovf_u8, ckfinite = 0xC3, \r
- conv_u2 = 0xD1, conv_u1, conv_i, conv_ovf_i, conv_ovf_u, add_ovf, \r
- add_ovf_un, mul_ovf, mul_ovf_un, sub_ovf, sub_ovf_un, endfinally, \r
- stind_i = 0xDF, conv_u, arglist = 0xFE00, ceq, cgt, cgt_un, clt, clt_un, \r
- localloc = 0xFE0F, endfilter = 0xFE11, volatile_ = 0xFE13, tail_, \r
- cpblk = 0xFE17, initblk, rethrow = 0xFE1A, refanytype = 0xFE1D}\r
-\r
- /// <summary>\r
- /// CIL instructions requiring an integer parameter\r
- /// </summary>\r
- public enum IntOp {ldarg_s = 0x0E, ldarga_s, starg_s, ldloc_s, ldloca_s, \r
- stloc_s, ldc_i4_s = 0x1F, ldc_i4, ldarg = 0xFE09,\r
- ldarga, starg, ldloc, ldloca, stloc, unaligned = 0xFE12 }\r
-\r
- /// <summary>\r
- /// CIL instructions requiring a field parameter\r
- /// </summary>\r
- public enum FieldOp {ldfld = 0x7B, ldflda, stfld, ldsfld, ldsflda,\r
- stsfld, ldtoken = 0xD0 }\r
-\r
- /// <summary>\r
- /// CIL instructions requiring a method parameter\r
- /// </summary>\r
- public enum MethodOp {jmp = 0x27, call, callvirt = 0x6F, newobj = 0x73, \r
- ldtoken = 0xD0, ldftn = 0xFE06, ldvirtfn }\r
-\r
- /// <summary>\r
- /// CIL instructions requiring a type parameter\r
- /// </summary>\r
- public enum TypeOp {cpobj = 0x70, ldobj, castclass = 0x74, isinst, \r
- unbox = 0x79, stobj = 0x81, box = 0x8C, newarr, \r
- ldelema = 0x8F, refanyval = 0xC2, mkrefany = 0xC6, \r
- ldtoken = 0xD0, initobj = 0xFE15, sizeOf = 0xFE1C,\r
- ldelem = 0xA3, stelem = 0xA4, unbox_any }\r
-\r
- /// <summary>\r
- /// CIL branch instructions\r
- /// </summary>\r
- public enum BranchOp {
- // short branches
- br_s = 0x2B, brfalse_s, brtrue_s, beq_s, bge_s, bgt_s,
- ble_s, blt_s, bne_un_s, bge_un_s, bgt_un_s, ble_un_s, blt_un_s,
- // long branches
- br = 0x38, brfalse, brtrue, beq, bge, bgt, ble, blt,\r
- bne_un, bge_un, bgt_un, ble_un, blt_un,
+ private void WriteIAT()
+ {
+ Write(text.RVA() + hintNameTableOffset);
+ Write(0);
+ }
- leave = 0xDD, leave_s }\r
-\r
- /// <summary>\r
- /// Index for all the tables in the meta data\r
- /// </summary>\r
- public enum MDTable { Module, TypeRef, TypeDef, Field = 0x04, Method = 0x06,\r
- Param = 0x08, InterfaceImpl, MemberRef, Constant, CustomAttribute, \r
- FieldMarshal, DeclSecurity, ClassLayout, FieldLayout, StandAloneSig, \r
- EventMap, Event = 0x14, PropertyMap, Property = 0x17, MethodSemantics, \r
- MethodImpl, ModuleRef, TypeSpec, ImplMap, FieldRVA, Assembly = 0x20, \r
- AssemblyProcessor, AssemblyOS, AssemblyRef, AssemblyRefProcessor, \r
- AssemblyRefOS, File, ExportedType, ManifestResource, NestedClass,\r
- GenericParam, MethodSpec, GenericParamConstraint }\r
-\r
- public enum SafeArrayType { int16 = 2, int32, float32, float64,\r
- currency, date, bstr, dispatch, error, boolean, variant, unknown,\r
- Decimal, int8 = 16, uint8, uint16, uint32, Int = 22, UInt }\r
-\r
- internal enum CIx { TypeDefOrRef, HasConst, HasCustomAttr, HasFieldMarshal,\r
- HasDeclSecurity, MemberRefParent, HasSemantics, MethodDefOrRef, \r
- MemberForwarded, Implementation, CustomAttributeType, ResolutionScope,\r
- TypeOrMethodDef, MaxCIx }\r
-\r
- internal enum MapType { eventMap, propertyMap, nestedClass }\r
-\r
- /**************************************************************************/ \r
- /// <summary>\r
- /// The assembly for mscorlib. \r
- /// </summary>\r
- public sealed class MSCorLib : AssemblyRef\r
- {\r
- private static readonly int valueTypeIx = 18;\r
- private readonly string systemName = "System";\r
- private ClassRef[] systemClasses = new ClassRef[valueTypeIx+2];\r
- private PrimitiveType[] systemTypes = new PrimitiveType[valueTypeIx];\r
- private TypeSpec[] specialTypeSpecs = new TypeSpec[valueTypeIx];\r
- private static int[] specialNames = {\r
- PrimitiveType.Void.GetName().GetHashCode(),\r
- PrimitiveType.Boolean.GetName().GetHashCode(),\r
- PrimitiveType.Char.GetName().GetHashCode(),\r
- PrimitiveType.Int8.GetName().GetHashCode(),\r
- PrimitiveType.UInt8.GetName().GetHashCode(),\r
- PrimitiveType.Int16.GetName().GetHashCode(),\r
- PrimitiveType.UInt16.GetName().GetHashCode(),\r
- PrimitiveType.Int32.GetName().GetHashCode(),\r
- PrimitiveType.UInt32.GetName().GetHashCode(),\r
- PrimitiveType.Int64.GetName().GetHashCode(),\r
- PrimitiveType.UInt64.GetName().GetHashCode(),\r
- PrimitiveType.Float32.GetName().GetHashCode(),\r
- PrimitiveType.Float64.GetName().GetHashCode(),\r
- PrimitiveType.String.GetName().GetHashCode(),\r
- PrimitiveType.TypedRef.GetName().GetHashCode(),\r
- PrimitiveType.IntPtr.GetName().GetHashCode(),\r
- PrimitiveType.UIntPtr.GetName().GetHashCode(),\r
- PrimitiveType.Object.GetName().GetHashCode(),\r
- "ValueType".GetHashCode(),\r
- "Enum".GetHashCode()\r
- };\r
-\r
- internal MSCorLib(MetaData md) : base(md,"mscorlib") {\r
- md.AddToTable(MDTable.AssemblyRef,this);\r
- systemTypes[PrimitiveType.Void.GetSystemTypeIx()] = PrimitiveType.Void;\r
- systemTypes[PrimitiveType.Boolean.GetSystemTypeIx()] = PrimitiveType.Boolean;\r
- systemTypes[PrimitiveType.Char.GetSystemTypeIx()] = PrimitiveType.Char;\r
- systemTypes[PrimitiveType.Int8.GetSystemTypeIx()] = PrimitiveType.Int8;\r
- systemTypes[PrimitiveType.UInt8.GetSystemTypeIx()] = PrimitiveType.UInt8;\r
- systemTypes[PrimitiveType.Int16.GetSystemTypeIx()] = PrimitiveType.Int16;\r
- systemTypes[PrimitiveType.UInt16.GetSystemTypeIx()] = PrimitiveType.UInt16;\r
- systemTypes[PrimitiveType.Int32.GetSystemTypeIx()] = PrimitiveType.Int32;\r
- systemTypes[PrimitiveType.UInt32.GetSystemTypeIx()] = PrimitiveType.UInt32;\r
- systemTypes[PrimitiveType.Int64.GetSystemTypeIx()] = PrimitiveType.Int64;\r
- systemTypes[PrimitiveType.UInt64.GetSystemTypeIx()] = PrimitiveType.UInt64;\r
- systemTypes[PrimitiveType.Float32.GetSystemTypeIx()] = PrimitiveType.Float32;\r
- systemTypes[PrimitiveType.Float64.GetSystemTypeIx()] = PrimitiveType.Float64;\r
- systemTypes[PrimitiveType.IntPtr.GetSystemTypeIx()] = PrimitiveType.IntPtr;\r
- systemTypes[PrimitiveType.UIntPtr.GetSystemTypeIx()] = PrimitiveType.UIntPtr;\r
- systemTypes[PrimitiveType.String.GetSystemTypeIx()] = PrimitiveType.String;\r
- systemTypes[PrimitiveType.Object.GetSystemTypeIx()] = PrimitiveType.Object;\r
- systemTypes[PrimitiveType.TypedRef.GetSystemTypeIx()] = PrimitiveType.TypedRef;\r
- }\r
-\r
- /// <summary>\r
- /// Add a class to the mscorlib assembly\r
- /// </summary>\r
- /// <param name="nsName">name space name</param>\r
- /// <param name="name">class name</param>\r
- /// <returns></returns>\r
- public override ClassRef AddClass(string nsName, string name) {\r
- ClassRef aClass = GetSpecialClass(nsName,name);\r
- if (aClass == null) {\r
- aClass = new ClassRef(nsName,name,metaData);\r
- metaData.AddToTable(MDTable.TypeRef,aClass);\r
- aClass.SetParent(this);\r
- }\r
- return aClass;\r
- }\r
-\r
- private ClassRef GetSpecialClass(string nsName,string name) {\r
- if (nsName.CompareTo(systemName) != 0) return null;\r
- int hash = name.GetHashCode();\r
- for (int i=0; i < specialNames.Length; i++) {\r
- if (hash == specialNames[i]) {\r
- if (systemClasses[i] == null) {\r
- if (i < valueTypeIx) {\r
- systemClasses[i] = new SystemClass(systemTypes[i],this,metaData);\r
- if ((systemTypes[i] != PrimitiveType.Object) &&\r
- (systemTypes[i] != PrimitiveType.String)) {\r
- systemClasses[i].MakeValueClass();\r
- }\r
- } else {\r
- systemClasses[i] = new ClassRef(nsName,name,metaData);\r
- systemClasses[i].SetParent(this);\r
- systemClasses[i].MakeValueClass();\r
- }\r
- metaData.AddToTable(MDTable.TypeRef,systemClasses[i]);\r
- }\r
- return systemClasses[i];\r
- }\r
- }\r
- return null;\r
- }\r
-\r
- internal ClassRef GetSpecialSystemClass(PrimitiveType pType) {\r
- int ix = pType.GetSystemTypeIx();\r
- if (systemClasses[ix] == null) {\r
- systemClasses[ix] = new SystemClass(pType,this,metaData);\r
- metaData.AddToTable(MDTable.TypeRef,systemClasses[ix]);\r
- }\r
- return systemClasses[ix];\r
- }\r
- \r
- private ClassRef GetValueClass(string name, int hash) {\r
- int ix = valueTypeIx;\r
- if (hash != specialNames[valueTypeIx]) ix++;\r
- if (systemClasses[ix] == null) {\r
- systemClasses[ix] = new ClassRef(systemName,name,metaData);\r
- systemClasses[ix].SetParent(this);\r
- systemClasses[ix].MakeValueClass();\r
- metaData.AddToTable(MDTable.TypeRef,systemClasses[ix]);\r
- }\r
- return systemClasses[ix];\r
- }\r
-\r
- internal ClassRef ValueType() {\r
- if (systemClasses[valueTypeIx] == null) {\r
- ClassRef valType = new ClassRef("System","ValueType",metaData);\r
- valType.SetParent(this);\r
- valType.MakeValueClass();\r
- metaData.AddToTable(MDTable.TypeRef,valType);\r
- systemClasses[valueTypeIx] = valType;\r
- }\r
- return systemClasses[valueTypeIx];\r
- }\r
-\r
- /// <summary>\r
- /// Add a value class to this external assembly\r
- /// </summary>\r
- /// <param name="nsName">name space name</param>\r
- /// <param name="name">class name</param>\r
- /// <returns></returns>\r
- public override ClassRef AddValueClass(string nsName, string name) {\r
- if (nsName.CompareTo(systemName) == 0) {\r
- int hash = name.GetHashCode();\r
- if ((hash == specialNames[valueTypeIx]) ||\r
- (hash == specialNames[valueTypeIx+1])) {\r
- return GetValueClass(name,hash);\r
- }\r
- }\r
- ClassRef aClass = new ClassRef(nsName,name,metaData);\r
- metaData.AddToTable(MDTable.TypeRef,aClass);\r
- aClass.SetParent(this);\r
- aClass.MakeValueClass();\r
- return aClass;\r
- }\r
-\r
- }\r
- /**************************************************************************/ \r
- /// <summary>\r
- /// Signature for calli instruction\r
- /// </summary>\r
- public class CalliSig : Signature\r
- {\r
- private static readonly byte Sentinel = 0x41;\r
- CallConv callConv;\r
- Type returnType;\r
- Type[] parameters, optParams;\r
- uint numPars = 0, numOptPars = 0;\r
-\r
- /// <summary>\r
- /// Create a signature for a calli instruction\r
- /// </summary>\r
- /// <param name="cconv">calling conventions</param>\r
- /// <param name="retType">return type</param>\r
- /// <param name="pars">parameter types</param>\r
- public CalliSig(CallConv cconv, Type retType, Type[] pars) {\r
- tabIx = MDTable.StandAloneSig;\r
- callConv = cconv;\r
- returnType = retType;\r
- parameters = pars;\r
- if (pars != null) numPars = (uint)pars.Length;\r
- }\r
-\r
- /// <summary>\r
- /// Add the optional parameters to a vararg method\r
- /// This method sets the vararg calling convention\r
- /// </summary>\r
- /// <param name="optPars">the optional pars for the vararg call</param>\r
- public void AddVarArgs(Type[] optPars) {\r
- optParams = optPars;\r
- if (optPars != null) numOptPars = (uint)optPars.Length;\r
- callConv |= CallConv.Vararg;\r
- }\r
-\r
- /// <summary>\r
- /// Add extra calling conventions to this callsite signature\r
- /// </summary>\r
- /// <param name="cconv"></param>\r
- public void AddCallingConv(CallConv cconv) {\r
- callConv |= cconv;\r
- }\r
-\r
- internal sealed override void BuildTables(MetaData md) {\r
- if (done) return;\r
- MemoryStream sig = new MemoryStream();\r
- sig.WriteByte((byte)callConv);\r
- MetaData.CompressNum(numPars+numOptPars,sig);\r
- returnType.TypeSig(sig);\r
- for (int i=0; i < numPars; i++) {\r
- parameters[i].TypeSig(sig);\r
- }\r
- sigIx = md.AddToBlobHeap(sig.ToArray());\r
- if (numOptPars > 0) {\r
- sig.WriteByte(Sentinel);\r
- for (int i=0; i < numOptPars; i++) {\r
- optParams[i].TypeSig(sig);\r
- }\r
- }\r
- done = true;\r
- }\r
-\r
- }\r
- /**************************************************************************/ \r
- /// <summary>\r
- /// The IL instructions for a method\r
- /// </summary>\r
- public class CILInstructions \r
- {\r
-\r
- private static readonly uint ExHeaderSize = 4;\r
- private static readonly uint FatExClauseSize = 24;\r
- private static readonly uint SmlExClauseSize = 12;\r
- private static readonly sbyte maxByteVal = 127;\r
- private static readonly sbyte minByteVal = -128;\r
- private static readonly byte maxUByteVal = 255;\r
- private static readonly int smallSize = 64;\r
- private static readonly ushort TinyFormat = 0x2;\r
- private static readonly ushort FatFormat = 0x3003;\r
- private static readonly ushort MoreSects = 0x8;\r
- private static readonly ushort InitLocals = 0x10;\r
- private static readonly uint FatSize = 12;\r
- private static readonly uint FatWords = FatSize/4;\r
- private static readonly byte FatExceptTable = 0x41;\r
- private static readonly byte SmlExceptTable = 0x01; \r
-\r
- private MetaData metaData;\r
- private ArrayList exceptions, blockStack;\r
- //private bool codeChecked = false;\r
- private static readonly int INITSIZE = 5;\r
- private CILInstruction[] buffer = new CILInstruction[INITSIZE];\r
- private int tide = 0;\r
- private uint offset = 0;\r
- private ushort headerFlags = 0;\r
- private short maxStack;\r
- private uint paddingNeeded = 0;\r
- private byte exceptHeader = 0;\r
- uint localSigIx = 0;\r
- uint codeSize = 0, exceptSize = 0;\r
- bool tinyFormat, fatExceptionFormat = false;\r
-\r
- public uint Offset {\r
- get { return offset; }\r
- } \r
-\r
- internal CILInstructions(MetaData md) {\r
- metaData = md;\r
- }\r
-\r
- private void AddToBuffer(CILInstruction inst) {\r
- if (tide >= buffer.Length) {\r
- CILInstruction[] tmp = buffer;\r
- buffer = new CILInstruction[tmp.Length * 2];\r
- for (int i=0; i < tide; i++) {\r
- buffer[i] = tmp[i];\r
- }\r
- }\r
- //Console.WriteLine("Adding instruction at offset " + offset + " with size " + inst.size);\r
- inst.offset = offset;\r
- offset += inst.size;\r
- buffer[tide++] = inst;\r
- }\r
-\r
- /// <summary>\r
- /// Add a simple IL instruction\r
- /// </summary>\r
- /// <param name="inst">the IL instruction</param>\r
- public void Inst(Op inst) {\r
- AddToBuffer(new Instr((int)inst));\r
- }\r
-\r
- /// <summary>\r
- /// Add an IL instruction with an integer parameter\r
- /// </summary>\r
- /// <param name="inst">the IL instruction</param>\r
- /// <param name="val">the integer parameter value</param>\r
- public void IntInst(IntOp inst, int val) {\r
- int instr = (int)inst;\r
- if ((inst == IntOp.ldc_i4_s) || (inst == IntOp.ldc_i4)) \r
- AddToBuffer(new IntInstr(instr,val,(inst == IntOp.ldc_i4_s)));\r
- else\r
- AddToBuffer(new UIntInstr(instr,val,((inst < IntOp.ldc_i4_s) ||\r
- (inst == IntOp.unaligned))));\r
- }\r
-\r
- /// <summary>\r
- /// Add the load long instruction\r
- /// </summary>\r
- /// <param name="cVal">the long value</param>\r
- public void ldc_i8(long cVal) {\r
- AddToBuffer(new LongInstr(0x21,cVal));\r
- }\r
-\r
- /// <summary>\r
- /// Add the load float32 instruction\r
- /// </summary>\r
- /// <param name="cVal">the float value</param>\r
- public void ldc_r4(float cVal) {\r
- AddToBuffer(new FloatInstr(0x22,cVal));\r
- }\r
-\r
- /// <summary>\r
- /// Add the load float64 instruction\r
- /// </summary>\r
- /// <param name="cVal">the float value</param>\r
- public void ldc_r8(double cVal) {\r
- AddToBuffer(new DoubleInstr(0x23,cVal));\r
- }\r
-\r
- /// <summary>\r
- /// Add the load string instruction\r
- /// </summary>\r
- /// <param name="str">the string value</param>\r
- public void ldstr(string str) {\r
- AddToBuffer(new StringInstr(0x72,str));\r
- }
+ private void WriteImportTables()
+ {
+ // Import Table
+ WriteZeros(importTablePadding);
+ // Console.WriteLine("Writing import tables at offset " + Hex.Long(Seek(0,SeekOrigin.Current)));
+ Write(importLookupTableOffset + text.RVA());
+ WriteZeros(8);
+ Write(runtimeEngineOffset + text.RVA());
+ Write(text.RVA()); // IAT is at the beginning of the text section
+ WriteZeros(20);
+ // Import Lookup Table
+ WriteIAT(); // lookup table and IAT are the same
+ // Hint/Name Table
+ // Console.WriteLine("Writing hintname table at " + Hex.Long(Seek(0,SeekOrigin.Current)));
+ Write(hintNameTable);
+ Write(runtimeEngineName.ToCharArray());
+ }
- /// <summary>
- /// Add the load string instruction
- /// </summary>
- public void ldstr (byte[] str) {
- AddToBuffer (new StringInstr (0x72, str));
- }
-
- /// <summary>\r
- /// Add the calli instruction\r
- /// </summary>\r
- /// <param name="sig">the signature for the calli</param>\r
- public void calli(CalliSig sig) {\r
- AddToBuffer(new SigInstr(0x29,sig));\r
- }\r
-\r
- /// <summary>\r
- /// Add a label to the CIL instructions\r
- /// </summary>\r
- /// <param name="lab">the label to be added</param>\r
- public void CodeLabel(CILLabel lab) {\r
- AddToBuffer(new LabelInstr(lab));\r
- }\r
-\r
- /// <summary>\r
- /// Add an instruction with a field parameter\r
- /// </summary>\r
- /// <param name="inst">the CIL instruction</param>\r
- /// <param name="f">the field parameter</param>\r
- public void FieldInst(FieldOp inst, Field f) {\r
- AddToBuffer(new FieldInstr((int)inst,f));\r
- }\r
-\r
- /// <summary>\r
- /// Add an instruction with a method parameter\r
- /// </summary>\r
- /// <param name="inst">the CIL instruction</param>\r
- /// <param name="m">the method parameter</param>\r
- public void MethInst(MethodOp inst, Method m) {\r
- AddToBuffer(new MethInstr((int)inst,m));\r
- }\r
-\r
- /// <summary>\r
- /// Add an instruction with a type parameter\r
- /// </summary>\r
- /// <param name="inst">the CIL instruction</param>\r
- /// <param name="t">the type argument for the CIL instruction</param>\r
- public void TypeInst(TypeOp inst, Type aType) {\r
- AddToBuffer(new TypeInstr((int)inst,aType,metaData));\r
- }\r
-\r
- /// <summary>\r
- /// Add a branch instruction\r
- /// </summary>\r
- /// <param name="inst">the branch instruction</param>\r
- /// <param name="lab">the label that is the target of the branch</param>\r
- public void Branch(BranchOp inst, CILLabel lab) {\r
- AddToBuffer(new BranchInstr((int)inst,lab));\r
- }\r
-\r
- /// <summary>\r
- /// Add a switch instruction\r
- /// </summary>\r
- /// <param name="labs">the target labels for the switch</param>\r
- public void Switch(CILLabel[] labs) {\r
- AddToBuffer(new SwitchInstr(0x45,labs));\r
- }\r
-\r
- /// <summary>\r
- /// Add a byte to the CIL instructions (.emitbyte)\r
- /// </summary>\r
- /// <param name="bVal"></param>\r
- public void emitbyte(byte bVal) { \r
- AddToBuffer(new CILByte(bVal));\r
- }\r
-\r
- /// <summary>\r
- /// Add an instruction which puts an integer on TOS. This method\r
- /// selects the correct instruction based on the value of the integer.\r
- /// </summary>\r
- /// <param name="i">the integer value</param>\r
- public void PushInt(int i) {\r
- if (i == -1) {\r
- AddToBuffer(new Instr((int)Op.ldc_i4_m1));\r
- } else if ((i >= 0) && (i <= 8)) {\r
- Op op = (Op)(Op.ldc_i4_0 + i);\r
- AddToBuffer(new Instr((int)op));\r
- } else if ((i >= minByteVal) && (i <= maxByteVal)) {\r
- AddToBuffer(new IntInstr((int)IntOp.ldc_i4_s,i,true));\r
- } else {\r
- AddToBuffer(new IntInstr((int)IntOp.ldc_i4,i,false)); \r
- }\r
- }\r
-\r
- /// <summary>\r
- /// Add the instruction to load a long on TOS\r
- /// </summary>\r
- /// <param name="l">the long value</param>\r
- public void PushLong(long l) {\r
- AddToBuffer(new LongInstr(0x21,l));\r
- }\r
-\r
- /// <summary>\r
- /// Add an instruction to push the boolean value true on TOS\r
- /// </summary>\r
- public void PushTrue() {\r
- AddToBuffer(new Instr((int)Op.ldc_i4_1));\r
- }\r
-\r
- /// <summary>\r
- /// Add an instruction to push the boolean value false on TOS\r
- /// </summary>\r
- public void PushFalse() {\r
- AddToBuffer(new Instr((int)Op.ldc_i4_0));\r
- }\r
-\r
- /// <summary>\r
- /// Add the instruction to load an argument on TOS. This method\r
- /// selects the correct instruction based on the value of argNo\r
- /// </summary>\r
- /// <param name="argNo">the number of the argument</param>\r
- public void LoadArg(int argNo) {\r
- if (argNo < 4) {\r
- int op = (int)Op.ldarg_0 + argNo;\r
- AddToBuffer(new Instr(op));\r
- } else if (argNo <= maxUByteVal) {\r
- AddToBuffer(new UIntInstr((int)IntOp.ldarg,argNo,true));\r
- } else {\r
- AddToBuffer(new UIntInstr(0x09,argNo,false)); \r
- }\r
- }\r
-\r
- /// <summary>\r
- /// Add the instruction to load the address of an argument on TOS.\r
- /// This method selects the correct instruction based on the value\r
- /// of argNo.\r
- /// </summary>\r
- /// <param name="argNo">the number of the argument</param>\r
- public void LoadArgAdr(int argNo) {\r
- if (argNo <= maxUByteVal) {\r
- AddToBuffer(new UIntInstr((int)IntOp.ldarga,argNo,true));\r
- } else {\r
- AddToBuffer(new UIntInstr(0x0A,argNo,false)); \r
- }\r
- }\r
-\r
- /// <summary>\r
- /// Add the instruction to load a local on TOS. This method selects\r
- /// the correct instruction based on the value of locNo.\r
- /// </summary>\r
- /// <param name="locNo">the number of the local to load</param>\r
- public void LoadLocal(int locNo) {\r
- if (locNo < 4) {\r
- int op = (int)Op.ldloc_0 + locNo;\r
- AddToBuffer(new Instr(op));\r
- } else if (locNo <= maxUByteVal) {\r
- AddToBuffer(new UIntInstr((int)IntOp.ldloc,locNo,true));\r
- } else {\r
- AddToBuffer(new UIntInstr(0x0C,locNo,false)); \r
- }\r
- }\r
-\r
- /// <summary>\r
- /// Add the instruction to load the address of a local on TOS.\r
- /// This method selects the correct instruction based on the \r
- /// value of locNo.\r
- /// </summary>\r
- /// <param name="locNo">the number of the local</param>\r
- public void LoadLocalAdr(int locNo) {\r
- if (locNo <= maxUByteVal) {\r
- AddToBuffer(new UIntInstr((int)IntOp.ldloca,locNo,true));\r
- } else {\r
- AddToBuffer(new UIntInstr(0x0D,locNo,false)); \r
- }\r
- }\r
-\r
- /// <summary>\r
- /// Add the instruction to store to an argument. This method\r
- /// selects the correct instruction based on the value of argNo.\r
- /// </summary>\r
- /// <param name="argNo">the argument to be stored to</param>\r
- public void StoreArg(int argNo) {\r
- if (argNo <= maxUByteVal) {\r
- AddToBuffer(new UIntInstr((int)IntOp.starg,argNo,true));\r
- } else {\r
- AddToBuffer(new UIntInstr(0x0B,argNo,false)); \r
- }\r
- }\r
-\r
- /// <summary>\r
- /// Add the instruction to store to a local. This method selects\r
- /// the correct instruction based on the value of locNo.\r
- /// </summary>\r
- /// <param name="locNo">the local to be stored to</param>\r
- public void StoreLocal(int locNo) {\r
- if (locNo < 4) {\r
- int op = (int)Op.stloc_0 + locNo;\r
- AddToBuffer(new Instr(op));\r
- } else if (locNo <= maxUByteVal) {\r
- AddToBuffer(new UIntInstr((int)IntOp.stloc,locNo,true));\r
- } else {\r
- AddToBuffer(new UIntInstr(0x0E,locNo,false)); \r
- }\r
- }\r
-\r
- /// <summary>\r
- /// Create a new CIL label. To place the label in the CIL instruction\r
- /// stream use CodeLabel.\r
- /// </summary>\r
- /// <returns>a new CIL label</returns>\r
- public CILLabel NewLabel() {\r
- return new CILLabel();\r
- }\r
-\r
- public void AddTryBlock(TryBlock tryBlock) {\r
- if (exceptions == null) \r
- exceptions = new ArrayList();\r
- else if (exceptions.Contains(tryBlock)) return;\r
- exceptions.Add(tryBlock);\r
- }\r
-\r
- /// <summary>\r
- /// Create a new label at this position in the code buffer\r
- /// </summary>\r
- /// <returns>the label at the current position</returns>\r
- public CILLabel NewCodedLabel() {\r
- CILLabel lab = new CILLabel();\r
- AddToBuffer(new LabelInstr(lab));\r
- return lab;\r
- }\r
-\r
- /// <summary>\r
- /// Mark this position as the start of a new block\r
- /// (try, catch, filter, finally or fault)\r
- /// </summary>\r
- public void StartBlock() {\r
- if (blockStack == null) blockStack = new ArrayList();\r
- blockStack.Insert(0,NewCodedLabel());\r
- }\r
-\r
- /// <summary>\r
- /// Mark this position as the end of the last started block and\r
- /// make it a try block. This try block is added to the current \r
- /// instructions (ie do not need to call AddTryBlock)\r
- /// </summary>\r
- /// <returns>The try block just ended</returns>\r
- public TryBlock EndTryBlock() {\r
- TryBlock tBlock = new TryBlock((CILLabel)blockStack[0],NewCodedLabel());\r
- blockStack.RemoveAt(0);\r
- AddTryBlock(tBlock);\r
- return tBlock;\r
- }\r
-\r
- /// <summary>\r
- /// Mark this position as the end of the last started block and\r
- /// make it a catch block. This catch block is associated with the\r
- /// specified try block.\r
- /// </summary>\r
- /// <param name="exceptType">the exception type to be caught</param>\r
- /// <param name="tryBlock">the try block associated with this catch block</param>\r
- public void EndCatchBlock(Class exceptType, TryBlock tryBlock) {\r
- Catch catchBlock = new Catch(exceptType,(CILLabel)blockStack[0],\r
- NewCodedLabel());\r
- tryBlock.AddHandler(catchBlock);\r
- }\r
-\r
- /// <summary>\r
- /// Mark this position as the end of the last started block and\r
- /// make it a filter block. This filter block is associated with the\r
- /// specified try block.\r
- /// </summary>\r
- /// <param name="filterLab">the label where the filter code is</param>\r
- /// <param name="tryBlock">the try block associated with this filter block</param>\r
- public void EndFilterBlock(CILLabel filterLab, TryBlock tryBlock) {\r
- Filter filBlock = new Filter(filterLab,(CILLabel)blockStack[0],NewCodedLabel());\r
- tryBlock.AddHandler(filBlock);\r
- }\r
-\r
- /// <summary>\r
- /// Mark this position as the end of the last started block and\r
- /// make it a finally block. This finally block is associated with the\r
- /// specified try block.\r
- /// </summary>\r
- /// <param name="tryBlock">the try block associated with this finally block</param>\r
- public void EndFinallyBlock(TryBlock tryBlock) {\r
- Finally finBlock= new Finally((CILLabel)blockStack[0],NewCodedLabel());\r
- tryBlock.AddHandler(finBlock);\r
- }\r
-\r
- /// <summary>\r
- /// Mark this position as the end of the last started block and\r
- /// make it a fault block. This fault block is associated with the\r
- /// specified try block.\r
- /// </summary>\r
- /// <param name="tryBlock">the try block associated with this fault block</param>\r
- public void EndFaultBlock(TryBlock tryBlock) {\r
- Fault fBlock= new Fault((CILLabel)blockStack[0],NewCodedLabel());\r
- tryBlock.AddHandler(fBlock);\r
- }\r
-\r
- internal uint GetCodeSize() {\r
- return codeSize + paddingNeeded + exceptSize;\r
- }\r
-\r
- internal void CheckCode(uint locSigIx, bool initLocals, int maxStack) {\r
- if (tide == 0) return;\r
- bool changed = true;\r
- while (changed) {\r
- changed = false;\r
- for (int i=0; i < tide; i++) {\r
- changed = buffer[i].Check(metaData) || changed;\r
- }\r
- if (changed) {\r
- for (int i=1; i < tide; i++) {\r
- buffer[i].offset = buffer[i-1].offset + buffer[i-1].size;\r
- }\r
- offset = buffer[tide-1].offset + buffer[tide-1].size;\r
- }\r
- }\r
- codeSize = offset;\r
- // Console.WriteLine("codeSize before header added = " + codeSize);\r
- if ((offset < smallSize) && (maxStack <= 8) && (locSigIx == 0) && (exceptions == null)) {\r
- // can use tiny header\r
- //Console.WriteLine("Tiny Header");\r
- tinyFormat = true;\r
- headerFlags = (ushort)(TinyFormat | ((ushort)codeSize << 2));\r
- codeSize++;\r
- if ((codeSize % 4) != 0) { paddingNeeded = 4 - (codeSize % 4); }\r
- } else {\r
- //Console.WriteLine("Fat Header");\r
- tinyFormat = false;\r
- localSigIx = locSigIx;\r
- this.maxStack = (short)maxStack;\r
- headerFlags = FatFormat;\r
- if (exceptions != null) {\r
- // Console.WriteLine("Got exceptions");\r
- headerFlags |= MoreSects;\r
- uint numExceptClauses = 0;\r
- for (int i=0; i < exceptions.Count; i++) {\r
- TryBlock tryBlock = (TryBlock)exceptions[i];\r
- tryBlock.SetSize();\r
- numExceptClauses += (uint)tryBlock.NumHandlers();\r
- if (tryBlock.isFat()) fatExceptionFormat = true;\r
- }\r
+ private void WriteTextSection()
+ {
+ WriteIAT();
+ WriteCLIHeader();
+ // Console.WriteLine("Writing code at " + Hex.Long(Seek(0,SeekOrigin.Current)));
+ metaData.WriteByteCodes(this);
+ // Console.WriteLine("Finished writing code at " + Hex.Long(Seek(0,SeekOrigin.Current)));
+ largeStrings = metaData.LargeStringsIndex();
+ largeGUID = metaData.LargeGUIDIndex();
+ largeUS = metaData.LargeUSIndex();
+ largeBlob = metaData.LargeBlobIndex();
+ metaData.WriteMetaData(this);
+ metaData.WriteResources (this);
+ if (reserveStrongNameSignatureSpace) {
+ WriteZeros(StrongNameSignatureSize);
+ }
+ WriteImportTables();
+ WriteZeros(entryPointPadding);
+ Write((ushort)0x25FF);
+ Write(ImageBase + text.RVA());
+ WriteZeros(text.Padding());
+ }
- uint data_size = ExHeaderSize + numExceptClauses *
- (fatExceptionFormat ? FatExClauseSize : SmlExClauseSize);
+ private void WriteCLIHeader()
+ {
+ Write(CLIHeaderSize); // Cb
+ Write((short)2); // Major runtime version
+ Write((short)0); // Minor runtime version
+ Write(text.RVA() + metaDataOffset);
+ Write(metaData.Size());
+ Write(runtimeFlags);
+ Write(entryPointToken);
+ if (resourcesSize > 0) {
+ Write (text.RVA () + resourcesOffset);
+ Write (resourcesSize);
+ } else {
+ WriteZeros (8);
+ }
+ // Strong Name Signature (RVA, size)
+ if (reserveStrongNameSignatureSpace) {
+ Write(text.RVA() + strongNameSigOffset);
+ Write(StrongNameSignatureSize);
+ } else {
+ WriteZeros(8);
+ }
+ WriteZeros(8); // CodeManagerTable
+ WriteZeros(8); // VTableFixups NYI
+ WriteZeros(16); // ExportAddressTableJumps, ManagedNativeHeader
+ }
- if (data_size > 256)
- fatExceptionFormat = true;
-
- // Console.WriteLine("numexceptclauses = " + numExceptClauses);\r
- if (fatExceptionFormat) {\r
- // Console.WriteLine("Fat exception format");\r
- exceptHeader = FatExceptTable;\r
- exceptSize = ExHeaderSize + numExceptClauses * FatExClauseSize;\r
- } else {\r
- // Console.WriteLine("Tiny exception format");\r
- exceptHeader = SmlExceptTable;\r
- exceptSize = ExHeaderSize + numExceptClauses * SmlExClauseSize;\r
- }\r
- // Console.WriteLine("exceptSize = " + exceptSize);\r
- }\r
- if (initLocals) headerFlags |= InitLocals;\r
- if ((offset % 4) != 0) { paddingNeeded = 4 - (offset % 4); }\r
- codeSize += FatSize;\r
- }\r
- // Console.WriteLine("codeSize = " + codeSize + " headerFlags = " + \r
- // Hex.Short(headerFlags));\r
- }\r
-\r
- internal void Write(FileImage output) {\r
- // Console.WriteLine("Writing header flags = " + Hex.Short(headerFlags));\r
- if (tinyFormat) {\r
- // Console.WriteLine("Writing tiny code");\r
- output.Write((byte)headerFlags);\r
- } else {\r
- // Console.WriteLine("Writing fat code");\r
- output.Write(headerFlags);\r
- output.Write((ushort)maxStack);\r
- output.Write(offset);\r
- output.Write(localSigIx);\r
- }\r
- // Console.WriteLine(Hex.Int(tide) + " CIL instructions");\r
- // Console.WriteLine("starting instructions at " + output.Seek(0,SeekOrigin.Current));\r
- for (int i=0; i < tide; i++) {\r
- buffer[i].Write(output);\r
- }\r
- // Console.WriteLine("ending instructions at " + output.Seek(0,SeekOrigin.Current));\r
- for (int i=0; i < paddingNeeded; i++) { output.Write((byte)0); }\r
- if (exceptions != null) {\r
- // Console.WriteLine("Writing exceptions");\r
- // Console.WriteLine("header = " + Hex.Short(exceptHeader) + " exceptSize = " + Hex.Int(exceptSize));\r
- output.Write(exceptHeader);\r
- output.Write3Bytes((uint)exceptSize);\r
- for (int i=0; i < exceptions.Count; i++) {\r
- TryBlock tryBlock = (TryBlock)exceptions[i];\r
- tryBlock.Write(output,fatExceptionFormat);\r
- }\r
- }\r
- }\r
-\r
- }\r
- /**************************************************************************/ \r
- /// <summary>\r
- /// A label in the IL\r
- /// </summary>\r
- public class CILLabel\r
- {\r
- CILInstruction branch;\r
- CILInstruction[] multipleBranches;\r
- int tide = 0;\r
- CILInstruction labInstr;\r
- uint offset = 0;\r
- \r
- public CILLabel (uint offset) {\r
- this.offset = offset;\r
- }\r
- \r
-\r
- internal CILLabel() {\r
- }
-\r
- internal void AddBranch(CILInstruction instr) {\r
- if (branch == null) {\r
- branch = instr;\r
- return;\r
- }\r
- if (multipleBranches == null) {\r
- multipleBranches = new CILInstruction[2];\r
- } else if (tide >= multipleBranches.Length) {\r
- CILInstruction[] tmp = multipleBranches;\r
- multipleBranches = new CILInstruction[tmp.Length*2];\r
- for (int i=0; i < tide; i++) {\r
- multipleBranches[i] = tmp[i];\r
- }\r
- }\r
- multipleBranches[tide++] = instr;\r
- }\r
-\r
- internal void AddLabelInstr(LabelInstr lInstr) {\r
- labInstr = lInstr;\r
- }\r
-\r
- internal uint GetLabelOffset() {\r
- if (labInstr == null) return 0;\r
- return labInstr.offset + offset;\r
- }\r
-\r
- }\r
- /**************************************************************************/ \r
- public abstract class CodeBlock {\r
-\r
- private static readonly int maxCodeSize = 256;\r
- protected CILLabel start, end;\r
- protected bool small = true;\r
-\r
- public CodeBlock(CILLabel start, CILLabel end) {\r
- this.start = start;\r
- this.end = end;\r
- }\r
-\r
- internal virtual bool isFat() {\r
- // Console.WriteLine("block start = " + start.GetLabelOffset() +\r
- // " block end = " + end.GetLabelOffset());\r
- return (end.GetLabelOffset() - start.GetLabelOffset()) > maxCodeSize;\r
- }\r
-\r
- internal virtual void Write(FileImage output, bool fatFormat) {\r
- if (fatFormat) output.Write(start.GetLabelOffset());\r
- else output.Write((short)start.GetLabelOffset());\r
- uint len = end.GetLabelOffset() - start.GetLabelOffset();\r
- if (fatFormat) output.Write(len);\r
- else output.Write((byte)len);\r
- }\r
-\r
- }\r
-\r
- /// <summary>\r
- /// The descriptor for a guarded block (.try)\r
- /// </summary>\r
- public class TryBlock : CodeBlock {\r
- protected bool fatFormat = false;\r
- protected int flags = 0;\r
- ArrayList handlers = new ArrayList();\r
-\r
- /// <summary>\r
- /// Create a new try block\r
- /// </summary>\r
- /// <param name="start">start label for the try block</param>\r
- /// <param name="end">end label for the try block</param>\r
- public TryBlock(CILLabel start, CILLabel end) : base(start,end) { }\r
-\r
- /// <summary>\r
- /// Add a handler to this try block\r
- /// </summary>\r
- /// <param name="handler">a handler to be added to the try block</param>\r
- public void AddHandler(HandlerBlock handler) {\r
- flags = handler.GetFlag();\r
- handlers.Add(handler);\r
- }\r
-\r
- internal void SetSize() {\r
- fatFormat = base.isFat();\r
- if (fatFormat) return;\r
- for (int i=0; i < handlers.Count; i++) {\r
- HandlerBlock handler = (HandlerBlock)handlers[i];\r
- if (handler.isFat()) {\r
- fatFormat = true;\r
- return;\r
- }\r
- }\r
- }\r
-\r
- internal int NumHandlers() {\r
- return handlers.Count;\r
- }\r
-\r
- internal override bool isFat() {\r
- return fatFormat;\r
- }\r
-\r
- internal override void Write(FileImage output, bool fatFormat) {\r
- // Console.WriteLine("writing exception details");\r
- for (int i=0; i < handlers.Count; i++) {\r
- // Console.WriteLine("Except block " + i);\r
- HandlerBlock handler = (HandlerBlock)handlers[i];\r
- if (fatFormat) output.Write(flags);\r
- else output.Write((short)flags);\r
- // Console.WriteLine("flags = " + Hex.Short(flags));\r
- base.Write(output,fatFormat);\r
- handler.Write(output,fatFormat);\r
- }\r
- }\r
- }\r
-\r
- public abstract class HandlerBlock : CodeBlock \r
- {\r
- protected static readonly short ExceptionFlag = 0;\r
- protected static readonly short FilterFlag = 0x01;\r
- protected static readonly short FinallyFlag = 0x02;\r
- protected static readonly short FaultFlag = 0x04;\r
-\r
- public HandlerBlock(CILLabel start, CILLabel end) : base(start,end) { }\r
-\r
- internal virtual short GetFlag() { return ExceptionFlag; }\r
-\r
- internal override void Write(FileImage output, bool fatFormat) {\r
- base.Write(output,fatFormat);\r
- }\r
-\r
- }\r
-\r
- /// <summary>\r
- /// The descriptor for a catch clause (.catch)\r
- /// </summary>\r
- public class Catch : HandlerBlock \r
- {\r
- Class exceptType;\r
- \r
- /// <summary>\r
- /// Create a new catch clause\r
- /// </summary>\r
- /// <param name="except">the exception to be caught</param>\r
- /// <param name="handlerStart">start of the handler code</param>\r
- /// <param name="handlerEnd">end of the handler code</param>\r
- public Catch(Class except, CILLabel handlerStart, CILLabel handlerEnd) \r
- : base(handlerStart,handlerEnd) {\r
- exceptType = except;\r
- }\r
-\r
- internal override void Write(FileImage output, bool fatFormat) {\r
- base.Write(output,fatFormat);\r
- output.Write(exceptType.Token());\r
- }\r
- }\r
-\r
- /// <summary>\r
- /// The descriptor for a filter clause (.filter)\r
- /// </summary>\r
- public class Filter : HandlerBlock \r
- {\r
- CILLabel filterLabel;\r
-\r
- /// <summary>\r
- /// Create a new filter clause\r
- /// </summary>\r
- /// <param name="filterLabel">the label where the filter code starts</param>\r
- /// <param name="handlerStart">the start of the handler code</param>\r
- /// <param name="handlerEnd">the end of the handler code</param>\r
- public Filter(CILLabel filterLabel, CILLabel handlerStart, \r
- CILLabel handlerEnd) : base(handlerStart,handlerEnd) {\r
- this.filterLabel = filterLabel;\r
- }\r
-\r
- internal override short GetFlag() { \r
- return FilterFlag; \r
- }\r
-\r
- internal override void Write(FileImage output, bool fatFormat) {\r
- base.Write(output,fatFormat);\r
- output.Write(filterLabel.GetLabelOffset());\r
- }\r
-\r
- }\r
-\r
- /// <summary>\r
- /// Descriptor for a finally block (.finally)\r
- /// </summary>\r
- public class Finally : HandlerBlock \r
- {\r
- /// <summary>\r
- /// Create a new finally clause\r
- /// </summary>\r
- /// <param name="finallyStart">start of finally code</param>\r
- /// <param name="finallyEnd">end of finally code</param>\r
- public Finally(CILLabel finallyStart, CILLabel finallyEnd)\r
- : base(finallyStart,finallyEnd) { }\r
-\r
- internal override short GetFlag() { \r
- return FinallyFlag; \r
- }\r
-\r
- internal override void Write(FileImage output, bool fatFormat) {\r
- base.Write(output,fatFormat);\r
- output.Write((int)0);\r
- }\r
-\r
- }\r
-\r
- /// <summary>\r
- /// Descriptor for a fault block (.fault)\r
- /// </summary>\r
- public class Fault : HandlerBlock \r
- {\r
- /// <summary>\r
- /// Create a new fault clause\r
- /// </summary>\r
- /// <param name="faultStart">start of the fault code</param>\r
- /// <param name="faultEnd">end of the fault code</param>\r
- public Fault(CILLabel faultStart, CILLabel faultEnd)\r
- : base(faultStart,faultEnd) { }\r
-\r
- internal override short GetFlag() { \r
- return FaultFlag; \r
- }\r
-\r
- internal override void Write(FileImage output, bool fatFormat) {\r
- base.Write(output,fatFormat);\r
- output.Write((int)0);\r
- \r
- }\r
- }\r
-\r
- /**************************************************************************/ \r
- /// <summary>\r
- /// The base descriptor for a class \r
- /// </summary>\r
- public abstract class Class : Type\r
- {\r
- protected int row = 0;\r
- protected string name, nameSpace;\r
- protected uint nameIx, nameSpaceIx;\r
- protected MetaData _metaData;\r
- internal Class(string nameSpaceName, string className, MetaData md)\r
- : base(0x12) {\r
- nameSpace = nameSpaceName;\r
- name = className;\r
- nameIx = md.AddToStringsHeap(name);\r
- nameSpaceIx = md.AddToStringsHeap(nameSpace);\r
- _metaData = md;\r
- }\r
-\r
- internal Class(uint nsIx, uint nIx) : base(0x12) {\r
- nameSpaceIx = nsIx;\r
- nameIx = nIx;\r
- }\r
-\r
- internal virtual uint TypeDefOrRefToken() { return 0; }\r
-\r
- internal virtual void MakeValueClass() {\r
- typeIndex = 0x11;\r
- }\r
- \r
- internal virtual string TypeName() {\r
- return (nameSpace + "." + name);\r
- }\r
-\r
- internal override MetaDataElement GetTypeSpec(MetaData md) {\r
- return this;\r
- }\r
- }\r
- /**************************************************************************/ \r
- // This Class produces entries in the TypeDef table of the MetaData \r
- // in the PE meta data.\r
-\r
- // NOTE: Entry 0 in TypeDef table is always the pseudo class <module> \r
- // which is the parent for functions and variables declared a module level\r
-\r
- /// <summary>\r
- /// The descriptor for a class defined in the IL (.class) in the current assembly/module\r
- /// </summary>\r
- /// \r
- public class ClassDef : Class\r
- {\r
- private static readonly uint HasSecurity = 0x00040000;\r
- private static readonly byte ElementType_Class = 0x12;\r
-\r
- Class superType;\r
- ArrayList fields = new ArrayList();\r
- ArrayList methods = new ArrayList();\r
- ArrayList events;\r
- ArrayList properties;\r
- bool typeIndexChecked = true;\r
- uint fieldIx = 0, methodIx = 0;\r
- byte[] securityActions;\r
- uint flags;\r
- ClassLayout layout;\r
- ClassDef parentClass;\r
- MetaData metaData;\r
- \r
- internal ClassDef(TypeAttr attrSet, string nsName, string name, \r
- MetaData md) : base(nsName, name, md) {\r
- metaData = md;\r
- superType = metaData.mscorlib.GetSpecialSystemClass(PrimitiveType.Object);\r
- flags = (uint)attrSet;\r
- tabIx = MDTable.TypeDef;\r
- }\r
-\r
- internal void SetSuper(Class sClass) {\r
- superType = sClass;\r
- if (sClass is ClassRef)\r
- typeIndex = superType.GetTypeIndex();\r
- else\r
- typeIndexChecked = false;\r
- }\r
-\r
- internal override void MakeValueClass() {\r
- superType = metaData.mscorlib.ValueType();\r
- typeIndex = superType.GetTypeIndex();\r
- }\r
-\r
- public void SpecialNoSuper() {\r
- superType = null;\r
- }\r
-\r
- /// <summary>\r
- /// Add an attribute to this class\r
- /// </summary>\r
- /// <param name="ta">the attribute to be added</param>\r
- public void AddAttribute(TypeAttr ta) { \r
- flags |= (uint)ta;\r
- }\r
-\r
- /// <summary>\r
- /// Add an interface that is implemented by this class\r
- /// </summary>\r
- /// <param name="iFace">the interface that is implemented</param>\r
- public void AddImplementedInterface(Class iFace) {\r
- metaData.AddToTable(MDTable.InterfaceImpl,new InterfaceImpl(this,iFace));\r
- }\r
-\r
- /// <summary>\r
- /// Add a named generic type parameter\r
- /// </summary>\r
- public GenericParameter AddGenericParameter (short index, string name) {\r
- GenericParameter gp = new GenericParameter (this, metaData, index, name);
- metaData.AddToTable (MDTable.GenericParam, gp);\r
- return gp;
- }\r
-\r
- /// <summary>\r
- /// Add a field to this class\r
- /// </summary>\r
- /// <param name="name">field name</param>\r
- /// <param name="fType">field type</param>\r
- /// <returns>a descriptor for this new field</returns>\r
- public FieldDef AddField(string name, Type fType) {\r
- FieldDef field = new FieldDef(name,fType);\r
- fields.Add(field);\r
- return field;\r
- }\r
-\r
- /// <summary>\r
- /// Add a field to this class\r
- /// </summary>\r
- /// <param name="fAtts">attributes for this field</param>\r
- /// <param name="name">field name</param>\r
- /// <param name="fType">field type</param>\r
- /// <returns>a descriptor for this new field</returns>\r
- public FieldDef AddField(FieldAttr fAtts, string name, Type fType) {\r
- FieldDef field = new FieldDef(fAtts,name,fType);\r
- fields.Add(field);\r
- return field;\r
- }\r
+ private void WriteSDataSection()
+ {
+ long size = sdata.Size ();
+ long start = BaseStream.Position;
+ for (int i=0; i < data.Count; i++) {
+ ((DataConstant)data[i]).Write(this);
+ }
+ while (BaseStream.Position < (start + size))
+ Write ((byte) 0);
+ }
- public void SetFieldOrder (ArrayList fields)
- {
- this.fields = fields;
- }
+ private void WriteRsrcSection()
+ {
+ }
- /// <summary>\r
- /// Add a method to this class\r
- /// </summary>\r
- /// <param name="name">method name</param>\r
- /// <param name="retType">return type</param>\r
- /// <param name="pars">parameters</param>\r
- /// <returns>a descriptor for this new method</returns>\r
- public MethodDef AddMethod(string name, Type retType, Param[] pars) {\r
- // Console.WriteLine("Adding method " + name + " to class " + this.name);\r
- MethodDef meth = new MethodDef(metaData,name,retType, pars);\r
- methods.Add(meth);\r
- return meth;\r
- }\r
-\r
- /// <summary>\r
- /// Add a method to this class\r
- /// </summary>\r
- /// <param name="mAtts">attributes for this method</param>\r
- /// <param name="iAtts">implementation attributes for this method</param>\r
- /// <param name="name">method name</param>\r
- /// <param name="retType">return type</param>\r
- /// <param name="pars">parameters</param>\r
- /// <returns>a descriptor for this new method</returns>\r
- public MethodDef AddMethod(MethAttr mAtts, ImplAttr iAtts, string name, \r
- Type retType, Param[] pars) {\r
- // Console.WriteLine("Adding method " + name + " to class " + this.name);\r
- MethodDef meth = new MethodDef(metaData,mAtts,iAtts,name,retType,pars);\r
- methods.Add(meth);\r
- return meth;\r
- }\r
-\r
- /// <summary>\r
- /// Add an event to this class\r
- /// </summary>\r
- /// <param name="name">event name</param>\r
- /// <param name="eType">event type</param>\r
- /// <returns>a descriptor for this new event</returns>\r
- public Event AddEvent(string name, Type eType) {\r
- Event e = new Event(name,eType,this);\r
- if (events == null) events = new ArrayList();\r
- events.Add(e);\r
- return e;\r
- }\r
-\r
- /// <summary>\r
- /// Add a property to this class\r
- /// </summary>\r
- /// <param name="name">property name</param>\r
- /// <param name="propType">property type</param>\r
- /// <returns>a descriptor for this new property</returns>\r
- public Property AddProperty(string name, Type retType, Type[] pars) {\r
- Property p = new Property(name, retType, pars, this);\r
- if (properties == null) properties = new ArrayList();\r
- properties.Add(p);\r
- return p;\r
- }\r
-\r
-\r
- /// <summary>\r
- /// Add a nested class to this class\r
- /// </summary>\r
- /// <param name="attrSet">attributes for this nested class</param>\r
- /// <param name="nsName">nested name space name</param>\r
- /// <param name="name">nested class name</param>\r
- /// <returns>a descriptor for this new nested class</returns>\r
- public ClassDef AddNestedClass(TypeAttr attrSet, string nsName, \r
- string name) {\r
- ClassDef nClass = new ClassDef(attrSet,nsName,name,metaData);\r
- metaData.AddToTable(MDTable.TypeDef,nClass);\r
- metaData.AddToTable(MDTable.NestedClass,new MapElem(nClass,Row,MDTable.TypeDef));\r
- nClass.parentClass = this;\r
- return (nClass);\r
- }\r
-\r
- /// <summary>\r
- /// Add a nested class to this class\r
- /// </summary>\r
- /// <param name="attrSet">attributes for this nested class</param>\r
- /// <param name="nsName">nested name space name</param>\r
- /// <param name="name">nested class name</param>\r
- /// <param name="sType">super type of this nested class</param>\r
- /// <returns>a descriptor for this new nested class</returns>\r
- public ClassDef AddNestedClass(TypeAttr attrSet, string nsName, \r
- string name, Class sType) {\r
- ClassDef nClass = new ClassDef(attrSet,nsName,name,metaData);\r
- nClass.SetSuper(sType);\r
- metaData.AddToTable(MDTable.TypeDef,nClass);\r
- metaData.AddToTable(MDTable.NestedClass,\r
- new MapElem(nClass,Row,MDTable.TypeDef));\r
- nClass.parentClass = this;\r
- return (nClass);\r
- }\r
-\r
- /// <summary>\r
- /// Add layout information for this class. This class must have the\r
- /// sequential or explicit attribute.\r
- /// </summary>\r
- /// <param name="packSize">packing size (.pack)</param>\r
- /// <param name="classSize">class size (.size)</param>\r
- public void AddLayoutInfo (int packSize, int classSize) {\r
- layout = new ClassLayout(packSize,classSize,this);\r
- }\r
-\r
- /// <summary>\r
- /// Use a method as the implementation for another method (.override)\r
- /// </summary>\r
- /// <param name="decl">the method to be overridden</param>\r
- /// <param name="body">the implementation to be used</param>\r
- public void AddMethodOverride(Method decl, Method body) {\r
- metaData.AddToTable(MDTable.MethodImpl,new MethodImpl(this,decl,body));\r
- }\r
-\r
- /// <summary>\r
- /// Add security to this class NOT YET IMPLEMENTED\r
- /// </summary>\r
- /// <param name="permissionSet"></param>\r
- public void AddSecurity(byte[] permissionSet) {\r
- throw(new NotYetImplementedException("Class security "));\r
- //flags |= HasSecurity;\r
- // securityActions = permissionSet;\r
- }\r
-\r
- //public void AddLineInfo(int row, int col) { }\r
-\r
- internal void CheckTypeIndex() {\r
- if (typeIndexChecked) return;\r
- if (!(superType is ClassRef)) \r
- ((ClassDef)superType).CheckTypeIndex();\r
- typeIndex = superType.GetTypeIndex();\r
- typeIndexChecked = true;\r
- }\r
-\r
- internal sealed override void BuildTables(MetaData md) {\r
- if (done) return;\r
- if ((flags & (uint)TypeAttr.Interface) != 0) { superType = null; }\r
- // Console.WriteLine("Building tables for " + name);\r
- if (layout != null) md.AddToTable(MDTable.ClassLayout,layout);\r
- // Console.WriteLine("adding methods " + methods.Count);\r
- methodIx = md.TableIndex(MDTable.Method);\r
- for (int i=0; i < methods.Count; i++) {\r
- md.AddToTable(MDTable.Method,(MetaDataElement)methods[i]);\r
- ((MethodDef)methods[i]).BuildTables(md);\r
- }\r
- // Console.WriteLine("adding fields");\r
- fieldIx = md.TableIndex(MDTable.Field);\r
- for (int i=0; i < fields.Count; i++) {\r
- md.AddToTable(MDTable.Field,(MetaDataElement)fields[i]);\r
- ((FieldDef)fields[i]).BuildTables(md);\r
- }\r
- // Console.WriteLine("adding events and properties");\r
- if (events != null) { \r
- for (int i=0; i < events.Count; i++) {\r
- md.AddToTable(MDTable.Event,(Event)events[i]);\r
- ((Event)events[i]).BuildTables(md);\r
- }\r
- md.AddToTable(MDTable.EventMap,\r
- new MapElem(this,((Event)events[0]).Row,MDTable.Event));\r
- }\r
- if (properties != null) { \r
- for (int i=0; i < properties.Count; i++) {\r
- md.AddToTable(MDTable.Property,(Property)properties[i]);\r
- ((Property)properties[i]).BuildTables(md);\r
- }\r
- md.AddToTable(MDTable.PropertyMap,new MapElem(this,\r
- ((Property)properties[0]).Row,MDTable.Property));\r
- }\r
- // Console.WriteLine("End of building tables");\r
- done = true;\r
- }\r
-\r
- internal sealed override uint Size(MetaData md) {\r
- return 4 + 2 * md.StringsIndexSize() + \r
- md.CodedIndexSize(CIx.TypeDefOrRef) +\r
- md.TableIndexSize(MDTable.Field) + \r
- md.TableIndexSize(MDTable.Method);\r
- }\r
-\r
- internal sealed override void Write(FileImage output) {\r
- output.Write(flags);\r
- output.StringsIndex(nameIx);\r
- output.StringsIndex(nameSpaceIx);\r
- //if (superType != null) \r
- // Console.WriteLine("getting coded index for superType of " + name + " = " + superType.GetCodedIx(CIx.TypeDefOrRef));\r
- output.WriteCodedIndex(CIx.TypeDefOrRef,superType);\r
- output.WriteIndex(MDTable.Field,fieldIx);\r
- output.WriteIndex(MDTable.Method,methodIx);\r
- }\r
-\r
- internal sealed override uint TypeDefOrRefToken() {\r
- uint cIx = Row;\r
- cIx = cIx << 2;\r
- return cIx;\r
- }\r
-\r
- internal sealed override void TypeSig(MemoryStream sig) {\r
- if (!typeIndexChecked) CheckTypeIndex();\r
- sig.WriteByte(GetTypeIndex());\r
- MetaData.CompressNum(TypeDefOrRefToken(),sig);\r
- }\r
-\r
- internal sealed override uint GetCodedIx(CIx code) {\r
- switch (code) {\r
- case (CIx.TypeDefOrRef) : return 0; \r
- case (CIx.HasCustomAttr) : return 3; \r
- case (CIx.HasDeclSecurity) : return 0; \r
- case (CIx.TypeOrMethodDef) : return 0; \r
- }\r
- return 0;\r
- }\r
- \r
- }\r
- /**************************************************************************/ \r
- /// <summary>\r
- /// Layout information for a class (.class [sequential | explicit])\r
- /// </summary>\r
- internal class ClassLayout : MetaDataElement\r
- {\r
- ClassDef parent;\r
- ushort packSize = 0;\r
- uint classSize = 0;\r
-\r
- internal ClassLayout(int pack, int cSize, ClassDef par) {\r
- packSize = (ushort)pack;\r
- classSize = (uint)cSize;\r
- parent = par;\r
- tabIx = MDTable.ClassLayout;\r
- }\r
-\r
- internal sealed override uint Size(MetaData md) {\r
- return 6 + md.TableIndexSize(MDTable.TypeDef);\r
- }\r
-\r
- internal sealed override void Write(FileImage output) {\r
- output.Write(packSize);\r
- output.Write(classSize);\r
- output.WriteIndex(MDTable.TypeDef,parent.Row);\r
- }\r
-\r
- }\r
- /**************************************************************************/ \r
- /// <summary>\r
- /// Descriptor for a class/interface declared in another module of THIS \r
- /// assembly, or in another assembly.\r
- /// </summary>\r
- public class ClassRef : Class\r
- {\r
- protected ResolutionScope parent;\r
- ExternClass externClass;\r
- protected MetaData metaData;\r
-\r
- internal ClassRef(string nsName, string name, MetaData md) : base(nsName, name, md) {\r
- metaData = md;\r
- tabIx = MDTable.TypeRef;\r
- }\r
-\r
- /// <summary>\r
- /// Add a method to this class\r
- /// </summary>\r
- /// <param name="name">method name</param>\r
- /// <param name="retType">return type</param>\r
- /// <param name="pars">parameter types</param>\r
- /// <returns>a descriptor for this method</returns>\r
- public MethodRef AddMethod(string name, Type retType, Type[] pars) {\r
- MethodRef meth = new MethodRef(this,name,retType,pars,false,null);\r
- metaData.AddToTable(MDTable.MemberRef,meth);\r
- return meth;\r
- }\r
-\r
- /// <summary>\r
- /// Add a method to this class\r
- /// </summary>\r
- /// <param name="name">method name</param>\r
- /// <param name="retType">return type</param>\r
- /// <param name="pars">parameter types</param>\r
- /// <returns>a descriptor for this method</returns>\r
- public MethodRef AddVarArgMethod(string name, Type retType, \r
- Type[] pars, Type[] optPars) {\r
- MethodRef meth = new MethodRef(this,name,retType,pars,true,optPars);\r
- metaData.AddToTable(MDTable.MemberRef,meth);\r
- return meth;\r
- }\r
-\r
- /// <summary>\r
- /// Add a field to this class\r
- /// </summary>\r
- /// <param name="name">field name</param>\r
- /// <param name="fType">field type</param>\r
- /// <returns>a descriptor for this field</returns>\r
- public FieldRef AddField(string name, Type fType) {\r
- FieldRef field = new FieldRef(this,name,fType);\r
- metaData.AddToTable(MDTable.MemberRef,field);\r
- return field;\r
- }\r
-\r
- internal void SetParent(ResolutionScope par) {\r
- parent = par;\r
- }\r
-\r
- internal override string TypeName() {\r
- if ((parent != null) && (parent is AssemblyRef))\r
- return (nameSpace + "." + name + ", " + ((AssemblyRef)parent).TypeName());\r
- else \r
- return (nameSpace + name);\r
- }\r
-\r
- internal sealed override uint Size(MetaData md) {\r
- return md.CodedIndexSize(CIx.ResolutionScope) + 2 * \r
- md.StringsIndexSize();\r
- }\r
-\r
- internal sealed override void Write(FileImage output) {\r
- output.WriteCodedIndex(CIx.ResolutionScope,parent);\r
- output.StringsIndex(nameIx);\r
- output.StringsIndex(nameSpaceIx);\r
- }\r
-\r
- internal override sealed uint TypeDefOrRefToken() {\r
- uint cIx = Row;\r
- cIx = (cIx << 2) | 0x1;\r
- return cIx;\r
- }\r
-\r
- internal override void TypeSig(MemoryStream sig) {\r
- sig.WriteByte(GetTypeIndex());\r
- MetaData.CompressNum(TypeDefOrRefToken(),sig);\r
- }\r
-\r
- internal sealed override uint GetCodedIx(CIx code) {\r
- switch (code) {\r
- case (CIx.TypeDefOrRef) : return 1; \r
- case (CIx.HasCustomAttr) : return 2; \r
- case (CIx.MemberRefParent) : return 1; \r
- case (CIx.ResolutionScope) : return 3; \r
- }\r
- return 0;\r
- }\r
- \r
- }\r
- /**************************************************************************/ \r
-\r
- public class ExternClassRef : ClassRef {\r
-\r
- ExternClass externClass;\r
-\r
- internal ExternClassRef(TypeAttr attrs, string nsName, string name,\r
- FileRef declFile, MetaData md) : base(nsName,name,md) {\r
- externClass = new ExternClass(attrs,nameSpaceIx,nameIx,declFile);\r
- metaData.AddToTable(MDTable.ExportedType,externClass);\r
- }\r
-\r
- internal ExternClassRef(string name, MetaData md) : base(null,name,md) {\r
- }\r
-\r
- public ClassRef AddNestedClass(TypeAttr attrs, string name) {\r
- ExternClassRef nestedClass = new ExternClassRef(name,metaData);\r
- externClass = new ExternClass(attrs,0,nameIx,this.externClass);\r
- metaData.AddToTable(MDTable.ExportedType,externClass);\r
- return nestedClass;\r
- }\r
- \r
- }\r
- /**************************************************************************/ \r
- /// <summary>\r
- /// Descriptor for a constant value\r
- /// </summary>\r
- public abstract class Constant {\r
- protected uint size = 0;\r
- protected Type type;\r
- protected uint blobIndex;\r
- protected bool addedToBlobHeap = false;\r
-\r
- internal Constant() { }\r
-\r
- internal virtual uint GetBlobIndex(MetaData md) { return 0; }\r
-\r
- internal uint GetSize() { return size; }\r
-\r
- internal byte GetTypeIndex() { return type.GetTypeIndex(); }\r
-\r
- internal virtual void Write(BinaryWriter bw) { }\r
-\r
- }\r
- /// <summary>\r
- /// Descriptor for a constant value\r
- /// </summary>\r
- public abstract class DataConstant : Constant {\r
- private uint dataOffset = 0;\r
-\r
- internal DataConstant() { }\r
+ private void WriteRelocSection()
+ {
+ // Console.WriteLine("Writing reloc section at " + Seek(0,SeekOrigin.Current) + " = " + relocOffset);
+ MemoryStream str = (MemoryStream)reloc.BaseStream;
+ Write(str.ToArray());
+ WriteZeros(NumToAlign((uint)str.Position,fileAlign));
+ }
- public Type Type {
- get { return type; }
- set { type = value; }
- }
+ internal void SetEntryPoint(uint entryPoint)
+ {
+ entryPointToken = entryPoint;
+ }
- public uint DataOffset {\r
- get { return dataOffset; }\r
- set { dataOffset = value; }\r
- }\r
-\r
- }\r
-\r
- /// <summary>\r
- /// Boolean constant\r
- /// </summary>\r
- public class BoolConst : Constant {\r
- bool val;\r
-\r
- /// <summary>\r
- /// Create a new boolean constant with the value "val"\r
- /// </summary>\r
- /// <param name="val">value of this boolean constant</param>\r
- public BoolConst(bool val) {\r
- this.val = val;\r
- size = 1;\r
- type = PrimitiveType.Boolean;\r
- }\r
-\r
- internal sealed override uint GetBlobIndex(MetaData md) {\r
- if (!addedToBlobHeap) {\r
- if (val) blobIndex = md.AddToBlobHeap((sbyte)1);\r
- else blobIndex = md.AddToBlobHeap((sbyte)0);\r
- addedToBlobHeap = true;\r
- }\r
- return blobIndex;\r
- }\r
-\r
- internal sealed override void Write(BinaryWriter bw) {\r
- if (val) bw.Write((sbyte)1);\r
- else bw.Write((sbyte)0);\r
- }\r
-\r
- }\r
-\r
- public class ByteArrConst : DataConstant {\r
- byte[] val;\r
-\r
- public ByteArrConst(byte[] val) {\r
- this.val = val;\r
- size = (uint)val.Length;\r
- }\r
-\r
- internal sealed override uint GetBlobIndex(MetaData md) {\r
- if (!addedToBlobHeap) {\r
- blobIndex = md.AddToBlobHeap(val);\r
- addedToBlobHeap = true;\r
- }\r
- return blobIndex;\r
- }\r
-\r
- internal sealed override void Write(BinaryWriter bw) {\r
- bw.Write(val);\r
- }\r
-\r
- }\r
-\r
- public class CharConst : Constant {\r
- char val;\r
-\r
- public CharConst(char val) {\r
- this.val = val;\r
- size = 2;\r
- type = PrimitiveType.Char;\r
- }\r
-\r
- internal sealed override uint GetBlobIndex(MetaData md) {\r
- if (!addedToBlobHeap) {\r
- blobIndex = md.AddToBlobHeap(val);\r
- addedToBlobHeap = true;\r
- }\r
- return blobIndex;\r
- }\r
-\r
- internal sealed override void Write(BinaryWriter bw) {\r
- bw.Write(val);\r
- }\r
-\r
- }\r
-\r
- public class FloatConst : DataConstant {\r
- float val;\r
-\r
- public FloatConst(float val) {\r
- this.val = val;\r
- size = 4;\r
- type = PrimitiveType.Float32;\r
- }\r
-\r
- internal sealed override uint GetBlobIndex(MetaData md) {\r
- if (!addedToBlobHeap) {\r
- blobIndex = md.AddToBlobHeap(val);\r
- addedToBlobHeap = true;\r
- }\r
- return blobIndex;\r
- }\r
-\r
- internal sealed override void Write(BinaryWriter bw) {\r
- bw.Write(val);\r
- }\r
-\r
- }\r
-\r
- public class DoubleConst : DataConstant {\r
- double val;\r
-\r
- public DoubleConst(double val) {\r
- this.val = val;\r
- size = 8;\r
- type = PrimitiveType.Float64;\r
- }\r
-\r
- internal sealed override uint GetBlobIndex(MetaData md) {\r
- if (!addedToBlobHeap) {\r
- blobIndex = md.AddToBlobHeap(val);\r
- addedToBlobHeap = true;\r
- }\r
- return blobIndex;\r
- }\r
-\r
- internal sealed override void Write(BinaryWriter bw) {\r
- bw.Write(val);\r
- }\r
-\r
- }\r
-\r
- public class IntConst : DataConstant {\r
- long val;\r
-\r
- public IntConst(sbyte val) {\r
- this.val = val;\r
- size = 1;\r
- type = PrimitiveType.Int8;\r
- }\r
-\r
- public IntConst(short val) {\r
- this.val = val;\r
- size = 2;\r
- type = PrimitiveType.Int16;\r
- }\r
-\r
- public IntConst(int val) {\r
- this.val = val;\r
- size = 4;\r
- type = PrimitiveType.Int32;\r
- }\r
-\r
- public IntConst(long val) {\r
- this.val = val;\r
- size = 8;\r
- type = PrimitiveType.Int64;\r
- }\r
-\r
- internal sealed override uint GetBlobIndex(MetaData md) {\r
- if (!addedToBlobHeap) {\r
- switch (size) {\r
- case (1) : blobIndex = md.AddToBlobHeap((sbyte)val); break;\r
- case (2) : blobIndex = md.AddToBlobHeap((short)val); break;\r
- case (4) : blobIndex = md.AddToBlobHeap((int)val); break;\r
- default : blobIndex = md.AddToBlobHeap(val); break; \r
- }\r
- addedToBlobHeap = true;\r
- }\r
- return blobIndex;\r
- }\r
-\r
- internal sealed override void Write(BinaryWriter bw) {\r
- switch (size) {\r
- case (1) : bw.Write((sbyte)val); break;\r
- case (2) : bw.Write((short)val); break;\r
- case (4) : bw.Write((int)val); break;\r
- default : bw.Write(val); break; \r
- }\r
- }\r
-\r
- }\r
-\r
- public class UIntConst : Constant {\r
- long val;\r
-\r
- public UIntConst(sbyte val) {\r
- this.val = val;\r
- size = 1;\r
- type = PrimitiveType.UInt8;\r
- }\r
- public UIntConst(short val) {\r
- this.val = val;\r
- size = 2;\r
- type = PrimitiveType.UInt16;\r
- }\r
- public UIntConst(int val) {\r
- this.val = val;\r
- size = 4;\r
- type = PrimitiveType.UInt32;\r
- }\r
- public UIntConst(long val) {\r
- this.val = val;\r
- size = 8;\r
- type = PrimitiveType.UInt64;\r
- }\r
-\r
- internal sealed override uint GetBlobIndex(MetaData md) {\r
- if (!addedToBlobHeap) {\r
- switch (size) {\r
- case (1) : blobIndex = md.AddToBlobHeap((sbyte)val); break;\r
- case (2) : blobIndex = md.AddToBlobHeap((short)val); break;\r
- case (4) : blobIndex = md.AddToBlobHeap((int)val); break;\r
- default : blobIndex = md.AddToBlobHeap(val); break;\r
- }\r
- addedToBlobHeap = true;\r
- }\r
- return blobIndex;\r
- }\r
-\r
- internal sealed override void Write(BinaryWriter bw) {\r
- switch (size) {\r
- case (1) : bw.Write((sbyte)val); break;\r
- case (2) : bw.Write((short)val); break;\r
- case (4) : bw.Write((int)val); break;\r
- default : bw.Write(val); break;\r
- }\r
- }\r
-\r
- }\r
-\r
- public class StringConst : DataConstant {\r
- string val;\r
-\r
- public StringConst(string val) {\r
- this.val = val;\r
- size = (uint)val.Length; // need to add null ??\r
- type = PrimitiveType.String;\r
- }\r
-\r
- internal sealed override uint GetBlobIndex(MetaData md) {\r
- if (!addedToBlobHeap) {
- byte [] b = Encoding.Unicode.GetBytes (val);
- blobIndex = md.AddToBlobHeap(b);\r
- addedToBlobHeap = true;\r
- }\r
- return blobIndex;\r
- }\r
-\r
- internal sealed override void Write(BinaryWriter bw) {\r
- bw.Write(val);\r
- }\r
-\r
- }\r
-\r
- public class NullConst : Constant {\r
- \r
- public NullConst() { \r
- size = 4;\r
- type = PrimitiveType.Class;\r
- }\r
-\r
- internal sealed override uint GetBlobIndex(MetaData md) {\r
- if (!addedToBlobHeap) {\r
- blobIndex = md.AddToBlobHeap((int)0);\r
- addedToBlobHeap = true;\r
- }\r
- return blobIndex;\r
- }\r
-\r
- internal sealed override void Write(BinaryWriter bw) {\r
- bw.Write((int)0); \r
- }\r
-\r
- }\r
-\r
- public class AddressConstant : DataConstant {\r
- DataConstant data;\r
-\r
- public AddressConstant(DataConstant dConst) {\r
- data = dConst;\r
- size = 4;\r
- type = PrimitiveType.TypedRef;\r
- }\r
-\r
- internal sealed override void Write(BinaryWriter bw) {\r
- ((FileImage)bw).WriteDataRVA(data.DataOffset);\r
- }\r
-\r
- }\r
-\r
- public class RepeatedConstant : DataConstant {\r
- DataConstant data;\r
- uint repCount;\r
-\r
- public RepeatedConstant(DataConstant dConst, int repeatCount) {\r
- data = dConst;\r
- repCount = (uint)repeatCount;\r
- int[] sizes = new int[1];\r
- sizes[0] = repeatCount;\r
- type = new BoundArray(type,1,sizes);\r
- size = data.GetSize() * repCount;\r
- }\r
-\r
- internal sealed override void Write(BinaryWriter bw) {\r
- for (int i=0; i < repCount; i++) {\r
- data.Write(bw);\r
- }\r
- }\r
-\r
- }\r
-\r
- public class ArrayConstant : DataConstant {\r
- DataConstant[] dataVals;\r
-\r
- public ArrayConstant(DataConstant[] dVals) {\r
- dataVals = dVals;\r
- for (int i=0; i < dataVals.Length; i++) {\r
- size += dataVals[i].GetSize();\r
- }\r
- }\r
-\r
- internal sealed override void Write(BinaryWriter bw) {\r
- for (int i=0; i < dataVals.Length; i++) {\r
- dataVals[i].Write(bw);\r
- }\r
- }\r
-\r
- }\r
-\r
- public class ClassType : Constant {\r
- string name;\r
- Class desc;\r
-\r
- public ClassType(string className) {\r
- name = className;\r
- type = PrimitiveType.ClassType;\r
- }\r
-\r
- public ClassType(Class classDesc) {\r
- desc = classDesc;\r
- type = PrimitiveType.ClassType;\r
- }\r
-\r
- internal override void Write(BinaryWriter bw) {\r
- if (name == null) name = desc.TypeName();\r
- bw.Write(name);\r
- }\r
-\r
- }\r
-\r
-\r
-\r
- /**************************************************************************/ \r
- /// <summary>\r
- /// Summary description for ConstantElem.\r
- /// </summary>\r
- internal class ConstantElem : MetaDataElement\r
- {\r
- MetaDataElement parent;\r
- Constant cValue;\r
- uint valIx = 0;\r
-\r
- internal ConstantElem(MetaDataElement parent, Constant val) {\r
- this.parent = parent;\r
- cValue = val;\r
- tabIx = MDTable.Constant;\r
- }\r
-\r
- internal sealed override void BuildTables(MetaData md) {\r
- if (done) return;\r
- valIx = cValue.GetBlobIndex(md);\r
- done = true;\r
- }\r
-\r
- internal void AddToBlob(BinaryWriter bw) {\r
- cValue.Write(bw);\r
- }\r
-\r
- internal sealed override uint Size(MetaData md) {\r
- return 2 + md.CodedIndexSize(CIx.HasConst) + md.BlobIndexSize();\r
- }\r
-\r
- internal sealed override void Write(FileImage output) {\r
- output.Write(cValue.GetTypeIndex());\r
- output.Write((byte)0);\r
- output.WriteCodedIndex(CIx.HasConst,parent);\r
- output.BlobIndex(valIx);\r
- }\r
-\r
- }\r
- /**************************************************************************/ \r
- /// <summary>\r
- /// Descriptor for a Custom Attribute (.custom) \r
- /// </summary>\r
-\r
- public class CustomAttribute : MetaDataElement\r
- {\r
- private static readonly ushort prolog = 0x0001;\r
- MetaDataElement parent;\r
- Method type;\r
- uint valIx;\r
- Constant cVal;\r
- byte[] byteVal;\r
- ushort numNamed = 0;\r
- ArrayList names, vals;\r
-\r
- internal CustomAttribute(MetaDataElement paren, Method constrType, \r
- Constant val) {\r
- parent = paren;\r
- type = constrType;\r
- cVal = val;\r
- tabIx = MDTable.CustomAttribute;\r
- throw(new NotYetImplementedException("Custom Attributes "));\r
- }\r
-\r
- internal CustomAttribute(MetaDataElement paren, Method constrType,\r
- byte[] val) {\r
- parent = paren;\r
- type = constrType;\r
- tabIx = MDTable.CustomAttribute;\r
- byteVal = val;\r
- }\r
-\r
- public void AddFieldOrProp(string name, Constant val) {\r
- if (numNamed == 0) {\r
- names = new ArrayList();\r
- vals = new ArrayList();\r
- }\r
- names.Add(name);\r
- vals.Add(val);\r
- }\r
-\r
- internal sealed override void BuildTables(MetaData md) {\r
- BinaryWriter bw = new BinaryWriter(new MemoryStream());\r
- bw.Write(byteVal);\r
- md.AddToTable(MDTable.CustomAttribute, this);\r
- MemoryStream str = (MemoryStream)bw.BaseStream;\r
- valIx = md.AddToBlobHeap(str.ToArray());\r
- }\r
-\r
- internal sealed override uint Size(MetaData md) {\r
- return md.CodedIndexSize(CIx.HasCustomAttr) + md.CodedIndexSize(CIx.CustomAttributeType) + md.BlobIndexSize();\r
- }\r
-\r
- internal sealed override void Write(FileImage output) {\r
- output.WriteCodedIndex(CIx.HasCustomAttr,parent);\r
- output.WriteCodedIndex(CIx.CustomAttributeType,type);\r
- output.BlobIndex(valIx);\r
- }\r
-\r
- }\r
- /**************************************************************************/ \r
- /// <summary>\r
- /// Descriptor for a custom modifier of a type (modopt or modreq)\r
- /// </summary>\r
-\r
- public class CustomModifiedType : Type\r
- {\r
- Type type;\r
- Class cmodType;\r
-\r
- /// <summary>\r
- /// Create a new custom modifier for a type\r
- /// </summary>\r
- /// <param name="type">the type to be modified</param>\r
- /// <param name="cmod">the modifier</param>\r
- /// <param name="cmodType">the type reference to be associated with the type</param>\r
- public CustomModifiedType(Type type, CustomModifier cmod, Class cmodType)\r
- : base((byte)cmod) {\r
- this.type = type;\r
- this.cmodType = cmodType;\r
- }\r
-\r
- internal sealed override void TypeSig(MemoryStream str) {\r
- str.WriteByte(typeIndex);\r
- MetaData.CompressNum(cmodType.TypeDefOrRefToken(),str);\r
- type.TypeSig(str);\r
- }\r
- \r
- }\r
- /**************************************************************************/ \r
- /// <summary>\r
- /// Descriptor for security permissions for a class or a method NOT YET IMPLEMENTED\r
- /// </summary>\r
- \r
- public class DeclSecurity : MetaDataElement\r
- {\r
- ushort action;\r
- MetaDataElement parent;\r
- uint permissionIx;\r
-\r
- internal DeclSecurity(MetaDataElement paren, ushort act) {\r
- parent = paren;\r
- action = act;\r
- tabIx = MDTable.DeclSecurity;\r
- throw(new NotYetImplementedException("Security "));\r
- }\r
-\r
- internal sealed override uint Size(MetaData md) {\r
- return 2 + md.CodedIndexSize(CIx.HasDeclSecurity) + md.BlobIndexSize();\r
- }\r
-\r
- internal sealed override void BuildTables(MetaData md) {\r
- if (done) return;\r
-// add permission to blob heap\r
- done = true;\r
- }\r
-\r
- internal sealed override void Write(FileImage output) {\r
- output.Write(action);\r
- output.WriteCodedIndex(CIx.HasDeclSecurity,parent);\r
- output.BlobIndex(permissionIx);\r
- }\r
- \r
- }\r
- /**************************************************************************/ \r
- /// <summary>\r
- /// Descriptor for an event\r
- /// </summary>\r
- public class Event : Feature\r
- {\r
- Type eventType;\r
-\r
- internal Event(string name, Type eType, ClassDef parent) \r
- : base(name, parent) {\r
- eventType = eType;\r
- tabIx = MDTable.Event;\r
- }\r
-\r
- /// <summary>\r
- /// Add the addon method to this event\r
- /// </summary>\r
- /// <param name="addon">the addon method</param>\r
- public void AddAddon(MethodDef addon) {\r
- AddMethod(addon,MethodType.AddOn);\r
- }\r
-\r
- /// <summary>\r
- /// Add the removeon method to this event\r
- /// </summary>\r
- /// <param name="removeOn">the removeon method</param>\r
- public void AddRemoveOn(MethodDef removeOn) {\r
- AddMethod(removeOn,MethodType.RemoveOn);\r
- }\r
-\r
- /// <summary>\r
- /// Add the fire method to this event\r
- /// </summary>\r
- /// <param name="fire">the fire method</param>\r
- public void AddFire(MethodDef fire) {\r
- AddMethod(fire,MethodType.Fire);\r
- }\r
-\r
- /// <summary>\r
- /// Add another method to this event\r
- /// </summary>\r
- /// <param name="other">the method to be added</param>\r
- public void AddOther(MethodDef other) {\r
- AddMethod(other,MethodType.Other);\r
- }\r
-\r
- internal sealed override void BuildTables(MetaData md) {\r
- if (done) return;\r
- nameIx = md.AddToStringsHeap(name);\r
- for (int i=0; i < tide; i++) {\r
- md.AddToTable(MDTable.MethodSemantics,methods[i]);\r
- }\r
- done = true;\r
- }\r
-\r
- internal sealed override uint Size(MetaData md) {\r
- return 2 + md.StringsIndexSize() + md.CodedIndexSize(CIx.TypeDefOrRef);\r
- }\r
-\r
- internal sealed override void Write(FileImage output) {\r
- output.Write(flags);\r
- output.StringsIndex(nameIx);\r
- output.WriteCodedIndex(CIx.TypeDefOrRef,eventType);\r
- }\r
-\r
- internal sealed override uint GetCodedIx(CIx code) {\r
- switch (code) {\r
- case (CIx.HasCustomAttr) : return 10; \r
- case (CIx.HasSemantics) : return 0; \r
- }\r
- return 0;\r
- }\r
- \r
- }\r
- /**************************************************************************/ \r
- /// <summary>\r
- /// Descriptor for a class defined in another module of THIS assembly \r
- /// and exported (.class extern)\r
- /// </summary>\r
-\r
- internal class ExternClass : Class\r
- {\r
- MetaDataElement parent;\r
- uint flags;\r
-\r
- internal ExternClass(TypeAttr attr, uint nsIx, uint nIx, \r
- MetaDataElement paren) : base(nsIx,nIx) {\r
- flags = (uint)attr;\r
- parent = paren;\r
- tabIx = MDTable.ExportedType;\r
- }\r
-\r
- internal sealed override uint Size(MetaData md) {\r
- return 8 + 2* md.StringsIndexSize() + md.CodedIndexSize(CIx.Implementation);\r
- }\r
-\r
- internal sealed override void Write(FileImage output) {\r
- output.Write(flags);\r
- output.Write(0);\r
- output.StringsIndex(nameIx);\r
- output.StringsIndex(nameSpaceIx);\r
- output.WriteCodedIndex(CIx.Implementation,parent);\r
- }\r
-\r
- internal sealed override uint GetCodedIx(CIx code) {\r
- switch (code) {\r
- case (CIx.HasCustomAttr) : return 17; \r
- case (CIx.Implementation) : return 2; \r
- }\r
- return 0;\r
- }\r
-\r
- }\r
- /**************************************************************************/ \r
- /// <summary>\r
- /// Base class for Event and Property descriptors\r
- /// </summary>\r
-\r
- public class Feature : MetaDataElement\r
- {\r
- internal enum MethodType : ushort { Setter = 0x01, Getter, Other = 0x04, AddOn = 0x08, \r
- RemoveOn = 0x10, Fire = 0x20 }\r
-\r
- private static readonly int INITSIZE = 5;\r
- private static readonly ushort specialName = 0x200;\r
- private static readonly ushort rtSpecialName = 0x400;\r
-\r
- protected ClassDef parent;\r
- protected ushort flags = 0;\r
- protected string name;\r
- protected int tide = 0;\r
- protected uint nameIx;\r
- protected MethodSemantics[] methods = new MethodSemantics[INITSIZE];\r
- \r
- internal Feature(string name, ClassDef par) {\r
- parent = par;\r
- this.name = name;\r
- }\r
-\r
- internal void AddMethod(MethodDef meth, MethodType mType) {\r
- if (tide >= methods.Length) { \r
- int len = methods.Length;\r
- MethodSemantics[] mTmp = methods;\r
- methods = new MethodSemantics[len * 2];\r
- for (int i=0; i < len; i++) {\r
- methods[i] = mTmp[i];\r
- }\r
- }\r
- methods[tide++] = new MethodSemantics(mType,meth,this);\r
- }\r
-\r
- /// <summary>\r
- /// Set the specialName attribute for this Event or Property\r
- /// </summary>\r
- public void SetSpecialName() {\r
- flags |= specialName;\r
- }\r
-\r
- /// <summary>\r
- /// Set the RTSpecialName attribute for this Event or Property\r
- /// </summary>\r
- public void SetRTSpecialName() {\r
- flags |= rtSpecialName;\r
- }\r
- \r
- }\r
- /*****************************************************************************/ \r
- /// <summary>\r
- /// Descriptor for a field of a class\r
- /// </summary>\r
-\r
- public abstract class Field : Member\r
- {\r
- protected static readonly byte FieldSig = 0x6;\r
-\r
- protected Type type;\r
-\r
- internal Field(string pfName, Type pfType) : base(pfName)\r
- {\r
- type = pfType;\r
- }\r
-\r
- }\r
- /**************************************************************************/ \r
- /// <summary>\r
- /// Descriptor for a field defined in a class of THIS assembly/module\r
- /// </summary>\r
- public class FieldDef : Field\r
- {\r
- //private static readonly uint PInvokeImpl = 0x2000;\r
- private static readonly ushort HasFieldMarshal = 0x1000;\r
- private static readonly ushort HasFieldRVA = 0x100;\r
- private static readonly ushort HasDefault = 0x8000;
-\r
- FieldRVA rva;\r
- ConstantElem constVal;\r
- FieldLayout layout;\r
- FieldMarshal marshalInfo;\r
- ushort flags;\r
-\r
- internal FieldDef(string name, Type fType) : base(name,fType) {\r
- tabIx = MDTable.Field;\r
- }\r
-\r
- internal FieldDef(FieldAttr attrSet, string name, Type fType) : base(name, fType) { \r
- flags = (ushort)attrSet;\r
- tabIx = MDTable.Field;\r
- }\r
-\r
- /// <summary>\r
- /// Add an attribute(s) to this field\r
- /// </summary>\r
- /// <param name="fa">the attribute(s) to be added</param>\r
- public void AddFieldAttr(FieldAttr fa) {\r
- flags |= (ushort)fa;\r
- }\r
- \r
- /// <summary>\r
- /// Add a value for this field\r
- /// </summary>\r
- /// <param name="val">the value for the field</param>\r
- public void AddValue(Constant val) {\r
- constVal = new ConstantElem(this,val);\r
- flags |= HasDefault;
- }\r
-\r
- /// <summary>\r
- /// Add an initial value for this field (at dataLabel) (.data)\r
- /// </summary>\r
- /// <param name="val">the value for the field</param>\r
- /// <param name="repeatVal">the number of repetitions of this value</param>\r
- public void AddDataValue(DataConstant val) {\r
- flags |= HasFieldRVA;\r
- rva = new FieldRVA(this,val);\r
- }\r
-\r
- /// <summary>\r
- /// Set the offset of the field. Used for sequential or explicit classes.\r
- /// (.field [offs])\r
- /// </summary>\r
- /// <param name="offs">field offset</param>\r
- public void SetOffset(uint offs) {\r
- layout = new FieldLayout(this,offs);\r
- }\r
-\r
- /// <summary>\r
- /// Set the marshalling info for a field\r
- /// </summary>\r
- /// <param name="mInf"></param>\r
- public void SetMarshalInfo(NativeType marshallType) {\r
- flags |= HasFieldMarshal;\r
- marshalInfo = new FieldMarshal(this,marshallType);\r
- }\r
-\r
- internal sealed override void BuildTables(MetaData md) {\r
- if (done) return;\r
- nameIx = md.AddToStringsHeap(name);\r
- MemoryStream sig = new MemoryStream();\r
- sig.WriteByte(FieldSig);\r
- type.TypeSig(sig);\r
- sigIx = md.AddToBlobHeap(sig.ToArray());\r
- if (rva != null) {\r
- md.AddToTable(MDTable.FieldRVA,rva);\r
- rva.BuildTables(md);\r
- } else if (constVal != null) {\r
- md.AddToTable(MDTable.Constant,constVal);\r
- constVal.BuildTables(md);\r
- }\r
- if (layout != null) md.AddToTable(MDTable.FieldLayout,layout);\r
- if (marshalInfo != null) {\r
- md.AddToTable(MDTable.FieldMarshal,marshalInfo);\r
- marshalInfo.BuildTables(md);\r
- }\r
- done = true;\r
- }\r
-\r
- internal sealed override uint Size(MetaData md) {\r
- return 2 + md.StringsIndexSize() + md.BlobIndexSize();\r
- }\r
-\r
- internal sealed override void Write(FileImage output) {\r
- output.Write(flags);\r
- output.StringsIndex(nameIx);\r
- output.BlobIndex(sigIx);\r
- }\r
-\r
- internal sealed override uint GetCodedIx(CIx code) {\r
- switch (code) {\r
- case (CIx.HasConst) : return 0; \r
- case (CIx.HasCustomAttr) : return 1; \r
- case (CIx.HasFieldMarshal) : return 0; \r
- case (CIx.MemberForwarded) : return 0; \r
- }\r
- return 0;\r
- }\r
-\r
- }\r
- /**************************************************************************/ \r
- /// <summary>\r
- /// Descriptor for layout information for a field\r
- /// </summary>\r
- \r
- public class FieldLayout : MetaDataElement\r
- {\r
- Field field;\r
- uint offset;\r
-\r
- internal FieldLayout(Field field, uint offset) {\r
- this.field = field;\r
- this.offset = offset;\r
- tabIx = MDTable.FieldLayout;\r
- }\r
-\r
- internal sealed override uint Size(MetaData md) {\r
- return 4 + md.TableIndexSize(MDTable.Field);\r
- }\r
-\r
- internal sealed override void Write(FileImage output) {\r
- output.Write(offset);\r
- output.WriteIndex(MDTable.Field,field.Row);\r
- }\r
-\r
- }\r
- /*****************************************************************************/ \r
- /// <summary>\r
- /// Marshalling information for a field or param\r
- /// </summary>\r
- public class FieldMarshal : MetaDataElement\r
- {\r
- MetaDataElement field;\r
- NativeType nt;\r
- uint ntIx;\r
-\r
- internal FieldMarshal(MetaDataElement field, NativeType nType) {\r
- this.field = field;\r
- this.nt = nType;\r
- tabIx = MDTable.FieldMarshal;\r
- }\r
-\r
- internal sealed override void BuildTables(MetaData md) {\r
- if (done) return;\r
- ntIx = md.AddToBlobHeap(nt.ToBlob());\r
- done = true;\r
- }\r
-\r
- internal sealed override uint Size(MetaData md) {\r
- return md.CodedIndexSize(CIx.HasFieldMarshal) + md.BlobIndexSize();\r
- }\r
-\r
- internal sealed override void Write(FileImage output) {\r
- output.WriteCodedIndex(CIx.HasFieldMarshal,field);\r
- output.BlobIndex(ntIx);\r
- }\r
-\r
- }\r
- /**************************************************************************/ \r
- /// <summary>\r
- /// Descriptor for a field of a class defined in another assembly/module\r
- /// </summary>\r
- public class FieldRef : Field\r
- {\r
- MetaDataElement parent;\r
-\r
- internal FieldRef(MetaDataElement paren, string name, Type fType) : base(name, fType) { \r
- parent = paren;\r
- }\r
-\r
- internal sealed override void BuildTables(MetaData md) {\r
- if (done) return;\r
- nameIx = md.AddToStringsHeap(name);\r
- MemoryStream sig = new MemoryStream();\r
- sig.WriteByte(FieldSig);\r
- type.TypeSig(sig);\r
- sigIx = md.AddToBlobHeap(sig.ToArray());\r
- done = true;\r
- }\r
-\r
- internal sealed override uint Size(MetaData md) {\r
- return md.CodedIndexSize(CIx.MemberRefParent) + md.StringsIndexSize() + md.BlobIndexSize();\r
- }\r
-\r
- internal sealed override void Write(FileImage output) {\r
- output.WriteCodedIndex(CIx.MemberRefParent,parent);\r
- output.StringsIndex(nameIx);\r
- output.BlobIndex(sigIx);\r
- }\r
-\r
- internal sealed override uint GetCodedIx(CIx code) { return 6; }\r
-\r
- }\r
- /**************************************************************************/ \r
- /// <summary>\r
- /// Descriptor for the address of a field's value in the PE file\r
- /// </summary>\r
- public class FieldRVA : MetaDataElement\r
- {\r
- Field field;\r
- DataConstant data;\r
-\r
- internal FieldRVA(Field field, DataConstant data) {\r
- this.field = field;\r
- this.data = data;\r
- tabIx = MDTable.FieldRVA;\r
- }\r
-\r
- internal sealed override void BuildTables(MetaData md) {\r
- if (done) return;\r
- md.AddData(data);\r
- done = true;\r
- }\r
-\r
- internal sealed override uint Size(MetaData md) {\r
- return 4 + md.TableIndexSize(MDTable.Field);\r
- }\r
-\r
- internal sealed override void Write(FileImage output) {\r
- output.WriteDataRVA(data.DataOffset);\r
- output.WriteIndex(MDTable.Field,field.Row);\r
- }\r
-\r
- }\r
- /**************************************************************************/ \r
- /// <summary>\r
- /// Image for a PEFile\r
- /// File Structure\r
- /// DOS Header (128 bytes) \r
- /// PE Signature ("PE\0\0") \r
- /// PEFileHeader (20 bytes)\r
- /// PEOptionalHeader (224 bytes) \r
- /// SectionHeaders (40 bytes * NumSections)\r
- ///\r
- /// Sections .text (always present - contains metadata)\r
- /// .sdata (contains any initialised data in the file - may not be present)\r
- /// (for ilams /debug this contains the Debug table)\r
- /// .reloc (always present - in pure CIL only has one fixup)\r
- /// others??? c# produces .rsrc section containing a Resource Table\r
- ///\r
- /// .text layout\r
- /// IAT (single entry 8 bytes for pure CIL)\r
- /// CLIHeader (72 bytes)\r
- /// CIL instructions for all methods (variable size)\r
- /// MetaData \r
- /// Root (20 bytes + UTF-8 Version String + quad align padding)\r
- /// StreamHeaders (8 bytes + null terminated name string + quad align padding)\r
- /// Streams \r
- /// #~ (always present - holds metadata tables)\r
- /// #Strings (always present - holds identifier strings)\r
- /// #US (Userstring heap)\r
- /// #Blob (signature blobs)\r
- /// #GUID (guids for assemblies or Modules)\r
- /// ImportTable (40 bytes)\r
- /// ImportLookupTable(8 bytes) (same as IAT for standard CIL files)\r
- /// Hint/Name Tables with entry "_CorExeMain" for .exe file and "_CorDllMain" for .dll (14 bytes)\r
- /// ASCII string "mscoree.dll" referenced in ImportTable (+ padding = 16 bytes)\r
- /// Entry Point (0xFF25 followed by 4 bytes 0x400000 + RVA of .text)\r
- ///\r
- /// #~ stream structure\r
- /// Header (24 bytes)\r
- /// Rows (4 bytes * numTables)\r
- /// Tables\r
- /// </summary>\r
- internal class FileImage : BinaryWriter\r
- {\r
- internal readonly static uint[] iByteMask = {0x000000FF, 0x0000FF00, 0x00FF0000, 0xFF000000};\r
- internal readonly static ulong[] lByteMask = {0x00000000000000FF, 0x000000000000FF00,\r
- 0x0000000000FF0000, 0x00000000FF000000,\r
- 0x000000FF00000000, 0x0000FF0000000000,\r
- 0x00FF000000000000, 0xFF00000000000000 };\r
- internal readonly static uint nibble0Mask = 0x0000000F;\r
- internal readonly static uint nibble1Mask = 0x000000F0;\r
-\r
- private static readonly byte[] DOSHeader = { 0x4d,0x5a,0x90,0x00,0x03,0x00,0x00,0x00,\r
- 0x04,0x00,0x00,0x00,0xff,0xff,0x00,0x00,\r
- 0xb8,0x00,0x00,0x00,0x00,0x00,0x00,0x00,\r
- 0x40,0x00,0x00,0x00,0x00,0x00,0x00,0x00,\r
- 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,\r
- 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,\r
- 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,\r
- 0x00,0x00,0x00,0x00,0x80,0x00,0x00,0x00,\r
- 0x0e,0x1f,0xba,0x0e,0x00,0xb4,0x09,0xcd,\r
- 0x21,0xb8,0x01,0x4c,0xcd,0x21,0x54,0x68,\r
- 0x69,0x73,0x20,0x70,0x72,0x6f,0x67,0x72,\r
- 0x61,0x6d,0x20,0x63,0x61,0x6e,0x6e,0x6f,\r
- 0x74,0x20,0x62,0x65,0x20,0x72,0x75,0x6e,\r
- 0x20,0x69,0x6e,0x20,0x44,0x4f,0x53,0x20,\r
- 0x6d,0x6f,0x64,0x65,0x2e,0x0d,0x0d,0x0a,\r
- 0x24,0x00,0x00,0x00,0x00,0x00,0x00,0x00,\r
- 0x50,0x45,0x00,0x00};\r
- private static byte[] PEHeader = { 0x4c, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \r
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\r
- 0xE0, 0x00, 0x0E, 0x01, // PE Header Standard Fields\r
- 0x0B, 0x01, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, \r
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \r
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00\r
- };\r
-\r
- private static readonly uint minFileAlign = 0x200;\r
- private static readonly uint maxFileAlign = 0x1000;\r
- private static readonly uint fileHeaderSize = 0x178;\r
- private static readonly uint sectionHeaderSize = 40;\r
- private static readonly uint SectionAlignment = 0x2000;\r
- private static readonly uint ImageBase = 0x400000;\r
- private static readonly uint ImportTableSize = 40;\r
- private static readonly uint IATSize = 8;\r
- private static readonly uint CLIHeaderSize = 72;\r
- private uint runtimeFlags = 0x01; // COMIMAGE_FLAGS_ILONLY\r
- // 32BITREQUIRED 0x02, STRONGNAMESIGNED 0x08, TRACKDEBUGDATA 0x10000\r
- private static readonly uint relocFlags = 0x42000040;\r
- private static readonly ushort exeCharacteristics = 0x010E;\r
- private static readonly ushort dllCharacteristics = 0x210E;\r
- // section names are all 8 bytes\r
- private static readonly string textName = ".text\0\0\0";\r
- private static readonly string sdataName = ".sdata\0\0";\r
- private static readonly string relocName = ".reloc\0\0";\r
- private static readonly string rsrcName = ".rsrc\0\0\0";\r
- private static readonly string exeHintNameTable = "\0\0_CorExeMain\0";\r
- private static readonly string dllHintNameTable = "\0\0_CorDllMain\0";\r
- private static readonly string runtimeEngineName = "mscoree.dll\0\0";\r
-\r
- private Section text, sdata, rsrc;\r
- ArrayList data;\r
- BinaryWriter reloc = new BinaryWriter(new MemoryStream());\r
- uint dateStamp = 0;\r
- DateTime origin = new DateTime(1970,1,1);\r
- uint numSections = 2; // always have .text and .reloc sections\r
- internal SubSystem subSys = SubSystem.Windows_CUI; // default is Windows Console mode\r
- internal uint fileAlign = minFileAlign;\r
- uint entryPointOffset, entryPointPadding, imageSize, headerSize, headerPadding, entryPointToken = 0;\r
- uint relocOffset, relocRVA, relocSize, relocPadding, relocTide, hintNameTableOffset;\r
- uint metaDataOffset, runtimeEngineOffset, initDataSize = 0, importTablePadding;\r
- uint importTableOffset, importLookupTableOffset, totalImportTableSize;\r
- MetaData metaData;\r
- char[] runtimeEngine = runtimeEngineName.ToCharArray(), hintNameTable;\r
- bool doDLL, largeStrings, largeGUID, largeUS, largeBlob;\r
- ushort characteristics;\r
-\r
- internal FileImage(bool makeDLL, string fileName) : base(new FileStream(fileName,FileMode.Create)) {\r
- InitFileImage(makeDLL);\r
- TimeSpan tmp = System.IO.File.GetCreationTime(fileName).Subtract(origin);\r
- dateStamp = Convert.ToUInt32(tmp.TotalSeconds);\r
- }\r
-\r
- internal FileImage(bool makeDLL, Stream str) : base(str) {\r
- InitFileImage(makeDLL);\r
- TimeSpan tmp = DateTime.Now.Subtract(origin);\r
- dateStamp = Convert.ToUInt32(tmp.TotalSeconds);\r
- }\r
-\r
- private void InitFileImage(bool makeDLL) {\r
- doDLL = makeDLL;\r
- if (doDLL) {\r
- hintNameTable = dllHintNameTable.ToCharArray();\r
- characteristics = dllCharacteristics;\r
- } else {\r
- hintNameTable = exeHintNameTable.ToCharArray();\r
- characteristics = exeCharacteristics;\r
- }\r
- text = new Section(textName,0x60000020); // IMAGE_SCN_CNT CODE, EXECUTE, READ\r
-// rsrc = new Section(rsrcName,0x40000040); // IMAGE_SCN_CNT INITIALIZED_DATA, READ\r
- metaData = new MetaData(this);\r
- }\r
-\r
- internal MetaData GetMetaData() {\r
- return metaData;\r
- }\r
-\r
- private uint GetNextSectStart(uint rva, uint tide) {\r
- if (tide < SectionAlignment) return rva + SectionAlignment;\r
- return rva + ((tide / SectionAlignment) + 1) * SectionAlignment;\r
- }\r
-\r
- private void BuildTextSection() {\r
- // .text layout\r
- // IAT (single entry 8 bytes for pure CIL)\r
- // CLIHeader (72 bytes)\r
- // CIL instructions for all methods (variable size)\r
- // MetaData \r
- // ImportTable (40 bytes)\r
- // ImportLookupTable(8 bytes) (same as IAT for standard CIL files)\r
- // Hint/Name Tables with entry "_CorExeMain" for .exe file and "_CorDllMain" for .dll (14 bytes)\r
- // ASCII string "mscoree.dll" referenced in ImportTable (+ padding = 16 bytes)\r
- // Entry Point (0xFF25 followed by 4 bytes 0x400000 + RVA of .text)\r
- metaData.BuildMetaData(IATSize + CLIHeaderSize);\r
- metaDataOffset = IATSize + CLIHeaderSize;\r
- // Console.WriteLine("Code starts at " + metaDataOffset);\r
- metaDataOffset += metaData.CodeSize();\r
- // resourcesStart =\r
- // strongNameSig = metaData.GetStrongNameSig();\r
- // fixUps = RVA for vtable\r
- importTableOffset = metaDataOffset + metaData.Size();\r
- importTablePadding = NumToAlign(importTableOffset,16);\r
- importTableOffset += importTablePadding;\r
- importLookupTableOffset = importTableOffset + ImportTableSize;\r
- hintNameTableOffset = importLookupTableOffset + IATSize;\r
- runtimeEngineOffset = hintNameTableOffset + (uint)hintNameTable.Length;\r
- entryPointOffset = runtimeEngineOffset + (uint)runtimeEngine.Length;\r
- totalImportTableSize = entryPointOffset - importTableOffset;\r
- // Console.WriteLine("total import table size = " + totalImportTableSize);\r
- // Console.WriteLine("entrypoint offset = " + entryPointOffset);\r
- entryPointPadding = NumToAlign(entryPointOffset,4) + 2;\r
- entryPointOffset += entryPointPadding;\r
- text.AddReloc(entryPointOffset+2);\r
- text.IncTide(entryPointOffset + 6);\r
- //if (text.Tide() < fileAlign) fileAlign = minFileAlign;\r
- text.SetSize(NumToAlign(text.Tide(),fileAlign));\r
- // Console.WriteLine("text size = " + text.Size() + " text tide = " + text.Tide() + " text padding = " + text.Padding());\r
- // Console.WriteLine("metaDataOffset = " + Hex.Int(metaDataOffset));\r
- // Console.WriteLine("importTableOffset = " + Hex.Int(importTableOffset));\r
- // Console.WriteLine("importLookupTableOffset = " + Hex.Int(importLookupTableOffset));\r
- // Console.WriteLine("hintNameTableOffset = " + Hex.Int(hintNameTableOffset));\r
- // Console.WriteLine("runtimeEngineOffset = " + Hex.Int(runtimeEngineOffset));\r
- // Console.WriteLine("entryPointOffset = " + Hex.Int(entryPointOffset));\r
- // Console.WriteLine("entryPointPadding = " + Hex.Int(entryPointPadding));\r
-\r
- }\r
-\r
- internal void BuildRelocSection() {\r
- text.DoRelocs(reloc);\r
- if (sdata != null) sdata.DoRelocs(reloc);\r
- if (rsrc != null) rsrc.DoRelocs(reloc);\r
- relocTide = (uint)reloc.Seek(0,SeekOrigin.Current);\r
- relocPadding = NumToAlign(relocTide,fileAlign);\r
- relocSize = relocTide + relocPadding;\r
- imageSize = relocRVA + SectionAlignment;\r
- initDataSize += relocSize;\r
- }\r
-\r
- private void CalcOffsets() {\r
-if (sdata != null)
- numSections++;
-if (rsrc != null)
- numSections++;
- headerSize = fileHeaderSize + (numSections * sectionHeaderSize);\r
- headerPadding = NumToAlign(headerSize,fileAlign);\r
- headerSize += headerPadding;\r
- uint offset = headerSize;\r
- uint rva = SectionAlignment;\r
- text.SetOffset(offset);\r
- text.SetRVA(rva);\r
- offset += text.Size();\r
- rva = GetNextSectStart(rva,text.Tide());\r
- // Console.WriteLine("headerSize = " + headerSize);\r
- // Console.WriteLine("headerPadding = " + headerPadding);\r
- // Console.WriteLine("textOffset = " + Hex.Int(text.Offset()));\r
- if (sdata != null) { \r
- sdata.SetSize(NumToAlign(sdata.Tide(),fileAlign));\r
- sdata.SetOffset(offset);\r
- sdata.SetRVA(rva);\r
- offset += sdata.Size();
- rva = GetNextSectStart(rva,sdata.Tide());\r
- initDataSize += sdata.Size();\r
- }\r
- if (rsrc != null) { \r
- rsrc.SetSize(NumToAlign(rsrc.Tide(),fileAlign));\r
- rsrc.SetOffset(offset);\r
- rsrc.SetRVA(rva);\r
- offset += rsrc.Size();\r
- rva = GetNextSectStart(rva,rsrc.Tide());\r
- initDataSize += rsrc.Size();\r
- }\r
- relocOffset = offset;\r
- relocRVA = rva;\r
- }\r
-\r
- internal void MakeFile() {\r
- if (doDLL) hintNameTable = dllHintNameTable.ToCharArray();\r
- else hintNameTable = exeHintNameTable.ToCharArray();\r
- BuildTextSection();\r
- CalcOffsets();\r
- BuildRelocSection();\r
- // now write it out\r
- WriteHeader();\r
- WriteSections();\r
- Flush();\r
- Close();\r
- }\r
-\r
- private void WriteHeader() {\r
- Write(DOSHeader);\r
- // Console.WriteLine("Writing PEHeader at offset " + Seek(0,SeekOrigin.Current));\r
- WritePEHeader();\r
- // Console.WriteLine("Writing text section header at offset " + Hex.Long(Seek(0,SeekOrigin.Current)));\r
- text.WriteHeader(this,relocRVA);\r
- if (sdata != null) sdata.WriteHeader(this,relocRVA);\r
- if (rsrc != null) rsrc.WriteHeader(this,relocRVA);\r
- // Console.WriteLine("Writing reloc section header at offset " + Seek(0,SeekOrigin.Current));\r
- WriteRelocSectionHeader();\r
- // Console.WriteLine("Writing padding at offset " + Seek(0,SeekOrigin.Current));\r
- WriteZeros(headerPadding);\r
- }\r
-\r
- private void WriteSections() {\r
- // Console.WriteLine("Writing text section at offset " + Seek(0,SeekOrigin.Current));\r
- WriteTextSection();\r
- if (sdata != null) WriteSDataSection();\r
- if (rsrc != null) WriteRsrcSection();\r
- WriteRelocSection();\r
- }\r
-\r
- private void WriteIAT() {\r
- Write(text.RVA() + hintNameTableOffset);\r
- Write(0);\r
- }\r
-\r
- private void WriteImportTables() {\r
- // Import Table\r
- WriteZeros(importTablePadding);\r
- // Console.WriteLine("Writing import tables at offset " + Hex.Long(Seek(0,SeekOrigin.Current)));\r
- Write(importLookupTableOffset + text.RVA());\r
- WriteZeros(8); \r
- Write(runtimeEngineOffset + text.RVA());\r
- Write(text.RVA()); // IAT is at the beginning of the text section\r
- WriteZeros(20);\r
- // Import Lookup Table\r
- WriteIAT(); // lookup table and IAT are the same\r
- // Hint/Name Table\r
- // Console.WriteLine("Writing hintname table at " + Hex.Long(Seek(0,SeekOrigin.Current)));\r
- Write(hintNameTable);\r
- Write(runtimeEngineName.ToCharArray());\r
- }\r
-\r
- private void WriteTextSection() {\r
- WriteIAT();\r
- WriteCLIHeader();\r
- // Console.WriteLine("Writing code at " + Hex.Long(Seek(0,SeekOrigin.Current)));\r
- metaData.WriteByteCodes(this);\r
- // Console.WriteLine("Finished writing code at " + Hex.Long(Seek(0,SeekOrigin.Current)));\r
- largeStrings = metaData.LargeStringsIndex();\r
- largeGUID = metaData.LargeGUIDIndex();\r
- largeUS = metaData.LargeUSIndex();\r
- largeBlob = metaData.LargeBlobIndex();\r
- metaData.WriteMetaData(this);\r
- WriteImportTables();\r
- WriteZeros(entryPointPadding);\r
- Write((ushort)0x25FF);\r
- Write(ImageBase + text.RVA());\r
- WriteZeros(text.Padding());\r
- }\r
-\r
- private void WriteCLIHeader() {\r
- Write(CLIHeaderSize); // Cb\r
- Write((short)2); // Major runtime version\r
- Write((short)0); // Minor runtime version\r
- Write(text.RVA() + metaDataOffset);\r
- Write(metaData.Size());\r
- Write(runtimeFlags);\r
- Write(entryPointToken);\r
- WriteZeros(8); // Resources - used by Manifest Resources NYI\r
- WriteZeros(8); // Strong Name stuff here!! NYI\r
- WriteZeros(8); // CodeManagerTable\r
- WriteZeros(8); // VTableFixups NYI\r
- WriteZeros(16); // ExportAddressTableJumps, ManagedNativeHeader\r
- }\r
-\r
- private void WriteSDataSection() {\r
- long size = sdata.Size ();
- long start = BaseStream.Position;
- for (int i=0; i < data.Count; i++) {\r
- ((DataConstant)data[i]).Write(this);\r
- }
- while (BaseStream.Position < (start + size))
- Write ((byte) 0);
- }\r
-\r
- private void WriteRsrcSection() {\r
- }\r
-\r
- private void WriteRelocSection() {\r
- // Console.WriteLine("Writing reloc section at " + Seek(0,SeekOrigin.Current) + " = " + relocOffset);\r
- MemoryStream str = (MemoryStream)reloc.BaseStream;\r
- Write(str.ToArray());\r
- WriteZeros(NumToAlign((uint)str.Position,fileAlign));\r
- }\r
-\r
- internal void SetEntryPoint(uint entryPoint) {\r
- entryPointToken = entryPoint;\r
- }\r
-\r
- internal void AddInitData(DataConstant cVal) {\r
- if (sdata == null) { \r
- sdata = new Section(sdataName,0xC0000040); // IMAGE_SCN_CNT INITIALIZED_DATA, READ, WRITE\r
- data = new ArrayList(); \r
- }\r
- data.Add(cVal);\r
- cVal.DataOffset = sdata.Tide();\r
- sdata.IncTide(cVal.GetSize());\r
- }\r
-\r
- internal void WriteZeros(uint numZeros) {\r
- for (int i=0; i < numZeros; i++) {\r
- Write((byte)0);\r
- }\r
- }\r
-\r
- internal void WritePEHeader() {\r
- Write((ushort)0x014C); // Machine - always 0x14C for Managed PE Files (allow others??)\r
- Write((ushort)numSections);\r
- Write(dateStamp);\r
- WriteZeros(8); // Pointer to Symbol Table and Number of Symbols (always zero for ECMA CLI files)\r
- Write((ushort)0x00E0); // Size of Optional Header\r
- Write(characteristics);\r
- // PE Optional Header\r
- Write((ushort)0x010B); // Magic\r
- Write((byte)0x6); // LMajor pure-IL = 6 C++ = 7\r
- Write((byte)0x0); // LMinor\r
- Write(text.Size());\r
- Write(initDataSize);\r
- Write(0); // Check other sections here!!\r
- Write(text.RVA() + entryPointOffset);\r
- Write(text.RVA());\r
- uint dataBase = 0;\r
- if (sdata != null) dataBase = sdata.RVA();\r
- else if (rsrc != null) dataBase = rsrc.RVA();\r
- else dataBase = relocRVA;\r
- Write(dataBase);\r
- Write(ImageBase);\r
- Write(SectionAlignment);\r
- Write(fileAlign);\r
- Write((ushort)0x04); // OS Major\r
- WriteZeros(6); // OS Minor, User Major, User Minor\r
- Write((ushort)0x04); // SubSys Major\r
- WriteZeros(6); // SybSys Minor, Reserved\r
- Write(imageSize);\r
- Write(headerSize);\r
- Write((int)0); // File Checksum\r
- Write((ushort)subSys);\r
- Write((short)0); // DLL Flags\r
- Write((uint)0x100000); // Stack Reserve Size\r
- Write((uint)0x1000); // Stack Commit Size\r
- Write((uint)0x100000); // Heap Reserve Size\r
- Write((uint)0x1000); // Heap Commit Size\r
- Write(0); // Loader Flags\r
- Write(0x10); // Number of Data Directories\r
- WriteZeros(8); // Export Table\r
- Write(importTableOffset + text.RVA());\r
- Write(totalImportTableSize);\r
- WriteZeros(24); // Resource, Exception and Certificate Tables\r
- Write(relocRVA);\r
- Write(relocTide);\r
- WriteZeros(48); // Debug, Copyright, Global Ptr, TLS, Load Config and Bound Import Tables\r
- Write(text.RVA()); // IATRVA - IAT is at start of .text Section\r
- Write(IATSize);\r
- WriteZeros(8); // Delay Import Descriptor\r
- Write(text.RVA()+IATSize); // CLIHeader immediately follows IAT\r
- Write(CLIHeaderSize); \r
- WriteZeros(8); // Reserved\r
- }\r
-\r
- internal void WriteRelocSectionHeader() {\r
- Write(relocName.ToCharArray());\r
- Write(relocTide);\r
- Write(relocRVA);\r
- Write(relocSize);\r
- Write(relocOffset);\r
- WriteZeros(12);\r
- Write(relocFlags);\r
- }\r
-\r
- private void Align (MemoryStream str, int val) {\r
- if ((str.Position % val) != 0) {\r
- for (int i=val - (int)(str.Position % val); i > 0; i--) {\r
- str.WriteByte(0);\r
- }\r
- }\r
- }\r
-\r
- private uint Align(uint val, uint alignVal) {\r
- if ((val % alignVal) != 0) {\r
- val += alignVal - (val % alignVal);\r
- }\r
- return val;\r
- }\r
-\r
- private uint NumToAlign(uint val, uint alignVal) {\r
- if ((val % alignVal) == 0) return 0;\r
- return alignVal - (val % alignVal);\r
- }\r
-\r
- internal void StringsIndex(uint ix) {\r
- if (largeStrings) Write(ix);\r
- else Write((ushort)ix);\r
- }\r
-\r
- internal void GUIDIndex(uint ix) {\r
- if (largeGUID) Write(ix);\r
- else Write((ushort)ix);\r
- }\r
-\r
- internal void USIndex(uint ix) {\r
- if (largeUS) Write(ix);\r
- else Write((ushort)ix);\r
- }\r
-\r
- internal void BlobIndex(uint ix) {\r
- if (largeBlob) Write(ix);\r
- else Write((ushort)ix);\r
- }\r
-\r
- internal void WriteIndex(MDTable tabIx,uint ix) {\r
- if (metaData.LargeIx(tabIx)) Write(ix);\r
- else Write((ushort)ix);\r
- }\r
-\r
- internal void WriteCodedIndex(CIx code, MetaDataElement elem) {\r
- metaData.WriteCodedIndex(code,elem,this);\r
- }\r
- \r
- internal void WriteCodeRVA(uint offs) {\r
- Write(text.RVA() + offs);\r
- }\r
-\r
- internal void WriteDataRVA(uint offs) {\r
- Write(sdata.RVA() + offs);\r
- }\r
-\r
- internal void Write3Bytes(uint val) {\r
- byte b3 = (byte)((val & FileImage.iByteMask[2]) >> 16);\r
- byte b2 = (byte)((val & FileImage.iByteMask[1]) >> 8);;\r
- byte b1 = (byte)(val & FileImage.iByteMask[0]);\r
- Write(b1);\r
- Write(b2);\r
- Write(b3);\r
- }\r
-\r
- }\r
- /**************************************************************************/ \r
- /// <summary>\r
- /// Descriptor for a file referenced in THIS assembly/module (.file)\r
- /// </summary>\r
- public class FileRef : MetaDataElement\r
- {\r
- private static readonly uint NoMetaData = 0x1;\r
- uint nameIx = 0, hashIx = 0;\r
- uint flags = 0;\r
-\r
- internal FileRef(string name, byte[] hashBytes, bool metaData,\r
- bool entryPoint, MetaData md) {\r
- if (!metaData) flags = NoMetaData;\r
- if (entryPoint) md.SetEntryPoint(this);\r
- nameIx = md.AddToStringsHeap(name);\r
- hashIx = md.AddToBlobHeap(hashBytes);\r
- tabIx = MDTable.File;\r
- }\r
-\r
- internal FileRef(uint nameIx, byte[] hashBytes, bool metaData,\r
- bool entryPoint, MetaData md) {\r
- if (!metaData) flags = NoMetaData;\r
- if (entryPoint) md.SetEntryPoint(this);\r
- this.nameIx = nameIx;\r
- hashIx = md.AddToBlobHeap(hashBytes);\r
- tabIx = MDTable.File;\r
- }\r
-\r
- internal sealed override uint Size(MetaData md) {\r
- return 4 + md.StringsIndexSize() + md.BlobIndexSize();\r
- }\r
-\r
- internal sealed override void Write(FileImage output) {\r
- output.Write(flags);\r
- output.StringsIndex(nameIx);\r
- output.BlobIndex(hashIx);\r
- }\r
-\r
- internal sealed override uint GetCodedIx(CIx code) {\r
- switch (code) {\r
- case (CIx.HasCustomAttr) : return 16; \r
- case (CIx.Implementation) : return 0;\r
- }\r
- return 0;\r
- }\r
-\r
- }\r
- /**************************************************************************/ \r
- /// <summary>\r
- /// Descriptor for pinvoke information for a method NOT YET IMPLEMENTED\r
- /// </summary>\r
- public class ImplMap : MetaDataElement\r
- {\r
- private static readonly ushort NoMangle = 0x01;\r
- ushort flags;\r
- Method meth;\r
- string importName;\r
- uint iNameIx;\r
- ModuleRef importScope;\r
-\r
- internal ImplMap(ushort flag, Method implMeth, string iName, ModuleRef mScope) {\r
- flags = flag;\r
- meth = implMeth;\r
- importName = iName;\r
- importScope = mScope;\r
- tabIx = MDTable.ImplMap;\r
- if (iName == null) flags |= NoMangle;\r
- //throw(new NotYetImplementedException("PInvoke "));\r
- }\r
-\r
- internal sealed override void BuildTables(MetaData md) {\r
- if (done) return;\r
- iNameIx = md.AddToStringsHeap(importName);\r
- done = true;\r
- }\r
-\r
- internal sealed override uint Size(MetaData md) {\r
- return 2+ md.CodedIndexSize(CIx.MemberForwarded) + \r
- md.StringsIndexSize() + md.TableIndexSize(MDTable.ModuleRef);\r
- }\r
-\r
- internal sealed override void Write(FileImage output) {\r
- output.Write(flags);\r
- output.WriteCodedIndex(CIx.MemberForwarded,meth);\r
- output.StringsIndex(iNameIx);\r
- output.WriteIndex(MDTable.ModuleRef,importScope.Row);\r
- }\r
-\r
- }\r
-\r
- /**************************************************************************/ \r
- /// <summary>\r
- /// Descriptor for an IL instruction\r
- /// </summary>\r
- internal abstract class CILInstruction {\r
- protected static readonly sbyte maxByteVal = 127;\r
- protected static readonly sbyte minByteVal = -128;\r
- protected static readonly byte leadByte = 0xFE;\r
- protected static readonly uint USHeapIndex = 0x70000000;\r
- protected static readonly int longInstrStart = (int)Op.arglist;\r
- public bool twoByteInstr = false;\r
- public uint size = 0;\r
- public uint offset;\r
-\r
- internal virtual bool Check(MetaData md) {\r
- return false;\r
- }\r
-\r
- internal virtual void Write(FileImage output) { }\r
-\r
- }\r
-\r
- internal class CILByte : CILInstruction {\r
- byte byteVal;\r
-\r
- internal CILByte(byte bVal) {\r
- byteVal = bVal;\r
- size = 1;\r
- }\r
-\r
- internal override void Write(FileImage output) {\r
- output.Write(byteVal);\r
- }\r
-\r
- }\r
-\r
- \r
- internal class Instr : CILInstruction {\r
- protected int instr;\r
-\r
- internal Instr(int inst) {\r
- if (inst >= longInstrStart) {\r
- instr = inst - longInstrStart;\r
- twoByteInstr = true;\r
- size = 2;\r
- } else {\r
- instr = inst;\r
- size = 1;\r
- }\r
- }\r
-\r
- internal override void Write(FileImage output) {\r
- //Console.WriteLine("Writing instruction " + instr + " with size " + size);\r
- if (twoByteInstr) output.Write(leadByte);\r
- output.Write((byte)instr);\r
- }\r
-\r
- }\r
-\r
- internal class IntInstr : Instr {\r
- int val;\r
- bool byteNum;\r
-\r
- internal IntInstr(int inst, int num, bool byteSize) : base(inst) {\r
- val = num;\r
- byteNum = byteSize;\r
- if (byteNum) size++;\r
- else size += 4;\r
- }\r
-\r
- internal sealed override void Write(FileImage output) {\r
- base.Write(output);\r
- if (byteNum) \r
- output.Write((sbyte)val);\r
- else \r
- output.Write(val); \r
- }\r
-\r
- }\r
-\r
- internal class UIntInstr : Instr {\r
- int val;\r
- bool byteNum;\r
-\r
- internal UIntInstr(int inst, int num, bool byteSize) : base(inst) {\r
- val = num;\r
- byteNum = byteSize;\r
- if (byteNum) size++;\r
- else size += 2;\r
- }\r
-\r
- internal sealed override void Write(FileImage output) {\r
- base.Write(output);\r
- if (byteNum)\r
- output.Write((byte)val);\r
- else\r
- output.Write((ushort)val); \r
- }\r
- \r
- }\r
-\r
- internal class LongInstr : Instr {\r
- long val;\r
-\r
- internal LongInstr(int inst, long l) : base(inst) {\r
- val = l;\r
- size += 8;\r
- }\r
-\r
- internal sealed override void Write(FileImage output) {\r
- base.Write(output);\r
- output.Write(val);\r
- }\r
-\r
- }\r
-\r
- internal class FloatInstr : Instr {\r
- float fVal;\r
-\r
- internal FloatInstr(int inst, float f) : base(inst) {\r
- fVal = f;\r
- size += 4;\r
- }\r
-\r
- internal sealed override void Write(FileImage output) {\r
- base.Write(output);\r
- output.Write(fVal);\r
- }\r
-\r
- }\r
-\r
- internal class DoubleInstr : Instr {\r
- double val;\r
-\r
- internal DoubleInstr(int inst, double d) : base(inst) {\r
- val = d;\r
- size += 8;\r
- }\r
-\r
- internal sealed override void Write(FileImage output) {\r
- base.Write(output);\r
- output.Write(val);\r
- }\r
-\r
- }\r
-\r
- internal class StringInstr : Instr {\r
- string val;
- byte[] bval;
- uint strIndex;\r
-\r
- internal StringInstr(int inst, string str) : base(inst) {\r
- val = str; \r
- size += 4;\r
- }
+ internal void AddInitData(DataConstant cVal)
+ {
+ if (sdata == null) {
+ sdata = new Section(sdataName,0xC0000040); // IMAGE_SCN_CNT INITIALIZED_DATA, READ, WRITE
+ data = new ArrayList();
+ }
+ data.Add(cVal);
+ cVal.DataOffset = sdata.Tide();
+ sdata.IncTide(cVal.GetSize());
+ }
- internal StringInstr (int inst, byte[] str) : base (inst) {
- bval = str;
- size += 4;
- }
-
- internal sealed override bool Check(MetaData md) {
- if (val != null)
- strIndex = md.AddToUSHeap(val);
- else
- strIndex = md.AddToUSHeap (bval);
- return false;\r
- }\r
-\r
- internal sealed override void Write(FileImage output) {\r
- base.Write(output);\r
- output.Write(USHeapIndex | strIndex);\r
- }\r
-\r
- }\r
-\r
- internal class LabelInstr : CILInstruction {\r
- CILLabel label;\r
-\r
- internal LabelInstr(CILLabel lab) {\r
- label = lab;\r
- label.AddLabelInstr(this);\r
- }\r
- }\r
-\r
- internal class FieldInstr : Instr {\r
- Field field;\r
-\r
- internal FieldInstr(int inst, Field f) : base(inst) {\r
- field = f;\r
- size += 4;\r
- }\r
-\r
- internal sealed override void Write(FileImage output) {\r
- base.Write(output);\r
- output.Write(field.Token());\r
- }\r
-\r
- }\r
-\r
- internal class MethInstr : Instr {\r
- Method meth;\r
-\r
- internal MethInstr(int inst, Method m) : base(inst) {\r
- meth = m;\r
- size += 4;\r
- }\r
-\r
- internal sealed override void Write(FileImage output) {\r
- base.Write(output);\r
- output.Write(meth.Token());\r
- }\r
-\r
- }\r
-\r
- internal class SigInstr : Instr {\r
- CalliSig signature;\r
-\r
- internal SigInstr(int inst, CalliSig sig) : base(inst) {\r
- signature = sig;\r
- size += 4;\r
- }\r
-\r
- internal sealed override bool Check(MetaData md) {\r
- md.AddToTable(MDTable.StandAloneSig,signature);\r
- signature.BuildTables(md);\r
- return false;\r
- }\r
-\r
- internal sealed override void Write(FileImage output) {\r
- base.Write(output);\r
- output.Write(signature.Token());\r
- }\r
- }\r
-\r
- internal class TypeInstr : Instr {\r
- MetaDataElement theType;\r
-\r
- internal TypeInstr(int inst, Type aType, MetaData md) : base(inst) {\r
- theType = aType.GetTypeSpec(md);\r
- size += 4;\r
- }\r
-\r
- internal sealed override void Write(FileImage output) {\r
- base.Write(output);\r
- output.Write(theType.Token());\r
- }\r
-\r
- }\r
-\r
- internal class BranchInstr : Instr {\r
- CILLabel dest;\r
- private bool shortVer = true;\r
- private static readonly byte longInstrOffset = 13;\r
- private int target = 0;\r
-\r
- internal BranchInstr(int inst, CILLabel dst) : base(inst) {\r
- dest = dst;\r
- dest.AddBranch(this);\r
- size++;\r
+ internal void WriteZeros(uint numZeros)
+ {
+ for (int i=0; i < numZeros; i++) {
+ Write((byte)0);
+ }
+ }
- if (inst >= (int) BranchOp.br && inst != (int) BranchOp.leave_s) {
- shortVer = false;
- size += 3;
- }
- }\r
-\r
- internal sealed override bool Check(MetaData md) {\r
- target = (int)dest.GetLabelOffset() - (int)(offset + size);\r
- return false;
- }\r
+ internal void WritePEHeader()
+ {
+ Write((ushort)0x014C); // Machine - always 0x14C for Managed PE Files (allow others??)
+ Write((ushort)numSections);
+ Write(dateStamp);
+ WriteZeros(8); // Pointer to Symbol Table and Number of Symbols (always zero for ECMA CLI files)
+ Write((ushort)0x00E0); // Size of Optional Header
+ Write(characteristics);
+ // PE Optional Header
+ Write((ushort)0x010B); // Magic
+ Write((byte)0x6); // LMajor pure-IL = 6 C++ = 7
+ Write((byte)0x0); // LMinor
+ Write(text.Size());
+ Write(initDataSize);
+ Write(0); // Check other sections here!!
+ Write(text.RVA() + entryPointOffset);
+ Write(text.RVA());
+ uint dataBase = 0;
+ if (sdata != null) dataBase = sdata.RVA();
+ else if (rsrc != null) dataBase = rsrc.RVA();
+ else dataBase = relocRVA;
+ Write(dataBase);
+ Write(ImageBase);
+ Write(SectionAlignment);
+ Write(fileAlign);
+ Write((ushort)0x04); // OS Major
+ WriteZeros(6); // OS Minor, User Major, User Minor
+ Write((ushort)0x04); // SubSys Major
+ WriteZeros(6); // SybSys Minor, Reserved
+ Write(imageSize);
+ Write(headerSize);
+ Write((int)0); // File Checksum
+ Write((ushort)subSys);
+ Write((short)0); // DLL Flags
+ Write((uint)stackReserve); // Stack Reserve Size
+ Write((uint)0x1000); // Stack Commit Size
+ Write((uint)0x100000); // Heap Reserve Size
+ Write((uint)0x1000); // Heap Commit Size
+ Write(0); // Loader Flags
+ Write(0x10); // Number of Data Directories
+ WriteZeros(8); // Export Table
+ Write(importTableOffset + text.RVA());
+ Write(totalImportTableSize);
+ WriteZeros(24); // Resource, Exception and Certificate Tables
+ Write(relocRVA);
+ Write(relocTide);
+ WriteZeros(48); // Debug, Copyright, Global Ptr, TLS, Load Config and Bound Import Tables
+ Write(text.RVA()); // IATRVA - IAT is at start of .text Section
+ Write(IATSize);
+ WriteZeros(8); // Delay Import Descriptor
+ Write(text.RVA()+IATSize); // CLIHeader immediately follows IAT
+ Write(CLIHeaderSize);
+ WriteZeros(8); // Reserved
+ }
- internal sealed override void Write(FileImage output) {\r
- base.Write(output);\r
- if (shortVer)\r
- output.Write((sbyte)target);\r
- else\r
- output.Write(target);\r
- }\r
-\r
- }\r
-\r
- internal class SwitchInstr : Instr {\r
- CILLabel[] cases;\r
- uint numCases = 0;\r
-\r
- internal SwitchInstr(int inst, CILLabel[] dsts) : base(inst) {\r
- cases = dsts;\r
- if (cases != null) numCases = (uint)cases.Length;\r
- size += 4 + (numCases * 4);\r
- for (int i=0; i < numCases; i++) {\r
- cases[i].AddBranch(this);\r
- }\r
- }\r
-\r
- internal sealed override void Write(FileImage output) {\r
- base.Write(output);\r
- output.Write(numCases);\r
- for (int i=0; i < numCases; i++) {\r
- int target = (int)cases[i].GetLabelOffset() - (int)(offset + size);\r
- output.Write(target);\r
- }\r
- }\r
-\r
- }\r
- /**************************************************************************/ \r
-\r
- public class GenericParameter : MetaDataElement\r
- {\r
- MetaDataElement owner;
- MetaData metadata;
- string name;\r
- uint nameIx;\r
- short index;\r
-\r
- internal GenericParameter (ClassDef owner, MetaData metadata,
- short index, string name) : this (owner, metadata, index, name, true)
- {
- }
-\r
- internal GenericParameter (MethodDef owner, MetaData metadata,
- short index, string name) : this (owner, metadata, index, name, true)
- {
- }
+ internal void WriteRelocSectionHeader()
+ {
+ Write(relocName.ToCharArray());
+ Write(relocTide);
+ Write(relocRVA);
+ Write(relocSize);
+ Write(relocOffset);
+ WriteZeros(12);
+ Write(relocFlags);
+ }
- private GenericParameter (MetaDataElement owner, MetaData metadata,
- short index, string name, bool nadda)
- {
- this.owner = owner;\r
- this.metadata = metadata;
- this.index = index;\r
- tabIx = MDTable.GenericParam;\r
- this.name = name;\r
- }
+ private void Align (MemoryStream str, int val)
+ {
+ if ((str.Position % val) != 0) {
+ for (int i=val - (int)(str.Position % val); i > 0; i--) {
+ str.WriteByte(0);
+ }
+ }
+ }
- public void AddConstraint (Type constraint) {
- metadata.AddToTable (MDTable.GenericParamConstraint,\r
- new GenericParamConstraint (this, constraint));\r
- }
+ private uint Align(uint val, uint alignVal)
+ {
+ if ((val % alignVal) != 0) {
+ val += alignVal - (val % alignVal);
+ }
+ return val;
+ }
- internal sealed override uint Size(MetaData md) {\r
- return (uint) (4 +\r
- md.CodedIndexSize(CIx.TypeOrMethodDef) + \r
- 4 +\r
- md.TableIndexSize(MDTable.TypeDef));\r
- }\r
-\r
- internal sealed override void BuildTables(MetaData md) {\r
- if (done) return;\r
- nameIx = md.AddToStringsHeap(name);\r
- done = true;\r
- }\r
-\r
- internal sealed override void Write(FileImage output) {\r
- output.Write ((short) index);\r
- output.Write ((short) 0);\r
- output.WriteCodedIndex(CIx.TypeOrMethodDef, owner);\r
- output.Write ((uint) nameIx);\r
- output.WriteIndex(MDTable.TypeDef,owner.Row);\r
- }\r
-\r
- \r
- }\r
-\r
- internal class GenericParamConstraint : MetaDataElement\r
- {\r
- GenericParameter param;\r
- Type type;\r
-\r
- public GenericParamConstraint (GenericParameter param, Type type) {\r
- this.param = param;\r
- this.type = type;\r
- tabIx = MDTable.GenericParamConstraint;\r
- }\r
-\r
- internal sealed override uint Size(MetaData md) {\r
- return (uint) (md.TableIndexSize(MDTable.GenericParam) +\r
- md.CodedIndexSize(CIx.TypeDefOrRef));\r
- }\r
-\r
- internal sealed override void Write(FileImage output) {\r
- output.WriteIndex(MDTable.GenericParam, param.Row);\r
- output.WriteCodedIndex(CIx.TypeDefOrRef, type);\r
- }\r
-\r
-\r
- }\r
+ private uint NumToAlign(uint val, uint alignVal)
+ {
+ if ((val % alignVal) == 0) return 0;
+ return alignVal - (val % alignVal);
+ }
- internal class MethodSpec : MetaDataElement
- {
- Method meth;
- GenericMethodSig g_sig;
- uint sidx;
+ internal void StringsIndex(uint ix)
+ {
+ if (largeStrings) Write(ix);
+ else Write((ushort)ix);
+ }
- internal MethodSpec (Method meth, GenericMethodSig g_sig) {
- this.meth = meth;
- this.g_sig = g_sig;
- tabIx = MDTable.MethodSpec;
- }
+ internal void GUIDIndex(uint ix)
+ {
+ if (largeGUID) Write(ix);
+ else Write((ushort)ix);
+ }
- internal sealed override void BuildTables (MetaData md) {
- if (done) return;
- sidx = g_sig.GetSigIx (md);
- done = true;
- }
+ internal void USIndex(uint ix)
+ {
+ if (largeUS) Write(ix);
+ else Write((ushort)ix);
+ }
- internal sealed override uint Size (MetaData md) {
- return (uint) (md.CodedIndexSize(CIx.MethodDefOrRef) +
- md.BlobIndexSize ());
- }
+ internal void BlobIndex(uint ix)
+ {
+ if (largeBlob) Write(ix);
+ else Write((ushort)ix);
+ }
- internal sealed override void Write (FileImage output) {
- output.WriteCodedIndex (CIx.MethodDefOrRef, meth);
- output.BlobIndex (sidx);\r
- }
- }
+ internal void WriteIndex(MDTable tabIx,uint ix)
+ {
+ if (metaData.LargeIx(tabIx)) Write(ix);
+ else Write((ushort)ix);
+ }
- /**************************************************************************/\r
- /// <summary>\r
- /// Descriptor for interface implemented by a class\r
- /// </summary>\r
- public class InterfaceImpl: MetaDataElement\r
- { \r
- ClassDef theClass;\r
- Class theInterface;\r
-\r
- internal InterfaceImpl(ClassDef theClass, Class theInterface) {\r
- this.theClass = theClass;\r
- this.theInterface = theInterface;\r
- tabIx = MDTable.InterfaceImpl;\r
- }\r
-\r
- internal sealed override uint Size(MetaData md) {\r
- return md.TableIndexSize(MDTable.TypeDef) + \r
- md.CodedIndexSize(CIx.TypeDefOrRef);\r
- }\r
-\r
- internal sealed override void Write(FileImage output) {\r
- output.WriteIndex(MDTable.TypeDef,theClass.Row);\r
- output.WriteCodedIndex(CIx.TypeDefOrRef,theInterface);\r
- }\r
-\r
- internal sealed override uint GetCodedIx(CIx code) { return 5; }\r
-\r
- }\r
- /**************************************************************************/ \r
- /// <summary>\r
- /// Descriptor for a local of a method\r
- /// </summary>\r
- public class Local\r
- {\r
- private static readonly byte Pinned = 0x45;\r
- string name;\r
- Type type;\r
- bool pinned = false, byref = false;\r
-\r
- /// <summary>\r
- /// Create a new local variable \r
- /// </summary>\r
- /// <param name="lName">name of the local variable</param>\r
- /// <param name="lType">type of the local variable</param>\r
- public Local(string lName, Type lType) {\r
- name = lName;\r
- type = lType;\r
- }\r
-\r
- /// <summary>\r
- /// Create a new local variable that is byref and/or pinned\r
- /// </summary>\r
- /// <param name="lName">local name</param>\r
- /// <param name="lType">local type</param>\r
- /// <param name="byRef">is byref</param>\r
- /// <param name="isPinned">has pinned attribute</param>\r
- public Local(string lName, Type lType, bool byRef, bool isPinned)\r
- {\r
- name = lName;\r
- type = lType;\r
- byref = byRef;\r
- pinned = isPinned;\r
- }\r
-\r
- internal void TypeSig(MemoryStream str) {\r
- if (pinned) str.WriteByte(Pinned);\r
- type.TypeSig(str);\r
- }\r
-\r
- }\r
- /**************************************************************************/ \r
- /// <summary>\r
- /// Descriptor for the locals for a method\r
- /// </summary>\r
-\r
- public class LocalSig : Signature\r
- {\r
- private static readonly byte LocalSigByte = 0x7;\r
- Local[] locals;\r
-\r
- public LocalSig(Local[] locals) {\r
- this.locals = locals;\r
- tabIx = MDTable.StandAloneSig;\r
- }\r
-\r
- internal sealed override void BuildTables(MetaData md) {\r
- if (done) return;\r
- MemoryStream sig = new MemoryStream();\r
- sig.WriteByte(LocalSigByte);\r
- MetaData.CompressNum((uint)locals.Length,sig);\r
- for (int i=0; i < locals.Length; i++) {\r
- ((Local)locals[i]).TypeSig(sig);\r
- }\r
- sigIx = md.AddToBlobHeap(sig.ToArray());\r
- done = true;\r
- }\r
-\r
- }\r
-\r
- /**************************************************************************/ \r
- /// <summary>\r
- /// Descriptor for resources used in this PE file NOT YET IMPLEMENTED\r
- /// </summary>\r
-\r
- public class ManifestResource : MetaDataElement\r
- {\r
- private static readonly uint PublicResource = 0x1;\r
- private static readonly uint PrivateResource = 0x2;\r
-\r
- string mrName;\r
- MetaDataElement rRef;\r
- int fileOffset;\r
- uint nameIx = 0;\r
- uint flags = 0;\r
-\r
- public ManifestResource(string name, bool isPub, FileRef fileRef) {\r
- mrName = name;\r
- if (isPub) flags = PublicResource;\r
- else flags = PrivateResource;\r
- rRef = fileRef;\r
- tabIx = MDTable.ManifestResource;\r
- throw(new NotYetImplementedException("Manifest Resources "));\r
- }\r
-\r
- public ManifestResource(string name, bool isPub, FileRef fileRef, \r
- int fileIx) {\r
- mrName = name;\r
- if (isPub) flags = PublicResource;\r
- else flags = PrivateResource;\r
- rRef = fileRef;\r
- fileOffset = fileIx;\r
- }\r
-\r
- public ManifestResource(string name, bool isPub, AssemblyRef assemRef) {\r
- mrName = name;\r
- if (isPub) flags = PublicResource;\r
- else flags = PrivateResource;\r
- rRef = assemRef;\r
- }\r
-\r
- internal sealed override void BuildTables(MetaData md) {\r
- if (done) return;\r
- nameIx = md.AddToStringsHeap(mrName);\r
- done = true;\r
- }\r
-\r
- internal sealed override uint Size(MetaData md) {\r
- return 8 + md.StringsIndexSize() + \r
- md.CodedIndexSize(CIx.Implementation);\r
- }\r
-\r
- internal sealed override void Write(FileImage output) {\r
- output.Write(fileOffset);\r
- output.Write(flags);\r
- output.StringsIndex(nameIx);\r
- output.WriteCodedIndex(CIx.Implementation,rRef);\r
- }\r
-\r
- internal sealed override uint GetCodedIx(CIx code) { return 18; }\r
-\r
- }\r
- /**************************************************************************/ \r
- /// <summary>\r
- /// Base class for elements in the PropertyMap, EventMap and \r
- /// NestedClass MetaData tables\r
- /// </summary>\r
- public class MapElem : MetaDataElement\r
- {\r
- ClassDef parent;\r
- uint elemIx;\r
- MDTable elemTable;\r
-\r
- internal MapElem(ClassDef par, uint elIx, MDTable elemTab) {\r
- parent = par;\r
- elemIx = elIx;\r
- elemTable = elemTab;\r
- }\r
-\r
- internal sealed override uint Size(MetaData md) {\r
- return md.TableIndexSize(MDTable.TypeDef) + md.TableIndexSize(elemTable);\r
- }\r
-\r
- internal sealed override void Write(FileImage output) {\r
- output.WriteIndex(MDTable.TypeDef,parent.Row);\r
- output.WriteIndex(elemTable,elemIx);\r
- }\r
- }\r
- /**************************************************************************/ \r
- /// <summary>\r
- /// Base class for field/methods (member of a class)\r
- /// </summary>\r
- public abstract class Member : MetaDataElement\r
- {\r
- protected string name;\r
- protected uint nameIx = 0, sigIx = 0;\r
- \r
- internal Member(string memName)\r
- {\r
- name = memName;\r
- tabIx = MDTable.MemberRef;\r
- }\r
-\r
- }\r
- /**************************************************************************/ \r
- /// <summary>\r
- /// MetaData \r
- /// Root (20 bytes + UTF-8 Version String + quad align padding)\r
- /// StreamHeaders (8 bytes + null terminated name string + quad align padding)\r
- /// Streams \r
- /// #~ (always present - holds metadata tables)\r
- /// #Strings (always present - holds identifier strings)\r
- /// #US (Userstring heap)\r
- /// #Blob (signature blobs)\r
- /// #GUID (guids for assemblies or Modules)\r
- /// </summary>\r
-\r
- public class MetaData \r
- {\r
- private static readonly int[] CIxShiftMap = {2,2,5,1,2,3,1,1,1,2,3,2,1};\r
- private static readonly byte StringsHeapMask = 0x1;\r
- private static readonly byte GUIDHeapMask = 0x2;\r
- private static readonly byte BlobHeapMask = 0x4;\r
- private static readonly uint MetaDataSignature = 0x424A5342;\r
- private static readonly uint maxSmlIxSize = 0xFFFF;\r
- private static readonly uint max1BitSmlIx = 0x7FFF;\r
- private static readonly uint max2BitSmlIx = 0x3FFF;\r
- private static readonly uint max3BitSmlIx = 0x1FFF;\r
- private static readonly uint max5BitSmlIx = 0x7FF;\r
- // NOTE: version and stream name strings MUST always be quad padded\r
- private static readonly string version = "v1.0.3705\0\0\0";\r
- private static readonly char[] tildeName = {'#','~','\0','\0'};\r
- private static readonly char[] stringsName = {'#','S','t','r','i','n','g','s','\0','\0','\0','\0'};\r
- private static readonly char[] usName = {'#','U','S','\0'};\r
- private static readonly char[] guidName = {'#','G','U','I','D','\0','\0','\0'};\r
- private static readonly char[] blobName = {'#','B','l','o','b','\0','\0','\0'};\r
- private static readonly uint MetaDataHeaderSize = 20 + (uint)version.Length;\r
- private static readonly uint TildeHeaderSize = 24;\r
- private static readonly uint StreamHeaderSize = 8;\r
- private static readonly uint numMetaDataTables = (int)MDTable.GenericParamConstraint + 1;\r
- private static readonly uint tildeHeaderSize = 8 + (uint)tildeName.Length;\r
-\r
- MetaDataStream strings, us, guid, blob;\r
-\r
- MetaDataStream[] streams = new MetaDataStream[5];\r
- uint numStreams = 5;\r
- uint tildeTide = 0, tildePadding = 0, tildeStart = 0;\r
- uint numTables = 0;\r
- ArrayList[] metaDataTables = new ArrayList[numMetaDataTables];\r
- ArrayList byteCodes = new ArrayList();\r
- uint codeSize = 0, codeStart, byteCodePadding = 0, metaDataSize = 0;\r
- ulong valid = 0, /*sorted = 0x000002003301FA00;*/ sorted = 0;\r
- bool[] largeIx = new bool[numMetaDataTables];\r
- bool[] lgeCIx = new bool[(int)CIx.MaxCIx];\r
- bool largeStrings = false, largeUS = false, largeGUID = false, largeBlob = false;\r
- private FileImage file;\r
- private byte heapSizes = 0;\r
- MetaDataElement entryPoint;\r
- BinaryWriter output;\r
- public MSCorLib mscorlib;\r
- private TypeSpec[] systemTypeSpecs = new TypeSpec[PrimitiveType.NumSystemTypes];\r
- long mdStart;\r
- private ArrayList cattr_list;
-
- internal MetaData(FileImage file) {\r
- // tilde = new MetaDataStream(tildeName,false,0);\r
- this.file = file;\r
- strings = new MetaDataStream(stringsName,new UTF8Encoding(),true);\r
- us = new MetaDataStream(usName,new UnicodeEncoding(),true);\r
- guid = new MetaDataStream(guidName,false);\r
- blob = new MetaDataStream(blobName,true);\r
- streams[1] = strings;\r
- streams[2] = us;\r
- streams[3] = guid;\r
- streams[4] = blob;\r
- for (int i=0; i < numMetaDataTables; i++) {\r
- largeIx[i] = false;\r
- }\r
- for (int i=0; i < lgeCIx.Length; i++) {\r
- lgeCIx[i] = false;\r
- }\r
- mscorlib = new MSCorLib(this);\r
- }\r
- \r
- internal TypeSpec GetPrimitiveTypeSpec(int ix) {\r
- return systemTypeSpecs[ix];\r
- }\r
-\r
- internal void SetPrimitiveTypeSpec(int ix, TypeSpec typeSpec) {\r
- systemTypeSpecs[ix] = typeSpec;\r
- }\r
-\r
- internal uint Size() {\r
- return metaDataSize;\r
- }\r
+ internal void WriteCodedIndex(CIx code, MetaDataElement elem)
+ {
+ metaData.WriteCodedIndex(code,elem,this);
+ }
-
- private void CalcHeapSizes ()
- {
- if (strings.LargeIx()) {\r
- largeStrings = true;\r
- heapSizes |= StringsHeapMask;\r
- }\r
- if (guid.LargeIx()) {\r
- largeGUID = true;\r
- heapSizes |= GUIDHeapMask;\r
- }\r
- if (blob.LargeIx()) {\r
- largeBlob = true;\r
- heapSizes |= BlobHeapMask;\r
- }\r
+ internal void WriteCodeRVA(uint offs)
+ {
+ Write(text.RVA() + offs);
+ }
- largeUS = us.LargeIx();\r
- }
+ internal void WriteDataRVA(uint offs)
+ {
+ Write(sdata.RVA() + offs);
+ }
- internal void StreamSize(byte mask) {\r
- heapSizes |= mask;\r
- }\r
-\r
- internal uint AddToUSHeap(string str) {\r
- if (str == null) return 0;\r
- return us.Add(str,true);\r
- }
+ internal void Write3Bytes(uint val)
+ {
+ byte b3 = (byte)((val & FileImage.iByteMask[2]) >> 16);
+ byte b2 = (byte)((val & FileImage.iByteMask[1]) >> 8);;
+ byte b1 = (byte)(val & FileImage.iByteMask[0]);
+ Write(b1);
+ Write(b2);
+ Write(b3);
+ }
- internal uint AddToUSHeap(byte[] str) {
- if (str == null) return 0;
- return us.Add (str, true);
- }
-
- internal uint AddToStringsHeap(string str) {\r
- if ((str == null) || (str.CompareTo("") == 0)) return 0;\r
- return strings.Add(str,false);\r
- }\r
-\r
- internal uint AddToGUIDHeap(Guid guidNum) {\r
- return guid.Add(guidNum, false);\r
- }\r
-\r
- internal uint AddToBlobHeap(byte[] blobBytes) {\r
- if (blobBytes == null) return 0;\r
- return blob.Add(blobBytes, true);\r
- }\r
-\r
- internal uint AddToBlobHeap(byte val) {\r
- return blob.Add(val, true);\r
- }\r
-\r
- internal uint AddToBlobHeap(sbyte val) {\r
- return blob.Add(val, true);\r
- }\r
-\r
- internal uint AddToBlobHeap(ushort val) {\r
- return blob.Add(val, true);\r
- }\r
-\r
- internal uint AddToBlobHeap(short val) {\r
- return blob.Add(val, true);\r
- }\r
-\r
- internal uint AddToBlobHeap(uint val) {\r
- return blob.Add(val, true);\r
- }\r
-\r
- internal uint AddToBlobHeap(int val) {\r
- return blob.Add(val, true);\r
- }\r
-\r
- internal uint AddToBlobHeap(ulong val) {\r
- return blob.Add(val, true);\r
- }\r
-\r
- internal uint AddToBlobHeap(long val) {\r
- return blob.Add(val, true);\r
- }\r
-\r
- internal uint AddToBlobHeap(float val) {\r
- return blob.Add(val, true);\r
- }\r
-\r
- internal uint AddToBlobHeap(double val) {\r
- return blob.Add(val, true);\r
- }\r
-\r
- internal uint AddToBlobHeap(string val) {\r
- return blob.Add(val,true);\r
- }\r
-\r
- internal void AddCustomAttribute (CustomAttribute cattr)
- {
- if (cattr_list == null)
- cattr_list = new ArrayList ();
- cattr_list.Add (cattr);
- }
+ internal bool ReserveStrongNameSignatureSpace {
+ get { return reserveStrongNameSignatureSpace; }
+ set { reserveStrongNameSignatureSpace = value; }
+ }
- private ArrayList GetTable(MDTable tableIx) {\r
- int tabIx = (int)tableIx;\r
- if (metaDataTables[tabIx] == null) {\r
- metaDataTables[tabIx] = new ArrayList();\r
- valid |= ((ulong)0x1 << tabIx);\r
- // Console.WriteLine("after creating table " + tableIx + "(" + tabIx + ") valid = " + valid);\r
- numTables++;\r
- }\r
- return metaDataTables[tabIx];\r
- }\r
- \r
- internal void AddToTable(MDTable tableIx, MetaDataElement elem) {\r
- if (elem.Row > 0) {\r
- // Console.Out.WriteLine("ERROR - element already in table " + tableIx);\r
- return;\r
- }\r
- // updates Row field of the element\r
- // Console.WriteLine("Adding element to table " + (uint)tableIx);\r
- ArrayList table = GetTable(tableIx);\r
- elem.Row = (uint)table.Count + 1;\r
- table.Add(elem);\r
- }\r
-\r
- internal uint TableIndex(MDTable tableIx) {\r
- if (metaDataTables[(int)tableIx] == null) return 1;\r
- return (uint)metaDataTables[(int)tableIx].Count+1;\r
- }\r
-\r
- internal uint AddCode(CILInstructions byteCode) {\r
- byteCodes.Add(byteCode);\r
- uint offset = codeSize + codeStart;\r
- codeSize += byteCode.GetCodeSize();\r
- return offset;\r
- }\r
-\r
- internal void SetEntryPoint(MetaDataElement ep) {\r
- entryPoint = ep;\r
- }\r
-\r
- internal void AddData(DataConstant cVal) {\r
- file.AddInitData(cVal);\r
- }\r
-\r
- internal static void CompressNum(uint val, MemoryStream sig) {\r
- if (val < 0x7F) {\r
- sig.WriteByte((byte)val);\r
- } else if (val < 0x3FFF) {\r
- byte b1 = (byte)((val >> 8) | 0x80);\r
- byte b2 = (byte)(val & FileImage.iByteMask[0]);\r
- sig.WriteByte(b1);\r
- sig.WriteByte(b2);\r
- } else {\r
- byte b1 = (byte)((val >> 24) | 0xC0);\r
- byte b2 = (byte)((val & FileImage.iByteMask[2]) >> 16);\r
- byte b3 = (byte)((val & FileImage.iByteMask[1]) >> 8);;\r
- byte b4 = (byte)(val & FileImage.iByteMask[0]);\r
- sig.WriteByte(b1);\r
- sig.WriteByte(b2);\r
- sig.WriteByte(b3);\r
- sig.WriteByte(b4);\r
- }\r
- }\r
-\r
- internal uint CodeSize() {\r
- return codeSize + byteCodePadding;\r
- }\r
-\r
- internal uint StringsIndexSize() {\r
- if (largeStrings) return 4;\r
- return 2;\r
- }\r
-\r
- internal uint GUIDIndexSize() {\r
- if (largeGUID) return 4;\r
- return 2;\r
- }\r
-\r
- internal uint USIndexSize() {\r
- if (largeUS) return 4;\r
- return 2;\r
- }\r
-\r
- internal uint BlobIndexSize() {\r
- if (largeBlob) return 4;\r
- return 2;\r
- }\r
-\r
- internal uint CodedIndexSize(CIx code) {\r
- if (lgeCIx[(uint)code]) return 4;\r
- return 2;\r
- }\r
-\r
- internal uint TableIndexSize(MDTable tabIx) {\r
- if (largeIx[(uint)tabIx]) return 4;\r
- return 2;\r
- }\r
- \r
- private void SetIndexSizes() {\r
- for (int i=0; i < numMetaDataTables; i++) {\r
- if (metaDataTables[i] == null)
- continue;
+ }
- uint count = (uint)metaDataTables[i].Count;\r
- if (count > maxSmlIxSize)
- largeIx[i] = true;\r
+ /**************************************************************************/
+ /// <summary>
+ /// Base class for the PEFile (starting point)
+ /// </summary>
+ public class PEFile {
+
+ private static readonly string mscorlibName = "mscorlib";
+ private Module thisMod;
+ private ClassDef moduleClass;
+ private ArrayList classRefList = new ArrayList();
+ private ArrayList classDefList = new ArrayList();
+ private ArrayList resources = new ArrayList ();
+ private Assembly thisAssembly;
+ private static bool isMSCorlib;
+ private int corFlags = 1;
+ FileImage fileImage;
+ MetaData metaData;
+
+ /// <summary>
+ /// Create a new PEFile. Each PEFile is a module.
+ /// </summary>
+ /// <param name="name">module name, also used for the file name</param>
+ /// <param name="isDLL">create a .dll or .exe file</param>
+ /// <param name="hasAssembly">this file is an assembly and
+ /// will contain the assembly manifest. The assembly name is the
+ /// same as the module name</param>
+ public PEFile(string name, bool isDLL, bool hasAssembly)
+ : this (name, null, isDLL, hasAssembly, null, null)
+ {
+ // Console.WriteLine(Hex.Byte(0x12));
+ // Console.WriteLine(Hex.Short(0x1234));
+ // Console.WriteLine(Hex.Int(0x12345678));
+ }
- MDTable tabIx = (MDTable)i;\r
- if (count > max5BitSmlIx) {\r
- lgeCIx[(int)CIx.HasCustomAttr] = true;\r
- }\r
- if (count > max3BitSmlIx) {\r
- if ((tabIx == MDTable.TypeRef) || (tabIx == MDTable.ModuleRef) || (tabIx == MDTable.Method) || (tabIx == MDTable.TypeSpec) || (tabIx == MDTable.Field)) \r
- lgeCIx[(int)CIx.CustomAttributeType] = true;\r
- if ((tabIx == MDTable.Method) || (tabIx == MDTable.MemberRef)) \r
- lgeCIx[(int)CIx.MemberRefParent] = true;\r
- }
- if (count > max2BitSmlIx) {\r
- if ((tabIx == MDTable.Field) || (tabIx == MDTable.Param) || (tabIx == MDTable.Property)) \r
- lgeCIx[(int)CIx.HasConst] = true;\r
- if ((tabIx == MDTable.TypeDef) || (tabIx == MDTable.TypeRef) || (tabIx == MDTable.TypeSpec))\r
- lgeCIx[(int)CIx.TypeDefOrRef] = true;\r
- if ((tabIx == MDTable.TypeDef) || (tabIx == MDTable.Method) || (tabIx == MDTable.Assembly))\r
- lgeCIx[(int)CIx.HasDeclSecurity] = true;\r
- if ((tabIx == MDTable.File) || (tabIx == MDTable.AssemblyRef) || (tabIx == MDTable.ExportedType))\r
- lgeCIx[(int)CIx.Implementation] = true;\r
- if ((tabIx == MDTable.Module) || (tabIx == MDTable.ModuleRef) || (tabIx == MDTable.AssemblyRef) || (tabIx == MDTable.TypeRef))\r
- lgeCIx[(int)CIx.ResolutionScope] = true;\r
- }
- if (count > max1BitSmlIx) {\r
- if ((tabIx == MDTable.Field) || (tabIx == MDTable.Param)) \r
- lgeCIx[(int)CIx.HasFieldMarshal] = true;\r
- if ((tabIx == MDTable.Event) || (tabIx == MDTable.Property)) \r
- lgeCIx[(int)CIx.HasSemantics] = true;\r
- if ((tabIx == MDTable.Method) || (tabIx == MDTable.MemberRef)) \r
- lgeCIx[(int)CIx.MethodDefOrRef] = true;\r
- if ((tabIx == MDTable.Field) || (tabIx == MDTable.Method)) \r
- lgeCIx[(int)CIx.MemberForwarded] = true; \r
- if ((tabIx == MDTable.TypeDef) || (tabIx == MDTable.Method)) \r
- lgeCIx[(int)CIx.TypeOrMethodDef] = true; \r
- }\r
- }\r
- }\r
-\r
- private void SetStreamOffsets() {\r
- uint sizeOfHeaders = StreamHeaderSize + (uint)tildeName.Length;\r
- for (int i=1; i < numStreams; i++) {\r
- sizeOfHeaders += streams[i].headerSize();\r
- }\r
- metaDataSize = MetaDataHeaderSize + sizeOfHeaders;\r
- tildeStart = metaDataSize;\r
- metaDataSize += tildeTide + tildePadding;\r
- for (int i=1; i < numStreams; i++) {\r
- streams[i].Start = metaDataSize;\r
- metaDataSize += streams[i].Size();\r
- streams[i].WriteDetails();\r
- }\r
- }\r
-\r
- internal void CalcTildeStreamSize() {\r
-CalcHeapSizes ();
- //tilde.SetIndexSizes(strings.LargeIx(),us.LargeIx(),guid.LargeIx(),blob.LargeIx());\r
- tildeTide = TildeHeaderSize;\r
- tildeTide += 4 * numTables;\r
- //Console.WriteLine("Tilde header + sizes = " + tildeTide);\r
- for (int i=0; i < numMetaDataTables; i++) {\r
- if (metaDataTables[i] != null) {\r
- ArrayList table = metaDataTables[i];\r
- // Console.WriteLine("Meta data table " + i + " at offset " + tildeTide);\r
- tildeTide += (uint)table.Count * ((MetaDataElement)table[0]).Size(this);\r
- // Console.WriteLine("Metadata table " + i + " has size " + table.Count);\r
- // Console.WriteLine("tildeTide = " + tildeTide);\r
- }\r
- }\r
- if ((tildeTide % 4) != 0) tildePadding = 4 - (tildeTide % 4);\r
- //Console.WriteLine("tildePadding = " + tildePadding);\r
- }\r
-\r
- internal void WriteTildeStream(FileImage output) {\r
- long startTilde = output.Seek(0,SeekOrigin.Current);\r
- output.Write((uint)0); // Reserved\r
- output.Write((byte)1); // MajorVersion\r
- output.Write((byte)0); // MinorVersion\r
- output.Write(heapSizes);\r
- output.Write((byte)1); // Reserved\r
- output.Write(valid);\r
- output.Write(sorted);\r
- for (int i=0; i < numMetaDataTables; i++) {\r
- if (metaDataTables[i] != null) {\r
- uint count = (uint)metaDataTables[i].Count;\r
- output.Write(count);\r
- }\r
- }\r
- long tabStart = output.Seek(0,SeekOrigin.Current);\r
- // Console.WriteLine("Starting metaData tables at " + tabStart);\r
- for (int i=0; i < numMetaDataTables; i++) {\r
- if (metaDataTables[i] != null) {\r
- // Console.WriteLine("Starting metaData table " + i + " at " + (output.Seek(0,SeekOrigin.Current) - startTilde));\r
- ArrayList table = metaDataTables[i];\r
- for (int j=0; j < table.Count; j++) {\r
- ((MetaDataElement)table[j]).Write(output);\r
- }\r
- }\r
- }\r
- // Console.WriteLine("Writing padding at " + output.Seek(0,SeekOrigin.Current));\r
- for (int i=0; i < tildePadding; i++) output.Write((byte)0);\r
- }\r
-\r
- private void BuildTable(ArrayList table) {\r
- if (table == null) return;\r
- for (int j=0; j < table.Count; j++) {\r
- ((MetaDataElement)table[j]).BuildTables(this);\r
- }\r
- }\r
-\r
- internal void BuildMetaData(uint codeStartOffset) {\r
- codeStart = codeStartOffset;\r
- BuildTable(metaDataTables[(int)MDTable.TypeDef]);\r
- BuildTable(metaDataTables[(int)MDTable.MemberRef]);\r
- BuildTable(metaDataTables[(int)MDTable.GenericParam]);\r
- BuildTable(metaDataTables[(int)MDTable.MethodSpec]);\r
- BuildTable(metaDataTables[(int)MDTable.GenericParamConstraint]);\r
+ /// <summary>
+ /// Create a new PEFile. Each PEFile is a module.
+ /// </summary>
+ /// <param name="name">module name, also used for the file name</param>
+ /// <param name="isDLL">create a .dll or .exe file</param>
+ /// <param name="hasAssembly">this file is an assembly and
+ /// will contain the assembly manifest. The assembly name is the
+ /// same as the module name</param>
+ /// <param name="outputDir">write the PEFile to this directory. If this
+ /// string is null then the output will be to the current directory</param>
+ public PEFile(string name, bool isDLL, bool hasAssembly, string outputDir)
+ : this (name, null, isDLL, hasAssembly, outputDir, null)
+ {
+ // Console.WriteLine(Hex.Byte(0x12));
+ // Console.WriteLine(Hex.Short(0x1234));
+ // Console.WriteLine(Hex.Int(0x12345678));
+ }
- if (cattr_list != null) {
- foreach (CustomAttribute cattr in cattr_list)
- cattr.BuildTables (this);
- }
+ /// <summary>
+ /// Create a new PEFile
+ /// </summary>
+ /// <param name="name">module name</param>
+ /// <param name="isDLL">create a .dll or .exe</param>
+ /// <param name="hasAssembly">this PEfile is an assembly and
+ /// will contain the assemly manifest. The assembly name is the
+ /// same as the module name</param>
+ /// <param name="outStream">write the PEFile to this stream instead
+ /// of to a new file</param>
+ public PEFile(string name, bool isDLL, bool hasAssembly, Stream outStream)
+ : this (name, null, isDLL, hasAssembly, null, outStream)
+ {
+ }
-/* for (int i=0; i < metaDataTables.Length; i++) {\r
- ArrayList table = metaDataTables[i];\r
- if (table != null) {\r
- for (int j=0; j < table.Count; j++) {\r
- ((MetaDataElement)table[j]).BuildTables(this);\r
- }\r
- }\r
- }\r
- */\r
+ public PEFile(string name, string module_name, bool isDLL, bool hasAssembly, Stream outStream)
+ : this (name, module_name, isDLL, hasAssembly, null, outStream)
+ {
+ }
- SetIndexSizes();\r
- for (int i=1; i < numStreams; i++) {\r
- streams[i].EndStream();\r
- }\r
- CalcTildeStreamSize();\r
- SetStreamOffsets();\r
- byteCodePadding = NumToAlign(codeSize,4);\r
- if (entryPoint != null) file.SetEntryPoint(entryPoint.Token());\r
- }\r
-\r
- internal void WriteByteCodes(FileImage output) {\r
- for (int i=0; i < byteCodes.Count; i++) {\r
- ((CILInstructions)byteCodes[i]).Write(output);\r
- }\r
- for (int i=0; i < byteCodePadding; i++) {\r
- output.Write((byte)0);\r
- }\r
- }\r
-\r
- internal void WriteMetaData(FileImage output) {\r
- this.output = output;\r
- mdStart = output.Seek(0,SeekOrigin.Current);\r
- // Console.WriteLine("Writing metaData at " + Hex.Long(mdStart));\r
- output.Write(MetaDataSignature);\r
- output.Write((short)1); // Major Version\r
- output.Write((short)1); // Minor Version ECMA = 0, PEFiles = 1\r
- output.Write(0); // Reserved\r
- output.Write(version.Length);\r
- output.Write(version.ToCharArray()); // version string is already zero padded\r
- output.Write((short)0);\r
- output.Write((ushort)numStreams);\r
- // write tilde header\r
- output.Write(tildeStart);\r
- output.Write(tildeTide + tildePadding);\r
- output.Write(tildeName);\r
- for (int i=1; i < numStreams; i++) streams[i].WriteHeader(output);\r
- // Console.WriteLine("Writing tilde stream at " + output.Seek(0,SeekOrigin.Current) + " = " + tildeStart);\r
- WriteTildeStream(output);\r
- for (int i=1; i < numStreams; i++) streams[i].Write(output);\r
- // Console.WriteLine("Finished Writing metaData at " + output.Seek(0,SeekOrigin.Current));\r
- }\r
-\r
- internal bool LargeStringsIndex() { return strings.LargeIx(); }\r
- internal bool LargeGUIDIndex() { return guid.LargeIx(); }\r
- internal bool LargeUSIndex() { return us.LargeIx(); }\r
- internal bool LargeBlobIndex() { return blob.LargeIx(); }\r
-\r
- internal bool LargeIx(MDTable tabIx) { return largeIx[(uint)tabIx]; }\r
-\r
-\r
- private uint NumToAlign(uint val, uint alignVal) {\r
- if ((val % alignVal) == 0) return 0;\r
- return alignVal - (val % alignVal);\r
- }\r
-\r
- internal void WriteCodedIndex(CIx code, MetaDataElement elem, FileImage output) {\r
- uint ix = 0;\r
- if (elem != null) { \r
- ix = (elem.Row << CIxShiftMap[(uint)code]) | elem.GetCodedIx(code);\r
- // Console.WriteLine("coded index = " + ix + " row = " + elem.Row);\r
- //} else {\r
- // Console.WriteLine("elem for coded index is null");\r
- }\r
- if (lgeCIx[(uint)code]) \r
- output.Write(ix);\r
- else\r
- output.Write((ushort)ix);\r
- }\r
-\r
- }\r
- /**************************************************************************/ \r
- /// <summary>\r
- /// Base class for all Meta Data table elements\r
- /// </summary>\r
-\r
- public abstract class MetaDataElement\r
- {\r
-\r
- protected ArrayList customAttributes;\r
- private uint row = 0;\r
- protected bool done = false;\r
- protected MDTable tabIx;\r
-\r
- internal MetaDataElement() { }\r
-\r
- public uint Row {\r
- get {\r
- return row;\r
- }\r
- set {\r
- if (row == 0) row = value;\r
- }\r
- }\r
-\r
- internal virtual uint GetCodedIx(CIx code) { return 0; }\r
-\r
- /// <summary>\r
- /// Add a custom attribute to this item\r
- /// </summary>\r
- /// <param name="ctorMeth">the constructor method for this attribute</param>\r
- /// <param name="val">the byte value of the parameters</param>\r
- public void AddCustomAttribute(Method ctorMeth, byte[] val) {\r
- if (customAttributes == null) {\r
- customAttributes = new ArrayList();\r
- } \r
- customAttributes.Add(new CustomAttribute(this,ctorMeth,val));\r
- }\r
-\r
- /// <summary>\r
- /// Add a custom attribute to this item\r
- /// </summary>\r
- /// <param name="ctorMeth">the constructor method for this attribute</param>\r
- /// <param name="val">the constant values of the parameters</param>\r
- public void AddCustomAttribute(Method ctorMeth, Constant[] cVals) {\r
- if (customAttributes == null) {\r
- customAttributes = new ArrayList();\r
- } \r
-// customAttributes.Add(new CustomAttribute(this,ctorMeth,cVals));\r
- }\r
+ public PEFile(string name, string module_name, bool isDLL, bool hasAssembly, string outputDir, Stream outStream)
+ {
+ SetName (name);
+ string fname = module_name == null ? MakeFileName (outputDir, name, isDLL) : module_name;
+ if (outStream == null)
+ fileImage = new FileImage (isDLL, fname);
+ else
+ fileImage = new FileImage (isDLL, outStream);
+
+ InitPEFile (name, fname, hasAssembly);
+ }
- internal uint Token() {\r
- return (((uint)tabIx << 24) | row);\r
- }\r
-\r
- internal virtual void BuildTables(MetaData md) {\r
- done = true;\r
- }\r
-\r
- internal virtual uint Size(MetaData md) { \r
- return 0;\r
- }\r
-\r
- internal virtual void Write(FileImage output) { }\r
-\r
- }\r
- /**************************************************************************/ \r
- /// <summary>\r
- /// Stream in the Meta Data (#Strings, #US, #Blob and #GUID)\r
- /// </summary>\r
-\r
- internal class MetaDataStream : BinaryWriter \r
- {\r
- private static readonly uint StreamHeaderSize = 8;\r
- private static uint maxSmlIxSize = 0xFFFF;\r
- \r
- private uint start = 0; \r
- uint size = 0, tide = 1;\r
- bool largeIx = false;\r
- uint sizeOfHeader;\r
- char[] name;\r
- Hashtable htable = new Hashtable();
- Hashtable btable = new Hashtable (new ByteArrayHashCodeProvider (), new ByteArrayComparer ());
+ private void SetName (string name)
+ {
+ if (name == "mscorlib")
+ isMSCorlib = true;
+ }
- internal MetaDataStream(char[] name, bool addInitByte) : base(new MemoryStream()) {\r
- if (addInitByte) { Write((byte)0); size = 1; }\r
- this.name = name;\r
- sizeOfHeader = StreamHeaderSize + (uint)name.Length;\r
- }\r
-\r
- internal MetaDataStream(char[] name, System.Text.Encoding enc, bool addInitByte) : base(new MemoryStream(),enc) {\r
- if (addInitByte) { Write((byte)0); size = 1; }\r
- this.name = name;\r
- sizeOfHeader = StreamHeaderSize + (uint)name.Length;\r
- }\r
-\r
- public uint Start {\r
- get {\r
- return start;\r
- }\r
- set {\r
- start = value;\r
- }\r
- }\r
- \r
- internal uint headerSize() {\r
- // Console.WriteLine(name + " stream has headersize of " + sizeOfHeader);\r
- return sizeOfHeader;\r
- }\r
-\r
- internal void SetSize(uint siz) {\r
- size = siz;\r
- }\r
-\r
- internal uint Size() {\r
- return size;\r
- }\r
-\r
- internal bool LargeIx() {\r
- return largeIx;\r
- }\r
-\r
- internal void WriteDetails() {\r
- // Console.WriteLine(name + " - size = " + size);\r
- }\r
-\r
- internal uint Add(string str, bool prependSize) {\r
- Object val = htable[str];\r
- uint index = 0;\r
- if (val == null) { \r
- index = size;\r
- htable[str] = index;\r
- char[] arr = str.ToCharArray();\r
- if (prependSize) CompressNum((uint)arr.Length*2+1);\r
- Write(arr);\r
- Write((byte)0);\r
- size = (uint)Seek(0,SeekOrigin.Current);\r
- } else {\r
- index = (uint)val;\r
- }\r
- return index;\r
- }
- internal uint Add (byte[] str, bool prependSize) {
- Object val = btable [str];
- uint index = 0;
- if (val == null) {
- index = size;
- btable [str] = index;
- if (prependSize) CompressNum ((uint) str.Length);
- Write (str);
- size = (uint) Seek (0, SeekOrigin.Current);
- } else {
- index = (uint) val;
- }
- return index;
- }
+ private void InitPEFile(string name, string fName, bool hasAssembly)
+ {
+ metaData = fileImage.GetMetaData();
+ thisMod = new Module(fName,metaData);
+ if (hasAssembly) {
+ thisAssembly = new Assembly(name,metaData);
+ metaData.AddToTable(MDTable.Assembly,thisAssembly);
+ }
+ moduleClass = AddClass(TypeAttr.Private,"","<Module>");
+ moduleClass.SpecialNoSuper();
+ metaData.AddToTable(MDTable.Module,thisMod);
+ }
-
- internal uint Add(Guid guid, bool prependSize) {\r
- byte [] b = guid.ToByteArray ();
- if (prependSize) CompressNum ((uint) b.Length);
- Write(guid.ToByteArray());\r
- size =(uint)Seek(0,SeekOrigin.Current);\r
- return tide++;\r
- }\r
-\r
- internal uint Add(byte[] blob) {\r
- uint ix = size;\r
- CompressNum((uint)blob.Length);
- Write(blob);\r
- size = (uint)Seek(0,SeekOrigin.Current);\r
- return ix;\r
- }\r
-\r
- internal uint Add(byte val, bool prependSize) {\r
- uint ix = size;\r
- if (prependSize) CompressNum (1);
- Write(val);\r
- size = (uint)Seek(0,SeekOrigin.Current);\r
- return ix;\r
- }\r
-\r
- internal uint Add(sbyte val, bool prependSize) {\r
- uint ix = size;\r
- if (prependSize) CompressNum (1);
- Write(val);\r
- size = (uint)Seek(0,SeekOrigin.Current);\r
- return ix;\r
- }\r
-\r
- internal uint Add(ushort val, bool prependSize) {\r
- uint ix = size;\r
- if (prependSize) CompressNum (2);
- Write(val);\r
- size = (uint)Seek(0,SeekOrigin.Current);\r
- return ix;\r
- }\r
-\r
- internal uint Add(short val, bool prependSize) {\r
- uint ix = size;\r
- if (prependSize) CompressNum (2);
- Write(val);\r
- size = (uint)Seek(0,SeekOrigin.Current);\r
- return ix;\r
- }\r
-\r
- internal uint Add(uint val, bool prependSize) {\r
- uint ix = size;\r
- if (prependSize) CompressNum (4);
- Write(val);\r
- size = (uint)Seek(0,SeekOrigin.Current);\r
- return ix;\r
- }\r
-\r
- internal uint Add(int val, bool prependSize) {\r
- uint ix = size;\r
- if (prependSize) CompressNum (4);
- Write (val);
- size = (uint)Seek(0,SeekOrigin.Current);\r
- return ix;\r
- }\r
-\r
- internal uint Add(ulong val, bool prependSize) {\r
- uint ix = size;\r
- if (prependSize) CompressNum (8);
- Write(val);\r
- size = (uint)Seek(0,SeekOrigin.Current);\r
- return ix;\r
- }\r
-\r
- internal uint Add(long val, bool prependSize) {\r
- uint ix = size;\r
- if (prependSize) CompressNum (8);
- Write(val);\r
- size = (uint)Seek(0,SeekOrigin.Current);\r
- return ix;\r
- }\r
-\r
- internal uint Add(float val, bool prependSize) {\r
- uint ix = size;\r
- if (prependSize) CompressNum (4);
- Write(val);\r
- size = (uint)Seek(0,SeekOrigin.Current);\r
- return ix;\r
- }\r
-\r
- internal uint Add(double val, bool prependSize) {\r
- uint ix = size;\r
- if (prependSize) CompressNum (8);
- Write(val);\r
- size = (uint)Seek(0,SeekOrigin.Current);\r
- return ix;\r
- }\r
-\r
- private void CompressNum(uint val) {\r
- if (val < 0x7F) {\r
- Write((byte)val);\r
- } else if (val < 0x3FFF) {\r
- byte b1 = (byte)((val >> 8) | 0x80);\r
- byte b2 = (byte)(val & FileImage.iByteMask[0]);\r
- Write(b1);\r
- Write(b2);\r
- } else {\r
- byte b1 = (byte)((val >> 24) | 0xC0);\r
- byte b2 = (byte)((val & FileImage.iByteMask[2]) >> 16);\r
- byte b3 = (byte)((val & FileImage.iByteMask[1]) >> 8);;\r
- byte b4 = (byte)(val & FileImage.iByteMask[0]);\r
- Write(b1);\r
- Write(b2);\r
- Write(b3);\r
- Write(b4);\r
- }\r
- }\r
-\r
- private void QuadAlign() {\r
- if ((size % 4) != 0) {\r
- uint pad = 4 - (size % 4);\r
- size += pad;\r
- for (int i=0; i < pad; i++) {\r
- Write((byte)0);\r
- }\r
- }\r
- }\r
-\r
- internal void EndStream() {\r
- QuadAlign();\r
- if (size > maxSmlIxSize) {\r
- largeIx = true;\r
- }\r
- }\r
-\r
- internal void WriteHeader(BinaryWriter output) {\r
- output.Write(start);\r
- output.Write(size);\r
- output.Write(name);\r
- }\r
-\r
- internal virtual void Write(BinaryWriter output) {\r
- // Console.WriteLine("Writing " + name + " stream at " + output.Seek(0,SeekOrigin.Current) + " = " + start);\r
- MemoryStream str = (MemoryStream)BaseStream;\r
- output.Write(str.ToArray());\r
- }\r
-\r
- }\r
- /**************************************************************************/ \r
- /// <summary>\r
- /// Base class for Method Descriptors\r
- /// </summary>\r
-\r
- public abstract class Method : Member\r
- {\r
- protected CallConv callConv = CallConv.Default;\r
- protected Type retType;\r
-\r
- internal Method(string methName, Type rType) : base(methName)\r
- {\r
- retType = rType;\r
- }\r
-\r
- /// <summary>\r
- /// Add calling conventions to this method descriptor\r
- /// </summary>\r
- /// <param name="cconv"></param>\r
- public void AddCallConv(CallConv cconv) {\r
- callConv |= cconv;\r
- }\r
-\r
- internal abstract void TypeSig(MemoryStream sig);\r
-\r
- internal uint GetSigIx(MetaData md) {\r
- MemoryStream sig = new MemoryStream();\r
- TypeSig(sig);\r
- return md.AddToBlobHeap(sig.ToArray());\r
- }\r
-\r
- internal Type GetRetType() {\r
- return retType;\r
- }\r
-\r
- }\r
- /**************************************************************************/ \r
- /// <summary>\r
- /// Descriptor for a method defined in THIS assembly/module\r
- /// IL .method\r
- /// </summary>\r
-\r
- public class MethodDef : Method\r
- {\r
- private static readonly ushort PInvokeImpl = 0x2000;\r
- //private static readonly uint UnmanagedExport = 0x0008;\r
- // private static readonly byte LocalSigByte = 0x7;\r
- uint parIx = 0, textOffset = 0;\r
-\r
- MetaData metaData;\r
- CILInstructions code;\r
- ArrayList securityActions = new ArrayList();\r
- Param[] parList;\r
- Local[] locals;\r
- bool initLocals;\r
- ushort methFlags = 0, implFlags = 0;\r
- int maxStack = 0, numPars = 0;\r
- bool entryPoint = false;\r
- LocalSig localSig;\r
- ArrayList varArgSigList;\r
- ImplMap pinvokeImpl;\r
-\r
-\r
- internal MethodDef(MetaData md, string name, Type retType, Param[] pars) : base(name,retType) {\r
- metaData = md;\r
- parList = pars;\r
- if (parList != null) numPars = parList.Length;\r
- tabIx = MDTable.Method;\r
- }\r
-\r
- internal MethodDef(MetaData md, MethAttr mAttrSet, ImplAttr iAttrSet, string name, Type retType, Param[] pars) : base(name,retType) {\r
- metaData = md;\r
- parList = pars;\r
- if (parList != null) numPars = parList.Length;\r
- // Console.WriteLine("Creating method " + name + " with " + numPars + " parameters");\r
- methFlags = (ushort)mAttrSet;\r
- implFlags = (ushort)iAttrSet;\r
- tabIx = MDTable.Method;\r
- }\r
-\r
- internal Param[] GetPars() {\r
- return parList;\r
- }\r
-\r
- /// <summary>\r
- /// Add some attributes to this method descriptor\r
- /// </summary>\r
- /// <param name="ma">the attributes to be added</param>\r
- public void AddMethAttribute(MethAttr ma) {\r
- methFlags |= (ushort)ma;\r
- }\r
-\r
- /// <summary>\r
- /// Add some implementation attributes to this method descriptor\r
- /// </summary>\r
- /// <param name="ia">the attributes to be added</param>\r
- public void AddImplAttribute(ImplAttr ia) {\r
- implFlags |= (ushort)ia;\r
- }\r
-\r
- public void AddPInvokeInfo(ModuleRef scope, string methName,\r
- PInvokeAttr callAttr) {\r
- pinvokeImpl = new ImplMap((ushort)callAttr,this,methName,scope);\r
- methFlags |= PInvokeImpl;\r
- }\r
-\r
- /// <summary>\r
- /// Add a named generic type parameter\r
- /// </summary>\r
- public GenericParameter AddGenericParameter (short index, string name) {\r
- GenericParameter gp = new GenericParameter (this, metaData, index, name);
- metaData.AddToTable (MDTable.GenericParam, gp);\r
- return gp;
- }\r
+ internal static bool IsMSCorlib {
+ get { return isMSCorlib; }
+ }
- /// <summary>\r
- /// Set the maximum stack height for this method\r
- /// </summary>\r
- /// <param name="maxStack">the maximum height of the stack</param>\r
- public void SetMaxStack(int maxStack) {\r
- this.maxStack = maxStack; \r
- }\r
-\r
- /// <summary>\r
- /// Add local variables to this method\r
- /// </summary>\r
- /// <param name="locals">the locals to be added</param>\r
- /// <param name="initLocals">are locals initialised to default values</param>\r
- public void AddLocals(Local[] locals, bool initLocals) {\r
- this.locals = locals;\r
- this.initLocals = initLocals;\r
- }\r
-\r
- /// <summary>\r
- /// Mark this method as having an entry point\r
- /// </summary>\r
- public void DeclareEntryPoint() {\r
- entryPoint = true;\r
- }\r
-\r
- /// <summary>\r
- /// Create a code buffer for this method to add the IL instructions to\r
- /// </summary>\r
- /// <returns>a buffer for this method's IL instructions</returns>\r
- public CILInstructions CreateCodeBuffer() {\r
- code = new CILInstructions(metaData);\r
- return code;\r
- }\r
-\r
- /// <summary>\r
- /// Make a method reference descriptor for this method to be used \r
- /// as a callsite signature for this vararg method\r
- /// </summary>\r
- /// <param name="optPars">the optional pars for the vararg method call</param>\r
- /// <returns></returns>\r
- public MethodRef MakeVarArgSignature(Type[] optPars) {\r
- Type[] pars = new Type[numPars];\r
- MethodRef varArgSig;\r
- for (int i=0; i < numPars; i++) {\r
- pars[i] = parList[i].GetParType();\r
- }\r
- varArgSig = new MethodRef(this,name,retType,pars,true,optPars);\r
-\r
- if (varArgSigList == null)\r
- varArgSigList = new ArrayList ();\r
- varArgSigList.Add (varArgSig);\r
- return varArgSig;\r
- }\r
-\r
- internal sealed override void TypeSig(MemoryStream sig) {\r
- sig.WriteByte((byte)callConv);\r
- MetaData.CompressNum((uint)numPars,sig);\r
- retType.TypeSig(sig);\r
- for (ushort i=0; i < numPars; i++) {\r
- parList[i].seqNo = (ushort)(i+1);\r
- parList[i].TypeSig(sig);\r
- }\r
- }\r
-\r
- internal sealed override void BuildTables(MetaData md) {\r
- if (done) return;\r
- if (pinvokeImpl != null) {\r
- md.AddToTable(MDTable.ImplMap,pinvokeImpl);\r
- pinvokeImpl.BuildTables(md);\r
- }\r
- if (entryPoint) md.SetEntryPoint(this);\r
- uint locToken = 0;\r
- if (locals != null) {\r
- localSig = new LocalSig(locals);\r
- md.AddToTable(MDTable.StandAloneSig,localSig);\r
- localSig.BuildTables(md);\r
- locToken = localSig.Token();\r
- }\r
- if (code != null) {\r
- code.CheckCode(locToken,initLocals,maxStack);\r
- textOffset = md.AddCode(code);\r
- }\r
- nameIx = md.AddToStringsHeap(name);\r
- sigIx = GetSigIx(md);\r
- parIx = md.TableIndex(MDTable.Param);\r
- for (int i=0; i < numPars; i++) {\r
- md.AddToTable(MDTable.Param,parList[i]);\r
- parList[i].BuildTables(md);\r
- }\r
- if (varArgSigList != null) {\r
- foreach (MethodRef varArgSig in varArgSigList) {\r
- md.AddToTable(MDTable.MemberRef,varArgSig);\r
- varArgSig.BuildTables(md);\r
- }\r
- }\r
- // Console.WriteLine("method has " + numPars + " parameters");\r
- done = true;\r
- }\r
-\r
- internal sealed override uint Size(MetaData md) {\r
- return 8 + md.StringsIndexSize() + md.BlobIndexSize() + md.TableIndexSize(MDTable.Param);\r
- }\r
-\r
- internal sealed override void Write(FileImage output) {\r
- if (ZeroRva ()) output.Write(0);\r
- else output.WriteCodeRVA(textOffset);\r
- output.Write(implFlags);\r
- output.Write(methFlags);\r
- output.StringsIndex(nameIx);\r
- output.BlobIndex(sigIx);\r
- output.WriteIndex(MDTable.Param,parIx);\r
- }\r
-\r
- internal bool ZeroRva () {
- return (((methFlags & (ushort)MethAttr.Abstract) != 0) ||
- ((implFlags & (ushort)ImplAttr.Runtime) != 0) ||
- ((implFlags & (ushort)ImplAttr.InternalCall) != 0) ||
- (pinvokeImpl != null)); // TODO: Not entirely true but works for now
- }
+ public ClassDef ModuleClass {
+ get { return moduleClass; }
+ }
- internal sealed override uint GetCodedIx(CIx code) {\r
- switch (code) {\r
- case (CIx.HasCustomAttr) : return 0; \r
- case (CIx.HasDeclSecurity) : return 1; \r
- case (CIx.MemberRefParent) : return 3; \r
- case (CIx.MethodDefOrRef) : return 0; \r
- case (CIx.MemberForwarded) : return 1; \r
- case (CIx.CustomAttributeType) : return 2; \r
- case (CIx.TypeOrMethodDef) : return 1; \r
- }\r
- return 0;\r
- }\r
-\r
- }\r
- /**************************************************************************/ \r
- /// <summary>\r
- /// Descriptor for an overriding method (.override)\r
- /// </summary>\r
- public class MethodImpl : MetaDataElement\r
- {\r
- ClassDef parent;\r
- Method header, body;\r
-\r
- internal MethodImpl(ClassDef par, Method decl, Method bod) {\r
- parent = par;\r
- header = decl;\r
- body = bod;\r
- tabIx = MDTable.MethodImpl;\r
- }\r
-\r
- internal sealed override uint Size(MetaData md) {\r
- return md.TableIndexSize(MDTable.TypeDef) + 2 * md.CodedIndexSize(CIx.MethodDefOrRef);\r
- }\r
-\r
- internal sealed override void Write(FileImage output) {\r
- output.WriteIndex(MDTable.TypeDef,parent.Row);\r
- output.WriteCodedIndex(CIx.MethodDefOrRef,body);\r
- output.WriteCodedIndex(CIx.MethodDefOrRef,header);\r
- }\r
-\r
- }\r
- /**************************************************************************/ \r
- /// <summary>\r
- /// Descriptor for a method defined in another assembly/module\r
- /// </summary>\r
- public class MethodRef : Method\r
- {\r
- private static readonly byte Sentinel = 0x41;\r
- Type[] parList, optParList;\r
- MetaDataElement parent;\r
- uint numPars = 0, numOptPars = 0;\r
-\r
- internal MethodRef(MetaDataElement paren, string name, Type retType,\r
- Type[] pars, bool varArgMeth, Type[] optPars) : base(name,retType) {\r
- parent = paren;\r
- parList = pars;\r
- if (parList != null) numPars = (uint)parList.Length;\r
- if (varArgMeth) {\r
- optParList = optPars;\r
- if (optParList != null) numOptPars = (uint)optParList.Length;\r
- callConv = CallConv.Vararg;\r
- }\r
- }\r
-\r
- internal sealed override void TypeSig(MemoryStream sig) {\r
- sig.WriteByte((byte)callConv);\r
- MetaData.CompressNum(numPars+numOptPars,sig);\r
- retType.TypeSig(sig);\r
- for (int i=0; i < numPars; i++) {\r
- parList[i].TypeSig(sig);\r
- }\r
- if (numOptPars > 0) {\r
- sig.WriteByte(Sentinel);\r
- for (int i=0; i < numOptPars; i++) {\r
- optParList[i].TypeSig(sig);\r
- }\r
- }\r
- }\r
-\r
- internal sealed override void BuildTables(MetaData md) {\r
- if (done) return;\r
- nameIx = md.AddToStringsHeap(name);\r
- sigIx = GetSigIx(md);\r
- done = true;\r
- }\r
-\r
- internal sealed override uint Size(MetaData md) {\r
- return md.CodedIndexSize(CIx.MemberRefParent) + md.StringsIndexSize() + md.BlobIndexSize();\r
- }\r
-\r
- internal sealed override void Write(FileImage output) {\r
- output.WriteCodedIndex(CIx.MemberRefParent,parent);\r
- output.StringsIndex(nameIx);\r
- output.BlobIndex(sigIx);\r
- }\r
-\r
- internal sealed override uint GetCodedIx(CIx code) {\r
- switch (code) {\r
- case (CIx.HasCustomAttr) : return 6; \r
- case (CIx.MethodDefOrRef) : return 1; \r
- case (CIx.CustomAttributeType) : return 3; \r
- }\r
- return 0;\r
- }\r
-\r
- }\r
- /**************************************************************************/ \r
- /// <summary>\r
- /// Descriptor for Property and Event methods\r
- /// </summary>\r
- public class MethodSemantics : MetaDataElement {\r
-\r
- Feature.MethodType type;\r
- MethodDef meth;\r
- Feature eventOrProp;\r
-\r
- internal MethodSemantics(Feature.MethodType mType, MethodDef method, Feature feature) {\r
- type = mType;\r
- meth = method;\r
- eventOrProp = feature;\r
- tabIx = MDTable.MethodSemantics;\r
- }\r
-\r
- internal sealed override uint Size(MetaData md) {\r
- return 2 + md.TableIndexSize(MDTable.Method) + md.CodedIndexSize(CIx.HasSemantics);\r
- }\r
-\r
- internal sealed override void Write(FileImage output) {\r
- output.Write((ushort)type);\r
- output.WriteIndex(MDTable.Method,meth.Row);\r
- output.WriteCodedIndex(CIx.HasSemantics,eventOrProp);\r
- }\r
-\r
- }\r
- /**************************************************************************/ \r
- /// <summary>\r
- /// Descriptor for a FunctionPointer type\r
- /// </summary>\r
- /// \r
- public class MethPtrType : Type\r
- {\r
- bool varArgMeth;
- Type retType;
- Type [] parList;
- Type [] optParList;
- CallConv callConv;
- uint numPars;
- uint numOptPars;
- uint sigIx = 0;
+ /// <summary>
+ /// Set the subsystem (.subsystem) (Default is Windows Console mode)
+ /// </summary>
+ /// <param name="subS">subsystem value</param>
+ public void SetSubSystem(SubSystem subS)
+ {
+ fileImage.subSys = subS;
+ }
- /// <summary>\r
- /// Create a new function pointer type\r
- /// </summary>\r
- /// <param name="meth">the function to be referenced</param>\r
- public MethPtrType (CallConv callconv, Type retType, Type[] pars,
- bool varArgMeth, Type[] optPars) : base(0x1B) {
- this.retType = retType;
- callConv = callconv;
- parList = pars;
- this.varArgMeth = varArgMeth;
- if (parList != null) numPars = (uint)parList.Length;
- if (varArgMeth) {
- optParList = optPars;
- if (optParList != null) numOptPars = (uint)optParList.Length;
- callConv |= CallConv.Vararg;
- }
- tabIx = MDTable.TypeSpec;
- }
-
- internal sealed override void TypeSig(MemoryStream sig) {
- sig.WriteByte(typeIndex);
- // Bootlegged from method ref
- sig.WriteByte((byte)callConv);
- MetaData.CompressNum (numPars + numOptPars, sig);
- retType.TypeSig (sig);
- for (int i=0; i < numPars; i++) {
- parList[i].TypeSig (sig);
- }
- if (varArgMeth) {
- sig.WriteByte (0x41); // Write the sentinel
- for (int i=0; i < numOptPars; i++) {
- optParList[i].TypeSig (sig);
- }
- }
- }
+ /// <summary>
+ /// Set the flags (.corflags)
+ /// </summary>
+ /// <param name="flags">the flags value</param>
+ public void SetCorFlags(int flags)
+ {
+ corFlags = flags;
+ }
- internal sealed override void BuildTables(MetaData md) {\r
- if (done) return;\r
- MemoryStream sig = new MemoryStream();\r
- TypeSig(sig);\r
- sigIx = md.AddToBlobHeap(sig.ToArray());\r
- done = true;\r
- }\r
-\r
- internal sealed override uint Size(MetaData md) {\r
- return md.BlobIndexSize();\r
- }\r
-\r
- internal sealed override void Write(FileImage output) {\r
- output.BlobIndex(sigIx);\r
- }\r
-\r
- internal sealed override uint GetCodedIx(CIx code) { return 0x1B; }\r
-\r
- }\r
- /**************************************************************************/ \r
- /// <summary>\r
- /// Descriptor for THIS module\r
- /// </summary>\r
- public class Module : ResolutionScope\r
- {\r
- Guid mvid;\r
- uint mvidIx = 0;\r
-\r
- internal Module(string name, MetaData md) : base(name,md) {\r
- mvid = Guid.NewGuid();\r
- mvidIx = md.AddToGUIDHeap(mvid);\r
- tabIx = MDTable.Module;\r
- }\r
-\r
- public Guid Guid {
- get { return mvid; }
- }
+ public void SetStackReserve (long stackReserve)
+ {
+ fileImage.stackReserve = stackReserve;
+ }
- internal sealed override uint Size(MetaData md) {\r
- return 2 + md.StringsIndexSize() + 3 * md.GUIDIndexSize();\r
- }\r
-\r
- internal sealed override void Write(FileImage output) {\r
- output.Write((short)0);\r
- output.StringsIndex(nameIx);\r
- output.GUIDIndex(mvidIx);\r
- output.GUIDIndex(0);\r
- output.GUIDIndex(0);\r
- }\r
-\r
- internal sealed override uint GetCodedIx(CIx code) {\r
- switch (code) {\r
- case (CIx.HasCustomAttr) : return 7; \r
- case (CIx.ResolutionScope) : return 0;\r
- }\r
- return 0;\r
- }\r
- }
- /**************************************************************************/ \r
- /// <summary>\r
- /// Descriptor for another module in THIS assembly\r
- /// </summary>\r
- public class ModuleRef : ResolutionScope, IExternRef
- {\r
-\r
- internal ModuleRef(MetaData md, string name) : base(name,md) {\r
- tabIx = MDTable.ModuleRef;\r
- }
+ private string MakeFileName(string dirName, string name, bool isDLL)
+ {
+ string result = "";
+ if ((dirName != null) && (dirName.CompareTo("") != 0)) {
+ result = dirName;
+ if (!dirName.EndsWith("\\")) result += "\\";
+ }
+ result += name;
- /// <summary>\r
- /// Add a class to this external module. This is a class declared in\r
- /// another module of THIS assembly.\r
- /// </summary>\r
- /// <param name="nsName">name space name</param>\r
- /// <param name="name">class name</param>\r
- /// <returns>a descriptor for this class in another module</returns>\r
- public ClassRef AddClass(string nsName, string name) {\r
- ClassRef aClass = new ClassRef(nsName,name,metaData);\r
- metaData.AddToTable(MDTable.TypeRef,aClass);\r
- aClass.SetParent(this);\r
- return aClass;\r
- }\r
-\r
- /// <summary>\r
- /// Make a file descriptor to correspond to this module. The file\r
- /// descriptor will have the same name as the module descriptor\r
- /// </summary>\r
- /// <param name="hashBytes">the hash of the file</param>\r
- /// <param name="hasMetaData">the file contains metadata</param>\r
- /// <param name="entryPoint">the program entry point is in this file</param>\r
- /// <returns>a descriptor for the file which contains this module</returns>\r
- public FileRef MakeFile(byte[] hashBytes, bool hasMetaData, bool entryPoint) {\r
- FileRef file = new FileRef(nameIx,hashBytes,hasMetaData,entryPoint,metaData);\r
- metaData.AddToTable(MDTable.File,file);\r
- return file;\r
- }\r
-\r
- /// <summary>\r
- /// Add a value class to this module. This is a class declared in\r
- /// another module of THIS assembly.\r
- /// </summary>\r
- /// <param name="nsName">name space name</param>\r
- /// <param name="name">class name</param>\r
- /// <returns></returns>\r
- public ClassRef AddValueClass(string nsName, string name) {\r
- ClassRef aClass = new ClassRef(nsName,name,metaData);\r
- metaData.AddToTable(MDTable.TypeRef,aClass);\r
- aClass.SetParent(this);\r
- aClass.MakeValueClass();\r
- return aClass;\r
- }\r
-\r
- /// <summary>\r
- /// Add a class which is declared public in this external module of\r
- /// THIS assembly. This class will be exported from this assembly.\r
- /// The ilasm syntax for this is .extern class\r
- /// </summary>\r
- /// <param name="attrSet">attributes of the class to be exported</param>\r
- /// <param name="nsName">name space name</param>\r
- /// <param name="name">external class name</param>\r
- /// <param name="declFile">the file where the class is declared</param>\r
- /// <param name="isValueClass">is this class a value type?</param>\r
- /// <returns>a descriptor for this external class</returns>\r
- public ExternClassRef AddExternClass(TypeAttr attrSet, string nsName, \r
- string name, FileRef declFile, \r
- bool isValueClass) {\r
- ExternClassRef cRef = new ExternClassRef(attrSet,nsName,name,declFile,metaData);\r
- metaData.AddToTable(MDTable.TypeRef,cRef);\r
- cRef.SetParent(this);\r
- if (isValueClass) cRef.MakeValueClass();\r
- return cRef;\r
- }\r
-\r
- /// <summary>\r
- /// Add a "global" method in another module\r
- /// </summary>\r
- /// <param name="name">method name</param>\r
- /// <param name="retType">return type</param>\r
- /// <param name="pars">method parameter types</param>\r
- /// <returns>a descriptor for this method in anther module</returns>\r
- public MethodRef AddMethod(string name, Type retType, Type[] pars) {\r
- MethodRef meth = new MethodRef(this,name,retType,pars,false,null);\r
- metaData.AddToTable(MDTable.MemberRef,meth);\r
- return meth;\r
- }\r
-\r
- /// <summary>\r
- /// Add a vararg method to this class\r
- /// </summary>\r
- /// <param name="name">method name</param>\r
- /// <param name="retType">return type</param>\r
- /// <param name="pars">parameter types</param>\r
- /// <param name="optPars">optional param types for this vararg method</param>\r
- /// <returns>a descriptor for this method</returns>\r
- public MethodRef AddVarArgMethod(string name, Type retType, \r
- Type[] pars, Type[] optPars) {\r
- MethodRef meth = new MethodRef(this,name,retType,pars,true,optPars);\r
- metaData.AddToTable(MDTable.MemberRef,meth);\r
- return meth;\r
- }\r
-\r
- /// <summary>\r
- /// Add a field in another module\r
- /// </summary>\r
- /// <param name="name">field name</param>\r
- /// <param name="fType">field type</param>\r
- /// <returns>a descriptor for this field in another module</returns>\r
- public FieldRef AddField(string name, Type fType) {\r
- FieldRef field = new FieldRef(this,name,fType);\r
- metaData.AddToTable(MDTable.MemberRef,field);\r
- return field;\r
- }\r
-\r
- internal sealed override uint Size(MetaData md) {\r
- return md.StringsIndexSize();\r
- }\r
-\r
- internal sealed override void Write(FileImage output) {\r
- output.StringsIndex(nameIx);\r
- }\r
-\r
- internal sealed override uint GetCodedIx(CIx code) {\r
- switch (code) {\r
- case (CIx.HasCustomAttr) : return 12; \r
- case (CIx.MemberRefParent) : return 2; \r
- case (CIx.ResolutionScope) : return 1; \r
- }\r
- return 0;\r
- }\r
- \r
- }\r
- /**************************************************************************/ \r
- /// <summary>\r
- /// Descriptors for native types used for marshalling\r
- /// </summary>\r
- public class NativeType {\r
- public static readonly NativeType Void = new NativeType(0x01);\r
- public static readonly NativeType Boolean = new NativeType(0x02);\r
- public static readonly NativeType Int8 = new NativeType(0x03);\r
- public static readonly NativeType UInt8 = new NativeType(0x04);\r
- public static readonly NativeType Int16 = new NativeType(0x05);\r
- public static readonly NativeType UInt16 = new NativeType(0x06);\r
- public static readonly NativeType Int32 = new NativeType(0x07);\r
- public static readonly NativeType UInt32 = new NativeType(0x08);\r
- public static readonly NativeType Int64 = new NativeType(0x09);\r
- public static readonly NativeType UInt64 = new NativeType(0x0A);\r
- public static readonly NativeType Float32 = new NativeType(0x0B);\r
- public static readonly NativeType Float64 = new NativeType(0x0C);\r
- public static readonly NativeType Currency = new NativeType(0x0F);\r
- public static readonly NativeType BStr = new NativeType(0x13);\r
- public static readonly NativeType LPStr = new NativeType(0x14);\r
- public static readonly NativeType LPWStr = new NativeType(0x15);\r
- public static readonly NativeType LPTStr = new NativeType(0x16);\r
- public static readonly NativeType FixedSysString = new NativeType(0x17);\r
- public static readonly NativeType IUnknown = new NativeType(0x19);\r
- public static readonly NativeType IDispatch = new NativeType(0x1A);\r
- public static readonly NativeType Struct = new NativeType(0x1B);\r
- public static readonly NativeType Interface = new NativeType(0x1C);\r
- public static readonly NativeType Int = new NativeType(0x1F);\r
- public static readonly NativeType UInt = new NativeType(0x20);\r
- public static readonly NativeType ByValStr = new NativeType(0x22);\r
- public static readonly NativeType AnsiBStr = new NativeType(0x23);\r
- public static readonly NativeType TBstr = new NativeType(0x24);\r
- public static readonly NativeType VariantBool = new NativeType(0x25);\r
- public static readonly NativeType FuncPtr = new NativeType(0x26);\r
- public static readonly NativeType AsAny = new NativeType(0x28);\r
-\r
- protected byte typeIndex;\r
-\r
- internal NativeType(byte tyIx) { typeIndex = tyIx; }\r
-\r
- internal byte GetTypeIndex() { return typeIndex; }\r
-\r
- internal virtual byte[] ToBlob() {\r
- byte[] bytes = new byte[1];\r
- bytes[0] = GetTypeIndex();\r
- return bytes;\r
- }\r
-\r
- }\r
-\r
- public class NativeArray : NativeType \r
- {\r
- NativeType elemType;\r
- uint len = 0, parNum = 0;\r
-\r
- /*\r
- public NativeArray(NativeType elemType) : base(0x2A) {\r
- this.elemType = elemType;\r
- }\r
-\r
- public NativeArray(NativeType elemType, int len) : base(0x2A) {\r
- this.elemType = elemType;\r
- this.len = len;\r
- }\r
-*/\r
- public NativeArray(NativeType elemType, int numElem, int parNumForLen) : base(0x2A) {\r
- this.elemType = elemType;\r
- len = (uint)numElem;\r
- parNum = (uint)parNumForLen;\r
- }\r
-\r
- internal override byte[] ToBlob() {\r
- MemoryStream str = new MemoryStream();\r
- str.WriteByte(GetTypeIndex());\r
- if (elemType == null) str.WriteByte(0x50); // no info (MAX)\r
- else str.WriteByte(elemType.GetTypeIndex());\r
- MetaData.CompressNum(parNum,str);\r
- str.WriteByte(1);\r
- MetaData.CompressNum(len,str);\r
- return str.ToArray();\r
- }\r
-\r
- }\r
-\r
- public class SafeArray : NativeType \r
- {\r
- SafeArrayType elemType;\r
-\r
- public SafeArray(SafeArrayType elemType) : base(0x1D) {\r
- this.elemType = elemType;\r
- }\r
-\r
- internal override byte[] ToBlob() {\r
- byte[] bytes = new byte[2];\r
- bytes[0] = GetTypeIndex();\r
- bytes[1] = (byte)elemType;\r
- return bytes;\r
- }\r
-\r
- }\r
-\r
- public class FixedArray : NativeType \r
- {\r
- NativeType elemType;\r
- uint numElem;\r
-\r
- public FixedArray(NativeType elemType, int numElems) : base(0x1E) {\r
- this.elemType = elemType;\r
- numElem = (uint)numElems;\r
- }\r
-\r
- internal override byte[] ToBlob() {\r
- MemoryStream str = new MemoryStream();\r
- str.WriteByte(GetTypeIndex());\r
- MetaData.CompressNum(numElem,str);\r
- if (elemType == null) str.WriteByte(0x50); // no info (MAX)\r
- else str.WriteByte(elemType.GetTypeIndex());\r
- return str.ToArray();\r
- }\r
-\r
- }\r
-\r
- public class CustomMarshaller : NativeType \r
- {\r
- string typeName;\r
- string marshallerName;\r
- string cookie;\r
-\r
- public CustomMarshaller(string typeNameOrGUID, string marshallerName, \r
- string optCookie) : base(0x2C) {\r
- typeName = typeNameOrGUID;\r
- this.marshallerName = marshallerName;\r
- cookie = optCookie;\r
- }\r
-\r
- internal override byte[] ToBlob() {\r
- MemoryStream str = new MemoryStream();\r
- BinaryWriter bw = new BinaryWriter(str,new UTF8Encoding());\r
- bw.Write(GetTypeIndex());\r
- bw.Write(typeName.ToCharArray());\r
- bw.Write((byte)0);\r
- bw.Write(marshallerName.ToCharArray());\r
- bw.Write((byte)0);\r
- if (cookie != null) bw.Write(cookie.ToCharArray());\r
- bw.Write((byte)0);\r
- bw.Flush();\r
- return str.ToArray();\r
- }\r
- }\r
-\r
- /**************************************************************************/ \r
- /// <summary>\r
- /// Descriptor for a parameter of a method defined in this assembly/module\r
- /// </summary>\r
- public class Param : MetaDataElement\r
- {\r
- private static readonly ushort hasDefault = 0x1000;\r
- private static readonly ushort hasFieldMarshal = 0x2000;\r
-\r
- Type pType;\r
- string pName;\r
- internal ushort seqNo = 0;\r
- ushort parMode;\r
- ConstantElem defaultVal;\r
- uint nameIx = 0;\r
- FieldMarshal marshalInfo;\r
-\r
- /// <summary>\r
- /// Create a new parameter for a method\r
- /// </summary>\r
- /// <param name="mode">param mode (in, out, opt)</param>\r
- /// <param name="parName">parameter name</param>\r
- /// <param name="parType">parameter type</param>\r
- public Param(ParamAttr mode, string parName, Type parType) {\r
- pName = parName;\r
- pType = parType;\r
- parMode = (ushort)mode;\r
- tabIx = MDTable.Param;\r
- }\r
-\r
- /// <summary>\r
- /// Add a default value to this parameter\r
- /// </summary>\r
- /// <param name="c">the default value for the parameter</param>\r
- public void AddDefaultValue(Constant cVal) {\r
- defaultVal = new ConstantElem(this,cVal);\r
- parMode |= hasDefault;\r
- }\r
-\r
- /// <summary>\r
- /// Add marshalling information about this parameter\r
- /// </summary>\r
- public void AddMarshallInfo(NativeType marshallType) {\r
- parMode |= hasFieldMarshal;\r
- marshalInfo = new FieldMarshal(this,marshallType);\r
- }\r
-\r
- internal Type GetParType() { return pType; }\r
-\r
- internal sealed override void BuildTables(MetaData md) {\r
- if (done) return;\r
- nameIx = md.AddToStringsHeap(pName);\r
- if (defaultVal != null) {\r
- md.AddToTable(MDTable.Constant,defaultVal);\r
- defaultVal.BuildTables(md);\r
- }\r
- if (marshalInfo != null) {\r
- md.AddToTable(MDTable.FieldMarshal,marshalInfo);\r
- marshalInfo.BuildTables(md);\r
- }\r
- done = true;\r
- }\r
-\r
- internal void TypeSig(MemoryStream str) {\r
- pType.TypeSig(str);\r
- }\r
-\r
- internal sealed override uint Size(MetaData md) {\r
- return 4 + md.StringsIndexSize();\r
- }\r
-\r
- internal sealed override void Write(FileImage output) {\r
- output.Write(parMode);\r
- output.Write(seqNo);\r
- output.StringsIndex(nameIx);\r
- }\r
-\r
- internal sealed override uint GetCodedIx(CIx code) {\r
- switch (code) {\r
- case (CIx.HasCustomAttr) : return 4; \r
- case (CIx.HasConst) : return 1; \r
- case (CIx.HasFieldMarshal) : return 1; \r
- }\r
- return 0;\r
- }\r
-\r
- }\r
- /**************************************************************************/ \r
- /// <summary>\r
- /// Base class for the PEFile (starting point)\r
- /// </summary>\r
- public class PEFile\r
- {\r
- private static readonly string mscorlibName = "mscorlib";\r
- private Module thisMod;\r
- private ClassDef moduleClass;\r
- private ArrayList classRefList = new ArrayList();\r
- private ArrayList classDefList = new ArrayList();\r
- private Assembly thisAssembly;\r
- private int corFlags = 1;\r
- FileImage fileImage;\r
- MetaData metaData;\r
-\r
- /// <summary>\r
- /// Create a new PEFile. Each PEFile is a module.\r
- /// </summary>\r
- /// <param name="name">module name, also used for the file name</param>\r
- /// <param name="isDLL">create a .dll or .exe file</param>\r
- /// <param name="hasAssembly">this file is an assembly and \r
- /// will contain the assembly manifest. The assembly name is the \r
- /// same as the module name</param>\r
- public PEFile(string name, bool isDLL, bool hasAssembly) {\r
- // Console.WriteLine(Hex.Byte(0x12));\r
- // Console.WriteLine(Hex.Short(0x1234));\r
- // Console.WriteLine(Hex.Int(0x12345678));\r
- string fName = MakeFileName(null,name,isDLL);\r
- fileImage = new FileImage(isDLL,fName);\r
- InitPEFile(name, fName, hasAssembly);\r
- }\r
-\r
- /// <summary>\r
- /// Create a new PEFile. Each PEFile is a module.\r
- /// </summary>\r
- /// <param name="name">module name, also used for the file name</param>\r
- /// <param name="isDLL">create a .dll or .exe file</param>\r
- /// <param name="hasAssembly">this file is an assembly and \r
- /// will contain the assembly manifest. The assembly name is the \r
- /// same as the module name</param>\r
- /// <param name="outputDir">write the PEFile to this directory. If this\r
- /// string is null then the output will be to the current directory</param>\r
- public PEFile(string name, bool isDLL, bool hasAssembly, string outputDir) {\r
- // Console.WriteLine(Hex.Byte(0x12));\r
- // Console.WriteLine(Hex.Short(0x1234));\r
- // Console.WriteLine(Hex.Int(0x12345678));\r
- string fName = MakeFileName(outputDir,name,isDLL);\r
- fileImage = new FileImage(isDLL,fName);\r
- InitPEFile(name, fName, hasAssembly);\r
- }\r
-\r
- /// <summary>\r
- /// Create a new PEFile\r
- /// </summary>\r
- /// <param name="name">module name</param>\r
- /// <param name="isDLL">create a .dll or .exe</param>\r
- /// <param name="hasAssembly">this PEfile is an assembly and\r
- /// will contain the assemly manifest. The assembly name is the\r
- /// same as the module name</param>\r
- /// <param name="outStream">write the PEFile to this stream instead\r
- /// of to a new file</param>\r
- public PEFile(string name, bool isDLL, bool hasAssembly, Stream outStream) {\r
- fileImage = new FileImage(isDLL,outStream);\r
- InitPEFile(name, MakeFileName(null,name,isDLL), hasAssembly);\r
- }\r
+ // if (isDLL) result += ".dll"; else result += ".exe";
- public PEFile(string name, string module_name, bool isDLL, bool hasAssembly, Stream outStream) {\r
- fileImage = new FileImage(isDLL,outStream);\r
- InitPEFile(name, (module_name == null ? MakeFileName(null,name,isDLL) : module_name), hasAssembly);\r
- }
+ return result;
+ }
- private void InitPEFile(string name, string fName, bool hasAssembly) {\r
- metaData = fileImage.GetMetaData();\r
- thisMod = new Module(fName,metaData);\r
- if (hasAssembly) {\r
- thisAssembly = new Assembly(name,metaData);\r
- metaData.AddToTable(MDTable.Assembly,thisAssembly); \r
- }\r
- moduleClass = AddClass(TypeAttr.Private,"","<Module>");\r
- moduleClass.SpecialNoSuper();\r
- metaData.AddToTable(MDTable.Module,thisMod);\r
- }\r
- \r
+ /// <summary>
+ /// Add an external assembly to this PEFile (.assembly extern)
+ /// </summary>
+ /// <param name="assemName">the external assembly name</param>
+ /// <returns>a descriptor for this external assembly</returns>
+ public AssemblyRef AddExternAssembly(string assemName)
+ {
+ if (assemName.CompareTo(mscorlibName) == 0) return metaData.mscorlib;
+ AssemblyRef anAssem = new AssemblyRef(metaData,assemName);
+ metaData.AddToTable(MDTable.AssemblyRef,anAssem);
+ // Console.WriteLine("Adding assembly " + assemName);
+ return anAssem;
+ }
- public ClassDef ModuleClass {
- get { return moduleClass; }
- }
+ /// <summary>
+ /// Add an external module to this PEFile (.module extern)
+ /// </summary>
+ /// <param name="name">the external module name</param>
+ /// <returns>a descriptor for this external module</returns>
+ public ModuleRef AddExternModule(string name)
+ {
+ ModuleRef modRef = new ModuleRef(metaData,name);
+ metaData.AddToTable(MDTable.ModuleRef,modRef);
+ return modRef;
+ }
- /// <summary>\r
- /// Set the subsystem (.subsystem) (Default is Windows Console mode)\r
- /// </summary>\r
- /// <param name="subS">subsystem value</param>\r
- public void SetSubSystem(SubSystem subS) {\r
- fileImage.subSys = subS;\r
- }\r
-\r
- /// <summary>\r
- /// Set the flags (.corflags)\r
- /// </summary>\r
- /// <param name="flags">the flags value</param>\r
- public void SetCorFlags(int flags) {\r
- corFlags = flags;\r
- }\r
-\r
- private string MakeFileName(string dirName, string name, bool isDLL) {\r
- string result = "";\r
- if ((dirName != null) && (dirName.CompareTo("") != 0)) {\r
- result = dirName;\r
- if (!dirName.EndsWith("\\")) result += "\\";\r
- }\r
- result += name;\r
- \r
- // if (isDLL) result += ".dll"; else result += ".exe";\r
- \r
- return result;\r
- }\r
-\r
- /// <summary>\r
- /// Add an external assembly to this PEFile (.assembly extern)\r
- /// </summary>\r
- /// <param name="assemName">the external assembly name</param>\r
- /// <returns>a descriptor for this external assembly</returns>\r
- public AssemblyRef AddExternAssembly(string assemName) {\r
- if (assemName.CompareTo(mscorlibName) == 0) return metaData.mscorlib;\r
- AssemblyRef anAssem = new AssemblyRef(metaData,assemName);\r
- metaData.AddToTable(MDTable.AssemblyRef,anAssem);\r
- // Console.WriteLine("Adding assembly " + assemName);\r
- return anAssem;\r
- }\r
-\r
- /// <summary>\r
- /// Add an external module to this PEFile (.module extern)\r
- /// </summary>\r
- /// <param name="name">the external module name</param>\r
- /// <returns>a descriptor for this external module</returns>\r
- public ModuleRef AddExternModule(string name) {\r
- ModuleRef modRef = new ModuleRef(metaData,name);\r
- metaData.AddToTable(MDTable.ModuleRef,modRef);\r
- return modRef;\r
- }\r
-\r
- /// <summary>\r
- /// Add a "global" method to this module\r
- /// </summary>\r
- /// <param name="name">method name</param>\r
- /// <param name="retType">return type</param>\r
- /// <param name="pars">method parameters</param>\r
- /// <returns>a descriptor for this new "global" method</returns>\r
- public MethodDef AddMethod(string name, Type retType, Param[] pars) {\r
- return moduleClass.AddMethod(name,retType,pars);\r
- }\r
-\r
- /// <summary>\r
- /// Add a "global" method to this module\r
- /// </summary>\r
- /// <param name="mAtts">method attributes</param>\r
- /// <param name="iAtts">method implementation attributes</param>\r
- /// <param name="name">method name</param>\r
- /// <param name="retType">return type</param>\r
- /// <param name="pars">method parameters</param>\r
- /// <returns>a descriptor for this new "global" method</returns>\r
- public MethodDef AddMethod(MethAttr mAtts, ImplAttr iAtts, string name, Type retType, Param[] pars) {\r
- return moduleClass.AddMethod(mAtts,iAtts,name,retType,pars);\r
- }\r
-\r
- public MethodRef AddMethodToTypeSpec (Type item, string name, Type retType, Type[] pars) {\r
- MethodRef meth = new MethodRef (item.GetTypeSpec (metaData), name, retType, pars, false, null);\r
- metaData.AddToTable (MDTable.MemberRef,meth);\r
- return meth;\r
- }\r
-\r
- public MethodRef AddVarArgMethodToTypeSpec (Type item, string name, Type retType,\r
- Type[] pars, Type[] optPars) {\r
- MethodRef meth = new MethodRef(item.GetTypeSpec (metaData), name,retType,pars,true,optPars);\r
- metaData.AddToTable(MDTable.MemberRef,meth);\r
- return meth;\r
- }\r
-\r
- public FieldRef AddFieldToTypeSpec (Type item, string name, Type fType) {\r
- FieldRef field = new FieldRef (item.GetTypeSpec (metaData), name,fType);\r
- metaData.AddToTable (MDTable.MemberRef,field);\r
- return field;\r
- }\r
-\r
- public void AddMethodSpec (Method m, GenericMethodSig g_sig)
- {
- MethodSpec ms = new MethodSpec (m, g_sig);
- metaData.AddToTable (MDTable.MethodSpec, ms);
- }
+ /// <summary>
+ /// Add a "global" method to this module
+ /// </summary>
+ /// <param name="name">method name</param>
+ /// <param name="retType">return type</param>
+ /// <param name="pars">method parameters</param>
+ /// <returns>a descriptor for this new "global" method</returns>
+ public MethodDef AddMethod(string name, Type retType, Param[] pars)
+ {
+ return moduleClass.AddMethod(name,retType,pars);
+ }
- /// <summary>\r
- /// Add a "global" field to this module\r
- /// </summary>\r
- /// <param name="name">field name</param>\r
- /// <param name="fType">field type</param>\r
- /// <returns>a descriptor for this new "global" field</returns>\r
- public FieldDef AddField(string name, Type fType) {\r
- return moduleClass.AddField(name,fType);\r
- }\r
-\r
- /// <summary>\r
- /// Add a "global" field to this module\r
- /// </summary>\r
- /// <param name="attrSet">attributes of this field</param>\r
- /// <param name="name">field name</param>\r
- /// <param name="fType">field type</param>\r
- /// <returns>a descriptor for this new "global" field</returns>\r
- public FieldDef AddField(FieldAttr attrSet, string name, Type fType) {\r
- return moduleClass.AddField(attrSet,name,fType);\r
- }\r
-\r
- /// <summary>\r
- /// Add a class to this module\r
- /// </summary>\r
- /// <param name="attrSet">attributes of this class</param>\r
- /// <param name="nsName">name space name</param>\r
- /// <param name="name">class name</param>\r
- /// <returns>a descriptor for this new class</returns>\r
- public ClassDef AddClass(TypeAttr attrSet, string nsName, string name) {\r
- ClassDef aClass = new ClassDef(attrSet,nsName,name,metaData);\r
- metaData.AddToTable(MDTable.TypeDef,aClass);\r
- return aClass;\r
- }\r
-\r
- /// <summary>\r
- /// Add a class which extends System.ValueType to this module\r
- /// </summary>\r
- /// <param name="attrSet">attributes of this class</param>\r
- /// <param name="nsName">name space name</param>\r
- /// <param name="name">class name</param>\r
- /// <returns>a descriptor for this new class</returns>\r
- public ClassDef AddValueClass(TypeAttr attrSet, string nsName, string name) {\r
- ClassDef aClass = new ClassDef(attrSet,nsName,name,metaData);\r
- aClass.MakeValueClass();\r
- metaData.AddToTable(MDTable.TypeDef,aClass);\r
- return aClass;\r
- }\r
-\r
- /// <summary>\r
- /// Add a class to this module\r
- /// </summary>\r
- /// <param name="attrSet">attributes of this class</param>\r
- /// <param name="nsName">name space name</param>\r
- /// <param name="name">class name</param>\r
- /// <param name="superType">super type of this class (extends)</param>\r
- /// <returns>a descriptor for this new class</returns>\r
- public ClassDef AddClass(TypeAttr attrSet, string nsName, string name, Class superType) {\r
- ClassDef aClass = new ClassDef(attrSet,nsName,name,metaData);\r
- aClass.SetSuper(superType);\r
- metaData.AddToTable(MDTable.TypeDef,aClass);\r
- return aClass;\r
- }\r
-\r
- public FileRef AddFile(string fName, byte[] hashBytes, bool hasMetaData, bool entryPoint) {\r
- FileRef file = new FileRef(fName,hashBytes,hasMetaData,entryPoint,metaData);\r
- metaData.AddToTable(MDTable.File,file);\r
- return file;\r
- }\r
-\r
- /// <summary>\r
- /// Add a manifest resource to this PEFile NOT YET IMPLEMENTED\r
- /// </summary>\r
- /// <param name="mr"></param>\r
- public void AddManifestResource(ManifestResource mr) {\r
- metaData.AddToTable(MDTable.ManifestResource,mr);\r
- //mr.FixName(metaData);\r
- }\r
+ /// <summary>
+ /// Add a "global" method to this module
+ /// </summary>
+ /// <param name="mAtts">method attributes</param>
+ /// <param name="iAtts">method implementation attributes</param>
+ /// <param name="name">method name</param>
+ /// <param name="retType">return type</param>
+ /// <param name="pars">method parameters</param>
+ /// <returns>a descriptor for this new "global" method</returns>
+ public MethodDef AddMethod(MethAttr mAtts, ImplAttr iAtts, string name, Type retType, Param[] pars)
+ {
+ return moduleClass.AddMethod(mAtts,iAtts,name,retType,pars);
+ }
+
+ public MethodRef AddMethodToTypeSpec (Type item, string name, Type retType, Type[] pars)
+ {
+ MethodRef meth = new MethodRef (item.GetTypeSpec (metaData), name, retType, pars, false, null);
+ metaData.AddToTable (MDTable.MemberRef,meth);
+ return meth;
+ }
+
+ public MethodRef AddVarArgMethodToTypeSpec (Type item, string name, Type retType,
+ Type[] pars, Type[] optPars) {
+ MethodRef meth = new MethodRef(item.GetTypeSpec (metaData), name,retType,pars,true,optPars);
+ metaData.AddToTable(MDTable.MemberRef,meth);
+ return meth;
+ }
+
+ public FieldRef AddFieldToTypeSpec (Type item, string name, Type fType)
+ {
+ FieldRef field = new FieldRef (item.GetTypeSpec (metaData), name,fType);
+ metaData.AddToTable (MDTable.MemberRef,field);
+ return field;
+ }
+
+ public void AddMethodSpec (Method m, GenericMethodSig g_sig)
+ {
+ MethodSpec ms = new MethodSpec (m, g_sig);
+ metaData.AddToTable (MDTable.MethodSpec, ms);
+ }
+
+ /// <summary>
+ /// Add a "global" field to this module
+ /// </summary>
+ /// <param name="name">field name</param>
+ /// <param name="fType">field type</param>
+ /// <returns>a descriptor for this new "global" field</returns>
+ public FieldDef AddField(string name, Type fType)
+ {
+ return moduleClass.AddField(name,fType);
+ }
+
+ /// <summary>
+ /// Add a "global" field to this module
+ /// </summary>
+ /// <param name="attrSet">attributes of this field</param>
+ /// <param name="name">field name</param>
+ /// <param name="fType">field type</param>
+ /// <returns>a descriptor for this new "global" field</returns>
+ public FieldDef AddField(FieldAttr attrSet, string name, Type fType)
+ {
+ return moduleClass.AddField(attrSet,name,fType);
+ }
+
+ /// <summary>
+ /// Add a class to this module
+ /// </summary>
+ /// <param name="attrSet">attributes of this class</param>
+ /// <param name="nsName">name space name</param>
+ /// <param name="name">class name</param>
+ /// <returns>a descriptor for this new class</returns>
+ public ClassDef AddClass(TypeAttr attrSet, string nsName, string name)
+ {
+ return AddClass (attrSet, nsName, name, null);
+ }
+
+ /// <summary>
+ /// Add a class which extends System.ValueType to this module
+ /// </summary>
+ /// <param name="attrSet">attributes of this class</param>
+ /// <param name="nsName">name space name</param>
+ /// <param name="name">class name</param>
+ /// <returns>a descriptor for this new class</returns>
+ public ClassDef AddValueClass(TypeAttr attrSet, string nsName, string name, ValueClass vClass)
+ {
+ ClassDef aClass = new ClassDef(attrSet,nsName,name,metaData);
+ if (!ClassDef.IsValueType (nsName, name) && !ClassDef.IsEnum (nsName, name)) {
+ aClass.MakeValueClass(vClass);
+ } else {
+ if (ClassDef.IsEnum (nsName, name))
+ aClass.SetSuper (metaData.mscorlib.ValueType ());
+ else
+ aClass.SetSuper (metaData.mscorlib.GetSpecialSystemClass (PrimitiveType.Object));
+
+ metaData.mscorlib.SetSpecialSystemClass (nsName, name, aClass);
+ }
+ aClass.SetTypeIndex (PrimitiveType.ValueType.GetTypeIndex ());
+ metaData.AddToTable(MDTable.TypeDef,aClass);
+ return aClass;
+ }
+
+ /// <summary>
+ /// Add a class to this module
+ /// </summary>
+ /// <param name="attrSet">attributes of this class</param>
+ /// <param name="nsName">name space name</param>
+ /// <param name="name">class name</param>
+ /// <param name="superType">super type of this class (extends)</param>
+ /// <returns>a descriptor for this new class</returns>
+ public ClassDef AddClass(TypeAttr attrSet, string nsName, string name, Class superType)
+ {
+ ClassDef aClass = new ClassDef(attrSet,nsName,name,metaData);
+ if (superType != null)
+ aClass.SetSuper(superType);
+ if (PEFile.IsMSCorlib)
+ metaData.mscorlib.SetSpecialSystemClass (nsName, name, aClass);
+ metaData.AddToTable(MDTable.TypeDef,aClass);
+ return aClass;
+ }
+
+ public FileRef AddFile(string fName, byte[] hashBytes, bool hasMetaData, bool entryPoint)
+ {
+ FileRef file = new FileRef(fName,hashBytes,hasMetaData,entryPoint,metaData);
+ metaData.AddToTable(MDTable.File,file);
+ return file;
+ }
+
+ /// <summary>
+ /// Add a manifest resource to this PEFile NOT YET IMPLEMENTED
+ /// </summary>
+ /// <param name="mr"></param>
+ public void AddManifestResource(ManifestResource mr)
+ {
+ metaData.AddToTable(MDTable.ManifestResource,mr);
+ resources.Add (mr);
+ //mr.FixName(metaData);
+ }
+
+ public void AddCustomAttribute (Method meth, byte [] data, MetaDataElement element)
+ {
+ metaData.AddCustomAttribute (new CustomAttribute (element, meth, data));
+ }
+
+ public void AddDeclSecurity (SecurityAction sec_action, byte [] data, MetaDataElement element)
+ {
+ metaData.AddDeclSecurity (new DeclSecurity (element, (ushort) sec_action, data));
+ }
+
+ /// <summary>
+ /// Add a managed resource from another assembly.
+ /// </summary>
+ /// <param name="resName">The name of the resource</param>
+ /// <param name="assem">The assembly where the resource is</param>
+ /// <param name="isPublic">Access for the resource</param>
+ public void AddExternalManagedResource (string resName, AssemblyRef assem, uint flags)
+ {
+ resources.Add (new ManifestResource (resName, flags, assem));
+ }
+
+ /// <summary>
+ /// Add a managed resource from another assembly.
+ /// </summary>
+ /// <param name="mr"></param>
+ /// <param name="isPublic"></param>
+ public void AddExternalManagedResource (ManifestResource mr)
+ {
+ resources.Add (new ManifestResource (mr));
+ }
+ /// <summary>
+ /// Find a resource
+ /// </summary>
+ /// <param name="name">The name of the resource</param>
+ /// <returns>The resource with the name "name" or null </returns>
+ public ManifestResource GetResource (string name)
+ {
+ for (int i = 0; i < resources.Count; i ++) {
+ if (((ManifestResource) resources [i]).Name == name)
+ return (ManifestResource) resources [i];
+ }
+ return null;
+ }
+
+ public ManifestResource [] GetResources()
+ {
+ return (ManifestResource []) resources.ToArray (typeof (ManifestResource));
+ }
+
+ /// <summary>
+ /// Write out the PEFile (the "bake" function)
+ /// </summary>
+ public void WritePEFile() { /* the "bake" function */
+ fileImage.ReserveStrongNameSignatureSpace = thisAssembly.HasPublicKey;
+ fileImage.MakeFile();
+ }
+
+ /// <summary>
+ /// Get the descriptor of this module
+ /// </summary>
+ /// <returns>the descriptor for this module</returns>
+ public Module GetThisModule()
+ {
+ return thisMod;
+ }
+
+ /// <summary>
+ /// Get the descriptor for this assembly. The PEFile must have been
+ /// created with hasAssembly = true
+ /// </summary>
+ /// <returns>the descriptor for this assembly</returns>
+ public Assembly GetThisAssembly()
+ {
+ return thisAssembly;
+ }
+
+ }
+
+ /**************************************************************************/
+ /// <summary>
+ /// Descriptor for a Section in a PEFile eg .text, .sdata
+ /// </summary>
+ internal class Section {
+ private static readonly uint relocPageSize = 4096; // 4K pages for fixups
+
+ char[] name;
+ uint offset = 0, tide = 0, size = 0, rva = 0, relocTide = 0;
+ //uint relocOff = 0;
+ uint flags = 0, padding = 0;
+ uint[] relocs;
+
+ internal Section(string sName, uint sFlags)
+ {
+ name = sName.ToCharArray();
+ flags = sFlags;
+ }
+
+ internal uint Tide() { return tide; }
+
+ internal void IncTide(uint incVal) { tide += incVal; }
+
+ internal uint Padding() { return padding; }
+
+ internal uint Size() { return size; }
+
+ internal void SetSize(uint pad)
+ {
+ padding = pad;
+ size = tide + padding;
+ }
+
+ internal uint RVA() { return rva; }
+
+ internal void SetRVA(uint rva) { this.rva = rva; }
- public void AddCustomAttribute (Method meth, byte [] data, MetaDataElement element)
- {
- metaData.AddCustomAttribute (new CustomAttribute (element, meth, data));
- }
+ internal uint Offset() { return offset; }
- /// <summary>\r
- /// Write out the PEFile (the "bake" function)\r
- /// </summary>\r
- public void WritePEFile() { /* the "bake" function */\r
- fileImage.MakeFile();\r
- }\r
-\r
- /// <summary>\r
- /// Get the descriptor of this module\r
- /// </summary>\r
- /// <returns>the descriptor for this module</returns>\r
- public Module GetThisModule() {\r
- return thisMod;\r
- }\r
-\r
- /// <summary>\r
- /// Get the descriptor for this assembly. The PEFile must have been\r
- /// created with hasAssembly = true\r
- /// </summary>\r
- /// <returns>the descriptor for this assembly</returns>\r
- public Assembly GetThisAssembly() {\r
- return thisAssembly;\r
- }\r
-\r
- }\r
-\r
- /**************************************************************************/ \r
- /// <summary>\r
- /// Descriptor for the Primitive types defined in IL\r
- /// </summary>\r
- public class PrimitiveType : Type\r
- {\r
- private string name;\r
- private int systemTypeIndex;\r
- public static int NumSystemTypes = 18;\r
-\r
- public static readonly PrimitiveType Void = new PrimitiveType(0x01,"Void",0);\r
- public static readonly PrimitiveType Boolean = new PrimitiveType(0x02,"Boolean",1);\r
- public static readonly PrimitiveType Char = new PrimitiveType(0x03,"Char",2);\r
- public static readonly PrimitiveType Int8 = new PrimitiveType(0x04,"SByte",3);\r
- public static readonly PrimitiveType UInt8 = new PrimitiveType(0x05,"Byte",4);\r
- public static readonly PrimitiveType Int16 = new PrimitiveType(0x06,"Int16",5);\r
- public static readonly PrimitiveType UInt16 = new PrimitiveType(0x07,"UInt16",6);\r
- public static readonly PrimitiveType Int32 = new PrimitiveType(0x08,"Int32",7);\r
- public static readonly PrimitiveType UInt32 = new PrimitiveType(0x09,"UInt32",8);\r
- public static readonly PrimitiveType Int64 = new PrimitiveType(0x0A,"Int64",9);\r
- public static readonly PrimitiveType UInt64 = new PrimitiveType(0x0B,"UInt64",10);\r
- public static readonly PrimitiveType Float32 = new PrimitiveType(0x0C,"Single",11);\r
- public static readonly PrimitiveType Float64 = new PrimitiveType(0x0D,"Double",12);\r
- public static readonly PrimitiveType String = new PrimitiveType(0x0E,"String",13);\r
- internal static readonly PrimitiveType Class = new PrimitiveType(0x12);\r
- public static readonly PrimitiveType TypedRef = new PrimitiveType(0x16,"TypedReference",14);\r
- public static readonly PrimitiveType IntPtr = new PrimitiveType(0x18,"IntPtr",15);\r
- public static readonly PrimitiveType UIntPtr = new PrimitiveType(0x19,"UIntPtr",16);\r
- public static readonly PrimitiveType Object = new PrimitiveType(0x1C,"Object",17);\r
- internal static readonly PrimitiveType ClassType = new PrimitiveType(0x50);\r
- public static readonly PrimitiveType NativeInt = IntPtr;\r
- public static readonly PrimitiveType NativeUInt = UIntPtr;\r
-\r
- internal PrimitiveType(byte typeIx) : base(typeIx) { }\r
-\r
- internal PrimitiveType(byte typeIx, string name, int STIx) : base(typeIx) {\r
- this.name = name;\r
- this.systemTypeIndex = STIx;\r
- }\r
-\r
- internal string GetName() { return name; }\r
-\r
- internal int GetSystemTypeIx() { return systemTypeIndex; }\r
-\r
- internal sealed override void TypeSig(MemoryStream str) {\r
- str.WriteByte(typeIndex);\r
- }\r
-\r
- internal override MetaDataElement GetTypeSpec(MetaData md) {\r
- TypeSpec tS = md.GetPrimitiveTypeSpec(systemTypeIndex);\r
- if (tS == null) {\r
- tS = new TypeSpec(this,md);\r
- md.SetPrimitiveTypeSpec(systemTypeIndex,tS);\r
- md.AddToTable(MDTable.TypeSpec,tS);\r
- }\r
- return tS;\r
- }\r
-\r
- }\r
-\r
- /**************************************************************************/ \r
- /// <summary>\r
- /// Descriptor for the Property of a class\r
- /// </summary>\r
- public class Property : Feature\r
- {\r
- private static readonly byte PropertyTag = 0x8;\r
- MethodDef getterMeth;\r
- ConstantElem constVal;\r
- uint typeBlobIx = 0;\r
- Type[] parList;\r
- Type returnType;\r
- uint numPars = 0;\r
-\r
- internal Property(string name, Type retType, Type[] pars, ClassDef parent) : base(name, parent) {\r
- returnType = retType;\r
- parList = pars;\r
- if (pars != null) numPars = (uint)pars.Length;\r
- tabIx = MDTable.Property;\r
- }\r
-\r
- /// <summary>\r
- /// Add a set method to this property\r
- /// </summary>\r
- /// <param name="setter">the set method</param>\r
- public void AddSetter(MethodDef setter) {\r
- AddMethod(setter,MethodType.Setter);\r
- }\r
-\r
- /// <summary>\r
- /// Add a get method to this property\r
- /// </summary>\r
- /// <param name="getter">the get method</param>\r
- public void AddGetter(MethodDef getter) {\r
- AddMethod(getter,MethodType.Getter);\r
- getterMeth = getter;\r
- }\r
-\r
- /// <summary>\r
- /// Add another method to this property\r
- /// </summary>\r
- /// <param name="other">the method</param>\r
- public void AddOther(MethodDef other) {\r
- AddMethod(other,MethodType.Other);\r
- }\r
-\r
- /// <summary>\r
- /// Add an initial value for this property\r
- /// </summary>\r
- /// <param name="constVal">the initial value for this property</param>\r
- public void AddInitValue(Constant constVal) {\r
- this.constVal = new ConstantElem(this,constVal);\r
- }\r
-\r
- internal sealed override void BuildTables(MetaData md) {\r
- if (done) return;\r
- nameIx = md.AddToStringsHeap(name);\r
- MemoryStream sig = new MemoryStream();\r
- sig.WriteByte(PropertyTag);\r
- MetaData.CompressNum(numPars,sig);\r
- returnType.TypeSig(sig);\r
- for (int i=0; i < numPars; i++) {\r
- parList[i].TypeSig(sig);\r
- }\r
- typeBlobIx = md.AddToBlobHeap(sig.ToArray());\r
- for (int i=0; i < tide; i++) {\r
- md.AddToTable(MDTable.MethodSemantics,methods[i]);\r
- }\r
- if (constVal != null) {\r
- md.AddToTable(MDTable.Constant,constVal);\r
- constVal.BuildTables(md);\r
- }\r
- done = true;\r
- }\r
-\r
- internal sealed override uint Size(MetaData md) {\r
- return 2 + md.StringsIndexSize() + md.BlobIndexSize();\r
- }\r
-\r
- internal sealed override void Write(FileImage output) {\r
- output.Write(flags);\r
- output.StringsIndex(nameIx);\r
- output.BlobIndex(typeBlobIx);\r
- }\r
-\r
- internal sealed override uint GetCodedIx(CIx code) {\r
- switch (code) {\r
- case (CIx.HasCustomAttr) : return 9; \r
- case (CIx.HasConst) : return 2; \r
- case (CIx.HasSemantics) : return 1; \r
- }\r
- return 0;\r
- }\r
-\r
- }\r
- /**************************************************************************/ \r
- /// <summary>\r
- /// Descriptor for an pointer (type * or type &)\r
- /// </summary>\r
- public abstract class PtrType : Type\r
- {\r
- Type baseType;\r
-\r
- internal PtrType(Type bType, byte typeIx) : base(typeIx)\r
- {\r
- baseType = bType;\r
- tabIx = MDTable.TypeSpec;\r
- }\r
-\r
- internal sealed override void TypeSig(MemoryStream str) {\r
- str.WriteByte(typeIndex);\r
- baseType.TypeSig(str);\r
- }\r
-\r
- }\r
- /**************************************************************************/ \r
- /// <summary>\r
- /// Descriptor for a managed pointer (type & or byref)\r
- /// </summary>\r
-\r
- public class ManagedPointer : PtrType // <type> & (BYREF) \r
- {\r
-\r
- /// <summary>\r
- /// Create new managed pointer to baseType\r
- /// </summary>\r
- /// <param name="bType">the base type of the pointer</param>\r
- public ManagedPointer(Type baseType) : base(baseType,0x10) { }\r
- \r
- }\r
- /**************************************************************************/ \r
- /// <summary>\r
- /// Descriptor for an unmanaged pointer (type *)\r
- /// </summary>\r
- public class UnmanagedPointer : PtrType // PTR\r
- {\r
- /// <summary>\r
- /// Create a new unmanaged pointer to baseType\r
- /// </summary>\r
- /// <param name="baseType">the base type of the pointer</param>\r
- public UnmanagedPointer(Type baseType) : base(baseType, 0x0F) { }\r
-\r
- }\r
- /**************************************************************************/ \r
- /// <summary>\r
- /// Base class for scopes (extended by Module, ModuleRef, Assembly, AssemblyRef)\r
- /// </summary>\r
- public abstract class ResolutionScope : MetaDataElement\r
- {\r
- protected uint nameIx = 0;\r
- protected MetaData metaData;\r
- protected string name;\r
-\r
- internal ResolutionScope(string name, MetaData md)\r
- {\r
- metaData = md;\r
- this.name = name;\r
- nameIx = md.AddToStringsHeap(name);\r
- }\r
-\r
- internal string GetName() { return name; }\r
-\r
- }\r
- /**************************************************************************/ \r
- /// <summary>\r
- /// Descriptor for a Section in a PEFile eg .text, .sdata\r
- /// </summary>\r
- internal class Section {\r
- private static readonly uint relocPageSize = 4096; // 4K pages for fixups\r
-\r
- char[] name; \r
- uint offset = 0, tide = 0, size = 0, rva = 0, relocTide = 0;\r
- //uint relocOff = 0;\r
- uint flags = 0, padding = 0;\r
- uint[] relocs; \r
-\r
- internal Section(string sName, uint sFlags) {
- name = sName.ToCharArray();\r
- flags = sFlags;\r
- }
-\r
- internal uint Tide() { return tide; }\r
-\r
- internal void IncTide(uint incVal) { tide += incVal; }\r
-\r
- internal uint Padding() { return padding; }\r
-\r
- internal uint Size() { return size; }\r
-\r
- internal void SetSize(uint pad) {\r
- padding = pad;\r
- size = tide + padding;\r
- }\r
-\r
- internal uint RVA() { return rva; }\r
-\r
- internal void SetRVA(uint rva) { this.rva = rva; }\r
-\r
- internal uint Offset() { return offset; }\r
-\r
- internal void SetOffset(uint offs) { offset = offs; }\r
-\r
- internal void DoBlock(BinaryWriter reloc, uint page, int start, int end) {\r
- //Console.WriteLine("rva = " + rva + " page = " + page);\r
- reloc.Write(rva + page);\r
- reloc.Write((uint)(((end-start+1)*2) + 8));\r
- for (int j=start; j < end; j++) {\r
- //Console.WriteLine("reloc offset = " + relocs[j]);\r
- reloc.Write((ushort)((0x3 << 12) | (relocs[j] - page)));\r
- }\r
- reloc.Write((ushort)0);\r
- }\r
-\r
- internal void DoRelocs(BinaryWriter reloc) {\r
- if (relocTide > 0) {\r
- //relocOff = (uint)reloc.Seek(0,SeekOrigin.Current);\r
- uint block = (relocs[0]/relocPageSize + 1) * relocPageSize;\r
- int start = 0;\r
- for (int i=1; i < relocTide; i++) {\r
- if (relocs[i] >= block) {\r
- DoBlock(reloc,block-relocPageSize,start,i);\r
- start = i;\r
- block = (relocs[i]/relocPageSize + 1) * relocPageSize;\r
- }\r
- }\r
- DoBlock(reloc,block-relocPageSize,start,(int)relocTide);\r
- }\r
- }\r
-\r
- internal void AddReloc(uint offs) {\r
- int pos = 0;\r
- if (relocs == null) {\r
- relocs = new uint[5];\r
- } else {\r
- if (relocTide >= relocs.Length) {\r
- uint[] tmp = relocs;\r
- relocs = new uint[tmp.Length + 5];\r
- for (int i=0; i < relocTide; i++) {\r
- relocs[i] = tmp[i];\r
- }\r
- }\r
- while ((pos < relocTide) && (relocs[pos] < offs)) pos++;\r
- for (int i=pos; i < relocTide; i++) {\r
- relocs[i+1] = relocs[i];\r
- }\r
- }\r
- relocs[pos] = offs;\r
- relocTide++; \r
- }\r
- \r
- internal void WriteHeader(BinaryWriter output, uint relocRVA) {\r
- output.Write(name);\r
- output.Write(tide);\r
- output.Write(rva);\r
- output.Write(size);\r
- output.Write(offset);\r
- output.Write(0);\r
- //output.Write(relocRVA + relocOff);\r
- output.Write(0);\r
- output.Write(0);\r
- //output.Write((ushort)relocTide);\r
- //output.Write((ushort)0);\r
- output.Write(flags);\r
- }\r
-\r
- }\r
- /**************************************************************************/ \r
- public abstract class Signature : MetaDataElement \r
- {\r
- protected uint sigIx;\r
-\r
- internal Signature() {\r
- tabIx = MDTable.StandAloneSig;\r
- }\r
-\r
- internal sealed override uint Size(MetaData md) {\r
- return md.BlobIndexSize();\r
- }\r
-\r
- internal sealed override void Write(FileImage output) {\r
- output.BlobIndex(sigIx);\r
- }\r
-\r
- internal sealed override uint GetCodedIx(CIx code) { return (uint)tabIx; }\r
-\r
- }\r
- /**************************************************************************/ \r
- /// <summary>\r
- /// Descriptor for a class defined in System (mscorlib)\r
- /// </summary>\r
- internal class SystemClass : ClassRef\r
- {\r
- PrimitiveType elemType; \r
-\r
- internal SystemClass(PrimitiveType eType, AssemblyRef paren, MetaData md)\r
- : base("System",eType.GetName(),md) {\r
- elemType = eType;\r
- parent = paren;\r
- }\r
-\r
- internal override sealed MetaDataElement GetTypeSpec(MetaData md) {\r
- if (typeSpec == null) typeSpec = (TypeSpec)elemType.GetTypeSpec(md);\r
- return typeSpec;\r
- }\r
-\r
-\r
- internal sealed override void TypeSig(MemoryStream str) {\r
- str.WriteByte(elemType.GetTypeIndex());\r
- }\r
-\r
- }\r
- /**************************************************************************/ \r
- /// <summary>\r
- /// Base class for all IL types\r
- /// </summary>\r
- public abstract class Type : MetaDataElement {\r
- protected byte typeIndex;\r
- protected TypeSpec typeSpec;\r
-\r
- internal Type(byte tyIx) { typeIndex = tyIx; }\r
-\r
- internal byte GetTypeIndex() { return typeIndex; }\r
- internal void SetTypeIndex (byte b) { typeIndex = b; }
-
- internal virtual MetaDataElement GetTypeSpec(MetaData md) {\r
- if (typeSpec == null) {\r
- typeSpec = new TypeSpec(this,md);\r
- md.AddToTable(MDTable.TypeSpec,typeSpec);\r
- }\r
- return typeSpec;\r
- }\r
- \r
- internal virtual void TypeSig(MemoryStream str) {\r
- throw(new TypeSignatureException(this.GetType().AssemblyQualifiedName +\r
- " doesn't have a type signature!!")); \r
- }\r
-\r
- }\r
-\r
- /**************************************************************************/ \r
-\r
- public class TypeSpec : MetaDataElement {\r
- uint sigIx = 0;\r
-\r
- internal TypeSpec(Type aType, MetaData md) {\r
- MemoryStream sig = new MemoryStream();\r
- aType.TypeSig(sig);\r
- sigIx = md.AddToBlobHeap(sig.ToArray());\r
- tabIx = MDTable.TypeSpec;\r
- }\r
-\r
- internal sealed override uint GetCodedIx(CIx code) {\r
- switch (code) {\r
- case (CIx.TypeDefOrRef) : return 2; \r
- case (CIx.HasCustomAttr) : return 13; \r
- case (CIx.MemberRefParent) : return 4; \r
- }\r
- return 0;\r
- }\r
-\r
- internal override uint Size(MetaData md) { \r
- return md.BlobIndexSize();\r
- }\r
-\r
- internal sealed override void Write(FileImage output) {\r
- //Console.WriteLine("Writing the blob index for a TypeSpec");\r
- output.BlobIndex(sigIx);\r
- }\r
-\r
- }\r
+ internal void SetOffset(uint offs) { offset = offs; }
- class ByteArrayComparer : IComparer {
+ internal void DoBlock(BinaryWriter reloc, uint page, int start, int end)
+ {
+ //Console.WriteLine("rva = " + rva + " page = " + page);
+ reloc.Write(rva + page);
+ reloc.Write((uint)(((end-start+1)*2) + 8));
+ for (int j=start; j < end; j++) {
+ //Console.WriteLine("reloc offset = " + relocs[j]);
+ reloc.Write((ushort)((0x3 << 12) | (relocs[j] - page)));
+ }
+ reloc.Write((ushort)0);
+ }
- public int Compare (object x, object y)
- {
- byte [] a = (byte []) x;
- byte [] b = (byte []) y;
- int len = a.Length;
+ internal void DoRelocs(BinaryWriter reloc)
+ {
+ if (relocTide > 0) {
+ //relocOff = (uint)reloc.Seek(0,SeekOrigin.Current);
+ uint block = (relocs[0]/relocPageSize + 1) * relocPageSize;
+ int start = 0;
+ for (int i=1; i < relocTide; i++) {
+ if (relocs[i] >= block) {
+ DoBlock(reloc,block-relocPageSize,start,i);
+ start = i;
+ block = (relocs[i]/relocPageSize + 1) * relocPageSize;
+ }
+ }
+ DoBlock(reloc,block-relocPageSize,start,(int)relocTide);
+ }
+ }
- if (b.Length != len)
- return 1;
+ internal void AddReloc(uint offs)
+ {
+ int pos = 0;
+ if (relocs == null) {
+ relocs = new uint[5];
+ } else {
+ if (relocTide >= relocs.Length) {
+ uint[] tmp = relocs;
+ relocs = new uint[tmp.Length + 5];
+ for (int i=0; i < relocTide; i++) {
+ relocs[i] = tmp[i];
+ }
+ }
+ while ((pos < relocTide) && (relocs[pos] < offs)) pos++;
+ for (int i=pos; i < relocTide; i++) {
+ relocs[i+1] = relocs[i];
+ }
+ }
+ relocs[pos] = offs;
+ relocTide++;
+ }
- for (int i = 0; i < len; ++i)
- if (a [i] != b [i])
- return 1;
- return 0;
- }
- }
+ internal void WriteHeader(BinaryWriter output, uint relocRVA)
+ {
+ output.Write(name);
+ output.Write(tide);
+ output.Write(rva);
+ output.Write(size);
+ output.Write(offset);
+ output.Write(0);
+ //output.Write(relocRVA + relocOff);
+ output.Write(0);
+ output.Write(0);
+ //output.Write((ushort)relocTide);
+ //output.Write((ushort)0);
+ output.Write(flags);
+ }
- class ByteArrayHashCodeProvider : IHashCodeProvider {
+ }
- public int GetHashCode (Object key)
+ public class Hex {
+ readonly static char[] hexDigit = {'0','1','2','3','4','5','6','7',
+ '8','9','A','B','C','D','E','F'};
+ readonly static uint[] iByteMask = {0x000000FF, 0x0000FF00, 0x00FF0000, 0xFF000000};
+ readonly static ulong[] lByteMask = {0x00000000000000FF, 0x000000000000FF00,
+ 0x0000000000FF0000, 0x00000000FF000000,
+ 0x000000FF00000000, 0x0000FF0000000000,
+ 0x00FF000000000000, 0xFF00000000000000 };
+ readonly static uint nibble0Mask = 0x0000000F;
+ readonly static uint nibble1Mask = 0x000000F0;
+
+ public static String Byte(int b)
{
- byte [] arr = (byte []) key;
- int len = arr.Length;
- int h = 0;
+ char[] str = new char[2];
+ uint num = (uint)b;
+ uint b1 = num & nibble0Mask;
+ uint b2 = (num & nibble1Mask) >> 4;
+ str[0] = hexDigit[b2];
+ str[1] = hexDigit[b1];
+ return new String(str);
+ }
- for (int i = 0; i < len; ++i)
- h = (h << 5) - h + arr [i];
+ public static String Short(int b)
+ {
+ char[] str = new char[4];
+ uint num1 = (uint)b & iByteMask[0];
+ uint num2 = ((uint)b & iByteMask[1]) >> 8;
+ uint b1 = num1 & nibble0Mask;
+ uint b2 = (num1 & nibble1Mask) >> 4;
+ uint b3 = num2 & nibble0Mask;
+ uint b4 = (num2 & nibble1Mask) >> 4;
+ str[0] = hexDigit[b4];
+ str[1] = hexDigit[b3];
+ str[2] = hexDigit[b2];
+ str[3] = hexDigit[b1];
+ return new String(str);
+ }
- return h;
+ public static String Int(int val)
+ {
+ char[] str = new char[8];
+ uint num = (uint)val;
+ int strIx = 7;
+ for (int i=0; i < iByteMask.Length; i++) {
+ uint b = num & iByteMask[i];
+ b >>= (i*8);
+ uint b1 = b & nibble0Mask;
+ uint b2 = (b & nibble1Mask) >> 4;
+ str[strIx--] = hexDigit[b1];
+ str[strIx--] = hexDigit[b2];
+ }
+ return new String(str);
}
+ public static String Int(uint num)
+ {
+ char[] str = new char[8];
+ int strIx = 7;
+ for (int i=0; i < iByteMask.Length; i++) {
+ uint b = num & iByteMask[i];
+ b >>= (i*8);
+ uint b1 = b & nibble0Mask;
+ uint b2 = (b & nibble1Mask) >> 4;
+ str[strIx--] = hexDigit[b1];
+ str[strIx--] = hexDigit[b2];
+ }
+ return new String(str);
+ }
+
+ public static String Long(long lnum)
+ {
+ ulong num = (ulong)lnum;
+ char[] str = new char[16];
+ int strIx = 15;
+ for (int i=0; i < lByteMask.Length; i++) {
+ ulong b = num & lByteMask[i];
+ b >>= (i*8);
+ ulong b1 = b & nibble0Mask;
+ ulong b2 = (b & nibble1Mask) >> 4;
+ str[strIx--] = hexDigit[b1];
+ str[strIx--] = hexDigit[b2];
+ }
+ return new String(str);
+ }
+ }
+
+ /// <summary>
+ /// Error for invalid PE file
+ /// </summary>
+ public class PEFileException : System.Exception {
+ public PEFileException(string msg) : base("Error in PE File: " + msg) { }
+ }
+
+ public class NotYetImplementedException : System.Exception {
+ public NotYetImplementedException(string msg) : base(msg + " Not Yet Implemented") { }
}
-}\r
-\r
-\r
+
+ public class TypeSignatureException : System.Exception {
+ public TypeSignatureException(string msg) : base(msg) { }
+ }
+
+}