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 {br = 0x2B, brfalse, brtrue, beq, bge, bgt, ble, blt,
\r
647 bne_un, bge_un, bgt_un, ble_un, blt_un, leave = 0xDE }
\r
650 /// Index for all the tables in the meta data
\r
652 public enum MDTable { Module, TypeRef, TypeDef, Field = 0x04, Method = 0x06,
\r
653 Param = 0x08, InterfaceImpl, MemberRef, Constant, CustomAttribute,
\r
654 FieldMarshal, DeclSecurity, ClassLayout, FieldLayout, StandAloneSig,
\r
655 EventMap, Event = 0x14, PropertyMap, Property = 0x17, MethodSemantics,
\r
656 MethodImpl, ModuleRef, TypeSpec, ImplMap, FieldRVA, Assembly = 0x20,
\r
657 AssemblyProcessor, AssemblyOS, AssemblyRef, AssemblyRefProcessor,
\r
658 AssemblyRefOS, File, ExportedType, ManifestResource, NestedClass,
\r
659 GenericParam, MethodSpec, GenericParamConstraint }
\r
661 public enum SafeArrayType { int16 = 2, int32, float32, float64,
\r
662 currency, date, bstr, dispatch, error, boolean, variant, unknown,
\r
663 Decimal, int8 = 16, uint8, uint16, uint32, Int = 22, UInt }
\r
665 internal enum CIx { TypeDefOrRef, HasConst, HasCustomAttr, HasFieldMarshal,
\r
666 HasDeclSecurity, MemberRefParent, HasSemantics, MethodDefOrRef,
\r
667 MemberForwarded, Implementation, CustomAttributeType, ResolutionScope,
\r
668 TypeOrMethodDef, MaxCIx }
\r
670 internal enum MapType { eventMap, propertyMap, nestedClass }
\r
672 /**************************************************************************/
\r
674 /// The assembly for mscorlib.
\r
676 public sealed class MSCorLib : AssemblyRef
\r
678 private static readonly int valueTypeIx = 18;
\r
679 private readonly string systemName = "System";
\r
680 private ClassRef[] systemClasses = new ClassRef[valueTypeIx+2];
\r
681 private PrimitiveType[] systemTypes = new PrimitiveType[valueTypeIx];
\r
682 private TypeSpec[] specialTypeSpecs = new TypeSpec[valueTypeIx];
\r
683 private static int[] specialNames = {
\r
684 PrimitiveType.Void.GetName().GetHashCode(),
\r
685 PrimitiveType.Boolean.GetName().GetHashCode(),
\r
686 PrimitiveType.Char.GetName().GetHashCode(),
\r
687 PrimitiveType.Int8.GetName().GetHashCode(),
\r
688 PrimitiveType.UInt8.GetName().GetHashCode(),
\r
689 PrimitiveType.Int16.GetName().GetHashCode(),
\r
690 PrimitiveType.UInt16.GetName().GetHashCode(),
\r
691 PrimitiveType.Int32.GetName().GetHashCode(),
\r
692 PrimitiveType.UInt32.GetName().GetHashCode(),
\r
693 PrimitiveType.Int64.GetName().GetHashCode(),
\r
694 PrimitiveType.UInt64.GetName().GetHashCode(),
\r
695 PrimitiveType.Float32.GetName().GetHashCode(),
\r
696 PrimitiveType.Float64.GetName().GetHashCode(),
\r
697 PrimitiveType.String.GetName().GetHashCode(),
\r
698 PrimitiveType.TypedRef.GetName().GetHashCode(),
\r
699 PrimitiveType.IntPtr.GetName().GetHashCode(),
\r
700 PrimitiveType.UIntPtr.GetName().GetHashCode(),
\r
701 PrimitiveType.Object.GetName().GetHashCode(),
\r
702 "ValueType".GetHashCode(),
\r
703 "Enum".GetHashCode()
\r
706 internal MSCorLib(MetaData md) : base(md,"mscorlib") {
\r
707 md.AddToTable(MDTable.AssemblyRef,this);
\r
708 systemTypes[PrimitiveType.Void.GetSystemTypeIx()] = PrimitiveType.Void;
\r
709 systemTypes[PrimitiveType.Boolean.GetSystemTypeIx()] = PrimitiveType.Boolean;
\r
710 systemTypes[PrimitiveType.Char.GetSystemTypeIx()] = PrimitiveType.Char;
\r
711 systemTypes[PrimitiveType.Int8.GetSystemTypeIx()] = PrimitiveType.Int8;
\r
712 systemTypes[PrimitiveType.UInt8.GetSystemTypeIx()] = PrimitiveType.UInt8;
\r
713 systemTypes[PrimitiveType.Int16.GetSystemTypeIx()] = PrimitiveType.Int16;
\r
714 systemTypes[PrimitiveType.UInt16.GetSystemTypeIx()] = PrimitiveType.UInt16;
\r
715 systemTypes[PrimitiveType.Int32.GetSystemTypeIx()] = PrimitiveType.Int32;
\r
716 systemTypes[PrimitiveType.UInt32.GetSystemTypeIx()] = PrimitiveType.UInt32;
\r
717 systemTypes[PrimitiveType.Int64.GetSystemTypeIx()] = PrimitiveType.Int64;
\r
718 systemTypes[PrimitiveType.UInt64.GetSystemTypeIx()] = PrimitiveType.UInt64;
\r
719 systemTypes[PrimitiveType.Float32.GetSystemTypeIx()] = PrimitiveType.Float32;
\r
720 systemTypes[PrimitiveType.Float64.GetSystemTypeIx()] = PrimitiveType.Float64;
\r
721 systemTypes[PrimitiveType.IntPtr.GetSystemTypeIx()] = PrimitiveType.IntPtr;
\r
722 systemTypes[PrimitiveType.UIntPtr.GetSystemTypeIx()] = PrimitiveType.UIntPtr;
\r
723 systemTypes[PrimitiveType.String.GetSystemTypeIx()] = PrimitiveType.String;
\r
724 systemTypes[PrimitiveType.Object.GetSystemTypeIx()] = PrimitiveType.Object;
\r
725 systemTypes[PrimitiveType.TypedRef.GetSystemTypeIx()] = PrimitiveType.TypedRef;
\r
729 /// Add a class to the mscorlib assembly
\r
731 /// <param name="nsName">name space name</param>
\r
732 /// <param name="name">class name</param>
\r
733 /// <returns></returns>
\r
734 public override ClassRef AddClass(string nsName, string name) {
\r
735 ClassRef aClass = GetSpecialClass(nsName,name);
\r
736 if (aClass == null) {
\r
737 aClass = new ClassRef(nsName,name,metaData);
\r
738 metaData.AddToTable(MDTable.TypeRef,aClass);
\r
739 aClass.SetParent(this);
\r
744 private ClassRef GetSpecialClass(string nsName,string name) {
\r
745 if (nsName.CompareTo(systemName) != 0) return null;
\r
746 int hash = name.GetHashCode();
\r
747 for (int i=0; i < specialNames.Length; i++) {
\r
748 if (hash == specialNames[i]) {
\r
749 if (systemClasses[i] == null) {
\r
750 if (i < valueTypeIx) {
\r
751 systemClasses[i] = new SystemClass(systemTypes[i],this,metaData);
\r
752 if ((systemTypes[i] != PrimitiveType.Object) &&
\r
753 (systemTypes[i] != PrimitiveType.String)) {
\r
754 systemClasses[i].MakeValueClass();
\r
757 systemClasses[i] = new ClassRef(nsName,name,metaData);
\r
758 systemClasses[i].SetParent(this);
\r
759 systemClasses[i].MakeValueClass();
\r
761 metaData.AddToTable(MDTable.TypeRef,systemClasses[i]);
\r
763 return systemClasses[i];
\r
769 internal ClassRef GetSpecialSystemClass(PrimitiveType pType) {
\r
770 int ix = pType.GetSystemTypeIx();
\r
771 if (systemClasses[ix] == null) {
\r
772 systemClasses[ix] = new SystemClass(pType,this,metaData);
\r
773 metaData.AddToTable(MDTable.TypeRef,systemClasses[ix]);
\r
775 return systemClasses[ix];
\r
778 private ClassRef GetValueClass(string name, int hash) {
\r
779 int ix = valueTypeIx;
\r
780 if (hash != specialNames[valueTypeIx]) ix++;
\r
781 if (systemClasses[ix] == null) {
\r
782 systemClasses[ix] = new ClassRef(systemName,name,metaData);
\r
783 systemClasses[ix].SetParent(this);
\r
784 systemClasses[ix].MakeValueClass();
\r
785 metaData.AddToTable(MDTable.TypeRef,systemClasses[ix]);
\r
787 return systemClasses[ix];
\r
790 internal ClassRef ValueType() {
\r
791 if (systemClasses[valueTypeIx] == null) {
\r
792 ClassRef valType = new ClassRef("System","ValueType",metaData);
\r
793 valType.SetParent(this);
\r
794 valType.MakeValueClass();
\r
795 metaData.AddToTable(MDTable.TypeRef,valType);
\r
796 systemClasses[valueTypeIx] = valType;
\r
798 return systemClasses[valueTypeIx];
\r
802 /// Add a value class to this external assembly
\r
804 /// <param name="nsName">name space name</param>
\r
805 /// <param name="name">class name</param>
\r
806 /// <returns></returns>
\r
807 public override ClassRef AddValueClass(string nsName, string name) {
\r
808 if (nsName.CompareTo(systemName) == 0) {
\r
809 int hash = name.GetHashCode();
\r
810 if ((hash == specialNames[valueTypeIx]) ||
\r
811 (hash == specialNames[valueTypeIx+1])) {
\r
812 return GetValueClass(name,hash);
\r
815 ClassRef aClass = new ClassRef(nsName,name,metaData);
\r
816 metaData.AddToTable(MDTable.TypeRef,aClass);
\r
817 aClass.SetParent(this);
\r
818 aClass.MakeValueClass();
\r
823 /**************************************************************************/
\r
825 /// Signature for calli instruction
\r
827 public class CalliSig : Signature
\r
829 private static readonly byte Sentinel = 0x41;
\r
832 Type[] parameters, optParams;
\r
833 uint numPars = 0, numOptPars = 0;
\r
836 /// Create a signature for a calli instruction
\r
838 /// <param name="cconv">calling conventions</param>
\r
839 /// <param name="retType">return type</param>
\r
840 /// <param name="pars">parameter types</param>
\r
841 public CalliSig(CallConv cconv, Type retType, Type[] pars) {
\r
842 tabIx = MDTable.StandAloneSig;
\r
844 returnType = retType;
\r
846 if (pars != null) numPars = (uint)pars.Length;
\r
850 /// Add the optional parameters to a vararg method
\r
851 /// This method sets the vararg calling convention
\r
853 /// <param name="optPars">the optional pars for the vararg call</param>
\r
854 public void AddVarArgs(Type[] optPars) {
\r
855 optParams = optPars;
\r
856 if (optPars != null) numOptPars = (uint)optPars.Length;
\r
857 callConv |= CallConv.Vararg;
\r
861 /// Add extra calling conventions to this callsite signature
\r
863 /// <param name="cconv"></param>
\r
864 public void AddCallingConv(CallConv cconv) {
\r
868 internal sealed override void BuildTables(MetaData md) {
\r
870 MemoryStream sig = new MemoryStream();
\r
871 sig.WriteByte((byte)callConv);
\r
872 MetaData.CompressNum(numPars+numOptPars,sig);
\r
873 returnType.TypeSig(sig);
\r
874 for (int i=0; i < numPars; i++) {
\r
875 parameters[i].TypeSig(sig);
\r
877 sigIx = md.AddToBlobHeap(sig.ToArray());
\r
878 if (numOptPars > 0) {
\r
879 sig.WriteByte(Sentinel);
\r
880 for (int i=0; i < numOptPars; i++) {
\r
881 optParams[i].TypeSig(sig);
\r
888 /**************************************************************************/
\r
890 /// The IL instructions for a method
\r
892 public class CILInstructions
\r
895 private static readonly uint ExHeaderSize = 4;
\r
896 private static readonly uint FatExClauseSize = 24;
\r
897 private static readonly uint SmlExClauseSize = 12;
\r
898 private static readonly sbyte maxByteVal = 127;
\r
899 private static readonly sbyte minByteVal = -128;
\r
900 private static readonly byte maxUByteVal = 255;
\r
901 private static readonly int smallSize = 64;
\r
902 private static readonly ushort TinyFormat = 0x2;
\r
903 private static readonly ushort FatFormat = 0x3003;
\r
904 private static readonly ushort MoreSects = 0x8;
\r
905 private static readonly ushort InitLocals = 0x10;
\r
906 private static readonly uint FatSize = 12;
\r
907 private static readonly uint FatWords = FatSize/4;
\r
908 private static readonly byte FatExceptTable = 0x41;
\r
909 private static readonly byte SmlExceptTable = 0x01;
\r
911 private MetaData metaData;
\r
912 private ArrayList exceptions, blockStack;
\r
913 //private bool codeChecked = false;
\r
914 private static readonly int INITSIZE = 5;
\r
915 private CILInstruction[] buffer = new CILInstruction[INITSIZE];
\r
916 private int tide = 0;
\r
917 private uint offset = 0;
\r
918 private ushort headerFlags = 0;
\r
919 private short maxStack;
\r
920 private uint paddingNeeded = 0;
\r
921 private byte exceptHeader = 0;
\r
922 uint localSigIx = 0;
\r
923 uint codeSize = 0, exceptSize = 0;
\r
924 bool tinyFormat, fatExceptionFormat = false;
\r
926 internal CILInstructions(MetaData md) {
\r
930 private void AddToBuffer(CILInstruction inst) {
\r
931 if (tide >= buffer.Length) {
\r
932 CILInstruction[] tmp = buffer;
\r
933 buffer = new CILInstruction[tmp.Length * 2];
\r
934 for (int i=0; i < tide; i++) {
\r
935 buffer[i] = tmp[i];
\r
938 //Console.WriteLine("Adding instruction at offset " + offset + " with size " + inst.size);
\r
939 inst.offset = offset;
\r
940 offset += inst.size;
\r
941 buffer[tide++] = inst;
\r
945 /// Add a simple IL instruction
\r
947 /// <param name="inst">the IL instruction</param>
\r
948 public void Inst(Op inst) {
\r
949 AddToBuffer(new Instr((int)inst));
\r
953 /// Add an IL instruction with an integer parameter
\r
955 /// <param name="inst">the IL instruction</param>
\r
956 /// <param name="val">the integer parameter value</param>
\r
957 public void IntInst(IntOp inst, int val) {
\r
958 int instr = (int)inst;
\r
959 if ((inst == IntOp.ldc_i4_s) || (inst == IntOp.ldc_i4))
\r
960 AddToBuffer(new IntInstr(instr,val,(inst == IntOp.ldc_i4_s)));
\r
962 AddToBuffer(new UIntInstr(instr,val,((inst < IntOp.ldc_i4_s) ||
\r
963 (inst == IntOp.unaligned))));
\r
967 /// Add the load long instruction
\r
969 /// <param name="cVal">the long value</param>
\r
970 public void ldc_i8(long cVal) {
\r
971 AddToBuffer(new LongInstr(0x21,cVal));
\r
975 /// Add the load float32 instruction
\r
977 /// <param name="cVal">the float value</param>
\r
978 public void ldc_r4(float cVal) {
\r
979 AddToBuffer(new FloatInstr(0x22,cVal));
\r
983 /// Add the load float64 instruction
\r
985 /// <param name="cVal">the float value</param>
\r
986 public void ldc_r8(double cVal) {
\r
987 AddToBuffer(new DoubleInstr(0x23,cVal));
\r
991 /// Add the load string instruction
\r
993 /// <param name="str">the string value</param>
\r
994 public void ldstr(string str) {
\r
995 AddToBuffer(new StringInstr(0x72,str));
\r
999 /// Add the calli instruction
\r
1001 /// <param name="sig">the signature for the calli</param>
\r
1002 public void calli(CalliSig sig) {
\r
1003 AddToBuffer(new SigInstr(0x29,sig));
\r
1007 /// Add a label to the CIL instructions
\r
1009 /// <param name="lab">the label to be added</param>
\r
1010 public void CodeLabel(CILLabel lab) {
\r
1011 AddToBuffer(new LabelInstr(lab));
\r
1015 /// Add an instruction with a field parameter
\r
1017 /// <param name="inst">the CIL instruction</param>
\r
1018 /// <param name="f">the field parameter</param>
\r
1019 public void FieldInst(FieldOp inst, Field f) {
\r
1020 AddToBuffer(new FieldInstr((int)inst,f));
\r
1024 /// Add an instruction with a method parameter
\r
1026 /// <param name="inst">the CIL instruction</param>
\r
1027 /// <param name="m">the method parameter</param>
\r
1028 public void MethInst(MethodOp inst, Method m) {
\r
1029 AddToBuffer(new MethInstr((int)inst,m));
\r
1033 /// Add an instruction with a type parameter
\r
1035 /// <param name="inst">the CIL instruction</param>
\r
1036 /// <param name="t">the type argument for the CIL instruction</param>
\r
1037 public void TypeInst(TypeOp inst, Type aType) {
\r
1038 AddToBuffer(new TypeInstr((int)inst,aType,metaData));
\r
1042 /// Add a branch instruction
\r
1044 /// <param name="inst">the branch instruction</param>
\r
1045 /// <param name="lab">the label that is the target of the branch</param>
\r
1046 public void Branch(BranchOp inst, CILLabel lab) {
\r
1047 AddToBuffer(new BranchInstr((int)inst,lab));
\r
1051 /// Add a switch instruction
\r
1053 /// <param name="labs">the target labels for the switch</param>
\r
1054 public void Switch(CILLabel[] labs) {
\r
1055 AddToBuffer(new SwitchInstr(0x45,labs));
\r
1059 /// Add a byte to the CIL instructions (.emitbyte)
\r
1061 /// <param name="bVal"></param>
\r
1062 public void emitbyte(byte bVal) {
\r
1063 AddToBuffer(new CILByte(bVal));
\r
1067 /// Add an instruction which puts an integer on TOS. This method
\r
1068 /// selects the correct instruction based on the value of the integer.
\r
1070 /// <param name="i">the integer value</param>
\r
1071 public void PushInt(int i) {
\r
1073 AddToBuffer(new Instr((int)Op.ldc_i4_m1));
\r
1074 } else if ((i >= 0) && (i <= 8)) {
\r
1075 Op op = (Op)(Op.ldc_i4_0 + i);
\r
1076 AddToBuffer(new Instr((int)op));
\r
1077 } else if ((i >= minByteVal) && (i <= maxByteVal)) {
\r
1078 AddToBuffer(new IntInstr((int)IntOp.ldc_i4_s,i,true));
\r
1080 AddToBuffer(new IntInstr((int)IntOp.ldc_i4,i,false));
\r
1085 /// Add the instruction to load a long on TOS
\r
1087 /// <param name="l">the long value</param>
\r
1088 public void PushLong(long l) {
\r
1089 AddToBuffer(new LongInstr(0x21,l));
\r
1093 /// Add an instruction to push the boolean value true on TOS
\r
1095 public void PushTrue() {
\r
1096 AddToBuffer(new Instr((int)Op.ldc_i4_1));
\r
1100 /// Add an instruction to push the boolean value false on TOS
\r
1102 public void PushFalse() {
\r
1103 AddToBuffer(new Instr((int)Op.ldc_i4_0));
\r
1107 /// Add the instruction to load an argument on TOS. This method
\r
1108 /// selects the correct instruction based on the value of argNo
\r
1110 /// <param name="argNo">the number of the argument</param>
\r
1111 public void LoadArg(int argNo) {
\r
1113 int op = (int)Op.ldarg_0 + argNo;
\r
1114 AddToBuffer(new Instr(op));
\r
1115 } else if (argNo <= maxUByteVal) {
\r
1116 AddToBuffer(new UIntInstr((int)IntOp.ldarg,argNo,true));
\r
1118 AddToBuffer(new UIntInstr(0x09,argNo,false));
\r
1123 /// Add the instruction to load the address of an argument on TOS.
\r
1124 /// This method selects the correct instruction based on the value
\r
1127 /// <param name="argNo">the number of the argument</param>
\r
1128 public void LoadArgAdr(int argNo) {
\r
1129 if (argNo <= maxUByteVal) {
\r
1130 AddToBuffer(new UIntInstr((int)IntOp.ldarga,argNo,true));
\r
1132 AddToBuffer(new UIntInstr(0x0A,argNo,false));
\r
1137 /// Add the instruction to load a local on TOS. This method selects
\r
1138 /// the correct instruction based on the value of locNo.
\r
1140 /// <param name="locNo">the number of the local to load</param>
\r
1141 public void LoadLocal(int locNo) {
\r
1143 int op = (int)Op.ldloc_0 + locNo;
\r
1144 AddToBuffer(new Instr(op));
\r
1145 } else if (locNo <= maxUByteVal) {
\r
1146 AddToBuffer(new UIntInstr((int)IntOp.ldloc,locNo,true));
\r
1148 AddToBuffer(new UIntInstr(0x0C,locNo,false));
\r
1153 /// Add the instruction to load the address of a local on TOS.
\r
1154 /// This method selects the correct instruction based on the
\r
1155 /// value of locNo.
\r
1157 /// <param name="locNo">the number of the local</param>
\r
1158 public void LoadLocalAdr(int locNo) {
\r
1159 if (locNo <= maxUByteVal) {
\r
1160 AddToBuffer(new UIntInstr((int)IntOp.ldloca,locNo,true));
\r
1162 AddToBuffer(new UIntInstr(0x0D,locNo,false));
\r
1167 /// Add the instruction to store to an argument. This method
\r
1168 /// selects the correct instruction based on the value of argNo.
\r
1170 /// <param name="argNo">the argument to be stored to</param>
\r
1171 public void StoreArg(int argNo) {
\r
1172 if (argNo <= maxUByteVal) {
\r
1173 AddToBuffer(new UIntInstr((int)IntOp.starg,argNo,true));
\r
1175 AddToBuffer(new UIntInstr(0x0B,argNo,false));
\r
1180 /// Add the instruction to store to a local. This method selects
\r
1181 /// the correct instruction based on the value of locNo.
\r
1183 /// <param name="locNo">the local to be stored to</param>
\r
1184 public void StoreLocal(int locNo) {
\r
1186 int op = (int)Op.stloc_0 + locNo;
\r
1187 AddToBuffer(new Instr(op));
\r
1188 } else if (locNo <= maxUByteVal) {
\r
1189 AddToBuffer(new UIntInstr((int)IntOp.stloc,locNo,true));
\r
1191 AddToBuffer(new UIntInstr(0x0E,locNo,false));
\r
1196 /// Create a new CIL label. To place the label in the CIL instruction
\r
1197 /// stream use CodeLabel.
\r
1199 /// <returns>a new CIL label</returns>
\r
1200 public CILLabel NewLabel() {
\r
1201 return new CILLabel();
\r
1204 public void AddTryBlock(TryBlock tryBlock) {
\r
1205 if (exceptions == null)
\r
1206 exceptions = new ArrayList();
\r
1207 else if (exceptions.Contains(tryBlock)) return;
\r
1208 exceptions.Add(tryBlock);
\r
1212 /// Create a new label at this position in the code buffer
\r
1214 /// <returns>the label at the current position</returns>
\r
1215 public CILLabel NewCodedLabel() {
\r
1216 CILLabel lab = new CILLabel();
\r
1217 AddToBuffer(new LabelInstr(lab));
\r
1222 /// Mark this position as the start of a new block
\r
1223 /// (try, catch, filter, finally or fault)
\r
1225 public void StartBlock() {
\r
1226 if (blockStack == null) blockStack = new ArrayList();
\r
1227 blockStack.Insert(0,NewCodedLabel());
\r
1231 /// Mark this position as the end of the last started block and
\r
1232 /// make it a try block. This try block is added to the current
\r
1233 /// instructions (ie do not need to call AddTryBlock)
\r
1235 /// <returns>The try block just ended</returns>
\r
1236 public TryBlock EndTryBlock() {
\r
1237 TryBlock tBlock = new TryBlock((CILLabel)blockStack[0],NewCodedLabel());
\r
1238 blockStack.RemoveAt(0);
\r
1239 AddTryBlock(tBlock);
\r
1244 /// Mark this position as the end of the last started block and
\r
1245 /// make it a catch block. This catch block is associated with the
\r
1246 /// specified try block.
\r
1248 /// <param name="exceptType">the exception type to be caught</param>
\r
1249 /// <param name="tryBlock">the try block associated with this catch block</param>
\r
1250 public void EndCatchBlock(Class exceptType, TryBlock tryBlock) {
\r
1251 Catch catchBlock = new Catch(exceptType,(CILLabel)blockStack[0],
\r
1253 tryBlock.AddHandler(catchBlock);
\r
1257 /// Mark this position as the end of the last started block and
\r
1258 /// make it a filter block. This filter block is associated with the
\r
1259 /// specified try block.
\r
1261 /// <param name="filterLab">the label where the filter code is</param>
\r
1262 /// <param name="tryBlock">the try block associated with this filter block</param>
\r
1263 public void EndFilterBlock(CILLabel filterLab, TryBlock tryBlock) {
\r
1264 Filter filBlock = new Filter(filterLab,(CILLabel)blockStack[0],NewCodedLabel());
\r
1265 tryBlock.AddHandler(filBlock);
\r
1269 /// Mark this position as the end of the last started block and
\r
1270 /// make it a finally block. This finally block is associated with the
\r
1271 /// specified try block.
\r
1273 /// <param name="tryBlock">the try block associated with this finally block</param>
\r
1274 public void EndFinallyBlock(TryBlock tryBlock) {
\r
1275 Finally finBlock= new Finally((CILLabel)blockStack[0],NewCodedLabel());
\r
1276 tryBlock.AddHandler(finBlock);
\r
1280 /// Mark this position as the end of the last started block and
\r
1281 /// make it a fault block. This fault block is associated with the
\r
1282 /// specified try block.
\r
1284 /// <param name="tryBlock">the try block associated with this fault block</param>
\r
1285 public void EndFaultBlock(TryBlock tryBlock) {
\r
1286 Fault fBlock= new Fault((CILLabel)blockStack[0],NewCodedLabel());
\r
1287 tryBlock.AddHandler(fBlock);
\r
1290 internal uint GetCodeSize() {
\r
1291 return codeSize + paddingNeeded + exceptSize;
\r
1294 internal void CheckCode(uint locSigIx, bool initLocals, int maxStack) {
\r
1295 if (tide == 0) return;
\r
1296 bool changed = true;
\r
1299 for (int i=0; i < tide; i++) {
\r
1300 changed = buffer[i].Check(metaData) || changed;
\r
1303 for (int i=1; i < tide; i++) {
\r
1304 buffer[i].offset = buffer[i-1].offset + buffer[i-1].size;
\r
1306 offset = buffer[tide-1].offset + buffer[tide-1].size;
\r
1309 codeSize = offset;
\r
1310 // Console.WriteLine("codeSize before header added = " + codeSize);
\r
1311 if ((offset < smallSize) && (maxStack <= 8) && (locSigIx == 0) && (exceptions == null)) {
\r
1312 // can use tiny header
\r
1313 //Console.WriteLine("Tiny Header");
\r
1314 tinyFormat = true;
\r
1315 headerFlags = (ushort)(TinyFormat | ((ushort)codeSize << 2));
\r
1317 if ((codeSize % 4) != 0) { paddingNeeded = 4 - (codeSize % 4); }
\r
1319 //Console.WriteLine("Fat Header");
\r
1320 tinyFormat = false;
\r
1321 localSigIx = locSigIx;
\r
1322 this.maxStack = (short)maxStack;
\r
1323 headerFlags = FatFormat;
\r
1324 if (exceptions != null) {
\r
1325 // Console.WriteLine("Got exceptions");
\r
1326 headerFlags |= MoreSects;
\r
1327 uint numExceptClauses = 0;
\r
1328 for (int i=0; i < exceptions.Count; i++) {
\r
1329 TryBlock tryBlock = (TryBlock)exceptions[i];
\r
1330 tryBlock.SetSize();
\r
1331 numExceptClauses += (uint)tryBlock.NumHandlers();
\r
1332 if (tryBlock.isFat()) fatExceptionFormat = true;
\r
1334 // Console.WriteLine("numexceptclauses = " + numExceptClauses);
\r
1335 if (fatExceptionFormat) {
\r
1336 // Console.WriteLine("Fat exception format");
\r
1337 exceptHeader = FatExceptTable;
\r
1338 exceptSize = ExHeaderSize + numExceptClauses * FatExClauseSize;
\r
1340 // Console.WriteLine("Tiny exception format");
\r
1341 exceptHeader = SmlExceptTable;
\r
1342 exceptSize = ExHeaderSize + numExceptClauses * SmlExClauseSize;
\r
1344 // Console.WriteLine("exceptSize = " + exceptSize);
\r
1346 if (initLocals) headerFlags |= InitLocals;
\r
1347 if ((offset % 4) != 0) { paddingNeeded = 4 - (offset % 4); }
\r
1348 codeSize += FatSize;
\r
1350 // Console.WriteLine("codeSize = " + codeSize + " headerFlags = " +
\r
1351 // Hex.Short(headerFlags));
\r
1354 internal void Write(FileImage output) {
\r
1355 // Console.WriteLine("Writing header flags = " + Hex.Short(headerFlags));
\r
1357 // Console.WriteLine("Writing tiny code");
\r
1358 output.Write((byte)headerFlags);
\r
1360 // Console.WriteLine("Writing fat code");
\r
1361 output.Write(headerFlags);
\r
1362 output.Write((ushort)maxStack);
\r
1363 output.Write(offset);
\r
1364 output.Write(localSigIx);
\r
1366 // Console.WriteLine(Hex.Int(tide) + " CIL instructions");
\r
1367 // Console.WriteLine("starting instructions at " + output.Seek(0,SeekOrigin.Current));
\r
1368 for (int i=0; i < tide; i++) {
\r
1369 buffer[i].Write(output);
\r
1371 // Console.WriteLine("ending instructions at " + output.Seek(0,SeekOrigin.Current));
\r
1372 for (int i=0; i < paddingNeeded; i++) { output.Write((byte)0); }
\r
1373 if (exceptions != null) {
\r
1374 // Console.WriteLine("Writing exceptions");
\r
1375 // Console.WriteLine("header = " + Hex.Short(exceptHeader) + " exceptSize = " + Hex.Int(exceptSize));
\r
1376 output.Write(exceptHeader);
\r
1377 output.Write3Bytes((uint)exceptSize);
\r
1378 for (int i=0; i < exceptions.Count; i++) {
\r
1379 TryBlock tryBlock = (TryBlock)exceptions[i];
\r
1380 tryBlock.Write(output,fatExceptionFormat);
\r
1386 /**************************************************************************/
\r
1388 /// A label in the IL
\r
1390 public class CILLabel
\r
1392 CILInstruction branch;
\r
1393 CILInstruction[] multipleBranches;
\r
1395 CILInstruction labInstr;
\r
1398 public CILLabel (uint offset) {
\r
1399 this.offset = offset;
\r
1403 internal CILLabel() {
\r
1406 internal void AddBranch(CILInstruction instr) {
\r
1407 if (branch == null) {
\r
1411 if (multipleBranches == null) {
\r
1412 multipleBranches = new CILInstruction[2];
\r
1413 } else if (tide >= multipleBranches.Length) {
\r
1414 CILInstruction[] tmp = multipleBranches;
\r
1415 multipleBranches = new CILInstruction[tmp.Length*2];
\r
1416 for (int i=0; i < tide; i++) {
\r
1417 multipleBranches[i] = tmp[i];
\r
1420 multipleBranches[tide++] = instr;
\r
1423 internal void AddLabelInstr(LabelInstr lInstr) {
\r
1424 labInstr = lInstr;
\r
1427 internal uint GetLabelOffset() {
\r
1428 if (labInstr == null) return 0;
\r
1429 return labInstr.offset + offset;
\r
1433 /**************************************************************************/
\r
1434 public abstract class CodeBlock {
\r
1436 private static readonly int maxCodeSize = 256;
\r
1437 protected CILLabel start, end;
\r
1438 protected bool small = true;
\r
1440 public CodeBlock(CILLabel start, CILLabel end) {
\r
1441 this.start = start;
\r
1445 internal virtual bool isFat() {
\r
1446 // Console.WriteLine("block start = " + start.GetLabelOffset() +
\r
1447 // " block end = " + end.GetLabelOffset());
\r
1448 return (end.GetLabelOffset() - start.GetLabelOffset()) > maxCodeSize;
\r
1451 internal virtual void Write(FileImage output, bool fatFormat) {
\r
1452 if (fatFormat) output.Write(start.GetLabelOffset());
\r
1453 else output.Write((short)start.GetLabelOffset());
\r
1454 uint len = end.GetLabelOffset() - start.GetLabelOffset();
\r
1455 if (fatFormat) output.Write(len);
\r
1456 else output.Write((byte)len);
\r
1462 /// The descriptor for a guarded block (.try)
\r
1464 public class TryBlock : CodeBlock {
\r
1465 protected bool fatFormat = false;
\r
1466 protected int flags = 0;
\r
1467 ArrayList handlers = new ArrayList();
\r
1470 /// Create a new try block
\r
1472 /// <param name="start">start label for the try block</param>
\r
1473 /// <param name="end">end label for the try block</param>
\r
1474 public TryBlock(CILLabel start, CILLabel end) : base(start,end) { }
\r
1477 /// Add a handler to this try block
\r
1479 /// <param name="handler">a handler to be added to the try block</param>
\r
1480 public void AddHandler(HandlerBlock handler) {
\r
1481 flags = handler.GetFlag();
\r
1482 handlers.Add(handler);
\r
1485 internal void SetSize() {
\r
1486 fatFormat = base.isFat();
\r
1487 if (fatFormat) return;
\r
1488 for (int i=0; i < handlers.Count; i++) {
\r
1489 HandlerBlock handler = (HandlerBlock)handlers[i];
\r
1490 if (handler.isFat()) {
\r
1497 internal int NumHandlers() {
\r
1498 return handlers.Count;
\r
1501 internal override bool isFat() {
\r
1505 internal override void Write(FileImage output, bool fatFormat) {
\r
1506 // Console.WriteLine("writing exception details");
\r
1507 for (int i=0; i < handlers.Count; i++) {
\r
1508 // Console.WriteLine("Except block " + i);
\r
1509 HandlerBlock handler = (HandlerBlock)handlers[i];
\r
1510 if (fatFormat) output.Write(flags);
\r
1511 else output.Write((short)flags);
\r
1512 // Console.WriteLine("flags = " + Hex.Short(flags));
\r
1513 base.Write(output,fatFormat);
\r
1514 handler.Write(output,fatFormat);
\r
1519 public abstract class HandlerBlock : CodeBlock
\r
1521 protected static readonly short ExceptionFlag = 0;
\r
1522 protected static readonly short FilterFlag = 0x01;
\r
1523 protected static readonly short FinallyFlag = 0x02;
\r
1524 protected static readonly short FaultFlag = 0x04;
\r
1526 public HandlerBlock(CILLabel start, CILLabel end) : base(start,end) { }
\r
1528 internal virtual short GetFlag() { return ExceptionFlag; }
\r
1530 internal override void Write(FileImage output, bool fatFormat) {
\r
1531 base.Write(output,fatFormat);
\r
1537 /// The descriptor for a catch clause (.catch)
\r
1539 public class Catch : HandlerBlock
\r
1544 /// Create a new catch clause
\r
1546 /// <param name="except">the exception to be caught</param>
\r
1547 /// <param name="handlerStart">start of the handler code</param>
\r
1548 /// <param name="handlerEnd">end of the handler code</param>
\r
1549 public Catch(Class except, CILLabel handlerStart, CILLabel handlerEnd)
\r
1550 : base(handlerStart,handlerEnd) {
\r
1551 exceptType = except;
\r
1554 internal override void Write(FileImage output, bool fatFormat) {
\r
1555 base.Write(output,fatFormat);
\r
1556 output.Write(exceptType.Token());
\r
1561 /// The descriptor for a filter clause (.filter)
\r
1563 public class Filter : HandlerBlock
\r
1565 CILLabel filterLabel;
\r
1568 /// Create a new filter clause
\r
1570 /// <param name="filterLabel">the label where the filter code starts</param>
\r
1571 /// <param name="handlerStart">the start of the handler code</param>
\r
1572 /// <param name="handlerEnd">the end of the handler code</param>
\r
1573 public Filter(CILLabel filterLabel, CILLabel handlerStart,
\r
1574 CILLabel handlerEnd) : base(handlerStart,handlerEnd) {
\r
1575 this.filterLabel = filterLabel;
\r
1578 internal override short GetFlag() {
\r
1579 return FilterFlag;
\r
1582 internal override void Write(FileImage output, bool fatFormat) {
\r
1583 base.Write(output,fatFormat);
\r
1584 output.Write(filterLabel.GetLabelOffset());
\r
1590 /// Descriptor for a finally block (.finally)
\r
1592 public class Finally : HandlerBlock
\r
1595 /// Create a new finally clause
\r
1597 /// <param name="finallyStart">start of finally code</param>
\r
1598 /// <param name="finallyEnd">end of finally code</param>
\r
1599 public Finally(CILLabel finallyStart, CILLabel finallyEnd)
\r
1600 : base(finallyStart,finallyEnd) { }
\r
1602 internal override short GetFlag() {
\r
1603 return FinallyFlag;
\r
1606 internal override void Write(FileImage output, bool fatFormat) {
\r
1607 base.Write(output,fatFormat);
\r
1608 output.Write((int)0);
\r
1614 /// Descriptor for a fault block (.fault)
\r
1616 public class Fault : HandlerBlock
\r
1619 /// Create a new fault clause
\r
1621 /// <param name="faultStart">start of the fault code</param>
\r
1622 /// <param name="faultEnd">end of the fault code</param>
\r
1623 public Fault(CILLabel faultStart, CILLabel faultEnd)
\r
1624 : base(faultStart,faultEnd) { }
\r
1626 internal override short GetFlag() {
\r
1627 return FaultFlag;
\r
1630 internal override void Write(FileImage output, bool fatFormat) {
\r
1631 base.Write(output,fatFormat);
\r
1632 output.Write((int)0);
\r
1637 /**************************************************************************/
\r
1639 /// The base descriptor for a class
\r
1641 public abstract class Class : Type
\r
1643 protected int row = 0;
\r
1644 protected string name, nameSpace;
\r
1645 protected uint nameIx, nameSpaceIx;
\r
1646 protected MetaData _metaData;
\r
1647 internal Class(string nameSpaceName, string className, MetaData md)
\r
1649 nameSpace = nameSpaceName;
\r
1651 nameIx = md.AddToStringsHeap(name);
\r
1652 nameSpaceIx = md.AddToStringsHeap(nameSpace);
\r
1656 internal Class(uint nsIx, uint nIx) : base(0x12) {
\r
1657 nameSpaceIx = nsIx;
\r
1661 internal virtual uint TypeDefOrRefToken() { return 0; }
\r
1663 internal virtual void MakeValueClass() {
\r
1667 internal virtual string TypeName() {
\r
1668 return (nameSpace + "." + name);
\r
1671 internal override MetaDataElement GetTypeSpec(MetaData md) {
\r
1675 /**************************************************************************/
\r
1676 // This Class produces entries in the TypeDef table of the MetaData
\r
1677 // in the PE meta data.
\r
1679 // NOTE: Entry 0 in TypeDef table is always the pseudo class <module>
\r
1680 // which is the parent for functions and variables declared a module level
\r
1683 /// The descriptor for a class defined in the IL (.class) in the current assembly/module
\r
1686 public class ClassDef : Class
\r
1688 private static readonly uint HasSecurity = 0x00040000;
\r
1689 private static readonly byte ElementType_Class = 0x12;
\r
1692 ArrayList fields = new ArrayList();
\r
1693 ArrayList methods = new ArrayList();
\r
1695 ArrayList properties;
\r
1696 bool typeIndexChecked = true;
\r
1697 uint fieldIx = 0, methodIx = 0;
\r
1698 byte[] securityActions;
\r
1700 ClassLayout layout;
\r
1701 ClassDef parentClass;
\r
1702 MetaData metaData;
\r
1704 internal ClassDef(TypeAttr attrSet, string nsName, string name,
\r
1705 MetaData md) : base(nsName, name, md) {
\r
1707 superType = metaData.mscorlib.GetSpecialSystemClass(PrimitiveType.Object);
\r
1708 flags = (uint)attrSet;
\r
1709 tabIx = MDTable.TypeDef;
\r
1712 internal void SetSuper(Class sClass) {
\r
1713 superType = sClass;
\r
1714 if (sClass is ClassRef)
\r
1715 typeIndex = superType.GetTypeIndex();
\r
1717 typeIndexChecked = false;
\r
1720 internal override void MakeValueClass() {
\r
1721 superType = metaData.mscorlib.ValueType();
\r
1722 typeIndex = superType.GetTypeIndex();
\r
1725 public void SpecialNoSuper() {
\r
1730 /// Add an attribute to this class
\r
1732 /// <param name="ta">the attribute to be added</param>
\r
1733 public void AddAttribute(TypeAttr ta) {
\r
1734 flags |= (uint)ta;
\r
1738 /// Add an interface that is implemented by this class
\r
1740 /// <param name="iFace">the interface that is implemented</param>
\r
1741 public void AddImplementedInterface(Class iFace) {
\r
1742 metaData.AddToTable(MDTable.InterfaceImpl,new InterfaceImpl(this,iFace));
\r
1746 /// Add a named generic type parameter
\r
1748 public GenericParameter AddGenericParameter (short index, string name) {
\r
1749 GenericParameter gp = new GenericParameter (this, metaData, index, name);
1750 metaData.AddToTable (MDTable.GenericParam, gp);
\r
1755 /// Add a field to this class
\r
1757 /// <param name="name">field name</param>
\r
1758 /// <param name="fType">field type</param>
\r
1759 /// <returns>a descriptor for this new field</returns>
\r
1760 public FieldDef AddField(string name, Type fType) {
\r
1761 FieldDef field = new FieldDef(name,fType);
\r
1762 fields.Add(field);
\r
1767 /// Add a field to this class
\r
1769 /// <param name="fAtts">attributes for this field</param>
\r
1770 /// <param name="name">field name</param>
\r
1771 /// <param name="fType">field type</param>
\r
1772 /// <returns>a descriptor for this new field</returns>
\r
1773 public FieldDef AddField(FieldAttr fAtts, string name, Type fType) {
\r
1774 FieldDef field = new FieldDef(fAtts,name,fType);
\r
1775 fields.Add(field);
\r
1780 /// Add a method to this class
\r
1782 /// <param name="name">method name</param>
\r
1783 /// <param name="retType">return type</param>
\r
1784 /// <param name="pars">parameters</param>
\r
1785 /// <returns>a descriptor for this new method</returns>
\r
1786 public MethodDef AddMethod(string name, Type retType, Param[] pars) {
\r
1787 // Console.WriteLine("Adding method " + name + " to class " + this.name);
\r
1788 MethodDef meth = new MethodDef(metaData,name,retType, pars);
\r
1789 methods.Add(meth);
\r
1794 /// Add a method to this class
\r
1796 /// <param name="mAtts">attributes for this method</param>
\r
1797 /// <param name="iAtts">implementation attributes for this method</param>
\r
1798 /// <param name="name">method name</param>
\r
1799 /// <param name="retType">return type</param>
\r
1800 /// <param name="pars">parameters</param>
\r
1801 /// <returns>a descriptor for this new method</returns>
\r
1802 public MethodDef AddMethod(MethAttr mAtts, ImplAttr iAtts, string name,
\r
1803 Type retType, Param[] pars) {
\r
1804 // Console.WriteLine("Adding method " + name + " to class " + this.name);
\r
1805 MethodDef meth = new MethodDef(metaData,mAtts,iAtts,name,retType,pars);
\r
1806 methods.Add(meth);
\r
1811 /// Add an event to this class
\r
1813 /// <param name="name">event name</param>
\r
1814 /// <param name="eType">event type</param>
\r
1815 /// <returns>a descriptor for this new event</returns>
\r
1816 public Event AddEvent(string name, Type eType) {
\r
1817 Event e = new Event(name,eType,this);
\r
1818 if (events == null) events = new ArrayList();
\r
1824 /// Add a property to this class
\r
1826 /// <param name="name">property name</param>
\r
1827 /// <param name="propType">property type</param>
\r
1828 /// <returns>a descriptor for this new property</returns>
\r
1829 public Property AddProperty(string name, Type retType, Type[] pars) {
\r
1830 Property p = new Property(name, retType, pars, this);
\r
1831 if (properties == null) properties = new ArrayList();
\r
1832 properties.Add(p);
\r
1838 /// Add a nested class to this class
\r
1840 /// <param name="attrSet">attributes for this nested class</param>
\r
1841 /// <param name="nsName">nested name space name</param>
\r
1842 /// <param name="name">nested class name</param>
\r
1843 /// <returns>a descriptor for this new nested class</returns>
\r
1844 public ClassDef AddNestedClass(TypeAttr attrSet, string nsName,
\r
1846 ClassDef nClass = new ClassDef(attrSet,nsName,name,metaData);
\r
1847 metaData.AddToTable(MDTable.TypeDef,nClass);
\r
1848 metaData.AddToTable(MDTable.NestedClass,new MapElem(nClass,Row,MDTable.TypeDef));
\r
1849 nClass.parentClass = this;
\r
1854 /// Add a nested class to this class
\r
1856 /// <param name="attrSet">attributes for this nested class</param>
\r
1857 /// <param name="nsName">nested name space name</param>
\r
1858 /// <param name="name">nested class name</param>
\r
1859 /// <param name="sType">super type of this nested class</param>
\r
1860 /// <returns>a descriptor for this new nested class</returns>
\r
1861 public ClassDef AddNestedClass(TypeAttr attrSet, string nsName,
\r
1862 string name, Class sType) {
\r
1863 ClassDef nClass = new ClassDef(attrSet,nsName,name,metaData);
\r
1864 nClass.SetSuper(sType);
\r
1865 metaData.AddToTable(MDTable.TypeDef,nClass);
\r
1866 metaData.AddToTable(MDTable.NestedClass,
\r
1867 new MapElem(nClass,Row,MDTable.TypeDef));
\r
1868 nClass.parentClass = this;
\r
1873 /// Add layout information for this class. This class must have the
\r
1874 /// sequential or explicit attribute.
\r
1876 /// <param name="packSize">packing size (.pack)</param>
\r
1877 /// <param name="classSize">class size (.size)</param>
\r
1878 public void AddLayoutInfo (int packSize, int classSize) {
\r
1879 layout = new ClassLayout(packSize,classSize,this);
\r
1883 /// Use a method as the implementation for another method (.override)
\r
1885 /// <param name="decl">the method to be overridden</param>
\r
1886 /// <param name="body">the implementation to be used</param>
\r
1887 public void AddMethodOverride(Method decl, Method body) {
\r
1888 metaData.AddToTable(MDTable.MethodImpl,new MethodImpl(this,decl,body));
\r
1892 /// Add security to this class NOT YET IMPLEMENTED
\r
1894 /// <param name="permissionSet"></param>
\r
1895 public void AddSecurity(byte[] permissionSet) {
\r
1896 throw(new NotYetImplementedException("Class security "));
\r
1897 //flags |= HasSecurity;
\r
1898 // securityActions = permissionSet;
\r
1901 //public void AddLineInfo(int row, int col) { }
\r
1903 internal void CheckTypeIndex() {
\r
1904 if (typeIndexChecked) return;
\r
1905 if (!(superType is ClassRef))
\r
1906 ((ClassDef)superType).CheckTypeIndex();
\r
1907 typeIndex = superType.GetTypeIndex();
\r
1908 typeIndexChecked = true;
\r
1911 internal sealed override void BuildTables(MetaData md) {
\r
1913 if ((flags & (uint)TypeAttr.Interface) != 0) { superType = null; }
\r
1914 // Console.WriteLine("Building tables for " + name);
\r
1915 if (layout != null) md.AddToTable(MDTable.ClassLayout,layout);
\r
1916 // Console.WriteLine("adding methods " + methods.Count);
\r
1917 methodIx = md.TableIndex(MDTable.Method);
\r
1918 for (int i=0; i < methods.Count; i++) {
\r
1919 md.AddToTable(MDTable.Method,(MetaDataElement)methods[i]);
\r
1920 ((MethodDef)methods[i]).BuildTables(md);
\r
1922 // Console.WriteLine("adding fields");
\r
1923 fieldIx = md.TableIndex(MDTable.Field);
\r
1924 for (int i=0; i < fields.Count; i++) {
\r
1925 md.AddToTable(MDTable.Field,(MetaDataElement)fields[i]);
\r
1926 ((FieldDef)fields[i]).BuildTables(md);
\r
1928 // Console.WriteLine("adding events and properties");
\r
1929 if (events != null) {
\r
1930 for (int i=0; i < events.Count; i++) {
\r
1931 md.AddToTable(MDTable.Event,(Event)events[i]);
\r
1932 ((Event)events[i]).BuildTables(md);
\r
1934 md.AddToTable(MDTable.EventMap,
\r
1935 new MapElem(this,((Event)events[0]).Row,MDTable.Event));
\r
1937 if (properties != null) {
\r
1938 for (int i=0; i < properties.Count; i++) {
\r
1939 md.AddToTable(MDTable.Property,(Property)properties[i]);
\r
1940 ((Property)properties[i]).BuildTables(md);
\r
1942 md.AddToTable(MDTable.PropertyMap,new MapElem(this,
\r
1943 ((Property)properties[0]).Row,MDTable.Property));
\r
1945 DoCustomAttributes (md);
\r
1946 // Console.WriteLine("End of building tables");
\r
1950 internal sealed override uint Size(MetaData md) {
\r
1951 return 4 + 2 * md.StringsIndexSize() +
\r
1952 md.CodedIndexSize(CIx.TypeDefOrRef) +
\r
1953 md.TableIndexSize(MDTable.Field) +
\r
1954 md.TableIndexSize(MDTable.Method);
\r
1957 internal sealed override void Write(FileImage output) {
\r
1958 output.Write(flags);
\r
1959 output.StringsIndex(nameIx);
\r
1960 output.StringsIndex(nameSpaceIx);
\r
1961 //if (superType != null)
\r
1962 // Console.WriteLine("getting coded index for superType of " + name + " = " + superType.GetCodedIx(CIx.TypeDefOrRef));
\r
1963 output.WriteCodedIndex(CIx.TypeDefOrRef,superType);
\r
1964 output.WriteIndex(MDTable.Field,fieldIx);
\r
1965 output.WriteIndex(MDTable.Method,methodIx);
\r
1968 internal sealed override uint TypeDefOrRefToken() {
\r
1974 internal sealed override void TypeSig(MemoryStream sig) {
\r
1975 if (!typeIndexChecked) CheckTypeIndex();
\r
1976 sig.WriteByte(GetTypeIndex());
\r
1977 MetaData.CompressNum(TypeDefOrRefToken(),sig);
\r
1980 internal sealed override uint GetCodedIx(CIx code) {
\r
1982 case (CIx.TypeDefOrRef) : return 0;
\r
1983 case (CIx.HasCustomAttr) : return 3;
\r
1984 case (CIx.HasDeclSecurity) : return 0;
\r
1985 case (CIx.TypeOrMethodDef) : return 0;
\r
1991 /**************************************************************************/
\r
1993 /// Layout information for a class (.class [sequential | explicit])
\r
1995 internal class ClassLayout : MetaDataElement
\r
1998 ushort packSize = 0;
\r
1999 uint classSize = 0;
\r
2001 internal ClassLayout(int pack, int cSize, ClassDef par) {
\r
2002 packSize = (ushort)pack;
\r
2003 classSize = (uint)cSize;
\r
2005 tabIx = MDTable.ClassLayout;
\r
2008 internal sealed override uint Size(MetaData md) {
\r
2009 return 6 + md.TableIndexSize(MDTable.TypeDef);
\r
2012 internal sealed override void Write(FileImage output) {
\r
2013 output.Write(packSize);
\r
2014 output.Write(classSize);
\r
2015 output.WriteIndex(MDTable.TypeDef,parent.Row);
\r
2019 /**************************************************************************/
\r
2021 /// Descriptor for a class/interface declared in another module of THIS
\r
2022 /// assembly, or in another assembly.
\r
2024 public class ClassRef : Class
\r
2026 protected ResolutionScope parent;
\r
2027 ExternClass externClass;
\r
2028 protected MetaData metaData;
\r
2030 internal ClassRef(string nsName, string name, MetaData md) : base(nsName, name, md) {
\r
2032 tabIx = MDTable.TypeRef;
\r
2036 /// Add a method to this class
\r
2038 /// <param name="name">method name</param>
\r
2039 /// <param name="retType">return type</param>
\r
2040 /// <param name="pars">parameter types</param>
\r
2041 /// <returns>a descriptor for this method</returns>
\r
2042 public MethodRef AddMethod(string name, Type retType, Type[] pars) {
\r
2043 MethodRef meth = new MethodRef(this,name,retType,pars,false,null);
\r
2044 metaData.AddToTable(MDTable.MemberRef,meth);
\r
2049 /// Add a method to this class
\r
2051 /// <param name="name">method name</param>
\r
2052 /// <param name="retType">return type</param>
\r
2053 /// <param name="pars">parameter types</param>
\r
2054 /// <returns>a descriptor for this method</returns>
\r
2055 public MethodRef AddVarArgMethod(string name, Type retType,
\r
2056 Type[] pars, Type[] optPars) {
\r
2057 MethodRef meth = new MethodRef(this,name,retType,pars,true,optPars);
\r
2058 metaData.AddToTable(MDTable.MemberRef,meth);
\r
2063 /// Add a field to this class
\r
2065 /// <param name="name">field name</param>
\r
2066 /// <param name="fType">field type</param>
\r
2067 /// <returns>a descriptor for this field</returns>
\r
2068 public FieldRef AddField(string name, Type fType) {
\r
2069 FieldRef field = new FieldRef(this,name,fType);
\r
2070 metaData.AddToTable(MDTable.MemberRef,field);
\r
2074 internal void SetParent(ResolutionScope par) {
\r
2078 internal override string TypeName() {
\r
2079 if ((parent != null) && (parent is AssemblyRef))
\r
2080 return (nameSpace + "." + name + ", " + ((AssemblyRef)parent).TypeName());
\r
2082 return (nameSpace + name);
\r
2085 internal sealed override uint Size(MetaData md) {
\r
2086 return md.CodedIndexSize(CIx.ResolutionScope) + 2 *
\r
2087 md.StringsIndexSize();
\r
2090 internal sealed override void Write(FileImage output) {
\r
2091 output.WriteCodedIndex(CIx.ResolutionScope,parent);
\r
2092 output.StringsIndex(nameIx);
\r
2093 output.StringsIndex(nameSpaceIx);
\r
2096 internal override sealed uint TypeDefOrRefToken() {
\r
2098 cIx = (cIx << 2) | 0x1;
\r
2102 internal override void TypeSig(MemoryStream sig) {
\r
2103 sig.WriteByte(GetTypeIndex());
\r
2104 MetaData.CompressNum(TypeDefOrRefToken(),sig);
\r
2107 internal sealed override uint GetCodedIx(CIx code) {
\r
2109 case (CIx.TypeDefOrRef) : return 1;
\r
2110 case (CIx.HasCustomAttr) : return 2;
\r
2111 case (CIx.MemberRefParent) : return 1;
\r
2112 case (CIx.ResolutionScope) : return 3;
\r
2118 /**************************************************************************/
\r
2120 public class ExternClassRef : ClassRef {
\r
2122 ExternClass externClass;
\r
2124 internal ExternClassRef(TypeAttr attrs, string nsName, string name,
\r
2125 FileRef declFile, MetaData md) : base(nsName,name,md) {
\r
2126 externClass = new ExternClass(attrs,nameSpaceIx,nameIx,declFile);
\r
2127 metaData.AddToTable(MDTable.ExportedType,externClass);
\r
2130 internal ExternClassRef(string name, MetaData md) : base(null,name,md) {
\r
2133 public ClassRef AddNestedClass(TypeAttr attrs, string name) {
\r
2134 ExternClassRef nestedClass = new ExternClassRef(name,metaData);
\r
2135 externClass = new ExternClass(attrs,0,nameIx,this.externClass);
\r
2136 metaData.AddToTable(MDTable.ExportedType,externClass);
\r
2137 return nestedClass;
\r
2141 /**************************************************************************/
\r
2143 /// Descriptor for a constant value
\r
2145 public abstract class Constant {
\r
2146 protected uint size = 0;
\r
2147 protected Type type;
\r
2148 protected uint blobIndex;
\r
2149 protected bool addedToBlobHeap = false;
\r
2151 internal Constant() { }
\r
2153 internal virtual uint GetBlobIndex(MetaData md) { return 0; }
\r
2155 internal uint GetSize() { return size; }
\r
2157 internal byte GetTypeIndex() { return type.GetTypeIndex(); }
\r
2159 internal virtual void Write(BinaryWriter bw) { }
\r
2163 /// Descriptor for a constant value
\r
2165 public abstract class DataConstant : Constant {
\r
2166 private uint dataOffset = 0;
\r
2168 internal DataConstant() { }
\r
2170 public uint DataOffset {
\r
2171 get { return dataOffset; }
\r
2172 set { dataOffset = value; }
\r
2178 /// Boolean constant
\r
2180 public class BoolConst : Constant {
\r
2184 /// Create a new boolean constant with the value "val"
\r
2186 /// <param name="val">value of this boolean constant</param>
\r
2187 public BoolConst(bool val) {
\r
2190 type = PrimitiveType.Boolean;
\r
2193 internal sealed override uint GetBlobIndex(MetaData md) {
\r
2194 if (!addedToBlobHeap) {
\r
2195 if (val) blobIndex = md.AddToBlobHeap((sbyte)1);
\r
2196 else blobIndex = md.AddToBlobHeap((sbyte)0);
\r
2197 addedToBlobHeap = true;
\r
2202 internal sealed override void Write(BinaryWriter bw) {
\r
2203 if (val) bw.Write((sbyte)1);
\r
2204 else bw.Write((sbyte)0);
\r
2209 public class ByteArrConst : DataConstant {
\r
2212 public ByteArrConst(byte[] val) {
\r
2214 size = (uint)val.Length;
\r
2217 internal sealed override uint GetBlobIndex(MetaData md) {
\r
2218 if (!addedToBlobHeap) {
\r
2219 blobIndex = md.AddToBlobHeap(val);
\r
2220 addedToBlobHeap = true;
\r
2225 internal sealed override void Write(BinaryWriter bw) {
\r
2231 public class CharConst : Constant {
\r
2234 public CharConst(char val) {
\r
2237 type = PrimitiveType.Char;
\r
2240 internal sealed override uint GetBlobIndex(MetaData md) {
\r
2241 if (!addedToBlobHeap) {
\r
2242 blobIndex = md.AddToBlobHeap(val);
\r
2243 addedToBlobHeap = true;
\r
2248 internal sealed override void Write(BinaryWriter bw) {
\r
2254 public class FloatConst : DataConstant {
\r
2257 public FloatConst(float val) {
\r
2260 type = PrimitiveType.Float32;
\r
2263 internal sealed override uint GetBlobIndex(MetaData md) {
\r
2264 if (!addedToBlobHeap) {
\r
2265 blobIndex = md.AddToBlobHeap(val);
\r
2266 addedToBlobHeap = true;
\r
2271 internal sealed override void Write(BinaryWriter bw) {
\r
2277 public class DoubleConst : DataConstant {
\r
2280 public DoubleConst(double val) {
\r
2283 type = PrimitiveType.Float64;
\r
2286 internal sealed override uint GetBlobIndex(MetaData md) {
\r
2287 if (!addedToBlobHeap) {
\r
2288 blobIndex = md.AddToBlobHeap(val);
\r
2289 addedToBlobHeap = true;
\r
2294 internal sealed override void Write(BinaryWriter bw) {
\r
2300 public class IntConst : DataConstant {
\r
2303 public IntConst(sbyte val) {
\r
2306 type = PrimitiveType.Int8;
\r
2309 public IntConst(short val) {
\r
2312 type = PrimitiveType.Int16;
\r
2315 public IntConst(int val) {
\r
2318 type = PrimitiveType.Int32;
\r
2321 public IntConst(long val) {
\r
2324 type = PrimitiveType.Int64;
\r
2327 internal sealed override uint GetBlobIndex(MetaData md) {
\r
2328 if (!addedToBlobHeap) {
\r
2330 case (1) : blobIndex = md.AddToBlobHeap((sbyte)val); break;
\r
2331 case (2) : blobIndex = md.AddToBlobHeap((short)val); break;
\r
2332 case (4) : blobIndex = md.AddToBlobHeap((int)val); break;
\r
2333 default : blobIndex = md.AddToBlobHeap(val); break;
\r
2335 addedToBlobHeap = true;
\r
2340 internal sealed override void Write(BinaryWriter bw) {
\r
2342 case (1) : bw.Write((sbyte)val); break;
\r
2343 case (2) : bw.Write((short)val); break;
\r
2344 case (4) : bw.Write((int)val); break;
\r
2345 default : bw.Write(val); break;
\r
2351 public class UIntConst : Constant {
\r
2354 public UIntConst(sbyte val) {
\r
2357 type = PrimitiveType.UInt8;
\r
2359 public UIntConst(short val) {
\r
2362 type = PrimitiveType.UInt16;
\r
2364 public UIntConst(int val) {
\r
2367 type = PrimitiveType.UInt32;
\r
2369 public UIntConst(long val) {
\r
2372 type = PrimitiveType.UInt64;
\r
2375 internal sealed override uint GetBlobIndex(MetaData md) {
\r
2376 if (!addedToBlobHeap) {
\r
2378 case (1) : blobIndex = md.AddToBlobHeap((sbyte)val); break;
\r
2379 case (2) : blobIndex = md.AddToBlobHeap((short)val); break;
\r
2380 case (4) : blobIndex = md.AddToBlobHeap((int)val); break;
\r
2381 default : blobIndex = md.AddToBlobHeap(val); break;
\r
2383 addedToBlobHeap = true;
\r
2388 internal sealed override void Write(BinaryWriter bw) {
\r
2390 case (1) : bw.Write((sbyte)val); break;
\r
2391 case (2) : bw.Write((short)val); break;
\r
2392 case (4) : bw.Write((int)val); break;
\r
2393 default : bw.Write(val); break;
\r
2399 public class StringConst : DataConstant {
\r
2402 public StringConst(string val) {
\r
2404 size = (uint)val.Length; // need to add null ??
\r
2405 type = PrimitiveType.String;
\r
2408 internal sealed override uint GetBlobIndex(MetaData md) {
\r
2409 if (!addedToBlobHeap) {
\r
2410 blobIndex = md.AddToBlobHeap(val);
\r
2411 addedToBlobHeap = true;
\r
2416 internal sealed override void Write(BinaryWriter bw) {
\r
2422 public class NullConst : Constant {
\r
2424 public NullConst() {
\r
2426 type = PrimitiveType.Class;
\r
2429 internal sealed override uint GetBlobIndex(MetaData md) {
\r
2430 if (!addedToBlobHeap) {
\r
2431 blobIndex = md.AddToBlobHeap((int)0);
\r
2432 addedToBlobHeap = true;
\r
2437 internal sealed override void Write(BinaryWriter bw) {
\r
2438 bw.Write((int)0);
\r
2443 public class AddressConstant : DataConstant {
\r
2444 DataConstant data;
\r
2446 public AddressConstant(DataConstant dConst) {
\r
2449 type = PrimitiveType.TypedRef;
\r
2452 internal sealed override void Write(BinaryWriter bw) {
\r
2453 ((FileImage)bw).WriteDataRVA(data.DataOffset);
\r
2458 public class RepeatedConstant : DataConstant {
\r
2459 DataConstant data;
\r
2462 public RepeatedConstant(DataConstant dConst, int repeatCount) {
\r
2464 repCount = (uint)repeatCount;
\r
2465 int[] sizes = new int[1];
\r
2466 sizes[0] = repeatCount;
\r
2467 type = new BoundArray(type,1,sizes);
\r
2468 size = data.GetSize() * repCount;
\r
2471 internal sealed override void Write(BinaryWriter bw) {
\r
2472 for (int i=0; i < repCount; i++) {
\r
2479 public class ArrayConstant : DataConstant {
\r
2480 DataConstant[] dataVals;
\r
2482 public ArrayConstant(DataConstant[] dVals) {
\r
2484 for (int i=0; i < dataVals.Length; i++) {
\r
2485 size += dataVals[i].GetSize();
\r
2489 internal sealed override void Write(BinaryWriter bw) {
\r
2490 for (int i=0; i < dataVals.Length; i++) {
\r
2491 dataVals[i].Write(bw);
\r
2497 public class ClassType : Constant {
\r
2501 public ClassType(string className) {
\r
2503 type = PrimitiveType.ClassType;
\r
2506 public ClassType(Class classDesc) {
\r
2508 type = PrimitiveType.ClassType;
\r
2511 internal override void Write(BinaryWriter bw) {
\r
2512 if (name == null) name = desc.TypeName();
\r
2520 /**************************************************************************/
\r
2522 /// Summary description for ConstantElem.
\r
2524 internal class ConstantElem : MetaDataElement
\r
2526 MetaDataElement parent;
\r
2530 internal ConstantElem(MetaDataElement parent, Constant val) {
\r
2531 this.parent = parent;
\r
2533 tabIx = MDTable.Constant;
\r
2536 internal sealed override void BuildTables(MetaData md) {
\r
2538 valIx = cValue.GetBlobIndex(md);
\r
2542 internal void AddToBlob(BinaryWriter bw) {
\r
2546 internal sealed override uint Size(MetaData md) {
\r
2547 return 2 + md.CodedIndexSize(CIx.HasConst) + md.BlobIndexSize();
\r
2550 internal sealed override void Write(FileImage output) {
\r
2551 output.Write(cValue.GetTypeIndex());
\r
2552 output.Write((byte)0);
\r
2553 output.WriteCodedIndex(CIx.HasConst,parent);
\r
2554 output.BlobIndex(valIx);
\r
2558 /**************************************************************************/
\r
2560 /// Descriptor for a Custom Attribute (.custom)
\r
2563 public class CustomAttribute : MetaDataElement
\r
2565 private static readonly ushort prolog = 0x0001;
\r
2566 MetaDataElement parent;
\r
2571 ushort numNamed = 0;
\r
2572 ArrayList names, vals;
\r
2574 internal CustomAttribute(MetaDataElement paren, Method constrType,
\r
2577 type = constrType;
\r
2579 tabIx = MDTable.CustomAttribute;
\r
2580 throw(new NotYetImplementedException("Custom Attributes "));
\r
2583 internal CustomAttribute(MetaDataElement paren, Method constrType,
\r
2586 type = constrType;
\r
2587 tabIx = MDTable.CustomAttribute;
\r
2591 public void AddFieldOrProp(string name, Constant val) {
\r
2592 if (numNamed == 0) {
\r
2593 names = new ArrayList();
\r
2594 vals = new ArrayList();
\r
2600 internal sealed override void BuildTables(MetaData md) {
\r
2601 BinaryWriter bw = new BinaryWriter(new MemoryStream());
\r
2602 bw.Write((ushort)1);
\r
2603 md.AddToTable(MDTable.CustomAttribute, this);
\r
2604 MemoryStream str = (MemoryStream)bw.BaseStream;
\r
2605 valIx = md.AddToBlobHeap(str.ToArray());
\r
2608 internal sealed override uint Size(MetaData md) {
\r
2609 return md.CodedIndexSize(CIx.HasCustomAttr) + md.CodedIndexSize(CIx.CustomAttributeType) + md.BlobIndexSize();
\r
2612 internal sealed override void Write(FileImage output) {
\r
2613 output.WriteCodedIndex(CIx.HasCustomAttr,parent);
\r
2614 output.WriteCodedIndex(CIx.CustomAttributeType,type);
\r
2615 output.BlobIndex(valIx);
\r
2619 /**************************************************************************/
\r
2621 /// Descriptor for a custom modifier of a type (modopt or modreq)
\r
2624 public class CustomModifiedType : Type
\r
2630 /// Create a new custom modifier for a type
\r
2632 /// <param name="type">the type to be modified</param>
\r
2633 /// <param name="cmod">the modifier</param>
\r
2634 /// <param name="cmodType">the type reference to be associated with the type</param>
\r
2635 public CustomModifiedType(Type type, CustomModifier cmod, Class cmodType)
\r
2636 : base((byte)cmod) {
\r
2638 this.cmodType = cmodType;
\r
2641 internal sealed override void TypeSig(MemoryStream str) {
\r
2642 str.WriteByte(typeIndex);
\r
2643 MetaData.CompressNum(cmodType.TypeDefOrRefToken(),str);
\r
2644 type.TypeSig(str);
\r
2648 /**************************************************************************/
\r
2650 /// Descriptor for security permissions for a class or a method NOT YET IMPLEMENTED
\r
2653 public class DeclSecurity : MetaDataElement
\r
2656 MetaDataElement parent;
\r
2657 uint permissionIx;
\r
2659 internal DeclSecurity(MetaDataElement paren, ushort act) {
\r
2662 tabIx = MDTable.DeclSecurity;
\r
2663 throw(new NotYetImplementedException("Security "));
\r
2666 internal sealed override uint Size(MetaData md) {
\r
2667 return 2 + md.CodedIndexSize(CIx.HasDeclSecurity) + md.BlobIndexSize();
\r
2670 internal sealed override void BuildTables(MetaData md) {
\r
2672 // add permission to blob heap
\r
2676 internal sealed override void Write(FileImage output) {
\r
2677 output.Write(action);
\r
2678 output.WriteCodedIndex(CIx.HasDeclSecurity,parent);
\r
2679 output.BlobIndex(permissionIx);
\r
2683 /**************************************************************************/
\r
2685 /// Descriptor for an event
\r
2687 public class Event : Feature
\r
2691 internal Event(string name, Type eType, ClassDef parent)
\r
2692 : base(name, parent) {
\r
2693 eventType = eType;
\r
2694 tabIx = MDTable.Event;
\r
2698 /// Add the addon method to this event
\r
2700 /// <param name="addon">the addon method</param>
\r
2701 public void AddAddon(MethodDef addon) {
\r
2702 AddMethod(addon,MethodType.AddOn);
\r
2706 /// Add the removeon method to this event
\r
2708 /// <param name="removeOn">the removeon method</param>
\r
2709 public void AddRemoveOn(MethodDef removeOn) {
\r
2710 AddMethod(removeOn,MethodType.RemoveOn);
\r
2714 /// Add the fire method to this event
\r
2716 /// <param name="fire">the fire method</param>
\r
2717 public void AddFire(MethodDef fire) {
\r
2718 AddMethod(fire,MethodType.Fire);
\r
2722 /// Add another method to this event
\r
2724 /// <param name="other">the method to be added</param>
\r
2725 public void AddOther(MethodDef other) {
\r
2726 AddMethod(other,MethodType.Other);
\r
2729 internal sealed override void BuildTables(MetaData md) {
\r
2731 nameIx = md.AddToStringsHeap(name);
\r
2732 for (int i=0; i < tide; i++) {
\r
2733 md.AddToTable(MDTable.MethodSemantics,methods[i]);
\r
2738 internal sealed override uint Size(MetaData md) {
\r
2739 return 2 + md.StringsIndexSize() + md.CodedIndexSize(CIx.TypeDefOrRef);
\r
2742 internal sealed override void Write(FileImage output) {
\r
2743 output.Write(flags);
\r
2744 output.StringsIndex(nameIx);
\r
2745 output.WriteCodedIndex(CIx.TypeDefOrRef,eventType);
\r
2748 internal sealed override uint GetCodedIx(CIx code) {
\r
2750 case (CIx.HasCustomAttr) : return 10;
\r
2751 case (CIx.HasSemantics) : return 0;
\r
2757 /**************************************************************************/
\r
2759 /// Descriptor for a class defined in another module of THIS assembly
\r
2760 /// and exported (.class extern)
\r
2763 internal class ExternClass : Class
\r
2765 MetaDataElement parent;
\r
2768 internal ExternClass(TypeAttr attr, uint nsIx, uint nIx,
\r
2769 MetaDataElement paren) : base(nsIx,nIx) {
\r
2770 flags = (uint)attr;
\r
2772 tabIx = MDTable.ExportedType;
\r
2775 internal sealed override uint Size(MetaData md) {
\r
2776 return 8 + 2* md.StringsIndexSize() + md.CodedIndexSize(CIx.Implementation);
\r
2779 internal sealed override void Write(FileImage output) {
\r
2780 output.Write(flags);
\r
2782 output.StringsIndex(nameIx);
\r
2783 output.StringsIndex(nameSpaceIx);
\r
2784 output.WriteCodedIndex(CIx.Implementation,parent);
\r
2787 internal sealed override uint GetCodedIx(CIx code) {
\r
2789 case (CIx.HasCustomAttr) : return 17;
\r
2790 case (CIx.Implementation) : return 2;
\r
2796 /**************************************************************************/
\r
2798 /// Base class for Event and Property descriptors
\r
2801 public class Feature : MetaDataElement
\r
2803 internal enum MethodType : ushort { Setter = 0x01, Getter, Other = 0x04, AddOn = 0x08,
\r
2804 RemoveOn = 0x10, Fire = 0x20 }
\r
2806 private static readonly int INITSIZE = 5;
\r
2807 private static readonly ushort specialName = 0x200;
\r
2808 private static readonly ushort rtSpecialName = 0x400;
\r
2810 protected ClassDef parent;
\r
2811 protected ushort flags = 0;
\r
2812 protected string name;
\r
2813 protected int tide = 0;
\r
2814 protected uint nameIx;
\r
2815 protected MethodSemantics[] methods = new MethodSemantics[INITSIZE];
\r
2817 internal Feature(string name, ClassDef par) {
\r
2822 internal void AddMethod(MethodDef meth, MethodType mType) {
\r
2823 if (tide >= methods.Length) {
\r
2824 int len = methods.Length;
\r
2825 MethodSemantics[] mTmp = methods;
\r
2826 methods = new MethodSemantics[len * 2];
\r
2827 for (int i=0; i < len; i++) {
\r
2828 methods[i] = mTmp[i];
\r
2831 methods[tide++] = new MethodSemantics(mType,meth,this);
\r
2835 /// Set the specialName attribute for this Event or Property
\r
2837 public void SetSpecialName() {
\r
2838 flags |= specialName;
\r
2842 /// Set the RTSpecialName attribute for this Event or Property
\r
2844 public void SetRTSpecialName() {
\r
2845 flags |= rtSpecialName;
\r
2849 /*****************************************************************************/
\r
2851 /// Descriptor for a field of a class
\r
2854 public abstract class Field : Member
\r
2856 protected static readonly byte FieldSig = 0x6;
\r
2858 protected Type type;
\r
2860 internal Field(string pfName, Type pfType) : base(pfName)
\r
2866 /**************************************************************************/
\r
2868 /// Descriptor for a field defined in a class of THIS assembly/module
\r
2870 public class FieldDef : Field
\r
2872 //private static readonly uint PInvokeImpl = 0x2000;
\r
2873 private static readonly ushort HasFieldMarshal = 0x1000;
\r
2874 private static readonly ushort HasFieldRVA = 0x100;
\r
2877 ConstantElem constVal;
\r
2878 FieldLayout layout;
\r
2879 FieldMarshal marshalInfo;
\r
2882 internal FieldDef(string name, Type fType) : base(name,fType) {
\r
2883 tabIx = MDTable.Field;
\r
2886 internal FieldDef(FieldAttr attrSet, string name, Type fType) : base(name, fType) {
\r
2887 flags = (ushort)attrSet;
\r
2888 tabIx = MDTable.Field;
\r
2892 /// Add an attribute(s) to this field
\r
2894 /// <param name="fa">the attribute(s) to be added</param>
\r
2895 public void AddFieldAttr(FieldAttr fa) {
\r
2896 flags |= (ushort)fa;
\r
2900 /// Add a value for this field
\r
2902 /// <param name="val">the value for the field</param>
\r
2903 public void AddValue(Constant val) {
\r
2904 constVal = new ConstantElem(this,val);
\r
2908 /// Add an initial value for this field (at dataLabel) (.data)
\r
2910 /// <param name="val">the value for the field</param>
\r
2911 /// <param name="repeatVal">the number of repetitions of this value</param>
\r
2912 public void AddDataValue(DataConstant val) {
\r
2913 flags |= HasFieldRVA;
\r
2914 rva = new FieldRVA(this,val);
\r
2918 /// Set the offset of the field. Used for sequential or explicit classes.
\r
2919 /// (.field [offs])
\r
2921 /// <param name="offs">field offset</param>
\r
2922 public void SetOffset(uint offs) {
\r
2923 layout = new FieldLayout(this,offs);
\r
2927 /// Set the marshalling info for a field
\r
2929 /// <param name="mInf"></param>
\r
2930 public void SetMarshalInfo(NativeType marshallType) {
\r
2931 flags |= HasFieldMarshal;
\r
2932 marshalInfo = new FieldMarshal(this,marshallType);
\r
2935 internal sealed override void BuildTables(MetaData md) {
\r
2937 nameIx = md.AddToStringsHeap(name);
\r
2938 MemoryStream sig = new MemoryStream();
\r
2939 sig.WriteByte(FieldSig);
\r
2940 type.TypeSig(sig);
\r
2941 sigIx = md.AddToBlobHeap(sig.ToArray());
\r
2942 if (rva != null) {
\r
2943 md.AddToTable(MDTable.FieldRVA,rva);
\r
2944 rva.BuildTables(md);
\r
2945 } else if (constVal != null) {
\r
2946 md.AddToTable(MDTable.Constant,constVal);
\r
2947 constVal.BuildTables(md);
\r
2949 if (layout != null) md.AddToTable(MDTable.FieldLayout,layout);
\r
2950 if (marshalInfo != null) {
\r
2951 md.AddToTable(MDTable.FieldMarshal,marshalInfo);
\r
2952 marshalInfo.BuildTables(md);
\r
2957 internal sealed override uint Size(MetaData md) {
\r
2958 return 2 + md.StringsIndexSize() + md.BlobIndexSize();
\r
2961 internal sealed override void Write(FileImage output) {
\r
2962 output.Write(flags);
\r
2963 output.StringsIndex(nameIx);
\r
2964 output.BlobIndex(sigIx);
\r
2967 internal sealed override uint GetCodedIx(CIx code) {
\r
2969 case (CIx.HasConst) : return 0;
\r
2970 case (CIx.HasCustomAttr) : return 1;
\r
2971 case (CIx.HasFieldMarshal) : return 0;
\r
2972 case (CIx.MemberForwarded) : return 0;
\r
2978 /**************************************************************************/
\r
2980 /// Descriptor for layout information for a field
\r
2983 public class FieldLayout : MetaDataElement
\r
2988 internal FieldLayout(Field field, uint offset) {
\r
2989 this.field = field;
\r
2990 this.offset = offset;
\r
2991 tabIx = MDTable.FieldLayout;
\r
2994 internal sealed override uint Size(MetaData md) {
\r
2995 return 4 + md.TableIndexSize(MDTable.Field);
\r
2998 internal sealed override void Write(FileImage output) {
\r
2999 output.Write(offset);
\r
3000 output.WriteIndex(MDTable.Field,field.Row);
\r
3004 /*****************************************************************************/
\r
3006 /// Marshalling information for a field or param
\r
3008 public class FieldMarshal : MetaDataElement
\r
3010 MetaDataElement field;
\r
3014 internal FieldMarshal(MetaDataElement field, NativeType nType) {
\r
3015 this.field = field;
\r
3017 tabIx = MDTable.FieldMarshal;
\r
3020 internal sealed override void BuildTables(MetaData md) {
\r
3022 ntIx = md.AddToBlobHeap(nt.ToBlob());
\r
3026 internal sealed override uint Size(MetaData md) {
\r
3027 return md.CodedIndexSize(CIx.HasFieldMarshal) + md.BlobIndexSize();
\r
3030 internal sealed override void Write(FileImage output) {
\r
3031 output.WriteCodedIndex(CIx.HasFieldMarshal,field);
\r
3032 output.BlobIndex(ntIx);
\r
3036 /**************************************************************************/
\r
3038 /// Descriptor for a field of a class defined in another assembly/module
\r
3040 public class FieldRef : Field
\r
3042 MetaDataElement parent;
\r
3044 internal FieldRef(MetaDataElement paren, string name, Type fType) : base(name, fType) {
\r
3048 internal sealed override void BuildTables(MetaData md) {
\r
3050 nameIx = md.AddToStringsHeap(name);
\r
3051 MemoryStream sig = new MemoryStream();
\r
3052 sig.WriteByte(FieldSig);
\r
3053 type.TypeSig(sig);
\r
3054 sigIx = md.AddToBlobHeap(sig.ToArray());
\r
3058 internal sealed override uint Size(MetaData md) {
\r
3059 return md.CodedIndexSize(CIx.MemberRefParent) + md.StringsIndexSize() + md.BlobIndexSize();
\r
3062 internal sealed override void Write(FileImage output) {
\r
3063 output.WriteCodedIndex(CIx.MemberRefParent,parent);
\r
3064 output.StringsIndex(nameIx);
\r
3065 output.BlobIndex(sigIx);
\r
3068 internal sealed override uint GetCodedIx(CIx code) { return 6; }
\r
3071 /**************************************************************************/
\r
3073 /// Descriptor for the address of a field's value in the PE file
\r
3075 public class FieldRVA : MetaDataElement
\r
3078 DataConstant data;
\r
3080 internal FieldRVA(Field field, DataConstant data) {
\r
3081 this.field = field;
\r
3083 tabIx = MDTable.FieldRVA;
\r
3086 internal sealed override void BuildTables(MetaData md) {
\r
3092 internal sealed override uint Size(MetaData md) {
\r
3093 return 4 + md.TableIndexSize(MDTable.Field);
\r
3096 internal sealed override void Write(FileImage output) {
\r
3097 output.WriteDataRVA(data.DataOffset);
\r
3098 output.WriteIndex(MDTable.Field,field.Row);
\r
3102 /**************************************************************************/
\r
3104 /// Image for a PEFile
\r
3105 /// File Structure
\r
3106 /// DOS Header (128 bytes)
\r
3107 /// PE Signature ("PE\0\0")
\r
3108 /// PEFileHeader (20 bytes)
\r
3109 /// PEOptionalHeader (224 bytes)
\r
3110 /// SectionHeaders (40 bytes * NumSections)
\r
3112 /// Sections .text (always present - contains metadata)
\r
3113 /// .sdata (contains any initialised data in the file - may not be present)
\r
3114 /// (for ilams /debug this contains the Debug table)
\r
3115 /// .reloc (always present - in pure CIL only has one fixup)
\r
3116 /// others??? c# produces .rsrc section containing a Resource Table
\r
3119 /// IAT (single entry 8 bytes for pure CIL)
\r
3120 /// CLIHeader (72 bytes)
\r
3121 /// CIL instructions for all methods (variable size)
\r
3123 /// Root (20 bytes + UTF-8 Version String + quad align padding)
\r
3124 /// StreamHeaders (8 bytes + null terminated name string + quad align padding)
\r
3126 /// #~ (always present - holds metadata tables)
\r
3127 /// #Strings (always present - holds identifier strings)
\r
3128 /// #US (Userstring heap)
\r
3129 /// #Blob (signature blobs)
\r
3130 /// #GUID (guids for assemblies or Modules)
\r
3131 /// ImportTable (40 bytes)
\r
3132 /// ImportLookupTable(8 bytes) (same as IAT for standard CIL files)
\r
3133 /// Hint/Name Tables with entry "_CorExeMain" for .exe file and "_CorDllMain" for .dll (14 bytes)
\r
3134 /// ASCII string "mscoree.dll" referenced in ImportTable (+ padding = 16 bytes)
\r
3135 /// Entry Point (0xFF25 followed by 4 bytes 0x400000 + RVA of .text)
\r
3137 /// #~ stream structure
\r
3138 /// Header (24 bytes)
\r
3139 /// Rows (4 bytes * numTables)
\r
3142 internal class FileImage : BinaryWriter
\r
3144 internal readonly static uint[] iByteMask = {0x000000FF, 0x0000FF00, 0x00FF0000, 0xFF000000};
\r
3145 internal readonly static ulong[] lByteMask = {0x00000000000000FF, 0x000000000000FF00,
\r
3146 0x0000000000FF0000, 0x00000000FF000000,
\r
3147 0x000000FF00000000, 0x0000FF0000000000,
\r
3148 0x00FF000000000000, 0xFF00000000000000 };
\r
3149 internal readonly static uint nibble0Mask = 0x0000000F;
\r
3150 internal readonly static uint nibble1Mask = 0x000000F0;
\r
3152 private static readonly byte[] DOSHeader = { 0x4d,0x5a,0x90,0x00,0x03,0x00,0x00,0x00,
\r
3153 0x04,0x00,0x00,0x00,0xff,0xff,0x00,0x00,
\r
3154 0xb8,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
\r
3155 0x40,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
\r
3156 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
\r
3157 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
\r
3158 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
\r
3159 0x00,0x00,0x00,0x00,0x80,0x00,0x00,0x00,
\r
3160 0x0e,0x1f,0xba,0x0e,0x00,0xb4,0x09,0xcd,
\r
3161 0x21,0xb8,0x01,0x4c,0xcd,0x21,0x54,0x68,
\r
3162 0x69,0x73,0x20,0x70,0x72,0x6f,0x67,0x72,
\r
3163 0x61,0x6d,0x20,0x63,0x61,0x6e,0x6e,0x6f,
\r
3164 0x74,0x20,0x62,0x65,0x20,0x72,0x75,0x6e,
\r
3165 0x20,0x69,0x6e,0x20,0x44,0x4f,0x53,0x20,
\r
3166 0x6d,0x6f,0x64,0x65,0x2e,0x0d,0x0d,0x0a,
\r
3167 0x24,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
\r
3168 0x50,0x45,0x00,0x00};
\r
3169 private static byte[] PEHeader = { 0x4c, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
\r
3170 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
\r
3171 0xE0, 0x00, 0x0E, 0x01, // PE Header Standard Fields
\r
3172 0x0B, 0x01, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00,
\r
3173 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
\r
3174 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
\r
3177 private static readonly uint minFileAlign = 0x200;
\r
3178 private static readonly uint maxFileAlign = 0x1000;
\r
3179 private static readonly uint fileHeaderSize = 0x178;
\r
3180 private static readonly uint sectionHeaderSize = 40;
\r
3181 private static readonly uint SectionAlignment = 0x2000;
\r
3182 private static readonly uint ImageBase = 0x400000;
\r
3183 private static readonly uint ImportTableSize = 40;
\r
3184 private static readonly uint IATSize = 8;
\r
3185 private static readonly uint CLIHeaderSize = 72;
\r
3186 private uint runtimeFlags = 0x01; // COMIMAGE_FLAGS_ILONLY
\r
3187 // 32BITREQUIRED 0x02, STRONGNAMESIGNED 0x08, TRACKDEBUGDATA 0x10000
\r
3188 private static readonly uint relocFlags = 0x42000040;
\r
3189 private static readonly ushort exeCharacteristics = 0x010E;
\r
3190 private static readonly ushort dllCharacteristics = 0x210E;
\r
3191 // section names are all 8 bytes
\r
3192 private static readonly string textName = ".text\0\0\0";
\r
3193 private static readonly string sdataName = ".sdata\0\0";
\r
3194 private static readonly string relocName = ".reloc\0\0";
\r
3195 private static readonly string rsrcName = ".rsrc\0\0\0";
\r
3196 private static readonly string exeHintNameTable = "\0\0_CorExeMain\0";
\r
3197 private static readonly string dllHintNameTable = "\0\0_CorDllMain\0";
\r
3198 private static readonly string runtimeEngineName = "mscoree.dll\0\0";
\r
3200 private Section text, sdata, rsrc;
\r
3202 BinaryWriter reloc = new BinaryWriter(new MemoryStream());
\r
3203 uint dateStamp = 0;
\r
3204 DateTime origin = new DateTime(1970,1,1);
\r
3205 uint numSections = 2; // always have .text and .reloc sections
\r
3206 internal SubSystem subSys = SubSystem.Windows_CUI; // default is Windows Console mode
\r
3207 internal uint fileAlign = minFileAlign;
\r
3208 uint entryPointOffset, entryPointPadding, imageSize, headerSize, headerPadding, entryPointToken = 0;
\r
3209 uint relocOffset, relocRVA, relocSize, relocPadding, relocTide, hintNameTableOffset;
\r
3210 uint metaDataOffset, runtimeEngineOffset, initDataSize = 0, importTablePadding;
\r
3211 uint importTableOffset, importLookupTableOffset, totalImportTableSize;
\r
3212 MetaData metaData;
\r
3213 char[] runtimeEngine = runtimeEngineName.ToCharArray(), hintNameTable;
\r
3214 bool doDLL, largeStrings, largeGUID, largeUS, largeBlob;
\r
3215 ushort characteristics;
\r
3217 internal FileImage(bool makeDLL, string fileName) : base(new FileStream(fileName,FileMode.Create)) {
\r
3218 InitFileImage(makeDLL);
\r
3219 TimeSpan tmp = System.IO.File.GetCreationTime(fileName).Subtract(origin);
\r
3220 dateStamp = Convert.ToUInt32(tmp.TotalSeconds);
\r
3223 internal FileImage(bool makeDLL, Stream str) : base(str) {
\r
3224 InitFileImage(makeDLL);
\r
3225 TimeSpan tmp = DateTime.Now.Subtract(origin);
\r
3226 dateStamp = Convert.ToUInt32(tmp.TotalSeconds);
\r
3229 private void InitFileImage(bool makeDLL) {
\r
3232 hintNameTable = dllHintNameTable.ToCharArray();
\r
3233 characteristics = dllCharacteristics;
\r
3235 hintNameTable = exeHintNameTable.ToCharArray();
\r
3236 characteristics = exeCharacteristics;
\r
3238 text = new Section(textName,0x60000020); // IMAGE_SCN_CNT CODE, EXECUTE, READ
\r
3239 // rsrc = new Section(rsrcName,0x40000040); // IMAGE_SCN_CNT INITIALIZED_DATA, READ
\r
3240 metaData = new MetaData(this);
\r
3243 internal MetaData GetMetaData() {
\r
3247 private uint GetNextSectStart(uint rva, uint tide) {
\r
3248 if (tide < SectionAlignment) return rva + SectionAlignment;
\r
3249 return rva + ((tide / SectionAlignment) + 1) * SectionAlignment;
\r
3252 private void BuildTextSection() {
\r
3254 // IAT (single entry 8 bytes for pure CIL)
\r
3255 // CLIHeader (72 bytes)
\r
3256 // CIL instructions for all methods (variable size)
\r
3258 // ImportTable (40 bytes)
\r
3259 // ImportLookupTable(8 bytes) (same as IAT for standard CIL files)
\r
3260 // Hint/Name Tables with entry "_CorExeMain" for .exe file and "_CorDllMain" for .dll (14 bytes)
\r
3261 // ASCII string "mscoree.dll" referenced in ImportTable (+ padding = 16 bytes)
\r
3262 // Entry Point (0xFF25 followed by 4 bytes 0x400000 + RVA of .text)
\r
3263 metaData.BuildMetaData(IATSize + CLIHeaderSize);
\r
3264 metaDataOffset = IATSize + CLIHeaderSize;
\r
3265 // Console.WriteLine("Code starts at " + metaDataOffset);
\r
3266 metaDataOffset += metaData.CodeSize();
\r
3267 // resourcesStart =
\r
3268 // strongNameSig = metaData.GetStrongNameSig();
\r
3269 // fixUps = RVA for vtable
\r
3270 importTableOffset = metaDataOffset + metaData.Size();
\r
3271 importTablePadding = NumToAlign(importTableOffset,16);
\r
3272 importTableOffset += importTablePadding;
\r
3273 importLookupTableOffset = importTableOffset + ImportTableSize;
\r
3274 hintNameTableOffset = importLookupTableOffset + IATSize;
\r
3275 runtimeEngineOffset = hintNameTableOffset + (uint)hintNameTable.Length;
\r
3276 entryPointOffset = runtimeEngineOffset + (uint)runtimeEngine.Length;
\r
3277 totalImportTableSize = entryPointOffset - importTableOffset;
\r
3278 // Console.WriteLine("total import table size = " + totalImportTableSize);
\r
3279 // Console.WriteLine("entrypoint offset = " + entryPointOffset);
\r
3280 entryPointPadding = NumToAlign(entryPointOffset,4) + 2;
\r
3281 entryPointOffset += entryPointPadding;
\r
3282 text.AddReloc(entryPointOffset+2);
\r
3283 text.IncTide(entryPointOffset + 6);
\r
3284 //if (text.Tide() < fileAlign) fileAlign = minFileAlign;
\r
3285 text.SetSize(NumToAlign(text.Tide(),fileAlign));
\r
3286 // Console.WriteLine("text size = " + text.Size() + " text tide = " + text.Tide() + " text padding = " + text.Padding());
\r
3287 // Console.WriteLine("metaDataOffset = " + Hex.Int(metaDataOffset));
\r
3288 // Console.WriteLine("importTableOffset = " + Hex.Int(importTableOffset));
\r
3289 // Console.WriteLine("importLookupTableOffset = " + Hex.Int(importLookupTableOffset));
\r
3290 // Console.WriteLine("hintNameTableOffset = " + Hex.Int(hintNameTableOffset));
\r
3291 // Console.WriteLine("runtimeEngineOffset = " + Hex.Int(runtimeEngineOffset));
\r
3292 // Console.WriteLine("entryPointOffset = " + Hex.Int(entryPointOffset));
\r
3293 // Console.WriteLine("entryPointPadding = " + Hex.Int(entryPointPadding));
\r
3297 internal void BuildRelocSection() {
\r
3298 text.DoRelocs(reloc);
\r
3299 if (sdata != null) sdata.DoRelocs(reloc);
\r
3300 if (rsrc != null) rsrc.DoRelocs(reloc);
\r
3301 relocTide = (uint)reloc.Seek(0,SeekOrigin.Current);
\r
3302 relocPadding = NumToAlign(relocTide,fileAlign);
\r
3303 relocSize = relocTide + relocPadding;
\r
3304 imageSize = relocRVA + SectionAlignment;
\r
3305 initDataSize += relocSize;
\r
3308 private void CalcOffsets() {
\r
3313 headerSize = fileHeaderSize + (numSections * sectionHeaderSize);
\r
3314 headerPadding = NumToAlign(headerSize,fileAlign);
\r
3315 headerSize += headerPadding;
\r
3316 uint offset = headerSize;
\r
3317 uint rva = SectionAlignment;
\r
3318 text.SetOffset(offset);
\r
3320 offset += text.Size();
\r
3321 rva = GetNextSectStart(rva,text.Tide());
\r
3322 // Console.WriteLine("headerSize = " + headerSize);
\r
3323 // Console.WriteLine("headerPadding = " + headerPadding);
\r
3324 // Console.WriteLine("textOffset = " + Hex.Int(text.Offset()));
\r
3325 if (sdata != null) {
\r
3326 sdata.SetSize(NumToAlign(sdata.Tide(),fileAlign));
\r
3327 sdata.SetOffset(offset);
\r
3328 sdata.SetRVA(rva);
\r
3329 offset += sdata.Size();
\r
3330 rva = GetNextSectStart(rva,sdata.Tide());
\r
3331 initDataSize += sdata.Size();
\r
3333 if (rsrc != null) {
\r
3334 rsrc.SetSize(NumToAlign(rsrc.Tide(),fileAlign));
\r
3335 rsrc.SetOffset(offset);
\r
3337 offset += rsrc.Size();
\r
3338 rva = GetNextSectStart(rva,rsrc.Tide());
\r
3339 initDataSize += rsrc.Size();
\r
3341 relocOffset = offset;
\r
3345 internal void MakeFile() {
\r
3346 if (doDLL) hintNameTable = dllHintNameTable.ToCharArray();
\r
3347 else hintNameTable = exeHintNameTable.ToCharArray();
\r
3348 BuildTextSection();
\r
3350 BuildRelocSection();
\r
3351 // now write it out
\r
3358 private void WriteHeader() {
\r
3360 // Console.WriteLine("Writing PEHeader at offset " + Seek(0,SeekOrigin.Current));
\r
3362 // Console.WriteLine("Writing text section header at offset " + Hex.Long(Seek(0,SeekOrigin.Current)));
\r
3363 text.WriteHeader(this,relocRVA);
\r
3364 if (sdata != null) sdata.WriteHeader(this,relocRVA);
\r
3365 if (rsrc != null) rsrc.WriteHeader(this,relocRVA);
\r
3366 // Console.WriteLine("Writing reloc section header at offset " + Seek(0,SeekOrigin.Current));
\r
3367 WriteRelocSectionHeader();
\r
3368 // Console.WriteLine("Writing padding at offset " + Seek(0,SeekOrigin.Current));
\r
3369 WriteZeros(headerPadding);
\r
3372 private void WriteSections() {
\r
3373 // Console.WriteLine("Writing text section at offset " + Seek(0,SeekOrigin.Current));
\r
3374 WriteTextSection();
\r
3375 if (sdata != null) WriteSDataSection();
\r
3376 if (rsrc != null) WriteRsrcSection();
\r
3377 WriteRelocSection();
\r
3380 private void WriteIAT() {
\r
3381 Write(text.RVA() + hintNameTableOffset);
\r
3385 private void WriteImportTables() {
\r
3387 WriteZeros(importTablePadding);
\r
3388 // Console.WriteLine("Writing import tables at offset " + Hex.Long(Seek(0,SeekOrigin.Current)));
\r
3389 Write(importLookupTableOffset + text.RVA());
\r
3391 Write(runtimeEngineOffset + text.RVA());
\r
3392 Write(text.RVA()); // IAT is at the beginning of the text section
\r
3394 // Import Lookup Table
\r
3395 WriteIAT(); // lookup table and IAT are the same
\r
3396 // Hint/Name Table
\r
3397 // Console.WriteLine("Writing hintname table at " + Hex.Long(Seek(0,SeekOrigin.Current)));
\r
3398 Write(hintNameTable);
\r
3399 Write(runtimeEngineName.ToCharArray());
\r
3402 private void WriteTextSection() {
\r
3405 // Console.WriteLine("Writing code at " + Hex.Long(Seek(0,SeekOrigin.Current)));
\r
3406 metaData.WriteByteCodes(this);
\r
3407 // Console.WriteLine("Finished writing code at " + Hex.Long(Seek(0,SeekOrigin.Current)));
\r
3408 largeStrings = metaData.LargeStringsIndex();
\r
3409 largeGUID = metaData.LargeGUIDIndex();
\r
3410 largeUS = metaData.LargeUSIndex();
\r
3411 largeBlob = metaData.LargeBlobIndex();
\r
3412 metaData.WriteMetaData(this);
\r
3413 WriteImportTables();
\r
3414 WriteZeros(entryPointPadding);
\r
3415 Write((ushort)0x25FF);
\r
3416 Write(ImageBase + text.RVA());
\r
3417 WriteZeros(text.Padding());
\r
3420 private void WriteCLIHeader() {
\r
3421 Write(CLIHeaderSize); // Cb
\r
3422 Write((short)2); // Major runtime version
\r
3423 Write((short)0); // Minor runtime version
\r
3424 Write(text.RVA() + metaDataOffset);
\r
3425 Write(metaData.Size());
\r
3426 Write(runtimeFlags);
\r
3427 Write(entryPointToken);
\r
3428 WriteZeros(8); // Resources - used by Manifest Resources NYI
\r
3429 WriteZeros(8); // Strong Name stuff here!! NYI
\r
3430 WriteZeros(8); // CodeManagerTable
\r
3431 WriteZeros(8); // VTableFixups NYI
\r
3432 WriteZeros(16); // ExportAddressTableJumps, ManagedNativeHeader
\r
3435 private void WriteSDataSection() {
\r
3436 for (int i=0; i < data.Count; i++) {
\r
3437 ((DataConstant)data[i]).Write(this);
\r
3441 private void WriteRsrcSection() {
\r
3444 private void WriteRelocSection() {
\r
3445 // Console.WriteLine("Writing reloc section at " + Seek(0,SeekOrigin.Current) + " = " + relocOffset);
\r
3446 MemoryStream str = (MemoryStream)reloc.BaseStream;
\r
3447 Write(str.ToArray());
\r
3448 WriteZeros(NumToAlign((uint)str.Position,fileAlign));
\r
3451 internal void SetEntryPoint(uint entryPoint) {
\r
3452 entryPointToken = entryPoint;
\r
3455 internal void AddInitData(DataConstant cVal) {
\r
3456 if (sdata == null) {
\r
3457 sdata = new Section(sdataName,0xC0000040); // IMAGE_SCN_CNT INITIALIZED_DATA, READ, WRITE
\r
3458 data = new ArrayList();
\r
3461 cVal.DataOffset = sdata.Tide();
\r
3462 sdata.IncTide(cVal.GetSize());
\r
3465 internal void WriteZeros(uint numZeros) {
\r
3466 for (int i=0; i < numZeros; i++) {
\r
3471 internal void WritePEHeader() {
\r
3472 Write((ushort)0x014C); // Machine - always 0x14C for Managed PE Files (allow others??)
\r
3473 Write((ushort)numSections);
\r
3475 WriteZeros(8); // Pointer to Symbol Table and Number of Symbols (always zero for ECMA CLI files)
\r
3476 Write((ushort)0x00E0); // Size of Optional Header
\r
3477 Write(characteristics);
\r
3478 // PE Optional Header
\r
3479 Write((ushort)0x010B); // Magic
\r
3480 Write((byte)0x6); // LMajor pure-IL = 6 C++ = 7
\r
3481 Write((byte)0x0); // LMinor
\r
3482 Write(text.Size());
\r
3483 Write(initDataSize);
\r
3484 Write(0); // Check other sections here!!
\r
3485 Write(text.RVA() + entryPointOffset);
\r
3486 Write(text.RVA());
\r
3487 uint dataBase = 0;
\r
3488 if (sdata != null) dataBase = sdata.RVA();
\r
3489 else if (rsrc != null) dataBase = rsrc.RVA();
\r
3490 else dataBase = relocRVA;
\r
3493 Write(SectionAlignment);
\r
3495 Write((ushort)0x04); // OS Major
\r
3496 WriteZeros(6); // OS Minor, User Major, User Minor
\r
3497 Write((ushort)0x04); // SubSys Major
\r
3498 WriteZeros(6); // SybSys Minor, Reserved
\r
3500 Write(headerSize);
\r
3501 Write((int)0); // File Checksum
\r
3502 Write((ushort)subSys);
\r
3503 Write((short)0); // DLL Flags
\r
3504 Write((uint)0x100000); // Stack Reserve Size
\r
3505 Write((uint)0x1000); // Stack Commit Size
\r
3506 Write((uint)0x100000); // Heap Reserve Size
\r
3507 Write((uint)0x1000); // Heap Commit Size
\r
3508 Write(0); // Loader Flags
\r
3509 Write(0x10); // Number of Data Directories
\r
3510 WriteZeros(8); // Export Table
\r
3511 Write(importTableOffset + text.RVA());
\r
3512 Write(totalImportTableSize);
\r
3513 WriteZeros(24); // Resource, Exception and Certificate Tables
\r
3516 WriteZeros(48); // Debug, Copyright, Global Ptr, TLS, Load Config and Bound Import Tables
\r
3517 Write(text.RVA()); // IATRVA - IAT is at start of .text Section
\r
3519 WriteZeros(8); // Delay Import Descriptor
\r
3520 Write(text.RVA()+IATSize); // CLIHeader immediately follows IAT
\r
3521 Write(CLIHeaderSize);
\r
3522 WriteZeros(8); // Reserved
\r
3525 internal void WriteRelocSectionHeader() {
\r
3526 Write(relocName.ToCharArray());
\r
3530 Write(relocOffset);
\r
3532 Write(relocFlags);
\r
3535 private void Align (MemoryStream str, int val) {
\r
3536 if ((str.Position % val) != 0) {
\r
3537 for (int i=val - (int)(str.Position % val); i > 0; i--) {
\r
3543 private uint Align(uint val, uint alignVal) {
\r
3544 if ((val % alignVal) != 0) {
\r
3545 val += alignVal - (val % alignVal);
\r
3550 private uint NumToAlign(uint val, uint alignVal) {
\r
3551 if ((val % alignVal) == 0) return 0;
\r
3552 return alignVal - (val % alignVal);
\r
3555 internal void StringsIndex(uint ix) {
\r
3556 if (largeStrings) Write(ix);
\r
3557 else Write((ushort)ix);
\r
3560 internal void GUIDIndex(uint ix) {
\r
3561 if (largeGUID) Write(ix);
\r
3562 else Write((ushort)ix);
\r
3565 internal void USIndex(uint ix) {
\r
3566 if (largeUS) Write(ix);
\r
3567 else Write((ushort)ix);
\r
3570 internal void BlobIndex(uint ix) {
\r
3571 if (largeBlob) Write(ix);
\r
3572 else Write((ushort)ix);
\r
3575 internal void WriteIndex(MDTable tabIx,uint ix) {
\r
3576 if (metaData.LargeIx(tabIx)) Write(ix);
\r
3577 else Write((ushort)ix);
\r
3580 internal void WriteCodedIndex(CIx code, MetaDataElement elem) {
\r
3581 metaData.WriteCodedIndex(code,elem,this);
\r
3584 internal void WriteCodeRVA(uint offs) {
\r
3585 Write(text.RVA() + offs);
\r
3588 internal void WriteDataRVA(uint offs) {
\r
3589 Write(sdata.RVA() + offs);
\r
3592 internal void Write3Bytes(uint val) {
\r
3593 byte b3 = (byte)((val & FileImage.iByteMask[2]) >> 16);
\r
3594 byte b2 = (byte)((val & FileImage.iByteMask[1]) >> 8);;
\r
3595 byte b1 = (byte)(val & FileImage.iByteMask[0]);
\r
3602 /**************************************************************************/
\r
3604 /// Descriptor for a file referenced in THIS assembly/module (.file)
\r
3606 public class FileRef : MetaDataElement
\r
3608 private static readonly uint HasMetaData = 0x1;
\r
3609 uint nameIx = 0, hashIx = 0;
\r
3612 internal FileRef(string name, byte[] hashBytes, bool metaData,
\r
3613 bool entryPoint, MetaData md) {
\r
3614 if (metaData) flags = HasMetaData;
\r
3615 if (entryPoint) md.SetEntryPoint(this);
\r
3616 nameIx = md.AddToStringsHeap(name);
\r
3617 hashIx = md.AddToBlobHeap(hashBytes);
\r
3618 tabIx = MDTable.File;
\r
3621 internal FileRef(uint nameIx, byte[] hashBytes, bool metaData,
\r
3622 bool entryPoint, MetaData md) {
\r
3623 if (metaData) flags = HasMetaData;
\r
3624 if (entryPoint) md.SetEntryPoint(this);
\r
3625 this.nameIx = nameIx;
\r
3626 hashIx = md.AddToBlobHeap(hashBytes);
\r
3627 tabIx = MDTable.File;
\r
3630 internal sealed override uint Size(MetaData md) {
\r
3631 return 4 + md.StringsIndexSize() + md.BlobIndexSize();
\r
3634 internal sealed override void Write(FileImage output) {
\r
3635 output.Write(flags);
\r
3636 output.StringsIndex(nameIx);
\r
3637 output.BlobIndex(hashIx);
\r
3640 internal sealed override uint GetCodedIx(CIx code) {
\r
3642 case (CIx.HasCustomAttr) : return 16;
\r
3643 case (CIx.Implementation) : return 0;
\r
3649 /**************************************************************************/
\r
3651 /// Descriptor for pinvoke information for a method NOT YET IMPLEMENTED
\r
3653 public class ImplMap : MetaDataElement
\r
3655 private static readonly ushort NoMangle = 0x01;
\r
3658 string importName;
\r
3660 ModuleRef importScope;
\r
3662 internal ImplMap(ushort flag, Method implMeth, string iName, ModuleRef mScope) {
\r
3665 importName = iName;
\r
3666 importScope = mScope;
\r
3667 tabIx = MDTable.ImplMap;
\r
3668 if (iName == null) flags |= NoMangle;
\r
3669 //throw(new NotYetImplementedException("PInvoke "));
\r
3672 internal sealed override void BuildTables(MetaData md) {
\r
3674 iNameIx = md.AddToStringsHeap(importName);
\r
3678 internal sealed override uint Size(MetaData md) {
\r
3679 return 2+ md.CodedIndexSize(CIx.MemberForwarded) +
\r
3680 md.StringsIndexSize() + md.TableIndexSize(MDTable.ModuleRef);
\r
3683 internal sealed override void Write(FileImage output) {
\r
3684 output.Write(flags);
\r
3685 output.WriteCodedIndex(CIx.MemberForwarded,meth);
\r
3686 output.StringsIndex(iNameIx);
\r
3687 output.WriteIndex(MDTable.ModuleRef,importScope.Row);
\r
3692 /**************************************************************************/
\r
3694 /// Descriptor for an IL instruction
\r
3696 internal abstract class CILInstruction {
\r
3697 protected static readonly sbyte maxByteVal = 127;
\r
3698 protected static readonly sbyte minByteVal = -128;
\r
3699 protected static readonly byte leadByte = 0xFE;
\r
3700 protected static readonly uint USHeapIndex = 0x70000000;
\r
3701 protected static readonly int longInstrStart = (int)Op.arglist;
\r
3702 public bool twoByteInstr = false;
\r
3703 public uint size = 0;
\r
3704 public uint offset;
\r
3706 internal virtual bool Check(MetaData md) {
\r
3710 internal virtual void Write(FileImage output) { }
\r
3714 internal class CILByte : CILInstruction {
\r
3717 internal CILByte(byte bVal) {
\r
3722 internal override void Write(FileImage output) {
\r
3723 output.Write(byteVal);
\r
3729 internal class Instr : CILInstruction {
\r
3730 protected int instr;
\r
3732 internal Instr(int inst) {
\r
3733 if (inst >= longInstrStart) {
\r
3734 instr = inst - longInstrStart;
\r
3735 twoByteInstr = true;
\r
3743 internal override void Write(FileImage output) {
\r
3744 //Console.WriteLine("Writing instruction " + instr + " with size " + size);
\r
3745 if (twoByteInstr) output.Write(leadByte);
\r
3746 output.Write((byte)instr);
\r
3751 internal class IntInstr : Instr {
\r
3755 internal IntInstr(int inst, int num, bool byteSize) : base(inst) {
\r
3757 byteNum = byteSize;
\r
3758 if (byteNum) size++;
\r
3762 internal sealed override void Write(FileImage output) {
\r
3763 base.Write(output);
\r
3765 output.Write((sbyte)val);
\r
3767 output.Write(val);
\r
3772 internal class UIntInstr : Instr {
\r
3776 internal UIntInstr(int inst, int num, bool byteSize) : base(inst) {
\r
3778 byteNum = byteSize;
\r
3779 if (byteNum) size++;
\r
3783 internal sealed override void Write(FileImage output) {
\r
3784 base.Write(output);
\r
3786 output.Write((byte)val);
\r
3788 output.Write((ushort)val);
\r
3793 internal class LongInstr : Instr {
\r
3796 internal LongInstr(int inst, long l) : base(inst) {
\r
3801 internal sealed override void Write(FileImage output) {
\r
3802 base.Write(output);
\r
3803 output.Write(val);
\r
3808 internal class FloatInstr : Instr {
\r
3811 internal FloatInstr(int inst, float f) : base(inst) {
\r
3816 internal sealed override void Write(FileImage output) {
\r
3817 base.Write(output);
\r
3818 output.Write(fVal);
\r
3823 internal class DoubleInstr : Instr {
\r
3826 internal DoubleInstr(int inst, double d) : base(inst) {
\r
3831 internal sealed override void Write(FileImage output) {
\r
3832 base.Write(output);
\r
3833 output.Write(val);
\r
3838 internal class StringInstr : Instr {
\r
3842 internal StringInstr(int inst, string str) : base(inst) {
\r
3847 internal sealed override bool Check(MetaData md) {
\r
3848 strIndex = md.AddToUSHeap(val);
\r
3852 internal sealed override void Write(FileImage output) {
\r
3853 base.Write(output);
\r
3854 output.Write(USHeapIndex | strIndex);
\r
3859 internal class LabelInstr : CILInstruction {
\r
3862 internal LabelInstr(CILLabel lab) {
\r
3864 label.AddLabelInstr(this);
\r
3868 internal class FieldInstr : Instr {
\r
3871 internal FieldInstr(int inst, Field f) : base(inst) {
\r
3876 internal sealed override void Write(FileImage output) {
\r
3877 base.Write(output);
\r
3878 output.Write(field.Token());
\r
3883 internal class MethInstr : Instr {
\r
3886 internal MethInstr(int inst, Method m) : base(inst) {
\r
3891 internal sealed override void Write(FileImage output) {
\r
3892 base.Write(output);
\r
3893 output.Write(meth.Token());
\r
3898 internal class SigInstr : Instr {
\r
3899 CalliSig signature;
\r
3901 internal SigInstr(int inst, CalliSig sig) : base(inst) {
\r
3906 internal sealed override bool Check(MetaData md) {
\r
3907 md.AddToTable(MDTable.StandAloneSig,signature);
\r
3908 signature.BuildTables(md);
\r
3912 internal sealed override void Write(FileImage output) {
\r
3913 base.Write(output);
\r
3914 output.Write(signature.Token());
\r
3918 internal class TypeInstr : Instr {
\r
3919 MetaDataElement theType;
\r
3921 internal TypeInstr(int inst, Type aType, MetaData md) : base(inst) {
\r
3922 theType = aType.GetTypeSpec(md);
\r
3926 internal sealed override void Write(FileImage output) {
\r
3927 base.Write(output);
\r
3928 output.Write(theType.Token());
\r
3933 internal class BranchInstr : Instr {
\r
3935 private bool shortVer = true;
\r
3936 private static readonly byte longInstrOffset = 13;
\r
3937 private int target = 0;
\r
3939 internal BranchInstr(int inst, CILLabel dst) : base(inst) {
\r
3941 dest.AddBranch(this);
\r
3945 internal sealed override bool Check(MetaData md) {
\r
3946 target = (int)dest.GetLabelOffset() - (int)(offset + size);
\r
3947 if (shortVer && ((target < minByteVal) || (target > maxByteVal))) {
\r
3948 if (instr < (int)BranchOp.leave) instr += longInstrOffset;
\r
3957 internal sealed override void Write(FileImage output) {
\r
3958 base.Write(output);
\r
3960 output.Write((sbyte)target);
\r
3962 output.Write(target);
\r
3967 internal class SwitchInstr : Instr {
\r
3969 uint numCases = 0;
\r
3971 internal SwitchInstr(int inst, CILLabel[] dsts) : base(inst) {
\r
3973 if (cases != null) numCases = (uint)cases.Length;
\r
3974 size += 4 + (numCases * 4);
\r
3975 for (int i=0; i < numCases; i++) {
\r
3976 cases[i].AddBranch(this);
\r
3980 internal sealed override void Write(FileImage output) {
\r
3981 base.Write(output);
\r
3982 output.Write(numCases);
\r
3983 for (int i=0; i < numCases; i++) {
\r
3984 int target = (int)cases[i].GetLabelOffset() - (int)(offset + size);
\r
3985 output.Write(target);
\r
3990 /**************************************************************************/
\r
3992 public class GenericParameter : MetaDataElement
\r
3994 MetaDataElement owner;
4000 internal GenericParameter (ClassDef owner, MetaData metadata,
4001 short index, string name) : this (owner, metadata, index, name, true)
4005 internal GenericParameter (MethodDef owner, MetaData metadata,
4006 short index, string name) : this (owner, metadata, index, name, true)
4010 private GenericParameter (MetaDataElement owner, MetaData metadata,
4011 short index, string name, bool nadda)
4013 this.owner = owner;
\r
4014 this.metadata = metadata;
4015 this.index = index;
\r
4016 tabIx = MDTable.GenericParam;
\r
4020 public void AddConstraint (Type constraint) {
4021 metadata.AddToTable (MDTable.GenericParamConstraint,
\r
4022 new GenericParamConstraint (this, constraint));
\r
4025 internal sealed override uint Size(MetaData md) {
\r
4026 return (uint) (4 +
\r
4027 md.CodedIndexSize(CIx.TypeOrMethodDef) +
\r
4029 md.TableIndexSize(MDTable.TypeDef));
\r
4032 internal sealed override void BuildTables(MetaData md) {
\r
4034 nameIx = md.AddToStringsHeap(name);
\r
4038 internal sealed override void Write(FileImage output) {
\r
4039 output.Write ((short) index);
\r
4040 output.Write ((short) 0);
\r
4041 output.WriteCodedIndex(CIx.TypeOrMethodDef, owner);
\r
4042 output.Write ((uint) nameIx);
\r
4043 output.WriteIndex(MDTable.TypeDef,owner.Row);
\r
4049 internal class GenericParamConstraint : MetaDataElement
\r
4051 GenericParameter param;
\r
4054 public GenericParamConstraint (GenericParameter param, Type type) {
\r
4055 this.param = param;
\r
4057 tabIx = MDTable.GenericParamConstraint;
\r
4060 internal sealed override uint Size(MetaData md) {
\r
4061 return (uint) (md.TableIndexSize(MDTable.GenericParam) +
\r
4062 md.CodedIndexSize(CIx.TypeDefOrRef));
\r
4065 internal sealed override void Write(FileImage output) {
\r
4066 output.WriteIndex(MDTable.GenericParam, param.Row);
\r
4067 output.WriteCodedIndex(CIx.TypeDefOrRef, type);
\r
4073 internal class MethodSpec : MetaDataElement
4076 GenericMethodSig g_sig;
4079 internal MethodSpec (Method meth, GenericMethodSig g_sig) {
4082 tabIx = MDTable.MethodSpec;
4085 internal sealed override void BuildTables (MetaData md) {
4087 sidx = g_sig.GetSigIx (md);
4091 internal sealed override uint Size (MetaData md) {
4092 return (uint) (md.CodedIndexSize(CIx.MethodDefOrRef) +
4093 md.BlobIndexSize ());
4096 internal sealed override void Write (FileImage output) {
4097 output.WriteCodedIndex (CIx.MethodDefOrRef, meth);
4098 output.BlobIndex (sidx);
\r
4102 /**************************************************************************/
\r
4104 /// Descriptor for interface implemented by a class
\r
4106 public class InterfaceImpl: MetaDataElement
\r
4108 ClassDef theClass;
\r
4109 Class theInterface;
\r
4111 internal InterfaceImpl(ClassDef theClass, Class theInterface) {
\r
4112 this.theClass = theClass;
\r
4113 this.theInterface = theInterface;
\r
4114 tabIx = MDTable.InterfaceImpl;
\r
4117 internal sealed override uint Size(MetaData md) {
\r
4118 return md.TableIndexSize(MDTable.TypeDef) +
\r
4119 md.CodedIndexSize(CIx.TypeDefOrRef);
\r
4122 internal sealed override void Write(FileImage output) {
\r
4123 output.WriteIndex(MDTable.TypeDef,theClass.Row);
\r
4124 output.WriteCodedIndex(CIx.TypeDefOrRef,theInterface);
\r
4127 internal sealed override uint GetCodedIx(CIx code) { return 5; }
\r
4130 /**************************************************************************/
\r
4132 /// Descriptor for a local of a method
\r
4134 public class Local
\r
4136 private static readonly byte Pinned = 0x45;
\r
4139 bool pinned = false, byref = false;
\r
4142 /// Create a new local variable
\r
4144 /// <param name="lName">name of the local variable</param>
\r
4145 /// <param name="lType">type of the local variable</param>
\r
4146 public Local(string lName, Type lType) {
\r
4152 /// Create a new local variable that is byref and/or pinned
\r
4154 /// <param name="lName">local name</param>
\r
4155 /// <param name="lType">local type</param>
\r
4156 /// <param name="byRef">is byref</param>
\r
4157 /// <param name="isPinned">has pinned attribute</param>
\r
4158 public Local(string lName, Type lType, bool byRef, bool isPinned)
\r
4163 pinned = isPinned;
\r
4166 internal void TypeSig(MemoryStream str) {
\r
4167 if (pinned) str.WriteByte(Pinned);
\r
4168 type.TypeSig(str);
\r
4172 /**************************************************************************/
\r
4174 /// Descriptor for the locals for a method
\r
4177 public class LocalSig : Signature
\r
4179 private static readonly byte LocalSigByte = 0x7;
\r
4182 public LocalSig(Local[] locals) {
\r
4183 this.locals = locals;
\r
4184 tabIx = MDTable.StandAloneSig;
\r
4187 internal sealed override void BuildTables(MetaData md) {
\r
4189 MemoryStream sig = new MemoryStream();
\r
4190 sig.WriteByte(LocalSigByte);
\r
4191 MetaData.CompressNum((uint)locals.Length,sig);
\r
4192 for (int i=0; i < locals.Length; i++) {
\r
4193 ((Local)locals[i]).TypeSig(sig);
\r
4195 sigIx = md.AddToBlobHeap(sig.ToArray());
\r
4201 /**************************************************************************/
\r
4203 /// Descriptor for resources used in this PE file NOT YET IMPLEMENTED
\r
4206 public class ManifestResource : MetaDataElement
\r
4208 private static readonly uint PublicResource = 0x1;
\r
4209 private static readonly uint PrivateResource = 0x2;
\r
4212 MetaDataElement rRef;
\r
4217 public ManifestResource(string name, bool isPub, FileRef fileRef) {
\r
4219 if (isPub) flags = PublicResource;
\r
4220 else flags = PrivateResource;
\r
4222 tabIx = MDTable.ManifestResource;
\r
4223 throw(new NotYetImplementedException("Manifest Resources "));
\r
4226 public ManifestResource(string name, bool isPub, FileRef fileRef,
\r
4229 if (isPub) flags = PublicResource;
\r
4230 else flags = PrivateResource;
\r
4232 fileOffset = fileIx;
\r
4235 public ManifestResource(string name, bool isPub, AssemblyRef assemRef) {
\r
4237 if (isPub) flags = PublicResource;
\r
4238 else flags = PrivateResource;
\r
4242 internal sealed override void BuildTables(MetaData md) {
\r
4244 nameIx = md.AddToStringsHeap(mrName);
\r
4248 internal sealed override uint Size(MetaData md) {
\r
4249 return 8 + md.StringsIndexSize() +
\r
4250 md.CodedIndexSize(CIx.Implementation);
\r
4253 internal sealed override void Write(FileImage output) {
\r
4254 output.Write(fileOffset);
\r
4255 output.Write(flags);
\r
4256 output.StringsIndex(nameIx);
\r
4257 output.WriteCodedIndex(CIx.Implementation,rRef);
\r
4260 internal sealed override uint GetCodedIx(CIx code) { return 18; }
\r
4263 /**************************************************************************/
\r
4265 /// Base class for elements in the PropertyMap, EventMap and
\r
4266 /// NestedClass MetaData tables
\r
4268 public class MapElem : MetaDataElement
\r
4272 MDTable elemTable;
\r
4274 internal MapElem(ClassDef par, uint elIx, MDTable elemTab) {
\r
4277 elemTable = elemTab;
\r
4280 internal sealed override uint Size(MetaData md) {
\r
4281 return md.TableIndexSize(MDTable.TypeDef) + md.TableIndexSize(elemTable);
\r
4284 internal sealed override void Write(FileImage output) {
\r
4285 output.WriteIndex(MDTable.TypeDef,parent.Row);
\r
4286 output.WriteIndex(elemTable,elemIx);
\r
4289 /**************************************************************************/
\r
4291 /// Base class for field/methods (member of a class)
\r
4293 public abstract class Member : MetaDataElement
\r
4295 protected string name;
\r
4296 protected uint nameIx = 0, sigIx = 0;
\r
4298 internal Member(string memName)
\r
4301 tabIx = MDTable.MemberRef;
\r
4305 /**************************************************************************/
\r
4308 /// Root (20 bytes + UTF-8 Version String + quad align padding)
\r
4309 /// StreamHeaders (8 bytes + null terminated name string + quad align padding)
\r
4311 /// #~ (always present - holds metadata tables)
\r
4312 /// #Strings (always present - holds identifier strings)
\r
4313 /// #US (Userstring heap)
\r
4314 /// #Blob (signature blobs)
\r
4315 /// #GUID (guids for assemblies or Modules)
\r
4318 public class MetaData
\r
4320 private static readonly int[] CIxShiftMap = {2,2,5,1,2,3,1,1,1,2,3,2,1};
\r
4321 private static readonly byte StringsHeapMask = 0x1;
\r
4322 private static readonly byte GUIDHeapMask = 0x2;
\r
4323 private static readonly byte BlobHeapMask = 0x4;
\r
4324 private static readonly uint MetaDataSignature = 0x424A5342;
\r
4325 private static readonly uint maxSmlIxSize = 0xFFFF;
\r
4326 private static readonly uint max1BitSmlIx = 0x7FFF;
\r
4327 private static readonly uint max2BitSmlIx = 0x3FFF;
\r
4328 private static readonly uint max3BitSmlIx = 0x1FFF;
\r
4329 private static readonly uint max5BitSmlIx = 0x7FF;
\r
4330 // NOTE: version and stream name strings MUST always be quad padded
\r
4331 private static readonly string version = "v1.0.3705\0\0\0";
\r
4332 private static readonly char[] tildeName = {'#','~','\0','\0'};
\r
4333 private static readonly char[] stringsName = {'#','S','t','r','i','n','g','s','\0','\0','\0','\0'};
\r
4334 private static readonly char[] usName = {'#','U','S','\0'};
\r
4335 private static readonly char[] guidName = {'#','G','U','I','D','\0','\0','\0'};
\r
4336 private static readonly char[] blobName = {'#','B','l','o','b','\0','\0','\0'};
\r
4337 private static readonly uint MetaDataHeaderSize = 20 + (uint)version.Length;
\r
4338 private static readonly uint TildeHeaderSize = 24;
\r
4339 private static readonly uint StreamHeaderSize = 8;
\r
4340 private static readonly uint numMetaDataTables = (int)MDTable.GenericParamConstraint + 1;
\r
4341 private static readonly uint tildeHeaderSize = 8 + (uint)tildeName.Length;
\r
4343 MetaDataStream strings, us, guid, blob;
\r
4345 MetaDataStream[] streams = new MetaDataStream[5];
\r
4346 uint numStreams = 5;
\r
4347 uint tildeTide = 0, tildePadding = 0, tildeStart = 0;
\r
4348 uint numTables = 0;
\r
4349 ArrayList[] metaDataTables = new ArrayList[numMetaDataTables];
\r
4350 ArrayList byteCodes = new ArrayList();
\r
4351 uint codeSize = 0, codeStart, byteCodePadding = 0, metaDataSize = 0;
\r
4352 ulong valid = 0, /*sorted = 0x000002003301FA00;*/ sorted = 0;
\r
4353 bool[] largeIx = new bool[numMetaDataTables];
\r
4354 bool[] lgeCIx = new bool[(int)CIx.MaxCIx];
\r
4355 bool largeStrings = false, largeUS = false, largeGUID = false, largeBlob = false;
\r
4356 private FileImage file;
\r
4357 private byte heapSizes = 0;
\r
4358 MetaDataElement entryPoint;
\r
4359 BinaryWriter output;
\r
4360 public MSCorLib mscorlib;
\r
4361 private TypeSpec[] systemTypeSpecs = new TypeSpec[PrimitiveType.NumSystemTypes];
\r
4364 internal MetaData(FileImage file) {
\r
4365 // tilde = new MetaDataStream(tildeName,false,0);
\r
4367 strings = new MetaDataStream(stringsName,new UTF8Encoding(),true);
\r
4368 us = new MetaDataStream(usName,new UnicodeEncoding(),true);
\r
4369 guid = new MetaDataStream(guidName,false);
\r
4370 blob = new MetaDataStream(blobName,true);
\r
4371 streams[1] = strings;
\r
4373 streams[3] = guid;
\r
4374 streams[4] = blob;
\r
4375 for (int i=0; i < numMetaDataTables; i++) {
\r
4376 largeIx[i] = false;
\r
4378 for (int i=0; i < lgeCIx.Length; i++) {
\r
4379 lgeCIx[i] = false;
\r
4381 mscorlib = new MSCorLib(this);
\r
4384 internal TypeSpec GetPrimitiveTypeSpec(int ix) {
\r
4385 return systemTypeSpecs[ix];
\r
4388 internal void SetPrimitiveTypeSpec(int ix, TypeSpec typeSpec) {
\r
4389 systemTypeSpecs[ix] = typeSpec;
\r
4392 internal uint Size() {
\r
4393 //Console.WriteLine("metaData size = " + metaDataSize);
\r
4394 return metaDataSize;
\r
4397 internal void StreamSize(byte mask) {
\r
4398 heapSizes |= mask;
\r
4401 internal uint AddToUSHeap(string str) {
\r
4402 if (str == null) return 0;
\r
4403 return us.Add(str,true);
\r
4406 internal uint AddToStringsHeap(string str) {
\r
4407 if ((str == null) || (str.CompareTo("") == 0)) return 0;
\r
4408 return strings.Add(str,false);
\r
4411 internal uint AddToGUIDHeap(Guid guidNum) {
\r
4412 return guid.Add(guidNum);
\r
4415 internal uint AddToBlobHeap(byte[] blobBytes) {
\r
4416 if (blobBytes == null) return 0;
\r
4417 return blob.Add(blobBytes);
\r
4420 internal uint AddToBlobHeap(byte val) {
\r
4421 return blob.Add(val);
\r
4424 internal uint AddToBlobHeap(sbyte val) {
\r
4425 return blob.Add(val);
\r
4428 internal uint AddToBlobHeap(ushort val) {
\r
4429 return blob.Add(val);
\r
4432 internal uint AddToBlobHeap(short val) {
\r
4433 return blob.Add(val);
\r
4436 internal uint AddToBlobHeap(uint val) {
\r
4437 return blob.Add(val);
\r
4440 internal uint AddToBlobHeap(int val) {
\r
4441 return blob.Add(val);
\r
4444 internal uint AddToBlobHeap(ulong val) {
\r
4445 return blob.Add(val);
\r
4448 internal uint AddToBlobHeap(long val) {
\r
4449 return blob.Add(val);
\r
4452 internal uint AddToBlobHeap(float val) {
\r
4453 return blob.Add(val);
\r
4456 internal uint AddToBlobHeap(double val) {
\r
4457 return blob.Add(val);
\r
4460 internal uint AddToBlobHeap(string val) {
\r
4461 return blob.Add(val,true);
\r
4465 private ArrayList GetTable(MDTable tableIx) {
\r
4466 int tabIx = (int)tableIx;
\r
4467 if (metaDataTables[tabIx] == null) {
\r
4468 metaDataTables[tabIx] = new ArrayList();
\r
4469 valid |= ((ulong)0x1 << tabIx);
\r
4470 // Console.WriteLine("after creating table " + tableIx + "(" + tabIx + ") valid = " + valid);
\r
4473 return metaDataTables[tabIx];
\r
4476 internal void AddToTable(MDTable tableIx, MetaDataElement elem) {
\r
4477 if (elem.Row > 0) {
\r
4478 // Console.Out.WriteLine("ERROR - element already in table " + tableIx);
\r
4481 // updates Row field of the element
\r
4482 // Console.WriteLine("Adding element to table " + (uint)tableIx);
\r
4483 ArrayList table = GetTable(tableIx);
\r
4484 elem.Row = (uint)table.Count + 1;
\r
4488 internal uint TableIndex(MDTable tableIx) {
\r
4489 if (metaDataTables[(int)tableIx] == null) return 1;
\r
4490 return (uint)metaDataTables[(int)tableIx].Count+1;
\r
4493 internal uint AddCode(CILInstructions byteCode) {
\r
4494 byteCodes.Add(byteCode);
\r
4495 uint offset = codeSize + codeStart;
\r
4496 codeSize += byteCode.GetCodeSize();
\r
4500 internal void SetEntryPoint(MetaDataElement ep) {
\r
4504 internal void AddData(DataConstant cVal) {
\r
4505 file.AddInitData(cVal);
\r
4508 internal static void CompressNum(uint val, MemoryStream sig) {
\r
4510 sig.WriteByte((byte)val);
\r
4511 } else if (val < 0x3FFF) {
\r
4512 byte b1 = (byte)((val >> 8) | 0x80);
\r
4513 byte b2 = (byte)(val & FileImage.iByteMask[0]);
\r
4514 sig.WriteByte(b1);
\r
4515 sig.WriteByte(b2);
\r
4517 byte b1 = (byte)((val >> 24) | 0xC0);
\r
4518 byte b2 = (byte)((val & FileImage.iByteMask[2]) >> 16);
\r
4519 byte b3 = (byte)((val & FileImage.iByteMask[1]) >> 8);;
\r
4520 byte b4 = (byte)(val & FileImage.iByteMask[0]);
\r
4521 sig.WriteByte(b1);
\r
4522 sig.WriteByte(b2);
\r
4523 sig.WriteByte(b3);
\r
4524 sig.WriteByte(b4);
\r
4528 internal uint CodeSize() {
\r
4529 return codeSize + byteCodePadding;
\r
4532 internal uint StringsIndexSize() {
\r
4533 if (largeStrings) return 4;
\r
4537 internal uint GUIDIndexSize() {
\r
4538 if (largeGUID) return 4;
\r
4542 internal uint USIndexSize() {
\r
4543 if (largeUS) return 4;
\r
4547 internal uint BlobIndexSize() {
\r
4548 if (largeBlob) return 4;
\r
4552 internal uint CodedIndexSize(CIx code) {
\r
4553 if (lgeCIx[(uint)code]) return 4;
\r
4557 internal uint TableIndexSize(MDTable tabIx) {
\r
4558 if (largeIx[(uint)tabIx]) return 4;
\r
4562 private void SetIndexSizes() {
\r
4563 for (int i=0; i < numMetaDataTables; i++) {
\r
4564 if (metaDataTables[i] != null) {
\r
4565 uint count = (uint)metaDataTables[i].Count;
\r
4566 if (count > maxSmlIxSize) {
\r
4567 largeIx[i] = true;
\r
4568 MDTable tabIx = (MDTable)i;
\r
4569 if (count > max5BitSmlIx) {
\r
4570 lgeCIx[(int)CIx.HasCustomAttr] = true;
\r
4572 if (count > max3BitSmlIx) {
\r
4573 if ((tabIx == MDTable.TypeRef) || (tabIx == MDTable.ModuleRef) || (tabIx == MDTable.Method) || (tabIx == MDTable.TypeSpec))
\r
4574 lgeCIx[(int)CIx.CustomAttributeType] = true;
\r
4575 if ((tabIx == MDTable.Method) || (tabIx == MDTable.MemberRef))
\r
4576 lgeCIx[(int)CIx.MemberRefParent] = true;
\r
4577 } else if (count > max2BitSmlIx) {
\r
4578 if ((tabIx == MDTable.Field) || (tabIx == MDTable.Param) || (tabIx == MDTable.Property))
\r
4579 lgeCIx[(int)CIx.HasConst] = true;
\r
4580 if ((tabIx == MDTable.TypeDef) || (tabIx == MDTable.TypeRef) || (tabIx == MDTable.TypeSpec))
\r
4581 lgeCIx[(int)CIx.TypeDefOrRef] = true;
\r
4582 if ((tabIx == MDTable.TypeDef) || (tabIx == MDTable.Method) || (tabIx == MDTable.Assembly))
\r
4583 lgeCIx[(int)CIx.HasDeclSecurity] = true;
\r
4584 if ((tabIx == MDTable.File) || (tabIx == MDTable.AssemblyRef) || (tabIx == MDTable.ExportedType))
\r
4585 lgeCIx[(int)CIx.Implementation] = true;
\r
4586 if ((tabIx == MDTable.Module) || (tabIx == MDTable.ModuleRef) || (tabIx == MDTable.AssemblyRef) || (tabIx == MDTable.TypeRef))
\r
4587 lgeCIx[(int)CIx.ResolutionScope] = true;
\r
4588 } else if (count > max1BitSmlIx) {
\r
4589 if ((tabIx == MDTable.Field) || (tabIx == MDTable.Param))
\r
4590 lgeCIx[(int)CIx.HasFieldMarshal] = true;
\r
4591 if ((tabIx == MDTable.Event) || (tabIx == MDTable.Property))
\r
4592 lgeCIx[(int)CIx.HasSemantics] = true;
\r
4593 if ((tabIx == MDTable.Method) || (tabIx == MDTable.MemberRef))
\r
4594 lgeCIx[(int)CIx.MethodDefOrRef] = true;
\r
4595 if ((tabIx == MDTable.Field) || (tabIx == MDTable.Method))
\r
4596 lgeCIx[(int)CIx.MemberForwarded] = true;
\r
4597 if ((tabIx == MDTable.TypeDef) || (tabIx == MDTable.Method))
\r
4598 lgeCIx[(int)CIx.TypeOrMethodDef] = true;
\r
4603 if (strings.LargeIx()) {
\r
4604 largeStrings = true;
\r
4605 heapSizes |= StringsHeapMask;
\r
4607 if (guid.LargeIx()) {
\r
4609 heapSizes |= GUIDHeapMask;
\r
4611 if (blob.LargeIx()) {
\r
4613 heapSizes |= BlobHeapMask;
\r
4615 largeUS = us.LargeIx();
\r
4618 private void SetStreamOffsets() {
\r
4619 uint sizeOfHeaders = StreamHeaderSize + (uint)tildeName.Length;
\r
4620 for (int i=1; i < numStreams; i++) {
\r
4621 sizeOfHeaders += streams[i].headerSize();
\r
4623 metaDataSize = MetaDataHeaderSize + sizeOfHeaders;
\r
4624 // Console.WriteLine("Size of meta data headers (tildeStart) = " + metaDataSize);
\r
4625 tildeStart = metaDataSize;
\r
4626 metaDataSize += tildeTide + tildePadding;
\r
4627 //Console.WriteLine(tildeName + " - size = " + (tildeTide + tildePadding));
\r
4628 for (int i=1; i < numStreams; i++) {
\r
4629 // Console.WriteLine("Stream " + i + " starts at " + metaDataSize);
\r
4630 streams[i].Start = metaDataSize;
\r
4631 metaDataSize += streams[i].Size();
\r
4632 streams[i].WriteDetails();
\r
4636 internal void CalcTildeStreamSize() {
\r
4637 //tilde.SetIndexSizes(strings.LargeIx(),us.LargeIx(),guid.LargeIx(),blob.LargeIx());
\r
4638 tildeTide = TildeHeaderSize;
\r
4639 tildeTide += 4 * numTables;
\r
4640 //Console.WriteLine("Tilde header + sizes = " + tildeTide);
\r
4641 for (int i=0; i < numMetaDataTables; i++) {
\r
4642 if (metaDataTables[i] != null) {
\r
4643 ArrayList table = metaDataTables[i];
\r
4644 // Console.WriteLine("Meta data table " + i + " at offset " + tildeTide);
\r
4645 tildeTide += (uint)table.Count * ((MetaDataElement)table[0]).Size(this);
\r
4646 // Console.WriteLine("Metadata table " + i + " has size " + table.Count);
\r
4647 // Console.WriteLine("tildeTide = " + tildeTide);
\r
4650 if ((tildeTide % 4) != 0) tildePadding = 4 - (tildeTide % 4);
\r
4651 //Console.WriteLine("tildePadding = " + tildePadding);
\r
4654 internal void WriteTildeStream(FileImage output) {
\r
4655 long startTilde = output.Seek(0,SeekOrigin.Current);
\r
4656 output.Write((uint)0); // Reserved
\r
4657 output.Write((byte)1); // MajorVersion
\r
4658 output.Write((byte)0); // MinorVersion
\r
4659 output.Write(heapSizes);
\r
4660 output.Write((byte)1); // Reserved
\r
4661 output.Write(valid);
\r
4662 output.Write(sorted);
\r
4663 for (int i=0; i < numMetaDataTables; i++) {
\r
4664 if (metaDataTables[i] != null) {
\r
4665 uint count = (uint)metaDataTables[i].Count;
\r
4666 output.Write(count);
\r
4669 long tabStart = output.Seek(0,SeekOrigin.Current);
\r
4670 // Console.WriteLine("Starting metaData tables at " + tabStart);
\r
4671 for (int i=0; i < numMetaDataTables; i++) {
\r
4672 if (metaDataTables[i] != null) {
\r
4673 // Console.WriteLine("Starting metaData table " + i + " at " + (output.Seek(0,SeekOrigin.Current) - startTilde));
\r
4674 ArrayList table = metaDataTables[i];
\r
4675 for (int j=0; j < table.Count; j++) {
\r
4676 ((MetaDataElement)table[j]).Write(output);
\r
4680 // Console.WriteLine("Writing padding at " + output.Seek(0,SeekOrigin.Current));
\r
4681 for (int i=0; i < tildePadding; i++) output.Write((byte)0);
\r
4684 private void BuildTable(ArrayList table) {
\r
4685 if (table == null) return;
\r
4686 for (int j=0; j < table.Count; j++) {
\r
4687 ((MetaDataElement)table[j]).BuildTables(this);
\r
4691 internal void BuildMetaData(uint codeStartOffset) {
\r
4692 codeStart = codeStartOffset;
\r
4693 BuildTable(metaDataTables[(int)MDTable.TypeDef]);
\r
4694 BuildTable(metaDataTables[(int)MDTable.MemberRef]);
\r
4695 BuildTable(metaDataTables[(int)MDTable.GenericParam]);
\r
4696 BuildTable(metaDataTables[(int)MDTable.MethodSpec]);
\r
4697 BuildTable(metaDataTables[(int)MDTable.GenericParamConstraint]);
\r
4698 BuildTable(metaDataTables[(int)MDTable.CustomAttribute]);
\r
4699 /* for (int i=0; i < metaDataTables.Length; i++) {
\r
4700 ArrayList table = metaDataTables[i];
\r
4701 if (table != null) {
\r
4702 for (int j=0; j < table.Count; j++) {
\r
4703 ((MetaDataElement)table[j]).BuildTables(this);
\r
4709 for (int i=1; i < numStreams; i++) {
\r
4710 streams[i].EndStream();
\r
4712 CalcTildeStreamSize();
\r
4713 SetStreamOffsets();
\r
4714 byteCodePadding = NumToAlign(codeSize,4);
\r
4715 if (entryPoint != null) file.SetEntryPoint(entryPoint.Token());
\r
4718 internal void WriteByteCodes(FileImage output) {
\r
4719 for (int i=0; i < byteCodes.Count; i++) {
\r
4720 ((CILInstructions)byteCodes[i]).Write(output);
\r
4722 for (int i=0; i < byteCodePadding; i++) {
\r
4723 output.Write((byte)0);
\r
4727 internal void WriteMetaData(FileImage output) {
\r
4728 this.output = output;
\r
4729 mdStart = output.Seek(0,SeekOrigin.Current);
\r
4730 // Console.WriteLine("Writing metaData at " + Hex.Long(mdStart));
\r
4731 output.Write(MetaDataSignature);
\r
4732 output.Write((short)1); // Major Version
\r
4733 output.Write((short)1); // Minor Version ECMA = 0, PEFiles = 1
\r
4734 output.Write(0); // Reserved
\r
4735 output.Write(version.Length);
\r
4736 output.Write(version.ToCharArray()); // version string is already zero padded
\r
4737 output.Write((short)0);
\r
4738 output.Write((ushort)numStreams);
\r
4739 // write tilde header
\r
4740 output.Write(tildeStart);
\r
4741 output.Write(tildeTide + tildePadding);
\r
4742 output.Write(tildeName);
\r
4743 for (int i=1; i < numStreams; i++) streams[i].WriteHeader(output);
\r
4744 // Console.WriteLine("Writing tilde stream at " + output.Seek(0,SeekOrigin.Current) + " = " + tildeStart);
\r
4745 WriteTildeStream(output);
\r
4746 for (int i=1; i < numStreams; i++) streams[i].Write(output);
\r
4747 // Console.WriteLine("Finished Writing metaData at " + output.Seek(0,SeekOrigin.Current));
\r
4750 internal bool LargeStringsIndex() { return strings.LargeIx(); }
\r
4751 internal bool LargeGUIDIndex() { return guid.LargeIx(); }
\r
4752 internal bool LargeUSIndex() { return us.LargeIx(); }
\r
4753 internal bool LargeBlobIndex() { return blob.LargeIx(); }
\r
4755 internal bool LargeIx(MDTable tabIx) { return largeIx[(uint)tabIx]; }
\r
4758 private uint NumToAlign(uint val, uint alignVal) {
\r
4759 if ((val % alignVal) == 0) return 0;
\r
4760 return alignVal - (val % alignVal);
\r
4763 internal void WriteCodedIndex(CIx code, MetaDataElement elem, FileImage output) {
\r
4765 if (elem != null) {
\r
4766 ix = (elem.Row << CIxShiftMap[(uint)code]) | elem.GetCodedIx(code);
\r
4767 // Console.WriteLine("coded index = " + ix + " row = " + elem.Row);
\r
4769 // Console.WriteLine("elem for coded index is null");
\r
4771 if (lgeCIx[(uint)code])
\r
4774 output.Write((ushort)ix);
\r
4778 /**************************************************************************/
\r
4780 /// Base class for all Meta Data table elements
\r
4783 public abstract class MetaDataElement
\r
4786 protected ArrayList customAttributes;
\r
4787 private uint row = 0;
\r
4788 protected bool done = false;
\r
4789 protected MDTable tabIx;
\r
4791 internal MetaDataElement() { }
\r
4798 if (row == 0) row = value;
\r
4802 internal virtual uint GetCodedIx(CIx code) { return 0; }
\r
4805 /// Add a custom attribute to this item
\r
4807 /// <param name="ctorMeth">the constructor method for this attribute</param>
\r
4808 /// <param name="val">the byte value of the parameters</param>
\r
4809 public void AddCustomAttribute(Method ctorMeth, byte[] val) {
\r
4810 if (customAttributes == null) {
\r
4811 customAttributes = new ArrayList();
\r
4813 customAttributes.Add(new CustomAttribute(this,ctorMeth,val));
\r
4817 /// Add a custom attribute to this item
\r
4819 /// <param name="ctorMeth">the constructor method for this attribute</param>
\r
4820 /// <param name="val">the constant values of the parameters</param>
\r
4821 public void AddCustomAttribute(Method ctorMeth, Constant[] cVals) {
\r
4822 if (customAttributes == null) {
\r
4823 customAttributes = new ArrayList();
\r
4825 // customAttributes.Add(new CustomAttribute(this,ctorMeth,cVals));
\r
4828 internal void DoCustomAttributes(MetaData md) {
\r
4829 if (customAttributes != null) {
\r
4830 for (int i=0; i < customAttributes.Count; i++) {
\r
4831 CustomAttribute ca = (CustomAttribute)customAttributes[i];
\r
4832 ca.BuildTables(md);
\r
4837 internal uint Token() {
\r
4838 return (((uint)tabIx << 24) | row);
\r
4841 internal virtual void BuildTables(MetaData md) {
\r
4845 internal virtual uint Size(MetaData md) {
\r
4849 internal virtual void Write(FileImage output) { }
\r
4852 /**************************************************************************/
\r
4854 /// Stream in the Meta Data (#Strings, #US, #Blob and #GUID)
\r
4857 internal class MetaDataStream : BinaryWriter
\r
4859 private static readonly uint StreamHeaderSize = 8;
\r
4860 private static uint maxSmlIxSize = 0xFFFF;
\r
4862 private uint start = 0;
\r
4863 uint size = 0, tide = 1;
\r
4864 bool largeIx = false;
\r
4865 uint sizeOfHeader;
\r
4867 Hashtable htable = new Hashtable();
\r
4869 internal MetaDataStream(char[] name, bool addInitByte) : base(new MemoryStream()) {
\r
4870 if (addInitByte) { Write((byte)0); size = 1; }
\r
4872 sizeOfHeader = StreamHeaderSize + (uint)name.Length;
\r
4875 internal MetaDataStream(char[] name, System.Text.Encoding enc, bool addInitByte) : base(new MemoryStream(),enc) {
\r
4876 if (addInitByte) { Write((byte)0); size = 1; }
\r
4878 sizeOfHeader = StreamHeaderSize + (uint)name.Length;
\r
4881 public uint Start {
\r
4890 internal uint headerSize() {
\r
4891 // Console.WriteLine(name + " stream has headersize of " + sizeOfHeader);
\r
4892 return sizeOfHeader;
\r
4895 internal void SetSize(uint siz) {
\r
4899 internal uint Size() {
\r
4903 internal bool LargeIx() {
\r
4907 internal void WriteDetails() {
\r
4908 // Console.WriteLine(name + " - size = " + size);
\r
4911 internal uint Add(string str, bool prependSize) {
\r
4912 Object val = htable[str];
\r
4914 if (val == null) {
\r
4916 htable[str] = index;
\r
4917 char[] arr = str.ToCharArray();
\r
4918 if (prependSize) CompressNum((uint)arr.Length*2+1);
\r
4921 size = (uint)Seek(0,SeekOrigin.Current);
\r
4923 index = (uint)val;
\r
4928 internal uint Add(Guid guid) {
\r
4929 Write(guid.ToByteArray());
\r
4930 size =(uint)Seek(0,SeekOrigin.Current);
\r
4934 internal uint Add(byte[] blob) {
\r
4936 CompressNum((uint)blob.Length);
\r
4938 size = (uint)Seek(0,SeekOrigin.Current);
\r
4942 internal uint Add(byte val) {
\r
4945 size = (uint)Seek(0,SeekOrigin.Current);
\r
4949 internal uint Add(sbyte val) {
\r
4952 size = (uint)Seek(0,SeekOrigin.Current);
\r
4956 internal uint Add(ushort val) {
\r
4959 size = (uint)Seek(0,SeekOrigin.Current);
\r
4963 internal uint Add(short val) {
\r
4966 size = (uint)Seek(0,SeekOrigin.Current);
\r
4970 internal uint Add(uint val) {
\r
4973 size = (uint)Seek(0,SeekOrigin.Current);
\r
4977 internal uint Add(int val) {
\r
4980 size = (uint)Seek(0,SeekOrigin.Current);
\r
4984 internal uint Add(ulong val) {
\r
4987 size = (uint)Seek(0,SeekOrigin.Current);
\r
4991 internal uint Add(long val) {
\r
4994 size = (uint)Seek(0,SeekOrigin.Current);
\r
4998 internal uint Add(float val) {
\r
5001 size = (uint)Seek(0,SeekOrigin.Current);
\r
5005 internal uint Add(double val) {
\r
5008 size = (uint)Seek(0,SeekOrigin.Current);
\r
5012 private void CompressNum(uint val) {
\r
5015 } else if (val < 0x3FFF) {
\r
5016 byte b1 = (byte)((val >> 8) | 0x80);
\r
5017 byte b2 = (byte)(val & FileImage.iByteMask[0]);
\r
5021 byte b1 = (byte)((val >> 24) | 0xC0);
\r
5022 byte b2 = (byte)((val & FileImage.iByteMask[2]) >> 16);
\r
5023 byte b3 = (byte)((val & FileImage.iByteMask[1]) >> 8);;
\r
5024 byte b4 = (byte)(val & FileImage.iByteMask[0]);
\r
5032 private void QuadAlign() {
\r
5033 if ((size % 4) != 0) {
\r
5034 uint pad = 4 - (size % 4);
\r
5036 for (int i=0; i < pad; i++) {
\r
5042 internal void EndStream() {
\r
5044 if (size > maxSmlIxSize) {
\r
5049 internal void WriteHeader(BinaryWriter output) {
\r
5050 output.Write(start);
\r
5051 output.Write(size);
\r
5052 output.Write(name);
\r
5055 internal virtual void Write(BinaryWriter output) {
\r
5056 // Console.WriteLine("Writing " + name + " stream at " + output.Seek(0,SeekOrigin.Current) + " = " + start);
\r
5057 MemoryStream str = (MemoryStream)BaseStream;
\r
5058 output.Write(str.ToArray());
\r
5062 /**************************************************************************/
\r
5064 /// Base class for Method Descriptors
\r
5067 public abstract class Method : Member
\r
5069 protected CallConv callConv = CallConv.Default;
\r
5070 protected Type retType;
\r
5072 internal Method(string methName, Type rType) : base(methName)
\r
5078 /// Add calling conventions to this method descriptor
\r
5080 /// <param name="cconv"></param>
\r
5081 public void AddCallConv(CallConv cconv) {
\r
5082 callConv |= cconv;
\r
5085 internal abstract void TypeSig(MemoryStream sig);
\r
5087 internal uint GetSigIx(MetaData md) {
\r
5088 MemoryStream sig = new MemoryStream();
\r
5090 return md.AddToBlobHeap(sig.ToArray());
\r
5093 internal Type GetRetType() {
\r
5098 /**************************************************************************/
\r
5100 /// Descriptor for a method defined in THIS assembly/module
\r
5104 public class MethodDef : Method
\r
5106 private static readonly ushort PInvokeImpl = 0x2000;
\r
5107 //private static readonly uint UnmanagedExport = 0x0008;
\r
5108 // private static readonly byte LocalSigByte = 0x7;
\r
5109 uint parIx = 0, textOffset = 0;
\r
5111 MetaData metaData;
\r
5112 CILInstructions code;
\r
5113 ArrayList securityActions = new ArrayList();
\r
5117 ushort methFlags = 0, implFlags = 0;
\r
5118 int maxStack = 0, numPars = 0;
\r
5119 bool entryPoint = false;
\r
5120 LocalSig localSig;
\r
5121 ArrayList varArgSigList;
\r
5122 ImplMap pinvokeImpl;
\r
5125 internal MethodDef(MetaData md, string name, Type retType, Param[] pars) : base(name,retType) {
\r
5128 if (parList != null) numPars = parList.Length;
\r
5129 tabIx = MDTable.Method;
\r
5132 internal MethodDef(MetaData md, MethAttr mAttrSet, ImplAttr iAttrSet, string name, Type retType, Param[] pars) : base(name,retType) {
\r
5135 if (parList != null) numPars = parList.Length;
\r
5136 // Console.WriteLine("Creating method " + name + " with " + numPars + " parameters");
\r
5137 methFlags = (ushort)mAttrSet;
\r
5138 implFlags = (ushort)iAttrSet;
\r
5139 tabIx = MDTable.Method;
\r
5142 internal Param[] GetPars() {
\r
5147 /// Add some attributes to this method descriptor
\r
5149 /// <param name="ma">the attributes to be added</param>
\r
5150 public void AddMethAttribute(MethAttr ma) {
\r
5151 methFlags |= (ushort)ma;
\r
5155 /// Add some implementation attributes to this method descriptor
\r
5157 /// <param name="ia">the attributes to be added</param>
\r
5158 public void AddImplAttribute(ImplAttr ia) {
\r
5159 implFlags |= (ushort)ia;
\r
5162 public void AddPInvokeInfo(ModuleRef scope, string methName,
\r
5163 PInvokeAttr callAttr) {
\r
5164 pinvokeImpl = new ImplMap((ushort)callAttr,this,methName,scope);
\r
5165 methFlags |= PInvokeImpl;
\r
5169 /// Add a named generic type parameter
\r
5171 public GenericParameter AddGenericParameter (short index, string name) {
\r
5172 GenericParameter gp = new GenericParameter (this, metaData, index, name);
5173 metaData.AddToTable (MDTable.GenericParam, gp);
\r
5178 /// Set the maximum stack height for this method
\r
5180 /// <param name="maxStack">the maximum height of the stack</param>
\r
5181 public void SetMaxStack(int maxStack) {
\r
5182 this.maxStack = maxStack;
\r
5186 /// Add local variables to this method
\r
5188 /// <param name="locals">the locals to be added</param>
\r
5189 /// <param name="initLocals">are locals initialised to default values</param>
\r
5190 public void AddLocals(Local[] locals, bool initLocals) {
\r
5191 this.locals = locals;
\r
5192 this.initLocals = initLocals;
\r
5196 /// Mark this method as having an entry point
\r
5198 public void DeclareEntryPoint() {
\r
5199 entryPoint = true;
\r
5203 /// Create a code buffer for this method to add the IL instructions to
\r
5205 /// <returns>a buffer for this method's IL instructions</returns>
\r
5206 public CILInstructions CreateCodeBuffer() {
\r
5207 code = new CILInstructions(metaData);
\r
5212 /// Make a method reference descriptor for this method to be used
\r
5213 /// as a callsite signature for this vararg method
\r
5215 /// <param name="optPars">the optional pars for the vararg method call</param>
\r
5216 /// <returns></returns>
\r
5217 public MethodRef MakeVarArgSignature(Type[] optPars) {
\r
5218 Type[] pars = new Type[numPars];
\r
5219 MethodRef varArgSig;
\r
5220 for (int i=0; i < numPars; i++) {
\r
5221 pars[i] = parList[i].GetParType();
\r
5223 varArgSig = new MethodRef(this,name,retType,pars,true,optPars);
\r
5225 if (varArgSigList == null)
\r
5226 varArgSigList = new ArrayList ();
\r
5227 varArgSigList.Add (varArgSig);
\r
5231 internal sealed override void TypeSig(MemoryStream sig) {
\r
5232 sig.WriteByte((byte)callConv);
\r
5233 MetaData.CompressNum((uint)numPars,sig);
\r
5234 retType.TypeSig(sig);
\r
5235 for (ushort i=0; i < numPars; i++) {
\r
5236 parList[i].seqNo = (ushort)(i+1);
\r
5237 parList[i].TypeSig(sig);
\r
5241 internal sealed override void BuildTables(MetaData md) {
\r
5243 if (pinvokeImpl != null) {
\r
5244 md.AddToTable(MDTable.ImplMap,pinvokeImpl);
\r
5245 pinvokeImpl.BuildTables(md);
\r
5247 if (entryPoint) md.SetEntryPoint(this);
\r
5248 uint locToken = 0;
\r
5249 if (locals != null) {
\r
5250 localSig = new LocalSig(locals);
\r
5251 md.AddToTable(MDTable.StandAloneSig,localSig);
\r
5252 localSig.BuildTables(md);
\r
5253 locToken = localSig.Token();
\r
5255 if (code != null) {
\r
5256 code.CheckCode(locToken,initLocals,maxStack);
\r
5257 textOffset = md.AddCode(code);
\r
5259 nameIx = md.AddToStringsHeap(name);
\r
5260 sigIx = GetSigIx(md);
\r
5261 parIx = md.TableIndex(MDTable.Param);
\r
5262 for (int i=0; i < numPars; i++) {
\r
5263 md.AddToTable(MDTable.Param,parList[i]);
\r
5264 parList[i].BuildTables(md);
\r
5266 if (varArgSigList != null) {
\r
5267 foreach (MethodRef varArgSig in varArgSigList) {
\r
5268 md.AddToTable(MDTable.MemberRef,varArgSig);
\r
5269 varArgSig.BuildTables(md);
\r
5272 DoCustomAttributes (md);
\r
5273 // Console.WriteLine("method has " + numPars + " parameters");
\r
5277 internal sealed override uint Size(MetaData md) {
\r
5278 return 8 + md.StringsIndexSize() + md.BlobIndexSize() + md.TableIndexSize(MDTable.Param);
\r
5281 internal sealed override void Write(FileImage output) {
\r
5282 if (ZeroRva ()) output.Write(0);
\r
5283 else output.WriteCodeRVA(textOffset);
\r
5284 output.Write(implFlags);
\r
5285 output.Write(methFlags);
\r
5286 output.StringsIndex(nameIx);
\r
5287 output.BlobIndex(sigIx);
\r
5288 output.WriteIndex(MDTable.Param,parIx);
\r
5291 internal bool ZeroRva () {
5292 return (((methFlags & (ushort)MethAttr.Abstract) != 0) ||
5293 (pinvokeImpl != null)); // TODO: Not entirely true but works for now
5296 internal sealed override uint GetCodedIx(CIx code) {
\r
5298 case (CIx.HasCustomAttr) : return 0;
\r
5299 case (CIx.HasDeclSecurity) : return 1;
\r
5300 case (CIx.MemberRefParent) : return 3;
\r
5301 case (CIx.MethodDefOrRef) : return 0;
\r
5302 case (CIx.MemberForwarded) : return 1;
\r
5303 case (CIx.CustomAttributeType) : return 2;
\r
5304 case (CIx.TypeOrMethodDef) : return 1;
\r
5310 /**************************************************************************/
\r
5312 /// Descriptor for an overriding method (.override)
\r
5314 public class MethodImpl : MetaDataElement
\r
5317 Method header, body;
\r
5319 internal MethodImpl(ClassDef par, Method decl, Method bod) {
\r
5323 tabIx = MDTable.MethodImpl;
\r
5326 internal sealed override uint Size(MetaData md) {
\r
5327 return md.TableIndexSize(MDTable.TypeDef) + 2 * md.CodedIndexSize(CIx.MethodDefOrRef);
\r
5330 internal sealed override void Write(FileImage output) {
\r
5331 output.WriteIndex(MDTable.TypeDef,parent.Row);
\r
5332 output.WriteCodedIndex(CIx.MethodDefOrRef,body);
\r
5333 output.WriteCodedIndex(CIx.MethodDefOrRef,header);
\r
5337 /**************************************************************************/
\r
5339 /// Descriptor for a method defined in another assembly/module
\r
5341 public class MethodRef : Method
\r
5343 private static readonly byte Sentinel = 0x41;
\r
5344 Type[] parList, optParList;
\r
5345 MetaDataElement parent;
\r
5346 uint numPars = 0, numOptPars = 0;
\r
5348 internal MethodRef(MetaDataElement paren, string name, Type retType,
\r
5349 Type[] pars, bool varArgMeth, Type[] optPars) : base(name,retType) {
\r
5352 if (parList != null) numPars = (uint)parList.Length;
\r
5354 optParList = optPars;
\r
5355 if (optParList != null) numOptPars = (uint)optParList.Length;
\r
5356 callConv = CallConv.Vararg;
\r
5360 internal sealed override void TypeSig(MemoryStream sig) {
\r
5361 sig.WriteByte((byte)callConv);
\r
5362 MetaData.CompressNum(numPars+numOptPars,sig);
\r
5363 retType.TypeSig(sig);
\r
5364 for (int i=0; i < numPars; i++) {
\r
5365 parList[i].TypeSig(sig);
\r
5367 if (numOptPars > 0) {
\r
5368 sig.WriteByte(Sentinel);
\r
5369 for (int i=0; i < numOptPars; i++) {
\r
5370 optParList[i].TypeSig(sig);
\r
5375 internal sealed override void BuildTables(MetaData md) {
\r
5377 nameIx = md.AddToStringsHeap(name);
\r
5378 sigIx = GetSigIx(md);
\r
5382 internal sealed override uint Size(MetaData md) {
\r
5383 return md.CodedIndexSize(CIx.MemberRefParent) + md.StringsIndexSize() + md.BlobIndexSize();
\r
5386 internal sealed override void Write(FileImage output) {
\r
5387 output.WriteCodedIndex(CIx.MemberRefParent,parent);
\r
5388 output.StringsIndex(nameIx);
\r
5389 output.BlobIndex(sigIx);
\r
5392 internal sealed override uint GetCodedIx(CIx code) {
\r
5394 case (CIx.HasCustomAttr) : return 6;
\r
5395 case (CIx.MethodDefOrRef) : return 1;
\r
5396 case (CIx.CustomAttributeType) : return 3;
\r
5402 /**************************************************************************/
\r
5404 /// Descriptor for Property and Event methods
\r
5406 public class MethodSemantics : MetaDataElement {
\r
5408 Feature.MethodType type;
\r
5410 Feature eventOrProp;
\r
5412 internal MethodSemantics(Feature.MethodType mType, MethodDef method, Feature feature) {
\r
5415 eventOrProp = feature;
\r
5416 tabIx = MDTable.MethodSemantics;
\r
5419 internal sealed override uint Size(MetaData md) {
\r
5420 return 2 + md.TableIndexSize(MDTable.Method) + md.CodedIndexSize(CIx.HasSemantics);
\r
5423 internal sealed override void Write(FileImage output) {
\r
5424 output.Write((ushort)type);
\r
5425 output.WriteIndex(MDTable.Method,meth.Row);
\r
5426 output.WriteCodedIndex(CIx.HasSemantics,eventOrProp);
\r
5430 /**************************************************************************/
\r
5432 /// Descriptor for a FunctionPointer type
\r
5435 public class MethPtrType : Type
\r
5437 // MethPtrType == FNPTR
\r
5442 /// Create a new function pointer type
\r
5444 /// <param name="meth">the function to be referenced</param>
\r
5445 public MethPtrType(Method meth) : base(0x1B)
\r
5448 tabIx = MDTable.TypeSpec;
\r
5451 internal sealed override void TypeSig(MemoryStream str) {
\r
5452 str.WriteByte(typeIndex);
\r
5453 method.TypeSig(str);
\r
5456 internal sealed override void BuildTables(MetaData md) {
\r
5458 MemoryStream sig = new MemoryStream();
\r
5460 sigIx = md.AddToBlobHeap(sig.ToArray());
\r
5464 internal sealed override uint Size(MetaData md) {
\r
5465 return md.BlobIndexSize();
\r
5468 internal sealed override void Write(FileImage output) {
\r
5469 output.BlobIndex(sigIx);
\r
5472 internal sealed override uint GetCodedIx(CIx code) { return 0x1B; }
\r
5475 /**************************************************************************/
\r
5477 /// Descriptor for THIS module
\r
5479 public class Module : ResolutionScope
\r
5484 internal Module(string name, MetaData md) : base(name,md) {
\r
5485 mvid = Guid.NewGuid();
\r
5486 mvidIx = md.AddToGUIDHeap(mvid);
\r
5487 tabIx = MDTable.Module;
\r
5490 internal sealed override uint Size(MetaData md) {
\r
5491 return 2 + md.StringsIndexSize() + 3 * md.GUIDIndexSize();
\r
5494 internal sealed override void Write(FileImage output) {
\r
5495 output.Write((short)0);
\r
5496 output.StringsIndex(nameIx);
\r
5497 output.GUIDIndex(mvidIx);
\r
5498 output.GUIDIndex(0);
\r
5499 output.GUIDIndex(0);
\r
5502 internal sealed override uint GetCodedIx(CIx code) {
\r
5504 case (CIx.HasCustomAttr) : return 7;
\r
5505 case (CIx.ResolutionScope) : return 0;
\r
5511 /**************************************************************************/
\r
5513 /// Descriptor for another module in THIS assembly
\r
5515 public class ModuleRef : ResolutionScope
\r
5518 internal ModuleRef(MetaData md, string name) : base(name,md) {
\r
5519 tabIx = MDTable.ModuleRef;
\r
5523 /// Add a class to this external module. This is a class declared in
\r
5524 /// another module of THIS assembly.
\r
5526 /// <param name="nsName">name space name</param>
\r
5527 /// <param name="name">class name</param>
\r
5528 /// <returns>a descriptor for this class in another module</returns>
\r
5529 public ClassRef AddClass(string nsName, string name, bool exportClass) {
\r
5530 ClassRef aClass = new ClassRef(nsName,name,metaData);
\r
5531 metaData.AddToTable(MDTable.TypeRef,aClass);
\r
5532 aClass.SetParent(this);
\r
5537 /// Make a file descriptor to correspond to this module. The file
\r
5538 /// descriptor will have the same name as the module descriptor
\r
5540 /// <param name="hashBytes">the hash of the file</param>
\r
5541 /// <param name="hasMetaData">the file contains metadata</param>
\r
5542 /// <param name="entryPoint">the program entry point is in this file</param>
\r
5543 /// <returns>a descriptor for the file which contains this module</returns>
\r
5544 public FileRef MakeFile(byte[] hashBytes, bool hasMetaData, bool entryPoint) {
\r
5545 FileRef file = new FileRef(nameIx,hashBytes,hasMetaData,entryPoint,metaData);
\r
5546 metaData.AddToTable(MDTable.File,file);
\r
5551 /// Add a value class to this module. This is a class declared in
\r
5552 /// another module of THIS assembly.
\r
5554 /// <param name="nsName">name space name</param>
\r
5555 /// <param name="name">class name</param>
\r
5556 /// <returns></returns>
\r
5557 public ClassRef AddValueClass(string nsName, string name) {
\r
5558 ClassRef aClass = new ClassRef(nsName,name,metaData);
\r
5559 metaData.AddToTable(MDTable.TypeRef,aClass);
\r
5560 aClass.SetParent(this);
\r
5561 aClass.MakeValueClass();
\r
5566 /// Add a class which is declared public in this external module of
\r
5567 /// THIS assembly. This class will be exported from this assembly.
\r
5568 /// The ilasm syntax for this is .extern class
\r
5570 /// <param name="attrSet">attributes of the class to be exported</param>
\r
5571 /// <param name="nsName">name space name</param>
\r
5572 /// <param name="name">external class name</param>
\r
5573 /// <param name="declFile">the file where the class is declared</param>
\r
5574 /// <param name="isValueClass">is this class a value type?</param>
\r
5575 /// <returns>a descriptor for this external class</returns>
\r
5576 public ExternClassRef AddExternClass(TypeAttr attrSet, string nsName,
\r
5577 string name, FileRef declFile,
\r
5578 bool isValueClass) {
\r
5579 ExternClassRef cRef = new ExternClassRef(attrSet,nsName,name,declFile,metaData);
\r
5580 metaData.AddToTable(MDTable.TypeRef,cRef);
\r
5581 cRef.SetParent(this);
\r
5582 if (isValueClass) cRef.MakeValueClass();
\r
5587 /// Add a "global" method in another module
\r
5589 /// <param name="name">method name</param>
\r
5590 /// <param name="retType">return type</param>
\r
5591 /// <param name="pars">method parameter types</param>
\r
5592 /// <returns>a descriptor for this method in anther module</returns>
\r
5593 public MethodRef AddMethod(string name, Type retType, Type[] pars) {
\r
5594 MethodRef meth = new MethodRef(this,name,retType,pars,false,null);
\r
5595 metaData.AddToTable(MDTable.MemberRef,meth);
\r
5600 /// Add a vararg method to this class
\r
5602 /// <param name="name">method name</param>
\r
5603 /// <param name="retType">return type</param>
\r
5604 /// <param name="pars">parameter types</param>
\r
5605 /// <param name="optPars">optional param types for this vararg method</param>
\r
5606 /// <returns>a descriptor for this method</returns>
\r
5607 public MethodRef AddVarArgMethod(string name, Type retType,
\r
5608 Type[] pars, Type[] optPars) {
\r
5609 MethodRef meth = new MethodRef(this,name,retType,pars,true,optPars);
\r
5610 metaData.AddToTable(MDTable.MemberRef,meth);
\r
5615 /// Add a field in another module
\r
5617 /// <param name="name">field name</param>
\r
5618 /// <param name="fType">field type</param>
\r
5619 /// <returns>a descriptor for this field in another module</returns>
\r
5620 public FieldRef AddField(string name, Type fType) {
\r
5621 FieldRef field = new FieldRef(this,name,fType);
\r
5622 metaData.AddToTable(MDTable.MemberRef,field);
\r
5626 internal sealed override uint Size(MetaData md) {
\r
5627 return md.StringsIndexSize();
\r
5630 internal sealed override void Write(FileImage output) {
\r
5631 output.StringsIndex(nameIx);
\r
5634 internal sealed override uint GetCodedIx(CIx code) {
\r
5636 case (CIx.HasCustomAttr) : return 12;
\r
5637 case (CIx.MemberRefParent) : return 2;
\r
5638 case (CIx.ResolutionScope) : return 1;
\r
5644 /**************************************************************************/
\r
5646 /// Descriptors for native types used for marshalling
\r
5648 public class NativeType {
\r
5649 public static readonly NativeType Void = new NativeType(0x01);
\r
5650 public static readonly NativeType Boolean = new NativeType(0x02);
\r
5651 public static readonly NativeType Int8 = new NativeType(0x03);
\r
5652 public static readonly NativeType UInt8 = new NativeType(0x04);
\r
5653 public static readonly NativeType Int16 = new NativeType(0x05);
\r
5654 public static readonly NativeType UInt16 = new NativeType(0x06);
\r
5655 public static readonly NativeType Int32 = new NativeType(0x07);
\r
5656 public static readonly NativeType UInt32 = new NativeType(0x08);
\r
5657 public static readonly NativeType Int64 = new NativeType(0x09);
\r
5658 public static readonly NativeType UInt64 = new NativeType(0x0A);
\r
5659 public static readonly NativeType Float32 = new NativeType(0x0B);
\r
5660 public static readonly NativeType Float64 = new NativeType(0x0C);
\r
5661 public static readonly NativeType Currency = new NativeType(0x0F);
\r
5662 public static readonly NativeType BStr = new NativeType(0x13);
\r
5663 public static readonly NativeType LPStr = new NativeType(0x14);
\r
5664 public static readonly NativeType LPWStr = new NativeType(0x15);
\r
5665 public static readonly NativeType LPTStr = new NativeType(0x16);
\r
5666 public static readonly NativeType FixedSysString = new NativeType(0x17);
\r
5667 public static readonly NativeType IUnknown = new NativeType(0x19);
\r
5668 public static readonly NativeType IDispatch = new NativeType(0x1A);
\r
5669 public static readonly NativeType Struct = new NativeType(0x1B);
\r
5670 public static readonly NativeType Interface = new NativeType(0x1C);
\r
5671 public static readonly NativeType Int = new NativeType(0x1F);
\r
5672 public static readonly NativeType UInt = new NativeType(0x20);
\r
5673 public static readonly NativeType ByValStr = new NativeType(0x22);
\r
5674 public static readonly NativeType AnsiBStr = new NativeType(0x23);
\r
5675 public static readonly NativeType TBstr = new NativeType(0x24);
\r
5676 public static readonly NativeType VariantBool = new NativeType(0x25);
\r
5677 public static readonly NativeType FuncPtr = new NativeType(0x26);
\r
5678 public static readonly NativeType AsAny = new NativeType(0x28);
\r
5680 protected byte typeIndex;
\r
5682 internal NativeType(byte tyIx) { typeIndex = tyIx; }
\r
5684 internal byte GetTypeIndex() { return typeIndex; }
\r
5686 internal virtual byte[] ToBlob() {
\r
5687 byte[] bytes = new byte[1];
\r
5688 bytes[0] = GetTypeIndex();
\r
5694 public class NativeArray : NativeType
\r
5696 NativeType elemType;
\r
5697 uint len = 0, parNum = 0;
\r
5700 public NativeArray(NativeType elemType) : base(0x2A) {
\r
5701 this.elemType = elemType;
\r
5704 public NativeArray(NativeType elemType, int len) : base(0x2A) {
\r
5705 this.elemType = elemType;
\r
5709 public NativeArray(NativeType elemType, int numElem, int parNumForLen) : base(0x2A) {
\r
5710 this.elemType = elemType;
\r
5711 len = (uint)numElem;
\r
5712 parNum = (uint)parNumForLen;
\r
5715 internal override byte[] ToBlob() {
\r
5716 MemoryStream str = new MemoryStream();
\r
5717 str.WriteByte(GetTypeIndex());
\r
5718 if (elemType == null) str.WriteByte(0x50); // no info (MAX)
\r
5719 else str.WriteByte(elemType.GetTypeIndex());
\r
5720 MetaData.CompressNum(parNum,str);
\r
5722 MetaData.CompressNum(len,str);
\r
5723 return str.ToArray();
\r
5728 public class SafeArray : NativeType
\r
5730 SafeArrayType elemType;
\r
5732 public SafeArray(SafeArrayType elemType) : base(0x1D) {
\r
5733 this.elemType = elemType;
\r
5736 internal override byte[] ToBlob() {
\r
5737 byte[] bytes = new byte[2];
\r
5738 bytes[0] = GetTypeIndex();
\r
5739 bytes[1] = (byte)elemType;
\r
5745 public class FixedArray : NativeType
\r
5747 NativeType elemType;
\r
5750 public FixedArray(NativeType elemType, int numElems) : base(0x1E) {
\r
5751 this.elemType = elemType;
\r
5752 numElem = (uint)numElems;
\r
5755 internal override byte[] ToBlob() {
\r
5756 MemoryStream str = new MemoryStream();
\r
5757 str.WriteByte(GetTypeIndex());
\r
5758 MetaData.CompressNum(numElem,str);
\r
5759 if (elemType == null) str.WriteByte(0x50); // no info (MAX)
\r
5760 else str.WriteByte(elemType.GetTypeIndex());
\r
5761 return str.ToArray();
\r
5766 public class CustomMarshaller : NativeType
\r
5769 string marshallerName;
\r
5772 public CustomMarshaller(string typeNameOrGUID, string marshallerName,
\r
5773 string optCookie) : base(0x2C) {
\r
5774 typeName = typeNameOrGUID;
\r
5775 this.marshallerName = marshallerName;
\r
5776 cookie = optCookie;
\r
5779 internal override byte[] ToBlob() {
\r
5780 MemoryStream str = new MemoryStream();
\r
5781 BinaryWriter bw = new BinaryWriter(str,new UTF8Encoding());
\r
5782 bw.Write(GetTypeIndex());
\r
5783 bw.Write(typeName.ToCharArray());
\r
5784 bw.Write((byte)0);
\r
5785 bw.Write(marshallerName.ToCharArray());
\r
5786 bw.Write((byte)0);
\r
5787 if (cookie != null) bw.Write(cookie.ToCharArray());
\r
5788 bw.Write((byte)0);
\r
5790 return str.ToArray();
\r
5794 /**************************************************************************/
\r
5796 /// Descriptor for a parameter of a method defined in this assembly/module
\r
5798 public class Param : MetaDataElement
\r
5800 private static readonly ushort hasDefault = 0x1000;
\r
5801 private static readonly ushort hasFieldMarshal = 0x2000;
\r
5805 internal ushort seqNo = 0;
\r
5807 ConstantElem defaultVal;
\r
5809 FieldMarshal marshalInfo;
\r
5812 /// Create a new parameter for a method
\r
5814 /// <param name="mode">param mode (in, out, opt)</param>
\r
5815 /// <param name="parName">parameter name</param>
\r
5816 /// <param name="parType">parameter type</param>
\r
5817 public Param(ParamAttr mode, string parName, Type parType) {
\r
5820 parMode = (ushort)mode;
\r
5821 tabIx = MDTable.Param;
\r
5825 /// Add a default value to this parameter
\r
5827 /// <param name="c">the default value for the parameter</param>
\r
5828 public void AddDefaultValue(Constant cVal) {
\r
5829 defaultVal = new ConstantElem(this,cVal);
\r
5830 parMode |= hasDefault;
\r
5834 /// Add marshalling information about this parameter
\r
5836 public void AddMarshallInfo(NativeType marshallType) {
\r
5837 parMode |= hasFieldMarshal;
\r
5838 marshalInfo = new FieldMarshal(this,marshallType);
\r
5841 internal Type GetParType() { return pType; }
\r
5843 internal sealed override void BuildTables(MetaData md) {
\r
5845 nameIx = md.AddToStringsHeap(pName);
\r
5846 if (defaultVal != null) {
\r
5847 md.AddToTable(MDTable.Constant,defaultVal);
\r
5848 defaultVal.BuildTables(md);
\r
5850 if (marshalInfo != null) {
\r
5851 md.AddToTable(MDTable.FieldMarshal,marshalInfo);
\r
5852 marshalInfo.BuildTables(md);
\r
5857 internal void TypeSig(MemoryStream str) {
\r
5858 pType.TypeSig(str);
\r
5861 internal sealed override uint Size(MetaData md) {
\r
5862 return 4 + md.StringsIndexSize();
\r
5865 internal sealed override void Write(FileImage output) {
\r
5866 output.Write(parMode);
\r
5867 output.Write(seqNo);
\r
5868 output.StringsIndex(nameIx);
\r
5871 internal sealed override uint GetCodedIx(CIx code) {
\r
5873 case (CIx.HasCustomAttr) : return 4;
\r
5874 case (CIx.HasConst) : return 1;
\r
5875 case (CIx.HasFieldMarshal) : return 1;
\r
5881 /**************************************************************************/
\r
5883 /// Base class for the PEFile (starting point)
\r
5885 public class PEFile
\r
5887 private static readonly string mscorlibName = "mscorlib";
\r
5888 private Module thisMod;
\r
5889 private ClassDef moduleClass;
\r
5890 private ArrayList classRefList = new ArrayList();
\r
5891 private ArrayList classDefList = new ArrayList();
\r
5892 private Assembly thisAssembly;
\r
5893 private int corFlags = 1;
\r
5894 FileImage fileImage;
\r
5895 MetaData metaData;
\r
5898 /// Create a new PEFile. Each PEFile is a module.
\r
5900 /// <param name="name">module name, also used for the file name</param>
\r
5901 /// <param name="isDLL">create a .dll or .exe file</param>
\r
5902 /// <param name="hasAssembly">this file is an assembly and
\r
5903 /// will contain the assembly manifest. The assembly name is the
\r
5904 /// same as the module name</param>
\r
5905 public PEFile(string name, bool isDLL, bool hasAssembly) {
\r
5906 // Console.WriteLine(Hex.Byte(0x12));
\r
5907 // Console.WriteLine(Hex.Short(0x1234));
\r
5908 // Console.WriteLine(Hex.Int(0x12345678));
\r
5909 string fName = MakeFileName(null,name,isDLL);
\r
5910 fileImage = new FileImage(isDLL,fName);
\r
5911 InitPEFile(name, fName, hasAssembly);
\r
5915 /// Create a new PEFile. Each PEFile is a module.
\r
5917 /// <param name="name">module name, also used for the file name</param>
\r
5918 /// <param name="isDLL">create a .dll or .exe file</param>
\r
5919 /// <param name="hasAssembly">this file is an assembly and
\r
5920 /// will contain the assembly manifest. The assembly name is the
\r
5921 /// same as the module name</param>
\r
5922 /// <param name="outputDir">write the PEFile to this directory. If this
\r
5923 /// string is null then the output will be to the current directory</param>
\r
5924 public PEFile(string name, bool isDLL, bool hasAssembly, string outputDir) {
\r
5925 // Console.WriteLine(Hex.Byte(0x12));
\r
5926 // Console.WriteLine(Hex.Short(0x1234));
\r
5927 // Console.WriteLine(Hex.Int(0x12345678));
\r
5928 string fName = MakeFileName(outputDir,name,isDLL);
\r
5929 fileImage = new FileImage(isDLL,fName);
\r
5930 InitPEFile(name, fName, hasAssembly);
\r
5934 /// Create a new PEFile
\r
5936 /// <param name="name">module name</param>
\r
5937 /// <param name="isDLL">create a .dll or .exe</param>
\r
5938 /// <param name="hasAssembly">this PEfile is an assembly and
\r
5939 /// will contain the assemly manifest. The assembly name is the
\r
5940 /// same as the module name</param>
\r
5941 /// <param name="outStream">write the PEFile to this stream instead
\r
5942 /// of to a new file</param>
\r
5943 public PEFile(string name, bool isDLL, bool hasAssembly, Stream outStream) {
\r
5944 fileImage = new FileImage(isDLL,outStream);
\r
5945 InitPEFile(name, MakeFileName(null,name,isDLL), hasAssembly);
\r
5948 private void InitPEFile(string name, string fName, bool hasAssembly) {
\r
5949 metaData = fileImage.GetMetaData();
\r
5950 thisMod = new Module(fName,metaData);
\r
5951 if (hasAssembly) {
\r
5952 thisAssembly = new Assembly(name,metaData);
\r
5953 metaData.AddToTable(MDTable.Assembly,thisAssembly);
\r
5955 moduleClass = AddClass(TypeAttr.Private,"","<Module>");
\r
5956 moduleClass.SpecialNoSuper();
\r
5957 metaData.AddToTable(MDTable.Module,thisMod);
\r
5961 public ClassDef ModuleClass {
5962 get { return moduleClass; }
5966 /// Set the subsystem (.subsystem) (Default is Windows Console mode)
\r
5968 /// <param name="subS">subsystem value</param>
\r
5969 public void SetSubSystem(SubSystem subS) {
\r
5970 fileImage.subSys = subS;
\r
5974 /// Set the flags (.corflags)
\r
5976 /// <param name="flags">the flags value</param>
\r
5977 public void SetCorFlags(int flags) {
\r
5981 private string MakeFileName(string dirName, string name, bool isDLL) {
\r
5982 string result = "";
\r
5983 if ((dirName != null) && (dirName.CompareTo("") != 0)) {
\r
5985 if (!dirName.EndsWith("\\")) result += "\\";
\r
5989 // if (isDLL) result += ".dll"; else result += ".exe";
\r
5995 /// Add an external assembly to this PEFile (.assembly extern)
\r
5997 /// <param name="assemName">the external assembly name</param>
\r
5998 /// <returns>a descriptor for this external assembly</returns>
\r
5999 public AssemblyRef AddExternAssembly(string assemName) {
\r
6000 if (assemName.CompareTo(mscorlibName) == 0) return metaData.mscorlib;
\r
6001 AssemblyRef anAssem = new AssemblyRef(metaData,assemName);
\r
6002 metaData.AddToTable(MDTable.AssemblyRef,anAssem);
\r
6003 // Console.WriteLine("Adding assembly " + assemName);
\r
6008 /// Add an external module to this PEFile (.module extern)
\r
6010 /// <param name="name">the external module name</param>
\r
6011 /// <returns>a descriptor for this external module</returns>
\r
6012 public ModuleRef AddExternModule(string name) {
\r
6013 ModuleRef modRef = new ModuleRef(metaData,name);
\r
6014 metaData.AddToTable(MDTable.ModuleRef,modRef);
\r
6019 /// Add a "global" method to this module
\r
6021 /// <param name="name">method name</param>
\r
6022 /// <param name="retType">return type</param>
\r
6023 /// <param name="pars">method parameters</param>
\r
6024 /// <returns>a descriptor for this new "global" method</returns>
\r
6025 public MethodDef AddMethod(string name, Type retType, Param[] pars) {
\r
6026 return moduleClass.AddMethod(name,retType,pars);
\r
6030 /// Add a "global" method to this module
\r
6032 /// <param name="mAtts">method attributes</param>
\r
6033 /// <param name="iAtts">method implementation attributes</param>
\r
6034 /// <param name="name">method name</param>
\r
6035 /// <param name="retType">return type</param>
\r
6036 /// <param name="pars">method parameters</param>
\r
6037 /// <returns>a descriptor for this new "global" method</returns>
\r
6038 public MethodDef AddMethod(MethAttr mAtts, ImplAttr iAtts, string name, Type retType, Param[] pars) {
\r
6039 return moduleClass.AddMethod(mAtts,iAtts,name,retType,pars);
\r
6042 public MethodRef AddMethodToTypeSpec (Type item, string name, Type retType, Type[] pars) {
\r
6043 MethodRef meth = new MethodRef (item.GetTypeSpec (metaData), name, retType, pars, false, null);
\r
6044 metaData.AddToTable (MDTable.MemberRef,meth);
\r
6048 public MethodRef AddVarArgMethodToTypeSpec (Type item, string name, Type retType,
\r
6049 Type[] pars, Type[] optPars) {
\r
6050 MethodRef meth = new MethodRef(item.GetTypeSpec (metaData), name,retType,pars,true,optPars);
\r
6051 metaData.AddToTable(MDTable.MemberRef,meth);
\r
6055 public FieldRef AddFieldToTypeSpec (Type item, string name, Type fType) {
\r
6056 FieldRef field = new FieldRef (item.GetTypeSpec (metaData), name,fType);
\r
6057 metaData.AddToTable (MDTable.MemberRef,field);
\r
6061 public void AddMethodSpec (Method m, GenericMethodSig g_sig)
6063 MethodSpec ms = new MethodSpec (m, g_sig);
6064 metaData.AddToTable (MDTable.MethodSpec, ms);
6068 /// Add a "global" field to this module
\r
6070 /// <param name="name">field name</param>
\r
6071 /// <param name="fType">field type</param>
\r
6072 /// <returns>a descriptor for this new "global" field</returns>
\r
6073 public FieldDef AddField(string name, Type fType) {
\r
6074 return moduleClass.AddField(name,fType);
\r
6078 /// Add a "global" field to this module
\r
6080 /// <param name="attrSet">attributes of this field</param>
\r
6081 /// <param name="name">field name</param>
\r
6082 /// <param name="fType">field type</param>
\r
6083 /// <returns>a descriptor for this new "global" field</returns>
\r
6084 public FieldDef AddField(FieldAttr attrSet, string name, Type fType) {
\r
6085 return moduleClass.AddField(attrSet,name,fType);
\r
6089 /// Add a class to this module
\r
6091 /// <param name="attrSet">attributes of this class</param>
\r
6092 /// <param name="nsName">name space name</param>
\r
6093 /// <param name="name">class name</param>
\r
6094 /// <returns>a descriptor for this new class</returns>
\r
6095 public ClassDef AddClass(TypeAttr attrSet, string nsName, string name) {
\r
6096 ClassDef aClass = new ClassDef(attrSet,nsName,name,metaData);
\r
6097 metaData.AddToTable(MDTable.TypeDef,aClass);
\r
6102 /// Add a class which extends System.ValueType to this module
\r
6104 /// <param name="attrSet">attributes of this class</param>
\r
6105 /// <param name="nsName">name space name</param>
\r
6106 /// <param name="name">class name</param>
\r
6107 /// <returns>a descriptor for this new class</returns>
\r
6108 public ClassDef AddValueClass(TypeAttr attrSet, string nsName, string name) {
\r
6109 ClassDef aClass = new ClassDef(attrSet,nsName,name,metaData);
\r
6110 aClass.MakeValueClass();
\r
6111 metaData.AddToTable(MDTable.TypeDef,aClass);
\r
6116 /// Add a class to this module
\r
6118 /// <param name="attrSet">attributes of this class</param>
\r
6119 /// <param name="nsName">name space name</param>
\r
6120 /// <param name="name">class name</param>
\r
6121 /// <param name="superType">super type of this class (extends)</param>
\r
6122 /// <returns>a descriptor for this new class</returns>
\r
6123 public ClassDef AddClass(TypeAttr attrSet, string nsName, string name, Class superType) {
\r
6124 ClassDef aClass = new ClassDef(attrSet,nsName,name,metaData);
\r
6125 aClass.SetSuper(superType);
\r
6126 metaData.AddToTable(MDTable.TypeDef,aClass);
\r
6130 public FileRef AddFile(string fName, byte[] hashBytes, bool hasMetaData, bool entryPoint) {
\r
6131 FileRef file = new FileRef(fName,hashBytes,hasMetaData,entryPoint,metaData);
\r
6132 metaData.AddToTable(MDTable.File,file);
\r
6137 /// Add a manifest resource to this PEFile NOT YET IMPLEMENTED
\r
6139 /// <param name="mr"></param>
\r
6140 public void AddManifestResource(ManifestResource mr) {
\r
6141 metaData.AddToTable(MDTable.ManifestResource,mr);
\r
6142 //mr.FixName(metaData);
\r
6146 /// Write out the PEFile (the "bake" function)
\r
6148 public void WritePEFile() { /* the "bake" function */
\r
6149 fileImage.MakeFile();
\r
6153 /// Get the descriptor of this module
\r
6155 /// <returns>the descriptor for this module</returns>
\r
6156 public Module GetThisModule() {
\r
6161 /// Get the descriptor for this assembly. The PEFile must have been
\r
6162 /// created with hasAssembly = true
\r
6164 /// <returns>the descriptor for this assembly</returns>
\r
6165 public Assembly GetThisAssembly() {
\r
6166 return thisAssembly;
\r
6171 /**************************************************************************/
\r
6173 /// Descriptor for the Primitive types defined in IL
\r
6175 public class PrimitiveType : Type
\r
6177 private string name;
\r
6178 private int systemTypeIndex;
\r
6179 public static int NumSystemTypes = 18;
\r
6181 public static readonly PrimitiveType Void = new PrimitiveType(0x01,"Void",0);
\r
6182 public static readonly PrimitiveType Boolean = new PrimitiveType(0x02,"Boolean",1);
\r
6183 public static readonly PrimitiveType Char = new PrimitiveType(0x03,"Char",2);
\r
6184 public static readonly PrimitiveType Int8 = new PrimitiveType(0x04,"SByte",3);
\r
6185 public static readonly PrimitiveType UInt8 = new PrimitiveType(0x05,"Byte",4);
\r
6186 public static readonly PrimitiveType Int16 = new PrimitiveType(0x06,"Int16",5);
\r
6187 public static readonly PrimitiveType UInt16 = new PrimitiveType(0x07,"UInt16",6);
\r
6188 public static readonly PrimitiveType Int32 = new PrimitiveType(0x08,"Int32",7);
\r
6189 public static readonly PrimitiveType UInt32 = new PrimitiveType(0x09,"UInt32",8);
\r
6190 public static readonly PrimitiveType Int64 = new PrimitiveType(0x0A,"Int64",9);
\r
6191 public static readonly PrimitiveType UInt64 = new PrimitiveType(0x0B,"UInt64",10);
\r
6192 public static readonly PrimitiveType Float32 = new PrimitiveType(0x0C,"Single",11);
\r
6193 public static readonly PrimitiveType Float64 = new PrimitiveType(0x0D,"Double",12);
\r
6194 public static readonly PrimitiveType String = new PrimitiveType(0x0E,"String",13);
\r
6195 internal static readonly PrimitiveType Class = new PrimitiveType(0x12);
\r
6196 public static readonly PrimitiveType TypedRef = new PrimitiveType(0x16,"TypedReference",14);
\r
6197 public static readonly PrimitiveType IntPtr = new PrimitiveType(0x18,"IntPtr",15);
\r
6198 public static readonly PrimitiveType UIntPtr = new PrimitiveType(0x19,"UIntPtr",16);
\r
6199 public static readonly PrimitiveType Object = new PrimitiveType(0x1C,"Object",17);
\r
6200 internal static readonly PrimitiveType ClassType = new PrimitiveType(0x50);
\r
6201 public static readonly PrimitiveType NativeInt = IntPtr;
\r
6202 public static readonly PrimitiveType NativeUInt = UIntPtr;
\r
6204 internal PrimitiveType(byte typeIx) : base(typeIx) { }
\r
6206 internal PrimitiveType(byte typeIx, string name, int STIx) : base(typeIx) {
\r
6208 this.systemTypeIndex = STIx;
\r
6211 internal string GetName() { return name; }
\r
6213 internal int GetSystemTypeIx() { return systemTypeIndex; }
\r
6215 internal sealed override void TypeSig(MemoryStream str) {
\r
6216 str.WriteByte(typeIndex);
\r
6219 internal override MetaDataElement GetTypeSpec(MetaData md) {
\r
6220 TypeSpec tS = md.GetPrimitiveTypeSpec(systemTypeIndex);
\r
6222 tS = new TypeSpec(this,md);
\r
6223 md.SetPrimitiveTypeSpec(systemTypeIndex,tS);
\r
6224 md.AddToTable(MDTable.TypeSpec,tS);
\r
6231 /**************************************************************************/
\r
6233 /// Descriptor for the Property of a class
\r
6235 public class Property : Feature
\r
6237 private static readonly byte PropertyTag = 0x8;
\r
6238 MethodDef getterMeth;
\r
6239 ConstantElem constVal;
\r
6240 uint typeBlobIx = 0;
\r
6245 internal Property(string name, Type retType, Type[] pars, ClassDef parent) : base(name, parent) {
\r
6246 returnType = retType;
\r
6248 if (pars != null) numPars = (uint)pars.Length;
\r
6249 tabIx = MDTable.Property;
\r
6253 /// Add a set method to this property
\r
6255 /// <param name="setter">the set method</param>
\r
6256 public void AddSetter(MethodDef setter) {
\r
6257 AddMethod(setter,MethodType.Setter);
\r
6261 /// Add a get method to this property
\r
6263 /// <param name="getter">the get method</param>
\r
6264 public void AddGetter(MethodDef getter) {
\r
6265 AddMethod(getter,MethodType.Getter);
\r
6266 getterMeth = getter;
\r
6270 /// Add another method to this property
\r
6272 /// <param name="other">the method</param>
\r
6273 public void AddOther(MethodDef other) {
\r
6274 AddMethod(other,MethodType.Other);
\r
6278 /// Add an initial value for this property
\r
6280 /// <param name="constVal">the initial value for this property</param>
\r
6281 public void AddInitValue(Constant constVal) {
\r
6282 this.constVal = new ConstantElem(this,constVal);
\r
6285 internal sealed override void BuildTables(MetaData md) {
\r
6287 nameIx = md.AddToStringsHeap(name);
\r
6288 MemoryStream sig = new MemoryStream();
\r
6289 sig.WriteByte(PropertyTag);
\r
6290 MetaData.CompressNum(numPars,sig);
\r
6291 returnType.TypeSig(sig);
\r
6292 for (int i=0; i < numPars; i++) {
\r
6293 parList[i].TypeSig(sig);
\r
6295 typeBlobIx = md.AddToBlobHeap(sig.ToArray());
\r
6296 for (int i=0; i < tide; i++) {
\r
6297 md.AddToTable(MDTable.MethodSemantics,methods[i]);
\r
6299 if (constVal != null) {
\r
6300 md.AddToTable(MDTable.Constant,constVal);
\r
6301 constVal.BuildTables(md);
\r
6306 internal sealed override uint Size(MetaData md) {
\r
6307 return 2 + md.StringsIndexSize() + md.BlobIndexSize();
\r
6310 internal sealed override void Write(FileImage output) {
\r
6311 output.Write(flags);
\r
6312 output.StringsIndex(nameIx);
\r
6313 output.BlobIndex(typeBlobIx);
\r
6316 internal sealed override uint GetCodedIx(CIx code) {
\r
6318 case (CIx.HasCustomAttr) : return 9;
\r
6319 case (CIx.HasConst) : return 2;
\r
6320 case (CIx.HasSemantics) : return 1;
\r
6326 /**************************************************************************/
\r
6328 /// Descriptor for an pointer (type * or type &)
\r
6330 public abstract class PtrType : Type
\r
6334 internal PtrType(Type bType, byte typeIx) : base(typeIx)
\r
6337 tabIx = MDTable.TypeSpec;
\r
6340 internal sealed override void TypeSig(MemoryStream str) {
\r
6341 str.WriteByte(typeIndex);
\r
6342 baseType.TypeSig(str);
\r
6346 /**************************************************************************/
\r
6348 /// Descriptor for a managed pointer (type & or byref)
\r
6351 public class ManagedPointer : PtrType // <type> & (BYREF)
\r
6355 /// Create new managed pointer to baseType
\r
6357 /// <param name="bType">the base type of the pointer</param>
\r
6358 public ManagedPointer(Type baseType) : base(baseType,0x10) { }
\r
6361 /**************************************************************************/
\r
6363 /// Descriptor for an unmanaged pointer (type *)
\r
6365 public class UnmanagedPointer : PtrType // PTR
\r
6368 /// Create a new unmanaged pointer to baseType
\r
6370 /// <param name="baseType">the base type of the pointer</param>
\r
6371 public UnmanagedPointer(Type baseType) : base(baseType, 0x0F) { }
\r
6374 /**************************************************************************/
\r
6376 /// Base class for scopes (extended by Module, ModuleRef, Assembly, AssemblyRef)
\r
6378 public abstract class ResolutionScope : MetaDataElement
\r
6380 protected uint nameIx = 0;
\r
6381 protected MetaData metaData;
\r
6382 protected string name;
\r
6384 internal ResolutionScope(string name, MetaData md)
\r
6388 nameIx = md.AddToStringsHeap(name);
\r
6391 internal string GetName() { return name; }
\r
6394 /**************************************************************************/
\r
6396 /// Descriptor for a Section in a PEFile eg .text, .sdata
\r
6398 internal class Section {
\r
6399 private static readonly uint relocPageSize = 4096; // 4K pages for fixups
\r
6402 uint offset = 0, tide = 0, size = 0, rva = 0, relocTide = 0;
\r
6403 //uint relocOff = 0;
\r
6404 uint flags = 0, padding = 0;
\r
6407 internal Section(string sName, uint sFlags) {
\r
6408 name = sName.ToCharArray();
\r
6412 internal uint Tide() { return tide; }
\r
6414 internal void IncTide(uint incVal) { tide += incVal; }
\r
6416 internal uint Padding() { return padding; }
\r
6418 internal uint Size() { return size; }
\r
6420 internal void SetSize(uint pad) {
\r
6422 size = tide + padding;
\r
6425 internal uint RVA() { return rva; }
\r
6427 internal void SetRVA(uint rva) { this.rva = rva; }
\r
6429 internal uint Offset() { return offset; }
\r
6431 internal void SetOffset(uint offs) { offset = offs; }
\r
6433 internal void DoBlock(BinaryWriter reloc, uint page, int start, int end) {
\r
6434 //Console.WriteLine("rva = " + rva + " page = " + page);
\r
6435 reloc.Write(rva + page);
\r
6436 reloc.Write((uint)(((end-start+1)*2) + 8));
\r
6437 for (int j=start; j < end; j++) {
\r
6438 //Console.WriteLine("reloc offset = " + relocs[j]);
\r
6439 reloc.Write((ushort)((0x3 << 12) | (relocs[j] - page)));
\r
6441 reloc.Write((ushort)0);
\r
6444 internal void DoRelocs(BinaryWriter reloc) {
\r
6445 if (relocTide > 0) {
\r
6446 //relocOff = (uint)reloc.Seek(0,SeekOrigin.Current);
\r
6447 uint block = (relocs[0]/relocPageSize + 1) * relocPageSize;
\r
6449 for (int i=1; i < relocTide; i++) {
\r
6450 if (relocs[i] >= block) {
\r
6451 DoBlock(reloc,block-relocPageSize,start,i);
\r
6453 block = (relocs[i]/relocPageSize + 1) * relocPageSize;
\r
6456 DoBlock(reloc,block-relocPageSize,start,(int)relocTide);
\r
6460 internal void AddReloc(uint offs) {
\r
6462 if (relocs == null) {
\r
6463 relocs = new uint[5];
\r
6465 if (relocTide >= relocs.Length) {
\r
6466 uint[] tmp = relocs;
\r
6467 relocs = new uint[tmp.Length + 5];
\r
6468 for (int i=0; i < relocTide; i++) {
\r
6469 relocs[i] = tmp[i];
\r
6472 while ((pos < relocTide) && (relocs[pos] < offs)) pos++;
\r
6473 for (int i=pos; i < relocTide; i++) {
\r
6474 relocs[i+1] = relocs[i];
\r
6477 relocs[pos] = offs;
\r
6481 internal void WriteHeader(BinaryWriter output, uint relocRVA) {
\r
6482 output.Write(name);
\r
6483 output.Write(tide);
\r
6484 output.Write(rva);
\r
6485 output.Write(size);
\r
6486 output.Write(offset);
\r
6488 //output.Write(relocRVA + relocOff);
\r
6491 //output.Write((ushort)relocTide);
\r
6492 //output.Write((ushort)0);
\r
6493 output.Write(flags);
\r
6497 /**************************************************************************/
\r
6498 public abstract class Signature : MetaDataElement
\r
6500 protected uint sigIx;
\r
6502 internal Signature() {
\r
6503 tabIx = MDTable.StandAloneSig;
\r
6506 internal sealed override uint Size(MetaData md) {
\r
6507 return md.BlobIndexSize();
\r
6510 internal sealed override void Write(FileImage output) {
\r
6511 output.BlobIndex(sigIx);
\r
6514 internal sealed override uint GetCodedIx(CIx code) { return (uint)tabIx; }
\r
6517 /**************************************************************************/
\r
6519 /// Descriptor for a class defined in System (mscorlib)
\r
6521 internal class SystemClass : ClassRef
\r
6523 PrimitiveType elemType;
\r
6525 internal SystemClass(PrimitiveType eType, AssemblyRef paren, MetaData md)
\r
6526 : base("System",eType.GetName(),md) {
\r
6531 internal override sealed MetaDataElement GetTypeSpec(MetaData md) {
\r
6532 if (typeSpec == null) typeSpec = (TypeSpec)elemType.GetTypeSpec(md);
\r
6537 internal sealed override void TypeSig(MemoryStream str) {
\r
6538 str.WriteByte(elemType.GetTypeIndex());
\r
6542 /**************************************************************************/
\r
6544 /// Base class for all IL types
\r
6546 public abstract class Type : MetaDataElement {
\r
6547 protected byte typeIndex;
\r
6548 protected TypeSpec typeSpec;
\r
6550 internal Type(byte tyIx) { typeIndex = tyIx; }
\r
6552 internal byte GetTypeIndex() { return typeIndex; }
\r
6554 internal virtual MetaDataElement GetTypeSpec(MetaData md) {
\r
6555 if (typeSpec == null) {
\r
6556 typeSpec = new TypeSpec(this,md);
\r
6557 md.AddToTable(MDTable.TypeSpec,typeSpec);
\r
6562 internal virtual void TypeSig(MemoryStream str) {
\r
6563 throw(new TypeSignatureException(this.GetType().AssemblyQualifiedName +
\r
6564 " doesn't have a type signature!!"));
\r
6569 /**************************************************************************/
\r
6571 public class TypeSpec : MetaDataElement {
\r
6574 internal TypeSpec(Type aType, MetaData md) {
\r
6575 MemoryStream sig = new MemoryStream();
\r
6576 aType.TypeSig(sig);
\r
6577 sigIx = md.AddToBlobHeap(sig.ToArray());
\r
6578 tabIx = MDTable.TypeSpec;
\r
6581 internal sealed override uint GetCodedIx(CIx code) {
\r
6583 case (CIx.TypeDefOrRef) : return 2;
\r
6584 case (CIx.HasCustomAttr) : return 13;
\r
6585 case (CIx.MemberRefParent) : return 4;
\r
6590 internal override uint Size(MetaData md) {
\r
6591 return md.BlobIndexSize();
\r
6594 internal sealed override void Write(FileImage output) {
\r
6595 //Console.WriteLine("Writing the blob index for a TypeSpec");
\r
6596 output.BlobIndex(sigIx);
\r