3 using System.Collections;
9 readonly static char[] hexDigit = {'0','1','2','3','4','5','6','7',
10 '8','9','A','B','C','D','E','F'};
11 readonly static uint[] iByteMask = {0x000000FF, 0x0000FF00, 0x00FF0000, 0xFF000000};
12 readonly static ulong[] lByteMask = {0x00000000000000FF, 0x000000000000FF00,
13 0x0000000000FF0000, 0x00000000FF000000,
14 0x000000FF00000000, 0x0000FF0000000000,
15 0x00FF000000000000, 0xFF00000000000000 };
16 readonly static uint nibble0Mask = 0x0000000F;
17 readonly static uint nibble1Mask = 0x000000F0;
19 public static String Byte(int b) {
20 char[] str = new char[2];
22 uint b1 = num & nibble0Mask;
23 uint b2 = (num & nibble1Mask) >> 4;
24 str[0] = hexDigit[b2];
25 str[1] = hexDigit[b1];
26 return new String(str);
29 public static String Short(int b) {
30 char[] str = new char[4];
31 uint num1 = (uint)b & iByteMask[0];
32 uint num2 = ((uint)b & iByteMask[1]) >> 8;
33 uint b1 = num1 & nibble0Mask;
34 uint b2 = (num1 & nibble1Mask) >> 4;
35 uint b3 = num2 & nibble0Mask;
36 uint b4 = (num2 & nibble1Mask) >> 4;
37 str[0] = hexDigit[b4];
38 str[1] = hexDigit[b3];
39 str[2] = hexDigit[b2];
40 str[3] = hexDigit[b1];
41 return new String(str);
44 public static String Int(int val) {
45 char[] str = new char[8];
48 for (int i=0; i < iByteMask.Length; i++) {
49 uint b = num & iByteMask[i];
51 uint b1 = b & nibble0Mask;
52 uint b2 = (b & nibble1Mask) >> 4;
53 str[strIx--] = hexDigit[b1];
54 str[strIx--] = hexDigit[b2];
56 return new String(str);
59 public static String Int(uint num) {
60 char[] str = new char[8];
62 for (int i=0; i < iByteMask.Length; i++) {
63 uint b = num & iByteMask[i];
65 uint b1 = b & nibble0Mask;
66 uint b2 = (b & nibble1Mask) >> 4;
67 str[strIx--] = hexDigit[b1];
68 str[strIx--] = hexDigit[b2];
70 return new String(str);
73 public static String Long(long lnum) {
74 ulong num = (ulong)lnum;
75 char[] str = new char[16];
77 for (int i=0; i < lByteMask.Length; i++) {
78 ulong b = num & lByteMask[i];
80 ulong b1 = b & nibble0Mask;
81 ulong b2 = (b & nibble1Mask) >> 4;
82 str[strIx--] = hexDigit[b1];
83 str[strIx--] = hexDigit[b2];
85 return new String(str);
89 public class NotYetImplementedException : System.Exception
91 public NotYetImplementedException(string msg) : base(msg + " Not Yet Implemented") { }
94 public class TypeSignatureException : System.Exception {
95 public TypeSignatureException(string msg) : base(msg) { }
98 public class ClassRefInst : Type {
101 private bool is_value;
103 public ClassRefInst (Type type, bool is_value) : base (PrimitiveType.Class.GetTypeIndex ()) {
105 this.is_value = is_value;
107 typeIndex = PrimitiveType.ValueType.GetTypeIndex ();
108 tabIx = MDTable.TypeSpec;
111 internal sealed override void TypeSig(MemoryStream str) {
116 public class MVar : Type {
120 public MVar (int index) : base (0x1E) {
122 tabIx = MDTable.TypeSpec;
125 internal sealed override void TypeSig(MemoryStream str) {
126 str.WriteByte(typeIndex);
127 MetaData.CompressNum ((uint) index, str);
131 public class GenericTypeSpec : Type {
135 public GenericTypeSpec (int index) : base (0x13) {
137 tabIx = MDTable.TypeSpec;
140 internal sealed override void TypeSig(MemoryStream str) {
141 str.WriteByte(typeIndex);
142 MetaData.CompressNum ((uint) index, str);
146 public class GenericTypeInst : Type {
148 private Type gen_type;
149 private Type[] gen_param;
151 public GenericTypeInst (Type gen_type, Type[] gen_param) : base (0x15)
154 this.gen_type = gen_type;
155 this.gen_param = gen_param;
156 tabIx = MDTable.TypeSpec;
159 internal sealed override void TypeSig(MemoryStream str) {
160 str.WriteByte(typeIndex);
161 gen_type.TypeSig (str);
162 MetaData.CompressNum ((uint) gen_param.Length, str);
163 foreach (Type param in gen_param)
168 public class GenericMethodSig {
170 private Type[] gen_param;
172 public GenericMethodSig (Type[] gen_param)
174 this.gen_param = gen_param;
177 internal void TypeSig (MemoryStream str)
179 MetaData.CompressNum ((uint) gen_param.Length, str); // THIS IS NOT RIGHT, but works
180 MetaData.CompressNum ((uint) gen_param.Length, str);
181 foreach (Type param in gen_param)
185 internal uint GetSigIx (MetaData md)
187 MemoryStream sig = new MemoryStream();
189 return md.AddToBlobHeap (sig.ToArray());
193 public class Sentinel : Type {
195 public Sentinel () : base (0x41) { }
197 internal sealed override void TypeSig(MemoryStream str) {
198 str.WriteByte(typeIndex);
203 /// The IL Array type
205 public abstract class Array : Type
208 protected Type elemType;
209 protected MetaData metaData;
210 protected string cnameSpace, cname;
212 internal Array(Type eType, byte TypeId) : base(TypeId) {
214 tabIx = MDTable.TypeSpec;
219 /**************************************************************************/
222 /// Single dimensional array with zero lower bound
224 public class ZeroBasedArray : Array {
227 /// Create a new array - elementType[]
229 /// <param name="elementType">the type of the array elements</param>
230 public ZeroBasedArray(Type elementType) : base (elementType, PrimitiveType.SZArray.GetTypeIndex ()) { }
232 internal sealed override void TypeSig(MemoryStream str) {
233 str.WriteByte(typeIndex);
234 elemType.TypeSig(str);
240 /**************************************************************************/
243 /// Multi dimensional array with explicit bounds
245 public class BoundArray : Array {
251 /// Create a new multi dimensional array type
252 /// eg. elemType[1..5,3..10,5,,] would be
253 /// new BoundArray(elemType,5,[1,3,0],[5,10,4])
255 /// <param name="elementType">the type of the elements</param>
256 /// <param name="dimensions">the number of dimensions</param>
257 /// <param name="loBounds">lower bounds of dimensions</param>
258 /// <param name="upBounds">upper bounds of dimensions</param>
259 public BoundArray(Type elementType, uint dimensions, int[] loBounds,
260 int[] upBounds) : base (elementType,0x14) {
261 numDims = dimensions;
262 lowerBounds = loBounds;
263 sizes = new int[loBounds.Length];
264 for (int i=0; i < loBounds.Length; i++) {
265 sizes[i] = upBounds[i] - loBounds[i] + 1;
270 /// Create a new multi dimensional array type
271 /// eg. elemType[5,10,20] would be new BoundArray(elemType,3,[5,10,20])
273 /// <param name="elementType">the type of the elements</param>
274 /// <param name="dimensions">the number of dimensions</param>
275 /// <param name="size">the sizes of the dimensions</param>
276 public BoundArray(Type elementType, uint dimensions, int[] size)
277 : base (elementType,0x14) {
278 numDims = dimensions;
283 /// Create a new multi dimensional array type
284 /// eg. elemType[,,] would be new BoundArray(elemType,3)
286 /// <param name="elementType">the type of the elements</param>
287 /// <param name="dimensions">the number of dimensions</param>
288 public BoundArray(Type elementType, uint dimensions)
289 : base (elementType,0x14) {
290 numDims = dimensions;
293 internal sealed override void TypeSig(MemoryStream str) {
294 str.WriteByte(typeIndex);
295 elemType.TypeSig(str);
296 MetaData.CompressNum(numDims,str);
297 if ((sizes != null) && (sizes.Length > 0)) {
298 MetaData.CompressNum((uint)sizes.Length,str);
299 for (int i=0; i < sizes.Length; i++) {
300 MetaData.CompressNum((uint)sizes[i],str);
302 } else str.WriteByte(0);
303 if ((lowerBounds != null) && (lowerBounds.Length > 0)) {
304 MetaData.CompressNum((uint)lowerBounds.Length,str);
305 for (int i=0; i < lowerBounds.Length; i++) {
306 MetaData.CompressNum((uint)lowerBounds[i],str);
308 } else str.WriteByte(0);
312 /**************************************************************************/
314 /// Descriptor for THIS assembly (.assembly)
316 public class Assembly : ResolutionScope
318 ushort majorVer, minorVer, buildNo, revisionNo;
321 uint keyIx = 0, cultIx = 0;
322 bool hasPublicKey = false;
324 internal Assembly(string name, MetaData md) : base(name,md) {
325 tabIx = MDTable.Assembly;
329 /// Add details about THIS assembly
331 /// <param name="majVer">Major Version</param>
332 /// <param name="minVer">Minor Version</param>
333 /// <param name="bldNo">Build Number</param>
334 /// <param name="revNo">Revision Number</param>
335 /// <param name="key">Hash Key</param>
336 /// <param name="hash">Hash Algorithm</param>
337 /// <param name="cult">Culture</param>
338 public void AddAssemblyInfo(int majVer, int minVer, int bldNo, int revNo,
339 byte[] key, uint hash, string cult) {
340 majorVer = (ushort)majVer;
341 minorVer = (ushort)minVer;
342 buildNo = (ushort)bldNo;
343 revisionNo = (ushort)revNo;
345 hasPublicKey = (key != null);
346 keyIx = metaData.AddToBlobHeap(key);
347 cultIx = metaData.AddToStringsHeap(cult);
351 /// Add an attribute to THIS assembly
353 /// <param name="aa">assembly attribute</param>
354 public void AddAssemblyAttr(AssemAttr aa) {
358 internal sealed override uint Size(MetaData md) {
359 return 16 + md.BlobIndexSize() + 2 * md.StringsIndexSize();
362 internal sealed override void Write(FileImage output) {
363 // Console.WriteLine("Writing assembly element with nameIx of " + nameIx + " at file offset " + output.Seek(0,SeekOrigin.Current));
364 output.Write((uint)hashAlgId);
365 output.Write(majorVer);
366 output.Write(minorVer);
367 output.Write(buildNo);
368 output.Write(revisionNo);
370 output.BlobIndex(keyIx);
371 output.StringsIndex(nameIx);
372 output.StringsIndex(cultIx);
375 internal sealed override uint GetCodedIx(CIx code) {
377 case (CIx.HasCustomAttr) : return 14;
378 case (CIx.HasDeclSecurity) : return 2;
383 internal bool HasPublicKey {
384 get { return hasPublicKey; }
387 /**************************************************************************/
389 public interface IExternRef {
390 ClassRef AddClass(string nsName, string name);
391 ClassRef AddValueClass(string nsName, string name);
395 /// A reference to an external assembly (.assembly extern)
397 public class AssemblyRef : ResolutionScope, IExternRef
399 private ushort major, minor, build, revision;
400 uint flags, keyIx, hashIx, cultIx;
401 bool hasVersion = false, isKeyToken = false;
405 internal AssemblyRef(MetaData md, string name) : base(name,md) {
406 tabIx = MDTable.AssemblyRef;
410 /// Add version information about this external assembly
412 /// <param name="majVer">Major Version</param>
413 /// <param name="minVer">Minor Version</param>
414 /// <param name="bldNo">Build Number</param>
415 /// <param name="revNo">Revision Number</param>
416 public void AddVersionInfo(int majVer, int minVer, int bldNo, int revNo) {
417 major = (ushort)majVer;
418 minor = (ushort)minVer;
419 build = (ushort)bldNo;
420 revision = (ushort)revNo;
425 /// Add the hash value for this external assembly
427 /// <param name="hash">bytes of the hash value</param>
428 public void AddHash(byte[] hash) {
429 hashIx = metaData.AddToBlobHeap(hash);
433 /// Set the culture for this external assembly
435 /// <param name="cult">the culture string</param>
436 public void AddCulture(string cult) {
437 cultIx = metaData.AddToStringsHeap(cult);
442 /// Add the full public key for this external assembly
444 /// <param name="key">bytes of the public key</param>
445 public void AddKey(byte[] key) {
446 flags |= 0x0001; // full public key
448 keyIx = metaData.AddToBlobHeap(key);
452 /// Add the public key token (low 8 bytes of the public key)
454 /// <param name="key">low 8 bytes of public key</param>
455 public void AddKeyToken(byte[] key) {
456 keyIx = metaData.AddToBlobHeap(key);
462 /// Add a class to this external assembly
464 /// <param name="nsName">name space name</param>
465 /// <param name="name">class name</param>
466 /// <returns></returns>
467 public virtual ClassRef AddClass(string nsName, string name) {
468 ClassRef aClass = new ClassRef(nsName,name,metaData);
469 metaData.AddToTable(MDTable.TypeRef,aClass);
470 aClass.SetParent(this);
475 /// Add a value class to this external assembly
477 /// <param name="nsName">name space name</param>
478 /// <param name="name">class name</param>
479 /// <returns></returns>
480 public virtual ClassRef AddValueClass(string nsName, string name) {
481 ClassRef aClass = new ClassRef(nsName,name,metaData);
482 metaData.AddToTable(MDTable.TypeRef,aClass);
483 aClass.SetParent(this);
484 aClass.MakeValueClass(ValueClass.ValueType);
488 internal string TypeName() {
489 string result = name;
491 result = result + ", Version=" + major + "." + minor + "." +
492 build + "." + revision;
493 if (keyBytes != null) {
494 string tokenStr = "=";
495 if (isKeyToken) tokenStr = "Token=";
496 result = result + ", PublicKey" + tokenStr;
497 for (int i=0; i < keyBytes.Length; i++) {
498 result = result + Hex.Byte(keyBytes[i]);
502 result = result + ", Culture=" + culture;
506 internal sealed override uint Size(MetaData md) {
507 return 12 + 2 * md.StringsIndexSize() + 2 * md.BlobIndexSize();
510 internal sealed override void Write(FileImage output) {
514 output.Write(revision);
516 output.BlobIndex(keyIx);
517 output.StringsIndex(nameIx);
518 output.StringsIndex(cultIx);
519 output.BlobIndex(hashIx);
522 internal sealed override uint GetCodedIx(CIx code) {
524 case (CIx.ResolutionScope) : return 2;
525 case (CIx.HasCustomAttr) : return 15;
526 case (CIx.Implementation) : return 1;
532 /**************************************************************************/
535 /// flags for the assembly (.corflags)
537 public enum CorFlags {CF_IL_ONLY = 1, CF_32_BITREQUIRED = 2,
538 CF_STRONGNAMESIGNED = 8, CF_TRACKDEBUGDATA = 0x10000 }
541 /// subsystem for the assembly (.subsystem)
543 public enum SubSystem { Native = 1, Windows_GUI = 2,
544 Windows_CUI = 3, OS2_CUI = 5, POSIX_CUI = 7, Native_Windows = 8,
548 /// Hash algorithms for the assembly
550 public enum HashAlgorithm { None, SHA1 }
553 /// Attributes for this assembly
555 public enum AssemAttr { EnableJITCompileTracking = 0x8000,
556 DisableJITCompileOptimizer = 0x4000}
559 /// Method call conventions
561 public enum CallConv { Default, Cdecl, Stdcall, Thiscall,
562 Fastcall, Vararg, Instance = 0x20, Generic = 0x10, InstanceExplicit = 0x60 }
565 /// Type custom modifier
567 public enum CustomModifier { modreq = 0x1F, modopt };
570 /// Attibutes for a class
572 public enum TypeAttr {Private, Public, NestedPublic, NestedPrivate,
573 NestedFamily, NestedAssembly, NestedFamAndAssem, NestedFamOrAssem,
574 SequentialLayout, ExplicitLayout = 0x10, Interface = 0x20,
575 Abstract = 0x80, PublicAbstract = 0x81, Sealed = 0x100,
576 PublicSealed = 0x101, SpecialName = 0x400, RTSpecialName = 0x800,
577 Import = 0x1000, Serializable = 0x2000, UnicodeClass = 0x10000,
578 AutoClass = 0x20000, BeforeFieldInit = 0x100000 }
581 /// Attributes for a field
583 public enum FieldAttr {Default, Private, FamAndAssem, Assembly,
584 Family, FamOrAssem, Public, Static = 0x10, PublicStatic = 0x16,
585 Initonly = 0x20, Literal = 0x40, Notserialized = 0x80,
586 SpecialName = 0x200, RTSpecialName = 0x400 }
589 /// Attributes for a method
591 public enum MethAttr { Default, Private, FamAndAssem, Assembly,
592 Family, FamOrAssem, Public, Static = 0x0010, PublicStatic = 0x16,
593 Final = 0x0020, PublicStaticFinal = 0x36, Virtual = 0x0040,
594 PrivateVirtual, PublicVirtual = 0x0046, HideBySig = 0x0080,
595 NewSlot = 0x0100, Abstract = 0x0400, SpecialName = 0x0800,
596 RTSpecialName = 0x1000, SpecialRTSpecialName = 0x1800,
597 RequireSecObject = 0x8000}
600 /// Attributes for .pinvokeimpl method declarations
602 public enum PInvokeAttr { nomangle = 1, ansi = 2, unicode = 4, autochar = 6,
603 lasterr = 0x0040, winapi = 0x0100, cdecl = 0x0200,
604 stdcall = 0x0300, thiscall = 0x0400, fastcall = 0x0500 }
607 /// Implementation attributes for a method
609 public enum ImplAttr { IL, Native, Runtime = 0x03, Unmanaged = 0x04,
610 ForwardRef = 0x10, PreserveSig = 0x0080, InternalCall = 0x1000,
611 Synchronised = 0x0020, Synchronized = 0x0020, NoInLining = 0x0008, Optil = 0x0002}
614 /// Modes for a parameter
616 public enum ParamAttr { Default, In, Out, Opt = 16 }
621 public enum Op { nop, breakOp, ldarg_0, ldarg_1, ldarg_2, ldarg_3,
622 ldloc_0, ldloc_1, ldloc_2, ldloc_3, stloc_0, stloc_1, stloc_2, stloc_3,
623 ldnull = 0x14, ldc_i4_m1, ldc_i4_0, ldc_i4_1, ldc_i4_2, ldc_i4_3,
624 ldc_i4_4, ldc_i4_5, ldc_i4_6, ldc_i4_7, ldc_i4_8, dup = 0x25, pop,
625 ret = 0x2A, ldind_i1 = 0x46, ldind_u1, ldind_i2, ldind_u2, ldind_i4,
626 ldind_u4, ldind_i8, ldind_i, ldind_r4, ldind_r8, ldind_ref, stind_ref,
627 stind_i1, stind_i2, stind_i4, stind_i8, stind_r4, stind_r8, add, sub, mul,
628 div, div_un, rem, rem_un, and, or, xor, shl, shr, shr_un, neg, not,
629 conv_i1, conv_i2, conv_i4, conv_i8, conv_r4, conv_r8, conv_u4, conv_u8,
630 conv_r_un = 0x76, throwOp = 0x7A, conv_ovf_i1_un = 0x82, conv_ovf_i2_un,
631 conv_ovf_i4_un, conv_ovf_i8_un, conf_ovf_u1_un, conv_ovf_u2_un,
632 conv_ovf_u4_un, conv_ovf_u8_un, conv_ovf_i_un, conv_ovf_u_un,
633 ldlen = 0x8E, ldelem_i1 = 0x90, ldelem_u1, ldelem_i2, ldelem_u2,
634 ldelem_i4, ldelem_u4, ldelem_i8, ldelem_i, ldelem_r4, ldelem_r8,
635 ldelem_ref, stelem_i, stelem_i1, stelem_i2, stelem_i4, stelem_i8, stelem_r4 = 0xA0, stelem_r8,
636 stelem_ref, conv_ovf_i1 = 0xb3, conv_ovf_u1, conv_ovf_i2, conv_ovf_u2,
637 conv_ovf_i4, conv_ovf_u4, conv_ovf_i8, conv_ovf_u8, ckfinite = 0xC3,
638 conv_u2 = 0xD1, conv_u1, conv_i, conv_ovf_i, conv_ovf_u, add_ovf,
639 add_ovf_un, mul_ovf, mul_ovf_un, sub_ovf, sub_ovf_un, endfinally,
640 stind_i = 0xDF, conv_u, arglist = 0xFE00, ceq, cgt, cgt_un, clt, clt_un,
641 localloc = 0xFE0F, endfilter = 0xFE11, volatile_ = 0xFE13, tail_,
642 cpblk = 0xFE17, initblk, rethrow = 0xFE1A, refanytype = 0xFE1D}
645 /// CIL instructions requiring an integer parameter
647 public enum IntOp {ldarg_s = 0x0E, ldarga_s, starg_s, ldloc_s, ldloca_s,
648 stloc_s, ldc_i4_s = 0x1F, ldc_i4, ldarg = 0xFE09,
649 ldarga, starg, ldloc, ldloca, stloc, unaligned = 0xFE12 }
652 /// CIL instructions requiring a field parameter
654 public enum FieldOp {ldfld = 0x7B, ldflda, stfld, ldsfld, ldsflda,
655 stsfld, ldtoken = 0xD0 }
658 /// CIL instructions requiring a method parameter
660 public enum MethodOp {jmp = 0x27, call, callvirt = 0x6F, newobj = 0x73,
661 ldtoken = 0xD0, ldftn = 0xFE06, ldvirtfn }
664 /// CIL instructions requiring a type parameter
666 public enum TypeOp {cpobj = 0x70, ldobj, castclass = 0x74, isinst,
667 unbox = 0x79, stobj = 0x81, box = 0x8C, newarr,
668 ldelema = 0x8F, refanyval = 0xC2, mkrefany = 0xC6,
669 ldtoken = 0xD0, initobj = 0xFE15, sizeOf = 0xFE1C,
670 ldelem = 0xA3, stelem = 0xA4, unbox_any }
673 /// CIL branch instructions
675 public enum BranchOp {
677 br_s = 0x2B, brfalse_s, brtrue_s, beq_s, bge_s, bgt_s,
678 ble_s, blt_s, bne_un_s, bge_un_s, bgt_un_s, ble_un_s, blt_un_s,
680 br = 0x38, brfalse, brtrue, beq, bge, bgt, ble, blt,
681 bne_un, bge_un, bgt_un, ble_un, blt_un,
683 leave = 0xDD, leave_s }
686 /// Index for all the tables in the meta data
688 public enum MDTable { Module, TypeRef, TypeDef, Field = 0x04, Method = 0x06,
689 Param = 0x08, InterfaceImpl, MemberRef, Constant, CustomAttribute,
690 FieldMarshal, DeclSecurity, ClassLayout, FieldLayout, StandAloneSig,
691 EventMap, Event = 0x14, PropertyMap, Property = 0x17, MethodSemantics,
692 MethodImpl, ModuleRef, TypeSpec, ImplMap, FieldRVA, Assembly = 0x20,
693 AssemblyProcessor, AssemblyOS, AssemblyRef, AssemblyRefProcessor,
694 AssemblyRefOS, File, ExportedType, ManifestResource, NestedClass,
695 GenericParam, MethodSpec, GenericParamConstraint }
697 public enum SafeArrayType { int16 = 2, int32, float32, float64,
698 currency, date, bstr, dispatch, error, boolean, variant, unknown,
699 Decimal, int8 = 16, uint8, uint16, uint32, Int = 22, UInt }
701 internal enum CIx { TypeDefOrRef, HasConst, HasCustomAttr, HasFieldMarshal,
702 HasDeclSecurity, MemberRefParent, HasSemantics, MethodDefOrRef,
703 MemberForwarded, Implementation, CustomAttributeType, ResolutionScope,
704 TypeOrMethodDef, MaxCIx }
706 internal enum MapType { eventMap, propertyMap, nestedClass }
708 /**************************************************************************/
710 /// The assembly for mscorlib.
712 public sealed class MSCorLib : AssemblyRef
714 private static readonly int valueTypeIx = 18;
715 private readonly string systemName = "System";
716 private ClassRef[] systemClasses = new ClassRef[valueTypeIx+2];
717 private PrimitiveType[] systemTypes = new PrimitiveType[valueTypeIx];
718 private TypeSpec[] specialTypeSpecs = new TypeSpec[valueTypeIx];
719 private static int[] specialNames = {
720 PrimitiveType.Void.GetName().GetHashCode(),
721 PrimitiveType.Boolean.GetName().GetHashCode(),
722 PrimitiveType.Char.GetName().GetHashCode(),
723 PrimitiveType.Int8.GetName().GetHashCode(),
724 PrimitiveType.UInt8.GetName().GetHashCode(),
725 PrimitiveType.Int16.GetName().GetHashCode(),
726 PrimitiveType.UInt16.GetName().GetHashCode(),
727 PrimitiveType.Int32.GetName().GetHashCode(),
728 PrimitiveType.UInt32.GetName().GetHashCode(),
729 PrimitiveType.Int64.GetName().GetHashCode(),
730 PrimitiveType.UInt64.GetName().GetHashCode(),
731 PrimitiveType.Float32.GetName().GetHashCode(),
732 PrimitiveType.Float64.GetName().GetHashCode(),
733 PrimitiveType.String.GetName().GetHashCode(),
734 PrimitiveType.TypedRef.GetName().GetHashCode(),
735 PrimitiveType.IntPtr.GetName().GetHashCode(),
736 PrimitiveType.UIntPtr.GetName().GetHashCode(),
737 PrimitiveType.Object.GetName().GetHashCode(),
738 PrimitiveType.ValueType.GetName ().GetHashCode(),
742 internal MSCorLib(MetaData md) : base(md,"mscorlib") {
743 md.AddToTable(MDTable.AssemblyRef,this);
744 systemTypes[PrimitiveType.Void.GetSystemTypeIx()] = PrimitiveType.Void;
745 systemTypes[PrimitiveType.Boolean.GetSystemTypeIx()] = PrimitiveType.Boolean;
746 systemTypes[PrimitiveType.Char.GetSystemTypeIx()] = PrimitiveType.Char;
747 systemTypes[PrimitiveType.Int8.GetSystemTypeIx()] = PrimitiveType.Int8;
748 systemTypes[PrimitiveType.UInt8.GetSystemTypeIx()] = PrimitiveType.UInt8;
749 systemTypes[PrimitiveType.Int16.GetSystemTypeIx()] = PrimitiveType.Int16;
750 systemTypes[PrimitiveType.UInt16.GetSystemTypeIx()] = PrimitiveType.UInt16;
751 systemTypes[PrimitiveType.Int32.GetSystemTypeIx()] = PrimitiveType.Int32;
752 systemTypes[PrimitiveType.UInt32.GetSystemTypeIx()] = PrimitiveType.UInt32;
753 systemTypes[PrimitiveType.Int64.GetSystemTypeIx()] = PrimitiveType.Int64;
754 systemTypes[PrimitiveType.UInt64.GetSystemTypeIx()] = PrimitiveType.UInt64;
755 systemTypes[PrimitiveType.Float32.GetSystemTypeIx()] = PrimitiveType.Float32;
756 systemTypes[PrimitiveType.Float64.GetSystemTypeIx()] = PrimitiveType.Float64;
757 systemTypes[PrimitiveType.IntPtr.GetSystemTypeIx()] = PrimitiveType.IntPtr;
758 systemTypes[PrimitiveType.UIntPtr.GetSystemTypeIx()] = PrimitiveType.UIntPtr;
759 systemTypes[PrimitiveType.String.GetSystemTypeIx()] = PrimitiveType.String;
760 systemTypes[PrimitiveType.Object.GetSystemTypeIx()] = PrimitiveType.Object;
761 systemTypes[PrimitiveType.TypedRef.GetSystemTypeIx()] = PrimitiveType.TypedRef;
765 /// Add a class to the mscorlib assembly
767 /// <param name="nsName">name space name</param>
768 /// <param name="name">class name</param>
769 /// <returns></returns>
770 public override ClassRef AddClass(string nsName, string name) {
771 ClassRef aClass = GetSpecialClass(nsName,name);
772 if (aClass == null) {
773 aClass = new ClassRef(nsName,name,metaData);
774 metaData.AddToTable(MDTable.TypeRef,aClass);
775 aClass.SetParent(this);
780 private ClassRef GetSpecialClass(string nsName,string name) {
781 if (nsName.CompareTo(systemName) != 0) return null;
782 int hash = name.GetHashCode();
783 for (int i=0; i < specialNames.Length; i++) {
784 if (hash == specialNames[i]) {
785 if (systemClasses[i] == null) {
786 if (i < valueTypeIx) {
787 systemClasses[i] = new SystemClass(systemTypes[i],this,metaData);
788 if ((systemTypes[i] != PrimitiveType.Object) &&
789 (systemTypes[i] != PrimitiveType.String)) {
790 systemClasses[i].MakeValueClass(ValueClass.ValueType);
793 systemClasses[i] = new ClassRef(nsName,name,metaData);
794 systemClasses[i].SetParent(this);
795 if (!ClassDef.IsValueType (nsName, name) && !ClassDef.IsEnum (nsName, name))
796 systemClasses[i].MakeValueClass(ValueClass.ValueType);
798 metaData.AddToTable(MDTable.TypeRef,systemClasses[i]);
800 return systemClasses[i];
806 internal ClassRef GetSpecialSystemClass(PrimitiveType pType) {
807 int ix = pType.GetSystemTypeIx();
808 if (systemClasses[ix] == null) {
809 systemClasses[ix] = new SystemClass(pType,this,metaData);
810 metaData.AddToTable(MDTable.TypeRef,systemClasses[ix]);
812 return systemClasses[ix];
815 private ClassRef GetValueClass(string name, int hash) {
816 int ix = valueTypeIx;
817 if (hash != specialNames[valueTypeIx]) ix++;
818 if (systemClasses[ix] == null) {
819 systemClasses[ix] = new ClassRef(systemName,name,metaData);
820 systemClasses[ix].SetParent(this);
821 systemClasses[ix].MakeValueClass(ValueClass.ValueType);
822 metaData.AddToTable(MDTable.TypeRef,systemClasses[ix]);
824 return systemClasses[ix];
827 internal ClassRef ValueType() {
828 if (systemClasses[valueTypeIx] == null) {
829 ClassRef valType = new ClassRef("System","ValueType",metaData);
830 valType.SetParent(this);
831 valType.MakeValueClass(ValueClass.ValueType);
832 metaData.AddToTable(MDTable.TypeRef,valType);
833 systemClasses[valueTypeIx] = valType;
835 return systemClasses[valueTypeIx];
838 internal ClassRef EnumType() {
839 //systemClasses [ valueTypeIx + 1] -> System.Enum
840 if (systemClasses[valueTypeIx + 1] == null) {
841 ClassRef valType = new ClassRef("System","Enum",metaData);
842 valType.SetParent(this);
843 valType.MakeValueClass(ValueClass.Enum);
844 metaData.AddToTable(MDTable.TypeRef,valType);
845 systemClasses[valueTypeIx + 1] = valType;
847 return systemClasses[valueTypeIx + 1];
851 /// Add a value class to this external assembly
853 /// <param name="nsName">name space name</param>
854 /// <param name="name">class name</param>
855 /// <returns></returns>
856 public override ClassRef AddValueClass(string nsName, string name) {
857 if (nsName.CompareTo(systemName) == 0) {
858 int hash = name.GetHashCode();
859 if ((hash == specialNames[valueTypeIx]) ||
860 (hash == specialNames[valueTypeIx+1])) {
861 return GetValueClass(name,hash);
864 ClassRef aClass = new ClassRef(nsName,name,metaData);
865 metaData.AddToTable(MDTable.TypeRef,aClass);
866 aClass.SetParent(this);
867 aClass.MakeValueClass(ValueClass.ValueType);
872 public enum ValueClass
878 /**************************************************************************/
880 /// Signature for calli instruction
882 public class CalliSig : Signature
884 private static readonly byte Sentinel = 0x41;
887 Type[] parameters, optParams;
888 uint numPars = 0, numOptPars = 0;
891 /// Create a signature for a calli instruction
893 /// <param name="cconv">calling conventions</param>
894 /// <param name="retType">return type</param>
895 /// <param name="pars">parameter types</param>
896 public CalliSig(CallConv cconv, Type retType, Type[] pars) {
897 tabIx = MDTable.StandAloneSig;
899 returnType = retType;
901 if (pars != null) numPars = (uint)pars.Length;
905 /// Add the optional parameters to a vararg method
906 /// This method sets the vararg calling convention
908 /// <param name="optPars">the optional pars for the vararg call</param>
909 public void AddVarArgs(Type[] optPars) {
911 if (optPars != null) numOptPars = (uint)optPars.Length;
912 callConv |= CallConv.Vararg;
916 /// Add extra calling conventions to this callsite signature
918 /// <param name="cconv"></param>
919 public void AddCallingConv(CallConv cconv) {
923 internal sealed override void BuildTables(MetaData md) {
925 MemoryStream sig = new MemoryStream();
926 sig.WriteByte((byte)callConv);
927 MetaData.CompressNum(numPars+numOptPars,sig);
928 returnType.TypeSig(sig);
929 for (int i=0; i < numPars; i++) {
930 parameters[i].TypeSig(sig);
932 sigIx = md.AddToBlobHeap(sig.ToArray());
933 if (numOptPars > 0) {
934 sig.WriteByte(Sentinel);
935 for (int i=0; i < numOptPars; i++) {
936 optParams[i].TypeSig(sig);
943 /**************************************************************************/
945 /// The IL instructions for a method
947 public class CILInstructions
950 private static readonly uint ExHeaderSize = 4;
951 private static readonly uint FatExClauseSize = 24;
952 private static readonly uint SmlExClauseSize = 12;
953 private static readonly sbyte maxByteVal = 127;
954 private static readonly sbyte minByteVal = -128;
955 private static readonly byte maxUByteVal = 255;
956 private static readonly int smallSize = 64;
957 private static readonly ushort TinyFormat = 0x2;
958 private static readonly ushort FatFormat = 0x3003;
959 private static readonly ushort MoreSects = 0x8;
960 private static readonly ushort InitLocals = 0x10;
961 private static readonly uint FatSize = 12;
962 private static readonly uint FatWords = FatSize/4;
963 private static readonly byte FatExceptTable = 0x41;
964 private static readonly byte SmlExceptTable = 0x01;
966 private MetaData metaData;
967 private ArrayList exceptions, blockStack;
968 //private bool codeChecked = false;
969 private static readonly int INITSIZE = 5;
970 private CILInstruction[] buffer = new CILInstruction[INITSIZE];
971 private int tide = 0;
972 private uint offset = 0;
973 private ushort headerFlags = 0;
974 private short maxStack;
975 private uint paddingNeeded = 0;
976 private byte exceptHeader = 0;
978 uint codeSize = 0, exceptSize = 0;
979 bool tinyFormat, fatExceptionFormat = false;
982 get { return offset; }
985 internal CILInstructions(MetaData md) {
989 private void AddToBuffer(CILInstruction inst) {
990 if (tide >= buffer.Length) {
991 CILInstruction[] tmp = buffer;
992 buffer = new CILInstruction[tmp.Length * 2];
993 for (int i=0; i < tide; i++) {
997 //Console.WriteLine("Adding instruction at offset " + offset + " with size " + inst.size);
998 inst.offset = offset;
1000 buffer[tide++] = inst;
1004 /// Add a simple IL instruction
1006 /// <param name="inst">the IL instruction</param>
1007 public void Inst(Op inst) {
1008 AddToBuffer(new Instr((int)inst));
1012 /// Add an IL instruction with an integer parameter
1014 /// <param name="inst">the IL instruction</param>
1015 /// <param name="val">the integer parameter value</param>
1016 public void IntInst(IntOp inst, int val) {
1017 int instr = (int)inst;
1018 if ((inst == IntOp.ldc_i4_s) || (inst == IntOp.ldc_i4))
1019 AddToBuffer(new IntInstr(instr,val,(inst == IntOp.ldc_i4_s)));
1021 AddToBuffer(new UIntInstr(instr,val,((inst < IntOp.ldc_i4_s) ||
1022 (inst == IntOp.unaligned))));
1026 /// Add the load long instruction
1028 /// <param name="cVal">the long value</param>
1029 public void ldc_i8(long cVal) {
1030 AddToBuffer(new LongInstr(0x21,cVal));
1034 /// Add the load float32 instruction
1036 /// <param name="cVal">the float value</param>
1037 public void ldc_r4(float cVal) {
1038 AddToBuffer(new FloatInstr(0x22,cVal));
1042 /// Add the load float64 instruction
1044 /// <param name="cVal">the float value</param>
1045 public void ldc_r8(double cVal) {
1046 AddToBuffer(new DoubleInstr(0x23,cVal));
1050 /// Add the load string instruction
1052 /// <param name="str">the string value</param>
1053 public void ldstr(string str) {
1054 AddToBuffer(new StringInstr(0x72,str));
1058 /// Add the load string instruction
1060 public void ldstr (byte[] str) {
1061 AddToBuffer (new StringInstr (0x72, str));
1065 /// Add the calli instruction
1067 /// <param name="sig">the signature for the calli</param>
1068 public void calli(CalliSig sig) {
1069 AddToBuffer(new SigInstr(0x29,sig));
1073 /// Add a label to the CIL instructions
1075 /// <param name="lab">the label to be added</param>
1076 public void CodeLabel(CILLabel lab) {
1077 AddToBuffer(new LabelInstr(lab));
1081 /// Add an instruction with a field parameter
1083 /// <param name="inst">the CIL instruction</param>
1084 /// <param name="f">the field parameter</param>
1085 public void FieldInst(FieldOp inst, Field f) {
1086 AddToBuffer(new FieldInstr((int)inst,f));
1090 /// Add an instruction with a method parameter
1092 /// <param name="inst">the CIL instruction</param>
1093 /// <param name="m">the method parameter</param>
1094 public void MethInst(MethodOp inst, Method m) {
1095 AddToBuffer(new MethInstr((int)inst,m));
1099 /// Add an instruction with a type parameter
1101 /// <param name="inst">the CIL instruction</param>
1102 /// <param name="t">the type argument for the CIL instruction</param>
1103 public void TypeInst(TypeOp inst, Type aType) {
1104 AddToBuffer(new TypeInstr((int)inst,aType,metaData));
1108 /// Add a branch instruction
1110 /// <param name="inst">the branch instruction</param>
1111 /// <param name="lab">the label that is the target of the branch</param>
1112 public void Branch(BranchOp inst, CILLabel lab) {
1113 AddToBuffer(new BranchInstr((int)inst,lab));
1117 /// Add a switch instruction
1119 /// <param name="labs">the target labels for the switch</param>
1120 public void Switch(CILLabel[] labs) {
1121 AddToBuffer(new SwitchInstr(0x45,labs));
1125 /// Add a byte to the CIL instructions (.emitbyte)
1127 /// <param name="bVal"></param>
1128 public void emitbyte(byte bVal) {
1129 AddToBuffer(new CILByte(bVal));
1133 /// Add an instruction which puts an integer on TOS. This method
1134 /// selects the correct instruction based on the value of the integer.
1136 /// <param name="i">the integer value</param>
1137 public void PushInt(int i) {
1139 AddToBuffer(new Instr((int)Op.ldc_i4_m1));
1140 } else if ((i >= 0) && (i <= 8)) {
1141 Op op = (Op)(Op.ldc_i4_0 + i);
1142 AddToBuffer(new Instr((int)op));
1143 } else if ((i >= minByteVal) && (i <= maxByteVal)) {
1144 AddToBuffer(new IntInstr((int)IntOp.ldc_i4_s,i,true));
1146 AddToBuffer(new IntInstr((int)IntOp.ldc_i4,i,false));
1151 /// Add the instruction to load a long on TOS
1153 /// <param name="l">the long value</param>
1154 public void PushLong(long l) {
1155 AddToBuffer(new LongInstr(0x21,l));
1159 /// Add an instruction to push the boolean value true on TOS
1161 public void PushTrue() {
1162 AddToBuffer(new Instr((int)Op.ldc_i4_1));
1166 /// Add an instruction to push the boolean value false on TOS
1168 public void PushFalse() {
1169 AddToBuffer(new Instr((int)Op.ldc_i4_0));
1173 /// Add the instruction to load an argument on TOS. This method
1174 /// selects the correct instruction based on the value of argNo
1176 /// <param name="argNo">the number of the argument</param>
1177 public void LoadArg(int argNo) {
1179 int op = (int)Op.ldarg_0 + argNo;
1180 AddToBuffer(new Instr(op));
1181 } else if (argNo <= maxUByteVal) {
1182 AddToBuffer(new UIntInstr((int)IntOp.ldarg,argNo,true));
1184 AddToBuffer(new UIntInstr(0x09,argNo,false));
1189 /// Add the instruction to load the address of an argument on TOS.
1190 /// This method selects the correct instruction based on the value
1193 /// <param name="argNo">the number of the argument</param>
1194 public void LoadArgAdr(int argNo) {
1195 if (argNo <= maxUByteVal) {
1196 AddToBuffer(new UIntInstr((int)IntOp.ldarga,argNo,true));
1198 AddToBuffer(new UIntInstr(0x0A,argNo,false));
1203 /// Add the instruction to load a local on TOS. This method selects
1204 /// the correct instruction based on the value of locNo.
1206 /// <param name="locNo">the number of the local to load</param>
1207 public void LoadLocal(int locNo) {
1209 int op = (int)Op.ldloc_0 + locNo;
1210 AddToBuffer(new Instr(op));
1211 } else if (locNo <= maxUByteVal) {
1212 AddToBuffer(new UIntInstr((int)IntOp.ldloc,locNo,true));
1214 AddToBuffer(new UIntInstr(0x0C,locNo,false));
1219 /// Add the instruction to load the address of a local on TOS.
1220 /// This method selects the correct instruction based on the
1223 /// <param name="locNo">the number of the local</param>
1224 public void LoadLocalAdr(int locNo) {
1225 if (locNo <= maxUByteVal) {
1226 AddToBuffer(new UIntInstr((int)IntOp.ldloca,locNo,true));
1228 AddToBuffer(new UIntInstr(0x0D,locNo,false));
1233 /// Add the instruction to store to an argument. This method
1234 /// selects the correct instruction based on the value of argNo.
1236 /// <param name="argNo">the argument to be stored to</param>
1237 public void StoreArg(int argNo) {
1238 if (argNo <= maxUByteVal) {
1239 AddToBuffer(new UIntInstr((int)IntOp.starg,argNo,true));
1241 AddToBuffer(new UIntInstr(0x0B,argNo,false));
1246 /// Add the instruction to store to a local. This method selects
1247 /// the correct instruction based on the value of locNo.
1249 /// <param name="locNo">the local to be stored to</param>
1250 public void StoreLocal(int locNo) {
1252 int op = (int)Op.stloc_0 + locNo;
1253 AddToBuffer(new Instr(op));
1254 } else if (locNo <= maxUByteVal) {
1255 AddToBuffer(new UIntInstr((int)IntOp.stloc,locNo,true));
1257 AddToBuffer(new UIntInstr(0x0E,locNo,false));
1262 /// Create a new CIL label. To place the label in the CIL instruction
1263 /// stream use CodeLabel.
1265 /// <returns>a new CIL label</returns>
1266 public CILLabel NewLabel() {
1267 return new CILLabel();
1270 public void AddTryBlock(TryBlock tryBlock) {
1271 if (exceptions == null)
1272 exceptions = new ArrayList();
1273 else if (exceptions.Contains(tryBlock)) return;
1274 exceptions.Add(tryBlock);
1278 /// Create a new label at this position in the code buffer
1280 /// <returns>the label at the current position</returns>
1281 public CILLabel NewCodedLabel() {
1282 CILLabel lab = new CILLabel();
1283 AddToBuffer(new LabelInstr(lab));
1288 /// Mark this position as the start of a new block
1289 /// (try, catch, filter, finally or fault)
1291 public void StartBlock() {
1292 if (blockStack == null) blockStack = new ArrayList();
1293 blockStack.Insert(0,NewCodedLabel());
1297 /// Mark this position as the end of the last started block and
1298 /// make it a try block. This try block is added to the current
1299 /// instructions (ie do not need to call AddTryBlock)
1301 /// <returns>The try block just ended</returns>
1302 public TryBlock EndTryBlock() {
1303 TryBlock tBlock = new TryBlock((CILLabel)blockStack[0],NewCodedLabel());
1304 blockStack.RemoveAt(0);
1305 AddTryBlock(tBlock);
1310 /// Mark this position as the end of the last started block and
1311 /// make it a catch block. This catch block is associated with the
1312 /// specified try block.
1314 /// <param name="exceptType">the exception type to be caught</param>
1315 /// <param name="tryBlock">the try block associated with this catch block</param>
1316 public void EndCatchBlock(Class exceptType, TryBlock tryBlock) {
1317 Catch catchBlock = new Catch(exceptType,(CILLabel)blockStack[0],
1319 tryBlock.AddHandler(catchBlock);
1323 /// Mark this position as the end of the last started block and
1324 /// make it a filter block. This filter block is associated with the
1325 /// specified try block.
1327 /// <param name="filterLab">the label where the filter code is</param>
1328 /// <param name="tryBlock">the try block associated with this filter block</param>
1329 public void EndFilterBlock(CILLabel filterLab, TryBlock tryBlock) {
1330 Filter filBlock = new Filter(filterLab,(CILLabel)blockStack[0],NewCodedLabel());
1331 tryBlock.AddHandler(filBlock);
1335 /// Mark this position as the end of the last started block and
1336 /// make it a finally block. This finally block is associated with the
1337 /// specified try block.
1339 /// <param name="tryBlock">the try block associated with this finally block</param>
1340 public void EndFinallyBlock(TryBlock tryBlock) {
1341 Finally finBlock= new Finally((CILLabel)blockStack[0],NewCodedLabel());
1342 tryBlock.AddHandler(finBlock);
1346 /// Mark this position as the end of the last started block and
1347 /// make it a fault block. This fault block is associated with the
1348 /// specified try block.
1350 /// <param name="tryBlock">the try block associated with this fault block</param>
1351 public void EndFaultBlock(TryBlock tryBlock) {
1352 Fault fBlock= new Fault((CILLabel)blockStack[0],NewCodedLabel());
1353 tryBlock.AddHandler(fBlock);
1356 internal uint GetCodeSize() {
1357 return codeSize + paddingNeeded + exceptSize;
1360 internal void CheckCode(uint locSigIx, bool initLocals, int maxStack) {
1361 if (tide == 0) return;
1362 bool changed = true;
1365 for (int i=0; i < tide; i++) {
1366 changed = buffer[i].Check(metaData) || changed;
1369 for (int i=1; i < tide; i++) {
1370 buffer[i].offset = buffer[i-1].offset + buffer[i-1].size;
1372 offset = buffer[tide-1].offset + buffer[tide-1].size;
1376 // Console.WriteLine("codeSize before header added = " + codeSize);
1377 if ((offset < smallSize) && (maxStack <= 8) && (locSigIx == 0) && (exceptions == null)) {
1378 // can use tiny header
1379 //Console.WriteLine("Tiny Header");
1381 headerFlags = (ushort)(TinyFormat | ((ushort)codeSize << 2));
1383 if ((codeSize % 4) != 0) { paddingNeeded = 4 - (codeSize % 4); }
1385 //Console.WriteLine("Fat Header");
1387 localSigIx = locSigIx;
1388 this.maxStack = (short)maxStack;
1389 headerFlags = FatFormat;
1390 if (exceptions != null) {
1391 // Console.WriteLine("Got exceptions");
1392 headerFlags |= MoreSects;
1393 uint numExceptClauses = 0;
1394 for (int i=0; i < exceptions.Count; i++) {
1395 TryBlock tryBlock = (TryBlock)exceptions[i];
1397 numExceptClauses += (uint)tryBlock.NumHandlers();
1398 if (tryBlock.isFat()) fatExceptionFormat = true;
1401 uint data_size = ExHeaderSize + numExceptClauses *
1402 (fatExceptionFormat ? FatExClauseSize : SmlExClauseSize);
1404 if (data_size > 256)
1405 fatExceptionFormat = true;
1407 // Console.WriteLine("numexceptclauses = " + numExceptClauses);
1408 if (fatExceptionFormat) {
1409 // Console.WriteLine("Fat exception format");
1410 exceptHeader = FatExceptTable;
1411 exceptSize = ExHeaderSize + numExceptClauses * FatExClauseSize;
1413 // Console.WriteLine("Tiny exception format");
1414 exceptHeader = SmlExceptTable;
1415 exceptSize = ExHeaderSize + numExceptClauses * SmlExClauseSize;
1417 // Console.WriteLine("exceptSize = " + exceptSize);
1419 if (initLocals) headerFlags |= InitLocals;
1420 if ((offset % 4) != 0) { paddingNeeded = 4 - (offset % 4); }
1421 codeSize += FatSize;
1423 // Console.WriteLine("codeSize = " + codeSize + " headerFlags = " +
1424 // Hex.Short(headerFlags));
1427 internal void Write(FileImage output) {
1428 // Console.WriteLine("Writing header flags = " + Hex.Short(headerFlags));
1430 // Console.WriteLine("Writing tiny code");
1431 output.Write((byte)headerFlags);
1433 // Console.WriteLine("Writing fat code");
1434 output.Write(headerFlags);
1435 output.Write((ushort)maxStack);
1436 output.Write(offset);
1437 output.Write(localSigIx);
1439 // Console.WriteLine(Hex.Int(tide) + " CIL instructions");
1440 // Console.WriteLine("starting instructions at " + output.Seek(0,SeekOrigin.Current));
1441 for (int i=0; i < tide; i++) {
1442 buffer[i].Write(output);
1444 // Console.WriteLine("ending instructions at " + output.Seek(0,SeekOrigin.Current));
1445 for (int i=0; i < paddingNeeded; i++) { output.Write((byte)0); }
1446 if (exceptions != null) {
1447 // Console.WriteLine("Writing exceptions");
1448 // Console.WriteLine("header = " + Hex.Short(exceptHeader) + " exceptSize = " + Hex.Int(exceptSize));
1449 output.Write(exceptHeader);
1450 output.Write3Bytes((uint)exceptSize);
1451 for (int i=0; i < exceptions.Count; i++) {
1452 TryBlock tryBlock = (TryBlock)exceptions[i];
1453 tryBlock.Write(output,fatExceptionFormat);
1459 /**************************************************************************/
1461 /// A label in the IL
1463 public class CILLabel
1465 CILInstruction branch;
1466 CILInstruction[] multipleBranches;
1468 CILInstruction labInstr;
1471 public CILLabel (uint offset) {
1472 this.offset = offset;
1476 internal CILLabel() {
1479 internal void AddBranch(CILInstruction instr) {
1480 if (branch == null) {
1484 if (multipleBranches == null) {
1485 multipleBranches = new CILInstruction[2];
1486 } else if (tide >= multipleBranches.Length) {
1487 CILInstruction[] tmp = multipleBranches;
1488 multipleBranches = new CILInstruction[tmp.Length*2];
1489 for (int i=0; i < tide; i++) {
1490 multipleBranches[i] = tmp[i];
1493 multipleBranches[tide++] = instr;
1496 internal void AddLabelInstr(LabelInstr lInstr) {
1500 internal uint GetLabelOffset() {
1501 if (labInstr == null) return 0;
1502 return labInstr.offset + offset;
1506 /**************************************************************************/
1507 public abstract class CodeBlock {
1509 private static readonly int maxCodeSize = 256;
1510 protected CILLabel start, end;
1511 protected bool small = true;
1513 public CodeBlock(CILLabel start, CILLabel end) {
1518 internal virtual bool isFat() {
1519 // Console.WriteLine("block start = " + start.GetLabelOffset() +
1520 // " block end = " + end.GetLabelOffset());
1521 return (end.GetLabelOffset() - start.GetLabelOffset()) > maxCodeSize;
1524 internal virtual void Write(FileImage output, bool fatFormat) {
1525 if (fatFormat) output.Write(start.GetLabelOffset());
1526 else output.Write((short)start.GetLabelOffset());
1527 uint len = end.GetLabelOffset() - start.GetLabelOffset();
1528 if (fatFormat) output.Write(len);
1529 else output.Write((byte)len);
1535 /// The descriptor for a guarded block (.try)
1537 public class TryBlock : CodeBlock {
1538 protected bool fatFormat = false;
1539 protected int flags = 0;
1540 ArrayList handlers = new ArrayList();
1543 /// Create a new try block
1545 /// <param name="start">start label for the try block</param>
1546 /// <param name="end">end label for the try block</param>
1547 public TryBlock(CILLabel start, CILLabel end) : base(start,end) { }
1550 /// Add a handler to this try block
1552 /// <param name="handler">a handler to be added to the try block</param>
1553 public void AddHandler(HandlerBlock handler) {
1554 flags = handler.GetFlag();
1555 handlers.Add(handler);
1558 internal void SetSize() {
1559 fatFormat = base.isFat();
1560 if (fatFormat) return;
1561 for (int i=0; i < handlers.Count; i++) {
1562 HandlerBlock handler = (HandlerBlock)handlers[i];
1563 if (handler.isFat()) {
1570 internal int NumHandlers() {
1571 return handlers.Count;
1574 internal override bool isFat() {
1578 internal override void Write(FileImage output, bool fatFormat) {
1579 // Console.WriteLine("writing exception details");
1580 for (int i=0; i < handlers.Count; i++) {
1581 // Console.WriteLine("Except block " + i);
1582 HandlerBlock handler = (HandlerBlock)handlers[i];
1583 if (fatFormat) output.Write(flags);
1584 else output.Write((short)flags);
1585 // Console.WriteLine("flags = " + Hex.Short(flags));
1586 base.Write(output,fatFormat);
1587 handler.Write(output,fatFormat);
1592 public abstract class HandlerBlock : CodeBlock
1594 protected static readonly short ExceptionFlag = 0;
1595 protected static readonly short FilterFlag = 0x01;
1596 protected static readonly short FinallyFlag = 0x02;
1597 protected static readonly short FaultFlag = 0x04;
1599 public HandlerBlock(CILLabel start, CILLabel end) : base(start,end) { }
1601 internal virtual short GetFlag() { return ExceptionFlag; }
1603 internal override void Write(FileImage output, bool fatFormat) {
1604 base.Write(output,fatFormat);
1610 /// The descriptor for a catch clause (.catch)
1612 public class Catch : HandlerBlock
1617 /// Create a new catch clause
1619 /// <param name="except">the exception to be caught</param>
1620 /// <param name="handlerStart">start of the handler code</param>
1621 /// <param name="handlerEnd">end of the handler code</param>
1622 public Catch(Class except, CILLabel handlerStart, CILLabel handlerEnd)
1623 : base(handlerStart,handlerEnd) {
1624 exceptType = except;
1627 internal override void Write(FileImage output, bool fatFormat) {
1628 base.Write(output,fatFormat);
1629 output.Write(exceptType.Token());
1634 /// The descriptor for a filter clause (.filter)
1636 public class Filter : HandlerBlock
1638 CILLabel filterLabel;
1641 /// Create a new filter clause
1643 /// <param name="filterLabel">the label where the filter code starts</param>
1644 /// <param name="handlerStart">the start of the handler code</param>
1645 /// <param name="handlerEnd">the end of the handler code</param>
1646 public Filter(CILLabel filterLabel, CILLabel handlerStart,
1647 CILLabel handlerEnd) : base(handlerStart,handlerEnd) {
1648 this.filterLabel = filterLabel;
1651 internal override short GetFlag() {
1655 internal override void Write(FileImage output, bool fatFormat) {
1656 base.Write(output,fatFormat);
1657 output.Write(filterLabel.GetLabelOffset());
1663 /// Descriptor for a finally block (.finally)
1665 public class Finally : HandlerBlock
1668 /// Create a new finally clause
1670 /// <param name="finallyStart">start of finally code</param>
1671 /// <param name="finallyEnd">end of finally code</param>
1672 public Finally(CILLabel finallyStart, CILLabel finallyEnd)
1673 : base(finallyStart,finallyEnd) { }
1675 internal override short GetFlag() {
1679 internal override void Write(FileImage output, bool fatFormat) {
1680 base.Write(output,fatFormat);
1681 output.Write((int)0);
1687 /// Descriptor for a fault block (.fault)
1689 public class Fault : HandlerBlock
1692 /// Create a new fault clause
1694 /// <param name="faultStart">start of the fault code</param>
1695 /// <param name="faultEnd">end of the fault code</param>
1696 public Fault(CILLabel faultStart, CILLabel faultEnd)
1697 : base(faultStart,faultEnd) { }
1699 internal override short GetFlag() {
1703 internal override void Write(FileImage output, bool fatFormat) {
1704 base.Write(output,fatFormat);
1705 output.Write((int)0);
1710 /**************************************************************************/
1712 /// The base descriptor for a class
1714 public abstract class Class : Type
1716 protected int row = 0;
1717 public string name, nameSpace;
1718 protected uint nameIx, nameSpaceIx;
1719 protected MetaData _metaData;
1720 internal Class(string nameSpaceName, string className, MetaData md)
1721 : base(PrimitiveType.Class.GetTypeIndex ()) {
1722 nameSpace = nameSpaceName;
1724 nameIx = md.AddToStringsHeap(name);
1725 nameSpaceIx = md.AddToStringsHeap(nameSpace);
1729 internal Class(uint nsIx, uint nIx) : base(PrimitiveType.Class.GetTypeIndex ()) {
1734 internal virtual uint TypeDefOrRefToken() { return 0; }
1736 internal virtual void MakeValueClass(ValueClass vClass) {
1737 typeIndex = PrimitiveType.ValueType.GetTypeIndex ();
1740 internal virtual string TypeName() {
1741 return (nameSpace + "." + name);
1744 internal override MetaDataElement GetTypeSpec(MetaData md) {
1748 /**************************************************************************/
1749 // This Class produces entries in the TypeDef table of the MetaData
1750 // in the PE meta data.
1752 // NOTE: Entry 0 in TypeDef table is always the pseudo class <module>
1753 // which is the parent for functions and variables declared a module level
1756 /// The descriptor for a class defined in the IL (.class) in the current assembly/module
1759 public class ClassDef : Class
1761 private static readonly uint HasSecurity = 0x00040000;
1762 private static readonly byte ElementType_Class = 0x12;
1765 ArrayList fields = new ArrayList();
1766 ArrayList methods = new ArrayList();
1768 ArrayList properties;
1769 bool typeIndexChecked = true;
1770 uint fieldIx = 0, methodIx = 0;
1771 byte[] securityActions;
1774 ClassDef parentClass;
1777 internal ClassDef(TypeAttr attrSet, string nsName, string name,
1778 MetaData md) : base(nsName, name, md) {
1780 superType = metaData.mscorlib.GetSpecialSystemClass(PrimitiveType.Object);
1781 flags = (uint)attrSet;
1782 tabIx = MDTable.TypeDef;
1785 internal void SetSuper(Class sClass) {
1787 if (sClass is ClassRef)
1788 typeIndex = superType.GetTypeIndex();
1790 typeIndexChecked = false;
1793 internal override void MakeValueClass(ValueClass vClass) {
1794 if (vClass == ValueClass.Enum)
1795 superType = metaData.mscorlib.EnumType();
1797 superType = metaData.mscorlib.ValueType();
1799 typeIndex = superType.GetTypeIndex();
1802 public void SpecialNoSuper() {
1807 /// Add an attribute to this class
1809 /// <param name="ta">the attribute to be added</param>
1810 public void AddAttribute(TypeAttr ta) {
1815 /// Add an interface that is implemented by this class
1817 /// <param name="iFace">the interface that is implemented</param>
1818 public void AddImplementedInterface(Class iFace) {
1819 metaData.AddToTable(MDTable.InterfaceImpl,new InterfaceImpl(this,iFace));
1823 /// Add a named generic type parameter
1825 public GenericParameter AddGenericParameter (short index, string name) {
1826 GenericParameter gp = new GenericParameter (this, metaData, index, name);
1827 metaData.AddToTable (MDTable.GenericParam, gp);
1832 /// Add a field to this class
1834 /// <param name="name">field name</param>
1835 /// <param name="fType">field type</param>
1836 /// <returns>a descriptor for this new field</returns>
1837 public FieldDef AddField(string name, Type fType) {
1838 FieldDef field = new FieldDef(name,fType);
1844 /// Add a field to this class
1846 /// <param name="fAtts">attributes for this field</param>
1847 /// <param name="name">field name</param>
1848 /// <param name="fType">field type</param>
1849 /// <returns>a descriptor for this new field</returns>
1850 public FieldDef AddField(FieldAttr fAtts, string name, Type fType) {
1851 FieldDef field = new FieldDef(fAtts,name,fType);
1856 public void SetFieldOrder (ArrayList fields)
1858 this.fields = fields;
1862 /// Add a method to this class
1864 /// <param name="name">method name</param>
1865 /// <param name="retType">return type</param>
1866 /// <param name="pars">parameters</param>
1867 /// <returns>a descriptor for this new method</returns>
1868 public MethodDef AddMethod(string name, Type retType, Param[] pars) {
1869 // Console.WriteLine("Adding method " + name + " to class " + this.name);
1870 MethodDef meth = new MethodDef(metaData,name,retType, pars);
1876 /// Add a method to this class
1878 /// <param name="mAtts">attributes for this method</param>
1879 /// <param name="iAtts">implementation attributes for this method</param>
1880 /// <param name="name">method name</param>
1881 /// <param name="retType">return type</param>
1882 /// <param name="pars">parameters</param>
1883 /// <returns>a descriptor for this new method</returns>
1884 public MethodDef AddMethod(MethAttr mAtts, ImplAttr iAtts, string name,
1885 Type retType, Param[] pars) {
1886 // Console.WriteLine("Adding method " + name + " to class " + this.name);
1887 MethodDef meth = new MethodDef(metaData,mAtts,iAtts,name,retType,pars);
1893 /// Add an event to this class
1895 /// <param name="name">event name</param>
1896 /// <param name="eType">event type</param>
1897 /// <returns>a descriptor for this new event</returns>
1898 public Event AddEvent(string name, Type eType) {
1899 Event e = new Event(name,eType,this);
1900 if (events == null) events = new ArrayList();
1906 /// Add a property to this class
1908 /// <param name="name">property name</param>
1909 /// <param name="propType">property type</param>
1910 /// <returns>a descriptor for this new property</returns>
1911 public Property AddProperty(string name, Type retType, Type[] pars) {
1912 Property p = new Property(name, retType, pars, this);
1913 if (properties == null) properties = new ArrayList();
1920 /// Add a nested class to this class
1922 /// <param name="attrSet">attributes for this nested class</param>
1923 /// <param name="nsName">nested name space name</param>
1924 /// <param name="name">nested class name</param>
1925 /// <returns>a descriptor for this new nested class</returns>
1926 public ClassDef AddNestedClass(TypeAttr attrSet, string nsName,
1928 ClassDef nClass = new ClassDef(attrSet,"",name,metaData);
1929 metaData.AddToTable(MDTable.TypeDef,nClass);
1930 metaData.AddToTable(MDTable.NestedClass,new MapElem(nClass,Row,MDTable.TypeDef));
1931 nClass.parentClass = this;
1934 public static bool IsValueType (Class type)
1936 return IsValueType (type.nameSpace, type.name);
1939 public static bool IsEnum (Class type)
1941 return IsEnum (type.nameSpace, type.name);
1944 public static bool IsValueType (string nsName, string name)
1946 return ((nsName.CompareTo ("System") == 0) &&
1947 (name.CompareTo ("ValueType") == 0));
1950 public static bool IsEnum (string nsName, string name)
1952 return ((nsName.CompareTo ("System") == 0) &&
1953 (name.CompareTo ("Enum") == 0));
1957 /// Add a nested class to this class
1959 /// <param name="attrSet">attributes for this nested class</param>
1960 /// <param name="nsName">nested name space name</param>
1961 /// <param name="name">nested class name</param>
1962 /// <param name="sType">super type of this nested class</param>
1963 /// <returns>a descriptor for this new nested class</returns>
1964 public ClassDef AddNestedClass(TypeAttr attrSet, string nsName,
1965 string name, Class sType) {
1966 ClassDef nClass = AddNestedClass (attrSet, nsName, name);
1967 nClass.SetSuper(sType);
1968 if (ClassDef.IsValueType (sType))
1969 nClass.MakeValueClass (ValueClass.ValueType);
1971 if (ClassDef.IsEnum (sType))
1972 nClass.MakeValueClass (ValueClass.Enum);
1974 if (ClassDef.IsValueType (sType) || ClassDef.IsEnum (sType))
1975 nClass.SetTypeIndex (PrimitiveType.ValueType.GetTypeIndex ());
1981 /// Add layout information for this class. This class must have the
1982 /// sequential or explicit attribute.
1984 /// <param name="packSize">packing size (.pack)</param>
1985 /// <param name="classSize">class size (.size)</param>
1986 public void AddLayoutInfo (int packSize, int classSize) {
1987 layout = new ClassLayout(packSize,classSize,this);
1991 /// Use a method as the implementation for another method (.override)
1993 /// <param name="decl">the method to be overridden</param>
1994 /// <param name="body">the implementation to be used</param>
1995 public void AddMethodOverride(Method decl, Method body) {
1996 metaData.AddToTable(MDTable.MethodImpl,new MethodImpl(this,decl,body));
2000 /// Add security to this class NOT YET IMPLEMENTED
2002 /// <param name="permissionSet"></param>
2003 public void AddSecurity(byte[] permissionSet) {
2004 throw(new NotYetImplementedException("Class security "));
2005 //flags |= HasSecurity;
2006 // securityActions = permissionSet;
2009 //public void AddLineInfo(int row, int col) { }
2011 internal void CheckTypeIndex() {
2012 if (typeIndexChecked) return;
2013 if (!(superType is ClassRef))
2014 ((ClassDef)superType).CheckTypeIndex();
2015 typeIndex = superType.GetTypeIndex();
2016 typeIndexChecked = true;
2019 internal sealed override void BuildTables(MetaData md) {
2021 if ((flags & (uint)TypeAttr.Interface) != 0) { superType = null; }
2022 // Console.WriteLine("Building tables for " + name);
2023 if (layout != null) md.AddToTable(MDTable.ClassLayout,layout);
2024 // Console.WriteLine("adding methods " + methods.Count);
2025 methodIx = md.TableIndex(MDTable.Method);
2026 for (int i=0; i < methods.Count; i++) {
2027 md.AddToTable(MDTable.Method,(MetaDataElement)methods[i]);
2028 ((MethodDef)methods[i]).BuildTables(md);
2030 // Console.WriteLine("adding fields");
2031 fieldIx = md.TableIndex(MDTable.Field);
2032 for (int i=0; i < fields.Count; i++) {
2033 md.AddToTable(MDTable.Field,(MetaDataElement)fields[i]);
2034 ((FieldDef)fields[i]).BuildTables(md);
2036 // Console.WriteLine("adding events and properties");
2037 if (events != null) {
2038 for (int i=0; i < events.Count; i++) {
2039 md.AddToTable(MDTable.Event,(Event)events[i]);
2040 ((Event)events[i]).BuildTables(md);
2042 md.AddToTable(MDTable.EventMap,
2043 new MapElem(this,((Event)events[0]).Row,MDTable.Event));
2045 if (properties != null) {
2046 for (int i=0; i < properties.Count; i++) {
2047 md.AddToTable(MDTable.Property,(Property)properties[i]);
2048 ((Property)properties[i]).BuildTables(md);
2050 md.AddToTable(MDTable.PropertyMap,new MapElem(this,
2051 ((Property)properties[0]).Row,MDTable.Property));
2053 // Console.WriteLine("End of building tables");
2057 internal sealed override uint Size(MetaData md) {
2058 return 4 + 2 * md.StringsIndexSize() +
2059 md.CodedIndexSize(CIx.TypeDefOrRef) +
2060 md.TableIndexSize(MDTable.Field) +
2061 md.TableIndexSize(MDTable.Method);
2064 internal sealed override void Write(FileImage output) {
2065 output.Write(flags);
2066 output.StringsIndex(nameIx);
2067 output.StringsIndex(nameSpaceIx);
2068 //if (superType != null)
2069 // Console.WriteLine("getting coded index for superType of " + name + " = " + superType.GetCodedIx(CIx.TypeDefOrRef));
2070 output.WriteCodedIndex(CIx.TypeDefOrRef,superType);
2071 output.WriteIndex(MDTable.Field,fieldIx);
2072 output.WriteIndex(MDTable.Method,methodIx);
2075 internal sealed override uint TypeDefOrRefToken() {
2081 internal sealed override void TypeSig(MemoryStream sig) {
2082 if (!typeIndexChecked) CheckTypeIndex();
2083 sig.WriteByte(GetTypeIndex());
2084 MetaData.CompressNum(TypeDefOrRefToken(),sig);
2087 internal sealed override uint GetCodedIx(CIx code) {
2089 case (CIx.TypeDefOrRef) : return 0;
2090 case (CIx.HasCustomAttr) : return 3;
2091 case (CIx.HasDeclSecurity) : return 0;
2092 case (CIx.TypeOrMethodDef) : return 0;
2098 /**************************************************************************/
2100 /// Layout information for a class (.class [sequential | explicit])
2102 internal class ClassLayout : MetaDataElement
2105 ushort packSize = 0;
2108 internal ClassLayout(int pack, int cSize, ClassDef par) {
2109 packSize = (ushort)pack;
2110 classSize = (uint)cSize;
2112 tabIx = MDTable.ClassLayout;
2115 internal sealed override uint Size(MetaData md) {
2116 return 6 + md.TableIndexSize(MDTable.TypeDef);
2119 internal sealed override void Write(FileImage output) {
2120 output.Write(packSize);
2121 output.Write(classSize);
2122 output.WriteIndex(MDTable.TypeDef,parent.Row);
2126 /**************************************************************************/
2128 /// Descriptor for a class/interface declared in another module of THIS
2129 /// assembly, or in another assembly.
2131 public class ClassRef : Class
2133 protected ResolutionScope parent;
2134 ExternClass externClass;
2135 protected MetaData metaData;
2137 internal ClassRef(string nsName, string name, MetaData md) : base(nsName, name, md) {
2139 tabIx = MDTable.TypeRef;
2143 /// Add a method to this class
2145 /// <param name="name">method name</param>
2146 /// <param name="retType">return type</param>
2147 /// <param name="pars">parameter types</param>
2148 /// <returns>a descriptor for this method</returns>
2149 public MethodRef AddMethod(string name, Type retType, Type[] pars) {
2150 MethodRef meth = new MethodRef(this,name,retType,pars,false,null);
2151 metaData.AddToTable(MDTable.MemberRef,meth);
2156 /// Add a method to this class
2158 /// <param name="name">method name</param>
2159 /// <param name="retType">return type</param>
2160 /// <param name="pars">parameter types</param>
2161 /// <returns>a descriptor for this method</returns>
2162 public MethodRef AddVarArgMethod(string name, Type retType,
2163 Type[] pars, Type[] optPars) {
2164 MethodRef meth = new MethodRef(this,name,retType,pars,true,optPars);
2165 metaData.AddToTable(MDTable.MemberRef,meth);
2170 /// Add a field to this class
2172 /// <param name="name">field name</param>
2173 /// <param name="fType">field type</param>
2174 /// <returns>a descriptor for this field</returns>
2175 public FieldRef AddField(string name, Type fType) {
2176 FieldRef field = new FieldRef(this,name,fType);
2177 metaData.AddToTable(MDTable.MemberRef,field);
2181 internal void SetParent(ResolutionScope par) {
2185 internal override string TypeName() {
2186 if ((parent != null) && (parent is AssemblyRef))
2187 return (nameSpace + "." + name + ", " + ((AssemblyRef)parent).TypeName());
2189 return (nameSpace + name);
2192 internal sealed override uint Size(MetaData md) {
2193 return md.CodedIndexSize(CIx.ResolutionScope) + 2 *
2194 md.StringsIndexSize();
2197 internal sealed override void Write(FileImage output) {
2198 output.WriteCodedIndex(CIx.ResolutionScope,parent);
2199 output.StringsIndex(nameIx);
2200 output.StringsIndex(nameSpaceIx);
2203 internal override sealed uint TypeDefOrRefToken() {
2205 cIx = (cIx << 2) | 0x1;
2209 internal override void TypeSig(MemoryStream sig) {
2210 sig.WriteByte(GetTypeIndex());
2211 MetaData.CompressNum(TypeDefOrRefToken(),sig);
2214 internal sealed override uint GetCodedIx(CIx code) {
2216 case (CIx.TypeDefOrRef) : return 1;
2217 case (CIx.HasCustomAttr) : return 2;
2218 case (CIx.MemberRefParent) : return 1;
2219 case (CIx.ResolutionScope) : return 3;
2225 /**************************************************************************/
2227 public class ExternClassRef : ClassRef {
2229 ExternClass externClass;
2231 internal ExternClassRef(TypeAttr attrs, string nsName, string name,
2232 FileRef declFile, MetaData md) : base(nsName,name,md) {
2233 externClass = new ExternClass(attrs,nameSpaceIx,nameIx,declFile);
2234 metaData.AddToTable(MDTable.ExportedType,externClass);
2237 internal ExternClassRef(string name, MetaData md) : base(null,name,md) {
2240 public ClassRef AddNestedClass(TypeAttr attrs, string name) {
2241 ExternClassRef nestedClass = new ExternClassRef(name,metaData);
2242 externClass = new ExternClass(attrs,0,nameIx,this.externClass);
2243 metaData.AddToTable(MDTable.ExportedType,externClass);
2248 /**************************************************************************/
2250 /// Descriptor for a constant value
2252 public abstract class Constant {
2253 protected uint size = 0;
2254 protected Type type;
2255 protected uint blobIndex;
2256 protected bool addedToBlobHeap = false;
2258 internal Constant() { }
2260 internal virtual uint GetBlobIndex(MetaData md) { return 0; }
2262 internal uint GetSize() { return size; }
2264 internal byte GetTypeIndex() { return type.GetTypeIndex(); }
2266 internal virtual void Write(BinaryWriter bw) { }
2270 /// Descriptor for a constant value
2272 public abstract class DataConstant : Constant {
2273 private uint dataOffset = 0;
2275 internal DataConstant() { }
2277 public uint DataOffset {
2278 get { return dataOffset; }
2279 set { dataOffset = value; }
2285 /// Boolean constant
2287 public class BoolConst : Constant {
2291 /// Create a new boolean constant with the value "val"
2293 /// <param name="val">value of this boolean constant</param>
2294 public BoolConst(bool val) {
2297 type = PrimitiveType.Boolean;
2300 internal sealed override uint GetBlobIndex(MetaData md) {
2301 if (!addedToBlobHeap) {
2302 if (val) blobIndex = md.AddToBlobHeap((sbyte)1);
2303 else blobIndex = md.AddToBlobHeap((sbyte)0);
2304 addedToBlobHeap = true;
2309 internal sealed override void Write(BinaryWriter bw) {
2310 if (val) bw.Write((sbyte)1);
2311 else bw.Write((sbyte)0);
2316 public class ByteArrConst : DataConstant {
2319 public ByteArrConst(byte[] val) {
2320 type = PrimitiveType.String;
2322 size = (uint)val.Length;
2326 get { return type; }
2327 set { type = value; }
2330 internal sealed override uint GetBlobIndex(MetaData md) {
2331 if (!addedToBlobHeap) {
2332 blobIndex = md.AddToBlobHeap(val);
2333 addedToBlobHeap = true;
2338 internal sealed override void Write(BinaryWriter bw) {
2344 public class CharConst : Constant {
2347 public CharConst(char val) {
2350 type = PrimitiveType.Char;
2353 internal sealed override uint GetBlobIndex(MetaData md) {
2354 if (!addedToBlobHeap) {
2355 blobIndex = md.AddToBlobHeap(val);
2356 addedToBlobHeap = true;
2361 internal sealed override void Write(BinaryWriter bw) {
2367 public class FloatConst : DataConstant {
2370 public FloatConst(float val) {
2373 type = PrimitiveType.Float32;
2376 internal sealed override uint GetBlobIndex(MetaData md) {
2377 if (!addedToBlobHeap) {
2378 blobIndex = md.AddToBlobHeap(val);
2379 addedToBlobHeap = true;
2384 internal sealed override void Write(BinaryWriter bw) {
2390 public class DoubleConst : DataConstant {
2393 public DoubleConst(double val) {
2396 type = PrimitiveType.Float64;
2399 internal sealed override uint GetBlobIndex(MetaData md) {
2400 if (!addedToBlobHeap) {
2401 blobIndex = md.AddToBlobHeap(val);
2402 addedToBlobHeap = true;
2407 internal sealed override void Write(BinaryWriter bw) {
2413 public class IntConst : DataConstant {
2416 public IntConst(sbyte val) {
2419 type = PrimitiveType.Int8;
2422 public IntConst(short val) {
2425 type = PrimitiveType.Int16;
2428 public IntConst(int val) {
2431 type = PrimitiveType.Int32;
2434 public IntConst(long val) {
2437 type = PrimitiveType.Int64;
2440 internal sealed override uint GetBlobIndex(MetaData md) {
2441 if (!addedToBlobHeap) {
2443 case (1) : blobIndex = md.AddToBlobHeap((sbyte)val); break;
2444 case (2) : blobIndex = md.AddToBlobHeap((short)val); break;
2445 case (4) : blobIndex = md.AddToBlobHeap((int)val); break;
2446 default : blobIndex = md.AddToBlobHeap(val); break;
2448 addedToBlobHeap = true;
2453 internal sealed override void Write(BinaryWriter bw) {
2455 case (1) : bw.Write((sbyte)val); break;
2456 case (2) : bw.Write((short)val); break;
2457 case (4) : bw.Write((int)val); break;
2458 default : bw.Write(val); break;
2464 public class UIntConst : Constant {
2467 public UIntConst(sbyte val) {
2470 type = PrimitiveType.UInt8;
2472 public UIntConst(short val) {
2475 type = PrimitiveType.UInt16;
2477 public UIntConst(int val) {
2480 type = PrimitiveType.UInt32;
2482 public UIntConst(long val) {
2485 type = PrimitiveType.UInt64;
2488 internal sealed override uint GetBlobIndex(MetaData md) {
2489 if (!addedToBlobHeap) {
2491 case (1) : blobIndex = md.AddToBlobHeap((sbyte)val); break;
2492 case (2) : blobIndex = md.AddToBlobHeap((short)val); break;
2493 case (4) : blobIndex = md.AddToBlobHeap((int)val); break;
2494 default : blobIndex = md.AddToBlobHeap(val); break;
2496 addedToBlobHeap = true;
2501 internal sealed override void Write(BinaryWriter bw) {
2503 case (1) : bw.Write((sbyte)val); break;
2504 case (2) : bw.Write((short)val); break;
2505 case (4) : bw.Write((int)val); break;
2506 default : bw.Write(val); break;
2512 public class StringConst : DataConstant {
2515 public StringConst(string val) {
2517 size = (uint)val.Length; // need to add null ??
2518 type = PrimitiveType.String;
2521 internal sealed override uint GetBlobIndex(MetaData md) {
2522 if (!addedToBlobHeap) {
2523 byte [] b = Encoding.Unicode.GetBytes (val);
2524 blobIndex = md.AddToBlobHeap(b);
2525 addedToBlobHeap = true;
2530 internal sealed override void Write(BinaryWriter bw) {
2536 public class NullConst : Constant {
2538 public NullConst() {
2540 type = PrimitiveType.Class;
2543 internal sealed override uint GetBlobIndex(MetaData md) {
2544 if (!addedToBlobHeap) {
2545 blobIndex = md.AddToBlobHeap((int)0);
2546 addedToBlobHeap = true;
2551 internal sealed override void Write(BinaryWriter bw) {
2557 public class AddressConstant : DataConstant {
2560 public AddressConstant(DataConstant dConst) {
2563 type = PrimitiveType.TypedRef;
2566 internal sealed override void Write(BinaryWriter bw) {
2567 ((FileImage)bw).WriteDataRVA(data.DataOffset);
2572 public class RepeatedConstant : DataConstant {
2576 public RepeatedConstant(DataConstant dConst, int repeatCount) {
2578 repCount = (uint)repeatCount;
2579 int[] sizes = new int[1];
2580 sizes[0] = repeatCount;
2581 type = new BoundArray(type,1,sizes);
2582 size = data.GetSize() * repCount;
2585 internal sealed override void Write(BinaryWriter bw) {
2586 for (int i=0; i < repCount; i++) {
2593 public class ArrayConstant : DataConstant {
2594 DataConstant[] dataVals;
2596 public ArrayConstant(DataConstant[] dVals) {
2598 for (int i=0; i < dataVals.Length; i++) {
2599 size += dataVals[i].GetSize();
2603 internal sealed override void Write(BinaryWriter bw) {
2604 for (int i=0; i < dataVals.Length; i++) {
2605 dataVals[i].Write(bw);
2611 public class ClassType : Constant {
2615 public ClassType(string className) {
2617 type = PrimitiveType.ClassType;
2620 public ClassType(Class classDesc) {
2622 type = PrimitiveType.ClassType;
2625 internal override void Write(BinaryWriter bw) {
2626 if (name == null) name = desc.TypeName();
2634 /**************************************************************************/
2636 /// Summary description for ConstantElem.
2638 internal class ConstantElem : MetaDataElement
2640 MetaDataElement parent;
2644 internal ConstantElem(MetaDataElement parent, Constant val) {
2645 this.parent = parent;
2647 tabIx = MDTable.Constant;
2651 internal override uint SortKey()
2653 return (parent.Row << MetaData.CIxShiftMap[(uint)CIx.HasConst])
2654 | parent.GetCodedIx(CIx.HasConst);
2657 internal sealed override void BuildTables(MetaData md) {
2659 valIx = cValue.GetBlobIndex(md);
2663 internal void AddToBlob(BinaryWriter bw) {
2667 internal sealed override uint Size(MetaData md) {
2668 return 2 + md.CodedIndexSize(CIx.HasConst) + md.BlobIndexSize();
2671 internal sealed override void Write(FileImage output) {
2672 output.Write(cValue.GetTypeIndex());
2673 output.Write((byte)0);
2674 output.WriteCodedIndex(CIx.HasConst,parent);
2675 output.BlobIndex(valIx);
2679 /**************************************************************************/
2681 /// Descriptor for a Custom Attribute (.custom)
2684 public class CustomAttribute : MetaDataElement
2686 private static readonly ushort prolog = 0x0001;
2687 MetaDataElement parent;
2692 ushort numNamed = 0;
2693 ArrayList names, vals;
2695 internal CustomAttribute(MetaDataElement paren, Method constrType,
2700 tabIx = MDTable.CustomAttribute;
2703 internal CustomAttribute(MetaDataElement paren, Method constrType,
2707 tabIx = MDTable.CustomAttribute;
2711 internal override uint SortKey() {
2712 return (parent.Row << MetaData.CIxShiftMap[(uint)CIx.HasCustomAttr])
2713 | parent.GetCodedIx(CIx.HasCustomAttr);
2716 public void AddFieldOrProp(string name, Constant val) {
2717 if (numNamed == 0) {
2718 names = new ArrayList();
2719 vals = new ArrayList();
2725 internal sealed override void BuildTables(MetaData md) {
2726 BinaryWriter bw = new BinaryWriter(new MemoryStream());
2728 md.AddToTable(MDTable.CustomAttribute, this);
2729 MemoryStream str = (MemoryStream)bw.BaseStream;
2730 valIx = md.AddToBlobHeap(str.ToArray());
2733 internal sealed override uint Size(MetaData md) {
2734 return md.CodedIndexSize(CIx.HasCustomAttr) + md.CodedIndexSize(CIx.CustomAttributeType) + md.BlobIndexSize();
2737 internal sealed override void Write(FileImage output) {
2738 output.WriteCodedIndex(CIx.HasCustomAttr,parent);
2739 output.WriteCodedIndex(CIx.CustomAttributeType,type);
2740 output.BlobIndex(valIx);
2744 /**************************************************************************/
2746 /// Descriptor for a custom modifier of a type (modopt or modreq)
2749 public class CustomModifiedType : Type
2755 /// Create a new custom modifier for a type
2757 /// <param name="type">the type to be modified</param>
2758 /// <param name="cmod">the modifier</param>
2759 /// <param name="cmodType">the type reference to be associated with the type</param>
2760 public CustomModifiedType(Type type, CustomModifier cmod, Class cmodType)
2761 : base((byte)cmod) {
2763 this.cmodType = cmodType;
2766 internal sealed override void TypeSig(MemoryStream str) {
2767 str.WriteByte(typeIndex);
2768 MetaData.CompressNum(cmodType.TypeDefOrRefToken(),str);
2773 /**************************************************************************/
2775 /// Descriptor for security permissions for a class or a method NOT YET IMPLEMENTED
2778 public class DeclSecurity : MetaDataElement
2781 MetaDataElement parent;
2784 internal DeclSecurity(MetaDataElement paren, ushort act) {
2787 tabIx = MDTable.DeclSecurity;
2788 throw(new NotYetImplementedException("Security "));
2791 internal override uint SortKey() {
2792 return (parent.Row << MetaData.CIxShiftMap[(uint)CIx.HasDeclSecurity])
2793 | parent.GetCodedIx(CIx.HasDeclSecurity);
2796 internal sealed override uint Size(MetaData md) {
2797 return 2 + md.CodedIndexSize(CIx.HasDeclSecurity) + md.BlobIndexSize();
2800 internal sealed override void BuildTables(MetaData md) {
2802 // add permission to blob heap
2806 internal sealed override void Write(FileImage output) {
2807 output.Write(action);
2808 output.WriteCodedIndex(CIx.HasDeclSecurity,parent);
2809 output.BlobIndex(permissionIx);
2813 /**************************************************************************/
2815 /// Descriptor for an event
2817 public class Event : Feature
2821 internal Event(string name, Type eType, ClassDef parent)
2822 : base(name, parent) {
2824 tabIx = MDTable.Event;
2828 /// Add the addon method to this event
2830 /// <param name="addon">the addon method</param>
2831 public void AddAddon(MethodDef addon) {
2832 AddMethod(addon,MethodType.AddOn);
2836 /// Add the removeon method to this event
2838 /// <param name="removeOn">the removeon method</param>
2839 public void AddRemoveOn(MethodDef removeOn) {
2840 AddMethod(removeOn,MethodType.RemoveOn);
2844 /// Add the fire method to this event
2846 /// <param name="fire">the fire method</param>
2847 public void AddFire(MethodDef fire) {
2848 AddMethod(fire,MethodType.Fire);
2852 /// Add another method to this event
2854 /// <param name="other">the method to be added</param>
2855 public void AddOther(MethodDef other) {
2856 AddMethod(other,MethodType.Other);
2859 internal sealed override void BuildTables(MetaData md) {
2861 nameIx = md.AddToStringsHeap(name);
2862 for (int i=0; i < tide; i++) {
2863 md.AddToTable(MDTable.MethodSemantics,methods[i]);
2868 internal sealed override uint Size(MetaData md) {
2869 return 2 + md.StringsIndexSize() + md.CodedIndexSize(CIx.TypeDefOrRef);
2872 internal sealed override void Write(FileImage output) {
2873 output.Write(flags);
2874 output.StringsIndex(nameIx);
2875 output.WriteCodedIndex(CIx.TypeDefOrRef,eventType);
2878 internal sealed override uint GetCodedIx(CIx code) {
2880 case (CIx.HasCustomAttr) : return 10;
2881 case (CIx.HasSemantics) : return 0;
2887 /**************************************************************************/
2889 /// Descriptor for a class defined in another module of THIS assembly
2890 /// and exported (.class extern)
2893 internal class ExternClass : Class
2895 MetaDataElement parent;
2898 internal ExternClass(TypeAttr attr, uint nsIx, uint nIx,
2899 MetaDataElement paren) : base(nsIx,nIx) {
2902 tabIx = MDTable.ExportedType;
2905 internal sealed override uint Size(MetaData md) {
2906 return 8 + 2* md.StringsIndexSize() + md.CodedIndexSize(CIx.Implementation);
2909 internal sealed override void Write(FileImage output) {
2910 output.Write(flags);
2912 output.StringsIndex(nameIx);
2913 output.StringsIndex(nameSpaceIx);
2914 output.WriteCodedIndex(CIx.Implementation,parent);
2917 internal sealed override uint GetCodedIx(CIx code) {
2919 case (CIx.HasCustomAttr) : return 17;
2920 case (CIx.Implementation) : return 2;
2926 /**************************************************************************/
2928 /// Base class for Event and Property descriptors
2931 public class Feature : MetaDataElement
2933 internal enum MethodType : ushort { Setter = 0x01, Getter, Other = 0x04, AddOn = 0x08,
2934 RemoveOn = 0x10, Fire = 0x20 }
2936 private static readonly int INITSIZE = 5;
2937 private static readonly ushort specialName = 0x200;
2938 private static readonly ushort rtSpecialName = 0x400;
2940 protected ClassDef parent;
2941 protected ushort flags = 0;
2942 protected string name;
2943 protected int tide = 0;
2944 protected uint nameIx;
2945 protected MethodSemantics[] methods = new MethodSemantics[INITSIZE];
2947 internal Feature(string name, ClassDef par) {
2952 internal void AddMethod(MethodDef meth, MethodType mType) {
2953 if (tide >= methods.Length) {
2954 int len = methods.Length;
2955 MethodSemantics[] mTmp = methods;
2956 methods = new MethodSemantics[len * 2];
2957 for (int i=0; i < len; i++) {
2958 methods[i] = mTmp[i];
2961 methods[tide++] = new MethodSemantics(mType,meth,this);
2965 /// Set the specialName attribute for this Event or Property
2967 public void SetSpecialName() {
2968 flags |= specialName;
2972 /// Set the RTSpecialName attribute for this Event or Property
2974 public void SetRTSpecialName() {
2975 flags |= rtSpecialName;
2979 /*****************************************************************************/
2981 /// Descriptor for a field of a class
2984 public abstract class Field : Member
2986 protected static readonly byte FieldSig = 0x6;
2988 protected Type type;
2990 internal Field(string pfName, Type pfType) : base(pfName)
2996 /**************************************************************************/
2998 /// Descriptor for a field defined in a class of THIS assembly/module
3000 public class FieldDef : Field
3002 //private static readonly uint PInvokeImpl = 0x2000;
3003 private static readonly ushort HasFieldMarshal = 0x1000;
3004 private static readonly ushort HasFieldRVA = 0x100;
3005 private static readonly ushort HasDefault = 0x8000;
3008 ConstantElem constVal;
3010 FieldMarshal marshalInfo;
3013 internal FieldDef(string name, Type fType) : base(name,fType) {
3014 tabIx = MDTable.Field;
3017 internal FieldDef(FieldAttr attrSet, string name, Type fType) : base(name, fType) {
3018 flags = (ushort)attrSet;
3019 tabIx = MDTable.Field;
3023 /// Add an attribute(s) to this field
3025 /// <param name="fa">the attribute(s) to be added</param>
3026 public void AddFieldAttr(FieldAttr fa) {
3027 flags |= (ushort)fa;
3031 /// Add a value for this field
3033 /// <param name="val">the value for the field</param>
3034 public void AddValue(Constant val) {
3035 constVal = new ConstantElem(this,val);
3036 flags |= HasDefault;
3040 /// Add an initial value for this field (at dataLabel) (.data)
3042 /// <param name="val">the value for the field</param>
3043 /// <param name="repeatVal">the number of repetitions of this value</param>
3044 public void AddDataValue(DataConstant val) {
3045 flags |= HasFieldRVA;
3046 rva = new FieldRVA(this,val);
3050 /// Set the offset of the field. Used for sequential or explicit classes.
3053 /// <param name="offs">field offset</param>
3054 public void SetOffset(uint offs) {
3055 layout = new FieldLayout(this,offs);
3059 /// Set the marshalling info for a field
3061 /// <param name="mInf"></param>
3062 public void SetMarshalInfo(NativeType marshallType) {
3063 flags |= HasFieldMarshal;
3064 marshalInfo = new FieldMarshal(this,marshallType);
3067 internal sealed override void BuildTables(MetaData md) {
3069 nameIx = md.AddToStringsHeap(name);
3070 MemoryStream sig = new MemoryStream();
3071 sig.WriteByte(FieldSig);
3073 sigIx = md.AddToBlobHeap(sig.ToArray());
3075 md.AddToTable(MDTable.FieldRVA,rva);
3076 rva.BuildTables(md);
3077 } else if (constVal != null) {
3078 md.AddToTable(MDTable.Constant,constVal);
3079 constVal.BuildTables(md);
3081 if (layout != null) md.AddToTable(MDTable.FieldLayout,layout);
3082 if (marshalInfo != null) {
3083 md.AddToTable(MDTable.FieldMarshal,marshalInfo);
3084 marshalInfo.BuildTables(md);
3089 internal sealed override uint Size(MetaData md) {
3090 return 2 + md.StringsIndexSize() + md.BlobIndexSize();
3093 internal sealed override void Write(FileImage output) {
3094 output.Write(flags);
3095 output.StringsIndex(nameIx);
3096 output.BlobIndex(sigIx);
3099 internal sealed override uint GetCodedIx(CIx code) {
3101 case (CIx.HasConst) : return 0;
3102 case (CIx.HasCustomAttr) : return 1;
3103 case (CIx.HasFieldMarshal) : return 0;
3104 case (CIx.MemberForwarded) : return 0;
3110 /**************************************************************************/
3112 /// Descriptor for layout information for a field
3115 public class FieldLayout : MetaDataElement
3120 internal FieldLayout(Field field, uint offset) {
3122 this.offset = offset;
3123 tabIx = MDTable.FieldLayout;
3126 internal sealed override uint Size(MetaData md) {
3127 return 4 + md.TableIndexSize(MDTable.Field);
3130 internal sealed override void Write(FileImage output) {
3131 output.Write(offset);
3132 output.WriteIndex(MDTable.Field,field.Row);
3136 /*****************************************************************************/
3138 /// Marshalling information for a field or param
3140 public class FieldMarshal : MetaDataElement
3142 MetaDataElement field;
3146 internal FieldMarshal(MetaDataElement field, NativeType nType) {
3149 tabIx = MDTable.FieldMarshal;
3152 internal override uint SortKey() {
3153 return (field.Row << MetaData.CIxShiftMap[(uint)CIx.HasFieldMarshal])
3154 | field.GetCodedIx(CIx.HasFieldMarshal);
3157 internal sealed override void BuildTables(MetaData md) {
3159 ntIx = md.AddToBlobHeap(nt.ToBlob());
3163 internal sealed override uint Size(MetaData md) {
3164 return md.CodedIndexSize(CIx.HasFieldMarshal) + md.BlobIndexSize();
3167 internal sealed override void Write(FileImage output) {
3168 output.WriteCodedIndex(CIx.HasFieldMarshal,field);
3169 output.BlobIndex(ntIx);
3173 /**************************************************************************/
3175 /// Descriptor for a field of a class defined in another assembly/module
3177 public class FieldRef : Field
3179 MetaDataElement parent;
3181 internal FieldRef(MetaDataElement paren, string name, Type fType) : base(name, fType) {
3185 internal sealed override void BuildTables(MetaData md) {
3187 nameIx = md.AddToStringsHeap(name);
3188 MemoryStream sig = new MemoryStream();
3189 sig.WriteByte(FieldSig);
3191 sigIx = md.AddToBlobHeap(sig.ToArray());
3195 internal sealed override uint Size(MetaData md) {
3196 return md.CodedIndexSize(CIx.MemberRefParent) + md.StringsIndexSize() + md.BlobIndexSize();
3199 internal sealed override void Write(FileImage output) {
3200 output.WriteCodedIndex(CIx.MemberRefParent,parent);
3201 output.StringsIndex(nameIx);
3202 output.BlobIndex(sigIx);
3205 internal sealed override uint GetCodedIx(CIx code) { return 6; }
3208 /**************************************************************************/
3210 /// Descriptor for the address of a field's value in the PE file
3212 public class FieldRVA : MetaDataElement
3217 internal FieldRVA(Field field, DataConstant data) {
3220 tabIx = MDTable.FieldRVA;
3223 internal sealed override void BuildTables(MetaData md) {
3229 internal sealed override uint Size(MetaData md) {
3230 return 4 + md.TableIndexSize(MDTable.Field);
3233 internal sealed override void Write(FileImage output) {
3234 output.WriteDataRVA(data.DataOffset);
3235 output.WriteIndex(MDTable.Field,field.Row);
3239 /**************************************************************************/
3241 /// Image for a PEFile
3243 /// DOS Header (128 bytes)
3244 /// PE Signature ("PE\0\0")
3245 /// PEFileHeader (20 bytes)
3246 /// PEOptionalHeader (224 bytes)
3247 /// SectionHeaders (40 bytes * NumSections)
3249 /// Sections .text (always present - contains metadata)
3250 /// .sdata (contains any initialised data in the file - may not be present)
3251 /// (for ilams /debug this contains the Debug table)
3252 /// .reloc (always present - in pure CIL only has one fixup)
3253 /// others??? c# produces .rsrc section containing a Resource Table
3256 /// IAT (single entry 8 bytes for pure CIL)
3257 /// CLIHeader (72 bytes)
3258 /// CIL instructions for all methods (variable size)
3260 /// Root (20 bytes + UTF-8 Version String + quad align padding)
3261 /// StreamHeaders (8 bytes + null terminated name string + quad align padding)
3263 /// #~ (always present - holds metadata tables)
3264 /// #Strings (always present - holds identifier strings)
3265 /// #US (Userstring heap)
3266 /// #Blob (signature blobs)
3267 /// #GUID (guids for assemblies or Modules)
3268 /// ImportTable (40 bytes)
3269 /// ImportLookupTable(8 bytes) (same as IAT for standard CIL files)
3270 /// Hint/Name Tables with entry "_CorExeMain" for .exe file and "_CorDllMain" for .dll (14 bytes)
3271 /// ASCII string "mscoree.dll" referenced in ImportTable (+ padding = 16 bytes)
3272 /// Entry Point (0xFF25 followed by 4 bytes 0x400000 + RVA of .text)
3274 /// #~ stream structure
3275 /// Header (24 bytes)
3276 /// Rows (4 bytes * numTables)
3279 internal class FileImage : BinaryWriter
3281 internal readonly static uint[] iByteMask = {0x000000FF, 0x0000FF00, 0x00FF0000, 0xFF000000};
3282 internal readonly static ulong[] lByteMask = {0x00000000000000FF, 0x000000000000FF00,
3283 0x0000000000FF0000, 0x00000000FF000000,
3284 0x000000FF00000000, 0x0000FF0000000000,
3285 0x00FF000000000000, 0xFF00000000000000 };
3286 internal readonly static uint nibble0Mask = 0x0000000F;
3287 internal readonly static uint nibble1Mask = 0x000000F0;
3289 private static readonly byte[] DOSHeader = { 0x4d,0x5a,0x90,0x00,0x03,0x00,0x00,0x00,
3290 0x04,0x00,0x00,0x00,0xff,0xff,0x00,0x00,
3291 0xb8,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
3292 0x40,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
3293 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
3294 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
3295 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
3296 0x00,0x00,0x00,0x00,0x80,0x00,0x00,0x00,
3297 0x0e,0x1f,0xba,0x0e,0x00,0xb4,0x09,0xcd,
3298 0x21,0xb8,0x01,0x4c,0xcd,0x21,0x54,0x68,
3299 0x69,0x73,0x20,0x70,0x72,0x6f,0x67,0x72,
3300 0x61,0x6d,0x20,0x63,0x61,0x6e,0x6e,0x6f,
3301 0x74,0x20,0x62,0x65,0x20,0x72,0x75,0x6e,
3302 0x20,0x69,0x6e,0x20,0x44,0x4f,0x53,0x20,
3303 0x6d,0x6f,0x64,0x65,0x2e,0x0d,0x0d,0x0a,
3304 0x24,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
3305 0x50,0x45,0x00,0x00};
3306 private static byte[] PEHeader = { 0x4c, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3307 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3308 0xE0, 0x00, 0x0E, 0x01, // PE Header Standard Fields
3309 0x0B, 0x01, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00,
3310 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3311 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
3314 private static readonly uint minFileAlign = 0x200;
3315 private static readonly uint maxFileAlign = 0x1000;
3316 private static readonly uint fileHeaderSize = 0x178;
3317 private static readonly uint sectionHeaderSize = 40;
3318 private static readonly uint SectionAlignment = 0x2000;
3319 private static readonly uint ImageBase = 0x400000;
3320 private static readonly uint ImportTableSize = 40;
3321 private static readonly uint IATSize = 8;
3322 private static readonly uint CLIHeaderSize = 72;
3323 private uint runtimeFlags = 0x01; // COMIMAGE_FLAGS_ILONLY
3324 // 32BITREQUIRED 0x02, STRONGNAMESIGNED 0x08, TRACKDEBUGDATA 0x10000
3325 private static readonly uint StrongNameSignatureSize = 128;
3326 private bool reserveStrongNameSignatureSpace = false;
3328 private static readonly uint relocFlags = 0x42000040;
3329 private static readonly ushort exeCharacteristics = 0x010E;
3330 private static readonly ushort dllCharacteristics = 0x210E;
3331 // section names are all 8 bytes
3332 private static readonly string textName = ".text\0\0\0";
3333 private static readonly string sdataName = ".sdata\0\0";
3334 private static readonly string relocName = ".reloc\0\0";
3335 private static readonly string rsrcName = ".rsrc\0\0\0";
3336 private static readonly string exeHintNameTable = "\0\0_CorExeMain\0";
3337 private static readonly string dllHintNameTable = "\0\0_CorDllMain\0";
3338 private static readonly string runtimeEngineName = "mscoree.dll\0\0";
3340 private Section text, sdata, rsrc;
3342 BinaryWriter reloc = new BinaryWriter(new MemoryStream());
3344 DateTime origin = new DateTime(1970,1,1);
3345 uint numSections = 2; // always have .text and .reloc sections
3346 internal SubSystem subSys = SubSystem.Windows_CUI; // default is Windows Console mode
3347 internal uint fileAlign = minFileAlign;
3348 uint entryPointOffset, entryPointPadding, imageSize, headerSize, headerPadding, entryPointToken = 0;
3349 uint relocOffset, relocRVA, relocSize, relocPadding, relocTide, hintNameTableOffset;
3350 uint metaDataOffset, runtimeEngineOffset, initDataSize = 0, importTablePadding;
3351 uint resourcesSize, resourcesOffset;
3352 uint strongNameSigOffset;
3353 uint importTableOffset, importLookupTableOffset, totalImportTableSize;
3355 char[] runtimeEngine = runtimeEngineName.ToCharArray(), hintNameTable;
3356 bool doDLL, largeStrings, largeGUID, largeUS, largeBlob;
3357 ushort characteristics;
3359 internal FileImage(bool makeDLL, string fileName) : base(new FileStream(fileName,FileMode.Create)) {
3360 InitFileImage(makeDLL);
3361 TimeSpan tmp = System.IO.File.GetCreationTime(fileName).Subtract(origin);
3362 dateStamp = Convert.ToUInt32(tmp.TotalSeconds);
3365 internal FileImage(bool makeDLL, Stream str) : base(str) {
3366 InitFileImage(makeDLL);
3367 TimeSpan tmp = DateTime.Now.Subtract(origin);
3368 dateStamp = Convert.ToUInt32(tmp.TotalSeconds);
3371 private void InitFileImage(bool makeDLL) {
3374 hintNameTable = dllHintNameTable.ToCharArray();
3375 characteristics = dllCharacteristics;
3377 hintNameTable = exeHintNameTable.ToCharArray();
3378 characteristics = exeCharacteristics;
3380 text = new Section(textName,0x60000020); // IMAGE_SCN_CNT CODE, EXECUTE, READ
3381 // rsrc = new Section(rsrcName,0x40000040); // IMAGE_SCN_CNT INITIALIZED_DATA, READ
3382 metaData = new MetaData(this);
3385 internal MetaData GetMetaData() {
3389 private uint GetNextSectStart(uint rva, uint tide) {
3390 if (tide < SectionAlignment) return rva + SectionAlignment;
3391 return rva + ((tide / SectionAlignment) + 1) * SectionAlignment;
3394 private void BuildTextSection() {
3396 // IAT (single entry 8 bytes for pure CIL)
3397 // CLIHeader (72 bytes)
3398 // CIL instructions for all methods (variable size)
3400 // ImportTable (40 bytes)
3401 // ImportLookupTable(8 bytes) (same as IAT for standard CIL files)
3402 // Hint/Name Tables with entry "_CorExeMain" for .exe file and "_CorDllMain" for .dll (14 bytes)
3403 // ASCII string "mscoree.dll" referenced in ImportTable (+ padding = 16 bytes)
3404 // Entry Point (0xFF25 followed by 4 bytes 0x400000 + RVA of .text)
3405 metaData.BuildMetaData(IATSize + CLIHeaderSize);
3406 metaDataOffset = IATSize + CLIHeaderSize;
3407 // Console.WriteLine("Code starts at " + metaDataOffset);
3408 metaDataOffset += metaData.CodeSize();
3410 resourcesOffset = metaDataOffset + metaData.Size ();
3411 resourcesSize = metaData.GetResourcesSize ();
3412 if (reserveStrongNameSignatureSpace) {
3413 strongNameSigOffset = resourcesOffset + resourcesSize;
3414 // fixUps = RVA for vtable
3415 importTableOffset = strongNameSigOffset + StrongNameSignatureSize;
3417 strongNameSigOffset = 0;
3418 // fixUps = RVA for vtable
3419 importTableOffset = resourcesOffset + resourcesSize;
3421 importTablePadding = NumToAlign(importTableOffset,16);
3422 importTableOffset += importTablePadding;
3423 importLookupTableOffset = importTableOffset + ImportTableSize;
3424 hintNameTableOffset = importLookupTableOffset + IATSize;
3425 runtimeEngineOffset = hintNameTableOffset + (uint)hintNameTable.Length;
3426 entryPointOffset = runtimeEngineOffset + (uint)runtimeEngine.Length;
3427 totalImportTableSize = entryPointOffset - importTableOffset;
3428 // Console.WriteLine("total import table size = " + totalImportTableSize);
3429 // Console.WriteLine("entrypoint offset = " + entryPointOffset);
3430 entryPointPadding = NumToAlign(entryPointOffset,4) + 2;
3431 entryPointOffset += entryPointPadding;
3432 text.AddReloc(entryPointOffset+2);
3433 text.IncTide(entryPointOffset + 6);
3434 //if (text.Tide() < fileAlign) fileAlign = minFileAlign;
3435 text.SetSize(NumToAlign(text.Tide(),fileAlign));
3436 // Console.WriteLine("text size = " + text.Size() + " text tide = " + text.Tide() + " text padding = " + text.Padding());
3437 // Console.WriteLine("metaDataOffset = " + Hex.Int(metaDataOffset));
3438 // Console.WriteLine("importTableOffset = " + Hex.Int(importTableOffset));
3439 // Console.WriteLine("importLookupTableOffset = " + Hex.Int(importLookupTableOffset));
3440 // Console.WriteLine("hintNameTableOffset = " + Hex.Int(hintNameTableOffset));
3441 // Console.WriteLine("runtimeEngineOffset = " + Hex.Int(runtimeEngineOffset));
3442 // Console.WriteLine("entryPointOffset = " + Hex.Int(entryPointOffset));
3443 // Console.WriteLine("entryPointPadding = " + Hex.Int(entryPointPadding));
3447 internal void BuildRelocSection() {
3448 text.DoRelocs(reloc);
3449 if (sdata != null) sdata.DoRelocs(reloc);
3450 if (rsrc != null) rsrc.DoRelocs(reloc);
3451 relocTide = (uint)reloc.Seek(0,SeekOrigin.Current);
3452 relocPadding = NumToAlign(relocTide,fileAlign);
3453 relocSize = relocTide + relocPadding;
3454 imageSize = relocRVA + SectionAlignment;
3455 initDataSize += relocSize;
3458 private void CalcOffsets() {
3463 headerSize = fileHeaderSize + (numSections * sectionHeaderSize);
3464 headerPadding = NumToAlign(headerSize,fileAlign);
3465 headerSize += headerPadding;
3466 uint offset = headerSize;
3467 uint rva = SectionAlignment;
3468 text.SetOffset(offset);
3470 offset += text.Size();
3471 rva = GetNextSectStart(rva,text.Tide());
3472 // Console.WriteLine("headerSize = " + headerSize);
3473 // Console.WriteLine("headerPadding = " + headerPadding);
3474 // Console.WriteLine("textOffset = " + Hex.Int(text.Offset()));
3475 if (sdata != null) {
3476 sdata.SetSize(NumToAlign(sdata.Tide(),fileAlign));
3477 sdata.SetOffset(offset);
3479 offset += sdata.Size();
3480 rva = GetNextSectStart(rva,sdata.Tide());
3481 initDataSize += sdata.Size();
3484 rsrc.SetSize(NumToAlign(rsrc.Tide(),fileAlign));
3485 rsrc.SetOffset(offset);
3487 offset += rsrc.Size();
3488 rva = GetNextSectStart(rva,rsrc.Tide());
3489 initDataSize += rsrc.Size();
3491 relocOffset = offset;
3495 internal void MakeFile() {
3496 if (doDLL) hintNameTable = dllHintNameTable.ToCharArray();
3497 else hintNameTable = exeHintNameTable.ToCharArray();
3500 BuildRelocSection();
3508 private void WriteHeader() {
3510 // Console.WriteLine("Writing PEHeader at offset " + Seek(0,SeekOrigin.Current));
3512 // Console.WriteLine("Writing text section header at offset " + Hex.Long(Seek(0,SeekOrigin.Current)));
3513 text.WriteHeader(this,relocRVA);
3514 if (sdata != null) sdata.WriteHeader(this,relocRVA);
3515 if (rsrc != null) rsrc.WriteHeader(this,relocRVA);
3516 // Console.WriteLine("Writing reloc section header at offset " + Seek(0,SeekOrigin.Current));
3517 WriteRelocSectionHeader();
3518 // Console.WriteLine("Writing padding at offset " + Seek(0,SeekOrigin.Current));
3519 WriteZeros(headerPadding);
3522 private void WriteSections() {
3523 // Console.WriteLine("Writing text section at offset " + Seek(0,SeekOrigin.Current));
3525 if (sdata != null) WriteSDataSection();
3526 if (rsrc != null) WriteRsrcSection();
3527 WriteRelocSection();
3530 private void WriteIAT() {
3531 Write(text.RVA() + hintNameTableOffset);
3535 private void WriteImportTables() {
3537 WriteZeros(importTablePadding);
3538 // Console.WriteLine("Writing import tables at offset " + Hex.Long(Seek(0,SeekOrigin.Current)));
3539 Write(importLookupTableOffset + text.RVA());
3541 Write(runtimeEngineOffset + text.RVA());
3542 Write(text.RVA()); // IAT is at the beginning of the text section
3544 // Import Lookup Table
3545 WriteIAT(); // lookup table and IAT are the same
3547 // Console.WriteLine("Writing hintname table at " + Hex.Long(Seek(0,SeekOrigin.Current)));
3548 Write(hintNameTable);
3549 Write(runtimeEngineName.ToCharArray());
3552 private void WriteTextSection() {
3555 // Console.WriteLine("Writing code at " + Hex.Long(Seek(0,SeekOrigin.Current)));
3556 metaData.WriteByteCodes(this);
3557 // Console.WriteLine("Finished writing code at " + Hex.Long(Seek(0,SeekOrigin.Current)));
3558 largeStrings = metaData.LargeStringsIndex();
3559 largeGUID = metaData.LargeGUIDIndex();
3560 largeUS = metaData.LargeUSIndex();
3561 largeBlob = metaData.LargeBlobIndex();
3562 metaData.WriteMetaData(this);
3563 metaData.WriteResources (this);
3564 if (reserveStrongNameSignatureSpace) {
3565 WriteZeros(StrongNameSignatureSize);
3567 WriteImportTables();
3568 WriteZeros(entryPointPadding);
3569 Write((ushort)0x25FF);
3570 Write(ImageBase + text.RVA());
3571 WriteZeros(text.Padding());
3574 private void WriteCLIHeader() {
3575 Write(CLIHeaderSize); // Cb
3576 Write((short)2); // Major runtime version
3577 Write((short)0); // Minor runtime version
3578 Write(text.RVA() + metaDataOffset);
3579 Write(metaData.Size());
3580 Write(runtimeFlags);
3581 Write(entryPointToken);
3582 if (resourcesSize > 0) {
3583 Write (text.RVA () + resourcesOffset);
3584 Write (resourcesSize);
3588 // Strong Name Signature (RVA, size)
3589 if (reserveStrongNameSignatureSpace) {
3590 Write(text.RVA() + strongNameSigOffset);
3591 Write(StrongNameSignatureSize);
3595 WriteZeros(8); // CodeManagerTable
3596 WriteZeros(8); // VTableFixups NYI
3597 WriteZeros(16); // ExportAddressTableJumps, ManagedNativeHeader
3600 private void WriteSDataSection() {
3601 long size = sdata.Size ();
3602 long start = BaseStream.Position;
3603 for (int i=0; i < data.Count; i++) {
3604 ((DataConstant)data[i]).Write(this);
3606 while (BaseStream.Position < (start + size))
3610 private void WriteRsrcSection() {
3613 private void WriteRelocSection() {
3614 // Console.WriteLine("Writing reloc section at " + Seek(0,SeekOrigin.Current) + " = " + relocOffset);
3615 MemoryStream str = (MemoryStream)reloc.BaseStream;
3616 Write(str.ToArray());
3617 WriteZeros(NumToAlign((uint)str.Position,fileAlign));
3620 internal void SetEntryPoint(uint entryPoint) {
3621 entryPointToken = entryPoint;
3624 internal void AddInitData(DataConstant cVal) {
3625 if (sdata == null) {
3626 sdata = new Section(sdataName,0xC0000040); // IMAGE_SCN_CNT INITIALIZED_DATA, READ, WRITE
3627 data = new ArrayList();
3630 cVal.DataOffset = sdata.Tide();
3631 sdata.IncTide(cVal.GetSize());
3634 internal void WriteZeros(uint numZeros) {
3635 for (int i=0; i < numZeros; i++) {
3640 internal void WritePEHeader() {
3641 Write((ushort)0x014C); // Machine - always 0x14C for Managed PE Files (allow others??)
3642 Write((ushort)numSections);
3644 WriteZeros(8); // Pointer to Symbol Table and Number of Symbols (always zero for ECMA CLI files)
3645 Write((ushort)0x00E0); // Size of Optional Header
3646 Write(characteristics);
3647 // PE Optional Header
3648 Write((ushort)0x010B); // Magic
3649 Write((byte)0x6); // LMajor pure-IL = 6 C++ = 7
3650 Write((byte)0x0); // LMinor
3652 Write(initDataSize);
3653 Write(0); // Check other sections here!!
3654 Write(text.RVA() + entryPointOffset);
3657 if (sdata != null) dataBase = sdata.RVA();
3658 else if (rsrc != null) dataBase = rsrc.RVA();
3659 else dataBase = relocRVA;
3662 Write(SectionAlignment);
3664 Write((ushort)0x04); // OS Major
3665 WriteZeros(6); // OS Minor, User Major, User Minor
3666 Write((ushort)0x04); // SubSys Major
3667 WriteZeros(6); // SybSys Minor, Reserved
3670 Write((int)0); // File Checksum
3671 Write((ushort)subSys);
3672 Write((short)0); // DLL Flags
3673 Write((uint)0x100000); // Stack Reserve Size
3674 Write((uint)0x1000); // Stack Commit Size
3675 Write((uint)0x100000); // Heap Reserve Size
3676 Write((uint)0x1000); // Heap Commit Size
3677 Write(0); // Loader Flags
3678 Write(0x10); // Number of Data Directories
3679 WriteZeros(8); // Export Table
3680 Write(importTableOffset + text.RVA());
3681 Write(totalImportTableSize);
3682 WriteZeros(24); // Resource, Exception and Certificate Tables
3685 WriteZeros(48); // Debug, Copyright, Global Ptr, TLS, Load Config and Bound Import Tables
3686 Write(text.RVA()); // IATRVA - IAT is at start of .text Section
3688 WriteZeros(8); // Delay Import Descriptor
3689 Write(text.RVA()+IATSize); // CLIHeader immediately follows IAT
3690 Write(CLIHeaderSize);
3691 WriteZeros(8); // Reserved
3694 internal void WriteRelocSectionHeader() {
3695 Write(relocName.ToCharArray());
3704 private void Align (MemoryStream str, int val) {
3705 if ((str.Position % val) != 0) {
3706 for (int i=val - (int)(str.Position % val); i > 0; i--) {
3712 private uint Align(uint val, uint alignVal) {
3713 if ((val % alignVal) != 0) {
3714 val += alignVal - (val % alignVal);
3719 private uint NumToAlign(uint val, uint alignVal) {
3720 if ((val % alignVal) == 0) return 0;
3721 return alignVal - (val % alignVal);
3724 internal void StringsIndex(uint ix) {
3725 if (largeStrings) Write(ix);
3726 else Write((ushort)ix);
3729 internal void GUIDIndex(uint ix) {
3730 if (largeGUID) Write(ix);
3731 else Write((ushort)ix);
3734 internal void USIndex(uint ix) {
3735 if (largeUS) Write(ix);
3736 else Write((ushort)ix);
3739 internal void BlobIndex(uint ix) {
3740 if (largeBlob) Write(ix);
3741 else Write((ushort)ix);
3744 internal void WriteIndex(MDTable tabIx,uint ix) {
3745 if (metaData.LargeIx(tabIx)) Write(ix);
3746 else Write((ushort)ix);
3749 internal void WriteCodedIndex(CIx code, MetaDataElement elem) {
3750 metaData.WriteCodedIndex(code,elem,this);
3753 internal void WriteCodeRVA(uint offs) {
3754 Write(text.RVA() + offs);
3757 internal void WriteDataRVA(uint offs) {
3758 Write(sdata.RVA() + offs);
3761 internal void Write3Bytes(uint val) {
3762 byte b3 = (byte)((val & FileImage.iByteMask[2]) >> 16);
3763 byte b2 = (byte)((val & FileImage.iByteMask[1]) >> 8);;
3764 byte b1 = (byte)(val & FileImage.iByteMask[0]);
3770 internal bool ReserveStrongNameSignatureSpace {
3771 get { return reserveStrongNameSignatureSpace; }
3772 set { reserveStrongNameSignatureSpace = value; }
3776 /**************************************************************************/
3778 /// Descriptor for a file referenced in THIS assembly/module (.file)
3780 public class FileRef : MetaDataElement
3782 private static readonly uint NoMetaData = 0x1;
3783 uint nameIx = 0, hashIx = 0;
3785 protected string name;
3787 internal FileRef(string name, byte[] hashBytes, bool metaData,
3788 bool entryPoint, MetaData md) {
3789 if (!metaData) flags = NoMetaData;
3790 if (entryPoint) md.SetEntryPoint(this);
3792 nameIx = md.AddToStringsHeap(name);
3793 hashIx = md.AddToBlobHeap(hashBytes);
3794 tabIx = MDTable.File;
3797 internal FileRef(uint nameIx, byte[] hashBytes, bool metaData,
3798 bool entryPoint, MetaData md) {
3799 if (!metaData) flags = NoMetaData;
3800 if (entryPoint) md.SetEntryPoint(this);
3801 this.nameIx = nameIx;
3802 hashIx = md.AddToBlobHeap(hashBytes);
3803 tabIx = MDTable.File;
3806 internal sealed override uint Size(MetaData md) {
3807 return 4 + md.StringsIndexSize() + md.BlobIndexSize();
3810 internal sealed override void BuildTables(MetaData md) {
3811 md.AddToTable(MDTable.File,this);
3814 internal sealed override void Write(FileImage output) {
3815 output.Write(flags);
3816 output.StringsIndex(nameIx);
3817 output.BlobIndex(hashIx);
3820 internal sealed override uint GetCodedIx(CIx code) {
3822 case (CIx.HasCustomAttr) : return 16;
3823 case (CIx.Implementation) : return 0;
3829 /**************************************************************************/
3831 /// Descriptor for pinvoke information for a method NOT YET IMPLEMENTED
3833 public class ImplMap : MetaDataElement
3835 private static readonly ushort NoMangle = 0x01;
3840 ModuleRef importScope;
3842 internal ImplMap(ushort flag, Method implMeth, string iName, ModuleRef mScope) {
3846 importScope = mScope;
3847 tabIx = MDTable.ImplMap;
3848 if (iName == null) flags |= NoMangle;
3849 //throw(new NotYetImplementedException("PInvoke "));
3852 internal override uint SortKey() {
3853 return (meth.Row << MetaData.CIxShiftMap[(uint)CIx.MemberForwarded])
3854 | meth.GetCodedIx(CIx.MemberForwarded);
3857 internal sealed override void BuildTables(MetaData md) {
3859 iNameIx = md.AddToStringsHeap(importName);
3863 internal sealed override uint Size(MetaData md) {
3864 return 2+ md.CodedIndexSize(CIx.MemberForwarded) +
3865 md.StringsIndexSize() + md.TableIndexSize(MDTable.ModuleRef);
3868 internal sealed override void Write(FileImage output) {
3869 output.Write(flags);
3870 output.WriteCodedIndex(CIx.MemberForwarded,meth);
3871 output.StringsIndex(iNameIx);
3872 output.WriteIndex(MDTable.ModuleRef,importScope.Row);
3877 /**************************************************************************/
3879 /// Descriptor for an IL instruction
3881 internal abstract class CILInstruction {
3882 protected static readonly sbyte maxByteVal = 127;
3883 protected static readonly sbyte minByteVal = -128;
3884 protected static readonly byte leadByte = 0xFE;
3885 protected static readonly uint USHeapIndex = 0x70000000;
3886 protected static readonly int longInstrStart = (int)Op.arglist;
3887 public bool twoByteInstr = false;
3888 public uint size = 0;
3891 internal virtual bool Check(MetaData md) {
3895 internal virtual void Write(FileImage output) { }
3899 internal class CILByte : CILInstruction {
3902 internal CILByte(byte bVal) {
3907 internal override void Write(FileImage output) {
3908 output.Write(byteVal);
3914 internal class Instr : CILInstruction {
3915 protected int instr;
3917 internal Instr(int inst) {
3918 if (inst >= longInstrStart) {
3919 instr = inst - longInstrStart;
3920 twoByteInstr = true;
3928 internal override void Write(FileImage output) {
3929 //Console.WriteLine("Writing instruction " + instr + " with size " + size);
3930 if (twoByteInstr) output.Write(leadByte);
3931 output.Write((byte)instr);
3936 internal class IntInstr : Instr {
3940 internal IntInstr(int inst, int num, bool byteSize) : base(inst) {
3943 if (byteNum) size++;
3947 internal sealed override void Write(FileImage output) {
3950 output.Write((sbyte)val);
3957 internal class UIntInstr : Instr {
3961 internal UIntInstr(int inst, int num, bool byteSize) : base(inst) {
3964 if (byteNum) size++;
3968 internal sealed override void Write(FileImage output) {
3971 output.Write((byte)val);
3973 output.Write((ushort)val);
3978 internal class LongInstr : Instr {
3981 internal LongInstr(int inst, long l) : base(inst) {
3986 internal sealed override void Write(FileImage output) {
3993 internal class FloatInstr : Instr {
3996 internal FloatInstr(int inst, float f) : base(inst) {
4001 internal sealed override void Write(FileImage output) {
4008 internal class DoubleInstr : Instr {
4011 internal DoubleInstr(int inst, double d) : base(inst) {
4016 internal sealed override void Write(FileImage output) {
4023 internal class StringInstr : Instr {
4028 internal StringInstr(int inst, string str) : base(inst) {
4033 internal StringInstr (int inst, byte[] str) : base (inst) {
4038 internal sealed override bool Check(MetaData md) {
4040 strIndex = md.AddToUSHeap(val);
4042 strIndex = md.AddToUSHeap (bval);
4046 internal sealed override void Write(FileImage output) {
4048 output.Write(USHeapIndex | strIndex);
4053 internal class LabelInstr : CILInstruction {
4056 internal LabelInstr(CILLabel lab) {
4058 label.AddLabelInstr(this);
4062 internal class FieldInstr : Instr {
4065 internal FieldInstr(int inst, Field f) : base(inst) {
4070 internal sealed override void Write(FileImage output) {
4072 output.Write(field.Token());
4077 internal class MethInstr : Instr {
4080 internal MethInstr(int inst, Method m) : base(inst) {
4085 internal sealed override void Write(FileImage output) {
4087 output.Write(meth.Token());
4092 internal class SigInstr : Instr {
4095 internal SigInstr(int inst, CalliSig sig) : base(inst) {
4100 internal sealed override bool Check(MetaData md) {
4101 md.AddToTable(MDTable.StandAloneSig,signature);
4102 signature.BuildTables(md);
4106 internal sealed override void Write(FileImage output) {
4108 output.Write(signature.Token());
4112 internal class TypeInstr : Instr {
4113 MetaDataElement theType;
4115 internal TypeInstr(int inst, Type aType, MetaData md) : base(inst) {
4116 theType = aType.GetTypeSpec(md);
4120 internal sealed override void Write(FileImage output) {
4122 output.Write(theType.Token());
4127 internal class BranchInstr : Instr {
4129 private bool shortVer = true;
4130 private static readonly byte longInstrOffset = 13;
4131 private int target = 0;
4133 internal BranchInstr(int inst, CILLabel dst) : base(inst) {
4135 dest.AddBranch(this);
4138 if (inst >= (int) BranchOp.br && inst != (int) BranchOp.leave_s) {
4144 internal sealed override bool Check(MetaData md) {
4145 target = (int)dest.GetLabelOffset() - (int)(offset + size);
4149 internal sealed override void Write(FileImage output) {
4152 output.Write((sbyte)target);
4154 output.Write(target);
4159 internal class SwitchInstr : Instr {
4163 internal SwitchInstr(int inst, CILLabel[] dsts) : base(inst) {
4165 if (cases != null) numCases = (uint)cases.Length;
4166 size += 4 + (numCases * 4);
4167 for (int i=0; i < numCases; i++) {
4168 cases[i].AddBranch(this);
4172 internal sealed override void Write(FileImage output) {
4174 output.Write(numCases);
4175 for (int i=0; i < numCases; i++) {
4176 int target = (int)cases[i].GetLabelOffset() - (int)(offset + size);
4177 output.Write(target);
4182 /**************************************************************************/
4184 public class GenericParameter : MetaDataElement
4186 MetaDataElement owner;
4192 internal GenericParameter (ClassDef owner, MetaData metadata,
4193 short index, string name) : this (owner, metadata, index, name, true)
4197 internal GenericParameter (MethodDef owner, MetaData metadata,
4198 short index, string name) : this (owner, metadata, index, name, true)
4202 private GenericParameter (MetaDataElement owner, MetaData metadata,
4203 short index, string name, bool nadda)
4206 this.metadata = metadata;
4208 tabIx = MDTable.GenericParam;
4212 internal override uint SortKey() {
4213 return (owner.Row << MetaData.CIxShiftMap[(uint)CIx.TypeOrMethodDef])
4214 | owner.GetCodedIx(CIx.TypeOrMethodDef);
4217 public void AddConstraint (Type constraint) {
4218 metadata.AddToTable (MDTable.GenericParamConstraint,
4219 new GenericParamConstraint (this, constraint));
4222 internal sealed override uint Size(MetaData md) {
4224 md.CodedIndexSize(CIx.TypeOrMethodDef) +
4226 md.TableIndexSize(MDTable.TypeDef));
4229 internal sealed override void BuildTables(MetaData md) {
4231 nameIx = md.AddToStringsHeap(name);
4235 internal sealed override void Write(FileImage output) {
4236 output.Write ((short) index);
4237 output.Write ((short) 0);
4238 output.WriteCodedIndex(CIx.TypeOrMethodDef, owner);
4239 output.Write ((uint) nameIx);
4240 output.WriteIndex(MDTable.TypeDef,owner.Row);
4246 internal class GenericParamConstraint : MetaDataElement
4248 GenericParameter param;
4251 public GenericParamConstraint (GenericParameter param, Type type) {
4254 tabIx = MDTable.GenericParamConstraint;
4257 internal sealed override uint Size(MetaData md) {
4258 return (uint) (md.TableIndexSize(MDTable.GenericParam) +
4259 md.CodedIndexSize(CIx.TypeDefOrRef));
4262 internal sealed override void Write(FileImage output) {
4263 output.WriteIndex(MDTable.GenericParam, param.Row);
4264 output.WriteCodedIndex(CIx.TypeDefOrRef, type);
4270 internal class MethodSpec : MetaDataElement
4273 GenericMethodSig g_sig;
4276 internal MethodSpec (Method meth, GenericMethodSig g_sig) {
4279 tabIx = MDTable.MethodSpec;
4282 internal sealed override void BuildTables (MetaData md) {
4284 sidx = g_sig.GetSigIx (md);
4288 internal sealed override uint Size (MetaData md) {
4289 return (uint) (md.CodedIndexSize(CIx.MethodDefOrRef) +
4290 md.BlobIndexSize ());
4293 internal sealed override void Write (FileImage output) {
4294 output.WriteCodedIndex (CIx.MethodDefOrRef, meth);
4295 output.BlobIndex (sidx);
4299 /**************************************************************************/
4301 /// Descriptor for interface implemented by a class
4303 public class InterfaceImpl: MetaDataElement
4308 internal InterfaceImpl(ClassDef theClass, Class theInterface) {
4309 this.theClass = theClass;
4310 this.theInterface = theInterface;
4311 tabIx = MDTable.InterfaceImpl;
4314 internal sealed override uint Size(MetaData md) {
4315 return md.TableIndexSize(MDTable.TypeDef) +
4316 md.CodedIndexSize(CIx.TypeDefOrRef);
4319 internal sealed override void Write(FileImage output) {
4320 output.WriteIndex(MDTable.TypeDef,theClass.Row);
4321 output.WriteCodedIndex(CIx.TypeDefOrRef,theInterface);
4324 internal sealed override uint GetCodedIx(CIx code) { return 5; }
4327 /**************************************************************************/
4329 /// Descriptor for a local of a method
4333 private static readonly byte Pinned = 0x45;
4336 bool pinned = false, byref = false;
4339 /// Create a new local variable
4341 /// <param name="lName">name of the local variable</param>
4342 /// <param name="lType">type of the local variable</param>
4343 public Local(string lName, Type lType) {
4349 /// Create a new local variable that is byref and/or pinned
4351 /// <param name="lName">local name</param>
4352 /// <param name="lType">local type</param>
4353 /// <param name="byRef">is byref</param>
4354 /// <param name="isPinned">has pinned attribute</param>
4355 public Local(string lName, Type lType, bool byRef, bool isPinned)
4363 internal void TypeSig(MemoryStream str) {
4364 if (pinned) str.WriteByte(Pinned);
4369 /**************************************************************************/
4371 /// Descriptor for the locals for a method
4374 public class LocalSig : Signature
4376 private static readonly byte LocalSigByte = 0x7;
4379 public LocalSig(Local[] locals) {
4380 this.locals = locals;
4381 tabIx = MDTable.StandAloneSig;
4384 internal sealed override void BuildTables(MetaData md) {
4386 MemoryStream sig = new MemoryStream();
4387 sig.WriteByte(LocalSigByte);
4388 MetaData.CompressNum((uint)locals.Length,sig);
4389 for (int i=0; i < locals.Length; i++) {
4390 ((Local)locals[i]).TypeSig(sig);
4392 sigIx = md.AddToBlobHeap(sig.ToArray());
4398 /**************************************************************************/
4400 /// Descriptor for resources used in this PE file
4403 public class ManifestResource : MetaDataElement
4405 public static readonly uint PublicResource = 0x1;
4406 public static readonly uint PrivateResource = 0x2;
4409 MetaDataElement rRef;
4413 byte [] resourceBytes;
4415 public ManifestResource (string name, byte[] resBytes, uint flags) {
4416 InitResource (name, flags);
4417 this.resourceBytes = resBytes;
4420 public ManifestResource(string name, uint flags, FileRef fileRef) {
4421 InitResource (name, flags);
4425 public ManifestResource(string name, uint flags, FileRef fileRef,
4427 InitResource (name, flags);
4429 fileOffset = fileIx;
4432 public ManifestResource(string name, uint flags, AssemblyRef assemRef) {
4433 InitResource (name, flags);
4437 internal ManifestResource (ManifestResource mres) {
4438 mrName = mres.mrName;
4441 this.fileOffset = fileOffset;
4442 this.resourceBytes = resourceBytes;
4445 private void InitResource (string name, uint flags) {
4448 tabIx = MDTable.ManifestResource;
4451 internal sealed override void BuildTables(MetaData md) {
4453 md.AddToTable (MDTable.ManifestResource, this);
4454 nameIx = md.AddToStringsHeap(mrName);
4455 if (resourceBytes != null) {
4457 throw new Exception("ERROR: Manifest Resource has byte value and file reference");
4458 fileOffset = md.AddResource(resourceBytes);
4461 throw new Exception("ERROR: Manifest Resource has no implementation or value");
4462 rRef.BuildTables (md);
4468 internal sealed override uint Size(MetaData md) {
4469 return 8 + md.StringsIndexSize() +
4470 md.CodedIndexSize(CIx.Implementation);
4473 internal sealed override void Write(FileImage output) {
4474 output.Write(fileOffset);
4475 output.Write(flags);
4476 output.StringsIndex(nameIx);
4477 output.WriteCodedIndex(CIx.Implementation,rRef);
4480 internal sealed override uint GetCodedIx(CIx code) { return 18; }
4482 public string Name {
4483 get { return mrName; }
4484 set { mrName = value; }
4488 /**************************************************************************/
4490 /// Base class for elements in the PropertyMap, EventMap and
4491 /// NestedClass MetaData tables
4493 public class MapElem : MetaDataElement
4499 internal MapElem(ClassDef par, uint elIx, MDTable elemTab) {
4502 elemTable = elemTab;
4505 internal sealed override uint Size(MetaData md) {
4506 return md.TableIndexSize(MDTable.TypeDef) + md.TableIndexSize(elemTable);
4509 internal sealed override void Write(FileImage output) {
4510 output.WriteIndex(MDTable.TypeDef,parent.Row);
4511 output.WriteIndex(elemTable,elemIx);
4514 /**************************************************************************/
4516 /// Base class for field/methods (member of a class)
4518 public abstract class Member : MetaDataElement
4520 protected string name;
4521 protected uint nameIx = 0, sigIx = 0;
4523 internal Member(string memName)
4526 tabIx = MDTable.MemberRef;
4530 /**************************************************************************/
4533 /// Root (20 bytes + UTF-8 Version String + quad align padding)
4534 /// StreamHeaders (8 bytes + null terminated name string + quad align padding)
4536 /// #~ (always present - holds metadata tables)
4537 /// #Strings (always present - holds identifier strings)
4538 /// #US (Userstring heap)
4539 /// #Blob (signature blobs)
4540 /// #GUID (guids for assemblies or Modules)
4543 public class MetaData
4545 internal static readonly int[] CIxShiftMap = {2,2,5,1,2,3,1,1,1,2,3,2,1};
4546 private static readonly byte StringsHeapMask = 0x1;
4547 private static readonly byte GUIDHeapMask = 0x2;
4548 private static readonly byte BlobHeapMask = 0x4;
4549 private static readonly uint MetaDataSignature = 0x424A5342;
4550 private static readonly uint maxSmlIxSize = 0xFFFF;
4551 private static readonly uint max1BitSmlIx = 0x7FFF;
4552 private static readonly uint max2BitSmlIx = 0x3FFF;
4553 private static readonly uint max3BitSmlIx = 0x1FFF;
4554 private static readonly uint max5BitSmlIx = 0x7FF;
4555 // NOTE: version and stream name strings MUST always be quad padded
4556 private static readonly string version = "v1.0.3705\0\0\0";
4557 private static readonly char[] tildeName = {'#','~','\0','\0'};
4558 private static readonly char[] stringsName = {'#','S','t','r','i','n','g','s','\0','\0','\0','\0'};
4559 private static readonly char[] usName = {'#','U','S','\0'};
4560 private static readonly char[] guidName = {'#','G','U','I','D','\0','\0','\0'};
4561 private static readonly char[] blobName = {'#','B','l','o','b','\0','\0','\0'};
4562 private static readonly uint MetaDataHeaderSize = 20 + (uint)version.Length;
4563 private static readonly uint TildeHeaderSize = 24;
4564 private static readonly uint StreamHeaderSize = 8;
4565 private static readonly uint numMetaDataTables = (int)MDTable.GenericParamConstraint + 1;
4566 private static readonly uint tildeHeaderSize = 8 + (uint)tildeName.Length;
4568 MetaDataStream strings, us, guid, blob;
4570 MetaDataStream[] streams = new MetaDataStream[5];
4571 uint numStreams = 5;
4572 uint tildeTide = 0, tildePadding = 0, tildeStart = 0;
4573 uint numTables = 0, resourcesSize = 0;
4574 ArrayList[] metaDataTables = new ArrayList[numMetaDataTables];
4575 ArrayList byteCodes = new ArrayList();
4576 uint codeSize = 0, codeStart, byteCodePadding = 0, metaDataSize = 0;
4577 ulong valid = 0, /*sorted = 0x000002003301FA00;*/ sorted = 0;
4578 bool[] largeIx = new bool[numMetaDataTables];
4579 bool[] lgeCIx = new bool[(int)CIx.MaxCIx];
4580 bool largeStrings = false, largeUS = false, largeGUID = false, largeBlob = false;
4581 private FileImage file;
4582 private byte heapSizes = 0;
4583 MetaDataElement entryPoint;
4584 BinaryWriter output;
4585 public MSCorLib mscorlib;
4586 private TypeSpec[] systemTypeSpecs = new TypeSpec[PrimitiveType.NumSystemTypes];
4588 private ArrayList cattr_list;
4589 ArrayList resources;
4591 internal MetaData(FileImage file) {
4592 // tilde = new MetaDataStream(tildeName,false,0);
4594 strings = new MetaDataStream(stringsName,new UTF8Encoding(),true);
4595 us = new MetaDataStream(usName,new UnicodeEncoding(),true);
4596 guid = new MetaDataStream(guidName,false);
4597 blob = new MetaDataStream(blobName,true);
4598 streams[1] = strings;
4602 for (int i=0; i < numMetaDataTables; i++) {
4605 for (int i=0; i < lgeCIx.Length; i++) {
4608 mscorlib = new MSCorLib(this);
4611 internal TypeSpec GetPrimitiveTypeSpec(int ix) {
4612 return systemTypeSpecs[ix];
4615 internal void SetPrimitiveTypeSpec(int ix, TypeSpec typeSpec) {
4616 systemTypeSpecs[ix] = typeSpec;
4619 internal uint Size() {
4620 return metaDataSize;
4624 private void CalcHeapSizes ()
4626 if (strings.LargeIx()) {
4627 largeStrings = true;
4628 heapSizes |= StringsHeapMask;
4630 if (guid.LargeIx()) {
4632 heapSizes |= GUIDHeapMask;
4634 if (blob.LargeIx()) {
4636 heapSizes |= BlobHeapMask;
4639 largeUS = us.LargeIx();
4642 internal void StreamSize(byte mask) {
4646 internal uint AddToUSHeap(string str) {
4647 if (str == null) return 0;
4648 return us.Add(str,true);
4651 internal uint AddToUSHeap(byte[] str) {
4652 if (str == null) return 0;
4653 return us.Add (str, true);
4656 internal uint AddToStringsHeap(string str) {
4657 if ((str == null) || (str.CompareTo("") == 0)) return 0;
4658 return strings.Add(str,false);
4661 internal uint AddToGUIDHeap(Guid guidNum) {
4662 return guid.Add(guidNum, false);
4665 internal uint AddToBlobHeap(byte[] blobBytes) {
4666 if (blobBytes == null) return 0;
4667 return blob.Add(blobBytes, true);
4670 internal uint AddToBlobHeap(byte val) {
4671 return blob.Add(val, true);
4674 internal uint AddToBlobHeap(sbyte val) {
4675 return blob.Add(val, true);
4678 internal uint AddToBlobHeap(ushort val) {
4679 return blob.Add(val, true);
4682 internal uint AddToBlobHeap(short val) {
4683 return blob.Add(val, true);
4686 internal uint AddToBlobHeap(uint val) {
4687 return blob.Add(val, true);
4690 internal uint AddToBlobHeap(int val) {
4691 return blob.Add(val, true);
4694 internal uint AddToBlobHeap(ulong val) {
4695 return blob.Add(val, true);
4698 internal uint AddToBlobHeap(long val) {
4699 return blob.Add(val, true);
4702 internal uint AddToBlobHeap(float val) {
4703 return blob.Add(val, true);
4706 internal uint AddToBlobHeap(double val) {
4707 return blob.Add(val, true);
4710 internal uint AddToBlobHeap(string val) {
4711 return blob.Add(val,true);
4714 internal void AddCustomAttribute (CustomAttribute cattr)
4716 if (cattr_list == null)
4717 cattr_list = new ArrayList ();
4718 cattr_list.Add (cattr);
4721 private ArrayList GetTable(MDTable tableIx) {
4722 int tabIx = (int)tableIx;
4723 if (metaDataTables[tabIx] == null) {
4724 metaDataTables[tabIx] = new ArrayList();
4725 valid |= ((ulong)0x1 << tabIx);
4726 // Console.WriteLine("after creating table " + tableIx + "(" + tabIx + ") valid = " + valid);
4729 return metaDataTables[tabIx];
4732 internal void AddToTable(MDTable tableIx, MetaDataElement elem) {
4734 // Console.Out.WriteLine("ERROR - element already in table " + tableIx);
4737 // updates Row field of the element
4738 // Console.WriteLine("Adding element to table " + (uint)tableIx);
4739 ArrayList table = GetTable(tableIx);
4740 elem.Row = (uint)table.Count + 1;
4744 internal uint TableIndex(MDTable tableIx) {
4745 if (metaDataTables[(int)tableIx] == null) return 1;
4746 return (uint)metaDataTables[(int)tableIx].Count+1;
4749 internal uint AddCode(CILInstructions byteCode) {
4750 byteCodes.Add(byteCode);
4751 uint offset = codeSize + codeStart;
4752 codeSize += byteCode.GetCodeSize();
4756 internal void SetEntryPoint(MetaDataElement ep) {
4760 internal uint AddResource(byte[] resBytes) {
4761 if (resources == null) resources = new ArrayList ();
4762 resources.Add (resBytes);
4763 uint offset = resourcesSize;
4764 resourcesSize += (uint)resBytes.Length + 4;
4768 internal void AddData(DataConstant cVal) {
4769 file.AddInitData(cVal);
4772 internal static void CompressNum(uint val, MemoryStream sig) {
4774 sig.WriteByte((byte)val);
4775 } else if (val < 0x3FFF) {
4776 byte b1 = (byte)((val >> 8) | 0x80);
4777 byte b2 = (byte)(val & FileImage.iByteMask[0]);
4781 byte b1 = (byte)((val >> 24) | 0xC0);
4782 byte b2 = (byte)((val & FileImage.iByteMask[2]) >> 16);
4783 byte b3 = (byte)((val & FileImage.iByteMask[1]) >> 8);;
4784 byte b4 = (byte)(val & FileImage.iByteMask[0]);
4792 internal uint CodeSize() {
4793 return codeSize + byteCodePadding;
4796 internal uint GetResourcesSize()
4798 return resourcesSize;
4801 internal uint StringsIndexSize() {
4802 if (largeStrings) return 4;
4806 internal uint GUIDIndexSize() {
4807 if (largeGUID) return 4;
4811 internal uint USIndexSize() {
4812 if (largeUS) return 4;
4816 internal uint BlobIndexSize() {
4817 if (largeBlob) return 4;
4821 internal uint CodedIndexSize(CIx code) {
4822 if (lgeCIx[(uint)code]) return 4;
4826 internal uint TableIndexSize(MDTable tabIx) {
4827 if (largeIx[(uint)tabIx]) return 4;
4831 private void SetIndexSizes() {
4832 for (int i=0; i < numMetaDataTables; i++) {
4833 if (metaDataTables[i] == null)
4836 uint count = (uint)metaDataTables[i].Count;
4837 if (count > maxSmlIxSize)
4840 MDTable tabIx = (MDTable)i;
4841 if (count > max5BitSmlIx) {
4842 lgeCIx[(int)CIx.HasCustomAttr] = true;
4844 if (count > max3BitSmlIx) {
4845 if ((tabIx == MDTable.TypeRef) || (tabIx == MDTable.ModuleRef) || (tabIx == MDTable.Method) || (tabIx == MDTable.TypeSpec) || (tabIx == MDTable.Field))
4846 lgeCIx[(int)CIx.CustomAttributeType] = true;
4847 if ((tabIx == MDTable.Method) || (tabIx == MDTable.MemberRef))
4848 lgeCIx[(int)CIx.MemberRefParent] = true;
4850 if (count > max2BitSmlIx) {
4851 if ((tabIx == MDTable.Field) || (tabIx == MDTable.Param) || (tabIx == MDTable.Property))
4852 lgeCIx[(int)CIx.HasConst] = true;
4853 if ((tabIx == MDTable.TypeDef) || (tabIx == MDTable.TypeRef) || (tabIx == MDTable.TypeSpec))
4854 lgeCIx[(int)CIx.TypeDefOrRef] = true;
4855 if ((tabIx == MDTable.TypeDef) || (tabIx == MDTable.Method) || (tabIx == MDTable.Assembly))
4856 lgeCIx[(int)CIx.HasDeclSecurity] = true;
4857 if ((tabIx == MDTable.File) || (tabIx == MDTable.AssemblyRef) || (tabIx == MDTable.ExportedType))
4858 lgeCIx[(int)CIx.Implementation] = true;
4859 if ((tabIx == MDTable.Module) || (tabIx == MDTable.ModuleRef) || (tabIx == MDTable.AssemblyRef) || (tabIx == MDTable.TypeRef))
4860 lgeCIx[(int)CIx.ResolutionScope] = true;
4862 if (count > max1BitSmlIx) {
4863 if ((tabIx == MDTable.Field) || (tabIx == MDTable.Param))
4864 lgeCIx[(int)CIx.HasFieldMarshal] = true;
4865 if ((tabIx == MDTable.Event) || (tabIx == MDTable.Property))
4866 lgeCIx[(int)CIx.HasSemantics] = true;
4867 if ((tabIx == MDTable.Method) || (tabIx == MDTable.MemberRef))
4868 lgeCIx[(int)CIx.MethodDefOrRef] = true;
4869 if ((tabIx == MDTable.Field) || (tabIx == MDTable.Method))
4870 lgeCIx[(int)CIx.MemberForwarded] = true;
4871 if ((tabIx == MDTable.TypeDef) || (tabIx == MDTable.Method))
4872 lgeCIx[(int)CIx.TypeOrMethodDef] = true;
4877 private void SetStreamOffsets() {
4878 uint sizeOfHeaders = StreamHeaderSize + (uint)tildeName.Length;
4879 for (int i=1; i < numStreams; i++) {
4880 sizeOfHeaders += streams[i].headerSize();
4882 metaDataSize = MetaDataHeaderSize + sizeOfHeaders;
4883 tildeStart = metaDataSize;
4884 metaDataSize += tildeTide + tildePadding;
4885 for (int i=1; i < numStreams; i++) {
4886 streams[i].Start = metaDataSize;
4887 metaDataSize += streams[i].Size();
4888 streams[i].WriteDetails();
4892 internal void CalcTildeStreamSize() {
4894 //tilde.SetIndexSizes(strings.LargeIx(),us.LargeIx(),guid.LargeIx(),blob.LargeIx());
4895 tildeTide = TildeHeaderSize;
4896 tildeTide += 4 * numTables;
4897 //Console.WriteLine("Tilde header + sizes = " + tildeTide);
4898 for (int i=0; i < numMetaDataTables; i++) {
4899 if (metaDataTables[i] != null) {
4900 ArrayList table = metaDataTables[i];
4901 // Console.WriteLine("Meta data table " + i + " at offset " + tildeTide);
4902 tildeTide += (uint)table.Count * ((MetaDataElement)table[0]).Size(this);
4903 // Console.WriteLine("Metadata table " + i + " has size " + table.Count);
4904 // Console.WriteLine("tildeTide = " + tildeTide);
4907 if ((tildeTide % 4) != 0) tildePadding = 4 - (tildeTide % 4);
4908 //Console.WriteLine("tildePadding = " + tildePadding);
4911 internal void WriteTildeStream(FileImage output) {
4912 long startTilde = output.Seek(0,SeekOrigin.Current);
4913 output.Write((uint)0); // Reserved
4914 output.Write((byte)1); // MajorVersion
4915 output.Write((byte)0); // MinorVersion
4916 output.Write(heapSizes);
4917 output.Write((byte)1); // Reserved
4918 output.Write(valid);
4919 output.Write(sorted);
4920 for (int i=0; i < numMetaDataTables; i++) {
4921 if (metaDataTables[i] != null) {
4922 uint count = (uint)metaDataTables[i].Count;
4923 output.Write(count);
4926 long tabStart = output.Seek(0,SeekOrigin.Current);
4927 // Console.WriteLine("Starting metaData tables at " + tabStart);
4928 for (int i=0; i < numMetaDataTables; i++) {
4929 if (metaDataTables[i] != null) {
4930 // Console.WriteLine("Starting metaData table " + i + " at " + (output.Seek(0,SeekOrigin.Current) - startTilde));
4931 ArrayList table = metaDataTables[i];
4932 for (int j=0; j < table.Count; j++) {
4933 ((MetaDataElement)table[j]).Write(output);
4937 // Console.WriteLine("Writing padding at " + output.Seek(0,SeekOrigin.Current));
4938 for (int i=0; i < tildePadding; i++) output.Write((byte)0);
4941 private void BuildTable(ArrayList table) {
4942 if (table == null) return;
4943 for (int j=0; j < table.Count; j++) {
4944 ((MetaDataElement)table[j]).BuildTables(this);
4948 private void SortTable (ArrayList mTable) {
4949 if (mTable == null) return;
4951 for (int i=0; i < mTable.Count; i++) {
4952 ((MetaDataElement)mTable[i]).Row = (uint)i+1;
4956 internal void BuildMetaData(uint codeStartOffset) {
4957 codeStart = codeStartOffset;
4958 BuildTable(metaDataTables[(int)MDTable.TypeDef]);
4959 BuildTable(metaDataTables[(int)MDTable.MemberRef]);
4960 BuildTable(metaDataTables[(int)MDTable.GenericParam]);
4961 BuildTable(metaDataTables[(int)MDTable.MethodSpec]);
4962 BuildTable(metaDataTables[(int)MDTable.GenericParamConstraint]);
4963 BuildTable(metaDataTables[(int)MDTable.ManifestResource]);
4965 if (cattr_list != null) {
4966 foreach (CustomAttribute cattr in cattr_list)
4967 cattr.BuildTables (this);
4970 /* for (int i=0; i < metaDataTables.Length; i++) {
4971 ArrayList table = metaDataTables[i];
4972 if (table != null) {
4973 for (int j=0; j < table.Count; j++) {
4974 ((MetaDataElement)table[j]).BuildTables(this);
4981 for (int i=1; i < numStreams; i++) {
4982 streams[i].EndStream();
4984 CalcTildeStreamSize();
4986 byteCodePadding = NumToAlign(codeSize,4);
4987 if (entryPoint != null) file.SetEntryPoint(entryPoint.Token());
4989 // Check ordering of specific tables
4990 // Constant, CustomAttribute, FieldMarshal, DeclSecurity, MethodSemantics
4991 // ImplMap, GenericParam
4992 // Need to load GenericParamConstraint AFTER GenericParam table in correct order
4994 // InterfaceImpl, ClassLayout, FieldLayout, MethodImpl, FieldRVA, NestedClass
4995 // will _ALWAYS_ be in the correct order as embedded in BuildMDTables
4997 SortTable(metaDataTables[(int)MDTable.Constant]);
4998 SortTable(metaDataTables[(int)MDTable.CustomAttribute]);
4999 SortTable(metaDataTables[(int)MDTable.FieldMarshal]);
5000 SortTable(metaDataTables[(int)MDTable.DeclSecurity]);
5001 SortTable(metaDataTables[(int)MDTable.MethodSemantics]);
5002 SortTable(metaDataTables[(int)MDTable.ImplMap]);
5003 if (metaDataTables[(int)MDTable.GenericParam] != null) {
5004 SortTable(metaDataTables[(int)MDTable.GenericParam]);
5005 // Now add GenericParamConstraints
5006 /*for (int i=0; i < metaDataTables[(int)MDTable.GenericParam].Count; i++) {
5007 ((GenericParameter)metaDataTables[(int)MDTable.GenericParam][i]).AddConstraints(this);
5010 SortTable(metaDataTables[(int)MDTable.GenericParamConstraint]);
5014 internal void WriteByteCodes(FileImage output) {
5015 for (int i=0; i < byteCodes.Count; i++) {
5016 ((CILInstructions)byteCodes[i]).Write(output);
5018 for (int i=0; i < byteCodePadding; i++) {
5019 output.Write((byte)0);
5023 internal void WriteResources (FileImage output) {
5024 if (resources == null) return;
5025 for (int i = 0; i < resources.Count; i ++) {
5026 byte [] resBytes = (byte []) resources [i];
5027 output.Write ((uint) resBytes.Length);
5028 output.Write (resBytes);
5032 internal void WriteMetaData(FileImage output) {
5033 this.output = output;
5034 mdStart = output.Seek(0,SeekOrigin.Current);
5035 // Console.WriteLine("Writing metaData at " + Hex.Long(mdStart));
5036 output.Write(MetaDataSignature);
5037 output.Write((short)1); // Major Version
5038 output.Write((short)1); // Minor Version ECMA = 0, PEFiles = 1
5039 output.Write(0); // Reserved
5040 output.Write(version.Length);
5041 output.Write(version.ToCharArray()); // version string is already zero padded
5042 output.Write((short)0);
5043 output.Write((ushort)numStreams);
5044 // write tilde header
5045 output.Write(tildeStart);
5046 output.Write(tildeTide + tildePadding);
5047 output.Write(tildeName);
5048 for (int i=1; i < numStreams; i++) streams[i].WriteHeader(output);
5049 // Console.WriteLine("Writing tilde stream at " + output.Seek(0,SeekOrigin.Current) + " = " + tildeStart);
5050 WriteTildeStream(output);
5051 for (int i=1; i < numStreams; i++) streams[i].Write(output);
5052 // Console.WriteLine("Finished Writing metaData at " + output.Seek(0,SeekOrigin.Current));
5055 internal bool LargeStringsIndex() { return strings.LargeIx(); }
5056 internal bool LargeGUIDIndex() { return guid.LargeIx(); }
5057 internal bool LargeUSIndex() { return us.LargeIx(); }
5058 internal bool LargeBlobIndex() { return blob.LargeIx(); }
5060 internal bool LargeIx(MDTable tabIx) { return largeIx[(uint)tabIx]; }
5063 private uint NumToAlign(uint val, uint alignVal) {
5064 if ((val % alignVal) == 0) return 0;
5065 return alignVal - (val % alignVal);
5068 internal void WriteCodedIndex(CIx code, MetaDataElement elem, FileImage output) {
5071 ix = (elem.Row << CIxShiftMap[(uint)code]) | elem.GetCodedIx(code);
5072 // Console.WriteLine("coded index = " + ix + " row = " + elem.Row);
5074 // Console.WriteLine("elem for coded index is null");
5076 if (lgeCIx[(uint)code])
5079 output.Write((ushort)ix);
5084 /// Error for invalid PE file
5086 public class PEFileException : System.Exception {
5087 public PEFileException(string msg) : base("Error in PE File: " + msg) { }
5090 /**************************************************************************/
5092 /// Base class for all Meta Data table elements
5095 public abstract class MetaDataElement: IComparable
5098 protected ArrayList customAttributes;
5099 private uint row = 0;
5100 protected bool done = false;
5101 protected MDTable tabIx;
5102 protected bool sortTable = false;
5104 internal MetaDataElement() { }
5111 if (row == 0) row = value;
5115 internal virtual uint GetCodedIx(CIx code) { return 0; }
5118 /// Add a custom attribute to this item
5120 /// <param name="ctorMeth">the constructor method for this attribute</param>
5121 /// <param name="val">the byte value of the parameters</param>
5122 public void AddCustomAttribute(Method ctorMeth, byte[] val) {
5123 if (customAttributes == null) {
5124 customAttributes = new ArrayList();
5126 customAttributes.Add(new CustomAttribute(this,ctorMeth,val));
5130 /// Add a custom attribute to this item
5132 /// <param name="ctorMeth">the constructor method for this attribute</param>
5133 /// <param name="val">the constant values of the parameters</param>
5134 public void AddCustomAttribute(Method ctorMeth, Constant[] cVals) {
5135 if (customAttributes == null) {
5136 customAttributes = new ArrayList();
5138 // customAttributes.Add(new CustomAttribute(this,ctorMeth,cVals));
5141 internal uint Token() {
5142 return (((uint)tabIx << 24) | row);
5145 internal virtual void BuildTables(MetaData md) {
5149 internal virtual uint Size(MetaData md) {
5153 internal virtual void Write(FileImage output) { }
5155 internal virtual uint SortKey()
5157 throw new PEFileException("Trying to sort table of " + this);
5161 internal virtual uint SortKey2()
5167 public int CompareTo(object obj)
5169 uint otherKey = ((MetaDataElement)obj).SortKey();
5170 uint thisKey = SortKey();
5172 if (thisKey == otherKey)
5174 otherKey = ((MetaDataElement)obj).SortKey2();
5175 thisKey = SortKey2();
5176 if (thisKey == otherKey)
5178 if (thisKey < otherKey)
5182 if (thisKey < otherKey) return -1;
5188 /**************************************************************************/
5190 /// Stream in the Meta Data (#Strings, #US, #Blob and #GUID)
5193 internal class MetaDataStream : BinaryWriter
5195 private static readonly uint StreamHeaderSize = 8;
5196 private static uint maxSmlIxSize = 0xFFFF;
5198 private uint start = 0;
5199 uint size = 0, tide = 1;
5200 bool largeIx = false;
5203 Hashtable htable = new Hashtable();
5204 Hashtable btable = new Hashtable (new ByteArrayHashCodeProvider (), new ByteArrayComparer ());
5206 internal MetaDataStream(char[] name, bool addInitByte) : base(new MemoryStream()) {
5207 if (addInitByte) { Write((byte)0); size = 1; }
5209 sizeOfHeader = StreamHeaderSize + (uint)name.Length;
5212 internal MetaDataStream(char[] name, System.Text.Encoding enc, bool addInitByte) : base(new MemoryStream(),enc) {
5213 if (addInitByte) { Write((byte)0); size = 1; }
5215 sizeOfHeader = StreamHeaderSize + (uint)name.Length;
5227 internal uint headerSize() {
5228 // Console.WriteLine(name + " stream has headersize of " + sizeOfHeader);
5229 return sizeOfHeader;
5232 internal void SetSize(uint siz) {
5236 internal uint Size() {
5240 internal bool LargeIx() {
5244 internal void WriteDetails() {
5245 // Console.WriteLine(name + " - size = " + size);
5248 internal uint Add(string str, bool prependSize) {
5249 Object val = htable[str];
5253 htable[str] = index;
5254 char[] arr = str.ToCharArray();
5255 if (prependSize) CompressNum((uint)arr.Length*2+1);
5258 size = (uint)Seek(0,SeekOrigin.Current);
5264 internal uint Add (byte[] str, bool prependSize) {
5265 Object val = btable [str];
5269 btable [str] = index;
5270 if (prependSize) CompressNum ((uint) str.Length);
5272 size = (uint) Seek (0, SeekOrigin.Current);
5280 internal uint Add(Guid guid, bool prependSize) {
5281 byte [] b = guid.ToByteArray ();
5282 if (prependSize) CompressNum ((uint) b.Length);
5283 Write(guid.ToByteArray());
5284 size =(uint)Seek(0,SeekOrigin.Current);
5288 internal uint Add(byte[] blob) {
5290 CompressNum((uint)blob.Length);
5292 size = (uint)Seek(0,SeekOrigin.Current);
5296 internal uint Add(byte val, bool prependSize) {
5298 if (prependSize) CompressNum (1);
5300 size = (uint)Seek(0,SeekOrigin.Current);
5304 internal uint Add(sbyte val, bool prependSize) {
5306 if (prependSize) CompressNum (1);
5308 size = (uint)Seek(0,SeekOrigin.Current);
5312 internal uint Add(ushort val, bool prependSize) {
5314 if (prependSize) CompressNum (2);
5316 size = (uint)Seek(0,SeekOrigin.Current);
5320 internal uint Add(short val, bool prependSize) {
5322 if (prependSize) CompressNum (2);
5324 size = (uint)Seek(0,SeekOrigin.Current);
5328 internal uint Add(uint val, bool prependSize) {
5330 if (prependSize) CompressNum (4);
5332 size = (uint)Seek(0,SeekOrigin.Current);
5336 internal uint Add(int val, bool prependSize) {
5338 if (prependSize) CompressNum (4);
5340 size = (uint)Seek(0,SeekOrigin.Current);
5344 internal uint Add(ulong val, bool prependSize) {
5346 if (prependSize) CompressNum (8);
5348 size = (uint)Seek(0,SeekOrigin.Current);
5352 internal uint Add(long val, bool prependSize) {
5354 if (prependSize) CompressNum (8);
5356 size = (uint)Seek(0,SeekOrigin.Current);
5360 internal uint Add(float val, bool prependSize) {
5362 if (prependSize) CompressNum (4);
5364 size = (uint)Seek(0,SeekOrigin.Current);
5368 internal uint Add(double val, bool prependSize) {
5370 if (prependSize) CompressNum (8);
5372 size = (uint)Seek(0,SeekOrigin.Current);
5376 private void CompressNum(uint val) {
5379 } else if (val < 0x3FFF) {
5380 byte b1 = (byte)((val >> 8) | 0x80);
5381 byte b2 = (byte)(val & FileImage.iByteMask[0]);
5385 byte b1 = (byte)((val >> 24) | 0xC0);
5386 byte b2 = (byte)((val & FileImage.iByteMask[2]) >> 16);
5387 byte b3 = (byte)((val & FileImage.iByteMask[1]) >> 8);;
5388 byte b4 = (byte)(val & FileImage.iByteMask[0]);
5396 private void QuadAlign() {
5397 if ((size % 4) != 0) {
5398 uint pad = 4 - (size % 4);
5400 for (int i=0; i < pad; i++) {
5406 internal void EndStream() {
5408 if (size > maxSmlIxSize) {
5413 internal void WriteHeader(BinaryWriter output) {
5414 output.Write(start);
5419 internal virtual void Write(BinaryWriter output) {
5420 // Console.WriteLine("Writing " + name + " stream at " + output.Seek(0,SeekOrigin.Current) + " = " + start);
5421 MemoryStream str = (MemoryStream)BaseStream;
5422 output.Write(str.ToArray());
5426 /**************************************************************************/
5428 /// Base class for Method Descriptors
5431 public abstract class Method : Member
5433 protected CallConv callConv = CallConv.Default;
5434 protected Type retType;
5436 internal Method(string methName, Type rType) : base(methName)
5442 /// Add calling conventions to this method descriptor
5444 /// <param name="cconv"></param>
5445 public void AddCallConv(CallConv cconv) {
5449 internal abstract void TypeSig(MemoryStream sig);
5451 internal uint GetSigIx(MetaData md) {
5452 MemoryStream sig = new MemoryStream();
5454 return md.AddToBlobHeap(sig.ToArray());
5457 internal Type GetRetType() {
5462 /**************************************************************************/
5464 /// Descriptor for a method defined in THIS assembly/module
5468 public class MethodDef : Method
5470 private static readonly ushort PInvokeImpl = 0x2000;
5471 //private static readonly uint UnmanagedExport = 0x0008;
5472 // private static readonly byte LocalSigByte = 0x7;
5473 uint parIx = 0, textOffset = 0;
5476 CILInstructions code;
5477 ArrayList securityActions = new ArrayList();
5481 ushort methFlags = 0, implFlags = 0;
5482 int maxStack = 0, numPars = 0;
5483 bool entryPoint = false;
5485 ArrayList varArgSigList;
5486 ImplMap pinvokeImpl;
5489 internal MethodDef(MetaData md, string name, Type retType, Param[] pars) : base(name,retType) {
5492 if (parList != null) numPars = parList.Length;
5493 tabIx = MDTable.Method;
5496 internal MethodDef(MetaData md, MethAttr mAttrSet, ImplAttr iAttrSet, string name, Type retType, Param[] pars) : base(name,retType) {
5499 if (parList != null) numPars = parList.Length;
5500 // Console.WriteLine("Creating method " + name + " with " + numPars + " parameters");
5501 methFlags = (ushort)mAttrSet;
5502 implFlags = (ushort)iAttrSet;
5503 tabIx = MDTable.Method;
5506 internal Param[] GetPars() {
5511 /// Add some attributes to this method descriptor
5513 /// <param name="ma">the attributes to be added</param>
5514 public void AddMethAttribute(MethAttr ma) {
5515 methFlags |= (ushort)ma;
5519 /// Add some implementation attributes to this method descriptor
5521 /// <param name="ia">the attributes to be added</param>
5522 public void AddImplAttribute(ImplAttr ia) {
5523 implFlags |= (ushort)ia;
5526 public void AddPInvokeInfo(ModuleRef scope, string methName,
5527 PInvokeAttr callAttr) {
5528 pinvokeImpl = new ImplMap((ushort)callAttr,this,methName,scope);
5529 methFlags |= PInvokeImpl;
5533 /// Add a named generic type parameter
5535 public GenericParameter AddGenericParameter (short index, string name) {
5536 GenericParameter gp = new GenericParameter (this, metaData, index, name);
5537 metaData.AddToTable (MDTable.GenericParam, gp);
5542 /// Set the maximum stack height for this method
5544 /// <param name="maxStack">the maximum height of the stack</param>
5545 public void SetMaxStack(int maxStack) {
5546 this.maxStack = maxStack;
5550 /// Add local variables to this method
5552 /// <param name="locals">the locals to be added</param>
5553 /// <param name="initLocals">are locals initialised to default values</param>
5554 public void AddLocals(Local[] locals, bool initLocals) {
5555 this.locals = locals;
5556 this.initLocals = initLocals;
5560 /// Mark this method as having an entry point
5562 public void DeclareEntryPoint() {
5567 /// Create a code buffer for this method to add the IL instructions to
5569 /// <returns>a buffer for this method's IL instructions</returns>
5570 public CILInstructions CreateCodeBuffer() {
5571 code = new CILInstructions(metaData);
5576 /// Make a method reference descriptor for this method to be used
5577 /// as a callsite signature for this vararg method
5579 /// <param name="optPars">the optional pars for the vararg method call</param>
5580 /// <returns></returns>
5581 public MethodRef MakeVarArgSignature(Type[] optPars) {
5582 Type[] pars = new Type[numPars];
5583 MethodRef varArgSig;
5584 for (int i=0; i < numPars; i++) {
5585 pars[i] = parList[i].GetParType();
5587 varArgSig = new MethodRef(this,name,retType,pars,true,optPars);
5589 if (varArgSigList == null)
5590 varArgSigList = new ArrayList ();
5591 varArgSigList.Add (varArgSig);
5595 internal sealed override void TypeSig(MemoryStream sig) {
5596 sig.WriteByte((byte)callConv);
5597 MetaData.CompressNum((uint)numPars,sig);
5598 retType.TypeSig(sig);
5599 for (ushort i=0; i < numPars; i++) {
5600 parList[i].seqNo = (ushort)(i+1);
5601 parList[i].TypeSig(sig);
5605 internal sealed override void BuildTables(MetaData md) {
5607 if (pinvokeImpl != null) {
5608 md.AddToTable(MDTable.ImplMap,pinvokeImpl);
5609 pinvokeImpl.BuildTables(md);
5611 if (entryPoint) md.SetEntryPoint(this);
5613 if (locals != null) {
5614 localSig = new LocalSig(locals);
5615 md.AddToTable(MDTable.StandAloneSig,localSig);
5616 localSig.BuildTables(md);
5617 locToken = localSig.Token();
5620 code.CheckCode(locToken,initLocals,maxStack);
5621 textOffset = md.AddCode(code);
5623 nameIx = md.AddToStringsHeap(name);
5624 sigIx = GetSigIx(md);
5625 parIx = md.TableIndex(MDTable.Param);
5626 for (int i=0; i < numPars; i++) {
5627 md.AddToTable(MDTable.Param,parList[i]);
5628 parList[i].BuildTables(md);
5630 if (varArgSigList != null) {
5631 foreach (MethodRef varArgSig in varArgSigList) {
5632 md.AddToTable(MDTable.MemberRef,varArgSig);
5633 varArgSig.BuildTables(md);
5636 // Console.WriteLine("method has " + numPars + " parameters");
5640 internal sealed override uint Size(MetaData md) {
5641 return 8 + md.StringsIndexSize() + md.BlobIndexSize() + md.TableIndexSize(MDTable.Param);
5644 internal sealed override void Write(FileImage output) {
5645 if (ZeroRva ()) output.Write(0);
5646 else output.WriteCodeRVA(textOffset);
5647 output.Write(implFlags);
5648 output.Write(methFlags);
5649 output.StringsIndex(nameIx);
5650 output.BlobIndex(sigIx);
5651 output.WriteIndex(MDTable.Param,parIx);
5654 internal bool ZeroRva () {
5655 return (((methFlags & (ushort)MethAttr.Abstract) != 0) ||
5656 ((implFlags & (ushort)ImplAttr.Runtime) != 0) ||
5657 ((implFlags & (ushort)ImplAttr.InternalCall) != 0) ||
5658 (pinvokeImpl != null)); // TODO: Not entirely true but works for now
5661 internal sealed override uint GetCodedIx(CIx code) {
5663 case (CIx.HasCustomAttr) : return 0;
5664 case (CIx.HasDeclSecurity) : return 1;
5665 case (CIx.MemberRefParent) : return 3;
5666 case (CIx.MethodDefOrRef) : return 0;
5667 case (CIx.MemberForwarded) : return 1;
5668 case (CIx.CustomAttributeType) : return 2;
5669 case (CIx.TypeOrMethodDef) : return 1;
5675 /**************************************************************************/
5677 /// Descriptor for an overriding method (.override)
5679 public class MethodImpl : MetaDataElement
5682 Method header, body;
5684 internal MethodImpl(ClassDef par, Method decl, Method bod) {
5688 tabIx = MDTable.MethodImpl;
5691 internal sealed override uint Size(MetaData md) {
5692 return md.TableIndexSize(MDTable.TypeDef) + 2 * md.CodedIndexSize(CIx.MethodDefOrRef);
5695 internal sealed override void Write(FileImage output) {
5696 output.WriteIndex(MDTable.TypeDef,parent.Row);
5697 output.WriteCodedIndex(CIx.MethodDefOrRef,body);
5698 output.WriteCodedIndex(CIx.MethodDefOrRef,header);
5702 /**************************************************************************/
5704 /// Descriptor for a method defined in another assembly/module
5706 public class MethodRef : Method
5708 private static readonly byte Sentinel = 0x41;
5709 Type[] parList, optParList;
5710 MetaDataElement parent;
5711 uint numPars = 0, numOptPars = 0;
5713 internal MethodRef(MetaDataElement paren, string name, Type retType,
5714 Type[] pars, bool varArgMeth, Type[] optPars) : base(name,retType) {
5717 if (parList != null) numPars = (uint)parList.Length;
5719 optParList = optPars;
5720 if (optParList != null) numOptPars = (uint)optParList.Length;
5721 callConv = CallConv.Vararg;
5725 internal sealed override void TypeSig(MemoryStream sig) {
5726 sig.WriteByte((byte)callConv);
5727 MetaData.CompressNum(numPars+numOptPars,sig);
5728 retType.TypeSig(sig);
5729 for (int i=0; i < numPars; i++) {
5730 parList[i].TypeSig(sig);
5732 if (numOptPars > 0) {
5733 sig.WriteByte(Sentinel);
5734 for (int i=0; i < numOptPars; i++) {
5735 optParList[i].TypeSig(sig);
5740 internal sealed override void BuildTables(MetaData md) {
5742 nameIx = md.AddToStringsHeap(name);
5743 sigIx = GetSigIx(md);
5747 internal sealed override uint Size(MetaData md) {
5748 return md.CodedIndexSize(CIx.MemberRefParent) + md.StringsIndexSize() + md.BlobIndexSize();
5751 internal sealed override void Write(FileImage output) {
5752 output.WriteCodedIndex(CIx.MemberRefParent,parent);
5753 output.StringsIndex(nameIx);
5754 output.BlobIndex(sigIx);
5757 internal sealed override uint GetCodedIx(CIx code) {
5759 case (CIx.HasCustomAttr) : return 6;
5760 case (CIx.MethodDefOrRef) : return 1;
5761 case (CIx.CustomAttributeType) : return 3;
5767 /**************************************************************************/
5769 /// Descriptor for Property and Event methods
5771 public class MethodSemantics : MetaDataElement {
5773 Feature.MethodType type;
5775 Feature eventOrProp;
5777 internal MethodSemantics(Feature.MethodType mType, MethodDef method, Feature feature) {
5780 eventOrProp = feature;
5781 tabIx = MDTable.MethodSemantics;
5784 internal override uint SortKey() {
5785 return eventOrProp.Row;
5788 internal sealed override uint Size(MetaData md) {
5789 return 2 + md.TableIndexSize(MDTable.Method) + md.CodedIndexSize(CIx.HasSemantics);
5792 internal sealed override void Write(FileImage output) {
5793 output.Write((ushort)type);
5794 output.WriteIndex(MDTable.Method,meth.Row);
5795 output.WriteCodedIndex(CIx.HasSemantics,eventOrProp);
5799 /**************************************************************************/
5801 /// Descriptor for a FunctionPointer type
5804 public class MethPtrType : Type
5816 /// Create a new function pointer type
5818 /// <param name="meth">the function to be referenced</param>
5819 public MethPtrType (CallConv callconv, Type retType, Type[] pars,
5820 bool varArgMeth, Type[] optPars) : base(0x1B) {
5821 this.retType = retType;
5822 callConv = callconv;
5824 this.varArgMeth = varArgMeth;
5825 if (parList != null) numPars = (uint)parList.Length;
5827 optParList = optPars;
5828 if (optParList != null) numOptPars = (uint)optParList.Length;
5829 callConv |= CallConv.Vararg;
5831 tabIx = MDTable.TypeSpec;
5834 internal sealed override void TypeSig(MemoryStream sig) {
5835 sig.WriteByte(typeIndex);
5836 // Bootlegged from method ref
5837 sig.WriteByte((byte)callConv);
5838 MetaData.CompressNum (numPars + numOptPars, sig);
5839 retType.TypeSig (sig);
5840 for (int i=0; i < numPars; i++) {
5841 parList[i].TypeSig (sig);
5844 sig.WriteByte (0x41); // Write the sentinel
5845 for (int i=0; i < numOptPars; i++) {
5846 optParList[i].TypeSig (sig);
5851 internal sealed override void BuildTables(MetaData md) {
5853 MemoryStream sig = new MemoryStream();
5855 sigIx = md.AddToBlobHeap(sig.ToArray());
5859 internal sealed override uint Size(MetaData md) {
5860 return md.BlobIndexSize();
5863 internal sealed override void Write(FileImage output) {
5864 output.BlobIndex(sigIx);
5867 internal sealed override uint GetCodedIx(CIx code) { return 0x1B; }
5870 /**************************************************************************/
5872 /// Descriptor for THIS module
5874 public class Module : ResolutionScope
5879 internal Module(string name, MetaData md) : base(name,md) {
5880 mvid = Guid.NewGuid();
5881 mvidIx = md.AddToGUIDHeap(mvid);
5882 tabIx = MDTable.Module;
5886 get { return mvid; }
5889 internal sealed override uint Size(MetaData md) {
5890 return 2 + md.StringsIndexSize() + 3 * md.GUIDIndexSize();
5893 internal sealed override void Write(FileImage output) {
5894 output.Write((short)0);
5895 output.StringsIndex(nameIx);
5896 output.GUIDIndex(mvidIx);
5897 output.GUIDIndex(0);
5898 output.GUIDIndex(0);
5901 internal sealed override uint GetCodedIx(CIx code) {
5903 case (CIx.HasCustomAttr) : return 7;
5904 case (CIx.ResolutionScope) : return 0;
5909 /**************************************************************************/
5911 /// Descriptor for another module in THIS assembly
5913 public class ModuleRef : ResolutionScope, IExternRef
5916 internal ModuleRef(MetaData md, string name) : base(name,md) {
5917 tabIx = MDTable.ModuleRef;
5921 /// Add a class to this external module. This is a class declared in
5922 /// another module of THIS assembly.
5924 /// <param name="nsName">name space name</param>
5925 /// <param name="name">class name</param>
5926 /// <returns>a descriptor for this class in another module</returns>
5927 public ClassRef AddClass(string nsName, string name) {
5928 ClassRef aClass = new ClassRef(nsName,name,metaData);
5929 metaData.AddToTable(MDTable.TypeRef,aClass);
5930 aClass.SetParent(this);
5935 /// Make a file descriptor to correspond to this module. The file
5936 /// descriptor will have the same name as the module descriptor
5938 /// <param name="hashBytes">the hash of the file</param>
5939 /// <param name="hasMetaData">the file contains metadata</param>
5940 /// <param name="entryPoint">the program entry point is in this file</param>
5941 /// <returns>a descriptor for the file which contains this module</returns>
5942 public FileRef MakeFile(byte[] hashBytes, bool hasMetaData, bool entryPoint) {
5943 FileRef file = new FileRef(nameIx,hashBytes,hasMetaData,entryPoint,metaData);
5944 metaData.AddToTable(MDTable.File,file);
5949 /// Add a value class to this module. This is a class declared in
5950 /// another module of THIS assembly.
5952 /// <param name="nsName">name space name</param>
5953 /// <param name="name">class name</param>
5954 /// <returns></returns>
5955 public ClassRef AddValueClass(string nsName, string name) {
5956 ClassRef aClass = new ClassRef(nsName,name,metaData);
5957 metaData.AddToTable(MDTable.TypeRef,aClass);
5958 aClass.SetParent(this);
5959 aClass.MakeValueClass(ValueClass.ValueType);
5964 /// Add a class which is declared public in this external module of
5965 /// THIS assembly. This class will be exported from this assembly.
5966 /// The ilasm syntax for this is .extern class
5968 /// <param name="attrSet">attributes of the class to be exported</param>
5969 /// <param name="nsName">name space name</param>
5970 /// <param name="name">external class name</param>
5971 /// <param name="declFile">the file where the class is declared</param>
5972 /// <param name="isValueClass">is this class a value type?</param>
5973 /// <returns>a descriptor for this external class</returns>
5974 public ExternClassRef AddExternClass(TypeAttr attrSet, string nsName,
5975 string name, FileRef declFile,
5976 bool isValueClass) {
5977 ExternClassRef cRef = new ExternClassRef(attrSet,nsName,name,declFile,metaData);
5978 metaData.AddToTable(MDTable.TypeRef,cRef);
5979 cRef.SetParent(this);
5980 if (isValueClass) cRef.MakeValueClass(ValueClass.ValueType);
5985 /// Add a "global" method in another module
5987 /// <param name="name">method name</param>
5988 /// <param name="retType">return type</param>
5989 /// <param name="pars">method parameter types</param>
5990 /// <returns>a descriptor for this method in anther module</returns>
5991 public MethodRef AddMethod(string name, Type retType, Type[] pars) {
5992 MethodRef meth = new MethodRef(this,name,retType,pars,false,null);
5993 metaData.AddToTable(MDTable.MemberRef,meth);
5998 /// Add a vararg method to this class
6000 /// <param name="name">method name</param>
6001 /// <param name="retType">return type</param>
6002 /// <param name="pars">parameter types</param>
6003 /// <param name="optPars">optional param types for this vararg method</param>
6004 /// <returns>a descriptor for this method</returns>
6005 public MethodRef AddVarArgMethod(string name, Type retType,
6006 Type[] pars, Type[] optPars) {
6007 MethodRef meth = new MethodRef(this,name,retType,pars,true,optPars);
6008 metaData.AddToTable(MDTable.MemberRef,meth);
6013 /// Add a field in another module
6015 /// <param name="name">field name</param>
6016 /// <param name="fType">field type</param>
6017 /// <returns>a descriptor for this field in another module</returns>
6018 public FieldRef AddField(string name, Type fType) {
6019 FieldRef field = new FieldRef(this,name,fType);
6020 metaData.AddToTable(MDTable.MemberRef,field);
6024 internal sealed override uint Size(MetaData md) {
6025 return md.StringsIndexSize();
6028 internal sealed override void Write(FileImage output) {
6029 output.StringsIndex(nameIx);
6032 internal sealed override uint GetCodedIx(CIx code) {
6034 case (CIx.HasCustomAttr) : return 12;
6035 case (CIx.MemberRefParent) : return 2;
6036 case (CIx.ResolutionScope) : return 1;
6042 /**************************************************************************/
6044 /// Descriptors for native types used for marshalling
6046 public class NativeType {
6047 public static readonly NativeType Void = new NativeType(0x01);
6048 public static readonly NativeType Boolean = new NativeType(0x02);
6049 public static readonly NativeType Int8 = new NativeType(0x03);
6050 public static readonly NativeType UInt8 = new NativeType(0x04);
6051 public static readonly NativeType Int16 = new NativeType(0x05);
6052 public static readonly NativeType UInt16 = new NativeType(0x06);
6053 public static readonly NativeType Int32 = new NativeType(0x07);
6054 public static readonly NativeType UInt32 = new NativeType(0x08);
6055 public static readonly NativeType Int64 = new NativeType(0x09);
6056 public static readonly NativeType UInt64 = new NativeType(0x0A);
6057 public static readonly NativeType Float32 = new NativeType(0x0B);
6058 public static readonly NativeType Float64 = new NativeType(0x0C);
6059 public static readonly NativeType Currency = new NativeType(0x0F);
6060 public static readonly NativeType BStr = new NativeType(0x13);
6061 public static readonly NativeType LPStr = new NativeType(0x14);
6062 public static readonly NativeType LPWStr = new NativeType(0x15);
6063 public static readonly NativeType LPTStr = new NativeType(0x16);
6064 public static readonly NativeType FixedSysString = new NativeType(0x17);
6065 public static readonly NativeType IUnknown = new NativeType(0x19);
6066 public static readonly NativeType IDispatch = new NativeType(0x1A);
6067 public static readonly NativeType Struct = new NativeType(0x1B);
6068 public static readonly NativeType Interface = new NativeType(0x1C);
6069 public static readonly NativeType Int = new NativeType(0x1F);
6070 public static readonly NativeType UInt = new NativeType(0x20);
6071 public static readonly NativeType ByValStr = new NativeType(0x22);
6072 public static readonly NativeType AnsiBStr = new NativeType(0x23);
6073 public static readonly NativeType TBstr = new NativeType(0x24);
6074 public static readonly NativeType VariantBool = new NativeType(0x25);
6075 public static readonly NativeType FuncPtr = new NativeType(0x26);
6076 public static readonly NativeType AsAny = new NativeType(0x28);
6078 protected byte typeIndex;
6080 internal NativeType(byte tyIx) { typeIndex = tyIx; }
6082 internal byte GetTypeIndex() { return typeIndex; }
6084 internal virtual byte[] ToBlob() {
6085 byte[] bytes = new byte[1];
6086 bytes[0] = GetTypeIndex();
6092 public class NativeArray : NativeType
6094 NativeType elemType;
6095 uint len = 0, parNum = 0;
6098 public NativeArray(NativeType elemType) : base(0x2A) {
6099 this.elemType = elemType;
6102 public NativeArray(NativeType elemType, int len) : base(0x2A) {
6103 this.elemType = elemType;
6107 public NativeArray(NativeType elemType, int numElem, int parNumForLen) : base(0x2A) {
6108 this.elemType = elemType;
6109 len = (uint)numElem;
6110 parNum = (uint)parNumForLen;
6113 internal override byte[] ToBlob() {
6114 MemoryStream str = new MemoryStream();
6115 str.WriteByte(GetTypeIndex());
6116 if (elemType == null) str.WriteByte(0x50); // no info (MAX)
6117 else str.WriteByte(elemType.GetTypeIndex());
6118 MetaData.CompressNum(parNum,str);
6120 MetaData.CompressNum(len,str);
6121 return str.ToArray();
6126 public class SafeArray : NativeType
6128 SafeArrayType elemType;
6130 public SafeArray(SafeArrayType elemType) : base(0x1D) {
6131 this.elemType = elemType;
6134 internal override byte[] ToBlob() {
6135 byte[] bytes = new byte[2];
6136 bytes[0] = GetTypeIndex();
6137 bytes[1] = (byte)elemType;
6143 public class FixedArray : NativeType
6145 NativeType elemType;
6148 public FixedArray(NativeType elemType, int numElems) : base(0x1E) {
6149 this.elemType = elemType;
6150 numElem = (uint)numElems;
6153 internal override byte[] ToBlob() {
6154 MemoryStream str = new MemoryStream();
6155 str.WriteByte(GetTypeIndex());
6156 MetaData.CompressNum(numElem,str);
6157 if (elemType == null) str.WriteByte(0x50); // no info (MAX)
6158 else str.WriteByte(elemType.GetTypeIndex());
6159 return str.ToArray();
6164 public class CustomMarshaller : NativeType
6167 string marshallerName;
6170 public CustomMarshaller(string typeNameOrGUID, string marshallerName,
6171 string optCookie) : base(0x2C) {
6172 typeName = typeNameOrGUID;
6173 this.marshallerName = marshallerName;
6177 internal override byte[] ToBlob() {
6178 MemoryStream str = new MemoryStream();
6179 BinaryWriter bw = new BinaryWriter(str,new UTF8Encoding());
6180 bw.Write(GetTypeIndex());
6181 bw.Write(typeName.ToCharArray());
6183 bw.Write(marshallerName.ToCharArray());
6185 if (cookie != null) bw.Write(cookie.ToCharArray());
6188 return str.ToArray();
6192 /**************************************************************************/
6194 /// Descriptor for a parameter of a method defined in this assembly/module
6196 public class Param : MetaDataElement
6198 private static readonly ushort hasDefault = 0x1000;
6199 private static readonly ushort hasFieldMarshal = 0x2000;
6203 internal ushort seqNo = 0;
6205 ConstantElem defaultVal;
6207 FieldMarshal marshalInfo;
6210 /// Create a new parameter for a method
6212 /// <param name="mode">param mode (in, out, opt)</param>
6213 /// <param name="parName">parameter name</param>
6214 /// <param name="parType">parameter type</param>
6215 public Param(ParamAttr mode, string parName, Type parType) {
6218 parMode = (ushort)mode;
6219 tabIx = MDTable.Param;
6223 /// Add a default value to this parameter
6225 /// <param name="c">the default value for the parameter</param>
6226 public void AddDefaultValue(Constant cVal) {
6227 defaultVal = new ConstantElem(this,cVal);
6228 parMode |= hasDefault;
6232 /// Add marshalling information about this parameter
6234 public void AddMarshallInfo(NativeType marshallType) {
6235 parMode |= hasFieldMarshal;
6236 marshalInfo = new FieldMarshal(this,marshallType);
6239 internal Type GetParType() { return pType; }
6241 internal sealed override void BuildTables(MetaData md) {
6243 nameIx = md.AddToStringsHeap(pName);
6244 if (defaultVal != null) {
6245 md.AddToTable(MDTable.Constant,defaultVal);
6246 defaultVal.BuildTables(md);
6248 if (marshalInfo != null) {
6249 md.AddToTable(MDTable.FieldMarshal,marshalInfo);
6250 marshalInfo.BuildTables(md);
6255 internal void TypeSig(MemoryStream str) {
6259 internal sealed override uint Size(MetaData md) {
6260 return 4 + md.StringsIndexSize();
6263 internal sealed override void Write(FileImage output) {
6264 output.Write(parMode);
6265 output.Write(seqNo);
6266 output.StringsIndex(nameIx);
6269 internal sealed override uint GetCodedIx(CIx code) {
6271 case (CIx.HasCustomAttr) : return 4;
6272 case (CIx.HasConst) : return 1;
6273 case (CIx.HasFieldMarshal) : return 1;
6279 /**************************************************************************/
6281 /// Base class for the PEFile (starting point)
6285 private static readonly string mscorlibName = "mscorlib";
6286 private Module thisMod;
6287 private ClassDef moduleClass;
6288 private ArrayList classRefList = new ArrayList();
6289 private ArrayList classDefList = new ArrayList();
6290 private ArrayList resources = new ArrayList ();
6291 private Assembly thisAssembly;
6292 private int corFlags = 1;
6293 FileImage fileImage;
6297 /// Create a new PEFile. Each PEFile is a module.
6299 /// <param name="name">module name, also used for the file name</param>
6300 /// <param name="isDLL">create a .dll or .exe file</param>
6301 /// <param name="hasAssembly">this file is an assembly and
6302 /// will contain the assembly manifest. The assembly name is the
6303 /// same as the module name</param>
6304 public PEFile(string name, bool isDLL, bool hasAssembly) {
6305 // Console.WriteLine(Hex.Byte(0x12));
6306 // Console.WriteLine(Hex.Short(0x1234));
6307 // Console.WriteLine(Hex.Int(0x12345678));
6308 string fName = MakeFileName(null,name,isDLL);
6309 fileImage = new FileImage(isDLL,fName);
6310 InitPEFile(name, fName, hasAssembly);
6314 /// Create a new PEFile. Each PEFile is a module.
6316 /// <param name="name">module name, also used for the file name</param>
6317 /// <param name="isDLL">create a .dll or .exe file</param>
6318 /// <param name="hasAssembly">this file is an assembly and
6319 /// will contain the assembly manifest. The assembly name is the
6320 /// same as the module name</param>
6321 /// <param name="outputDir">write the PEFile to this directory. If this
6322 /// string is null then the output will be to the current directory</param>
6323 public PEFile(string name, bool isDLL, bool hasAssembly, string outputDir) {
6324 // Console.WriteLine(Hex.Byte(0x12));
6325 // Console.WriteLine(Hex.Short(0x1234));
6326 // Console.WriteLine(Hex.Int(0x12345678));
6327 string fName = MakeFileName(outputDir,name,isDLL);
6328 fileImage = new FileImage(isDLL,fName);
6329 InitPEFile(name, fName, hasAssembly);
6333 /// Create a new PEFile
6335 /// <param name="name">module name</param>
6336 /// <param name="isDLL">create a .dll or .exe</param>
6337 /// <param name="hasAssembly">this PEfile is an assembly and
6338 /// will contain the assemly manifest. The assembly name is the
6339 /// same as the module name</param>
6340 /// <param name="outStream">write the PEFile to this stream instead
6341 /// of to a new file</param>
6342 public PEFile(string name, bool isDLL, bool hasAssembly, Stream outStream) {
6343 fileImage = new FileImage(isDLL,outStream);
6344 InitPEFile(name, MakeFileName(null,name,isDLL), hasAssembly);
6347 public PEFile(string name, string module_name, bool isDLL, bool hasAssembly, Stream outStream) {
6348 fileImage = new FileImage(isDLL,outStream);
6349 InitPEFile(name, (module_name == null ? MakeFileName(null,name,isDLL) : module_name), hasAssembly);
6352 private void InitPEFile(string name, string fName, bool hasAssembly) {
6353 metaData = fileImage.GetMetaData();
6354 thisMod = new Module(fName,metaData);
6356 thisAssembly = new Assembly(name,metaData);
6357 metaData.AddToTable(MDTable.Assembly,thisAssembly);
6359 moduleClass = AddClass(TypeAttr.Private,"","<Module>");
6360 moduleClass.SpecialNoSuper();
6361 metaData.AddToTable(MDTable.Module,thisMod);
6365 public ClassDef ModuleClass {
6366 get { return moduleClass; }
6370 /// Set the subsystem (.subsystem) (Default is Windows Console mode)
6372 /// <param name="subS">subsystem value</param>
6373 public void SetSubSystem(SubSystem subS) {
6374 fileImage.subSys = subS;
6378 /// Set the flags (.corflags)
6380 /// <param name="flags">the flags value</param>
6381 public void SetCorFlags(int flags) {
6385 private string MakeFileName(string dirName, string name, bool isDLL) {
6387 if ((dirName != null) && (dirName.CompareTo("") != 0)) {
6389 if (!dirName.EndsWith("\\")) result += "\\";
6393 // if (isDLL) result += ".dll"; else result += ".exe";
6399 /// Add an external assembly to this PEFile (.assembly extern)
6401 /// <param name="assemName">the external assembly name</param>
6402 /// <returns>a descriptor for this external assembly</returns>
6403 public AssemblyRef AddExternAssembly(string assemName) {
6404 if (assemName.CompareTo(mscorlibName) == 0) return metaData.mscorlib;
6405 AssemblyRef anAssem = new AssemblyRef(metaData,assemName);
6406 metaData.AddToTable(MDTable.AssemblyRef,anAssem);
6407 // Console.WriteLine("Adding assembly " + assemName);
6412 /// Add an external module to this PEFile (.module extern)
6414 /// <param name="name">the external module name</param>
6415 /// <returns>a descriptor for this external module</returns>
6416 public ModuleRef AddExternModule(string name) {
6417 ModuleRef modRef = new ModuleRef(metaData,name);
6418 metaData.AddToTable(MDTable.ModuleRef,modRef);
6423 /// Add a "global" method to this module
6425 /// <param name="name">method name</param>
6426 /// <param name="retType">return type</param>
6427 /// <param name="pars">method parameters</param>
6428 /// <returns>a descriptor for this new "global" method</returns>
6429 public MethodDef AddMethod(string name, Type retType, Param[] pars) {
6430 return moduleClass.AddMethod(name,retType,pars);
6434 /// Add a "global" method to this module
6436 /// <param name="mAtts">method attributes</param>
6437 /// <param name="iAtts">method implementation attributes</param>
6438 /// <param name="name">method name</param>
6439 /// <param name="retType">return type</param>
6440 /// <param name="pars">method parameters</param>
6441 /// <returns>a descriptor for this new "global" method</returns>
6442 public MethodDef AddMethod(MethAttr mAtts, ImplAttr iAtts, string name, Type retType, Param[] pars) {
6443 return moduleClass.AddMethod(mAtts,iAtts,name,retType,pars);
6446 public MethodRef AddMethodToTypeSpec (Type item, string name, Type retType, Type[] pars) {
6447 MethodRef meth = new MethodRef (item.GetTypeSpec (metaData), name, retType, pars, false, null);
6448 metaData.AddToTable (MDTable.MemberRef,meth);
6452 public MethodRef AddVarArgMethodToTypeSpec (Type item, string name, Type retType,
6453 Type[] pars, Type[] optPars) {
6454 MethodRef meth = new MethodRef(item.GetTypeSpec (metaData), name,retType,pars,true,optPars);
6455 metaData.AddToTable(MDTable.MemberRef,meth);
6459 public FieldRef AddFieldToTypeSpec (Type item, string name, Type fType) {
6460 FieldRef field = new FieldRef (item.GetTypeSpec (metaData), name,fType);
6461 metaData.AddToTable (MDTable.MemberRef,field);
6465 public void AddMethodSpec (Method m, GenericMethodSig g_sig)
6467 MethodSpec ms = new MethodSpec (m, g_sig);
6468 metaData.AddToTable (MDTable.MethodSpec, ms);
6472 /// Add a "global" field to this module
6474 /// <param name="name">field name</param>
6475 /// <param name="fType">field type</param>
6476 /// <returns>a descriptor for this new "global" field</returns>
6477 public FieldDef AddField(string name, Type fType) {
6478 return moduleClass.AddField(name,fType);
6482 /// Add a "global" field to this module
6484 /// <param name="attrSet">attributes of this field</param>
6485 /// <param name="name">field name</param>
6486 /// <param name="fType">field type</param>
6487 /// <returns>a descriptor for this new "global" field</returns>
6488 public FieldDef AddField(FieldAttr attrSet, string name, Type fType) {
6489 return moduleClass.AddField(attrSet,name,fType);
6493 /// Add a class to this module
6495 /// <param name="attrSet">attributes of this class</param>
6496 /// <param name="nsName">name space name</param>
6497 /// <param name="name">class name</param>
6498 /// <returns>a descriptor for this new class</returns>
6499 public ClassDef AddClass(TypeAttr attrSet, string nsName, string name) {
6500 ClassDef aClass = new ClassDef(attrSet,nsName,name,metaData);
6501 metaData.AddToTable(MDTable.TypeDef,aClass);
6506 /// Add a class which extends System.ValueType to this module
6508 /// <param name="attrSet">attributes of this class</param>
6509 /// <param name="nsName">name space name</param>
6510 /// <param name="name">class name</param>
6511 /// <returns>a descriptor for this new class</returns>
6512 public ClassDef AddValueClass(TypeAttr attrSet, string nsName, string name, ValueClass vClass) {
6513 ClassDef aClass = new ClassDef(attrSet,nsName,name,metaData);
6514 aClass.MakeValueClass(vClass);
6515 aClass.SetTypeIndex (PrimitiveType.ValueType.GetTypeIndex ());
6516 metaData.AddToTable(MDTable.TypeDef,aClass);
6521 /// Add a class to this module
6523 /// <param name="attrSet">attributes of this class</param>
6524 /// <param name="nsName">name space name</param>
6525 /// <param name="name">class name</param>
6526 /// <param name="superType">super type of this class (extends)</param>
6527 /// <returns>a descriptor for this new class</returns>
6528 public ClassDef AddClass(TypeAttr attrSet, string nsName, string name, Class superType) {
6529 ClassDef aClass = new ClassDef(attrSet,nsName,name,metaData);
6530 aClass.SetSuper(superType);
6531 metaData.AddToTable(MDTable.TypeDef,aClass);
6535 public FileRef AddFile(string fName, byte[] hashBytes, bool hasMetaData, bool entryPoint) {
6536 FileRef file = new FileRef(fName,hashBytes,hasMetaData,entryPoint,metaData);
6537 metaData.AddToTable(MDTable.File,file);
6542 /// Add a manifest resource to this PEFile NOT YET IMPLEMENTED
6544 /// <param name="mr"></param>
6545 public void AddManifestResource(ManifestResource mr) {
6546 metaData.AddToTable(MDTable.ManifestResource,mr);
6548 //mr.FixName(metaData);
6551 public void AddCustomAttribute (Method meth, byte [] data, MetaDataElement element)
6553 metaData.AddCustomAttribute (new CustomAttribute (element, meth, data));
6557 /// Add a managed resource from another assembly.
6559 /// <param name="resName">The name of the resource</param>
6560 /// <param name="assem">The assembly where the resource is</param>
6561 /// <param name="isPublic">Access for the resource</param>
6562 public void AddExternalManagedResource (string resName, AssemblyRef assem, uint flags) {
6563 resources.Add (new ManifestResource (resName, flags, assem));
6567 /// Add a managed resource from another assembly.
6569 /// <param name="mr"></param>
6570 /// <param name="isPublic"></param>
6571 public void AddExternalManagedResource (ManifestResource mr) {
6572 resources.Add (new ManifestResource (mr));
6577 /// <param name="name">The name of the resource</param>
6578 /// <returns>The resource with the name "name" or null </returns>
6579 public ManifestResource GetResource (string name) {
6580 for (int i = 0; i < resources.Count; i ++) {
6581 if (((ManifestResource) resources [i]).Name == name)
6582 return (ManifestResource) resources [i];
6587 public ManifestResource [] GetResources() {
6588 return (ManifestResource []) resources.ToArray (typeof (ManifestResource));
6592 /// Write out the PEFile (the "bake" function)
6594 public void WritePEFile() { /* the "bake" function */
6595 fileImage.ReserveStrongNameSignatureSpace = thisAssembly.HasPublicKey;
6596 fileImage.MakeFile();
6600 /// Get the descriptor of this module
6602 /// <returns>the descriptor for this module</returns>
6603 public Module GetThisModule() {
6608 /// Get the descriptor for this assembly. The PEFile must have been
6609 /// created with hasAssembly = true
6611 /// <returns>the descriptor for this assembly</returns>
6612 public Assembly GetThisAssembly() {
6613 return thisAssembly;
6618 /**************************************************************************/
6620 /// Descriptor for the Primitive types defined in IL
6622 public class PrimitiveType : Type
6624 private string name;
6625 private int systemTypeIndex;
6626 public static int NumSystemTypes = 18;
6628 public static readonly PrimitiveType Void = new PrimitiveType(0x01,"Void",0);
6629 public static readonly PrimitiveType Boolean = new PrimitiveType(0x02,"Boolean",1);
6630 public static readonly PrimitiveType Char = new PrimitiveType(0x03,"Char",2);
6631 public static readonly PrimitiveType Int8 = new PrimitiveType(0x04,"SByte",3);
6632 public static readonly PrimitiveType UInt8 = new PrimitiveType(0x05,"Byte",4);
6633 public static readonly PrimitiveType Int16 = new PrimitiveType(0x06,"Int16",5);
6634 public static readonly PrimitiveType UInt16 = new PrimitiveType(0x07,"UInt16",6);
6635 public static readonly PrimitiveType Int32 = new PrimitiveType(0x08,"Int32",7);
6636 public static readonly PrimitiveType UInt32 = new PrimitiveType(0x09,"UInt32",8);
6637 public static readonly PrimitiveType Int64 = new PrimitiveType(0x0A,"Int64",9);
6638 public static readonly PrimitiveType UInt64 = new PrimitiveType(0x0B,"UInt64",10);
6639 public static readonly PrimitiveType Float32 = new PrimitiveType(0x0C,"Single",11);
6640 public static readonly PrimitiveType Float64 = new PrimitiveType(0x0D,"Double",12);
6641 public static readonly PrimitiveType String = new PrimitiveType(0x0E,"String",13);
6642 internal static readonly PrimitiveType Class = new PrimitiveType(0x12);
6643 public static readonly PrimitiveType TypedRef = new PrimitiveType(0x16,"TypedReference",14);
6644 public static readonly PrimitiveType IntPtr = new PrimitiveType(0x18,"IntPtr",15);
6645 public static readonly PrimitiveType UIntPtr = new PrimitiveType(0x19,"UIntPtr",16);
6646 public static readonly PrimitiveType Object = new PrimitiveType(0x1C,"Object",17);
6647 internal static readonly PrimitiveType ClassType = new PrimitiveType(0x50);
6648 internal static readonly PrimitiveType SZArray = new PrimitiveType(0x1D);
6649 internal static readonly PrimitiveType ValueType = new PrimitiveType(0x11, "ValueType", 18);
6650 public static readonly PrimitiveType NativeInt = IntPtr;
6651 public static readonly PrimitiveType NativeUInt = UIntPtr;
6653 internal PrimitiveType(byte typeIx) : base(typeIx) { }
6655 internal PrimitiveType(byte typeIx, string name, int STIx) : base(typeIx) {
6657 this.systemTypeIndex = STIx;
6660 internal string GetName() { return name; }
6662 internal int GetSystemTypeIx() { return systemTypeIndex; }
6664 internal sealed override void TypeSig(MemoryStream str) {
6665 str.WriteByte(typeIndex);
6668 internal override MetaDataElement GetTypeSpec(MetaData md) {
6669 TypeSpec tS = md.GetPrimitiveTypeSpec(systemTypeIndex);
6671 tS = new TypeSpec(this,md);
6672 md.SetPrimitiveTypeSpec(systemTypeIndex,tS);
6673 md.AddToTable(MDTable.TypeSpec,tS);
6680 /**************************************************************************/
6682 /// Descriptor for the Property of a class
6684 public class Property : Feature
6686 private static readonly byte PropertyTag = 0x8;
6687 MethodDef getterMeth;
6688 ConstantElem constVal;
6689 uint typeBlobIx = 0;
6694 internal Property(string name, Type retType, Type[] pars, ClassDef parent) : base(name, parent) {
6695 returnType = retType;
6697 if (pars != null) numPars = (uint)pars.Length;
6698 tabIx = MDTable.Property;
6702 /// Add a set method to this property
6704 /// <param name="setter">the set method</param>
6705 public void AddSetter(MethodDef setter) {
6706 AddMethod(setter,MethodType.Setter);
6710 /// Add a get method to this property
6712 /// <param name="getter">the get method</param>
6713 public void AddGetter(MethodDef getter) {
6714 AddMethod(getter,MethodType.Getter);
6715 getterMeth = getter;
6719 /// Add another method to this property
6721 /// <param name="other">the method</param>
6722 public void AddOther(MethodDef other) {
6723 AddMethod(other,MethodType.Other);
6727 /// Add an initial value for this property
6729 /// <param name="constVal">the initial value for this property</param>
6730 public void AddInitValue(Constant constVal) {
6731 this.constVal = new ConstantElem(this,constVal);
6734 internal sealed override void BuildTables(MetaData md) {
6736 nameIx = md.AddToStringsHeap(name);
6737 MemoryStream sig = new MemoryStream();
6738 sig.WriteByte(PropertyTag);
6739 MetaData.CompressNum(numPars,sig);
6740 returnType.TypeSig(sig);
6741 for (int i=0; i < numPars; i++) {
6742 parList[i].TypeSig(sig);
6744 typeBlobIx = md.AddToBlobHeap(sig.ToArray());
6745 for (int i=0; i < tide; i++) {
6746 md.AddToTable(MDTable.MethodSemantics,methods[i]);
6748 if (constVal != null) {
6749 md.AddToTable(MDTable.Constant,constVal);
6750 constVal.BuildTables(md);
6755 internal sealed override uint Size(MetaData md) {
6756 return 2 + md.StringsIndexSize() + md.BlobIndexSize();
6759 internal sealed override void Write(FileImage output) {
6760 output.Write(flags);
6761 output.StringsIndex(nameIx);
6762 output.BlobIndex(typeBlobIx);
6765 internal sealed override uint GetCodedIx(CIx code) {
6767 case (CIx.HasCustomAttr) : return 9;
6768 case (CIx.HasConst) : return 2;
6769 case (CIx.HasSemantics) : return 1;
6775 /**************************************************************************/
6777 /// Descriptor for an pointer (type * or type &)
6779 public abstract class PtrType : Type
6783 internal PtrType(Type bType, byte typeIx) : base(typeIx)
6786 tabIx = MDTable.TypeSpec;
6789 internal sealed override void TypeSig(MemoryStream str) {
6790 str.WriteByte(typeIndex);
6791 baseType.TypeSig(str);
6795 /**************************************************************************/
6797 /// Descriptor for a managed pointer (type & or byref)
6800 public class ManagedPointer : PtrType // <type> & (BYREF)
6804 /// Create new managed pointer to baseType
6806 /// <param name="bType">the base type of the pointer</param>
6807 public ManagedPointer(Type baseType) : base(baseType,0x10) { }
6810 /**************************************************************************/
6812 /// Descriptor for an unmanaged pointer (type *)
6814 public class UnmanagedPointer : PtrType // PTR
6817 /// Create a new unmanaged pointer to baseType
6819 /// <param name="baseType">the base type of the pointer</param>
6820 public UnmanagedPointer(Type baseType) : base(baseType, 0x0F) { }
6823 /**************************************************************************/
6825 /// Base class for scopes (extended by Module, ModuleRef, Assembly, AssemblyRef)
6827 public abstract class ResolutionScope : MetaDataElement
6829 protected uint nameIx = 0;
6830 protected MetaData metaData;
6831 protected string name;
6833 internal ResolutionScope(string name, MetaData md)
6837 nameIx = md.AddToStringsHeap(name);
6840 internal string GetName() { return name; }
6843 /**************************************************************************/
6845 /// Descriptor for a Section in a PEFile eg .text, .sdata
6847 internal class Section {
6848 private static readonly uint relocPageSize = 4096; // 4K pages for fixups
6851 uint offset = 0, tide = 0, size = 0, rva = 0, relocTide = 0;
6852 //uint relocOff = 0;
6853 uint flags = 0, padding = 0;
6856 internal Section(string sName, uint sFlags) {
6857 name = sName.ToCharArray();
6861 internal uint Tide() { return tide; }
6863 internal void IncTide(uint incVal) { tide += incVal; }
6865 internal uint Padding() { return padding; }
6867 internal uint Size() { return size; }
6869 internal void SetSize(uint pad) {
6871 size = tide + padding;
6874 internal uint RVA() { return rva; }
6876 internal void SetRVA(uint rva) { this.rva = rva; }
6878 internal uint Offset() { return offset; }
6880 internal void SetOffset(uint offs) { offset = offs; }
6882 internal void DoBlock(BinaryWriter reloc, uint page, int start, int end) {
6883 //Console.WriteLine("rva = " + rva + " page = " + page);
6884 reloc.Write(rva + page);
6885 reloc.Write((uint)(((end-start+1)*2) + 8));
6886 for (int j=start; j < end; j++) {
6887 //Console.WriteLine("reloc offset = " + relocs[j]);
6888 reloc.Write((ushort)((0x3 << 12) | (relocs[j] - page)));
6890 reloc.Write((ushort)0);
6893 internal void DoRelocs(BinaryWriter reloc) {
6894 if (relocTide > 0) {
6895 //relocOff = (uint)reloc.Seek(0,SeekOrigin.Current);
6896 uint block = (relocs[0]/relocPageSize + 1) * relocPageSize;
6898 for (int i=1; i < relocTide; i++) {
6899 if (relocs[i] >= block) {
6900 DoBlock(reloc,block-relocPageSize,start,i);
6902 block = (relocs[i]/relocPageSize + 1) * relocPageSize;
6905 DoBlock(reloc,block-relocPageSize,start,(int)relocTide);
6909 internal void AddReloc(uint offs) {
6911 if (relocs == null) {
6912 relocs = new uint[5];
6914 if (relocTide >= relocs.Length) {
6915 uint[] tmp = relocs;
6916 relocs = new uint[tmp.Length + 5];
6917 for (int i=0; i < relocTide; i++) {
6921 while ((pos < relocTide) && (relocs[pos] < offs)) pos++;
6922 for (int i=pos; i < relocTide; i++) {
6923 relocs[i+1] = relocs[i];
6930 internal void WriteHeader(BinaryWriter output, uint relocRVA) {
6935 output.Write(offset);
6937 //output.Write(relocRVA + relocOff);
6940 //output.Write((ushort)relocTide);
6941 //output.Write((ushort)0);
6942 output.Write(flags);
6946 /**************************************************************************/
6947 public abstract class Signature : MetaDataElement
6949 protected uint sigIx;
6951 internal Signature() {
6952 tabIx = MDTable.StandAloneSig;
6955 internal sealed override uint Size(MetaData md) {
6956 return md.BlobIndexSize();
6959 internal sealed override void Write(FileImage output) {
6960 output.BlobIndex(sigIx);
6963 internal sealed override uint GetCodedIx(CIx code) { return (uint)tabIx; }
6966 /**************************************************************************/
6968 /// Descriptor for a class defined in System (mscorlib)
6970 internal class SystemClass : ClassRef
6972 PrimitiveType elemType;
6974 internal SystemClass(PrimitiveType eType, AssemblyRef paren, MetaData md)
6975 : base("System",eType.GetName(),md) {
6980 internal override sealed MetaDataElement GetTypeSpec(MetaData md) {
6981 if (typeSpec == null) typeSpec = (TypeSpec)elemType.GetTypeSpec(md);
6986 internal sealed override void TypeSig(MemoryStream str) {
6987 str.WriteByte(elemType.GetTypeIndex());
6991 /**************************************************************************/
6993 /// Base class for all IL types
6995 public abstract class Type : MetaDataElement {
6996 protected byte typeIndex;
6997 protected TypeSpec typeSpec;
6999 internal Type(byte tyIx) { typeIndex = tyIx; }
7001 internal byte GetTypeIndex() { return typeIndex; }
7002 internal void SetTypeIndex (byte b) { typeIndex = b; }
7004 internal virtual MetaDataElement GetTypeSpec(MetaData md) {
7005 if (typeSpec == null) {
7006 typeSpec = new TypeSpec(this,md);
7007 md.AddToTable(MDTable.TypeSpec,typeSpec);
7012 internal virtual void TypeSig(MemoryStream str) {
7013 throw(new TypeSignatureException(this.GetType().AssemblyQualifiedName +
7014 " doesn't have a type signature!!"));
7019 /**************************************************************************/
7021 public class TypeSpec : MetaDataElement {
7024 internal TypeSpec(Type aType, MetaData md) {
7025 MemoryStream sig = new MemoryStream();
7027 sigIx = md.AddToBlobHeap(sig.ToArray());
7028 tabIx = MDTable.TypeSpec;
7031 internal sealed override uint GetCodedIx(CIx code) {
7033 case (CIx.TypeDefOrRef) : return 2;
7034 case (CIx.HasCustomAttr) : return 13;
7035 case (CIx.MemberRefParent) : return 4;
7040 internal override uint Size(MetaData md) {
7041 return md.BlobIndexSize();
7044 internal sealed override void Write(FileImage output) {
7045 //Console.WriteLine("Writing the blob index for a TypeSpec");
7046 output.BlobIndex(sigIx);
7051 class ByteArrayComparer : IComparer {
7053 public int Compare (object x, object y)
7055 byte [] a = (byte []) x;
7056 byte [] b = (byte []) y;
7059 if (b.Length != len)
7062 for (int i = 0; i < len; ++i)
7069 class ByteArrayHashCodeProvider : IHashCodeProvider {
7071 public int GetHashCode (Object key)
7073 byte [] arr = (byte []) key;
7074 int len = arr.Length;
7077 for (int i = 0; i < len; ++i)
7078 h = (h << 5) - h + arr [i];