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; }
4326 internal override uint SortKey ()
4328 return (theClass.Row << MetaData.CIxShiftMap[(uint)CIx.TypeDefOrRef])
4329 | theClass.GetCodedIx (CIx.TypeDefOrRef);
4333 /**************************************************************************/
4335 /// Descriptor for a local of a method
4339 private static readonly byte Pinned = 0x45;
4342 bool pinned = false, byref = false;
4345 /// Create a new local variable
4347 /// <param name="lName">name of the local variable</param>
4348 /// <param name="lType">type of the local variable</param>
4349 public Local(string lName, Type lType) {
4355 /// Create a new local variable that is byref and/or pinned
4357 /// <param name="lName">local name</param>
4358 /// <param name="lType">local type</param>
4359 /// <param name="byRef">is byref</param>
4360 /// <param name="isPinned">has pinned attribute</param>
4361 public Local(string lName, Type lType, bool byRef, bool isPinned)
4369 internal void TypeSig(MemoryStream str) {
4370 if (pinned) str.WriteByte(Pinned);
4375 /**************************************************************************/
4377 /// Descriptor for the locals for a method
4380 public class LocalSig : Signature
4382 private static readonly byte LocalSigByte = 0x7;
4385 public LocalSig(Local[] locals) {
4386 this.locals = locals;
4387 tabIx = MDTable.StandAloneSig;
4390 internal sealed override void BuildTables(MetaData md) {
4392 MemoryStream sig = new MemoryStream();
4393 sig.WriteByte(LocalSigByte);
4394 MetaData.CompressNum((uint)locals.Length,sig);
4395 for (int i=0; i < locals.Length; i++) {
4396 ((Local)locals[i]).TypeSig(sig);
4398 sigIx = md.AddToBlobHeap(sig.ToArray());
4404 /**************************************************************************/
4406 /// Descriptor for resources used in this PE file
4409 public class ManifestResource : MetaDataElement
4411 public static readonly uint PublicResource = 0x1;
4412 public static readonly uint PrivateResource = 0x2;
4415 MetaDataElement rRef;
4419 byte [] resourceBytes;
4421 public ManifestResource (string name, byte[] resBytes, uint flags) {
4422 InitResource (name, flags);
4423 this.resourceBytes = resBytes;
4426 public ManifestResource(string name, uint flags, FileRef fileRef) {
4427 InitResource (name, flags);
4431 public ManifestResource(string name, uint flags, FileRef fileRef,
4433 InitResource (name, flags);
4435 fileOffset = fileIx;
4438 public ManifestResource(string name, uint flags, AssemblyRef assemRef) {
4439 InitResource (name, flags);
4443 internal ManifestResource (ManifestResource mres) {
4444 mrName = mres.mrName;
4447 this.fileOffset = fileOffset;
4448 this.resourceBytes = resourceBytes;
4451 private void InitResource (string name, uint flags) {
4454 tabIx = MDTable.ManifestResource;
4457 internal sealed override void BuildTables(MetaData md) {
4459 md.AddToTable (MDTable.ManifestResource, this);
4460 nameIx = md.AddToStringsHeap(mrName);
4461 if (resourceBytes != null) {
4463 throw new Exception("ERROR: Manifest Resource has byte value and file reference");
4464 fileOffset = md.AddResource(resourceBytes);
4467 throw new Exception("ERROR: Manifest Resource has no implementation or value");
4468 rRef.BuildTables (md);
4474 internal sealed override uint Size(MetaData md) {
4475 return 8 + md.StringsIndexSize() +
4476 md.CodedIndexSize(CIx.Implementation);
4479 internal sealed override void Write(FileImage output) {
4480 output.Write(fileOffset);
4481 output.Write(flags);
4482 output.StringsIndex(nameIx);
4483 output.WriteCodedIndex(CIx.Implementation,rRef);
4486 internal sealed override uint GetCodedIx(CIx code) { return 18; }
4488 public string Name {
4489 get { return mrName; }
4490 set { mrName = value; }
4494 /**************************************************************************/
4496 /// Base class for elements in the PropertyMap, EventMap and
4497 /// NestedClass MetaData tables
4499 public class MapElem : MetaDataElement
4505 internal MapElem(ClassDef par, uint elIx, MDTable elemTab) {
4508 elemTable = elemTab;
4511 internal sealed override uint Size(MetaData md) {
4512 return md.TableIndexSize(MDTable.TypeDef) + md.TableIndexSize(elemTable);
4515 internal sealed override void Write(FileImage output) {
4516 output.WriteIndex(MDTable.TypeDef,parent.Row);
4517 output.WriteIndex(elemTable,elemIx);
4520 /**************************************************************************/
4522 /// Base class for field/methods (member of a class)
4524 public abstract class Member : MetaDataElement
4526 protected string name;
4527 protected uint nameIx = 0, sigIx = 0;
4529 internal Member(string memName)
4532 tabIx = MDTable.MemberRef;
4536 /**************************************************************************/
4539 /// Root (20 bytes + UTF-8 Version String + quad align padding)
4540 /// StreamHeaders (8 bytes + null terminated name string + quad align padding)
4542 /// #~ (always present - holds metadata tables)
4543 /// #Strings (always present - holds identifier strings)
4544 /// #US (Userstring heap)
4545 /// #Blob (signature blobs)
4546 /// #GUID (guids for assemblies or Modules)
4549 public class MetaData
4551 internal static readonly int[] CIxShiftMap = {2,2,5,1,2,3,1,1,1,2,3,2,1};
4552 private static readonly byte StringsHeapMask = 0x1;
4553 private static readonly byte GUIDHeapMask = 0x2;
4554 private static readonly byte BlobHeapMask = 0x4;
4555 private static readonly uint MetaDataSignature = 0x424A5342;
4556 private static readonly uint maxSmlIxSize = 0xFFFF;
4557 private static readonly uint max1BitSmlIx = 0x7FFF;
4558 private static readonly uint max2BitSmlIx = 0x3FFF;
4559 private static readonly uint max3BitSmlIx = 0x1FFF;
4560 private static readonly uint max5BitSmlIx = 0x7FF;
4561 // NOTE: version and stream name strings MUST always be quad padded
4562 private static readonly string version = "v1.0.3705\0\0\0";
4563 private static readonly char[] tildeName = {'#','~','\0','\0'};
4564 private static readonly char[] stringsName = {'#','S','t','r','i','n','g','s','\0','\0','\0','\0'};
4565 private static readonly char[] usName = {'#','U','S','\0'};
4566 private static readonly char[] guidName = {'#','G','U','I','D','\0','\0','\0'};
4567 private static readonly char[] blobName = {'#','B','l','o','b','\0','\0','\0'};
4568 private static readonly uint MetaDataHeaderSize = 20 + (uint)version.Length;
4569 private static readonly uint TildeHeaderSize = 24;
4570 private static readonly uint StreamHeaderSize = 8;
4571 private static readonly uint numMetaDataTables = (int)MDTable.GenericParamConstraint + 1;
4572 private static readonly uint tildeHeaderSize = 8 + (uint)tildeName.Length;
4574 MetaDataStream strings, us, guid, blob;
4576 MetaDataStream[] streams = new MetaDataStream[5];
4577 uint numStreams = 5;
4578 uint tildeTide = 0, tildePadding = 0, tildeStart = 0;
4579 uint numTables = 0, resourcesSize = 0;
4580 ArrayList[] metaDataTables = new ArrayList[numMetaDataTables];
4581 ArrayList byteCodes = new ArrayList();
4582 uint codeSize = 0, codeStart, byteCodePadding = 0, metaDataSize = 0;
4583 ulong valid = 0, /*sorted = 0x000002003301FA00;*/ sorted = 0;
4584 bool[] largeIx = new bool[numMetaDataTables];
4585 bool[] lgeCIx = new bool[(int)CIx.MaxCIx];
4586 bool largeStrings = false, largeUS = false, largeGUID = false, largeBlob = false;
4587 private FileImage file;
4588 private byte heapSizes = 0;
4589 MetaDataElement entryPoint;
4590 BinaryWriter output;
4591 public MSCorLib mscorlib;
4592 private TypeSpec[] systemTypeSpecs = new TypeSpec[PrimitiveType.NumSystemTypes];
4594 private ArrayList cattr_list;
4595 ArrayList resources;
4597 internal MetaData(FileImage file) {
4598 // tilde = new MetaDataStream(tildeName,false,0);
4600 strings = new MetaDataStream(stringsName,new UTF8Encoding(),true);
4601 us = new MetaDataStream(usName,new UnicodeEncoding(),true);
4602 guid = new MetaDataStream(guidName,false);
4603 blob = new MetaDataStream(blobName,true);
4604 streams[1] = strings;
4608 for (int i=0; i < numMetaDataTables; i++) {
4611 for (int i=0; i < lgeCIx.Length; i++) {
4614 mscorlib = new MSCorLib(this);
4617 internal TypeSpec GetPrimitiveTypeSpec(int ix) {
4618 return systemTypeSpecs[ix];
4621 internal void SetPrimitiveTypeSpec(int ix, TypeSpec typeSpec) {
4622 systemTypeSpecs[ix] = typeSpec;
4625 internal uint Size() {
4626 return metaDataSize;
4630 private void CalcHeapSizes ()
4632 if (strings.LargeIx()) {
4633 largeStrings = true;
4634 heapSizes |= StringsHeapMask;
4636 if (guid.LargeIx()) {
4638 heapSizes |= GUIDHeapMask;
4640 if (blob.LargeIx()) {
4642 heapSizes |= BlobHeapMask;
4645 largeUS = us.LargeIx();
4648 internal void StreamSize(byte mask) {
4652 internal uint AddToUSHeap(string str) {
4653 if (str == null) return 0;
4654 return us.Add(str,true);
4657 internal uint AddToUSHeap(byte[] str) {
4658 if (str == null) return 0;
4659 return us.Add (str, true);
4662 internal uint AddToStringsHeap(string str) {
4663 if ((str == null) || (str.CompareTo("") == 0)) return 0;
4664 return strings.Add(str,false);
4667 internal uint AddToGUIDHeap(Guid guidNum) {
4668 return guid.Add(guidNum, false);
4671 internal uint AddToBlobHeap(byte[] blobBytes) {
4672 if (blobBytes == null) return 0;
4673 return blob.Add(blobBytes, true);
4676 internal uint AddToBlobHeap(byte val) {
4677 return blob.Add(val, true);
4680 internal uint AddToBlobHeap(sbyte val) {
4681 return blob.Add(val, true);
4684 internal uint AddToBlobHeap(ushort val) {
4685 return blob.Add(val, true);
4688 internal uint AddToBlobHeap(short val) {
4689 return blob.Add(val, true);
4692 internal uint AddToBlobHeap(uint val) {
4693 return blob.Add(val, true);
4696 internal uint AddToBlobHeap(int val) {
4697 return blob.Add(val, true);
4700 internal uint AddToBlobHeap(ulong val) {
4701 return blob.Add(val, true);
4704 internal uint AddToBlobHeap(long val) {
4705 return blob.Add(val, true);
4708 internal uint AddToBlobHeap(float val) {
4709 return blob.Add(val, true);
4712 internal uint AddToBlobHeap(double val) {
4713 return blob.Add(val, true);
4716 internal uint AddToBlobHeap(string val) {
4717 return blob.Add(val,true);
4720 internal void AddCustomAttribute (CustomAttribute cattr)
4722 if (cattr_list == null)
4723 cattr_list = new ArrayList ();
4724 cattr_list.Add (cattr);
4727 private ArrayList GetTable(MDTable tableIx) {
4728 int tabIx = (int)tableIx;
4729 if (metaDataTables[tabIx] == null) {
4730 metaDataTables[tabIx] = new ArrayList();
4731 valid |= ((ulong)0x1 << tabIx);
4732 // Console.WriteLine("after creating table " + tableIx + "(" + tabIx + ") valid = " + valid);
4735 return metaDataTables[tabIx];
4738 internal void AddToTable(MDTable tableIx, MetaDataElement elem) {
4740 // Console.Out.WriteLine("ERROR - element already in table " + tableIx);
4743 // updates Row field of the element
4744 // Console.WriteLine("Adding element to table " + (uint)tableIx);
4745 ArrayList table = GetTable(tableIx);
4746 elem.Row = (uint)table.Count + 1;
4750 internal uint TableIndex(MDTable tableIx) {
4751 if (metaDataTables[(int)tableIx] == null) return 1;
4752 return (uint)metaDataTables[(int)tableIx].Count+1;
4755 internal uint AddCode(CILInstructions byteCode) {
4756 byteCodes.Add(byteCode);
4757 uint offset = codeSize + codeStart;
4758 codeSize += byteCode.GetCodeSize();
4762 internal void SetEntryPoint(MetaDataElement ep) {
4766 internal uint AddResource(byte[] resBytes) {
4767 if (resources == null) resources = new ArrayList ();
4768 resources.Add (resBytes);
4769 uint offset = resourcesSize;
4770 resourcesSize += (uint)resBytes.Length + 4;
4774 internal void AddData(DataConstant cVal) {
4775 file.AddInitData(cVal);
4778 internal static void CompressNum(uint val, MemoryStream sig) {
4780 sig.WriteByte((byte)val);
4781 } else if (val < 0x3FFF) {
4782 byte b1 = (byte)((val >> 8) | 0x80);
4783 byte b2 = (byte)(val & FileImage.iByteMask[0]);
4787 byte b1 = (byte)((val >> 24) | 0xC0);
4788 byte b2 = (byte)((val & FileImage.iByteMask[2]) >> 16);
4789 byte b3 = (byte)((val & FileImage.iByteMask[1]) >> 8);;
4790 byte b4 = (byte)(val & FileImage.iByteMask[0]);
4798 internal uint CodeSize() {
4799 return codeSize + byteCodePadding;
4802 internal uint GetResourcesSize()
4804 return resourcesSize;
4807 internal uint StringsIndexSize() {
4808 if (largeStrings) return 4;
4812 internal uint GUIDIndexSize() {
4813 if (largeGUID) return 4;
4817 internal uint USIndexSize() {
4818 if (largeUS) return 4;
4822 internal uint BlobIndexSize() {
4823 if (largeBlob) return 4;
4827 internal uint CodedIndexSize(CIx code) {
4828 if (lgeCIx[(uint)code]) return 4;
4832 internal uint TableIndexSize(MDTable tabIx) {
4833 if (largeIx[(uint)tabIx]) return 4;
4837 private void SetIndexSizes() {
4838 for (int i=0; i < numMetaDataTables; i++) {
4839 if (metaDataTables[i] == null)
4842 uint count = (uint)metaDataTables[i].Count;
4843 if (count > maxSmlIxSize)
4846 MDTable tabIx = (MDTable)i;
4847 if (count > max5BitSmlIx) {
4848 lgeCIx[(int)CIx.HasCustomAttr] = true;
4850 if (count > max3BitSmlIx) {
4851 if ((tabIx == MDTable.TypeRef) || (tabIx == MDTable.ModuleRef) || (tabIx == MDTable.Method) || (tabIx == MDTable.TypeSpec) || (tabIx == MDTable.Field))
4852 lgeCIx[(int)CIx.CustomAttributeType] = true;
4853 if ((tabIx == MDTable.Method) || (tabIx == MDTable.MemberRef))
4854 lgeCIx[(int)CIx.MemberRefParent] = true;
4856 if (count > max2BitSmlIx) {
4857 if ((tabIx == MDTable.Field) || (tabIx == MDTable.Param) || (tabIx == MDTable.Property))
4858 lgeCIx[(int)CIx.HasConst] = true;
4859 if ((tabIx == MDTable.TypeDef) || (tabIx == MDTable.TypeRef) || (tabIx == MDTable.TypeSpec))
4860 lgeCIx[(int)CIx.TypeDefOrRef] = true;
4861 if ((tabIx == MDTable.TypeDef) || (tabIx == MDTable.Method) || (tabIx == MDTable.Assembly))
4862 lgeCIx[(int)CIx.HasDeclSecurity] = true;
4863 if ((tabIx == MDTable.File) || (tabIx == MDTable.AssemblyRef) || (tabIx == MDTable.ExportedType))
4864 lgeCIx[(int)CIx.Implementation] = true;
4865 if ((tabIx == MDTable.Module) || (tabIx == MDTable.ModuleRef) || (tabIx == MDTable.AssemblyRef) || (tabIx == MDTable.TypeRef))
4866 lgeCIx[(int)CIx.ResolutionScope] = true;
4868 if (count > max1BitSmlIx) {
4869 if ((tabIx == MDTable.Field) || (tabIx == MDTable.Param))
4870 lgeCIx[(int)CIx.HasFieldMarshal] = true;
4871 if ((tabIx == MDTable.Event) || (tabIx == MDTable.Property))
4872 lgeCIx[(int)CIx.HasSemantics] = true;
4873 if ((tabIx == MDTable.Method) || (tabIx == MDTable.MemberRef))
4874 lgeCIx[(int)CIx.MethodDefOrRef] = true;
4875 if ((tabIx == MDTable.Field) || (tabIx == MDTable.Method))
4876 lgeCIx[(int)CIx.MemberForwarded] = true;
4877 if ((tabIx == MDTable.TypeDef) || (tabIx == MDTable.Method))
4878 lgeCIx[(int)CIx.TypeOrMethodDef] = true;
4883 private void SetStreamOffsets() {
4884 uint sizeOfHeaders = StreamHeaderSize + (uint)tildeName.Length;
4885 for (int i=1; i < numStreams; i++) {
4886 sizeOfHeaders += streams[i].headerSize();
4888 metaDataSize = MetaDataHeaderSize + sizeOfHeaders;
4889 tildeStart = metaDataSize;
4890 metaDataSize += tildeTide + tildePadding;
4891 for (int i=1; i < numStreams; i++) {
4892 streams[i].Start = metaDataSize;
4893 metaDataSize += streams[i].Size();
4894 streams[i].WriteDetails();
4898 internal void CalcTildeStreamSize() {
4900 //tilde.SetIndexSizes(strings.LargeIx(),us.LargeIx(),guid.LargeIx(),blob.LargeIx());
4901 tildeTide = TildeHeaderSize;
4902 tildeTide += 4 * numTables;
4903 //Console.WriteLine("Tilde header + sizes = " + tildeTide);
4904 for (int i=0; i < numMetaDataTables; i++) {
4905 if (metaDataTables[i] != null) {
4906 ArrayList table = metaDataTables[i];
4907 // Console.WriteLine("Meta data table " + i + " at offset " + tildeTide);
4908 tildeTide += (uint)table.Count * ((MetaDataElement)table[0]).Size(this);
4909 // Console.WriteLine("Metadata table " + i + " has size " + table.Count);
4910 // Console.WriteLine("tildeTide = " + tildeTide);
4913 if ((tildeTide % 4) != 0) tildePadding = 4 - (tildeTide % 4);
4914 //Console.WriteLine("tildePadding = " + tildePadding);
4917 internal void WriteTildeStream(FileImage output) {
4918 long startTilde = output.Seek(0,SeekOrigin.Current);
4919 output.Write((uint)0); // Reserved
4920 output.Write((byte)1); // MajorVersion
4921 output.Write((byte)0); // MinorVersion
4922 output.Write(heapSizes);
4923 output.Write((byte)1); // Reserved
4924 output.Write(valid);
4925 output.Write(sorted);
4926 for (int i=0; i < numMetaDataTables; i++) {
4927 if (metaDataTables[i] != null) {
4928 uint count = (uint)metaDataTables[i].Count;
4929 output.Write(count);
4932 long tabStart = output.Seek(0,SeekOrigin.Current);
4933 // Console.WriteLine("Starting metaData tables at " + tabStart);
4934 for (int i=0; i < numMetaDataTables; i++) {
4935 if (metaDataTables[i] != null) {
4936 // Console.WriteLine("Starting metaData table " + i + " at " + (output.Seek(0,SeekOrigin.Current) - startTilde));
4937 ArrayList table = metaDataTables[i];
4938 for (int j=0; j < table.Count; j++) {
4939 ((MetaDataElement)table[j]).Write(output);
4943 // Console.WriteLine("Writing padding at " + output.Seek(0,SeekOrigin.Current));
4944 for (int i=0; i < tildePadding; i++) output.Write((byte)0);
4947 private void BuildTable(ArrayList table) {
4948 if (table == null) return;
4949 for (int j=0; j < table.Count; j++) {
4950 ((MetaDataElement)table[j]).BuildTables(this);
4954 private void SortTable (ArrayList mTable) {
4955 if (mTable == null) return;
4957 for (int i=0; i < mTable.Count; i++) {
4958 ((MetaDataElement)mTable[i]).Row = (uint)i+1;
4962 internal void BuildMetaData(uint codeStartOffset) {
4963 codeStart = codeStartOffset;
4964 BuildTable(metaDataTables[(int)MDTable.TypeDef]);
4965 BuildTable(metaDataTables[(int)MDTable.MemberRef]);
4966 BuildTable(metaDataTables[(int)MDTable.GenericParam]);
4967 BuildTable(metaDataTables[(int)MDTable.MethodSpec]);
4968 BuildTable(metaDataTables[(int)MDTable.GenericParamConstraint]);
4969 BuildTable(metaDataTables[(int)MDTable.ManifestResource]);
4971 if (cattr_list != null) {
4972 foreach (CustomAttribute cattr in cattr_list)
4973 cattr.BuildTables (this);
4976 /* for (int i=0; i < metaDataTables.Length; i++) {
4977 ArrayList table = metaDataTables[i];
4978 if (table != null) {
4979 for (int j=0; j < table.Count; j++) {
4980 ((MetaDataElement)table[j]).BuildTables(this);
4987 for (int i=1; i < numStreams; i++) {
4988 streams[i].EndStream();
4990 CalcTildeStreamSize();
4992 byteCodePadding = NumToAlign(codeSize,4);
4993 if (entryPoint != null) file.SetEntryPoint(entryPoint.Token());
4995 // Check ordering of specific tables
4996 // Constant, CustomAttribute, FieldMarshal, DeclSecurity, MethodSemantics
4997 // ImplMap, GenericParam
4998 // Need to load GenericParamConstraint AFTER GenericParam table in correct order
5000 // InterfaceImpl, ClassLayout, FieldLayout, MethodImpl, FieldRVA, NestedClass
5001 // will _ALWAYS_ be in the correct order as embedded in BuildMDTables
5003 SortTable(metaDataTables[(int)MDTable.Constant]);
5004 SortTable(metaDataTables[(int)MDTable.CustomAttribute]);
5005 SortTable(metaDataTables[(int)MDTable.FieldMarshal]);
5006 SortTable(metaDataTables[(int)MDTable.DeclSecurity]);
5007 SortTable(metaDataTables[(int)MDTable.MethodSemantics]);
5008 SortTable(metaDataTables[(int)MDTable.ImplMap]);
5009 if (metaDataTables[(int)MDTable.GenericParam] != null) {
5010 SortTable(metaDataTables[(int)MDTable.GenericParam]);
5011 // Now add GenericParamConstraints
5012 /*for (int i=0; i < metaDataTables[(int)MDTable.GenericParam].Count; i++) {
5013 ((GenericParameter)metaDataTables[(int)MDTable.GenericParam][i]).AddConstraints(this);
5016 SortTable(metaDataTables[(int)MDTable.GenericParamConstraint]);
5017 SortTable(metaDataTables[(int)MDTable.InterfaceImpl]);
5021 internal void WriteByteCodes(FileImage output) {
5022 for (int i=0; i < byteCodes.Count; i++) {
5023 ((CILInstructions)byteCodes[i]).Write(output);
5025 for (int i=0; i < byteCodePadding; i++) {
5026 output.Write((byte)0);
5030 internal void WriteResources (FileImage output) {
5031 if (resources == null) return;
5032 for (int i = 0; i < resources.Count; i ++) {
5033 byte [] resBytes = (byte []) resources [i];
5034 output.Write ((uint) resBytes.Length);
5035 output.Write (resBytes);
5039 internal void WriteMetaData(FileImage output) {
5040 this.output = output;
5041 mdStart = output.Seek(0,SeekOrigin.Current);
5042 // Console.WriteLine("Writing metaData at " + Hex.Long(mdStart));
5043 output.Write(MetaDataSignature);
5044 output.Write((short)1); // Major Version
5045 output.Write((short)1); // Minor Version ECMA = 0, PEFiles = 1
5046 output.Write(0); // Reserved
5047 output.Write(version.Length);
5048 output.Write(version.ToCharArray()); // version string is already zero padded
5049 output.Write((short)0);
5050 output.Write((ushort)numStreams);
5051 // write tilde header
5052 output.Write(tildeStart);
5053 output.Write(tildeTide + tildePadding);
5054 output.Write(tildeName);
5055 for (int i=1; i < numStreams; i++) streams[i].WriteHeader(output);
5056 // Console.WriteLine("Writing tilde stream at " + output.Seek(0,SeekOrigin.Current) + " = " + tildeStart);
5057 WriteTildeStream(output);
5058 for (int i=1; i < numStreams; i++) streams[i].Write(output);
5059 // Console.WriteLine("Finished Writing metaData at " + output.Seek(0,SeekOrigin.Current));
5062 internal bool LargeStringsIndex() { return strings.LargeIx(); }
5063 internal bool LargeGUIDIndex() { return guid.LargeIx(); }
5064 internal bool LargeUSIndex() { return us.LargeIx(); }
5065 internal bool LargeBlobIndex() { return blob.LargeIx(); }
5067 internal bool LargeIx(MDTable tabIx) { return largeIx[(uint)tabIx]; }
5070 private uint NumToAlign(uint val, uint alignVal) {
5071 if ((val % alignVal) == 0) return 0;
5072 return alignVal - (val % alignVal);
5075 internal void WriteCodedIndex(CIx code, MetaDataElement elem, FileImage output) {
5078 ix = (elem.Row << CIxShiftMap[(uint)code]) | elem.GetCodedIx(code);
5079 // Console.WriteLine("coded index = " + ix + " row = " + elem.Row);
5081 // Console.WriteLine("elem for coded index is null");
5083 if (lgeCIx[(uint)code])
5086 output.Write((ushort)ix);
5091 /// Error for invalid PE file
5093 public class PEFileException : System.Exception {
5094 public PEFileException(string msg) : base("Error in PE File: " + msg) { }
5097 /**************************************************************************/
5099 /// Base class for all Meta Data table elements
5102 public abstract class MetaDataElement: IComparable
5105 protected ArrayList customAttributes;
5106 private uint row = 0;
5107 protected bool done = false;
5108 protected MDTable tabIx;
5109 protected bool sortTable = false;
5111 internal MetaDataElement() { }
5118 if (row == 0) row = value;
5122 internal virtual uint GetCodedIx(CIx code) { return 0; }
5125 /// Add a custom attribute to this item
5127 /// <param name="ctorMeth">the constructor method for this attribute</param>
5128 /// <param name="val">the byte value of the parameters</param>
5129 public void AddCustomAttribute(Method ctorMeth, byte[] val) {
5130 if (customAttributes == null) {
5131 customAttributes = new ArrayList();
5133 customAttributes.Add(new CustomAttribute(this,ctorMeth,val));
5137 /// Add a custom attribute to this item
5139 /// <param name="ctorMeth">the constructor method for this attribute</param>
5140 /// <param name="val">the constant values of the parameters</param>
5141 public void AddCustomAttribute(Method ctorMeth, Constant[] cVals) {
5142 if (customAttributes == null) {
5143 customAttributes = new ArrayList();
5145 // customAttributes.Add(new CustomAttribute(this,ctorMeth,cVals));
5148 internal uint Token() {
5149 return (((uint)tabIx << 24) | row);
5152 internal virtual void BuildTables(MetaData md) {
5156 internal virtual uint Size(MetaData md) {
5160 internal virtual void Write(FileImage output) { }
5162 internal virtual uint SortKey()
5164 throw new PEFileException("Trying to sort table of " + this);
5168 internal virtual uint SortKey2()
5174 public int CompareTo(object obj)
5176 uint otherKey = ((MetaDataElement)obj).SortKey();
5177 uint thisKey = SortKey();
5179 if (thisKey == otherKey)
5181 otherKey = ((MetaDataElement)obj).SortKey2();
5182 thisKey = SortKey2();
5183 if (thisKey == otherKey)
5185 if (thisKey < otherKey)
5189 if (thisKey < otherKey) return -1;
5195 /**************************************************************************/
5197 /// Stream in the Meta Data (#Strings, #US, #Blob and #GUID)
5200 internal class MetaDataStream : BinaryWriter
5202 private static readonly uint StreamHeaderSize = 8;
5203 private static uint maxSmlIxSize = 0xFFFF;
5205 private uint start = 0;
5206 uint size = 0, tide = 1;
5207 bool largeIx = false;
5210 Hashtable htable = new Hashtable();
5211 Hashtable btable = new Hashtable (new ByteArrayHashCodeProvider (), new ByteArrayComparer ());
5213 internal MetaDataStream(char[] name, bool addInitByte) : base(new MemoryStream()) {
5214 if (addInitByte) { Write((byte)0); size = 1; }
5216 sizeOfHeader = StreamHeaderSize + (uint)name.Length;
5219 internal MetaDataStream(char[] name, System.Text.Encoding enc, bool addInitByte) : base(new MemoryStream(),enc) {
5220 if (addInitByte) { Write((byte)0); size = 1; }
5222 sizeOfHeader = StreamHeaderSize + (uint)name.Length;
5234 internal uint headerSize() {
5235 // Console.WriteLine(name + " stream has headersize of " + sizeOfHeader);
5236 return sizeOfHeader;
5239 internal void SetSize(uint siz) {
5243 internal uint Size() {
5247 internal bool LargeIx() {
5251 internal void WriteDetails() {
5252 // Console.WriteLine(name + " - size = " + size);
5255 internal uint Add(string str, bool prependSize) {
5256 Object val = htable[str];
5260 htable[str] = index;
5261 char[] arr = str.ToCharArray();
5262 if (prependSize) CompressNum((uint)arr.Length*2+1);
5265 size = (uint)Seek(0,SeekOrigin.Current);
5271 internal uint Add (byte[] str, bool prependSize) {
5272 Object val = btable [str];
5276 btable [str] = index;
5277 if (prependSize) CompressNum ((uint) str.Length);
5279 size = (uint) Seek (0, SeekOrigin.Current);
5287 internal uint Add(Guid guid, bool prependSize) {
5288 byte [] b = guid.ToByteArray ();
5289 if (prependSize) CompressNum ((uint) b.Length);
5290 Write(guid.ToByteArray());
5291 size =(uint)Seek(0,SeekOrigin.Current);
5295 internal uint Add(byte[] blob) {
5297 CompressNum((uint)blob.Length);
5299 size = (uint)Seek(0,SeekOrigin.Current);
5303 internal uint Add(byte val, bool prependSize) {
5305 if (prependSize) CompressNum (1);
5307 size = (uint)Seek(0,SeekOrigin.Current);
5311 internal uint Add(sbyte val, bool prependSize) {
5313 if (prependSize) CompressNum (1);
5315 size = (uint)Seek(0,SeekOrigin.Current);
5319 internal uint Add(ushort val, bool prependSize) {
5321 if (prependSize) CompressNum (2);
5323 size = (uint)Seek(0,SeekOrigin.Current);
5327 internal uint Add(short val, bool prependSize) {
5329 if (prependSize) CompressNum (2);
5331 size = (uint)Seek(0,SeekOrigin.Current);
5335 internal uint Add(uint val, bool prependSize) {
5337 if (prependSize) CompressNum (4);
5339 size = (uint)Seek(0,SeekOrigin.Current);
5343 internal uint Add(int val, bool prependSize) {
5345 if (prependSize) CompressNum (4);
5347 size = (uint)Seek(0,SeekOrigin.Current);
5351 internal uint Add(ulong val, bool prependSize) {
5353 if (prependSize) CompressNum (8);
5355 size = (uint)Seek(0,SeekOrigin.Current);
5359 internal uint Add(long val, bool prependSize) {
5361 if (prependSize) CompressNum (8);
5363 size = (uint)Seek(0,SeekOrigin.Current);
5367 internal uint Add(float val, bool prependSize) {
5369 if (prependSize) CompressNum (4);
5371 size = (uint)Seek(0,SeekOrigin.Current);
5375 internal uint Add(double val, bool prependSize) {
5377 if (prependSize) CompressNum (8);
5379 size = (uint)Seek(0,SeekOrigin.Current);
5383 private void CompressNum(uint val) {
5386 } else if (val < 0x3FFF) {
5387 byte b1 = (byte)((val >> 8) | 0x80);
5388 byte b2 = (byte)(val & FileImage.iByteMask[0]);
5392 byte b1 = (byte)((val >> 24) | 0xC0);
5393 byte b2 = (byte)((val & FileImage.iByteMask[2]) >> 16);
5394 byte b3 = (byte)((val & FileImage.iByteMask[1]) >> 8);;
5395 byte b4 = (byte)(val & FileImage.iByteMask[0]);
5403 private void QuadAlign() {
5404 if ((size % 4) != 0) {
5405 uint pad = 4 - (size % 4);
5407 for (int i=0; i < pad; i++) {
5413 internal void EndStream() {
5415 if (size > maxSmlIxSize) {
5420 internal void WriteHeader(BinaryWriter output) {
5421 output.Write(start);
5426 internal virtual void Write(BinaryWriter output) {
5427 // Console.WriteLine("Writing " + name + " stream at " + output.Seek(0,SeekOrigin.Current) + " = " + start);
5428 MemoryStream str = (MemoryStream)BaseStream;
5429 output.Write(str.ToArray());
5433 /**************************************************************************/
5435 /// Base class for Method Descriptors
5438 public abstract class Method : Member
5440 protected CallConv callConv = CallConv.Default;
5441 protected Type retType;
5443 internal Method(string methName, Type rType) : base(methName)
5449 /// Add calling conventions to this method descriptor
5451 /// <param name="cconv"></param>
5452 public void AddCallConv(CallConv cconv) {
5456 internal abstract void TypeSig(MemoryStream sig);
5458 internal uint GetSigIx(MetaData md) {
5459 MemoryStream sig = new MemoryStream();
5461 return md.AddToBlobHeap(sig.ToArray());
5464 internal Type GetRetType() {
5469 /**************************************************************************/
5471 /// Descriptor for a method defined in THIS assembly/module
5475 public class MethodDef : Method
5477 private static readonly ushort PInvokeImpl = 0x2000;
5478 //private static readonly uint UnmanagedExport = 0x0008;
5479 // private static readonly byte LocalSigByte = 0x7;
5480 uint parIx = 0, textOffset = 0;
5483 CILInstructions code;
5484 ArrayList securityActions = new ArrayList();
5488 ushort methFlags = 0, implFlags = 0;
5489 int maxStack = 0, numPars = 0;
5490 bool entryPoint = false;
5492 ArrayList varArgSigList;
5493 ImplMap pinvokeImpl;
5496 internal MethodDef(MetaData md, string name, Type retType, Param[] pars) : base(name,retType) {
5499 if (parList != null) numPars = parList.Length;
5500 tabIx = MDTable.Method;
5503 internal MethodDef(MetaData md, MethAttr mAttrSet, ImplAttr iAttrSet, string name, Type retType, Param[] pars) : base(name,retType) {
5506 if (parList != null) numPars = parList.Length;
5507 // Console.WriteLine("Creating method " + name + " with " + numPars + " parameters");
5508 methFlags = (ushort)mAttrSet;
5509 implFlags = (ushort)iAttrSet;
5510 tabIx = MDTable.Method;
5513 internal Param[] GetPars() {
5518 /// Add some attributes to this method descriptor
5520 /// <param name="ma">the attributes to be added</param>
5521 public void AddMethAttribute(MethAttr ma) {
5522 methFlags |= (ushort)ma;
5526 /// Add some implementation attributes to this method descriptor
5528 /// <param name="ia">the attributes to be added</param>
5529 public void AddImplAttribute(ImplAttr ia) {
5530 implFlags |= (ushort)ia;
5533 public void AddPInvokeInfo(ModuleRef scope, string methName,
5534 PInvokeAttr callAttr) {
5535 pinvokeImpl = new ImplMap((ushort)callAttr,this,methName,scope);
5536 methFlags |= PInvokeImpl;
5540 /// Add a named generic type parameter
5542 public GenericParameter AddGenericParameter (short index, string name) {
5543 GenericParameter gp = new GenericParameter (this, metaData, index, name);
5544 metaData.AddToTable (MDTable.GenericParam, gp);
5549 /// Set the maximum stack height for this method
5551 /// <param name="maxStack">the maximum height of the stack</param>
5552 public void SetMaxStack(int maxStack) {
5553 this.maxStack = maxStack;
5557 /// Add local variables to this method
5559 /// <param name="locals">the locals to be added</param>
5560 /// <param name="initLocals">are locals initialised to default values</param>
5561 public void AddLocals(Local[] locals, bool initLocals) {
5562 this.locals = locals;
5563 this.initLocals = initLocals;
5567 /// Mark this method as having an entry point
5569 public void DeclareEntryPoint() {
5574 /// Create a code buffer for this method to add the IL instructions to
5576 /// <returns>a buffer for this method's IL instructions</returns>
5577 public CILInstructions CreateCodeBuffer() {
5578 code = new CILInstructions(metaData);
5583 /// Make a method reference descriptor for this method to be used
5584 /// as a callsite signature for this vararg method
5586 /// <param name="optPars">the optional pars for the vararg method call</param>
5587 /// <returns></returns>
5588 public MethodRef MakeVarArgSignature(Type[] optPars) {
5589 Type[] pars = new Type[numPars];
5590 MethodRef varArgSig;
5591 for (int i=0; i < numPars; i++) {
5592 pars[i] = parList[i].GetParType();
5594 varArgSig = new MethodRef(this,name,retType,pars,true,optPars);
5596 if (varArgSigList == null)
5597 varArgSigList = new ArrayList ();
5598 varArgSigList.Add (varArgSig);
5602 internal sealed override void TypeSig(MemoryStream sig) {
5603 sig.WriteByte((byte)callConv);
5604 MetaData.CompressNum((uint)numPars,sig);
5605 retType.TypeSig(sig);
5606 for (ushort i=0; i < numPars; i++) {
5607 parList[i].seqNo = (ushort)(i+1);
5608 parList[i].TypeSig(sig);
5612 internal sealed override void BuildTables(MetaData md) {
5614 if (pinvokeImpl != null) {
5615 md.AddToTable(MDTable.ImplMap,pinvokeImpl);
5616 pinvokeImpl.BuildTables(md);
5618 if (entryPoint) md.SetEntryPoint(this);
5620 if (locals != null) {
5621 localSig = new LocalSig(locals);
5622 md.AddToTable(MDTable.StandAloneSig,localSig);
5623 localSig.BuildTables(md);
5624 locToken = localSig.Token();
5627 code.CheckCode(locToken,initLocals,maxStack);
5628 textOffset = md.AddCode(code);
5630 nameIx = md.AddToStringsHeap(name);
5631 sigIx = GetSigIx(md);
5632 parIx = md.TableIndex(MDTable.Param);
5633 for (int i=0; i < numPars; i++) {
5634 md.AddToTable(MDTable.Param,parList[i]);
5635 parList[i].BuildTables(md);
5637 if (varArgSigList != null) {
5638 foreach (MethodRef varArgSig in varArgSigList) {
5639 md.AddToTable(MDTable.MemberRef,varArgSig);
5640 varArgSig.BuildTables(md);
5643 // Console.WriteLine("method has " + numPars + " parameters");
5647 internal sealed override uint Size(MetaData md) {
5648 return 8 + md.StringsIndexSize() + md.BlobIndexSize() + md.TableIndexSize(MDTable.Param);
5651 internal sealed override void Write(FileImage output) {
5652 if (ZeroRva ()) output.Write(0);
5653 else output.WriteCodeRVA(textOffset);
5654 output.Write(implFlags);
5655 output.Write(methFlags);
5656 output.StringsIndex(nameIx);
5657 output.BlobIndex(sigIx);
5658 output.WriteIndex(MDTable.Param,parIx);
5661 internal bool ZeroRva () {
5662 return (((methFlags & (ushort)MethAttr.Abstract) != 0) ||
5663 ((implFlags & (ushort)ImplAttr.Runtime) != 0) ||
5664 ((implFlags & (ushort)ImplAttr.InternalCall) != 0) ||
5665 (pinvokeImpl != null)); // TODO: Not entirely true but works for now
5668 internal sealed override uint GetCodedIx(CIx code) {
5670 case (CIx.HasCustomAttr) : return 0;
5671 case (CIx.HasDeclSecurity) : return 1;
5672 case (CIx.MemberRefParent) : return 3;
5673 case (CIx.MethodDefOrRef) : return 0;
5674 case (CIx.MemberForwarded) : return 1;
5675 case (CIx.CustomAttributeType) : return 2;
5676 case (CIx.TypeOrMethodDef) : return 1;
5682 /**************************************************************************/
5684 /// Descriptor for an overriding method (.override)
5686 public class MethodImpl : MetaDataElement
5689 Method header, body;
5691 internal MethodImpl(ClassDef par, Method decl, Method bod) {
5695 tabIx = MDTable.MethodImpl;
5698 internal sealed override uint Size(MetaData md) {
5699 return md.TableIndexSize(MDTable.TypeDef) + 2 * md.CodedIndexSize(CIx.MethodDefOrRef);
5702 internal sealed override void Write(FileImage output) {
5703 output.WriteIndex(MDTable.TypeDef,parent.Row);
5704 output.WriteCodedIndex(CIx.MethodDefOrRef,body);
5705 output.WriteCodedIndex(CIx.MethodDefOrRef,header);
5709 /**************************************************************************/
5711 /// Descriptor for a method defined in another assembly/module
5713 public class MethodRef : Method
5715 private static readonly byte Sentinel = 0x41;
5716 Type[] parList, optParList;
5717 MetaDataElement parent;
5718 uint numPars = 0, numOptPars = 0;
5720 internal MethodRef(MetaDataElement paren, string name, Type retType,
5721 Type[] pars, bool varArgMeth, Type[] optPars) : base(name,retType) {
5724 if (parList != null) numPars = (uint)parList.Length;
5726 optParList = optPars;
5727 if (optParList != null) numOptPars = (uint)optParList.Length;
5728 callConv = CallConv.Vararg;
5732 internal sealed override void TypeSig(MemoryStream sig) {
5733 sig.WriteByte((byte)callConv);
5734 MetaData.CompressNum(numPars+numOptPars,sig);
5735 retType.TypeSig(sig);
5736 for (int i=0; i < numPars; i++) {
5737 parList[i].TypeSig(sig);
5739 if (numOptPars > 0) {
5740 sig.WriteByte(Sentinel);
5741 for (int i=0; i < numOptPars; i++) {
5742 optParList[i].TypeSig(sig);
5747 internal sealed override void BuildTables(MetaData md) {
5749 nameIx = md.AddToStringsHeap(name);
5750 sigIx = GetSigIx(md);
5754 internal sealed override uint Size(MetaData md) {
5755 return md.CodedIndexSize(CIx.MemberRefParent) + md.StringsIndexSize() + md.BlobIndexSize();
5758 internal sealed override void Write(FileImage output) {
5759 output.WriteCodedIndex(CIx.MemberRefParent,parent);
5760 output.StringsIndex(nameIx);
5761 output.BlobIndex(sigIx);
5764 internal sealed override uint GetCodedIx(CIx code) {
5766 case (CIx.HasCustomAttr) : return 6;
5767 case (CIx.MethodDefOrRef) : return 1;
5768 case (CIx.CustomAttributeType) : return 3;
5774 /**************************************************************************/
5776 /// Descriptor for Property and Event methods
5778 public class MethodSemantics : MetaDataElement {
5780 Feature.MethodType type;
5782 Feature eventOrProp;
5784 internal MethodSemantics(Feature.MethodType mType, MethodDef method, Feature feature) {
5787 eventOrProp = feature;
5788 tabIx = MDTable.MethodSemantics;
5791 internal override uint SortKey() {
5792 return (eventOrProp.Row << MetaData.CIxShiftMap [(uint)CIx.HasSemantics])
5793 | eventOrProp.GetCodedIx (CIx.HasSemantics);
5796 internal sealed override uint Size(MetaData md) {
5797 return 2 + md.TableIndexSize(MDTable.Method) + md.CodedIndexSize(CIx.HasSemantics);
5800 internal sealed override void Write(FileImage output) {
5801 output.Write((ushort)type);
5802 output.WriteIndex(MDTable.Method,meth.Row);
5803 output.WriteCodedIndex(CIx.HasSemantics,eventOrProp);
5807 /**************************************************************************/
5809 /// Descriptor for a FunctionPointer type
5812 public class MethPtrType : Type
5824 /// Create a new function pointer type
5826 /// <param name="meth">the function to be referenced</param>
5827 public MethPtrType (CallConv callconv, Type retType, Type[] pars,
5828 bool varArgMeth, Type[] optPars) : base(0x1B) {
5829 this.retType = retType;
5830 callConv = callconv;
5832 this.varArgMeth = varArgMeth;
5833 if (parList != null) numPars = (uint)parList.Length;
5835 optParList = optPars;
5836 if (optParList != null) numOptPars = (uint)optParList.Length;
5837 callConv |= CallConv.Vararg;
5839 tabIx = MDTable.TypeSpec;
5842 internal sealed override void TypeSig(MemoryStream sig) {
5843 sig.WriteByte(typeIndex);
5844 // Bootlegged from method ref
5845 sig.WriteByte((byte)callConv);
5846 MetaData.CompressNum (numPars + numOptPars, sig);
5847 retType.TypeSig (sig);
5848 for (int i=0; i < numPars; i++) {
5849 parList[i].TypeSig (sig);
5852 sig.WriteByte (0x41); // Write the sentinel
5853 for (int i=0; i < numOptPars; i++) {
5854 optParList[i].TypeSig (sig);
5859 internal sealed override void BuildTables(MetaData md) {
5861 MemoryStream sig = new MemoryStream();
5863 sigIx = md.AddToBlobHeap(sig.ToArray());
5867 internal sealed override uint Size(MetaData md) {
5868 return md.BlobIndexSize();
5871 internal sealed override void Write(FileImage output) {
5872 output.BlobIndex(sigIx);
5875 internal sealed override uint GetCodedIx(CIx code) { return 0x1B; }
5878 /**************************************************************************/
5880 /// Descriptor for THIS module
5882 public class Module : ResolutionScope
5887 internal Module(string name, MetaData md) : base(name,md) {
5888 mvid = Guid.NewGuid();
5889 mvidIx = md.AddToGUIDHeap(mvid);
5890 tabIx = MDTable.Module;
5894 get { return mvid; }
5897 internal sealed override uint Size(MetaData md) {
5898 return 2 + md.StringsIndexSize() + 3 * md.GUIDIndexSize();
5901 internal sealed override void Write(FileImage output) {
5902 output.Write((short)0);
5903 output.StringsIndex(nameIx);
5904 output.GUIDIndex(mvidIx);
5905 output.GUIDIndex(0);
5906 output.GUIDIndex(0);
5909 internal sealed override uint GetCodedIx(CIx code) {
5911 case (CIx.HasCustomAttr) : return 7;
5912 case (CIx.ResolutionScope) : return 0;
5917 /**************************************************************************/
5919 /// Descriptor for another module in THIS assembly
5921 public class ModuleRef : ResolutionScope, IExternRef
5924 internal ModuleRef(MetaData md, string name) : base(name,md) {
5925 tabIx = MDTable.ModuleRef;
5929 /// Add a class to this external module. This is a class declared in
5930 /// another module of THIS assembly.
5932 /// <param name="nsName">name space name</param>
5933 /// <param name="name">class name</param>
5934 /// <returns>a descriptor for this class in another module</returns>
5935 public ClassRef AddClass(string nsName, string name) {
5936 ClassRef aClass = new ClassRef(nsName,name,metaData);
5937 metaData.AddToTable(MDTable.TypeRef,aClass);
5938 aClass.SetParent(this);
5943 /// Make a file descriptor to correspond to this module. The file
5944 /// descriptor will have the same name as the module descriptor
5946 /// <param name="hashBytes">the hash of the file</param>
5947 /// <param name="hasMetaData">the file contains metadata</param>
5948 /// <param name="entryPoint">the program entry point is in this file</param>
5949 /// <returns>a descriptor for the file which contains this module</returns>
5950 public FileRef MakeFile(byte[] hashBytes, bool hasMetaData, bool entryPoint) {
5951 FileRef file = new FileRef(nameIx,hashBytes,hasMetaData,entryPoint,metaData);
5952 metaData.AddToTable(MDTable.File,file);
5957 /// Add a value class to this module. This is a class declared in
5958 /// another module of THIS assembly.
5960 /// <param name="nsName">name space name</param>
5961 /// <param name="name">class name</param>
5962 /// <returns></returns>
5963 public ClassRef AddValueClass(string nsName, string name) {
5964 ClassRef aClass = new ClassRef(nsName,name,metaData);
5965 metaData.AddToTable(MDTable.TypeRef,aClass);
5966 aClass.SetParent(this);
5967 aClass.MakeValueClass(ValueClass.ValueType);
5972 /// Add a class which is declared public in this external module of
5973 /// THIS assembly. This class will be exported from this assembly.
5974 /// The ilasm syntax for this is .extern class
5976 /// <param name="attrSet">attributes of the class to be exported</param>
5977 /// <param name="nsName">name space name</param>
5978 /// <param name="name">external class name</param>
5979 /// <param name="declFile">the file where the class is declared</param>
5980 /// <param name="isValueClass">is this class a value type?</param>
5981 /// <returns>a descriptor for this external class</returns>
5982 public ExternClassRef AddExternClass(TypeAttr attrSet, string nsName,
5983 string name, FileRef declFile,
5984 bool isValueClass) {
5985 ExternClassRef cRef = new ExternClassRef(attrSet,nsName,name,declFile,metaData);
5986 metaData.AddToTable(MDTable.TypeRef,cRef);
5987 cRef.SetParent(this);
5988 if (isValueClass) cRef.MakeValueClass(ValueClass.ValueType);
5993 /// Add a "global" method in another module
5995 /// <param name="name">method name</param>
5996 /// <param name="retType">return type</param>
5997 /// <param name="pars">method parameter types</param>
5998 /// <returns>a descriptor for this method in anther module</returns>
5999 public MethodRef AddMethod(string name, Type retType, Type[] pars) {
6000 MethodRef meth = new MethodRef(this,name,retType,pars,false,null);
6001 metaData.AddToTable(MDTable.MemberRef,meth);
6006 /// Add a vararg method to this class
6008 /// <param name="name">method name</param>
6009 /// <param name="retType">return type</param>
6010 /// <param name="pars">parameter types</param>
6011 /// <param name="optPars">optional param types for this vararg method</param>
6012 /// <returns>a descriptor for this method</returns>
6013 public MethodRef AddVarArgMethod(string name, Type retType,
6014 Type[] pars, Type[] optPars) {
6015 MethodRef meth = new MethodRef(this,name,retType,pars,true,optPars);
6016 metaData.AddToTable(MDTable.MemberRef,meth);
6021 /// Add a field in another module
6023 /// <param name="name">field name</param>
6024 /// <param name="fType">field type</param>
6025 /// <returns>a descriptor for this field in another module</returns>
6026 public FieldRef AddField(string name, Type fType) {
6027 FieldRef field = new FieldRef(this,name,fType);
6028 metaData.AddToTable(MDTable.MemberRef,field);
6032 internal sealed override uint Size(MetaData md) {
6033 return md.StringsIndexSize();
6036 internal sealed override void Write(FileImage output) {
6037 output.StringsIndex(nameIx);
6040 internal sealed override uint GetCodedIx(CIx code) {
6042 case (CIx.HasCustomAttr) : return 12;
6043 case (CIx.MemberRefParent) : return 2;
6044 case (CIx.ResolutionScope) : return 1;
6050 /**************************************************************************/
6052 /// Descriptors for native types used for marshalling
6054 public class NativeType {
6055 public static readonly NativeType Void = new NativeType(0x01);
6056 public static readonly NativeType Boolean = new NativeType(0x02);
6057 public static readonly NativeType Int8 = new NativeType(0x03);
6058 public static readonly NativeType UInt8 = new NativeType(0x04);
6059 public static readonly NativeType Int16 = new NativeType(0x05);
6060 public static readonly NativeType UInt16 = new NativeType(0x06);
6061 public static readonly NativeType Int32 = new NativeType(0x07);
6062 public static readonly NativeType UInt32 = new NativeType(0x08);
6063 public static readonly NativeType Int64 = new NativeType(0x09);
6064 public static readonly NativeType UInt64 = new NativeType(0x0A);
6065 public static readonly NativeType Float32 = new NativeType(0x0B);
6066 public static readonly NativeType Float64 = new NativeType(0x0C);
6067 public static readonly NativeType Currency = new NativeType(0x0F);
6068 public static readonly NativeType BStr = new NativeType(0x13);
6069 public static readonly NativeType LPStr = new NativeType(0x14);
6070 public static readonly NativeType LPWStr = new NativeType(0x15);
6071 public static readonly NativeType LPTStr = new NativeType(0x16);
6072 public static readonly NativeType FixedSysString = new NativeType(0x17);
6073 public static readonly NativeType IUnknown = new NativeType(0x19);
6074 public static readonly NativeType IDispatch = new NativeType(0x1A);
6075 public static readonly NativeType Struct = new NativeType(0x1B);
6076 public static readonly NativeType Interface = new NativeType(0x1C);
6077 public static readonly NativeType Int = new NativeType(0x1F);
6078 public static readonly NativeType UInt = new NativeType(0x20);
6079 public static readonly NativeType ByValStr = new NativeType(0x22);
6080 public static readonly NativeType AnsiBStr = new NativeType(0x23);
6081 public static readonly NativeType TBstr = new NativeType(0x24);
6082 public static readonly NativeType VariantBool = new NativeType(0x25);
6083 public static readonly NativeType FuncPtr = new NativeType(0x26);
6084 public static readonly NativeType AsAny = new NativeType(0x28);
6086 protected byte typeIndex;
6088 internal NativeType(byte tyIx) { typeIndex = tyIx; }
6090 internal byte GetTypeIndex() { return typeIndex; }
6092 internal virtual byte[] ToBlob() {
6093 byte[] bytes = new byte[1];
6094 bytes[0] = GetTypeIndex();
6100 public class NativeArray : NativeType
6102 NativeType elemType;
6103 uint len = 0, parNum = 0;
6106 public NativeArray(NativeType elemType) : base(0x2A) {
6107 this.elemType = elemType;
6110 public NativeArray(NativeType elemType, int len) : base(0x2A) {
6111 this.elemType = elemType;
6115 public NativeArray(NativeType elemType, int numElem, int parNumForLen) : base(0x2A) {
6116 this.elemType = elemType;
6117 len = (uint)numElem;
6118 parNum = (uint)parNumForLen;
6121 internal override byte[] ToBlob() {
6122 MemoryStream str = new MemoryStream();
6123 str.WriteByte(GetTypeIndex());
6124 if (elemType == null) str.WriteByte(0x50); // no info (MAX)
6125 else str.WriteByte(elemType.GetTypeIndex());
6126 MetaData.CompressNum(parNum,str);
6128 MetaData.CompressNum(len,str);
6129 return str.ToArray();
6134 public class SafeArray : NativeType
6136 SafeArrayType elemType;
6138 public SafeArray(SafeArrayType elemType) : base(0x1D) {
6139 this.elemType = elemType;
6142 internal override byte[] ToBlob() {
6143 byte[] bytes = new byte[2];
6144 bytes[0] = GetTypeIndex();
6145 bytes[1] = (byte)elemType;
6151 public class FixedArray : NativeType
6153 NativeType elemType;
6156 public FixedArray(NativeType elemType, int numElems) : base(0x1E) {
6157 this.elemType = elemType;
6158 numElem = (uint)numElems;
6161 internal override byte[] ToBlob() {
6162 MemoryStream str = new MemoryStream();
6163 str.WriteByte(GetTypeIndex());
6164 MetaData.CompressNum(numElem,str);
6165 if (elemType == null) str.WriteByte(0x50); // no info (MAX)
6166 else str.WriteByte(elemType.GetTypeIndex());
6167 return str.ToArray();
6172 public class CustomMarshaller : NativeType
6175 string marshallerName;
6178 public CustomMarshaller(string typeNameOrGUID, string marshallerName,
6179 string optCookie) : base(0x2C) {
6180 typeName = typeNameOrGUID;
6181 this.marshallerName = marshallerName;
6185 internal override byte[] ToBlob() {
6186 MemoryStream str = new MemoryStream();
6187 BinaryWriter bw = new BinaryWriter(str,new UTF8Encoding());
6188 bw.Write(GetTypeIndex());
6189 bw.Write(typeName.ToCharArray());
6191 bw.Write(marshallerName.ToCharArray());
6193 if (cookie != null) bw.Write(cookie.ToCharArray());
6196 return str.ToArray();
6200 /**************************************************************************/
6202 /// Descriptor for a parameter of a method defined in this assembly/module
6204 public class Param : MetaDataElement
6206 private static readonly ushort hasDefault = 0x1000;
6207 private static readonly ushort hasFieldMarshal = 0x2000;
6211 internal ushort seqNo = 0;
6213 ConstantElem defaultVal;
6215 FieldMarshal marshalInfo;
6218 /// Create a new parameter for a method
6220 /// <param name="mode">param mode (in, out, opt)</param>
6221 /// <param name="parName">parameter name</param>
6222 /// <param name="parType">parameter type</param>
6223 public Param(ParamAttr mode, string parName, Type parType) {
6226 parMode = (ushort)mode;
6227 tabIx = MDTable.Param;
6231 /// Add a default value to this parameter
6233 /// <param name="c">the default value for the parameter</param>
6234 public void AddDefaultValue(Constant cVal) {
6235 defaultVal = new ConstantElem(this,cVal);
6236 parMode |= hasDefault;
6240 /// Add marshalling information about this parameter
6242 public void AddMarshallInfo(NativeType marshallType) {
6243 parMode |= hasFieldMarshal;
6244 marshalInfo = new FieldMarshal(this,marshallType);
6247 internal Type GetParType() { return pType; }
6249 internal sealed override void BuildTables(MetaData md) {
6251 nameIx = md.AddToStringsHeap(pName);
6252 if (defaultVal != null) {
6253 md.AddToTable(MDTable.Constant,defaultVal);
6254 defaultVal.BuildTables(md);
6256 if (marshalInfo != null) {
6257 md.AddToTable(MDTable.FieldMarshal,marshalInfo);
6258 marshalInfo.BuildTables(md);
6263 internal void TypeSig(MemoryStream str) {
6267 internal sealed override uint Size(MetaData md) {
6268 return 4 + md.StringsIndexSize();
6271 internal sealed override void Write(FileImage output) {
6272 output.Write(parMode);
6273 output.Write(seqNo);
6274 output.StringsIndex(nameIx);
6277 internal sealed override uint GetCodedIx(CIx code) {
6279 case (CIx.HasCustomAttr) : return 4;
6280 case (CIx.HasConst) : return 1;
6281 case (CIx.HasFieldMarshal) : return 1;
6287 /**************************************************************************/
6289 /// Base class for the PEFile (starting point)
6293 private static readonly string mscorlibName = "mscorlib";
6294 private Module thisMod;
6295 private ClassDef moduleClass;
6296 private ArrayList classRefList = new ArrayList();
6297 private ArrayList classDefList = new ArrayList();
6298 private ArrayList resources = new ArrayList ();
6299 private Assembly thisAssembly;
6300 private int corFlags = 1;
6301 FileImage fileImage;
6305 /// Create a new PEFile. Each PEFile is a module.
6307 /// <param name="name">module name, also used for the file name</param>
6308 /// <param name="isDLL">create a .dll or .exe file</param>
6309 /// <param name="hasAssembly">this file is an assembly and
6310 /// will contain the assembly manifest. The assembly name is the
6311 /// same as the module name</param>
6312 public PEFile(string name, bool isDLL, bool hasAssembly) {
6313 // Console.WriteLine(Hex.Byte(0x12));
6314 // Console.WriteLine(Hex.Short(0x1234));
6315 // Console.WriteLine(Hex.Int(0x12345678));
6316 string fName = MakeFileName(null,name,isDLL);
6317 fileImage = new FileImage(isDLL,fName);
6318 InitPEFile(name, fName, hasAssembly);
6322 /// Create a new PEFile. Each PEFile is a module.
6324 /// <param name="name">module name, also used for the file name</param>
6325 /// <param name="isDLL">create a .dll or .exe file</param>
6326 /// <param name="hasAssembly">this file is an assembly and
6327 /// will contain the assembly manifest. The assembly name is the
6328 /// same as the module name</param>
6329 /// <param name="outputDir">write the PEFile to this directory. If this
6330 /// string is null then the output will be to the current directory</param>
6331 public PEFile(string name, bool isDLL, bool hasAssembly, string outputDir) {
6332 // Console.WriteLine(Hex.Byte(0x12));
6333 // Console.WriteLine(Hex.Short(0x1234));
6334 // Console.WriteLine(Hex.Int(0x12345678));
6335 string fName = MakeFileName(outputDir,name,isDLL);
6336 fileImage = new FileImage(isDLL,fName);
6337 InitPEFile(name, fName, hasAssembly);
6341 /// Create a new PEFile
6343 /// <param name="name">module name</param>
6344 /// <param name="isDLL">create a .dll or .exe</param>
6345 /// <param name="hasAssembly">this PEfile is an assembly and
6346 /// will contain the assemly manifest. The assembly name is the
6347 /// same as the module name</param>
6348 /// <param name="outStream">write the PEFile to this stream instead
6349 /// of to a new file</param>
6350 public PEFile(string name, bool isDLL, bool hasAssembly, Stream outStream) {
6351 fileImage = new FileImage(isDLL,outStream);
6352 InitPEFile(name, MakeFileName(null,name,isDLL), hasAssembly);
6355 public PEFile(string name, string module_name, bool isDLL, bool hasAssembly, Stream outStream) {
6356 fileImage = new FileImage(isDLL,outStream);
6357 InitPEFile(name, (module_name == null ? MakeFileName(null,name,isDLL) : module_name), hasAssembly);
6360 private void InitPEFile(string name, string fName, bool hasAssembly) {
6361 metaData = fileImage.GetMetaData();
6362 thisMod = new Module(fName,metaData);
6364 thisAssembly = new Assembly(name,metaData);
6365 metaData.AddToTable(MDTable.Assembly,thisAssembly);
6367 moduleClass = AddClass(TypeAttr.Private,"","<Module>");
6368 moduleClass.SpecialNoSuper();
6369 metaData.AddToTable(MDTable.Module,thisMod);
6373 public ClassDef ModuleClass {
6374 get { return moduleClass; }
6378 /// Set the subsystem (.subsystem) (Default is Windows Console mode)
6380 /// <param name="subS">subsystem value</param>
6381 public void SetSubSystem(SubSystem subS) {
6382 fileImage.subSys = subS;
6386 /// Set the flags (.corflags)
6388 /// <param name="flags">the flags value</param>
6389 public void SetCorFlags(int flags) {
6393 private string MakeFileName(string dirName, string name, bool isDLL) {
6395 if ((dirName != null) && (dirName.CompareTo("") != 0)) {
6397 if (!dirName.EndsWith("\\")) result += "\\";
6401 // if (isDLL) result += ".dll"; else result += ".exe";
6407 /// Add an external assembly to this PEFile (.assembly extern)
6409 /// <param name="assemName">the external assembly name</param>
6410 /// <returns>a descriptor for this external assembly</returns>
6411 public AssemblyRef AddExternAssembly(string assemName) {
6412 if (assemName.CompareTo(mscorlibName) == 0) return metaData.mscorlib;
6413 AssemblyRef anAssem = new AssemblyRef(metaData,assemName);
6414 metaData.AddToTable(MDTable.AssemblyRef,anAssem);
6415 // Console.WriteLine("Adding assembly " + assemName);
6420 /// Add an external module to this PEFile (.module extern)
6422 /// <param name="name">the external module name</param>
6423 /// <returns>a descriptor for this external module</returns>
6424 public ModuleRef AddExternModule(string name) {
6425 ModuleRef modRef = new ModuleRef(metaData,name);
6426 metaData.AddToTable(MDTable.ModuleRef,modRef);
6431 /// Add a "global" method to this module
6433 /// <param name="name">method name</param>
6434 /// <param name="retType">return type</param>
6435 /// <param name="pars">method parameters</param>
6436 /// <returns>a descriptor for this new "global" method</returns>
6437 public MethodDef AddMethod(string name, Type retType, Param[] pars) {
6438 return moduleClass.AddMethod(name,retType,pars);
6442 /// Add a "global" method to this module
6444 /// <param name="mAtts">method attributes</param>
6445 /// <param name="iAtts">method implementation attributes</param>
6446 /// <param name="name">method name</param>
6447 /// <param name="retType">return type</param>
6448 /// <param name="pars">method parameters</param>
6449 /// <returns>a descriptor for this new "global" method</returns>
6450 public MethodDef AddMethod(MethAttr mAtts, ImplAttr iAtts, string name, Type retType, Param[] pars) {
6451 return moduleClass.AddMethod(mAtts,iAtts,name,retType,pars);
6454 public MethodRef AddMethodToTypeSpec (Type item, string name, Type retType, Type[] pars) {
6455 MethodRef meth = new MethodRef (item.GetTypeSpec (metaData), name, retType, pars, false, null);
6456 metaData.AddToTable (MDTable.MemberRef,meth);
6460 public MethodRef AddVarArgMethodToTypeSpec (Type item, string name, Type retType,
6461 Type[] pars, Type[] optPars) {
6462 MethodRef meth = new MethodRef(item.GetTypeSpec (metaData), name,retType,pars,true,optPars);
6463 metaData.AddToTable(MDTable.MemberRef,meth);
6467 public FieldRef AddFieldToTypeSpec (Type item, string name, Type fType) {
6468 FieldRef field = new FieldRef (item.GetTypeSpec (metaData), name,fType);
6469 metaData.AddToTable (MDTable.MemberRef,field);
6473 public void AddMethodSpec (Method m, GenericMethodSig g_sig)
6475 MethodSpec ms = new MethodSpec (m, g_sig);
6476 metaData.AddToTable (MDTable.MethodSpec, ms);
6480 /// Add a "global" field to this module
6482 /// <param name="name">field name</param>
6483 /// <param name="fType">field type</param>
6484 /// <returns>a descriptor for this new "global" field</returns>
6485 public FieldDef AddField(string name, Type fType) {
6486 return moduleClass.AddField(name,fType);
6490 /// Add a "global" field to this module
6492 /// <param name="attrSet">attributes of this field</param>
6493 /// <param name="name">field name</param>
6494 /// <param name="fType">field type</param>
6495 /// <returns>a descriptor for this new "global" field</returns>
6496 public FieldDef AddField(FieldAttr attrSet, string name, Type fType) {
6497 return moduleClass.AddField(attrSet,name,fType);
6501 /// Add a class to this module
6503 /// <param name="attrSet">attributes of this class</param>
6504 /// <param name="nsName">name space name</param>
6505 /// <param name="name">class name</param>
6506 /// <returns>a descriptor for this new class</returns>
6507 public ClassDef AddClass(TypeAttr attrSet, string nsName, string name) {
6508 ClassDef aClass = new ClassDef(attrSet,nsName,name,metaData);
6509 metaData.AddToTable(MDTable.TypeDef,aClass);
6514 /// Add a class which extends System.ValueType to this module
6516 /// <param name="attrSet">attributes of this class</param>
6517 /// <param name="nsName">name space name</param>
6518 /// <param name="name">class name</param>
6519 /// <returns>a descriptor for this new class</returns>
6520 public ClassDef AddValueClass(TypeAttr attrSet, string nsName, string name, ValueClass vClass) {
6521 ClassDef aClass = new ClassDef(attrSet,nsName,name,metaData);
6522 aClass.MakeValueClass(vClass);
6523 aClass.SetTypeIndex (PrimitiveType.ValueType.GetTypeIndex ());
6524 metaData.AddToTable(MDTable.TypeDef,aClass);
6529 /// Add a class to this module
6531 /// <param name="attrSet">attributes of this class</param>
6532 /// <param name="nsName">name space name</param>
6533 /// <param name="name">class name</param>
6534 /// <param name="superType">super type of this class (extends)</param>
6535 /// <returns>a descriptor for this new class</returns>
6536 public ClassDef AddClass(TypeAttr attrSet, string nsName, string name, Class superType) {
6537 ClassDef aClass = new ClassDef(attrSet,nsName,name,metaData);
6538 aClass.SetSuper(superType);
6539 metaData.AddToTable(MDTable.TypeDef,aClass);
6543 public FileRef AddFile(string fName, byte[] hashBytes, bool hasMetaData, bool entryPoint) {
6544 FileRef file = new FileRef(fName,hashBytes,hasMetaData,entryPoint,metaData);
6545 metaData.AddToTable(MDTable.File,file);
6550 /// Add a manifest resource to this PEFile NOT YET IMPLEMENTED
6552 /// <param name="mr"></param>
6553 public void AddManifestResource(ManifestResource mr) {
6554 metaData.AddToTable(MDTable.ManifestResource,mr);
6556 //mr.FixName(metaData);
6559 public void AddCustomAttribute (Method meth, byte [] data, MetaDataElement element)
6561 metaData.AddCustomAttribute (new CustomAttribute (element, meth, data));
6565 /// Add a managed resource from another assembly.
6567 /// <param name="resName">The name of the resource</param>
6568 /// <param name="assem">The assembly where the resource is</param>
6569 /// <param name="isPublic">Access for the resource</param>
6570 public void AddExternalManagedResource (string resName, AssemblyRef assem, uint flags) {
6571 resources.Add (new ManifestResource (resName, flags, assem));
6575 /// Add a managed resource from another assembly.
6577 /// <param name="mr"></param>
6578 /// <param name="isPublic"></param>
6579 public void AddExternalManagedResource (ManifestResource mr) {
6580 resources.Add (new ManifestResource (mr));
6585 /// <param name="name">The name of the resource</param>
6586 /// <returns>The resource with the name "name" or null </returns>
6587 public ManifestResource GetResource (string name) {
6588 for (int i = 0; i < resources.Count; i ++) {
6589 if (((ManifestResource) resources [i]).Name == name)
6590 return (ManifestResource) resources [i];
6595 public ManifestResource [] GetResources() {
6596 return (ManifestResource []) resources.ToArray (typeof (ManifestResource));
6600 /// Write out the PEFile (the "bake" function)
6602 public void WritePEFile() { /* the "bake" function */
6603 fileImage.ReserveStrongNameSignatureSpace = thisAssembly.HasPublicKey;
6604 fileImage.MakeFile();
6608 /// Get the descriptor of this module
6610 /// <returns>the descriptor for this module</returns>
6611 public Module GetThisModule() {
6616 /// Get the descriptor for this assembly. The PEFile must have been
6617 /// created with hasAssembly = true
6619 /// <returns>the descriptor for this assembly</returns>
6620 public Assembly GetThisAssembly() {
6621 return thisAssembly;
6626 /**************************************************************************/
6628 /// Descriptor for the Primitive types defined in IL
6630 public class PrimitiveType : Type
6632 private string name;
6633 private int systemTypeIndex;
6634 public static int NumSystemTypes = 18;
6636 public static readonly PrimitiveType Void = new PrimitiveType(0x01,"Void",0);
6637 public static readonly PrimitiveType Boolean = new PrimitiveType(0x02,"Boolean",1);
6638 public static readonly PrimitiveType Char = new PrimitiveType(0x03,"Char",2);
6639 public static readonly PrimitiveType Int8 = new PrimitiveType(0x04,"SByte",3);
6640 public static readonly PrimitiveType UInt8 = new PrimitiveType(0x05,"Byte",4);
6641 public static readonly PrimitiveType Int16 = new PrimitiveType(0x06,"Int16",5);
6642 public static readonly PrimitiveType UInt16 = new PrimitiveType(0x07,"UInt16",6);
6643 public static readonly PrimitiveType Int32 = new PrimitiveType(0x08,"Int32",7);
6644 public static readonly PrimitiveType UInt32 = new PrimitiveType(0x09,"UInt32",8);
6645 public static readonly PrimitiveType Int64 = new PrimitiveType(0x0A,"Int64",9);
6646 public static readonly PrimitiveType UInt64 = new PrimitiveType(0x0B,"UInt64",10);
6647 public static readonly PrimitiveType Float32 = new PrimitiveType(0x0C,"Single",11);
6648 public static readonly PrimitiveType Float64 = new PrimitiveType(0x0D,"Double",12);
6649 public static readonly PrimitiveType String = new PrimitiveType(0x0E,"String",13);
6650 internal static readonly PrimitiveType Class = new PrimitiveType(0x12);
6651 public static readonly PrimitiveType TypedRef = new PrimitiveType(0x16,"TypedReference",14);
6652 public static readonly PrimitiveType IntPtr = new PrimitiveType(0x18,"IntPtr",15);
6653 public static readonly PrimitiveType UIntPtr = new PrimitiveType(0x19,"UIntPtr",16);
6654 public static readonly PrimitiveType Object = new PrimitiveType(0x1C,"Object",17);
6655 internal static readonly PrimitiveType ClassType = new PrimitiveType(0x50);
6656 internal static readonly PrimitiveType SZArray = new PrimitiveType(0x1D);
6657 internal static readonly PrimitiveType ValueType = new PrimitiveType(0x11, "ValueType", 18);
6658 public static readonly PrimitiveType NativeInt = IntPtr;
6659 public static readonly PrimitiveType NativeUInt = UIntPtr;
6661 internal PrimitiveType(byte typeIx) : base(typeIx) { }
6663 internal PrimitiveType(byte typeIx, string name, int STIx) : base(typeIx) {
6665 this.systemTypeIndex = STIx;
6668 internal string GetName() { return name; }
6670 internal int GetSystemTypeIx() { return systemTypeIndex; }
6672 internal sealed override void TypeSig(MemoryStream str) {
6673 str.WriteByte(typeIndex);
6676 internal override MetaDataElement GetTypeSpec(MetaData md) {
6677 TypeSpec tS = md.GetPrimitiveTypeSpec(systemTypeIndex);
6679 tS = new TypeSpec(this,md);
6680 md.SetPrimitiveTypeSpec(systemTypeIndex,tS);
6681 md.AddToTable(MDTable.TypeSpec,tS);
6688 /**************************************************************************/
6690 /// Descriptor for the Property of a class
6692 public class Property : Feature
6694 private static readonly byte PropertyTag = 0x8;
6695 MethodDef getterMeth;
6696 ConstantElem constVal;
6697 uint typeBlobIx = 0;
6702 internal Property(string name, Type retType, Type[] pars, ClassDef parent) : base(name, parent) {
6703 returnType = retType;
6705 if (pars != null) numPars = (uint)pars.Length;
6706 tabIx = MDTable.Property;
6710 /// Add a set method to this property
6712 /// <param name="setter">the set method</param>
6713 public void AddSetter(MethodDef setter) {
6714 AddMethod(setter,MethodType.Setter);
6718 /// Add a get method to this property
6720 /// <param name="getter">the get method</param>
6721 public void AddGetter(MethodDef getter) {
6722 AddMethod(getter,MethodType.Getter);
6723 getterMeth = getter;
6727 /// Add another method to this property
6729 /// <param name="other">the method</param>
6730 public void AddOther(MethodDef other) {
6731 AddMethod(other,MethodType.Other);
6735 /// Add an initial value for this property
6737 /// <param name="constVal">the initial value for this property</param>
6738 public void AddInitValue(Constant constVal) {
6739 this.constVal = new ConstantElem(this,constVal);
6742 internal sealed override void BuildTables(MetaData md) {
6744 nameIx = md.AddToStringsHeap(name);
6745 MemoryStream sig = new MemoryStream();
6746 sig.WriteByte(PropertyTag);
6747 MetaData.CompressNum(numPars,sig);
6748 returnType.TypeSig(sig);
6749 for (int i=0; i < numPars; i++) {
6750 parList[i].TypeSig(sig);
6752 typeBlobIx = md.AddToBlobHeap(sig.ToArray());
6753 for (int i=0; i < tide; i++) {
6754 md.AddToTable(MDTable.MethodSemantics,methods[i]);
6756 if (constVal != null) {
6757 md.AddToTable(MDTable.Constant,constVal);
6758 constVal.BuildTables(md);
6763 internal sealed override uint Size(MetaData md) {
6764 return 2 + md.StringsIndexSize() + md.BlobIndexSize();
6767 internal sealed override void Write(FileImage output) {
6768 output.Write(flags);
6769 output.StringsIndex(nameIx);
6770 output.BlobIndex(typeBlobIx);
6773 internal sealed override uint GetCodedIx(CIx code) {
6775 case (CIx.HasCustomAttr) : return 9;
6776 case (CIx.HasConst) : return 2;
6777 case (CIx.HasSemantics) : return 1;
6783 /**************************************************************************/
6785 /// Descriptor for an pointer (type * or type &)
6787 public abstract class PtrType : Type
6791 internal PtrType(Type bType, byte typeIx) : base(typeIx)
6794 tabIx = MDTable.TypeSpec;
6797 internal sealed override void TypeSig(MemoryStream str) {
6798 str.WriteByte(typeIndex);
6799 baseType.TypeSig(str);
6803 /**************************************************************************/
6805 /// Descriptor for a managed pointer (type & or byref)
6808 public class ManagedPointer : PtrType // <type> & (BYREF)
6812 /// Create new managed pointer to baseType
6814 /// <param name="bType">the base type of the pointer</param>
6815 public ManagedPointer(Type baseType) : base(baseType,0x10) { }
6818 /**************************************************************************/
6820 /// Descriptor for an unmanaged pointer (type *)
6822 public class UnmanagedPointer : PtrType // PTR
6825 /// Create a new unmanaged pointer to baseType
6827 /// <param name="baseType">the base type of the pointer</param>
6828 public UnmanagedPointer(Type baseType) : base(baseType, 0x0F) { }
6831 /**************************************************************************/
6833 /// Base class for scopes (extended by Module, ModuleRef, Assembly, AssemblyRef)
6835 public abstract class ResolutionScope : MetaDataElement
6837 protected uint nameIx = 0;
6838 protected MetaData metaData;
6839 protected string name;
6841 internal ResolutionScope(string name, MetaData md)
6845 nameIx = md.AddToStringsHeap(name);
6848 internal string GetName() { return name; }
6851 /**************************************************************************/
6853 /// Descriptor for a Section in a PEFile eg .text, .sdata
6855 internal class Section {
6856 private static readonly uint relocPageSize = 4096; // 4K pages for fixups
6859 uint offset = 0, tide = 0, size = 0, rva = 0, relocTide = 0;
6860 //uint relocOff = 0;
6861 uint flags = 0, padding = 0;
6864 internal Section(string sName, uint sFlags) {
6865 name = sName.ToCharArray();
6869 internal uint Tide() { return tide; }
6871 internal void IncTide(uint incVal) { tide += incVal; }
6873 internal uint Padding() { return padding; }
6875 internal uint Size() { return size; }
6877 internal void SetSize(uint pad) {
6879 size = tide + padding;
6882 internal uint RVA() { return rva; }
6884 internal void SetRVA(uint rva) { this.rva = rva; }
6886 internal uint Offset() { return offset; }
6888 internal void SetOffset(uint offs) { offset = offs; }
6890 internal void DoBlock(BinaryWriter reloc, uint page, int start, int end) {
6891 //Console.WriteLine("rva = " + rva + " page = " + page);
6892 reloc.Write(rva + page);
6893 reloc.Write((uint)(((end-start+1)*2) + 8));
6894 for (int j=start; j < end; j++) {
6895 //Console.WriteLine("reloc offset = " + relocs[j]);
6896 reloc.Write((ushort)((0x3 << 12) | (relocs[j] - page)));
6898 reloc.Write((ushort)0);
6901 internal void DoRelocs(BinaryWriter reloc) {
6902 if (relocTide > 0) {
6903 //relocOff = (uint)reloc.Seek(0,SeekOrigin.Current);
6904 uint block = (relocs[0]/relocPageSize + 1) * relocPageSize;
6906 for (int i=1; i < relocTide; i++) {
6907 if (relocs[i] >= block) {
6908 DoBlock(reloc,block-relocPageSize,start,i);
6910 block = (relocs[i]/relocPageSize + 1) * relocPageSize;
6913 DoBlock(reloc,block-relocPageSize,start,(int)relocTide);
6917 internal void AddReloc(uint offs) {
6919 if (relocs == null) {
6920 relocs = new uint[5];
6922 if (relocTide >= relocs.Length) {
6923 uint[] tmp = relocs;
6924 relocs = new uint[tmp.Length + 5];
6925 for (int i=0; i < relocTide; i++) {
6929 while ((pos < relocTide) && (relocs[pos] < offs)) pos++;
6930 for (int i=pos; i < relocTide; i++) {
6931 relocs[i+1] = relocs[i];
6938 internal void WriteHeader(BinaryWriter output, uint relocRVA) {
6943 output.Write(offset);
6945 //output.Write(relocRVA + relocOff);
6948 //output.Write((ushort)relocTide);
6949 //output.Write((ushort)0);
6950 output.Write(flags);
6954 /**************************************************************************/
6955 public abstract class Signature : MetaDataElement
6957 protected uint sigIx;
6959 internal Signature() {
6960 tabIx = MDTable.StandAloneSig;
6963 internal sealed override uint Size(MetaData md) {
6964 return md.BlobIndexSize();
6967 internal sealed override void Write(FileImage output) {
6968 output.BlobIndex(sigIx);
6971 internal sealed override uint GetCodedIx(CIx code) { return (uint)tabIx; }
6974 /**************************************************************************/
6976 /// Descriptor for a class defined in System (mscorlib)
6978 internal class SystemClass : ClassRef
6980 PrimitiveType elemType;
6982 internal SystemClass(PrimitiveType eType, AssemblyRef paren, MetaData md)
6983 : base("System",eType.GetName(),md) {
6988 internal override sealed MetaDataElement GetTypeSpec(MetaData md) {
6989 if (typeSpec == null) typeSpec = (TypeSpec)elemType.GetTypeSpec(md);
6994 internal sealed override void TypeSig(MemoryStream str) {
6995 str.WriteByte(elemType.GetTypeIndex());
6999 /**************************************************************************/
7001 /// Base class for all IL types
7003 public abstract class Type : MetaDataElement {
7004 protected byte typeIndex;
7005 protected TypeSpec typeSpec;
7007 internal Type(byte tyIx) { typeIndex = tyIx; }
7009 internal byte GetTypeIndex() { return typeIndex; }
7010 internal void SetTypeIndex (byte b) { typeIndex = b; }
7012 internal virtual MetaDataElement GetTypeSpec(MetaData md) {
7013 if (typeSpec == null) {
7014 typeSpec = new TypeSpec(this,md);
7015 md.AddToTable(MDTable.TypeSpec,typeSpec);
7020 internal virtual void TypeSig(MemoryStream str) {
7021 throw(new TypeSignatureException(this.GetType().AssemblyQualifiedName +
7022 " doesn't have a type signature!!"));
7027 /**************************************************************************/
7029 public class TypeSpec : MetaDataElement {
7032 internal TypeSpec(Type aType, MetaData md) {
7033 MemoryStream sig = new MemoryStream();
7035 sigIx = md.AddToBlobHeap(sig.ToArray());
7036 tabIx = MDTable.TypeSpec;
7039 internal sealed override uint GetCodedIx(CIx code) {
7041 case (CIx.TypeDefOrRef) : return 2;
7042 case (CIx.HasCustomAttr) : return 13;
7043 case (CIx.MemberRefParent) : return 4;
7048 internal override uint Size(MetaData md) {
7049 return md.BlobIndexSize();
7052 internal sealed override void Write(FileImage output) {
7053 //Console.WriteLine("Writing the blob index for a TypeSpec");
7054 output.BlobIndex(sigIx);
7059 class ByteArrayComparer : IComparer {
7061 public int Compare (object x, object y)
7063 byte [] a = (byte []) x;
7064 byte [] b = (byte []) y;
7067 if (b.Length != len)
7070 for (int i = 0; i < len; ++i)
7077 class ByteArrayHashCodeProvider : IHashCodeProvider {
7079 public int GetHashCode (Object key)
7081 byte [] arr = (byte []) key;
7082 int len = arr.Length;
7085 for (int i = 0; i < len; ++i)
7086 h = (h << 5) - h + arr [i];