3 using System.Collections;
5 using System.Reflection;
12 /// flags for the assembly (.corflags)
14 public enum CorFlags {CF_IL_ONLY = 1, CF_32_BITREQUIRED = 2,
15 CF_STRONGNAMESIGNED = 8, CF_TRACKDEBUGDATA = 0x10000 }
18 /// subsystem for the assembly (.subsystem)
20 public enum SubSystem { Native = 1, Windows_GUI = 2,
21 Windows_CUI = 3, OS2_CUI = 5, POSIX_CUI = 7, Native_Windows = 8,
25 /// Hash algorithms for the assembly
27 public enum HashAlgorithm { None, SHA1 }
30 /// Attributes for this assembly
32 public enum AssemAttr { Retargetable = 0x100, EnableJITCompileTracking = 0x8000,
33 DisableJITCompileOptimizer = 0x4000}
36 /// Method call conventions
39 public enum CallConv { Default, Cdecl, Stdcall, Thiscall,
40 Fastcall, Vararg, Instance = 0x20, Generic = 0x10, InstanceExplicit = 0x60 }
43 /// Type custom modifier
45 public enum CustomModifier { modreq = 0x1F, modopt };
48 /// Attibutes for a class
51 public enum TypeAttr {Private, Public, NestedPublic, NestedPrivate,
52 NestedFamily, NestedAssembly, NestedFamAndAssem, NestedFamOrAssem,
53 SequentialLayout, ExplicitLayout = 0x10, Interface = 0x20,
54 Abstract = 0x80, PublicAbstract = 0x81, Sealed = 0x100,
55 PublicSealed = 0x101, SpecialName = 0x400, RTSpecialName = 0x800,
56 Import = 0x1000, Serializable = 0x2000, UnicodeClass = 0x10000,
57 AutoClass = 0x20000, HasSecurity = 0x40000, BeforeFieldInit = 0x100000,
59 VisibilityMask = 0x07 }
62 /// Attributes for a field
64 public enum FieldAttr {Default, Private, FamAndAssem, Assembly,
65 Family, FamOrAssem, Public, Static = 0x10, PublicStatic = 0x16,
66 Initonly = 0x20, Literal = 0x40, Notserialized = 0x80,
67 SpecialName = 0x200, RTSpecialName = 0x400, HasFieldMarshal = 0x1000 }
70 /// Attributes for a method
72 public enum MethAttr { Default, Private, FamAndAssem, Assembly,
73 Family, FamOrAssem, Public, Static = 0x0010, PublicStatic = 0x16,
74 Final = 0x0020, PublicStaticFinal = 0x36, Virtual = 0x0040,
75 PrivateVirtual, PublicVirtual = 0x0046, HideBySig = 0x0080,
76 NewSlot = 0x0100, Strict = 0x200, Abstract = 0x0400, SpecialName = 0x0800,
77 RTSpecialName = 0x1000, SpecialRTSpecialName = 0x1800,
78 HasSecurity = 0x4000, RequireSecObject = 0x8000}
81 /// Attributes for .pinvokeimpl method declarations
83 public enum PInvokeAttr { nomangle = 1, ansi = 2, unicode = 4, autochar = 6,
84 bestfit_on = 0x0010, bestfit_off = 0x0020, bestfit_mask = 0x0030,
85 lasterr = 0x0040, winapi = 0x0100, cdecl = 0x0200,
86 stdcall = 0x0300, thiscall = 0x0400, fastcall = 0x0500,
87 charmaperror_on = 0x1000, charmaperror_off = 0x2000
91 /// Implementation attributes for a method
93 public enum ImplAttr { IL, Native, Runtime = 0x03, Unmanaged = 0x04,
94 ForwardRef = 0x10, PreserveSig = 0x0080, InternalCall = 0x1000,
95 Synchronised = 0x0020, Synchronized = 0x0020, NoInLining = 0x0008, Optil = 0x0002}
98 /// Modes for a parameter
100 public enum ParamAttr { Default, In, Out, Opt = 16, HasDefault = 0x1000, HasFieldMarshal = 0x2000 }
105 public enum Op { nop, breakOp, ldarg_0, ldarg_1, ldarg_2, ldarg_3,
106 ldloc_0, ldloc_1, ldloc_2, ldloc_3, stloc_0, stloc_1, stloc_2, stloc_3,
107 ldnull = 0x14, ldc_i4_m1, ldc_i4_0, ldc_i4_1, ldc_i4_2, ldc_i4_3,
108 ldc_i4_4, ldc_i4_5, ldc_i4_6, ldc_i4_7, ldc_i4_8, dup = 0x25, pop,
109 ret = 0x2A, ldind_i1 = 0x46, ldind_u1, ldind_i2, ldind_u2, ldind_i4,
110 ldind_u4, ldind_i8, ldind_i, ldind_r4, ldind_r8, ldind_ref, stind_ref,
111 stind_i1, stind_i2, stind_i4, stind_i8, stind_r4, stind_r8, add, sub, mul,
112 div, div_un, rem, rem_un, and, or, xor, shl, shr, shr_un, neg, not,
113 conv_i1, conv_i2, conv_i4, conv_i8, conv_r4, conv_r8, conv_u4, conv_u8,
114 conv_r_un = 0x76, throwOp = 0x7A, conv_ovf_i1_un = 0x82, conv_ovf_i2_un,
115 conv_ovf_i4_un, conv_ovf_i8_un, conf_ovf_u1_un, conv_ovf_u2_un,
116 conv_ovf_u4_un, conv_ovf_u8_un, conv_ovf_i_un, conv_ovf_u_un,
117 ldlen = 0x8E, ldelem_i1 = 0x90, ldelem_u1, ldelem_i2, ldelem_u2,
118 ldelem_i4, ldelem_u4, ldelem_i8, ldelem_i, ldelem_r4, ldelem_r8,
119 ldelem_ref, stelem_i, stelem_i1, stelem_i2, stelem_i4, stelem_i8, stelem_r4 = 0xA0, stelem_r8,
120 stelem_ref, conv_ovf_i1 = 0xb3, conv_ovf_u1, conv_ovf_i2, conv_ovf_u2,
121 conv_ovf_i4, conv_ovf_u4, conv_ovf_i8, conv_ovf_u8, ckfinite = 0xC3,
122 conv_u2 = 0xD1, conv_u1, conv_i, conv_ovf_i, conv_ovf_u, add_ovf,
123 add_ovf_un, mul_ovf, mul_ovf_un, sub_ovf, sub_ovf_un, endfinally,
124 stind_i = 0xDF, conv_u, arglist = 0xFE00, ceq, cgt, cgt_un, clt, clt_un,
125 localloc = 0xFE0F, endfilter = 0xFE11, volatile_ = 0xFE13, tail_,
126 cpblk = 0xFE17, initblk, rethrow = 0xFE1A, refanytype = 0xFE1D, readonly_ = 0xFE1E }
129 /// CIL instructions requiring an integer parameter
131 public enum IntOp {ldarg_s = 0x0E, ldarga_s, starg_s, ldloc_s, ldloca_s,
132 stloc_s, ldc_i4_s = 0x1F, ldc_i4, ldarg = 0xFE09,
133 ldarga, starg, ldloc, ldloca, stloc, unaligned = 0xFE12 }
136 /// CIL instructions requiring a field parameter
138 public enum FieldOp {ldfld = 0x7B, ldflda, stfld, ldsfld, ldsflda,
139 stsfld, ldtoken = 0xD0 }
142 /// CIL instructions requiring a method parameter
144 public enum MethodOp {jmp = 0x27, call, callvirt = 0x6F, newobj = 0x73,
145 ldtoken = 0xD0, ldftn = 0xFE06, ldvirtfn }
148 /// CIL instructions requiring a type parameter
150 public enum TypeOp {cpobj = 0x70, ldobj, castclass = 0x74, isinst,
151 unbox = 0x79, stobj = 0x81, box = 0x8C, newarr,
152 ldelema = 0x8F, refanyval = 0xC2, mkrefany = 0xC6,
153 ldtoken = 0xD0, initobj = 0xFE15, constrained = 0xFE16,
154 sizeOf = 0xFE1C, ldelem = 0xA3, stelem = 0xA4, unbox_any }
157 /// CIL branch instructions
159 public enum BranchOp {
161 br_s = 0x2B, brfalse_s, brtrue_s, beq_s, bge_s, bgt_s,
162 ble_s, blt_s, bne_un_s, bge_un_s, bgt_un_s, ble_un_s, blt_un_s,
164 br = 0x38, brfalse, brtrue, beq, bge, bgt, ble, blt,
165 bne_un, bge_un, bgt_un, ble_un, blt_un,
167 leave = 0xDD, leave_s }
170 /// Index for all the tables in the meta data
172 public enum MDTable { Module, TypeRef, TypeDef, Field = 0x04, Method = 0x06,
173 Param = 0x08, InterfaceImpl, MemberRef, Constant, CustomAttribute,
174 FieldMarshal, DeclSecurity, ClassLayout, FieldLayout, StandAloneSig,
175 EventMap, Event = 0x14, PropertyMap, Property = 0x17, MethodSemantics,
176 MethodImpl, ModuleRef, TypeSpec, ImplMap, FieldRVA, Assembly = 0x20,
177 AssemblyProcessor, AssemblyOS, AssemblyRef, AssemblyRefProcessor,
178 AssemblyRefOS, File, ExportedType, ManifestResource, NestedClass,
179 GenericParam, MethodSpec, GenericParamConstraint }
181 public enum SafeArrayType { int16 = 2, int32, float32, float64,
182 currency, date, bstr, dispatch, error, boolean, variant, unknown,
183 Decimal, int8 = 16, uint8, uint16, uint32, Int = 22, UInt }
185 internal enum CIx { TypeDefOrRef, HasConst, HasCustomAttr, HasFieldMarshal,
186 HasDeclSecurity, MemberRefParent, HasSemantics, MethodDefOrRef,
187 MemberForwarded, Implementation, CustomAttributeType, ResolutionScope,
188 TypeOrMethodDef, MaxCIx }
190 internal enum MapType { eventMap, propertyMap, nestedClass }
192 public enum ValueClass { ValueType, Enum }
194 public enum GenParamType : byte {
195 Var = 0x13, MVar = 0x1E
199 public enum GenericParamAttributes : ushort {
200 VarianceMask = 0x0003,
203 Contravariant = 0x0002,
205 SpecialConstraintMask = 0x001c,
206 ReferenceTypeConstraint = 0x0004,
207 NotNullableValueTypeConstraint = 0x0008,
208 DefaultConstructorConstrait = 0x0010
211 /* Taken from Mono.Cecil */
212 public enum SecurityAction : short {
226 NonCasLinkDemand = 14,
227 NonCasInheritance = 15,
228 LinkDemandChoice = 16,
229 InheritDemandChoice = 17,
235 /**************************************************************************/
237 /// Base class for all Meta Data table elements
240 public abstract class MetaDataElement: IComparable {
241 protected ArrayList customAttributes;
242 private uint row = 0;
243 protected bool done = false;
244 protected MDTable tabIx;
245 protected bool sortTable = false;
247 private bool has_custom_attrs = false;
249 internal MetaDataElement() { }
260 public bool HasCustomAttr {
261 get { return has_custom_attrs; }
262 set { has_custom_attrs = value; }
265 internal virtual uint GetCodedIx(CIx code) { return 0; }
268 /// Add a custom attribute to this item
270 /// <param name="ctorMeth">the constructor method for this attribute</param>
271 /// <param name="val">the byte value of the parameters</param>
272 public void AddCustomAttribute(Method ctorMeth, byte[] val)
274 if (customAttributes == null) {
275 customAttributes = new ArrayList();
277 customAttributes.Add(new CustomAttribute(this,ctorMeth,val));
281 /// Add a custom attribute to this item
283 /// <param name="ctorMeth">the constructor method for this attribute</param>
284 /// <param name="val">the constant values of the parameters</param>
285 public void AddCustomAttribute(Method ctorMeth, Constant[] cVals)
287 if (customAttributes == null) {
288 customAttributes = new ArrayList();
290 // customAttributes.Add(new CustomAttribute(this,ctorMeth,cVals));
293 internal uint Token()
295 return (((uint)tabIx << 24) | row);
298 internal virtual void BuildTables(MetaData md)
303 internal virtual uint Size(MetaData md)
308 internal virtual void Write(FileImage output) { }
310 internal virtual uint SortKey()
312 throw new PEFileException("Trying to sort table of " + this);
316 internal virtual uint SortKey2()
321 public int CompareTo(object obj)
323 uint otherKey = ((MetaDataElement)obj).SortKey();
324 uint thisKey = SortKey();
326 if (thisKey == otherKey) {
328 otherKey = ((MetaDataElement)obj).SortKey2();
329 thisKey = SortKey2();
330 if (thisKey == otherKey)
332 if (thisKey < otherKey)
336 if (thisKey < otherKey) return -1;
343 /**************************************************************************/
345 /// Layout information for a class (.class [sequential | explicit])
347 internal class ClassLayout : MetaDataElement {
353 internal ClassLayout(int pack, int cSize, ClassDef par)
355 packSize = (ushort)pack;
356 classSize = (uint)cSize;
358 tabIx = MDTable.ClassLayout;
361 internal sealed override uint Size(MetaData md)
363 return 6 + md.TableIndexSize(MDTable.TypeDef);
366 internal sealed override void Write(FileImage output)
368 output.Write(packSize);
369 output.Write(classSize);
370 output.WriteIndex(MDTable.TypeDef,parent.Row);
375 /**************************************************************************/
377 /// Summary description for ConstantElem.
379 internal class ConstantElem : MetaDataElement {
381 MetaDataElement parent;
385 internal ConstantElem(MetaDataElement parent, Constant val)
387 this.parent = parent;
389 tabIx = MDTable.Constant;
393 internal override uint SortKey()
395 return (parent.Row << MetaData.CIxShiftMap[(uint)CIx.HasConst])
396 | parent.GetCodedIx(CIx.HasConst);
399 internal sealed override void BuildTables(MetaData md)
402 valIx = cValue.GetBlobIndex(md);
406 internal void AddToBlob(BinaryWriter bw)
411 internal sealed override uint Size(MetaData md)
413 return 2 + md.CodedIndexSize(CIx.HasConst) + md.BlobIndexSize();
416 internal sealed override void Write(FileImage output)
418 output.Write(cValue.GetTypeIndex());
419 output.Write((byte)0);
420 output.WriteCodedIndex(CIx.HasConst,parent);
421 output.BlobIndex(valIx);
425 /**************************************************************************/
427 /// Descriptor for a Custom Attribute (.custom)
430 public class CustomAttribute : MetaDataElement {
432 MetaDataElement parent;
438 ArrayList names, vals;
440 internal CustomAttribute(MetaDataElement paren, Method constrType,
445 tabIx = MDTable.CustomAttribute;
447 byteVal = ConstantToByteArray (val);
450 static byte[] ConstantToByteArray (Constant c)
452 var bac = c as ByteArrConst;
456 var ms = new MemoryStream ();
464 return ms.ToArray ();
467 var sc = c as StringConst;
469 string value = sc.val;
471 throw new NotImplementedException ();
473 var buf = Encoding.UTF8.GetBytes (value);
474 MetaData.CompressNum ((uint) buf.Length, ms);
475 var byteVal = ms.ToArray ();
476 System.Array.Resize (ref byteVal, (int) ms.Length + buf.Length + 2);
477 System.Array.Copy (buf, 0, byteVal, ms.Length, buf.Length);
481 var ac = c as ArrayConstant;
483 var bw = new BinaryWriter (ms);
484 if (ac.ExplicitSize != null)
485 bw.Write (ac.ExplicitSize.Value);
488 return ms.ToArray ();
491 var bc = c as DataConstant;
493 var bw = new BinaryWriter (ms);
496 return ms.ToArray ();
499 throw new NotImplementedException (c.GetType ().ToString ());
502 internal CustomAttribute(MetaDataElement paren, Method constrType,
506 tabIx = MDTable.CustomAttribute;
510 internal override uint SortKey()
512 return (parent.Row << MetaData.CIxShiftMap[(uint)CIx.HasCustomAttr])
513 | parent.GetCodedIx(CIx.HasCustomAttr);
516 public void AddFieldOrProp(string name, Constant val)
519 names = new ArrayList();
520 vals = new ArrayList();
526 internal sealed override void BuildTables(MetaData md)
528 md.AddToTable(MDTable.CustomAttribute, this);
529 if (byteVal == null) {
534 BinaryWriter bw = new BinaryWriter(new MemoryStream());
536 MemoryStream str = (MemoryStream)bw.BaseStream;
537 valIx = md.AddToBlobHeap(str.ToArray());
540 internal sealed override uint Size(MetaData md)
542 return md.CodedIndexSize(CIx.HasCustomAttr) + md.CodedIndexSize(CIx.CustomAttributeType) + md.BlobIndexSize();
545 internal sealed override void Write(FileImage output)
547 output.WriteCodedIndex(CIx.HasCustomAttr,parent);
548 output.WriteCodedIndex(CIx.CustomAttributeType,type);
549 output.BlobIndex(valIx);
554 /**************************************************************************/
556 /// Descriptor for security permissions for a class or a method
559 public abstract class BaseDeclSecurity : MetaDataElement {
562 MetaDataElement parent;
565 internal BaseDeclSecurity(MetaDataElement paren, ushort act)
569 tabIx = MDTable.DeclSecurity;
572 internal override uint SortKey()
574 return (parent.Row << MetaData.CIxShiftMap[(uint)CIx.HasDeclSecurity])
575 | parent.GetCodedIx(CIx.HasDeclSecurity);
578 internal sealed override uint Size(MetaData md)
580 return 2 + md.CodedIndexSize(CIx.HasDeclSecurity) + md.BlobIndexSize();
583 internal sealed override void BuildTables(MetaData md)
587 BinaryWriter bw = new BinaryWriter (new MemoryStream ());
588 md.AddToTable (MDTable.DeclSecurity, this);
589 MemoryStream str = (MemoryStream)bw.BaseStream;
591 permissionIx = md.AddToBlobHeap(str.ToArray());
596 internal abstract void WriteSig (BinaryWriter bw);
598 internal sealed override void Write(FileImage output)
600 output.Write(action);
601 output.WriteCodedIndex(CIx.HasDeclSecurity,parent);
602 output.BlobIndex(permissionIx);
607 public class DeclSecurity : BaseDeclSecurity {
611 internal DeclSecurity(MetaDataElement paren, ushort act, byte [] val)
617 internal override void WriteSig (BinaryWriter bw)
624 public class DeclSecurity_20 : BaseDeclSecurity {
628 internal DeclSecurity_20 (MetaDataElement paren, ushort act, PermissionSet ps)
634 internal override void WriteSig (BinaryWriter bw)
640 public class PermissionMember {
642 MemberTypes member_type;
647 public PermissionMember (MemberTypes member_type, PEAPI.Type type, string name, object value)
649 this.member_type = member_type;
655 public void Write (BinaryWriter bw)
659 if (member_type == MemberTypes.Field)
660 bw.Write ((byte) 0x53);
663 bw.Write ((byte) 0x54);
665 if (type is PrimitiveType) {
666 bw.Write (type.GetTypeIndex ());
669 bw.Write ((byte) 0x55); //ENUM
671 b = Encoding.UTF8.GetBytes (((ClassRef) type).TypeName ());
672 MetaData.CompressNum ((uint) b.Length, (MemoryStream) bw.BaseStream);
676 b = Encoding.UTF8.GetBytes (name);
677 MetaData.CompressNum ((uint) b.Length, (MemoryStream) bw.BaseStream);
680 ((Constant) value).Write (bw);
685 public class Permission
693 public Permission (PEAPI.Type type, string name)
699 public void AddMember (PEAPI.PermissionMember member)
702 members = new ArrayList ();
704 members.Add (member);
707 public void Write (BinaryWriter bw)
709 byte [] b = Encoding.UTF8.GetBytes (name);
710 MetaData.CompressNum ((uint) b.Length, (MemoryStream) bw.BaseStream);
713 BinaryWriter perm_writer = new BinaryWriter (new MemoryStream (), Encoding.Unicode);
714 MemoryStream str = (MemoryStream) perm_writer.BaseStream;
716 MetaData.CompressNum ((uint) members.Count, str);//number of params
717 foreach (PermissionMember member in members)
718 member.Write (perm_writer);
720 bw.Write ((byte) str.Length); //(optional) parameters length
721 bw.Write (str.ToArray ());
725 public class PermissionSet
727 PEAPI.SecurityAction sec_action;
728 ArrayList permissions;
730 public PermissionSet (PEAPI.SecurityAction sec_action)
732 this.sec_action = sec_action;
735 public void AddPermission (PEAPI.Permission perm)
737 if (permissions == null)
738 permissions = new ArrayList ();
740 permissions.Add (perm);
743 public void Write (BinaryWriter bw)
745 bw.Write ((byte) 0x2e);
746 MetaData.CompressNum ((uint) permissions.Count, (MemoryStream) bw.BaseStream);
748 foreach (Permission perm in permissions)
754 /**************************************************************************/
756 /// Descriptor for layout information for a field
759 public class FieldLayout : MetaDataElement {
764 internal FieldLayout(Field field, uint offset)
767 this.offset = offset;
768 tabIx = MDTable.FieldLayout;
771 internal sealed override uint Size(MetaData md)
773 return 4 + md.TableIndexSize(MDTable.Field);
776 internal sealed override void Write(FileImage output)
778 output.Write(offset);
779 output.WriteIndex(MDTable.Field,field.Row);
784 /*****************************************************************************/
786 /// Marshalling information for a field or param
788 public class FieldMarshal : MetaDataElement {
790 MetaDataElement field;
794 internal FieldMarshal(MetaDataElement field, NativeType nType)
798 tabIx = MDTable.FieldMarshal;
801 internal override uint SortKey()
803 return (field.Row << MetaData.CIxShiftMap[(uint)CIx.HasFieldMarshal])
804 | field.GetCodedIx(CIx.HasFieldMarshal);
807 internal sealed override void BuildTables(MetaData md)
810 ntIx = md.AddToBlobHeap(nt.ToBlob());
814 internal sealed override uint Size(MetaData md)
816 return md.CodedIndexSize(CIx.HasFieldMarshal) + md.BlobIndexSize();
819 internal sealed override void Write(FileImage output)
821 output.WriteCodedIndex(CIx.HasFieldMarshal,field);
822 output.BlobIndex(ntIx);
827 /**************************************************************************/
829 /// Descriptor for the address of a field's value in the PE file
831 public class FieldRVA : MetaDataElement {
836 internal FieldRVA(Field field, DataConstant data)
840 tabIx = MDTable.FieldRVA;
843 internal sealed override void BuildTables(MetaData md)
850 internal sealed override uint Size(MetaData md)
852 return 4 + md.TableIndexSize(MDTable.Field);
855 internal sealed override void Write(FileImage output)
857 output.WriteDataRVA(data.DataOffset);
858 output.WriteIndex(MDTable.Field,field.Row);
863 /**************************************************************************/
865 /// Descriptor for a file referenced in THIS assembly/module (.file)
867 public class FileRef : MetaDataElement {
869 private static readonly uint NoMetaData = 0x1;
870 uint nameIx = 0, hashIx = 0;
872 protected string name;
874 internal FileRef(string name, byte[] hashBytes, bool metaData,
875 bool entryPoint, MetaData md) {
876 if (!metaData) flags = NoMetaData;
877 if (entryPoint) md.SetEntryPoint(this);
879 nameIx = md.AddToStringsHeap(name);
880 hashIx = md.AddToBlobHeap(hashBytes);
881 tabIx = MDTable.File;
884 internal FileRef(uint nameIx, byte[] hashBytes, bool metaData,
885 bool entryPoint, MetaData md) {
886 if (!metaData) flags = NoMetaData;
887 if (entryPoint) md.SetEntryPoint(this);
888 this.nameIx = nameIx;
889 hashIx = md.AddToBlobHeap(hashBytes);
890 tabIx = MDTable.File;
893 internal sealed override uint Size(MetaData md)
895 return 4 + md.StringsIndexSize() + md.BlobIndexSize();
898 internal sealed override void BuildTables(MetaData md)
900 md.AddToTable(MDTable.File,this);
903 internal sealed override void Write(FileImage output)
906 output.StringsIndex(nameIx);
907 output.BlobIndex(hashIx);
910 internal sealed override uint GetCodedIx(CIx code)
913 case (CIx.HasCustomAttr) : return 16;
914 case (CIx.Implementation) : return 0;
920 /**************************************************************************/
922 /// Descriptor for pinvoke information for a method NOT YET IMPLEMENTED
924 public class ImplMap : MetaDataElement {
926 private static readonly ushort NoMangle = 0x01;
931 ModuleRef importScope;
933 internal ImplMap(ushort flag, Method implMeth, string iName, ModuleRef mScope)
938 importScope = mScope;
939 tabIx = MDTable.ImplMap;
940 if (iName == null) flags |= NoMangle;
941 //throw(new NotYetImplementedException("PInvoke "));
944 internal override uint SortKey()
946 return (meth.Row << MetaData.CIxShiftMap[(uint)CIx.MemberForwarded])
947 | meth.GetCodedIx(CIx.MemberForwarded);
950 internal sealed override void BuildTables(MetaData md)
953 iNameIx = md.AddToStringsHeap(importName);
957 internal sealed override uint Size(MetaData md)
959 return 2+ md.CodedIndexSize(CIx.MemberForwarded) +
960 md.StringsIndexSize() + md.TableIndexSize(MDTable.ModuleRef);
963 internal sealed override void Write(FileImage output)
966 output.WriteCodedIndex(CIx.MemberForwarded,meth);
967 output.StringsIndex(iNameIx);
968 output.WriteIndex(MDTable.ModuleRef,importScope.Row);
973 /**************************************************************************/
975 public class GenericParameter : MetaDataElement {
977 MetaDataElement owner;
982 GenericParamAttributes attr;
984 internal GenericParameter (ClassDef owner, MetaData metadata,
985 short index, string name, GenericParamAttributes attr) : this (owner, metadata, index, name, attr, true)
989 internal GenericParameter (MethodDef owner, MetaData metadata,
990 short index, string name, GenericParamAttributes attr) : this (owner, metadata, index, name, attr, true)
994 private GenericParameter (MetaDataElement owner, MetaData metadata,
995 short index, string name, GenericParamAttributes attr, bool nadda) {
997 this.metadata = metadata;
999 tabIx = MDTable.GenericParam;
1004 internal override uint SortKey()
1006 return (owner.Row << MetaData.CIxShiftMap[(uint)CIx.TypeOrMethodDef])
1007 | owner.GetCodedIx(CIx.TypeOrMethodDef);
1010 internal override uint SortKey2 ()
1012 return (uint) index;
1015 public void AddConstraint (Type constraint)
1017 metadata.AddToTable (MDTable.GenericParamConstraint,
1018 new GenericParamConstraint (this, constraint));
1021 internal sealed override uint Size(MetaData md)
1024 md.CodedIndexSize(CIx.TypeOrMethodDef) +
1025 md.StringsIndexSize ());
1028 internal sealed override void BuildTables(MetaData md)
1031 nameIx = md.AddToStringsHeap(name);
1035 internal sealed override void Write(FileImage output)
1037 output.Write ((short) index);
1038 output.Write ((short) attr);
1039 output.WriteCodedIndex(CIx.TypeOrMethodDef, owner);
1040 output.StringsIndex (nameIx);
1043 internal sealed override uint GetCodedIx(CIx code)
1046 case (CIx.HasCustomAttr) : return 19;
1053 internal class GenericParamConstraint : MetaDataElement {
1055 GenericParameter param;
1058 public GenericParamConstraint (GenericParameter param, Type type)
1062 tabIx = MDTable.GenericParamConstraint;
1065 internal override uint SortKey()
1070 internal sealed override uint Size(MetaData md)
1072 return (uint) (md.TableIndexSize(MDTable.GenericParam) +
1073 md.CodedIndexSize(CIx.TypeDefOrRef));
1076 internal sealed override void Write(FileImage output)
1078 output.WriteIndex(MDTable.GenericParam, param.Row);
1079 output.WriteCodedIndex(CIx.TypeDefOrRef, type);
1084 internal class MethodSpec : Method {
1087 GenericMethodSig g_sig;
1090 internal MethodSpec (Method meth, GenericMethodSig g_sig) : base ("")
1094 tabIx = MDTable.MethodSpec;
1097 internal override uint GetSigIx (MetaData md)
1099 throw new Exception ("Should not be used.");
1102 public override void AddCallConv (CallConv cconv)
1104 throw new Exception ("Should not be used.");
1107 internal sealed override void BuildTables (MetaData md)
1110 sidx = g_sig.GetSigIx (md);
1114 internal sealed override uint Size (MetaData md)
1116 return (uint) (md.CodedIndexSize(CIx.MethodDefOrRef) +
1117 md.BlobIndexSize ());
1120 internal sealed override void Write (FileImage output)
1122 output.WriteCodedIndex (CIx.MethodDefOrRef, meth);
1123 output.BlobIndex (sidx);
1126 internal sealed override void TypeSig (MemoryStream sig)
1128 throw new Exception ("Should not be used.");
1132 /**************************************************************************/
1134 /// Descriptor for interface implemented by a class
1136 public class InterfaceImpl: MetaDataElement {
1141 internal InterfaceImpl(ClassDef theClass, Class theInterface)
1143 this.theClass = theClass;
1144 this.theInterface = theInterface;
1145 tabIx = MDTable.InterfaceImpl;
1148 internal sealed override uint Size(MetaData md)
1150 return md.TableIndexSize(MDTable.TypeDef) +
1151 md.CodedIndexSize(CIx.TypeDefOrRef);
1154 internal sealed override void Write(FileImage output)
1156 output.WriteIndex(MDTable.TypeDef,theClass.Row);
1157 output.WriteCodedIndex(CIx.TypeDefOrRef,theInterface);
1160 internal sealed override uint GetCodedIx(CIx code) { return 5; }
1162 internal override uint SortKey ()
1164 return (theClass.Row << MetaData.CIxShiftMap[(uint)CIx.TypeDefOrRef])
1165 | theClass.GetCodedIx (CIx.TypeDefOrRef);
1170 /**************************************************************************/
1172 /// Descriptor for resources used in this PE file
1175 public class ManifestResource : MetaDataElement {
1177 public static readonly uint PublicResource = 0x1;
1178 public static readonly uint PrivateResource = 0x2;
1181 MetaDataElement rRef;
1185 byte [] resourceBytes;
1187 public ManifestResource (string name, byte[] resBytes, uint flags)
1189 InitResource (name, flags);
1190 this.resourceBytes = resBytes;
1193 public ManifestResource(string name, uint flags, FileRef fileRef)
1195 InitResource (name, flags);
1199 public ManifestResource(string name, uint flags, FileRef fileRef,
1201 InitResource (name, flags);
1203 fileOffset = fileIx;
1206 public ManifestResource(string name, uint flags, AssemblyRef assemRef)
1208 InitResource (name, flags);
1212 internal ManifestResource (ManifestResource mres)
1214 mrName = mres.mrName;
1217 fileOffset = mres.fileOffset;
1218 resourceBytes = mres.resourceBytes;
1221 private void InitResource (string name, uint flags)
1225 tabIx = MDTable.ManifestResource;
1228 internal sealed override void BuildTables(MetaData md)
1231 md.AddToTable (MDTable.ManifestResource, this);
1232 nameIx = md.AddToStringsHeap(mrName);
1233 if (resourceBytes != null) {
1235 throw new PEFileException ("Manifest Resource has byte value and file reference");
1236 fileOffset = md.AddResource(resourceBytes);
1239 throw new PEFileException ("Manifest Resource has no implementation or value");
1240 rRef.BuildTables (md);
1246 internal sealed override uint Size(MetaData md)
1248 return 8 + md.StringsIndexSize() +
1249 md.CodedIndexSize(CIx.Implementation);
1252 internal sealed override void Write(FileImage output)
1254 output.Write(fileOffset);
1255 output.Write(flags);
1256 output.StringsIndex(nameIx);
1257 output.WriteCodedIndex(CIx.Implementation,rRef);
1260 internal sealed override uint GetCodedIx(CIx code) { return 18; }
1262 public string Name {
1263 get { return mrName; }
1264 set { mrName = value; }
1268 /**************************************************************************/
1270 /// Base class for elements in the PropertyMap, EventMap and
1271 /// NestedClass MetaData tables
1273 public class MapElem : MetaDataElement {
1279 internal MapElem(ClassDef par, uint elIx, MDTable elemTab)
1283 elemTable = elemTab;
1286 internal sealed override uint Size(MetaData md)
1288 return md.TableIndexSize(MDTable.TypeDef) + md.TableIndexSize(elemTable);
1291 internal sealed override void Write(FileImage output)
1293 output.WriteIndex(MDTable.TypeDef,parent.Row);
1294 output.WriteIndex(elemTable,elemIx);
1298 /**************************************************************************/
1300 /// Descriptor for an overriding method (.override)
1302 public class MethodImpl : MetaDataElement {
1305 Method header, body;
1307 internal MethodImpl(ClassDef par, Method decl, Method bod)
1312 tabIx = MDTable.MethodImpl;
1315 internal sealed override uint Size(MetaData md)
1317 return md.TableIndexSize(MDTable.TypeDef) + 2 * md.CodedIndexSize(CIx.MethodDefOrRef);
1320 internal sealed override void Write(FileImage output)
1322 output.WriteIndex(MDTable.TypeDef,parent.Row);
1323 output.WriteCodedIndex(CIx.MethodDefOrRef,body);
1324 output.WriteCodedIndex(CIx.MethodDefOrRef,header);
1329 /**************************************************************************/
1331 /// Descriptor for Property and Event methods
1333 public class MethodSemantics : MetaDataElement {
1335 Feature.MethodType type;
1337 Feature eventOrProp;
1339 internal MethodSemantics(Feature.MethodType mType, MethodDef method, Feature feature)
1343 eventOrProp = feature;
1344 tabIx = MDTable.MethodSemantics;
1347 internal override uint SortKey()
1349 return (eventOrProp.Row << MetaData.CIxShiftMap [(uint)CIx.HasSemantics])
1350 | eventOrProp.GetCodedIx (CIx.HasSemantics);
1353 internal sealed override uint Size(MetaData md)
1355 return 2 + md.TableIndexSize(MDTable.Method) + md.CodedIndexSize(CIx.HasSemantics);
1358 internal sealed override void Write(FileImage output)
1360 output.Write((ushort)type);
1361 output.WriteIndex(MDTable.Method,meth.Row);
1362 output.WriteCodedIndex(CIx.HasSemantics,eventOrProp);
1367 /**************************************************************************/
1369 /// Descriptor for a parameter of a method defined in this assembly/module
1371 public class Param : MetaDataElement {
1376 internal ushort seqNo = 0;
1378 ConstantElem defaultVal;
1380 FieldMarshal marshalInfo;
1383 /// Create a new parameter for a method
1385 /// <param name="mode">param mode (in, out, opt)</param>
1386 /// <param name="parName">parameter name</param>
1387 /// <param name="parType">parameter type</param>
1388 public Param(ParamAttr mode, string parName, Type parType)
1392 parMode = (ushort)mode;
1393 tabIx = MDTable.Param;
1396 public bool HasMarshalInfo {
1397 get { return marshalInfo != null; }
1401 /// Add a default value to this parameter
1403 /// <param name="c">the default value for the parameter</param>
1404 public void AddDefaultValue(Constant cVal)
1406 defaultVal = new ConstantElem(this,cVal);
1407 parMode |= (ushort) ParamAttr.HasDefault;
1411 /// Add marshalling information about this parameter
1413 public void AddMarshallInfo(NativeType marshallType)
1415 parMode |= (ushort) ParamAttr.HasFieldMarshal;
1416 marshalInfo = new FieldMarshal(this,marshallType);
1419 internal Type GetParType() { return pType; }
1421 internal sealed override void BuildTables(MetaData md)
1424 nameIx = md.AddToStringsHeap(pName);
1425 if (defaultVal != null) {
1426 md.AddToTable(MDTable.Constant,defaultVal);
1427 defaultVal.BuildTables(md);
1429 if (marshalInfo != null) {
1430 md.AddToTable(MDTable.FieldMarshal,marshalInfo);
1431 marshalInfo.BuildTables(md);
1436 internal void TypeSig(MemoryStream str)
1441 internal sealed override uint Size(MetaData md)
1443 return 4 + md.StringsIndexSize();
1446 internal sealed override void Write(FileImage output)
1448 output.Write(parMode);
1449 output.Write(seqNo);
1450 output.StringsIndex(nameIx);
1453 internal sealed override uint GetCodedIx(CIx code)
1456 case (CIx.HasCustomAttr) : return 4;
1457 case (CIx.HasConst) : return 1;
1458 case (CIx.HasFieldMarshal) : return 1;
1465 /**************************************************************************/
1466 public abstract class Signature : MetaDataElement {
1468 protected uint sigIx;
1470 internal Signature()
1472 tabIx = MDTable.StandAloneSig;
1475 internal sealed override uint Size(MetaData md)
1477 return md.BlobIndexSize();
1480 internal sealed override void Write(FileImage output)
1482 output.BlobIndex(sigIx);
1485 internal sealed override uint GetCodedIx(CIx code) { return (uint)tabIx; }
1489 /**************************************************************************/
1490 public class TypeSpec : MetaDataElement {
1493 internal TypeSpec(Type aType, MetaData md)
1495 MemoryStream sig = new MemoryStream();
1497 sigIx = md.AddToBlobHeap(sig.ToArray());
1498 tabIx = MDTable.TypeSpec;
1501 internal sealed override uint GetCodedIx(CIx code)
1504 case (CIx.TypeDefOrRef) : return 2;
1505 case (CIx.HasCustomAttr) : return 13;
1506 case (CIx.MemberRefParent) : return 4;
1511 internal override uint Size(MetaData md)
1513 return md.BlobIndexSize();
1516 internal sealed override void Write(FileImage output)
1518 //Console.WriteLine("Writing the blob index for a TypeSpec");
1519 output.BlobIndex(sigIx);
1524 /**************************************************************************/
1526 /// Base class for all IL types
1528 public abstract class Type : MetaDataElement {
1529 protected byte typeIndex;
1530 protected TypeSpec typeSpec;
1532 internal Type(byte tyIx) { typeIndex = tyIx; }
1534 internal byte GetTypeIndex() { return typeIndex; }
1535 internal void SetTypeIndex (byte b) { typeIndex = b; }
1537 internal virtual MetaDataElement GetTypeSpec(MetaData md)
1539 if (typeSpec == null) {
1540 typeSpec = new TypeSpec(this,md);
1541 md.AddToTable(MDTable.TypeSpec,typeSpec);
1546 internal virtual void TypeSig(MemoryStream str)
1548 throw(new TypeSignatureException(this.GetType().AssemblyQualifiedName +
1549 " doesn't have a type signature!!"));
1553 public class ClassRefInst : Type {
1556 private bool is_value;
1558 public ClassRefInst (Type type, bool is_value) : base (PrimitiveType.Class.GetTypeIndex ())
1561 this.is_value = is_value;
1563 typeIndex = PrimitiveType.ValueType.GetTypeIndex ();
1564 tabIx = MDTable.TypeSpec;
1567 internal sealed override void TypeSig(MemoryStream str)
1573 /**************************************************************************/
1575 /// The base descriptor for a class
1577 public abstract class Class : Type {
1579 protected int row = 0;
1580 public string name, nameSpace;
1581 protected uint nameIx, nameSpaceIx;
1582 protected MetaData _metaData;
1583 internal Class(string nameSpaceName, string className, MetaData md)
1584 : base(PrimitiveType.Class.GetTypeIndex ())
1586 nameSpace = nameSpaceName;
1588 nameIx = md.AddToStringsHeap(name);
1589 nameSpaceIx = md.AddToStringsHeap(nameSpace);
1593 internal Class(uint nsIx, uint nIx) : base(PrimitiveType.Class.GetTypeIndex ())
1599 internal Class (byte typeIndex) : base (typeIndex)
1601 nameSpace = "Should not be used";
1602 name = "Should not be used";
1605 internal virtual uint TypeDefOrRefToken() { return 0; }
1607 internal virtual void MakeValueClass(ValueClass vClass)
1609 typeIndex = PrimitiveType.ValueType.GetTypeIndex ();
1612 internal virtual string TypeName()
1614 return (nameSpace + "." + name);
1617 internal override MetaDataElement GetTypeSpec(MetaData md)
1623 /**************************************************************************/
1624 // This Class produces entries in the TypeDef table of the MetaData
1625 // in the PE meta data.
1627 // NOTE: Entry 0 in TypeDef table is always the pseudo class <module>
1628 // which is the parent for functions and variables declared a module level
1631 /// The descriptor for a class defined in the IL (.class) in the current assembly/module
1634 public class ClassDef : Class {
1637 ArrayList fields = new ArrayList();
1638 ArrayList methods = new ArrayList();
1640 ArrayList properties;
1641 bool typeIndexChecked = true;
1642 uint fieldIx = 0, methodIx = 0;
1645 ClassDef parentClass;
1648 internal ClassDef(TypeAttr attrSet, string nsName, string name,
1649 MetaData md) : base(nsName, name, md)
1652 if (! ((nsName == "" && name == "<Module>") || (nsName == "System" && name == "Object")) ) {
1653 superType = metaData.mscorlib.GetSpecialSystemClass(PrimitiveType.Object);
1655 flags = (uint)attrSet;
1656 tabIx = MDTable.TypeDef;
1659 internal void SetSuper(Class sClass)
1662 if (! (sClass is GenericTypeInst))
1663 typeIndexChecked = false;
1666 internal override void MakeValueClass(ValueClass vClass)
1668 if (vClass == ValueClass.Enum)
1669 superType = metaData.mscorlib.EnumType();
1671 superType = metaData.mscorlib.ValueType();
1673 typeIndex = PrimitiveType.ValueType.GetTypeIndex ();
1676 public void SpecialNoSuper()
1682 /// Add an attribute to this class
1684 /// <param name="ta">the attribute to be added</param>
1685 public void AddAttribute(TypeAttr ta)
1691 /// Add an interface that is implemented by this class
1693 /// <param name="iFace">the interface that is implemented</param>
1694 public void AddImplementedInterface(Class iFace)
1696 metaData.AddToTable(MDTable.InterfaceImpl,new InterfaceImpl(this,iFace));
1700 /// Add a named generic type parameter
1702 public GenericParameter AddGenericParameter (short index, string name)
1704 return AddGenericParameter (index, name, 0);
1708 /// Add a named generic type parameter with attributes
1710 public GenericParameter AddGenericParameter (short index, string name, GenericParamAttributes attr)
1712 GenericParameter gp = new GenericParameter (this, metaData, index, name, attr);
1713 metaData.AddToTable (MDTable.GenericParam, gp);
1718 /// Add a field to this class
1720 /// <param name="name">field name</param>
1721 /// <param name="fType">field type</param>
1722 /// <returns>a descriptor for this new field</returns>
1723 public FieldDef AddField(string name, Type fType)
1725 FieldDef field = new FieldDef(name,fType);
1731 /// Add a field to this class
1733 /// <param name="fAtts">attributes for this field</param>
1734 /// <param name="name">field name</param>
1735 /// <param name="fType">field type</param>
1736 /// <returns>a descriptor for this new field</returns>
1737 public FieldDef AddField(FieldAttr fAtts, string name, Type fType)
1739 FieldDef field = new FieldDef(fAtts,name,fType);
1744 public void SetFieldOrder (ArrayList fields)
1746 this.fields = fields;
1750 /// Add a method to this class
1752 /// <param name="name">method name</param>
1753 /// <param name="retType">return type</param>
1754 /// <param name="pars">parameters</param>
1755 /// <returns>a descriptor for this new method</returns>
1756 public MethodDef AddMethod(string name, Type retType, Param[] pars)
1758 return AddMethod (name, new Param (ParamAttr.Default, "", retType), pars);
1761 public MethodDef AddMethod (string name, Param ret_param, Param [] pars)
1763 // Console.WriteLine("Adding method " + name + " to class " + this.name);
1764 MethodDef meth = new MethodDef(metaData,name, ret_param, pars);
1770 /// Add a method to this class
1772 /// <param name="mAtts">attributes for this method</param>
1773 /// <param name="iAtts">implementation attributes for this method</param>
1774 /// <param name="name">method name</param>
1775 /// <param name="retType">return type</param>
1776 /// <param name="pars">parameters</param>
1777 /// <returns>a descriptor for this new method</returns>
1778 public MethodDef AddMethod(MethAttr mAtts, ImplAttr iAtts, string name,
1779 Param ret_param, Param [] pars) {
1780 // Console.WriteLine("Adding method " + name + " to class " + this.name);
1781 MethodDef meth = new MethodDef (metaData, mAtts, iAtts, name, ret_param, pars);
1787 /// Add an event to this class
1789 /// <param name="name">event name</param>
1790 /// <param name="eType">event type</param>
1791 /// <returns>a descriptor for this new event</returns>
1792 public Event AddEvent(string name, Type eType)
1794 Event e = new Event(name,eType,this);
1795 if (events == null) events = new ArrayList();
1801 /// Add a property to this class
1803 /// <param name="name">property name</param>
1804 /// <param name="propType">property type</param>
1805 /// <returns>a descriptor for this new property</returns>
1806 public Property AddProperty(string name, Type retType, Type[] pars)
1808 Property p = new Property(name, retType, pars, this);
1809 if (properties == null) properties = new ArrayList();
1815 /// Add a nested class to this class
1817 /// <param name="attrSet">attributes for this nested class</param>
1818 /// <param name="nsName">nested name space name</param>
1819 /// <param name="name">nested class name</param>
1820 /// <returns>a descriptor for this new nested class</returns>
1821 public ClassDef AddNestedClass(TypeAttr attrSet, string nsName,
1823 ClassDef nClass = new ClassDef(attrSet,"",name,metaData);
1824 metaData.AddToTable(MDTable.TypeDef,nClass);
1825 metaData.AddToTable(MDTable.NestedClass,new MapElem(nClass,Row,MDTable.TypeDef));
1826 nClass.parentClass = this;
1830 public static bool IsValueType (Class type)
1832 return IsValueType (type.nameSpace, type.name);
1835 public static bool IsEnum (Class type)
1837 return IsEnum (type.nameSpace, type.name);
1840 public static bool IsValueType (string nsName, string name)
1842 return (nsName == "System" && name == "ValueType");
1845 public static bool IsEnum (string nsName, string name)
1847 return (nsName == "System" && name == "Enum");
1851 /// Add a nested class to this class
1853 /// <param name="attrSet">attributes for this nested class</param>
1854 /// <param name="nsName">nested name space name</param>
1855 /// <param name="name">nested class name</param>
1856 /// <param name="sType">super type of this nested class</param>
1857 /// <returns>a descriptor for this new nested class</returns>
1858 public ClassDef AddNestedClass(TypeAttr attrSet, string nsName,
1859 string name, Class sType) {
1860 ClassDef nClass = AddNestedClass (attrSet, nsName, name);
1861 nClass.SetSuper(sType);
1862 if (ClassDef.IsValueType (sType))
1863 nClass.MakeValueClass (ValueClass.ValueType);
1865 if (ClassDef.IsEnum (sType))
1866 nClass.MakeValueClass (ValueClass.Enum);
1868 if (ClassDef.IsValueType (sType) || ClassDef.IsEnum (sType))
1869 nClass.SetTypeIndex (PrimitiveType.ValueType.GetTypeIndex ());
1871 nClass.typeIndexChecked = true;
1876 /// Add layout information for this class. This class must have the
1877 /// sequential or explicit attribute.
1879 /// <param name="packSize">packing size (.pack)</param>
1880 /// <param name="classSize">class size (.size)</param>
1881 public void AddLayoutInfo (int packSize, int classSize)
1883 layout = new ClassLayout(packSize,classSize,this);
1887 /// Use a method as the implementation for another method (.override)
1889 /// <param name="decl">the method to be overridden</param>
1890 /// <param name="body">the implementation to be used</param>
1891 public void AddMethodOverride(Method decl, Method body)
1893 metaData.AddToTable(MDTable.MethodImpl,new MethodImpl(this,decl,body));
1897 /// Add security to this class NOT YET IMPLEMENTED
1899 /// <param name="permissionSet"></param>
1900 public void AddSecurity(byte[] permissionSet)
1902 throw(new NotYetImplementedException("Class security "));
1903 //flags |= HasSecurity;
1904 // securityActions = permissionSet;
1907 //public void AddLineInfo(int row, int col) { }
1909 internal void CheckTypeIndex()
1911 if (typeIndexChecked) return;
1912 if (superType is ClassDef)
1913 ((ClassDef)superType).CheckTypeIndex();
1914 typeIndex = superType.GetTypeIndex();
1915 typeIndexChecked = true;
1918 internal sealed override void BuildTables(MetaData md)
1921 if ((flags & (uint)TypeAttr.Interface) != 0) { superType = null; }
1922 // Console.WriteLine("Building tables for " + name);
1923 if (layout != null) md.AddToTable(MDTable.ClassLayout,layout);
1924 // Console.WriteLine("adding methods " + methods.Count);
1925 methodIx = md.TableIndex(MDTable.Method);
1926 for (int i=0; i < methods.Count; i++) {
1927 md.AddToTable(MDTable.Method,(MetaDataElement)methods[i]);
1928 ((MethodDef)methods[i]).BuildTables(md);
1930 // Console.WriteLine("adding fields");
1931 fieldIx = md.TableIndex(MDTable.Field);
1932 for (int i=0; i < fields.Count; i++) {
1933 md.AddToTable(MDTable.Field,(MetaDataElement)fields[i]);
1934 ((FieldDef)fields[i]).BuildTables(md);
1936 // Console.WriteLine("adding events and properties");
1937 if (events != null) {
1938 for (int i=0; i < events.Count; i++) {
1939 md.AddToTable(MDTable.Event,(Event)events[i]);
1940 ((Event)events[i]).BuildTables(md);
1942 md.AddToTable(MDTable.EventMap,
1943 new MapElem(this,((Event)events[0]).Row,MDTable.Event));
1945 if (properties != null) {
1946 for (int i=0; i < properties.Count; i++) {
1947 md.AddToTable(MDTable.Property,(Property)properties[i]);
1948 ((Property)properties[i]).BuildTables(md);
1950 md.AddToTable(MDTable.PropertyMap,new MapElem(this,
1951 ((Property)properties[0]).Row,MDTable.Property));
1953 // Console.WriteLine("End of building tables");
1957 internal sealed override uint Size(MetaData md)
1959 return 4 + 2 * md.StringsIndexSize() +
1960 md.CodedIndexSize(CIx.TypeDefOrRef) +
1961 md.TableIndexSize(MDTable.Field) +
1962 md.TableIndexSize(MDTable.Method);
1965 internal sealed override void Write(FileImage output)
1967 output.Write(flags);
1968 output.StringsIndex(nameIx);
1969 output.StringsIndex(nameSpaceIx);
1970 //if (superType != null)
1971 // Console.WriteLine("getting coded index for superType of " + name + " = " + superType.GetCodedIx(CIx.TypeDefOrRef));
1972 output.WriteCodedIndex(CIx.TypeDefOrRef,superType);
1973 output.WriteIndex(MDTable.Field,fieldIx);
1974 output.WriteIndex(MDTable.Method,methodIx);
1977 internal sealed override uint TypeDefOrRefToken()
1984 internal sealed override void TypeSig(MemoryStream sig)
1986 if (!typeIndexChecked) CheckTypeIndex();
1987 sig.WriteByte(GetTypeIndex());
1988 MetaData.CompressNum(TypeDefOrRefToken(),sig);
1991 internal sealed override uint GetCodedIx(CIx code)
1994 case (CIx.TypeDefOrRef) : return 0;
1995 case (CIx.HasCustomAttr) : return 3;
1996 case (CIx.HasDeclSecurity) : return 0;
1997 case (CIx.TypeOrMethodDef) : return 0;
2004 /**************************************************************************/
2006 /// Descriptor for a class/interface declared in another module of THIS
2007 /// assembly, or in another assembly.
2009 public class ClassRef : Class, IExternRef, IResolutionScope {
2011 protected IResolutionScope parent;
2012 protected MetaData metaData;
2014 internal ClassRef(string nsName, string name, MetaData md) : base(nsName, name, md)
2017 tabIx = MDTable.TypeRef;
2021 /// Add a method to this class
2023 /// <param name="name">method name</param>
2024 /// <param name="retType">return type</param>
2025 /// <param name="pars">parameter types</param>
2026 /// <returns>a descriptor for this method</returns>
2027 public MethodRef AddMethod(string name, Type retType, Type[] pars)
2029 return AddMethod (name, retType, pars, 0);
2033 /// Add a method to this class
2035 /// <param name="name">method name</param>
2036 /// <param name="retType">return type</param>
2037 /// <param name="pars">parameter types</param>
2038 /// <param name="gen_param_count">num of generic parameters</param>
2039 /// <returns>a descriptor for this method</returns>
2040 public MethodRef AddMethod (string name, Type retType, Type[] pars, int gen_param_count)
2042 MethodRef meth = new MethodRef (this, name, retType, pars, false, null, gen_param_count);
2043 metaData.AddToTable(MDTable.MemberRef,meth);
2048 /// Add a method to this class
2050 /// <param name="name">method name</param>
2051 /// <param name="retType">return type</param>
2052 /// <param name="pars">parameter types</param>
2053 /// <returns>a descriptor for this method</returns>
2054 public MethodRef AddVarArgMethod(string name, Type retType,
2055 Type[] pars, Type[] optPars)
2057 MethodRef meth = new MethodRef(this,name,retType,pars,true,optPars, 0);
2058 metaData.AddToTable(MDTable.MemberRef,meth);
2063 /// Add a field to this class
2065 /// <param name="name">field name</param>
2066 /// <param name="fType">field type</param>
2067 /// <returns>a descriptor for this field</returns>
2068 public FieldRef AddField(string name, Type fType)
2070 FieldRef field = new FieldRef(this,name,fType);
2071 metaData.AddToTable(MDTable.MemberRef,field);
2075 public ClassRef AddClass (string nsName, string name)
2077 ClassRef aClass = new ClassRef(nsName,name,metaData);
2078 metaData.AddToTable(MDTable.TypeRef,aClass);
2079 aClass.SetParent(this);
2083 public ClassRef AddValueClass (string nsName, string name)
2085 ClassRef aClass = AddClass (nsName, name);
2086 aClass.MakeValueClass (ValueClass.ValueType);
2090 internal void SetParent(IResolutionScope par)
2095 internal override string TypeName()
2097 if ((parent != null) && (parent is AssemblyRef))
2098 return (nameSpace + "." + name + ", " + ((AssemblyRef)parent).TypeName());
2100 return (nameSpace + name);
2103 internal sealed override uint Size(MetaData md)
2105 return md.CodedIndexSize(CIx.ResolutionScope) + 2 *
2106 md.StringsIndexSize();
2109 internal sealed override void Write(FileImage output)
2111 output.WriteCodedIndex(CIx.ResolutionScope,(MetaDataElement) parent);
2112 output.StringsIndex(nameIx);
2113 output.StringsIndex(nameSpaceIx);
2116 internal override sealed uint TypeDefOrRefToken()
2119 cIx = (cIx << 2) | 0x1;
2123 internal override void TypeSig(MemoryStream sig)
2125 sig.WriteByte(GetTypeIndex());
2126 MetaData.CompressNum(TypeDefOrRefToken(),sig);
2129 internal sealed override uint GetCodedIx(CIx code)
2132 case (CIx.TypeDefOrRef) : return 1;
2133 case (CIx.HasCustomAttr) : return 2;
2134 case (CIx.MemberRefParent) : return 1;
2135 case (CIx.ResolutionScope) : return 3;
2142 /**************************************************************************/
2143 public class ExternClassRef : ClassRef {
2145 ExternClass externClass;
2147 internal ExternClassRef(TypeAttr attrs, string nsName, string name,
2148 MetaDataElement declRef, MetaData md) : base(nsName,name,md)
2150 externClass = new ExternClass(attrs,nameSpaceIx,nameIx,declRef);
2151 metaData.AddToTable(MDTable.ExportedType,externClass);
2154 internal ExternClassRef(string name, MetaData md) : base(null,name,md)
2158 public ClassRef AddNestedClass(TypeAttr attrs, string name)
2160 ExternClassRef nestedClass = new ExternClassRef(name,metaData);
2161 externClass = new ExternClass(attrs,0,nameIx,this.externClass);
2162 metaData.AddToTable(MDTable.ExportedType,externClass);
2168 /**************************************************************************/
2170 /// Descriptor for a class defined in another module of THIS assembly
2171 /// and exported (.class extern)
2174 internal class ExternClass : Class {
2176 MetaDataElement parent;
2179 internal ExternClass(TypeAttr attr, uint nsIx, uint nIx,
2180 MetaDataElement paren) : base(nsIx,nIx)
2184 tabIx = MDTable.ExportedType;
2187 internal sealed override uint Size(MetaData md)
2189 return 8 + 2* md.StringsIndexSize() + md.CodedIndexSize(CIx.Implementation);
2192 internal sealed override void Write(FileImage output)
2194 output.Write(flags);
2196 output.StringsIndex(nameIx);
2197 output.StringsIndex(nameSpaceIx);
2198 output.WriteCodedIndex(CIx.Implementation,parent);
2201 internal sealed override uint GetCodedIx(CIx code)
2204 case (CIx.HasCustomAttr) : return 17;
2205 case (CIx.Implementation) : return 2;
2212 public class GenParam : Class {
2215 private string param_name;
2216 private uint sigIx = 0;
2218 public GenParam (int index, string name, GenParamType ptype) : base ((byte) ptype)
2221 this.param_name = name;
2222 tabIx = MDTable.TypeSpec;
2226 get { return index; }
2227 set { index = value; }
2230 public string Name {
2231 get { return param_name; }
2232 set { param_name = value; }
2235 public GenParamType Type {
2236 get { return (GenParamType) GetTypeIndex (); }
2239 internal sealed override void BuildTables (MetaData md)
2243 MemoryStream str = new MemoryStream ();
2245 sigIx = md.AddToBlobHeap (str.ToArray ());
2250 internal sealed override void TypeSig(MemoryStream str)
2253 throw new PEFileException (String.Format ("Unresolved {0} - {1}", (GenParamType) GetTypeIndex (), param_name));
2254 str.WriteByte(typeIndex);
2255 MetaData.CompressNum ((uint) index, str);
2258 internal override uint Size(MetaData md)
2260 return md.BlobIndexSize();
2263 internal sealed override void Write (FileImage output)
2265 output.BlobIndex (sigIx);
2268 internal sealed override uint GetCodedIx(CIx code)
2271 case (CIx.TypeDefOrRef) : return 2;
2272 case (CIx.HasCustomAttr) : return 13;
2273 case (CIx.MemberRefParent) : return 4;
2279 public class GenericTypeInst : Class {
2281 private Type gen_type;
2282 private Type[] gen_param;
2283 bool inTable = false;
2286 public GenericTypeInst (Type gen_type, Type[] gen_param)
2287 : base ((byte) PrimitiveType.GenericInst.GetTypeIndex ())
2289 this.gen_type = gen_type;
2290 this.gen_param = gen_param;
2291 tabIx = MDTable.TypeSpec;
2294 internal override MetaDataElement GetTypeSpec (MetaData md)
2297 md.AddToTable (MDTable.TypeSpec, this);
2304 internal sealed override void TypeSig(MemoryStream str)
2306 str.WriteByte(typeIndex);
2307 gen_type.TypeSig (str);
2308 MetaData.CompressNum ((uint) gen_param.Length, str);
2309 foreach (Type param in gen_param)
2310 param.TypeSig (str);
2313 internal sealed override void BuildTables (MetaData md)
2317 MemoryStream str = new MemoryStream ();
2319 sigIx = md.AddToBlobHeap (str.ToArray ());
2324 internal sealed override uint Size (MetaData md)
2326 return md.BlobIndexSize ();
2329 internal sealed override void Write (FileImage output)
2331 output.BlobIndex (sigIx);
2334 internal sealed override uint GetCodedIx (CIx code)
2337 case (CIx.TypeDefOrRef): return 2;
2338 case (CIx.MemberRefParent): return 4;
2339 case (CIx.HasCustomAttr): return 13;
2345 public class GenericMethodSig {
2347 private Type[] gen_param;
2349 private uint sigIx = 0;
2351 public GenericMethodSig (Type[] gen_param)
2353 this.gen_param = gen_param;
2357 internal void TypeSig (MemoryStream str)
2359 str.WriteByte (0x0A); /* GENERIC_INST */
2360 MetaData.CompressNum ((uint) gen_param.Length, str);
2361 foreach (Type param in gen_param)
2362 param.TypeSig (str);
2365 internal uint GetSigIx (MetaData md)
2370 MemoryStream sig = new MemoryStream();
2372 sigIx = md.AddToBlobHeap (sig.ToArray());
2378 public class Sentinel : Type {
2380 public Sentinel () : base (0x41) { }
2382 internal sealed override void TypeSig(MemoryStream str)
2384 str.WriteByte(typeIndex);
2388 /**************************************************************************/
2390 /// Descriptor for a FunctionPointer type
2393 public class MethPtrType : Type {
2405 /// Create a new function pointer type
2407 /// <param name="meth">the function to be referenced</param>
2408 public MethPtrType (CallConv callconv, Type retType, Type[] pars,
2409 bool varArgMeth, Type[] optPars) : base(0x1B)
2411 this.retType = retType;
2412 callConv = callconv;
2414 this.varArgMeth = varArgMeth;
2415 if (parList != null) numPars = (uint)parList.Length;
2417 optParList = optPars;
2418 if (optParList != null) numOptPars = (uint)optParList.Length;
2419 callConv |= CallConv.Vararg;
2421 tabIx = MDTable.TypeSpec;
2424 internal sealed override void TypeSig(MemoryStream sig)
2426 sig.WriteByte(typeIndex);
2427 // Bootlegged from method ref
2428 sig.WriteByte((byte)callConv);
2429 MetaData.CompressNum (numPars + numOptPars, sig);
2430 retType.TypeSig (sig);
2431 for (int i=0; i < numPars; i++) {
2432 parList[i].TypeSig (sig);
2435 sig.WriteByte (0x41); // Write the sentinel
2436 for (int i=0; i < numOptPars; i++) {
2437 optParList[i].TypeSig (sig);
2442 internal sealed override void BuildTables(MetaData md)
2445 MemoryStream sig = new MemoryStream();
2447 sigIx = md.AddToBlobHeap(sig.ToArray());
2451 internal sealed override uint Size(MetaData md)
2453 return md.BlobIndexSize();
2456 internal sealed override void Write(FileImage output)
2458 output.BlobIndex(sigIx);
2461 internal sealed override uint GetCodedIx(CIx code) { return 0x1B; }
2466 /* Classes for Arrays */
2469 /// The IL Array type
2471 public abstract class Array : Type {
2473 protected Type elemType;
2474 protected MetaData metaData;
2475 protected string cnameSpace, cname;
2477 internal Array(Type eType, byte TypeId) : base(TypeId)
2480 tabIx = MDTable.TypeSpec;
2485 /// Single dimensional array with zero lower bound
2487 public class ZeroBasedArray : Array {
2490 /// Create a new array - elementType[]
2492 /// <param name="elementType">the type of the array elements</param>
2493 public ZeroBasedArray(Type elementType) : base (elementType, PrimitiveType.SZArray.GetTypeIndex ()) { }
2495 internal sealed override void TypeSig(MemoryStream str)
2497 str.WriteByte(typeIndex);
2498 elemType.TypeSig(str);
2504 /// Multi dimensional array with explicit bounds
2506 public class BoundArray : Array {
2512 /// Create a new multi dimensional array type
2513 /// eg. elemType[1..5,3..10,5,,] would be
2514 /// new BoundArray(elemType,5,[1,3,0],[5,10,4])
2516 /// <param name="elementType">the type of the elements</param>
2517 /// <param name="dimensions">the number of dimensions</param>
2518 /// <param name="loBounds">lower bounds of dimensions</param>
2519 /// <param name="sizes">sizes for the dimensions</param>
2520 public BoundArray(Type elementType, uint dimensions, int[] loBounds,
2521 int[] sizes) : base (elementType,0x14)
2523 numDims = dimensions;
2524 lowerBounds = loBounds;
2529 /// Create a new multi dimensional array type
2530 /// eg. elemType[5,10,20] would be new BoundArray(elemType,3,[5,10,20])
2532 /// <param name="elementType">the type of the elements</param>
2533 /// <param name="dimensions">the number of dimensions</param>
2534 /// <param name="size">the sizes of the dimensions</param>
2535 public BoundArray(Type elementType, uint dimensions, int[] size)
2536 : base (elementType,0x14)
2538 numDims = dimensions;
2543 /// Create a new multi dimensional array type
2544 /// eg. elemType[,,] would be new BoundArray(elemType,3)
2546 /// <param name="elementType">the type of the elements</param>
2547 /// <param name="dimensions">the number of dimensions</param>
2548 public BoundArray(Type elementType, uint dimensions)
2549 : base (elementType,0x14)
2551 numDims = dimensions;
2554 internal sealed override void TypeSig(MemoryStream str)
2556 str.WriteByte(typeIndex);
2557 elemType.TypeSig(str);
2558 MetaData.CompressNum(numDims,str);
2559 if ((sizes != null) && (sizes.Length > 0)) {
2561 MetaData.CompressNum((uint)sizes.Length,str);
2562 for (int i=0; i < sizes.Length; i++) {
2563 MetaData.CompressNum((uint)sizes[i],str);
2565 } else str.WriteByte(0);
2566 if ((lowerBounds != null) && (lowerBounds.Length > 0)) {
2567 MetaData.CompressNum((uint)lowerBounds.Length,str);
2568 for (int i=0; i < lowerBounds.Length; i++) {
2569 CompressSignedNum (lowerBounds[i],str);
2571 } else str.WriteByte(0);
2573 private void CompressSignedNum (int val, MemoryStream str)
2575 uint uval = (uint) val;
2582 /* Map the signed number to an unsigned number in two ways.
2584 fval: left-rotated 2's complement representation
2585 sval: map the signed number to unsigned as follows: 0 -> 0, -1 -> 1, 1 -> 2, -2 -> 3, 2 -> 4, ....
2586 the mapping is: x -> 2*|x| - signbit(x)
2588 uint fval = (uval << 1) | sign;
2589 int sval = (val << 1) - sign;
2591 /* An overly clever transformation:
2593 a. sval is used to determine the number of bytes in the compressed representation.
2594 b. fval is truncated to the appropriate number of bits and output using the
2595 normal unsigned-int compressor.
2597 However, or certain values, the truncated fval doesn't carry enough information to round trip.
2599 (fval & 0x3FFF) <= 0x7F => compressor emits 1 byte, not 2 => there is aliasing of values
2601 So, we use full 4 bytes to encode such values.
2603 LAMESPEC: The Microsoft implementation doesn't appear to handle this subtle case.
2604 e.g., it ends up encoding -8192 as the byte 0x01, which decodes to -64
2607 MetaData.CompressNum (fval & 0x7F, str);
2608 else if (sval <= 0x3FFF && (fval & 0x3FFF) > 0x7F)
2609 MetaData.CompressNum (fval & 0x3FFF, str);
2610 else if (sval <= 0x1FFFFFFF && (fval & 0x1FFFFFFF) > 0x3FFF)
2611 MetaData.CompressNum (fval & 0x1FFFFFFF, str);
2613 /* FIXME: number cannot be represented. Report a warning. */
2614 // throw new Exception ("cannot represent signed value" + -val);
2615 MetaData.CompressNum (fval, str);
2622 /* Empty interface for grouping TypeRef's possible ResolutionScope
2623 namely : Module, ModuleRef, AssemblyRef and TypeRef */
2624 public interface IResolutionScope {
2627 /**************************************************************************/
2629 /// Base class for scopes (extended by Module, ModuleRef, Assembly, AssemblyRef)
2631 public abstract class ResolutionScope : MetaDataElement, IResolutionScope {
2633 protected uint nameIx = 0;
2634 protected MetaData metaData;
2635 protected string name;
2637 internal ResolutionScope(string name, MetaData md)
2641 nameIx = md.AddToStringsHeap(name);
2644 internal string GetName() { return name; }
2648 /**************************************************************************/
2650 /// Descriptor for THIS assembly (.assembly)
2652 public class Assembly : ResolutionScope {
2654 ushort majorVer, minorVer, buildNo, revisionNo;
2657 uint keyIx = 0, cultIx = 0;
2658 bool hasPublicKey = false;
2660 internal Assembly(string name, MetaData md) : base(name,md)
2662 tabIx = MDTable.Assembly;
2666 /// Add details about THIS assembly
2668 /// <param name="majVer">Major Version</param>
2669 /// <param name="minVer">Minor Version</param>
2670 /// <param name="bldNo">Build Number</param>
2671 /// <param name="revNo">Revision Number</param>
2672 /// <param name="key">Hash Key</param>
2673 /// <param name="hash">Hash Algorithm</param>
2674 /// <param name="cult">Culture</param>
2675 public void AddAssemblyInfo(int majVer, int minVer, int bldNo, int revNo,
2676 byte[] key, uint hash, string cult)
2678 majorVer = (ushort)majVer;
2679 minorVer = (ushort)minVer;
2680 buildNo = (ushort)bldNo;
2681 revisionNo = (ushort)revNo;
2683 hasPublicKey = (key != null);
2684 keyIx = metaData.AddToBlobHeap(key);
2685 cultIx = metaData.AddToStringsHeap(cult);
2689 /// Add an attribute to THIS assembly
2691 /// <param name="aa">assembly attribute</param>
2692 public void AddAssemblyAttr(AssemAttr aa)
2697 internal sealed override uint Size(MetaData md)
2699 return 16 + md.BlobIndexSize() + 2 * md.StringsIndexSize();
2702 internal sealed override void Write(FileImage output)
2704 // Console.WriteLine("Writing assembly element with nameIx of " + nameIx + " at file offset " + output.Seek(0,SeekOrigin.Current));
2705 output.Write((uint)hashAlgId);
2706 output.Write(majorVer);
2707 output.Write(minorVer);
2708 output.Write(buildNo);
2709 output.Write(revisionNo);
2710 output.Write(flags);
2711 output.BlobIndex(keyIx);
2712 output.StringsIndex(nameIx);
2713 output.StringsIndex(cultIx);
2716 internal sealed override uint GetCodedIx(CIx code)
2719 case (CIx.HasCustomAttr) : return 14;
2720 case (CIx.HasDeclSecurity) : return 2;
2725 internal bool HasPublicKey {
2726 get { return hasPublicKey; }
2730 /**************************************************************************/
2732 /// Descriptor for THIS module
2734 public class Module : ResolutionScope, IExternRef {
2739 internal Module(string name, MetaData md) : base(name,md)
2741 mvid = Guid.NewGuid();
2742 mvidIx = md.AddToGUIDHeap(mvid);
2743 tabIx = MDTable.Module;
2747 get { return mvid; }
2750 public ClassRef AddClass(string nsName, string name)
2752 ClassRef aClass = new ClassRef (nsName, name, metaData);
2753 metaData.AddToTable (MDTable.TypeRef, aClass);
2754 aClass.SetParent (this);
2758 public ClassRef AddValueClass(string nsName, string name)
2760 ClassRef aClass = AddClass (nsName, name);
2761 aClass.MakeValueClass (ValueClass.ValueType);
2765 internal sealed override uint Size(MetaData md)
2767 return 2 + md.StringsIndexSize() + 3 * md.GUIDIndexSize();
2770 internal sealed override void Write(FileImage output)
2772 output.Write((short)0);
2773 output.StringsIndex(nameIx);
2774 output.GUIDIndex(mvidIx);
2775 output.GUIDIndex(0);
2776 output.GUIDIndex(0);
2779 internal sealed override uint GetCodedIx(CIx code)
2782 case (CIx.HasCustomAttr) : return 7;
2783 case (CIx.ResolutionScope) : return 0;
2788 /**************************************************************************/
2790 /// Descriptor for another module in THIS assembly
2792 public class ModuleRef : ResolutionScope, IExternRef {
2794 internal ModuleRef(MetaData md, string name) : base(name,md)
2796 tabIx = MDTable.ModuleRef;
2800 /// Add a class to this external module. This is a class declared in
2801 /// another module of THIS assembly.
2803 /// <param name="nsName">name space name</param>
2804 /// <param name="name">class name</param>
2805 /// <returns>a descriptor for this class in another module</returns>
2806 public ClassRef AddClass(string nsName, string name)
2808 ClassRef aClass = new ClassRef(nsName,name,metaData);
2809 metaData.AddToTable(MDTable.TypeRef,aClass);
2810 aClass.SetParent(this);
2815 /// Make a file descriptor to correspond to this module. The file
2816 /// descriptor will have the same name as the module descriptor
2818 /// <param name="hashBytes">the hash of the file</param>
2819 /// <param name="hasMetaData">the file contains metadata</param>
2820 /// <param name="entryPoint">the program entry point is in this file</param>
2821 /// <returns>a descriptor for the file which contains this module</returns>
2822 public FileRef MakeFile(byte[] hashBytes, bool hasMetaData, bool entryPoint)
2824 FileRef file = new FileRef(nameIx,hashBytes,hasMetaData,entryPoint,metaData);
2825 metaData.AddToTable(MDTable.File,file);
2830 /// Add a value class to this module. This is a class declared in
2831 /// another module of THIS assembly.
2833 /// <param name="nsName">name space name</param>
2834 /// <param name="name">class name</param>
2835 /// <returns></returns>
2836 public ClassRef AddValueClass(string nsName, string name)
2838 ClassRef aClass = new ClassRef(nsName,name,metaData);
2839 metaData.AddToTable(MDTable.TypeRef,aClass);
2840 aClass.SetParent(this);
2841 aClass.MakeValueClass(ValueClass.ValueType);
2846 /// Add a class which is declared public in this external module of
2847 /// THIS assembly. This class will be exported from this assembly.
2848 /// The ilasm syntax for this is .extern class
2850 /// <param name="attrSet">attributes of the class to be exported</param>
2851 /// <param name="nsName">name space name</param>
2852 /// <param name="name">external class name</param>
2853 /// <param name="declFile">the file where the class is declared</param>
2854 /// <param name="isValueClass">is this class a value type?</param>
2855 /// <returns>a descriptor for this external class</returns>
2856 public ExternClassRef AddExternClass(TypeAttr attrSet, string nsName,
2857 string name, FileRef declFile,
2858 bool isValueClass) {
2859 ExternClassRef cRef = new ExternClassRef(attrSet,nsName,name,declFile,metaData);
2860 metaData.AddToTable(MDTable.TypeRef,cRef);
2861 cRef.SetParent(this);
2862 if (isValueClass) cRef.MakeValueClass(ValueClass.ValueType);
2867 /// Add a "global" method in another module
2869 /// <param name="name">method name</param>
2870 /// <param name="retType">return type</param>
2871 /// <param name="pars">method parameter types</param>
2872 /// <returns>a descriptor for this method in anther module</returns>
2873 public MethodRef AddMethod(string name, Type retType, Type[] pars)
2875 MethodRef meth = new MethodRef(this,name,retType,pars,false,null, 0);
2876 metaData.AddToTable(MDTable.MemberRef,meth);
2881 /// Add a vararg method to this class
2883 /// <param name="name">method name</param>
2884 /// <param name="retType">return type</param>
2885 /// <param name="pars">parameter types</param>
2886 /// <param name="optPars">optional param types for this vararg method</param>
2887 /// <returns>a descriptor for this method</returns>
2888 public MethodRef AddVarArgMethod(string name, Type retType,
2889 Type[] pars, Type[] optPars) {
2890 MethodRef meth = new MethodRef(this,name,retType,pars,true,optPars, 0);
2891 metaData.AddToTable(MDTable.MemberRef,meth);
2896 /// Add a field in another module
2898 /// <param name="name">field name</param>
2899 /// <param name="fType">field type</param>
2900 /// <returns>a descriptor for this field in another module</returns>
2901 public FieldRef AddField(string name, Type fType)
2903 FieldRef field = new FieldRef(this,name,fType);
2904 metaData.AddToTable(MDTable.MemberRef,field);
2908 internal sealed override uint Size(MetaData md)
2910 return md.StringsIndexSize();
2913 internal sealed override void Write(FileImage output)
2915 output.StringsIndex(nameIx);
2918 internal sealed override uint GetCodedIx(CIx code)
2921 case (CIx.HasCustomAttr) : return 12;
2922 case (CIx.MemberRefParent) : return 2;
2923 case (CIx.ResolutionScope) : return 1;
2930 #region Classes for Constants
2932 /// Descriptor for a constant value
2934 public abstract class Constant {
2935 protected uint size = 0;
2936 protected Type type;
2937 protected uint blobIndex;
2938 protected bool addedToBlobHeap = false;
2940 internal Constant() { }
2942 internal virtual uint GetBlobIndex(MetaData md) { return 0; }
2944 internal uint GetSize() { return size; }
2946 internal byte GetTypeIndex() { return type.GetTypeIndex(); }
2948 internal virtual void Write(BinaryWriter bw) { }
2952 /// Descriptor for a constant value
2954 public abstract class DataConstant : Constant {
2955 private uint dataOffset = 0;
2957 internal DataConstant() { }
2959 public uint DataOffset {
2960 get { return dataOffset; }
2961 set { dataOffset = value; }
2967 /// Boolean constant
2969 public class BoolConst : DataConstant {
2973 /// Create a new boolean constant with the value "val"
2975 /// <param name="val">value of this boolean constant</param>
2976 public BoolConst(bool val)
2980 type = PrimitiveType.Boolean;
2983 internal sealed override uint GetBlobIndex(MetaData md)
2985 if (!addedToBlobHeap) {
2986 if (val) blobIndex = md.AddToBlobHeap((sbyte)1);
2987 else blobIndex = md.AddToBlobHeap((sbyte)0);
2988 addedToBlobHeap = true;
2993 internal sealed override void Write(BinaryWriter bw)
2995 if (val) bw.Write((sbyte)1);
2996 else bw.Write((sbyte)0);
3001 public class ByteArrConst : DataConstant {
3002 internal byte[] val;
3004 public ByteArrConst(byte[] val)
3006 type = PrimitiveType.String;
3008 size = (uint)val.Length;
3012 get { return type; }
3013 set { type = value; }
3016 internal sealed override uint GetBlobIndex(MetaData md)
3018 if (!addedToBlobHeap) {
3019 blobIndex = md.AddToBlobHeap(val);
3020 addedToBlobHeap = true;
3025 internal sealed override void Write(BinaryWriter bw)
3032 public class CharConst : Constant {
3035 public CharConst(char val)
3039 type = PrimitiveType.Char;
3042 internal sealed override uint GetBlobIndex(MetaData md)
3044 if (!addedToBlobHeap) {
3045 blobIndex = md.AddToBlobHeap(val);
3046 addedToBlobHeap = true;
3051 internal sealed override void Write(BinaryWriter bw)
3058 public class FloatConst : DataConstant {
3061 public FloatConst(float val)
3065 type = PrimitiveType.Float32;
3068 internal sealed override uint GetBlobIndex(MetaData md)
3070 if (!addedToBlobHeap) {
3071 blobIndex = md.AddToBlobHeap(val);
3072 addedToBlobHeap = true;
3077 internal sealed override void Write(BinaryWriter bw)
3084 public class DoubleConst : DataConstant {
3087 public DoubleConst(double val)
3091 type = PrimitiveType.Float64;
3094 internal sealed override uint GetBlobIndex(MetaData md)
3096 if (!addedToBlobHeap) {
3097 blobIndex = md.AddToBlobHeap(val);
3098 addedToBlobHeap = true;
3103 internal sealed override void Write(BinaryWriter bw)
3110 public class IntConst : DataConstant {
3113 public IntConst(sbyte val)
3117 type = PrimitiveType.Int8;
3120 public IntConst(short val)
3124 type = PrimitiveType.Int16;
3127 public IntConst(int val)
3131 type = PrimitiveType.Int32;
3134 public IntConst(long val)
3138 type = PrimitiveType.Int64;
3141 internal sealed override uint GetBlobIndex(MetaData md)
3143 if (!addedToBlobHeap) {
3145 case (1) : blobIndex = md.AddToBlobHeap((sbyte)val); break;
3146 case (2) : blobIndex = md.AddToBlobHeap((short)val); break;
3147 case (4) : blobIndex = md.AddToBlobHeap((int)val); break;
3148 default : blobIndex = md.AddToBlobHeap(val); break;
3150 addedToBlobHeap = true;
3155 internal sealed override void Write(BinaryWriter bw)
3158 case (1) : bw.Write((sbyte)val); break;
3159 case (2) : bw.Write((short)val); break;
3160 case (4) : bw.Write((int)val); break;
3161 default : bw.Write(val); break;
3167 public class UIntConst : DataConstant {
3170 public UIntConst(byte val)
3174 type = PrimitiveType.UInt8;
3176 public UIntConst(ushort val)
3180 type = PrimitiveType.UInt16;
3182 public UIntConst(uint val)
3186 type = PrimitiveType.UInt32;
3188 public UIntConst(ulong val)
3192 type = PrimitiveType.UInt64;
3195 internal sealed override uint GetBlobIndex(MetaData md)
3197 if (!addedToBlobHeap) {
3199 case (1) : blobIndex = md.AddToBlobHeap((byte)val); break;
3200 case (2) : blobIndex = md.AddToBlobHeap((ushort)val); break;
3201 case (4) : blobIndex = md.AddToBlobHeap((uint)val); break;
3202 default : blobIndex = md.AddToBlobHeap(val); break;
3204 addedToBlobHeap = true;
3209 internal sealed override void Write(BinaryWriter bw)
3212 case (1) : bw.Write((byte)val); break;
3213 case (2) : bw.Write((ushort)val); break;
3214 case (4) : bw.Write((uint)val); break;
3215 default : bw.Write(val); break;
3221 public class StringConst : DataConstant {
3222 internal string val;
3224 public StringConst(string val)
3227 size = (uint)val.Length; // need to add null ??
3228 type = PrimitiveType.String;
3231 internal sealed override uint GetBlobIndex(MetaData md)
3233 if (!addedToBlobHeap) {
3234 byte [] b = Encoding.Unicode.GetBytes (val);
3235 blobIndex = md.AddToBlobHeap(b);
3236 addedToBlobHeap = true;
3241 internal sealed override void Write(BinaryWriter bw)
3248 public class NullConst : Constant {
3253 type = PrimitiveType.Class;
3256 internal sealed override uint GetBlobIndex(MetaData md)
3258 if (!addedToBlobHeap) {
3259 blobIndex = md.AddToBlobHeap((int)0);
3260 addedToBlobHeap = true;
3265 internal sealed override void Write(BinaryWriter bw)
3272 public class AddressConstant : DataConstant {
3275 public AddressConstant(DataConstant dConst)
3279 type = PrimitiveType.TypedRef;
3282 internal sealed override void Write(BinaryWriter bw)
3284 ((FileImage)bw).WriteDataRVA(data.DataOffset);
3289 public class RepeatedConstant : DataConstant {
3293 public RepeatedConstant(DataConstant dConst, int repeatCount)
3296 repCount = (uint)repeatCount;
3297 int[] sizes = new int[1];
3298 sizes[0] = repeatCount;
3299 type = new BoundArray(type,1,sizes);
3300 size = data.GetSize() * repCount;
3303 internal sealed override void Write(BinaryWriter bw)
3305 for (int i=0; i < repCount; i++) {
3312 public class ArrayConstant : DataConstant {
3313 DataConstant[] dataVals;
3315 public ArrayConstant(DataConstant[] dVals)
3318 for (int i=0; i < dataVals.Length; i++) {
3319 size += dataVals[i].GetSize();
3323 public int? ExplicitSize { get; set; }
3325 internal sealed override void Write(BinaryWriter bw)
3327 for (int i=0; i < dataVals.Length; i++) {
3328 dataVals[i].Write(bw);
3334 public class ClassType : Constant {
3338 public ClassType(string className)
3341 type = PrimitiveType.ClassType;
3344 public ClassType(Class classDesc)
3347 type = PrimitiveType.ClassType;
3350 internal override void Write(BinaryWriter bw)
3352 if (name == null) name = desc.TypeName();
3360 /**************************************************************************/
3362 /// Descriptor for a custom modifier of a type (modopt or modreq)
3365 public class CustomModifiedType : Type {
3369 PrimitiveTypeRef cmodPrimType;
3372 /// Create a new custom modifier for a type
3374 /// <param name="type">the type to be modified</param>
3375 /// <param name="cmod">the modifier</param>
3376 /// <param name="cmodType">the type reference to be associated with the type</param>
3377 public CustomModifiedType(Type type, CustomModifier cmod, Class cmodType)
3381 this.cmodType = cmodType;
3384 public CustomModifiedType(Type type, CustomModifier cmod, PrimitiveTypeRef cmodType)
3388 this.cmodPrimType = cmodType;
3391 internal sealed override void TypeSig(MemoryStream str)
3393 str.WriteByte(typeIndex);
3395 if (cmodType != null) {
3396 MetaData.CompressNum(cmodType.TypeDefOrRefToken(),str);
3398 MetaData.CompressNum(cmodPrimType.TypeDefOrRefToken(),str);
3406 /**************************************************************************/
3408 /// Base class for Event and Property descriptors
3411 public class Feature : MetaDataElement {
3413 internal enum MethodType : ushort { Setter = 0x01, Getter, Other = 0x04, AddOn = 0x08,
3414 RemoveOn = 0x10, Fire = 0x20 }
3416 private static readonly int INITSIZE = 5;
3417 private static readonly ushort specialName = 0x200;
3418 private static readonly ushort rtSpecialName = 0x400;
3420 protected ClassDef parent;
3421 protected ushort flags = 0;
3422 protected string name;
3423 protected int tide = 0;
3424 protected uint nameIx;
3425 protected MethodSemantics[] methods = new MethodSemantics[INITSIZE];
3427 internal Feature(string name, ClassDef par)
3433 internal void AddMethod(MethodDef meth, MethodType mType)
3435 if (tide >= methods.Length) {
3436 int len = methods.Length;
3437 MethodSemantics[] mTmp = methods;
3438 methods = new MethodSemantics[len * 2];
3439 for (int i=0; i < len; i++) {
3440 methods[i] = mTmp[i];
3443 methods[tide++] = new MethodSemantics(mType,meth,this);
3447 /// Set the specialName attribute for this Event or Property
3449 public void SetSpecialName()
3451 flags |= specialName;
3455 /// Set the RTSpecialName attribute for this Event or Property
3457 public void SetRTSpecialName()
3459 flags |= rtSpecialName;
3464 /**************************************************************************/
3466 /// Descriptor for an event
3468 public class Event : Feature {
3472 internal Event(string name, Type eType, ClassDef parent)
3473 : base(name, parent)
3476 tabIx = MDTable.Event;
3480 /// Add the addon method to this event
3482 /// <param name="addon">the addon method</param>
3483 public void AddAddon(MethodDef addon)
3485 AddMethod(addon,MethodType.AddOn);
3489 /// Add the removeon method to this event
3491 /// <param name="removeOn">the removeon method</param>
3492 public void AddRemoveOn(MethodDef removeOn)
3494 AddMethod(removeOn,MethodType.RemoveOn);
3498 /// Add the fire method to this event
3500 /// <param name="fire">the fire method</param>
3501 public void AddFire(MethodDef fire)
3503 AddMethod(fire,MethodType.Fire);
3507 /// Add another method to this event
3509 /// <param name="other">the method to be added</param>
3510 public void AddOther(MethodDef other)
3512 AddMethod(other,MethodType.Other);
3515 internal sealed override void BuildTables(MetaData md)
3518 nameIx = md.AddToStringsHeap(name);
3519 for (int i=0; i < tide; i++) {
3520 md.AddToTable(MDTable.MethodSemantics,methods[i]);
3525 internal sealed override uint Size(MetaData md)
3527 return 2 + md.StringsIndexSize() + md.CodedIndexSize(CIx.TypeDefOrRef);
3530 internal sealed override void Write(FileImage output)
3532 output.Write(flags);
3533 output.StringsIndex(nameIx);
3534 output.WriteCodedIndex(CIx.TypeDefOrRef,eventType);
3537 internal sealed override uint GetCodedIx(CIx code)
3540 case (CIx.HasCustomAttr) : return 10;
3541 case (CIx.HasSemantics) : return 0;
3548 /**************************************************************************/
3550 /// Descriptor for the Property of a class
3552 public class Property : Feature {
3554 private static readonly byte PropertyTag = 0x8;
3555 private bool instance;
3556 MethodDef getterMeth;
3557 ConstantElem constVal;
3558 uint typeBlobIx = 0;
3563 internal Property(string name, Type retType, Type[] pars, ClassDef parent) : base(name, parent)
3565 returnType = retType;
3567 if (pars != null) numPars = (uint)pars.Length;
3568 tabIx = MDTable.Property;
3572 /// Add a set method to this property
3574 /// <param name="setter">the set method</param>
3575 public void AddSetter(MethodDef setter)
3577 AddMethod(setter,MethodType.Setter);
3581 /// Add a get method to this property
3583 /// <param name="getter">the get method</param>
3584 public void AddGetter(MethodDef getter)
3586 AddMethod(getter,MethodType.Getter);
3587 getterMeth = getter;
3591 /// Add another method to this property
3593 /// <param name="other">the method</param>
3594 public void AddOther(MethodDef other)
3596 AddMethod(other,MethodType.Other);
3600 /// Add an initial value for this property
3602 /// <param name="constVal">the initial value for this property</param>
3603 public void AddInitValue(Constant constVal)
3605 this.constVal = new ConstantElem(this,constVal);
3608 public void SetInstance (bool isInstance)
3610 this.instance = isInstance;
3613 internal sealed override void BuildTables(MetaData md)
3616 nameIx = md.AddToStringsHeap(name);
3617 MemoryStream sig = new MemoryStream();
3618 byte tag = PropertyTag;
3622 MetaData.CompressNum(numPars,sig);
3623 returnType.TypeSig(sig);
3624 for (int i=0; i < numPars; i++) {
3625 parList[i].TypeSig(sig);
3627 typeBlobIx = md.AddToBlobHeap(sig.ToArray());
3628 for (int i=0; i < tide; i++) {
3629 md.AddToTable(MDTable.MethodSemantics,methods[i]);
3631 if (constVal != null) {
3632 md.AddToTable(MDTable.Constant,constVal);
3633 constVal.BuildTables(md);
3638 internal sealed override uint Size(MetaData md)
3640 return 2 + md.StringsIndexSize() + md.BlobIndexSize();
3643 internal sealed override void Write(FileImage output)
3645 output.Write(flags);
3646 output.StringsIndex(nameIx);
3647 output.BlobIndex(typeBlobIx);
3650 internal sealed override uint GetCodedIx(CIx code)
3653 case (CIx.HasCustomAttr) : return 9;
3654 case (CIx.HasConst) : return 2;
3655 case (CIx.HasSemantics) : return 1;
3662 /**************************************************************************/
3664 /// Base class for field/methods (member of a class)
3666 public abstract class Member : MetaDataElement {
3668 protected string name;
3669 protected uint nameIx = 0, sigIx = 0;
3671 internal Member(string memName)
3674 tabIx = MDTable.MemberRef;
3679 /*****************************************************************************/
3681 /// Descriptor for a field of a class
3684 public abstract class Field : Member {
3686 protected static readonly byte FieldSig = 0x6;
3688 protected Type type;
3690 internal Field(string pfName, Type pfType) : base(pfName)
3696 /**************************************************************************/
3698 /// Descriptor for a field defined in a class of THIS assembly/module
3700 public class FieldDef : Field {
3702 //private static readonly uint PInvokeImpl = 0x2000;
3703 private static readonly ushort HasFieldRVA = 0x100;
3704 private static readonly ushort HasDefault = 0x8000;
3707 ConstantElem constVal;
3709 FieldMarshal marshalInfo;
3712 internal FieldDef(string name, Type fType) : base(name,fType)
3714 tabIx = MDTable.Field;
3717 internal FieldDef(FieldAttr attrSet, string name, Type fType) : base(name, fType)
3719 flags = (ushort)attrSet;
3720 tabIx = MDTable.Field;
3724 /// Add an attribute(s) to this field
3726 /// <param name="fa">the attribute(s) to be added</param>
3727 public void AddFieldAttr(FieldAttr fa)
3729 flags |= (ushort)fa;
3733 /// Add a value for this field
3735 /// <param name="val">the value for the field</param>
3736 public void AddValue(Constant val)
3738 constVal = new ConstantElem(this,val);
3739 flags |= HasDefault;
3743 /// Add an initial value for this field (at dataLabel) (.data)
3745 /// <param name="val">the value for the field</param>
3746 /// <param name="repeatVal">the number of repetitions of this value</param>
3747 public void AddDataValue(DataConstant val)
3749 flags |= HasFieldRVA;
3750 rva = new FieldRVA(this,val);
3754 /// Set the offset of the field. Used for sequential or explicit classes.
3757 /// <param name="offs">field offset</param>
3758 public void SetOffset(uint offs)
3760 layout = new FieldLayout(this,offs);
3764 /// Set the marshalling info for a field
3766 /// <param name="mInf"></param>
3767 public void SetMarshalInfo(NativeType marshallType)
3769 flags |= (ushort) FieldAttr.HasFieldMarshal;
3770 marshalInfo = new FieldMarshal(this,marshallType);
3773 internal sealed override void BuildTables(MetaData md)
3776 nameIx = md.AddToStringsHeap(name);
3777 MemoryStream sig = new MemoryStream();
3778 sig.WriteByte(FieldSig);
3780 sigIx = md.AddToBlobHeap(sig.ToArray());
3782 md.AddToTable(MDTable.FieldRVA,rva);
3783 rva.BuildTables(md);
3784 } else if (constVal != null) {
3785 md.AddToTable(MDTable.Constant,constVal);
3786 constVal.BuildTables(md);
3788 if (layout != null) md.AddToTable(MDTable.FieldLayout,layout);
3789 if (marshalInfo != null) {
3790 md.AddToTable(MDTable.FieldMarshal,marshalInfo);
3791 marshalInfo.BuildTables(md);
3796 internal sealed override uint Size(MetaData md)
3798 return 2 + md.StringsIndexSize() + md.BlobIndexSize();
3801 internal sealed override void Write(FileImage output)
3803 output.Write(flags);
3804 output.StringsIndex(nameIx);
3805 output.BlobIndex(sigIx);
3808 internal sealed override uint GetCodedIx(CIx code)
3811 case (CIx.HasConst) : return 0;
3812 case (CIx.HasCustomAttr) : return 1;
3813 case (CIx.HasFieldMarshal) : return 0;
3814 case (CIx.MemberForwarded) : return 0;
3821 /**************************************************************************/
3823 /// Descriptor for a field of a class defined in another assembly/module
3825 public class FieldRef : Field {
3827 MetaDataElement parent;
3829 internal FieldRef(MetaDataElement paren, string name, Type fType) : base(name, fType)
3834 internal sealed override void BuildTables(MetaData md)
3837 nameIx = md.AddToStringsHeap(name);
3838 MemoryStream sig = new MemoryStream();
3839 sig.WriteByte(FieldSig);
3841 sigIx = md.AddToBlobHeap(sig.ToArray());
3845 internal sealed override uint Size(MetaData md)
3847 return md.CodedIndexSize(CIx.MemberRefParent) + md.StringsIndexSize() + md.BlobIndexSize();
3850 internal sealed override void Write(FileImage output)
3852 output.WriteCodedIndex(CIx.MemberRefParent,parent);
3853 output.StringsIndex(nameIx);
3854 output.BlobIndex(sigIx);
3857 internal sealed override uint GetCodedIx(CIx code) { return 6; }
3861 /**************************************************************************/
3863 /// Base class for Method Descriptors
3866 public abstract class Method : Member {
3868 internal Method (string methName) : base (methName)
3871 public abstract void AddCallConv(CallConv cconv);
3872 internal abstract void TypeSig(MemoryStream sig);
3873 internal abstract uint GetSigIx(MetaData md);
3876 /**************************************************************************/
3878 /// Descriptor for a method defined in THIS assembly/module
3882 public class MethodDef : Method {
3884 private static readonly ushort PInvokeImpl = 0x2000;
3885 //private static readonly uint UnmanagedExport = 0x0008;
3886 // private static readonly byte LocalSigByte = 0x7;
3887 uint parIx = 0, textOffset = 0;
3888 private CallConv callConv = CallConv.Default;
3889 private int gen_param_count;
3892 CILInstructions code;
3896 ushort methFlags = 0, implFlags = 0;
3897 int maxStack = 0, numPars = 0;
3898 bool entryPoint = false;
3900 ArrayList varArgSigList;
3901 ImplMap pinvokeImpl;
3904 internal MethodDef (MetaData md, string name, Param ret_param, Param [] pars)
3905 : this (md, 0, 0, name, ret_param, pars)
3909 internal MethodDef (MetaData md, MethAttr mAttrSet, ImplAttr iAttrSet, string name,
3910 Param ret_param, Param [] pars)
3913 methFlags = (ushort)mAttrSet;
3914 implFlags = (ushort)iAttrSet;
3915 this.ret_param = ret_param;
3918 if (parList != null)
3919 numPars = parList.Length;
3920 tabIx = MDTable.Method;
3923 internal Param[] GetPars()
3928 internal override uint GetSigIx(MetaData md)
3930 MemoryStream sig = new MemoryStream();
3932 return md.AddToBlobHeap(sig.ToArray());
3935 public override void AddCallConv(CallConv cconv)
3941 /// Add some attributes to this method descriptor
3943 /// <param name="ma">the attributes to be added</param>
3944 public void AddMethAttribute(MethAttr ma)
3946 methFlags |= (ushort)ma;
3950 /// Add some implementation attributes to this method descriptor
3952 /// <param name="ia">the attributes to be added</param>
3953 public void AddImplAttribute(ImplAttr ia)
3955 implFlags |= (ushort)ia;
3958 public void AddPInvokeInfo(ModuleRef scope, string methName,
3959 PInvokeAttr callAttr) {
3960 pinvokeImpl = new ImplMap((ushort)callAttr,this,methName,scope);
3961 methFlags |= PInvokeImpl;
3965 /// Add a named generic type parameter
3967 public GenericParameter AddGenericParameter (short index, string name)
3969 return AddGenericParameter (index, name, 0);
3973 /// Add a named generic type parameter with attributes
3975 public GenericParameter AddGenericParameter (short index, string name, GenericParamAttributes attr)
3977 GenericParameter gp = new GenericParameter (this, metaData, index, name, attr);
3978 metaData.AddToTable (MDTable.GenericParam, gp);
3984 /// Set the maximum stack height for this method
3986 /// <param name="maxStack">the maximum height of the stack</param>
3987 public void SetMaxStack(int maxStack)
3989 this.maxStack = maxStack;
3993 /// Add local variables to this method
3995 /// <param name="locals">the locals to be added</param>
3996 /// <param name="initLocals">are locals initialised to default values</param>
3997 public void AddLocals(Local[] locals, bool initLocals)
3999 this.locals = locals;
4000 this.initLocals = initLocals;
4003 /* Add Marshal info for return type */
4004 public void AddRetTypeMarshallInfo (NativeType marshallType)
4006 ret_param.AddMarshallInfo (marshallType);
4010 /// Mark this method as having an entry point
4012 public void DeclareEntryPoint()
4018 /// Create a code buffer for this method to add the IL instructions to
4020 /// <returns>a buffer for this method's IL instructions</returns>
4021 public CILInstructions CreateCodeBuffer()
4023 code = new CILInstructions(metaData);
4028 /// Make a method reference descriptor for this method to be used
4029 /// as a callsite signature for this vararg method
4031 /// <param name="optPars">the optional pars for the vararg method call</param>
4032 /// <returns></returns>
4033 public MethodRef MakeVarArgSignature(Type[] optPars)
4035 Type[] pars = new Type[numPars];
4036 MethodRef varArgSig;
4037 for (int i=0; i < numPars; i++) {
4038 pars[i] = parList[i].GetParType();
4040 varArgSig = new MethodRef (this, name, ret_param.GetParType (), pars, true, optPars, 0);
4042 if (varArgSigList == null)
4043 varArgSigList = new ArrayList ();
4044 varArgSigList.Add (varArgSig);
4048 internal sealed override void TypeSig(MemoryStream sig)
4050 sig.WriteByte((byte)callConv);
4051 if ((callConv & CallConv.Generic) == CallConv.Generic)
4052 MetaData.CompressNum ((uint) gen_param_count, sig);
4053 MetaData.CompressNum((uint)numPars,sig);
4055 ret_param.seqNo = 0;
4056 ret_param.TypeSig (sig);
4057 for (ushort i=0; i < numPars; i++) {
4058 parList[i].seqNo = (ushort)(i+1);
4059 parList[i].TypeSig(sig);
4063 internal sealed override void BuildTables(MetaData md)
4066 if (pinvokeImpl != null) {
4067 md.AddToTable(MDTable.ImplMap,pinvokeImpl);
4068 pinvokeImpl.BuildTables(md);
4070 if (entryPoint) md.SetEntryPoint(this);
4072 if (locals != null) {
4073 localSig = new LocalSig(locals);
4074 md.AddToTable(MDTable.StandAloneSig,localSig);
4075 localSig.BuildTables(md);
4076 locToken = localSig.Token();
4079 code.CheckCode(locToken,initLocals,maxStack);
4080 textOffset = md.AddCode(code);
4082 nameIx = md.AddToStringsHeap(name);
4083 sigIx = GetSigIx(md);
4084 parIx = md.TableIndex(MDTable.Param);
4085 if (ret_param.HasMarshalInfo || ret_param.HasCustomAttr) {
4086 md.AddToTable(MDTable.Param, ret_param);
4087 ret_param.BuildTables(md);
4089 for (int i=0; i < numPars; i++) {
4090 md.AddToTable(MDTable.Param,parList[i]);
4091 parList[i].BuildTables(md);
4093 if (varArgSigList != null) {
4094 foreach (MethodRef varArgSig in varArgSigList) {
4095 md.AddToTable(MDTable.MemberRef,varArgSig);
4096 varArgSig.BuildTables(md);
4099 // Console.WriteLine("method has " + numPars + " parameters");
4103 internal sealed override uint Size(MetaData md)
4105 return 8 + md.StringsIndexSize() + md.BlobIndexSize() + md.TableIndexSize(MDTable.Param);
4108 internal sealed override void Write(FileImage output)
4110 if (ZeroRva ()) output.Write(0);
4111 else output.WriteCodeRVA(textOffset);
4112 output.Write(implFlags);
4113 output.Write(methFlags);
4114 output.StringsIndex(nameIx);
4115 output.BlobIndex(sigIx);
4116 output.WriteIndex(MDTable.Param,parIx);
4119 internal bool ZeroRva ()
4121 return (((methFlags & (ushort)MethAttr.Abstract) != 0) ||
4122 ((implFlags & (ushort)ImplAttr.Runtime) != 0) ||
4123 ((implFlags & (ushort)ImplAttr.InternalCall) != 0) ||
4124 (pinvokeImpl != null)); // TODO: Not entirely true but works for now
4127 internal sealed override uint GetCodedIx(CIx code)
4130 case (CIx.HasCustomAttr) : return 0;
4131 case (CIx.HasDeclSecurity) : return 1;
4132 case (CIx.MemberRefParent) : return 3;
4133 case (CIx.MethodDefOrRef) : return 0;
4134 case (CIx.MemberForwarded) : return 1;
4135 case (CIx.CustomAttributeType) : return 2;
4136 case (CIx.TypeOrMethodDef) : return 1;
4142 /**************************************************************************/
4144 /// Descriptor for a method defined in another assembly/module
4146 public class MethodRef : Method {
4148 private static readonly byte Sentinel = 0x41;
4149 Type[] parList, optParList;
4150 MetaDataElement parent;
4151 uint numPars = 0, numOptPars = 0;
4152 CallConv callConv = CallConv.Default;
4154 int gen_param_count;
4156 internal MethodRef(MetaDataElement paren, string name, Type retType,
4157 Type[] pars, bool varArgMeth, Type[] optPars, int gen_param_count) : base(name)
4161 this.retType = retType;
4162 if (parList != null) numPars = (uint)parList.Length;
4164 optParList = optPars;
4165 if (optParList != null) numOptPars = (uint)optParList.Length;
4166 callConv = CallConv.Vararg;
4168 this.gen_param_count = gen_param_count;
4171 internal override uint GetSigIx(MetaData md)
4173 MemoryStream sig = new MemoryStream();
4175 return md.AddToBlobHeap(sig.ToArray());
4178 public override void AddCallConv(CallConv cconv)
4183 internal sealed override void TypeSig(MemoryStream sig)
4185 sig.WriteByte((byte)callConv);
4186 if ((callConv & CallConv.Generic) == CallConv.Generic)
4187 MetaData.CompressNum ((uint) gen_param_count, sig);
4188 MetaData.CompressNum(numPars+numOptPars,sig);
4189 retType.TypeSig(sig);
4190 for (int i=0; i < numPars; i++) {
4191 parList[i].TypeSig(sig);
4193 if (numOptPars > 0) {
4194 sig.WriteByte(Sentinel);
4195 for (int i=0; i < numOptPars; i++) {
4196 optParList[i].TypeSig(sig);
4201 internal sealed override void BuildTables(MetaData md)
4204 nameIx = md.AddToStringsHeap(name);
4205 sigIx = GetSigIx(md);
4209 internal sealed override uint Size(MetaData md)
4211 return md.CodedIndexSize(CIx.MemberRefParent) + md.StringsIndexSize() + md.BlobIndexSize();
4214 internal sealed override void Write(FileImage output)
4216 output.WriteCodedIndex(CIx.MemberRefParent,parent);
4217 output.StringsIndex(nameIx);
4218 output.BlobIndex(sigIx);
4221 internal sealed override uint GetCodedIx(CIx code)
4224 case (CIx.HasCustomAttr) : return 6;
4225 case (CIx.MethodDefOrRef) : return 1;
4226 case (CIx.CustomAttributeType) : return 3;
4234 /**************************************************************************/
4236 /// Descriptors for native types used for marshalling
4238 public class NativeType {
4239 public static readonly NativeType Void = new NativeType(0x01);
4240 public static readonly NativeType Boolean = new NativeType(0x02);
4241 public static readonly NativeType Int8 = new NativeType(0x03);
4242 public static readonly NativeType UInt8 = new NativeType(0x04);
4243 public static readonly NativeType Int16 = new NativeType(0x05);
4244 public static readonly NativeType UInt16 = new NativeType(0x06);
4245 public static readonly NativeType Int32 = new NativeType(0x07);
4246 public static readonly NativeType UInt32 = new NativeType(0x08);
4247 public static readonly NativeType Int64 = new NativeType(0x09);
4248 public static readonly NativeType UInt64 = new NativeType(0x0A);
4249 public static readonly NativeType Float32 = new NativeType(0x0B);
4250 public static readonly NativeType Float64 = new NativeType(0x0C);
4251 public static readonly NativeType Currency = new NativeType(0x0F);
4252 public static readonly NativeType BStr = new NativeType(0x13);
4253 public static readonly NativeType LPStr = new NativeType(0x14);
4254 public static readonly NativeType LPWStr = new NativeType(0x15);
4255 public static readonly NativeType LPTStr = new NativeType(0x16);
4256 public static readonly NativeType FixedSysString = new NativeType(0x17);
4257 public static readonly NativeType IUnknown = new NativeType(0x19);
4258 public static readonly NativeType IDispatch = new NativeType(0x1A);
4259 public static readonly NativeType Struct = new NativeType(0x1B);
4260 public static readonly NativeType Interface = new NativeType(0x1C);
4261 public static readonly NativeType Int = new NativeType(0x1F);
4262 public static readonly NativeType UInt = new NativeType(0x20);
4263 public static readonly NativeType ByValStr = new NativeType(0x22);
4264 public static readonly NativeType AnsiBStr = new NativeType(0x23);
4265 public static readonly NativeType TBstr = new NativeType(0x24);
4266 public static readonly NativeType VariantBool = new NativeType(0x25);
4267 public static readonly NativeType FuncPtr = new NativeType(0x26);
4268 public static readonly NativeType AsAny = new NativeType(0x28);
4269 public static readonly NativeType LPStruct = new NativeType(0x2b);
4270 public static readonly NativeType Error = new NativeType(0x2d);
4272 protected byte typeIndex;
4274 internal NativeType(byte tyIx) { typeIndex = tyIx; }
4275 internal byte GetTypeIndex() { return typeIndex; }
4277 internal virtual byte[] ToBlob()
4279 byte[] bytes = new byte[1];
4280 bytes[0] = GetTypeIndex();
4286 public class FixedSysString : NativeType {
4290 public FixedSysString (uint size) : base (NativeType.FixedSysString.GetTypeIndex ())
4295 internal override byte [] ToBlob ()
4297 MemoryStream str = new MemoryStream ();
4298 str.WriteByte (GetTypeIndex ());
4299 MetaData.CompressNum (size, str);
4300 return str.ToArray ();
4305 public class NativeArray : NativeType {
4307 NativeType elemType;
4308 int numElem = -1, parNum = -1, elemMult = -1;
4310 public NativeArray(NativeType elemType) : this (elemType, -1, -1, -1)
4312 this.elemType = elemType;
4315 /* public NativeArray(NativeType elemType, int len) : base(0x2A) {
4316 this.elemType = elemType;
4321 public NativeArray(NativeType elemType, int numElem, int parNumForLen, int elemMult) : base(0x2A)
4323 this.elemType = elemType;
4324 this.numElem = numElem;
4325 parNum = parNumForLen;
4326 this.elemMult = elemMult;
4329 public NativeArray(NativeType elemType, int numElem, int parNumForLen)
4330 : this (elemType, numElem, parNumForLen, -1)
4334 internal override byte[] ToBlob()
4336 MemoryStream str = new MemoryStream();
4337 str.WriteByte(GetTypeIndex());
4338 if (elemType == null) str.WriteByte(0x50); // no info (MAX)
4339 else str.WriteByte(elemType.GetTypeIndex());
4341 /* see : mono/metadata/metadata.c:mono_metadata_parse_marshal_spec
4342 * LAMESPEC: Older spec versions say elemMult comes before
4343 * len. Newer spec versions don't talk about elemMult at
4344 * all, but csc still emits it, and it is used to distinguish
4345 * between parNum being 0, and parNum being omitted.
4350 return str.ToArray ();
4352 MetaData.CompressNum((uint) parNum,str);
4353 if (numElem != -1) {
4354 MetaData.CompressNum ((uint) numElem, str);
4356 // <native_type> [ int32 ]
4357 MetaData.CompressNum((uint) elemMult,str);
4358 //else <native_type> [ int32 + int32 ]
4359 } else if (elemMult != -1) {
4360 // When can this occur ?
4361 MetaData.CompressNum (0, str);
4362 MetaData.CompressNum((uint) elemMult,str);
4364 //else <native_type> [ + int32 ]
4366 return str.ToArray();
4371 public class SafeArray : NativeType {
4373 SafeArrayType elemType;
4376 public SafeArray() : base(0x1D)
4380 public SafeArray(SafeArrayType elemType) : base(0x1D)
4382 this.elemType = elemType;
4386 internal override byte[] ToBlob()
4388 byte[] bytes = new byte[hasElemType ? 2 : 1];
4389 bytes[0] = GetTypeIndex();
4391 bytes[1] = (byte)elemType;
4397 public class FixedArray : NativeType {
4401 //public FixedArray(NativeType elemType, int numElems) : base(0x1E) {
4402 public FixedArray(int numElems) : base(0x1E)
4404 //this.elemType = elemType;
4405 numElem = (uint)numElems;
4408 internal override byte[] ToBlob()
4410 MemoryStream str = new MemoryStream();
4411 str.WriteByte(GetTypeIndex());
4412 MetaData.CompressNum(numElem,str);
4414 fixed array [5] lpstr [2]
4415 This format is not supported by ilasm 1.1.4322.2032,
4416 but is supported by 2.0.5125..
4417 ilasm 1.1 only supports "fixed array [5]"
4418 if (elemType == null) str.WriteByte(0x50); // no info (MAX)
4419 else str.WriteByte(elemType.GetTypeIndex());*/
4421 return str.ToArray();
4426 public class CustomMarshaller : NativeType {
4429 string marshallerName;
4432 public CustomMarshaller(string typeNameOrGUID, string marshallerName,
4433 string optCookie) : base(0x2C)
4435 typeName = typeNameOrGUID;
4436 this.marshallerName = marshallerName;
4440 public CustomMarshaller(string marshallerName, string optCookie)
4441 :this (null, marshallerName, optCookie)
4445 internal override byte[] ToBlob()
4447 MemoryStream str = new MemoryStream();
4448 BinaryWriter bw = new BinaryWriter(str,new UTF8Encoding());
4449 bw.Write(GetTypeIndex());
4450 //Native type name & unmanaged type - unused
4451 //See mono/metadata/metadata.c : mono_metadata_parse_marshal_spec
4452 bw.Write ((byte) 0); // Native Type name, unused
4453 bw.Write ((byte) 0); // Unmanaged type, unused
4454 if (marshallerName != null) {
4455 MetaData.CompressNum ((uint)marshallerName.Length, str);
4456 bw.Write(marshallerName.ToCharArray());
4458 bw.Write ((byte) 0);
4460 if (cookie != null) {
4461 MetaData.CompressNum ((uint)cookie.Length, str);
4462 bw.Write(cookie.ToCharArray());
4464 bw.Write ((byte) 0);
4467 return str.ToArray();
4471 /**************************************************************************/
4473 /// Descriptor for the Primitive types defined in IL
4475 public class PrimitiveType : Type {
4477 private string name;
4478 private int systemTypeIndex;
4479 public static int NumSystemTypes = 18;
4481 public static readonly PrimitiveType Void = new PrimitiveType(0x01,"Void",0);
4482 public static readonly PrimitiveType Boolean = new PrimitiveType(0x02,"Boolean",1);
4483 public static readonly PrimitiveType Char = new PrimitiveType(0x03,"Char",2);
4484 public static readonly PrimitiveType Int8 = new PrimitiveType(0x04,"SByte",3);
4485 public static readonly PrimitiveType UInt8 = new PrimitiveType(0x05,"Byte",4);
4486 public static readonly PrimitiveType Int16 = new PrimitiveType(0x06,"Int16",5);
4487 public static readonly PrimitiveType UInt16 = new PrimitiveType(0x07,"UInt16",6);
4488 public static readonly PrimitiveType Int32 = new PrimitiveType(0x08,"Int32",7);
4489 public static readonly PrimitiveType UInt32 = new PrimitiveType(0x09,"UInt32",8);
4490 public static readonly PrimitiveType Int64 = new PrimitiveType(0x0A,"Int64",9);
4491 public static readonly PrimitiveType UInt64 = new PrimitiveType(0x0B,"UInt64",10);
4492 public static readonly PrimitiveType Float32 = new PrimitiveType(0x0C,"Single",11);
4493 public static readonly PrimitiveType Float64 = new PrimitiveType(0x0D,"Double",12);
4494 public static readonly PrimitiveType String = new PrimitiveType(0x0E,"String",13);
4495 internal static readonly PrimitiveType Class = new PrimitiveType(0x12);
4496 internal static readonly PrimitiveType Var = new PrimitiveType(0x13);
4497 internal static readonly PrimitiveType GenericInst = new PrimitiveType(0x15);
4498 public static readonly PrimitiveType TypedRef = new PrimitiveType(0x16,"TypedReference",14);
4499 public static readonly PrimitiveType IntPtr = new PrimitiveType(0x18,"IntPtr",15);
4500 public static readonly PrimitiveType UIntPtr = new PrimitiveType(0x19,"UIntPtr",16);
4501 public static readonly PrimitiveType Object = new PrimitiveType(0x1C,"Object",17);
4502 internal static readonly PrimitiveType ClassType = new PrimitiveType(0x50);
4503 internal static readonly PrimitiveType SZArray = new PrimitiveType(0x1D);
4504 internal static readonly PrimitiveType MVar = new PrimitiveType(0x1E);
4505 internal static readonly PrimitiveType ValueType = new PrimitiveType(0x11, "ValueType", 18);
4506 public static readonly PrimitiveType NativeInt = IntPtr;
4507 public static readonly PrimitiveType NativeUInt = UIntPtr;
4509 internal PrimitiveType(byte typeIx) : base(typeIx) { }
4511 internal PrimitiveType(byte typeIx, string name, int STIx) : base(typeIx)
4514 this.systemTypeIndex = STIx;
4517 internal string GetName() { return name; }
4519 internal int GetSystemTypeIx() { return systemTypeIndex; }
4521 internal sealed override void TypeSig(MemoryStream str)
4523 str.WriteByte(typeIndex);
4526 internal override MetaDataElement GetTypeSpec(MetaData md)
4528 TypeSpec tS = md.GetPrimitiveTypeSpec(systemTypeIndex);
4530 tS = new TypeSpec(this,md);
4531 md.SetPrimitiveTypeSpec(systemTypeIndex,tS);
4532 md.AddToTable(MDTable.TypeSpec,tS);
4539 public class PrimitiveTypeRef : Type
4544 internal PrimitiveTypeRef(PrimitiveType type, MetaData md)
4551 internal uint TypeDefOrRefToken()
4553 uint cIx = type.GetTypeSpec (metaData).Row;
4554 cIx = (cIx << 2) | 0x2;
4559 /**************************************************************************/
4561 /// Descriptor for an pointer (type * or type &)
4563 public abstract class PtrType : Type {
4567 internal PtrType(Type bType, byte typeIx) : base(typeIx)
4570 tabIx = MDTable.TypeSpec;
4573 internal sealed override void TypeSig(MemoryStream str)
4575 str.WriteByte(typeIndex);
4576 baseType.TypeSig(str);
4580 /**************************************************************************/
4582 /// Descriptor for a managed pointer (type & or byref)
4585 public class ManagedPointer : PtrType {
4588 /// Create new managed pointer to baseType
4590 /// <param name="bType">the base type of the pointer</param>
4591 public ManagedPointer(Type baseType) : base(baseType,0x10) { }
4594 /**************************************************************************/
4596 /// Descriptor for an unmanaged pointer (type *)
4598 public class UnmanagedPointer : PtrType {
4601 /// Create a new unmanaged pointer to baseType
4603 /// <param name="baseType">the base type of the pointer</param>
4604 public UnmanagedPointer(Type baseType) : base(baseType, 0x0F) { }
4608 /**************************************************************************/
4610 public interface IExternRef {
4611 ClassRef AddClass(string nsName, string name);
4612 ClassRef AddValueClass(string nsName, string name);
4616 /// A reference to an external assembly (.assembly extern)
4618 public class AssemblyRef : ResolutionScope, IExternRef {
4620 private ushort major, minor, build, revision;
4621 uint flags, keyIx, hashIx, cultIx;
4622 bool hasVersion = false, isKeyToken = false;
4626 internal AssemblyRef(MetaData md, string name) : base(name,md)
4628 tabIx = MDTable.AssemblyRef;
4631 public void AddAssemblyAttr (AssemAttr aa)
4637 /// Add version information about this external assembly
4639 /// <param name="majVer">Major Version</param>
4640 /// <param name="minVer">Minor Version</param>
4641 /// <param name="bldNo">Build Number</param>
4642 /// <param name="revNo">Revision Number</param>
4643 public void AddVersionInfo(int majVer, int minVer, int bldNo, int revNo)
4645 major = (ushort)majVer;
4646 minor = (ushort)minVer;
4647 build = (ushort)bldNo;
4648 revision = (ushort)revNo;
4653 /// Add the hash value for this external assembly
4655 /// <param name="hash">bytes of the hash value</param>
4656 public void AddHash(byte[] hash)
4658 hashIx = metaData.AddToBlobHeap(hash);
4662 /// Set the culture for this external assembly
4664 /// <param name="cult">the culture string</param>
4665 public void AddCulture(string cult)
4667 cultIx = metaData.AddToStringsHeap(cult);
4672 /// Add the full public key for this external assembly
4674 /// <param name="key">bytes of the public key</param>
4675 public void AddKey(byte[] key)
4677 flags |= 0x0001; // full public key
4679 keyIx = metaData.AddToBlobHeap(key);
4683 /// Add the public key token (low 8 bytes of the public key)
4685 /// <param name="key">low 8 bytes of public key</param>
4686 public void AddKeyToken(byte[] key)
4688 keyIx = metaData.AddToBlobHeap(key);
4694 /// Add a class to this external assembly
4696 /// <param name="nsName">name space name</param>
4697 /// <param name="name">class name</param>
4698 /// <returns></returns>
4699 public virtual ClassRef AddClass(string nsName, string name)
4701 ClassRef aClass = new ClassRef(nsName,name,metaData);
4702 metaData.AddToTable(MDTable.TypeRef,aClass);
4703 aClass.SetParent(this);
4708 /// Add a value class to this external assembly
4710 /// <param name="nsName">name space name</param>
4711 /// <param name="name">class name</param>
4712 /// <returns></returns>
4713 public virtual ClassRef AddValueClass(string nsName, string name)
4715 ClassRef aClass = new ClassRef(nsName,name,metaData);
4716 metaData.AddToTable(MDTable.TypeRef,aClass);
4717 aClass.SetParent(this);
4718 aClass.MakeValueClass(ValueClass.ValueType);
4722 internal string TypeName()
4724 string result = name;
4726 result = result + ", Version=" + major + "." + minor + "." +
4727 build + "." + revision;
4728 if (keyBytes != null) {
4729 string tokenStr = "=";
4730 if (isKeyToken) tokenStr = "Token=";
4731 result = result + ", PublicKey" + tokenStr;
4732 for (int i=0; i < keyBytes.Length; i++) {
4733 result = result + Hex.Byte(keyBytes[i]);
4736 if (culture != null)
4737 result = result + ", Culture=" + culture;
4741 internal sealed override uint Size(MetaData md)
4743 return 12 + 2 * md.StringsIndexSize() + 2 * md.BlobIndexSize();
4746 internal sealed override void Write(FileImage output)
4748 output.Write(major);
4749 output.Write(minor);
4750 output.Write(build);
4751 output.Write(revision);
4752 output.Write(flags);
4753 output.BlobIndex(keyIx);
4754 output.StringsIndex(nameIx);
4755 output.StringsIndex(cultIx);
4756 output.BlobIndex(hashIx);
4759 internal sealed override uint GetCodedIx(CIx code)
4762 case (CIx.ResolutionScope) : return 2;
4763 case (CIx.HasCustomAttr) : return 15;
4764 case (CIx.Implementation) : return 1;
4771 /**************************************************************************/
4773 /// Descriptor for a class defined in System (mscorlib)
4775 internal class SystemClass : ClassRef {
4777 PrimitiveType elemType;
4779 internal SystemClass(PrimitiveType eType, AssemblyRef paren, MetaData md)
4780 : base("System",eType.GetName(),md) {
4785 internal override sealed MetaDataElement GetTypeSpec(MetaData md)
4787 if (typeSpec == null) typeSpec = (TypeSpec)elemType.GetTypeSpec(md);
4792 internal sealed override void TypeSig(MemoryStream str)
4794 str.WriteByte(elemType.GetTypeIndex());
4799 /**************************************************************************/
4801 /// The assembly for mscorlib.
4803 public sealed class MSCorLib : AssemblyRef {
4805 private static readonly int valueTypeIx = 18;
4806 private readonly string systemName = "System";
4807 private Class[] systemClasses = new Class[valueTypeIx+2];
4808 private PrimitiveType[] systemTypes = new PrimitiveType[valueTypeIx];
4810 private static int[] specialNames = {
4811 PrimitiveType.Void.GetName().GetHashCode(),
4812 PrimitiveType.Boolean.GetName().GetHashCode(),
4813 PrimitiveType.Char.GetName().GetHashCode(),
4814 PrimitiveType.Int8.GetName().GetHashCode(),
4815 PrimitiveType.UInt8.GetName().GetHashCode(),
4816 PrimitiveType.Int16.GetName().GetHashCode(),
4817 PrimitiveType.UInt16.GetName().GetHashCode(),
4818 PrimitiveType.Int32.GetName().GetHashCode(),
4819 PrimitiveType.UInt32.GetName().GetHashCode(),
4820 PrimitiveType.Int64.GetName().GetHashCode(),
4821 PrimitiveType.UInt64.GetName().GetHashCode(),
4822 PrimitiveType.Float32.GetName().GetHashCode(),
4823 PrimitiveType.Float64.GetName().GetHashCode(),
4824 PrimitiveType.String.GetName().GetHashCode(),
4825 PrimitiveType.TypedRef.GetName().GetHashCode(),
4826 PrimitiveType.IntPtr.GetName().GetHashCode(),
4827 PrimitiveType.UIntPtr.GetName().GetHashCode(),
4828 PrimitiveType.Object.GetName().GetHashCode(),
4829 PrimitiveType.ValueType.GetName ().GetHashCode(),
4830 "Enum".GetHashCode()
4833 internal MSCorLib(MetaData md) : base(md,"mscorlib")
4835 if (!PEFile.IsMSCorlib)
4836 md.AddToTable(MDTable.AssemblyRef,this);
4837 systemTypes[PrimitiveType.Void.GetSystemTypeIx()] = PrimitiveType.Void;
4838 systemTypes[PrimitiveType.Boolean.GetSystemTypeIx()] = PrimitiveType.Boolean;
4839 systemTypes[PrimitiveType.Char.GetSystemTypeIx()] = PrimitiveType.Char;
4840 systemTypes[PrimitiveType.Int8.GetSystemTypeIx()] = PrimitiveType.Int8;
4841 systemTypes[PrimitiveType.UInt8.GetSystemTypeIx()] = PrimitiveType.UInt8;
4842 systemTypes[PrimitiveType.Int16.GetSystemTypeIx()] = PrimitiveType.Int16;
4843 systemTypes[PrimitiveType.UInt16.GetSystemTypeIx()] = PrimitiveType.UInt16;
4844 systemTypes[PrimitiveType.Int32.GetSystemTypeIx()] = PrimitiveType.Int32;
4845 systemTypes[PrimitiveType.UInt32.GetSystemTypeIx()] = PrimitiveType.UInt32;
4846 systemTypes[PrimitiveType.Int64.GetSystemTypeIx()] = PrimitiveType.Int64;
4847 systemTypes[PrimitiveType.UInt64.GetSystemTypeIx()] = PrimitiveType.UInt64;
4848 systemTypes[PrimitiveType.Float32.GetSystemTypeIx()] = PrimitiveType.Float32;
4849 systemTypes[PrimitiveType.Float64.GetSystemTypeIx()] = PrimitiveType.Float64;
4850 systemTypes[PrimitiveType.IntPtr.GetSystemTypeIx()] = PrimitiveType.IntPtr;
4851 systemTypes[PrimitiveType.UIntPtr.GetSystemTypeIx()] = PrimitiveType.UIntPtr;
4852 systemTypes[PrimitiveType.String.GetSystemTypeIx()] = PrimitiveType.String;
4853 systemTypes[PrimitiveType.Object.GetSystemTypeIx()] = PrimitiveType.Object;
4854 systemTypes[PrimitiveType.TypedRef.GetSystemTypeIx()] = PrimitiveType.TypedRef;
4858 /// Add a class to the mscorlib assembly
4860 /// <param name="nsName">name space name</param>
4861 /// <param name="name">class name</param>
4862 /// <returns></returns>
4863 public override ClassRef AddClass(string nsName, string name)
4865 /* This gets called by !mscorlib, for adding references INTO mscorlib, so
4866 it should be returning ClassRef ..*/
4867 Class aClass = GetSpecialClass(nsName,name);
4868 if (aClass == null) {
4869 aClass = new ClassRef(nsName,name,metaData);
4870 metaData.AddToTable(MDTable.TypeRef,aClass);
4871 if (aClass is ClassRef)
4872 ((ClassRef) aClass).SetParent(this);
4874 //FIXME: Check for !ClassRef here?
4875 return (ClassRef) aClass;
4878 private Class GetSpecialClass(string nsName,string name)
4880 if (nsName.CompareTo(systemName) != 0) return null;
4881 int hash = name.GetHashCode();
4882 for (int i=0; i < specialNames.Length; i++) {
4883 if (hash != specialNames[i])
4885 if (systemClasses[i] == null) {
4886 if (i < valueTypeIx) {
4887 systemClasses[i] = new SystemClass(systemTypes[i],this,metaData);
4888 if ((systemTypes[i] != PrimitiveType.Object) &&
4889 (systemTypes[i] != PrimitiveType.String)) {
4890 systemClasses[i].MakeValueClass(ValueClass.ValueType);
4893 systemClasses[i] = new ClassRef(nsName,name,metaData);
4894 ((ClassRef) systemClasses[i]).SetParent(this);
4895 if (!ClassDef.IsValueType (nsName, name) && !ClassDef.IsEnum (nsName, name))
4896 systemClasses[i].MakeValueClass(ValueClass.ValueType);
4898 metaData.AddToTable(MDTable.TypeRef,systemClasses[i]);
4900 return systemClasses[i];
4905 internal void SetSpecialSystemClass (string nsName, string name, Class aClass)
4907 if (nsName != systemName) return;
4908 int hash = name.GetHashCode ();
4909 for (int i = 0; i < specialNames.Length; i++) {
4910 if (hash != specialNames [i])
4912 if (systemClasses [i] == null) {
4913 systemClasses [i] = aClass;
4918 internal Class GetSpecialSystemClass(PrimitiveType pType)
4920 int ix = pType.GetSystemTypeIx();
4921 if (systemClasses[ix] == null && !PEFile.IsMSCorlib) {
4922 systemClasses[ix] = new SystemClass(pType,this,metaData);
4923 metaData.AddToTable(MDTable.TypeRef,systemClasses[ix]);
4925 return systemClasses[ix];
4928 private ClassRef GetValueClass(string name, int hash)
4930 /* Called by MSCorLib.AddValueClass, which is called by
4931 !mscorlib, for adding ref to value class INTO mscorlib,
4932 so this should be classref */
4933 int ix = valueTypeIx;
4934 if (hash != specialNames[valueTypeIx]) ix++;
4935 if (systemClasses[ix] == null) {
4936 systemClasses[ix] = new ClassRef(systemName,name,metaData);
4937 ((ClassRef) systemClasses[ix]).SetParent(this);
4938 ((ClassRef) systemClasses[ix]).MakeValueClass(ValueClass.ValueType);
4939 metaData.AddToTable(MDTable.TypeRef,systemClasses[ix]);
4941 return (ClassRef) systemClasses[ix];
4944 internal Class ValueType()
4946 if (systemClasses[valueTypeIx] == null && !PEFile.IsMSCorlib) {
4947 ClassRef valType = new ClassRef("System","ValueType",metaData);
4948 valType.SetParent(this);
4949 valType.MakeValueClass(ValueClass.ValueType);
4950 metaData.AddToTable(MDTable.TypeRef,valType);
4951 systemClasses[valueTypeIx] = valType;
4953 return systemClasses[valueTypeIx];
4956 internal Class EnumType()
4958 /* Called by both mscorlib & !mscorlib, so can be
4959 either ClassRef or ClassDef */
4960 //systemClasses [ valueTypeIx + 1] -> System.Enum
4961 if (systemClasses[valueTypeIx + 1] == null && !PEFile.IsMSCorlib) {
4962 ClassRef valType = new ClassRef("System","Enum",metaData);
4963 valType.SetParent(this);
4964 valType.MakeValueClass(ValueClass.Enum);
4965 metaData.AddToTable(MDTable.TypeRef,valType);
4966 systemClasses[valueTypeIx + 1] = valType;
4968 return systemClasses[valueTypeIx + 1];
4972 /// Add a value class to this external assembly
4974 /// <param name="nsName">name space name</param>
4975 /// <param name="name">class name</param>
4976 /// <returns></returns>
4977 public override ClassRef AddValueClass(string nsName, string name)
4979 if (nsName.CompareTo(systemName) == 0) {
4980 int hash = name.GetHashCode();
4981 if ((hash == specialNames[valueTypeIx]) ||
4982 (hash == specialNames[valueTypeIx+1])) {
4983 return GetValueClass(name,hash);
4986 ClassRef aClass = new ClassRef(nsName,name,metaData);
4987 metaData.AddToTable(MDTable.TypeRef,aClass);
4988 aClass.SetParent(this);
4989 aClass.MakeValueClass(ValueClass.ValueType);
4995 /**************************************************************************/
4998 /// Root (20 bytes + UTF-8 Version String + quad align padding)
4999 /// StreamHeaders (8 bytes + null terminated name string + quad align padding)
5001 /// #~ (always present - holds metadata tables)
5002 /// #Strings (always present - holds identifier strings)
5003 /// #US (Userstring heap)
5004 /// #Blob (signature blobs)
5005 /// #GUID (guids for assemblies or Modules)
5007 public class MetaData {
5009 internal static readonly int[] CIxShiftMap = {2,2,5,1,2,3,1,1,1,2,3,2,1};
5010 private static readonly byte StringsHeapMask = 0x1;
5011 private static readonly byte GUIDHeapMask = 0x2;
5012 private static readonly byte BlobHeapMask = 0x4;
5013 private static readonly uint MetaDataSignature = 0x424A5342;
5014 private static readonly uint maxSmlIxSize = 0xFFFF;
5015 private static readonly uint max1BitSmlIx = 0x7FFF;
5016 private static readonly uint max2BitSmlIx = 0x3FFF;
5017 private static readonly uint max3BitSmlIx = 0x1FFF;
5018 private static readonly uint max5BitSmlIx = 0x7FF;
5019 // NOTE: version and stream name strings MUST always be quad padded
5020 private static readonly string version = "v4.0.30319\0\0";
5021 private static readonly char[] tildeName = {'#','~','\0','\0'};
5022 private static readonly char[] stringsName = {'#','S','t','r','i','n','g','s','\0','\0','\0','\0'};
5023 private static readonly char[] usName = {'#','U','S','\0'};
5024 private static readonly char[] guidName = {'#','G','U','I','D','\0','\0','\0'};
5025 private static readonly char[] blobName = {'#','B','l','o','b','\0','\0','\0'};
5026 private static readonly uint MetaDataHeaderSize = 20 + (uint)version.Length;
5027 private static readonly uint TildeHeaderSize = 24;
5028 private static readonly uint StreamHeaderSize = 8;
5029 private static readonly uint numMetaDataTables = (int)MDTable.GenericParamConstraint + 1;
5031 MetaDataStream strings, us, guid, blob;
5033 MetaDataStream[] streams = new MetaDataStream[5];
5034 uint numStreams = 5;
5035 uint tildeTide = 0, tildePadding = 0, tildeStart = 0;
5036 uint numTables = 0, resourcesSize = 0;
5037 ArrayList[] metaDataTables = new ArrayList[numMetaDataTables];
5038 ArrayList byteCodes = new ArrayList();
5039 uint codeSize = 0, codeStart, byteCodePadding = 0, metaDataSize = 0;
5040 ulong valid = 0, /*sorted = 0x000002003301FA00;*/ sorted = 0;
5041 bool[] largeIx = new bool[numMetaDataTables];
5042 bool[] lgeCIx = new bool[(int)CIx.MaxCIx];
5043 bool largeStrings = false, largeUS = false, largeGUID = false, largeBlob = false;
5044 private FileImage file;
5045 private byte heapSizes = 0;
5046 MetaDataElement entryPoint;
5047 BinaryWriter output;
5048 public MSCorLib mscorlib;
5049 private TypeSpec[] systemTypeSpecs = new TypeSpec[PrimitiveType.NumSystemTypes];
5051 private ArrayList cattr_list;
5052 private ArrayList declsec_list;
5053 ArrayList resources;
5055 internal MetaData(FileImage file)
5057 // tilde = new MetaDataStream(tildeName,false,0);
5059 strings = new MetaDataStream(stringsName,new UTF8Encoding(),true);
5060 us = new MetaDataStream(usName,new UnicodeEncoding(),true);
5061 guid = new MetaDataStream(guidName,false);
5062 blob = new MetaDataStream(blobName,true);
5063 streams[1] = strings;
5067 for (int i=0; i < numMetaDataTables; i++) {
5070 for (int i=0; i < lgeCIx.Length; i++) {
5073 mscorlib = new MSCorLib(this);
5076 internal TypeSpec GetPrimitiveTypeSpec(int ix)
5078 return systemTypeSpecs[ix];
5081 internal void SetPrimitiveTypeSpec(int ix, TypeSpec typeSpec)
5083 systemTypeSpecs[ix] = typeSpec;
5086 internal uint Size()
5088 return metaDataSize;
5091 private void CalcHeapSizes ()
5093 if (strings.LargeIx()) {
5094 largeStrings = true;
5095 heapSizes |= StringsHeapMask;
5097 if (guid.LargeIx()) {
5099 heapSizes |= GUIDHeapMask;
5101 if (blob.LargeIx()) {
5103 heapSizes |= BlobHeapMask;
5106 largeUS = us.LargeIx();
5109 internal void StreamSize(byte mask)
5114 internal uint AddToUSHeap(string str)
5116 if (str == null) return 0;
5117 return us.Add(str,true);
5120 internal uint AddToUSHeap(byte[] str)
5122 if (str == null) return 0;
5123 return us.Add (str, true);
5126 internal uint AddToStringsHeap(string str)
5128 if ((str == null) || (str.CompareTo("") == 0)) return 0;
5129 return strings.Add(str,false);
5132 internal uint AddToGUIDHeap(Guid guidNum)
5134 return guid.Add(guidNum, false);
5137 internal uint AddToBlobHeap(byte[] blobBytes)
5139 if (blobBytes == null) return 0;
5140 return blob.Add(blobBytes, true);
5143 internal uint AddToBlobHeap(byte val)
5145 return blob.Add(val, true);
5148 internal uint AddToBlobHeap(sbyte val)
5150 return blob.Add(val, true);
5153 internal uint AddToBlobHeap(ushort val)
5155 return blob.Add(val, true);
5158 internal uint AddToBlobHeap(short val)
5160 return blob.Add(val, true);
5163 internal uint AddToBlobHeap(uint val)
5165 return blob.Add(val, true);
5168 internal uint AddToBlobHeap(int val)
5170 return blob.Add(val, true);
5173 internal uint AddToBlobHeap(ulong val)
5175 return blob.Add(val, true);
5178 internal uint AddToBlobHeap(long val)
5180 return blob.Add(val, true);
5183 internal uint AddToBlobHeap(float val)
5185 return blob.Add(val, true);
5188 internal uint AddToBlobHeap(double val)
5190 return blob.Add(val, true);
5193 internal uint AddToBlobHeap(string val)
5195 return blob.Add(val,true);
5198 internal void AddCustomAttribute (CustomAttribute cattr)
5200 if (cattr_list == null)
5201 cattr_list = new ArrayList ();
5202 cattr_list.Add (cattr);
5205 internal void AddDeclSecurity (BaseDeclSecurity decl_sec)
5207 if (declsec_list == null)
5208 declsec_list = new ArrayList ();
5209 declsec_list.Add (decl_sec);
5212 private ArrayList GetTable(MDTable tableIx)
5214 int tabIx = (int)tableIx;
5215 if (metaDataTables[tabIx] == null) {
5216 metaDataTables[tabIx] = new ArrayList();
5217 valid |= ((ulong)0x1 << tabIx);
5218 // Console.WriteLine("after creating table " + tableIx + "(" + tabIx + ") valid = " + valid);
5221 return metaDataTables[tabIx];
5224 internal void AddToTable(MDTable tableIx, MetaDataElement elem)
5227 // Console.Out.WriteLine("ERROR - element already in table " + tableIx);
5230 // updates Row field of the element
5231 // Console.WriteLine("Adding element to table " + (uint)tableIx);
5232 ArrayList table = GetTable(tableIx);
5233 elem.Row = (uint)table.Count + 1;
5237 internal uint TableIndex(MDTable tableIx)
5239 if (metaDataTables[(int)tableIx] == null) return 1;
5240 return (uint)metaDataTables[(int)tableIx].Count+1;
5243 internal uint AddCode(CILInstructions byteCode)
5245 byteCodes.Add(byteCode);
5246 uint offset = codeSize + codeStart;
5247 codeSize += byteCode.GetCodeSize();
5251 internal void SetEntryPoint(MetaDataElement ep)
5256 internal uint AddResource(byte[] resBytes)
5258 if (resources == null) resources = new ArrayList ();
5259 resources.Add (resBytes);
5260 uint offset = resourcesSize;
5261 resourcesSize += (uint)resBytes.Length + 4;
5265 internal void AddData(DataConstant cVal)
5267 file.AddInitData(cVal);
5270 internal static void CompressNum(uint val, MemoryStream sig)
5273 sig.WriteByte((byte)val);
5274 } else if (val <= 0x3FFF) {
5275 byte b1 = (byte)((val >> 8) | 0x80);
5276 byte b2 = (byte)(val & FileImage.iByteMask[0]);
5280 byte b1 = (byte)((val >> 24) | 0xC0);
5281 byte b2 = (byte)((val & FileImage.iByteMask[2]) >> 16);
5282 byte b3 = (byte)((val & FileImage.iByteMask[1]) >> 8);;
5283 byte b4 = (byte)(val & FileImage.iByteMask[0]);
5291 internal uint CodeSize()
5293 return codeSize + byteCodePadding;
5296 internal uint GetResourcesSize()
5298 return resourcesSize;
5301 internal uint StringsIndexSize()
5303 if (largeStrings) return 4;
5307 internal uint GUIDIndexSize()
5309 if (largeGUID) return 4;
5313 internal uint USIndexSize()
5315 if (largeUS) return 4;
5319 internal uint BlobIndexSize()
5321 if (largeBlob) return 4;
5325 internal uint CodedIndexSize(CIx code)
5327 if (lgeCIx[(uint)code]) return 4;
5331 internal uint TableIndexSize(MDTable tabIx)
5333 if (largeIx[(uint)tabIx]) return 4;
5337 private void SetIndexSizes()
5339 for (int i=0; i < numMetaDataTables; i++) {
5340 if (metaDataTables[i] == null)
5343 uint count = (uint)metaDataTables[i].Count;
5344 if (count > maxSmlIxSize)
5347 MDTable tabIx = (MDTable)i;
5348 if (count > max5BitSmlIx) {
5349 lgeCIx[(int)CIx.HasCustomAttr] = true;
5351 if (count > max3BitSmlIx) {
5352 if ((tabIx == MDTable.TypeRef) || (tabIx == MDTable.ModuleRef) || (tabIx == MDTable.Method) || (tabIx == MDTable.TypeSpec) || (tabIx == MDTable.Field))
5353 lgeCIx[(int)CIx.CustomAttributeType] = true;
5354 if ((tabIx == MDTable.Method) || (tabIx == MDTable.MemberRef))
5355 lgeCIx[(int)CIx.MemberRefParent] = true;
5357 if (count > max2BitSmlIx) {
5358 if ((tabIx == MDTable.Field) || (tabIx == MDTable.Param) || (tabIx == MDTable.Property))
5359 lgeCIx[(int)CIx.HasConst] = true;
5360 if ((tabIx == MDTable.TypeDef) || (tabIx == MDTable.TypeRef) || (tabIx == MDTable.TypeSpec))
5361 lgeCIx[(int)CIx.TypeDefOrRef] = true;
5362 if ((tabIx == MDTable.TypeDef) || (tabIx == MDTable.Method) || (tabIx == MDTable.Assembly))
5363 lgeCIx[(int)CIx.HasDeclSecurity] = true;
5364 if ((tabIx == MDTable.File) || (tabIx == MDTable.AssemblyRef) || (tabIx == MDTable.ExportedType))
5365 lgeCIx[(int)CIx.Implementation] = true;
5366 if ((tabIx == MDTable.Module) || (tabIx == MDTable.ModuleRef) || (tabIx == MDTable.AssemblyRef) || (tabIx == MDTable.TypeRef))
5367 lgeCIx[(int)CIx.ResolutionScope] = true;
5369 if (count > max1BitSmlIx) {
5370 if ((tabIx == MDTable.Field) || (tabIx == MDTable.Param))
5371 lgeCIx[(int)CIx.HasFieldMarshal] = true;
5372 if ((tabIx == MDTable.Event) || (tabIx == MDTable.Property))
5373 lgeCIx[(int)CIx.HasSemantics] = true;
5374 if ((tabIx == MDTable.Method) || (tabIx == MDTable.MemberRef))
5375 lgeCIx[(int)CIx.MethodDefOrRef] = true;
5376 if ((tabIx == MDTable.Field) || (tabIx == MDTable.Method))
5377 lgeCIx[(int)CIx.MemberForwarded] = true;
5378 if ((tabIx == MDTable.TypeDef) || (tabIx == MDTable.Method))
5379 lgeCIx[(int)CIx.TypeOrMethodDef] = true;
5384 private void SetStreamOffsets()
5386 uint sizeOfHeaders = StreamHeaderSize + (uint)tildeName.Length;
5387 for (int i=1; i < numStreams; i++) {
5388 sizeOfHeaders += streams[i].headerSize();
5390 metaDataSize = MetaDataHeaderSize + sizeOfHeaders;
5391 tildeStart = metaDataSize;
5392 metaDataSize += tildeTide + tildePadding;
5393 for (int i=1; i < numStreams; i++) {
5394 streams[i].Start = metaDataSize;
5395 metaDataSize += streams[i].Size();
5396 streams[i].WriteDetails();
5400 internal void CalcTildeStreamSize()
5403 //tilde.SetIndexSizes(strings.LargeIx(),us.LargeIx(),guid.LargeIx(),blob.LargeIx());
5404 tildeTide = TildeHeaderSize;
5405 tildeTide += 4 * numTables;
5406 //Console.WriteLine("Tilde header + sizes = " + tildeTide);
5407 for (int i=0; i < numMetaDataTables; i++) {
5408 if (metaDataTables[i] != null) {
5409 ArrayList table = metaDataTables[i];
5410 // Console.WriteLine("Meta data table " + i + " at offset " + tildeTide);
5411 tildeTide += (uint)table.Count * ((MetaDataElement)table[0]).Size(this);
5412 // Console.WriteLine("Metadata table " + i + " has size " + table.Count);
5413 // Console.WriteLine("tildeTide = " + tildeTide);
5416 if ((tildeTide % 4) != 0) tildePadding = 4 - (tildeTide % 4);
5417 //Console.WriteLine("tildePadding = " + tildePadding);
5420 internal void WriteTildeStream(FileImage output)
5422 output.Seek(0,SeekOrigin.Current);
5423 output.Write((uint)0); // Reserved
5424 output.Write((byte)2); // MajorVersion
5425 output.Write((byte)0); // MinorVersion
5426 output.Write(heapSizes);
5427 output.Write((byte)1); // Reserved
5428 output.Write(valid);
5429 output.Write(sorted);
5431 for (int i=0; i < numMetaDataTables; i++) {
5432 if (metaDataTables[i] != null) {
5433 uint count = (uint)metaDataTables[i].Count;
5434 output.Write(count);
5438 output.Seek(0,SeekOrigin.Current);
5439 // Console.WriteLine("Starting metaData tables at " + tabStart);
5440 for (int i=0; i < numMetaDataTables; i++) {
5441 if (metaDataTables[i] != null) {
5442 // Console.WriteLine("Starting metaData table " + i + " at " + (output.Seek(0,SeekOrigin.Current) - startTilde));
5443 ArrayList table = metaDataTables[i];
5444 for (int j=0; j < table.Count; j++) {
5445 ((MetaDataElement)table[j]).Write(output);
5449 // Console.WriteLine("Writing padding at " + output.Seek(0,SeekOrigin.Current));
5450 for (int i=0; i < tildePadding; i++) output.Write((byte)0);
5453 private void BuildTable(ArrayList table)
5455 if (table == null) return;
5456 for (int j=0; j < table.Count; j++) {
5457 ((MetaDataElement)table[j]).BuildTables(this);
5461 private void SortTable (ArrayList mTable)
5463 if (mTable == null) return;
5465 for (int i=0; i < mTable.Count; i++) {
5466 ((MetaDataElement)mTable[i]).Row = (uint)i+1;
5470 internal void BuildMetaData(uint codeStartOffset)
5472 codeStart = codeStartOffset;
5473 BuildTable(metaDataTables[(int)MDTable.TypeDef]);
5474 BuildTable(metaDataTables[(int)MDTable.TypeSpec]);
5475 BuildTable(metaDataTables[(int)MDTable.MemberRef]);
5476 BuildTable(metaDataTables[(int)MDTable.GenericParam]);
5477 BuildTable(metaDataTables[(int)MDTable.MethodSpec]);
5478 BuildTable(metaDataTables[(int)MDTable.GenericParamConstraint]);
5479 BuildTable(metaDataTables[(int)MDTable.ManifestResource]);
5481 if (cattr_list != null) {
5482 foreach (CustomAttribute cattr in cattr_list)
5483 cattr.BuildTables (this);
5486 if (declsec_list != null) {
5487 foreach (BaseDeclSecurity decl_sec in declsec_list)
5488 decl_sec.BuildTables (this);
5491 /* for (int i=0; i < metaDataTables.Length; i++) {
5492 ArrayList table = metaDataTables[i];
5493 if (table != null) {
5494 for (int j=0; j < table.Count; j++) {
5495 ((MetaDataElement)table[j]).BuildTables(this);
5502 for (int i=1; i < numStreams; i++) {
5503 streams[i].EndStream();
5505 CalcTildeStreamSize();
5507 byteCodePadding = NumToAlign(codeSize,4);
5508 if (entryPoint != null) file.SetEntryPoint(entryPoint.Token());
5510 // Check ordering of specific tables
5511 // Constant, CustomAttribute, FieldMarshal, DeclSecurity, MethodSemantics
5512 // ImplMap, GenericParam
5513 // Need to load GenericParamConstraint AFTER GenericParam table in correct order
5515 // InterfaceImpl, ClassLayout, FieldLayout, MethodImpl, FieldRVA, NestedClass
5516 // will _ALWAYS_ be in the correct order as embedded in BuildMDTables
5518 SortTable(metaDataTables[(int)MDTable.Constant]);
5519 SortTable(metaDataTables[(int)MDTable.FieldMarshal]);
5520 SortTable(metaDataTables[(int)MDTable.DeclSecurity]);
5521 SortTable(metaDataTables[(int)MDTable.MethodSemantics]);
5522 SortTable(metaDataTables[(int)MDTable.ImplMap]);
5523 if (metaDataTables[(int)MDTable.GenericParam] != null) {
5524 SortTable(metaDataTables[(int)MDTable.GenericParam]);
5525 // Now add GenericParamConstraints
5526 /*for (int i=0; i < metaDataTables[(int)MDTable.GenericParam].Count; i++) {
5527 ((GenericParameter)metaDataTables[(int)MDTable.GenericParam][i]).AddConstraints(this);
5530 SortTable(metaDataTables[(int)MDTable.GenericParamConstraint]);
5531 SortTable(metaDataTables[(int)MDTable.InterfaceImpl]);
5532 SortTable(metaDataTables[(int)MDTable.CustomAttribute]);
5536 internal void WriteByteCodes(FileImage output)
5538 for (int i=0; i < byteCodes.Count; i++) {
5539 ((CILInstructions)byteCodes[i]).Write(output);
5541 for (int i=0; i < byteCodePadding; i++) {
5542 output.Write((byte)0);
5546 internal void WriteResources (FileImage output)
5548 if (resources == null) return;
5549 for (int i = 0; i < resources.Count; i ++) {
5550 byte [] resBytes = (byte []) resources [i];
5551 output.Write ((uint) resBytes.Length);
5552 output.Write (resBytes);
5556 internal void WriteMetaData(FileImage output)
5558 this.output = output;
5559 mdStart = output.Seek(0,SeekOrigin.Current);
5560 // Console.WriteLine("Writing metaData at " + Hex.Long(mdStart));
5561 output.Write(MetaDataSignature);
5562 output.Write((short)1); // Major Version
5563 output.Write((short)1); // Minor Version ECMA = 0, PEFiles = 1
5564 output.Write(0); // Reserved
5565 output.Write(version.Length);
5566 output.Write(version.ToCharArray()); // version string is already zero padded
5567 output.Write((short)0);
5568 output.Write((ushort)numStreams);
5569 // write tilde header
5570 output.Write(tildeStart);
5571 output.Write(tildeTide + tildePadding);
5572 output.Write(tildeName);
5573 for (int i=1; i < numStreams; i++) streams[i].WriteHeader(output);
5574 // Console.WriteLine("Writing tilde stream at " + output.Seek(0,SeekOrigin.Current) + " = " + tildeStart);
5575 WriteTildeStream(output);
5576 for (int i=1; i < numStreams; i++) streams[i].Write(output);
5577 // Console.WriteLine("Finished Writing metaData at " + output.Seek(0,SeekOrigin.Current));
5580 internal bool LargeStringsIndex() { return strings.LargeIx(); }
5581 internal bool LargeGUIDIndex() { return guid.LargeIx(); }
5582 internal bool LargeUSIndex() { return us.LargeIx(); }
5583 internal bool LargeBlobIndex() { return blob.LargeIx(); }
5585 internal bool LargeIx(MDTable tabIx) { return largeIx[(uint)tabIx]; }
5588 private uint NumToAlign(uint val, uint alignVal)
5590 if ((val % alignVal) == 0) return 0;
5591 return alignVal - (val % alignVal);
5594 internal void WriteCodedIndex(CIx code, MetaDataElement elem, FileImage output)
5598 ix = (elem.Row << CIxShiftMap[(uint)code]) | elem.GetCodedIx(code);
5599 // Console.WriteLine("coded index = " + ix + " row = " + elem.Row);
5601 // Console.WriteLine("elem for coded index is null");
5603 if (lgeCIx[(uint)code])
5606 output.Write((ushort)ix);
5611 /**************************************************************************/
5613 /// Stream in the Meta Data (#Strings, #US, #Blob and #GUID)
5616 internal class MetaDataStream : BinaryWriter {
5618 private static readonly uint StreamHeaderSize = 8;
5619 private static uint maxSmlIxSize = 0xFFFF;
5621 private uint start = 0;
5622 uint size = 0, tide = 1;
5623 bool largeIx = false;
5626 Hashtable htable = new Hashtable();
5627 Hashtable btable = new Hashtable (new ByteArrayHashCodeProvider (), new ByteArrayComparer ());
5629 internal MetaDataStream(char[] name, bool addInitByte) : base(new MemoryStream())
5631 if (addInitByte) { Write((byte)0); size = 1; }
5633 sizeOfHeader = StreamHeaderSize + (uint)name.Length;
5636 internal MetaDataStream(char[] name, System.Text.Encoding enc, bool addInitByte) : base(new MemoryStream(),enc)
5638 if (addInitByte) { Write((byte)0); size = 1; }
5640 sizeOfHeader = StreamHeaderSize + (uint)name.Length;
5644 get { return start; }
5645 set { start = value; }
5648 internal uint headerSize()
5650 // Console.WriteLine(name + " stream has headersize of " + sizeOfHeader);
5651 return sizeOfHeader;
5654 internal void SetSize(uint siz)
5659 internal uint Size()
5664 internal bool LargeIx()
5669 internal void WriteDetails()
5671 // Console.WriteLine(name + " - size = " + size);
5674 internal uint Add(string str, bool prependSize)
5676 Object val = htable[str];
5680 htable[str] = index;
5681 char[] arr = str.ToCharArray();
5682 if (prependSize) CompressNum((uint)arr.Length*2+1);
5685 size = (uint)Seek(0,SeekOrigin.Current);
5691 internal uint Add (byte[] str, bool prependSize)
5693 Object val = btable [str];
5697 btable [str] = index;
5698 if (prependSize) CompressNum ((uint) str.Length);
5700 size = (uint) Seek (0, SeekOrigin.Current);
5708 internal uint Add(Guid guid, bool prependSize)
5710 byte [] b = guid.ToByteArray ();
5711 if (prependSize) CompressNum ((uint) b.Length);
5712 Write(guid.ToByteArray());
5713 size =(uint)Seek(0,SeekOrigin.Current);
5717 internal uint Add(byte[] blob)
5720 CompressNum((uint)blob.Length);
5722 size = (uint)Seek(0,SeekOrigin.Current);
5726 internal uint Add(byte val, bool prependSize)
5729 if (prependSize) CompressNum (1);
5731 size = (uint)Seek(0,SeekOrigin.Current);
5735 internal uint Add(sbyte val, bool prependSize)
5738 if (prependSize) CompressNum (1);
5740 size = (uint)Seek(0,SeekOrigin.Current);
5744 internal uint Add(ushort val, bool prependSize)
5747 if (prependSize) CompressNum (2);
5749 size = (uint)Seek(0,SeekOrigin.Current);
5753 internal uint Add(short val, bool prependSize)
5756 if (prependSize) CompressNum (2);
5758 size = (uint)Seek(0,SeekOrigin.Current);
5762 internal uint Add(uint val, bool prependSize)
5765 if (prependSize) CompressNum (4);
5767 size = (uint)Seek(0,SeekOrigin.Current);
5771 internal uint Add(int val, bool prependSize)
5774 if (prependSize) CompressNum (4);
5776 size = (uint)Seek(0,SeekOrigin.Current);
5780 internal uint Add(ulong val, bool prependSize)
5783 if (prependSize) CompressNum (8);
5785 size = (uint)Seek(0,SeekOrigin.Current);
5789 internal uint Add(long val, bool prependSize)
5792 if (prependSize) CompressNum (8);
5794 size = (uint)Seek(0,SeekOrigin.Current);
5798 internal uint Add(float val, bool prependSize)
5801 if (prependSize) CompressNum (4);
5803 size = (uint)Seek(0,SeekOrigin.Current);
5807 internal uint Add(double val, bool prependSize)
5810 if (prependSize) CompressNum (8);
5812 size = (uint)Seek(0,SeekOrigin.Current);
5816 private void CompressNum(uint val)
5820 } else if (val < 0x3FFF) {
5821 byte b1 = (byte)((val >> 8) | 0x80);
5822 byte b2 = (byte)(val & FileImage.iByteMask[0]);
5826 byte b1 = (byte)((val >> 24) | 0xC0);
5827 byte b2 = (byte)((val & FileImage.iByteMask[2]) >> 16);
5828 byte b3 = (byte)((val & FileImage.iByteMask[1]) >> 8);;
5829 byte b4 = (byte)(val & FileImage.iByteMask[0]);
5837 private void QuadAlign()
5839 if ((size % 4) != 0) {
5840 uint pad = 4 - (size % 4);
5842 for (int i=0; i < pad; i++) {
5848 internal void EndStream()
5851 if (size > maxSmlIxSize) {
5856 internal void WriteHeader(BinaryWriter output)
5858 output.Write(start);
5863 internal virtual void Write(BinaryWriter output)
5865 // Console.WriteLine("Writing " + name + " stream at " + output.Seek(0,SeekOrigin.Current) + " = " + start);
5866 MemoryStream str = (MemoryStream)BaseStream;
5867 output.Write(str.ToArray());
5872 /**************************************************************************/
5873 class ByteArrayComparer : IComparer {
5875 public int Compare (object x, object y)
5877 byte [] a = (byte []) x;
5878 byte [] b = (byte []) y;
5881 if (b.Length != len)
5884 for (int i = 0; i < len; ++i)
5891 class ByteArrayHashCodeProvider : IHashCodeProvider {
5893 public int GetHashCode (Object key)
5895 byte [] arr = (byte []) key;
5896 int len = arr.Length;
5899 for (int i = 0; i < len; ++i)
5900 h = (h << 5) - h + arr [i];