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 GenericTypeSpec : Type {
\r
102 public GenericTypeSpec (int index) : base (0x13) {
\r
103 this.index = index;
\r
104 tabIx = MDTable.TypeSpec;
\r
107 internal sealed override void TypeSig(MemoryStream str) {
\r
108 str.WriteByte(typeIndex);
\r
109 MetaData.CompressNum ((uint) index, str);
\r
114 public class GenericTypeInst : Type {
\r
116 private Type gen_type;
\r
117 private Type[] gen_param;
\r
119 public GenericTypeInst (Type gen_type, Type[] gen_param) : base (0x15)
\r
122 this.gen_type = gen_type;
\r
123 this.gen_param = gen_param;
\r
124 tabIx = MDTable.TypeSpec;
\r
127 internal sealed override void TypeSig(MemoryStream str) {
\r
128 str.WriteByte(typeIndex);
\r
129 gen_type.TypeSig (str);
\r
130 MetaData.CompressNum ((uint) gen_param.Length, str);
\r
131 foreach (Type param in gen_param)
\r
132 param.TypeSig (str);
\r
136 public class Sentinel : Type {
138 public Sentinel () : base (0x41) { }
140 internal sealed override void TypeSig(MemoryStream str) {
141 str.WriteByte(typeIndex);
146 /// The IL Array type
\r
148 public abstract class Array : Type
\r
151 protected Type elemType;
\r
152 protected MetaData metaData;
\r
153 protected string cnameSpace, cname;
\r
155 internal Array(Type eType, byte TypeId) : base(TypeId) {
\r
157 tabIx = MDTable.TypeSpec;
\r
160 internal Array(Class eClass, MetaData md, string nameSpace, string name,
\r
161 byte TypeId) : base(TypeId) {
\r
163 tabIx = MDTable.TypeSpec;
\r
165 cnameSpace = nameSpace;
\r
169 public Method AddMethod(string name, Type retType, Type[] pars) {
\r
171 if (metaData == null || cnameSpace == null || cname == null)
\r
172 throw new Exception ("Methods cannot be added to arrays not created with the Class.GetArray* methods.");
\r
173 Method meth = new MethodRef (GetTypeSpec (metaData), name, retType, pars, false, null);
\r
174 metaData.AddToTable(MDTable.MemberRef,meth);
\r
181 /**************************************************************************/
\r
184 /// Single dimensional array with zero lower bound
\r
186 public class ZeroBasedArray : Array {
\r
189 /// Create a new array - elementType[]
\r
191 /// <param name="elementType">the type of the array elements</param>
\r
192 public ZeroBasedArray(Type elementType) : base (elementType,0x1D) { }
\r
194 public ZeroBasedArray(Class elementClass, MetaData md,
\r
195 string nameSpace, string name) : base (elementClass, md, nameSpace, name, 0x1D) { }
\r
197 internal sealed override void TypeSig(MemoryStream str) {
\r
198 str.WriteByte(typeIndex);
\r
199 elemType.TypeSig(str);
\r
205 /**************************************************************************/
\r
208 /// Multi dimensional array with explicit bounds
\r
210 public class BoundArray : Array {
\r
216 /// Create a new multi dimensional array type
\r
217 /// eg. elemType[1..5,3..10,5,,] would be
\r
218 /// new BoundArray(elemType,5,[1,3,0],[5,10,4])
\r
220 /// <param name="elementType">the type of the elements</param>
\r
221 /// <param name="dimensions">the number of dimensions</param>
\r
222 /// <param name="loBounds">lower bounds of dimensions</param>
\r
223 /// <param name="upBounds">upper bounds of dimensions</param>
\r
224 public BoundArray(Type elementType, uint dimensions, int[] loBounds,
\r
225 int[] upBounds) : base (elementType,0x14) {
\r
226 numDims = dimensions;
\r
227 lowerBounds = loBounds;
\r
228 sizes = new int[loBounds.Length];
\r
229 for (int i=0; i < loBounds.Length; i++) {
\r
230 sizes[i] = upBounds[i] - loBounds[i] + 1;
\r
234 internal BoundArray(Class elementClass, MetaData md, string nameSpace, string name,
\r
235 uint dimensions, int[] loBounds,
\r
236 int[] upBounds) : base (elementClass,md, nameSpace, name, 0x14) {
\r
237 numDims = dimensions;
\r
238 lowerBounds = loBounds;
\r
239 sizes = new int[loBounds.Length];
\r
240 for (int i=0; i < loBounds.Length; i++) {
\r
241 sizes[i] = upBounds[i] - loBounds[i] + 1;
\r
246 /// Create a new multi dimensional array type
\r
247 /// eg. elemType[5,10,20] would be new BoundArray(elemType,3,[5,10,20])
\r
249 /// <param name="elementType">the type of the elements</param>
\r
250 /// <param name="dimensions">the number of dimensions</param>
\r
251 /// <param name="size">the sizes of the dimensions</param>
\r
252 public BoundArray(Type elementType, uint dimensions, int[] size)
\r
253 : base (elementType,0x14) {
\r
254 numDims = dimensions;
\r
259 /// Create a new multi dimensional array type
\r
260 /// eg. elemType[,,] would be new BoundArray(elemType,3)
\r
262 /// <param name="elementType">the type of the elements</param>
\r
263 /// <param name="dimensions">the number of dimensions</param>
\r
264 public BoundArray(Type elementType, uint dimensions)
\r
265 : base (elementType,0x14) {
\r
266 numDims = dimensions;
\r
269 internal sealed override void TypeSig(MemoryStream str) {
\r
270 str.WriteByte(typeIndex);
\r
271 elemType.TypeSig(str);
\r
272 MetaData.CompressNum(numDims,str);
\r
273 if ((sizes != null) && (sizes.Length > 0)) {
\r
274 MetaData.CompressNum((uint)sizes.Length,str);
\r
275 for (int i=0; i < sizes.Length; i++) {
\r
276 MetaData.CompressNum((uint)sizes[i],str);
\r
278 } else str.WriteByte(0);
\r
279 if ((lowerBounds != null) && (lowerBounds.Length > 0)) {
\r
280 MetaData.CompressNum((uint)lowerBounds.Length,str);
\r
281 for (int i=0; i < lowerBounds.Length; i++) {
\r
282 MetaData.CompressNum((uint)lowerBounds[i],str);
\r
284 } else str.WriteByte(0);
\r
288 /**************************************************************************/
\r
290 /// Descriptor for THIS assembly (.assembly)
\r
292 public class Assembly : ResolutionScope
\r
294 ushort majorVer, minorVer, buildNo, revisionNo;
\r
296 HashAlgorithm hashAlgId = HashAlgorithm.None;
\r
297 uint keyIx = 0, cultIx = 0;
\r
299 internal Assembly(string name, MetaData md) : base(name,md) {
\r
300 tabIx = MDTable.Assembly;
\r
304 /// Add details about THIS assembly
\r
306 /// <param name="majVer">Major Version</param>
\r
307 /// <param name="minVer">Minor Version</param>
\r
308 /// <param name="bldNo">Build Number</param>
\r
309 /// <param name="revNo">Revision Number</param>
\r
310 /// <param name="key">Hash Key</param>
\r
311 /// <param name="hash">Hash Algorithm</param>
\r
312 /// <param name="cult">Culture</param>
\r
313 public void AddAssemblyInfo(int majVer, int minVer, int bldNo, int revNo,
\r
314 byte[] key, HashAlgorithm hash, string cult) {
\r
315 majorVer = (ushort)majVer;
\r
316 minorVer = (ushort)minVer;
\r
317 buildNo = (ushort)bldNo;
\r
318 revisionNo = (ushort)revNo;
\r
320 keyIx = metaData.AddToBlobHeap(key);
\r
321 cultIx = metaData.AddToStringsHeap(cult);
\r
325 /// Add an attribute to THIS assembly
\r
327 /// <param name="aa">assembly attribute</param>
\r
328 public void AddAssemblyAttr(AssemAttr aa) {
\r
332 internal sealed override uint Size(MetaData md) {
\r
333 return 16 + md.BlobIndexSize() + 2 * md.StringsIndexSize();
\r
336 internal sealed override void Write(FileImage output) {
\r
337 // Console.WriteLine("Writing assembly element with nameIx of " + nameIx + " at file offset " + output.Seek(0,SeekOrigin.Current));
\r
338 output.Write((uint)hashAlgId);
\r
339 output.Write(majorVer);
\r
340 output.Write(minorVer);
\r
341 output.Write(buildNo);
\r
342 output.Write(revisionNo);
\r
343 output.Write(flags);
\r
344 output.BlobIndex(keyIx);
\r
345 output.StringsIndex(nameIx);
\r
346 output.StringsIndex(cultIx);
\r
349 internal sealed override uint GetCodedIx(CIx code) {
\r
351 case (CIx.HasCustomAttr) : return 14;
\r
352 case (CIx.HasDeclSecurity) : return 2;
\r
358 /**************************************************************************/
\r
360 /// A reference to an external assembly (.assembly extern)
\r
362 public class AssemblyRef : ResolutionScope
\r
364 private ushort major, minor, build, revision;
\r
365 uint flags, keyIx, hashIx, cultIx;
\r
366 bool hasVersion = false, isKeyToken = false;
\r
370 internal AssemblyRef(MetaData md, string name) : base(name,md) {
\r
371 tabIx = MDTable.AssemblyRef;
\r
375 /// Add version information about this external assembly
\r
377 /// <param name="majVer">Major Version</param>
\r
378 /// <param name="minVer">Minor Version</param>
\r
379 /// <param name="bldNo">Build Number</param>
\r
380 /// <param name="revNo">Revision Number</param>
\r
381 public void AddVersionInfo(int majVer, int minVer, int bldNo, int revNo) {
\r
382 major = (ushort)majVer;
\r
383 minor = (ushort)minVer;
\r
384 build = (ushort)bldNo;
\r
385 revision = (ushort)revNo;
\r
390 /// Add the hash value for this external assembly
\r
392 /// <param name="hash">bytes of the hash value</param>
\r
393 public void AddHash(byte[] hash) {
\r
394 hashIx = metaData.AddToBlobHeap(hash);
\r
398 /// Set the culture for this external assembly
\r
400 /// <param name="cult">the culture string</param>
\r
401 public void AddCulture(string cult) {
\r
402 cultIx = metaData.AddToStringsHeap(cult);
\r
407 /// Add the full public key for this external assembly
\r
409 /// <param name="key">bytes of the public key</param>
\r
410 public void AddKey(byte[] key) {
\r
411 flags |= 0x0001; // full public key
\r
413 keyIx = metaData.AddToBlobHeap(key);
\r
417 /// Add the public key token (low 8 bytes of the public key)
\r
419 /// <param name="key">low 8 bytes of public key</param>
\r
420 public void AddKeyToken(byte[] key) {
\r
421 keyIx = metaData.AddToBlobHeap(key);
\r
427 /// Add a class to this external assembly
\r
429 /// <param name="nsName">name space name</param>
\r
430 /// <param name="name">class name</param>
\r
431 /// <returns></returns>
\r
432 public virtual ClassRef AddClass(string nsName, string name) {
\r
433 ClassRef aClass = new ClassRef(nsName,name,metaData);
\r
434 metaData.AddToTable(MDTable.TypeRef,aClass);
\r
435 aClass.SetParent(this);
\r
440 /// Add a value class to this external assembly
\r
442 /// <param name="nsName">name space name</param>
\r
443 /// <param name="name">class name</param>
\r
444 /// <returns></returns>
\r
445 public virtual ClassRef AddValueClass(string nsName, string name) {
\r
446 ClassRef aClass = new ClassRef(nsName,name,metaData);
\r
447 metaData.AddToTable(MDTable.TypeRef,aClass);
\r
448 aClass.SetParent(this);
\r
449 aClass.MakeValueClass();
\r
453 internal string TypeName() {
\r
454 string result = name;
\r
456 result = result + ", Version=" + major + "." + minor + "." +
\r
457 build + "." + revision;
\r
458 if (keyBytes != null) {
\r
459 string tokenStr = "=";
\r
460 if (isKeyToken) tokenStr = "Token=";
\r
461 result = result + ", PublicKey" + tokenStr;
\r
462 for (int i=0; i < keyBytes.Length; i++) {
\r
463 result = result + Hex.Byte(keyBytes[i]);
\r
466 if (culture != null)
\r
467 result = result + ", Culture=" + culture;
\r
471 internal sealed override uint Size(MetaData md) {
\r
472 return 12 + 2 * md.StringsIndexSize() + 2 * md.BlobIndexSize();
\r
475 internal sealed override void Write(FileImage output) {
\r
476 output.Write(major);
\r
477 output.Write(minor);
\r
478 output.Write(build);
\r
479 output.Write(revision);
\r
480 output.Write(flags);
\r
481 output.BlobIndex(keyIx);
\r
482 output.StringsIndex(nameIx);
\r
483 output.StringsIndex(cultIx);
\r
484 output.BlobIndex(hashIx);
\r
487 internal sealed override uint GetCodedIx(CIx code) {
\r
489 case (CIx.ResolutionScope) : return 2;
\r
490 case (CIx.HasCustomAttr) : return 15;
\r
491 case (CIx.Implementation) : return 1;
\r
497 /**************************************************************************/
\r
500 /// flags for the assembly (.corflags)
\r
502 public enum CorFlags {CF_IL_ONLY, CF_32_BITREQUIRED, CF_STRONGNAMESIGNED,
\r
506 /// subsystem for the assembly (.subsystem)
\r
508 public enum SubSystem { Native = 1, Windows_GUI = 2,
\r
509 Windows_CUI = 3, OS2_CUI = 5, POSIX_CUI = 7, Native_Windows = 8,
\r
510 Windows_CE_GUI = 9}
\r
513 /// Hash algorithms for the assembly
\r
515 public enum HashAlgorithm { None, SHA1 }
\r
518 /// Attributes for this assembly
\r
520 public enum AssemAttr { EnableJITCompileTracking = 0x8000,
\r
521 DisableJITCompileOptimizer = 0x4000}
\r
524 /// Method call conventions
\r
526 public enum CallConv { Default, Cdecl, Stdcall, Thiscall,
\r
527 Fastcall, Vararg, Instance = 0x20, InstanceExplicit = 0x60 }
\r
530 /// Type custom modifier
\r
532 public enum CustomModifier { modreq = 0x1F, modopt };
\r
535 /// Attibutes for a class
\r
537 public enum TypeAttr {Private, Public, NestedPublic, NestedPrivate,
\r
538 NestedFamily, NestedAssembly, NestedFamAndAssem, NestedFamOrAssem,
\r
539 SequentialLayout, ExplicitLayout = 0x10, Interface = 0x20,
\r
540 Abstract = 0x80, PublicAbstract = 0x81, Sealed = 0x100,
\r
541 PublicSealed = 0x101, SpecialName = 0x400, RTSpecialName = 0x800,
\r
542 Import = 0x1000, Serializable = 0x2000, UnicodeClass = 0x10000,
\r
543 AutoClass = 0x20000, BeforeFieldInit = 0x100000 }
\r
546 /// Attributes for a field
\r
548 public enum FieldAttr {Default, Private, FamAndAssem, Assembly,
\r
549 Family, FamOrAssem, Public, Static = 0x10, PublicStatic = 0x16,
\r
550 Initonly = 0x20, Literal = 0x40, Notserialized = 0x80,
\r
551 SpecialName = 0x200, RTSpecialName = 0x400 }
\r
554 /// Attributes for a method
\r
556 public enum MethAttr { Default, Private, FamAndAssem, Assembly,
\r
557 Family, FamOrAssem, Public, Static = 0x0010, PublicStatic = 0x16,
\r
558 Final = 0x0020, PublicStaticFinal = 0x36, Virtual = 0x0040,
\r
559 PrivateVirtual, PublicVirtual = 0x0046, HideBySig = 0x0080,
\r
560 NewSlot = 0x0100, Abstract = 0x0400, SpecialName = 0x0800,
\r
561 RTSpecialName = 0x1000, SpecialRTSpecialName = 0x1800,
\r
562 RequireSecObject = 0x8000}
\r
565 /// Attributes for .pinvokeimpl method declarations
\r
567 public enum PInvokeAttr { nomangle = 1, ansi = 2, unicode = 4, autochar = 6,
568 lasterr = 0x0040, winapi = 0x0100, cdecl = 0x0200,
569 stdcall = 0x0300, thiscall = 0x0400, fastcall = 0x0500 }
\r
572 /// Implementation attributes for a method
\r
574 public enum ImplAttr { IL, Native, Runtime = 0x03, Unmanaged = 0x04,
\r
575 ForwardRef = 0x10, PreserveSig = 0x0080, InternalCall = 0x1000,
\r
576 Synchronised = 0x0020, Synchronized = 0x0020, NoInLining = 0x0008, Optil = 0x0002}
\r
579 /// Modes for a parameter
\r
581 public enum ParamAttr { Default, In, Out, Opt = 4 }
\r
584 /// CIL instructions
\r
586 public enum Op { nop, breakOp, ldarg_0, ldarg_1, ldarg_2, ldarg_3,
\r
587 ldloc_0, ldloc_1, ldloc_2, ldloc_3, stloc_0, stloc_1, stloc_2, stloc_3,
\r
588 ldnull = 0x14, ldc_i4_m1, ldc_i4_0, ldc_i4_1, ldc_i4_2, ldc_i4_3,
\r
589 ldc_i4_4, ldc_i4_5, ldc_i4_6, ldc_i4_7, ldc_i4_8, dup = 0x25, pop,
\r
590 ret = 0x2A, ldind_i1 = 0x46, ldind_u1, ldind_i2, ldind_u2, ldind_i4,
\r
591 ldind_u4, ldind_i8, ldind_i, ldind_r4, ldind_r8, ldind_ref, stind_ref,
\r
592 stind_i1, stind_i2, stind_i4, stind_i8, stind_r4, stind_r8, add, sub, mul,
\r
593 div, div_un, rem, rem_un, and, or, xor, shl, shr, shr_un, neg, not,
\r
594 conv_i1, conv_i2, conv_i4, conv_i8, conv_r4, conv_r8, conv_u4, conv_u8,
\r
595 conv_r_un = 0x76, throwOp = 0x7A, conv_ovf_i1_un = 0x82, conv_ovf_i2_un,
\r
596 conv_ovf_i4_un, conv_ovf_i8_un, conf_ovf_u1_un, conv_ovf_u2_un,
\r
597 conv_ovf_u4_un, conv_ovf_u8_un, conv_ovf_i_un, conv_ovf_u_un,
\r
598 ldlen = 0x8E, ldelem_i1 = 0x90, ldelem_u1, ldelem_i2, ldelem_u2,
\r
599 ldelem_i4, ldelem_u4, ldelem_i8, ldelem_i, ldelem_r4, ldelem_r8,
\r
600 ldelem_ref, stelem_i, stelem_i1, stelem_i2, stelem_i4, stelem_i8, stelem_r4 = 0xA0, stelem_r8,
\r
601 stelem_ref, conv_ovf_i1 = 0xb3, conv_ovf_u1, conv_ovf_i2, conv_ovf_u2,
\r
602 conv_ovf_i4, conv_ovf_u4, conv_ovf_i8, conv_ovf_u8, ckfinite = 0xC3,
\r
603 conv_u2 = 0xD1, conv_u1, conv_i, conv_ovf_i, conv_ovf_u, add_ovf,
\r
604 add_ovf_un, mul_ovf, mul_ovf_un, sub_ovf, sub_ovf_un, endfinally,
\r
605 stind_i = 0xDF, conv_u, arglist = 0xFE00, ceq, cgt, cgt_un, clt, clt_un,
\r
606 localloc = 0xFE0F, endfilter = 0xFE11, volatile_ = 0xFE13, tail_,
\r
607 cpblk = 0xFE17, initblk, rethrow = 0xFE1A, refanytype = 0xFE1D}
\r
610 /// CIL instructions requiring an integer parameter
\r
612 public enum IntOp {ldarg_s = 0x0E, ldarga_s, starg_s, ldloc_s, ldloca_s,
\r
613 stloc_s, ldc_i4_s = 0x1F, ldc_i4, ldarg = 0xFE09,
\r
614 ldarga, starg, ldloc, ldloca, stloc, unaligned = 0xFE12 }
\r
617 /// CIL instructions requiring a field parameter
\r
619 public enum FieldOp {ldfld = 0x7B, ldflda, stfld, ldsfld, ldsflda,
\r
620 stsfld, ldtoken = 0xD0 }
\r
623 /// CIL instructions requiring a method parameter
\r
625 public enum MethodOp {jmp = 0x27, call, callvirt = 0x6F, newobj = 0x73,
\r
626 ldtoken = 0xD0, ldftn = 0xFE06, ldvirtfn }
\r
629 /// CIL instructions requiring a type parameter
\r
631 public enum TypeOp {cpobj = 0x70, ldobj, castclass = 0x74, isinst,
\r
632 unbox = 0x79, stobj = 0x81, box = 0x8C, newarr,
\r
633 ldelema = 0x8F, refanyval = 0xC2, mkrefany = 0xC6,
\r
634 ldtoken = 0xD0, initobj = 0xFE15, sizeOf = 0xFE1C,
\r
635 ldelem = 0xA3, stelem = 0xA4, unbox_any }
\r
638 /// CIL branch instructions
\r
640 public enum BranchOp {br = 0x2B, brfalse, brtrue, beq, bge, bgt, ble, blt,
\r
641 bne_un, bge_un, bgt_un, ble_un, blt_un, leave = 0xDE }
\r
644 /// Index for all the tables in the meta data
\r
646 public enum MDTable { Module, TypeRef, TypeDef, Field = 0x04, Method = 0x06,
\r
647 Param = 0x08, InterfaceImpl, MemberRef, Constant, CustomAttribute,
\r
648 FieldMarshal, DeclSecurity, ClassLayout, FieldLayout, StandAloneSig,
\r
649 EventMap, Event = 0x14, PropertyMap, Property = 0x17, MethodSemantics,
\r
650 MethodImpl, ModuleRef, TypeSpec, ImplMap, FieldRVA, Assembly = 0x20,
\r
651 AssemblyProcessor, AssemblyOS, AssemblyRef, AssemblyRefProcessor,
\r
652 AssemblyRefOS, File, ExportedType, ManifestResource, NestedClass,
\r
653 GenericParam, MethodSpec, GenericParamConstraint }
\r
655 public enum SafeArrayType { int16 = 2, int32, float32, float64,
\r
656 currency, date, bstr, dispatch, error, boolean, variant, unknown,
\r
657 Decimal, int8 = 16, uint8, uint16, uint32, Int = 22, UInt }
\r
659 internal enum CIx { TypeDefOrRef, HasConst, HasCustomAttr, HasFieldMarshal,
\r
660 HasDeclSecurity, MemberRefParent, HasSemantics, MethodDefOrRef,
\r
661 MemberForwarded, Implementation, CustomAttributeType, ResolutionScope,
\r
662 TypeOrMethodDef, MaxCIx }
\r
664 internal enum MapType { eventMap, propertyMap, nestedClass }
\r
666 /**************************************************************************/
\r
668 /// The assembly for mscorlib.
\r
670 public sealed class MSCorLib : AssemblyRef
\r
672 private static readonly int valueTypeIx = 18;
\r
673 private readonly string systemName = "System";
\r
674 private ClassRef[] systemClasses = new ClassRef[valueTypeIx+2];
\r
675 private PrimitiveType[] systemTypes = new PrimitiveType[valueTypeIx];
\r
676 private TypeSpec[] specialTypeSpecs = new TypeSpec[valueTypeIx];
\r
677 private static int[] specialNames = {
\r
678 PrimitiveType.Void.GetName().GetHashCode(),
\r
679 PrimitiveType.Boolean.GetName().GetHashCode(),
\r
680 PrimitiveType.Char.GetName().GetHashCode(),
\r
681 PrimitiveType.Int8.GetName().GetHashCode(),
\r
682 PrimitiveType.UInt8.GetName().GetHashCode(),
\r
683 PrimitiveType.Int16.GetName().GetHashCode(),
\r
684 PrimitiveType.UInt16.GetName().GetHashCode(),
\r
685 PrimitiveType.Int32.GetName().GetHashCode(),
\r
686 PrimitiveType.UInt32.GetName().GetHashCode(),
\r
687 PrimitiveType.Int64.GetName().GetHashCode(),
\r
688 PrimitiveType.UInt64.GetName().GetHashCode(),
\r
689 PrimitiveType.Float32.GetName().GetHashCode(),
\r
690 PrimitiveType.Float64.GetName().GetHashCode(),
\r
691 PrimitiveType.String.GetName().GetHashCode(),
\r
692 PrimitiveType.TypedRef.GetName().GetHashCode(),
\r
693 PrimitiveType.IntPtr.GetName().GetHashCode(),
\r
694 PrimitiveType.UIntPtr.GetName().GetHashCode(),
\r
695 PrimitiveType.Object.GetName().GetHashCode(),
\r
696 "ValueType".GetHashCode(),
\r
697 "Enum".GetHashCode()
\r
700 internal MSCorLib(MetaData md) : base(md,"mscorlib") {
\r
701 md.AddToTable(MDTable.AssemblyRef,this);
\r
702 systemTypes[PrimitiveType.Void.GetSystemTypeIx()] = PrimitiveType.Void;
\r
703 systemTypes[PrimitiveType.Boolean.GetSystemTypeIx()] = PrimitiveType.Boolean;
\r
704 systemTypes[PrimitiveType.Char.GetSystemTypeIx()] = PrimitiveType.Char;
\r
705 systemTypes[PrimitiveType.Int8.GetSystemTypeIx()] = PrimitiveType.Int8;
\r
706 systemTypes[PrimitiveType.UInt8.GetSystemTypeIx()] = PrimitiveType.UInt8;
\r
707 systemTypes[PrimitiveType.Int16.GetSystemTypeIx()] = PrimitiveType.Int16;
\r
708 systemTypes[PrimitiveType.UInt16.GetSystemTypeIx()] = PrimitiveType.UInt16;
\r
709 systemTypes[PrimitiveType.Int32.GetSystemTypeIx()] = PrimitiveType.Int32;
\r
710 systemTypes[PrimitiveType.UInt32.GetSystemTypeIx()] = PrimitiveType.UInt32;
\r
711 systemTypes[PrimitiveType.Int64.GetSystemTypeIx()] = PrimitiveType.Int64;
\r
712 systemTypes[PrimitiveType.UInt64.GetSystemTypeIx()] = PrimitiveType.UInt64;
\r
713 systemTypes[PrimitiveType.Float32.GetSystemTypeIx()] = PrimitiveType.Float32;
\r
714 systemTypes[PrimitiveType.Float64.GetSystemTypeIx()] = PrimitiveType.Float64;
\r
715 systemTypes[PrimitiveType.IntPtr.GetSystemTypeIx()] = PrimitiveType.IntPtr;
\r
716 systemTypes[PrimitiveType.UIntPtr.GetSystemTypeIx()] = PrimitiveType.UIntPtr;
\r
717 systemTypes[PrimitiveType.String.GetSystemTypeIx()] = PrimitiveType.String;
\r
718 systemTypes[PrimitiveType.Object.GetSystemTypeIx()] = PrimitiveType.Object;
\r
719 systemTypes[PrimitiveType.TypedRef.GetSystemTypeIx()] = PrimitiveType.TypedRef;
\r
723 /// Add a class to the mscorlib assembly
\r
725 /// <param name="nsName">name space name</param>
\r
726 /// <param name="name">class name</param>
\r
727 /// <returns></returns>
\r
728 public override ClassRef AddClass(string nsName, string name) {
\r
729 ClassRef aClass = GetSpecialClass(nsName,name);
\r
730 if (aClass == null) {
\r
731 aClass = new ClassRef(nsName,name,metaData);
\r
732 metaData.AddToTable(MDTable.TypeRef,aClass);
\r
733 aClass.SetParent(this);
\r
738 private ClassRef GetSpecialClass(string nsName,string name) {
\r
739 if (nsName.CompareTo(systemName) != 0) return null;
\r
740 int hash = name.GetHashCode();
\r
741 for (int i=0; i < specialNames.Length; i++) {
\r
742 if (hash == specialNames[i]) {
\r
743 if (systemClasses[i] == null) {
\r
744 if (i < valueTypeIx) {
\r
745 systemClasses[i] = new SystemClass(systemTypes[i],this,metaData);
\r
746 if ((systemTypes[i] != PrimitiveType.Object) &&
\r
747 (systemTypes[i] != PrimitiveType.String)) {
\r
748 systemClasses[i].MakeValueClass();
\r
751 systemClasses[i] = new ClassRef(nsName,name,metaData);
\r
752 systemClasses[i].SetParent(this);
\r
753 systemClasses[i].MakeValueClass();
\r
755 metaData.AddToTable(MDTable.TypeRef,systemClasses[i]);
\r
757 return systemClasses[i];
\r
763 internal ClassRef GetSpecialSystemClass(PrimitiveType pType) {
\r
764 int ix = pType.GetSystemTypeIx();
\r
765 if (systemClasses[ix] == null) {
\r
766 systemClasses[ix] = new SystemClass(pType,this,metaData);
\r
767 metaData.AddToTable(MDTable.TypeRef,systemClasses[ix]);
\r
769 return systemClasses[ix];
\r
772 private ClassRef GetValueClass(string name, int hash) {
\r
773 int ix = valueTypeIx;
\r
774 if (hash != specialNames[valueTypeIx]) ix++;
\r
775 if (systemClasses[ix] == null) {
\r
776 systemClasses[ix] = new ClassRef(systemName,name,metaData);
\r
777 systemClasses[ix].SetParent(this);
\r
778 systemClasses[ix].MakeValueClass();
\r
779 metaData.AddToTable(MDTable.TypeRef,systemClasses[ix]);
\r
781 return systemClasses[ix];
\r
784 internal ClassRef ValueType() {
\r
785 if (systemClasses[valueTypeIx] == null) {
\r
786 ClassRef valType = new ClassRef("System","ValueType",metaData);
\r
787 valType.SetParent(this);
\r
788 valType.MakeValueClass();
\r
789 metaData.AddToTable(MDTable.TypeRef,valType);
\r
790 systemClasses[valueTypeIx] = valType;
\r
792 return systemClasses[valueTypeIx];
\r
796 /// Add a value class to this external assembly
\r
798 /// <param name="nsName">name space name</param>
\r
799 /// <param name="name">class name</param>
\r
800 /// <returns></returns>
\r
801 public override ClassRef AddValueClass(string nsName, string name) {
\r
802 if (nsName.CompareTo(systemName) == 0) {
\r
803 int hash = name.GetHashCode();
\r
804 if ((hash == specialNames[valueTypeIx]) ||
\r
805 (hash == specialNames[valueTypeIx+1])) {
\r
806 return GetValueClass(name,hash);
\r
809 ClassRef aClass = new ClassRef(nsName,name,metaData);
\r
810 metaData.AddToTable(MDTable.TypeRef,aClass);
\r
811 aClass.SetParent(this);
\r
812 aClass.MakeValueClass();
\r
817 /**************************************************************************/
\r
819 /// Signature for calli instruction
\r
821 public class CalliSig : Signature
\r
823 private static readonly byte Sentinel = 0x41;
\r
826 Type[] parameters, optParams;
\r
827 uint numPars = 0, numOptPars = 0;
\r
830 /// Create a signature for a calli instruction
\r
832 /// <param name="cconv">calling conventions</param>
\r
833 /// <param name="retType">return type</param>
\r
834 /// <param name="pars">parameter types</param>
\r
835 public CalliSig(CallConv cconv, Type retType, Type[] pars) {
\r
836 tabIx = MDTable.StandAloneSig;
\r
838 returnType = retType;
\r
840 if (pars != null) numPars = (uint)pars.Length;
\r
844 /// Add the optional parameters to a vararg method
\r
845 /// This method sets the vararg calling convention
\r
847 /// <param name="optPars">the optional pars for the vararg call</param>
\r
848 public void AddVarArgs(Type[] optPars) {
\r
849 optParams = optPars;
\r
850 if (optPars != null) numOptPars = (uint)optPars.Length;
\r
851 callConv |= CallConv.Vararg;
\r
855 /// Add extra calling conventions to this callsite signature
\r
857 /// <param name="cconv"></param>
\r
858 public void AddCallingConv(CallConv cconv) {
\r
862 internal sealed override void BuildTables(MetaData md) {
\r
864 MemoryStream sig = new MemoryStream();
\r
865 sig.WriteByte((byte)callConv);
\r
866 MetaData.CompressNum(numPars+numOptPars,sig);
\r
867 returnType.TypeSig(sig);
\r
868 for (int i=0; i < numPars; i++) {
\r
869 parameters[i].TypeSig(sig);
\r
871 sigIx = md.AddToBlobHeap(sig.ToArray());
\r
872 if (numOptPars > 0) {
\r
873 sig.WriteByte(Sentinel);
\r
874 for (int i=0; i < numOptPars; i++) {
\r
875 optParams[i].TypeSig(sig);
\r
882 /**************************************************************************/
\r
884 /// The IL instructions for a method
\r
886 public class CILInstructions
\r
889 private static readonly uint ExHeaderSize = 4;
\r
890 private static readonly uint FatExClauseSize = 24;
\r
891 private static readonly uint SmlExClauseSize = 12;
\r
892 private static readonly sbyte maxByteVal = 127;
\r
893 private static readonly sbyte minByteVal = -128;
\r
894 private static readonly byte maxUByteVal = 255;
\r
895 private static readonly int smallSize = 64;
\r
896 private static readonly ushort TinyFormat = 0x2;
\r
897 private static readonly ushort FatFormat = 0x3003;
\r
898 private static readonly ushort MoreSects = 0x8;
\r
899 private static readonly ushort InitLocals = 0x10;
\r
900 private static readonly uint FatSize = 12;
\r
901 private static readonly uint FatWords = FatSize/4;
\r
902 private static readonly byte FatExceptTable = 0x41;
\r
903 private static readonly byte SmlExceptTable = 0x01;
\r
905 private MetaData metaData;
\r
906 private ArrayList exceptions, blockStack;
\r
907 //private bool codeChecked = false;
\r
908 private static readonly int INITSIZE = 5;
\r
909 private CILInstruction[] buffer = new CILInstruction[INITSIZE];
\r
910 private int tide = 0;
\r
911 private uint offset = 0;
\r
912 private ushort headerFlags = 0;
\r
913 private short maxStack;
\r
914 private uint paddingNeeded = 0;
\r
915 private byte exceptHeader = 0;
\r
916 uint localSigIx = 0;
\r
917 uint codeSize = 0, exceptSize = 0;
\r
918 bool tinyFormat, fatExceptionFormat = false;
\r
920 internal CILInstructions(MetaData md) {
\r
924 private void AddToBuffer(CILInstruction inst) {
\r
925 if (tide >= buffer.Length) {
\r
926 CILInstruction[] tmp = buffer;
\r
927 buffer = new CILInstruction[tmp.Length * 2];
\r
928 for (int i=0; i < tide; i++) {
\r
929 buffer[i] = tmp[i];
\r
932 //Console.WriteLine("Adding instruction at offset " + offset + " with size " + inst.size);
\r
933 inst.offset = offset;
\r
934 offset += inst.size;
\r
935 buffer[tide++] = inst;
\r
939 /// Add a simple IL instruction
\r
941 /// <param name="inst">the IL instruction</param>
\r
942 public void Inst(Op inst) {
\r
943 AddToBuffer(new Instr((int)inst));
\r
947 /// Add an IL instruction with an integer parameter
\r
949 /// <param name="inst">the IL instruction</param>
\r
950 /// <param name="val">the integer parameter value</param>
\r
951 public void IntInst(IntOp inst, int val) {
\r
952 int instr = (int)inst;
\r
953 if ((inst == IntOp.ldc_i4_s) || (inst == IntOp.ldc_i4))
\r
954 AddToBuffer(new IntInstr(instr,val,(inst == IntOp.ldc_i4_s)));
\r
956 AddToBuffer(new UIntInstr(instr,val,((inst < IntOp.ldc_i4_s) ||
\r
957 (inst == IntOp.unaligned))));
\r
961 /// Add the load long instruction
\r
963 /// <param name="cVal">the long value</param>
\r
964 public void ldc_i8(long cVal) {
\r
965 AddToBuffer(new LongInstr(0x21,cVal));
\r
969 /// Add the load float32 instruction
\r
971 /// <param name="cVal">the float value</param>
\r
972 public void ldc_r4(float cVal) {
\r
973 AddToBuffer(new FloatInstr(0x22,cVal));
\r
977 /// Add the load float64 instruction
\r
979 /// <param name="cVal">the float value</param>
\r
980 public void ldc_r8(double cVal) {
\r
981 AddToBuffer(new DoubleInstr(0x23,cVal));
\r
985 /// Add the load string instruction
\r
987 /// <param name="str">the string value</param>
\r
988 public void ldstr(string str) {
\r
989 AddToBuffer(new StringInstr(0x72,str));
\r
993 /// Add the calli instruction
\r
995 /// <param name="sig">the signature for the calli</param>
\r
996 public void calli(CalliSig sig) {
\r
997 AddToBuffer(new SigInstr(0x29,sig));
\r
1001 /// Add a label to the CIL instructions
\r
1003 /// <param name="lab">the label to be added</param>
\r
1004 public void CodeLabel(CILLabel lab) {
\r
1005 AddToBuffer(new LabelInstr(lab));
\r
1009 /// Add an instruction with a field parameter
\r
1011 /// <param name="inst">the CIL instruction</param>
\r
1012 /// <param name="f">the field parameter</param>
\r
1013 public void FieldInst(FieldOp inst, Field f) {
\r
1014 AddToBuffer(new FieldInstr((int)inst,f));
\r
1018 /// Add an instruction with a method parameter
\r
1020 /// <param name="inst">the CIL instruction</param>
\r
1021 /// <param name="m">the method parameter</param>
\r
1022 public void MethInst(MethodOp inst, Method m) {
\r
1023 AddToBuffer(new MethInstr((int)inst,m));
\r
1027 /// Add an instruction with a type parameter
\r
1029 /// <param name="inst">the CIL instruction</param>
\r
1030 /// <param name="t">the type argument for the CIL instruction</param>
\r
1031 public void TypeInst(TypeOp inst, Type aType) {
\r
1032 AddToBuffer(new TypeInstr((int)inst,aType,metaData));
\r
1036 /// Add a branch instruction
\r
1038 /// <param name="inst">the branch instruction</param>
\r
1039 /// <param name="lab">the label that is the target of the branch</param>
\r
1040 public void Branch(BranchOp inst, CILLabel lab) {
\r
1041 AddToBuffer(new BranchInstr((int)inst,lab));
\r
1045 /// Add a switch instruction
\r
1047 /// <param name="labs">the target labels for the switch</param>
\r
1048 public void Switch(CILLabel[] labs) {
\r
1049 AddToBuffer(new SwitchInstr(0x45,labs));
\r
1053 /// Add a byte to the CIL instructions (.emitbyte)
\r
1055 /// <param name="bVal"></param>
\r
1056 public void emitbyte(byte bVal) {
\r
1057 AddToBuffer(new CILByte(bVal));
\r
1061 /// Add an instruction which puts an integer on TOS. This method
\r
1062 /// selects the correct instruction based on the value of the integer.
\r
1064 /// <param name="i">the integer value</param>
\r
1065 public void PushInt(int i) {
\r
1067 AddToBuffer(new Instr((int)Op.ldc_i4_m1));
\r
1068 } else if ((i >= 0) && (i <= 8)) {
\r
1069 Op op = (Op)(Op.ldc_i4_0 + i);
\r
1070 AddToBuffer(new Instr((int)op));
\r
1071 } else if ((i >= minByteVal) && (i <= maxByteVal)) {
\r
1072 AddToBuffer(new IntInstr((int)IntOp.ldc_i4_s,i,true));
\r
1074 AddToBuffer(new IntInstr((int)IntOp.ldc_i4,i,false));
\r
1079 /// Add the instruction to load a long on TOS
\r
1081 /// <param name="l">the long value</param>
\r
1082 public void PushLong(long l) {
\r
1083 AddToBuffer(new LongInstr(0x21,l));
\r
1087 /// Add an instruction to push the boolean value true on TOS
\r
1089 public void PushTrue() {
\r
1090 AddToBuffer(new Instr((int)Op.ldc_i4_1));
\r
1094 /// Add an instruction to push the boolean value false on TOS
\r
1096 public void PushFalse() {
\r
1097 AddToBuffer(new Instr((int)Op.ldc_i4_0));
\r
1101 /// Add the instruction to load an argument on TOS. This method
\r
1102 /// selects the correct instruction based on the value of argNo
\r
1104 /// <param name="argNo">the number of the argument</param>
\r
1105 public void LoadArg(int argNo) {
\r
1107 int op = (int)Op.ldarg_0 + argNo;
\r
1108 AddToBuffer(new Instr(op));
\r
1109 } else if (argNo <= maxUByteVal) {
\r
1110 AddToBuffer(new UIntInstr((int)IntOp.ldarg,argNo,true));
\r
1112 AddToBuffer(new UIntInstr(0x09,argNo,false));
\r
1117 /// Add the instruction to load the address of an argument on TOS.
\r
1118 /// This method selects the correct instruction based on the value
\r
1121 /// <param name="argNo">the number of the argument</param>
\r
1122 public void LoadArgAdr(int argNo) {
\r
1123 if (argNo <= maxUByteVal) {
\r
1124 AddToBuffer(new UIntInstr((int)IntOp.ldarga,argNo,true));
\r
1126 AddToBuffer(new UIntInstr(0x0A,argNo,false));
\r
1131 /// Add the instruction to load a local on TOS. This method selects
\r
1132 /// the correct instruction based on the value of locNo.
\r
1134 /// <param name="locNo">the number of the local to load</param>
\r
1135 public void LoadLocal(int locNo) {
\r
1137 int op = (int)Op.ldloc_0 + locNo;
\r
1138 AddToBuffer(new Instr(op));
\r
1139 } else if (locNo <= maxUByteVal) {
\r
1140 AddToBuffer(new UIntInstr((int)IntOp.ldloc,locNo,true));
\r
1142 AddToBuffer(new UIntInstr(0x0C,locNo,false));
\r
1147 /// Add the instruction to load the address of a local on TOS.
\r
1148 /// This method selects the correct instruction based on the
\r
1149 /// value of locNo.
\r
1151 /// <param name="locNo">the number of the local</param>
\r
1152 public void LoadLocalAdr(int locNo) {
\r
1153 if (locNo <= maxUByteVal) {
\r
1154 AddToBuffer(new UIntInstr((int)IntOp.ldloca,locNo,true));
\r
1156 AddToBuffer(new UIntInstr(0x0D,locNo,false));
\r
1161 /// Add the instruction to store to an argument. This method
\r
1162 /// selects the correct instruction based on the value of argNo.
\r
1164 /// <param name="argNo">the argument to be stored to</param>
\r
1165 public void StoreArg(int argNo) {
\r
1166 if (argNo <= maxUByteVal) {
\r
1167 AddToBuffer(new UIntInstr((int)IntOp.starg,argNo,true));
\r
1169 AddToBuffer(new UIntInstr(0x0B,argNo,false));
\r
1174 /// Add the instruction to store to a local. This method selects
\r
1175 /// the correct instruction based on the value of locNo.
\r
1177 /// <param name="locNo">the local to be stored to</param>
\r
1178 public void StoreLocal(int locNo) {
\r
1180 int op = (int)Op.stloc_0 + locNo;
\r
1181 AddToBuffer(new Instr(op));
\r
1182 } else if (locNo <= maxUByteVal) {
\r
1183 AddToBuffer(new UIntInstr((int)IntOp.stloc,locNo,true));
\r
1185 AddToBuffer(new UIntInstr(0x0E,locNo,false));
\r
1190 /// Create a new CIL label. To place the label in the CIL instruction
\r
1191 /// stream use CodeLabel.
\r
1193 /// <returns>a new CIL label</returns>
\r
1194 public CILLabel NewLabel() {
\r
1195 return new CILLabel();
\r
1198 public void AddTryBlock(TryBlock tryBlock) {
\r
1199 if (exceptions == null)
\r
1200 exceptions = new ArrayList();
\r
1201 else if (exceptions.Contains(tryBlock)) return;
\r
1202 exceptions.Add(tryBlock);
\r
1206 /// Create a new label at this position in the code buffer
\r
1208 /// <returns>the label at the current position</returns>
\r
1209 public CILLabel NewCodedLabel() {
\r
1210 CILLabel lab = new CILLabel();
\r
1211 AddToBuffer(new LabelInstr(lab));
\r
1216 /// Mark this position as the start of a new block
\r
1217 /// (try, catch, filter, finally or fault)
\r
1219 public void StartBlock() {
\r
1220 if (blockStack == null) blockStack = new ArrayList();
\r
1221 blockStack.Insert(0,NewCodedLabel());
\r
1225 /// Mark this position as the end of the last started block and
\r
1226 /// make it a try block. This try block is added to the current
\r
1227 /// instructions (ie do not need to call AddTryBlock)
\r
1229 /// <returns>The try block just ended</returns>
\r
1230 public TryBlock EndTryBlock() {
\r
1231 TryBlock tBlock = new TryBlock((CILLabel)blockStack[0],NewCodedLabel());
\r
1232 blockStack.RemoveAt(0);
\r
1233 AddTryBlock(tBlock);
\r
1238 /// Mark this position as the end of the last started block and
\r
1239 /// make it a catch block. This catch block is associated with the
\r
1240 /// specified try block.
\r
1242 /// <param name="exceptType">the exception type to be caught</param>
\r
1243 /// <param name="tryBlock">the try block associated with this catch block</param>
\r
1244 public void EndCatchBlock(Class exceptType, TryBlock tryBlock) {
\r
1245 Catch catchBlock = new Catch(exceptType,(CILLabel)blockStack[0],
\r
1247 tryBlock.AddHandler(catchBlock);
\r
1251 /// Mark this position as the end of the last started block and
\r
1252 /// make it a filter block. This filter block is associated with the
\r
1253 /// specified try block.
\r
1255 /// <param name="filterLab">the label where the filter code is</param>
\r
1256 /// <param name="tryBlock">the try block associated with this filter block</param>
\r
1257 public void EndFilterBlock(CILLabel filterLab, TryBlock tryBlock) {
\r
1258 Filter filBlock = new Filter(filterLab,(CILLabel)blockStack[0],NewCodedLabel());
\r
1259 tryBlock.AddHandler(filBlock);
\r
1263 /// Mark this position as the end of the last started block and
\r
1264 /// make it a finally block. This finally block is associated with the
\r
1265 /// specified try block.
\r
1267 /// <param name="tryBlock">the try block associated with this finally block</param>
\r
1268 public void EndFinallyBlock(TryBlock tryBlock) {
\r
1269 Finally finBlock= new Finally((CILLabel)blockStack[0],NewCodedLabel());
\r
1270 tryBlock.AddHandler(finBlock);
\r
1274 /// Mark this position as the end of the last started block and
\r
1275 /// make it a fault block. This fault block is associated with the
\r
1276 /// specified try block.
\r
1278 /// <param name="tryBlock">the try block associated with this fault block</param>
\r
1279 public void EndFaultBlock(TryBlock tryBlock) {
\r
1280 Fault fBlock= new Fault((CILLabel)blockStack[0],NewCodedLabel());
\r
1281 tryBlock.AddHandler(fBlock);
\r
1284 internal uint GetCodeSize() {
\r
1285 return codeSize + paddingNeeded + exceptSize;
\r
1288 internal void CheckCode(uint locSigIx, bool initLocals, int maxStack) {
\r
1289 if (tide == 0) return;
\r
1290 bool changed = true;
\r
1293 for (int i=0; i < tide; i++) {
\r
1294 changed = buffer[i].Check(metaData) || changed;
\r
1297 for (int i=1; i < tide; i++) {
\r
1298 buffer[i].offset = buffer[i-1].offset + buffer[i-1].size;
\r
1300 offset = buffer[tide-1].offset + buffer[tide-1].size;
\r
1303 codeSize = offset;
\r
1304 // Console.WriteLine("codeSize before header added = " + codeSize);
\r
1305 if ((offset < smallSize) && (maxStack <= 8) && (locSigIx == 0) && (exceptions == null)) {
\r
1306 // can use tiny header
\r
1307 //Console.WriteLine("Tiny Header");
\r
1308 tinyFormat = true;
\r
1309 headerFlags = (ushort)(TinyFormat | ((ushort)codeSize << 2));
\r
1311 if ((codeSize % 4) != 0) { paddingNeeded = 4 - (codeSize % 4); }
\r
1313 //Console.WriteLine("Fat Header");
\r
1314 tinyFormat = false;
\r
1315 localSigIx = locSigIx;
\r
1316 this.maxStack = (short)maxStack;
\r
1317 headerFlags = FatFormat;
\r
1318 if (exceptions != null) {
\r
1319 // Console.WriteLine("Got exceptions");
\r
1320 headerFlags |= MoreSects;
\r
1321 uint numExceptClauses = 0;
\r
1322 for (int i=0; i < exceptions.Count; i++) {
\r
1323 TryBlock tryBlock = (TryBlock)exceptions[i];
\r
1324 tryBlock.SetSize();
\r
1325 numExceptClauses += (uint)tryBlock.NumHandlers();
\r
1326 if (tryBlock.isFat()) fatExceptionFormat = true;
\r
1328 // Console.WriteLine("numexceptclauses = " + numExceptClauses);
\r
1329 if (fatExceptionFormat) {
\r
1330 // Console.WriteLine("Fat exception format");
\r
1331 exceptHeader = FatExceptTable;
\r
1332 exceptSize = ExHeaderSize + numExceptClauses * FatExClauseSize;
\r
1334 // Console.WriteLine("Tiny exception format");
\r
1335 exceptHeader = SmlExceptTable;
\r
1336 exceptSize = ExHeaderSize + numExceptClauses * SmlExClauseSize;
\r
1338 // Console.WriteLine("exceptSize = " + exceptSize);
\r
1340 if (initLocals) headerFlags |= InitLocals;
\r
1341 if ((offset % 4) != 0) { paddingNeeded = 4 - (offset % 4); }
\r
1342 codeSize += FatSize;
\r
1344 // Console.WriteLine("codeSize = " + codeSize + " headerFlags = " +
\r
1345 // Hex.Short(headerFlags));
\r
1348 internal void Write(FileImage output) {
\r
1349 // Console.WriteLine("Writing header flags = " + Hex.Short(headerFlags));
\r
1351 // Console.WriteLine("Writing tiny code");
\r
1352 output.Write((byte)headerFlags);
\r
1354 // Console.WriteLine("Writing fat code");
\r
1355 output.Write(headerFlags);
\r
1356 output.Write((ushort)maxStack);
\r
1357 output.Write(offset);
\r
1358 output.Write(localSigIx);
\r
1360 // Console.WriteLine(Hex.Int(tide) + " CIL instructions");
\r
1361 // Console.WriteLine("starting instructions at " + output.Seek(0,SeekOrigin.Current));
\r
1362 for (int i=0; i < tide; i++) {
\r
1363 buffer[i].Write(output);
\r
1365 // Console.WriteLine("ending instructions at " + output.Seek(0,SeekOrigin.Current));
\r
1366 for (int i=0; i < paddingNeeded; i++) { output.Write((byte)0); }
\r
1367 if (exceptions != null) {
\r
1368 // Console.WriteLine("Writing exceptions");
\r
1369 // Console.WriteLine("header = " + Hex.Short(exceptHeader) + " exceptSize = " + Hex.Int(exceptSize));
\r
1370 output.Write(exceptHeader);
\r
1371 output.Write3Bytes((uint)exceptSize);
\r
1372 for (int i=0; i < exceptions.Count; i++) {
\r
1373 TryBlock tryBlock = (TryBlock)exceptions[i];
\r
1374 tryBlock.Write(output,fatExceptionFormat);
\r
1380 /**************************************************************************/
\r
1382 /// A label in the IL
\r
1384 public class CILLabel
\r
1386 CILInstruction branch;
\r
1387 CILInstruction[] multipleBranches;
\r
1389 CILInstruction labInstr;
\r
1392 public CILLabel (uint offset) {
\r
1393 this.offset = offset;
\r
1397 internal CILLabel() {
\r
1400 internal void AddBranch(CILInstruction instr) {
\r
1401 if (branch == null) {
\r
1405 if (multipleBranches == null) {
\r
1406 multipleBranches = new CILInstruction[2];
\r
1407 } else if (tide >= multipleBranches.Length) {
\r
1408 CILInstruction[] tmp = multipleBranches;
\r
1409 multipleBranches = new CILInstruction[tmp.Length*2];
\r
1410 for (int i=0; i < tide; i++) {
\r
1411 multipleBranches[i] = tmp[i];
\r
1414 multipleBranches[tide++] = instr;
\r
1417 internal void AddLabelInstr(LabelInstr lInstr) {
\r
1418 labInstr = lInstr;
\r
1421 internal uint GetLabelOffset() {
\r
1422 if (labInstr == null) return 0;
\r
1423 return labInstr.offset + offset;
\r
1427 /**************************************************************************/
\r
1428 public abstract class CodeBlock {
\r
1430 private static readonly int maxCodeSize = 256;
\r
1431 protected CILLabel start, end;
\r
1432 protected bool small = true;
\r
1434 public CodeBlock(CILLabel start, CILLabel end) {
\r
1435 this.start = start;
\r
1439 internal virtual bool isFat() {
\r
1440 // Console.WriteLine("block start = " + start.GetLabelOffset() +
\r
1441 // " block end = " + end.GetLabelOffset());
\r
1442 return (end.GetLabelOffset() - start.GetLabelOffset()) > maxCodeSize;
\r
1445 internal virtual void Write(FileImage output, bool fatFormat) {
\r
1446 if (fatFormat) output.Write(start.GetLabelOffset());
\r
1447 else output.Write((short)start.GetLabelOffset());
\r
1448 uint len = end.GetLabelOffset() - start.GetLabelOffset();
\r
1449 if (fatFormat) output.Write(len);
\r
1450 else output.Write((byte)len);
\r
1456 /// The descriptor for a guarded block (.try)
\r
1458 public class TryBlock : CodeBlock {
\r
1459 protected bool fatFormat = false;
\r
1460 protected int flags = 0;
\r
1461 ArrayList handlers = new ArrayList();
\r
1464 /// Create a new try block
\r
1466 /// <param name="start">start label for the try block</param>
\r
1467 /// <param name="end">end label for the try block</param>
\r
1468 public TryBlock(CILLabel start, CILLabel end) : base(start,end) { }
\r
1471 /// Add a handler to this try block
\r
1473 /// <param name="handler">a handler to be added to the try block</param>
\r
1474 public void AddHandler(HandlerBlock handler) {
\r
1475 flags = handler.GetFlag();
\r
1476 handlers.Add(handler);
\r
1479 internal void SetSize() {
\r
1480 fatFormat = base.isFat();
\r
1481 if (fatFormat) return;
\r
1482 for (int i=0; i < handlers.Count; i++) {
\r
1483 HandlerBlock handler = (HandlerBlock)handlers[i];
\r
1484 if (handler.isFat()) {
\r
1491 internal int NumHandlers() {
\r
1492 return handlers.Count;
\r
1495 internal override bool isFat() {
\r
1499 internal override void Write(FileImage output, bool fatFormat) {
\r
1500 // Console.WriteLine("writing exception details");
\r
1501 for (int i=0; i < handlers.Count; i++) {
\r
1502 // Console.WriteLine("Except block " + i);
\r
1503 HandlerBlock handler = (HandlerBlock)handlers[i];
\r
1504 if (fatFormat) output.Write(flags);
\r
1505 else output.Write((short)flags);
\r
1506 // Console.WriteLine("flags = " + Hex.Short(flags));
\r
1507 base.Write(output,fatFormat);
\r
1508 handler.Write(output,fatFormat);
\r
1513 public abstract class HandlerBlock : CodeBlock
\r
1515 protected static readonly short ExceptionFlag = 0;
\r
1516 protected static readonly short FilterFlag = 0x01;
\r
1517 protected static readonly short FinallyFlag = 0x02;
\r
1518 protected static readonly short FaultFlag = 0x04;
\r
1520 public HandlerBlock(CILLabel start, CILLabel end) : base(start,end) { }
\r
1522 internal virtual short GetFlag() { return ExceptionFlag; }
\r
1524 internal override void Write(FileImage output, bool fatFormat) {
\r
1525 base.Write(output,fatFormat);
\r
1531 /// The descriptor for a catch clause (.catch)
\r
1533 public class Catch : HandlerBlock
\r
1538 /// Create a new catch clause
\r
1540 /// <param name="except">the exception to be caught</param>
\r
1541 /// <param name="handlerStart">start of the handler code</param>
\r
1542 /// <param name="handlerEnd">end of the handler code</param>
\r
1543 public Catch(Class except, CILLabel handlerStart, CILLabel handlerEnd)
\r
1544 : base(handlerStart,handlerEnd) {
\r
1545 exceptType = except;
\r
1548 internal override void Write(FileImage output, bool fatFormat) {
\r
1549 base.Write(output,fatFormat);
\r
1550 output.Write(exceptType.Token());
\r
1555 /// The descriptor for a filter clause (.filter)
\r
1557 public class Filter : HandlerBlock
\r
1559 CILLabel filterLabel;
\r
1562 /// Create a new filter clause
\r
1564 /// <param name="filterLabel">the label where the filter code starts</param>
\r
1565 /// <param name="handlerStart">the start of the handler code</param>
\r
1566 /// <param name="handlerEnd">the end of the handler code</param>
\r
1567 public Filter(CILLabel filterLabel, CILLabel handlerStart,
\r
1568 CILLabel handlerEnd) : base(handlerStart,handlerEnd) {
\r
1569 this.filterLabel = filterLabel;
\r
1572 internal override short GetFlag() {
\r
1573 return FilterFlag;
\r
1576 internal override void Write(FileImage output, bool fatFormat) {
\r
1577 base.Write(output,fatFormat);
\r
1578 output.Write(filterLabel.GetLabelOffset());
\r
1584 /// Descriptor for a finally block (.finally)
\r
1586 public class Finally : HandlerBlock
\r
1589 /// Create a new finally clause
\r
1591 /// <param name="finallyStart">start of finally code</param>
\r
1592 /// <param name="finallyEnd">end of finally code</param>
\r
1593 public Finally(CILLabel finallyStart, CILLabel finallyEnd)
\r
1594 : base(finallyStart,finallyEnd) { }
\r
1596 internal override short GetFlag() {
\r
1597 return FinallyFlag;
\r
1600 internal override void Write(FileImage output, bool fatFormat) {
\r
1601 base.Write(output,fatFormat);
\r
1602 output.Write((int)0);
\r
1608 /// Descriptor for a fault block (.fault)
\r
1610 public class Fault : HandlerBlock
\r
1613 /// Create a new fault clause
\r
1615 /// <param name="faultStart">start of the fault code</param>
\r
1616 /// <param name="faultEnd">end of the fault code</param>
\r
1617 public Fault(CILLabel faultStart, CILLabel faultEnd)
\r
1618 : base(faultStart,faultEnd) { }
\r
1620 internal override short GetFlag() {
\r
1621 return FaultFlag;
\r
1624 internal override void Write(FileImage output, bool fatFormat) {
\r
1625 base.Write(output,fatFormat);
\r
1626 output.Write((int)0);
\r
1631 /**************************************************************************/
\r
1633 /// The base descriptor for a class
\r
1635 public abstract class Class : Type
\r
1637 protected int row = 0;
\r
1638 protected string name, nameSpace;
\r
1639 protected uint nameIx, nameSpaceIx;
\r
1640 protected MetaData _metaData;
\r
1641 internal Class(string nameSpaceName, string className, MetaData md)
\r
1643 nameSpace = nameSpaceName;
\r
1645 nameIx = md.AddToStringsHeap(name);
\r
1646 nameSpaceIx = md.AddToStringsHeap(nameSpace);
\r
1650 internal Class(uint nsIx, uint nIx) : base(0x12) {
\r
1651 nameSpaceIx = nsIx;
\r
1655 public BoundArray GetBoundArray (uint dimensions, int[] loBounds,
\r
1657 BoundArray bound_array = new BoundArray (this, _metaData, nameSpace,
\r
1658 name, dimensions, loBounds, upBounds);
\r
1659 return bound_array;
\r
1662 public ZeroBasedArray GetZeroBasedArray () {
\r
1663 ZeroBasedArray array = new ZeroBasedArray (this, _metaData,
\r
1668 internal virtual uint TypeDefOrRefToken() { return 0; }
\r
1670 internal virtual void MakeValueClass() {
\r
1674 internal virtual string TypeName() {
\r
1675 return (nameSpace + "." + name);
\r
1678 internal override MetaDataElement GetTypeSpec(MetaData md) {
\r
1682 /**************************************************************************/
\r
1683 // This Class produces entries in the TypeDef table of the MetaData
\r
1684 // in the PE meta data.
\r
1686 // NOTE: Entry 0 in TypeDef table is always the pseudo class <module>
\r
1687 // which is the parent for functions and variables declared a module level
\r
1690 /// The descriptor for a class defined in the IL (.class) in the current assembly/module
\r
1693 public class ClassDef : Class
\r
1695 private static readonly uint HasSecurity = 0x00040000;
\r
1696 private static readonly byte ElementType_Class = 0x12;
\r
1699 ArrayList fields = new ArrayList();
\r
1700 ArrayList methods = new ArrayList();
\r
1702 ArrayList properties;
\r
1703 bool typeIndexChecked = true;
\r
1704 uint fieldIx = 0, methodIx = 0;
\r
1705 byte[] securityActions;
\r
1707 ClassLayout layout;
\r
1708 ClassDef parentClass;
\r
1709 MetaData metaData;
\r
1711 internal ClassDef(TypeAttr attrSet, string nsName, string name,
\r
1712 MetaData md) : base(nsName, name, md) {
\r
1714 superType = metaData.mscorlib.GetSpecialSystemClass(PrimitiveType.Object);
\r
1715 flags = (uint)attrSet;
\r
1716 tabIx = MDTable.TypeDef;
\r
1719 internal void SetSuper(Class sClass) {
\r
1720 superType = sClass;
\r
1721 if (sClass is ClassRef)
\r
1722 typeIndex = superType.GetTypeIndex();
\r
1724 typeIndexChecked = false;
\r
1727 internal override void MakeValueClass() {
\r
1728 superType = metaData.mscorlib.ValueType();
\r
1729 typeIndex = superType.GetTypeIndex();
\r
1732 public void SpecialNoSuper() {
\r
1737 /// Add an attribute to this class
\r
1739 /// <param name="ta">the attribute to be added</param>
\r
1740 public void AddAttribute(TypeAttr ta) {
\r
1741 flags |= (uint)ta;
\r
1745 /// Add an interface that is implemented by this class
\r
1747 /// <param name="iFace">the interface that is implemented</param>
\r
1748 public void AddImplementedInterface(Class iFace) {
\r
1749 metaData.AddToTable(MDTable.InterfaceImpl,new InterfaceImpl(this,iFace));
\r
1753 /// Add a named generic type parameter
\r
1755 public GenericParameter AddGenericParameter (short index, string name) {
\r
1756 GenericParameter gp = new GenericParameter (this, metaData, index, name);
1757 metaData.AddToTable (MDTable.GenericParam, gp);
\r
1762 /// Add a field to this class
\r
1764 /// <param name="name">field name</param>
\r
1765 /// <param name="fType">field type</param>
\r
1766 /// <returns>a descriptor for this new field</returns>
\r
1767 public FieldDef AddField(string name, Type fType) {
\r
1768 FieldDef field = new FieldDef(name,fType);
\r
1769 fields.Add(field);
\r
1774 /// Add a field to this class
\r
1776 /// <param name="fAtts">attributes for this field</param>
\r
1777 /// <param name="name">field name</param>
\r
1778 /// <param name="fType">field type</param>
\r
1779 /// <returns>a descriptor for this new field</returns>
\r
1780 public FieldDef AddField(FieldAttr fAtts, string name, Type fType) {
\r
1781 FieldDef field = new FieldDef(fAtts,name,fType);
\r
1782 fields.Add(field);
\r
1787 /// Add a method to this class
\r
1789 /// <param name="name">method name</param>
\r
1790 /// <param name="retType">return type</param>
\r
1791 /// <param name="pars">parameters</param>
\r
1792 /// <returns>a descriptor for this new method</returns>
\r
1793 public MethodDef AddMethod(string name, Type retType, Param[] pars) {
\r
1794 // Console.WriteLine("Adding method " + name + " to class " + this.name);
\r
1795 MethodDef meth = new MethodDef(metaData,name,retType, pars);
\r
1796 methods.Add(meth);
\r
1801 /// Add a method to this class
\r
1803 /// <param name="mAtts">attributes for this method</param>
\r
1804 /// <param name="iAtts">implementation attributes for this method</param>
\r
1805 /// <param name="name">method name</param>
\r
1806 /// <param name="retType">return type</param>
\r
1807 /// <param name="pars">parameters</param>
\r
1808 /// <returns>a descriptor for this new method</returns>
\r
1809 public MethodDef AddMethod(MethAttr mAtts, ImplAttr iAtts, string name,
\r
1810 Type retType, Param[] pars) {
\r
1811 // Console.WriteLine("Adding method " + name + " to class " + this.name);
\r
1812 MethodDef meth = new MethodDef(metaData,mAtts,iAtts,name,retType,pars);
\r
1813 methods.Add(meth);
\r
1818 /// Add an event to this class
\r
1820 /// <param name="name">event name</param>
\r
1821 /// <param name="eType">event type</param>
\r
1822 /// <returns>a descriptor for this new event</returns>
\r
1823 public Event AddEvent(string name, Type eType) {
\r
1824 Event e = new Event(name,eType,this);
\r
1825 if (events == null) events = new ArrayList();
\r
1831 /// Add a property to this class
\r
1833 /// <param name="name">property name</param>
\r
1834 /// <param name="propType">property type</param>
\r
1835 /// <returns>a descriptor for this new property</returns>
\r
1836 public Property AddProperty(string name, Type retType, Type[] pars) {
\r
1837 Property p = new Property(name, retType, pars, this);
\r
1838 if (properties == null) properties = new ArrayList();
\r
1839 properties.Add(p);
\r
1845 /// Add a nested class to this class
\r
1847 /// <param name="attrSet">attributes for this nested class</param>
\r
1848 /// <param name="nsName">nested name space name</param>
\r
1849 /// <param name="name">nested class name</param>
\r
1850 /// <returns>a descriptor for this new nested class</returns>
\r
1851 public ClassDef AddNestedClass(TypeAttr attrSet, string nsName,
\r
1853 ClassDef nClass = new ClassDef(attrSet,nsName,name,metaData);
\r
1854 metaData.AddToTable(MDTable.TypeDef,nClass);
\r
1855 metaData.AddToTable(MDTable.NestedClass,new MapElem(nClass,Row,MDTable.TypeDef));
\r
1856 nClass.parentClass = this;
\r
1861 /// Add a nested class to this class
\r
1863 /// <param name="attrSet">attributes for this nested class</param>
\r
1864 /// <param name="nsName">nested name space name</param>
\r
1865 /// <param name="name">nested class name</param>
\r
1866 /// <param name="sType">super type of this nested class</param>
\r
1867 /// <returns>a descriptor for this new nested class</returns>
\r
1868 public ClassDef AddNestedClass(TypeAttr attrSet, string nsName,
\r
1869 string name, Class sType) {
\r
1870 ClassDef nClass = new ClassDef(attrSet,nsName,name,metaData);
\r
1871 nClass.SetSuper(sType);
\r
1872 metaData.AddToTable(MDTable.TypeDef,nClass);
\r
1873 metaData.AddToTable(MDTable.NestedClass,
\r
1874 new MapElem(nClass,Row,MDTable.TypeDef));
\r
1875 nClass.parentClass = this;
\r
1880 /// Add layout information for this class. This class must have the
\r
1881 /// sequential or explicit attribute.
\r
1883 /// <param name="packSize">packing size (.pack)</param>
\r
1884 /// <param name="classSize">class size (.size)</param>
\r
1885 public void AddLayoutInfo (int packSize, int classSize) {
\r
1886 layout = new ClassLayout(packSize,classSize,this);
\r
1890 /// Use a method as the implementation for another method (.override)
\r
1892 /// <param name="decl">the method to be overridden</param>
\r
1893 /// <param name="body">the implementation to be used</param>
\r
1894 public void AddMethodOverride(Method decl, Method body) {
\r
1895 metaData.AddToTable(MDTable.MethodImpl,new MethodImpl(this,decl,body));
\r
1899 /// Add security to this class NOT YET IMPLEMENTED
\r
1901 /// <param name="permissionSet"></param>
\r
1902 public void AddSecurity(byte[] permissionSet) {
\r
1903 throw(new NotYetImplementedException("Class security "));
\r
1904 //flags |= HasSecurity;
\r
1905 // securityActions = permissionSet;
\r
1908 //public void AddLineInfo(int row, int col) { }
\r
1910 internal void CheckTypeIndex() {
\r
1911 if (typeIndexChecked) return;
\r
1912 if (!(superType is ClassRef))
\r
1913 ((ClassDef)superType).CheckTypeIndex();
\r
1914 typeIndex = superType.GetTypeIndex();
\r
1915 typeIndexChecked = true;
\r
1918 internal sealed override void BuildTables(MetaData md) {
\r
1920 if ((flags & (uint)TypeAttr.Interface) != 0) { superType = null; }
\r
1921 // Console.WriteLine("Building tables for " + name);
\r
1922 if (layout != null) md.AddToTable(MDTable.ClassLayout,layout);
\r
1923 // Console.WriteLine("adding methods " + methods.Count);
\r
1924 methodIx = md.TableIndex(MDTable.Method);
\r
1925 for (int i=0; i < methods.Count; i++) {
\r
1926 md.AddToTable(MDTable.Method,(MetaDataElement)methods[i]);
\r
1927 ((MethodDef)methods[i]).BuildTables(md);
\r
1929 // Console.WriteLine("adding fields");
\r
1930 fieldIx = md.TableIndex(MDTable.Field);
\r
1931 for (int i=0; i < fields.Count; i++) {
\r
1932 md.AddToTable(MDTable.Field,(MetaDataElement)fields[i]);
\r
1933 ((FieldDef)fields[i]).BuildTables(md);
\r
1935 // Console.WriteLine("adding events and properties");
\r
1936 if (events != null) {
\r
1937 for (int i=0; i < events.Count; i++) {
\r
1938 md.AddToTable(MDTable.Event,(Event)events[i]);
\r
1939 ((Event)events[i]).BuildTables(md);
\r
1941 md.AddToTable(MDTable.EventMap,
\r
1942 new MapElem(this,((Event)events[0]).Row,MDTable.Event));
\r
1944 if (properties != null) {
\r
1945 for (int i=0; i < properties.Count; i++) {
\r
1946 md.AddToTable(MDTable.Property,(Property)properties[i]);
\r
1947 ((Property)properties[i]).BuildTables(md);
\r
1949 md.AddToTable(MDTable.PropertyMap,new MapElem(this,
\r
1950 ((Property)properties[0]).Row,MDTable.Property));
\r
1952 DoCustomAttributes (md);
\r
1953 // Console.WriteLine("End of building tables");
\r
1957 internal sealed override uint Size(MetaData md) {
\r
1958 return 4 + 2 * md.StringsIndexSize() +
\r
1959 md.CodedIndexSize(CIx.TypeDefOrRef) +
\r
1960 md.TableIndexSize(MDTable.Field) +
\r
1961 md.TableIndexSize(MDTable.Method);
\r
1964 internal sealed override void Write(FileImage output) {
\r
1965 output.Write(flags);
\r
1966 output.StringsIndex(nameIx);
\r
1967 output.StringsIndex(nameSpaceIx);
\r
1968 //if (superType != null)
\r
1969 // Console.WriteLine("getting coded index for superType of " + name + " = " + superType.GetCodedIx(CIx.TypeDefOrRef));
\r
1970 output.WriteCodedIndex(CIx.TypeDefOrRef,superType);
\r
1971 output.WriteIndex(MDTable.Field,fieldIx);
\r
1972 output.WriteIndex(MDTable.Method,methodIx);
\r
1975 internal sealed override uint TypeDefOrRefToken() {
\r
1981 internal sealed override void TypeSig(MemoryStream sig) {
\r
1982 if (!typeIndexChecked) CheckTypeIndex();
\r
1983 sig.WriteByte(GetTypeIndex());
\r
1984 MetaData.CompressNum(TypeDefOrRefToken(),sig);
\r
1987 internal sealed override uint GetCodedIx(CIx code) {
\r
1989 case (CIx.TypeDefOrRef) : return 0;
\r
1990 case (CIx.HasCustomAttr) : return 3;
\r
1991 case (CIx.HasDeclSecurity) : return 0;
\r
1992 case (CIx.TypeOrMethodDef) : return 0;
\r
1998 /**************************************************************************/
\r
2000 /// Layout information for a class (.class [sequential | explicit])
\r
2002 internal class ClassLayout : MetaDataElement
\r
2005 ushort packSize = 0;
\r
2006 uint classSize = 0;
\r
2008 internal ClassLayout(int pack, int cSize, ClassDef par) {
\r
2009 packSize = (ushort)pack;
\r
2010 classSize = (uint)cSize;
\r
2012 tabIx = MDTable.ClassLayout;
\r
2015 internal sealed override uint Size(MetaData md) {
\r
2016 return 6 + md.TableIndexSize(MDTable.TypeDef);
\r
2019 internal sealed override void Write(FileImage output) {
\r
2020 output.Write(packSize);
\r
2021 output.Write(classSize);
\r
2022 output.WriteIndex(MDTable.TypeDef,parent.Row);
\r
2026 /**************************************************************************/
\r
2028 /// Descriptor for a class/interface declared in another module of THIS
\r
2029 /// assembly, or in another assembly.
\r
2031 public class ClassRef : Class
\r
2033 protected ResolutionScope parent;
\r
2034 ExternClass externClass;
\r
2035 protected MetaData metaData;
\r
2037 internal ClassRef(string nsName, string name, MetaData md) : base(nsName, name, md) {
\r
2039 tabIx = MDTable.TypeRef;
\r
2043 /// Add a method to this class
\r
2045 /// <param name="name">method name</param>
\r
2046 /// <param name="retType">return type</param>
\r
2047 /// <param name="pars">parameter types</param>
\r
2048 /// <returns>a descriptor for this method</returns>
\r
2049 public MethodRef AddMethod(string name, Type retType, Type[] pars) {
\r
2050 MethodRef meth = new MethodRef(this,name,retType,pars,false,null);
\r
2051 metaData.AddToTable(MDTable.MemberRef,meth);
\r
2056 /// Add a method to this class
\r
2058 /// <param name="name">method name</param>
\r
2059 /// <param name="retType">return type</param>
\r
2060 /// <param name="pars">parameter types</param>
\r
2061 /// <returns>a descriptor for this method</returns>
\r
2062 public MethodRef AddVarArgMethod(string name, Type retType,
\r
2063 Type[] pars, Type[] optPars) {
\r
2064 MethodRef meth = new MethodRef(this,name,retType,pars,true,optPars);
\r
2065 metaData.AddToTable(MDTable.MemberRef,meth);
\r
2070 /// Add a field to this class
\r
2072 /// <param name="name">field name</param>
\r
2073 /// <param name="fType">field type</param>
\r
2074 /// <returns>a descriptor for this field</returns>
\r
2075 public FieldRef AddField(string name, Type fType) {
\r
2076 FieldRef field = new FieldRef(this,name,fType);
\r
2077 metaData.AddToTable(MDTable.MemberRef,field);
\r
2081 internal void SetParent(ResolutionScope par) {
\r
2085 internal override string TypeName() {
\r
2086 if ((parent != null) && (parent is AssemblyRef))
\r
2087 return (nameSpace + "." + name + ", " + ((AssemblyRef)parent).TypeName());
\r
2089 return (nameSpace + name);
\r
2092 internal sealed override uint Size(MetaData md) {
\r
2093 return md.CodedIndexSize(CIx.ResolutionScope) + 2 *
\r
2094 md.StringsIndexSize();
\r
2097 internal sealed override void Write(FileImage output) {
\r
2098 output.WriteCodedIndex(CIx.ResolutionScope,parent);
\r
2099 output.StringsIndex(nameIx);
\r
2100 output.StringsIndex(nameSpaceIx);
\r
2103 internal override sealed uint TypeDefOrRefToken() {
\r
2105 cIx = (cIx << 2) | 0x1;
\r
2109 internal override void TypeSig(MemoryStream sig) {
\r
2110 sig.WriteByte(GetTypeIndex());
\r
2111 MetaData.CompressNum(TypeDefOrRefToken(),sig);
\r
2114 internal sealed override uint GetCodedIx(CIx code) {
\r
2116 case (CIx.TypeDefOrRef) : return 1;
\r
2117 case (CIx.HasCustomAttr) : return 2;
\r
2118 case (CIx.MemberRefParent) : return 1;
\r
2119 case (CIx.ResolutionScope) : return 3;
\r
2125 /**************************************************************************/
\r
2127 public class ExternClassRef : ClassRef {
\r
2129 ExternClass externClass;
\r
2131 internal ExternClassRef(TypeAttr attrs, string nsName, string name,
\r
2132 FileRef declFile, MetaData md) : base(nsName,name,md) {
\r
2133 externClass = new ExternClass(attrs,nameSpaceIx,nameIx,declFile);
\r
2134 metaData.AddToTable(MDTable.ExportedType,externClass);
\r
2137 internal ExternClassRef(string name, MetaData md) : base(null,name,md) {
\r
2140 public ClassRef AddNestedClass(TypeAttr attrs, string name) {
\r
2141 ExternClassRef nestedClass = new ExternClassRef(name,metaData);
\r
2142 externClass = new ExternClass(attrs,0,nameIx,this.externClass);
\r
2143 metaData.AddToTable(MDTable.ExportedType,externClass);
\r
2144 return nestedClass;
\r
2148 /**************************************************************************/
\r
2150 /// Descriptor for a constant value
\r
2152 public abstract class Constant {
\r
2153 protected uint size = 0;
\r
2154 protected Type type;
\r
2155 protected uint blobIndex;
\r
2156 protected bool addedToBlobHeap = false;
\r
2158 internal Constant() { }
\r
2160 internal virtual uint GetBlobIndex(MetaData md) { return 0; }
\r
2162 internal uint GetSize() { return size; }
\r
2164 internal byte GetTypeIndex() { return type.GetTypeIndex(); }
\r
2166 internal virtual void Write(BinaryWriter bw) { }
\r
2170 /// Descriptor for a constant value
\r
2172 public abstract class DataConstant : Constant {
\r
2173 private uint dataOffset = 0;
\r
2175 internal DataConstant() { }
\r
2177 public uint DataOffset {
\r
2178 get { return dataOffset; }
\r
2179 set { dataOffset = value; }
\r
2185 /// Boolean constant
\r
2187 public class BoolConst : Constant {
\r
2191 /// Create a new boolean constant with the value "val"
\r
2193 /// <param name="val">value of this boolean constant</param>
\r
2194 public BoolConst(bool val) {
\r
2197 type = PrimitiveType.Boolean;
\r
2200 internal sealed override uint GetBlobIndex(MetaData md) {
\r
2201 if (!addedToBlobHeap) {
\r
2202 if (val) blobIndex = md.AddToBlobHeap((sbyte)1);
\r
2203 else blobIndex = md.AddToBlobHeap((sbyte)0);
\r
2204 addedToBlobHeap = true;
\r
2209 internal sealed override void Write(BinaryWriter bw) {
\r
2210 if (val) bw.Write((sbyte)1);
\r
2211 else bw.Write((sbyte)0);
\r
2216 public class ByteArrConst : DataConstant {
\r
2219 public ByteArrConst(byte[] val) {
\r
2221 size = (uint)val.Length;
\r
2224 internal sealed override uint GetBlobIndex(MetaData md) {
\r
2225 if (!addedToBlobHeap) {
\r
2226 blobIndex = md.AddToBlobHeap(val);
\r
2227 addedToBlobHeap = true;
\r
2232 internal sealed override void Write(BinaryWriter bw) {
\r
2238 public class CharConst : Constant {
\r
2241 public CharConst(char val) {
\r
2244 type = PrimitiveType.Char;
\r
2247 internal sealed override uint GetBlobIndex(MetaData md) {
\r
2248 if (!addedToBlobHeap) {
\r
2249 blobIndex = md.AddToBlobHeap(val);
\r
2250 addedToBlobHeap = true;
\r
2255 internal sealed override void Write(BinaryWriter bw) {
\r
2261 public class FloatConst : DataConstant {
\r
2264 public FloatConst(float val) {
\r
2267 type = PrimitiveType.Float32;
\r
2270 internal sealed override uint GetBlobIndex(MetaData md) {
\r
2271 if (!addedToBlobHeap) {
\r
2272 blobIndex = md.AddToBlobHeap(val);
\r
2273 addedToBlobHeap = true;
\r
2278 internal sealed override void Write(BinaryWriter bw) {
\r
2284 public class DoubleConst : DataConstant {
\r
2287 public DoubleConst(double val) {
\r
2290 type = PrimitiveType.Float64;
\r
2293 internal sealed override uint GetBlobIndex(MetaData md) {
\r
2294 if (!addedToBlobHeap) {
\r
2295 blobIndex = md.AddToBlobHeap(val);
\r
2296 addedToBlobHeap = true;
\r
2301 internal sealed override void Write(BinaryWriter bw) {
\r
2307 public class IntConst : DataConstant {
\r
2310 public IntConst(sbyte val) {
\r
2313 type = PrimitiveType.Int8;
\r
2316 public IntConst(short val) {
\r
2319 type = PrimitiveType.Int16;
\r
2322 public IntConst(int val) {
\r
2325 type = PrimitiveType.Int32;
\r
2328 public IntConst(long val) {
\r
2331 type = PrimitiveType.Int64;
\r
2334 internal sealed override uint GetBlobIndex(MetaData md) {
\r
2335 if (!addedToBlobHeap) {
\r
2337 case (1) : blobIndex = md.AddToBlobHeap((sbyte)val); break;
\r
2338 case (2) : blobIndex = md.AddToBlobHeap((short)val); break;
\r
2339 case (4) : blobIndex = md.AddToBlobHeap((int)val); break;
\r
2340 default : blobIndex = md.AddToBlobHeap(val); break;
\r
2342 addedToBlobHeap = true;
\r
2347 internal sealed override void Write(BinaryWriter bw) {
\r
2349 case (1) : bw.Write((sbyte)val); break;
\r
2350 case (2) : bw.Write((short)val); break;
\r
2351 case (4) : bw.Write((int)val); break;
\r
2352 default : bw.Write(val); break;
\r
2358 public class UIntConst : Constant {
\r
2361 public UIntConst(sbyte val) {
\r
2364 type = PrimitiveType.UInt8;
\r
2366 public UIntConst(short val) {
\r
2369 type = PrimitiveType.UInt16;
\r
2371 public UIntConst(int val) {
\r
2374 type = PrimitiveType.UInt32;
\r
2376 public UIntConst(long val) {
\r
2379 type = PrimitiveType.UInt64;
\r
2382 internal sealed override uint GetBlobIndex(MetaData md) {
\r
2383 if (!addedToBlobHeap) {
\r
2385 case (1) : blobIndex = md.AddToBlobHeap((sbyte)val); break;
\r
2386 case (2) : blobIndex = md.AddToBlobHeap((short)val); break;
\r
2387 case (4) : blobIndex = md.AddToBlobHeap((int)val); break;
\r
2388 default : blobIndex = md.AddToBlobHeap(val); break;
\r
2390 addedToBlobHeap = true;
\r
2395 internal sealed override void Write(BinaryWriter bw) {
\r
2397 case (1) : bw.Write((sbyte)val); break;
\r
2398 case (2) : bw.Write((short)val); break;
\r
2399 case (4) : bw.Write((int)val); break;
\r
2400 default : bw.Write(val); break;
\r
2406 public class StringConst : DataConstant {
\r
2409 public StringConst(string val) {
\r
2411 size = (uint)val.Length; // need to add null ??
\r
2412 type = PrimitiveType.String;
\r
2415 internal sealed override uint GetBlobIndex(MetaData md) {
\r
2416 if (!addedToBlobHeap) {
\r
2417 blobIndex = md.AddToBlobHeap(val);
\r
2418 addedToBlobHeap = true;
\r
2423 internal sealed override void Write(BinaryWriter bw) {
\r
2429 public class NullConst : Constant {
\r
2431 public NullConst() {
\r
2433 type = PrimitiveType.Class;
\r
2436 internal sealed override uint GetBlobIndex(MetaData md) {
\r
2437 if (!addedToBlobHeap) {
\r
2438 blobIndex = md.AddToBlobHeap((int)0);
\r
2439 addedToBlobHeap = true;
\r
2444 internal sealed override void Write(BinaryWriter bw) {
\r
2445 bw.Write((int)0);
\r
2450 public class AddressConstant : DataConstant {
\r
2451 DataConstant data;
\r
2453 public AddressConstant(DataConstant dConst) {
\r
2456 type = PrimitiveType.TypedRef;
\r
2459 internal sealed override void Write(BinaryWriter bw) {
\r
2460 ((FileImage)bw).WriteDataRVA(data.DataOffset);
\r
2465 public class RepeatedConstant : DataConstant {
\r
2466 DataConstant data;
\r
2469 public RepeatedConstant(DataConstant dConst, int repeatCount) {
\r
2471 repCount = (uint)repeatCount;
\r
2472 int[] sizes = new int[1];
\r
2473 sizes[0] = repeatCount;
\r
2474 type = new BoundArray(type,1,sizes);
\r
2475 size = data.GetSize() * repCount;
\r
2478 internal sealed override void Write(BinaryWriter bw) {
\r
2479 for (int i=0; i < repCount; i++) {
\r
2486 public class ArrayConstant : DataConstant {
\r
2487 DataConstant[] dataVals;
\r
2489 public ArrayConstant(DataConstant[] dVals) {
\r
2491 for (int i=0; i < dataVals.Length; i++) {
\r
2492 size += dataVals[i].GetSize();
\r
2496 internal sealed override void Write(BinaryWriter bw) {
\r
2497 for (int i=0; i < dataVals.Length; i++) {
\r
2498 dataVals[i].Write(bw);
\r
2504 public class ClassType : Constant {
\r
2508 public ClassType(string className) {
\r
2510 type = PrimitiveType.ClassType;
\r
2513 public ClassType(Class classDesc) {
\r
2515 type = PrimitiveType.ClassType;
\r
2518 internal override void Write(BinaryWriter bw) {
\r
2519 if (name == null) name = desc.TypeName();
\r
2527 /**************************************************************************/
\r
2529 /// Summary description for ConstantElem.
\r
2531 internal class ConstantElem : MetaDataElement
\r
2533 MetaDataElement parent;
\r
2537 internal ConstantElem(MetaDataElement parent, Constant val) {
\r
2538 this.parent = parent;
\r
2540 tabIx = MDTable.Constant;
\r
2543 internal sealed override void BuildTables(MetaData md) {
\r
2545 valIx = cValue.GetBlobIndex(md);
\r
2549 internal void AddToBlob(BinaryWriter bw) {
\r
2553 internal sealed override uint Size(MetaData md) {
\r
2554 return 2 + md.CodedIndexSize(CIx.HasConst) + md.BlobIndexSize();
\r
2557 internal sealed override void Write(FileImage output) {
\r
2558 output.Write(cValue.GetTypeIndex());
\r
2559 output.Write((byte)0);
\r
2560 output.WriteCodedIndex(CIx.HasConst,parent);
\r
2561 output.BlobIndex(valIx);
\r
2565 /**************************************************************************/
\r
2567 /// Descriptor for a Custom Attribute (.custom)
\r
2570 public class CustomAttribute : MetaDataElement
\r
2572 private static readonly ushort prolog = 0x0001;
\r
2573 MetaDataElement parent;
\r
2578 ushort numNamed = 0;
\r
2579 ArrayList names, vals;
\r
2581 internal CustomAttribute(MetaDataElement paren, Method constrType,
\r
2584 type = constrType;
\r
2586 tabIx = MDTable.CustomAttribute;
\r
2587 throw(new NotYetImplementedException("Custom Attributes "));
\r
2590 internal CustomAttribute(MetaDataElement paren, Method constrType,
\r
2593 type = constrType;
\r
2594 tabIx = MDTable.CustomAttribute;
\r
2598 public void AddFieldOrProp(string name, Constant val) {
\r
2599 if (numNamed == 0) {
\r
2600 names = new ArrayList();
\r
2601 vals = new ArrayList();
\r
2607 internal sealed override void BuildTables(MetaData md) {
\r
2608 BinaryWriter bw = new BinaryWriter(new MemoryStream());
\r
2609 bw.Write((ushort)1);
\r
2610 md.AddToTable(MDTable.CustomAttribute, this);
\r
2611 MemoryStream str = (MemoryStream)bw.BaseStream;
\r
2612 valIx = md.AddToBlobHeap(str.ToArray());
\r
2615 internal sealed override uint Size(MetaData md) {
\r
2616 return md.CodedIndexSize(CIx.HasCustomAttr) + md.CodedIndexSize(CIx.CustomAttributeType) + md.BlobIndexSize();
\r
2619 internal sealed override void Write(FileImage output) {
\r
2620 output.WriteCodedIndex(CIx.HasCustomAttr,parent);
\r
2621 output.WriteCodedIndex(CIx.CustomAttributeType,type);
\r
2622 output.BlobIndex(valIx);
\r
2626 /**************************************************************************/
\r
2628 /// Descriptor for a custom modifier of a type (modopt or modreq)
\r
2631 public class CustomModifiedType : Type
\r
2637 /// Create a new custom modifier for a type
\r
2639 /// <param name="type">the type to be modified</param>
\r
2640 /// <param name="cmod">the modifier</param>
\r
2641 /// <param name="cmodType">the type reference to be associated with the type</param>
\r
2642 public CustomModifiedType(Type type, CustomModifier cmod, Class cmodType)
\r
2643 : base((byte)cmod) {
\r
2645 this.cmodType = cmodType;
\r
2648 internal sealed override void TypeSig(MemoryStream str) {
\r
2649 str.WriteByte(typeIndex);
\r
2650 MetaData.CompressNum(cmodType.TypeDefOrRefToken(),str);
\r
2651 type.TypeSig(str);
\r
2655 /**************************************************************************/
\r
2657 /// Descriptor for security permissions for a class or a method NOT YET IMPLEMENTED
\r
2660 public class DeclSecurity : MetaDataElement
\r
2663 MetaDataElement parent;
\r
2664 uint permissionIx;
\r
2666 internal DeclSecurity(MetaDataElement paren, ushort act) {
\r
2669 tabIx = MDTable.DeclSecurity;
\r
2670 throw(new NotYetImplementedException("Security "));
\r
2673 internal sealed override uint Size(MetaData md) {
\r
2674 return 2 + md.CodedIndexSize(CIx.HasDeclSecurity) + md.BlobIndexSize();
\r
2677 internal sealed override void BuildTables(MetaData md) {
\r
2679 // add permission to blob heap
\r
2683 internal sealed override void Write(FileImage output) {
\r
2684 output.Write(action);
\r
2685 output.WriteCodedIndex(CIx.HasDeclSecurity,parent);
\r
2686 output.BlobIndex(permissionIx);
\r
2690 /**************************************************************************/
\r
2692 /// Descriptor for an event
\r
2694 public class Event : Feature
\r
2698 internal Event(string name, Type eType, ClassDef parent)
\r
2699 : base(name, parent) {
\r
2700 eventType = eType;
\r
2701 tabIx = MDTable.Event;
\r
2705 /// Add the addon method to this event
\r
2707 /// <param name="addon">the addon method</param>
\r
2708 public void AddAddon(MethodDef addon) {
\r
2709 AddMethod(addon,MethodType.AddOn);
\r
2713 /// Add the removeon method to this event
\r
2715 /// <param name="removeOn">the removeon method</param>
\r
2716 public void AddRemoveOn(MethodDef removeOn) {
\r
2717 AddMethod(removeOn,MethodType.RemoveOn);
\r
2721 /// Add the fire method to this event
\r
2723 /// <param name="fire">the fire method</param>
\r
2724 public void AddFire(MethodDef fire) {
\r
2725 AddMethod(fire,MethodType.Fire);
\r
2729 /// Add another method to this event
\r
2731 /// <param name="other">the method to be added</param>
\r
2732 public void AddOther(MethodDef other) {
\r
2733 AddMethod(other,MethodType.Other);
\r
2736 internal sealed override void BuildTables(MetaData md) {
\r
2738 nameIx = md.AddToStringsHeap(name);
\r
2739 for (int i=0; i < tide; i++) {
\r
2740 md.AddToTable(MDTable.MethodSemantics,methods[i]);
\r
2745 internal sealed override uint Size(MetaData md) {
\r
2746 return 2 + md.StringsIndexSize() + md.CodedIndexSize(CIx.TypeDefOrRef);
\r
2749 internal sealed override void Write(FileImage output) {
\r
2750 output.Write(flags);
\r
2751 output.StringsIndex(nameIx);
\r
2752 output.WriteCodedIndex(CIx.TypeDefOrRef,eventType);
\r
2755 internal sealed override uint GetCodedIx(CIx code) {
\r
2757 case (CIx.HasCustomAttr) : return 10;
\r
2758 case (CIx.HasSemantics) : return 0;
\r
2764 /**************************************************************************/
\r
2766 /// Descriptor for a class defined in another module of THIS assembly
\r
2767 /// and exported (.class extern)
\r
2770 internal class ExternClass : Class
\r
2772 MetaDataElement parent;
\r
2775 internal ExternClass(TypeAttr attr, uint nsIx, uint nIx,
\r
2776 MetaDataElement paren) : base(nsIx,nIx) {
\r
2777 flags = (uint)attr;
\r
2779 tabIx = MDTable.ExportedType;
\r
2782 internal sealed override uint Size(MetaData md) {
\r
2783 return 8 + 2* md.StringsIndexSize() + md.CodedIndexSize(CIx.Implementation);
\r
2786 internal sealed override void Write(FileImage output) {
\r
2787 output.Write(flags);
\r
2789 output.StringsIndex(nameIx);
\r
2790 output.StringsIndex(nameSpaceIx);
\r
2791 output.WriteCodedIndex(CIx.Implementation,parent);
\r
2794 internal sealed override uint GetCodedIx(CIx code) {
\r
2796 case (CIx.HasCustomAttr) : return 17;
\r
2797 case (CIx.Implementation) : return 2;
\r
2803 /**************************************************************************/
\r
2805 /// Base class for Event and Property descriptors
\r
2808 public class Feature : MetaDataElement
\r
2810 internal enum MethodType : ushort { Setter = 0x01, Getter, Other = 0x04, AddOn = 0x08,
\r
2811 RemoveOn = 0x10, Fire = 0x20 }
\r
2813 private static readonly int INITSIZE = 5;
\r
2814 private static readonly ushort specialName = 0x200;
\r
2815 private static readonly ushort rtSpecialName = 0x400;
\r
2817 protected ClassDef parent;
\r
2818 protected ushort flags = 0;
\r
2819 protected string name;
\r
2820 protected int tide = 0;
\r
2821 protected uint nameIx;
\r
2822 protected MethodSemantics[] methods = new MethodSemantics[INITSIZE];
\r
2824 internal Feature(string name, ClassDef par) {
\r
2829 internal void AddMethod(MethodDef meth, MethodType mType) {
\r
2830 if (tide >= methods.Length) {
\r
2831 int len = methods.Length;
\r
2832 MethodSemantics[] mTmp = methods;
\r
2833 methods = new MethodSemantics[len * 2];
\r
2834 for (int i=0; i < len; i++) {
\r
2835 methods[i] = mTmp[i];
\r
2838 methods[tide++] = new MethodSemantics(mType,meth,this);
\r
2842 /// Set the specialName attribute for this Event or Property
\r
2844 public void SetSpecialName() {
\r
2845 flags |= specialName;
\r
2849 /// Set the RTSpecialName attribute for this Event or Property
\r
2851 public void SetRTSpecialName() {
\r
2852 flags |= rtSpecialName;
\r
2856 /*****************************************************************************/
\r
2858 /// Descriptor for a field of a class
\r
2861 public abstract class Field : Member
\r
2863 protected static readonly byte FieldSig = 0x6;
\r
2865 protected Type type;
\r
2867 internal Field(string pfName, Type pfType) : base(pfName)
\r
2873 /**************************************************************************/
\r
2875 /// Descriptor for a field defined in a class of THIS assembly/module
\r
2877 public class FieldDef : Field
\r
2879 //private static readonly uint PInvokeImpl = 0x2000;
\r
2880 private static readonly ushort HasFieldMarshal = 0x1000;
\r
2881 private static readonly ushort HasFieldRVA = 0x100;
\r
2884 ConstantElem constVal;
\r
2885 FieldLayout layout;
\r
2886 FieldMarshal marshalInfo;
\r
2889 internal FieldDef(string name, Type fType) : base(name,fType) {
\r
2890 tabIx = MDTable.Field;
\r
2893 internal FieldDef(FieldAttr attrSet, string name, Type fType) : base(name, fType) {
\r
2894 flags = (ushort)attrSet;
\r
2895 tabIx = MDTable.Field;
\r
2899 /// Add an attribute(s) to this field
\r
2901 /// <param name="fa">the attribute(s) to be added</param>
\r
2902 public void AddFieldAttr(FieldAttr fa) {
\r
2903 flags |= (ushort)fa;
\r
2907 /// Add a value for this field
\r
2909 /// <param name="val">the value for the field</param>
\r
2910 public void AddValue(Constant val) {
\r
2911 constVal = new ConstantElem(this,val);
\r
2915 /// Add an initial value for this field (at dataLabel) (.data)
\r
2917 /// <param name="val">the value for the field</param>
\r
2918 /// <param name="repeatVal">the number of repetitions of this value</param>
\r
2919 public void AddDataValue(DataConstant val) {
\r
2920 flags |= HasFieldRVA;
\r
2921 rva = new FieldRVA(this,val);
\r
2925 /// Set the offset of the field. Used for sequential or explicit classes.
\r
2926 /// (.field [offs])
\r
2928 /// <param name="offs">field offset</param>
\r
2929 public void SetOffset(uint offs) {
\r
2930 layout = new FieldLayout(this,offs);
\r
2934 /// Set the marshalling info for a field
\r
2936 /// <param name="mInf"></param>
\r
2937 public void SetMarshalInfo(NativeType marshallType) {
\r
2938 flags |= HasFieldMarshal;
\r
2939 marshalInfo = new FieldMarshal(this,marshallType);
\r
2942 internal sealed override void BuildTables(MetaData md) {
\r
2944 nameIx = md.AddToStringsHeap(name);
\r
2945 MemoryStream sig = new MemoryStream();
\r
2946 sig.WriteByte(FieldSig);
\r
2947 type.TypeSig(sig);
\r
2948 sigIx = md.AddToBlobHeap(sig.ToArray());
\r
2949 if (rva != null) {
\r
2950 md.AddToTable(MDTable.FieldRVA,rva);
\r
2951 rva.BuildTables(md);
\r
2952 } else if (constVal != null) {
\r
2953 md.AddToTable(MDTable.Constant,constVal);
\r
2954 constVal.BuildTables(md);
\r
2956 if (layout != null) md.AddToTable(MDTable.FieldLayout,layout);
\r
2957 if (marshalInfo != null) {
\r
2958 md.AddToTable(MDTable.FieldMarshal,marshalInfo);
\r
2959 marshalInfo.BuildTables(md);
\r
2964 internal sealed override uint Size(MetaData md) {
\r
2965 return 2 + md.StringsIndexSize() + md.BlobIndexSize();
\r
2968 internal sealed override void Write(FileImage output) {
\r
2969 output.Write(flags);
\r
2970 output.StringsIndex(nameIx);
\r
2971 output.BlobIndex(sigIx);
\r
2974 internal sealed override uint GetCodedIx(CIx code) {
\r
2976 case (CIx.HasConst) : return 0;
\r
2977 case (CIx.HasCustomAttr) : return 1;
\r
2978 case (CIx.HasFieldMarshal) : return 0;
\r
2979 case (CIx.MemberForwarded) : return 0;
\r
2985 /**************************************************************************/
\r
2987 /// Descriptor for layout information for a field
\r
2990 public class FieldLayout : MetaDataElement
\r
2995 internal FieldLayout(Field field, uint offset) {
\r
2996 this.field = field;
\r
2997 this.offset = offset;
\r
2998 tabIx = MDTable.FieldLayout;
\r
3001 internal sealed override uint Size(MetaData md) {
\r
3002 return 4 + md.TableIndexSize(MDTable.Field);
\r
3005 internal sealed override void Write(FileImage output) {
\r
3006 output.Write(offset);
\r
3007 output.WriteIndex(MDTable.Field,field.Row);
\r
3011 /*****************************************************************************/
\r
3013 /// Marshalling information for a field or param
\r
3015 public class FieldMarshal : MetaDataElement
\r
3017 MetaDataElement field;
\r
3021 internal FieldMarshal(MetaDataElement field, NativeType nType) {
\r
3022 this.field = field;
\r
3024 tabIx = MDTable.FieldMarshal;
\r
3027 internal sealed override void BuildTables(MetaData md) {
\r
3029 ntIx = md.AddToBlobHeap(nt.ToBlob());
\r
3033 internal sealed override uint Size(MetaData md) {
\r
3034 return md.CodedIndexSize(CIx.HasFieldMarshal) + md.BlobIndexSize();
\r
3037 internal sealed override void Write(FileImage output) {
\r
3038 output.WriteCodedIndex(CIx.HasFieldMarshal,field);
\r
3039 output.BlobIndex(ntIx);
\r
3043 /**************************************************************************/
\r
3045 /// Descriptor for a field of a class defined in another assembly/module
\r
3047 public class FieldRef : Field
\r
3049 MetaDataElement parent;
\r
3051 internal FieldRef(MetaDataElement paren, string name, Type fType) : base(name, fType) {
\r
3055 internal sealed override void BuildTables(MetaData md) {
\r
3057 nameIx = md.AddToStringsHeap(name);
\r
3058 MemoryStream sig = new MemoryStream();
\r
3059 sig.WriteByte(FieldSig);
\r
3060 type.TypeSig(sig);
\r
3061 sigIx = md.AddToBlobHeap(sig.ToArray());
\r
3065 internal sealed override uint Size(MetaData md) {
\r
3066 return md.CodedIndexSize(CIx.MemberRefParent) + md.StringsIndexSize() + md.BlobIndexSize();
\r
3069 internal sealed override void Write(FileImage output) {
\r
3070 output.WriteCodedIndex(CIx.MemberRefParent,parent);
\r
3071 output.StringsIndex(nameIx);
\r
3072 output.BlobIndex(sigIx);
\r
3075 internal sealed override uint GetCodedIx(CIx code) { return 6; }
\r
3078 /**************************************************************************/
\r
3080 /// Descriptor for the address of a field's value in the PE file
\r
3082 public class FieldRVA : MetaDataElement
\r
3085 DataConstant data;
\r
3087 internal FieldRVA(Field field, DataConstant data) {
\r
3088 this.field = field;
\r
3090 tabIx = MDTable.FieldRVA;
\r
3093 internal sealed override void BuildTables(MetaData md) {
\r
3099 internal sealed override uint Size(MetaData md) {
\r
3100 return 4 + md.TableIndexSize(MDTable.Field);
\r
3103 internal sealed override void Write(FileImage output) {
\r
3104 output.WriteDataRVA(data.DataOffset);
\r
3105 output.WriteIndex(MDTable.Field,field.Row);
\r
3109 /**************************************************************************/
\r
3111 /// Image for a PEFile
\r
3112 /// File Structure
\r
3113 /// DOS Header (128 bytes)
\r
3114 /// PE Signature ("PE\0\0")
\r
3115 /// PEFileHeader (20 bytes)
\r
3116 /// PEOptionalHeader (224 bytes)
\r
3117 /// SectionHeaders (40 bytes * NumSections)
\r
3119 /// Sections .text (always present - contains metadata)
\r
3120 /// .sdata (contains any initialised data in the file - may not be present)
\r
3121 /// (for ilams /debug this contains the Debug table)
\r
3122 /// .reloc (always present - in pure CIL only has one fixup)
\r
3123 /// others??? c# produces .rsrc section containing a Resource Table
\r
3126 /// IAT (single entry 8 bytes for pure CIL)
\r
3127 /// CLIHeader (72 bytes)
\r
3128 /// CIL instructions for all methods (variable size)
\r
3130 /// Root (20 bytes + UTF-8 Version String + quad align padding)
\r
3131 /// StreamHeaders (8 bytes + null terminated name string + quad align padding)
\r
3133 /// #~ (always present - holds metadata tables)
\r
3134 /// #Strings (always present - holds identifier strings)
\r
3135 /// #US (Userstring heap)
\r
3136 /// #Blob (signature blobs)
\r
3137 /// #GUID (guids for assemblies or Modules)
\r
3138 /// ImportTable (40 bytes)
\r
3139 /// ImportLookupTable(8 bytes) (same as IAT for standard CIL files)
\r
3140 /// Hint/Name Tables with entry "_CorExeMain" for .exe file and "_CorDllMain" for .dll (14 bytes)
\r
3141 /// ASCII string "mscoree.dll" referenced in ImportTable (+ padding = 16 bytes)
\r
3142 /// Entry Point (0xFF25 followed by 4 bytes 0x400000 + RVA of .text)
\r
3144 /// #~ stream structure
\r
3145 /// Header (24 bytes)
\r
3146 /// Rows (4 bytes * numTables)
\r
3149 internal class FileImage : BinaryWriter
\r
3151 internal readonly static uint[] iByteMask = {0x000000FF, 0x0000FF00, 0x00FF0000, 0xFF000000};
\r
3152 internal readonly static ulong[] lByteMask = {0x00000000000000FF, 0x000000000000FF00,
\r
3153 0x0000000000FF0000, 0x00000000FF000000,
\r
3154 0x000000FF00000000, 0x0000FF0000000000,
\r
3155 0x00FF000000000000, 0xFF00000000000000 };
\r
3156 internal readonly static uint nibble0Mask = 0x0000000F;
\r
3157 internal readonly static uint nibble1Mask = 0x000000F0;
\r
3159 private static readonly byte[] DOSHeader = { 0x4d,0x5a,0x90,0x00,0x03,0x00,0x00,0x00,
\r
3160 0x04,0x00,0x00,0x00,0xff,0xff,0x00,0x00,
\r
3161 0xb8,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
\r
3162 0x40,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
\r
3163 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
\r
3164 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
\r
3165 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
\r
3166 0x00,0x00,0x00,0x00,0x80,0x00,0x00,0x00,
\r
3167 0x0e,0x1f,0xba,0x0e,0x00,0xb4,0x09,0xcd,
\r
3168 0x21,0xb8,0x01,0x4c,0xcd,0x21,0x54,0x68,
\r
3169 0x69,0x73,0x20,0x70,0x72,0x6f,0x67,0x72,
\r
3170 0x61,0x6d,0x20,0x63,0x61,0x6e,0x6e,0x6f,
\r
3171 0x74,0x20,0x62,0x65,0x20,0x72,0x75,0x6e,
\r
3172 0x20,0x69,0x6e,0x20,0x44,0x4f,0x53,0x20,
\r
3173 0x6d,0x6f,0x64,0x65,0x2e,0x0d,0x0d,0x0a,
\r
3174 0x24,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
\r
3175 0x50,0x45,0x00,0x00};
\r
3176 private static byte[] PEHeader = { 0x4c, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
\r
3177 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
\r
3178 0xE0, 0x00, 0x0E, 0x01, // PE Header Standard Fields
\r
3179 0x0B, 0x01, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00,
\r
3180 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
\r
3181 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
\r
3184 private static readonly uint minFileAlign = 0x200;
\r
3185 private static readonly uint maxFileAlign = 0x1000;
\r
3186 private static readonly uint fileHeaderSize = 0x178;
\r
3187 private static readonly uint sectionHeaderSize = 40;
\r
3188 private static readonly uint SectionAlignment = 0x2000;
\r
3189 private static readonly uint ImageBase = 0x400000;
\r
3190 private static readonly uint ImportTableSize = 40;
\r
3191 private static readonly uint IATSize = 8;
\r
3192 private static readonly uint CLIHeaderSize = 72;
\r
3193 private uint runtimeFlags = 0x01; // COMIMAGE_FLAGS_ILONLY
\r
3194 // 32BITREQUIRED 0x02, STRONGNAMESIGNED 0x08, TRACKDEBUGDATA 0x10000
\r
3195 private static readonly uint relocFlags = 0x42000040;
\r
3196 private static readonly ushort exeCharacteristics = 0x010E;
\r
3197 private static readonly ushort dllCharacteristics = 0x210E;
\r
3198 // section names are all 8 bytes
\r
3199 private static readonly string textName = ".text\0\0\0";
\r
3200 private static readonly string sdataName = ".sdata\0\0";
\r
3201 private static readonly string relocName = ".reloc\0\0";
\r
3202 private static readonly string rsrcName = ".rsrc\0\0\0";
\r
3203 private static readonly string exeHintNameTable = "\0\0_CorExeMain\0";
\r
3204 private static readonly string dllHintNameTable = "\0\0_CorDllMain\0";
\r
3205 private static readonly string runtimeEngineName = "mscoree.dll\0\0";
\r
3207 private Section text, sdata, rsrc;
\r
3209 BinaryWriter reloc = new BinaryWriter(new MemoryStream());
\r
3210 uint dateStamp = 0;
\r
3211 DateTime origin = new DateTime(1970,1,1);
\r
3212 uint numSections = 2; // always have .text and .reloc sections
\r
3213 internal SubSystem subSys = SubSystem.Windows_CUI; // default is Windows Console mode
\r
3214 internal uint fileAlign = minFileAlign;
\r
3215 uint entryPointOffset, entryPointPadding, imageSize, headerSize, headerPadding, entryPointToken = 0;
\r
3216 uint relocOffset, relocRVA, relocSize, relocPadding, relocTide, hintNameTableOffset;
\r
3217 uint metaDataOffset, runtimeEngineOffset, initDataSize = 0, importTablePadding;
\r
3218 uint importTableOffset, importLookupTableOffset, totalImportTableSize;
\r
3219 MetaData metaData;
\r
3220 char[] runtimeEngine = runtimeEngineName.ToCharArray(), hintNameTable;
\r
3221 bool doDLL, largeStrings, largeGUID, largeUS, largeBlob;
\r
3222 ushort characteristics;
\r
3224 internal FileImage(bool makeDLL, string fileName) : base(new FileStream(fileName,FileMode.Create)) {
\r
3225 InitFileImage(makeDLL);
\r
3226 TimeSpan tmp = System.IO.File.GetCreationTime(fileName).Subtract(origin);
\r
3227 dateStamp = Convert.ToUInt32(tmp.TotalSeconds);
\r
3230 internal FileImage(bool makeDLL, Stream str) : base(str) {
\r
3231 InitFileImage(makeDLL);
\r
3232 TimeSpan tmp = DateTime.Now.Subtract(origin);
\r
3233 dateStamp = Convert.ToUInt32(tmp.TotalSeconds);
\r
3236 private void InitFileImage(bool makeDLL) {
\r
3239 hintNameTable = dllHintNameTable.ToCharArray();
\r
3240 characteristics = dllCharacteristics;
\r
3242 hintNameTable = exeHintNameTable.ToCharArray();
\r
3243 characteristics = exeCharacteristics;
\r
3245 text = new Section(textName,0x60000020); // IMAGE_SCN_CNT CODE, EXECUTE, READ
\r
3246 // rsrc = new Section(rsrcName,0x40000040); // IMAGE_SCN_CNT INITIALIZED_DATA, READ
\r
3247 metaData = new MetaData(this);
\r
3250 internal MetaData GetMetaData() {
\r
3254 private uint GetNextSectStart(uint rva, uint tide) {
\r
3255 if (tide < SectionAlignment) return rva + SectionAlignment;
\r
3256 return rva + ((tide / SectionAlignment) + 1) * SectionAlignment;
\r
3259 private void BuildTextSection() {
\r
3261 // IAT (single entry 8 bytes for pure CIL)
\r
3262 // CLIHeader (72 bytes)
\r
3263 // CIL instructions for all methods (variable size)
\r
3265 // ImportTable (40 bytes)
\r
3266 // ImportLookupTable(8 bytes) (same as IAT for standard CIL files)
\r
3267 // Hint/Name Tables with entry "_CorExeMain" for .exe file and "_CorDllMain" for .dll (14 bytes)
\r
3268 // ASCII string "mscoree.dll" referenced in ImportTable (+ padding = 16 bytes)
\r
3269 // Entry Point (0xFF25 followed by 4 bytes 0x400000 + RVA of .text)
\r
3270 metaData.BuildMetaData(IATSize + CLIHeaderSize);
\r
3271 metaDataOffset = IATSize + CLIHeaderSize;
\r
3272 // Console.WriteLine("Code starts at " + metaDataOffset);
\r
3273 metaDataOffset += metaData.CodeSize();
\r
3274 // resourcesStart =
\r
3275 // strongNameSig = metaData.GetStrongNameSig();
\r
3276 // fixUps = RVA for vtable
\r
3277 importTableOffset = metaDataOffset + metaData.Size();
\r
3278 importTablePadding = NumToAlign(importTableOffset,16);
\r
3279 importTableOffset += importTablePadding;
\r
3280 importLookupTableOffset = importTableOffset + ImportTableSize;
\r
3281 hintNameTableOffset = importLookupTableOffset + IATSize;
\r
3282 runtimeEngineOffset = hintNameTableOffset + (uint)hintNameTable.Length;
\r
3283 entryPointOffset = runtimeEngineOffset + (uint)runtimeEngine.Length;
\r
3284 totalImportTableSize = entryPointOffset - importTableOffset;
\r
3285 // Console.WriteLine("total import table size = " + totalImportTableSize);
\r
3286 // Console.WriteLine("entrypoint offset = " + entryPointOffset);
\r
3287 entryPointPadding = NumToAlign(entryPointOffset,4) + 2;
\r
3288 entryPointOffset += entryPointPadding;
\r
3289 text.AddReloc(entryPointOffset+2);
\r
3290 text.IncTide(entryPointOffset + 6);
\r
3291 //if (text.Tide() < fileAlign) fileAlign = minFileAlign;
\r
3292 text.SetSize(NumToAlign(text.Tide(),fileAlign));
\r
3293 // Console.WriteLine("text size = " + text.Size() + " text tide = " + text.Tide() + " text padding = " + text.Padding());
\r
3294 // Console.WriteLine("metaDataOffset = " + Hex.Int(metaDataOffset));
\r
3295 // Console.WriteLine("importTableOffset = " + Hex.Int(importTableOffset));
\r
3296 // Console.WriteLine("importLookupTableOffset = " + Hex.Int(importLookupTableOffset));
\r
3297 // Console.WriteLine("hintNameTableOffset = " + Hex.Int(hintNameTableOffset));
\r
3298 // Console.WriteLine("runtimeEngineOffset = " + Hex.Int(runtimeEngineOffset));
\r
3299 // Console.WriteLine("entryPointOffset = " + Hex.Int(entryPointOffset));
\r
3300 // Console.WriteLine("entryPointPadding = " + Hex.Int(entryPointPadding));
\r
3304 internal void BuildRelocSection() {
\r
3305 text.DoRelocs(reloc);
\r
3306 if (sdata != null) sdata.DoRelocs(reloc);
\r
3307 if (rsrc != null) rsrc.DoRelocs(reloc);
\r
3308 relocTide = (uint)reloc.Seek(0,SeekOrigin.Current);
\r
3309 relocPadding = NumToAlign(relocTide,fileAlign);
\r
3310 relocSize = relocTide + relocPadding;
\r
3311 imageSize = relocRVA + SectionAlignment;
\r
3312 initDataSize += relocSize;
\r
3315 private void CalcOffsets() {
\r
3320 headerSize = fileHeaderSize + (numSections * sectionHeaderSize);
\r
3321 headerPadding = NumToAlign(headerSize,fileAlign);
\r
3322 headerSize += headerPadding;
\r
3323 uint offset = headerSize;
\r
3324 uint rva = SectionAlignment;
\r
3325 text.SetOffset(offset);
\r
3327 offset += text.Size();
\r
3328 rva = GetNextSectStart(rva,text.Tide());
\r
3329 // Console.WriteLine("headerSize = " + headerSize);
\r
3330 // Console.WriteLine("headerPadding = " + headerPadding);
\r
3331 // Console.WriteLine("textOffset = " + Hex.Int(text.Offset()));
\r
3332 if (sdata != null) {
\r
3333 sdata.SetSize(NumToAlign(sdata.Tide(),fileAlign));
\r
3334 sdata.SetOffset(offset);
\r
3335 sdata.SetRVA(rva);
\r
3336 offset += sdata.Size();
\r
3337 rva = GetNextSectStart(rva,sdata.Tide());
\r
3338 initDataSize += sdata.Size();
\r
3340 if (rsrc != null) {
\r
3341 rsrc.SetSize(NumToAlign(rsrc.Tide(),fileAlign));
\r
3342 rsrc.SetOffset(offset);
\r
3344 offset += rsrc.Size();
\r
3345 rva = GetNextSectStart(rva,rsrc.Tide());
\r
3346 initDataSize += rsrc.Size();
\r
3348 relocOffset = offset;
\r
3352 internal void MakeFile() {
\r
3353 if (doDLL) hintNameTable = dllHintNameTable.ToCharArray();
\r
3354 else hintNameTable = exeHintNameTable.ToCharArray();
\r
3355 BuildTextSection();
\r
3357 BuildRelocSection();
\r
3358 // now write it out
\r
3365 private void WriteHeader() {
\r
3367 // Console.WriteLine("Writing PEHeader at offset " + Seek(0,SeekOrigin.Current));
\r
3369 // Console.WriteLine("Writing text section header at offset " + Hex.Long(Seek(0,SeekOrigin.Current)));
\r
3370 text.WriteHeader(this,relocRVA);
\r
3371 if (sdata != null) sdata.WriteHeader(this,relocRVA);
\r
3372 if (rsrc != null) rsrc.WriteHeader(this,relocRVA);
\r
3373 // Console.WriteLine("Writing reloc section header at offset " + Seek(0,SeekOrigin.Current));
\r
3374 WriteRelocSectionHeader();
\r
3375 // Console.WriteLine("Writing padding at offset " + Seek(0,SeekOrigin.Current));
\r
3376 WriteZeros(headerPadding);
\r
3379 private void WriteSections() {
\r
3380 // Console.WriteLine("Writing text section at offset " + Seek(0,SeekOrigin.Current));
\r
3381 WriteTextSection();
\r
3382 if (sdata != null) WriteSDataSection();
\r
3383 if (rsrc != null) WriteRsrcSection();
\r
3384 WriteRelocSection();
\r
3387 private void WriteIAT() {
\r
3388 Write(text.RVA() + hintNameTableOffset);
\r
3392 private void WriteImportTables() {
\r
3394 WriteZeros(importTablePadding);
\r
3395 // Console.WriteLine("Writing import tables at offset " + Hex.Long(Seek(0,SeekOrigin.Current)));
\r
3396 Write(importLookupTableOffset + text.RVA());
\r
3398 Write(runtimeEngineOffset + text.RVA());
\r
3399 Write(text.RVA()); // IAT is at the beginning of the text section
\r
3401 // Import Lookup Table
\r
3402 WriteIAT(); // lookup table and IAT are the same
\r
3403 // Hint/Name Table
\r
3404 // Console.WriteLine("Writing hintname table at " + Hex.Long(Seek(0,SeekOrigin.Current)));
\r
3405 Write(hintNameTable);
\r
3406 Write(runtimeEngineName.ToCharArray());
\r
3409 private void WriteTextSection() {
\r
3412 // Console.WriteLine("Writing code at " + Hex.Long(Seek(0,SeekOrigin.Current)));
\r
3413 metaData.WriteByteCodes(this);
\r
3414 // Console.WriteLine("Finished writing code at " + Hex.Long(Seek(0,SeekOrigin.Current)));
\r
3415 largeStrings = metaData.LargeStringsIndex();
\r
3416 largeGUID = metaData.LargeGUIDIndex();
\r
3417 largeUS = metaData.LargeUSIndex();
\r
3418 largeBlob = metaData.LargeBlobIndex();
\r
3419 metaData.WriteMetaData(this);
\r
3420 WriteImportTables();
\r
3421 WriteZeros(entryPointPadding);
\r
3422 Write((ushort)0x25FF);
\r
3423 Write(ImageBase + text.RVA());
\r
3424 WriteZeros(text.Padding());
\r
3427 private void WriteCLIHeader() {
\r
3428 Write(CLIHeaderSize); // Cb
\r
3429 Write((short)2); // Major runtime version
\r
3430 Write((short)0); // Minor runtime version
\r
3431 Write(text.RVA() + metaDataOffset);
\r
3432 Write(metaData.Size());
\r
3433 Write(runtimeFlags);
\r
3434 Write(entryPointToken);
\r
3435 WriteZeros(8); // Resources - used by Manifest Resources NYI
\r
3436 WriteZeros(8); // Strong Name stuff here!! NYI
\r
3437 WriteZeros(8); // CodeManagerTable
\r
3438 WriteZeros(8); // VTableFixups NYI
\r
3439 WriteZeros(16); // ExportAddressTableJumps, ManagedNativeHeader
\r
3442 private void WriteSDataSection() {
\r
3443 for (int i=0; i < data.Count; i++) {
\r
3444 ((DataConstant)data[i]).Write(this);
\r
3448 private void WriteRsrcSection() {
\r
3451 private void WriteRelocSection() {
\r
3452 // Console.WriteLine("Writing reloc section at " + Seek(0,SeekOrigin.Current) + " = " + relocOffset);
\r
3453 MemoryStream str = (MemoryStream)reloc.BaseStream;
\r
3454 Write(str.ToArray());
\r
3455 WriteZeros(NumToAlign((uint)str.Position,fileAlign));
\r
3458 internal void SetEntryPoint(uint entryPoint) {
\r
3459 entryPointToken = entryPoint;
\r
3462 internal void AddInitData(DataConstant cVal) {
\r
3463 if (sdata == null) {
\r
3464 sdata = new Section(sdataName,0xC0000040); // IMAGE_SCN_CNT INITIALIZED_DATA, READ, WRITE
\r
3465 data = new ArrayList();
\r
3468 cVal.DataOffset = sdata.Tide();
\r
3469 sdata.IncTide(cVal.GetSize());
\r
3472 internal void WriteZeros(uint numZeros) {
\r
3473 for (int i=0; i < numZeros; i++) {
\r
3478 internal void WritePEHeader() {
\r
3479 Write((ushort)0x014C); // Machine - always 0x14C for Managed PE Files (allow others??)
\r
3480 Write((ushort)numSections);
\r
3482 WriteZeros(8); // Pointer to Symbol Table and Number of Symbols (always zero for ECMA CLI files)
\r
3483 Write((ushort)0x00E0); // Size of Optional Header
\r
3484 Write(characteristics);
\r
3485 // PE Optional Header
\r
3486 Write((ushort)0x010B); // Magic
\r
3487 Write((byte)0x6); // LMajor pure-IL = 6 C++ = 7
\r
3488 Write((byte)0x0); // LMinor
\r
3489 Write(text.Size());
\r
3490 Write(initDataSize);
\r
3491 Write(0); // Check other sections here!!
\r
3492 Write(text.RVA() + entryPointOffset);
\r
3493 Write(text.RVA());
\r
3494 uint dataBase = 0;
\r
3495 if (sdata != null) dataBase = sdata.RVA();
\r
3496 else if (rsrc != null) dataBase = rsrc.RVA();
\r
3497 else dataBase = relocRVA;
\r
3500 Write(SectionAlignment);
\r
3502 Write((ushort)0x04); // OS Major
\r
3503 WriteZeros(6); // OS Minor, User Major, User Minor
\r
3504 Write((ushort)0x04); // SubSys Major
\r
3505 WriteZeros(6); // SybSys Minor, Reserved
\r
3507 Write(headerSize);
\r
3508 Write((int)0); // File Checksum
\r
3509 Write((ushort)subSys);
\r
3510 Write((short)0); // DLL Flags
\r
3511 Write((uint)0x100000); // Stack Reserve Size
\r
3512 Write((uint)0x1000); // Stack Commit Size
\r
3513 Write((uint)0x100000); // Heap Reserve Size
\r
3514 Write((uint)0x1000); // Heap Commit Size
\r
3515 Write(0); // Loader Flags
\r
3516 Write(0x10); // Number of Data Directories
\r
3517 WriteZeros(8); // Export Table
\r
3518 Write(importTableOffset + text.RVA());
\r
3519 Write(totalImportTableSize);
\r
3520 WriteZeros(24); // Resource, Exception and Certificate Tables
\r
3523 WriteZeros(48); // Debug, Copyright, Global Ptr, TLS, Load Config and Bound Import Tables
\r
3524 Write(text.RVA()); // IATRVA - IAT is at start of .text Section
\r
3526 WriteZeros(8); // Delay Import Descriptor
\r
3527 Write(text.RVA()+IATSize); // CLIHeader immediately follows IAT
\r
3528 Write(CLIHeaderSize);
\r
3529 WriteZeros(8); // Reserved
\r
3532 internal void WriteRelocSectionHeader() {
\r
3533 Write(relocName.ToCharArray());
\r
3537 Write(relocOffset);
\r
3539 Write(relocFlags);
\r
3542 private void Align (MemoryStream str, int val) {
\r
3543 if ((str.Position % val) != 0) {
\r
3544 for (int i=val - (int)(str.Position % val); i > 0; i--) {
\r
3550 private uint Align(uint val, uint alignVal) {
\r
3551 if ((val % alignVal) != 0) {
\r
3552 val += alignVal - (val % alignVal);
\r
3557 private uint NumToAlign(uint val, uint alignVal) {
\r
3558 if ((val % alignVal) == 0) return 0;
\r
3559 return alignVal - (val % alignVal);
\r
3562 internal void StringsIndex(uint ix) {
\r
3563 if (largeStrings) Write(ix);
\r
3564 else Write((ushort)ix);
\r
3567 internal void GUIDIndex(uint ix) {
\r
3568 if (largeGUID) Write(ix);
\r
3569 else Write((ushort)ix);
\r
3572 internal void USIndex(uint ix) {
\r
3573 if (largeUS) Write(ix);
\r
3574 else Write((ushort)ix);
\r
3577 internal void BlobIndex(uint ix) {
\r
3578 if (largeBlob) Write(ix);
\r
3579 else Write((ushort)ix);
\r
3582 internal void WriteIndex(MDTable tabIx,uint ix) {
\r
3583 if (metaData.LargeIx(tabIx)) Write(ix);
\r
3584 else Write((ushort)ix);
\r
3587 internal void WriteCodedIndex(CIx code, MetaDataElement elem) {
\r
3588 metaData.WriteCodedIndex(code,elem,this);
\r
3591 internal void WriteCodeRVA(uint offs) {
\r
3592 Write(text.RVA() + offs);
\r
3595 internal void WriteDataRVA(uint offs) {
\r
3596 Write(sdata.RVA() + offs);
\r
3599 internal void Write3Bytes(uint val) {
\r
3600 byte b3 = (byte)((val & FileImage.iByteMask[2]) >> 16);
\r
3601 byte b2 = (byte)((val & FileImage.iByteMask[1]) >> 8);;
\r
3602 byte b1 = (byte)(val & FileImage.iByteMask[0]);
\r
3609 /**************************************************************************/
\r
3611 /// Descriptor for a file referenced in THIS assembly/module (.file)
\r
3613 public class FileRef : MetaDataElement
\r
3615 private static readonly uint HasMetaData = 0x1;
\r
3616 uint nameIx = 0, hashIx = 0;
\r
3619 internal FileRef(string name, byte[] hashBytes, bool metaData,
\r
3620 bool entryPoint, MetaData md) {
\r
3621 if (metaData) flags = HasMetaData;
\r
3622 if (entryPoint) md.SetEntryPoint(this);
\r
3623 nameIx = md.AddToStringsHeap(name);
\r
3624 hashIx = md.AddToBlobHeap(hashBytes);
\r
3625 tabIx = MDTable.File;
\r
3628 internal FileRef(uint nameIx, byte[] hashBytes, bool metaData,
\r
3629 bool entryPoint, MetaData md) {
\r
3630 if (metaData) flags = HasMetaData;
\r
3631 if (entryPoint) md.SetEntryPoint(this);
\r
3632 this.nameIx = nameIx;
\r
3633 hashIx = md.AddToBlobHeap(hashBytes);
\r
3634 tabIx = MDTable.File;
\r
3637 internal sealed override uint Size(MetaData md) {
\r
3638 return 4 + md.StringsIndexSize() + md.BlobIndexSize();
\r
3641 internal sealed override void Write(FileImage output) {
\r
3642 output.Write(flags);
\r
3643 output.StringsIndex(nameIx);
\r
3644 output.BlobIndex(hashIx);
\r
3647 internal sealed override uint GetCodedIx(CIx code) {
\r
3649 case (CIx.HasCustomAttr) : return 16;
\r
3650 case (CIx.Implementation) : return 0;
\r
3656 /**************************************************************************/
\r
3658 /// Descriptor for pinvoke information for a method NOT YET IMPLEMENTED
\r
3660 public class ImplMap : MetaDataElement
\r
3662 private static readonly ushort NoMangle = 0x01;
\r
3665 string importName;
\r
3667 ModuleRef importScope;
\r
3669 internal ImplMap(ushort flag, Method implMeth, string iName, ModuleRef mScope) {
\r
3672 importName = iName;
\r
3673 importScope = mScope;
\r
3674 tabIx = MDTable.ImplMap;
\r
3675 if (iName == null) flags |= NoMangle;
\r
3676 //throw(new NotYetImplementedException("PInvoke "));
\r
3679 internal sealed override void BuildTables(MetaData md) {
\r
3681 iNameIx = md.AddToStringsHeap(importName);
\r
3685 internal sealed override uint Size(MetaData md) {
\r
3686 return 2+ md.CodedIndexSize(CIx.MemberForwarded) +
\r
3687 md.StringsIndexSize() + md.TableIndexSize(MDTable.ModuleRef);
\r
3690 internal sealed override void Write(FileImage output) {
\r
3691 output.Write(flags);
\r
3692 output.WriteCodedIndex(CIx.MemberForwarded,meth);
\r
3693 output.StringsIndex(iNameIx);
\r
3694 output.WriteIndex(MDTable.ModuleRef,importScope.Row);
\r
3699 /**************************************************************************/
\r
3701 /// Descriptor for an IL instruction
\r
3703 internal abstract class CILInstruction {
\r
3704 protected static readonly sbyte maxByteVal = 127;
\r
3705 protected static readonly sbyte minByteVal = -128;
\r
3706 protected static readonly byte leadByte = 0xFE;
\r
3707 protected static readonly uint USHeapIndex = 0x70000000;
\r
3708 protected static readonly int longInstrStart = (int)Op.arglist;
\r
3709 public bool twoByteInstr = false;
\r
3710 public uint size = 0;
\r
3711 public uint offset;
\r
3713 internal virtual bool Check(MetaData md) {
\r
3717 internal virtual void Write(FileImage output) { }
\r
3721 internal class CILByte : CILInstruction {
\r
3724 internal CILByte(byte bVal) {
\r
3729 internal override void Write(FileImage output) {
\r
3730 output.Write(byteVal);
\r
3736 internal class Instr : CILInstruction {
\r
3737 protected int instr;
\r
3739 internal Instr(int inst) {
\r
3740 if (inst >= longInstrStart) {
\r
3741 instr = inst - longInstrStart;
\r
3742 twoByteInstr = true;
\r
3750 internal override void Write(FileImage output) {
\r
3751 //Console.WriteLine("Writing instruction " + instr + " with size " + size);
\r
3752 if (twoByteInstr) output.Write(leadByte);
\r
3753 output.Write((byte)instr);
\r
3758 internal class IntInstr : Instr {
\r
3762 internal IntInstr(int inst, int num, bool byteSize) : base(inst) {
\r
3764 byteNum = byteSize;
\r
3765 if (byteNum) size++;
\r
3769 internal sealed override void Write(FileImage output) {
\r
3770 base.Write(output);
\r
3772 output.Write((sbyte)val);
\r
3774 output.Write(val);
\r
3779 internal class UIntInstr : Instr {
\r
3783 internal UIntInstr(int inst, int num, bool byteSize) : base(inst) {
\r
3785 byteNum = byteSize;
\r
3786 if (byteNum) size++;
\r
3790 internal sealed override void Write(FileImage output) {
\r
3791 base.Write(output);
\r
3793 output.Write((byte)val);
\r
3795 output.Write((ushort)val);
\r
3800 internal class LongInstr : Instr {
\r
3803 internal LongInstr(int inst, long l) : base(inst) {
\r
3808 internal sealed override void Write(FileImage output) {
\r
3809 base.Write(output);
\r
3810 output.Write(val);
\r
3815 internal class FloatInstr : Instr {
\r
3818 internal FloatInstr(int inst, float f) : base(inst) {
\r
3823 internal sealed override void Write(FileImage output) {
\r
3824 base.Write(output);
\r
3825 output.Write(fVal);
\r
3830 internal class DoubleInstr : Instr {
\r
3833 internal DoubleInstr(int inst, double d) : base(inst) {
\r
3838 internal sealed override void Write(FileImage output) {
\r
3839 base.Write(output);
\r
3840 output.Write(val);
\r
3845 internal class StringInstr : Instr {
\r
3849 internal StringInstr(int inst, string str) : base(inst) {
\r
3854 internal sealed override bool Check(MetaData md) {
\r
3855 strIndex = md.AddToUSHeap(val);
\r
3859 internal sealed override void Write(FileImage output) {
\r
3860 base.Write(output);
\r
3861 output.Write(USHeapIndex | strIndex);
\r
3866 internal class LabelInstr : CILInstruction {
\r
3869 internal LabelInstr(CILLabel lab) {
\r
3871 label.AddLabelInstr(this);
\r
3875 internal class FieldInstr : Instr {
\r
3878 internal FieldInstr(int inst, Field f) : base(inst) {
\r
3883 internal sealed override void Write(FileImage output) {
\r
3884 base.Write(output);
\r
3885 output.Write(field.Token());
\r
3890 internal class MethInstr : Instr {
\r
3893 internal MethInstr(int inst, Method m) : base(inst) {
\r
3898 internal sealed override void Write(FileImage output) {
\r
3899 base.Write(output);
\r
3900 output.Write(meth.Token());
\r
3905 internal class SigInstr : Instr {
\r
3906 CalliSig signature;
\r
3908 internal SigInstr(int inst, CalliSig sig) : base(inst) {
\r
3913 internal sealed override bool Check(MetaData md) {
\r
3914 md.AddToTable(MDTable.StandAloneSig,signature);
\r
3915 signature.BuildTables(md);
\r
3919 internal sealed override void Write(FileImage output) {
\r
3920 base.Write(output);
\r
3921 output.Write(signature.Token());
\r
3925 internal class TypeInstr : Instr {
\r
3926 MetaDataElement theType;
\r
3928 internal TypeInstr(int inst, Type aType, MetaData md) : base(inst) {
\r
3929 theType = aType.GetTypeSpec(md);
\r
3933 internal sealed override void Write(FileImage output) {
\r
3934 base.Write(output);
\r
3935 output.Write(theType.Token());
\r
3940 internal class BranchInstr : Instr {
\r
3942 private bool shortVer = true;
\r
3943 private static readonly byte longInstrOffset = 13;
\r
3944 private int target = 0;
\r
3946 internal BranchInstr(int inst, CILLabel dst) : base(inst) {
\r
3948 dest.AddBranch(this);
\r
3952 internal sealed override bool Check(MetaData md) {
\r
3953 target = (int)dest.GetLabelOffset() - (int)(offset + size);
\r
3954 if (shortVer && ((target < minByteVal) || (target > maxByteVal))) {
\r
3955 if (instr < (int)BranchOp.leave) instr += longInstrOffset;
\r
3964 internal sealed override void Write(FileImage output) {
\r
3965 base.Write(output);
\r
3967 output.Write((sbyte)target);
\r
3969 output.Write(target);
\r
3974 internal class SwitchInstr : Instr {
\r
3976 uint numCases = 0;
\r
3978 internal SwitchInstr(int inst, CILLabel[] dsts) : base(inst) {
\r
3980 if (cases != null) numCases = (uint)cases.Length;
\r
3981 size += 4 + (numCases * 4);
\r
3982 for (int i=0; i < numCases; i++) {
\r
3983 cases[i].AddBranch(this);
\r
3987 internal sealed override void Write(FileImage output) {
\r
3988 base.Write(output);
\r
3989 output.Write(numCases);
\r
3990 for (int i=0; i < numCases; i++) {
\r
3991 int target = (int)cases[i].GetLabelOffset() - (int)(offset + size);
\r
3992 output.Write(target);
\r
3997 /**************************************************************************/
\r
3999 public class GenericParameter : MetaDataElement
\r
4001 MetaDataElement owner;
4007 internal GenericParameter (ClassDef owner, MetaData metadata,
4008 short index, string name) : this (owner, metadata, index, name, true)
4012 internal GenericParameter (MethodDef owner, MetaData metadata,
4013 short index, string name) : this (owner, metadata, index, name, true)
4017 private GenericParameter (MetaDataElement owner, MetaData metadata,
4018 short index, string name, bool nadda)
4020 this.owner = owner;
\r
4021 this.metadata = metadata;
4022 this.index = index;
\r
4023 tabIx = MDTable.GenericParam;
\r
4027 public void AddConstraint (Type constraint) {
4028 metadata.AddToTable (MDTable.GenericParamConstraint,
\r
4029 new GenericParamConstraint (this, constraint));
\r
4032 internal sealed override uint Size(MetaData md) {
\r
4033 return (uint) (4 +
\r
4034 md.CodedIndexSize(CIx.TypeOrMethodDef) +
\r
4036 md.TableIndexSize(MDTable.TypeDef));
\r
4039 internal sealed override void BuildTables(MetaData md) {
\r
4041 nameIx = md.AddToStringsHeap(name);
\r
4045 internal sealed override void Write(FileImage output) {
\r
4046 output.Write ((short) index);
\r
4047 output.Write ((short) 0);
\r
4048 output.WriteCodedIndex(CIx.TypeOrMethodDef, owner);
\r
4049 output.Write ((uint) nameIx);
\r
4050 output.WriteIndex(MDTable.TypeDef,owner.Row);
\r
4056 internal class GenericParamConstraint : MetaDataElement
\r
4058 GenericParameter param;
\r
4061 public GenericParamConstraint (GenericParameter param, Type type) {
\r
4062 this.param = param;
\r
4064 tabIx = MDTable.GenericParamConstraint;
\r
4067 internal sealed override uint Size(MetaData md) {
\r
4068 return (uint) (md.TableIndexSize(MDTable.GenericParam) +
\r
4069 md.CodedIndexSize(CIx.TypeDefOrRef));
\r
4072 internal sealed override void Write(FileImage output) {
\r
4073 output.WriteIndex(MDTable.GenericParam, param.Row);
\r
4074 output.WriteCodedIndex(CIx.TypeDefOrRef, type);
\r
4079 /**************************************************************************/
\r
4081 /// Descriptor for interface implemented by a class
\r
4083 public class InterfaceImpl: MetaDataElement
\r
4085 ClassDef theClass;
\r
4086 Class theInterface;
\r
4088 internal InterfaceImpl(ClassDef theClass, Class theInterface) {
\r
4089 this.theClass = theClass;
\r
4090 this.theInterface = theInterface;
\r
4091 tabIx = MDTable.InterfaceImpl;
\r
4094 internal sealed override uint Size(MetaData md) {
\r
4095 return md.TableIndexSize(MDTable.TypeDef) +
\r
4096 md.CodedIndexSize(CIx.TypeDefOrRef);
\r
4099 internal sealed override void Write(FileImage output) {
\r
4100 output.WriteIndex(MDTable.TypeDef,theClass.Row);
\r
4101 output.WriteCodedIndex(CIx.TypeDefOrRef,theInterface);
\r
4104 internal sealed override uint GetCodedIx(CIx code) { return 5; }
\r
4107 /**************************************************************************/
\r
4109 /// Descriptor for a local of a method
\r
4111 public class Local
\r
4113 private static readonly byte Pinned = 0x45;
\r
4116 bool pinned = false, byref = false;
\r
4119 /// Create a new local variable
\r
4121 /// <param name="lName">name of the local variable</param>
\r
4122 /// <param name="lType">type of the local variable</param>
\r
4123 public Local(string lName, Type lType) {
\r
4129 /// Create a new local variable that is byref and/or pinned
\r
4131 /// <param name="lName">local name</param>
\r
4132 /// <param name="lType">local type</param>
\r
4133 /// <param name="byRef">is byref</param>
\r
4134 /// <param name="isPinned">has pinned attribute</param>
\r
4135 public Local(string lName, Type lType, bool byRef, bool isPinned)
\r
4140 pinned = isPinned;
\r
4143 internal void TypeSig(MemoryStream str) {
\r
4144 if (pinned) str.WriteByte(Pinned);
\r
4145 type.TypeSig(str);
\r
4149 /**************************************************************************/
\r
4151 /// Descriptor for the locals for a method
\r
4154 public class LocalSig : Signature
\r
4156 private static readonly byte LocalSigByte = 0x7;
\r
4159 public LocalSig(Local[] locals) {
\r
4160 this.locals = locals;
\r
4161 tabIx = MDTable.StandAloneSig;
\r
4164 internal sealed override void BuildTables(MetaData md) {
\r
4166 MemoryStream sig = new MemoryStream();
\r
4167 sig.WriteByte(LocalSigByte);
\r
4168 MetaData.CompressNum((uint)locals.Length,sig);
\r
4169 for (int i=0; i < locals.Length; i++) {
\r
4170 ((Local)locals[i]).TypeSig(sig);
\r
4172 sigIx = md.AddToBlobHeap(sig.ToArray());
\r
4178 /**************************************************************************/
\r
4180 /// Descriptor for resources used in this PE file NOT YET IMPLEMENTED
\r
4183 public class ManifestResource : MetaDataElement
\r
4185 private static readonly uint PublicResource = 0x1;
\r
4186 private static readonly uint PrivateResource = 0x2;
\r
4189 MetaDataElement rRef;
\r
4194 public ManifestResource(string name, bool isPub, FileRef fileRef) {
\r
4196 if (isPub) flags = PublicResource;
\r
4197 else flags = PrivateResource;
\r
4199 tabIx = MDTable.ManifestResource;
\r
4200 throw(new NotYetImplementedException("Manifest Resources "));
\r
4203 public ManifestResource(string name, bool isPub, FileRef fileRef,
\r
4206 if (isPub) flags = PublicResource;
\r
4207 else flags = PrivateResource;
\r
4209 fileOffset = fileIx;
\r
4212 public ManifestResource(string name, bool isPub, AssemblyRef assemRef) {
\r
4214 if (isPub) flags = PublicResource;
\r
4215 else flags = PrivateResource;
\r
4219 internal sealed override void BuildTables(MetaData md) {
\r
4221 nameIx = md.AddToStringsHeap(mrName);
\r
4225 internal sealed override uint Size(MetaData md) {
\r
4226 return 8 + md.StringsIndexSize() +
\r
4227 md.CodedIndexSize(CIx.Implementation);
\r
4230 internal sealed override void Write(FileImage output) {
\r
4231 output.Write(fileOffset);
\r
4232 output.Write(flags);
\r
4233 output.StringsIndex(nameIx);
\r
4234 output.WriteCodedIndex(CIx.Implementation,rRef);
\r
4237 internal sealed override uint GetCodedIx(CIx code) { return 18; }
\r
4240 /**************************************************************************/
\r
4242 /// Base class for elements in the PropertyMap, EventMap and
\r
4243 /// NestedClass MetaData tables
\r
4245 public class MapElem : MetaDataElement
\r
4249 MDTable elemTable;
\r
4251 internal MapElem(ClassDef par, uint elIx, MDTable elemTab) {
\r
4254 elemTable = elemTab;
\r
4257 internal sealed override uint Size(MetaData md) {
\r
4258 return md.TableIndexSize(MDTable.TypeDef) + md.TableIndexSize(elemTable);
\r
4261 internal sealed override void Write(FileImage output) {
\r
4262 output.WriteIndex(MDTable.TypeDef,parent.Row);
\r
4263 output.WriteIndex(elemTable,elemIx);
\r
4266 /**************************************************************************/
\r
4268 /// Base class for field/methods (member of a class)
\r
4270 public abstract class Member : MetaDataElement
\r
4272 protected string name;
\r
4273 protected uint nameIx = 0, sigIx = 0;
\r
4275 internal Member(string memName)
\r
4278 tabIx = MDTable.MemberRef;
\r
4282 /**************************************************************************/
\r
4285 /// Root (20 bytes + UTF-8 Version String + quad align padding)
\r
4286 /// StreamHeaders (8 bytes + null terminated name string + quad align padding)
\r
4288 /// #~ (always present - holds metadata tables)
\r
4289 /// #Strings (always present - holds identifier strings)
\r
4290 /// #US (Userstring heap)
\r
4291 /// #Blob (signature blobs)
\r
4292 /// #GUID (guids for assemblies or Modules)
\r
4295 public class MetaData
\r
4297 private static readonly int[] CIxShiftMap = {2,2,5,1,2,3,1,1,1,2,3,2,1};
\r
4298 private static readonly byte StringsHeapMask = 0x1;
\r
4299 private static readonly byte GUIDHeapMask = 0x2;
\r
4300 private static readonly byte BlobHeapMask = 0x4;
\r
4301 private static readonly uint MetaDataSignature = 0x424A5342;
\r
4302 private static readonly uint maxSmlIxSize = 0xFFFF;
\r
4303 private static readonly uint max1BitSmlIx = 0x7FFF;
\r
4304 private static readonly uint max2BitSmlIx = 0x3FFF;
\r
4305 private static readonly uint max3BitSmlIx = 0x1FFF;
\r
4306 private static readonly uint max5BitSmlIx = 0x7FF;
\r
4307 // NOTE: version and stream name strings MUST always be quad padded
\r
4308 private static readonly string version = "v1.0.3705\0\0\0";
\r
4309 private static readonly char[] tildeName = {'#','~','\0','\0'};
\r
4310 private static readonly char[] stringsName = {'#','S','t','r','i','n','g','s','\0','\0','\0','\0'};
\r
4311 private static readonly char[] usName = {'#','U','S','\0'};
\r
4312 private static readonly char[] guidName = {'#','G','U','I','D','\0','\0','\0'};
\r
4313 private static readonly char[] blobName = {'#','B','l','o','b','\0','\0','\0'};
\r
4314 private static readonly uint MetaDataHeaderSize = 20 + (uint)version.Length;
\r
4315 private static readonly uint TildeHeaderSize = 24;
\r
4316 private static readonly uint StreamHeaderSize = 8;
\r
4317 private static readonly uint numMetaDataTables = (int)MDTable.GenericParamConstraint + 1;
\r
4318 private static readonly uint tildeHeaderSize = 8 + (uint)tildeName.Length;
\r
4320 MetaDataStream strings, us, guid, blob;
\r
4322 MetaDataStream[] streams = new MetaDataStream[5];
\r
4323 uint numStreams = 5;
\r
4324 uint tildeTide = 0, tildePadding = 0, tildeStart = 0;
\r
4325 uint numTables = 0;
\r
4326 ArrayList[] metaDataTables = new ArrayList[numMetaDataTables];
\r
4327 ArrayList byteCodes = new ArrayList();
\r
4328 uint codeSize = 0, codeStart, byteCodePadding = 0, metaDataSize = 0;
\r
4329 ulong valid = 0, /*sorted = 0x000002003301FA00;*/ sorted = 0;
\r
4330 bool[] largeIx = new bool[numMetaDataTables];
\r
4331 bool[] lgeCIx = new bool[(int)CIx.MaxCIx];
\r
4332 bool largeStrings = false, largeUS = false, largeGUID = false, largeBlob = false;
\r
4333 private FileImage file;
\r
4334 private byte heapSizes = 0;
\r
4335 MetaDataElement entryPoint;
\r
4336 BinaryWriter output;
\r
4337 public MSCorLib mscorlib;
\r
4338 private TypeSpec[] systemTypeSpecs = new TypeSpec[PrimitiveType.NumSystemTypes];
\r
4341 internal MetaData(FileImage file) {
\r
4342 // tilde = new MetaDataStream(tildeName,false,0);
\r
4344 strings = new MetaDataStream(stringsName,new UTF8Encoding(),true);
\r
4345 us = new MetaDataStream(usName,new UnicodeEncoding(),true);
\r
4346 guid = new MetaDataStream(guidName,false);
\r
4347 blob = new MetaDataStream(blobName,true);
\r
4348 streams[1] = strings;
\r
4350 streams[3] = guid;
\r
4351 streams[4] = blob;
\r
4352 for (int i=0; i < numMetaDataTables; i++) {
\r
4353 largeIx[i] = false;
\r
4355 for (int i=0; i < lgeCIx.Length; i++) {
\r
4356 lgeCIx[i] = false;
\r
4358 mscorlib = new MSCorLib(this);
\r
4361 internal TypeSpec GetPrimitiveTypeSpec(int ix) {
\r
4362 return systemTypeSpecs[ix];
\r
4365 internal void SetPrimitiveTypeSpec(int ix, TypeSpec typeSpec) {
\r
4366 systemTypeSpecs[ix] = typeSpec;
\r
4369 internal uint Size() {
\r
4370 //Console.WriteLine("metaData size = " + metaDataSize);
\r
4371 return metaDataSize;
\r
4374 internal void StreamSize(byte mask) {
\r
4375 heapSizes |= mask;
\r
4378 internal uint AddToUSHeap(string str) {
\r
4379 if (str == null) return 0;
\r
4380 return us.Add(str,true);
\r
4383 internal uint AddToStringsHeap(string str) {
\r
4384 if ((str == null) || (str.CompareTo("") == 0)) return 0;
\r
4385 return strings.Add(str,false);
\r
4388 internal uint AddToGUIDHeap(Guid guidNum) {
\r
4389 return guid.Add(guidNum);
\r
4392 internal uint AddToBlobHeap(byte[] blobBytes) {
\r
4393 if (blobBytes == null) return 0;
\r
4394 return blob.Add(blobBytes);
\r
4397 internal uint AddToBlobHeap(byte val) {
\r
4398 return blob.Add(val);
\r
4401 internal uint AddToBlobHeap(sbyte val) {
\r
4402 return blob.Add(val);
\r
4405 internal uint AddToBlobHeap(ushort val) {
\r
4406 return blob.Add(val);
\r
4409 internal uint AddToBlobHeap(short val) {
\r
4410 return blob.Add(val);
\r
4413 internal uint AddToBlobHeap(uint val) {
\r
4414 return blob.Add(val);
\r
4417 internal uint AddToBlobHeap(int val) {
\r
4418 return blob.Add(val);
\r
4421 internal uint AddToBlobHeap(ulong val) {
\r
4422 return blob.Add(val);
\r
4425 internal uint AddToBlobHeap(long val) {
\r
4426 return blob.Add(val);
\r
4429 internal uint AddToBlobHeap(float val) {
\r
4430 return blob.Add(val);
\r
4433 internal uint AddToBlobHeap(double val) {
\r
4434 return blob.Add(val);
\r
4437 internal uint AddToBlobHeap(string val) {
\r
4438 return blob.Add(val,true);
\r
4442 private ArrayList GetTable(MDTable tableIx) {
\r
4443 int tabIx = (int)tableIx;
\r
4444 if (metaDataTables[tabIx] == null) {
\r
4445 metaDataTables[tabIx] = new ArrayList();
\r
4446 valid |= ((ulong)0x1 << tabIx);
\r
4447 // Console.WriteLine("after creating table " + tableIx + "(" + tabIx + ") valid = " + valid);
\r
4450 return metaDataTables[tabIx];
\r
4453 internal void AddToTable(MDTable tableIx, MetaDataElement elem) {
\r
4454 if (elem.Row > 0) {
\r
4455 // Console.Out.WriteLine("ERROR - element already in table " + tableIx);
\r
4458 // updates Row field of the element
\r
4459 // Console.WriteLine("Adding element to table " + (uint)tableIx);
\r
4460 ArrayList table = GetTable(tableIx);
\r
4461 elem.Row = (uint)table.Count + 1;
\r
4465 internal uint TableIndex(MDTable tableIx) {
\r
4466 if (metaDataTables[(int)tableIx] == null) return 1;
\r
4467 return (uint)metaDataTables[(int)tableIx].Count+1;
\r
4470 internal uint AddCode(CILInstructions byteCode) {
\r
4471 byteCodes.Add(byteCode);
\r
4472 uint offset = codeSize + codeStart;
\r
4473 codeSize += byteCode.GetCodeSize();
\r
4477 internal void SetEntryPoint(MetaDataElement ep) {
\r
4481 internal void AddData(DataConstant cVal) {
\r
4482 file.AddInitData(cVal);
\r
4485 internal static void CompressNum(uint val, MemoryStream sig) {
\r
4487 sig.WriteByte((byte)val);
\r
4488 } else if (val < 0x3FFF) {
\r
4489 byte b1 = (byte)((val >> 8) | 0x80);
\r
4490 byte b2 = (byte)(val & FileImage.iByteMask[0]);
\r
4491 sig.WriteByte(b1);
\r
4492 sig.WriteByte(b2);
\r
4494 byte b1 = (byte)((val >> 24) | 0xC0);
\r
4495 byte b2 = (byte)((val & FileImage.iByteMask[2]) >> 16);
\r
4496 byte b3 = (byte)((val & FileImage.iByteMask[1]) >> 8);;
\r
4497 byte b4 = (byte)(val & FileImage.iByteMask[0]);
\r
4498 sig.WriteByte(b1);
\r
4499 sig.WriteByte(b2);
\r
4500 sig.WriteByte(b3);
\r
4501 sig.WriteByte(b4);
\r
4505 internal uint CodeSize() {
\r
4506 return codeSize + byteCodePadding;
\r
4509 internal uint StringsIndexSize() {
\r
4510 if (largeStrings) return 4;
\r
4514 internal uint GUIDIndexSize() {
\r
4515 if (largeGUID) return 4;
\r
4519 internal uint USIndexSize() {
\r
4520 if (largeUS) return 4;
\r
4524 internal uint BlobIndexSize() {
\r
4525 if (largeBlob) return 4;
\r
4529 internal uint CodedIndexSize(CIx code) {
\r
4530 if (lgeCIx[(uint)code]) return 4;
\r
4534 internal uint TableIndexSize(MDTable tabIx) {
\r
4535 if (largeIx[(uint)tabIx]) return 4;
\r
4539 private void SetIndexSizes() {
\r
4540 for (int i=0; i < numMetaDataTables; i++) {
\r
4541 if (metaDataTables[i] != null) {
\r
4542 uint count = (uint)metaDataTables[i].Count;
\r
4543 if (count > maxSmlIxSize) {
\r
4544 largeIx[i] = true;
\r
4545 MDTable tabIx = (MDTable)i;
\r
4546 if (count > max5BitSmlIx) {
\r
4547 lgeCIx[(int)CIx.HasCustomAttr] = true;
\r
4549 if (count > max3BitSmlIx) {
\r
4550 if ((tabIx == MDTable.TypeRef) || (tabIx == MDTable.ModuleRef) || (tabIx == MDTable.Method) || (tabIx == MDTable.TypeSpec))
\r
4551 lgeCIx[(int)CIx.CustomAttributeType] = true;
\r
4552 if ((tabIx == MDTable.Method) || (tabIx == MDTable.MemberRef))
\r
4553 lgeCIx[(int)CIx.MemberRefParent] = true;
\r
4554 } else if (count > max2BitSmlIx) {
\r
4555 if ((tabIx == MDTable.Field) || (tabIx == MDTable.Param) || (tabIx == MDTable.Property))
\r
4556 lgeCIx[(int)CIx.HasConst] = true;
\r
4557 if ((tabIx == MDTable.TypeDef) || (tabIx == MDTable.TypeRef) || (tabIx == MDTable.TypeSpec))
\r
4558 lgeCIx[(int)CIx.TypeDefOrRef] = true;
\r
4559 if ((tabIx == MDTable.TypeDef) || (tabIx == MDTable.Method) || (tabIx == MDTable.Assembly))
\r
4560 lgeCIx[(int)CIx.HasDeclSecurity] = true;
\r
4561 if ((tabIx == MDTable.File) || (tabIx == MDTable.AssemblyRef) || (tabIx == MDTable.ExportedType))
\r
4562 lgeCIx[(int)CIx.Implementation] = true;
\r
4563 if ((tabIx == MDTable.Module) || (tabIx == MDTable.ModuleRef) || (tabIx == MDTable.AssemblyRef) || (tabIx == MDTable.TypeRef))
\r
4564 lgeCIx[(int)CIx.ResolutionScope] = true;
\r
4565 } else if (count > max1BitSmlIx) {
\r
4566 if ((tabIx == MDTable.Field) || (tabIx == MDTable.Param))
\r
4567 lgeCIx[(int)CIx.HasFieldMarshal] = true;
\r
4568 if ((tabIx == MDTable.Event) || (tabIx == MDTable.Property))
\r
4569 lgeCIx[(int)CIx.HasSemantics] = true;
\r
4570 if ((tabIx == MDTable.Method) || (tabIx == MDTable.MemberRef))
\r
4571 lgeCIx[(int)CIx.MethodDefOrRef] = true;
\r
4572 if ((tabIx == MDTable.Field) || (tabIx == MDTable.Method))
\r
4573 lgeCIx[(int)CIx.MemberForwarded] = true;
\r
4574 if ((tabIx == MDTable.TypeDef) || (tabIx == MDTable.Method))
\r
4575 lgeCIx[(int)CIx.TypeOrMethodDef] = true;
\r
4580 if (strings.LargeIx()) {
\r
4581 largeStrings = true;
\r
4582 heapSizes |= StringsHeapMask;
\r
4584 if (guid.LargeIx()) {
\r
4586 heapSizes |= GUIDHeapMask;
\r
4588 if (blob.LargeIx()) {
\r
4590 heapSizes |= BlobHeapMask;
\r
4592 largeUS = us.LargeIx();
\r
4595 private void SetStreamOffsets() {
\r
4596 uint sizeOfHeaders = StreamHeaderSize + (uint)tildeName.Length;
\r
4597 for (int i=1; i < numStreams; i++) {
\r
4598 sizeOfHeaders += streams[i].headerSize();
\r
4600 metaDataSize = MetaDataHeaderSize + sizeOfHeaders;
\r
4601 // Console.WriteLine("Size of meta data headers (tildeStart) = " + metaDataSize);
\r
4602 tildeStart = metaDataSize;
\r
4603 metaDataSize += tildeTide + tildePadding;
\r
4604 //Console.WriteLine(tildeName + " - size = " + (tildeTide + tildePadding));
\r
4605 for (int i=1; i < numStreams; i++) {
\r
4606 // Console.WriteLine("Stream " + i + " starts at " + metaDataSize);
\r
4607 streams[i].Start = metaDataSize;
\r
4608 metaDataSize += streams[i].Size();
\r
4609 streams[i].WriteDetails();
\r
4613 internal void CalcTildeStreamSize() {
\r
4614 //tilde.SetIndexSizes(strings.LargeIx(),us.LargeIx(),guid.LargeIx(),blob.LargeIx());
\r
4615 tildeTide = TildeHeaderSize;
\r
4616 tildeTide += 4 * numTables;
\r
4617 //Console.WriteLine("Tilde header + sizes = " + tildeTide);
\r
4618 for (int i=0; i < numMetaDataTables; i++) {
\r
4619 if (metaDataTables[i] != null) {
\r
4620 ArrayList table = metaDataTables[i];
\r
4621 // Console.WriteLine("Meta data table " + i + " at offset " + tildeTide);
\r
4622 tildeTide += (uint)table.Count * ((MetaDataElement)table[0]).Size(this);
\r
4623 // Console.WriteLine("Metadata table " + i + " has size " + table.Count);
\r
4624 // Console.WriteLine("tildeTide = " + tildeTide);
\r
4627 if ((tildeTide % 4) != 0) tildePadding = 4 - (tildeTide % 4);
\r
4628 //Console.WriteLine("tildePadding = " + tildePadding);
\r
4631 internal void WriteTildeStream(FileImage output) {
\r
4632 long startTilde = output.Seek(0,SeekOrigin.Current);
\r
4633 output.Write((uint)0); // Reserved
\r
4634 output.Write((byte)1); // MajorVersion
\r
4635 output.Write((byte)0); // MinorVersion
\r
4636 output.Write(heapSizes);
\r
4637 output.Write((byte)1); // Reserved
\r
4638 output.Write(valid);
\r
4639 output.Write(sorted);
\r
4640 for (int i=0; i < numMetaDataTables; i++) {
\r
4641 if (metaDataTables[i] != null) {
\r
4642 uint count = (uint)metaDataTables[i].Count;
\r
4643 output.Write(count);
\r
4646 long tabStart = output.Seek(0,SeekOrigin.Current);
\r
4647 // Console.WriteLine("Starting metaData tables at " + tabStart);
\r
4648 for (int i=0; i < numMetaDataTables; i++) {
\r
4649 if (metaDataTables[i] != null) {
\r
4650 // Console.WriteLine("Starting metaData table " + i + " at " + (output.Seek(0,SeekOrigin.Current) - startTilde));
\r
4651 ArrayList table = metaDataTables[i];
\r
4652 for (int j=0; j < table.Count; j++) {
\r
4653 ((MetaDataElement)table[j]).Write(output);
\r
4657 // Console.WriteLine("Writing padding at " + output.Seek(0,SeekOrigin.Current));
\r
4658 for (int i=0; i < tildePadding; i++) output.Write((byte)0);
\r
4661 private void BuildTable(ArrayList table) {
\r
4662 if (table == null) return;
\r
4663 for (int j=0; j < table.Count; j++) {
\r
4664 ((MetaDataElement)table[j]).BuildTables(this);
\r
4668 internal void BuildMetaData(uint codeStartOffset) {
\r
4669 codeStart = codeStartOffset;
\r
4670 BuildTable(metaDataTables[(int)MDTable.TypeDef]);
\r
4671 BuildTable(metaDataTables[(int)MDTable.MemberRef]);
\r
4672 BuildTable(metaDataTables[(int)MDTable.GenericParam]);
\r
4673 BuildTable(metaDataTables[(int)MDTable.GenericParamConstraint]);
\r
4674 BuildTable(metaDataTables[(int)MDTable.CustomAttribute]);
\r
4675 /* for (int i=0; i < metaDataTables.Length; i++) {
\r
4676 ArrayList table = metaDataTables[i];
\r
4677 if (table != null) {
\r
4678 for (int j=0; j < table.Count; j++) {
\r
4679 ((MetaDataElement)table[j]).BuildTables(this);
\r
4685 for (int i=1; i < numStreams; i++) {
\r
4686 streams[i].EndStream();
\r
4688 CalcTildeStreamSize();
\r
4689 SetStreamOffsets();
\r
4690 byteCodePadding = NumToAlign(codeSize,4);
\r
4691 if (entryPoint != null) file.SetEntryPoint(entryPoint.Token());
\r
4694 internal void WriteByteCodes(FileImage output) {
\r
4695 for (int i=0; i < byteCodes.Count; i++) {
\r
4696 ((CILInstructions)byteCodes[i]).Write(output);
\r
4698 for (int i=0; i < byteCodePadding; i++) {
\r
4699 output.Write((byte)0);
\r
4703 internal void WriteMetaData(FileImage output) {
\r
4704 this.output = output;
\r
4705 mdStart = output.Seek(0,SeekOrigin.Current);
\r
4706 // Console.WriteLine("Writing metaData at " + Hex.Long(mdStart));
\r
4707 output.Write(MetaDataSignature);
\r
4708 output.Write((short)1); // Major Version
\r
4709 output.Write((short)1); // Minor Version ECMA = 0, PEFiles = 1
\r
4710 output.Write(0); // Reserved
\r
4711 output.Write(version.Length);
\r
4712 output.Write(version.ToCharArray()); // version string is already zero padded
\r
4713 output.Write((short)0);
\r
4714 output.Write((ushort)numStreams);
\r
4715 // write tilde header
\r
4716 output.Write(tildeStart);
\r
4717 output.Write(tildeTide + tildePadding);
\r
4718 output.Write(tildeName);
\r
4719 for (int i=1; i < numStreams; i++) streams[i].WriteHeader(output);
\r
4720 // Console.WriteLine("Writing tilde stream at " + output.Seek(0,SeekOrigin.Current) + " = " + tildeStart);
\r
4721 WriteTildeStream(output);
\r
4722 for (int i=1; i < numStreams; i++) streams[i].Write(output);
\r
4723 // Console.WriteLine("Finished Writing metaData at " + output.Seek(0,SeekOrigin.Current));
\r
4726 internal bool LargeStringsIndex() { return strings.LargeIx(); }
\r
4727 internal bool LargeGUIDIndex() { return guid.LargeIx(); }
\r
4728 internal bool LargeUSIndex() { return us.LargeIx(); }
\r
4729 internal bool LargeBlobIndex() { return blob.LargeIx(); }
\r
4731 internal bool LargeIx(MDTable tabIx) { return largeIx[(uint)tabIx]; }
\r
4734 private uint NumToAlign(uint val, uint alignVal) {
\r
4735 if ((val % alignVal) == 0) return 0;
\r
4736 return alignVal - (val % alignVal);
\r
4739 internal void WriteCodedIndex(CIx code, MetaDataElement elem, FileImage output) {
\r
4741 if (elem != null) {
\r
4742 ix = (elem.Row << CIxShiftMap[(uint)code]) | elem.GetCodedIx(code);
\r
4743 // Console.WriteLine("coded index = " + ix + " row = " + elem.Row);
\r
4745 // Console.WriteLine("elem for coded index is null");
\r
4747 if (lgeCIx[(uint)code])
\r
4750 output.Write((ushort)ix);
\r
4754 /**************************************************************************/
\r
4756 /// Base class for all Meta Data table elements
\r
4759 public abstract class MetaDataElement
\r
4762 protected ArrayList customAttributes;
\r
4763 private uint row = 0;
\r
4764 protected bool done = false;
\r
4765 protected MDTable tabIx;
\r
4767 internal MetaDataElement() { }
\r
4774 if (row == 0) row = value;
\r
4778 internal virtual uint GetCodedIx(CIx code) { return 0; }
\r
4781 /// Add a custom attribute to this item
\r
4783 /// <param name="ctorMeth">the constructor method for this attribute</param>
\r
4784 /// <param name="val">the byte value of the parameters</param>
\r
4785 public void AddCustomAttribute(Method ctorMeth, byte[] val) {
\r
4786 if (customAttributes == null) {
\r
4787 customAttributes = new ArrayList();
\r
4789 customAttributes.Add(new CustomAttribute(this,ctorMeth,val));
\r
4793 /// Add a custom attribute to this item
\r
4795 /// <param name="ctorMeth">the constructor method for this attribute</param>
\r
4796 /// <param name="val">the constant values of the parameters</param>
\r
4797 public void AddCustomAttribute(Method ctorMeth, Constant[] cVals) {
\r
4798 if (customAttributes == null) {
\r
4799 customAttributes = new ArrayList();
\r
4801 // customAttributes.Add(new CustomAttribute(this,ctorMeth,cVals));
\r
4804 internal void DoCustomAttributes(MetaData md) {
\r
4805 if (customAttributes != null) {
\r
4806 for (int i=0; i < customAttributes.Count; i++) {
\r
4807 CustomAttribute ca = (CustomAttribute)customAttributes[i];
\r
4808 ca.BuildTables(md);
\r
4813 internal uint Token() {
\r
4814 return (((uint)tabIx << 24) | row);
\r
4817 internal virtual void BuildTables(MetaData md) {
\r
4821 internal virtual uint Size(MetaData md) {
\r
4825 internal virtual void Write(FileImage output) { }
\r
4828 /**************************************************************************/
\r
4830 /// Stream in the Meta Data (#Strings, #US, #Blob and #GUID)
\r
4833 internal class MetaDataStream : BinaryWriter
\r
4835 private static readonly uint StreamHeaderSize = 8;
\r
4836 private static uint maxSmlIxSize = 0xFFFF;
\r
4838 private uint start = 0;
\r
4839 uint size = 0, tide = 1;
\r
4840 bool largeIx = false;
\r
4841 uint sizeOfHeader;
\r
4843 Hashtable htable = new Hashtable();
\r
4845 internal MetaDataStream(char[] name, bool addInitByte) : base(new MemoryStream()) {
\r
4846 if (addInitByte) { Write((byte)0); size = 1; }
\r
4848 sizeOfHeader = StreamHeaderSize + (uint)name.Length;
\r
4851 internal MetaDataStream(char[] name, System.Text.Encoding enc, bool addInitByte) : base(new MemoryStream(),enc) {
\r
4852 if (addInitByte) { Write((byte)0); size = 1; }
\r
4854 sizeOfHeader = StreamHeaderSize + (uint)name.Length;
\r
4857 public uint Start {
\r
4866 internal uint headerSize() {
\r
4867 // Console.WriteLine(name + " stream has headersize of " + sizeOfHeader);
\r
4868 return sizeOfHeader;
\r
4871 internal void SetSize(uint siz) {
\r
4875 internal uint Size() {
\r
4879 internal bool LargeIx() {
\r
4883 internal void WriteDetails() {
\r
4884 // Console.WriteLine(name + " - size = " + size);
\r
4887 internal uint Add(string str, bool prependSize) {
\r
4888 Object val = htable[str];
\r
4890 if (val == null) {
\r
4892 htable[str] = index;
\r
4893 char[] arr = str.ToCharArray();
\r
4894 if (prependSize) CompressNum((uint)arr.Length*2+1);
\r
4897 size = (uint)Seek(0,SeekOrigin.Current);
\r
4899 index = (uint)val;
\r
4904 internal uint Add(Guid guid) {
\r
4905 Write(guid.ToByteArray());
\r
4906 size =(uint)Seek(0,SeekOrigin.Current);
\r
4910 internal uint Add(byte[] blob) {
\r
4912 CompressNum((uint)blob.Length);
\r
4914 size = (uint)Seek(0,SeekOrigin.Current);
\r
4918 internal uint Add(byte val) {
\r
4921 size = (uint)Seek(0,SeekOrigin.Current);
\r
4925 internal uint Add(sbyte val) {
\r
4928 size = (uint)Seek(0,SeekOrigin.Current);
\r
4932 internal uint Add(ushort val) {
\r
4935 size = (uint)Seek(0,SeekOrigin.Current);
\r
4939 internal uint Add(short val) {
\r
4942 size = (uint)Seek(0,SeekOrigin.Current);
\r
4946 internal uint Add(uint val) {
\r
4949 size = (uint)Seek(0,SeekOrigin.Current);
\r
4953 internal uint Add(int val) {
\r
4956 size = (uint)Seek(0,SeekOrigin.Current);
\r
4960 internal uint Add(ulong val) {
\r
4963 size = (uint)Seek(0,SeekOrigin.Current);
\r
4967 internal uint Add(long val) {
\r
4970 size = (uint)Seek(0,SeekOrigin.Current);
\r
4974 internal uint Add(float val) {
\r
4977 size = (uint)Seek(0,SeekOrigin.Current);
\r
4981 internal uint Add(double val) {
\r
4984 size = (uint)Seek(0,SeekOrigin.Current);
\r
4988 private void CompressNum(uint val) {
\r
4991 } else if (val < 0x3FFF) {
\r
4992 byte b1 = (byte)((val >> 8) | 0x80);
\r
4993 byte b2 = (byte)(val & FileImage.iByteMask[0]);
\r
4997 byte b1 = (byte)((val >> 24) | 0xC0);
\r
4998 byte b2 = (byte)((val & FileImage.iByteMask[2]) >> 16);
\r
4999 byte b3 = (byte)((val & FileImage.iByteMask[1]) >> 8);;
\r
5000 byte b4 = (byte)(val & FileImage.iByteMask[0]);
\r
5008 private void QuadAlign() {
\r
5009 if ((size % 4) != 0) {
\r
5010 uint pad = 4 - (size % 4);
\r
5012 for (int i=0; i < pad; i++) {
\r
5018 internal void EndStream() {
\r
5020 if (size > maxSmlIxSize) {
\r
5025 internal void WriteHeader(BinaryWriter output) {
\r
5026 output.Write(start);
\r
5027 output.Write(size);
\r
5028 output.Write(name);
\r
5031 internal virtual void Write(BinaryWriter output) {
\r
5032 // Console.WriteLine("Writing " + name + " stream at " + output.Seek(0,SeekOrigin.Current) + " = " + start);
\r
5033 MemoryStream str = (MemoryStream)BaseStream;
\r
5034 output.Write(str.ToArray());
\r
5038 /**************************************************************************/
\r
5040 /// Base class for Method Descriptors
\r
5043 public abstract class Method : Member
\r
5045 protected CallConv callConv = CallConv.Default;
\r
5046 protected Type retType;
\r
5048 internal Method(string methName, Type rType) : base(methName)
\r
5054 /// Add calling conventions to this method descriptor
\r
5056 /// <param name="cconv"></param>
\r
5057 public void AddCallConv(CallConv cconv) {
\r
5058 callConv |= cconv;
\r
5061 internal abstract void TypeSig(MemoryStream sig);
\r
5063 internal uint GetSigIx(MetaData md) {
\r
5064 MemoryStream sig = new MemoryStream();
\r
5066 return md.AddToBlobHeap(sig.ToArray());
\r
5069 internal Type GetRetType() {
\r
5074 /**************************************************************************/
\r
5076 /// Descriptor for a method defined in THIS assembly/module
\r
5080 public class MethodDef : Method
\r
5082 private static readonly ushort PInvokeImpl = 0x2000;
\r
5083 //private static readonly uint UnmanagedExport = 0x0008;
\r
5084 // private static readonly byte LocalSigByte = 0x7;
\r
5085 uint parIx = 0, textOffset = 0;
\r
5087 MetaData metaData;
\r
5088 CILInstructions code;
\r
5089 ArrayList securityActions = new ArrayList();
\r
5093 ushort methFlags = 0, implFlags = 0;
\r
5094 int maxStack = 0, numPars = 0;
\r
5095 bool entryPoint = false;
\r
5096 LocalSig localSig;
\r
5097 ArrayList varArgSigList;
\r
5098 ImplMap pinvokeImpl;
\r
5101 internal MethodDef(MetaData md, string name, Type retType, Param[] pars) : base(name,retType) {
\r
5104 if (parList != null) numPars = parList.Length;
\r
5105 tabIx = MDTable.Method;
\r
5108 internal MethodDef(MetaData md, MethAttr mAttrSet, ImplAttr iAttrSet, string name, Type retType, Param[] pars) : base(name,retType) {
\r
5111 if (parList != null) numPars = parList.Length;
\r
5112 // Console.WriteLine("Creating method " + name + " with " + numPars + " parameters");
\r
5113 methFlags = (ushort)mAttrSet;
\r
5114 implFlags = (ushort)iAttrSet;
\r
5115 tabIx = MDTable.Method;
\r
5118 internal Param[] GetPars() {
\r
5123 /// Add some attributes to this method descriptor
\r
5125 /// <param name="ma">the attributes to be added</param>
\r
5126 public void AddMethAttribute(MethAttr ma) {
\r
5127 methFlags |= (ushort)ma;
\r
5131 /// Add some implementation attributes to this method descriptor
\r
5133 /// <param name="ia">the attributes to be added</param>
\r
5134 public void AddImplAttribute(ImplAttr ia) {
\r
5135 implFlags |= (ushort)ia;
\r
5138 public void AddPInvokeInfo(ModuleRef scope, string methName,
\r
5139 PInvokeAttr callAttr) {
\r
5140 pinvokeImpl = new ImplMap((ushort)callAttr,this,methName,scope);
\r
5141 methFlags |= PInvokeImpl;
\r
5145 /// Add a named generic type parameter
\r
5147 public GenericParameter AddGenericParameter (short index, string name) {
\r
5148 GenericParameter gp = new GenericParameter (this, metaData, index, name);
5149 metaData.AddToTable (MDTable.GenericParam, gp);
\r
5154 /// Set the maximum stack height for this method
\r
5156 /// <param name="maxStack">the maximum height of the stack</param>
\r
5157 public void SetMaxStack(int maxStack) {
\r
5158 this.maxStack = maxStack;
\r
5162 /// Add local variables to this method
\r
5164 /// <param name="locals">the locals to be added</param>
\r
5165 /// <param name="initLocals">are locals initialised to default values</param>
\r
5166 public void AddLocals(Local[] locals, bool initLocals) {
\r
5167 this.locals = locals;
\r
5168 this.initLocals = initLocals;
\r
5172 /// Mark this method as having an entry point
\r
5174 public void DeclareEntryPoint() {
\r
5175 entryPoint = true;
\r
5179 /// Create a code buffer for this method to add the IL instructions to
\r
5181 /// <returns>a buffer for this method's IL instructions</returns>
\r
5182 public CILInstructions CreateCodeBuffer() {
\r
5183 code = new CILInstructions(metaData);
\r
5188 /// Make a method reference descriptor for this method to be used
\r
5189 /// as a callsite signature for this vararg method
\r
5191 /// <param name="optPars">the optional pars for the vararg method call</param>
\r
5192 /// <returns></returns>
\r
5193 public MethodRef MakeVarArgSignature(Type[] optPars) {
\r
5194 Type[] pars = new Type[numPars];
\r
5195 MethodRef varArgSig;
\r
5196 for (int i=0; i < numPars; i++) {
\r
5197 pars[i] = parList[i].GetParType();
\r
5199 varArgSig = new MethodRef(this,name,retType,pars,true,optPars);
\r
5201 if (varArgSigList == null)
\r
5202 varArgSigList = new ArrayList ();
\r
5203 varArgSigList.Add (varArgSig);
\r
5207 internal sealed override void TypeSig(MemoryStream sig) {
\r
5208 sig.WriteByte((byte)callConv);
\r
5209 MetaData.CompressNum((uint)numPars,sig);
\r
5210 retType.TypeSig(sig);
\r
5211 for (ushort i=0; i < numPars; i++) {
\r
5212 parList[i].seqNo = (ushort)(i+1);
\r
5213 parList[i].TypeSig(sig);
\r
5217 internal sealed override void BuildTables(MetaData md) {
\r
5219 if (pinvokeImpl != null) {
\r
5220 md.AddToTable(MDTable.ImplMap,pinvokeImpl);
\r
5221 pinvokeImpl.BuildTables(md);
\r
5223 if (entryPoint) md.SetEntryPoint(this);
\r
5224 uint locToken = 0;
\r
5225 if (locals != null) {
\r
5226 localSig = new LocalSig(locals);
\r
5227 md.AddToTable(MDTable.StandAloneSig,localSig);
\r
5228 localSig.BuildTables(md);
\r
5229 locToken = localSig.Token();
\r
5231 if (code != null) {
\r
5232 code.CheckCode(locToken,initLocals,maxStack);
\r
5233 textOffset = md.AddCode(code);
\r
5235 nameIx = md.AddToStringsHeap(name);
\r
5236 sigIx = GetSigIx(md);
\r
5237 parIx = md.TableIndex(MDTable.Param);
\r
5238 for (int i=0; i < numPars; i++) {
\r
5239 md.AddToTable(MDTable.Param,parList[i]);
\r
5240 parList[i].BuildTables(md);
\r
5242 if (varArgSigList != null) {
\r
5243 foreach (MethodRef varArgSig in varArgSigList) {
\r
5244 md.AddToTable(MDTable.MemberRef,varArgSig);
\r
5245 varArgSig.BuildTables(md);
\r
5248 DoCustomAttributes (md);
\r
5249 // Console.WriteLine("method has " + numPars + " parameters");
\r
5253 internal sealed override uint Size(MetaData md) {
\r
5254 return 8 + md.StringsIndexSize() + md.BlobIndexSize() + md.TableIndexSize(MDTable.Param);
\r
5257 internal sealed override void Write(FileImage output) {
\r
5258 if (ZeroRva ()) output.Write(0);
\r
5259 else output.WriteCodeRVA(textOffset);
\r
5260 output.Write(implFlags);
\r
5261 output.Write(methFlags);
\r
5262 output.StringsIndex(nameIx);
\r
5263 output.BlobIndex(sigIx);
\r
5264 output.WriteIndex(MDTable.Param,parIx);
\r
5267 internal bool ZeroRva () {
5268 return (((methFlags & (ushort)MethAttr.Abstract) != 0) ||
5269 (pinvokeImpl != null)); // TODO: Not entirely true but works for now
5272 internal sealed override uint GetCodedIx(CIx code) {
\r
5274 case (CIx.HasCustomAttr) : return 0;
\r
5275 case (CIx.HasDeclSecurity) : return 1;
\r
5276 case (CIx.MemberRefParent) : return 3;
\r
5277 case (CIx.MethodDefOrRef) : return 0;
\r
5278 case (CIx.MemberForwarded) : return 1;
\r
5279 case (CIx.CustomAttributeType) : return 2;
\r
5280 case (CIx.TypeOrMethodDef) : return 1;
\r
5286 /**************************************************************************/
\r
5288 /// Descriptor for an overriding method (.override)
\r
5290 public class MethodImpl : MetaDataElement
\r
5293 Method header, body;
\r
5295 internal MethodImpl(ClassDef par, Method decl, Method bod) {
\r
5299 tabIx = MDTable.MethodImpl;
\r
5302 internal sealed override uint Size(MetaData md) {
\r
5303 return md.TableIndexSize(MDTable.TypeDef) + 2 * md.CodedIndexSize(CIx.MethodDefOrRef);
\r
5306 internal sealed override void Write(FileImage output) {
\r
5307 output.WriteIndex(MDTable.TypeDef,parent.Row);
\r
5308 output.WriteCodedIndex(CIx.MethodDefOrRef,body);
\r
5309 output.WriteCodedIndex(CIx.MethodDefOrRef,header);
\r
5313 /**************************************************************************/
\r
5315 /// Descriptor for a method defined in another assembly/module
\r
5317 public class MethodRef : Method
\r
5319 private static readonly byte Sentinel = 0x41;
\r
5320 Type[] parList, optParList;
\r
5321 MetaDataElement parent;
\r
5322 uint numPars = 0, numOptPars = 0;
\r
5324 internal MethodRef(MetaDataElement paren, string name, Type retType,
\r
5325 Type[] pars, bool varArgMeth, Type[] optPars) : base(name,retType) {
\r
5328 if (parList != null) numPars = (uint)parList.Length;
\r
5330 optParList = optPars;
\r
5331 if (optParList != null) numOptPars = (uint)optParList.Length;
\r
5332 callConv = CallConv.Vararg;
\r
5336 internal sealed override void TypeSig(MemoryStream sig) {
\r
5337 sig.WriteByte((byte)callConv);
\r
5338 MetaData.CompressNum(numPars+numOptPars,sig);
\r
5339 retType.TypeSig(sig);
\r
5340 for (int i=0; i < numPars; i++) {
\r
5341 parList[i].TypeSig(sig);
\r
5343 if (numOptPars > 0) {
\r
5344 sig.WriteByte(Sentinel);
\r
5345 for (int i=0; i < numOptPars; i++) {
\r
5346 optParList[i].TypeSig(sig);
\r
5351 internal sealed override void BuildTables(MetaData md) {
\r
5353 nameIx = md.AddToStringsHeap(name);
\r
5354 sigIx = GetSigIx(md);
\r
5358 internal sealed override uint Size(MetaData md) {
\r
5359 return md.CodedIndexSize(CIx.MemberRefParent) + md.StringsIndexSize() + md.BlobIndexSize();
\r
5362 internal sealed override void Write(FileImage output) {
\r
5363 output.WriteCodedIndex(CIx.MemberRefParent,parent);
\r
5364 output.StringsIndex(nameIx);
\r
5365 output.BlobIndex(sigIx);
\r
5368 internal sealed override uint GetCodedIx(CIx code) {
\r
5370 case (CIx.HasCustomAttr) : return 6;
\r
5371 case (CIx.MethodDefOrRef) : return 1;
\r
5372 case (CIx.CustomAttributeType) : return 3;
\r
5378 /**************************************************************************/
\r
5380 /// Descriptor for Property and Event methods
\r
5382 public class MethodSemantics : MetaDataElement {
\r
5384 Feature.MethodType type;
\r
5386 Feature eventOrProp;
\r
5388 internal MethodSemantics(Feature.MethodType mType, MethodDef method, Feature feature) {
\r
5391 eventOrProp = feature;
\r
5392 tabIx = MDTable.MethodSemantics;
\r
5395 internal sealed override uint Size(MetaData md) {
\r
5396 return 2 + md.TableIndexSize(MDTable.Method) + md.CodedIndexSize(CIx.HasSemantics);
\r
5399 internal sealed override void Write(FileImage output) {
\r
5400 output.Write((ushort)type);
\r
5401 output.WriteIndex(MDTable.Method,meth.Row);
\r
5402 output.WriteCodedIndex(CIx.HasSemantics,eventOrProp);
\r
5406 /**************************************************************************/
\r
5408 /// Descriptor for a FunctionPointer type
\r
5411 public class MethPtrType : Type
\r
5413 // MethPtrType == FNPTR
\r
5418 /// Create a new function pointer type
\r
5420 /// <param name="meth">the function to be referenced</param>
\r
5421 public MethPtrType(Method meth) : base(0x1B)
\r
5424 tabIx = MDTable.TypeSpec;
\r
5427 internal sealed override void TypeSig(MemoryStream str) {
\r
5428 str.WriteByte(typeIndex);
\r
5429 method.TypeSig(str);
\r
5432 internal sealed override void BuildTables(MetaData md) {
\r
5434 MemoryStream sig = new MemoryStream();
\r
5436 sigIx = md.AddToBlobHeap(sig.ToArray());
\r
5440 internal sealed override uint Size(MetaData md) {
\r
5441 return md.BlobIndexSize();
\r
5444 internal sealed override void Write(FileImage output) {
\r
5445 output.BlobIndex(sigIx);
\r
5448 internal sealed override uint GetCodedIx(CIx code) { return 0x1B; }
\r
5451 /**************************************************************************/
\r
5453 /// Descriptor for THIS module
\r
5455 public class Module : ResolutionScope
\r
5460 internal Module(string name, MetaData md) : base(name,md) {
\r
5461 mvid = Guid.NewGuid();
\r
5462 mvidIx = md.AddToGUIDHeap(mvid);
\r
5463 tabIx = MDTable.Module;
\r
5466 internal sealed override uint Size(MetaData md) {
\r
5467 return 2 + md.StringsIndexSize() + 3 * md.GUIDIndexSize();
\r
5470 internal sealed override void Write(FileImage output) {
\r
5471 output.Write((short)0);
\r
5472 output.StringsIndex(nameIx);
\r
5473 output.GUIDIndex(mvidIx);
\r
5474 output.GUIDIndex(0);
\r
5475 output.GUIDIndex(0);
\r
5478 internal sealed override uint GetCodedIx(CIx code) {
\r
5480 case (CIx.HasCustomAttr) : return 7;
\r
5481 case (CIx.ResolutionScope) : return 0;
\r
5487 /**************************************************************************/
\r
5489 /// Descriptor for another module in THIS assembly
\r
5491 public class ModuleRef : ResolutionScope
\r
5494 internal ModuleRef(MetaData md, string name) : base(name,md) {
\r
5495 tabIx = MDTable.ModuleRef;
\r
5499 /// Add a class to this external module. This is a class declared in
\r
5500 /// another module of THIS assembly.
\r
5502 /// <param name="nsName">name space name</param>
\r
5503 /// <param name="name">class name</param>
\r
5504 /// <returns>a descriptor for this class in another module</returns>
\r
5505 public ClassRef AddClass(string nsName, string name, bool exportClass) {
\r
5506 ClassRef aClass = new ClassRef(nsName,name,metaData);
\r
5507 metaData.AddToTable(MDTable.TypeRef,aClass);
\r
5508 aClass.SetParent(this);
\r
5513 /// Make a file descriptor to correspond to this module. The file
\r
5514 /// descriptor will have the same name as the module descriptor
\r
5516 /// <param name="hashBytes">the hash of the file</param>
\r
5517 /// <param name="hasMetaData">the file contains metadata</param>
\r
5518 /// <param name="entryPoint">the program entry point is in this file</param>
\r
5519 /// <returns>a descriptor for the file which contains this module</returns>
\r
5520 public FileRef MakeFile(byte[] hashBytes, bool hasMetaData, bool entryPoint) {
\r
5521 FileRef file = new FileRef(nameIx,hashBytes,hasMetaData,entryPoint,metaData);
\r
5522 metaData.AddToTable(MDTable.File,file);
\r
5527 /// Add a value class to this module. This is a class declared in
\r
5528 /// another module of THIS assembly.
\r
5530 /// <param name="nsName">name space name</param>
\r
5531 /// <param name="name">class name</param>
\r
5532 /// <returns></returns>
\r
5533 public ClassRef AddValueClass(string nsName, string name) {
\r
5534 ClassRef aClass = new ClassRef(nsName,name,metaData);
\r
5535 metaData.AddToTable(MDTable.TypeRef,aClass);
\r
5536 aClass.SetParent(this);
\r
5537 aClass.MakeValueClass();
\r
5542 /// Add a class which is declared public in this external module of
\r
5543 /// THIS assembly. This class will be exported from this assembly.
\r
5544 /// The ilasm syntax for this is .extern class
\r
5546 /// <param name="attrSet">attributes of the class to be exported</param>
\r
5547 /// <param name="nsName">name space name</param>
\r
5548 /// <param name="name">external class name</param>
\r
5549 /// <param name="declFile">the file where the class is declared</param>
\r
5550 /// <param name="isValueClass">is this class a value type?</param>
\r
5551 /// <returns>a descriptor for this external class</returns>
\r
5552 public ExternClassRef AddExternClass(TypeAttr attrSet, string nsName,
\r
5553 string name, FileRef declFile,
\r
5554 bool isValueClass) {
\r
5555 ExternClassRef cRef = new ExternClassRef(attrSet,nsName,name,declFile,metaData);
\r
5556 metaData.AddToTable(MDTable.TypeRef,cRef);
\r
5557 cRef.SetParent(this);
\r
5558 if (isValueClass) cRef.MakeValueClass();
\r
5563 /// Add a "global" method in another module
\r
5565 /// <param name="name">method name</param>
\r
5566 /// <param name="retType">return type</param>
\r
5567 /// <param name="pars">method parameter types</param>
\r
5568 /// <returns>a descriptor for this method in anther module</returns>
\r
5569 public MethodRef AddMethod(string name, Type retType, Type[] pars) {
\r
5570 MethodRef meth = new MethodRef(this,name,retType,pars,false,null);
\r
5571 metaData.AddToTable(MDTable.MemberRef,meth);
\r
5576 /// Add a vararg method to this class
\r
5578 /// <param name="name">method name</param>
\r
5579 /// <param name="retType">return type</param>
\r
5580 /// <param name="pars">parameter types</param>
\r
5581 /// <param name="optPars">optional param types for this vararg method</param>
\r
5582 /// <returns>a descriptor for this method</returns>
\r
5583 public MethodRef AddVarArgMethod(string name, Type retType,
\r
5584 Type[] pars, Type[] optPars) {
\r
5585 MethodRef meth = new MethodRef(this,name,retType,pars,true,optPars);
\r
5586 metaData.AddToTable(MDTable.MemberRef,meth);
\r
5591 /// Add a field in another module
\r
5593 /// <param name="name">field name</param>
\r
5594 /// <param name="fType">field type</param>
\r
5595 /// <returns>a descriptor for this field in another module</returns>
\r
5596 public FieldRef AddField(string name, Type fType) {
\r
5597 FieldRef field = new FieldRef(this,name,fType);
\r
5598 metaData.AddToTable(MDTable.MemberRef,field);
\r
5602 internal sealed override uint Size(MetaData md) {
\r
5603 return md.StringsIndexSize();
\r
5606 internal sealed override void Write(FileImage output) {
\r
5607 output.StringsIndex(nameIx);
\r
5610 internal sealed override uint GetCodedIx(CIx code) {
\r
5612 case (CIx.HasCustomAttr) : return 12;
\r
5613 case (CIx.MemberRefParent) : return 2;
\r
5614 case (CIx.ResolutionScope) : return 1;
\r
5620 /**************************************************************************/
\r
5622 /// Descriptors for native types used for marshalling
\r
5624 public class NativeType {
\r
5625 public static readonly NativeType Void = new NativeType(0x01);
\r
5626 public static readonly NativeType Boolean = new NativeType(0x02);
\r
5627 public static readonly NativeType Int8 = new NativeType(0x03);
\r
5628 public static readonly NativeType UInt8 = new NativeType(0x04);
\r
5629 public static readonly NativeType Int16 = new NativeType(0x05);
\r
5630 public static readonly NativeType UInt16 = new NativeType(0x06);
\r
5631 public static readonly NativeType Int32 = new NativeType(0x07);
\r
5632 public static readonly NativeType UInt32 = new NativeType(0x08);
\r
5633 public static readonly NativeType Int64 = new NativeType(0x09);
\r
5634 public static readonly NativeType UInt64 = new NativeType(0x0A);
\r
5635 public static readonly NativeType Float32 = new NativeType(0x0B);
\r
5636 public static readonly NativeType Float64 = new NativeType(0x0C);
\r
5637 public static readonly NativeType Currency = new NativeType(0x0F);
\r
5638 public static readonly NativeType BStr = new NativeType(0x13);
\r
5639 public static readonly NativeType LPStr = new NativeType(0x14);
\r
5640 public static readonly NativeType LPWStr = new NativeType(0x15);
\r
5641 public static readonly NativeType LPTStr = new NativeType(0x16);
\r
5642 public static readonly NativeType FixedSysString = new NativeType(0x17);
\r
5643 public static readonly NativeType IUnknown = new NativeType(0x19);
\r
5644 public static readonly NativeType IDispatch = new NativeType(0x1A);
\r
5645 public static readonly NativeType Struct = new NativeType(0x1B);
\r
5646 public static readonly NativeType Interface = new NativeType(0x1C);
\r
5647 public static readonly NativeType Int = new NativeType(0x1F);
\r
5648 public static readonly NativeType UInt = new NativeType(0x20);
\r
5649 public static readonly NativeType ByValStr = new NativeType(0x22);
\r
5650 public static readonly NativeType AnsiBStr = new NativeType(0x23);
\r
5651 public static readonly NativeType TBstr = new NativeType(0x24);
\r
5652 public static readonly NativeType VariantBool = new NativeType(0x25);
\r
5653 public static readonly NativeType FuncPtr = new NativeType(0x26);
\r
5654 public static readonly NativeType AsAny = new NativeType(0x28);
\r
5656 protected byte typeIndex;
\r
5658 internal NativeType(byte tyIx) { typeIndex = tyIx; }
\r
5660 internal byte GetTypeIndex() { return typeIndex; }
\r
5662 internal virtual byte[] ToBlob() {
\r
5663 byte[] bytes = new byte[1];
\r
5664 bytes[0] = GetTypeIndex();
\r
5670 public class NativeArray : NativeType
\r
5672 NativeType elemType;
\r
5673 uint len = 0, parNum = 0;
\r
5676 public NativeArray(NativeType elemType) : base(0x2A) {
\r
5677 this.elemType = elemType;
\r
5680 public NativeArray(NativeType elemType, int len) : base(0x2A) {
\r
5681 this.elemType = elemType;
\r
5685 public NativeArray(NativeType elemType, int numElem, int parNumForLen) : base(0x2A) {
\r
5686 this.elemType = elemType;
\r
5687 len = (uint)numElem;
\r
5688 parNum = (uint)parNumForLen;
\r
5691 internal override byte[] ToBlob() {
\r
5692 MemoryStream str = new MemoryStream();
\r
5693 str.WriteByte(GetTypeIndex());
\r
5694 if (elemType == null) str.WriteByte(0x50); // no info (MAX)
\r
5695 else str.WriteByte(elemType.GetTypeIndex());
\r
5696 MetaData.CompressNum(parNum,str);
\r
5698 MetaData.CompressNum(len,str);
\r
5699 return str.ToArray();
\r
5704 public class SafeArray : NativeType
\r
5706 SafeArrayType elemType;
\r
5708 public SafeArray(SafeArrayType elemType) : base(0x1D) {
\r
5709 this.elemType = elemType;
\r
5712 internal override byte[] ToBlob() {
\r
5713 byte[] bytes = new byte[2];
\r
5714 bytes[0] = GetTypeIndex();
\r
5715 bytes[1] = (byte)elemType;
\r
5721 public class FixedArray : NativeType
\r
5723 NativeType elemType;
\r
5726 public FixedArray(NativeType elemType, int numElems) : base(0x1E) {
\r
5727 this.elemType = elemType;
\r
5728 numElem = (uint)numElems;
\r
5731 internal override byte[] ToBlob() {
\r
5732 MemoryStream str = new MemoryStream();
\r
5733 str.WriteByte(GetTypeIndex());
\r
5734 MetaData.CompressNum(numElem,str);
\r
5735 if (elemType == null) str.WriteByte(0x50); // no info (MAX)
\r
5736 else str.WriteByte(elemType.GetTypeIndex());
\r
5737 return str.ToArray();
\r
5742 public class CustomMarshaller : NativeType
\r
5745 string marshallerName;
\r
5748 public CustomMarshaller(string typeNameOrGUID, string marshallerName,
\r
5749 string optCookie) : base(0x2C) {
\r
5750 typeName = typeNameOrGUID;
\r
5751 this.marshallerName = marshallerName;
\r
5752 cookie = optCookie;
\r
5755 internal override byte[] ToBlob() {
\r
5756 MemoryStream str = new MemoryStream();
\r
5757 BinaryWriter bw = new BinaryWriter(str,new UTF8Encoding());
\r
5758 bw.Write(GetTypeIndex());
\r
5759 bw.Write(typeName.ToCharArray());
\r
5760 bw.Write((byte)0);
\r
5761 bw.Write(marshallerName.ToCharArray());
\r
5762 bw.Write((byte)0);
\r
5763 if (cookie != null) bw.Write(cookie.ToCharArray());
\r
5764 bw.Write((byte)0);
\r
5766 return str.ToArray();
\r
5770 /**************************************************************************/
\r
5772 /// Descriptor for a parameter of a method defined in this assembly/module
\r
5774 public class Param : MetaDataElement
\r
5776 private static readonly ushort hasDefault = 0x1000;
\r
5777 private static readonly ushort hasFieldMarshal = 0x2000;
\r
5781 internal ushort seqNo = 0;
\r
5783 ConstantElem defaultVal;
\r
5785 FieldMarshal marshalInfo;
\r
5788 /// Create a new parameter for a method
\r
5790 /// <param name="mode">param mode (in, out, opt)</param>
\r
5791 /// <param name="parName">parameter name</param>
\r
5792 /// <param name="parType">parameter type</param>
\r
5793 public Param(ParamAttr mode, string parName, Type parType) {
\r
5796 parMode = (ushort)mode;
\r
5797 tabIx = MDTable.Param;
\r
5801 /// Add a default value to this parameter
\r
5803 /// <param name="c">the default value for the parameter</param>
\r
5804 public void AddDefaultValue(Constant cVal) {
\r
5805 defaultVal = new ConstantElem(this,cVal);
\r
5806 parMode |= hasDefault;
\r
5810 /// Add marshalling information about this parameter
\r
5812 public void AddMarshallInfo(NativeType marshallType) {
\r
5813 parMode |= hasFieldMarshal;
\r
5814 marshalInfo = new FieldMarshal(this,marshallType);
\r
5817 internal Type GetParType() { return pType; }
\r
5819 internal sealed override void BuildTables(MetaData md) {
\r
5821 nameIx = md.AddToStringsHeap(pName);
\r
5822 if (defaultVal != null) {
\r
5823 md.AddToTable(MDTable.Constant,defaultVal);
\r
5824 defaultVal.BuildTables(md);
\r
5826 if (marshalInfo != null) {
\r
5827 md.AddToTable(MDTable.FieldMarshal,marshalInfo);
\r
5828 marshalInfo.BuildTables(md);
\r
5833 internal void TypeSig(MemoryStream str) {
\r
5834 pType.TypeSig(str);
\r
5837 internal sealed override uint Size(MetaData md) {
\r
5838 return 4 + md.StringsIndexSize();
\r
5841 internal sealed override void Write(FileImage output) {
\r
5842 output.Write(parMode);
\r
5843 output.Write(seqNo);
\r
5844 output.StringsIndex(nameIx);
\r
5847 internal sealed override uint GetCodedIx(CIx code) {
\r
5849 case (CIx.HasCustomAttr) : return 4;
\r
5850 case (CIx.HasConst) : return 1;
\r
5851 case (CIx.HasFieldMarshal) : return 1;
\r
5857 /**************************************************************************/
\r
5859 /// Base class for the PEFile (starting point)
\r
5861 public class PEFile
\r
5863 private static readonly string mscorlibName = "mscorlib";
\r
5864 private Module thisMod;
\r
5865 private ClassDef moduleClass;
\r
5866 private ArrayList classRefList = new ArrayList();
\r
5867 private ArrayList classDefList = new ArrayList();
\r
5868 private Assembly thisAssembly;
\r
5869 private int corFlags = 1;
\r
5870 FileImage fileImage;
\r
5871 MetaData metaData;
\r
5874 /// Create a new PEFile. Each PEFile is a module.
\r
5876 /// <param name="name">module name, also used for the file name</param>
\r
5877 /// <param name="isDLL">create a .dll or .exe file</param>
\r
5878 /// <param name="hasAssembly">this file is an assembly and
\r
5879 /// will contain the assembly manifest. The assembly name is the
\r
5880 /// same as the module name</param>
\r
5881 public PEFile(string name, bool isDLL, bool hasAssembly) {
\r
5882 // Console.WriteLine(Hex.Byte(0x12));
\r
5883 // Console.WriteLine(Hex.Short(0x1234));
\r
5884 // Console.WriteLine(Hex.Int(0x12345678));
\r
5885 string fName = MakeFileName(null,name,isDLL);
\r
5886 fileImage = new FileImage(isDLL,fName);
\r
5887 InitPEFile(name, fName, hasAssembly);
\r
5891 /// Create a new PEFile. Each PEFile is a module.
\r
5893 /// <param name="name">module name, also used for the file name</param>
\r
5894 /// <param name="isDLL">create a .dll or .exe file</param>
\r
5895 /// <param name="hasAssembly">this file is an assembly and
\r
5896 /// will contain the assembly manifest. The assembly name is the
\r
5897 /// same as the module name</param>
\r
5898 /// <param name="outputDir">write the PEFile to this directory. If this
\r
5899 /// string is null then the output will be to the current directory</param>
\r
5900 public PEFile(string name, bool isDLL, bool hasAssembly, string outputDir) {
\r
5901 // Console.WriteLine(Hex.Byte(0x12));
\r
5902 // Console.WriteLine(Hex.Short(0x1234));
\r
5903 // Console.WriteLine(Hex.Int(0x12345678));
\r
5904 string fName = MakeFileName(outputDir,name,isDLL);
\r
5905 fileImage = new FileImage(isDLL,fName);
\r
5906 InitPEFile(name, fName, hasAssembly);
\r
5910 /// Create a new PEFile
\r
5912 /// <param name="name">module name</param>
\r
5913 /// <param name="isDLL">create a .dll or .exe</param>
\r
5914 /// <param name="hasAssembly">this PEfile is an assembly and
\r
5915 /// will contain the assemly manifest. The assembly name is the
\r
5916 /// same as the module name</param>
\r
5917 /// <param name="outStream">write the PEFile to this stream instead
\r
5918 /// of to a new file</param>
\r
5919 public PEFile(string name, bool isDLL, bool hasAssembly, Stream outStream) {
\r
5920 fileImage = new FileImage(isDLL,outStream);
\r
5921 InitPEFile(name, MakeFileName(null,name,isDLL), hasAssembly);
\r
5924 private void InitPEFile(string name, string fName, bool hasAssembly) {
\r
5925 metaData = fileImage.GetMetaData();
\r
5926 thisMod = new Module(fName,metaData);
\r
5927 if (hasAssembly) {
\r
5928 thisAssembly = new Assembly(name,metaData);
\r
5929 metaData.AddToTable(MDTable.Assembly,thisAssembly);
\r
5931 moduleClass = AddClass(TypeAttr.Private,"","<Module>");
\r
5932 moduleClass.SpecialNoSuper();
\r
5933 metaData.AddToTable(MDTable.Module,thisMod);
\r
5937 public ClassDef ModuleClass {
5938 get { return moduleClass; }
5942 /// Set the subsystem (.subsystem) (Default is Windows Console mode)
\r
5944 /// <param name="subS">subsystem value</param>
\r
5945 public void SetSubSystem(SubSystem subS) {
\r
5946 fileImage.subSys = subS;
\r
5950 /// Set the flags (.corflags)
\r
5952 /// <param name="flags">the flags value</param>
\r
5953 public void SetCorFlags(int flags) {
\r
5957 private string MakeFileName(string dirName, string name, bool isDLL) {
\r
5958 string result = "";
\r
5959 if ((dirName != null) && (dirName.CompareTo("") != 0)) {
\r
5961 if (!dirName.EndsWith("\\")) result += "\\";
\r
5965 // if (isDLL) result += ".dll"; else result += ".exe";
\r
5971 /// Add an external assembly to this PEFile (.assembly extern)
\r
5973 /// <param name="assemName">the external assembly name</param>
\r
5974 /// <returns>a descriptor for this external assembly</returns>
\r
5975 public AssemblyRef AddExternAssembly(string assemName) {
\r
5976 if (assemName.CompareTo(mscorlibName) == 0) return metaData.mscorlib;
\r
5977 AssemblyRef anAssem = new AssemblyRef(metaData,assemName);
\r
5978 metaData.AddToTable(MDTable.AssemblyRef,anAssem);
\r
5979 // Console.WriteLine("Adding assembly " + assemName);
\r
5984 /// Add an external module to this PEFile (.module extern)
\r
5986 /// <param name="name">the external module name</param>
\r
5987 /// <returns>a descriptor for this external module</returns>
\r
5988 public ModuleRef AddExternModule(string name) {
\r
5989 ModuleRef modRef = new ModuleRef(metaData,name);
\r
5990 metaData.AddToTable(MDTable.ModuleRef,modRef);
\r
5995 /// Add a "global" method to this module
\r
5997 /// <param name="name">method name</param>
\r
5998 /// <param name="retType">return type</param>
\r
5999 /// <param name="pars">method parameters</param>
\r
6000 /// <returns>a descriptor for this new "global" method</returns>
\r
6001 public MethodDef AddMethod(string name, Type retType, Param[] pars) {
\r
6002 return moduleClass.AddMethod(name,retType,pars);
\r
6006 /// Add a "global" method to this module
\r
6008 /// <param name="mAtts">method attributes</param>
\r
6009 /// <param name="iAtts">method implementation attributes</param>
\r
6010 /// <param name="name">method name</param>
\r
6011 /// <param name="retType">return type</param>
\r
6012 /// <param name="pars">method parameters</param>
\r
6013 /// <returns>a descriptor for this new "global" method</returns>
\r
6014 public MethodDef AddMethod(MethAttr mAtts, ImplAttr iAtts, string name, Type retType, Param[] pars) {
\r
6015 return moduleClass.AddMethod(mAtts,iAtts,name,retType,pars);
\r
6018 public MethodRef AddMethodToTypeSpec (Type item, string name, Type retType, Type[] pars) {
\r
6019 MethodRef meth = new MethodRef (item.GetTypeSpec (metaData), name, retType, pars, false, null);
\r
6020 metaData.AddToTable (MDTable.MemberRef,meth);
\r
6024 public MethodRef AddVarArgMethodToTypeSpec (Type item, string name, Type retType,
\r
6025 Type[] pars, Type[] optPars) {
\r
6026 MethodRef meth = new MethodRef(item.GetTypeSpec (metaData), name,retType,pars,true,optPars);
\r
6027 metaData.AddToTable(MDTable.MemberRef,meth);
\r
6031 public FieldRef AddFieldToTypeSpec (Type item, string name, Type fType) {
\r
6032 FieldRef field = new FieldRef (item.GetTypeSpec (metaData), name,fType);
\r
6033 metaData.AddToTable (MDTable.MemberRef,field);
\r
6038 /// Add a "global" field to this module
\r
6040 /// <param name="name">field name</param>
\r
6041 /// <param name="fType">field type</param>
\r
6042 /// <returns>a descriptor for this new "global" field</returns>
\r
6043 public FieldDef AddField(string name, Type fType) {
\r
6044 return moduleClass.AddField(name,fType);
\r
6048 /// Add a "global" field to this module
\r
6050 /// <param name="attrSet">attributes of this field</param>
\r
6051 /// <param name="name">field name</param>
\r
6052 /// <param name="fType">field type</param>
\r
6053 /// <returns>a descriptor for this new "global" field</returns>
\r
6054 public FieldDef AddField(FieldAttr attrSet, string name, Type fType) {
\r
6055 return moduleClass.AddField(attrSet,name,fType);
\r
6059 /// Add a class to this module
\r
6061 /// <param name="attrSet">attributes of this class</param>
\r
6062 /// <param name="nsName">name space name</param>
\r
6063 /// <param name="name">class name</param>
\r
6064 /// <returns>a descriptor for this new class</returns>
\r
6065 public ClassDef AddClass(TypeAttr attrSet, string nsName, string name) {
\r
6066 ClassDef aClass = new ClassDef(attrSet,nsName,name,metaData);
\r
6067 metaData.AddToTable(MDTable.TypeDef,aClass);
\r
6072 /// Add a class which extends System.ValueType to this module
\r
6074 /// <param name="attrSet">attributes of this class</param>
\r
6075 /// <param name="nsName">name space name</param>
\r
6076 /// <param name="name">class name</param>
\r
6077 /// <returns>a descriptor for this new class</returns>
\r
6078 public ClassDef AddValueClass(TypeAttr attrSet, string nsName, string name) {
\r
6079 ClassDef aClass = new ClassDef(attrSet,nsName,name,metaData);
\r
6080 aClass.MakeValueClass();
\r
6081 metaData.AddToTable(MDTable.TypeDef,aClass);
\r
6086 /// Add a class to this module
\r
6088 /// <param name="attrSet">attributes of this class</param>
\r
6089 /// <param name="nsName">name space name</param>
\r
6090 /// <param name="name">class name</param>
\r
6091 /// <param name="superType">super type of this class (extends)</param>
\r
6092 /// <returns>a descriptor for this new class</returns>
\r
6093 public ClassDef AddClass(TypeAttr attrSet, string nsName, string name, Class superType) {
\r
6094 ClassDef aClass = new ClassDef(attrSet,nsName,name,metaData);
\r
6095 aClass.SetSuper(superType);
\r
6096 metaData.AddToTable(MDTable.TypeDef,aClass);
\r
6100 public FileRef AddFile(string fName, byte[] hashBytes, bool hasMetaData, bool entryPoint) {
\r
6101 FileRef file = new FileRef(fName,hashBytes,hasMetaData,entryPoint,metaData);
\r
6102 metaData.AddToTable(MDTable.File,file);
\r
6107 /// Add a manifest resource to this PEFile NOT YET IMPLEMENTED
\r
6109 /// <param name="mr"></param>
\r
6110 public void AddManifestResource(ManifestResource mr) {
\r
6111 metaData.AddToTable(MDTable.ManifestResource,mr);
\r
6112 //mr.FixName(metaData);
\r
6116 /// Write out the PEFile (the "bake" function)
\r
6118 public void WritePEFile() { /* the "bake" function */
\r
6119 fileImage.MakeFile();
\r
6123 /// Get the descriptor of this module
\r
6125 /// <returns>the descriptor for this module</returns>
\r
6126 public Module GetThisModule() {
\r
6131 /// Get the descriptor for this assembly. The PEFile must have been
\r
6132 /// created with hasAssembly = true
\r
6134 /// <returns>the descriptor for this assembly</returns>
\r
6135 public Assembly GetThisAssembly() {
\r
6136 return thisAssembly;
\r
6141 /**************************************************************************/
\r
6143 /// Descriptor for the Primitive types defined in IL
\r
6145 public class PrimitiveType : Type
\r
6147 private string name;
\r
6148 private int systemTypeIndex;
\r
6149 public static int NumSystemTypes = 18;
\r
6151 public static readonly PrimitiveType Void = new PrimitiveType(0x01,"Void",0);
\r
6152 public static readonly PrimitiveType Boolean = new PrimitiveType(0x02,"Boolean",1);
\r
6153 public static readonly PrimitiveType Char = new PrimitiveType(0x03,"Char",2);
\r
6154 public static readonly PrimitiveType Int8 = new PrimitiveType(0x04,"SByte",3);
\r
6155 public static readonly PrimitiveType UInt8 = new PrimitiveType(0x05,"Byte",4);
\r
6156 public static readonly PrimitiveType Int16 = new PrimitiveType(0x06,"Int16",5);
\r
6157 public static readonly PrimitiveType UInt16 = new PrimitiveType(0x07,"UInt16",6);
\r
6158 public static readonly PrimitiveType Int32 = new PrimitiveType(0x08,"Int32",7);
\r
6159 public static readonly PrimitiveType UInt32 = new PrimitiveType(0x09,"UInt32",8);
\r
6160 public static readonly PrimitiveType Int64 = new PrimitiveType(0x0A,"Int64",9);
\r
6161 public static readonly PrimitiveType UInt64 = new PrimitiveType(0x0B,"UInt64",10);
\r
6162 public static readonly PrimitiveType Float32 = new PrimitiveType(0x0C,"Single",11);
\r
6163 public static readonly PrimitiveType Float64 = new PrimitiveType(0x0D,"Double",12);
\r
6164 public static readonly PrimitiveType String = new PrimitiveType(0x0E,"String",13);
\r
6165 internal static readonly PrimitiveType Class = new PrimitiveType(0x12);
\r
6166 public static readonly PrimitiveType TypedRef = new PrimitiveType(0x16,"TypedReference",14);
\r
6167 public static readonly PrimitiveType IntPtr = new PrimitiveType(0x18,"IntPtr",15);
\r
6168 public static readonly PrimitiveType UIntPtr = new PrimitiveType(0x19,"UIntPtr",16);
\r
6169 public static readonly PrimitiveType Object = new PrimitiveType(0x1C,"Object",17);
\r
6170 internal static readonly PrimitiveType ClassType = new PrimitiveType(0x50);
\r
6171 public static readonly PrimitiveType NativeInt = IntPtr;
\r
6172 public static readonly PrimitiveType NativeUInt = UIntPtr;
\r
6174 internal PrimitiveType(byte typeIx) : base(typeIx) { }
\r
6176 internal PrimitiveType(byte typeIx, string name, int STIx) : base(typeIx) {
\r
6178 this.systemTypeIndex = STIx;
\r
6181 internal string GetName() { return name; }
\r
6183 internal int GetSystemTypeIx() { return systemTypeIndex; }
\r
6185 internal sealed override void TypeSig(MemoryStream str) {
\r
6186 str.WriteByte(typeIndex);
\r
6189 internal override MetaDataElement GetTypeSpec(MetaData md) {
\r
6190 TypeSpec tS = md.GetPrimitiveTypeSpec(systemTypeIndex);
\r
6192 tS = new TypeSpec(this,md);
\r
6193 md.SetPrimitiveTypeSpec(systemTypeIndex,tS);
\r
6194 md.AddToTable(MDTable.TypeSpec,tS);
\r
6201 /**************************************************************************/
\r
6203 /// Descriptor for the Property of a class
\r
6205 public class Property : Feature
\r
6207 private static readonly byte PropertyTag = 0x8;
\r
6208 MethodDef getterMeth;
\r
6209 ConstantElem constVal;
\r
6210 uint typeBlobIx = 0;
\r
6215 internal Property(string name, Type retType, Type[] pars, ClassDef parent) : base(name, parent) {
\r
6216 returnType = retType;
\r
6218 if (pars != null) numPars = (uint)pars.Length;
\r
6219 tabIx = MDTable.Property;
\r
6223 /// Add a set method to this property
\r
6225 /// <param name="setter">the set method</param>
\r
6226 public void AddSetter(MethodDef setter) {
\r
6227 AddMethod(setter,MethodType.Setter);
\r
6231 /// Add a get method to this property
\r
6233 /// <param name="getter">the get method</param>
\r
6234 public void AddGetter(MethodDef getter) {
\r
6235 AddMethod(getter,MethodType.Getter);
\r
6236 getterMeth = getter;
\r
6240 /// Add another method to this property
\r
6242 /// <param name="other">the method</param>
\r
6243 public void AddOther(MethodDef other) {
\r
6244 AddMethod(other,MethodType.Other);
\r
6248 /// Add an initial value for this property
\r
6250 /// <param name="constVal">the initial value for this property</param>
\r
6251 public void AddInitValue(Constant constVal) {
\r
6252 this.constVal = new ConstantElem(this,constVal);
\r
6255 internal sealed override void BuildTables(MetaData md) {
\r
6257 nameIx = md.AddToStringsHeap(name);
\r
6258 MemoryStream sig = new MemoryStream();
\r
6259 sig.WriteByte(PropertyTag);
\r
6260 MetaData.CompressNum(numPars,sig);
\r
6261 returnType.TypeSig(sig);
\r
6262 for (int i=0; i < numPars; i++) {
\r
6263 parList[i].TypeSig(sig);
\r
6265 typeBlobIx = md.AddToBlobHeap(sig.ToArray());
\r
6266 for (int i=0; i < tide; i++) {
\r
6267 md.AddToTable(MDTable.MethodSemantics,methods[i]);
\r
6269 if (constVal != null) {
\r
6270 md.AddToTable(MDTable.Constant,constVal);
\r
6271 constVal.BuildTables(md);
\r
6276 internal sealed override uint Size(MetaData md) {
\r
6277 return 2 + md.StringsIndexSize() + md.BlobIndexSize();
\r
6280 internal sealed override void Write(FileImage output) {
\r
6281 output.Write(flags);
\r
6282 output.StringsIndex(nameIx);
\r
6283 output.BlobIndex(typeBlobIx);
\r
6286 internal sealed override uint GetCodedIx(CIx code) {
\r
6288 case (CIx.HasCustomAttr) : return 9;
\r
6289 case (CIx.HasConst) : return 2;
\r
6290 case (CIx.HasSemantics) : return 1;
\r
6296 /**************************************************************************/
\r
6298 /// Descriptor for an pointer (type * or type &)
\r
6300 public abstract class PtrType : Type
\r
6304 internal PtrType(Type bType, byte typeIx) : base(typeIx)
\r
6307 tabIx = MDTable.TypeSpec;
\r
6310 internal sealed override void TypeSig(MemoryStream str) {
\r
6311 str.WriteByte(typeIndex);
\r
6312 baseType.TypeSig(str);
\r
6316 /**************************************************************************/
\r
6318 /// Descriptor for a managed pointer (type & or byref)
\r
6321 public class ManagedPointer : PtrType // <type> & (BYREF)
\r
6325 /// Create new managed pointer to baseType
\r
6327 /// <param name="bType">the base type of the pointer</param>
\r
6328 public ManagedPointer(Type baseType) : base(baseType,0x10) { }
\r
6331 /**************************************************************************/
\r
6333 /// Descriptor for an unmanaged pointer (type *)
\r
6335 public class UnmanagedPointer : PtrType // PTR
\r
6338 /// Create a new unmanaged pointer to baseType
\r
6340 /// <param name="baseType">the base type of the pointer</param>
\r
6341 public UnmanagedPointer(Type baseType) : base(baseType, 0x0F) { }
\r
6344 /**************************************************************************/
\r
6346 /// Base class for scopes (extended by Module, ModuleRef, Assembly, AssemblyRef)
\r
6348 public abstract class ResolutionScope : MetaDataElement
\r
6350 protected uint nameIx = 0;
\r
6351 protected MetaData metaData;
\r
6352 protected string name;
\r
6354 internal ResolutionScope(string name, MetaData md)
\r
6358 nameIx = md.AddToStringsHeap(name);
\r
6361 internal string GetName() { return name; }
\r
6364 /**************************************************************************/
\r
6366 /// Descriptor for a Section in a PEFile eg .text, .sdata
\r
6368 internal class Section {
\r
6369 private static readonly uint relocPageSize = 4096; // 4K pages for fixups
\r
6372 uint offset = 0, tide = 0, size = 0, rva = 0, relocTide = 0;
\r
6373 //uint relocOff = 0;
\r
6374 uint flags = 0, padding = 0;
\r
6377 internal Section(string sName, uint sFlags) {
\r
6378 name = sName.ToCharArray();
\r
6382 internal uint Tide() { return tide; }
\r
6384 internal void IncTide(uint incVal) { tide += incVal; }
\r
6386 internal uint Padding() { return padding; }
\r
6388 internal uint Size() { return size; }
\r
6390 internal void SetSize(uint pad) {
\r
6392 size = tide + padding;
\r
6395 internal uint RVA() { return rva; }
\r
6397 internal void SetRVA(uint rva) { this.rva = rva; }
\r
6399 internal uint Offset() { return offset; }
\r
6401 internal void SetOffset(uint offs) { offset = offs; }
\r
6403 internal void DoBlock(BinaryWriter reloc, uint page, int start, int end) {
\r
6404 //Console.WriteLine("rva = " + rva + " page = " + page);
\r
6405 reloc.Write(rva + page);
\r
6406 reloc.Write((uint)(((end-start+1)*2) + 8));
\r
6407 for (int j=start; j < end; j++) {
\r
6408 //Console.WriteLine("reloc offset = " + relocs[j]);
\r
6409 reloc.Write((ushort)((0x3 << 12) | (relocs[j] - page)));
\r
6411 reloc.Write((ushort)0);
\r
6414 internal void DoRelocs(BinaryWriter reloc) {
\r
6415 if (relocTide > 0) {
\r
6416 //relocOff = (uint)reloc.Seek(0,SeekOrigin.Current);
\r
6417 uint block = (relocs[0]/relocPageSize + 1) * relocPageSize;
\r
6419 for (int i=1; i < relocTide; i++) {
\r
6420 if (relocs[i] >= block) {
\r
6421 DoBlock(reloc,block-relocPageSize,start,i);
\r
6423 block = (relocs[i]/relocPageSize + 1) * relocPageSize;
\r
6426 DoBlock(reloc,block-relocPageSize,start,(int)relocTide);
\r
6430 internal void AddReloc(uint offs) {
\r
6432 if (relocs == null) {
\r
6433 relocs = new uint[5];
\r
6435 if (relocTide >= relocs.Length) {
\r
6436 uint[] tmp = relocs;
\r
6437 relocs = new uint[tmp.Length + 5];
\r
6438 for (int i=0; i < relocTide; i++) {
\r
6439 relocs[i] = tmp[i];
\r
6442 while ((pos < relocTide) && (relocs[pos] < offs)) pos++;
\r
6443 for (int i=pos; i < relocTide; i++) {
\r
6444 relocs[i+1] = relocs[i];
\r
6447 relocs[pos] = offs;
\r
6451 internal void WriteHeader(BinaryWriter output, uint relocRVA) {
\r
6452 output.Write(name);
\r
6453 output.Write(tide);
\r
6454 output.Write(rva);
\r
6455 output.Write(size);
\r
6456 output.Write(offset);
\r
6458 //output.Write(relocRVA + relocOff);
\r
6461 //output.Write((ushort)relocTide);
\r
6462 //output.Write((ushort)0);
\r
6463 output.Write(flags);
\r
6467 /**************************************************************************/
\r
6468 public abstract class Signature : MetaDataElement
\r
6470 protected uint sigIx;
\r
6472 internal Signature() {
\r
6473 tabIx = MDTable.StandAloneSig;
\r
6476 internal sealed override uint Size(MetaData md) {
\r
6477 return md.BlobIndexSize();
\r
6480 internal sealed override void Write(FileImage output) {
\r
6481 output.BlobIndex(sigIx);
\r
6484 internal sealed override uint GetCodedIx(CIx code) { return (uint)tabIx; }
\r
6487 /**************************************************************************/
\r
6489 /// Descriptor for a class defined in System (mscorlib)
\r
6491 internal class SystemClass : ClassRef
\r
6493 PrimitiveType elemType;
\r
6495 internal SystemClass(PrimitiveType eType, AssemblyRef paren, MetaData md)
\r
6496 : base("System",eType.GetName(),md) {
\r
6501 internal override sealed MetaDataElement GetTypeSpec(MetaData md) {
\r
6502 if (typeSpec == null) typeSpec = (TypeSpec)elemType.GetTypeSpec(md);
\r
6507 internal sealed override void TypeSig(MemoryStream str) {
\r
6508 str.WriteByte(elemType.GetTypeIndex());
\r
6512 /**************************************************************************/
\r
6514 /// Base class for all IL types
\r
6516 public abstract class Type : MetaDataElement {
\r
6517 protected byte typeIndex;
\r
6518 protected TypeSpec typeSpec;
\r
6520 internal Type(byte tyIx) { typeIndex = tyIx; }
\r
6522 internal byte GetTypeIndex() { return typeIndex; }
\r
6524 internal virtual MetaDataElement GetTypeSpec(MetaData md) {
\r
6525 if (typeSpec == null) {
\r
6526 typeSpec = new TypeSpec(this,md);
\r
6527 md.AddToTable(MDTable.TypeSpec,typeSpec);
\r
6532 internal virtual void TypeSig(MemoryStream str) {
\r
6533 throw(new TypeSignatureException(this.GetType().AssemblyQualifiedName +
\r
6534 " doesn't have a type signature!!"));
\r
6539 /**************************************************************************/
\r
6541 public class TypeSpec : MetaDataElement {
\r
6544 internal TypeSpec(Type aType, MetaData md) {
\r
6545 MemoryStream sig = new MemoryStream();
\r
6546 aType.TypeSig(sig);
\r
6547 sigIx = md.AddToBlobHeap(sig.ToArray());
\r
6548 tabIx = MDTable.TypeSpec;
\r
6551 internal sealed override uint GetCodedIx(CIx code) {
\r
6553 case (CIx.TypeDefOrRef) : return 2;
\r
6554 case (CIx.HasCustomAttr) : return 13;
\r
6555 case (CIx.MemberRefParent) : return 4;
\r
6560 internal override uint Size(MetaData md) {
\r
6561 return md.BlobIndexSize();
\r
6564 internal sealed override void Write(FileImage output) {
\r
6565 //Console.WriteLine("Writing the blob index for a TypeSpec");
\r
6566 output.BlobIndex(sigIx);
\r