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