3 using System.Collections;
\r
9 readonly static char[] hexDigit = {'0','1','2','3','4','5','6','7',
\r
10 '8','9','A','B','C','D','E','F'};
\r
11 readonly static uint[] iByteMask = {0x000000FF, 0x0000FF00, 0x00FF0000, 0xFF000000};
\r
12 readonly static ulong[] lByteMask = {0x00000000000000FF, 0x000000000000FF00,
\r
13 0x0000000000FF0000, 0x00000000FF000000,
\r
14 0x000000FF00000000, 0x0000FF0000000000,
\r
15 0x00FF000000000000, 0xFF00000000000000 };
\r
16 readonly static uint nibble0Mask = 0x0000000F;
\r
17 readonly static uint nibble1Mask = 0x000000F0;
\r
19 public static String Byte(int b) {
\r
20 char[] str = new char[2];
\r
22 uint b1 = num & nibble0Mask;
\r
23 uint b2 = (num & nibble1Mask) >> 4;
\r
24 str[0] = hexDigit[b2];
\r
25 str[1] = hexDigit[b1];
\r
26 return new String(str);
\r
29 public static String Short(int b) {
\r
30 char[] str = new char[4];
\r
31 uint num1 = (uint)b & iByteMask[0];
\r
32 uint num2 = ((uint)b & iByteMask[1]) >> 8;
\r
33 uint b1 = num1 & nibble0Mask;
\r
34 uint b2 = (num1 & nibble1Mask) >> 4;
\r
35 uint b3 = num2 & nibble0Mask;
\r
36 uint b4 = (num2 & nibble1Mask) >> 4;
\r
37 str[0] = hexDigit[b4];
\r
38 str[1] = hexDigit[b3];
\r
39 str[2] = hexDigit[b2];
\r
40 str[3] = hexDigit[b1];
\r
41 return new String(str);
\r
44 public static String Int(int val) {
\r
45 char[] str = new char[8];
\r
46 uint num = (uint)val;
\r
48 for (int i=0; i < iByteMask.Length; i++) {
\r
49 uint b = num & iByteMask[i];
\r
51 uint b1 = b & nibble0Mask;
\r
52 uint b2 = (b & nibble1Mask) >> 4;
\r
53 str[strIx--] = hexDigit[b1];
\r
54 str[strIx--] = hexDigit[b2];
\r
56 return new String(str);
\r
59 public static String Int(uint num) {
\r
60 char[] str = new char[8];
\r
62 for (int i=0; i < iByteMask.Length; i++) {
\r
63 uint b = num & iByteMask[i];
\r
65 uint b1 = b & nibble0Mask;
\r
66 uint b2 = (b & nibble1Mask) >> 4;
\r
67 str[strIx--] = hexDigit[b1];
\r
68 str[strIx--] = hexDigit[b2];
\r
70 return new String(str);
\r
73 public static String Long(long lnum) {
\r
74 ulong num = (ulong)lnum;
\r
75 char[] str = new char[16];
\r
77 for (int i=0; i < lByteMask.Length; i++) {
\r
78 ulong b = num & lByteMask[i];
\r
80 ulong b1 = b & nibble0Mask;
\r
81 ulong b2 = (b & nibble1Mask) >> 4;
\r
82 str[strIx--] = hexDigit[b1];
\r
83 str[strIx--] = hexDigit[b2];
\r
85 return new String(str);
\r
89 public class NotYetImplementedException : System.Exception
\r
91 public NotYetImplementedException(string msg) : base(msg + " Not Yet Implemented") { }
\r
94 public class TypeSignatureException : System.Exception {
\r
95 public TypeSignatureException(string msg) : base(msg) { }
\r
98 public class ClassRefInst : Type {
\r
101 private bool is_value;
103 public ClassRefInst (Type type, bool is_value) : base (0x12) {
\r
105 this.is_value = is_value;
107 type.SetTypeIndex (0x11);
108 tabIx = MDTable.TypeSpec;
\r
111 internal sealed override void TypeSig(MemoryStream str) {
116 public class MVar : Type {
\r
120 public MVar (int index) : base (0x1E) {
\r
121 this.index = index;
\r
122 tabIx = MDTable.TypeSpec;
\r
125 internal sealed override void TypeSig(MemoryStream str) {
\r
126 str.WriteByte(typeIndex);
\r
127 MetaData.CompressNum ((uint) index, str);
\r
131 public class GenericTypeSpec : Type {
\r
135 public GenericTypeSpec (int index) : base (0x13) {
\r
136 this.index = index;
\r
137 tabIx = MDTable.TypeSpec;
\r
140 internal sealed override void TypeSig(MemoryStream str) {
\r
141 str.WriteByte(typeIndex);
\r
142 MetaData.CompressNum ((uint) index, str);
\r
146 public class GenericTypeInst : Type {
\r
148 private Type gen_type;
\r
149 private Type[] gen_param;
\r
151 public GenericTypeInst (Type gen_type, Type[] gen_param) : base (0x15)
\r
154 this.gen_type = gen_type;
\r
155 this.gen_param = gen_param;
\r
156 tabIx = MDTable.TypeSpec;
\r
159 internal sealed override void TypeSig(MemoryStream str) {
\r
160 str.WriteByte(typeIndex);
\r
161 gen_type.TypeSig (str);
\r
162 MetaData.CompressNum ((uint) gen_param.Length, str);
\r
163 foreach (Type param in gen_param)
\r
164 param.TypeSig (str);
\r
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
\r
205 public abstract class Array : Type
\r
208 protected Type elemType;
\r
209 protected MetaData metaData;
\r
210 protected string cnameSpace, cname;
\r
212 internal Array(Type eType, byte TypeId) : base(TypeId) {
\r
214 tabIx = MDTable.TypeSpec;
\r
219 /**************************************************************************/
\r
222 /// Single dimensional array with zero lower bound
\r
224 public class ZeroBasedArray : Array {
\r
227 /// Create a new array - elementType[]
\r
229 /// <param name="elementType">the type of the array elements</param>
\r
230 public ZeroBasedArray(Type elementType) : base (elementType,0x1D) { }
\r
232 internal sealed override void TypeSig(MemoryStream str) {
\r
233 str.WriteByte(typeIndex);
\r
234 elemType.TypeSig(str);
\r
240 /**************************************************************************/
\r
243 /// Multi dimensional array with explicit bounds
\r
245 public class BoundArray : Array {
\r
251 /// Create a new multi dimensional array type
\r
252 /// eg. elemType[1..5,3..10,5,,] would be
\r
253 /// new BoundArray(elemType,5,[1,3,0],[5,10,4])
\r
255 /// <param name="elementType">the type of the elements</param>
\r
256 /// <param name="dimensions">the number of dimensions</param>
\r
257 /// <param name="loBounds">lower bounds of dimensions</param>
\r
258 /// <param name="upBounds">upper bounds of dimensions</param>
\r
259 public BoundArray(Type elementType, uint dimensions, int[] loBounds,
\r
260 int[] upBounds) : base (elementType,0x14) {
\r
261 numDims = dimensions;
\r
262 lowerBounds = loBounds;
\r
263 sizes = new int[loBounds.Length];
\r
264 for (int i=0; i < loBounds.Length; i++) {
\r
265 sizes[i] = upBounds[i] - loBounds[i] + 1;
\r
270 /// Create a new multi dimensional array type
\r
271 /// eg. elemType[5,10,20] would be new BoundArray(elemType,3,[5,10,20])
\r
273 /// <param name="elementType">the type of the elements</param>
\r
274 /// <param name="dimensions">the number of dimensions</param>
\r
275 /// <param name="size">the sizes of the dimensions</param>
\r
276 public BoundArray(Type elementType, uint dimensions, int[] size)
\r
277 : base (elementType,0x14) {
\r
278 numDims = dimensions;
\r
283 /// Create a new multi dimensional array type
\r
284 /// eg. elemType[,,] would be new BoundArray(elemType,3)
\r
286 /// <param name="elementType">the type of the elements</param>
\r
287 /// <param name="dimensions">the number of dimensions</param>
\r
288 public BoundArray(Type elementType, uint dimensions)
\r
289 : base (elementType,0x14) {
\r
290 numDims = dimensions;
\r
293 internal sealed override void TypeSig(MemoryStream str) {
\r
294 str.WriteByte(typeIndex);
\r
295 elemType.TypeSig(str);
\r
296 MetaData.CompressNum(numDims,str);
\r
297 if ((sizes != null) && (sizes.Length > 0)) {
\r
298 MetaData.CompressNum((uint)sizes.Length,str);
\r
299 for (int i=0; i < sizes.Length; i++) {
\r
300 MetaData.CompressNum((uint)sizes[i],str);
\r
302 } else str.WriteByte(0);
\r
303 if ((lowerBounds != null) && (lowerBounds.Length > 0)) {
\r
304 MetaData.CompressNum((uint)lowerBounds.Length,str);
\r
305 for (int i=0; i < lowerBounds.Length; i++) {
\r
306 MetaData.CompressNum((uint)lowerBounds[i],str);
\r
308 } else str.WriteByte(0);
\r
312 /**************************************************************************/
\r
314 /// Descriptor for THIS assembly (.assembly)
\r
316 public class Assembly : ResolutionScope
\r
318 ushort majorVer, minorVer, buildNo, revisionNo;
\r
321 uint keyIx = 0, cultIx = 0;
322 bool hasPublicKey = false;
\r
324 internal Assembly(string name, MetaData md) : base(name,md) {
\r
325 tabIx = MDTable.Assembly;
\r
329 /// Add details about THIS assembly
\r
331 /// <param name="majVer">Major Version</param>
\r
332 /// <param name="minVer">Minor Version</param>
\r
333 /// <param name="bldNo">Build Number</param>
\r
334 /// <param name="revNo">Revision Number</param>
\r
335 /// <param name="key">Hash Key</param>
\r
336 /// <param name="hash">Hash Algorithm</param>
\r
337 /// <param name="cult">Culture</param>
\r
338 public void AddAssemblyInfo(int majVer, int minVer, int bldNo, int revNo,
\r
339 byte[] key, uint hash, string cult) {
\r
340 majorVer = (ushort)majVer;
\r
341 minorVer = (ushort)minVer;
\r
342 buildNo = (ushort)bldNo;
\r
343 revisionNo = (ushort)revNo;
\r
345 hasPublicKey = (key != null);
\r
346 keyIx = metaData.AddToBlobHeap(key);
\r
347 cultIx = metaData.AddToStringsHeap(cult);
\r
351 /// Add an attribute to THIS assembly
\r
353 /// <param name="aa">assembly attribute</param>
\r
354 public void AddAssemblyAttr(AssemAttr aa) {
\r
358 internal sealed override uint Size(MetaData md) {
\r
359 return 16 + md.BlobIndexSize() + 2 * md.StringsIndexSize();
\r
362 internal sealed override void Write(FileImage output) {
\r
363 // Console.WriteLine("Writing assembly element with nameIx of " + nameIx + " at file offset " + output.Seek(0,SeekOrigin.Current));
\r
364 output.Write((uint)hashAlgId);
\r
365 output.Write(majorVer);
\r
366 output.Write(minorVer);
\r
367 output.Write(buildNo);
\r
368 output.Write(revisionNo);
\r
369 output.Write(flags);
\r
370 output.BlobIndex(keyIx);
\r
371 output.StringsIndex(nameIx);
\r
372 output.StringsIndex(cultIx);
\r
375 internal sealed override uint GetCodedIx(CIx code) {
\r
377 case (CIx.HasCustomAttr) : return 14;
\r
378 case (CIx.HasDeclSecurity) : return 2;
\r
383 internal bool HasPublicKey {
384 get { return hasPublicKey; }
387 /**************************************************************************/
\r
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)
\r
397 public class AssemblyRef : ResolutionScope, IExternRef
399 private ushort major, minor, build, revision;
\r
400 uint flags, keyIx, hashIx, cultIx;
\r
401 bool hasVersion = false, isKeyToken = false;
\r
405 internal AssemblyRef(MetaData md, string name) : base(name,md) {
\r
406 tabIx = MDTable.AssemblyRef;
\r
410 /// Add version information about this external assembly
\r
412 /// <param name="majVer">Major Version</param>
\r
413 /// <param name="minVer">Minor Version</param>
\r
414 /// <param name="bldNo">Build Number</param>
\r
415 /// <param name="revNo">Revision Number</param>
\r
416 public void AddVersionInfo(int majVer, int minVer, int bldNo, int revNo) {
\r
417 major = (ushort)majVer;
\r
418 minor = (ushort)minVer;
\r
419 build = (ushort)bldNo;
\r
420 revision = (ushort)revNo;
\r
425 /// Add the hash value for this external assembly
\r
427 /// <param name="hash">bytes of the hash value</param>
\r
428 public void AddHash(byte[] hash) {
\r
429 hashIx = metaData.AddToBlobHeap(hash);
\r
433 /// Set the culture for this external assembly
\r
435 /// <param name="cult">the culture string</param>
\r
436 public void AddCulture(string cult) {
\r
437 cultIx = metaData.AddToStringsHeap(cult);
\r
442 /// Add the full public key for this external assembly
\r
444 /// <param name="key">bytes of the public key</param>
\r
445 public void AddKey(byte[] key) {
\r
446 flags |= 0x0001; // full public key
\r
448 keyIx = metaData.AddToBlobHeap(key);
\r
452 /// Add the public key token (low 8 bytes of the public key)
\r
454 /// <param name="key">low 8 bytes of public key</param>
\r
455 public void AddKeyToken(byte[] key) {
\r
456 keyIx = metaData.AddToBlobHeap(key);
\r
462 /// Add a class to this external assembly
\r
464 /// <param name="nsName">name space name</param>
\r
465 /// <param name="name">class name</param>
\r
466 /// <returns></returns>
\r
467 public virtual ClassRef AddClass(string nsName, string name) {
\r
468 ClassRef aClass = new ClassRef(nsName,name,metaData);
\r
469 metaData.AddToTable(MDTable.TypeRef,aClass);
\r
470 aClass.SetParent(this);
\r
475 /// Add a value class to this external assembly
\r
477 /// <param name="nsName">name space name</param>
\r
478 /// <param name="name">class name</param>
\r
479 /// <returns></returns>
\r
480 public virtual ClassRef AddValueClass(string nsName, string name) {
\r
481 ClassRef aClass = new ClassRef(nsName,name,metaData);
\r
482 metaData.AddToTable(MDTable.TypeRef,aClass);
\r
483 aClass.SetParent(this);
\r
484 aClass.MakeValueClass();
\r
488 internal string TypeName() {
\r
489 string result = name;
\r
491 result = result + ", Version=" + major + "." + minor + "." +
\r
492 build + "." + revision;
\r
493 if (keyBytes != null) {
\r
494 string tokenStr = "=";
\r
495 if (isKeyToken) tokenStr = "Token=";
\r
496 result = result + ", PublicKey" + tokenStr;
\r
497 for (int i=0; i < keyBytes.Length; i++) {
\r
498 result = result + Hex.Byte(keyBytes[i]);
\r
501 if (culture != null)
\r
502 result = result + ", Culture=" + culture;
\r
506 internal sealed override uint Size(MetaData md) {
\r
507 return 12 + 2 * md.StringsIndexSize() + 2 * md.BlobIndexSize();
\r
510 internal sealed override void Write(FileImage output) {
\r
511 output.Write(major);
\r
512 output.Write(minor);
\r
513 output.Write(build);
\r
514 output.Write(revision);
\r
515 output.Write(flags);
\r
516 output.BlobIndex(keyIx);
\r
517 output.StringsIndex(nameIx);
\r
518 output.StringsIndex(cultIx);
\r
519 output.BlobIndex(hashIx);
\r
522 internal sealed override uint GetCodedIx(CIx code) {
\r
524 case (CIx.ResolutionScope) : return 2;
\r
525 case (CIx.HasCustomAttr) : return 15;
\r
526 case (CIx.Implementation) : return 1;
\r
532 /**************************************************************************/
\r
535 /// flags for the assembly (.corflags)
\r
537 public enum CorFlags {CF_IL_ONLY = 1, CF_32_BITREQUIRED = 2,
538 CF_STRONGNAMESIGNED = 8, CF_TRACKDEBUGDATA = 0x10000 }
\r
541 /// subsystem for the assembly (.subsystem)
\r
543 public enum SubSystem { Native = 1, Windows_GUI = 2,
\r
544 Windows_CUI = 3, OS2_CUI = 5, POSIX_CUI = 7, Native_Windows = 8,
\r
545 Windows_CE_GUI = 9}
\r
548 /// Hash algorithms for the assembly
\r
550 public enum HashAlgorithm { None, SHA1 }
\r
553 /// Attributes for this assembly
\r
555 public enum AssemAttr { EnableJITCompileTracking = 0x8000,
\r
556 DisableJITCompileOptimizer = 0x4000}
\r
559 /// Method call conventions
\r
561 public enum CallConv { Default, Cdecl, Stdcall, Thiscall,
\r
562 Fastcall, Vararg, Instance = 0x20, Generic = 0x10, InstanceExplicit = 0x60 }
\r
565 /// Type custom modifier
\r
567 public enum CustomModifier { modreq = 0x1F, modopt };
\r
570 /// Attibutes for a class
\r
572 public enum TypeAttr {Private, Public, NestedPublic, NestedPrivate,
\r
573 NestedFamily, NestedAssembly, NestedFamAndAssem, NestedFamOrAssem,
\r
574 SequentialLayout, ExplicitLayout = 0x10, Interface = 0x20,
\r
575 Abstract = 0x80, PublicAbstract = 0x81, Sealed = 0x100,
\r
576 PublicSealed = 0x101, SpecialName = 0x400, RTSpecialName = 0x800,
\r
577 Import = 0x1000, Serializable = 0x2000, UnicodeClass = 0x10000,
\r
578 AutoClass = 0x20000, BeforeFieldInit = 0x100000 }
\r
581 /// Attributes for a field
\r
583 public enum FieldAttr {Default, Private, FamAndAssem, Assembly,
\r
584 Family, FamOrAssem, Public, Static = 0x10, PublicStatic = 0x16,
\r
585 Initonly = 0x20, Literal = 0x40, Notserialized = 0x80,
\r
586 SpecialName = 0x200, RTSpecialName = 0x400 }
\r
589 /// Attributes for a method
\r
591 public enum MethAttr { Default, Private, FamAndAssem, Assembly,
\r
592 Family, FamOrAssem, Public, Static = 0x0010, PublicStatic = 0x16,
\r
593 Final = 0x0020, PublicStaticFinal = 0x36, Virtual = 0x0040,
\r
594 PrivateVirtual, PublicVirtual = 0x0046, HideBySig = 0x0080,
\r
595 NewSlot = 0x0100, Abstract = 0x0400, SpecialName = 0x0800,
\r
596 RTSpecialName = 0x1000, SpecialRTSpecialName = 0x1800,
\r
597 RequireSecObject = 0x8000}
\r
600 /// Attributes for .pinvokeimpl method declarations
\r
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 }
\r
607 /// Implementation attributes for a method
\r
609 public enum ImplAttr { IL, Native, Runtime = 0x03, Unmanaged = 0x04,
\r
610 ForwardRef = 0x10, PreserveSig = 0x0080, InternalCall = 0x1000,
\r
611 Synchronised = 0x0020, Synchronized = 0x0020, NoInLining = 0x0008, Optil = 0x0002}
\r
614 /// Modes for a parameter
\r
616 public enum ParamAttr { Default, In, Out, Opt = 4 }
\r
619 /// CIL instructions
\r
621 public enum Op { nop, breakOp, ldarg_0, ldarg_1, ldarg_2, ldarg_3,
\r
622 ldloc_0, ldloc_1, ldloc_2, ldloc_3, stloc_0, stloc_1, stloc_2, stloc_3,
\r
623 ldnull = 0x14, ldc_i4_m1, ldc_i4_0, ldc_i4_1, ldc_i4_2, ldc_i4_3,
\r
624 ldc_i4_4, ldc_i4_5, ldc_i4_6, ldc_i4_7, ldc_i4_8, dup = 0x25, pop,
\r
625 ret = 0x2A, ldind_i1 = 0x46, ldind_u1, ldind_i2, ldind_u2, ldind_i4,
\r
626 ldind_u4, ldind_i8, ldind_i, ldind_r4, ldind_r8, ldind_ref, stind_ref,
\r
627 stind_i1, stind_i2, stind_i4, stind_i8, stind_r4, stind_r8, add, sub, mul,
\r
628 div, div_un, rem, rem_un, and, or, xor, shl, shr, shr_un, neg, not,
\r
629 conv_i1, conv_i2, conv_i4, conv_i8, conv_r4, conv_r8, conv_u4, conv_u8,
\r
630 conv_r_un = 0x76, throwOp = 0x7A, conv_ovf_i1_un = 0x82, conv_ovf_i2_un,
\r
631 conv_ovf_i4_un, conv_ovf_i8_un, conf_ovf_u1_un, conv_ovf_u2_un,
\r
632 conv_ovf_u4_un, conv_ovf_u8_un, conv_ovf_i_un, conv_ovf_u_un,
\r
633 ldlen = 0x8E, ldelem_i1 = 0x90, ldelem_u1, ldelem_i2, ldelem_u2,
\r
634 ldelem_i4, ldelem_u4, ldelem_i8, ldelem_i, ldelem_r4, ldelem_r8,
\r
635 ldelem_ref, stelem_i, stelem_i1, stelem_i2, stelem_i4, stelem_i8, stelem_r4 = 0xA0, stelem_r8,
\r
636 stelem_ref, conv_ovf_i1 = 0xb3, conv_ovf_u1, conv_ovf_i2, conv_ovf_u2,
\r
637 conv_ovf_i4, conv_ovf_u4, conv_ovf_i8, conv_ovf_u8, ckfinite = 0xC3,
\r
638 conv_u2 = 0xD1, conv_u1, conv_i, conv_ovf_i, conv_ovf_u, add_ovf,
\r
639 add_ovf_un, mul_ovf, mul_ovf_un, sub_ovf, sub_ovf_un, endfinally,
\r
640 stind_i = 0xDF, conv_u, arglist = 0xFE00, ceq, cgt, cgt_un, clt, clt_un,
\r
641 localloc = 0xFE0F, endfilter = 0xFE11, volatile_ = 0xFE13, tail_,
\r
642 cpblk = 0xFE17, initblk, rethrow = 0xFE1A, refanytype = 0xFE1D}
\r
645 /// CIL instructions requiring an integer parameter
\r
647 public enum IntOp {ldarg_s = 0x0E, ldarga_s, starg_s, ldloc_s, ldloca_s,
\r
648 stloc_s, ldc_i4_s = 0x1F, ldc_i4, ldarg = 0xFE09,
\r
649 ldarga, starg, ldloc, ldloca, stloc, unaligned = 0xFE12 }
\r
652 /// CIL instructions requiring a field parameter
\r
654 public enum FieldOp {ldfld = 0x7B, ldflda, stfld, ldsfld, ldsflda,
\r
655 stsfld, ldtoken = 0xD0 }
\r
658 /// CIL instructions requiring a method parameter
\r
660 public enum MethodOp {jmp = 0x27, call, callvirt = 0x6F, newobj = 0x73,
\r
661 ldtoken = 0xD0, ldftn = 0xFE06, ldvirtfn }
\r
664 /// CIL instructions requiring a type parameter
\r
666 public enum TypeOp {cpobj = 0x70, ldobj, castclass = 0x74, isinst,
\r
667 unbox = 0x79, stobj = 0x81, box = 0x8C, newarr,
\r
668 ldelema = 0x8F, refanyval = 0xC2, mkrefany = 0xC6,
\r
669 ldtoken = 0xD0, initobj = 0xFE15, sizeOf = 0xFE1C,
\r
670 ldelem = 0xA3, stelem = 0xA4, unbox_any }
\r
673 /// CIL branch instructions
\r
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,
\r
681 bne_un, bge_un, bgt_un, ble_un, blt_un,
683 leave = 0xDD, leave_s }
\r
686 /// Index for all the tables in the meta data
\r
688 public enum MDTable { Module, TypeRef, TypeDef, Field = 0x04, Method = 0x06,
\r
689 Param = 0x08, InterfaceImpl, MemberRef, Constant, CustomAttribute,
\r
690 FieldMarshal, DeclSecurity, ClassLayout, FieldLayout, StandAloneSig,
\r
691 EventMap, Event = 0x14, PropertyMap, Property = 0x17, MethodSemantics,
\r
692 MethodImpl, ModuleRef, TypeSpec, ImplMap, FieldRVA, Assembly = 0x20,
\r
693 AssemblyProcessor, AssemblyOS, AssemblyRef, AssemblyRefProcessor,
\r
694 AssemblyRefOS, File, ExportedType, ManifestResource, NestedClass,
\r
695 GenericParam, MethodSpec, GenericParamConstraint }
\r
697 public enum SafeArrayType { int16 = 2, int32, float32, float64,
\r
698 currency, date, bstr, dispatch, error, boolean, variant, unknown,
\r
699 Decimal, int8 = 16, uint8, uint16, uint32, Int = 22, UInt }
\r
701 internal enum CIx { TypeDefOrRef, HasConst, HasCustomAttr, HasFieldMarshal,
\r
702 HasDeclSecurity, MemberRefParent, HasSemantics, MethodDefOrRef,
\r
703 MemberForwarded, Implementation, CustomAttributeType, ResolutionScope,
\r
704 TypeOrMethodDef, MaxCIx }
\r
706 internal enum MapType { eventMap, propertyMap, nestedClass }
\r
708 /**************************************************************************/
\r
710 /// The assembly for mscorlib.
\r
712 public sealed class MSCorLib : AssemblyRef
\r
714 private static readonly int valueTypeIx = 18;
\r
715 private readonly string systemName = "System";
\r
716 private ClassRef[] systemClasses = new ClassRef[valueTypeIx+2];
\r
717 private PrimitiveType[] systemTypes = new PrimitiveType[valueTypeIx];
\r
718 private TypeSpec[] specialTypeSpecs = new TypeSpec[valueTypeIx];
\r
719 private static int[] specialNames = {
\r
720 PrimitiveType.Void.GetName().GetHashCode(),
\r
721 PrimitiveType.Boolean.GetName().GetHashCode(),
\r
722 PrimitiveType.Char.GetName().GetHashCode(),
\r
723 PrimitiveType.Int8.GetName().GetHashCode(),
\r
724 PrimitiveType.UInt8.GetName().GetHashCode(),
\r
725 PrimitiveType.Int16.GetName().GetHashCode(),
\r
726 PrimitiveType.UInt16.GetName().GetHashCode(),
\r
727 PrimitiveType.Int32.GetName().GetHashCode(),
\r
728 PrimitiveType.UInt32.GetName().GetHashCode(),
\r
729 PrimitiveType.Int64.GetName().GetHashCode(),
\r
730 PrimitiveType.UInt64.GetName().GetHashCode(),
\r
731 PrimitiveType.Float32.GetName().GetHashCode(),
\r
732 PrimitiveType.Float64.GetName().GetHashCode(),
\r
733 PrimitiveType.String.GetName().GetHashCode(),
\r
734 PrimitiveType.TypedRef.GetName().GetHashCode(),
\r
735 PrimitiveType.IntPtr.GetName().GetHashCode(),
\r
736 PrimitiveType.UIntPtr.GetName().GetHashCode(),
\r
737 PrimitiveType.Object.GetName().GetHashCode(),
\r
738 "ValueType".GetHashCode(),
\r
739 "Enum".GetHashCode()
\r
742 internal MSCorLib(MetaData md) : base(md,"mscorlib") {
\r
743 md.AddToTable(MDTable.AssemblyRef,this);
\r
744 systemTypes[PrimitiveType.Void.GetSystemTypeIx()] = PrimitiveType.Void;
\r
745 systemTypes[PrimitiveType.Boolean.GetSystemTypeIx()] = PrimitiveType.Boolean;
\r
746 systemTypes[PrimitiveType.Char.GetSystemTypeIx()] = PrimitiveType.Char;
\r
747 systemTypes[PrimitiveType.Int8.GetSystemTypeIx()] = PrimitiveType.Int8;
\r
748 systemTypes[PrimitiveType.UInt8.GetSystemTypeIx()] = PrimitiveType.UInt8;
\r
749 systemTypes[PrimitiveType.Int16.GetSystemTypeIx()] = PrimitiveType.Int16;
\r
750 systemTypes[PrimitiveType.UInt16.GetSystemTypeIx()] = PrimitiveType.UInt16;
\r
751 systemTypes[PrimitiveType.Int32.GetSystemTypeIx()] = PrimitiveType.Int32;
\r
752 systemTypes[PrimitiveType.UInt32.GetSystemTypeIx()] = PrimitiveType.UInt32;
\r
753 systemTypes[PrimitiveType.Int64.GetSystemTypeIx()] = PrimitiveType.Int64;
\r
754 systemTypes[PrimitiveType.UInt64.GetSystemTypeIx()] = PrimitiveType.UInt64;
\r
755 systemTypes[PrimitiveType.Float32.GetSystemTypeIx()] = PrimitiveType.Float32;
\r
756 systemTypes[PrimitiveType.Float64.GetSystemTypeIx()] = PrimitiveType.Float64;
\r
757 systemTypes[PrimitiveType.IntPtr.GetSystemTypeIx()] = PrimitiveType.IntPtr;
\r
758 systemTypes[PrimitiveType.UIntPtr.GetSystemTypeIx()] = PrimitiveType.UIntPtr;
\r
759 systemTypes[PrimitiveType.String.GetSystemTypeIx()] = PrimitiveType.String;
\r
760 systemTypes[PrimitiveType.Object.GetSystemTypeIx()] = PrimitiveType.Object;
\r
761 systemTypes[PrimitiveType.TypedRef.GetSystemTypeIx()] = PrimitiveType.TypedRef;
\r
765 /// Add a class to the mscorlib assembly
\r
767 /// <param name="nsName">name space name</param>
\r
768 /// <param name="name">class name</param>
\r
769 /// <returns></returns>
\r
770 public override ClassRef AddClass(string nsName, string name) {
\r
771 ClassRef aClass = GetSpecialClass(nsName,name);
\r
772 if (aClass == null) {
\r
773 aClass = new ClassRef(nsName,name,metaData);
\r
774 metaData.AddToTable(MDTable.TypeRef,aClass);
\r
775 aClass.SetParent(this);
\r
780 private ClassRef GetSpecialClass(string nsName,string name) {
\r
781 if (nsName.CompareTo(systemName) != 0) return null;
\r
782 int hash = name.GetHashCode();
\r
783 for (int i=0; i < specialNames.Length; i++) {
\r
784 if (hash == specialNames[i]) {
\r
785 if (systemClasses[i] == null) {
\r
786 if (i < valueTypeIx) {
\r
787 systemClasses[i] = new SystemClass(systemTypes[i],this,metaData);
\r
788 if ((systemTypes[i] != PrimitiveType.Object) &&
\r
789 (systemTypes[i] != PrimitiveType.String)) {
\r
790 systemClasses[i].MakeValueClass();
\r
793 systemClasses[i] = new ClassRef(nsName,name,metaData);
\r
794 systemClasses[i].SetParent(this);
\r
795 systemClasses[i].MakeValueClass();
\r
797 metaData.AddToTable(MDTable.TypeRef,systemClasses[i]);
\r
799 return systemClasses[i];
\r
805 internal ClassRef GetSpecialSystemClass(PrimitiveType pType) {
\r
806 int ix = pType.GetSystemTypeIx();
\r
807 if (systemClasses[ix] == null) {
\r
808 systemClasses[ix] = new SystemClass(pType,this,metaData);
\r
809 metaData.AddToTable(MDTable.TypeRef,systemClasses[ix]);
\r
811 return systemClasses[ix];
\r
814 private ClassRef GetValueClass(string name, int hash) {
\r
815 int ix = valueTypeIx;
\r
816 if (hash != specialNames[valueTypeIx]) ix++;
\r
817 if (systemClasses[ix] == null) {
\r
818 systemClasses[ix] = new ClassRef(systemName,name,metaData);
\r
819 systemClasses[ix].SetParent(this);
\r
820 systemClasses[ix].MakeValueClass();
\r
821 metaData.AddToTable(MDTable.TypeRef,systemClasses[ix]);
\r
823 return systemClasses[ix];
\r
826 internal ClassRef ValueType() {
\r
827 if (systemClasses[valueTypeIx] == null) {
\r
828 ClassRef valType = new ClassRef("System","ValueType",metaData);
\r
829 valType.SetParent(this);
\r
830 valType.MakeValueClass();
\r
831 metaData.AddToTable(MDTable.TypeRef,valType);
\r
832 systemClasses[valueTypeIx] = valType;
\r
834 return systemClasses[valueTypeIx];
\r
838 /// Add a value class to this external assembly
\r
840 /// <param name="nsName">name space name</param>
\r
841 /// <param name="name">class name</param>
\r
842 /// <returns></returns>
\r
843 public override ClassRef AddValueClass(string nsName, string name) {
\r
844 if (nsName.CompareTo(systemName) == 0) {
\r
845 int hash = name.GetHashCode();
\r
846 if ((hash == specialNames[valueTypeIx]) ||
\r
847 (hash == specialNames[valueTypeIx+1])) {
\r
848 return GetValueClass(name,hash);
\r
851 ClassRef aClass = new ClassRef(nsName,name,metaData);
\r
852 metaData.AddToTable(MDTable.TypeRef,aClass);
\r
853 aClass.SetParent(this);
\r
854 aClass.MakeValueClass();
\r
859 /**************************************************************************/
\r
861 /// Signature for calli instruction
\r
863 public class CalliSig : Signature
\r
865 private static readonly byte Sentinel = 0x41;
\r
868 Type[] parameters, optParams;
\r
869 uint numPars = 0, numOptPars = 0;
\r
872 /// Create a signature for a calli instruction
\r
874 /// <param name="cconv">calling conventions</param>
\r
875 /// <param name="retType">return type</param>
\r
876 /// <param name="pars">parameter types</param>
\r
877 public CalliSig(CallConv cconv, Type retType, Type[] pars) {
\r
878 tabIx = MDTable.StandAloneSig;
\r
880 returnType = retType;
\r
882 if (pars != null) numPars = (uint)pars.Length;
\r
886 /// Add the optional parameters to a vararg method
\r
887 /// This method sets the vararg calling convention
\r
889 /// <param name="optPars">the optional pars for the vararg call</param>
\r
890 public void AddVarArgs(Type[] optPars) {
\r
891 optParams = optPars;
\r
892 if (optPars != null) numOptPars = (uint)optPars.Length;
\r
893 callConv |= CallConv.Vararg;
\r
897 /// Add extra calling conventions to this callsite signature
\r
899 /// <param name="cconv"></param>
\r
900 public void AddCallingConv(CallConv cconv) {
\r
904 internal sealed override void BuildTables(MetaData md) {
\r
906 MemoryStream sig = new MemoryStream();
\r
907 sig.WriteByte((byte)callConv);
\r
908 MetaData.CompressNum(numPars+numOptPars,sig);
\r
909 returnType.TypeSig(sig);
\r
910 for (int i=0; i < numPars; i++) {
\r
911 parameters[i].TypeSig(sig);
\r
913 sigIx = md.AddToBlobHeap(sig.ToArray());
\r
914 if (numOptPars > 0) {
\r
915 sig.WriteByte(Sentinel);
\r
916 for (int i=0; i < numOptPars; i++) {
\r
917 optParams[i].TypeSig(sig);
\r
924 /**************************************************************************/
\r
926 /// The IL instructions for a method
\r
928 public class CILInstructions
\r
931 private static readonly uint ExHeaderSize = 4;
\r
932 private static readonly uint FatExClauseSize = 24;
\r
933 private static readonly uint SmlExClauseSize = 12;
\r
934 private static readonly sbyte maxByteVal = 127;
\r
935 private static readonly sbyte minByteVal = -128;
\r
936 private static readonly byte maxUByteVal = 255;
\r
937 private static readonly int smallSize = 64;
\r
938 private static readonly ushort TinyFormat = 0x2;
\r
939 private static readonly ushort FatFormat = 0x3003;
\r
940 private static readonly ushort MoreSects = 0x8;
\r
941 private static readonly ushort InitLocals = 0x10;
\r
942 private static readonly uint FatSize = 12;
\r
943 private static readonly uint FatWords = FatSize/4;
\r
944 private static readonly byte FatExceptTable = 0x41;
\r
945 private static readonly byte SmlExceptTable = 0x01;
\r
947 private MetaData metaData;
\r
948 private ArrayList exceptions, blockStack;
\r
949 //private bool codeChecked = false;
\r
950 private static readonly int INITSIZE = 5;
\r
951 private CILInstruction[] buffer = new CILInstruction[INITSIZE];
\r
952 private int tide = 0;
\r
953 private uint offset = 0;
\r
954 private ushort headerFlags = 0;
\r
955 private short maxStack;
\r
956 private uint paddingNeeded = 0;
\r
957 private byte exceptHeader = 0;
\r
958 uint localSigIx = 0;
\r
959 uint codeSize = 0, exceptSize = 0;
\r
960 bool tinyFormat, fatExceptionFormat = false;
\r
962 public uint Offset {
\r
963 get { return offset; }
\r
966 internal CILInstructions(MetaData md) {
\r
970 private void AddToBuffer(CILInstruction inst) {
\r
971 if (tide >= buffer.Length) {
\r
972 CILInstruction[] tmp = buffer;
\r
973 buffer = new CILInstruction[tmp.Length * 2];
\r
974 for (int i=0; i < tide; i++) {
\r
975 buffer[i] = tmp[i];
\r
978 //Console.WriteLine("Adding instruction at offset " + offset + " with size " + inst.size);
\r
979 inst.offset = offset;
\r
980 offset += inst.size;
\r
981 buffer[tide++] = inst;
\r
985 /// Add a simple IL instruction
\r
987 /// <param name="inst">the IL instruction</param>
\r
988 public void Inst(Op inst) {
\r
989 AddToBuffer(new Instr((int)inst));
\r
993 /// Add an IL instruction with an integer parameter
\r
995 /// <param name="inst">the IL instruction</param>
\r
996 /// <param name="val">the integer parameter value</param>
\r
997 public void IntInst(IntOp inst, int val) {
\r
998 int instr = (int)inst;
\r
999 if ((inst == IntOp.ldc_i4_s) || (inst == IntOp.ldc_i4))
\r
1000 AddToBuffer(new IntInstr(instr,val,(inst == IntOp.ldc_i4_s)));
\r
1002 AddToBuffer(new UIntInstr(instr,val,((inst < IntOp.ldc_i4_s) ||
\r
1003 (inst == IntOp.unaligned))));
\r
1007 /// Add the load long instruction
\r
1009 /// <param name="cVal">the long value</param>
\r
1010 public void ldc_i8(long cVal) {
\r
1011 AddToBuffer(new LongInstr(0x21,cVal));
\r
1015 /// Add the load float32 instruction
\r
1017 /// <param name="cVal">the float value</param>
\r
1018 public void ldc_r4(float cVal) {
\r
1019 AddToBuffer(new FloatInstr(0x22,cVal));
\r
1023 /// Add the load float64 instruction
\r
1025 /// <param name="cVal">the float value</param>
\r
1026 public void ldc_r8(double cVal) {
\r
1027 AddToBuffer(new DoubleInstr(0x23,cVal));
\r
1031 /// Add the load string instruction
\r
1033 /// <param name="str">the string value</param>
\r
1034 public void ldstr(string str) {
\r
1035 AddToBuffer(new StringInstr(0x72,str));
\r
1039 /// Add the load string instruction
1041 public void ldstr (byte[] str) {
1042 AddToBuffer (new StringInstr (0x72, str));
1046 /// Add the calli instruction
\r
1048 /// <param name="sig">the signature for the calli</param>
\r
1049 public void calli(CalliSig sig) {
\r
1050 AddToBuffer(new SigInstr(0x29,sig));
\r
1054 /// Add a label to the CIL instructions
\r
1056 /// <param name="lab">the label to be added</param>
\r
1057 public void CodeLabel(CILLabel lab) {
\r
1058 AddToBuffer(new LabelInstr(lab));
\r
1062 /// Add an instruction with a field parameter
\r
1064 /// <param name="inst">the CIL instruction</param>
\r
1065 /// <param name="f">the field parameter</param>
\r
1066 public void FieldInst(FieldOp inst, Field f) {
\r
1067 AddToBuffer(new FieldInstr((int)inst,f));
\r
1071 /// Add an instruction with a method parameter
\r
1073 /// <param name="inst">the CIL instruction</param>
\r
1074 /// <param name="m">the method parameter</param>
\r
1075 public void MethInst(MethodOp inst, Method m) {
\r
1076 AddToBuffer(new MethInstr((int)inst,m));
\r
1080 /// Add an instruction with a type parameter
\r
1082 /// <param name="inst">the CIL instruction</param>
\r
1083 /// <param name="t">the type argument for the CIL instruction</param>
\r
1084 public void TypeInst(TypeOp inst, Type aType) {
\r
1085 AddToBuffer(new TypeInstr((int)inst,aType,metaData));
\r
1089 /// Add a branch instruction
\r
1091 /// <param name="inst">the branch instruction</param>
\r
1092 /// <param name="lab">the label that is the target of the branch</param>
\r
1093 public void Branch(BranchOp inst, CILLabel lab) {
\r
1094 AddToBuffer(new BranchInstr((int)inst,lab));
\r
1098 /// Add a switch instruction
\r
1100 /// <param name="labs">the target labels for the switch</param>
\r
1101 public void Switch(CILLabel[] labs) {
\r
1102 AddToBuffer(new SwitchInstr(0x45,labs));
\r
1106 /// Add a byte to the CIL instructions (.emitbyte)
\r
1108 /// <param name="bVal"></param>
\r
1109 public void emitbyte(byte bVal) {
\r
1110 AddToBuffer(new CILByte(bVal));
\r
1114 /// Add an instruction which puts an integer on TOS. This method
\r
1115 /// selects the correct instruction based on the value of the integer.
\r
1117 /// <param name="i">the integer value</param>
\r
1118 public void PushInt(int i) {
\r
1120 AddToBuffer(new Instr((int)Op.ldc_i4_m1));
\r
1121 } else if ((i >= 0) && (i <= 8)) {
\r
1122 Op op = (Op)(Op.ldc_i4_0 + i);
\r
1123 AddToBuffer(new Instr((int)op));
\r
1124 } else if ((i >= minByteVal) && (i <= maxByteVal)) {
\r
1125 AddToBuffer(new IntInstr((int)IntOp.ldc_i4_s,i,true));
\r
1127 AddToBuffer(new IntInstr((int)IntOp.ldc_i4,i,false));
\r
1132 /// Add the instruction to load a long on TOS
\r
1134 /// <param name="l">the long value</param>
\r
1135 public void PushLong(long l) {
\r
1136 AddToBuffer(new LongInstr(0x21,l));
\r
1140 /// Add an instruction to push the boolean value true on TOS
\r
1142 public void PushTrue() {
\r
1143 AddToBuffer(new Instr((int)Op.ldc_i4_1));
\r
1147 /// Add an instruction to push the boolean value false on TOS
\r
1149 public void PushFalse() {
\r
1150 AddToBuffer(new Instr((int)Op.ldc_i4_0));
\r
1154 /// Add the instruction to load an argument on TOS. This method
\r
1155 /// selects the correct instruction based on the value of argNo
\r
1157 /// <param name="argNo">the number of the argument</param>
\r
1158 public void LoadArg(int argNo) {
\r
1160 int op = (int)Op.ldarg_0 + argNo;
\r
1161 AddToBuffer(new Instr(op));
\r
1162 } else if (argNo <= maxUByteVal) {
\r
1163 AddToBuffer(new UIntInstr((int)IntOp.ldarg,argNo,true));
\r
1165 AddToBuffer(new UIntInstr(0x09,argNo,false));
\r
1170 /// Add the instruction to load the address of an argument on TOS.
\r
1171 /// This method selects the correct instruction based on the value
\r
1174 /// <param name="argNo">the number of the argument</param>
\r
1175 public void LoadArgAdr(int argNo) {
\r
1176 if (argNo <= maxUByteVal) {
\r
1177 AddToBuffer(new UIntInstr((int)IntOp.ldarga,argNo,true));
\r
1179 AddToBuffer(new UIntInstr(0x0A,argNo,false));
\r
1184 /// Add the instruction to load a local on TOS. This method selects
\r
1185 /// the correct instruction based on the value of locNo.
\r
1187 /// <param name="locNo">the number of the local to load</param>
\r
1188 public void LoadLocal(int locNo) {
\r
1190 int op = (int)Op.ldloc_0 + locNo;
\r
1191 AddToBuffer(new Instr(op));
\r
1192 } else if (locNo <= maxUByteVal) {
\r
1193 AddToBuffer(new UIntInstr((int)IntOp.ldloc,locNo,true));
\r
1195 AddToBuffer(new UIntInstr(0x0C,locNo,false));
\r
1200 /// Add the instruction to load the address of a local on TOS.
\r
1201 /// This method selects the correct instruction based on the
\r
1202 /// value of locNo.
\r
1204 /// <param name="locNo">the number of the local</param>
\r
1205 public void LoadLocalAdr(int locNo) {
\r
1206 if (locNo <= maxUByteVal) {
\r
1207 AddToBuffer(new UIntInstr((int)IntOp.ldloca,locNo,true));
\r
1209 AddToBuffer(new UIntInstr(0x0D,locNo,false));
\r
1214 /// Add the instruction to store to an argument. This method
\r
1215 /// selects the correct instruction based on the value of argNo.
\r
1217 /// <param name="argNo">the argument to be stored to</param>
\r
1218 public void StoreArg(int argNo) {
\r
1219 if (argNo <= maxUByteVal) {
\r
1220 AddToBuffer(new UIntInstr((int)IntOp.starg,argNo,true));
\r
1222 AddToBuffer(new UIntInstr(0x0B,argNo,false));
\r
1227 /// Add the instruction to store to a local. This method selects
\r
1228 /// the correct instruction based on the value of locNo.
\r
1230 /// <param name="locNo">the local to be stored to</param>
\r
1231 public void StoreLocal(int locNo) {
\r
1233 int op = (int)Op.stloc_0 + locNo;
\r
1234 AddToBuffer(new Instr(op));
\r
1235 } else if (locNo <= maxUByteVal) {
\r
1236 AddToBuffer(new UIntInstr((int)IntOp.stloc,locNo,true));
\r
1238 AddToBuffer(new UIntInstr(0x0E,locNo,false));
\r
1243 /// Create a new CIL label. To place the label in the CIL instruction
\r
1244 /// stream use CodeLabel.
\r
1246 /// <returns>a new CIL label</returns>
\r
1247 public CILLabel NewLabel() {
\r
1248 return new CILLabel();
\r
1251 public void AddTryBlock(TryBlock tryBlock) {
\r
1252 if (exceptions == null)
\r
1253 exceptions = new ArrayList();
\r
1254 else if (exceptions.Contains(tryBlock)) return;
\r
1255 exceptions.Add(tryBlock);
\r
1259 /// Create a new label at this position in the code buffer
\r
1261 /// <returns>the label at the current position</returns>
\r
1262 public CILLabel NewCodedLabel() {
\r
1263 CILLabel lab = new CILLabel();
\r
1264 AddToBuffer(new LabelInstr(lab));
\r
1269 /// Mark this position as the start of a new block
\r
1270 /// (try, catch, filter, finally or fault)
\r
1272 public void StartBlock() {
\r
1273 if (blockStack == null) blockStack = new ArrayList();
\r
1274 blockStack.Insert(0,NewCodedLabel());
\r
1278 /// Mark this position as the end of the last started block and
\r
1279 /// make it a try block. This try block is added to the current
\r
1280 /// instructions (ie do not need to call AddTryBlock)
\r
1282 /// <returns>The try block just ended</returns>
\r
1283 public TryBlock EndTryBlock() {
\r
1284 TryBlock tBlock = new TryBlock((CILLabel)blockStack[0],NewCodedLabel());
\r
1285 blockStack.RemoveAt(0);
\r
1286 AddTryBlock(tBlock);
\r
1291 /// Mark this position as the end of the last started block and
\r
1292 /// make it a catch block. This catch block is associated with the
\r
1293 /// specified try block.
\r
1295 /// <param name="exceptType">the exception type to be caught</param>
\r
1296 /// <param name="tryBlock">the try block associated with this catch block</param>
\r
1297 public void EndCatchBlock(Class exceptType, TryBlock tryBlock) {
\r
1298 Catch catchBlock = new Catch(exceptType,(CILLabel)blockStack[0],
\r
1300 tryBlock.AddHandler(catchBlock);
\r
1304 /// Mark this position as the end of the last started block and
\r
1305 /// make it a filter block. This filter block is associated with the
\r
1306 /// specified try block.
\r
1308 /// <param name="filterLab">the label where the filter code is</param>
\r
1309 /// <param name="tryBlock">the try block associated with this filter block</param>
\r
1310 public void EndFilterBlock(CILLabel filterLab, TryBlock tryBlock) {
\r
1311 Filter filBlock = new Filter(filterLab,(CILLabel)blockStack[0],NewCodedLabel());
\r
1312 tryBlock.AddHandler(filBlock);
\r
1316 /// Mark this position as the end of the last started block and
\r
1317 /// make it a finally block. This finally block is associated with the
\r
1318 /// specified try block.
\r
1320 /// <param name="tryBlock">the try block associated with this finally block</param>
\r
1321 public void EndFinallyBlock(TryBlock tryBlock) {
\r
1322 Finally finBlock= new Finally((CILLabel)blockStack[0],NewCodedLabel());
\r
1323 tryBlock.AddHandler(finBlock);
\r
1327 /// Mark this position as the end of the last started block and
\r
1328 /// make it a fault block. This fault block is associated with the
\r
1329 /// specified try block.
\r
1331 /// <param name="tryBlock">the try block associated with this fault block</param>
\r
1332 public void EndFaultBlock(TryBlock tryBlock) {
\r
1333 Fault fBlock= new Fault((CILLabel)blockStack[0],NewCodedLabel());
\r
1334 tryBlock.AddHandler(fBlock);
\r
1337 internal uint GetCodeSize() {
\r
1338 return codeSize + paddingNeeded + exceptSize;
\r
1341 internal void CheckCode(uint locSigIx, bool initLocals, int maxStack) {
\r
1342 if (tide == 0) return;
\r
1343 bool changed = true;
\r
1346 for (int i=0; i < tide; i++) {
\r
1347 changed = buffer[i].Check(metaData) || changed;
\r
1350 for (int i=1; i < tide; i++) {
\r
1351 buffer[i].offset = buffer[i-1].offset + buffer[i-1].size;
\r
1353 offset = buffer[tide-1].offset + buffer[tide-1].size;
\r
1356 codeSize = offset;
\r
1357 // Console.WriteLine("codeSize before header added = " + codeSize);
\r
1358 if ((offset < smallSize) && (maxStack <= 8) && (locSigIx == 0) && (exceptions == null)) {
\r
1359 // can use tiny header
\r
1360 //Console.WriteLine("Tiny Header");
\r
1361 tinyFormat = true;
\r
1362 headerFlags = (ushort)(TinyFormat | ((ushort)codeSize << 2));
\r
1364 if ((codeSize % 4) != 0) { paddingNeeded = 4 - (codeSize % 4); }
\r
1366 //Console.WriteLine("Fat Header");
\r
1367 tinyFormat = false;
\r
1368 localSigIx = locSigIx;
\r
1369 this.maxStack = (short)maxStack;
\r
1370 headerFlags = FatFormat;
\r
1371 if (exceptions != null) {
\r
1372 // Console.WriteLine("Got exceptions");
\r
1373 headerFlags |= MoreSects;
\r
1374 uint numExceptClauses = 0;
\r
1375 for (int i=0; i < exceptions.Count; i++) {
\r
1376 TryBlock tryBlock = (TryBlock)exceptions[i];
\r
1377 tryBlock.SetSize();
\r
1378 numExceptClauses += (uint)tryBlock.NumHandlers();
\r
1379 if (tryBlock.isFat()) fatExceptionFormat = true;
\r
1382 uint data_size = ExHeaderSize + numExceptClauses *
1383 (fatExceptionFormat ? FatExClauseSize : SmlExClauseSize);
1385 if (data_size > 256)
1386 fatExceptionFormat = true;
1388 // Console.WriteLine("numexceptclauses = " + numExceptClauses);
\r
1389 if (fatExceptionFormat) {
\r
1390 // Console.WriteLine("Fat exception format");
\r
1391 exceptHeader = FatExceptTable;
\r
1392 exceptSize = ExHeaderSize + numExceptClauses * FatExClauseSize;
\r
1394 // Console.WriteLine("Tiny exception format");
\r
1395 exceptHeader = SmlExceptTable;
\r
1396 exceptSize = ExHeaderSize + numExceptClauses * SmlExClauseSize;
\r
1398 // Console.WriteLine("exceptSize = " + exceptSize);
\r
1400 if (initLocals) headerFlags |= InitLocals;
\r
1401 if ((offset % 4) != 0) { paddingNeeded = 4 - (offset % 4); }
\r
1402 codeSize += FatSize;
\r
1404 // Console.WriteLine("codeSize = " + codeSize + " headerFlags = " +
\r
1405 // Hex.Short(headerFlags));
\r
1408 internal void Write(FileImage output) {
\r
1409 // Console.WriteLine("Writing header flags = " + Hex.Short(headerFlags));
\r
1411 // Console.WriteLine("Writing tiny code");
\r
1412 output.Write((byte)headerFlags);
\r
1414 // Console.WriteLine("Writing fat code");
\r
1415 output.Write(headerFlags);
\r
1416 output.Write((ushort)maxStack);
\r
1417 output.Write(offset);
\r
1418 output.Write(localSigIx);
\r
1420 // Console.WriteLine(Hex.Int(tide) + " CIL instructions");
\r
1421 // Console.WriteLine("starting instructions at " + output.Seek(0,SeekOrigin.Current));
\r
1422 for (int i=0; i < tide; i++) {
\r
1423 buffer[i].Write(output);
\r
1425 // Console.WriteLine("ending instructions at " + output.Seek(0,SeekOrigin.Current));
\r
1426 for (int i=0; i < paddingNeeded; i++) { output.Write((byte)0); }
\r
1427 if (exceptions != null) {
\r
1428 // Console.WriteLine("Writing exceptions");
\r
1429 // Console.WriteLine("header = " + Hex.Short(exceptHeader) + " exceptSize = " + Hex.Int(exceptSize));
\r
1430 output.Write(exceptHeader);
\r
1431 output.Write3Bytes((uint)exceptSize);
\r
1432 for (int i=0; i < exceptions.Count; i++) {
\r
1433 TryBlock tryBlock = (TryBlock)exceptions[i];
\r
1434 tryBlock.Write(output,fatExceptionFormat);
\r
1440 /**************************************************************************/
\r
1442 /// A label in the IL
\r
1444 public class CILLabel
\r
1446 CILInstruction branch;
\r
1447 CILInstruction[] multipleBranches;
\r
1449 CILInstruction labInstr;
\r
1452 public CILLabel (uint offset) {
\r
1453 this.offset = offset;
\r
1457 internal CILLabel() {
\r
1460 internal void AddBranch(CILInstruction instr) {
\r
1461 if (branch == null) {
\r
1465 if (multipleBranches == null) {
\r
1466 multipleBranches = new CILInstruction[2];
\r
1467 } else if (tide >= multipleBranches.Length) {
\r
1468 CILInstruction[] tmp = multipleBranches;
\r
1469 multipleBranches = new CILInstruction[tmp.Length*2];
\r
1470 for (int i=0; i < tide; i++) {
\r
1471 multipleBranches[i] = tmp[i];
\r
1474 multipleBranches[tide++] = instr;
\r
1477 internal void AddLabelInstr(LabelInstr lInstr) {
\r
1478 labInstr = lInstr;
\r
1481 internal uint GetLabelOffset() {
\r
1482 if (labInstr == null) return 0;
\r
1483 return labInstr.offset + offset;
\r
1487 /**************************************************************************/
\r
1488 public abstract class CodeBlock {
\r
1490 private static readonly int maxCodeSize = 256;
\r
1491 protected CILLabel start, end;
\r
1492 protected bool small = true;
\r
1494 public CodeBlock(CILLabel start, CILLabel end) {
\r
1495 this.start = start;
\r
1499 internal virtual bool isFat() {
\r
1500 // Console.WriteLine("block start = " + start.GetLabelOffset() +
\r
1501 // " block end = " + end.GetLabelOffset());
\r
1502 return (end.GetLabelOffset() - start.GetLabelOffset()) > maxCodeSize;
\r
1505 internal virtual void Write(FileImage output, bool fatFormat) {
\r
1506 if (fatFormat) output.Write(start.GetLabelOffset());
\r
1507 else output.Write((short)start.GetLabelOffset());
\r
1508 uint len = end.GetLabelOffset() - start.GetLabelOffset();
\r
1509 if (fatFormat) output.Write(len);
\r
1510 else output.Write((byte)len);
\r
1516 /// The descriptor for a guarded block (.try)
\r
1518 public class TryBlock : CodeBlock {
\r
1519 protected bool fatFormat = false;
\r
1520 protected int flags = 0;
\r
1521 ArrayList handlers = new ArrayList();
\r
1524 /// Create a new try block
\r
1526 /// <param name="start">start label for the try block</param>
\r
1527 /// <param name="end">end label for the try block</param>
\r
1528 public TryBlock(CILLabel start, CILLabel end) : base(start,end) { }
\r
1531 /// Add a handler to this try block
\r
1533 /// <param name="handler">a handler to be added to the try block</param>
\r
1534 public void AddHandler(HandlerBlock handler) {
\r
1535 flags = handler.GetFlag();
\r
1536 handlers.Add(handler);
\r
1539 internal void SetSize() {
\r
1540 fatFormat = base.isFat();
\r
1541 if (fatFormat) return;
\r
1542 for (int i=0; i < handlers.Count; i++) {
\r
1543 HandlerBlock handler = (HandlerBlock)handlers[i];
\r
1544 if (handler.isFat()) {
\r
1551 internal int NumHandlers() {
\r
1552 return handlers.Count;
\r
1555 internal override bool isFat() {
\r
1559 internal override void Write(FileImage output, bool fatFormat) {
\r
1560 // Console.WriteLine("writing exception details");
\r
1561 for (int i=0; i < handlers.Count; i++) {
\r
1562 // Console.WriteLine("Except block " + i);
\r
1563 HandlerBlock handler = (HandlerBlock)handlers[i];
\r
1564 if (fatFormat) output.Write(flags);
\r
1565 else output.Write((short)flags);
\r
1566 // Console.WriteLine("flags = " + Hex.Short(flags));
\r
1567 base.Write(output,fatFormat);
\r
1568 handler.Write(output,fatFormat);
\r
1573 public abstract class HandlerBlock : CodeBlock
\r
1575 protected static readonly short ExceptionFlag = 0;
\r
1576 protected static readonly short FilterFlag = 0x01;
\r
1577 protected static readonly short FinallyFlag = 0x02;
\r
1578 protected static readonly short FaultFlag = 0x04;
\r
1580 public HandlerBlock(CILLabel start, CILLabel end) : base(start,end) { }
\r
1582 internal virtual short GetFlag() { return ExceptionFlag; }
\r
1584 internal override void Write(FileImage output, bool fatFormat) {
\r
1585 base.Write(output,fatFormat);
\r
1591 /// The descriptor for a catch clause (.catch)
\r
1593 public class Catch : HandlerBlock
\r
1598 /// Create a new catch clause
\r
1600 /// <param name="except">the exception to be caught</param>
\r
1601 /// <param name="handlerStart">start of the handler code</param>
\r
1602 /// <param name="handlerEnd">end of the handler code</param>
\r
1603 public Catch(Class except, CILLabel handlerStart, CILLabel handlerEnd)
\r
1604 : base(handlerStart,handlerEnd) {
\r
1605 exceptType = except;
\r
1608 internal override void Write(FileImage output, bool fatFormat) {
\r
1609 base.Write(output,fatFormat);
\r
1610 output.Write(exceptType.Token());
\r
1615 /// The descriptor for a filter clause (.filter)
\r
1617 public class Filter : HandlerBlock
\r
1619 CILLabel filterLabel;
\r
1622 /// Create a new filter clause
\r
1624 /// <param name="filterLabel">the label where the filter code starts</param>
\r
1625 /// <param name="handlerStart">the start of the handler code</param>
\r
1626 /// <param name="handlerEnd">the end of the handler code</param>
\r
1627 public Filter(CILLabel filterLabel, CILLabel handlerStart,
\r
1628 CILLabel handlerEnd) : base(handlerStart,handlerEnd) {
\r
1629 this.filterLabel = filterLabel;
\r
1632 internal override short GetFlag() {
\r
1633 return FilterFlag;
\r
1636 internal override void Write(FileImage output, bool fatFormat) {
\r
1637 base.Write(output,fatFormat);
\r
1638 output.Write(filterLabel.GetLabelOffset());
\r
1644 /// Descriptor for a finally block (.finally)
\r
1646 public class Finally : HandlerBlock
\r
1649 /// Create a new finally clause
\r
1651 /// <param name="finallyStart">start of finally code</param>
\r
1652 /// <param name="finallyEnd">end of finally code</param>
\r
1653 public Finally(CILLabel finallyStart, CILLabel finallyEnd)
\r
1654 : base(finallyStart,finallyEnd) { }
\r
1656 internal override short GetFlag() {
\r
1657 return FinallyFlag;
\r
1660 internal override void Write(FileImage output, bool fatFormat) {
\r
1661 base.Write(output,fatFormat);
\r
1662 output.Write((int)0);
\r
1668 /// Descriptor for a fault block (.fault)
\r
1670 public class Fault : HandlerBlock
\r
1673 /// Create a new fault clause
\r
1675 /// <param name="faultStart">start of the fault code</param>
\r
1676 /// <param name="faultEnd">end of the fault code</param>
\r
1677 public Fault(CILLabel faultStart, CILLabel faultEnd)
\r
1678 : base(faultStart,faultEnd) { }
\r
1680 internal override short GetFlag() {
\r
1681 return FaultFlag;
\r
1684 internal override void Write(FileImage output, bool fatFormat) {
\r
1685 base.Write(output,fatFormat);
\r
1686 output.Write((int)0);
\r
1691 /**************************************************************************/
\r
1693 /// The base descriptor for a class
\r
1695 public abstract class Class : Type
\r
1697 protected int row = 0;
\r
1698 protected string name, nameSpace;
\r
1699 protected uint nameIx, nameSpaceIx;
\r
1700 protected MetaData _metaData;
\r
1701 internal Class(string nameSpaceName, string className, MetaData md)
\r
1703 nameSpace = nameSpaceName;
\r
1705 nameIx = md.AddToStringsHeap(name);
\r
1706 nameSpaceIx = md.AddToStringsHeap(nameSpace);
\r
1710 internal Class(uint nsIx, uint nIx) : base(0x12) {
\r
1711 nameSpaceIx = nsIx;
\r
1715 internal virtual uint TypeDefOrRefToken() { return 0; }
\r
1717 internal virtual void MakeValueClass() {
\r
1721 internal virtual string TypeName() {
\r
1722 return (nameSpace + "." + name);
\r
1725 internal override MetaDataElement GetTypeSpec(MetaData md) {
\r
1729 /**************************************************************************/
\r
1730 // This Class produces entries in the TypeDef table of the MetaData
\r
1731 // in the PE meta data.
\r
1733 // NOTE: Entry 0 in TypeDef table is always the pseudo class <module>
\r
1734 // which is the parent for functions and variables declared a module level
\r
1737 /// The descriptor for a class defined in the IL (.class) in the current assembly/module
\r
1740 public class ClassDef : Class
\r
1742 private static readonly uint HasSecurity = 0x00040000;
\r
1743 private static readonly byte ElementType_Class = 0x12;
\r
1746 ArrayList fields = new ArrayList();
\r
1747 ArrayList methods = new ArrayList();
\r
1749 ArrayList properties;
\r
1750 bool typeIndexChecked = true;
\r
1751 uint fieldIx = 0, methodIx = 0;
\r
1752 byte[] securityActions;
\r
1754 ClassLayout layout;
\r
1755 ClassDef parentClass;
\r
1756 MetaData metaData;
\r
1758 internal ClassDef(TypeAttr attrSet, string nsName, string name,
\r
1759 MetaData md) : base(nsName, name, md) {
\r
1761 superType = metaData.mscorlib.GetSpecialSystemClass(PrimitiveType.Object);
\r
1762 flags = (uint)attrSet;
\r
1763 tabIx = MDTable.TypeDef;
\r
1766 internal void SetSuper(Class sClass) {
\r
1767 superType = sClass;
\r
1768 if (sClass is ClassRef)
\r
1769 typeIndex = superType.GetTypeIndex();
\r
1771 typeIndexChecked = false;
\r
1774 internal override void MakeValueClass() {
\r
1775 superType = metaData.mscorlib.ValueType();
\r
1776 typeIndex = superType.GetTypeIndex();
\r
1779 public void SpecialNoSuper() {
\r
1784 /// Add an attribute to this class
\r
1786 /// <param name="ta">the attribute to be added</param>
\r
1787 public void AddAttribute(TypeAttr ta) {
\r
1788 flags |= (uint)ta;
\r
1792 /// Add an interface that is implemented by this class
\r
1794 /// <param name="iFace">the interface that is implemented</param>
\r
1795 public void AddImplementedInterface(Class iFace) {
\r
1796 metaData.AddToTable(MDTable.InterfaceImpl,new InterfaceImpl(this,iFace));
\r
1800 /// Add a named generic type parameter
\r
1802 public GenericParameter AddGenericParameter (short index, string name) {
\r
1803 GenericParameter gp = new GenericParameter (this, metaData, index, name);
1804 metaData.AddToTable (MDTable.GenericParam, gp);
\r
1809 /// Add a field to this class
\r
1811 /// <param name="name">field name</param>
\r
1812 /// <param name="fType">field type</param>
\r
1813 /// <returns>a descriptor for this new field</returns>
\r
1814 public FieldDef AddField(string name, Type fType) {
\r
1815 FieldDef field = new FieldDef(name,fType);
\r
1816 fields.Add(field);
\r
1821 /// Add a field to this class
\r
1823 /// <param name="fAtts">attributes for this field</param>
\r
1824 /// <param name="name">field name</param>
\r
1825 /// <param name="fType">field type</param>
\r
1826 /// <returns>a descriptor for this new field</returns>
\r
1827 public FieldDef AddField(FieldAttr fAtts, string name, Type fType) {
\r
1828 FieldDef field = new FieldDef(fAtts,name,fType);
\r
1829 fields.Add(field);
\r
1833 public void SetFieldOrder (ArrayList fields)
1835 this.fields = fields;
1839 /// Add a method to this class
\r
1841 /// <param name="name">method name</param>
\r
1842 /// <param name="retType">return type</param>
\r
1843 /// <param name="pars">parameters</param>
\r
1844 /// <returns>a descriptor for this new method</returns>
\r
1845 public MethodDef AddMethod(string name, Type retType, Param[] pars) {
\r
1846 // Console.WriteLine("Adding method " + name + " to class " + this.name);
\r
1847 MethodDef meth = new MethodDef(metaData,name,retType, pars);
\r
1848 methods.Add(meth);
\r
1853 /// Add a method to this class
\r
1855 /// <param name="mAtts">attributes for this method</param>
\r
1856 /// <param name="iAtts">implementation attributes for this method</param>
\r
1857 /// <param name="name">method name</param>
\r
1858 /// <param name="retType">return type</param>
\r
1859 /// <param name="pars">parameters</param>
\r
1860 /// <returns>a descriptor for this new method</returns>
\r
1861 public MethodDef AddMethod(MethAttr mAtts, ImplAttr iAtts, string name,
\r
1862 Type retType, Param[] pars) {
\r
1863 // Console.WriteLine("Adding method " + name + " to class " + this.name);
\r
1864 MethodDef meth = new MethodDef(metaData,mAtts,iAtts,name,retType,pars);
\r
1865 methods.Add(meth);
\r
1870 /// Add an event to this class
\r
1872 /// <param name="name">event name</param>
\r
1873 /// <param name="eType">event type</param>
\r
1874 /// <returns>a descriptor for this new event</returns>
\r
1875 public Event AddEvent(string name, Type eType) {
\r
1876 Event e = new Event(name,eType,this);
\r
1877 if (events == null) events = new ArrayList();
\r
1883 /// Add a property to this class
\r
1885 /// <param name="name">property name</param>
\r
1886 /// <param name="propType">property type</param>
\r
1887 /// <returns>a descriptor for this new property</returns>
\r
1888 public Property AddProperty(string name, Type retType, Type[] pars) {
\r
1889 Property p = new Property(name, retType, pars, this);
\r
1890 if (properties == null) properties = new ArrayList();
\r
1891 properties.Add(p);
\r
1897 /// Add a nested class to this class
\r
1899 /// <param name="attrSet">attributes for this nested class</param>
\r
1900 /// <param name="nsName">nested name space name</param>
\r
1901 /// <param name="name">nested class name</param>
\r
1902 /// <returns>a descriptor for this new nested class</returns>
\r
1903 public ClassDef AddNestedClass(TypeAttr attrSet, string nsName,
\r
1905 ClassDef nClass = new ClassDef(attrSet,nsName,name,metaData);
\r
1906 metaData.AddToTable(MDTable.TypeDef,nClass);
\r
1907 metaData.AddToTable(MDTable.NestedClass,new MapElem(nClass,Row,MDTable.TypeDef));
\r
1908 nClass.parentClass = this;
\r
1913 /// Add a nested class to this class
\r
1915 /// <param name="attrSet">attributes for this nested class</param>
\r
1916 /// <param name="nsName">nested name space name</param>
\r
1917 /// <param name="name">nested class name</param>
\r
1918 /// <param name="sType">super type of this nested class</param>
\r
1919 /// <returns>a descriptor for this new nested class</returns>
\r
1920 public ClassDef AddNestedClass(TypeAttr attrSet, string nsName,
\r
1921 string name, Class sType) {
\r
1922 ClassDef nClass = new ClassDef(attrSet,nsName,name,metaData);
\r
1923 nClass.SetSuper(sType);
\r
1924 metaData.AddToTable(MDTable.TypeDef,nClass);
\r
1925 metaData.AddToTable(MDTable.NestedClass,
\r
1926 new MapElem(nClass,Row,MDTable.TypeDef));
\r
1927 nClass.parentClass = this;
\r
1932 /// Add layout information for this class. This class must have the
\r
1933 /// sequential or explicit attribute.
\r
1935 /// <param name="packSize">packing size (.pack)</param>
\r
1936 /// <param name="classSize">class size (.size)</param>
\r
1937 public void AddLayoutInfo (int packSize, int classSize) {
\r
1938 layout = new ClassLayout(packSize,classSize,this);
\r
1942 /// Use a method as the implementation for another method (.override)
\r
1944 /// <param name="decl">the method to be overridden</param>
\r
1945 /// <param name="body">the implementation to be used</param>
\r
1946 public void AddMethodOverride(Method decl, Method body) {
\r
1947 metaData.AddToTable(MDTable.MethodImpl,new MethodImpl(this,decl,body));
\r
1951 /// Add security to this class NOT YET IMPLEMENTED
\r
1953 /// <param name="permissionSet"></param>
\r
1954 public void AddSecurity(byte[] permissionSet) {
\r
1955 throw(new NotYetImplementedException("Class security "));
\r
1956 //flags |= HasSecurity;
\r
1957 // securityActions = permissionSet;
\r
1960 //public void AddLineInfo(int row, int col) { }
\r
1962 internal void CheckTypeIndex() {
\r
1963 if (typeIndexChecked) return;
\r
1964 if (!(superType is ClassRef))
\r
1965 ((ClassDef)superType).CheckTypeIndex();
\r
1966 typeIndex = superType.GetTypeIndex();
\r
1967 typeIndexChecked = true;
\r
1970 internal sealed override void BuildTables(MetaData md) {
\r
1972 if ((flags & (uint)TypeAttr.Interface) != 0) { superType = null; }
\r
1973 // Console.WriteLine("Building tables for " + name);
\r
1974 if (layout != null) md.AddToTable(MDTable.ClassLayout,layout);
\r
1975 // Console.WriteLine("adding methods " + methods.Count);
\r
1976 methodIx = md.TableIndex(MDTable.Method);
\r
1977 for (int i=0; i < methods.Count; i++) {
\r
1978 md.AddToTable(MDTable.Method,(MetaDataElement)methods[i]);
\r
1979 ((MethodDef)methods[i]).BuildTables(md);
\r
1981 // Console.WriteLine("adding fields");
\r
1982 fieldIx = md.TableIndex(MDTable.Field);
\r
1983 for (int i=0; i < fields.Count; i++) {
\r
1984 md.AddToTable(MDTable.Field,(MetaDataElement)fields[i]);
\r
1985 ((FieldDef)fields[i]).BuildTables(md);
\r
1987 // Console.WriteLine("adding events and properties");
\r
1988 if (events != null) {
\r
1989 for (int i=0; i < events.Count; i++) {
\r
1990 md.AddToTable(MDTable.Event,(Event)events[i]);
\r
1991 ((Event)events[i]).BuildTables(md);
\r
1993 md.AddToTable(MDTable.EventMap,
\r
1994 new MapElem(this,((Event)events[0]).Row,MDTable.Event));
\r
1996 if (properties != null) {
\r
1997 for (int i=0; i < properties.Count; i++) {
\r
1998 md.AddToTable(MDTable.Property,(Property)properties[i]);
\r
1999 ((Property)properties[i]).BuildTables(md);
\r
2001 md.AddToTable(MDTable.PropertyMap,new MapElem(this,
\r
2002 ((Property)properties[0]).Row,MDTable.Property));
\r
2004 // Console.WriteLine("End of building tables");
\r
2008 internal sealed override uint Size(MetaData md) {
\r
2009 return 4 + 2 * md.StringsIndexSize() +
\r
2010 md.CodedIndexSize(CIx.TypeDefOrRef) +
\r
2011 md.TableIndexSize(MDTable.Field) +
\r
2012 md.TableIndexSize(MDTable.Method);
\r
2015 internal sealed override void Write(FileImage output) {
\r
2016 output.Write(flags);
\r
2017 output.StringsIndex(nameIx);
\r
2018 output.StringsIndex(nameSpaceIx);
\r
2019 //if (superType != null)
\r
2020 // Console.WriteLine("getting coded index for superType of " + name + " = " + superType.GetCodedIx(CIx.TypeDefOrRef));
\r
2021 output.WriteCodedIndex(CIx.TypeDefOrRef,superType);
\r
2022 output.WriteIndex(MDTable.Field,fieldIx);
\r
2023 output.WriteIndex(MDTable.Method,methodIx);
\r
2026 internal sealed override uint TypeDefOrRefToken() {
\r
2032 internal sealed override void TypeSig(MemoryStream sig) {
\r
2033 if (!typeIndexChecked) CheckTypeIndex();
\r
2034 sig.WriteByte(GetTypeIndex());
\r
2035 MetaData.CompressNum(TypeDefOrRefToken(),sig);
\r
2038 internal sealed override uint GetCodedIx(CIx code) {
\r
2040 case (CIx.TypeDefOrRef) : return 0;
\r
2041 case (CIx.HasCustomAttr) : return 3;
\r
2042 case (CIx.HasDeclSecurity) : return 0;
\r
2043 case (CIx.TypeOrMethodDef) : return 0;
\r
2049 /**************************************************************************/
\r
2051 /// Layout information for a class (.class [sequential | explicit])
\r
2053 internal class ClassLayout : MetaDataElement
\r
2056 ushort packSize = 0;
\r
2057 uint classSize = 0;
\r
2059 internal ClassLayout(int pack, int cSize, ClassDef par) {
\r
2060 packSize = (ushort)pack;
\r
2061 classSize = (uint)cSize;
\r
2063 tabIx = MDTable.ClassLayout;
\r
2066 internal sealed override uint Size(MetaData md) {
\r
2067 return 6 + md.TableIndexSize(MDTable.TypeDef);
\r
2070 internal sealed override void Write(FileImage output) {
\r
2071 output.Write(packSize);
\r
2072 output.Write(classSize);
\r
2073 output.WriteIndex(MDTable.TypeDef,parent.Row);
\r
2077 /**************************************************************************/
\r
2079 /// Descriptor for a class/interface declared in another module of THIS
\r
2080 /// assembly, or in another assembly.
\r
2082 public class ClassRef : Class
\r
2084 protected ResolutionScope parent;
\r
2085 ExternClass externClass;
\r
2086 protected MetaData metaData;
\r
2088 internal ClassRef(string nsName, string name, MetaData md) : base(nsName, name, md) {
\r
2090 tabIx = MDTable.TypeRef;
\r
2094 /// Add a method to this class
\r
2096 /// <param name="name">method name</param>
\r
2097 /// <param name="retType">return type</param>
\r
2098 /// <param name="pars">parameter types</param>
\r
2099 /// <returns>a descriptor for this method</returns>
\r
2100 public MethodRef AddMethod(string name, Type retType, Type[] pars) {
\r
2101 MethodRef meth = new MethodRef(this,name,retType,pars,false,null);
\r
2102 metaData.AddToTable(MDTable.MemberRef,meth);
\r
2107 /// Add a method to this class
\r
2109 /// <param name="name">method name</param>
\r
2110 /// <param name="retType">return type</param>
\r
2111 /// <param name="pars">parameter types</param>
\r
2112 /// <returns>a descriptor for this method</returns>
\r
2113 public MethodRef AddVarArgMethod(string name, Type retType,
\r
2114 Type[] pars, Type[] optPars) {
\r
2115 MethodRef meth = new MethodRef(this,name,retType,pars,true,optPars);
\r
2116 metaData.AddToTable(MDTable.MemberRef,meth);
\r
2121 /// Add a field to this class
\r
2123 /// <param name="name">field name</param>
\r
2124 /// <param name="fType">field type</param>
\r
2125 /// <returns>a descriptor for this field</returns>
\r
2126 public FieldRef AddField(string name, Type fType) {
\r
2127 FieldRef field = new FieldRef(this,name,fType);
\r
2128 metaData.AddToTable(MDTable.MemberRef,field);
\r
2132 internal void SetParent(ResolutionScope par) {
\r
2136 internal override string TypeName() {
\r
2137 if ((parent != null) && (parent is AssemblyRef))
\r
2138 return (nameSpace + "." + name + ", " + ((AssemblyRef)parent).TypeName());
\r
2140 return (nameSpace + name);
\r
2143 internal sealed override uint Size(MetaData md) {
\r
2144 return md.CodedIndexSize(CIx.ResolutionScope) + 2 *
\r
2145 md.StringsIndexSize();
\r
2148 internal sealed override void Write(FileImage output) {
\r
2149 output.WriteCodedIndex(CIx.ResolutionScope,parent);
\r
2150 output.StringsIndex(nameIx);
\r
2151 output.StringsIndex(nameSpaceIx);
\r
2154 internal override sealed uint TypeDefOrRefToken() {
\r
2156 cIx = (cIx << 2) | 0x1;
\r
2160 internal override void TypeSig(MemoryStream sig) {
\r
2161 sig.WriteByte(GetTypeIndex());
\r
2162 MetaData.CompressNum(TypeDefOrRefToken(),sig);
\r
2165 internal sealed override uint GetCodedIx(CIx code) {
\r
2167 case (CIx.TypeDefOrRef) : return 1;
\r
2168 case (CIx.HasCustomAttr) : return 2;
\r
2169 case (CIx.MemberRefParent) : return 1;
\r
2170 case (CIx.ResolutionScope) : return 3;
\r
2176 /**************************************************************************/
\r
2178 public class ExternClassRef : ClassRef {
\r
2180 ExternClass externClass;
\r
2182 internal ExternClassRef(TypeAttr attrs, string nsName, string name,
\r
2183 FileRef declFile, MetaData md) : base(nsName,name,md) {
\r
2184 externClass = new ExternClass(attrs,nameSpaceIx,nameIx,declFile);
\r
2185 metaData.AddToTable(MDTable.ExportedType,externClass);
\r
2188 internal ExternClassRef(string name, MetaData md) : base(null,name,md) {
\r
2191 public ClassRef AddNestedClass(TypeAttr attrs, string name) {
\r
2192 ExternClassRef nestedClass = new ExternClassRef(name,metaData);
\r
2193 externClass = new ExternClass(attrs,0,nameIx,this.externClass);
\r
2194 metaData.AddToTable(MDTable.ExportedType,externClass);
\r
2195 return nestedClass;
\r
2199 /**************************************************************************/
\r
2201 /// Descriptor for a constant value
\r
2203 public abstract class Constant {
\r
2204 protected uint size = 0;
\r
2205 protected Type type;
\r
2206 protected uint blobIndex;
\r
2207 protected bool addedToBlobHeap = false;
\r
2209 internal Constant() { }
\r
2211 internal virtual uint GetBlobIndex(MetaData md) { return 0; }
\r
2213 internal uint GetSize() { return size; }
\r
2215 internal byte GetTypeIndex() { return type.GetTypeIndex(); }
\r
2217 internal virtual void Write(BinaryWriter bw) { }
\r
2221 /// Descriptor for a constant value
\r
2223 public abstract class DataConstant : Constant {
\r
2224 private uint dataOffset = 0;
\r
2226 internal DataConstant() { }
\r
2228 public uint DataOffset {
\r
2229 get { return dataOffset; }
\r
2230 set { dataOffset = value; }
\r
2236 /// Boolean constant
\r
2238 public class BoolConst : Constant {
\r
2242 /// Create a new boolean constant with the value "val"
\r
2244 /// <param name="val">value of this boolean constant</param>
\r
2245 public BoolConst(bool val) {
\r
2248 type = PrimitiveType.Boolean;
\r
2251 internal sealed override uint GetBlobIndex(MetaData md) {
\r
2252 if (!addedToBlobHeap) {
\r
2253 if (val) blobIndex = md.AddToBlobHeap((sbyte)1);
\r
2254 else blobIndex = md.AddToBlobHeap((sbyte)0);
\r
2255 addedToBlobHeap = true;
\r
2260 internal sealed override void Write(BinaryWriter bw) {
\r
2261 if (val) bw.Write((sbyte)1);
\r
2262 else bw.Write((sbyte)0);
\r
2267 public class ByteArrConst : DataConstant {
\r
2270 public ByteArrConst(byte[] val) {
\r
2272 size = (uint)val.Length;
\r
2276 get { return type; }
2277 set { type = value; }
2280 internal sealed override uint GetBlobIndex(MetaData md) {
\r
2281 if (!addedToBlobHeap) {
\r
2282 blobIndex = md.AddToBlobHeap(val);
\r
2283 addedToBlobHeap = true;
\r
2288 internal sealed override void Write(BinaryWriter bw) {
\r
2294 public class CharConst : Constant {
\r
2297 public CharConst(char val) {
\r
2300 type = PrimitiveType.Char;
\r
2303 internal sealed override uint GetBlobIndex(MetaData md) {
\r
2304 if (!addedToBlobHeap) {
\r
2305 blobIndex = md.AddToBlobHeap(val);
\r
2306 addedToBlobHeap = true;
\r
2311 internal sealed override void Write(BinaryWriter bw) {
\r
2317 public class FloatConst : DataConstant {
\r
2320 public FloatConst(float val) {
\r
2323 type = PrimitiveType.Float32;
\r
2326 internal sealed override uint GetBlobIndex(MetaData md) {
\r
2327 if (!addedToBlobHeap) {
\r
2328 blobIndex = md.AddToBlobHeap(val);
\r
2329 addedToBlobHeap = true;
\r
2334 internal sealed override void Write(BinaryWriter bw) {
\r
2340 public class DoubleConst : DataConstant {
\r
2343 public DoubleConst(double val) {
\r
2346 type = PrimitiveType.Float64;
\r
2349 internal sealed override uint GetBlobIndex(MetaData md) {
\r
2350 if (!addedToBlobHeap) {
\r
2351 blobIndex = md.AddToBlobHeap(val);
\r
2352 addedToBlobHeap = true;
\r
2357 internal sealed override void Write(BinaryWriter bw) {
\r
2363 public class IntConst : DataConstant {
\r
2366 public IntConst(sbyte val) {
\r
2369 type = PrimitiveType.Int8;
\r
2372 public IntConst(short val) {
\r
2375 type = PrimitiveType.Int16;
\r
2378 public IntConst(int val) {
\r
2381 type = PrimitiveType.Int32;
\r
2384 public IntConst(long val) {
\r
2387 type = PrimitiveType.Int64;
\r
2390 internal sealed override uint GetBlobIndex(MetaData md) {
\r
2391 if (!addedToBlobHeap) {
\r
2393 case (1) : blobIndex = md.AddToBlobHeap((sbyte)val); break;
\r
2394 case (2) : blobIndex = md.AddToBlobHeap((short)val); break;
\r
2395 case (4) : blobIndex = md.AddToBlobHeap((int)val); break;
\r
2396 default : blobIndex = md.AddToBlobHeap(val); break;
\r
2398 addedToBlobHeap = true;
\r
2403 internal sealed override void Write(BinaryWriter bw) {
\r
2405 case (1) : bw.Write((sbyte)val); break;
\r
2406 case (2) : bw.Write((short)val); break;
\r
2407 case (4) : bw.Write((int)val); break;
\r
2408 default : bw.Write(val); break;
\r
2414 public class UIntConst : Constant {
\r
2417 public UIntConst(sbyte val) {
\r
2420 type = PrimitiveType.UInt8;
\r
2422 public UIntConst(short val) {
\r
2425 type = PrimitiveType.UInt16;
\r
2427 public UIntConst(int val) {
\r
2430 type = PrimitiveType.UInt32;
\r
2432 public UIntConst(long val) {
\r
2435 type = PrimitiveType.UInt64;
\r
2438 internal sealed override uint GetBlobIndex(MetaData md) {
\r
2439 if (!addedToBlobHeap) {
\r
2441 case (1) : blobIndex = md.AddToBlobHeap((sbyte)val); break;
\r
2442 case (2) : blobIndex = md.AddToBlobHeap((short)val); break;
\r
2443 case (4) : blobIndex = md.AddToBlobHeap((int)val); break;
\r
2444 default : blobIndex = md.AddToBlobHeap(val); break;
\r
2446 addedToBlobHeap = true;
\r
2451 internal sealed override void Write(BinaryWriter bw) {
\r
2453 case (1) : bw.Write((sbyte)val); break;
\r
2454 case (2) : bw.Write((short)val); break;
\r
2455 case (4) : bw.Write((int)val); break;
\r
2456 default : bw.Write(val); break;
\r
2462 public class StringConst : DataConstant {
\r
2465 public StringConst(string val) {
\r
2467 size = (uint)val.Length; // need to add null ??
\r
2468 type = PrimitiveType.String;
\r
2471 internal sealed override uint GetBlobIndex(MetaData md) {
\r
2472 if (!addedToBlobHeap) {
2473 byte [] b = Encoding.Unicode.GetBytes (val);
2474 blobIndex = md.AddToBlobHeap(b);
\r
2475 addedToBlobHeap = true;
\r
2480 internal sealed override void Write(BinaryWriter bw) {
\r
2486 public class NullConst : Constant {
\r
2488 public NullConst() {
\r
2490 type = PrimitiveType.Class;
\r
2493 internal sealed override uint GetBlobIndex(MetaData md) {
\r
2494 if (!addedToBlobHeap) {
\r
2495 blobIndex = md.AddToBlobHeap((int)0);
\r
2496 addedToBlobHeap = true;
\r
2501 internal sealed override void Write(BinaryWriter bw) {
\r
2502 bw.Write((int)0);
\r
2507 public class AddressConstant : DataConstant {
\r
2508 DataConstant data;
\r
2510 public AddressConstant(DataConstant dConst) {
\r
2513 type = PrimitiveType.TypedRef;
\r
2516 internal sealed override void Write(BinaryWriter bw) {
\r
2517 ((FileImage)bw).WriteDataRVA(data.DataOffset);
\r
2522 public class RepeatedConstant : DataConstant {
\r
2523 DataConstant data;
\r
2526 public RepeatedConstant(DataConstant dConst, int repeatCount) {
\r
2528 repCount = (uint)repeatCount;
\r
2529 int[] sizes = new int[1];
\r
2530 sizes[0] = repeatCount;
\r
2531 type = new BoundArray(type,1,sizes);
\r
2532 size = data.GetSize() * repCount;
\r
2535 internal sealed override void Write(BinaryWriter bw) {
\r
2536 for (int i=0; i < repCount; i++) {
\r
2543 public class ArrayConstant : DataConstant {
\r
2544 DataConstant[] dataVals;
\r
2546 public ArrayConstant(DataConstant[] dVals) {
\r
2548 for (int i=0; i < dataVals.Length; i++) {
\r
2549 size += dataVals[i].GetSize();
\r
2553 internal sealed override void Write(BinaryWriter bw) {
\r
2554 for (int i=0; i < dataVals.Length; i++) {
\r
2555 dataVals[i].Write(bw);
\r
2561 public class ClassType : Constant {
\r
2565 public ClassType(string className) {
\r
2567 type = PrimitiveType.ClassType;
\r
2570 public ClassType(Class classDesc) {
\r
2572 type = PrimitiveType.ClassType;
\r
2575 internal override void Write(BinaryWriter bw) {
\r
2576 if (name == null) name = desc.TypeName();
\r
2584 /**************************************************************************/
\r
2586 /// Summary description for ConstantElem.
\r
2588 internal class ConstantElem : MetaDataElement
\r
2590 MetaDataElement parent;
\r
2594 internal ConstantElem(MetaDataElement parent, Constant val) {
\r
2595 this.parent = parent;
\r
2597 tabIx = MDTable.Constant;
\r
2600 internal sealed override void BuildTables(MetaData md) {
\r
2602 valIx = cValue.GetBlobIndex(md);
\r
2606 internal void AddToBlob(BinaryWriter bw) {
\r
2610 internal sealed override uint Size(MetaData md) {
\r
2611 return 2 + md.CodedIndexSize(CIx.HasConst) + md.BlobIndexSize();
\r
2614 internal sealed override void Write(FileImage output) {
\r
2615 output.Write(cValue.GetTypeIndex());
\r
2616 output.Write((byte)0);
\r
2617 output.WriteCodedIndex(CIx.HasConst,parent);
\r
2618 output.BlobIndex(valIx);
\r
2622 /**************************************************************************/
\r
2624 /// Descriptor for a Custom Attribute (.custom)
\r
2627 public class CustomAttribute : MetaDataElement
\r
2629 private static readonly ushort prolog = 0x0001;
\r
2630 MetaDataElement parent;
\r
2635 ushort numNamed = 0;
\r
2636 ArrayList names, vals;
\r
2638 internal CustomAttribute(MetaDataElement paren, Method constrType,
\r
2641 type = constrType;
\r
2643 tabIx = MDTable.CustomAttribute;
\r
2644 throw(new NotYetImplementedException("Custom Attributes "));
\r
2647 internal CustomAttribute(MetaDataElement paren, Method constrType,
\r
2650 type = constrType;
\r
2651 tabIx = MDTable.CustomAttribute;
\r
2655 public void AddFieldOrProp(string name, Constant val) {
\r
2656 if (numNamed == 0) {
\r
2657 names = new ArrayList();
\r
2658 vals = new ArrayList();
\r
2664 internal sealed override void BuildTables(MetaData md) {
\r
2665 BinaryWriter bw = new BinaryWriter(new MemoryStream());
\r
2666 bw.Write(byteVal);
\r
2667 md.AddToTable(MDTable.CustomAttribute, this);
\r
2668 MemoryStream str = (MemoryStream)bw.BaseStream;
\r
2669 valIx = md.AddToBlobHeap(str.ToArray());
\r
2672 internal sealed override uint Size(MetaData md) {
\r
2673 return md.CodedIndexSize(CIx.HasCustomAttr) + md.CodedIndexSize(CIx.CustomAttributeType) + md.BlobIndexSize();
\r
2676 internal sealed override void Write(FileImage output) {
\r
2677 output.WriteCodedIndex(CIx.HasCustomAttr,parent);
\r
2678 output.WriteCodedIndex(CIx.CustomAttributeType,type);
\r
2679 output.BlobIndex(valIx);
\r
2683 /**************************************************************************/
\r
2685 /// Descriptor for a custom modifier of a type (modopt or modreq)
\r
2688 public class CustomModifiedType : Type
\r
2694 /// Create a new custom modifier for a type
\r
2696 /// <param name="type">the type to be modified</param>
\r
2697 /// <param name="cmod">the modifier</param>
\r
2698 /// <param name="cmodType">the type reference to be associated with the type</param>
\r
2699 public CustomModifiedType(Type type, CustomModifier cmod, Class cmodType)
\r
2700 : base((byte)cmod) {
\r
2702 this.cmodType = cmodType;
\r
2705 internal sealed override void TypeSig(MemoryStream str) {
\r
2706 str.WriteByte(typeIndex);
\r
2707 MetaData.CompressNum(cmodType.TypeDefOrRefToken(),str);
\r
2708 type.TypeSig(str);
\r
2712 /**************************************************************************/
\r
2714 /// Descriptor for security permissions for a class or a method NOT YET IMPLEMENTED
\r
2717 public class DeclSecurity : MetaDataElement
\r
2720 MetaDataElement parent;
\r
2721 uint permissionIx;
\r
2723 internal DeclSecurity(MetaDataElement paren, ushort act) {
\r
2726 tabIx = MDTable.DeclSecurity;
\r
2727 throw(new NotYetImplementedException("Security "));
\r
2730 internal sealed override uint Size(MetaData md) {
\r
2731 return 2 + md.CodedIndexSize(CIx.HasDeclSecurity) + md.BlobIndexSize();
\r
2734 internal sealed override void BuildTables(MetaData md) {
\r
2736 // add permission to blob heap
\r
2740 internal sealed override void Write(FileImage output) {
\r
2741 output.Write(action);
\r
2742 output.WriteCodedIndex(CIx.HasDeclSecurity,parent);
\r
2743 output.BlobIndex(permissionIx);
\r
2747 /**************************************************************************/
\r
2749 /// Descriptor for an event
\r
2751 public class Event : Feature
\r
2755 internal Event(string name, Type eType, ClassDef parent)
\r
2756 : base(name, parent) {
\r
2757 eventType = eType;
\r
2758 tabIx = MDTable.Event;
\r
2762 /// Add the addon method to this event
\r
2764 /// <param name="addon">the addon method</param>
\r
2765 public void AddAddon(MethodDef addon) {
\r
2766 AddMethod(addon,MethodType.AddOn);
\r
2770 /// Add the removeon method to this event
\r
2772 /// <param name="removeOn">the removeon method</param>
\r
2773 public void AddRemoveOn(MethodDef removeOn) {
\r
2774 AddMethod(removeOn,MethodType.RemoveOn);
\r
2778 /// Add the fire method to this event
\r
2780 /// <param name="fire">the fire method</param>
\r
2781 public void AddFire(MethodDef fire) {
\r
2782 AddMethod(fire,MethodType.Fire);
\r
2786 /// Add another method to this event
\r
2788 /// <param name="other">the method to be added</param>
\r
2789 public void AddOther(MethodDef other) {
\r
2790 AddMethod(other,MethodType.Other);
\r
2793 internal sealed override void BuildTables(MetaData md) {
\r
2795 nameIx = md.AddToStringsHeap(name);
\r
2796 for (int i=0; i < tide; i++) {
\r
2797 md.AddToTable(MDTable.MethodSemantics,methods[i]);
\r
2802 internal sealed override uint Size(MetaData md) {
\r
2803 return 2 + md.StringsIndexSize() + md.CodedIndexSize(CIx.TypeDefOrRef);
\r
2806 internal sealed override void Write(FileImage output) {
\r
2807 output.Write(flags);
\r
2808 output.StringsIndex(nameIx);
\r
2809 output.WriteCodedIndex(CIx.TypeDefOrRef,eventType);
\r
2812 internal sealed override uint GetCodedIx(CIx code) {
\r
2814 case (CIx.HasCustomAttr) : return 10;
\r
2815 case (CIx.HasSemantics) : return 0;
\r
2821 /**************************************************************************/
\r
2823 /// Descriptor for a class defined in another module of THIS assembly
\r
2824 /// and exported (.class extern)
\r
2827 internal class ExternClass : Class
\r
2829 MetaDataElement parent;
\r
2832 internal ExternClass(TypeAttr attr, uint nsIx, uint nIx,
\r
2833 MetaDataElement paren) : base(nsIx,nIx) {
\r
2834 flags = (uint)attr;
\r
2836 tabIx = MDTable.ExportedType;
\r
2839 internal sealed override uint Size(MetaData md) {
\r
2840 return 8 + 2* md.StringsIndexSize() + md.CodedIndexSize(CIx.Implementation);
\r
2843 internal sealed override void Write(FileImage output) {
\r
2844 output.Write(flags);
\r
2846 output.StringsIndex(nameIx);
\r
2847 output.StringsIndex(nameSpaceIx);
\r
2848 output.WriteCodedIndex(CIx.Implementation,parent);
\r
2851 internal sealed override uint GetCodedIx(CIx code) {
\r
2853 case (CIx.HasCustomAttr) : return 17;
\r
2854 case (CIx.Implementation) : return 2;
\r
2860 /**************************************************************************/
\r
2862 /// Base class for Event and Property descriptors
\r
2865 public class Feature : MetaDataElement
\r
2867 internal enum MethodType : ushort { Setter = 0x01, Getter, Other = 0x04, AddOn = 0x08,
\r
2868 RemoveOn = 0x10, Fire = 0x20 }
\r
2870 private static readonly int INITSIZE = 5;
\r
2871 private static readonly ushort specialName = 0x200;
\r
2872 private static readonly ushort rtSpecialName = 0x400;
\r
2874 protected ClassDef parent;
\r
2875 protected ushort flags = 0;
\r
2876 protected string name;
\r
2877 protected int tide = 0;
\r
2878 protected uint nameIx;
\r
2879 protected MethodSemantics[] methods = new MethodSemantics[INITSIZE];
\r
2881 internal Feature(string name, ClassDef par) {
\r
2886 internal void AddMethod(MethodDef meth, MethodType mType) {
\r
2887 if (tide >= methods.Length) {
\r
2888 int len = methods.Length;
\r
2889 MethodSemantics[] mTmp = methods;
\r
2890 methods = new MethodSemantics[len * 2];
\r
2891 for (int i=0; i < len; i++) {
\r
2892 methods[i] = mTmp[i];
\r
2895 methods[tide++] = new MethodSemantics(mType,meth,this);
\r
2899 /// Set the specialName attribute for this Event or Property
\r
2901 public void SetSpecialName() {
\r
2902 flags |= specialName;
\r
2906 /// Set the RTSpecialName attribute for this Event or Property
\r
2908 public void SetRTSpecialName() {
\r
2909 flags |= rtSpecialName;
\r
2913 /*****************************************************************************/
\r
2915 /// Descriptor for a field of a class
\r
2918 public abstract class Field : Member
\r
2920 protected static readonly byte FieldSig = 0x6;
\r
2922 protected Type type;
\r
2924 internal Field(string pfName, Type pfType) : base(pfName)
\r
2930 /**************************************************************************/
\r
2932 /// Descriptor for a field defined in a class of THIS assembly/module
\r
2934 public class FieldDef : Field
\r
2936 //private static readonly uint PInvokeImpl = 0x2000;
\r
2937 private static readonly ushort HasFieldMarshal = 0x1000;
\r
2938 private static readonly ushort HasFieldRVA = 0x100;
\r
2939 private static readonly ushort HasDefault = 0x8000;
2942 ConstantElem constVal;
\r
2943 FieldLayout layout;
\r
2944 FieldMarshal marshalInfo;
\r
2947 internal FieldDef(string name, Type fType) : base(name,fType) {
\r
2948 tabIx = MDTable.Field;
\r
2951 internal FieldDef(FieldAttr attrSet, string name, Type fType) : base(name, fType) {
\r
2952 flags = (ushort)attrSet;
\r
2953 tabIx = MDTable.Field;
\r
2957 /// Add an attribute(s) to this field
\r
2959 /// <param name="fa">the attribute(s) to be added</param>
\r
2960 public void AddFieldAttr(FieldAttr fa) {
\r
2961 flags |= (ushort)fa;
\r
2965 /// Add a value for this field
\r
2967 /// <param name="val">the value for the field</param>
\r
2968 public void AddValue(Constant val) {
\r
2969 constVal = new ConstantElem(this,val);
\r
2970 flags |= HasDefault;
2974 /// Add an initial value for this field (at dataLabel) (.data)
\r
2976 /// <param name="val">the value for the field</param>
\r
2977 /// <param name="repeatVal">the number of repetitions of this value</param>
\r
2978 public void AddDataValue(DataConstant val) {
\r
2979 flags |= HasFieldRVA;
\r
2980 rva = new FieldRVA(this,val);
\r
2984 /// Set the offset of the field. Used for sequential or explicit classes.
\r
2985 /// (.field [offs])
\r
2987 /// <param name="offs">field offset</param>
\r
2988 public void SetOffset(uint offs) {
\r
2989 layout = new FieldLayout(this,offs);
\r
2993 /// Set the marshalling info for a field
\r
2995 /// <param name="mInf"></param>
\r
2996 public void SetMarshalInfo(NativeType marshallType) {
\r
2997 flags |= HasFieldMarshal;
\r
2998 marshalInfo = new FieldMarshal(this,marshallType);
\r
3001 internal sealed override void BuildTables(MetaData md) {
\r
3003 nameIx = md.AddToStringsHeap(name);
\r
3004 MemoryStream sig = new MemoryStream();
\r
3005 sig.WriteByte(FieldSig);
\r
3006 type.TypeSig(sig);
\r
3007 sigIx = md.AddToBlobHeap(sig.ToArray());
\r
3008 if (rva != null) {
\r
3009 md.AddToTable(MDTable.FieldRVA,rva);
\r
3010 rva.BuildTables(md);
\r
3011 } else if (constVal != null) {
\r
3012 md.AddToTable(MDTable.Constant,constVal);
\r
3013 constVal.BuildTables(md);
\r
3015 if (layout != null) md.AddToTable(MDTable.FieldLayout,layout);
\r
3016 if (marshalInfo != null) {
\r
3017 md.AddToTable(MDTable.FieldMarshal,marshalInfo);
\r
3018 marshalInfo.BuildTables(md);
\r
3023 internal sealed override uint Size(MetaData md) {
\r
3024 return 2 + md.StringsIndexSize() + md.BlobIndexSize();
\r
3027 internal sealed override void Write(FileImage output) {
\r
3028 output.Write(flags);
\r
3029 output.StringsIndex(nameIx);
\r
3030 output.BlobIndex(sigIx);
\r
3033 internal sealed override uint GetCodedIx(CIx code) {
\r
3035 case (CIx.HasConst) : return 0;
\r
3036 case (CIx.HasCustomAttr) : return 1;
\r
3037 case (CIx.HasFieldMarshal) : return 0;
\r
3038 case (CIx.MemberForwarded) : return 0;
\r
3044 /**************************************************************************/
\r
3046 /// Descriptor for layout information for a field
\r
3049 public class FieldLayout : MetaDataElement
\r
3054 internal FieldLayout(Field field, uint offset) {
\r
3055 this.field = field;
\r
3056 this.offset = offset;
\r
3057 tabIx = MDTable.FieldLayout;
\r
3060 internal sealed override uint Size(MetaData md) {
\r
3061 return 4 + md.TableIndexSize(MDTable.Field);
\r
3064 internal sealed override void Write(FileImage output) {
\r
3065 output.Write(offset);
\r
3066 output.WriteIndex(MDTable.Field,field.Row);
\r
3070 /*****************************************************************************/
\r
3072 /// Marshalling information for a field or param
\r
3074 public class FieldMarshal : MetaDataElement
\r
3076 MetaDataElement field;
\r
3080 internal FieldMarshal(MetaDataElement field, NativeType nType) {
\r
3081 this.field = field;
\r
3083 tabIx = MDTable.FieldMarshal;
\r
3086 internal sealed override void BuildTables(MetaData md) {
\r
3088 ntIx = md.AddToBlobHeap(nt.ToBlob());
\r
3092 internal sealed override uint Size(MetaData md) {
\r
3093 return md.CodedIndexSize(CIx.HasFieldMarshal) + md.BlobIndexSize();
\r
3096 internal sealed override void Write(FileImage output) {
\r
3097 output.WriteCodedIndex(CIx.HasFieldMarshal,field);
\r
3098 output.BlobIndex(ntIx);
\r
3102 /**************************************************************************/
\r
3104 /// Descriptor for a field of a class defined in another assembly/module
\r
3106 public class FieldRef : Field
\r
3108 MetaDataElement parent;
\r
3110 internal FieldRef(MetaDataElement paren, string name, Type fType) : base(name, fType) {
\r
3114 internal sealed override void BuildTables(MetaData md) {
\r
3116 nameIx = md.AddToStringsHeap(name);
\r
3117 MemoryStream sig = new MemoryStream();
\r
3118 sig.WriteByte(FieldSig);
\r
3119 type.TypeSig(sig);
\r
3120 sigIx = md.AddToBlobHeap(sig.ToArray());
\r
3124 internal sealed override uint Size(MetaData md) {
\r
3125 return md.CodedIndexSize(CIx.MemberRefParent) + md.StringsIndexSize() + md.BlobIndexSize();
\r
3128 internal sealed override void Write(FileImage output) {
\r
3129 output.WriteCodedIndex(CIx.MemberRefParent,parent);
\r
3130 output.StringsIndex(nameIx);
\r
3131 output.BlobIndex(sigIx);
\r
3134 internal sealed override uint GetCodedIx(CIx code) { return 6; }
\r
3137 /**************************************************************************/
\r
3139 /// Descriptor for the address of a field's value in the PE file
\r
3141 public class FieldRVA : MetaDataElement
\r
3144 DataConstant data;
\r
3146 internal FieldRVA(Field field, DataConstant data) {
\r
3147 this.field = field;
\r
3149 tabIx = MDTable.FieldRVA;
\r
3152 internal sealed override void BuildTables(MetaData md) {
\r
3158 internal sealed override uint Size(MetaData md) {
\r
3159 return 4 + md.TableIndexSize(MDTable.Field);
\r
3162 internal sealed override void Write(FileImage output) {
\r
3163 output.WriteDataRVA(data.DataOffset);
\r
3164 output.WriteIndex(MDTable.Field,field.Row);
\r
3168 /**************************************************************************/
\r
3170 /// Image for a PEFile
\r
3171 /// File Structure
\r
3172 /// DOS Header (128 bytes)
\r
3173 /// PE Signature ("PE\0\0")
\r
3174 /// PEFileHeader (20 bytes)
\r
3175 /// PEOptionalHeader (224 bytes)
\r
3176 /// SectionHeaders (40 bytes * NumSections)
\r
3178 /// Sections .text (always present - contains metadata)
\r
3179 /// .sdata (contains any initialised data in the file - may not be present)
\r
3180 /// (for ilams /debug this contains the Debug table)
\r
3181 /// .reloc (always present - in pure CIL only has one fixup)
\r
3182 /// others??? c# produces .rsrc section containing a Resource Table
\r
3185 /// IAT (single entry 8 bytes for pure CIL)
\r
3186 /// CLIHeader (72 bytes)
\r
3187 /// CIL instructions for all methods (variable size)
\r
3189 /// Root (20 bytes + UTF-8 Version String + quad align padding)
\r
3190 /// StreamHeaders (8 bytes + null terminated name string + quad align padding)
\r
3192 /// #~ (always present - holds metadata tables)
\r
3193 /// #Strings (always present - holds identifier strings)
\r
3194 /// #US (Userstring heap)
\r
3195 /// #Blob (signature blobs)
\r
3196 /// #GUID (guids for assemblies or Modules)
\r
3197 /// ImportTable (40 bytes)
\r
3198 /// ImportLookupTable(8 bytes) (same as IAT for standard CIL files)
\r
3199 /// Hint/Name Tables with entry "_CorExeMain" for .exe file and "_CorDllMain" for .dll (14 bytes)
\r
3200 /// ASCII string "mscoree.dll" referenced in ImportTable (+ padding = 16 bytes)
\r
3201 /// Entry Point (0xFF25 followed by 4 bytes 0x400000 + RVA of .text)
\r
3203 /// #~ stream structure
\r
3204 /// Header (24 bytes)
\r
3205 /// Rows (4 bytes * numTables)
\r
3208 internal class FileImage : BinaryWriter
\r
3210 internal readonly static uint[] iByteMask = {0x000000FF, 0x0000FF00, 0x00FF0000, 0xFF000000};
\r
3211 internal readonly static ulong[] lByteMask = {0x00000000000000FF, 0x000000000000FF00,
\r
3212 0x0000000000FF0000, 0x00000000FF000000,
\r
3213 0x000000FF00000000, 0x0000FF0000000000,
\r
3214 0x00FF000000000000, 0xFF00000000000000 };
\r
3215 internal readonly static uint nibble0Mask = 0x0000000F;
\r
3216 internal readonly static uint nibble1Mask = 0x000000F0;
\r
3218 private static readonly byte[] DOSHeader = { 0x4d,0x5a,0x90,0x00,0x03,0x00,0x00,0x00,
\r
3219 0x04,0x00,0x00,0x00,0xff,0xff,0x00,0x00,
\r
3220 0xb8,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
\r
3221 0x40,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
\r
3222 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
\r
3223 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
\r
3224 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
\r
3225 0x00,0x00,0x00,0x00,0x80,0x00,0x00,0x00,
\r
3226 0x0e,0x1f,0xba,0x0e,0x00,0xb4,0x09,0xcd,
\r
3227 0x21,0xb8,0x01,0x4c,0xcd,0x21,0x54,0x68,
\r
3228 0x69,0x73,0x20,0x70,0x72,0x6f,0x67,0x72,
\r
3229 0x61,0x6d,0x20,0x63,0x61,0x6e,0x6e,0x6f,
\r
3230 0x74,0x20,0x62,0x65,0x20,0x72,0x75,0x6e,
\r
3231 0x20,0x69,0x6e,0x20,0x44,0x4f,0x53,0x20,
\r
3232 0x6d,0x6f,0x64,0x65,0x2e,0x0d,0x0d,0x0a,
\r
3233 0x24,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
\r
3234 0x50,0x45,0x00,0x00};
\r
3235 private static byte[] PEHeader = { 0x4c, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
\r
3236 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
\r
3237 0xE0, 0x00, 0x0E, 0x01, // PE Header Standard Fields
\r
3238 0x0B, 0x01, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00,
\r
3239 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
\r
3240 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
\r
3243 private static readonly uint minFileAlign = 0x200;
\r
3244 private static readonly uint maxFileAlign = 0x1000;
\r
3245 private static readonly uint fileHeaderSize = 0x178;
\r
3246 private static readonly uint sectionHeaderSize = 40;
\r
3247 private static readonly uint SectionAlignment = 0x2000;
\r
3248 private static readonly uint ImageBase = 0x400000;
\r
3249 private static readonly uint ImportTableSize = 40;
\r
3250 private static readonly uint IATSize = 8;
\r
3251 private static readonly uint CLIHeaderSize = 72;
3252 private uint runtimeFlags = 0x01; // COMIMAGE_FLAGS_ILONLY
3253 // 32BITREQUIRED 0x02, STRONGNAMESIGNED 0x08, TRACKDEBUGDATA 0x10000
3254 private static readonly uint StrongNameSignatureSize = 128;
3255 private bool reserveStrongNameSignatureSpace = false;
3257 private static readonly uint relocFlags = 0x42000040;
\r
3258 private static readonly ushort exeCharacteristics = 0x010E;
\r
3259 private static readonly ushort dllCharacteristics = 0x210E;
\r
3260 // section names are all 8 bytes
\r
3261 private static readonly string textName = ".text\0\0\0";
\r
3262 private static readonly string sdataName = ".sdata\0\0";
\r
3263 private static readonly string relocName = ".reloc\0\0";
\r
3264 private static readonly string rsrcName = ".rsrc\0\0\0";
\r
3265 private static readonly string exeHintNameTable = "\0\0_CorExeMain\0";
\r
3266 private static readonly string dllHintNameTable = "\0\0_CorDllMain\0";
\r
3267 private static readonly string runtimeEngineName = "mscoree.dll\0\0";
\r
3269 private Section text, sdata, rsrc;
\r
3271 BinaryWriter reloc = new BinaryWriter(new MemoryStream());
\r
3272 uint dateStamp = 0;
\r
3273 DateTime origin = new DateTime(1970,1,1);
\r
3274 uint numSections = 2; // always have .text and .reloc sections
\r
3275 internal SubSystem subSys = SubSystem.Windows_CUI; // default is Windows Console mode
\r
3276 internal uint fileAlign = minFileAlign;
\r
3277 uint entryPointOffset, entryPointPadding, imageSize, headerSize, headerPadding, entryPointToken = 0;
\r
3278 uint relocOffset, relocRVA, relocSize, relocPadding, relocTide, hintNameTableOffset;
\r
3279 uint metaDataOffset, runtimeEngineOffset, initDataSize = 0, importTablePadding;
3280 uint strongNameSigOffset;
\r
3281 uint importTableOffset, importLookupTableOffset, totalImportTableSize;
\r
3282 MetaData metaData;
\r
3283 char[] runtimeEngine = runtimeEngineName.ToCharArray(), hintNameTable;
\r
3284 bool doDLL, largeStrings, largeGUID, largeUS, largeBlob;
\r
3285 ushort characteristics;
\r
3287 internal FileImage(bool makeDLL, string fileName) : base(new FileStream(fileName,FileMode.Create)) {
\r
3288 InitFileImage(makeDLL);
\r
3289 TimeSpan tmp = System.IO.File.GetCreationTime(fileName).Subtract(origin);
\r
3290 dateStamp = Convert.ToUInt32(tmp.TotalSeconds);
\r
3293 internal FileImage(bool makeDLL, Stream str) : base(str) {
\r
3294 InitFileImage(makeDLL);
\r
3295 TimeSpan tmp = DateTime.Now.Subtract(origin);
\r
3296 dateStamp = Convert.ToUInt32(tmp.TotalSeconds);
\r
3299 private void InitFileImage(bool makeDLL) {
\r
3302 hintNameTable = dllHintNameTable.ToCharArray();
\r
3303 characteristics = dllCharacteristics;
\r
3305 hintNameTable = exeHintNameTable.ToCharArray();
\r
3306 characteristics = exeCharacteristics;
\r
3308 text = new Section(textName,0x60000020); // IMAGE_SCN_CNT CODE, EXECUTE, READ
\r
3309 // rsrc = new Section(rsrcName,0x40000040); // IMAGE_SCN_CNT INITIALIZED_DATA, READ
\r
3310 metaData = new MetaData(this);
\r
3313 internal MetaData GetMetaData() {
\r
3317 private uint GetNextSectStart(uint rva, uint tide) {
\r
3318 if (tide < SectionAlignment) return rva + SectionAlignment;
\r
3319 return rva + ((tide / SectionAlignment) + 1) * SectionAlignment;
\r
3322 private void BuildTextSection() {
\r
3324 // IAT (single entry 8 bytes for pure CIL)
\r
3325 // CLIHeader (72 bytes)
\r
3326 // CIL instructions for all methods (variable size)
\r
3328 // ImportTable (40 bytes)
\r
3329 // ImportLookupTable(8 bytes) (same as IAT for standard CIL files)
\r
3330 // Hint/Name Tables with entry "_CorExeMain" for .exe file and "_CorDllMain" for .dll (14 bytes)
\r
3331 // ASCII string "mscoree.dll" referenced in ImportTable (+ padding = 16 bytes)
\r
3332 // Entry Point (0xFF25 followed by 4 bytes 0x400000 + RVA of .text)
\r
3333 metaData.BuildMetaData(IATSize + CLIHeaderSize);
\r
3334 metaDataOffset = IATSize + CLIHeaderSize;
\r
3335 // Console.WriteLine("Code starts at " + metaDataOffset);
\r
3336 metaDataOffset += metaData.CodeSize();
\r
3338 if (reserveStrongNameSignatureSpace) {
\r
3339 strongNameSigOffset = metaDataOffset + metaData.Size();
\r
3340 // fixUps = RVA for vtable
\r
3341 importTableOffset = strongNameSigOffset + StrongNameSignatureSize;
3343 strongNameSigOffset = 0;
\r
3344 // fixUps = RVA for vtable
\r
3345 importTableOffset = metaDataOffset + metaData.Size();
3347 importTablePadding = NumToAlign(importTableOffset,16);
\r
3348 importTableOffset += importTablePadding;
\r
3349 importLookupTableOffset = importTableOffset + ImportTableSize;
\r
3350 hintNameTableOffset = importLookupTableOffset + IATSize;
\r
3351 runtimeEngineOffset = hintNameTableOffset + (uint)hintNameTable.Length;
\r
3352 entryPointOffset = runtimeEngineOffset + (uint)runtimeEngine.Length;
\r
3353 totalImportTableSize = entryPointOffset - importTableOffset;
\r
3354 // Console.WriteLine("total import table size = " + totalImportTableSize);
\r
3355 // Console.WriteLine("entrypoint offset = " + entryPointOffset);
\r
3356 entryPointPadding = NumToAlign(entryPointOffset,4) + 2;
\r
3357 entryPointOffset += entryPointPadding;
\r
3358 text.AddReloc(entryPointOffset+2);
\r
3359 text.IncTide(entryPointOffset + 6);
\r
3360 //if (text.Tide() < fileAlign) fileAlign = minFileAlign;
\r
3361 text.SetSize(NumToAlign(text.Tide(),fileAlign));
\r
3362 // Console.WriteLine("text size = " + text.Size() + " text tide = " + text.Tide() + " text padding = " + text.Padding());
\r
3363 // Console.WriteLine("metaDataOffset = " + Hex.Int(metaDataOffset));
\r
3364 // Console.WriteLine("importTableOffset = " + Hex.Int(importTableOffset));
\r
3365 // Console.WriteLine("importLookupTableOffset = " + Hex.Int(importLookupTableOffset));
\r
3366 // Console.WriteLine("hintNameTableOffset = " + Hex.Int(hintNameTableOffset));
\r
3367 // Console.WriteLine("runtimeEngineOffset = " + Hex.Int(runtimeEngineOffset));
\r
3368 // Console.WriteLine("entryPointOffset = " + Hex.Int(entryPointOffset));
\r
3369 // Console.WriteLine("entryPointPadding = " + Hex.Int(entryPointPadding));
\r
3373 internal void BuildRelocSection() {
\r
3374 text.DoRelocs(reloc);
\r
3375 if (sdata != null) sdata.DoRelocs(reloc);
\r
3376 if (rsrc != null) rsrc.DoRelocs(reloc);
\r
3377 relocTide = (uint)reloc.Seek(0,SeekOrigin.Current);
\r
3378 relocPadding = NumToAlign(relocTide,fileAlign);
\r
3379 relocSize = relocTide + relocPadding;
\r
3380 imageSize = relocRVA + SectionAlignment;
\r
3381 initDataSize += relocSize;
\r
3384 private void CalcOffsets() {
\r
3389 headerSize = fileHeaderSize + (numSections * sectionHeaderSize);
\r
3390 headerPadding = NumToAlign(headerSize,fileAlign);
\r
3391 headerSize += headerPadding;
\r
3392 uint offset = headerSize;
\r
3393 uint rva = SectionAlignment;
\r
3394 text.SetOffset(offset);
\r
3396 offset += text.Size();
\r
3397 rva = GetNextSectStart(rva,text.Tide());
\r
3398 // Console.WriteLine("headerSize = " + headerSize);
\r
3399 // Console.WriteLine("headerPadding = " + headerPadding);
\r
3400 // Console.WriteLine("textOffset = " + Hex.Int(text.Offset()));
\r
3401 if (sdata != null) {
\r
3402 sdata.SetSize(NumToAlign(sdata.Tide(),fileAlign));
\r
3403 sdata.SetOffset(offset);
\r
3404 sdata.SetRVA(rva);
\r
3405 offset += sdata.Size();
3406 rva = GetNextSectStart(rva,sdata.Tide());
\r
3407 initDataSize += sdata.Size();
\r
3409 if (rsrc != null) {
\r
3410 rsrc.SetSize(NumToAlign(rsrc.Tide(),fileAlign));
\r
3411 rsrc.SetOffset(offset);
\r
3413 offset += rsrc.Size();
\r
3414 rva = GetNextSectStart(rva,rsrc.Tide());
\r
3415 initDataSize += rsrc.Size();
\r
3417 relocOffset = offset;
\r
3421 internal void MakeFile() {
\r
3422 if (doDLL) hintNameTable = dllHintNameTable.ToCharArray();
\r
3423 else hintNameTable = exeHintNameTable.ToCharArray();
\r
3424 BuildTextSection();
\r
3426 BuildRelocSection();
\r
3427 // now write it out
\r
3434 private void WriteHeader() {
\r
3436 // Console.WriteLine("Writing PEHeader at offset " + Seek(0,SeekOrigin.Current));
\r
3438 // Console.WriteLine("Writing text section header at offset " + Hex.Long(Seek(0,SeekOrigin.Current)));
\r
3439 text.WriteHeader(this,relocRVA);
\r
3440 if (sdata != null) sdata.WriteHeader(this,relocRVA);
\r
3441 if (rsrc != null) rsrc.WriteHeader(this,relocRVA);
\r
3442 // Console.WriteLine("Writing reloc section header at offset " + Seek(0,SeekOrigin.Current));
\r
3443 WriteRelocSectionHeader();
\r
3444 // Console.WriteLine("Writing padding at offset " + Seek(0,SeekOrigin.Current));
\r
3445 WriteZeros(headerPadding);
\r
3448 private void WriteSections() {
\r
3449 // Console.WriteLine("Writing text section at offset " + Seek(0,SeekOrigin.Current));
\r
3450 WriteTextSection();
\r
3451 if (sdata != null) WriteSDataSection();
\r
3452 if (rsrc != null) WriteRsrcSection();
\r
3453 WriteRelocSection();
\r
3456 private void WriteIAT() {
\r
3457 Write(text.RVA() + hintNameTableOffset);
\r
3461 private void WriteImportTables() {
\r
3463 WriteZeros(importTablePadding);
\r
3464 // Console.WriteLine("Writing import tables at offset " + Hex.Long(Seek(0,SeekOrigin.Current)));
\r
3465 Write(importLookupTableOffset + text.RVA());
\r
3467 Write(runtimeEngineOffset + text.RVA());
\r
3468 Write(text.RVA()); // IAT is at the beginning of the text section
\r
3470 // Import Lookup Table
\r
3471 WriteIAT(); // lookup table and IAT are the same
\r
3472 // Hint/Name Table
\r
3473 // Console.WriteLine("Writing hintname table at " + Hex.Long(Seek(0,SeekOrigin.Current)));
\r
3474 Write(hintNameTable);
\r
3475 Write(runtimeEngineName.ToCharArray());
\r
3478 private void WriteTextSection() {
\r
3481 // Console.WriteLine("Writing code at " + Hex.Long(Seek(0,SeekOrigin.Current)));
\r
3482 metaData.WriteByteCodes(this);
\r
3483 // Console.WriteLine("Finished writing code at " + Hex.Long(Seek(0,SeekOrigin.Current)));
\r
3484 largeStrings = metaData.LargeStringsIndex();
\r
3485 largeGUID = metaData.LargeGUIDIndex();
\r
3486 largeUS = metaData.LargeUSIndex();
\r
3487 largeBlob = metaData.LargeBlobIndex();
\r
3488 metaData.WriteMetaData(this);
3489 if (reserveStrongNameSignatureSpace) {
\r
3490 WriteZeros(StrongNameSignatureSize);
3492 WriteImportTables();
\r
3493 WriteZeros(entryPointPadding);
\r
3494 Write((ushort)0x25FF);
\r
3495 Write(ImageBase + text.RVA());
\r
3496 WriteZeros(text.Padding());
\r
3499 private void WriteCLIHeader() {
\r
3500 Write(CLIHeaderSize); // Cb
\r
3501 Write((short)2); // Major runtime version
\r
3502 Write((short)0); // Minor runtime version
\r
3503 Write(text.RVA() + metaDataOffset);
\r
3504 Write(metaData.Size());
\r
3505 Write(runtimeFlags);
\r
3506 Write(entryPointToken);
\r
3507 WriteZeros(8); // Resources - used by Manifest Resources NYI
3508 // Strong Name Signature (RVA, size)
3509 if (reserveStrongNameSignatureSpace) {
\r
3510 Write(text.RVA() + strongNameSigOffset);
3511 Write(StrongNameSignatureSize);
3515 WriteZeros(8); // CodeManagerTable
\r
3516 WriteZeros(8); // VTableFixups NYI
\r
3517 WriteZeros(16); // ExportAddressTableJumps, ManagedNativeHeader
\r
3520 private void WriteSDataSection() {
\r
3521 long size = sdata.Size ();
3522 long start = BaseStream.Position;
3523 for (int i=0; i < data.Count; i++) {
\r
3524 ((DataConstant)data[i]).Write(this);
\r
3526 while (BaseStream.Position < (start + size))
3530 private void WriteRsrcSection() {
\r
3533 private void WriteRelocSection() {
\r
3534 // Console.WriteLine("Writing reloc section at " + Seek(0,SeekOrigin.Current) + " = " + relocOffset);
\r
3535 MemoryStream str = (MemoryStream)reloc.BaseStream;
\r
3536 Write(str.ToArray());
\r
3537 WriteZeros(NumToAlign((uint)str.Position,fileAlign));
\r
3540 internal void SetEntryPoint(uint entryPoint) {
\r
3541 entryPointToken = entryPoint;
\r
3544 internal void AddInitData(DataConstant cVal) {
\r
3545 if (sdata == null) {
\r
3546 sdata = new Section(sdataName,0xC0000040); // IMAGE_SCN_CNT INITIALIZED_DATA, READ, WRITE
\r
3547 data = new ArrayList();
\r
3550 cVal.DataOffset = sdata.Tide();
\r
3551 sdata.IncTide(cVal.GetSize());
\r
3554 internal void WriteZeros(uint numZeros) {
\r
3555 for (int i=0; i < numZeros; i++) {
\r
3560 internal void WritePEHeader() {
\r
3561 Write((ushort)0x014C); // Machine - always 0x14C for Managed PE Files (allow others??)
\r
3562 Write((ushort)numSections);
\r
3564 WriteZeros(8); // Pointer to Symbol Table and Number of Symbols (always zero for ECMA CLI files)
\r
3565 Write((ushort)0x00E0); // Size of Optional Header
\r
3566 Write(characteristics);
\r
3567 // PE Optional Header
\r
3568 Write((ushort)0x010B); // Magic
\r
3569 Write((byte)0x6); // LMajor pure-IL = 6 C++ = 7
\r
3570 Write((byte)0x0); // LMinor
\r
3571 Write(text.Size());
\r
3572 Write(initDataSize);
\r
3573 Write(0); // Check other sections here!!
\r
3574 Write(text.RVA() + entryPointOffset);
\r
3575 Write(text.RVA());
\r
3576 uint dataBase = 0;
\r
3577 if (sdata != null) dataBase = sdata.RVA();
\r
3578 else if (rsrc != null) dataBase = rsrc.RVA();
\r
3579 else dataBase = relocRVA;
\r
3582 Write(SectionAlignment);
\r
3584 Write((ushort)0x04); // OS Major
\r
3585 WriteZeros(6); // OS Minor, User Major, User Minor
\r
3586 Write((ushort)0x04); // SubSys Major
\r
3587 WriteZeros(6); // SybSys Minor, Reserved
\r
3589 Write(headerSize);
\r
3590 Write((int)0); // File Checksum
\r
3591 Write((ushort)subSys);
\r
3592 Write((short)0); // DLL Flags
\r
3593 Write((uint)0x100000); // Stack Reserve Size
\r
3594 Write((uint)0x1000); // Stack Commit Size
\r
3595 Write((uint)0x100000); // Heap Reserve Size
\r
3596 Write((uint)0x1000); // Heap Commit Size
\r
3597 Write(0); // Loader Flags
\r
3598 Write(0x10); // Number of Data Directories
\r
3599 WriteZeros(8); // Export Table
\r
3600 Write(importTableOffset + text.RVA());
\r
3601 Write(totalImportTableSize);
\r
3602 WriteZeros(24); // Resource, Exception and Certificate Tables
\r
3605 WriteZeros(48); // Debug, Copyright, Global Ptr, TLS, Load Config and Bound Import Tables
\r
3606 Write(text.RVA()); // IATRVA - IAT is at start of .text Section
\r
3608 WriteZeros(8); // Delay Import Descriptor
\r
3609 Write(text.RVA()+IATSize); // CLIHeader immediately follows IAT
\r
3610 Write(CLIHeaderSize);
\r
3611 WriteZeros(8); // Reserved
\r
3614 internal void WriteRelocSectionHeader() {
\r
3615 Write(relocName.ToCharArray());
\r
3619 Write(relocOffset);
\r
3621 Write(relocFlags);
\r
3624 private void Align (MemoryStream str, int val) {
\r
3625 if ((str.Position % val) != 0) {
\r
3626 for (int i=val - (int)(str.Position % val); i > 0; i--) {
\r
3632 private uint Align(uint val, uint alignVal) {
\r
3633 if ((val % alignVal) != 0) {
\r
3634 val += alignVal - (val % alignVal);
\r
3639 private uint NumToAlign(uint val, uint alignVal) {
\r
3640 if ((val % alignVal) == 0) return 0;
\r
3641 return alignVal - (val % alignVal);
\r
3644 internal void StringsIndex(uint ix) {
\r
3645 if (largeStrings) Write(ix);
\r
3646 else Write((ushort)ix);
\r
3649 internal void GUIDIndex(uint ix) {
\r
3650 if (largeGUID) Write(ix);
\r
3651 else Write((ushort)ix);
\r
3654 internal void USIndex(uint ix) {
\r
3655 if (largeUS) Write(ix);
\r
3656 else Write((ushort)ix);
\r
3659 internal void BlobIndex(uint ix) {
\r
3660 if (largeBlob) Write(ix);
\r
3661 else Write((ushort)ix);
\r
3664 internal void WriteIndex(MDTable tabIx,uint ix) {
\r
3665 if (metaData.LargeIx(tabIx)) Write(ix);
\r
3666 else Write((ushort)ix);
\r
3669 internal void WriteCodedIndex(CIx code, MetaDataElement elem) {
\r
3670 metaData.WriteCodedIndex(code,elem,this);
\r
3673 internal void WriteCodeRVA(uint offs) {
\r
3674 Write(text.RVA() + offs);
\r
3677 internal void WriteDataRVA(uint offs) {
\r
3678 Write(sdata.RVA() + offs);
\r
3681 internal void Write3Bytes(uint val) {
\r
3682 byte b3 = (byte)((val & FileImage.iByteMask[2]) >> 16);
\r
3683 byte b2 = (byte)((val & FileImage.iByteMask[1]) >> 8);;
\r
3684 byte b1 = (byte)(val & FileImage.iByteMask[0]);
\r
3690 internal bool ReserveStrongNameSignatureSpace {
3691 get { return reserveStrongNameSignatureSpace; }
3692 set { reserveStrongNameSignatureSpace = value; }
3696 /**************************************************************************/
\r
3698 /// Descriptor for a file referenced in THIS assembly/module (.file)
\r
3700 public class FileRef : MetaDataElement
\r
3702 private static readonly uint NoMetaData = 0x1;
\r
3703 uint nameIx = 0, hashIx = 0;
\r
3706 internal FileRef(string name, byte[] hashBytes, bool metaData,
\r
3707 bool entryPoint, MetaData md) {
\r
3708 if (!metaData) flags = NoMetaData;
\r
3709 if (entryPoint) md.SetEntryPoint(this);
\r
3710 nameIx = md.AddToStringsHeap(name);
\r
3711 hashIx = md.AddToBlobHeap(hashBytes);
\r
3712 tabIx = MDTable.File;
\r
3715 internal FileRef(uint nameIx, byte[] hashBytes, bool metaData,
\r
3716 bool entryPoint, MetaData md) {
\r
3717 if (!metaData) flags = NoMetaData;
\r
3718 if (entryPoint) md.SetEntryPoint(this);
\r
3719 this.nameIx = nameIx;
\r
3720 hashIx = md.AddToBlobHeap(hashBytes);
\r
3721 tabIx = MDTable.File;
\r
3724 internal sealed override uint Size(MetaData md) {
\r
3725 return 4 + md.StringsIndexSize() + md.BlobIndexSize();
\r
3728 internal sealed override void Write(FileImage output) {
\r
3729 output.Write(flags);
\r
3730 output.StringsIndex(nameIx);
\r
3731 output.BlobIndex(hashIx);
\r
3734 internal sealed override uint GetCodedIx(CIx code) {
\r
3736 case (CIx.HasCustomAttr) : return 16;
\r
3737 case (CIx.Implementation) : return 0;
\r
3743 /**************************************************************************/
\r
3745 /// Descriptor for pinvoke information for a method NOT YET IMPLEMENTED
\r
3747 public class ImplMap : MetaDataElement
\r
3749 private static readonly ushort NoMangle = 0x01;
\r
3752 string importName;
\r
3754 ModuleRef importScope;
\r
3756 internal ImplMap(ushort flag, Method implMeth, string iName, ModuleRef mScope) {
\r
3759 importName = iName;
\r
3760 importScope = mScope;
\r
3761 tabIx = MDTable.ImplMap;
\r
3762 if (iName == null) flags |= NoMangle;
\r
3763 //throw(new NotYetImplementedException("PInvoke "));
\r
3766 internal sealed override void BuildTables(MetaData md) {
\r
3768 iNameIx = md.AddToStringsHeap(importName);
\r
3772 internal sealed override uint Size(MetaData md) {
\r
3773 return 2+ md.CodedIndexSize(CIx.MemberForwarded) +
\r
3774 md.StringsIndexSize() + md.TableIndexSize(MDTable.ModuleRef);
\r
3777 internal sealed override void Write(FileImage output) {
\r
3778 output.Write(flags);
\r
3779 output.WriteCodedIndex(CIx.MemberForwarded,meth);
\r
3780 output.StringsIndex(iNameIx);
\r
3781 output.WriteIndex(MDTable.ModuleRef,importScope.Row);
\r
3786 /**************************************************************************/
\r
3788 /// Descriptor for an IL instruction
\r
3790 internal abstract class CILInstruction {
\r
3791 protected static readonly sbyte maxByteVal = 127;
\r
3792 protected static readonly sbyte minByteVal = -128;
\r
3793 protected static readonly byte leadByte = 0xFE;
\r
3794 protected static readonly uint USHeapIndex = 0x70000000;
\r
3795 protected static readonly int longInstrStart = (int)Op.arglist;
\r
3796 public bool twoByteInstr = false;
\r
3797 public uint size = 0;
\r
3798 public uint offset;
\r
3800 internal virtual bool Check(MetaData md) {
\r
3804 internal virtual void Write(FileImage output) { }
\r
3808 internal class CILByte : CILInstruction {
\r
3811 internal CILByte(byte bVal) {
\r
3816 internal override void Write(FileImage output) {
\r
3817 output.Write(byteVal);
\r
3823 internal class Instr : CILInstruction {
\r
3824 protected int instr;
\r
3826 internal Instr(int inst) {
\r
3827 if (inst >= longInstrStart) {
\r
3828 instr = inst - longInstrStart;
\r
3829 twoByteInstr = true;
\r
3837 internal override void Write(FileImage output) {
\r
3838 //Console.WriteLine("Writing instruction " + instr + " with size " + size);
\r
3839 if (twoByteInstr) output.Write(leadByte);
\r
3840 output.Write((byte)instr);
\r
3845 internal class IntInstr : Instr {
\r
3849 internal IntInstr(int inst, int num, bool byteSize) : base(inst) {
\r
3851 byteNum = byteSize;
\r
3852 if (byteNum) size++;
\r
3856 internal sealed override void Write(FileImage output) {
\r
3857 base.Write(output);
\r
3859 output.Write((sbyte)val);
\r
3861 output.Write(val);
\r
3866 internal class UIntInstr : Instr {
\r
3870 internal UIntInstr(int inst, int num, bool byteSize) : base(inst) {
\r
3872 byteNum = byteSize;
\r
3873 if (byteNum) size++;
\r
3877 internal sealed override void Write(FileImage output) {
\r
3878 base.Write(output);
\r
3880 output.Write((byte)val);
\r
3882 output.Write((ushort)val);
\r
3887 internal class LongInstr : Instr {
\r
3890 internal LongInstr(int inst, long l) : base(inst) {
\r
3895 internal sealed override void Write(FileImage output) {
\r
3896 base.Write(output);
\r
3897 output.Write(val);
\r
3902 internal class FloatInstr : Instr {
\r
3905 internal FloatInstr(int inst, float f) : base(inst) {
\r
3910 internal sealed override void Write(FileImage output) {
\r
3911 base.Write(output);
\r
3912 output.Write(fVal);
\r
3917 internal class DoubleInstr : Instr {
\r
3920 internal DoubleInstr(int inst, double d) : base(inst) {
\r
3925 internal sealed override void Write(FileImage output) {
\r
3926 base.Write(output);
\r
3927 output.Write(val);
\r
3932 internal class StringInstr : Instr {
\r
3937 internal StringInstr(int inst, string str) : base(inst) {
\r
3942 internal StringInstr (int inst, byte[] str) : base (inst) {
3947 internal sealed override bool Check(MetaData md) {
3949 strIndex = md.AddToUSHeap(val);
3951 strIndex = md.AddToUSHeap (bval);
3955 internal sealed override void Write(FileImage output) {
\r
3956 base.Write(output);
\r
3957 output.Write(USHeapIndex | strIndex);
\r
3962 internal class LabelInstr : CILInstruction {
\r
3965 internal LabelInstr(CILLabel lab) {
\r
3967 label.AddLabelInstr(this);
\r
3971 internal class FieldInstr : Instr {
\r
3974 internal FieldInstr(int inst, Field f) : base(inst) {
\r
3979 internal sealed override void Write(FileImage output) {
\r
3980 base.Write(output);
\r
3981 output.Write(field.Token());
\r
3986 internal class MethInstr : Instr {
\r
3989 internal MethInstr(int inst, Method m) : base(inst) {
\r
3994 internal sealed override void Write(FileImage output) {
\r
3995 base.Write(output);
\r
3996 output.Write(meth.Token());
\r
4001 internal class SigInstr : Instr {
\r
4002 CalliSig signature;
\r
4004 internal SigInstr(int inst, CalliSig sig) : base(inst) {
\r
4009 internal sealed override bool Check(MetaData md) {
\r
4010 md.AddToTable(MDTable.StandAloneSig,signature);
\r
4011 signature.BuildTables(md);
\r
4015 internal sealed override void Write(FileImage output) {
\r
4016 base.Write(output);
\r
4017 output.Write(signature.Token());
\r
4021 internal class TypeInstr : Instr {
\r
4022 MetaDataElement theType;
\r
4024 internal TypeInstr(int inst, Type aType, MetaData md) : base(inst) {
\r
4025 theType = aType.GetTypeSpec(md);
\r
4029 internal sealed override void Write(FileImage output) {
\r
4030 base.Write(output);
\r
4031 output.Write(theType.Token());
\r
4036 internal class BranchInstr : Instr {
\r
4038 private bool shortVer = true;
\r
4039 private static readonly byte longInstrOffset = 13;
\r
4040 private int target = 0;
\r
4042 internal BranchInstr(int inst, CILLabel dst) : base(inst) {
\r
4044 dest.AddBranch(this);
\r
4047 if (inst >= (int) BranchOp.br && inst != (int) BranchOp.leave_s) {
4053 internal sealed override bool Check(MetaData md) {
\r
4054 target = (int)dest.GetLabelOffset() - (int)(offset + size);
\r
4058 internal sealed override void Write(FileImage output) {
\r
4059 base.Write(output);
\r
4061 output.Write((sbyte)target);
\r
4063 output.Write(target);
\r
4068 internal class SwitchInstr : Instr {
\r
4070 uint numCases = 0;
\r
4072 internal SwitchInstr(int inst, CILLabel[] dsts) : base(inst) {
\r
4074 if (cases != null) numCases = (uint)cases.Length;
\r
4075 size += 4 + (numCases * 4);
\r
4076 for (int i=0; i < numCases; i++) {
\r
4077 cases[i].AddBranch(this);
\r
4081 internal sealed override void Write(FileImage output) {
\r
4082 base.Write(output);
\r
4083 output.Write(numCases);
\r
4084 for (int i=0; i < numCases; i++) {
\r
4085 int target = (int)cases[i].GetLabelOffset() - (int)(offset + size);
\r
4086 output.Write(target);
\r
4091 /**************************************************************************/
\r
4093 public class GenericParameter : MetaDataElement
\r
4095 MetaDataElement owner;
4101 internal GenericParameter (ClassDef owner, MetaData metadata,
4102 short index, string name) : this (owner, metadata, index, name, true)
4106 internal GenericParameter (MethodDef owner, MetaData metadata,
4107 short index, string name) : this (owner, metadata, index, name, true)
4111 private GenericParameter (MetaDataElement owner, MetaData metadata,
4112 short index, string name, bool nadda)
4114 this.owner = owner;
\r
4115 this.metadata = metadata;
4116 this.index = index;
\r
4117 tabIx = MDTable.GenericParam;
\r
4121 public void AddConstraint (Type constraint) {
4122 metadata.AddToTable (MDTable.GenericParamConstraint,
\r
4123 new GenericParamConstraint (this, constraint));
\r
4126 internal sealed override uint Size(MetaData md) {
\r
4127 return (uint) (4 +
\r
4128 md.CodedIndexSize(CIx.TypeOrMethodDef) +
\r
4130 md.TableIndexSize(MDTable.TypeDef));
\r
4133 internal sealed override void BuildTables(MetaData md) {
\r
4135 nameIx = md.AddToStringsHeap(name);
\r
4139 internal sealed override void Write(FileImage output) {
\r
4140 output.Write ((short) index);
\r
4141 output.Write ((short) 0);
\r
4142 output.WriteCodedIndex(CIx.TypeOrMethodDef, owner);
\r
4143 output.Write ((uint) nameIx);
\r
4144 output.WriteIndex(MDTable.TypeDef,owner.Row);
\r
4150 internal class GenericParamConstraint : MetaDataElement
\r
4152 GenericParameter param;
\r
4155 public GenericParamConstraint (GenericParameter param, Type type) {
\r
4156 this.param = param;
\r
4158 tabIx = MDTable.GenericParamConstraint;
\r
4161 internal sealed override uint Size(MetaData md) {
\r
4162 return (uint) (md.TableIndexSize(MDTable.GenericParam) +
\r
4163 md.CodedIndexSize(CIx.TypeDefOrRef));
\r
4166 internal sealed override void Write(FileImage output) {
\r
4167 output.WriteIndex(MDTable.GenericParam, param.Row);
\r
4168 output.WriteCodedIndex(CIx.TypeDefOrRef, type);
\r
4174 internal class MethodSpec : MetaDataElement
4177 GenericMethodSig g_sig;
4180 internal MethodSpec (Method meth, GenericMethodSig g_sig) {
4183 tabIx = MDTable.MethodSpec;
4186 internal sealed override void BuildTables (MetaData md) {
4188 sidx = g_sig.GetSigIx (md);
4192 internal sealed override uint Size (MetaData md) {
4193 return (uint) (md.CodedIndexSize(CIx.MethodDefOrRef) +
4194 md.BlobIndexSize ());
4197 internal sealed override void Write (FileImage output) {
4198 output.WriteCodedIndex (CIx.MethodDefOrRef, meth);
4199 output.BlobIndex (sidx);
\r
4203 /**************************************************************************/
\r
4205 /// Descriptor for interface implemented by a class
\r
4207 public class InterfaceImpl: MetaDataElement
\r
4209 ClassDef theClass;
\r
4210 Class theInterface;
\r
4212 internal InterfaceImpl(ClassDef theClass, Class theInterface) {
\r
4213 this.theClass = theClass;
\r
4214 this.theInterface = theInterface;
\r
4215 tabIx = MDTable.InterfaceImpl;
\r
4218 internal sealed override uint Size(MetaData md) {
\r
4219 return md.TableIndexSize(MDTable.TypeDef) +
\r
4220 md.CodedIndexSize(CIx.TypeDefOrRef);
\r
4223 internal sealed override void Write(FileImage output) {
\r
4224 output.WriteIndex(MDTable.TypeDef,theClass.Row);
\r
4225 output.WriteCodedIndex(CIx.TypeDefOrRef,theInterface);
\r
4228 internal sealed override uint GetCodedIx(CIx code) { return 5; }
\r
4231 /**************************************************************************/
\r
4233 /// Descriptor for a local of a method
\r
4235 public class Local
\r
4237 private static readonly byte Pinned = 0x45;
\r
4240 bool pinned = false, byref = false;
\r
4243 /// Create a new local variable
\r
4245 /// <param name="lName">name of the local variable</param>
\r
4246 /// <param name="lType">type of the local variable</param>
\r
4247 public Local(string lName, Type lType) {
\r
4253 /// Create a new local variable that is byref and/or pinned
\r
4255 /// <param name="lName">local name</param>
\r
4256 /// <param name="lType">local type</param>
\r
4257 /// <param name="byRef">is byref</param>
\r
4258 /// <param name="isPinned">has pinned attribute</param>
\r
4259 public Local(string lName, Type lType, bool byRef, bool isPinned)
\r
4264 pinned = isPinned;
\r
4267 internal void TypeSig(MemoryStream str) {
\r
4268 if (pinned) str.WriteByte(Pinned);
\r
4269 type.TypeSig(str);
\r
4273 /**************************************************************************/
\r
4275 /// Descriptor for the locals for a method
\r
4278 public class LocalSig : Signature
\r
4280 private static readonly byte LocalSigByte = 0x7;
\r
4283 public LocalSig(Local[] locals) {
\r
4284 this.locals = locals;
\r
4285 tabIx = MDTable.StandAloneSig;
\r
4288 internal sealed override void BuildTables(MetaData md) {
\r
4290 MemoryStream sig = new MemoryStream();
\r
4291 sig.WriteByte(LocalSigByte);
\r
4292 MetaData.CompressNum((uint)locals.Length,sig);
\r
4293 for (int i=0; i < locals.Length; i++) {
\r
4294 ((Local)locals[i]).TypeSig(sig);
\r
4296 sigIx = md.AddToBlobHeap(sig.ToArray());
\r
4302 /**************************************************************************/
\r
4304 /// Descriptor for resources used in this PE file NOT YET IMPLEMENTED
\r
4307 public class ManifestResource : MetaDataElement
\r
4309 private static readonly uint PublicResource = 0x1;
\r
4310 private static readonly uint PrivateResource = 0x2;
\r
4313 MetaDataElement rRef;
\r
4318 public ManifestResource(string name, bool isPub, FileRef fileRef) {
\r
4320 if (isPub) flags = PublicResource;
\r
4321 else flags = PrivateResource;
\r
4323 tabIx = MDTable.ManifestResource;
\r
4324 throw(new NotYetImplementedException("Manifest Resources "));
\r
4327 public ManifestResource(string name, bool isPub, FileRef fileRef,
\r
4330 if (isPub) flags = PublicResource;
\r
4331 else flags = PrivateResource;
\r
4333 fileOffset = fileIx;
\r
4336 public ManifestResource(string name, bool isPub, AssemblyRef assemRef) {
\r
4338 if (isPub) flags = PublicResource;
\r
4339 else flags = PrivateResource;
\r
4343 internal sealed override void BuildTables(MetaData md) {
\r
4345 nameIx = md.AddToStringsHeap(mrName);
\r
4349 internal sealed override uint Size(MetaData md) {
\r
4350 return 8 + md.StringsIndexSize() +
\r
4351 md.CodedIndexSize(CIx.Implementation);
\r
4354 internal sealed override void Write(FileImage output) {
\r
4355 output.Write(fileOffset);
\r
4356 output.Write(flags);
\r
4357 output.StringsIndex(nameIx);
\r
4358 output.WriteCodedIndex(CIx.Implementation,rRef);
\r
4361 internal sealed override uint GetCodedIx(CIx code) { return 18; }
\r
4364 /**************************************************************************/
\r
4366 /// Base class for elements in the PropertyMap, EventMap and
\r
4367 /// NestedClass MetaData tables
\r
4369 public class MapElem : MetaDataElement
\r
4373 MDTable elemTable;
\r
4375 internal MapElem(ClassDef par, uint elIx, MDTable elemTab) {
\r
4378 elemTable = elemTab;
\r
4381 internal sealed override uint Size(MetaData md) {
\r
4382 return md.TableIndexSize(MDTable.TypeDef) + md.TableIndexSize(elemTable);
\r
4385 internal sealed override void Write(FileImage output) {
\r
4386 output.WriteIndex(MDTable.TypeDef,parent.Row);
\r
4387 output.WriteIndex(elemTable,elemIx);
\r
4390 /**************************************************************************/
\r
4392 /// Base class for field/methods (member of a class)
\r
4394 public abstract class Member : MetaDataElement
\r
4396 protected string name;
\r
4397 protected uint nameIx = 0, sigIx = 0;
\r
4399 internal Member(string memName)
\r
4402 tabIx = MDTable.MemberRef;
\r
4406 /**************************************************************************/
\r
4409 /// Root (20 bytes + UTF-8 Version String + quad align padding)
\r
4410 /// StreamHeaders (8 bytes + null terminated name string + quad align padding)
\r
4412 /// #~ (always present - holds metadata tables)
\r
4413 /// #Strings (always present - holds identifier strings)
\r
4414 /// #US (Userstring heap)
\r
4415 /// #Blob (signature blobs)
\r
4416 /// #GUID (guids for assemblies or Modules)
\r
4419 public class MetaData
\r
4421 private static readonly int[] CIxShiftMap = {2,2,5,1,2,3,1,1,1,2,3,2,1};
\r
4422 private static readonly byte StringsHeapMask = 0x1;
\r
4423 private static readonly byte GUIDHeapMask = 0x2;
\r
4424 private static readonly byte BlobHeapMask = 0x4;
\r
4425 private static readonly uint MetaDataSignature = 0x424A5342;
\r
4426 private static readonly uint maxSmlIxSize = 0xFFFF;
\r
4427 private static readonly uint max1BitSmlIx = 0x7FFF;
\r
4428 private static readonly uint max2BitSmlIx = 0x3FFF;
\r
4429 private static readonly uint max3BitSmlIx = 0x1FFF;
\r
4430 private static readonly uint max5BitSmlIx = 0x7FF;
\r
4431 // NOTE: version and stream name strings MUST always be quad padded
\r
4432 private static readonly string version = "v1.0.3705\0\0\0";
\r
4433 private static readonly char[] tildeName = {'#','~','\0','\0'};
\r
4434 private static readonly char[] stringsName = {'#','S','t','r','i','n','g','s','\0','\0','\0','\0'};
\r
4435 private static readonly char[] usName = {'#','U','S','\0'};
\r
4436 private static readonly char[] guidName = {'#','G','U','I','D','\0','\0','\0'};
\r
4437 private static readonly char[] blobName = {'#','B','l','o','b','\0','\0','\0'};
\r
4438 private static readonly uint MetaDataHeaderSize = 20 + (uint)version.Length;
\r
4439 private static readonly uint TildeHeaderSize = 24;
\r
4440 private static readonly uint StreamHeaderSize = 8;
\r
4441 private static readonly uint numMetaDataTables = (int)MDTable.GenericParamConstraint + 1;
\r
4442 private static readonly uint tildeHeaderSize = 8 + (uint)tildeName.Length;
\r
4444 MetaDataStream strings, us, guid, blob;
\r
4446 MetaDataStream[] streams = new MetaDataStream[5];
\r
4447 uint numStreams = 5;
\r
4448 uint tildeTide = 0, tildePadding = 0, tildeStart = 0;
\r
4449 uint numTables = 0;
\r
4450 ArrayList[] metaDataTables = new ArrayList[numMetaDataTables];
\r
4451 ArrayList byteCodes = new ArrayList();
\r
4452 uint codeSize = 0, codeStart, byteCodePadding = 0, metaDataSize = 0;
\r
4453 ulong valid = 0, /*sorted = 0x000002003301FA00;*/ sorted = 0;
\r
4454 bool[] largeIx = new bool[numMetaDataTables];
\r
4455 bool[] lgeCIx = new bool[(int)CIx.MaxCIx];
\r
4456 bool largeStrings = false, largeUS = false, largeGUID = false, largeBlob = false;
\r
4457 private FileImage file;
\r
4458 private byte heapSizes = 0;
\r
4459 MetaDataElement entryPoint;
\r
4460 BinaryWriter output;
\r
4461 public MSCorLib mscorlib;
\r
4462 private TypeSpec[] systemTypeSpecs = new TypeSpec[PrimitiveType.NumSystemTypes];
\r
4464 private ArrayList cattr_list;
4466 internal MetaData(FileImage file) {
\r
4467 // tilde = new MetaDataStream(tildeName,false,0);
\r
4469 strings = new MetaDataStream(stringsName,new UTF8Encoding(),true);
\r
4470 us = new MetaDataStream(usName,new UnicodeEncoding(),true);
\r
4471 guid = new MetaDataStream(guidName,false);
\r
4472 blob = new MetaDataStream(blobName,true);
\r
4473 streams[1] = strings;
\r
4475 streams[3] = guid;
\r
4476 streams[4] = blob;
\r
4477 for (int i=0; i < numMetaDataTables; i++) {
\r
4478 largeIx[i] = false;
\r
4480 for (int i=0; i < lgeCIx.Length; i++) {
\r
4481 lgeCIx[i] = false;
\r
4483 mscorlib = new MSCorLib(this);
\r
4486 internal TypeSpec GetPrimitiveTypeSpec(int ix) {
\r
4487 return systemTypeSpecs[ix];
\r
4490 internal void SetPrimitiveTypeSpec(int ix, TypeSpec typeSpec) {
\r
4491 systemTypeSpecs[ix] = typeSpec;
\r
4494 internal uint Size() {
\r
4495 return metaDataSize;
\r
4499 private void CalcHeapSizes ()
4501 if (strings.LargeIx()) {
\r
4502 largeStrings = true;
\r
4503 heapSizes |= StringsHeapMask;
\r
4505 if (guid.LargeIx()) {
\r
4507 heapSizes |= GUIDHeapMask;
\r
4509 if (blob.LargeIx()) {
\r
4511 heapSizes |= BlobHeapMask;
\r
4514 largeUS = us.LargeIx();
\r
4517 internal void StreamSize(byte mask) {
\r
4518 heapSizes |= mask;
\r
4521 internal uint AddToUSHeap(string str) {
\r
4522 if (str == null) return 0;
\r
4523 return us.Add(str,true);
\r
4526 internal uint AddToUSHeap(byte[] str) {
4527 if (str == null) return 0;
4528 return us.Add (str, true);
4531 internal uint AddToStringsHeap(string str) {
\r
4532 if ((str == null) || (str.CompareTo("") == 0)) return 0;
\r
4533 return strings.Add(str,false);
\r
4536 internal uint AddToGUIDHeap(Guid guidNum) {
\r
4537 return guid.Add(guidNum, false);
\r
4540 internal uint AddToBlobHeap(byte[] blobBytes) {
\r
4541 if (blobBytes == null) return 0;
\r
4542 return blob.Add(blobBytes, true);
\r
4545 internal uint AddToBlobHeap(byte val) {
\r
4546 return blob.Add(val, true);
\r
4549 internal uint AddToBlobHeap(sbyte val) {
\r
4550 return blob.Add(val, true);
\r
4553 internal uint AddToBlobHeap(ushort val) {
\r
4554 return blob.Add(val, true);
\r
4557 internal uint AddToBlobHeap(short val) {
\r
4558 return blob.Add(val, true);
\r
4561 internal uint AddToBlobHeap(uint val) {
\r
4562 return blob.Add(val, true);
\r
4565 internal uint AddToBlobHeap(int val) {
\r
4566 return blob.Add(val, true);
\r
4569 internal uint AddToBlobHeap(ulong val) {
\r
4570 return blob.Add(val, true);
\r
4573 internal uint AddToBlobHeap(long val) {
\r
4574 return blob.Add(val, true);
\r
4577 internal uint AddToBlobHeap(float val) {
\r
4578 return blob.Add(val, true);
\r
4581 internal uint AddToBlobHeap(double val) {
\r
4582 return blob.Add(val, true);
\r
4585 internal uint AddToBlobHeap(string val) {
\r
4586 return blob.Add(val,true);
\r
4589 internal void AddCustomAttribute (CustomAttribute cattr)
4591 if (cattr_list == null)
4592 cattr_list = new ArrayList ();
4593 cattr_list.Add (cattr);
4596 private ArrayList GetTable(MDTable tableIx) {
\r
4597 int tabIx = (int)tableIx;
\r
4598 if (metaDataTables[tabIx] == null) {
\r
4599 metaDataTables[tabIx] = new ArrayList();
\r
4600 valid |= ((ulong)0x1 << tabIx);
\r
4601 // Console.WriteLine("after creating table " + tableIx + "(" + tabIx + ") valid = " + valid);
\r
4604 return metaDataTables[tabIx];
\r
4607 internal void AddToTable(MDTable tableIx, MetaDataElement elem) {
\r
4608 if (elem.Row > 0) {
\r
4609 // Console.Out.WriteLine("ERROR - element already in table " + tableIx);
\r
4612 // updates Row field of the element
\r
4613 // Console.WriteLine("Adding element to table " + (uint)tableIx);
\r
4614 ArrayList table = GetTable(tableIx);
\r
4615 elem.Row = (uint)table.Count + 1;
\r
4619 internal uint TableIndex(MDTable tableIx) {
\r
4620 if (metaDataTables[(int)tableIx] == null) return 1;
\r
4621 return (uint)metaDataTables[(int)tableIx].Count+1;
\r
4624 internal uint AddCode(CILInstructions byteCode) {
\r
4625 byteCodes.Add(byteCode);
\r
4626 uint offset = codeSize + codeStart;
\r
4627 codeSize += byteCode.GetCodeSize();
\r
4631 internal void SetEntryPoint(MetaDataElement ep) {
\r
4635 internal void AddData(DataConstant cVal) {
\r
4636 file.AddInitData(cVal);
\r
4639 internal static void CompressNum(uint val, MemoryStream sig) {
\r
4641 sig.WriteByte((byte)val);
\r
4642 } else if (val < 0x3FFF) {
\r
4643 byte b1 = (byte)((val >> 8) | 0x80);
\r
4644 byte b2 = (byte)(val & FileImage.iByteMask[0]);
\r
4645 sig.WriteByte(b1);
\r
4646 sig.WriteByte(b2);
\r
4648 byte b1 = (byte)((val >> 24) | 0xC0);
\r
4649 byte b2 = (byte)((val & FileImage.iByteMask[2]) >> 16);
\r
4650 byte b3 = (byte)((val & FileImage.iByteMask[1]) >> 8);;
\r
4651 byte b4 = (byte)(val & FileImage.iByteMask[0]);
\r
4652 sig.WriteByte(b1);
\r
4653 sig.WriteByte(b2);
\r
4654 sig.WriteByte(b3);
\r
4655 sig.WriteByte(b4);
\r
4659 internal uint CodeSize() {
\r
4660 return codeSize + byteCodePadding;
\r
4663 internal uint StringsIndexSize() {
\r
4664 if (largeStrings) return 4;
\r
4668 internal uint GUIDIndexSize() {
\r
4669 if (largeGUID) return 4;
\r
4673 internal uint USIndexSize() {
\r
4674 if (largeUS) return 4;
\r
4678 internal uint BlobIndexSize() {
\r
4679 if (largeBlob) return 4;
\r
4683 internal uint CodedIndexSize(CIx code) {
\r
4684 if (lgeCIx[(uint)code]) return 4;
\r
4688 internal uint TableIndexSize(MDTable tabIx) {
\r
4689 if (largeIx[(uint)tabIx]) return 4;
\r
4693 private void SetIndexSizes() {
\r
4694 for (int i=0; i < numMetaDataTables; i++) {
\r
4695 if (metaDataTables[i] == null)
4698 uint count = (uint)metaDataTables[i].Count;
\r
4699 if (count > maxSmlIxSize)
4700 largeIx[i] = true;
\r
4702 MDTable tabIx = (MDTable)i;
\r
4703 if (count > max5BitSmlIx) {
\r
4704 lgeCIx[(int)CIx.HasCustomAttr] = true;
\r
4706 if (count > max3BitSmlIx) {
\r
4707 if ((tabIx == MDTable.TypeRef) || (tabIx == MDTable.ModuleRef) || (tabIx == MDTable.Method) || (tabIx == MDTable.TypeSpec) || (tabIx == MDTable.Field))
\r
4708 lgeCIx[(int)CIx.CustomAttributeType] = true;
\r
4709 if ((tabIx == MDTable.Method) || (tabIx == MDTable.MemberRef))
\r
4710 lgeCIx[(int)CIx.MemberRefParent] = true;
\r
4712 if (count > max2BitSmlIx) {
\r
4713 if ((tabIx == MDTable.Field) || (tabIx == MDTable.Param) || (tabIx == MDTable.Property))
\r
4714 lgeCIx[(int)CIx.HasConst] = true;
\r
4715 if ((tabIx == MDTable.TypeDef) || (tabIx == MDTable.TypeRef) || (tabIx == MDTable.TypeSpec))
\r
4716 lgeCIx[(int)CIx.TypeDefOrRef] = true;
\r
4717 if ((tabIx == MDTable.TypeDef) || (tabIx == MDTable.Method) || (tabIx == MDTable.Assembly))
\r
4718 lgeCIx[(int)CIx.HasDeclSecurity] = true;
\r
4719 if ((tabIx == MDTable.File) || (tabIx == MDTable.AssemblyRef) || (tabIx == MDTable.ExportedType))
\r
4720 lgeCIx[(int)CIx.Implementation] = true;
\r
4721 if ((tabIx == MDTable.Module) || (tabIx == MDTable.ModuleRef) || (tabIx == MDTable.AssemblyRef) || (tabIx == MDTable.TypeRef))
\r
4722 lgeCIx[(int)CIx.ResolutionScope] = true;
\r
4724 if (count > max1BitSmlIx) {
\r
4725 if ((tabIx == MDTable.Field) || (tabIx == MDTable.Param))
\r
4726 lgeCIx[(int)CIx.HasFieldMarshal] = true;
\r
4727 if ((tabIx == MDTable.Event) || (tabIx == MDTable.Property))
\r
4728 lgeCIx[(int)CIx.HasSemantics] = true;
\r
4729 if ((tabIx == MDTable.Method) || (tabIx == MDTable.MemberRef))
\r
4730 lgeCIx[(int)CIx.MethodDefOrRef] = true;
\r
4731 if ((tabIx == MDTable.Field) || (tabIx == MDTable.Method))
\r
4732 lgeCIx[(int)CIx.MemberForwarded] = true;
\r
4733 if ((tabIx == MDTable.TypeDef) || (tabIx == MDTable.Method))
\r
4734 lgeCIx[(int)CIx.TypeOrMethodDef] = true;
\r
4739 private void SetStreamOffsets() {
\r
4740 uint sizeOfHeaders = StreamHeaderSize + (uint)tildeName.Length;
\r
4741 for (int i=1; i < numStreams; i++) {
\r
4742 sizeOfHeaders += streams[i].headerSize();
\r
4744 metaDataSize = MetaDataHeaderSize + sizeOfHeaders;
\r
4745 tildeStart = metaDataSize;
\r
4746 metaDataSize += tildeTide + tildePadding;
\r
4747 for (int i=1; i < numStreams; i++) {
\r
4748 streams[i].Start = metaDataSize;
\r
4749 metaDataSize += streams[i].Size();
\r
4750 streams[i].WriteDetails();
\r
4754 internal void CalcTildeStreamSize() {
\r
4756 //tilde.SetIndexSizes(strings.LargeIx(),us.LargeIx(),guid.LargeIx(),blob.LargeIx());
\r
4757 tildeTide = TildeHeaderSize;
\r
4758 tildeTide += 4 * numTables;
\r
4759 //Console.WriteLine("Tilde header + sizes = " + tildeTide);
\r
4760 for (int i=0; i < numMetaDataTables; i++) {
\r
4761 if (metaDataTables[i] != null) {
\r
4762 ArrayList table = metaDataTables[i];
\r
4763 // Console.WriteLine("Meta data table " + i + " at offset " + tildeTide);
\r
4764 tildeTide += (uint)table.Count * ((MetaDataElement)table[0]).Size(this);
\r
4765 // Console.WriteLine("Metadata table " + i + " has size " + table.Count);
\r
4766 // Console.WriteLine("tildeTide = " + tildeTide);
\r
4769 if ((tildeTide % 4) != 0) tildePadding = 4 - (tildeTide % 4);
\r
4770 //Console.WriteLine("tildePadding = " + tildePadding);
\r
4773 internal void WriteTildeStream(FileImage output) {
\r
4774 long startTilde = output.Seek(0,SeekOrigin.Current);
\r
4775 output.Write((uint)0); // Reserved
\r
4776 output.Write((byte)1); // MajorVersion
\r
4777 output.Write((byte)0); // MinorVersion
\r
4778 output.Write(heapSizes);
\r
4779 output.Write((byte)1); // Reserved
\r
4780 output.Write(valid);
\r
4781 output.Write(sorted);
\r
4782 for (int i=0; i < numMetaDataTables; i++) {
\r
4783 if (metaDataTables[i] != null) {
\r
4784 uint count = (uint)metaDataTables[i].Count;
\r
4785 output.Write(count);
\r
4788 long tabStart = output.Seek(0,SeekOrigin.Current);
\r
4789 // Console.WriteLine("Starting metaData tables at " + tabStart);
\r
4790 for (int i=0; i < numMetaDataTables; i++) {
\r
4791 if (metaDataTables[i] != null) {
\r
4792 // Console.WriteLine("Starting metaData table " + i + " at " + (output.Seek(0,SeekOrigin.Current) - startTilde));
\r
4793 ArrayList table = metaDataTables[i];
\r
4794 for (int j=0; j < table.Count; j++) {
\r
4795 ((MetaDataElement)table[j]).Write(output);
\r
4799 // Console.WriteLine("Writing padding at " + output.Seek(0,SeekOrigin.Current));
\r
4800 for (int i=0; i < tildePadding; i++) output.Write((byte)0);
\r
4803 private void BuildTable(ArrayList table) {
\r
4804 if (table == null) return;
\r
4805 for (int j=0; j < table.Count; j++) {
\r
4806 ((MetaDataElement)table[j]).BuildTables(this);
\r
4810 internal void BuildMetaData(uint codeStartOffset) {
\r
4811 codeStart = codeStartOffset;
\r
4812 BuildTable(metaDataTables[(int)MDTable.TypeDef]);
\r
4813 BuildTable(metaDataTables[(int)MDTable.MemberRef]);
\r
4814 BuildTable(metaDataTables[(int)MDTable.GenericParam]);
\r
4815 BuildTable(metaDataTables[(int)MDTable.MethodSpec]);
\r
4816 BuildTable(metaDataTables[(int)MDTable.GenericParamConstraint]);
\r
4818 if (cattr_list != null) {
4819 foreach (CustomAttribute cattr in cattr_list)
4820 cattr.BuildTables (this);
4823 /* for (int i=0; i < metaDataTables.Length; i++) {
\r
4824 ArrayList table = metaDataTables[i];
\r
4825 if (table != null) {
\r
4826 for (int j=0; j < table.Count; j++) {
\r
4827 ((MetaDataElement)table[j]).BuildTables(this);
\r
4834 for (int i=1; i < numStreams; i++) {
\r
4835 streams[i].EndStream();
\r
4837 CalcTildeStreamSize();
\r
4838 SetStreamOffsets();
\r
4839 byteCodePadding = NumToAlign(codeSize,4);
\r
4840 if (entryPoint != null) file.SetEntryPoint(entryPoint.Token());
\r
4843 internal void WriteByteCodes(FileImage output) {
\r
4844 for (int i=0; i < byteCodes.Count; i++) {
\r
4845 ((CILInstructions)byteCodes[i]).Write(output);
\r
4847 for (int i=0; i < byteCodePadding; i++) {
\r
4848 output.Write((byte)0);
\r
4852 internal void WriteMetaData(FileImage output) {
\r
4853 this.output = output;
\r
4854 mdStart = output.Seek(0,SeekOrigin.Current);
\r
4855 // Console.WriteLine("Writing metaData at " + Hex.Long(mdStart));
\r
4856 output.Write(MetaDataSignature);
\r
4857 output.Write((short)1); // Major Version
\r
4858 output.Write((short)1); // Minor Version ECMA = 0, PEFiles = 1
\r
4859 output.Write(0); // Reserved
\r
4860 output.Write(version.Length);
\r
4861 output.Write(version.ToCharArray()); // version string is already zero padded
\r
4862 output.Write((short)0);
\r
4863 output.Write((ushort)numStreams);
\r
4864 // write tilde header
\r
4865 output.Write(tildeStart);
\r
4866 output.Write(tildeTide + tildePadding);
\r
4867 output.Write(tildeName);
\r
4868 for (int i=1; i < numStreams; i++) streams[i].WriteHeader(output);
\r
4869 // Console.WriteLine("Writing tilde stream at " + output.Seek(0,SeekOrigin.Current) + " = " + tildeStart);
\r
4870 WriteTildeStream(output);
\r
4871 for (int i=1; i < numStreams; i++) streams[i].Write(output);
\r
4872 // Console.WriteLine("Finished Writing metaData at " + output.Seek(0,SeekOrigin.Current));
\r
4875 internal bool LargeStringsIndex() { return strings.LargeIx(); }
\r
4876 internal bool LargeGUIDIndex() { return guid.LargeIx(); }
\r
4877 internal bool LargeUSIndex() { return us.LargeIx(); }
\r
4878 internal bool LargeBlobIndex() { return blob.LargeIx(); }
\r
4880 internal bool LargeIx(MDTable tabIx) { return largeIx[(uint)tabIx]; }
\r
4883 private uint NumToAlign(uint val, uint alignVal) {
\r
4884 if ((val % alignVal) == 0) return 0;
\r
4885 return alignVal - (val % alignVal);
\r
4888 internal void WriteCodedIndex(CIx code, MetaDataElement elem, FileImage output) {
\r
4890 if (elem != null) {
\r
4891 ix = (elem.Row << CIxShiftMap[(uint)code]) | elem.GetCodedIx(code);
\r
4892 // Console.WriteLine("coded index = " + ix + " row = " + elem.Row);
\r
4894 // Console.WriteLine("elem for coded index is null");
\r
4896 if (lgeCIx[(uint)code])
\r
4899 output.Write((ushort)ix);
\r
4903 /**************************************************************************/
\r
4905 /// Base class for all Meta Data table elements
\r
4908 public abstract class MetaDataElement
\r
4911 protected ArrayList customAttributes;
\r
4912 private uint row = 0;
\r
4913 protected bool done = false;
\r
4914 protected MDTable tabIx;
\r
4916 internal MetaDataElement() { }
\r
4923 if (row == 0) row = value;
\r
4927 internal virtual uint GetCodedIx(CIx code) { return 0; }
\r
4930 /// Add a custom attribute to this item
\r
4932 /// <param name="ctorMeth">the constructor method for this attribute</param>
\r
4933 /// <param name="val">the byte value of the parameters</param>
\r
4934 public void AddCustomAttribute(Method ctorMeth, byte[] val) {
\r
4935 if (customAttributes == null) {
\r
4936 customAttributes = new ArrayList();
\r
4938 customAttributes.Add(new CustomAttribute(this,ctorMeth,val));
\r
4942 /// Add a custom attribute to this item
\r
4944 /// <param name="ctorMeth">the constructor method for this attribute</param>
\r
4945 /// <param name="val">the constant values of the parameters</param>
\r
4946 public void AddCustomAttribute(Method ctorMeth, Constant[] cVals) {
\r
4947 if (customAttributes == null) {
\r
4948 customAttributes = new ArrayList();
\r
4950 // customAttributes.Add(new CustomAttribute(this,ctorMeth,cVals));
\r
4953 internal uint Token() {
\r
4954 return (((uint)tabIx << 24) | row);
\r
4957 internal virtual void BuildTables(MetaData md) {
\r
4961 internal virtual uint Size(MetaData md) {
\r
4965 internal virtual void Write(FileImage output) { }
\r
4968 /**************************************************************************/
\r
4970 /// Stream in the Meta Data (#Strings, #US, #Blob and #GUID)
\r
4973 internal class MetaDataStream : BinaryWriter
\r
4975 private static readonly uint StreamHeaderSize = 8;
\r
4976 private static uint maxSmlIxSize = 0xFFFF;
\r
4978 private uint start = 0;
\r
4979 uint size = 0, tide = 1;
\r
4980 bool largeIx = false;
\r
4981 uint sizeOfHeader;
\r
4983 Hashtable htable = new Hashtable();
4984 Hashtable btable = new Hashtable (new ByteArrayHashCodeProvider (), new ByteArrayComparer ());
4986 internal MetaDataStream(char[] name, bool addInitByte) : base(new MemoryStream()) {
\r
4987 if (addInitByte) { Write((byte)0); size = 1; }
\r
4989 sizeOfHeader = StreamHeaderSize + (uint)name.Length;
\r
4992 internal MetaDataStream(char[] name, System.Text.Encoding enc, bool addInitByte) : base(new MemoryStream(),enc) {
\r
4993 if (addInitByte) { Write((byte)0); size = 1; }
\r
4995 sizeOfHeader = StreamHeaderSize + (uint)name.Length;
\r
4998 public uint Start {
\r
5007 internal uint headerSize() {
\r
5008 // Console.WriteLine(name + " stream has headersize of " + sizeOfHeader);
\r
5009 return sizeOfHeader;
\r
5012 internal void SetSize(uint siz) {
\r
5016 internal uint Size() {
\r
5020 internal bool LargeIx() {
\r
5024 internal void WriteDetails() {
\r
5025 // Console.WriteLine(name + " - size = " + size);
\r
5028 internal uint Add(string str, bool prependSize) {
\r
5029 Object val = htable[str];
\r
5031 if (val == null) {
\r
5033 htable[str] = index;
\r
5034 char[] arr = str.ToCharArray();
\r
5035 if (prependSize) CompressNum((uint)arr.Length*2+1);
\r
5038 size = (uint)Seek(0,SeekOrigin.Current);
\r
5040 index = (uint)val;
\r
5044 internal uint Add (byte[] str, bool prependSize) {
5045 Object val = btable [str];
5049 btable [str] = index;
5050 if (prependSize) CompressNum ((uint) str.Length);
5052 size = (uint) Seek (0, SeekOrigin.Current);
5060 internal uint Add(Guid guid, bool prependSize) {
\r
5061 byte [] b = guid.ToByteArray ();
5062 if (prependSize) CompressNum ((uint) b.Length);
5063 Write(guid.ToByteArray());
\r
5064 size =(uint)Seek(0,SeekOrigin.Current);
\r
5068 internal uint Add(byte[] blob) {
\r
5070 CompressNum((uint)blob.Length);
5072 size = (uint)Seek(0,SeekOrigin.Current);
\r
5076 internal uint Add(byte val, bool prependSize) {
\r
5078 if (prependSize) CompressNum (1);
5080 size = (uint)Seek(0,SeekOrigin.Current);
\r
5084 internal uint Add(sbyte val, bool prependSize) {
\r
5086 if (prependSize) CompressNum (1);
5088 size = (uint)Seek(0,SeekOrigin.Current);
\r
5092 internal uint Add(ushort val, bool prependSize) {
\r
5094 if (prependSize) CompressNum (2);
5096 size = (uint)Seek(0,SeekOrigin.Current);
\r
5100 internal uint Add(short val, bool prependSize) {
\r
5102 if (prependSize) CompressNum (2);
5104 size = (uint)Seek(0,SeekOrigin.Current);
\r
5108 internal uint Add(uint val, bool prependSize) {
\r
5110 if (prependSize) CompressNum (4);
5112 size = (uint)Seek(0,SeekOrigin.Current);
\r
5116 internal uint Add(int val, bool prependSize) {
\r
5118 if (prependSize) CompressNum (4);
5120 size = (uint)Seek(0,SeekOrigin.Current);
\r
5124 internal uint Add(ulong val, bool prependSize) {
\r
5126 if (prependSize) CompressNum (8);
5128 size = (uint)Seek(0,SeekOrigin.Current);
\r
5132 internal uint Add(long val, bool prependSize) {
\r
5134 if (prependSize) CompressNum (8);
5136 size = (uint)Seek(0,SeekOrigin.Current);
\r
5140 internal uint Add(float val, bool prependSize) {
\r
5142 if (prependSize) CompressNum (4);
5144 size = (uint)Seek(0,SeekOrigin.Current);
\r
5148 internal uint Add(double val, bool prependSize) {
\r
5150 if (prependSize) CompressNum (8);
5152 size = (uint)Seek(0,SeekOrigin.Current);
\r
5156 private void CompressNum(uint val) {
\r
5159 } else if (val < 0x3FFF) {
\r
5160 byte b1 = (byte)((val >> 8) | 0x80);
\r
5161 byte b2 = (byte)(val & FileImage.iByteMask[0]);
\r
5165 byte b1 = (byte)((val >> 24) | 0xC0);
\r
5166 byte b2 = (byte)((val & FileImage.iByteMask[2]) >> 16);
\r
5167 byte b3 = (byte)((val & FileImage.iByteMask[1]) >> 8);;
\r
5168 byte b4 = (byte)(val & FileImage.iByteMask[0]);
\r
5176 private void QuadAlign() {
\r
5177 if ((size % 4) != 0) {
\r
5178 uint pad = 4 - (size % 4);
\r
5180 for (int i=0; i < pad; i++) {
\r
5186 internal void EndStream() {
\r
5188 if (size > maxSmlIxSize) {
\r
5193 internal void WriteHeader(BinaryWriter output) {
\r
5194 output.Write(start);
\r
5195 output.Write(size);
\r
5196 output.Write(name);
\r
5199 internal virtual void Write(BinaryWriter output) {
\r
5200 // Console.WriteLine("Writing " + name + " stream at " + output.Seek(0,SeekOrigin.Current) + " = " + start);
\r
5201 MemoryStream str = (MemoryStream)BaseStream;
\r
5202 output.Write(str.ToArray());
\r
5206 /**************************************************************************/
\r
5208 /// Base class for Method Descriptors
\r
5211 public abstract class Method : Member
\r
5213 protected CallConv callConv = CallConv.Default;
\r
5214 protected Type retType;
\r
5216 internal Method(string methName, Type rType) : base(methName)
\r
5222 /// Add calling conventions to this method descriptor
\r
5224 /// <param name="cconv"></param>
\r
5225 public void AddCallConv(CallConv cconv) {
\r
5226 callConv |= cconv;
\r
5229 internal abstract void TypeSig(MemoryStream sig);
\r
5231 internal uint GetSigIx(MetaData md) {
\r
5232 MemoryStream sig = new MemoryStream();
\r
5234 return md.AddToBlobHeap(sig.ToArray());
\r
5237 internal Type GetRetType() {
\r
5242 /**************************************************************************/
\r
5244 /// Descriptor for a method defined in THIS assembly/module
\r
5248 public class MethodDef : Method
\r
5250 private static readonly ushort PInvokeImpl = 0x2000;
\r
5251 //private static readonly uint UnmanagedExport = 0x0008;
\r
5252 // private static readonly byte LocalSigByte = 0x7;
\r
5253 uint parIx = 0, textOffset = 0;
\r
5255 MetaData metaData;
\r
5256 CILInstructions code;
\r
5257 ArrayList securityActions = new ArrayList();
\r
5261 ushort methFlags = 0, implFlags = 0;
\r
5262 int maxStack = 0, numPars = 0;
\r
5263 bool entryPoint = false;
\r
5264 LocalSig localSig;
\r
5265 ArrayList varArgSigList;
\r
5266 ImplMap pinvokeImpl;
\r
5269 internal MethodDef(MetaData md, string name, Type retType, Param[] pars) : base(name,retType) {
\r
5272 if (parList != null) numPars = parList.Length;
\r
5273 tabIx = MDTable.Method;
\r
5276 internal MethodDef(MetaData md, MethAttr mAttrSet, ImplAttr iAttrSet, string name, Type retType, Param[] pars) : base(name,retType) {
\r
5279 if (parList != null) numPars = parList.Length;
\r
5280 // Console.WriteLine("Creating method " + name + " with " + numPars + " parameters");
\r
5281 methFlags = (ushort)mAttrSet;
\r
5282 implFlags = (ushort)iAttrSet;
\r
5283 tabIx = MDTable.Method;
\r
5286 internal Param[] GetPars() {
\r
5291 /// Add some attributes to this method descriptor
\r
5293 /// <param name="ma">the attributes to be added</param>
\r
5294 public void AddMethAttribute(MethAttr ma) {
\r
5295 methFlags |= (ushort)ma;
\r
5299 /// Add some implementation attributes to this method descriptor
\r
5301 /// <param name="ia">the attributes to be added</param>
\r
5302 public void AddImplAttribute(ImplAttr ia) {
\r
5303 implFlags |= (ushort)ia;
\r
5306 public void AddPInvokeInfo(ModuleRef scope, string methName,
\r
5307 PInvokeAttr callAttr) {
\r
5308 pinvokeImpl = new ImplMap((ushort)callAttr,this,methName,scope);
\r
5309 methFlags |= PInvokeImpl;
\r
5313 /// Add a named generic type parameter
\r
5315 public GenericParameter AddGenericParameter (short index, string name) {
\r
5316 GenericParameter gp = new GenericParameter (this, metaData, index, name);
5317 metaData.AddToTable (MDTable.GenericParam, gp);
\r
5322 /// Set the maximum stack height for this method
\r
5324 /// <param name="maxStack">the maximum height of the stack</param>
\r
5325 public void SetMaxStack(int maxStack) {
\r
5326 this.maxStack = maxStack;
\r
5330 /// Add local variables to this method
\r
5332 /// <param name="locals">the locals to be added</param>
\r
5333 /// <param name="initLocals">are locals initialised to default values</param>
\r
5334 public void AddLocals(Local[] locals, bool initLocals) {
\r
5335 this.locals = locals;
\r
5336 this.initLocals = initLocals;
\r
5340 /// Mark this method as having an entry point
\r
5342 public void DeclareEntryPoint() {
\r
5343 entryPoint = true;
\r
5347 /// Create a code buffer for this method to add the IL instructions to
\r
5349 /// <returns>a buffer for this method's IL instructions</returns>
\r
5350 public CILInstructions CreateCodeBuffer() {
\r
5351 code = new CILInstructions(metaData);
\r
5356 /// Make a method reference descriptor for this method to be used
\r
5357 /// as a callsite signature for this vararg method
\r
5359 /// <param name="optPars">the optional pars for the vararg method call</param>
\r
5360 /// <returns></returns>
\r
5361 public MethodRef MakeVarArgSignature(Type[] optPars) {
\r
5362 Type[] pars = new Type[numPars];
\r
5363 MethodRef varArgSig;
\r
5364 for (int i=0; i < numPars; i++) {
\r
5365 pars[i] = parList[i].GetParType();
\r
5367 varArgSig = new MethodRef(this,name,retType,pars,true,optPars);
\r
5369 if (varArgSigList == null)
\r
5370 varArgSigList = new ArrayList ();
\r
5371 varArgSigList.Add (varArgSig);
\r
5375 internal sealed override void TypeSig(MemoryStream sig) {
\r
5376 sig.WriteByte((byte)callConv);
\r
5377 MetaData.CompressNum((uint)numPars,sig);
\r
5378 retType.TypeSig(sig);
\r
5379 for (ushort i=0; i < numPars; i++) {
\r
5380 parList[i].seqNo = (ushort)(i+1);
\r
5381 parList[i].TypeSig(sig);
\r
5385 internal sealed override void BuildTables(MetaData md) {
\r
5387 if (pinvokeImpl != null) {
\r
5388 md.AddToTable(MDTable.ImplMap,pinvokeImpl);
\r
5389 pinvokeImpl.BuildTables(md);
\r
5391 if (entryPoint) md.SetEntryPoint(this);
\r
5392 uint locToken = 0;
\r
5393 if (locals != null) {
\r
5394 localSig = new LocalSig(locals);
\r
5395 md.AddToTable(MDTable.StandAloneSig,localSig);
\r
5396 localSig.BuildTables(md);
\r
5397 locToken = localSig.Token();
\r
5399 if (code != null) {
\r
5400 code.CheckCode(locToken,initLocals,maxStack);
\r
5401 textOffset = md.AddCode(code);
\r
5403 nameIx = md.AddToStringsHeap(name);
\r
5404 sigIx = GetSigIx(md);
\r
5405 parIx = md.TableIndex(MDTable.Param);
\r
5406 for (int i=0; i < numPars; i++) {
\r
5407 md.AddToTable(MDTable.Param,parList[i]);
\r
5408 parList[i].BuildTables(md);
\r
5410 if (varArgSigList != null) {
\r
5411 foreach (MethodRef varArgSig in varArgSigList) {
\r
5412 md.AddToTable(MDTable.MemberRef,varArgSig);
\r
5413 varArgSig.BuildTables(md);
\r
5416 // Console.WriteLine("method has " + numPars + " parameters");
\r
5420 internal sealed override uint Size(MetaData md) {
\r
5421 return 8 + md.StringsIndexSize() + md.BlobIndexSize() + md.TableIndexSize(MDTable.Param);
\r
5424 internal sealed override void Write(FileImage output) {
\r
5425 if (ZeroRva ()) output.Write(0);
\r
5426 else output.WriteCodeRVA(textOffset);
\r
5427 output.Write(implFlags);
\r
5428 output.Write(methFlags);
\r
5429 output.StringsIndex(nameIx);
\r
5430 output.BlobIndex(sigIx);
\r
5431 output.WriteIndex(MDTable.Param,parIx);
\r
5434 internal bool ZeroRva () {
5435 return (((methFlags & (ushort)MethAttr.Abstract) != 0) ||
5436 ((implFlags & (ushort)ImplAttr.Runtime) != 0) ||
5437 ((implFlags & (ushort)ImplAttr.InternalCall) != 0) ||
5438 (pinvokeImpl != null)); // TODO: Not entirely true but works for now
5441 internal sealed override uint GetCodedIx(CIx code) {
\r
5443 case (CIx.HasCustomAttr) : return 0;
\r
5444 case (CIx.HasDeclSecurity) : return 1;
\r
5445 case (CIx.MemberRefParent) : return 3;
\r
5446 case (CIx.MethodDefOrRef) : return 0;
\r
5447 case (CIx.MemberForwarded) : return 1;
\r
5448 case (CIx.CustomAttributeType) : return 2;
\r
5449 case (CIx.TypeOrMethodDef) : return 1;
\r
5455 /**************************************************************************/
\r
5457 /// Descriptor for an overriding method (.override)
\r
5459 public class MethodImpl : MetaDataElement
\r
5462 Method header, body;
\r
5464 internal MethodImpl(ClassDef par, Method decl, Method bod) {
\r
5468 tabIx = MDTable.MethodImpl;
\r
5471 internal sealed override uint Size(MetaData md) {
\r
5472 return md.TableIndexSize(MDTable.TypeDef) + 2 * md.CodedIndexSize(CIx.MethodDefOrRef);
\r
5475 internal sealed override void Write(FileImage output) {
\r
5476 output.WriteIndex(MDTable.TypeDef,parent.Row);
\r
5477 output.WriteCodedIndex(CIx.MethodDefOrRef,body);
\r
5478 output.WriteCodedIndex(CIx.MethodDefOrRef,header);
\r
5482 /**************************************************************************/
\r
5484 /// Descriptor for a method defined in another assembly/module
\r
5486 public class MethodRef : Method
\r
5488 private static readonly byte Sentinel = 0x41;
\r
5489 Type[] parList, optParList;
\r
5490 MetaDataElement parent;
\r
5491 uint numPars = 0, numOptPars = 0;
\r
5493 internal MethodRef(MetaDataElement paren, string name, Type retType,
\r
5494 Type[] pars, bool varArgMeth, Type[] optPars) : base(name,retType) {
\r
5497 if (parList != null) numPars = (uint)parList.Length;
\r
5499 optParList = optPars;
\r
5500 if (optParList != null) numOptPars = (uint)optParList.Length;
\r
5501 callConv = CallConv.Vararg;
\r
5505 internal sealed override void TypeSig(MemoryStream sig) {
\r
5506 sig.WriteByte((byte)callConv);
\r
5507 MetaData.CompressNum(numPars+numOptPars,sig);
\r
5508 retType.TypeSig(sig);
\r
5509 for (int i=0; i < numPars; i++) {
\r
5510 parList[i].TypeSig(sig);
\r
5512 if (numOptPars > 0) {
\r
5513 sig.WriteByte(Sentinel);
\r
5514 for (int i=0; i < numOptPars; i++) {
\r
5515 optParList[i].TypeSig(sig);
\r
5520 internal sealed override void BuildTables(MetaData md) {
\r
5522 nameIx = md.AddToStringsHeap(name);
\r
5523 sigIx = GetSigIx(md);
\r
5527 internal sealed override uint Size(MetaData md) {
\r
5528 return md.CodedIndexSize(CIx.MemberRefParent) + md.StringsIndexSize() + md.BlobIndexSize();
\r
5531 internal sealed override void Write(FileImage output) {
\r
5532 output.WriteCodedIndex(CIx.MemberRefParent,parent);
\r
5533 output.StringsIndex(nameIx);
\r
5534 output.BlobIndex(sigIx);
\r
5537 internal sealed override uint GetCodedIx(CIx code) {
\r
5539 case (CIx.HasCustomAttr) : return 6;
\r
5540 case (CIx.MethodDefOrRef) : return 1;
\r
5541 case (CIx.CustomAttributeType) : return 3;
\r
5547 /**************************************************************************/
\r
5549 /// Descriptor for Property and Event methods
\r
5551 public class MethodSemantics : MetaDataElement {
\r
5553 Feature.MethodType type;
\r
5555 Feature eventOrProp;
\r
5557 internal MethodSemantics(Feature.MethodType mType, MethodDef method, Feature feature) {
\r
5560 eventOrProp = feature;
\r
5561 tabIx = MDTable.MethodSemantics;
\r
5564 internal sealed override uint Size(MetaData md) {
\r
5565 return 2 + md.TableIndexSize(MDTable.Method) + md.CodedIndexSize(CIx.HasSemantics);
\r
5568 internal sealed override void Write(FileImage output) {
\r
5569 output.Write((ushort)type);
\r
5570 output.WriteIndex(MDTable.Method,meth.Row);
\r
5571 output.WriteCodedIndex(CIx.HasSemantics,eventOrProp);
\r
5575 /**************************************************************************/
\r
5577 /// Descriptor for a FunctionPointer type
\r
5580 public class MethPtrType : Type
\r
5592 /// Create a new function pointer type
\r
5594 /// <param name="meth">the function to be referenced</param>
\r
5595 public MethPtrType (CallConv callconv, Type retType, Type[] pars,
5596 bool varArgMeth, Type[] optPars) : base(0x1B) {
5597 this.retType = retType;
5598 callConv = callconv;
5600 this.varArgMeth = varArgMeth;
5601 if (parList != null) numPars = (uint)parList.Length;
5603 optParList = optPars;
5604 if (optParList != null) numOptPars = (uint)optParList.Length;
5605 callConv |= CallConv.Vararg;
5607 tabIx = MDTable.TypeSpec;
5610 internal sealed override void TypeSig(MemoryStream sig) {
5611 sig.WriteByte(typeIndex);
5612 // Bootlegged from method ref
5613 sig.WriteByte((byte)callConv);
5614 MetaData.CompressNum (numPars + numOptPars, sig);
5615 retType.TypeSig (sig);
5616 for (int i=0; i < numPars; i++) {
5617 parList[i].TypeSig (sig);
5620 sig.WriteByte (0x41); // Write the sentinel
5621 for (int i=0; i < numOptPars; i++) {
5622 optParList[i].TypeSig (sig);
5627 internal sealed override void BuildTables(MetaData md) {
\r
5629 MemoryStream sig = new MemoryStream();
\r
5631 sigIx = md.AddToBlobHeap(sig.ToArray());
\r
5635 internal sealed override uint Size(MetaData md) {
\r
5636 return md.BlobIndexSize();
\r
5639 internal sealed override void Write(FileImage output) {
\r
5640 output.BlobIndex(sigIx);
\r
5643 internal sealed override uint GetCodedIx(CIx code) { return 0x1B; }
\r
5646 /**************************************************************************/
\r
5648 /// Descriptor for THIS module
\r
5650 public class Module : ResolutionScope
\r
5655 internal Module(string name, MetaData md) : base(name,md) {
\r
5656 mvid = Guid.NewGuid();
\r
5657 mvidIx = md.AddToGUIDHeap(mvid);
\r
5658 tabIx = MDTable.Module;
\r
5662 get { return mvid; }
5665 internal sealed override uint Size(MetaData md) {
\r
5666 return 2 + md.StringsIndexSize() + 3 * md.GUIDIndexSize();
\r
5669 internal sealed override void Write(FileImage output) {
\r
5670 output.Write((short)0);
\r
5671 output.StringsIndex(nameIx);
\r
5672 output.GUIDIndex(mvidIx);
\r
5673 output.GUIDIndex(0);
\r
5674 output.GUIDIndex(0);
\r
5677 internal sealed override uint GetCodedIx(CIx code) {
\r
5679 case (CIx.HasCustomAttr) : return 7;
\r
5680 case (CIx.ResolutionScope) : return 0;
\r
5685 /**************************************************************************/
\r
5687 /// Descriptor for another module in THIS assembly
\r
5689 public class ModuleRef : ResolutionScope, IExternRef
5692 internal ModuleRef(MetaData md, string name) : base(name,md) {
\r
5693 tabIx = MDTable.ModuleRef;
\r
5697 /// Add a class to this external module. This is a class declared in
\r
5698 /// another module of THIS assembly.
\r
5700 /// <param name="nsName">name space name</param>
\r
5701 /// <param name="name">class name</param>
\r
5702 /// <returns>a descriptor for this class in another module</returns>
\r
5703 public ClassRef AddClass(string nsName, string name) {
\r
5704 ClassRef aClass = new ClassRef(nsName,name,metaData);
\r
5705 metaData.AddToTable(MDTable.TypeRef,aClass);
\r
5706 aClass.SetParent(this);
\r
5711 /// Make a file descriptor to correspond to this module. The file
\r
5712 /// descriptor will have the same name as the module descriptor
\r
5714 /// <param name="hashBytes">the hash of the file</param>
\r
5715 /// <param name="hasMetaData">the file contains metadata</param>
\r
5716 /// <param name="entryPoint">the program entry point is in this file</param>
\r
5717 /// <returns>a descriptor for the file which contains this module</returns>
\r
5718 public FileRef MakeFile(byte[] hashBytes, bool hasMetaData, bool entryPoint) {
\r
5719 FileRef file = new FileRef(nameIx,hashBytes,hasMetaData,entryPoint,metaData);
\r
5720 metaData.AddToTable(MDTable.File,file);
\r
5725 /// Add a value class to this module. This is a class declared in
\r
5726 /// another module of THIS assembly.
\r
5728 /// <param name="nsName">name space name</param>
\r
5729 /// <param name="name">class name</param>
\r
5730 /// <returns></returns>
\r
5731 public ClassRef AddValueClass(string nsName, string name) {
\r
5732 ClassRef aClass = new ClassRef(nsName,name,metaData);
\r
5733 metaData.AddToTable(MDTable.TypeRef,aClass);
\r
5734 aClass.SetParent(this);
\r
5735 aClass.MakeValueClass();
\r
5740 /// Add a class which is declared public in this external module of
\r
5741 /// THIS assembly. This class will be exported from this assembly.
\r
5742 /// The ilasm syntax for this is .extern class
\r
5744 /// <param name="attrSet">attributes of the class to be exported</param>
\r
5745 /// <param name="nsName">name space name</param>
\r
5746 /// <param name="name">external class name</param>
\r
5747 /// <param name="declFile">the file where the class is declared</param>
\r
5748 /// <param name="isValueClass">is this class a value type?</param>
\r
5749 /// <returns>a descriptor for this external class</returns>
\r
5750 public ExternClassRef AddExternClass(TypeAttr attrSet, string nsName,
\r
5751 string name, FileRef declFile,
\r
5752 bool isValueClass) {
\r
5753 ExternClassRef cRef = new ExternClassRef(attrSet,nsName,name,declFile,metaData);
\r
5754 metaData.AddToTable(MDTable.TypeRef,cRef);
\r
5755 cRef.SetParent(this);
\r
5756 if (isValueClass) cRef.MakeValueClass();
\r
5761 /// Add a "global" method in another module
\r
5763 /// <param name="name">method name</param>
\r
5764 /// <param name="retType">return type</param>
\r
5765 /// <param name="pars">method parameter types</param>
\r
5766 /// <returns>a descriptor for this method in anther module</returns>
\r
5767 public MethodRef AddMethod(string name, Type retType, Type[] pars) {
\r
5768 MethodRef meth = new MethodRef(this,name,retType,pars,false,null);
\r
5769 metaData.AddToTable(MDTable.MemberRef,meth);
\r
5774 /// Add a vararg method to this class
\r
5776 /// <param name="name">method name</param>
\r
5777 /// <param name="retType">return type</param>
\r
5778 /// <param name="pars">parameter types</param>
\r
5779 /// <param name="optPars">optional param types for this vararg method</param>
\r
5780 /// <returns>a descriptor for this method</returns>
\r
5781 public MethodRef AddVarArgMethod(string name, Type retType,
\r
5782 Type[] pars, Type[] optPars) {
\r
5783 MethodRef meth = new MethodRef(this,name,retType,pars,true,optPars);
\r
5784 metaData.AddToTable(MDTable.MemberRef,meth);
\r
5789 /// Add a field in another module
\r
5791 /// <param name="name">field name</param>
\r
5792 /// <param name="fType">field type</param>
\r
5793 /// <returns>a descriptor for this field in another module</returns>
\r
5794 public FieldRef AddField(string name, Type fType) {
\r
5795 FieldRef field = new FieldRef(this,name,fType);
\r
5796 metaData.AddToTable(MDTable.MemberRef,field);
\r
5800 internal sealed override uint Size(MetaData md) {
\r
5801 return md.StringsIndexSize();
\r
5804 internal sealed override void Write(FileImage output) {
\r
5805 output.StringsIndex(nameIx);
\r
5808 internal sealed override uint GetCodedIx(CIx code) {
\r
5810 case (CIx.HasCustomAttr) : return 12;
\r
5811 case (CIx.MemberRefParent) : return 2;
\r
5812 case (CIx.ResolutionScope) : return 1;
\r
5818 /**************************************************************************/
\r
5820 /// Descriptors for native types used for marshalling
\r
5822 public class NativeType {
\r
5823 public static readonly NativeType Void = new NativeType(0x01);
\r
5824 public static readonly NativeType Boolean = new NativeType(0x02);
\r
5825 public static readonly NativeType Int8 = new NativeType(0x03);
\r
5826 public static readonly NativeType UInt8 = new NativeType(0x04);
\r
5827 public static readonly NativeType Int16 = new NativeType(0x05);
\r
5828 public static readonly NativeType UInt16 = new NativeType(0x06);
\r
5829 public static readonly NativeType Int32 = new NativeType(0x07);
\r
5830 public static readonly NativeType UInt32 = new NativeType(0x08);
\r
5831 public static readonly NativeType Int64 = new NativeType(0x09);
\r
5832 public static readonly NativeType UInt64 = new NativeType(0x0A);
\r
5833 public static readonly NativeType Float32 = new NativeType(0x0B);
\r
5834 public static readonly NativeType Float64 = new NativeType(0x0C);
\r
5835 public static readonly NativeType Currency = new NativeType(0x0F);
\r
5836 public static readonly NativeType BStr = new NativeType(0x13);
\r
5837 public static readonly NativeType LPStr = new NativeType(0x14);
\r
5838 public static readonly NativeType LPWStr = new NativeType(0x15);
\r
5839 public static readonly NativeType LPTStr = new NativeType(0x16);
\r
5840 public static readonly NativeType FixedSysString = new NativeType(0x17);
\r
5841 public static readonly NativeType IUnknown = new NativeType(0x19);
\r
5842 public static readonly NativeType IDispatch = new NativeType(0x1A);
\r
5843 public static readonly NativeType Struct = new NativeType(0x1B);
\r
5844 public static readonly NativeType Interface = new NativeType(0x1C);
\r
5845 public static readonly NativeType Int = new NativeType(0x1F);
\r
5846 public static readonly NativeType UInt = new NativeType(0x20);
\r
5847 public static readonly NativeType ByValStr = new NativeType(0x22);
\r
5848 public static readonly NativeType AnsiBStr = new NativeType(0x23);
\r
5849 public static readonly NativeType TBstr = new NativeType(0x24);
\r
5850 public static readonly NativeType VariantBool = new NativeType(0x25);
\r
5851 public static readonly NativeType FuncPtr = new NativeType(0x26);
\r
5852 public static readonly NativeType AsAny = new NativeType(0x28);
\r
5854 protected byte typeIndex;
\r
5856 internal NativeType(byte tyIx) { typeIndex = tyIx; }
\r
5858 internal byte GetTypeIndex() { return typeIndex; }
\r
5860 internal virtual byte[] ToBlob() {
\r
5861 byte[] bytes = new byte[1];
\r
5862 bytes[0] = GetTypeIndex();
\r
5868 public class NativeArray : NativeType
\r
5870 NativeType elemType;
\r
5871 uint len = 0, parNum = 0;
\r
5874 public NativeArray(NativeType elemType) : base(0x2A) {
\r
5875 this.elemType = elemType;
\r
5878 public NativeArray(NativeType elemType, int len) : base(0x2A) {
\r
5879 this.elemType = elemType;
\r
5883 public NativeArray(NativeType elemType, int numElem, int parNumForLen) : base(0x2A) {
\r
5884 this.elemType = elemType;
\r
5885 len = (uint)numElem;
\r
5886 parNum = (uint)parNumForLen;
\r
5889 internal override byte[] ToBlob() {
\r
5890 MemoryStream str = new MemoryStream();
\r
5891 str.WriteByte(GetTypeIndex());
\r
5892 if (elemType == null) str.WriteByte(0x50); // no info (MAX)
\r
5893 else str.WriteByte(elemType.GetTypeIndex());
\r
5894 MetaData.CompressNum(parNum,str);
\r
5896 MetaData.CompressNum(len,str);
\r
5897 return str.ToArray();
\r
5902 public class SafeArray : NativeType
\r
5904 SafeArrayType elemType;
\r
5906 public SafeArray(SafeArrayType elemType) : base(0x1D) {
\r
5907 this.elemType = elemType;
\r
5910 internal override byte[] ToBlob() {
\r
5911 byte[] bytes = new byte[2];
\r
5912 bytes[0] = GetTypeIndex();
\r
5913 bytes[1] = (byte)elemType;
\r
5919 public class FixedArray : NativeType
\r
5921 NativeType elemType;
\r
5924 public FixedArray(NativeType elemType, int numElems) : base(0x1E) {
\r
5925 this.elemType = elemType;
\r
5926 numElem = (uint)numElems;
\r
5929 internal override byte[] ToBlob() {
\r
5930 MemoryStream str = new MemoryStream();
\r
5931 str.WriteByte(GetTypeIndex());
\r
5932 MetaData.CompressNum(numElem,str);
\r
5933 if (elemType == null) str.WriteByte(0x50); // no info (MAX)
\r
5934 else str.WriteByte(elemType.GetTypeIndex());
\r
5935 return str.ToArray();
\r
5940 public class CustomMarshaller : NativeType
\r
5943 string marshallerName;
\r
5946 public CustomMarshaller(string typeNameOrGUID, string marshallerName,
\r
5947 string optCookie) : base(0x2C) {
\r
5948 typeName = typeNameOrGUID;
\r
5949 this.marshallerName = marshallerName;
\r
5950 cookie = optCookie;
\r
5953 internal override byte[] ToBlob() {
\r
5954 MemoryStream str = new MemoryStream();
\r
5955 BinaryWriter bw = new BinaryWriter(str,new UTF8Encoding());
\r
5956 bw.Write(GetTypeIndex());
\r
5957 bw.Write(typeName.ToCharArray());
\r
5958 bw.Write((byte)0);
\r
5959 bw.Write(marshallerName.ToCharArray());
\r
5960 bw.Write((byte)0);
\r
5961 if (cookie != null) bw.Write(cookie.ToCharArray());
\r
5962 bw.Write((byte)0);
\r
5964 return str.ToArray();
\r
5968 /**************************************************************************/
\r
5970 /// Descriptor for a parameter of a method defined in this assembly/module
\r
5972 public class Param : MetaDataElement
\r
5974 private static readonly ushort hasDefault = 0x1000;
\r
5975 private static readonly ushort hasFieldMarshal = 0x2000;
\r
5979 internal ushort seqNo = 0;
\r
5981 ConstantElem defaultVal;
\r
5983 FieldMarshal marshalInfo;
\r
5986 /// Create a new parameter for a method
\r
5988 /// <param name="mode">param mode (in, out, opt)</param>
\r
5989 /// <param name="parName">parameter name</param>
\r
5990 /// <param name="parType">parameter type</param>
\r
5991 public Param(ParamAttr mode, string parName, Type parType) {
\r
5994 parMode = (ushort)mode;
\r
5995 tabIx = MDTable.Param;
\r
5999 /// Add a default value to this parameter
\r
6001 /// <param name="c">the default value for the parameter</param>
\r
6002 public void AddDefaultValue(Constant cVal) {
\r
6003 defaultVal = new ConstantElem(this,cVal);
\r
6004 parMode |= hasDefault;
\r
6008 /// Add marshalling information about this parameter
\r
6010 public void AddMarshallInfo(NativeType marshallType) {
\r
6011 parMode |= hasFieldMarshal;
\r
6012 marshalInfo = new FieldMarshal(this,marshallType);
\r
6015 internal Type GetParType() { return pType; }
\r
6017 internal sealed override void BuildTables(MetaData md) {
\r
6019 nameIx = md.AddToStringsHeap(pName);
\r
6020 if (defaultVal != null) {
\r
6021 md.AddToTable(MDTable.Constant,defaultVal);
\r
6022 defaultVal.BuildTables(md);
\r
6024 if (marshalInfo != null) {
\r
6025 md.AddToTable(MDTable.FieldMarshal,marshalInfo);
\r
6026 marshalInfo.BuildTables(md);
\r
6031 internal void TypeSig(MemoryStream str) {
\r
6032 pType.TypeSig(str);
\r
6035 internal sealed override uint Size(MetaData md) {
\r
6036 return 4 + md.StringsIndexSize();
\r
6039 internal sealed override void Write(FileImage output) {
\r
6040 output.Write(parMode);
\r
6041 output.Write(seqNo);
\r
6042 output.StringsIndex(nameIx);
\r
6045 internal sealed override uint GetCodedIx(CIx code) {
\r
6047 case (CIx.HasCustomAttr) : return 4;
\r
6048 case (CIx.HasConst) : return 1;
\r
6049 case (CIx.HasFieldMarshal) : return 1;
\r
6055 /**************************************************************************/
\r
6057 /// Base class for the PEFile (starting point)
\r
6059 public class PEFile
\r
6061 private static readonly string mscorlibName = "mscorlib";
\r
6062 private Module thisMod;
\r
6063 private ClassDef moduleClass;
\r
6064 private ArrayList classRefList = new ArrayList();
\r
6065 private ArrayList classDefList = new ArrayList();
\r
6066 private Assembly thisAssembly;
\r
6067 private int corFlags = 1;
\r
6068 FileImage fileImage;
\r
6069 MetaData metaData;
\r
6072 /// Create a new PEFile. Each PEFile is a module.
\r
6074 /// <param name="name">module name, also used for the file name</param>
\r
6075 /// <param name="isDLL">create a .dll or .exe file</param>
\r
6076 /// <param name="hasAssembly">this file is an assembly and
\r
6077 /// will contain the assembly manifest. The assembly name is the
\r
6078 /// same as the module name</param>
\r
6079 public PEFile(string name, bool isDLL, bool hasAssembly) {
\r
6080 // Console.WriteLine(Hex.Byte(0x12));
\r
6081 // Console.WriteLine(Hex.Short(0x1234));
\r
6082 // Console.WriteLine(Hex.Int(0x12345678));
\r
6083 string fName = MakeFileName(null,name,isDLL);
\r
6084 fileImage = new FileImage(isDLL,fName);
\r
6085 InitPEFile(name, fName, hasAssembly);
\r
6089 /// Create a new PEFile. Each PEFile is a module.
\r
6091 /// <param name="name">module name, also used for the file name</param>
\r
6092 /// <param name="isDLL">create a .dll or .exe file</param>
\r
6093 /// <param name="hasAssembly">this file is an assembly and
\r
6094 /// will contain the assembly manifest. The assembly name is the
\r
6095 /// same as the module name</param>
\r
6096 /// <param name="outputDir">write the PEFile to this directory. If this
\r
6097 /// string is null then the output will be to the current directory</param>
\r
6098 public PEFile(string name, bool isDLL, bool hasAssembly, string outputDir) {
\r
6099 // Console.WriteLine(Hex.Byte(0x12));
\r
6100 // Console.WriteLine(Hex.Short(0x1234));
\r
6101 // Console.WriteLine(Hex.Int(0x12345678));
\r
6102 string fName = MakeFileName(outputDir,name,isDLL);
\r
6103 fileImage = new FileImage(isDLL,fName);
\r
6104 InitPEFile(name, fName, hasAssembly);
\r
6108 /// Create a new PEFile
\r
6110 /// <param name="name">module name</param>
\r
6111 /// <param name="isDLL">create a .dll or .exe</param>
\r
6112 /// <param name="hasAssembly">this PEfile is an assembly and
\r
6113 /// will contain the assemly manifest. The assembly name is the
\r
6114 /// same as the module name</param>
\r
6115 /// <param name="outStream">write the PEFile to this stream instead
\r
6116 /// of to a new file</param>
\r
6117 public PEFile(string name, bool isDLL, bool hasAssembly, Stream outStream) {
\r
6118 fileImage = new FileImage(isDLL,outStream);
\r
6119 InitPEFile(name, MakeFileName(null,name,isDLL), hasAssembly);
\r
6122 public PEFile(string name, string module_name, bool isDLL, bool hasAssembly, Stream outStream) {
\r
6123 fileImage = new FileImage(isDLL,outStream);
\r
6124 InitPEFile(name, (module_name == null ? MakeFileName(null,name,isDLL) : module_name), hasAssembly);
\r
6127 private void InitPEFile(string name, string fName, bool hasAssembly) {
6128 metaData = fileImage.GetMetaData();
\r
6129 thisMod = new Module(fName,metaData);
\r
6130 if (hasAssembly) {
\r
6131 thisAssembly = new Assembly(name,metaData);
\r
6132 metaData.AddToTable(MDTable.Assembly,thisAssembly);
\r
6134 moduleClass = AddClass(TypeAttr.Private,"","<Module>");
\r
6135 moduleClass.SpecialNoSuper();
\r
6136 metaData.AddToTable(MDTable.Module,thisMod);
\r
6140 public ClassDef ModuleClass {
6141 get { return moduleClass; }
6145 /// Set the subsystem (.subsystem) (Default is Windows Console mode)
\r
6147 /// <param name="subS">subsystem value</param>
\r
6148 public void SetSubSystem(SubSystem subS) {
\r
6149 fileImage.subSys = subS;
\r
6153 /// Set the flags (.corflags)
\r
6155 /// <param name="flags">the flags value</param>
\r
6156 public void SetCorFlags(int flags) {
\r
6160 private string MakeFileName(string dirName, string name, bool isDLL) {
\r
6161 string result = "";
\r
6162 if ((dirName != null) && (dirName.CompareTo("") != 0)) {
\r
6164 if (!dirName.EndsWith("\\")) result += "\\";
\r
6168 // if (isDLL) result += ".dll"; else result += ".exe";
\r
6174 /// Add an external assembly to this PEFile (.assembly extern)
\r
6176 /// <param name="assemName">the external assembly name</param>
\r
6177 /// <returns>a descriptor for this external assembly</returns>
\r
6178 public AssemblyRef AddExternAssembly(string assemName) {
\r
6179 if (assemName.CompareTo(mscorlibName) == 0) return metaData.mscorlib;
\r
6180 AssemblyRef anAssem = new AssemblyRef(metaData,assemName);
\r
6181 metaData.AddToTable(MDTable.AssemblyRef,anAssem);
\r
6182 // Console.WriteLine("Adding assembly " + assemName);
\r
6187 /// Add an external module to this PEFile (.module extern)
\r
6189 /// <param name="name">the external module name</param>
\r
6190 /// <returns>a descriptor for this external module</returns>
\r
6191 public ModuleRef AddExternModule(string name) {
\r
6192 ModuleRef modRef = new ModuleRef(metaData,name);
\r
6193 metaData.AddToTable(MDTable.ModuleRef,modRef);
\r
6198 /// Add a "global" method to this module
\r
6200 /// <param name="name">method name</param>
\r
6201 /// <param name="retType">return type</param>
\r
6202 /// <param name="pars">method parameters</param>
\r
6203 /// <returns>a descriptor for this new "global" method</returns>
\r
6204 public MethodDef AddMethod(string name, Type retType, Param[] pars) {
\r
6205 return moduleClass.AddMethod(name,retType,pars);
\r
6209 /// Add a "global" method to this module
\r
6211 /// <param name="mAtts">method attributes</param>
\r
6212 /// <param name="iAtts">method implementation attributes</param>
\r
6213 /// <param name="name">method name</param>
\r
6214 /// <param name="retType">return type</param>
\r
6215 /// <param name="pars">method parameters</param>
\r
6216 /// <returns>a descriptor for this new "global" method</returns>
\r
6217 public MethodDef AddMethod(MethAttr mAtts, ImplAttr iAtts, string name, Type retType, Param[] pars) {
\r
6218 return moduleClass.AddMethod(mAtts,iAtts,name,retType,pars);
\r
6221 public MethodRef AddMethodToTypeSpec (Type item, string name, Type retType, Type[] pars) {
\r
6222 MethodRef meth = new MethodRef (item.GetTypeSpec (metaData), name, retType, pars, false, null);
\r
6223 metaData.AddToTable (MDTable.MemberRef,meth);
\r
6227 public MethodRef AddVarArgMethodToTypeSpec (Type item, string name, Type retType,
\r
6228 Type[] pars, Type[] optPars) {
\r
6229 MethodRef meth = new MethodRef(item.GetTypeSpec (metaData), name,retType,pars,true,optPars);
\r
6230 metaData.AddToTable(MDTable.MemberRef,meth);
\r
6234 public FieldRef AddFieldToTypeSpec (Type item, string name, Type fType) {
\r
6235 FieldRef field = new FieldRef (item.GetTypeSpec (metaData), name,fType);
\r
6236 metaData.AddToTable (MDTable.MemberRef,field);
\r
6240 public void AddMethodSpec (Method m, GenericMethodSig g_sig)
6242 MethodSpec ms = new MethodSpec (m, g_sig);
6243 metaData.AddToTable (MDTable.MethodSpec, ms);
6247 /// Add a "global" field to this module
\r
6249 /// <param name="name">field name</param>
\r
6250 /// <param name="fType">field type</param>
\r
6251 /// <returns>a descriptor for this new "global" field</returns>
\r
6252 public FieldDef AddField(string name, Type fType) {
\r
6253 return moduleClass.AddField(name,fType);
\r
6257 /// Add a "global" field to this module
\r
6259 /// <param name="attrSet">attributes of this field</param>
\r
6260 /// <param name="name">field name</param>
\r
6261 /// <param name="fType">field type</param>
\r
6262 /// <returns>a descriptor for this new "global" field</returns>
\r
6263 public FieldDef AddField(FieldAttr attrSet, string name, Type fType) {
\r
6264 return moduleClass.AddField(attrSet,name,fType);
\r
6268 /// Add a class to this module
\r
6270 /// <param name="attrSet">attributes of this class</param>
\r
6271 /// <param name="nsName">name space name</param>
\r
6272 /// <param name="name">class name</param>
\r
6273 /// <returns>a descriptor for this new class</returns>
\r
6274 public ClassDef AddClass(TypeAttr attrSet, string nsName, string name) {
\r
6275 ClassDef aClass = new ClassDef(attrSet,nsName,name,metaData);
\r
6276 metaData.AddToTable(MDTable.TypeDef,aClass);
\r
6281 /// Add a class which extends System.ValueType to this module
\r
6283 /// <param name="attrSet">attributes of this class</param>
\r
6284 /// <param name="nsName">name space name</param>
\r
6285 /// <param name="name">class name</param>
\r
6286 /// <returns>a descriptor for this new class</returns>
\r
6287 public ClassDef AddValueClass(TypeAttr attrSet, string nsName, string name) {
\r
6288 ClassDef aClass = new ClassDef(attrSet,nsName,name,metaData);
\r
6289 aClass.MakeValueClass();
\r
6290 metaData.AddToTable(MDTable.TypeDef,aClass);
\r
6295 /// Add a class to this module
\r
6297 /// <param name="attrSet">attributes of this class</param>
\r
6298 /// <param name="nsName">name space name</param>
\r
6299 /// <param name="name">class name</param>
\r
6300 /// <param name="superType">super type of this class (extends)</param>
\r
6301 /// <returns>a descriptor for this new class</returns>
\r
6302 public ClassDef AddClass(TypeAttr attrSet, string nsName, string name, Class superType) {
\r
6303 ClassDef aClass = new ClassDef(attrSet,nsName,name,metaData);
\r
6304 aClass.SetSuper(superType);
\r
6305 metaData.AddToTable(MDTable.TypeDef,aClass);
\r
6309 public FileRef AddFile(string fName, byte[] hashBytes, bool hasMetaData, bool entryPoint) {
\r
6310 FileRef file = new FileRef(fName,hashBytes,hasMetaData,entryPoint,metaData);
\r
6311 metaData.AddToTable(MDTable.File,file);
\r
6316 /// Add a manifest resource to this PEFile NOT YET IMPLEMENTED
\r
6318 /// <param name="mr"></param>
\r
6319 public void AddManifestResource(ManifestResource mr) {
\r
6320 metaData.AddToTable(MDTable.ManifestResource,mr);
\r
6321 //mr.FixName(metaData);
\r
6324 public void AddCustomAttribute (Method meth, byte [] data, MetaDataElement element)
6326 metaData.AddCustomAttribute (new CustomAttribute (element, meth, data));
6330 /// Write out the PEFile (the "bake" function)
\r
6332 public void WritePEFile() { /* the "bake" function */
6333 fileImage.ReserveStrongNameSignatureSpace = thisAssembly.HasPublicKey;
6334 fileImage.MakeFile();
\r
6338 /// Get the descriptor of this module
\r
6340 /// <returns>the descriptor for this module</returns>
\r
6341 public Module GetThisModule() {
\r
6346 /// Get the descriptor for this assembly. The PEFile must have been
\r
6347 /// created with hasAssembly = true
\r
6349 /// <returns>the descriptor for this assembly</returns>
\r
6350 public Assembly GetThisAssembly() {
\r
6351 return thisAssembly;
\r
6356 /**************************************************************************/
\r
6358 /// Descriptor for the Primitive types defined in IL
\r
6360 public class PrimitiveType : Type
\r
6362 private string name;
\r
6363 private int systemTypeIndex;
\r
6364 public static int NumSystemTypes = 18;
\r
6366 public static readonly PrimitiveType Void = new PrimitiveType(0x01,"Void",0);
\r
6367 public static readonly PrimitiveType Boolean = new PrimitiveType(0x02,"Boolean",1);
\r
6368 public static readonly PrimitiveType Char = new PrimitiveType(0x03,"Char",2);
\r
6369 public static readonly PrimitiveType Int8 = new PrimitiveType(0x04,"SByte",3);
\r
6370 public static readonly PrimitiveType UInt8 = new PrimitiveType(0x05,"Byte",4);
\r
6371 public static readonly PrimitiveType Int16 = new PrimitiveType(0x06,"Int16",5);
\r
6372 public static readonly PrimitiveType UInt16 = new PrimitiveType(0x07,"UInt16",6);
\r
6373 public static readonly PrimitiveType Int32 = new PrimitiveType(0x08,"Int32",7);
\r
6374 public static readonly PrimitiveType UInt32 = new PrimitiveType(0x09,"UInt32",8);
\r
6375 public static readonly PrimitiveType Int64 = new PrimitiveType(0x0A,"Int64",9);
\r
6376 public static readonly PrimitiveType UInt64 = new PrimitiveType(0x0B,"UInt64",10);
\r
6377 public static readonly PrimitiveType Float32 = new PrimitiveType(0x0C,"Single",11);
\r
6378 public static readonly PrimitiveType Float64 = new PrimitiveType(0x0D,"Double",12);
\r
6379 public static readonly PrimitiveType String = new PrimitiveType(0x0E,"String",13);
\r
6380 internal static readonly PrimitiveType Class = new PrimitiveType(0x12);
\r
6381 public static readonly PrimitiveType TypedRef = new PrimitiveType(0x16,"TypedReference",14);
\r
6382 public static readonly PrimitiveType IntPtr = new PrimitiveType(0x18,"IntPtr",15);
\r
6383 public static readonly PrimitiveType UIntPtr = new PrimitiveType(0x19,"UIntPtr",16);
\r
6384 public static readonly PrimitiveType Object = new PrimitiveType(0x1C,"Object",17);
\r
6385 internal static readonly PrimitiveType ClassType = new PrimitiveType(0x50);
\r
6386 public static readonly PrimitiveType NativeInt = IntPtr;
\r
6387 public static readonly PrimitiveType NativeUInt = UIntPtr;
\r
6389 internal PrimitiveType(byte typeIx) : base(typeIx) { }
\r
6391 internal PrimitiveType(byte typeIx, string name, int STIx) : base(typeIx) {
\r
6393 this.systemTypeIndex = STIx;
\r
6396 internal string GetName() { return name; }
\r
6398 internal int GetSystemTypeIx() { return systemTypeIndex; }
\r
6400 internal sealed override void TypeSig(MemoryStream str) {
\r
6401 str.WriteByte(typeIndex);
\r
6404 internal override MetaDataElement GetTypeSpec(MetaData md) {
\r
6405 TypeSpec tS = md.GetPrimitiveTypeSpec(systemTypeIndex);
\r
6407 tS = new TypeSpec(this,md);
\r
6408 md.SetPrimitiveTypeSpec(systemTypeIndex,tS);
\r
6409 md.AddToTable(MDTable.TypeSpec,tS);
\r
6416 /**************************************************************************/
\r
6418 /// Descriptor for the Property of a class
\r
6420 public class Property : Feature
\r
6422 private static readonly byte PropertyTag = 0x8;
\r
6423 MethodDef getterMeth;
\r
6424 ConstantElem constVal;
\r
6425 uint typeBlobIx = 0;
\r
6430 internal Property(string name, Type retType, Type[] pars, ClassDef parent) : base(name, parent) {
\r
6431 returnType = retType;
\r
6433 if (pars != null) numPars = (uint)pars.Length;
\r
6434 tabIx = MDTable.Property;
\r
6438 /// Add a set method to this property
\r
6440 /// <param name="setter">the set method</param>
\r
6441 public void AddSetter(MethodDef setter) {
\r
6442 AddMethod(setter,MethodType.Setter);
\r
6446 /// Add a get method to this property
\r
6448 /// <param name="getter">the get method</param>
\r
6449 public void AddGetter(MethodDef getter) {
\r
6450 AddMethod(getter,MethodType.Getter);
\r
6451 getterMeth = getter;
\r
6455 /// Add another method to this property
\r
6457 /// <param name="other">the method</param>
\r
6458 public void AddOther(MethodDef other) {
\r
6459 AddMethod(other,MethodType.Other);
\r
6463 /// Add an initial value for this property
\r
6465 /// <param name="constVal">the initial value for this property</param>
\r
6466 public void AddInitValue(Constant constVal) {
\r
6467 this.constVal = new ConstantElem(this,constVal);
\r
6470 internal sealed override void BuildTables(MetaData md) {
\r
6472 nameIx = md.AddToStringsHeap(name);
\r
6473 MemoryStream sig = new MemoryStream();
\r
6474 sig.WriteByte(PropertyTag);
\r
6475 MetaData.CompressNum(numPars,sig);
\r
6476 returnType.TypeSig(sig);
\r
6477 for (int i=0; i < numPars; i++) {
\r
6478 parList[i].TypeSig(sig);
\r
6480 typeBlobIx = md.AddToBlobHeap(sig.ToArray());
\r
6481 for (int i=0; i < tide; i++) {
\r
6482 md.AddToTable(MDTable.MethodSemantics,methods[i]);
\r
6484 if (constVal != null) {
\r
6485 md.AddToTable(MDTable.Constant,constVal);
\r
6486 constVal.BuildTables(md);
\r
6491 internal sealed override uint Size(MetaData md) {
\r
6492 return 2 + md.StringsIndexSize() + md.BlobIndexSize();
\r
6495 internal sealed override void Write(FileImage output) {
\r
6496 output.Write(flags);
\r
6497 output.StringsIndex(nameIx);
\r
6498 output.BlobIndex(typeBlobIx);
\r
6501 internal sealed override uint GetCodedIx(CIx code) {
\r
6503 case (CIx.HasCustomAttr) : return 9;
\r
6504 case (CIx.HasConst) : return 2;
\r
6505 case (CIx.HasSemantics) : return 1;
\r
6511 /**************************************************************************/
\r
6513 /// Descriptor for an pointer (type * or type &)
\r
6515 public abstract class PtrType : Type
\r
6519 internal PtrType(Type bType, byte typeIx) : base(typeIx)
\r
6522 tabIx = MDTable.TypeSpec;
\r
6525 internal sealed override void TypeSig(MemoryStream str) {
\r
6526 str.WriteByte(typeIndex);
\r
6527 baseType.TypeSig(str);
\r
6531 /**************************************************************************/
\r
6533 /// Descriptor for a managed pointer (type & or byref)
\r
6536 public class ManagedPointer : PtrType // <type> & (BYREF)
\r
6540 /// Create new managed pointer to baseType
\r
6542 /// <param name="bType">the base type of the pointer</param>
\r
6543 public ManagedPointer(Type baseType) : base(baseType,0x10) { }
\r
6546 /**************************************************************************/
\r
6548 /// Descriptor for an unmanaged pointer (type *)
\r
6550 public class UnmanagedPointer : PtrType // PTR
\r
6553 /// Create a new unmanaged pointer to baseType
\r
6555 /// <param name="baseType">the base type of the pointer</param>
\r
6556 public UnmanagedPointer(Type baseType) : base(baseType, 0x0F) { }
\r
6559 /**************************************************************************/
\r
6561 /// Base class for scopes (extended by Module, ModuleRef, Assembly, AssemblyRef)
\r
6563 public abstract class ResolutionScope : MetaDataElement
\r
6565 protected uint nameIx = 0;
\r
6566 protected MetaData metaData;
\r
6567 protected string name;
\r
6569 internal ResolutionScope(string name, MetaData md)
\r
6573 nameIx = md.AddToStringsHeap(name);
\r
6576 internal string GetName() { return name; }
\r
6579 /**************************************************************************/
\r
6581 /// Descriptor for a Section in a PEFile eg .text, .sdata
\r
6583 internal class Section {
\r
6584 private static readonly uint relocPageSize = 4096; // 4K pages for fixups
\r
6587 uint offset = 0, tide = 0, size = 0, rva = 0, relocTide = 0;
\r
6588 //uint relocOff = 0;
\r
6589 uint flags = 0, padding = 0;
\r
6592 internal Section(string sName, uint sFlags) {
6593 name = sName.ToCharArray();
\r
6597 internal uint Tide() { return tide; }
\r
6599 internal void IncTide(uint incVal) { tide += incVal; }
\r
6601 internal uint Padding() { return padding; }
\r
6603 internal uint Size() { return size; }
\r
6605 internal void SetSize(uint pad) {
\r
6607 size = tide + padding;
\r
6610 internal uint RVA() { return rva; }
\r
6612 internal void SetRVA(uint rva) { this.rva = rva; }
\r
6614 internal uint Offset() { return offset; }
\r
6616 internal void SetOffset(uint offs) { offset = offs; }
\r
6618 internal void DoBlock(BinaryWriter reloc, uint page, int start, int end) {
\r
6619 //Console.WriteLine("rva = " + rva + " page = " + page);
\r
6620 reloc.Write(rva + page);
\r
6621 reloc.Write((uint)(((end-start+1)*2) + 8));
\r
6622 for (int j=start; j < end; j++) {
\r
6623 //Console.WriteLine("reloc offset = " + relocs[j]);
\r
6624 reloc.Write((ushort)((0x3 << 12) | (relocs[j] - page)));
\r
6626 reloc.Write((ushort)0);
\r
6629 internal void DoRelocs(BinaryWriter reloc) {
\r
6630 if (relocTide > 0) {
\r
6631 //relocOff = (uint)reloc.Seek(0,SeekOrigin.Current);
\r
6632 uint block = (relocs[0]/relocPageSize + 1) * relocPageSize;
\r
6634 for (int i=1; i < relocTide; i++) {
\r
6635 if (relocs[i] >= block) {
\r
6636 DoBlock(reloc,block-relocPageSize,start,i);
\r
6638 block = (relocs[i]/relocPageSize + 1) * relocPageSize;
\r
6641 DoBlock(reloc,block-relocPageSize,start,(int)relocTide);
\r
6645 internal void AddReloc(uint offs) {
\r
6647 if (relocs == null) {
\r
6648 relocs = new uint[5];
\r
6650 if (relocTide >= relocs.Length) {
\r
6651 uint[] tmp = relocs;
\r
6652 relocs = new uint[tmp.Length + 5];
\r
6653 for (int i=0; i < relocTide; i++) {
\r
6654 relocs[i] = tmp[i];
\r
6657 while ((pos < relocTide) && (relocs[pos] < offs)) pos++;
\r
6658 for (int i=pos; i < relocTide; i++) {
\r
6659 relocs[i+1] = relocs[i];
\r
6662 relocs[pos] = offs;
\r
6666 internal void WriteHeader(BinaryWriter output, uint relocRVA) {
\r
6667 output.Write(name);
\r
6668 output.Write(tide);
\r
6669 output.Write(rva);
\r
6670 output.Write(size);
\r
6671 output.Write(offset);
\r
6673 //output.Write(relocRVA + relocOff);
\r
6676 //output.Write((ushort)relocTide);
\r
6677 //output.Write((ushort)0);
\r
6678 output.Write(flags);
\r
6682 /**************************************************************************/
\r
6683 public abstract class Signature : MetaDataElement
\r
6685 protected uint sigIx;
\r
6687 internal Signature() {
\r
6688 tabIx = MDTable.StandAloneSig;
\r
6691 internal sealed override uint Size(MetaData md) {
\r
6692 return md.BlobIndexSize();
\r
6695 internal sealed override void Write(FileImage output) {
\r
6696 output.BlobIndex(sigIx);
\r
6699 internal sealed override uint GetCodedIx(CIx code) { return (uint)tabIx; }
\r
6702 /**************************************************************************/
\r
6704 /// Descriptor for a class defined in System (mscorlib)
\r
6706 internal class SystemClass : ClassRef
\r
6708 PrimitiveType elemType;
\r
6710 internal SystemClass(PrimitiveType eType, AssemblyRef paren, MetaData md)
\r
6711 : base("System",eType.GetName(),md) {
\r
6716 internal override sealed MetaDataElement GetTypeSpec(MetaData md) {
\r
6717 if (typeSpec == null) typeSpec = (TypeSpec)elemType.GetTypeSpec(md);
\r
6722 internal sealed override void TypeSig(MemoryStream str) {
\r
6723 str.WriteByte(elemType.GetTypeIndex());
\r
6727 /**************************************************************************/
\r
6729 /// Base class for all IL types
\r
6731 public abstract class Type : MetaDataElement {
\r
6732 protected byte typeIndex;
\r
6733 protected TypeSpec typeSpec;
\r
6735 internal Type(byte tyIx) { typeIndex = tyIx; }
\r
6737 internal byte GetTypeIndex() { return typeIndex; }
\r
6738 internal void SetTypeIndex (byte b) { typeIndex = b; }
6740 internal virtual MetaDataElement GetTypeSpec(MetaData md) {
\r
6741 if (typeSpec == null) {
\r
6742 typeSpec = new TypeSpec(this,md);
\r
6743 md.AddToTable(MDTable.TypeSpec,typeSpec);
\r
6748 internal virtual void TypeSig(MemoryStream str) {
\r
6749 throw(new TypeSignatureException(this.GetType().AssemblyQualifiedName +
\r
6750 " doesn't have a type signature!!"));
\r
6755 /**************************************************************************/
\r
6757 public class TypeSpec : MetaDataElement {
\r
6760 internal TypeSpec(Type aType, MetaData md) {
\r
6761 MemoryStream sig = new MemoryStream();
\r
6762 aType.TypeSig(sig);
\r
6763 sigIx = md.AddToBlobHeap(sig.ToArray());
\r
6764 tabIx = MDTable.TypeSpec;
\r
6767 internal sealed override uint GetCodedIx(CIx code) {
\r
6769 case (CIx.TypeDefOrRef) : return 2;
\r
6770 case (CIx.HasCustomAttr) : return 13;
\r
6771 case (CIx.MemberRefParent) : return 4;
\r
6776 internal override uint Size(MetaData md) {
\r
6777 return md.BlobIndexSize();
\r
6780 internal sealed override void Write(FileImage output) {
\r
6781 //Console.WriteLine("Writing the blob index for a TypeSpec");
\r
6782 output.BlobIndex(sigIx);
\r
6787 class ByteArrayComparer : IComparer {
6789 public int Compare (object x, object y)
6791 byte [] a = (byte []) x;
6792 byte [] b = (byte []) y;
6795 if (b.Length != len)
6798 for (int i = 0; i < len; ++i)
6805 class ByteArrayHashCodeProvider : IHashCodeProvider {
6807 public int GetHashCode (Object key)
6809 byte [] arr = (byte []) key;
6810 int len = arr.Length;
6813 for (int i = 0; i < len; ++i)
6814 h = (h << 5) - h + arr [i];