3 using System.Collections;
5 using System.Reflection;
12 /// flags for the assembly (.corflags)
14 public enum CorFlags {CF_IL_ONLY = 1, CF_32_BITREQUIRED = 2,
15 CF_STRONGNAMESIGNED = 8, CF_TRACKDEBUGDATA = 0x10000 }
18 /// subsystem for the assembly (.subsystem)
20 public enum SubSystem { Native = 1, Windows_GUI = 2,
21 Windows_CUI = 3, OS2_CUI = 5, POSIX_CUI = 7, Native_Windows = 8,
25 /// Hash algorithms for the assembly
27 public enum HashAlgorithm { None, SHA1 }
30 /// Attributes for this assembly
32 public enum AssemAttr { Retargetable = 0x100, EnableJITCompileTracking = 0x8000,
33 DisableJITCompileOptimizer = 0x4000}
36 /// Method call conventions
39 public enum CallConv { Default, Cdecl, Stdcall, Thiscall,
40 Fastcall, Vararg, Instance = 0x20, Generic = 0x10, InstanceExplicit = 0x60 }
43 /// Type custom modifier
45 public enum CustomModifier { modreq = 0x1F, modopt };
48 /// Attibutes for a class
51 public enum TypeAttr {Private, Public, NestedPublic, NestedPrivate,
52 NestedFamily, NestedAssembly, NestedFamAndAssem, NestedFamOrAssem,
53 SequentialLayout, ExplicitLayout = 0x10, Interface = 0x20,
54 Abstract = 0x80, PublicAbstract = 0x81, Sealed = 0x100,
55 PublicSealed = 0x101, SpecialName = 0x400, RTSpecialName = 0x800,
56 Import = 0x1000, Serializable = 0x2000, UnicodeClass = 0x10000,
57 AutoClass = 0x20000, HasSecurity = 0x40000, BeforeFieldInit = 0x100000,
59 VisibilityMask = 0x07 }
62 /// Attributes for a field
64 public enum FieldAttr {Default, Private, FamAndAssem, Assembly,
65 Family, FamOrAssem, Public, Static = 0x10, PublicStatic = 0x16,
66 Initonly = 0x20, Literal = 0x40, Notserialized = 0x80,
67 SpecialName = 0x200, RTSpecialName = 0x400, HasFieldMarshal = 0x1000 }
70 /// Attributes for a method
72 public enum MethAttr { Default, Private, FamAndAssem, Assembly,
73 Family, FamOrAssem, Public, Static = 0x0010, PublicStatic = 0x16,
74 Final = 0x0020, PublicStaticFinal = 0x36, Virtual = 0x0040,
75 PrivateVirtual, PublicVirtual = 0x0046, HideBySig = 0x0080,
76 NewSlot = 0x0100, Strict = 0x200, Abstract = 0x0400, SpecialName = 0x0800,
77 RTSpecialName = 0x1000, SpecialRTSpecialName = 0x1800,
78 HasSecurity = 0x4000, RequireSecObject = 0x8000}
81 /// Attributes for .pinvokeimpl method declarations
83 public enum PInvokeAttr { nomangle = 1, ansi = 2, unicode = 4, autochar = 6,
84 bestfit_on = 0x0010, bestfit_off = 0x0020, bestfit_mask = 0x0030,
85 lasterr = 0x0040, winapi = 0x0100, cdecl = 0x0200,
86 stdcall = 0x0300, thiscall = 0x0400, fastcall = 0x0500,
87 charmaperror_on = 0x1000, charmaperror_off = 0x2000
91 /// Implementation attributes for a method
93 public enum ImplAttr { IL, Native, Runtime = 0x03, Unmanaged = 0x04,
94 ForwardRef = 0x10, PreserveSig = 0x0080, InternalCall = 0x1000,
95 Synchronised = 0x0020, Synchronized = 0x0020, NoInLining = 0x0008, Optil = 0x0002}
98 /// Modes for a parameter
100 public enum ParamAttr { Default, In, Out, Opt = 16, HasDefault = 0x1000, HasFieldMarshal = 0x2000 }
105 public enum Op { nop, breakOp, ldarg_0, ldarg_1, ldarg_2, ldarg_3,
106 ldloc_0, ldloc_1, ldloc_2, ldloc_3, stloc_0, stloc_1, stloc_2, stloc_3,
107 ldnull = 0x14, ldc_i4_m1, ldc_i4_0, ldc_i4_1, ldc_i4_2, ldc_i4_3,
108 ldc_i4_4, ldc_i4_5, ldc_i4_6, ldc_i4_7, ldc_i4_8, dup = 0x25, pop,
109 ret = 0x2A, ldind_i1 = 0x46, ldind_u1, ldind_i2, ldind_u2, ldind_i4,
110 ldind_u4, ldind_i8, ldind_i, ldind_r4, ldind_r8, ldind_ref, stind_ref,
111 stind_i1, stind_i2, stind_i4, stind_i8, stind_r4, stind_r8, add, sub, mul,
112 div, div_un, rem, rem_un, and, or, xor, shl, shr, shr_un, neg, not,
113 conv_i1, conv_i2, conv_i4, conv_i8, conv_r4, conv_r8, conv_u4, conv_u8,
114 conv_r_un = 0x76, throwOp = 0x7A, conv_ovf_i1_un = 0x82, conv_ovf_i2_un,
115 conv_ovf_i4_un, conv_ovf_i8_un, conf_ovf_u1_un, conv_ovf_u2_un,
116 conv_ovf_u4_un, conv_ovf_u8_un, conv_ovf_i_un, conv_ovf_u_un,
117 ldlen = 0x8E, ldelem_i1 = 0x90, ldelem_u1, ldelem_i2, ldelem_u2,
118 ldelem_i4, ldelem_u4, ldelem_i8, ldelem_i, ldelem_r4, ldelem_r8,
119 ldelem_ref, stelem_i, stelem_i1, stelem_i2, stelem_i4, stelem_i8, stelem_r4 = 0xA0, stelem_r8,
120 stelem_ref, conv_ovf_i1 = 0xb3, conv_ovf_u1, conv_ovf_i2, conv_ovf_u2,
121 conv_ovf_i4, conv_ovf_u4, conv_ovf_i8, conv_ovf_u8, ckfinite = 0xC3,
122 conv_u2 = 0xD1, conv_u1, conv_i, conv_ovf_i, conv_ovf_u, add_ovf,
123 add_ovf_un, mul_ovf, mul_ovf_un, sub_ovf, sub_ovf_un, endfinally,
124 stind_i = 0xDF, conv_u, arglist = 0xFE00, ceq, cgt, cgt_un, clt, clt_un,
125 localloc = 0xFE0F, endfilter = 0xFE11, volatile_ = 0xFE13, tail_,
126 cpblk = 0xFE17, initblk, rethrow = 0xFE1A, refanytype = 0xFE1D, readonly_ = 0xFE1E }
129 /// CIL instructions requiring an integer parameter
131 public enum IntOp {ldarg_s = 0x0E, ldarga_s, starg_s, ldloc_s, ldloca_s,
132 stloc_s, ldc_i4_s = 0x1F, ldc_i4, ldarg = 0xFE09,
133 ldarga, starg, ldloc, ldloca, stloc, unaligned = 0xFE12 }
136 /// CIL instructions requiring a field parameter
138 public enum FieldOp {ldfld = 0x7B, ldflda, stfld, ldsfld, ldsflda,
139 stsfld, ldtoken = 0xD0 }
142 /// CIL instructions requiring a method parameter
144 public enum MethodOp {jmp = 0x27, call, callvirt = 0x6F, newobj = 0x73,
145 ldtoken = 0xD0, ldftn = 0xFE06, ldvirtfn }
148 /// CIL instructions requiring a type parameter
150 public enum TypeOp {cpobj = 0x70, ldobj, castclass = 0x74, isinst,
151 unbox = 0x79, stobj = 0x81, box = 0x8C, newarr,
152 ldelema = 0x8F, refanyval = 0xC2, mkrefany = 0xC6,
153 ldtoken = 0xD0, initobj = 0xFE15, constrained = 0xFE16,
154 sizeOf = 0xFE1C, ldelem = 0xA3, stelem = 0xA4, unbox_any }
157 /// CIL branch instructions
159 public enum BranchOp {
161 br_s = 0x2B, brfalse_s, brtrue_s, beq_s, bge_s, bgt_s,
162 ble_s, blt_s, bne_un_s, bge_un_s, bgt_un_s, ble_un_s, blt_un_s,
164 br = 0x38, brfalse, brtrue, beq, bge, bgt, ble, blt,
165 bne_un, bge_un, bgt_un, ble_un, blt_un,
167 leave = 0xDD, leave_s }
170 /// Index for all the tables in the meta data
172 public enum MDTable { Module, TypeRef, TypeDef, Field = 0x04, Method = 0x06,
173 Param = 0x08, InterfaceImpl, MemberRef, Constant, CustomAttribute,
174 FieldMarshal, DeclSecurity, ClassLayout, FieldLayout, StandAloneSig,
175 EventMap, Event = 0x14, PropertyMap, Property = 0x17, MethodSemantics,
176 MethodImpl, ModuleRef, TypeSpec, ImplMap, FieldRVA, Assembly = 0x20,
177 AssemblyProcessor, AssemblyOS, AssemblyRef, AssemblyRefProcessor,
178 AssemblyRefOS, File, ExportedType, ManifestResource, NestedClass,
179 GenericParam, MethodSpec, GenericParamConstraint }
181 public enum SafeArrayType { int16 = 2, int32, float32, float64,
182 currency, date, bstr, dispatch, error, boolean, variant, unknown,
183 Decimal, int8 = 16, uint8, uint16, uint32, Int = 22, UInt }
185 internal enum CIx { TypeDefOrRef, HasConst, HasCustomAttr, HasFieldMarshal,
186 HasDeclSecurity, MemberRefParent, HasSemantics, MethodDefOrRef,
187 MemberForwarded, Implementation, CustomAttributeType, ResolutionScope,
188 TypeOrMethodDef, MaxCIx }
190 internal enum MapType { eventMap, propertyMap, nestedClass }
192 public enum ValueClass { ValueType, Enum }
194 public enum GenParamType : byte {
195 Var = 0x13, MVar = 0x1E
199 public enum GenericParamAttributes : ushort {
200 VarianceMask = 0x0003,
203 Contravariant = 0x0002,
205 SpecialConstraintMask = 0x001c,
206 ReferenceTypeConstraint = 0x0004,
207 NotNullableValueTypeConstraint = 0x0008,
208 DefaultConstructorConstrait = 0x0010
211 /* Taken from Mono.Cecil */
212 public enum SecurityAction : short {
226 NonCasLinkDemand = 14,
227 NonCasInheritance = 15,
228 LinkDemandChoice = 16,
229 InheritDemandChoice = 17,
235 /**************************************************************************/
237 /// Base class for all Meta Data table elements
240 public abstract class MetaDataElement: IComparable {
241 protected ArrayList customAttributes;
242 private uint row = 0;
243 protected bool done = false;
244 protected MDTable tabIx;
245 protected bool sortTable = false;
247 private bool has_custom_attrs = false;
249 internal MetaDataElement() { }
260 public bool HasCustomAttr {
261 get { return has_custom_attrs; }
262 set { has_custom_attrs = value; }
265 internal virtual uint GetCodedIx(CIx code) { return 0; }
268 /// Add a custom attribute to this item
270 /// <param name="ctorMeth">the constructor method for this attribute</param>
271 /// <param name="val">the byte value of the parameters</param>
272 public void AddCustomAttribute(Method ctorMeth, byte[] val)
274 if (customAttributes == null) {
275 customAttributes = new ArrayList();
277 customAttributes.Add(new CustomAttribute(this,ctorMeth,val));
281 /// Add a custom attribute to this item
283 /// <param name="ctorMeth">the constructor method for this attribute</param>
284 /// <param name="val">the constant values of the parameters</param>
285 public void AddCustomAttribute(Method ctorMeth, Constant[] cVals)
287 if (customAttributes == null) {
288 customAttributes = new ArrayList();
290 // customAttributes.Add(new CustomAttribute(this,ctorMeth,cVals));
293 internal uint Token()
295 return (((uint)tabIx << 24) | row);
298 internal virtual void BuildTables(MetaData md)
303 internal virtual uint Size(MetaData md)
308 internal virtual void Write(FileImage output) { }
310 internal virtual uint SortKey()
312 throw new PEFileException("Trying to sort table of " + this);
316 internal virtual uint SortKey2()
321 public int CompareTo(object obj)
323 uint otherKey = ((MetaDataElement)obj).SortKey();
324 uint thisKey = SortKey();
326 if (thisKey == otherKey) {
328 otherKey = ((MetaDataElement)obj).SortKey2();
329 thisKey = SortKey2();
330 if (thisKey == otherKey)
332 if (thisKey < otherKey)
336 if (thisKey < otherKey) return -1;
343 /**************************************************************************/
345 /// Layout information for a class (.class [sequential | explicit])
347 internal class ClassLayout : MetaDataElement {
353 internal ClassLayout(int pack, int cSize, ClassDef par)
355 packSize = (ushort)pack;
356 classSize = (uint)cSize;
358 tabIx = MDTable.ClassLayout;
361 internal sealed override uint Size(MetaData md)
363 return 6 + md.TableIndexSize(MDTable.TypeDef);
366 internal sealed override void Write(FileImage output)
368 output.Write(packSize);
369 output.Write(classSize);
370 output.WriteIndex(MDTable.TypeDef,parent.Row);
375 /**************************************************************************/
377 /// Summary description for ConstantElem.
379 internal class ConstantElem : MetaDataElement {
381 MetaDataElement parent;
385 internal ConstantElem(MetaDataElement parent, Constant val)
387 this.parent = parent;
389 tabIx = MDTable.Constant;
393 internal override uint SortKey()
395 return (parent.Row << MetaData.CIxShiftMap[(uint)CIx.HasConst])
396 | parent.GetCodedIx(CIx.HasConst);
399 internal sealed override void BuildTables(MetaData md)
402 valIx = cValue.GetBlobIndex(md);
406 internal void AddToBlob(BinaryWriter bw)
411 internal sealed override uint Size(MetaData md)
413 return 2 + md.CodedIndexSize(CIx.HasConst) + md.BlobIndexSize();
416 internal sealed override void Write(FileImage output)
418 output.Write(cValue.GetTypeIndex());
419 output.Write((byte)0);
420 output.WriteCodedIndex(CIx.HasConst,parent);
421 output.BlobIndex(valIx);
425 /**************************************************************************/
427 /// Descriptor for a Custom Attribute (.custom)
430 public class CustomAttribute : MetaDataElement {
432 MetaDataElement parent;
438 ArrayList names, vals;
440 internal CustomAttribute(MetaDataElement paren, Method constrType,
445 tabIx = MDTable.CustomAttribute;
447 var bac = val as ByteArrConst;
452 internal CustomAttribute(MetaDataElement paren, Method constrType,
456 tabIx = MDTable.CustomAttribute;
460 internal override uint SortKey()
462 return (parent.Row << MetaData.CIxShiftMap[(uint)CIx.HasCustomAttr])
463 | parent.GetCodedIx(CIx.HasCustomAttr);
466 public void AddFieldOrProp(string name, Constant val)
469 names = new ArrayList();
470 vals = new ArrayList();
476 internal sealed override void BuildTables(MetaData md)
478 md.AddToTable(MDTable.CustomAttribute, this);
479 if (byteVal == null) {
484 BinaryWriter bw = new BinaryWriter(new MemoryStream());
486 MemoryStream str = (MemoryStream)bw.BaseStream;
487 valIx = md.AddToBlobHeap(str.ToArray());
490 internal sealed override uint Size(MetaData md)
492 return md.CodedIndexSize(CIx.HasCustomAttr) + md.CodedIndexSize(CIx.CustomAttributeType) + md.BlobIndexSize();
495 internal sealed override void Write(FileImage output)
497 output.WriteCodedIndex(CIx.HasCustomAttr,parent);
498 output.WriteCodedIndex(CIx.CustomAttributeType,type);
499 output.BlobIndex(valIx);
504 /**************************************************************************/
506 /// Descriptor for security permissions for a class or a method
509 public abstract class BaseDeclSecurity : MetaDataElement {
512 MetaDataElement parent;
515 internal BaseDeclSecurity(MetaDataElement paren, ushort act)
519 tabIx = MDTable.DeclSecurity;
522 internal override uint SortKey()
524 return (parent.Row << MetaData.CIxShiftMap[(uint)CIx.HasDeclSecurity])
525 | parent.GetCodedIx(CIx.HasDeclSecurity);
528 internal sealed override uint Size(MetaData md)
530 return 2 + md.CodedIndexSize(CIx.HasDeclSecurity) + md.BlobIndexSize();
533 internal sealed override void BuildTables(MetaData md)
537 BinaryWriter bw = new BinaryWriter (new MemoryStream ());
538 md.AddToTable (MDTable.DeclSecurity, this);
539 MemoryStream str = (MemoryStream)bw.BaseStream;
541 permissionIx = md.AddToBlobHeap(str.ToArray());
546 internal abstract void WriteSig (BinaryWriter bw);
548 internal sealed override void Write(FileImage output)
550 output.Write(action);
551 output.WriteCodedIndex(CIx.HasDeclSecurity,parent);
552 output.BlobIndex(permissionIx);
557 public class DeclSecurity : BaseDeclSecurity {
561 internal DeclSecurity(MetaDataElement paren, ushort act, byte [] val)
567 internal override void WriteSig (BinaryWriter bw)
574 public class DeclSecurity_20 : BaseDeclSecurity {
578 internal DeclSecurity_20 (MetaDataElement paren, ushort act, PermissionSet ps)
584 internal override void WriteSig (BinaryWriter bw)
590 public class PermissionMember {
592 MemberTypes member_type;
597 public PermissionMember (MemberTypes member_type, PEAPI.Type type, string name, object value)
599 this.member_type = member_type;
605 public void Write (BinaryWriter bw)
609 if (member_type == MemberTypes.Field)
610 bw.Write ((byte) 0x53);
613 bw.Write ((byte) 0x54);
615 if (type is PrimitiveType) {
616 bw.Write (type.GetTypeIndex ());
619 bw.Write ((byte) 0x55); //ENUM
621 b = Encoding.UTF8.GetBytes (((ClassRef) type).TypeName ());
622 MetaData.CompressNum ((uint) b.Length, (MemoryStream) bw.BaseStream);
626 b = Encoding.UTF8.GetBytes (name);
627 MetaData.CompressNum ((uint) b.Length, (MemoryStream) bw.BaseStream);
630 ((Constant) value).Write (bw);
635 public class Permission
643 public Permission (PEAPI.Type type, string name)
649 public void AddMember (PEAPI.PermissionMember member)
652 members = new ArrayList ();
654 members.Add (member);
657 public void Write (BinaryWriter bw)
659 byte [] b = Encoding.UTF8.GetBytes (name);
660 MetaData.CompressNum ((uint) b.Length, (MemoryStream) bw.BaseStream);
663 BinaryWriter perm_writer = new BinaryWriter (new MemoryStream (), Encoding.Unicode);
664 MemoryStream str = (MemoryStream) perm_writer.BaseStream;
666 MetaData.CompressNum ((uint) members.Count, str);//number of params
667 foreach (PermissionMember member in members)
668 member.Write (perm_writer);
670 bw.Write ((byte) str.Length); //(optional) parameters length
671 bw.Write (str.ToArray ());
675 public class PermissionSet
677 PEAPI.SecurityAction sec_action;
678 ArrayList permissions;
680 public PermissionSet (PEAPI.SecurityAction sec_action)
682 this.sec_action = sec_action;
685 public void AddPermission (PEAPI.Permission perm)
687 if (permissions == null)
688 permissions = new ArrayList ();
690 permissions.Add (perm);
693 public void Write (BinaryWriter bw)
695 bw.Write ((byte) 0x2e);
696 MetaData.CompressNum ((uint) permissions.Count, (MemoryStream) bw.BaseStream);
698 foreach (Permission perm in permissions)
704 /**************************************************************************/
706 /// Descriptor for layout information for a field
709 public class FieldLayout : MetaDataElement {
714 internal FieldLayout(Field field, uint offset)
717 this.offset = offset;
718 tabIx = MDTable.FieldLayout;
721 internal sealed override uint Size(MetaData md)
723 return 4 + md.TableIndexSize(MDTable.Field);
726 internal sealed override void Write(FileImage output)
728 output.Write(offset);
729 output.WriteIndex(MDTable.Field,field.Row);
734 /*****************************************************************************/
736 /// Marshalling information for a field or param
738 public class FieldMarshal : MetaDataElement {
740 MetaDataElement field;
744 internal FieldMarshal(MetaDataElement field, NativeType nType)
748 tabIx = MDTable.FieldMarshal;
751 internal override uint SortKey()
753 return (field.Row << MetaData.CIxShiftMap[(uint)CIx.HasFieldMarshal])
754 | field.GetCodedIx(CIx.HasFieldMarshal);
757 internal sealed override void BuildTables(MetaData md)
760 ntIx = md.AddToBlobHeap(nt.ToBlob());
764 internal sealed override uint Size(MetaData md)
766 return md.CodedIndexSize(CIx.HasFieldMarshal) + md.BlobIndexSize();
769 internal sealed override void Write(FileImage output)
771 output.WriteCodedIndex(CIx.HasFieldMarshal,field);
772 output.BlobIndex(ntIx);
777 /**************************************************************************/
779 /// Descriptor for the address of a field's value in the PE file
781 public class FieldRVA : MetaDataElement {
786 internal FieldRVA(Field field, DataConstant data)
790 tabIx = MDTable.FieldRVA;
793 internal sealed override void BuildTables(MetaData md)
800 internal sealed override uint Size(MetaData md)
802 return 4 + md.TableIndexSize(MDTable.Field);
805 internal sealed override void Write(FileImage output)
807 output.WriteDataRVA(data.DataOffset);
808 output.WriteIndex(MDTable.Field,field.Row);
813 /**************************************************************************/
815 /// Descriptor for a file referenced in THIS assembly/module (.file)
817 public class FileRef : MetaDataElement {
819 private static readonly uint NoMetaData = 0x1;
820 uint nameIx = 0, hashIx = 0;
822 protected string name;
824 internal FileRef(string name, byte[] hashBytes, bool metaData,
825 bool entryPoint, MetaData md) {
826 if (!metaData) flags = NoMetaData;
827 if (entryPoint) md.SetEntryPoint(this);
829 nameIx = md.AddToStringsHeap(name);
830 hashIx = md.AddToBlobHeap(hashBytes);
831 tabIx = MDTable.File;
834 internal FileRef(uint nameIx, byte[] hashBytes, bool metaData,
835 bool entryPoint, MetaData md) {
836 if (!metaData) flags = NoMetaData;
837 if (entryPoint) md.SetEntryPoint(this);
838 this.nameIx = nameIx;
839 hashIx = md.AddToBlobHeap(hashBytes);
840 tabIx = MDTable.File;
843 internal sealed override uint Size(MetaData md)
845 return 4 + md.StringsIndexSize() + md.BlobIndexSize();
848 internal sealed override void BuildTables(MetaData md)
850 md.AddToTable(MDTable.File,this);
853 internal sealed override void Write(FileImage output)
856 output.StringsIndex(nameIx);
857 output.BlobIndex(hashIx);
860 internal sealed override uint GetCodedIx(CIx code)
863 case (CIx.HasCustomAttr) : return 16;
864 case (CIx.Implementation) : return 0;
870 /**************************************************************************/
872 /// Descriptor for pinvoke information for a method NOT YET IMPLEMENTED
874 public class ImplMap : MetaDataElement {
876 private static readonly ushort NoMangle = 0x01;
881 ModuleRef importScope;
883 internal ImplMap(ushort flag, Method implMeth, string iName, ModuleRef mScope)
888 importScope = mScope;
889 tabIx = MDTable.ImplMap;
890 if (iName == null) flags |= NoMangle;
891 //throw(new NotYetImplementedException("PInvoke "));
894 internal override uint SortKey()
896 return (meth.Row << MetaData.CIxShiftMap[(uint)CIx.MemberForwarded])
897 | meth.GetCodedIx(CIx.MemberForwarded);
900 internal sealed override void BuildTables(MetaData md)
903 iNameIx = md.AddToStringsHeap(importName);
907 internal sealed override uint Size(MetaData md)
909 return 2+ md.CodedIndexSize(CIx.MemberForwarded) +
910 md.StringsIndexSize() + md.TableIndexSize(MDTable.ModuleRef);
913 internal sealed override void Write(FileImage output)
916 output.WriteCodedIndex(CIx.MemberForwarded,meth);
917 output.StringsIndex(iNameIx);
918 output.WriteIndex(MDTable.ModuleRef,importScope.Row);
923 /**************************************************************************/
925 public class GenericParameter : MetaDataElement {
927 MetaDataElement owner;
932 GenericParamAttributes attr;
934 internal GenericParameter (ClassDef owner, MetaData metadata,
935 short index, string name, GenericParamAttributes attr) : this (owner, metadata, index, name, attr, true)
939 internal GenericParameter (MethodDef owner, MetaData metadata,
940 short index, string name, GenericParamAttributes attr) : this (owner, metadata, index, name, attr, true)
944 private GenericParameter (MetaDataElement owner, MetaData metadata,
945 short index, string name, GenericParamAttributes attr, bool nadda) {
947 this.metadata = metadata;
949 tabIx = MDTable.GenericParam;
954 internal override uint SortKey()
956 return (owner.Row << MetaData.CIxShiftMap[(uint)CIx.TypeOrMethodDef])
957 | owner.GetCodedIx(CIx.TypeOrMethodDef);
960 internal override uint SortKey2 ()
965 public void AddConstraint (Type constraint)
967 metadata.AddToTable (MDTable.GenericParamConstraint,
968 new GenericParamConstraint (this, constraint));
971 internal sealed override uint Size(MetaData md)
974 md.CodedIndexSize(CIx.TypeOrMethodDef) +
975 md.StringsIndexSize ());
978 internal sealed override void BuildTables(MetaData md)
981 nameIx = md.AddToStringsHeap(name);
985 internal sealed override void Write(FileImage output)
987 output.Write ((short) index);
988 output.Write ((short) attr);
989 output.WriteCodedIndex(CIx.TypeOrMethodDef, owner);
990 output.StringsIndex (nameIx);
993 internal sealed override uint GetCodedIx(CIx code)
996 case (CIx.HasCustomAttr) : return 19;
1003 internal class GenericParamConstraint : MetaDataElement {
1005 GenericParameter param;
1008 public GenericParamConstraint (GenericParameter param, Type type)
1012 tabIx = MDTable.GenericParamConstraint;
1015 internal override uint SortKey()
1020 internal sealed override uint Size(MetaData md)
1022 return (uint) (md.TableIndexSize(MDTable.GenericParam) +
1023 md.CodedIndexSize(CIx.TypeDefOrRef));
1026 internal sealed override void Write(FileImage output)
1028 output.WriteIndex(MDTable.GenericParam, param.Row);
1029 output.WriteCodedIndex(CIx.TypeDefOrRef, type);
1034 internal class MethodSpec : Method {
1037 GenericMethodSig g_sig;
1040 internal MethodSpec (Method meth, GenericMethodSig g_sig) : base ("")
1044 tabIx = MDTable.MethodSpec;
1047 internal override uint GetSigIx (MetaData md)
1049 throw new Exception ("Should not be used.");
1052 public override void AddCallConv (CallConv cconv)
1054 throw new Exception ("Should not be used.");
1057 internal sealed override void BuildTables (MetaData md)
1060 sidx = g_sig.GetSigIx (md);
1064 internal sealed override uint Size (MetaData md)
1066 return (uint) (md.CodedIndexSize(CIx.MethodDefOrRef) +
1067 md.BlobIndexSize ());
1070 internal sealed override void Write (FileImage output)
1072 output.WriteCodedIndex (CIx.MethodDefOrRef, meth);
1073 output.BlobIndex (sidx);
1076 internal sealed override void TypeSig (MemoryStream sig)
1078 throw new Exception ("Should not be used.");
1082 /**************************************************************************/
1084 /// Descriptor for interface implemented by a class
1086 public class InterfaceImpl: MetaDataElement {
1091 internal InterfaceImpl(ClassDef theClass, Class theInterface)
1093 this.theClass = theClass;
1094 this.theInterface = theInterface;
1095 tabIx = MDTable.InterfaceImpl;
1098 internal sealed override uint Size(MetaData md)
1100 return md.TableIndexSize(MDTable.TypeDef) +
1101 md.CodedIndexSize(CIx.TypeDefOrRef);
1104 internal sealed override void Write(FileImage output)
1106 output.WriteIndex(MDTable.TypeDef,theClass.Row);
1107 output.WriteCodedIndex(CIx.TypeDefOrRef,theInterface);
1110 internal sealed override uint GetCodedIx(CIx code) { return 5; }
1112 internal override uint SortKey ()
1114 return (theClass.Row << MetaData.CIxShiftMap[(uint)CIx.TypeDefOrRef])
1115 | theClass.GetCodedIx (CIx.TypeDefOrRef);
1120 /**************************************************************************/
1122 /// Descriptor for resources used in this PE file
1125 public class ManifestResource : MetaDataElement {
1127 public static readonly uint PublicResource = 0x1;
1128 public static readonly uint PrivateResource = 0x2;
1131 MetaDataElement rRef;
1135 byte [] resourceBytes;
1137 public ManifestResource (string name, byte[] resBytes, uint flags)
1139 InitResource (name, flags);
1140 this.resourceBytes = resBytes;
1143 public ManifestResource(string name, uint flags, FileRef fileRef)
1145 InitResource (name, flags);
1149 public ManifestResource(string name, uint flags, FileRef fileRef,
1151 InitResource (name, flags);
1153 fileOffset = fileIx;
1156 public ManifestResource(string name, uint flags, AssemblyRef assemRef)
1158 InitResource (name, flags);
1162 internal ManifestResource (ManifestResource mres)
1164 mrName = mres.mrName;
1167 fileOffset = mres.fileOffset;
1168 resourceBytes = mres.resourceBytes;
1171 private void InitResource (string name, uint flags)
1175 tabIx = MDTable.ManifestResource;
1178 internal sealed override void BuildTables(MetaData md)
1181 md.AddToTable (MDTable.ManifestResource, this);
1182 nameIx = md.AddToStringsHeap(mrName);
1183 if (resourceBytes != null) {
1185 throw new PEFileException ("Manifest Resource has byte value and file reference");
1186 fileOffset = md.AddResource(resourceBytes);
1189 throw new PEFileException ("Manifest Resource has no implementation or value");
1190 rRef.BuildTables (md);
1196 internal sealed override uint Size(MetaData md)
1198 return 8 + md.StringsIndexSize() +
1199 md.CodedIndexSize(CIx.Implementation);
1202 internal sealed override void Write(FileImage output)
1204 output.Write(fileOffset);
1205 output.Write(flags);
1206 output.StringsIndex(nameIx);
1207 output.WriteCodedIndex(CIx.Implementation,rRef);
1210 internal sealed override uint GetCodedIx(CIx code) { return 18; }
1212 public string Name {
1213 get { return mrName; }
1214 set { mrName = value; }
1218 /**************************************************************************/
1220 /// Base class for elements in the PropertyMap, EventMap and
1221 /// NestedClass MetaData tables
1223 public class MapElem : MetaDataElement {
1229 internal MapElem(ClassDef par, uint elIx, MDTable elemTab)
1233 elemTable = elemTab;
1236 internal sealed override uint Size(MetaData md)
1238 return md.TableIndexSize(MDTable.TypeDef) + md.TableIndexSize(elemTable);
1241 internal sealed override void Write(FileImage output)
1243 output.WriteIndex(MDTable.TypeDef,parent.Row);
1244 output.WriteIndex(elemTable,elemIx);
1248 /**************************************************************************/
1250 /// Descriptor for an overriding method (.override)
1252 public class MethodImpl : MetaDataElement {
1255 Method header, body;
1257 internal MethodImpl(ClassDef par, Method decl, Method bod)
1262 tabIx = MDTable.MethodImpl;
1265 internal sealed override uint Size(MetaData md)
1267 return md.TableIndexSize(MDTable.TypeDef) + 2 * md.CodedIndexSize(CIx.MethodDefOrRef);
1270 internal sealed override void Write(FileImage output)
1272 output.WriteIndex(MDTable.TypeDef,parent.Row);
1273 output.WriteCodedIndex(CIx.MethodDefOrRef,body);
1274 output.WriteCodedIndex(CIx.MethodDefOrRef,header);
1279 /**************************************************************************/
1281 /// Descriptor for Property and Event methods
1283 public class MethodSemantics : MetaDataElement {
1285 Feature.MethodType type;
1287 Feature eventOrProp;
1289 internal MethodSemantics(Feature.MethodType mType, MethodDef method, Feature feature)
1293 eventOrProp = feature;
1294 tabIx = MDTable.MethodSemantics;
1297 internal override uint SortKey()
1299 return (eventOrProp.Row << MetaData.CIxShiftMap [(uint)CIx.HasSemantics])
1300 | eventOrProp.GetCodedIx (CIx.HasSemantics);
1303 internal sealed override uint Size(MetaData md)
1305 return 2 + md.TableIndexSize(MDTable.Method) + md.CodedIndexSize(CIx.HasSemantics);
1308 internal sealed override void Write(FileImage output)
1310 output.Write((ushort)type);
1311 output.WriteIndex(MDTable.Method,meth.Row);
1312 output.WriteCodedIndex(CIx.HasSemantics,eventOrProp);
1317 /**************************************************************************/
1319 /// Descriptor for a parameter of a method defined in this assembly/module
1321 public class Param : MetaDataElement {
1326 internal ushort seqNo = 0;
1328 ConstantElem defaultVal;
1330 FieldMarshal marshalInfo;
1333 /// Create a new parameter for a method
1335 /// <param name="mode">param mode (in, out, opt)</param>
1336 /// <param name="parName">parameter name</param>
1337 /// <param name="parType">parameter type</param>
1338 public Param(ParamAttr mode, string parName, Type parType)
1342 parMode = (ushort)mode;
1343 tabIx = MDTable.Param;
1346 public bool HasMarshalInfo {
1347 get { return marshalInfo != null; }
1351 /// Add a default value to this parameter
1353 /// <param name="c">the default value for the parameter</param>
1354 public void AddDefaultValue(Constant cVal)
1356 defaultVal = new ConstantElem(this,cVal);
1357 parMode |= (ushort) ParamAttr.HasDefault;
1361 /// Add marshalling information about this parameter
1363 public void AddMarshallInfo(NativeType marshallType)
1365 parMode |= (ushort) ParamAttr.HasFieldMarshal;
1366 marshalInfo = new FieldMarshal(this,marshallType);
1369 internal Type GetParType() { return pType; }
1371 internal sealed override void BuildTables(MetaData md)
1374 nameIx = md.AddToStringsHeap(pName);
1375 if (defaultVal != null) {
1376 md.AddToTable(MDTable.Constant,defaultVal);
1377 defaultVal.BuildTables(md);
1379 if (marshalInfo != null) {
1380 md.AddToTable(MDTable.FieldMarshal,marshalInfo);
1381 marshalInfo.BuildTables(md);
1386 internal void TypeSig(MemoryStream str)
1391 internal sealed override uint Size(MetaData md)
1393 return 4 + md.StringsIndexSize();
1396 internal sealed override void Write(FileImage output)
1398 output.Write(parMode);
1399 output.Write(seqNo);
1400 output.StringsIndex(nameIx);
1403 internal sealed override uint GetCodedIx(CIx code)
1406 case (CIx.HasCustomAttr) : return 4;
1407 case (CIx.HasConst) : return 1;
1408 case (CIx.HasFieldMarshal) : return 1;
1415 /**************************************************************************/
1416 public abstract class Signature : MetaDataElement {
1418 protected uint sigIx;
1420 internal Signature()
1422 tabIx = MDTable.StandAloneSig;
1425 internal sealed override uint Size(MetaData md)
1427 return md.BlobIndexSize();
1430 internal sealed override void Write(FileImage output)
1432 output.BlobIndex(sigIx);
1435 internal sealed override uint GetCodedIx(CIx code) { return (uint)tabIx; }
1439 /**************************************************************************/
1440 public class TypeSpec : MetaDataElement {
1443 internal TypeSpec(Type aType, MetaData md)
1445 MemoryStream sig = new MemoryStream();
1447 sigIx = md.AddToBlobHeap(sig.ToArray());
1448 tabIx = MDTable.TypeSpec;
1451 internal sealed override uint GetCodedIx(CIx code)
1454 case (CIx.TypeDefOrRef) : return 2;
1455 case (CIx.HasCustomAttr) : return 13;
1456 case (CIx.MemberRefParent) : return 4;
1461 internal override uint Size(MetaData md)
1463 return md.BlobIndexSize();
1466 internal sealed override void Write(FileImage output)
1468 //Console.WriteLine("Writing the blob index for a TypeSpec");
1469 output.BlobIndex(sigIx);
1474 /**************************************************************************/
1476 /// Base class for all IL types
1478 public abstract class Type : MetaDataElement {
1479 protected byte typeIndex;
1480 protected TypeSpec typeSpec;
1482 internal Type(byte tyIx) { typeIndex = tyIx; }
1484 internal byte GetTypeIndex() { return typeIndex; }
1485 internal void SetTypeIndex (byte b) { typeIndex = b; }
1487 internal virtual MetaDataElement GetTypeSpec(MetaData md)
1489 if (typeSpec == null) {
1490 typeSpec = new TypeSpec(this,md);
1491 md.AddToTable(MDTable.TypeSpec,typeSpec);
1496 internal virtual void TypeSig(MemoryStream str)
1498 throw(new TypeSignatureException(this.GetType().AssemblyQualifiedName +
1499 " doesn't have a type signature!!"));
1503 public class ClassRefInst : Type {
1506 private bool is_value;
1508 public ClassRefInst (Type type, bool is_value) : base (PrimitiveType.Class.GetTypeIndex ())
1511 this.is_value = is_value;
1513 typeIndex = PrimitiveType.ValueType.GetTypeIndex ();
1514 tabIx = MDTable.TypeSpec;
1517 internal sealed override void TypeSig(MemoryStream str)
1523 /**************************************************************************/
1525 /// The base descriptor for a class
1527 public abstract class Class : Type {
1529 protected int row = 0;
1530 public string name, nameSpace;
1531 protected uint nameIx, nameSpaceIx;
1532 protected MetaData _metaData;
1533 internal Class(string nameSpaceName, string className, MetaData md)
1534 : base(PrimitiveType.Class.GetTypeIndex ())
1536 nameSpace = nameSpaceName;
1538 nameIx = md.AddToStringsHeap(name);
1539 nameSpaceIx = md.AddToStringsHeap(nameSpace);
1543 internal Class(uint nsIx, uint nIx) : base(PrimitiveType.Class.GetTypeIndex ())
1549 internal Class (byte typeIndex) : base (typeIndex)
1551 nameSpace = "Should not be used";
1552 name = "Should not be used";
1555 internal virtual uint TypeDefOrRefToken() { return 0; }
1557 internal virtual void MakeValueClass(ValueClass vClass)
1559 typeIndex = PrimitiveType.ValueType.GetTypeIndex ();
1562 internal virtual string TypeName()
1564 return (nameSpace + "." + name);
1567 internal override MetaDataElement GetTypeSpec(MetaData md)
1573 /**************************************************************************/
1574 // This Class produces entries in the TypeDef table of the MetaData
1575 // in the PE meta data.
1577 // NOTE: Entry 0 in TypeDef table is always the pseudo class <module>
1578 // which is the parent for functions and variables declared a module level
1581 /// The descriptor for a class defined in the IL (.class) in the current assembly/module
1584 public class ClassDef : Class {
1587 ArrayList fields = new ArrayList();
1588 ArrayList methods = new ArrayList();
1590 ArrayList properties;
1591 bool typeIndexChecked = true;
1592 uint fieldIx = 0, methodIx = 0;
1595 ClassDef parentClass;
1598 internal ClassDef(TypeAttr attrSet, string nsName, string name,
1599 MetaData md) : base(nsName, name, md)
1602 if (! ((nsName == "" && name == "<Module>") || (nsName == "System" && name == "Object")) ) {
1603 superType = metaData.mscorlib.GetSpecialSystemClass(PrimitiveType.Object);
1605 flags = (uint)attrSet;
1606 tabIx = MDTable.TypeDef;
1609 internal void SetSuper(Class sClass)
1612 if (! (sClass is GenericTypeInst))
1613 typeIndexChecked = false;
1616 internal override void MakeValueClass(ValueClass vClass)
1618 if (vClass == ValueClass.Enum)
1619 superType = metaData.mscorlib.EnumType();
1621 superType = metaData.mscorlib.ValueType();
1623 typeIndex = PrimitiveType.ValueType.GetTypeIndex ();
1626 public void SpecialNoSuper()
1632 /// Add an attribute to this class
1634 /// <param name="ta">the attribute to be added</param>
1635 public void AddAttribute(TypeAttr ta)
1641 /// Add an interface that is implemented by this class
1643 /// <param name="iFace">the interface that is implemented</param>
1644 public void AddImplementedInterface(Class iFace)
1646 metaData.AddToTable(MDTable.InterfaceImpl,new InterfaceImpl(this,iFace));
1650 /// Add a named generic type parameter
1652 public GenericParameter AddGenericParameter (short index, string name)
1654 return AddGenericParameter (index, name, 0);
1658 /// Add a named generic type parameter with attributes
1660 public GenericParameter AddGenericParameter (short index, string name, GenericParamAttributes attr)
1662 GenericParameter gp = new GenericParameter (this, metaData, index, name, attr);
1663 metaData.AddToTable (MDTable.GenericParam, gp);
1668 /// Add a field to this class
1670 /// <param name="name">field name</param>
1671 /// <param name="fType">field type</param>
1672 /// <returns>a descriptor for this new field</returns>
1673 public FieldDef AddField(string name, Type fType)
1675 FieldDef field = new FieldDef(name,fType);
1681 /// Add a field to this class
1683 /// <param name="fAtts">attributes for this field</param>
1684 /// <param name="name">field name</param>
1685 /// <param name="fType">field type</param>
1686 /// <returns>a descriptor for this new field</returns>
1687 public FieldDef AddField(FieldAttr fAtts, string name, Type fType)
1689 FieldDef field = new FieldDef(fAtts,name,fType);
1694 public void SetFieldOrder (ArrayList fields)
1696 this.fields = fields;
1700 /// Add a method to this class
1702 /// <param name="name">method name</param>
1703 /// <param name="retType">return type</param>
1704 /// <param name="pars">parameters</param>
1705 /// <returns>a descriptor for this new method</returns>
1706 public MethodDef AddMethod(string name, Type retType, Param[] pars)
1708 return AddMethod (name, new Param (ParamAttr.Default, "", retType), pars);
1711 public MethodDef AddMethod (string name, Param ret_param, Param [] pars)
1713 // Console.WriteLine("Adding method " + name + " to class " + this.name);
1714 MethodDef meth = new MethodDef(metaData,name, ret_param, pars);
1720 /// Add a method to this class
1722 /// <param name="mAtts">attributes for this method</param>
1723 /// <param name="iAtts">implementation attributes for this method</param>
1724 /// <param name="name">method name</param>
1725 /// <param name="retType">return type</param>
1726 /// <param name="pars">parameters</param>
1727 /// <returns>a descriptor for this new method</returns>
1728 public MethodDef AddMethod(MethAttr mAtts, ImplAttr iAtts, string name,
1729 Param ret_param, Param [] pars) {
1730 // Console.WriteLine("Adding method " + name + " to class " + this.name);
1731 MethodDef meth = new MethodDef (metaData, mAtts, iAtts, name, ret_param, pars);
1737 /// Add an event to this class
1739 /// <param name="name">event name</param>
1740 /// <param name="eType">event type</param>
1741 /// <returns>a descriptor for this new event</returns>
1742 public Event AddEvent(string name, Type eType)
1744 Event e = new Event(name,eType,this);
1745 if (events == null) events = new ArrayList();
1751 /// Add a property to this class
1753 /// <param name="name">property name</param>
1754 /// <param name="propType">property type</param>
1755 /// <returns>a descriptor for this new property</returns>
1756 public Property AddProperty(string name, Type retType, Type[] pars)
1758 Property p = new Property(name, retType, pars, this);
1759 if (properties == null) properties = new ArrayList();
1765 /// Add a nested class to this class
1767 /// <param name="attrSet">attributes for this nested class</param>
1768 /// <param name="nsName">nested name space name</param>
1769 /// <param name="name">nested class name</param>
1770 /// <returns>a descriptor for this new nested class</returns>
1771 public ClassDef AddNestedClass(TypeAttr attrSet, string nsName,
1773 ClassDef nClass = new ClassDef(attrSet,"",name,metaData);
1774 metaData.AddToTable(MDTable.TypeDef,nClass);
1775 metaData.AddToTable(MDTable.NestedClass,new MapElem(nClass,Row,MDTable.TypeDef));
1776 nClass.parentClass = this;
1780 public static bool IsValueType (Class type)
1782 return IsValueType (type.nameSpace, type.name);
1785 public static bool IsEnum (Class type)
1787 return IsEnum (type.nameSpace, type.name);
1790 public static bool IsValueType (string nsName, string name)
1792 return (nsName == "System" && name == "ValueType");
1795 public static bool IsEnum (string nsName, string name)
1797 return (nsName == "System" && name == "Enum");
1801 /// Add a nested class to this class
1803 /// <param name="attrSet">attributes for this nested class</param>
1804 /// <param name="nsName">nested name space name</param>
1805 /// <param name="name">nested class name</param>
1806 /// <param name="sType">super type of this nested class</param>
1807 /// <returns>a descriptor for this new nested class</returns>
1808 public ClassDef AddNestedClass(TypeAttr attrSet, string nsName,
1809 string name, Class sType) {
1810 ClassDef nClass = AddNestedClass (attrSet, nsName, name);
1811 nClass.SetSuper(sType);
1812 if (ClassDef.IsValueType (sType))
1813 nClass.MakeValueClass (ValueClass.ValueType);
1815 if (ClassDef.IsEnum (sType))
1816 nClass.MakeValueClass (ValueClass.Enum);
1818 if (ClassDef.IsValueType (sType) || ClassDef.IsEnum (sType))
1819 nClass.SetTypeIndex (PrimitiveType.ValueType.GetTypeIndex ());
1821 nClass.typeIndexChecked = true;
1826 /// Add layout information for this class. This class must have the
1827 /// sequential or explicit attribute.
1829 /// <param name="packSize">packing size (.pack)</param>
1830 /// <param name="classSize">class size (.size)</param>
1831 public void AddLayoutInfo (int packSize, int classSize)
1833 layout = new ClassLayout(packSize,classSize,this);
1837 /// Use a method as the implementation for another method (.override)
1839 /// <param name="decl">the method to be overridden</param>
1840 /// <param name="body">the implementation to be used</param>
1841 public void AddMethodOverride(Method decl, Method body)
1843 metaData.AddToTable(MDTable.MethodImpl,new MethodImpl(this,decl,body));
1847 /// Add security to this class NOT YET IMPLEMENTED
1849 /// <param name="permissionSet"></param>
1850 public void AddSecurity(byte[] permissionSet)
1852 throw(new NotYetImplementedException("Class security "));
1853 //flags |= HasSecurity;
1854 // securityActions = permissionSet;
1857 //public void AddLineInfo(int row, int col) { }
1859 internal void CheckTypeIndex()
1861 if (typeIndexChecked) return;
1862 if (superType is ClassDef)
1863 ((ClassDef)superType).CheckTypeIndex();
1864 typeIndex = superType.GetTypeIndex();
1865 typeIndexChecked = true;
1868 internal sealed override void BuildTables(MetaData md)
1871 if ((flags & (uint)TypeAttr.Interface) != 0) { superType = null; }
1872 // Console.WriteLine("Building tables for " + name);
1873 if (layout != null) md.AddToTable(MDTable.ClassLayout,layout);
1874 // Console.WriteLine("adding methods " + methods.Count);
1875 methodIx = md.TableIndex(MDTable.Method);
1876 for (int i=0; i < methods.Count; i++) {
1877 md.AddToTable(MDTable.Method,(MetaDataElement)methods[i]);
1878 ((MethodDef)methods[i]).BuildTables(md);
1880 // Console.WriteLine("adding fields");
1881 fieldIx = md.TableIndex(MDTable.Field);
1882 for (int i=0; i < fields.Count; i++) {
1883 md.AddToTable(MDTable.Field,(MetaDataElement)fields[i]);
1884 ((FieldDef)fields[i]).BuildTables(md);
1886 // Console.WriteLine("adding events and properties");
1887 if (events != null) {
1888 for (int i=0; i < events.Count; i++) {
1889 md.AddToTable(MDTable.Event,(Event)events[i]);
1890 ((Event)events[i]).BuildTables(md);
1892 md.AddToTable(MDTable.EventMap,
1893 new MapElem(this,((Event)events[0]).Row,MDTable.Event));
1895 if (properties != null) {
1896 for (int i=0; i < properties.Count; i++) {
1897 md.AddToTable(MDTable.Property,(Property)properties[i]);
1898 ((Property)properties[i]).BuildTables(md);
1900 md.AddToTable(MDTable.PropertyMap,new MapElem(this,
1901 ((Property)properties[0]).Row,MDTable.Property));
1903 // Console.WriteLine("End of building tables");
1907 internal sealed override uint Size(MetaData md)
1909 return 4 + 2 * md.StringsIndexSize() +
1910 md.CodedIndexSize(CIx.TypeDefOrRef) +
1911 md.TableIndexSize(MDTable.Field) +
1912 md.TableIndexSize(MDTable.Method);
1915 internal sealed override void Write(FileImage output)
1917 output.Write(flags);
1918 output.StringsIndex(nameIx);
1919 output.StringsIndex(nameSpaceIx);
1920 //if (superType != null)
1921 // Console.WriteLine("getting coded index for superType of " + name + " = " + superType.GetCodedIx(CIx.TypeDefOrRef));
1922 output.WriteCodedIndex(CIx.TypeDefOrRef,superType);
1923 output.WriteIndex(MDTable.Field,fieldIx);
1924 output.WriteIndex(MDTable.Method,methodIx);
1927 internal sealed override uint TypeDefOrRefToken()
1934 internal sealed override void TypeSig(MemoryStream sig)
1936 if (!typeIndexChecked) CheckTypeIndex();
1937 sig.WriteByte(GetTypeIndex());
1938 MetaData.CompressNum(TypeDefOrRefToken(),sig);
1941 internal sealed override uint GetCodedIx(CIx code)
1944 case (CIx.TypeDefOrRef) : return 0;
1945 case (CIx.HasCustomAttr) : return 3;
1946 case (CIx.HasDeclSecurity) : return 0;
1947 case (CIx.TypeOrMethodDef) : return 0;
1954 /**************************************************************************/
1956 /// Descriptor for a class/interface declared in another module of THIS
1957 /// assembly, or in another assembly.
1959 public class ClassRef : Class, IExternRef, IResolutionScope {
1961 protected IResolutionScope parent;
1962 protected MetaData metaData;
1964 internal ClassRef(string nsName, string name, MetaData md) : base(nsName, name, md)
1967 tabIx = MDTable.TypeRef;
1971 /// Add a method to this class
1973 /// <param name="name">method name</param>
1974 /// <param name="retType">return type</param>
1975 /// <param name="pars">parameter types</param>
1976 /// <returns>a descriptor for this method</returns>
1977 public MethodRef AddMethod(string name, Type retType, Type[] pars)
1979 return AddMethod (name, retType, pars, 0);
1983 /// Add a method to this class
1985 /// <param name="name">method name</param>
1986 /// <param name="retType">return type</param>
1987 /// <param name="pars">parameter types</param>
1988 /// <param name="gen_param_count">num of generic parameters</param>
1989 /// <returns>a descriptor for this method</returns>
1990 public MethodRef AddMethod (string name, Type retType, Type[] pars, int gen_param_count)
1992 MethodRef meth = new MethodRef (this, name, retType, pars, false, null, gen_param_count);
1993 metaData.AddToTable(MDTable.MemberRef,meth);
1998 /// Add a method to this class
2000 /// <param name="name">method name</param>
2001 /// <param name="retType">return type</param>
2002 /// <param name="pars">parameter types</param>
2003 /// <returns>a descriptor for this method</returns>
2004 public MethodRef AddVarArgMethod(string name, Type retType,
2005 Type[] pars, Type[] optPars)
2007 MethodRef meth = new MethodRef(this,name,retType,pars,true,optPars, 0);
2008 metaData.AddToTable(MDTable.MemberRef,meth);
2013 /// Add a field to this class
2015 /// <param name="name">field name</param>
2016 /// <param name="fType">field type</param>
2017 /// <returns>a descriptor for this field</returns>
2018 public FieldRef AddField(string name, Type fType)
2020 FieldRef field = new FieldRef(this,name,fType);
2021 metaData.AddToTable(MDTable.MemberRef,field);
2025 public ClassRef AddClass (string nsName, string name)
2027 ClassRef aClass = new ClassRef(nsName,name,metaData);
2028 metaData.AddToTable(MDTable.TypeRef,aClass);
2029 aClass.SetParent(this);
2033 public ClassRef AddValueClass (string nsName, string name)
2035 ClassRef aClass = AddClass (nsName, name);
2036 aClass.MakeValueClass (ValueClass.ValueType);
2040 internal void SetParent(IResolutionScope par)
2045 internal override string TypeName()
2047 if ((parent != null) && (parent is AssemblyRef))
2048 return (nameSpace + "." + name + ", " + ((AssemblyRef)parent).TypeName());
2050 return (nameSpace + name);
2053 internal sealed override uint Size(MetaData md)
2055 return md.CodedIndexSize(CIx.ResolutionScope) + 2 *
2056 md.StringsIndexSize();
2059 internal sealed override void Write(FileImage output)
2061 output.WriteCodedIndex(CIx.ResolutionScope,(MetaDataElement) parent);
2062 output.StringsIndex(nameIx);
2063 output.StringsIndex(nameSpaceIx);
2066 internal override sealed uint TypeDefOrRefToken()
2069 cIx = (cIx << 2) | 0x1;
2073 internal override void TypeSig(MemoryStream sig)
2075 sig.WriteByte(GetTypeIndex());
2076 MetaData.CompressNum(TypeDefOrRefToken(),sig);
2079 internal sealed override uint GetCodedIx(CIx code)
2082 case (CIx.TypeDefOrRef) : return 1;
2083 case (CIx.HasCustomAttr) : return 2;
2084 case (CIx.MemberRefParent) : return 1;
2085 case (CIx.ResolutionScope) : return 3;
2092 /**************************************************************************/
2093 public class ExternClassRef : ClassRef {
2095 ExternClass externClass;
2097 internal ExternClassRef(TypeAttr attrs, string nsName, string name,
2098 MetaDataElement declRef, MetaData md) : base(nsName,name,md)
2100 externClass = new ExternClass(attrs,nameSpaceIx,nameIx,declRef);
2101 metaData.AddToTable(MDTable.ExportedType,externClass);
2104 internal ExternClassRef(string name, MetaData md) : base(null,name,md)
2108 public ClassRef AddNestedClass(TypeAttr attrs, string name)
2110 ExternClassRef nestedClass = new ExternClassRef(name,metaData);
2111 externClass = new ExternClass(attrs,0,nameIx,this.externClass);
2112 metaData.AddToTable(MDTable.ExportedType,externClass);
2118 /**************************************************************************/
2120 /// Descriptor for a class defined in another module of THIS assembly
2121 /// and exported (.class extern)
2124 internal class ExternClass : Class {
2126 MetaDataElement parent;
2129 internal ExternClass(TypeAttr attr, uint nsIx, uint nIx,
2130 MetaDataElement paren) : base(nsIx,nIx)
2134 tabIx = MDTable.ExportedType;
2137 internal sealed override uint Size(MetaData md)
2139 return 8 + 2* md.StringsIndexSize() + md.CodedIndexSize(CIx.Implementation);
2142 internal sealed override void Write(FileImage output)
2144 output.Write(flags);
2146 output.StringsIndex(nameIx);
2147 output.StringsIndex(nameSpaceIx);
2148 output.WriteCodedIndex(CIx.Implementation,parent);
2151 internal sealed override uint GetCodedIx(CIx code)
2154 case (CIx.HasCustomAttr) : return 17;
2155 case (CIx.Implementation) : return 2;
2162 public class GenParam : Class {
2165 private string param_name;
2166 private uint sigIx = 0;
2168 public GenParam (int index, string name, GenParamType ptype) : base ((byte) ptype)
2171 this.param_name = name;
2172 tabIx = MDTable.TypeSpec;
2176 get { return index; }
2177 set { index = value; }
2180 public string Name {
2181 get { return param_name; }
2182 set { param_name = value; }
2185 public GenParamType Type {
2186 get { return (GenParamType) GetTypeIndex (); }
2189 internal sealed override void BuildTables (MetaData md)
2193 MemoryStream str = new MemoryStream ();
2195 sigIx = md.AddToBlobHeap (str.ToArray ());
2200 internal sealed override void TypeSig(MemoryStream str)
2203 throw new PEFileException (String.Format ("Unresolved {0} - {1}", (GenParamType) GetTypeIndex (), param_name));
2204 str.WriteByte(typeIndex);
2205 MetaData.CompressNum ((uint) index, str);
2208 internal override uint Size(MetaData md)
2210 return md.BlobIndexSize();
2213 internal sealed override void Write (FileImage output)
2215 output.BlobIndex (sigIx);
2218 internal sealed override uint GetCodedIx(CIx code)
2221 case (CIx.TypeDefOrRef) : return 2;
2222 case (CIx.HasCustomAttr) : return 13;
2223 case (CIx.MemberRefParent) : return 4;
2229 public class GenericTypeInst : Class {
2231 private Type gen_type;
2232 private Type[] gen_param;
2233 bool inTable = false;
2236 public GenericTypeInst (Type gen_type, Type[] gen_param)
2237 : base ((byte) PrimitiveType.GenericInst.GetTypeIndex ())
2239 this.gen_type = gen_type;
2240 this.gen_param = gen_param;
2241 tabIx = MDTable.TypeSpec;
2244 internal override MetaDataElement GetTypeSpec (MetaData md)
2247 md.AddToTable (MDTable.TypeSpec, this);
2254 internal sealed override void TypeSig(MemoryStream str)
2256 str.WriteByte(typeIndex);
2257 gen_type.TypeSig (str);
2258 MetaData.CompressNum ((uint) gen_param.Length, str);
2259 foreach (Type param in gen_param)
2260 param.TypeSig (str);
2263 internal sealed override void BuildTables (MetaData md)
2267 MemoryStream str = new MemoryStream ();
2269 sigIx = md.AddToBlobHeap (str.ToArray ());
2274 internal sealed override uint Size (MetaData md)
2276 return md.BlobIndexSize ();
2279 internal sealed override void Write (FileImage output)
2281 output.BlobIndex (sigIx);
2284 internal sealed override uint GetCodedIx (CIx code)
2287 case (CIx.TypeDefOrRef): return 2;
2288 case (CIx.MemberRefParent): return 4;
2289 case (CIx.HasCustomAttr): return 13;
2295 public class GenericMethodSig {
2297 private Type[] gen_param;
2299 private uint sigIx = 0;
2301 public GenericMethodSig (Type[] gen_param)
2303 this.gen_param = gen_param;
2307 internal void TypeSig (MemoryStream str)
2309 str.WriteByte (0x0A); /* GENERIC_INST */
2310 MetaData.CompressNum ((uint) gen_param.Length, str);
2311 foreach (Type param in gen_param)
2312 param.TypeSig (str);
2315 internal uint GetSigIx (MetaData md)
2320 MemoryStream sig = new MemoryStream();
2322 sigIx = md.AddToBlobHeap (sig.ToArray());
2328 public class Sentinel : Type {
2330 public Sentinel () : base (0x41) { }
2332 internal sealed override void TypeSig(MemoryStream str)
2334 str.WriteByte(typeIndex);
2338 /**************************************************************************/
2340 /// Descriptor for a FunctionPointer type
2343 public class MethPtrType : Type {
2355 /// Create a new function pointer type
2357 /// <param name="meth">the function to be referenced</param>
2358 public MethPtrType (CallConv callconv, Type retType, Type[] pars,
2359 bool varArgMeth, Type[] optPars) : base(0x1B)
2361 this.retType = retType;
2362 callConv = callconv;
2364 this.varArgMeth = varArgMeth;
2365 if (parList != null) numPars = (uint)parList.Length;
2367 optParList = optPars;
2368 if (optParList != null) numOptPars = (uint)optParList.Length;
2369 callConv |= CallConv.Vararg;
2371 tabIx = MDTable.TypeSpec;
2374 internal sealed override void TypeSig(MemoryStream sig)
2376 sig.WriteByte(typeIndex);
2377 // Bootlegged from method ref
2378 sig.WriteByte((byte)callConv);
2379 MetaData.CompressNum (numPars + numOptPars, sig);
2380 retType.TypeSig (sig);
2381 for (int i=0; i < numPars; i++) {
2382 parList[i].TypeSig (sig);
2385 sig.WriteByte (0x41); // Write the sentinel
2386 for (int i=0; i < numOptPars; i++) {
2387 optParList[i].TypeSig (sig);
2392 internal sealed override void BuildTables(MetaData md)
2395 MemoryStream sig = new MemoryStream();
2397 sigIx = md.AddToBlobHeap(sig.ToArray());
2401 internal sealed override uint Size(MetaData md)
2403 return md.BlobIndexSize();
2406 internal sealed override void Write(FileImage output)
2408 output.BlobIndex(sigIx);
2411 internal sealed override uint GetCodedIx(CIx code) { return 0x1B; }
2416 /* Classes for Arrays */
2419 /// The IL Array type
2421 public abstract class Array : Type {
2423 protected Type elemType;
2424 protected MetaData metaData;
2425 protected string cnameSpace, cname;
2427 internal Array(Type eType, byte TypeId) : base(TypeId)
2430 tabIx = MDTable.TypeSpec;
2435 /// Single dimensional array with zero lower bound
2437 public class ZeroBasedArray : Array {
2440 /// Create a new array - elementType[]
2442 /// <param name="elementType">the type of the array elements</param>
2443 public ZeroBasedArray(Type elementType) : base (elementType, PrimitiveType.SZArray.GetTypeIndex ()) { }
2445 internal sealed override void TypeSig(MemoryStream str)
2447 str.WriteByte(typeIndex);
2448 elemType.TypeSig(str);
2454 /// Multi dimensional array with explicit bounds
2456 public class BoundArray : Array {
2462 /// Create a new multi dimensional array type
2463 /// eg. elemType[1..5,3..10,5,,] would be
2464 /// new BoundArray(elemType,5,[1,3,0],[5,10,4])
2466 /// <param name="elementType">the type of the elements</param>
2467 /// <param name="dimensions">the number of dimensions</param>
2468 /// <param name="loBounds">lower bounds of dimensions</param>
2469 /// <param name="sizes">sizes for the dimensions</param>
2470 public BoundArray(Type elementType, uint dimensions, int[] loBounds,
2471 int[] sizes) : base (elementType,0x14)
2473 numDims = dimensions;
2474 lowerBounds = loBounds;
2479 /// Create a new multi dimensional array type
2480 /// eg. elemType[5,10,20] would be new BoundArray(elemType,3,[5,10,20])
2482 /// <param name="elementType">the type of the elements</param>
2483 /// <param name="dimensions">the number of dimensions</param>
2484 /// <param name="size">the sizes of the dimensions</param>
2485 public BoundArray(Type elementType, uint dimensions, int[] size)
2486 : base (elementType,0x14)
2488 numDims = dimensions;
2493 /// Create a new multi dimensional array type
2494 /// eg. elemType[,,] would be new BoundArray(elemType,3)
2496 /// <param name="elementType">the type of the elements</param>
2497 /// <param name="dimensions">the number of dimensions</param>
2498 public BoundArray(Type elementType, uint dimensions)
2499 : base (elementType,0x14)
2501 numDims = dimensions;
2504 internal sealed override void TypeSig(MemoryStream str)
2506 str.WriteByte(typeIndex);
2507 elemType.TypeSig(str);
2508 MetaData.CompressNum(numDims,str);
2509 if ((sizes != null) && (sizes.Length > 0)) {
2511 MetaData.CompressNum((uint)sizes.Length,str);
2512 for (int i=0; i < sizes.Length; i++) {
2513 MetaData.CompressNum((uint)sizes[i],str);
2515 } else str.WriteByte(0);
2516 if ((lowerBounds != null) && (lowerBounds.Length > 0)) {
2517 MetaData.CompressNum((uint)lowerBounds.Length,str);
2518 for (int i=0; i < lowerBounds.Length; i++) {
2519 CompressSignedNum (lowerBounds[i],str);
2521 } else str.WriteByte(0);
2523 private void CompressSignedNum (int val, MemoryStream str)
2525 uint uval = (uint) val;
2532 /* Map the signed number to an unsigned number in two ways.
2534 fval: left-rotated 2's complement representation
2535 sval: map the signed number to unsigned as follows: 0 -> 0, -1 -> 1, 1 -> 2, -2 -> 3, 2 -> 4, ....
2536 the mapping is: x -> 2*|x| - signbit(x)
2538 uint fval = (uval << 1) | sign;
2539 int sval = (val << 1) - sign;
2541 /* An overly clever transformation:
2543 a. sval is used to determine the number of bytes in the compressed representation.
2544 b. fval is truncated to the appropriate number of bits and output using the
2545 normal unsigned-int compressor.
2547 However, or certain values, the truncated fval doesn't carry enough information to round trip.
2549 (fval & 0x3FFF) <= 0x7F => compressor emits 1 byte, not 2 => there is aliasing of values
2551 So, we use full 4 bytes to encode such values.
2553 LAMESPEC: The Microsoft implementation doesn't appear to handle this subtle case.
2554 e.g., it ends up encoding -8192 as the byte 0x01, which decodes to -64
2557 MetaData.CompressNum (fval & 0x7F, str);
2558 else if (sval <= 0x3FFF && (fval & 0x3FFF) > 0x7F)
2559 MetaData.CompressNum (fval & 0x3FFF, str);
2560 else if (sval <= 0x1FFFFFFF && (fval & 0x1FFFFFFF) > 0x3FFF)
2561 MetaData.CompressNum (fval & 0x1FFFFFFF, str);
2563 /* FIXME: number cannot be represented. Report a warning. */
2564 // throw new Exception ("cannot represent signed value" + -val);
2565 MetaData.CompressNum (fval, str);
2572 /* Empty interface for grouping TypeRef's possible ResolutionScope
2573 namely : Module, ModuleRef, AssemblyRef and TypeRef */
2574 public interface IResolutionScope {
2577 /**************************************************************************/
2579 /// Base class for scopes (extended by Module, ModuleRef, Assembly, AssemblyRef)
2581 public abstract class ResolutionScope : MetaDataElement, IResolutionScope {
2583 protected uint nameIx = 0;
2584 protected MetaData metaData;
2585 protected string name;
2587 internal ResolutionScope(string name, MetaData md)
2591 nameIx = md.AddToStringsHeap(name);
2594 internal string GetName() { return name; }
2598 /**************************************************************************/
2600 /// Descriptor for THIS assembly (.assembly)
2602 public class Assembly : ResolutionScope {
2604 ushort majorVer, minorVer, buildNo, revisionNo;
2607 uint keyIx = 0, cultIx = 0;
2608 bool hasPublicKey = false;
2610 internal Assembly(string name, MetaData md) : base(name,md)
2612 tabIx = MDTable.Assembly;
2616 /// Add details about THIS assembly
2618 /// <param name="majVer">Major Version</param>
2619 /// <param name="minVer">Minor Version</param>
2620 /// <param name="bldNo">Build Number</param>
2621 /// <param name="revNo">Revision Number</param>
2622 /// <param name="key">Hash Key</param>
2623 /// <param name="hash">Hash Algorithm</param>
2624 /// <param name="cult">Culture</param>
2625 public void AddAssemblyInfo(int majVer, int minVer, int bldNo, int revNo,
2626 byte[] key, uint hash, string cult)
2628 majorVer = (ushort)majVer;
2629 minorVer = (ushort)minVer;
2630 buildNo = (ushort)bldNo;
2631 revisionNo = (ushort)revNo;
2633 hasPublicKey = (key != null);
2634 keyIx = metaData.AddToBlobHeap(key);
2635 cultIx = metaData.AddToStringsHeap(cult);
2639 /// Add an attribute to THIS assembly
2641 /// <param name="aa">assembly attribute</param>
2642 public void AddAssemblyAttr(AssemAttr aa)
2647 internal sealed override uint Size(MetaData md)
2649 return 16 + md.BlobIndexSize() + 2 * md.StringsIndexSize();
2652 internal sealed override void Write(FileImage output)
2654 // Console.WriteLine("Writing assembly element with nameIx of " + nameIx + " at file offset " + output.Seek(0,SeekOrigin.Current));
2655 output.Write((uint)hashAlgId);
2656 output.Write(majorVer);
2657 output.Write(minorVer);
2658 output.Write(buildNo);
2659 output.Write(revisionNo);
2660 output.Write(flags);
2661 output.BlobIndex(keyIx);
2662 output.StringsIndex(nameIx);
2663 output.StringsIndex(cultIx);
2666 internal sealed override uint GetCodedIx(CIx code)
2669 case (CIx.HasCustomAttr) : return 14;
2670 case (CIx.HasDeclSecurity) : return 2;
2675 internal bool HasPublicKey {
2676 get { return hasPublicKey; }
2680 /**************************************************************************/
2682 /// Descriptor for THIS module
2684 public class Module : ResolutionScope, IExternRef {
2689 internal Module(string name, MetaData md) : base(name,md)
2691 mvid = Guid.NewGuid();
2692 mvidIx = md.AddToGUIDHeap(mvid);
2693 tabIx = MDTable.Module;
2697 get { return mvid; }
2700 public ClassRef AddClass(string nsName, string name)
2702 ClassRef aClass = new ClassRef (nsName, name, metaData);
2703 metaData.AddToTable (MDTable.TypeRef, aClass);
2704 aClass.SetParent (this);
2708 public ClassRef AddValueClass(string nsName, string name)
2710 ClassRef aClass = AddClass (nsName, name);
2711 aClass.MakeValueClass (ValueClass.ValueType);
2715 internal sealed override uint Size(MetaData md)
2717 return 2 + md.StringsIndexSize() + 3 * md.GUIDIndexSize();
2720 internal sealed override void Write(FileImage output)
2722 output.Write((short)0);
2723 output.StringsIndex(nameIx);
2724 output.GUIDIndex(mvidIx);
2725 output.GUIDIndex(0);
2726 output.GUIDIndex(0);
2729 internal sealed override uint GetCodedIx(CIx code)
2732 case (CIx.HasCustomAttr) : return 7;
2733 case (CIx.ResolutionScope) : return 0;
2738 /**************************************************************************/
2740 /// Descriptor for another module in THIS assembly
2742 public class ModuleRef : ResolutionScope, IExternRef {
2744 internal ModuleRef(MetaData md, string name) : base(name,md)
2746 tabIx = MDTable.ModuleRef;
2750 /// Add a class to this external module. This is a class declared in
2751 /// another module of THIS assembly.
2753 /// <param name="nsName">name space name</param>
2754 /// <param name="name">class name</param>
2755 /// <returns>a descriptor for this class in another module</returns>
2756 public ClassRef AddClass(string nsName, string name)
2758 ClassRef aClass = new ClassRef(nsName,name,metaData);
2759 metaData.AddToTable(MDTable.TypeRef,aClass);
2760 aClass.SetParent(this);
2765 /// Make a file descriptor to correspond to this module. The file
2766 /// descriptor will have the same name as the module descriptor
2768 /// <param name="hashBytes">the hash of the file</param>
2769 /// <param name="hasMetaData">the file contains metadata</param>
2770 /// <param name="entryPoint">the program entry point is in this file</param>
2771 /// <returns>a descriptor for the file which contains this module</returns>
2772 public FileRef MakeFile(byte[] hashBytes, bool hasMetaData, bool entryPoint)
2774 FileRef file = new FileRef(nameIx,hashBytes,hasMetaData,entryPoint,metaData);
2775 metaData.AddToTable(MDTable.File,file);
2780 /// Add a value class to this module. This is a class declared in
2781 /// another module of THIS assembly.
2783 /// <param name="nsName">name space name</param>
2784 /// <param name="name">class name</param>
2785 /// <returns></returns>
2786 public ClassRef AddValueClass(string nsName, string name)
2788 ClassRef aClass = new ClassRef(nsName,name,metaData);
2789 metaData.AddToTable(MDTable.TypeRef,aClass);
2790 aClass.SetParent(this);
2791 aClass.MakeValueClass(ValueClass.ValueType);
2796 /// Add a class which is declared public in this external module of
2797 /// THIS assembly. This class will be exported from this assembly.
2798 /// The ilasm syntax for this is .extern class
2800 /// <param name="attrSet">attributes of the class to be exported</param>
2801 /// <param name="nsName">name space name</param>
2802 /// <param name="name">external class name</param>
2803 /// <param name="declFile">the file where the class is declared</param>
2804 /// <param name="isValueClass">is this class a value type?</param>
2805 /// <returns>a descriptor for this external class</returns>
2806 public ExternClassRef AddExternClass(TypeAttr attrSet, string nsName,
2807 string name, FileRef declFile,
2808 bool isValueClass) {
2809 ExternClassRef cRef = new ExternClassRef(attrSet,nsName,name,declFile,metaData);
2810 metaData.AddToTable(MDTable.TypeRef,cRef);
2811 cRef.SetParent(this);
2812 if (isValueClass) cRef.MakeValueClass(ValueClass.ValueType);
2817 /// Add a "global" method in another module
2819 /// <param name="name">method name</param>
2820 /// <param name="retType">return type</param>
2821 /// <param name="pars">method parameter types</param>
2822 /// <returns>a descriptor for this method in anther module</returns>
2823 public MethodRef AddMethod(string name, Type retType, Type[] pars)
2825 MethodRef meth = new MethodRef(this,name,retType,pars,false,null, 0);
2826 metaData.AddToTable(MDTable.MemberRef,meth);
2831 /// Add a vararg method to this class
2833 /// <param name="name">method name</param>
2834 /// <param name="retType">return type</param>
2835 /// <param name="pars">parameter types</param>
2836 /// <param name="optPars">optional param types for this vararg method</param>
2837 /// <returns>a descriptor for this method</returns>
2838 public MethodRef AddVarArgMethod(string name, Type retType,
2839 Type[] pars, Type[] optPars) {
2840 MethodRef meth = new MethodRef(this,name,retType,pars,true,optPars, 0);
2841 metaData.AddToTable(MDTable.MemberRef,meth);
2846 /// Add a field in another module
2848 /// <param name="name">field name</param>
2849 /// <param name="fType">field type</param>
2850 /// <returns>a descriptor for this field in another module</returns>
2851 public FieldRef AddField(string name, Type fType)
2853 FieldRef field = new FieldRef(this,name,fType);
2854 metaData.AddToTable(MDTable.MemberRef,field);
2858 internal sealed override uint Size(MetaData md)
2860 return md.StringsIndexSize();
2863 internal sealed override void Write(FileImage output)
2865 output.StringsIndex(nameIx);
2868 internal sealed override uint GetCodedIx(CIx code)
2871 case (CIx.HasCustomAttr) : return 12;
2872 case (CIx.MemberRefParent) : return 2;
2873 case (CIx.ResolutionScope) : return 1;
2880 #region Classes for Constants
2882 /// Descriptor for a constant value
2884 public abstract class Constant {
2885 protected uint size = 0;
2886 protected Type type;
2887 protected uint blobIndex;
2888 protected bool addedToBlobHeap = false;
2890 internal Constant() { }
2892 internal virtual uint GetBlobIndex(MetaData md) { return 0; }
2894 internal uint GetSize() { return size; }
2896 internal byte GetTypeIndex() { return type.GetTypeIndex(); }
2898 internal virtual void Write(BinaryWriter bw) { }
2902 /// Descriptor for a constant value
2904 public abstract class DataConstant : Constant {
2905 private uint dataOffset = 0;
2907 internal DataConstant() { }
2909 public uint DataOffset {
2910 get { return dataOffset; }
2911 set { dataOffset = value; }
2917 /// Boolean constant
2919 public class BoolConst : Constant {
2923 /// Create a new boolean constant with the value "val"
2925 /// <param name="val">value of this boolean constant</param>
2926 public BoolConst(bool val)
2930 type = PrimitiveType.Boolean;
2933 internal sealed override uint GetBlobIndex(MetaData md)
2935 if (!addedToBlobHeap) {
2936 if (val) blobIndex = md.AddToBlobHeap((sbyte)1);
2937 else blobIndex = md.AddToBlobHeap((sbyte)0);
2938 addedToBlobHeap = true;
2943 internal sealed override void Write(BinaryWriter bw)
2945 if (val) bw.Write((sbyte)1);
2946 else bw.Write((sbyte)0);
2951 public class ByteArrConst : DataConstant {
2952 internal byte[] val;
2954 public ByteArrConst(byte[] val)
2956 type = PrimitiveType.String;
2958 size = (uint)val.Length;
2962 get { return type; }
2963 set { type = value; }
2966 internal sealed override uint GetBlobIndex(MetaData md)
2968 if (!addedToBlobHeap) {
2969 blobIndex = md.AddToBlobHeap(val);
2970 addedToBlobHeap = true;
2975 internal sealed override void Write(BinaryWriter bw)
2982 public class CharConst : Constant {
2985 public CharConst(char val)
2989 type = PrimitiveType.Char;
2992 internal sealed override uint GetBlobIndex(MetaData md)
2994 if (!addedToBlobHeap) {
2995 blobIndex = md.AddToBlobHeap(val);
2996 addedToBlobHeap = true;
3001 internal sealed override void Write(BinaryWriter bw)
3008 public class FloatConst : DataConstant {
3011 public FloatConst(float val)
3015 type = PrimitiveType.Float32;
3018 internal sealed override uint GetBlobIndex(MetaData md)
3020 if (!addedToBlobHeap) {
3021 blobIndex = md.AddToBlobHeap(val);
3022 addedToBlobHeap = true;
3027 internal sealed override void Write(BinaryWriter bw)
3034 public class DoubleConst : DataConstant {
3037 public DoubleConst(double val)
3041 type = PrimitiveType.Float64;
3044 internal sealed override uint GetBlobIndex(MetaData md)
3046 if (!addedToBlobHeap) {
3047 blobIndex = md.AddToBlobHeap(val);
3048 addedToBlobHeap = true;
3053 internal sealed override void Write(BinaryWriter bw)
3060 public class IntConst : DataConstant {
3063 public IntConst(sbyte val)
3067 type = PrimitiveType.Int8;
3070 public IntConst(short val)
3074 type = PrimitiveType.Int16;
3077 public IntConst(int val)
3081 type = PrimitiveType.Int32;
3084 public IntConst(long val)
3088 type = PrimitiveType.Int64;
3091 internal sealed override uint GetBlobIndex(MetaData md)
3093 if (!addedToBlobHeap) {
3095 case (1) : blobIndex = md.AddToBlobHeap((sbyte)val); break;
3096 case (2) : blobIndex = md.AddToBlobHeap((short)val); break;
3097 case (4) : blobIndex = md.AddToBlobHeap((int)val); break;
3098 default : blobIndex = md.AddToBlobHeap(val); break;
3100 addedToBlobHeap = true;
3105 internal sealed override void Write(BinaryWriter bw)
3108 case (1) : bw.Write((sbyte)val); break;
3109 case (2) : bw.Write((short)val); break;
3110 case (4) : bw.Write((int)val); break;
3111 default : bw.Write(val); break;
3117 public class UIntConst : Constant {
3120 public UIntConst(byte val)
3124 type = PrimitiveType.UInt8;
3126 public UIntConst(ushort val)
3130 type = PrimitiveType.UInt16;
3132 public UIntConst(uint val)
3136 type = PrimitiveType.UInt32;
3138 public UIntConst(ulong val)
3142 type = PrimitiveType.UInt64;
3145 internal sealed override uint GetBlobIndex(MetaData md)
3147 if (!addedToBlobHeap) {
3149 case (1) : blobIndex = md.AddToBlobHeap((byte)val); break;
3150 case (2) : blobIndex = md.AddToBlobHeap((ushort)val); break;
3151 case (4) : blobIndex = md.AddToBlobHeap((uint)val); break;
3152 default : blobIndex = md.AddToBlobHeap(val); break;
3154 addedToBlobHeap = true;
3159 internal sealed override void Write(BinaryWriter bw)
3162 case (1) : bw.Write((byte)val); break;
3163 case (2) : bw.Write((ushort)val); break;
3164 case (4) : bw.Write((uint)val); break;
3165 default : bw.Write(val); break;
3171 public class StringConst : DataConstant {
3174 public StringConst(string val)
3177 size = (uint)val.Length; // need to add null ??
3178 type = PrimitiveType.String;
3181 internal sealed override uint GetBlobIndex(MetaData md)
3183 if (!addedToBlobHeap) {
3184 byte [] b = Encoding.Unicode.GetBytes (val);
3185 blobIndex = md.AddToBlobHeap(b);
3186 addedToBlobHeap = true;
3191 internal sealed override void Write(BinaryWriter bw)
3198 public class NullConst : Constant {
3203 type = PrimitiveType.Class;
3206 internal sealed override uint GetBlobIndex(MetaData md)
3208 if (!addedToBlobHeap) {
3209 blobIndex = md.AddToBlobHeap((int)0);
3210 addedToBlobHeap = true;
3215 internal sealed override void Write(BinaryWriter bw)
3222 public class AddressConstant : DataConstant {
3225 public AddressConstant(DataConstant dConst)
3229 type = PrimitiveType.TypedRef;
3232 internal sealed override void Write(BinaryWriter bw)
3234 ((FileImage)bw).WriteDataRVA(data.DataOffset);
3239 public class RepeatedConstant : DataConstant {
3243 public RepeatedConstant(DataConstant dConst, int repeatCount)
3246 repCount = (uint)repeatCount;
3247 int[] sizes = new int[1];
3248 sizes[0] = repeatCount;
3249 type = new BoundArray(type,1,sizes);
3250 size = data.GetSize() * repCount;
3253 internal sealed override void Write(BinaryWriter bw)
3255 for (int i=0; i < repCount; i++) {
3262 public class ArrayConstant : DataConstant {
3263 DataConstant[] dataVals;
3265 public ArrayConstant(DataConstant[] dVals)
3268 for (int i=0; i < dataVals.Length; i++) {
3269 size += dataVals[i].GetSize();
3273 internal sealed override void Write(BinaryWriter bw)
3275 for (int i=0; i < dataVals.Length; i++) {
3276 dataVals[i].Write(bw);
3282 public class ClassType : Constant {
3286 public ClassType(string className)
3289 type = PrimitiveType.ClassType;
3292 public ClassType(Class classDesc)
3295 type = PrimitiveType.ClassType;
3298 internal override void Write(BinaryWriter bw)
3300 if (name == null) name = desc.TypeName();
3308 /**************************************************************************/
3310 /// Descriptor for a custom modifier of a type (modopt or modreq)
3313 public class CustomModifiedType : Type {
3317 PrimitiveTypeRef cmodPrimType;
3320 /// Create a new custom modifier for a type
3322 /// <param name="type">the type to be modified</param>
3323 /// <param name="cmod">the modifier</param>
3324 /// <param name="cmodType">the type reference to be associated with the type</param>
3325 public CustomModifiedType(Type type, CustomModifier cmod, Class cmodType)
3329 this.cmodType = cmodType;
3332 public CustomModifiedType(Type type, CustomModifier cmod, PrimitiveTypeRef cmodType)
3336 this.cmodPrimType = cmodType;
3339 internal sealed override void TypeSig(MemoryStream str)
3341 str.WriteByte(typeIndex);
3343 if (cmodType != null) {
3344 MetaData.CompressNum(cmodType.TypeDefOrRefToken(),str);
3346 MetaData.CompressNum(cmodPrimType.TypeDefOrRefToken(),str);
3354 /**************************************************************************/
3356 /// Base class for Event and Property descriptors
3359 public class Feature : MetaDataElement {
3361 internal enum MethodType : ushort { Setter = 0x01, Getter, Other = 0x04, AddOn = 0x08,
3362 RemoveOn = 0x10, Fire = 0x20 }
3364 private static readonly int INITSIZE = 5;
3365 private static readonly ushort specialName = 0x200;
3366 private static readonly ushort rtSpecialName = 0x400;
3368 protected ClassDef parent;
3369 protected ushort flags = 0;
3370 protected string name;
3371 protected int tide = 0;
3372 protected uint nameIx;
3373 protected MethodSemantics[] methods = new MethodSemantics[INITSIZE];
3375 internal Feature(string name, ClassDef par)
3381 internal void AddMethod(MethodDef meth, MethodType mType)
3383 if (tide >= methods.Length) {
3384 int len = methods.Length;
3385 MethodSemantics[] mTmp = methods;
3386 methods = new MethodSemantics[len * 2];
3387 for (int i=0; i < len; i++) {
3388 methods[i] = mTmp[i];
3391 methods[tide++] = new MethodSemantics(mType,meth,this);
3395 /// Set the specialName attribute for this Event or Property
3397 public void SetSpecialName()
3399 flags |= specialName;
3403 /// Set the RTSpecialName attribute for this Event or Property
3405 public void SetRTSpecialName()
3407 flags |= rtSpecialName;
3412 /**************************************************************************/
3414 /// Descriptor for an event
3416 public class Event : Feature {
3420 internal Event(string name, Type eType, ClassDef parent)
3421 : base(name, parent)
3424 tabIx = MDTable.Event;
3428 /// Add the addon method to this event
3430 /// <param name="addon">the addon method</param>
3431 public void AddAddon(MethodDef addon)
3433 AddMethod(addon,MethodType.AddOn);
3437 /// Add the removeon method to this event
3439 /// <param name="removeOn">the removeon method</param>
3440 public void AddRemoveOn(MethodDef removeOn)
3442 AddMethod(removeOn,MethodType.RemoveOn);
3446 /// Add the fire method to this event
3448 /// <param name="fire">the fire method</param>
3449 public void AddFire(MethodDef fire)
3451 AddMethod(fire,MethodType.Fire);
3455 /// Add another method to this event
3457 /// <param name="other">the method to be added</param>
3458 public void AddOther(MethodDef other)
3460 AddMethod(other,MethodType.Other);
3463 internal sealed override void BuildTables(MetaData md)
3466 nameIx = md.AddToStringsHeap(name);
3467 for (int i=0; i < tide; i++) {
3468 md.AddToTable(MDTable.MethodSemantics,methods[i]);
3473 internal sealed override uint Size(MetaData md)
3475 return 2 + md.StringsIndexSize() + md.CodedIndexSize(CIx.TypeDefOrRef);
3478 internal sealed override void Write(FileImage output)
3480 output.Write(flags);
3481 output.StringsIndex(nameIx);
3482 output.WriteCodedIndex(CIx.TypeDefOrRef,eventType);
3485 internal sealed override uint GetCodedIx(CIx code)
3488 case (CIx.HasCustomAttr) : return 10;
3489 case (CIx.HasSemantics) : return 0;
3496 /**************************************************************************/
3498 /// Descriptor for the Property of a class
3500 public class Property : Feature {
3502 private static readonly byte PropertyTag = 0x8;
3503 private bool instance;
3504 MethodDef getterMeth;
3505 ConstantElem constVal;
3506 uint typeBlobIx = 0;
3511 internal Property(string name, Type retType, Type[] pars, ClassDef parent) : base(name, parent)
3513 returnType = retType;
3515 if (pars != null) numPars = (uint)pars.Length;
3516 tabIx = MDTable.Property;
3520 /// Add a set method to this property
3522 /// <param name="setter">the set method</param>
3523 public void AddSetter(MethodDef setter)
3525 AddMethod(setter,MethodType.Setter);
3529 /// Add a get method to this property
3531 /// <param name="getter">the get method</param>
3532 public void AddGetter(MethodDef getter)
3534 AddMethod(getter,MethodType.Getter);
3535 getterMeth = getter;
3539 /// Add another method to this property
3541 /// <param name="other">the method</param>
3542 public void AddOther(MethodDef other)
3544 AddMethod(other,MethodType.Other);
3548 /// Add an initial value for this property
3550 /// <param name="constVal">the initial value for this property</param>
3551 public void AddInitValue(Constant constVal)
3553 this.constVal = new ConstantElem(this,constVal);
3556 public void SetInstance (bool isInstance)
3558 this.instance = isInstance;
3561 internal sealed override void BuildTables(MetaData md)
3564 nameIx = md.AddToStringsHeap(name);
3565 MemoryStream sig = new MemoryStream();
3566 byte tag = PropertyTag;
3570 MetaData.CompressNum(numPars,sig);
3571 returnType.TypeSig(sig);
3572 for (int i=0; i < numPars; i++) {
3573 parList[i].TypeSig(sig);
3575 typeBlobIx = md.AddToBlobHeap(sig.ToArray());
3576 for (int i=0; i < tide; i++) {
3577 md.AddToTable(MDTable.MethodSemantics,methods[i]);
3579 if (constVal != null) {
3580 md.AddToTable(MDTable.Constant,constVal);
3581 constVal.BuildTables(md);
3586 internal sealed override uint Size(MetaData md)
3588 return 2 + md.StringsIndexSize() + md.BlobIndexSize();
3591 internal sealed override void Write(FileImage output)
3593 output.Write(flags);
3594 output.StringsIndex(nameIx);
3595 output.BlobIndex(typeBlobIx);
3598 internal sealed override uint GetCodedIx(CIx code)
3601 case (CIx.HasCustomAttr) : return 9;
3602 case (CIx.HasConst) : return 2;
3603 case (CIx.HasSemantics) : return 1;
3610 /**************************************************************************/
3612 /// Base class for field/methods (member of a class)
3614 public abstract class Member : MetaDataElement {
3616 protected string name;
3617 protected uint nameIx = 0, sigIx = 0;
3619 internal Member(string memName)
3622 tabIx = MDTable.MemberRef;
3627 /*****************************************************************************/
3629 /// Descriptor for a field of a class
3632 public abstract class Field : Member {
3634 protected static readonly byte FieldSig = 0x6;
3636 protected Type type;
3638 internal Field(string pfName, Type pfType) : base(pfName)
3644 /**************************************************************************/
3646 /// Descriptor for a field defined in a class of THIS assembly/module
3648 public class FieldDef : Field {
3650 //private static readonly uint PInvokeImpl = 0x2000;
3651 private static readonly ushort HasFieldRVA = 0x100;
3652 private static readonly ushort HasDefault = 0x8000;
3655 ConstantElem constVal;
3657 FieldMarshal marshalInfo;
3660 internal FieldDef(string name, Type fType) : base(name,fType)
3662 tabIx = MDTable.Field;
3665 internal FieldDef(FieldAttr attrSet, string name, Type fType) : base(name, fType)
3667 flags = (ushort)attrSet;
3668 tabIx = MDTable.Field;
3672 /// Add an attribute(s) to this field
3674 /// <param name="fa">the attribute(s) to be added</param>
3675 public void AddFieldAttr(FieldAttr fa)
3677 flags |= (ushort)fa;
3681 /// Add a value for this field
3683 /// <param name="val">the value for the field</param>
3684 public void AddValue(Constant val)
3686 constVal = new ConstantElem(this,val);
3687 flags |= HasDefault;
3691 /// Add an initial value for this field (at dataLabel) (.data)
3693 /// <param name="val">the value for the field</param>
3694 /// <param name="repeatVal">the number of repetitions of this value</param>
3695 public void AddDataValue(DataConstant val)
3697 flags |= HasFieldRVA;
3698 rva = new FieldRVA(this,val);
3702 /// Set the offset of the field. Used for sequential or explicit classes.
3705 /// <param name="offs">field offset</param>
3706 public void SetOffset(uint offs)
3708 layout = new FieldLayout(this,offs);
3712 /// Set the marshalling info for a field
3714 /// <param name="mInf"></param>
3715 public void SetMarshalInfo(NativeType marshallType)
3717 flags |= (ushort) FieldAttr.HasFieldMarshal;
3718 marshalInfo = new FieldMarshal(this,marshallType);
3721 internal sealed override void BuildTables(MetaData md)
3724 nameIx = md.AddToStringsHeap(name);
3725 MemoryStream sig = new MemoryStream();
3726 sig.WriteByte(FieldSig);
3728 sigIx = md.AddToBlobHeap(sig.ToArray());
3730 md.AddToTable(MDTable.FieldRVA,rva);
3731 rva.BuildTables(md);
3732 } else if (constVal != null) {
3733 md.AddToTable(MDTable.Constant,constVal);
3734 constVal.BuildTables(md);
3736 if (layout != null) md.AddToTable(MDTable.FieldLayout,layout);
3737 if (marshalInfo != null) {
3738 md.AddToTable(MDTable.FieldMarshal,marshalInfo);
3739 marshalInfo.BuildTables(md);
3744 internal sealed override uint Size(MetaData md)
3746 return 2 + md.StringsIndexSize() + md.BlobIndexSize();
3749 internal sealed override void Write(FileImage output)
3751 output.Write(flags);
3752 output.StringsIndex(nameIx);
3753 output.BlobIndex(sigIx);
3756 internal sealed override uint GetCodedIx(CIx code)
3759 case (CIx.HasConst) : return 0;
3760 case (CIx.HasCustomAttr) : return 1;
3761 case (CIx.HasFieldMarshal) : return 0;
3762 case (CIx.MemberForwarded) : return 0;
3769 /**************************************************************************/
3771 /// Descriptor for a field of a class defined in another assembly/module
3773 public class FieldRef : Field {
3775 MetaDataElement parent;
3777 internal FieldRef(MetaDataElement paren, string name, Type fType) : base(name, fType)
3782 internal sealed override void BuildTables(MetaData md)
3785 nameIx = md.AddToStringsHeap(name);
3786 MemoryStream sig = new MemoryStream();
3787 sig.WriteByte(FieldSig);
3789 sigIx = md.AddToBlobHeap(sig.ToArray());
3793 internal sealed override uint Size(MetaData md)
3795 return md.CodedIndexSize(CIx.MemberRefParent) + md.StringsIndexSize() + md.BlobIndexSize();
3798 internal sealed override void Write(FileImage output)
3800 output.WriteCodedIndex(CIx.MemberRefParent,parent);
3801 output.StringsIndex(nameIx);
3802 output.BlobIndex(sigIx);
3805 internal sealed override uint GetCodedIx(CIx code) { return 6; }
3809 /**************************************************************************/
3811 /// Base class for Method Descriptors
3814 public abstract class Method : Member {
3816 internal Method (string methName) : base (methName)
3819 public abstract void AddCallConv(CallConv cconv);
3820 internal abstract void TypeSig(MemoryStream sig);
3821 internal abstract uint GetSigIx(MetaData md);
3824 /**************************************************************************/
3826 /// Descriptor for a method defined in THIS assembly/module
3830 public class MethodDef : Method {
3832 private static readonly ushort PInvokeImpl = 0x2000;
3833 //private static readonly uint UnmanagedExport = 0x0008;
3834 // private static readonly byte LocalSigByte = 0x7;
3835 uint parIx = 0, textOffset = 0;
3836 private CallConv callConv = CallConv.Default;
3837 private int gen_param_count;
3840 CILInstructions code;
3844 ushort methFlags = 0, implFlags = 0;
3845 int maxStack = 0, numPars = 0;
3846 bool entryPoint = false;
3848 ArrayList varArgSigList;
3849 ImplMap pinvokeImpl;
3852 internal MethodDef (MetaData md, string name, Param ret_param, Param [] pars)
3853 : this (md, 0, 0, name, ret_param, pars)
3857 internal MethodDef (MetaData md, MethAttr mAttrSet, ImplAttr iAttrSet, string name,
3858 Param ret_param, Param [] pars)
3861 methFlags = (ushort)mAttrSet;
3862 implFlags = (ushort)iAttrSet;
3863 this.ret_param = ret_param;
3866 if (parList != null)
3867 numPars = parList.Length;
3868 tabIx = MDTable.Method;
3871 internal Param[] GetPars()
3876 internal override uint GetSigIx(MetaData md)
3878 MemoryStream sig = new MemoryStream();
3880 return md.AddToBlobHeap(sig.ToArray());
3883 public override void AddCallConv(CallConv cconv)
3889 /// Add some attributes to this method descriptor
3891 /// <param name="ma">the attributes to be added</param>
3892 public void AddMethAttribute(MethAttr ma)
3894 methFlags |= (ushort)ma;
3898 /// Add some implementation attributes to this method descriptor
3900 /// <param name="ia">the attributes to be added</param>
3901 public void AddImplAttribute(ImplAttr ia)
3903 implFlags |= (ushort)ia;
3906 public void AddPInvokeInfo(ModuleRef scope, string methName,
3907 PInvokeAttr callAttr) {
3908 pinvokeImpl = new ImplMap((ushort)callAttr,this,methName,scope);
3909 methFlags |= PInvokeImpl;
3913 /// Add a named generic type parameter
3915 public GenericParameter AddGenericParameter (short index, string name)
3917 return AddGenericParameter (index, name, 0);
3921 /// Add a named generic type parameter with attributes
3923 public GenericParameter AddGenericParameter (short index, string name, GenericParamAttributes attr)
3925 GenericParameter gp = new GenericParameter (this, metaData, index, name, attr);
3926 metaData.AddToTable (MDTable.GenericParam, gp);
3932 /// Set the maximum stack height for this method
3934 /// <param name="maxStack">the maximum height of the stack</param>
3935 public void SetMaxStack(int maxStack)
3937 this.maxStack = maxStack;
3941 /// Add local variables to this method
3943 /// <param name="locals">the locals to be added</param>
3944 /// <param name="initLocals">are locals initialised to default values</param>
3945 public void AddLocals(Local[] locals, bool initLocals)
3947 this.locals = locals;
3948 this.initLocals = initLocals;
3951 /* Add Marshal info for return type */
3952 public void AddRetTypeMarshallInfo (NativeType marshallType)
3954 ret_param.AddMarshallInfo (marshallType);
3958 /// Mark this method as having an entry point
3960 public void DeclareEntryPoint()
3966 /// Create a code buffer for this method to add the IL instructions to
3968 /// <returns>a buffer for this method's IL instructions</returns>
3969 public CILInstructions CreateCodeBuffer()
3971 code = new CILInstructions(metaData);
3976 /// Make a method reference descriptor for this method to be used
3977 /// as a callsite signature for this vararg method
3979 /// <param name="optPars">the optional pars for the vararg method call</param>
3980 /// <returns></returns>
3981 public MethodRef MakeVarArgSignature(Type[] optPars)
3983 Type[] pars = new Type[numPars];
3984 MethodRef varArgSig;
3985 for (int i=0; i < numPars; i++) {
3986 pars[i] = parList[i].GetParType();
3988 varArgSig = new MethodRef (this, name, ret_param.GetParType (), pars, true, optPars, 0);
3990 if (varArgSigList == null)
3991 varArgSigList = new ArrayList ();
3992 varArgSigList.Add (varArgSig);
3996 internal sealed override void TypeSig(MemoryStream sig)
3998 sig.WriteByte((byte)callConv);
3999 if ((callConv & CallConv.Generic) == CallConv.Generic)
4000 MetaData.CompressNum ((uint) gen_param_count, sig);
4001 MetaData.CompressNum((uint)numPars,sig);
4003 ret_param.seqNo = 0;
4004 ret_param.TypeSig (sig);
4005 for (ushort i=0; i < numPars; i++) {
4006 parList[i].seqNo = (ushort)(i+1);
4007 parList[i].TypeSig(sig);
4011 internal sealed override void BuildTables(MetaData md)
4014 if (pinvokeImpl != null) {
4015 md.AddToTable(MDTable.ImplMap,pinvokeImpl);
4016 pinvokeImpl.BuildTables(md);
4018 if (entryPoint) md.SetEntryPoint(this);
4020 if (locals != null) {
4021 localSig = new LocalSig(locals);
4022 md.AddToTable(MDTable.StandAloneSig,localSig);
4023 localSig.BuildTables(md);
4024 locToken = localSig.Token();
4027 code.CheckCode(locToken,initLocals,maxStack);
4028 textOffset = md.AddCode(code);
4030 nameIx = md.AddToStringsHeap(name);
4031 sigIx = GetSigIx(md);
4032 parIx = md.TableIndex(MDTable.Param);
4033 if (ret_param.HasMarshalInfo || ret_param.HasCustomAttr) {
4034 md.AddToTable(MDTable.Param, ret_param);
4035 ret_param.BuildTables(md);
4037 for (int i=0; i < numPars; i++) {
4038 md.AddToTable(MDTable.Param,parList[i]);
4039 parList[i].BuildTables(md);
4041 if (varArgSigList != null) {
4042 foreach (MethodRef varArgSig in varArgSigList) {
4043 md.AddToTable(MDTable.MemberRef,varArgSig);
4044 varArgSig.BuildTables(md);
4047 // Console.WriteLine("method has " + numPars + " parameters");
4051 internal sealed override uint Size(MetaData md)
4053 return 8 + md.StringsIndexSize() + md.BlobIndexSize() + md.TableIndexSize(MDTable.Param);
4056 internal sealed override void Write(FileImage output)
4058 if (ZeroRva ()) output.Write(0);
4059 else output.WriteCodeRVA(textOffset);
4060 output.Write(implFlags);
4061 output.Write(methFlags);
4062 output.StringsIndex(nameIx);
4063 output.BlobIndex(sigIx);
4064 output.WriteIndex(MDTable.Param,parIx);
4067 internal bool ZeroRva ()
4069 return (((methFlags & (ushort)MethAttr.Abstract) != 0) ||
4070 ((implFlags & (ushort)ImplAttr.Runtime) != 0) ||
4071 ((implFlags & (ushort)ImplAttr.InternalCall) != 0) ||
4072 (pinvokeImpl != null)); // TODO: Not entirely true but works for now
4075 internal sealed override uint GetCodedIx(CIx code)
4078 case (CIx.HasCustomAttr) : return 0;
4079 case (CIx.HasDeclSecurity) : return 1;
4080 case (CIx.MemberRefParent) : return 3;
4081 case (CIx.MethodDefOrRef) : return 0;
4082 case (CIx.MemberForwarded) : return 1;
4083 case (CIx.CustomAttributeType) : return 2;
4084 case (CIx.TypeOrMethodDef) : return 1;
4090 /**************************************************************************/
4092 /// Descriptor for a method defined in another assembly/module
4094 public class MethodRef : Method {
4096 private static readonly byte Sentinel = 0x41;
4097 Type[] parList, optParList;
4098 MetaDataElement parent;
4099 uint numPars = 0, numOptPars = 0;
4100 CallConv callConv = CallConv.Default;
4102 int gen_param_count;
4104 internal MethodRef(MetaDataElement paren, string name, Type retType,
4105 Type[] pars, bool varArgMeth, Type[] optPars, int gen_param_count) : base(name)
4109 this.retType = retType;
4110 if (parList != null) numPars = (uint)parList.Length;
4112 optParList = optPars;
4113 if (optParList != null) numOptPars = (uint)optParList.Length;
4114 callConv = CallConv.Vararg;
4116 this.gen_param_count = gen_param_count;
4119 internal override uint GetSigIx(MetaData md)
4121 MemoryStream sig = new MemoryStream();
4123 return md.AddToBlobHeap(sig.ToArray());
4126 public override void AddCallConv(CallConv cconv)
4131 internal sealed override void TypeSig(MemoryStream sig)
4133 sig.WriteByte((byte)callConv);
4134 if ((callConv & CallConv.Generic) == CallConv.Generic)
4135 MetaData.CompressNum ((uint) gen_param_count, sig);
4136 MetaData.CompressNum(numPars+numOptPars,sig);
4137 retType.TypeSig(sig);
4138 for (int i=0; i < numPars; i++) {
4139 parList[i].TypeSig(sig);
4141 if (numOptPars > 0) {
4142 sig.WriteByte(Sentinel);
4143 for (int i=0; i < numOptPars; i++) {
4144 optParList[i].TypeSig(sig);
4149 internal sealed override void BuildTables(MetaData md)
4152 nameIx = md.AddToStringsHeap(name);
4153 sigIx = GetSigIx(md);
4157 internal sealed override uint Size(MetaData md)
4159 return md.CodedIndexSize(CIx.MemberRefParent) + md.StringsIndexSize() + md.BlobIndexSize();
4162 internal sealed override void Write(FileImage output)
4164 output.WriteCodedIndex(CIx.MemberRefParent,parent);
4165 output.StringsIndex(nameIx);
4166 output.BlobIndex(sigIx);
4169 internal sealed override uint GetCodedIx(CIx code)
4172 case (CIx.HasCustomAttr) : return 6;
4173 case (CIx.MethodDefOrRef) : return 1;
4174 case (CIx.CustomAttributeType) : return 3;
4182 /**************************************************************************/
4184 /// Descriptors for native types used for marshalling
4186 public class NativeType {
4187 public static readonly NativeType Void = new NativeType(0x01);
4188 public static readonly NativeType Boolean = new NativeType(0x02);
4189 public static readonly NativeType Int8 = new NativeType(0x03);
4190 public static readonly NativeType UInt8 = new NativeType(0x04);
4191 public static readonly NativeType Int16 = new NativeType(0x05);
4192 public static readonly NativeType UInt16 = new NativeType(0x06);
4193 public static readonly NativeType Int32 = new NativeType(0x07);
4194 public static readonly NativeType UInt32 = new NativeType(0x08);
4195 public static readonly NativeType Int64 = new NativeType(0x09);
4196 public static readonly NativeType UInt64 = new NativeType(0x0A);
4197 public static readonly NativeType Float32 = new NativeType(0x0B);
4198 public static readonly NativeType Float64 = new NativeType(0x0C);
4199 public static readonly NativeType Currency = new NativeType(0x0F);
4200 public static readonly NativeType BStr = new NativeType(0x13);
4201 public static readonly NativeType LPStr = new NativeType(0x14);
4202 public static readonly NativeType LPWStr = new NativeType(0x15);
4203 public static readonly NativeType LPTStr = new NativeType(0x16);
4204 public static readonly NativeType FixedSysString = new NativeType(0x17);
4205 public static readonly NativeType IUnknown = new NativeType(0x19);
4206 public static readonly NativeType IDispatch = new NativeType(0x1A);
4207 public static readonly NativeType Struct = new NativeType(0x1B);
4208 public static readonly NativeType Interface = new NativeType(0x1C);
4209 public static readonly NativeType Int = new NativeType(0x1F);
4210 public static readonly NativeType UInt = new NativeType(0x20);
4211 public static readonly NativeType ByValStr = new NativeType(0x22);
4212 public static readonly NativeType AnsiBStr = new NativeType(0x23);
4213 public static readonly NativeType TBstr = new NativeType(0x24);
4214 public static readonly NativeType VariantBool = new NativeType(0x25);
4215 public static readonly NativeType FuncPtr = new NativeType(0x26);
4216 public static readonly NativeType AsAny = new NativeType(0x28);
4217 public static readonly NativeType LPStruct = new NativeType(0x2b);
4218 public static readonly NativeType Error = new NativeType(0x2d);
4220 protected byte typeIndex;
4222 internal NativeType(byte tyIx) { typeIndex = tyIx; }
4223 internal byte GetTypeIndex() { return typeIndex; }
4225 internal virtual byte[] ToBlob()
4227 byte[] bytes = new byte[1];
4228 bytes[0] = GetTypeIndex();
4234 public class FixedSysString : NativeType {
4238 public FixedSysString (uint size) : base (NativeType.FixedSysString.GetTypeIndex ())
4243 internal override byte [] ToBlob ()
4245 MemoryStream str = new MemoryStream ();
4246 str.WriteByte (GetTypeIndex ());
4247 MetaData.CompressNum (size, str);
4248 return str.ToArray ();
4253 public class NativeArray : NativeType {
4255 NativeType elemType;
4256 int numElem = -1, parNum = -1, elemMult = -1;
4258 public NativeArray(NativeType elemType) : this (elemType, -1, -1, -1)
4260 this.elemType = elemType;
4263 /* public NativeArray(NativeType elemType, int len) : base(0x2A) {
4264 this.elemType = elemType;
4269 public NativeArray(NativeType elemType, int numElem, int parNumForLen, int elemMult) : base(0x2A)
4271 this.elemType = elemType;
4272 this.numElem = numElem;
4273 parNum = parNumForLen;
4274 this.elemMult = elemMult;
4277 public NativeArray(NativeType elemType, int numElem, int parNumForLen)
4278 : this (elemType, numElem, parNumForLen, -1)
4282 internal override byte[] ToBlob()
4284 MemoryStream str = new MemoryStream();
4285 str.WriteByte(GetTypeIndex());
4286 if (elemType == null) str.WriteByte(0x50); // no info (MAX)
4287 else str.WriteByte(elemType.GetTypeIndex());
4289 /* see : mono/metadata/metadata.c:mono_metadata_parse_marshal_spec
4290 * LAMESPEC: Older spec versions say elemMult comes before
4291 * len. Newer spec versions don't talk about elemMult at
4292 * all, but csc still emits it, and it is used to distinguish
4293 * between parNum being 0, and parNum being omitted.
4298 return str.ToArray ();
4300 MetaData.CompressNum((uint) parNum,str);
4301 if (numElem != -1) {
4302 MetaData.CompressNum ((uint) numElem, str);
4304 // <native_type> [ int32 ]
4305 MetaData.CompressNum((uint) elemMult,str);
4306 //else <native_type> [ int32 + int32 ]
4307 } else if (elemMult != -1) {
4308 // When can this occur ?
4309 MetaData.CompressNum (0, str);
4310 MetaData.CompressNum((uint) elemMult,str);
4312 //else <native_type> [ + int32 ]
4314 return str.ToArray();
4319 public class SafeArray : NativeType {
4321 SafeArrayType elemType;
4324 public SafeArray() : base(0x1D)
4328 public SafeArray(SafeArrayType elemType) : base(0x1D)
4330 this.elemType = elemType;
4334 internal override byte[] ToBlob()
4336 byte[] bytes = new byte[hasElemType ? 2 : 1];
4337 bytes[0] = GetTypeIndex();
4339 bytes[1] = (byte)elemType;
4345 public class FixedArray : NativeType {
4349 //public FixedArray(NativeType elemType, int numElems) : base(0x1E) {
4350 public FixedArray(int numElems) : base(0x1E)
4352 //this.elemType = elemType;
4353 numElem = (uint)numElems;
4356 internal override byte[] ToBlob()
4358 MemoryStream str = new MemoryStream();
4359 str.WriteByte(GetTypeIndex());
4360 MetaData.CompressNum(numElem,str);
4362 fixed array [5] lpstr [2]
4363 This format is not supported by ilasm 1.1.4322.2032,
4364 but is supported by 2.0.5125..
4365 ilasm 1.1 only supports "fixed array [5]"
4366 if (elemType == null) str.WriteByte(0x50); // no info (MAX)
4367 else str.WriteByte(elemType.GetTypeIndex());*/
4369 return str.ToArray();
4374 public class CustomMarshaller : NativeType {
4377 string marshallerName;
4380 public CustomMarshaller(string typeNameOrGUID, string marshallerName,
4381 string optCookie) : base(0x2C)
4383 typeName = typeNameOrGUID;
4384 this.marshallerName = marshallerName;
4388 public CustomMarshaller(string marshallerName, string optCookie)
4389 :this (null, marshallerName, optCookie)
4393 internal override byte[] ToBlob()
4395 MemoryStream str = new MemoryStream();
4396 BinaryWriter bw = new BinaryWriter(str,new UTF8Encoding());
4397 bw.Write(GetTypeIndex());
4398 //Native type name & unmanaged type - unused
4399 //See mono/metadata/metadata.c : mono_metadata_parse_marshal_spec
4400 bw.Write ((byte) 0); // Native Type name, unused
4401 bw.Write ((byte) 0); // Unmanaged type, unused
4402 if (marshallerName != null) {
4403 MetaData.CompressNum ((uint)marshallerName.Length, str);
4404 bw.Write(marshallerName.ToCharArray());
4406 bw.Write ((byte) 0);
4408 if (cookie != null) {
4409 MetaData.CompressNum ((uint)cookie.Length, str);
4410 bw.Write(cookie.ToCharArray());
4412 bw.Write ((byte) 0);
4415 return str.ToArray();
4419 /**************************************************************************/
4421 /// Descriptor for the Primitive types defined in IL
4423 public class PrimitiveType : Type {
4425 private string name;
4426 private int systemTypeIndex;
4427 public static int NumSystemTypes = 18;
4429 public static readonly PrimitiveType Void = new PrimitiveType(0x01,"Void",0);
4430 public static readonly PrimitiveType Boolean = new PrimitiveType(0x02,"Boolean",1);
4431 public static readonly PrimitiveType Char = new PrimitiveType(0x03,"Char",2);
4432 public static readonly PrimitiveType Int8 = new PrimitiveType(0x04,"SByte",3);
4433 public static readonly PrimitiveType UInt8 = new PrimitiveType(0x05,"Byte",4);
4434 public static readonly PrimitiveType Int16 = new PrimitiveType(0x06,"Int16",5);
4435 public static readonly PrimitiveType UInt16 = new PrimitiveType(0x07,"UInt16",6);
4436 public static readonly PrimitiveType Int32 = new PrimitiveType(0x08,"Int32",7);
4437 public static readonly PrimitiveType UInt32 = new PrimitiveType(0x09,"UInt32",8);
4438 public static readonly PrimitiveType Int64 = new PrimitiveType(0x0A,"Int64",9);
4439 public static readonly PrimitiveType UInt64 = new PrimitiveType(0x0B,"UInt64",10);
4440 public static readonly PrimitiveType Float32 = new PrimitiveType(0x0C,"Single",11);
4441 public static readonly PrimitiveType Float64 = new PrimitiveType(0x0D,"Double",12);
4442 public static readonly PrimitiveType String = new PrimitiveType(0x0E,"String",13);
4443 internal static readonly PrimitiveType Class = new PrimitiveType(0x12);
4444 internal static readonly PrimitiveType Var = new PrimitiveType(0x13);
4445 internal static readonly PrimitiveType GenericInst = new PrimitiveType(0x15);
4446 public static readonly PrimitiveType TypedRef = new PrimitiveType(0x16,"TypedReference",14);
4447 public static readonly PrimitiveType IntPtr = new PrimitiveType(0x18,"IntPtr",15);
4448 public static readonly PrimitiveType UIntPtr = new PrimitiveType(0x19,"UIntPtr",16);
4449 public static readonly PrimitiveType Object = new PrimitiveType(0x1C,"Object",17);
4450 internal static readonly PrimitiveType ClassType = new PrimitiveType(0x50);
4451 internal static readonly PrimitiveType SZArray = new PrimitiveType(0x1D);
4452 internal static readonly PrimitiveType MVar = new PrimitiveType(0x1E);
4453 internal static readonly PrimitiveType ValueType = new PrimitiveType(0x11, "ValueType", 18);
4454 public static readonly PrimitiveType NativeInt = IntPtr;
4455 public static readonly PrimitiveType NativeUInt = UIntPtr;
4457 internal PrimitiveType(byte typeIx) : base(typeIx) { }
4459 internal PrimitiveType(byte typeIx, string name, int STIx) : base(typeIx)
4462 this.systemTypeIndex = STIx;
4465 internal string GetName() { return name; }
4467 internal int GetSystemTypeIx() { return systemTypeIndex; }
4469 internal sealed override void TypeSig(MemoryStream str)
4471 str.WriteByte(typeIndex);
4474 internal override MetaDataElement GetTypeSpec(MetaData md)
4476 TypeSpec tS = md.GetPrimitiveTypeSpec(systemTypeIndex);
4478 tS = new TypeSpec(this,md);
4479 md.SetPrimitiveTypeSpec(systemTypeIndex,tS);
4480 md.AddToTable(MDTable.TypeSpec,tS);
4487 public class PrimitiveTypeRef : Type
4492 internal PrimitiveTypeRef(PrimitiveType type, MetaData md)
4499 internal uint TypeDefOrRefToken()
4501 uint cIx = type.GetTypeSpec (metaData).Row;
4502 cIx = (cIx << 2) | 0x2;
4507 /**************************************************************************/
4509 /// Descriptor for an pointer (type * or type &)
4511 public abstract class PtrType : Type {
4515 internal PtrType(Type bType, byte typeIx) : base(typeIx)
4518 tabIx = MDTable.TypeSpec;
4521 internal sealed override void TypeSig(MemoryStream str)
4523 str.WriteByte(typeIndex);
4524 baseType.TypeSig(str);
4528 /**************************************************************************/
4530 /// Descriptor for a managed pointer (type & or byref)
4533 public class ManagedPointer : PtrType {
4536 /// Create new managed pointer to baseType
4538 /// <param name="bType">the base type of the pointer</param>
4539 public ManagedPointer(Type baseType) : base(baseType,0x10) { }
4542 /**************************************************************************/
4544 /// Descriptor for an unmanaged pointer (type *)
4546 public class UnmanagedPointer : PtrType {
4549 /// Create a new unmanaged pointer to baseType
4551 /// <param name="baseType">the base type of the pointer</param>
4552 public UnmanagedPointer(Type baseType) : base(baseType, 0x0F) { }
4556 /**************************************************************************/
4558 public interface IExternRef {
4559 ClassRef AddClass(string nsName, string name);
4560 ClassRef AddValueClass(string nsName, string name);
4564 /// A reference to an external assembly (.assembly extern)
4566 public class AssemblyRef : ResolutionScope, IExternRef {
4568 private ushort major, minor, build, revision;
4569 uint flags, keyIx, hashIx, cultIx;
4570 bool hasVersion = false, isKeyToken = false;
4574 internal AssemblyRef(MetaData md, string name) : base(name,md)
4576 tabIx = MDTable.AssemblyRef;
4579 public void AddAssemblyAttr (AssemAttr aa)
4585 /// Add version information about this external assembly
4587 /// <param name="majVer">Major Version</param>
4588 /// <param name="minVer">Minor Version</param>
4589 /// <param name="bldNo">Build Number</param>
4590 /// <param name="revNo">Revision Number</param>
4591 public void AddVersionInfo(int majVer, int minVer, int bldNo, int revNo)
4593 major = (ushort)majVer;
4594 minor = (ushort)minVer;
4595 build = (ushort)bldNo;
4596 revision = (ushort)revNo;
4601 /// Add the hash value for this external assembly
4603 /// <param name="hash">bytes of the hash value</param>
4604 public void AddHash(byte[] hash)
4606 hashIx = metaData.AddToBlobHeap(hash);
4610 /// Set the culture for this external assembly
4612 /// <param name="cult">the culture string</param>
4613 public void AddCulture(string cult)
4615 cultIx = metaData.AddToStringsHeap(cult);
4620 /// Add the full public key for this external assembly
4622 /// <param name="key">bytes of the public key</param>
4623 public void AddKey(byte[] key)
4625 flags |= 0x0001; // full public key
4627 keyIx = metaData.AddToBlobHeap(key);
4631 /// Add the public key token (low 8 bytes of the public key)
4633 /// <param name="key">low 8 bytes of public key</param>
4634 public void AddKeyToken(byte[] key)
4636 keyIx = metaData.AddToBlobHeap(key);
4642 /// Add a class to this external assembly
4644 /// <param name="nsName">name space name</param>
4645 /// <param name="name">class name</param>
4646 /// <returns></returns>
4647 public virtual ClassRef AddClass(string nsName, string name)
4649 ClassRef aClass = new ClassRef(nsName,name,metaData);
4650 metaData.AddToTable(MDTable.TypeRef,aClass);
4651 aClass.SetParent(this);
4656 /// Add a value class to this external assembly
4658 /// <param name="nsName">name space name</param>
4659 /// <param name="name">class name</param>
4660 /// <returns></returns>
4661 public virtual ClassRef AddValueClass(string nsName, string name)
4663 ClassRef aClass = new ClassRef(nsName,name,metaData);
4664 metaData.AddToTable(MDTable.TypeRef,aClass);
4665 aClass.SetParent(this);
4666 aClass.MakeValueClass(ValueClass.ValueType);
4670 internal string TypeName()
4672 string result = name;
4674 result = result + ", Version=" + major + "." + minor + "." +
4675 build + "." + revision;
4676 if (keyBytes != null) {
4677 string tokenStr = "=";
4678 if (isKeyToken) tokenStr = "Token=";
4679 result = result + ", PublicKey" + tokenStr;
4680 for (int i=0; i < keyBytes.Length; i++) {
4681 result = result + Hex.Byte(keyBytes[i]);
4684 if (culture != null)
4685 result = result + ", Culture=" + culture;
4689 internal sealed override uint Size(MetaData md)
4691 return 12 + 2 * md.StringsIndexSize() + 2 * md.BlobIndexSize();
4694 internal sealed override void Write(FileImage output)
4696 output.Write(major);
4697 output.Write(minor);
4698 output.Write(build);
4699 output.Write(revision);
4700 output.Write(flags);
4701 output.BlobIndex(keyIx);
4702 output.StringsIndex(nameIx);
4703 output.StringsIndex(cultIx);
4704 output.BlobIndex(hashIx);
4707 internal sealed override uint GetCodedIx(CIx code)
4710 case (CIx.ResolutionScope) : return 2;
4711 case (CIx.HasCustomAttr) : return 15;
4712 case (CIx.Implementation) : return 1;
4719 /**************************************************************************/
4721 /// Descriptor for a class defined in System (mscorlib)
4723 internal class SystemClass : ClassRef {
4725 PrimitiveType elemType;
4727 internal SystemClass(PrimitiveType eType, AssemblyRef paren, MetaData md)
4728 : base("System",eType.GetName(),md) {
4733 internal override sealed MetaDataElement GetTypeSpec(MetaData md)
4735 if (typeSpec == null) typeSpec = (TypeSpec)elemType.GetTypeSpec(md);
4740 internal sealed override void TypeSig(MemoryStream str)
4742 str.WriteByte(elemType.GetTypeIndex());
4747 /**************************************************************************/
4749 /// The assembly for mscorlib.
4751 public sealed class MSCorLib : AssemblyRef {
4753 private static readonly int valueTypeIx = 18;
4754 private readonly string systemName = "System";
4755 private Class[] systemClasses = new Class[valueTypeIx+2];
4756 private PrimitiveType[] systemTypes = new PrimitiveType[valueTypeIx];
4758 private static int[] specialNames = {
4759 PrimitiveType.Void.GetName().GetHashCode(),
4760 PrimitiveType.Boolean.GetName().GetHashCode(),
4761 PrimitiveType.Char.GetName().GetHashCode(),
4762 PrimitiveType.Int8.GetName().GetHashCode(),
4763 PrimitiveType.UInt8.GetName().GetHashCode(),
4764 PrimitiveType.Int16.GetName().GetHashCode(),
4765 PrimitiveType.UInt16.GetName().GetHashCode(),
4766 PrimitiveType.Int32.GetName().GetHashCode(),
4767 PrimitiveType.UInt32.GetName().GetHashCode(),
4768 PrimitiveType.Int64.GetName().GetHashCode(),
4769 PrimitiveType.UInt64.GetName().GetHashCode(),
4770 PrimitiveType.Float32.GetName().GetHashCode(),
4771 PrimitiveType.Float64.GetName().GetHashCode(),
4772 PrimitiveType.String.GetName().GetHashCode(),
4773 PrimitiveType.TypedRef.GetName().GetHashCode(),
4774 PrimitiveType.IntPtr.GetName().GetHashCode(),
4775 PrimitiveType.UIntPtr.GetName().GetHashCode(),
4776 PrimitiveType.Object.GetName().GetHashCode(),
4777 PrimitiveType.ValueType.GetName ().GetHashCode(),
4778 "Enum".GetHashCode()
4781 internal MSCorLib(MetaData md) : base(md,"mscorlib")
4783 if (!PEFile.IsMSCorlib)
4784 md.AddToTable(MDTable.AssemblyRef,this);
4785 systemTypes[PrimitiveType.Void.GetSystemTypeIx()] = PrimitiveType.Void;
4786 systemTypes[PrimitiveType.Boolean.GetSystemTypeIx()] = PrimitiveType.Boolean;
4787 systemTypes[PrimitiveType.Char.GetSystemTypeIx()] = PrimitiveType.Char;
4788 systemTypes[PrimitiveType.Int8.GetSystemTypeIx()] = PrimitiveType.Int8;
4789 systemTypes[PrimitiveType.UInt8.GetSystemTypeIx()] = PrimitiveType.UInt8;
4790 systemTypes[PrimitiveType.Int16.GetSystemTypeIx()] = PrimitiveType.Int16;
4791 systemTypes[PrimitiveType.UInt16.GetSystemTypeIx()] = PrimitiveType.UInt16;
4792 systemTypes[PrimitiveType.Int32.GetSystemTypeIx()] = PrimitiveType.Int32;
4793 systemTypes[PrimitiveType.UInt32.GetSystemTypeIx()] = PrimitiveType.UInt32;
4794 systemTypes[PrimitiveType.Int64.GetSystemTypeIx()] = PrimitiveType.Int64;
4795 systemTypes[PrimitiveType.UInt64.GetSystemTypeIx()] = PrimitiveType.UInt64;
4796 systemTypes[PrimitiveType.Float32.GetSystemTypeIx()] = PrimitiveType.Float32;
4797 systemTypes[PrimitiveType.Float64.GetSystemTypeIx()] = PrimitiveType.Float64;
4798 systemTypes[PrimitiveType.IntPtr.GetSystemTypeIx()] = PrimitiveType.IntPtr;
4799 systemTypes[PrimitiveType.UIntPtr.GetSystemTypeIx()] = PrimitiveType.UIntPtr;
4800 systemTypes[PrimitiveType.String.GetSystemTypeIx()] = PrimitiveType.String;
4801 systemTypes[PrimitiveType.Object.GetSystemTypeIx()] = PrimitiveType.Object;
4802 systemTypes[PrimitiveType.TypedRef.GetSystemTypeIx()] = PrimitiveType.TypedRef;
4806 /// Add a class to the mscorlib assembly
4808 /// <param name="nsName">name space name</param>
4809 /// <param name="name">class name</param>
4810 /// <returns></returns>
4811 public override ClassRef AddClass(string nsName, string name)
4813 /* This gets called by !mscorlib, for adding references INTO mscorlib, so
4814 it should be returning ClassRef ..*/
4815 Class aClass = GetSpecialClass(nsName,name);
4816 if (aClass == null) {
4817 aClass = new ClassRef(nsName,name,metaData);
4818 metaData.AddToTable(MDTable.TypeRef,aClass);
4819 if (aClass is ClassRef)
4820 ((ClassRef) aClass).SetParent(this);
4822 //FIXME: Check for !ClassRef here?
4823 return (ClassRef) aClass;
4826 private Class GetSpecialClass(string nsName,string name)
4828 if (nsName.CompareTo(systemName) != 0) return null;
4829 int hash = name.GetHashCode();
4830 for (int i=0; i < specialNames.Length; i++) {
4831 if (hash != specialNames[i])
4833 if (systemClasses[i] == null) {
4834 if (i < valueTypeIx) {
4835 systemClasses[i] = new SystemClass(systemTypes[i],this,metaData);
4836 if ((systemTypes[i] != PrimitiveType.Object) &&
4837 (systemTypes[i] != PrimitiveType.String)) {
4838 systemClasses[i].MakeValueClass(ValueClass.ValueType);
4841 systemClasses[i] = new ClassRef(nsName,name,metaData);
4842 ((ClassRef) systemClasses[i]).SetParent(this);
4843 if (!ClassDef.IsValueType (nsName, name) && !ClassDef.IsEnum (nsName, name))
4844 systemClasses[i].MakeValueClass(ValueClass.ValueType);
4846 metaData.AddToTable(MDTable.TypeRef,systemClasses[i]);
4848 return systemClasses[i];
4853 internal void SetSpecialSystemClass (string nsName, string name, Class aClass)
4855 if (nsName != systemName) return;
4856 int hash = name.GetHashCode ();
4857 for (int i = 0; i < specialNames.Length; i++) {
4858 if (hash != specialNames [i])
4860 if (systemClasses [i] == null) {
4861 systemClasses [i] = aClass;
4866 internal Class GetSpecialSystemClass(PrimitiveType pType)
4868 int ix = pType.GetSystemTypeIx();
4869 if (systemClasses[ix] == null && !PEFile.IsMSCorlib) {
4870 systemClasses[ix] = new SystemClass(pType,this,metaData);
4871 metaData.AddToTable(MDTable.TypeRef,systemClasses[ix]);
4873 return systemClasses[ix];
4876 private ClassRef GetValueClass(string name, int hash)
4878 /* Called by MSCorLib.AddValueClass, which is called by
4879 !mscorlib, for adding ref to value class INTO mscorlib,
4880 so this should be classref */
4881 int ix = valueTypeIx;
4882 if (hash != specialNames[valueTypeIx]) ix++;
4883 if (systemClasses[ix] == null) {
4884 systemClasses[ix] = new ClassRef(systemName,name,metaData);
4885 ((ClassRef) systemClasses[ix]).SetParent(this);
4886 ((ClassRef) systemClasses[ix]).MakeValueClass(ValueClass.ValueType);
4887 metaData.AddToTable(MDTable.TypeRef,systemClasses[ix]);
4889 return (ClassRef) systemClasses[ix];
4892 internal Class ValueType()
4894 if (systemClasses[valueTypeIx] == null && !PEFile.IsMSCorlib) {
4895 ClassRef valType = new ClassRef("System","ValueType",metaData);
4896 valType.SetParent(this);
4897 valType.MakeValueClass(ValueClass.ValueType);
4898 metaData.AddToTable(MDTable.TypeRef,valType);
4899 systemClasses[valueTypeIx] = valType;
4901 return systemClasses[valueTypeIx];
4904 internal Class EnumType()
4906 /* Called by both mscorlib & !mscorlib, so can be
4907 either ClassRef or ClassDef */
4908 //systemClasses [ valueTypeIx + 1] -> System.Enum
4909 if (systemClasses[valueTypeIx + 1] == null && !PEFile.IsMSCorlib) {
4910 ClassRef valType = new ClassRef("System","Enum",metaData);
4911 valType.SetParent(this);
4912 valType.MakeValueClass(ValueClass.Enum);
4913 metaData.AddToTable(MDTable.TypeRef,valType);
4914 systemClasses[valueTypeIx + 1] = valType;
4916 return systemClasses[valueTypeIx + 1];
4920 /// Add a value class to this external assembly
4922 /// <param name="nsName">name space name</param>
4923 /// <param name="name">class name</param>
4924 /// <returns></returns>
4925 public override ClassRef AddValueClass(string nsName, string name)
4927 if (nsName.CompareTo(systemName) == 0) {
4928 int hash = name.GetHashCode();
4929 if ((hash == specialNames[valueTypeIx]) ||
4930 (hash == specialNames[valueTypeIx+1])) {
4931 return GetValueClass(name,hash);
4934 ClassRef aClass = new ClassRef(nsName,name,metaData);
4935 metaData.AddToTable(MDTable.TypeRef,aClass);
4936 aClass.SetParent(this);
4937 aClass.MakeValueClass(ValueClass.ValueType);
4943 /**************************************************************************/
4946 /// Root (20 bytes + UTF-8 Version String + quad align padding)
4947 /// StreamHeaders (8 bytes + null terminated name string + quad align padding)
4949 /// #~ (always present - holds metadata tables)
4950 /// #Strings (always present - holds identifier strings)
4951 /// #US (Userstring heap)
4952 /// #Blob (signature blobs)
4953 /// #GUID (guids for assemblies or Modules)
4955 public class MetaData {
4957 internal static readonly int[] CIxShiftMap = {2,2,5,1,2,3,1,1,1,2,3,2,1};
4958 private static readonly byte StringsHeapMask = 0x1;
4959 private static readonly byte GUIDHeapMask = 0x2;
4960 private static readonly byte BlobHeapMask = 0x4;
4961 private static readonly uint MetaDataSignature = 0x424A5342;
4962 private static readonly uint maxSmlIxSize = 0xFFFF;
4963 private static readonly uint max1BitSmlIx = 0x7FFF;
4964 private static readonly uint max2BitSmlIx = 0x3FFF;
4965 private static readonly uint max3BitSmlIx = 0x1FFF;
4966 private static readonly uint max5BitSmlIx = 0x7FF;
4967 // NOTE: version and stream name strings MUST always be quad padded
4968 private static readonly string version = "v4.0.30319\0\0";
4969 private static readonly char[] tildeName = {'#','~','\0','\0'};
4970 private static readonly char[] stringsName = {'#','S','t','r','i','n','g','s','\0','\0','\0','\0'};
4971 private static readonly char[] usName = {'#','U','S','\0'};
4972 private static readonly char[] guidName = {'#','G','U','I','D','\0','\0','\0'};
4973 private static readonly char[] blobName = {'#','B','l','o','b','\0','\0','\0'};
4974 private static readonly uint MetaDataHeaderSize = 20 + (uint)version.Length;
4975 private static readonly uint TildeHeaderSize = 24;
4976 private static readonly uint StreamHeaderSize = 8;
4977 private static readonly uint numMetaDataTables = (int)MDTable.GenericParamConstraint + 1;
4979 MetaDataStream strings, us, guid, blob;
4981 MetaDataStream[] streams = new MetaDataStream[5];
4982 uint numStreams = 5;
4983 uint tildeTide = 0, tildePadding = 0, tildeStart = 0;
4984 uint numTables = 0, resourcesSize = 0;
4985 ArrayList[] metaDataTables = new ArrayList[numMetaDataTables];
4986 ArrayList byteCodes = new ArrayList();
4987 uint codeSize = 0, codeStart, byteCodePadding = 0, metaDataSize = 0;
4988 ulong valid = 0, /*sorted = 0x000002003301FA00;*/ sorted = 0;
4989 bool[] largeIx = new bool[numMetaDataTables];
4990 bool[] lgeCIx = new bool[(int)CIx.MaxCIx];
4991 bool largeStrings = false, largeUS = false, largeGUID = false, largeBlob = false;
4992 private FileImage file;
4993 private byte heapSizes = 0;
4994 MetaDataElement entryPoint;
4995 BinaryWriter output;
4996 public MSCorLib mscorlib;
4997 private TypeSpec[] systemTypeSpecs = new TypeSpec[PrimitiveType.NumSystemTypes];
4999 private ArrayList cattr_list;
5000 private ArrayList declsec_list;
5001 ArrayList resources;
5003 internal MetaData(FileImage file)
5005 // tilde = new MetaDataStream(tildeName,false,0);
5007 strings = new MetaDataStream(stringsName,new UTF8Encoding(),true);
5008 us = new MetaDataStream(usName,new UnicodeEncoding(),true);
5009 guid = new MetaDataStream(guidName,false);
5010 blob = new MetaDataStream(blobName,true);
5011 streams[1] = strings;
5015 for (int i=0; i < numMetaDataTables; i++) {
5018 for (int i=0; i < lgeCIx.Length; i++) {
5021 mscorlib = new MSCorLib(this);
5024 internal TypeSpec GetPrimitiveTypeSpec(int ix)
5026 return systemTypeSpecs[ix];
5029 internal void SetPrimitiveTypeSpec(int ix, TypeSpec typeSpec)
5031 systemTypeSpecs[ix] = typeSpec;
5034 internal uint Size()
5036 return metaDataSize;
5039 private void CalcHeapSizes ()
5041 if (strings.LargeIx()) {
5042 largeStrings = true;
5043 heapSizes |= StringsHeapMask;
5045 if (guid.LargeIx()) {
5047 heapSizes |= GUIDHeapMask;
5049 if (blob.LargeIx()) {
5051 heapSizes |= BlobHeapMask;
5054 largeUS = us.LargeIx();
5057 internal void StreamSize(byte mask)
5062 internal uint AddToUSHeap(string str)
5064 if (str == null) return 0;
5065 return us.Add(str,true);
5068 internal uint AddToUSHeap(byte[] str)
5070 if (str == null) return 0;
5071 return us.Add (str, true);
5074 internal uint AddToStringsHeap(string str)
5076 if ((str == null) || (str.CompareTo("") == 0)) return 0;
5077 return strings.Add(str,false);
5080 internal uint AddToGUIDHeap(Guid guidNum)
5082 return guid.Add(guidNum, false);
5085 internal uint AddToBlobHeap(byte[] blobBytes)
5087 if (blobBytes == null) return 0;
5088 return blob.Add(blobBytes, true);
5091 internal uint AddToBlobHeap(byte val)
5093 return blob.Add(val, true);
5096 internal uint AddToBlobHeap(sbyte val)
5098 return blob.Add(val, true);
5101 internal uint AddToBlobHeap(ushort val)
5103 return blob.Add(val, true);
5106 internal uint AddToBlobHeap(short val)
5108 return blob.Add(val, true);
5111 internal uint AddToBlobHeap(uint val)
5113 return blob.Add(val, true);
5116 internal uint AddToBlobHeap(int val)
5118 return blob.Add(val, true);
5121 internal uint AddToBlobHeap(ulong val)
5123 return blob.Add(val, true);
5126 internal uint AddToBlobHeap(long val)
5128 return blob.Add(val, true);
5131 internal uint AddToBlobHeap(float val)
5133 return blob.Add(val, true);
5136 internal uint AddToBlobHeap(double val)
5138 return blob.Add(val, true);
5141 internal uint AddToBlobHeap(string val)
5143 return blob.Add(val,true);
5146 internal void AddCustomAttribute (CustomAttribute cattr)
5148 if (cattr_list == null)
5149 cattr_list = new ArrayList ();
5150 cattr_list.Add (cattr);
5153 internal void AddDeclSecurity (BaseDeclSecurity decl_sec)
5155 if (declsec_list == null)
5156 declsec_list = new ArrayList ();
5157 declsec_list.Add (decl_sec);
5160 private ArrayList GetTable(MDTable tableIx)
5162 int tabIx = (int)tableIx;
5163 if (metaDataTables[tabIx] == null) {
5164 metaDataTables[tabIx] = new ArrayList();
5165 valid |= ((ulong)0x1 << tabIx);
5166 // Console.WriteLine("after creating table " + tableIx + "(" + tabIx + ") valid = " + valid);
5169 return metaDataTables[tabIx];
5172 internal void AddToTable(MDTable tableIx, MetaDataElement elem)
5175 // Console.Out.WriteLine("ERROR - element already in table " + tableIx);
5178 // updates Row field of the element
5179 // Console.WriteLine("Adding element to table " + (uint)tableIx);
5180 ArrayList table = GetTable(tableIx);
5181 elem.Row = (uint)table.Count + 1;
5185 internal uint TableIndex(MDTable tableIx)
5187 if (metaDataTables[(int)tableIx] == null) return 1;
5188 return (uint)metaDataTables[(int)tableIx].Count+1;
5191 internal uint AddCode(CILInstructions byteCode)
5193 byteCodes.Add(byteCode);
5194 uint offset = codeSize + codeStart;
5195 codeSize += byteCode.GetCodeSize();
5199 internal void SetEntryPoint(MetaDataElement ep)
5204 internal uint AddResource(byte[] resBytes)
5206 if (resources == null) resources = new ArrayList ();
5207 resources.Add (resBytes);
5208 uint offset = resourcesSize;
5209 resourcesSize += (uint)resBytes.Length + 4;
5213 internal void AddData(DataConstant cVal)
5215 file.AddInitData(cVal);
5218 internal static void CompressNum(uint val, MemoryStream sig)
5221 sig.WriteByte((byte)val);
5222 } else if (val <= 0x3FFF) {
5223 byte b1 = (byte)((val >> 8) | 0x80);
5224 byte b2 = (byte)(val & FileImage.iByteMask[0]);
5228 byte b1 = (byte)((val >> 24) | 0xC0);
5229 byte b2 = (byte)((val & FileImage.iByteMask[2]) >> 16);
5230 byte b3 = (byte)((val & FileImage.iByteMask[1]) >> 8);;
5231 byte b4 = (byte)(val & FileImage.iByteMask[0]);
5239 internal uint CodeSize()
5241 return codeSize + byteCodePadding;
5244 internal uint GetResourcesSize()
5246 return resourcesSize;
5249 internal uint StringsIndexSize()
5251 if (largeStrings) return 4;
5255 internal uint GUIDIndexSize()
5257 if (largeGUID) return 4;
5261 internal uint USIndexSize()
5263 if (largeUS) return 4;
5267 internal uint BlobIndexSize()
5269 if (largeBlob) return 4;
5273 internal uint CodedIndexSize(CIx code)
5275 if (lgeCIx[(uint)code]) return 4;
5279 internal uint TableIndexSize(MDTable tabIx)
5281 if (largeIx[(uint)tabIx]) return 4;
5285 private void SetIndexSizes()
5287 for (int i=0; i < numMetaDataTables; i++) {
5288 if (metaDataTables[i] == null)
5291 uint count = (uint)metaDataTables[i].Count;
5292 if (count > maxSmlIxSize)
5295 MDTable tabIx = (MDTable)i;
5296 if (count > max5BitSmlIx) {
5297 lgeCIx[(int)CIx.HasCustomAttr] = true;
5299 if (count > max3BitSmlIx) {
5300 if ((tabIx == MDTable.TypeRef) || (tabIx == MDTable.ModuleRef) || (tabIx == MDTable.Method) || (tabIx == MDTable.TypeSpec) || (tabIx == MDTable.Field))
5301 lgeCIx[(int)CIx.CustomAttributeType] = true;
5302 if ((tabIx == MDTable.Method) || (tabIx == MDTable.MemberRef))
5303 lgeCIx[(int)CIx.MemberRefParent] = true;
5305 if (count > max2BitSmlIx) {
5306 if ((tabIx == MDTable.Field) || (tabIx == MDTable.Param) || (tabIx == MDTable.Property))
5307 lgeCIx[(int)CIx.HasConst] = true;
5308 if ((tabIx == MDTable.TypeDef) || (tabIx == MDTable.TypeRef) || (tabIx == MDTable.TypeSpec))
5309 lgeCIx[(int)CIx.TypeDefOrRef] = true;
5310 if ((tabIx == MDTable.TypeDef) || (tabIx == MDTable.Method) || (tabIx == MDTable.Assembly))
5311 lgeCIx[(int)CIx.HasDeclSecurity] = true;
5312 if ((tabIx == MDTable.File) || (tabIx == MDTable.AssemblyRef) || (tabIx == MDTable.ExportedType))
5313 lgeCIx[(int)CIx.Implementation] = true;
5314 if ((tabIx == MDTable.Module) || (tabIx == MDTable.ModuleRef) || (tabIx == MDTable.AssemblyRef) || (tabIx == MDTable.TypeRef))
5315 lgeCIx[(int)CIx.ResolutionScope] = true;
5317 if (count > max1BitSmlIx) {
5318 if ((tabIx == MDTable.Field) || (tabIx == MDTable.Param))
5319 lgeCIx[(int)CIx.HasFieldMarshal] = true;
5320 if ((tabIx == MDTable.Event) || (tabIx == MDTable.Property))
5321 lgeCIx[(int)CIx.HasSemantics] = true;
5322 if ((tabIx == MDTable.Method) || (tabIx == MDTable.MemberRef))
5323 lgeCIx[(int)CIx.MethodDefOrRef] = true;
5324 if ((tabIx == MDTable.Field) || (tabIx == MDTable.Method))
5325 lgeCIx[(int)CIx.MemberForwarded] = true;
5326 if ((tabIx == MDTable.TypeDef) || (tabIx == MDTable.Method))
5327 lgeCIx[(int)CIx.TypeOrMethodDef] = true;
5332 private void SetStreamOffsets()
5334 uint sizeOfHeaders = StreamHeaderSize + (uint)tildeName.Length;
5335 for (int i=1; i < numStreams; i++) {
5336 sizeOfHeaders += streams[i].headerSize();
5338 metaDataSize = MetaDataHeaderSize + sizeOfHeaders;
5339 tildeStart = metaDataSize;
5340 metaDataSize += tildeTide + tildePadding;
5341 for (int i=1; i < numStreams; i++) {
5342 streams[i].Start = metaDataSize;
5343 metaDataSize += streams[i].Size();
5344 streams[i].WriteDetails();
5348 internal void CalcTildeStreamSize()
5351 //tilde.SetIndexSizes(strings.LargeIx(),us.LargeIx(),guid.LargeIx(),blob.LargeIx());
5352 tildeTide = TildeHeaderSize;
5353 tildeTide += 4 * numTables;
5354 //Console.WriteLine("Tilde header + sizes = " + tildeTide);
5355 for (int i=0; i < numMetaDataTables; i++) {
5356 if (metaDataTables[i] != null) {
5357 ArrayList table = metaDataTables[i];
5358 // Console.WriteLine("Meta data table " + i + " at offset " + tildeTide);
5359 tildeTide += (uint)table.Count * ((MetaDataElement)table[0]).Size(this);
5360 // Console.WriteLine("Metadata table " + i + " has size " + table.Count);
5361 // Console.WriteLine("tildeTide = " + tildeTide);
5364 if ((tildeTide % 4) != 0) tildePadding = 4 - (tildeTide % 4);
5365 //Console.WriteLine("tildePadding = " + tildePadding);
5368 internal void WriteTildeStream(FileImage output)
5370 output.Seek(0,SeekOrigin.Current);
5371 output.Write((uint)0); // Reserved
5372 output.Write((byte)2); // MajorVersion
5373 output.Write((byte)0); // MinorVersion
5374 output.Write(heapSizes);
5375 output.Write((byte)1); // Reserved
5376 output.Write(valid);
5377 output.Write(sorted);
5379 for (int i=0; i < numMetaDataTables; i++) {
5380 if (metaDataTables[i] != null) {
5381 uint count = (uint)metaDataTables[i].Count;
5382 output.Write(count);
5386 output.Seek(0,SeekOrigin.Current);
5387 // Console.WriteLine("Starting metaData tables at " + tabStart);
5388 for (int i=0; i < numMetaDataTables; i++) {
5389 if (metaDataTables[i] != null) {
5390 // Console.WriteLine("Starting metaData table " + i + " at " + (output.Seek(0,SeekOrigin.Current) - startTilde));
5391 ArrayList table = metaDataTables[i];
5392 for (int j=0; j < table.Count; j++) {
5393 ((MetaDataElement)table[j]).Write(output);
5397 // Console.WriteLine("Writing padding at " + output.Seek(0,SeekOrigin.Current));
5398 for (int i=0; i < tildePadding; i++) output.Write((byte)0);
5401 private void BuildTable(ArrayList table)
5403 if (table == null) return;
5404 for (int j=0; j < table.Count; j++) {
5405 ((MetaDataElement)table[j]).BuildTables(this);
5409 private void SortTable (ArrayList mTable)
5411 if (mTable == null) return;
5413 for (int i=0; i < mTable.Count; i++) {
5414 ((MetaDataElement)mTable[i]).Row = (uint)i+1;
5418 internal void BuildMetaData(uint codeStartOffset)
5420 codeStart = codeStartOffset;
5421 BuildTable(metaDataTables[(int)MDTable.TypeDef]);
5422 BuildTable(metaDataTables[(int)MDTable.TypeSpec]);
5423 BuildTable(metaDataTables[(int)MDTable.MemberRef]);
5424 BuildTable(metaDataTables[(int)MDTable.GenericParam]);
5425 BuildTable(metaDataTables[(int)MDTable.MethodSpec]);
5426 BuildTable(metaDataTables[(int)MDTable.GenericParamConstraint]);
5427 BuildTable(metaDataTables[(int)MDTable.ManifestResource]);
5429 if (cattr_list != null) {
5430 foreach (CustomAttribute cattr in cattr_list)
5431 cattr.BuildTables (this);
5434 if (declsec_list != null) {
5435 foreach (BaseDeclSecurity decl_sec in declsec_list)
5436 decl_sec.BuildTables (this);
5439 /* for (int i=0; i < metaDataTables.Length; i++) {
5440 ArrayList table = metaDataTables[i];
5441 if (table != null) {
5442 for (int j=0; j < table.Count; j++) {
5443 ((MetaDataElement)table[j]).BuildTables(this);
5450 for (int i=1; i < numStreams; i++) {
5451 streams[i].EndStream();
5453 CalcTildeStreamSize();
5455 byteCodePadding = NumToAlign(codeSize,4);
5456 if (entryPoint != null) file.SetEntryPoint(entryPoint.Token());
5458 // Check ordering of specific tables
5459 // Constant, CustomAttribute, FieldMarshal, DeclSecurity, MethodSemantics
5460 // ImplMap, GenericParam
5461 // Need to load GenericParamConstraint AFTER GenericParam table in correct order
5463 // InterfaceImpl, ClassLayout, FieldLayout, MethodImpl, FieldRVA, NestedClass
5464 // will _ALWAYS_ be in the correct order as embedded in BuildMDTables
5466 SortTable(metaDataTables[(int)MDTable.Constant]);
5467 SortTable(metaDataTables[(int)MDTable.FieldMarshal]);
5468 SortTable(metaDataTables[(int)MDTable.DeclSecurity]);
5469 SortTable(metaDataTables[(int)MDTable.MethodSemantics]);
5470 SortTable(metaDataTables[(int)MDTable.ImplMap]);
5471 if (metaDataTables[(int)MDTable.GenericParam] != null) {
5472 SortTable(metaDataTables[(int)MDTable.GenericParam]);
5473 // Now add GenericParamConstraints
5474 /*for (int i=0; i < metaDataTables[(int)MDTable.GenericParam].Count; i++) {
5475 ((GenericParameter)metaDataTables[(int)MDTable.GenericParam][i]).AddConstraints(this);
5478 SortTable(metaDataTables[(int)MDTable.GenericParamConstraint]);
5479 SortTable(metaDataTables[(int)MDTable.InterfaceImpl]);
5480 SortTable(metaDataTables[(int)MDTable.CustomAttribute]);
5484 internal void WriteByteCodes(FileImage output)
5486 for (int i=0; i < byteCodes.Count; i++) {
5487 ((CILInstructions)byteCodes[i]).Write(output);
5489 for (int i=0; i < byteCodePadding; i++) {
5490 output.Write((byte)0);
5494 internal void WriteResources (FileImage output)
5496 if (resources == null) return;
5497 for (int i = 0; i < resources.Count; i ++) {
5498 byte [] resBytes = (byte []) resources [i];
5499 output.Write ((uint) resBytes.Length);
5500 output.Write (resBytes);
5504 internal void WriteMetaData(FileImage output)
5506 this.output = output;
5507 mdStart = output.Seek(0,SeekOrigin.Current);
5508 // Console.WriteLine("Writing metaData at " + Hex.Long(mdStart));
5509 output.Write(MetaDataSignature);
5510 output.Write((short)1); // Major Version
5511 output.Write((short)1); // Minor Version ECMA = 0, PEFiles = 1
5512 output.Write(0); // Reserved
5513 output.Write(version.Length);
5514 output.Write(version.ToCharArray()); // version string is already zero padded
5515 output.Write((short)0);
5516 output.Write((ushort)numStreams);
5517 // write tilde header
5518 output.Write(tildeStart);
5519 output.Write(tildeTide + tildePadding);
5520 output.Write(tildeName);
5521 for (int i=1; i < numStreams; i++) streams[i].WriteHeader(output);
5522 // Console.WriteLine("Writing tilde stream at " + output.Seek(0,SeekOrigin.Current) + " = " + tildeStart);
5523 WriteTildeStream(output);
5524 for (int i=1; i < numStreams; i++) streams[i].Write(output);
5525 // Console.WriteLine("Finished Writing metaData at " + output.Seek(0,SeekOrigin.Current));
5528 internal bool LargeStringsIndex() { return strings.LargeIx(); }
5529 internal bool LargeGUIDIndex() { return guid.LargeIx(); }
5530 internal bool LargeUSIndex() { return us.LargeIx(); }
5531 internal bool LargeBlobIndex() { return blob.LargeIx(); }
5533 internal bool LargeIx(MDTable tabIx) { return largeIx[(uint)tabIx]; }
5536 private uint NumToAlign(uint val, uint alignVal)
5538 if ((val % alignVal) == 0) return 0;
5539 return alignVal - (val % alignVal);
5542 internal void WriteCodedIndex(CIx code, MetaDataElement elem, FileImage output)
5546 ix = (elem.Row << CIxShiftMap[(uint)code]) | elem.GetCodedIx(code);
5547 // Console.WriteLine("coded index = " + ix + " row = " + elem.Row);
5549 // Console.WriteLine("elem for coded index is null");
5551 if (lgeCIx[(uint)code])
5554 output.Write((ushort)ix);
5559 /**************************************************************************/
5561 /// Stream in the Meta Data (#Strings, #US, #Blob and #GUID)
5564 internal class MetaDataStream : BinaryWriter {
5566 private static readonly uint StreamHeaderSize = 8;
5567 private static uint maxSmlIxSize = 0xFFFF;
5569 private uint start = 0;
5570 uint size = 0, tide = 1;
5571 bool largeIx = false;
5574 Hashtable htable = new Hashtable();
5575 Hashtable btable = new Hashtable (new ByteArrayHashCodeProvider (), new ByteArrayComparer ());
5577 internal MetaDataStream(char[] name, bool addInitByte) : base(new MemoryStream())
5579 if (addInitByte) { Write((byte)0); size = 1; }
5581 sizeOfHeader = StreamHeaderSize + (uint)name.Length;
5584 internal MetaDataStream(char[] name, System.Text.Encoding enc, bool addInitByte) : base(new MemoryStream(),enc)
5586 if (addInitByte) { Write((byte)0); size = 1; }
5588 sizeOfHeader = StreamHeaderSize + (uint)name.Length;
5592 get { return start; }
5593 set { start = value; }
5596 internal uint headerSize()
5598 // Console.WriteLine(name + " stream has headersize of " + sizeOfHeader);
5599 return sizeOfHeader;
5602 internal void SetSize(uint siz)
5607 internal uint Size()
5612 internal bool LargeIx()
5617 internal void WriteDetails()
5619 // Console.WriteLine(name + " - size = " + size);
5622 internal uint Add(string str, bool prependSize)
5624 Object val = htable[str];
5628 htable[str] = index;
5629 char[] arr = str.ToCharArray();
5630 if (prependSize) CompressNum((uint)arr.Length*2+1);
5633 size = (uint)Seek(0,SeekOrigin.Current);
5639 internal uint Add (byte[] str, bool prependSize)
5641 Object val = btable [str];
5645 btable [str] = index;
5646 if (prependSize) CompressNum ((uint) str.Length);
5648 size = (uint) Seek (0, SeekOrigin.Current);
5656 internal uint Add(Guid guid, bool prependSize)
5658 byte [] b = guid.ToByteArray ();
5659 if (prependSize) CompressNum ((uint) b.Length);
5660 Write(guid.ToByteArray());
5661 size =(uint)Seek(0,SeekOrigin.Current);
5665 internal uint Add(byte[] blob)
5668 CompressNum((uint)blob.Length);
5670 size = (uint)Seek(0,SeekOrigin.Current);
5674 internal uint Add(byte val, bool prependSize)
5677 if (prependSize) CompressNum (1);
5679 size = (uint)Seek(0,SeekOrigin.Current);
5683 internal uint Add(sbyte val, bool prependSize)
5686 if (prependSize) CompressNum (1);
5688 size = (uint)Seek(0,SeekOrigin.Current);
5692 internal uint Add(ushort val, bool prependSize)
5695 if (prependSize) CompressNum (2);
5697 size = (uint)Seek(0,SeekOrigin.Current);
5701 internal uint Add(short val, bool prependSize)
5704 if (prependSize) CompressNum (2);
5706 size = (uint)Seek(0,SeekOrigin.Current);
5710 internal uint Add(uint val, bool prependSize)
5713 if (prependSize) CompressNum (4);
5715 size = (uint)Seek(0,SeekOrigin.Current);
5719 internal uint Add(int val, bool prependSize)
5722 if (prependSize) CompressNum (4);
5724 size = (uint)Seek(0,SeekOrigin.Current);
5728 internal uint Add(ulong val, bool prependSize)
5731 if (prependSize) CompressNum (8);
5733 size = (uint)Seek(0,SeekOrigin.Current);
5737 internal uint Add(long val, bool prependSize)
5740 if (prependSize) CompressNum (8);
5742 size = (uint)Seek(0,SeekOrigin.Current);
5746 internal uint Add(float val, bool prependSize)
5749 if (prependSize) CompressNum (4);
5751 size = (uint)Seek(0,SeekOrigin.Current);
5755 internal uint Add(double val, bool prependSize)
5758 if (prependSize) CompressNum (8);
5760 size = (uint)Seek(0,SeekOrigin.Current);
5764 private void CompressNum(uint val)
5768 } else if (val < 0x3FFF) {
5769 byte b1 = (byte)((val >> 8) | 0x80);
5770 byte b2 = (byte)(val & FileImage.iByteMask[0]);
5774 byte b1 = (byte)((val >> 24) | 0xC0);
5775 byte b2 = (byte)((val & FileImage.iByteMask[2]) >> 16);
5776 byte b3 = (byte)((val & FileImage.iByteMask[1]) >> 8);;
5777 byte b4 = (byte)(val & FileImage.iByteMask[0]);
5785 private void QuadAlign()
5787 if ((size % 4) != 0) {
5788 uint pad = 4 - (size % 4);
5790 for (int i=0; i < pad; i++) {
5796 internal void EndStream()
5799 if (size > maxSmlIxSize) {
5804 internal void WriteHeader(BinaryWriter output)
5806 output.Write(start);
5811 internal virtual void Write(BinaryWriter output)
5813 // Console.WriteLine("Writing " + name + " stream at " + output.Seek(0,SeekOrigin.Current) + " = " + start);
5814 MemoryStream str = (MemoryStream)BaseStream;
5815 output.Write(str.ToArray());
5820 /**************************************************************************/
5821 class ByteArrayComparer : IComparer {
5823 public int Compare (object x, object y)
5825 byte [] a = (byte []) x;
5826 byte [] b = (byte []) y;
5829 if (b.Length != len)
5832 for (int i = 0; i < len; ++i)
5839 class ByteArrayHashCodeProvider : IHashCodeProvider {
5841 public int GetHashCode (Object key)
5843 byte [] arr = (byte []) key;
5844 int len = arr.Length;
5847 for (int i = 0; i < len; ++i)
5848 h = (h << 5) - h + arr [i];