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 /// Storage location for initial field data
100 public enum DataSegment { Data, TLS, CIL }
103 /// Modes for a parameter
105 public enum ParamAttr { Default, In, Out, Opt = 16, HasDefault = 0x1000, HasFieldMarshal = 0x2000 }
110 public enum Op { nop, breakOp, ldarg_0, ldarg_1, ldarg_2, ldarg_3,
111 ldloc_0, ldloc_1, ldloc_2, ldloc_3, stloc_0, stloc_1, stloc_2, stloc_3,
112 ldnull = 0x14, ldc_i4_m1, ldc_i4_0, ldc_i4_1, ldc_i4_2, ldc_i4_3,
113 ldc_i4_4, ldc_i4_5, ldc_i4_6, ldc_i4_7, ldc_i4_8, dup = 0x25, pop,
114 ret = 0x2A, ldind_i1 = 0x46, ldind_u1, ldind_i2, ldind_u2, ldind_i4,
115 ldind_u4, ldind_i8, ldind_i, ldind_r4, ldind_r8, ldind_ref, stind_ref,
116 stind_i1, stind_i2, stind_i4, stind_i8, stind_r4, stind_r8, add, sub, mul,
117 div, div_un, rem, rem_un, and, or, xor, shl, shr, shr_un, neg, not,
118 conv_i1, conv_i2, conv_i4, conv_i8, conv_r4, conv_r8, conv_u4, conv_u8,
119 conv_r_un = 0x76, throwOp = 0x7A, conv_ovf_i1_un = 0x82, conv_ovf_i2_un,
120 conv_ovf_i4_un, conv_ovf_i8_un, conf_ovf_u1_un, conv_ovf_u2_un,
121 conv_ovf_u4_un, conv_ovf_u8_un, conv_ovf_i_un, conv_ovf_u_un,
122 ldlen = 0x8E, ldelem_i1 = 0x90, ldelem_u1, ldelem_i2, ldelem_u2,
123 ldelem_i4, ldelem_u4, ldelem_i8, ldelem_i, ldelem_r4, ldelem_r8,
124 ldelem_ref, stelem_i, stelem_i1, stelem_i2, stelem_i4, stelem_i8, stelem_r4 = 0xA0, stelem_r8,
125 stelem_ref, conv_ovf_i1 = 0xb3, conv_ovf_u1, conv_ovf_i2, conv_ovf_u2,
126 conv_ovf_i4, conv_ovf_u4, conv_ovf_i8, conv_ovf_u8, ckfinite = 0xC3,
127 conv_u2 = 0xD1, conv_u1, conv_i, conv_ovf_i, conv_ovf_u, add_ovf,
128 add_ovf_un, mul_ovf, mul_ovf_un, sub_ovf, sub_ovf_un, endfinally,
129 stind_i = 0xDF, conv_u, arglist = 0xFE00, ceq, cgt, cgt_un, clt, clt_un,
130 localloc = 0xFE0F, endfilter = 0xFE11, volatile_ = 0xFE13, tail_,
131 cpblk = 0xFE17, initblk, rethrow = 0xFE1A, refanytype = 0xFE1D, readonly_ = 0xFE1E }
134 /// CIL instructions requiring an integer parameter
136 public enum IntOp {ldarg_s = 0x0E, ldarga_s, starg_s, ldloc_s, ldloca_s,
137 stloc_s, ldc_i4_s = 0x1F, ldc_i4, ldarg = 0xFE09,
138 ldarga, starg, ldloc, ldloca, stloc, unaligned = 0xFE12 }
141 /// CIL instructions requiring a field parameter
143 public enum FieldOp {ldfld = 0x7B, ldflda, stfld, ldsfld, ldsflda,
144 stsfld, ldtoken = 0xD0 }
147 /// CIL instructions requiring a method parameter
149 public enum MethodOp {jmp = 0x27, call, callvirt = 0x6F, newobj = 0x73,
150 ldtoken = 0xD0, ldftn = 0xFE06, ldvirtfn }
153 /// CIL instructions requiring a type parameter
155 public enum TypeOp {cpobj = 0x70, ldobj, castclass = 0x74, isinst,
156 unbox = 0x79, stobj = 0x81, box = 0x8C, newarr,
157 ldelema = 0x8F, refanyval = 0xC2, mkrefany = 0xC6,
158 ldtoken = 0xD0, initobj = 0xFE15, constrained = 0xFE16,
159 sizeOf = 0xFE1C, ldelem = 0xA3, stelem = 0xA4, unbox_any }
162 /// CIL branch instructions
164 public enum BranchOp {
166 br_s = 0x2B, brfalse_s, brtrue_s, beq_s, bge_s, bgt_s,
167 ble_s, blt_s, bne_un_s, bge_un_s, bgt_un_s, ble_un_s, blt_un_s,
169 br = 0x38, brfalse, brtrue, beq, bge, bgt, ble, blt,
170 bne_un, bge_un, bgt_un, ble_un, blt_un,
172 leave = 0xDD, leave_s }
175 /// Index for all the tables in the meta data
177 public enum MDTable { Module, TypeRef, TypeDef, Field = 0x04, Method = 0x06,
178 Param = 0x08, InterfaceImpl, MemberRef, Constant, CustomAttribute,
179 FieldMarshal, DeclSecurity, ClassLayout, FieldLayout, StandAloneSig,
180 EventMap, Event = 0x14, PropertyMap, Property = 0x17, MethodSemantics,
181 MethodImpl, ModuleRef, TypeSpec, ImplMap, FieldRVA, Assembly = 0x20,
182 AssemblyProcessor, AssemblyOS, AssemblyRef, AssemblyRefProcessor,
183 AssemblyRefOS, File, ExportedType, ManifestResource, NestedClass,
184 GenericParam, MethodSpec, GenericParamConstraint }
186 public enum SafeArrayType { int16 = 2, int32, float32, float64,
187 currency, date, bstr, dispatch, error, boolean, variant, unknown,
188 Decimal, int8 = 16, uint8, uint16, uint32, Int = 22, UInt }
190 internal enum CIx { TypeDefOrRef, HasConst, HasCustomAttr, HasFieldMarshal,
191 HasDeclSecurity, MemberRefParent, HasSemantics, MethodDefOrRef,
192 MemberForwarded, Implementation, CustomAttributeType, ResolutionScope,
193 TypeOrMethodDef, MaxCIx }
195 internal enum MapType { eventMap, propertyMap, nestedClass }
197 public enum ValueClass { ValueType, Enum }
199 public enum GenParamType : byte {
200 Var = 0x13, MVar = 0x1E
204 public enum GenericParamAttributes : ushort {
205 VarianceMask = 0x0003,
208 Contravariant = 0x0002,
210 SpecialConstraintMask = 0x001c,
211 ReferenceTypeConstraint = 0x0004,
212 NotNullableValueTypeConstraint = 0x0008,
213 DefaultConstructorConstrait = 0x0010
216 /* Taken from Mono.Cecil */
217 public enum SecurityAction : short {
231 NonCasLinkDemand = 14,
232 NonCasInheritance = 15,
233 LinkDemandChoice = 16,
234 InheritDemandChoice = 17,
240 /**************************************************************************/
242 /// Base class for all Meta Data table elements
245 public abstract class MetaDataElement: IComparable {
246 protected ArrayList customAttributes;
247 private uint row = 0;
248 protected bool done = false;
249 protected MDTable tabIx;
250 protected bool sortTable = false;
252 private bool has_custom_attrs = false;
254 internal MetaDataElement() { }
265 public bool HasCustomAttr {
266 get { return has_custom_attrs; }
267 set { has_custom_attrs = value; }
270 internal virtual uint GetCodedIx(CIx code) { return 0; }
273 /// Add a custom attribute to this item
275 /// <param name="ctorMeth">the constructor method for this attribute</param>
276 /// <param name="val">the byte value of the parameters</param>
277 public void AddCustomAttribute(Method ctorMeth, byte[] val)
279 if (customAttributes == null) {
280 customAttributes = new ArrayList();
282 customAttributes.Add(new CustomAttribute(this,ctorMeth,val));
286 /// Add a custom attribute to this item
288 /// <param name="ctorMeth">the constructor method for this attribute</param>
289 /// <param name="val">the constant values of the parameters</param>
290 public void AddCustomAttribute(Method ctorMeth, Constant[] cVals)
292 if (customAttributes == null) {
293 customAttributes = new ArrayList();
295 // customAttributes.Add(new CustomAttribute(this,ctorMeth,cVals));
298 internal uint Token()
300 return (((uint)tabIx << 24) | row);
303 internal virtual void BuildTables(MetaData md)
308 internal virtual uint Size(MetaData md)
313 internal virtual void Write(FileImage output) { }
315 internal virtual uint SortKey()
317 throw new PEFileException("Trying to sort table of " + this);
321 internal virtual uint SortKey2()
326 public int CompareTo(object obj)
328 uint otherKey = ((MetaDataElement)obj).SortKey();
329 uint thisKey = SortKey();
331 if (thisKey == otherKey) {
333 otherKey = ((MetaDataElement)obj).SortKey2();
334 thisKey = SortKey2();
335 if (thisKey == otherKey)
337 if (thisKey < otherKey)
341 if (thisKey < otherKey) return -1;
348 /**************************************************************************/
350 /// Layout information for a class (.class [sequential | explicit])
352 internal class ClassLayout : MetaDataElement {
358 internal ClassLayout(int pack, int cSize, ClassDef par)
360 packSize = (ushort)pack;
361 classSize = (uint)cSize;
363 tabIx = MDTable.ClassLayout;
366 internal sealed override uint Size(MetaData md)
368 return 6 + md.TableIndexSize(MDTable.TypeDef);
371 internal sealed override void Write(FileImage output)
373 output.Write(packSize);
374 output.Write(classSize);
375 output.WriteIndex(MDTable.TypeDef,parent.Row);
380 /**************************************************************************/
382 /// Summary description for ConstantElem.
384 internal class ConstantElem : MetaDataElement {
386 MetaDataElement parent;
390 internal ConstantElem(MetaDataElement parent, Constant val)
392 this.parent = parent;
394 tabIx = MDTable.Constant;
398 internal override uint SortKey()
400 return (parent.Row << MetaData.CIxShiftMap[(uint)CIx.HasConst])
401 | parent.GetCodedIx(CIx.HasConst);
404 internal sealed override void BuildTables(MetaData md)
407 valIx = cValue.GetBlobIndex(md);
411 internal void AddToBlob(BinaryWriter bw)
416 internal sealed override uint Size(MetaData md)
418 return 2 + md.CodedIndexSize(CIx.HasConst) + md.BlobIndexSize();
421 internal sealed override void Write(FileImage output)
423 output.Write(cValue.GetTypeIndex());
424 output.Write((byte)0);
425 output.WriteCodedIndex(CIx.HasConst,parent);
426 output.BlobIndex(valIx);
430 /**************************************************************************/
432 /// Descriptor for a Custom Attribute (.custom)
435 public class CustomAttribute : MetaDataElement {
437 MetaDataElement parent;
443 ArrayList names, vals;
445 internal CustomAttribute(MetaDataElement paren, Method constrType,
450 tabIx = MDTable.CustomAttribute;
452 byteVal = ConstantToByteArray (val);
455 static byte[] ConstantToByteArray (Constant c)
457 var bac = c as ByteArrConst;
461 var ms = new MemoryStream ();
469 return ms.ToArray ();
472 var sc = c as StringConst;
474 string value = sc.val;
476 throw new NotImplementedException ();
478 var buf = Encoding.UTF8.GetBytes (value);
479 MetaData.CompressNum ((uint) buf.Length, ms);
480 var byteVal = ms.ToArray ();
481 System.Array.Resize (ref byteVal, (int) ms.Length + buf.Length + 2);
482 System.Array.Copy (buf, 0, byteVal, ms.Length, buf.Length);
486 var ac = c as ArrayConstant;
488 var bw = new BinaryWriter (ms);
489 if (ac.ExplicitSize != null)
490 bw.Write (ac.ExplicitSize.Value);
493 return ms.ToArray ();
496 var bc = c as DataConstant;
498 var bw = new BinaryWriter (ms);
501 return ms.ToArray ();
504 throw new NotImplementedException (c.GetType ().ToString ());
507 internal CustomAttribute(MetaDataElement paren, Method constrType,
511 tabIx = MDTable.CustomAttribute;
515 internal override uint SortKey()
517 return (parent.Row << MetaData.CIxShiftMap[(uint)CIx.HasCustomAttr])
518 | parent.GetCodedIx(CIx.HasCustomAttr);
521 public void AddFieldOrProp(string name, Constant val)
524 names = new ArrayList();
525 vals = new ArrayList();
531 internal sealed override void BuildTables(MetaData md)
533 md.AddToTable(MDTable.CustomAttribute, this);
534 if (byteVal == null) {
539 BinaryWriter bw = new BinaryWriter(new MemoryStream());
541 MemoryStream str = (MemoryStream)bw.BaseStream;
542 valIx = md.AddToBlobHeap(str.ToArray());
545 internal sealed override uint Size(MetaData md)
547 return md.CodedIndexSize(CIx.HasCustomAttr) + md.CodedIndexSize(CIx.CustomAttributeType) + md.BlobIndexSize();
550 internal sealed override void Write(FileImage output)
552 output.WriteCodedIndex(CIx.HasCustomAttr,parent);
553 output.WriteCodedIndex(CIx.CustomAttributeType,type);
554 output.BlobIndex(valIx);
559 /**************************************************************************/
561 /// Descriptor for security permissions for a class or a method
564 public abstract class BaseDeclSecurity : MetaDataElement {
567 MetaDataElement parent;
570 internal BaseDeclSecurity(MetaDataElement paren, ushort act)
574 tabIx = MDTable.DeclSecurity;
577 internal override uint SortKey()
579 return (parent.Row << MetaData.CIxShiftMap[(uint)CIx.HasDeclSecurity])
580 | parent.GetCodedIx(CIx.HasDeclSecurity);
583 internal sealed override uint Size(MetaData md)
585 return 2 + md.CodedIndexSize(CIx.HasDeclSecurity) + md.BlobIndexSize();
588 internal sealed override void BuildTables(MetaData md)
592 BinaryWriter bw = new BinaryWriter (new MemoryStream ());
593 md.AddToTable (MDTable.DeclSecurity, this);
594 MemoryStream str = (MemoryStream)bw.BaseStream;
596 permissionIx = md.AddToBlobHeap(str.ToArray());
601 internal abstract void WriteSig (BinaryWriter bw);
603 internal sealed override void Write(FileImage output)
605 output.Write(action);
606 output.WriteCodedIndex(CIx.HasDeclSecurity,parent);
607 output.BlobIndex(permissionIx);
612 public class DeclSecurity : BaseDeclSecurity {
616 internal DeclSecurity(MetaDataElement paren, ushort act, byte [] val)
622 internal override void WriteSig (BinaryWriter bw)
629 public class DeclSecurity_20 : BaseDeclSecurity {
633 internal DeclSecurity_20 (MetaDataElement paren, ushort act, PermissionSet ps)
639 internal override void WriteSig (BinaryWriter bw)
645 public class PermissionMember {
647 MemberTypes member_type;
652 public PermissionMember (MemberTypes member_type, PEAPI.Type type, string name, object value)
654 this.member_type = member_type;
660 public void Write (BinaryWriter bw)
664 if (member_type == MemberTypes.Field)
665 bw.Write ((byte) 0x53);
668 bw.Write ((byte) 0x54);
670 if (type is PrimitiveType) {
671 bw.Write (type.GetTypeIndex ());
674 bw.Write ((byte) 0x55); //ENUM
676 b = Encoding.UTF8.GetBytes (((ClassRef) type).TypeName ());
677 MetaData.CompressNum ((uint) b.Length, (MemoryStream) bw.BaseStream);
681 b = Encoding.UTF8.GetBytes (name);
682 MetaData.CompressNum ((uint) b.Length, (MemoryStream) bw.BaseStream);
685 ((Constant) value).Write (bw);
690 public class Permission
698 public Permission (PEAPI.Type type, string name)
704 public void AddMember (PEAPI.PermissionMember member)
707 members = new ArrayList ();
709 members.Add (member);
712 public void Write (BinaryWriter bw)
714 byte [] b = Encoding.UTF8.GetBytes (name);
715 MetaData.CompressNum ((uint) b.Length, (MemoryStream) bw.BaseStream);
718 BinaryWriter perm_writer = new BinaryWriter (new MemoryStream (), Encoding.Unicode);
719 MemoryStream str = (MemoryStream) perm_writer.BaseStream;
721 MetaData.CompressNum ((uint) members.Count, str);//number of params
722 foreach (PermissionMember member in members)
723 member.Write (perm_writer);
725 bw.Write ((byte) str.Length); //(optional) parameters length
726 bw.Write (str.ToArray ());
730 public class PermissionSet
732 PEAPI.SecurityAction sec_action;
733 ArrayList permissions;
735 public PermissionSet (PEAPI.SecurityAction sec_action)
737 this.sec_action = sec_action;
740 public void AddPermission (PEAPI.Permission perm)
742 if (permissions == null)
743 permissions = new ArrayList ();
745 permissions.Add (perm);
748 public void Write (BinaryWriter bw)
750 bw.Write ((byte) 0x2e);
751 MetaData.CompressNum ((uint) permissions.Count, (MemoryStream) bw.BaseStream);
753 foreach (Permission perm in permissions)
759 /**************************************************************************/
761 /// Descriptor for layout information for a field
764 public class FieldLayout : MetaDataElement {
769 internal FieldLayout(Field field, uint offset)
772 this.offset = offset;
773 tabIx = MDTable.FieldLayout;
776 internal sealed override uint Size(MetaData md)
778 return 4 + md.TableIndexSize(MDTable.Field);
781 internal sealed override void Write(FileImage output)
783 output.Write(offset);
784 output.WriteIndex(MDTable.Field,field.Row);
789 /*****************************************************************************/
791 /// Marshalling information for a field or param
793 public class FieldMarshal : MetaDataElement {
795 MetaDataElement field;
799 internal FieldMarshal(MetaDataElement field, NativeType nType)
803 tabIx = MDTable.FieldMarshal;
806 internal override uint SortKey()
808 return (field.Row << MetaData.CIxShiftMap[(uint)CIx.HasFieldMarshal])
809 | field.GetCodedIx(CIx.HasFieldMarshal);
812 internal sealed override void BuildTables(MetaData md)
815 ntIx = md.AddToBlobHeap(nt.ToBlob());
819 internal sealed override uint Size(MetaData md)
821 return md.CodedIndexSize(CIx.HasFieldMarshal) + md.BlobIndexSize();
824 internal sealed override void Write(FileImage output)
826 output.WriteCodedIndex(CIx.HasFieldMarshal,field);
827 output.BlobIndex(ntIx);
832 /**************************************************************************/
834 /// Descriptor for the address of a field's value in the PE file
836 public class FieldRVA : MetaDataElement {
841 internal FieldRVA(Field field, DataConstant data)
845 tabIx = MDTable.FieldRVA;
848 internal sealed override void BuildTables(MetaData md)
855 internal sealed override uint Size(MetaData md)
857 return 4 + md.TableIndexSize(MDTable.Field);
860 internal sealed override void Write(FileImage output)
862 output.WriteDataRVA(data.DataOffset);
863 output.WriteIndex(MDTable.Field,field.Row);
868 /**************************************************************************/
870 /// Descriptor for a file referenced in THIS assembly/module (.file)
872 public class FileRef : MetaDataElement {
874 private static readonly uint NoMetaData = 0x1;
875 uint nameIx = 0, hashIx = 0;
877 protected string name;
879 internal FileRef(string name, byte[] hashBytes, bool metaData,
880 bool entryPoint, MetaData md) {
881 if (!metaData) flags = NoMetaData;
882 if (entryPoint) md.SetEntryPoint(this);
884 nameIx = md.AddToStringsHeap(name);
885 hashIx = md.AddToBlobHeap(hashBytes);
886 tabIx = MDTable.File;
889 internal FileRef(uint nameIx, byte[] hashBytes, bool metaData,
890 bool entryPoint, MetaData md) {
891 if (!metaData) flags = NoMetaData;
892 if (entryPoint) md.SetEntryPoint(this);
893 this.nameIx = nameIx;
894 hashIx = md.AddToBlobHeap(hashBytes);
895 tabIx = MDTable.File;
898 internal sealed override uint Size(MetaData md)
900 return 4 + md.StringsIndexSize() + md.BlobIndexSize();
903 internal sealed override void BuildTables(MetaData md)
905 md.AddToTable(MDTable.File,this);
908 internal sealed override void Write(FileImage output)
911 output.StringsIndex(nameIx);
912 output.BlobIndex(hashIx);
915 internal sealed override uint GetCodedIx(CIx code)
918 case (CIx.HasCustomAttr) : return 16;
919 case (CIx.Implementation) : return 0;
925 /**************************************************************************/
927 /// Descriptor for pinvoke information for a method NOT YET IMPLEMENTED
929 public class ImplMap : MetaDataElement {
931 private static readonly ushort NoMangle = 0x01;
936 ModuleRef importScope;
938 internal ImplMap(ushort flag, Method implMeth, string iName, ModuleRef mScope)
943 importScope = mScope;
944 tabIx = MDTable.ImplMap;
945 if (iName == null) flags |= NoMangle;
946 //throw(new NotYetImplementedException("PInvoke "));
949 internal override uint SortKey()
951 return (meth.Row << MetaData.CIxShiftMap[(uint)CIx.MemberForwarded])
952 | meth.GetCodedIx(CIx.MemberForwarded);
955 internal sealed override void BuildTables(MetaData md)
958 iNameIx = md.AddToStringsHeap(importName);
962 internal sealed override uint Size(MetaData md)
964 return 2+ md.CodedIndexSize(CIx.MemberForwarded) +
965 md.StringsIndexSize() + md.TableIndexSize(MDTable.ModuleRef);
968 internal sealed override void Write(FileImage output)
971 output.WriteCodedIndex(CIx.MemberForwarded,meth);
972 output.StringsIndex(iNameIx);
973 output.WriteIndex(MDTable.ModuleRef,importScope.Row);
978 /**************************************************************************/
980 public class GenericParameter : MetaDataElement {
982 MetaDataElement owner;
987 GenericParamAttributes attr;
989 internal GenericParameter (ClassDef owner, MetaData metadata,
990 short index, string name, GenericParamAttributes attr) : this (owner, metadata, index, name, attr, true)
994 internal GenericParameter (MethodDef owner, MetaData metadata,
995 short index, string name, GenericParamAttributes attr) : this (owner, metadata, index, name, attr, true)
999 private GenericParameter (MetaDataElement owner, MetaData metadata,
1000 short index, string name, GenericParamAttributes attr, bool nadda) {
1002 this.metadata = metadata;
1004 tabIx = MDTable.GenericParam;
1009 internal override uint SortKey()
1011 return (owner.Row << MetaData.CIxShiftMap[(uint)CIx.TypeOrMethodDef])
1012 | owner.GetCodedIx(CIx.TypeOrMethodDef);
1015 internal override uint SortKey2 ()
1017 return (uint) index;
1020 public void AddConstraint (Type constraint)
1022 metadata.AddToTable (MDTable.GenericParamConstraint,
1023 new GenericParamConstraint (this, constraint));
1026 internal sealed override uint Size(MetaData md)
1029 md.CodedIndexSize(CIx.TypeOrMethodDef) +
1030 md.StringsIndexSize ());
1033 internal sealed override void BuildTables(MetaData md)
1036 nameIx = md.AddToStringsHeap(name);
1040 internal sealed override void Write(FileImage output)
1042 output.Write ((short) index);
1043 output.Write ((short) attr);
1044 output.WriteCodedIndex(CIx.TypeOrMethodDef, owner);
1045 output.StringsIndex (nameIx);
1048 internal sealed override uint GetCodedIx(CIx code)
1051 case (CIx.HasCustomAttr) : return 19;
1058 internal class GenericParamConstraint : MetaDataElement {
1060 GenericParameter param;
1063 public GenericParamConstraint (GenericParameter param, Type type)
1067 tabIx = MDTable.GenericParamConstraint;
1070 internal override uint SortKey()
1075 internal sealed override uint Size(MetaData md)
1077 return (uint) (md.TableIndexSize(MDTable.GenericParam) +
1078 md.CodedIndexSize(CIx.TypeDefOrRef));
1081 internal sealed override void Write(FileImage output)
1083 output.WriteIndex(MDTable.GenericParam, param.Row);
1084 output.WriteCodedIndex(CIx.TypeDefOrRef, type);
1089 internal class MethodSpec : Method {
1092 GenericMethodSig g_sig;
1095 internal MethodSpec (Method meth, GenericMethodSig g_sig) : base ("")
1099 tabIx = MDTable.MethodSpec;
1102 internal override uint GetSigIx (MetaData md)
1104 throw new Exception ("Should not be used.");
1107 public override void AddCallConv (CallConv cconv)
1109 throw new Exception ("Should not be used.");
1112 internal sealed override void BuildTables (MetaData md)
1115 sidx = g_sig.GetSigIx (md);
1119 internal sealed override uint Size (MetaData md)
1121 return (uint) (md.CodedIndexSize(CIx.MethodDefOrRef) +
1122 md.BlobIndexSize ());
1125 internal sealed override void Write (FileImage output)
1127 output.WriteCodedIndex (CIx.MethodDefOrRef, meth);
1128 output.BlobIndex (sidx);
1131 internal sealed override void TypeSig (MemoryStream sig)
1133 throw new Exception ("Should not be used.");
1137 /**************************************************************************/
1139 /// Descriptor for interface implemented by a class
1141 public class InterfaceImpl: MetaDataElement {
1146 internal InterfaceImpl(ClassDef theClass, Class theInterface)
1148 this.theClass = theClass;
1149 this.theInterface = theInterface;
1150 tabIx = MDTable.InterfaceImpl;
1153 internal sealed override uint Size(MetaData md)
1155 return md.TableIndexSize(MDTable.TypeDef) +
1156 md.CodedIndexSize(CIx.TypeDefOrRef);
1159 internal sealed override void Write(FileImage output)
1161 output.WriteIndex(MDTable.TypeDef,theClass.Row);
1162 output.WriteCodedIndex(CIx.TypeDefOrRef,theInterface);
1165 internal sealed override uint GetCodedIx(CIx code) { return 5; }
1167 internal override uint SortKey ()
1169 return (theClass.Row << MetaData.CIxShiftMap[(uint)CIx.TypeDefOrRef])
1170 | theClass.GetCodedIx (CIx.TypeDefOrRef);
1175 /**************************************************************************/
1177 /// Descriptor for resources used in this PE file
1180 public class ManifestResource : MetaDataElement {
1182 public static readonly uint PublicResource = 0x1;
1183 public static readonly uint PrivateResource = 0x2;
1186 MetaDataElement rRef;
1190 byte [] resourceBytes;
1192 public ManifestResource (string name, byte[] resBytes, uint flags)
1194 InitResource (name, flags);
1195 this.resourceBytes = resBytes;
1198 public ManifestResource(string name, uint flags, FileRef fileRef)
1200 InitResource (name, flags);
1204 public ManifestResource(string name, uint flags, FileRef fileRef,
1206 InitResource (name, flags);
1208 fileOffset = fileIx;
1211 public ManifestResource(string name, uint flags, AssemblyRef assemRef)
1213 InitResource (name, flags);
1217 internal ManifestResource (ManifestResource mres)
1219 mrName = mres.mrName;
1222 fileOffset = mres.fileOffset;
1223 resourceBytes = mres.resourceBytes;
1226 private void InitResource (string name, uint flags)
1230 tabIx = MDTable.ManifestResource;
1233 internal sealed override void BuildTables(MetaData md)
1236 md.AddToTable (MDTable.ManifestResource, this);
1237 nameIx = md.AddToStringsHeap(mrName);
1238 if (resourceBytes != null) {
1240 throw new PEFileException ("Manifest Resource has byte value and file reference");
1241 fileOffset = md.AddResource(resourceBytes);
1244 throw new PEFileException ("Manifest Resource has no implementation or value");
1245 rRef.BuildTables (md);
1251 internal sealed override uint Size(MetaData md)
1253 return 8 + md.StringsIndexSize() +
1254 md.CodedIndexSize(CIx.Implementation);
1257 internal sealed override void Write(FileImage output)
1259 output.Write(fileOffset);
1260 output.Write(flags);
1261 output.StringsIndex(nameIx);
1262 output.WriteCodedIndex(CIx.Implementation,rRef);
1265 internal sealed override uint GetCodedIx(CIx code) { return 18; }
1267 public string Name {
1268 get { return mrName; }
1269 set { mrName = value; }
1273 /**************************************************************************/
1275 /// Base class for elements in the PropertyMap, EventMap and
1276 /// NestedClass MetaData tables
1278 public class MapElem : MetaDataElement {
1284 internal MapElem(ClassDef par, uint elIx, MDTable elemTab)
1288 elemTable = elemTab;
1291 internal sealed override uint Size(MetaData md)
1293 return md.TableIndexSize(MDTable.TypeDef) + md.TableIndexSize(elemTable);
1296 internal sealed override void Write(FileImage output)
1298 output.WriteIndex(MDTable.TypeDef,parent.Row);
1299 output.WriteIndex(elemTable,elemIx);
1303 /**************************************************************************/
1305 /// Descriptor for an overriding method (.override)
1307 public class MethodImpl : MetaDataElement {
1310 Method header, body;
1312 internal MethodImpl(ClassDef par, Method decl, Method bod)
1317 tabIx = MDTable.MethodImpl;
1320 internal sealed override uint Size(MetaData md)
1322 return md.TableIndexSize(MDTable.TypeDef) + 2 * md.CodedIndexSize(CIx.MethodDefOrRef);
1325 internal sealed override void Write(FileImage output)
1327 output.WriteIndex(MDTable.TypeDef,parent.Row);
1328 output.WriteCodedIndex(CIx.MethodDefOrRef,body);
1329 output.WriteCodedIndex(CIx.MethodDefOrRef,header);
1334 /**************************************************************************/
1336 /// Descriptor for Property and Event methods
1338 public class MethodSemantics : MetaDataElement {
1340 Feature.MethodType type;
1342 Feature eventOrProp;
1344 internal MethodSemantics(Feature.MethodType mType, MethodDef method, Feature feature)
1348 eventOrProp = feature;
1349 tabIx = MDTable.MethodSemantics;
1352 internal override uint SortKey()
1354 return (eventOrProp.Row << MetaData.CIxShiftMap [(uint)CIx.HasSemantics])
1355 | eventOrProp.GetCodedIx (CIx.HasSemantics);
1358 internal sealed override uint Size(MetaData md)
1360 return 2 + md.TableIndexSize(MDTable.Method) + md.CodedIndexSize(CIx.HasSemantics);
1363 internal sealed override void Write(FileImage output)
1365 output.Write((ushort)type);
1366 output.WriteIndex(MDTable.Method,meth.Row);
1367 output.WriteCodedIndex(CIx.HasSemantics,eventOrProp);
1372 /**************************************************************************/
1374 /// Descriptor for a parameter of a method defined in this assembly/module
1376 public class Param : MetaDataElement {
1381 internal ushort seqNo = 0;
1383 ConstantElem defaultVal;
1385 FieldMarshal marshalInfo;
1388 /// Create a new parameter for a method
1390 /// <param name="mode">param mode (in, out, opt)</param>
1391 /// <param name="parName">parameter name</param>
1392 /// <param name="parType">parameter type</param>
1393 public Param(ParamAttr mode, string parName, Type parType)
1397 parMode = (ushort)mode;
1398 tabIx = MDTable.Param;
1401 public bool HasMarshalInfo {
1402 get { return marshalInfo != null; }
1406 /// Add a default value to this parameter
1408 /// <param name="c">the default value for the parameter</param>
1409 public void AddDefaultValue(Constant cVal)
1411 defaultVal = new ConstantElem(this,cVal);
1412 parMode |= (ushort) ParamAttr.HasDefault;
1416 /// Add marshalling information about this parameter
1418 public void AddMarshallInfo(NativeType marshallType)
1420 parMode |= (ushort) ParamAttr.HasFieldMarshal;
1421 marshalInfo = new FieldMarshal(this,marshallType);
1424 internal Type GetParType() { return pType; }
1426 internal sealed override void BuildTables(MetaData md)
1429 nameIx = md.AddToStringsHeap(pName);
1430 if (defaultVal != null) {
1431 md.AddToTable(MDTable.Constant,defaultVal);
1432 defaultVal.BuildTables(md);
1434 if (marshalInfo != null) {
1435 md.AddToTable(MDTable.FieldMarshal,marshalInfo);
1436 marshalInfo.BuildTables(md);
1441 internal void TypeSig(MemoryStream str)
1446 internal sealed override uint Size(MetaData md)
1448 return 4 + md.StringsIndexSize();
1451 internal sealed override void Write(FileImage output)
1453 output.Write(parMode);
1454 output.Write(seqNo);
1455 output.StringsIndex(nameIx);
1458 internal sealed override uint GetCodedIx(CIx code)
1461 case (CIx.HasCustomAttr) : return 4;
1462 case (CIx.HasConst) : return 1;
1463 case (CIx.HasFieldMarshal) : return 1;
1470 /**************************************************************************/
1471 public abstract class Signature : MetaDataElement {
1473 protected uint sigIx;
1475 internal Signature()
1477 tabIx = MDTable.StandAloneSig;
1480 internal sealed override uint Size(MetaData md)
1482 return md.BlobIndexSize();
1485 internal sealed override void Write(FileImage output)
1487 output.BlobIndex(sigIx);
1490 internal sealed override uint GetCodedIx(CIx code) { return (uint)tabIx; }
1494 /**************************************************************************/
1495 public class TypeSpec : MetaDataElement {
1498 internal TypeSpec(Type aType, MetaData md)
1500 MemoryStream sig = new MemoryStream();
1502 sigIx = md.AddToBlobHeap(sig.ToArray());
1503 tabIx = MDTable.TypeSpec;
1506 internal sealed override uint GetCodedIx(CIx code)
1509 case (CIx.TypeDefOrRef) : return 2;
1510 case (CIx.HasCustomAttr) : return 13;
1511 case (CIx.MemberRefParent) : return 4;
1516 internal override uint Size(MetaData md)
1518 return md.BlobIndexSize();
1521 internal sealed override void Write(FileImage output)
1523 //Console.WriteLine("Writing the blob index for a TypeSpec");
1524 output.BlobIndex(sigIx);
1529 /**************************************************************************/
1531 /// Base class for all IL types
1533 public abstract class Type : MetaDataElement {
1534 protected byte typeIndex;
1535 protected TypeSpec typeSpec;
1537 internal Type(byte tyIx) { typeIndex = tyIx; }
1539 internal byte GetTypeIndex() { return typeIndex; }
1540 internal void SetTypeIndex (byte b) { typeIndex = b; }
1542 internal virtual MetaDataElement GetTypeSpec(MetaData md)
1544 if (typeSpec == null) {
1545 typeSpec = new TypeSpec(this,md);
1546 md.AddToTable(MDTable.TypeSpec,typeSpec);
1551 internal virtual void TypeSig(MemoryStream str)
1553 throw(new TypeSignatureException(this.GetType().AssemblyQualifiedName +
1554 " doesn't have a type signature!!"));
1558 public class ClassRefInst : Type {
1561 private bool is_value;
1563 public ClassRefInst (Type type, bool is_value) : base (PrimitiveType.Class.GetTypeIndex ())
1566 this.is_value = is_value;
1568 typeIndex = PrimitiveType.ValueType.GetTypeIndex ();
1569 tabIx = MDTable.TypeSpec;
1572 internal sealed override void TypeSig(MemoryStream str)
1578 /**************************************************************************/
1580 /// The base descriptor for a class
1582 public abstract class Class : Type {
1584 protected int row = 0;
1585 public string name, nameSpace;
1586 protected uint nameIx, nameSpaceIx;
1587 protected MetaData _metaData;
1588 internal Class(string nameSpaceName, string className, MetaData md)
1589 : base(PrimitiveType.Class.GetTypeIndex ())
1591 nameSpace = nameSpaceName;
1593 nameIx = md.AddToStringsHeap(name);
1594 nameSpaceIx = md.AddToStringsHeap(nameSpace);
1598 internal Class(uint nsIx, uint nIx) : base(PrimitiveType.Class.GetTypeIndex ())
1604 internal Class (byte typeIndex) : base (typeIndex)
1606 nameSpace = "Should not be used";
1607 name = "Should not be used";
1610 internal virtual uint TypeDefOrRefToken() { return 0; }
1612 internal virtual void MakeValueClass(ValueClass vClass)
1614 typeIndex = PrimitiveType.ValueType.GetTypeIndex ();
1617 internal virtual string TypeName()
1619 return (nameSpace + "." + name);
1622 internal override MetaDataElement GetTypeSpec(MetaData md)
1628 /**************************************************************************/
1629 // This Class produces entries in the TypeDef table of the MetaData
1630 // in the PE meta data.
1632 // NOTE: Entry 0 in TypeDef table is always the pseudo class <module>
1633 // which is the parent for functions and variables declared a module level
1636 /// The descriptor for a class defined in the IL (.class) in the current assembly/module
1639 public class ClassDef : Class {
1642 ArrayList fields = new ArrayList();
1643 ArrayList methods = new ArrayList();
1645 ArrayList properties;
1646 bool typeIndexChecked = true;
1647 uint fieldIx = 0, methodIx = 0;
1650 ClassDef parentClass;
1653 internal ClassDef(TypeAttr attrSet, string nsName, string name,
1654 MetaData md) : base(nsName, name, md)
1657 if (! ((nsName == "" && name == "<Module>") || (nsName == "System" && name == "Object")) ) {
1658 superType = metaData.mscorlib.GetSpecialSystemClass(PrimitiveType.Object);
1660 flags = (uint)attrSet;
1661 tabIx = MDTable.TypeDef;
1664 internal void SetSuper(Class sClass)
1667 if (! (sClass is GenericTypeInst))
1668 typeIndexChecked = false;
1671 internal override void MakeValueClass(ValueClass vClass)
1673 if (vClass == ValueClass.Enum)
1674 superType = metaData.mscorlib.EnumType();
1676 superType = metaData.mscorlib.ValueType();
1678 typeIndex = PrimitiveType.ValueType.GetTypeIndex ();
1681 public void SpecialNoSuper()
1687 /// Add an attribute to this class
1689 /// <param name="ta">the attribute to be added</param>
1690 public void AddAttribute(TypeAttr ta)
1696 /// Add an interface that is implemented by this class
1698 /// <param name="iFace">the interface that is implemented</param>
1699 public void AddImplementedInterface(Class iFace)
1701 metaData.AddToTable(MDTable.InterfaceImpl,new InterfaceImpl(this,iFace));
1705 /// Add a named generic type parameter
1707 public GenericParameter AddGenericParameter (short index, string name)
1709 return AddGenericParameter (index, name, 0);
1713 /// Add a named generic type parameter with attributes
1715 public GenericParameter AddGenericParameter (short index, string name, GenericParamAttributes attr)
1717 GenericParameter gp = new GenericParameter (this, metaData, index, name, attr);
1718 metaData.AddToTable (MDTable.GenericParam, gp);
1723 /// Add a field to this class
1725 /// <param name="name">field name</param>
1726 /// <param name="fType">field type</param>
1727 /// <returns>a descriptor for this new field</returns>
1728 public FieldDef AddField(string name, Type fType)
1730 FieldDef field = new FieldDef(name,fType);
1736 /// Add a field to this class
1738 /// <param name="fAtts">attributes for this field</param>
1739 /// <param name="name">field name</param>
1740 /// <param name="fType">field type</param>
1741 /// <returns>a descriptor for this new field</returns>
1742 public FieldDef AddField(FieldAttr fAtts, string name, Type fType)
1744 FieldDef field = new FieldDef(fAtts,name,fType);
1749 public void SetFieldOrder (ArrayList fields)
1751 this.fields = fields;
1755 /// Add a method to this class
1757 /// <param name="name">method name</param>
1758 /// <param name="retType">return type</param>
1759 /// <param name="pars">parameters</param>
1760 /// <returns>a descriptor for this new method</returns>
1761 public MethodDef AddMethod(string name, Type retType, Param[] pars)
1763 return AddMethod (name, new Param (ParamAttr.Default, "", retType), pars);
1766 public MethodDef AddMethod (string name, Param ret_param, Param [] pars)
1768 // Console.WriteLine("Adding method " + name + " to class " + this.name);
1769 MethodDef meth = new MethodDef(metaData,name, ret_param, pars);
1775 /// Add a method to this class
1777 /// <param name="mAtts">attributes for this method</param>
1778 /// <param name="iAtts">implementation attributes for this method</param>
1779 /// <param name="name">method name</param>
1780 /// <param name="retType">return type</param>
1781 /// <param name="pars">parameters</param>
1782 /// <returns>a descriptor for this new method</returns>
1783 public MethodDef AddMethod(MethAttr mAtts, ImplAttr iAtts, string name,
1784 Param ret_param, Param [] pars) {
1785 // Console.WriteLine("Adding method " + name + " to class " + this.name);
1786 MethodDef meth = new MethodDef (metaData, mAtts, iAtts, name, ret_param, pars);
1792 /// Add an event to this class
1794 /// <param name="name">event name</param>
1795 /// <param name="eType">event type</param>
1796 /// <returns>a descriptor for this new event</returns>
1797 public Event AddEvent(string name, Type eType)
1799 Event e = new Event(name,eType,this);
1800 if (events == null) events = new ArrayList();
1806 /// Add a property to this class
1808 /// <param name="name">property name</param>
1809 /// <param name="propType">property type</param>
1810 /// <returns>a descriptor for this new property</returns>
1811 public Property AddProperty(string name, Type retType, Type[] pars)
1813 Property p = new Property(name, retType, pars, this);
1814 if (properties == null) properties = new ArrayList();
1820 /// Add a nested class to this class
1822 /// <param name="attrSet">attributes for this nested class</param>
1823 /// <param name="nsName">nested name space name</param>
1824 /// <param name="name">nested class name</param>
1825 /// <returns>a descriptor for this new nested class</returns>
1826 public ClassDef AddNestedClass(TypeAttr attrSet, string nsName,
1828 ClassDef nClass = new ClassDef(attrSet,"",name,metaData);
1829 metaData.AddToTable(MDTable.TypeDef,nClass);
1830 metaData.AddToTable(MDTable.NestedClass,new MapElem(nClass,Row,MDTable.TypeDef));
1831 nClass.parentClass = this;
1835 public static bool IsValueType (Class type)
1837 return IsValueType (type.nameSpace, type.name);
1840 public static bool IsEnum (Class type)
1842 return IsEnum (type.nameSpace, type.name);
1845 public static bool IsValueType (string nsName, string name)
1847 return (nsName == "System" && name == "ValueType");
1850 public static bool IsEnum (string nsName, string name)
1852 return (nsName == "System" && name == "Enum");
1856 /// Add a nested class to this class
1858 /// <param name="attrSet">attributes for this nested class</param>
1859 /// <param name="nsName">nested name space name</param>
1860 /// <param name="name">nested class name</param>
1861 /// <param name="sType">super type of this nested class</param>
1862 /// <returns>a descriptor for this new nested class</returns>
1863 public ClassDef AddNestedClass(TypeAttr attrSet, string nsName,
1864 string name, Class sType) {
1865 ClassDef nClass = AddNestedClass (attrSet, nsName, name);
1866 nClass.SetSuper(sType);
1867 if (ClassDef.IsValueType (sType))
1868 nClass.MakeValueClass (ValueClass.ValueType);
1870 if (ClassDef.IsEnum (sType))
1871 nClass.MakeValueClass (ValueClass.Enum);
1873 if (ClassDef.IsValueType (sType) || ClassDef.IsEnum (sType))
1874 nClass.SetTypeIndex (PrimitiveType.ValueType.GetTypeIndex ());
1876 nClass.typeIndexChecked = true;
1881 /// Add layout information for this class. This class must have the
1882 /// sequential or explicit attribute.
1884 /// <param name="packSize">packing size (.pack)</param>
1885 /// <param name="classSize">class size (.size)</param>
1886 public void AddLayoutInfo (int packSize, int classSize)
1888 layout = new ClassLayout(packSize,classSize,this);
1892 /// Use a method as the implementation for another method (.override)
1894 /// <param name="decl">the method to be overridden</param>
1895 /// <param name="body">the implementation to be used</param>
1896 public void AddMethodOverride(Method decl, Method body)
1898 metaData.AddToTable(MDTable.MethodImpl,new MethodImpl(this,decl,body));
1902 /// Add security to this class NOT YET IMPLEMENTED
1904 /// <param name="permissionSet"></param>
1905 public void AddSecurity(byte[] permissionSet)
1907 throw(new NotYetImplementedException("Class security "));
1908 //flags |= HasSecurity;
1909 // securityActions = permissionSet;
1912 //public void AddLineInfo(int row, int col) { }
1914 internal void CheckTypeIndex()
1916 if (typeIndexChecked) return;
1917 if (superType is ClassDef)
1918 ((ClassDef)superType).CheckTypeIndex();
1919 typeIndex = superType.GetTypeIndex();
1920 typeIndexChecked = true;
1923 internal sealed override void BuildTables(MetaData md)
1926 if ((flags & (uint)TypeAttr.Interface) != 0) { superType = null; }
1927 // Console.WriteLine("Building tables for " + name);
1928 if (layout != null) md.AddToTable(MDTable.ClassLayout,layout);
1929 // Console.WriteLine("adding methods " + methods.Count);
1930 methodIx = md.TableIndex(MDTable.Method);
1931 for (int i=0; i < methods.Count; i++) {
1932 md.AddToTable(MDTable.Method,(MetaDataElement)methods[i]);
1933 ((MethodDef)methods[i]).BuildTables(md);
1935 // Console.WriteLine("adding fields");
1936 fieldIx = md.TableIndex(MDTable.Field);
1937 for (int i=0; i < fields.Count; i++) {
1938 md.AddToTable(MDTable.Field,(MetaDataElement)fields[i]);
1939 ((FieldDef)fields[i]).BuildTables(md);
1941 // Console.WriteLine("adding events and properties");
1942 if (events != null) {
1943 for (int i=0; i < events.Count; i++) {
1944 md.AddToTable(MDTable.Event,(Event)events[i]);
1945 ((Event)events[i]).BuildTables(md);
1947 md.AddToTable(MDTable.EventMap,
1948 new MapElem(this,((Event)events[0]).Row,MDTable.Event));
1950 if (properties != null) {
1951 for (int i=0; i < properties.Count; i++) {
1952 md.AddToTable(MDTable.Property,(Property)properties[i]);
1953 ((Property)properties[i]).BuildTables(md);
1955 md.AddToTable(MDTable.PropertyMap,new MapElem(this,
1956 ((Property)properties[0]).Row,MDTable.Property));
1958 // Console.WriteLine("End of building tables");
1962 internal sealed override uint Size(MetaData md)
1964 return 4 + 2 * md.StringsIndexSize() +
1965 md.CodedIndexSize(CIx.TypeDefOrRef) +
1966 md.TableIndexSize(MDTable.Field) +
1967 md.TableIndexSize(MDTable.Method);
1970 internal sealed override void Write(FileImage output)
1972 output.Write(flags);
1973 output.StringsIndex(nameIx);
1974 output.StringsIndex(nameSpaceIx);
1975 //if (superType != null)
1976 // Console.WriteLine("getting coded index for superType of " + name + " = " + superType.GetCodedIx(CIx.TypeDefOrRef));
1977 output.WriteCodedIndex(CIx.TypeDefOrRef,superType);
1978 output.WriteIndex(MDTable.Field,fieldIx);
1979 output.WriteIndex(MDTable.Method,methodIx);
1982 internal sealed override uint TypeDefOrRefToken()
1989 internal sealed override void TypeSig(MemoryStream sig)
1991 if (!typeIndexChecked) CheckTypeIndex();
1992 sig.WriteByte(GetTypeIndex());
1993 MetaData.CompressNum(TypeDefOrRefToken(),sig);
1996 internal sealed override uint GetCodedIx(CIx code)
1999 case (CIx.TypeDefOrRef) : return 0;
2000 case (CIx.HasCustomAttr) : return 3;
2001 case (CIx.HasDeclSecurity) : return 0;
2002 case (CIx.TypeOrMethodDef) : return 0;
2009 /**************************************************************************/
2011 /// Descriptor for a class/interface declared in another module of THIS
2012 /// assembly, or in another assembly.
2014 public class ClassRef : Class, IExternRef, IResolutionScope {
2016 protected IResolutionScope parent;
2017 protected MetaData metaData;
2019 internal ClassRef(string nsName, string name, MetaData md) : base(nsName, name, md)
2022 tabIx = MDTable.TypeRef;
2026 /// Add a method to this class
2028 /// <param name="name">method name</param>
2029 /// <param name="retType">return type</param>
2030 /// <param name="pars">parameter types</param>
2031 /// <returns>a descriptor for this method</returns>
2032 public MethodRef AddMethod(string name, Type retType, Type[] pars)
2034 return AddMethod (name, retType, pars, 0);
2038 /// Add a method to this class
2040 /// <param name="name">method name</param>
2041 /// <param name="retType">return type</param>
2042 /// <param name="pars">parameter types</param>
2043 /// <param name="gen_param_count">num of generic parameters</param>
2044 /// <returns>a descriptor for this method</returns>
2045 public MethodRef AddMethod (string name, Type retType, Type[] pars, int gen_param_count)
2047 MethodRef meth = new MethodRef (this, name, retType, pars, false, null, gen_param_count);
2048 metaData.AddToTable(MDTable.MemberRef,meth);
2053 /// Add a method to this class
2055 /// <param name="name">method name</param>
2056 /// <param name="retType">return type</param>
2057 /// <param name="pars">parameter types</param>
2058 /// <returns>a descriptor for this method</returns>
2059 public MethodRef AddVarArgMethod(string name, Type retType,
2060 Type[] pars, Type[] optPars)
2062 MethodRef meth = new MethodRef(this,name,retType,pars,true,optPars, 0);
2063 metaData.AddToTable(MDTable.MemberRef,meth);
2068 /// Add a field to this class
2070 /// <param name="name">field name</param>
2071 /// <param name="fType">field type</param>
2072 /// <returns>a descriptor for this field</returns>
2073 public FieldRef AddField(string name, Type fType)
2075 FieldRef field = new FieldRef(this,name,fType);
2076 metaData.AddToTable(MDTable.MemberRef,field);
2080 public ClassRef AddClass (string nsName, string name)
2082 ClassRef aClass = new ClassRef(nsName,name,metaData);
2083 metaData.AddToTable(MDTable.TypeRef,aClass);
2084 aClass.SetParent(this);
2088 public ClassRef AddValueClass (string nsName, string name)
2090 ClassRef aClass = AddClass (nsName, name);
2091 aClass.MakeValueClass (ValueClass.ValueType);
2095 internal void SetParent(IResolutionScope par)
2100 internal override string TypeName()
2102 if ((parent != null) && (parent is AssemblyRef))
2103 return (nameSpace + "." + name + ", " + ((AssemblyRef)parent).TypeName());
2105 return (nameSpace + name);
2108 internal sealed override uint Size(MetaData md)
2110 return md.CodedIndexSize(CIx.ResolutionScope) + 2 *
2111 md.StringsIndexSize();
2114 internal sealed override void Write(FileImage output)
2116 output.WriteCodedIndex(CIx.ResolutionScope,(MetaDataElement) parent);
2117 output.StringsIndex(nameIx);
2118 output.StringsIndex(nameSpaceIx);
2121 internal override sealed uint TypeDefOrRefToken()
2124 cIx = (cIx << 2) | 0x1;
2128 internal override void TypeSig(MemoryStream sig)
2130 sig.WriteByte(GetTypeIndex());
2131 MetaData.CompressNum(TypeDefOrRefToken(),sig);
2134 internal sealed override uint GetCodedIx(CIx code)
2137 case (CIx.TypeDefOrRef) : return 1;
2138 case (CIx.HasCustomAttr) : return 2;
2139 case (CIx.MemberRefParent) : return 1;
2140 case (CIx.ResolutionScope) : return 3;
2147 /**************************************************************************/
2148 public class ExternClassRef : ClassRef {
2150 ExternClass externClass;
2152 internal ExternClassRef(TypeAttr attrs, string nsName, string name,
2153 MetaDataElement declRef, MetaData md) : base(nsName,name,md)
2155 externClass = new ExternClass(attrs,nameSpaceIx,nameIx,declRef);
2156 metaData.AddToTable(MDTable.ExportedType,externClass);
2159 internal ExternClassRef(string name, MetaData md) : base(null,name,md)
2163 public ClassRef AddNestedClass(TypeAttr attrs, string name)
2165 ExternClassRef nestedClass = new ExternClassRef(name,metaData);
2166 externClass = new ExternClass(attrs,0,nameIx,this.externClass);
2167 metaData.AddToTable(MDTable.ExportedType,externClass);
2173 /**************************************************************************/
2175 /// Descriptor for a class defined in another module of THIS assembly
2176 /// and exported (.class extern)
2179 internal class ExternClass : Class {
2181 MetaDataElement parent;
2184 internal ExternClass(TypeAttr attr, uint nsIx, uint nIx,
2185 MetaDataElement paren) : base(nsIx,nIx)
2189 tabIx = MDTable.ExportedType;
2192 internal sealed override uint Size(MetaData md)
2194 return 8 + 2* md.StringsIndexSize() + md.CodedIndexSize(CIx.Implementation);
2197 internal sealed override void Write(FileImage output)
2199 output.Write(flags);
2201 output.StringsIndex(nameIx);
2202 output.StringsIndex(nameSpaceIx);
2203 output.WriteCodedIndex(CIx.Implementation,parent);
2206 internal sealed override uint GetCodedIx(CIx code)
2209 case (CIx.HasCustomAttr) : return 17;
2210 case (CIx.Implementation) : return 2;
2217 public class GenParam : Class {
2220 private string param_name;
2221 private uint sigIx = 0;
2223 public GenParam (int index, string name, GenParamType ptype) : base ((byte) ptype)
2226 this.param_name = name;
2227 tabIx = MDTable.TypeSpec;
2231 get { return index; }
2232 set { index = value; }
2235 public string Name {
2236 get { return param_name; }
2237 set { param_name = value; }
2240 public GenParamType Type {
2241 get { return (GenParamType) GetTypeIndex (); }
2244 internal sealed override void BuildTables (MetaData md)
2248 MemoryStream str = new MemoryStream ();
2250 sigIx = md.AddToBlobHeap (str.ToArray ());
2255 internal sealed override void TypeSig(MemoryStream str)
2258 throw new PEFileException (String.Format ("Unresolved {0} - {1}", (GenParamType) GetTypeIndex (), param_name));
2259 str.WriteByte(typeIndex);
2260 MetaData.CompressNum ((uint) index, str);
2263 internal override uint Size(MetaData md)
2265 return md.BlobIndexSize();
2268 internal sealed override void Write (FileImage output)
2270 output.BlobIndex (sigIx);
2273 internal sealed override uint GetCodedIx(CIx code)
2276 case (CIx.TypeDefOrRef) : return 2;
2277 case (CIx.HasCustomAttr) : return 13;
2278 case (CIx.MemberRefParent) : return 4;
2284 public class GenericTypeInst : Class {
2286 private Type gen_type;
2287 private Type[] gen_param;
2288 bool inTable = false;
2291 public GenericTypeInst (Type gen_type, Type[] gen_param)
2292 : base ((byte) PrimitiveType.GenericInst.GetTypeIndex ())
2294 this.gen_type = gen_type;
2295 this.gen_param = gen_param;
2296 tabIx = MDTable.TypeSpec;
2299 internal override MetaDataElement GetTypeSpec (MetaData md)
2302 md.AddToTable (MDTable.TypeSpec, this);
2309 internal sealed override void TypeSig(MemoryStream str)
2311 str.WriteByte(typeIndex);
2312 gen_type.TypeSig (str);
2313 MetaData.CompressNum ((uint) gen_param.Length, str);
2314 foreach (Type param in gen_param)
2315 param.TypeSig (str);
2318 internal sealed override void BuildTables (MetaData md)
2322 MemoryStream str = new MemoryStream ();
2324 sigIx = md.AddToBlobHeap (str.ToArray ());
2329 internal sealed override uint Size (MetaData md)
2331 return md.BlobIndexSize ();
2334 internal sealed override void Write (FileImage output)
2336 output.BlobIndex (sigIx);
2339 internal sealed override uint GetCodedIx (CIx code)
2342 case (CIx.TypeDefOrRef): return 2;
2343 case (CIx.MemberRefParent): return 4;
2344 case (CIx.HasCustomAttr): return 13;
2350 public class GenericMethodSig {
2352 private Type[] gen_param;
2354 private uint sigIx = 0;
2356 public GenericMethodSig (Type[] gen_param)
2358 this.gen_param = gen_param;
2362 internal void TypeSig (MemoryStream str)
2364 str.WriteByte (0x0A); /* GENERIC_INST */
2365 MetaData.CompressNum ((uint) gen_param.Length, str);
2366 foreach (Type param in gen_param)
2367 param.TypeSig (str);
2370 internal uint GetSigIx (MetaData md)
2375 MemoryStream sig = new MemoryStream();
2377 sigIx = md.AddToBlobHeap (sig.ToArray());
2383 public class Sentinel : Type {
2385 public Sentinel () : base (0x41) { }
2387 internal sealed override void TypeSig(MemoryStream str)
2389 str.WriteByte(typeIndex);
2393 /**************************************************************************/
2395 /// Descriptor for a FunctionPointer type
2398 public class MethPtrType : Type {
2410 /// Create a new function pointer type
2412 /// <param name="meth">the function to be referenced</param>
2413 public MethPtrType (CallConv callconv, Type retType, Type[] pars,
2414 bool varArgMeth, Type[] optPars) : base(0x1B)
2416 this.retType = retType;
2417 callConv = callconv;
2419 this.varArgMeth = varArgMeth;
2420 if (parList != null) numPars = (uint)parList.Length;
2422 optParList = optPars;
2423 if (optParList != null) numOptPars = (uint)optParList.Length;
2424 callConv |= CallConv.Vararg;
2426 tabIx = MDTable.TypeSpec;
2429 internal sealed override void TypeSig(MemoryStream sig)
2431 sig.WriteByte(typeIndex);
2432 // Bootlegged from method ref
2433 sig.WriteByte((byte)callConv);
2434 MetaData.CompressNum (numPars + numOptPars, sig);
2435 retType.TypeSig (sig);
2436 for (int i=0; i < numPars; i++) {
2437 parList[i].TypeSig (sig);
2440 sig.WriteByte (0x41); // Write the sentinel
2441 for (int i=0; i < numOptPars; i++) {
2442 optParList[i].TypeSig (sig);
2447 internal sealed override void BuildTables(MetaData md)
2450 MemoryStream sig = new MemoryStream();
2452 sigIx = md.AddToBlobHeap(sig.ToArray());
2456 internal sealed override uint Size(MetaData md)
2458 return md.BlobIndexSize();
2461 internal sealed override void Write(FileImage output)
2463 output.BlobIndex(sigIx);
2466 internal sealed override uint GetCodedIx(CIx code) { return 0x1B; }
2471 /* Classes for Arrays */
2474 /// The IL Array type
2476 public abstract class Array : Type {
2478 protected Type elemType;
2479 protected MetaData metaData;
2480 protected string cnameSpace, cname;
2482 internal Array(Type eType, byte TypeId) : base(TypeId)
2485 tabIx = MDTable.TypeSpec;
2490 /// Single dimensional array with zero lower bound
2492 public class ZeroBasedArray : Array {
2495 /// Create a new array - elementType[]
2497 /// <param name="elementType">the type of the array elements</param>
2498 public ZeroBasedArray(Type elementType) : base (elementType, PrimitiveType.SZArray.GetTypeIndex ()) { }
2500 internal sealed override void TypeSig(MemoryStream str)
2502 str.WriteByte(typeIndex);
2503 elemType.TypeSig(str);
2509 /// Multi dimensional array with explicit bounds
2511 public class BoundArray : Array {
2517 /// Create a new multi dimensional array type
2518 /// eg. elemType[1..5,3..10,5,,] would be
2519 /// new BoundArray(elemType,5,[1,3,0],[5,10,4])
2521 /// <param name="elementType">the type of the elements</param>
2522 /// <param name="dimensions">the number of dimensions</param>
2523 /// <param name="loBounds">lower bounds of dimensions</param>
2524 /// <param name="sizes">sizes for the dimensions</param>
2525 public BoundArray(Type elementType, uint dimensions, int[] loBounds,
2526 int[] sizes) : base (elementType,0x14)
2528 numDims = dimensions;
2529 lowerBounds = loBounds;
2534 /// Create a new multi dimensional array type
2535 /// eg. elemType[5,10,20] would be new BoundArray(elemType,3,[5,10,20])
2537 /// <param name="elementType">the type of the elements</param>
2538 /// <param name="dimensions">the number of dimensions</param>
2539 /// <param name="size">the sizes of the dimensions</param>
2540 public BoundArray(Type elementType, uint dimensions, int[] size)
2541 : base (elementType,0x14)
2543 numDims = dimensions;
2548 /// Create a new multi dimensional array type
2549 /// eg. elemType[,,] would be new BoundArray(elemType,3)
2551 /// <param name="elementType">the type of the elements</param>
2552 /// <param name="dimensions">the number of dimensions</param>
2553 public BoundArray(Type elementType, uint dimensions)
2554 : base (elementType,0x14)
2556 numDims = dimensions;
2559 internal sealed override void TypeSig(MemoryStream str)
2561 str.WriteByte(typeIndex);
2562 elemType.TypeSig(str);
2563 MetaData.CompressNum(numDims,str);
2564 if ((sizes != null) && (sizes.Length > 0)) {
2566 MetaData.CompressNum((uint)sizes.Length,str);
2567 for (int i=0; i < sizes.Length; i++) {
2568 MetaData.CompressNum((uint)sizes[i],str);
2570 } else str.WriteByte(0);
2571 if ((lowerBounds != null) && (lowerBounds.Length > 0)) {
2572 MetaData.CompressNum((uint)lowerBounds.Length,str);
2573 for (int i=0; i < lowerBounds.Length; i++) {
2574 CompressSignedNum (lowerBounds[i],str);
2576 } else str.WriteByte(0);
2578 private void CompressSignedNum (int val, MemoryStream str)
2580 uint uval = (uint) val;
2587 /* Map the signed number to an unsigned number in two ways.
2589 fval: left-rotated 2's complement representation
2590 sval: map the signed number to unsigned as follows: 0 -> 0, -1 -> 1, 1 -> 2, -2 -> 3, 2 -> 4, ....
2591 the mapping is: x -> 2*|x| - signbit(x)
2593 uint fval = (uval << 1) | sign;
2594 int sval = (val << 1) - sign;
2596 /* An overly clever transformation:
2598 a. sval is used to determine the number of bytes in the compressed representation.
2599 b. fval is truncated to the appropriate number of bits and output using the
2600 normal unsigned-int compressor.
2602 However, or certain values, the truncated fval doesn't carry enough information to round trip.
2604 (fval & 0x3FFF) <= 0x7F => compressor emits 1 byte, not 2 => there is aliasing of values
2606 So, we use full 4 bytes to encode such values.
2608 LAMESPEC: The Microsoft implementation doesn't appear to handle this subtle case.
2609 e.g., it ends up encoding -8192 as the byte 0x01, which decodes to -64
2612 MetaData.CompressNum (fval & 0x7F, str);
2613 else if (sval <= 0x3FFF && (fval & 0x3FFF) > 0x7F)
2614 MetaData.CompressNum (fval & 0x3FFF, str);
2615 else if (sval <= 0x1FFFFFFF && (fval & 0x1FFFFFFF) > 0x3FFF)
2616 MetaData.CompressNum (fval & 0x1FFFFFFF, str);
2618 /* FIXME: number cannot be represented. Report a warning. */
2619 // throw new Exception ("cannot represent signed value" + -val);
2620 MetaData.CompressNum (fval, str);
2627 /* Empty interface for grouping TypeRef's possible ResolutionScope
2628 namely : Module, ModuleRef, AssemblyRef and TypeRef */
2629 public interface IResolutionScope {
2632 /**************************************************************************/
2634 /// Base class for scopes (extended by Module, ModuleRef, Assembly, AssemblyRef)
2636 public abstract class ResolutionScope : MetaDataElement, IResolutionScope {
2638 protected uint nameIx = 0;
2639 protected MetaData metaData;
2640 protected string name;
2642 internal ResolutionScope(string name, MetaData md)
2646 nameIx = md.AddToStringsHeap(name);
2649 internal string GetName() { return name; }
2653 /**************************************************************************/
2655 /// Descriptor for THIS assembly (.assembly)
2657 public class Assembly : ResolutionScope {
2659 ushort majorVer, minorVer, buildNo, revisionNo;
2662 uint keyIx = 0, cultIx = 0;
2663 bool hasPublicKey = false;
2665 internal Assembly(string name, MetaData md) : base(name,md)
2667 tabIx = MDTable.Assembly;
2671 /// Add details about THIS assembly
2673 /// <param name="majVer">Major Version</param>
2674 /// <param name="minVer">Minor Version</param>
2675 /// <param name="bldNo">Build Number</param>
2676 /// <param name="revNo">Revision Number</param>
2677 /// <param name="key">Hash Key</param>
2678 /// <param name="hash">Hash Algorithm</param>
2679 /// <param name="cult">Culture</param>
2680 public void AddAssemblyInfo(int majVer, int minVer, int bldNo, int revNo,
2681 byte[] key, uint hash, string cult)
2683 majorVer = (ushort)majVer;
2684 minorVer = (ushort)minVer;
2685 buildNo = (ushort)bldNo;
2686 revisionNo = (ushort)revNo;
2688 hasPublicKey = (key != null);
2689 keyIx = metaData.AddToBlobHeap(key);
2690 cultIx = metaData.AddToStringsHeap(cult);
2694 /// Add an attribute to THIS assembly
2696 /// <param name="aa">assembly attribute</param>
2697 public void AddAssemblyAttr(AssemAttr aa)
2702 internal sealed override uint Size(MetaData md)
2704 return 16 + md.BlobIndexSize() + 2 * md.StringsIndexSize();
2707 internal sealed override void Write(FileImage output)
2709 // Console.WriteLine("Writing assembly element with nameIx of " + nameIx + " at file offset " + output.Seek(0,SeekOrigin.Current));
2710 output.Write((uint)hashAlgId);
2711 output.Write(majorVer);
2712 output.Write(minorVer);
2713 output.Write(buildNo);
2714 output.Write(revisionNo);
2715 output.Write(flags);
2716 output.BlobIndex(keyIx);
2717 output.StringsIndex(nameIx);
2718 output.StringsIndex(cultIx);
2721 internal sealed override uint GetCodedIx(CIx code)
2724 case (CIx.HasCustomAttr) : return 14;
2725 case (CIx.HasDeclSecurity) : return 2;
2730 internal bool HasPublicKey {
2731 get { return hasPublicKey; }
2735 /**************************************************************************/
2737 /// Descriptor for THIS module
2739 public class Module : ResolutionScope, IExternRef {
2744 internal Module(string name, MetaData md) : base(name,md)
2746 mvid = Guid.NewGuid();
2747 mvidIx = md.AddToGUIDHeap(mvid);
2748 tabIx = MDTable.Module;
2752 get { return mvid; }
2755 public ClassRef AddClass(string nsName, string name)
2757 ClassRef aClass = new ClassRef (nsName, name, metaData);
2758 metaData.AddToTable (MDTable.TypeRef, aClass);
2759 aClass.SetParent (this);
2763 public ClassRef AddValueClass(string nsName, string name)
2765 ClassRef aClass = AddClass (nsName, name);
2766 aClass.MakeValueClass (ValueClass.ValueType);
2770 internal sealed override uint Size(MetaData md)
2772 return 2 + md.StringsIndexSize() + 3 * md.GUIDIndexSize();
2775 internal sealed override void Write(FileImage output)
2777 output.Write((short)0);
2778 output.StringsIndex(nameIx);
2779 output.GUIDIndex(mvidIx);
2780 output.GUIDIndex(0);
2781 output.GUIDIndex(0);
2784 internal sealed override uint GetCodedIx(CIx code)
2787 case (CIx.HasCustomAttr) : return 7;
2788 case (CIx.ResolutionScope) : return 0;
2793 /**************************************************************************/
2795 /// Descriptor for another module in THIS assembly
2797 public class ModuleRef : ResolutionScope, IExternRef {
2799 internal ModuleRef(MetaData md, string name) : base(name,md)
2801 tabIx = MDTable.ModuleRef;
2805 /// Add a class to this external module. This is a class declared in
2806 /// another module of THIS assembly.
2808 /// <param name="nsName">name space name</param>
2809 /// <param name="name">class name</param>
2810 /// <returns>a descriptor for this class in another module</returns>
2811 public ClassRef AddClass(string nsName, string name)
2813 ClassRef aClass = new ClassRef(nsName,name,metaData);
2814 metaData.AddToTable(MDTable.TypeRef,aClass);
2815 aClass.SetParent(this);
2820 /// Make a file descriptor to correspond to this module. The file
2821 /// descriptor will have the same name as the module descriptor
2823 /// <param name="hashBytes">the hash of the file</param>
2824 /// <param name="hasMetaData">the file contains metadata</param>
2825 /// <param name="entryPoint">the program entry point is in this file</param>
2826 /// <returns>a descriptor for the file which contains this module</returns>
2827 public FileRef MakeFile(byte[] hashBytes, bool hasMetaData, bool entryPoint)
2829 FileRef file = new FileRef(nameIx,hashBytes,hasMetaData,entryPoint,metaData);
2830 metaData.AddToTable(MDTable.File,file);
2835 /// Add a value class to this module. This is a class declared in
2836 /// another module of THIS assembly.
2838 /// <param name="nsName">name space name</param>
2839 /// <param name="name">class name</param>
2840 /// <returns></returns>
2841 public ClassRef AddValueClass(string nsName, string name)
2843 ClassRef aClass = new ClassRef(nsName,name,metaData);
2844 metaData.AddToTable(MDTable.TypeRef,aClass);
2845 aClass.SetParent(this);
2846 aClass.MakeValueClass(ValueClass.ValueType);
2851 /// Add a class which is declared public in this external module of
2852 /// THIS assembly. This class will be exported from this assembly.
2853 /// The ilasm syntax for this is .extern class
2855 /// <param name="attrSet">attributes of the class to be exported</param>
2856 /// <param name="nsName">name space name</param>
2857 /// <param name="name">external class name</param>
2858 /// <param name="declFile">the file where the class is declared</param>
2859 /// <param name="isValueClass">is this class a value type?</param>
2860 /// <returns>a descriptor for this external class</returns>
2861 public ExternClassRef AddExternClass(TypeAttr attrSet, string nsName,
2862 string name, FileRef declFile,
2863 bool isValueClass) {
2864 ExternClassRef cRef = new ExternClassRef(attrSet,nsName,name,declFile,metaData);
2865 metaData.AddToTable(MDTable.TypeRef,cRef);
2866 cRef.SetParent(this);
2867 if (isValueClass) cRef.MakeValueClass(ValueClass.ValueType);
2872 /// Add a "global" method in another module
2874 /// <param name="name">method name</param>
2875 /// <param name="retType">return type</param>
2876 /// <param name="pars">method parameter types</param>
2877 /// <returns>a descriptor for this method in anther module</returns>
2878 public MethodRef AddMethod(string name, Type retType, Type[] pars)
2880 MethodRef meth = new MethodRef(this,name,retType,pars,false,null, 0);
2881 metaData.AddToTable(MDTable.MemberRef,meth);
2886 /// Add a vararg method to this class
2888 /// <param name="name">method name</param>
2889 /// <param name="retType">return type</param>
2890 /// <param name="pars">parameter types</param>
2891 /// <param name="optPars">optional param types for this vararg method</param>
2892 /// <returns>a descriptor for this method</returns>
2893 public MethodRef AddVarArgMethod(string name, Type retType,
2894 Type[] pars, Type[] optPars) {
2895 MethodRef meth = new MethodRef(this,name,retType,pars,true,optPars, 0);
2896 metaData.AddToTable(MDTable.MemberRef,meth);
2901 /// Add a field in another module
2903 /// <param name="name">field name</param>
2904 /// <param name="fType">field type</param>
2905 /// <returns>a descriptor for this field in another module</returns>
2906 public FieldRef AddField(string name, Type fType)
2908 FieldRef field = new FieldRef(this,name,fType);
2909 metaData.AddToTable(MDTable.MemberRef,field);
2913 internal sealed override uint Size(MetaData md)
2915 return md.StringsIndexSize();
2918 internal sealed override void Write(FileImage output)
2920 output.StringsIndex(nameIx);
2923 internal sealed override uint GetCodedIx(CIx code)
2926 case (CIx.HasCustomAttr) : return 12;
2927 case (CIx.MemberRefParent) : return 2;
2928 case (CIx.ResolutionScope) : return 1;
2935 #region Classes for Constants
2937 /// Descriptor for a constant value
2939 public abstract class Constant {
2940 protected uint size = 0;
2941 protected Type type;
2942 protected uint blobIndex;
2943 protected bool addedToBlobHeap = false;
2945 internal Constant() { }
2947 internal virtual uint GetBlobIndex(MetaData md) { return 0; }
2949 internal uint GetSize() { return size; }
2951 internal byte GetTypeIndex() { return type.GetTypeIndex(); }
2953 internal virtual void Write(BinaryWriter bw) { }
2957 /// Descriptor for a constant value
2959 public abstract class DataConstant : Constant {
2960 private uint dataOffset = 0;
2962 internal DataConstant() { }
2964 public uint DataOffset {
2965 get { return dataOffset; }
2966 set { dataOffset = value; }
2972 /// Boolean constant
2974 public class BoolConst : DataConstant {
2978 /// Create a new boolean constant with the value "val"
2980 /// <param name="val">value of this boolean constant</param>
2981 public BoolConst(bool val)
2985 type = PrimitiveType.Boolean;
2988 internal sealed override uint GetBlobIndex(MetaData md)
2990 if (!addedToBlobHeap) {
2991 if (val) blobIndex = md.AddToBlobHeap((sbyte)1);
2992 else blobIndex = md.AddToBlobHeap((sbyte)0);
2993 addedToBlobHeap = true;
2998 internal sealed override void Write(BinaryWriter bw)
3000 if (val) bw.Write((sbyte)1);
3001 else bw.Write((sbyte)0);
3006 public class ByteArrConst : DataConstant {
3007 internal byte[] val;
3009 public ByteArrConst(byte[] val)
3011 type = PrimitiveType.String;
3013 size = (uint)val.Length;
3017 get { return type; }
3018 set { type = value; }
3021 internal sealed override uint GetBlobIndex(MetaData md)
3023 if (!addedToBlobHeap) {
3024 blobIndex = md.AddToBlobHeap(val);
3025 addedToBlobHeap = true;
3030 internal sealed override void Write(BinaryWriter bw)
3037 public class CharConst : Constant {
3040 public CharConst(char val)
3044 type = PrimitiveType.Char;
3047 internal sealed override uint GetBlobIndex(MetaData md)
3049 if (!addedToBlobHeap) {
3050 blobIndex = md.AddToBlobHeap(val);
3051 addedToBlobHeap = true;
3056 internal sealed override void Write(BinaryWriter bw)
3063 public class FloatConst : DataConstant {
3066 public FloatConst(float val)
3070 type = PrimitiveType.Float32;
3073 internal sealed override uint GetBlobIndex(MetaData md)
3075 if (!addedToBlobHeap) {
3076 blobIndex = md.AddToBlobHeap(val);
3077 addedToBlobHeap = true;
3082 internal sealed override void Write(BinaryWriter bw)
3089 public class DoubleConst : DataConstant {
3092 public DoubleConst(double val)
3096 type = PrimitiveType.Float64;
3099 internal sealed override uint GetBlobIndex(MetaData md)
3101 if (!addedToBlobHeap) {
3102 blobIndex = md.AddToBlobHeap(val);
3103 addedToBlobHeap = true;
3108 internal sealed override void Write(BinaryWriter bw)
3115 public class IntConst : DataConstant {
3118 public IntConst(sbyte val)
3122 type = PrimitiveType.Int8;
3125 public IntConst(short val)
3129 type = PrimitiveType.Int16;
3132 public IntConst(int val)
3136 type = PrimitiveType.Int32;
3139 public IntConst(long val)
3143 type = PrimitiveType.Int64;
3146 internal sealed override uint GetBlobIndex(MetaData md)
3148 if (!addedToBlobHeap) {
3150 case (1) : blobIndex = md.AddToBlobHeap((sbyte)val); break;
3151 case (2) : blobIndex = md.AddToBlobHeap((short)val); break;
3152 case (4) : blobIndex = md.AddToBlobHeap((int)val); break;
3153 default : blobIndex = md.AddToBlobHeap(val); break;
3155 addedToBlobHeap = true;
3160 internal sealed override void Write(BinaryWriter bw)
3163 case (1) : bw.Write((sbyte)val); break;
3164 case (2) : bw.Write((short)val); break;
3165 case (4) : bw.Write((int)val); break;
3166 default : bw.Write(val); break;
3172 public class UIntConst : DataConstant {
3175 public UIntConst(byte val)
3179 type = PrimitiveType.UInt8;
3181 public UIntConst(ushort val)
3185 type = PrimitiveType.UInt16;
3187 public UIntConst(uint val)
3191 type = PrimitiveType.UInt32;
3193 public UIntConst(ulong val)
3197 type = PrimitiveType.UInt64;
3200 internal sealed override uint GetBlobIndex(MetaData md)
3202 if (!addedToBlobHeap) {
3204 case (1) : blobIndex = md.AddToBlobHeap((byte)val); break;
3205 case (2) : blobIndex = md.AddToBlobHeap((ushort)val); break;
3206 case (4) : blobIndex = md.AddToBlobHeap((uint)val); break;
3207 default : blobIndex = md.AddToBlobHeap(val); break;
3209 addedToBlobHeap = true;
3214 internal sealed override void Write(BinaryWriter bw)
3217 case (1) : bw.Write((byte)val); break;
3218 case (2) : bw.Write((ushort)val); break;
3219 case (4) : bw.Write((uint)val); break;
3220 default : bw.Write(val); break;
3226 public class StringConst : DataConstant {
3227 internal string val;
3229 public StringConst(string val)
3232 size = (uint)val.Length; // need to add null ??
3233 type = PrimitiveType.String;
3236 internal sealed override uint GetBlobIndex(MetaData md)
3238 if (!addedToBlobHeap) {
3239 byte [] b = Encoding.Unicode.GetBytes (val);
3240 blobIndex = md.AddToBlobHeap(b);
3241 addedToBlobHeap = true;
3246 internal sealed override void Write(BinaryWriter bw)
3253 public class NullConst : Constant {
3258 type = PrimitiveType.Class;
3261 internal sealed override uint GetBlobIndex(MetaData md)
3263 if (!addedToBlobHeap) {
3264 blobIndex = md.AddToBlobHeap((int)0);
3265 addedToBlobHeap = true;
3270 internal sealed override void Write(BinaryWriter bw)
3277 public class AddressConstant : DataConstant {
3280 public AddressConstant(DataConstant dConst)
3284 type = PrimitiveType.TypedRef;
3287 internal sealed override void Write(BinaryWriter bw)
3289 ((FileImage)bw).WriteDataRVA(data.DataOffset);
3294 public class RepeatedConstant : DataConstant {
3298 public RepeatedConstant(DataConstant dConst, int repeatCount)
3301 repCount = (uint)repeatCount;
3302 int[] sizes = new int[1];
3303 sizes[0] = repeatCount;
3304 type = new BoundArray(type,1,sizes);
3305 size = data.GetSize() * repCount;
3308 internal sealed override void Write(BinaryWriter bw)
3310 for (int i=0; i < repCount; i++) {
3317 public class ArrayConstant : DataConstant {
3318 DataConstant[] dataVals;
3320 public ArrayConstant(DataConstant[] dVals)
3323 for (int i=0; i < dataVals.Length; i++) {
3324 size += dataVals[i].GetSize();
3328 public int? ExplicitSize { get; set; }
3330 internal sealed override void Write(BinaryWriter bw)
3332 for (int i=0; i < dataVals.Length; i++) {
3333 dataVals[i].Write(bw);
3339 public class ClassType : Constant {
3343 public ClassType(string className)
3346 type = PrimitiveType.ClassType;
3349 public ClassType(Class classDesc)
3352 type = PrimitiveType.ClassType;
3355 internal override void Write(BinaryWriter bw)
3357 if (name == null) name = desc.TypeName();
3365 /**************************************************************************/
3367 /// Descriptor for a custom modifier of a type (modopt or modreq)
3370 public class CustomModifiedType : Type {
3374 PrimitiveTypeRef cmodPrimType;
3377 /// Create a new custom modifier for a type
3379 /// <param name="type">the type to be modified</param>
3380 /// <param name="cmod">the modifier</param>
3381 /// <param name="cmodType">the type reference to be associated with the type</param>
3382 public CustomModifiedType(Type type, CustomModifier cmod, Class cmodType)
3386 this.cmodType = cmodType;
3389 public CustomModifiedType(Type type, CustomModifier cmod, PrimitiveTypeRef cmodType)
3393 this.cmodPrimType = cmodType;
3396 internal sealed override void TypeSig(MemoryStream str)
3398 str.WriteByte(typeIndex);
3400 if (cmodType != null) {
3401 MetaData.CompressNum(cmodType.TypeDefOrRefToken(),str);
3403 MetaData.CompressNum(cmodPrimType.TypeDefOrRefToken(),str);
3411 /**************************************************************************/
3413 /// Base class for Event and Property descriptors
3416 public class Feature : MetaDataElement {
3418 internal enum MethodType : ushort { Setter = 0x01, Getter, Other = 0x04, AddOn = 0x08,
3419 RemoveOn = 0x10, Fire = 0x20 }
3421 private static readonly int INITSIZE = 5;
3422 private static readonly ushort specialName = 0x200;
3423 private static readonly ushort rtSpecialName = 0x400;
3425 protected ClassDef parent;
3426 protected ushort flags = 0;
3427 protected string name;
3428 protected int tide = 0;
3429 protected uint nameIx;
3430 protected MethodSemantics[] methods = new MethodSemantics[INITSIZE];
3432 internal Feature(string name, ClassDef par)
3438 internal void AddMethod(MethodDef meth, MethodType mType)
3440 if (tide >= methods.Length) {
3441 int len = methods.Length;
3442 MethodSemantics[] mTmp = methods;
3443 methods = new MethodSemantics[len * 2];
3444 for (int i=0; i < len; i++) {
3445 methods[i] = mTmp[i];
3448 methods[tide++] = new MethodSemantics(mType,meth,this);
3452 /// Set the specialName attribute for this Event or Property
3454 public void SetSpecialName()
3456 flags |= specialName;
3460 /// Set the RTSpecialName attribute for this Event or Property
3462 public void SetRTSpecialName()
3464 flags |= rtSpecialName;
3469 /**************************************************************************/
3471 /// Descriptor for an event
3473 public class Event : Feature {
3477 internal Event(string name, Type eType, ClassDef parent)
3478 : base(name, parent)
3481 tabIx = MDTable.Event;
3485 /// Add the addon method to this event
3487 /// <param name="addon">the addon method</param>
3488 public void AddAddon(MethodDef addon)
3490 AddMethod(addon,MethodType.AddOn);
3494 /// Add the removeon method to this event
3496 /// <param name="removeOn">the removeon method</param>
3497 public void AddRemoveOn(MethodDef removeOn)
3499 AddMethod(removeOn,MethodType.RemoveOn);
3503 /// Add the fire method to this event
3505 /// <param name="fire">the fire method</param>
3506 public void AddFire(MethodDef fire)
3508 AddMethod(fire,MethodType.Fire);
3512 /// Add another method to this event
3514 /// <param name="other">the method to be added</param>
3515 public void AddOther(MethodDef other)
3517 AddMethod(other,MethodType.Other);
3520 internal sealed override void BuildTables(MetaData md)
3523 nameIx = md.AddToStringsHeap(name);
3524 for (int i=0; i < tide; i++) {
3525 md.AddToTable(MDTable.MethodSemantics,methods[i]);
3530 internal sealed override uint Size(MetaData md)
3532 return 2 + md.StringsIndexSize() + md.CodedIndexSize(CIx.TypeDefOrRef);
3535 internal sealed override void Write(FileImage output)
3537 output.Write(flags);
3538 output.StringsIndex(nameIx);
3539 output.WriteCodedIndex(CIx.TypeDefOrRef,eventType);
3542 internal sealed override uint GetCodedIx(CIx code)
3545 case (CIx.HasCustomAttr) : return 10;
3546 case (CIx.HasSemantics) : return 0;
3553 /**************************************************************************/
3555 /// Descriptor for the Property of a class
3557 public class Property : Feature {
3559 private static readonly byte PropertyTag = 0x8;
3560 private bool instance;
3561 MethodDef getterMeth;
3562 ConstantElem constVal;
3563 uint typeBlobIx = 0;
3568 internal Property(string name, Type retType, Type[] pars, ClassDef parent) : base(name, parent)
3570 returnType = retType;
3572 if (pars != null) numPars = (uint)pars.Length;
3573 tabIx = MDTable.Property;
3577 /// Add a set method to this property
3579 /// <param name="setter">the set method</param>
3580 public void AddSetter(MethodDef setter)
3582 AddMethod(setter,MethodType.Setter);
3586 /// Add a get method to this property
3588 /// <param name="getter">the get method</param>
3589 public void AddGetter(MethodDef getter)
3591 AddMethod(getter,MethodType.Getter);
3592 getterMeth = getter;
3596 /// Add another method to this property
3598 /// <param name="other">the method</param>
3599 public void AddOther(MethodDef other)
3601 AddMethod(other,MethodType.Other);
3605 /// Add an initial value for this property
3607 /// <param name="constVal">the initial value for this property</param>
3608 public void AddInitValue(Constant constVal)
3610 this.constVal = new ConstantElem(this,constVal);
3613 public void SetInstance (bool isInstance)
3615 this.instance = isInstance;
3618 internal sealed override void BuildTables(MetaData md)
3621 nameIx = md.AddToStringsHeap(name);
3622 MemoryStream sig = new MemoryStream();
3623 byte tag = PropertyTag;
3627 MetaData.CompressNum(numPars,sig);
3628 returnType.TypeSig(sig);
3629 for (int i=0; i < numPars; i++) {
3630 parList[i].TypeSig(sig);
3632 typeBlobIx = md.AddToBlobHeap(sig.ToArray());
3633 for (int i=0; i < tide; i++) {
3634 md.AddToTable(MDTable.MethodSemantics,methods[i]);
3636 if (constVal != null) {
3637 md.AddToTable(MDTable.Constant,constVal);
3638 constVal.BuildTables(md);
3643 internal sealed override uint Size(MetaData md)
3645 return 2 + md.StringsIndexSize() + md.BlobIndexSize();
3648 internal sealed override void Write(FileImage output)
3650 output.Write(flags);
3651 output.StringsIndex(nameIx);
3652 output.BlobIndex(typeBlobIx);
3655 internal sealed override uint GetCodedIx(CIx code)
3658 case (CIx.HasCustomAttr) : return 9;
3659 case (CIx.HasConst) : return 2;
3660 case (CIx.HasSemantics) : return 1;
3667 /**************************************************************************/
3669 /// Base class for field/methods (member of a class)
3671 public abstract class Member : MetaDataElement {
3673 protected string name;
3674 protected uint nameIx = 0, sigIx = 0;
3676 internal Member(string memName)
3679 tabIx = MDTable.MemberRef;
3684 /*****************************************************************************/
3686 /// Descriptor for a field of a class
3689 public abstract class Field : Member {
3691 protected static readonly byte FieldSig = 0x6;
3693 protected Type type;
3695 internal Field(string pfName, Type pfType) : base(pfName)
3701 /**************************************************************************/
3703 /// Descriptor for a field defined in a class of THIS assembly/module
3705 public class FieldDef : Field {
3707 //private static readonly uint PInvokeImpl = 0x2000;
3708 private static readonly ushort HasFieldRVA = 0x100;
3709 private static readonly ushort HasDefault = 0x8000;
3712 ConstantElem constVal;
3714 FieldMarshal marshalInfo;
3717 internal FieldDef(string name, Type fType) : base(name,fType)
3719 tabIx = MDTable.Field;
3722 internal FieldDef(FieldAttr attrSet, string name, Type fType) : base(name, fType)
3724 flags = (ushort)attrSet;
3725 tabIx = MDTable.Field;
3729 /// Add an attribute(s) to this field
3731 /// <param name="fa">the attribute(s) to be added</param>
3732 public void AddFieldAttr(FieldAttr fa)
3734 flags |= (ushort)fa;
3738 /// Add a value for this field
3740 /// <param name="val">the value for the field</param>
3741 public void AddValue(Constant val)
3743 constVal = new ConstantElem(this,val);
3744 flags |= HasDefault;
3748 /// Add an initial value for this field (at dataLabel) (.data)
3750 /// <param name="val">the value for the field</param>
3751 /// <param name="repeatVal">the number of repetitions of this value</param>
3752 public void AddDataValue(DataConstant val)
3754 flags |= HasFieldRVA;
3755 rva = new FieldRVA(this,val);
3759 /// Set the offset of the field. Used for sequential or explicit classes.
3762 /// <param name="offs">field offset</param>
3763 public void SetOffset(uint offs)
3765 layout = new FieldLayout(this,offs);
3769 /// Set the marshalling info for a field
3771 /// <param name="mInf"></param>
3772 public void SetMarshalInfo(NativeType marshallType)
3774 flags |= (ushort) FieldAttr.HasFieldMarshal;
3775 marshalInfo = new FieldMarshal(this,marshallType);
3778 internal sealed override void BuildTables(MetaData md)
3781 nameIx = md.AddToStringsHeap(name);
3782 MemoryStream sig = new MemoryStream();
3783 sig.WriteByte(FieldSig);
3785 sigIx = md.AddToBlobHeap(sig.ToArray());
3787 md.AddToTable(MDTable.FieldRVA,rva);
3788 rva.BuildTables(md);
3789 } else if (constVal != null) {
3790 md.AddToTable(MDTable.Constant,constVal);
3791 constVal.BuildTables(md);
3793 if (layout != null) md.AddToTable(MDTable.FieldLayout,layout);
3794 if (marshalInfo != null) {
3795 md.AddToTable(MDTable.FieldMarshal,marshalInfo);
3796 marshalInfo.BuildTables(md);
3801 internal sealed override uint Size(MetaData md)
3803 return 2 + md.StringsIndexSize() + md.BlobIndexSize();
3806 internal sealed override void Write(FileImage output)
3808 output.Write(flags);
3809 output.StringsIndex(nameIx);
3810 output.BlobIndex(sigIx);
3813 internal sealed override uint GetCodedIx(CIx code)
3816 case (CIx.HasConst) : return 0;
3817 case (CIx.HasCustomAttr) : return 1;
3818 case (CIx.HasFieldMarshal) : return 0;
3819 case (CIx.MemberForwarded) : return 0;
3826 /**************************************************************************/
3828 /// Descriptor for a field of a class defined in another assembly/module
3830 public class FieldRef : Field {
3832 MetaDataElement parent;
3834 internal FieldRef(MetaDataElement paren, string name, Type fType) : base(name, fType)
3839 internal sealed override void BuildTables(MetaData md)
3842 nameIx = md.AddToStringsHeap(name);
3843 MemoryStream sig = new MemoryStream();
3844 sig.WriteByte(FieldSig);
3846 sigIx = md.AddToBlobHeap(sig.ToArray());
3850 internal sealed override uint Size(MetaData md)
3852 return md.CodedIndexSize(CIx.MemberRefParent) + md.StringsIndexSize() + md.BlobIndexSize();
3855 internal sealed override void Write(FileImage output)
3857 output.WriteCodedIndex(CIx.MemberRefParent,parent);
3858 output.StringsIndex(nameIx);
3859 output.BlobIndex(sigIx);
3862 internal sealed override uint GetCodedIx(CIx code) { return 6; }
3866 /**************************************************************************/
3868 /// Base class for Method Descriptors
3871 public abstract class Method : Member {
3873 internal Method (string methName) : base (methName)
3876 public abstract void AddCallConv(CallConv cconv);
3877 internal abstract void TypeSig(MemoryStream sig);
3878 internal abstract uint GetSigIx(MetaData md);
3881 /**************************************************************************/
3883 /// Descriptor for a method defined in THIS assembly/module
3887 public class MethodDef : Method {
3889 private static readonly ushort PInvokeImpl = 0x2000;
3890 //private static readonly uint UnmanagedExport = 0x0008;
3891 // private static readonly byte LocalSigByte = 0x7;
3892 uint parIx = 0, textOffset = 0;
3893 private CallConv callConv = CallConv.Default;
3894 private int gen_param_count;
3897 CILInstructions code;
3901 ushort methFlags = 0, implFlags = 0;
3902 int maxStack = 0, numPars = 0;
3903 bool entryPoint = false;
3905 ArrayList varArgSigList;
3906 ImplMap pinvokeImpl;
3909 internal MethodDef (MetaData md, string name, Param ret_param, Param [] pars)
3910 : this (md, 0, 0, name, ret_param, pars)
3914 internal MethodDef (MetaData md, MethAttr mAttrSet, ImplAttr iAttrSet, string name,
3915 Param ret_param, Param [] pars)
3918 methFlags = (ushort)mAttrSet;
3919 implFlags = (ushort)iAttrSet;
3920 this.ret_param = ret_param;
3923 if (parList != null)
3924 numPars = parList.Length;
3925 tabIx = MDTable.Method;
3928 internal Param[] GetPars()
3933 internal override uint GetSigIx(MetaData md)
3935 MemoryStream sig = new MemoryStream();
3937 return md.AddToBlobHeap(sig.ToArray());
3940 public override void AddCallConv(CallConv cconv)
3946 /// Add some attributes to this method descriptor
3948 /// <param name="ma">the attributes to be added</param>
3949 public void AddMethAttribute(MethAttr ma)
3951 methFlags |= (ushort)ma;
3955 /// Add some implementation attributes to this method descriptor
3957 /// <param name="ia">the attributes to be added</param>
3958 public void AddImplAttribute(ImplAttr ia)
3960 implFlags |= (ushort)ia;
3963 public void AddPInvokeInfo(ModuleRef scope, string methName,
3964 PInvokeAttr callAttr) {
3965 pinvokeImpl = new ImplMap((ushort)callAttr,this,methName,scope);
3966 methFlags |= PInvokeImpl;
3970 /// Add a named generic type parameter
3972 public GenericParameter AddGenericParameter (short index, string name)
3974 return AddGenericParameter (index, name, 0);
3978 /// Add a named generic type parameter with attributes
3980 public GenericParameter AddGenericParameter (short index, string name, GenericParamAttributes attr)
3982 GenericParameter gp = new GenericParameter (this, metaData, index, name, attr);
3983 metaData.AddToTable (MDTable.GenericParam, gp);
3989 /// Set the maximum stack height for this method
3991 /// <param name="maxStack">the maximum height of the stack</param>
3992 public void SetMaxStack(int maxStack)
3994 this.maxStack = maxStack;
3998 /// Add local variables to this method
4000 /// <param name="locals">the locals to be added</param>
4001 /// <param name="initLocals">are locals initialised to default values</param>
4002 public void AddLocals(Local[] locals, bool initLocals)
4004 this.locals = locals;
4005 this.initLocals = initLocals;
4008 /* Add Marshal info for return type */
4009 public void AddRetTypeMarshallInfo (NativeType marshallType)
4011 ret_param.AddMarshallInfo (marshallType);
4015 /// Mark this method as having an entry point
4017 public void DeclareEntryPoint()
4023 /// Create a code buffer for this method to add the IL instructions to
4025 /// <returns>a buffer for this method's IL instructions</returns>
4026 public CILInstructions CreateCodeBuffer()
4028 code = new CILInstructions(metaData);
4033 /// Make a method reference descriptor for this method to be used
4034 /// as a callsite signature for this vararg method
4036 /// <param name="optPars">the optional pars for the vararg method call</param>
4037 /// <returns></returns>
4038 public MethodRef MakeVarArgSignature(Type[] optPars)
4040 Type[] pars = new Type[numPars];
4041 MethodRef varArgSig;
4042 for (int i=0; i < numPars; i++) {
4043 pars[i] = parList[i].GetParType();
4045 varArgSig = new MethodRef (this, name, ret_param.GetParType (), pars, true, optPars, 0);
4047 if (varArgSigList == null)
4048 varArgSigList = new ArrayList ();
4049 varArgSigList.Add (varArgSig);
4053 internal sealed override void TypeSig(MemoryStream sig)
4055 sig.WriteByte((byte)callConv);
4056 if ((callConv & CallConv.Generic) == CallConv.Generic)
4057 MetaData.CompressNum ((uint) gen_param_count, sig);
4058 MetaData.CompressNum((uint)numPars,sig);
4060 ret_param.seqNo = 0;
4061 ret_param.TypeSig (sig);
4062 for (ushort i=0; i < numPars; i++) {
4063 parList[i].seqNo = (ushort)(i+1);
4064 parList[i].TypeSig(sig);
4068 internal sealed override void BuildTables(MetaData md)
4071 if (pinvokeImpl != null) {
4072 md.AddToTable(MDTable.ImplMap,pinvokeImpl);
4073 pinvokeImpl.BuildTables(md);
4075 if (entryPoint) md.SetEntryPoint(this);
4077 if (locals != null) {
4078 localSig = new LocalSig(locals);
4079 md.AddToTable(MDTable.StandAloneSig,localSig);
4080 localSig.BuildTables(md);
4081 locToken = localSig.Token();
4084 code.CheckCode(locToken,initLocals,maxStack);
4085 textOffset = md.AddCode(code);
4087 nameIx = md.AddToStringsHeap(name);
4088 sigIx = GetSigIx(md);
4089 parIx = md.TableIndex(MDTable.Param);
4090 if (ret_param.HasMarshalInfo || ret_param.HasCustomAttr) {
4091 md.AddToTable(MDTable.Param, ret_param);
4092 ret_param.BuildTables(md);
4094 for (int i=0; i < numPars; i++) {
4095 md.AddToTable(MDTable.Param,parList[i]);
4096 parList[i].BuildTables(md);
4098 if (varArgSigList != null) {
4099 foreach (MethodRef varArgSig in varArgSigList) {
4100 md.AddToTable(MDTable.MemberRef,varArgSig);
4101 varArgSig.BuildTables(md);
4104 // Console.WriteLine("method has " + numPars + " parameters");
4108 internal sealed override uint Size(MetaData md)
4110 return 8 + md.StringsIndexSize() + md.BlobIndexSize() + md.TableIndexSize(MDTable.Param);
4113 internal sealed override void Write(FileImage output)
4115 if (ZeroRva ()) output.Write(0);
4116 else output.WriteCodeRVA(textOffset);
4117 output.Write(implFlags);
4118 output.Write(methFlags);
4119 output.StringsIndex(nameIx);
4120 output.BlobIndex(sigIx);
4121 output.WriteIndex(MDTable.Param,parIx);
4124 internal bool ZeroRva ()
4126 return (((methFlags & (ushort)MethAttr.Abstract) != 0) ||
4127 ((implFlags & (ushort)ImplAttr.Runtime) != 0) ||
4128 ((implFlags & (ushort)ImplAttr.InternalCall) != 0) ||
4129 (pinvokeImpl != null)); // TODO: Not entirely true but works for now
4132 internal sealed override uint GetCodedIx(CIx code)
4135 case (CIx.HasCustomAttr) : return 0;
4136 case (CIx.HasDeclSecurity) : return 1;
4137 case (CIx.MemberRefParent) : return 3;
4138 case (CIx.MethodDefOrRef) : return 0;
4139 case (CIx.MemberForwarded) : return 1;
4140 case (CIx.CustomAttributeType) : return 2;
4141 case (CIx.TypeOrMethodDef) : return 1;
4147 /**************************************************************************/
4149 /// Descriptor for a method defined in another assembly/module
4151 public class MethodRef : Method {
4153 private static readonly byte Sentinel = 0x41;
4154 Type[] parList, optParList;
4155 MetaDataElement parent;
4156 uint numPars = 0, numOptPars = 0;
4157 CallConv callConv = CallConv.Default;
4159 int gen_param_count;
4161 internal MethodRef(MetaDataElement paren, string name, Type retType,
4162 Type[] pars, bool varArgMeth, Type[] optPars, int gen_param_count) : base(name)
4166 this.retType = retType;
4167 if (parList != null) numPars = (uint)parList.Length;
4169 optParList = optPars;
4170 if (optParList != null) numOptPars = (uint)optParList.Length;
4171 callConv = CallConv.Vararg;
4173 this.gen_param_count = gen_param_count;
4176 internal override uint GetSigIx(MetaData md)
4178 MemoryStream sig = new MemoryStream();
4180 return md.AddToBlobHeap(sig.ToArray());
4183 public override void AddCallConv(CallConv cconv)
4188 internal sealed override void TypeSig(MemoryStream sig)
4190 sig.WriteByte((byte)callConv);
4191 if ((callConv & CallConv.Generic) == CallConv.Generic)
4192 MetaData.CompressNum ((uint) gen_param_count, sig);
4193 MetaData.CompressNum(numPars+numOptPars,sig);
4194 retType.TypeSig(sig);
4195 for (int i=0; i < numPars; i++) {
4196 parList[i].TypeSig(sig);
4198 if (numOptPars > 0) {
4199 sig.WriteByte(Sentinel);
4200 for (int i=0; i < numOptPars; i++) {
4201 optParList[i].TypeSig(sig);
4206 internal sealed override void BuildTables(MetaData md)
4209 nameIx = md.AddToStringsHeap(name);
4210 sigIx = GetSigIx(md);
4214 internal sealed override uint Size(MetaData md)
4216 return md.CodedIndexSize(CIx.MemberRefParent) + md.StringsIndexSize() + md.BlobIndexSize();
4219 internal sealed override void Write(FileImage output)
4221 output.WriteCodedIndex(CIx.MemberRefParent,parent);
4222 output.StringsIndex(nameIx);
4223 output.BlobIndex(sigIx);
4226 internal sealed override uint GetCodedIx(CIx code)
4229 case (CIx.HasCustomAttr) : return 6;
4230 case (CIx.MethodDefOrRef) : return 1;
4231 case (CIx.CustomAttributeType) : return 3;
4239 /**************************************************************************/
4241 /// Descriptors for native types used for marshalling
4243 public class NativeType {
4244 public static readonly NativeType Void = new NativeType(0x01);
4245 public static readonly NativeType Boolean = new NativeType(0x02);
4246 public static readonly NativeType Int8 = new NativeType(0x03);
4247 public static readonly NativeType UInt8 = new NativeType(0x04);
4248 public static readonly NativeType Int16 = new NativeType(0x05);
4249 public static readonly NativeType UInt16 = new NativeType(0x06);
4250 public static readonly NativeType Int32 = new NativeType(0x07);
4251 public static readonly NativeType UInt32 = new NativeType(0x08);
4252 public static readonly NativeType Int64 = new NativeType(0x09);
4253 public static readonly NativeType UInt64 = new NativeType(0x0A);
4254 public static readonly NativeType Float32 = new NativeType(0x0B);
4255 public static readonly NativeType Float64 = new NativeType(0x0C);
4256 public static readonly NativeType Currency = new NativeType(0x0F);
4257 public static readonly NativeType BStr = new NativeType(0x13);
4258 public static readonly NativeType LPStr = new NativeType(0x14);
4259 public static readonly NativeType LPWStr = new NativeType(0x15);
4260 public static readonly NativeType LPTStr = new NativeType(0x16);
4261 public static readonly NativeType FixedSysString = new NativeType(0x17);
4262 public static readonly NativeType IUnknown = new NativeType(0x19);
4263 public static readonly NativeType IDispatch = new NativeType(0x1A);
4264 public static readonly NativeType Struct = new NativeType(0x1B);
4265 public static readonly NativeType Interface = new NativeType(0x1C);
4266 public static readonly NativeType Int = new NativeType(0x1F);
4267 public static readonly NativeType UInt = new NativeType(0x20);
4268 public static readonly NativeType ByValStr = new NativeType(0x22);
4269 public static readonly NativeType AnsiBStr = new NativeType(0x23);
4270 public static readonly NativeType TBstr = new NativeType(0x24);
4271 public static readonly NativeType VariantBool = new NativeType(0x25);
4272 public static readonly NativeType FuncPtr = new NativeType(0x26);
4273 public static readonly NativeType AsAny = new NativeType(0x28);
4274 public static readonly NativeType LPStruct = new NativeType(0x2b);
4275 public static readonly NativeType Error = new NativeType(0x2d);
4277 protected byte typeIndex;
4279 internal NativeType(byte tyIx) { typeIndex = tyIx; }
4280 internal byte GetTypeIndex() { return typeIndex; }
4282 internal virtual byte[] ToBlob()
4284 byte[] bytes = new byte[1];
4285 bytes[0] = GetTypeIndex();
4291 public class FixedSysString : NativeType {
4295 public FixedSysString (uint size) : base (NativeType.FixedSysString.GetTypeIndex ())
4300 internal override byte [] ToBlob ()
4302 MemoryStream str = new MemoryStream ();
4303 str.WriteByte (GetTypeIndex ());
4304 MetaData.CompressNum (size, str);
4305 return str.ToArray ();
4310 public class NativeArray : NativeType {
4312 NativeType elemType;
4313 int numElem = -1, parNum = -1, elemMult = -1;
4315 public NativeArray(NativeType elemType) : this (elemType, -1, -1, -1)
4317 this.elemType = elemType;
4320 /* public NativeArray(NativeType elemType, int len) : base(0x2A) {
4321 this.elemType = elemType;
4326 public NativeArray(NativeType elemType, int numElem, int parNumForLen, int elemMult) : base(0x2A)
4328 this.elemType = elemType;
4329 this.numElem = numElem;
4330 parNum = parNumForLen;
4331 this.elemMult = elemMult;
4334 public NativeArray(NativeType elemType, int numElem, int parNumForLen)
4335 : this (elemType, numElem, parNumForLen, -1)
4339 internal override byte[] ToBlob()
4341 MemoryStream str = new MemoryStream();
4342 str.WriteByte(GetTypeIndex());
4343 if (elemType == null) str.WriteByte(0x50); // no info (MAX)
4344 else str.WriteByte(elemType.GetTypeIndex());
4346 /* see : mono/metadata/metadata.c:mono_metadata_parse_marshal_spec
4347 * LAMESPEC: Older spec versions say elemMult comes before
4348 * len. Newer spec versions don't talk about elemMult at
4349 * all, but csc still emits it, and it is used to distinguish
4350 * between parNum being 0, and parNum being omitted.
4355 return str.ToArray ();
4357 MetaData.CompressNum((uint) parNum,str);
4358 if (numElem != -1) {
4359 MetaData.CompressNum ((uint) numElem, str);
4361 // <native_type> [ int32 ]
4362 MetaData.CompressNum((uint) elemMult,str);
4363 //else <native_type> [ int32 + int32 ]
4364 } else if (elemMult != -1) {
4365 // When can this occur ?
4366 MetaData.CompressNum (0, str);
4367 MetaData.CompressNum((uint) elemMult,str);
4369 //else <native_type> [ + int32 ]
4371 return str.ToArray();
4376 public class SafeArray : NativeType {
4378 SafeArrayType elemType;
4381 public SafeArray() : base(0x1D)
4385 public SafeArray(SafeArrayType elemType) : base(0x1D)
4387 this.elemType = elemType;
4391 internal override byte[] ToBlob()
4393 byte[] bytes = new byte[hasElemType ? 2 : 1];
4394 bytes[0] = GetTypeIndex();
4396 bytes[1] = (byte)elemType;
4402 public class FixedArray : NativeType {
4406 //public FixedArray(NativeType elemType, int numElems) : base(0x1E) {
4407 public FixedArray(int numElems) : base(0x1E)
4409 //this.elemType = elemType;
4410 numElem = (uint)numElems;
4413 internal override byte[] ToBlob()
4415 MemoryStream str = new MemoryStream();
4416 str.WriteByte(GetTypeIndex());
4417 MetaData.CompressNum(numElem,str);
4419 fixed array [5] lpstr [2]
4420 This format is not supported by ilasm 1.1.4322.2032,
4421 but is supported by 2.0.5125..
4422 ilasm 1.1 only supports "fixed array [5]"
4423 if (elemType == null) str.WriteByte(0x50); // no info (MAX)
4424 else str.WriteByte(elemType.GetTypeIndex());*/
4426 return str.ToArray();
4431 public class CustomMarshaller : NativeType {
4434 string marshallerName;
4437 public CustomMarshaller(string typeNameOrGUID, string marshallerName,
4438 string optCookie) : base(0x2C)
4440 typeName = typeNameOrGUID;
4441 this.marshallerName = marshallerName;
4445 public CustomMarshaller(string marshallerName, string optCookie)
4446 :this (null, marshallerName, optCookie)
4450 internal override byte[] ToBlob()
4452 MemoryStream str = new MemoryStream();
4453 BinaryWriter bw = new BinaryWriter(str,new UTF8Encoding());
4454 bw.Write(GetTypeIndex());
4455 //Native type name & unmanaged type - unused
4456 //See mono/metadata/metadata.c : mono_metadata_parse_marshal_spec
4457 bw.Write ((byte) 0); // Native Type name, unused
4458 bw.Write ((byte) 0); // Unmanaged type, unused
4459 if (marshallerName != null) {
4460 MetaData.CompressNum ((uint)marshallerName.Length, str);
4461 bw.Write(marshallerName.ToCharArray());
4463 bw.Write ((byte) 0);
4465 if (cookie != null) {
4466 MetaData.CompressNum ((uint)cookie.Length, str);
4467 bw.Write(cookie.ToCharArray());
4469 bw.Write ((byte) 0);
4472 return str.ToArray();
4476 /**************************************************************************/
4478 /// Descriptor for the Primitive types defined in IL
4480 public class PrimitiveType : Type {
4482 private string name;
4483 private int systemTypeIndex;
4484 public static int NumSystemTypes = 18;
4486 public static readonly PrimitiveType Void = new PrimitiveType(0x01,"Void",0);
4487 public static readonly PrimitiveType Boolean = new PrimitiveType(0x02,"Boolean",1);
4488 public static readonly PrimitiveType Char = new PrimitiveType(0x03,"Char",2);
4489 public static readonly PrimitiveType Int8 = new PrimitiveType(0x04,"SByte",3);
4490 public static readonly PrimitiveType UInt8 = new PrimitiveType(0x05,"Byte",4);
4491 public static readonly PrimitiveType Int16 = new PrimitiveType(0x06,"Int16",5);
4492 public static readonly PrimitiveType UInt16 = new PrimitiveType(0x07,"UInt16",6);
4493 public static readonly PrimitiveType Int32 = new PrimitiveType(0x08,"Int32",7);
4494 public static readonly PrimitiveType UInt32 = new PrimitiveType(0x09,"UInt32",8);
4495 public static readonly PrimitiveType Int64 = new PrimitiveType(0x0A,"Int64",9);
4496 public static readonly PrimitiveType UInt64 = new PrimitiveType(0x0B,"UInt64",10);
4497 public static readonly PrimitiveType Float32 = new PrimitiveType(0x0C,"Single",11);
4498 public static readonly PrimitiveType Float64 = new PrimitiveType(0x0D,"Double",12);
4499 public static readonly PrimitiveType String = new PrimitiveType(0x0E,"String",13);
4500 internal static readonly PrimitiveType Class = new PrimitiveType(0x12);
4501 internal static readonly PrimitiveType Var = new PrimitiveType(0x13);
4502 internal static readonly PrimitiveType GenericInst = new PrimitiveType(0x15);
4503 public static readonly PrimitiveType TypedRef = new PrimitiveType(0x16,"TypedReference",14);
4504 public static readonly PrimitiveType IntPtr = new PrimitiveType(0x18,"IntPtr",15);
4505 public static readonly PrimitiveType UIntPtr = new PrimitiveType(0x19,"UIntPtr",16);
4506 public static readonly PrimitiveType Object = new PrimitiveType(0x1C,"Object",17);
4507 internal static readonly PrimitiveType ClassType = new PrimitiveType(0x50);
4508 internal static readonly PrimitiveType SZArray = new PrimitiveType(0x1D);
4509 internal static readonly PrimitiveType MVar = new PrimitiveType(0x1E);
4510 internal static readonly PrimitiveType ValueType = new PrimitiveType(0x11, "ValueType", 18);
4511 public static readonly PrimitiveType NativeInt = IntPtr;
4512 public static readonly PrimitiveType NativeUInt = UIntPtr;
4514 internal PrimitiveType(byte typeIx) : base(typeIx) { }
4516 internal PrimitiveType(byte typeIx, string name, int STIx) : base(typeIx)
4519 this.systemTypeIndex = STIx;
4522 internal string GetName() { return name; }
4524 internal int GetSystemTypeIx() { return systemTypeIndex; }
4526 internal sealed override void TypeSig(MemoryStream str)
4528 str.WriteByte(typeIndex);
4531 internal override MetaDataElement GetTypeSpec(MetaData md)
4533 TypeSpec tS = md.GetPrimitiveTypeSpec(systemTypeIndex);
4535 tS = new TypeSpec(this,md);
4536 md.SetPrimitiveTypeSpec(systemTypeIndex,tS);
4537 md.AddToTable(MDTable.TypeSpec,tS);
4544 public class PrimitiveTypeRef : Type
4549 internal PrimitiveTypeRef(PrimitiveType type, MetaData md)
4556 internal uint TypeDefOrRefToken()
4558 uint cIx = type.GetTypeSpec (metaData).Row;
4559 cIx = (cIx << 2) | 0x2;
4564 /**************************************************************************/
4566 /// Descriptor for an pointer (type * or type &)
4568 public abstract class PtrType : Type {
4572 internal PtrType(Type bType, byte typeIx) : base(typeIx)
4575 tabIx = MDTable.TypeSpec;
4578 internal sealed override void TypeSig(MemoryStream str)
4580 str.WriteByte(typeIndex);
4581 baseType.TypeSig(str);
4585 /**************************************************************************/
4587 /// Descriptor for a managed pointer (type & or byref)
4590 public class ManagedPointer : PtrType {
4593 /// Create new managed pointer to baseType
4595 /// <param name="bType">the base type of the pointer</param>
4596 public ManagedPointer(Type baseType) : base(baseType,0x10) { }
4599 /**************************************************************************/
4601 /// Descriptor for an unmanaged pointer (type *)
4603 public class UnmanagedPointer : PtrType {
4606 /// Create a new unmanaged pointer to baseType
4608 /// <param name="baseType">the base type of the pointer</param>
4609 public UnmanagedPointer(Type baseType) : base(baseType, 0x0F) { }
4613 /**************************************************************************/
4615 public interface IExternRef {
4616 ClassRef AddClass(string nsName, string name);
4617 ClassRef AddValueClass(string nsName, string name);
4621 /// A reference to an external assembly (.assembly extern)
4623 public class AssemblyRef : ResolutionScope, IExternRef {
4625 private ushort major, minor, build, revision;
4626 uint flags, keyIx, hashIx, cultIx;
4627 bool hasVersion = false, isKeyToken = false;
4631 internal AssemblyRef(MetaData md, string name) : base(name,md)
4633 tabIx = MDTable.AssemblyRef;
4636 public void AddAssemblyAttr (AssemAttr aa)
4642 /// Add version information about this external assembly
4644 /// <param name="majVer">Major Version</param>
4645 /// <param name="minVer">Minor Version</param>
4646 /// <param name="bldNo">Build Number</param>
4647 /// <param name="revNo">Revision Number</param>
4648 public void AddVersionInfo(int majVer, int minVer, int bldNo, int revNo)
4650 major = (ushort)majVer;
4651 minor = (ushort)minVer;
4652 build = (ushort)bldNo;
4653 revision = (ushort)revNo;
4658 /// Add the hash value for this external assembly
4660 /// <param name="hash">bytes of the hash value</param>
4661 public void AddHash(byte[] hash)
4663 hashIx = metaData.AddToBlobHeap(hash);
4667 /// Set the culture for this external assembly
4669 /// <param name="cult">the culture string</param>
4670 public void AddCulture(string cult)
4672 cultIx = metaData.AddToStringsHeap(cult);
4677 /// Add the full public key for this external assembly
4679 /// <param name="key">bytes of the public key</param>
4680 public void AddKey(byte[] key)
4682 flags |= 0x0001; // full public key
4684 keyIx = metaData.AddToBlobHeap(key);
4688 /// Add the public key token (low 8 bytes of the public key)
4690 /// <param name="key">low 8 bytes of public key</param>
4691 public void AddKeyToken(byte[] key)
4693 keyIx = metaData.AddToBlobHeap(key);
4699 /// Add a class to this external assembly
4701 /// <param name="nsName">name space name</param>
4702 /// <param name="name">class name</param>
4703 /// <returns></returns>
4704 public virtual ClassRef AddClass(string nsName, string name)
4706 ClassRef aClass = new ClassRef(nsName,name,metaData);
4707 metaData.AddToTable(MDTable.TypeRef,aClass);
4708 aClass.SetParent(this);
4713 /// Add a value class to this external assembly
4715 /// <param name="nsName">name space name</param>
4716 /// <param name="name">class name</param>
4717 /// <returns></returns>
4718 public virtual ClassRef AddValueClass(string nsName, string name)
4720 ClassRef aClass = new ClassRef(nsName,name,metaData);
4721 metaData.AddToTable(MDTable.TypeRef,aClass);
4722 aClass.SetParent(this);
4723 aClass.MakeValueClass(ValueClass.ValueType);
4727 internal string TypeName()
4729 string result = name;
4731 result = result + ", Version=" + major + "." + minor + "." +
4732 build + "." + revision;
4733 if (keyBytes != null) {
4734 string tokenStr = "=";
4735 if (isKeyToken) tokenStr = "Token=";
4736 result = result + ", PublicKey" + tokenStr;
4737 for (int i=0; i < keyBytes.Length; i++) {
4738 result = result + Hex.Byte(keyBytes[i]);
4741 if (culture != null)
4742 result = result + ", Culture=" + culture;
4746 internal sealed override uint Size(MetaData md)
4748 return 12 + 2 * md.StringsIndexSize() + 2 * md.BlobIndexSize();
4751 internal sealed override void Write(FileImage output)
4753 output.Write(major);
4754 output.Write(minor);
4755 output.Write(build);
4756 output.Write(revision);
4757 output.Write(flags);
4758 output.BlobIndex(keyIx);
4759 output.StringsIndex(nameIx);
4760 output.StringsIndex(cultIx);
4761 output.BlobIndex(hashIx);
4764 internal sealed override uint GetCodedIx(CIx code)
4767 case (CIx.ResolutionScope) : return 2;
4768 case (CIx.HasCustomAttr) : return 15;
4769 case (CIx.Implementation) : return 1;
4776 /**************************************************************************/
4778 /// Descriptor for a class defined in System (mscorlib)
4780 internal class SystemClass : ClassRef {
4782 PrimitiveType elemType;
4784 internal SystemClass(PrimitiveType eType, AssemblyRef paren, MetaData md)
4785 : base("System",eType.GetName(),md) {
4790 internal override sealed MetaDataElement GetTypeSpec(MetaData md)
4792 if (typeSpec == null) typeSpec = (TypeSpec)elemType.GetTypeSpec(md);
4797 internal sealed override void TypeSig(MemoryStream str)
4799 str.WriteByte(elemType.GetTypeIndex());
4804 /**************************************************************************/
4806 /// The assembly for mscorlib.
4808 public sealed class MSCorLib : AssemblyRef {
4810 private static readonly int valueTypeIx = 18;
4811 private readonly string systemName = "System";
4812 private Class[] systemClasses = new Class[valueTypeIx+2];
4813 private PrimitiveType[] systemTypes = new PrimitiveType[valueTypeIx];
4815 private static int[] specialNames = {
4816 PrimitiveType.Void.GetName().GetHashCode(),
4817 PrimitiveType.Boolean.GetName().GetHashCode(),
4818 PrimitiveType.Char.GetName().GetHashCode(),
4819 PrimitiveType.Int8.GetName().GetHashCode(),
4820 PrimitiveType.UInt8.GetName().GetHashCode(),
4821 PrimitiveType.Int16.GetName().GetHashCode(),
4822 PrimitiveType.UInt16.GetName().GetHashCode(),
4823 PrimitiveType.Int32.GetName().GetHashCode(),
4824 PrimitiveType.UInt32.GetName().GetHashCode(),
4825 PrimitiveType.Int64.GetName().GetHashCode(),
4826 PrimitiveType.UInt64.GetName().GetHashCode(),
4827 PrimitiveType.Float32.GetName().GetHashCode(),
4828 PrimitiveType.Float64.GetName().GetHashCode(),
4829 PrimitiveType.String.GetName().GetHashCode(),
4830 PrimitiveType.TypedRef.GetName().GetHashCode(),
4831 PrimitiveType.IntPtr.GetName().GetHashCode(),
4832 PrimitiveType.UIntPtr.GetName().GetHashCode(),
4833 PrimitiveType.Object.GetName().GetHashCode(),
4834 PrimitiveType.ValueType.GetName ().GetHashCode(),
4835 "Enum".GetHashCode()
4838 internal MSCorLib(MetaData md) : base(md,"mscorlib")
4840 if (!PEFile.IsMSCorlib)
4841 md.AddToTable(MDTable.AssemblyRef,this);
4842 systemTypes[PrimitiveType.Void.GetSystemTypeIx()] = PrimitiveType.Void;
4843 systemTypes[PrimitiveType.Boolean.GetSystemTypeIx()] = PrimitiveType.Boolean;
4844 systemTypes[PrimitiveType.Char.GetSystemTypeIx()] = PrimitiveType.Char;
4845 systemTypes[PrimitiveType.Int8.GetSystemTypeIx()] = PrimitiveType.Int8;
4846 systemTypes[PrimitiveType.UInt8.GetSystemTypeIx()] = PrimitiveType.UInt8;
4847 systemTypes[PrimitiveType.Int16.GetSystemTypeIx()] = PrimitiveType.Int16;
4848 systemTypes[PrimitiveType.UInt16.GetSystemTypeIx()] = PrimitiveType.UInt16;
4849 systemTypes[PrimitiveType.Int32.GetSystemTypeIx()] = PrimitiveType.Int32;
4850 systemTypes[PrimitiveType.UInt32.GetSystemTypeIx()] = PrimitiveType.UInt32;
4851 systemTypes[PrimitiveType.Int64.GetSystemTypeIx()] = PrimitiveType.Int64;
4852 systemTypes[PrimitiveType.UInt64.GetSystemTypeIx()] = PrimitiveType.UInt64;
4853 systemTypes[PrimitiveType.Float32.GetSystemTypeIx()] = PrimitiveType.Float32;
4854 systemTypes[PrimitiveType.Float64.GetSystemTypeIx()] = PrimitiveType.Float64;
4855 systemTypes[PrimitiveType.IntPtr.GetSystemTypeIx()] = PrimitiveType.IntPtr;
4856 systemTypes[PrimitiveType.UIntPtr.GetSystemTypeIx()] = PrimitiveType.UIntPtr;
4857 systemTypes[PrimitiveType.String.GetSystemTypeIx()] = PrimitiveType.String;
4858 systemTypes[PrimitiveType.Object.GetSystemTypeIx()] = PrimitiveType.Object;
4859 systemTypes[PrimitiveType.TypedRef.GetSystemTypeIx()] = PrimitiveType.TypedRef;
4863 /// Add a class to the mscorlib assembly
4865 /// <param name="nsName">name space name</param>
4866 /// <param name="name">class name</param>
4867 /// <returns></returns>
4868 public override ClassRef AddClass(string nsName, string name)
4870 /* This gets called by !mscorlib, for adding references INTO mscorlib, so
4871 it should be returning ClassRef ..*/
4872 Class aClass = GetSpecialClass(nsName,name);
4873 if (aClass == null) {
4874 aClass = new ClassRef(nsName,name,metaData);
4875 metaData.AddToTable(MDTable.TypeRef,aClass);
4876 if (aClass is ClassRef)
4877 ((ClassRef) aClass).SetParent(this);
4879 //FIXME: Check for !ClassRef here?
4880 return (ClassRef) aClass;
4883 private Class GetSpecialClass(string nsName,string name)
4885 if (nsName.CompareTo(systemName) != 0) return null;
4886 int hash = name.GetHashCode();
4887 for (int i=0; i < specialNames.Length; i++) {
4888 if (hash != specialNames[i])
4890 if (systemClasses[i] == null) {
4891 if (i < valueTypeIx) {
4892 systemClasses[i] = new SystemClass(systemTypes[i],this,metaData);
4893 if ((systemTypes[i] != PrimitiveType.Object) &&
4894 (systemTypes[i] != PrimitiveType.String)) {
4895 systemClasses[i].MakeValueClass(ValueClass.ValueType);
4898 systemClasses[i] = new ClassRef(nsName,name,metaData);
4899 ((ClassRef) systemClasses[i]).SetParent(this);
4900 if (!ClassDef.IsValueType (nsName, name) && !ClassDef.IsEnum (nsName, name))
4901 systemClasses[i].MakeValueClass(ValueClass.ValueType);
4903 metaData.AddToTable(MDTable.TypeRef,systemClasses[i]);
4905 return systemClasses[i];
4910 internal void SetSpecialSystemClass (string nsName, string name, Class aClass)
4912 if (nsName != systemName) return;
4913 int hash = name.GetHashCode ();
4914 for (int i = 0; i < specialNames.Length; i++) {
4915 if (hash != specialNames [i])
4917 if (systemClasses [i] == null) {
4918 systemClasses [i] = aClass;
4923 internal Class GetSpecialSystemClass(PrimitiveType pType)
4925 int ix = pType.GetSystemTypeIx();
4926 if (systemClasses[ix] == null && !PEFile.IsMSCorlib) {
4927 systemClasses[ix] = new SystemClass(pType,this,metaData);
4928 metaData.AddToTable(MDTable.TypeRef,systemClasses[ix]);
4930 return systemClasses[ix];
4933 private ClassRef GetValueClass(string name, int hash)
4935 /* Called by MSCorLib.AddValueClass, which is called by
4936 !mscorlib, for adding ref to value class INTO mscorlib,
4937 so this should be classref */
4938 int ix = valueTypeIx;
4939 if (hash != specialNames[valueTypeIx]) ix++;
4940 if (systemClasses[ix] == null) {
4941 systemClasses[ix] = new ClassRef(systemName,name,metaData);
4942 ((ClassRef) systemClasses[ix]).SetParent(this);
4943 ((ClassRef) systemClasses[ix]).MakeValueClass(ValueClass.ValueType);
4944 metaData.AddToTable(MDTable.TypeRef,systemClasses[ix]);
4946 return (ClassRef) systemClasses[ix];
4949 internal Class ValueType()
4951 if (systemClasses[valueTypeIx] == null && !PEFile.IsMSCorlib) {
4952 ClassRef valType = new ClassRef("System","ValueType",metaData);
4953 valType.SetParent(this);
4954 valType.MakeValueClass(ValueClass.ValueType);
4955 metaData.AddToTable(MDTable.TypeRef,valType);
4956 systemClasses[valueTypeIx] = valType;
4958 return systemClasses[valueTypeIx];
4961 internal Class EnumType()
4963 /* Called by both mscorlib & !mscorlib, so can be
4964 either ClassRef or ClassDef */
4965 //systemClasses [ valueTypeIx + 1] -> System.Enum
4966 if (systemClasses[valueTypeIx + 1] == null && !PEFile.IsMSCorlib) {
4967 ClassRef valType = new ClassRef("System","Enum",metaData);
4968 valType.SetParent(this);
4969 valType.MakeValueClass(ValueClass.Enum);
4970 metaData.AddToTable(MDTable.TypeRef,valType);
4971 systemClasses[valueTypeIx + 1] = valType;
4973 return systemClasses[valueTypeIx + 1];
4977 /// Add a value class to this external assembly
4979 /// <param name="nsName">name space name</param>
4980 /// <param name="name">class name</param>
4981 /// <returns></returns>
4982 public override ClassRef AddValueClass(string nsName, string name)
4984 if (nsName.CompareTo(systemName) == 0) {
4985 int hash = name.GetHashCode();
4986 if ((hash == specialNames[valueTypeIx]) ||
4987 (hash == specialNames[valueTypeIx+1])) {
4988 return GetValueClass(name,hash);
4991 ClassRef aClass = new ClassRef(nsName,name,metaData);
4992 metaData.AddToTable(MDTable.TypeRef,aClass);
4993 aClass.SetParent(this);
4994 aClass.MakeValueClass(ValueClass.ValueType);
5000 /**************************************************************************/
5003 /// Root (20 bytes + UTF-8 Version String + quad align padding)
5004 /// StreamHeaders (8 bytes + null terminated name string + quad align padding)
5006 /// #~ (always present - holds metadata tables)
5007 /// #Strings (always present - holds identifier strings)
5008 /// #US (Userstring heap)
5009 /// #Blob (signature blobs)
5010 /// #GUID (guids for assemblies or Modules)
5012 public class MetaData {
5014 internal static readonly int[] CIxShiftMap = {2,2,5,1,2,3,1,1,1,2,3,2,1};
5015 private static readonly byte StringsHeapMask = 0x1;
5016 private static readonly byte GUIDHeapMask = 0x2;
5017 private static readonly byte BlobHeapMask = 0x4;
5018 private static readonly uint MetaDataSignature = 0x424A5342;
5019 private static readonly uint maxSmlIxSize = 0xFFFF;
5020 private static readonly uint max1BitSmlIx = 0x7FFF;
5021 private static readonly uint max2BitSmlIx = 0x3FFF;
5022 private static readonly uint max3BitSmlIx = 0x1FFF;
5023 private static readonly uint max5BitSmlIx = 0x7FF;
5024 // NOTE: version and stream name strings MUST always be quad padded
5025 private static readonly string version = "v4.0.30319\0\0";
5026 private static readonly char[] tildeName = {'#','~','\0','\0'};
5027 private static readonly char[] stringsName = {'#','S','t','r','i','n','g','s','\0','\0','\0','\0'};
5028 private static readonly char[] usName = {'#','U','S','\0'};
5029 private static readonly char[] guidName = {'#','G','U','I','D','\0','\0','\0'};
5030 private static readonly char[] blobName = {'#','B','l','o','b','\0','\0','\0'};
5031 private static readonly uint MetaDataHeaderSize = 20 + (uint)version.Length;
5032 private static readonly uint TildeHeaderSize = 24;
5033 private static readonly uint StreamHeaderSize = 8;
5034 private static readonly uint numMetaDataTables = (int)MDTable.GenericParamConstraint + 1;
5036 MetaDataStream strings, us, guid, blob;
5038 MetaDataStream[] streams = new MetaDataStream[5];
5039 uint numStreams = 5;
5040 uint tildeTide = 0, tildePadding = 0, tildeStart = 0;
5041 uint numTables = 0, resourcesSize = 0;
5042 ArrayList[] metaDataTables = new ArrayList[numMetaDataTables];
5043 ArrayList byteCodes = new ArrayList();
5044 uint codeSize = 0, codeStart, byteCodePadding = 0, metaDataSize = 0;
5045 ulong valid = 0, /*sorted = 0x000002003301FA00;*/ sorted = 0;
5046 bool[] largeIx = new bool[numMetaDataTables];
5047 bool[] lgeCIx = new bool[(int)CIx.MaxCIx];
5048 bool largeStrings = false, largeUS = false, largeGUID = false, largeBlob = false;
5049 private FileImage file;
5050 private byte heapSizes = 0;
5051 MetaDataElement entryPoint;
5052 BinaryWriter output;
5053 public MSCorLib mscorlib;
5054 private TypeSpec[] systemTypeSpecs = new TypeSpec[PrimitiveType.NumSystemTypes];
5056 private ArrayList cattr_list;
5057 private ArrayList declsec_list;
5058 ArrayList resources;
5060 internal MetaData(FileImage file)
5062 // tilde = new MetaDataStream(tildeName,false,0);
5064 strings = new MetaDataStream(stringsName,new UTF8Encoding(),true);
5065 us = new MetaDataStream(usName,new UnicodeEncoding(),true);
5066 guid = new MetaDataStream(guidName,false);
5067 blob = new MetaDataStream(blobName,true);
5068 streams[1] = strings;
5072 for (int i=0; i < numMetaDataTables; i++) {
5075 for (int i=0; i < lgeCIx.Length; i++) {
5078 mscorlib = new MSCorLib(this);
5081 internal TypeSpec GetPrimitiveTypeSpec(int ix)
5083 return systemTypeSpecs[ix];
5086 internal void SetPrimitiveTypeSpec(int ix, TypeSpec typeSpec)
5088 systemTypeSpecs[ix] = typeSpec;
5091 internal uint Size()
5093 return metaDataSize;
5096 private void CalcHeapSizes ()
5098 if (strings.LargeIx()) {
5099 largeStrings = true;
5100 heapSizes |= StringsHeapMask;
5102 if (guid.LargeIx()) {
5104 heapSizes |= GUIDHeapMask;
5106 if (blob.LargeIx()) {
5108 heapSizes |= BlobHeapMask;
5111 largeUS = us.LargeIx();
5114 internal void StreamSize(byte mask)
5119 internal uint AddToUSHeap(string str)
5121 if (str == null) return 0;
5122 return us.Add(str,true);
5125 internal uint AddToUSHeap(byte[] str)
5127 if (str == null) return 0;
5128 return us.Add (str, true);
5131 internal uint AddToStringsHeap(string str)
5133 if ((str == null) || (str.CompareTo("") == 0)) return 0;
5134 return strings.Add(str,false);
5137 internal uint AddToGUIDHeap(Guid guidNum)
5139 return guid.Add(guidNum, false);
5142 internal uint AddToBlobHeap(byte[] blobBytes)
5144 if (blobBytes == null) return 0;
5145 return blob.Add(blobBytes, true);
5148 internal uint AddToBlobHeap(byte val)
5150 return blob.Add(val, true);
5153 internal uint AddToBlobHeap(sbyte val)
5155 return blob.Add(val, true);
5158 internal uint AddToBlobHeap(ushort val)
5160 return blob.Add(val, true);
5163 internal uint AddToBlobHeap(short val)
5165 return blob.Add(val, true);
5168 internal uint AddToBlobHeap(uint val)
5170 return blob.Add(val, true);
5173 internal uint AddToBlobHeap(int val)
5175 return blob.Add(val, true);
5178 internal uint AddToBlobHeap(ulong val)
5180 return blob.Add(val, true);
5183 internal uint AddToBlobHeap(long val)
5185 return blob.Add(val, true);
5188 internal uint AddToBlobHeap(float val)
5190 return blob.Add(val, true);
5193 internal uint AddToBlobHeap(double val)
5195 return blob.Add(val, true);
5198 internal uint AddToBlobHeap(string val)
5200 return blob.Add(val,true);
5203 internal void AddCustomAttribute (CustomAttribute cattr)
5205 if (cattr_list == null)
5206 cattr_list = new ArrayList ();
5207 cattr_list.Add (cattr);
5210 internal void AddDeclSecurity (BaseDeclSecurity decl_sec)
5212 if (declsec_list == null)
5213 declsec_list = new ArrayList ();
5214 declsec_list.Add (decl_sec);
5217 private ArrayList GetTable(MDTable tableIx)
5219 int tabIx = (int)tableIx;
5220 if (metaDataTables[tabIx] == null) {
5221 metaDataTables[tabIx] = new ArrayList();
5222 valid |= ((ulong)0x1 << tabIx);
5223 // Console.WriteLine("after creating table " + tableIx + "(" + tabIx + ") valid = " + valid);
5226 return metaDataTables[tabIx];
5229 internal void AddToTable(MDTable tableIx, MetaDataElement elem)
5232 // Console.Out.WriteLine("ERROR - element already in table " + tableIx);
5235 // updates Row field of the element
5236 // Console.WriteLine("Adding element to table " + (uint)tableIx);
5237 ArrayList table = GetTable(tableIx);
5238 elem.Row = (uint)table.Count + 1;
5242 internal uint TableIndex(MDTable tableIx)
5244 if (metaDataTables[(int)tableIx] == null) return 1;
5245 return (uint)metaDataTables[(int)tableIx].Count+1;
5248 internal uint AddCode(CILInstructions byteCode)
5250 byteCodes.Add(byteCode);
5251 uint offset = codeSize + codeStart;
5252 codeSize += byteCode.GetCodeSize();
5256 internal void SetEntryPoint(MetaDataElement ep)
5261 internal uint AddResource(byte[] resBytes)
5263 if (resources == null) resources = new ArrayList ();
5264 resources.Add (resBytes);
5265 uint offset = resourcesSize;
5266 resourcesSize += (uint)resBytes.Length + 4;
5270 internal void AddData(DataConstant cVal)
5272 file.AddInitData(cVal);
5275 internal static void CompressNum(uint val, MemoryStream sig)
5278 sig.WriteByte((byte)val);
5279 } else if (val <= 0x3FFF) {
5280 byte b1 = (byte)((val >> 8) | 0x80);
5281 byte b2 = (byte)(val & FileImage.iByteMask[0]);
5285 byte b1 = (byte)((val >> 24) | 0xC0);
5286 byte b2 = (byte)((val & FileImage.iByteMask[2]) >> 16);
5287 byte b3 = (byte)((val & FileImage.iByteMask[1]) >> 8);;
5288 byte b4 = (byte)(val & FileImage.iByteMask[0]);
5296 internal uint CodeSize()
5298 return codeSize + byteCodePadding;
5301 internal uint GetResourcesSize()
5303 return resourcesSize;
5306 internal uint StringsIndexSize()
5308 if (largeStrings) return 4;
5312 internal uint GUIDIndexSize()
5314 if (largeGUID) return 4;
5318 internal uint USIndexSize()
5320 if (largeUS) return 4;
5324 internal uint BlobIndexSize()
5326 if (largeBlob) return 4;
5330 internal uint CodedIndexSize(CIx code)
5332 if (lgeCIx[(uint)code]) return 4;
5336 internal uint TableIndexSize(MDTable tabIx)
5338 if (largeIx[(uint)tabIx]) return 4;
5342 private void SetIndexSizes()
5344 for (int i=0; i < numMetaDataTables; i++) {
5345 if (metaDataTables[i] == null)
5348 uint count = (uint)metaDataTables[i].Count;
5349 if (count > maxSmlIxSize)
5352 MDTable tabIx = (MDTable)i;
5353 if (count > max5BitSmlIx) {
5354 if (tabIx == MDTable.Method || tabIx == MDTable.Field || tabIx == MDTable.TypeRef ||
5355 tabIx == MDTable.TypeDef || tabIx == MDTable.Param || tabIx == MDTable.InterfaceImpl ||
5356 tabIx == MDTable.MemberRef || tabIx == MDTable.Module || tabIx == MDTable.DeclSecurity ||
5357 tabIx == MDTable.Property || tabIx == MDTable.Event || tabIx == MDTable.StandAloneSig ||
5358 tabIx == MDTable.ModuleRef || tabIx == MDTable.TypeSpec || tabIx == MDTable.Assembly ||
5359 tabIx == MDTable.AssemblyRef || tabIx == MDTable.File || tabIx == MDTable.ExportedType ||
5360 tabIx == MDTable.ManifestResource || tabIx == MDTable.GenericParam)
5361 lgeCIx[(int)CIx.HasCustomAttr] = true;
5363 if (count > max3BitSmlIx) {
5364 if (tabIx == MDTable.Method || tabIx == MDTable.MemberRef)
5365 lgeCIx[(int)CIx.CustomAttributeType] = true;
5366 if (tabIx == MDTable.TypeDef || tabIx == MDTable.TypeRef || tabIx == MDTable.ModuleRef ||
5367 tabIx == MDTable.Method || tabIx == MDTable.TypeSpec)
5368 lgeCIx[(int)CIx.MemberRefParent] = true;
5370 if (count > max2BitSmlIx) {
5371 if ((tabIx == MDTable.Field) || (tabIx == MDTable.Param) || (tabIx == MDTable.Property))
5372 lgeCIx[(int)CIx.HasConst] = true;
5373 if ((tabIx == MDTable.TypeDef) || (tabIx == MDTable.TypeRef) || (tabIx == MDTable.TypeSpec))
5374 lgeCIx[(int)CIx.TypeDefOrRef] = true;
5375 if ((tabIx == MDTable.TypeDef) || (tabIx == MDTable.Method) || (tabIx == MDTable.Assembly))
5376 lgeCIx[(int)CIx.HasDeclSecurity] = true;
5377 if ((tabIx == MDTable.File) || (tabIx == MDTable.AssemblyRef) || (tabIx == MDTable.ExportedType))
5378 lgeCIx[(int)CIx.Implementation] = true;
5379 if ((tabIx == MDTable.Module) || (tabIx == MDTable.ModuleRef) || (tabIx == MDTable.AssemblyRef) || (tabIx == MDTable.TypeRef))
5380 lgeCIx[(int)CIx.ResolutionScope] = true;
5382 if (count > max1BitSmlIx) {
5383 if ((tabIx == MDTable.Field) || (tabIx == MDTable.Param))
5384 lgeCIx[(int)CIx.HasFieldMarshal] = true;
5385 if ((tabIx == MDTable.Event) || (tabIx == MDTable.Property))
5386 lgeCIx[(int)CIx.HasSemantics] = true;
5387 if ((tabIx == MDTable.Method) || (tabIx == MDTable.MemberRef))
5388 lgeCIx[(int)CIx.MethodDefOrRef] = true;
5389 if ((tabIx == MDTable.Field) || (tabIx == MDTable.Method))
5390 lgeCIx[(int)CIx.MemberForwarded] = true;
5391 if ((tabIx == MDTable.TypeDef) || (tabIx == MDTable.Method))
5392 lgeCIx[(int)CIx.TypeOrMethodDef] = true;
5397 private void SetStreamOffsets()
5399 uint sizeOfHeaders = StreamHeaderSize + (uint)tildeName.Length;
5400 for (int i=1; i < numStreams; i++) {
5401 sizeOfHeaders += streams[i].headerSize();
5403 metaDataSize = MetaDataHeaderSize + sizeOfHeaders;
5404 tildeStart = metaDataSize;
5405 metaDataSize += tildeTide + tildePadding;
5406 for (int i=1; i < numStreams; i++) {
5407 streams[i].Start = metaDataSize;
5408 metaDataSize += streams[i].Size();
5409 streams[i].WriteDetails();
5413 internal void CalcTildeStreamSize()
5416 //tilde.SetIndexSizes(strings.LargeIx(),us.LargeIx(),guid.LargeIx(),blob.LargeIx());
5417 tildeTide = TildeHeaderSize;
5418 tildeTide += 4 * numTables;
5419 //Console.WriteLine("Tilde header + sizes = " + tildeTide);
5420 for (int i=0; i < numMetaDataTables; i++) {
5421 if (metaDataTables[i] != null) {
5422 ArrayList table = metaDataTables[i];
5423 // Console.WriteLine("Meta data table " + i + " at offset " + tildeTide);
5424 tildeTide += (uint)table.Count * ((MetaDataElement)table[0]).Size(this);
5425 // Console.WriteLine("Metadata table " + i + " has size " + table.Count);
5426 // Console.WriteLine("tildeTide = " + tildeTide);
5429 if ((tildeTide % 4) != 0) tildePadding = 4 - (tildeTide % 4);
5430 //Console.WriteLine("tildePadding = " + tildePadding);
5433 internal void WriteTildeStream(FileImage output)
5435 output.Seek(0,SeekOrigin.Current);
5436 output.Write((uint)0); // Reserved
5437 output.Write((byte)2); // MajorVersion
5438 output.Write((byte)0); // MinorVersion
5439 output.Write(heapSizes);
5440 output.Write((byte)1); // Reserved
5441 output.Write(valid);
5442 output.Write(sorted);
5444 for (int i=0; i < numMetaDataTables; i++) {
5445 if (metaDataTables[i] != null) {
5446 uint count = (uint)metaDataTables[i].Count;
5447 output.Write(count);
5451 output.Seek(0,SeekOrigin.Current);
5452 // Console.WriteLine("Starting metaData tables at " + tabStart);
5453 for (int i=0; i < numMetaDataTables; i++) {
5454 if (metaDataTables[i] != null) {
5455 // Console.WriteLine("Starting metaData table " + i + " at " + (output.Seek(0,SeekOrigin.Current) - startTilde));
5456 ArrayList table = metaDataTables[i];
5457 for (int j=0; j < table.Count; j++) {
5458 ((MetaDataElement)table[j]).Write(output);
5462 // Console.WriteLine("Writing padding at " + output.Seek(0,SeekOrigin.Current));
5463 for (int i=0; i < tildePadding; i++) output.Write((byte)0);
5466 private void BuildTable(ArrayList table)
5468 if (table == null) return;
5469 for (int j=0; j < table.Count; j++) {
5470 ((MetaDataElement)table[j]).BuildTables(this);
5474 private void SortTable (ArrayList mTable)
5476 if (mTable == null) return;
5478 for (int i=0; i < mTable.Count; i++) {
5479 ((MetaDataElement)mTable[i]).Row = (uint)i+1;
5483 internal void BuildMetaData(uint codeStartOffset)
5485 codeStart = codeStartOffset;
5486 BuildTable(metaDataTables[(int)MDTable.TypeDef]);
5487 BuildTable(metaDataTables[(int)MDTable.TypeSpec]);
5488 BuildTable(metaDataTables[(int)MDTable.MemberRef]);
5489 BuildTable(metaDataTables[(int)MDTable.GenericParam]);
5490 BuildTable(metaDataTables[(int)MDTable.MethodSpec]);
5491 BuildTable(metaDataTables[(int)MDTable.GenericParamConstraint]);
5492 BuildTable(metaDataTables[(int)MDTable.ManifestResource]);
5494 if (cattr_list != null) {
5495 foreach (CustomAttribute cattr in cattr_list)
5496 cattr.BuildTables (this);
5499 if (declsec_list != null) {
5500 foreach (BaseDeclSecurity decl_sec in declsec_list)
5501 decl_sec.BuildTables (this);
5504 /* for (int i=0; i < metaDataTables.Length; i++) {
5505 ArrayList table = metaDataTables[i];
5506 if (table != null) {
5507 for (int j=0; j < table.Count; j++) {
5508 ((MetaDataElement)table[j]).BuildTables(this);
5515 for (int i=1; i < numStreams; i++) {
5516 streams[i].EndStream();
5518 CalcTildeStreamSize();
5520 byteCodePadding = NumToAlign(codeSize,4);
5521 if (entryPoint != null) file.SetEntryPoint(entryPoint.Token());
5523 // Check ordering of specific tables
5524 // Constant, CustomAttribute, FieldMarshal, DeclSecurity, MethodSemantics
5525 // ImplMap, GenericParam
5526 // Need to load GenericParamConstraint AFTER GenericParam table in correct order
5528 // InterfaceImpl, ClassLayout, FieldLayout, MethodImpl, FieldRVA, NestedClass
5529 // will _ALWAYS_ be in the correct order as embedded in BuildMDTables
5531 SortTable(metaDataTables[(int)MDTable.Constant]);
5532 SortTable(metaDataTables[(int)MDTable.FieldMarshal]);
5533 SortTable(metaDataTables[(int)MDTable.DeclSecurity]);
5534 SortTable(metaDataTables[(int)MDTable.MethodSemantics]);
5535 SortTable(metaDataTables[(int)MDTable.ImplMap]);
5536 if (metaDataTables[(int)MDTable.GenericParam] != null) {
5537 SortTable(metaDataTables[(int)MDTable.GenericParam]);
5538 // Now add GenericParamConstraints
5539 /*for (int i=0; i < metaDataTables[(int)MDTable.GenericParam].Count; i++) {
5540 ((GenericParameter)metaDataTables[(int)MDTable.GenericParam][i]).AddConstraints(this);
5543 SortTable(metaDataTables[(int)MDTable.GenericParamConstraint]);
5544 SortTable(metaDataTables[(int)MDTable.InterfaceImpl]);
5545 SortTable(metaDataTables[(int)MDTable.CustomAttribute]);
5549 internal void WriteByteCodes(FileImage output)
5551 for (int i=0; i < byteCodes.Count; i++) {
5552 ((CILInstructions)byteCodes[i]).Write(output);
5554 for (int i=0; i < byteCodePadding; i++) {
5555 output.Write((byte)0);
5559 internal void WriteResources (FileImage output)
5561 if (resources == null) return;
5562 for (int i = 0; i < resources.Count; i ++) {
5563 byte [] resBytes = (byte []) resources [i];
5564 output.Write ((uint) resBytes.Length);
5565 output.Write (resBytes);
5569 internal void WriteMetaData(FileImage output)
5571 this.output = output;
5572 mdStart = output.Seek(0,SeekOrigin.Current);
5573 // Console.WriteLine("Writing metaData at " + Hex.Long(mdStart));
5574 output.Write(MetaDataSignature);
5575 output.Write((short)1); // Major Version
5576 output.Write((short)1); // Minor Version ECMA = 0, PEFiles = 1
5577 output.Write(0); // Reserved
5578 output.Write(version.Length);
5579 output.Write(version.ToCharArray()); // version string is already zero padded
5580 output.Write((short)0);
5581 output.Write((ushort)numStreams);
5582 // write tilde header
5583 output.Write(tildeStart);
5584 output.Write(tildeTide + tildePadding);
5585 output.Write(tildeName);
5586 for (int i=1; i < numStreams; i++) streams[i].WriteHeader(output);
5587 // Console.WriteLine("Writing tilde stream at " + output.Seek(0,SeekOrigin.Current) + " = " + tildeStart);
5588 WriteTildeStream(output);
5589 for (int i=1; i < numStreams; i++) streams[i].Write(output);
5590 // Console.WriteLine("Finished Writing metaData at " + output.Seek(0,SeekOrigin.Current));
5593 internal bool LargeStringsIndex() { return strings.LargeIx(); }
5594 internal bool LargeGUIDIndex() { return guid.LargeIx(); }
5595 internal bool LargeUSIndex() { return us.LargeIx(); }
5596 internal bool LargeBlobIndex() { return blob.LargeIx(); }
5598 internal bool LargeIx(MDTable tabIx) { return largeIx[(uint)tabIx]; }
5601 private uint NumToAlign(uint val, uint alignVal)
5603 if ((val % alignVal) == 0) return 0;
5604 return alignVal - (val % alignVal);
5607 internal void WriteCodedIndex(CIx code, MetaDataElement elem, FileImage output)
5611 ix = (elem.Row << CIxShiftMap[(uint)code]) | elem.GetCodedIx(code);
5612 // Console.WriteLine("coded index = " + ix + " row = " + elem.Row);
5614 // Console.WriteLine("elem for coded index is null");
5616 if (lgeCIx[(uint)code])
5619 output.Write((ushort)ix);
5624 /**************************************************************************/
5626 /// Stream in the Meta Data (#Strings, #US, #Blob and #GUID)
5629 internal class MetaDataStream : BinaryWriter {
5631 private static readonly uint StreamHeaderSize = 8;
5632 private static uint maxSmlIxSize = 0xFFFF;
5634 private uint start = 0;
5635 uint size = 0, tide = 1;
5636 bool largeIx = false;
5639 Hashtable htable = new Hashtable();
5640 Hashtable btable = new Hashtable (new ByteArrayHashCodeProvider (), new ByteArrayComparer ());
5642 internal MetaDataStream(char[] name, bool addInitByte) : base(new MemoryStream())
5644 if (addInitByte) { Write((byte)0); size = 1; }
5646 sizeOfHeader = StreamHeaderSize + (uint)name.Length;
5649 internal MetaDataStream(char[] name, System.Text.Encoding enc, bool addInitByte) : base(new MemoryStream(),enc)
5651 if (addInitByte) { Write((byte)0); size = 1; }
5653 sizeOfHeader = StreamHeaderSize + (uint)name.Length;
5657 get { return start; }
5658 set { start = value; }
5661 internal uint headerSize()
5663 // Console.WriteLine(name + " stream has headersize of " + sizeOfHeader);
5664 return sizeOfHeader;
5667 internal void SetSize(uint siz)
5672 internal uint Size()
5677 internal bool LargeIx()
5682 internal void WriteDetails()
5684 // Console.WriteLine(name + " - size = " + size);
5687 internal uint Add(string str, bool prependSize)
5689 Object val = htable[str];
5693 htable[str] = index;
5694 char[] arr = str.ToCharArray();
5695 if (prependSize) CompressNum((uint)arr.Length*2+1);
5698 size = (uint)Seek(0,SeekOrigin.Current);
5704 internal uint Add (byte[] str, bool prependSize)
5706 Object val = btable [str];
5710 btable [str] = index;
5711 if (prependSize) CompressNum ((uint) str.Length);
5713 size = (uint) Seek (0, SeekOrigin.Current);
5721 internal uint Add(Guid guid, bool prependSize)
5723 byte [] b = guid.ToByteArray ();
5724 if (prependSize) CompressNum ((uint) b.Length);
5725 Write(guid.ToByteArray());
5726 size =(uint)Seek(0,SeekOrigin.Current);
5730 internal uint Add(byte[] blob)
5733 CompressNum((uint)blob.Length);
5735 size = (uint)Seek(0,SeekOrigin.Current);
5739 internal uint Add(byte val, bool prependSize)
5742 if (prependSize) CompressNum (1);
5744 size = (uint)Seek(0,SeekOrigin.Current);
5748 internal uint Add(sbyte val, bool prependSize)
5751 if (prependSize) CompressNum (1);
5753 size = (uint)Seek(0,SeekOrigin.Current);
5757 internal uint Add(ushort val, bool prependSize)
5760 if (prependSize) CompressNum (2);
5762 size = (uint)Seek(0,SeekOrigin.Current);
5766 internal uint Add(short val, bool prependSize)
5769 if (prependSize) CompressNum (2);
5771 size = (uint)Seek(0,SeekOrigin.Current);
5775 internal uint Add(uint val, bool prependSize)
5778 if (prependSize) CompressNum (4);
5780 size = (uint)Seek(0,SeekOrigin.Current);
5784 internal uint Add(int val, bool prependSize)
5787 if (prependSize) CompressNum (4);
5789 size = (uint)Seek(0,SeekOrigin.Current);
5793 internal uint Add(ulong val, bool prependSize)
5796 if (prependSize) CompressNum (8);
5798 size = (uint)Seek(0,SeekOrigin.Current);
5802 internal uint Add(long val, bool prependSize)
5805 if (prependSize) CompressNum (8);
5807 size = (uint)Seek(0,SeekOrigin.Current);
5811 internal uint Add(float val, bool prependSize)
5814 if (prependSize) CompressNum (4);
5816 size = (uint)Seek(0,SeekOrigin.Current);
5820 internal uint Add(double val, bool prependSize)
5823 if (prependSize) CompressNum (8);
5825 size = (uint)Seek(0,SeekOrigin.Current);
5829 private void CompressNum(uint val)
5833 } else if (val < 0x3FFF) {
5834 byte b1 = (byte)((val >> 8) | 0x80);
5835 byte b2 = (byte)(val & FileImage.iByteMask[0]);
5839 byte b1 = (byte)((val >> 24) | 0xC0);
5840 byte b2 = (byte)((val & FileImage.iByteMask[2]) >> 16);
5841 byte b3 = (byte)((val & FileImage.iByteMask[1]) >> 8);;
5842 byte b4 = (byte)(val & FileImage.iByteMask[0]);
5850 private void QuadAlign()
5852 if ((size % 4) != 0) {
5853 uint pad = 4 - (size % 4);
5855 for (int i=0; i < pad; i++) {
5861 internal void EndStream()
5864 if (size > maxSmlIxSize) {
5869 internal void WriteHeader(BinaryWriter output)
5871 output.Write(start);
5876 internal virtual void Write(BinaryWriter output)
5878 // Console.WriteLine("Writing " + name + " stream at " + output.Seek(0,SeekOrigin.Current) + " = " + start);
5879 MemoryStream str = (MemoryStream)BaseStream;
5880 output.Write(str.ToArray());
5885 /**************************************************************************/
5886 class ByteArrayComparer : IComparer {
5888 public int Compare (object x, object y)
5890 byte [] a = (byte []) x;
5891 byte [] b = (byte []) y;
5894 if (b.Length != len)
5897 for (int i = 0; i < len; ++i)
5904 class ByteArrayHashCodeProvider : IHashCodeProvider {
5906 public int GetHashCode (Object key)
5908 byte [] arr = (byte []) key;
5909 int len = arr.Length;
5912 for (int i = 0; i < len; ++i)
5913 h = (h << 5) - h + arr [i];