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 { ansi = 2, unicode = 4, autochar = 6,
\r
568 platformapi = 0x100, cdecl = 0x200, stdcall = 0x300, thiscall = 0x400,
\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 }
\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 generic type parameter.
\r
1755 public void AddGenericParameter (short index) {
\r
1756 metaData.AddToTable (MDTable.GenericParam, new GenericParameter (this, index));
\r
1760 /// Add a named generic type parameter
\r
1762 public void AddGenericParameter (short index, string name) {
\r
1763 metaData.AddToTable (MDTable.GenericParam, new GenericParameter (this, index, name));
\r
1766 public void AddGenericParameter (short index, Type constraint) {
\r
1767 GenericParameter gp = new GenericParameter (this, index);
\r
1768 metaData.AddToTable (MDTable.GenericParam, gp);
\r
1769 metaData.AddToTable (MDTable.GenericParamConstraint,
\r
1770 new GenericParamConstraint (gp, constraint));
\r
1773 public void AddGenericParameter (short index, string name, Type constraint) {
\r
1774 GenericParameter gp = new GenericParameter (this, index, name);
\r
1775 metaData.AddToTable (MDTable.GenericParam, gp);
\r
1776 metaData.AddToTable (MDTable.GenericParamConstraint,
\r
1777 new GenericParamConstraint (gp, constraint));
\r
1781 /// Add a field to this class
\r
1783 /// <param name="name">field name</param>
\r
1784 /// <param name="fType">field type</param>
\r
1785 /// <returns>a descriptor for this new field</returns>
\r
1786 public FieldDef AddField(string name, Type fType) {
\r
1787 FieldDef field = new FieldDef(name,fType);
\r
1788 fields.Add(field);
\r
1793 /// Add a field to this class
\r
1795 /// <param name="fAtts">attributes for this field</param>
\r
1796 /// <param name="name">field name</param>
\r
1797 /// <param name="fType">field type</param>
\r
1798 /// <returns>a descriptor for this new field</returns>
\r
1799 public FieldDef AddField(FieldAttr fAtts, string name, Type fType) {
\r
1800 FieldDef field = new FieldDef(fAtts,name,fType);
\r
1801 fields.Add(field);
\r
1806 /// Add a method to this class
\r
1808 /// <param name="name">method name</param>
\r
1809 /// <param name="retType">return type</param>
\r
1810 /// <param name="pars">parameters</param>
\r
1811 /// <returns>a descriptor for this new method</returns>
\r
1812 public MethodDef AddMethod(string name, Type retType, Param[] pars) {
\r
1813 // Console.WriteLine("Adding method " + name + " to class " + this.name);
\r
1814 MethodDef meth = new MethodDef(metaData,name,retType, pars);
\r
1815 methods.Add(meth);
\r
1820 /// Add a method to this class
\r
1822 /// <param name="mAtts">attributes for this method</param>
\r
1823 /// <param name="iAtts">implementation attributes for this method</param>
\r
1824 /// <param name="name">method name</param>
\r
1825 /// <param name="retType">return type</param>
\r
1826 /// <param name="pars">parameters</param>
\r
1827 /// <returns>a descriptor for this new method</returns>
\r
1828 public MethodDef AddMethod(MethAttr mAtts, ImplAttr iAtts, string name,
\r
1829 Type retType, Param[] pars) {
\r
1830 // Console.WriteLine("Adding method " + name + " to class " + this.name);
\r
1831 MethodDef meth = new MethodDef(metaData,mAtts,iAtts,name,retType,pars);
\r
1832 methods.Add(meth);
\r
1837 /// Add an event to this class
\r
1839 /// <param name="name">event name</param>
\r
1840 /// <param name="eType">event type</param>
\r
1841 /// <returns>a descriptor for this new event</returns>
\r
1842 public Event AddEvent(string name, Type eType) {
\r
1843 Event e = new Event(name,eType,this);
\r
1844 if (events == null) events = new ArrayList();
\r
1850 /// Add a property to this class
\r
1852 /// <param name="name">property name</param>
\r
1853 /// <param name="propType">property type</param>
\r
1854 /// <returns>a descriptor for this new property</returns>
\r
1855 public Property AddProperty(string name, Type retType, Type[] pars) {
\r
1856 Property p = new Property(name, retType, pars, this);
\r
1857 if (properties == null) properties = new ArrayList();
\r
1858 properties.Add(p);
\r
1864 /// Add a nested class to this class
\r
1866 /// <param name="attrSet">attributes for this nested class</param>
\r
1867 /// <param name="nsName">nested name space name</param>
\r
1868 /// <param name="name">nested class name</param>
\r
1869 /// <returns>a descriptor for this new nested class</returns>
\r
1870 public ClassDef AddNestedClass(TypeAttr attrSet, string nsName,
\r
1872 ClassDef nClass = new ClassDef(attrSet,nsName,name,metaData);
\r
1873 metaData.AddToTable(MDTable.TypeDef,nClass);
\r
1874 metaData.AddToTable(MDTable.NestedClass,new MapElem(nClass,Row,MDTable.TypeDef));
\r
1875 nClass.parentClass = this;
\r
1880 /// Add a nested class to this class
\r
1882 /// <param name="attrSet">attributes for this nested class</param>
\r
1883 /// <param name="nsName">nested name space name</param>
\r
1884 /// <param name="name">nested class name</param>
\r
1885 /// <param name="sType">super type of this nested class</param>
\r
1886 /// <returns>a descriptor for this new nested class</returns>
\r
1887 public ClassDef AddNestedClass(TypeAttr attrSet, string nsName,
\r
1888 string name, Class sType) {
\r
1889 ClassDef nClass = new ClassDef(attrSet,nsName,name,metaData);
\r
1890 nClass.SetSuper(sType);
\r
1891 metaData.AddToTable(MDTable.TypeDef,nClass);
\r
1892 metaData.AddToTable(MDTable.NestedClass,
\r
1893 new MapElem(nClass,Row,MDTable.TypeDef));
\r
1894 nClass.parentClass = this;
\r
1899 /// Add layout information for this class. This class must have the
\r
1900 /// sequential or explicit attribute.
\r
1902 /// <param name="packSize">packing size (.pack)</param>
\r
1903 /// <param name="classSize">class size (.size)</param>
\r
1904 public void AddLayoutInfo (int packSize, int classSize) {
\r
1905 layout = new ClassLayout(packSize,classSize,this);
\r
1909 /// Use a method as the implementation for another method (.override)
\r
1911 /// <param name="decl">the method to be overridden</param>
\r
1912 /// <param name="body">the implementation to be used</param>
\r
1913 public void AddMethodOverride(Method decl, Method body) {
\r
1914 metaData.AddToTable(MDTable.MethodImpl,new MethodImpl(this,decl,body));
\r
1918 /// Add security to this class NOT YET IMPLEMENTED
\r
1920 /// <param name="permissionSet"></param>
\r
1921 public void AddSecurity(byte[] permissionSet) {
\r
1922 throw(new NotYetImplementedException("Class security "));
\r
1923 //flags |= HasSecurity;
\r
1924 // securityActions = permissionSet;
\r
1927 //public void AddLineInfo(int row, int col) { }
\r
1929 internal void CheckTypeIndex() {
\r
1930 if (typeIndexChecked) return;
\r
1931 if (!(superType is ClassRef))
\r
1932 ((ClassDef)superType).CheckTypeIndex();
\r
1933 typeIndex = superType.GetTypeIndex();
\r
1934 typeIndexChecked = true;
\r
1937 internal sealed override void BuildTables(MetaData md) {
\r
1939 if ((flags & (uint)TypeAttr.Interface) != 0) { superType = null; }
\r
1940 // Console.WriteLine("Building tables for " + name);
\r
1941 if (layout != null) md.AddToTable(MDTable.ClassLayout,layout);
\r
1942 // Console.WriteLine("adding methods " + methods.Count);
\r
1943 methodIx = md.TableIndex(MDTable.Method);
\r
1944 for (int i=0; i < methods.Count; i++) {
\r
1945 md.AddToTable(MDTable.Method,(MetaDataElement)methods[i]);
\r
1946 ((MethodDef)methods[i]).BuildTables(md);
\r
1948 // Console.WriteLine("adding fields");
\r
1949 fieldIx = md.TableIndex(MDTable.Field);
\r
1950 for (int i=0; i < fields.Count; i++) {
\r
1951 md.AddToTable(MDTable.Field,(MetaDataElement)fields[i]);
\r
1952 ((FieldDef)fields[i]).BuildTables(md);
\r
1954 // Console.WriteLine("adding events and properties");
\r
1955 if (events != null) {
\r
1956 for (int i=0; i < events.Count; i++) {
\r
1957 md.AddToTable(MDTable.Event,(Event)events[i]);
\r
1958 ((Event)events[i]).BuildTables(md);
\r
1960 md.AddToTable(MDTable.EventMap,
\r
1961 new MapElem(this,((Event)events[0]).Row,MDTable.Event));
\r
1963 if (properties != null) {
\r
1964 for (int i=0; i < properties.Count; i++) {
\r
1965 md.AddToTable(MDTable.Property,(Property)properties[i]);
\r
1966 ((Property)properties[i]).BuildTables(md);
\r
1968 md.AddToTable(MDTable.PropertyMap,new MapElem(this,
\r
1969 ((Property)properties[0]).Row,MDTable.Property));
\r
1971 DoCustomAttributes (md);
\r
1972 // Console.WriteLine("End of building tables");
\r
1976 internal sealed override uint Size(MetaData md) {
\r
1977 return 4 + 2 * md.StringsIndexSize() +
\r
1978 md.CodedIndexSize(CIx.TypeDefOrRef) +
\r
1979 md.TableIndexSize(MDTable.Field) +
\r
1980 md.TableIndexSize(MDTable.Method);
\r
1983 internal sealed override void Write(FileImage output) {
\r
1984 output.Write(flags);
\r
1985 output.StringsIndex(nameIx);
\r
1986 output.StringsIndex(nameSpaceIx);
\r
1987 //if (superType != null)
\r
1988 // Console.WriteLine("getting coded index for superType of " + name + " = " + superType.GetCodedIx(CIx.TypeDefOrRef));
\r
1989 output.WriteCodedIndex(CIx.TypeDefOrRef,superType);
\r
1990 output.WriteIndex(MDTable.Field,fieldIx);
\r
1991 output.WriteIndex(MDTable.Method,methodIx);
\r
1994 internal sealed override uint TypeDefOrRefToken() {
\r
2000 internal sealed override void TypeSig(MemoryStream sig) {
\r
2001 if (!typeIndexChecked) CheckTypeIndex();
\r
2002 sig.WriteByte(GetTypeIndex());
\r
2003 MetaData.CompressNum(TypeDefOrRefToken(),sig);
\r
2006 internal sealed override uint GetCodedIx(CIx code) {
\r
2008 case (CIx.TypeDefOrRef) : return 0;
\r
2009 case (CIx.HasCustomAttr) : return 3;
\r
2010 case (CIx.HasDeclSecurity) : return 0;
\r
2011 case (CIx.TypeOrMethodDef) : return 0;
\r
2017 /**************************************************************************/
\r
2019 /// Layout information for a class (.class [sequential | explicit])
\r
2021 internal class ClassLayout : MetaDataElement
\r
2024 ushort packSize = 0;
\r
2025 uint classSize = 0;
\r
2027 internal ClassLayout(int pack, int cSize, ClassDef par) {
\r
2028 packSize = (ushort)pack;
\r
2029 classSize = (uint)cSize;
\r
2031 tabIx = MDTable.ClassLayout;
\r
2034 internal sealed override uint Size(MetaData md) {
\r
2035 return 6 + md.TableIndexSize(MDTable.TypeDef);
\r
2038 internal sealed override void Write(FileImage output) {
\r
2039 output.Write(packSize);
\r
2040 output.Write(classSize);
\r
2041 output.WriteIndex(MDTable.TypeDef,parent.Row);
\r
2045 /**************************************************************************/
\r
2047 /// Descriptor for a class/interface declared in another module of THIS
\r
2048 /// assembly, or in another assembly.
\r
2050 public class ClassRef : Class
\r
2052 protected ResolutionScope parent;
\r
2053 ExternClass externClass;
\r
2054 protected MetaData metaData;
\r
2056 internal ClassRef(string nsName, string name, MetaData md) : base(nsName, name, md) {
\r
2058 tabIx = MDTable.TypeRef;
\r
2062 /// Add a method to this class
\r
2064 /// <param name="name">method name</param>
\r
2065 /// <param name="retType">return type</param>
\r
2066 /// <param name="pars">parameter types</param>
\r
2067 /// <returns>a descriptor for this method</returns>
\r
2068 public MethodRef AddMethod(string name, Type retType, Type[] pars) {
\r
2069 MethodRef meth = new MethodRef(this,name,retType,pars,false,null);
\r
2070 metaData.AddToTable(MDTable.MemberRef,meth);
\r
2075 /// Add a method to this class
\r
2077 /// <param name="name">method name</param>
\r
2078 /// <param name="retType">return type</param>
\r
2079 /// <param name="pars">parameter types</param>
\r
2080 /// <returns>a descriptor for this method</returns>
\r
2081 public MethodRef AddVarArgMethod(string name, Type retType,
\r
2082 Type[] pars, Type[] optPars) {
\r
2083 MethodRef meth = new MethodRef(this,name,retType,pars,true,optPars);
\r
2084 metaData.AddToTable(MDTable.MemberRef,meth);
\r
2089 /// Add a field to this class
\r
2091 /// <param name="name">field name</param>
\r
2092 /// <param name="fType">field type</param>
\r
2093 /// <returns>a descriptor for this field</returns>
\r
2094 public FieldRef AddField(string name, Type fType) {
\r
2095 FieldRef field = new FieldRef(this,name,fType);
\r
2096 metaData.AddToTable(MDTable.MemberRef,field);
\r
2100 internal void SetParent(ResolutionScope par) {
\r
2104 internal override string TypeName() {
\r
2105 if ((parent != null) && (parent is AssemblyRef))
\r
2106 return (nameSpace + "." + name + ", " + ((AssemblyRef)parent).TypeName());
\r
2108 return (nameSpace + name);
\r
2111 internal sealed override uint Size(MetaData md) {
\r
2112 return md.CodedIndexSize(CIx.ResolutionScope) + 2 *
\r
2113 md.StringsIndexSize();
\r
2116 internal sealed override void Write(FileImage output) {
\r
2117 output.WriteCodedIndex(CIx.ResolutionScope,parent);
\r
2118 output.StringsIndex(nameIx);
\r
2119 output.StringsIndex(nameSpaceIx);
\r
2122 internal override sealed uint TypeDefOrRefToken() {
\r
2124 cIx = (cIx << 2) | 0x1;
\r
2128 internal override void TypeSig(MemoryStream sig) {
\r
2129 sig.WriteByte(GetTypeIndex());
\r
2130 MetaData.CompressNum(TypeDefOrRefToken(),sig);
\r
2133 internal sealed override uint GetCodedIx(CIx code) {
\r
2135 case (CIx.TypeDefOrRef) : return 1;
\r
2136 case (CIx.HasCustomAttr) : return 2;
\r
2137 case (CIx.MemberRefParent) : return 1;
\r
2138 case (CIx.ResolutionScope) : return 3;
\r
2144 /**************************************************************************/
\r
2146 public class ExternClassRef : ClassRef {
\r
2148 ExternClass externClass;
\r
2150 internal ExternClassRef(TypeAttr attrs, string nsName, string name,
\r
2151 FileRef declFile, MetaData md) : base(nsName,name,md) {
\r
2152 externClass = new ExternClass(attrs,nameSpaceIx,nameIx,declFile);
\r
2153 metaData.AddToTable(MDTable.ExportedType,externClass);
\r
2156 internal ExternClassRef(string name, MetaData md) : base(null,name,md) {
\r
2159 public ClassRef AddNestedClass(TypeAttr attrs, string name) {
\r
2160 ExternClassRef nestedClass = new ExternClassRef(name,metaData);
\r
2161 externClass = new ExternClass(attrs,0,nameIx,this.externClass);
\r
2162 metaData.AddToTable(MDTable.ExportedType,externClass);
\r
2163 return nestedClass;
\r
2167 /**************************************************************************/
\r
2169 /// Descriptor for a constant value
\r
2171 public abstract class Constant {
\r
2172 protected uint size = 0;
\r
2173 protected Type type;
\r
2174 protected uint blobIndex;
\r
2175 protected bool addedToBlobHeap = false;
\r
2177 internal Constant() { }
\r
2179 internal virtual uint GetBlobIndex(MetaData md) { return 0; }
\r
2181 internal uint GetSize() { return size; }
\r
2183 internal byte GetTypeIndex() { return type.GetTypeIndex(); }
\r
2185 internal virtual void Write(BinaryWriter bw) { }
\r
2189 /// Descriptor for a constant value
\r
2191 public abstract class DataConstant : Constant {
\r
2192 private uint dataOffset = 0;
\r
2194 internal DataConstant() { }
\r
2196 public uint DataOffset {
\r
2197 get { return dataOffset; }
\r
2198 set { dataOffset = value; }
\r
2204 /// Boolean constant
\r
2206 public class BoolConst : Constant {
\r
2210 /// Create a new boolean constant with the value "val"
\r
2212 /// <param name="val">value of this boolean constant</param>
\r
2213 public BoolConst(bool val) {
\r
2216 type = PrimitiveType.Boolean;
\r
2219 internal sealed override uint GetBlobIndex(MetaData md) {
\r
2220 if (!addedToBlobHeap) {
\r
2221 if (val) blobIndex = md.AddToBlobHeap((sbyte)1);
\r
2222 else blobIndex = md.AddToBlobHeap((sbyte)0);
\r
2223 addedToBlobHeap = true;
\r
2228 internal sealed override void Write(BinaryWriter bw) {
\r
2229 if (val) bw.Write((sbyte)1);
\r
2230 else bw.Write((sbyte)0);
\r
2235 public class ByteArrConst : DataConstant {
\r
2238 public ByteArrConst(byte[] val) {
\r
2240 size = (uint)val.Length;
\r
2243 internal sealed override uint GetBlobIndex(MetaData md) {
\r
2244 if (!addedToBlobHeap) {
\r
2245 blobIndex = md.AddToBlobHeap(val);
\r
2246 addedToBlobHeap = true;
\r
2251 internal sealed override void Write(BinaryWriter bw) {
\r
2257 public class CharConst : Constant {
\r
2260 public CharConst(char val) {
\r
2263 type = PrimitiveType.Char;
\r
2266 internal sealed override uint GetBlobIndex(MetaData md) {
\r
2267 if (!addedToBlobHeap) {
\r
2268 blobIndex = md.AddToBlobHeap(val);
\r
2269 addedToBlobHeap = true;
\r
2274 internal sealed override void Write(BinaryWriter bw) {
\r
2280 public class FloatConst : DataConstant {
\r
2283 public FloatConst(float val) {
\r
2286 type = PrimitiveType.Float32;
\r
2289 internal sealed override uint GetBlobIndex(MetaData md) {
\r
2290 if (!addedToBlobHeap) {
\r
2291 blobIndex = md.AddToBlobHeap(val);
\r
2292 addedToBlobHeap = true;
\r
2297 internal sealed override void Write(BinaryWriter bw) {
\r
2303 public class DoubleConst : DataConstant {
\r
2306 public DoubleConst(double val) {
\r
2309 type = PrimitiveType.Float64;
\r
2312 internal sealed override uint GetBlobIndex(MetaData md) {
\r
2313 if (!addedToBlobHeap) {
\r
2314 blobIndex = md.AddToBlobHeap(val);
\r
2315 addedToBlobHeap = true;
\r
2320 internal sealed override void Write(BinaryWriter bw) {
\r
2326 public class IntConst : DataConstant {
\r
2329 public IntConst(sbyte val) {
\r
2332 type = PrimitiveType.Int8;
\r
2335 public IntConst(short val) {
\r
2338 type = PrimitiveType.Int16;
\r
2341 public IntConst(int val) {
\r
2344 type = PrimitiveType.Int32;
\r
2347 public IntConst(long val) {
\r
2350 type = PrimitiveType.Int64;
\r
2353 internal sealed override uint GetBlobIndex(MetaData md) {
\r
2354 if (!addedToBlobHeap) {
\r
2356 case (1) : blobIndex = md.AddToBlobHeap((sbyte)val); break;
\r
2357 case (2) : blobIndex = md.AddToBlobHeap((short)val); break;
\r
2358 case (4) : blobIndex = md.AddToBlobHeap((int)val); break;
\r
2359 default : blobIndex = md.AddToBlobHeap(val); break;
\r
2361 addedToBlobHeap = true;
\r
2366 internal sealed override void Write(BinaryWriter bw) {
\r
2368 case (1) : bw.Write((sbyte)val); break;
\r
2369 case (2) : bw.Write((short)val); break;
\r
2370 case (4) : bw.Write((int)val); break;
\r
2371 default : bw.Write(val); break;
\r
2377 public class UIntConst : Constant {
\r
2380 public UIntConst(sbyte val) {
\r
2383 type = PrimitiveType.UInt8;
\r
2385 public UIntConst(short val) {
\r
2388 type = PrimitiveType.UInt16;
\r
2390 public UIntConst(int val) {
\r
2393 type = PrimitiveType.UInt32;
\r
2395 public UIntConst(long val) {
\r
2398 type = PrimitiveType.UInt64;
\r
2401 internal sealed override uint GetBlobIndex(MetaData md) {
\r
2402 if (!addedToBlobHeap) {
\r
2404 case (1) : blobIndex = md.AddToBlobHeap((sbyte)val); break;
\r
2405 case (2) : blobIndex = md.AddToBlobHeap((short)val); break;
\r
2406 case (4) : blobIndex = md.AddToBlobHeap((int)val); break;
\r
2407 default : blobIndex = md.AddToBlobHeap(val); break;
\r
2409 addedToBlobHeap = true;
\r
2414 internal sealed override void Write(BinaryWriter bw) {
\r
2416 case (1) : bw.Write((sbyte)val); break;
\r
2417 case (2) : bw.Write((short)val); break;
\r
2418 case (4) : bw.Write((int)val); break;
\r
2419 default : bw.Write(val); break;
\r
2425 public class StringConst : DataConstant {
\r
2428 public StringConst(string val) {
\r
2430 size = (uint)val.Length; // need to add null ??
\r
2431 type = PrimitiveType.String;
\r
2434 internal sealed override uint GetBlobIndex(MetaData md) {
\r
2435 if (!addedToBlobHeap) {
\r
2436 blobIndex = md.AddToBlobHeap(val);
\r
2437 addedToBlobHeap = true;
\r
2442 internal sealed override void Write(BinaryWriter bw) {
\r
2448 public class NullConst : Constant {
\r
2450 public NullConst() {
\r
2452 type = PrimitiveType.Class;
\r
2455 internal sealed override uint GetBlobIndex(MetaData md) {
\r
2456 if (!addedToBlobHeap) {
\r
2457 blobIndex = md.AddToBlobHeap((int)0);
\r
2458 addedToBlobHeap = true;
\r
2463 internal sealed override void Write(BinaryWriter bw) {
\r
2464 bw.Write((int)0);
\r
2469 public class AddressConstant : DataConstant {
\r
2470 DataConstant data;
\r
2472 public AddressConstant(DataConstant dConst) {
\r
2475 type = PrimitiveType.TypedRef;
\r
2478 internal sealed override void Write(BinaryWriter bw) {
\r
2479 ((FileImage)bw).WriteDataRVA(data.DataOffset);
\r
2484 public class RepeatedConstant : DataConstant {
\r
2485 DataConstant data;
\r
2488 public RepeatedConstant(DataConstant dConst, int repeatCount) {
\r
2490 repCount = (uint)repeatCount;
\r
2491 int[] sizes = new int[1];
\r
2492 sizes[0] = repeatCount;
\r
2493 type = new BoundArray(type,1,sizes);
\r
2494 size = data.GetSize() * repCount;
\r
2497 internal sealed override void Write(BinaryWriter bw) {
\r
2498 for (int i=0; i < repCount; i++) {
\r
2505 public class ArrayConstant : DataConstant {
\r
2506 DataConstant[] dataVals;
\r
2508 public ArrayConstant(DataConstant[] dVals) {
\r
2510 for (int i=0; i < dataVals.Length; i++) {
\r
2511 size += dataVals[i].GetSize();
\r
2515 internal sealed override void Write(BinaryWriter bw) {
\r
2516 for (int i=0; i < dataVals.Length; i++) {
\r
2517 dataVals[i].Write(bw);
\r
2523 public class ClassType : Constant {
\r
2527 public ClassType(string className) {
\r
2529 type = PrimitiveType.ClassType;
\r
2532 public ClassType(Class classDesc) {
\r
2534 type = PrimitiveType.ClassType;
\r
2537 internal override void Write(BinaryWriter bw) {
\r
2538 if (name == null) name = desc.TypeName();
\r
2546 /**************************************************************************/
\r
2548 /// Summary description for ConstantElem.
\r
2550 internal class ConstantElem : MetaDataElement
\r
2552 MetaDataElement parent;
\r
2556 internal ConstantElem(MetaDataElement parent, Constant val) {
\r
2557 this.parent = parent;
\r
2559 tabIx = MDTable.Constant;
\r
2562 internal sealed override void BuildTables(MetaData md) {
\r
2564 valIx = cValue.GetBlobIndex(md);
\r
2568 internal void AddToBlob(BinaryWriter bw) {
\r
2572 internal sealed override uint Size(MetaData md) {
\r
2573 return 2 + md.CodedIndexSize(CIx.HasConst) + md.BlobIndexSize();
\r
2576 internal sealed override void Write(FileImage output) {
\r
2577 output.Write(cValue.GetTypeIndex());
\r
2578 output.Write((byte)0);
\r
2579 output.WriteCodedIndex(CIx.HasConst,parent);
\r
2580 output.BlobIndex(valIx);
\r
2584 /**************************************************************************/
\r
2586 /// Descriptor for a Custom Attribute (.custom)
\r
2589 public class CustomAttribute : MetaDataElement
\r
2591 private static readonly ushort prolog = 0x0001;
\r
2592 MetaDataElement parent;
\r
2597 ushort numNamed = 0;
\r
2598 ArrayList names, vals;
\r
2600 internal CustomAttribute(MetaDataElement paren, Method constrType,
\r
2603 type = constrType;
\r
2605 tabIx = MDTable.CustomAttribute;
\r
2606 throw(new NotYetImplementedException("Custom Attributes "));
\r
2609 internal CustomAttribute(MetaDataElement paren, Method constrType,
\r
2612 type = constrType;
\r
2613 tabIx = MDTable.CustomAttribute;
\r
2617 public void AddFieldOrProp(string name, Constant val) {
\r
2618 if (numNamed == 0) {
\r
2619 names = new ArrayList();
\r
2620 vals = new ArrayList();
\r
2626 internal sealed override void BuildTables(MetaData md) {
\r
2627 BinaryWriter bw = new BinaryWriter(new MemoryStream());
\r
2628 bw.Write((ushort)1);
\r
2629 md.AddToTable(MDTable.CustomAttribute, this);
\r
2630 MemoryStream str = (MemoryStream)bw.BaseStream;
\r
2631 valIx = md.AddToBlobHeap(str.ToArray());
\r
2634 internal sealed override uint Size(MetaData md) {
\r
2635 return md.CodedIndexSize(CIx.HasCustomAttr) + md.CodedIndexSize(CIx.CustomAttributeType) + md.BlobIndexSize();
\r
2638 internal sealed override void Write(FileImage output) {
\r
2639 output.WriteCodedIndex(CIx.HasCustomAttr,parent);
\r
2640 output.WriteCodedIndex(CIx.CustomAttributeType,type);
\r
2641 output.BlobIndex(valIx);
\r
2645 /**************************************************************************/
\r
2647 /// Descriptor for a custom modifier of a type (modopt or modreq)
\r
2650 public class CustomModifiedType : Type
\r
2656 /// Create a new custom modifier for a type
\r
2658 /// <param name="type">the type to be modified</param>
\r
2659 /// <param name="cmod">the modifier</param>
\r
2660 /// <param name="cmodType">the type reference to be associated with the type</param>
\r
2661 public CustomModifiedType(Type type, CustomModifier cmod, Class cmodType)
\r
2662 : base((byte)cmod) {
\r
2664 this.cmodType = cmodType;
\r
2667 internal sealed override void TypeSig(MemoryStream str) {
\r
2668 str.WriteByte(typeIndex);
\r
2669 MetaData.CompressNum(cmodType.TypeDefOrRefToken(),str);
\r
2670 type.TypeSig(str);
\r
2674 /**************************************************************************/
\r
2676 /// Descriptor for security permissions for a class or a method NOT YET IMPLEMENTED
\r
2679 public class DeclSecurity : MetaDataElement
\r
2682 MetaDataElement parent;
\r
2683 uint permissionIx;
\r
2685 internal DeclSecurity(MetaDataElement paren, ushort act) {
\r
2688 tabIx = MDTable.DeclSecurity;
\r
2689 throw(new NotYetImplementedException("Security "));
\r
2692 internal sealed override uint Size(MetaData md) {
\r
2693 return 2 + md.CodedIndexSize(CIx.HasDeclSecurity) + md.BlobIndexSize();
\r
2696 internal sealed override void BuildTables(MetaData md) {
\r
2698 // add permission to blob heap
\r
2702 internal sealed override void Write(FileImage output) {
\r
2703 output.Write(action);
\r
2704 output.WriteCodedIndex(CIx.HasDeclSecurity,parent);
\r
2705 output.BlobIndex(permissionIx);
\r
2709 /**************************************************************************/
\r
2711 /// Descriptor for an event
\r
2713 public class Event : Feature
\r
2717 internal Event(string name, Type eType, ClassDef parent)
\r
2718 : base(name, parent) {
\r
2719 eventType = eType;
\r
2720 tabIx = MDTable.Event;
\r
2724 /// Add the addon method to this event
\r
2726 /// <param name="addon">the addon method</param>
\r
2727 public void AddAddon(MethodDef addon) {
\r
2728 AddMethod(addon,MethodType.AddOn);
\r
2732 /// Add the removeon method to this event
\r
2734 /// <param name="removeOn">the removeon method</param>
\r
2735 public void AddRemoveOn(MethodDef removeOn) {
\r
2736 AddMethod(removeOn,MethodType.RemoveOn);
\r
2740 /// Add the fire method to this event
\r
2742 /// <param name="fire">the fire method</param>
\r
2743 public void AddFire(MethodDef fire) {
\r
2744 AddMethod(fire,MethodType.Fire);
\r
2748 /// Add another method to this event
\r
2750 /// <param name="other">the method to be added</param>
\r
2751 public void AddOther(MethodDef other) {
\r
2752 AddMethod(other,MethodType.Other);
\r
2755 internal sealed override void BuildTables(MetaData md) {
\r
2757 nameIx = md.AddToStringsHeap(name);
\r
2758 for (int i=0; i < tide; i++) {
\r
2759 md.AddToTable(MDTable.MethodSemantics,methods[i]);
\r
2764 internal sealed override uint Size(MetaData md) {
\r
2765 return 2 + md.StringsIndexSize() + md.CodedIndexSize(CIx.TypeDefOrRef);
\r
2768 internal sealed override void Write(FileImage output) {
\r
2769 output.Write(flags);
\r
2770 output.StringsIndex(nameIx);
\r
2771 output.WriteCodedIndex(CIx.TypeDefOrRef,eventType);
\r
2774 internal sealed override uint GetCodedIx(CIx code) {
\r
2776 case (CIx.HasCustomAttr) : return 10;
\r
2777 case (CIx.HasSemantics) : return 0;
\r
2783 /**************************************************************************/
\r
2785 /// Descriptor for a class defined in another module of THIS assembly
\r
2786 /// and exported (.class extern)
\r
2789 internal class ExternClass : Class
\r
2791 MetaDataElement parent;
\r
2794 internal ExternClass(TypeAttr attr, uint nsIx, uint nIx,
\r
2795 MetaDataElement paren) : base(nsIx,nIx) {
\r
2796 flags = (uint)attr;
\r
2798 tabIx = MDTable.ExportedType;
\r
2801 internal sealed override uint Size(MetaData md) {
\r
2802 return 8 + 2* md.StringsIndexSize() + md.CodedIndexSize(CIx.Implementation);
\r
2805 internal sealed override void Write(FileImage output) {
\r
2806 output.Write(flags);
\r
2808 output.StringsIndex(nameIx);
\r
2809 output.StringsIndex(nameSpaceIx);
\r
2810 output.WriteCodedIndex(CIx.Implementation,parent);
\r
2813 internal sealed override uint GetCodedIx(CIx code) {
\r
2815 case (CIx.HasCustomAttr) : return 17;
\r
2816 case (CIx.Implementation) : return 2;
\r
2822 /**************************************************************************/
\r
2824 /// Base class for Event and Property descriptors
\r
2827 public class Feature : MetaDataElement
\r
2829 internal enum MethodType : ushort { Setter = 0x01, Getter, Other = 0x04, AddOn = 0x08,
\r
2830 RemoveOn = 0x10, Fire = 0x20 }
\r
2832 private static readonly int INITSIZE = 5;
\r
2833 private static readonly ushort specialName = 0x200;
\r
2834 private static readonly ushort rtSpecialName = 0x400;
\r
2836 protected ClassDef parent;
\r
2837 protected ushort flags = 0;
\r
2838 protected string name;
\r
2839 protected int tide = 0;
\r
2840 protected uint nameIx;
\r
2841 protected MethodSemantics[] methods = new MethodSemantics[INITSIZE];
\r
2843 internal Feature(string name, ClassDef par) {
\r
2848 internal void AddMethod(MethodDef meth, MethodType mType) {
\r
2849 if (tide >= methods.Length) {
\r
2850 int len = methods.Length;
\r
2851 MethodSemantics[] mTmp = methods;
\r
2852 methods = new MethodSemantics[len * 2];
\r
2853 for (int i=0; i < len; i++) {
\r
2854 methods[i] = mTmp[i];
\r
2857 methods[tide++] = new MethodSemantics(mType,meth,this);
\r
2861 /// Set the specialName attribute for this Event or Property
\r
2863 public void SetSpecialName() {
\r
2864 flags |= specialName;
\r
2868 /// Set the RTSpecialName attribute for this Event or Property
\r
2870 public void SetRTSpecialName() {
\r
2871 flags |= rtSpecialName;
\r
2875 /*****************************************************************************/
\r
2877 /// Descriptor for a field of a class
\r
2880 public abstract class Field : Member
\r
2882 protected static readonly byte FieldSig = 0x6;
\r
2884 protected Type type;
\r
2886 internal Field(string pfName, Type pfType) : base(pfName)
\r
2892 /**************************************************************************/
\r
2894 /// Descriptor for a field defined in a class of THIS assembly/module
\r
2896 public class FieldDef : Field
\r
2898 //private static readonly uint PInvokeImpl = 0x2000;
\r
2899 private static readonly ushort HasFieldMarshal = 0x1000;
\r
2900 private static readonly ushort HasFieldRVA = 0x100;
\r
2903 ConstantElem constVal;
\r
2904 FieldLayout layout;
\r
2905 FieldMarshal marshalInfo;
\r
2908 internal FieldDef(string name, Type fType) : base(name,fType) {
\r
2909 tabIx = MDTable.Field;
\r
2912 internal FieldDef(FieldAttr attrSet, string name, Type fType) : base(name, fType) {
\r
2913 flags = (ushort)attrSet;
\r
2914 tabIx = MDTable.Field;
\r
2918 /// Add an attribute(s) to this field
\r
2920 /// <param name="fa">the attribute(s) to be added</param>
\r
2921 public void AddFieldAttr(FieldAttr fa) {
\r
2922 flags |= (ushort)fa;
\r
2926 /// Add a value for this field
\r
2928 /// <param name="val">the value for the field</param>
\r
2929 public void AddValue(Constant val) {
\r
2930 constVal = new ConstantElem(this,val);
\r
2934 /// Add an initial value for this field (at dataLabel) (.data)
\r
2936 /// <param name="val">the value for the field</param>
\r
2937 /// <param name="repeatVal">the number of repetitions of this value</param>
\r
2938 public void AddDataValue(DataConstant val) {
\r
2939 flags |= HasFieldRVA;
\r
2940 rva = new FieldRVA(this,val);
\r
2944 /// Set the offset of the field. Used for sequential or explicit classes.
\r
2945 /// (.field [offs])
\r
2947 /// <param name="offs">field offset</param>
\r
2948 public void SetOffset(uint offs) {
\r
2949 layout = new FieldLayout(this,offs);
\r
2953 /// Set the marshalling info for a field
\r
2955 /// <param name="mInf"></param>
\r
2956 public void SetMarshalInfo(NativeType marshallType) {
\r
2957 flags |= HasFieldMarshal;
\r
2958 marshalInfo = new FieldMarshal(this,marshallType);
\r
2961 internal sealed override void BuildTables(MetaData md) {
\r
2963 nameIx = md.AddToStringsHeap(name);
\r
2964 MemoryStream sig = new MemoryStream();
\r
2965 sig.WriteByte(FieldSig);
\r
2966 type.TypeSig(sig);
\r
2967 sigIx = md.AddToBlobHeap(sig.ToArray());
\r
2968 if (rva != null) {
\r
2969 md.AddToTable(MDTable.FieldRVA,rva);
\r
2970 rva.BuildTables(md);
\r
2971 } else if (constVal != null) {
\r
2972 md.AddToTable(MDTable.Constant,constVal);
\r
2973 constVal.BuildTables(md);
\r
2975 if (layout != null) md.AddToTable(MDTable.FieldLayout,layout);
\r
2976 if (marshalInfo != null) {
\r
2977 md.AddToTable(MDTable.FieldMarshal,marshalInfo);
\r
2978 marshalInfo.BuildTables(md);
\r
2983 internal sealed override uint Size(MetaData md) {
\r
2984 return 2 + md.StringsIndexSize() + md.BlobIndexSize();
\r
2987 internal sealed override void Write(FileImage output) {
\r
2988 output.Write(flags);
\r
2989 output.StringsIndex(nameIx);
\r
2990 output.BlobIndex(sigIx);
\r
2993 internal sealed override uint GetCodedIx(CIx code) {
\r
2995 case (CIx.HasConst) : return 0;
\r
2996 case (CIx.HasCustomAttr) : return 1;
\r
2997 case (CIx.HasFieldMarshal) : return 0;
\r
2998 case (CIx.MemberForwarded) : return 0;
\r
3004 /**************************************************************************/
\r
3006 /// Descriptor for layout information for a field
\r
3009 public class FieldLayout : MetaDataElement
\r
3014 internal FieldLayout(Field field, uint offset) {
\r
3015 this.field = field;
\r
3016 this.offset = offset;
\r
3017 tabIx = MDTable.FieldLayout;
\r
3020 internal sealed override uint Size(MetaData md) {
\r
3021 return 4 + md.TableIndexSize(MDTable.Field);
\r
3024 internal sealed override void Write(FileImage output) {
\r
3025 output.Write(offset);
\r
3026 output.WriteIndex(MDTable.Field,field.Row);
\r
3030 /*****************************************************************************/
\r
3032 /// Marshalling information for a field or param
\r
3034 public class FieldMarshal : MetaDataElement
\r
3036 MetaDataElement field;
\r
3040 internal FieldMarshal(MetaDataElement field, NativeType nType) {
\r
3041 this.field = field;
\r
3043 tabIx = MDTable.FieldMarshal;
\r
3046 internal sealed override void BuildTables(MetaData md) {
\r
3048 ntIx = md.AddToBlobHeap(nt.ToBlob());
\r
3052 internal sealed override uint Size(MetaData md) {
\r
3053 return md.CodedIndexSize(CIx.HasFieldMarshal) + md.BlobIndexSize();
\r
3056 internal sealed override void Write(FileImage output) {
\r
3057 output.WriteCodedIndex(CIx.HasFieldMarshal,field);
\r
3058 output.BlobIndex(ntIx);
\r
3062 /**************************************************************************/
\r
3064 /// Descriptor for a field of a class defined in another assembly/module
\r
3066 public class FieldRef : Field
\r
3068 MetaDataElement parent;
\r
3070 internal FieldRef(MetaDataElement paren, string name, Type fType) : base(name, fType) {
\r
3074 internal sealed override void BuildTables(MetaData md) {
\r
3076 nameIx = md.AddToStringsHeap(name);
\r
3077 MemoryStream sig = new MemoryStream();
\r
3078 sig.WriteByte(FieldSig);
\r
3079 type.TypeSig(sig);
\r
3080 sigIx = md.AddToBlobHeap(sig.ToArray());
\r
3084 internal sealed override uint Size(MetaData md) {
\r
3085 return md.CodedIndexSize(CIx.MemberRefParent) + md.StringsIndexSize() + md.BlobIndexSize();
\r
3088 internal sealed override void Write(FileImage output) {
\r
3089 output.WriteCodedIndex(CIx.MemberRefParent,parent);
\r
3090 output.StringsIndex(nameIx);
\r
3091 output.BlobIndex(sigIx);
\r
3094 internal sealed override uint GetCodedIx(CIx code) { return 6; }
\r
3097 /**************************************************************************/
\r
3099 /// Descriptor for the address of a field's value in the PE file
\r
3101 public class FieldRVA : MetaDataElement
\r
3104 DataConstant data;
\r
3106 internal FieldRVA(Field field, DataConstant data) {
\r
3107 this.field = field;
\r
3109 tabIx = MDTable.FieldRVA;
\r
3112 internal sealed override void BuildTables(MetaData md) {
\r
3118 internal sealed override uint Size(MetaData md) {
\r
3119 return 4 + md.TableIndexSize(MDTable.Field);
\r
3122 internal sealed override void Write(FileImage output) {
\r
3123 output.WriteDataRVA(data.DataOffset);
\r
3124 output.WriteIndex(MDTable.Field,field.Row);
\r
3128 /**************************************************************************/
\r
3130 /// Image for a PEFile
\r
3131 /// File Structure
\r
3132 /// DOS Header (128 bytes)
\r
3133 /// PE Signature ("PE\0\0")
\r
3134 /// PEFileHeader (20 bytes)
\r
3135 /// PEOptionalHeader (224 bytes)
\r
3136 /// SectionHeaders (40 bytes * NumSections)
\r
3138 /// Sections .text (always present - contains metadata)
\r
3139 /// .sdata (contains any initialised data in the file - may not be present)
\r
3140 /// (for ilams /debug this contains the Debug table)
\r
3141 /// .reloc (always present - in pure CIL only has one fixup)
\r
3142 /// others??? c# produces .rsrc section containing a Resource Table
\r
3145 /// IAT (single entry 8 bytes for pure CIL)
\r
3146 /// CLIHeader (72 bytes)
\r
3147 /// CIL instructions for all methods (variable size)
\r
3149 /// Root (20 bytes + UTF-8 Version String + quad align padding)
\r
3150 /// StreamHeaders (8 bytes + null terminated name string + quad align padding)
\r
3152 /// #~ (always present - holds metadata tables)
\r
3153 /// #Strings (always present - holds identifier strings)
\r
3154 /// #US (Userstring heap)
\r
3155 /// #Blob (signature blobs)
\r
3156 /// #GUID (guids for assemblies or Modules)
\r
3157 /// ImportTable (40 bytes)
\r
3158 /// ImportLookupTable(8 bytes) (same as IAT for standard CIL files)
\r
3159 /// Hint/Name Tables with entry "_CorExeMain" for .exe file and "_CorDllMain" for .dll (14 bytes)
\r
3160 /// ASCII string "mscoree.dll" referenced in ImportTable (+ padding = 16 bytes)
\r
3161 /// Entry Point (0xFF25 followed by 4 bytes 0x400000 + RVA of .text)
\r
3163 /// #~ stream structure
\r
3164 /// Header (24 bytes)
\r
3165 /// Rows (4 bytes * numTables)
\r
3168 internal class FileImage : BinaryWriter
\r
3170 internal readonly static uint[] iByteMask = {0x000000FF, 0x0000FF00, 0x00FF0000, 0xFF000000};
\r
3171 internal readonly static ulong[] lByteMask = {0x00000000000000FF, 0x000000000000FF00,
\r
3172 0x0000000000FF0000, 0x00000000FF000000,
\r
3173 0x000000FF00000000, 0x0000FF0000000000,
\r
3174 0x00FF000000000000, 0xFF00000000000000 };
\r
3175 internal readonly static uint nibble0Mask = 0x0000000F;
\r
3176 internal readonly static uint nibble1Mask = 0x000000F0;
\r
3178 private static readonly byte[] DOSHeader = { 0x4d,0x5a,0x90,0x00,0x03,0x00,0x00,0x00,
\r
3179 0x04,0x00,0x00,0x00,0xff,0xff,0x00,0x00,
\r
3180 0xb8,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
\r
3181 0x40,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
\r
3182 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
\r
3183 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
\r
3184 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
\r
3185 0x00,0x00,0x00,0x00,0x80,0x00,0x00,0x00,
\r
3186 0x0e,0x1f,0xba,0x0e,0x00,0xb4,0x09,0xcd,
\r
3187 0x21,0xb8,0x01,0x4c,0xcd,0x21,0x54,0x68,
\r
3188 0x69,0x73,0x20,0x70,0x72,0x6f,0x67,0x72,
\r
3189 0x61,0x6d,0x20,0x63,0x61,0x6e,0x6e,0x6f,
\r
3190 0x74,0x20,0x62,0x65,0x20,0x72,0x75,0x6e,
\r
3191 0x20,0x69,0x6e,0x20,0x44,0x4f,0x53,0x20,
\r
3192 0x6d,0x6f,0x64,0x65,0x2e,0x0d,0x0d,0x0a,
\r
3193 0x24,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
\r
3194 0x50,0x45,0x00,0x00};
\r
3195 private static byte[] PEHeader = { 0x4c, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
\r
3196 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
\r
3197 0xE0, 0x00, 0x0E, 0x01, // PE Header Standard Fields
\r
3198 0x0B, 0x01, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00,
\r
3199 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
\r
3200 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
\r
3203 private static readonly uint minFileAlign = 0x200;
\r
3204 private static readonly uint maxFileAlign = 0x1000;
\r
3205 private static readonly uint fileHeaderSize = 0x178;
\r
3206 private static readonly uint sectionHeaderSize = 40;
\r
3207 private static readonly uint SectionAlignment = 0x2000;
\r
3208 private static readonly uint ImageBase = 0x400000;
\r
3209 private static readonly uint ImportTableSize = 40;
\r
3210 private static readonly uint IATSize = 8;
\r
3211 private static readonly uint CLIHeaderSize = 72;
\r
3212 private uint runtimeFlags = 0x01; // COMIMAGE_FLAGS_ILONLY
\r
3213 // 32BITREQUIRED 0x02, STRONGNAMESIGNED 0x08, TRACKDEBUGDATA 0x10000
\r
3214 private static readonly uint relocFlags = 0x42000040;
\r
3215 private static readonly ushort exeCharacteristics = 0x010E;
\r
3216 private static readonly ushort dllCharacteristics = 0x210E;
\r
3217 // section names are all 8 bytes
\r
3218 private static readonly string textName = ".text\0\0\0";
\r
3219 private static readonly string sdataName = ".sdata\0\0";
\r
3220 private static readonly string relocName = ".reloc\0\0";
\r
3221 private static readonly string rsrcName = ".rsrc\0\0\0";
\r
3222 private static readonly string exeHintNameTable = "\0\0_CorExeMain\0";
\r
3223 private static readonly string dllHintNameTable = "\0\0_CorDllMain\0";
\r
3224 private static readonly string runtimeEngineName = "mscoree.dll\0\0";
\r
3226 private Section text, sdata, rsrc;
\r
3228 BinaryWriter reloc = new BinaryWriter(new MemoryStream());
\r
3229 uint dateStamp = 0;
\r
3230 DateTime origin = new DateTime(1970,1,1);
\r
3231 uint numSections = 2; // always have .text and .reloc sections
\r
3232 internal SubSystem subSys = SubSystem.Windows_CUI; // default is Windows Console mode
\r
3233 internal uint fileAlign = minFileAlign;
\r
3234 uint entryPointOffset, entryPointPadding, imageSize, headerSize, headerPadding, entryPointToken = 0;
\r
3235 uint relocOffset, relocRVA, relocSize, relocPadding, relocTide, hintNameTableOffset;
\r
3236 uint metaDataOffset, runtimeEngineOffset, initDataSize = 0, importTablePadding;
\r
3237 uint importTableOffset, importLookupTableOffset, totalImportTableSize;
\r
3238 MetaData metaData;
\r
3239 char[] runtimeEngine = runtimeEngineName.ToCharArray(), hintNameTable;
\r
3240 bool doDLL, largeStrings, largeGUID, largeUS, largeBlob;
\r
3241 ushort characteristics;
\r
3243 internal FileImage(bool makeDLL, string fileName) : base(new FileStream(fileName,FileMode.Create)) {
\r
3244 InitFileImage(makeDLL);
\r
3245 TimeSpan tmp = System.IO.File.GetCreationTime(fileName).Subtract(origin);
\r
3246 dateStamp = Convert.ToUInt32(tmp.TotalSeconds);
\r
3249 internal FileImage(bool makeDLL, Stream str) : base(str) {
\r
3250 InitFileImage(makeDLL);
\r
3251 TimeSpan tmp = DateTime.Now.Subtract(origin);
\r
3252 dateStamp = Convert.ToUInt32(tmp.TotalSeconds);
\r
3255 private void InitFileImage(bool makeDLL) {
\r
3258 hintNameTable = dllHintNameTable.ToCharArray();
\r
3259 characteristics = dllCharacteristics;
\r
3261 hintNameTable = exeHintNameTable.ToCharArray();
\r
3262 characteristics = exeCharacteristics;
\r
3264 text = new Section(textName,0x60000020); // IMAGE_SCN_CNT CODE, EXECUTE, READ
\r
3265 // rsrc = new Section(rsrcName,0x40000040); // IMAGE_SCN_CNT INITIALIZED_DATA, READ
\r
3266 metaData = new MetaData(this);
\r
3269 internal MetaData GetMetaData() {
\r
3273 private uint GetNextSectStart(uint rva, uint tide) {
\r
3274 if (tide < SectionAlignment) return rva + SectionAlignment;
\r
3275 return rva + ((tide / SectionAlignment) + 1) * SectionAlignment;
\r
3278 private void BuildTextSection() {
\r
3280 // IAT (single entry 8 bytes for pure CIL)
\r
3281 // CLIHeader (72 bytes)
\r
3282 // CIL instructions for all methods (variable size)
\r
3284 // ImportTable (40 bytes)
\r
3285 // ImportLookupTable(8 bytes) (same as IAT for standard CIL files)
\r
3286 // Hint/Name Tables with entry "_CorExeMain" for .exe file and "_CorDllMain" for .dll (14 bytes)
\r
3287 // ASCII string "mscoree.dll" referenced in ImportTable (+ padding = 16 bytes)
\r
3288 // Entry Point (0xFF25 followed by 4 bytes 0x400000 + RVA of .text)
\r
3289 metaData.BuildMetaData(IATSize + CLIHeaderSize);
\r
3290 metaDataOffset = IATSize + CLIHeaderSize;
\r
3291 // Console.WriteLine("Code starts at " + metaDataOffset);
\r
3292 metaDataOffset += metaData.CodeSize();
\r
3293 // resourcesStart =
\r
3294 // strongNameSig = metaData.GetStrongNameSig();
\r
3295 // fixUps = RVA for vtable
\r
3296 importTableOffset = metaDataOffset + metaData.Size();
\r
3297 importTablePadding = NumToAlign(importTableOffset,16);
\r
3298 importTableOffset += importTablePadding;
\r
3299 importLookupTableOffset = importTableOffset + ImportTableSize;
\r
3300 hintNameTableOffset = importLookupTableOffset + IATSize;
\r
3301 runtimeEngineOffset = hintNameTableOffset + (uint)hintNameTable.Length;
\r
3302 entryPointOffset = runtimeEngineOffset + (uint)runtimeEngine.Length;
\r
3303 totalImportTableSize = entryPointOffset - importTableOffset;
\r
3304 // Console.WriteLine("total import table size = " + totalImportTableSize);
\r
3305 // Console.WriteLine("entrypoint offset = " + entryPointOffset);
\r
3306 entryPointPadding = NumToAlign(entryPointOffset,4) + 2;
\r
3307 entryPointOffset += entryPointPadding;
\r
3308 text.AddReloc(entryPointOffset+2);
\r
3309 text.IncTide(entryPointOffset + 6);
\r
3310 //if (text.Tide() < fileAlign) fileAlign = minFileAlign;
\r
3311 text.SetSize(NumToAlign(text.Tide(),fileAlign));
\r
3312 // Console.WriteLine("text size = " + text.Size() + " text tide = " + text.Tide() + " text padding = " + text.Padding());
\r
3313 // Console.WriteLine("metaDataOffset = " + Hex.Int(metaDataOffset));
\r
3314 // Console.WriteLine("importTableOffset = " + Hex.Int(importTableOffset));
\r
3315 // Console.WriteLine("importLookupTableOffset = " + Hex.Int(importLookupTableOffset));
\r
3316 // Console.WriteLine("hintNameTableOffset = " + Hex.Int(hintNameTableOffset));
\r
3317 // Console.WriteLine("runtimeEngineOffset = " + Hex.Int(runtimeEngineOffset));
\r
3318 // Console.WriteLine("entryPointOffset = " + Hex.Int(entryPointOffset));
\r
3319 // Console.WriteLine("entryPointPadding = " + Hex.Int(entryPointPadding));
\r
3323 internal void BuildRelocSection() {
\r
3324 text.DoRelocs(reloc);
\r
3325 if (sdata != null) sdata.DoRelocs(reloc);
\r
3326 if (rsrc != null) rsrc.DoRelocs(reloc);
\r
3327 relocTide = (uint)reloc.Seek(0,SeekOrigin.Current);
\r
3328 relocPadding = NumToAlign(relocTide,fileAlign);
\r
3329 relocSize = relocTide + relocPadding;
\r
3330 imageSize = relocRVA + SectionAlignment;
\r
3331 initDataSize += relocSize;
\r
3334 private void CalcOffsets() {
\r
3335 headerSize = fileHeaderSize + (numSections * sectionHeaderSize);
\r
3336 headerPadding = NumToAlign(headerSize,fileAlign);
\r
3337 headerSize += headerPadding;
\r
3338 uint offset = headerSize;
\r
3339 uint rva = SectionAlignment;
\r
3340 text.SetOffset(offset);
\r
3342 offset += text.Size();
\r
3343 rva = GetNextSectStart(rva,text.Tide());
\r
3344 // Console.WriteLine("headerSize = " + headerSize);
\r
3345 // Console.WriteLine("headerPadding = " + headerPadding);
\r
3346 // Console.WriteLine("textOffset = " + Hex.Int(text.Offset()));
\r
3347 if (sdata != null) {
\r
3349 sdata.SetSize(NumToAlign(sdata.Tide(),fileAlign));
\r
3350 sdata.SetOffset(offset);
\r
3351 sdata.SetRVA(rva);
\r
3352 offset += sdata.Size();
\r
3353 rva = GetNextSectStart(rva,sdata.Tide());
\r
3354 initDataSize += sdata.Size();
\r
3356 if (rsrc != null) {
\r
3358 rsrc.SetSize(NumToAlign(rsrc.Tide(),fileAlign));
\r
3359 rsrc.SetOffset(offset);
\r
3361 offset += rsrc.Size();
\r
3362 rva = GetNextSectStart(rva,rsrc.Tide());
\r
3363 initDataSize += rsrc.Size();
\r
3365 relocOffset = offset;
\r
3369 internal void MakeFile() {
\r
3370 if (doDLL) hintNameTable = dllHintNameTable.ToCharArray();
\r
3371 else hintNameTable = exeHintNameTable.ToCharArray();
\r
3372 BuildTextSection();
\r
3374 BuildRelocSection();
\r
3375 // now write it out
\r
3382 private void WriteHeader() {
\r
3384 // Console.WriteLine("Writing PEHeader at offset " + Seek(0,SeekOrigin.Current));
\r
3386 // Console.WriteLine("Writing text section header at offset " + Hex.Long(Seek(0,SeekOrigin.Current)));
\r
3387 text.WriteHeader(this,relocRVA);
\r
3388 if (sdata != null) sdata.WriteHeader(this,relocRVA);
\r
3389 if (rsrc != null) rsrc.WriteHeader(this,relocRVA);
\r
3390 // Console.WriteLine("Writing reloc section header at offset " + Seek(0,SeekOrigin.Current));
\r
3391 WriteRelocSectionHeader();
\r
3392 // Console.WriteLine("Writing padding at offset " + Seek(0,SeekOrigin.Current));
\r
3393 WriteZeros(headerPadding);
\r
3396 private void WriteSections() {
\r
3397 // Console.WriteLine("Writing text section at offset " + Seek(0,SeekOrigin.Current));
\r
3398 WriteTextSection();
\r
3399 if (sdata != null) WriteSDataSection();
\r
3400 if (rsrc != null) WriteRsrcSection();
\r
3401 WriteRelocSection();
\r
3404 private void WriteIAT() {
\r
3405 Write(text.RVA() + hintNameTableOffset);
\r
3409 private void WriteImportTables() {
\r
3411 WriteZeros(importTablePadding);
\r
3412 // Console.WriteLine("Writing import tables at offset " + Hex.Long(Seek(0,SeekOrigin.Current)));
\r
3413 Write(importLookupTableOffset + text.RVA());
\r
3415 Write(runtimeEngineOffset + text.RVA());
\r
3416 Write(text.RVA()); // IAT is at the beginning of the text section
\r
3418 // Import Lookup Table
\r
3419 WriteIAT(); // lookup table and IAT are the same
\r
3420 // Hint/Name Table
\r
3421 // Console.WriteLine("Writing hintname table at " + Hex.Long(Seek(0,SeekOrigin.Current)));
\r
3422 Write(hintNameTable);
\r
3423 Write(runtimeEngineName.ToCharArray());
\r
3426 private void WriteTextSection() {
\r
3429 // Console.WriteLine("Writing code at " + Hex.Long(Seek(0,SeekOrigin.Current)));
\r
3430 metaData.WriteByteCodes(this);
\r
3431 // Console.WriteLine("Finished writing code at " + Hex.Long(Seek(0,SeekOrigin.Current)));
\r
3432 largeStrings = metaData.LargeStringsIndex();
\r
3433 largeGUID = metaData.LargeGUIDIndex();
\r
3434 largeUS = metaData.LargeUSIndex();
\r
3435 largeBlob = metaData.LargeBlobIndex();
\r
3436 metaData.WriteMetaData(this);
\r
3437 WriteImportTables();
\r
3438 WriteZeros(entryPointPadding);
\r
3439 Write((ushort)0x25FF);
\r
3440 Write(ImageBase + text.RVA());
\r
3441 WriteZeros(text.Padding());
\r
3444 private void WriteCLIHeader() {
\r
3445 Write(CLIHeaderSize); // Cb
\r
3446 Write((short)2); // Major runtime version
\r
3447 Write((short)0); // Minor runtime version
\r
3448 Write(text.RVA() + metaDataOffset);
\r
3449 Write(metaData.Size());
\r
3450 Write(runtimeFlags);
\r
3451 Write(entryPointToken);
\r
3452 WriteZeros(8); // Resources - used by Manifest Resources NYI
\r
3453 WriteZeros(8); // Strong Name stuff here!! NYI
\r
3454 WriteZeros(8); // CodeManagerTable
\r
3455 WriteZeros(8); // VTableFixups NYI
\r
3456 WriteZeros(16); // ExportAddressTableJumps, ManagedNativeHeader
\r
3459 private void WriteSDataSection() {
\r
3460 for (int i=0; i < data.Count; i++) {
\r
3461 ((DataConstant)data[i]).Write(this);
\r
3465 private void WriteRsrcSection() {
\r
3468 private void WriteRelocSection() {
\r
3469 // Console.WriteLine("Writing reloc section at " + Seek(0,SeekOrigin.Current) + " = " + relocOffset);
\r
3470 MemoryStream str = (MemoryStream)reloc.BaseStream;
\r
3471 Write(str.ToArray());
\r
3472 WriteZeros(NumToAlign((uint)str.Position,fileAlign));
\r
3475 internal void SetEntryPoint(uint entryPoint) {
\r
3476 entryPointToken = entryPoint;
\r
3479 internal void AddInitData(DataConstant cVal) {
\r
3480 if (sdata == null) {
\r
3481 sdata = new Section(sdataName,0xC0000040); // IMAGE_SCN_CNT INITIALIZED_DATA, READ, WRITE
\r
3482 data = new ArrayList();
\r
3485 cVal.DataOffset = sdata.Tide();
\r
3486 sdata.IncTide(cVal.GetSize());
\r
3489 internal void WriteZeros(uint numZeros) {
\r
3490 for (int i=0; i < numZeros; i++) {
\r
3495 internal void WritePEHeader() {
\r
3496 Write((ushort)0x014C); // Machine - always 0x14C for Managed PE Files (allow others??)
\r
3497 Write((ushort)numSections);
\r
3499 WriteZeros(8); // Pointer to Symbol Table and Number of Symbols (always zero for ECMA CLI files)
\r
3500 Write((ushort)0x00E0); // Size of Optional Header
\r
3501 Write(characteristics);
\r
3502 // PE Optional Header
\r
3503 Write((ushort)0x010B); // Magic
\r
3504 Write((byte)0x6); // LMajor pure-IL = 6 C++ = 7
\r
3505 Write((byte)0x0); // LMinor
\r
3506 Write(text.Size());
\r
3507 Write(initDataSize);
\r
3508 Write(0); // Check other sections here!!
\r
3509 Write(text.RVA() + entryPointOffset);
\r
3510 Write(text.RVA());
\r
3511 uint dataBase = 0;
\r
3512 if (sdata != null) dataBase = sdata.RVA();
\r
3513 else if (rsrc != null) dataBase = rsrc.RVA();
\r
3514 else dataBase = relocRVA;
\r
3517 Write(SectionAlignment);
\r
3519 Write((ushort)0x04); // OS Major
\r
3520 WriteZeros(6); // OS Minor, User Major, User Minor
\r
3521 Write((ushort)0x04); // SubSys Major
\r
3522 WriteZeros(6); // SybSys Minor, Reserved
\r
3524 Write(headerSize);
\r
3525 Write((int)0); // File Checksum
\r
3526 Write((ushort)subSys);
\r
3527 Write((short)0); // DLL Flags
\r
3528 Write((uint)0x100000); // Stack Reserve Size
\r
3529 Write((uint)0x1000); // Stack Commit Size
\r
3530 Write((uint)0x100000); // Heap Reserve Size
\r
3531 Write((uint)0x1000); // Heap Commit Size
\r
3532 Write(0); // Loader Flags
\r
3533 Write(0x10); // Number of Data Directories
\r
3534 WriteZeros(8); // Export Table
\r
3535 Write(importTableOffset + text.RVA());
\r
3536 Write(totalImportTableSize);
\r
3537 WriteZeros(24); // Resource, Exception and Certificate Tables
\r
3540 WriteZeros(48); // Debug, Copyright, Global Ptr, TLS, Load Config and Bound Import Tables
\r
3541 Write(text.RVA()); // IATRVA - IAT is at start of .text Section
\r
3543 WriteZeros(8); // Delay Import Descriptor
\r
3544 Write(text.RVA()+IATSize); // CLIHeader immediately follows IAT
\r
3545 Write(CLIHeaderSize);
\r
3546 WriteZeros(8); // Reserved
\r
3549 internal void WriteRelocSectionHeader() {
\r
3550 Write(relocName.ToCharArray());
\r
3554 Write(relocOffset);
\r
3556 Write(relocFlags);
\r
3559 private void Align (MemoryStream str, int val) {
\r
3560 if ((str.Position % val) != 0) {
\r
3561 for (int i=val - (int)(str.Position % val); i > 0; i--) {
\r
3567 private uint Align(uint val, uint alignVal) {
\r
3568 if ((val % alignVal) != 0) {
\r
3569 val += alignVal - (val % alignVal);
\r
3574 private uint NumToAlign(uint val, uint alignVal) {
\r
3575 if ((val % alignVal) == 0) return 0;
\r
3576 return alignVal - (val % alignVal);
\r
3579 internal void StringsIndex(uint ix) {
\r
3580 if (largeStrings) Write(ix);
\r
3581 else Write((ushort)ix);
\r
3584 internal void GUIDIndex(uint ix) {
\r
3585 if (largeGUID) Write(ix);
\r
3586 else Write((ushort)ix);
\r
3589 internal void USIndex(uint ix) {
\r
3590 if (largeUS) Write(ix);
\r
3591 else Write((ushort)ix);
\r
3594 internal void BlobIndex(uint ix) {
\r
3595 if (largeBlob) Write(ix);
\r
3596 else Write((ushort)ix);
\r
3599 internal void WriteIndex(MDTable tabIx,uint ix) {
\r
3600 if (metaData.LargeIx(tabIx)) Write(ix);
\r
3601 else Write((ushort)ix);
\r
3604 internal void WriteCodedIndex(CIx code, MetaDataElement elem) {
\r
3605 metaData.WriteCodedIndex(code,elem,this);
\r
3608 internal void WriteCodeRVA(uint offs) {
\r
3609 Write(text.RVA() + offs);
\r
3612 internal void WriteDataRVA(uint offs) {
\r
3613 Write(sdata.RVA() + offs);
\r
3616 internal void Write3Bytes(uint val) {
\r
3617 byte b3 = (byte)((val & FileImage.iByteMask[2]) >> 16);
\r
3618 byte b2 = (byte)((val & FileImage.iByteMask[1]) >> 8);;
\r
3619 byte b1 = (byte)(val & FileImage.iByteMask[0]);
\r
3626 /**************************************************************************/
\r
3628 /// Descriptor for a file referenced in THIS assembly/module (.file)
\r
3630 public class FileRef : MetaDataElement
\r
3632 private static readonly uint HasMetaData = 0x1;
\r
3633 uint nameIx = 0, hashIx = 0;
\r
3636 internal FileRef(string name, byte[] hashBytes, bool metaData,
\r
3637 bool entryPoint, MetaData md) {
\r
3638 if (metaData) flags = HasMetaData;
\r
3639 if (entryPoint) md.SetEntryPoint(this);
\r
3640 nameIx = md.AddToStringsHeap(name);
\r
3641 hashIx = md.AddToBlobHeap(hashBytes);
\r
3642 tabIx = MDTable.File;
\r
3645 internal FileRef(uint nameIx, byte[] hashBytes, bool metaData,
\r
3646 bool entryPoint, MetaData md) {
\r
3647 if (metaData) flags = HasMetaData;
\r
3648 if (entryPoint) md.SetEntryPoint(this);
\r
3649 this.nameIx = nameIx;
\r
3650 hashIx = md.AddToBlobHeap(hashBytes);
\r
3651 tabIx = MDTable.File;
\r
3654 internal sealed override uint Size(MetaData md) {
\r
3655 return 4 + md.StringsIndexSize() + md.BlobIndexSize();
\r
3658 internal sealed override void Write(FileImage output) {
\r
3659 output.Write(flags);
\r
3660 output.StringsIndex(nameIx);
\r
3661 output.BlobIndex(hashIx);
\r
3664 internal sealed override uint GetCodedIx(CIx code) {
\r
3666 case (CIx.HasCustomAttr) : return 16;
\r
3667 case (CIx.Implementation) : return 0;
\r
3673 /**************************************************************************/
\r
3675 /// Descriptor for pinvoke information for a method NOT YET IMPLEMENTED
\r
3677 public class ImplMap : MetaDataElement
\r
3679 private static readonly ushort NoMangle = 0x01;
\r
3682 string importName;
\r
3684 ModuleRef importScope;
\r
3686 internal ImplMap(ushort flag, Method implMeth, string iName, ModuleRef mScope) {
\r
3689 importName = iName;
\r
3690 importScope = mScope;
\r
3691 tabIx = MDTable.ImplMap;
\r
3692 if (iName == null) flags |= NoMangle;
\r
3693 //throw(new NotYetImplementedException("PInvoke "));
\r
3696 internal sealed override void BuildTables(MetaData md) {
\r
3698 iNameIx = md.AddToStringsHeap(importName);
\r
3702 internal sealed override uint Size(MetaData md) {
\r
3703 return 2+ md.CodedIndexSize(CIx.MemberForwarded) +
\r
3704 md.StringsIndexSize() + md.TableIndexSize(MDTable.ModuleRef);
\r
3707 internal sealed override void Write(FileImage output) {
\r
3708 output.Write(flags);
\r
3709 output.WriteCodedIndex(CIx.MemberForwarded,meth);
\r
3710 output.StringsIndex(iNameIx);
\r
3711 output.WriteIndex(MDTable.ModuleRef,importScope.Row);
\r
3716 /**************************************************************************/
\r
3718 /// Descriptor for an IL instruction
\r
3720 internal abstract class CILInstruction {
\r
3721 protected static readonly sbyte maxByteVal = 127;
\r
3722 protected static readonly sbyte minByteVal = -128;
\r
3723 protected static readonly byte leadByte = 0xFE;
\r
3724 protected static readonly uint USHeapIndex = 0x70000000;
\r
3725 protected static readonly int longInstrStart = (int)Op.arglist;
\r
3726 public bool twoByteInstr = false;
\r
3727 public uint size = 0;
\r
3728 public uint offset;
\r
3730 internal virtual bool Check(MetaData md) {
\r
3734 internal virtual void Write(FileImage output) { }
\r
3738 internal class CILByte : CILInstruction {
\r
3741 internal CILByte(byte bVal) {
\r
3746 internal override void Write(FileImage output) {
\r
3747 output.Write(byteVal);
\r
3753 internal class Instr : CILInstruction {
\r
3754 protected int instr;
\r
3756 internal Instr(int inst) {
\r
3757 if (inst >= longInstrStart) {
\r
3758 instr = inst - longInstrStart;
\r
3759 twoByteInstr = true;
\r
3767 internal override void Write(FileImage output) {
\r
3768 //Console.WriteLine("Writing instruction " + instr + " with size " + size);
\r
3769 if (twoByteInstr) output.Write(leadByte);
\r
3770 output.Write((byte)instr);
\r
3775 internal class IntInstr : Instr {
\r
3779 internal IntInstr(int inst, int num, bool byteSize) : base(inst) {
\r
3781 byteNum = byteSize;
\r
3782 if (byteNum) size++;
\r
3786 internal sealed override void Write(FileImage output) {
\r
3787 base.Write(output);
\r
3789 output.Write((sbyte)val);
\r
3791 output.Write(val);
\r
3796 internal class UIntInstr : Instr {
\r
3800 internal UIntInstr(int inst, int num, bool byteSize) : base(inst) {
\r
3802 byteNum = byteSize;
\r
3803 if (byteNum) size++;
\r
3807 internal sealed override void Write(FileImage output) {
\r
3808 base.Write(output);
\r
3810 output.Write((byte)val);
\r
3812 output.Write((ushort)val);
\r
3817 internal class LongInstr : Instr {
\r
3820 internal LongInstr(int inst, long l) : base(inst) {
\r
3825 internal sealed override void Write(FileImage output) {
\r
3826 base.Write(output);
\r
3827 output.Write(val);
\r
3832 internal class FloatInstr : Instr {
\r
3835 internal FloatInstr(int inst, float f) : base(inst) {
\r
3840 internal sealed override void Write(FileImage output) {
\r
3841 base.Write(output);
\r
3842 output.Write(fVal);
\r
3847 internal class DoubleInstr : Instr {
\r
3850 internal DoubleInstr(int inst, double d) : base(inst) {
\r
3855 internal sealed override void Write(FileImage output) {
\r
3856 base.Write(output);
\r
3857 output.Write(val);
\r
3862 internal class StringInstr : Instr {
\r
3866 internal StringInstr(int inst, string str) : base(inst) {
\r
3871 internal sealed override bool Check(MetaData md) {
\r
3872 strIndex = md.AddToUSHeap(val);
\r
3876 internal sealed override void Write(FileImage output) {
\r
3877 base.Write(output);
\r
3878 output.Write(USHeapIndex | strIndex);
\r
3883 internal class LabelInstr : CILInstruction {
\r
3886 internal LabelInstr(CILLabel lab) {
\r
3888 label.AddLabelInstr(this);
\r
3892 internal class FieldInstr : Instr {
\r
3895 internal FieldInstr(int inst, Field f) : base(inst) {
\r
3900 internal sealed override void Write(FileImage output) {
\r
3901 base.Write(output);
\r
3902 output.Write(field.Token());
\r
3907 internal class MethInstr : Instr {
\r
3910 internal MethInstr(int inst, Method m) : base(inst) {
\r
3915 internal sealed override void Write(FileImage output) {
\r
3916 base.Write(output);
\r
3917 output.Write(meth.Token());
\r
3922 internal class SigInstr : Instr {
\r
3923 CalliSig signature;
\r
3925 internal SigInstr(int inst, CalliSig sig) : base(inst) {
\r
3930 internal sealed override bool Check(MetaData md) {
\r
3931 md.AddToTable(MDTable.StandAloneSig,signature);
\r
3932 signature.BuildTables(md);
\r
3936 internal sealed override void Write(FileImage output) {
\r
3937 base.Write(output);
\r
3938 output.Write(signature.Token());
\r
3942 internal class TypeInstr : Instr {
\r
3943 MetaDataElement theType;
\r
3945 internal TypeInstr(int inst, Type aType, MetaData md) : base(inst) {
\r
3946 theType = aType.GetTypeSpec(md);
\r
3950 internal sealed override void Write(FileImage output) {
\r
3951 base.Write(output);
\r
3952 output.Write(theType.Token());
\r
3957 internal class BranchInstr : Instr {
\r
3959 private bool shortVer = true;
\r
3960 private static readonly byte longInstrOffset = 13;
\r
3961 private int target = 0;
\r
3963 internal BranchInstr(int inst, CILLabel dst) : base(inst) {
\r
3965 dest.AddBranch(this);
\r
3969 internal sealed override bool Check(MetaData md) {
\r
3970 target = (int)dest.GetLabelOffset() - (int)(offset + size);
\r
3971 if (shortVer && ((target < minByteVal) || (target > maxByteVal))) {
\r
3972 if (instr < (int)BranchOp.leave) instr += longInstrOffset;
\r
3981 internal sealed override void Write(FileImage output) {
\r
3982 base.Write(output);
\r
3984 output.Write((sbyte)target);
\r
3986 output.Write(target);
\r
3991 internal class SwitchInstr : Instr {
\r
3993 uint numCases = 0;
\r
3995 internal SwitchInstr(int inst, CILLabel[] dsts) : base(inst) {
\r
3997 if (cases != null) numCases = (uint)cases.Length;
\r
3998 size += 4 + (numCases * 4);
\r
3999 for (int i=0; i < numCases; i++) {
\r
4000 cases[i].AddBranch(this);
\r
4004 internal sealed override void Write(FileImage output) {
\r
4005 base.Write(output);
\r
4006 output.Write(numCases);
\r
4007 for (int i=0; i < numCases; i++) {
\r
4008 int target = (int)cases[i].GetLabelOffset() - (int)(offset + size);
\r
4009 output.Write(target);
\r
4014 /**************************************************************************/
\r
4016 internal class GenericParameter : MetaDataElement
\r
4018 ClassDef owner; /* FIXME: can also be a MethodDef */
\r
4023 public GenericParameter (ClassDef owner, short index) {
\r
4024 this.owner = owner;
\r
4025 this.index = index;
\r
4026 tabIx = MDTable.GenericParam;
\r
4029 public GenericParameter (ClassDef owner, short index,
\r
4030 string name) : this (owner, index) {
\r
4034 internal sealed override uint Size(MetaData md) {
\r
4035 return (uint) (4 +
\r
4036 md.CodedIndexSize(CIx.TypeOrMethodDef) +
\r
4038 md.TableIndexSize(MDTable.TypeDef));
\r
4041 internal sealed override void BuildTables(MetaData md) {
\r
4046 nameIx = md.AddToStringsHeap(name);
\r
4050 internal sealed override void Write(FileImage output) {
\r
4051 output.Write ((short) index);
\r
4052 output.Write ((short) 0);
\r
4053 output.WriteCodedIndex(CIx.TypeOrMethodDef, owner);
\r
4054 output.Write ((uint) nameIx);
\r
4055 output.WriteIndex(MDTable.TypeDef,owner.Row);
\r
4061 internal class GenericParamConstraint : MetaDataElement
\r
4063 GenericParameter param;
\r
4066 public GenericParamConstraint (GenericParameter param, Type type) {
\r
4067 this.param = param;
\r
4069 tabIx = MDTable.GenericParamConstraint;
\r
4072 internal sealed override uint Size(MetaData md) {
\r
4073 return (uint) (md.TableIndexSize(MDTable.GenericParam) +
\r
4074 md.CodedIndexSize(CIx.TypeDefOrRef));
\r
4077 internal sealed override void Write(FileImage output) {
\r
4078 output.WriteIndex(MDTable.GenericParam, param.Row);
\r
4079 output.WriteCodedIndex(CIx.TypeDefOrRef, type);
\r
4084 /**************************************************************************/
\r
4086 /// Descriptor for interface implemented by a class
\r
4088 public class InterfaceImpl: MetaDataElement
\r
4090 ClassDef theClass;
\r
4091 Class theInterface;
\r
4093 internal InterfaceImpl(ClassDef theClass, Class theInterface) {
\r
4094 this.theClass = theClass;
\r
4095 this.theInterface = theInterface;
\r
4096 tabIx = MDTable.InterfaceImpl;
\r
4099 internal sealed override uint Size(MetaData md) {
\r
4100 return md.TableIndexSize(MDTable.TypeDef) +
\r
4101 md.CodedIndexSize(CIx.TypeDefOrRef);
\r
4104 internal sealed override void Write(FileImage output) {
\r
4105 output.WriteIndex(MDTable.TypeDef,theClass.Row);
\r
4106 output.WriteCodedIndex(CIx.TypeDefOrRef,theInterface);
\r
4109 internal sealed override uint GetCodedIx(CIx code) { return 5; }
\r
4112 /**************************************************************************/
\r
4114 /// Descriptor for a local of a method
\r
4116 public class Local
\r
4118 private static readonly byte Pinned = 0x45;
\r
4121 bool pinned = false, byref = false;
\r
4124 /// Create a new local variable
\r
4126 /// <param name="lName">name of the local variable</param>
\r
4127 /// <param name="lType">type of the local variable</param>
\r
4128 public Local(string lName, Type lType) {
\r
4134 /// Create a new local variable that is byref and/or pinned
\r
4136 /// <param name="lName">local name</param>
\r
4137 /// <param name="lType">local type</param>
\r
4138 /// <param name="byRef">is byref</param>
\r
4139 /// <param name="isPinned">has pinned attribute</param>
\r
4140 public Local(string lName, Type lType, bool byRef, bool isPinned)
\r
4145 pinned = isPinned;
\r
4148 internal void TypeSig(MemoryStream str) {
\r
4149 if (pinned) str.WriteByte(Pinned);
\r
4150 type.TypeSig(str);
\r
4154 /**************************************************************************/
\r
4156 /// Descriptor for the locals for a method
\r
4159 public class LocalSig : Signature
\r
4161 private static readonly byte LocalSigByte = 0x7;
\r
4164 public LocalSig(Local[] locals) {
\r
4165 this.locals = locals;
\r
4166 tabIx = MDTable.StandAloneSig;
\r
4169 internal sealed override void BuildTables(MetaData md) {
\r
4171 MemoryStream sig = new MemoryStream();
\r
4172 sig.WriteByte(LocalSigByte);
\r
4173 MetaData.CompressNum((uint)locals.Length,sig);
\r
4174 for (int i=0; i < locals.Length; i++) {
\r
4175 ((Local)locals[i]).TypeSig(sig);
\r
4177 sigIx = md.AddToBlobHeap(sig.ToArray());
\r
4183 /**************************************************************************/
\r
4185 /// Descriptor for resources used in this PE file NOT YET IMPLEMENTED
\r
4188 public class ManifestResource : MetaDataElement
\r
4190 private static readonly uint PublicResource = 0x1;
\r
4191 private static readonly uint PrivateResource = 0x2;
\r
4194 MetaDataElement rRef;
\r
4199 public ManifestResource(string name, bool isPub, FileRef fileRef) {
\r
4201 if (isPub) flags = PublicResource;
\r
4202 else flags = PrivateResource;
\r
4204 tabIx = MDTable.ManifestResource;
\r
4205 throw(new NotYetImplementedException("Manifest Resources "));
\r
4208 public ManifestResource(string name, bool isPub, FileRef fileRef,
\r
4211 if (isPub) flags = PublicResource;
\r
4212 else flags = PrivateResource;
\r
4214 fileOffset = fileIx;
\r
4217 public ManifestResource(string name, bool isPub, AssemblyRef assemRef) {
\r
4219 if (isPub) flags = PublicResource;
\r
4220 else flags = PrivateResource;
\r
4224 internal sealed override void BuildTables(MetaData md) {
\r
4226 nameIx = md.AddToStringsHeap(mrName);
\r
4230 internal sealed override uint Size(MetaData md) {
\r
4231 return 8 + md.StringsIndexSize() +
\r
4232 md.CodedIndexSize(CIx.Implementation);
\r
4235 internal sealed override void Write(FileImage output) {
\r
4236 output.Write(fileOffset);
\r
4237 output.Write(flags);
\r
4238 output.StringsIndex(nameIx);
\r
4239 output.WriteCodedIndex(CIx.Implementation,rRef);
\r
4242 internal sealed override uint GetCodedIx(CIx code) { return 18; }
\r
4245 /**************************************************************************/
\r
4247 /// Base class for elements in the PropertyMap, EventMap and
\r
4248 /// NestedClass MetaData tables
\r
4250 public class MapElem : MetaDataElement
\r
4254 MDTable elemTable;
\r
4256 internal MapElem(ClassDef par, uint elIx, MDTable elemTab) {
\r
4259 elemTable = elemTab;
\r
4262 internal sealed override uint Size(MetaData md) {
\r
4263 return md.TableIndexSize(MDTable.TypeDef) + md.TableIndexSize(elemTable);
\r
4266 internal sealed override void Write(FileImage output) {
\r
4267 output.WriteIndex(MDTable.TypeDef,parent.Row);
\r
4268 output.WriteIndex(elemTable,elemIx);
\r
4271 /**************************************************************************/
\r
4273 /// Base class for field/methods (member of a class)
\r
4275 public abstract class Member : MetaDataElement
\r
4277 protected string name;
\r
4278 protected uint nameIx = 0, sigIx = 0;
\r
4280 internal Member(string memName)
\r
4283 tabIx = MDTable.MemberRef;
\r
4287 /**************************************************************************/
\r
4290 /// Root (20 bytes + UTF-8 Version String + quad align padding)
\r
4291 /// StreamHeaders (8 bytes + null terminated name string + quad align padding)
\r
4293 /// #~ (always present - holds metadata tables)
\r
4294 /// #Strings (always present - holds identifier strings)
\r
4295 /// #US (Userstring heap)
\r
4296 /// #Blob (signature blobs)
\r
4297 /// #GUID (guids for assemblies or Modules)
\r
4300 public class MetaData
\r
4302 private static readonly int[] CIxShiftMap = {2,2,5,1,2,3,1,1,1,2,3,2,1};
\r
4303 private static readonly byte StringsHeapMask = 0x1;
\r
4304 private static readonly byte GUIDHeapMask = 0x2;
\r
4305 private static readonly byte BlobHeapMask = 0x4;
\r
4306 private static readonly uint MetaDataSignature = 0x424A5342;
\r
4307 private static readonly uint maxSmlIxSize = 0xFFFF;
\r
4308 private static readonly uint max1BitSmlIx = 0x7FFF;
\r
4309 private static readonly uint max2BitSmlIx = 0x3FFF;
\r
4310 private static readonly uint max3BitSmlIx = 0x1FFF;
\r
4311 private static readonly uint max5BitSmlIx = 0x7FF;
\r
4312 // NOTE: version and stream name strings MUST always be quad padded
\r
4313 private static readonly string version = "v1.0.3705\0\0\0";
\r
4314 private static readonly char[] tildeName = {'#','~','\0','\0'};
\r
4315 private static readonly char[] stringsName = {'#','S','t','r','i','n','g','s','\0','\0','\0','\0'};
\r
4316 private static readonly char[] usName = {'#','U','S','\0'};
\r
4317 private static readonly char[] guidName = {'#','G','U','I','D','\0','\0','\0'};
\r
4318 private static readonly char[] blobName = {'#','B','l','o','b','\0','\0','\0'};
\r
4319 private static readonly uint MetaDataHeaderSize = 20 + (uint)version.Length;
\r
4320 private static readonly uint TildeHeaderSize = 24;
\r
4321 private static readonly uint StreamHeaderSize = 8;
\r
4322 private static readonly uint numMetaDataTables = (int)MDTable.GenericParamConstraint + 1;
\r
4323 private static readonly uint tildeHeaderSize = 8 + (uint)tildeName.Length;
\r
4325 MetaDataStream strings, us, guid, blob;
\r
4327 MetaDataStream[] streams = new MetaDataStream[5];
\r
4328 uint numStreams = 5;
\r
4329 uint tildeTide = 0, tildePadding = 0, tildeStart = 0;
\r
4330 uint numTables = 0;
\r
4331 ArrayList[] metaDataTables = new ArrayList[numMetaDataTables];
\r
4332 ArrayList byteCodes = new ArrayList();
\r
4333 uint codeSize = 0, codeStart, byteCodePadding = 0, metaDataSize = 0;
\r
4334 ulong valid = 0, /*sorted = 0x000002003301FA00;*/ sorted = 0;
\r
4335 bool[] largeIx = new bool[numMetaDataTables];
\r
4336 bool[] lgeCIx = new bool[(int)CIx.MaxCIx];
\r
4337 bool largeStrings = false, largeUS = false, largeGUID = false, largeBlob = false;
\r
4338 private FileImage file;
\r
4339 private byte heapSizes = 0;
\r
4340 MetaDataElement entryPoint;
\r
4341 BinaryWriter output;
\r
4342 public MSCorLib mscorlib;
\r
4343 private TypeSpec[] systemTypeSpecs = new TypeSpec[PrimitiveType.NumSystemTypes];
\r
4346 internal MetaData(FileImage file) {
\r
4347 // tilde = new MetaDataStream(tildeName,false,0);
\r
4349 strings = new MetaDataStream(stringsName,new UTF8Encoding(),true);
\r
4350 us = new MetaDataStream(usName,new UnicodeEncoding(),true);
\r
4351 guid = new MetaDataStream(guidName,false);
\r
4352 blob = new MetaDataStream(blobName,true);
\r
4353 streams[1] = strings;
\r
4355 streams[3] = guid;
\r
4356 streams[4] = blob;
\r
4357 for (int i=0; i < numMetaDataTables; i++) {
\r
4358 largeIx[i] = false;
\r
4360 for (int i=0; i < lgeCIx.Length; i++) {
\r
4361 lgeCIx[i] = false;
\r
4363 mscorlib = new MSCorLib(this);
\r
4366 internal TypeSpec GetPrimitiveTypeSpec(int ix) {
\r
4367 return systemTypeSpecs[ix];
\r
4370 internal void SetPrimitiveTypeSpec(int ix, TypeSpec typeSpec) {
\r
4371 systemTypeSpecs[ix] = typeSpec;
\r
4374 internal uint Size() {
\r
4375 //Console.WriteLine("metaData size = " + metaDataSize);
\r
4376 return metaDataSize;
\r
4379 internal void StreamSize(byte mask) {
\r
4380 heapSizes |= mask;
\r
4383 internal uint AddToUSHeap(string str) {
\r
4384 if (str == null) return 0;
\r
4385 return us.Add(str,true);
\r
4388 internal uint AddToStringsHeap(string str) {
\r
4389 if ((str == null) || (str.CompareTo("") == 0)) return 0;
\r
4390 return strings.Add(str,false);
\r
4393 internal uint AddToGUIDHeap(Guid guidNum) {
\r
4394 return guid.Add(guidNum);
\r
4397 internal uint AddToBlobHeap(byte[] blobBytes) {
\r
4398 if (blobBytes == null) return 0;
\r
4399 return blob.Add(blobBytes);
\r
4402 internal uint AddToBlobHeap(byte val) {
\r
4403 return blob.Add(val);
\r
4406 internal uint AddToBlobHeap(sbyte val) {
\r
4407 return blob.Add(val);
\r
4410 internal uint AddToBlobHeap(ushort val) {
\r
4411 return blob.Add(val);
\r
4414 internal uint AddToBlobHeap(short val) {
\r
4415 return blob.Add(val);
\r
4418 internal uint AddToBlobHeap(uint val) {
\r
4419 return blob.Add(val);
\r
4422 internal uint AddToBlobHeap(int val) {
\r
4423 return blob.Add(val);
\r
4426 internal uint AddToBlobHeap(ulong val) {
\r
4427 return blob.Add(val);
\r
4430 internal uint AddToBlobHeap(long val) {
\r
4431 return blob.Add(val);
\r
4434 internal uint AddToBlobHeap(float val) {
\r
4435 return blob.Add(val);
\r
4438 internal uint AddToBlobHeap(double val) {
\r
4439 return blob.Add(val);
\r
4442 internal uint AddToBlobHeap(string val) {
\r
4443 return blob.Add(val,true);
\r
4447 private ArrayList GetTable(MDTable tableIx) {
\r
4448 int tabIx = (int)tableIx;
\r
4449 if (metaDataTables[tabIx] == null) {
\r
4450 metaDataTables[tabIx] = new ArrayList();
\r
4451 valid |= ((ulong)0x1 << tabIx);
\r
4452 // Console.WriteLine("after creating table " + tableIx + "(" + tabIx + ") valid = " + valid);
\r
4455 return metaDataTables[tabIx];
\r
4458 internal void AddToTable(MDTable tableIx, MetaDataElement elem) {
\r
4459 if (elem.Row > 0) {
\r
4460 // Console.Out.WriteLine("ERROR - element already in table " + tableIx);
\r
4463 // updates Row field of the element
\r
4464 // Console.WriteLine("Adding element to table " + (uint)tableIx);
\r
4465 ArrayList table = GetTable(tableIx);
\r
4466 elem.Row = (uint)table.Count + 1;
\r
4470 internal uint TableIndex(MDTable tableIx) {
\r
4471 if (metaDataTables[(int)tableIx] == null) return 1;
\r
4472 return (uint)metaDataTables[(int)tableIx].Count+1;
\r
4475 internal uint AddCode(CILInstructions byteCode) {
\r
4476 byteCodes.Add(byteCode);
\r
4477 uint offset = codeSize + codeStart;
\r
4478 codeSize += byteCode.GetCodeSize();
\r
4482 internal void SetEntryPoint(MetaDataElement ep) {
\r
4486 internal void AddData(DataConstant cVal) {
\r
4487 file.AddInitData(cVal);
\r
4490 internal static void CompressNum(uint val, MemoryStream sig) {
\r
4492 sig.WriteByte((byte)val);
\r
4493 } else if (val < 0x3FFF) {
\r
4494 byte b1 = (byte)((val >> 8) | 0x80);
\r
4495 byte b2 = (byte)(val & FileImage.iByteMask[0]);
\r
4496 sig.WriteByte(b1);
\r
4497 sig.WriteByte(b2);
\r
4499 byte b1 = (byte)((val >> 24) | 0xC0);
\r
4500 byte b2 = (byte)((val & FileImage.iByteMask[2]) >> 16);
\r
4501 byte b3 = (byte)((val & FileImage.iByteMask[1]) >> 8);;
\r
4502 byte b4 = (byte)(val & FileImage.iByteMask[0]);
\r
4503 sig.WriteByte(b1);
\r
4504 sig.WriteByte(b2);
\r
4505 sig.WriteByte(b3);
\r
4506 sig.WriteByte(b4);
\r
4510 internal uint CodeSize() {
\r
4511 return codeSize + byteCodePadding;
\r
4514 internal uint StringsIndexSize() {
\r
4515 if (largeStrings) return 4;
\r
4519 internal uint GUIDIndexSize() {
\r
4520 if (largeGUID) return 4;
\r
4524 internal uint USIndexSize() {
\r
4525 if (largeUS) return 4;
\r
4529 internal uint BlobIndexSize() {
\r
4530 if (largeBlob) return 4;
\r
4534 internal uint CodedIndexSize(CIx code) {
\r
4535 if (lgeCIx[(uint)code]) return 4;
\r
4539 internal uint TableIndexSize(MDTable tabIx) {
\r
4540 if (largeIx[(uint)tabIx]) return 4;
\r
4544 private void SetIndexSizes() {
\r
4545 for (int i=0; i < numMetaDataTables; i++) {
\r
4546 if (metaDataTables[i] != null) {
\r
4547 uint count = (uint)metaDataTables[i].Count;
\r
4548 if (count > maxSmlIxSize) {
\r
4549 largeIx[i] = true;
\r
4550 MDTable tabIx = (MDTable)i;
\r
4551 if (count > max5BitSmlIx) {
\r
4552 lgeCIx[(int)CIx.HasCustomAttr] = true;
\r
4554 if (count > max3BitSmlIx) {
\r
4555 if ((tabIx == MDTable.TypeRef) || (tabIx == MDTable.ModuleRef) || (tabIx == MDTable.Method) || (tabIx == MDTable.TypeSpec))
\r
4556 lgeCIx[(int)CIx.CustomAttributeType] = true;
\r
4557 if ((tabIx == MDTable.Method) || (tabIx == MDTable.MemberRef))
\r
4558 lgeCIx[(int)CIx.MemberRefParent] = true;
\r
4559 } else if (count > max2BitSmlIx) {
\r
4560 if ((tabIx == MDTable.Field) || (tabIx == MDTable.Param) || (tabIx == MDTable.Property))
\r
4561 lgeCIx[(int)CIx.HasConst] = true;
\r
4562 if ((tabIx == MDTable.TypeDef) || (tabIx == MDTable.TypeRef) || (tabIx == MDTable.TypeSpec))
\r
4563 lgeCIx[(int)CIx.TypeDefOrRef] = true;
\r
4564 if ((tabIx == MDTable.TypeDef) || (tabIx == MDTable.Method) || (tabIx == MDTable.Assembly))
\r
4565 lgeCIx[(int)CIx.HasDeclSecurity] = true;
\r
4566 if ((tabIx == MDTable.File) || (tabIx == MDTable.AssemblyRef) || (tabIx == MDTable.ExportedType))
\r
4567 lgeCIx[(int)CIx.Implementation] = true;
\r
4568 if ((tabIx == MDTable.Module) || (tabIx == MDTable.ModuleRef) || (tabIx == MDTable.AssemblyRef) || (tabIx == MDTable.TypeRef))
\r
4569 lgeCIx[(int)CIx.ResolutionScope] = true;
\r
4570 } else if (count > max1BitSmlIx) {
\r
4571 if ((tabIx == MDTable.Field) || (tabIx == MDTable.Param))
\r
4572 lgeCIx[(int)CIx.HasFieldMarshal] = true;
\r
4573 if ((tabIx == MDTable.Event) || (tabIx == MDTable.Property))
\r
4574 lgeCIx[(int)CIx.HasSemantics] = true;
\r
4575 if ((tabIx == MDTable.Method) || (tabIx == MDTable.MemberRef))
\r
4576 lgeCIx[(int)CIx.MethodDefOrRef] = true;
\r
4577 if ((tabIx == MDTable.Field) || (tabIx == MDTable.Method))
\r
4578 lgeCIx[(int)CIx.MemberForwarded] = true;
\r
4579 if ((tabIx == MDTable.TypeDef) || (tabIx == MDTable.Method))
\r
4580 lgeCIx[(int)CIx.TypeOrMethodDef] = true;
\r
4585 if (strings.LargeIx()) {
\r
4586 largeStrings = true;
\r
4587 heapSizes |= StringsHeapMask;
\r
4589 if (guid.LargeIx()) {
\r
4591 heapSizes |= GUIDHeapMask;
\r
4593 if (blob.LargeIx()) {
\r
4595 heapSizes |= BlobHeapMask;
\r
4597 largeUS = us.LargeIx();
\r
4600 private void SetStreamOffsets() {
\r
4601 uint sizeOfHeaders = StreamHeaderSize + (uint)tildeName.Length;
\r
4602 for (int i=1; i < numStreams; i++) {
\r
4603 sizeOfHeaders += streams[i].headerSize();
\r
4605 metaDataSize = MetaDataHeaderSize + sizeOfHeaders;
\r
4606 // Console.WriteLine("Size of meta data headers (tildeStart) = " + metaDataSize);
\r
4607 tildeStart = metaDataSize;
\r
4608 metaDataSize += tildeTide + tildePadding;
\r
4609 //Console.WriteLine(tildeName + " - size = " + (tildeTide + tildePadding));
\r
4610 for (int i=1; i < numStreams; i++) {
\r
4611 // Console.WriteLine("Stream " + i + " starts at " + metaDataSize);
\r
4612 streams[i].Start = metaDataSize;
\r
4613 metaDataSize += streams[i].Size();
\r
4614 streams[i].WriteDetails();
\r
4618 internal void CalcTildeStreamSize() {
\r
4619 //tilde.SetIndexSizes(strings.LargeIx(),us.LargeIx(),guid.LargeIx(),blob.LargeIx());
\r
4620 tildeTide = TildeHeaderSize;
\r
4621 tildeTide += 4 * numTables;
\r
4622 //Console.WriteLine("Tilde header + sizes = " + tildeTide);
\r
4623 for (int i=0; i < numMetaDataTables; i++) {
\r
4624 if (metaDataTables[i] != null) {
\r
4625 ArrayList table = metaDataTables[i];
\r
4626 // Console.WriteLine("Meta data table " + i + " at offset " + tildeTide);
\r
4627 tildeTide += (uint)table.Count * ((MetaDataElement)table[0]).Size(this);
\r
4628 // Console.WriteLine("Metadata table " + i + " has size " + table.Count);
\r
4629 // Console.WriteLine("tildeTide = " + tildeTide);
\r
4632 if ((tildeTide % 4) != 0) tildePadding = 4 - (tildeTide % 4);
\r
4633 //Console.WriteLine("tildePadding = " + tildePadding);
\r
4636 internal void WriteTildeStream(FileImage output) {
\r
4637 long startTilde = output.Seek(0,SeekOrigin.Current);
\r
4638 output.Write((uint)0); // Reserved
\r
4639 output.Write((byte)1); // MajorVersion
\r
4640 output.Write((byte)0); // MinorVersion
\r
4641 output.Write(heapSizes);
\r
4642 output.Write((byte)1); // Reserved
\r
4643 output.Write(valid);
\r
4644 output.Write(sorted);
\r
4645 for (int i=0; i < numMetaDataTables; i++) {
\r
4646 if (metaDataTables[i] != null) {
\r
4647 uint count = (uint)metaDataTables[i].Count;
\r
4648 output.Write(count);
\r
4651 long tabStart = output.Seek(0,SeekOrigin.Current);
\r
4652 // Console.WriteLine("Starting metaData tables at " + tabStart);
\r
4653 for (int i=0; i < numMetaDataTables; i++) {
\r
4654 if (metaDataTables[i] != null) {
\r
4655 // Console.WriteLine("Starting metaData table " + i + " at " + (output.Seek(0,SeekOrigin.Current) - startTilde));
\r
4656 ArrayList table = metaDataTables[i];
\r
4657 for (int j=0; j < table.Count; j++) {
\r
4658 ((MetaDataElement)table[j]).Write(output);
\r
4662 // Console.WriteLine("Writing padding at " + output.Seek(0,SeekOrigin.Current));
\r
4663 for (int i=0; i < tildePadding; i++) output.Write((byte)0);
\r
4666 private void BuildTable(ArrayList table) {
\r
4667 if (table == null) return;
\r
4668 for (int j=0; j < table.Count; j++) {
\r
4669 ((MetaDataElement)table[j]).BuildTables(this);
\r
4673 internal void BuildMetaData(uint codeStartOffset) {
\r
4674 codeStart = codeStartOffset;
\r
4675 BuildTable(metaDataTables[(int)MDTable.TypeDef]);
\r
4676 BuildTable(metaDataTables[(int)MDTable.MemberRef]);
\r
4677 BuildTable(metaDataTables[(int)MDTable.GenericParam]);
\r
4678 BuildTable(metaDataTables[(int)MDTable.GenericParamConstraint]);
\r
4679 BuildTable(metaDataTables[(int)MDTable.CustomAttribute]);
\r
4680 /* for (int i=0; i < metaDataTables.Length; i++) {
\r
4681 ArrayList table = metaDataTables[i];
\r
4682 if (table != null) {
\r
4683 for (int j=0; j < table.Count; j++) {
\r
4684 ((MetaDataElement)table[j]).BuildTables(this);
\r
4690 for (int i=1; i < numStreams; i++) {
\r
4691 streams[i].EndStream();
\r
4693 CalcTildeStreamSize();
\r
4694 SetStreamOffsets();
\r
4695 byteCodePadding = NumToAlign(codeSize,4);
\r
4696 if (entryPoint != null) file.SetEntryPoint(entryPoint.Token());
\r
4699 internal void WriteByteCodes(FileImage output) {
\r
4700 for (int i=0; i < byteCodes.Count; i++) {
\r
4701 ((CILInstructions)byteCodes[i]).Write(output);
\r
4703 for (int i=0; i < byteCodePadding; i++) {
\r
4704 output.Write((byte)0);
\r
4708 internal void WriteMetaData(FileImage output) {
\r
4709 this.output = output;
\r
4710 mdStart = output.Seek(0,SeekOrigin.Current);
\r
4711 // Console.WriteLine("Writing metaData at " + Hex.Long(mdStart));
\r
4712 output.Write(MetaDataSignature);
\r
4713 output.Write((short)1); // Major Version
\r
4714 output.Write((short)1); // Minor Version ECMA = 0, PEFiles = 1
\r
4715 output.Write(0); // Reserved
\r
4716 output.Write(version.Length);
\r
4717 output.Write(version.ToCharArray()); // version string is already zero padded
\r
4718 output.Write((short)0);
\r
4719 output.Write((ushort)numStreams);
\r
4720 // write tilde header
\r
4721 output.Write(tildeStart);
\r
4722 output.Write(tildeTide + tildePadding);
\r
4723 output.Write(tildeName);
\r
4724 for (int i=1; i < numStreams; i++) streams[i].WriteHeader(output);
\r
4725 // Console.WriteLine("Writing tilde stream at " + output.Seek(0,SeekOrigin.Current) + " = " + tildeStart);
\r
4726 WriteTildeStream(output);
\r
4727 for (int i=1; i < numStreams; i++) streams[i].Write(output);
\r
4728 // Console.WriteLine("Finished Writing metaData at " + output.Seek(0,SeekOrigin.Current));
\r
4731 internal bool LargeStringsIndex() { return strings.LargeIx(); }
\r
4732 internal bool LargeGUIDIndex() { return guid.LargeIx(); }
\r
4733 internal bool LargeUSIndex() { return us.LargeIx(); }
\r
4734 internal bool LargeBlobIndex() { return blob.LargeIx(); }
\r
4736 internal bool LargeIx(MDTable tabIx) { return largeIx[(uint)tabIx]; }
\r
4739 private uint NumToAlign(uint val, uint alignVal) {
\r
4740 if ((val % alignVal) == 0) return 0;
\r
4741 return alignVal - (val % alignVal);
\r
4744 internal void WriteCodedIndex(CIx code, MetaDataElement elem, FileImage output) {
\r
4746 if (elem != null) {
\r
4747 ix = (elem.Row << CIxShiftMap[(uint)code]) | elem.GetCodedIx(code);
\r
4748 // Console.WriteLine("coded index = " + ix + " row = " + elem.Row);
\r
4750 // Console.WriteLine("elem for coded index is null");
\r
4752 if (lgeCIx[(uint)code])
\r
4755 output.Write((ushort)ix);
\r
4759 /**************************************************************************/
\r
4761 /// Base class for all Meta Data table elements
\r
4764 public abstract class MetaDataElement
\r
4767 protected ArrayList customAttributes;
\r
4768 private uint row = 0;
\r
4769 protected bool done = false;
\r
4770 protected MDTable tabIx;
\r
4772 internal MetaDataElement() { }
\r
4779 if (row == 0) row = value;
\r
4783 internal virtual uint GetCodedIx(CIx code) { return 0; }
\r
4786 /// Add a custom attribute to this item
\r
4788 /// <param name="ctorMeth">the constructor method for this attribute</param>
\r
4789 /// <param name="val">the byte value of the parameters</param>
\r
4790 public void AddCustomAttribute(Method ctorMeth, byte[] val) {
\r
4791 if (customAttributes == null) {
\r
4792 customAttributes = new ArrayList();
\r
4794 customAttributes.Add(new CustomAttribute(this,ctorMeth,val));
\r
4798 /// Add a custom attribute to this item
\r
4800 /// <param name="ctorMeth">the constructor method for this attribute</param>
\r
4801 /// <param name="val">the constant values of the parameters</param>
\r
4802 public void AddCustomAttribute(Method ctorMeth, Constant[] cVals) {
\r
4803 if (customAttributes == null) {
\r
4804 customAttributes = new ArrayList();
\r
4806 // customAttributes.Add(new CustomAttribute(this,ctorMeth,cVals));
\r
4809 internal void DoCustomAttributes(MetaData md) {
\r
4810 if (customAttributes != null) {
\r
4811 for (int i=0; i < customAttributes.Count; i++) {
\r
4812 CustomAttribute ca = (CustomAttribute)customAttributes[i];
\r
4813 ca.BuildTables(md);
\r
4818 internal uint Token() {
\r
4819 return (((uint)tabIx << 24) | row);
\r
4822 internal virtual void BuildTables(MetaData md) {
\r
4826 internal virtual uint Size(MetaData md) {
\r
4830 internal virtual void Write(FileImage output) { }
\r
4833 /**************************************************************************/
\r
4835 /// Stream in the Meta Data (#Strings, #US, #Blob and #GUID)
\r
4838 internal class MetaDataStream : BinaryWriter
\r
4840 private static readonly uint StreamHeaderSize = 8;
\r
4841 private static uint maxSmlIxSize = 0xFFFF;
\r
4843 private uint start = 0;
\r
4844 uint size = 0, tide = 1;
\r
4845 bool largeIx = false;
\r
4846 uint sizeOfHeader;
\r
4848 Hashtable htable = new Hashtable();
\r
4850 internal MetaDataStream(char[] name, bool addInitByte) : base(new MemoryStream()) {
\r
4851 if (addInitByte) { Write((byte)0); size = 1; }
\r
4853 sizeOfHeader = StreamHeaderSize + (uint)name.Length;
\r
4856 internal MetaDataStream(char[] name, System.Text.Encoding enc, bool addInitByte) : base(new MemoryStream(),enc) {
\r
4857 if (addInitByte) { Write((byte)0); size = 1; }
\r
4859 sizeOfHeader = StreamHeaderSize + (uint)name.Length;
\r
4862 public uint Start {
\r
4871 internal uint headerSize() {
\r
4872 // Console.WriteLine(name + " stream has headersize of " + sizeOfHeader);
\r
4873 return sizeOfHeader;
\r
4876 internal void SetSize(uint siz) {
\r
4880 internal uint Size() {
\r
4884 internal bool LargeIx() {
\r
4888 internal void WriteDetails() {
\r
4889 // Console.WriteLine(name + " - size = " + size);
\r
4892 internal uint Add(string str, bool prependSize) {
\r
4893 Object val = htable[str];
\r
4895 if (val == null) {
\r
4897 htable[str] = index;
\r
4898 char[] arr = str.ToCharArray();
\r
4899 if (prependSize) CompressNum((uint)arr.Length*2+1);
\r
4902 size = (uint)Seek(0,SeekOrigin.Current);
\r
4904 index = (uint)val;
\r
4909 internal uint Add(Guid guid) {
\r
4910 Write(guid.ToByteArray());
\r
4911 size =(uint)Seek(0,SeekOrigin.Current);
\r
4915 internal uint Add(byte[] blob) {
\r
4917 CompressNum((uint)blob.Length);
\r
4919 size = (uint)Seek(0,SeekOrigin.Current);
\r
4923 internal uint Add(byte val) {
\r
4926 size = (uint)Seek(0,SeekOrigin.Current);
\r
4930 internal uint Add(sbyte val) {
\r
4933 size = (uint)Seek(0,SeekOrigin.Current);
\r
4937 internal uint Add(ushort val) {
\r
4940 size = (uint)Seek(0,SeekOrigin.Current);
\r
4944 internal uint Add(short val) {
\r
4947 size = (uint)Seek(0,SeekOrigin.Current);
\r
4951 internal uint Add(uint val) {
\r
4954 size = (uint)Seek(0,SeekOrigin.Current);
\r
4958 internal uint Add(int val) {
\r
4961 size = (uint)Seek(0,SeekOrigin.Current);
\r
4965 internal uint Add(ulong val) {
\r
4968 size = (uint)Seek(0,SeekOrigin.Current);
\r
4972 internal uint Add(long val) {
\r
4975 size = (uint)Seek(0,SeekOrigin.Current);
\r
4979 internal uint Add(float val) {
\r
4982 size = (uint)Seek(0,SeekOrigin.Current);
\r
4986 internal uint Add(double val) {
\r
4989 size = (uint)Seek(0,SeekOrigin.Current);
\r
4993 private void CompressNum(uint val) {
\r
4996 } else if (val < 0x3FFF) {
\r
4997 byte b1 = (byte)((val >> 8) | 0x80);
\r
4998 byte b2 = (byte)(val & FileImage.iByteMask[0]);
\r
5002 byte b1 = (byte)((val >> 24) | 0xC0);
\r
5003 byte b2 = (byte)((val & FileImage.iByteMask[2]) >> 16);
\r
5004 byte b3 = (byte)((val & FileImage.iByteMask[1]) >> 8);;
\r
5005 byte b4 = (byte)(val & FileImage.iByteMask[0]);
\r
5013 private void QuadAlign() {
\r
5014 if ((size % 4) != 0) {
\r
5015 uint pad = 4 - (size % 4);
\r
5017 for (int i=0; i < pad; i++) {
\r
5023 internal void EndStream() {
\r
5025 if (size > maxSmlIxSize) {
\r
5030 internal void WriteHeader(BinaryWriter output) {
\r
5031 output.Write(start);
\r
5032 output.Write(size);
\r
5033 output.Write(name);
\r
5036 internal virtual void Write(BinaryWriter output) {
\r
5037 // Console.WriteLine("Writing " + name + " stream at " + output.Seek(0,SeekOrigin.Current) + " = " + start);
\r
5038 MemoryStream str = (MemoryStream)BaseStream;
\r
5039 output.Write(str.ToArray());
\r
5043 /**************************************************************************/
\r
5045 /// Base class for Method Descriptors
\r
5048 public abstract class Method : Member
\r
5050 protected CallConv callConv = CallConv.Default;
\r
5051 protected Type retType;
\r
5053 internal Method(string methName, Type rType) : base(methName)
\r
5059 /// Add calling conventions to this method descriptor
\r
5061 /// <param name="cconv"></param>
\r
5062 public void AddCallConv(CallConv cconv) {
\r
5063 callConv |= cconv;
\r
5066 internal abstract void TypeSig(MemoryStream sig);
\r
5068 internal uint GetSigIx(MetaData md) {
\r
5069 MemoryStream sig = new MemoryStream();
\r
5071 return md.AddToBlobHeap(sig.ToArray());
\r
5074 internal Type GetRetType() {
\r
5079 /**************************************************************************/
\r
5081 /// Descriptor for a method defined in THIS assembly/module
\r
5085 public class MethodDef : Method
\r
5087 private static readonly ushort PInvokeImpl = 0x2000;
\r
5088 //private static readonly uint UnmanagedExport = 0x0008;
\r
5089 // private static readonly byte LocalSigByte = 0x7;
\r
5090 uint parIx = 0, textOffset = 0;
\r
5092 MetaData metaData;
\r
5093 CILInstructions code;
\r
5094 ArrayList securityActions = new ArrayList();
\r
5098 ushort methFlags = 0, implFlags = 0;
\r
5099 int maxStack = 0, numPars = 0;
\r
5100 bool entryPoint = false;
\r
5101 LocalSig localSig;
\r
5102 ArrayList varArgSigList;
\r
5103 ImplMap pinvokeImpl;
\r
5106 internal MethodDef(MetaData md, string name, Type retType, Param[] pars) : base(name,retType) {
\r
5109 if (parList != null) numPars = parList.Length;
\r
5110 tabIx = MDTable.Method;
\r
5113 internal MethodDef(MetaData md, MethAttr mAttrSet, ImplAttr iAttrSet, string name, Type retType, Param[] pars) : base(name,retType) {
\r
5116 if (parList != null) numPars = parList.Length;
\r
5117 // Console.WriteLine("Creating method " + name + " with " + numPars + " parameters");
\r
5118 methFlags = (ushort)mAttrSet;
\r
5119 implFlags = (ushort)iAttrSet;
\r
5120 tabIx = MDTable.Method;
\r
5123 internal Param[] GetPars() {
\r
5128 /// Add some attributes to this method descriptor
\r
5130 /// <param name="ma">the attributes to be added</param>
\r
5131 public void AddMethAttribute(MethAttr ma) {
\r
5132 methFlags |= (ushort)ma;
\r
5136 /// Add some implementation attributes to this method descriptor
\r
5138 /// <param name="ia">the attributes to be added</param>
\r
5139 public void AddImplAttribute(ImplAttr ia) {
\r
5140 implFlags |= (ushort)ia;
\r
5143 public void AddPInvokeInfo(ModuleRef scope, string methName,
\r
5144 PInvokeAttr callAttr) {
\r
5145 pinvokeImpl = new ImplMap((ushort)callAttr,this,methName,scope);
\r
5146 methFlags |= PInvokeImpl;
\r
5150 /// Set the maximum stack height for this method
\r
5152 /// <param name="maxStack">the maximum height of the stack</param>
\r
5153 public void SetMaxStack(int maxStack) {
\r
5154 this.maxStack = maxStack;
\r
5158 /// Add local variables to this method
\r
5160 /// <param name="locals">the locals to be added</param>
\r
5161 /// <param name="initLocals">are locals initialised to default values</param>
\r
5162 public void AddLocals(Local[] locals, bool initLocals) {
\r
5163 this.locals = locals;
\r
5164 this.initLocals = initLocals;
\r
5168 /// Mark this method as having an entry point
\r
5170 public void DeclareEntryPoint() {
\r
5171 entryPoint = true;
\r
5175 /// Create a code buffer for this method to add the IL instructions to
\r
5177 /// <returns>a buffer for this method's IL instructions</returns>
\r
5178 public CILInstructions CreateCodeBuffer() {
\r
5179 code = new CILInstructions(metaData);
\r
5184 /// Make a method reference descriptor for this method to be used
\r
5185 /// as a callsite signature for this vararg method
\r
5187 /// <param name="optPars">the optional pars for the vararg method call</param>
\r
5188 /// <returns></returns>
\r
5189 public MethodRef MakeVarArgSignature(Type[] optPars) {
\r
5190 Type[] pars = new Type[numPars];
\r
5191 MethodRef varArgSig;
\r
5192 for (int i=0; i < numPars; i++) {
\r
5193 pars[i] = parList[i].GetParType();
\r
5195 varArgSig = new MethodRef(this,name,retType,pars,true,optPars);
\r
5197 if (varArgSigList == null)
\r
5198 varArgSigList = new ArrayList ();
\r
5199 varArgSigList.Add (varArgSig);
\r
5203 internal sealed override void TypeSig(MemoryStream sig) {
\r
5204 sig.WriteByte((byte)callConv);
\r
5205 MetaData.CompressNum((uint)numPars,sig);
\r
5206 retType.TypeSig(sig);
\r
5207 for (ushort i=0; i < numPars; i++) {
\r
5208 parList[i].seqNo = (ushort)(i+1);
\r
5209 parList[i].TypeSig(sig);
\r
5213 internal sealed override void BuildTables(MetaData md) {
\r
5215 if (pinvokeImpl != null) {
\r
5216 md.AddToTable(MDTable.ImplMap,pinvokeImpl);
\r
5217 pinvokeImpl.BuildTables(md);
\r
5219 if (entryPoint) md.SetEntryPoint(this);
\r
5220 uint locToken = 0;
\r
5221 if (locals != null) {
\r
5222 localSig = new LocalSig(locals);
\r
5223 md.AddToTable(MDTable.StandAloneSig,localSig);
\r
5224 localSig.BuildTables(md);
\r
5225 locToken = localSig.Token();
\r
5227 if (code != null) {
\r
5228 code.CheckCode(locToken,initLocals,maxStack);
\r
5229 textOffset = md.AddCode(code);
\r
5231 nameIx = md.AddToStringsHeap(name);
\r
5232 sigIx = GetSigIx(md);
\r
5233 parIx = md.TableIndex(MDTable.Param);
\r
5234 for (int i=0; i < numPars; i++) {
\r
5235 md.AddToTable(MDTable.Param,parList[i]);
\r
5236 parList[i].BuildTables(md);
\r
5238 if (varArgSigList != null) {
\r
5239 foreach (MethodRef varArgSig in varArgSigList) {
\r
5240 md.AddToTable(MDTable.MemberRef,varArgSig);
\r
5241 varArgSig.BuildTables(md);
\r
5244 DoCustomAttributes (md);
\r
5245 // Console.WriteLine("method has " + numPars + " parameters");
\r
5249 internal sealed override uint Size(MetaData md) {
\r
5250 return 8 + md.StringsIndexSize() + md.BlobIndexSize() + md.TableIndexSize(MDTable.Param);
\r
5253 internal sealed override void Write(FileImage output) {
\r
5254 if (ZeroRva ()) output.Write(0);
\r
5255 else output.WriteCodeRVA(textOffset);
\r
5256 output.Write(implFlags);
\r
5257 output.Write(methFlags);
\r
5258 output.StringsIndex(nameIx);
\r
5259 output.BlobIndex(sigIx);
\r
5260 output.WriteIndex(MDTable.Param,parIx);
\r
5263 internal bool ZeroRva () {
5264 return ((methFlags & (ushort)MethAttr.Abstract) != 0);
5267 internal sealed override uint GetCodedIx(CIx code) {
\r
5269 case (CIx.HasCustomAttr) : return 0;
\r
5270 case (CIx.HasDeclSecurity) : return 1;
\r
5271 case (CIx.MemberRefParent) : return 3;
\r
5272 case (CIx.MethodDefOrRef) : return 0;
\r
5273 case (CIx.MemberForwarded) : return 1;
\r
5274 case (CIx.CustomAttributeType) : return 2;
\r
5275 case (CIx.TypeOrMethodDef) : return 1;
\r
5281 /**************************************************************************/
\r
5283 /// Descriptor for an overriding method (.override)
\r
5285 public class MethodImpl : MetaDataElement
\r
5288 Method header, body;
\r
5290 internal MethodImpl(ClassDef par, Method decl, Method bod) {
\r
5294 tabIx = MDTable.MethodImpl;
\r
5297 internal sealed override uint Size(MetaData md) {
\r
5298 return md.TableIndexSize(MDTable.TypeDef) + 2 * md.CodedIndexSize(CIx.MethodDefOrRef);
\r
5301 internal sealed override void Write(FileImage output) {
\r
5302 output.WriteIndex(MDTable.TypeDef,parent.Row);
\r
5303 output.WriteCodedIndex(CIx.MethodDefOrRef,body);
\r
5304 output.WriteCodedIndex(CIx.MethodDefOrRef,header);
\r
5308 /**************************************************************************/
\r
5310 /// Descriptor for a method defined in another assembly/module
\r
5312 public class MethodRef : Method
\r
5314 private static readonly byte Sentinel = 0x41;
\r
5315 Type[] parList, optParList;
\r
5316 MetaDataElement parent;
\r
5317 uint numPars = 0, numOptPars = 0;
\r
5319 internal MethodRef(MetaDataElement paren, string name, Type retType,
\r
5320 Type[] pars, bool varArgMeth, Type[] optPars) : base(name,retType) {
\r
5323 if (parList != null) numPars = (uint)parList.Length;
\r
5325 optParList = optPars;
\r
5326 if (optParList != null) numOptPars = (uint)optParList.Length;
\r
5327 callConv = CallConv.Vararg;
\r
5331 internal sealed override void TypeSig(MemoryStream sig) {
\r
5332 sig.WriteByte((byte)callConv);
\r
5333 MetaData.CompressNum(numPars+numOptPars,sig);
\r
5334 retType.TypeSig(sig);
\r
5335 for (int i=0; i < numPars; i++) {
\r
5336 parList[i].TypeSig(sig);
\r
5338 if (numOptPars > 0) {
\r
5339 sig.WriteByte(Sentinel);
\r
5340 for (int i=0; i < numOptPars; i++) {
\r
5341 optParList[i].TypeSig(sig);
\r
5346 internal sealed override void BuildTables(MetaData md) {
\r
5348 nameIx = md.AddToStringsHeap(name);
\r
5349 sigIx = GetSigIx(md);
\r
5353 internal sealed override uint Size(MetaData md) {
\r
5354 return md.CodedIndexSize(CIx.MemberRefParent) + md.StringsIndexSize() + md.BlobIndexSize();
\r
5357 internal sealed override void Write(FileImage output) {
\r
5358 output.WriteCodedIndex(CIx.MemberRefParent,parent);
\r
5359 output.StringsIndex(nameIx);
\r
5360 output.BlobIndex(sigIx);
\r
5363 internal sealed override uint GetCodedIx(CIx code) {
\r
5365 case (CIx.HasCustomAttr) : return 6;
\r
5366 case (CIx.MethodDefOrRef) : return 1;
\r
5367 case (CIx.CustomAttributeType) : return 3;
\r
5373 /**************************************************************************/
\r
5375 /// Descriptor for Property and Event methods
\r
5377 public class MethodSemantics : MetaDataElement {
\r
5379 Feature.MethodType type;
\r
5381 Feature eventOrProp;
\r
5383 internal MethodSemantics(Feature.MethodType mType, MethodDef method, Feature feature) {
\r
5386 eventOrProp = feature;
\r
5387 tabIx = MDTable.MethodSemantics;
\r
5390 internal sealed override uint Size(MetaData md) {
\r
5391 return 2 + md.TableIndexSize(MDTable.Method) + md.CodedIndexSize(CIx.HasSemantics);
\r
5394 internal sealed override void Write(FileImage output) {
\r
5395 output.Write((ushort)type);
\r
5396 output.WriteIndex(MDTable.Method,meth.Row);
\r
5397 output.WriteCodedIndex(CIx.HasSemantics,eventOrProp);
\r
5401 /**************************************************************************/
\r
5403 /// Descriptor for a FunctionPointer type
\r
5406 public class MethPtrType : Type
\r
5408 // MethPtrType == FNPTR
\r
5413 /// Create a new function pointer type
\r
5415 /// <param name="meth">the function to be referenced</param>
\r
5416 public MethPtrType(Method meth) : base(0x1B)
\r
5419 tabIx = MDTable.TypeSpec;
\r
5422 internal sealed override void TypeSig(MemoryStream str) {
\r
5423 str.WriteByte(typeIndex);
\r
5424 method.TypeSig(str);
\r
5427 internal sealed override void BuildTables(MetaData md) {
\r
5429 MemoryStream sig = new MemoryStream();
\r
5431 sigIx = md.AddToBlobHeap(sig.ToArray());
\r
5435 internal sealed override uint Size(MetaData md) {
\r
5436 return md.BlobIndexSize();
\r
5439 internal sealed override void Write(FileImage output) {
\r
5440 output.BlobIndex(sigIx);
\r
5443 internal sealed override uint GetCodedIx(CIx code) { return 0x1B; }
\r
5446 /**************************************************************************/
\r
5448 /// Descriptor for THIS module
\r
5450 public class Module : ResolutionScope
\r
5455 internal Module(string name, MetaData md) : base(name,md) {
\r
5456 mvid = Guid.NewGuid();
\r
5457 mvidIx = md.AddToGUIDHeap(mvid);
\r
5458 tabIx = MDTable.Module;
\r
5461 internal sealed override uint Size(MetaData md) {
\r
5462 return 2 + md.StringsIndexSize() + 3 * md.GUIDIndexSize();
\r
5465 internal sealed override void Write(FileImage output) {
\r
5466 output.Write((short)0);
\r
5467 output.StringsIndex(nameIx);
\r
5468 output.GUIDIndex(mvidIx);
\r
5469 output.GUIDIndex(0);
\r
5470 output.GUIDIndex(0);
\r
5473 internal sealed override uint GetCodedIx(CIx code) {
\r
5475 case (CIx.HasCustomAttr) : return 7;
\r
5476 case (CIx.ResolutionScope) : return 0;
\r
5482 /**************************************************************************/
\r
5484 /// Descriptor for another module in THIS assembly
\r
5486 public class ModuleRef : ResolutionScope
\r
5489 internal ModuleRef(MetaData md, string name) : base(name,md) {
\r
5490 tabIx = MDTable.ModuleRef;
\r
5494 /// Add a class to this external module. This is a class declared in
\r
5495 /// another module of THIS assembly.
\r
5497 /// <param name="nsName">name space name</param>
\r
5498 /// <param name="name">class name</param>
\r
5499 /// <returns>a descriptor for this class in another module</returns>
\r
5500 public ClassRef AddClass(string nsName, string name, bool exportClass) {
\r
5501 ClassRef aClass = new ClassRef(nsName,name,metaData);
\r
5502 metaData.AddToTable(MDTable.TypeRef,aClass);
\r
5503 aClass.SetParent(this);
\r
5508 /// Make a file descriptor to correspond to this module. The file
\r
5509 /// descriptor will have the same name as the module descriptor
\r
5511 /// <param name="hashBytes">the hash of the file</param>
\r
5512 /// <param name="hasMetaData">the file contains metadata</param>
\r
5513 /// <param name="entryPoint">the program entry point is in this file</param>
\r
5514 /// <returns>a descriptor for the file which contains this module</returns>
\r
5515 public FileRef MakeFile(byte[] hashBytes, bool hasMetaData, bool entryPoint) {
\r
5516 FileRef file = new FileRef(nameIx,hashBytes,hasMetaData,entryPoint,metaData);
\r
5517 metaData.AddToTable(MDTable.File,file);
\r
5522 /// Add a value class to this module. This is a class declared in
\r
5523 /// another module of THIS assembly.
\r
5525 /// <param name="nsName">name space name</param>
\r
5526 /// <param name="name">class name</param>
\r
5527 /// <returns></returns>
\r
5528 public ClassRef AddValueClass(string nsName, string name) {
\r
5529 ClassRef aClass = new ClassRef(nsName,name,metaData);
\r
5530 metaData.AddToTable(MDTable.TypeRef,aClass);
\r
5531 aClass.SetParent(this);
\r
5532 aClass.MakeValueClass();
\r
5537 /// Add a class which is declared public in this external module of
\r
5538 /// THIS assembly. This class will be exported from this assembly.
\r
5539 /// The ilasm syntax for this is .extern class
\r
5541 /// <param name="attrSet">attributes of the class to be exported</param>
\r
5542 /// <param name="nsName">name space name</param>
\r
5543 /// <param name="name">external class name</param>
\r
5544 /// <param name="declFile">the file where the class is declared</param>
\r
5545 /// <param name="isValueClass">is this class a value type?</param>
\r
5546 /// <returns>a descriptor for this external class</returns>
\r
5547 public ExternClassRef AddExternClass(TypeAttr attrSet, string nsName,
\r
5548 string name, FileRef declFile,
\r
5549 bool isValueClass) {
\r
5550 ExternClassRef cRef = new ExternClassRef(attrSet,nsName,name,declFile,metaData);
\r
5551 metaData.AddToTable(MDTable.TypeRef,cRef);
\r
5552 cRef.SetParent(this);
\r
5553 if (isValueClass) cRef.MakeValueClass();
\r
5558 /// Add a "global" method in another module
\r
5560 /// <param name="name">method name</param>
\r
5561 /// <param name="retType">return type</param>
\r
5562 /// <param name="pars">method parameter types</param>
\r
5563 /// <returns>a descriptor for this method in anther module</returns>
\r
5564 public MethodRef AddMethod(string name, Type retType, Type[] pars) {
\r
5565 MethodRef meth = new MethodRef(this,name,retType,pars,false,null);
\r
5566 metaData.AddToTable(MDTable.MemberRef,meth);
\r
5571 /// Add a vararg method to this class
\r
5573 /// <param name="name">method name</param>
\r
5574 /// <param name="retType">return type</param>
\r
5575 /// <param name="pars">parameter types</param>
\r
5576 /// <param name="optPars">optional param types for this vararg method</param>
\r
5577 /// <returns>a descriptor for this method</returns>
\r
5578 public MethodRef AddVarArgMethod(string name, Type retType,
\r
5579 Type[] pars, Type[] optPars) {
\r
5580 MethodRef meth = new MethodRef(this,name,retType,pars,true,optPars);
\r
5581 metaData.AddToTable(MDTable.MemberRef,meth);
\r
5586 /// Add a field in another module
\r
5588 /// <param name="name">field name</param>
\r
5589 /// <param name="fType">field type</param>
\r
5590 /// <returns>a descriptor for this field in another module</returns>
\r
5591 public FieldRef AddField(string name, Type fType) {
\r
5592 FieldRef field = new FieldRef(this,name,fType);
\r
5593 metaData.AddToTable(MDTable.MemberRef,field);
\r
5597 internal sealed override uint Size(MetaData md) {
\r
5598 return md.StringsIndexSize();
\r
5601 internal sealed override void Write(FileImage output) {
\r
5602 output.StringsIndex(nameIx);
\r
5605 internal sealed override uint GetCodedIx(CIx code) {
\r
5607 case (CIx.HasCustomAttr) : return 12;
\r
5608 case (CIx.MemberRefParent) : return 2;
\r
5609 case (CIx.ResolutionScope) : return 1;
\r
5615 /**************************************************************************/
\r
5617 /// Descriptors for native types used for marshalling
\r
5619 public class NativeType {
\r
5620 public static readonly NativeType Void = new NativeType(0x01);
\r
5621 public static readonly NativeType Boolean = new NativeType(0x02);
\r
5622 public static readonly NativeType Int8 = new NativeType(0x03);
\r
5623 public static readonly NativeType UInt8 = new NativeType(0x04);
\r
5624 public static readonly NativeType Int16 = new NativeType(0x05);
\r
5625 public static readonly NativeType UInt16 = new NativeType(0x06);
\r
5626 public static readonly NativeType Int32 = new NativeType(0x07);
\r
5627 public static readonly NativeType UInt32 = new NativeType(0x08);
\r
5628 public static readonly NativeType Int64 = new NativeType(0x09);
\r
5629 public static readonly NativeType UInt64 = new NativeType(0x0A);
\r
5630 public static readonly NativeType Float32 = new NativeType(0x0B);
\r
5631 public static readonly NativeType Float64 = new NativeType(0x0C);
\r
5632 public static readonly NativeType Currency = new NativeType(0x0F);
\r
5633 public static readonly NativeType BStr = new NativeType(0x13);
\r
5634 public static readonly NativeType LPStr = new NativeType(0x14);
\r
5635 public static readonly NativeType LPWStr = new NativeType(0x15);
\r
5636 public static readonly NativeType LPTStr = new NativeType(0x16);
\r
5637 public static readonly NativeType FixedSysString = new NativeType(0x17);
\r
5638 public static readonly NativeType IUnknown = new NativeType(0x19);
\r
5639 public static readonly NativeType IDispatch = new NativeType(0x1A);
\r
5640 public static readonly NativeType Struct = new NativeType(0x1B);
\r
5641 public static readonly NativeType Interface = new NativeType(0x1C);
\r
5642 public static readonly NativeType Int = new NativeType(0x1F);
\r
5643 public static readonly NativeType UInt = new NativeType(0x20);
\r
5644 public static readonly NativeType ByValStr = new NativeType(0x22);
\r
5645 public static readonly NativeType AnsiBStr = new NativeType(0x23);
\r
5646 public static readonly NativeType TBstr = new NativeType(0x24);
\r
5647 public static readonly NativeType VariantBool = new NativeType(0x25);
\r
5648 public static readonly NativeType FuncPtr = new NativeType(0x26);
\r
5649 public static readonly NativeType AsAny = new NativeType(0x28);
\r
5651 protected byte typeIndex;
\r
5653 internal NativeType(byte tyIx) { typeIndex = tyIx; }
\r
5655 internal byte GetTypeIndex() { return typeIndex; }
\r
5657 internal virtual byte[] ToBlob() {
\r
5658 byte[] bytes = new byte[1];
\r
5659 bytes[0] = GetTypeIndex();
\r
5665 public class NativeArray : NativeType
\r
5667 NativeType elemType;
\r
5668 uint len = 0, parNum = 0;
\r
5671 public NativeArray(NativeType elemType) : base(0x2A) {
\r
5672 this.elemType = elemType;
\r
5675 public NativeArray(NativeType elemType, int len) : base(0x2A) {
\r
5676 this.elemType = elemType;
\r
5680 public NativeArray(NativeType elemType, int numElem, int parNumForLen) : base(0x2A) {
\r
5681 this.elemType = elemType;
\r
5682 len = (uint)numElem;
\r
5683 parNum = (uint)parNumForLen;
\r
5686 internal override byte[] ToBlob() {
\r
5687 MemoryStream str = new MemoryStream();
\r
5688 str.WriteByte(GetTypeIndex());
\r
5689 if (elemType == null) str.WriteByte(0x50); // no info (MAX)
\r
5690 else str.WriteByte(elemType.GetTypeIndex());
\r
5691 MetaData.CompressNum(parNum,str);
\r
5693 MetaData.CompressNum(len,str);
\r
5694 return str.ToArray();
\r
5699 public class SafeArray : NativeType
\r
5701 SafeArrayType elemType;
\r
5703 public SafeArray(SafeArrayType elemType) : base(0x1D) {
\r
5704 this.elemType = elemType;
\r
5707 internal override byte[] ToBlob() {
\r
5708 byte[] bytes = new byte[2];
\r
5709 bytes[0] = GetTypeIndex();
\r
5710 bytes[1] = (byte)elemType;
\r
5716 public class FixedArray : NativeType
\r
5718 NativeType elemType;
\r
5721 public FixedArray(NativeType elemType, int numElems) : base(0x1E) {
\r
5722 this.elemType = elemType;
\r
5723 numElem = (uint)numElems;
\r
5726 internal override byte[] ToBlob() {
\r
5727 MemoryStream str = new MemoryStream();
\r
5728 str.WriteByte(GetTypeIndex());
\r
5729 MetaData.CompressNum(numElem,str);
\r
5730 if (elemType == null) str.WriteByte(0x50); // no info (MAX)
\r
5731 else str.WriteByte(elemType.GetTypeIndex());
\r
5732 return str.ToArray();
\r
5737 public class CustomMarshaller : NativeType
\r
5740 string marshallerName;
\r
5743 public CustomMarshaller(string typeNameOrGUID, string marshallerName,
\r
5744 string optCookie) : base(0x2C) {
\r
5745 typeName = typeNameOrGUID;
\r
5746 this.marshallerName = marshallerName;
\r
5747 cookie = optCookie;
\r
5750 internal override byte[] ToBlob() {
\r
5751 MemoryStream str = new MemoryStream();
\r
5752 BinaryWriter bw = new BinaryWriter(str,new UTF8Encoding());
\r
5753 bw.Write(GetTypeIndex());
\r
5754 bw.Write(typeName.ToCharArray());
\r
5755 bw.Write((byte)0);
\r
5756 bw.Write(marshallerName.ToCharArray());
\r
5757 bw.Write((byte)0);
\r
5758 if (cookie != null) bw.Write(cookie.ToCharArray());
\r
5759 bw.Write((byte)0);
\r
5761 return str.ToArray();
\r
5765 /**************************************************************************/
\r
5767 /// Descriptor for a parameter of a method defined in this assembly/module
\r
5769 public class Param : MetaDataElement
\r
5771 private static readonly ushort hasDefault = 0x1000;
\r
5772 private static readonly ushort hasFieldMarshal = 0x2000;
\r
5776 internal ushort seqNo = 0;
\r
5778 ConstantElem defaultVal;
\r
5780 FieldMarshal marshalInfo;
\r
5783 /// Create a new parameter for a method
\r
5785 /// <param name="mode">param mode (in, out, opt)</param>
\r
5786 /// <param name="parName">parameter name</param>
\r
5787 /// <param name="parType">parameter type</param>
\r
5788 public Param(ParamAttr mode, string parName, Type parType) {
\r
5791 parMode = (ushort)mode;
\r
5792 tabIx = MDTable.Param;
\r
5796 /// Add a default value to this parameter
\r
5798 /// <param name="c">the default value for the parameter</param>
\r
5799 public void AddDefaultValue(Constant cVal) {
\r
5800 defaultVal = new ConstantElem(this,cVal);
\r
5801 parMode |= hasDefault;
\r
5805 /// Add marshalling information about this parameter
\r
5807 public void AddMarshallInfo(NativeType marshallType) {
\r
5808 parMode |= hasFieldMarshal;
\r
5809 marshalInfo = new FieldMarshal(this,marshallType);
\r
5812 internal Type GetParType() { return pType; }
\r
5814 internal sealed override void BuildTables(MetaData md) {
\r
5816 nameIx = md.AddToStringsHeap(pName);
\r
5817 if (defaultVal != null) {
\r
5818 md.AddToTable(MDTable.Constant,defaultVal);
\r
5819 defaultVal.BuildTables(md);
\r
5821 if (marshalInfo != null) {
\r
5822 md.AddToTable(MDTable.FieldMarshal,marshalInfo);
\r
5823 marshalInfo.BuildTables(md);
\r
5828 internal void TypeSig(MemoryStream str) {
\r
5829 pType.TypeSig(str);
\r
5832 internal sealed override uint Size(MetaData md) {
\r
5833 return 4 + md.StringsIndexSize();
\r
5836 internal sealed override void Write(FileImage output) {
\r
5837 output.Write(parMode);
\r
5838 output.Write(seqNo);
\r
5839 output.StringsIndex(nameIx);
\r
5842 internal sealed override uint GetCodedIx(CIx code) {
\r
5844 case (CIx.HasCustomAttr) : return 4;
\r
5845 case (CIx.HasConst) : return 1;
\r
5846 case (CIx.HasFieldMarshal) : return 1;
\r
5852 /**************************************************************************/
\r
5854 /// Base class for the PEFile (starting point)
\r
5856 public class PEFile
\r
5858 private static readonly string mscorlibName = "mscorlib";
\r
5859 private Module thisMod;
\r
5860 private ClassDef moduleClass;
\r
5861 private ArrayList classRefList = new ArrayList();
\r
5862 private ArrayList classDefList = new ArrayList();
\r
5863 private Assembly thisAssembly;
\r
5864 private int corFlags = 1;
\r
5865 FileImage fileImage;
\r
5866 MetaData metaData;
\r
5869 /// Create a new PEFile. Each PEFile is a module.
\r
5871 /// <param name="name">module name, also used for the file name</param>
\r
5872 /// <param name="isDLL">create a .dll or .exe file</param>
\r
5873 /// <param name="hasAssembly">this file is an assembly and
\r
5874 /// will contain the assembly manifest. The assembly name is the
\r
5875 /// same as the module name</param>
\r
5876 public PEFile(string name, bool isDLL, bool hasAssembly) {
\r
5877 // Console.WriteLine(Hex.Byte(0x12));
\r
5878 // Console.WriteLine(Hex.Short(0x1234));
\r
5879 // Console.WriteLine(Hex.Int(0x12345678));
\r
5880 string fName = MakeFileName(null,name,isDLL);
\r
5881 fileImage = new FileImage(isDLL,fName);
\r
5882 InitPEFile(name, fName, hasAssembly);
\r
5886 /// Create a new PEFile. Each PEFile is a module.
\r
5888 /// <param name="name">module name, also used for the file name</param>
\r
5889 /// <param name="isDLL">create a .dll or .exe file</param>
\r
5890 /// <param name="hasAssembly">this file is an assembly and
\r
5891 /// will contain the assembly manifest. The assembly name is the
\r
5892 /// same as the module name</param>
\r
5893 /// <param name="outputDir">write the PEFile to this directory. If this
\r
5894 /// string is null then the output will be to the current directory</param>
\r
5895 public PEFile(string name, bool isDLL, bool hasAssembly, string outputDir) {
\r
5896 // Console.WriteLine(Hex.Byte(0x12));
\r
5897 // Console.WriteLine(Hex.Short(0x1234));
\r
5898 // Console.WriteLine(Hex.Int(0x12345678));
\r
5899 string fName = MakeFileName(outputDir,name,isDLL);
\r
5900 fileImage = new FileImage(isDLL,fName);
\r
5901 InitPEFile(name, fName, hasAssembly);
\r
5905 /// Create a new PEFile
\r
5907 /// <param name="name">module name</param>
\r
5908 /// <param name="isDLL">create a .dll or .exe</param>
\r
5909 /// <param name="hasAssembly">this PEfile is an assembly and
\r
5910 /// will contain the assemly manifest. The assembly name is the
\r
5911 /// same as the module name</param>
\r
5912 /// <param name="outStream">write the PEFile to this stream instead
\r
5913 /// of to a new file</param>
\r
5914 public PEFile(string name, bool isDLL, bool hasAssembly, Stream outStream) {
\r
5915 fileImage = new FileImage(isDLL,outStream);
\r
5916 InitPEFile(name, MakeFileName(null,name,isDLL), hasAssembly);
\r
5919 private void InitPEFile(string name, string fName, bool hasAssembly) {
\r
5920 metaData = fileImage.GetMetaData();
\r
5921 thisMod = new Module(fName,metaData);
\r
5922 if (hasAssembly) {
\r
5923 thisAssembly = new Assembly(name,metaData);
\r
5924 metaData.AddToTable(MDTable.Assembly,thisAssembly);
\r
5926 moduleClass = AddClass(TypeAttr.Private,"","<Module>");
\r
5927 moduleClass.SpecialNoSuper();
\r
5928 metaData.AddToTable(MDTable.Module,thisMod);
\r
5932 /// Set the subsystem (.subsystem) (Default is Windows Console mode)
\r
5934 /// <param name="subS">subsystem value</param>
\r
5935 public void SetSubSystem(SubSystem subS) {
\r
5936 fileImage.subSys = subS;
\r
5940 /// Set the flags (.corflags)
\r
5942 /// <param name="flags">the flags value</param>
\r
5943 public void SetCorFlags(int flags) {
\r
5947 private string MakeFileName(string dirName, string name, bool isDLL) {
\r
5948 string result = "";
\r
5949 if ((dirName != null) && (dirName.CompareTo("") != 0)) {
\r
5951 if (!dirName.EndsWith("\\")) result += "\\";
\r
5955 // if (isDLL) result += ".dll"; else result += ".exe";
\r
5961 /// Add an external assembly to this PEFile (.assembly extern)
\r
5963 /// <param name="assemName">the external assembly name</param>
\r
5964 /// <returns>a descriptor for this external assembly</returns>
\r
5965 public AssemblyRef AddExternAssembly(string assemName) {
\r
5966 if (assemName.CompareTo(mscorlibName) == 0) return metaData.mscorlib;
\r
5967 AssemblyRef anAssem = new AssemblyRef(metaData,assemName);
\r
5968 metaData.AddToTable(MDTable.AssemblyRef,anAssem);
\r
5969 // Console.WriteLine("Adding assembly " + assemName);
\r
5974 /// Add an external module to this PEFile (.module extern)
\r
5976 /// <param name="name">the external module name</param>
\r
5977 /// <returns>a descriptor for this external module</returns>
\r
5978 public ModuleRef AddExternModule(string name) {
\r
5979 ModuleRef modRef = new ModuleRef(metaData,name);
\r
5980 metaData.AddToTable(MDTable.ModuleRef,modRef);
\r
5985 /// Add a "global" method to this module
\r
5987 /// <param name="name">method name</param>
\r
5988 /// <param name="retType">return type</param>
\r
5989 /// <param name="pars">method parameters</param>
\r
5990 /// <returns>a descriptor for this new "global" method</returns>
\r
5991 public MethodDef AddMethod(string name, Type retType, Param[] pars) {
\r
5992 return moduleClass.AddMethod(name,retType,pars);
\r
5996 /// Add a "global" method to this module
\r
5998 /// <param name="mAtts">method attributes</param>
\r
5999 /// <param name="iAtts">method implementation attributes</param>
\r
6000 /// <param name="name">method name</param>
\r
6001 /// <param name="retType">return type</param>
\r
6002 /// <param name="pars">method parameters</param>
\r
6003 /// <returns>a descriptor for this new "global" method</returns>
\r
6004 public MethodDef AddMethod(MethAttr mAtts, ImplAttr iAtts, string name, Type retType, Param[] pars) {
\r
6005 return moduleClass.AddMethod(mAtts,iAtts,name,retType,pars);
\r
6008 public MethodRef AddMethodToTypeSpec (Type item, string name, Type retType, Type[] pars) {
\r
6009 MethodRef meth = new MethodRef (item.GetTypeSpec (metaData), name, retType, pars, false, null);
\r
6010 metaData.AddToTable (MDTable.MemberRef,meth);
\r
6014 public MethodRef AddVarArgMethodToTypeSpec (Type item, string name, Type retType,
\r
6015 Type[] pars, Type[] optPars) {
\r
6016 MethodRef meth = new MethodRef(item.GetTypeSpec (metaData), name,retType,pars,true,optPars);
\r
6017 metaData.AddToTable(MDTable.MemberRef,meth);
\r
6021 public FieldRef AddFieldToTypeSpec (Type item, string name, Type fType) {
\r
6022 FieldRef field = new FieldRef (item.GetTypeSpec (metaData), name,fType);
\r
6023 metaData.AddToTable (MDTable.MemberRef,field);
\r
6028 /// Add a "global" field to this module
\r
6030 /// <param name="name">field name</param>
\r
6031 /// <param name="fType">field type</param>
\r
6032 /// <returns>a descriptor for this new "global" field</returns>
\r
6033 public FieldDef AddField(string name, Type fType) {
\r
6034 return moduleClass.AddField(name,fType);
\r
6038 /// Add a "global" field to this module
\r
6040 /// <param name="attrSet">attributes of this field</param>
\r
6041 /// <param name="name">field name</param>
\r
6042 /// <param name="fType">field type</param>
\r
6043 /// <returns>a descriptor for this new "global" field</returns>
\r
6044 public FieldDef AddField(FieldAttr attrSet, string name, Type fType) {
\r
6045 return moduleClass.AddField(attrSet,name,fType);
\r
6049 /// Add a class to this module
\r
6051 /// <param name="attrSet">attributes of this class</param>
\r
6052 /// <param name="nsName">name space name</param>
\r
6053 /// <param name="name">class name</param>
\r
6054 /// <returns>a descriptor for this new class</returns>
\r
6055 public ClassDef AddClass(TypeAttr attrSet, string nsName, string name) {
\r
6056 ClassDef aClass = new ClassDef(attrSet,nsName,name,metaData);
\r
6057 metaData.AddToTable(MDTable.TypeDef,aClass);
\r
6062 /// Add a class which extends System.ValueType to this module
\r
6064 /// <param name="attrSet">attributes of this class</param>
\r
6065 /// <param name="nsName">name space name</param>
\r
6066 /// <param name="name">class name</param>
\r
6067 /// <returns>a descriptor for this new class</returns>
\r
6068 public ClassDef AddValueClass(TypeAttr attrSet, string nsName, string name) {
\r
6069 ClassDef aClass = new ClassDef(attrSet,nsName,name,metaData);
\r
6070 aClass.MakeValueClass();
\r
6071 metaData.AddToTable(MDTable.TypeDef,aClass);
\r
6076 /// Add a class to this module
\r
6078 /// <param name="attrSet">attributes of this class</param>
\r
6079 /// <param name="nsName">name space name</param>
\r
6080 /// <param name="name">class name</param>
\r
6081 /// <param name="superType">super type of this class (extends)</param>
\r
6082 /// <returns>a descriptor for this new class</returns>
\r
6083 public ClassDef AddClass(TypeAttr attrSet, string nsName, string name, Class superType) {
\r
6084 ClassDef aClass = new ClassDef(attrSet,nsName,name,metaData);
\r
6085 aClass.SetSuper(superType);
\r
6086 metaData.AddToTable(MDTable.TypeDef,aClass);
\r
6090 public FileRef AddFile(string fName, byte[] hashBytes, bool hasMetaData, bool entryPoint) {
\r
6091 FileRef file = new FileRef(fName,hashBytes,hasMetaData,entryPoint,metaData);
\r
6092 metaData.AddToTable(MDTable.File,file);
\r
6097 /// Add a manifest resource to this PEFile NOT YET IMPLEMENTED
\r
6099 /// <param name="mr"></param>
\r
6100 public void AddManifestResource(ManifestResource mr) {
\r
6101 metaData.AddToTable(MDTable.ManifestResource,mr);
\r
6102 //mr.FixName(metaData);
\r
6106 /// Write out the PEFile (the "bake" function)
\r
6108 public void WritePEFile() { /* the "bake" function */
\r
6109 fileImage.MakeFile();
\r
6113 /// Get the descriptor of this module
\r
6115 /// <returns>the descriptor for this module</returns>
\r
6116 public Module GetThisModule() {
\r
6121 /// Get the descriptor for this assembly. The PEFile must have been
\r
6122 /// created with hasAssembly = true
\r
6124 /// <returns>the descriptor for this assembly</returns>
\r
6125 public Assembly GetThisAssembly() {
\r
6126 return thisAssembly;
\r
6131 /**************************************************************************/
\r
6133 /// Descriptor for the Primitive types defined in IL
\r
6135 public class PrimitiveType : Type
\r
6137 private string name;
\r
6138 private int systemTypeIndex;
\r
6139 public static int NumSystemTypes = 18;
\r
6141 public static readonly PrimitiveType Void = new PrimitiveType(0x01,"Void",0);
\r
6142 public static readonly PrimitiveType Boolean = new PrimitiveType(0x02,"Boolean",1);
\r
6143 public static readonly PrimitiveType Char = new PrimitiveType(0x03,"Char",2);
\r
6144 public static readonly PrimitiveType Int8 = new PrimitiveType(0x04,"SByte",3);
\r
6145 public static readonly PrimitiveType UInt8 = new PrimitiveType(0x05,"Byte",4);
\r
6146 public static readonly PrimitiveType Int16 = new PrimitiveType(0x06,"Int16",5);
\r
6147 public static readonly PrimitiveType UInt16 = new PrimitiveType(0x07,"UInt16",6);
\r
6148 public static readonly PrimitiveType Int32 = new PrimitiveType(0x08,"Int32",7);
\r
6149 public static readonly PrimitiveType UInt32 = new PrimitiveType(0x09,"UInt32",8);
\r
6150 public static readonly PrimitiveType Int64 = new PrimitiveType(0x0A,"Int64",9);
\r
6151 public static readonly PrimitiveType UInt64 = new PrimitiveType(0x0B,"UInt64",10);
\r
6152 public static readonly PrimitiveType Float32 = new PrimitiveType(0x0C,"Single",11);
\r
6153 public static readonly PrimitiveType Float64 = new PrimitiveType(0x0D,"Double",12);
\r
6154 public static readonly PrimitiveType String = new PrimitiveType(0x0E,"String",13);
\r
6155 internal static readonly PrimitiveType Class = new PrimitiveType(0x12);
\r
6156 public static readonly PrimitiveType TypedRef = new PrimitiveType(0x16,"TypedReference",14);
\r
6157 public static readonly PrimitiveType IntPtr = new PrimitiveType(0x18,"IntPtr",15);
\r
6158 public static readonly PrimitiveType UIntPtr = new PrimitiveType(0x19,"UIntPtr",16);
\r
6159 public static readonly PrimitiveType Object = new PrimitiveType(0x1C,"Object",17);
\r
6160 internal static readonly PrimitiveType ClassType = new PrimitiveType(0x50);
\r
6161 public static readonly PrimitiveType NativeInt = IntPtr;
\r
6162 public static readonly PrimitiveType NativeUInt = UIntPtr;
\r
6164 internal PrimitiveType(byte typeIx) : base(typeIx) { }
\r
6166 internal PrimitiveType(byte typeIx, string name, int STIx) : base(typeIx) {
\r
6168 this.systemTypeIndex = STIx;
\r
6171 internal string GetName() { return name; }
\r
6173 internal int GetSystemTypeIx() { return systemTypeIndex; }
\r
6175 internal sealed override void TypeSig(MemoryStream str) {
\r
6176 str.WriteByte(typeIndex);
\r
6179 internal override MetaDataElement GetTypeSpec(MetaData md) {
\r
6180 TypeSpec tS = md.GetPrimitiveTypeSpec(systemTypeIndex);
\r
6182 tS = new TypeSpec(this,md);
\r
6183 md.SetPrimitiveTypeSpec(systemTypeIndex,tS);
\r
6184 md.AddToTable(MDTable.TypeSpec,tS);
\r
6191 /**************************************************************************/
\r
6193 /// Descriptor for the Property of a class
\r
6195 public class Property : Feature
\r
6197 private static readonly byte PropertyTag = 0x8;
\r
6198 MethodDef getterMeth;
\r
6199 ConstantElem constVal;
\r
6200 uint typeBlobIx = 0;
\r
6205 internal Property(string name, Type retType, Type[] pars, ClassDef parent) : base(name, parent) {
\r
6206 returnType = retType;
\r
6208 if (pars != null) numPars = (uint)pars.Length;
\r
6209 tabIx = MDTable.Property;
\r
6213 /// Add a set method to this property
\r
6215 /// <param name="setter">the set method</param>
\r
6216 public void AddSetter(MethodDef setter) {
\r
6217 AddMethod(setter,MethodType.Setter);
\r
6221 /// Add a get method to this property
\r
6223 /// <param name="getter">the get method</param>
\r
6224 public void AddGetter(MethodDef getter) {
\r
6225 AddMethod(getter,MethodType.Getter);
\r
6226 getterMeth = getter;
\r
6230 /// Add another method to this property
\r
6232 /// <param name="other">the method</param>
\r
6233 public void AddOther(MethodDef other) {
\r
6234 AddMethod(other,MethodType.Other);
\r
6238 /// Add an initial value for this property
\r
6240 /// <param name="constVal">the initial value for this property</param>
\r
6241 public void AddInitValue(Constant constVal) {
\r
6242 this.constVal = new ConstantElem(this,constVal);
\r
6245 internal sealed override void BuildTables(MetaData md) {
\r
6247 nameIx = md.AddToStringsHeap(name);
\r
6248 MemoryStream sig = new MemoryStream();
\r
6249 sig.WriteByte(PropertyTag);
\r
6250 MetaData.CompressNum(numPars,sig);
\r
6251 returnType.TypeSig(sig);
\r
6252 for (int i=0; i < numPars; i++) {
\r
6253 parList[i].TypeSig(sig);
\r
6255 typeBlobIx = md.AddToBlobHeap(sig.ToArray());
\r
6256 for (int i=0; i < tide; i++) {
\r
6257 md.AddToTable(MDTable.MethodSemantics,methods[i]);
\r
6259 if (constVal != null) {
\r
6260 md.AddToTable(MDTable.Constant,constVal);
\r
6261 constVal.BuildTables(md);
\r
6266 internal sealed override uint Size(MetaData md) {
\r
6267 return 2 + md.StringsIndexSize() + md.BlobIndexSize();
\r
6270 internal sealed override void Write(FileImage output) {
\r
6271 output.Write(flags);
\r
6272 output.StringsIndex(nameIx);
\r
6273 output.BlobIndex(typeBlobIx);
\r
6276 internal sealed override uint GetCodedIx(CIx code) {
\r
6278 case (CIx.HasCustomAttr) : return 9;
\r
6279 case (CIx.HasConst) : return 2;
\r
6280 case (CIx.HasSemantics) : return 1;
\r
6286 /**************************************************************************/
\r
6288 /// Descriptor for an pointer (type * or type &)
\r
6290 public abstract class PtrType : Type
\r
6294 internal PtrType(Type bType, byte typeIx) : base(typeIx)
\r
6297 tabIx = MDTable.TypeSpec;
\r
6300 internal sealed override void TypeSig(MemoryStream str) {
\r
6301 str.WriteByte(typeIndex);
\r
6302 baseType.TypeSig(str);
\r
6306 /**************************************************************************/
\r
6308 /// Descriptor for a managed pointer (type & or byref)
\r
6311 public class ManagedPointer : PtrType // <type> & (BYREF)
\r
6315 /// Create new managed pointer to baseType
\r
6317 /// <param name="bType">the base type of the pointer</param>
\r
6318 public ManagedPointer(Type baseType) : base(baseType,0x10) { }
\r
6321 /**************************************************************************/
\r
6323 /// Descriptor for an unmanaged pointer (type *)
\r
6325 public class UnmanagedPointer : PtrType // PTR
\r
6328 /// Create a new unmanaged pointer to baseType
\r
6330 /// <param name="baseType">the base type of the pointer</param>
\r
6331 public UnmanagedPointer(Type baseType) : base(baseType, 0x0F) { }
\r
6334 /**************************************************************************/
\r
6336 /// Base class for scopes (extended by Module, ModuleRef, Assembly, AssemblyRef)
\r
6338 public abstract class ResolutionScope : MetaDataElement
\r
6340 protected uint nameIx = 0;
\r
6341 protected MetaData metaData;
\r
6342 protected string name;
\r
6344 internal ResolutionScope(string name, MetaData md)
\r
6348 nameIx = md.AddToStringsHeap(name);
\r
6351 internal string GetName() { return name; }
\r
6354 /**************************************************************************/
\r
6356 /// Descriptor for a Section in a PEFile eg .text, .sdata
\r
6358 internal class Section {
\r
6359 private static readonly uint relocPageSize = 4096; // 4K pages for fixups
\r
6362 uint offset = 0, tide = 0, size = 0, rva = 0, relocTide = 0;
\r
6363 //uint relocOff = 0;
\r
6364 uint flags = 0, padding = 0;
\r
6367 internal Section(string sName, uint sFlags) {
\r
6368 name = sName.ToCharArray();
\r
6372 internal uint Tide() { return tide; }
\r
6374 internal void IncTide(uint incVal) { tide += incVal; }
\r
6376 internal uint Padding() { return padding; }
\r
6378 internal uint Size() { return size; }
\r
6380 internal void SetSize(uint pad) {
\r
6382 size = tide + padding;
\r
6385 internal uint RVA() { return rva; }
\r
6387 internal void SetRVA(uint rva) { this.rva = rva; }
\r
6389 internal uint Offset() { return offset; }
\r
6391 internal void SetOffset(uint offs) { offset = offs; }
\r
6393 internal void DoBlock(BinaryWriter reloc, uint page, int start, int end) {
\r
6394 //Console.WriteLine("rva = " + rva + " page = " + page);
\r
6395 reloc.Write(rva + page);
\r
6396 reloc.Write((uint)(((end-start+1)*2) + 8));
\r
6397 for (int j=start; j < end; j++) {
\r
6398 //Console.WriteLine("reloc offset = " + relocs[j]);
\r
6399 reloc.Write((ushort)((0x3 << 12) | (relocs[j] - page)));
\r
6401 reloc.Write((ushort)0);
\r
6404 internal void DoRelocs(BinaryWriter reloc) {
\r
6405 if (relocTide > 0) {
\r
6406 //relocOff = (uint)reloc.Seek(0,SeekOrigin.Current);
\r
6407 uint block = (relocs[0]/relocPageSize + 1) * relocPageSize;
\r
6409 for (int i=1; i < relocTide; i++) {
\r
6410 if (relocs[i] >= block) {
\r
6411 DoBlock(reloc,block-relocPageSize,start,i);
\r
6413 block = (relocs[i]/relocPageSize + 1) * relocPageSize;
\r
6416 DoBlock(reloc,block-relocPageSize,start,(int)relocTide);
\r
6420 internal void AddReloc(uint offs) {
\r
6422 if (relocs == null) {
\r
6423 relocs = new uint[5];
\r
6425 if (relocTide >= relocs.Length) {
\r
6426 uint[] tmp = relocs;
\r
6427 relocs = new uint[tmp.Length + 5];
\r
6428 for (int i=0; i < relocTide; i++) {
\r
6429 relocs[i] = tmp[i];
\r
6432 while ((pos < relocTide) && (relocs[pos] < offs)) pos++;
\r
6433 for (int i=pos; i < relocTide; i++) {
\r
6434 relocs[i+1] = relocs[i];
\r
6437 relocs[pos] = offs;
\r
6441 internal void WriteHeader(BinaryWriter output, uint relocRVA) {
\r
6442 output.Write(name);
\r
6443 output.Write(tide);
\r
6444 output.Write(rva);
\r
6445 output.Write(size);
\r
6446 output.Write(offset);
\r
6448 //output.Write(relocRVA + relocOff);
\r
6451 //output.Write((ushort)relocTide);
\r
6452 //output.Write((ushort)0);
\r
6453 output.Write(flags);
\r
6457 /**************************************************************************/
\r
6458 public abstract class Signature : MetaDataElement
\r
6460 protected uint sigIx;
\r
6462 internal Signature() {
\r
6463 tabIx = MDTable.StandAloneSig;
\r
6466 internal sealed override uint Size(MetaData md) {
\r
6467 return md.BlobIndexSize();
\r
6470 internal sealed override void Write(FileImage output) {
\r
6471 output.BlobIndex(sigIx);
\r
6474 internal sealed override uint GetCodedIx(CIx code) { return (uint)tabIx; }
\r
6477 /**************************************************************************/
\r
6479 /// Descriptor for a class defined in System (mscorlib)
\r
6481 internal class SystemClass : ClassRef
\r
6483 PrimitiveType elemType;
\r
6485 internal SystemClass(PrimitiveType eType, AssemblyRef paren, MetaData md)
\r
6486 : base("System",eType.GetName(),md) {
\r
6491 internal override sealed MetaDataElement GetTypeSpec(MetaData md) {
\r
6492 if (typeSpec == null) typeSpec = (TypeSpec)elemType.GetTypeSpec(md);
\r
6497 internal sealed override void TypeSig(MemoryStream str) {
\r
6498 str.WriteByte(elemType.GetTypeIndex());
\r
6502 /**************************************************************************/
\r
6504 /// Base class for all IL types
\r
6506 public abstract class Type : MetaDataElement {
\r
6507 protected byte typeIndex;
\r
6508 protected TypeSpec typeSpec;
\r
6510 internal Type(byte tyIx) { typeIndex = tyIx; }
\r
6512 internal byte GetTypeIndex() { return typeIndex; }
\r
6514 internal virtual MetaDataElement GetTypeSpec(MetaData md) {
\r
6515 if (typeSpec == null) {
\r
6516 typeSpec = new TypeSpec(this,md);
\r
6517 md.AddToTable(MDTable.TypeSpec,typeSpec);
\r
6522 internal virtual void TypeSig(MemoryStream str) {
\r
6523 throw(new TypeSignatureException(this.GetType().AssemblyQualifiedName +
\r
6524 " doesn't have a type signature!!"));
\r
6529 /**************************************************************************/
\r
6531 public class TypeSpec : MetaDataElement {
\r
6534 internal TypeSpec(Type aType, MetaData md) {
\r
6535 MemoryStream sig = new MemoryStream();
\r
6536 aType.TypeSig(sig);
\r
6537 sigIx = md.AddToBlobHeap(sig.ToArray());
\r
6538 tabIx = MDTable.TypeSpec;
\r
6541 internal sealed override uint GetCodedIx(CIx code) {
\r
6543 case (CIx.TypeDefOrRef) : return 2;
\r
6544 case (CIx.HasCustomAttr) : return 13;
\r
6545 case (CIx.MemberRefParent) : return 4;
\r
6550 internal override uint Size(MetaData md) {
\r
6551 return md.BlobIndexSize();
\r
6554 internal sealed override void Write(FileImage output) {
\r
6555 //Console.WriteLine("Writing the blob index for a TypeSpec");
\r
6556 output.BlobIndex(sigIx);
\r