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 MVar : Type {
\r
102 public MVar (int index) : base (0x1E) {
\r
103 this.index = index;
\r
104 tabIx = MDTable.TypeSpec;
\r
107 internal sealed override void TypeSig(MemoryStream str) {
\r
108 str.WriteByte(typeIndex);
\r
109 MetaData.CompressNum ((uint) index, str);
\r
113 public class GenericTypeSpec : Type {
\r
117 public GenericTypeSpec (int index) : base (0x13) {
\r
118 this.index = index;
\r
119 tabIx = MDTable.TypeSpec;
\r
122 internal sealed override void TypeSig(MemoryStream str) {
\r
123 str.WriteByte(typeIndex);
\r
124 MetaData.CompressNum ((uint) index, str);
\r
128 public class GenericTypeInst : Type {
\r
130 private Type gen_type;
\r
131 private Type[] gen_param;
\r
133 public GenericTypeInst (Type gen_type, Type[] gen_param) : base (0x15)
\r
136 this.gen_type = gen_type;
\r
137 this.gen_param = gen_param;
\r
138 tabIx = MDTable.TypeSpec;
\r
141 internal sealed override void TypeSig(MemoryStream str) {
\r
142 str.WriteByte(typeIndex);
\r
143 gen_type.TypeSig (str);
\r
144 MetaData.CompressNum ((uint) gen_param.Length, str);
\r
145 foreach (Type param in gen_param)
\r
146 param.TypeSig (str);
\r
150 public class GenericMethodSig {
152 private Type[] gen_param;
154 public GenericMethodSig (Type[] gen_param)
156 this.gen_param = gen_param;
159 internal void TypeSig (MemoryStream str)
161 MetaData.CompressNum ((uint) gen_param.Length, str); // THIS IS NOT RIGHT, but works
162 MetaData.CompressNum ((uint) gen_param.Length, str);
163 foreach (Type param in gen_param)
167 internal uint GetSigIx (MetaData md)
169 MemoryStream sig = new MemoryStream();
171 return md.AddToBlobHeap (sig.ToArray());
175 public class Sentinel : Type {
177 public Sentinel () : base (0x41) { }
179 internal sealed override void TypeSig(MemoryStream str) {
180 str.WriteByte(typeIndex);
185 /// The IL Array type
\r
187 public abstract class Array : Type
\r
190 protected Type elemType;
\r
191 protected MetaData metaData;
\r
192 protected string cnameSpace, cname;
\r
194 internal Array(Type eType, byte TypeId) : base(TypeId) {
\r
196 tabIx = MDTable.TypeSpec;
\r
201 /**************************************************************************/
\r
204 /// Single dimensional array with zero lower bound
\r
206 public class ZeroBasedArray : Array {
\r
209 /// Create a new array - elementType[]
\r
211 /// <param name="elementType">the type of the array elements</param>
\r
212 public ZeroBasedArray(Type elementType) : base (elementType,0x1D) { }
\r
214 internal sealed override void TypeSig(MemoryStream str) {
\r
215 str.WriteByte(typeIndex);
\r
216 elemType.TypeSig(str);
\r
222 /**************************************************************************/
\r
225 /// Multi dimensional array with explicit bounds
\r
227 public class BoundArray : Array {
\r
233 /// Create a new multi dimensional array type
\r
234 /// eg. elemType[1..5,3..10,5,,] would be
\r
235 /// new BoundArray(elemType,5,[1,3,0],[5,10,4])
\r
237 /// <param name="elementType">the type of the elements</param>
\r
238 /// <param name="dimensions">the number of dimensions</param>
\r
239 /// <param name="loBounds">lower bounds of dimensions</param>
\r
240 /// <param name="upBounds">upper bounds of dimensions</param>
\r
241 public BoundArray(Type elementType, uint dimensions, int[] loBounds,
\r
242 int[] upBounds) : base (elementType,0x14) {
\r
243 numDims = dimensions;
\r
244 lowerBounds = loBounds;
\r
245 sizes = new int[loBounds.Length];
\r
246 for (int i=0; i < loBounds.Length; i++) {
\r
247 sizes[i] = upBounds[i] - loBounds[i] + 1;
\r
252 /// Create a new multi dimensional array type
\r
253 /// eg. elemType[5,10,20] would be new BoundArray(elemType,3,[5,10,20])
\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="size">the sizes of the dimensions</param>
\r
258 public BoundArray(Type elementType, uint dimensions, int[] size)
\r
259 : base (elementType,0x14) {
\r
260 numDims = dimensions;
\r
265 /// Create a new multi dimensional array type
\r
266 /// eg. elemType[,,] would be new BoundArray(elemType,3)
\r
268 /// <param name="elementType">the type of the elements</param>
\r
269 /// <param name="dimensions">the number of dimensions</param>
\r
270 public BoundArray(Type elementType, uint dimensions)
\r
271 : base (elementType,0x14) {
\r
272 numDims = dimensions;
\r
275 internal sealed override void TypeSig(MemoryStream str) {
\r
276 str.WriteByte(typeIndex);
\r
277 elemType.TypeSig(str);
\r
278 MetaData.CompressNum(numDims,str);
\r
279 if ((sizes != null) && (sizes.Length > 0)) {
\r
280 MetaData.CompressNum((uint)sizes.Length,str);
\r
281 for (int i=0; i < sizes.Length; i++) {
\r
282 MetaData.CompressNum((uint)sizes[i],str);
\r
284 } else str.WriteByte(0);
\r
285 if ((lowerBounds != null) && (lowerBounds.Length > 0)) {
\r
286 MetaData.CompressNum((uint)lowerBounds.Length,str);
\r
287 for (int i=0; i < lowerBounds.Length; i++) {
\r
288 MetaData.CompressNum((uint)lowerBounds[i],str);
\r
290 } else str.WriteByte(0);
\r
294 /**************************************************************************/
\r
296 /// Descriptor for THIS assembly (.assembly)
\r
298 public class Assembly : ResolutionScope
\r
300 ushort majorVer, minorVer, buildNo, revisionNo;
\r
302 HashAlgorithm hashAlgId = HashAlgorithm.None;
\r
303 uint keyIx = 0, cultIx = 0;
\r
305 internal Assembly(string name, MetaData md) : base(name,md) {
\r
306 tabIx = MDTable.Assembly;
\r
310 /// Add details about THIS assembly
\r
312 /// <param name="majVer">Major Version</param>
\r
313 /// <param name="minVer">Minor Version</param>
\r
314 /// <param name="bldNo">Build Number</param>
\r
315 /// <param name="revNo">Revision Number</param>
\r
316 /// <param name="key">Hash Key</param>
\r
317 /// <param name="hash">Hash Algorithm</param>
\r
318 /// <param name="cult">Culture</param>
\r
319 public void AddAssemblyInfo(int majVer, int minVer, int bldNo, int revNo,
\r
320 byte[] key, HashAlgorithm hash, string cult) {
\r
321 majorVer = (ushort)majVer;
\r
322 minorVer = (ushort)minVer;
\r
323 buildNo = (ushort)bldNo;
\r
324 revisionNo = (ushort)revNo;
\r
326 keyIx = metaData.AddToBlobHeap(key);
\r
327 cultIx = metaData.AddToStringsHeap(cult);
\r
331 /// Add an attribute to THIS assembly
\r
333 /// <param name="aa">assembly attribute</param>
\r
334 public void AddAssemblyAttr(AssemAttr aa) {
\r
338 internal sealed override uint Size(MetaData md) {
\r
339 return 16 + md.BlobIndexSize() + 2 * md.StringsIndexSize();
\r
342 internal sealed override void Write(FileImage output) {
\r
343 // Console.WriteLine("Writing assembly element with nameIx of " + nameIx + " at file offset " + output.Seek(0,SeekOrigin.Current));
\r
344 output.Write((uint)hashAlgId);
\r
345 output.Write(majorVer);
\r
346 output.Write(minorVer);
\r
347 output.Write(buildNo);
\r
348 output.Write(revisionNo);
\r
349 output.Write(flags);
\r
350 output.BlobIndex(keyIx);
\r
351 output.StringsIndex(nameIx);
\r
352 output.StringsIndex(cultIx);
\r
355 internal sealed override uint GetCodedIx(CIx code) {
\r
357 case (CIx.HasCustomAttr) : return 14;
\r
358 case (CIx.HasDeclSecurity) : return 2;
\r
364 /**************************************************************************/
\r
366 /// A reference to an external assembly (.assembly extern)
\r
368 public class AssemblyRef : ResolutionScope
\r
370 private ushort major, minor, build, revision;
\r
371 uint flags, keyIx, hashIx, cultIx;
\r
372 bool hasVersion = false, isKeyToken = false;
\r
376 internal AssemblyRef(MetaData md, string name) : base(name,md) {
\r
377 tabIx = MDTable.AssemblyRef;
\r
381 /// Add version information about this external assembly
\r
383 /// <param name="majVer">Major Version</param>
\r
384 /// <param name="minVer">Minor Version</param>
\r
385 /// <param name="bldNo">Build Number</param>
\r
386 /// <param name="revNo">Revision Number</param>
\r
387 public void AddVersionInfo(int majVer, int minVer, int bldNo, int revNo) {
\r
388 major = (ushort)majVer;
\r
389 minor = (ushort)minVer;
\r
390 build = (ushort)bldNo;
\r
391 revision = (ushort)revNo;
\r
396 /// Add the hash value for this external assembly
\r
398 /// <param name="hash">bytes of the hash value</param>
\r
399 public void AddHash(byte[] hash) {
\r
400 hashIx = metaData.AddToBlobHeap(hash);
\r
404 /// Set the culture for this external assembly
\r
406 /// <param name="cult">the culture string</param>
\r
407 public void AddCulture(string cult) {
\r
408 cultIx = metaData.AddToStringsHeap(cult);
\r
413 /// Add the full public key for this external assembly
\r
415 /// <param name="key">bytes of the public key</param>
\r
416 public void AddKey(byte[] key) {
\r
417 flags |= 0x0001; // full public key
\r
419 keyIx = metaData.AddToBlobHeap(key);
\r
423 /// Add the public key token (low 8 bytes of the public key)
\r
425 /// <param name="key">low 8 bytes of public key</param>
\r
426 public void AddKeyToken(byte[] key) {
\r
427 keyIx = metaData.AddToBlobHeap(key);
\r
433 /// Add a class to this external assembly
\r
435 /// <param name="nsName">name space name</param>
\r
436 /// <param name="name">class name</param>
\r
437 /// <returns></returns>
\r
438 public virtual ClassRef AddClass(string nsName, string name) {
\r
439 ClassRef aClass = new ClassRef(nsName,name,metaData);
\r
440 metaData.AddToTable(MDTable.TypeRef,aClass);
\r
441 aClass.SetParent(this);
\r
446 /// Add a value class to this external assembly
\r
448 /// <param name="nsName">name space name</param>
\r
449 /// <param name="name">class name</param>
\r
450 /// <returns></returns>
\r
451 public virtual ClassRef AddValueClass(string nsName, string name) {
\r
452 ClassRef aClass = new ClassRef(nsName,name,metaData);
\r
453 metaData.AddToTable(MDTable.TypeRef,aClass);
\r
454 aClass.SetParent(this);
\r
455 aClass.MakeValueClass();
\r
459 internal string TypeName() {
\r
460 string result = name;
\r
462 result = result + ", Version=" + major + "." + minor + "." +
\r
463 build + "." + revision;
\r
464 if (keyBytes != null) {
\r
465 string tokenStr = "=";
\r
466 if (isKeyToken) tokenStr = "Token=";
\r
467 result = result + ", PublicKey" + tokenStr;
\r
468 for (int i=0; i < keyBytes.Length; i++) {
\r
469 result = result + Hex.Byte(keyBytes[i]);
\r
472 if (culture != null)
\r
473 result = result + ", Culture=" + culture;
\r
477 internal sealed override uint Size(MetaData md) {
\r
478 return 12 + 2 * md.StringsIndexSize() + 2 * md.BlobIndexSize();
\r
481 internal sealed override void Write(FileImage output) {
\r
482 output.Write(major);
\r
483 output.Write(minor);
\r
484 output.Write(build);
\r
485 output.Write(revision);
\r
486 output.Write(flags);
\r
487 output.BlobIndex(keyIx);
\r
488 output.StringsIndex(nameIx);
\r
489 output.StringsIndex(cultIx);
\r
490 output.BlobIndex(hashIx);
\r
493 internal sealed override uint GetCodedIx(CIx code) {
\r
495 case (CIx.ResolutionScope) : return 2;
\r
496 case (CIx.HasCustomAttr) : return 15;
\r
497 case (CIx.Implementation) : return 1;
\r
503 /**************************************************************************/
\r
506 /// flags for the assembly (.corflags)
\r
508 public enum CorFlags {CF_IL_ONLY, CF_32_BITREQUIRED, CF_STRONGNAMESIGNED,
\r
512 /// subsystem for the assembly (.subsystem)
\r
514 public enum SubSystem { Native = 1, Windows_GUI = 2,
\r
515 Windows_CUI = 3, OS2_CUI = 5, POSIX_CUI = 7, Native_Windows = 8,
\r
516 Windows_CE_GUI = 9}
\r
519 /// Hash algorithms for the assembly
\r
521 public enum HashAlgorithm { None, SHA1 }
\r
524 /// Attributes for this assembly
\r
526 public enum AssemAttr { EnableJITCompileTracking = 0x8000,
\r
527 DisableJITCompileOptimizer = 0x4000}
\r
530 /// Method call conventions
\r
532 public enum CallConv { Default, Cdecl, Stdcall, Thiscall,
\r
533 Fastcall, Vararg, Instance = 0x20, Generic = 0x10, InstanceExplicit = 0x60 }
\r
536 /// Type custom modifier
\r
538 public enum CustomModifier { modreq = 0x1F, modopt };
\r
541 /// Attibutes for a class
\r
543 public enum TypeAttr {Private, Public, NestedPublic, NestedPrivate,
\r
544 NestedFamily, NestedAssembly, NestedFamAndAssem, NestedFamOrAssem,
\r
545 SequentialLayout, ExplicitLayout = 0x10, Interface = 0x20,
\r
546 Abstract = 0x80, PublicAbstract = 0x81, Sealed = 0x100,
\r
547 PublicSealed = 0x101, SpecialName = 0x400, RTSpecialName = 0x800,
\r
548 Import = 0x1000, Serializable = 0x2000, UnicodeClass = 0x10000,
\r
549 AutoClass = 0x20000, BeforeFieldInit = 0x100000 }
\r
552 /// Attributes for a field
\r
554 public enum FieldAttr {Default, Private, FamAndAssem, Assembly,
\r
555 Family, FamOrAssem, Public, Static = 0x10, PublicStatic = 0x16,
\r
556 Initonly = 0x20, Literal = 0x40, Notserialized = 0x80,
\r
557 SpecialName = 0x200, RTSpecialName = 0x400 }
\r
560 /// Attributes for a method
\r
562 public enum MethAttr { Default, Private, FamAndAssem, Assembly,
\r
563 Family, FamOrAssem, Public, Static = 0x0010, PublicStatic = 0x16,
\r
564 Final = 0x0020, PublicStaticFinal = 0x36, Virtual = 0x0040,
\r
565 PrivateVirtual, PublicVirtual = 0x0046, HideBySig = 0x0080,
\r
566 NewSlot = 0x0100, Abstract = 0x0400, SpecialName = 0x0800,
\r
567 RTSpecialName = 0x1000, SpecialRTSpecialName = 0x1800,
\r
568 RequireSecObject = 0x8000}
\r
571 /// Attributes for .pinvokeimpl method declarations
\r
573 public enum PInvokeAttr { nomangle = 1, ansi = 2, unicode = 4, autochar = 6,
574 lasterr = 0x0040, winapi = 0x0100, cdecl = 0x0200,
575 stdcall = 0x0300, thiscall = 0x0400, fastcall = 0x0500 }
\r
578 /// Implementation attributes for a method
\r
580 public enum ImplAttr { IL, Native, Runtime = 0x03, Unmanaged = 0x04,
\r
581 ForwardRef = 0x10, PreserveSig = 0x0080, InternalCall = 0x1000,
\r
582 Synchronised = 0x0020, Synchronized = 0x0020, NoInLining = 0x0008, Optil = 0x0002}
\r
585 /// Modes for a parameter
\r
587 public enum ParamAttr { Default, In, Out, Opt = 4 }
\r
590 /// CIL instructions
\r
592 public enum Op { nop, breakOp, ldarg_0, ldarg_1, ldarg_2, ldarg_3,
\r
593 ldloc_0, ldloc_1, ldloc_2, ldloc_3, stloc_0, stloc_1, stloc_2, stloc_3,
\r
594 ldnull = 0x14, ldc_i4_m1, ldc_i4_0, ldc_i4_1, ldc_i4_2, ldc_i4_3,
\r
595 ldc_i4_4, ldc_i4_5, ldc_i4_6, ldc_i4_7, ldc_i4_8, dup = 0x25, pop,
\r
596 ret = 0x2A, ldind_i1 = 0x46, ldind_u1, ldind_i2, ldind_u2, ldind_i4,
\r
597 ldind_u4, ldind_i8, ldind_i, ldind_r4, ldind_r8, ldind_ref, stind_ref,
\r
598 stind_i1, stind_i2, stind_i4, stind_i8, stind_r4, stind_r8, add, sub, mul,
\r
599 div, div_un, rem, rem_un, and, or, xor, shl, shr, shr_un, neg, not,
\r
600 conv_i1, conv_i2, conv_i4, conv_i8, conv_r4, conv_r8, conv_u4, conv_u8,
\r
601 conv_r_un = 0x76, throwOp = 0x7A, conv_ovf_i1_un = 0x82, conv_ovf_i2_un,
\r
602 conv_ovf_i4_un, conv_ovf_i8_un, conf_ovf_u1_un, conv_ovf_u2_un,
\r
603 conv_ovf_u4_un, conv_ovf_u8_un, conv_ovf_i_un, conv_ovf_u_un,
\r
604 ldlen = 0x8E, ldelem_i1 = 0x90, ldelem_u1, ldelem_i2, ldelem_u2,
\r
605 ldelem_i4, ldelem_u4, ldelem_i8, ldelem_i, ldelem_r4, ldelem_r8,
\r
606 ldelem_ref, stelem_i, stelem_i1, stelem_i2, stelem_i4, stelem_i8, stelem_r4 = 0xA0, stelem_r8,
\r
607 stelem_ref, conv_ovf_i1 = 0xb3, conv_ovf_u1, conv_ovf_i2, conv_ovf_u2,
\r
608 conv_ovf_i4, conv_ovf_u4, conv_ovf_i8, conv_ovf_u8, ckfinite = 0xC3,
\r
609 conv_u2 = 0xD1, conv_u1, conv_i, conv_ovf_i, conv_ovf_u, add_ovf,
\r
610 add_ovf_un, mul_ovf, mul_ovf_un, sub_ovf, sub_ovf_un, endfinally,
\r
611 stind_i = 0xDF, conv_u, arglist = 0xFE00, ceq, cgt, cgt_un, clt, clt_un,
\r
612 localloc = 0xFE0F, endfilter = 0xFE11, volatile_ = 0xFE13, tail_,
\r
613 cpblk = 0xFE17, initblk, rethrow = 0xFE1A, refanytype = 0xFE1D}
\r
616 /// CIL instructions requiring an integer parameter
\r
618 public enum IntOp {ldarg_s = 0x0E, ldarga_s, starg_s, ldloc_s, ldloca_s,
\r
619 stloc_s, ldc_i4_s = 0x1F, ldc_i4, ldarg = 0xFE09,
\r
620 ldarga, starg, ldloc, ldloca, stloc, unaligned = 0xFE12 }
\r
623 /// CIL instructions requiring a field parameter
\r
625 public enum FieldOp {ldfld = 0x7B, ldflda, stfld, ldsfld, ldsflda,
\r
626 stsfld, ldtoken = 0xD0 }
\r
629 /// CIL instructions requiring a method parameter
\r
631 public enum MethodOp {jmp = 0x27, call, callvirt = 0x6F, newobj = 0x73,
\r
632 ldtoken = 0xD0, ldftn = 0xFE06, ldvirtfn }
\r
635 /// CIL instructions requiring a type parameter
\r
637 public enum TypeOp {cpobj = 0x70, ldobj, castclass = 0x74, isinst,
\r
638 unbox = 0x79, stobj = 0x81, box = 0x8C, newarr,
\r
639 ldelema = 0x8F, refanyval = 0xC2, mkrefany = 0xC6,
\r
640 ldtoken = 0xD0, initobj = 0xFE15, sizeOf = 0xFE1C,
\r
641 ldelem = 0xA3, stelem = 0xA4, unbox_any }
\r
644 /// CIL branch instructions
\r
646 public enum BranchOp {
648 br_s = 0x2B, brfalse_s, brtrue_s, beq_s, bge_s, bgt_s,
649 ble_s, blt_s, bne_un_s, bge_un_s, bgt_un_s, ble_un_s, blt_un_s,
651 br = 0x38, brfalse, brtrue, beq, bge, bgt, ble, blt,
\r
652 bne_un, bge_un, bgt_un, ble_un, blt_un,
654 leave = 0xDD, leave_s }
\r
657 /// Index for all the tables in the meta data
\r
659 public enum MDTable { Module, TypeRef, TypeDef, Field = 0x04, Method = 0x06,
\r
660 Param = 0x08, InterfaceImpl, MemberRef, Constant, CustomAttribute,
\r
661 FieldMarshal, DeclSecurity, ClassLayout, FieldLayout, StandAloneSig,
\r
662 EventMap, Event = 0x14, PropertyMap, Property = 0x17, MethodSemantics,
\r
663 MethodImpl, ModuleRef, TypeSpec, ImplMap, FieldRVA, Assembly = 0x20,
\r
664 AssemblyProcessor, AssemblyOS, AssemblyRef, AssemblyRefProcessor,
\r
665 AssemblyRefOS, File, ExportedType, ManifestResource, NestedClass,
\r
666 GenericParam, MethodSpec, GenericParamConstraint }
\r
668 public enum SafeArrayType { int16 = 2, int32, float32, float64,
\r
669 currency, date, bstr, dispatch, error, boolean, variant, unknown,
\r
670 Decimal, int8 = 16, uint8, uint16, uint32, Int = 22, UInt }
\r
672 internal enum CIx { TypeDefOrRef, HasConst, HasCustomAttr, HasFieldMarshal,
\r
673 HasDeclSecurity, MemberRefParent, HasSemantics, MethodDefOrRef,
\r
674 MemberForwarded, Implementation, CustomAttributeType, ResolutionScope,
\r
675 TypeOrMethodDef, MaxCIx }
\r
677 internal enum MapType { eventMap, propertyMap, nestedClass }
\r
679 /**************************************************************************/
\r
681 /// The assembly for mscorlib.
\r
683 public sealed class MSCorLib : AssemblyRef
\r
685 private static readonly int valueTypeIx = 18;
\r
686 private readonly string systemName = "System";
\r
687 private ClassRef[] systemClasses = new ClassRef[valueTypeIx+2];
\r
688 private PrimitiveType[] systemTypes = new PrimitiveType[valueTypeIx];
\r
689 private TypeSpec[] specialTypeSpecs = new TypeSpec[valueTypeIx];
\r
690 private static int[] specialNames = {
\r
691 PrimitiveType.Void.GetName().GetHashCode(),
\r
692 PrimitiveType.Boolean.GetName().GetHashCode(),
\r
693 PrimitiveType.Char.GetName().GetHashCode(),
\r
694 PrimitiveType.Int8.GetName().GetHashCode(),
\r
695 PrimitiveType.UInt8.GetName().GetHashCode(),
\r
696 PrimitiveType.Int16.GetName().GetHashCode(),
\r
697 PrimitiveType.UInt16.GetName().GetHashCode(),
\r
698 PrimitiveType.Int32.GetName().GetHashCode(),
\r
699 PrimitiveType.UInt32.GetName().GetHashCode(),
\r
700 PrimitiveType.Int64.GetName().GetHashCode(),
\r
701 PrimitiveType.UInt64.GetName().GetHashCode(),
\r
702 PrimitiveType.Float32.GetName().GetHashCode(),
\r
703 PrimitiveType.Float64.GetName().GetHashCode(),
\r
704 PrimitiveType.String.GetName().GetHashCode(),
\r
705 PrimitiveType.TypedRef.GetName().GetHashCode(),
\r
706 PrimitiveType.IntPtr.GetName().GetHashCode(),
\r
707 PrimitiveType.UIntPtr.GetName().GetHashCode(),
\r
708 PrimitiveType.Object.GetName().GetHashCode(),
\r
709 "ValueType".GetHashCode(),
\r
710 "Enum".GetHashCode()
\r
713 internal MSCorLib(MetaData md) : base(md,"mscorlib") {
\r
714 md.AddToTable(MDTable.AssemblyRef,this);
\r
715 systemTypes[PrimitiveType.Void.GetSystemTypeIx()] = PrimitiveType.Void;
\r
716 systemTypes[PrimitiveType.Boolean.GetSystemTypeIx()] = PrimitiveType.Boolean;
\r
717 systemTypes[PrimitiveType.Char.GetSystemTypeIx()] = PrimitiveType.Char;
\r
718 systemTypes[PrimitiveType.Int8.GetSystemTypeIx()] = PrimitiveType.Int8;
\r
719 systemTypes[PrimitiveType.UInt8.GetSystemTypeIx()] = PrimitiveType.UInt8;
\r
720 systemTypes[PrimitiveType.Int16.GetSystemTypeIx()] = PrimitiveType.Int16;
\r
721 systemTypes[PrimitiveType.UInt16.GetSystemTypeIx()] = PrimitiveType.UInt16;
\r
722 systemTypes[PrimitiveType.Int32.GetSystemTypeIx()] = PrimitiveType.Int32;
\r
723 systemTypes[PrimitiveType.UInt32.GetSystemTypeIx()] = PrimitiveType.UInt32;
\r
724 systemTypes[PrimitiveType.Int64.GetSystemTypeIx()] = PrimitiveType.Int64;
\r
725 systemTypes[PrimitiveType.UInt64.GetSystemTypeIx()] = PrimitiveType.UInt64;
\r
726 systemTypes[PrimitiveType.Float32.GetSystemTypeIx()] = PrimitiveType.Float32;
\r
727 systemTypes[PrimitiveType.Float64.GetSystemTypeIx()] = PrimitiveType.Float64;
\r
728 systemTypes[PrimitiveType.IntPtr.GetSystemTypeIx()] = PrimitiveType.IntPtr;
\r
729 systemTypes[PrimitiveType.UIntPtr.GetSystemTypeIx()] = PrimitiveType.UIntPtr;
\r
730 systemTypes[PrimitiveType.String.GetSystemTypeIx()] = PrimitiveType.String;
\r
731 systemTypes[PrimitiveType.Object.GetSystemTypeIx()] = PrimitiveType.Object;
\r
732 systemTypes[PrimitiveType.TypedRef.GetSystemTypeIx()] = PrimitiveType.TypedRef;
\r
736 /// Add a class to the mscorlib assembly
\r
738 /// <param name="nsName">name space name</param>
\r
739 /// <param name="name">class name</param>
\r
740 /// <returns></returns>
\r
741 public override ClassRef AddClass(string nsName, string name) {
\r
742 ClassRef aClass = GetSpecialClass(nsName,name);
\r
743 if (aClass == null) {
\r
744 aClass = new ClassRef(nsName,name,metaData);
\r
745 metaData.AddToTable(MDTable.TypeRef,aClass);
\r
746 aClass.SetParent(this);
\r
751 private ClassRef GetSpecialClass(string nsName,string name) {
\r
752 if (nsName.CompareTo(systemName) != 0) return null;
\r
753 int hash = name.GetHashCode();
\r
754 for (int i=0; i < specialNames.Length; i++) {
\r
755 if (hash == specialNames[i]) {
\r
756 if (systemClasses[i] == null) {
\r
757 if (i < valueTypeIx) {
\r
758 systemClasses[i] = new SystemClass(systemTypes[i],this,metaData);
\r
759 if ((systemTypes[i] != PrimitiveType.Object) &&
\r
760 (systemTypes[i] != PrimitiveType.String)) {
\r
761 systemClasses[i].MakeValueClass();
\r
764 systemClasses[i] = new ClassRef(nsName,name,metaData);
\r
765 systemClasses[i].SetParent(this);
\r
766 systemClasses[i].MakeValueClass();
\r
768 metaData.AddToTable(MDTable.TypeRef,systemClasses[i]);
\r
770 return systemClasses[i];
\r
776 internal ClassRef GetSpecialSystemClass(PrimitiveType pType) {
\r
777 int ix = pType.GetSystemTypeIx();
\r
778 if (systemClasses[ix] == null) {
\r
779 systemClasses[ix] = new SystemClass(pType,this,metaData);
\r
780 metaData.AddToTable(MDTable.TypeRef,systemClasses[ix]);
\r
782 return systemClasses[ix];
\r
785 private ClassRef GetValueClass(string name, int hash) {
\r
786 int ix = valueTypeIx;
\r
787 if (hash != specialNames[valueTypeIx]) ix++;
\r
788 if (systemClasses[ix] == null) {
\r
789 systemClasses[ix] = new ClassRef(systemName,name,metaData);
\r
790 systemClasses[ix].SetParent(this);
\r
791 systemClasses[ix].MakeValueClass();
\r
792 metaData.AddToTable(MDTable.TypeRef,systemClasses[ix]);
\r
794 return systemClasses[ix];
\r
797 internal ClassRef ValueType() {
\r
798 if (systemClasses[valueTypeIx] == null) {
\r
799 ClassRef valType = new ClassRef("System","ValueType",metaData);
\r
800 valType.SetParent(this);
\r
801 valType.MakeValueClass();
\r
802 metaData.AddToTable(MDTable.TypeRef,valType);
\r
803 systemClasses[valueTypeIx] = valType;
\r
805 return systemClasses[valueTypeIx];
\r
809 /// Add a value class to this external assembly
\r
811 /// <param name="nsName">name space name</param>
\r
812 /// <param name="name">class name</param>
\r
813 /// <returns></returns>
\r
814 public override ClassRef AddValueClass(string nsName, string name) {
\r
815 if (nsName.CompareTo(systemName) == 0) {
\r
816 int hash = name.GetHashCode();
\r
817 if ((hash == specialNames[valueTypeIx]) ||
\r
818 (hash == specialNames[valueTypeIx+1])) {
\r
819 return GetValueClass(name,hash);
\r
822 ClassRef aClass = new ClassRef(nsName,name,metaData);
\r
823 metaData.AddToTable(MDTable.TypeRef,aClass);
\r
824 aClass.SetParent(this);
\r
825 aClass.MakeValueClass();
\r
830 /**************************************************************************/
\r
832 /// Signature for calli instruction
\r
834 public class CalliSig : Signature
\r
836 private static readonly byte Sentinel = 0x41;
\r
839 Type[] parameters, optParams;
\r
840 uint numPars = 0, numOptPars = 0;
\r
843 /// Create a signature for a calli instruction
\r
845 /// <param name="cconv">calling conventions</param>
\r
846 /// <param name="retType">return type</param>
\r
847 /// <param name="pars">parameter types</param>
\r
848 public CalliSig(CallConv cconv, Type retType, Type[] pars) {
\r
849 tabIx = MDTable.StandAloneSig;
\r
851 returnType = retType;
\r
853 if (pars != null) numPars = (uint)pars.Length;
\r
857 /// Add the optional parameters to a vararg method
\r
858 /// This method sets the vararg calling convention
\r
860 /// <param name="optPars">the optional pars for the vararg call</param>
\r
861 public void AddVarArgs(Type[] optPars) {
\r
862 optParams = optPars;
\r
863 if (optPars != null) numOptPars = (uint)optPars.Length;
\r
864 callConv |= CallConv.Vararg;
\r
868 /// Add extra calling conventions to this callsite signature
\r
870 /// <param name="cconv"></param>
\r
871 public void AddCallingConv(CallConv cconv) {
\r
875 internal sealed override void BuildTables(MetaData md) {
\r
877 MemoryStream sig = new MemoryStream();
\r
878 sig.WriteByte((byte)callConv);
\r
879 MetaData.CompressNum(numPars+numOptPars,sig);
\r
880 returnType.TypeSig(sig);
\r
881 for (int i=0; i < numPars; i++) {
\r
882 parameters[i].TypeSig(sig);
\r
884 sigIx = md.AddToBlobHeap(sig.ToArray());
\r
885 if (numOptPars > 0) {
\r
886 sig.WriteByte(Sentinel);
\r
887 for (int i=0; i < numOptPars; i++) {
\r
888 optParams[i].TypeSig(sig);
\r
895 /**************************************************************************/
\r
897 /// The IL instructions for a method
\r
899 public class CILInstructions
\r
902 private static readonly uint ExHeaderSize = 4;
\r
903 private static readonly uint FatExClauseSize = 24;
\r
904 private static readonly uint SmlExClauseSize = 12;
\r
905 private static readonly sbyte maxByteVal = 127;
\r
906 private static readonly sbyte minByteVal = -128;
\r
907 private static readonly byte maxUByteVal = 255;
\r
908 private static readonly int smallSize = 64;
\r
909 private static readonly ushort TinyFormat = 0x2;
\r
910 private static readonly ushort FatFormat = 0x3003;
\r
911 private static readonly ushort MoreSects = 0x8;
\r
912 private static readonly ushort InitLocals = 0x10;
\r
913 private static readonly uint FatSize = 12;
\r
914 private static readonly uint FatWords = FatSize/4;
\r
915 private static readonly byte FatExceptTable = 0x41;
\r
916 private static readonly byte SmlExceptTable = 0x01;
\r
918 private MetaData metaData;
\r
919 private ArrayList exceptions, blockStack;
\r
920 //private bool codeChecked = false;
\r
921 private static readonly int INITSIZE = 5;
\r
922 private CILInstruction[] buffer = new CILInstruction[INITSIZE];
\r
923 private int tide = 0;
\r
924 private uint offset = 0;
\r
925 private ushort headerFlags = 0;
\r
926 private short maxStack;
\r
927 private uint paddingNeeded = 0;
\r
928 private byte exceptHeader = 0;
\r
929 uint localSigIx = 0;
\r
930 uint codeSize = 0, exceptSize = 0;
\r
931 bool tinyFormat, fatExceptionFormat = false;
\r
933 internal CILInstructions(MetaData md) {
\r
937 private void AddToBuffer(CILInstruction inst) {
\r
938 if (tide >= buffer.Length) {
\r
939 CILInstruction[] tmp = buffer;
\r
940 buffer = new CILInstruction[tmp.Length * 2];
\r
941 for (int i=0; i < tide; i++) {
\r
942 buffer[i] = tmp[i];
\r
945 //Console.WriteLine("Adding instruction at offset " + offset + " with size " + inst.size);
\r
946 inst.offset = offset;
\r
947 offset += inst.size;
\r
948 buffer[tide++] = inst;
\r
952 /// Add a simple IL instruction
\r
954 /// <param name="inst">the IL instruction</param>
\r
955 public void Inst(Op inst) {
\r
956 AddToBuffer(new Instr((int)inst));
\r
960 /// Add an IL instruction with an integer parameter
\r
962 /// <param name="inst">the IL instruction</param>
\r
963 /// <param name="val">the integer parameter value</param>
\r
964 public void IntInst(IntOp inst, int val) {
\r
965 int instr = (int)inst;
\r
966 if ((inst == IntOp.ldc_i4_s) || (inst == IntOp.ldc_i4))
\r
967 AddToBuffer(new IntInstr(instr,val,(inst == IntOp.ldc_i4_s)));
\r
969 AddToBuffer(new UIntInstr(instr,val,((inst < IntOp.ldc_i4_s) ||
\r
970 (inst == IntOp.unaligned))));
\r
974 /// Add the load long instruction
\r
976 /// <param name="cVal">the long value</param>
\r
977 public void ldc_i8(long cVal) {
\r
978 AddToBuffer(new LongInstr(0x21,cVal));
\r
982 /// Add the load float32 instruction
\r
984 /// <param name="cVal">the float value</param>
\r
985 public void ldc_r4(float cVal) {
\r
986 AddToBuffer(new FloatInstr(0x22,cVal));
\r
990 /// Add the load float64 instruction
\r
992 /// <param name="cVal">the float value</param>
\r
993 public void ldc_r8(double cVal) {
\r
994 AddToBuffer(new DoubleInstr(0x23,cVal));
\r
998 /// Add the load string instruction
\r
1000 /// <param name="str">the string value</param>
\r
1001 public void ldstr(string str) {
\r
1002 AddToBuffer(new StringInstr(0x72,str));
\r
1006 /// Add the calli instruction
\r
1008 /// <param name="sig">the signature for the calli</param>
\r
1009 public void calli(CalliSig sig) {
\r
1010 AddToBuffer(new SigInstr(0x29,sig));
\r
1014 /// Add a label to the CIL instructions
\r
1016 /// <param name="lab">the label to be added</param>
\r
1017 public void CodeLabel(CILLabel lab) {
\r
1018 AddToBuffer(new LabelInstr(lab));
\r
1022 /// Add an instruction with a field parameter
\r
1024 /// <param name="inst">the CIL instruction</param>
\r
1025 /// <param name="f">the field parameter</param>
\r
1026 public void FieldInst(FieldOp inst, Field f) {
\r
1027 AddToBuffer(new FieldInstr((int)inst,f));
\r
1031 /// Add an instruction with a method parameter
\r
1033 /// <param name="inst">the CIL instruction</param>
\r
1034 /// <param name="m">the method parameter</param>
\r
1035 public void MethInst(MethodOp inst, Method m) {
\r
1036 AddToBuffer(new MethInstr((int)inst,m));
\r
1040 /// Add an instruction with a type parameter
\r
1042 /// <param name="inst">the CIL instruction</param>
\r
1043 /// <param name="t">the type argument for the CIL instruction</param>
\r
1044 public void TypeInst(TypeOp inst, Type aType) {
\r
1045 AddToBuffer(new TypeInstr((int)inst,aType,metaData));
\r
1049 /// Add a branch instruction
\r
1051 /// <param name="inst">the branch instruction</param>
\r
1052 /// <param name="lab">the label that is the target of the branch</param>
\r
1053 public void Branch(BranchOp inst, CILLabel lab) {
\r
1054 AddToBuffer(new BranchInstr((int)inst,lab));
\r
1058 /// Add a switch instruction
\r
1060 /// <param name="labs">the target labels for the switch</param>
\r
1061 public void Switch(CILLabel[] labs) {
\r
1062 AddToBuffer(new SwitchInstr(0x45,labs));
\r
1066 /// Add a byte to the CIL instructions (.emitbyte)
\r
1068 /// <param name="bVal"></param>
\r
1069 public void emitbyte(byte bVal) {
\r
1070 AddToBuffer(new CILByte(bVal));
\r
1074 /// Add an instruction which puts an integer on TOS. This method
\r
1075 /// selects the correct instruction based on the value of the integer.
\r
1077 /// <param name="i">the integer value</param>
\r
1078 public void PushInt(int i) {
\r
1080 AddToBuffer(new Instr((int)Op.ldc_i4_m1));
\r
1081 } else if ((i >= 0) && (i <= 8)) {
\r
1082 Op op = (Op)(Op.ldc_i4_0 + i);
\r
1083 AddToBuffer(new Instr((int)op));
\r
1084 } else if ((i >= minByteVal) && (i <= maxByteVal)) {
\r
1085 AddToBuffer(new IntInstr((int)IntOp.ldc_i4_s,i,true));
\r
1087 AddToBuffer(new IntInstr((int)IntOp.ldc_i4,i,false));
\r
1092 /// Add the instruction to load a long on TOS
\r
1094 /// <param name="l">the long value</param>
\r
1095 public void PushLong(long l) {
\r
1096 AddToBuffer(new LongInstr(0x21,l));
\r
1100 /// Add an instruction to push the boolean value true on TOS
\r
1102 public void PushTrue() {
\r
1103 AddToBuffer(new Instr((int)Op.ldc_i4_1));
\r
1107 /// Add an instruction to push the boolean value false on TOS
\r
1109 public void PushFalse() {
\r
1110 AddToBuffer(new Instr((int)Op.ldc_i4_0));
\r
1114 /// Add the instruction to load an argument on TOS. This method
\r
1115 /// selects the correct instruction based on the value of argNo
\r
1117 /// <param name="argNo">the number of the argument</param>
\r
1118 public void LoadArg(int argNo) {
\r
1120 int op = (int)Op.ldarg_0 + argNo;
\r
1121 AddToBuffer(new Instr(op));
\r
1122 } else if (argNo <= maxUByteVal) {
\r
1123 AddToBuffer(new UIntInstr((int)IntOp.ldarg,argNo,true));
\r
1125 AddToBuffer(new UIntInstr(0x09,argNo,false));
\r
1130 /// Add the instruction to load the address of an argument on TOS.
\r
1131 /// This method selects the correct instruction based on the value
\r
1134 /// <param name="argNo">the number of the argument</param>
\r
1135 public void LoadArgAdr(int argNo) {
\r
1136 if (argNo <= maxUByteVal) {
\r
1137 AddToBuffer(new UIntInstr((int)IntOp.ldarga,argNo,true));
\r
1139 AddToBuffer(new UIntInstr(0x0A,argNo,false));
\r
1144 /// Add the instruction to load a local on TOS. This method selects
\r
1145 /// the correct instruction based on the value of locNo.
\r
1147 /// <param name="locNo">the number of the local to load</param>
\r
1148 public void LoadLocal(int locNo) {
\r
1150 int op = (int)Op.ldloc_0 + locNo;
\r
1151 AddToBuffer(new Instr(op));
\r
1152 } else if (locNo <= maxUByteVal) {
\r
1153 AddToBuffer(new UIntInstr((int)IntOp.ldloc,locNo,true));
\r
1155 AddToBuffer(new UIntInstr(0x0C,locNo,false));
\r
1160 /// Add the instruction to load the address of a local on TOS.
\r
1161 /// This method selects the correct instruction based on the
\r
1162 /// value of locNo.
\r
1164 /// <param name="locNo">the number of the local</param>
\r
1165 public void LoadLocalAdr(int locNo) {
\r
1166 if (locNo <= maxUByteVal) {
\r
1167 AddToBuffer(new UIntInstr((int)IntOp.ldloca,locNo,true));
\r
1169 AddToBuffer(new UIntInstr(0x0D,locNo,false));
\r
1174 /// Add the instruction to store to an argument. This method
\r
1175 /// selects the correct instruction based on the value of argNo.
\r
1177 /// <param name="argNo">the argument to be stored to</param>
\r
1178 public void StoreArg(int argNo) {
\r
1179 if (argNo <= maxUByteVal) {
\r
1180 AddToBuffer(new UIntInstr((int)IntOp.starg,argNo,true));
\r
1182 AddToBuffer(new UIntInstr(0x0B,argNo,false));
\r
1187 /// Add the instruction to store to a local. This method selects
\r
1188 /// the correct instruction based on the value of locNo.
\r
1190 /// <param name="locNo">the local to be stored to</param>
\r
1191 public void StoreLocal(int locNo) {
\r
1193 int op = (int)Op.stloc_0 + locNo;
\r
1194 AddToBuffer(new Instr(op));
\r
1195 } else if (locNo <= maxUByteVal) {
\r
1196 AddToBuffer(new UIntInstr((int)IntOp.stloc,locNo,true));
\r
1198 AddToBuffer(new UIntInstr(0x0E,locNo,false));
\r
1203 /// Create a new CIL label. To place the label in the CIL instruction
\r
1204 /// stream use CodeLabel.
\r
1206 /// <returns>a new CIL label</returns>
\r
1207 public CILLabel NewLabel() {
\r
1208 return new CILLabel();
\r
1211 public void AddTryBlock(TryBlock tryBlock) {
\r
1212 if (exceptions == null)
\r
1213 exceptions = new ArrayList();
\r
1214 else if (exceptions.Contains(tryBlock)) return;
\r
1215 exceptions.Add(tryBlock);
\r
1219 /// Create a new label at this position in the code buffer
\r
1221 /// <returns>the label at the current position</returns>
\r
1222 public CILLabel NewCodedLabel() {
\r
1223 CILLabel lab = new CILLabel();
\r
1224 AddToBuffer(new LabelInstr(lab));
\r
1229 /// Mark this position as the start of a new block
\r
1230 /// (try, catch, filter, finally or fault)
\r
1232 public void StartBlock() {
\r
1233 if (blockStack == null) blockStack = new ArrayList();
\r
1234 blockStack.Insert(0,NewCodedLabel());
\r
1238 /// Mark this position as the end of the last started block and
\r
1239 /// make it a try block. This try block is added to the current
\r
1240 /// instructions (ie do not need to call AddTryBlock)
\r
1242 /// <returns>The try block just ended</returns>
\r
1243 public TryBlock EndTryBlock() {
\r
1244 TryBlock tBlock = new TryBlock((CILLabel)blockStack[0],NewCodedLabel());
\r
1245 blockStack.RemoveAt(0);
\r
1246 AddTryBlock(tBlock);
\r
1251 /// Mark this position as the end of the last started block and
\r
1252 /// make it a catch block. This catch block is associated with the
\r
1253 /// specified try block.
\r
1255 /// <param name="exceptType">the exception type to be caught</param>
\r
1256 /// <param name="tryBlock">the try block associated with this catch block</param>
\r
1257 public void EndCatchBlock(Class exceptType, TryBlock tryBlock) {
\r
1258 Catch catchBlock = new Catch(exceptType,(CILLabel)blockStack[0],
\r
1260 tryBlock.AddHandler(catchBlock);
\r
1264 /// Mark this position as the end of the last started block and
\r
1265 /// make it a filter block. This filter block is associated with the
\r
1266 /// specified try block.
\r
1268 /// <param name="filterLab">the label where the filter code is</param>
\r
1269 /// <param name="tryBlock">the try block associated with this filter block</param>
\r
1270 public void EndFilterBlock(CILLabel filterLab, TryBlock tryBlock) {
\r
1271 Filter filBlock = new Filter(filterLab,(CILLabel)blockStack[0],NewCodedLabel());
\r
1272 tryBlock.AddHandler(filBlock);
\r
1276 /// Mark this position as the end of the last started block and
\r
1277 /// make it a finally block. This finally block is associated with the
\r
1278 /// specified try block.
\r
1280 /// <param name="tryBlock">the try block associated with this finally block</param>
\r
1281 public void EndFinallyBlock(TryBlock tryBlock) {
\r
1282 Finally finBlock= new Finally((CILLabel)blockStack[0],NewCodedLabel());
\r
1283 tryBlock.AddHandler(finBlock);
\r
1287 /// Mark this position as the end of the last started block and
\r
1288 /// make it a fault block. This fault block is associated with the
\r
1289 /// specified try block.
\r
1291 /// <param name="tryBlock">the try block associated with this fault block</param>
\r
1292 public void EndFaultBlock(TryBlock tryBlock) {
\r
1293 Fault fBlock= new Fault((CILLabel)blockStack[0],NewCodedLabel());
\r
1294 tryBlock.AddHandler(fBlock);
\r
1297 internal uint GetCodeSize() {
\r
1298 return codeSize + paddingNeeded + exceptSize;
\r
1301 internal void CheckCode(uint locSigIx, bool initLocals, int maxStack) {
\r
1302 if (tide == 0) return;
\r
1303 bool changed = true;
\r
1306 for (int i=0; i < tide; i++) {
\r
1307 changed = buffer[i].Check(metaData) || changed;
\r
1310 for (int i=1; i < tide; i++) {
\r
1311 buffer[i].offset = buffer[i-1].offset + buffer[i-1].size;
\r
1313 offset = buffer[tide-1].offset + buffer[tide-1].size;
\r
1316 codeSize = offset;
\r
1317 // Console.WriteLine("codeSize before header added = " + codeSize);
\r
1318 if ((offset < smallSize) && (maxStack <= 8) && (locSigIx == 0) && (exceptions == null)) {
\r
1319 // can use tiny header
\r
1320 //Console.WriteLine("Tiny Header");
\r
1321 tinyFormat = true;
\r
1322 headerFlags = (ushort)(TinyFormat | ((ushort)codeSize << 2));
\r
1324 if ((codeSize % 4) != 0) { paddingNeeded = 4 - (codeSize % 4); }
\r
1326 //Console.WriteLine("Fat Header");
\r
1327 tinyFormat = false;
\r
1328 localSigIx = locSigIx;
\r
1329 this.maxStack = (short)maxStack;
\r
1330 headerFlags = FatFormat;
\r
1331 if (exceptions != null) {
\r
1332 // Console.WriteLine("Got exceptions");
\r
1333 headerFlags |= MoreSects;
\r
1334 uint numExceptClauses = 0;
\r
1335 for (int i=0; i < exceptions.Count; i++) {
\r
1336 TryBlock tryBlock = (TryBlock)exceptions[i];
\r
1337 tryBlock.SetSize();
\r
1338 numExceptClauses += (uint)tryBlock.NumHandlers();
\r
1339 if (tryBlock.isFat()) fatExceptionFormat = true;
\r
1341 // Console.WriteLine("numexceptclauses = " + numExceptClauses);
\r
1342 if (fatExceptionFormat) {
\r
1343 // Console.WriteLine("Fat exception format");
\r
1344 exceptHeader = FatExceptTable;
\r
1345 exceptSize = ExHeaderSize + numExceptClauses * FatExClauseSize;
\r
1347 // Console.WriteLine("Tiny exception format");
\r
1348 exceptHeader = SmlExceptTable;
\r
1349 exceptSize = ExHeaderSize + numExceptClauses * SmlExClauseSize;
\r
1351 // Console.WriteLine("exceptSize = " + exceptSize);
\r
1353 if (initLocals) headerFlags |= InitLocals;
\r
1354 if ((offset % 4) != 0) { paddingNeeded = 4 - (offset % 4); }
\r
1355 codeSize += FatSize;
\r
1357 // Console.WriteLine("codeSize = " + codeSize + " headerFlags = " +
\r
1358 // Hex.Short(headerFlags));
\r
1361 internal void Write(FileImage output) {
\r
1362 // Console.WriteLine("Writing header flags = " + Hex.Short(headerFlags));
\r
1364 // Console.WriteLine("Writing tiny code");
\r
1365 output.Write((byte)headerFlags);
\r
1367 // Console.WriteLine("Writing fat code");
\r
1368 output.Write(headerFlags);
\r
1369 output.Write((ushort)maxStack);
\r
1370 output.Write(offset);
\r
1371 output.Write(localSigIx);
\r
1373 // Console.WriteLine(Hex.Int(tide) + " CIL instructions");
\r
1374 // Console.WriteLine("starting instructions at " + output.Seek(0,SeekOrigin.Current));
\r
1375 for (int i=0; i < tide; i++) {
\r
1376 buffer[i].Write(output);
\r
1378 // Console.WriteLine("ending instructions at " + output.Seek(0,SeekOrigin.Current));
\r
1379 for (int i=0; i < paddingNeeded; i++) { output.Write((byte)0); }
\r
1380 if (exceptions != null) {
\r
1381 // Console.WriteLine("Writing exceptions");
\r
1382 // Console.WriteLine("header = " + Hex.Short(exceptHeader) + " exceptSize = " + Hex.Int(exceptSize));
\r
1383 output.Write(exceptHeader);
\r
1384 output.Write3Bytes((uint)exceptSize);
\r
1385 for (int i=0; i < exceptions.Count; i++) {
\r
1386 TryBlock tryBlock = (TryBlock)exceptions[i];
\r
1387 tryBlock.Write(output,fatExceptionFormat);
\r
1393 /**************************************************************************/
\r
1395 /// A label in the IL
\r
1397 public class CILLabel
\r
1399 CILInstruction branch;
\r
1400 CILInstruction[] multipleBranches;
\r
1402 CILInstruction labInstr;
\r
1405 public CILLabel (uint offset) {
\r
1406 this.offset = offset;
\r
1410 internal CILLabel() {
\r
1413 internal void AddBranch(CILInstruction instr) {
\r
1414 if (branch == null) {
\r
1418 if (multipleBranches == null) {
\r
1419 multipleBranches = new CILInstruction[2];
\r
1420 } else if (tide >= multipleBranches.Length) {
\r
1421 CILInstruction[] tmp = multipleBranches;
\r
1422 multipleBranches = new CILInstruction[tmp.Length*2];
\r
1423 for (int i=0; i < tide; i++) {
\r
1424 multipleBranches[i] = tmp[i];
\r
1427 multipleBranches[tide++] = instr;
\r
1430 internal void AddLabelInstr(LabelInstr lInstr) {
\r
1431 labInstr = lInstr;
\r
1434 internal uint GetLabelOffset() {
\r
1435 if (labInstr == null) return 0;
\r
1436 return labInstr.offset + offset;
\r
1440 /**************************************************************************/
\r
1441 public abstract class CodeBlock {
\r
1443 private static readonly int maxCodeSize = 256;
\r
1444 protected CILLabel start, end;
\r
1445 protected bool small = true;
\r
1447 public CodeBlock(CILLabel start, CILLabel end) {
\r
1448 this.start = start;
\r
1452 internal virtual bool isFat() {
\r
1453 // Console.WriteLine("block start = " + start.GetLabelOffset() +
\r
1454 // " block end = " + end.GetLabelOffset());
\r
1455 return (end.GetLabelOffset() - start.GetLabelOffset()) > maxCodeSize;
\r
1458 internal virtual void Write(FileImage output, bool fatFormat) {
\r
1459 if (fatFormat) output.Write(start.GetLabelOffset());
\r
1460 else output.Write((short)start.GetLabelOffset());
\r
1461 uint len = end.GetLabelOffset() - start.GetLabelOffset();
\r
1462 if (fatFormat) output.Write(len);
\r
1463 else output.Write((byte)len);
\r
1469 /// The descriptor for a guarded block (.try)
\r
1471 public class TryBlock : CodeBlock {
\r
1472 protected bool fatFormat = false;
\r
1473 protected int flags = 0;
\r
1474 ArrayList handlers = new ArrayList();
\r
1477 /// Create a new try block
\r
1479 /// <param name="start">start label for the try block</param>
\r
1480 /// <param name="end">end label for the try block</param>
\r
1481 public TryBlock(CILLabel start, CILLabel end) : base(start,end) { }
\r
1484 /// Add a handler to this try block
\r
1486 /// <param name="handler">a handler to be added to the try block</param>
\r
1487 public void AddHandler(HandlerBlock handler) {
\r
1488 flags = handler.GetFlag();
\r
1489 handlers.Add(handler);
\r
1492 internal void SetSize() {
\r
1493 fatFormat = base.isFat();
\r
1494 if (fatFormat) return;
\r
1495 for (int i=0; i < handlers.Count; i++) {
\r
1496 HandlerBlock handler = (HandlerBlock)handlers[i];
\r
1497 if (handler.isFat()) {
\r
1504 internal int NumHandlers() {
\r
1505 return handlers.Count;
\r
1508 internal override bool isFat() {
\r
1512 internal override void Write(FileImage output, bool fatFormat) {
\r
1513 // Console.WriteLine("writing exception details");
\r
1514 for (int i=0; i < handlers.Count; i++) {
\r
1515 // Console.WriteLine("Except block " + i);
\r
1516 HandlerBlock handler = (HandlerBlock)handlers[i];
\r
1517 if (fatFormat) output.Write(flags);
\r
1518 else output.Write((short)flags);
\r
1519 // Console.WriteLine("flags = " + Hex.Short(flags));
\r
1520 base.Write(output,fatFormat);
\r
1521 handler.Write(output,fatFormat);
\r
1526 public abstract class HandlerBlock : CodeBlock
\r
1528 protected static readonly short ExceptionFlag = 0;
\r
1529 protected static readonly short FilterFlag = 0x01;
\r
1530 protected static readonly short FinallyFlag = 0x02;
\r
1531 protected static readonly short FaultFlag = 0x04;
\r
1533 public HandlerBlock(CILLabel start, CILLabel end) : base(start,end) { }
\r
1535 internal virtual short GetFlag() { return ExceptionFlag; }
\r
1537 internal override void Write(FileImage output, bool fatFormat) {
\r
1538 base.Write(output,fatFormat);
\r
1544 /// The descriptor for a catch clause (.catch)
\r
1546 public class Catch : HandlerBlock
\r
1551 /// Create a new catch clause
\r
1553 /// <param name="except">the exception to be caught</param>
\r
1554 /// <param name="handlerStart">start of the handler code</param>
\r
1555 /// <param name="handlerEnd">end of the handler code</param>
\r
1556 public Catch(Class except, CILLabel handlerStart, CILLabel handlerEnd)
\r
1557 : base(handlerStart,handlerEnd) {
\r
1558 exceptType = except;
\r
1561 internal override void Write(FileImage output, bool fatFormat) {
\r
1562 base.Write(output,fatFormat);
\r
1563 output.Write(exceptType.Token());
\r
1568 /// The descriptor for a filter clause (.filter)
\r
1570 public class Filter : HandlerBlock
\r
1572 CILLabel filterLabel;
\r
1575 /// Create a new filter clause
\r
1577 /// <param name="filterLabel">the label where the filter code starts</param>
\r
1578 /// <param name="handlerStart">the start of the handler code</param>
\r
1579 /// <param name="handlerEnd">the end of the handler code</param>
\r
1580 public Filter(CILLabel filterLabel, CILLabel handlerStart,
\r
1581 CILLabel handlerEnd) : base(handlerStart,handlerEnd) {
\r
1582 this.filterLabel = filterLabel;
\r
1585 internal override short GetFlag() {
\r
1586 return FilterFlag;
\r
1589 internal override void Write(FileImage output, bool fatFormat) {
\r
1590 base.Write(output,fatFormat);
\r
1591 output.Write(filterLabel.GetLabelOffset());
\r
1597 /// Descriptor for a finally block (.finally)
\r
1599 public class Finally : HandlerBlock
\r
1602 /// Create a new finally clause
\r
1604 /// <param name="finallyStart">start of finally code</param>
\r
1605 /// <param name="finallyEnd">end of finally code</param>
\r
1606 public Finally(CILLabel finallyStart, CILLabel finallyEnd)
\r
1607 : base(finallyStart,finallyEnd) { }
\r
1609 internal override short GetFlag() {
\r
1610 return FinallyFlag;
\r
1613 internal override void Write(FileImage output, bool fatFormat) {
\r
1614 base.Write(output,fatFormat);
\r
1615 output.Write((int)0);
\r
1621 /// Descriptor for a fault block (.fault)
\r
1623 public class Fault : HandlerBlock
\r
1626 /// Create a new fault clause
\r
1628 /// <param name="faultStart">start of the fault code</param>
\r
1629 /// <param name="faultEnd">end of the fault code</param>
\r
1630 public Fault(CILLabel faultStart, CILLabel faultEnd)
\r
1631 : base(faultStart,faultEnd) { }
\r
1633 internal override short GetFlag() {
\r
1634 return FaultFlag;
\r
1637 internal override void Write(FileImage output, bool fatFormat) {
\r
1638 base.Write(output,fatFormat);
\r
1639 output.Write((int)0);
\r
1644 /**************************************************************************/
\r
1646 /// The base descriptor for a class
\r
1648 public abstract class Class : Type
\r
1650 protected int row = 0;
\r
1651 protected string name, nameSpace;
\r
1652 protected uint nameIx, nameSpaceIx;
\r
1653 protected MetaData _metaData;
\r
1654 internal Class(string nameSpaceName, string className, MetaData md)
\r
1656 nameSpace = nameSpaceName;
\r
1658 nameIx = md.AddToStringsHeap(name);
\r
1659 nameSpaceIx = md.AddToStringsHeap(nameSpace);
\r
1663 internal Class(uint nsIx, uint nIx) : base(0x12) {
\r
1664 nameSpaceIx = nsIx;
\r
1668 internal virtual uint TypeDefOrRefToken() { return 0; }
\r
1670 internal virtual void MakeValueClass() {
\r
1674 internal virtual string TypeName() {
\r
1675 return (nameSpace + "." + name);
\r
1678 internal override MetaDataElement GetTypeSpec(MetaData md) {
\r
1682 /**************************************************************************/
\r
1683 // This Class produces entries in the TypeDef table of the MetaData
\r
1684 // in the PE meta data.
\r
1686 // NOTE: Entry 0 in TypeDef table is always the pseudo class <module>
\r
1687 // which is the parent for functions and variables declared a module level
\r
1690 /// The descriptor for a class defined in the IL (.class) in the current assembly/module
\r
1693 public class ClassDef : Class
\r
1695 private static readonly uint HasSecurity = 0x00040000;
\r
1696 private static readonly byte ElementType_Class = 0x12;
\r
1699 ArrayList fields = new ArrayList();
\r
1700 ArrayList methods = new ArrayList();
\r
1702 ArrayList properties;
\r
1703 bool typeIndexChecked = true;
\r
1704 uint fieldIx = 0, methodIx = 0;
\r
1705 byte[] securityActions;
\r
1707 ClassLayout layout;
\r
1708 ClassDef parentClass;
\r
1709 MetaData metaData;
\r
1711 internal ClassDef(TypeAttr attrSet, string nsName, string name,
\r
1712 MetaData md) : base(nsName, name, md) {
\r
1714 superType = metaData.mscorlib.GetSpecialSystemClass(PrimitiveType.Object);
\r
1715 flags = (uint)attrSet;
\r
1716 tabIx = MDTable.TypeDef;
\r
1719 internal void SetSuper(Class sClass) {
\r
1720 superType = sClass;
\r
1721 if (sClass is ClassRef)
\r
1722 typeIndex = superType.GetTypeIndex();
\r
1724 typeIndexChecked = false;
\r
1727 internal override void MakeValueClass() {
\r
1728 superType = metaData.mscorlib.ValueType();
\r
1729 typeIndex = superType.GetTypeIndex();
\r
1732 public void SpecialNoSuper() {
\r
1737 /// Add an attribute to this class
\r
1739 /// <param name="ta">the attribute to be added</param>
\r
1740 public void AddAttribute(TypeAttr ta) {
\r
1741 flags |= (uint)ta;
\r
1745 /// Add an interface that is implemented by this class
\r
1747 /// <param name="iFace">the interface that is implemented</param>
\r
1748 public void AddImplementedInterface(Class iFace) {
\r
1749 metaData.AddToTable(MDTable.InterfaceImpl,new InterfaceImpl(this,iFace));
\r
1753 /// Add a named generic type parameter
\r
1755 public GenericParameter AddGenericParameter (short index, string name) {
\r
1756 GenericParameter gp = new GenericParameter (this, metaData, index, name);
1757 metaData.AddToTable (MDTable.GenericParam, gp);
\r
1762 /// Add a field to this class
\r
1764 /// <param name="name">field name</param>
\r
1765 /// <param name="fType">field type</param>
\r
1766 /// <returns>a descriptor for this new field</returns>
\r
1767 public FieldDef AddField(string name, Type fType) {
\r
1768 FieldDef field = new FieldDef(name,fType);
\r
1769 fields.Add(field);
\r
1774 /// Add a field to this class
\r
1776 /// <param name="fAtts">attributes for this field</param>
\r
1777 /// <param name="name">field name</param>
\r
1778 /// <param name="fType">field type</param>
\r
1779 /// <returns>a descriptor for this new field</returns>
\r
1780 public FieldDef AddField(FieldAttr fAtts, string name, Type fType) {
\r
1781 FieldDef field = new FieldDef(fAtts,name,fType);
\r
1782 fields.Add(field);
\r
1787 /// Add a method to this class
\r
1789 /// <param name="name">method name</param>
\r
1790 /// <param name="retType">return type</param>
\r
1791 /// <param name="pars">parameters</param>
\r
1792 /// <returns>a descriptor for this new method</returns>
\r
1793 public MethodDef AddMethod(string name, Type retType, Param[] pars) {
\r
1794 // Console.WriteLine("Adding method " + name + " to class " + this.name);
\r
1795 MethodDef meth = new MethodDef(metaData,name,retType, pars);
\r
1796 methods.Add(meth);
\r
1801 /// Add a method to this class
\r
1803 /// <param name="mAtts">attributes for this method</param>
\r
1804 /// <param name="iAtts">implementation attributes for this method</param>
\r
1805 /// <param name="name">method name</param>
\r
1806 /// <param name="retType">return type</param>
\r
1807 /// <param name="pars">parameters</param>
\r
1808 /// <returns>a descriptor for this new method</returns>
\r
1809 public MethodDef AddMethod(MethAttr mAtts, ImplAttr iAtts, string name,
\r
1810 Type retType, Param[] pars) {
\r
1811 // Console.WriteLine("Adding method " + name + " to class " + this.name);
\r
1812 MethodDef meth = new MethodDef(metaData,mAtts,iAtts,name,retType,pars);
\r
1813 methods.Add(meth);
\r
1818 /// Add an event to this class
\r
1820 /// <param name="name">event name</param>
\r
1821 /// <param name="eType">event type</param>
\r
1822 /// <returns>a descriptor for this new event</returns>
\r
1823 public Event AddEvent(string name, Type eType) {
\r
1824 Event e = new Event(name,eType,this);
\r
1825 if (events == null) events = new ArrayList();
\r
1831 /// Add a property to this class
\r
1833 /// <param name="name">property name</param>
\r
1834 /// <param name="propType">property type</param>
\r
1835 /// <returns>a descriptor for this new property</returns>
\r
1836 public Property AddProperty(string name, Type retType, Type[] pars) {
\r
1837 Property p = new Property(name, retType, pars, this);
\r
1838 if (properties == null) properties = new ArrayList();
\r
1839 properties.Add(p);
\r
1845 /// Add a nested class to this class
\r
1847 /// <param name="attrSet">attributes for this nested class</param>
\r
1848 /// <param name="nsName">nested name space name</param>
\r
1849 /// <param name="name">nested class name</param>
\r
1850 /// <returns>a descriptor for this new nested class</returns>
\r
1851 public ClassDef AddNestedClass(TypeAttr attrSet, string nsName,
\r
1853 ClassDef nClass = new ClassDef(attrSet,nsName,name,metaData);
\r
1854 metaData.AddToTable(MDTable.TypeDef,nClass);
\r
1855 metaData.AddToTable(MDTable.NestedClass,new MapElem(nClass,Row,MDTable.TypeDef));
\r
1856 nClass.parentClass = this;
\r
1861 /// Add a nested class to this class
\r
1863 /// <param name="attrSet">attributes for this nested class</param>
\r
1864 /// <param name="nsName">nested name space name</param>
\r
1865 /// <param name="name">nested class name</param>
\r
1866 /// <param name="sType">super type of this nested class</param>
\r
1867 /// <returns>a descriptor for this new nested class</returns>
\r
1868 public ClassDef AddNestedClass(TypeAttr attrSet, string nsName,
\r
1869 string name, Class sType) {
\r
1870 ClassDef nClass = new ClassDef(attrSet,nsName,name,metaData);
\r
1871 nClass.SetSuper(sType);
\r
1872 metaData.AddToTable(MDTable.TypeDef,nClass);
\r
1873 metaData.AddToTable(MDTable.NestedClass,
\r
1874 new MapElem(nClass,Row,MDTable.TypeDef));
\r
1875 nClass.parentClass = this;
\r
1880 /// Add layout information for this class. This class must have the
\r
1881 /// sequential or explicit attribute.
\r
1883 /// <param name="packSize">packing size (.pack)</param>
\r
1884 /// <param name="classSize">class size (.size)</param>
\r
1885 public void AddLayoutInfo (int packSize, int classSize) {
\r
1886 layout = new ClassLayout(packSize,classSize,this);
\r
1890 /// Use a method as the implementation for another method (.override)
\r
1892 /// <param name="decl">the method to be overridden</param>
\r
1893 /// <param name="body">the implementation to be used</param>
\r
1894 public void AddMethodOverride(Method decl, Method body) {
\r
1895 metaData.AddToTable(MDTable.MethodImpl,new MethodImpl(this,decl,body));
\r
1899 /// Add security to this class NOT YET IMPLEMENTED
\r
1901 /// <param name="permissionSet"></param>
\r
1902 public void AddSecurity(byte[] permissionSet) {
\r
1903 throw(new NotYetImplementedException("Class security "));
\r
1904 //flags |= HasSecurity;
\r
1905 // securityActions = permissionSet;
\r
1908 //public void AddLineInfo(int row, int col) { }
\r
1910 internal void CheckTypeIndex() {
\r
1911 if (typeIndexChecked) return;
\r
1912 if (!(superType is ClassRef))
\r
1913 ((ClassDef)superType).CheckTypeIndex();
\r
1914 typeIndex = superType.GetTypeIndex();
\r
1915 typeIndexChecked = true;
\r
1918 internal sealed override void BuildTables(MetaData md) {
\r
1920 if ((flags & (uint)TypeAttr.Interface) != 0) { superType = null; }
\r
1921 // Console.WriteLine("Building tables for " + name);
\r
1922 if (layout != null) md.AddToTable(MDTable.ClassLayout,layout);
\r
1923 // Console.WriteLine("adding methods " + methods.Count);
\r
1924 methodIx = md.TableIndex(MDTable.Method);
\r
1925 for (int i=0; i < methods.Count; i++) {
\r
1926 md.AddToTable(MDTable.Method,(MetaDataElement)methods[i]);
\r
1927 ((MethodDef)methods[i]).BuildTables(md);
\r
1929 // Console.WriteLine("adding fields");
\r
1930 fieldIx = md.TableIndex(MDTable.Field);
\r
1931 for (int i=0; i < fields.Count; i++) {
\r
1932 md.AddToTable(MDTable.Field,(MetaDataElement)fields[i]);
\r
1933 ((FieldDef)fields[i]).BuildTables(md);
\r
1935 // Console.WriteLine("adding events and properties");
\r
1936 if (events != null) {
\r
1937 for (int i=0; i < events.Count; i++) {
\r
1938 md.AddToTable(MDTable.Event,(Event)events[i]);
\r
1939 ((Event)events[i]).BuildTables(md);
\r
1941 md.AddToTable(MDTable.EventMap,
\r
1942 new MapElem(this,((Event)events[0]).Row,MDTable.Event));
\r
1944 if (properties != null) {
\r
1945 for (int i=0; i < properties.Count; i++) {
\r
1946 md.AddToTable(MDTable.Property,(Property)properties[i]);
\r
1947 ((Property)properties[i]).BuildTables(md);
\r
1949 md.AddToTable(MDTable.PropertyMap,new MapElem(this,
\r
1950 ((Property)properties[0]).Row,MDTable.Property));
\r
1952 DoCustomAttributes (md);
\r
1953 // Console.WriteLine("End of building tables");
\r
1957 internal sealed override uint Size(MetaData md) {
\r
1958 return 4 + 2 * md.StringsIndexSize() +
\r
1959 md.CodedIndexSize(CIx.TypeDefOrRef) +
\r
1960 md.TableIndexSize(MDTable.Field) +
\r
1961 md.TableIndexSize(MDTable.Method);
\r
1964 internal sealed override void Write(FileImage output) {
\r
1965 output.Write(flags);
\r
1966 output.StringsIndex(nameIx);
\r
1967 output.StringsIndex(nameSpaceIx);
\r
1968 //if (superType != null)
\r
1969 // Console.WriteLine("getting coded index for superType of " + name + " = " + superType.GetCodedIx(CIx.TypeDefOrRef));
\r
1970 output.WriteCodedIndex(CIx.TypeDefOrRef,superType);
\r
1971 output.WriteIndex(MDTable.Field,fieldIx);
\r
1972 output.WriteIndex(MDTable.Method,methodIx);
\r
1975 internal sealed override uint TypeDefOrRefToken() {
\r
1981 internal sealed override void TypeSig(MemoryStream sig) {
\r
1982 if (!typeIndexChecked) CheckTypeIndex();
\r
1983 sig.WriteByte(GetTypeIndex());
\r
1984 MetaData.CompressNum(TypeDefOrRefToken(),sig);
\r
1987 internal sealed override uint GetCodedIx(CIx code) {
\r
1989 case (CIx.TypeDefOrRef) : return 0;
\r
1990 case (CIx.HasCustomAttr) : return 3;
\r
1991 case (CIx.HasDeclSecurity) : return 0;
\r
1992 case (CIx.TypeOrMethodDef) : return 0;
\r
1998 /**************************************************************************/
\r
2000 /// Layout information for a class (.class [sequential | explicit])
\r
2002 internal class ClassLayout : MetaDataElement
\r
2005 ushort packSize = 0;
\r
2006 uint classSize = 0;
\r
2008 internal ClassLayout(int pack, int cSize, ClassDef par) {
\r
2009 packSize = (ushort)pack;
\r
2010 classSize = (uint)cSize;
\r
2012 tabIx = MDTable.ClassLayout;
\r
2015 internal sealed override uint Size(MetaData md) {
\r
2016 return 6 + md.TableIndexSize(MDTable.TypeDef);
\r
2019 internal sealed override void Write(FileImage output) {
\r
2020 output.Write(packSize);
\r
2021 output.Write(classSize);
\r
2022 output.WriteIndex(MDTable.TypeDef,parent.Row);
\r
2026 /**************************************************************************/
\r
2028 /// Descriptor for a class/interface declared in another module of THIS
\r
2029 /// assembly, or in another assembly.
\r
2031 public class ClassRef : Class
\r
2033 protected ResolutionScope parent;
\r
2034 ExternClass externClass;
\r
2035 protected MetaData metaData;
\r
2037 internal ClassRef(string nsName, string name, MetaData md) : base(nsName, name, md) {
\r
2039 tabIx = MDTable.TypeRef;
\r
2043 /// Add a method to this class
\r
2045 /// <param name="name">method name</param>
\r
2046 /// <param name="retType">return type</param>
\r
2047 /// <param name="pars">parameter types</param>
\r
2048 /// <returns>a descriptor for this method</returns>
\r
2049 public MethodRef AddMethod(string name, Type retType, Type[] pars) {
\r
2050 MethodRef meth = new MethodRef(this,name,retType,pars,false,null);
\r
2051 metaData.AddToTable(MDTable.MemberRef,meth);
\r
2056 /// Add a method to this class
\r
2058 /// <param name="name">method name</param>
\r
2059 /// <param name="retType">return type</param>
\r
2060 /// <param name="pars">parameter types</param>
\r
2061 /// <returns>a descriptor for this method</returns>
\r
2062 public MethodRef AddVarArgMethod(string name, Type retType,
\r
2063 Type[] pars, Type[] optPars) {
\r
2064 MethodRef meth = new MethodRef(this,name,retType,pars,true,optPars);
\r
2065 metaData.AddToTable(MDTable.MemberRef,meth);
\r
2070 /// Add a field to this class
\r
2072 /// <param name="name">field name</param>
\r
2073 /// <param name="fType">field type</param>
\r
2074 /// <returns>a descriptor for this field</returns>
\r
2075 public FieldRef AddField(string name, Type fType) {
\r
2076 FieldRef field = new FieldRef(this,name,fType);
\r
2077 metaData.AddToTable(MDTable.MemberRef,field);
\r
2081 internal void SetParent(ResolutionScope par) {
\r
2085 internal override string TypeName() {
\r
2086 if ((parent != null) && (parent is AssemblyRef))
\r
2087 return (nameSpace + "." + name + ", " + ((AssemblyRef)parent).TypeName());
\r
2089 return (nameSpace + name);
\r
2092 internal sealed override uint Size(MetaData md) {
\r
2093 return md.CodedIndexSize(CIx.ResolutionScope) + 2 *
\r
2094 md.StringsIndexSize();
\r
2097 internal sealed override void Write(FileImage output) {
\r
2098 output.WriteCodedIndex(CIx.ResolutionScope,parent);
\r
2099 output.StringsIndex(nameIx);
\r
2100 output.StringsIndex(nameSpaceIx);
\r
2103 internal override sealed uint TypeDefOrRefToken() {
\r
2105 cIx = (cIx << 2) | 0x1;
\r
2109 internal override void TypeSig(MemoryStream sig) {
\r
2110 sig.WriteByte(GetTypeIndex());
\r
2111 MetaData.CompressNum(TypeDefOrRefToken(),sig);
\r
2114 internal sealed override uint GetCodedIx(CIx code) {
\r
2116 case (CIx.TypeDefOrRef) : return 1;
\r
2117 case (CIx.HasCustomAttr) : return 2;
\r
2118 case (CIx.MemberRefParent) : return 1;
\r
2119 case (CIx.ResolutionScope) : return 3;
\r
2125 /**************************************************************************/
\r
2127 public class ExternClassRef : ClassRef {
\r
2129 ExternClass externClass;
\r
2131 internal ExternClassRef(TypeAttr attrs, string nsName, string name,
\r
2132 FileRef declFile, MetaData md) : base(nsName,name,md) {
\r
2133 externClass = new ExternClass(attrs,nameSpaceIx,nameIx,declFile);
\r
2134 metaData.AddToTable(MDTable.ExportedType,externClass);
\r
2137 internal ExternClassRef(string name, MetaData md) : base(null,name,md) {
\r
2140 public ClassRef AddNestedClass(TypeAttr attrs, string name) {
\r
2141 ExternClassRef nestedClass = new ExternClassRef(name,metaData);
\r
2142 externClass = new ExternClass(attrs,0,nameIx,this.externClass);
\r
2143 metaData.AddToTable(MDTable.ExportedType,externClass);
\r
2144 return nestedClass;
\r
2148 /**************************************************************************/
\r
2150 /// Descriptor for a constant value
\r
2152 public abstract class Constant {
\r
2153 protected uint size = 0;
\r
2154 protected Type type;
\r
2155 protected uint blobIndex;
\r
2156 protected bool addedToBlobHeap = false;
\r
2158 internal Constant() { }
\r
2160 internal virtual uint GetBlobIndex(MetaData md) { return 0; }
\r
2162 internal uint GetSize() { return size; }
\r
2164 internal byte GetTypeIndex() { return type.GetTypeIndex(); }
\r
2166 internal virtual void Write(BinaryWriter bw) { }
\r
2170 /// Descriptor for a constant value
\r
2172 public abstract class DataConstant : Constant {
\r
2173 private uint dataOffset = 0;
\r
2175 internal DataConstant() { }
\r
2177 public uint DataOffset {
\r
2178 get { return dataOffset; }
\r
2179 set { dataOffset = value; }
\r
2185 /// Boolean constant
\r
2187 public class BoolConst : Constant {
\r
2191 /// Create a new boolean constant with the value "val"
\r
2193 /// <param name="val">value of this boolean constant</param>
\r
2194 public BoolConst(bool val) {
\r
2197 type = PrimitiveType.Boolean;
\r
2200 internal sealed override uint GetBlobIndex(MetaData md) {
\r
2201 if (!addedToBlobHeap) {
\r
2202 if (val) blobIndex = md.AddToBlobHeap((sbyte)1);
\r
2203 else blobIndex = md.AddToBlobHeap((sbyte)0);
\r
2204 addedToBlobHeap = true;
\r
2209 internal sealed override void Write(BinaryWriter bw) {
\r
2210 if (val) bw.Write((sbyte)1);
\r
2211 else bw.Write((sbyte)0);
\r
2216 public class ByteArrConst : DataConstant {
\r
2219 public ByteArrConst(byte[] val) {
\r
2221 size = (uint)val.Length;
\r
2224 internal sealed override uint GetBlobIndex(MetaData md) {
\r
2225 if (!addedToBlobHeap) {
\r
2226 blobIndex = md.AddToBlobHeap(val);
\r
2227 addedToBlobHeap = true;
\r
2232 internal sealed override void Write(BinaryWriter bw) {
\r
2238 public class CharConst : Constant {
\r
2241 public CharConst(char val) {
\r
2244 type = PrimitiveType.Char;
\r
2247 internal sealed override uint GetBlobIndex(MetaData md) {
\r
2248 if (!addedToBlobHeap) {
\r
2249 blobIndex = md.AddToBlobHeap(val);
\r
2250 addedToBlobHeap = true;
\r
2255 internal sealed override void Write(BinaryWriter bw) {
\r
2261 public class FloatConst : DataConstant {
\r
2264 public FloatConst(float val) {
\r
2267 type = PrimitiveType.Float32;
\r
2270 internal sealed override uint GetBlobIndex(MetaData md) {
\r
2271 if (!addedToBlobHeap) {
\r
2272 blobIndex = md.AddToBlobHeap(val);
\r
2273 addedToBlobHeap = true;
\r
2278 internal sealed override void Write(BinaryWriter bw) {
\r
2284 public class DoubleConst : DataConstant {
\r
2287 public DoubleConst(double val) {
\r
2290 type = PrimitiveType.Float64;
\r
2293 internal sealed override uint GetBlobIndex(MetaData md) {
\r
2294 if (!addedToBlobHeap) {
\r
2295 blobIndex = md.AddToBlobHeap(val);
\r
2296 addedToBlobHeap = true;
\r
2301 internal sealed override void Write(BinaryWriter bw) {
\r
2307 public class IntConst : DataConstant {
\r
2310 public IntConst(sbyte val) {
\r
2313 type = PrimitiveType.Int8;
\r
2316 public IntConst(short val) {
\r
2319 type = PrimitiveType.Int16;
\r
2322 public IntConst(int val) {
\r
2325 type = PrimitiveType.Int32;
\r
2328 public IntConst(long val) {
\r
2331 type = PrimitiveType.Int64;
\r
2334 internal sealed override uint GetBlobIndex(MetaData md) {
\r
2335 if (!addedToBlobHeap) {
\r
2337 case (1) : blobIndex = md.AddToBlobHeap((sbyte)val); break;
\r
2338 case (2) : blobIndex = md.AddToBlobHeap((short)val); break;
\r
2339 case (4) : blobIndex = md.AddToBlobHeap((int)val); break;
\r
2340 default : blobIndex = md.AddToBlobHeap(val); break;
\r
2342 addedToBlobHeap = true;
\r
2347 internal sealed override void Write(BinaryWriter bw) {
\r
2349 case (1) : bw.Write((sbyte)val); break;
\r
2350 case (2) : bw.Write((short)val); break;
\r
2351 case (4) : bw.Write((int)val); break;
\r
2352 default : bw.Write(val); break;
\r
2358 public class UIntConst : Constant {
\r
2361 public UIntConst(sbyte val) {
\r
2364 type = PrimitiveType.UInt8;
\r
2366 public UIntConst(short val) {
\r
2369 type = PrimitiveType.UInt16;
\r
2371 public UIntConst(int val) {
\r
2374 type = PrimitiveType.UInt32;
\r
2376 public UIntConst(long val) {
\r
2379 type = PrimitiveType.UInt64;
\r
2382 internal sealed override uint GetBlobIndex(MetaData md) {
\r
2383 if (!addedToBlobHeap) {
\r
2385 case (1) : blobIndex = md.AddToBlobHeap((sbyte)val); break;
\r
2386 case (2) : blobIndex = md.AddToBlobHeap((short)val); break;
\r
2387 case (4) : blobIndex = md.AddToBlobHeap((int)val); break;
\r
2388 default : blobIndex = md.AddToBlobHeap(val); break;
\r
2390 addedToBlobHeap = true;
\r
2395 internal sealed override void Write(BinaryWriter bw) {
\r
2397 case (1) : bw.Write((sbyte)val); break;
\r
2398 case (2) : bw.Write((short)val); break;
\r
2399 case (4) : bw.Write((int)val); break;
\r
2400 default : bw.Write(val); break;
\r
2406 public class StringConst : DataConstant {
\r
2409 public StringConst(string val) {
\r
2411 size = (uint)val.Length; // need to add null ??
\r
2412 type = PrimitiveType.String;
\r
2415 internal sealed override uint GetBlobIndex(MetaData md) {
\r
2416 if (!addedToBlobHeap) {
\r
2417 blobIndex = md.AddToBlobHeap(val);
\r
2418 addedToBlobHeap = true;
\r
2423 internal sealed override void Write(BinaryWriter bw) {
\r
2429 public class NullConst : Constant {
\r
2431 public NullConst() {
\r
2433 type = PrimitiveType.Class;
\r
2436 internal sealed override uint GetBlobIndex(MetaData md) {
\r
2437 if (!addedToBlobHeap) {
\r
2438 blobIndex = md.AddToBlobHeap((int)0);
\r
2439 addedToBlobHeap = true;
\r
2444 internal sealed override void Write(BinaryWriter bw) {
\r
2445 bw.Write((int)0);
\r
2450 public class AddressConstant : DataConstant {
\r
2451 DataConstant data;
\r
2453 public AddressConstant(DataConstant dConst) {
\r
2456 type = PrimitiveType.TypedRef;
\r
2459 internal sealed override void Write(BinaryWriter bw) {
\r
2460 ((FileImage)bw).WriteDataRVA(data.DataOffset);
\r
2465 public class RepeatedConstant : DataConstant {
\r
2466 DataConstant data;
\r
2469 public RepeatedConstant(DataConstant dConst, int repeatCount) {
\r
2471 repCount = (uint)repeatCount;
\r
2472 int[] sizes = new int[1];
\r
2473 sizes[0] = repeatCount;
\r
2474 type = new BoundArray(type,1,sizes);
\r
2475 size = data.GetSize() * repCount;
\r
2478 internal sealed override void Write(BinaryWriter bw) {
\r
2479 for (int i=0; i < repCount; i++) {
\r
2486 public class ArrayConstant : DataConstant {
\r
2487 DataConstant[] dataVals;
\r
2489 public ArrayConstant(DataConstant[] dVals) {
\r
2491 for (int i=0; i < dataVals.Length; i++) {
\r
2492 size += dataVals[i].GetSize();
\r
2496 internal sealed override void Write(BinaryWriter bw) {
\r
2497 for (int i=0; i < dataVals.Length; i++) {
\r
2498 dataVals[i].Write(bw);
\r
2504 public class ClassType : Constant {
\r
2508 public ClassType(string className) {
\r
2510 type = PrimitiveType.ClassType;
\r
2513 public ClassType(Class classDesc) {
\r
2515 type = PrimitiveType.ClassType;
\r
2518 internal override void Write(BinaryWriter bw) {
\r
2519 if (name == null) name = desc.TypeName();
\r
2527 /**************************************************************************/
\r
2529 /// Summary description for ConstantElem.
\r
2531 internal class ConstantElem : MetaDataElement
\r
2533 MetaDataElement parent;
\r
2537 internal ConstantElem(MetaDataElement parent, Constant val) {
\r
2538 this.parent = parent;
\r
2540 tabIx = MDTable.Constant;
\r
2543 internal sealed override void BuildTables(MetaData md) {
\r
2545 valIx = cValue.GetBlobIndex(md);
\r
2549 internal void AddToBlob(BinaryWriter bw) {
\r
2553 internal sealed override uint Size(MetaData md) {
\r
2554 return 2 + md.CodedIndexSize(CIx.HasConst) + md.BlobIndexSize();
\r
2557 internal sealed override void Write(FileImage output) {
\r
2558 output.Write(cValue.GetTypeIndex());
\r
2559 output.Write((byte)0);
\r
2560 output.WriteCodedIndex(CIx.HasConst,parent);
\r
2561 output.BlobIndex(valIx);
\r
2565 /**************************************************************************/
\r
2567 /// Descriptor for a Custom Attribute (.custom)
\r
2570 public class CustomAttribute : MetaDataElement
\r
2572 private static readonly ushort prolog = 0x0001;
\r
2573 MetaDataElement parent;
\r
2578 ushort numNamed = 0;
\r
2579 ArrayList names, vals;
\r
2581 internal CustomAttribute(MetaDataElement paren, Method constrType,
\r
2584 type = constrType;
\r
2586 tabIx = MDTable.CustomAttribute;
\r
2587 throw(new NotYetImplementedException("Custom Attributes "));
\r
2590 internal CustomAttribute(MetaDataElement paren, Method constrType,
\r
2593 type = constrType;
\r
2594 tabIx = MDTable.CustomAttribute;
\r
2598 public void AddFieldOrProp(string name, Constant val) {
\r
2599 if (numNamed == 0) {
\r
2600 names = new ArrayList();
\r
2601 vals = new ArrayList();
\r
2607 internal sealed override void BuildTables(MetaData md) {
\r
2608 BinaryWriter bw = new BinaryWriter(new MemoryStream());
\r
2609 bw.Write((ushort)1);
\r
2610 md.AddToTable(MDTable.CustomAttribute, this);
\r
2611 MemoryStream str = (MemoryStream)bw.BaseStream;
\r
2612 valIx = md.AddToBlobHeap(str.ToArray());
\r
2615 internal sealed override uint Size(MetaData md) {
\r
2616 return md.CodedIndexSize(CIx.HasCustomAttr) + md.CodedIndexSize(CIx.CustomAttributeType) + md.BlobIndexSize();
\r
2619 internal sealed override void Write(FileImage output) {
\r
2620 output.WriteCodedIndex(CIx.HasCustomAttr,parent);
\r
2621 output.WriteCodedIndex(CIx.CustomAttributeType,type);
\r
2622 output.BlobIndex(valIx);
\r
2626 /**************************************************************************/
\r
2628 /// Descriptor for a custom modifier of a type (modopt or modreq)
\r
2631 public class CustomModifiedType : Type
\r
2637 /// Create a new custom modifier for a type
\r
2639 /// <param name="type">the type to be modified</param>
\r
2640 /// <param name="cmod">the modifier</param>
\r
2641 /// <param name="cmodType">the type reference to be associated with the type</param>
\r
2642 public CustomModifiedType(Type type, CustomModifier cmod, Class cmodType)
\r
2643 : base((byte)cmod) {
\r
2645 this.cmodType = cmodType;
\r
2648 internal sealed override void TypeSig(MemoryStream str) {
\r
2649 str.WriteByte(typeIndex);
\r
2650 MetaData.CompressNum(cmodType.TypeDefOrRefToken(),str);
\r
2651 type.TypeSig(str);
\r
2655 /**************************************************************************/
\r
2657 /// Descriptor for security permissions for a class or a method NOT YET IMPLEMENTED
\r
2660 public class DeclSecurity : MetaDataElement
\r
2663 MetaDataElement parent;
\r
2664 uint permissionIx;
\r
2666 internal DeclSecurity(MetaDataElement paren, ushort act) {
\r
2669 tabIx = MDTable.DeclSecurity;
\r
2670 throw(new NotYetImplementedException("Security "));
\r
2673 internal sealed override uint Size(MetaData md) {
\r
2674 return 2 + md.CodedIndexSize(CIx.HasDeclSecurity) + md.BlobIndexSize();
\r
2677 internal sealed override void BuildTables(MetaData md) {
\r
2679 // add permission to blob heap
\r
2683 internal sealed override void Write(FileImage output) {
\r
2684 output.Write(action);
\r
2685 output.WriteCodedIndex(CIx.HasDeclSecurity,parent);
\r
2686 output.BlobIndex(permissionIx);
\r
2690 /**************************************************************************/
\r
2692 /// Descriptor for an event
\r
2694 public class Event : Feature
\r
2698 internal Event(string name, Type eType, ClassDef parent)
\r
2699 : base(name, parent) {
\r
2700 eventType = eType;
\r
2701 tabIx = MDTable.Event;
\r
2705 /// Add the addon method to this event
\r
2707 /// <param name="addon">the addon method</param>
\r
2708 public void AddAddon(MethodDef addon) {
\r
2709 AddMethod(addon,MethodType.AddOn);
\r
2713 /// Add the removeon method to this event
\r
2715 /// <param name="removeOn">the removeon method</param>
\r
2716 public void AddRemoveOn(MethodDef removeOn) {
\r
2717 AddMethod(removeOn,MethodType.RemoveOn);
\r
2721 /// Add the fire method to this event
\r
2723 /// <param name="fire">the fire method</param>
\r
2724 public void AddFire(MethodDef fire) {
\r
2725 AddMethod(fire,MethodType.Fire);
\r
2729 /// Add another method to this event
\r
2731 /// <param name="other">the method to be added</param>
\r
2732 public void AddOther(MethodDef other) {
\r
2733 AddMethod(other,MethodType.Other);
\r
2736 internal sealed override void BuildTables(MetaData md) {
\r
2738 nameIx = md.AddToStringsHeap(name);
\r
2739 for (int i=0; i < tide; i++) {
\r
2740 md.AddToTable(MDTable.MethodSemantics,methods[i]);
\r
2745 internal sealed override uint Size(MetaData md) {
\r
2746 return 2 + md.StringsIndexSize() + md.CodedIndexSize(CIx.TypeDefOrRef);
\r
2749 internal sealed override void Write(FileImage output) {
\r
2750 output.Write(flags);
\r
2751 output.StringsIndex(nameIx);
\r
2752 output.WriteCodedIndex(CIx.TypeDefOrRef,eventType);
\r
2755 internal sealed override uint GetCodedIx(CIx code) {
\r
2757 case (CIx.HasCustomAttr) : return 10;
\r
2758 case (CIx.HasSemantics) : return 0;
\r
2764 /**************************************************************************/
\r
2766 /// Descriptor for a class defined in another module of THIS assembly
\r
2767 /// and exported (.class extern)
\r
2770 internal class ExternClass : Class
\r
2772 MetaDataElement parent;
\r
2775 internal ExternClass(TypeAttr attr, uint nsIx, uint nIx,
\r
2776 MetaDataElement paren) : base(nsIx,nIx) {
\r
2777 flags = (uint)attr;
\r
2779 tabIx = MDTable.ExportedType;
\r
2782 internal sealed override uint Size(MetaData md) {
\r
2783 return 8 + 2* md.StringsIndexSize() + md.CodedIndexSize(CIx.Implementation);
\r
2786 internal sealed override void Write(FileImage output) {
\r
2787 output.Write(flags);
\r
2789 output.StringsIndex(nameIx);
\r
2790 output.StringsIndex(nameSpaceIx);
\r
2791 output.WriteCodedIndex(CIx.Implementation,parent);
\r
2794 internal sealed override uint GetCodedIx(CIx code) {
\r
2796 case (CIx.HasCustomAttr) : return 17;
\r
2797 case (CIx.Implementation) : return 2;
\r
2803 /**************************************************************************/
\r
2805 /// Base class for Event and Property descriptors
\r
2808 public class Feature : MetaDataElement
\r
2810 internal enum MethodType : ushort { Setter = 0x01, Getter, Other = 0x04, AddOn = 0x08,
\r
2811 RemoveOn = 0x10, Fire = 0x20 }
\r
2813 private static readonly int INITSIZE = 5;
\r
2814 private static readonly ushort specialName = 0x200;
\r
2815 private static readonly ushort rtSpecialName = 0x400;
\r
2817 protected ClassDef parent;
\r
2818 protected ushort flags = 0;
\r
2819 protected string name;
\r
2820 protected int tide = 0;
\r
2821 protected uint nameIx;
\r
2822 protected MethodSemantics[] methods = new MethodSemantics[INITSIZE];
\r
2824 internal Feature(string name, ClassDef par) {
\r
2829 internal void AddMethod(MethodDef meth, MethodType mType) {
\r
2830 if (tide >= methods.Length) {
\r
2831 int len = methods.Length;
\r
2832 MethodSemantics[] mTmp = methods;
\r
2833 methods = new MethodSemantics[len * 2];
\r
2834 for (int i=0; i < len; i++) {
\r
2835 methods[i] = mTmp[i];
\r
2838 methods[tide++] = new MethodSemantics(mType,meth,this);
\r
2842 /// Set the specialName attribute for this Event or Property
\r
2844 public void SetSpecialName() {
\r
2845 flags |= specialName;
\r
2849 /// Set the RTSpecialName attribute for this Event or Property
\r
2851 public void SetRTSpecialName() {
\r
2852 flags |= rtSpecialName;
\r
2856 /*****************************************************************************/
\r
2858 /// Descriptor for a field of a class
\r
2861 public abstract class Field : Member
\r
2863 protected static readonly byte FieldSig = 0x6;
\r
2865 protected Type type;
\r
2867 internal Field(string pfName, Type pfType) : base(pfName)
\r
2873 /**************************************************************************/
\r
2875 /// Descriptor for a field defined in a class of THIS assembly/module
\r
2877 public class FieldDef : Field
\r
2879 //private static readonly uint PInvokeImpl = 0x2000;
\r
2880 private static readonly ushort HasFieldMarshal = 0x1000;
\r
2881 private static readonly ushort HasFieldRVA = 0x100;
\r
2884 ConstantElem constVal;
\r
2885 FieldLayout layout;
\r
2886 FieldMarshal marshalInfo;
\r
2889 internal FieldDef(string name, Type fType) : base(name,fType) {
\r
2890 tabIx = MDTable.Field;
\r
2893 internal FieldDef(FieldAttr attrSet, string name, Type fType) : base(name, fType) {
\r
2894 flags = (ushort)attrSet;
\r
2895 tabIx = MDTable.Field;
\r
2899 /// Add an attribute(s) to this field
\r
2901 /// <param name="fa">the attribute(s) to be added</param>
\r
2902 public void AddFieldAttr(FieldAttr fa) {
\r
2903 flags |= (ushort)fa;
\r
2907 /// Add a value for this field
\r
2909 /// <param name="val">the value for the field</param>
\r
2910 public void AddValue(Constant val) {
\r
2911 constVal = new ConstantElem(this,val);
\r
2915 /// Add an initial value for this field (at dataLabel) (.data)
\r
2917 /// <param name="val">the value for the field</param>
\r
2918 /// <param name="repeatVal">the number of repetitions of this value</param>
\r
2919 public void AddDataValue(DataConstant val) {
\r
2920 flags |= HasFieldRVA;
\r
2921 rva = new FieldRVA(this,val);
\r
2925 /// Set the offset of the field. Used for sequential or explicit classes.
\r
2926 /// (.field [offs])
\r
2928 /// <param name="offs">field offset</param>
\r
2929 public void SetOffset(uint offs) {
\r
2930 layout = new FieldLayout(this,offs);
\r
2934 /// Set the marshalling info for a field
\r
2936 /// <param name="mInf"></param>
\r
2937 public void SetMarshalInfo(NativeType marshallType) {
\r
2938 flags |= HasFieldMarshal;
\r
2939 marshalInfo = new FieldMarshal(this,marshallType);
\r
2942 internal sealed override void BuildTables(MetaData md) {
\r
2944 nameIx = md.AddToStringsHeap(name);
\r
2945 MemoryStream sig = new MemoryStream();
\r
2946 sig.WriteByte(FieldSig);
\r
2947 type.TypeSig(sig);
\r
2948 sigIx = md.AddToBlobHeap(sig.ToArray());
\r
2949 if (rva != null) {
\r
2950 md.AddToTable(MDTable.FieldRVA,rva);
\r
2951 rva.BuildTables(md);
\r
2952 } else if (constVal != null) {
\r
2953 md.AddToTable(MDTable.Constant,constVal);
\r
2954 constVal.BuildTables(md);
\r
2956 if (layout != null) md.AddToTable(MDTable.FieldLayout,layout);
\r
2957 if (marshalInfo != null) {
\r
2958 md.AddToTable(MDTable.FieldMarshal,marshalInfo);
\r
2959 marshalInfo.BuildTables(md);
\r
2964 internal sealed override uint Size(MetaData md) {
\r
2965 return 2 + md.StringsIndexSize() + md.BlobIndexSize();
\r
2968 internal sealed override void Write(FileImage output) {
\r
2969 output.Write(flags);
\r
2970 output.StringsIndex(nameIx);
\r
2971 output.BlobIndex(sigIx);
\r
2974 internal sealed override uint GetCodedIx(CIx code) {
\r
2976 case (CIx.HasConst) : return 0;
\r
2977 case (CIx.HasCustomAttr) : return 1;
\r
2978 case (CIx.HasFieldMarshal) : return 0;
\r
2979 case (CIx.MemberForwarded) : return 0;
\r
2985 /**************************************************************************/
\r
2987 /// Descriptor for layout information for a field
\r
2990 public class FieldLayout : MetaDataElement
\r
2995 internal FieldLayout(Field field, uint offset) {
\r
2996 this.field = field;
\r
2997 this.offset = offset;
\r
2998 tabIx = MDTable.FieldLayout;
\r
3001 internal sealed override uint Size(MetaData md) {
\r
3002 return 4 + md.TableIndexSize(MDTable.Field);
\r
3005 internal sealed override void Write(FileImage output) {
\r
3006 output.Write(offset);
\r
3007 output.WriteIndex(MDTable.Field,field.Row);
\r
3011 /*****************************************************************************/
\r
3013 /// Marshalling information for a field or param
\r
3015 public class FieldMarshal : MetaDataElement
\r
3017 MetaDataElement field;
\r
3021 internal FieldMarshal(MetaDataElement field, NativeType nType) {
\r
3022 this.field = field;
\r
3024 tabIx = MDTable.FieldMarshal;
\r
3027 internal sealed override void BuildTables(MetaData md) {
\r
3029 ntIx = md.AddToBlobHeap(nt.ToBlob());
\r
3033 internal sealed override uint Size(MetaData md) {
\r
3034 return md.CodedIndexSize(CIx.HasFieldMarshal) + md.BlobIndexSize();
\r
3037 internal sealed override void Write(FileImage output) {
\r
3038 output.WriteCodedIndex(CIx.HasFieldMarshal,field);
\r
3039 output.BlobIndex(ntIx);
\r
3043 /**************************************************************************/
\r
3045 /// Descriptor for a field of a class defined in another assembly/module
\r
3047 public class FieldRef : Field
\r
3049 MetaDataElement parent;
\r
3051 internal FieldRef(MetaDataElement paren, string name, Type fType) : base(name, fType) {
\r
3055 internal sealed override void BuildTables(MetaData md) {
\r
3057 nameIx = md.AddToStringsHeap(name);
\r
3058 MemoryStream sig = new MemoryStream();
\r
3059 sig.WriteByte(FieldSig);
\r
3060 type.TypeSig(sig);
\r
3061 sigIx = md.AddToBlobHeap(sig.ToArray());
\r
3065 internal sealed override uint Size(MetaData md) {
\r
3066 return md.CodedIndexSize(CIx.MemberRefParent) + md.StringsIndexSize() + md.BlobIndexSize();
\r
3069 internal sealed override void Write(FileImage output) {
\r
3070 output.WriteCodedIndex(CIx.MemberRefParent,parent);
\r
3071 output.StringsIndex(nameIx);
\r
3072 output.BlobIndex(sigIx);
\r
3075 internal sealed override uint GetCodedIx(CIx code) { return 6; }
\r
3078 /**************************************************************************/
\r
3080 /// Descriptor for the address of a field's value in the PE file
\r
3082 public class FieldRVA : MetaDataElement
\r
3085 DataConstant data;
\r
3087 internal FieldRVA(Field field, DataConstant data) {
\r
3088 this.field = field;
\r
3090 tabIx = MDTable.FieldRVA;
\r
3093 internal sealed override void BuildTables(MetaData md) {
\r
3099 internal sealed override uint Size(MetaData md) {
\r
3100 return 4 + md.TableIndexSize(MDTable.Field);
\r
3103 internal sealed override void Write(FileImage output) {
\r
3104 output.WriteDataRVA(data.DataOffset);
\r
3105 output.WriteIndex(MDTable.Field,field.Row);
\r
3109 /**************************************************************************/
\r
3111 /// Image for a PEFile
\r
3112 /// File Structure
\r
3113 /// DOS Header (128 bytes)
\r
3114 /// PE Signature ("PE\0\0")
\r
3115 /// PEFileHeader (20 bytes)
\r
3116 /// PEOptionalHeader (224 bytes)
\r
3117 /// SectionHeaders (40 bytes * NumSections)
\r
3119 /// Sections .text (always present - contains metadata)
\r
3120 /// .sdata (contains any initialised data in the file - may not be present)
\r
3121 /// (for ilams /debug this contains the Debug table)
\r
3122 /// .reloc (always present - in pure CIL only has one fixup)
\r
3123 /// others??? c# produces .rsrc section containing a Resource Table
\r
3126 /// IAT (single entry 8 bytes for pure CIL)
\r
3127 /// CLIHeader (72 bytes)
\r
3128 /// CIL instructions for all methods (variable size)
\r
3130 /// Root (20 bytes + UTF-8 Version String + quad align padding)
\r
3131 /// StreamHeaders (8 bytes + null terminated name string + quad align padding)
\r
3133 /// #~ (always present - holds metadata tables)
\r
3134 /// #Strings (always present - holds identifier strings)
\r
3135 /// #US (Userstring heap)
\r
3136 /// #Blob (signature blobs)
\r
3137 /// #GUID (guids for assemblies or Modules)
\r
3138 /// ImportTable (40 bytes)
\r
3139 /// ImportLookupTable(8 bytes) (same as IAT for standard CIL files)
\r
3140 /// Hint/Name Tables with entry "_CorExeMain" for .exe file and "_CorDllMain" for .dll (14 bytes)
\r
3141 /// ASCII string "mscoree.dll" referenced in ImportTable (+ padding = 16 bytes)
\r
3142 /// Entry Point (0xFF25 followed by 4 bytes 0x400000 + RVA of .text)
\r
3144 /// #~ stream structure
\r
3145 /// Header (24 bytes)
\r
3146 /// Rows (4 bytes * numTables)
\r
3149 internal class FileImage : BinaryWriter
\r
3151 internal readonly static uint[] iByteMask = {0x000000FF, 0x0000FF00, 0x00FF0000, 0xFF000000};
\r
3152 internal readonly static ulong[] lByteMask = {0x00000000000000FF, 0x000000000000FF00,
\r
3153 0x0000000000FF0000, 0x00000000FF000000,
\r
3154 0x000000FF00000000, 0x0000FF0000000000,
\r
3155 0x00FF000000000000, 0xFF00000000000000 };
\r
3156 internal readonly static uint nibble0Mask = 0x0000000F;
\r
3157 internal readonly static uint nibble1Mask = 0x000000F0;
\r
3159 private static readonly byte[] DOSHeader = { 0x4d,0x5a,0x90,0x00,0x03,0x00,0x00,0x00,
\r
3160 0x04,0x00,0x00,0x00,0xff,0xff,0x00,0x00,
\r
3161 0xb8,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
\r
3162 0x40,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
\r
3163 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
\r
3164 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
\r
3165 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
\r
3166 0x00,0x00,0x00,0x00,0x80,0x00,0x00,0x00,
\r
3167 0x0e,0x1f,0xba,0x0e,0x00,0xb4,0x09,0xcd,
\r
3168 0x21,0xb8,0x01,0x4c,0xcd,0x21,0x54,0x68,
\r
3169 0x69,0x73,0x20,0x70,0x72,0x6f,0x67,0x72,
\r
3170 0x61,0x6d,0x20,0x63,0x61,0x6e,0x6e,0x6f,
\r
3171 0x74,0x20,0x62,0x65,0x20,0x72,0x75,0x6e,
\r
3172 0x20,0x69,0x6e,0x20,0x44,0x4f,0x53,0x20,
\r
3173 0x6d,0x6f,0x64,0x65,0x2e,0x0d,0x0d,0x0a,
\r
3174 0x24,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
\r
3175 0x50,0x45,0x00,0x00};
\r
3176 private static byte[] PEHeader = { 0x4c, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
\r
3177 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
\r
3178 0xE0, 0x00, 0x0E, 0x01, // PE Header Standard Fields
\r
3179 0x0B, 0x01, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00,
\r
3180 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
\r
3181 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
\r
3184 private static readonly uint minFileAlign = 0x200;
\r
3185 private static readonly uint maxFileAlign = 0x1000;
\r
3186 private static readonly uint fileHeaderSize = 0x178;
\r
3187 private static readonly uint sectionHeaderSize = 40;
\r
3188 private static readonly uint SectionAlignment = 0x2000;
\r
3189 private static readonly uint ImageBase = 0x400000;
\r
3190 private static readonly uint ImportTableSize = 40;
\r
3191 private static readonly uint IATSize = 8;
\r
3192 private static readonly uint CLIHeaderSize = 72;
\r
3193 private uint runtimeFlags = 0x01; // COMIMAGE_FLAGS_ILONLY
\r
3194 // 32BITREQUIRED 0x02, STRONGNAMESIGNED 0x08, TRACKDEBUGDATA 0x10000
\r
3195 private static readonly uint relocFlags = 0x42000040;
\r
3196 private static readonly ushort exeCharacteristics = 0x010E;
\r
3197 private static readonly ushort dllCharacteristics = 0x210E;
\r
3198 // section names are all 8 bytes
\r
3199 private static readonly string textName = ".text\0\0\0";
\r
3200 private static readonly string sdataName = ".sdata\0\0";
\r
3201 private static readonly string relocName = ".reloc\0\0";
\r
3202 private static readonly string rsrcName = ".rsrc\0\0\0";
\r
3203 private static readonly string exeHintNameTable = "\0\0_CorExeMain\0";
\r
3204 private static readonly string dllHintNameTable = "\0\0_CorDllMain\0";
\r
3205 private static readonly string runtimeEngineName = "mscoree.dll\0\0";
\r
3207 private Section text, sdata, rsrc;
\r
3209 BinaryWriter reloc = new BinaryWriter(new MemoryStream());
\r
3210 uint dateStamp = 0;
\r
3211 DateTime origin = new DateTime(1970,1,1);
\r
3212 uint numSections = 2; // always have .text and .reloc sections
\r
3213 internal SubSystem subSys = SubSystem.Windows_CUI; // default is Windows Console mode
\r
3214 internal uint fileAlign = minFileAlign;
\r
3215 uint entryPointOffset, entryPointPadding, imageSize, headerSize, headerPadding, entryPointToken = 0;
\r
3216 uint relocOffset, relocRVA, relocSize, relocPadding, relocTide, hintNameTableOffset;
\r
3217 uint metaDataOffset, runtimeEngineOffset, initDataSize = 0, importTablePadding;
\r
3218 uint importTableOffset, importLookupTableOffset, totalImportTableSize;
\r
3219 MetaData metaData;
\r
3220 char[] runtimeEngine = runtimeEngineName.ToCharArray(), hintNameTable;
\r
3221 bool doDLL, largeStrings, largeGUID, largeUS, largeBlob;
\r
3222 ushort characteristics;
\r
3224 internal FileImage(bool makeDLL, string fileName) : base(new FileStream(fileName,FileMode.Create)) {
\r
3225 InitFileImage(makeDLL);
\r
3226 TimeSpan tmp = System.IO.File.GetCreationTime(fileName).Subtract(origin);
\r
3227 dateStamp = Convert.ToUInt32(tmp.TotalSeconds);
\r
3230 internal FileImage(bool makeDLL, Stream str) : base(str) {
\r
3231 InitFileImage(makeDLL);
\r
3232 TimeSpan tmp = DateTime.Now.Subtract(origin);
\r
3233 dateStamp = Convert.ToUInt32(tmp.TotalSeconds);
\r
3236 private void InitFileImage(bool makeDLL) {
\r
3239 hintNameTable = dllHintNameTable.ToCharArray();
\r
3240 characteristics = dllCharacteristics;
\r
3242 hintNameTable = exeHintNameTable.ToCharArray();
\r
3243 characteristics = exeCharacteristics;
\r
3245 text = new Section(textName,0x60000020); // IMAGE_SCN_CNT CODE, EXECUTE, READ
\r
3246 // rsrc = new Section(rsrcName,0x40000040); // IMAGE_SCN_CNT INITIALIZED_DATA, READ
\r
3247 metaData = new MetaData(this);
\r
3250 internal MetaData GetMetaData() {
\r
3254 private uint GetNextSectStart(uint rva, uint tide) {
\r
3255 if (tide < SectionAlignment) return rva + SectionAlignment;
\r
3256 return rva + ((tide / SectionAlignment) + 1) * SectionAlignment;
\r
3259 private void BuildTextSection() {
\r
3261 // IAT (single entry 8 bytes for pure CIL)
\r
3262 // CLIHeader (72 bytes)
\r
3263 // CIL instructions for all methods (variable size)
\r
3265 // ImportTable (40 bytes)
\r
3266 // ImportLookupTable(8 bytes) (same as IAT for standard CIL files)
\r
3267 // Hint/Name Tables with entry "_CorExeMain" for .exe file and "_CorDllMain" for .dll (14 bytes)
\r
3268 // ASCII string "mscoree.dll" referenced in ImportTable (+ padding = 16 bytes)
\r
3269 // Entry Point (0xFF25 followed by 4 bytes 0x400000 + RVA of .text)
\r
3270 metaData.BuildMetaData(IATSize + CLIHeaderSize);
\r
3271 metaDataOffset = IATSize + CLIHeaderSize;
\r
3272 // Console.WriteLine("Code starts at " + metaDataOffset);
\r
3273 metaDataOffset += metaData.CodeSize();
\r
3274 // resourcesStart =
\r
3275 // strongNameSig = metaData.GetStrongNameSig();
\r
3276 // fixUps = RVA for vtable
\r
3277 importTableOffset = metaDataOffset + metaData.Size();
\r
3278 importTablePadding = NumToAlign(importTableOffset,16);
\r
3279 importTableOffset += importTablePadding;
\r
3280 importLookupTableOffset = importTableOffset + ImportTableSize;
\r
3281 hintNameTableOffset = importLookupTableOffset + IATSize;
\r
3282 runtimeEngineOffset = hintNameTableOffset + (uint)hintNameTable.Length;
\r
3283 entryPointOffset = runtimeEngineOffset + (uint)runtimeEngine.Length;
\r
3284 totalImportTableSize = entryPointOffset - importTableOffset;
\r
3285 // Console.WriteLine("total import table size = " + totalImportTableSize);
\r
3286 // Console.WriteLine("entrypoint offset = " + entryPointOffset);
\r
3287 entryPointPadding = NumToAlign(entryPointOffset,4) + 2;
\r
3288 entryPointOffset += entryPointPadding;
\r
3289 text.AddReloc(entryPointOffset+2);
\r
3290 text.IncTide(entryPointOffset + 6);
\r
3291 //if (text.Tide() < fileAlign) fileAlign = minFileAlign;
\r
3292 text.SetSize(NumToAlign(text.Tide(),fileAlign));
\r
3293 // Console.WriteLine("text size = " + text.Size() + " text tide = " + text.Tide() + " text padding = " + text.Padding());
\r
3294 // Console.WriteLine("metaDataOffset = " + Hex.Int(metaDataOffset));
\r
3295 // Console.WriteLine("importTableOffset = " + Hex.Int(importTableOffset));
\r
3296 // Console.WriteLine("importLookupTableOffset = " + Hex.Int(importLookupTableOffset));
\r
3297 // Console.WriteLine("hintNameTableOffset = " + Hex.Int(hintNameTableOffset));
\r
3298 // Console.WriteLine("runtimeEngineOffset = " + Hex.Int(runtimeEngineOffset));
\r
3299 // Console.WriteLine("entryPointOffset = " + Hex.Int(entryPointOffset));
\r
3300 // Console.WriteLine("entryPointPadding = " + Hex.Int(entryPointPadding));
\r
3304 internal void BuildRelocSection() {
\r
3305 text.DoRelocs(reloc);
\r
3306 if (sdata != null) sdata.DoRelocs(reloc);
\r
3307 if (rsrc != null) rsrc.DoRelocs(reloc);
\r
3308 relocTide = (uint)reloc.Seek(0,SeekOrigin.Current);
\r
3309 relocPadding = NumToAlign(relocTide,fileAlign);
\r
3310 relocSize = relocTide + relocPadding;
\r
3311 imageSize = relocRVA + SectionAlignment;
\r
3312 initDataSize += relocSize;
\r
3315 private void CalcOffsets() {
\r
3320 headerSize = fileHeaderSize + (numSections * sectionHeaderSize);
\r
3321 headerPadding = NumToAlign(headerSize,fileAlign);
\r
3322 headerSize += headerPadding;
\r
3323 uint offset = headerSize;
\r
3324 uint rva = SectionAlignment;
\r
3325 text.SetOffset(offset);
\r
3327 offset += text.Size();
\r
3328 rva = GetNextSectStart(rva,text.Tide());
\r
3329 // Console.WriteLine("headerSize = " + headerSize);
\r
3330 // Console.WriteLine("headerPadding = " + headerPadding);
\r
3331 // Console.WriteLine("textOffset = " + Hex.Int(text.Offset()));
\r
3332 if (sdata != null) {
\r
3333 sdata.SetSize(NumToAlign(sdata.Tide(),fileAlign));
\r
3334 sdata.SetOffset(offset);
\r
3335 sdata.SetRVA(rva);
\r
3336 offset += sdata.Size();
3337 rva = GetNextSectStart(rva,sdata.Tide());
\r
3338 initDataSize += sdata.Size();
\r
3340 if (rsrc != null) {
\r
3341 rsrc.SetSize(NumToAlign(rsrc.Tide(),fileAlign));
\r
3342 rsrc.SetOffset(offset);
\r
3344 offset += rsrc.Size();
\r
3345 rva = GetNextSectStart(rva,rsrc.Tide());
\r
3346 initDataSize += rsrc.Size();
\r
3348 relocOffset = offset;
\r
3352 internal void MakeFile() {
\r
3353 if (doDLL) hintNameTable = dllHintNameTable.ToCharArray();
\r
3354 else hintNameTable = exeHintNameTable.ToCharArray();
\r
3355 BuildTextSection();
\r
3357 BuildRelocSection();
\r
3358 // now write it out
\r
3365 private void WriteHeader() {
\r
3367 // Console.WriteLine("Writing PEHeader at offset " + Seek(0,SeekOrigin.Current));
\r
3369 // Console.WriteLine("Writing text section header at offset " + Hex.Long(Seek(0,SeekOrigin.Current)));
\r
3370 text.WriteHeader(this,relocRVA);
\r
3371 if (sdata != null) sdata.WriteHeader(this,relocRVA);
\r
3372 if (rsrc != null) rsrc.WriteHeader(this,relocRVA);
\r
3373 // Console.WriteLine("Writing reloc section header at offset " + Seek(0,SeekOrigin.Current));
\r
3374 WriteRelocSectionHeader();
\r
3375 // Console.WriteLine("Writing padding at offset " + Seek(0,SeekOrigin.Current));
\r
3376 WriteZeros(headerPadding);
\r
3379 private void WriteSections() {
\r
3380 // Console.WriteLine("Writing text section at offset " + Seek(0,SeekOrigin.Current));
\r
3381 WriteTextSection();
\r
3382 if (sdata != null) WriteSDataSection();
\r
3383 if (rsrc != null) WriteRsrcSection();
\r
3384 WriteRelocSection();
\r
3387 private void WriteIAT() {
\r
3388 Write(text.RVA() + hintNameTableOffset);
\r
3392 private void WriteImportTables() {
\r
3394 WriteZeros(importTablePadding);
\r
3395 // Console.WriteLine("Writing import tables at offset " + Hex.Long(Seek(0,SeekOrigin.Current)));
\r
3396 Write(importLookupTableOffset + text.RVA());
\r
3398 Write(runtimeEngineOffset + text.RVA());
\r
3399 Write(text.RVA()); // IAT is at the beginning of the text section
\r
3401 // Import Lookup Table
\r
3402 WriteIAT(); // lookup table and IAT are the same
\r
3403 // Hint/Name Table
\r
3404 // Console.WriteLine("Writing hintname table at " + Hex.Long(Seek(0,SeekOrigin.Current)));
\r
3405 Write(hintNameTable);
\r
3406 Write(runtimeEngineName.ToCharArray());
\r
3409 private void WriteTextSection() {
\r
3412 // Console.WriteLine("Writing code at " + Hex.Long(Seek(0,SeekOrigin.Current)));
\r
3413 metaData.WriteByteCodes(this);
\r
3414 // Console.WriteLine("Finished writing code at " + Hex.Long(Seek(0,SeekOrigin.Current)));
\r
3415 largeStrings = metaData.LargeStringsIndex();
\r
3416 largeGUID = metaData.LargeGUIDIndex();
\r
3417 largeUS = metaData.LargeUSIndex();
\r
3418 largeBlob = metaData.LargeBlobIndex();
\r
3419 metaData.WriteMetaData(this);
\r
3420 WriteImportTables();
\r
3421 WriteZeros(entryPointPadding);
\r
3422 Write((ushort)0x25FF);
\r
3423 Write(ImageBase + text.RVA());
\r
3424 WriteZeros(text.Padding());
\r
3427 private void WriteCLIHeader() {
\r
3428 Write(CLIHeaderSize); // Cb
\r
3429 Write((short)2); // Major runtime version
\r
3430 Write((short)0); // Minor runtime version
\r
3431 Write(text.RVA() + metaDataOffset);
\r
3432 Write(metaData.Size());
\r
3433 Write(runtimeFlags);
\r
3434 Write(entryPointToken);
\r
3435 WriteZeros(8); // Resources - used by Manifest Resources NYI
\r
3436 WriteZeros(8); // Strong Name stuff here!! NYI
\r
3437 WriteZeros(8); // CodeManagerTable
\r
3438 WriteZeros(8); // VTableFixups NYI
\r
3439 WriteZeros(16); // ExportAddressTableJumps, ManagedNativeHeader
\r
3442 private void WriteSDataSection() {
\r
3443 for (int i=0; i < data.Count; i++) {
\r
3444 ((DataConstant)data[i]).Write(this);
\r
3448 private void WriteRsrcSection() {
\r
3451 private void WriteRelocSection() {
\r
3452 // Console.WriteLine("Writing reloc section at " + Seek(0,SeekOrigin.Current) + " = " + relocOffset);
\r
3453 MemoryStream str = (MemoryStream)reloc.BaseStream;
\r
3454 Write(str.ToArray());
\r
3455 WriteZeros(NumToAlign((uint)str.Position,fileAlign));
\r
3458 internal void SetEntryPoint(uint entryPoint) {
\r
3459 entryPointToken = entryPoint;
\r
3462 internal void AddInitData(DataConstant cVal) {
\r
3463 if (sdata == null) {
\r
3464 sdata = new Section(sdataName,0xC0000040); // IMAGE_SCN_CNT INITIALIZED_DATA, READ, WRITE
\r
3465 data = new ArrayList();
\r
3468 cVal.DataOffset = sdata.Tide();
\r
3469 sdata.IncTide(cVal.GetSize());
\r
3472 internal void WriteZeros(uint numZeros) {
\r
3473 for (int i=0; i < numZeros; i++) {
\r
3478 internal void WritePEHeader() {
\r
3479 Write((ushort)0x014C); // Machine - always 0x14C for Managed PE Files (allow others??)
\r
3480 Write((ushort)numSections);
\r
3482 WriteZeros(8); // Pointer to Symbol Table and Number of Symbols (always zero for ECMA CLI files)
\r
3483 Write((ushort)0x00E0); // Size of Optional Header
\r
3484 Write(characteristics);
\r
3485 // PE Optional Header
\r
3486 Write((ushort)0x010B); // Magic
\r
3487 Write((byte)0x6); // LMajor pure-IL = 6 C++ = 7
\r
3488 Write((byte)0x0); // LMinor
\r
3489 Write(text.Size());
\r
3490 Write(initDataSize);
\r
3491 Write(0); // Check other sections here!!
\r
3492 Write(text.RVA() + entryPointOffset);
\r
3493 Write(text.RVA());
\r
3494 uint dataBase = 0;
\r
3495 if (sdata != null) dataBase = sdata.RVA();
\r
3496 else if (rsrc != null) dataBase = rsrc.RVA();
\r
3497 else dataBase = relocRVA;
\r
3500 Write(SectionAlignment);
\r
3502 Write((ushort)0x04); // OS Major
\r
3503 WriteZeros(6); // OS Minor, User Major, User Minor
\r
3504 Write((ushort)0x04); // SubSys Major
\r
3505 WriteZeros(6); // SybSys Minor, Reserved
\r
3507 Write(headerSize);
\r
3508 Write((int)0); // File Checksum
\r
3509 Write((ushort)subSys);
\r
3510 Write((short)0); // DLL Flags
\r
3511 Write((uint)0x100000); // Stack Reserve Size
\r
3512 Write((uint)0x1000); // Stack Commit Size
\r
3513 Write((uint)0x100000); // Heap Reserve Size
\r
3514 Write((uint)0x1000); // Heap Commit Size
\r
3515 Write(0); // Loader Flags
\r
3516 Write(0x10); // Number of Data Directories
\r
3517 WriteZeros(8); // Export Table
\r
3518 Write(importTableOffset + text.RVA());
\r
3519 Write(totalImportTableSize);
\r
3520 WriteZeros(24); // Resource, Exception and Certificate Tables
\r
3523 WriteZeros(48); // Debug, Copyright, Global Ptr, TLS, Load Config and Bound Import Tables
\r
3524 Write(text.RVA()); // IATRVA - IAT is at start of .text Section
\r
3526 WriteZeros(8); // Delay Import Descriptor
\r
3527 Write(text.RVA()+IATSize); // CLIHeader immediately follows IAT
\r
3528 Write(CLIHeaderSize);
\r
3529 WriteZeros(8); // Reserved
\r
3532 internal void WriteRelocSectionHeader() {
\r
3533 Write(relocName.ToCharArray());
\r
3537 Write(relocOffset);
\r
3539 Write(relocFlags);
\r
3542 private void Align (MemoryStream str, int val) {
\r
3543 if ((str.Position % val) != 0) {
\r
3544 for (int i=val - (int)(str.Position % val); i > 0; i--) {
\r
3550 private uint Align(uint val, uint alignVal) {
\r
3551 if ((val % alignVal) != 0) {
\r
3552 val += alignVal - (val % alignVal);
\r
3557 private uint NumToAlign(uint val, uint alignVal) {
\r
3558 if ((val % alignVal) == 0) return 0;
\r
3559 return alignVal - (val % alignVal);
\r
3562 internal void StringsIndex(uint ix) {
\r
3563 if (largeStrings) Write(ix);
\r
3564 else Write((ushort)ix);
\r
3567 internal void GUIDIndex(uint ix) {
\r
3568 if (largeGUID) Write(ix);
\r
3569 else Write((ushort)ix);
\r
3572 internal void USIndex(uint ix) {
\r
3573 if (largeUS) Write(ix);
\r
3574 else Write((ushort)ix);
\r
3577 internal void BlobIndex(uint ix) {
\r
3578 if (largeBlob) Write(ix);
\r
3579 else Write((ushort)ix);
\r
3582 internal void WriteIndex(MDTable tabIx,uint ix) {
\r
3583 if (metaData.LargeIx(tabIx)) Write(ix);
\r
3584 else Write((ushort)ix);
\r
3587 internal void WriteCodedIndex(CIx code, MetaDataElement elem) {
\r
3588 metaData.WriteCodedIndex(code,elem,this);
\r
3591 internal void WriteCodeRVA(uint offs) {
\r
3592 Write(text.RVA() + offs);
\r
3595 internal void WriteDataRVA(uint offs) {
\r
3596 Write(sdata.RVA() + offs);
\r
3599 internal void Write3Bytes(uint val) {
\r
3600 byte b3 = (byte)((val & FileImage.iByteMask[2]) >> 16);
\r
3601 byte b2 = (byte)((val & FileImage.iByteMask[1]) >> 8);;
\r
3602 byte b1 = (byte)(val & FileImage.iByteMask[0]);
\r
3609 /**************************************************************************/
\r
3611 /// Descriptor for a file referenced in THIS assembly/module (.file)
\r
3613 public class FileRef : MetaDataElement
\r
3615 private static readonly uint HasMetaData = 0x1;
\r
3616 uint nameIx = 0, hashIx = 0;
\r
3619 internal FileRef(string name, byte[] hashBytes, bool metaData,
\r
3620 bool entryPoint, MetaData md) {
\r
3621 if (metaData) flags = HasMetaData;
\r
3622 if (entryPoint) md.SetEntryPoint(this);
\r
3623 nameIx = md.AddToStringsHeap(name);
\r
3624 hashIx = md.AddToBlobHeap(hashBytes);
\r
3625 tabIx = MDTable.File;
\r
3628 internal FileRef(uint nameIx, byte[] hashBytes, bool metaData,
\r
3629 bool entryPoint, MetaData md) {
\r
3630 if (metaData) flags = HasMetaData;
\r
3631 if (entryPoint) md.SetEntryPoint(this);
\r
3632 this.nameIx = nameIx;
\r
3633 hashIx = md.AddToBlobHeap(hashBytes);
\r
3634 tabIx = MDTable.File;
\r
3637 internal sealed override uint Size(MetaData md) {
\r
3638 return 4 + md.StringsIndexSize() + md.BlobIndexSize();
\r
3641 internal sealed override void Write(FileImage output) {
\r
3642 output.Write(flags);
\r
3643 output.StringsIndex(nameIx);
\r
3644 output.BlobIndex(hashIx);
\r
3647 internal sealed override uint GetCodedIx(CIx code) {
\r
3649 case (CIx.HasCustomAttr) : return 16;
\r
3650 case (CIx.Implementation) : return 0;
\r
3656 /**************************************************************************/
\r
3658 /// Descriptor for pinvoke information for a method NOT YET IMPLEMENTED
\r
3660 public class ImplMap : MetaDataElement
\r
3662 private static readonly ushort NoMangle = 0x01;
\r
3665 string importName;
\r
3667 ModuleRef importScope;
\r
3669 internal ImplMap(ushort flag, Method implMeth, string iName, ModuleRef mScope) {
\r
3672 importName = iName;
\r
3673 importScope = mScope;
\r
3674 tabIx = MDTable.ImplMap;
\r
3675 if (iName == null) flags |= NoMangle;
\r
3676 //throw(new NotYetImplementedException("PInvoke "));
\r
3679 internal sealed override void BuildTables(MetaData md) {
\r
3681 iNameIx = md.AddToStringsHeap(importName);
\r
3685 internal sealed override uint Size(MetaData md) {
\r
3686 return 2+ md.CodedIndexSize(CIx.MemberForwarded) +
\r
3687 md.StringsIndexSize() + md.TableIndexSize(MDTable.ModuleRef);
\r
3690 internal sealed override void Write(FileImage output) {
\r
3691 output.Write(flags);
\r
3692 output.WriteCodedIndex(CIx.MemberForwarded,meth);
\r
3693 output.StringsIndex(iNameIx);
\r
3694 output.WriteIndex(MDTable.ModuleRef,importScope.Row);
\r
3699 /**************************************************************************/
\r
3701 /// Descriptor for an IL instruction
\r
3703 internal abstract class CILInstruction {
\r
3704 protected static readonly sbyte maxByteVal = 127;
\r
3705 protected static readonly sbyte minByteVal = -128;
\r
3706 protected static readonly byte leadByte = 0xFE;
\r
3707 protected static readonly uint USHeapIndex = 0x70000000;
\r
3708 protected static readonly int longInstrStart = (int)Op.arglist;
\r
3709 public bool twoByteInstr = false;
\r
3710 public uint size = 0;
\r
3711 public uint offset;
\r
3713 internal virtual bool Check(MetaData md) {
\r
3717 internal virtual void Write(FileImage output) { }
\r
3721 internal class CILByte : CILInstruction {
\r
3724 internal CILByte(byte bVal) {
\r
3729 internal override void Write(FileImage output) {
\r
3730 output.Write(byteVal);
\r
3736 internal class Instr : CILInstruction {
\r
3737 protected int instr;
\r
3739 internal Instr(int inst) {
\r
3740 if (inst >= longInstrStart) {
\r
3741 instr = inst - longInstrStart;
\r
3742 twoByteInstr = true;
\r
3750 internal override void Write(FileImage output) {
\r
3751 //Console.WriteLine("Writing instruction " + instr + " with size " + size);
\r
3752 if (twoByteInstr) output.Write(leadByte);
\r
3753 output.Write((byte)instr);
\r
3758 internal class IntInstr : Instr {
\r
3762 internal IntInstr(int inst, int num, bool byteSize) : base(inst) {
\r
3764 byteNum = byteSize;
\r
3765 if (byteNum) size++;
\r
3769 internal sealed override void Write(FileImage output) {
\r
3770 base.Write(output);
\r
3772 output.Write((sbyte)val);
\r
3774 output.Write(val);
\r
3779 internal class UIntInstr : Instr {
\r
3783 internal UIntInstr(int inst, int num, bool byteSize) : base(inst) {
\r
3785 byteNum = byteSize;
\r
3786 if (byteNum) size++;
\r
3790 internal sealed override void Write(FileImage output) {
\r
3791 base.Write(output);
\r
3793 output.Write((byte)val);
\r
3795 output.Write((ushort)val);
\r
3800 internal class LongInstr : Instr {
\r
3803 internal LongInstr(int inst, long l) : base(inst) {
\r
3808 internal sealed override void Write(FileImage output) {
\r
3809 base.Write(output);
\r
3810 output.Write(val);
\r
3815 internal class FloatInstr : Instr {
\r
3818 internal FloatInstr(int inst, float f) : base(inst) {
\r
3823 internal sealed override void Write(FileImage output) {
\r
3824 base.Write(output);
\r
3825 output.Write(fVal);
\r
3830 internal class DoubleInstr : Instr {
\r
3833 internal DoubleInstr(int inst, double d) : base(inst) {
\r
3838 internal sealed override void Write(FileImage output) {
\r
3839 base.Write(output);
\r
3840 output.Write(val);
\r
3845 internal class StringInstr : Instr {
\r
3849 internal StringInstr(int inst, string str) : base(inst) {
\r
3854 internal sealed override bool Check(MetaData md) {
\r
3855 strIndex = md.AddToUSHeap(val);
\r
3859 internal sealed override void Write(FileImage output) {
\r
3860 base.Write(output);
\r
3861 output.Write(USHeapIndex | strIndex);
\r
3866 internal class LabelInstr : CILInstruction {
\r
3869 internal LabelInstr(CILLabel lab) {
\r
3871 label.AddLabelInstr(this);
\r
3875 internal class FieldInstr : Instr {
\r
3878 internal FieldInstr(int inst, Field f) : base(inst) {
\r
3883 internal sealed override void Write(FileImage output) {
\r
3884 base.Write(output);
\r
3885 output.Write(field.Token());
\r
3890 internal class MethInstr : Instr {
\r
3893 internal MethInstr(int inst, Method m) : base(inst) {
\r
3898 internal sealed override void Write(FileImage output) {
\r
3899 base.Write(output);
\r
3900 output.Write(meth.Token());
\r
3905 internal class SigInstr : Instr {
\r
3906 CalliSig signature;
\r
3908 internal SigInstr(int inst, CalliSig sig) : base(inst) {
\r
3913 internal sealed override bool Check(MetaData md) {
\r
3914 md.AddToTable(MDTable.StandAloneSig,signature);
\r
3915 signature.BuildTables(md);
\r
3919 internal sealed override void Write(FileImage output) {
\r
3920 base.Write(output);
\r
3921 output.Write(signature.Token());
\r
3925 internal class TypeInstr : Instr {
\r
3926 MetaDataElement theType;
\r
3928 internal TypeInstr(int inst, Type aType, MetaData md) : base(inst) {
\r
3929 theType = aType.GetTypeSpec(md);
\r
3933 internal sealed override void Write(FileImage output) {
\r
3934 base.Write(output);
\r
3935 output.Write(theType.Token());
\r
3940 internal class BranchInstr : Instr {
\r
3942 private bool shortVer = true;
\r
3943 private static readonly byte longInstrOffset = 13;
\r
3944 private int target = 0;
\r
3946 internal BranchInstr(int inst, CILLabel dst) : base(inst) {
\r
3948 dest.AddBranch(this);
\r
3951 if (inst >= (int) BranchOp.br && inst != (int) BranchOp.leave_s) {
3957 internal sealed override bool Check(MetaData md) {
\r
3958 target = (int)dest.GetLabelOffset() - (int)(offset + size);
\r
3962 internal sealed override void Write(FileImage output) {
\r
3963 base.Write(output);
\r
3965 output.Write((sbyte)target);
\r
3967 output.Write(target);
\r
3972 internal class SwitchInstr : Instr {
\r
3974 uint numCases = 0;
\r
3976 internal SwitchInstr(int inst, CILLabel[] dsts) : base(inst) {
\r
3978 if (cases != null) numCases = (uint)cases.Length;
\r
3979 size += 4 + (numCases * 4);
\r
3980 for (int i=0; i < numCases; i++) {
\r
3981 cases[i].AddBranch(this);
\r
3985 internal sealed override void Write(FileImage output) {
\r
3986 base.Write(output);
\r
3987 output.Write(numCases);
\r
3988 for (int i=0; i < numCases; i++) {
\r
3989 int target = (int)cases[i].GetLabelOffset() - (int)(offset + size);
\r
3990 output.Write(target);
\r
3995 /**************************************************************************/
\r
3997 public class GenericParameter : MetaDataElement
\r
3999 MetaDataElement owner;
4005 internal GenericParameter (ClassDef owner, MetaData metadata,
4006 short index, string name) : this (owner, metadata, index, name, true)
4010 internal GenericParameter (MethodDef owner, MetaData metadata,
4011 short index, string name) : this (owner, metadata, index, name, true)
4015 private GenericParameter (MetaDataElement owner, MetaData metadata,
4016 short index, string name, bool nadda)
4018 this.owner = owner;
\r
4019 this.metadata = metadata;
4020 this.index = index;
\r
4021 tabIx = MDTable.GenericParam;
\r
4025 public void AddConstraint (Type constraint) {
4026 metadata.AddToTable (MDTable.GenericParamConstraint,
\r
4027 new GenericParamConstraint (this, constraint));
\r
4030 internal sealed override uint Size(MetaData md) {
\r
4031 return (uint) (4 +
\r
4032 md.CodedIndexSize(CIx.TypeOrMethodDef) +
\r
4034 md.TableIndexSize(MDTable.TypeDef));
\r
4037 internal sealed override void BuildTables(MetaData md) {
\r
4039 nameIx = md.AddToStringsHeap(name);
\r
4043 internal sealed override void Write(FileImage output) {
\r
4044 output.Write ((short) index);
\r
4045 output.Write ((short) 0);
\r
4046 output.WriteCodedIndex(CIx.TypeOrMethodDef, owner);
\r
4047 output.Write ((uint) nameIx);
\r
4048 output.WriteIndex(MDTable.TypeDef,owner.Row);
\r
4054 internal class GenericParamConstraint : MetaDataElement
\r
4056 GenericParameter param;
\r
4059 public GenericParamConstraint (GenericParameter param, Type type) {
\r
4060 this.param = param;
\r
4062 tabIx = MDTable.GenericParamConstraint;
\r
4065 internal sealed override uint Size(MetaData md) {
\r
4066 return (uint) (md.TableIndexSize(MDTable.GenericParam) +
\r
4067 md.CodedIndexSize(CIx.TypeDefOrRef));
\r
4070 internal sealed override void Write(FileImage output) {
\r
4071 output.WriteIndex(MDTable.GenericParam, param.Row);
\r
4072 output.WriteCodedIndex(CIx.TypeDefOrRef, type);
\r
4078 internal class MethodSpec : MetaDataElement
4081 GenericMethodSig g_sig;
4084 internal MethodSpec (Method meth, GenericMethodSig g_sig) {
4087 tabIx = MDTable.MethodSpec;
4090 internal sealed override void BuildTables (MetaData md) {
4092 sidx = g_sig.GetSigIx (md);
4096 internal sealed override uint Size (MetaData md) {
4097 return (uint) (md.CodedIndexSize(CIx.MethodDefOrRef) +
4098 md.BlobIndexSize ());
4101 internal sealed override void Write (FileImage output) {
4102 output.WriteCodedIndex (CIx.MethodDefOrRef, meth);
4103 output.BlobIndex (sidx);
\r
4107 /**************************************************************************/
\r
4109 /// Descriptor for interface implemented by a class
\r
4111 public class InterfaceImpl: MetaDataElement
\r
4113 ClassDef theClass;
\r
4114 Class theInterface;
\r
4116 internal InterfaceImpl(ClassDef theClass, Class theInterface) {
\r
4117 this.theClass = theClass;
\r
4118 this.theInterface = theInterface;
\r
4119 tabIx = MDTable.InterfaceImpl;
\r
4122 internal sealed override uint Size(MetaData md) {
\r
4123 return md.TableIndexSize(MDTable.TypeDef) +
\r
4124 md.CodedIndexSize(CIx.TypeDefOrRef);
\r
4127 internal sealed override void Write(FileImage output) {
\r
4128 output.WriteIndex(MDTable.TypeDef,theClass.Row);
\r
4129 output.WriteCodedIndex(CIx.TypeDefOrRef,theInterface);
\r
4132 internal sealed override uint GetCodedIx(CIx code) { return 5; }
\r
4135 /**************************************************************************/
\r
4137 /// Descriptor for a local of a method
\r
4139 public class Local
\r
4141 private static readonly byte Pinned = 0x45;
\r
4144 bool pinned = false, byref = false;
\r
4147 /// Create a new local variable
\r
4149 /// <param name="lName">name of the local variable</param>
\r
4150 /// <param name="lType">type of the local variable</param>
\r
4151 public Local(string lName, Type lType) {
\r
4157 /// Create a new local variable that is byref and/or pinned
\r
4159 /// <param name="lName">local name</param>
\r
4160 /// <param name="lType">local type</param>
\r
4161 /// <param name="byRef">is byref</param>
\r
4162 /// <param name="isPinned">has pinned attribute</param>
\r
4163 public Local(string lName, Type lType, bool byRef, bool isPinned)
\r
4168 pinned = isPinned;
\r
4171 internal void TypeSig(MemoryStream str) {
\r
4172 if (pinned) str.WriteByte(Pinned);
\r
4173 type.TypeSig(str);
\r
4177 /**************************************************************************/
\r
4179 /// Descriptor for the locals for a method
\r
4182 public class LocalSig : Signature
\r
4184 private static readonly byte LocalSigByte = 0x7;
\r
4187 public LocalSig(Local[] locals) {
\r
4188 this.locals = locals;
\r
4189 tabIx = MDTable.StandAloneSig;
\r
4192 internal sealed override void BuildTables(MetaData md) {
\r
4194 MemoryStream sig = new MemoryStream();
\r
4195 sig.WriteByte(LocalSigByte);
\r
4196 MetaData.CompressNum((uint)locals.Length,sig);
\r
4197 for (int i=0; i < locals.Length; i++) {
\r
4198 ((Local)locals[i]).TypeSig(sig);
\r
4200 sigIx = md.AddToBlobHeap(sig.ToArray());
\r
4206 /**************************************************************************/
\r
4208 /// Descriptor for resources used in this PE file NOT YET IMPLEMENTED
\r
4211 public class ManifestResource : MetaDataElement
\r
4213 private static readonly uint PublicResource = 0x1;
\r
4214 private static readonly uint PrivateResource = 0x2;
\r
4217 MetaDataElement rRef;
\r
4222 public ManifestResource(string name, bool isPub, FileRef fileRef) {
\r
4224 if (isPub) flags = PublicResource;
\r
4225 else flags = PrivateResource;
\r
4227 tabIx = MDTable.ManifestResource;
\r
4228 throw(new NotYetImplementedException("Manifest Resources "));
\r
4231 public ManifestResource(string name, bool isPub, FileRef fileRef,
\r
4234 if (isPub) flags = PublicResource;
\r
4235 else flags = PrivateResource;
\r
4237 fileOffset = fileIx;
\r
4240 public ManifestResource(string name, bool isPub, AssemblyRef assemRef) {
\r
4242 if (isPub) flags = PublicResource;
\r
4243 else flags = PrivateResource;
\r
4247 internal sealed override void BuildTables(MetaData md) {
\r
4249 nameIx = md.AddToStringsHeap(mrName);
\r
4253 internal sealed override uint Size(MetaData md) {
\r
4254 return 8 + md.StringsIndexSize() +
\r
4255 md.CodedIndexSize(CIx.Implementation);
\r
4258 internal sealed override void Write(FileImage output) {
\r
4259 output.Write(fileOffset);
\r
4260 output.Write(flags);
\r
4261 output.StringsIndex(nameIx);
\r
4262 output.WriteCodedIndex(CIx.Implementation,rRef);
\r
4265 internal sealed override uint GetCodedIx(CIx code) { return 18; }
\r
4268 /**************************************************************************/
\r
4270 /// Base class for elements in the PropertyMap, EventMap and
\r
4271 /// NestedClass MetaData tables
\r
4273 public class MapElem : MetaDataElement
\r
4277 MDTable elemTable;
\r
4279 internal MapElem(ClassDef par, uint elIx, MDTable elemTab) {
\r
4282 elemTable = elemTab;
\r
4285 internal sealed override uint Size(MetaData md) {
\r
4286 return md.TableIndexSize(MDTable.TypeDef) + md.TableIndexSize(elemTable);
\r
4289 internal sealed override void Write(FileImage output) {
\r
4290 output.WriteIndex(MDTable.TypeDef,parent.Row);
\r
4291 output.WriteIndex(elemTable,elemIx);
\r
4294 /**************************************************************************/
\r
4296 /// Base class for field/methods (member of a class)
\r
4298 public abstract class Member : MetaDataElement
\r
4300 protected string name;
\r
4301 protected uint nameIx = 0, sigIx = 0;
\r
4303 internal Member(string memName)
\r
4306 tabIx = MDTable.MemberRef;
\r
4310 /**************************************************************************/
\r
4313 /// Root (20 bytes + UTF-8 Version String + quad align padding)
\r
4314 /// StreamHeaders (8 bytes + null terminated name string + quad align padding)
\r
4316 /// #~ (always present - holds metadata tables)
\r
4317 /// #Strings (always present - holds identifier strings)
\r
4318 /// #US (Userstring heap)
\r
4319 /// #Blob (signature blobs)
\r
4320 /// #GUID (guids for assemblies or Modules)
\r
4323 public class MetaData
\r
4325 private static readonly int[] CIxShiftMap = {2,2,5,1,2,3,1,1,1,2,3,2,1};
\r
4326 private static readonly byte StringsHeapMask = 0x1;
\r
4327 private static readonly byte GUIDHeapMask = 0x2;
\r
4328 private static readonly byte BlobHeapMask = 0x4;
\r
4329 private static readonly uint MetaDataSignature = 0x424A5342;
\r
4330 private static readonly uint maxSmlIxSize = 0xFFFF;
\r
4331 private static readonly uint max1BitSmlIx = 0x7FFF;
\r
4332 private static readonly uint max2BitSmlIx = 0x3FFF;
\r
4333 private static readonly uint max3BitSmlIx = 0x1FFF;
\r
4334 private static readonly uint max5BitSmlIx = 0x7FF;
\r
4335 // NOTE: version and stream name strings MUST always be quad padded
\r
4336 private static readonly string version = "v1.0.3705\0\0\0";
\r
4337 private static readonly char[] tildeName = {'#','~','\0','\0'};
\r
4338 private static readonly char[] stringsName = {'#','S','t','r','i','n','g','s','\0','\0','\0','\0'};
\r
4339 private static readonly char[] usName = {'#','U','S','\0'};
\r
4340 private static readonly char[] guidName = {'#','G','U','I','D','\0','\0','\0'};
\r
4341 private static readonly char[] blobName = {'#','B','l','o','b','\0','\0','\0'};
\r
4342 private static readonly uint MetaDataHeaderSize = 20 + (uint)version.Length;
\r
4343 private static readonly uint TildeHeaderSize = 24;
\r
4344 private static readonly uint StreamHeaderSize = 8;
\r
4345 private static readonly uint numMetaDataTables = (int)MDTable.GenericParamConstraint + 1;
\r
4346 private static readonly uint tildeHeaderSize = 8 + (uint)tildeName.Length;
\r
4348 MetaDataStream strings, us, guid, blob;
\r
4350 MetaDataStream[] streams = new MetaDataStream[5];
\r
4351 uint numStreams = 5;
\r
4352 uint tildeTide = 0, tildePadding = 0, tildeStart = 0;
\r
4353 uint numTables = 0;
\r
4354 ArrayList[] metaDataTables = new ArrayList[numMetaDataTables];
\r
4355 ArrayList byteCodes = new ArrayList();
\r
4356 uint codeSize = 0, codeStart, byteCodePadding = 0, metaDataSize = 0;
\r
4357 ulong valid = 0, /*sorted = 0x000002003301FA00;*/ sorted = 0;
\r
4358 bool[] largeIx = new bool[numMetaDataTables];
\r
4359 bool[] lgeCIx = new bool[(int)CIx.MaxCIx];
\r
4360 bool largeStrings = false, largeUS = false, largeGUID = false, largeBlob = false;
\r
4361 private FileImage file;
\r
4362 private byte heapSizes = 0;
\r
4363 MetaDataElement entryPoint;
\r
4364 BinaryWriter output;
\r
4365 public MSCorLib mscorlib;
\r
4366 private TypeSpec[] systemTypeSpecs = new TypeSpec[PrimitiveType.NumSystemTypes];
\r
4369 internal MetaData(FileImage file) {
\r
4370 // tilde = new MetaDataStream(tildeName,false,0);
\r
4372 strings = new MetaDataStream(stringsName,new UTF8Encoding(),true);
\r
4373 us = new MetaDataStream(usName,new UnicodeEncoding(),true);
\r
4374 guid = new MetaDataStream(guidName,false);
\r
4375 blob = new MetaDataStream(blobName,true);
\r
4376 streams[1] = strings;
\r
4378 streams[3] = guid;
\r
4379 streams[4] = blob;
\r
4380 for (int i=0; i < numMetaDataTables; i++) {
\r
4381 largeIx[i] = false;
\r
4383 for (int i=0; i < lgeCIx.Length; i++) {
\r
4384 lgeCIx[i] = false;
\r
4386 mscorlib = new MSCorLib(this);
\r
4389 internal TypeSpec GetPrimitiveTypeSpec(int ix) {
\r
4390 return systemTypeSpecs[ix];
\r
4393 internal void SetPrimitiveTypeSpec(int ix, TypeSpec typeSpec) {
\r
4394 systemTypeSpecs[ix] = typeSpec;
\r
4397 internal uint Size() {
\r
4398 return metaDataSize;
\r
4401 internal void StreamSize(byte mask) {
\r
4402 heapSizes |= mask;
\r
4405 internal uint AddToUSHeap(string str) {
\r
4406 if (str == null) return 0;
\r
4407 return us.Add(str,true);
\r
4410 internal uint AddToStringsHeap(string str) {
\r
4411 if ((str == null) || (str.CompareTo("") == 0)) return 0;
\r
4412 return strings.Add(str,false);
\r
4415 internal uint AddToGUIDHeap(Guid guidNum) {
\r
4416 return guid.Add(guidNum);
\r
4419 internal uint AddToBlobHeap(byte[] blobBytes) {
\r
4420 if (blobBytes == null) return 0;
\r
4421 return blob.Add(blobBytes);
\r
4424 internal uint AddToBlobHeap(byte val) {
\r
4425 return blob.Add(val);
\r
4428 internal uint AddToBlobHeap(sbyte val) {
\r
4429 return blob.Add(val);
\r
4432 internal uint AddToBlobHeap(ushort val) {
\r
4433 return blob.Add(val);
\r
4436 internal uint AddToBlobHeap(short val) {
\r
4437 return blob.Add(val);
\r
4440 internal uint AddToBlobHeap(uint val) {
\r
4441 return blob.Add(val);
\r
4444 internal uint AddToBlobHeap(int val) {
\r
4445 return blob.Add(val);
\r
4448 internal uint AddToBlobHeap(ulong val) {
\r
4449 return blob.Add(val);
\r
4452 internal uint AddToBlobHeap(long val) {
\r
4453 return blob.Add(val);
\r
4456 internal uint AddToBlobHeap(float val) {
\r
4457 return blob.Add(val);
\r
4460 internal uint AddToBlobHeap(double val) {
\r
4461 return blob.Add(val);
\r
4464 internal uint AddToBlobHeap(string val) {
\r
4465 return blob.Add(val,true);
\r
4469 private ArrayList GetTable(MDTable tableIx) {
\r
4470 int tabIx = (int)tableIx;
\r
4471 if (metaDataTables[tabIx] == null) {
\r
4472 metaDataTables[tabIx] = new ArrayList();
\r
4473 valid |= ((ulong)0x1 << tabIx);
\r
4474 // Console.WriteLine("after creating table " + tableIx + "(" + tabIx + ") valid = " + valid);
\r
4477 return metaDataTables[tabIx];
\r
4480 internal void AddToTable(MDTable tableIx, MetaDataElement elem) {
\r
4481 if (elem.Row > 0) {
\r
4482 // Console.Out.WriteLine("ERROR - element already in table " + tableIx);
\r
4485 // updates Row field of the element
\r
4486 // Console.WriteLine("Adding element to table " + (uint)tableIx);
\r
4487 ArrayList table = GetTable(tableIx);
\r
4488 elem.Row = (uint)table.Count + 1;
\r
4492 internal uint TableIndex(MDTable tableIx) {
\r
4493 if (metaDataTables[(int)tableIx] == null) return 1;
\r
4494 return (uint)metaDataTables[(int)tableIx].Count+1;
\r
4497 internal uint AddCode(CILInstructions byteCode) {
\r
4498 byteCodes.Add(byteCode);
\r
4499 uint offset = codeSize + codeStart;
\r
4500 codeSize += byteCode.GetCodeSize();
\r
4504 internal void SetEntryPoint(MetaDataElement ep) {
\r
4508 internal void AddData(DataConstant cVal) {
\r
4509 file.AddInitData(cVal);
\r
4512 internal static void CompressNum(uint val, MemoryStream sig) {
\r
4514 sig.WriteByte((byte)val);
\r
4515 } else if (val < 0x3FFF) {
\r
4516 byte b1 = (byte)((val >> 8) | 0x80);
\r
4517 byte b2 = (byte)(val & FileImage.iByteMask[0]);
\r
4518 sig.WriteByte(b1);
\r
4519 sig.WriteByte(b2);
\r
4521 byte b1 = (byte)((val >> 24) | 0xC0);
\r
4522 byte b2 = (byte)((val & FileImage.iByteMask[2]) >> 16);
\r
4523 byte b3 = (byte)((val & FileImage.iByteMask[1]) >> 8);;
\r
4524 byte b4 = (byte)(val & FileImage.iByteMask[0]);
\r
4525 sig.WriteByte(b1);
\r
4526 sig.WriteByte(b2);
\r
4527 sig.WriteByte(b3);
\r
4528 sig.WriteByte(b4);
\r
4532 internal uint CodeSize() {
\r
4533 return codeSize + byteCodePadding;
\r
4536 internal uint StringsIndexSize() {
\r
4537 if (largeStrings) return 4;
\r
4541 internal uint GUIDIndexSize() {
\r
4542 if (largeGUID) return 4;
\r
4546 internal uint USIndexSize() {
\r
4547 if (largeUS) return 4;
\r
4551 internal uint BlobIndexSize() {
\r
4552 if (largeBlob) return 4;
\r
4556 internal uint CodedIndexSize(CIx code) {
\r
4557 if (lgeCIx[(uint)code]) return 4;
\r
4561 internal uint TableIndexSize(MDTable tabIx) {
\r
4562 if (largeIx[(uint)tabIx]) return 4;
\r
4566 private void SetIndexSizes() {
\r
4567 for (int i=0; i < numMetaDataTables; i++) {
\r
4568 if (metaDataTables[i] != null) {
\r
4569 uint count = (uint)metaDataTables[i].Count;
\r
4570 if (count > maxSmlIxSize) {
\r
4571 largeIx[i] = true;
\r
4572 MDTable tabIx = (MDTable)i;
\r
4573 if (count > max5BitSmlIx) {
\r
4574 lgeCIx[(int)CIx.HasCustomAttr] = true;
\r
4576 if (count > max3BitSmlIx) {
\r
4577 if ((tabIx == MDTable.TypeRef) || (tabIx == MDTable.ModuleRef) || (tabIx == MDTable.Method) || (tabIx == MDTable.TypeSpec))
\r
4578 lgeCIx[(int)CIx.CustomAttributeType] = true;
\r
4579 if ((tabIx == MDTable.Method) || (tabIx == MDTable.MemberRef))
\r
4580 lgeCIx[(int)CIx.MemberRefParent] = true;
\r
4581 } else if (count > max2BitSmlIx) {
\r
4582 if ((tabIx == MDTable.Field) || (tabIx == MDTable.Param) || (tabIx == MDTable.Property))
\r
4583 lgeCIx[(int)CIx.HasConst] = true;
\r
4584 if ((tabIx == MDTable.TypeDef) || (tabIx == MDTable.TypeRef) || (tabIx == MDTable.TypeSpec))
\r
4585 lgeCIx[(int)CIx.TypeDefOrRef] = true;
\r
4586 if ((tabIx == MDTable.TypeDef) || (tabIx == MDTable.Method) || (tabIx == MDTable.Assembly))
\r
4587 lgeCIx[(int)CIx.HasDeclSecurity] = true;
\r
4588 if ((tabIx == MDTable.File) || (tabIx == MDTable.AssemblyRef) || (tabIx == MDTable.ExportedType))
\r
4589 lgeCIx[(int)CIx.Implementation] = true;
\r
4590 if ((tabIx == MDTable.Module) || (tabIx == MDTable.ModuleRef) || (tabIx == MDTable.AssemblyRef) || (tabIx == MDTable.TypeRef))
\r
4591 lgeCIx[(int)CIx.ResolutionScope] = true;
\r
4592 } else if (count > max1BitSmlIx) {
\r
4593 if ((tabIx == MDTable.Field) || (tabIx == MDTable.Param))
\r
4594 lgeCIx[(int)CIx.HasFieldMarshal] = true;
\r
4595 if ((tabIx == MDTable.Event) || (tabIx == MDTable.Property))
\r
4596 lgeCIx[(int)CIx.HasSemantics] = true;
\r
4597 if ((tabIx == MDTable.Method) || (tabIx == MDTable.MemberRef))
\r
4598 lgeCIx[(int)CIx.MethodDefOrRef] = true;
\r
4599 if ((tabIx == MDTable.Field) || (tabIx == MDTable.Method))
\r
4600 lgeCIx[(int)CIx.MemberForwarded] = true;
\r
4601 if ((tabIx == MDTable.TypeDef) || (tabIx == MDTable.Method))
\r
4602 lgeCIx[(int)CIx.TypeOrMethodDef] = true;
\r
4607 if (strings.LargeIx()) {
\r
4608 largeStrings = true;
\r
4609 heapSizes |= StringsHeapMask;
\r
4611 if (guid.LargeIx()) {
\r
4613 heapSizes |= GUIDHeapMask;
\r
4615 if (blob.LargeIx()) {
\r
4617 heapSizes |= BlobHeapMask;
\r
4619 largeUS = us.LargeIx();
\r
4622 private void SetStreamOffsets() {
\r
4623 uint sizeOfHeaders = StreamHeaderSize + (uint)tildeName.Length;
\r
4624 for (int i=1; i < numStreams; i++) {
\r
4625 sizeOfHeaders += streams[i].headerSize();
\r
4627 metaDataSize = MetaDataHeaderSize + sizeOfHeaders;
\r
4628 tildeStart = metaDataSize;
\r
4629 metaDataSize += tildeTide + tildePadding;
\r
4630 for (int i=1; i < numStreams; i++) {
\r
4631 streams[i].Start = metaDataSize;
\r
4632 metaDataSize += streams[i].Size();
\r
4633 streams[i].WriteDetails();
\r
4637 internal void CalcTildeStreamSize() {
\r
4638 //tilde.SetIndexSizes(strings.LargeIx(),us.LargeIx(),guid.LargeIx(),blob.LargeIx());
\r
4639 tildeTide = TildeHeaderSize;
\r
4640 tildeTide += 4 * numTables;
\r
4641 //Console.WriteLine("Tilde header + sizes = " + tildeTide);
\r
4642 for (int i=0; i < numMetaDataTables; i++) {
\r
4643 if (metaDataTables[i] != null) {
\r
4644 ArrayList table = metaDataTables[i];
\r
4645 // Console.WriteLine("Meta data table " + i + " at offset " + tildeTide);
\r
4646 tildeTide += (uint)table.Count * ((MetaDataElement)table[0]).Size(this);
\r
4647 // Console.WriteLine("Metadata table " + i + " has size " + table.Count);
\r
4648 // Console.WriteLine("tildeTide = " + tildeTide);
\r
4651 if ((tildeTide % 4) != 0) tildePadding = 4 - (tildeTide % 4);
\r
4652 //Console.WriteLine("tildePadding = " + tildePadding);
\r
4655 internal void WriteTildeStream(FileImage output) {
\r
4656 long startTilde = output.Seek(0,SeekOrigin.Current);
\r
4657 output.Write((uint)0); // Reserved
\r
4658 output.Write((byte)1); // MajorVersion
\r
4659 output.Write((byte)0); // MinorVersion
\r
4660 output.Write(heapSizes);
\r
4661 output.Write((byte)1); // Reserved
\r
4662 output.Write(valid);
\r
4663 output.Write(sorted);
\r
4664 for (int i=0; i < numMetaDataTables; i++) {
\r
4665 if (metaDataTables[i] != null) {
\r
4666 uint count = (uint)metaDataTables[i].Count;
\r
4667 output.Write(count);
\r
4670 long tabStart = output.Seek(0,SeekOrigin.Current);
\r
4671 // Console.WriteLine("Starting metaData tables at " + tabStart);
\r
4672 for (int i=0; i < numMetaDataTables; i++) {
\r
4673 if (metaDataTables[i] != null) {
\r
4674 // Console.WriteLine("Starting metaData table " + i + " at " + (output.Seek(0,SeekOrigin.Current) - startTilde));
\r
4675 ArrayList table = metaDataTables[i];
\r
4676 for (int j=0; j < table.Count; j++) {
\r
4677 ((MetaDataElement)table[j]).Write(output);
\r
4681 // Console.WriteLine("Writing padding at " + output.Seek(0,SeekOrigin.Current));
\r
4682 for (int i=0; i < tildePadding; i++) output.Write((byte)0);
\r
4685 private void BuildTable(ArrayList table) {
\r
4686 if (table == null) return;
\r
4687 for (int j=0; j < table.Count; j++) {
\r
4688 ((MetaDataElement)table[j]).BuildTables(this);
\r
4692 internal void BuildMetaData(uint codeStartOffset) {
\r
4693 codeStart = codeStartOffset;
\r
4694 BuildTable(metaDataTables[(int)MDTable.TypeDef]);
\r
4695 BuildTable(metaDataTables[(int)MDTable.MemberRef]);
\r
4696 BuildTable(metaDataTables[(int)MDTable.GenericParam]);
\r
4697 BuildTable(metaDataTables[(int)MDTable.MethodSpec]);
\r
4698 BuildTable(metaDataTables[(int)MDTable.GenericParamConstraint]);
\r
4699 BuildTable(metaDataTables[(int)MDTable.CustomAttribute]);
\r
4700 /* for (int i=0; i < metaDataTables.Length; i++) {
\r
4701 ArrayList table = metaDataTables[i];
\r
4702 if (table != null) {
\r
4703 for (int j=0; j < table.Count; j++) {
\r
4704 ((MetaDataElement)table[j]).BuildTables(this);
\r
4710 for (int i=1; i < numStreams; i++) {
\r
4711 streams[i].EndStream();
\r
4713 CalcTildeStreamSize();
\r
4714 SetStreamOffsets();
\r
4715 byteCodePadding = NumToAlign(codeSize,4);
\r
4716 if (entryPoint != null) file.SetEntryPoint(entryPoint.Token());
\r
4719 internal void WriteByteCodes(FileImage output) {
\r
4720 for (int i=0; i < byteCodes.Count; i++) {
\r
4721 ((CILInstructions)byteCodes[i]).Write(output);
\r
4723 for (int i=0; i < byteCodePadding; i++) {
\r
4724 output.Write((byte)0);
\r
4728 internal void WriteMetaData(FileImage output) {
\r
4729 this.output = output;
\r
4730 mdStart = output.Seek(0,SeekOrigin.Current);
\r
4731 // Console.WriteLine("Writing metaData at " + Hex.Long(mdStart));
\r
4732 output.Write(MetaDataSignature);
\r
4733 output.Write((short)1); // Major Version
\r
4734 output.Write((short)1); // Minor Version ECMA = 0, PEFiles = 1
\r
4735 output.Write(0); // Reserved
\r
4736 output.Write(version.Length);
\r
4737 output.Write(version.ToCharArray()); // version string is already zero padded
\r
4738 output.Write((short)0);
\r
4739 output.Write((ushort)numStreams);
\r
4740 // write tilde header
\r
4741 output.Write(tildeStart);
\r
4742 output.Write(tildeTide + tildePadding);
\r
4743 output.Write(tildeName);
\r
4744 for (int i=1; i < numStreams; i++) streams[i].WriteHeader(output);
\r
4745 // Console.WriteLine("Writing tilde stream at " + output.Seek(0,SeekOrigin.Current) + " = " + tildeStart);
\r
4746 WriteTildeStream(output);
\r
4747 for (int i=1; i < numStreams; i++) streams[i].Write(output);
\r
4748 // Console.WriteLine("Finished Writing metaData at " + output.Seek(0,SeekOrigin.Current));
\r
4751 internal bool LargeStringsIndex() { return strings.LargeIx(); }
\r
4752 internal bool LargeGUIDIndex() { return guid.LargeIx(); }
\r
4753 internal bool LargeUSIndex() { return us.LargeIx(); }
\r
4754 internal bool LargeBlobIndex() { return blob.LargeIx(); }
\r
4756 internal bool LargeIx(MDTable tabIx) { return largeIx[(uint)tabIx]; }
\r
4759 private uint NumToAlign(uint val, uint alignVal) {
\r
4760 if ((val % alignVal) == 0) return 0;
\r
4761 return alignVal - (val % alignVal);
\r
4764 internal void WriteCodedIndex(CIx code, MetaDataElement elem, FileImage output) {
\r
4766 if (elem != null) {
\r
4767 ix = (elem.Row << CIxShiftMap[(uint)code]) | elem.GetCodedIx(code);
\r
4768 // Console.WriteLine("coded index = " + ix + " row = " + elem.Row);
\r
4770 // Console.WriteLine("elem for coded index is null");
\r
4772 if (lgeCIx[(uint)code])
\r
4775 output.Write((ushort)ix);
\r
4779 /**************************************************************************/
\r
4781 /// Base class for all Meta Data table elements
\r
4784 public abstract class MetaDataElement
\r
4787 protected ArrayList customAttributes;
\r
4788 private uint row = 0;
\r
4789 protected bool done = false;
\r
4790 protected MDTable tabIx;
\r
4792 internal MetaDataElement() { }
\r
4799 if (row == 0) row = value;
\r
4803 internal virtual uint GetCodedIx(CIx code) { return 0; }
\r
4806 /// Add a custom attribute to this item
\r
4808 /// <param name="ctorMeth">the constructor method for this attribute</param>
\r
4809 /// <param name="val">the byte value of the parameters</param>
\r
4810 public void AddCustomAttribute(Method ctorMeth, byte[] val) {
\r
4811 if (customAttributes == null) {
\r
4812 customAttributes = new ArrayList();
\r
4814 customAttributes.Add(new CustomAttribute(this,ctorMeth,val));
\r
4818 /// Add a custom attribute to this item
\r
4820 /// <param name="ctorMeth">the constructor method for this attribute</param>
\r
4821 /// <param name="val">the constant values of the parameters</param>
\r
4822 public void AddCustomAttribute(Method ctorMeth, Constant[] cVals) {
\r
4823 if (customAttributes == null) {
\r
4824 customAttributes = new ArrayList();
\r
4826 // customAttributes.Add(new CustomAttribute(this,ctorMeth,cVals));
\r
4829 internal void DoCustomAttributes(MetaData md) {
\r
4830 if (customAttributes != null) {
\r
4831 for (int i=0; i < customAttributes.Count; i++) {
\r
4832 CustomAttribute ca = (CustomAttribute)customAttributes[i];
\r
4833 ca.BuildTables(md);
\r
4838 internal uint Token() {
\r
4839 return (((uint)tabIx << 24) | row);
\r
4842 internal virtual void BuildTables(MetaData md) {
\r
4846 internal virtual uint Size(MetaData md) {
\r
4850 internal virtual void Write(FileImage output) { }
\r
4853 /**************************************************************************/
\r
4855 /// Stream in the Meta Data (#Strings, #US, #Blob and #GUID)
\r
4858 internal class MetaDataStream : BinaryWriter
\r
4860 private static readonly uint StreamHeaderSize = 8;
\r
4861 private static uint maxSmlIxSize = 0xFFFF;
\r
4863 private uint start = 0;
\r
4864 uint size = 0, tide = 1;
\r
4865 bool largeIx = false;
\r
4866 uint sizeOfHeader;
\r
4868 Hashtable htable = new Hashtable();
\r
4870 internal MetaDataStream(char[] name, bool addInitByte) : base(new MemoryStream()) {
\r
4871 if (addInitByte) { Write((byte)0); size = 1; }
\r
4873 sizeOfHeader = StreamHeaderSize + (uint)name.Length;
\r
4876 internal MetaDataStream(char[] name, System.Text.Encoding enc, bool addInitByte) : base(new MemoryStream(),enc) {
\r
4877 if (addInitByte) { Write((byte)0); size = 1; }
\r
4879 sizeOfHeader = StreamHeaderSize + (uint)name.Length;
\r
4882 public uint Start {
\r
4891 internal uint headerSize() {
\r
4892 // Console.WriteLine(name + " stream has headersize of " + sizeOfHeader);
\r
4893 return sizeOfHeader;
\r
4896 internal void SetSize(uint siz) {
\r
4900 internal uint Size() {
\r
4904 internal bool LargeIx() {
\r
4908 internal void WriteDetails() {
\r
4909 // Console.WriteLine(name + " - size = " + size);
\r
4912 internal uint Add(string str, bool prependSize) {
\r
4913 Object val = htable[str];
\r
4915 if (val == null) {
\r
4917 htable[str] = index;
\r
4918 char[] arr = str.ToCharArray();
\r
4919 if (prependSize) CompressNum((uint)arr.Length*2+1);
\r
4922 size = (uint)Seek(0,SeekOrigin.Current);
\r
4924 index = (uint)val;
\r
4929 internal uint Add(Guid guid) {
\r
4930 Write(guid.ToByteArray());
\r
4931 size =(uint)Seek(0,SeekOrigin.Current);
\r
4935 internal uint Add(byte[] blob) {
\r
4937 CompressNum((uint)blob.Length);
\r
4939 size = (uint)Seek(0,SeekOrigin.Current);
\r
4943 internal uint Add(byte val) {
\r
4946 size = (uint)Seek(0,SeekOrigin.Current);
\r
4950 internal uint Add(sbyte val) {
\r
4953 size = (uint)Seek(0,SeekOrigin.Current);
\r
4957 internal uint Add(ushort val) {
\r
4960 size = (uint)Seek(0,SeekOrigin.Current);
\r
4964 internal uint Add(short val) {
\r
4967 size = (uint)Seek(0,SeekOrigin.Current);
\r
4971 internal uint Add(uint val) {
\r
4974 size = (uint)Seek(0,SeekOrigin.Current);
\r
4978 internal uint Add(int val) {
\r
4981 size = (uint)Seek(0,SeekOrigin.Current);
\r
4985 internal uint Add(ulong val) {
\r
4988 size = (uint)Seek(0,SeekOrigin.Current);
\r
4992 internal uint Add(long val) {
\r
4995 size = (uint)Seek(0,SeekOrigin.Current);
\r
4999 internal uint Add(float val) {
\r
5002 size = (uint)Seek(0,SeekOrigin.Current);
\r
5006 internal uint Add(double val) {
\r
5009 size = (uint)Seek(0,SeekOrigin.Current);
\r
5013 private void CompressNum(uint val) {
\r
5016 } else if (val < 0x3FFF) {
\r
5017 byte b1 = (byte)((val >> 8) | 0x80);
\r
5018 byte b2 = (byte)(val & FileImage.iByteMask[0]);
\r
5022 byte b1 = (byte)((val >> 24) | 0xC0);
\r
5023 byte b2 = (byte)((val & FileImage.iByteMask[2]) >> 16);
\r
5024 byte b3 = (byte)((val & FileImage.iByteMask[1]) >> 8);;
\r
5025 byte b4 = (byte)(val & FileImage.iByteMask[0]);
\r
5033 private void QuadAlign() {
\r
5034 if ((size % 4) != 0) {
\r
5035 uint pad = 4 - (size % 4);
\r
5037 for (int i=0; i < pad; i++) {
\r
5043 internal void EndStream() {
\r
5045 if (size > maxSmlIxSize) {
\r
5050 internal void WriteHeader(BinaryWriter output) {
\r
5051 output.Write(start);
\r
5052 output.Write(size);
\r
5053 output.Write(name);
\r
5056 internal virtual void Write(BinaryWriter output) {
\r
5057 // Console.WriteLine("Writing " + name + " stream at " + output.Seek(0,SeekOrigin.Current) + " = " + start);
\r
5058 MemoryStream str = (MemoryStream)BaseStream;
\r
5059 output.Write(str.ToArray());
\r
5063 /**************************************************************************/
\r
5065 /// Base class for Method Descriptors
\r
5068 public abstract class Method : Member
\r
5070 protected CallConv callConv = CallConv.Default;
\r
5071 protected Type retType;
\r
5073 internal Method(string methName, Type rType) : base(methName)
\r
5079 /// Add calling conventions to this method descriptor
\r
5081 /// <param name="cconv"></param>
\r
5082 public void AddCallConv(CallConv cconv) {
\r
5083 callConv |= cconv;
\r
5086 internal abstract void TypeSig(MemoryStream sig);
\r
5088 internal uint GetSigIx(MetaData md) {
\r
5089 MemoryStream sig = new MemoryStream();
\r
5091 return md.AddToBlobHeap(sig.ToArray());
\r
5094 internal Type GetRetType() {
\r
5099 /**************************************************************************/
\r
5101 /// Descriptor for a method defined in THIS assembly/module
\r
5105 public class MethodDef : Method
\r
5107 private static readonly ushort PInvokeImpl = 0x2000;
\r
5108 //private static readonly uint UnmanagedExport = 0x0008;
\r
5109 // private static readonly byte LocalSigByte = 0x7;
\r
5110 uint parIx = 0, textOffset = 0;
\r
5112 MetaData metaData;
\r
5113 CILInstructions code;
\r
5114 ArrayList securityActions = new ArrayList();
\r
5118 ushort methFlags = 0, implFlags = 0;
\r
5119 int maxStack = 0, numPars = 0;
\r
5120 bool entryPoint = false;
\r
5121 LocalSig localSig;
\r
5122 ArrayList varArgSigList;
\r
5123 ImplMap pinvokeImpl;
\r
5126 internal MethodDef(MetaData md, string name, Type retType, Param[] pars) : base(name,retType) {
\r
5129 if (parList != null) numPars = parList.Length;
\r
5130 tabIx = MDTable.Method;
\r
5133 internal MethodDef(MetaData md, MethAttr mAttrSet, ImplAttr iAttrSet, string name, Type retType, Param[] pars) : base(name,retType) {
\r
5136 if (parList != null) numPars = parList.Length;
\r
5137 // Console.WriteLine("Creating method " + name + " with " + numPars + " parameters");
\r
5138 methFlags = (ushort)mAttrSet;
\r
5139 implFlags = (ushort)iAttrSet;
\r
5140 tabIx = MDTable.Method;
\r
5143 internal Param[] GetPars() {
\r
5148 /// Add some attributes to this method descriptor
\r
5150 /// <param name="ma">the attributes to be added</param>
\r
5151 public void AddMethAttribute(MethAttr ma) {
\r
5152 methFlags |= (ushort)ma;
\r
5156 /// Add some implementation attributes to this method descriptor
\r
5158 /// <param name="ia">the attributes to be added</param>
\r
5159 public void AddImplAttribute(ImplAttr ia) {
\r
5160 implFlags |= (ushort)ia;
\r
5163 public void AddPInvokeInfo(ModuleRef scope, string methName,
\r
5164 PInvokeAttr callAttr) {
\r
5165 pinvokeImpl = new ImplMap((ushort)callAttr,this,methName,scope);
\r
5166 methFlags |= PInvokeImpl;
\r
5170 /// Add a named generic type parameter
\r
5172 public GenericParameter AddGenericParameter (short index, string name) {
\r
5173 GenericParameter gp = new GenericParameter (this, metaData, index, name);
5174 metaData.AddToTable (MDTable.GenericParam, gp);
\r
5179 /// Set the maximum stack height for this method
\r
5181 /// <param name="maxStack">the maximum height of the stack</param>
\r
5182 public void SetMaxStack(int maxStack) {
\r
5183 this.maxStack = maxStack;
\r
5187 /// Add local variables to this method
\r
5189 /// <param name="locals">the locals to be added</param>
\r
5190 /// <param name="initLocals">are locals initialised to default values</param>
\r
5191 public void AddLocals(Local[] locals, bool initLocals) {
\r
5192 this.locals = locals;
\r
5193 this.initLocals = initLocals;
\r
5197 /// Mark this method as having an entry point
\r
5199 public void DeclareEntryPoint() {
\r
5200 entryPoint = true;
\r
5204 /// Create a code buffer for this method to add the IL instructions to
\r
5206 /// <returns>a buffer for this method's IL instructions</returns>
\r
5207 public CILInstructions CreateCodeBuffer() {
\r
5208 code = new CILInstructions(metaData);
\r
5213 /// Make a method reference descriptor for this method to be used
\r
5214 /// as a callsite signature for this vararg method
\r
5216 /// <param name="optPars">the optional pars for the vararg method call</param>
\r
5217 /// <returns></returns>
\r
5218 public MethodRef MakeVarArgSignature(Type[] optPars) {
\r
5219 Type[] pars = new Type[numPars];
\r
5220 MethodRef varArgSig;
\r
5221 for (int i=0; i < numPars; i++) {
\r
5222 pars[i] = parList[i].GetParType();
\r
5224 varArgSig = new MethodRef(this,name,retType,pars,true,optPars);
\r
5226 if (varArgSigList == null)
\r
5227 varArgSigList = new ArrayList ();
\r
5228 varArgSigList.Add (varArgSig);
\r
5232 internal sealed override void TypeSig(MemoryStream sig) {
\r
5233 sig.WriteByte((byte)callConv);
\r
5234 MetaData.CompressNum((uint)numPars,sig);
\r
5235 retType.TypeSig(sig);
\r
5236 for (ushort i=0; i < numPars; i++) {
\r
5237 parList[i].seqNo = (ushort)(i+1);
\r
5238 parList[i].TypeSig(sig);
\r
5242 internal sealed override void BuildTables(MetaData md) {
\r
5244 if (pinvokeImpl != null) {
\r
5245 md.AddToTable(MDTable.ImplMap,pinvokeImpl);
\r
5246 pinvokeImpl.BuildTables(md);
\r
5248 if (entryPoint) md.SetEntryPoint(this);
\r
5249 uint locToken = 0;
\r
5250 if (locals != null) {
\r
5251 localSig = new LocalSig(locals);
\r
5252 md.AddToTable(MDTable.StandAloneSig,localSig);
\r
5253 localSig.BuildTables(md);
\r
5254 locToken = localSig.Token();
\r
5256 if (code != null) {
\r
5257 code.CheckCode(locToken,initLocals,maxStack);
\r
5258 textOffset = md.AddCode(code);
\r
5260 nameIx = md.AddToStringsHeap(name);
\r
5261 sigIx = GetSigIx(md);
\r
5262 parIx = md.TableIndex(MDTable.Param);
\r
5263 for (int i=0; i < numPars; i++) {
\r
5264 md.AddToTable(MDTable.Param,parList[i]);
\r
5265 parList[i].BuildTables(md);
\r
5267 if (varArgSigList != null) {
\r
5268 foreach (MethodRef varArgSig in varArgSigList) {
\r
5269 md.AddToTable(MDTable.MemberRef,varArgSig);
\r
5270 varArgSig.BuildTables(md);
\r
5273 DoCustomAttributes (md);
\r
5274 // Console.WriteLine("method has " + numPars + " parameters");
\r
5278 internal sealed override uint Size(MetaData md) {
\r
5279 return 8 + md.StringsIndexSize() + md.BlobIndexSize() + md.TableIndexSize(MDTable.Param);
\r
5282 internal sealed override void Write(FileImage output) {
\r
5283 if (ZeroRva ()) output.Write(0);
\r
5284 else output.WriteCodeRVA(textOffset);
\r
5285 output.Write(implFlags);
\r
5286 output.Write(methFlags);
\r
5287 output.StringsIndex(nameIx);
\r
5288 output.BlobIndex(sigIx);
\r
5289 output.WriteIndex(MDTable.Param,parIx);
\r
5292 internal bool ZeroRva () {
5293 return (((methFlags & (ushort)MethAttr.Abstract) != 0) ||
5294 (pinvokeImpl != null)); // TODO: Not entirely true but works for now
5297 internal sealed override uint GetCodedIx(CIx code) {
\r
5299 case (CIx.HasCustomAttr) : return 0;
\r
5300 case (CIx.HasDeclSecurity) : return 1;
\r
5301 case (CIx.MemberRefParent) : return 3;
\r
5302 case (CIx.MethodDefOrRef) : return 0;
\r
5303 case (CIx.MemberForwarded) : return 1;
\r
5304 case (CIx.CustomAttributeType) : return 2;
\r
5305 case (CIx.TypeOrMethodDef) : return 1;
\r
5311 /**************************************************************************/
\r
5313 /// Descriptor for an overriding method (.override)
\r
5315 public class MethodImpl : MetaDataElement
\r
5318 Method header, body;
\r
5320 internal MethodImpl(ClassDef par, Method decl, Method bod) {
\r
5324 tabIx = MDTable.MethodImpl;
\r
5327 internal sealed override uint Size(MetaData md) {
\r
5328 return md.TableIndexSize(MDTable.TypeDef) + 2 * md.CodedIndexSize(CIx.MethodDefOrRef);
\r
5331 internal sealed override void Write(FileImage output) {
\r
5332 output.WriteIndex(MDTable.TypeDef,parent.Row);
\r
5333 output.WriteCodedIndex(CIx.MethodDefOrRef,body);
\r
5334 output.WriteCodedIndex(CIx.MethodDefOrRef,header);
\r
5338 /**************************************************************************/
\r
5340 /// Descriptor for a method defined in another assembly/module
\r
5342 public class MethodRef : Method
\r
5344 private static readonly byte Sentinel = 0x41;
\r
5345 Type[] parList, optParList;
\r
5346 MetaDataElement parent;
\r
5347 uint numPars = 0, numOptPars = 0;
\r
5349 internal MethodRef(MetaDataElement paren, string name, Type retType,
\r
5350 Type[] pars, bool varArgMeth, Type[] optPars) : base(name,retType) {
\r
5353 if (parList != null) numPars = (uint)parList.Length;
\r
5355 optParList = optPars;
\r
5356 if (optParList != null) numOptPars = (uint)optParList.Length;
\r
5357 callConv = CallConv.Vararg;
\r
5361 internal sealed override void TypeSig(MemoryStream sig) {
\r
5362 sig.WriteByte((byte)callConv);
\r
5363 MetaData.CompressNum(numPars+numOptPars,sig);
\r
5364 retType.TypeSig(sig);
\r
5365 for (int i=0; i < numPars; i++) {
\r
5366 parList[i].TypeSig(sig);
\r
5368 if (numOptPars > 0) {
\r
5369 sig.WriteByte(Sentinel);
\r
5370 for (int i=0; i < numOptPars; i++) {
\r
5371 optParList[i].TypeSig(sig);
\r
5376 internal sealed override void BuildTables(MetaData md) {
\r
5378 nameIx = md.AddToStringsHeap(name);
\r
5379 sigIx = GetSigIx(md);
\r
5383 internal sealed override uint Size(MetaData md) {
\r
5384 return md.CodedIndexSize(CIx.MemberRefParent) + md.StringsIndexSize() + md.BlobIndexSize();
\r
5387 internal sealed override void Write(FileImage output) {
\r
5388 output.WriteCodedIndex(CIx.MemberRefParent,parent);
\r
5389 output.StringsIndex(nameIx);
\r
5390 output.BlobIndex(sigIx);
\r
5393 internal sealed override uint GetCodedIx(CIx code) {
\r
5395 case (CIx.HasCustomAttr) : return 6;
\r
5396 case (CIx.MethodDefOrRef) : return 1;
\r
5397 case (CIx.CustomAttributeType) : return 3;
\r
5403 /**************************************************************************/
\r
5405 /// Descriptor for Property and Event methods
\r
5407 public class MethodSemantics : MetaDataElement {
\r
5409 Feature.MethodType type;
\r
5411 Feature eventOrProp;
\r
5413 internal MethodSemantics(Feature.MethodType mType, MethodDef method, Feature feature) {
\r
5416 eventOrProp = feature;
\r
5417 tabIx = MDTable.MethodSemantics;
\r
5420 internal sealed override uint Size(MetaData md) {
\r
5421 return 2 + md.TableIndexSize(MDTable.Method) + md.CodedIndexSize(CIx.HasSemantics);
\r
5424 internal sealed override void Write(FileImage output) {
\r
5425 output.Write((ushort)type);
\r
5426 output.WriteIndex(MDTable.Method,meth.Row);
\r
5427 output.WriteCodedIndex(CIx.HasSemantics,eventOrProp);
\r
5431 /**************************************************************************/
\r
5433 /// Descriptor for a FunctionPointer type
\r
5436 public class MethPtrType : Type
\r
5438 // MethPtrType == FNPTR
\r
5443 /// Create a new function pointer type
\r
5445 /// <param name="meth">the function to be referenced</param>
\r
5446 public MethPtrType(Method meth) : base(0x1B)
\r
5449 tabIx = MDTable.TypeSpec;
\r
5452 internal sealed override void TypeSig(MemoryStream str) {
\r
5453 str.WriteByte(typeIndex);
\r
5454 method.TypeSig(str);
\r
5457 internal sealed override void BuildTables(MetaData md) {
\r
5459 MemoryStream sig = new MemoryStream();
\r
5461 sigIx = md.AddToBlobHeap(sig.ToArray());
\r
5465 internal sealed override uint Size(MetaData md) {
\r
5466 return md.BlobIndexSize();
\r
5469 internal sealed override void Write(FileImage output) {
\r
5470 output.BlobIndex(sigIx);
\r
5473 internal sealed override uint GetCodedIx(CIx code) { return 0x1B; }
\r
5476 /**************************************************************************/
\r
5478 /// Descriptor for THIS module
\r
5480 public class Module : ResolutionScope
\r
5485 internal Module(string name, MetaData md) : base(name,md) {
\r
5486 mvid = Guid.NewGuid();
\r
5487 mvidIx = md.AddToGUIDHeap(mvid);
\r
5488 tabIx = MDTable.Module;
\r
5491 internal sealed override uint Size(MetaData md) {
\r
5492 return 2 + md.StringsIndexSize() + 3 * md.GUIDIndexSize();
\r
5495 internal sealed override void Write(FileImage output) {
\r
5496 output.Write((short)0);
\r
5497 output.StringsIndex(nameIx);
\r
5498 output.GUIDIndex(mvidIx);
\r
5499 output.GUIDIndex(0);
\r
5500 output.GUIDIndex(0);
\r
5503 internal sealed override uint GetCodedIx(CIx code) {
\r
5505 case (CIx.HasCustomAttr) : return 7;
\r
5506 case (CIx.ResolutionScope) : return 0;
\r
5512 /**************************************************************************/
\r
5514 /// Descriptor for another module in THIS assembly
\r
5516 public class ModuleRef : ResolutionScope
\r
5519 internal ModuleRef(MetaData md, string name) : base(name,md) {
\r
5520 tabIx = MDTable.ModuleRef;
\r
5524 /// Add a class to this external module. This is a class declared in
\r
5525 /// another module of THIS assembly.
\r
5527 /// <param name="nsName">name space name</param>
\r
5528 /// <param name="name">class name</param>
\r
5529 /// <returns>a descriptor for this class in another module</returns>
\r
5530 public ClassRef AddClass(string nsName, string name, bool exportClass) {
\r
5531 ClassRef aClass = new ClassRef(nsName,name,metaData);
\r
5532 metaData.AddToTable(MDTable.TypeRef,aClass);
\r
5533 aClass.SetParent(this);
\r
5538 /// Make a file descriptor to correspond to this module. The file
\r
5539 /// descriptor will have the same name as the module descriptor
\r
5541 /// <param name="hashBytes">the hash of the file</param>
\r
5542 /// <param name="hasMetaData">the file contains metadata</param>
\r
5543 /// <param name="entryPoint">the program entry point is in this file</param>
\r
5544 /// <returns>a descriptor for the file which contains this module</returns>
\r
5545 public FileRef MakeFile(byte[] hashBytes, bool hasMetaData, bool entryPoint) {
\r
5546 FileRef file = new FileRef(nameIx,hashBytes,hasMetaData,entryPoint,metaData);
\r
5547 metaData.AddToTable(MDTable.File,file);
\r
5552 /// Add a value class to this module. This is a class declared in
\r
5553 /// another module of THIS assembly.
\r
5555 /// <param name="nsName">name space name</param>
\r
5556 /// <param name="name">class name</param>
\r
5557 /// <returns></returns>
\r
5558 public ClassRef AddValueClass(string nsName, string name) {
\r
5559 ClassRef aClass = new ClassRef(nsName,name,metaData);
\r
5560 metaData.AddToTable(MDTable.TypeRef,aClass);
\r
5561 aClass.SetParent(this);
\r
5562 aClass.MakeValueClass();
\r
5567 /// Add a class which is declared public in this external module of
\r
5568 /// THIS assembly. This class will be exported from this assembly.
\r
5569 /// The ilasm syntax for this is .extern class
\r
5571 /// <param name="attrSet">attributes of the class to be exported</param>
\r
5572 /// <param name="nsName">name space name</param>
\r
5573 /// <param name="name">external class name</param>
\r
5574 /// <param name="declFile">the file where the class is declared</param>
\r
5575 /// <param name="isValueClass">is this class a value type?</param>
\r
5576 /// <returns>a descriptor for this external class</returns>
\r
5577 public ExternClassRef AddExternClass(TypeAttr attrSet, string nsName,
\r
5578 string name, FileRef declFile,
\r
5579 bool isValueClass) {
\r
5580 ExternClassRef cRef = new ExternClassRef(attrSet,nsName,name,declFile,metaData);
\r
5581 metaData.AddToTable(MDTable.TypeRef,cRef);
\r
5582 cRef.SetParent(this);
\r
5583 if (isValueClass) cRef.MakeValueClass();
\r
5588 /// Add a "global" method in another module
\r
5590 /// <param name="name">method name</param>
\r
5591 /// <param name="retType">return type</param>
\r
5592 /// <param name="pars">method parameter types</param>
\r
5593 /// <returns>a descriptor for this method in anther module</returns>
\r
5594 public MethodRef AddMethod(string name, Type retType, Type[] pars) {
\r
5595 MethodRef meth = new MethodRef(this,name,retType,pars,false,null);
\r
5596 metaData.AddToTable(MDTable.MemberRef,meth);
\r
5601 /// Add a vararg method to this class
\r
5603 /// <param name="name">method name</param>
\r
5604 /// <param name="retType">return type</param>
\r
5605 /// <param name="pars">parameter types</param>
\r
5606 /// <param name="optPars">optional param types for this vararg method</param>
\r
5607 /// <returns>a descriptor for this method</returns>
\r
5608 public MethodRef AddVarArgMethod(string name, Type retType,
\r
5609 Type[] pars, Type[] optPars) {
\r
5610 MethodRef meth = new MethodRef(this,name,retType,pars,true,optPars);
\r
5611 metaData.AddToTable(MDTable.MemberRef,meth);
\r
5616 /// Add a field in another module
\r
5618 /// <param name="name">field name</param>
\r
5619 /// <param name="fType">field type</param>
\r
5620 /// <returns>a descriptor for this field in another module</returns>
\r
5621 public FieldRef AddField(string name, Type fType) {
\r
5622 FieldRef field = new FieldRef(this,name,fType);
\r
5623 metaData.AddToTable(MDTable.MemberRef,field);
\r
5627 internal sealed override uint Size(MetaData md) {
\r
5628 return md.StringsIndexSize();
\r
5631 internal sealed override void Write(FileImage output) {
\r
5632 output.StringsIndex(nameIx);
\r
5635 internal sealed override uint GetCodedIx(CIx code) {
\r
5637 case (CIx.HasCustomAttr) : return 12;
\r
5638 case (CIx.MemberRefParent) : return 2;
\r
5639 case (CIx.ResolutionScope) : return 1;
\r
5645 /**************************************************************************/
\r
5647 /// Descriptors for native types used for marshalling
\r
5649 public class NativeType {
\r
5650 public static readonly NativeType Void = new NativeType(0x01);
\r
5651 public static readonly NativeType Boolean = new NativeType(0x02);
\r
5652 public static readonly NativeType Int8 = new NativeType(0x03);
\r
5653 public static readonly NativeType UInt8 = new NativeType(0x04);
\r
5654 public static readonly NativeType Int16 = new NativeType(0x05);
\r
5655 public static readonly NativeType UInt16 = new NativeType(0x06);
\r
5656 public static readonly NativeType Int32 = new NativeType(0x07);
\r
5657 public static readonly NativeType UInt32 = new NativeType(0x08);
\r
5658 public static readonly NativeType Int64 = new NativeType(0x09);
\r
5659 public static readonly NativeType UInt64 = new NativeType(0x0A);
\r
5660 public static readonly NativeType Float32 = new NativeType(0x0B);
\r
5661 public static readonly NativeType Float64 = new NativeType(0x0C);
\r
5662 public static readonly NativeType Currency = new NativeType(0x0F);
\r
5663 public static readonly NativeType BStr = new NativeType(0x13);
\r
5664 public static readonly NativeType LPStr = new NativeType(0x14);
\r
5665 public static readonly NativeType LPWStr = new NativeType(0x15);
\r
5666 public static readonly NativeType LPTStr = new NativeType(0x16);
\r
5667 public static readonly NativeType FixedSysString = new NativeType(0x17);
\r
5668 public static readonly NativeType IUnknown = new NativeType(0x19);
\r
5669 public static readonly NativeType IDispatch = new NativeType(0x1A);
\r
5670 public static readonly NativeType Struct = new NativeType(0x1B);
\r
5671 public static readonly NativeType Interface = new NativeType(0x1C);
\r
5672 public static readonly NativeType Int = new NativeType(0x1F);
\r
5673 public static readonly NativeType UInt = new NativeType(0x20);
\r
5674 public static readonly NativeType ByValStr = new NativeType(0x22);
\r
5675 public static readonly NativeType AnsiBStr = new NativeType(0x23);
\r
5676 public static readonly NativeType TBstr = new NativeType(0x24);
\r
5677 public static readonly NativeType VariantBool = new NativeType(0x25);
\r
5678 public static readonly NativeType FuncPtr = new NativeType(0x26);
\r
5679 public static readonly NativeType AsAny = new NativeType(0x28);
\r
5681 protected byte typeIndex;
\r
5683 internal NativeType(byte tyIx) { typeIndex = tyIx; }
\r
5685 internal byte GetTypeIndex() { return typeIndex; }
\r
5687 internal virtual byte[] ToBlob() {
\r
5688 byte[] bytes = new byte[1];
\r
5689 bytes[0] = GetTypeIndex();
\r
5695 public class NativeArray : NativeType
\r
5697 NativeType elemType;
\r
5698 uint len = 0, parNum = 0;
\r
5701 public NativeArray(NativeType elemType) : base(0x2A) {
\r
5702 this.elemType = elemType;
\r
5705 public NativeArray(NativeType elemType, int len) : base(0x2A) {
\r
5706 this.elemType = elemType;
\r
5710 public NativeArray(NativeType elemType, int numElem, int parNumForLen) : base(0x2A) {
\r
5711 this.elemType = elemType;
\r
5712 len = (uint)numElem;
\r
5713 parNum = (uint)parNumForLen;
\r
5716 internal override byte[] ToBlob() {
\r
5717 MemoryStream str = new MemoryStream();
\r
5718 str.WriteByte(GetTypeIndex());
\r
5719 if (elemType == null) str.WriteByte(0x50); // no info (MAX)
\r
5720 else str.WriteByte(elemType.GetTypeIndex());
\r
5721 MetaData.CompressNum(parNum,str);
\r
5723 MetaData.CompressNum(len,str);
\r
5724 return str.ToArray();
\r
5729 public class SafeArray : NativeType
\r
5731 SafeArrayType elemType;
\r
5733 public SafeArray(SafeArrayType elemType) : base(0x1D) {
\r
5734 this.elemType = elemType;
\r
5737 internal override byte[] ToBlob() {
\r
5738 byte[] bytes = new byte[2];
\r
5739 bytes[0] = GetTypeIndex();
\r
5740 bytes[1] = (byte)elemType;
\r
5746 public class FixedArray : NativeType
\r
5748 NativeType elemType;
\r
5751 public FixedArray(NativeType elemType, int numElems) : base(0x1E) {
\r
5752 this.elemType = elemType;
\r
5753 numElem = (uint)numElems;
\r
5756 internal override byte[] ToBlob() {
\r
5757 MemoryStream str = new MemoryStream();
\r
5758 str.WriteByte(GetTypeIndex());
\r
5759 MetaData.CompressNum(numElem,str);
\r
5760 if (elemType == null) str.WriteByte(0x50); // no info (MAX)
\r
5761 else str.WriteByte(elemType.GetTypeIndex());
\r
5762 return str.ToArray();
\r
5767 public class CustomMarshaller : NativeType
\r
5770 string marshallerName;
\r
5773 public CustomMarshaller(string typeNameOrGUID, string marshallerName,
\r
5774 string optCookie) : base(0x2C) {
\r
5775 typeName = typeNameOrGUID;
\r
5776 this.marshallerName = marshallerName;
\r
5777 cookie = optCookie;
\r
5780 internal override byte[] ToBlob() {
\r
5781 MemoryStream str = new MemoryStream();
\r
5782 BinaryWriter bw = new BinaryWriter(str,new UTF8Encoding());
\r
5783 bw.Write(GetTypeIndex());
\r
5784 bw.Write(typeName.ToCharArray());
\r
5785 bw.Write((byte)0);
\r
5786 bw.Write(marshallerName.ToCharArray());
\r
5787 bw.Write((byte)0);
\r
5788 if (cookie != null) bw.Write(cookie.ToCharArray());
\r
5789 bw.Write((byte)0);
\r
5791 return str.ToArray();
\r
5795 /**************************************************************************/
\r
5797 /// Descriptor for a parameter of a method defined in this assembly/module
\r
5799 public class Param : MetaDataElement
\r
5801 private static readonly ushort hasDefault = 0x1000;
\r
5802 private static readonly ushort hasFieldMarshal = 0x2000;
\r
5806 internal ushort seqNo = 0;
\r
5808 ConstantElem defaultVal;
\r
5810 FieldMarshal marshalInfo;
\r
5813 /// Create a new parameter for a method
\r
5815 /// <param name="mode">param mode (in, out, opt)</param>
\r
5816 /// <param name="parName">parameter name</param>
\r
5817 /// <param name="parType">parameter type</param>
\r
5818 public Param(ParamAttr mode, string parName, Type parType) {
\r
5821 parMode = (ushort)mode;
\r
5822 tabIx = MDTable.Param;
\r
5826 /// Add a default value to this parameter
\r
5828 /// <param name="c">the default value for the parameter</param>
\r
5829 public void AddDefaultValue(Constant cVal) {
\r
5830 defaultVal = new ConstantElem(this,cVal);
\r
5831 parMode |= hasDefault;
\r
5835 /// Add marshalling information about this parameter
\r
5837 public void AddMarshallInfo(NativeType marshallType) {
\r
5838 parMode |= hasFieldMarshal;
\r
5839 marshalInfo = new FieldMarshal(this,marshallType);
\r
5842 internal Type GetParType() { return pType; }
\r
5844 internal sealed override void BuildTables(MetaData md) {
\r
5846 nameIx = md.AddToStringsHeap(pName);
\r
5847 if (defaultVal != null) {
\r
5848 md.AddToTable(MDTable.Constant,defaultVal);
\r
5849 defaultVal.BuildTables(md);
\r
5851 if (marshalInfo != null) {
\r
5852 md.AddToTable(MDTable.FieldMarshal,marshalInfo);
\r
5853 marshalInfo.BuildTables(md);
\r
5858 internal void TypeSig(MemoryStream str) {
\r
5859 pType.TypeSig(str);
\r
5862 internal sealed override uint Size(MetaData md) {
\r
5863 return 4 + md.StringsIndexSize();
\r
5866 internal sealed override void Write(FileImage output) {
\r
5867 output.Write(parMode);
\r
5868 output.Write(seqNo);
\r
5869 output.StringsIndex(nameIx);
\r
5872 internal sealed override uint GetCodedIx(CIx code) {
\r
5874 case (CIx.HasCustomAttr) : return 4;
\r
5875 case (CIx.HasConst) : return 1;
\r
5876 case (CIx.HasFieldMarshal) : return 1;
\r
5882 /**************************************************************************/
\r
5884 /// Base class for the PEFile (starting point)
\r
5886 public class PEFile
\r
5888 private static readonly string mscorlibName = "mscorlib";
\r
5889 private Module thisMod;
\r
5890 private ClassDef moduleClass;
\r
5891 private ArrayList classRefList = new ArrayList();
\r
5892 private ArrayList classDefList = new ArrayList();
\r
5893 private Assembly thisAssembly;
\r
5894 private int corFlags = 1;
\r
5895 FileImage fileImage;
\r
5896 MetaData metaData;
\r
5899 /// Create a new PEFile. Each PEFile is a module.
\r
5901 /// <param name="name">module name, also used for the file name</param>
\r
5902 /// <param name="isDLL">create a .dll or .exe file</param>
\r
5903 /// <param name="hasAssembly">this file is an assembly and
\r
5904 /// will contain the assembly manifest. The assembly name is the
\r
5905 /// same as the module name</param>
\r
5906 public PEFile(string name, bool isDLL, bool hasAssembly) {
\r
5907 // Console.WriteLine(Hex.Byte(0x12));
\r
5908 // Console.WriteLine(Hex.Short(0x1234));
\r
5909 // Console.WriteLine(Hex.Int(0x12345678));
\r
5910 string fName = MakeFileName(null,name,isDLL);
\r
5911 fileImage = new FileImage(isDLL,fName);
\r
5912 InitPEFile(name, fName, hasAssembly);
\r
5916 /// Create a new PEFile. Each PEFile is a module.
\r
5918 /// <param name="name">module name, also used for the file name</param>
\r
5919 /// <param name="isDLL">create a .dll or .exe file</param>
\r
5920 /// <param name="hasAssembly">this file is an assembly and
\r
5921 /// will contain the assembly manifest. The assembly name is the
\r
5922 /// same as the module name</param>
\r
5923 /// <param name="outputDir">write the PEFile to this directory. If this
\r
5924 /// string is null then the output will be to the current directory</param>
\r
5925 public PEFile(string name, bool isDLL, bool hasAssembly, string outputDir) {
\r
5926 // Console.WriteLine(Hex.Byte(0x12));
\r
5927 // Console.WriteLine(Hex.Short(0x1234));
\r
5928 // Console.WriteLine(Hex.Int(0x12345678));
\r
5929 string fName = MakeFileName(outputDir,name,isDLL);
\r
5930 fileImage = new FileImage(isDLL,fName);
\r
5931 InitPEFile(name, fName, hasAssembly);
\r
5935 /// Create a new PEFile
\r
5937 /// <param name="name">module name</param>
\r
5938 /// <param name="isDLL">create a .dll or .exe</param>
\r
5939 /// <param name="hasAssembly">this PEfile is an assembly and
\r
5940 /// will contain the assemly manifest. The assembly name is the
\r
5941 /// same as the module name</param>
\r
5942 /// <param name="outStream">write the PEFile to this stream instead
\r
5943 /// of to a new file</param>
\r
5944 public PEFile(string name, bool isDLL, bool hasAssembly, Stream outStream) {
\r
5945 fileImage = new FileImage(isDLL,outStream);
\r
5946 InitPEFile(name, MakeFileName(null,name,isDLL), hasAssembly);
\r
5949 private void InitPEFile(string name, string fName, bool hasAssembly) {
\r
5950 metaData = fileImage.GetMetaData();
\r
5951 thisMod = new Module(fName,metaData);
\r
5952 if (hasAssembly) {
\r
5953 thisAssembly = new Assembly(name,metaData);
\r
5954 metaData.AddToTable(MDTable.Assembly,thisAssembly);
\r
5956 moduleClass = AddClass(TypeAttr.Private,"","<Module>");
\r
5957 moduleClass.SpecialNoSuper();
\r
5958 metaData.AddToTable(MDTable.Module,thisMod);
\r
5962 public ClassDef ModuleClass {
5963 get { return moduleClass; }
5967 /// Set the subsystem (.subsystem) (Default is Windows Console mode)
\r
5969 /// <param name="subS">subsystem value</param>
\r
5970 public void SetSubSystem(SubSystem subS) {
\r
5971 fileImage.subSys = subS;
\r
5975 /// Set the flags (.corflags)
\r
5977 /// <param name="flags">the flags value</param>
\r
5978 public void SetCorFlags(int flags) {
\r
5982 private string MakeFileName(string dirName, string name, bool isDLL) {
\r
5983 string result = "";
\r
5984 if ((dirName != null) && (dirName.CompareTo("") != 0)) {
\r
5986 if (!dirName.EndsWith("\\")) result += "\\";
\r
5990 // if (isDLL) result += ".dll"; else result += ".exe";
\r
5996 /// Add an external assembly to this PEFile (.assembly extern)
\r
5998 /// <param name="assemName">the external assembly name</param>
\r
5999 /// <returns>a descriptor for this external assembly</returns>
\r
6000 public AssemblyRef AddExternAssembly(string assemName) {
\r
6001 if (assemName.CompareTo(mscorlibName) == 0) return metaData.mscorlib;
\r
6002 AssemblyRef anAssem = new AssemblyRef(metaData,assemName);
\r
6003 metaData.AddToTable(MDTable.AssemblyRef,anAssem);
\r
6004 // Console.WriteLine("Adding assembly " + assemName);
\r
6009 /// Add an external module to this PEFile (.module extern)
\r
6011 /// <param name="name">the external module name</param>
\r
6012 /// <returns>a descriptor for this external module</returns>
\r
6013 public ModuleRef AddExternModule(string name) {
\r
6014 ModuleRef modRef = new ModuleRef(metaData,name);
\r
6015 metaData.AddToTable(MDTable.ModuleRef,modRef);
\r
6020 /// Add a "global" method to this module
\r
6022 /// <param name="name">method name</param>
\r
6023 /// <param name="retType">return type</param>
\r
6024 /// <param name="pars">method parameters</param>
\r
6025 /// <returns>a descriptor for this new "global" method</returns>
\r
6026 public MethodDef AddMethod(string name, Type retType, Param[] pars) {
\r
6027 return moduleClass.AddMethod(name,retType,pars);
\r
6031 /// Add a "global" method to this module
\r
6033 /// <param name="mAtts">method attributes</param>
\r
6034 /// <param name="iAtts">method implementation attributes</param>
\r
6035 /// <param name="name">method name</param>
\r
6036 /// <param name="retType">return type</param>
\r
6037 /// <param name="pars">method parameters</param>
\r
6038 /// <returns>a descriptor for this new "global" method</returns>
\r
6039 public MethodDef AddMethod(MethAttr mAtts, ImplAttr iAtts, string name, Type retType, Param[] pars) {
\r
6040 return moduleClass.AddMethod(mAtts,iAtts,name,retType,pars);
\r
6043 public MethodRef AddMethodToTypeSpec (Type item, string name, Type retType, Type[] pars) {
\r
6044 MethodRef meth = new MethodRef (item.GetTypeSpec (metaData), name, retType, pars, false, null);
\r
6045 metaData.AddToTable (MDTable.MemberRef,meth);
\r
6049 public MethodRef AddVarArgMethodToTypeSpec (Type item, string name, Type retType,
\r
6050 Type[] pars, Type[] optPars) {
\r
6051 MethodRef meth = new MethodRef(item.GetTypeSpec (metaData), name,retType,pars,true,optPars);
\r
6052 metaData.AddToTable(MDTable.MemberRef,meth);
\r
6056 public FieldRef AddFieldToTypeSpec (Type item, string name, Type fType) {
\r
6057 FieldRef field = new FieldRef (item.GetTypeSpec (metaData), name,fType);
\r
6058 metaData.AddToTable (MDTable.MemberRef,field);
\r
6062 public void AddMethodSpec (Method m, GenericMethodSig g_sig)
6064 MethodSpec ms = new MethodSpec (m, g_sig);
6065 metaData.AddToTable (MDTable.MethodSpec, ms);
6069 /// Add a "global" field to this module
\r
6071 /// <param name="name">field name</param>
\r
6072 /// <param name="fType">field type</param>
\r
6073 /// <returns>a descriptor for this new "global" field</returns>
\r
6074 public FieldDef AddField(string name, Type fType) {
\r
6075 return moduleClass.AddField(name,fType);
\r
6079 /// Add a "global" field to this module
\r
6081 /// <param name="attrSet">attributes of this field</param>
\r
6082 /// <param name="name">field name</param>
\r
6083 /// <param name="fType">field type</param>
\r
6084 /// <returns>a descriptor for this new "global" field</returns>
\r
6085 public FieldDef AddField(FieldAttr attrSet, string name, Type fType) {
\r
6086 return moduleClass.AddField(attrSet,name,fType);
\r
6090 /// Add a class to this module
\r
6092 /// <param name="attrSet">attributes of this class</param>
\r
6093 /// <param name="nsName">name space name</param>
\r
6094 /// <param name="name">class name</param>
\r
6095 /// <returns>a descriptor for this new class</returns>
\r
6096 public ClassDef AddClass(TypeAttr attrSet, string nsName, string name) {
\r
6097 ClassDef aClass = new ClassDef(attrSet,nsName,name,metaData);
\r
6098 metaData.AddToTable(MDTable.TypeDef,aClass);
\r
6103 /// Add a class which extends System.ValueType to this module
\r
6105 /// <param name="attrSet">attributes of this class</param>
\r
6106 /// <param name="nsName">name space name</param>
\r
6107 /// <param name="name">class name</param>
\r
6108 /// <returns>a descriptor for this new class</returns>
\r
6109 public ClassDef AddValueClass(TypeAttr attrSet, string nsName, string name) {
\r
6110 ClassDef aClass = new ClassDef(attrSet,nsName,name,metaData);
\r
6111 aClass.MakeValueClass();
\r
6112 metaData.AddToTable(MDTable.TypeDef,aClass);
\r
6117 /// Add a class to this module
\r
6119 /// <param name="attrSet">attributes of this class</param>
\r
6120 /// <param name="nsName">name space name</param>
\r
6121 /// <param name="name">class name</param>
\r
6122 /// <param name="superType">super type of this class (extends)</param>
\r
6123 /// <returns>a descriptor for this new class</returns>
\r
6124 public ClassDef AddClass(TypeAttr attrSet, string nsName, string name, Class superType) {
\r
6125 ClassDef aClass = new ClassDef(attrSet,nsName,name,metaData);
\r
6126 aClass.SetSuper(superType);
\r
6127 metaData.AddToTable(MDTable.TypeDef,aClass);
\r
6131 public FileRef AddFile(string fName, byte[] hashBytes, bool hasMetaData, bool entryPoint) {
\r
6132 FileRef file = new FileRef(fName,hashBytes,hasMetaData,entryPoint,metaData);
\r
6133 metaData.AddToTable(MDTable.File,file);
\r
6138 /// Add a manifest resource to this PEFile NOT YET IMPLEMENTED
\r
6140 /// <param name="mr"></param>
\r
6141 public void AddManifestResource(ManifestResource mr) {
\r
6142 metaData.AddToTable(MDTable.ManifestResource,mr);
\r
6143 //mr.FixName(metaData);
\r
6147 /// Write out the PEFile (the "bake" function)
\r
6149 public void WritePEFile() { /* the "bake" function */
\r
6150 fileImage.MakeFile();
\r
6154 /// Get the descriptor of this module
\r
6156 /// <returns>the descriptor for this module</returns>
\r
6157 public Module GetThisModule() {
\r
6162 /// Get the descriptor for this assembly. The PEFile must have been
\r
6163 /// created with hasAssembly = true
\r
6165 /// <returns>the descriptor for this assembly</returns>
\r
6166 public Assembly GetThisAssembly() {
\r
6167 return thisAssembly;
\r
6172 /**************************************************************************/
\r
6174 /// Descriptor for the Primitive types defined in IL
\r
6176 public class PrimitiveType : Type
\r
6178 private string name;
\r
6179 private int systemTypeIndex;
\r
6180 public static int NumSystemTypes = 18;
\r
6182 public static readonly PrimitiveType Void = new PrimitiveType(0x01,"Void",0);
\r
6183 public static readonly PrimitiveType Boolean = new PrimitiveType(0x02,"Boolean",1);
\r
6184 public static readonly PrimitiveType Char = new PrimitiveType(0x03,"Char",2);
\r
6185 public static readonly PrimitiveType Int8 = new PrimitiveType(0x04,"SByte",3);
\r
6186 public static readonly PrimitiveType UInt8 = new PrimitiveType(0x05,"Byte",4);
\r
6187 public static readonly PrimitiveType Int16 = new PrimitiveType(0x06,"Int16",5);
\r
6188 public static readonly PrimitiveType UInt16 = new PrimitiveType(0x07,"UInt16",6);
\r
6189 public static readonly PrimitiveType Int32 = new PrimitiveType(0x08,"Int32",7);
\r
6190 public static readonly PrimitiveType UInt32 = new PrimitiveType(0x09,"UInt32",8);
\r
6191 public static readonly PrimitiveType Int64 = new PrimitiveType(0x0A,"Int64",9);
\r
6192 public static readonly PrimitiveType UInt64 = new PrimitiveType(0x0B,"UInt64",10);
\r
6193 public static readonly PrimitiveType Float32 = new PrimitiveType(0x0C,"Single",11);
\r
6194 public static readonly PrimitiveType Float64 = new PrimitiveType(0x0D,"Double",12);
\r
6195 public static readonly PrimitiveType String = new PrimitiveType(0x0E,"String",13);
\r
6196 internal static readonly PrimitiveType Class = new PrimitiveType(0x12);
\r
6197 public static readonly PrimitiveType TypedRef = new PrimitiveType(0x16,"TypedReference",14);
\r
6198 public static readonly PrimitiveType IntPtr = new PrimitiveType(0x18,"IntPtr",15);
\r
6199 public static readonly PrimitiveType UIntPtr = new PrimitiveType(0x19,"UIntPtr",16);
\r
6200 public static readonly PrimitiveType Object = new PrimitiveType(0x1C,"Object",17);
\r
6201 internal static readonly PrimitiveType ClassType = new PrimitiveType(0x50);
\r
6202 public static readonly PrimitiveType NativeInt = IntPtr;
\r
6203 public static readonly PrimitiveType NativeUInt = UIntPtr;
\r
6205 internal PrimitiveType(byte typeIx) : base(typeIx) { }
\r
6207 internal PrimitiveType(byte typeIx, string name, int STIx) : base(typeIx) {
\r
6209 this.systemTypeIndex = STIx;
\r
6212 internal string GetName() { return name; }
\r
6214 internal int GetSystemTypeIx() { return systemTypeIndex; }
\r
6216 internal sealed override void TypeSig(MemoryStream str) {
\r
6217 str.WriteByte(typeIndex);
\r
6220 internal override MetaDataElement GetTypeSpec(MetaData md) {
\r
6221 TypeSpec tS = md.GetPrimitiveTypeSpec(systemTypeIndex);
\r
6223 tS = new TypeSpec(this,md);
\r
6224 md.SetPrimitiveTypeSpec(systemTypeIndex,tS);
\r
6225 md.AddToTable(MDTable.TypeSpec,tS);
\r
6232 /**************************************************************************/
\r
6234 /// Descriptor for the Property of a class
\r
6236 public class Property : Feature
\r
6238 private static readonly byte PropertyTag = 0x8;
\r
6239 MethodDef getterMeth;
\r
6240 ConstantElem constVal;
\r
6241 uint typeBlobIx = 0;
\r
6246 internal Property(string name, Type retType, Type[] pars, ClassDef parent) : base(name, parent) {
\r
6247 returnType = retType;
\r
6249 if (pars != null) numPars = (uint)pars.Length;
\r
6250 tabIx = MDTable.Property;
\r
6254 /// Add a set method to this property
\r
6256 /// <param name="setter">the set method</param>
\r
6257 public void AddSetter(MethodDef setter) {
\r
6258 AddMethod(setter,MethodType.Setter);
\r
6262 /// Add a get method to this property
\r
6264 /// <param name="getter">the get method</param>
\r
6265 public void AddGetter(MethodDef getter) {
\r
6266 AddMethod(getter,MethodType.Getter);
\r
6267 getterMeth = getter;
\r
6271 /// Add another method to this property
\r
6273 /// <param name="other">the method</param>
\r
6274 public void AddOther(MethodDef other) {
\r
6275 AddMethod(other,MethodType.Other);
\r
6279 /// Add an initial value for this property
\r
6281 /// <param name="constVal">the initial value for this property</param>
\r
6282 public void AddInitValue(Constant constVal) {
\r
6283 this.constVal = new ConstantElem(this,constVal);
\r
6286 internal sealed override void BuildTables(MetaData md) {
\r
6288 nameIx = md.AddToStringsHeap(name);
\r
6289 MemoryStream sig = new MemoryStream();
\r
6290 sig.WriteByte(PropertyTag);
\r
6291 MetaData.CompressNum(numPars,sig);
\r
6292 returnType.TypeSig(sig);
\r
6293 for (int i=0; i < numPars; i++) {
\r
6294 parList[i].TypeSig(sig);
\r
6296 typeBlobIx = md.AddToBlobHeap(sig.ToArray());
\r
6297 for (int i=0; i < tide; i++) {
\r
6298 md.AddToTable(MDTable.MethodSemantics,methods[i]);
\r
6300 if (constVal != null) {
\r
6301 md.AddToTable(MDTable.Constant,constVal);
\r
6302 constVal.BuildTables(md);
\r
6307 internal sealed override uint Size(MetaData md) {
\r
6308 return 2 + md.StringsIndexSize() + md.BlobIndexSize();
\r
6311 internal sealed override void Write(FileImage output) {
\r
6312 output.Write(flags);
\r
6313 output.StringsIndex(nameIx);
\r
6314 output.BlobIndex(typeBlobIx);
\r
6317 internal sealed override uint GetCodedIx(CIx code) {
\r
6319 case (CIx.HasCustomAttr) : return 9;
\r
6320 case (CIx.HasConst) : return 2;
\r
6321 case (CIx.HasSemantics) : return 1;
\r
6327 /**************************************************************************/
\r
6329 /// Descriptor for an pointer (type * or type &)
\r
6331 public abstract class PtrType : Type
\r
6335 internal PtrType(Type bType, byte typeIx) : base(typeIx)
\r
6338 tabIx = MDTable.TypeSpec;
\r
6341 internal sealed override void TypeSig(MemoryStream str) {
\r
6342 str.WriteByte(typeIndex);
\r
6343 baseType.TypeSig(str);
\r
6347 /**************************************************************************/
\r
6349 /// Descriptor for a managed pointer (type & or byref)
\r
6352 public class ManagedPointer : PtrType // <type> & (BYREF)
\r
6356 /// Create new managed pointer to baseType
\r
6358 /// <param name="bType">the base type of the pointer</param>
\r
6359 public ManagedPointer(Type baseType) : base(baseType,0x10) { }
\r
6362 /**************************************************************************/
\r
6364 /// Descriptor for an unmanaged pointer (type *)
\r
6366 public class UnmanagedPointer : PtrType // PTR
\r
6369 /// Create a new unmanaged pointer to baseType
\r
6371 /// <param name="baseType">the base type of the pointer</param>
\r
6372 public UnmanagedPointer(Type baseType) : base(baseType, 0x0F) { }
\r
6375 /**************************************************************************/
\r
6377 /// Base class for scopes (extended by Module, ModuleRef, Assembly, AssemblyRef)
\r
6379 public abstract class ResolutionScope : MetaDataElement
\r
6381 protected uint nameIx = 0;
\r
6382 protected MetaData metaData;
\r
6383 protected string name;
\r
6385 internal ResolutionScope(string name, MetaData md)
\r
6389 nameIx = md.AddToStringsHeap(name);
\r
6392 internal string GetName() { return name; }
\r
6395 /**************************************************************************/
\r
6397 /// Descriptor for a Section in a PEFile eg .text, .sdata
\r
6399 internal class Section {
\r
6400 private static readonly uint relocPageSize = 4096; // 4K pages for fixups
\r
6403 uint offset = 0, tide = 0, size = 0, rva = 0, relocTide = 0;
\r
6404 //uint relocOff = 0;
\r
6405 uint flags = 0, padding = 0;
\r
6408 internal Section(string sName, uint sFlags) {
6409 name = sName.ToCharArray();
\r
6413 internal uint Tide() { return tide; }
\r
6415 internal void IncTide(uint incVal) { tide += incVal; }
\r
6417 internal uint Padding() { return padding; }
\r
6419 internal uint Size() { return size; }
\r
6421 internal void SetSize(uint pad) {
\r
6423 size = tide + padding;
\r
6426 internal uint RVA() { return rva; }
\r
6428 internal void SetRVA(uint rva) { this.rva = rva; }
\r
6430 internal uint Offset() { return offset; }
\r
6432 internal void SetOffset(uint offs) { offset = offs; }
\r
6434 internal void DoBlock(BinaryWriter reloc, uint page, int start, int end) {
\r
6435 //Console.WriteLine("rva = " + rva + " page = " + page);
\r
6436 reloc.Write(rva + page);
\r
6437 reloc.Write((uint)(((end-start+1)*2) + 8));
\r
6438 for (int j=start; j < end; j++) {
\r
6439 //Console.WriteLine("reloc offset = " + relocs[j]);
\r
6440 reloc.Write((ushort)((0x3 << 12) | (relocs[j] - page)));
\r
6442 reloc.Write((ushort)0);
\r
6445 internal void DoRelocs(BinaryWriter reloc) {
\r
6446 if (relocTide > 0) {
\r
6447 //relocOff = (uint)reloc.Seek(0,SeekOrigin.Current);
\r
6448 uint block = (relocs[0]/relocPageSize + 1) * relocPageSize;
\r
6450 for (int i=1; i < relocTide; i++) {
\r
6451 if (relocs[i] >= block) {
\r
6452 DoBlock(reloc,block-relocPageSize,start,i);
\r
6454 block = (relocs[i]/relocPageSize + 1) * relocPageSize;
\r
6457 DoBlock(reloc,block-relocPageSize,start,(int)relocTide);
\r
6461 internal void AddReloc(uint offs) {
\r
6463 if (relocs == null) {
\r
6464 relocs = new uint[5];
\r
6466 if (relocTide >= relocs.Length) {
\r
6467 uint[] tmp = relocs;
\r
6468 relocs = new uint[tmp.Length + 5];
\r
6469 for (int i=0; i < relocTide; i++) {
\r
6470 relocs[i] = tmp[i];
\r
6473 while ((pos < relocTide) && (relocs[pos] < offs)) pos++;
\r
6474 for (int i=pos; i < relocTide; i++) {
\r
6475 relocs[i+1] = relocs[i];
\r
6478 relocs[pos] = offs;
\r
6482 internal void WriteHeader(BinaryWriter output, uint relocRVA) {
\r
6483 output.Write(name);
\r
6484 output.Write(tide);
\r
6485 output.Write(rva);
\r
6486 output.Write(size);
\r
6487 output.Write(offset);
\r
6489 //output.Write(relocRVA + relocOff);
\r
6492 //output.Write((ushort)relocTide);
\r
6493 //output.Write((ushort)0);
\r
6494 output.Write(flags);
\r
6498 /**************************************************************************/
\r
6499 public abstract class Signature : MetaDataElement
\r
6501 protected uint sigIx;
\r
6503 internal Signature() {
\r
6504 tabIx = MDTable.StandAloneSig;
\r
6507 internal sealed override uint Size(MetaData md) {
\r
6508 return md.BlobIndexSize();
\r
6511 internal sealed override void Write(FileImage output) {
\r
6512 output.BlobIndex(sigIx);
\r
6515 internal sealed override uint GetCodedIx(CIx code) { return (uint)tabIx; }
\r
6518 /**************************************************************************/
\r
6520 /// Descriptor for a class defined in System (mscorlib)
\r
6522 internal class SystemClass : ClassRef
\r
6524 PrimitiveType elemType;
\r
6526 internal SystemClass(PrimitiveType eType, AssemblyRef paren, MetaData md)
\r
6527 : base("System",eType.GetName(),md) {
\r
6532 internal override sealed MetaDataElement GetTypeSpec(MetaData md) {
\r
6533 if (typeSpec == null) typeSpec = (TypeSpec)elemType.GetTypeSpec(md);
\r
6538 internal sealed override void TypeSig(MemoryStream str) {
\r
6539 str.WriteByte(elemType.GetTypeIndex());
\r
6543 /**************************************************************************/
\r
6545 /// Base class for all IL types
\r
6547 public abstract class Type : MetaDataElement {
\r
6548 protected byte typeIndex;
\r
6549 protected TypeSpec typeSpec;
\r
6551 internal Type(byte tyIx) { typeIndex = tyIx; }
\r
6553 internal byte GetTypeIndex() { return typeIndex; }
\r
6555 internal virtual MetaDataElement GetTypeSpec(MetaData md) {
\r
6556 if (typeSpec == null) {
\r
6557 typeSpec = new TypeSpec(this,md);
\r
6558 md.AddToTable(MDTable.TypeSpec,typeSpec);
\r
6563 internal virtual void TypeSig(MemoryStream str) {
\r
6564 throw(new TypeSignatureException(this.GetType().AssemblyQualifiedName +
\r
6565 " doesn't have a type signature!!"));
\r
6570 /**************************************************************************/
\r
6572 public class TypeSpec : MetaDataElement {
\r
6575 internal TypeSpec(Type aType, MetaData md) {
\r
6576 MemoryStream sig = new MemoryStream();
\r
6577 aType.TypeSig(sig);
\r
6578 sigIx = md.AddToBlobHeap(sig.ToArray());
\r
6579 tabIx = MDTable.TypeSpec;
\r
6582 internal sealed override uint GetCodedIx(CIx code) {
\r
6584 case (CIx.TypeDefOrRef) : return 2;
\r
6585 case (CIx.HasCustomAttr) : return 13;
\r
6586 case (CIx.MemberRefParent) : return 4;
\r
6591 internal override uint Size(MetaData md) {
\r
6592 return md.BlobIndexSize();
\r
6595 internal sealed override void Write(FileImage output) {
\r
6596 //Console.WriteLine("Writing the blob index for a TypeSpec");
\r
6597 output.BlobIndex(sigIx);
\r