* PEAPI.cs: Use bytes not bits for constant sizes.
[mono.git] / mcs / class / PEAPI / PEAPI.cs
1 using System;\r
2 using System.IO;\r
3 using System.Collections;\r
4 using System.Text;\r
5 \r
6 namespace PEAPI \r
7 {\r
8   public class Hex {\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
18 \r
19     public static String Byte(int b) {\r
20       char[] str = new char[2];\r
21       uint num = (uint)b;\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
27     }\r
28 \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
42     }\r
43 \r
44     public static String Int(int val) {\r
45       char[] str = new char[8];\r
46       uint num = (uint)val;\r
47       int strIx = 7;\r
48       for (int i=0; i < iByteMask.Length; i++) {\r
49         uint b = num & iByteMask[i];\r
50         b >>= (i*8);\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
55       }\r
56       return new String(str);\r
57     }\r
58  \r
59     public static String Int(uint num) {\r
60       char[] str = new char[8];\r
61       int strIx = 7;\r
62       for (int i=0; i < iByteMask.Length; i++) {\r
63         uint b = num & iByteMask[i];\r
64         b >>= (i*8);\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
69       }\r
70       return new String(str);\r
71     }\r
72 \r
73     public static String Long(long lnum) {\r
74       ulong num = (ulong)lnum;\r
75       char[] str = new char[16];\r
76       int strIx = 15;\r
77       for (int i=0; i < lByteMask.Length; i++) {\r
78         ulong b = num & lByteMask[i];\r
79         b >>= (i*8);\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
84       }\r
85       return new String(str);\r
86     }\r
87   }\r
88 \r
89   public class NotYetImplementedException : System.Exception \r
90   {\r
91      public NotYetImplementedException(string msg) : base(msg + " Not Yet Implemented") { }\r
92   }\r
93 \r
94   public class TypeSignatureException : System.Exception {\r
95     public TypeSignatureException(string msg) : base(msg) { }\r
96   }\r
97 \r
98   public class MVar : Type {\r
99 \r
100             private int index;\r
101 \r
102             public MVar (int index) : base (0x1E) {\r
103                     this.index = index;\r
104                     tabIx = MDTable.TypeSpec;\r
105             }\r
106 \r
107             internal sealed override void TypeSig(MemoryStream str) {\r
108                     str.WriteByte(typeIndex);\r
109                     MetaData.CompressNum ((uint) index, str);\r
110             }\r
111     }\r
112 \r
113     public class GenericTypeSpec : Type {\r
114 \r
115             private int index;\r
116 \r
117             public GenericTypeSpec (int index) : base (0x13) {\r
118                     this.index = index;\r
119                     tabIx = MDTable.TypeSpec;\r
120             }\r
121 \r
122             internal sealed override void TypeSig(MemoryStream str) {\r
123                     str.WriteByte(typeIndex);\r
124                     MetaData.CompressNum ((uint) index, str);\r
125             }\r
126     }\r
127 \r
128   public class GenericTypeInst : Type {\r
129 \r
130           private Type gen_type;\r
131           private Type[] gen_param;\r
132 \r
133           public GenericTypeInst (Type gen_type, Type[] gen_param) : base (0x15)\r
134           {\r
135                   typeIndex = 0x15;\r
136                   this.gen_type = gen_type;\r
137                   this.gen_param = gen_param;\r
138                   tabIx = MDTable.TypeSpec;\r
139   }\r
140 \r
141           internal sealed override void TypeSig(MemoryStream str) {\r
142                   str.WriteByte(typeIndex);\r
143                   gen_type.TypeSig (str);\r
144                   MetaData.CompressNum ((uint) gen_param.Length, str);\r
145                   foreach (Type param in gen_param)\r
146                           param.TypeSig (str);\r
147             }\r
148   }\r
149
150   public class GenericMethodSig {
151
152           private Type[] gen_param;
153
154           public GenericMethodSig (Type[] gen_param)
155           {
156                   this.gen_param = gen_param;
157           }
158
159           internal void TypeSig (MemoryStream str)
160           {
161                   MetaData.CompressNum ((uint) gen_param.Length, str); // THIS IS NOT RIGHT, but works
162                   MetaData.CompressNum ((uint) gen_param.Length, str);
163                   foreach (Type param in gen_param)
164                           param.TypeSig (str);
165           }
166
167           internal uint GetSigIx (MetaData md)
168           {
169                   MemoryStream sig = new MemoryStream();
170                   TypeSig (sig);
171                   return md.AddToBlobHeap (sig.ToArray());
172           }
173   }
174
175         public class Sentinel : Type {
176
177             public Sentinel () : base (0x41) { }
178
179             internal sealed override void TypeSig(MemoryStream str) {
180                     str.WriteByte(typeIndex);
181             }
182         }
183
184         /// <summary>\r
185         /// The IL Array type\r
186         /// </summary>\r
187         public abstract class Array : Type\r
188         {\r
189 \r
190     protected Type elemType;\r
191                 protected MetaData metaData;\r
192                 protected string cnameSpace, cname;\r
193 \r
194     internal Array(Type eType, byte TypeId) : base(TypeId) {\r
195       elemType = eType;\r
196                         tabIx = MDTable.TypeSpec;\r
197     }\r
198 \r
199         }\r
200 \r
201   /**************************************************************************/  \r
202   \r
203   /// <summary>\r
204   /// Single dimensional array with zero lower bound\r
205   /// </summary>\r
206   public class ZeroBasedArray : Array {\r
207 \r
208     /// <summary>\r
209     /// Create a new array  -   elementType[]\r
210     /// </summary>\r
211     /// <param name="elementType">the type of the array elements</param>\r
212     public ZeroBasedArray(Type elementType) : base (elementType,0x1D) { }\r
213 \r
214     internal sealed override void TypeSig(MemoryStream str) {\r
215       str.WriteByte(typeIndex);\r
216       elemType.TypeSig(str); \r
217     }\r
218 \r
219   }\r
220 \r
221 \r
222   /**************************************************************************/           \r
223 \r
224   /// <summary>\r
225   /// Multi dimensional array with explicit bounds\r
226   /// </summary>\r
227   public class BoundArray : Array {\r
228     int[] lowerBounds;\r
229     int[] sizes;\r
230     uint numDims;\r
231 \r
232     /// <summary>\r
233     /// Create a new multi dimensional array type \r
234     /// eg. elemType[1..5,3..10,5,,] would be \r
235     /// new BoundArray(elemType,5,[1,3,0],[5,10,4])\r
236     /// </summary>\r
237     /// <param name="elementType">the type of the elements</param>\r
238     /// <param name="dimensions">the number of dimensions</param>\r
239     /// <param name="loBounds">lower bounds of dimensions</param>\r
240     /// <param name="upBounds">upper bounds of dimensions</param>\r
241     public BoundArray(Type elementType, uint dimensions, int[] loBounds, \r
242       int[] upBounds) : base (elementType,0x14) {\r
243       numDims = dimensions;\r
244       lowerBounds = loBounds;\r
245       sizes = new int[loBounds.Length];\r
246       for (int i=0; i < loBounds.Length; i++) {\r
247         sizes[i] = upBounds[i] - loBounds[i] + 1;\r
248       }\r
249     }\r
250 \r
251     /// <summary>\r
252     /// Create a new multi dimensional array type \r
253     /// eg. elemType[5,10,20] would be new BoundArray(elemType,3,[5,10,20])\r
254     /// </summary>\r
255     /// <param name="elementType">the type of the elements</param>\r
256     /// <param name="dimensions">the number of dimensions</param>\r
257     /// <param name="size">the sizes of the dimensions</param>\r
258     public BoundArray(Type elementType, uint dimensions, int[] size) \r
259                                                   : base (elementType,0x14) {\r
260       numDims = dimensions;\r
261       sizes = size;\r
262     }\r
263 \r
264     /// <summary>\r
265     /// Create a new multi dimensional array type \r
266     /// eg. elemType[,,] would be new BoundArray(elemType,3)\r
267     /// </summary>\r
268     /// <param name="elementType">the type of the elements</param>\r
269     /// <param name="dimensions">the number of dimensions</param>\r
270     public BoundArray(Type elementType, uint dimensions)\r
271                                                   : base (elementType,0x14) {\r
272       numDims = dimensions;\r
273     }\r
274 \r
275     internal sealed override void TypeSig(MemoryStream str) {\r
276       str.WriteByte(typeIndex);\r
277       elemType.TypeSig(str);\r
278       MetaData.CompressNum(numDims,str);\r
279       if ((sizes != null) && (sizes.Length > 0)) {\r
280         MetaData.CompressNum((uint)sizes.Length,str);\r
281         for (int i=0; i < sizes.Length; i++) {\r
282           MetaData.CompressNum((uint)sizes[i],str);\r
283         }\r
284       } else str.WriteByte(0);\r
285       if ((lowerBounds != null) && (lowerBounds.Length > 0)) {\r
286         MetaData.CompressNum((uint)lowerBounds.Length,str);\r
287         for (int i=0; i < lowerBounds.Length; i++) {\r
288           MetaData.CompressNum((uint)lowerBounds[i],str);\r
289         }\r
290       } else str.WriteByte(0);\r
291     }\r
292   \r
293   }\r
294   /**************************************************************************/  \r
295   /// <summary>\r
296   /// Descriptor for THIS assembly (.assembly)\r
297   /// </summary>\r
298   public class Assembly : ResolutionScope \r
299   {\r
300     ushort majorVer, minorVer, buildNo, revisionNo;\r
301     uint flags;\r
302     HashAlgorithm hashAlgId = HashAlgorithm.None;\r
303     uint keyIx = 0, cultIx = 0;\r
304     \r
305     internal Assembly(string name, MetaData md) : base(name,md) {\r
306       tabIx = MDTable.Assembly;\r
307     }\r
308 \r
309     /// <summary>\r
310     /// Add details about THIS assembly\r
311     /// </summary>\r
312     /// <param name="majVer">Major Version</param>\r
313     /// <param name="minVer">Minor Version</param>\r
314     /// <param name="bldNo">Build Number</param>\r
315     /// <param name="revNo">Revision Number</param>\r
316     /// <param name="key">Hash Key</param>\r
317     /// <param name="hash">Hash Algorithm</param>\r
318     /// <param name="cult">Culture</param>\r
319     public void AddAssemblyInfo(int majVer, int minVer, int bldNo, int revNo, \r
320                               byte[] key, HashAlgorithm hash, string cult) {\r
321       majorVer = (ushort)majVer;\r
322       minorVer = (ushort)minVer;\r
323       buildNo = (ushort)bldNo;\r
324       revisionNo = (ushort)revNo;\r
325       hashAlgId = hash;\r
326       keyIx = metaData.AddToBlobHeap(key);\r
327       cultIx = metaData.AddToStringsHeap(cult);\r
328     }\r
329 \r
330     /// <summary>\r
331     /// Add an attribute to THIS assembly\r
332     /// </summary>\r
333     /// <param name="aa">assembly attribute</param>\r
334     public void AddAssemblyAttr(AssemAttr aa) {\r
335       flags |= (uint)aa;\r
336     }\r
337 \r
338     internal sealed override uint Size(MetaData md) {\r
339       return 16 + md.BlobIndexSize() + 2 * md.StringsIndexSize();\r
340     }\r
341 \r
342     internal sealed override void Write(FileImage output) {\r
343 //      Console.WriteLine("Writing assembly element with nameIx of " + nameIx + " at file offset " + output.Seek(0,SeekOrigin.Current));\r
344       output.Write((uint)hashAlgId);\r
345       output.Write(majorVer);\r
346       output.Write(minorVer);\r
347       output.Write(buildNo);\r
348       output.Write(revisionNo);\r
349       output.Write(flags);\r
350       output.BlobIndex(keyIx);\r
351       output.StringsIndex(nameIx);\r
352       output.StringsIndex(cultIx);\r
353     }\r
354 \r
355     internal sealed override uint GetCodedIx(CIx code) {\r
356       switch (code) {\r
357         case (CIx.HasCustomAttr) : return 14; \r
358         case (CIx.HasDeclSecurity) : return 2; \r
359       }\r
360       return 0;\r
361     }\r
362 \r
363   }     \r
364   /**************************************************************************/  \r
365         /// <summary>\r
366         /// A reference to an external assembly (.assembly extern)\r
367         /// </summary>\r
368         public class AssemblyRef : ResolutionScope\r
369         {\r
370     private ushort major, minor, build, revision;\r
371     uint flags, keyIx, hashIx, cultIx;\r
372     bool hasVersion = false, isKeyToken = false;\r
373     byte[] keyBytes;\r
374     string culture;\r
375 \r
376     internal AssemblyRef(MetaData md, string name) : base(name,md) {\r
377       tabIx = MDTable.AssemblyRef;\r
378                 }\r
379 \r
380     /// <summary>\r
381     /// Add version information about this external assembly\r
382     /// </summary>\r
383     /// <param name="majVer">Major Version</param>\r
384     /// <param name="minVer">Minor Version</param>\r
385     /// <param name="bldNo">Build Number</param>\r
386     /// <param name="revNo">Revision Number</param>\r
387     public void AddVersionInfo(int majVer, int minVer, int bldNo, int revNo) {\r
388       major = (ushort)majVer;\r
389       minor = (ushort)minVer;\r
390       build = (ushort)bldNo;\r
391       revision = (ushort)revNo;\r
392       hasVersion = true;\r
393     }\r
394 \r
395     /// <summary>\r
396     /// Add the hash value for this external assembly\r
397     /// </summary>\r
398     /// <param name="hash">bytes of the hash value</param>\r
399     public void AddHash(byte[] hash) {\r
400       hashIx = metaData.AddToBlobHeap(hash); \r
401     }\r
402 \r
403     /// <summary>\r
404     /// Set the culture for this external assembly\r
405     /// </summary>\r
406     /// <param name="cult">the culture string</param>\r
407     public void AddCulture(string cult) {\r
408       cultIx = metaData.AddToStringsHeap(cult);\r
409       culture = cult;\r
410     }\r
411 \r
412     /// <summary>\r
413     /// Add the full public key for this external assembly\r
414     /// </summary>\r
415     /// <param name="key">bytes of the public key</param>\r
416     public void AddKey(byte[] key) {\r
417       flags |= 0x0001;   // full public key\r
418       keyBytes = key;\r
419       keyIx = metaData.AddToBlobHeap(key); \r
420     }\r
421 \r
422     /// <summary>\r
423     /// Add the public key token (low 8 bytes of the public key)\r
424     /// </summary>\r
425     /// <param name="key">low 8 bytes of public key</param>\r
426     public void AddKeyToken(byte[] key) {\r
427       keyIx = metaData.AddToBlobHeap(key); \r
428       keyBytes = key;\r
429       isKeyToken = true;\r
430     }\r
431 \r
432     /// <summary>\r
433     /// Add a class to this external assembly\r
434     /// </summary>\r
435     /// <param name="nsName">name space name</param>\r
436     /// <param name="name">class name</param>\r
437     /// <returns></returns>\r
438     public virtual ClassRef AddClass(string nsName, string name) {\r
439       ClassRef aClass = new ClassRef(nsName,name,metaData);\r
440       metaData.AddToTable(MDTable.TypeRef,aClass);\r
441       aClass.SetParent(this);\r
442       return aClass;\r
443     }\r
444 \r
445     /// <summary>\r
446     /// Add a value class to this external assembly\r
447     /// </summary>\r
448     /// <param name="nsName">name space name</param>\r
449     /// <param name="name">class name</param>\r
450     /// <returns></returns>\r
451     public virtual ClassRef AddValueClass(string nsName, string name) {\r
452       ClassRef aClass = new ClassRef(nsName,name,metaData);\r
453       metaData.AddToTable(MDTable.TypeRef,aClass);\r
454       aClass.SetParent(this);\r
455       aClass.MakeValueClass();\r
456       return aClass;\r
457     }\r
458 \r
459     internal string TypeName() {\r
460       string result = name;\r
461       if (hasVersion) \r
462         result = result + ", Version=" + major + "." + minor + "." + \r
463                   build + "." + revision;\r
464       if (keyBytes != null) {\r
465         string tokenStr = "=";\r
466         if (isKeyToken) tokenStr = "Token=";\r
467         result = result + ", PublicKey" + tokenStr;\r
468         for (int i=0; i < keyBytes.Length; i++) {\r
469           result = result + Hex.Byte(keyBytes[i]);\r
470         }\r
471       }\r
472       if (culture != null) \r
473         result = result + ", Culture=" + culture;\r
474       return result;\r
475     }\r
476 \r
477     internal sealed override uint Size(MetaData md) {\r
478       return 12 + 2 * md.StringsIndexSize() + 2 * md.BlobIndexSize();\r
479     }\r
480 \r
481     internal sealed override void Write(FileImage output) {\r
482       output.Write(major);\r
483       output.Write(minor);\r
484       output.Write(build);\r
485       output.Write(revision);\r
486       output.Write(flags);\r
487       output.BlobIndex(keyIx);\r
488       output.StringsIndex(nameIx);\r
489       output.StringsIndex(cultIx);\r
490       output.BlobIndex(hashIx);\r
491     }\r
492 \r
493     internal sealed override uint GetCodedIx(CIx code) {\r
494       switch (code) {\r
495         case (CIx.ResolutionScope) : return 2; \r
496         case (CIx.HasCustomAttr) : return 15; \r
497         case (CIx.Implementation) : return 1; \r
498       }\r
499       return 0;\r
500     }\r
501  \r
502         }\r
503   /**************************************************************************/  \r
504 \r
505   /// <summary>\r
506   /// flags for the assembly (.corflags)\r
507   /// </summary>\r
508   public enum CorFlags {CF_IL_ONLY, CF_32_BITREQUIRED, CF_STRONGNAMESIGNED, \r
509                         CF_TRACKDEBUGDATA}\r
510 \r
511   /// <summary>\r
512   /// subsystem for the assembly (.subsystem)\r
513   /// </summary>\r
514   public enum SubSystem { Native = 1, Windows_GUI = 2, \r
515     Windows_CUI = 3, OS2_CUI = 5, POSIX_CUI = 7, Native_Windows = 8, \r
516     Windows_CE_GUI = 9}\r
517  \r
518   /// <summary>\r
519   /// Hash algorithms for the assembly\r
520   /// </summary>\r
521   public enum HashAlgorithm { None, SHA1 }\r
522 \r
523   /// <summary>\r
524   /// Attributes for this assembly\r
525   /// </summary>\r
526   public enum AssemAttr { EnableJITCompileTracking = 0x8000, \r
527                           DisableJITCompileOptimizer = 0x4000}\r
528 \r
529   /// <summary>\r
530   /// Method call conventions\r
531   /// </summary>\r
532   public enum CallConv { Default, Cdecl, Stdcall, Thiscall, \r
533     Fastcall, Vararg, Instance = 0x20, Generic = 0x10, InstanceExplicit = 0x60 }\r
534 \r
535   /// <summary>\r
536   /// Type custom modifier\r
537   /// </summary>\r
538   public enum CustomModifier { modreq = 0x1F, modopt };\r
539 \r
540   /// <summary>\r
541   /// Attibutes for a class\r
542   /// </summary>\r
543   public enum TypeAttr {Private, Public, NestedPublic, NestedPrivate, \r
544     NestedFamily, NestedAssembly, NestedFamAndAssem, NestedFamOrAssem, \r
545     SequentialLayout, ExplicitLayout = 0x10, Interface = 0x20, \r
546     Abstract = 0x80, PublicAbstract = 0x81, Sealed = 0x100, \r
547     PublicSealed = 0x101, SpecialName = 0x400, RTSpecialName = 0x800, \r
548     Import = 0x1000, Serializable = 0x2000, UnicodeClass = 0x10000,\r
549     AutoClass = 0x20000, BeforeFieldInit = 0x100000 }\r
550 \r
551   /// <summary>\r
552   /// Attributes for a field\r
553   /// </summary>\r
554   public enum FieldAttr {Default, Private, FamAndAssem, Assembly, \r
555     Family, FamOrAssem, Public, Static = 0x10, PublicStatic = 0x16, \r
556     Initonly = 0x20, Literal = 0x40, Notserialized = 0x80, \r
557     SpecialName = 0x200, RTSpecialName = 0x400 }\r
558   \r
559   /// <summary>\r
560   /// Attributes for a method\r
561   /// </summary>\r
562   public enum MethAttr { Default, Private, FamAndAssem, Assembly,\r
563     Family, FamOrAssem, Public, Static = 0x0010, PublicStatic = 0x16, \r
564     Final = 0x0020, PublicStaticFinal = 0x36, Virtual = 0x0040, \r
565     PrivateVirtual, PublicVirtual = 0x0046, HideBySig = 0x0080, \r
566     NewSlot = 0x0100, Abstract = 0x0400, SpecialName = 0x0800,\r
567     RTSpecialName = 0x1000, SpecialRTSpecialName = 0x1800, \r
568     RequireSecObject = 0x8000}\r
569 \r
570   /// <summary>\r
571   /// Attributes for .pinvokeimpl method declarations\r
572   /// </summary>\r
573   public enum PInvokeAttr { nomangle = 1, ansi = 2, unicode = 4, autochar = 6,
574                             lasterr = 0x0040, winapi = 0x0100, cdecl = 0x0200,
575                             stdcall = 0x0300, thiscall = 0x0400, fastcall = 0x0500 }\r
576 \r
577   /// <summary>\r
578   /// Implementation attributes for a method\r
579   /// </summary>\r
580   public enum ImplAttr { IL, Native, Runtime = 0x03, Unmanaged = 0x04,\r
581     ForwardRef = 0x10, PreserveSig = 0x0080, InternalCall = 0x1000, \r
582     Synchronised = 0x0020, Synchronized = 0x0020, NoInLining = 0x0008, Optil = 0x0002}\r
583 \r
584   /// <summary>\r
585   /// Modes for a parameter\r
586   /// </summary>\r
587   public enum ParamAttr { Default, In, Out, Opt = 4 }\r
588 \r
589   /// <summary>\r
590   /// CIL instructions\r
591   /// </summary>\r
592   public enum Op { nop, breakOp, ldarg_0, ldarg_1, ldarg_2, ldarg_3,\r
593     ldloc_0, ldloc_1, ldloc_2, ldloc_3, stloc_0, stloc_1, stloc_2, stloc_3, \r
594     ldnull = 0x14, ldc_i4_m1, ldc_i4_0, ldc_i4_1, ldc_i4_2, ldc_i4_3, \r
595     ldc_i4_4, ldc_i4_5, ldc_i4_6, ldc_i4_7, ldc_i4_8, dup = 0x25, pop, \r
596     ret = 0x2A, ldind_i1 = 0x46, ldind_u1, ldind_i2, ldind_u2, ldind_i4, \r
597     ldind_u4, ldind_i8, ldind_i,  ldind_r4, ldind_r8, ldind_ref, stind_ref, \r
598     stind_i1, stind_i2, stind_i4, stind_i8, stind_r4, stind_r8, add, sub, mul,\r
599     div, div_un, rem, rem_un, and, or, xor, shl, shr, shr_un, neg, not, \r
600     conv_i1, conv_i2, conv_i4, conv_i8, conv_r4, conv_r8, conv_u4, conv_u8, \r
601     conv_r_un = 0x76, throwOp = 0x7A, conv_ovf_i1_un = 0x82, conv_ovf_i2_un,\r
602     conv_ovf_i4_un, conv_ovf_i8_un, conf_ovf_u1_un, conv_ovf_u2_un, \r
603     conv_ovf_u4_un, conv_ovf_u8_un, conv_ovf_i_un, conv_ovf_u_un, \r
604     ldlen = 0x8E, ldelem_i1 = 0x90, ldelem_u1, ldelem_i2, ldelem_u2, \r
605     ldelem_i4, ldelem_u4, ldelem_i8, ldelem_i, ldelem_r4, ldelem_r8, \r
606     ldelem_ref, stelem_i, stelem_i1, stelem_i2, stelem_i4, stelem_i8, stelem_r4 = 0xA0, stelem_r8,\r
607     stelem_ref, conv_ovf_i1 = 0xb3, conv_ovf_u1, conv_ovf_i2, conv_ovf_u2, \r
608     conv_ovf_i4, conv_ovf_u4, conv_ovf_i8, conv_ovf_u8, ckfinite = 0xC3, \r
609     conv_u2 = 0xD1, conv_u1, conv_i, conv_ovf_i, conv_ovf_u, add_ovf, \r
610     add_ovf_un, mul_ovf, mul_ovf_un, sub_ovf, sub_ovf_un, endfinally, \r
611     stind_i = 0xDF, conv_u, arglist = 0xFE00, ceq, cgt, cgt_un, clt, clt_un, \r
612     localloc = 0xFE0F, endfilter = 0xFE11, volatile_ = 0xFE13, tail_, \r
613     cpblk = 0xFE17, initblk, rethrow = 0xFE1A, refanytype = 0xFE1D}\r
614 \r
615   /// <summary>\r
616   /// CIL instructions requiring an integer parameter\r
617   /// </summary>\r
618   public enum IntOp {ldarg_s = 0x0E, ldarga_s, starg_s, ldloc_s, ldloca_s, \r
619                      stloc_s, ldc_i4_s = 0x1F, ldc_i4, ldarg = 0xFE09,\r
620                      ldarga, starg, ldloc, ldloca, stloc, unaligned = 0xFE12 }\r
621 \r
622   /// <summary>\r
623   /// CIL instructions requiring a field parameter\r
624   /// </summary>\r
625   public enum FieldOp {ldfld = 0x7B, ldflda, stfld, ldsfld, ldsflda,\r
626                        stsfld, ldtoken = 0xD0 }\r
627 \r
628   /// <summary>\r
629   /// CIL instructions requiring a method parameter\r
630   /// </summary>\r
631   public enum MethodOp {jmp = 0x27, call, callvirt = 0x6F, newobj = 0x73, \r
632                         ldtoken = 0xD0, ldftn = 0xFE06, ldvirtfn }\r
633 \r
634   /// <summary>\r
635   /// CIL instructions requiring a type parameter\r
636   /// </summary>\r
637   public enum TypeOp {cpobj = 0x70, ldobj, castclass = 0x74, isinst, \r
638                       unbox = 0x79, stobj = 0x81, box = 0x8C, newarr, \r
639                       ldelema = 0x8F, refanyval = 0xC2, mkrefany = 0xC6, \r
640                       ldtoken = 0xD0, initobj = 0xFE15, sizeOf = 0xFE1C,\r
641                       ldelem = 0xA3, stelem = 0xA4, unbox_any }\r
642 \r
643   /// <summary>\r
644   /// CIL branch instructions\r
645   /// </summary>\r
646   public enum BranchOp {
647           // short branches
648           br_s = 0x2B, brfalse_s, brtrue_s, beq_s, bge_s, bgt_s,
649           ble_s, blt_s, bne_un_s, bge_un_s, bgt_un_s, ble_un_s, blt_un_s,
650           // long branches
651           br = 0x38, brfalse, brtrue, beq, bge, bgt, ble, blt,\r
652           bne_un, bge_un, bgt_un, ble_un, blt_un,
653
654           leave = 0xDD, leave_s }\r
655 \r
656   /// <summary>\r
657   /// Index for all the tables in the meta data\r
658   /// </summary>\r
659   public enum MDTable { Module, TypeRef, TypeDef, Field = 0x04, Method = 0x06,\r
660     Param = 0x08, InterfaceImpl, MemberRef, Constant, CustomAttribute, \r
661     FieldMarshal, DeclSecurity, ClassLayout, FieldLayout, StandAloneSig, \r
662     EventMap, Event = 0x14, PropertyMap, Property = 0x17, MethodSemantics, \r
663     MethodImpl, ModuleRef, TypeSpec, ImplMap, FieldRVA, Assembly = 0x20, \r
664     AssemblyProcessor, AssemblyOS, AssemblyRef, AssemblyRefProcessor, \r
665     AssemblyRefOS, File, ExportedType, ManifestResource, NestedClass,\r
666     GenericParam, MethodSpec, GenericParamConstraint  }\r
667 \r
668   public enum SafeArrayType { int16 = 2, int32, float32, float64,\r
669     currency, date, bstr, dispatch, error, boolean, variant, unknown,\r
670     Decimal, int8 = 16, uint8, uint16, uint32, Int = 22, UInt }\r
671 \r
672   internal enum CIx { TypeDefOrRef, HasConst, HasCustomAttr, HasFieldMarshal,\r
673     HasDeclSecurity, MemberRefParent, HasSemantics, MethodDefOrRef, \r
674     MemberForwarded, Implementation, CustomAttributeType, ResolutionScope,\r
675     TypeOrMethodDef, MaxCIx }\r
676 \r
677   internal enum MapType { eventMap, propertyMap, nestedClass }\r
678 \r
679   /**************************************************************************/  \r
680         /// <summary>\r
681         /// The assembly for mscorlib.  \r
682         /// </summary>\r
683         public sealed class MSCorLib : AssemblyRef\r
684         {\r
685     private static readonly int valueTypeIx = 18;\r
686     private readonly string systemName = "System";\r
687     private ClassRef[] systemClasses = new ClassRef[valueTypeIx+2];\r
688     private PrimitiveType[] systemTypes = new PrimitiveType[valueTypeIx];\r
689     private TypeSpec[] specialTypeSpecs = new TypeSpec[valueTypeIx];\r
690     private static int[] specialNames = {\r
691       PrimitiveType.Void.GetName().GetHashCode(),\r
692       PrimitiveType.Boolean.GetName().GetHashCode(),\r
693       PrimitiveType.Char.GetName().GetHashCode(),\r
694       PrimitiveType.Int8.GetName().GetHashCode(),\r
695       PrimitiveType.UInt8.GetName().GetHashCode(),\r
696       PrimitiveType.Int16.GetName().GetHashCode(),\r
697       PrimitiveType.UInt16.GetName().GetHashCode(),\r
698       PrimitiveType.Int32.GetName().GetHashCode(),\r
699       PrimitiveType.UInt32.GetName().GetHashCode(),\r
700       PrimitiveType.Int64.GetName().GetHashCode(),\r
701       PrimitiveType.UInt64.GetName().GetHashCode(),\r
702       PrimitiveType.Float32.GetName().GetHashCode(),\r
703       PrimitiveType.Float64.GetName().GetHashCode(),\r
704       PrimitiveType.String.GetName().GetHashCode(),\r
705       PrimitiveType.TypedRef.GetName().GetHashCode(),\r
706       PrimitiveType.IntPtr.GetName().GetHashCode(),\r
707       PrimitiveType.UIntPtr.GetName().GetHashCode(),\r
708       PrimitiveType.Object.GetName().GetHashCode(),\r
709       "ValueType".GetHashCode(),\r
710       "Enum".GetHashCode()\r
711     };\r
712 \r
713     internal MSCorLib(MetaData md) : base(md,"mscorlib") {\r
714       md.AddToTable(MDTable.AssemblyRef,this);\r
715       systemTypes[PrimitiveType.Void.GetSystemTypeIx()] = PrimitiveType.Void;\r
716       systemTypes[PrimitiveType.Boolean.GetSystemTypeIx()] = PrimitiveType.Boolean;\r
717       systemTypes[PrimitiveType.Char.GetSystemTypeIx()] = PrimitiveType.Char;\r
718       systemTypes[PrimitiveType.Int8.GetSystemTypeIx()] = PrimitiveType.Int8;\r
719       systemTypes[PrimitiveType.UInt8.GetSystemTypeIx()] = PrimitiveType.UInt8;\r
720       systemTypes[PrimitiveType.Int16.GetSystemTypeIx()] = PrimitiveType.Int16;\r
721       systemTypes[PrimitiveType.UInt16.GetSystemTypeIx()] = PrimitiveType.UInt16;\r
722       systemTypes[PrimitiveType.Int32.GetSystemTypeIx()] = PrimitiveType.Int32;\r
723       systemTypes[PrimitiveType.UInt32.GetSystemTypeIx()] = PrimitiveType.UInt32;\r
724       systemTypes[PrimitiveType.Int64.GetSystemTypeIx()] = PrimitiveType.Int64;\r
725       systemTypes[PrimitiveType.UInt64.GetSystemTypeIx()] = PrimitiveType.UInt64;\r
726       systemTypes[PrimitiveType.Float32.GetSystemTypeIx()] = PrimitiveType.Float32;\r
727       systemTypes[PrimitiveType.Float64.GetSystemTypeIx()] = PrimitiveType.Float64;\r
728       systemTypes[PrimitiveType.IntPtr.GetSystemTypeIx()] = PrimitiveType.IntPtr;\r
729       systemTypes[PrimitiveType.UIntPtr.GetSystemTypeIx()] = PrimitiveType.UIntPtr;\r
730       systemTypes[PrimitiveType.String.GetSystemTypeIx()] = PrimitiveType.String;\r
731       systemTypes[PrimitiveType.Object.GetSystemTypeIx()] = PrimitiveType.Object;\r
732       systemTypes[PrimitiveType.TypedRef.GetSystemTypeIx()] = PrimitiveType.TypedRef;\r
733     }\r
734 \r
735     /// <summary>\r
736     /// Add a class to the mscorlib assembly\r
737     /// </summary>\r
738     /// <param name="nsName">name space name</param>\r
739     /// <param name="name">class name</param>\r
740     /// <returns></returns>\r
741     public override ClassRef AddClass(string nsName, string name) {\r
742       ClassRef aClass = GetSpecialClass(nsName,name);\r
743       if (aClass == null) {\r
744         aClass = new ClassRef(nsName,name,metaData);\r
745         metaData.AddToTable(MDTable.TypeRef,aClass);\r
746         aClass.SetParent(this);\r
747       }\r
748       return aClass;\r
749     }\r
750 \r
751     private ClassRef GetSpecialClass(string nsName,string name) {\r
752       if (nsName.CompareTo(systemName) != 0) return null;\r
753       int hash = name.GetHashCode();\r
754       for (int i=0; i < specialNames.Length; i++) {\r
755         if (hash == specialNames[i]) {\r
756           if (systemClasses[i] == null) {\r
757             if (i < valueTypeIx) {\r
758               systemClasses[i] = new SystemClass(systemTypes[i],this,metaData);\r
759               if ((systemTypes[i] != PrimitiveType.Object) &&\r
760                 (systemTypes[i] != PrimitiveType.String)) {\r
761                 systemClasses[i].MakeValueClass();\r
762               }\r
763             } else {\r
764               systemClasses[i] = new ClassRef(nsName,name,metaData);\r
765               systemClasses[i].SetParent(this);\r
766               systemClasses[i].MakeValueClass();\r
767             }\r
768             metaData.AddToTable(MDTable.TypeRef,systemClasses[i]);\r
769           }\r
770           return systemClasses[i];\r
771         }\r
772       }\r
773       return null;\r
774     }\r
775 \r
776     internal ClassRef GetSpecialSystemClass(PrimitiveType pType) {\r
777       int ix = pType.GetSystemTypeIx();\r
778       if (systemClasses[ix] == null) {\r
779         systemClasses[ix] = new SystemClass(pType,this,metaData);\r
780         metaData.AddToTable(MDTable.TypeRef,systemClasses[ix]);\r
781       }\r
782       return systemClasses[ix];\r
783     }\r
784         \r
785     private ClassRef GetValueClass(string name, int hash) {\r
786       int ix = valueTypeIx;\r
787       if (hash != specialNames[valueTypeIx]) ix++;\r
788       if (systemClasses[ix] == null) {\r
789         systemClasses[ix] = new ClassRef(systemName,name,metaData);\r
790         systemClasses[ix].SetParent(this);\r
791         systemClasses[ix].MakeValueClass();\r
792         metaData.AddToTable(MDTable.TypeRef,systemClasses[ix]);\r
793       }\r
794       return systemClasses[ix];\r
795     }\r
796 \r
797     internal ClassRef ValueType() {\r
798       if (systemClasses[valueTypeIx] == null) {\r
799         ClassRef valType = new ClassRef("System","ValueType",metaData);\r
800         valType.SetParent(this);\r
801         valType.MakeValueClass();\r
802         metaData.AddToTable(MDTable.TypeRef,valType);\r
803         systemClasses[valueTypeIx] = valType;\r
804       }\r
805       return systemClasses[valueTypeIx];\r
806     }\r
807 \r
808     /// <summary>\r
809     /// Add a value class to this external assembly\r
810     /// </summary>\r
811     /// <param name="nsName">name space name</param>\r
812     /// <param name="name">class name</param>\r
813     /// <returns></returns>\r
814     public override ClassRef AddValueClass(string nsName, string name) {\r
815       if (nsName.CompareTo(systemName) == 0) {\r
816         int hash = name.GetHashCode();\r
817         if ((hash == specialNames[valueTypeIx]) ||\r
818             (hash == specialNames[valueTypeIx+1])) {\r
819           return GetValueClass(name,hash);\r
820         }\r
821       }\r
822       ClassRef aClass = new ClassRef(nsName,name,metaData);\r
823       metaData.AddToTable(MDTable.TypeRef,aClass);\r
824       aClass.SetParent(this);\r
825       aClass.MakeValueClass();\r
826       return aClass;\r
827     }\r
828 \r
829         }\r
830   /**************************************************************************/  \r
831         /// <summary>\r
832         /// Signature for calli instruction\r
833         /// </summary>\r
834         public class CalliSig : Signature\r
835         {\r
836     private static readonly byte Sentinel = 0x41;\r
837     CallConv callConv;\r
838     Type returnType;\r
839     Type[] parameters, optParams;\r
840                 uint numPars = 0, numOptPars = 0;\r
841 \r
842     /// <summary>\r
843     /// Create a signature for a calli instruction\r
844     /// </summary>\r
845     /// <param name="cconv">calling conventions</param>\r
846     /// <param name="retType">return type</param>\r
847     /// <param name="pars">parameter types</param>\r
848     public CalliSig(CallConv cconv, Type retType, Type[] pars) {\r
849                         tabIx = MDTable.StandAloneSig;\r
850       callConv = cconv;\r
851       returnType = retType;\r
852       parameters = pars;\r
853                         if (pars != null) numPars = (uint)pars.Length;\r
854     }\r
855 \r
856     /// <summary>\r
857     /// Add the optional parameters to a vararg method\r
858     /// This method sets the vararg calling convention\r
859     /// </summary>\r
860     /// <param name="optPars">the optional pars for the vararg call</param>\r
861     public void AddVarArgs(Type[] optPars) {\r
862       optParams = optPars;\r
863       if (optPars != null) numOptPars = (uint)optPars.Length;\r
864       callConv |= CallConv.Vararg;\r
865     }\r
866 \r
867     /// <summary>\r
868     /// Add extra calling conventions to this callsite signature\r
869     /// </summary>\r
870     /// <param name="cconv"></param>\r
871     public void AddCallingConv(CallConv cconv) {\r
872       callConv |= cconv;\r
873     }\r
874 \r
875     internal sealed override void BuildTables(MetaData md) {\r
876       if (done) return;\r
877       MemoryStream sig = new MemoryStream();\r
878       sig.WriteByte((byte)callConv);\r
879       MetaData.CompressNum(numPars+numOptPars,sig);\r
880       returnType.TypeSig(sig);\r
881       for (int i=0; i < numPars; i++) {\r
882         parameters[i].TypeSig(sig);\r
883       }\r
884       sigIx = md.AddToBlobHeap(sig.ToArray());\r
885       if (numOptPars > 0) {\r
886         sig.WriteByte(Sentinel);\r
887         for (int i=0; i < numOptPars; i++) {\r
888           optParams[i].TypeSig(sig);\r
889         }\r
890       }\r
891       done = true;\r
892     }\r
893 \r
894         }\r
895   /**************************************************************************/  \r
896   /// <summary>\r
897   /// The IL instructions for a method\r
898   /// </summary>\r
899   public class CILInstructions \r
900   {\r
901 \r
902     private static readonly uint ExHeaderSize = 4;\r
903     private static readonly uint FatExClauseSize = 24;\r
904     private static readonly uint SmlExClauseSize = 12;\r
905     private static readonly sbyte maxByteVal = 127;\r
906     private static readonly sbyte minByteVal = -128;\r
907     private static readonly byte maxUByteVal = 255;\r
908     private static readonly int smallSize = 64;\r
909     private static readonly ushort TinyFormat = 0x2;\r
910     private static readonly ushort FatFormat = 0x3003;\r
911     private static readonly ushort MoreSects = 0x8;\r
912     private static readonly ushort InitLocals = 0x10;\r
913     private static readonly uint FatSize = 12;\r
914     private static readonly uint FatWords = FatSize/4;\r
915     private static readonly byte FatExceptTable = 0x41;\r
916     private static readonly byte SmlExceptTable = 0x01; \r
917 \r
918     private MetaData metaData;\r
919     private ArrayList exceptions, blockStack;\r
920     //private bool codeChecked = false;\r
921     private static readonly int INITSIZE = 5;\r
922     private CILInstruction[] buffer = new CILInstruction[INITSIZE];\r
923     private int tide = 0;\r
924     private uint offset = 0;\r
925     private ushort headerFlags = 0;\r
926     private short maxStack;\r
927     private uint paddingNeeded = 0;\r
928     private byte exceptHeader = 0;\r
929     uint localSigIx = 0;\r
930     uint codeSize = 0, exceptSize = 0;\r
931     bool tinyFormat, fatExceptionFormat = false;\r
932 \r
933     internal CILInstructions(MetaData md) {\r
934       metaData = md;\r
935     }\r
936 \r
937     private void AddToBuffer(CILInstruction inst) {\r
938       if (tide >= buffer.Length) {\r
939         CILInstruction[] tmp = buffer;\r
940         buffer = new CILInstruction[tmp.Length * 2];\r
941         for (int i=0; i < tide; i++) {\r
942           buffer[i] = tmp[i];\r
943         }\r
944       }\r
945                         //Console.WriteLine("Adding instruction at offset " + offset + " with size " + inst.size);\r
946                         inst.offset = offset;\r
947       offset += inst.size;\r
948       buffer[tide++] = inst;\r
949     }\r
950 \r
951     /// <summary>\r
952     /// Add a simple IL instruction\r
953     /// </summary>\r
954     /// <param name="inst">the IL instruction</param>\r
955     public void Inst(Op inst) {\r
956       AddToBuffer(new Instr((int)inst));\r
957     }\r
958 \r
959     /// <summary>\r
960     /// Add an IL instruction with an integer parameter\r
961     /// </summary>\r
962     /// <param name="inst">the IL instruction</param>\r
963     /// <param name="val">the integer parameter value</param>\r
964     public void IntInst(IntOp inst, int val) {\r
965       int instr = (int)inst;\r
966       if ((inst == IntOp.ldc_i4_s) || (inst == IntOp.ldc_i4)) \r
967         AddToBuffer(new IntInstr(instr,val,(inst == IntOp.ldc_i4_s)));\r
968       else\r
969         AddToBuffer(new UIntInstr(instr,val,((inst < IntOp.ldc_i4_s) ||\r
970                                               (inst == IntOp.unaligned))));\r
971     }\r
972 \r
973     /// <summary>\r
974     /// Add the load long instruction\r
975     /// </summary>\r
976     /// <param name="cVal">the long value</param>\r
977     public void ldc_i8(long cVal) {\r
978       AddToBuffer(new LongInstr(0x21,cVal));\r
979     }\r
980 \r
981     /// <summary>\r
982     /// Add the load float32 instruction\r
983     /// </summary>\r
984     /// <param name="cVal">the float value</param>\r
985     public void ldc_r4(float cVal) {\r
986       AddToBuffer(new FloatInstr(0x22,cVal));\r
987     }\r
988 \r
989     /// <summary>\r
990     /// Add the load float64 instruction\r
991     /// </summary>\r
992     /// <param name="cVal">the float value</param>\r
993     public void ldc_r8(double cVal) {\r
994       AddToBuffer(new DoubleInstr(0x23,cVal));\r
995     }\r
996 \r
997     /// <summary>\r
998     /// Add the load string instruction\r
999     /// </summary>\r
1000     /// <param name="str">the string value</param>\r
1001     public void ldstr(string str) {\r
1002       AddToBuffer(new StringInstr(0x72,str));\r
1003     }\r
1004 \r
1005     /// <summary>\r
1006     /// Add the calli instruction\r
1007     /// </summary>\r
1008     /// <param name="sig">the signature for the calli</param>\r
1009     public void calli(CalliSig sig) {\r
1010       AddToBuffer(new SigInstr(0x29,sig));\r
1011     }\r
1012 \r
1013     /// <summary>\r
1014     /// Add a label to the CIL instructions\r
1015     /// </summary>\r
1016     /// <param name="lab">the label to be added</param>\r
1017     public void CodeLabel(CILLabel lab) {\r
1018       AddToBuffer(new LabelInstr(lab));\r
1019     }\r
1020 \r
1021     /// <summary>\r
1022     /// Add an instruction with a field parameter\r
1023     /// </summary>\r
1024     /// <param name="inst">the CIL instruction</param>\r
1025     /// <param name="f">the field parameter</param>\r
1026     public void FieldInst(FieldOp inst, Field f) {\r
1027       AddToBuffer(new FieldInstr((int)inst,f));\r
1028     }\r
1029 \r
1030     /// <summary>\r
1031     /// Add an instruction with a method parameter\r
1032     /// </summary>\r
1033     /// <param name="inst">the CIL instruction</param>\r
1034     /// <param name="m">the method parameter</param>\r
1035     public void MethInst(MethodOp inst, Method m) {\r
1036       AddToBuffer(new MethInstr((int)inst,m));\r
1037     }\r
1038 \r
1039     /// <summary>\r
1040     /// Add an instruction with a type parameter\r
1041     /// </summary>\r
1042     /// <param name="inst">the CIL instruction</param>\r
1043     /// <param name="t">the type argument for the CIL instruction</param>\r
1044     public void TypeInst(TypeOp inst, Type aType) {\r
1045       AddToBuffer(new TypeInstr((int)inst,aType,metaData));\r
1046     }\r
1047 \r
1048     /// <summary>\r
1049     /// Add a branch instruction\r
1050     /// </summary>\r
1051     /// <param name="inst">the branch instruction</param>\r
1052     /// <param name="lab">the label that is the target of the branch</param>\r
1053     public void Branch(BranchOp inst,  CILLabel lab) {\r
1054       AddToBuffer(new BranchInstr((int)inst,lab));\r
1055     }\r
1056 \r
1057     /// <summary>\r
1058     /// Add a switch instruction\r
1059     /// </summary>\r
1060     /// <param name="labs">the target labels for the switch</param>\r
1061     public void Switch(CILLabel[] labs) {\r
1062       AddToBuffer(new SwitchInstr(0x45,labs));\r
1063     }\r
1064 \r
1065     /// <summary>\r
1066     /// Add a byte to the CIL instructions (.emitbyte)\r
1067     /// </summary>\r
1068     /// <param name="bVal"></param>\r
1069     public void emitbyte(byte bVal) { \r
1070       AddToBuffer(new CILByte(bVal));\r
1071     }\r
1072 \r
1073     /// <summary>\r
1074     /// Add an instruction which puts an integer on TOS.  This method\r
1075     /// selects the correct instruction based on the value of the integer.\r
1076     /// </summary>\r
1077     /// <param name="i">the integer value</param>\r
1078     public void PushInt(int i) {\r
1079       if (i == -1) {\r
1080         AddToBuffer(new Instr((int)Op.ldc_i4_m1));\r
1081       } else if ((i >= 0) && (i <= 8)) {\r
1082         Op op = (Op)(Op.ldc_i4_0 + i);\r
1083         AddToBuffer(new Instr((int)op));\r
1084       } else if ((i >= minByteVal) && (i <= maxByteVal)) {\r
1085         AddToBuffer(new IntInstr((int)IntOp.ldc_i4_s,i,true));\r
1086       } else {\r
1087         AddToBuffer(new IntInstr((int)IntOp.ldc_i4,i,false)); \r
1088       }\r
1089     }\r
1090 \r
1091     /// <summary>\r
1092     /// Add the instruction to load a long on TOS\r
1093     /// </summary>\r
1094     /// <param name="l">the long value</param>\r
1095     public void PushLong(long l) {\r
1096       AddToBuffer(new LongInstr(0x21,l));\r
1097     }\r
1098 \r
1099     /// <summary>\r
1100     /// Add an instruction to push the boolean value true on TOS\r
1101     /// </summary>\r
1102     public void PushTrue() {\r
1103       AddToBuffer(new Instr((int)Op.ldc_i4_1));\r
1104     }\r
1105 \r
1106     /// <summary>\r
1107     ///  Add an instruction to push the boolean value false on TOS\r
1108     /// </summary>\r
1109     public void PushFalse() {\r
1110       AddToBuffer(new Instr((int)Op.ldc_i4_0));\r
1111     }\r
1112 \r
1113     /// <summary>\r
1114     /// Add the instruction to load an argument on TOS.  This method\r
1115     /// selects the correct instruction based on the value of argNo\r
1116     /// </summary>\r
1117     /// <param name="argNo">the number of the argument</param>\r
1118     public void LoadArg(int argNo) {\r
1119       if (argNo < 4) {\r
1120         int op = (int)Op.ldarg_0 + argNo;\r
1121         AddToBuffer(new Instr(op));\r
1122       } else if (argNo <= maxUByteVal) {\r
1123         AddToBuffer(new UIntInstr((int)IntOp.ldarg,argNo,true));\r
1124       } else {\r
1125         AddToBuffer(new UIntInstr(0x09,argNo,false)); \r
1126       }\r
1127    }\r
1128 \r
1129     /// <summary>\r
1130     /// Add the instruction to load the address of an argument on TOS.\r
1131     /// This method selects the correct instruction based on the value\r
1132     /// of argNo.\r
1133     /// </summary>\r
1134     /// <param name="argNo">the number of the argument</param>\r
1135     public void LoadArgAdr(int argNo) {\r
1136       if (argNo <= maxUByteVal) {\r
1137         AddToBuffer(new UIntInstr((int)IntOp.ldarga,argNo,true));\r
1138       } else {\r
1139         AddToBuffer(new UIntInstr(0x0A,argNo,false)); \r
1140       }\r
1141     }\r
1142 \r
1143     /// <summary>\r
1144     /// Add the instruction to load a local on TOS.  This method selects\r
1145     /// the correct instruction based on the value of locNo.\r
1146     /// </summary>\r
1147     /// <param name="locNo">the number of the local to load</param>\r
1148     public void LoadLocal(int locNo) {\r
1149       if (locNo < 4) {\r
1150         int op = (int)Op.ldloc_0 + locNo;\r
1151         AddToBuffer(new Instr(op));\r
1152       } else if (locNo <= maxUByteVal) {\r
1153         AddToBuffer(new UIntInstr((int)IntOp.ldloc,locNo,true));\r
1154       } else {\r
1155         AddToBuffer(new UIntInstr(0x0C,locNo,false)); \r
1156       }\r
1157     }\r
1158 \r
1159     /// <summary>\r
1160     /// Add the instruction to load the address of a local on TOS.\r
1161     /// This method selects the correct instruction based on the \r
1162     /// value of locNo.\r
1163     /// </summary>\r
1164     /// <param name="locNo">the number of the local</param>\r
1165     public void LoadLocalAdr(int locNo) {\r
1166       if (locNo <= maxUByteVal) {\r
1167         AddToBuffer(new UIntInstr((int)IntOp.ldloca,locNo,true));\r
1168       } else {\r
1169         AddToBuffer(new UIntInstr(0x0D,locNo,false)); \r
1170       }\r
1171     }\r
1172 \r
1173     /// <summary>\r
1174     /// Add the instruction to store to an argument.  This method\r
1175     /// selects the correct instruction based on the value of argNo.\r
1176     /// </summary>\r
1177     /// <param name="argNo">the argument to be stored to</param>\r
1178     public void StoreArg(int argNo) {\r
1179       if (argNo <= maxUByteVal) {\r
1180         AddToBuffer(new UIntInstr((int)IntOp.starg,argNo,true));\r
1181       } else {\r
1182         AddToBuffer(new UIntInstr(0x0B,argNo,false)); \r
1183       }\r
1184     }\r
1185 \r
1186     /// <summary>\r
1187     /// Add the instruction to store to a local.  This method selects\r
1188     /// the correct instruction based on the value of locNo.\r
1189     /// </summary>\r
1190     /// <param name="locNo">the local to be stored to</param>\r
1191     public void StoreLocal(int locNo) {\r
1192       if (locNo < 4) {\r
1193         int op = (int)Op.stloc_0 + locNo;\r
1194         AddToBuffer(new Instr(op));\r
1195       } else if (locNo <= maxUByteVal) {\r
1196         AddToBuffer(new UIntInstr((int)IntOp.stloc,locNo,true));\r
1197       } else {\r
1198         AddToBuffer(new UIntInstr(0x0E,locNo,false)); \r
1199       }\r
1200     }\r
1201 \r
1202     /// <summary>\r
1203     /// Create a new CIL label.  To place the label in the CIL instruction\r
1204     /// stream use CodeLabel.\r
1205     /// </summary>\r
1206     /// <returns>a new CIL label</returns>\r
1207     public CILLabel NewLabel() {\r
1208       return new CILLabel();\r
1209     }\r
1210 \r
1211     public void AddTryBlock(TryBlock tryBlock) {\r
1212       if (exceptions == null) \r
1213         exceptions = new ArrayList();\r
1214       else if (exceptions.Contains(tryBlock)) return;\r
1215       exceptions.Add(tryBlock);\r
1216     }\r
1217 \r
1218     /// <summary>\r
1219     /// Create a new label at this position in the code buffer\r
1220     /// </summary>\r
1221     /// <returns>the label at the current position</returns>\r
1222     public CILLabel NewCodedLabel() {\r
1223       CILLabel lab = new CILLabel();\r
1224       AddToBuffer(new LabelInstr(lab));\r
1225       return lab;\r
1226     }\r
1227 \r
1228     /// <summary>\r
1229     /// Mark this position as the start of a new block\r
1230     /// (try, catch, filter, finally or fault)\r
1231     /// </summary>\r
1232     public void StartBlock() {\r
1233       if (blockStack == null) blockStack = new ArrayList();\r
1234       blockStack.Insert(0,NewCodedLabel());\r
1235     }\r
1236 \r
1237     /// <summary>\r
1238     /// Mark this position as the end of the last started block and\r
1239     /// make it a try block.  This try block is added to the current \r
1240     /// instructions (ie do not need to call AddTryBlock)\r
1241     /// </summary>\r
1242     /// <returns>The try block just ended</returns>\r
1243     public TryBlock EndTryBlock() {\r
1244       TryBlock tBlock = new TryBlock((CILLabel)blockStack[0],NewCodedLabel());\r
1245       blockStack.RemoveAt(0);\r
1246       AddTryBlock(tBlock);\r
1247       return tBlock;\r
1248     }\r
1249 \r
1250     /// <summary>\r
1251     /// Mark this position as the end of the last started block and\r
1252     /// make it a catch block.  This catch block is associated with the\r
1253     /// specified try block.\r
1254     /// </summary>\r
1255     /// <param name="exceptType">the exception type to be caught</param>\r
1256     /// <param name="tryBlock">the try block associated with this catch block</param>\r
1257     public void EndCatchBlock(Class exceptType, TryBlock tryBlock) {\r
1258       Catch catchBlock = new Catch(exceptType,(CILLabel)blockStack[0],\r
1259         NewCodedLabel());\r
1260       tryBlock.AddHandler(catchBlock);\r
1261     }\r
1262 \r
1263     /// <summary>\r
1264     /// Mark this position as the end of the last started block and\r
1265     /// make it a filter block.  This filter block is associated with the\r
1266     /// specified try block.\r
1267     /// </summary>\r
1268     /// <param name="filterLab">the label where the filter code is</param>\r
1269     /// <param name="tryBlock">the try block associated with this filter block</param>\r
1270     public void EndFilterBlock(CILLabel filterLab, TryBlock tryBlock) {\r
1271       Filter filBlock = new Filter(filterLab,(CILLabel)blockStack[0],NewCodedLabel());\r
1272       tryBlock.AddHandler(filBlock);\r
1273     }\r
1274 \r
1275     /// <summary>\r
1276     /// Mark this position as the end of the last started block and\r
1277     /// make it a finally block.  This finally block is associated with the\r
1278     /// specified try block.\r
1279     /// </summary>\r
1280     /// <param name="tryBlock">the try block associated with this finally block</param>\r
1281     public void EndFinallyBlock(TryBlock tryBlock) {\r
1282       Finally finBlock= new Finally((CILLabel)blockStack[0],NewCodedLabel());\r
1283       tryBlock.AddHandler(finBlock);\r
1284     }\r
1285 \r
1286     /// <summary>\r
1287     /// Mark this position as the end of the last started block and\r
1288     /// make it a fault block.  This fault block is associated with the\r
1289     /// specified try block.\r
1290     /// </summary>\r
1291     /// <param name="tryBlock">the try block associated with this fault block</param>\r
1292     public void EndFaultBlock(TryBlock tryBlock) {\r
1293       Fault fBlock= new Fault((CILLabel)blockStack[0],NewCodedLabel());\r
1294       tryBlock.AddHandler(fBlock);\r
1295     }\r
1296 \r
1297     internal uint GetCodeSize() {\r
1298       return codeSize + paddingNeeded + exceptSize;\r
1299     }\r
1300 \r
1301     internal void CheckCode(uint locSigIx, bool initLocals, int maxStack) {\r
1302       if (tide == 0) return;\r
1303       bool changed = true;\r
1304       while (changed) {\r
1305         changed = false;\r
1306         for (int i=0; i < tide; i++) {\r
1307           changed = buffer[i].Check(metaData) || changed;\r
1308         }\r
1309         if (changed) {\r
1310           for (int i=1; i < tide; i++) {\r
1311             buffer[i].offset = buffer[i-1].offset + buffer[i-1].size;\r
1312           }\r
1313           offset = buffer[tide-1].offset + buffer[tide-1].size;\r
1314         }\r
1315       }\r
1316                         codeSize = offset;\r
1317                         // Console.WriteLine("codeSize before header added = " + codeSize);\r
1318       if ((offset < smallSize) && (maxStack <= 8) && (locSigIx == 0) && (exceptions == null)) {\r
1319         // can use tiny header\r
1320         //Console.WriteLine("Tiny Header");\r
1321         tinyFormat = true;\r
1322         headerFlags = (ushort)(TinyFormat | ((ushort)codeSize << 2));\r
1323         codeSize++;\r
1324         if ((codeSize % 4) != 0) { paddingNeeded = 4 - (codeSize % 4); }\r
1325       } else {\r
1326         //Console.WriteLine("Fat Header");\r
1327         tinyFormat = false;\r
1328         localSigIx = locSigIx;\r
1329         this.maxStack = (short)maxStack;\r
1330         headerFlags = FatFormat;\r
1331         if (exceptions != null) {\r
1332           // Console.WriteLine("Got exceptions");\r
1333           headerFlags |= MoreSects;\r
1334           uint numExceptClauses = 0;\r
1335           for (int i=0; i < exceptions.Count; i++) {\r
1336             TryBlock tryBlock = (TryBlock)exceptions[i];\r
1337             tryBlock.SetSize();\r
1338             numExceptClauses += (uint)tryBlock.NumHandlers();\r
1339             if (tryBlock.isFat()) fatExceptionFormat = true;\r
1340           }\r
1341           // Console.WriteLine("numexceptclauses = " + numExceptClauses);\r
1342           if (fatExceptionFormat) {\r
1343             // Console.WriteLine("Fat exception format");\r
1344             exceptHeader = FatExceptTable;\r
1345             exceptSize = ExHeaderSize + numExceptClauses * FatExClauseSize;\r
1346           } else {\r
1347             // Console.WriteLine("Tiny exception format");\r
1348             exceptHeader = SmlExceptTable;\r
1349             exceptSize = ExHeaderSize + numExceptClauses * SmlExClauseSize;\r
1350           }\r
1351           // Console.WriteLine("exceptSize = " + exceptSize);\r
1352         }\r
1353         if (initLocals) headerFlags |= InitLocals;\r
1354         if ((offset % 4) != 0) { paddingNeeded = 4 - (offset % 4); }\r
1355         codeSize += FatSize;\r
1356       }\r
1357                   // Console.WriteLine("codeSize = " + codeSize + "  headerFlags = " + \r
1358       //                   Hex.Short(headerFlags));\r
1359     }\r
1360 \r
1361                 internal void Write(FileImage output) {\r
1362       // Console.WriteLine("Writing header flags = " + Hex.Short(headerFlags));\r
1363                         if (tinyFormat) {\r
1364         // Console.WriteLine("Writing tiny code");\r
1365                                 output.Write((byte)headerFlags);\r
1366                         } else {\r
1367         // Console.WriteLine("Writing fat code");\r
1368                                 output.Write(headerFlags);\r
1369                                 output.Write((ushort)maxStack);\r
1370                                 output.Write(offset);\r
1371                                 output.Write(localSigIx);\r
1372                         }\r
1373       // Console.WriteLine(Hex.Int(tide) + " CIL instructions");\r
1374       // Console.WriteLine("starting instructions at " + output.Seek(0,SeekOrigin.Current));\r
1375                         for (int i=0; i < tide; i++) {\r
1376                                 buffer[i].Write(output);\r
1377                         }\r
1378       // Console.WriteLine("ending instructions at " + output.Seek(0,SeekOrigin.Current));\r
1379       for (int i=0; i < paddingNeeded; i++) { output.Write((byte)0); }\r
1380       if (exceptions != null) {\r
1381         // Console.WriteLine("Writing exceptions");\r
1382         // Console.WriteLine("header = " + Hex.Short(exceptHeader) + " exceptSize = " + Hex.Int(exceptSize));\r
1383         output.Write(exceptHeader);\r
1384         output.Write3Bytes((uint)exceptSize);\r
1385         for (int i=0; i < exceptions.Count; i++) {\r
1386           TryBlock tryBlock = (TryBlock)exceptions[i];\r
1387           tryBlock.Write(output,fatExceptionFormat);\r
1388         }\r
1389       }\r
1390                 }\r
1391 \r
1392   }\r
1393   /**************************************************************************/  \r
1394         /// <summary>\r
1395         /// A label in the IL\r
1396         /// </summary>\r
1397         public class CILLabel\r
1398         {\r
1399     CILInstruction branch;\r
1400     CILInstruction[] multipleBranches;\r
1401     int tide = 0;\r
1402     CILInstruction labInstr;\r
1403     uint offset = 0;\r
1404  \r
1405     public CILLabel (uint offset) {\r
1406         this.offset = offset;\r
1407         }\r
1408         \r
1409 \r
1410     internal CILLabel() {\r
1411     }
1412 \r
1413     internal void AddBranch(CILInstruction instr) {\r
1414       if (branch == null) {\r
1415         branch = instr;\r
1416         return;\r
1417       }\r
1418       if (multipleBranches == null) {\r
1419         multipleBranches = new CILInstruction[2];\r
1420       } else if (tide >= multipleBranches.Length) {\r
1421         CILInstruction[] tmp = multipleBranches;\r
1422         multipleBranches = new CILInstruction[tmp.Length*2];\r
1423         for (int i=0; i < tide; i++) {\r
1424           multipleBranches[i] = tmp[i];\r
1425         }\r
1426       }\r
1427       multipleBranches[tide++] = instr;\r
1428     }\r
1429 \r
1430     internal void AddLabelInstr(LabelInstr lInstr) {\r
1431       labInstr = lInstr;\r
1432     }\r
1433 \r
1434     internal uint GetLabelOffset() {\r
1435       if (labInstr == null) return 0;\r
1436       return labInstr.offset + offset;\r
1437     }\r
1438 \r
1439         }\r
1440   /**************************************************************************/  \r
1441   public abstract class CodeBlock {\r
1442 \r
1443     private static readonly int maxCodeSize = 256;\r
1444     protected CILLabel start, end;\r
1445     protected bool small = true;\r
1446 \r
1447     public CodeBlock(CILLabel start, CILLabel end) {\r
1448       this.start = start;\r
1449       this.end = end;\r
1450     }\r
1451 \r
1452     internal virtual bool isFat() {\r
1453       // Console.WriteLine("block start = " + start.GetLabelOffset() +\r
1454       //                  "  block end = " + end.GetLabelOffset());\r
1455       return (end.GetLabelOffset() - start.GetLabelOffset()) > maxCodeSize;\r
1456     }\r
1457 \r
1458     internal virtual void Write(FileImage output, bool fatFormat) {\r
1459       if (fatFormat) output.Write(start.GetLabelOffset());\r
1460       else output.Write((short)start.GetLabelOffset());\r
1461       uint len = end.GetLabelOffset() - start.GetLabelOffset();\r
1462       if (fatFormat) output.Write(len);\r
1463       else output.Write((byte)len);\r
1464     }\r
1465 \r
1466   }\r
1467 \r
1468   /// <summary>\r
1469   /// The descriptor for a guarded block (.try)\r
1470   /// </summary>\r
1471   public class TryBlock : CodeBlock {\r
1472     protected bool fatFormat = false;\r
1473     protected int flags = 0;\r
1474     ArrayList handlers = new ArrayList();\r
1475 \r
1476     /// <summary>\r
1477     /// Create a new try block\r
1478     /// </summary>\r
1479     /// <param name="start">start label for the try block</param>\r
1480     /// <param name="end">end label for the try block</param>\r
1481     public TryBlock(CILLabel start, CILLabel end) : base(start,end) { }\r
1482 \r
1483     /// <summary>\r
1484     /// Add a handler to this try block\r
1485     /// </summary>\r
1486     /// <param name="handler">a handler to be added to the try block</param>\r
1487     public void AddHandler(HandlerBlock handler) {\r
1488       flags = handler.GetFlag();\r
1489       handlers.Add(handler);\r
1490     }\r
1491 \r
1492     internal void SetSize() {\r
1493       fatFormat = base.isFat();\r
1494       if (fatFormat) return;\r
1495       for (int i=0; i < handlers.Count; i++) {\r
1496         HandlerBlock handler = (HandlerBlock)handlers[i];\r
1497         if (handler.isFat()) {\r
1498           fatFormat = true;\r
1499           return;\r
1500         }\r
1501       }\r
1502     }\r
1503 \r
1504     internal int NumHandlers() {\r
1505       return handlers.Count;\r
1506   }\r
1507 \r
1508     internal override bool isFat() {\r
1509       return fatFormat;\r
1510     }\r
1511 \r
1512     internal override void Write(FileImage output, bool fatFormat) {\r
1513       // Console.WriteLine("writing exception details");\r
1514       for (int i=0; i < handlers.Count; i++) {\r
1515         // Console.WriteLine("Except block " + i);\r
1516         HandlerBlock handler = (HandlerBlock)handlers[i];\r
1517         if (fatFormat) output.Write(flags);\r
1518         else output.Write((short)flags);\r
1519         // Console.WriteLine("flags = " + Hex.Short(flags));\r
1520         base.Write(output,fatFormat);\r
1521         handler.Write(output,fatFormat);\r
1522       }\r
1523     }\r
1524   }\r
1525 \r
1526   public abstract class HandlerBlock : CodeBlock \r
1527   {\r
1528     protected static readonly short ExceptionFlag = 0;\r
1529     protected static readonly short FilterFlag = 0x01;\r
1530     protected static readonly short FinallyFlag = 0x02;\r
1531     protected static readonly short FaultFlag = 0x04;\r
1532 \r
1533     public HandlerBlock(CILLabel start, CILLabel end) : base(start,end) { }\r
1534 \r
1535     internal virtual short GetFlag() { return ExceptionFlag; }\r
1536 \r
1537     internal override void Write(FileImage output, bool fatFormat) {\r
1538       base.Write(output,fatFormat);\r
1539     }\r
1540 \r
1541   }\r
1542 \r
1543   /// <summary>\r
1544   /// The descriptor for a catch clause (.catch)\r
1545   /// </summary>\r
1546   public class Catch : HandlerBlock \r
1547   {\r
1548     Class exceptType;\r
1549     \r
1550     /// <summary>\r
1551     /// Create a new catch clause\r
1552     /// </summary>\r
1553     /// <param name="except">the exception to be caught</param>\r
1554     /// <param name="handlerStart">start of the handler code</param>\r
1555     /// <param name="handlerEnd">end of the handler code</param>\r
1556     public Catch(Class except, CILLabel handlerStart, CILLabel handlerEnd) \r
1557                                             : base(handlerStart,handlerEnd) {\r
1558       exceptType = except;\r
1559     }\r
1560 \r
1561     internal override void Write(FileImage output, bool fatFormat) {\r
1562       base.Write(output,fatFormat);\r
1563       output.Write(exceptType.Token());\r
1564     }\r
1565   }\r
1566 \r
1567   /// <summary>\r
1568   /// The descriptor for a filter clause (.filter)\r
1569   /// </summary>\r
1570   public class Filter : HandlerBlock \r
1571   {\r
1572     CILLabel filterLabel;\r
1573 \r
1574     /// <summary>\r
1575     /// Create a new filter clause\r
1576     /// </summary>\r
1577     /// <param name="filterLabel">the label where the filter code starts</param>\r
1578     /// <param name="handlerStart">the start of the handler code</param>\r
1579     /// <param name="handlerEnd">the end of the handler code</param>\r
1580     public Filter(CILLabel filterLabel, CILLabel handlerStart, \r
1581                         CILLabel handlerEnd) : base(handlerStart,handlerEnd) {\r
1582       this.filterLabel = filterLabel;\r
1583     }\r
1584 \r
1585     internal override short GetFlag() { \r
1586       return FilterFlag; \r
1587     }\r
1588 \r
1589     internal override void Write(FileImage output, bool fatFormat) {\r
1590       base.Write(output,fatFormat);\r
1591       output.Write(filterLabel.GetLabelOffset());\r
1592     }\r
1593 \r
1594   }\r
1595 \r
1596   /// <summary>\r
1597   /// Descriptor for a finally block (.finally)\r
1598   /// </summary>\r
1599   public class Finally : HandlerBlock \r
1600   {\r
1601     /// <summary>\r
1602     /// Create a new finally clause\r
1603     /// </summary>\r
1604     /// <param name="finallyStart">start of finally code</param>\r
1605     /// <param name="finallyEnd">end of finally code</param>\r
1606     public Finally(CILLabel finallyStart, CILLabel finallyEnd)\r
1607       : base(finallyStart,finallyEnd) { }\r
1608 \r
1609     internal override short GetFlag() { \r
1610       return FinallyFlag; \r
1611     }\r
1612 \r
1613     internal override void Write(FileImage output, bool fatFormat) {\r
1614       base.Write(output,fatFormat);\r
1615       output.Write((int)0);\r
1616     }\r
1617 \r
1618   }\r
1619 \r
1620   /// <summary>\r
1621   /// Descriptor for a fault block (.fault)\r
1622   /// </summary>\r
1623   public class Fault : HandlerBlock \r
1624   {\r
1625     /// <summary>\r
1626     /// Create a new fault clause\r
1627     /// </summary>\r
1628     /// <param name="faultStart">start of the fault code</param>\r
1629     /// <param name="faultEnd">end of the fault code</param>\r
1630     public Fault(CILLabel faultStart, CILLabel faultEnd)\r
1631                                               : base(faultStart,faultEnd) { }\r
1632 \r
1633     internal override short GetFlag() { \r
1634       return FaultFlag; \r
1635     }\r
1636 \r
1637     internal override void Write(FileImage output, bool fatFormat) {\r
1638       base.Write(output,fatFormat);\r
1639       output.Write((int)0);\r
1640       \r
1641     }\r
1642   }\r
1643 \r
1644   /**************************************************************************/  \r
1645   /// <summary>\r
1646         /// The base descriptor for a class \r
1647         /// </summary>\r
1648         public abstract class Class : Type\r
1649         {\r
1650     protected int row = 0;\r
1651     protected string name, nameSpace;\r
1652     protected uint nameIx, nameSpaceIx;\r
1653                 protected MetaData _metaData;\r
1654                 internal Class(string nameSpaceName, string className, MetaData md)\r
1655                                                               : base(0x12) {\r
1656       nameSpace = nameSpaceName;\r
1657       name = className;\r
1658       nameIx = md.AddToStringsHeap(name);\r
1659       nameSpaceIx = md.AddToStringsHeap(nameSpace);\r
1660       _metaData = md;\r
1661     }\r
1662 \r
1663     internal Class(uint nsIx, uint nIx) : base(0x12) {\r
1664       nameSpaceIx = nsIx;\r
1665       nameIx = nIx;\r
1666     }\r
1667 \r
1668     internal virtual uint TypeDefOrRefToken() { return 0; }\r
1669 \r
1670     internal virtual void MakeValueClass() {\r
1671       typeIndex = 0x11;\r
1672     }\r
1673         \r
1674     internal virtual string TypeName() {\r
1675       return (nameSpace + "." + name);\r
1676     }\r
1677 \r
1678     internal override MetaDataElement GetTypeSpec(MetaData md) {\r
1679       return this;\r
1680     }\r
1681         }\r
1682   /**************************************************************************/  \r
1683   // This Class produces entries in the TypeDef table of the MetaData \r
1684   // in the PE meta data.\r
1685 \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
1688 \r
1689   /// <summary>\r
1690         /// The descriptor for a class defined in the IL (.class) in the current assembly/module\r
1691         /// </summary>\r
1692         /// \r
1693         public class ClassDef : Class\r
1694         {\r
1695     private static readonly uint HasSecurity = 0x00040000;\r
1696     private static readonly byte ElementType_Class = 0x12;\r
1697 \r
1698     Class superType;\r
1699     ArrayList fields = new ArrayList();\r
1700     ArrayList methods = new ArrayList();\r
1701     ArrayList events;\r
1702     ArrayList properties;\r
1703     bool typeIndexChecked = true;\r
1704     uint fieldIx = 0, methodIx = 0;\r
1705     byte[] securityActions;\r
1706     uint flags;\r
1707     ClassLayout layout;\r
1708     ClassDef parentClass;\r
1709     MetaData metaData;\r
1710     \r
1711     internal ClassDef(TypeAttr attrSet, string nsName, string name, \r
1712                       MetaData md) : base(nsName, name, md) {\r
1713                         metaData = md;\r
1714       superType = metaData.mscorlib.GetSpecialSystemClass(PrimitiveType.Object);\r
1715       flags = (uint)attrSet;\r
1716       tabIx = MDTable.TypeDef;\r
1717     }\r
1718 \r
1719     internal void SetSuper(Class sClass) {\r
1720       superType = sClass;\r
1721       if (sClass is ClassRef)\r
1722         typeIndex = superType.GetTypeIndex();\r
1723       else\r
1724         typeIndexChecked = false;\r
1725     }\r
1726 \r
1727     internal override void MakeValueClass() {\r
1728       superType = metaData.mscorlib.ValueType();\r
1729       typeIndex = superType.GetTypeIndex();\r
1730     }\r
1731 \r
1732     public void SpecialNoSuper() {\r
1733       superType = null;\r
1734     }\r
1735 \r
1736     /// <summary>\r
1737     /// Add an attribute to this class\r
1738     /// </summary>\r
1739     /// <param name="ta">the attribute to be added</param>\r
1740     public void AddAttribute(TypeAttr ta) { \r
1741       flags |= (uint)ta;\r
1742     }\r
1743 \r
1744     /// <summary>\r
1745     /// Add an interface that is implemented by this class\r
1746     /// </summary>\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
1750     }\r
1751 \r
1752     /// <summary>\r
1753     ///  Add a named generic type parameter\r
1754     /// </summary>\r
1755     public GenericParameter AddGenericParameter (short index, string name) {\r
1756             GenericParameter gp = new GenericParameter (this, metaData, index, name);
1757             metaData.AddToTable (MDTable.GenericParam, gp);\r
1758             return gp;
1759     }\r
1760 \r
1761     /// <summary>\r
1762     /// Add a field to this class\r
1763     /// </summary>\r
1764     /// <param name="name">field name</param>\r
1765     /// <param name="fType">field type</param>\r
1766     /// <returns>a descriptor for this new field</returns>\r
1767     public FieldDef AddField(string name, Type fType) {\r
1768       FieldDef field = new FieldDef(name,fType);\r
1769       fields.Add(field);\r
1770       return field;\r
1771     }\r
1772 \r
1773     /// <summary>\r
1774     /// Add a field to this class\r
1775     /// </summary>\r
1776     /// <param name="fAtts">attributes for this field</param>\r
1777     /// <param name="name">field name</param>\r
1778     /// <param name="fType">field type</param>\r
1779     /// <returns>a descriptor for this new field</returns>\r
1780     public FieldDef AddField(FieldAttr fAtts, string name, Type fType) {\r
1781       FieldDef field = new FieldDef(fAtts,name,fType);\r
1782       fields.Add(field);\r
1783       return field;\r
1784     }\r
1785 \r
1786     /// <summary>\r
1787     /// Add a method to this class\r
1788     /// </summary>\r
1789     /// <param name="name">method name</param>\r
1790     /// <param name="retType">return type</param>\r
1791     /// <param name="pars">parameters</param>\r
1792     /// <returns>a descriptor for this new method</returns>\r
1793     public MethodDef AddMethod(string name, Type retType, Param[] pars) {\r
1794       // Console.WriteLine("Adding method " + name + " to class " + this.name);\r
1795       MethodDef meth = new MethodDef(metaData,name,retType, pars);\r
1796       methods.Add(meth);\r
1797       return meth;\r
1798     }\r
1799 \r
1800     /// <summary>\r
1801     /// Add a method to this class\r
1802     /// </summary>\r
1803     /// <param name="mAtts">attributes for this method</param>\r
1804     /// <param name="iAtts">implementation attributes for this method</param>\r
1805     /// <param name="name">method name</param>\r
1806     /// <param name="retType">return type</param>\r
1807     /// <param name="pars">parameters</param>\r
1808     /// <returns>a descriptor for this new method</returns>\r
1809     public MethodDef AddMethod(MethAttr mAtts, ImplAttr iAtts, string name, \r
1810                                Type retType, Param[] pars) {\r
1811       // Console.WriteLine("Adding method " + name + " to class " + this.name);\r
1812       MethodDef meth = new MethodDef(metaData,mAtts,iAtts,name,retType,pars);\r
1813       methods.Add(meth);\r
1814       return meth;\r
1815     }\r
1816 \r
1817     /// <summary>\r
1818     /// Add an event to this class\r
1819     /// </summary>\r
1820     /// <param name="name">event name</param>\r
1821     /// <param name="eType">event type</param>\r
1822     /// <returns>a descriptor for this new event</returns>\r
1823     public Event AddEvent(string name, Type eType) {\r
1824       Event e = new Event(name,eType,this);\r
1825       if (events == null) events = new ArrayList();\r
1826       events.Add(e);\r
1827       return e;\r
1828     }\r
1829 \r
1830     /// <summary>\r
1831     /// Add a property to this class\r
1832     /// </summary>\r
1833     /// <param name="name">property name</param>\r
1834     /// <param name="propType">property type</param>\r
1835     /// <returns>a descriptor for this new property</returns>\r
1836     public Property AddProperty(string name, Type retType, Type[] pars) {\r
1837       Property p = new Property(name, retType, pars, this);\r
1838       if (properties == null) properties = new ArrayList();\r
1839       properties.Add(p);\r
1840       return p;\r
1841     }\r
1842 \r
1843 \r
1844     /// <summary>\r
1845     /// Add a nested class to this class\r
1846     /// </summary>\r
1847     /// <param name="attrSet">attributes for this nested class</param>\r
1848     /// <param name="nsName">nested name space name</param>\r
1849     /// <param name="name">nested class name</param>\r
1850     /// <returns>a descriptor for this new nested class</returns>\r
1851     public ClassDef AddNestedClass(TypeAttr attrSet, string nsName, \r
1852                                    string name) {\r
1853       ClassDef nClass = new ClassDef(attrSet,nsName,name,metaData);\r
1854       metaData.AddToTable(MDTable.TypeDef,nClass);\r
1855       metaData.AddToTable(MDTable.NestedClass,new MapElem(nClass,Row,MDTable.TypeDef));\r
1856       nClass.parentClass = this;\r
1857       return (nClass);\r
1858      }\r
1859 \r
1860     /// <summary>\r
1861     /// Add a nested class to this class\r
1862     /// </summary>\r
1863     /// <param name="attrSet">attributes for this nested class</param>\r
1864     /// <param name="nsName">nested name space name</param>\r
1865     /// <param name="name">nested class name</param>\r
1866     /// <param name="sType">super type of this nested class</param>\r
1867     /// <returns>a descriptor for this new nested class</returns>\r
1868     public ClassDef AddNestedClass(TypeAttr attrSet, string nsName, \r
1869                                    string name, Class sType) {\r
1870       ClassDef nClass = new ClassDef(attrSet,nsName,name,metaData);\r
1871       nClass.SetSuper(sType);\r
1872       metaData.AddToTable(MDTable.TypeDef,nClass);\r
1873       metaData.AddToTable(MDTable.NestedClass,\r
1874                           new MapElem(nClass,Row,MDTable.TypeDef));\r
1875       nClass.parentClass = this;\r
1876       return (nClass);\r
1877     }\r
1878 \r
1879     /// <summary>\r
1880     /// Add layout information for this class.  This class must have the\r
1881     /// sequential or explicit attribute.\r
1882     /// </summary>\r
1883     /// <param name="packSize">packing size (.pack)</param>\r
1884     /// <param name="classSize">class size (.size)</param>\r
1885     public void AddLayoutInfo (int packSize, int classSize) {\r
1886       layout = new ClassLayout(packSize,classSize,this);\r
1887     }\r
1888 \r
1889     /// <summary>\r
1890     /// Use a method as the implementation for another method (.override)\r
1891     /// </summary>\r
1892     /// <param name="decl">the method to be overridden</param>\r
1893     /// <param name="body">the implementation to be used</param>\r
1894     public void AddMethodOverride(Method decl, Method body) {\r
1895       metaData.AddToTable(MDTable.MethodImpl,new MethodImpl(this,decl,body));\r
1896     }\r
1897 \r
1898     /// <summary>\r
1899     /// Add security to this class NOT YET IMPLEMENTED\r
1900     /// </summary>\r
1901     /// <param name="permissionSet"></param>\r
1902     public void AddSecurity(byte[] permissionSet) {\r
1903       throw(new NotYetImplementedException("Class security "));\r
1904       //flags |= HasSecurity;\r
1905      // securityActions = permissionSet;\r
1906     }\r
1907 \r
1908     //public void AddLineInfo(int row, int col) { }\r
1909 \r
1910     internal void CheckTypeIndex() {\r
1911       if (typeIndexChecked) return;\r
1912       if (!(superType is ClassRef)) \r
1913         ((ClassDef)superType).CheckTypeIndex();\r
1914       typeIndex = superType.GetTypeIndex();\r
1915       typeIndexChecked = true;\r
1916     }\r
1917 \r
1918     internal sealed override void BuildTables(MetaData md) {\r
1919       if (done) return;\r
1920       if ((flags & (uint)TypeAttr.Interface) != 0) { superType = null; }\r
1921       // Console.WriteLine("Building tables for " + name);\r
1922       if (layout != null) md.AddToTable(MDTable.ClassLayout,layout);\r
1923       // Console.WriteLine("adding methods " + methods.Count);\r
1924       methodIx = md.TableIndex(MDTable.Method);\r
1925       for (int i=0; i < methods.Count; i++) {\r
1926         md.AddToTable(MDTable.Method,(MetaDataElement)methods[i]);\r
1927         ((MethodDef)methods[i]).BuildTables(md);\r
1928       }\r
1929       // Console.WriteLine("adding fields");\r
1930       fieldIx = md.TableIndex(MDTable.Field);\r
1931       for (int i=0; i < fields.Count; i++) {\r
1932         md.AddToTable(MDTable.Field,(MetaDataElement)fields[i]);\r
1933         ((FieldDef)fields[i]).BuildTables(md);\r
1934       }\r
1935       // Console.WriteLine("adding events and properties");\r
1936       if (events != null) { \r
1937         for (int i=0; i < events.Count; i++) {\r
1938           md.AddToTable(MDTable.Event,(Event)events[i]);\r
1939           ((Event)events[i]).BuildTables(md);\r
1940         }\r
1941         md.AddToTable(MDTable.EventMap,\r
1942           new MapElem(this,((Event)events[0]).Row,MDTable.Event));\r
1943       }\r
1944       if (properties != null) { \r
1945         for (int i=0; i < properties.Count; i++) {\r
1946           md.AddToTable(MDTable.Property,(Property)properties[i]);\r
1947           ((Property)properties[i]).BuildTables(md);\r
1948         }\r
1949         md.AddToTable(MDTable.PropertyMap,new MapElem(this,\r
1950                           ((Property)properties[0]).Row,MDTable.Property));\r
1951       }\r
1952       DoCustomAttributes (md);\r
1953       // Console.WriteLine("End of building tables");\r
1954       done = true;\r
1955     }\r
1956 \r
1957     internal sealed override uint Size(MetaData md) {\r
1958       return 4 + 2 * md.StringsIndexSize() + \r
1959         md.CodedIndexSize(CIx.TypeDefOrRef) +\r
1960         md.TableIndexSize(MDTable.Field) + \r
1961         md.TableIndexSize(MDTable.Method);\r
1962     }\r
1963 \r
1964     internal sealed override void Write(FileImage output) {\r
1965       output.Write(flags);\r
1966       output.StringsIndex(nameIx);\r
1967       output.StringsIndex(nameSpaceIx);\r
1968       //if (superType != null) \r
1969       // Console.WriteLine("getting coded index for superType of " + name + " = " + superType.GetCodedIx(CIx.TypeDefOrRef));\r
1970       output.WriteCodedIndex(CIx.TypeDefOrRef,superType);\r
1971       output.WriteIndex(MDTable.Field,fieldIx);\r
1972       output.WriteIndex(MDTable.Method,methodIx);\r
1973     }\r
1974 \r
1975     internal sealed override uint TypeDefOrRefToken() {\r
1976       uint cIx = Row;\r
1977       cIx = cIx << 2;\r
1978       return cIx;\r
1979     }\r
1980 \r
1981     internal sealed override void TypeSig(MemoryStream sig) {\r
1982       if (!typeIndexChecked) CheckTypeIndex();\r
1983       sig.WriteByte(GetTypeIndex());\r
1984       MetaData.CompressNum(TypeDefOrRefToken(),sig);\r
1985     }\r
1986 \r
1987     internal sealed override uint GetCodedIx(CIx code) {\r
1988       switch (code) {\r
1989         case (CIx.TypeDefOrRef) : return 0; \r
1990         case (CIx.HasCustomAttr) : return 3; \r
1991         case (CIx.HasDeclSecurity) : return 0; \r
1992         case (CIx.TypeOrMethodDef) : return 0; \r
1993       }\r
1994       return 0;\r
1995     }\r
1996  \r
1997         }\r
1998   /**************************************************************************/  \r
1999         /// <summary>\r
2000         /// Layout information for a class (.class [sequential | explicit])\r
2001         /// </summary>\r
2002         internal class ClassLayout : MetaDataElement\r
2003         {\r
2004     ClassDef parent;\r
2005     ushort packSize = 0;\r
2006     uint classSize = 0;\r
2007 \r
2008                 internal ClassLayout(int pack, int cSize, ClassDef par) {\r
2009       packSize = (ushort)pack;\r
2010       classSize = (uint)cSize;\r
2011       parent = par;\r
2012       tabIx = MDTable.ClassLayout;\r
2013                 }\r
2014 \r
2015     internal sealed override uint Size(MetaData md) {\r
2016       return 6 + md.TableIndexSize(MDTable.TypeDef);\r
2017     }\r
2018 \r
2019     internal sealed override void Write(FileImage output) {\r
2020       output.Write(packSize);\r
2021       output.Write(classSize);\r
2022       output.WriteIndex(MDTable.TypeDef,parent.Row);\r
2023     }\r
2024 \r
2025         }\r
2026   /**************************************************************************/  \r
2027         /// <summary>\r
2028         /// Descriptor for a class/interface declared in another module of THIS \r
2029         /// assembly, or in another assembly.\r
2030         /// </summary>\r
2031         public class ClassRef : Class\r
2032         {\r
2033     protected ResolutionScope parent;\r
2034     ExternClass externClass;\r
2035     protected MetaData metaData;\r
2036 \r
2037                 internal ClassRef(string nsName, string name, MetaData md) : base(nsName, name, md) {\r
2038       metaData = md;\r
2039       tabIx = MDTable.TypeRef;\r
2040     }\r
2041 \r
2042     /// <summary>\r
2043     /// Add a method to this class\r
2044     /// </summary>\r
2045     /// <param name="name">method name</param>\r
2046     /// <param name="retType">return type</param>\r
2047     /// <param name="pars">parameter types</param>\r
2048     /// <returns>a descriptor for this method</returns>\r
2049     public MethodRef AddMethod(string name, Type retType, Type[] pars) {\r
2050       MethodRef meth = new MethodRef(this,name,retType,pars,false,null);\r
2051       metaData.AddToTable(MDTable.MemberRef,meth);\r
2052       return meth;\r
2053     }\r
2054 \r
2055     /// <summary>\r
2056     /// Add a method to this class\r
2057     /// </summary>\r
2058     /// <param name="name">method name</param>\r
2059     /// <param name="retType">return type</param>\r
2060     /// <param name="pars">parameter types</param>\r
2061     /// <returns>a descriptor for this method</returns>\r
2062     public MethodRef AddVarArgMethod(string name, Type retType, \r
2063                                      Type[] pars, Type[] optPars) {\r
2064       MethodRef meth = new MethodRef(this,name,retType,pars,true,optPars);\r
2065       metaData.AddToTable(MDTable.MemberRef,meth);\r
2066       return meth;\r
2067     }\r
2068 \r
2069     /// <summary>\r
2070     /// Add a field to this class\r
2071     /// </summary>\r
2072     /// <param name="name">field name</param>\r
2073     /// <param name="fType">field type</param>\r
2074     /// <returns>a descriptor for this field</returns>\r
2075     public FieldRef AddField(string name, Type fType) {\r
2076       FieldRef field = new FieldRef(this,name,fType);\r
2077       metaData.AddToTable(MDTable.MemberRef,field);\r
2078       return field;\r
2079     }\r
2080 \r
2081     internal void SetParent(ResolutionScope par) {\r
2082       parent = par;\r
2083     }\r
2084 \r
2085     internal override string TypeName() {\r
2086       if ((parent != null) && (parent is AssemblyRef))\r
2087         return (nameSpace + "." + name + ", " + ((AssemblyRef)parent).TypeName());\r
2088       else \r
2089         return (nameSpace + name);\r
2090     }\r
2091 \r
2092     internal sealed override uint Size(MetaData md) {\r
2093       return md.CodedIndexSize(CIx.ResolutionScope) + 2 * \r
2094              md.StringsIndexSize();\r
2095     }\r
2096 \r
2097     internal sealed override void Write(FileImage output) {\r
2098       output.WriteCodedIndex(CIx.ResolutionScope,parent);\r
2099       output.StringsIndex(nameIx);\r
2100       output.StringsIndex(nameSpaceIx);\r
2101     }\r
2102 \r
2103     internal override sealed uint TypeDefOrRefToken() {\r
2104       uint cIx = Row;\r
2105       cIx = (cIx << 2) | 0x1;\r
2106       return cIx;\r
2107     }\r
2108 \r
2109     internal override void TypeSig(MemoryStream sig) {\r
2110       sig.WriteByte(GetTypeIndex());\r
2111       MetaData.CompressNum(TypeDefOrRefToken(),sig);\r
2112     }\r
2113 \r
2114     internal sealed override uint GetCodedIx(CIx code) {\r
2115       switch (code) {\r
2116         case (CIx.TypeDefOrRef) : return 1; \r
2117         case (CIx.HasCustomAttr) : return 2; \r
2118         case (CIx.MemberRefParent) : return 1; \r
2119         case (CIx.ResolutionScope) : return 3; \r
2120       }\r
2121       return 0;\r
2122     }\r
2123  \r
2124         }\r
2125   /**************************************************************************/  \r
2126 \r
2127   public class ExternClassRef : ClassRef {\r
2128 \r
2129     ExternClass externClass;\r
2130 \r
2131     internal ExternClassRef(TypeAttr attrs, string nsName, string name,\r
2132                           FileRef declFile, MetaData md) : base(nsName,name,md) {\r
2133       externClass = new ExternClass(attrs,nameSpaceIx,nameIx,declFile);\r
2134       metaData.AddToTable(MDTable.ExportedType,externClass);\r
2135     }\r
2136 \r
2137     internal ExternClassRef(string name, MetaData md) : base(null,name,md) {\r
2138     }\r
2139 \r
2140     public ClassRef AddNestedClass(TypeAttr attrs, string name) {\r
2141       ExternClassRef nestedClass = new ExternClassRef(name,metaData);\r
2142       externClass = new ExternClass(attrs,0,nameIx,this.externClass);\r
2143       metaData.AddToTable(MDTable.ExportedType,externClass);\r
2144       return nestedClass;\r
2145     }\r
2146  \r
2147   }\r
2148   /**************************************************************************/  \r
2149   /// <summary>\r
2150   /// Descriptor for a constant value\r
2151   /// </summary>\r
2152   public abstract class Constant {\r
2153     protected uint size = 0;\r
2154     protected Type type;\r
2155     protected uint blobIndex;\r
2156     protected bool addedToBlobHeap = false;\r
2157 \r
2158                 internal Constant()     {       }\r
2159 \r
2160     internal virtual uint GetBlobIndex(MetaData md) { return 0; }\r
2161 \r
2162     internal uint GetSize() { return size; }\r
2163 \r
2164     internal byte GetTypeIndex() { return type.GetTypeIndex(); }\r
2165 \r
2166     internal virtual void Write(BinaryWriter bw) {  }\r
2167 \r
2168         }\r
2169   /// <summary>\r
2170   /// Descriptor for a constant value\r
2171   /// </summary>\r
2172   public abstract class DataConstant : Constant {\r
2173     private uint dataOffset = 0;\r
2174 \r
2175     internal DataConstant() { }\r
2176 \r
2177     public uint DataOffset {\r
2178       get { return dataOffset; }\r
2179       set { dataOffset = value; }\r
2180     }\r
2181 \r
2182   }\r
2183 \r
2184   /// <summary>\r
2185   /// Boolean constant\r
2186   /// </summary>\r
2187   public class BoolConst : Constant {\r
2188     bool val;\r
2189 \r
2190     /// <summary>\r
2191     /// Create a new boolean constant with the value "val"\r
2192     /// </summary>\r
2193     /// <param name="val">value of this boolean constant</param>\r
2194     public BoolConst(bool val) {\r
2195       this.val = val;\r
2196       size = 1;\r
2197       type = PrimitiveType.Boolean;\r
2198     }\r
2199 \r
2200     internal sealed override uint GetBlobIndex(MetaData md) {\r
2201       if (!addedToBlobHeap) {\r
2202         if (val) blobIndex = md.AddToBlobHeap((sbyte)1);\r
2203         else blobIndex = md.AddToBlobHeap((sbyte)0);\r
2204         addedToBlobHeap = true;\r
2205       }\r
2206       return blobIndex;\r
2207     }\r
2208 \r
2209     internal sealed override void Write(BinaryWriter bw) {\r
2210       if (val) bw.Write((sbyte)1);\r
2211       else bw.Write((sbyte)0);\r
2212     }\r
2213 \r
2214   }\r
2215 \r
2216   public class ByteArrConst : DataConstant {\r
2217     byte[] val;\r
2218 \r
2219     public ByteArrConst(byte[] val) {\r
2220       this.val = val;\r
2221       size = (uint)val.Length;\r
2222     }\r
2223 \r
2224     internal sealed override uint GetBlobIndex(MetaData md) {\r
2225       if (!addedToBlobHeap) {\r
2226         blobIndex = md.AddToBlobHeap(val);\r
2227         addedToBlobHeap = true;\r
2228       }\r
2229       return blobIndex;\r
2230     }\r
2231 \r
2232     internal sealed override void Write(BinaryWriter bw) {\r
2233       bw.Write(val);\r
2234     }\r
2235 \r
2236   }\r
2237 \r
2238   public class CharConst : Constant {\r
2239     char val;\r
2240 \r
2241     public CharConst(char val) {\r
2242       this.val = val;\r
2243       size = 2;\r
2244       type = PrimitiveType.Char;\r
2245     }\r
2246 \r
2247     internal sealed override uint GetBlobIndex(MetaData md) {\r
2248       if (!addedToBlobHeap) {\r
2249         blobIndex = md.AddToBlobHeap(val);\r
2250         addedToBlobHeap = true;\r
2251       }\r
2252       return blobIndex;\r
2253     }\r
2254 \r
2255     internal sealed override void Write(BinaryWriter bw) {\r
2256       bw.Write(val);\r
2257     }\r
2258 \r
2259   }\r
2260 \r
2261   public class FloatConst : DataConstant {\r
2262     float val;\r
2263 \r
2264     public FloatConst(float val) {\r
2265       this.val = val;\r
2266       size = 4;\r
2267       type = PrimitiveType.Float32;\r
2268     }\r
2269 \r
2270     internal sealed override uint GetBlobIndex(MetaData md) {\r
2271       if (!addedToBlobHeap) {\r
2272         blobIndex = md.AddToBlobHeap(val);\r
2273         addedToBlobHeap = true;\r
2274       }\r
2275       return blobIndex;\r
2276     }\r
2277 \r
2278     internal sealed override void Write(BinaryWriter bw) {\r
2279       bw.Write(val);\r
2280     }\r
2281 \r
2282   }\r
2283 \r
2284   public class DoubleConst : DataConstant {\r
2285     double val;\r
2286 \r
2287     public DoubleConst(double val) {\r
2288       this.val = val;\r
2289       size = 8;\r
2290       type = PrimitiveType.Float64;\r
2291     }\r
2292 \r
2293     internal sealed override uint GetBlobIndex(MetaData md) {\r
2294       if (!addedToBlobHeap) {\r
2295         blobIndex = md.AddToBlobHeap(val);\r
2296         addedToBlobHeap = true;\r
2297       }\r
2298       return blobIndex;\r
2299     }\r
2300 \r
2301     internal sealed override void Write(BinaryWriter bw) {\r
2302       bw.Write(val);\r
2303     }\r
2304 \r
2305   }\r
2306 \r
2307   public class IntConst : DataConstant {\r
2308     long val;\r
2309 \r
2310     public IntConst(sbyte val) {\r
2311       this.val = val;\r
2312       size = 1;\r
2313       type = PrimitiveType.Int8;\r
2314     }\r
2315 \r
2316     public IntConst(short val) {\r
2317       this.val = val;\r
2318       size = 2;\r
2319       type = PrimitiveType.Int16;\r
2320     }\r
2321 \r
2322     public IntConst(int val) {\r
2323       this.val = val;\r
2324       size = 4;\r
2325       type = PrimitiveType.Int32;\r
2326     }\r
2327 \r
2328     public IntConst(long val) {\r
2329       this.val = val;\r
2330       size = 8;\r
2331       type = PrimitiveType.Int64;\r
2332     }\r
2333 \r
2334     internal sealed override uint GetBlobIndex(MetaData md) {\r
2335       if (!addedToBlobHeap) {\r
2336         switch (size) {\r
2337           case (1) : blobIndex = md.AddToBlobHeap((sbyte)val); break;\r
2338           case (2) : blobIndex = md.AddToBlobHeap((short)val); break;\r
2339           case (4) : blobIndex = md.AddToBlobHeap((int)val); break;\r
2340           default : blobIndex = md.AddToBlobHeap(val); break; \r
2341         }\r
2342         addedToBlobHeap = true;\r
2343       }\r
2344       return blobIndex;\r
2345     }\r
2346 \r
2347     internal sealed override void Write(BinaryWriter bw) {\r
2348       switch (size) {\r
2349         case (1) : bw.Write((sbyte)val); break;\r
2350         case (2) : bw.Write((short)val); break;\r
2351         case (4) : bw.Write((int)val); break;\r
2352         default : bw.Write(val); break; \r
2353       }\r
2354     }\r
2355 \r
2356   }\r
2357 \r
2358   public class UIntConst : Constant {\r
2359     long val;\r
2360 \r
2361     public UIntConst(sbyte val) {\r
2362       this.val = val;\r
2363       size = 1;\r
2364       type = PrimitiveType.UInt8;\r
2365     }\r
2366     public UIntConst(short val) {\r
2367       this.val = val;\r
2368       size = 2;\r
2369       type = PrimitiveType.UInt16;\r
2370     }\r
2371     public UIntConst(int val) {\r
2372       this.val = val;\r
2373       size = 4;\r
2374       type = PrimitiveType.UInt32;\r
2375     }\r
2376     public UIntConst(long val) {\r
2377       this.val = val;\r
2378       size = 8;\r
2379       type = PrimitiveType.UInt64;\r
2380     }\r
2381 \r
2382     internal sealed override uint GetBlobIndex(MetaData md) {\r
2383       if (!addedToBlobHeap) {\r
2384         switch (size) {\r
2385           case (1) : blobIndex = md.AddToBlobHeap((sbyte)val); break;\r
2386           case (2) : blobIndex = md.AddToBlobHeap((short)val); break;\r
2387           case (4) : blobIndex = md.AddToBlobHeap((int)val); break;\r
2388           default : blobIndex = md.AddToBlobHeap(val); break;\r
2389         }\r
2390         addedToBlobHeap = true;\r
2391       }\r
2392       return blobIndex;\r
2393     }\r
2394 \r
2395     internal sealed override void Write(BinaryWriter bw) {\r
2396       switch (size) {\r
2397         case (1) : bw.Write((sbyte)val); break;\r
2398         case (2) : bw.Write((short)val); break;\r
2399         case (4) : bw.Write((int)val); break;\r
2400         default : bw.Write(val); break;\r
2401       }\r
2402     }\r
2403 \r
2404   }\r
2405 \r
2406   public class StringConst : DataConstant {\r
2407     string val;\r
2408 \r
2409     public StringConst(string val) {\r
2410       this.val = val;\r
2411       size = (uint)val.Length;  // need to add null ??\r
2412       type = PrimitiveType.String;\r
2413     }\r
2414 \r
2415     internal sealed override uint GetBlobIndex(MetaData md) {\r
2416       if (!addedToBlobHeap) {\r
2417         blobIndex = md.AddToBlobHeap(val);\r
2418         addedToBlobHeap = true;\r
2419       }\r
2420       return blobIndex;\r
2421     }\r
2422 \r
2423     internal sealed override void Write(BinaryWriter bw) {\r
2424       bw.Write(val);\r
2425     }\r
2426 \r
2427   }\r
2428 \r
2429   public class NullConst : Constant {\r
2430  \r
2431     public NullConst() { \r
2432       size = 4;\r
2433       type = PrimitiveType.Class;\r
2434     }\r
2435 \r
2436     internal sealed override uint GetBlobIndex(MetaData md) {\r
2437       if (!addedToBlobHeap) {\r
2438         blobIndex = md.AddToBlobHeap((int)0);\r
2439         addedToBlobHeap = true;\r
2440       }\r
2441       return blobIndex;\r
2442     }\r
2443 \r
2444     internal sealed override void Write(BinaryWriter bw) {\r
2445       bw.Write((int)0); \r
2446     }\r
2447 \r
2448   }\r
2449 \r
2450   public class AddressConstant : DataConstant {\r
2451     DataConstant data;\r
2452 \r
2453     public AddressConstant(DataConstant dConst) {\r
2454       data = dConst;\r
2455       size = 4;\r
2456       type = PrimitiveType.TypedRef;\r
2457     }\r
2458 \r
2459     internal sealed override void Write(BinaryWriter bw) {\r
2460       ((FileImage)bw).WriteDataRVA(data.DataOffset);\r
2461     }\r
2462 \r
2463   }\r
2464 \r
2465   public class RepeatedConstant : DataConstant {\r
2466     DataConstant data;\r
2467     uint repCount;\r
2468 \r
2469     public RepeatedConstant(DataConstant dConst, int repeatCount) {\r
2470       data = dConst;\r
2471       repCount = (uint)repeatCount;\r
2472       int[] sizes = new int[1];\r
2473       sizes[0] = repeatCount;\r
2474       type = new BoundArray(type,1,sizes);\r
2475       size = data.GetSize() * repCount;\r
2476     }\r
2477 \r
2478     internal sealed override void Write(BinaryWriter bw) {\r
2479       for (int i=0; i < repCount; i++) {\r
2480         data.Write(bw);\r
2481       }\r
2482     }\r
2483 \r
2484   }\r
2485 \r
2486   public class ArrayConstant : DataConstant {\r
2487     DataConstant[] dataVals;\r
2488 \r
2489     public ArrayConstant(DataConstant[] dVals) {\r
2490       dataVals = dVals;\r
2491       for (int i=0; i < dataVals.Length; i++) {\r
2492         size += dataVals[i].GetSize();\r
2493       }\r
2494     }\r
2495 \r
2496     internal sealed override void Write(BinaryWriter bw) {\r
2497       for (int i=0; i < dataVals.Length; i++) {\r
2498         dataVals[i].Write(bw);\r
2499       }\r
2500     }\r
2501 \r
2502   }\r
2503 \r
2504   public class ClassType : Constant {\r
2505     string name;\r
2506     Class desc;\r
2507 \r
2508     public ClassType(string className) {\r
2509       name = className;\r
2510       type = PrimitiveType.ClassType;\r
2511     }\r
2512 \r
2513     public ClassType(Class classDesc) {\r
2514       desc = classDesc;\r
2515       type = PrimitiveType.ClassType;\r
2516     }\r
2517 \r
2518     internal override void Write(BinaryWriter bw) {\r
2519       if (name == null)  name = desc.TypeName();\r
2520       bw.Write(name);\r
2521     }\r
2522 \r
2523   }\r
2524 \r
2525 \r
2526 \r
2527   /**************************************************************************/  \r
2528         /// <summary>\r
2529         /// Summary description for ConstantElem.\r
2530         /// </summary>\r
2531         internal class ConstantElem : MetaDataElement\r
2532         {\r
2533     MetaDataElement parent;\r
2534     Constant cValue;\r
2535     uint valIx = 0;\r
2536 \r
2537                 internal ConstantElem(MetaDataElement parent, Constant val) {\r
2538       this.parent = parent;\r
2539       cValue = val;\r
2540                         tabIx = MDTable.Constant;\r
2541                 }\r
2542 \r
2543     internal sealed override void BuildTables(MetaData md) {\r
2544       if (done) return;\r
2545       valIx = cValue.GetBlobIndex(md);\r
2546       done = true;\r
2547     }\r
2548 \r
2549     internal void AddToBlob(BinaryWriter bw) {\r
2550       cValue.Write(bw);\r
2551     }\r
2552 \r
2553     internal sealed override uint Size(MetaData md) {\r
2554       return 2 + md.CodedIndexSize(CIx.HasConst) + md.BlobIndexSize();\r
2555     }\r
2556 \r
2557     internal sealed override void Write(FileImage output) {\r
2558       output.Write(cValue.GetTypeIndex());\r
2559       output.Write((byte)0);\r
2560       output.WriteCodedIndex(CIx.HasConst,parent);\r
2561       output.BlobIndex(valIx);\r
2562     }\r
2563 \r
2564         }\r
2565   /**************************************************************************/  \r
2566         /// <summary>\r
2567         /// Descriptor for a Custom Attribute (.custom) \r
2568         /// </summary>\r
2569 \r
2570         public class CustomAttribute : MetaDataElement\r
2571         {\r
2572     private static readonly ushort prolog = 0x0001;\r
2573     MetaDataElement parent;\r
2574     Method type;\r
2575     uint valIx;\r
2576     Constant cVal;\r
2577     byte[] byteVal;\r
2578     ushort numNamed = 0;\r
2579     ArrayList names, vals;\r
2580 \r
2581                 internal CustomAttribute(MetaDataElement paren, Method constrType, \r
2582                                                           Constant val) {\r
2583       parent = paren;\r
2584       type = constrType;\r
2585       cVal = val;\r
2586       tabIx = MDTable.CustomAttribute;\r
2587       throw(new NotYetImplementedException("Custom Attributes "));\r
2588                 }\r
2589 \r
2590     internal CustomAttribute(MetaDataElement paren, Method constrType,\r
2591                                                           byte[] val) {\r
2592       parent = paren;\r
2593       type = constrType;\r
2594       tabIx = MDTable.CustomAttribute;\r
2595       byteVal = val;\r
2596     }\r
2597 \r
2598     public void AddFieldOrProp(string name, Constant val) {\r
2599       if (numNamed == 0) {\r
2600         names = new ArrayList();\r
2601         vals = new ArrayList();\r
2602       }\r
2603       names.Add(name);\r
2604       vals.Add(val);\r
2605     }\r
2606 \r
2607     internal sealed override void BuildTables(MetaData md) {\r
2608       BinaryWriter bw = new BinaryWriter(new MemoryStream());\r
2609       bw.Write((ushort)1);\r
2610       md.AddToTable(MDTable.CustomAttribute, this);\r
2611       MemoryStream str = (MemoryStream)bw.BaseStream;\r
2612       valIx = md.AddToBlobHeap(str.ToArray());\r
2613     }\r
2614 \r
2615     internal sealed override uint Size(MetaData md) {\r
2616       return md.CodedIndexSize(CIx.HasCustomAttr) + md.CodedIndexSize(CIx.CustomAttributeType) + md.BlobIndexSize();\r
2617     }\r
2618 \r
2619     internal sealed override void Write(FileImage output) {\r
2620       output.WriteCodedIndex(CIx.HasCustomAttr,parent);\r
2621       output.WriteCodedIndex(CIx.CustomAttributeType,type);\r
2622       output.BlobIndex(valIx);\r
2623     }\r
2624 \r
2625         }\r
2626   /**************************************************************************/  \r
2627         /// <summary>\r
2628         /// Descriptor for a custom modifier of a type (modopt or modreq)\r
2629         /// </summary>\r
2630 \r
2631         public class CustomModifiedType : Type\r
2632         {\r
2633     Type type;\r
2634     Class cmodType;\r
2635 \r
2636     /// <summary>\r
2637     /// Create a new custom modifier for a type\r
2638     /// </summary>\r
2639     /// <param name="type">the type to be modified</param>\r
2640     /// <param name="cmod">the modifier</param>\r
2641     /// <param name="cmodType">the type reference to be associated with the type</param>\r
2642                 public CustomModifiedType(Type type, CustomModifier cmod, Class cmodType)\r
2643                                                           : base((byte)cmod) {\r
2644       this.type = type;\r
2645       this.cmodType = cmodType;\r
2646                 }\r
2647 \r
2648     internal sealed override void TypeSig(MemoryStream str) {\r
2649       str.WriteByte(typeIndex);\r
2650       MetaData.CompressNum(cmodType.TypeDefOrRefToken(),str);\r
2651       type.TypeSig(str);\r
2652     }\r
2653   \r
2654   }\r
2655   /**************************************************************************/  \r
2656   /// <summary>\r
2657   /// Descriptor for security permissions for a class or a method NOT YET IMPLEMENTED\r
2658   /// </summary>\r
2659         \r
2660         public class DeclSecurity : MetaDataElement\r
2661         {\r
2662     ushort action;\r
2663     MetaDataElement parent;\r
2664     uint permissionIx;\r
2665 \r
2666                 internal DeclSecurity(MetaDataElement paren, ushort act)        {\r
2667       parent = paren;\r
2668       action = act;\r
2669       tabIx = MDTable.DeclSecurity;\r
2670       throw(new NotYetImplementedException("Security "));\r
2671                 }\r
2672 \r
2673     internal sealed override uint Size(MetaData md) {\r
2674       return 2 + md.CodedIndexSize(CIx.HasDeclSecurity) + md.BlobIndexSize();\r
2675     }\r
2676 \r
2677     internal sealed override void BuildTables(MetaData md) {\r
2678       if (done) return;\r
2679 // add permission to blob heap\r
2680       done = true;\r
2681     }\r
2682 \r
2683     internal sealed override void Write(FileImage output) {\r
2684       output.Write(action);\r
2685       output.WriteCodedIndex(CIx.HasDeclSecurity,parent);\r
2686       output.BlobIndex(permissionIx);\r
2687     }\r
2688  \r
2689         }\r
2690   /**************************************************************************/  \r
2691         /// <summary>\r
2692         /// Descriptor for an event\r
2693         /// </summary>\r
2694   public class Event : Feature\r
2695         {\r
2696     Type eventType;\r
2697 \r
2698     internal Event(string name, Type eType, ClassDef parent) \r
2699                                             : base(name, parent) {\r
2700       eventType = eType;\r
2701                         tabIx = MDTable.Event;\r
2702     }\r
2703 \r
2704     /// <summary>\r
2705     /// Add the addon method to this event\r
2706     /// </summary>\r
2707     /// <param name="addon">the addon method</param>\r
2708     public void AddAddon(MethodDef addon) {\r
2709       AddMethod(addon,MethodType.AddOn);\r
2710     }\r
2711 \r
2712     /// <summary>\r
2713     /// Add the removeon method to this event\r
2714     /// </summary>\r
2715     /// <param name="removeOn">the removeon method</param>\r
2716     public void AddRemoveOn(MethodDef removeOn) {\r
2717       AddMethod(removeOn,MethodType.RemoveOn);\r
2718     }\r
2719 \r
2720     /// <summary>\r
2721     /// Add the fire method to this event\r
2722     /// </summary>\r
2723     /// <param name="fire">the fire method</param>\r
2724     public void AddFire(MethodDef fire) {\r
2725       AddMethod(fire,MethodType.Fire);\r
2726     }\r
2727 \r
2728     /// <summary>\r
2729     /// Add another method to this event\r
2730     /// </summary>\r
2731     /// <param name="other">the method to be added</param>\r
2732     public void AddOther(MethodDef other) {\r
2733       AddMethod(other,MethodType.Other);\r
2734     }\r
2735 \r
2736     internal sealed override void BuildTables(MetaData md) {\r
2737       if (done) return;\r
2738       nameIx = md.AddToStringsHeap(name);\r
2739       for (int i=0; i < tide; i++) {\r
2740         md.AddToTable(MDTable.MethodSemantics,methods[i]);\r
2741       }\r
2742       done = true;\r
2743     }\r
2744 \r
2745     internal sealed override uint Size(MetaData md) {\r
2746       return 2 + md.StringsIndexSize() + md.CodedIndexSize(CIx.TypeDefOrRef);\r
2747     }\r
2748 \r
2749     internal sealed override void Write(FileImage output) {\r
2750       output.Write(flags);\r
2751       output.StringsIndex(nameIx);\r
2752       output.WriteCodedIndex(CIx.TypeDefOrRef,eventType);\r
2753     }\r
2754 \r
2755     internal sealed override uint GetCodedIx(CIx code) {\r
2756       switch (code) {\r
2757         case (CIx.HasCustomAttr) : return 10; \r
2758         case (CIx.HasSemantics) : return 0; \r
2759       }\r
2760       return 0;\r
2761     }\r
2762    \r
2763         }\r
2764   /**************************************************************************/  \r
2765         /// <summary>\r
2766         /// Descriptor for a class defined in another module of THIS assembly \r
2767         /// and exported (.class extern)\r
2768         /// </summary>\r
2769 \r
2770   internal class ExternClass : Class\r
2771         {\r
2772                 MetaDataElement parent;\r
2773     uint flags;\r
2774 \r
2775     internal ExternClass(TypeAttr attr, uint nsIx, uint nIx, \r
2776                          MetaDataElement paren) : base(nsIx,nIx) {\r
2777       flags = (uint)attr;\r
2778             parent = paren;\r
2779                         tabIx = MDTable.ExportedType;\r
2780     }\r
2781 \r
2782     internal sealed override uint Size(MetaData md) {\r
2783       return 8 + 2* md.StringsIndexSize() + md.CodedIndexSize(CIx.Implementation);\r
2784     }\r
2785 \r
2786     internal sealed override void Write(FileImage output) {\r
2787       output.Write(flags);\r
2788       output.Write(0);\r
2789       output.StringsIndex(nameIx);\r
2790       output.StringsIndex(nameSpaceIx);\r
2791       output.WriteCodedIndex(CIx.Implementation,parent);\r
2792     }\r
2793 \r
2794     internal sealed override uint GetCodedIx(CIx code) {\r
2795       switch (code) {\r
2796         case (CIx.HasCustomAttr) : return 17; \r
2797         case (CIx.Implementation) : return 2; \r
2798       }\r
2799       return 0;\r
2800     }\r
2801 \r
2802         }\r
2803   /**************************************************************************/  \r
2804         /// <summary>\r
2805         /// Base class for Event and Property descriptors\r
2806         /// </summary>\r
2807 \r
2808   public class Feature : MetaDataElement\r
2809         {\r
2810     internal enum MethodType : ushort { Setter = 0x01, Getter, Other = 0x04, AddOn = 0x08, \r
2811       RemoveOn = 0x10, Fire = 0x20 }\r
2812 \r
2813     private static readonly int INITSIZE = 5;\r
2814     private static readonly ushort specialName = 0x200;\r
2815     private static readonly ushort rtSpecialName = 0x400;\r
2816 \r
2817     protected ClassDef parent;\r
2818     protected ushort flags = 0;\r
2819     protected string name;\r
2820     protected int tide = 0;\r
2821     protected uint nameIx;\r
2822     protected MethodSemantics[] methods = new MethodSemantics[INITSIZE];\r
2823     \r
2824     internal Feature(string name, ClassDef par) {\r
2825       parent = par;\r
2826       this.name = name;\r
2827     }\r
2828 \r
2829     internal void AddMethod(MethodDef meth, MethodType mType) {\r
2830       if (tide >= methods.Length) { \r
2831         int len = methods.Length;\r
2832         MethodSemantics[] mTmp = methods;\r
2833         methods = new MethodSemantics[len * 2];\r
2834         for (int i=0; i < len; i++) {\r
2835           methods[i] = mTmp[i];\r
2836         }\r
2837       }\r
2838       methods[tide++] = new MethodSemantics(mType,meth,this);\r
2839     }\r
2840 \r
2841     /// <summary>\r
2842     /// Set the specialName attribute for this Event or Property\r
2843     /// </summary>\r
2844     public void SetSpecialName() {\r
2845       flags |= specialName;\r
2846     }\r
2847 \r
2848     /// <summary>\r
2849     /// Set the RTSpecialName attribute for this Event or Property\r
2850     /// </summary>\r
2851     public void SetRTSpecialName() {\r
2852       flags |= rtSpecialName;\r
2853     }\r
2854   \r
2855         }\r
2856   /*****************************************************************************/  \r
2857         /// <summary>\r
2858         /// Descriptor for a field of a class\r
2859         /// </summary>\r
2860 \r
2861   public abstract class Field : Member\r
2862         {\r
2863     protected static readonly byte FieldSig = 0x6;\r
2864 \r
2865     protected Type type;\r
2866 \r
2867                 internal Field(string pfName, Type pfType) : base(pfName)\r
2868                 {\r
2869       type = pfType;\r
2870                 }\r
2871 \r
2872         }\r
2873   /**************************************************************************/  \r
2874         /// <summary>\r
2875         /// Descriptor for a field defined in a class of THIS assembly/module\r
2876         /// </summary>\r
2877   public class FieldDef : Field\r
2878         {\r
2879     //private static readonly uint PInvokeImpl = 0x2000;\r
2880     private static readonly ushort HasFieldMarshal = 0x1000;\r
2881     private static readonly ushort HasFieldRVA = 0x100;\r
2882 \r
2883     FieldRVA rva;\r
2884     ConstantElem constVal;\r
2885     FieldLayout layout;\r
2886     FieldMarshal marshalInfo;\r
2887     ushort flags;\r
2888 \r
2889     internal FieldDef(string name, Type fType) : base(name,fType) {\r
2890       tabIx = MDTable.Field;\r
2891     }\r
2892 \r
2893     internal FieldDef(FieldAttr attrSet, string name, Type fType) : base(name, fType) { \r
2894       flags = (ushort)attrSet;\r
2895       tabIx = MDTable.Field;\r
2896     }\r
2897 \r
2898     /// <summary>\r
2899     /// Add an attribute(s) to this field\r
2900     /// </summary>\r
2901     /// <param name="fa">the attribute(s) to be added</param>\r
2902     public void AddFieldAttr(FieldAttr fa) {\r
2903       flags |= (ushort)fa;\r
2904     }\r
2905  \r
2906     /// <summary>\r
2907     /// Add a value for this field\r
2908     /// </summary>\r
2909     /// <param name="val">the value for the field</param>\r
2910     public void AddValue(Constant val) {\r
2911       constVal = new ConstantElem(this,val);\r
2912     }\r
2913 \r
2914     /// <summary>\r
2915     /// Add an initial value for this field (at dataLabel) (.data)\r
2916     /// </summary>\r
2917     /// <param name="val">the value for the field</param>\r
2918     /// <param name="repeatVal">the number of repetitions of this value</param>\r
2919     public void AddDataValue(DataConstant val) {\r
2920       flags |= HasFieldRVA;\r
2921       rva = new FieldRVA(this,val);\r
2922     }\r
2923 \r
2924     /// <summary>\r
2925     /// Set the offset of the field.  Used for sequential or explicit classes.\r
2926     /// (.field [offs])\r
2927     /// </summary>\r
2928     /// <param name="offs">field offset</param>\r
2929     public void SetOffset(uint offs) {\r
2930       layout = new FieldLayout(this,offs);\r
2931     }\r
2932 \r
2933     /// <summary>\r
2934     /// Set the marshalling info for a field\r
2935     /// </summary>\r
2936     /// <param name="mInf"></param>\r
2937     public void SetMarshalInfo(NativeType marshallType) {\r
2938       flags |= HasFieldMarshal;\r
2939       marshalInfo = new FieldMarshal(this,marshallType);\r
2940     }\r
2941 \r
2942     internal sealed override void BuildTables(MetaData md) {\r
2943       if (done) return;\r
2944       nameIx = md.AddToStringsHeap(name);\r
2945       MemoryStream sig = new MemoryStream();\r
2946       sig.WriteByte(FieldSig);\r
2947       type.TypeSig(sig);\r
2948       sigIx = md.AddToBlobHeap(sig.ToArray());\r
2949       if (rva != null) {\r
2950         md.AddToTable(MDTable.FieldRVA,rva);\r
2951         rva.BuildTables(md);\r
2952       } else if (constVal != null) {\r
2953         md.AddToTable(MDTable.Constant,constVal);\r
2954         constVal.BuildTables(md);\r
2955       }\r
2956       if (layout != null) md.AddToTable(MDTable.FieldLayout,layout);\r
2957       if (marshalInfo != null) {\r
2958         md.AddToTable(MDTable.FieldMarshal,marshalInfo);\r
2959         marshalInfo.BuildTables(md);\r
2960       }\r
2961       done = true;\r
2962     }\r
2963 \r
2964     internal sealed override uint Size(MetaData md) {\r
2965       return 2 + md.StringsIndexSize() + md.BlobIndexSize();\r
2966     }\r
2967 \r
2968     internal sealed override void Write(FileImage output) {\r
2969       output.Write(flags);\r
2970       output.StringsIndex(nameIx);\r
2971       output.BlobIndex(sigIx);\r
2972     }\r
2973 \r
2974     internal sealed override uint GetCodedIx(CIx code) {\r
2975       switch (code) {\r
2976         case (CIx.HasConst) : return 0; \r
2977         case (CIx.HasCustomAttr) : return 1; \r
2978         case (CIx.HasFieldMarshal) : return 0; \r
2979         case (CIx.MemberForwarded) : return 0; \r
2980       }\r
2981       return 0;\r
2982     }\r
2983 \r
2984         }\r
2985   /**************************************************************************/  \r
2986         /// <summary>\r
2987         /// Descriptor for layout information for a field\r
2988         /// </summary>\r
2989         \r
2990         public class FieldLayout : MetaDataElement\r
2991         {\r
2992     Field field;\r
2993     uint offset;\r
2994 \r
2995     internal FieldLayout(Field field, uint offset)      {\r
2996       this.field = field;\r
2997       this.offset = offset;\r
2998                         tabIx = MDTable.FieldLayout;\r
2999     }\r
3000 \r
3001     internal sealed override uint Size(MetaData md) {\r
3002       return 4 + md.TableIndexSize(MDTable.Field);\r
3003     }\r
3004 \r
3005     internal sealed override void Write(FileImage output) {\r
3006       output.Write(offset);\r
3007       output.WriteIndex(MDTable.Field,field.Row);\r
3008     }\r
3009 \r
3010         }\r
3011   /*****************************************************************************/  \r
3012         /// <summary>\r
3013         /// Marshalling information for a field or param\r
3014         /// </summary>\r
3015   public class FieldMarshal : MetaDataElement\r
3016         {\r
3017     MetaDataElement field;\r
3018     NativeType nt;\r
3019     uint ntIx;\r
3020 \r
3021     internal FieldMarshal(MetaDataElement field, NativeType nType)      {\r
3022       this.field = field;\r
3023       this.nt = nType;\r
3024                         tabIx = MDTable.FieldMarshal;\r
3025                 }\r
3026 \r
3027     internal sealed override void BuildTables(MetaData md) {\r
3028       if (done) return;\r
3029       ntIx = md.AddToBlobHeap(nt.ToBlob());\r
3030       done = true;\r
3031     }\r
3032 \r
3033     internal sealed override uint Size(MetaData md) {\r
3034       return md.CodedIndexSize(CIx.HasFieldMarshal) + md.BlobIndexSize();\r
3035     }\r
3036 \r
3037     internal sealed override void Write(FileImage output) {\r
3038       output.WriteCodedIndex(CIx.HasFieldMarshal,field);\r
3039       output.BlobIndex(ntIx);\r
3040     }\r
3041 \r
3042         }\r
3043   /**************************************************************************/  \r
3044         /// <summary>\r
3045         /// Descriptor for a field of a class defined in another assembly/module\r
3046         /// </summary>\r
3047   public class FieldRef : Field\r
3048         {\r
3049     MetaDataElement parent;\r
3050 \r
3051                 internal FieldRef(MetaDataElement paren, string name, Type fType) : base(name, fType)   {       \r
3052       parent = paren;\r
3053     }\r
3054 \r
3055     internal sealed override void BuildTables(MetaData md) {\r
3056       if (done) return;\r
3057       nameIx = md.AddToStringsHeap(name);\r
3058       MemoryStream sig = new MemoryStream();\r
3059       sig.WriteByte(FieldSig);\r
3060       type.TypeSig(sig);\r
3061       sigIx = md.AddToBlobHeap(sig.ToArray());\r
3062       done = true;\r
3063     }\r
3064 \r
3065     internal sealed override uint Size(MetaData md) {\r
3066       return md.CodedIndexSize(CIx.MemberRefParent) + md.StringsIndexSize() + md.BlobIndexSize();\r
3067     }\r
3068 \r
3069     internal sealed override void Write(FileImage output) {\r
3070       output.WriteCodedIndex(CIx.MemberRefParent,parent);\r
3071       output.StringsIndex(nameIx);\r
3072       output.BlobIndex(sigIx);\r
3073     }\r
3074 \r
3075     internal sealed override uint GetCodedIx(CIx code) { return 6; }\r
3076 \r
3077         }\r
3078   /**************************************************************************/  \r
3079         /// <summary>\r
3080         /// Descriptor for the address of a field's value in the PE file\r
3081         /// </summary>\r
3082   public class FieldRVA : MetaDataElement\r
3083         {\r
3084     Field field;\r
3085     DataConstant data;\r
3086 \r
3087     internal FieldRVA(Field field, DataConstant data)   {\r
3088       this.field = field;\r
3089       this.data = data;\r
3090       tabIx = MDTable.FieldRVA;\r
3091                 }\r
3092 \r
3093     internal sealed override void BuildTables(MetaData md) {\r
3094       if (done) return;\r
3095       md.AddData(data);\r
3096       done = true;\r
3097     }\r
3098 \r
3099     internal sealed override uint Size(MetaData md) {\r
3100       return 4 + md.TableIndexSize(MDTable.Field);\r
3101     }\r
3102 \r
3103     internal sealed override void Write(FileImage output) {\r
3104       output.WriteDataRVA(data.DataOffset);\r
3105       output.WriteIndex(MDTable.Field,field.Row);\r
3106     }\r
3107 \r
3108         }\r
3109   /**************************************************************************/  \r
3110         /// <summary>\r
3111         /// Image for a PEFile\r
3112         /// File Structure\r
3113   ///     DOS Header (128 bytes) \r
3114   ///     PE Signature ("PE\0\0") \r
3115   ///     PEFileHeader (20 bytes)\r
3116   ///     PEOptionalHeader (224 bytes) \r
3117   ///     SectionHeaders (40 bytes * NumSections)\r
3118   ///\r
3119   ///     Sections .text (always present - contains metadata)\r
3120   ///              .sdata (contains any initialised data in the file - may not be present)\r
3121   ///                     (for ilams /debug this contains the Debug table)\r
3122   ///              .reloc (always present - in pure CIL only has one fixup)\r
3123   ///               others???  c# produces .rsrc section containing a Resource Table\r
3124   ///\r
3125   /// .text layout\r
3126   ///     IAT (single entry 8 bytes for pure CIL)\r
3127   ///     CLIHeader (72 bytes)\r
3128   ///     CIL instructions for all methods (variable size)\r
3129   ///     MetaData \r
3130   ///       Root (20 bytes + UTF-8 Version String + quad align padding)\r
3131   ///       StreamHeaders (8 bytes + null terminated name string + quad align padding)\r
3132   ///       Streams \r
3133   ///         #~        (always present - holds metadata tables)\r
3134   ///         #Strings  (always present - holds identifier strings)\r
3135   ///         #US       (Userstring heap)\r
3136   ///         #Blob     (signature blobs)\r
3137   ///         #GUID     (guids for assemblies or Modules)\r
3138   ///    ImportTable (40 bytes)\r
3139   ///    ImportLookupTable(8 bytes) (same as IAT for standard CIL files)\r
3140   ///    Hint/Name Tables with entry "_CorExeMain" for .exe file and "_CorDllMain" for .dll (14 bytes)\r
3141   ///    ASCII string "mscoree.dll" referenced in ImportTable (+ padding = 16 bytes)\r
3142   ///    Entry Point  (0xFF25 followed by 4 bytes 0x400000 + RVA of .text)\r
3143   ///\r
3144   ///  #~ stream structure\r
3145   ///    Header (24 bytes)\r
3146   ///    Rows   (4 bytes * numTables)\r
3147   ///    Tables\r
3148   /// </summary>\r
3149         internal class FileImage : BinaryWriter\r
3150         {\r
3151     internal readonly static uint[] iByteMask = {0x000000FF, 0x0000FF00, 0x00FF0000, 0xFF000000};\r
3152     internal readonly static ulong[] lByteMask = {0x00000000000000FF, 0x000000000000FF00,\r
3153                                                   0x0000000000FF0000, 0x00000000FF000000,\r
3154                                                   0x000000FF00000000, 0x0000FF0000000000,\r
3155                                                   0x00FF000000000000, 0xFF00000000000000 };\r
3156     internal readonly static uint nibble0Mask = 0x0000000F;\r
3157     internal readonly static uint nibble1Mask = 0x000000F0;\r
3158 \r
3159     private static readonly byte[] DOSHeader = { 0x4d,0x5a,0x90,0x00,0x03,0x00,0x00,0x00,\r
3160                                                  0x04,0x00,0x00,0x00,0xff,0xff,0x00,0x00,\r
3161                                                  0xb8,0x00,0x00,0x00,0x00,0x00,0x00,0x00,\r
3162                                                  0x40,0x00,0x00,0x00,0x00,0x00,0x00,0x00,\r
3163                                                  0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,\r
3164                                                  0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,\r
3165                                                  0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,\r
3166                                                  0x00,0x00,0x00,0x00,0x80,0x00,0x00,0x00,\r
3167                                                  0x0e,0x1f,0xba,0x0e,0x00,0xb4,0x09,0xcd,\r
3168                                                  0x21,0xb8,0x01,0x4c,0xcd,0x21,0x54,0x68,\r
3169                                                  0x69,0x73,0x20,0x70,0x72,0x6f,0x67,0x72,\r
3170                                                  0x61,0x6d,0x20,0x63,0x61,0x6e,0x6e,0x6f,\r
3171                                                  0x74,0x20,0x62,0x65,0x20,0x72,0x75,0x6e,\r
3172                                                  0x20,0x69,0x6e,0x20,0x44,0x4f,0x53,0x20,\r
3173                                                  0x6d,0x6f,0x64,0x65,0x2e,0x0d,0x0d,0x0a,\r
3174                                                  0x24,0x00,0x00,0x00,0x00,0x00,0x00,0x00,\r
3175                                                  0x50,0x45,0x00,0x00};\r
3176     private static byte[] PEHeader = { 0x4c, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \r
3177                                        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\r
3178                                        0xE0, 0x00, 0x0E, 0x01, // PE Header Standard Fields\r
3179                                        0x0B, 0x01, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, \r
3180                                        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \r
3181                                        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00\r
3182                                      };\r
3183 \r
3184     private static readonly uint minFileAlign = 0x200;\r
3185     private static readonly uint maxFileAlign = 0x1000;\r
3186     private static readonly uint fileHeaderSize = 0x178;\r
3187     private static readonly uint sectionHeaderSize = 40;\r
3188     private static readonly uint SectionAlignment = 0x2000;\r
3189     private static readonly uint ImageBase = 0x400000;\r
3190     private static readonly uint ImportTableSize = 40;\r
3191     private static readonly uint IATSize = 8;\r
3192     private static readonly uint CLIHeaderSize = 72;\r
3193     private uint runtimeFlags = 0x01;  // COMIMAGE_FLAGS_ILONLY\r
3194     // 32BITREQUIRED 0x02, STRONGNAMESIGNED 0x08, TRACKDEBUGDATA 0x10000\r
3195                 private static readonly uint relocFlags = 0x42000040;\r
3196                 private static readonly ushort exeCharacteristics = 0x010E;\r
3197                 private static readonly ushort dllCharacteristics = 0x210E;\r
3198     // section names are all 8 bytes\r
3199     private static readonly string textName = ".text\0\0\0";\r
3200     private static readonly string sdataName = ".sdata\0\0";\r
3201     private static readonly string relocName = ".reloc\0\0";\r
3202     private static readonly string rsrcName = ".rsrc\0\0\0";\r
3203     private static readonly string exeHintNameTable = "\0\0_CorExeMain\0";\r
3204     private static readonly string dllHintNameTable = "\0\0_CorDllMain\0";\r
3205     private static readonly string runtimeEngineName = "mscoree.dll\0\0";\r
3206 \r
3207                 private Section text, sdata, rsrc;\r
3208                 ArrayList data;\r
3209     BinaryWriter reloc = new BinaryWriter(new MemoryStream());\r
3210     uint dateStamp = 0;\r
3211     DateTime origin = new DateTime(1970,1,1);\r
3212     uint numSections = 2; // always have .text  and .reloc sections\r
3213     internal SubSystem subSys = SubSystem.Windows_CUI;  // default is Windows Console mode\r
3214     internal uint fileAlign = minFileAlign;\r
3215     uint entryPointOffset, entryPointPadding, imageSize, headerSize, headerPadding, entryPointToken = 0;\r
3216     uint relocOffset, relocRVA, relocSize, relocPadding, relocTide, hintNameTableOffset;\r
3217     uint metaDataOffset, runtimeEngineOffset, initDataSize = 0, importTablePadding;\r
3218     uint importTableOffset, importLookupTableOffset, totalImportTableSize;\r
3219     MetaData metaData;\r
3220     char[] runtimeEngine = runtimeEngineName.ToCharArray(), hintNameTable;\r
3221                 bool doDLL, largeStrings, largeGUID, largeUS, largeBlob;\r
3222                 ushort characteristics;\r
3223 \r
3224     internal FileImage(bool makeDLL, string fileName) : base(new FileStream(fileName,FileMode.Create)) {\r
3225       InitFileImage(makeDLL);\r
3226       TimeSpan tmp = System.IO.File.GetCreationTime(fileName).Subtract(origin);\r
3227       dateStamp = Convert.ToUInt32(tmp.TotalSeconds);\r
3228     }\r
3229 \r
3230     internal FileImage(bool makeDLL, Stream str) : base(str) {\r
3231       InitFileImage(makeDLL);\r
3232       TimeSpan tmp = DateTime.Now.Subtract(origin);\r
3233       dateStamp = Convert.ToUInt32(tmp.TotalSeconds);\r
3234     }\r
3235 \r
3236     private void InitFileImage(bool makeDLL) {\r
3237       doDLL = makeDLL;\r
3238                         if (doDLL) {\r
3239                                 hintNameTable = dllHintNameTable.ToCharArray();\r
3240                                 characteristics = dllCharacteristics;\r
3241                         } else {\r
3242                                 hintNameTable = exeHintNameTable.ToCharArray();\r
3243                                 characteristics = exeCharacteristics;\r
3244                         }\r
3245       text = new Section(textName,0x60000020);     // IMAGE_SCN_CNT  CODE, EXECUTE, READ\r
3246 //                      rsrc = new Section(rsrcName,0x40000040);     // IMAGE_SCN_CNT  INITIALIZED_DATA, READ\r
3247       metaData = new MetaData(this);\r
3248     }\r
3249 \r
3250                 internal MetaData GetMetaData() {\r
3251                         return metaData;\r
3252                 }\r
3253 \r
3254     private uint GetNextSectStart(uint rva, uint tide) {\r
3255       if (tide < SectionAlignment) return rva + SectionAlignment;\r
3256       return rva + ((tide / SectionAlignment) + 1) * SectionAlignment;\r
3257     }\r
3258 \r
3259     private void BuildTextSection() {\r
3260       // .text layout\r
3261       //    IAT (single entry 8 bytes for pure CIL)\r
3262       //    CLIHeader (72 bytes)\r
3263       //    CIL instructions for all methods (variable size)\r
3264       //    MetaData \r
3265       //    ImportTable (40 bytes)\r
3266       //    ImportLookupTable(8 bytes) (same as IAT for standard CIL files)\r
3267       //    Hint/Name Tables with entry "_CorExeMain" for .exe file and "_CorDllMain" for .dll (14 bytes)\r
3268       //    ASCII string "mscoree.dll" referenced in ImportTable (+ padding = 16 bytes)\r
3269       //    Entry Point  (0xFF25 followed by 4 bytes 0x400000 + RVA of .text)\r
3270       metaData.BuildMetaData(IATSize + CLIHeaderSize);\r
3271       metaDataOffset = IATSize + CLIHeaderSize;\r
3272       // Console.WriteLine("Code starts at " + metaDataOffset);\r
3273       metaDataOffset += metaData.CodeSize();\r
3274       // resourcesStart =\r
3275       // strongNameSig = metaData.GetStrongNameSig();\r
3276       // fixUps = RVA for vtable\r
3277       importTableOffset = metaDataOffset + metaData.Size();\r
3278       importTablePadding = NumToAlign(importTableOffset,16);\r
3279       importTableOffset += importTablePadding;\r
3280       importLookupTableOffset = importTableOffset + ImportTableSize;\r
3281       hintNameTableOffset = importLookupTableOffset + IATSize;\r
3282       runtimeEngineOffset = hintNameTableOffset + (uint)hintNameTable.Length;\r
3283       entryPointOffset = runtimeEngineOffset + (uint)runtimeEngine.Length;\r
3284       totalImportTableSize = entryPointOffset - importTableOffset;\r
3285       // Console.WriteLine("total import table size = " + totalImportTableSize);\r
3286       // Console.WriteLine("entrypoint offset = " + entryPointOffset);\r
3287       entryPointPadding = NumToAlign(entryPointOffset,4) + 2;\r
3288       entryPointOffset += entryPointPadding;\r
3289       text.AddReloc(entryPointOffset+2);\r
3290       text.IncTide(entryPointOffset + 6);\r
3291       //if (text.Tide() < fileAlign) fileAlign = minFileAlign;\r
3292                         text.SetSize(NumToAlign(text.Tide(),fileAlign));\r
3293       // Console.WriteLine("text size = " + text.Size() + " text tide = " + text.Tide() + " text padding = " + text.Padding());\r
3294                         // Console.WriteLine("metaDataOffset = " + Hex.Int(metaDataOffset));\r
3295                         // Console.WriteLine("importTableOffset = " + Hex.Int(importTableOffset));\r
3296                         // Console.WriteLine("importLookupTableOffset = " + Hex.Int(importLookupTableOffset));\r
3297                         // Console.WriteLine("hintNameTableOffset = " + Hex.Int(hintNameTableOffset));\r
3298                         // Console.WriteLine("runtimeEngineOffset = " + Hex.Int(runtimeEngineOffset));\r
3299                         // Console.WriteLine("entryPointOffset = " + Hex.Int(entryPointOffset));\r
3300                         // Console.WriteLine("entryPointPadding = " + Hex.Int(entryPointPadding));\r
3301 \r
3302     }\r
3303 \r
3304     internal void BuildRelocSection() {\r
3305                         text.DoRelocs(reloc);\r
3306                         if (sdata != null) sdata.DoRelocs(reloc);\r
3307                         if (rsrc != null) rsrc.DoRelocs(reloc);\r
3308       relocTide = (uint)reloc.Seek(0,SeekOrigin.Current);\r
3309       relocPadding = NumToAlign(relocTide,fileAlign);\r
3310       relocSize = relocTide + relocPadding;\r
3311                         imageSize = relocRVA + SectionAlignment;\r
3312       initDataSize += relocSize;\r
3313     }\r
3314 \r
3315     private void CalcOffsets() {\r
3316 if (sdata != null)
3317         numSections++;
3318 if (rsrc != null)
3319         numSections++;
3320       headerSize = fileHeaderSize + (numSections * sectionHeaderSize);\r
3321       headerPadding = NumToAlign(headerSize,fileAlign);\r
3322       headerSize += headerPadding;\r
3323       uint offset = headerSize;\r
3324       uint rva = SectionAlignment;\r
3325       text.SetOffset(offset);\r
3326       text.SetRVA(rva);\r
3327       offset += text.Size();\r
3328       rva  = GetNextSectStart(rva,text.Tide());\r
3329                         // Console.WriteLine("headerSize = " + headerSize);\r
3330                         // Console.WriteLine("headerPadding = " + headerPadding);\r
3331                         // Console.WriteLine("textOffset = " + Hex.Int(text.Offset()));\r
3332                         if (sdata != null) { \r
3333                                 sdata.SetSize(NumToAlign(sdata.Tide(),fileAlign));\r
3334                                 sdata.SetOffset(offset);\r
3335         sdata.SetRVA(rva);\r
3336         offset += sdata.Size();
3337         rva = GetNextSectStart(rva,sdata.Tide());\r
3338                                 initDataSize += sdata.Size();\r
3339       }\r
3340       if (rsrc != null) { \r
3341                      rsrc.SetSize(NumToAlign(rsrc.Tide(),fileAlign));\r
3342                                 rsrc.SetOffset(offset);\r
3343         rsrc.SetRVA(rva);\r
3344         offset += rsrc.Size();\r
3345         rva = GetNextSectStart(rva,rsrc.Tide());\r
3346                                 initDataSize += rsrc.Size();\r
3347       }\r
3348       relocOffset = offset;\r
3349       relocRVA = rva;\r
3350     }\r
3351 \r
3352     internal void MakeFile() {\r
3353       if (doDLL) hintNameTable = dllHintNameTable.ToCharArray();\r
3354       else hintNameTable = exeHintNameTable.ToCharArray();\r
3355       BuildTextSection();\r
3356       CalcOffsets();\r
3357       BuildRelocSection();\r
3358       // now write it out\r
3359       WriteHeader();\r
3360       WriteSections();\r
3361       Flush();\r
3362       Close();\r
3363     }\r
3364 \r
3365     private void WriteHeader() {\r
3366       Write(DOSHeader);\r
3367                         // Console.WriteLine("Writing PEHeader at offset " + Seek(0,SeekOrigin.Current));\r
3368                         WritePEHeader();\r
3369                          // Console.WriteLine("Writing text section header at offset " + Hex.Long(Seek(0,SeekOrigin.Current)));\r
3370                         text.WriteHeader(this,relocRVA);\r
3371       if (sdata != null) sdata.WriteHeader(this,relocRVA);\r
3372       if (rsrc != null) rsrc.WriteHeader(this,relocRVA);\r
3373                         // Console.WriteLine("Writing reloc section header at offset " + Seek(0,SeekOrigin.Current));\r
3374                         WriteRelocSectionHeader();\r
3375                         // Console.WriteLine("Writing padding at offset " + Seek(0,SeekOrigin.Current));\r
3376                         WriteZeros(headerPadding);\r
3377     }\r
3378 \r
3379     private void WriteSections() {\r
3380                         // Console.WriteLine("Writing text section at offset " + Seek(0,SeekOrigin.Current));\r
3381       WriteTextSection();\r
3382       if (sdata != null) WriteSDataSection();\r
3383       if (rsrc != null) WriteRsrcSection();\r
3384       WriteRelocSection();\r
3385     }\r
3386 \r
3387      private void WriteIAT() {\r
3388       Write(text.RVA() + hintNameTableOffset);\r
3389       Write(0);\r
3390     }\r
3391 \r
3392                 private void WriteImportTables() {\r
3393                         // Import Table\r
3394       WriteZeros(importTablePadding);\r
3395       // Console.WriteLine("Writing import tables at offset " + Hex.Long(Seek(0,SeekOrigin.Current)));\r
3396                         Write(importLookupTableOffset + text.RVA());\r
3397                         WriteZeros(8); \r
3398                         Write(runtimeEngineOffset + text.RVA());\r
3399                         Write(text.RVA());    // IAT is at the beginning of the text section\r
3400                         WriteZeros(20);\r
3401                         // Import Lookup Table\r
3402                         WriteIAT();                // lookup table and IAT are the same\r
3403                         // Hint/Name Table\r
3404        // Console.WriteLine("Writing hintname table at " + Hex.Long(Seek(0,SeekOrigin.Current)));\r
3405                         Write(hintNameTable);\r
3406       Write(runtimeEngineName.ToCharArray());\r
3407                 }\r
3408 \r
3409     private void WriteTextSection() {\r
3410       WriteIAT();\r
3411       WriteCLIHeader();\r
3412       // Console.WriteLine("Writing code at " + Hex.Long(Seek(0,SeekOrigin.Current)));\r
3413       metaData.WriteByteCodes(this);\r
3414       // Console.WriteLine("Finished writing code at " + Hex.Long(Seek(0,SeekOrigin.Current)));\r
3415       largeStrings = metaData.LargeStringsIndex();\r
3416       largeGUID = metaData.LargeGUIDIndex();\r
3417       largeUS = metaData.LargeUSIndex();\r
3418       largeBlob = metaData.LargeBlobIndex();\r
3419       metaData.WriteMetaData(this);\r
3420       WriteImportTables();\r
3421                         WriteZeros(entryPointPadding);\r
3422                         Write((ushort)0x25FF);\r
3423                         Write(ImageBase + text.RVA());\r
3424                         WriteZeros(text.Padding());\r
3425     }\r
3426 \r
3427     private void WriteCLIHeader() {\r
3428       Write(CLIHeaderSize);       // Cb\r
3429       Write((short)2);            // Major runtime version\r
3430       Write((short)0);            // Minor runtime version\r
3431       Write(text.RVA() + metaDataOffset);\r
3432       Write(metaData.Size());\r
3433       Write(runtimeFlags);\r
3434       Write(entryPointToken);\r
3435       WriteZeros(8);                     // Resources - used by Manifest Resources NYI\r
3436       WriteZeros(8);                     // Strong Name stuff here!! NYI\r
3437       WriteZeros(8);                     // CodeManagerTable\r
3438       WriteZeros(8);                     // VTableFixups NYI\r
3439       WriteZeros(16);                    // ExportAddressTableJumps, ManagedNativeHeader\r
3440      }\r
3441 \r
3442     private void WriteSDataSection() {\r
3443       for (int i=0; i < data.Count; i++) {\r
3444         ((DataConstant)data[i]).Write(this);\r
3445       }\r
3446     }\r
3447 \r
3448                 private void WriteRsrcSection() {\r
3449                 }\r
3450 \r
3451     private void WriteRelocSection() {\r
3452      // Console.WriteLine("Writing reloc section at " + Seek(0,SeekOrigin.Current) + " = " + relocOffset);\r
3453       MemoryStream str = (MemoryStream)reloc.BaseStream;\r
3454       Write(str.ToArray());\r
3455       WriteZeros(NumToAlign((uint)str.Position,fileAlign));\r
3456     }\r
3457 \r
3458     internal void SetEntryPoint(uint entryPoint) {\r
3459       entryPointToken = entryPoint;\r
3460     }\r
3461 \r
3462     internal void AddInitData(DataConstant cVal) {\r
3463                         if (sdata == null) {                    \r
3464                                 sdata = new Section(sdataName,0xC0000040);   // IMAGE_SCN_CNT  INITIALIZED_DATA, READ, WRITE\r
3465                                 data = new ArrayList(); \r
3466                         }\r
3467       data.Add(cVal);\r
3468       cVal.DataOffset = sdata.Tide();\r
3469       sdata.IncTide(cVal.GetSize());\r
3470     }\r
3471 \r
3472     internal void WriteZeros(uint numZeros) {\r
3473       for (int i=0; i < numZeros; i++) {\r
3474         Write((byte)0);\r
3475       }\r
3476     }\r
3477 \r
3478     internal void WritePEHeader() {\r
3479       Write((ushort)0x014C);  // Machine - always 0x14C for Managed PE Files (allow others??)\r
3480       Write((ushort)numSections);\r
3481       Write(dateStamp);\r
3482       WriteZeros(8); // Pointer to Symbol Table and Number of Symbols (always zero for ECMA CLI files)\r
3483       Write((ushort)0x00E0);  // Size of Optional Header\r
3484       Write(characteristics);\r
3485       // PE Optional Header\r
3486       Write((ushort)0x010B);   // Magic\r
3487       Write((byte)0x6);        // LMajor pure-IL = 6   C++ = 7\r
3488       Write((byte)0x0);        // LMinor\r
3489       Write(text.Size());\r
3490       Write(initDataSize);\r
3491       Write(0);                // Check other sections here!!\r
3492       Write(text.RVA() + entryPointOffset);\r
3493       Write(text.RVA());\r
3494                         uint dataBase = 0;\r
3495                         if (sdata != null) dataBase = sdata.RVA();\r
3496                         else if (rsrc != null) dataBase = rsrc.RVA();\r
3497       else dataBase = relocRVA;\r
3498                         Write(dataBase);\r
3499       Write(ImageBase);\r
3500       Write(SectionAlignment);\r
3501       Write(fileAlign);\r
3502       Write((ushort)0x04);     // OS Major\r
3503       WriteZeros(6);                  // OS Minor, User Major, User Minor\r
3504       Write((ushort)0x04);     // SubSys Major\r
3505       WriteZeros(6);           // SybSys Minor, Reserved\r
3506       Write(imageSize);\r
3507       Write(headerSize);\r
3508       Write((int)0);           // File Checksum\r
3509       Write((ushort)subSys);\r
3510       Write((short)0);         // DLL Flags\r
3511       Write((uint)0x100000);   // Stack Reserve Size\r
3512       Write((uint)0x1000);     // Stack Commit Size\r
3513       Write((uint)0x100000);   // Heap Reserve Size\r
3514       Write((uint)0x1000);     // Heap Commit Size\r
3515       Write(0);                // Loader Flags\r
3516       Write(0x10);             // Number of Data Directories\r
3517       WriteZeros(8);                  // Export Table\r
3518       Write(importTableOffset + text.RVA());\r
3519       Write(totalImportTableSize);\r
3520       WriteZeros(24);            // Resource, Exception and Certificate Tables\r
3521       Write(relocRVA);\r
3522       Write(relocTide);\r
3523       WriteZeros(48);            // Debug, Copyright, Global Ptr, TLS, Load Config and Bound Import Tables\r
3524       Write(text.RVA());         // IATRVA - IAT is at start of .text Section\r
3525       Write(IATSize);\r
3526       WriteZeros(8);             // Delay Import Descriptor\r
3527       Write(text.RVA()+IATSize); // CLIHeader immediately follows IAT\r
3528       Write(CLIHeaderSize);    \r
3529       WriteZeros(8);             // Reserved\r
3530     }\r
3531 \r
3532     internal void WriteRelocSectionHeader() {\r
3533       Write(relocName.ToCharArray());\r
3534       Write(relocTide);\r
3535       Write(relocRVA);\r
3536       Write(relocSize);\r
3537       Write(relocOffset);\r
3538       WriteZeros(12);\r
3539       Write(relocFlags);\r
3540     }\r
3541 \r
3542     private void Align (MemoryStream str, int val) {\r
3543       if ((str.Position % val) != 0) {\r
3544         for (int i=val - (int)(str.Position % val); i > 0; i--) {\r
3545           str.WriteByte(0);\r
3546         }\r
3547       }\r
3548     }\r
3549 \r
3550     private uint Align(uint val, uint alignVal) {\r
3551       if ((val % alignVal) != 0) {\r
3552         val += alignVal - (val % alignVal);\r
3553       }\r
3554       return val;\r
3555     }\r
3556 \r
3557     private uint NumToAlign(uint val, uint alignVal) {\r
3558       if ((val % alignVal) == 0) return 0;\r
3559       return alignVal - (val % alignVal);\r
3560     }\r
3561 \r
3562     internal void StringsIndex(uint ix) {\r
3563       if (largeStrings) Write(ix);\r
3564       else Write((ushort)ix);\r
3565     }\r
3566 \r
3567     internal void GUIDIndex(uint ix) {\r
3568       if (largeGUID) Write(ix);\r
3569       else Write((ushort)ix);\r
3570     }\r
3571 \r
3572     internal void USIndex(uint ix) {\r
3573       if (largeUS) Write(ix);\r
3574       else Write((ushort)ix);\r
3575     }\r
3576 \r
3577     internal void BlobIndex(uint ix) {\r
3578       if (largeBlob) Write(ix);\r
3579       else Write((ushort)ix);\r
3580     }\r
3581 \r
3582     internal void WriteIndex(MDTable tabIx,uint ix) {\r
3583       if (metaData.LargeIx(tabIx)) Write(ix);\r
3584       else Write((ushort)ix);\r
3585     }\r
3586 \r
3587     internal void WriteCodedIndex(CIx code, MetaDataElement elem) {\r
3588       metaData.WriteCodedIndex(code,elem,this);\r
3589     }\r
3590     \r
3591     internal void WriteCodeRVA(uint offs) {\r
3592       Write(text.RVA() + offs);\r
3593     }\r
3594 \r
3595     internal void WriteDataRVA(uint offs) {\r
3596       Write(sdata.RVA() + offs);\r
3597     }\r
3598 \r
3599     internal void Write3Bytes(uint val) {\r
3600       byte b3 = (byte)((val & FileImage.iByteMask[2]) >> 16);\r
3601       byte b2 = (byte)((val & FileImage.iByteMask[1]) >> 8);;\r
3602       byte b1 = (byte)(val & FileImage.iByteMask[0]);\r
3603       Write(b1);\r
3604       Write(b2);\r
3605       Write(b3);\r
3606     }\r
3607 \r
3608         }\r
3609   /**************************************************************************/  \r
3610         /// <summary>\r
3611         /// Descriptor for a file referenced in THIS assembly/module (.file)\r
3612         /// </summary>\r
3613         public class FileRef : MetaDataElement\r
3614         {\r
3615     private static readonly uint HasMetaData = 0x1;\r
3616     uint nameIx = 0, hashIx = 0;\r
3617     uint flags = 0;\r
3618 \r
3619     internal FileRef(string name, byte[] hashBytes, bool metaData,\r
3620                       bool entryPoint, MetaData md) {\r
3621       if (metaData) flags = HasMetaData;\r
3622       if (entryPoint) md.SetEntryPoint(this);\r
3623       nameIx = md.AddToStringsHeap(name);\r
3624       hashIx = md.AddToBlobHeap(hashBytes);\r
3625       tabIx = MDTable.File;\r
3626                 }\r
3627 \r
3628     internal FileRef(uint nameIx, byte[] hashBytes, bool metaData,\r
3629                       bool entryPoint, MetaData md) {\r
3630       if (metaData) flags = HasMetaData;\r
3631       if (entryPoint) md.SetEntryPoint(this);\r
3632       this.nameIx = nameIx;\r
3633       hashIx = md.AddToBlobHeap(hashBytes);\r
3634       tabIx = MDTable.File;\r
3635     }\r
3636 \r
3637     internal sealed override uint Size(MetaData md) {\r
3638       return 4 + md.StringsIndexSize() + md.BlobIndexSize();\r
3639     }\r
3640 \r
3641     internal sealed override void Write(FileImage output) {\r
3642       output.Write(flags);\r
3643       output.StringsIndex(nameIx);\r
3644       output.BlobIndex(hashIx);\r
3645     }\r
3646 \r
3647     internal sealed override uint GetCodedIx(CIx code) {\r
3648       switch (code) {\r
3649         case (CIx.HasCustomAttr) : return 16; \r
3650         case (CIx.Implementation) : return 0;\r
3651       }\r
3652       return 0;\r
3653     }\r
3654 \r
3655         }\r
3656   /**************************************************************************/  \r
3657         /// <summary>\r
3658         /// Descriptor for pinvoke information for a method NOT YET IMPLEMENTED\r
3659         /// </summary>\r
3660         public class ImplMap : MetaDataElement\r
3661         {\r
3662     private static readonly ushort NoMangle = 0x01;\r
3663     ushort flags;\r
3664     Method meth;\r
3665     string importName;\r
3666     uint iNameIx;\r
3667     ModuleRef importScope;\r
3668 \r
3669                 internal ImplMap(ushort flag, Method implMeth, string iName, ModuleRef mScope) {\r
3670       flags = flag;\r
3671       meth = implMeth;\r
3672       importName = iName;\r
3673       importScope = mScope;\r
3674       tabIx = MDTable.ImplMap;\r
3675       if (iName == null) flags |= NoMangle;\r
3676       //throw(new NotYetImplementedException("PInvoke "));\r
3677                 }\r
3678 \r
3679     internal sealed override void BuildTables(MetaData md) {\r
3680       if (done) return;\r
3681       iNameIx = md.AddToStringsHeap(importName);\r
3682       done = true;\r
3683     }\r
3684 \r
3685     internal sealed override uint Size(MetaData md) {\r
3686       return 2+ md.CodedIndexSize(CIx.MemberForwarded) + \r
3687         md.StringsIndexSize() +  md.TableIndexSize(MDTable.ModuleRef);\r
3688     }\r
3689 \r
3690     internal sealed override void Write(FileImage output) {\r
3691       output.Write(flags);\r
3692       output.WriteCodedIndex(CIx.MemberForwarded,meth);\r
3693       output.StringsIndex(iNameIx);\r
3694       output.WriteIndex(MDTable.ModuleRef,importScope.Row);\r
3695     }\r
3696 \r
3697         }\r
3698 \r
3699   /**************************************************************************/  \r
3700   /// <summary>\r
3701   /// Descriptor for an IL instruction\r
3702   /// </summary>\r
3703   internal abstract class CILInstruction {\r
3704     protected static readonly sbyte maxByteVal = 127;\r
3705     protected static readonly sbyte minByteVal = -128;\r
3706     protected static readonly byte leadByte = 0xFE;\r
3707                 protected static readonly uint USHeapIndex = 0x70000000;\r
3708     protected static readonly int longInstrStart = (int)Op.arglist;\r
3709     public bool twoByteInstr = false;\r
3710     public uint size = 0;\r
3711     public uint offset;\r
3712 \r
3713     internal virtual bool Check(MetaData md) {\r
3714       return false;\r
3715     }\r
3716 \r
3717                 internal virtual void Write(FileImage output) { }\r
3718 \r
3719   }\r
3720 \r
3721   internal class CILByte : CILInstruction {\r
3722     byte byteVal;\r
3723 \r
3724     internal CILByte(byte bVal) {\r
3725       byteVal = bVal;\r
3726       size = 1;\r
3727     }\r
3728 \r
3729     internal override void Write(FileImage output) {\r
3730       output.Write(byteVal);\r
3731     }\r
3732 \r
3733   }\r
3734 \r
3735   \r
3736   internal class Instr : CILInstruction {\r
3737     protected int instr;\r
3738 \r
3739     internal Instr(int inst) {\r
3740       if (inst >= longInstrStart) {\r
3741         instr = inst - longInstrStart;\r
3742         twoByteInstr = true;\r
3743         size = 2;\r
3744       } else {\r
3745         instr = inst;\r
3746         size = 1;\r
3747       }\r
3748     }\r
3749 \r
3750                 internal override void Write(FileImage output) {\r
3751       //Console.WriteLine("Writing instruction " + instr + " with size " + size);\r
3752       if (twoByteInstr) output.Write(leadByte);\r
3753       output.Write((byte)instr);\r
3754                 }\r
3755 \r
3756   }\r
3757 \r
3758   internal class IntInstr : Instr {\r
3759     int val;\r
3760     bool byteNum;\r
3761 \r
3762     internal IntInstr(int inst, int num, bool byteSize) : base(inst) {\r
3763       val = num;\r
3764       byteNum = byteSize;\r
3765       if (byteNum) size++;\r
3766       else size += 4;\r
3767     }\r
3768 \r
3769                 internal sealed override void Write(FileImage output) {\r
3770                         base.Write(output);\r
3771       if (byteNum) \r
3772         output.Write((sbyte)val);\r
3773       else \r
3774                                 output.Write(val); \r
3775                 }\r
3776 \r
3777   }\r
3778 \r
3779   internal class UIntInstr : Instr {\r
3780     int val;\r
3781     bool byteNum;\r
3782 \r
3783                 internal UIntInstr(int inst, int num, bool byteSize) : base(inst) {\r
3784                         val = num;\r
3785       byteNum = byteSize;\r
3786       if (byteNum) size++;\r
3787       else size += 2;\r
3788                 }\r
3789 \r
3790                 internal sealed override void Write(FileImage output) {\r
3791                         base.Write(output);\r
3792       if (byteNum)\r
3793                           output.Write((byte)val);\r
3794       else\r
3795                                 output.Write((ushort)val); \r
3796                 }\r
3797         \r
3798   }\r
3799 \r
3800         internal class LongInstr : Instr {\r
3801                 long val;\r
3802 \r
3803                 internal LongInstr(int inst, long l) : base(inst) {\r
3804                         val = l;\r
3805                         size += 8;\r
3806                 }\r
3807 \r
3808                 internal sealed override void Write(FileImage output) {\r
3809                         base.Write(output);\r
3810                         output.Write(val);\r
3811                 }\r
3812 \r
3813         }\r
3814 \r
3815   internal class FloatInstr : Instr {\r
3816     float fVal;\r
3817 \r
3818     internal FloatInstr(int inst, float f) : base(inst) {\r
3819       fVal = f;\r
3820       size += 4;\r
3821     }\r
3822 \r
3823                 internal sealed override void Write(FileImage output) {\r
3824                         base.Write(output);\r
3825                         output.Write(fVal);\r
3826                 }\r
3827 \r
3828         }\r
3829 \r
3830   internal class DoubleInstr : Instr {\r
3831     double val;\r
3832 \r
3833     internal DoubleInstr(int inst, double d) : base(inst) {\r
3834       val = d;\r
3835       size += 8;\r
3836     }\r
3837 \r
3838                 internal sealed override void Write(FileImage output) {\r
3839                         base.Write(output);\r
3840                         output.Write(val);\r
3841                 }\r
3842 \r
3843         }\r
3844 \r
3845   internal class StringInstr : Instr {\r
3846     string val;\r
3847     uint strIndex;\r
3848 \r
3849     internal StringInstr(int inst, string str) : base(inst) {\r
3850       val = str;  \r
3851       size += 4;\r
3852     }\r
3853 \r
3854     internal sealed override bool Check(MetaData md) {\r
3855       strIndex = md.AddToUSHeap(val);\r
3856       return false;\r
3857     }\r
3858 \r
3859                 internal sealed override void Write(FileImage output) {\r
3860                         base.Write(output);\r
3861                         output.Write(USHeapIndex  | strIndex);\r
3862                 }\r
3863 \r
3864         }\r
3865 \r
3866   internal class LabelInstr : CILInstruction {\r
3867     CILLabel label;\r
3868 \r
3869     internal LabelInstr(CILLabel lab) {\r
3870       label = lab;\r
3871       label.AddLabelInstr(this);\r
3872     }\r
3873   }\r
3874 \r
3875   internal class FieldInstr : Instr {\r
3876     Field field;\r
3877 \r
3878     internal FieldInstr(int inst, Field f) : base(inst) {\r
3879       field = f;\r
3880       size += 4;\r
3881     }\r
3882 \r
3883                 internal sealed override void Write(FileImage output) {\r
3884                         base.Write(output);\r
3885                         output.Write(field.Token());\r
3886                 }\r
3887 \r
3888         }\r
3889 \r
3890   internal class MethInstr : Instr {\r
3891     Method meth;\r
3892 \r
3893     internal MethInstr(int inst, Method m) : base(inst) {\r
3894       meth = m;\r
3895       size += 4;\r
3896     }\r
3897 \r
3898                 internal sealed override void Write(FileImage output) {\r
3899                         base.Write(output);\r
3900                         output.Write(meth.Token());\r
3901                 }\r
3902 \r
3903   }\r
3904 \r
3905   internal class SigInstr : Instr {\r
3906     CalliSig signature;\r
3907 \r
3908     internal SigInstr(int inst, CalliSig sig) : base(inst) {\r
3909       signature = sig;\r
3910       size += 4;\r
3911     }\r
3912 \r
3913     internal sealed override bool Check(MetaData md) {\r
3914       md.AddToTable(MDTable.StandAloneSig,signature);\r
3915       signature.BuildTables(md);\r
3916       return false;\r
3917     }\r
3918 \r
3919                 internal sealed override void Write(FileImage output) {\r
3920                         base.Write(output);\r
3921                         output.Write(signature.Token());\r
3922                 }\r
3923   }\r
3924 \r
3925   internal class TypeInstr : Instr {\r
3926     MetaDataElement theType;\r
3927 \r
3928     internal TypeInstr(int inst, Type aType, MetaData md) : base(inst) {\r
3929       theType = aType.GetTypeSpec(md);\r
3930       size += 4;\r
3931     }\r
3932 \r
3933     internal sealed override void Write(FileImage output) {\r
3934       base.Write(output);\r
3935       output.Write(theType.Token());\r
3936                 }\r
3937 \r
3938   }\r
3939 \r
3940   internal class BranchInstr : Instr {\r
3941     CILLabel dest;\r
3942     private bool shortVer = true;\r
3943     private static readonly byte longInstrOffset = 13;\r
3944     private int target = 0;\r
3945 \r
3946     internal BranchInstr(int inst, CILLabel dst) : base(inst) {\r
3947       dest = dst;\r
3948       dest.AddBranch(this);\r
3949       size++;\r
3950
3951       if (inst >= (int) BranchOp.br && inst != (int) BranchOp.leave_s) {
3952               shortVer = false;
3953               size += 3;
3954       }
3955     }\r
3956 \r
3957     internal sealed override bool Check(MetaData md) {\r
3958       target = (int)dest.GetLabelOffset() - (int)(offset + size);\r
3959       return false;
3960     }\r
3961
3962                 internal sealed override void Write(FileImage output) {\r
3963                         base.Write(output);\r
3964                         if (shortVer)\r
3965                                 output.Write((sbyte)target);\r
3966                         else\r
3967                                 output.Write(target);\r
3968                 }\r
3969 \r
3970   }\r
3971 \r
3972   internal class SwitchInstr : Instr {\r
3973     CILLabel[] cases;\r
3974                 uint numCases = 0;\r
3975 \r
3976     internal SwitchInstr(int inst, CILLabel[] dsts) : base(inst) {\r
3977       cases = dsts;\r
3978                         if (cases != null) numCases = (uint)cases.Length;\r
3979       size += 4 + (numCases * 4);\r
3980       for (int i=0; i < numCases; i++) {\r
3981         cases[i].AddBranch(this);\r
3982       }\r
3983     }\r
3984 \r
3985                 internal sealed override void Write(FileImage output) {\r
3986                         base.Write(output);\r
3987                         output.Write(numCases);\r
3988                         for (int i=0; i < numCases; i++) {\r
3989                                 int target = (int)cases[i].GetLabelOffset() - (int)(offset + size);\r
3990                                 output.Write(target);\r
3991                         }\r
3992                 }\r
3993 \r
3994   }\r
3995   /**************************************************************************/  \r
3996 \r
3997         public class GenericParameter : MetaDataElement\r
3998         {\r
3999                 MetaDataElement owner;
4000                 MetaData metadata;
4001                 string name;\r
4002                 uint nameIx;\r
4003                 short index;\r
4004 \r
4005                 internal GenericParameter (ClassDef owner, MetaData metadata,
4006                                 short index, string name) : this (owner, metadata, index, name, true)
4007                 {
4008                 }
4009 \r
4010                 internal GenericParameter (MethodDef owner, MetaData metadata,
4011                                 short index, string name) : this (owner, metadata, index, name, true)
4012                 {
4013                 }
4014
4015                 private GenericParameter (MetaDataElement owner, MetaData metadata,
4016                                 short index, string name, bool nadda)
4017                 {
4018                         this.owner = owner;\r
4019                         this.metadata = metadata;
4020                         this.index = index;\r
4021                         tabIx = MDTable.GenericParam;\r
4022                         this.name = name;\r
4023                 }
4024
4025                 public void AddConstraint  (Type constraint) {
4026                         metadata.AddToTable (MDTable.GenericParamConstraint,\r
4027                                         new GenericParamConstraint (this, constraint));\r
4028                 }
4029
4030                 internal sealed override uint Size(MetaData md) {\r
4031                         return (uint) (4 +\r
4032                                md.CodedIndexSize(CIx.TypeOrMethodDef) + \r
4033                                4 +\r
4034                                md.TableIndexSize(MDTable.TypeDef));\r
4035                 }\r
4036 \r
4037                 internal sealed override void BuildTables(MetaData md) {\r
4038                         if (done) return;\r
4039                         nameIx = md.AddToStringsHeap(name);\r
4040                         done = true;\r
4041                 }\r
4042 \r
4043                 internal sealed override void Write(FileImage output) {\r
4044                         output.Write ((short) index);\r
4045                         output.Write ((short) 0);\r
4046                         output.WriteCodedIndex(CIx.TypeOrMethodDef, owner);\r
4047                         output.Write ((uint) nameIx);\r
4048                         output.WriteIndex(MDTable.TypeDef,owner.Row);\r
4049                 }\r
4050 \r
4051     \r
4052         }\r
4053 \r
4054         internal class GenericParamConstraint : MetaDataElement\r
4055         {\r
4056                 GenericParameter param;\r
4057                 Type type;\r
4058 \r
4059                 public GenericParamConstraint (GenericParameter param, Type type) {\r
4060                         this.param = param;\r
4061                         this.type = type;\r
4062                         tabIx = MDTable.GenericParamConstraint;\r
4063                 }\r
4064 \r
4065                 internal sealed override uint Size(MetaData md) {\r
4066                         return (uint) (md.TableIndexSize(MDTable.GenericParam) +\r
4067                                        md.CodedIndexSize(CIx.TypeDefOrRef));\r
4068                 }\r
4069 \r
4070                 internal sealed override void Write(FileImage output) {\r
4071                         output.WriteIndex(MDTable.GenericParam, param.Row);\r
4072                         output.WriteCodedIndex(CIx.TypeDefOrRef, type);\r
4073                 }\r
4074 \r
4075 \r
4076         }\r
4077
4078         internal class MethodSpec : MetaDataElement
4079         {
4080                 Method meth;
4081                 GenericMethodSig g_sig;
4082                 uint sidx;
4083
4084                 internal MethodSpec (Method meth, GenericMethodSig g_sig) {
4085                         this.meth = meth;
4086                         this.g_sig = g_sig;
4087                         tabIx = MDTable.MethodSpec;
4088                 }
4089
4090                 internal sealed override void BuildTables (MetaData md) {
4091                         if (done) return;
4092                         sidx = g_sig.GetSigIx (md);
4093                         done = true;
4094                 }
4095
4096                 internal sealed override uint Size (MetaData md) {
4097                         return (uint) (md.CodedIndexSize(CIx.MethodDefOrRef) +
4098                                        md.BlobIndexSize ());
4099                 }
4100
4101                 internal sealed override void Write (FileImage output) {
4102                     output.WriteCodedIndex (CIx.MethodDefOrRef, meth);
4103                     output.BlobIndex (sidx);\r
4104                 }
4105         }
4106
4107   /**************************************************************************/\r
4108         /// <summary>\r
4109         /// Descriptor for interface implemented by a class\r
4110         /// </summary>\r
4111         public class InterfaceImpl: MetaDataElement\r
4112         { \r
4113     ClassDef theClass;\r
4114     Class theInterface;\r
4115 \r
4116                 internal InterfaceImpl(ClassDef theClass, Class theInterface) {\r
4117       this.theClass = theClass;\r
4118       this.theInterface = theInterface;\r
4119                         tabIx = MDTable.InterfaceImpl;\r
4120                 }\r
4121 \r
4122     internal sealed override uint Size(MetaData md) {\r
4123       return md.TableIndexSize(MDTable.TypeDef) + \r
4124              md.CodedIndexSize(CIx.TypeDefOrRef);\r
4125     }\r
4126 \r
4127     internal sealed override void Write(FileImage output) {\r
4128       output.WriteIndex(MDTable.TypeDef,theClass.Row);\r
4129       output.WriteCodedIndex(CIx.TypeDefOrRef,theInterface);\r
4130     }\r
4131 \r
4132     internal sealed override uint GetCodedIx(CIx code) { return 5; }\r
4133 \r
4134         }\r
4135   /**************************************************************************/  \r
4136         /// <summary>\r
4137         /// Descriptor for a local of a method\r
4138         /// </summary>\r
4139   public class Local\r
4140         {\r
4141     private static readonly byte Pinned = 0x45;\r
4142     string name;\r
4143     Type type;\r
4144     bool pinned = false, byref = false;\r
4145 \r
4146     /// <summary>\r
4147     /// Create a new local variable \r
4148     /// </summary>\r
4149     /// <param name="lName">name of the local variable</param>\r
4150     /// <param name="lType">type of the local variable</param>\r
4151     public Local(string lName, Type lType) {\r
4152       name = lName;\r
4153       type = lType;\r
4154     }\r
4155 \r
4156     /// <summary>\r
4157     /// Create a new local variable that is byref and/or pinned\r
4158     /// </summary>\r
4159     /// <param name="lName">local name</param>\r
4160     /// <param name="lType">local type</param>\r
4161     /// <param name="byRef">is byref</param>\r
4162     /// <param name="isPinned">has pinned attribute</param>\r
4163                 public Local(string lName, Type lType, bool byRef, bool isPinned)\r
4164                 {\r
4165       name = lName;\r
4166       type = lType;\r
4167       byref = byRef;\r
4168       pinned = isPinned;\r
4169                 }\r
4170 \r
4171     internal void TypeSig(MemoryStream str) {\r
4172       if (pinned) str.WriteByte(Pinned);\r
4173       type.TypeSig(str);\r
4174     }\r
4175 \r
4176         }\r
4177   /**************************************************************************/  \r
4178         /// <summary>\r
4179         /// Descriptor for the locals for a method\r
4180         /// </summary>\r
4181 \r
4182   public class LocalSig : Signature\r
4183         {\r
4184                 private static readonly byte LocalSigByte = 0x7;\r
4185     Local[] locals;\r
4186 \r
4187                 public LocalSig(Local[] locals)         {\r
4188       this.locals = locals;\r
4189       tabIx = MDTable.StandAloneSig;\r
4190                 }\r
4191 \r
4192     internal sealed override void BuildTables(MetaData md) {\r
4193       if (done) return;\r
4194       MemoryStream sig = new MemoryStream();\r
4195       sig.WriteByte(LocalSigByte);\r
4196       MetaData.CompressNum((uint)locals.Length,sig);\r
4197       for (int i=0; i < locals.Length; i++) {\r
4198         ((Local)locals[i]).TypeSig(sig);\r
4199       }\r
4200       sigIx = md.AddToBlobHeap(sig.ToArray());\r
4201       done = true;\r
4202     }\r
4203 \r
4204   }\r
4205 \r
4206   /**************************************************************************/  \r
4207         /// <summary>\r
4208         /// Descriptor for resources used in this PE file NOT YET IMPLEMENTED\r
4209         /// </summary>\r
4210 \r
4211   public class ManifestResource : MetaDataElement\r
4212         {\r
4213     private static readonly uint PublicResource = 0x1;\r
4214     private static readonly uint PrivateResource = 0x2;\r
4215 \r
4216     string mrName;\r
4217     MetaDataElement rRef;\r
4218     int fileOffset;\r
4219     uint nameIx = 0;\r
4220     uint flags = 0;\r
4221 \r
4222     public ManifestResource(string name, bool isPub, FileRef fileRef) {\r
4223       mrName = name;\r
4224       if (isPub) flags = PublicResource;\r
4225       else flags = PrivateResource;\r
4226       rRef = fileRef;\r
4227       tabIx = MDTable.ManifestResource;\r
4228       throw(new NotYetImplementedException("Manifest Resources "));\r
4229     }\r
4230 \r
4231     public ManifestResource(string name, bool isPub, FileRef fileRef, \r
4232                                                             int fileIx) {\r
4233       mrName = name;\r
4234       if (isPub) flags = PublicResource;\r
4235       else flags = PrivateResource;\r
4236       rRef = fileRef;\r
4237       fileOffset = fileIx;\r
4238     }\r
4239 \r
4240     public ManifestResource(string name, bool isPub, AssemblyRef assemRef) {\r
4241       mrName = name;\r
4242       if (isPub) flags = PublicResource;\r
4243       else flags = PrivateResource;\r
4244       rRef = assemRef;\r
4245     }\r
4246 \r
4247     internal sealed override void BuildTables(MetaData md) {\r
4248       if (done) return;\r
4249       nameIx = md.AddToStringsHeap(mrName);\r
4250       done = true;\r
4251     }\r
4252 \r
4253     internal sealed override uint Size(MetaData md) {\r
4254       return 8 + md.StringsIndexSize() + \r
4255                  md.CodedIndexSize(CIx.Implementation);\r
4256     }\r
4257 \r
4258     internal sealed override void Write(FileImage output) {\r
4259       output.Write(fileOffset);\r
4260       output.Write(flags);\r
4261       output.StringsIndex(nameIx);\r
4262       output.WriteCodedIndex(CIx.Implementation,rRef);\r
4263     }\r
4264 \r
4265     internal sealed override uint GetCodedIx(CIx code) { return 18; }\r
4266 \r
4267         }\r
4268   /**************************************************************************/  \r
4269         /// <summary>\r
4270         /// Base class for elements in the PropertyMap, EventMap and \r
4271         /// NestedClass MetaData tables\r
4272         /// </summary>\r
4273   public class MapElem : MetaDataElement\r
4274         {\r
4275     ClassDef parent;\r
4276     uint elemIx;\r
4277     MDTable elemTable;\r
4278 \r
4279                 internal MapElem(ClassDef par, uint elIx, MDTable elemTab) {\r
4280       parent = par;\r
4281       elemIx = elIx;\r
4282       elemTable = elemTab;\r
4283                 }\r
4284 \r
4285     internal sealed override uint Size(MetaData md) {\r
4286       return md.TableIndexSize(MDTable.TypeDef) + md.TableIndexSize(elemTable);\r
4287     }\r
4288 \r
4289     internal sealed override void Write(FileImage output) {\r
4290       output.WriteIndex(MDTable.TypeDef,parent.Row);\r
4291       output.WriteIndex(elemTable,elemIx);\r
4292     }\r
4293         }\r
4294   /**************************************************************************/  \r
4295         /// <summary>\r
4296         /// Base class for field/methods (member of a class)\r
4297         /// </summary>\r
4298         public abstract class Member : MetaDataElement\r
4299         {\r
4300     protected string name;\r
4301     protected uint nameIx = 0, sigIx = 0;\r
4302     \r
4303                 internal Member(string memName)\r
4304                 {\r
4305       name = memName;\r
4306                         tabIx = MDTable.MemberRef;\r
4307                 }\r
4308 \r
4309         }\r
4310   /**************************************************************************/  \r
4311         /// <summary>\r
4312   /// MetaData \r
4313   ///   Root (20 bytes + UTF-8 Version String + quad align padding)\r
4314   ///   StreamHeaders (8 bytes + null terminated name string + quad align padding)\r
4315   ///   Streams \r
4316   ///     #~        (always present - holds metadata tables)\r
4317   ///     #Strings  (always present - holds identifier strings)\r
4318   ///     #US       (Userstring heap)\r
4319   ///     #Blob     (signature blobs)\r
4320   ///     #GUID     (guids for assemblies or Modules)\r
4321   /// </summary>\r
4322 \r
4323   public class MetaData \r
4324         {\r
4325                 private static readonly int[] CIxShiftMap = {2,2,5,1,2,3,1,1,1,2,3,2,1};\r
4326                 private static readonly byte StringsHeapMask = 0x1;\r
4327                 private static readonly byte GUIDHeapMask = 0x2;\r
4328                 private static readonly byte BlobHeapMask = 0x4;\r
4329     private static readonly uint MetaDataSignature = 0x424A5342;\r
4330     private static readonly uint maxSmlIxSize = 0xFFFF;\r
4331     private static readonly uint max1BitSmlIx = 0x7FFF;\r
4332     private static readonly uint max2BitSmlIx = 0x3FFF;\r
4333     private static readonly uint max3BitSmlIx = 0x1FFF;\r
4334     private static readonly uint max5BitSmlIx = 0x7FF;\r
4335     // NOTE: version and stream name strings MUST always be quad padded\r
4336     private static readonly string version = "v1.0.3705\0\0\0";\r
4337     private static readonly char[] tildeName = {'#','~','\0','\0'};\r
4338     private static readonly char[] stringsName = {'#','S','t','r','i','n','g','s','\0','\0','\0','\0'};\r
4339     private static readonly char[] usName = {'#','U','S','\0'};\r
4340     private static readonly char[] guidName = {'#','G','U','I','D','\0','\0','\0'};\r
4341     private static readonly char[] blobName = {'#','B','l','o','b','\0','\0','\0'};\r
4342                 private static readonly uint MetaDataHeaderSize = 20 + (uint)version.Length;\r
4343     private static readonly uint TildeHeaderSize = 24;\r
4344     private static readonly uint StreamHeaderSize = 8;\r
4345     private static readonly uint numMetaDataTables = (int)MDTable.GenericParamConstraint + 1;\r
4346     private static readonly uint tildeHeaderSize = 8 + (uint)tildeName.Length;\r
4347 \r
4348     MetaDataStream strings, us, guid, blob;\r
4349 \r
4350     MetaDataStream[] streams = new MetaDataStream[5];\r
4351     uint numStreams = 5;\r
4352     uint tildeTide = 0, tildePadding = 0, tildeStart = 0;\r
4353     uint numTables = 0;\r
4354     ArrayList[] metaDataTables = new ArrayList[numMetaDataTables];\r
4355     ArrayList byteCodes = new ArrayList();\r
4356     uint codeSize = 0, codeStart, byteCodePadding = 0, metaDataSize = 0;\r
4357                 ulong valid = 0, /*sorted = 0x000002003301FA00;*/ sorted = 0;\r
4358     bool[] largeIx = new bool[numMetaDataTables];\r
4359     bool[] lgeCIx = new bool[(int)CIx.MaxCIx];\r
4360                 bool largeStrings = false, largeUS = false, largeGUID = false, largeBlob = false;\r
4361                 private FileImage file;\r
4362     private byte heapSizes = 0;\r
4363                 MetaDataElement entryPoint;\r
4364                 BinaryWriter output;\r
4365     public MSCorLib mscorlib;\r
4366     private TypeSpec[] systemTypeSpecs = new TypeSpec[PrimitiveType.NumSystemTypes];\r
4367     long mdStart;\r
4368 \r
4369     internal MetaData(FileImage file) {\r
4370       // tilde = new MetaDataStream(tildeName,false,0);\r
4371       this.file = file;\r
4372                         strings = new MetaDataStream(stringsName,new UTF8Encoding(),true);\r
4373       us = new MetaDataStream(usName,new UnicodeEncoding(),true);\r
4374       guid = new MetaDataStream(guidName,false);\r
4375       blob = new MetaDataStream(blobName,true);\r
4376       streams[1] = strings;\r
4377       streams[2] = us;\r
4378       streams[3] = guid;\r
4379       streams[4] = blob;\r
4380       for (int i=0; i < numMetaDataTables; i++) {\r
4381         largeIx[i] = false;\r
4382       }\r
4383       for (int i=0; i < lgeCIx.Length; i++) {\r
4384         lgeCIx[i] = false;\r
4385       }\r
4386       mscorlib = new MSCorLib(this);\r
4387                 }\r
4388  \r
4389     internal TypeSpec GetPrimitiveTypeSpec(int ix) {\r
4390       return systemTypeSpecs[ix];\r
4391     }\r
4392 \r
4393     internal void SetPrimitiveTypeSpec(int ix, TypeSpec typeSpec) {\r
4394       systemTypeSpecs[ix] = typeSpec;\r
4395     }\r
4396 \r
4397     internal uint Size() {\r
4398       return metaDataSize;\r
4399     }\r
4400 \r
4401                 internal void StreamSize(byte mask) {\r
4402                         heapSizes |= mask;\r
4403                 }\r
4404 \r
4405     internal uint AddToUSHeap(string str) {\r
4406       if (str == null) return 0;\r
4407       return us.Add(str,true);\r
4408    }\r
4409 \r
4410     internal uint AddToStringsHeap(string str) {\r
4411       if ((str == null) || (str.CompareTo("") == 0)) return 0;\r
4412       return strings.Add(str,false);\r
4413     }\r
4414 \r
4415     internal uint AddToGUIDHeap(Guid guidNum) {\r
4416       return guid.Add(guidNum);\r
4417     }\r
4418 \r
4419     internal uint AddToBlobHeap(byte[] blobBytes) {\r
4420       if (blobBytes == null) return 0;\r
4421       return blob.Add(blobBytes);\r
4422     }\r
4423 \r
4424     internal uint AddToBlobHeap(byte val) {\r
4425       return blob.Add(val);\r
4426     }\r
4427 \r
4428     internal uint AddToBlobHeap(sbyte val) {\r
4429       return blob.Add(val);\r
4430     }\r
4431 \r
4432     internal uint AddToBlobHeap(ushort val) {\r
4433       return blob.Add(val);\r
4434     }\r
4435 \r
4436     internal uint AddToBlobHeap(short val) {\r
4437       return blob.Add(val);\r
4438     }\r
4439 \r
4440     internal uint AddToBlobHeap(uint val) {\r
4441       return blob.Add(val);\r
4442     }\r
4443 \r
4444     internal uint AddToBlobHeap(int val) {\r
4445       return blob.Add(val);\r
4446     }\r
4447 \r
4448     internal uint AddToBlobHeap(ulong val) {\r
4449       return blob.Add(val);\r
4450     }\r
4451 \r
4452     internal uint AddToBlobHeap(long val) {\r
4453       return blob.Add(val);\r
4454     }\r
4455 \r
4456     internal uint AddToBlobHeap(float val) {\r
4457       return blob.Add(val);\r
4458     }\r
4459 \r
4460     internal uint AddToBlobHeap(double val) {\r
4461       return blob.Add(val);\r
4462     }\r
4463 \r
4464     internal uint AddToBlobHeap(string val) {\r
4465       return blob.Add(val,true);\r
4466     }\r
4467 \r
4468 \r
4469     private ArrayList GetTable(MDTable tableIx) {\r
4470       int tabIx = (int)tableIx;\r
4471       if (metaDataTables[tabIx] == null) {\r
4472         metaDataTables[tabIx] = new ArrayList();\r
4473         valid |= ((ulong)0x1 << tabIx);\r
4474         // Console.WriteLine("after creating table " + tableIx + "(" + tabIx + ") valid = " + valid);\r
4475         numTables++;\r
4476       }\r
4477       return metaDataTables[tabIx];\r
4478     }\r
4479  \r
4480     internal void AddToTable(MDTable tableIx, MetaDataElement elem) {\r
4481       if (elem.Row > 0) {\r
4482         // Console.Out.WriteLine("ERROR - element already in table " + tableIx);\r
4483         return;\r
4484       }\r
4485       // updates Row field of the element\r
4486       // Console.WriteLine("Adding element to table " + (uint)tableIx);\r
4487       ArrayList table = GetTable(tableIx);\r
4488       elem.Row = (uint)table.Count + 1;\r
4489       table.Add(elem);\r
4490     }\r
4491 \r
4492     internal uint TableIndex(MDTable tableIx) {\r
4493       if (metaDataTables[(int)tableIx] == null) return 1;\r
4494       return (uint)metaDataTables[(int)tableIx].Count+1;\r
4495     }\r
4496 \r
4497     internal uint AddCode(CILInstructions byteCode) {\r
4498       byteCodes.Add(byteCode);\r
4499       uint offset = codeSize + codeStart;\r
4500       codeSize += byteCode.GetCodeSize();\r
4501       return offset;\r
4502     }\r
4503 \r
4504     internal void SetEntryPoint(MetaDataElement ep) {\r
4505       entryPoint = ep;\r
4506     }\r
4507 \r
4508     internal void AddData(DataConstant cVal) {\r
4509       file.AddInitData(cVal);\r
4510     }\r
4511 \r
4512                 internal static void CompressNum(uint val, MemoryStream sig) {\r
4513                         if (val < 0x7F) {\r
4514                                 sig.WriteByte((byte)val);\r
4515                         } else if (val < 0x3FFF) {\r
4516                                 byte b1 = (byte)((val >> 8) | 0x80);\r
4517                                 byte b2 = (byte)(val & FileImage.iByteMask[0]);\r
4518                                 sig.WriteByte(b1);\r
4519                                 sig.WriteByte(b2);\r
4520                         } else {\r
4521                                 byte b1 = (byte)((val >> 24) | 0xC0);\r
4522                                 byte b2 = (byte)((val & FileImage.iByteMask[2]) >> 16);\r
4523                                 byte b3 = (byte)((val & FileImage.iByteMask[1]) >> 8);;\r
4524                                 byte b4 = (byte)(val & FileImage.iByteMask[0]);\r
4525                                 sig.WriteByte(b1);\r
4526                                 sig.WriteByte(b2);\r
4527                                 sig.WriteByte(b3);\r
4528                                 sig.WriteByte(b4);\r
4529                         }\r
4530                 }\r
4531 \r
4532     internal uint CodeSize() {\r
4533       return codeSize + byteCodePadding;\r
4534     }\r
4535 \r
4536     internal uint StringsIndexSize() {\r
4537       if (largeStrings) return 4;\r
4538       return 2;\r
4539     }\r
4540 \r
4541     internal uint GUIDIndexSize() {\r
4542       if (largeGUID) return 4;\r
4543       return 2;\r
4544     }\r
4545 \r
4546     internal uint USIndexSize() {\r
4547       if (largeUS) return 4;\r
4548       return 2;\r
4549     }\r
4550 \r
4551     internal uint BlobIndexSize() {\r
4552       if (largeBlob) return 4;\r
4553       return 2;\r
4554     }\r
4555 \r
4556     internal uint CodedIndexSize(CIx code) {\r
4557       if (lgeCIx[(uint)code]) return 4;\r
4558       return 2;\r
4559     }\r
4560 \r
4561     internal uint TableIndexSize(MDTable tabIx) {\r
4562       if (largeIx[(uint)tabIx]) return 4;\r
4563       return 2;\r
4564     }\r
4565     \r
4566     private void SetIndexSizes() {\r
4567       for (int i=0; i < numMetaDataTables; i++) {\r
4568         if (metaDataTables[i] != null) {\r
4569           uint count = (uint)metaDataTables[i].Count;\r
4570           if (count > maxSmlIxSize) {\r
4571             largeIx[i] = true;\r
4572                                                 MDTable tabIx = (MDTable)i;\r
4573             if (count > max5BitSmlIx) {\r
4574               lgeCIx[(int)CIx.HasCustomAttr] = true;\r
4575             }\r
4576             if (count > max3BitSmlIx) {\r
4577               if ((tabIx == MDTable.TypeRef) || (tabIx == MDTable.ModuleRef) || (tabIx == MDTable.Method) || (tabIx == MDTable.TypeSpec)) \r
4578                 lgeCIx[(int)CIx.CustomAttributeType] = true;\r
4579               if ((tabIx == MDTable.Method) || (tabIx == MDTable.MemberRef)) \r
4580                 lgeCIx[(int)CIx.MemberRefParent] = true;\r
4581             } else if (count > max2BitSmlIx) {\r
4582               if ((tabIx == MDTable.Field) || (tabIx == MDTable.Param) || (tabIx == MDTable.Property)) \r
4583                 lgeCIx[(int)CIx.HasConst] = true;\r
4584               if ((tabIx == MDTable.TypeDef) || (tabIx == MDTable.TypeRef) || (tabIx == MDTable.TypeSpec))\r
4585                 lgeCIx[(int)CIx.TypeDefOrRef] = true;\r
4586               if ((tabIx == MDTable.TypeDef) || (tabIx == MDTable.Method) || (tabIx == MDTable.Assembly))\r
4587                 lgeCIx[(int)CIx.HasDeclSecurity] = true;\r
4588               if ((tabIx == MDTable.File) || (tabIx == MDTable.AssemblyRef) || (tabIx == MDTable.ExportedType))\r
4589                 lgeCIx[(int)CIx.Implementation] = true;\r
4590               if ((tabIx == MDTable.Module) || (tabIx == MDTable.ModuleRef) || (tabIx == MDTable.AssemblyRef) || (tabIx == MDTable.TypeRef))\r
4591                 lgeCIx[(int)CIx.ResolutionScope] = true;\r
4592             } else if (count > max1BitSmlIx) {\r
4593               if ((tabIx == MDTable.Field) || (tabIx == MDTable.Param)) \r
4594                 lgeCIx[(int)CIx.HasFieldMarshal] = true;\r
4595               if ((tabIx == MDTable.Event) || (tabIx == MDTable.Property)) \r
4596                 lgeCIx[(int)CIx.HasSemantics] = true;\r
4597               if ((tabIx == MDTable.Method) || (tabIx == MDTable.MemberRef)) \r
4598                 lgeCIx[(int)CIx.MethodDefOrRef] = true;\r
4599               if ((tabIx == MDTable.Field) || (tabIx == MDTable.Method)) \r
4600                 lgeCIx[(int)CIx.MemberForwarded] = true; \r
4601               if ((tabIx == MDTable.TypeDef) || (tabIx == MDTable.Method)) \r
4602                 lgeCIx[(int)CIx.TypeOrMethodDef] = true; \r
4603             }\r
4604           }\r
4605         }\r
4606       }\r
4607                         if (strings.LargeIx()) {\r
4608                                 largeStrings = true;\r
4609                                 heapSizes |= StringsHeapMask;\r
4610                         }\r
4611                         if (guid.LargeIx()) {\r
4612                                 largeGUID = true;\r
4613                                 heapSizes |= GUIDHeapMask;\r
4614                         }\r
4615                         if (blob.LargeIx()) {\r
4616                                 largeBlob = true;\r
4617                                 heapSizes |= BlobHeapMask;\r
4618                         }\r
4619       largeUS = us.LargeIx();\r
4620     }\r
4621 \r
4622     private void SetStreamOffsets() {\r
4623       uint sizeOfHeaders = StreamHeaderSize + (uint)tildeName.Length;\r
4624       for (int i=1; i < numStreams; i++) {\r
4625         sizeOfHeaders += streams[i].headerSize();\r
4626       }\r
4627       metaDataSize = MetaDataHeaderSize + sizeOfHeaders;\r
4628       tildeStart = metaDataSize;\r
4629       metaDataSize += tildeTide + tildePadding;\r
4630       for (int i=1; i < numStreams; i++) {\r
4631         streams[i].Start = metaDataSize;\r
4632         metaDataSize += streams[i].Size();\r
4633         streams[i].WriteDetails();\r
4634       }\r
4635     }\r
4636 \r
4637     internal void CalcTildeStreamSize() {\r
4638       //tilde.SetIndexSizes(strings.LargeIx(),us.LargeIx(),guid.LargeIx(),blob.LargeIx());\r
4639       tildeTide = TildeHeaderSize;\r
4640       tildeTide += 4 * numTables;\r
4641       //Console.WriteLine("Tilde header + sizes = " + tildeTide);\r
4642       for (int i=0; i < numMetaDataTables; i++) {\r
4643         if (metaDataTables[i] != null) {\r
4644           ArrayList table = metaDataTables[i];\r
4645           // Console.WriteLine("Meta data table " + i + " at offset " + tildeTide);\r
4646           tildeTide += (uint)table.Count * ((MetaDataElement)table[0]).Size(this);\r
4647           // Console.WriteLine("Metadata table " + i + " has size " + table.Count);\r
4648           // Console.WriteLine("tildeTide = " + tildeTide);\r
4649         }\r
4650       }\r
4651       if ((tildeTide % 4) != 0) tildePadding = 4 - (tildeTide % 4);\r
4652       //Console.WriteLine("tildePadding = " + tildePadding);\r
4653     }\r
4654 \r
4655     internal void WriteTildeStream(FileImage output) {\r
4656       long startTilde = output.Seek(0,SeekOrigin.Current);\r
4657                         output.Write((uint)0); // Reserved\r
4658                         output.Write((byte)1); // MajorVersion\r
4659                         output.Write((byte)0); // MinorVersion\r
4660                         output.Write(heapSizes);\r
4661                         output.Write((byte)1); // Reserved\r
4662                         output.Write(valid);\r
4663                         output.Write(sorted);\r
4664                         for (int i=0; i < numMetaDataTables; i++) {\r
4665                                 if (metaDataTables[i] != null) {\r
4666                                         uint count = (uint)metaDataTables[i].Count;\r
4667                                         output.Write(count);\r
4668                                 }\r
4669                         }\r
4670       long tabStart = output.Seek(0,SeekOrigin.Current);\r
4671       // Console.WriteLine("Starting metaData tables at " + tabStart);\r
4672                         for (int i=0; i < numMetaDataTables; i++) {\r
4673                                 if (metaDataTables[i] != null) {\r
4674           // Console.WriteLine("Starting metaData table " + i + " at " + (output.Seek(0,SeekOrigin.Current) - startTilde));\r
4675           ArrayList table = metaDataTables[i];\r
4676                                         for (int j=0; j < table.Count; j++) {\r
4677              ((MetaDataElement)table[j]).Write(output);\r
4678                                         }\r
4679                                 }\r
4680                         }\r
4681       // Console.WriteLine("Writing padding at " + output.Seek(0,SeekOrigin.Current));\r
4682       for (int i=0; i < tildePadding; i++) output.Write((byte)0);\r
4683                 }\r
4684 \r
4685     private void BuildTable(ArrayList table) {\r
4686       if (table == null) return;\r
4687       for (int j=0; j < table.Count; j++) {\r
4688         ((MetaDataElement)table[j]).BuildTables(this);\r
4689       }\r
4690     }\r
4691 \r
4692     internal void BuildMetaData(uint codeStartOffset) {\r
4693       codeStart = codeStartOffset;\r
4694       BuildTable(metaDataTables[(int)MDTable.TypeDef]);\r
4695       BuildTable(metaDataTables[(int)MDTable.MemberRef]);\r
4696       BuildTable(metaDataTables[(int)MDTable.GenericParam]);\r
4697       BuildTable(metaDataTables[(int)MDTable.MethodSpec]);\r
4698       BuildTable(metaDataTables[(int)MDTable.GenericParamConstraint]);\r
4699       BuildTable(metaDataTables[(int)MDTable.CustomAttribute]);\r
4700 /*      for (int i=0; i < metaDataTables.Length; i++) {\r
4701         ArrayList table = metaDataTables[i];\r
4702         if (table != null) {\r
4703           for (int j=0; j < table.Count; j++) {\r
4704             ((MetaDataElement)table[j]).BuildTables(this);\r
4705           }\r
4706         }\r
4707       }\r
4708       */\r
4709                         SetIndexSizes();\r
4710                         for (int i=1; i < numStreams; i++) {\r
4711                                 streams[i].EndStream();\r
4712                         }\r
4713                         CalcTildeStreamSize();\r
4714                         SetStreamOffsets();\r
4715       byteCodePadding = NumToAlign(codeSize,4);\r
4716       if (entryPoint != null) file.SetEntryPoint(entryPoint.Token());\r
4717     }\r
4718 \r
4719     internal void WriteByteCodes(FileImage output) {\r
4720       for (int i=0; i < byteCodes.Count; i++) {\r
4721         ((CILInstructions)byteCodes[i]).Write(output);\r
4722       }\r
4723       for (int i=0; i < byteCodePadding; i++) {\r
4724         output.Write((byte)0);\r
4725       }\r
4726     }\r
4727 \r
4728     internal void WriteMetaData(FileImage output) {\r
4729                         this.output = output;\r
4730       mdStart = output.Seek(0,SeekOrigin.Current);\r
4731       // Console.WriteLine("Writing metaData at " + Hex.Long(mdStart));\r
4732       output.Write(MetaDataSignature);\r
4733       output.Write((short)1);  // Major Version\r
4734       output.Write((short)1);  // Minor Version  ECMA = 0, PEFiles = 1\r
4735       output.Write(0);         // Reserved\r
4736       output.Write(version.Length);\r
4737       output.Write(version.ToCharArray());   // version string is already zero padded\r
4738       output.Write((short)0);\r
4739       output.Write((ushort)numStreams);\r
4740       // write tilde header\r
4741       output.Write(tildeStart);\r
4742       output.Write(tildeTide + tildePadding);\r
4743       output.Write(tildeName);\r
4744       for (int i=1; i < numStreams; i++) streams[i].WriteHeader(output);\r
4745       // Console.WriteLine("Writing tilde stream at " + output.Seek(0,SeekOrigin.Current) + " = " + tildeStart);\r
4746       WriteTildeStream(output);\r
4747       for (int i=1; i < numStreams; i++) streams[i].Write(output);\r
4748       // Console.WriteLine("Finished Writing metaData at " + output.Seek(0,SeekOrigin.Current));\r
4749     }\r
4750 \r
4751                 internal bool LargeStringsIndex() { return strings.LargeIx(); }\r
4752                 internal bool LargeGUIDIndex() { return guid.LargeIx(); }\r
4753                 internal bool LargeUSIndex() { return us.LargeIx(); }\r
4754                 internal bool LargeBlobIndex() { return blob.LargeIx(); }\r
4755 \r
4756     internal bool LargeIx(MDTable tabIx) { return largeIx[(uint)tabIx]; }\r
4757 \r
4758 \r
4759                 private uint NumToAlign(uint val, uint alignVal) {\r
4760                         if ((val % alignVal) == 0) return 0;\r
4761                         return alignVal - (val % alignVal);\r
4762                 }\r
4763 \r
4764     internal void WriteCodedIndex(CIx code, MetaDataElement elem, FileImage output) {\r
4765       uint ix = 0;\r
4766       if (elem != null) { \r
4767         ix = (elem.Row << CIxShiftMap[(uint)code]) | elem.GetCodedIx(code);\r
4768         // Console.WriteLine("coded index = " + ix + " row = " + elem.Row);\r
4769       //} else {\r
4770         // Console.WriteLine("elem for coded index is null");\r
4771       }\r
4772       if (lgeCIx[(uint)code]) \r
4773         output.Write(ix);\r
4774       else\r
4775         output.Write((ushort)ix);\r
4776     }\r
4777 \r
4778         }\r
4779   /**************************************************************************/  \r
4780         /// <summary>\r
4781         /// Base class for all Meta Data table elements\r
4782         /// </summary>\r
4783 \r
4784   public abstract class MetaDataElement\r
4785         {\r
4786 \r
4787     protected ArrayList customAttributes;\r
4788     private uint row = 0;\r
4789     protected bool done = false;\r
4790                 protected MDTable tabIx;\r
4791 \r
4792     internal MetaDataElement() { }\r
4793 \r
4794     public uint Row {\r
4795       get {\r
4796         return row;\r
4797       }\r
4798       set {\r
4799         if (row == 0) row = value;\r
4800       }\r
4801     }\r
4802 \r
4803     internal virtual uint GetCodedIx(CIx code) { return 0; }\r
4804 \r
4805     /// <summary>\r
4806     /// Add a custom attribute to this item\r
4807     /// </summary>\r
4808     /// <param name="ctorMeth">the constructor method for this attribute</param>\r
4809     /// <param name="val">the byte value of the parameters</param>\r
4810     public void AddCustomAttribute(Method ctorMeth, byte[] val) {\r
4811       if (customAttributes == null) {\r
4812         customAttributes = new ArrayList();\r
4813       } \r
4814       customAttributes.Add(new CustomAttribute(this,ctorMeth,val));\r
4815     }\r
4816 \r
4817     /// <summary>\r
4818     /// Add a custom attribute to this item\r
4819     /// </summary>\r
4820     /// <param name="ctorMeth">the constructor method for this attribute</param>\r
4821     /// <param name="val">the constant values of the parameters</param>\r
4822     public void AddCustomAttribute(Method ctorMeth, Constant[] cVals) {\r
4823       if (customAttributes == null) {\r
4824         customAttributes = new ArrayList();\r
4825       } \r
4826 //      customAttributes.Add(new CustomAttribute(this,ctorMeth,cVals));\r
4827     }\r
4828 \r
4829     internal void DoCustomAttributes(MetaData md) {\r
4830       if (customAttributes != null) {\r
4831         for (int i=0; i < customAttributes.Count; i++) {\r
4832           CustomAttribute ca = (CustomAttribute)customAttributes[i];\r
4833           ca.BuildTables(md);\r
4834         }\r
4835       }\r
4836     }\r
4837 \r
4838     internal uint Token() {\r
4839       return (((uint)tabIx << 24) | row);\r
4840     }\r
4841 \r
4842     internal virtual void BuildTables(MetaData md) {\r
4843       done = true;\r
4844     }\r
4845 \r
4846     internal virtual uint Size(MetaData md) { \r
4847       return 0;\r
4848     }\r
4849 \r
4850     internal virtual void Write(FileImage output) {   }\r
4851 \r
4852         }\r
4853   /**************************************************************************/  \r
4854         /// <summary>\r
4855         /// Stream in the Meta Data  (#Strings, #US, #Blob and #GUID)\r
4856         /// </summary>\r
4857 \r
4858   internal class MetaDataStream : BinaryWriter \r
4859         {\r
4860                 private static readonly uint StreamHeaderSize = 8;\r
4861                 private static uint maxSmlIxSize = 0xFFFF;\r
4862                 \r
4863     private uint start = 0; \r
4864     uint size = 0, tide = 1;\r
4865     bool largeIx = false;\r
4866     uint sizeOfHeader;\r
4867     char[] name;\r
4868     Hashtable htable = new Hashtable();\r
4869 \r
4870     internal MetaDataStream(char[] name, bool addInitByte) : base(new MemoryStream()) {\r
4871       if (addInitByte) { Write((byte)0); size = 1; }\r
4872       this.name = name;\r
4873       sizeOfHeader = StreamHeaderSize + (uint)name.Length;\r
4874     }\r
4875 \r
4876     internal MetaDataStream(char[] name, System.Text.Encoding enc, bool addInitByte) : base(new MemoryStream(),enc) {\r
4877       if (addInitByte) { Write((byte)0); size = 1; }\r
4878       this.name = name;\r
4879       sizeOfHeader = StreamHeaderSize + (uint)name.Length;\r
4880                 }\r
4881 \r
4882     public uint Start {\r
4883       get {\r
4884         return start;\r
4885       }\r
4886       set {\r
4887         start = value;\r
4888       }\r
4889     }\r
4890   \r
4891     internal uint headerSize() {\r
4892       // Console.WriteLine(name + " stream has headersize of " + sizeOfHeader);\r
4893       return sizeOfHeader;\r
4894     }\r
4895 \r
4896     internal void SetSize(uint siz) {\r
4897       size = siz;\r
4898     }\r
4899 \r
4900     internal uint Size() {\r
4901       return size;\r
4902     }\r
4903 \r
4904     internal bool LargeIx() {\r
4905       return largeIx;\r
4906     }\r
4907 \r
4908     internal void WriteDetails() {\r
4909       // Console.WriteLine(name + " - size = " + size);\r
4910     }\r
4911 \r
4912                 internal uint Add(string str, bool prependSize) {\r
4913       Object val = htable[str];\r
4914       uint index = 0;\r
4915       if (val == null) { \r
4916         index = size;\r
4917         htable[str] = index;\r
4918         char[] arr = str.ToCharArray();\r
4919         if (prependSize) CompressNum((uint)arr.Length*2+1);\r
4920         Write(arr);\r
4921         Write((byte)0);\r
4922         size = (uint)Seek(0,SeekOrigin.Current);\r
4923       } else {\r
4924         index = (uint)val;\r
4925       }\r
4926                         return index;\r
4927                 }\r
4928 \r
4929                 internal uint Add(Guid guid) {\r
4930                         Write(guid.ToByteArray());\r
4931                         size =(uint)Seek(0,SeekOrigin.Current);\r
4932                         return tide++;\r
4933                 }\r
4934 \r
4935                 internal uint Add(byte[] blob) {\r
4936                         uint ix = size;\r
4937                         CompressNum((uint)blob.Length);\r
4938                         Write(blob);\r
4939                         size = (uint)Seek(0,SeekOrigin.Current);\r
4940                         return ix;\r
4941                 }\r
4942 \r
4943     internal uint Add(byte val) {\r
4944       uint ix = size;\r
4945       Write(val);\r
4946       size = (uint)Seek(0,SeekOrigin.Current);\r
4947       return ix;\r
4948     }\r
4949 \r
4950     internal uint Add(sbyte val) {\r
4951       uint ix = size;\r
4952       Write(val);\r
4953       size = (uint)Seek(0,SeekOrigin.Current);\r
4954       return ix;\r
4955     }\r
4956 \r
4957     internal uint Add(ushort val) {\r
4958       uint ix = size;\r
4959       Write(val);\r
4960       size = (uint)Seek(0,SeekOrigin.Current);\r
4961       return ix;\r
4962     }\r
4963 \r
4964     internal uint Add(short val) {\r
4965       uint ix = size;\r
4966       Write(val);\r
4967       size = (uint)Seek(0,SeekOrigin.Current);\r
4968       return ix;\r
4969     }\r
4970 \r
4971     internal uint Add(uint val) {\r
4972       uint ix = size;\r
4973       Write(val);\r
4974       size = (uint)Seek(0,SeekOrigin.Current);\r
4975       return ix;\r
4976     }\r
4977 \r
4978     internal uint Add(int val) {\r
4979       uint ix = size;\r
4980       Write(val);\r
4981       size = (uint)Seek(0,SeekOrigin.Current);\r
4982       return ix;\r
4983     }\r
4984 \r
4985     internal uint Add(ulong val) {\r
4986       uint ix = size;\r
4987       Write(val);\r
4988       size = (uint)Seek(0,SeekOrigin.Current);\r
4989       return ix;\r
4990     }\r
4991 \r
4992     internal uint Add(long val) {\r
4993       uint ix = size;\r
4994       Write(val);\r
4995       size = (uint)Seek(0,SeekOrigin.Current);\r
4996       return ix;\r
4997     }\r
4998 \r
4999     internal uint Add(float val) {\r
5000       uint ix = size;\r
5001       Write(val);\r
5002       size = (uint)Seek(0,SeekOrigin.Current);\r
5003       return ix;\r
5004     }\r
5005 \r
5006     internal uint Add(double val) {\r
5007       uint ix = size;\r
5008       Write(val);\r
5009       size = (uint)Seek(0,SeekOrigin.Current);\r
5010       return ix;\r
5011     }\r
5012 \r
5013                 private void CompressNum(uint val) {\r
5014       if (val < 0x7F) {\r
5015         Write((byte)val);\r
5016       } else if (val < 0x3FFF) {\r
5017         byte b1 = (byte)((val >> 8) | 0x80);\r
5018         byte b2 = (byte)(val & FileImage.iByteMask[0]);\r
5019         Write(b1);\r
5020         Write(b2);\r
5021       } else {\r
5022         byte b1 = (byte)((val >> 24) | 0xC0);\r
5023         byte b2 = (byte)((val & FileImage.iByteMask[2]) >> 16);\r
5024         byte b3 = (byte)((val & FileImage.iByteMask[1]) >> 8);;\r
5025         byte b4 = (byte)(val & FileImage.iByteMask[0]);\r
5026         Write(b1);\r
5027         Write(b2);\r
5028         Write(b3);\r
5029         Write(b4);\r
5030       }\r
5031     }\r
5032 \r
5033     private void QuadAlign() {\r
5034       if ((size % 4) != 0) {\r
5035         uint pad = 4 - (size % 4);\r
5036         size += pad;\r
5037         for (int i=0; i < pad; i++) {\r
5038           Write((byte)0);\r
5039         }\r
5040       }\r
5041     }\r
5042 \r
5043                 internal void EndStream() {\r
5044                         QuadAlign();\r
5045                         if (size > maxSmlIxSize) {\r
5046                                 largeIx = true;\r
5047                         }\r
5048                 }\r
5049 \r
5050     internal void WriteHeader(BinaryWriter output) {\r
5051       output.Write(start);\r
5052       output.Write(size);\r
5053       output.Write(name);\r
5054     }\r
5055 \r
5056                 internal virtual void Write(BinaryWriter output) {\r
5057        // Console.WriteLine("Writing " + name + " stream at " + output.Seek(0,SeekOrigin.Current) + " = " + start);\r
5058       MemoryStream str = (MemoryStream)BaseStream;\r
5059                         output.Write(str.ToArray());\r
5060                 }\r
5061 \r
5062         }\r
5063   /**************************************************************************/  \r
5064         /// <summary>\r
5065         /// Base class for Method Descriptors\r
5066         /// </summary>\r
5067 \r
5068   public abstract class Method : Member\r
5069         {\r
5070     protected CallConv callConv = CallConv.Default;\r
5071     protected Type retType;\r
5072 \r
5073     internal Method(string methName, Type rType) : base(methName)\r
5074                 {\r
5075       retType = rType;\r
5076                 }\r
5077 \r
5078     /// <summary>\r
5079     /// Add calling conventions to this method descriptor\r
5080     /// </summary>\r
5081     /// <param name="cconv"></param>\r
5082     public void AddCallConv(CallConv cconv) {\r
5083       callConv |= cconv;\r
5084     }\r
5085 \r
5086                 internal abstract void TypeSig(MemoryStream sig);\r
5087 \r
5088     internal uint GetSigIx(MetaData md) {\r
5089       MemoryStream sig = new MemoryStream();\r
5090                         TypeSig(sig);\r
5091       return md.AddToBlobHeap(sig.ToArray());\r
5092     }\r
5093 \r
5094     internal Type GetRetType() {\r
5095       return retType;\r
5096     }\r
5097 \r
5098         }\r
5099   /**************************************************************************/  \r
5100         /// <summary>\r
5101         /// Descriptor for a method defined in THIS assembly/module\r
5102         /// IL     .method\r
5103         /// </summary>\r
5104 \r
5105   public class MethodDef : Method\r
5106         {\r
5107     private static readonly ushort PInvokeImpl = 0x2000;\r
5108     //private static readonly uint UnmanagedExport = 0x0008;\r
5109    // private static readonly byte LocalSigByte = 0x7;\r
5110     uint parIx = 0, textOffset = 0;\r
5111 \r
5112     MetaData metaData;\r
5113     CILInstructions code;\r
5114     ArrayList securityActions = new ArrayList();\r
5115                 Param[] parList;\r
5116     Local[] locals;\r
5117     bool initLocals;\r
5118     ushort methFlags = 0, implFlags = 0;\r
5119     int maxStack = 0, numPars = 0;\r
5120     bool entryPoint = false;\r
5121     LocalSig localSig;\r
5122                 ArrayList varArgSigList;\r
5123     ImplMap pinvokeImpl;\r
5124 \r
5125 \r
5126                 internal MethodDef(MetaData md, string name, Type retType, Param[] pars) : base(name,retType) {\r
5127       metaData = md;\r
5128                         parList = pars;\r
5129                         if (parList != null) numPars = parList.Length;\r
5130       tabIx = MDTable.Method;\r
5131                 }\r
5132 \r
5133     internal MethodDef(MetaData md, MethAttr mAttrSet, ImplAttr iAttrSet, string name, Type retType, Param[] pars) : base(name,retType) {\r
5134       metaData = md;\r
5135                         parList = pars;\r
5136                         if (parList != null) numPars = parList.Length;\r
5137       // Console.WriteLine("Creating method " + name + " with " + numPars + " parameters");\r
5138                         methFlags = (ushort)mAttrSet;\r
5139       implFlags = (ushort)iAttrSet;\r
5140       tabIx = MDTable.Method;\r
5141     }\r
5142 \r
5143                 internal Param[] GetPars() {\r
5144                         return parList;\r
5145                 }\r
5146 \r
5147     /// <summary>\r
5148     /// Add some attributes to this method descriptor\r
5149     /// </summary>\r
5150     /// <param name="ma">the attributes to be added</param>\r
5151     public void AddMethAttribute(MethAttr ma) {\r
5152       methFlags |= (ushort)ma;\r
5153     }\r
5154 \r
5155     /// <summary>\r
5156     /// Add some implementation attributes to this method descriptor\r
5157     /// </summary>\r
5158     /// <param name="ia">the attributes to be added</param>\r
5159     public void AddImplAttribute(ImplAttr ia) {\r
5160       implFlags |= (ushort)ia;\r
5161     }\r
5162 \r
5163     public void AddPInvokeInfo(ModuleRef scope, string methName,\r
5164                                PInvokeAttr callAttr) {\r
5165       pinvokeImpl = new ImplMap((ushort)callAttr,this,methName,scope);\r
5166       methFlags |= PInvokeImpl;\r
5167     }\r
5168 \r
5169     /// <summary>\r
5170     ///  Add a named generic type parameter\r
5171     /// </summary>\r
5172     public GenericParameter AddGenericParameter (short index, string name) {\r
5173             GenericParameter gp = new GenericParameter (this, metaData, index, name);
5174             metaData.AddToTable (MDTable.GenericParam, gp);\r
5175             return gp;
5176     }\r
5177
5178     /// <summary>\r
5179     /// Set the maximum stack height for this method\r
5180     /// </summary>\r
5181     /// <param name="maxStack">the maximum height of the stack</param>\r
5182     public void SetMaxStack(int maxStack) {\r
5183       this.maxStack = maxStack; \r
5184     }\r
5185 \r
5186     /// <summary>\r
5187     /// Add local variables to this method\r
5188     /// </summary>\r
5189     /// <param name="locals">the locals to be added</param>\r
5190     /// <param name="initLocals">are locals initialised to default values</param>\r
5191     public void AddLocals(Local[] locals, bool initLocals) {\r
5192       this.locals = locals;\r
5193       this.initLocals = initLocals;\r
5194     }\r
5195 \r
5196     /// <summary>\r
5197     /// Mark this method as having an entry point\r
5198     /// </summary>\r
5199     public void DeclareEntryPoint() {\r
5200       entryPoint = true;\r
5201     }\r
5202 \r
5203     /// <summary>\r
5204     /// Create a code buffer for this method to add the IL instructions to\r
5205     /// </summary>\r
5206     /// <returns>a buffer for this method's IL instructions</returns>\r
5207     public CILInstructions CreateCodeBuffer() {\r
5208       code = new CILInstructions(metaData);\r
5209       return code;\r
5210     }\r
5211 \r
5212     /// <summary>\r
5213     /// Make a method reference descriptor for this method to be used \r
5214     /// as a callsite signature for this vararg method\r
5215     /// </summary>\r
5216     /// <param name="optPars">the optional pars for the vararg method call</param>\r
5217     /// <returns></returns>\r
5218     public MethodRef MakeVarArgSignature(Type[] optPars) {\r
5219       Type[] pars = new Type[numPars];\r
5220       MethodRef varArgSig;\r
5221       for (int i=0; i < numPars; i++) {\r
5222         pars[i] = parList[i].GetParType();\r
5223       }\r
5224       varArgSig = new MethodRef(this,name,retType,pars,true,optPars);\r
5225 \r
5226       if (varArgSigList == null)\r
5227               varArgSigList = new ArrayList ();\r
5228       varArgSigList.Add (varArgSig);\r
5229       return varArgSig;\r
5230     }\r
5231 \r
5232                 internal sealed override void TypeSig(MemoryStream sig) {\r
5233                         sig.WriteByte((byte)callConv);\r
5234                         MetaData.CompressNum((uint)numPars,sig);\r
5235                         retType.TypeSig(sig);\r
5236                         for (ushort i=0; i < numPars; i++) {\r
5237                                 parList[i].seqNo = (ushort)(i+1);\r
5238                                 parList[i].TypeSig(sig);\r
5239                         }\r
5240                 }\r
5241 \r
5242     internal sealed override void BuildTables(MetaData md) {\r
5243       if (done) return;\r
5244       if (pinvokeImpl != null) {\r
5245         md.AddToTable(MDTable.ImplMap,pinvokeImpl);\r
5246         pinvokeImpl.BuildTables(md);\r
5247       }\r
5248       if (entryPoint) md.SetEntryPoint(this);\r
5249       uint locToken = 0;\r
5250       if (locals != null) {\r
5251         localSig = new LocalSig(locals);\r
5252         md.AddToTable(MDTable.StandAloneSig,localSig);\r
5253         localSig.BuildTables(md);\r
5254         locToken = localSig.Token();\r
5255       }\r
5256                         if (code != null) {\r
5257                                 code.CheckCode(locToken,initLocals,maxStack);\r
5258                                 textOffset = md.AddCode(code);\r
5259                         }\r
5260       nameIx = md.AddToStringsHeap(name);\r
5261       sigIx = GetSigIx(md);\r
5262       parIx = md.TableIndex(MDTable.Param);\r
5263                         for (int i=0; i < numPars; i++) {\r
5264                                 md.AddToTable(MDTable.Param,parList[i]);\r
5265                                 parList[i].BuildTables(md);\r
5266                         }\r
5267       if (varArgSigList != null) {\r
5268               foreach (MethodRef varArgSig in varArgSigList) {\r
5269         md.AddToTable(MDTable.MemberRef,varArgSig);\r
5270         varArgSig.BuildTables(md);\r
5271       }\r
5272       }\r
5273       DoCustomAttributes (md);\r
5274       // Console.WriteLine("method has " + numPars + " parameters");\r
5275       done = true;\r
5276     }\r
5277 \r
5278     internal sealed override uint Size(MetaData md) {\r
5279       return 8 + md.StringsIndexSize() + md.BlobIndexSize() + md.TableIndexSize(MDTable.Param);\r
5280     }\r
5281 \r
5282     internal sealed override void Write(FileImage output) {\r
5283       if (ZeroRva ()) output.Write(0);\r
5284       else output.WriteCodeRVA(textOffset);\r
5285       output.Write(implFlags);\r
5286       output.Write(methFlags);\r
5287       output.StringsIndex(nameIx);\r
5288       output.BlobIndex(sigIx);\r
5289       output.WriteIndex(MDTable.Param,parIx);\r
5290     }\r
5291 \r
5292     internal bool ZeroRva () {
5293         return (((methFlags & (ushort)MethAttr.Abstract) != 0) ||
5294                         (pinvokeImpl != null)); // TODO: Not entirely true but works for now
5295     }
5296
5297     internal sealed override uint GetCodedIx(CIx code) {\r
5298                         switch (code) {\r
5299                                 case (CIx.HasCustomAttr) : return 0; \r
5300                                 case (CIx.HasDeclSecurity) : return 1; \r
5301                                 case (CIx.MemberRefParent) : return 3; \r
5302                                 case (CIx.MethodDefOrRef) : return 0; \r
5303                                 case (CIx.MemberForwarded) : return 1; \r
5304                                 case (CIx.CustomAttributeType) : return 2; \r
5305                                 case (CIx.TypeOrMethodDef) : return 1; \r
5306                         }\r
5307                         return 0;\r
5308     }\r
5309 \r
5310         }\r
5311   /**************************************************************************/  \r
5312         /// <summary>\r
5313         /// Descriptor for an overriding method (.override)\r
5314         /// </summary>\r
5315   public class MethodImpl : MetaDataElement\r
5316         {\r
5317     ClassDef parent;\r
5318     Method header, body;\r
5319 \r
5320                 internal MethodImpl(ClassDef par, Method decl, Method bod)      {\r
5321       parent = par;\r
5322       header = decl;\r
5323       body = bod;\r
5324                         tabIx = MDTable.MethodImpl;\r
5325                 }\r
5326 \r
5327     internal sealed override uint Size(MetaData md) {\r
5328       return md.TableIndexSize(MDTable.TypeDef) + 2 * md.CodedIndexSize(CIx.MethodDefOrRef);\r
5329     }\r
5330 \r
5331     internal sealed override void Write(FileImage output) {\r
5332       output.WriteIndex(MDTable.TypeDef,parent.Row);\r
5333       output.WriteCodedIndex(CIx.MethodDefOrRef,body);\r
5334       output.WriteCodedIndex(CIx.MethodDefOrRef,header);\r
5335     }\r
5336 \r
5337         }\r
5338   /**************************************************************************/  \r
5339         /// <summary>\r
5340         /// Descriptor for a method defined in another assembly/module\r
5341         /// </summary>\r
5342   public class MethodRef : Method\r
5343   {\r
5344     private static readonly byte Sentinel = 0x41;\r
5345                 Type[] parList, optParList;\r
5346     MetaDataElement parent;\r
5347     uint numPars = 0, numOptPars = 0;\r
5348 \r
5349     internal MethodRef(MetaDataElement paren, string name, Type retType,\r
5350         Type[] pars, bool varArgMeth, Type[] optPars) : base(name,retType) {\r
5351       parent = paren;\r
5352       parList = pars;\r
5353       if (parList != null) numPars = (uint)parList.Length;\r
5354       if (varArgMeth) {\r
5355         optParList = optPars;\r
5356         if (optParList != null) numOptPars = (uint)optParList.Length;\r
5357         callConv = CallConv.Vararg;\r
5358       }\r
5359     }\r
5360 \r
5361                 internal sealed override void TypeSig(MemoryStream sig) {\r
5362                         sig.WriteByte((byte)callConv);\r
5363                         MetaData.CompressNum(numPars+numOptPars,sig);\r
5364                         retType.TypeSig(sig);\r
5365                         for (int i=0; i < numPars; i++) {\r
5366                                 parList[i].TypeSig(sig);\r
5367                         }\r
5368       if (numOptPars > 0) {\r
5369         sig.WriteByte(Sentinel);\r
5370         for (int i=0; i < numOptPars; i++) {\r
5371           optParList[i].TypeSig(sig);\r
5372         }\r
5373       }\r
5374                 }\r
5375 \r
5376     internal sealed override void BuildTables(MetaData md) {\r
5377       if (done) return;\r
5378       nameIx = md.AddToStringsHeap(name);\r
5379       sigIx = GetSigIx(md);\r
5380       done = true;\r
5381     }\r
5382 \r
5383     internal sealed override uint Size(MetaData md) {\r
5384       return md.CodedIndexSize(CIx.MemberRefParent) + md.StringsIndexSize() + md.BlobIndexSize();\r
5385     }\r
5386 \r
5387     internal sealed override void Write(FileImage output) {\r
5388       output.WriteCodedIndex(CIx.MemberRefParent,parent);\r
5389       output.StringsIndex(nameIx);\r
5390       output.BlobIndex(sigIx);\r
5391     }\r
5392 \r
5393     internal sealed override uint GetCodedIx(CIx code) {\r
5394       switch (code) {\r
5395         case (CIx.HasCustomAttr) : return 6; \r
5396         case (CIx.MethodDefOrRef) : return 1; \r
5397         case (CIx.CustomAttributeType) : return 3; \r
5398       }\r
5399                         return 0;\r
5400     }\r
5401 \r
5402         }\r
5403   /**************************************************************************/  \r
5404         /// <summary>\r
5405         /// Descriptor for Property and Event methods\r
5406         /// </summary>\r
5407   public class MethodSemantics : MetaDataElement {\r
5408 \r
5409     Feature.MethodType type;\r
5410     MethodDef meth;\r
5411     Feature eventOrProp;\r
5412 \r
5413     internal MethodSemantics(Feature.MethodType mType, MethodDef method, Feature feature) {\r
5414       type = mType;\r
5415       meth = method;\r
5416       eventOrProp = feature;\r
5417                         tabIx = MDTable.MethodSemantics;\r
5418                 }\r
5419 \r
5420     internal sealed override uint Size(MetaData md) {\r
5421       return 2 + md.TableIndexSize(MDTable.Method) + md.CodedIndexSize(CIx.HasSemantics);\r
5422     }\r
5423 \r
5424     internal sealed override void Write(FileImage output) {\r
5425       output.Write((ushort)type);\r
5426       output.WriteIndex(MDTable.Method,meth.Row);\r
5427       output.WriteCodedIndex(CIx.HasSemantics,eventOrProp);\r
5428     }\r
5429 \r
5430         }\r
5431   /**************************************************************************/  \r
5432         /// <summary>\r
5433         /// Descriptor for a FunctionPointer type\r
5434         /// </summary>\r
5435         /// \r
5436         public class MethPtrType : Type\r
5437         {\r
5438     // MethPtrType == FNPTR\r
5439     Method method;\r
5440     uint sigIx = 0;\r
5441 \r
5442     /// <summary>\r
5443     /// Create a new function pointer type\r
5444     /// </summary>\r
5445     /// <param name="meth">the function to be referenced</param>\r
5446                 public MethPtrType(Method meth) : base(0x1B)\r
5447                 {\r
5448       method = meth;\r
5449                         tabIx = MDTable.TypeSpec;\r
5450                 }\r
5451 \r
5452     internal sealed override void TypeSig(MemoryStream str) {\r
5453       str.WriteByte(typeIndex);\r
5454       method.TypeSig(str);\r
5455     }\r
5456 \r
5457     internal sealed override void BuildTables(MetaData md) {\r
5458       if (done) return;\r
5459       MemoryStream sig = new MemoryStream();\r
5460       TypeSig(sig);\r
5461       sigIx = md.AddToBlobHeap(sig.ToArray());\r
5462       done = true;\r
5463     }\r
5464 \r
5465                 internal sealed override uint Size(MetaData md) {\r
5466                         return md.BlobIndexSize();\r
5467                 }\r
5468 \r
5469                 internal sealed override void Write(FileImage output) {\r
5470                         output.BlobIndex(sigIx);\r
5471                 }\r
5472 \r
5473                 internal sealed override uint GetCodedIx(CIx code) { return 0x1B; }\r
5474 \r
5475         }\r
5476   /**************************************************************************/  \r
5477         /// <summary>\r
5478         /// Descriptor for THIS module\r
5479         /// </summary>\r
5480   public class Module : ResolutionScope\r
5481         {\r
5482     Guid mvid;\r
5483     uint mvidIx = 0;\r
5484 \r
5485                 internal Module(string name, MetaData md) : base(name,md)       {\r
5486       mvid = Guid.NewGuid();\r
5487       mvidIx = md.AddToGUIDHeap(mvid);\r
5488       tabIx = MDTable.Module;\r
5489     }\r
5490 \r
5491     internal sealed override uint Size(MetaData md) {\r
5492       return 2 + md.StringsIndexSize() + 3 * md.GUIDIndexSize();\r
5493     }\r
5494 \r
5495     internal sealed override void Write(FileImage output) {\r
5496       output.Write((short)0);\r
5497       output.StringsIndex(nameIx);\r
5498       output.GUIDIndex(mvidIx);\r
5499       output.GUIDIndex(0);\r
5500       output.GUIDIndex(0);\r
5501     }\r
5502 \r
5503     internal sealed override uint GetCodedIx(CIx code) {\r
5504                         switch (code) {\r
5505                                 case (CIx.HasCustomAttr) : return 7; \r
5506                                 case (CIx.ResolutionScope) : return 0;\r
5507                         }\r
5508                         return 0;\r
5509     }\r
5510 \r
5511         }\r
5512   /**************************************************************************/  \r
5513         /// <summary>\r
5514         /// Descriptor for another module in THIS assembly\r
5515         /// </summary>\r
5516   public class ModuleRef : ResolutionScope\r
5517         {\r
5518 \r
5519                 internal ModuleRef(MetaData md, string name) : base(name,md) {\r
5520       tabIx = MDTable.ModuleRef;\r
5521                 }\r
5522 \r
5523     /// <summary>\r
5524     /// Add a class to this external module.  This is a class declared in\r
5525     /// another module of THIS assembly.\r
5526     /// </summary>\r
5527     /// <param name="nsName">name space name</param>\r
5528     /// <param name="name">class name</param>\r
5529     /// <returns>a descriptor for this class in another module</returns>\r
5530     public ClassRef AddClass(string nsName, string name, bool exportClass) {\r
5531       ClassRef aClass = new ClassRef(nsName,name,metaData);\r
5532       metaData.AddToTable(MDTable.TypeRef,aClass);\r
5533       aClass.SetParent(this);\r
5534       return aClass;\r
5535     }\r
5536 \r
5537     /// <summary>\r
5538     /// Make a file descriptor to correspond to this module.  The file\r
5539     /// descriptor will have the same name as the module descriptor\r
5540     /// </summary>\r
5541     /// <param name="hashBytes">the hash of the file</param>\r
5542     /// <param name="hasMetaData">the file contains metadata</param>\r
5543     /// <param name="entryPoint">the program entry point is in this file</param>\r
5544     /// <returns>a descriptor for the file which contains this module</returns>\r
5545     public FileRef MakeFile(byte[] hashBytes, bool hasMetaData, bool entryPoint) {\r
5546       FileRef file = new FileRef(nameIx,hashBytes,hasMetaData,entryPoint,metaData);\r
5547       metaData.AddToTable(MDTable.File,file);\r
5548       return file;\r
5549     }\r
5550 \r
5551     /// <summary>\r
5552     /// Add a value class to this module.  This is a class declared in\r
5553     /// another module of THIS assembly.\r
5554     /// </summary>\r
5555     /// <param name="nsName">name space name</param>\r
5556     /// <param name="name">class name</param>\r
5557     /// <returns></returns>\r
5558     public ClassRef AddValueClass(string nsName, string name) {\r
5559       ClassRef aClass = new ClassRef(nsName,name,metaData);\r
5560       metaData.AddToTable(MDTable.TypeRef,aClass);\r
5561       aClass.SetParent(this);\r
5562       aClass.MakeValueClass();\r
5563       return aClass;\r
5564     }\r
5565 \r
5566     /// <summary>\r
5567     /// Add a class which is declared public in this external module of\r
5568     /// THIS assembly.  This class will be exported from this assembly.\r
5569     /// The ilasm syntax for this is .extern class\r
5570     /// </summary>\r
5571     /// <param name="attrSet">attributes of the class to be exported</param>\r
5572     /// <param name="nsName">name space name</param>\r
5573     /// <param name="name">external class name</param>\r
5574     /// <param name="declFile">the file where the class is declared</param>\r
5575     /// <param name="isValueClass">is this class a value type?</param>\r
5576     /// <returns>a descriptor for this external class</returns>\r
5577     public ExternClassRef AddExternClass(TypeAttr attrSet, string nsName, \r
5578                                          string name, FileRef declFile, \r
5579                                          bool isValueClass) {\r
5580       ExternClassRef cRef = new ExternClassRef(attrSet,nsName,name,declFile,metaData);\r
5581       metaData.AddToTable(MDTable.TypeRef,cRef);\r
5582       cRef.SetParent(this);\r
5583       if (isValueClass) cRef.MakeValueClass();\r
5584       return cRef;\r
5585     }\r
5586 \r
5587     /// <summary>\r
5588     /// Add a "global" method in another module\r
5589     /// </summary>\r
5590     /// <param name="name">method name</param>\r
5591     /// <param name="retType">return type</param>\r
5592     /// <param name="pars">method parameter types</param>\r
5593     /// <returns>a descriptor for this method in anther module</returns>\r
5594     public MethodRef AddMethod(string name, Type retType, Type[] pars) {\r
5595       MethodRef meth = new MethodRef(this,name,retType,pars,false,null);\r
5596       metaData.AddToTable(MDTable.MemberRef,meth);\r
5597       return meth;\r
5598     }\r
5599 \r
5600     /// <summary>\r
5601     /// Add a vararg method to this class\r
5602     /// </summary>\r
5603     /// <param name="name">method name</param>\r
5604     /// <param name="retType">return type</param>\r
5605     /// <param name="pars">parameter types</param>\r
5606     /// <param name="optPars">optional param types for this vararg method</param>\r
5607     /// <returns>a descriptor for this method</returns>\r
5608     public MethodRef AddVarArgMethod(string name, Type retType, \r
5609       Type[] pars, Type[] optPars) {\r
5610       MethodRef meth = new MethodRef(this,name,retType,pars,true,optPars);\r
5611       metaData.AddToTable(MDTable.MemberRef,meth);\r
5612       return meth;\r
5613     }\r
5614 \r
5615     /// <summary>\r
5616     /// Add a field in another module\r
5617     /// </summary>\r
5618     /// <param name="name">field name</param>\r
5619     /// <param name="fType">field type</param>\r
5620     /// <returns>a descriptor for this field in another module</returns>\r
5621     public FieldRef AddField(string name, Type fType) {\r
5622       FieldRef field = new FieldRef(this,name,fType);\r
5623       metaData.AddToTable(MDTable.MemberRef,field);\r
5624       return field;\r
5625     }\r
5626 \r
5627     internal sealed override uint Size(MetaData md) {\r
5628       return md.StringsIndexSize();\r
5629     }\r
5630 \r
5631     internal sealed override void Write(FileImage output) {\r
5632       output.StringsIndex(nameIx);\r
5633     }\r
5634 \r
5635     internal sealed override uint GetCodedIx(CIx code) {\r
5636       switch (code) {\r
5637         case (CIx.HasCustomAttr) : return 12; \r
5638         case (CIx.MemberRefParent) : return 2; \r
5639         case (CIx.ResolutionScope) : return 1; \r
5640       }\r
5641                         return 0;\r
5642     }\r
5643  \r
5644   }\r
5645   /**************************************************************************/  \r
5646         /// <summary>\r
5647         /// Descriptors for native types used for marshalling\r
5648         /// </summary>\r
5649   public class NativeType {\r
5650     public static readonly NativeType Void = new NativeType(0x01);\r
5651     public static readonly NativeType Boolean = new NativeType(0x02);\r
5652     public static readonly NativeType Int8 = new NativeType(0x03);\r
5653     public static readonly NativeType UInt8 = new NativeType(0x04);\r
5654     public static readonly NativeType Int16 = new NativeType(0x05);\r
5655     public static readonly NativeType UInt16 = new NativeType(0x06);\r
5656     public static readonly NativeType Int32 = new NativeType(0x07);\r
5657     public static readonly NativeType UInt32 = new NativeType(0x08);\r
5658     public static readonly NativeType Int64 = new NativeType(0x09);\r
5659     public static readonly NativeType UInt64 = new NativeType(0x0A);\r
5660     public static readonly NativeType Float32 = new NativeType(0x0B);\r
5661     public static readonly NativeType Float64 = new NativeType(0x0C);\r
5662     public static readonly NativeType Currency = new NativeType(0x0F);\r
5663     public static readonly NativeType BStr = new NativeType(0x13);\r
5664     public static readonly NativeType LPStr = new NativeType(0x14);\r
5665     public static readonly NativeType LPWStr = new NativeType(0x15);\r
5666     public static readonly NativeType LPTStr = new NativeType(0x16);\r
5667     public static readonly NativeType FixedSysString = new NativeType(0x17);\r
5668     public static readonly NativeType IUnknown = new NativeType(0x19);\r
5669     public static readonly NativeType IDispatch = new NativeType(0x1A);\r
5670     public static readonly NativeType Struct = new NativeType(0x1B);\r
5671     public static readonly NativeType Interface = new NativeType(0x1C);\r
5672     public static readonly NativeType Int = new NativeType(0x1F);\r
5673     public static readonly NativeType UInt = new NativeType(0x20);\r
5674     public static readonly NativeType ByValStr = new NativeType(0x22);\r
5675     public static readonly NativeType AnsiBStr = new NativeType(0x23);\r
5676     public static readonly NativeType TBstr = new NativeType(0x24);\r
5677     public static readonly NativeType VariantBool = new NativeType(0x25);\r
5678     public static readonly NativeType FuncPtr = new NativeType(0x26);\r
5679     public static readonly NativeType AsAny = new NativeType(0x28);\r
5680 \r
5681     protected byte typeIndex;\r
5682 \r
5683     internal NativeType(byte tyIx) { typeIndex = tyIx; }\r
5684 \r
5685     internal byte GetTypeIndex() { return typeIndex; }\r
5686 \r
5687     internal virtual byte[] ToBlob() {\r
5688       byte[] bytes = new byte[1];\r
5689       bytes[0] = GetTypeIndex();\r
5690       return bytes;\r
5691     }\r
5692 \r
5693    }\r
5694 \r
5695   public class NativeArray : NativeType \r
5696   {\r
5697     NativeType elemType;\r
5698     uint len = 0, parNum = 0;\r
5699 \r
5700     /*\r
5701     public NativeArray(NativeType elemType) : base(0x2A) {\r
5702       this.elemType = elemType;\r
5703     }\r
5704 \r
5705     public NativeArray(NativeType elemType, int len) : base(0x2A) {\r
5706       this.elemType = elemType;\r
5707       this.len = len;\r
5708     }\r
5709 */\r
5710     public NativeArray(NativeType elemType, int numElem, int parNumForLen) : base(0x2A) {\r
5711       this.elemType = elemType;\r
5712       len = (uint)numElem;\r
5713       parNum = (uint)parNumForLen;\r
5714     }\r
5715 \r
5716     internal override byte[] ToBlob() {\r
5717       MemoryStream str = new MemoryStream();\r
5718       str.WriteByte(GetTypeIndex());\r
5719       if (elemType == null) str.WriteByte(0x50);  // no info (MAX)\r
5720       else str.WriteByte(elemType.GetTypeIndex());\r
5721       MetaData.CompressNum(parNum,str);\r
5722       str.WriteByte(1);\r
5723       MetaData.CompressNum(len,str);\r
5724       return str.ToArray();\r
5725     }\r
5726 \r
5727   }\r
5728 \r
5729   public class SafeArray : NativeType \r
5730   {\r
5731     SafeArrayType elemType;\r
5732 \r
5733     public SafeArray(SafeArrayType elemType) : base(0x1D) {\r
5734       this.elemType = elemType;\r
5735     }\r
5736 \r
5737     internal override byte[] ToBlob() {\r
5738       byte[] bytes = new byte[2];\r
5739       bytes[0] = GetTypeIndex();\r
5740       bytes[1] = (byte)elemType;\r
5741       return bytes;\r
5742     }\r
5743 \r
5744   }\r
5745 \r
5746   public class FixedArray : NativeType \r
5747   {\r
5748     NativeType elemType;\r
5749     uint numElem;\r
5750 \r
5751     public FixedArray(NativeType elemType, int numElems) : base(0x1E) {\r
5752       this.elemType = elemType;\r
5753       numElem = (uint)numElems;\r
5754     }\r
5755 \r
5756     internal override byte[] ToBlob() {\r
5757       MemoryStream str = new MemoryStream();\r
5758       str.WriteByte(GetTypeIndex());\r
5759       MetaData.CompressNum(numElem,str);\r
5760       if (elemType == null) str.WriteByte(0x50);  // no info (MAX)\r
5761       else str.WriteByte(elemType.GetTypeIndex());\r
5762       return str.ToArray();\r
5763     }\r
5764 \r
5765   }\r
5766 \r
5767   public class CustomMarshaller : NativeType \r
5768   {\r
5769     string typeName;\r
5770     string marshallerName;\r
5771     string cookie;\r
5772 \r
5773     public CustomMarshaller(string typeNameOrGUID, string marshallerName, \r
5774                 string optCookie) : base(0x2C) {\r
5775       typeName = typeNameOrGUID;\r
5776       this.marshallerName = marshallerName;\r
5777       cookie = optCookie;\r
5778     }\r
5779 \r
5780     internal override byte[] ToBlob() {\r
5781       MemoryStream str = new MemoryStream();\r
5782       BinaryWriter bw = new BinaryWriter(str,new UTF8Encoding());\r
5783       bw.Write(GetTypeIndex());\r
5784       bw.Write(typeName.ToCharArray());\r
5785       bw.Write((byte)0);\r
5786       bw.Write(marshallerName.ToCharArray());\r
5787       bw.Write((byte)0);\r
5788       if (cookie != null) bw.Write(cookie.ToCharArray());\r
5789       bw.Write((byte)0);\r
5790       bw.Flush();\r
5791       return str.ToArray();\r
5792     }\r
5793   }\r
5794 \r
5795   /**************************************************************************/  \r
5796         /// <summary>\r
5797         /// Descriptor for a parameter of a method defined in this assembly/module\r
5798         /// </summary>\r
5799   public class Param : MetaDataElement\r
5800         {\r
5801     private static readonly ushort hasDefault = 0x1000;\r
5802     private static readonly ushort hasFieldMarshal = 0x2000;\r
5803 \r
5804     Type pType;\r
5805     string pName;\r
5806     internal ushort seqNo = 0;\r
5807     ushort parMode;\r
5808     ConstantElem defaultVal;\r
5809     uint nameIx = 0;\r
5810     FieldMarshal marshalInfo;\r
5811 \r
5812     /// <summary>\r
5813     /// Create a new parameter for a method\r
5814     /// </summary>\r
5815     /// <param name="mode">param mode (in, out, opt)</param>\r
5816     /// <param name="parName">parameter name</param>\r
5817     /// <param name="parType">parameter type</param>\r
5818     public Param(ParamAttr mode, string parName, Type parType) {\r
5819       pName = parName;\r
5820       pType = parType;\r
5821       parMode = (ushort)mode;\r
5822                         tabIx = MDTable.Param;\r
5823                 }\r
5824 \r
5825     /// <summary>\r
5826     /// Add a default value to this parameter\r
5827     /// </summary>\r
5828     /// <param name="c">the default value for the parameter</param>\r
5829     public void AddDefaultValue(Constant cVal) {\r
5830       defaultVal = new ConstantElem(this,cVal);\r
5831       parMode |= hasDefault;\r
5832     }\r
5833 \r
5834     /// <summary>\r
5835     /// Add marshalling information about this parameter\r
5836     /// </summary>\r
5837     public void AddMarshallInfo(NativeType marshallType) {\r
5838       parMode |= hasFieldMarshal;\r
5839       marshalInfo = new FieldMarshal(this,marshallType);\r
5840     }\r
5841 \r
5842     internal Type GetParType() { return pType; }\r
5843 \r
5844     internal sealed override void BuildTables(MetaData md) {\r
5845       if (done) return;\r
5846       nameIx = md.AddToStringsHeap(pName);\r
5847       if (defaultVal != null) {\r
5848         md.AddToTable(MDTable.Constant,defaultVal);\r
5849         defaultVal.BuildTables(md);\r
5850       }\r
5851       if (marshalInfo != null) {\r
5852         md.AddToTable(MDTable.FieldMarshal,marshalInfo);\r
5853         marshalInfo.BuildTables(md);\r
5854       }\r
5855       done = true;\r
5856     }\r
5857 \r
5858     internal void TypeSig(MemoryStream str) {\r
5859       pType.TypeSig(str);\r
5860     }\r
5861 \r
5862     internal sealed override uint Size(MetaData md) {\r
5863       return 4 + md.StringsIndexSize();\r
5864     }\r
5865 \r
5866     internal sealed override void Write(FileImage output) {\r
5867       output.Write(parMode);\r
5868       output.Write(seqNo);\r
5869       output.StringsIndex(nameIx);\r
5870     }\r
5871 \r
5872     internal sealed override uint GetCodedIx(CIx code) {\r
5873       switch (code) {\r
5874         case (CIx.HasCustomAttr) : return 4; \r
5875         case (CIx.HasConst) : return 1; \r
5876         case (CIx.HasFieldMarshal) : return 1; \r
5877       }\r
5878                         return 0;\r
5879     }\r
5880 \r
5881         }\r
5882   /**************************************************************************/  \r
5883         /// <summary>\r
5884         /// Base class for the PEFile (starting point)\r
5885         /// </summary>\r
5886   public class PEFile\r
5887         {\r
5888     private static readonly string mscorlibName = "mscorlib";\r
5889     private Module thisMod;\r
5890     private ClassDef moduleClass;\r
5891     private ArrayList classRefList = new ArrayList();\r
5892     private ArrayList classDefList = new ArrayList();\r
5893     private Assembly thisAssembly;\r
5894     private int corFlags = 1;\r
5895     FileImage fileImage;\r
5896                 MetaData metaData;\r
5897 \r
5898     /// <summary>\r
5899     /// Create a new PEFile.  Each PEFile is a module.\r
5900     /// </summary>\r
5901     /// <param name="name">module name, also used for the file name</param>\r
5902     /// <param name="isDLL">create a .dll or .exe file</param>\r
5903     /// <param name="hasAssembly">this file is an assembly and \r
5904     /// will contain the assembly manifest.  The assembly name is the \r
5905     /// same as the module name</param>\r
5906     public PEFile(string name, bool isDLL, bool hasAssembly) {\r
5907       // Console.WriteLine(Hex.Byte(0x12));\r
5908       // Console.WriteLine(Hex.Short(0x1234));\r
5909       // Console.WriteLine(Hex.Int(0x12345678));\r
5910       string fName = MakeFileName(null,name,isDLL);\r
5911       fileImage = new FileImage(isDLL,fName);\r
5912       InitPEFile(name, fName, hasAssembly);\r
5913     }\r
5914 \r
5915     /// <summary>\r
5916     /// Create a new PEFile.  Each PEFile is a module.\r
5917     /// </summary>\r
5918     /// <param name="name">module name, also used for the file name</param>\r
5919     /// <param name="isDLL">create a .dll or .exe file</param>\r
5920     /// <param name="hasAssembly">this file is an assembly and \r
5921     /// will contain the assembly manifest.  The assembly name is the \r
5922     /// same as the module name</param>\r
5923     /// <param name="outputDir">write the PEFile to this directory.  If this\r
5924     /// string is null then the output will be to the current directory</param>\r
5925     public PEFile(string name, bool isDLL, bool hasAssembly, string outputDir) {\r
5926       // Console.WriteLine(Hex.Byte(0x12));\r
5927       // Console.WriteLine(Hex.Short(0x1234));\r
5928       // Console.WriteLine(Hex.Int(0x12345678));\r
5929       string fName = MakeFileName(outputDir,name,isDLL);\r
5930                         fileImage = new FileImage(isDLL,fName);\r
5931       InitPEFile(name, fName, hasAssembly);\r
5932     }\r
5933 \r
5934     /// <summary>\r
5935     /// Create a new PEFile\r
5936     /// </summary>\r
5937     /// <param name="name">module name</param>\r
5938     /// <param name="isDLL">create a .dll or .exe</param>\r
5939     /// <param name="hasAssembly">this PEfile is an assembly and\r
5940     /// will contain the assemly manifest.  The assembly name is the\r
5941     /// same as the module name</param>\r
5942     /// <param name="outStream">write the PEFile to this stream instead\r
5943     /// of to a new file</param>\r
5944     public PEFile(string name, bool isDLL, bool hasAssembly, Stream outStream) {\r
5945       fileImage = new FileImage(isDLL,outStream);\r
5946       InitPEFile(name, MakeFileName(null,name,isDLL), hasAssembly);\r
5947     }\r
5948 \r
5949     private void InitPEFile(string name, string fName, bool hasAssembly) {\r
5950       metaData = fileImage.GetMetaData();\r
5951       thisMod = new Module(fName,metaData);\r
5952       if (hasAssembly) {\r
5953         thisAssembly = new Assembly(name,metaData);\r
5954         metaData.AddToTable(MDTable.Assembly,thisAssembly);      \r
5955       }\r
5956       moduleClass = AddClass(TypeAttr.Private,"","<Module>");\r
5957       moduleClass.SpecialNoSuper();\r
5958       metaData.AddToTable(MDTable.Module,thisMod);\r
5959     }\r
5960  \r
5961
5962     public ClassDef ModuleClass {
5963             get { return moduleClass; }
5964     }
5965
5966     /// <summary>\r
5967     /// Set the subsystem (.subsystem) (Default is Windows Console mode)\r
5968     /// </summary>\r
5969     /// <param name="subS">subsystem value</param>\r
5970     public void SetSubSystem(SubSystem subS) {\r
5971       fileImage.subSys = subS;\r
5972     }\r
5973 \r
5974     /// <summary>\r
5975     /// Set the flags (.corflags)\r
5976     /// </summary>\r
5977     /// <param name="flags">the flags value</param>\r
5978     public void SetCorFlags(int flags) {\r
5979       corFlags = flags;\r
5980     }\r
5981 \r
5982     private string MakeFileName(string dirName, string name, bool isDLL) {\r
5983       string result = "";\r
5984       if ((dirName != null) && (dirName.CompareTo("") != 0)) {\r
5985         result = dirName;\r
5986         if (!dirName.EndsWith("\\")) result += "\\";\r
5987       }\r
5988       result += name;\r
5989        \r
5990       // if (isDLL) result += ".dll";  else result += ".exe";\r
5991       \r
5992       return result;\r
5993     }\r
5994 \r
5995     /// <summary>\r
5996     /// Add an external assembly to this PEFile (.assembly extern)\r
5997     /// </summary>\r
5998     /// <param name="assemName">the external assembly name</param>\r
5999     /// <returns>a descriptor for this external assembly</returns>\r
6000     public AssemblyRef AddExternAssembly(string assemName) {\r
6001       if (assemName.CompareTo(mscorlibName) == 0) return metaData.mscorlib;\r
6002       AssemblyRef anAssem = new AssemblyRef(metaData,assemName);\r
6003       metaData.AddToTable(MDTable.AssemblyRef,anAssem);\r
6004       // Console.WriteLine("Adding assembly " + assemName);\r
6005       return anAssem;\r
6006     }\r
6007 \r
6008     /// <summary>\r
6009     /// Add an external module to this PEFile (.module extern)\r
6010     /// </summary>\r
6011     /// <param name="name">the external module name</param>\r
6012     /// <returns>a descriptor for this external module</returns>\r
6013     public ModuleRef AddExternModule(string name) {\r
6014       ModuleRef modRef = new ModuleRef(metaData,name);\r
6015       metaData.AddToTable(MDTable.ModuleRef,modRef);\r
6016       return modRef;\r
6017     }\r
6018 \r
6019     /// <summary>\r
6020     /// Add a "global" method to this module\r
6021     /// </summary>\r
6022     /// <param name="name">method name</param>\r
6023     /// <param name="retType">return type</param>\r
6024     /// <param name="pars">method parameters</param>\r
6025     /// <returns>a descriptor for this new "global" method</returns>\r
6026     public MethodDef AddMethod(string name, Type retType, Param[] pars) {\r
6027       return moduleClass.AddMethod(name,retType,pars);\r
6028     }\r
6029 \r
6030     /// <summary>\r
6031     /// Add a "global" method to this module\r
6032     /// </summary>\r
6033     /// <param name="mAtts">method attributes</param>\r
6034     /// <param name="iAtts">method implementation attributes</param>\r
6035     /// <param name="name">method name</param>\r
6036     /// <param name="retType">return type</param>\r
6037     /// <param name="pars">method parameters</param>\r
6038     /// <returns>a descriptor for this new "global" method</returns>\r
6039     public MethodDef AddMethod(MethAttr mAtts, ImplAttr iAtts, string name, Type retType, Param[] pars) {\r
6040       return moduleClass.AddMethod(mAtts,iAtts,name,retType,pars);\r
6041     }\r
6042 \r
6043     public MethodRef AddMethodToTypeSpec (Type item, string name, Type retType, Type[] pars) {\r
6044             MethodRef meth = new MethodRef (item.GetTypeSpec (metaData), name, retType, pars, false, null);\r
6045             metaData.AddToTable (MDTable.MemberRef,meth);\r
6046             return meth;\r
6047     }\r
6048 \r
6049     public MethodRef AddVarArgMethodToTypeSpec (Type item, string name, Type retType,\r
6050                     Type[] pars, Type[] optPars) {\r
6051             MethodRef meth = new MethodRef(item.GetTypeSpec (metaData), name,retType,pars,true,optPars);\r
6052             metaData.AddToTable(MDTable.MemberRef,meth);\r
6053             return meth;\r
6054     }\r
6055 \r
6056     public FieldRef AddFieldToTypeSpec (Type item, string name, Type fType) {\r
6057             FieldRef field = new FieldRef (item.GetTypeSpec (metaData), name,fType);\r
6058             metaData.AddToTable (MDTable.MemberRef,field);\r
6059             return field;\r
6060     }\r
6061 \r
6062     public void AddMethodSpec (Method m, GenericMethodSig g_sig)
6063     {
6064             MethodSpec ms = new MethodSpec (m, g_sig);
6065             metaData.AddToTable (MDTable.MethodSpec, ms);
6066     }
6067
6068     /// <summary>\r
6069     /// Add a "global" field to this module\r
6070     /// </summary>\r
6071     /// <param name="name">field name</param>\r
6072     /// <param name="fType">field type</param>\r
6073     /// <returns>a descriptor for this new "global" field</returns>\r
6074     public FieldDef AddField(string name, Type fType) {\r
6075       return moduleClass.AddField(name,fType);\r
6076     }\r
6077 \r
6078     /// <summary>\r
6079     /// Add a "global" field to this module\r
6080     /// </summary>\r
6081     /// <param name="attrSet">attributes of this field</param>\r
6082     /// <param name="name">field name</param>\r
6083     /// <param name="fType">field type</param>\r
6084     /// <returns>a descriptor for this new "global" field</returns>\r
6085     public FieldDef AddField(FieldAttr attrSet, string name, Type fType) {\r
6086       return moduleClass.AddField(attrSet,name,fType);\r
6087     }\r
6088 \r
6089     /// <summary>\r
6090     /// Add a class to this module\r
6091     /// </summary>\r
6092     /// <param name="attrSet">attributes of this class</param>\r
6093     /// <param name="nsName">name space name</param>\r
6094     /// <param name="name">class name</param>\r
6095     /// <returns>a descriptor for this new class</returns>\r
6096     public ClassDef AddClass(TypeAttr attrSet, string nsName, string name) {\r
6097       ClassDef aClass = new ClassDef(attrSet,nsName,name,metaData);\r
6098       metaData.AddToTable(MDTable.TypeDef,aClass);\r
6099       return aClass;\r
6100     }\r
6101 \r
6102     /// <summary>\r
6103     /// Add a class which extends System.ValueType to this module\r
6104     /// </summary>\r
6105     /// <param name="attrSet">attributes of this class</param>\r
6106     /// <param name="nsName">name space name</param>\r
6107     /// <param name="name">class name</param>\r
6108     /// <returns>a descriptor for this new class</returns>\r
6109     public ClassDef AddValueClass(TypeAttr attrSet, string nsName, string name) {\r
6110       ClassDef aClass = new ClassDef(attrSet,nsName,name,metaData);\r
6111       aClass.MakeValueClass();\r
6112       metaData.AddToTable(MDTable.TypeDef,aClass);\r
6113       return aClass;\r
6114     }\r
6115 \r
6116     /// <summary>\r
6117     /// Add a class to this module\r
6118     /// </summary>\r
6119     /// <param name="attrSet">attributes of this class</param>\r
6120     /// <param name="nsName">name space name</param>\r
6121     /// <param name="name">class name</param>\r
6122     /// <param name="superType">super type of this class (extends)</param>\r
6123     /// <returns>a descriptor for this new class</returns>\r
6124     public ClassDef AddClass(TypeAttr attrSet, string nsName, string name, Class superType) {\r
6125       ClassDef aClass = new ClassDef(attrSet,nsName,name,metaData);\r
6126       aClass.SetSuper(superType);\r
6127       metaData.AddToTable(MDTable.TypeDef,aClass);\r
6128       return aClass;\r
6129     }\r
6130 \r
6131     public FileRef AddFile(string fName, byte[] hashBytes, bool hasMetaData, bool entryPoint) {\r
6132       FileRef file = new FileRef(fName,hashBytes,hasMetaData,entryPoint,metaData);\r
6133       metaData.AddToTable(MDTable.File,file);\r
6134       return file;\r
6135     }\r
6136 \r
6137     /// <summary>\r
6138     /// Add a manifest resource to this PEFile NOT YET IMPLEMENTED\r
6139     /// </summary>\r
6140     /// <param name="mr"></param>\r
6141     public void AddManifestResource(ManifestResource mr) {\r
6142       metaData.AddToTable(MDTable.ManifestResource,mr);\r
6143       //mr.FixName(metaData);\r
6144     }\r
6145 \r
6146     /// <summary>\r
6147     /// Write out the PEFile (the "bake" function)\r
6148     /// </summary>\r
6149     public void WritePEFile() { /* the "bake" function */\r
6150       fileImage.MakeFile();\r
6151     }\r
6152 \r
6153     /// <summary>\r
6154     /// Get the descriptor of this module\r
6155     /// </summary>\r
6156     /// <returns>the descriptor for this module</returns>\r
6157     public Module GetThisModule() {\r
6158       return thisMod;\r
6159     }\r
6160 \r
6161     /// <summary>\r
6162     /// Get the descriptor for this assembly.  The PEFile must have been\r
6163     /// created with hasAssembly = true\r
6164     /// </summary>\r
6165     /// <returns>the descriptor for this assembly</returns>\r
6166     public Assembly GetThisAssembly() {\r
6167       return thisAssembly;\r
6168     }\r
6169 \r
6170         }\r
6171 \r
6172   /**************************************************************************/  \r
6173         /// <summary>\r
6174         /// Descriptor for the Primitive types defined in IL\r
6175         /// </summary>\r
6176   public class PrimitiveType : Type\r
6177         {\r
6178     private string name;\r
6179     private int systemTypeIndex;\r
6180     public static int NumSystemTypes = 18;\r
6181 \r
6182     public static readonly PrimitiveType Void = new PrimitiveType(0x01,"Void",0);\r
6183     public static readonly PrimitiveType Boolean = new PrimitiveType(0x02,"Boolean",1);\r
6184     public static readonly PrimitiveType Char = new PrimitiveType(0x03,"Char",2);\r
6185     public static readonly PrimitiveType Int8 = new PrimitiveType(0x04,"SByte",3);\r
6186     public static readonly PrimitiveType UInt8 = new PrimitiveType(0x05,"Byte",4);\r
6187     public static readonly PrimitiveType Int16 = new PrimitiveType(0x06,"Int16",5);\r
6188     public static readonly PrimitiveType UInt16 = new PrimitiveType(0x07,"UInt16",6);\r
6189     public static readonly PrimitiveType Int32 = new PrimitiveType(0x08,"Int32",7);\r
6190     public static readonly PrimitiveType UInt32 = new PrimitiveType(0x09,"UInt32",8);\r
6191     public static readonly PrimitiveType Int64 = new PrimitiveType(0x0A,"Int64",9);\r
6192     public static readonly PrimitiveType UInt64 = new PrimitiveType(0x0B,"UInt64",10);\r
6193     public static readonly PrimitiveType Float32 = new PrimitiveType(0x0C,"Single",11);\r
6194     public static readonly PrimitiveType Float64 = new PrimitiveType(0x0D,"Double",12);\r
6195     public static readonly PrimitiveType String = new PrimitiveType(0x0E,"String",13);\r
6196                 internal static readonly PrimitiveType Class = new PrimitiveType(0x12);\r
6197     public static readonly PrimitiveType TypedRef = new PrimitiveType(0x16,"TypedReference",14);\r
6198     public static readonly PrimitiveType IntPtr = new PrimitiveType(0x18,"IntPtr",15);\r
6199     public static readonly PrimitiveType UIntPtr = new PrimitiveType(0x19,"UIntPtr",16);\r
6200     public static readonly PrimitiveType Object = new PrimitiveType(0x1C,"Object",17);\r
6201     internal static readonly PrimitiveType ClassType = new PrimitiveType(0x50);\r
6202     public static readonly PrimitiveType NativeInt = IntPtr;\r
6203     public static readonly PrimitiveType NativeUInt = UIntPtr;\r
6204 \r
6205     internal PrimitiveType(byte typeIx) : base(typeIx) { }\r
6206 \r
6207                 internal PrimitiveType(byte typeIx, string name, int STIx) : base(typeIx) {\r
6208       this.name = name;\r
6209       this.systemTypeIndex = STIx;\r
6210     }\r
6211 \r
6212     internal string GetName() { return name; }\r
6213 \r
6214     internal int GetSystemTypeIx() { return systemTypeIndex; }\r
6215 \r
6216     internal sealed override void TypeSig(MemoryStream str) {\r
6217       str.WriteByte(typeIndex);\r
6218     }\r
6219 \r
6220     internal override MetaDataElement GetTypeSpec(MetaData md) {\r
6221       TypeSpec tS = md.GetPrimitiveTypeSpec(systemTypeIndex);\r
6222       if (tS == null) {\r
6223         tS = new TypeSpec(this,md);\r
6224         md.SetPrimitiveTypeSpec(systemTypeIndex,tS);\r
6225         md.AddToTable(MDTable.TypeSpec,tS);\r
6226       }\r
6227       return tS;\r
6228     }\r
6229 \r
6230         }\r
6231 \r
6232   /**************************************************************************/  \r
6233         /// <summary>\r
6234         /// Descriptor for the Property of a class\r
6235         /// </summary>\r
6236   public class Property : Feature\r
6237         {\r
6238     private static readonly byte PropertyTag = 0x8;\r
6239     MethodDef getterMeth;\r
6240     ConstantElem constVal;\r
6241     uint typeBlobIx = 0;\r
6242     Type[] parList;\r
6243     Type returnType;\r
6244     uint numPars = 0;\r
6245 \r
6246     internal Property(string name, Type retType, Type[] pars, ClassDef parent) : base(name, parent) {\r
6247       returnType = retType;\r
6248       parList = pars;\r
6249       if (pars != null) numPars = (uint)pars.Length;\r
6250                         tabIx = MDTable.Property;\r
6251                 }\r
6252 \r
6253     /// <summary>\r
6254     /// Add a set method to this property\r
6255     /// </summary>\r
6256     /// <param name="setter">the set method</param>\r
6257     public void AddSetter(MethodDef setter) {\r
6258       AddMethod(setter,MethodType.Setter);\r
6259     }\r
6260 \r
6261     /// <summary>\r
6262     /// Add a get method to this property\r
6263     /// </summary>\r
6264     /// <param name="getter">the get method</param>\r
6265     public void AddGetter(MethodDef getter) {\r
6266       AddMethod(getter,MethodType.Getter);\r
6267       getterMeth = getter;\r
6268     }\r
6269 \r
6270     /// <summary>\r
6271     /// Add another method to this property\r
6272     /// </summary>\r
6273     /// <param name="other">the method</param>\r
6274     public void AddOther(MethodDef other) {\r
6275       AddMethod(other,MethodType.Other);\r
6276     }\r
6277 \r
6278     /// <summary>\r
6279     /// Add an initial value for this property\r
6280     /// </summary>\r
6281     /// <param name="constVal">the initial value for this property</param>\r
6282     public void AddInitValue(Constant constVal) {\r
6283       this.constVal = new ConstantElem(this,constVal);\r
6284     }\r
6285 \r
6286     internal sealed override void BuildTables(MetaData md) {\r
6287       if (done) return;\r
6288       nameIx = md.AddToStringsHeap(name);\r
6289       MemoryStream sig = new MemoryStream();\r
6290       sig.WriteByte(PropertyTag);\r
6291       MetaData.CompressNum(numPars,sig);\r
6292       returnType.TypeSig(sig);\r
6293       for (int i=0; i < numPars; i++) {\r
6294         parList[i].TypeSig(sig);\r
6295       }\r
6296       typeBlobIx = md.AddToBlobHeap(sig.ToArray());\r
6297       for (int i=0; i < tide; i++) {\r
6298         md.AddToTable(MDTable.MethodSemantics,methods[i]);\r
6299       }\r
6300       if (constVal != null) {\r
6301         md.AddToTable(MDTable.Constant,constVal);\r
6302         constVal.BuildTables(md);\r
6303       }\r
6304       done = true;\r
6305     }\r
6306 \r
6307     internal sealed override uint Size(MetaData md) {\r
6308       return 2 + md.StringsIndexSize() + md.BlobIndexSize();\r
6309     }\r
6310 \r
6311     internal sealed override void Write(FileImage output) {\r
6312       output.Write(flags);\r
6313       output.StringsIndex(nameIx);\r
6314       output.BlobIndex(typeBlobIx);\r
6315     }\r
6316 \r
6317     internal sealed override uint GetCodedIx(CIx code) {\r
6318                         switch (code) {\r
6319                                 case (CIx.HasCustomAttr) : return 9; \r
6320                                 case (CIx.HasConst) : return 2; \r
6321                                 case (CIx.HasSemantics) : return 1; \r
6322                         }\r
6323                         return 0;\r
6324     }\r
6325 \r
6326         }\r
6327   /**************************************************************************/  \r
6328         /// <summary>\r
6329         /// Descriptor for an pointer (type * or type &)\r
6330         /// </summary>\r
6331   public abstract class PtrType : Type\r
6332         {\r
6333     Type baseType;\r
6334 \r
6335                 internal PtrType(Type bType, byte typeIx) : base(typeIx)\r
6336                 {\r
6337       baseType = bType;\r
6338       tabIx = MDTable.TypeSpec;\r
6339                 }\r
6340 \r
6341     internal sealed override void TypeSig(MemoryStream str) {\r
6342       str.WriteByte(typeIndex);\r
6343       baseType.TypeSig(str);\r
6344     }\r
6345 \r
6346         }\r
6347   /**************************************************************************/  \r
6348   /// <summary>\r
6349   /// Descriptor for a managed pointer (type &  or byref)\r
6350   /// </summary>\r
6351 \r
6352   public class ManagedPointer : PtrType  // <type> & (BYREF)  \r
6353   {\r
6354 \r
6355     /// <summary>\r
6356     /// Create new managed pointer to baseType\r
6357     /// </summary>\r
6358     /// <param name="bType">the base type of the pointer</param>\r
6359     public ManagedPointer(Type baseType) : base(baseType,0x10) { }\r
6360  \r
6361   }\r
6362   /**************************************************************************/  \r
6363   /// <summary>\r
6364   /// Descriptor for an unmanaged pointer (type *)\r
6365   /// </summary>\r
6366   public class UnmanagedPointer : PtrType // PTR\r
6367   {\r
6368     /// <summary>\r
6369     /// Create a new unmanaged pointer to baseType\r
6370     /// </summary>\r
6371     /// <param name="baseType">the base type of the pointer</param>\r
6372     public UnmanagedPointer(Type baseType) : base(baseType, 0x0F) { }\r
6373 \r
6374   }\r
6375   /**************************************************************************/  \r
6376         /// <summary>\r
6377         /// Base class for scopes (extended by Module, ModuleRef, Assembly, AssemblyRef)\r
6378         /// </summary>\r
6379   public abstract class ResolutionScope : MetaDataElement\r
6380         {\r
6381     protected uint nameIx = 0;\r
6382     protected MetaData metaData;\r
6383     protected string name;\r
6384 \r
6385                 internal ResolutionScope(string name, MetaData md)\r
6386                 {\r
6387       metaData = md;\r
6388       this.name = name;\r
6389       nameIx = md.AddToStringsHeap(name);\r
6390                 }\r
6391 \r
6392     internal string GetName() { return name; }\r
6393 \r
6394         }\r
6395   /**************************************************************************/  \r
6396         /// <summary>\r
6397         /// Descriptor for a Section in a PEFile  eg .text, .sdata\r
6398         /// </summary>\r
6399   internal class Section {\r
6400                 private static readonly uint relocPageSize = 4096;  // 4K pages for fixups\r
6401 \r
6402                 char[] name; \r
6403                 uint offset = 0, tide = 0, size = 0, rva = 0, relocTide = 0;\r
6404                 //uint relocOff = 0;\r
6405     uint flags = 0, padding = 0;\r
6406                 uint[] relocs; \r
6407 \r
6408                 internal Section(string sName, uint sFlags) {
6409                   name = sName.ToCharArray();\r
6410                   flags = sFlags;\r
6411                 }
6412 \r
6413                 internal uint Tide() { return tide; }\r
6414 \r
6415                 internal void IncTide(uint incVal) { tide += incVal; }\r
6416 \r
6417                 internal uint Padding() { return padding; }\r
6418 \r
6419                 internal uint Size() { return size; }\r
6420 \r
6421                 internal void SetSize(uint pad) {\r
6422                         padding = pad;\r
6423                         size = tide + padding;\r
6424                 }\r
6425 \r
6426                 internal uint RVA() { return rva; }\r
6427 \r
6428                 internal void SetRVA(uint rva) { this.rva = rva; }\r
6429 \r
6430                 internal uint Offset() { return offset; }\r
6431 \r
6432                 internal void SetOffset(uint offs) { offset = offs; }\r
6433 \r
6434     internal void DoBlock(BinaryWriter reloc, uint page, int start, int end) {\r
6435       //Console.WriteLine("rva = " + rva + "  page = " + page);\r
6436       reloc.Write(rva + page);\r
6437       reloc.Write((uint)(((end-start+1)*2) + 8));\r
6438       for (int j=start; j < end; j++) {\r
6439         //Console.WriteLine("reloc offset = " + relocs[j]);\r
6440         reloc.Write((ushort)((0x3 << 12) | (relocs[j] - page)));\r
6441       }\r
6442       reloc.Write((ushort)0);\r
6443     }\r
6444 \r
6445                 internal void DoRelocs(BinaryWriter reloc) {\r
6446       if (relocTide > 0) {\r
6447         //relocOff = (uint)reloc.Seek(0,SeekOrigin.Current);\r
6448         uint block = (relocs[0]/relocPageSize + 1) * relocPageSize;\r
6449         int start = 0;\r
6450         for (int i=1; i < relocTide; i++) {\r
6451           if (relocs[i] >= block) {\r
6452             DoBlock(reloc,block-relocPageSize,start,i);\r
6453             start = i;\r
6454             block = (relocs[i]/relocPageSize + 1) * relocPageSize;\r
6455           }\r
6456         }\r
6457         DoBlock(reloc,block-relocPageSize,start,(int)relocTide);\r
6458       }\r
6459                 }\r
6460 \r
6461                 internal void AddReloc(uint offs) {\r
6462                         int pos = 0;\r
6463                         if (relocs == null) {\r
6464                                 relocs = new uint[5];\r
6465                         } else {\r
6466                                 if (relocTide >= relocs.Length) {\r
6467                                         uint[] tmp = relocs;\r
6468                                         relocs = new uint[tmp.Length + 5];\r
6469                                         for (int i=0; i < relocTide; i++) {\r
6470                                                 relocs[i] = tmp[i];\r
6471                                         }\r
6472                                 }\r
6473                                 while ((pos < relocTide) && (relocs[pos] < offs)) pos++;\r
6474                                 for (int i=pos; i < relocTide; i++) {\r
6475                                         relocs[i+1] = relocs[i];\r
6476                                 }\r
6477                         }\r
6478                         relocs[pos] = offs;\r
6479                         relocTide++;    \r
6480                 }\r
6481       \r
6482                 internal void WriteHeader(BinaryWriter output, uint relocRVA) {\r
6483                         output.Write(name);\r
6484                         output.Write(tide);\r
6485                         output.Write(rva);\r
6486                         output.Write(size);\r
6487                         output.Write(offset);\r
6488                         output.Write(0);\r
6489                         //output.Write(relocRVA + relocOff);\r
6490                         output.Write(0);\r
6491       output.Write(0);\r
6492                         //output.Write((ushort)relocTide);\r
6493                         //output.Write((ushort)0);\r
6494                         output.Write(flags);\r
6495                 }\r
6496 \r
6497         }\r
6498   /**************************************************************************/  \r
6499   public abstract class Signature : MetaDataElement \r
6500   {\r
6501     protected uint sigIx;\r
6502 \r
6503     internal Signature() {\r
6504       tabIx = MDTable.StandAloneSig;\r
6505     }\r
6506 \r
6507     internal sealed override uint Size(MetaData md) {\r
6508       return md.BlobIndexSize();\r
6509     }\r
6510 \r
6511     internal sealed override void Write(FileImage output) {\r
6512       output.BlobIndex(sigIx);\r
6513     }\r
6514 \r
6515     internal sealed override uint GetCodedIx(CIx code) { return (uint)tabIx; }\r
6516 \r
6517   }\r
6518   /**************************************************************************/  \r
6519         /// <summary>\r
6520         /// Descriptor for a class defined in System (mscorlib)\r
6521         /// </summary>\r
6522   internal class SystemClass : ClassRef\r
6523         {\r
6524     PrimitiveType elemType; \r
6525 \r
6526                 internal SystemClass(PrimitiveType eType, AssemblyRef paren, MetaData md)\r
6527                                     : base("System",eType.GetName(),md) {\r
6528       elemType = eType;\r
6529       parent = paren;\r
6530                 }\r
6531 \r
6532     internal override sealed MetaDataElement GetTypeSpec(MetaData md) {\r
6533       if (typeSpec == null) typeSpec = (TypeSpec)elemType.GetTypeSpec(md);\r
6534       return typeSpec;\r
6535     }\r
6536 \r
6537 \r
6538     internal sealed override void TypeSig(MemoryStream str) {\r
6539         str.WriteByte(elemType.GetTypeIndex());\r
6540     }\r
6541 \r
6542         }\r
6543   /**************************************************************************/  \r
6544         /// <summary>\r
6545         /// Base class for all IL types\r
6546         /// </summary>\r
6547   public abstract class Type : MetaDataElement {\r
6548     protected byte typeIndex;\r
6549     protected TypeSpec typeSpec;\r
6550 \r
6551     internal Type(byte tyIx) { typeIndex = tyIx; }\r
6552 \r
6553     internal byte GetTypeIndex() { return typeIndex; }\r
6554 \r
6555     internal virtual MetaDataElement GetTypeSpec(MetaData md) {\r
6556       if (typeSpec == null) {\r
6557         typeSpec = new TypeSpec(this,md);\r
6558         md.AddToTable(MDTable.TypeSpec,typeSpec);\r
6559       }\r
6560       return typeSpec;\r
6561     }\r
6562  \r
6563     internal virtual void TypeSig(MemoryStream str) {\r
6564       throw(new TypeSignatureException(this.GetType().AssemblyQualifiedName +\r
6565         " doesn't have a type signature!!"));   \r
6566     }\r
6567 \r
6568   }\r
6569 \r
6570   /**************************************************************************/  \r
6571 \r
6572   public class TypeSpec : MetaDataElement {\r
6573     uint sigIx = 0;\r
6574 \r
6575     internal TypeSpec(Type aType, MetaData md) {\r
6576       MemoryStream sig = new MemoryStream();\r
6577       aType.TypeSig(sig);\r
6578       sigIx = md.AddToBlobHeap(sig.ToArray());\r
6579       tabIx = MDTable.TypeSpec;\r
6580     }\r
6581 \r
6582     internal sealed override uint GetCodedIx(CIx code) {\r
6583       switch (code) {\r
6584         case (CIx.TypeDefOrRef) : return 2; \r
6585         case (CIx.HasCustomAttr) : return 13; \r
6586         case (CIx.MemberRefParent) : return 4; \r
6587       }\r
6588       return 0;\r
6589     }\r
6590 \r
6591     internal override uint Size(MetaData md) { \r
6592       return md.BlobIndexSize();\r
6593     }\r
6594 \r
6595     internal sealed override void Write(FileImage output) {\r
6596       //Console.WriteLine("Writing the blob index for a TypeSpec");\r
6597       output.BlobIndex(sigIx);\r
6598     }\r
6599 \r
6600   }\r
6601 \r
6602 \r
6603 }\r
6604 \r
6605 \r