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 /// A reference to an external assembly (.assembly extern)
\r
387 public class AssemblyRef : ResolutionScope
\r
389 private ushort major, minor, build, revision;
\r
390 uint flags, keyIx, hashIx, cultIx;
\r
391 bool hasVersion = false, isKeyToken = false;
\r
395 internal AssemblyRef(MetaData md, string name) : base(name,md) {
\r
396 tabIx = MDTable.AssemblyRef;
\r
400 /// Add version information about this external assembly
\r
402 /// <param name="majVer">Major Version</param>
\r
403 /// <param name="minVer">Minor Version</param>
\r
404 /// <param name="bldNo">Build Number</param>
\r
405 /// <param name="revNo">Revision Number</param>
\r
406 public void AddVersionInfo(int majVer, int minVer, int bldNo, int revNo) {
\r
407 major = (ushort)majVer;
\r
408 minor = (ushort)minVer;
\r
409 build = (ushort)bldNo;
\r
410 revision = (ushort)revNo;
\r
415 /// Add the hash value for this external assembly
\r
417 /// <param name="hash">bytes of the hash value</param>
\r
418 public void AddHash(byte[] hash) {
\r
419 hashIx = metaData.AddToBlobHeap(hash);
\r
423 /// Set the culture for this external assembly
\r
425 /// <param name="cult">the culture string</param>
\r
426 public void AddCulture(string cult) {
\r
427 cultIx = metaData.AddToStringsHeap(cult);
\r
432 /// Add the full public key for this external assembly
\r
434 /// <param name="key">bytes of the public key</param>
\r
435 public void AddKey(byte[] key) {
\r
436 flags |= 0x0001; // full public key
\r
438 keyIx = metaData.AddToBlobHeap(key);
\r
442 /// Add the public key token (low 8 bytes of the public key)
\r
444 /// <param name="key">low 8 bytes of public key</param>
\r
445 public void AddKeyToken(byte[] key) {
\r
446 keyIx = metaData.AddToBlobHeap(key);
\r
452 /// Add a class to this external assembly
\r
454 /// <param name="nsName">name space name</param>
\r
455 /// <param name="name">class name</param>
\r
456 /// <returns></returns>
\r
457 public virtual ClassRef AddClass(string nsName, string name) {
\r
458 ClassRef aClass = new ClassRef(nsName,name,metaData);
\r
459 metaData.AddToTable(MDTable.TypeRef,aClass);
\r
460 aClass.SetParent(this);
\r
465 /// Add a value class to this external assembly
\r
467 /// <param name="nsName">name space name</param>
\r
468 /// <param name="name">class name</param>
\r
469 /// <returns></returns>
\r
470 public virtual ClassRef AddValueClass(string nsName, string name) {
\r
471 ClassRef aClass = new ClassRef(nsName,name,metaData);
\r
472 metaData.AddToTable(MDTable.TypeRef,aClass);
\r
473 aClass.SetParent(this);
\r
474 aClass.MakeValueClass();
\r
478 internal string TypeName() {
\r
479 string result = name;
\r
481 result = result + ", Version=" + major + "." + minor + "." +
\r
482 build + "." + revision;
\r
483 if (keyBytes != null) {
\r
484 string tokenStr = "=";
\r
485 if (isKeyToken) tokenStr = "Token=";
\r
486 result = result + ", PublicKey" + tokenStr;
\r
487 for (int i=0; i < keyBytes.Length; i++) {
\r
488 result = result + Hex.Byte(keyBytes[i]);
\r
491 if (culture != null)
\r
492 result = result + ", Culture=" + culture;
\r
496 internal sealed override uint Size(MetaData md) {
\r
497 return 12 + 2 * md.StringsIndexSize() + 2 * md.BlobIndexSize();
\r
500 internal sealed override void Write(FileImage output) {
\r
501 output.Write(major);
\r
502 output.Write(minor);
\r
503 output.Write(build);
\r
504 output.Write(revision);
\r
505 output.Write(flags);
\r
506 output.BlobIndex(keyIx);
\r
507 output.StringsIndex(nameIx);
\r
508 output.StringsIndex(cultIx);
\r
509 output.BlobIndex(hashIx);
\r
512 internal sealed override uint GetCodedIx(CIx code) {
\r
514 case (CIx.ResolutionScope) : return 2;
\r
515 case (CIx.HasCustomAttr) : return 15;
\r
516 case (CIx.Implementation) : return 1;
\r
522 /**************************************************************************/
\r
525 /// flags for the assembly (.corflags)
\r
527 public enum CorFlags {CF_IL_ONLY, CF_32_BITREQUIRED, CF_STRONGNAMESIGNED,
\r
531 /// subsystem for the assembly (.subsystem)
\r
533 public enum SubSystem { Native = 1, Windows_GUI = 2,
\r
534 Windows_CUI = 3, OS2_CUI = 5, POSIX_CUI = 7, Native_Windows = 8,
\r
535 Windows_CE_GUI = 9}
\r
538 /// Hash algorithms for the assembly
\r
540 public enum HashAlgorithm { None, SHA1 }
\r
543 /// Attributes for this assembly
\r
545 public enum AssemAttr { EnableJITCompileTracking = 0x8000,
\r
546 DisableJITCompileOptimizer = 0x4000}
\r
549 /// Method call conventions
\r
551 public enum CallConv { Default, Cdecl, Stdcall, Thiscall,
\r
552 Fastcall, Vararg, Instance = 0x20, Generic = 0x10, InstanceExplicit = 0x60 }
\r
555 /// Type custom modifier
\r
557 public enum CustomModifier { modreq = 0x1F, modopt };
\r
560 /// Attibutes for a class
\r
562 public enum TypeAttr {Private, Public, NestedPublic, NestedPrivate,
\r
563 NestedFamily, NestedAssembly, NestedFamAndAssem, NestedFamOrAssem,
\r
564 SequentialLayout, ExplicitLayout = 0x10, Interface = 0x20,
\r
565 Abstract = 0x80, PublicAbstract = 0x81, Sealed = 0x100,
\r
566 PublicSealed = 0x101, SpecialName = 0x400, RTSpecialName = 0x800,
\r
567 Import = 0x1000, Serializable = 0x2000, UnicodeClass = 0x10000,
\r
568 AutoClass = 0x20000, BeforeFieldInit = 0x100000 }
\r
571 /// Attributes for a field
\r
573 public enum FieldAttr {Default, Private, FamAndAssem, Assembly,
\r
574 Family, FamOrAssem, Public, Static = 0x10, PublicStatic = 0x16,
\r
575 Initonly = 0x20, Literal = 0x40, Notserialized = 0x80,
\r
576 SpecialName = 0x200, RTSpecialName = 0x400 }
\r
579 /// Attributes for a method
\r
581 public enum MethAttr { Default, Private, FamAndAssem, Assembly,
\r
582 Family, FamOrAssem, Public, Static = 0x0010, PublicStatic = 0x16,
\r
583 Final = 0x0020, PublicStaticFinal = 0x36, Virtual = 0x0040,
\r
584 PrivateVirtual, PublicVirtual = 0x0046, HideBySig = 0x0080,
\r
585 NewSlot = 0x0100, Abstract = 0x0400, SpecialName = 0x0800,
\r
586 RTSpecialName = 0x1000, SpecialRTSpecialName = 0x1800,
\r
587 RequireSecObject = 0x8000}
\r
590 /// Attributes for .pinvokeimpl method declarations
\r
592 public enum PInvokeAttr { nomangle = 1, ansi = 2, unicode = 4, autochar = 6,
593 lasterr = 0x0040, winapi = 0x0100, cdecl = 0x0200,
594 stdcall = 0x0300, thiscall = 0x0400, fastcall = 0x0500 }
\r
597 /// Implementation attributes for a method
\r
599 public enum ImplAttr { IL, Native, Runtime = 0x03, Unmanaged = 0x04,
\r
600 ForwardRef = 0x10, PreserveSig = 0x0080, InternalCall = 0x1000,
\r
601 Synchronised = 0x0020, Synchronized = 0x0020, NoInLining = 0x0008, Optil = 0x0002}
\r
604 /// Modes for a parameter
\r
606 public enum ParamAttr { Default, In, Out, Opt = 4 }
\r
609 /// CIL instructions
\r
611 public enum Op { nop, breakOp, ldarg_0, ldarg_1, ldarg_2, ldarg_3,
\r
612 ldloc_0, ldloc_1, ldloc_2, ldloc_3, stloc_0, stloc_1, stloc_2, stloc_3,
\r
613 ldnull = 0x14, ldc_i4_m1, ldc_i4_0, ldc_i4_1, ldc_i4_2, ldc_i4_3,
\r
614 ldc_i4_4, ldc_i4_5, ldc_i4_6, ldc_i4_7, ldc_i4_8, dup = 0x25, pop,
\r
615 ret = 0x2A, ldind_i1 = 0x46, ldind_u1, ldind_i2, ldind_u2, ldind_i4,
\r
616 ldind_u4, ldind_i8, ldind_i, ldind_r4, ldind_r8, ldind_ref, stind_ref,
\r
617 stind_i1, stind_i2, stind_i4, stind_i8, stind_r4, stind_r8, add, sub, mul,
\r
618 div, div_un, rem, rem_un, and, or, xor, shl, shr, shr_un, neg, not,
\r
619 conv_i1, conv_i2, conv_i4, conv_i8, conv_r4, conv_r8, conv_u4, conv_u8,
\r
620 conv_r_un = 0x76, throwOp = 0x7A, conv_ovf_i1_un = 0x82, conv_ovf_i2_un,
\r
621 conv_ovf_i4_un, conv_ovf_i8_un, conf_ovf_u1_un, conv_ovf_u2_un,
\r
622 conv_ovf_u4_un, conv_ovf_u8_un, conv_ovf_i_un, conv_ovf_u_un,
\r
623 ldlen = 0x8E, ldelem_i1 = 0x90, ldelem_u1, ldelem_i2, ldelem_u2,
\r
624 ldelem_i4, ldelem_u4, ldelem_i8, ldelem_i, ldelem_r4, ldelem_r8,
\r
625 ldelem_ref, stelem_i, stelem_i1, stelem_i2, stelem_i4, stelem_i8, stelem_r4 = 0xA0, stelem_r8,
\r
626 stelem_ref, conv_ovf_i1 = 0xb3, conv_ovf_u1, conv_ovf_i2, conv_ovf_u2,
\r
627 conv_ovf_i4, conv_ovf_u4, conv_ovf_i8, conv_ovf_u8, ckfinite = 0xC3,
\r
628 conv_u2 = 0xD1, conv_u1, conv_i, conv_ovf_i, conv_ovf_u, add_ovf,
\r
629 add_ovf_un, mul_ovf, mul_ovf_un, sub_ovf, sub_ovf_un, endfinally,
\r
630 stind_i = 0xDF, conv_u, arglist = 0xFE00, ceq, cgt, cgt_un, clt, clt_un,
\r
631 localloc = 0xFE0F, endfilter = 0xFE11, volatile_ = 0xFE13, tail_,
\r
632 cpblk = 0xFE17, initblk, rethrow = 0xFE1A, refanytype = 0xFE1D}
\r
635 /// CIL instructions requiring an integer parameter
\r
637 public enum IntOp {ldarg_s = 0x0E, ldarga_s, starg_s, ldloc_s, ldloca_s,
\r
638 stloc_s, ldc_i4_s = 0x1F, ldc_i4, ldarg = 0xFE09,
\r
639 ldarga, starg, ldloc, ldloca, stloc, unaligned = 0xFE12 }
\r
642 /// CIL instructions requiring a field parameter
\r
644 public enum FieldOp {ldfld = 0x7B, ldflda, stfld, ldsfld, ldsflda,
\r
645 stsfld, ldtoken = 0xD0 }
\r
648 /// CIL instructions requiring a method parameter
\r
650 public enum MethodOp {jmp = 0x27, call, callvirt = 0x6F, newobj = 0x73,
\r
651 ldtoken = 0xD0, ldftn = 0xFE06, ldvirtfn }
\r
654 /// CIL instructions requiring a type parameter
\r
656 public enum TypeOp {cpobj = 0x70, ldobj, castclass = 0x74, isinst,
\r
657 unbox = 0x79, stobj = 0x81, box = 0x8C, newarr,
\r
658 ldelema = 0x8F, refanyval = 0xC2, mkrefany = 0xC6,
\r
659 ldtoken = 0xD0, initobj = 0xFE15, sizeOf = 0xFE1C,
\r
660 ldelem = 0xA3, stelem = 0xA4, unbox_any }
\r
663 /// CIL branch instructions
\r
665 public enum BranchOp {
667 br_s = 0x2B, brfalse_s, brtrue_s, beq_s, bge_s, bgt_s,
668 ble_s, blt_s, bne_un_s, bge_un_s, bgt_un_s, ble_un_s, blt_un_s,
670 br = 0x38, brfalse, brtrue, beq, bge, bgt, ble, blt,
\r
671 bne_un, bge_un, bgt_un, ble_un, blt_un,
673 leave = 0xDD, leave_s }
\r
676 /// Index for all the tables in the meta data
\r
678 public enum MDTable { Module, TypeRef, TypeDef, Field = 0x04, Method = 0x06,
\r
679 Param = 0x08, InterfaceImpl, MemberRef, Constant, CustomAttribute,
\r
680 FieldMarshal, DeclSecurity, ClassLayout, FieldLayout, StandAloneSig,
\r
681 EventMap, Event = 0x14, PropertyMap, Property = 0x17, MethodSemantics,
\r
682 MethodImpl, ModuleRef, TypeSpec, ImplMap, FieldRVA, Assembly = 0x20,
\r
683 AssemblyProcessor, AssemblyOS, AssemblyRef, AssemblyRefProcessor,
\r
684 AssemblyRefOS, File, ExportedType, ManifestResource, NestedClass,
\r
685 GenericParam, MethodSpec, GenericParamConstraint }
\r
687 public enum SafeArrayType { int16 = 2, int32, float32, float64,
\r
688 currency, date, bstr, dispatch, error, boolean, variant, unknown,
\r
689 Decimal, int8 = 16, uint8, uint16, uint32, Int = 22, UInt }
\r
691 internal enum CIx { TypeDefOrRef, HasConst, HasCustomAttr, HasFieldMarshal,
\r
692 HasDeclSecurity, MemberRefParent, HasSemantics, MethodDefOrRef,
\r
693 MemberForwarded, Implementation, CustomAttributeType, ResolutionScope,
\r
694 TypeOrMethodDef, MaxCIx }
\r
696 internal enum MapType { eventMap, propertyMap, nestedClass }
\r
698 /**************************************************************************/
\r
700 /// The assembly for mscorlib.
\r
702 public sealed class MSCorLib : AssemblyRef
\r
704 private static readonly int valueTypeIx = 18;
\r
705 private readonly string systemName = "System";
\r
706 private ClassRef[] systemClasses = new ClassRef[valueTypeIx+2];
\r
707 private PrimitiveType[] systemTypes = new PrimitiveType[valueTypeIx];
\r
708 private TypeSpec[] specialTypeSpecs = new TypeSpec[valueTypeIx];
\r
709 private static int[] specialNames = {
\r
710 PrimitiveType.Void.GetName().GetHashCode(),
\r
711 PrimitiveType.Boolean.GetName().GetHashCode(),
\r
712 PrimitiveType.Char.GetName().GetHashCode(),
\r
713 PrimitiveType.Int8.GetName().GetHashCode(),
\r
714 PrimitiveType.UInt8.GetName().GetHashCode(),
\r
715 PrimitiveType.Int16.GetName().GetHashCode(),
\r
716 PrimitiveType.UInt16.GetName().GetHashCode(),
\r
717 PrimitiveType.Int32.GetName().GetHashCode(),
\r
718 PrimitiveType.UInt32.GetName().GetHashCode(),
\r
719 PrimitiveType.Int64.GetName().GetHashCode(),
\r
720 PrimitiveType.UInt64.GetName().GetHashCode(),
\r
721 PrimitiveType.Float32.GetName().GetHashCode(),
\r
722 PrimitiveType.Float64.GetName().GetHashCode(),
\r
723 PrimitiveType.String.GetName().GetHashCode(),
\r
724 PrimitiveType.TypedRef.GetName().GetHashCode(),
\r
725 PrimitiveType.IntPtr.GetName().GetHashCode(),
\r
726 PrimitiveType.UIntPtr.GetName().GetHashCode(),
\r
727 PrimitiveType.Object.GetName().GetHashCode(),
\r
728 "ValueType".GetHashCode(),
\r
729 "Enum".GetHashCode()
\r
732 internal MSCorLib(MetaData md) : base(md,"mscorlib") {
\r
733 md.AddToTable(MDTable.AssemblyRef,this);
\r
734 systemTypes[PrimitiveType.Void.GetSystemTypeIx()] = PrimitiveType.Void;
\r
735 systemTypes[PrimitiveType.Boolean.GetSystemTypeIx()] = PrimitiveType.Boolean;
\r
736 systemTypes[PrimitiveType.Char.GetSystemTypeIx()] = PrimitiveType.Char;
\r
737 systemTypes[PrimitiveType.Int8.GetSystemTypeIx()] = PrimitiveType.Int8;
\r
738 systemTypes[PrimitiveType.UInt8.GetSystemTypeIx()] = PrimitiveType.UInt8;
\r
739 systemTypes[PrimitiveType.Int16.GetSystemTypeIx()] = PrimitiveType.Int16;
\r
740 systemTypes[PrimitiveType.UInt16.GetSystemTypeIx()] = PrimitiveType.UInt16;
\r
741 systemTypes[PrimitiveType.Int32.GetSystemTypeIx()] = PrimitiveType.Int32;
\r
742 systemTypes[PrimitiveType.UInt32.GetSystemTypeIx()] = PrimitiveType.UInt32;
\r
743 systemTypes[PrimitiveType.Int64.GetSystemTypeIx()] = PrimitiveType.Int64;
\r
744 systemTypes[PrimitiveType.UInt64.GetSystemTypeIx()] = PrimitiveType.UInt64;
\r
745 systemTypes[PrimitiveType.Float32.GetSystemTypeIx()] = PrimitiveType.Float32;
\r
746 systemTypes[PrimitiveType.Float64.GetSystemTypeIx()] = PrimitiveType.Float64;
\r
747 systemTypes[PrimitiveType.IntPtr.GetSystemTypeIx()] = PrimitiveType.IntPtr;
\r
748 systemTypes[PrimitiveType.UIntPtr.GetSystemTypeIx()] = PrimitiveType.UIntPtr;
\r
749 systemTypes[PrimitiveType.String.GetSystemTypeIx()] = PrimitiveType.String;
\r
750 systemTypes[PrimitiveType.Object.GetSystemTypeIx()] = PrimitiveType.Object;
\r
751 systemTypes[PrimitiveType.TypedRef.GetSystemTypeIx()] = PrimitiveType.TypedRef;
\r
755 /// Add a class to the mscorlib assembly
\r
757 /// <param name="nsName">name space name</param>
\r
758 /// <param name="name">class name</param>
\r
759 /// <returns></returns>
\r
760 public override ClassRef AddClass(string nsName, string name) {
\r
761 ClassRef aClass = GetSpecialClass(nsName,name);
\r
762 if (aClass == null) {
\r
763 aClass = new ClassRef(nsName,name,metaData);
\r
764 metaData.AddToTable(MDTable.TypeRef,aClass);
\r
765 aClass.SetParent(this);
\r
770 private ClassRef GetSpecialClass(string nsName,string name) {
\r
771 if (nsName.CompareTo(systemName) != 0) return null;
\r
772 int hash = name.GetHashCode();
\r
773 for (int i=0; i < specialNames.Length; i++) {
\r
774 if (hash == specialNames[i]) {
\r
775 if (systemClasses[i] == null) {
\r
776 if (i < valueTypeIx) {
\r
777 systemClasses[i] = new SystemClass(systemTypes[i],this,metaData);
\r
778 if ((systemTypes[i] != PrimitiveType.Object) &&
\r
779 (systemTypes[i] != PrimitiveType.String)) {
\r
780 systemClasses[i].MakeValueClass();
\r
783 systemClasses[i] = new ClassRef(nsName,name,metaData);
\r
784 systemClasses[i].SetParent(this);
\r
785 systemClasses[i].MakeValueClass();
\r
787 metaData.AddToTable(MDTable.TypeRef,systemClasses[i]);
\r
789 return systemClasses[i];
\r
795 internal ClassRef GetSpecialSystemClass(PrimitiveType pType) {
\r
796 int ix = pType.GetSystemTypeIx();
\r
797 if (systemClasses[ix] == null) {
\r
798 systemClasses[ix] = new SystemClass(pType,this,metaData);
\r
799 metaData.AddToTable(MDTable.TypeRef,systemClasses[ix]);
\r
801 return systemClasses[ix];
\r
804 private ClassRef GetValueClass(string name, int hash) {
\r
805 int ix = valueTypeIx;
\r
806 if (hash != specialNames[valueTypeIx]) ix++;
\r
807 if (systemClasses[ix] == null) {
\r
808 systemClasses[ix] = new ClassRef(systemName,name,metaData);
\r
809 systemClasses[ix].SetParent(this);
\r
810 systemClasses[ix].MakeValueClass();
\r
811 metaData.AddToTable(MDTable.TypeRef,systemClasses[ix]);
\r
813 return systemClasses[ix];
\r
816 internal ClassRef ValueType() {
\r
817 if (systemClasses[valueTypeIx] == null) {
\r
818 ClassRef valType = new ClassRef("System","ValueType",metaData);
\r
819 valType.SetParent(this);
\r
820 valType.MakeValueClass();
\r
821 metaData.AddToTable(MDTable.TypeRef,valType);
\r
822 systemClasses[valueTypeIx] = valType;
\r
824 return systemClasses[valueTypeIx];
\r
828 /// Add a value class to this external assembly
\r
830 /// <param name="nsName">name space name</param>
\r
831 /// <param name="name">class name</param>
\r
832 /// <returns></returns>
\r
833 public override ClassRef AddValueClass(string nsName, string name) {
\r
834 if (nsName.CompareTo(systemName) == 0) {
\r
835 int hash = name.GetHashCode();
\r
836 if ((hash == specialNames[valueTypeIx]) ||
\r
837 (hash == specialNames[valueTypeIx+1])) {
\r
838 return GetValueClass(name,hash);
\r
841 ClassRef aClass = new ClassRef(nsName,name,metaData);
\r
842 metaData.AddToTable(MDTable.TypeRef,aClass);
\r
843 aClass.SetParent(this);
\r
844 aClass.MakeValueClass();
\r
849 /**************************************************************************/
\r
851 /// Signature for calli instruction
\r
853 public class CalliSig : Signature
\r
855 private static readonly byte Sentinel = 0x41;
\r
858 Type[] parameters, optParams;
\r
859 uint numPars = 0, numOptPars = 0;
\r
862 /// Create a signature for a calli instruction
\r
864 /// <param name="cconv">calling conventions</param>
\r
865 /// <param name="retType">return type</param>
\r
866 /// <param name="pars">parameter types</param>
\r
867 public CalliSig(CallConv cconv, Type retType, Type[] pars) {
\r
868 tabIx = MDTable.StandAloneSig;
\r
870 returnType = retType;
\r
872 if (pars != null) numPars = (uint)pars.Length;
\r
876 /// Add the optional parameters to a vararg method
\r
877 /// This method sets the vararg calling convention
\r
879 /// <param name="optPars">the optional pars for the vararg call</param>
\r
880 public void AddVarArgs(Type[] optPars) {
\r
881 optParams = optPars;
\r
882 if (optPars != null) numOptPars = (uint)optPars.Length;
\r
883 callConv |= CallConv.Vararg;
\r
887 /// Add extra calling conventions to this callsite signature
\r
889 /// <param name="cconv"></param>
\r
890 public void AddCallingConv(CallConv cconv) {
\r
894 internal sealed override void BuildTables(MetaData md) {
\r
896 MemoryStream sig = new MemoryStream();
\r
897 sig.WriteByte((byte)callConv);
\r
898 MetaData.CompressNum(numPars+numOptPars,sig);
\r
899 returnType.TypeSig(sig);
\r
900 for (int i=0; i < numPars; i++) {
\r
901 parameters[i].TypeSig(sig);
\r
903 sigIx = md.AddToBlobHeap(sig.ToArray());
\r
904 if (numOptPars > 0) {
\r
905 sig.WriteByte(Sentinel);
\r
906 for (int i=0; i < numOptPars; i++) {
\r
907 optParams[i].TypeSig(sig);
\r
914 /**************************************************************************/
\r
916 /// The IL instructions for a method
\r
918 public class CILInstructions
\r
921 private static readonly uint ExHeaderSize = 4;
\r
922 private static readonly uint FatExClauseSize = 24;
\r
923 private static readonly uint SmlExClauseSize = 12;
\r
924 private static readonly sbyte maxByteVal = 127;
\r
925 private static readonly sbyte minByteVal = -128;
\r
926 private static readonly byte maxUByteVal = 255;
\r
927 private static readonly int smallSize = 64;
\r
928 private static readonly ushort TinyFormat = 0x2;
\r
929 private static readonly ushort FatFormat = 0x3003;
\r
930 private static readonly ushort MoreSects = 0x8;
\r
931 private static readonly ushort InitLocals = 0x10;
\r
932 private static readonly uint FatSize = 12;
\r
933 private static readonly uint FatWords = FatSize/4;
\r
934 private static readonly byte FatExceptTable = 0x41;
\r
935 private static readonly byte SmlExceptTable = 0x01;
\r
937 private MetaData metaData;
\r
938 private ArrayList exceptions, blockStack;
\r
939 //private bool codeChecked = false;
\r
940 private static readonly int INITSIZE = 5;
\r
941 private CILInstruction[] buffer = new CILInstruction[INITSIZE];
\r
942 private int tide = 0;
\r
943 private uint offset = 0;
\r
944 private ushort headerFlags = 0;
\r
945 private short maxStack;
\r
946 private uint paddingNeeded = 0;
\r
947 private byte exceptHeader = 0;
\r
948 uint localSigIx = 0;
\r
949 uint codeSize = 0, exceptSize = 0;
\r
950 bool tinyFormat, fatExceptionFormat = false;
\r
952 internal CILInstructions(MetaData md) {
\r
956 private void AddToBuffer(CILInstruction inst) {
\r
957 if (tide >= buffer.Length) {
\r
958 CILInstruction[] tmp = buffer;
\r
959 buffer = new CILInstruction[tmp.Length * 2];
\r
960 for (int i=0; i < tide; i++) {
\r
961 buffer[i] = tmp[i];
\r
964 //Console.WriteLine("Adding instruction at offset " + offset + " with size " + inst.size);
\r
965 inst.offset = offset;
\r
966 offset += inst.size;
\r
967 buffer[tide++] = inst;
\r
971 /// Add a simple IL instruction
\r
973 /// <param name="inst">the IL instruction</param>
\r
974 public void Inst(Op inst) {
\r
975 AddToBuffer(new Instr((int)inst));
\r
979 /// Add an IL instruction with an integer parameter
\r
981 /// <param name="inst">the IL instruction</param>
\r
982 /// <param name="val">the integer parameter value</param>
\r
983 public void IntInst(IntOp inst, int val) {
\r
984 int instr = (int)inst;
\r
985 if ((inst == IntOp.ldc_i4_s) || (inst == IntOp.ldc_i4))
\r
986 AddToBuffer(new IntInstr(instr,val,(inst == IntOp.ldc_i4_s)));
\r
988 AddToBuffer(new UIntInstr(instr,val,((inst < IntOp.ldc_i4_s) ||
\r
989 (inst == IntOp.unaligned))));
\r
993 /// Add the load long instruction
\r
995 /// <param name="cVal">the long value</param>
\r
996 public void ldc_i8(long cVal) {
\r
997 AddToBuffer(new LongInstr(0x21,cVal));
\r
1001 /// Add the load float32 instruction
\r
1003 /// <param name="cVal">the float value</param>
\r
1004 public void ldc_r4(float cVal) {
\r
1005 AddToBuffer(new FloatInstr(0x22,cVal));
\r
1009 /// Add the load float64 instruction
\r
1011 /// <param name="cVal">the float value</param>
\r
1012 public void ldc_r8(double cVal) {
\r
1013 AddToBuffer(new DoubleInstr(0x23,cVal));
\r
1017 /// Add the load string instruction
\r
1019 /// <param name="str">the string value</param>
\r
1020 public void ldstr(string str) {
\r
1021 AddToBuffer(new StringInstr(0x72,str));
\r
1025 /// Add the load string instruction
1027 public void ldstr (byte[] str) {
1028 AddToBuffer (new StringInstr (0x72, str));
1032 /// Add the calli instruction
\r
1034 /// <param name="sig">the signature for the calli</param>
\r
1035 public void calli(CalliSig sig) {
\r
1036 AddToBuffer(new SigInstr(0x29,sig));
\r
1040 /// Add a label to the CIL instructions
\r
1042 /// <param name="lab">the label to be added</param>
\r
1043 public void CodeLabel(CILLabel lab) {
\r
1044 AddToBuffer(new LabelInstr(lab));
\r
1048 /// Add an instruction with a field parameter
\r
1050 /// <param name="inst">the CIL instruction</param>
\r
1051 /// <param name="f">the field parameter</param>
\r
1052 public void FieldInst(FieldOp inst, Field f) {
\r
1053 AddToBuffer(new FieldInstr((int)inst,f));
\r
1057 /// Add an instruction with a method parameter
\r
1059 /// <param name="inst">the CIL instruction</param>
\r
1060 /// <param name="m">the method parameter</param>
\r
1061 public void MethInst(MethodOp inst, Method m) {
\r
1062 AddToBuffer(new MethInstr((int)inst,m));
\r
1066 /// Add an instruction with a type parameter
\r
1068 /// <param name="inst">the CIL instruction</param>
\r
1069 /// <param name="t">the type argument for the CIL instruction</param>
\r
1070 public void TypeInst(TypeOp inst, Type aType) {
\r
1071 AddToBuffer(new TypeInstr((int)inst,aType,metaData));
\r
1075 /// Add a branch instruction
\r
1077 /// <param name="inst">the branch instruction</param>
\r
1078 /// <param name="lab">the label that is the target of the branch</param>
\r
1079 public void Branch(BranchOp inst, CILLabel lab) {
\r
1080 AddToBuffer(new BranchInstr((int)inst,lab));
\r
1084 /// Add a switch instruction
\r
1086 /// <param name="labs">the target labels for the switch</param>
\r
1087 public void Switch(CILLabel[] labs) {
\r
1088 AddToBuffer(new SwitchInstr(0x45,labs));
\r
1092 /// Add a byte to the CIL instructions (.emitbyte)
\r
1094 /// <param name="bVal"></param>
\r
1095 public void emitbyte(byte bVal) {
\r
1096 AddToBuffer(new CILByte(bVal));
\r
1100 /// Add an instruction which puts an integer on TOS. This method
\r
1101 /// selects the correct instruction based on the value of the integer.
\r
1103 /// <param name="i">the integer value</param>
\r
1104 public void PushInt(int i) {
\r
1106 AddToBuffer(new Instr((int)Op.ldc_i4_m1));
\r
1107 } else if ((i >= 0) && (i <= 8)) {
\r
1108 Op op = (Op)(Op.ldc_i4_0 + i);
\r
1109 AddToBuffer(new Instr((int)op));
\r
1110 } else if ((i >= minByteVal) && (i <= maxByteVal)) {
\r
1111 AddToBuffer(new IntInstr((int)IntOp.ldc_i4_s,i,true));
\r
1113 AddToBuffer(new IntInstr((int)IntOp.ldc_i4,i,false));
\r
1118 /// Add the instruction to load a long on TOS
\r
1120 /// <param name="l">the long value</param>
\r
1121 public void PushLong(long l) {
\r
1122 AddToBuffer(new LongInstr(0x21,l));
\r
1126 /// Add an instruction to push the boolean value true on TOS
\r
1128 public void PushTrue() {
\r
1129 AddToBuffer(new Instr((int)Op.ldc_i4_1));
\r
1133 /// Add an instruction to push the boolean value false on TOS
\r
1135 public void PushFalse() {
\r
1136 AddToBuffer(new Instr((int)Op.ldc_i4_0));
\r
1140 /// Add the instruction to load an argument on TOS. This method
\r
1141 /// selects the correct instruction based on the value of argNo
\r
1143 /// <param name="argNo">the number of the argument</param>
\r
1144 public void LoadArg(int argNo) {
\r
1146 int op = (int)Op.ldarg_0 + argNo;
\r
1147 AddToBuffer(new Instr(op));
\r
1148 } else if (argNo <= maxUByteVal) {
\r
1149 AddToBuffer(new UIntInstr((int)IntOp.ldarg,argNo,true));
\r
1151 AddToBuffer(new UIntInstr(0x09,argNo,false));
\r
1156 /// Add the instruction to load the address of an argument on TOS.
\r
1157 /// This method selects the correct instruction based on the value
\r
1160 /// <param name="argNo">the number of the argument</param>
\r
1161 public void LoadArgAdr(int argNo) {
\r
1162 if (argNo <= maxUByteVal) {
\r
1163 AddToBuffer(new UIntInstr((int)IntOp.ldarga,argNo,true));
\r
1165 AddToBuffer(new UIntInstr(0x0A,argNo,false));
\r
1170 /// Add the instruction to load a local on TOS. This method selects
\r
1171 /// the correct instruction based on the value of locNo.
\r
1173 /// <param name="locNo">the number of the local to load</param>
\r
1174 public void LoadLocal(int locNo) {
\r
1176 int op = (int)Op.ldloc_0 + locNo;
\r
1177 AddToBuffer(new Instr(op));
\r
1178 } else if (locNo <= maxUByteVal) {
\r
1179 AddToBuffer(new UIntInstr((int)IntOp.ldloc,locNo,true));
\r
1181 AddToBuffer(new UIntInstr(0x0C,locNo,false));
\r
1186 /// Add the instruction to load the address of a local on TOS.
\r
1187 /// This method selects the correct instruction based on the
\r
1188 /// value of locNo.
\r
1190 /// <param name="locNo">the number of the local</param>
\r
1191 public void LoadLocalAdr(int locNo) {
\r
1192 if (locNo <= maxUByteVal) {
\r
1193 AddToBuffer(new UIntInstr((int)IntOp.ldloca,locNo,true));
\r
1195 AddToBuffer(new UIntInstr(0x0D,locNo,false));
\r
1200 /// Add the instruction to store to an argument. This method
\r
1201 /// selects the correct instruction based on the value of argNo.
\r
1203 /// <param name="argNo">the argument to be stored to</param>
\r
1204 public void StoreArg(int argNo) {
\r
1205 if (argNo <= maxUByteVal) {
\r
1206 AddToBuffer(new UIntInstr((int)IntOp.starg,argNo,true));
\r
1208 AddToBuffer(new UIntInstr(0x0B,argNo,false));
\r
1213 /// Add the instruction to store to a local. This method selects
\r
1214 /// the correct instruction based on the value of locNo.
\r
1216 /// <param name="locNo">the local to be stored to</param>
\r
1217 public void StoreLocal(int locNo) {
\r
1219 int op = (int)Op.stloc_0 + locNo;
\r
1220 AddToBuffer(new Instr(op));
\r
1221 } else if (locNo <= maxUByteVal) {
\r
1222 AddToBuffer(new UIntInstr((int)IntOp.stloc,locNo,true));
\r
1224 AddToBuffer(new UIntInstr(0x0E,locNo,false));
\r
1229 /// Create a new CIL label. To place the label in the CIL instruction
\r
1230 /// stream use CodeLabel.
\r
1232 /// <returns>a new CIL label</returns>
\r
1233 public CILLabel NewLabel() {
\r
1234 return new CILLabel();
\r
1237 public void AddTryBlock(TryBlock tryBlock) {
\r
1238 if (exceptions == null)
\r
1239 exceptions = new ArrayList();
\r
1240 else if (exceptions.Contains(tryBlock)) return;
\r
1241 exceptions.Add(tryBlock);
\r
1245 /// Create a new label at this position in the code buffer
\r
1247 /// <returns>the label at the current position</returns>
\r
1248 public CILLabel NewCodedLabel() {
\r
1249 CILLabel lab = new CILLabel();
\r
1250 AddToBuffer(new LabelInstr(lab));
\r
1255 /// Mark this position as the start of a new block
\r
1256 /// (try, catch, filter, finally or fault)
\r
1258 public void StartBlock() {
\r
1259 if (blockStack == null) blockStack = new ArrayList();
\r
1260 blockStack.Insert(0,NewCodedLabel());
\r
1264 /// Mark this position as the end of the last started block and
\r
1265 /// make it a try block. This try block is added to the current
\r
1266 /// instructions (ie do not need to call AddTryBlock)
\r
1268 /// <returns>The try block just ended</returns>
\r
1269 public TryBlock EndTryBlock() {
\r
1270 TryBlock tBlock = new TryBlock((CILLabel)blockStack[0],NewCodedLabel());
\r
1271 blockStack.RemoveAt(0);
\r
1272 AddTryBlock(tBlock);
\r
1277 /// Mark this position as the end of the last started block and
\r
1278 /// make it a catch block. This catch block is associated with the
\r
1279 /// specified try block.
\r
1281 /// <param name="exceptType">the exception type to be caught</param>
\r
1282 /// <param name="tryBlock">the try block associated with this catch block</param>
\r
1283 public void EndCatchBlock(Class exceptType, TryBlock tryBlock) {
\r
1284 Catch catchBlock = new Catch(exceptType,(CILLabel)blockStack[0],
\r
1286 tryBlock.AddHandler(catchBlock);
\r
1290 /// Mark this position as the end of the last started block and
\r
1291 /// make it a filter block. This filter block is associated with the
\r
1292 /// specified try block.
\r
1294 /// <param name="filterLab">the label where the filter code is</param>
\r
1295 /// <param name="tryBlock">the try block associated with this filter block</param>
\r
1296 public void EndFilterBlock(CILLabel filterLab, TryBlock tryBlock) {
\r
1297 Filter filBlock = new Filter(filterLab,(CILLabel)blockStack[0],NewCodedLabel());
\r
1298 tryBlock.AddHandler(filBlock);
\r
1302 /// Mark this position as the end of the last started block and
\r
1303 /// make it a finally block. This finally block is associated with the
\r
1304 /// specified try block.
\r
1306 /// <param name="tryBlock">the try block associated with this finally block</param>
\r
1307 public void EndFinallyBlock(TryBlock tryBlock) {
\r
1308 Finally finBlock= new Finally((CILLabel)blockStack[0],NewCodedLabel());
\r
1309 tryBlock.AddHandler(finBlock);
\r
1313 /// Mark this position as the end of the last started block and
\r
1314 /// make it a fault block. This fault block is associated with the
\r
1315 /// specified try block.
\r
1317 /// <param name="tryBlock">the try block associated with this fault block</param>
\r
1318 public void EndFaultBlock(TryBlock tryBlock) {
\r
1319 Fault fBlock= new Fault((CILLabel)blockStack[0],NewCodedLabel());
\r
1320 tryBlock.AddHandler(fBlock);
\r
1323 internal uint GetCodeSize() {
\r
1324 return codeSize + paddingNeeded + exceptSize;
\r
1327 internal void CheckCode(uint locSigIx, bool initLocals, int maxStack) {
\r
1328 if (tide == 0) return;
\r
1329 bool changed = true;
\r
1332 for (int i=0; i < tide; i++) {
\r
1333 changed = buffer[i].Check(metaData) || changed;
\r
1336 for (int i=1; i < tide; i++) {
\r
1337 buffer[i].offset = buffer[i-1].offset + buffer[i-1].size;
\r
1339 offset = buffer[tide-1].offset + buffer[tide-1].size;
\r
1342 codeSize = offset;
\r
1343 // Console.WriteLine("codeSize before header added = " + codeSize);
\r
1344 if ((offset < smallSize) && (maxStack <= 8) && (locSigIx == 0) && (exceptions == null)) {
\r
1345 // can use tiny header
\r
1346 //Console.WriteLine("Tiny Header");
\r
1347 tinyFormat = true;
\r
1348 headerFlags = (ushort)(TinyFormat | ((ushort)codeSize << 2));
\r
1350 if ((codeSize % 4) != 0) { paddingNeeded = 4 - (codeSize % 4); }
\r
1352 //Console.WriteLine("Fat Header");
\r
1353 tinyFormat = false;
\r
1354 localSigIx = locSigIx;
\r
1355 this.maxStack = (short)maxStack;
\r
1356 headerFlags = FatFormat;
\r
1357 if (exceptions != null) {
\r
1358 // Console.WriteLine("Got exceptions");
\r
1359 headerFlags |= MoreSects;
\r
1360 uint numExceptClauses = 0;
\r
1361 for (int i=0; i < exceptions.Count; i++) {
\r
1362 TryBlock tryBlock = (TryBlock)exceptions[i];
\r
1363 tryBlock.SetSize();
\r
1364 numExceptClauses += (uint)tryBlock.NumHandlers();
\r
1365 if (tryBlock.isFat()) fatExceptionFormat = true;
\r
1368 uint data_size = ExHeaderSize + numExceptClauses *
1369 (fatExceptionFormat ? FatExClauseSize : SmlExClauseSize);
1371 if (data_size > 256)
1372 fatExceptionFormat = true;
1374 // Console.WriteLine("numexceptclauses = " + numExceptClauses);
\r
1375 if (fatExceptionFormat) {
\r
1376 // Console.WriteLine("Fat exception format");
\r
1377 exceptHeader = FatExceptTable;
\r
1378 exceptSize = ExHeaderSize + numExceptClauses * FatExClauseSize;
\r
1380 // Console.WriteLine("Tiny exception format");
\r
1381 exceptHeader = SmlExceptTable;
\r
1382 exceptSize = ExHeaderSize + numExceptClauses * SmlExClauseSize;
\r
1384 // Console.WriteLine("exceptSize = " + exceptSize);
\r
1386 if (initLocals) headerFlags |= InitLocals;
\r
1387 if ((offset % 4) != 0) { paddingNeeded = 4 - (offset % 4); }
\r
1388 codeSize += FatSize;
\r
1390 // Console.WriteLine("codeSize = " + codeSize + " headerFlags = " +
\r
1391 // Hex.Short(headerFlags));
\r
1394 internal void Write(FileImage output) {
\r
1395 // Console.WriteLine("Writing header flags = " + Hex.Short(headerFlags));
\r
1397 // Console.WriteLine("Writing tiny code");
\r
1398 output.Write((byte)headerFlags);
\r
1400 // Console.WriteLine("Writing fat code");
\r
1401 output.Write(headerFlags);
\r
1402 output.Write((ushort)maxStack);
\r
1403 output.Write(offset);
\r
1404 output.Write(localSigIx);
\r
1406 // Console.WriteLine(Hex.Int(tide) + " CIL instructions");
\r
1407 // Console.WriteLine("starting instructions at " + output.Seek(0,SeekOrigin.Current));
\r
1408 for (int i=0; i < tide; i++) {
\r
1409 buffer[i].Write(output);
\r
1411 // Console.WriteLine("ending instructions at " + output.Seek(0,SeekOrigin.Current));
\r
1412 for (int i=0; i < paddingNeeded; i++) { output.Write((byte)0); }
\r
1413 if (exceptions != null) {
\r
1414 // Console.WriteLine("Writing exceptions");
\r
1415 // Console.WriteLine("header = " + Hex.Short(exceptHeader) + " exceptSize = " + Hex.Int(exceptSize));
\r
1416 output.Write(exceptHeader);
\r
1417 output.Write3Bytes((uint)exceptSize);
\r
1418 for (int i=0; i < exceptions.Count; i++) {
\r
1419 TryBlock tryBlock = (TryBlock)exceptions[i];
\r
1420 tryBlock.Write(output,fatExceptionFormat);
\r
1426 /**************************************************************************/
\r
1428 /// A label in the IL
\r
1430 public class CILLabel
\r
1432 CILInstruction branch;
\r
1433 CILInstruction[] multipleBranches;
\r
1435 CILInstruction labInstr;
\r
1438 public CILLabel (uint offset) {
\r
1439 this.offset = offset;
\r
1443 internal CILLabel() {
\r
1446 internal void AddBranch(CILInstruction instr) {
\r
1447 if (branch == null) {
\r
1451 if (multipleBranches == null) {
\r
1452 multipleBranches = new CILInstruction[2];
\r
1453 } else if (tide >= multipleBranches.Length) {
\r
1454 CILInstruction[] tmp = multipleBranches;
\r
1455 multipleBranches = new CILInstruction[tmp.Length*2];
\r
1456 for (int i=0; i < tide; i++) {
\r
1457 multipleBranches[i] = tmp[i];
\r
1460 multipleBranches[tide++] = instr;
\r
1463 internal void AddLabelInstr(LabelInstr lInstr) {
\r
1464 labInstr = lInstr;
\r
1467 internal uint GetLabelOffset() {
\r
1468 if (labInstr == null) return 0;
\r
1469 return labInstr.offset + offset;
\r
1473 /**************************************************************************/
\r
1474 public abstract class CodeBlock {
\r
1476 private static readonly int maxCodeSize = 256;
\r
1477 protected CILLabel start, end;
\r
1478 protected bool small = true;
\r
1480 public CodeBlock(CILLabel start, CILLabel end) {
\r
1481 this.start = start;
\r
1485 internal virtual bool isFat() {
\r
1486 // Console.WriteLine("block start = " + start.GetLabelOffset() +
\r
1487 // " block end = " + end.GetLabelOffset());
\r
1488 return (end.GetLabelOffset() - start.GetLabelOffset()) > maxCodeSize;
\r
1491 internal virtual void Write(FileImage output, bool fatFormat) {
\r
1492 if (fatFormat) output.Write(start.GetLabelOffset());
\r
1493 else output.Write((short)start.GetLabelOffset());
\r
1494 uint len = end.GetLabelOffset() - start.GetLabelOffset();
\r
1495 if (fatFormat) output.Write(len);
\r
1496 else output.Write((byte)len);
\r
1502 /// The descriptor for a guarded block (.try)
\r
1504 public class TryBlock : CodeBlock {
\r
1505 protected bool fatFormat = false;
\r
1506 protected int flags = 0;
\r
1507 ArrayList handlers = new ArrayList();
\r
1510 /// Create a new try block
\r
1512 /// <param name="start">start label for the try block</param>
\r
1513 /// <param name="end">end label for the try block</param>
\r
1514 public TryBlock(CILLabel start, CILLabel end) : base(start,end) { }
\r
1517 /// Add a handler to this try block
\r
1519 /// <param name="handler">a handler to be added to the try block</param>
\r
1520 public void AddHandler(HandlerBlock handler) {
\r
1521 flags = handler.GetFlag();
\r
1522 handlers.Add(handler);
\r
1525 internal void SetSize() {
\r
1526 fatFormat = base.isFat();
\r
1527 if (fatFormat) return;
\r
1528 for (int i=0; i < handlers.Count; i++) {
\r
1529 HandlerBlock handler = (HandlerBlock)handlers[i];
\r
1530 if (handler.isFat()) {
\r
1537 internal int NumHandlers() {
\r
1538 return handlers.Count;
\r
1541 internal override bool isFat() {
\r
1545 internal override void Write(FileImage output, bool fatFormat) {
\r
1546 // Console.WriteLine("writing exception details");
\r
1547 for (int i=0; i < handlers.Count; i++) {
\r
1548 // Console.WriteLine("Except block " + i);
\r
1549 HandlerBlock handler = (HandlerBlock)handlers[i];
\r
1550 if (fatFormat) output.Write(flags);
\r
1551 else output.Write((short)flags);
\r
1552 // Console.WriteLine("flags = " + Hex.Short(flags));
\r
1553 base.Write(output,fatFormat);
\r
1554 handler.Write(output,fatFormat);
\r
1559 public abstract class HandlerBlock : CodeBlock
\r
1561 protected static readonly short ExceptionFlag = 0;
\r
1562 protected static readonly short FilterFlag = 0x01;
\r
1563 protected static readonly short FinallyFlag = 0x02;
\r
1564 protected static readonly short FaultFlag = 0x04;
\r
1566 public HandlerBlock(CILLabel start, CILLabel end) : base(start,end) { }
\r
1568 internal virtual short GetFlag() { return ExceptionFlag; }
\r
1570 internal override void Write(FileImage output, bool fatFormat) {
\r
1571 base.Write(output,fatFormat);
\r
1577 /// The descriptor for a catch clause (.catch)
\r
1579 public class Catch : HandlerBlock
\r
1584 /// Create a new catch clause
\r
1586 /// <param name="except">the exception to be caught</param>
\r
1587 /// <param name="handlerStart">start of the handler code</param>
\r
1588 /// <param name="handlerEnd">end of the handler code</param>
\r
1589 public Catch(Class except, CILLabel handlerStart, CILLabel handlerEnd)
\r
1590 : base(handlerStart,handlerEnd) {
\r
1591 exceptType = except;
\r
1594 internal override void Write(FileImage output, bool fatFormat) {
\r
1595 base.Write(output,fatFormat);
\r
1596 output.Write(exceptType.Token());
\r
1601 /// The descriptor for a filter clause (.filter)
\r
1603 public class Filter : HandlerBlock
\r
1605 CILLabel filterLabel;
\r
1608 /// Create a new filter clause
\r
1610 /// <param name="filterLabel">the label where the filter code starts</param>
\r
1611 /// <param name="handlerStart">the start of the handler code</param>
\r
1612 /// <param name="handlerEnd">the end of the handler code</param>
\r
1613 public Filter(CILLabel filterLabel, CILLabel handlerStart,
\r
1614 CILLabel handlerEnd) : base(handlerStart,handlerEnd) {
\r
1615 this.filterLabel = filterLabel;
\r
1618 internal override short GetFlag() {
\r
1619 return FilterFlag;
\r
1622 internal override void Write(FileImage output, bool fatFormat) {
\r
1623 base.Write(output,fatFormat);
\r
1624 output.Write(filterLabel.GetLabelOffset());
\r
1630 /// Descriptor for a finally block (.finally)
\r
1632 public class Finally : HandlerBlock
\r
1635 /// Create a new finally clause
\r
1637 /// <param name="finallyStart">start of finally code</param>
\r
1638 /// <param name="finallyEnd">end of finally code</param>
\r
1639 public Finally(CILLabel finallyStart, CILLabel finallyEnd)
\r
1640 : base(finallyStart,finallyEnd) { }
\r
1642 internal override short GetFlag() {
\r
1643 return FinallyFlag;
\r
1646 internal override void Write(FileImage output, bool fatFormat) {
\r
1647 base.Write(output,fatFormat);
\r
1648 output.Write((int)0);
\r
1654 /// Descriptor for a fault block (.fault)
\r
1656 public class Fault : HandlerBlock
\r
1659 /// Create a new fault clause
\r
1661 /// <param name="faultStart">start of the fault code</param>
\r
1662 /// <param name="faultEnd">end of the fault code</param>
\r
1663 public Fault(CILLabel faultStart, CILLabel faultEnd)
\r
1664 : base(faultStart,faultEnd) { }
\r
1666 internal override short GetFlag() {
\r
1667 return FaultFlag;
\r
1670 internal override void Write(FileImage output, bool fatFormat) {
\r
1671 base.Write(output,fatFormat);
\r
1672 output.Write((int)0);
\r
1677 /**************************************************************************/
\r
1679 /// The base descriptor for a class
\r
1681 public abstract class Class : Type
\r
1683 protected int row = 0;
\r
1684 protected string name, nameSpace;
\r
1685 protected uint nameIx, nameSpaceIx;
\r
1686 protected MetaData _metaData;
\r
1687 internal Class(string nameSpaceName, string className, MetaData md)
\r
1689 nameSpace = nameSpaceName;
\r
1691 nameIx = md.AddToStringsHeap(name);
\r
1692 nameSpaceIx = md.AddToStringsHeap(nameSpace);
\r
1696 internal Class(uint nsIx, uint nIx) : base(0x12) {
\r
1697 nameSpaceIx = nsIx;
\r
1701 internal virtual uint TypeDefOrRefToken() { return 0; }
\r
1703 internal virtual void MakeValueClass() {
\r
1707 internal virtual string TypeName() {
\r
1708 return (nameSpace + "." + name);
\r
1711 internal override MetaDataElement GetTypeSpec(MetaData md) {
\r
1715 /**************************************************************************/
\r
1716 // This Class produces entries in the TypeDef table of the MetaData
\r
1717 // in the PE meta data.
\r
1719 // NOTE: Entry 0 in TypeDef table is always the pseudo class <module>
\r
1720 // which is the parent for functions and variables declared a module level
\r
1723 /// The descriptor for a class defined in the IL (.class) in the current assembly/module
\r
1726 public class ClassDef : Class
\r
1728 private static readonly uint HasSecurity = 0x00040000;
\r
1729 private static readonly byte ElementType_Class = 0x12;
\r
1732 ArrayList fields = new ArrayList();
\r
1733 ArrayList methods = new ArrayList();
\r
1735 ArrayList properties;
\r
1736 bool typeIndexChecked = true;
\r
1737 uint fieldIx = 0, methodIx = 0;
\r
1738 byte[] securityActions;
\r
1740 ClassLayout layout;
\r
1741 ClassDef parentClass;
\r
1742 MetaData metaData;
\r
1744 internal ClassDef(TypeAttr attrSet, string nsName, string name,
\r
1745 MetaData md) : base(nsName, name, md) {
\r
1747 superType = metaData.mscorlib.GetSpecialSystemClass(PrimitiveType.Object);
\r
1748 flags = (uint)attrSet;
\r
1749 tabIx = MDTable.TypeDef;
\r
1752 internal void SetSuper(Class sClass) {
\r
1753 superType = sClass;
\r
1754 if (sClass is ClassRef)
\r
1755 typeIndex = superType.GetTypeIndex();
\r
1757 typeIndexChecked = false;
\r
1760 internal override void MakeValueClass() {
\r
1761 superType = metaData.mscorlib.ValueType();
\r
1762 typeIndex = superType.GetTypeIndex();
\r
1765 public void SpecialNoSuper() {
\r
1770 /// Add an attribute to this class
\r
1772 /// <param name="ta">the attribute to be added</param>
\r
1773 public void AddAttribute(TypeAttr ta) {
\r
1774 flags |= (uint)ta;
\r
1778 /// Add an interface that is implemented by this class
\r
1780 /// <param name="iFace">the interface that is implemented</param>
\r
1781 public void AddImplementedInterface(Class iFace) {
\r
1782 metaData.AddToTable(MDTable.InterfaceImpl,new InterfaceImpl(this,iFace));
\r
1786 /// Add a named generic type parameter
\r
1788 public GenericParameter AddGenericParameter (short index, string name) {
\r
1789 GenericParameter gp = new GenericParameter (this, metaData, index, name);
1790 metaData.AddToTable (MDTable.GenericParam, gp);
\r
1795 /// Add a field to this class
\r
1797 /// <param name="name">field name</param>
\r
1798 /// <param name="fType">field type</param>
\r
1799 /// <returns>a descriptor for this new field</returns>
\r
1800 public FieldDef AddField(string name, Type fType) {
\r
1801 FieldDef field = new FieldDef(name,fType);
\r
1802 fields.Add(field);
\r
1807 /// Add a field to this class
\r
1809 /// <param name="fAtts">attributes for this field</param>
\r
1810 /// <param name="name">field name</param>
\r
1811 /// <param name="fType">field type</param>
\r
1812 /// <returns>a descriptor for this new field</returns>
\r
1813 public FieldDef AddField(FieldAttr fAtts, string name, Type fType) {
\r
1814 FieldDef field = new FieldDef(fAtts,name,fType);
\r
1815 fields.Add(field);
\r
1820 /// Add a method to this class
\r
1822 /// <param name="name">method name</param>
\r
1823 /// <param name="retType">return type</param>
\r
1824 /// <param name="pars">parameters</param>
\r
1825 /// <returns>a descriptor for this new method</returns>
\r
1826 public MethodDef AddMethod(string name, Type retType, Param[] pars) {
\r
1827 // Console.WriteLine("Adding method " + name + " to class " + this.name);
\r
1828 MethodDef meth = new MethodDef(metaData,name,retType, pars);
\r
1829 methods.Add(meth);
\r
1834 /// Add a method to this class
\r
1836 /// <param name="mAtts">attributes for this method</param>
\r
1837 /// <param name="iAtts">implementation attributes for this method</param>
\r
1838 /// <param name="name">method name</param>
\r
1839 /// <param name="retType">return type</param>
\r
1840 /// <param name="pars">parameters</param>
\r
1841 /// <returns>a descriptor for this new method</returns>
\r
1842 public MethodDef AddMethod(MethAttr mAtts, ImplAttr iAtts, string name,
\r
1843 Type retType, Param[] pars) {
\r
1844 // Console.WriteLine("Adding method " + name + " to class " + this.name);
\r
1845 MethodDef meth = new MethodDef(metaData,mAtts,iAtts,name,retType,pars);
\r
1846 methods.Add(meth);
\r
1851 /// Add an event to this class
\r
1853 /// <param name="name">event name</param>
\r
1854 /// <param name="eType">event type</param>
\r
1855 /// <returns>a descriptor for this new event</returns>
\r
1856 public Event AddEvent(string name, Type eType) {
\r
1857 Event e = new Event(name,eType,this);
\r
1858 if (events == null) events = new ArrayList();
\r
1864 /// Add a property to this class
\r
1866 /// <param name="name">property name</param>
\r
1867 /// <param name="propType">property type</param>
\r
1868 /// <returns>a descriptor for this new property</returns>
\r
1869 public Property AddProperty(string name, Type retType, Type[] pars) {
\r
1870 Property p = new Property(name, retType, pars, this);
\r
1871 if (properties == null) properties = new ArrayList();
\r
1872 properties.Add(p);
\r
1878 /// Add a nested class to this class
\r
1880 /// <param name="attrSet">attributes for this nested class</param>
\r
1881 /// <param name="nsName">nested name space name</param>
\r
1882 /// <param name="name">nested class name</param>
\r
1883 /// <returns>a descriptor for this new nested class</returns>
\r
1884 public ClassDef AddNestedClass(TypeAttr attrSet, string nsName,
\r
1886 ClassDef nClass = new ClassDef(attrSet,nsName,name,metaData);
\r
1887 metaData.AddToTable(MDTable.TypeDef,nClass);
\r
1888 metaData.AddToTable(MDTable.NestedClass,new MapElem(nClass,Row,MDTable.TypeDef));
\r
1889 nClass.parentClass = this;
\r
1894 /// Add a nested class to this class
\r
1896 /// <param name="attrSet">attributes for this nested class</param>
\r
1897 /// <param name="nsName">nested name space name</param>
\r
1898 /// <param name="name">nested class name</param>
\r
1899 /// <param name="sType">super type of this nested class</param>
\r
1900 /// <returns>a descriptor for this new nested class</returns>
\r
1901 public ClassDef AddNestedClass(TypeAttr attrSet, string nsName,
\r
1902 string name, Class sType) {
\r
1903 ClassDef nClass = new ClassDef(attrSet,nsName,name,metaData);
\r
1904 nClass.SetSuper(sType);
\r
1905 metaData.AddToTable(MDTable.TypeDef,nClass);
\r
1906 metaData.AddToTable(MDTable.NestedClass,
\r
1907 new MapElem(nClass,Row,MDTable.TypeDef));
\r
1908 nClass.parentClass = this;
\r
1913 /// Add layout information for this class. This class must have the
\r
1914 /// sequential or explicit attribute.
\r
1916 /// <param name="packSize">packing size (.pack)</param>
\r
1917 /// <param name="classSize">class size (.size)</param>
\r
1918 public void AddLayoutInfo (int packSize, int classSize) {
\r
1919 layout = new ClassLayout(packSize,classSize,this);
\r
1923 /// Use a method as the implementation for another method (.override)
\r
1925 /// <param name="decl">the method to be overridden</param>
\r
1926 /// <param name="body">the implementation to be used</param>
\r
1927 public void AddMethodOverride(Method decl, Method body) {
\r
1928 metaData.AddToTable(MDTable.MethodImpl,new MethodImpl(this,decl,body));
\r
1932 /// Add security to this class NOT YET IMPLEMENTED
\r
1934 /// <param name="permissionSet"></param>
\r
1935 public void AddSecurity(byte[] permissionSet) {
\r
1936 throw(new NotYetImplementedException("Class security "));
\r
1937 //flags |= HasSecurity;
\r
1938 // securityActions = permissionSet;
\r
1941 //public void AddLineInfo(int row, int col) { }
\r
1943 internal void CheckTypeIndex() {
\r
1944 if (typeIndexChecked) return;
\r
1945 if (!(superType is ClassRef))
\r
1946 ((ClassDef)superType).CheckTypeIndex();
\r
1947 typeIndex = superType.GetTypeIndex();
\r
1948 typeIndexChecked = true;
\r
1951 internal sealed override void BuildTables(MetaData md) {
\r
1953 if ((flags & (uint)TypeAttr.Interface) != 0) { superType = null; }
\r
1954 // Console.WriteLine("Building tables for " + name);
\r
1955 if (layout != null) md.AddToTable(MDTable.ClassLayout,layout);
\r
1956 // Console.WriteLine("adding methods " + methods.Count);
\r
1957 methodIx = md.TableIndex(MDTable.Method);
\r
1958 for (int i=0; i < methods.Count; i++) {
\r
1959 md.AddToTable(MDTable.Method,(MetaDataElement)methods[i]);
\r
1960 ((MethodDef)methods[i]).BuildTables(md);
\r
1962 // Console.WriteLine("adding fields");
\r
1963 fieldIx = md.TableIndex(MDTable.Field);
\r
1964 for (int i=0; i < fields.Count; i++) {
\r
1965 md.AddToTable(MDTable.Field,(MetaDataElement)fields[i]);
\r
1966 ((FieldDef)fields[i]).BuildTables(md);
\r
1968 // Console.WriteLine("adding events and properties");
\r
1969 if (events != null) {
\r
1970 for (int i=0; i < events.Count; i++) {
\r
1971 md.AddToTable(MDTable.Event,(Event)events[i]);
\r
1972 ((Event)events[i]).BuildTables(md);
\r
1974 md.AddToTable(MDTable.EventMap,
\r
1975 new MapElem(this,((Event)events[0]).Row,MDTable.Event));
\r
1977 if (properties != null) {
\r
1978 for (int i=0; i < properties.Count; i++) {
\r
1979 md.AddToTable(MDTable.Property,(Property)properties[i]);
\r
1980 ((Property)properties[i]).BuildTables(md);
\r
1982 md.AddToTable(MDTable.PropertyMap,new MapElem(this,
\r
1983 ((Property)properties[0]).Row,MDTable.Property));
\r
1985 DoCustomAttributes (md);
\r
1986 // Console.WriteLine("End of building tables");
\r
1990 internal sealed override uint Size(MetaData md) {
\r
1991 return 4 + 2 * md.StringsIndexSize() +
\r
1992 md.CodedIndexSize(CIx.TypeDefOrRef) +
\r
1993 md.TableIndexSize(MDTable.Field) +
\r
1994 md.TableIndexSize(MDTable.Method);
\r
1997 internal sealed override void Write(FileImage output) {
\r
1998 output.Write(flags);
\r
1999 output.StringsIndex(nameIx);
\r
2000 output.StringsIndex(nameSpaceIx);
\r
2001 //if (superType != null)
\r
2002 // Console.WriteLine("getting coded index for superType of " + name + " = " + superType.GetCodedIx(CIx.TypeDefOrRef));
\r
2003 output.WriteCodedIndex(CIx.TypeDefOrRef,superType);
\r
2004 output.WriteIndex(MDTable.Field,fieldIx);
\r
2005 output.WriteIndex(MDTable.Method,methodIx);
\r
2008 internal sealed override uint TypeDefOrRefToken() {
\r
2014 internal sealed override void TypeSig(MemoryStream sig) {
\r
2015 if (!typeIndexChecked) CheckTypeIndex();
\r
2016 sig.WriteByte(GetTypeIndex());
\r
2017 MetaData.CompressNum(TypeDefOrRefToken(),sig);
\r
2020 internal sealed override uint GetCodedIx(CIx code) {
\r
2022 case (CIx.TypeDefOrRef) : return 0;
\r
2023 case (CIx.HasCustomAttr) : return 3;
\r
2024 case (CIx.HasDeclSecurity) : return 0;
\r
2025 case (CIx.TypeOrMethodDef) : return 0;
\r
2031 /**************************************************************************/
\r
2033 /// Layout information for a class (.class [sequential | explicit])
\r
2035 internal class ClassLayout : MetaDataElement
\r
2038 ushort packSize = 0;
\r
2039 uint classSize = 0;
\r
2041 internal ClassLayout(int pack, int cSize, ClassDef par) {
\r
2042 packSize = (ushort)pack;
\r
2043 classSize = (uint)cSize;
\r
2045 tabIx = MDTable.ClassLayout;
\r
2048 internal sealed override uint Size(MetaData md) {
\r
2049 return 6 + md.TableIndexSize(MDTable.TypeDef);
\r
2052 internal sealed override void Write(FileImage output) {
\r
2053 output.Write(packSize);
\r
2054 output.Write(classSize);
\r
2055 output.WriteIndex(MDTable.TypeDef,parent.Row);
\r
2059 /**************************************************************************/
\r
2061 /// Descriptor for a class/interface declared in another module of THIS
\r
2062 /// assembly, or in another assembly.
\r
2064 public class ClassRef : Class
\r
2066 protected ResolutionScope parent;
\r
2067 ExternClass externClass;
\r
2068 protected MetaData metaData;
\r
2070 internal ClassRef(string nsName, string name, MetaData md) : base(nsName, name, md) {
\r
2072 tabIx = MDTable.TypeRef;
\r
2076 /// Add a method to this class
\r
2078 /// <param name="name">method name</param>
\r
2079 /// <param name="retType">return type</param>
\r
2080 /// <param name="pars">parameter types</param>
\r
2081 /// <returns>a descriptor for this method</returns>
\r
2082 public MethodRef AddMethod(string name, Type retType, Type[] pars) {
\r
2083 MethodRef meth = new MethodRef(this,name,retType,pars,false,null);
\r
2084 metaData.AddToTable(MDTable.MemberRef,meth);
\r
2089 /// Add a method to this class
\r
2091 /// <param name="name">method name</param>
\r
2092 /// <param name="retType">return type</param>
\r
2093 /// <param name="pars">parameter types</param>
\r
2094 /// <returns>a descriptor for this method</returns>
\r
2095 public MethodRef AddVarArgMethod(string name, Type retType,
\r
2096 Type[] pars, Type[] optPars) {
\r
2097 MethodRef meth = new MethodRef(this,name,retType,pars,true,optPars);
\r
2098 metaData.AddToTable(MDTable.MemberRef,meth);
\r
2103 /// Add a field to this class
\r
2105 /// <param name="name">field name</param>
\r
2106 /// <param name="fType">field type</param>
\r
2107 /// <returns>a descriptor for this field</returns>
\r
2108 public FieldRef AddField(string name, Type fType) {
\r
2109 FieldRef field = new FieldRef(this,name,fType);
\r
2110 metaData.AddToTable(MDTable.MemberRef,field);
\r
2114 internal void SetParent(ResolutionScope par) {
\r
2118 internal override string TypeName() {
\r
2119 if ((parent != null) && (parent is AssemblyRef))
\r
2120 return (nameSpace + "." + name + ", " + ((AssemblyRef)parent).TypeName());
\r
2122 return (nameSpace + name);
\r
2125 internal sealed override uint Size(MetaData md) {
\r
2126 return md.CodedIndexSize(CIx.ResolutionScope) + 2 *
\r
2127 md.StringsIndexSize();
\r
2130 internal sealed override void Write(FileImage output) {
\r
2131 output.WriteCodedIndex(CIx.ResolutionScope,parent);
\r
2132 output.StringsIndex(nameIx);
\r
2133 output.StringsIndex(nameSpaceIx);
\r
2136 internal override sealed uint TypeDefOrRefToken() {
\r
2138 cIx = (cIx << 2) | 0x1;
\r
2142 internal override void TypeSig(MemoryStream sig) {
\r
2143 sig.WriteByte(GetTypeIndex());
\r
2144 MetaData.CompressNum(TypeDefOrRefToken(),sig);
\r
2147 internal sealed override uint GetCodedIx(CIx code) {
\r
2149 case (CIx.TypeDefOrRef) : return 1;
\r
2150 case (CIx.HasCustomAttr) : return 2;
\r
2151 case (CIx.MemberRefParent) : return 1;
\r
2152 case (CIx.ResolutionScope) : return 3;
\r
2158 /**************************************************************************/
\r
2160 public class ExternClassRef : ClassRef {
\r
2162 ExternClass externClass;
\r
2164 internal ExternClassRef(TypeAttr attrs, string nsName, string name,
\r
2165 FileRef declFile, MetaData md) : base(nsName,name,md) {
\r
2166 externClass = new ExternClass(attrs,nameSpaceIx,nameIx,declFile);
\r
2167 metaData.AddToTable(MDTable.ExportedType,externClass);
\r
2170 internal ExternClassRef(string name, MetaData md) : base(null,name,md) {
\r
2173 public ClassRef AddNestedClass(TypeAttr attrs, string name) {
\r
2174 ExternClassRef nestedClass = new ExternClassRef(name,metaData);
\r
2175 externClass = new ExternClass(attrs,0,nameIx,this.externClass);
\r
2176 metaData.AddToTable(MDTable.ExportedType,externClass);
\r
2177 return nestedClass;
\r
2181 /**************************************************************************/
\r
2183 /// Descriptor for a constant value
\r
2185 public abstract class Constant {
\r
2186 protected uint size = 0;
\r
2187 protected Type type;
\r
2188 protected uint blobIndex;
\r
2189 protected bool addedToBlobHeap = false;
\r
2191 internal Constant() { }
\r
2193 internal virtual uint GetBlobIndex(MetaData md) { return 0; }
\r
2195 internal uint GetSize() { return size; }
\r
2197 internal byte GetTypeIndex() { return type.GetTypeIndex(); }
\r
2199 internal virtual void Write(BinaryWriter bw) { }
\r
2203 /// Descriptor for a constant value
\r
2205 public abstract class DataConstant : Constant {
\r
2206 private uint dataOffset = 0;
\r
2208 internal DataConstant() { }
\r
2210 public uint DataOffset {
\r
2211 get { return dataOffset; }
\r
2212 set { dataOffset = value; }
\r
2218 /// Boolean constant
\r
2220 public class BoolConst : Constant {
\r
2224 /// Create a new boolean constant with the value "val"
\r
2226 /// <param name="val">value of this boolean constant</param>
\r
2227 public BoolConst(bool val) {
\r
2230 type = PrimitiveType.Boolean;
\r
2233 internal sealed override uint GetBlobIndex(MetaData md) {
\r
2234 if (!addedToBlobHeap) {
\r
2235 if (val) blobIndex = md.AddToBlobHeap((sbyte)1);
\r
2236 else blobIndex = md.AddToBlobHeap((sbyte)0);
\r
2237 addedToBlobHeap = true;
\r
2242 internal sealed override void Write(BinaryWriter bw) {
\r
2243 if (val) bw.Write((sbyte)1);
\r
2244 else bw.Write((sbyte)0);
\r
2249 public class ByteArrConst : DataConstant {
\r
2252 public ByteArrConst(byte[] val) {
\r
2254 size = (uint)val.Length;
\r
2257 internal sealed override uint GetBlobIndex(MetaData md) {
\r
2258 if (!addedToBlobHeap) {
\r
2259 blobIndex = md.AddToBlobHeap(val);
\r
2260 addedToBlobHeap = true;
\r
2265 internal sealed override void Write(BinaryWriter bw) {
\r
2271 public class CharConst : Constant {
\r
2274 public CharConst(char val) {
\r
2277 type = PrimitiveType.Char;
\r
2280 internal sealed override uint GetBlobIndex(MetaData md) {
\r
2281 if (!addedToBlobHeap) {
\r
2282 blobIndex = md.AddToBlobHeap(val);
\r
2283 addedToBlobHeap = true;
\r
2288 internal sealed override void Write(BinaryWriter bw) {
\r
2294 public class FloatConst : DataConstant {
\r
2297 public FloatConst(float val) {
\r
2300 type = PrimitiveType.Float32;
\r
2303 internal sealed override uint GetBlobIndex(MetaData md) {
\r
2304 if (!addedToBlobHeap) {
\r
2305 blobIndex = md.AddToBlobHeap(val);
\r
2306 addedToBlobHeap = true;
\r
2311 internal sealed override void Write(BinaryWriter bw) {
\r
2317 public class DoubleConst : DataConstant {
\r
2320 public DoubleConst(double val) {
\r
2323 type = PrimitiveType.Float64;
\r
2326 internal sealed override uint GetBlobIndex(MetaData md) {
\r
2327 if (!addedToBlobHeap) {
\r
2328 blobIndex = md.AddToBlobHeap(val);
\r
2329 addedToBlobHeap = true;
\r
2334 internal sealed override void Write(BinaryWriter bw) {
\r
2340 public class IntConst : DataConstant {
\r
2343 public IntConst(sbyte val) {
\r
2346 type = PrimitiveType.Int8;
\r
2349 public IntConst(short val) {
\r
2352 type = PrimitiveType.Int16;
\r
2355 public IntConst(int val) {
\r
2358 type = PrimitiveType.Int32;
\r
2361 public IntConst(long val) {
\r
2364 type = PrimitiveType.Int64;
\r
2367 internal sealed override uint GetBlobIndex(MetaData md) {
\r
2368 if (!addedToBlobHeap) {
\r
2370 case (1) : blobIndex = md.AddToBlobHeap((sbyte)val); break;
\r
2371 case (2) : blobIndex = md.AddToBlobHeap((short)val); break;
\r
2372 case (4) : blobIndex = md.AddToBlobHeap((int)val); break;
\r
2373 default : blobIndex = md.AddToBlobHeap(val); break;
\r
2375 addedToBlobHeap = true;
\r
2380 internal sealed override void Write(BinaryWriter bw) {
\r
2382 case (1) : bw.Write((sbyte)val); break;
\r
2383 case (2) : bw.Write((short)val); break;
\r
2384 case (4) : bw.Write((int)val); break;
\r
2385 default : bw.Write(val); break;
\r
2391 public class UIntConst : Constant {
\r
2394 public UIntConst(sbyte val) {
\r
2397 type = PrimitiveType.UInt8;
\r
2399 public UIntConst(short val) {
\r
2402 type = PrimitiveType.UInt16;
\r
2404 public UIntConst(int val) {
\r
2407 type = PrimitiveType.UInt32;
\r
2409 public UIntConst(long val) {
\r
2412 type = PrimitiveType.UInt64;
\r
2415 internal sealed override uint GetBlobIndex(MetaData md) {
\r
2416 if (!addedToBlobHeap) {
\r
2418 case (1) : blobIndex = md.AddToBlobHeap((sbyte)val); break;
\r
2419 case (2) : blobIndex = md.AddToBlobHeap((short)val); break;
\r
2420 case (4) : blobIndex = md.AddToBlobHeap((int)val); break;
\r
2421 default : blobIndex = md.AddToBlobHeap(val); break;
\r
2423 addedToBlobHeap = true;
\r
2428 internal sealed override void Write(BinaryWriter bw) {
\r
2430 case (1) : bw.Write((sbyte)val); break;
\r
2431 case (2) : bw.Write((short)val); break;
\r
2432 case (4) : bw.Write((int)val); break;
\r
2433 default : bw.Write(val); break;
\r
2439 public class StringConst : DataConstant {
\r
2442 public StringConst(string val) {
\r
2444 size = (uint)val.Length; // need to add null ??
\r
2445 type = PrimitiveType.String;
\r
2448 internal sealed override uint GetBlobIndex(MetaData md) {
\r
2449 if (!addedToBlobHeap) {
2450 byte [] b = Encoding.Unicode.GetBytes (val);
2451 blobIndex = md.AddToBlobHeap(b);
\r
2452 addedToBlobHeap = true;
\r
2457 internal sealed override void Write(BinaryWriter bw) {
\r
2463 public class NullConst : Constant {
\r
2465 public NullConst() {
\r
2467 type = PrimitiveType.Class;
\r
2470 internal sealed override uint GetBlobIndex(MetaData md) {
\r
2471 if (!addedToBlobHeap) {
\r
2472 blobIndex = md.AddToBlobHeap((int)0);
\r
2473 addedToBlobHeap = true;
\r
2478 internal sealed override void Write(BinaryWriter bw) {
\r
2479 bw.Write((int)0);
\r
2484 public class AddressConstant : DataConstant {
\r
2485 DataConstant data;
\r
2487 public AddressConstant(DataConstant dConst) {
\r
2490 type = PrimitiveType.TypedRef;
\r
2493 internal sealed override void Write(BinaryWriter bw) {
\r
2494 ((FileImage)bw).WriteDataRVA(data.DataOffset);
\r
2499 public class RepeatedConstant : DataConstant {
\r
2500 DataConstant data;
\r
2503 public RepeatedConstant(DataConstant dConst, int repeatCount) {
\r
2505 repCount = (uint)repeatCount;
\r
2506 int[] sizes = new int[1];
\r
2507 sizes[0] = repeatCount;
\r
2508 type = new BoundArray(type,1,sizes);
\r
2509 size = data.GetSize() * repCount;
\r
2512 internal sealed override void Write(BinaryWriter bw) {
\r
2513 for (int i=0; i < repCount; i++) {
\r
2520 public class ArrayConstant : DataConstant {
\r
2521 DataConstant[] dataVals;
\r
2523 public ArrayConstant(DataConstant[] dVals) {
\r
2525 for (int i=0; i < dataVals.Length; i++) {
\r
2526 size += dataVals[i].GetSize();
\r
2530 internal sealed override void Write(BinaryWriter bw) {
\r
2531 for (int i=0; i < dataVals.Length; i++) {
\r
2532 dataVals[i].Write(bw);
\r
2538 public class ClassType : Constant {
\r
2542 public ClassType(string className) {
\r
2544 type = PrimitiveType.ClassType;
\r
2547 public ClassType(Class classDesc) {
\r
2549 type = PrimitiveType.ClassType;
\r
2552 internal override void Write(BinaryWriter bw) {
\r
2553 if (name == null) name = desc.TypeName();
\r
2561 /**************************************************************************/
\r
2563 /// Summary description for ConstantElem.
\r
2565 internal class ConstantElem : MetaDataElement
\r
2567 MetaDataElement parent;
\r
2571 internal ConstantElem(MetaDataElement parent, Constant val) {
\r
2572 this.parent = parent;
\r
2574 tabIx = MDTable.Constant;
\r
2577 internal sealed override void BuildTables(MetaData md) {
\r
2579 valIx = cValue.GetBlobIndex(md);
\r
2583 internal void AddToBlob(BinaryWriter bw) {
\r
2587 internal sealed override uint Size(MetaData md) {
\r
2588 return 2 + md.CodedIndexSize(CIx.HasConst) + md.BlobIndexSize();
\r
2591 internal sealed override void Write(FileImage output) {
\r
2592 output.Write(cValue.GetTypeIndex());
\r
2593 output.Write((byte)0);
\r
2594 output.WriteCodedIndex(CIx.HasConst,parent);
\r
2595 output.BlobIndex(valIx);
\r
2599 /**************************************************************************/
\r
2601 /// Descriptor for a Custom Attribute (.custom)
\r
2604 public class CustomAttribute : MetaDataElement
\r
2606 private static readonly ushort prolog = 0x0001;
\r
2607 MetaDataElement parent;
\r
2612 ushort numNamed = 0;
\r
2613 ArrayList names, vals;
\r
2615 internal CustomAttribute(MetaDataElement paren, Method constrType,
\r
2618 type = constrType;
\r
2620 tabIx = MDTable.CustomAttribute;
\r
2621 throw(new NotYetImplementedException("Custom Attributes "));
\r
2624 internal CustomAttribute(MetaDataElement paren, Method constrType,
\r
2627 type = constrType;
\r
2628 tabIx = MDTable.CustomAttribute;
\r
2632 public void AddFieldOrProp(string name, Constant val) {
\r
2633 if (numNamed == 0) {
\r
2634 names = new ArrayList();
\r
2635 vals = new ArrayList();
\r
2641 internal sealed override void BuildTables(MetaData md) {
\r
2642 BinaryWriter bw = new BinaryWriter(new MemoryStream());
\r
2643 bw.Write((ushort)1);
\r
2644 md.AddToTable(MDTable.CustomAttribute, this);
\r
2645 MemoryStream str = (MemoryStream)bw.BaseStream;
\r
2646 valIx = md.AddToBlobHeap(str.ToArray());
\r
2649 internal sealed override uint Size(MetaData md) {
\r
2650 return md.CodedIndexSize(CIx.HasCustomAttr) + md.CodedIndexSize(CIx.CustomAttributeType) + md.BlobIndexSize();
\r
2653 internal sealed override void Write(FileImage output) {
\r
2654 output.WriteCodedIndex(CIx.HasCustomAttr,parent);
\r
2655 output.WriteCodedIndex(CIx.CustomAttributeType,type);
\r
2656 output.BlobIndex(valIx);
\r
2660 /**************************************************************************/
\r
2662 /// Descriptor for a custom modifier of a type (modopt or modreq)
\r
2665 public class CustomModifiedType : Type
\r
2671 /// Create a new custom modifier for a type
\r
2673 /// <param name="type">the type to be modified</param>
\r
2674 /// <param name="cmod">the modifier</param>
\r
2675 /// <param name="cmodType">the type reference to be associated with the type</param>
\r
2676 public CustomModifiedType(Type type, CustomModifier cmod, Class cmodType)
\r
2677 : base((byte)cmod) {
\r
2679 this.cmodType = cmodType;
\r
2682 internal sealed override void TypeSig(MemoryStream str) {
\r
2683 str.WriteByte(typeIndex);
\r
2684 MetaData.CompressNum(cmodType.TypeDefOrRefToken(),str);
\r
2685 type.TypeSig(str);
\r
2689 /**************************************************************************/
\r
2691 /// Descriptor for security permissions for a class or a method NOT YET IMPLEMENTED
\r
2694 public class DeclSecurity : MetaDataElement
\r
2697 MetaDataElement parent;
\r
2698 uint permissionIx;
\r
2700 internal DeclSecurity(MetaDataElement paren, ushort act) {
\r
2703 tabIx = MDTable.DeclSecurity;
\r
2704 throw(new NotYetImplementedException("Security "));
\r
2707 internal sealed override uint Size(MetaData md) {
\r
2708 return 2 + md.CodedIndexSize(CIx.HasDeclSecurity) + md.BlobIndexSize();
\r
2711 internal sealed override void BuildTables(MetaData md) {
\r
2713 // add permission to blob heap
\r
2717 internal sealed override void Write(FileImage output) {
\r
2718 output.Write(action);
\r
2719 output.WriteCodedIndex(CIx.HasDeclSecurity,parent);
\r
2720 output.BlobIndex(permissionIx);
\r
2724 /**************************************************************************/
\r
2726 /// Descriptor for an event
\r
2728 public class Event : Feature
\r
2732 internal Event(string name, Type eType, ClassDef parent)
\r
2733 : base(name, parent) {
\r
2734 eventType = eType;
\r
2735 tabIx = MDTable.Event;
\r
2739 /// Add the addon method to this event
\r
2741 /// <param name="addon">the addon method</param>
\r
2742 public void AddAddon(MethodDef addon) {
\r
2743 AddMethod(addon,MethodType.AddOn);
\r
2747 /// Add the removeon method to this event
\r
2749 /// <param name="removeOn">the removeon method</param>
\r
2750 public void AddRemoveOn(MethodDef removeOn) {
\r
2751 AddMethod(removeOn,MethodType.RemoveOn);
\r
2755 /// Add the fire method to this event
\r
2757 /// <param name="fire">the fire method</param>
\r
2758 public void AddFire(MethodDef fire) {
\r
2759 AddMethod(fire,MethodType.Fire);
\r
2763 /// Add another method to this event
\r
2765 /// <param name="other">the method to be added</param>
\r
2766 public void AddOther(MethodDef other) {
\r
2767 AddMethod(other,MethodType.Other);
\r
2770 internal sealed override void BuildTables(MetaData md) {
\r
2772 nameIx = md.AddToStringsHeap(name);
\r
2773 for (int i=0; i < tide; i++) {
\r
2774 md.AddToTable(MDTable.MethodSemantics,methods[i]);
\r
2779 internal sealed override uint Size(MetaData md) {
\r
2780 return 2 + md.StringsIndexSize() + md.CodedIndexSize(CIx.TypeDefOrRef);
\r
2783 internal sealed override void Write(FileImage output) {
\r
2784 output.Write(flags);
\r
2785 output.StringsIndex(nameIx);
\r
2786 output.WriteCodedIndex(CIx.TypeDefOrRef,eventType);
\r
2789 internal sealed override uint GetCodedIx(CIx code) {
\r
2791 case (CIx.HasCustomAttr) : return 10;
\r
2792 case (CIx.HasSemantics) : return 0;
\r
2798 /**************************************************************************/
\r
2800 /// Descriptor for a class defined in another module of THIS assembly
\r
2801 /// and exported (.class extern)
\r
2804 internal class ExternClass : Class
\r
2806 MetaDataElement parent;
\r
2809 internal ExternClass(TypeAttr attr, uint nsIx, uint nIx,
\r
2810 MetaDataElement paren) : base(nsIx,nIx) {
\r
2811 flags = (uint)attr;
\r
2813 tabIx = MDTable.ExportedType;
\r
2816 internal sealed override uint Size(MetaData md) {
\r
2817 return 8 + 2* md.StringsIndexSize() + md.CodedIndexSize(CIx.Implementation);
\r
2820 internal sealed override void Write(FileImage output) {
\r
2821 output.Write(flags);
\r
2823 output.StringsIndex(nameIx);
\r
2824 output.StringsIndex(nameSpaceIx);
\r
2825 output.WriteCodedIndex(CIx.Implementation,parent);
\r
2828 internal sealed override uint GetCodedIx(CIx code) {
\r
2830 case (CIx.HasCustomAttr) : return 17;
\r
2831 case (CIx.Implementation) : return 2;
\r
2837 /**************************************************************************/
\r
2839 /// Base class for Event and Property descriptors
\r
2842 public class Feature : MetaDataElement
\r
2844 internal enum MethodType : ushort { Setter = 0x01, Getter, Other = 0x04, AddOn = 0x08,
\r
2845 RemoveOn = 0x10, Fire = 0x20 }
\r
2847 private static readonly int INITSIZE = 5;
\r
2848 private static readonly ushort specialName = 0x200;
\r
2849 private static readonly ushort rtSpecialName = 0x400;
\r
2851 protected ClassDef parent;
\r
2852 protected ushort flags = 0;
\r
2853 protected string name;
\r
2854 protected int tide = 0;
\r
2855 protected uint nameIx;
\r
2856 protected MethodSemantics[] methods = new MethodSemantics[INITSIZE];
\r
2858 internal Feature(string name, ClassDef par) {
\r
2863 internal void AddMethod(MethodDef meth, MethodType mType) {
\r
2864 if (tide >= methods.Length) {
\r
2865 int len = methods.Length;
\r
2866 MethodSemantics[] mTmp = methods;
\r
2867 methods = new MethodSemantics[len * 2];
\r
2868 for (int i=0; i < len; i++) {
\r
2869 methods[i] = mTmp[i];
\r
2872 methods[tide++] = new MethodSemantics(mType,meth,this);
\r
2876 /// Set the specialName attribute for this Event or Property
\r
2878 public void SetSpecialName() {
\r
2879 flags |= specialName;
\r
2883 /// Set the RTSpecialName attribute for this Event or Property
\r
2885 public void SetRTSpecialName() {
\r
2886 flags |= rtSpecialName;
\r
2890 /*****************************************************************************/
\r
2892 /// Descriptor for a field of a class
\r
2895 public abstract class Field : Member
\r
2897 protected static readonly byte FieldSig = 0x6;
\r
2899 protected Type type;
\r
2901 internal Field(string pfName, Type pfType) : base(pfName)
\r
2907 /**************************************************************************/
\r
2909 /// Descriptor for a field defined in a class of THIS assembly/module
\r
2911 public class FieldDef : Field
\r
2913 //private static readonly uint PInvokeImpl = 0x2000;
\r
2914 private static readonly ushort HasFieldMarshal = 0x1000;
\r
2915 private static readonly ushort HasFieldRVA = 0x100;
\r
2916 private static readonly ushort HasDefault = 0x8000;
2919 ConstantElem constVal;
\r
2920 FieldLayout layout;
\r
2921 FieldMarshal marshalInfo;
\r
2924 internal FieldDef(string name, Type fType) : base(name,fType) {
\r
2925 tabIx = MDTable.Field;
\r
2928 internal FieldDef(FieldAttr attrSet, string name, Type fType) : base(name, fType) {
\r
2929 flags = (ushort)attrSet;
\r
2930 tabIx = MDTable.Field;
\r
2934 /// Add an attribute(s) to this field
\r
2936 /// <param name="fa">the attribute(s) to be added</param>
\r
2937 public void AddFieldAttr(FieldAttr fa) {
\r
2938 flags |= (ushort)fa;
\r
2942 /// Add a value for this field
\r
2944 /// <param name="val">the value for the field</param>
\r
2945 public void AddValue(Constant val) {
\r
2946 constVal = new ConstantElem(this,val);
\r
2947 flags |= HasDefault;
2951 /// Add an initial value for this field (at dataLabel) (.data)
\r
2953 /// <param name="val">the value for the field</param>
\r
2954 /// <param name="repeatVal">the number of repetitions of this value</param>
\r
2955 public void AddDataValue(DataConstant val) {
\r
2956 flags |= HasFieldRVA;
\r
2957 rva = new FieldRVA(this,val);
\r
2961 /// Set the offset of the field. Used for sequential or explicit classes.
\r
2962 /// (.field [offs])
\r
2964 /// <param name="offs">field offset</param>
\r
2965 public void SetOffset(uint offs) {
\r
2966 layout = new FieldLayout(this,offs);
\r
2970 /// Set the marshalling info for a field
\r
2972 /// <param name="mInf"></param>
\r
2973 public void SetMarshalInfo(NativeType marshallType) {
\r
2974 flags |= HasFieldMarshal;
\r
2975 marshalInfo = new FieldMarshal(this,marshallType);
\r
2978 internal sealed override void BuildTables(MetaData md) {
\r
2980 nameIx = md.AddToStringsHeap(name);
\r
2981 MemoryStream sig = new MemoryStream();
\r
2982 sig.WriteByte(FieldSig);
\r
2983 type.TypeSig(sig);
\r
2984 sigIx = md.AddToBlobHeap(sig.ToArray());
\r
2985 if (rva != null) {
\r
2986 md.AddToTable(MDTable.FieldRVA,rva);
\r
2987 rva.BuildTables(md);
\r
2988 } else if (constVal != null) {
\r
2989 md.AddToTable(MDTable.Constant,constVal);
\r
2990 constVal.BuildTables(md);
\r
2992 if (layout != null) md.AddToTable(MDTable.FieldLayout,layout);
\r
2993 if (marshalInfo != null) {
\r
2994 md.AddToTable(MDTable.FieldMarshal,marshalInfo);
\r
2995 marshalInfo.BuildTables(md);
\r
3000 internal sealed override uint Size(MetaData md) {
\r
3001 return 2 + md.StringsIndexSize() + md.BlobIndexSize();
\r
3004 internal sealed override void Write(FileImage output) {
\r
3005 output.Write(flags);
\r
3006 output.StringsIndex(nameIx);
\r
3007 output.BlobIndex(sigIx);
\r
3010 internal sealed override uint GetCodedIx(CIx code) {
\r
3012 case (CIx.HasConst) : return 0;
\r
3013 case (CIx.HasCustomAttr) : return 1;
\r
3014 case (CIx.HasFieldMarshal) : return 0;
\r
3015 case (CIx.MemberForwarded) : return 0;
\r
3021 /**************************************************************************/
\r
3023 /// Descriptor for layout information for a field
\r
3026 public class FieldLayout : MetaDataElement
\r
3031 internal FieldLayout(Field field, uint offset) {
\r
3032 this.field = field;
\r
3033 this.offset = offset;
\r
3034 tabIx = MDTable.FieldLayout;
\r
3037 internal sealed override uint Size(MetaData md) {
\r
3038 return 4 + md.TableIndexSize(MDTable.Field);
\r
3041 internal sealed override void Write(FileImage output) {
\r
3042 output.Write(offset);
\r
3043 output.WriteIndex(MDTable.Field,field.Row);
\r
3047 /*****************************************************************************/
\r
3049 /// Marshalling information for a field or param
\r
3051 public class FieldMarshal : MetaDataElement
\r
3053 MetaDataElement field;
\r
3057 internal FieldMarshal(MetaDataElement field, NativeType nType) {
\r
3058 this.field = field;
\r
3060 tabIx = MDTable.FieldMarshal;
\r
3063 internal sealed override void BuildTables(MetaData md) {
\r
3065 ntIx = md.AddToBlobHeap(nt.ToBlob());
\r
3069 internal sealed override uint Size(MetaData md) {
\r
3070 return md.CodedIndexSize(CIx.HasFieldMarshal) + md.BlobIndexSize();
\r
3073 internal sealed override void Write(FileImage output) {
\r
3074 output.WriteCodedIndex(CIx.HasFieldMarshal,field);
\r
3075 output.BlobIndex(ntIx);
\r
3079 /**************************************************************************/
\r
3081 /// Descriptor for a field of a class defined in another assembly/module
\r
3083 public class FieldRef : Field
\r
3085 MetaDataElement parent;
\r
3087 internal FieldRef(MetaDataElement paren, string name, Type fType) : base(name, fType) {
\r
3091 internal sealed override void BuildTables(MetaData md) {
\r
3093 nameIx = md.AddToStringsHeap(name);
\r
3094 MemoryStream sig = new MemoryStream();
\r
3095 sig.WriteByte(FieldSig);
\r
3096 type.TypeSig(sig);
\r
3097 sigIx = md.AddToBlobHeap(sig.ToArray());
\r
3101 internal sealed override uint Size(MetaData md) {
\r
3102 return md.CodedIndexSize(CIx.MemberRefParent) + md.StringsIndexSize() + md.BlobIndexSize();
\r
3105 internal sealed override void Write(FileImage output) {
\r
3106 output.WriteCodedIndex(CIx.MemberRefParent,parent);
\r
3107 output.StringsIndex(nameIx);
\r
3108 output.BlobIndex(sigIx);
\r
3111 internal sealed override uint GetCodedIx(CIx code) { return 6; }
\r
3114 /**************************************************************************/
\r
3116 /// Descriptor for the address of a field's value in the PE file
\r
3118 public class FieldRVA : MetaDataElement
\r
3121 DataConstant data;
\r
3123 internal FieldRVA(Field field, DataConstant data) {
\r
3124 this.field = field;
\r
3126 tabIx = MDTable.FieldRVA;
\r
3129 internal sealed override void BuildTables(MetaData md) {
\r
3135 internal sealed override uint Size(MetaData md) {
\r
3136 return 4 + md.TableIndexSize(MDTable.Field);
\r
3139 internal sealed override void Write(FileImage output) {
\r
3140 output.WriteDataRVA(data.DataOffset);
\r
3141 output.WriteIndex(MDTable.Field,field.Row);
\r
3145 /**************************************************************************/
\r
3147 /// Image for a PEFile
\r
3148 /// File Structure
\r
3149 /// DOS Header (128 bytes)
\r
3150 /// PE Signature ("PE\0\0")
\r
3151 /// PEFileHeader (20 bytes)
\r
3152 /// PEOptionalHeader (224 bytes)
\r
3153 /// SectionHeaders (40 bytes * NumSections)
\r
3155 /// Sections .text (always present - contains metadata)
\r
3156 /// .sdata (contains any initialised data in the file - may not be present)
\r
3157 /// (for ilams /debug this contains the Debug table)
\r
3158 /// .reloc (always present - in pure CIL only has one fixup)
\r
3159 /// others??? c# produces .rsrc section containing a Resource Table
\r
3162 /// IAT (single entry 8 bytes for pure CIL)
\r
3163 /// CLIHeader (72 bytes)
\r
3164 /// CIL instructions for all methods (variable size)
\r
3166 /// Root (20 bytes + UTF-8 Version String + quad align padding)
\r
3167 /// StreamHeaders (8 bytes + null terminated name string + quad align padding)
\r
3169 /// #~ (always present - holds metadata tables)
\r
3170 /// #Strings (always present - holds identifier strings)
\r
3171 /// #US (Userstring heap)
\r
3172 /// #Blob (signature blobs)
\r
3173 /// #GUID (guids for assemblies or Modules)
\r
3174 /// ImportTable (40 bytes)
\r
3175 /// ImportLookupTable(8 bytes) (same as IAT for standard CIL files)
\r
3176 /// Hint/Name Tables with entry "_CorExeMain" for .exe file and "_CorDllMain" for .dll (14 bytes)
\r
3177 /// ASCII string "mscoree.dll" referenced in ImportTable (+ padding = 16 bytes)
\r
3178 /// Entry Point (0xFF25 followed by 4 bytes 0x400000 + RVA of .text)
\r
3180 /// #~ stream structure
\r
3181 /// Header (24 bytes)
\r
3182 /// Rows (4 bytes * numTables)
\r
3185 internal class FileImage : BinaryWriter
\r
3187 internal readonly static uint[] iByteMask = {0x000000FF, 0x0000FF00, 0x00FF0000, 0xFF000000};
\r
3188 internal readonly static ulong[] lByteMask = {0x00000000000000FF, 0x000000000000FF00,
\r
3189 0x0000000000FF0000, 0x00000000FF000000,
\r
3190 0x000000FF00000000, 0x0000FF0000000000,
\r
3191 0x00FF000000000000, 0xFF00000000000000 };
\r
3192 internal readonly static uint nibble0Mask = 0x0000000F;
\r
3193 internal readonly static uint nibble1Mask = 0x000000F0;
\r
3195 private static readonly byte[] DOSHeader = { 0x4d,0x5a,0x90,0x00,0x03,0x00,0x00,0x00,
\r
3196 0x04,0x00,0x00,0x00,0xff,0xff,0x00,0x00,
\r
3197 0xb8,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
\r
3198 0x40,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
\r
3199 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
\r
3200 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
\r
3201 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
\r
3202 0x00,0x00,0x00,0x00,0x80,0x00,0x00,0x00,
\r
3203 0x0e,0x1f,0xba,0x0e,0x00,0xb4,0x09,0xcd,
\r
3204 0x21,0xb8,0x01,0x4c,0xcd,0x21,0x54,0x68,
\r
3205 0x69,0x73,0x20,0x70,0x72,0x6f,0x67,0x72,
\r
3206 0x61,0x6d,0x20,0x63,0x61,0x6e,0x6e,0x6f,
\r
3207 0x74,0x20,0x62,0x65,0x20,0x72,0x75,0x6e,
\r
3208 0x20,0x69,0x6e,0x20,0x44,0x4f,0x53,0x20,
\r
3209 0x6d,0x6f,0x64,0x65,0x2e,0x0d,0x0d,0x0a,
\r
3210 0x24,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
\r
3211 0x50,0x45,0x00,0x00};
\r
3212 private static byte[] PEHeader = { 0x4c, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
\r
3213 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
\r
3214 0xE0, 0x00, 0x0E, 0x01, // PE Header Standard Fields
\r
3215 0x0B, 0x01, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00,
\r
3216 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
\r
3217 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
\r
3220 private static readonly uint minFileAlign = 0x200;
\r
3221 private static readonly uint maxFileAlign = 0x1000;
\r
3222 private static readonly uint fileHeaderSize = 0x178;
\r
3223 private static readonly uint sectionHeaderSize = 40;
\r
3224 private static readonly uint SectionAlignment = 0x2000;
\r
3225 private static readonly uint ImageBase = 0x400000;
\r
3226 private static readonly uint ImportTableSize = 40;
\r
3227 private static readonly uint IATSize = 8;
\r
3228 private static readonly uint CLIHeaderSize = 72;
\r
3229 private uint runtimeFlags = 0x01; // COMIMAGE_FLAGS_ILONLY
\r
3230 // 32BITREQUIRED 0x02, STRONGNAMESIGNED 0x08, TRACKDEBUGDATA 0x10000
\r
3231 private static readonly uint relocFlags = 0x42000040;
\r
3232 private static readonly ushort exeCharacteristics = 0x010E;
\r
3233 private static readonly ushort dllCharacteristics = 0x210E;
\r
3234 // section names are all 8 bytes
\r
3235 private static readonly string textName = ".text\0\0\0";
\r
3236 private static readonly string sdataName = ".sdata\0\0";
\r
3237 private static readonly string relocName = ".reloc\0\0";
\r
3238 private static readonly string rsrcName = ".rsrc\0\0\0";
\r
3239 private static readonly string exeHintNameTable = "\0\0_CorExeMain\0";
\r
3240 private static readonly string dllHintNameTable = "\0\0_CorDllMain\0";
\r
3241 private static readonly string runtimeEngineName = "mscoree.dll\0\0";
\r
3243 private Section text, sdata, rsrc;
\r
3245 BinaryWriter reloc = new BinaryWriter(new MemoryStream());
\r
3246 uint dateStamp = 0;
\r
3247 DateTime origin = new DateTime(1970,1,1);
\r
3248 uint numSections = 2; // always have .text and .reloc sections
\r
3249 internal SubSystem subSys = SubSystem.Windows_CUI; // default is Windows Console mode
\r
3250 internal uint fileAlign = minFileAlign;
\r
3251 uint entryPointOffset, entryPointPadding, imageSize, headerSize, headerPadding, entryPointToken = 0;
\r
3252 uint relocOffset, relocRVA, relocSize, relocPadding, relocTide, hintNameTableOffset;
\r
3253 uint metaDataOffset, runtimeEngineOffset, initDataSize = 0, importTablePadding;
\r
3254 uint importTableOffset, importLookupTableOffset, totalImportTableSize;
\r
3255 MetaData metaData;
\r
3256 char[] runtimeEngine = runtimeEngineName.ToCharArray(), hintNameTable;
\r
3257 bool doDLL, largeStrings, largeGUID, largeUS, largeBlob;
\r
3258 ushort characteristics;
\r
3260 internal FileImage(bool makeDLL, string fileName) : base(new FileStream(fileName,FileMode.Create)) {
\r
3261 InitFileImage(makeDLL);
\r
3262 TimeSpan tmp = System.IO.File.GetCreationTime(fileName).Subtract(origin);
\r
3263 dateStamp = Convert.ToUInt32(tmp.TotalSeconds);
\r
3266 internal FileImage(bool makeDLL, Stream str) : base(str) {
\r
3267 InitFileImage(makeDLL);
\r
3268 TimeSpan tmp = DateTime.Now.Subtract(origin);
\r
3269 dateStamp = Convert.ToUInt32(tmp.TotalSeconds);
\r
3272 private void InitFileImage(bool makeDLL) {
\r
3275 hintNameTable = dllHintNameTable.ToCharArray();
\r
3276 characteristics = dllCharacteristics;
\r
3278 hintNameTable = exeHintNameTable.ToCharArray();
\r
3279 characteristics = exeCharacteristics;
\r
3281 text = new Section(textName,0x60000020); // IMAGE_SCN_CNT CODE, EXECUTE, READ
\r
3282 // rsrc = new Section(rsrcName,0x40000040); // IMAGE_SCN_CNT INITIALIZED_DATA, READ
\r
3283 metaData = new MetaData(this);
\r
3286 internal MetaData GetMetaData() {
\r
3290 private uint GetNextSectStart(uint rva, uint tide) {
\r
3291 if (tide < SectionAlignment) return rva + SectionAlignment;
\r
3292 return rva + ((tide / SectionAlignment) + 1) * SectionAlignment;
\r
3295 private void BuildTextSection() {
\r
3297 // IAT (single entry 8 bytes for pure CIL)
\r
3298 // CLIHeader (72 bytes)
\r
3299 // CIL instructions for all methods (variable size)
\r
3301 // ImportTable (40 bytes)
\r
3302 // ImportLookupTable(8 bytes) (same as IAT for standard CIL files)
\r
3303 // Hint/Name Tables with entry "_CorExeMain" for .exe file and "_CorDllMain" for .dll (14 bytes)
\r
3304 // ASCII string "mscoree.dll" referenced in ImportTable (+ padding = 16 bytes)
\r
3305 // Entry Point (0xFF25 followed by 4 bytes 0x400000 + RVA of .text)
\r
3306 metaData.BuildMetaData(IATSize + CLIHeaderSize);
\r
3307 metaDataOffset = IATSize + CLIHeaderSize;
\r
3308 // Console.WriteLine("Code starts at " + metaDataOffset);
\r
3309 metaDataOffset += metaData.CodeSize();
\r
3310 // resourcesStart =
\r
3311 // strongNameSig = metaData.GetStrongNameSig();
\r
3312 // fixUps = RVA for vtable
\r
3313 importTableOffset = metaDataOffset + metaData.Size();
\r
3314 importTablePadding = NumToAlign(importTableOffset,16);
\r
3315 importTableOffset += importTablePadding;
\r
3316 importLookupTableOffset = importTableOffset + ImportTableSize;
\r
3317 hintNameTableOffset = importLookupTableOffset + IATSize;
\r
3318 runtimeEngineOffset = hintNameTableOffset + (uint)hintNameTable.Length;
\r
3319 entryPointOffset = runtimeEngineOffset + (uint)runtimeEngine.Length;
\r
3320 totalImportTableSize = entryPointOffset - importTableOffset;
\r
3321 // Console.WriteLine("total import table size = " + totalImportTableSize);
\r
3322 // Console.WriteLine("entrypoint offset = " + entryPointOffset);
\r
3323 entryPointPadding = NumToAlign(entryPointOffset,4) + 2;
\r
3324 entryPointOffset += entryPointPadding;
\r
3325 text.AddReloc(entryPointOffset+2);
\r
3326 text.IncTide(entryPointOffset + 6);
\r
3327 //if (text.Tide() < fileAlign) fileAlign = minFileAlign;
\r
3328 text.SetSize(NumToAlign(text.Tide(),fileAlign));
\r
3329 // Console.WriteLine("text size = " + text.Size() + " text tide = " + text.Tide() + " text padding = " + text.Padding());
\r
3330 // Console.WriteLine("metaDataOffset = " + Hex.Int(metaDataOffset));
\r
3331 // Console.WriteLine("importTableOffset = " + Hex.Int(importTableOffset));
\r
3332 // Console.WriteLine("importLookupTableOffset = " + Hex.Int(importLookupTableOffset));
\r
3333 // Console.WriteLine("hintNameTableOffset = " + Hex.Int(hintNameTableOffset));
\r
3334 // Console.WriteLine("runtimeEngineOffset = " + Hex.Int(runtimeEngineOffset));
\r
3335 // Console.WriteLine("entryPointOffset = " + Hex.Int(entryPointOffset));
\r
3336 // Console.WriteLine("entryPointPadding = " + Hex.Int(entryPointPadding));
\r
3340 internal void BuildRelocSection() {
\r
3341 text.DoRelocs(reloc);
\r
3342 if (sdata != null) sdata.DoRelocs(reloc);
\r
3343 if (rsrc != null) rsrc.DoRelocs(reloc);
\r
3344 relocTide = (uint)reloc.Seek(0,SeekOrigin.Current);
\r
3345 relocPadding = NumToAlign(relocTide,fileAlign);
\r
3346 relocSize = relocTide + relocPadding;
\r
3347 imageSize = relocRVA + SectionAlignment;
\r
3348 initDataSize += relocSize;
\r
3351 private void CalcOffsets() {
\r
3356 headerSize = fileHeaderSize + (numSections * sectionHeaderSize);
\r
3357 headerPadding = NumToAlign(headerSize,fileAlign);
\r
3358 headerSize += headerPadding;
\r
3359 uint offset = headerSize;
\r
3360 uint rva = SectionAlignment;
\r
3361 text.SetOffset(offset);
\r
3363 offset += text.Size();
\r
3364 rva = GetNextSectStart(rva,text.Tide());
\r
3365 // Console.WriteLine("headerSize = " + headerSize);
\r
3366 // Console.WriteLine("headerPadding = " + headerPadding);
\r
3367 // Console.WriteLine("textOffset = " + Hex.Int(text.Offset()));
\r
3368 if (sdata != null) {
\r
3369 sdata.SetSize(NumToAlign(sdata.Tide(),fileAlign));
\r
3370 sdata.SetOffset(offset);
\r
3371 sdata.SetRVA(rva);
\r
3372 offset += sdata.Size();
3373 rva = GetNextSectStart(rva,sdata.Tide());
\r
3374 initDataSize += sdata.Size();
\r
3376 if (rsrc != null) {
\r
3377 rsrc.SetSize(NumToAlign(rsrc.Tide(),fileAlign));
\r
3378 rsrc.SetOffset(offset);
\r
3380 offset += rsrc.Size();
\r
3381 rva = GetNextSectStart(rva,rsrc.Tide());
\r
3382 initDataSize += rsrc.Size();
\r
3384 relocOffset = offset;
\r
3388 internal void MakeFile() {
\r
3389 if (doDLL) hintNameTable = dllHintNameTable.ToCharArray();
\r
3390 else hintNameTable = exeHintNameTable.ToCharArray();
\r
3391 BuildTextSection();
\r
3393 BuildRelocSection();
\r
3394 // now write it out
\r
3401 private void WriteHeader() {
\r
3403 // Console.WriteLine("Writing PEHeader at offset " + Seek(0,SeekOrigin.Current));
\r
3405 // Console.WriteLine("Writing text section header at offset " + Hex.Long(Seek(0,SeekOrigin.Current)));
\r
3406 text.WriteHeader(this,relocRVA);
\r
3407 if (sdata != null) sdata.WriteHeader(this,relocRVA);
\r
3408 if (rsrc != null) rsrc.WriteHeader(this,relocRVA);
\r
3409 // Console.WriteLine("Writing reloc section header at offset " + Seek(0,SeekOrigin.Current));
\r
3410 WriteRelocSectionHeader();
\r
3411 // Console.WriteLine("Writing padding at offset " + Seek(0,SeekOrigin.Current));
\r
3412 WriteZeros(headerPadding);
\r
3415 private void WriteSections() {
\r
3416 // Console.WriteLine("Writing text section at offset " + Seek(0,SeekOrigin.Current));
\r
3417 WriteTextSection();
\r
3418 if (sdata != null) WriteSDataSection();
\r
3419 if (rsrc != null) WriteRsrcSection();
\r
3420 WriteRelocSection();
\r
3423 private void WriteIAT() {
\r
3424 Write(text.RVA() + hintNameTableOffset);
\r
3428 private void WriteImportTables() {
\r
3430 WriteZeros(importTablePadding);
\r
3431 // Console.WriteLine("Writing import tables at offset " + Hex.Long(Seek(0,SeekOrigin.Current)));
\r
3432 Write(importLookupTableOffset + text.RVA());
\r
3434 Write(runtimeEngineOffset + text.RVA());
\r
3435 Write(text.RVA()); // IAT is at the beginning of the text section
\r
3437 // Import Lookup Table
\r
3438 WriteIAT(); // lookup table and IAT are the same
\r
3439 // Hint/Name Table
\r
3440 // Console.WriteLine("Writing hintname table at " + Hex.Long(Seek(0,SeekOrigin.Current)));
\r
3441 Write(hintNameTable);
\r
3442 Write(runtimeEngineName.ToCharArray());
\r
3445 private void WriteTextSection() {
\r
3448 // Console.WriteLine("Writing code at " + Hex.Long(Seek(0,SeekOrigin.Current)));
\r
3449 metaData.WriteByteCodes(this);
\r
3450 // Console.WriteLine("Finished writing code at " + Hex.Long(Seek(0,SeekOrigin.Current)));
\r
3451 largeStrings = metaData.LargeStringsIndex();
\r
3452 largeGUID = metaData.LargeGUIDIndex();
\r
3453 largeUS = metaData.LargeUSIndex();
\r
3454 largeBlob = metaData.LargeBlobIndex();
\r
3455 metaData.WriteMetaData(this);
\r
3456 WriteImportTables();
\r
3457 WriteZeros(entryPointPadding);
\r
3458 Write((ushort)0x25FF);
\r
3459 Write(ImageBase + text.RVA());
\r
3460 WriteZeros(text.Padding());
\r
3463 private void WriteCLIHeader() {
\r
3464 Write(CLIHeaderSize); // Cb
\r
3465 Write((short)2); // Major runtime version
\r
3466 Write((short)0); // Minor runtime version
\r
3467 Write(text.RVA() + metaDataOffset);
\r
3468 Write(metaData.Size());
\r
3469 Write(runtimeFlags);
\r
3470 Write(entryPointToken);
\r
3471 WriteZeros(8); // Resources - used by Manifest Resources NYI
\r
3472 WriteZeros(8); // Strong Name stuff here!! NYI
\r
3473 WriteZeros(8); // CodeManagerTable
\r
3474 WriteZeros(8); // VTableFixups NYI
\r
3475 WriteZeros(16); // ExportAddressTableJumps, ManagedNativeHeader
\r
3478 private void WriteSDataSection() {
\r
3479 for (int i=0; i < data.Count; i++) {
\r
3480 ((DataConstant)data[i]).Write(this);
\r
3484 private void WriteRsrcSection() {
\r
3487 private void WriteRelocSection() {
\r
3488 // Console.WriteLine("Writing reloc section at " + Seek(0,SeekOrigin.Current) + " = " + relocOffset);
\r
3489 MemoryStream str = (MemoryStream)reloc.BaseStream;
\r
3490 Write(str.ToArray());
\r
3491 WriteZeros(NumToAlign((uint)str.Position,fileAlign));
\r
3494 internal void SetEntryPoint(uint entryPoint) {
\r
3495 entryPointToken = entryPoint;
\r
3498 internal void AddInitData(DataConstant cVal) {
\r
3499 if (sdata == null) {
\r
3500 sdata = new Section(sdataName,0xC0000040); // IMAGE_SCN_CNT INITIALIZED_DATA, READ, WRITE
\r
3501 data = new ArrayList();
\r
3504 cVal.DataOffset = sdata.Tide();
\r
3505 sdata.IncTide(cVal.GetSize());
\r
3508 internal void WriteZeros(uint numZeros) {
\r
3509 for (int i=0; i < numZeros; i++) {
\r
3514 internal void WritePEHeader() {
\r
3515 Write((ushort)0x014C); // Machine - always 0x14C for Managed PE Files (allow others??)
\r
3516 Write((ushort)numSections);
\r
3518 WriteZeros(8); // Pointer to Symbol Table and Number of Symbols (always zero for ECMA CLI files)
\r
3519 Write((ushort)0x00E0); // Size of Optional Header
\r
3520 Write(characteristics);
\r
3521 // PE Optional Header
\r
3522 Write((ushort)0x010B); // Magic
\r
3523 Write((byte)0x6); // LMajor pure-IL = 6 C++ = 7
\r
3524 Write((byte)0x0); // LMinor
\r
3525 Write(text.Size());
\r
3526 Write(initDataSize);
\r
3527 Write(0); // Check other sections here!!
\r
3528 Write(text.RVA() + entryPointOffset);
\r
3529 Write(text.RVA());
\r
3530 uint dataBase = 0;
\r
3531 if (sdata != null) dataBase = sdata.RVA();
\r
3532 else if (rsrc != null) dataBase = rsrc.RVA();
\r
3533 else dataBase = relocRVA;
\r
3536 Write(SectionAlignment);
\r
3538 Write((ushort)0x04); // OS Major
\r
3539 WriteZeros(6); // OS Minor, User Major, User Minor
\r
3540 Write((ushort)0x04); // SubSys Major
\r
3541 WriteZeros(6); // SybSys Minor, Reserved
\r
3543 Write(headerSize);
\r
3544 Write((int)0); // File Checksum
\r
3545 Write((ushort)subSys);
\r
3546 Write((short)0); // DLL Flags
\r
3547 Write((uint)0x100000); // Stack Reserve Size
\r
3548 Write((uint)0x1000); // Stack Commit Size
\r
3549 Write((uint)0x100000); // Heap Reserve Size
\r
3550 Write((uint)0x1000); // Heap Commit Size
\r
3551 Write(0); // Loader Flags
\r
3552 Write(0x10); // Number of Data Directories
\r
3553 WriteZeros(8); // Export Table
\r
3554 Write(importTableOffset + text.RVA());
\r
3555 Write(totalImportTableSize);
\r
3556 WriteZeros(24); // Resource, Exception and Certificate Tables
\r
3559 WriteZeros(48); // Debug, Copyright, Global Ptr, TLS, Load Config and Bound Import Tables
\r
3560 Write(text.RVA()); // IATRVA - IAT is at start of .text Section
\r
3562 WriteZeros(8); // Delay Import Descriptor
\r
3563 Write(text.RVA()+IATSize); // CLIHeader immediately follows IAT
\r
3564 Write(CLIHeaderSize);
\r
3565 WriteZeros(8); // Reserved
\r
3568 internal void WriteRelocSectionHeader() {
\r
3569 Write(relocName.ToCharArray());
\r
3573 Write(relocOffset);
\r
3575 Write(relocFlags);
\r
3578 private void Align (MemoryStream str, int val) {
\r
3579 if ((str.Position % val) != 0) {
\r
3580 for (int i=val - (int)(str.Position % val); i > 0; i--) {
\r
3586 private uint Align(uint val, uint alignVal) {
\r
3587 if ((val % alignVal) != 0) {
\r
3588 val += alignVal - (val % alignVal);
\r
3593 private uint NumToAlign(uint val, uint alignVal) {
\r
3594 if ((val % alignVal) == 0) return 0;
\r
3595 return alignVal - (val % alignVal);
\r
3598 internal void StringsIndex(uint ix) {
\r
3599 if (largeStrings) Write(ix);
\r
3600 else Write((ushort)ix);
\r
3603 internal void GUIDIndex(uint ix) {
\r
3604 if (largeGUID) Write(ix);
\r
3605 else Write((ushort)ix);
\r
3608 internal void USIndex(uint ix) {
\r
3609 if (largeUS) Write(ix);
\r
3610 else Write((ushort)ix);
\r
3613 internal void BlobIndex(uint ix) {
\r
3614 if (largeBlob) Write(ix);
\r
3615 else Write((ushort)ix);
\r
3618 internal void WriteIndex(MDTable tabIx,uint ix) {
\r
3619 if (metaData.LargeIx(tabIx)) Write(ix);
\r
3620 else Write((ushort)ix);
\r
3623 internal void WriteCodedIndex(CIx code, MetaDataElement elem) {
\r
3624 metaData.WriteCodedIndex(code,elem,this);
\r
3627 internal void WriteCodeRVA(uint offs) {
\r
3628 Write(text.RVA() + offs);
\r
3631 internal void WriteDataRVA(uint offs) {
\r
3632 Write(sdata.RVA() + offs);
\r
3635 internal void Write3Bytes(uint val) {
\r
3636 byte b3 = (byte)((val & FileImage.iByteMask[2]) >> 16);
\r
3637 byte b2 = (byte)((val & FileImage.iByteMask[1]) >> 8);;
\r
3638 byte b1 = (byte)(val & FileImage.iByteMask[0]);
\r
3645 /**************************************************************************/
\r
3647 /// Descriptor for a file referenced in THIS assembly/module (.file)
\r
3649 public class FileRef : MetaDataElement
\r
3651 private static readonly uint HasMetaData = 0x1;
\r
3652 uint nameIx = 0, hashIx = 0;
\r
3655 internal FileRef(string name, byte[] hashBytes, bool metaData,
\r
3656 bool entryPoint, MetaData md) {
\r
3657 if (metaData) flags = HasMetaData;
\r
3658 if (entryPoint) md.SetEntryPoint(this);
\r
3659 nameIx = md.AddToStringsHeap(name);
\r
3660 hashIx = md.AddToBlobHeap(hashBytes);
\r
3661 tabIx = MDTable.File;
\r
3664 internal FileRef(uint nameIx, byte[] hashBytes, bool metaData,
\r
3665 bool entryPoint, MetaData md) {
\r
3666 if (metaData) flags = HasMetaData;
\r
3667 if (entryPoint) md.SetEntryPoint(this);
\r
3668 this.nameIx = nameIx;
\r
3669 hashIx = md.AddToBlobHeap(hashBytes);
\r
3670 tabIx = MDTable.File;
\r
3673 internal sealed override uint Size(MetaData md) {
\r
3674 return 4 + md.StringsIndexSize() + md.BlobIndexSize();
\r
3677 internal sealed override void Write(FileImage output) {
\r
3678 output.Write(flags);
\r
3679 output.StringsIndex(nameIx);
\r
3680 output.BlobIndex(hashIx);
\r
3683 internal sealed override uint GetCodedIx(CIx code) {
\r
3685 case (CIx.HasCustomAttr) : return 16;
\r
3686 case (CIx.Implementation) : return 0;
\r
3692 /**************************************************************************/
\r
3694 /// Descriptor for pinvoke information for a method NOT YET IMPLEMENTED
\r
3696 public class ImplMap : MetaDataElement
\r
3698 private static readonly ushort NoMangle = 0x01;
\r
3701 string importName;
\r
3703 ModuleRef importScope;
\r
3705 internal ImplMap(ushort flag, Method implMeth, string iName, ModuleRef mScope) {
\r
3708 importName = iName;
\r
3709 importScope = mScope;
\r
3710 tabIx = MDTable.ImplMap;
\r
3711 if (iName == null) flags |= NoMangle;
\r
3712 //throw(new NotYetImplementedException("PInvoke "));
\r
3715 internal sealed override void BuildTables(MetaData md) {
\r
3717 iNameIx = md.AddToStringsHeap(importName);
\r
3721 internal sealed override uint Size(MetaData md) {
\r
3722 return 2+ md.CodedIndexSize(CIx.MemberForwarded) +
\r
3723 md.StringsIndexSize() + md.TableIndexSize(MDTable.ModuleRef);
\r
3726 internal sealed override void Write(FileImage output) {
\r
3727 output.Write(flags);
\r
3728 output.WriteCodedIndex(CIx.MemberForwarded,meth);
\r
3729 output.StringsIndex(iNameIx);
\r
3730 output.WriteIndex(MDTable.ModuleRef,importScope.Row);
\r
3735 /**************************************************************************/
\r
3737 /// Descriptor for an IL instruction
\r
3739 internal abstract class CILInstruction {
\r
3740 protected static readonly sbyte maxByteVal = 127;
\r
3741 protected static readonly sbyte minByteVal = -128;
\r
3742 protected static readonly byte leadByte = 0xFE;
\r
3743 protected static readonly uint USHeapIndex = 0x70000000;
\r
3744 protected static readonly int longInstrStart = (int)Op.arglist;
\r
3745 public bool twoByteInstr = false;
\r
3746 public uint size = 0;
\r
3747 public uint offset;
\r
3749 internal virtual bool Check(MetaData md) {
\r
3753 internal virtual void Write(FileImage output) { }
\r
3757 internal class CILByte : CILInstruction {
\r
3760 internal CILByte(byte bVal) {
\r
3765 internal override void Write(FileImage output) {
\r
3766 output.Write(byteVal);
\r
3772 internal class Instr : CILInstruction {
\r
3773 protected int instr;
\r
3775 internal Instr(int inst) {
\r
3776 if (inst >= longInstrStart) {
\r
3777 instr = inst - longInstrStart;
\r
3778 twoByteInstr = true;
\r
3786 internal override void Write(FileImage output) {
\r
3787 //Console.WriteLine("Writing instruction " + instr + " with size " + size);
\r
3788 if (twoByteInstr) output.Write(leadByte);
\r
3789 output.Write((byte)instr);
\r
3794 internal class IntInstr : Instr {
\r
3798 internal IntInstr(int inst, int num, bool byteSize) : base(inst) {
\r
3800 byteNum = byteSize;
\r
3801 if (byteNum) size++;
\r
3805 internal sealed override void Write(FileImage output) {
\r
3806 base.Write(output);
\r
3808 output.Write((sbyte)val);
\r
3810 output.Write(val);
\r
3815 internal class UIntInstr : Instr {
\r
3819 internal UIntInstr(int inst, int num, bool byteSize) : base(inst) {
\r
3821 byteNum = byteSize;
\r
3822 if (byteNum) size++;
\r
3826 internal sealed override void Write(FileImage output) {
\r
3827 base.Write(output);
\r
3829 output.Write((byte)val);
\r
3831 output.Write((ushort)val);
\r
3836 internal class LongInstr : Instr {
\r
3839 internal LongInstr(int inst, long l) : base(inst) {
\r
3844 internal sealed override void Write(FileImage output) {
\r
3845 base.Write(output);
\r
3846 output.Write(val);
\r
3851 internal class FloatInstr : Instr {
\r
3854 internal FloatInstr(int inst, float f) : base(inst) {
\r
3859 internal sealed override void Write(FileImage output) {
\r
3860 base.Write(output);
\r
3861 output.Write(fVal);
\r
3866 internal class DoubleInstr : Instr {
\r
3869 internal DoubleInstr(int inst, double d) : base(inst) {
\r
3874 internal sealed override void Write(FileImage output) {
\r
3875 base.Write(output);
\r
3876 output.Write(val);
\r
3881 internal class StringInstr : Instr {
\r
3886 internal StringInstr(int inst, string str) : base(inst) {
\r
3891 internal StringInstr (int inst, byte[] str) : base (inst) {
3896 internal sealed override bool Check(MetaData md) {
3898 strIndex = md.AddToUSHeap(val);
3900 strIndex = md.AddToUSHeap (bval);
3904 internal sealed override void Write(FileImage output) {
\r
3905 base.Write(output);
\r
3906 output.Write(USHeapIndex | strIndex);
\r
3911 internal class LabelInstr : CILInstruction {
\r
3914 internal LabelInstr(CILLabel lab) {
\r
3916 label.AddLabelInstr(this);
\r
3920 internal class FieldInstr : Instr {
\r
3923 internal FieldInstr(int inst, Field f) : base(inst) {
\r
3928 internal sealed override void Write(FileImage output) {
\r
3929 base.Write(output);
\r
3930 output.Write(field.Token());
\r
3935 internal class MethInstr : Instr {
\r
3938 internal MethInstr(int inst, Method m) : base(inst) {
\r
3943 internal sealed override void Write(FileImage output) {
\r
3944 base.Write(output);
\r
3945 output.Write(meth.Token());
\r
3950 internal class SigInstr : Instr {
\r
3951 CalliSig signature;
\r
3953 internal SigInstr(int inst, CalliSig sig) : base(inst) {
\r
3958 internal sealed override bool Check(MetaData md) {
\r
3959 md.AddToTable(MDTable.StandAloneSig,signature);
\r
3960 signature.BuildTables(md);
\r
3964 internal sealed override void Write(FileImage output) {
\r
3965 base.Write(output);
\r
3966 output.Write(signature.Token());
\r
3970 internal class TypeInstr : Instr {
\r
3971 MetaDataElement theType;
\r
3973 internal TypeInstr(int inst, Type aType, MetaData md) : base(inst) {
\r
3974 theType = aType.GetTypeSpec(md);
\r
3978 internal sealed override void Write(FileImage output) {
\r
3979 base.Write(output);
\r
3980 output.Write(theType.Token());
\r
3985 internal class BranchInstr : Instr {
\r
3987 private bool shortVer = true;
\r
3988 private static readonly byte longInstrOffset = 13;
\r
3989 private int target = 0;
\r
3991 internal BranchInstr(int inst, CILLabel dst) : base(inst) {
\r
3993 dest.AddBranch(this);
\r
3996 if (inst >= (int) BranchOp.br && inst != (int) BranchOp.leave_s) {
4002 internal sealed override bool Check(MetaData md) {
\r
4003 target = (int)dest.GetLabelOffset() - (int)(offset + size);
\r
4007 internal sealed override void Write(FileImage output) {
\r
4008 base.Write(output);
\r
4010 output.Write((sbyte)target);
\r
4012 output.Write(target);
\r
4017 internal class SwitchInstr : Instr {
\r
4019 uint numCases = 0;
\r
4021 internal SwitchInstr(int inst, CILLabel[] dsts) : base(inst) {
\r
4023 if (cases != null) numCases = (uint)cases.Length;
\r
4024 size += 4 + (numCases * 4);
\r
4025 for (int i=0; i < numCases; i++) {
\r
4026 cases[i].AddBranch(this);
\r
4030 internal sealed override void Write(FileImage output) {
\r
4031 base.Write(output);
\r
4032 output.Write(numCases);
\r
4033 for (int i=0; i < numCases; i++) {
\r
4034 int target = (int)cases[i].GetLabelOffset() - (int)(offset + size);
\r
4035 output.Write(target);
\r
4040 /**************************************************************************/
\r
4042 public class GenericParameter : MetaDataElement
\r
4044 MetaDataElement owner;
4050 internal GenericParameter (ClassDef owner, MetaData metadata,
4051 short index, string name) : this (owner, metadata, index, name, true)
4055 internal GenericParameter (MethodDef owner, MetaData metadata,
4056 short index, string name) : this (owner, metadata, index, name, true)
4060 private GenericParameter (MetaDataElement owner, MetaData metadata,
4061 short index, string name, bool nadda)
4063 this.owner = owner;
\r
4064 this.metadata = metadata;
4065 this.index = index;
\r
4066 tabIx = MDTable.GenericParam;
\r
4070 public void AddConstraint (Type constraint) {
4071 metadata.AddToTable (MDTable.GenericParamConstraint,
\r
4072 new GenericParamConstraint (this, constraint));
\r
4075 internal sealed override uint Size(MetaData md) {
\r
4076 return (uint) (4 +
\r
4077 md.CodedIndexSize(CIx.TypeOrMethodDef) +
\r
4079 md.TableIndexSize(MDTable.TypeDef));
\r
4082 internal sealed override void BuildTables(MetaData md) {
\r
4084 nameIx = md.AddToStringsHeap(name);
\r
4088 internal sealed override void Write(FileImage output) {
\r
4089 output.Write ((short) index);
\r
4090 output.Write ((short) 0);
\r
4091 output.WriteCodedIndex(CIx.TypeOrMethodDef, owner);
\r
4092 output.Write ((uint) nameIx);
\r
4093 output.WriteIndex(MDTable.TypeDef,owner.Row);
\r
4099 internal class GenericParamConstraint : MetaDataElement
\r
4101 GenericParameter param;
\r
4104 public GenericParamConstraint (GenericParameter param, Type type) {
\r
4105 this.param = param;
\r
4107 tabIx = MDTable.GenericParamConstraint;
\r
4110 internal sealed override uint Size(MetaData md) {
\r
4111 return (uint) (md.TableIndexSize(MDTable.GenericParam) +
\r
4112 md.CodedIndexSize(CIx.TypeDefOrRef));
\r
4115 internal sealed override void Write(FileImage output) {
\r
4116 output.WriteIndex(MDTable.GenericParam, param.Row);
\r
4117 output.WriteCodedIndex(CIx.TypeDefOrRef, type);
\r
4123 internal class MethodSpec : MetaDataElement
4126 GenericMethodSig g_sig;
4129 internal MethodSpec (Method meth, GenericMethodSig g_sig) {
4132 tabIx = MDTable.MethodSpec;
4135 internal sealed override void BuildTables (MetaData md) {
4137 sidx = g_sig.GetSigIx (md);
4141 internal sealed override uint Size (MetaData md) {
4142 return (uint) (md.CodedIndexSize(CIx.MethodDefOrRef) +
4143 md.BlobIndexSize ());
4146 internal sealed override void Write (FileImage output) {
4147 output.WriteCodedIndex (CIx.MethodDefOrRef, meth);
4148 output.BlobIndex (sidx);
\r
4152 /**************************************************************************/
\r
4154 /// Descriptor for interface implemented by a class
\r
4156 public class InterfaceImpl: MetaDataElement
\r
4158 ClassDef theClass;
\r
4159 Class theInterface;
\r
4161 internal InterfaceImpl(ClassDef theClass, Class theInterface) {
\r
4162 this.theClass = theClass;
\r
4163 this.theInterface = theInterface;
\r
4164 tabIx = MDTable.InterfaceImpl;
\r
4167 internal sealed override uint Size(MetaData md) {
\r
4168 return md.TableIndexSize(MDTable.TypeDef) +
\r
4169 md.CodedIndexSize(CIx.TypeDefOrRef);
\r
4172 internal sealed override void Write(FileImage output) {
\r
4173 output.WriteIndex(MDTable.TypeDef,theClass.Row);
\r
4174 output.WriteCodedIndex(CIx.TypeDefOrRef,theInterface);
\r
4177 internal sealed override uint GetCodedIx(CIx code) { return 5; }
\r
4180 /**************************************************************************/
\r
4182 /// Descriptor for a local of a method
\r
4184 public class Local
\r
4186 private static readonly byte Pinned = 0x45;
\r
4189 bool pinned = false, byref = false;
\r
4192 /// Create a new local variable
\r
4194 /// <param name="lName">name of the local variable</param>
\r
4195 /// <param name="lType">type of the local variable</param>
\r
4196 public Local(string lName, Type lType) {
\r
4202 /// Create a new local variable that is byref and/or pinned
\r
4204 /// <param name="lName">local name</param>
\r
4205 /// <param name="lType">local type</param>
\r
4206 /// <param name="byRef">is byref</param>
\r
4207 /// <param name="isPinned">has pinned attribute</param>
\r
4208 public Local(string lName, Type lType, bool byRef, bool isPinned)
\r
4213 pinned = isPinned;
\r
4216 internal void TypeSig(MemoryStream str) {
\r
4217 if (pinned) str.WriteByte(Pinned);
\r
4218 type.TypeSig(str);
\r
4222 /**************************************************************************/
\r
4224 /// Descriptor for the locals for a method
\r
4227 public class LocalSig : Signature
\r
4229 private static readonly byte LocalSigByte = 0x7;
\r
4232 public LocalSig(Local[] locals) {
\r
4233 this.locals = locals;
\r
4234 tabIx = MDTable.StandAloneSig;
\r
4237 internal sealed override void BuildTables(MetaData md) {
\r
4239 MemoryStream sig = new MemoryStream();
\r
4240 sig.WriteByte(LocalSigByte);
\r
4241 MetaData.CompressNum((uint)locals.Length,sig);
\r
4242 for (int i=0; i < locals.Length; i++) {
\r
4243 ((Local)locals[i]).TypeSig(sig);
\r
4245 sigIx = md.AddToBlobHeap(sig.ToArray());
\r
4251 /**************************************************************************/
\r
4253 /// Descriptor for resources used in this PE file NOT YET IMPLEMENTED
\r
4256 public class ManifestResource : MetaDataElement
\r
4258 private static readonly uint PublicResource = 0x1;
\r
4259 private static readonly uint PrivateResource = 0x2;
\r
4262 MetaDataElement rRef;
\r
4267 public ManifestResource(string name, bool isPub, FileRef fileRef) {
\r
4269 if (isPub) flags = PublicResource;
\r
4270 else flags = PrivateResource;
\r
4272 tabIx = MDTable.ManifestResource;
\r
4273 throw(new NotYetImplementedException("Manifest Resources "));
\r
4276 public ManifestResource(string name, bool isPub, FileRef fileRef,
\r
4279 if (isPub) flags = PublicResource;
\r
4280 else flags = PrivateResource;
\r
4282 fileOffset = fileIx;
\r
4285 public ManifestResource(string name, bool isPub, AssemblyRef assemRef) {
\r
4287 if (isPub) flags = PublicResource;
\r
4288 else flags = PrivateResource;
\r
4292 internal sealed override void BuildTables(MetaData md) {
\r
4294 nameIx = md.AddToStringsHeap(mrName);
\r
4298 internal sealed override uint Size(MetaData md) {
\r
4299 return 8 + md.StringsIndexSize() +
\r
4300 md.CodedIndexSize(CIx.Implementation);
\r
4303 internal sealed override void Write(FileImage output) {
\r
4304 output.Write(fileOffset);
\r
4305 output.Write(flags);
\r
4306 output.StringsIndex(nameIx);
\r
4307 output.WriteCodedIndex(CIx.Implementation,rRef);
\r
4310 internal sealed override uint GetCodedIx(CIx code) { return 18; }
\r
4313 /**************************************************************************/
\r
4315 /// Base class for elements in the PropertyMap, EventMap and
\r
4316 /// NestedClass MetaData tables
\r
4318 public class MapElem : MetaDataElement
\r
4322 MDTable elemTable;
\r
4324 internal MapElem(ClassDef par, uint elIx, MDTable elemTab) {
\r
4327 elemTable = elemTab;
\r
4330 internal sealed override uint Size(MetaData md) {
\r
4331 return md.TableIndexSize(MDTable.TypeDef) + md.TableIndexSize(elemTable);
\r
4334 internal sealed override void Write(FileImage output) {
\r
4335 output.WriteIndex(MDTable.TypeDef,parent.Row);
\r
4336 output.WriteIndex(elemTable,elemIx);
\r
4339 /**************************************************************************/
\r
4341 /// Base class for field/methods (member of a class)
\r
4343 public abstract class Member : MetaDataElement
\r
4345 protected string name;
\r
4346 protected uint nameIx = 0, sigIx = 0;
\r
4348 internal Member(string memName)
\r
4351 tabIx = MDTable.MemberRef;
\r
4355 /**************************************************************************/
\r
4358 /// Root (20 bytes + UTF-8 Version String + quad align padding)
\r
4359 /// StreamHeaders (8 bytes + null terminated name string + quad align padding)
\r
4361 /// #~ (always present - holds metadata tables)
\r
4362 /// #Strings (always present - holds identifier strings)
\r
4363 /// #US (Userstring heap)
\r
4364 /// #Blob (signature blobs)
\r
4365 /// #GUID (guids for assemblies or Modules)
\r
4368 public class MetaData
\r
4370 private static readonly int[] CIxShiftMap = {2,2,5,1,2,3,1,1,1,2,3,2,1};
\r
4371 private static readonly byte StringsHeapMask = 0x1;
\r
4372 private static readonly byte GUIDHeapMask = 0x2;
\r
4373 private static readonly byte BlobHeapMask = 0x4;
\r
4374 private static readonly uint MetaDataSignature = 0x424A5342;
\r
4375 private static readonly uint maxSmlIxSize = 0xFFFF;
\r
4376 private static readonly uint max1BitSmlIx = 0x7FFF;
\r
4377 private static readonly uint max2BitSmlIx = 0x3FFF;
\r
4378 private static readonly uint max3BitSmlIx = 0x1FFF;
\r
4379 private static readonly uint max5BitSmlIx = 0x7FF;
\r
4380 // NOTE: version and stream name strings MUST always be quad padded
\r
4381 private static readonly string version = "v1.0.3705\0\0\0";
\r
4382 private static readonly char[] tildeName = {'#','~','\0','\0'};
\r
4383 private static readonly char[] stringsName = {'#','S','t','r','i','n','g','s','\0','\0','\0','\0'};
\r
4384 private static readonly char[] usName = {'#','U','S','\0'};
\r
4385 private static readonly char[] guidName = {'#','G','U','I','D','\0','\0','\0'};
\r
4386 private static readonly char[] blobName = {'#','B','l','o','b','\0','\0','\0'};
\r
4387 private static readonly uint MetaDataHeaderSize = 20 + (uint)version.Length;
\r
4388 private static readonly uint TildeHeaderSize = 24;
\r
4389 private static readonly uint StreamHeaderSize = 8;
\r
4390 private static readonly uint numMetaDataTables = (int)MDTable.GenericParamConstraint + 1;
\r
4391 private static readonly uint tildeHeaderSize = 8 + (uint)tildeName.Length;
\r
4393 MetaDataStream strings, us, guid, blob;
\r
4395 MetaDataStream[] streams = new MetaDataStream[5];
\r
4396 uint numStreams = 5;
\r
4397 uint tildeTide = 0, tildePadding = 0, tildeStart = 0;
\r
4398 uint numTables = 0;
\r
4399 ArrayList[] metaDataTables = new ArrayList[numMetaDataTables];
\r
4400 ArrayList byteCodes = new ArrayList();
\r
4401 uint codeSize = 0, codeStart, byteCodePadding = 0, metaDataSize = 0;
\r
4402 ulong valid = 0, /*sorted = 0x000002003301FA00;*/ sorted = 0;
\r
4403 bool[] largeIx = new bool[numMetaDataTables];
\r
4404 bool[] lgeCIx = new bool[(int)CIx.MaxCIx];
\r
4405 bool largeStrings = false, largeUS = false, largeGUID = false, largeBlob = false;
\r
4406 private FileImage file;
\r
4407 private byte heapSizes = 0;
\r
4408 MetaDataElement entryPoint;
\r
4409 BinaryWriter output;
\r
4410 public MSCorLib mscorlib;
\r
4411 private TypeSpec[] systemTypeSpecs = new TypeSpec[PrimitiveType.NumSystemTypes];
\r
4414 internal MetaData(FileImage file) {
\r
4415 // tilde = new MetaDataStream(tildeName,false,0);
\r
4417 strings = new MetaDataStream(stringsName,new UTF8Encoding(),true);
\r
4418 us = new MetaDataStream(usName,new UnicodeEncoding(),true);
\r
4419 guid = new MetaDataStream(guidName,false);
\r
4420 blob = new MetaDataStream(blobName,true);
\r
4421 streams[1] = strings;
\r
4423 streams[3] = guid;
\r
4424 streams[4] = blob;
\r
4425 for (int i=0; i < numMetaDataTables; i++) {
\r
4426 largeIx[i] = false;
\r
4428 for (int i=0; i < lgeCIx.Length; i++) {
\r
4429 lgeCIx[i] = false;
\r
4431 mscorlib = new MSCorLib(this);
\r
4434 internal TypeSpec GetPrimitiveTypeSpec(int ix) {
\r
4435 return systemTypeSpecs[ix];
\r
4438 internal void SetPrimitiveTypeSpec(int ix, TypeSpec typeSpec) {
\r
4439 systemTypeSpecs[ix] = typeSpec;
\r
4442 internal uint Size() {
\r
4443 return metaDataSize;
\r
4446 internal void StreamSize(byte mask) {
\r
4447 heapSizes |= mask;
\r
4450 internal uint AddToUSHeap(string str) {
\r
4451 if (str == null) return 0;
\r
4452 return us.Add(str,true);
\r
4455 internal uint AddToUSHeap(byte[] str) {
4456 if (str == null) return 0;
4457 return us.Add (str, true);
4460 internal uint AddToStringsHeap(string str) {
\r
4461 if ((str == null) || (str.CompareTo("") == 0)) return 0;
\r
4462 return strings.Add(str,false);
\r
4465 internal uint AddToGUIDHeap(Guid guidNum) {
\r
4466 return guid.Add(guidNum, false);
\r
4469 internal uint AddToBlobHeap(byte[] blobBytes) {
\r
4470 if (blobBytes == null) return 0;
\r
4471 return blob.Add(blobBytes, true);
\r
4474 internal uint AddToBlobHeap(byte val) {
\r
4475 return blob.Add(val, true);
\r
4478 internal uint AddToBlobHeap(sbyte val) {
\r
4479 return blob.Add(val, true);
\r
4482 internal uint AddToBlobHeap(ushort val) {
\r
4483 return blob.Add(val, true);
\r
4486 internal uint AddToBlobHeap(short val) {
\r
4487 return blob.Add(val, true);
\r
4490 internal uint AddToBlobHeap(uint val) {
\r
4491 return blob.Add(val, true);
\r
4494 internal uint AddToBlobHeap(int val) {
\r
4495 return blob.Add(val, true);
\r
4498 internal uint AddToBlobHeap(ulong val) {
\r
4499 return blob.Add(val, true);
\r
4502 internal uint AddToBlobHeap(long val) {
\r
4503 return blob.Add(val, true);
\r
4506 internal uint AddToBlobHeap(float val) {
\r
4507 return blob.Add(val, true);
\r
4510 internal uint AddToBlobHeap(double val) {
\r
4511 return blob.Add(val, true);
\r
4514 internal uint AddToBlobHeap(string val) {
\r
4515 return blob.Add(val,true);
\r
4519 private ArrayList GetTable(MDTable tableIx) {
\r
4520 int tabIx = (int)tableIx;
\r
4521 if (metaDataTables[tabIx] == null) {
\r
4522 metaDataTables[tabIx] = new ArrayList();
\r
4523 valid |= ((ulong)0x1 << tabIx);
\r
4524 // Console.WriteLine("after creating table " + tableIx + "(" + tabIx + ") valid = " + valid);
\r
4527 return metaDataTables[tabIx];
\r
4530 internal void AddToTable(MDTable tableIx, MetaDataElement elem) {
\r
4531 if (elem.Row > 0) {
\r
4532 // Console.Out.WriteLine("ERROR - element already in table " + tableIx);
\r
4535 // updates Row field of the element
\r
4536 // Console.WriteLine("Adding element to table " + (uint)tableIx);
\r
4537 ArrayList table = GetTable(tableIx);
\r
4538 elem.Row = (uint)table.Count + 1;
\r
4542 internal uint TableIndex(MDTable tableIx) {
\r
4543 if (metaDataTables[(int)tableIx] == null) return 1;
\r
4544 return (uint)metaDataTables[(int)tableIx].Count+1;
\r
4547 internal uint AddCode(CILInstructions byteCode) {
\r
4548 byteCodes.Add(byteCode);
\r
4549 uint offset = codeSize + codeStart;
\r
4550 codeSize += byteCode.GetCodeSize();
\r
4554 internal void SetEntryPoint(MetaDataElement ep) {
\r
4558 internal void AddData(DataConstant cVal) {
\r
4559 file.AddInitData(cVal);
\r
4562 internal static void CompressNum(uint val, MemoryStream sig) {
\r
4564 sig.WriteByte((byte)val);
\r
4565 } else if (val < 0x3FFF) {
\r
4566 byte b1 = (byte)((val >> 8) | 0x80);
\r
4567 byte b2 = (byte)(val & FileImage.iByteMask[0]);
\r
4568 sig.WriteByte(b1);
\r
4569 sig.WriteByte(b2);
\r
4571 byte b1 = (byte)((val >> 24) | 0xC0);
\r
4572 byte b2 = (byte)((val & FileImage.iByteMask[2]) >> 16);
\r
4573 byte b3 = (byte)((val & FileImage.iByteMask[1]) >> 8);;
\r
4574 byte b4 = (byte)(val & FileImage.iByteMask[0]);
\r
4575 sig.WriteByte(b1);
\r
4576 sig.WriteByte(b2);
\r
4577 sig.WriteByte(b3);
\r
4578 sig.WriteByte(b4);
\r
4582 internal uint CodeSize() {
\r
4583 return codeSize + byteCodePadding;
\r
4586 internal uint StringsIndexSize() {
\r
4587 if (largeStrings) return 4;
\r
4591 internal uint GUIDIndexSize() {
\r
4592 if (largeGUID) return 4;
\r
4596 internal uint USIndexSize() {
\r
4597 if (largeUS) return 4;
\r
4601 internal uint BlobIndexSize() {
\r
4602 if (largeBlob) return 4;
\r
4606 internal uint CodedIndexSize(CIx code) {
\r
4607 if (lgeCIx[(uint)code]) return 4;
\r
4611 internal uint TableIndexSize(MDTable tabIx) {
\r
4612 if (largeIx[(uint)tabIx]) return 4;
\r
4616 private void SetIndexSizes() {
\r
4617 for (int i=0; i < numMetaDataTables; i++) {
\r
4618 if (metaDataTables[i] != null) {
\r
4619 uint count = (uint)metaDataTables[i].Count;
\r
4620 if (count > maxSmlIxSize) {
\r
4621 largeIx[i] = true;
\r
4622 MDTable tabIx = (MDTable)i;
\r
4623 if (count > max5BitSmlIx) {
\r
4624 lgeCIx[(int)CIx.HasCustomAttr] = true;
\r
4626 if (count > max3BitSmlIx) {
\r
4627 if ((tabIx == MDTable.TypeRef) || (tabIx == MDTable.ModuleRef) || (tabIx == MDTable.Method) || (tabIx == MDTable.TypeSpec))
\r
4628 lgeCIx[(int)CIx.CustomAttributeType] = true;
\r
4629 if ((tabIx == MDTable.Method) || (tabIx == MDTable.MemberRef))
\r
4630 lgeCIx[(int)CIx.MemberRefParent] = true;
\r
4631 } else if (count > max2BitSmlIx) {
\r
4632 if ((tabIx == MDTable.Field) || (tabIx == MDTable.Param) || (tabIx == MDTable.Property))
\r
4633 lgeCIx[(int)CIx.HasConst] = true;
\r
4634 if ((tabIx == MDTable.TypeDef) || (tabIx == MDTable.TypeRef) || (tabIx == MDTable.TypeSpec))
\r
4635 lgeCIx[(int)CIx.TypeDefOrRef] = true;
\r
4636 if ((tabIx == MDTable.TypeDef) || (tabIx == MDTable.Method) || (tabIx == MDTable.Assembly))
\r
4637 lgeCIx[(int)CIx.HasDeclSecurity] = true;
\r
4638 if ((tabIx == MDTable.File) || (tabIx == MDTable.AssemblyRef) || (tabIx == MDTable.ExportedType))
\r
4639 lgeCIx[(int)CIx.Implementation] = true;
\r
4640 if ((tabIx == MDTable.Module) || (tabIx == MDTable.ModuleRef) || (tabIx == MDTable.AssemblyRef) || (tabIx == MDTable.TypeRef))
\r
4641 lgeCIx[(int)CIx.ResolutionScope] = true;
\r
4642 } else if (count > max1BitSmlIx) {
\r
4643 if ((tabIx == MDTable.Field) || (tabIx == MDTable.Param))
\r
4644 lgeCIx[(int)CIx.HasFieldMarshal] = true;
\r
4645 if ((tabIx == MDTable.Event) || (tabIx == MDTable.Property))
\r
4646 lgeCIx[(int)CIx.HasSemantics] = true;
\r
4647 if ((tabIx == MDTable.Method) || (tabIx == MDTable.MemberRef))
\r
4648 lgeCIx[(int)CIx.MethodDefOrRef] = true;
\r
4649 if ((tabIx == MDTable.Field) || (tabIx == MDTable.Method))
\r
4650 lgeCIx[(int)CIx.MemberForwarded] = true;
\r
4651 if ((tabIx == MDTable.TypeDef) || (tabIx == MDTable.Method))
\r
4652 lgeCIx[(int)CIx.TypeOrMethodDef] = true;
\r
4657 if (strings.LargeIx()) {
\r
4658 largeStrings = true;
\r
4659 heapSizes |= StringsHeapMask;
\r
4661 if (guid.LargeIx()) {
\r
4663 heapSizes |= GUIDHeapMask;
\r
4665 if (blob.LargeIx()) {
\r
4667 heapSizes |= BlobHeapMask;
\r
4669 largeUS = us.LargeIx();
\r
4672 private void SetStreamOffsets() {
\r
4673 uint sizeOfHeaders = StreamHeaderSize + (uint)tildeName.Length;
\r
4674 for (int i=1; i < numStreams; i++) {
\r
4675 sizeOfHeaders += streams[i].headerSize();
\r
4677 metaDataSize = MetaDataHeaderSize + sizeOfHeaders;
\r
4678 tildeStart = metaDataSize;
\r
4679 metaDataSize += tildeTide + tildePadding;
\r
4680 for (int i=1; i < numStreams; i++) {
\r
4681 streams[i].Start = metaDataSize;
\r
4682 metaDataSize += streams[i].Size();
\r
4683 streams[i].WriteDetails();
\r
4687 internal void CalcTildeStreamSize() {
\r
4688 //tilde.SetIndexSizes(strings.LargeIx(),us.LargeIx(),guid.LargeIx(),blob.LargeIx());
\r
4689 tildeTide = TildeHeaderSize;
\r
4690 tildeTide += 4 * numTables;
\r
4691 //Console.WriteLine("Tilde header + sizes = " + tildeTide);
\r
4692 for (int i=0; i < numMetaDataTables; i++) {
\r
4693 if (metaDataTables[i] != null) {
\r
4694 ArrayList table = metaDataTables[i];
\r
4695 // Console.WriteLine("Meta data table " + i + " at offset " + tildeTide);
\r
4696 tildeTide += (uint)table.Count * ((MetaDataElement)table[0]).Size(this);
\r
4697 // Console.WriteLine("Metadata table " + i + " has size " + table.Count);
\r
4698 // Console.WriteLine("tildeTide = " + tildeTide);
\r
4701 if ((tildeTide % 4) != 0) tildePadding = 4 - (tildeTide % 4);
\r
4702 //Console.WriteLine("tildePadding = " + tildePadding);
\r
4705 internal void WriteTildeStream(FileImage output) {
\r
4706 long startTilde = output.Seek(0,SeekOrigin.Current);
\r
4707 output.Write((uint)0); // Reserved
\r
4708 output.Write((byte)1); // MajorVersion
\r
4709 output.Write((byte)0); // MinorVersion
\r
4710 output.Write(heapSizes);
\r
4711 output.Write((byte)1); // Reserved
\r
4712 output.Write(valid);
\r
4713 output.Write(sorted);
\r
4714 for (int i=0; i < numMetaDataTables; i++) {
\r
4715 if (metaDataTables[i] != null) {
\r
4716 uint count = (uint)metaDataTables[i].Count;
\r
4717 output.Write(count);
\r
4720 long tabStart = output.Seek(0,SeekOrigin.Current);
\r
4721 // Console.WriteLine("Starting metaData tables at " + tabStart);
\r
4722 for (int i=0; i < numMetaDataTables; i++) {
\r
4723 if (metaDataTables[i] != null) {
\r
4724 // Console.WriteLine("Starting metaData table " + i + " at " + (output.Seek(0,SeekOrigin.Current) - startTilde));
\r
4725 ArrayList table = metaDataTables[i];
\r
4726 for (int j=0; j < table.Count; j++) {
\r
4727 ((MetaDataElement)table[j]).Write(output);
\r
4731 // Console.WriteLine("Writing padding at " + output.Seek(0,SeekOrigin.Current));
\r
4732 for (int i=0; i < tildePadding; i++) output.Write((byte)0);
\r
4735 private void BuildTable(ArrayList table) {
\r
4736 if (table == null) return;
\r
4737 for (int j=0; j < table.Count; j++) {
\r
4738 ((MetaDataElement)table[j]).BuildTables(this);
\r
4742 internal void BuildMetaData(uint codeStartOffset) {
\r
4743 codeStart = codeStartOffset;
\r
4744 BuildTable(metaDataTables[(int)MDTable.TypeDef]);
\r
4745 BuildTable(metaDataTables[(int)MDTable.MemberRef]);
\r
4746 BuildTable(metaDataTables[(int)MDTable.GenericParam]);
\r
4747 BuildTable(metaDataTables[(int)MDTable.MethodSpec]);
\r
4748 BuildTable(metaDataTables[(int)MDTable.GenericParamConstraint]);
\r
4749 BuildTable(metaDataTables[(int)MDTable.CustomAttribute]);
\r
4750 /* for (int i=0; i < metaDataTables.Length; i++) {
\r
4751 ArrayList table = metaDataTables[i];
\r
4752 if (table != null) {
\r
4753 for (int j=0; j < table.Count; j++) {
\r
4754 ((MetaDataElement)table[j]).BuildTables(this);
\r
4760 for (int i=1; i < numStreams; i++) {
\r
4761 streams[i].EndStream();
\r
4763 CalcTildeStreamSize();
\r
4764 SetStreamOffsets();
\r
4765 byteCodePadding = NumToAlign(codeSize,4);
\r
4766 if (entryPoint != null) file.SetEntryPoint(entryPoint.Token());
\r
4769 internal void WriteByteCodes(FileImage output) {
\r
4770 for (int i=0; i < byteCodes.Count; i++) {
\r
4771 ((CILInstructions)byteCodes[i]).Write(output);
\r
4773 for (int i=0; i < byteCodePadding; i++) {
\r
4774 output.Write((byte)0);
\r
4778 internal void WriteMetaData(FileImage output) {
\r
4779 this.output = output;
\r
4780 mdStart = output.Seek(0,SeekOrigin.Current);
\r
4781 // Console.WriteLine("Writing metaData at " + Hex.Long(mdStart));
\r
4782 output.Write(MetaDataSignature);
\r
4783 output.Write((short)1); // Major Version
\r
4784 output.Write((short)1); // Minor Version ECMA = 0, PEFiles = 1
\r
4785 output.Write(0); // Reserved
\r
4786 output.Write(version.Length);
\r
4787 output.Write(version.ToCharArray()); // version string is already zero padded
\r
4788 output.Write((short)0);
\r
4789 output.Write((ushort)numStreams);
\r
4790 // write tilde header
\r
4791 output.Write(tildeStart);
\r
4792 output.Write(tildeTide + tildePadding);
\r
4793 output.Write(tildeName);
\r
4794 for (int i=1; i < numStreams; i++) streams[i].WriteHeader(output);
\r
4795 // Console.WriteLine("Writing tilde stream at " + output.Seek(0,SeekOrigin.Current) + " = " + tildeStart);
\r
4796 WriteTildeStream(output);
\r
4797 for (int i=1; i < numStreams; i++) streams[i].Write(output);
\r
4798 // Console.WriteLine("Finished Writing metaData at " + output.Seek(0,SeekOrigin.Current));
\r
4801 internal bool LargeStringsIndex() { return strings.LargeIx(); }
\r
4802 internal bool LargeGUIDIndex() { return guid.LargeIx(); }
\r
4803 internal bool LargeUSIndex() { return us.LargeIx(); }
\r
4804 internal bool LargeBlobIndex() { return blob.LargeIx(); }
\r
4806 internal bool LargeIx(MDTable tabIx) { return largeIx[(uint)tabIx]; }
\r
4809 private uint NumToAlign(uint val, uint alignVal) {
\r
4810 if ((val % alignVal) == 0) return 0;
\r
4811 return alignVal - (val % alignVal);
\r
4814 internal void WriteCodedIndex(CIx code, MetaDataElement elem, FileImage output) {
\r
4816 if (elem != null) {
\r
4817 ix = (elem.Row << CIxShiftMap[(uint)code]) | elem.GetCodedIx(code);
\r
4818 // Console.WriteLine("coded index = " + ix + " row = " + elem.Row);
\r
4820 // Console.WriteLine("elem for coded index is null");
\r
4822 if (lgeCIx[(uint)code])
\r
4825 output.Write((ushort)ix);
\r
4829 /**************************************************************************/
\r
4831 /// Base class for all Meta Data table elements
\r
4834 public abstract class MetaDataElement
\r
4837 protected ArrayList customAttributes;
\r
4838 private uint row = 0;
\r
4839 protected bool done = false;
\r
4840 protected MDTable tabIx;
\r
4842 internal MetaDataElement() { }
\r
4849 if (row == 0) row = value;
\r
4853 internal virtual uint GetCodedIx(CIx code) { return 0; }
\r
4856 /// Add a custom attribute to this item
\r
4858 /// <param name="ctorMeth">the constructor method for this attribute</param>
\r
4859 /// <param name="val">the byte value of the parameters</param>
\r
4860 public void AddCustomAttribute(Method ctorMeth, byte[] val) {
\r
4861 if (customAttributes == null) {
\r
4862 customAttributes = new ArrayList();
\r
4864 customAttributes.Add(new CustomAttribute(this,ctorMeth,val));
\r
4868 /// Add a custom attribute to this item
\r
4870 /// <param name="ctorMeth">the constructor method for this attribute</param>
\r
4871 /// <param name="val">the constant values of the parameters</param>
\r
4872 public void AddCustomAttribute(Method ctorMeth, Constant[] cVals) {
\r
4873 if (customAttributes == null) {
\r
4874 customAttributes = new ArrayList();
\r
4876 // customAttributes.Add(new CustomAttribute(this,ctorMeth,cVals));
\r
4879 internal void DoCustomAttributes(MetaData md) {
\r
4880 if (customAttributes != null) {
\r
4881 for (int i=0; i < customAttributes.Count; i++) {
\r
4882 CustomAttribute ca = (CustomAttribute)customAttributes[i];
\r
4883 ca.BuildTables(md);
\r
4888 internal uint Token() {
\r
4889 return (((uint)tabIx << 24) | row);
\r
4892 internal virtual void BuildTables(MetaData md) {
\r
4896 internal virtual uint Size(MetaData md) {
\r
4900 internal virtual void Write(FileImage output) { }
\r
4903 /**************************************************************************/
\r
4905 /// Stream in the Meta Data (#Strings, #US, #Blob and #GUID)
\r
4908 internal class MetaDataStream : BinaryWriter
\r
4910 private static readonly uint StreamHeaderSize = 8;
\r
4911 private static uint maxSmlIxSize = 0xFFFF;
\r
4913 private uint start = 0;
\r
4914 uint size = 0, tide = 1;
\r
4915 bool largeIx = false;
\r
4916 uint sizeOfHeader;
\r
4918 Hashtable htable = new Hashtable();
4919 Hashtable btable = new Hashtable ();
4921 internal MetaDataStream(char[] name, bool addInitByte) : base(new MemoryStream()) {
\r
4922 if (addInitByte) { Write((byte)0); size = 1; }
\r
4924 sizeOfHeader = StreamHeaderSize + (uint)name.Length;
\r
4927 internal MetaDataStream(char[] name, System.Text.Encoding enc, bool addInitByte) : base(new MemoryStream(),enc) {
\r
4928 if (addInitByte) { Write((byte)0); size = 1; }
\r
4930 sizeOfHeader = StreamHeaderSize + (uint)name.Length;
\r
4933 public uint Start {
\r
4942 internal uint headerSize() {
\r
4943 // Console.WriteLine(name + " stream has headersize of " + sizeOfHeader);
\r
4944 return sizeOfHeader;
\r
4947 internal void SetSize(uint siz) {
\r
4951 internal uint Size() {
\r
4955 internal bool LargeIx() {
\r
4959 internal void WriteDetails() {
\r
4960 // Console.WriteLine(name + " - size = " + size);
\r
4963 internal uint Add(string str, bool prependSize) {
\r
4964 Object val = htable[str];
\r
4966 if (val == null) {
\r
4968 htable[str] = index;
\r
4969 char[] arr = str.ToCharArray();
\r
4970 if (prependSize) CompressNum((uint)arr.Length*2+1);
\r
4973 size = (uint)Seek(0,SeekOrigin.Current);
\r
4975 index = (uint)val;
\r
4979 internal uint Add (byte[] str, bool prependSize) {
4980 Object val = btable [str];
4984 btable [str] = index;
4985 if (prependSize) CompressNum ((uint) str.Length);
4987 size = (uint) Seek (0, SeekOrigin.Current);
4995 internal uint Add(Guid guid, bool prependSize) {
\r
4996 byte [] b = guid.ToByteArray ();
4997 if (prependSize) CompressNum ((uint) b.Length);
4998 Write(guid.ToByteArray());
\r
4999 size =(uint)Seek(0,SeekOrigin.Current);
\r
5003 internal uint Add(byte[] blob) {
\r
5005 CompressNum((uint)blob.Length);
5007 size = (uint)Seek(0,SeekOrigin.Current);
\r
5011 internal uint Add(byte val, bool prependSize) {
\r
5013 if (prependSize) CompressNum (1);
5015 size = (uint)Seek(0,SeekOrigin.Current);
\r
5019 internal uint Add(sbyte val, bool prependSize) {
\r
5021 if (prependSize) CompressNum (1);
5023 size = (uint)Seek(0,SeekOrigin.Current);
\r
5027 internal uint Add(ushort val, bool prependSize) {
\r
5029 if (prependSize) CompressNum (2);
5031 size = (uint)Seek(0,SeekOrigin.Current);
\r
5035 internal uint Add(short val, bool prependSize) {
\r
5037 if (prependSize) CompressNum (2);
5039 size = (uint)Seek(0,SeekOrigin.Current);
\r
5043 internal uint Add(uint val, bool prependSize) {
\r
5045 if (prependSize) CompressNum (4);
5047 size = (uint)Seek(0,SeekOrigin.Current);
\r
5051 internal uint Add(int val, bool prependSize) {
\r
5053 if (prependSize) CompressNum (4);
5055 size = (uint)Seek(0,SeekOrigin.Current);
\r
5059 internal uint Add(ulong val, bool prependSize) {
\r
5061 if (prependSize) CompressNum (8);
5063 size = (uint)Seek(0,SeekOrigin.Current);
\r
5067 internal uint Add(long val, bool prependSize) {
\r
5069 if (prependSize) CompressNum (8);
5071 size = (uint)Seek(0,SeekOrigin.Current);
\r
5075 internal uint Add(float val, bool prependSize) {
\r
5077 if (prependSize) CompressNum (4);
5079 size = (uint)Seek(0,SeekOrigin.Current);
\r
5083 internal uint Add(double val, bool prependSize) {
\r
5085 if (prependSize) CompressNum (8);
5087 size = (uint)Seek(0,SeekOrigin.Current);
\r
5091 private void CompressNum(uint val) {
\r
5094 } else if (val < 0x3FFF) {
\r
5095 byte b1 = (byte)((val >> 8) | 0x80);
\r
5096 byte b2 = (byte)(val & FileImage.iByteMask[0]);
\r
5100 byte b1 = (byte)((val >> 24) | 0xC0);
\r
5101 byte b2 = (byte)((val & FileImage.iByteMask[2]) >> 16);
\r
5102 byte b3 = (byte)((val & FileImage.iByteMask[1]) >> 8);;
\r
5103 byte b4 = (byte)(val & FileImage.iByteMask[0]);
\r
5111 private void QuadAlign() {
\r
5112 if ((size % 4) != 0) {
\r
5113 uint pad = 4 - (size % 4);
\r
5115 for (int i=0; i < pad; i++) {
\r
5121 internal void EndStream() {
\r
5123 if (size > maxSmlIxSize) {
\r
5128 internal void WriteHeader(BinaryWriter output) {
\r
5129 output.Write(start);
\r
5130 output.Write(size);
\r
5131 output.Write(name);
\r
5134 internal virtual void Write(BinaryWriter output) {
\r
5135 // Console.WriteLine("Writing " + name + " stream at " + output.Seek(0,SeekOrigin.Current) + " = " + start);
\r
5136 MemoryStream str = (MemoryStream)BaseStream;
\r
5137 output.Write(str.ToArray());
\r
5141 /**************************************************************************/
\r
5143 /// Base class for Method Descriptors
\r
5146 public abstract class Method : Member
\r
5148 protected CallConv callConv = CallConv.Default;
\r
5149 protected Type retType;
\r
5151 internal Method(string methName, Type rType) : base(methName)
\r
5157 /// Add calling conventions to this method descriptor
\r
5159 /// <param name="cconv"></param>
\r
5160 public void AddCallConv(CallConv cconv) {
\r
5161 callConv |= cconv;
\r
5164 internal abstract void TypeSig(MemoryStream sig);
\r
5166 internal uint GetSigIx(MetaData md) {
\r
5167 MemoryStream sig = new MemoryStream();
\r
5169 return md.AddToBlobHeap(sig.ToArray());
\r
5172 internal Type GetRetType() {
\r
5177 /**************************************************************************/
\r
5179 /// Descriptor for a method defined in THIS assembly/module
\r
5183 public class MethodDef : Method
\r
5185 private static readonly ushort PInvokeImpl = 0x2000;
\r
5186 //private static readonly uint UnmanagedExport = 0x0008;
\r
5187 // private static readonly byte LocalSigByte = 0x7;
\r
5188 uint parIx = 0, textOffset = 0;
\r
5190 MetaData metaData;
\r
5191 CILInstructions code;
\r
5192 ArrayList securityActions = new ArrayList();
\r
5196 ushort methFlags = 0, implFlags = 0;
\r
5197 int maxStack = 0, numPars = 0;
\r
5198 bool entryPoint = false;
\r
5199 LocalSig localSig;
\r
5200 ArrayList varArgSigList;
\r
5201 ImplMap pinvokeImpl;
\r
5204 internal MethodDef(MetaData md, string name, Type retType, Param[] pars) : base(name,retType) {
\r
5207 if (parList != null) numPars = parList.Length;
\r
5208 tabIx = MDTable.Method;
\r
5211 internal MethodDef(MetaData md, MethAttr mAttrSet, ImplAttr iAttrSet, string name, Type retType, Param[] pars) : base(name,retType) {
\r
5214 if (parList != null) numPars = parList.Length;
\r
5215 // Console.WriteLine("Creating method " + name + " with " + numPars + " parameters");
\r
5216 methFlags = (ushort)mAttrSet;
\r
5217 implFlags = (ushort)iAttrSet;
\r
5218 tabIx = MDTable.Method;
\r
5221 internal Param[] GetPars() {
\r
5226 /// Add some attributes to this method descriptor
\r
5228 /// <param name="ma">the attributes to be added</param>
\r
5229 public void AddMethAttribute(MethAttr ma) {
\r
5230 methFlags |= (ushort)ma;
\r
5234 /// Add some implementation attributes to this method descriptor
\r
5236 /// <param name="ia">the attributes to be added</param>
\r
5237 public void AddImplAttribute(ImplAttr ia) {
\r
5238 implFlags |= (ushort)ia;
\r
5241 public void AddPInvokeInfo(ModuleRef scope, string methName,
\r
5242 PInvokeAttr callAttr) {
\r
5243 pinvokeImpl = new ImplMap((ushort)callAttr,this,methName,scope);
\r
5244 methFlags |= PInvokeImpl;
\r
5248 /// Add a named generic type parameter
\r
5250 public GenericParameter AddGenericParameter (short index, string name) {
\r
5251 GenericParameter gp = new GenericParameter (this, metaData, index, name);
5252 metaData.AddToTable (MDTable.GenericParam, gp);
\r
5257 /// Set the maximum stack height for this method
\r
5259 /// <param name="maxStack">the maximum height of the stack</param>
\r
5260 public void SetMaxStack(int maxStack) {
\r
5261 this.maxStack = maxStack;
\r
5265 /// Add local variables to this method
\r
5267 /// <param name="locals">the locals to be added</param>
\r
5268 /// <param name="initLocals">are locals initialised to default values</param>
\r
5269 public void AddLocals(Local[] locals, bool initLocals) {
\r
5270 this.locals = locals;
\r
5271 this.initLocals = initLocals;
\r
5275 /// Mark this method as having an entry point
\r
5277 public void DeclareEntryPoint() {
\r
5278 entryPoint = true;
\r
5282 /// Create a code buffer for this method to add the IL instructions to
\r
5284 /// <returns>a buffer for this method's IL instructions</returns>
\r
5285 public CILInstructions CreateCodeBuffer() {
\r
5286 code = new CILInstructions(metaData);
\r
5291 /// Make a method reference descriptor for this method to be used
\r
5292 /// as a callsite signature for this vararg method
\r
5294 /// <param name="optPars">the optional pars for the vararg method call</param>
\r
5295 /// <returns></returns>
\r
5296 public MethodRef MakeVarArgSignature(Type[] optPars) {
\r
5297 Type[] pars = new Type[numPars];
\r
5298 MethodRef varArgSig;
\r
5299 for (int i=0; i < numPars; i++) {
\r
5300 pars[i] = parList[i].GetParType();
\r
5302 varArgSig = new MethodRef(this,name,retType,pars,true,optPars);
\r
5304 if (varArgSigList == null)
\r
5305 varArgSigList = new ArrayList ();
\r
5306 varArgSigList.Add (varArgSig);
\r
5310 internal sealed override void TypeSig(MemoryStream sig) {
\r
5311 sig.WriteByte((byte)callConv);
\r
5312 MetaData.CompressNum((uint)numPars,sig);
\r
5313 retType.TypeSig(sig);
\r
5314 for (ushort i=0; i < numPars; i++) {
\r
5315 parList[i].seqNo = (ushort)(i+1);
\r
5316 parList[i].TypeSig(sig);
\r
5320 internal sealed override void BuildTables(MetaData md) {
\r
5322 if (pinvokeImpl != null) {
\r
5323 md.AddToTable(MDTable.ImplMap,pinvokeImpl);
\r
5324 pinvokeImpl.BuildTables(md);
\r
5326 if (entryPoint) md.SetEntryPoint(this);
\r
5327 uint locToken = 0;
\r
5328 if (locals != null) {
\r
5329 localSig = new LocalSig(locals);
\r
5330 md.AddToTable(MDTable.StandAloneSig,localSig);
\r
5331 localSig.BuildTables(md);
\r
5332 locToken = localSig.Token();
\r
5334 if (code != null) {
\r
5335 code.CheckCode(locToken,initLocals,maxStack);
\r
5336 textOffset = md.AddCode(code);
\r
5338 nameIx = md.AddToStringsHeap(name);
\r
5339 sigIx = GetSigIx(md);
\r
5340 parIx = md.TableIndex(MDTable.Param);
\r
5341 for (int i=0; i < numPars; i++) {
\r
5342 md.AddToTable(MDTable.Param,parList[i]);
\r
5343 parList[i].BuildTables(md);
\r
5345 if (varArgSigList != null) {
\r
5346 foreach (MethodRef varArgSig in varArgSigList) {
\r
5347 md.AddToTable(MDTable.MemberRef,varArgSig);
\r
5348 varArgSig.BuildTables(md);
\r
5351 DoCustomAttributes (md);
\r
5352 // Console.WriteLine("method has " + numPars + " parameters");
\r
5356 internal sealed override uint Size(MetaData md) {
\r
5357 return 8 + md.StringsIndexSize() + md.BlobIndexSize() + md.TableIndexSize(MDTable.Param);
\r
5360 internal sealed override void Write(FileImage output) {
\r
5361 if (ZeroRva ()) output.Write(0);
\r
5362 else output.WriteCodeRVA(textOffset);
\r
5363 output.Write(implFlags);
\r
5364 output.Write(methFlags);
\r
5365 output.StringsIndex(nameIx);
\r
5366 output.BlobIndex(sigIx);
\r
5367 output.WriteIndex(MDTable.Param,parIx);
\r
5370 internal bool ZeroRva () {
5371 return (((methFlags & (ushort)MethAttr.Abstract) != 0) ||
5372 ((implFlags & (ushort)ImplAttr.Runtime) != 0) ||
5373 ((implFlags & (ushort)ImplAttr.InternalCall) != 0) ||
5374 (pinvokeImpl != null)); // TODO: Not entirely true but works for now
5377 internal sealed override uint GetCodedIx(CIx code) {
\r
5379 case (CIx.HasCustomAttr) : return 0;
\r
5380 case (CIx.HasDeclSecurity) : return 1;
\r
5381 case (CIx.MemberRefParent) : return 3;
\r
5382 case (CIx.MethodDefOrRef) : return 0;
\r
5383 case (CIx.MemberForwarded) : return 1;
\r
5384 case (CIx.CustomAttributeType) : return 2;
\r
5385 case (CIx.TypeOrMethodDef) : return 1;
\r
5391 /**************************************************************************/
\r
5393 /// Descriptor for an overriding method (.override)
\r
5395 public class MethodImpl : MetaDataElement
\r
5398 Method header, body;
\r
5400 internal MethodImpl(ClassDef par, Method decl, Method bod) {
\r
5404 tabIx = MDTable.MethodImpl;
\r
5407 internal sealed override uint Size(MetaData md) {
\r
5408 return md.TableIndexSize(MDTable.TypeDef) + 2 * md.CodedIndexSize(CIx.MethodDefOrRef);
\r
5411 internal sealed override void Write(FileImage output) {
\r
5412 output.WriteIndex(MDTable.TypeDef,parent.Row);
\r
5413 output.WriteCodedIndex(CIx.MethodDefOrRef,body);
\r
5414 output.WriteCodedIndex(CIx.MethodDefOrRef,header);
\r
5418 /**************************************************************************/
\r
5420 /// Descriptor for a method defined in another assembly/module
\r
5422 public class MethodRef : Method
\r
5424 private static readonly byte Sentinel = 0x41;
\r
5425 Type[] parList, optParList;
\r
5426 MetaDataElement parent;
\r
5427 uint numPars = 0, numOptPars = 0;
\r
5429 internal MethodRef(MetaDataElement paren, string name, Type retType,
\r
5430 Type[] pars, bool varArgMeth, Type[] optPars) : base(name,retType) {
\r
5433 if (parList != null) numPars = (uint)parList.Length;
\r
5435 optParList = optPars;
\r
5436 if (optParList != null) numOptPars = (uint)optParList.Length;
\r
5437 callConv = CallConv.Vararg;
\r
5441 internal sealed override void TypeSig(MemoryStream sig) {
\r
5442 sig.WriteByte((byte)callConv);
\r
5443 MetaData.CompressNum(numPars+numOptPars,sig);
\r
5444 retType.TypeSig(sig);
\r
5445 for (int i=0; i < numPars; i++) {
\r
5446 parList[i].TypeSig(sig);
\r
5448 if (numOptPars > 0) {
\r
5449 sig.WriteByte(Sentinel);
\r
5450 for (int i=0; i < numOptPars; i++) {
\r
5451 optParList[i].TypeSig(sig);
\r
5456 internal sealed override void BuildTables(MetaData md) {
\r
5458 nameIx = md.AddToStringsHeap(name);
\r
5459 sigIx = GetSigIx(md);
\r
5463 internal sealed override uint Size(MetaData md) {
\r
5464 return md.CodedIndexSize(CIx.MemberRefParent) + md.StringsIndexSize() + md.BlobIndexSize();
\r
5467 internal sealed override void Write(FileImage output) {
\r
5468 output.WriteCodedIndex(CIx.MemberRefParent,parent);
\r
5469 output.StringsIndex(nameIx);
\r
5470 output.BlobIndex(sigIx);
\r
5473 internal sealed override uint GetCodedIx(CIx code) {
\r
5475 case (CIx.HasCustomAttr) : return 6;
\r
5476 case (CIx.MethodDefOrRef) : return 1;
\r
5477 case (CIx.CustomAttributeType) : return 3;
\r
5483 /**************************************************************************/
\r
5485 /// Descriptor for Property and Event methods
\r
5487 public class MethodSemantics : MetaDataElement {
\r
5489 Feature.MethodType type;
\r
5491 Feature eventOrProp;
\r
5493 internal MethodSemantics(Feature.MethodType mType, MethodDef method, Feature feature) {
\r
5496 eventOrProp = feature;
\r
5497 tabIx = MDTable.MethodSemantics;
\r
5500 internal sealed override uint Size(MetaData md) {
\r
5501 return 2 + md.TableIndexSize(MDTable.Method) + md.CodedIndexSize(CIx.HasSemantics);
\r
5504 internal sealed override void Write(FileImage output) {
\r
5505 output.Write((ushort)type);
\r
5506 output.WriteIndex(MDTable.Method,meth.Row);
\r
5507 output.WriteCodedIndex(CIx.HasSemantics,eventOrProp);
\r
5511 /**************************************************************************/
\r
5513 /// Descriptor for a FunctionPointer type
\r
5516 public class MethPtrType : Type
\r
5518 // MethPtrType == FNPTR
\r
5523 /// Create a new function pointer type
\r
5525 /// <param name="meth">the function to be referenced</param>
\r
5526 public MethPtrType(Method meth) : base(0x1B)
\r
5529 tabIx = MDTable.TypeSpec;
\r
5532 internal sealed override void TypeSig(MemoryStream str) {
\r
5533 str.WriteByte(typeIndex);
\r
5534 method.TypeSig(str);
\r
5537 internal sealed override void BuildTables(MetaData md) {
\r
5539 MemoryStream sig = new MemoryStream();
\r
5541 sigIx = md.AddToBlobHeap(sig.ToArray());
\r
5545 internal sealed override uint Size(MetaData md) {
\r
5546 return md.BlobIndexSize();
\r
5549 internal sealed override void Write(FileImage output) {
\r
5550 output.BlobIndex(sigIx);
\r
5553 internal sealed override uint GetCodedIx(CIx code) { return 0x1B; }
\r
5556 /**************************************************************************/
\r
5558 /// Descriptor for THIS module
\r
5560 public class Module : ResolutionScope
\r
5565 internal Module(string name, MetaData md) : base(name,md) {
\r
5566 mvid = Guid.NewGuid();
\r
5567 mvidIx = md.AddToGUIDHeap(mvid);
\r
5568 tabIx = MDTable.Module;
\r
5571 internal sealed override uint Size(MetaData md) {
\r
5572 return 2 + md.StringsIndexSize() + 3 * md.GUIDIndexSize();
\r
5575 internal sealed override void Write(FileImage output) {
\r
5576 output.Write((short)0);
\r
5577 output.StringsIndex(nameIx);
\r
5578 output.GUIDIndex(mvidIx);
\r
5579 output.GUIDIndex(0);
\r
5580 output.GUIDIndex(0);
\r
5583 internal sealed override uint GetCodedIx(CIx code) {
\r
5585 case (CIx.HasCustomAttr) : return 7;
\r
5586 case (CIx.ResolutionScope) : return 0;
\r
5592 /**************************************************************************/
\r
5594 /// Descriptor for another module in THIS assembly
\r
5596 public class ModuleRef : ResolutionScope
\r
5599 internal ModuleRef(MetaData md, string name) : base(name,md) {
\r
5600 tabIx = MDTable.ModuleRef;
\r
5604 /// Add a class to this external module. This is a class declared in
\r
5605 /// another module of THIS assembly.
\r
5607 /// <param name="nsName">name space name</param>
\r
5608 /// <param name="name">class name</param>
\r
5609 /// <returns>a descriptor for this class in another module</returns>
\r
5610 public ClassRef AddClass(string nsName, string name, bool exportClass) {
\r
5611 ClassRef aClass = new ClassRef(nsName,name,metaData);
\r
5612 metaData.AddToTable(MDTable.TypeRef,aClass);
\r
5613 aClass.SetParent(this);
\r
5618 /// Make a file descriptor to correspond to this module. The file
\r
5619 /// descriptor will have the same name as the module descriptor
\r
5621 /// <param name="hashBytes">the hash of the file</param>
\r
5622 /// <param name="hasMetaData">the file contains metadata</param>
\r
5623 /// <param name="entryPoint">the program entry point is in this file</param>
\r
5624 /// <returns>a descriptor for the file which contains this module</returns>
\r
5625 public FileRef MakeFile(byte[] hashBytes, bool hasMetaData, bool entryPoint) {
\r
5626 FileRef file = new FileRef(nameIx,hashBytes,hasMetaData,entryPoint,metaData);
\r
5627 metaData.AddToTable(MDTable.File,file);
\r
5632 /// Add a value class to this module. This is a class declared in
\r
5633 /// another module of THIS assembly.
\r
5635 /// <param name="nsName">name space name</param>
\r
5636 /// <param name="name">class name</param>
\r
5637 /// <returns></returns>
\r
5638 public ClassRef AddValueClass(string nsName, string name) {
\r
5639 ClassRef aClass = new ClassRef(nsName,name,metaData);
\r
5640 metaData.AddToTable(MDTable.TypeRef,aClass);
\r
5641 aClass.SetParent(this);
\r
5642 aClass.MakeValueClass();
\r
5647 /// Add a class which is declared public in this external module of
\r
5648 /// THIS assembly. This class will be exported from this assembly.
\r
5649 /// The ilasm syntax for this is .extern class
\r
5651 /// <param name="attrSet">attributes of the class to be exported</param>
\r
5652 /// <param name="nsName">name space name</param>
\r
5653 /// <param name="name">external class name</param>
\r
5654 /// <param name="declFile">the file where the class is declared</param>
\r
5655 /// <param name="isValueClass">is this class a value type?</param>
\r
5656 /// <returns>a descriptor for this external class</returns>
\r
5657 public ExternClassRef AddExternClass(TypeAttr attrSet, string nsName,
\r
5658 string name, FileRef declFile,
\r
5659 bool isValueClass) {
\r
5660 ExternClassRef cRef = new ExternClassRef(attrSet,nsName,name,declFile,metaData);
\r
5661 metaData.AddToTable(MDTable.TypeRef,cRef);
\r
5662 cRef.SetParent(this);
\r
5663 if (isValueClass) cRef.MakeValueClass();
\r
5668 /// Add a "global" method in another module
\r
5670 /// <param name="name">method name</param>
\r
5671 /// <param name="retType">return type</param>
\r
5672 /// <param name="pars">method parameter types</param>
\r
5673 /// <returns>a descriptor for this method in anther module</returns>
\r
5674 public MethodRef AddMethod(string name, Type retType, Type[] pars) {
\r
5675 MethodRef meth = new MethodRef(this,name,retType,pars,false,null);
\r
5676 metaData.AddToTable(MDTable.MemberRef,meth);
\r
5681 /// Add a vararg method to this class
\r
5683 /// <param name="name">method name</param>
\r
5684 /// <param name="retType">return type</param>
\r
5685 /// <param name="pars">parameter types</param>
\r
5686 /// <param name="optPars">optional param types for this vararg method</param>
\r
5687 /// <returns>a descriptor for this method</returns>
\r
5688 public MethodRef AddVarArgMethod(string name, Type retType,
\r
5689 Type[] pars, Type[] optPars) {
\r
5690 MethodRef meth = new MethodRef(this,name,retType,pars,true,optPars);
\r
5691 metaData.AddToTable(MDTable.MemberRef,meth);
\r
5696 /// Add a field in another module
\r
5698 /// <param name="name">field name</param>
\r
5699 /// <param name="fType">field type</param>
\r
5700 /// <returns>a descriptor for this field in another module</returns>
\r
5701 public FieldRef AddField(string name, Type fType) {
\r
5702 FieldRef field = new FieldRef(this,name,fType);
\r
5703 metaData.AddToTable(MDTable.MemberRef,field);
\r
5707 internal sealed override uint Size(MetaData md) {
\r
5708 return md.StringsIndexSize();
\r
5711 internal sealed override void Write(FileImage output) {
\r
5712 output.StringsIndex(nameIx);
\r
5715 internal sealed override uint GetCodedIx(CIx code) {
\r
5717 case (CIx.HasCustomAttr) : return 12;
\r
5718 case (CIx.MemberRefParent) : return 2;
\r
5719 case (CIx.ResolutionScope) : return 1;
\r
5725 /**************************************************************************/
\r
5727 /// Descriptors for native types used for marshalling
\r
5729 public class NativeType {
\r
5730 public static readonly NativeType Void = new NativeType(0x01);
\r
5731 public static readonly NativeType Boolean = new NativeType(0x02);
\r
5732 public static readonly NativeType Int8 = new NativeType(0x03);
\r
5733 public static readonly NativeType UInt8 = new NativeType(0x04);
\r
5734 public static readonly NativeType Int16 = new NativeType(0x05);
\r
5735 public static readonly NativeType UInt16 = new NativeType(0x06);
\r
5736 public static readonly NativeType Int32 = new NativeType(0x07);
\r
5737 public static readonly NativeType UInt32 = new NativeType(0x08);
\r
5738 public static readonly NativeType Int64 = new NativeType(0x09);
\r
5739 public static readonly NativeType UInt64 = new NativeType(0x0A);
\r
5740 public static readonly NativeType Float32 = new NativeType(0x0B);
\r
5741 public static readonly NativeType Float64 = new NativeType(0x0C);
\r
5742 public static readonly NativeType Currency = new NativeType(0x0F);
\r
5743 public static readonly NativeType BStr = new NativeType(0x13);
\r
5744 public static readonly NativeType LPStr = new NativeType(0x14);
\r
5745 public static readonly NativeType LPWStr = new NativeType(0x15);
\r
5746 public static readonly NativeType LPTStr = new NativeType(0x16);
\r
5747 public static readonly NativeType FixedSysString = new NativeType(0x17);
\r
5748 public static readonly NativeType IUnknown = new NativeType(0x19);
\r
5749 public static readonly NativeType IDispatch = new NativeType(0x1A);
\r
5750 public static readonly NativeType Struct = new NativeType(0x1B);
\r
5751 public static readonly NativeType Interface = new NativeType(0x1C);
\r
5752 public static readonly NativeType Int = new NativeType(0x1F);
\r
5753 public static readonly NativeType UInt = new NativeType(0x20);
\r
5754 public static readonly NativeType ByValStr = new NativeType(0x22);
\r
5755 public static readonly NativeType AnsiBStr = new NativeType(0x23);
\r
5756 public static readonly NativeType TBstr = new NativeType(0x24);
\r
5757 public static readonly NativeType VariantBool = new NativeType(0x25);
\r
5758 public static readonly NativeType FuncPtr = new NativeType(0x26);
\r
5759 public static readonly NativeType AsAny = new NativeType(0x28);
\r
5761 protected byte typeIndex;
\r
5763 internal NativeType(byte tyIx) { typeIndex = tyIx; }
\r
5765 internal byte GetTypeIndex() { return typeIndex; }
\r
5767 internal virtual byte[] ToBlob() {
\r
5768 byte[] bytes = new byte[1];
\r
5769 bytes[0] = GetTypeIndex();
\r
5775 public class NativeArray : NativeType
\r
5777 NativeType elemType;
\r
5778 uint len = 0, parNum = 0;
\r
5781 public NativeArray(NativeType elemType) : base(0x2A) {
\r
5782 this.elemType = elemType;
\r
5785 public NativeArray(NativeType elemType, int len) : base(0x2A) {
\r
5786 this.elemType = elemType;
\r
5790 public NativeArray(NativeType elemType, int numElem, int parNumForLen) : base(0x2A) {
\r
5791 this.elemType = elemType;
\r
5792 len = (uint)numElem;
\r
5793 parNum = (uint)parNumForLen;
\r
5796 internal override byte[] ToBlob() {
\r
5797 MemoryStream str = new MemoryStream();
\r
5798 str.WriteByte(GetTypeIndex());
\r
5799 if (elemType == null) str.WriteByte(0x50); // no info (MAX)
\r
5800 else str.WriteByte(elemType.GetTypeIndex());
\r
5801 MetaData.CompressNum(parNum,str);
\r
5803 MetaData.CompressNum(len,str);
\r
5804 return str.ToArray();
\r
5809 public class SafeArray : NativeType
\r
5811 SafeArrayType elemType;
\r
5813 public SafeArray(SafeArrayType elemType) : base(0x1D) {
\r
5814 this.elemType = elemType;
\r
5817 internal override byte[] ToBlob() {
\r
5818 byte[] bytes = new byte[2];
\r
5819 bytes[0] = GetTypeIndex();
\r
5820 bytes[1] = (byte)elemType;
\r
5826 public class FixedArray : NativeType
\r
5828 NativeType elemType;
\r
5831 public FixedArray(NativeType elemType, int numElems) : base(0x1E) {
\r
5832 this.elemType = elemType;
\r
5833 numElem = (uint)numElems;
\r
5836 internal override byte[] ToBlob() {
\r
5837 MemoryStream str = new MemoryStream();
\r
5838 str.WriteByte(GetTypeIndex());
\r
5839 MetaData.CompressNum(numElem,str);
\r
5840 if (elemType == null) str.WriteByte(0x50); // no info (MAX)
\r
5841 else str.WriteByte(elemType.GetTypeIndex());
\r
5842 return str.ToArray();
\r
5847 public class CustomMarshaller : NativeType
\r
5850 string marshallerName;
\r
5853 public CustomMarshaller(string typeNameOrGUID, string marshallerName,
\r
5854 string optCookie) : base(0x2C) {
\r
5855 typeName = typeNameOrGUID;
\r
5856 this.marshallerName = marshallerName;
\r
5857 cookie = optCookie;
\r
5860 internal override byte[] ToBlob() {
\r
5861 MemoryStream str = new MemoryStream();
\r
5862 BinaryWriter bw = new BinaryWriter(str,new UTF8Encoding());
\r
5863 bw.Write(GetTypeIndex());
\r
5864 bw.Write(typeName.ToCharArray());
\r
5865 bw.Write((byte)0);
\r
5866 bw.Write(marshallerName.ToCharArray());
\r
5867 bw.Write((byte)0);
\r
5868 if (cookie != null) bw.Write(cookie.ToCharArray());
\r
5869 bw.Write((byte)0);
\r
5871 return str.ToArray();
\r
5875 /**************************************************************************/
\r
5877 /// Descriptor for a parameter of a method defined in this assembly/module
\r
5879 public class Param : MetaDataElement
\r
5881 private static readonly ushort hasDefault = 0x1000;
\r
5882 private static readonly ushort hasFieldMarshal = 0x2000;
\r
5886 internal ushort seqNo = 0;
\r
5888 ConstantElem defaultVal;
\r
5890 FieldMarshal marshalInfo;
\r
5893 /// Create a new parameter for a method
\r
5895 /// <param name="mode">param mode (in, out, opt)</param>
\r
5896 /// <param name="parName">parameter name</param>
\r
5897 /// <param name="parType">parameter type</param>
\r
5898 public Param(ParamAttr mode, string parName, Type parType) {
\r
5901 parMode = (ushort)mode;
\r
5902 tabIx = MDTable.Param;
\r
5906 /// Add a default value to this parameter
\r
5908 /// <param name="c">the default value for the parameter</param>
\r
5909 public void AddDefaultValue(Constant cVal) {
\r
5910 defaultVal = new ConstantElem(this,cVal);
\r
5911 parMode |= hasDefault;
\r
5915 /// Add marshalling information about this parameter
\r
5917 public void AddMarshallInfo(NativeType marshallType) {
\r
5918 parMode |= hasFieldMarshal;
\r
5919 marshalInfo = new FieldMarshal(this,marshallType);
\r
5922 internal Type GetParType() { return pType; }
\r
5924 internal sealed override void BuildTables(MetaData md) {
\r
5926 nameIx = md.AddToStringsHeap(pName);
\r
5927 if (defaultVal != null) {
\r
5928 md.AddToTable(MDTable.Constant,defaultVal);
\r
5929 defaultVal.BuildTables(md);
\r
5931 if (marshalInfo != null) {
\r
5932 md.AddToTable(MDTable.FieldMarshal,marshalInfo);
\r
5933 marshalInfo.BuildTables(md);
\r
5938 internal void TypeSig(MemoryStream str) {
\r
5939 pType.TypeSig(str);
\r
5942 internal sealed override uint Size(MetaData md) {
\r
5943 return 4 + md.StringsIndexSize();
\r
5946 internal sealed override void Write(FileImage output) {
\r
5947 output.Write(parMode);
\r
5948 output.Write(seqNo);
\r
5949 output.StringsIndex(nameIx);
\r
5952 internal sealed override uint GetCodedIx(CIx code) {
\r
5954 case (CIx.HasCustomAttr) : return 4;
\r
5955 case (CIx.HasConst) : return 1;
\r
5956 case (CIx.HasFieldMarshal) : return 1;
\r
5962 /**************************************************************************/
\r
5964 /// Base class for the PEFile (starting point)
\r
5966 public class PEFile
\r
5968 private static readonly string mscorlibName = "mscorlib";
\r
5969 private Module thisMod;
\r
5970 private ClassDef moduleClass;
\r
5971 private ArrayList classRefList = new ArrayList();
\r
5972 private ArrayList classDefList = new ArrayList();
\r
5973 private Assembly thisAssembly;
\r
5974 private int corFlags = 1;
\r
5975 FileImage fileImage;
\r
5976 MetaData metaData;
\r
5979 /// Create a new PEFile. Each PEFile is a module.
\r
5981 /// <param name="name">module name, also used for the file name</param>
\r
5982 /// <param name="isDLL">create a .dll or .exe file</param>
\r
5983 /// <param name="hasAssembly">this file is an assembly and
\r
5984 /// will contain the assembly manifest. The assembly name is the
\r
5985 /// same as the module name</param>
\r
5986 public PEFile(string name, bool isDLL, bool hasAssembly) {
\r
5987 // Console.WriteLine(Hex.Byte(0x12));
\r
5988 // Console.WriteLine(Hex.Short(0x1234));
\r
5989 // Console.WriteLine(Hex.Int(0x12345678));
\r
5990 string fName = MakeFileName(null,name,isDLL);
\r
5991 fileImage = new FileImage(isDLL,fName);
\r
5992 InitPEFile(name, fName, hasAssembly);
\r
5996 /// Create a new PEFile. Each PEFile is a module.
\r
5998 /// <param name="name">module name, also used for the file name</param>
\r
5999 /// <param name="isDLL">create a .dll or .exe file</param>
\r
6000 /// <param name="hasAssembly">this file is an assembly and
\r
6001 /// will contain the assembly manifest. The assembly name is the
\r
6002 /// same as the module name</param>
\r
6003 /// <param name="outputDir">write the PEFile to this directory. If this
\r
6004 /// string is null then the output will be to the current directory</param>
\r
6005 public PEFile(string name, bool isDLL, bool hasAssembly, string outputDir) {
\r
6006 // Console.WriteLine(Hex.Byte(0x12));
\r
6007 // Console.WriteLine(Hex.Short(0x1234));
\r
6008 // Console.WriteLine(Hex.Int(0x12345678));
\r
6009 string fName = MakeFileName(outputDir,name,isDLL);
\r
6010 fileImage = new FileImage(isDLL,fName);
\r
6011 InitPEFile(name, fName, hasAssembly);
\r
6015 /// Create a new PEFile
\r
6017 /// <param name="name">module name</param>
\r
6018 /// <param name="isDLL">create a .dll or .exe</param>
\r
6019 /// <param name="hasAssembly">this PEfile is an assembly and
\r
6020 /// will contain the assemly manifest. The assembly name is the
\r
6021 /// same as the module name</param>
\r
6022 /// <param name="outStream">write the PEFile to this stream instead
\r
6023 /// of to a new file</param>
\r
6024 public PEFile(string name, bool isDLL, bool hasAssembly, Stream outStream) {
\r
6025 fileImage = new FileImage(isDLL,outStream);
\r
6026 InitPEFile(name, MakeFileName(null,name,isDLL), hasAssembly);
\r
6029 public PEFile(string name, string module_name, bool isDLL, bool hasAssembly, Stream outStream) {
\r
6030 fileImage = new FileImage(isDLL,outStream);
\r
6031 InitPEFile(name, (module_name == null ? MakeFileName(null,name,isDLL) : module_name), hasAssembly);
\r
6034 private void InitPEFile(string name, string fName, bool hasAssembly) {
\r
6035 metaData = fileImage.GetMetaData();
\r
6036 thisMod = new Module(fName,metaData);
\r
6037 if (hasAssembly) {
\r
6038 thisAssembly = new Assembly(name,metaData);
\r
6039 metaData.AddToTable(MDTable.Assembly,thisAssembly);
\r
6041 moduleClass = AddClass(TypeAttr.Private,"","<Module>");
\r
6042 moduleClass.SpecialNoSuper();
\r
6043 metaData.AddToTable(MDTable.Module,thisMod);
\r
6047 public ClassDef ModuleClass {
6048 get { return moduleClass; }
6052 /// Set the subsystem (.subsystem) (Default is Windows Console mode)
\r
6054 /// <param name="subS">subsystem value</param>
\r
6055 public void SetSubSystem(SubSystem subS) {
\r
6056 fileImage.subSys = subS;
\r
6060 /// Set the flags (.corflags)
\r
6062 /// <param name="flags">the flags value</param>
\r
6063 public void SetCorFlags(int flags) {
\r
6067 private string MakeFileName(string dirName, string name, bool isDLL) {
\r
6068 string result = "";
\r
6069 if ((dirName != null) && (dirName.CompareTo("") != 0)) {
\r
6071 if (!dirName.EndsWith("\\")) result += "\\";
\r
6075 // if (isDLL) result += ".dll"; else result += ".exe";
\r
6081 /// Add an external assembly to this PEFile (.assembly extern)
\r
6083 /// <param name="assemName">the external assembly name</param>
\r
6084 /// <returns>a descriptor for this external assembly</returns>
\r
6085 public AssemblyRef AddExternAssembly(string assemName) {
\r
6086 if (assemName.CompareTo(mscorlibName) == 0) return metaData.mscorlib;
\r
6087 AssemblyRef anAssem = new AssemblyRef(metaData,assemName);
\r
6088 metaData.AddToTable(MDTable.AssemblyRef,anAssem);
\r
6089 // Console.WriteLine("Adding assembly " + assemName);
\r
6094 /// Add an external module to this PEFile (.module extern)
\r
6096 /// <param name="name">the external module name</param>
\r
6097 /// <returns>a descriptor for this external module</returns>
\r
6098 public ModuleRef AddExternModule(string name) {
\r
6099 ModuleRef modRef = new ModuleRef(metaData,name);
\r
6100 metaData.AddToTable(MDTable.ModuleRef,modRef);
\r
6105 /// Add a "global" method to this module
\r
6107 /// <param name="name">method name</param>
\r
6108 /// <param name="retType">return type</param>
\r
6109 /// <param name="pars">method parameters</param>
\r
6110 /// <returns>a descriptor for this new "global" method</returns>
\r
6111 public MethodDef AddMethod(string name, Type retType, Param[] pars) {
\r
6112 return moduleClass.AddMethod(name,retType,pars);
\r
6116 /// Add a "global" method to this module
\r
6118 /// <param name="mAtts">method attributes</param>
\r
6119 /// <param name="iAtts">method implementation attributes</param>
\r
6120 /// <param name="name">method name</param>
\r
6121 /// <param name="retType">return type</param>
\r
6122 /// <param name="pars">method parameters</param>
\r
6123 /// <returns>a descriptor for this new "global" method</returns>
\r
6124 public MethodDef AddMethod(MethAttr mAtts, ImplAttr iAtts, string name, Type retType, Param[] pars) {
\r
6125 return moduleClass.AddMethod(mAtts,iAtts,name,retType,pars);
\r
6128 public MethodRef AddMethodToTypeSpec (Type item, string name, Type retType, Type[] pars) {
\r
6129 MethodRef meth = new MethodRef (item.GetTypeSpec (metaData), name, retType, pars, false, null);
\r
6130 metaData.AddToTable (MDTable.MemberRef,meth);
\r
6134 public MethodRef AddVarArgMethodToTypeSpec (Type item, string name, Type retType,
\r
6135 Type[] pars, Type[] optPars) {
\r
6136 MethodRef meth = new MethodRef(item.GetTypeSpec (metaData), name,retType,pars,true,optPars);
\r
6137 metaData.AddToTable(MDTable.MemberRef,meth);
\r
6141 public FieldRef AddFieldToTypeSpec (Type item, string name, Type fType) {
\r
6142 FieldRef field = new FieldRef (item.GetTypeSpec (metaData), name,fType);
\r
6143 metaData.AddToTable (MDTable.MemberRef,field);
\r
6147 public void AddMethodSpec (Method m, GenericMethodSig g_sig)
6149 MethodSpec ms = new MethodSpec (m, g_sig);
6150 metaData.AddToTable (MDTable.MethodSpec, ms);
6154 /// Add a "global" field to this module
\r
6156 /// <param name="name">field name</param>
\r
6157 /// <param name="fType">field type</param>
\r
6158 /// <returns>a descriptor for this new "global" field</returns>
\r
6159 public FieldDef AddField(string name, Type fType) {
\r
6160 return moduleClass.AddField(name,fType);
\r
6164 /// Add a "global" field to this module
\r
6166 /// <param name="attrSet">attributes of this field</param>
\r
6167 /// <param name="name">field name</param>
\r
6168 /// <param name="fType">field type</param>
\r
6169 /// <returns>a descriptor for this new "global" field</returns>
\r
6170 public FieldDef AddField(FieldAttr attrSet, string name, Type fType) {
\r
6171 return moduleClass.AddField(attrSet,name,fType);
\r
6175 /// Add a class to this module
\r
6177 /// <param name="attrSet">attributes of this class</param>
\r
6178 /// <param name="nsName">name space name</param>
\r
6179 /// <param name="name">class name</param>
\r
6180 /// <returns>a descriptor for this new class</returns>
\r
6181 public ClassDef AddClass(TypeAttr attrSet, string nsName, string name) {
\r
6182 ClassDef aClass = new ClassDef(attrSet,nsName,name,metaData);
\r
6183 metaData.AddToTable(MDTable.TypeDef,aClass);
\r
6188 /// Add a class which extends System.ValueType to this module
\r
6190 /// <param name="attrSet">attributes of this class</param>
\r
6191 /// <param name="nsName">name space name</param>
\r
6192 /// <param name="name">class name</param>
\r
6193 /// <returns>a descriptor for this new class</returns>
\r
6194 public ClassDef AddValueClass(TypeAttr attrSet, string nsName, string name) {
\r
6195 ClassDef aClass = new ClassDef(attrSet,nsName,name,metaData);
\r
6196 aClass.MakeValueClass();
\r
6197 metaData.AddToTable(MDTable.TypeDef,aClass);
\r
6202 /// Add a class to this module
\r
6204 /// <param name="attrSet">attributes of this class</param>
\r
6205 /// <param name="nsName">name space name</param>
\r
6206 /// <param name="name">class name</param>
\r
6207 /// <param name="superType">super type of this class (extends)</param>
\r
6208 /// <returns>a descriptor for this new class</returns>
\r
6209 public ClassDef AddClass(TypeAttr attrSet, string nsName, string name, Class superType) {
\r
6210 ClassDef aClass = new ClassDef(attrSet,nsName,name,metaData);
\r
6211 aClass.SetSuper(superType);
\r
6212 metaData.AddToTable(MDTable.TypeDef,aClass);
\r
6216 public FileRef AddFile(string fName, byte[] hashBytes, bool hasMetaData, bool entryPoint) {
\r
6217 FileRef file = new FileRef(fName,hashBytes,hasMetaData,entryPoint,metaData);
\r
6218 metaData.AddToTable(MDTable.File,file);
\r
6223 /// Add a manifest resource to this PEFile NOT YET IMPLEMENTED
\r
6225 /// <param name="mr"></param>
\r
6226 public void AddManifestResource(ManifestResource mr) {
\r
6227 metaData.AddToTable(MDTable.ManifestResource,mr);
\r
6228 //mr.FixName(metaData);
\r
6232 /// Write out the PEFile (the "bake" function)
\r
6234 public void WritePEFile() { /* the "bake" function */
\r
6235 fileImage.MakeFile();
\r
6239 /// Get the descriptor of this module
\r
6241 /// <returns>the descriptor for this module</returns>
\r
6242 public Module GetThisModule() {
\r
6247 /// Get the descriptor for this assembly. The PEFile must have been
\r
6248 /// created with hasAssembly = true
\r
6250 /// <returns>the descriptor for this assembly</returns>
\r
6251 public Assembly GetThisAssembly() {
\r
6252 return thisAssembly;
\r
6257 /**************************************************************************/
\r
6259 /// Descriptor for the Primitive types defined in IL
\r
6261 public class PrimitiveType : Type
\r
6263 private string name;
\r
6264 private int systemTypeIndex;
\r
6265 public static int NumSystemTypes = 18;
\r
6267 public static readonly PrimitiveType Void = new PrimitiveType(0x01,"Void",0);
\r
6268 public static readonly PrimitiveType Boolean = new PrimitiveType(0x02,"Boolean",1);
\r
6269 public static readonly PrimitiveType Char = new PrimitiveType(0x03,"Char",2);
\r
6270 public static readonly PrimitiveType Int8 = new PrimitiveType(0x04,"SByte",3);
\r
6271 public static readonly PrimitiveType UInt8 = new PrimitiveType(0x05,"Byte",4);
\r
6272 public static readonly PrimitiveType Int16 = new PrimitiveType(0x06,"Int16",5);
\r
6273 public static readonly PrimitiveType UInt16 = new PrimitiveType(0x07,"UInt16",6);
\r
6274 public static readonly PrimitiveType Int32 = new PrimitiveType(0x08,"Int32",7);
\r
6275 public static readonly PrimitiveType UInt32 = new PrimitiveType(0x09,"UInt32",8);
\r
6276 public static readonly PrimitiveType Int64 = new PrimitiveType(0x0A,"Int64",9);
\r
6277 public static readonly PrimitiveType UInt64 = new PrimitiveType(0x0B,"UInt64",10);
\r
6278 public static readonly PrimitiveType Float32 = new PrimitiveType(0x0C,"Single",11);
\r
6279 public static readonly PrimitiveType Float64 = new PrimitiveType(0x0D,"Double",12);
\r
6280 public static readonly PrimitiveType String = new PrimitiveType(0x0E,"String",13);
\r
6281 internal static readonly PrimitiveType Class = new PrimitiveType(0x12);
\r
6282 public static readonly PrimitiveType TypedRef = new PrimitiveType(0x16,"TypedReference",14);
\r
6283 public static readonly PrimitiveType IntPtr = new PrimitiveType(0x18,"IntPtr",15);
\r
6284 public static readonly PrimitiveType UIntPtr = new PrimitiveType(0x19,"UIntPtr",16);
\r
6285 public static readonly PrimitiveType Object = new PrimitiveType(0x1C,"Object",17);
\r
6286 internal static readonly PrimitiveType ClassType = new PrimitiveType(0x50);
\r
6287 public static readonly PrimitiveType NativeInt = IntPtr;
\r
6288 public static readonly PrimitiveType NativeUInt = UIntPtr;
\r
6290 internal PrimitiveType(byte typeIx) : base(typeIx) { }
\r
6292 internal PrimitiveType(byte typeIx, string name, int STIx) : base(typeIx) {
\r
6294 this.systemTypeIndex = STIx;
\r
6297 internal string GetName() { return name; }
\r
6299 internal int GetSystemTypeIx() { return systemTypeIndex; }
\r
6301 internal sealed override void TypeSig(MemoryStream str) {
\r
6302 str.WriteByte(typeIndex);
\r
6305 internal override MetaDataElement GetTypeSpec(MetaData md) {
\r
6306 TypeSpec tS = md.GetPrimitiveTypeSpec(systemTypeIndex);
\r
6308 tS = new TypeSpec(this,md);
\r
6309 md.SetPrimitiveTypeSpec(systemTypeIndex,tS);
\r
6310 md.AddToTable(MDTable.TypeSpec,tS);
\r
6317 /**************************************************************************/
\r
6319 /// Descriptor for the Property of a class
\r
6321 public class Property : Feature
\r
6323 private static readonly byte PropertyTag = 0x8;
\r
6324 MethodDef getterMeth;
\r
6325 ConstantElem constVal;
\r
6326 uint typeBlobIx = 0;
\r
6331 internal Property(string name, Type retType, Type[] pars, ClassDef parent) : base(name, parent) {
\r
6332 returnType = retType;
\r
6334 if (pars != null) numPars = (uint)pars.Length;
\r
6335 tabIx = MDTable.Property;
\r
6339 /// Add a set method to this property
\r
6341 /// <param name="setter">the set method</param>
\r
6342 public void AddSetter(MethodDef setter) {
\r
6343 AddMethod(setter,MethodType.Setter);
\r
6347 /// Add a get method to this property
\r
6349 /// <param name="getter">the get method</param>
\r
6350 public void AddGetter(MethodDef getter) {
\r
6351 AddMethod(getter,MethodType.Getter);
\r
6352 getterMeth = getter;
\r
6356 /// Add another method to this property
\r
6358 /// <param name="other">the method</param>
\r
6359 public void AddOther(MethodDef other) {
\r
6360 AddMethod(other,MethodType.Other);
\r
6364 /// Add an initial value for this property
\r
6366 /// <param name="constVal">the initial value for this property</param>
\r
6367 public void AddInitValue(Constant constVal) {
\r
6368 this.constVal = new ConstantElem(this,constVal);
\r
6371 internal sealed override void BuildTables(MetaData md) {
\r
6373 nameIx = md.AddToStringsHeap(name);
\r
6374 MemoryStream sig = new MemoryStream();
\r
6375 sig.WriteByte(PropertyTag);
\r
6376 MetaData.CompressNum(numPars,sig);
\r
6377 returnType.TypeSig(sig);
\r
6378 for (int i=0; i < numPars; i++) {
\r
6379 parList[i].TypeSig(sig);
\r
6381 typeBlobIx = md.AddToBlobHeap(sig.ToArray());
\r
6382 for (int i=0; i < tide; i++) {
\r
6383 md.AddToTable(MDTable.MethodSemantics,methods[i]);
\r
6385 if (constVal != null) {
\r
6386 md.AddToTable(MDTable.Constant,constVal);
\r
6387 constVal.BuildTables(md);
\r
6392 internal sealed override uint Size(MetaData md) {
\r
6393 return 2 + md.StringsIndexSize() + md.BlobIndexSize();
\r
6396 internal sealed override void Write(FileImage output) {
\r
6397 output.Write(flags);
\r
6398 output.StringsIndex(nameIx);
\r
6399 output.BlobIndex(typeBlobIx);
\r
6402 internal sealed override uint GetCodedIx(CIx code) {
\r
6404 case (CIx.HasCustomAttr) : return 9;
\r
6405 case (CIx.HasConst) : return 2;
\r
6406 case (CIx.HasSemantics) : return 1;
\r
6412 /**************************************************************************/
\r
6414 /// Descriptor for an pointer (type * or type &)
\r
6416 public abstract class PtrType : Type
\r
6420 internal PtrType(Type bType, byte typeIx) : base(typeIx)
\r
6423 tabIx = MDTable.TypeSpec;
\r
6426 internal sealed override void TypeSig(MemoryStream str) {
\r
6427 str.WriteByte(typeIndex);
\r
6428 baseType.TypeSig(str);
\r
6432 /**************************************************************************/
\r
6434 /// Descriptor for a managed pointer (type & or byref)
\r
6437 public class ManagedPointer : PtrType // <type> & (BYREF)
\r
6441 /// Create new managed pointer to baseType
\r
6443 /// <param name="bType">the base type of the pointer</param>
\r
6444 public ManagedPointer(Type baseType) : base(baseType,0x10) { }
\r
6447 /**************************************************************************/
\r
6449 /// Descriptor for an unmanaged pointer (type *)
\r
6451 public class UnmanagedPointer : PtrType // PTR
\r
6454 /// Create a new unmanaged pointer to baseType
\r
6456 /// <param name="baseType">the base type of the pointer</param>
\r
6457 public UnmanagedPointer(Type baseType) : base(baseType, 0x0F) { }
\r
6460 /**************************************************************************/
\r
6462 /// Base class for scopes (extended by Module, ModuleRef, Assembly, AssemblyRef)
\r
6464 public abstract class ResolutionScope : MetaDataElement
\r
6466 protected uint nameIx = 0;
\r
6467 protected MetaData metaData;
\r
6468 protected string name;
\r
6470 internal ResolutionScope(string name, MetaData md)
\r
6474 nameIx = md.AddToStringsHeap(name);
\r
6477 internal string GetName() { return name; }
\r
6480 /**************************************************************************/
\r
6482 /// Descriptor for a Section in a PEFile eg .text, .sdata
\r
6484 internal class Section {
\r
6485 private static readonly uint relocPageSize = 4096; // 4K pages for fixups
\r
6488 uint offset = 0, tide = 0, size = 0, rva = 0, relocTide = 0;
\r
6489 //uint relocOff = 0;
\r
6490 uint flags = 0, padding = 0;
\r
6493 internal Section(string sName, uint sFlags) {
6494 name = sName.ToCharArray();
\r
6498 internal uint Tide() { return tide; }
\r
6500 internal void IncTide(uint incVal) { tide += incVal; }
\r
6502 internal uint Padding() { return padding; }
\r
6504 internal uint Size() { return size; }
\r
6506 internal void SetSize(uint pad) {
\r
6508 size = tide + padding;
\r
6511 internal uint RVA() { return rva; }
\r
6513 internal void SetRVA(uint rva) { this.rva = rva; }
\r
6515 internal uint Offset() { return offset; }
\r
6517 internal void SetOffset(uint offs) { offset = offs; }
\r
6519 internal void DoBlock(BinaryWriter reloc, uint page, int start, int end) {
\r
6520 //Console.WriteLine("rva = " + rva + " page = " + page);
\r
6521 reloc.Write(rva + page);
\r
6522 reloc.Write((uint)(((end-start+1)*2) + 8));
\r
6523 for (int j=start; j < end; j++) {
\r
6524 //Console.WriteLine("reloc offset = " + relocs[j]);
\r
6525 reloc.Write((ushort)((0x3 << 12) | (relocs[j] - page)));
\r
6527 reloc.Write((ushort)0);
\r
6530 internal void DoRelocs(BinaryWriter reloc) {
\r
6531 if (relocTide > 0) {
\r
6532 //relocOff = (uint)reloc.Seek(0,SeekOrigin.Current);
\r
6533 uint block = (relocs[0]/relocPageSize + 1) * relocPageSize;
\r
6535 for (int i=1; i < relocTide; i++) {
\r
6536 if (relocs[i] >= block) {
\r
6537 DoBlock(reloc,block-relocPageSize,start,i);
\r
6539 block = (relocs[i]/relocPageSize + 1) * relocPageSize;
\r
6542 DoBlock(reloc,block-relocPageSize,start,(int)relocTide);
\r
6546 internal void AddReloc(uint offs) {
\r
6548 if (relocs == null) {
\r
6549 relocs = new uint[5];
\r
6551 if (relocTide >= relocs.Length) {
\r
6552 uint[] tmp = relocs;
\r
6553 relocs = new uint[tmp.Length + 5];
\r
6554 for (int i=0; i < relocTide; i++) {
\r
6555 relocs[i] = tmp[i];
\r
6558 while ((pos < relocTide) && (relocs[pos] < offs)) pos++;
\r
6559 for (int i=pos; i < relocTide; i++) {
\r
6560 relocs[i+1] = relocs[i];
\r
6563 relocs[pos] = offs;
\r
6567 internal void WriteHeader(BinaryWriter output, uint relocRVA) {
\r
6568 output.Write(name);
\r
6569 output.Write(tide);
\r
6570 output.Write(rva);
\r
6571 output.Write(size);
\r
6572 output.Write(offset);
\r
6574 //output.Write(relocRVA + relocOff);
\r
6577 //output.Write((ushort)relocTide);
\r
6578 //output.Write((ushort)0);
\r
6579 output.Write(flags);
\r
6583 /**************************************************************************/
\r
6584 public abstract class Signature : MetaDataElement
\r
6586 protected uint sigIx;
\r
6588 internal Signature() {
\r
6589 tabIx = MDTable.StandAloneSig;
\r
6592 internal sealed override uint Size(MetaData md) {
\r
6593 return md.BlobIndexSize();
\r
6596 internal sealed override void Write(FileImage output) {
\r
6597 output.BlobIndex(sigIx);
\r
6600 internal sealed override uint GetCodedIx(CIx code) { return (uint)tabIx; }
\r
6603 /**************************************************************************/
\r
6605 /// Descriptor for a class defined in System (mscorlib)
\r
6607 internal class SystemClass : ClassRef
\r
6609 PrimitiveType elemType;
\r
6611 internal SystemClass(PrimitiveType eType, AssemblyRef paren, MetaData md)
\r
6612 : base("System",eType.GetName(),md) {
\r
6617 internal override sealed MetaDataElement GetTypeSpec(MetaData md) {
\r
6618 if (typeSpec == null) typeSpec = (TypeSpec)elemType.GetTypeSpec(md);
\r
6623 internal sealed override void TypeSig(MemoryStream str) {
\r
6624 str.WriteByte(elemType.GetTypeIndex());
\r
6628 /**************************************************************************/
\r
6630 /// Base class for all IL types
\r
6632 public abstract class Type : MetaDataElement {
\r
6633 protected byte typeIndex;
\r
6634 protected TypeSpec typeSpec;
\r
6636 internal Type(byte tyIx) { typeIndex = tyIx; }
\r
6638 internal byte GetTypeIndex() { return typeIndex; }
\r
6640 internal virtual MetaDataElement GetTypeSpec(MetaData md) {
\r
6641 if (typeSpec == null) {
\r
6642 typeSpec = new TypeSpec(this,md);
\r
6643 md.AddToTable(MDTable.TypeSpec,typeSpec);
\r
6648 internal virtual void TypeSig(MemoryStream str) {
\r
6649 throw(new TypeSignatureException(this.GetType().AssemblyQualifiedName +
\r
6650 " doesn't have a type signature!!"));
\r
6655 /**************************************************************************/
\r
6657 public class TypeSpec : MetaDataElement {
\r
6660 internal TypeSpec(Type aType, MetaData md) {
\r
6661 MemoryStream sig = new MemoryStream();
\r
6662 aType.TypeSig(sig);
\r
6663 sigIx = md.AddToBlobHeap(sig.ToArray());
\r
6664 tabIx = MDTable.TypeSpec;
\r
6667 internal sealed override uint GetCodedIx(CIx code) {
\r
6669 case (CIx.TypeDefOrRef) : return 2;
\r
6670 case (CIx.HasCustomAttr) : return 13;
\r
6671 case (CIx.MemberRefParent) : return 4;
\r
6676 internal override uint Size(MetaData md) {
\r
6677 return md.BlobIndexSize();
\r
6680 internal sealed override void Write(FileImage output) {
\r
6681 //Console.WriteLine("Writing the blob index for a TypeSpec");
\r
6682 output.BlobIndex(sigIx);
\r