3 using System.Collections;
\r
9 readonly static char[] hexDigit = {'0','1','2','3','4','5','6','7',
\r
10 '8','9','A','B','C','D','E','F'};
\r
11 readonly static uint[] iByteMask = {0x000000FF, 0x0000FF00, 0x00FF0000, 0xFF000000};
\r
12 readonly static ulong[] lByteMask = {0x00000000000000FF, 0x000000000000FF00,
\r
13 0x0000000000FF0000, 0x00000000FF000000,
\r
14 0x000000FF00000000, 0x0000FF0000000000,
\r
15 0x00FF000000000000, 0xFF00000000000000 };
\r
16 readonly static uint nibble0Mask = 0x0000000F;
\r
17 readonly static uint nibble1Mask = 0x000000F0;
\r
19 public static String Byte(int b) {
\r
20 char[] str = new char[2];
\r
22 uint b1 = num & nibble0Mask;
\r
23 uint b2 = (num & nibble1Mask) >> 4;
\r
24 str[0] = hexDigit[b2];
\r
25 str[1] = hexDigit[b1];
\r
26 return new String(str);
\r
29 public static String Short(int b) {
\r
30 char[] str = new char[4];
\r
31 uint num1 = (uint)b & iByteMask[0];
\r
32 uint num2 = ((uint)b & iByteMask[1]) >> 8;
\r
33 uint b1 = num1 & nibble0Mask;
\r
34 uint b2 = (num1 & nibble1Mask) >> 4;
\r
35 uint b3 = num2 & nibble0Mask;
\r
36 uint b4 = (num2 & nibble1Mask) >> 4;
\r
37 str[0] = hexDigit[b4];
\r
38 str[1] = hexDigit[b3];
\r
39 str[2] = hexDigit[b2];
\r
40 str[3] = hexDigit[b1];
\r
41 return new String(str);
\r
44 public static String Int(int val) {
\r
45 char[] str = new char[8];
\r
46 uint num = (uint)val;
\r
48 for (int i=0; i < iByteMask.Length; i++) {
\r
49 uint b = num & iByteMask[i];
\r
51 uint b1 = b & nibble0Mask;
\r
52 uint b2 = (b & nibble1Mask) >> 4;
\r
53 str[strIx--] = hexDigit[b1];
\r
54 str[strIx--] = hexDigit[b2];
\r
56 return new String(str);
\r
59 public static String Int(uint num) {
\r
60 char[] str = new char[8];
\r
62 for (int i=0; i < iByteMask.Length; i++) {
\r
63 uint b = num & iByteMask[i];
\r
65 uint b1 = b & nibble0Mask;
\r
66 uint b2 = (b & nibble1Mask) >> 4;
\r
67 str[strIx--] = hexDigit[b1];
\r
68 str[strIx--] = hexDigit[b2];
\r
70 return new String(str);
\r
73 public static String Long(long lnum) {
\r
74 ulong num = (ulong)lnum;
\r
75 char[] str = new char[16];
\r
77 for (int i=0; i < lByteMask.Length; i++) {
\r
78 ulong b = num & lByteMask[i];
\r
80 ulong b1 = b & nibble0Mask;
\r
81 ulong b2 = (b & nibble1Mask) >> 4;
\r
82 str[strIx--] = hexDigit[b1];
\r
83 str[strIx--] = hexDigit[b2];
\r
85 return new String(str);
\r
89 public class NotYetImplementedException : System.Exception
\r
91 public NotYetImplementedException(string msg) : base(msg + " Not Yet Implemented") { }
\r
94 public class TypeSignatureException : System.Exception {
\r
95 public TypeSignatureException(string msg) : base(msg) { }
\r
98 public class ClassRefInst : Type {
\r
101 private bool is_value;
103 public ClassRefInst (Class type, bool is_value) : base (0x12) {
\r
105 this.is_value = is_value;
108 tabIx = MDTable.TypeSpec;
\r
111 internal sealed override void TypeSig(MemoryStream str) {
\r
112 str.WriteByte (GetTypeIndex());
113 MetaData.CompressNum (type.TypeDefOrRefToken(), str);
\r
117 public class MVar : Type {
\r
121 public MVar (int index) : base (0x1E) {
\r
122 this.index = index;
\r
123 tabIx = MDTable.TypeSpec;
\r
126 internal sealed override void TypeSig(MemoryStream str) {
\r
127 str.WriteByte(typeIndex);
\r
128 MetaData.CompressNum ((uint) index, str);
\r
132 public class GenericTypeSpec : Type {
\r
136 public GenericTypeSpec (int index) : base (0x13) {
\r
137 this.index = index;
\r
138 tabIx = MDTable.TypeSpec;
\r
141 internal sealed override void TypeSig(MemoryStream str) {
\r
142 str.WriteByte(typeIndex);
\r
143 MetaData.CompressNum ((uint) index, str);
\r
147 public class GenericTypeInst : Type {
\r
149 private Type gen_type;
\r
150 private Type[] gen_param;
\r
152 public GenericTypeInst (Type gen_type, Type[] gen_param) : base (0x15)
\r
155 this.gen_type = gen_type;
\r
156 this.gen_param = gen_param;
\r
157 tabIx = MDTable.TypeSpec;
\r
160 internal sealed override void TypeSig(MemoryStream str) {
\r
161 str.WriteByte(typeIndex);
\r
162 gen_type.TypeSig (str);
\r
163 MetaData.CompressNum ((uint) gen_param.Length, str);
\r
164 foreach (Type param in gen_param)
\r
165 param.TypeSig (str);
\r
169 public class GenericMethodSig {
171 private Type[] gen_param;
173 public GenericMethodSig (Type[] gen_param)
175 this.gen_param = gen_param;
178 internal void TypeSig (MemoryStream str)
180 MetaData.CompressNum ((uint) gen_param.Length, str); // THIS IS NOT RIGHT, but works
181 MetaData.CompressNum ((uint) gen_param.Length, str);
182 foreach (Type param in gen_param)
186 internal uint GetSigIx (MetaData md)
188 MemoryStream sig = new MemoryStream();
190 return md.AddToBlobHeap (sig.ToArray());
194 public class Sentinel : Type {
196 public Sentinel () : base (0x41) { }
198 internal sealed override void TypeSig(MemoryStream str) {
199 str.WriteByte(typeIndex);
204 /// The IL Array type
\r
206 public abstract class Array : Type
\r
209 protected Type elemType;
\r
210 protected MetaData metaData;
\r
211 protected string cnameSpace, cname;
\r
213 internal Array(Type eType, byte TypeId) : base(TypeId) {
\r
215 tabIx = MDTable.TypeSpec;
\r
220 /**************************************************************************/
\r
223 /// Single dimensional array with zero lower bound
\r
225 public class ZeroBasedArray : Array {
\r
228 /// Create a new array - elementType[]
\r
230 /// <param name="elementType">the type of the array elements</param>
\r
231 public ZeroBasedArray(Type elementType) : base (elementType,0x1D) { }
\r
233 internal sealed override void TypeSig(MemoryStream str) {
\r
234 str.WriteByte(typeIndex);
\r
235 elemType.TypeSig(str);
\r
241 /**************************************************************************/
\r
244 /// Multi dimensional array with explicit bounds
\r
246 public class BoundArray : Array {
\r
252 /// Create a new multi dimensional array type
\r
253 /// eg. elemType[1..5,3..10,5,,] would be
\r
254 /// new BoundArray(elemType,5,[1,3,0],[5,10,4])
\r
256 /// <param name="elementType">the type of the elements</param>
\r
257 /// <param name="dimensions">the number of dimensions</param>
\r
258 /// <param name="loBounds">lower bounds of dimensions</param>
\r
259 /// <param name="upBounds">upper bounds of dimensions</param>
\r
260 public BoundArray(Type elementType, uint dimensions, int[] loBounds,
\r
261 int[] upBounds) : base (elementType,0x14) {
\r
262 numDims = dimensions;
\r
263 lowerBounds = loBounds;
\r
264 sizes = new int[loBounds.Length];
\r
265 for (int i=0; i < loBounds.Length; i++) {
\r
266 sizes[i] = upBounds[i] - loBounds[i] + 1;
\r
271 /// Create a new multi dimensional array type
\r
272 /// eg. elemType[5,10,20] would be new BoundArray(elemType,3,[5,10,20])
\r
274 /// <param name="elementType">the type of the elements</param>
\r
275 /// <param name="dimensions">the number of dimensions</param>
\r
276 /// <param name="size">the sizes of the dimensions</param>
\r
277 public BoundArray(Type elementType, uint dimensions, int[] size)
\r
278 : base (elementType,0x14) {
\r
279 numDims = dimensions;
\r
284 /// Create a new multi dimensional array type
\r
285 /// eg. elemType[,,] would be new BoundArray(elemType,3)
\r
287 /// <param name="elementType">the type of the elements</param>
\r
288 /// <param name="dimensions">the number of dimensions</param>
\r
289 public BoundArray(Type elementType, uint dimensions)
\r
290 : base (elementType,0x14) {
\r
291 numDims = dimensions;
\r
294 internal sealed override void TypeSig(MemoryStream str) {
\r
295 str.WriteByte(typeIndex);
\r
296 elemType.TypeSig(str);
\r
297 MetaData.CompressNum(numDims,str);
\r
298 if ((sizes != null) && (sizes.Length > 0)) {
\r
299 MetaData.CompressNum((uint)sizes.Length,str);
\r
300 for (int i=0; i < sizes.Length; i++) {
\r
301 MetaData.CompressNum((uint)sizes[i],str);
\r
303 } else str.WriteByte(0);
\r
304 if ((lowerBounds != null) && (lowerBounds.Length > 0)) {
\r
305 MetaData.CompressNum((uint)lowerBounds.Length,str);
\r
306 for (int i=0; i < lowerBounds.Length; i++) {
\r
307 MetaData.CompressNum((uint)lowerBounds[i],str);
\r
309 } else str.WriteByte(0);
\r
313 /**************************************************************************/
\r
315 /// Descriptor for THIS assembly (.assembly)
\r
317 public class Assembly : ResolutionScope
\r
319 ushort majorVer, minorVer, buildNo, revisionNo;
\r
322 uint keyIx = 0, cultIx = 0;
\r
324 internal Assembly(string name, MetaData md) : base(name,md) {
\r
325 tabIx = MDTable.Assembly;
\r
329 /// Add details about THIS assembly
\r
331 /// <param name="majVer">Major Version</param>
\r
332 /// <param name="minVer">Minor Version</param>
\r
333 /// <param name="bldNo">Build Number</param>
\r
334 /// <param name="revNo">Revision Number</param>
\r
335 /// <param name="key">Hash Key</param>
\r
336 /// <param name="hash">Hash Algorithm</param>
\r
337 /// <param name="cult">Culture</param>
\r
338 public void AddAssemblyInfo(int majVer, int minVer, int bldNo, int revNo,
\r
339 byte[] key, uint hash, string cult) {
\r
340 majorVer = (ushort)majVer;
\r
341 minorVer = (ushort)minVer;
\r
342 buildNo = (ushort)bldNo;
\r
343 revisionNo = (ushort)revNo;
\r
345 keyIx = metaData.AddToBlobHeap(key);
\r
346 cultIx = metaData.AddToStringsHeap(cult);
\r
350 /// Add an attribute to THIS assembly
\r
352 /// <param name="aa">assembly attribute</param>
\r
353 public void AddAssemblyAttr(AssemAttr aa) {
\r
357 internal sealed override uint Size(MetaData md) {
\r
358 return 16 + md.BlobIndexSize() + 2 * md.StringsIndexSize();
\r
361 internal sealed override void Write(FileImage output) {
\r
362 // Console.WriteLine("Writing assembly element with nameIx of " + nameIx + " at file offset " + output.Seek(0,SeekOrigin.Current));
\r
363 output.Write((uint)hashAlgId);
\r
364 output.Write(majorVer);
\r
365 output.Write(minorVer);
\r
366 output.Write(buildNo);
\r
367 output.Write(revisionNo);
\r
368 output.Write(flags);
\r
369 output.BlobIndex(keyIx);
\r
370 output.StringsIndex(nameIx);
\r
371 output.StringsIndex(cultIx);
\r
374 internal sealed override uint GetCodedIx(CIx code) {
\r
376 case (CIx.HasCustomAttr) : return 14;
\r
377 case (CIx.HasDeclSecurity) : return 2;
\r
383 /**************************************************************************/
\r
385 public interface IExternRef {
386 ClassRef AddClass(string nsName, string name);
387 ClassRef AddValueClass(string nsName, string name);
391 /// A reference to an external assembly (.assembly extern)
\r
393 public class AssemblyRef : ResolutionScope, IExternRef
395 private ushort major, minor, build, revision;
\r
396 uint flags, keyIx, hashIx, cultIx;
\r
397 bool hasVersion = false, isKeyToken = false;
\r
401 internal AssemblyRef(MetaData md, string name) : base(name,md) {
\r
402 tabIx = MDTable.AssemblyRef;
\r
406 /// Add version information about this external assembly
\r
408 /// <param name="majVer">Major Version</param>
\r
409 /// <param name="minVer">Minor Version</param>
\r
410 /// <param name="bldNo">Build Number</param>
\r
411 /// <param name="revNo">Revision Number</param>
\r
412 public void AddVersionInfo(int majVer, int minVer, int bldNo, int revNo) {
\r
413 major = (ushort)majVer;
\r
414 minor = (ushort)minVer;
\r
415 build = (ushort)bldNo;
\r
416 revision = (ushort)revNo;
\r
421 /// Add the hash value for this external assembly
\r
423 /// <param name="hash">bytes of the hash value</param>
\r
424 public void AddHash(byte[] hash) {
\r
425 hashIx = metaData.AddToBlobHeap(hash);
\r
429 /// Set the culture for this external assembly
\r
431 /// <param name="cult">the culture string</param>
\r
432 public void AddCulture(string cult) {
\r
433 cultIx = metaData.AddToStringsHeap(cult);
\r
438 /// Add the full public key for this external assembly
\r
440 /// <param name="key">bytes of the public key</param>
\r
441 public void AddKey(byte[] key) {
\r
442 flags |= 0x0001; // full public key
\r
444 keyIx = metaData.AddToBlobHeap(key);
\r
448 /// Add the public key token (low 8 bytes of the public key)
\r
450 /// <param name="key">low 8 bytes of public key</param>
\r
451 public void AddKeyToken(byte[] key) {
\r
452 keyIx = metaData.AddToBlobHeap(key);
\r
458 /// Add a class to this external assembly
\r
460 /// <param name="nsName">name space name</param>
\r
461 /// <param name="name">class name</param>
\r
462 /// <returns></returns>
\r
463 public virtual ClassRef AddClass(string nsName, string name) {
\r
464 ClassRef aClass = new ClassRef(nsName,name,metaData);
\r
465 metaData.AddToTable(MDTable.TypeRef,aClass);
\r
466 aClass.SetParent(this);
\r
471 /// Add a value class to this external assembly
\r
473 /// <param name="nsName">name space name</param>
\r
474 /// <param name="name">class name</param>
\r
475 /// <returns></returns>
\r
476 public virtual ClassRef AddValueClass(string nsName, string name) {
\r
477 ClassRef aClass = new ClassRef(nsName,name,metaData);
\r
478 metaData.AddToTable(MDTable.TypeRef,aClass);
\r
479 aClass.SetParent(this);
\r
480 aClass.MakeValueClass();
\r
484 internal string TypeName() {
\r
485 string result = name;
\r
487 result = result + ", Version=" + major + "." + minor + "." +
\r
488 build + "." + revision;
\r
489 if (keyBytes != null) {
\r
490 string tokenStr = "=";
\r
491 if (isKeyToken) tokenStr = "Token=";
\r
492 result = result + ", PublicKey" + tokenStr;
\r
493 for (int i=0; i < keyBytes.Length; i++) {
\r
494 result = result + Hex.Byte(keyBytes[i]);
\r
497 if (culture != null)
\r
498 result = result + ", Culture=" + culture;
\r
502 internal sealed override uint Size(MetaData md) {
\r
503 return 12 + 2 * md.StringsIndexSize() + 2 * md.BlobIndexSize();
\r
506 internal sealed override void Write(FileImage output) {
\r
507 output.Write(major);
\r
508 output.Write(minor);
\r
509 output.Write(build);
\r
510 output.Write(revision);
\r
511 output.Write(flags);
\r
512 output.BlobIndex(keyIx);
\r
513 output.StringsIndex(nameIx);
\r
514 output.StringsIndex(cultIx);
\r
515 output.BlobIndex(hashIx);
\r
518 internal sealed override uint GetCodedIx(CIx code) {
\r
520 case (CIx.ResolutionScope) : return 2;
\r
521 case (CIx.HasCustomAttr) : return 15;
\r
522 case (CIx.Implementation) : return 1;
\r
528 /**************************************************************************/
\r
531 /// flags for the assembly (.corflags)
\r
533 public enum CorFlags {CF_IL_ONLY, CF_32_BITREQUIRED, CF_STRONGNAMESIGNED,
\r
537 /// subsystem for the assembly (.subsystem)
\r
539 public enum SubSystem { Native = 1, Windows_GUI = 2,
\r
540 Windows_CUI = 3, OS2_CUI = 5, POSIX_CUI = 7, Native_Windows = 8,
\r
541 Windows_CE_GUI = 9}
\r
544 /// Hash algorithms for the assembly
\r
546 public enum HashAlgorithm { None, SHA1 }
\r
549 /// Attributes for this assembly
\r
551 public enum AssemAttr { EnableJITCompileTracking = 0x8000,
\r
552 DisableJITCompileOptimizer = 0x4000}
\r
555 /// Method call conventions
\r
557 public enum CallConv { Default, Cdecl, Stdcall, Thiscall,
\r
558 Fastcall, Vararg, Instance = 0x20, Generic = 0x10, InstanceExplicit = 0x60 }
\r
561 /// Type custom modifier
\r
563 public enum CustomModifier { modreq = 0x1F, modopt };
\r
566 /// Attibutes for a class
\r
568 public enum TypeAttr {Private, Public, NestedPublic, NestedPrivate,
\r
569 NestedFamily, NestedAssembly, NestedFamAndAssem, NestedFamOrAssem,
\r
570 SequentialLayout, ExplicitLayout = 0x10, Interface = 0x20,
\r
571 Abstract = 0x80, PublicAbstract = 0x81, Sealed = 0x100,
\r
572 PublicSealed = 0x101, SpecialName = 0x400, RTSpecialName = 0x800,
\r
573 Import = 0x1000, Serializable = 0x2000, UnicodeClass = 0x10000,
\r
574 AutoClass = 0x20000, BeforeFieldInit = 0x100000 }
\r
577 /// Attributes for a field
\r
579 public enum FieldAttr {Default, Private, FamAndAssem, Assembly,
\r
580 Family, FamOrAssem, Public, Static = 0x10, PublicStatic = 0x16,
\r
581 Initonly = 0x20, Literal = 0x40, Notserialized = 0x80,
\r
582 SpecialName = 0x200, RTSpecialName = 0x400 }
\r
585 /// Attributes for a method
\r
587 public enum MethAttr { Default, Private, FamAndAssem, Assembly,
\r
588 Family, FamOrAssem, Public, Static = 0x0010, PublicStatic = 0x16,
\r
589 Final = 0x0020, PublicStaticFinal = 0x36, Virtual = 0x0040,
\r
590 PrivateVirtual, PublicVirtual = 0x0046, HideBySig = 0x0080,
\r
591 NewSlot = 0x0100, Abstract = 0x0400, SpecialName = 0x0800,
\r
592 RTSpecialName = 0x1000, SpecialRTSpecialName = 0x1800,
\r
593 RequireSecObject = 0x8000}
\r
596 /// Attributes for .pinvokeimpl method declarations
\r
598 public enum PInvokeAttr { nomangle = 1, ansi = 2, unicode = 4, autochar = 6,
599 lasterr = 0x0040, winapi = 0x0100, cdecl = 0x0200,
600 stdcall = 0x0300, thiscall = 0x0400, fastcall = 0x0500 }
\r
603 /// Implementation attributes for a method
\r
605 public enum ImplAttr { IL, Native, Runtime = 0x03, Unmanaged = 0x04,
\r
606 ForwardRef = 0x10, PreserveSig = 0x0080, InternalCall = 0x1000,
\r
607 Synchronised = 0x0020, Synchronized = 0x0020, NoInLining = 0x0008, Optil = 0x0002}
\r
610 /// Modes for a parameter
\r
612 public enum ParamAttr { Default, In, Out, Opt = 4 }
\r
615 /// CIL instructions
\r
617 public enum Op { nop, breakOp, ldarg_0, ldarg_1, ldarg_2, ldarg_3,
\r
618 ldloc_0, ldloc_1, ldloc_2, ldloc_3, stloc_0, stloc_1, stloc_2, stloc_3,
\r
619 ldnull = 0x14, ldc_i4_m1, ldc_i4_0, ldc_i4_1, ldc_i4_2, ldc_i4_3,
\r
620 ldc_i4_4, ldc_i4_5, ldc_i4_6, ldc_i4_7, ldc_i4_8, dup = 0x25, pop,
\r
621 ret = 0x2A, ldind_i1 = 0x46, ldind_u1, ldind_i2, ldind_u2, ldind_i4,
\r
622 ldind_u4, ldind_i8, ldind_i, ldind_r4, ldind_r8, ldind_ref, stind_ref,
\r
623 stind_i1, stind_i2, stind_i4, stind_i8, stind_r4, stind_r8, add, sub, mul,
\r
624 div, div_un, rem, rem_un, and, or, xor, shl, shr, shr_un, neg, not,
\r
625 conv_i1, conv_i2, conv_i4, conv_i8, conv_r4, conv_r8, conv_u4, conv_u8,
\r
626 conv_r_un = 0x76, throwOp = 0x7A, conv_ovf_i1_un = 0x82, conv_ovf_i2_un,
\r
627 conv_ovf_i4_un, conv_ovf_i8_un, conf_ovf_u1_un, conv_ovf_u2_un,
\r
628 conv_ovf_u4_un, conv_ovf_u8_un, conv_ovf_i_un, conv_ovf_u_un,
\r
629 ldlen = 0x8E, ldelem_i1 = 0x90, ldelem_u1, ldelem_i2, ldelem_u2,
\r
630 ldelem_i4, ldelem_u4, ldelem_i8, ldelem_i, ldelem_r4, ldelem_r8,
\r
631 ldelem_ref, stelem_i, stelem_i1, stelem_i2, stelem_i4, stelem_i8, stelem_r4 = 0xA0, stelem_r8,
\r
632 stelem_ref, conv_ovf_i1 = 0xb3, conv_ovf_u1, conv_ovf_i2, conv_ovf_u2,
\r
633 conv_ovf_i4, conv_ovf_u4, conv_ovf_i8, conv_ovf_u8, ckfinite = 0xC3,
\r
634 conv_u2 = 0xD1, conv_u1, conv_i, conv_ovf_i, conv_ovf_u, add_ovf,
\r
635 add_ovf_un, mul_ovf, mul_ovf_un, sub_ovf, sub_ovf_un, endfinally,
\r
636 stind_i = 0xDF, conv_u, arglist = 0xFE00, ceq, cgt, cgt_un, clt, clt_un,
\r
637 localloc = 0xFE0F, endfilter = 0xFE11, volatile_ = 0xFE13, tail_,
\r
638 cpblk = 0xFE17, initblk, rethrow = 0xFE1A, refanytype = 0xFE1D}
\r
641 /// CIL instructions requiring an integer parameter
\r
643 public enum IntOp {ldarg_s = 0x0E, ldarga_s, starg_s, ldloc_s, ldloca_s,
\r
644 stloc_s, ldc_i4_s = 0x1F, ldc_i4, ldarg = 0xFE09,
\r
645 ldarga, starg, ldloc, ldloca, stloc, unaligned = 0xFE12 }
\r
648 /// CIL instructions requiring a field parameter
\r
650 public enum FieldOp {ldfld = 0x7B, ldflda, stfld, ldsfld, ldsflda,
\r
651 stsfld, ldtoken = 0xD0 }
\r
654 /// CIL instructions requiring a method parameter
\r
656 public enum MethodOp {jmp = 0x27, call, callvirt = 0x6F, newobj = 0x73,
\r
657 ldtoken = 0xD0, ldftn = 0xFE06, ldvirtfn }
\r
660 /// CIL instructions requiring a type parameter
\r
662 public enum TypeOp {cpobj = 0x70, ldobj, castclass = 0x74, isinst,
\r
663 unbox = 0x79, stobj = 0x81, box = 0x8C, newarr,
\r
664 ldelema = 0x8F, refanyval = 0xC2, mkrefany = 0xC6,
\r
665 ldtoken = 0xD0, initobj = 0xFE15, sizeOf = 0xFE1C,
\r
666 ldelem = 0xA3, stelem = 0xA4, unbox_any }
\r
669 /// CIL branch instructions
\r
671 public enum BranchOp {
673 br_s = 0x2B, brfalse_s, brtrue_s, beq_s, bge_s, bgt_s,
674 ble_s, blt_s, bne_un_s, bge_un_s, bgt_un_s, ble_un_s, blt_un_s,
676 br = 0x38, brfalse, brtrue, beq, bge, bgt, ble, blt,
\r
677 bne_un, bge_un, bgt_un, ble_un, blt_un,
679 leave = 0xDD, leave_s }
\r
682 /// Index for all the tables in the meta data
\r
684 public enum MDTable { Module, TypeRef, TypeDef, Field = 0x04, Method = 0x06,
\r
685 Param = 0x08, InterfaceImpl, MemberRef, Constant, CustomAttribute,
\r
686 FieldMarshal, DeclSecurity, ClassLayout, FieldLayout, StandAloneSig,
\r
687 EventMap, Event = 0x14, PropertyMap, Property = 0x17, MethodSemantics,
\r
688 MethodImpl, ModuleRef, TypeSpec, ImplMap, FieldRVA, Assembly = 0x20,
\r
689 AssemblyProcessor, AssemblyOS, AssemblyRef, AssemblyRefProcessor,
\r
690 AssemblyRefOS, File, ExportedType, ManifestResource, NestedClass,
\r
691 GenericParam, MethodSpec, GenericParamConstraint }
\r
693 public enum SafeArrayType { int16 = 2, int32, float32, float64,
\r
694 currency, date, bstr, dispatch, error, boolean, variant, unknown,
\r
695 Decimal, int8 = 16, uint8, uint16, uint32, Int = 22, UInt }
\r
697 internal enum CIx { TypeDefOrRef, HasConst, HasCustomAttr, HasFieldMarshal,
\r
698 HasDeclSecurity, MemberRefParent, HasSemantics, MethodDefOrRef,
\r
699 MemberForwarded, Implementation, CustomAttributeType, ResolutionScope,
\r
700 TypeOrMethodDef, MaxCIx }
\r
702 internal enum MapType { eventMap, propertyMap, nestedClass }
\r
704 /**************************************************************************/
\r
706 /// The assembly for mscorlib.
\r
708 public sealed class MSCorLib : AssemblyRef
\r
710 private static readonly int valueTypeIx = 18;
\r
711 private readonly string systemName = "System";
\r
712 private ClassRef[] systemClasses = new ClassRef[valueTypeIx+2];
\r
713 private PrimitiveType[] systemTypes = new PrimitiveType[valueTypeIx];
\r
714 private TypeSpec[] specialTypeSpecs = new TypeSpec[valueTypeIx];
\r
715 private static int[] specialNames = {
\r
716 PrimitiveType.Void.GetName().GetHashCode(),
\r
717 PrimitiveType.Boolean.GetName().GetHashCode(),
\r
718 PrimitiveType.Char.GetName().GetHashCode(),
\r
719 PrimitiveType.Int8.GetName().GetHashCode(),
\r
720 PrimitiveType.UInt8.GetName().GetHashCode(),
\r
721 PrimitiveType.Int16.GetName().GetHashCode(),
\r
722 PrimitiveType.UInt16.GetName().GetHashCode(),
\r
723 PrimitiveType.Int32.GetName().GetHashCode(),
\r
724 PrimitiveType.UInt32.GetName().GetHashCode(),
\r
725 PrimitiveType.Int64.GetName().GetHashCode(),
\r
726 PrimitiveType.UInt64.GetName().GetHashCode(),
\r
727 PrimitiveType.Float32.GetName().GetHashCode(),
\r
728 PrimitiveType.Float64.GetName().GetHashCode(),
\r
729 PrimitiveType.String.GetName().GetHashCode(),
\r
730 PrimitiveType.TypedRef.GetName().GetHashCode(),
\r
731 PrimitiveType.IntPtr.GetName().GetHashCode(),
\r
732 PrimitiveType.UIntPtr.GetName().GetHashCode(),
\r
733 PrimitiveType.Object.GetName().GetHashCode(),
\r
734 "ValueType".GetHashCode(),
\r
735 "Enum".GetHashCode()
\r
738 internal MSCorLib(MetaData md) : base(md,"mscorlib") {
\r
739 md.AddToTable(MDTable.AssemblyRef,this);
\r
740 systemTypes[PrimitiveType.Void.GetSystemTypeIx()] = PrimitiveType.Void;
\r
741 systemTypes[PrimitiveType.Boolean.GetSystemTypeIx()] = PrimitiveType.Boolean;
\r
742 systemTypes[PrimitiveType.Char.GetSystemTypeIx()] = PrimitiveType.Char;
\r
743 systemTypes[PrimitiveType.Int8.GetSystemTypeIx()] = PrimitiveType.Int8;
\r
744 systemTypes[PrimitiveType.UInt8.GetSystemTypeIx()] = PrimitiveType.UInt8;
\r
745 systemTypes[PrimitiveType.Int16.GetSystemTypeIx()] = PrimitiveType.Int16;
\r
746 systemTypes[PrimitiveType.UInt16.GetSystemTypeIx()] = PrimitiveType.UInt16;
\r
747 systemTypes[PrimitiveType.Int32.GetSystemTypeIx()] = PrimitiveType.Int32;
\r
748 systemTypes[PrimitiveType.UInt32.GetSystemTypeIx()] = PrimitiveType.UInt32;
\r
749 systemTypes[PrimitiveType.Int64.GetSystemTypeIx()] = PrimitiveType.Int64;
\r
750 systemTypes[PrimitiveType.UInt64.GetSystemTypeIx()] = PrimitiveType.UInt64;
\r
751 systemTypes[PrimitiveType.Float32.GetSystemTypeIx()] = PrimitiveType.Float32;
\r
752 systemTypes[PrimitiveType.Float64.GetSystemTypeIx()] = PrimitiveType.Float64;
\r
753 systemTypes[PrimitiveType.IntPtr.GetSystemTypeIx()] = PrimitiveType.IntPtr;
\r
754 systemTypes[PrimitiveType.UIntPtr.GetSystemTypeIx()] = PrimitiveType.UIntPtr;
\r
755 systemTypes[PrimitiveType.String.GetSystemTypeIx()] = PrimitiveType.String;
\r
756 systemTypes[PrimitiveType.Object.GetSystemTypeIx()] = PrimitiveType.Object;
\r
757 systemTypes[PrimitiveType.TypedRef.GetSystemTypeIx()] = PrimitiveType.TypedRef;
\r
761 /// Add a class to the mscorlib assembly
\r
763 /// <param name="nsName">name space name</param>
\r
764 /// <param name="name">class name</param>
\r
765 /// <returns></returns>
\r
766 public override ClassRef AddClass(string nsName, string name) {
\r
767 ClassRef aClass = GetSpecialClass(nsName,name);
\r
768 if (aClass == null) {
\r
769 aClass = new ClassRef(nsName,name,metaData);
\r
770 metaData.AddToTable(MDTable.TypeRef,aClass);
\r
771 aClass.SetParent(this);
\r
776 private ClassRef GetSpecialClass(string nsName,string name) {
\r
777 if (nsName.CompareTo(systemName) != 0) return null;
\r
778 int hash = name.GetHashCode();
\r
779 for (int i=0; i < specialNames.Length; i++) {
\r
780 if (hash == specialNames[i]) {
\r
781 if (systemClasses[i] == null) {
\r
782 if (i < valueTypeIx) {
\r
783 systemClasses[i] = new SystemClass(systemTypes[i],this,metaData);
\r
784 if ((systemTypes[i] != PrimitiveType.Object) &&
\r
785 (systemTypes[i] != PrimitiveType.String)) {
\r
786 systemClasses[i].MakeValueClass();
\r
789 systemClasses[i] = new ClassRef(nsName,name,metaData);
\r
790 systemClasses[i].SetParent(this);
\r
791 systemClasses[i].MakeValueClass();
\r
793 metaData.AddToTable(MDTable.TypeRef,systemClasses[i]);
\r
795 return systemClasses[i];
\r
801 internal ClassRef GetSpecialSystemClass(PrimitiveType pType) {
\r
802 int ix = pType.GetSystemTypeIx();
\r
803 if (systemClasses[ix] == null) {
\r
804 systemClasses[ix] = new SystemClass(pType,this,metaData);
\r
805 metaData.AddToTable(MDTable.TypeRef,systemClasses[ix]);
\r
807 return systemClasses[ix];
\r
810 private ClassRef GetValueClass(string name, int hash) {
\r
811 int ix = valueTypeIx;
\r
812 if (hash != specialNames[valueTypeIx]) ix++;
\r
813 if (systemClasses[ix] == null) {
\r
814 systemClasses[ix] = new ClassRef(systemName,name,metaData);
\r
815 systemClasses[ix].SetParent(this);
\r
816 systemClasses[ix].MakeValueClass();
\r
817 metaData.AddToTable(MDTable.TypeRef,systemClasses[ix]);
\r
819 return systemClasses[ix];
\r
822 internal ClassRef ValueType() {
\r
823 if (systemClasses[valueTypeIx] == null) {
\r
824 ClassRef valType = new ClassRef("System","ValueType",metaData);
\r
825 valType.SetParent(this);
\r
826 valType.MakeValueClass();
\r
827 metaData.AddToTable(MDTable.TypeRef,valType);
\r
828 systemClasses[valueTypeIx] = valType;
\r
830 return systemClasses[valueTypeIx];
\r
834 /// Add a value class to this external assembly
\r
836 /// <param name="nsName">name space name</param>
\r
837 /// <param name="name">class name</param>
\r
838 /// <returns></returns>
\r
839 public override ClassRef AddValueClass(string nsName, string name) {
\r
840 if (nsName.CompareTo(systemName) == 0) {
\r
841 int hash = name.GetHashCode();
\r
842 if ((hash == specialNames[valueTypeIx]) ||
\r
843 (hash == specialNames[valueTypeIx+1])) {
\r
844 return GetValueClass(name,hash);
\r
847 ClassRef aClass = new ClassRef(nsName,name,metaData);
\r
848 metaData.AddToTable(MDTable.TypeRef,aClass);
\r
849 aClass.SetParent(this);
\r
850 aClass.MakeValueClass();
\r
855 /**************************************************************************/
\r
857 /// Signature for calli instruction
\r
859 public class CalliSig : Signature
\r
861 private static readonly byte Sentinel = 0x41;
\r
864 Type[] parameters, optParams;
\r
865 uint numPars = 0, numOptPars = 0;
\r
868 /// Create a signature for a calli instruction
\r
870 /// <param name="cconv">calling conventions</param>
\r
871 /// <param name="retType">return type</param>
\r
872 /// <param name="pars">parameter types</param>
\r
873 public CalliSig(CallConv cconv, Type retType, Type[] pars) {
\r
874 tabIx = MDTable.StandAloneSig;
\r
876 returnType = retType;
\r
878 if (pars != null) numPars = (uint)pars.Length;
\r
882 /// Add the optional parameters to a vararg method
\r
883 /// This method sets the vararg calling convention
\r
885 /// <param name="optPars">the optional pars for the vararg call</param>
\r
886 public void AddVarArgs(Type[] optPars) {
\r
887 optParams = optPars;
\r
888 if (optPars != null) numOptPars = (uint)optPars.Length;
\r
889 callConv |= CallConv.Vararg;
\r
893 /// Add extra calling conventions to this callsite signature
\r
895 /// <param name="cconv"></param>
\r
896 public void AddCallingConv(CallConv cconv) {
\r
900 internal sealed override void BuildTables(MetaData md) {
\r
902 MemoryStream sig = new MemoryStream();
\r
903 sig.WriteByte((byte)callConv);
\r
904 MetaData.CompressNum(numPars+numOptPars,sig);
\r
905 returnType.TypeSig(sig);
\r
906 for (int i=0; i < numPars; i++) {
\r
907 parameters[i].TypeSig(sig);
\r
909 sigIx = md.AddToBlobHeap(sig.ToArray());
\r
910 if (numOptPars > 0) {
\r
911 sig.WriteByte(Sentinel);
\r
912 for (int i=0; i < numOptPars; i++) {
\r
913 optParams[i].TypeSig(sig);
\r
920 /**************************************************************************/
\r
922 /// The IL instructions for a method
\r
924 public class CILInstructions
\r
927 private static readonly uint ExHeaderSize = 4;
\r
928 private static readonly uint FatExClauseSize = 24;
\r
929 private static readonly uint SmlExClauseSize = 12;
\r
930 private static readonly sbyte maxByteVal = 127;
\r
931 private static readonly sbyte minByteVal = -128;
\r
932 private static readonly byte maxUByteVal = 255;
\r
933 private static readonly int smallSize = 64;
\r
934 private static readonly ushort TinyFormat = 0x2;
\r
935 private static readonly ushort FatFormat = 0x3003;
\r
936 private static readonly ushort MoreSects = 0x8;
\r
937 private static readonly ushort InitLocals = 0x10;
\r
938 private static readonly uint FatSize = 12;
\r
939 private static readonly uint FatWords = FatSize/4;
\r
940 private static readonly byte FatExceptTable = 0x41;
\r
941 private static readonly byte SmlExceptTable = 0x01;
\r
943 private MetaData metaData;
\r
944 private ArrayList exceptions, blockStack;
\r
945 //private bool codeChecked = false;
\r
946 private static readonly int INITSIZE = 5;
\r
947 private CILInstruction[] buffer = new CILInstruction[INITSIZE];
\r
948 private int tide = 0;
\r
949 private uint offset = 0;
\r
950 private ushort headerFlags = 0;
\r
951 private short maxStack;
\r
952 private uint paddingNeeded = 0;
\r
953 private byte exceptHeader = 0;
\r
954 uint localSigIx = 0;
\r
955 uint codeSize = 0, exceptSize = 0;
\r
956 bool tinyFormat, fatExceptionFormat = false;
\r
958 internal CILInstructions(MetaData md) {
\r
962 private void AddToBuffer(CILInstruction inst) {
\r
963 if (tide >= buffer.Length) {
\r
964 CILInstruction[] tmp = buffer;
\r
965 buffer = new CILInstruction[tmp.Length * 2];
\r
966 for (int i=0; i < tide; i++) {
\r
967 buffer[i] = tmp[i];
\r
970 //Console.WriteLine("Adding instruction at offset " + offset + " with size " + inst.size);
\r
971 inst.offset = offset;
\r
972 offset += inst.size;
\r
973 buffer[tide++] = inst;
\r
977 /// Add a simple IL instruction
\r
979 /// <param name="inst">the IL instruction</param>
\r
980 public void Inst(Op inst) {
\r
981 AddToBuffer(new Instr((int)inst));
\r
985 /// Add an IL instruction with an integer parameter
\r
987 /// <param name="inst">the IL instruction</param>
\r
988 /// <param name="val">the integer parameter value</param>
\r
989 public void IntInst(IntOp inst, int val) {
\r
990 int instr = (int)inst;
\r
991 if ((inst == IntOp.ldc_i4_s) || (inst == IntOp.ldc_i4))
\r
992 AddToBuffer(new IntInstr(instr,val,(inst == IntOp.ldc_i4_s)));
\r
994 AddToBuffer(new UIntInstr(instr,val,((inst < IntOp.ldc_i4_s) ||
\r
995 (inst == IntOp.unaligned))));
\r
999 /// Add the load long instruction
\r
1001 /// <param name="cVal">the long value</param>
\r
1002 public void ldc_i8(long cVal) {
\r
1003 AddToBuffer(new LongInstr(0x21,cVal));
\r
1007 /// Add the load float32 instruction
\r
1009 /// <param name="cVal">the float value</param>
\r
1010 public void ldc_r4(float cVal) {
\r
1011 AddToBuffer(new FloatInstr(0x22,cVal));
\r
1015 /// Add the load float64 instruction
\r
1017 /// <param name="cVal">the float value</param>
\r
1018 public void ldc_r8(double cVal) {
\r
1019 AddToBuffer(new DoubleInstr(0x23,cVal));
\r
1023 /// Add the load string instruction
\r
1025 /// <param name="str">the string value</param>
\r
1026 public void ldstr(string str) {
\r
1027 AddToBuffer(new StringInstr(0x72,str));
\r
1031 /// Add the load string instruction
1033 public void ldstr (byte[] str) {
1034 AddToBuffer (new StringInstr (0x72, str));
1038 /// Add the calli instruction
\r
1040 /// <param name="sig">the signature for the calli</param>
\r
1041 public void calli(CalliSig sig) {
\r
1042 AddToBuffer(new SigInstr(0x29,sig));
\r
1046 /// Add a label to the CIL instructions
\r
1048 /// <param name="lab">the label to be added</param>
\r
1049 public void CodeLabel(CILLabel lab) {
\r
1050 AddToBuffer(new LabelInstr(lab));
\r
1054 /// Add an instruction with a field parameter
\r
1056 /// <param name="inst">the CIL instruction</param>
\r
1057 /// <param name="f">the field parameter</param>
\r
1058 public void FieldInst(FieldOp inst, Field f) {
\r
1059 AddToBuffer(new FieldInstr((int)inst,f));
\r
1063 /// Add an instruction with a method parameter
\r
1065 /// <param name="inst">the CIL instruction</param>
\r
1066 /// <param name="m">the method parameter</param>
\r
1067 public void MethInst(MethodOp inst, Method m) {
\r
1068 AddToBuffer(new MethInstr((int)inst,m));
\r
1072 /// Add an instruction with a type parameter
\r
1074 /// <param name="inst">the CIL instruction</param>
\r
1075 /// <param name="t">the type argument for the CIL instruction</param>
\r
1076 public void TypeInst(TypeOp inst, Type aType) {
\r
1077 AddToBuffer(new TypeInstr((int)inst,aType,metaData));
\r
1081 /// Add a branch instruction
\r
1083 /// <param name="inst">the branch instruction</param>
\r
1084 /// <param name="lab">the label that is the target of the branch</param>
\r
1085 public void Branch(BranchOp inst, CILLabel lab) {
\r
1086 AddToBuffer(new BranchInstr((int)inst,lab));
\r
1090 /// Add a switch instruction
\r
1092 /// <param name="labs">the target labels for the switch</param>
\r
1093 public void Switch(CILLabel[] labs) {
\r
1094 AddToBuffer(new SwitchInstr(0x45,labs));
\r
1098 /// Add a byte to the CIL instructions (.emitbyte)
\r
1100 /// <param name="bVal"></param>
\r
1101 public void emitbyte(byte bVal) {
\r
1102 AddToBuffer(new CILByte(bVal));
\r
1106 /// Add an instruction which puts an integer on TOS. This method
\r
1107 /// selects the correct instruction based on the value of the integer.
\r
1109 /// <param name="i">the integer value</param>
\r
1110 public void PushInt(int i) {
\r
1112 AddToBuffer(new Instr((int)Op.ldc_i4_m1));
\r
1113 } else if ((i >= 0) && (i <= 8)) {
\r
1114 Op op = (Op)(Op.ldc_i4_0 + i);
\r
1115 AddToBuffer(new Instr((int)op));
\r
1116 } else if ((i >= minByteVal) && (i <= maxByteVal)) {
\r
1117 AddToBuffer(new IntInstr((int)IntOp.ldc_i4_s,i,true));
\r
1119 AddToBuffer(new IntInstr((int)IntOp.ldc_i4,i,false));
\r
1124 /// Add the instruction to load a long on TOS
\r
1126 /// <param name="l">the long value</param>
\r
1127 public void PushLong(long l) {
\r
1128 AddToBuffer(new LongInstr(0x21,l));
\r
1132 /// Add an instruction to push the boolean value true on TOS
\r
1134 public void PushTrue() {
\r
1135 AddToBuffer(new Instr((int)Op.ldc_i4_1));
\r
1139 /// Add an instruction to push the boolean value false on TOS
\r
1141 public void PushFalse() {
\r
1142 AddToBuffer(new Instr((int)Op.ldc_i4_0));
\r
1146 /// Add the instruction to load an argument on TOS. This method
\r
1147 /// selects the correct instruction based on the value of argNo
\r
1149 /// <param name="argNo">the number of the argument</param>
\r
1150 public void LoadArg(int argNo) {
\r
1152 int op = (int)Op.ldarg_0 + argNo;
\r
1153 AddToBuffer(new Instr(op));
\r
1154 } else if (argNo <= maxUByteVal) {
\r
1155 AddToBuffer(new UIntInstr((int)IntOp.ldarg,argNo,true));
\r
1157 AddToBuffer(new UIntInstr(0x09,argNo,false));
\r
1162 /// Add the instruction to load the address of an argument on TOS.
\r
1163 /// This method selects the correct instruction based on the value
\r
1166 /// <param name="argNo">the number of the argument</param>
\r
1167 public void LoadArgAdr(int argNo) {
\r
1168 if (argNo <= maxUByteVal) {
\r
1169 AddToBuffer(new UIntInstr((int)IntOp.ldarga,argNo,true));
\r
1171 AddToBuffer(new UIntInstr(0x0A,argNo,false));
\r
1176 /// Add the instruction to load a local on TOS. This method selects
\r
1177 /// the correct instruction based on the value of locNo.
\r
1179 /// <param name="locNo">the number of the local to load</param>
\r
1180 public void LoadLocal(int locNo) {
\r
1182 int op = (int)Op.ldloc_0 + locNo;
\r
1183 AddToBuffer(new Instr(op));
\r
1184 } else if (locNo <= maxUByteVal) {
\r
1185 AddToBuffer(new UIntInstr((int)IntOp.ldloc,locNo,true));
\r
1187 AddToBuffer(new UIntInstr(0x0C,locNo,false));
\r
1192 /// Add the instruction to load the address of a local on TOS.
\r
1193 /// This method selects the correct instruction based on the
\r
1194 /// value of locNo.
\r
1196 /// <param name="locNo">the number of the local</param>
\r
1197 public void LoadLocalAdr(int locNo) {
\r
1198 if (locNo <= maxUByteVal) {
\r
1199 AddToBuffer(new UIntInstr((int)IntOp.ldloca,locNo,true));
\r
1201 AddToBuffer(new UIntInstr(0x0D,locNo,false));
\r
1206 /// Add the instruction to store to an argument. This method
\r
1207 /// selects the correct instruction based on the value of argNo.
\r
1209 /// <param name="argNo">the argument to be stored to</param>
\r
1210 public void StoreArg(int argNo) {
\r
1211 if (argNo <= maxUByteVal) {
\r
1212 AddToBuffer(new UIntInstr((int)IntOp.starg,argNo,true));
\r
1214 AddToBuffer(new UIntInstr(0x0B,argNo,false));
\r
1219 /// Add the instruction to store to a local. This method selects
\r
1220 /// the correct instruction based on the value of locNo.
\r
1222 /// <param name="locNo">the local to be stored to</param>
\r
1223 public void StoreLocal(int locNo) {
\r
1225 int op = (int)Op.stloc_0 + locNo;
\r
1226 AddToBuffer(new Instr(op));
\r
1227 } else if (locNo <= maxUByteVal) {
\r
1228 AddToBuffer(new UIntInstr((int)IntOp.stloc,locNo,true));
\r
1230 AddToBuffer(new UIntInstr(0x0E,locNo,false));
\r
1235 /// Create a new CIL label. To place the label in the CIL instruction
\r
1236 /// stream use CodeLabel.
\r
1238 /// <returns>a new CIL label</returns>
\r
1239 public CILLabel NewLabel() {
\r
1240 return new CILLabel();
\r
1243 public void AddTryBlock(TryBlock tryBlock) {
\r
1244 if (exceptions == null)
\r
1245 exceptions = new ArrayList();
\r
1246 else if (exceptions.Contains(tryBlock)) return;
\r
1247 exceptions.Add(tryBlock);
\r
1251 /// Create a new label at this position in the code buffer
\r
1253 /// <returns>the label at the current position</returns>
\r
1254 public CILLabel NewCodedLabel() {
\r
1255 CILLabel lab = new CILLabel();
\r
1256 AddToBuffer(new LabelInstr(lab));
\r
1261 /// Mark this position as the start of a new block
\r
1262 /// (try, catch, filter, finally or fault)
\r
1264 public void StartBlock() {
\r
1265 if (blockStack == null) blockStack = new ArrayList();
\r
1266 blockStack.Insert(0,NewCodedLabel());
\r
1270 /// Mark this position as the end of the last started block and
\r
1271 /// make it a try block. This try block is added to the current
\r
1272 /// instructions (ie do not need to call AddTryBlock)
\r
1274 /// <returns>The try block just ended</returns>
\r
1275 public TryBlock EndTryBlock() {
\r
1276 TryBlock tBlock = new TryBlock((CILLabel)blockStack[0],NewCodedLabel());
\r
1277 blockStack.RemoveAt(0);
\r
1278 AddTryBlock(tBlock);
\r
1283 /// Mark this position as the end of the last started block and
\r
1284 /// make it a catch block. This catch block is associated with the
\r
1285 /// specified try block.
\r
1287 /// <param name="exceptType">the exception type to be caught</param>
\r
1288 /// <param name="tryBlock">the try block associated with this catch block</param>
\r
1289 public void EndCatchBlock(Class exceptType, TryBlock tryBlock) {
\r
1290 Catch catchBlock = new Catch(exceptType,(CILLabel)blockStack[0],
\r
1292 tryBlock.AddHandler(catchBlock);
\r
1296 /// Mark this position as the end of the last started block and
\r
1297 /// make it a filter block. This filter block is associated with the
\r
1298 /// specified try block.
\r
1300 /// <param name="filterLab">the label where the filter code is</param>
\r
1301 /// <param name="tryBlock">the try block associated with this filter block</param>
\r
1302 public void EndFilterBlock(CILLabel filterLab, TryBlock tryBlock) {
\r
1303 Filter filBlock = new Filter(filterLab,(CILLabel)blockStack[0],NewCodedLabel());
\r
1304 tryBlock.AddHandler(filBlock);
\r
1308 /// Mark this position as the end of the last started block and
\r
1309 /// make it a finally block. This finally block is associated with the
\r
1310 /// specified try block.
\r
1312 /// <param name="tryBlock">the try block associated with this finally block</param>
\r
1313 public void EndFinallyBlock(TryBlock tryBlock) {
\r
1314 Finally finBlock= new Finally((CILLabel)blockStack[0],NewCodedLabel());
\r
1315 tryBlock.AddHandler(finBlock);
\r
1319 /// Mark this position as the end of the last started block and
\r
1320 /// make it a fault block. This fault block is associated with the
\r
1321 /// specified try block.
\r
1323 /// <param name="tryBlock">the try block associated with this fault block</param>
\r
1324 public void EndFaultBlock(TryBlock tryBlock) {
\r
1325 Fault fBlock= new Fault((CILLabel)blockStack[0],NewCodedLabel());
\r
1326 tryBlock.AddHandler(fBlock);
\r
1329 internal uint GetCodeSize() {
\r
1330 return codeSize + paddingNeeded + exceptSize;
\r
1333 internal void CheckCode(uint locSigIx, bool initLocals, int maxStack) {
\r
1334 if (tide == 0) return;
\r
1335 bool changed = true;
\r
1338 for (int i=0; i < tide; i++) {
\r
1339 changed = buffer[i].Check(metaData) || changed;
\r
1342 for (int i=1; i < tide; i++) {
\r
1343 buffer[i].offset = buffer[i-1].offset + buffer[i-1].size;
\r
1345 offset = buffer[tide-1].offset + buffer[tide-1].size;
\r
1348 codeSize = offset;
\r
1349 // Console.WriteLine("codeSize before header added = " + codeSize);
\r
1350 if ((offset < smallSize) && (maxStack <= 8) && (locSigIx == 0) && (exceptions == null)) {
\r
1351 // can use tiny header
\r
1352 //Console.WriteLine("Tiny Header");
\r
1353 tinyFormat = true;
\r
1354 headerFlags = (ushort)(TinyFormat | ((ushort)codeSize << 2));
\r
1356 if ((codeSize % 4) != 0) { paddingNeeded = 4 - (codeSize % 4); }
\r
1358 //Console.WriteLine("Fat Header");
\r
1359 tinyFormat = false;
\r
1360 localSigIx = locSigIx;
\r
1361 this.maxStack = (short)maxStack;
\r
1362 headerFlags = FatFormat;
\r
1363 if (exceptions != null) {
\r
1364 // Console.WriteLine("Got exceptions");
\r
1365 headerFlags |= MoreSects;
\r
1366 uint numExceptClauses = 0;
\r
1367 for (int i=0; i < exceptions.Count; i++) {
\r
1368 TryBlock tryBlock = (TryBlock)exceptions[i];
\r
1369 tryBlock.SetSize();
\r
1370 numExceptClauses += (uint)tryBlock.NumHandlers();
\r
1371 if (tryBlock.isFat()) fatExceptionFormat = true;
\r
1374 uint data_size = ExHeaderSize + numExceptClauses *
1375 (fatExceptionFormat ? FatExClauseSize : SmlExClauseSize);
1377 if (data_size > 256)
1378 fatExceptionFormat = true;
1380 // Console.WriteLine("numexceptclauses = " + numExceptClauses);
\r
1381 if (fatExceptionFormat) {
\r
1382 // Console.WriteLine("Fat exception format");
\r
1383 exceptHeader = FatExceptTable;
\r
1384 exceptSize = ExHeaderSize + numExceptClauses * FatExClauseSize;
\r
1386 // Console.WriteLine("Tiny exception format");
\r
1387 exceptHeader = SmlExceptTable;
\r
1388 exceptSize = ExHeaderSize + numExceptClauses * SmlExClauseSize;
\r
1390 // Console.WriteLine("exceptSize = " + exceptSize);
\r
1392 if (initLocals) headerFlags |= InitLocals;
\r
1393 if ((offset % 4) != 0) { paddingNeeded = 4 - (offset % 4); }
\r
1394 codeSize += FatSize;
\r
1396 // Console.WriteLine("codeSize = " + codeSize + " headerFlags = " +
\r
1397 // Hex.Short(headerFlags));
\r
1400 internal void Write(FileImage output) {
\r
1401 // Console.WriteLine("Writing header flags = " + Hex.Short(headerFlags));
\r
1403 // Console.WriteLine("Writing tiny code");
\r
1404 output.Write((byte)headerFlags);
\r
1406 // Console.WriteLine("Writing fat code");
\r
1407 output.Write(headerFlags);
\r
1408 output.Write((ushort)maxStack);
\r
1409 output.Write(offset);
\r
1410 output.Write(localSigIx);
\r
1412 // Console.WriteLine(Hex.Int(tide) + " CIL instructions");
\r
1413 // Console.WriteLine("starting instructions at " + output.Seek(0,SeekOrigin.Current));
\r
1414 for (int i=0; i < tide; i++) {
\r
1415 buffer[i].Write(output);
\r
1417 // Console.WriteLine("ending instructions at " + output.Seek(0,SeekOrigin.Current));
\r
1418 for (int i=0; i < paddingNeeded; i++) { output.Write((byte)0); }
\r
1419 if (exceptions != null) {
\r
1420 // Console.WriteLine("Writing exceptions");
\r
1421 // Console.WriteLine("header = " + Hex.Short(exceptHeader) + " exceptSize = " + Hex.Int(exceptSize));
\r
1422 output.Write(exceptHeader);
\r
1423 output.Write3Bytes((uint)exceptSize);
\r
1424 for (int i=0; i < exceptions.Count; i++) {
\r
1425 TryBlock tryBlock = (TryBlock)exceptions[i];
\r
1426 tryBlock.Write(output,fatExceptionFormat);
\r
1432 /**************************************************************************/
\r
1434 /// A label in the IL
\r
1436 public class CILLabel
\r
1438 CILInstruction branch;
\r
1439 CILInstruction[] multipleBranches;
\r
1441 CILInstruction labInstr;
\r
1444 public CILLabel (uint offset) {
\r
1445 this.offset = offset;
\r
1449 internal CILLabel() {
\r
1452 internal void AddBranch(CILInstruction instr) {
\r
1453 if (branch == null) {
\r
1457 if (multipleBranches == null) {
\r
1458 multipleBranches = new CILInstruction[2];
\r
1459 } else if (tide >= multipleBranches.Length) {
\r
1460 CILInstruction[] tmp = multipleBranches;
\r
1461 multipleBranches = new CILInstruction[tmp.Length*2];
\r
1462 for (int i=0; i < tide; i++) {
\r
1463 multipleBranches[i] = tmp[i];
\r
1466 multipleBranches[tide++] = instr;
\r
1469 internal void AddLabelInstr(LabelInstr lInstr) {
\r
1470 labInstr = lInstr;
\r
1473 internal uint GetLabelOffset() {
\r
1474 if (labInstr == null) return 0;
\r
1475 return labInstr.offset + offset;
\r
1479 /**************************************************************************/
\r
1480 public abstract class CodeBlock {
\r
1482 private static readonly int maxCodeSize = 256;
\r
1483 protected CILLabel start, end;
\r
1484 protected bool small = true;
\r
1486 public CodeBlock(CILLabel start, CILLabel end) {
\r
1487 this.start = start;
\r
1491 internal virtual bool isFat() {
\r
1492 // Console.WriteLine("block start = " + start.GetLabelOffset() +
\r
1493 // " block end = " + end.GetLabelOffset());
\r
1494 return (end.GetLabelOffset() - start.GetLabelOffset()) > maxCodeSize;
\r
1497 internal virtual void Write(FileImage output, bool fatFormat) {
\r
1498 if (fatFormat) output.Write(start.GetLabelOffset());
\r
1499 else output.Write((short)start.GetLabelOffset());
\r
1500 uint len = end.GetLabelOffset() - start.GetLabelOffset();
\r
1501 if (fatFormat) output.Write(len);
\r
1502 else output.Write((byte)len);
\r
1508 /// The descriptor for a guarded block (.try)
\r
1510 public class TryBlock : CodeBlock {
\r
1511 protected bool fatFormat = false;
\r
1512 protected int flags = 0;
\r
1513 ArrayList handlers = new ArrayList();
\r
1516 /// Create a new try block
\r
1518 /// <param name="start">start label for the try block</param>
\r
1519 /// <param name="end">end label for the try block</param>
\r
1520 public TryBlock(CILLabel start, CILLabel end) : base(start,end) { }
\r
1523 /// Add a handler to this try block
\r
1525 /// <param name="handler">a handler to be added to the try block</param>
\r
1526 public void AddHandler(HandlerBlock handler) {
\r
1527 flags = handler.GetFlag();
\r
1528 handlers.Add(handler);
\r
1531 internal void SetSize() {
\r
1532 fatFormat = base.isFat();
\r
1533 if (fatFormat) return;
\r
1534 for (int i=0; i < handlers.Count; i++) {
\r
1535 HandlerBlock handler = (HandlerBlock)handlers[i];
\r
1536 if (handler.isFat()) {
\r
1543 internal int NumHandlers() {
\r
1544 return handlers.Count;
\r
1547 internal override bool isFat() {
\r
1551 internal override void Write(FileImage output, bool fatFormat) {
\r
1552 // Console.WriteLine("writing exception details");
\r
1553 for (int i=0; i < handlers.Count; i++) {
\r
1554 // Console.WriteLine("Except block " + i);
\r
1555 HandlerBlock handler = (HandlerBlock)handlers[i];
\r
1556 if (fatFormat) output.Write(flags);
\r
1557 else output.Write((short)flags);
\r
1558 // Console.WriteLine("flags = " + Hex.Short(flags));
\r
1559 base.Write(output,fatFormat);
\r
1560 handler.Write(output,fatFormat);
\r
1565 public abstract class HandlerBlock : CodeBlock
\r
1567 protected static readonly short ExceptionFlag = 0;
\r
1568 protected static readonly short FilterFlag = 0x01;
\r
1569 protected static readonly short FinallyFlag = 0x02;
\r
1570 protected static readonly short FaultFlag = 0x04;
\r
1572 public HandlerBlock(CILLabel start, CILLabel end) : base(start,end) { }
\r
1574 internal virtual short GetFlag() { return ExceptionFlag; }
\r
1576 internal override void Write(FileImage output, bool fatFormat) {
\r
1577 base.Write(output,fatFormat);
\r
1583 /// The descriptor for a catch clause (.catch)
\r
1585 public class Catch : HandlerBlock
\r
1590 /// Create a new catch clause
\r
1592 /// <param name="except">the exception to be caught</param>
\r
1593 /// <param name="handlerStart">start of the handler code</param>
\r
1594 /// <param name="handlerEnd">end of the handler code</param>
\r
1595 public Catch(Class except, CILLabel handlerStart, CILLabel handlerEnd)
\r
1596 : base(handlerStart,handlerEnd) {
\r
1597 exceptType = except;
\r
1600 internal override void Write(FileImage output, bool fatFormat) {
\r
1601 base.Write(output,fatFormat);
\r
1602 output.Write(exceptType.Token());
\r
1607 /// The descriptor for a filter clause (.filter)
\r
1609 public class Filter : HandlerBlock
\r
1611 CILLabel filterLabel;
\r
1614 /// Create a new filter clause
\r
1616 /// <param name="filterLabel">the label where the filter code starts</param>
\r
1617 /// <param name="handlerStart">the start of the handler code</param>
\r
1618 /// <param name="handlerEnd">the end of the handler code</param>
\r
1619 public Filter(CILLabel filterLabel, CILLabel handlerStart,
\r
1620 CILLabel handlerEnd) : base(handlerStart,handlerEnd) {
\r
1621 this.filterLabel = filterLabel;
\r
1624 internal override short GetFlag() {
\r
1625 return FilterFlag;
\r
1628 internal override void Write(FileImage output, bool fatFormat) {
\r
1629 base.Write(output,fatFormat);
\r
1630 output.Write(filterLabel.GetLabelOffset());
\r
1636 /// Descriptor for a finally block (.finally)
\r
1638 public class Finally : HandlerBlock
\r
1641 /// Create a new finally clause
\r
1643 /// <param name="finallyStart">start of finally code</param>
\r
1644 /// <param name="finallyEnd">end of finally code</param>
\r
1645 public Finally(CILLabel finallyStart, CILLabel finallyEnd)
\r
1646 : base(finallyStart,finallyEnd) { }
\r
1648 internal override short GetFlag() {
\r
1649 return FinallyFlag;
\r
1652 internal override void Write(FileImage output, bool fatFormat) {
\r
1653 base.Write(output,fatFormat);
\r
1654 output.Write((int)0);
\r
1660 /// Descriptor for a fault block (.fault)
\r
1662 public class Fault : HandlerBlock
\r
1665 /// Create a new fault clause
\r
1667 /// <param name="faultStart">start of the fault code</param>
\r
1668 /// <param name="faultEnd">end of the fault code</param>
\r
1669 public Fault(CILLabel faultStart, CILLabel faultEnd)
\r
1670 : base(faultStart,faultEnd) { }
\r
1672 internal override short GetFlag() {
\r
1673 return FaultFlag;
\r
1676 internal override void Write(FileImage output, bool fatFormat) {
\r
1677 base.Write(output,fatFormat);
\r
1678 output.Write((int)0);
\r
1683 /**************************************************************************/
\r
1685 /// The base descriptor for a class
\r
1687 public abstract class Class : Type
\r
1689 protected int row = 0;
\r
1690 protected string name, nameSpace;
\r
1691 protected uint nameIx, nameSpaceIx;
\r
1692 protected MetaData _metaData;
\r
1693 internal Class(string nameSpaceName, string className, MetaData md)
\r
1695 nameSpace = nameSpaceName;
\r
1697 nameIx = md.AddToStringsHeap(name);
\r
1698 nameSpaceIx = md.AddToStringsHeap(nameSpace);
\r
1702 internal Class(uint nsIx, uint nIx) : base(0x12) {
\r
1703 nameSpaceIx = nsIx;
\r
1707 internal virtual uint TypeDefOrRefToken() { return 0; }
\r
1709 internal virtual void MakeValueClass() {
\r
1713 internal virtual string TypeName() {
\r
1714 return (nameSpace + "." + name);
\r
1717 internal override MetaDataElement GetTypeSpec(MetaData md) {
\r
1721 /**************************************************************************/
\r
1722 // This Class produces entries in the TypeDef table of the MetaData
\r
1723 // in the PE meta data.
\r
1725 // NOTE: Entry 0 in TypeDef table is always the pseudo class <module>
\r
1726 // which is the parent for functions and variables declared a module level
\r
1729 /// The descriptor for a class defined in the IL (.class) in the current assembly/module
\r
1732 public class ClassDef : Class
\r
1734 private static readonly uint HasSecurity = 0x00040000;
\r
1735 private static readonly byte ElementType_Class = 0x12;
\r
1738 ArrayList fields = new ArrayList();
\r
1739 ArrayList methods = new ArrayList();
\r
1741 ArrayList properties;
\r
1742 bool typeIndexChecked = true;
\r
1743 uint fieldIx = 0, methodIx = 0;
\r
1744 byte[] securityActions;
\r
1746 ClassLayout layout;
\r
1747 ClassDef parentClass;
\r
1748 MetaData metaData;
\r
1750 internal ClassDef(TypeAttr attrSet, string nsName, string name,
\r
1751 MetaData md) : base(nsName, name, md) {
\r
1753 superType = metaData.mscorlib.GetSpecialSystemClass(PrimitiveType.Object);
\r
1754 flags = (uint)attrSet;
\r
1755 tabIx = MDTable.TypeDef;
\r
1758 internal void SetSuper(Class sClass) {
\r
1759 superType = sClass;
\r
1760 if (sClass is ClassRef)
\r
1761 typeIndex = superType.GetTypeIndex();
\r
1763 typeIndexChecked = false;
\r
1766 internal override void MakeValueClass() {
\r
1767 superType = metaData.mscorlib.ValueType();
\r
1768 typeIndex = superType.GetTypeIndex();
\r
1771 public void SpecialNoSuper() {
\r
1776 /// Add an attribute to this class
\r
1778 /// <param name="ta">the attribute to be added</param>
\r
1779 public void AddAttribute(TypeAttr ta) {
\r
1780 flags |= (uint)ta;
\r
1784 /// Add an interface that is implemented by this class
\r
1786 /// <param name="iFace">the interface that is implemented</param>
\r
1787 public void AddImplementedInterface(Class iFace) {
\r
1788 metaData.AddToTable(MDTable.InterfaceImpl,new InterfaceImpl(this,iFace));
\r
1792 /// Add a named generic type parameter
\r
1794 public GenericParameter AddGenericParameter (short index, string name) {
\r
1795 GenericParameter gp = new GenericParameter (this, metaData, index, name);
1796 metaData.AddToTable (MDTable.GenericParam, gp);
\r
1801 /// Add a field to this class
\r
1803 /// <param name="name">field name</param>
\r
1804 /// <param name="fType">field type</param>
\r
1805 /// <returns>a descriptor for this new field</returns>
\r
1806 public FieldDef AddField(string name, Type fType) {
\r
1807 FieldDef field = new FieldDef(name,fType);
\r
1808 fields.Add(field);
\r
1813 /// Add a field to this class
\r
1815 /// <param name="fAtts">attributes for this field</param>
\r
1816 /// <param name="name">field name</param>
\r
1817 /// <param name="fType">field type</param>
\r
1818 /// <returns>a descriptor for this new field</returns>
\r
1819 public FieldDef AddField(FieldAttr fAtts, string name, Type fType) {
\r
1820 FieldDef field = new FieldDef(fAtts,name,fType);
\r
1821 fields.Add(field);
\r
1826 /// Add a method to this class
\r
1828 /// <param name="name">method name</param>
\r
1829 /// <param name="retType">return type</param>
\r
1830 /// <param name="pars">parameters</param>
\r
1831 /// <returns>a descriptor for this new method</returns>
\r
1832 public MethodDef AddMethod(string name, Type retType, Param[] pars) {
\r
1833 // Console.WriteLine("Adding method " + name + " to class " + this.name);
\r
1834 MethodDef meth = new MethodDef(metaData,name,retType, pars);
\r
1835 methods.Add(meth);
\r
1840 /// Add a method to this class
\r
1842 /// <param name="mAtts">attributes for this method</param>
\r
1843 /// <param name="iAtts">implementation attributes for this method</param>
\r
1844 /// <param name="name">method name</param>
\r
1845 /// <param name="retType">return type</param>
\r
1846 /// <param name="pars">parameters</param>
\r
1847 /// <returns>a descriptor for this new method</returns>
\r
1848 public MethodDef AddMethod(MethAttr mAtts, ImplAttr iAtts, string name,
\r
1849 Type retType, Param[] pars) {
\r
1850 // Console.WriteLine("Adding method " + name + " to class " + this.name);
\r
1851 MethodDef meth = new MethodDef(metaData,mAtts,iAtts,name,retType,pars);
\r
1852 methods.Add(meth);
\r
1857 /// Add an event to this class
\r
1859 /// <param name="name">event name</param>
\r
1860 /// <param name="eType">event type</param>
\r
1861 /// <returns>a descriptor for this new event</returns>
\r
1862 public Event AddEvent(string name, Type eType) {
\r
1863 Event e = new Event(name,eType,this);
\r
1864 if (events == null) events = new ArrayList();
\r
1870 /// Add a property to this class
\r
1872 /// <param name="name">property name</param>
\r
1873 /// <param name="propType">property type</param>
\r
1874 /// <returns>a descriptor for this new property</returns>
\r
1875 public Property AddProperty(string name, Type retType, Type[] pars) {
\r
1876 Property p = new Property(name, retType, pars, this);
\r
1877 if (properties == null) properties = new ArrayList();
\r
1878 properties.Add(p);
\r
1884 /// Add a nested class to this class
\r
1886 /// <param name="attrSet">attributes for this nested class</param>
\r
1887 /// <param name="nsName">nested name space name</param>
\r
1888 /// <param name="name">nested class name</param>
\r
1889 /// <returns>a descriptor for this new nested class</returns>
\r
1890 public ClassDef AddNestedClass(TypeAttr attrSet, string nsName,
\r
1892 ClassDef nClass = new ClassDef(attrSet,nsName,name,metaData);
\r
1893 metaData.AddToTable(MDTable.TypeDef,nClass);
\r
1894 metaData.AddToTable(MDTable.NestedClass,new MapElem(nClass,Row,MDTable.TypeDef));
\r
1895 nClass.parentClass = this;
\r
1900 /// Add a nested class to this class
\r
1902 /// <param name="attrSet">attributes for this nested class</param>
\r
1903 /// <param name="nsName">nested name space name</param>
\r
1904 /// <param name="name">nested class name</param>
\r
1905 /// <param name="sType">super type of this nested class</param>
\r
1906 /// <returns>a descriptor for this new nested class</returns>
\r
1907 public ClassDef AddNestedClass(TypeAttr attrSet, string nsName,
\r
1908 string name, Class sType) {
\r
1909 ClassDef nClass = new ClassDef(attrSet,nsName,name,metaData);
\r
1910 nClass.SetSuper(sType);
\r
1911 metaData.AddToTable(MDTable.TypeDef,nClass);
\r
1912 metaData.AddToTable(MDTable.NestedClass,
\r
1913 new MapElem(nClass,Row,MDTable.TypeDef));
\r
1914 nClass.parentClass = this;
\r
1919 /// Add layout information for this class. This class must have the
\r
1920 /// sequential or explicit attribute.
\r
1922 /// <param name="packSize">packing size (.pack)</param>
\r
1923 /// <param name="classSize">class size (.size)</param>
\r
1924 public void AddLayoutInfo (int packSize, int classSize) {
\r
1925 layout = new ClassLayout(packSize,classSize,this);
\r
1929 /// Use a method as the implementation for another method (.override)
\r
1931 /// <param name="decl">the method to be overridden</param>
\r
1932 /// <param name="body">the implementation to be used</param>
\r
1933 public void AddMethodOverride(Method decl, Method body) {
\r
1934 metaData.AddToTable(MDTable.MethodImpl,new MethodImpl(this,decl,body));
\r
1938 /// Add security to this class NOT YET IMPLEMENTED
\r
1940 /// <param name="permissionSet"></param>
\r
1941 public void AddSecurity(byte[] permissionSet) {
\r
1942 throw(new NotYetImplementedException("Class security "));
\r
1943 //flags |= HasSecurity;
\r
1944 // securityActions = permissionSet;
\r
1947 //public void AddLineInfo(int row, int col) { }
\r
1949 internal void CheckTypeIndex() {
\r
1950 if (typeIndexChecked) return;
\r
1951 if (!(superType is ClassRef))
\r
1952 ((ClassDef)superType).CheckTypeIndex();
\r
1953 typeIndex = superType.GetTypeIndex();
\r
1954 typeIndexChecked = true;
\r
1957 internal sealed override void BuildTables(MetaData md) {
\r
1959 if ((flags & (uint)TypeAttr.Interface) != 0) { superType = null; }
\r
1960 // Console.WriteLine("Building tables for " + name);
\r
1961 if (layout != null) md.AddToTable(MDTable.ClassLayout,layout);
\r
1962 // Console.WriteLine("adding methods " + methods.Count);
\r
1963 methodIx = md.TableIndex(MDTable.Method);
\r
1964 for (int i=0; i < methods.Count; i++) {
\r
1965 md.AddToTable(MDTable.Method,(MetaDataElement)methods[i]);
\r
1966 ((MethodDef)methods[i]).BuildTables(md);
\r
1968 // Console.WriteLine("adding fields");
\r
1969 fieldIx = md.TableIndex(MDTable.Field);
\r
1970 for (int i=0; i < fields.Count; i++) {
\r
1971 md.AddToTable(MDTable.Field,(MetaDataElement)fields[i]);
\r
1972 ((FieldDef)fields[i]).BuildTables(md);
\r
1974 // Console.WriteLine("adding events and properties");
\r
1975 if (events != null) {
\r
1976 for (int i=0; i < events.Count; i++) {
\r
1977 md.AddToTable(MDTable.Event,(Event)events[i]);
\r
1978 ((Event)events[i]).BuildTables(md);
\r
1980 md.AddToTable(MDTable.EventMap,
\r
1981 new MapElem(this,((Event)events[0]).Row,MDTable.Event));
\r
1983 if (properties != null) {
\r
1984 for (int i=0; i < properties.Count; i++) {
\r
1985 md.AddToTable(MDTable.Property,(Property)properties[i]);
\r
1986 ((Property)properties[i]).BuildTables(md);
\r
1988 md.AddToTable(MDTable.PropertyMap,new MapElem(this,
\r
1989 ((Property)properties[0]).Row,MDTable.Property));
\r
1991 DoCustomAttributes (md);
\r
1992 // Console.WriteLine("End of building tables");
\r
1996 internal sealed override uint Size(MetaData md) {
\r
1997 return 4 + 2 * md.StringsIndexSize() +
\r
1998 md.CodedIndexSize(CIx.TypeDefOrRef) +
\r
1999 md.TableIndexSize(MDTable.Field) +
\r
2000 md.TableIndexSize(MDTable.Method);
\r
2003 internal sealed override void Write(FileImage output) {
\r
2004 output.Write(flags);
\r
2005 output.StringsIndex(nameIx);
\r
2006 output.StringsIndex(nameSpaceIx);
\r
2007 //if (superType != null)
\r
2008 // Console.WriteLine("getting coded index for superType of " + name + " = " + superType.GetCodedIx(CIx.TypeDefOrRef));
\r
2009 output.WriteCodedIndex(CIx.TypeDefOrRef,superType);
\r
2010 output.WriteIndex(MDTable.Field,fieldIx);
\r
2011 output.WriteIndex(MDTable.Method,methodIx);
\r
2014 internal sealed override uint TypeDefOrRefToken() {
\r
2020 internal sealed override void TypeSig(MemoryStream sig) {
\r
2021 if (!typeIndexChecked) CheckTypeIndex();
\r
2022 sig.WriteByte(GetTypeIndex());
\r
2023 MetaData.CompressNum(TypeDefOrRefToken(),sig);
\r
2026 internal sealed override uint GetCodedIx(CIx code) {
\r
2028 case (CIx.TypeDefOrRef) : return 0;
\r
2029 case (CIx.HasCustomAttr) : return 3;
\r
2030 case (CIx.HasDeclSecurity) : return 0;
\r
2031 case (CIx.TypeOrMethodDef) : return 0;
\r
2037 /**************************************************************************/
\r
2039 /// Layout information for a class (.class [sequential | explicit])
\r
2041 internal class ClassLayout : MetaDataElement
\r
2044 ushort packSize = 0;
\r
2045 uint classSize = 0;
\r
2047 internal ClassLayout(int pack, int cSize, ClassDef par) {
\r
2048 packSize = (ushort)pack;
\r
2049 classSize = (uint)cSize;
\r
2051 tabIx = MDTable.ClassLayout;
\r
2054 internal sealed override uint Size(MetaData md) {
\r
2055 return 6 + md.TableIndexSize(MDTable.TypeDef);
\r
2058 internal sealed override void Write(FileImage output) {
\r
2059 output.Write(packSize);
\r
2060 output.Write(classSize);
\r
2061 output.WriteIndex(MDTable.TypeDef,parent.Row);
\r
2065 /**************************************************************************/
\r
2067 /// Descriptor for a class/interface declared in another module of THIS
\r
2068 /// assembly, or in another assembly.
\r
2070 public class ClassRef : Class
\r
2072 protected ResolutionScope parent;
\r
2073 ExternClass externClass;
\r
2074 protected MetaData metaData;
\r
2076 internal ClassRef(string nsName, string name, MetaData md) : base(nsName, name, md) {
\r
2078 tabIx = MDTable.TypeRef;
\r
2082 /// Add a method to this class
\r
2084 /// <param name="name">method name</param>
\r
2085 /// <param name="retType">return type</param>
\r
2086 /// <param name="pars">parameter types</param>
\r
2087 /// <returns>a descriptor for this method</returns>
\r
2088 public MethodRef AddMethod(string name, Type retType, Type[] pars) {
\r
2089 MethodRef meth = new MethodRef(this,name,retType,pars,false,null);
\r
2090 metaData.AddToTable(MDTable.MemberRef,meth);
\r
2095 /// Add a method to this class
\r
2097 /// <param name="name">method name</param>
\r
2098 /// <param name="retType">return type</param>
\r
2099 /// <param name="pars">parameter types</param>
\r
2100 /// <returns>a descriptor for this method</returns>
\r
2101 public MethodRef AddVarArgMethod(string name, Type retType,
\r
2102 Type[] pars, Type[] optPars) {
\r
2103 MethodRef meth = new MethodRef(this,name,retType,pars,true,optPars);
\r
2104 metaData.AddToTable(MDTable.MemberRef,meth);
\r
2109 /// Add a field to this class
\r
2111 /// <param name="name">field name</param>
\r
2112 /// <param name="fType">field type</param>
\r
2113 /// <returns>a descriptor for this field</returns>
\r
2114 public FieldRef AddField(string name, Type fType) {
\r
2115 FieldRef field = new FieldRef(this,name,fType);
\r
2116 metaData.AddToTable(MDTable.MemberRef,field);
\r
2120 internal void SetParent(ResolutionScope par) {
\r
2124 internal override string TypeName() {
\r
2125 if ((parent != null) && (parent is AssemblyRef))
\r
2126 return (nameSpace + "." + name + ", " + ((AssemblyRef)parent).TypeName());
\r
2128 return (nameSpace + name);
\r
2131 internal sealed override uint Size(MetaData md) {
\r
2132 return md.CodedIndexSize(CIx.ResolutionScope) + 2 *
\r
2133 md.StringsIndexSize();
\r
2136 internal sealed override void Write(FileImage output) {
\r
2137 output.WriteCodedIndex(CIx.ResolutionScope,parent);
\r
2138 output.StringsIndex(nameIx);
\r
2139 output.StringsIndex(nameSpaceIx);
\r
2142 internal override sealed uint TypeDefOrRefToken() {
\r
2144 cIx = (cIx << 2) | 0x1;
\r
2148 internal override void TypeSig(MemoryStream sig) {
\r
2149 sig.WriteByte(GetTypeIndex());
\r
2150 MetaData.CompressNum(TypeDefOrRefToken(),sig);
\r
2153 internal sealed override uint GetCodedIx(CIx code) {
\r
2155 case (CIx.TypeDefOrRef) : return 1;
\r
2156 case (CIx.HasCustomAttr) : return 2;
\r
2157 case (CIx.MemberRefParent) : return 1;
\r
2158 case (CIx.ResolutionScope) : return 3;
\r
2164 /**************************************************************************/
\r
2166 public class ExternClassRef : ClassRef {
\r
2168 ExternClass externClass;
\r
2170 internal ExternClassRef(TypeAttr attrs, string nsName, string name,
\r
2171 FileRef declFile, MetaData md) : base(nsName,name,md) {
\r
2172 externClass = new ExternClass(attrs,nameSpaceIx,nameIx,declFile);
\r
2173 metaData.AddToTable(MDTable.ExportedType,externClass);
\r
2176 internal ExternClassRef(string name, MetaData md) : base(null,name,md) {
\r
2179 public ClassRef AddNestedClass(TypeAttr attrs, string name) {
\r
2180 ExternClassRef nestedClass = new ExternClassRef(name,metaData);
\r
2181 externClass = new ExternClass(attrs,0,nameIx,this.externClass);
\r
2182 metaData.AddToTable(MDTable.ExportedType,externClass);
\r
2183 return nestedClass;
\r
2187 /**************************************************************************/
\r
2189 /// Descriptor for a constant value
\r
2191 public abstract class Constant {
\r
2192 protected uint size = 0;
\r
2193 protected Type type;
\r
2194 protected uint blobIndex;
\r
2195 protected bool addedToBlobHeap = false;
\r
2197 internal Constant() { }
\r
2199 internal virtual uint GetBlobIndex(MetaData md) { return 0; }
\r
2201 internal uint GetSize() { return size; }
\r
2203 internal byte GetTypeIndex() { return type.GetTypeIndex(); }
\r
2205 internal virtual void Write(BinaryWriter bw) { }
\r
2209 /// Descriptor for a constant value
\r
2211 public abstract class DataConstant : Constant {
\r
2212 private uint dataOffset = 0;
\r
2214 internal DataConstant() { }
\r
2216 public uint DataOffset {
\r
2217 get { return dataOffset; }
\r
2218 set { dataOffset = value; }
\r
2224 /// Boolean constant
\r
2226 public class BoolConst : Constant {
\r
2230 /// Create a new boolean constant with the value "val"
\r
2232 /// <param name="val">value of this boolean constant</param>
\r
2233 public BoolConst(bool val) {
\r
2236 type = PrimitiveType.Boolean;
\r
2239 internal sealed override uint GetBlobIndex(MetaData md) {
\r
2240 if (!addedToBlobHeap) {
\r
2241 if (val) blobIndex = md.AddToBlobHeap((sbyte)1);
\r
2242 else blobIndex = md.AddToBlobHeap((sbyte)0);
\r
2243 addedToBlobHeap = true;
\r
2248 internal sealed override void Write(BinaryWriter bw) {
\r
2249 if (val) bw.Write((sbyte)1);
\r
2250 else bw.Write((sbyte)0);
\r
2255 public class ByteArrConst : DataConstant {
\r
2258 public ByteArrConst(byte[] val) {
\r
2260 size = (uint)val.Length;
\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 CharConst : Constant {
\r
2280 public CharConst(char val) {
\r
2283 type = PrimitiveType.Char;
\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 FloatConst : DataConstant {
\r
2303 public FloatConst(float val) {
\r
2306 type = PrimitiveType.Float32;
\r
2309 internal sealed override uint GetBlobIndex(MetaData md) {
\r
2310 if (!addedToBlobHeap) {
\r
2311 blobIndex = md.AddToBlobHeap(val);
\r
2312 addedToBlobHeap = true;
\r
2317 internal sealed override void Write(BinaryWriter bw) {
\r
2323 public class DoubleConst : DataConstant {
\r
2326 public DoubleConst(double val) {
\r
2329 type = PrimitiveType.Float64;
\r
2332 internal sealed override uint GetBlobIndex(MetaData md) {
\r
2333 if (!addedToBlobHeap) {
\r
2334 blobIndex = md.AddToBlobHeap(val);
\r
2335 addedToBlobHeap = true;
\r
2340 internal sealed override void Write(BinaryWriter bw) {
\r
2346 public class IntConst : DataConstant {
\r
2349 public IntConst(sbyte val) {
\r
2352 type = PrimitiveType.Int8;
\r
2355 public IntConst(short val) {
\r
2358 type = PrimitiveType.Int16;
\r
2361 public IntConst(int val) {
\r
2364 type = PrimitiveType.Int32;
\r
2367 public IntConst(long val) {
\r
2370 type = PrimitiveType.Int64;
\r
2373 internal sealed override uint GetBlobIndex(MetaData md) {
\r
2374 if (!addedToBlobHeap) {
\r
2376 case (1) : blobIndex = md.AddToBlobHeap((sbyte)val); break;
\r
2377 case (2) : blobIndex = md.AddToBlobHeap((short)val); break;
\r
2378 case (4) : blobIndex = md.AddToBlobHeap((int)val); break;
\r
2379 default : blobIndex = md.AddToBlobHeap(val); break;
\r
2381 addedToBlobHeap = true;
\r
2386 internal sealed override void Write(BinaryWriter bw) {
\r
2388 case (1) : bw.Write((sbyte)val); break;
\r
2389 case (2) : bw.Write((short)val); break;
\r
2390 case (4) : bw.Write((int)val); break;
\r
2391 default : bw.Write(val); break;
\r
2397 public class UIntConst : Constant {
\r
2400 public UIntConst(sbyte val) {
\r
2403 type = PrimitiveType.UInt8;
\r
2405 public UIntConst(short val) {
\r
2408 type = PrimitiveType.UInt16;
\r
2410 public UIntConst(int val) {
\r
2413 type = PrimitiveType.UInt32;
\r
2415 public UIntConst(long val) {
\r
2418 type = PrimitiveType.UInt64;
\r
2421 internal sealed override uint GetBlobIndex(MetaData md) {
\r
2422 if (!addedToBlobHeap) {
\r
2424 case (1) : blobIndex = md.AddToBlobHeap((sbyte)val); break;
\r
2425 case (2) : blobIndex = md.AddToBlobHeap((short)val); break;
\r
2426 case (4) : blobIndex = md.AddToBlobHeap((int)val); break;
\r
2427 default : blobIndex = md.AddToBlobHeap(val); break;
\r
2429 addedToBlobHeap = true;
\r
2434 internal sealed override void Write(BinaryWriter bw) {
\r
2436 case (1) : bw.Write((sbyte)val); break;
\r
2437 case (2) : bw.Write((short)val); break;
\r
2438 case (4) : bw.Write((int)val); break;
\r
2439 default : bw.Write(val); break;
\r
2445 public class StringConst : DataConstant {
\r
2448 public StringConst(string val) {
\r
2450 size = (uint)val.Length; // need to add null ??
\r
2451 type = PrimitiveType.String;
\r
2454 internal sealed override uint GetBlobIndex(MetaData md) {
\r
2455 if (!addedToBlobHeap) {
2456 byte [] b = Encoding.Unicode.GetBytes (val);
2457 blobIndex = md.AddToBlobHeap(b);
\r
2458 addedToBlobHeap = true;
\r
2463 internal sealed override void Write(BinaryWriter bw) {
\r
2469 public class NullConst : Constant {
\r
2471 public NullConst() {
\r
2473 type = PrimitiveType.Class;
\r
2476 internal sealed override uint GetBlobIndex(MetaData md) {
\r
2477 if (!addedToBlobHeap) {
\r
2478 blobIndex = md.AddToBlobHeap((int)0);
\r
2479 addedToBlobHeap = true;
\r
2484 internal sealed override void Write(BinaryWriter bw) {
\r
2485 bw.Write((int)0);
\r
2490 public class AddressConstant : DataConstant {
\r
2491 DataConstant data;
\r
2493 public AddressConstant(DataConstant dConst) {
\r
2496 type = PrimitiveType.TypedRef;
\r
2499 internal sealed override void Write(BinaryWriter bw) {
\r
2500 ((FileImage)bw).WriteDataRVA(data.DataOffset);
\r
2505 public class RepeatedConstant : DataConstant {
\r
2506 DataConstant data;
\r
2509 public RepeatedConstant(DataConstant dConst, int repeatCount) {
\r
2511 repCount = (uint)repeatCount;
\r
2512 int[] sizes = new int[1];
\r
2513 sizes[0] = repeatCount;
\r
2514 type = new BoundArray(type,1,sizes);
\r
2515 size = data.GetSize() * repCount;
\r
2518 internal sealed override void Write(BinaryWriter bw) {
\r
2519 for (int i=0; i < repCount; i++) {
\r
2526 public class ArrayConstant : DataConstant {
\r
2527 DataConstant[] dataVals;
\r
2529 public ArrayConstant(DataConstant[] dVals) {
\r
2531 for (int i=0; i < dataVals.Length; i++) {
\r
2532 size += dataVals[i].GetSize();
\r
2536 internal sealed override void Write(BinaryWriter bw) {
\r
2537 for (int i=0; i < dataVals.Length; i++) {
\r
2538 dataVals[i].Write(bw);
\r
2544 public class ClassType : Constant {
\r
2548 public ClassType(string className) {
\r
2550 type = PrimitiveType.ClassType;
\r
2553 public ClassType(Class classDesc) {
\r
2555 type = PrimitiveType.ClassType;
\r
2558 internal override void Write(BinaryWriter bw) {
\r
2559 if (name == null) name = desc.TypeName();
\r
2567 /**************************************************************************/
\r
2569 /// Summary description for ConstantElem.
\r
2571 internal class ConstantElem : MetaDataElement
\r
2573 MetaDataElement parent;
\r
2577 internal ConstantElem(MetaDataElement parent, Constant val) {
\r
2578 this.parent = parent;
\r
2580 tabIx = MDTable.Constant;
\r
2583 internal sealed override void BuildTables(MetaData md) {
\r
2585 valIx = cValue.GetBlobIndex(md);
\r
2589 internal void AddToBlob(BinaryWriter bw) {
\r
2593 internal sealed override uint Size(MetaData md) {
\r
2594 return 2 + md.CodedIndexSize(CIx.HasConst) + md.BlobIndexSize();
\r
2597 internal sealed override void Write(FileImage output) {
\r
2598 output.Write(cValue.GetTypeIndex());
\r
2599 output.Write((byte)0);
\r
2600 output.WriteCodedIndex(CIx.HasConst,parent);
\r
2601 output.BlobIndex(valIx);
\r
2605 /**************************************************************************/
\r
2607 /// Descriptor for a Custom Attribute (.custom)
\r
2610 public class CustomAttribute : MetaDataElement
\r
2612 private static readonly ushort prolog = 0x0001;
\r
2613 MetaDataElement parent;
\r
2618 ushort numNamed = 0;
\r
2619 ArrayList names, vals;
\r
2621 internal CustomAttribute(MetaDataElement paren, Method constrType,
\r
2624 type = constrType;
\r
2626 tabIx = MDTable.CustomAttribute;
\r
2627 throw(new NotYetImplementedException("Custom Attributes "));
\r
2630 internal CustomAttribute(MetaDataElement paren, Method constrType,
\r
2633 type = constrType;
\r
2634 tabIx = MDTable.CustomAttribute;
\r
2638 public void AddFieldOrProp(string name, Constant val) {
\r
2639 if (numNamed == 0) {
\r
2640 names = new ArrayList();
\r
2641 vals = new ArrayList();
\r
2647 internal sealed override void BuildTables(MetaData md) {
\r
2648 BinaryWriter bw = new BinaryWriter(new MemoryStream());
\r
2649 bw.Write((ushort)1);
\r
2650 md.AddToTable(MDTable.CustomAttribute, this);
\r
2651 MemoryStream str = (MemoryStream)bw.BaseStream;
\r
2652 valIx = md.AddToBlobHeap(str.ToArray());
\r
2655 internal sealed override uint Size(MetaData md) {
\r
2656 return md.CodedIndexSize(CIx.HasCustomAttr) + md.CodedIndexSize(CIx.CustomAttributeType) + md.BlobIndexSize();
\r
2659 internal sealed override void Write(FileImage output) {
\r
2660 output.WriteCodedIndex(CIx.HasCustomAttr,parent);
\r
2661 output.WriteCodedIndex(CIx.CustomAttributeType,type);
\r
2662 output.BlobIndex(valIx);
\r
2666 /**************************************************************************/
\r
2668 /// Descriptor for a custom modifier of a type (modopt or modreq)
\r
2671 public class CustomModifiedType : Type
\r
2677 /// Create a new custom modifier for a type
\r
2679 /// <param name="type">the type to be modified</param>
\r
2680 /// <param name="cmod">the modifier</param>
\r
2681 /// <param name="cmodType">the type reference to be associated with the type</param>
\r
2682 public CustomModifiedType(Type type, CustomModifier cmod, Class cmodType)
\r
2683 : base((byte)cmod) {
\r
2685 this.cmodType = cmodType;
\r
2688 internal sealed override void TypeSig(MemoryStream str) {
\r
2689 str.WriteByte(typeIndex);
\r
2690 MetaData.CompressNum(cmodType.TypeDefOrRefToken(),str);
\r
2691 type.TypeSig(str);
\r
2695 /**************************************************************************/
\r
2697 /// Descriptor for security permissions for a class or a method NOT YET IMPLEMENTED
\r
2700 public class DeclSecurity : MetaDataElement
\r
2703 MetaDataElement parent;
\r
2704 uint permissionIx;
\r
2706 internal DeclSecurity(MetaDataElement paren, ushort act) {
\r
2709 tabIx = MDTable.DeclSecurity;
\r
2710 throw(new NotYetImplementedException("Security "));
\r
2713 internal sealed override uint Size(MetaData md) {
\r
2714 return 2 + md.CodedIndexSize(CIx.HasDeclSecurity) + md.BlobIndexSize();
\r
2717 internal sealed override void BuildTables(MetaData md) {
\r
2719 // add permission to blob heap
\r
2723 internal sealed override void Write(FileImage output) {
\r
2724 output.Write(action);
\r
2725 output.WriteCodedIndex(CIx.HasDeclSecurity,parent);
\r
2726 output.BlobIndex(permissionIx);
\r
2730 /**************************************************************************/
\r
2732 /// Descriptor for an event
\r
2734 public class Event : Feature
\r
2738 internal Event(string name, Type eType, ClassDef parent)
\r
2739 : base(name, parent) {
\r
2740 eventType = eType;
\r
2741 tabIx = MDTable.Event;
\r
2745 /// Add the addon method to this event
\r
2747 /// <param name="addon">the addon method</param>
\r
2748 public void AddAddon(MethodDef addon) {
\r
2749 AddMethod(addon,MethodType.AddOn);
\r
2753 /// Add the removeon method to this event
\r
2755 /// <param name="removeOn">the removeon method</param>
\r
2756 public void AddRemoveOn(MethodDef removeOn) {
\r
2757 AddMethod(removeOn,MethodType.RemoveOn);
\r
2761 /// Add the fire method to this event
\r
2763 /// <param name="fire">the fire method</param>
\r
2764 public void AddFire(MethodDef fire) {
\r
2765 AddMethod(fire,MethodType.Fire);
\r
2769 /// Add another method to this event
\r
2771 /// <param name="other">the method to be added</param>
\r
2772 public void AddOther(MethodDef other) {
\r
2773 AddMethod(other,MethodType.Other);
\r
2776 internal sealed override void BuildTables(MetaData md) {
\r
2778 nameIx = md.AddToStringsHeap(name);
\r
2779 for (int i=0; i < tide; i++) {
\r
2780 md.AddToTable(MDTable.MethodSemantics,methods[i]);
\r
2785 internal sealed override uint Size(MetaData md) {
\r
2786 return 2 + md.StringsIndexSize() + md.CodedIndexSize(CIx.TypeDefOrRef);
\r
2789 internal sealed override void Write(FileImage output) {
\r
2790 output.Write(flags);
\r
2791 output.StringsIndex(nameIx);
\r
2792 output.WriteCodedIndex(CIx.TypeDefOrRef,eventType);
\r
2795 internal sealed override uint GetCodedIx(CIx code) {
\r
2797 case (CIx.HasCustomAttr) : return 10;
\r
2798 case (CIx.HasSemantics) : return 0;
\r
2804 /**************************************************************************/
\r
2806 /// Descriptor for a class defined in another module of THIS assembly
\r
2807 /// and exported (.class extern)
\r
2810 internal class ExternClass : Class
\r
2812 MetaDataElement parent;
\r
2815 internal ExternClass(TypeAttr attr, uint nsIx, uint nIx,
\r
2816 MetaDataElement paren) : base(nsIx,nIx) {
\r
2817 flags = (uint)attr;
\r
2819 tabIx = MDTable.ExportedType;
\r
2822 internal sealed override uint Size(MetaData md) {
\r
2823 return 8 + 2* md.StringsIndexSize() + md.CodedIndexSize(CIx.Implementation);
\r
2826 internal sealed override void Write(FileImage output) {
\r
2827 output.Write(flags);
\r
2829 output.StringsIndex(nameIx);
\r
2830 output.StringsIndex(nameSpaceIx);
\r
2831 output.WriteCodedIndex(CIx.Implementation,parent);
\r
2834 internal sealed override uint GetCodedIx(CIx code) {
\r
2836 case (CIx.HasCustomAttr) : return 17;
\r
2837 case (CIx.Implementation) : return 2;
\r
2843 /**************************************************************************/
\r
2845 /// Base class for Event and Property descriptors
\r
2848 public class Feature : MetaDataElement
\r
2850 internal enum MethodType : ushort { Setter = 0x01, Getter, Other = 0x04, AddOn = 0x08,
\r
2851 RemoveOn = 0x10, Fire = 0x20 }
\r
2853 private static readonly int INITSIZE = 5;
\r
2854 private static readonly ushort specialName = 0x200;
\r
2855 private static readonly ushort rtSpecialName = 0x400;
\r
2857 protected ClassDef parent;
\r
2858 protected ushort flags = 0;
\r
2859 protected string name;
\r
2860 protected int tide = 0;
\r
2861 protected uint nameIx;
\r
2862 protected MethodSemantics[] methods = new MethodSemantics[INITSIZE];
\r
2864 internal Feature(string name, ClassDef par) {
\r
2869 internal void AddMethod(MethodDef meth, MethodType mType) {
\r
2870 if (tide >= methods.Length) {
\r
2871 int len = methods.Length;
\r
2872 MethodSemantics[] mTmp = methods;
\r
2873 methods = new MethodSemantics[len * 2];
\r
2874 for (int i=0; i < len; i++) {
\r
2875 methods[i] = mTmp[i];
\r
2878 methods[tide++] = new MethodSemantics(mType,meth,this);
\r
2882 /// Set the specialName attribute for this Event or Property
\r
2884 public void SetSpecialName() {
\r
2885 flags |= specialName;
\r
2889 /// Set the RTSpecialName attribute for this Event or Property
\r
2891 public void SetRTSpecialName() {
\r
2892 flags |= rtSpecialName;
\r
2896 /*****************************************************************************/
\r
2898 /// Descriptor for a field of a class
\r
2901 public abstract class Field : Member
\r
2903 protected static readonly byte FieldSig = 0x6;
\r
2905 protected Type type;
\r
2907 internal Field(string pfName, Type pfType) : base(pfName)
\r
2913 /**************************************************************************/
\r
2915 /// Descriptor for a field defined in a class of THIS assembly/module
\r
2917 public class FieldDef : Field
\r
2919 //private static readonly uint PInvokeImpl = 0x2000;
\r
2920 private static readonly ushort HasFieldMarshal = 0x1000;
\r
2921 private static readonly ushort HasFieldRVA = 0x100;
\r
2922 private static readonly ushort HasDefault = 0x8000;
2925 ConstantElem constVal;
\r
2926 FieldLayout layout;
\r
2927 FieldMarshal marshalInfo;
\r
2930 internal FieldDef(string name, Type fType) : base(name,fType) {
\r
2931 tabIx = MDTable.Field;
\r
2934 internal FieldDef(FieldAttr attrSet, string name, Type fType) : base(name, fType) {
\r
2935 flags = (ushort)attrSet;
\r
2936 tabIx = MDTable.Field;
\r
2940 /// Add an attribute(s) to this field
\r
2942 /// <param name="fa">the attribute(s) to be added</param>
\r
2943 public void AddFieldAttr(FieldAttr fa) {
\r
2944 flags |= (ushort)fa;
\r
2948 /// Add a value for this field
\r
2950 /// <param name="val">the value for the field</param>
\r
2951 public void AddValue(Constant val) {
\r
2952 constVal = new ConstantElem(this,val);
\r
2953 flags |= HasDefault;
2957 /// Add an initial value for this field (at dataLabel) (.data)
\r
2959 /// <param name="val">the value for the field</param>
\r
2960 /// <param name="repeatVal">the number of repetitions of this value</param>
\r
2961 public void AddDataValue(DataConstant val) {
\r
2962 flags |= HasFieldRVA;
\r
2963 rva = new FieldRVA(this,val);
\r
2967 /// Set the offset of the field. Used for sequential or explicit classes.
\r
2968 /// (.field [offs])
\r
2970 /// <param name="offs">field offset</param>
\r
2971 public void SetOffset(uint offs) {
\r
2972 layout = new FieldLayout(this,offs);
\r
2976 /// Set the marshalling info for a field
\r
2978 /// <param name="mInf"></param>
\r
2979 public void SetMarshalInfo(NativeType marshallType) {
\r
2980 flags |= HasFieldMarshal;
\r
2981 marshalInfo = new FieldMarshal(this,marshallType);
\r
2984 internal sealed override void BuildTables(MetaData md) {
\r
2986 nameIx = md.AddToStringsHeap(name);
\r
2987 MemoryStream sig = new MemoryStream();
\r
2988 sig.WriteByte(FieldSig);
\r
2989 type.TypeSig(sig);
\r
2990 sigIx = md.AddToBlobHeap(sig.ToArray());
\r
2991 if (rva != null) {
\r
2992 md.AddToTable(MDTable.FieldRVA,rva);
\r
2993 rva.BuildTables(md);
\r
2994 } else if (constVal != null) {
\r
2995 md.AddToTable(MDTable.Constant,constVal);
\r
2996 constVal.BuildTables(md);
\r
2998 if (layout != null) md.AddToTable(MDTable.FieldLayout,layout);
\r
2999 if (marshalInfo != null) {
\r
3000 md.AddToTable(MDTable.FieldMarshal,marshalInfo);
\r
3001 marshalInfo.BuildTables(md);
\r
3006 internal sealed override uint Size(MetaData md) {
\r
3007 return 2 + md.StringsIndexSize() + md.BlobIndexSize();
\r
3010 internal sealed override void Write(FileImage output) {
\r
3011 output.Write(flags);
\r
3012 output.StringsIndex(nameIx);
\r
3013 output.BlobIndex(sigIx);
\r
3016 internal sealed override uint GetCodedIx(CIx code) {
\r
3018 case (CIx.HasConst) : return 0;
\r
3019 case (CIx.HasCustomAttr) : return 1;
\r
3020 case (CIx.HasFieldMarshal) : return 0;
\r
3021 case (CIx.MemberForwarded) : return 0;
\r
3027 /**************************************************************************/
\r
3029 /// Descriptor for layout information for a field
\r
3032 public class FieldLayout : MetaDataElement
\r
3037 internal FieldLayout(Field field, uint offset) {
\r
3038 this.field = field;
\r
3039 this.offset = offset;
\r
3040 tabIx = MDTable.FieldLayout;
\r
3043 internal sealed override uint Size(MetaData md) {
\r
3044 return 4 + md.TableIndexSize(MDTable.Field);
\r
3047 internal sealed override void Write(FileImage output) {
\r
3048 output.Write(offset);
\r
3049 output.WriteIndex(MDTable.Field,field.Row);
\r
3053 /*****************************************************************************/
\r
3055 /// Marshalling information for a field or param
\r
3057 public class FieldMarshal : MetaDataElement
\r
3059 MetaDataElement field;
\r
3063 internal FieldMarshal(MetaDataElement field, NativeType nType) {
\r
3064 this.field = field;
\r
3066 tabIx = MDTable.FieldMarshal;
\r
3069 internal sealed override void BuildTables(MetaData md) {
\r
3071 ntIx = md.AddToBlobHeap(nt.ToBlob());
\r
3075 internal sealed override uint Size(MetaData md) {
\r
3076 return md.CodedIndexSize(CIx.HasFieldMarshal) + md.BlobIndexSize();
\r
3079 internal sealed override void Write(FileImage output) {
\r
3080 output.WriteCodedIndex(CIx.HasFieldMarshal,field);
\r
3081 output.BlobIndex(ntIx);
\r
3085 /**************************************************************************/
\r
3087 /// Descriptor for a field of a class defined in another assembly/module
\r
3089 public class FieldRef : Field
\r
3091 MetaDataElement parent;
\r
3093 internal FieldRef(MetaDataElement paren, string name, Type fType) : base(name, fType) {
\r
3097 internal sealed override void BuildTables(MetaData md) {
\r
3099 nameIx = md.AddToStringsHeap(name);
\r
3100 MemoryStream sig = new MemoryStream();
\r
3101 sig.WriteByte(FieldSig);
\r
3102 type.TypeSig(sig);
\r
3103 sigIx = md.AddToBlobHeap(sig.ToArray());
\r
3107 internal sealed override uint Size(MetaData md) {
\r
3108 return md.CodedIndexSize(CIx.MemberRefParent) + md.StringsIndexSize() + md.BlobIndexSize();
\r
3111 internal sealed override void Write(FileImage output) {
\r
3112 output.WriteCodedIndex(CIx.MemberRefParent,parent);
\r
3113 output.StringsIndex(nameIx);
\r
3114 output.BlobIndex(sigIx);
\r
3117 internal sealed override uint GetCodedIx(CIx code) { return 6; }
\r
3120 /**************************************************************************/
\r
3122 /// Descriptor for the address of a field's value in the PE file
\r
3124 public class FieldRVA : MetaDataElement
\r
3127 DataConstant data;
\r
3129 internal FieldRVA(Field field, DataConstant data) {
\r
3130 this.field = field;
\r
3132 tabIx = MDTable.FieldRVA;
\r
3135 internal sealed override void BuildTables(MetaData md) {
\r
3141 internal sealed override uint Size(MetaData md) {
\r
3142 return 4 + md.TableIndexSize(MDTable.Field);
\r
3145 internal sealed override void Write(FileImage output) {
\r
3146 output.WriteDataRVA(data.DataOffset);
\r
3147 output.WriteIndex(MDTable.Field,field.Row);
\r
3151 /**************************************************************************/
\r
3153 /// Image for a PEFile
\r
3154 /// File Structure
\r
3155 /// DOS Header (128 bytes)
\r
3156 /// PE Signature ("PE\0\0")
\r
3157 /// PEFileHeader (20 bytes)
\r
3158 /// PEOptionalHeader (224 bytes)
\r
3159 /// SectionHeaders (40 bytes * NumSections)
\r
3161 /// Sections .text (always present - contains metadata)
\r
3162 /// .sdata (contains any initialised data in the file - may not be present)
\r
3163 /// (for ilams /debug this contains the Debug table)
\r
3164 /// .reloc (always present - in pure CIL only has one fixup)
\r
3165 /// others??? c# produces .rsrc section containing a Resource Table
\r
3168 /// IAT (single entry 8 bytes for pure CIL)
\r
3169 /// CLIHeader (72 bytes)
\r
3170 /// CIL instructions for all methods (variable size)
\r
3172 /// Root (20 bytes + UTF-8 Version String + quad align padding)
\r
3173 /// StreamHeaders (8 bytes + null terminated name string + quad align padding)
\r
3175 /// #~ (always present - holds metadata tables)
\r
3176 /// #Strings (always present - holds identifier strings)
\r
3177 /// #US (Userstring heap)
\r
3178 /// #Blob (signature blobs)
\r
3179 /// #GUID (guids for assemblies or Modules)
\r
3180 /// ImportTable (40 bytes)
\r
3181 /// ImportLookupTable(8 bytes) (same as IAT for standard CIL files)
\r
3182 /// Hint/Name Tables with entry "_CorExeMain" for .exe file and "_CorDllMain" for .dll (14 bytes)
\r
3183 /// ASCII string "mscoree.dll" referenced in ImportTable (+ padding = 16 bytes)
\r
3184 /// Entry Point (0xFF25 followed by 4 bytes 0x400000 + RVA of .text)
\r
3186 /// #~ stream structure
\r
3187 /// Header (24 bytes)
\r
3188 /// Rows (4 bytes * numTables)
\r
3191 internal class FileImage : BinaryWriter
\r
3193 internal readonly static uint[] iByteMask = {0x000000FF, 0x0000FF00, 0x00FF0000, 0xFF000000};
\r
3194 internal readonly static ulong[] lByteMask = {0x00000000000000FF, 0x000000000000FF00,
\r
3195 0x0000000000FF0000, 0x00000000FF000000,
\r
3196 0x000000FF00000000, 0x0000FF0000000000,
\r
3197 0x00FF000000000000, 0xFF00000000000000 };
\r
3198 internal readonly static uint nibble0Mask = 0x0000000F;
\r
3199 internal readonly static uint nibble1Mask = 0x000000F0;
\r
3201 private static readonly byte[] DOSHeader = { 0x4d,0x5a,0x90,0x00,0x03,0x00,0x00,0x00,
\r
3202 0x04,0x00,0x00,0x00,0xff,0xff,0x00,0x00,
\r
3203 0xb8,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
\r
3204 0x40,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
\r
3205 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
\r
3206 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
\r
3207 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
\r
3208 0x00,0x00,0x00,0x00,0x80,0x00,0x00,0x00,
\r
3209 0x0e,0x1f,0xba,0x0e,0x00,0xb4,0x09,0xcd,
\r
3210 0x21,0xb8,0x01,0x4c,0xcd,0x21,0x54,0x68,
\r
3211 0x69,0x73,0x20,0x70,0x72,0x6f,0x67,0x72,
\r
3212 0x61,0x6d,0x20,0x63,0x61,0x6e,0x6e,0x6f,
\r
3213 0x74,0x20,0x62,0x65,0x20,0x72,0x75,0x6e,
\r
3214 0x20,0x69,0x6e,0x20,0x44,0x4f,0x53,0x20,
\r
3215 0x6d,0x6f,0x64,0x65,0x2e,0x0d,0x0d,0x0a,
\r
3216 0x24,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
\r
3217 0x50,0x45,0x00,0x00};
\r
3218 private static byte[] PEHeader = { 0x4c, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
\r
3219 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
\r
3220 0xE0, 0x00, 0x0E, 0x01, // PE Header Standard Fields
\r
3221 0x0B, 0x01, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00,
\r
3222 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
\r
3223 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
\r
3226 private static readonly uint minFileAlign = 0x200;
\r
3227 private static readonly uint maxFileAlign = 0x1000;
\r
3228 private static readonly uint fileHeaderSize = 0x178;
\r
3229 private static readonly uint sectionHeaderSize = 40;
\r
3230 private static readonly uint SectionAlignment = 0x2000;
\r
3231 private static readonly uint ImageBase = 0x400000;
\r
3232 private static readonly uint ImportTableSize = 40;
\r
3233 private static readonly uint IATSize = 8;
\r
3234 private static readonly uint CLIHeaderSize = 72;
\r
3235 private uint runtimeFlags = 0x01; // COMIMAGE_FLAGS_ILONLY
\r
3236 // 32BITREQUIRED 0x02, STRONGNAMESIGNED 0x08, TRACKDEBUGDATA 0x10000
\r
3237 private static readonly uint relocFlags = 0x42000040;
\r
3238 private static readonly ushort exeCharacteristics = 0x010E;
\r
3239 private static readonly ushort dllCharacteristics = 0x210E;
\r
3240 // section names are all 8 bytes
\r
3241 private static readonly string textName = ".text\0\0\0";
\r
3242 private static readonly string sdataName = ".sdata\0\0";
\r
3243 private static readonly string relocName = ".reloc\0\0";
\r
3244 private static readonly string rsrcName = ".rsrc\0\0\0";
\r
3245 private static readonly string exeHintNameTable = "\0\0_CorExeMain\0";
\r
3246 private static readonly string dllHintNameTable = "\0\0_CorDllMain\0";
\r
3247 private static readonly string runtimeEngineName = "mscoree.dll\0\0";
\r
3249 private Section text, sdata, rsrc;
\r
3251 BinaryWriter reloc = new BinaryWriter(new MemoryStream());
\r
3252 uint dateStamp = 0;
\r
3253 DateTime origin = new DateTime(1970,1,1);
\r
3254 uint numSections = 2; // always have .text and .reloc sections
\r
3255 internal SubSystem subSys = SubSystem.Windows_CUI; // default is Windows Console mode
\r
3256 internal uint fileAlign = minFileAlign;
\r
3257 uint entryPointOffset, entryPointPadding, imageSize, headerSize, headerPadding, entryPointToken = 0;
\r
3258 uint relocOffset, relocRVA, relocSize, relocPadding, relocTide, hintNameTableOffset;
\r
3259 uint metaDataOffset, runtimeEngineOffset, initDataSize = 0, importTablePadding;
\r
3260 uint importTableOffset, importLookupTableOffset, totalImportTableSize;
\r
3261 MetaData metaData;
\r
3262 char[] runtimeEngine = runtimeEngineName.ToCharArray(), hintNameTable;
\r
3263 bool doDLL, largeStrings, largeGUID, largeUS, largeBlob;
\r
3264 ushort characteristics;
\r
3266 internal FileImage(bool makeDLL, string fileName) : base(new FileStream(fileName,FileMode.Create)) {
\r
3267 InitFileImage(makeDLL);
\r
3268 TimeSpan tmp = System.IO.File.GetCreationTime(fileName).Subtract(origin);
\r
3269 dateStamp = Convert.ToUInt32(tmp.TotalSeconds);
\r
3272 internal FileImage(bool makeDLL, Stream str) : base(str) {
\r
3273 InitFileImage(makeDLL);
\r
3274 TimeSpan tmp = DateTime.Now.Subtract(origin);
\r
3275 dateStamp = Convert.ToUInt32(tmp.TotalSeconds);
\r
3278 private void InitFileImage(bool makeDLL) {
\r
3281 hintNameTable = dllHintNameTable.ToCharArray();
\r
3282 characteristics = dllCharacteristics;
\r
3284 hintNameTable = exeHintNameTable.ToCharArray();
\r
3285 characteristics = exeCharacteristics;
\r
3287 text = new Section(textName,0x60000020); // IMAGE_SCN_CNT CODE, EXECUTE, READ
\r
3288 // rsrc = new Section(rsrcName,0x40000040); // IMAGE_SCN_CNT INITIALIZED_DATA, READ
\r
3289 metaData = new MetaData(this);
\r
3292 internal MetaData GetMetaData() {
\r
3296 private uint GetNextSectStart(uint rva, uint tide) {
\r
3297 if (tide < SectionAlignment) return rva + SectionAlignment;
\r
3298 return rva + ((tide / SectionAlignment) + 1) * SectionAlignment;
\r
3301 private void BuildTextSection() {
\r
3303 // IAT (single entry 8 bytes for pure CIL)
\r
3304 // CLIHeader (72 bytes)
\r
3305 // CIL instructions for all methods (variable size)
\r
3307 // ImportTable (40 bytes)
\r
3308 // ImportLookupTable(8 bytes) (same as IAT for standard CIL files)
\r
3309 // Hint/Name Tables with entry "_CorExeMain" for .exe file and "_CorDllMain" for .dll (14 bytes)
\r
3310 // ASCII string "mscoree.dll" referenced in ImportTable (+ padding = 16 bytes)
\r
3311 // Entry Point (0xFF25 followed by 4 bytes 0x400000 + RVA of .text)
\r
3312 metaData.BuildMetaData(IATSize + CLIHeaderSize);
\r
3313 metaDataOffset = IATSize + CLIHeaderSize;
\r
3314 // Console.WriteLine("Code starts at " + metaDataOffset);
\r
3315 metaDataOffset += metaData.CodeSize();
\r
3316 // resourcesStart =
\r
3317 // strongNameSig = metaData.GetStrongNameSig();
\r
3318 // fixUps = RVA for vtable
\r
3319 importTableOffset = metaDataOffset + metaData.Size();
\r
3320 importTablePadding = NumToAlign(importTableOffset,16);
\r
3321 importTableOffset += importTablePadding;
\r
3322 importLookupTableOffset = importTableOffset + ImportTableSize;
\r
3323 hintNameTableOffset = importLookupTableOffset + IATSize;
\r
3324 runtimeEngineOffset = hintNameTableOffset + (uint)hintNameTable.Length;
\r
3325 entryPointOffset = runtimeEngineOffset + (uint)runtimeEngine.Length;
\r
3326 totalImportTableSize = entryPointOffset - importTableOffset;
\r
3327 // Console.WriteLine("total import table size = " + totalImportTableSize);
\r
3328 // Console.WriteLine("entrypoint offset = " + entryPointOffset);
\r
3329 entryPointPadding = NumToAlign(entryPointOffset,4) + 2;
\r
3330 entryPointOffset += entryPointPadding;
\r
3331 text.AddReloc(entryPointOffset+2);
\r
3332 text.IncTide(entryPointOffset + 6);
\r
3333 //if (text.Tide() < fileAlign) fileAlign = minFileAlign;
\r
3334 text.SetSize(NumToAlign(text.Tide(),fileAlign));
\r
3335 // Console.WriteLine("text size = " + text.Size() + " text tide = " + text.Tide() + " text padding = " + text.Padding());
\r
3336 // Console.WriteLine("metaDataOffset = " + Hex.Int(metaDataOffset));
\r
3337 // Console.WriteLine("importTableOffset = " + Hex.Int(importTableOffset));
\r
3338 // Console.WriteLine("importLookupTableOffset = " + Hex.Int(importLookupTableOffset));
\r
3339 // Console.WriteLine("hintNameTableOffset = " + Hex.Int(hintNameTableOffset));
\r
3340 // Console.WriteLine("runtimeEngineOffset = " + Hex.Int(runtimeEngineOffset));
\r
3341 // Console.WriteLine("entryPointOffset = " + Hex.Int(entryPointOffset));
\r
3342 // Console.WriteLine("entryPointPadding = " + Hex.Int(entryPointPadding));
\r
3346 internal void BuildRelocSection() {
\r
3347 text.DoRelocs(reloc);
\r
3348 if (sdata != null) sdata.DoRelocs(reloc);
\r
3349 if (rsrc != null) rsrc.DoRelocs(reloc);
\r
3350 relocTide = (uint)reloc.Seek(0,SeekOrigin.Current);
\r
3351 relocPadding = NumToAlign(relocTide,fileAlign);
\r
3352 relocSize = relocTide + relocPadding;
\r
3353 imageSize = relocRVA + SectionAlignment;
\r
3354 initDataSize += relocSize;
\r
3357 private void CalcOffsets() {
\r
3362 headerSize = fileHeaderSize + (numSections * sectionHeaderSize);
\r
3363 headerPadding = NumToAlign(headerSize,fileAlign);
\r
3364 headerSize += headerPadding;
\r
3365 uint offset = headerSize;
\r
3366 uint rva = SectionAlignment;
\r
3367 text.SetOffset(offset);
\r
3369 offset += text.Size();
\r
3370 rva = GetNextSectStart(rva,text.Tide());
\r
3371 // Console.WriteLine("headerSize = " + headerSize);
\r
3372 // Console.WriteLine("headerPadding = " + headerPadding);
\r
3373 // Console.WriteLine("textOffset = " + Hex.Int(text.Offset()));
\r
3374 if (sdata != null) {
\r
3375 sdata.SetSize(NumToAlign(sdata.Tide(),fileAlign));
\r
3376 sdata.SetOffset(offset);
\r
3377 sdata.SetRVA(rva);
\r
3378 offset += sdata.Size();
3379 rva = GetNextSectStart(rva,sdata.Tide());
\r
3380 initDataSize += sdata.Size();
\r
3382 if (rsrc != null) {
\r
3383 rsrc.SetSize(NumToAlign(rsrc.Tide(),fileAlign));
\r
3384 rsrc.SetOffset(offset);
\r
3386 offset += rsrc.Size();
\r
3387 rva = GetNextSectStart(rva,rsrc.Tide());
\r
3388 initDataSize += rsrc.Size();
\r
3390 relocOffset = offset;
\r
3394 internal void MakeFile() {
\r
3395 if (doDLL) hintNameTable = dllHintNameTable.ToCharArray();
\r
3396 else hintNameTable = exeHintNameTable.ToCharArray();
\r
3397 BuildTextSection();
\r
3399 BuildRelocSection();
\r
3400 // now write it out
\r
3407 private void WriteHeader() {
\r
3409 // Console.WriteLine("Writing PEHeader at offset " + Seek(0,SeekOrigin.Current));
\r
3411 // Console.WriteLine("Writing text section header at offset " + Hex.Long(Seek(0,SeekOrigin.Current)));
\r
3412 text.WriteHeader(this,relocRVA);
\r
3413 if (sdata != null) sdata.WriteHeader(this,relocRVA);
\r
3414 if (rsrc != null) rsrc.WriteHeader(this,relocRVA);
\r
3415 // Console.WriteLine("Writing reloc section header at offset " + Seek(0,SeekOrigin.Current));
\r
3416 WriteRelocSectionHeader();
\r
3417 // Console.WriteLine("Writing padding at offset " + Seek(0,SeekOrigin.Current));
\r
3418 WriteZeros(headerPadding);
\r
3421 private void WriteSections() {
\r
3422 // Console.WriteLine("Writing text section at offset " + Seek(0,SeekOrigin.Current));
\r
3423 WriteTextSection();
\r
3424 if (sdata != null) WriteSDataSection();
\r
3425 if (rsrc != null) WriteRsrcSection();
\r
3426 WriteRelocSection();
\r
3429 private void WriteIAT() {
\r
3430 Write(text.RVA() + hintNameTableOffset);
\r
3434 private void WriteImportTables() {
\r
3436 WriteZeros(importTablePadding);
\r
3437 // Console.WriteLine("Writing import tables at offset " + Hex.Long(Seek(0,SeekOrigin.Current)));
\r
3438 Write(importLookupTableOffset + text.RVA());
\r
3440 Write(runtimeEngineOffset + text.RVA());
\r
3441 Write(text.RVA()); // IAT is at the beginning of the text section
\r
3443 // Import Lookup Table
\r
3444 WriteIAT(); // lookup table and IAT are the same
\r
3445 // Hint/Name Table
\r
3446 // Console.WriteLine("Writing hintname table at " + Hex.Long(Seek(0,SeekOrigin.Current)));
\r
3447 Write(hintNameTable);
\r
3448 Write(runtimeEngineName.ToCharArray());
\r
3451 private void WriteTextSection() {
\r
3454 // Console.WriteLine("Writing code at " + Hex.Long(Seek(0,SeekOrigin.Current)));
\r
3455 metaData.WriteByteCodes(this);
\r
3456 // Console.WriteLine("Finished writing code at " + Hex.Long(Seek(0,SeekOrigin.Current)));
\r
3457 largeStrings = metaData.LargeStringsIndex();
\r
3458 largeGUID = metaData.LargeGUIDIndex();
\r
3459 largeUS = metaData.LargeUSIndex();
\r
3460 largeBlob = metaData.LargeBlobIndex();
\r
3461 metaData.WriteMetaData(this);
\r
3462 WriteImportTables();
\r
3463 WriteZeros(entryPointPadding);
\r
3464 Write((ushort)0x25FF);
\r
3465 Write(ImageBase + text.RVA());
\r
3466 WriteZeros(text.Padding());
\r
3469 private void WriteCLIHeader() {
\r
3470 Write(CLIHeaderSize); // Cb
\r
3471 Write((short)2); // Major runtime version
\r
3472 Write((short)0); // Minor runtime version
\r
3473 Write(text.RVA() + metaDataOffset);
\r
3474 Write(metaData.Size());
\r
3475 Write(runtimeFlags);
\r
3476 Write(entryPointToken);
\r
3477 WriteZeros(8); // Resources - used by Manifest Resources NYI
\r
3478 WriteZeros(8); // Strong Name stuff here!! NYI
\r
3479 WriteZeros(8); // CodeManagerTable
\r
3480 WriteZeros(8); // VTableFixups NYI
\r
3481 WriteZeros(16); // ExportAddressTableJumps, ManagedNativeHeader
\r
3484 private void WriteSDataSection() {
\r
3485 for (int i=0; i < data.Count; i++) {
\r
3486 ((DataConstant)data[i]).Write(this);
\r
3490 private void WriteRsrcSection() {
\r
3493 private void WriteRelocSection() {
\r
3494 // Console.WriteLine("Writing reloc section at " + Seek(0,SeekOrigin.Current) + " = " + relocOffset);
\r
3495 MemoryStream str = (MemoryStream)reloc.BaseStream;
\r
3496 Write(str.ToArray());
\r
3497 WriteZeros(NumToAlign((uint)str.Position,fileAlign));
\r
3500 internal void SetEntryPoint(uint entryPoint) {
\r
3501 entryPointToken = entryPoint;
\r
3504 internal void AddInitData(DataConstant cVal) {
\r
3505 if (sdata == null) {
\r
3506 sdata = new Section(sdataName,0xC0000040); // IMAGE_SCN_CNT INITIALIZED_DATA, READ, WRITE
\r
3507 data = new ArrayList();
\r
3510 cVal.DataOffset = sdata.Tide();
\r
3511 sdata.IncTide(cVal.GetSize());
\r
3514 internal void WriteZeros(uint numZeros) {
\r
3515 for (int i=0; i < numZeros; i++) {
\r
3520 internal void WritePEHeader() {
\r
3521 Write((ushort)0x014C); // Machine - always 0x14C for Managed PE Files (allow others??)
\r
3522 Write((ushort)numSections);
\r
3524 WriteZeros(8); // Pointer to Symbol Table and Number of Symbols (always zero for ECMA CLI files)
\r
3525 Write((ushort)0x00E0); // Size of Optional Header
\r
3526 Write(characteristics);
\r
3527 // PE Optional Header
\r
3528 Write((ushort)0x010B); // Magic
\r
3529 Write((byte)0x6); // LMajor pure-IL = 6 C++ = 7
\r
3530 Write((byte)0x0); // LMinor
\r
3531 Write(text.Size());
\r
3532 Write(initDataSize);
\r
3533 Write(0); // Check other sections here!!
\r
3534 Write(text.RVA() + entryPointOffset);
\r
3535 Write(text.RVA());
\r
3536 uint dataBase = 0;
\r
3537 if (sdata != null) dataBase = sdata.RVA();
\r
3538 else if (rsrc != null) dataBase = rsrc.RVA();
\r
3539 else dataBase = relocRVA;
\r
3542 Write(SectionAlignment);
\r
3544 Write((ushort)0x04); // OS Major
\r
3545 WriteZeros(6); // OS Minor, User Major, User Minor
\r
3546 Write((ushort)0x04); // SubSys Major
\r
3547 WriteZeros(6); // SybSys Minor, Reserved
\r
3549 Write(headerSize);
\r
3550 Write((int)0); // File Checksum
\r
3551 Write((ushort)subSys);
\r
3552 Write((short)0); // DLL Flags
\r
3553 Write((uint)0x100000); // Stack Reserve Size
\r
3554 Write((uint)0x1000); // Stack Commit Size
\r
3555 Write((uint)0x100000); // Heap Reserve Size
\r
3556 Write((uint)0x1000); // Heap Commit Size
\r
3557 Write(0); // Loader Flags
\r
3558 Write(0x10); // Number of Data Directories
\r
3559 WriteZeros(8); // Export Table
\r
3560 Write(importTableOffset + text.RVA());
\r
3561 Write(totalImportTableSize);
\r
3562 WriteZeros(24); // Resource, Exception and Certificate Tables
\r
3565 WriteZeros(48); // Debug, Copyright, Global Ptr, TLS, Load Config and Bound Import Tables
\r
3566 Write(text.RVA()); // IATRVA - IAT is at start of .text Section
\r
3568 WriteZeros(8); // Delay Import Descriptor
\r
3569 Write(text.RVA()+IATSize); // CLIHeader immediately follows IAT
\r
3570 Write(CLIHeaderSize);
\r
3571 WriteZeros(8); // Reserved
\r
3574 internal void WriteRelocSectionHeader() {
\r
3575 Write(relocName.ToCharArray());
\r
3579 Write(relocOffset);
\r
3581 Write(relocFlags);
\r
3584 private void Align (MemoryStream str, int val) {
\r
3585 if ((str.Position % val) != 0) {
\r
3586 for (int i=val - (int)(str.Position % val); i > 0; i--) {
\r
3592 private uint Align(uint val, uint alignVal) {
\r
3593 if ((val % alignVal) != 0) {
\r
3594 val += alignVal - (val % alignVal);
\r
3599 private uint NumToAlign(uint val, uint alignVal) {
\r
3600 if ((val % alignVal) == 0) return 0;
\r
3601 return alignVal - (val % alignVal);
\r
3604 internal void StringsIndex(uint ix) {
\r
3605 if (largeStrings) Write(ix);
\r
3606 else Write((ushort)ix);
\r
3609 internal void GUIDIndex(uint ix) {
\r
3610 if (largeGUID) Write(ix);
\r
3611 else Write((ushort)ix);
\r
3614 internal void USIndex(uint ix) {
\r
3615 if (largeUS) Write(ix);
\r
3616 else Write((ushort)ix);
\r
3619 internal void BlobIndex(uint ix) {
\r
3620 if (largeBlob) Write(ix);
\r
3621 else Write((ushort)ix);
\r
3624 internal void WriteIndex(MDTable tabIx,uint ix) {
\r
3625 if (metaData.LargeIx(tabIx)) Write(ix);
\r
3626 else Write((ushort)ix);
\r
3629 internal void WriteCodedIndex(CIx code, MetaDataElement elem) {
\r
3630 metaData.WriteCodedIndex(code,elem,this);
\r
3633 internal void WriteCodeRVA(uint offs) {
\r
3634 Write(text.RVA() + offs);
\r
3637 internal void WriteDataRVA(uint offs) {
\r
3638 Write(sdata.RVA() + offs);
\r
3641 internal void Write3Bytes(uint val) {
\r
3642 byte b3 = (byte)((val & FileImage.iByteMask[2]) >> 16);
\r
3643 byte b2 = (byte)((val & FileImage.iByteMask[1]) >> 8);;
\r
3644 byte b1 = (byte)(val & FileImage.iByteMask[0]);
\r
3651 /**************************************************************************/
\r
3653 /// Descriptor for a file referenced in THIS assembly/module (.file)
\r
3655 public class FileRef : MetaDataElement
\r
3657 private static readonly uint NoMetaData = 0x1;
\r
3658 uint nameIx = 0, hashIx = 0;
\r
3661 internal FileRef(string name, byte[] hashBytes, bool metaData,
\r
3662 bool entryPoint, MetaData md) {
\r
3663 if (!metaData) flags = NoMetaData;
\r
3664 if (entryPoint) md.SetEntryPoint(this);
\r
3665 nameIx = md.AddToStringsHeap(name);
\r
3666 hashIx = md.AddToBlobHeap(hashBytes);
\r
3667 tabIx = MDTable.File;
\r
3670 internal FileRef(uint nameIx, byte[] hashBytes, bool metaData,
\r
3671 bool entryPoint, MetaData md) {
\r
3672 if (metaData) flags = HasMetaData;
\r
3673 if (entryPoint) md.SetEntryPoint(this);
\r
3674 this.nameIx = nameIx;
\r
3675 hashIx = md.AddToBlobHeap(hashBytes);
\r
3676 tabIx = MDTable.File;
\r
3679 internal sealed override uint Size(MetaData md) {
\r
3680 return 4 + md.StringsIndexSize() + md.BlobIndexSize();
\r
3683 internal sealed override void Write(FileImage output) {
\r
3684 output.Write(flags);
\r
3685 output.StringsIndex(nameIx);
\r
3686 output.BlobIndex(hashIx);
\r
3689 internal sealed override uint GetCodedIx(CIx code) {
\r
3691 case (CIx.HasCustomAttr) : return 16;
\r
3692 case (CIx.Implementation) : return 0;
\r
3698 /**************************************************************************/
\r
3700 /// Descriptor for pinvoke information for a method NOT YET IMPLEMENTED
\r
3702 public class ImplMap : MetaDataElement
\r
3704 private static readonly ushort NoMangle = 0x01;
\r
3707 string importName;
\r
3709 ModuleRef importScope;
\r
3711 internal ImplMap(ushort flag, Method implMeth, string iName, ModuleRef mScope) {
\r
3714 importName = iName;
\r
3715 importScope = mScope;
\r
3716 tabIx = MDTable.ImplMap;
\r
3717 if (iName == null) flags |= NoMangle;
\r
3718 //throw(new NotYetImplementedException("PInvoke "));
\r
3721 internal sealed override void BuildTables(MetaData md) {
\r
3723 iNameIx = md.AddToStringsHeap(importName);
\r
3727 internal sealed override uint Size(MetaData md) {
\r
3728 return 2+ md.CodedIndexSize(CIx.MemberForwarded) +
\r
3729 md.StringsIndexSize() + md.TableIndexSize(MDTable.ModuleRef);
\r
3732 internal sealed override void Write(FileImage output) {
\r
3733 output.Write(flags);
\r
3734 output.WriteCodedIndex(CIx.MemberForwarded,meth);
\r
3735 output.StringsIndex(iNameIx);
\r
3736 output.WriteIndex(MDTable.ModuleRef,importScope.Row);
\r
3741 /**************************************************************************/
\r
3743 /// Descriptor for an IL instruction
\r
3745 internal abstract class CILInstruction {
\r
3746 protected static readonly sbyte maxByteVal = 127;
\r
3747 protected static readonly sbyte minByteVal = -128;
\r
3748 protected static readonly byte leadByte = 0xFE;
\r
3749 protected static readonly uint USHeapIndex = 0x70000000;
\r
3750 protected static readonly int longInstrStart = (int)Op.arglist;
\r
3751 public bool twoByteInstr = false;
\r
3752 public uint size = 0;
\r
3753 public uint offset;
\r
3755 internal virtual bool Check(MetaData md) {
\r
3759 internal virtual void Write(FileImage output) { }
\r
3763 internal class CILByte : CILInstruction {
\r
3766 internal CILByte(byte bVal) {
\r
3771 internal override void Write(FileImage output) {
\r
3772 output.Write(byteVal);
\r
3778 internal class Instr : CILInstruction {
\r
3779 protected int instr;
\r
3781 internal Instr(int inst) {
\r
3782 if (inst >= longInstrStart) {
\r
3783 instr = inst - longInstrStart;
\r
3784 twoByteInstr = true;
\r
3792 internal override void Write(FileImage output) {
\r
3793 //Console.WriteLine("Writing instruction " + instr + " with size " + size);
\r
3794 if (twoByteInstr) output.Write(leadByte);
\r
3795 output.Write((byte)instr);
\r
3800 internal class IntInstr : Instr {
\r
3804 internal IntInstr(int inst, int num, bool byteSize) : base(inst) {
\r
3806 byteNum = byteSize;
\r
3807 if (byteNum) size++;
\r
3811 internal sealed override void Write(FileImage output) {
\r
3812 base.Write(output);
\r
3814 output.Write((sbyte)val);
\r
3816 output.Write(val);
\r
3821 internal class UIntInstr : Instr {
\r
3825 internal UIntInstr(int inst, int num, bool byteSize) : base(inst) {
\r
3827 byteNum = byteSize;
\r
3828 if (byteNum) size++;
\r
3832 internal sealed override void Write(FileImage output) {
\r
3833 base.Write(output);
\r
3835 output.Write((byte)val);
\r
3837 output.Write((ushort)val);
\r
3842 internal class LongInstr : Instr {
\r
3845 internal LongInstr(int inst, long l) : base(inst) {
\r
3850 internal sealed override void Write(FileImage output) {
\r
3851 base.Write(output);
\r
3852 output.Write(val);
\r
3857 internal class FloatInstr : Instr {
\r
3860 internal FloatInstr(int inst, float f) : base(inst) {
\r
3865 internal sealed override void Write(FileImage output) {
\r
3866 base.Write(output);
\r
3867 output.Write(fVal);
\r
3872 internal class DoubleInstr : Instr {
\r
3875 internal DoubleInstr(int inst, double d) : base(inst) {
\r
3880 internal sealed override void Write(FileImage output) {
\r
3881 base.Write(output);
\r
3882 output.Write(val);
\r
3887 internal class StringInstr : Instr {
\r
3892 internal StringInstr(int inst, string str) : base(inst) {
\r
3897 internal StringInstr (int inst, byte[] str) : base (inst) {
3902 internal sealed override bool Check(MetaData md) {
3904 strIndex = md.AddToUSHeap(val);
3906 strIndex = md.AddToUSHeap (bval);
3910 internal sealed override void Write(FileImage output) {
\r
3911 base.Write(output);
\r
3912 output.Write(USHeapIndex | strIndex);
\r
3917 internal class LabelInstr : CILInstruction {
\r
3920 internal LabelInstr(CILLabel lab) {
\r
3922 label.AddLabelInstr(this);
\r
3926 internal class FieldInstr : Instr {
\r
3929 internal FieldInstr(int inst, Field f) : base(inst) {
\r
3934 internal sealed override void Write(FileImage output) {
\r
3935 base.Write(output);
\r
3936 output.Write(field.Token());
\r
3941 internal class MethInstr : Instr {
\r
3944 internal MethInstr(int inst, Method m) : base(inst) {
\r
3949 internal sealed override void Write(FileImage output) {
\r
3950 base.Write(output);
\r
3951 output.Write(meth.Token());
\r
3956 internal class SigInstr : Instr {
\r
3957 CalliSig signature;
\r
3959 internal SigInstr(int inst, CalliSig sig) : base(inst) {
\r
3964 internal sealed override bool Check(MetaData md) {
\r
3965 md.AddToTable(MDTable.StandAloneSig,signature);
\r
3966 signature.BuildTables(md);
\r
3970 internal sealed override void Write(FileImage output) {
\r
3971 base.Write(output);
\r
3972 output.Write(signature.Token());
\r
3976 internal class TypeInstr : Instr {
\r
3977 MetaDataElement theType;
\r
3979 internal TypeInstr(int inst, Type aType, MetaData md) : base(inst) {
\r
3980 theType = aType.GetTypeSpec(md);
\r
3984 internal sealed override void Write(FileImage output) {
\r
3985 base.Write(output);
\r
3986 output.Write(theType.Token());
\r
3991 internal class BranchInstr : Instr {
\r
3993 private bool shortVer = true;
\r
3994 private static readonly byte longInstrOffset = 13;
\r
3995 private int target = 0;
\r
3997 internal BranchInstr(int inst, CILLabel dst) : base(inst) {
\r
3999 dest.AddBranch(this);
\r
4002 if (inst >= (int) BranchOp.br && inst != (int) BranchOp.leave_s) {
4008 internal sealed override bool Check(MetaData md) {
\r
4009 target = (int)dest.GetLabelOffset() - (int)(offset + size);
\r
4013 internal sealed override void Write(FileImage output) {
\r
4014 base.Write(output);
\r
4016 output.Write((sbyte)target);
\r
4018 output.Write(target);
\r
4023 internal class SwitchInstr : Instr {
\r
4025 uint numCases = 0;
\r
4027 internal SwitchInstr(int inst, CILLabel[] dsts) : base(inst) {
\r
4029 if (cases != null) numCases = (uint)cases.Length;
\r
4030 size += 4 + (numCases * 4);
\r
4031 for (int i=0; i < numCases; i++) {
\r
4032 cases[i].AddBranch(this);
\r
4036 internal sealed override void Write(FileImage output) {
\r
4037 base.Write(output);
\r
4038 output.Write(numCases);
\r
4039 for (int i=0; i < numCases; i++) {
\r
4040 int target = (int)cases[i].GetLabelOffset() - (int)(offset + size);
\r
4041 output.Write(target);
\r
4046 /**************************************************************************/
\r
4048 public class GenericParameter : MetaDataElement
\r
4050 MetaDataElement owner;
4056 internal GenericParameter (ClassDef owner, MetaData metadata,
4057 short index, string name) : this (owner, metadata, index, name, true)
4061 internal GenericParameter (MethodDef owner, MetaData metadata,
4062 short index, string name) : this (owner, metadata, index, name, true)
4066 private GenericParameter (MetaDataElement owner, MetaData metadata,
4067 short index, string name, bool nadda)
4069 this.owner = owner;
\r
4070 this.metadata = metadata;
4071 this.index = index;
\r
4072 tabIx = MDTable.GenericParam;
\r
4076 public void AddConstraint (Type constraint) {
4077 metadata.AddToTable (MDTable.GenericParamConstraint,
\r
4078 new GenericParamConstraint (this, constraint));
\r
4081 internal sealed override uint Size(MetaData md) {
\r
4082 return (uint) (4 +
\r
4083 md.CodedIndexSize(CIx.TypeOrMethodDef) +
\r
4085 md.TableIndexSize(MDTable.TypeDef));
\r
4088 internal sealed override void BuildTables(MetaData md) {
\r
4090 nameIx = md.AddToStringsHeap(name);
\r
4094 internal sealed override void Write(FileImage output) {
\r
4095 output.Write ((short) index);
\r
4096 output.Write ((short) 0);
\r
4097 output.WriteCodedIndex(CIx.TypeOrMethodDef, owner);
\r
4098 output.Write ((uint) nameIx);
\r
4099 output.WriteIndex(MDTable.TypeDef,owner.Row);
\r
4105 internal class GenericParamConstraint : MetaDataElement
\r
4107 GenericParameter param;
\r
4110 public GenericParamConstraint (GenericParameter param, Type type) {
\r
4111 this.param = param;
\r
4113 tabIx = MDTable.GenericParamConstraint;
\r
4116 internal sealed override uint Size(MetaData md) {
\r
4117 return (uint) (md.TableIndexSize(MDTable.GenericParam) +
\r
4118 md.CodedIndexSize(CIx.TypeDefOrRef));
\r
4121 internal sealed override void Write(FileImage output) {
\r
4122 output.WriteIndex(MDTable.GenericParam, param.Row);
\r
4123 output.WriteCodedIndex(CIx.TypeDefOrRef, type);
\r
4129 internal class MethodSpec : MetaDataElement
4132 GenericMethodSig g_sig;
4135 internal MethodSpec (Method meth, GenericMethodSig g_sig) {
4138 tabIx = MDTable.MethodSpec;
4141 internal sealed override void BuildTables (MetaData md) {
4143 sidx = g_sig.GetSigIx (md);
4147 internal sealed override uint Size (MetaData md) {
4148 return (uint) (md.CodedIndexSize(CIx.MethodDefOrRef) +
4149 md.BlobIndexSize ());
4152 internal sealed override void Write (FileImage output) {
4153 output.WriteCodedIndex (CIx.MethodDefOrRef, meth);
4154 output.BlobIndex (sidx);
\r
4158 /**************************************************************************/
\r
4160 /// Descriptor for interface implemented by a class
\r
4162 public class InterfaceImpl: MetaDataElement
\r
4164 ClassDef theClass;
\r
4165 Class theInterface;
\r
4167 internal InterfaceImpl(ClassDef theClass, Class theInterface) {
\r
4168 this.theClass = theClass;
\r
4169 this.theInterface = theInterface;
\r
4170 tabIx = MDTable.InterfaceImpl;
\r
4173 internal sealed override uint Size(MetaData md) {
\r
4174 return md.TableIndexSize(MDTable.TypeDef) +
\r
4175 md.CodedIndexSize(CIx.TypeDefOrRef);
\r
4178 internal sealed override void Write(FileImage output) {
\r
4179 output.WriteIndex(MDTable.TypeDef,theClass.Row);
\r
4180 output.WriteCodedIndex(CIx.TypeDefOrRef,theInterface);
\r
4183 internal sealed override uint GetCodedIx(CIx code) { return 5; }
\r
4186 /**************************************************************************/
\r
4188 /// Descriptor for a local of a method
\r
4190 public class Local
\r
4192 private static readonly byte Pinned = 0x45;
\r
4195 bool pinned = false, byref = false;
\r
4198 /// Create a new local variable
\r
4200 /// <param name="lName">name of the local variable</param>
\r
4201 /// <param name="lType">type of the local variable</param>
\r
4202 public Local(string lName, Type lType) {
\r
4208 /// Create a new local variable that is byref and/or pinned
\r
4210 /// <param name="lName">local name</param>
\r
4211 /// <param name="lType">local type</param>
\r
4212 /// <param name="byRef">is byref</param>
\r
4213 /// <param name="isPinned">has pinned attribute</param>
\r
4214 public Local(string lName, Type lType, bool byRef, bool isPinned)
\r
4219 pinned = isPinned;
\r
4222 internal void TypeSig(MemoryStream str) {
\r
4223 if (pinned) str.WriteByte(Pinned);
\r
4224 type.TypeSig(str);
\r
4228 /**************************************************************************/
\r
4230 /// Descriptor for the locals for a method
\r
4233 public class LocalSig : Signature
\r
4235 private static readonly byte LocalSigByte = 0x7;
\r
4238 public LocalSig(Local[] locals) {
\r
4239 this.locals = locals;
\r
4240 tabIx = MDTable.StandAloneSig;
\r
4243 internal sealed override void BuildTables(MetaData md) {
\r
4245 MemoryStream sig = new MemoryStream();
\r
4246 sig.WriteByte(LocalSigByte);
\r
4247 MetaData.CompressNum((uint)locals.Length,sig);
\r
4248 for (int i=0; i < locals.Length; i++) {
\r
4249 ((Local)locals[i]).TypeSig(sig);
\r
4251 sigIx = md.AddToBlobHeap(sig.ToArray());
\r
4257 /**************************************************************************/
\r
4259 /// Descriptor for resources used in this PE file NOT YET IMPLEMENTED
\r
4262 public class ManifestResource : MetaDataElement
\r
4264 private static readonly uint PublicResource = 0x1;
\r
4265 private static readonly uint PrivateResource = 0x2;
\r
4268 MetaDataElement rRef;
\r
4273 public ManifestResource(string name, bool isPub, FileRef fileRef) {
\r
4275 if (isPub) flags = PublicResource;
\r
4276 else flags = PrivateResource;
\r
4278 tabIx = MDTable.ManifestResource;
\r
4279 throw(new NotYetImplementedException("Manifest Resources "));
\r
4282 public ManifestResource(string name, bool isPub, FileRef fileRef,
\r
4285 if (isPub) flags = PublicResource;
\r
4286 else flags = PrivateResource;
\r
4288 fileOffset = fileIx;
\r
4291 public ManifestResource(string name, bool isPub, AssemblyRef assemRef) {
\r
4293 if (isPub) flags = PublicResource;
\r
4294 else flags = PrivateResource;
\r
4298 internal sealed override void BuildTables(MetaData md) {
\r
4300 nameIx = md.AddToStringsHeap(mrName);
\r
4304 internal sealed override uint Size(MetaData md) {
\r
4305 return 8 + md.StringsIndexSize() +
\r
4306 md.CodedIndexSize(CIx.Implementation);
\r
4309 internal sealed override void Write(FileImage output) {
\r
4310 output.Write(fileOffset);
\r
4311 output.Write(flags);
\r
4312 output.StringsIndex(nameIx);
\r
4313 output.WriteCodedIndex(CIx.Implementation,rRef);
\r
4316 internal sealed override uint GetCodedIx(CIx code) { return 18; }
\r
4319 /**************************************************************************/
\r
4321 /// Base class for elements in the PropertyMap, EventMap and
\r
4322 /// NestedClass MetaData tables
\r
4324 public class MapElem : MetaDataElement
\r
4328 MDTable elemTable;
\r
4330 internal MapElem(ClassDef par, uint elIx, MDTable elemTab) {
\r
4333 elemTable = elemTab;
\r
4336 internal sealed override uint Size(MetaData md) {
\r
4337 return md.TableIndexSize(MDTable.TypeDef) + md.TableIndexSize(elemTable);
\r
4340 internal sealed override void Write(FileImage output) {
\r
4341 output.WriteIndex(MDTable.TypeDef,parent.Row);
\r
4342 output.WriteIndex(elemTable,elemIx);
\r
4345 /**************************************************************************/
\r
4347 /// Base class for field/methods (member of a class)
\r
4349 public abstract class Member : MetaDataElement
\r
4351 protected string name;
\r
4352 protected uint nameIx = 0, sigIx = 0;
\r
4354 internal Member(string memName)
\r
4357 tabIx = MDTable.MemberRef;
\r
4361 /**************************************************************************/
\r
4364 /// Root (20 bytes + UTF-8 Version String + quad align padding)
\r
4365 /// StreamHeaders (8 bytes + null terminated name string + quad align padding)
\r
4367 /// #~ (always present - holds metadata tables)
\r
4368 /// #Strings (always present - holds identifier strings)
\r
4369 /// #US (Userstring heap)
\r
4370 /// #Blob (signature blobs)
\r
4371 /// #GUID (guids for assemblies or Modules)
\r
4374 public class MetaData
\r
4376 private static readonly int[] CIxShiftMap = {2,2,5,1,2,3,1,1,1,2,3,2,1};
\r
4377 private static readonly byte StringsHeapMask = 0x1;
\r
4378 private static readonly byte GUIDHeapMask = 0x2;
\r
4379 private static readonly byte BlobHeapMask = 0x4;
\r
4380 private static readonly uint MetaDataSignature = 0x424A5342;
\r
4381 private static readonly uint maxSmlIxSize = 0xFFFF;
\r
4382 private static readonly uint max1BitSmlIx = 0x7FFF;
\r
4383 private static readonly uint max2BitSmlIx = 0x3FFF;
\r
4384 private static readonly uint max3BitSmlIx = 0x1FFF;
\r
4385 private static readonly uint max5BitSmlIx = 0x7FF;
\r
4386 // NOTE: version and stream name strings MUST always be quad padded
\r
4387 private static readonly string version = "v1.0.3705\0\0\0";
\r
4388 private static readonly char[] tildeName = {'#','~','\0','\0'};
\r
4389 private static readonly char[] stringsName = {'#','S','t','r','i','n','g','s','\0','\0','\0','\0'};
\r
4390 private static readonly char[] usName = {'#','U','S','\0'};
\r
4391 private static readonly char[] guidName = {'#','G','U','I','D','\0','\0','\0'};
\r
4392 private static readonly char[] blobName = {'#','B','l','o','b','\0','\0','\0'};
\r
4393 private static readonly uint MetaDataHeaderSize = 20 + (uint)version.Length;
\r
4394 private static readonly uint TildeHeaderSize = 24;
\r
4395 private static readonly uint StreamHeaderSize = 8;
\r
4396 private static readonly uint numMetaDataTables = (int)MDTable.GenericParamConstraint + 1;
\r
4397 private static readonly uint tildeHeaderSize = 8 + (uint)tildeName.Length;
\r
4399 MetaDataStream strings, us, guid, blob;
\r
4401 MetaDataStream[] streams = new MetaDataStream[5];
\r
4402 uint numStreams = 5;
\r
4403 uint tildeTide = 0, tildePadding = 0, tildeStart = 0;
\r
4404 uint numTables = 0;
\r
4405 ArrayList[] metaDataTables = new ArrayList[numMetaDataTables];
\r
4406 ArrayList byteCodes = new ArrayList();
\r
4407 uint codeSize = 0, codeStart, byteCodePadding = 0, metaDataSize = 0;
\r
4408 ulong valid = 0, /*sorted = 0x000002003301FA00;*/ sorted = 0;
\r
4409 bool[] largeIx = new bool[numMetaDataTables];
\r
4410 bool[] lgeCIx = new bool[(int)CIx.MaxCIx];
\r
4411 bool largeStrings = false, largeUS = false, largeGUID = false, largeBlob = false;
\r
4412 private FileImage file;
\r
4413 private byte heapSizes = 0;
\r
4414 MetaDataElement entryPoint;
\r
4415 BinaryWriter output;
\r
4416 public MSCorLib mscorlib;
\r
4417 private TypeSpec[] systemTypeSpecs = new TypeSpec[PrimitiveType.NumSystemTypes];
\r
4420 internal MetaData(FileImage file) {
\r
4421 // tilde = new MetaDataStream(tildeName,false,0);
\r
4423 strings = new MetaDataStream(stringsName,new UTF8Encoding(),true);
\r
4424 us = new MetaDataStream(usName,new UnicodeEncoding(),true);
\r
4425 guid = new MetaDataStream(guidName,false);
\r
4426 blob = new MetaDataStream(blobName,true);
\r
4427 streams[1] = strings;
\r
4429 streams[3] = guid;
\r
4430 streams[4] = blob;
\r
4431 for (int i=0; i < numMetaDataTables; i++) {
\r
4432 largeIx[i] = false;
\r
4434 for (int i=0; i < lgeCIx.Length; i++) {
\r
4435 lgeCIx[i] = false;
\r
4437 mscorlib = new MSCorLib(this);
\r
4440 internal TypeSpec GetPrimitiveTypeSpec(int ix) {
\r
4441 return systemTypeSpecs[ix];
\r
4444 internal void SetPrimitiveTypeSpec(int ix, TypeSpec typeSpec) {
\r
4445 systemTypeSpecs[ix] = typeSpec;
\r
4448 internal uint Size() {
\r
4449 return metaDataSize;
\r
4452 internal void StreamSize(byte mask) {
\r
4453 heapSizes |= mask;
\r
4456 internal uint AddToUSHeap(string str) {
\r
4457 if (str == null) return 0;
\r
4458 return us.Add(str,true);
\r
4461 internal uint AddToUSHeap(byte[] str) {
4462 if (str == null) return 0;
4463 return us.Add (str, true);
4466 internal uint AddToStringsHeap(string str) {
\r
4467 if ((str == null) || (str.CompareTo("") == 0)) return 0;
\r
4468 return strings.Add(str,false);
\r
4471 internal uint AddToGUIDHeap(Guid guidNum) {
\r
4472 return guid.Add(guidNum, false);
\r
4475 internal uint AddToBlobHeap(byte[] blobBytes) {
\r
4476 if (blobBytes == null) return 0;
\r
4477 return blob.Add(blobBytes, true);
\r
4480 internal uint AddToBlobHeap(byte val) {
\r
4481 return blob.Add(val, true);
\r
4484 internal uint AddToBlobHeap(sbyte val) {
\r
4485 return blob.Add(val, true);
\r
4488 internal uint AddToBlobHeap(ushort val) {
\r
4489 return blob.Add(val, true);
\r
4492 internal uint AddToBlobHeap(short val) {
\r
4493 return blob.Add(val, true);
\r
4496 internal uint AddToBlobHeap(uint val) {
\r
4497 return blob.Add(val, true);
\r
4500 internal uint AddToBlobHeap(int val) {
\r
4501 return blob.Add(val, true);
\r
4504 internal uint AddToBlobHeap(ulong val) {
\r
4505 return blob.Add(val, true);
\r
4508 internal uint AddToBlobHeap(long val) {
\r
4509 return blob.Add(val, true);
\r
4512 internal uint AddToBlobHeap(float val) {
\r
4513 return blob.Add(val, true);
\r
4516 internal uint AddToBlobHeap(double val) {
\r
4517 return blob.Add(val, true);
\r
4520 internal uint AddToBlobHeap(string val) {
\r
4521 return blob.Add(val,true);
\r
4525 private ArrayList GetTable(MDTable tableIx) {
\r
4526 int tabIx = (int)tableIx;
\r
4527 if (metaDataTables[tabIx] == null) {
\r
4528 metaDataTables[tabIx] = new ArrayList();
\r
4529 valid |= ((ulong)0x1 << tabIx);
\r
4530 // Console.WriteLine("after creating table " + tableIx + "(" + tabIx + ") valid = " + valid);
\r
4533 return metaDataTables[tabIx];
\r
4536 internal void AddToTable(MDTable tableIx, MetaDataElement elem) {
\r
4537 if (elem.Row > 0) {
\r
4538 // Console.Out.WriteLine("ERROR - element already in table " + tableIx);
\r
4541 // updates Row field of the element
\r
4542 // Console.WriteLine("Adding element to table " + (uint)tableIx);
\r
4543 ArrayList table = GetTable(tableIx);
\r
4544 elem.Row = (uint)table.Count + 1;
\r
4548 internal uint TableIndex(MDTable tableIx) {
\r
4549 if (metaDataTables[(int)tableIx] == null) return 1;
\r
4550 return (uint)metaDataTables[(int)tableIx].Count+1;
\r
4553 internal uint AddCode(CILInstructions byteCode) {
\r
4554 byteCodes.Add(byteCode);
\r
4555 uint offset = codeSize + codeStart;
\r
4556 codeSize += byteCode.GetCodeSize();
\r
4560 internal void SetEntryPoint(MetaDataElement ep) {
\r
4564 internal void AddData(DataConstant cVal) {
\r
4565 file.AddInitData(cVal);
\r
4568 internal static void CompressNum(uint val, MemoryStream sig) {
\r
4570 sig.WriteByte((byte)val);
\r
4571 } else if (val < 0x3FFF) {
\r
4572 byte b1 = (byte)((val >> 8) | 0x80);
\r
4573 byte b2 = (byte)(val & FileImage.iByteMask[0]);
\r
4574 sig.WriteByte(b1);
\r
4575 sig.WriteByte(b2);
\r
4577 byte b1 = (byte)((val >> 24) | 0xC0);
\r
4578 byte b2 = (byte)((val & FileImage.iByteMask[2]) >> 16);
\r
4579 byte b3 = (byte)((val & FileImage.iByteMask[1]) >> 8);;
\r
4580 byte b4 = (byte)(val & FileImage.iByteMask[0]);
\r
4581 sig.WriteByte(b1);
\r
4582 sig.WriteByte(b2);
\r
4583 sig.WriteByte(b3);
\r
4584 sig.WriteByte(b4);
\r
4588 internal uint CodeSize() {
\r
4589 return codeSize + byteCodePadding;
\r
4592 internal uint StringsIndexSize() {
\r
4593 if (largeStrings) return 4;
\r
4597 internal uint GUIDIndexSize() {
\r
4598 if (largeGUID) return 4;
\r
4602 internal uint USIndexSize() {
\r
4603 if (largeUS) return 4;
\r
4607 internal uint BlobIndexSize() {
\r
4608 if (largeBlob) return 4;
\r
4612 internal uint CodedIndexSize(CIx code) {
\r
4613 if (lgeCIx[(uint)code]) return 4;
\r
4617 internal uint TableIndexSize(MDTable tabIx) {
\r
4618 if (largeIx[(uint)tabIx]) return 4;
\r
4622 private void SetIndexSizes() {
\r
4623 for (int i=0; i < numMetaDataTables; i++) {
\r
4624 if (metaDataTables[i] != null) {
\r
4625 uint count = (uint)metaDataTables[i].Count;
\r
4626 if (count > maxSmlIxSize) {
\r
4627 largeIx[i] = true;
\r
4628 MDTable tabIx = (MDTable)i;
\r
4629 if (count > max5BitSmlIx) {
\r
4630 lgeCIx[(int)CIx.HasCustomAttr] = true;
\r
4632 if (count > max3BitSmlIx) {
\r
4633 if ((tabIx == MDTable.TypeRef) || (tabIx == MDTable.ModuleRef) || (tabIx == MDTable.Method) || (tabIx == MDTable.TypeSpec))
\r
4634 lgeCIx[(int)CIx.CustomAttributeType] = true;
\r
4635 if ((tabIx == MDTable.Method) || (tabIx == MDTable.MemberRef))
\r
4636 lgeCIx[(int)CIx.MemberRefParent] = true;
\r
4637 } else if (count > max2BitSmlIx) {
\r
4638 if ((tabIx == MDTable.Field) || (tabIx == MDTable.Param) || (tabIx == MDTable.Property))
\r
4639 lgeCIx[(int)CIx.HasConst] = true;
\r
4640 if ((tabIx == MDTable.TypeDef) || (tabIx == MDTable.TypeRef) || (tabIx == MDTable.TypeSpec))
\r
4641 lgeCIx[(int)CIx.TypeDefOrRef] = true;
\r
4642 if ((tabIx == MDTable.TypeDef) || (tabIx == MDTable.Method) || (tabIx == MDTable.Assembly))
\r
4643 lgeCIx[(int)CIx.HasDeclSecurity] = true;
\r
4644 if ((tabIx == MDTable.File) || (tabIx == MDTable.AssemblyRef) || (tabIx == MDTable.ExportedType))
\r
4645 lgeCIx[(int)CIx.Implementation] = true;
\r
4646 if ((tabIx == MDTable.Module) || (tabIx == MDTable.ModuleRef) || (tabIx == MDTable.AssemblyRef) || (tabIx == MDTable.TypeRef))
\r
4647 lgeCIx[(int)CIx.ResolutionScope] = true;
\r
4648 } else if (count > max1BitSmlIx) {
\r
4649 if ((tabIx == MDTable.Field) || (tabIx == MDTable.Param))
\r
4650 lgeCIx[(int)CIx.HasFieldMarshal] = true;
\r
4651 if ((tabIx == MDTable.Event) || (tabIx == MDTable.Property))
\r
4652 lgeCIx[(int)CIx.HasSemantics] = true;
\r
4653 if ((tabIx == MDTable.Method) || (tabIx == MDTable.MemberRef))
\r
4654 lgeCIx[(int)CIx.MethodDefOrRef] = true;
\r
4655 if ((tabIx == MDTable.Field) || (tabIx == MDTable.Method))
\r
4656 lgeCIx[(int)CIx.MemberForwarded] = true;
\r
4657 if ((tabIx == MDTable.TypeDef) || (tabIx == MDTable.Method))
\r
4658 lgeCIx[(int)CIx.TypeOrMethodDef] = true;
\r
4663 if (strings.LargeIx()) {
\r
4664 largeStrings = true;
\r
4665 heapSizes |= StringsHeapMask;
\r
4667 if (guid.LargeIx()) {
\r
4669 heapSizes |= GUIDHeapMask;
\r
4671 if (blob.LargeIx()) {
\r
4673 heapSizes |= BlobHeapMask;
\r
4675 largeUS = us.LargeIx();
\r
4678 private void SetStreamOffsets() {
\r
4679 uint sizeOfHeaders = StreamHeaderSize + (uint)tildeName.Length;
\r
4680 for (int i=1; i < numStreams; i++) {
\r
4681 sizeOfHeaders += streams[i].headerSize();
\r
4683 metaDataSize = MetaDataHeaderSize + sizeOfHeaders;
\r
4684 tildeStart = metaDataSize;
\r
4685 metaDataSize += tildeTide + tildePadding;
\r
4686 for (int i=1; i < numStreams; i++) {
\r
4687 streams[i].Start = metaDataSize;
\r
4688 metaDataSize += streams[i].Size();
\r
4689 streams[i].WriteDetails();
\r
4693 internal void CalcTildeStreamSize() {
\r
4694 //tilde.SetIndexSizes(strings.LargeIx(),us.LargeIx(),guid.LargeIx(),blob.LargeIx());
\r
4695 tildeTide = TildeHeaderSize;
\r
4696 tildeTide += 4 * numTables;
\r
4697 //Console.WriteLine("Tilde header + sizes = " + tildeTide);
\r
4698 for (int i=0; i < numMetaDataTables; i++) {
\r
4699 if (metaDataTables[i] != null) {
\r
4700 ArrayList table = metaDataTables[i];
\r
4701 // Console.WriteLine("Meta data table " + i + " at offset " + tildeTide);
\r
4702 tildeTide += (uint)table.Count * ((MetaDataElement)table[0]).Size(this);
\r
4703 // Console.WriteLine("Metadata table " + i + " has size " + table.Count);
\r
4704 // Console.WriteLine("tildeTide = " + tildeTide);
\r
4707 if ((tildeTide % 4) != 0) tildePadding = 4 - (tildeTide % 4);
\r
4708 //Console.WriteLine("tildePadding = " + tildePadding);
\r
4711 internal void WriteTildeStream(FileImage output) {
\r
4712 long startTilde = output.Seek(0,SeekOrigin.Current);
\r
4713 output.Write((uint)0); // Reserved
\r
4714 output.Write((byte)1); // MajorVersion
\r
4715 output.Write((byte)0); // MinorVersion
\r
4716 output.Write(heapSizes);
\r
4717 output.Write((byte)1); // Reserved
\r
4718 output.Write(valid);
\r
4719 output.Write(sorted);
\r
4720 for (int i=0; i < numMetaDataTables; i++) {
\r
4721 if (metaDataTables[i] != null) {
\r
4722 uint count = (uint)metaDataTables[i].Count;
\r
4723 output.Write(count);
\r
4726 long tabStart = output.Seek(0,SeekOrigin.Current);
\r
4727 // Console.WriteLine("Starting metaData tables at " + tabStart);
\r
4728 for (int i=0; i < numMetaDataTables; i++) {
\r
4729 if (metaDataTables[i] != null) {
\r
4730 // Console.WriteLine("Starting metaData table " + i + " at " + (output.Seek(0,SeekOrigin.Current) - startTilde));
\r
4731 ArrayList table = metaDataTables[i];
\r
4732 for (int j=0; j < table.Count; j++) {
\r
4733 ((MetaDataElement)table[j]).Write(output);
\r
4737 // Console.WriteLine("Writing padding at " + output.Seek(0,SeekOrigin.Current));
\r
4738 for (int i=0; i < tildePadding; i++) output.Write((byte)0);
\r
4741 private void BuildTable(ArrayList table) {
\r
4742 if (table == null) return;
\r
4743 for (int j=0; j < table.Count; j++) {
\r
4744 ((MetaDataElement)table[j]).BuildTables(this);
\r
4748 internal void BuildMetaData(uint codeStartOffset) {
\r
4749 codeStart = codeStartOffset;
\r
4750 BuildTable(metaDataTables[(int)MDTable.TypeDef]);
\r
4751 BuildTable(metaDataTables[(int)MDTable.MemberRef]);
\r
4752 BuildTable(metaDataTables[(int)MDTable.GenericParam]);
\r
4753 BuildTable(metaDataTables[(int)MDTable.MethodSpec]);
\r
4754 BuildTable(metaDataTables[(int)MDTable.GenericParamConstraint]);
\r
4755 BuildTable(metaDataTables[(int)MDTable.CustomAttribute]);
\r
4756 /* for (int i=0; i < metaDataTables.Length; i++) {
\r
4757 ArrayList table = metaDataTables[i];
\r
4758 if (table != null) {
\r
4759 for (int j=0; j < table.Count; j++) {
\r
4760 ((MetaDataElement)table[j]).BuildTables(this);
\r
4766 for (int i=1; i < numStreams; i++) {
\r
4767 streams[i].EndStream();
\r
4769 CalcTildeStreamSize();
\r
4770 SetStreamOffsets();
\r
4771 byteCodePadding = NumToAlign(codeSize,4);
\r
4772 if (entryPoint != null) file.SetEntryPoint(entryPoint.Token());
\r
4775 internal void WriteByteCodes(FileImage output) {
\r
4776 for (int i=0; i < byteCodes.Count; i++) {
\r
4777 ((CILInstructions)byteCodes[i]).Write(output);
\r
4779 for (int i=0; i < byteCodePadding; i++) {
\r
4780 output.Write((byte)0);
\r
4784 internal void WriteMetaData(FileImage output) {
\r
4785 this.output = output;
\r
4786 mdStart = output.Seek(0,SeekOrigin.Current);
\r
4787 // Console.WriteLine("Writing metaData at " + Hex.Long(mdStart));
\r
4788 output.Write(MetaDataSignature);
\r
4789 output.Write((short)1); // Major Version
\r
4790 output.Write((short)1); // Minor Version ECMA = 0, PEFiles = 1
\r
4791 output.Write(0); // Reserved
\r
4792 output.Write(version.Length);
\r
4793 output.Write(version.ToCharArray()); // version string is already zero padded
\r
4794 output.Write((short)0);
\r
4795 output.Write((ushort)numStreams);
\r
4796 // write tilde header
\r
4797 output.Write(tildeStart);
\r
4798 output.Write(tildeTide + tildePadding);
\r
4799 output.Write(tildeName);
\r
4800 for (int i=1; i < numStreams; i++) streams[i].WriteHeader(output);
\r
4801 // Console.WriteLine("Writing tilde stream at " + output.Seek(0,SeekOrigin.Current) + " = " + tildeStart);
\r
4802 WriteTildeStream(output);
\r
4803 for (int i=1; i < numStreams; i++) streams[i].Write(output);
\r
4804 // Console.WriteLine("Finished Writing metaData at " + output.Seek(0,SeekOrigin.Current));
\r
4807 internal bool LargeStringsIndex() { return strings.LargeIx(); }
\r
4808 internal bool LargeGUIDIndex() { return guid.LargeIx(); }
\r
4809 internal bool LargeUSIndex() { return us.LargeIx(); }
\r
4810 internal bool LargeBlobIndex() { return blob.LargeIx(); }
\r
4812 internal bool LargeIx(MDTable tabIx) { return largeIx[(uint)tabIx]; }
\r
4815 private uint NumToAlign(uint val, uint alignVal) {
\r
4816 if ((val % alignVal) == 0) return 0;
\r
4817 return alignVal - (val % alignVal);
\r
4820 internal void WriteCodedIndex(CIx code, MetaDataElement elem, FileImage output) {
\r
4822 if (elem != null) {
\r
4823 ix = (elem.Row << CIxShiftMap[(uint)code]) | elem.GetCodedIx(code);
\r
4824 // Console.WriteLine("coded index = " + ix + " row = " + elem.Row);
\r
4826 // Console.WriteLine("elem for coded index is null");
\r
4828 if (lgeCIx[(uint)code])
\r
4831 output.Write((ushort)ix);
\r
4835 /**************************************************************************/
\r
4837 /// Base class for all Meta Data table elements
\r
4840 public abstract class MetaDataElement
\r
4843 protected ArrayList customAttributes;
\r
4844 private uint row = 0;
\r
4845 protected bool done = false;
\r
4846 protected MDTable tabIx;
\r
4848 internal MetaDataElement() { }
\r
4855 if (row == 0) row = value;
\r
4859 internal virtual uint GetCodedIx(CIx code) { return 0; }
\r
4862 /// Add a custom attribute to this item
\r
4864 /// <param name="ctorMeth">the constructor method for this attribute</param>
\r
4865 /// <param name="val">the byte value of the parameters</param>
\r
4866 public void AddCustomAttribute(Method ctorMeth, byte[] val) {
\r
4867 if (customAttributes == null) {
\r
4868 customAttributes = new ArrayList();
\r
4870 customAttributes.Add(new CustomAttribute(this,ctorMeth,val));
\r
4874 /// Add a custom attribute to this item
\r
4876 /// <param name="ctorMeth">the constructor method for this attribute</param>
\r
4877 /// <param name="val">the constant values of the parameters</param>
\r
4878 public void AddCustomAttribute(Method ctorMeth, Constant[] cVals) {
\r
4879 if (customAttributes == null) {
\r
4880 customAttributes = new ArrayList();
\r
4882 // customAttributes.Add(new CustomAttribute(this,ctorMeth,cVals));
\r
4885 internal void DoCustomAttributes(MetaData md) {
\r
4886 if (customAttributes != null) {
\r
4887 for (int i=0; i < customAttributes.Count; i++) {
\r
4888 CustomAttribute ca = (CustomAttribute)customAttributes[i];
\r
4889 ca.BuildTables(md);
\r
4894 internal uint Token() {
\r
4895 return (((uint)tabIx << 24) | row);
\r
4898 internal virtual void BuildTables(MetaData md) {
\r
4902 internal virtual uint Size(MetaData md) {
\r
4906 internal virtual void Write(FileImage output) { }
\r
4909 /**************************************************************************/
\r
4911 /// Stream in the Meta Data (#Strings, #US, #Blob and #GUID)
\r
4914 internal class MetaDataStream : BinaryWriter
\r
4916 private static readonly uint StreamHeaderSize = 8;
\r
4917 private static uint maxSmlIxSize = 0xFFFF;
\r
4919 private uint start = 0;
\r
4920 uint size = 0, tide = 1;
\r
4921 bool largeIx = false;
\r
4922 uint sizeOfHeader;
\r
4924 Hashtable htable = new Hashtable();
4925 Hashtable btable = new Hashtable ();
4927 internal MetaDataStream(char[] name, bool addInitByte) : base(new MemoryStream()) {
\r
4928 if (addInitByte) { Write((byte)0); size = 1; }
\r
4930 sizeOfHeader = StreamHeaderSize + (uint)name.Length;
\r
4933 internal MetaDataStream(char[] name, System.Text.Encoding enc, bool addInitByte) : base(new MemoryStream(),enc) {
\r
4934 if (addInitByte) { Write((byte)0); size = 1; }
\r
4936 sizeOfHeader = StreamHeaderSize + (uint)name.Length;
\r
4939 public uint Start {
\r
4948 internal uint headerSize() {
\r
4949 // Console.WriteLine(name + " stream has headersize of " + sizeOfHeader);
\r
4950 return sizeOfHeader;
\r
4953 internal void SetSize(uint siz) {
\r
4957 internal uint Size() {
\r
4961 internal bool LargeIx() {
\r
4965 internal void WriteDetails() {
\r
4966 // Console.WriteLine(name + " - size = " + size);
\r
4969 internal uint Add(string str, bool prependSize) {
\r
4970 Object val = htable[str];
\r
4972 if (val == null) {
\r
4974 htable[str] = index;
\r
4975 char[] arr = str.ToCharArray();
\r
4976 if (prependSize) CompressNum((uint)arr.Length*2+1);
\r
4979 size = (uint)Seek(0,SeekOrigin.Current);
\r
4981 index = (uint)val;
\r
4985 internal uint Add (byte[] str, bool prependSize) {
4986 Object val = btable [str];
4990 btable [str] = index;
4991 if (prependSize) CompressNum ((uint) str.Length);
4993 size = (uint) Seek (0, SeekOrigin.Current);
5001 internal uint Add(Guid guid, bool prependSize) {
\r
5002 byte [] b = guid.ToByteArray ();
5003 if (prependSize) CompressNum ((uint) b.Length);
5004 Write(guid.ToByteArray());
\r
5005 size =(uint)Seek(0,SeekOrigin.Current);
\r
5009 internal uint Add(byte[] blob) {
\r
5011 CompressNum((uint)blob.Length);
5013 size = (uint)Seek(0,SeekOrigin.Current);
\r
5017 internal uint Add(byte val, bool prependSize) {
\r
5019 if (prependSize) CompressNum (1);
5021 size = (uint)Seek(0,SeekOrigin.Current);
\r
5025 internal uint Add(sbyte val, bool prependSize) {
\r
5027 if (prependSize) CompressNum (1);
5029 size = (uint)Seek(0,SeekOrigin.Current);
\r
5033 internal uint Add(ushort val, bool prependSize) {
\r
5035 if (prependSize) CompressNum (2);
5037 size = (uint)Seek(0,SeekOrigin.Current);
\r
5041 internal uint Add(short val, bool prependSize) {
\r
5043 if (prependSize) CompressNum (2);
5045 size = (uint)Seek(0,SeekOrigin.Current);
\r
5049 internal uint Add(uint val, bool prependSize) {
\r
5051 if (prependSize) CompressNum (4);
5053 size = (uint)Seek(0,SeekOrigin.Current);
\r
5057 internal uint Add(int val, bool prependSize) {
\r
5059 if (prependSize) CompressNum (4);
5061 size = (uint)Seek(0,SeekOrigin.Current);
\r
5065 internal uint Add(ulong val, bool prependSize) {
\r
5067 if (prependSize) CompressNum (8);
5069 size = (uint)Seek(0,SeekOrigin.Current);
\r
5073 internal uint Add(long val, bool prependSize) {
\r
5075 if (prependSize) CompressNum (8);
5077 size = (uint)Seek(0,SeekOrigin.Current);
\r
5081 internal uint Add(float val, bool prependSize) {
\r
5083 if (prependSize) CompressNum (4);
5085 size = (uint)Seek(0,SeekOrigin.Current);
\r
5089 internal uint Add(double val, bool prependSize) {
\r
5091 if (prependSize) CompressNum (8);
5093 size = (uint)Seek(0,SeekOrigin.Current);
\r
5097 private void CompressNum(uint val) {
\r
5100 } else if (val < 0x3FFF) {
\r
5101 byte b1 = (byte)((val >> 8) | 0x80);
\r
5102 byte b2 = (byte)(val & FileImage.iByteMask[0]);
\r
5106 byte b1 = (byte)((val >> 24) | 0xC0);
\r
5107 byte b2 = (byte)((val & FileImage.iByteMask[2]) >> 16);
\r
5108 byte b3 = (byte)((val & FileImage.iByteMask[1]) >> 8);;
\r
5109 byte b4 = (byte)(val & FileImage.iByteMask[0]);
\r
5117 private void QuadAlign() {
\r
5118 if ((size % 4) != 0) {
\r
5119 uint pad = 4 - (size % 4);
\r
5121 for (int i=0; i < pad; i++) {
\r
5127 internal void EndStream() {
\r
5129 if (size > maxSmlIxSize) {
\r
5134 internal void WriteHeader(BinaryWriter output) {
\r
5135 output.Write(start);
\r
5136 output.Write(size);
\r
5137 output.Write(name);
\r
5140 internal virtual void Write(BinaryWriter output) {
\r
5141 // Console.WriteLine("Writing " + name + " stream at " + output.Seek(0,SeekOrigin.Current) + " = " + start);
\r
5142 MemoryStream str = (MemoryStream)BaseStream;
\r
5143 output.Write(str.ToArray());
\r
5147 /**************************************************************************/
\r
5149 /// Base class for Method Descriptors
\r
5152 public abstract class Method : Member
\r
5154 protected CallConv callConv = CallConv.Default;
\r
5155 protected Type retType;
\r
5157 internal Method(string methName, Type rType) : base(methName)
\r
5163 /// Add calling conventions to this method descriptor
\r
5165 /// <param name="cconv"></param>
\r
5166 public void AddCallConv(CallConv cconv) {
\r
5167 callConv |= cconv;
\r
5170 internal abstract void TypeSig(MemoryStream sig);
\r
5172 internal uint GetSigIx(MetaData md) {
\r
5173 MemoryStream sig = new MemoryStream();
\r
5175 return md.AddToBlobHeap(sig.ToArray());
\r
5178 internal Type GetRetType() {
\r
5183 /**************************************************************************/
\r
5185 /// Descriptor for a method defined in THIS assembly/module
\r
5189 public class MethodDef : Method
\r
5191 private static readonly ushort PInvokeImpl = 0x2000;
\r
5192 //private static readonly uint UnmanagedExport = 0x0008;
\r
5193 // private static readonly byte LocalSigByte = 0x7;
\r
5194 uint parIx = 0, textOffset = 0;
\r
5196 MetaData metaData;
\r
5197 CILInstructions code;
\r
5198 ArrayList securityActions = new ArrayList();
\r
5202 ushort methFlags = 0, implFlags = 0;
\r
5203 int maxStack = 0, numPars = 0;
\r
5204 bool entryPoint = false;
\r
5205 LocalSig localSig;
\r
5206 ArrayList varArgSigList;
\r
5207 ImplMap pinvokeImpl;
\r
5210 internal MethodDef(MetaData md, string name, Type retType, Param[] pars) : base(name,retType) {
\r
5213 if (parList != null) numPars = parList.Length;
\r
5214 tabIx = MDTable.Method;
\r
5217 internal MethodDef(MetaData md, MethAttr mAttrSet, ImplAttr iAttrSet, string name, Type retType, Param[] pars) : base(name,retType) {
\r
5220 if (parList != null) numPars = parList.Length;
\r
5221 // Console.WriteLine("Creating method " + name + " with " + numPars + " parameters");
\r
5222 methFlags = (ushort)mAttrSet;
\r
5223 implFlags = (ushort)iAttrSet;
\r
5224 tabIx = MDTable.Method;
\r
5227 internal Param[] GetPars() {
\r
5232 /// Add some attributes to this method descriptor
\r
5234 /// <param name="ma">the attributes to be added</param>
\r
5235 public void AddMethAttribute(MethAttr ma) {
\r
5236 methFlags |= (ushort)ma;
\r
5240 /// Add some implementation attributes to this method descriptor
\r
5242 /// <param name="ia">the attributes to be added</param>
\r
5243 public void AddImplAttribute(ImplAttr ia) {
\r
5244 implFlags |= (ushort)ia;
\r
5247 public void AddPInvokeInfo(ModuleRef scope, string methName,
\r
5248 PInvokeAttr callAttr) {
\r
5249 pinvokeImpl = new ImplMap((ushort)callAttr,this,methName,scope);
\r
5250 methFlags |= PInvokeImpl;
\r
5254 /// Add a named generic type parameter
\r
5256 public GenericParameter AddGenericParameter (short index, string name) {
\r
5257 GenericParameter gp = new GenericParameter (this, metaData, index, name);
5258 metaData.AddToTable (MDTable.GenericParam, gp);
\r
5263 /// Set the maximum stack height for this method
\r
5265 /// <param name="maxStack">the maximum height of the stack</param>
\r
5266 public void SetMaxStack(int maxStack) {
\r
5267 this.maxStack = maxStack;
\r
5271 /// Add local variables to this method
\r
5273 /// <param name="locals">the locals to be added</param>
\r
5274 /// <param name="initLocals">are locals initialised to default values</param>
\r
5275 public void AddLocals(Local[] locals, bool initLocals) {
\r
5276 this.locals = locals;
\r
5277 this.initLocals = initLocals;
\r
5281 /// Mark this method as having an entry point
\r
5283 public void DeclareEntryPoint() {
\r
5284 entryPoint = true;
\r
5288 /// Create a code buffer for this method to add the IL instructions to
\r
5290 /// <returns>a buffer for this method's IL instructions</returns>
\r
5291 public CILInstructions CreateCodeBuffer() {
\r
5292 code = new CILInstructions(metaData);
\r
5297 /// Make a method reference descriptor for this method to be used
\r
5298 /// as a callsite signature for this vararg method
\r
5300 /// <param name="optPars">the optional pars for the vararg method call</param>
\r
5301 /// <returns></returns>
\r
5302 public MethodRef MakeVarArgSignature(Type[] optPars) {
\r
5303 Type[] pars = new Type[numPars];
\r
5304 MethodRef varArgSig;
\r
5305 for (int i=0; i < numPars; i++) {
\r
5306 pars[i] = parList[i].GetParType();
\r
5308 varArgSig = new MethodRef(this,name,retType,pars,true,optPars);
\r
5310 if (varArgSigList == null)
\r
5311 varArgSigList = new ArrayList ();
\r
5312 varArgSigList.Add (varArgSig);
\r
5316 internal sealed override void TypeSig(MemoryStream sig) {
\r
5317 sig.WriteByte((byte)callConv);
\r
5318 MetaData.CompressNum((uint)numPars,sig);
\r
5319 retType.TypeSig(sig);
\r
5320 for (ushort i=0; i < numPars; i++) {
\r
5321 parList[i].seqNo = (ushort)(i+1);
\r
5322 parList[i].TypeSig(sig);
\r
5326 internal sealed override void BuildTables(MetaData md) {
\r
5328 if (pinvokeImpl != null) {
\r
5329 md.AddToTable(MDTable.ImplMap,pinvokeImpl);
\r
5330 pinvokeImpl.BuildTables(md);
\r
5332 if (entryPoint) md.SetEntryPoint(this);
\r
5333 uint locToken = 0;
\r
5334 if (locals != null) {
\r
5335 localSig = new LocalSig(locals);
\r
5336 md.AddToTable(MDTable.StandAloneSig,localSig);
\r
5337 localSig.BuildTables(md);
\r
5338 locToken = localSig.Token();
\r
5340 if (code != null) {
\r
5341 code.CheckCode(locToken,initLocals,maxStack);
\r
5342 textOffset = md.AddCode(code);
\r
5344 nameIx = md.AddToStringsHeap(name);
\r
5345 sigIx = GetSigIx(md);
\r
5346 parIx = md.TableIndex(MDTable.Param);
\r
5347 for (int i=0; i < numPars; i++) {
\r
5348 md.AddToTable(MDTable.Param,parList[i]);
\r
5349 parList[i].BuildTables(md);
\r
5351 if (varArgSigList != null) {
\r
5352 foreach (MethodRef varArgSig in varArgSigList) {
\r
5353 md.AddToTable(MDTable.MemberRef,varArgSig);
\r
5354 varArgSig.BuildTables(md);
\r
5357 DoCustomAttributes (md);
\r
5358 // Console.WriteLine("method has " + numPars + " parameters");
\r
5362 internal sealed override uint Size(MetaData md) {
\r
5363 return 8 + md.StringsIndexSize() + md.BlobIndexSize() + md.TableIndexSize(MDTable.Param);
\r
5366 internal sealed override void Write(FileImage output) {
\r
5367 if (ZeroRva ()) output.Write(0);
\r
5368 else output.WriteCodeRVA(textOffset);
\r
5369 output.Write(implFlags);
\r
5370 output.Write(methFlags);
\r
5371 output.StringsIndex(nameIx);
\r
5372 output.BlobIndex(sigIx);
\r
5373 output.WriteIndex(MDTable.Param,parIx);
\r
5376 internal bool ZeroRva () {
5377 return (((methFlags & (ushort)MethAttr.Abstract) != 0) ||
5378 ((implFlags & (ushort)ImplAttr.Runtime) != 0) ||
5379 ((implFlags & (ushort)ImplAttr.InternalCall) != 0) ||
5380 (pinvokeImpl != null)); // TODO: Not entirely true but works for now
5383 internal sealed override uint GetCodedIx(CIx code) {
\r
5385 case (CIx.HasCustomAttr) : return 0;
\r
5386 case (CIx.HasDeclSecurity) : return 1;
\r
5387 case (CIx.MemberRefParent) : return 3;
\r
5388 case (CIx.MethodDefOrRef) : return 0;
\r
5389 case (CIx.MemberForwarded) : return 1;
\r
5390 case (CIx.CustomAttributeType) : return 2;
\r
5391 case (CIx.TypeOrMethodDef) : return 1;
\r
5397 /**************************************************************************/
\r
5399 /// Descriptor for an overriding method (.override)
\r
5401 public class MethodImpl : MetaDataElement
\r
5404 Method header, body;
\r
5406 internal MethodImpl(ClassDef par, Method decl, Method bod) {
\r
5410 tabIx = MDTable.MethodImpl;
\r
5413 internal sealed override uint Size(MetaData md) {
\r
5414 return md.TableIndexSize(MDTable.TypeDef) + 2 * md.CodedIndexSize(CIx.MethodDefOrRef);
\r
5417 internal sealed override void Write(FileImage output) {
\r
5418 output.WriteIndex(MDTable.TypeDef,parent.Row);
\r
5419 output.WriteCodedIndex(CIx.MethodDefOrRef,body);
\r
5420 output.WriteCodedIndex(CIx.MethodDefOrRef,header);
\r
5424 /**************************************************************************/
\r
5426 /// Descriptor for a method defined in another assembly/module
\r
5428 public class MethodRef : Method
\r
5430 private static readonly byte Sentinel = 0x41;
\r
5431 Type[] parList, optParList;
\r
5432 MetaDataElement parent;
\r
5433 uint numPars = 0, numOptPars = 0;
\r
5435 internal MethodRef(MetaDataElement paren, string name, Type retType,
\r
5436 Type[] pars, bool varArgMeth, Type[] optPars) : base(name,retType) {
\r
5439 if (parList != null) numPars = (uint)parList.Length;
\r
5441 optParList = optPars;
\r
5442 if (optParList != null) numOptPars = (uint)optParList.Length;
\r
5443 callConv = CallConv.Vararg;
\r
5447 internal sealed override void TypeSig(MemoryStream sig) {
\r
5448 sig.WriteByte((byte)callConv);
\r
5449 MetaData.CompressNum(numPars+numOptPars,sig);
\r
5450 retType.TypeSig(sig);
\r
5451 for (int i=0; i < numPars; i++) {
\r
5452 parList[i].TypeSig(sig);
\r
5454 if (numOptPars > 0) {
\r
5455 sig.WriteByte(Sentinel);
\r
5456 for (int i=0; i < numOptPars; i++) {
\r
5457 optParList[i].TypeSig(sig);
\r
5462 internal sealed override void BuildTables(MetaData md) {
\r
5464 nameIx = md.AddToStringsHeap(name);
\r
5465 sigIx = GetSigIx(md);
\r
5469 internal sealed override uint Size(MetaData md) {
\r
5470 return md.CodedIndexSize(CIx.MemberRefParent) + md.StringsIndexSize() + md.BlobIndexSize();
\r
5473 internal sealed override void Write(FileImage output) {
\r
5474 output.WriteCodedIndex(CIx.MemberRefParent,parent);
\r
5475 output.StringsIndex(nameIx);
\r
5476 output.BlobIndex(sigIx);
\r
5479 internal sealed override uint GetCodedIx(CIx code) {
\r
5481 case (CIx.HasCustomAttr) : return 6;
\r
5482 case (CIx.MethodDefOrRef) : return 1;
\r
5483 case (CIx.CustomAttributeType) : return 3;
\r
5489 /**************************************************************************/
\r
5491 /// Descriptor for Property and Event methods
\r
5493 public class MethodSemantics : MetaDataElement {
\r
5495 Feature.MethodType type;
\r
5497 Feature eventOrProp;
\r
5499 internal MethodSemantics(Feature.MethodType mType, MethodDef method, Feature feature) {
\r
5502 eventOrProp = feature;
\r
5503 tabIx = MDTable.MethodSemantics;
\r
5506 internal sealed override uint Size(MetaData md) {
\r
5507 return 2 + md.TableIndexSize(MDTable.Method) + md.CodedIndexSize(CIx.HasSemantics);
\r
5510 internal sealed override void Write(FileImage output) {
\r
5511 output.Write((ushort)type);
\r
5512 output.WriteIndex(MDTable.Method,meth.Row);
\r
5513 output.WriteCodedIndex(CIx.HasSemantics,eventOrProp);
\r
5517 /**************************************************************************/
\r
5519 /// Descriptor for a FunctionPointer type
\r
5522 public class MethPtrType : Type
\r
5524 // MethPtrType == FNPTR
\r
5529 /// Create a new function pointer type
\r
5531 /// <param name="meth">the function to be referenced</param>
\r
5532 public MethPtrType(Method meth) : base(0x1B)
\r
5535 tabIx = MDTable.TypeSpec;
\r
5538 internal sealed override void TypeSig(MemoryStream str) {
\r
5539 str.WriteByte(typeIndex);
\r
5540 method.TypeSig(str);
\r
5543 internal sealed override void BuildTables(MetaData md) {
\r
5545 MemoryStream sig = new MemoryStream();
\r
5547 sigIx = md.AddToBlobHeap(sig.ToArray());
\r
5551 internal sealed override uint Size(MetaData md) {
\r
5552 return md.BlobIndexSize();
\r
5555 internal sealed override void Write(FileImage output) {
\r
5556 output.BlobIndex(sigIx);
\r
5559 internal sealed override uint GetCodedIx(CIx code) { return 0x1B; }
\r
5562 /**************************************************************************/
\r
5564 /// Descriptor for THIS module
\r
5566 public class Module : ResolutionScope
\r
5571 internal Module(string name, MetaData md) : base(name,md) {
\r
5572 mvid = Guid.NewGuid();
\r
5573 mvidIx = md.AddToGUIDHeap(mvid);
\r
5574 tabIx = MDTable.Module;
\r
5577 internal sealed override uint Size(MetaData md) {
\r
5578 return 2 + md.StringsIndexSize() + 3 * md.GUIDIndexSize();
\r
5581 internal sealed override void Write(FileImage output) {
\r
5582 output.Write((short)0);
\r
5583 output.StringsIndex(nameIx);
\r
5584 output.GUIDIndex(mvidIx);
\r
5585 output.GUIDIndex(0);
\r
5586 output.GUIDIndex(0);
\r
5589 internal sealed override uint GetCodedIx(CIx code) {
\r
5591 case (CIx.HasCustomAttr) : return 7;
\r
5592 case (CIx.ResolutionScope) : return 0;
\r
5597 /**************************************************************************/
\r
5599 /// Descriptor for another module in THIS assembly
\r
5601 public class ModuleRef : ResolutionScope, IExternRef
5604 internal ModuleRef(MetaData md, string name) : base(name,md) {
\r
5605 tabIx = MDTable.ModuleRef;
\r
5609 /// Add a class to this external module. This is a class declared in
\r
5610 /// another module of THIS assembly.
\r
5612 /// <param name="nsName">name space name</param>
\r
5613 /// <param name="name">class name</param>
\r
5614 /// <returns>a descriptor for this class in another module</returns>
\r
5615 public ClassRef AddClass(string nsName, string name) {
\r
5616 ClassRef aClass = new ClassRef(nsName,name,metaData);
\r
5617 metaData.AddToTable(MDTable.TypeRef,aClass);
\r
5618 aClass.SetParent(this);
\r
5623 /// Make a file descriptor to correspond to this module. The file
\r
5624 /// descriptor will have the same name as the module descriptor
\r
5626 /// <param name="hashBytes">the hash of the file</param>
\r
5627 /// <param name="hasMetaData">the file contains metadata</param>
\r
5628 /// <param name="entryPoint">the program entry point is in this file</param>
\r
5629 /// <returns>a descriptor for the file which contains this module</returns>
\r
5630 public FileRef MakeFile(byte[] hashBytes, bool hasMetaData, bool entryPoint) {
\r
5631 FileRef file = new FileRef(nameIx,hashBytes,hasMetaData,entryPoint,metaData);
\r
5632 metaData.AddToTable(MDTable.File,file);
\r
5637 /// Add a value class to this module. This is a class declared in
\r
5638 /// another module of THIS assembly.
\r
5640 /// <param name="nsName">name space name</param>
\r
5641 /// <param name="name">class name</param>
\r
5642 /// <returns></returns>
\r
5643 public ClassRef AddValueClass(string nsName, string name) {
\r
5644 ClassRef aClass = new ClassRef(nsName,name,metaData);
\r
5645 metaData.AddToTable(MDTable.TypeRef,aClass);
\r
5646 aClass.SetParent(this);
\r
5647 aClass.MakeValueClass();
\r
5652 /// Add a class which is declared public in this external module of
\r
5653 /// THIS assembly. This class will be exported from this assembly.
\r
5654 /// The ilasm syntax for this is .extern class
\r
5656 /// <param name="attrSet">attributes of the class to be exported</param>
\r
5657 /// <param name="nsName">name space name</param>
\r
5658 /// <param name="name">external class name</param>
\r
5659 /// <param name="declFile">the file where the class is declared</param>
\r
5660 /// <param name="isValueClass">is this class a value type?</param>
\r
5661 /// <returns>a descriptor for this external class</returns>
\r
5662 public ExternClassRef AddExternClass(TypeAttr attrSet, string nsName,
\r
5663 string name, FileRef declFile,
\r
5664 bool isValueClass) {
\r
5665 ExternClassRef cRef = new ExternClassRef(attrSet,nsName,name,declFile,metaData);
\r
5666 metaData.AddToTable(MDTable.TypeRef,cRef);
\r
5667 cRef.SetParent(this);
\r
5668 if (isValueClass) cRef.MakeValueClass();
\r
5673 /// Add a "global" method in another module
\r
5675 /// <param name="name">method name</param>
\r
5676 /// <param name="retType">return type</param>
\r
5677 /// <param name="pars">method parameter types</param>
\r
5678 /// <returns>a descriptor for this method in anther module</returns>
\r
5679 public MethodRef AddMethod(string name, Type retType, Type[] pars) {
\r
5680 MethodRef meth = new MethodRef(this,name,retType,pars,false,null);
\r
5681 metaData.AddToTable(MDTable.MemberRef,meth);
\r
5686 /// Add a vararg method to this class
\r
5688 /// <param name="name">method name</param>
\r
5689 /// <param name="retType">return type</param>
\r
5690 /// <param name="pars">parameter types</param>
\r
5691 /// <param name="optPars">optional param types for this vararg method</param>
\r
5692 /// <returns>a descriptor for this method</returns>
\r
5693 public MethodRef AddVarArgMethod(string name, Type retType,
\r
5694 Type[] pars, Type[] optPars) {
\r
5695 MethodRef meth = new MethodRef(this,name,retType,pars,true,optPars);
\r
5696 metaData.AddToTable(MDTable.MemberRef,meth);
\r
5701 /// Add a field in another module
\r
5703 /// <param name="name">field name</param>
\r
5704 /// <param name="fType">field type</param>
\r
5705 /// <returns>a descriptor for this field in another module</returns>
\r
5706 public FieldRef AddField(string name, Type fType) {
\r
5707 FieldRef field = new FieldRef(this,name,fType);
\r
5708 metaData.AddToTable(MDTable.MemberRef,field);
\r
5712 internal sealed override uint Size(MetaData md) {
\r
5713 return md.StringsIndexSize();
\r
5716 internal sealed override void Write(FileImage output) {
\r
5717 output.StringsIndex(nameIx);
\r
5720 internal sealed override uint GetCodedIx(CIx code) {
\r
5722 case (CIx.HasCustomAttr) : return 12;
\r
5723 case (CIx.MemberRefParent) : return 2;
\r
5724 case (CIx.ResolutionScope) : return 1;
\r
5730 /**************************************************************************/
\r
5732 /// Descriptors for native types used for marshalling
\r
5734 public class NativeType {
\r
5735 public static readonly NativeType Void = new NativeType(0x01);
\r
5736 public static readonly NativeType Boolean = new NativeType(0x02);
\r
5737 public static readonly NativeType Int8 = new NativeType(0x03);
\r
5738 public static readonly NativeType UInt8 = new NativeType(0x04);
\r
5739 public static readonly NativeType Int16 = new NativeType(0x05);
\r
5740 public static readonly NativeType UInt16 = new NativeType(0x06);
\r
5741 public static readonly NativeType Int32 = new NativeType(0x07);
\r
5742 public static readonly NativeType UInt32 = new NativeType(0x08);
\r
5743 public static readonly NativeType Int64 = new NativeType(0x09);
\r
5744 public static readonly NativeType UInt64 = new NativeType(0x0A);
\r
5745 public static readonly NativeType Float32 = new NativeType(0x0B);
\r
5746 public static readonly NativeType Float64 = new NativeType(0x0C);
\r
5747 public static readonly NativeType Currency = new NativeType(0x0F);
\r
5748 public static readonly NativeType BStr = new NativeType(0x13);
\r
5749 public static readonly NativeType LPStr = new NativeType(0x14);
\r
5750 public static readonly NativeType LPWStr = new NativeType(0x15);
\r
5751 public static readonly NativeType LPTStr = new NativeType(0x16);
\r
5752 public static readonly NativeType FixedSysString = new NativeType(0x17);
\r
5753 public static readonly NativeType IUnknown = new NativeType(0x19);
\r
5754 public static readonly NativeType IDispatch = new NativeType(0x1A);
\r
5755 public static readonly NativeType Struct = new NativeType(0x1B);
\r
5756 public static readonly NativeType Interface = new NativeType(0x1C);
\r
5757 public static readonly NativeType Int = new NativeType(0x1F);
\r
5758 public static readonly NativeType UInt = new NativeType(0x20);
\r
5759 public static readonly NativeType ByValStr = new NativeType(0x22);
\r
5760 public static readonly NativeType AnsiBStr = new NativeType(0x23);
\r
5761 public static readonly NativeType TBstr = new NativeType(0x24);
\r
5762 public static readonly NativeType VariantBool = new NativeType(0x25);
\r
5763 public static readonly NativeType FuncPtr = new NativeType(0x26);
\r
5764 public static readonly NativeType AsAny = new NativeType(0x28);
\r
5766 protected byte typeIndex;
\r
5768 internal NativeType(byte tyIx) { typeIndex = tyIx; }
\r
5770 internal byte GetTypeIndex() { return typeIndex; }
\r
5772 internal virtual byte[] ToBlob() {
\r
5773 byte[] bytes = new byte[1];
\r
5774 bytes[0] = GetTypeIndex();
\r
5780 public class NativeArray : NativeType
\r
5782 NativeType elemType;
\r
5783 uint len = 0, parNum = 0;
\r
5786 public NativeArray(NativeType elemType) : base(0x2A) {
\r
5787 this.elemType = elemType;
\r
5790 public NativeArray(NativeType elemType, int len) : base(0x2A) {
\r
5791 this.elemType = elemType;
\r
5795 public NativeArray(NativeType elemType, int numElem, int parNumForLen) : base(0x2A) {
\r
5796 this.elemType = elemType;
\r
5797 len = (uint)numElem;
\r
5798 parNum = (uint)parNumForLen;
\r
5801 internal override byte[] ToBlob() {
\r
5802 MemoryStream str = new MemoryStream();
\r
5803 str.WriteByte(GetTypeIndex());
\r
5804 if (elemType == null) str.WriteByte(0x50); // no info (MAX)
\r
5805 else str.WriteByte(elemType.GetTypeIndex());
\r
5806 MetaData.CompressNum(parNum,str);
\r
5808 MetaData.CompressNum(len,str);
\r
5809 return str.ToArray();
\r
5814 public class SafeArray : NativeType
\r
5816 SafeArrayType elemType;
\r
5818 public SafeArray(SafeArrayType elemType) : base(0x1D) {
\r
5819 this.elemType = elemType;
\r
5822 internal override byte[] ToBlob() {
\r
5823 byte[] bytes = new byte[2];
\r
5824 bytes[0] = GetTypeIndex();
\r
5825 bytes[1] = (byte)elemType;
\r
5831 public class FixedArray : NativeType
\r
5833 NativeType elemType;
\r
5836 public FixedArray(NativeType elemType, int numElems) : base(0x1E) {
\r
5837 this.elemType = elemType;
\r
5838 numElem = (uint)numElems;
\r
5841 internal override byte[] ToBlob() {
\r
5842 MemoryStream str = new MemoryStream();
\r
5843 str.WriteByte(GetTypeIndex());
\r
5844 MetaData.CompressNum(numElem,str);
\r
5845 if (elemType == null) str.WriteByte(0x50); // no info (MAX)
\r
5846 else str.WriteByte(elemType.GetTypeIndex());
\r
5847 return str.ToArray();
\r
5852 public class CustomMarshaller : NativeType
\r
5855 string marshallerName;
\r
5858 public CustomMarshaller(string typeNameOrGUID, string marshallerName,
\r
5859 string optCookie) : base(0x2C) {
\r
5860 typeName = typeNameOrGUID;
\r
5861 this.marshallerName = marshallerName;
\r
5862 cookie = optCookie;
\r
5865 internal override byte[] ToBlob() {
\r
5866 MemoryStream str = new MemoryStream();
\r
5867 BinaryWriter bw = new BinaryWriter(str,new UTF8Encoding());
\r
5868 bw.Write(GetTypeIndex());
\r
5869 bw.Write(typeName.ToCharArray());
\r
5870 bw.Write((byte)0);
\r
5871 bw.Write(marshallerName.ToCharArray());
\r
5872 bw.Write((byte)0);
\r
5873 if (cookie != null) bw.Write(cookie.ToCharArray());
\r
5874 bw.Write((byte)0);
\r
5876 return str.ToArray();
\r
5880 /**************************************************************************/
\r
5882 /// Descriptor for a parameter of a method defined in this assembly/module
\r
5884 public class Param : MetaDataElement
\r
5886 private static readonly ushort hasDefault = 0x1000;
\r
5887 private static readonly ushort hasFieldMarshal = 0x2000;
\r
5891 internal ushort seqNo = 0;
\r
5893 ConstantElem defaultVal;
\r
5895 FieldMarshal marshalInfo;
\r
5898 /// Create a new parameter for a method
\r
5900 /// <param name="mode">param mode (in, out, opt)</param>
\r
5901 /// <param name="parName">parameter name</param>
\r
5902 /// <param name="parType">parameter type</param>
\r
5903 public Param(ParamAttr mode, string parName, Type parType) {
\r
5906 parMode = (ushort)mode;
\r
5907 tabIx = MDTable.Param;
\r
5911 /// Add a default value to this parameter
\r
5913 /// <param name="c">the default value for the parameter</param>
\r
5914 public void AddDefaultValue(Constant cVal) {
\r
5915 defaultVal = new ConstantElem(this,cVal);
\r
5916 parMode |= hasDefault;
\r
5920 /// Add marshalling information about this parameter
\r
5922 public void AddMarshallInfo(NativeType marshallType) {
\r
5923 parMode |= hasFieldMarshal;
\r
5924 marshalInfo = new FieldMarshal(this,marshallType);
\r
5927 internal Type GetParType() { return pType; }
\r
5929 internal sealed override void BuildTables(MetaData md) {
\r
5931 nameIx = md.AddToStringsHeap(pName);
\r
5932 if (defaultVal != null) {
\r
5933 md.AddToTable(MDTable.Constant,defaultVal);
\r
5934 defaultVal.BuildTables(md);
\r
5936 if (marshalInfo != null) {
\r
5937 md.AddToTable(MDTable.FieldMarshal,marshalInfo);
\r
5938 marshalInfo.BuildTables(md);
\r
5943 internal void TypeSig(MemoryStream str) {
\r
5944 pType.TypeSig(str);
\r
5947 internal sealed override uint Size(MetaData md) {
\r
5948 return 4 + md.StringsIndexSize();
\r
5951 internal sealed override void Write(FileImage output) {
\r
5952 output.Write(parMode);
\r
5953 output.Write(seqNo);
\r
5954 output.StringsIndex(nameIx);
\r
5957 internal sealed override uint GetCodedIx(CIx code) {
\r
5959 case (CIx.HasCustomAttr) : return 4;
\r
5960 case (CIx.HasConst) : return 1;
\r
5961 case (CIx.HasFieldMarshal) : return 1;
\r
5967 /**************************************************************************/
\r
5969 /// Base class for the PEFile (starting point)
\r
5971 public class PEFile
\r
5973 private static readonly string mscorlibName = "mscorlib";
\r
5974 private Module thisMod;
\r
5975 private ClassDef moduleClass;
\r
5976 private ArrayList classRefList = new ArrayList();
\r
5977 private ArrayList classDefList = new ArrayList();
\r
5978 private Assembly thisAssembly;
\r
5979 private int corFlags = 1;
\r
5980 FileImage fileImage;
\r
5981 MetaData metaData;
\r
5984 /// Create a new PEFile. Each PEFile is a module.
\r
5986 /// <param name="name">module name, also used for the file name</param>
\r
5987 /// <param name="isDLL">create a .dll or .exe file</param>
\r
5988 /// <param name="hasAssembly">this file is an assembly and
\r
5989 /// will contain the assembly manifest. The assembly name is the
\r
5990 /// same as the module name</param>
\r
5991 public PEFile(string name, bool isDLL, bool hasAssembly) {
\r
5992 // Console.WriteLine(Hex.Byte(0x12));
\r
5993 // Console.WriteLine(Hex.Short(0x1234));
\r
5994 // Console.WriteLine(Hex.Int(0x12345678));
\r
5995 string fName = MakeFileName(null,name,isDLL);
\r
5996 fileImage = new FileImage(isDLL,fName);
\r
5997 InitPEFile(name, fName, hasAssembly);
\r
6001 /// Create a new PEFile. Each PEFile is a module.
\r
6003 /// <param name="name">module name, also used for the file name</param>
\r
6004 /// <param name="isDLL">create a .dll or .exe file</param>
\r
6005 /// <param name="hasAssembly">this file is an assembly and
\r
6006 /// will contain the assembly manifest. The assembly name is the
\r
6007 /// same as the module name</param>
\r
6008 /// <param name="outputDir">write the PEFile to this directory. If this
\r
6009 /// string is null then the output will be to the current directory</param>
\r
6010 public PEFile(string name, bool isDLL, bool hasAssembly, string outputDir) {
\r
6011 // Console.WriteLine(Hex.Byte(0x12));
\r
6012 // Console.WriteLine(Hex.Short(0x1234));
\r
6013 // Console.WriteLine(Hex.Int(0x12345678));
\r
6014 string fName = MakeFileName(outputDir,name,isDLL);
\r
6015 fileImage = new FileImage(isDLL,fName);
\r
6016 InitPEFile(name, fName, hasAssembly);
\r
6020 /// Create a new PEFile
\r
6022 /// <param name="name">module name</param>
\r
6023 /// <param name="isDLL">create a .dll or .exe</param>
\r
6024 /// <param name="hasAssembly">this PEfile is an assembly and
\r
6025 /// will contain the assemly manifest. The assembly name is the
\r
6026 /// same as the module name</param>
\r
6027 /// <param name="outStream">write the PEFile to this stream instead
\r
6028 /// of to a new file</param>
\r
6029 public PEFile(string name, bool isDLL, bool hasAssembly, Stream outStream) {
\r
6030 fileImage = new FileImage(isDLL,outStream);
\r
6031 InitPEFile(name, MakeFileName(null,name,isDLL), hasAssembly);
\r
6034 public PEFile(string name, string module_name, bool isDLL, bool hasAssembly, Stream outStream) {
\r
6035 fileImage = new FileImage(isDLL,outStream);
\r
6036 InitPEFile(name, (module_name == null ? MakeFileName(null,name,isDLL) : module_name), hasAssembly);
\r
6039 private void InitPEFile(string name, string fName, bool hasAssembly) {
\r
6040 metaData = fileImage.GetMetaData();
\r
6041 thisMod = new Module(fName,metaData);
\r
6042 if (hasAssembly) {
\r
6043 thisAssembly = new Assembly(name,metaData);
\r
6044 metaData.AddToTable(MDTable.Assembly,thisAssembly);
\r
6046 moduleClass = AddClass(TypeAttr.Private,"","<Module>");
\r
6047 moduleClass.SpecialNoSuper();
\r
6048 metaData.AddToTable(MDTable.Module,thisMod);
\r
6052 public ClassDef ModuleClass {
6053 get { return moduleClass; }
6057 /// Set the subsystem (.subsystem) (Default is Windows Console mode)
\r
6059 /// <param name="subS">subsystem value</param>
\r
6060 public void SetSubSystem(SubSystem subS) {
\r
6061 fileImage.subSys = subS;
\r
6065 /// Set the flags (.corflags)
\r
6067 /// <param name="flags">the flags value</param>
\r
6068 public void SetCorFlags(int flags) {
\r
6072 private string MakeFileName(string dirName, string name, bool isDLL) {
\r
6073 string result = "";
\r
6074 if ((dirName != null) && (dirName.CompareTo("") != 0)) {
\r
6076 if (!dirName.EndsWith("\\")) result += "\\";
\r
6080 // if (isDLL) result += ".dll"; else result += ".exe";
\r
6086 /// Add an external assembly to this PEFile (.assembly extern)
\r
6088 /// <param name="assemName">the external assembly name</param>
\r
6089 /// <returns>a descriptor for this external assembly</returns>
\r
6090 public AssemblyRef AddExternAssembly(string assemName) {
\r
6091 if (assemName.CompareTo(mscorlibName) == 0) return metaData.mscorlib;
\r
6092 AssemblyRef anAssem = new AssemblyRef(metaData,assemName);
\r
6093 metaData.AddToTable(MDTable.AssemblyRef,anAssem);
\r
6094 // Console.WriteLine("Adding assembly " + assemName);
\r
6099 /// Add an external module to this PEFile (.module extern)
\r
6101 /// <param name="name">the external module name</param>
\r
6102 /// <returns>a descriptor for this external module</returns>
\r
6103 public ModuleRef AddExternModule(string name) {
\r
6104 ModuleRef modRef = new ModuleRef(metaData,name);
\r
6105 metaData.AddToTable(MDTable.ModuleRef,modRef);
\r
6110 /// Add a "global" method to this module
\r
6112 /// <param name="name">method name</param>
\r
6113 /// <param name="retType">return type</param>
\r
6114 /// <param name="pars">method parameters</param>
\r
6115 /// <returns>a descriptor for this new "global" method</returns>
\r
6116 public MethodDef AddMethod(string name, Type retType, Param[] pars) {
\r
6117 return moduleClass.AddMethod(name,retType,pars);
\r
6121 /// Add a "global" method to this module
\r
6123 /// <param name="mAtts">method attributes</param>
\r
6124 /// <param name="iAtts">method implementation attributes</param>
\r
6125 /// <param name="name">method name</param>
\r
6126 /// <param name="retType">return type</param>
\r
6127 /// <param name="pars">method parameters</param>
\r
6128 /// <returns>a descriptor for this new "global" method</returns>
\r
6129 public MethodDef AddMethod(MethAttr mAtts, ImplAttr iAtts, string name, Type retType, Param[] pars) {
\r
6130 return moduleClass.AddMethod(mAtts,iAtts,name,retType,pars);
\r
6133 public MethodRef AddMethodToTypeSpec (Type item, string name, Type retType, Type[] pars) {
\r
6134 MethodRef meth = new MethodRef (item.GetTypeSpec (metaData), name, retType, pars, false, null);
\r
6135 metaData.AddToTable (MDTable.MemberRef,meth);
\r
6139 public MethodRef AddVarArgMethodToTypeSpec (Type item, string name, Type retType,
\r
6140 Type[] pars, Type[] optPars) {
\r
6141 MethodRef meth = new MethodRef(item.GetTypeSpec (metaData), name,retType,pars,true,optPars);
\r
6142 metaData.AddToTable(MDTable.MemberRef,meth);
\r
6146 public FieldRef AddFieldToTypeSpec (Type item, string name, Type fType) {
\r
6147 FieldRef field = new FieldRef (item.GetTypeSpec (metaData), name,fType);
\r
6148 metaData.AddToTable (MDTable.MemberRef,field);
\r
6152 public void AddMethodSpec (Method m, GenericMethodSig g_sig)
6154 MethodSpec ms = new MethodSpec (m, g_sig);
6155 metaData.AddToTable (MDTable.MethodSpec, ms);
6159 /// Add a "global" field to this module
\r
6161 /// <param name="name">field name</param>
\r
6162 /// <param name="fType">field type</param>
\r
6163 /// <returns>a descriptor for this new "global" field</returns>
\r
6164 public FieldDef AddField(string name, Type fType) {
\r
6165 return moduleClass.AddField(name,fType);
\r
6169 /// Add a "global" field to this module
\r
6171 /// <param name="attrSet">attributes of this field</param>
\r
6172 /// <param name="name">field name</param>
\r
6173 /// <param name="fType">field type</param>
\r
6174 /// <returns>a descriptor for this new "global" field</returns>
\r
6175 public FieldDef AddField(FieldAttr attrSet, string name, Type fType) {
\r
6176 return moduleClass.AddField(attrSet,name,fType);
\r
6180 /// Add a class to this module
\r
6182 /// <param name="attrSet">attributes of this class</param>
\r
6183 /// <param name="nsName">name space name</param>
\r
6184 /// <param name="name">class name</param>
\r
6185 /// <returns>a descriptor for this new class</returns>
\r
6186 public ClassDef AddClass(TypeAttr attrSet, string nsName, string name) {
\r
6187 ClassDef aClass = new ClassDef(attrSet,nsName,name,metaData);
\r
6188 metaData.AddToTable(MDTable.TypeDef,aClass);
\r
6193 /// Add a class which extends System.ValueType to this module
\r
6195 /// <param name="attrSet">attributes of this class</param>
\r
6196 /// <param name="nsName">name space name</param>
\r
6197 /// <param name="name">class name</param>
\r
6198 /// <returns>a descriptor for this new class</returns>
\r
6199 public ClassDef AddValueClass(TypeAttr attrSet, string nsName, string name) {
\r
6200 ClassDef aClass = new ClassDef(attrSet,nsName,name,metaData);
\r
6201 aClass.MakeValueClass();
\r
6202 metaData.AddToTable(MDTable.TypeDef,aClass);
\r
6207 /// Add a class to this module
\r
6209 /// <param name="attrSet">attributes of this class</param>
\r
6210 /// <param name="nsName">name space name</param>
\r
6211 /// <param name="name">class name</param>
\r
6212 /// <param name="superType">super type of this class (extends)</param>
\r
6213 /// <returns>a descriptor for this new class</returns>
\r
6214 public ClassDef AddClass(TypeAttr attrSet, string nsName, string name, Class superType) {
\r
6215 ClassDef aClass = new ClassDef(attrSet,nsName,name,metaData);
\r
6216 aClass.SetSuper(superType);
\r
6217 metaData.AddToTable(MDTable.TypeDef,aClass);
\r
6221 public FileRef AddFile(string fName, byte[] hashBytes, bool hasMetaData, bool entryPoint) {
\r
6222 FileRef file = new FileRef(fName,hashBytes,hasMetaData,entryPoint,metaData);
\r
6223 metaData.AddToTable(MDTable.File,file);
\r
6228 /// Add a manifest resource to this PEFile NOT YET IMPLEMENTED
\r
6230 /// <param name="mr"></param>
\r
6231 public void AddManifestResource(ManifestResource mr) {
\r
6232 metaData.AddToTable(MDTable.ManifestResource,mr);
\r
6233 //mr.FixName(metaData);
\r
6237 /// Write out the PEFile (the "bake" function)
\r
6239 public void WritePEFile() { /* the "bake" function */
\r
6240 fileImage.MakeFile();
\r
6244 /// Get the descriptor of this module
\r
6246 /// <returns>the descriptor for this module</returns>
\r
6247 public Module GetThisModule() {
\r
6252 /// Get the descriptor for this assembly. The PEFile must have been
\r
6253 /// created with hasAssembly = true
\r
6255 /// <returns>the descriptor for this assembly</returns>
\r
6256 public Assembly GetThisAssembly() {
\r
6257 return thisAssembly;
\r
6262 /**************************************************************************/
\r
6264 /// Descriptor for the Primitive types defined in IL
\r
6266 public class PrimitiveType : Type
\r
6268 private string name;
\r
6269 private int systemTypeIndex;
\r
6270 public static int NumSystemTypes = 18;
\r
6272 public static readonly PrimitiveType Void = new PrimitiveType(0x01,"Void",0);
\r
6273 public static readonly PrimitiveType Boolean = new PrimitiveType(0x02,"Boolean",1);
\r
6274 public static readonly PrimitiveType Char = new PrimitiveType(0x03,"Char",2);
\r
6275 public static readonly PrimitiveType Int8 = new PrimitiveType(0x04,"SByte",3);
\r
6276 public static readonly PrimitiveType UInt8 = new PrimitiveType(0x05,"Byte",4);
\r
6277 public static readonly PrimitiveType Int16 = new PrimitiveType(0x06,"Int16",5);
\r
6278 public static readonly PrimitiveType UInt16 = new PrimitiveType(0x07,"UInt16",6);
\r
6279 public static readonly PrimitiveType Int32 = new PrimitiveType(0x08,"Int32",7);
\r
6280 public static readonly PrimitiveType UInt32 = new PrimitiveType(0x09,"UInt32",8);
\r
6281 public static readonly PrimitiveType Int64 = new PrimitiveType(0x0A,"Int64",9);
\r
6282 public static readonly PrimitiveType UInt64 = new PrimitiveType(0x0B,"UInt64",10);
\r
6283 public static readonly PrimitiveType Float32 = new PrimitiveType(0x0C,"Single",11);
\r
6284 public static readonly PrimitiveType Float64 = new PrimitiveType(0x0D,"Double",12);
\r
6285 public static readonly PrimitiveType String = new PrimitiveType(0x0E,"String",13);
\r
6286 internal static readonly PrimitiveType Class = new PrimitiveType(0x12);
\r
6287 public static readonly PrimitiveType TypedRef = new PrimitiveType(0x16,"TypedReference",14);
\r
6288 public static readonly PrimitiveType IntPtr = new PrimitiveType(0x18,"IntPtr",15);
\r
6289 public static readonly PrimitiveType UIntPtr = new PrimitiveType(0x19,"UIntPtr",16);
\r
6290 public static readonly PrimitiveType Object = new PrimitiveType(0x1C,"Object",17);
\r
6291 internal static readonly PrimitiveType ClassType = new PrimitiveType(0x50);
\r
6292 public static readonly PrimitiveType NativeInt = IntPtr;
\r
6293 public static readonly PrimitiveType NativeUInt = UIntPtr;
\r
6295 internal PrimitiveType(byte typeIx) : base(typeIx) { }
\r
6297 internal PrimitiveType(byte typeIx, string name, int STIx) : base(typeIx) {
\r
6299 this.systemTypeIndex = STIx;
\r
6302 internal string GetName() { return name; }
\r
6304 internal int GetSystemTypeIx() { return systemTypeIndex; }
\r
6306 internal sealed override void TypeSig(MemoryStream str) {
\r
6307 str.WriteByte(typeIndex);
\r
6310 internal override MetaDataElement GetTypeSpec(MetaData md) {
\r
6311 TypeSpec tS = md.GetPrimitiveTypeSpec(systemTypeIndex);
\r
6313 tS = new TypeSpec(this,md);
\r
6314 md.SetPrimitiveTypeSpec(systemTypeIndex,tS);
\r
6315 md.AddToTable(MDTable.TypeSpec,tS);
\r
6322 /**************************************************************************/
\r
6324 /// Descriptor for the Property of a class
\r
6326 public class Property : Feature
\r
6328 private static readonly byte PropertyTag = 0x8;
\r
6329 MethodDef getterMeth;
\r
6330 ConstantElem constVal;
\r
6331 uint typeBlobIx = 0;
\r
6336 internal Property(string name, Type retType, Type[] pars, ClassDef parent) : base(name, parent) {
\r
6337 returnType = retType;
\r
6339 if (pars != null) numPars = (uint)pars.Length;
\r
6340 tabIx = MDTable.Property;
\r
6344 /// Add a set method to this property
\r
6346 /// <param name="setter">the set method</param>
\r
6347 public void AddSetter(MethodDef setter) {
\r
6348 AddMethod(setter,MethodType.Setter);
\r
6352 /// Add a get method to this property
\r
6354 /// <param name="getter">the get method</param>
\r
6355 public void AddGetter(MethodDef getter) {
\r
6356 AddMethod(getter,MethodType.Getter);
\r
6357 getterMeth = getter;
\r
6361 /// Add another method to this property
\r
6363 /// <param name="other">the method</param>
\r
6364 public void AddOther(MethodDef other) {
\r
6365 AddMethod(other,MethodType.Other);
\r
6369 /// Add an initial value for this property
\r
6371 /// <param name="constVal">the initial value for this property</param>
\r
6372 public void AddInitValue(Constant constVal) {
\r
6373 this.constVal = new ConstantElem(this,constVal);
\r
6376 internal sealed override void BuildTables(MetaData md) {
\r
6378 nameIx = md.AddToStringsHeap(name);
\r
6379 MemoryStream sig = new MemoryStream();
\r
6380 sig.WriteByte(PropertyTag);
\r
6381 MetaData.CompressNum(numPars,sig);
\r
6382 returnType.TypeSig(sig);
\r
6383 for (int i=0; i < numPars; i++) {
\r
6384 parList[i].TypeSig(sig);
\r
6386 typeBlobIx = md.AddToBlobHeap(sig.ToArray());
\r
6387 for (int i=0; i < tide; i++) {
\r
6388 md.AddToTable(MDTable.MethodSemantics,methods[i]);
\r
6390 if (constVal != null) {
\r
6391 md.AddToTable(MDTable.Constant,constVal);
\r
6392 constVal.BuildTables(md);
\r
6397 internal sealed override uint Size(MetaData md) {
\r
6398 return 2 + md.StringsIndexSize() + md.BlobIndexSize();
\r
6401 internal sealed override void Write(FileImage output) {
\r
6402 output.Write(flags);
\r
6403 output.StringsIndex(nameIx);
\r
6404 output.BlobIndex(typeBlobIx);
\r
6407 internal sealed override uint GetCodedIx(CIx code) {
\r
6409 case (CIx.HasCustomAttr) : return 9;
\r
6410 case (CIx.HasConst) : return 2;
\r
6411 case (CIx.HasSemantics) : return 1;
\r
6417 /**************************************************************************/
\r
6419 /// Descriptor for an pointer (type * or type &)
\r
6421 public abstract class PtrType : Type
\r
6425 internal PtrType(Type bType, byte typeIx) : base(typeIx)
\r
6428 tabIx = MDTable.TypeSpec;
\r
6431 internal sealed override void TypeSig(MemoryStream str) {
\r
6432 str.WriteByte(typeIndex);
\r
6433 baseType.TypeSig(str);
\r
6437 /**************************************************************************/
\r
6439 /// Descriptor for a managed pointer (type & or byref)
\r
6442 public class ManagedPointer : PtrType // <type> & (BYREF)
\r
6446 /// Create new managed pointer to baseType
\r
6448 /// <param name="bType">the base type of the pointer</param>
\r
6449 public ManagedPointer(Type baseType) : base(baseType,0x10) { }
\r
6452 /**************************************************************************/
\r
6454 /// Descriptor for an unmanaged pointer (type *)
\r
6456 public class UnmanagedPointer : PtrType // PTR
\r
6459 /// Create a new unmanaged pointer to baseType
\r
6461 /// <param name="baseType">the base type of the pointer</param>
\r
6462 public UnmanagedPointer(Type baseType) : base(baseType, 0x0F) { }
\r
6465 /**************************************************************************/
\r
6467 /// Base class for scopes (extended by Module, ModuleRef, Assembly, AssemblyRef)
\r
6469 public abstract class ResolutionScope : MetaDataElement
\r
6471 protected uint nameIx = 0;
\r
6472 protected MetaData metaData;
\r
6473 protected string name;
\r
6475 internal ResolutionScope(string name, MetaData md)
\r
6479 nameIx = md.AddToStringsHeap(name);
\r
6482 internal string GetName() { return name; }
\r
6485 /**************************************************************************/
\r
6487 /// Descriptor for a Section in a PEFile eg .text, .sdata
\r
6489 internal class Section {
\r
6490 private static readonly uint relocPageSize = 4096; // 4K pages for fixups
\r
6493 uint offset = 0, tide = 0, size = 0, rva = 0, relocTide = 0;
\r
6494 //uint relocOff = 0;
\r
6495 uint flags = 0, padding = 0;
\r
6498 internal Section(string sName, uint sFlags) {
6499 name = sName.ToCharArray();
\r
6503 internal uint Tide() { return tide; }
\r
6505 internal void IncTide(uint incVal) { tide += incVal; }
\r
6507 internal uint Padding() { return padding; }
\r
6509 internal uint Size() { return size; }
\r
6511 internal void SetSize(uint pad) {
\r
6513 size = tide + padding;
\r
6516 internal uint RVA() { return rva; }
\r
6518 internal void SetRVA(uint rva) { this.rva = rva; }
\r
6520 internal uint Offset() { return offset; }
\r
6522 internal void SetOffset(uint offs) { offset = offs; }
\r
6524 internal void DoBlock(BinaryWriter reloc, uint page, int start, int end) {
\r
6525 //Console.WriteLine("rva = " + rva + " page = " + page);
\r
6526 reloc.Write(rva + page);
\r
6527 reloc.Write((uint)(((end-start+1)*2) + 8));
\r
6528 for (int j=start; j < end; j++) {
\r
6529 //Console.WriteLine("reloc offset = " + relocs[j]);
\r
6530 reloc.Write((ushort)((0x3 << 12) | (relocs[j] - page)));
\r
6532 reloc.Write((ushort)0);
\r
6535 internal void DoRelocs(BinaryWriter reloc) {
\r
6536 if (relocTide > 0) {
\r
6537 //relocOff = (uint)reloc.Seek(0,SeekOrigin.Current);
\r
6538 uint block = (relocs[0]/relocPageSize + 1) * relocPageSize;
\r
6540 for (int i=1; i < relocTide; i++) {
\r
6541 if (relocs[i] >= block) {
\r
6542 DoBlock(reloc,block-relocPageSize,start,i);
\r
6544 block = (relocs[i]/relocPageSize + 1) * relocPageSize;
\r
6547 DoBlock(reloc,block-relocPageSize,start,(int)relocTide);
\r
6551 internal void AddReloc(uint offs) {
\r
6553 if (relocs == null) {
\r
6554 relocs = new uint[5];
\r
6556 if (relocTide >= relocs.Length) {
\r
6557 uint[] tmp = relocs;
\r
6558 relocs = new uint[tmp.Length + 5];
\r
6559 for (int i=0; i < relocTide; i++) {
\r
6560 relocs[i] = tmp[i];
\r
6563 while ((pos < relocTide) && (relocs[pos] < offs)) pos++;
\r
6564 for (int i=pos; i < relocTide; i++) {
\r
6565 relocs[i+1] = relocs[i];
\r
6568 relocs[pos] = offs;
\r
6572 internal void WriteHeader(BinaryWriter output, uint relocRVA) {
\r
6573 output.Write(name);
\r
6574 output.Write(tide);
\r
6575 output.Write(rva);
\r
6576 output.Write(size);
\r
6577 output.Write(offset);
\r
6579 //output.Write(relocRVA + relocOff);
\r
6582 //output.Write((ushort)relocTide);
\r
6583 //output.Write((ushort)0);
\r
6584 output.Write(flags);
\r
6588 /**************************************************************************/
\r
6589 public abstract class Signature : MetaDataElement
\r
6591 protected uint sigIx;
\r
6593 internal Signature() {
\r
6594 tabIx = MDTable.StandAloneSig;
\r
6597 internal sealed override uint Size(MetaData md) {
\r
6598 return md.BlobIndexSize();
\r
6601 internal sealed override void Write(FileImage output) {
\r
6602 output.BlobIndex(sigIx);
\r
6605 internal sealed override uint GetCodedIx(CIx code) { return (uint)tabIx; }
\r
6608 /**************************************************************************/
\r
6610 /// Descriptor for a class defined in System (mscorlib)
\r
6612 internal class SystemClass : ClassRef
\r
6614 PrimitiveType elemType;
\r
6616 internal SystemClass(PrimitiveType eType, AssemblyRef paren, MetaData md)
\r
6617 : base("System",eType.GetName(),md) {
\r
6622 internal override sealed MetaDataElement GetTypeSpec(MetaData md) {
\r
6623 if (typeSpec == null) typeSpec = (TypeSpec)elemType.GetTypeSpec(md);
\r
6628 internal sealed override void TypeSig(MemoryStream str) {
\r
6629 str.WriteByte(elemType.GetTypeIndex());
\r
6633 /**************************************************************************/
\r
6635 /// Base class for all IL types
\r
6637 public abstract class Type : MetaDataElement {
\r
6638 protected byte typeIndex;
\r
6639 protected TypeSpec typeSpec;
\r
6641 internal Type(byte tyIx) { typeIndex = tyIx; }
\r
6643 internal byte GetTypeIndex() { return typeIndex; }
\r
6645 internal virtual MetaDataElement GetTypeSpec(MetaData md) {
\r
6646 if (typeSpec == null) {
\r
6647 typeSpec = new TypeSpec(this,md);
\r
6648 md.AddToTable(MDTable.TypeSpec,typeSpec);
\r
6653 internal virtual void TypeSig(MemoryStream str) {
\r
6654 throw(new TypeSignatureException(this.GetType().AssemblyQualifiedName +
\r
6655 " doesn't have a type signature!!"));
\r
6660 /**************************************************************************/
\r
6662 public class TypeSpec : MetaDataElement {
\r
6665 internal TypeSpec(Type aType, MetaData md) {
\r
6666 MemoryStream sig = new MemoryStream();
\r
6667 aType.TypeSig(sig);
\r
6668 sigIx = md.AddToBlobHeap(sig.ToArray());
\r
6669 tabIx = MDTable.TypeSpec;
\r
6672 internal sealed override uint GetCodedIx(CIx code) {
\r
6674 case (CIx.TypeDefOrRef) : return 2;
\r
6675 case (CIx.HasCustomAttr) : return 13;
\r
6676 case (CIx.MemberRefParent) : return 4;
\r
6681 internal override uint Size(MetaData md) {
\r
6682 return md.BlobIndexSize();
\r
6685 internal sealed override void Write(FileImage output) {
\r
6686 //Console.WriteLine("Writing the blob index for a TypeSpec");
\r
6687 output.BlobIndex(sigIx);
\r