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 {
3319 /// Create a new custom modifier for a type
3321 /// <param name="type">the type to be modified</param>
3322 /// <param name="cmod">the modifier</param>
3323 /// <param name="cmodType">the type reference to be associated with the type</param>
3324 public CustomModifiedType(Type type, CustomModifier cmod, Class cmodType)
3328 this.cmodType = cmodType;
3331 internal sealed override void TypeSig(MemoryStream str)
3333 str.WriteByte(typeIndex);
3334 MetaData.CompressNum(cmodType.TypeDefOrRefToken(),str);
3340 /**************************************************************************/
3342 /// Base class for Event and Property descriptors
3345 public class Feature : MetaDataElement {
3347 internal enum MethodType : ushort { Setter = 0x01, Getter, Other = 0x04, AddOn = 0x08,
3348 RemoveOn = 0x10, Fire = 0x20 }
3350 private static readonly int INITSIZE = 5;
3351 private static readonly ushort specialName = 0x200;
3352 private static readonly ushort rtSpecialName = 0x400;
3354 protected ClassDef parent;
3355 protected ushort flags = 0;
3356 protected string name;
3357 protected int tide = 0;
3358 protected uint nameIx;
3359 protected MethodSemantics[] methods = new MethodSemantics[INITSIZE];
3361 internal Feature(string name, ClassDef par)
3367 internal void AddMethod(MethodDef meth, MethodType mType)
3369 if (tide >= methods.Length) {
3370 int len = methods.Length;
3371 MethodSemantics[] mTmp = methods;
3372 methods = new MethodSemantics[len * 2];
3373 for (int i=0; i < len; i++) {
3374 methods[i] = mTmp[i];
3377 methods[tide++] = new MethodSemantics(mType,meth,this);
3381 /// Set the specialName attribute for this Event or Property
3383 public void SetSpecialName()
3385 flags |= specialName;
3389 /// Set the RTSpecialName attribute for this Event or Property
3391 public void SetRTSpecialName()
3393 flags |= rtSpecialName;
3398 /**************************************************************************/
3400 /// Descriptor for an event
3402 public class Event : Feature {
3406 internal Event(string name, Type eType, ClassDef parent)
3407 : base(name, parent)
3410 tabIx = MDTable.Event;
3414 /// Add the addon method to this event
3416 /// <param name="addon">the addon method</param>
3417 public void AddAddon(MethodDef addon)
3419 AddMethod(addon,MethodType.AddOn);
3423 /// Add the removeon method to this event
3425 /// <param name="removeOn">the removeon method</param>
3426 public void AddRemoveOn(MethodDef removeOn)
3428 AddMethod(removeOn,MethodType.RemoveOn);
3432 /// Add the fire method to this event
3434 /// <param name="fire">the fire method</param>
3435 public void AddFire(MethodDef fire)
3437 AddMethod(fire,MethodType.Fire);
3441 /// Add another method to this event
3443 /// <param name="other">the method to be added</param>
3444 public void AddOther(MethodDef other)
3446 AddMethod(other,MethodType.Other);
3449 internal sealed override void BuildTables(MetaData md)
3452 nameIx = md.AddToStringsHeap(name);
3453 for (int i=0; i < tide; i++) {
3454 md.AddToTable(MDTable.MethodSemantics,methods[i]);
3459 internal sealed override uint Size(MetaData md)
3461 return 2 + md.StringsIndexSize() + md.CodedIndexSize(CIx.TypeDefOrRef);
3464 internal sealed override void Write(FileImage output)
3466 output.Write(flags);
3467 output.StringsIndex(nameIx);
3468 output.WriteCodedIndex(CIx.TypeDefOrRef,eventType);
3471 internal sealed override uint GetCodedIx(CIx code)
3474 case (CIx.HasCustomAttr) : return 10;
3475 case (CIx.HasSemantics) : return 0;
3482 /**************************************************************************/
3484 /// Descriptor for the Property of a class
3486 public class Property : Feature {
3488 private static readonly byte PropertyTag = 0x8;
3489 private bool instance;
3490 MethodDef getterMeth;
3491 ConstantElem constVal;
3492 uint typeBlobIx = 0;
3497 internal Property(string name, Type retType, Type[] pars, ClassDef parent) : base(name, parent)
3499 returnType = retType;
3501 if (pars != null) numPars = (uint)pars.Length;
3502 tabIx = MDTable.Property;
3506 /// Add a set method to this property
3508 /// <param name="setter">the set method</param>
3509 public void AddSetter(MethodDef setter)
3511 AddMethod(setter,MethodType.Setter);
3515 /// Add a get method to this property
3517 /// <param name="getter">the get method</param>
3518 public void AddGetter(MethodDef getter)
3520 AddMethod(getter,MethodType.Getter);
3521 getterMeth = getter;
3525 /// Add another method to this property
3527 /// <param name="other">the method</param>
3528 public void AddOther(MethodDef other)
3530 AddMethod(other,MethodType.Other);
3534 /// Add an initial value for this property
3536 /// <param name="constVal">the initial value for this property</param>
3537 public void AddInitValue(Constant constVal)
3539 this.constVal = new ConstantElem(this,constVal);
3542 public void SetInstance (bool isInstance)
3544 this.instance = isInstance;
3547 internal sealed override void BuildTables(MetaData md)
3550 nameIx = md.AddToStringsHeap(name);
3551 MemoryStream sig = new MemoryStream();
3552 byte tag = PropertyTag;
3556 MetaData.CompressNum(numPars,sig);
3557 returnType.TypeSig(sig);
3558 for (int i=0; i < numPars; i++) {
3559 parList[i].TypeSig(sig);
3561 typeBlobIx = md.AddToBlobHeap(sig.ToArray());
3562 for (int i=0; i < tide; i++) {
3563 md.AddToTable(MDTable.MethodSemantics,methods[i]);
3565 if (constVal != null) {
3566 md.AddToTable(MDTable.Constant,constVal);
3567 constVal.BuildTables(md);
3572 internal sealed override uint Size(MetaData md)
3574 return 2 + md.StringsIndexSize() + md.BlobIndexSize();
3577 internal sealed override void Write(FileImage output)
3579 output.Write(flags);
3580 output.StringsIndex(nameIx);
3581 output.BlobIndex(typeBlobIx);
3584 internal sealed override uint GetCodedIx(CIx code)
3587 case (CIx.HasCustomAttr) : return 9;
3588 case (CIx.HasConst) : return 2;
3589 case (CIx.HasSemantics) : return 1;
3596 /**************************************************************************/
3598 /// Base class for field/methods (member of a class)
3600 public abstract class Member : MetaDataElement {
3602 protected string name;
3603 protected uint nameIx = 0, sigIx = 0;
3605 internal Member(string memName)
3608 tabIx = MDTable.MemberRef;
3613 /*****************************************************************************/
3615 /// Descriptor for a field of a class
3618 public abstract class Field : Member {
3620 protected static readonly byte FieldSig = 0x6;
3622 protected Type type;
3624 internal Field(string pfName, Type pfType) : base(pfName)
3630 /**************************************************************************/
3632 /// Descriptor for a field defined in a class of THIS assembly/module
3634 public class FieldDef : Field {
3636 //private static readonly uint PInvokeImpl = 0x2000;
3637 private static readonly ushort HasFieldRVA = 0x100;
3638 private static readonly ushort HasDefault = 0x8000;
3641 ConstantElem constVal;
3643 FieldMarshal marshalInfo;
3646 internal FieldDef(string name, Type fType) : base(name,fType)
3648 tabIx = MDTable.Field;
3651 internal FieldDef(FieldAttr attrSet, string name, Type fType) : base(name, fType)
3653 flags = (ushort)attrSet;
3654 tabIx = MDTable.Field;
3658 /// Add an attribute(s) to this field
3660 /// <param name="fa">the attribute(s) to be added</param>
3661 public void AddFieldAttr(FieldAttr fa)
3663 flags |= (ushort)fa;
3667 /// Add a value for this field
3669 /// <param name="val">the value for the field</param>
3670 public void AddValue(Constant val)
3672 constVal = new ConstantElem(this,val);
3673 flags |= HasDefault;
3677 /// Add an initial value for this field (at dataLabel) (.data)
3679 /// <param name="val">the value for the field</param>
3680 /// <param name="repeatVal">the number of repetitions of this value</param>
3681 public void AddDataValue(DataConstant val)
3683 flags |= HasFieldRVA;
3684 rva = new FieldRVA(this,val);
3688 /// Set the offset of the field. Used for sequential or explicit classes.
3691 /// <param name="offs">field offset</param>
3692 public void SetOffset(uint offs)
3694 layout = new FieldLayout(this,offs);
3698 /// Set the marshalling info for a field
3700 /// <param name="mInf"></param>
3701 public void SetMarshalInfo(NativeType marshallType)
3703 flags |= (ushort) FieldAttr.HasFieldMarshal;
3704 marshalInfo = new FieldMarshal(this,marshallType);
3707 internal sealed override void BuildTables(MetaData md)
3710 nameIx = md.AddToStringsHeap(name);
3711 MemoryStream sig = new MemoryStream();
3712 sig.WriteByte(FieldSig);
3714 sigIx = md.AddToBlobHeap(sig.ToArray());
3716 md.AddToTable(MDTable.FieldRVA,rva);
3717 rva.BuildTables(md);
3718 } else if (constVal != null) {
3719 md.AddToTable(MDTable.Constant,constVal);
3720 constVal.BuildTables(md);
3722 if (layout != null) md.AddToTable(MDTable.FieldLayout,layout);
3723 if (marshalInfo != null) {
3724 md.AddToTable(MDTable.FieldMarshal,marshalInfo);
3725 marshalInfo.BuildTables(md);
3730 internal sealed override uint Size(MetaData md)
3732 return 2 + md.StringsIndexSize() + md.BlobIndexSize();
3735 internal sealed override void Write(FileImage output)
3737 output.Write(flags);
3738 output.StringsIndex(nameIx);
3739 output.BlobIndex(sigIx);
3742 internal sealed override uint GetCodedIx(CIx code)
3745 case (CIx.HasConst) : return 0;
3746 case (CIx.HasCustomAttr) : return 1;
3747 case (CIx.HasFieldMarshal) : return 0;
3748 case (CIx.MemberForwarded) : return 0;
3755 /**************************************************************************/
3757 /// Descriptor for a field of a class defined in another assembly/module
3759 public class FieldRef : Field {
3761 MetaDataElement parent;
3763 internal FieldRef(MetaDataElement paren, string name, Type fType) : base(name, fType)
3768 internal sealed override void BuildTables(MetaData md)
3771 nameIx = md.AddToStringsHeap(name);
3772 MemoryStream sig = new MemoryStream();
3773 sig.WriteByte(FieldSig);
3775 sigIx = md.AddToBlobHeap(sig.ToArray());
3779 internal sealed override uint Size(MetaData md)
3781 return md.CodedIndexSize(CIx.MemberRefParent) + md.StringsIndexSize() + md.BlobIndexSize();
3784 internal sealed override void Write(FileImage output)
3786 output.WriteCodedIndex(CIx.MemberRefParent,parent);
3787 output.StringsIndex(nameIx);
3788 output.BlobIndex(sigIx);
3791 internal sealed override uint GetCodedIx(CIx code) { return 6; }
3795 /**************************************************************************/
3797 /// Base class for Method Descriptors
3800 public abstract class Method : Member {
3802 internal Method (string methName) : base (methName)
3805 public abstract void AddCallConv(CallConv cconv);
3806 internal abstract void TypeSig(MemoryStream sig);
3807 internal abstract uint GetSigIx(MetaData md);
3810 /**************************************************************************/
3812 /// Descriptor for a method defined in THIS assembly/module
3816 public class MethodDef : Method {
3818 private static readonly ushort PInvokeImpl = 0x2000;
3819 //private static readonly uint UnmanagedExport = 0x0008;
3820 // private static readonly byte LocalSigByte = 0x7;
3821 uint parIx = 0, textOffset = 0;
3822 private CallConv callConv = CallConv.Default;
3823 private int gen_param_count;
3826 CILInstructions code;
3830 ushort methFlags = 0, implFlags = 0;
3831 int maxStack = 0, numPars = 0;
3832 bool entryPoint = false;
3834 ArrayList varArgSigList;
3835 ImplMap pinvokeImpl;
3838 internal MethodDef (MetaData md, string name, Param ret_param, Param [] pars)
3839 : this (md, 0, 0, name, ret_param, pars)
3843 internal MethodDef (MetaData md, MethAttr mAttrSet, ImplAttr iAttrSet, string name,
3844 Param ret_param, Param [] pars)
3847 methFlags = (ushort)mAttrSet;
3848 implFlags = (ushort)iAttrSet;
3849 this.ret_param = ret_param;
3852 if (parList != null)
3853 numPars = parList.Length;
3854 tabIx = MDTable.Method;
3857 internal Param[] GetPars()
3862 internal override uint GetSigIx(MetaData md)
3864 MemoryStream sig = new MemoryStream();
3866 return md.AddToBlobHeap(sig.ToArray());
3869 public override void AddCallConv(CallConv cconv)
3875 /// Add some attributes to this method descriptor
3877 /// <param name="ma">the attributes to be added</param>
3878 public void AddMethAttribute(MethAttr ma)
3880 methFlags |= (ushort)ma;
3884 /// Add some implementation attributes to this method descriptor
3886 /// <param name="ia">the attributes to be added</param>
3887 public void AddImplAttribute(ImplAttr ia)
3889 implFlags |= (ushort)ia;
3892 public void AddPInvokeInfo(ModuleRef scope, string methName,
3893 PInvokeAttr callAttr) {
3894 pinvokeImpl = new ImplMap((ushort)callAttr,this,methName,scope);
3895 methFlags |= PInvokeImpl;
3899 /// Add a named generic type parameter
3901 public GenericParameter AddGenericParameter (short index, string name)
3903 return AddGenericParameter (index, name, 0);
3907 /// Add a named generic type parameter with attributes
3909 public GenericParameter AddGenericParameter (short index, string name, GenericParamAttributes attr)
3911 GenericParameter gp = new GenericParameter (this, metaData, index, name, attr);
3912 metaData.AddToTable (MDTable.GenericParam, gp);
3918 /// Set the maximum stack height for this method
3920 /// <param name="maxStack">the maximum height of the stack</param>
3921 public void SetMaxStack(int maxStack)
3923 this.maxStack = maxStack;
3927 /// Add local variables to this method
3929 /// <param name="locals">the locals to be added</param>
3930 /// <param name="initLocals">are locals initialised to default values</param>
3931 public void AddLocals(Local[] locals, bool initLocals)
3933 this.locals = locals;
3934 this.initLocals = initLocals;
3937 /* Add Marshal info for return type */
3938 public void AddRetTypeMarshallInfo (NativeType marshallType)
3940 ret_param.AddMarshallInfo (marshallType);
3944 /// Mark this method as having an entry point
3946 public void DeclareEntryPoint()
3952 /// Create a code buffer for this method to add the IL instructions to
3954 /// <returns>a buffer for this method's IL instructions</returns>
3955 public CILInstructions CreateCodeBuffer()
3957 code = new CILInstructions(metaData);
3962 /// Make a method reference descriptor for this method to be used
3963 /// as a callsite signature for this vararg method
3965 /// <param name="optPars">the optional pars for the vararg method call</param>
3966 /// <returns></returns>
3967 public MethodRef MakeVarArgSignature(Type[] optPars)
3969 Type[] pars = new Type[numPars];
3970 MethodRef varArgSig;
3971 for (int i=0; i < numPars; i++) {
3972 pars[i] = parList[i].GetParType();
3974 varArgSig = new MethodRef (this, name, ret_param.GetParType (), pars, true, optPars, 0);
3976 if (varArgSigList == null)
3977 varArgSigList = new ArrayList ();
3978 varArgSigList.Add (varArgSig);
3982 internal sealed override void TypeSig(MemoryStream sig)
3984 sig.WriteByte((byte)callConv);
3985 if ((callConv & CallConv.Generic) == CallConv.Generic)
3986 MetaData.CompressNum ((uint) gen_param_count, sig);
3987 MetaData.CompressNum((uint)numPars,sig);
3989 ret_param.seqNo = 0;
3990 ret_param.TypeSig (sig);
3991 for (ushort i=0; i < numPars; i++) {
3992 parList[i].seqNo = (ushort)(i+1);
3993 parList[i].TypeSig(sig);
3997 internal sealed override void BuildTables(MetaData md)
4000 if (pinvokeImpl != null) {
4001 md.AddToTable(MDTable.ImplMap,pinvokeImpl);
4002 pinvokeImpl.BuildTables(md);
4004 if (entryPoint) md.SetEntryPoint(this);
4006 if (locals != null) {
4007 localSig = new LocalSig(locals);
4008 md.AddToTable(MDTable.StandAloneSig,localSig);
4009 localSig.BuildTables(md);
4010 locToken = localSig.Token();
4013 code.CheckCode(locToken,initLocals,maxStack);
4014 textOffset = md.AddCode(code);
4016 nameIx = md.AddToStringsHeap(name);
4017 sigIx = GetSigIx(md);
4018 parIx = md.TableIndex(MDTable.Param);
4019 if (ret_param.HasMarshalInfo || ret_param.HasCustomAttr) {
4020 md.AddToTable(MDTable.Param, ret_param);
4021 ret_param.BuildTables(md);
4023 for (int i=0; i < numPars; i++) {
4024 md.AddToTable(MDTable.Param,parList[i]);
4025 parList[i].BuildTables(md);
4027 if (varArgSigList != null) {
4028 foreach (MethodRef varArgSig in varArgSigList) {
4029 md.AddToTable(MDTable.MemberRef,varArgSig);
4030 varArgSig.BuildTables(md);
4033 // Console.WriteLine("method has " + numPars + " parameters");
4037 internal sealed override uint Size(MetaData md)
4039 return 8 + md.StringsIndexSize() + md.BlobIndexSize() + md.TableIndexSize(MDTable.Param);
4042 internal sealed override void Write(FileImage output)
4044 if (ZeroRva ()) output.Write(0);
4045 else output.WriteCodeRVA(textOffset);
4046 output.Write(implFlags);
4047 output.Write(methFlags);
4048 output.StringsIndex(nameIx);
4049 output.BlobIndex(sigIx);
4050 output.WriteIndex(MDTable.Param,parIx);
4053 internal bool ZeroRva ()
4055 return (((methFlags & (ushort)MethAttr.Abstract) != 0) ||
4056 ((implFlags & (ushort)ImplAttr.Runtime) != 0) ||
4057 ((implFlags & (ushort)ImplAttr.InternalCall) != 0) ||
4058 (pinvokeImpl != null)); // TODO: Not entirely true but works for now
4061 internal sealed override uint GetCodedIx(CIx code)
4064 case (CIx.HasCustomAttr) : return 0;
4065 case (CIx.HasDeclSecurity) : return 1;
4066 case (CIx.MemberRefParent) : return 3;
4067 case (CIx.MethodDefOrRef) : return 0;
4068 case (CIx.MemberForwarded) : return 1;
4069 case (CIx.CustomAttributeType) : return 2;
4070 case (CIx.TypeOrMethodDef) : return 1;
4076 /**************************************************************************/
4078 /// Descriptor for a method defined in another assembly/module
4080 public class MethodRef : Method {
4082 private static readonly byte Sentinel = 0x41;
4083 Type[] parList, optParList;
4084 MetaDataElement parent;
4085 uint numPars = 0, numOptPars = 0;
4086 CallConv callConv = CallConv.Default;
4088 int gen_param_count;
4090 internal MethodRef(MetaDataElement paren, string name, Type retType,
4091 Type[] pars, bool varArgMeth, Type[] optPars, int gen_param_count) : base(name)
4095 this.retType = retType;
4096 if (parList != null) numPars = (uint)parList.Length;
4098 optParList = optPars;
4099 if (optParList != null) numOptPars = (uint)optParList.Length;
4100 callConv = CallConv.Vararg;
4102 this.gen_param_count = gen_param_count;
4105 internal override uint GetSigIx(MetaData md)
4107 MemoryStream sig = new MemoryStream();
4109 return md.AddToBlobHeap(sig.ToArray());
4112 public override void AddCallConv(CallConv cconv)
4117 internal sealed override void TypeSig(MemoryStream sig)
4119 sig.WriteByte((byte)callConv);
4120 if ((callConv & CallConv.Generic) == CallConv.Generic)
4121 MetaData.CompressNum ((uint) gen_param_count, sig);
4122 MetaData.CompressNum(numPars+numOptPars,sig);
4123 retType.TypeSig(sig);
4124 for (int i=0; i < numPars; i++) {
4125 parList[i].TypeSig(sig);
4127 if (numOptPars > 0) {
4128 sig.WriteByte(Sentinel);
4129 for (int i=0; i < numOptPars; i++) {
4130 optParList[i].TypeSig(sig);
4135 internal sealed override void BuildTables(MetaData md)
4138 nameIx = md.AddToStringsHeap(name);
4139 sigIx = GetSigIx(md);
4143 internal sealed override uint Size(MetaData md)
4145 return md.CodedIndexSize(CIx.MemberRefParent) + md.StringsIndexSize() + md.BlobIndexSize();
4148 internal sealed override void Write(FileImage output)
4150 output.WriteCodedIndex(CIx.MemberRefParent,parent);
4151 output.StringsIndex(nameIx);
4152 output.BlobIndex(sigIx);
4155 internal sealed override uint GetCodedIx(CIx code)
4158 case (CIx.HasCustomAttr) : return 6;
4159 case (CIx.MethodDefOrRef) : return 1;
4160 case (CIx.CustomAttributeType) : return 3;
4168 /**************************************************************************/
4170 /// Descriptors for native types used for marshalling
4172 public class NativeType {
4173 public static readonly NativeType Void = new NativeType(0x01);
4174 public static readonly NativeType Boolean = new NativeType(0x02);
4175 public static readonly NativeType Int8 = new NativeType(0x03);
4176 public static readonly NativeType UInt8 = new NativeType(0x04);
4177 public static readonly NativeType Int16 = new NativeType(0x05);
4178 public static readonly NativeType UInt16 = new NativeType(0x06);
4179 public static readonly NativeType Int32 = new NativeType(0x07);
4180 public static readonly NativeType UInt32 = new NativeType(0x08);
4181 public static readonly NativeType Int64 = new NativeType(0x09);
4182 public static readonly NativeType UInt64 = new NativeType(0x0A);
4183 public static readonly NativeType Float32 = new NativeType(0x0B);
4184 public static readonly NativeType Float64 = new NativeType(0x0C);
4185 public static readonly NativeType Currency = new NativeType(0x0F);
4186 public static readonly NativeType BStr = new NativeType(0x13);
4187 public static readonly NativeType LPStr = new NativeType(0x14);
4188 public static readonly NativeType LPWStr = new NativeType(0x15);
4189 public static readonly NativeType LPTStr = new NativeType(0x16);
4190 public static readonly NativeType FixedSysString = new NativeType(0x17);
4191 public static readonly NativeType IUnknown = new NativeType(0x19);
4192 public static readonly NativeType IDispatch = new NativeType(0x1A);
4193 public static readonly NativeType Struct = new NativeType(0x1B);
4194 public static readonly NativeType Interface = new NativeType(0x1C);
4195 public static readonly NativeType Int = new NativeType(0x1F);
4196 public static readonly NativeType UInt = new NativeType(0x20);
4197 public static readonly NativeType ByValStr = new NativeType(0x22);
4198 public static readonly NativeType AnsiBStr = new NativeType(0x23);
4199 public static readonly NativeType TBstr = new NativeType(0x24);
4200 public static readonly NativeType VariantBool = new NativeType(0x25);
4201 public static readonly NativeType FuncPtr = new NativeType(0x26);
4202 public static readonly NativeType AsAny = new NativeType(0x28);
4203 public static readonly NativeType LPStruct = new NativeType(0x2b);
4204 public static readonly NativeType Error = new NativeType(0x2d);
4206 protected byte typeIndex;
4208 internal NativeType(byte tyIx) { typeIndex = tyIx; }
4209 internal byte GetTypeIndex() { return typeIndex; }
4211 internal virtual byte[] ToBlob()
4213 byte[] bytes = new byte[1];
4214 bytes[0] = GetTypeIndex();
4220 public class FixedSysString : NativeType {
4224 public FixedSysString (uint size) : base (NativeType.FixedSysString.GetTypeIndex ())
4229 internal override byte [] ToBlob ()
4231 MemoryStream str = new MemoryStream ();
4232 str.WriteByte (GetTypeIndex ());
4233 MetaData.CompressNum (size, str);
4234 return str.ToArray ();
4239 public class NativeArray : NativeType {
4241 NativeType elemType;
4242 int numElem = -1, parNum = -1, elemMult = -1;
4244 public NativeArray(NativeType elemType) : this (elemType, -1, -1, -1)
4246 this.elemType = elemType;
4249 /* public NativeArray(NativeType elemType, int len) : base(0x2A) {
4250 this.elemType = elemType;
4255 public NativeArray(NativeType elemType, int numElem, int parNumForLen, int elemMult) : base(0x2A)
4257 this.elemType = elemType;
4258 this.numElem = numElem;
4259 parNum = parNumForLen;
4260 this.elemMult = elemMult;
4263 public NativeArray(NativeType elemType, int numElem, int parNumForLen)
4264 : this (elemType, numElem, parNumForLen, -1)
4268 internal override byte[] ToBlob()
4270 MemoryStream str = new MemoryStream();
4271 str.WriteByte(GetTypeIndex());
4272 if (elemType == null) str.WriteByte(0x50); // no info (MAX)
4273 else str.WriteByte(elemType.GetTypeIndex());
4275 /* see : mono/metadata/metadata.c:mono_metadata_parse_marshal_spec
4276 * LAMESPEC: Older spec versions say elemMult comes before
4277 * len. Newer spec versions don't talk about elemMult at
4278 * all, but csc still emits it, and it is used to distinguish
4279 * between parNum being 0, and parNum being omitted.
4284 return str.ToArray ();
4286 MetaData.CompressNum((uint) parNum,str);
4287 if (numElem != -1) {
4288 MetaData.CompressNum ((uint) numElem, str);
4290 // <native_type> [ int32 ]
4291 MetaData.CompressNum((uint) elemMult,str);
4292 //else <native_type> [ int32 + int32 ]
4293 } else if (elemMult != -1) {
4294 // When can this occur ?
4295 MetaData.CompressNum (0, str);
4296 MetaData.CompressNum((uint) elemMult,str);
4298 //else <native_type> [ + int32 ]
4300 return str.ToArray();
4305 public class SafeArray : NativeType {
4307 SafeArrayType elemType;
4310 public SafeArray() : base(0x1D)
4314 public SafeArray(SafeArrayType elemType) : base(0x1D)
4316 this.elemType = elemType;
4320 internal override byte[] ToBlob()
4322 byte[] bytes = new byte[hasElemType ? 2 : 1];
4323 bytes[0] = GetTypeIndex();
4325 bytes[1] = (byte)elemType;
4331 public class FixedArray : NativeType {
4335 //public FixedArray(NativeType elemType, int numElems) : base(0x1E) {
4336 public FixedArray(int numElems) : base(0x1E)
4338 //this.elemType = elemType;
4339 numElem = (uint)numElems;
4342 internal override byte[] ToBlob()
4344 MemoryStream str = new MemoryStream();
4345 str.WriteByte(GetTypeIndex());
4346 MetaData.CompressNum(numElem,str);
4348 fixed array [5] lpstr [2]
4349 This format is not supported by ilasm 1.1.4322.2032,
4350 but is supported by 2.0.5125..
4351 ilasm 1.1 only supports "fixed array [5]"
4352 if (elemType == null) str.WriteByte(0x50); // no info (MAX)
4353 else str.WriteByte(elemType.GetTypeIndex());*/
4355 return str.ToArray();
4360 public class CustomMarshaller : NativeType {
4363 string marshallerName;
4366 public CustomMarshaller(string typeNameOrGUID, string marshallerName,
4367 string optCookie) : base(0x2C)
4369 typeName = typeNameOrGUID;
4370 this.marshallerName = marshallerName;
4374 public CustomMarshaller(string marshallerName, string optCookie)
4375 :this (null, marshallerName, optCookie)
4379 internal override byte[] ToBlob()
4381 MemoryStream str = new MemoryStream();
4382 BinaryWriter bw = new BinaryWriter(str,new UTF8Encoding());
4383 bw.Write(GetTypeIndex());
4384 //Native type name & unmanaged type - unused
4385 //See mono/metadata/metadata.c : mono_metadata_parse_marshal_spec
4386 bw.Write ((byte) 0); // Native Type name, unused
4387 bw.Write ((byte) 0); // Unmanaged type, unused
4388 if (marshallerName != null) {
4389 MetaData.CompressNum ((uint)marshallerName.Length, str);
4390 bw.Write(marshallerName.ToCharArray());
4392 bw.Write ((byte) 0);
4394 if (cookie != null) {
4395 MetaData.CompressNum ((uint)cookie.Length, str);
4396 bw.Write(cookie.ToCharArray());
4398 bw.Write ((byte) 0);
4401 return str.ToArray();
4405 /**************************************************************************/
4407 /// Descriptor for the Primitive types defined in IL
4409 public class PrimitiveType : Type {
4411 private string name;
4412 private int systemTypeIndex;
4413 public static int NumSystemTypes = 18;
4415 public static readonly PrimitiveType Void = new PrimitiveType(0x01,"Void",0);
4416 public static readonly PrimitiveType Boolean = new PrimitiveType(0x02,"Boolean",1);
4417 public static readonly PrimitiveType Char = new PrimitiveType(0x03,"Char",2);
4418 public static readonly PrimitiveType Int8 = new PrimitiveType(0x04,"SByte",3);
4419 public static readonly PrimitiveType UInt8 = new PrimitiveType(0x05,"Byte",4);
4420 public static readonly PrimitiveType Int16 = new PrimitiveType(0x06,"Int16",5);
4421 public static readonly PrimitiveType UInt16 = new PrimitiveType(0x07,"UInt16",6);
4422 public static readonly PrimitiveType Int32 = new PrimitiveType(0x08,"Int32",7);
4423 public static readonly PrimitiveType UInt32 = new PrimitiveType(0x09,"UInt32",8);
4424 public static readonly PrimitiveType Int64 = new PrimitiveType(0x0A,"Int64",9);
4425 public static readonly PrimitiveType UInt64 = new PrimitiveType(0x0B,"UInt64",10);
4426 public static readonly PrimitiveType Float32 = new PrimitiveType(0x0C,"Single",11);
4427 public static readonly PrimitiveType Float64 = new PrimitiveType(0x0D,"Double",12);
4428 public static readonly PrimitiveType String = new PrimitiveType(0x0E,"String",13);
4429 internal static readonly PrimitiveType Class = new PrimitiveType(0x12);
4430 internal static readonly PrimitiveType Var = new PrimitiveType(0x13);
4431 internal static readonly PrimitiveType GenericInst = new PrimitiveType(0x15);
4432 public static readonly PrimitiveType TypedRef = new PrimitiveType(0x16,"TypedReference",14);
4433 public static readonly PrimitiveType IntPtr = new PrimitiveType(0x18,"IntPtr",15);
4434 public static readonly PrimitiveType UIntPtr = new PrimitiveType(0x19,"UIntPtr",16);
4435 public static readonly PrimitiveType Object = new PrimitiveType(0x1C,"Object",17);
4436 internal static readonly PrimitiveType ClassType = new PrimitiveType(0x50);
4437 internal static readonly PrimitiveType SZArray = new PrimitiveType(0x1D);
4438 internal static readonly PrimitiveType MVar = new PrimitiveType(0x1E);
4439 internal static readonly PrimitiveType ValueType = new PrimitiveType(0x11, "ValueType", 18);
4440 public static readonly PrimitiveType NativeInt = IntPtr;
4441 public static readonly PrimitiveType NativeUInt = UIntPtr;
4443 internal PrimitiveType(byte typeIx) : base(typeIx) { }
4445 internal PrimitiveType(byte typeIx, string name, int STIx) : base(typeIx)
4448 this.systemTypeIndex = STIx;
4451 internal string GetName() { return name; }
4453 internal int GetSystemTypeIx() { return systemTypeIndex; }
4455 internal sealed override void TypeSig(MemoryStream str)
4457 str.WriteByte(typeIndex);
4460 internal override MetaDataElement GetTypeSpec(MetaData md)
4462 TypeSpec tS = md.GetPrimitiveTypeSpec(systemTypeIndex);
4464 tS = new TypeSpec(this,md);
4465 md.SetPrimitiveTypeSpec(systemTypeIndex,tS);
4466 md.AddToTable(MDTable.TypeSpec,tS);
4473 /**************************************************************************/
4475 /// Descriptor for an pointer (type * or type &)
4477 public abstract class PtrType : Type {
4481 internal PtrType(Type bType, byte typeIx) : base(typeIx)
4484 tabIx = MDTable.TypeSpec;
4487 internal sealed override void TypeSig(MemoryStream str)
4489 str.WriteByte(typeIndex);
4490 baseType.TypeSig(str);
4494 /**************************************************************************/
4496 /// Descriptor for a managed pointer (type & or byref)
4499 public class ManagedPointer : PtrType {
4502 /// Create new managed pointer to baseType
4504 /// <param name="bType">the base type of the pointer</param>
4505 public ManagedPointer(Type baseType) : base(baseType,0x10) { }
4508 /**************************************************************************/
4510 /// Descriptor for an unmanaged pointer (type *)
4512 public class UnmanagedPointer : PtrType {
4515 /// Create a new unmanaged pointer to baseType
4517 /// <param name="baseType">the base type of the pointer</param>
4518 public UnmanagedPointer(Type baseType) : base(baseType, 0x0F) { }
4522 /**************************************************************************/
4524 public interface IExternRef {
4525 ClassRef AddClass(string nsName, string name);
4526 ClassRef AddValueClass(string nsName, string name);
4530 /// A reference to an external assembly (.assembly extern)
4532 public class AssemblyRef : ResolutionScope, IExternRef {
4534 private ushort major, minor, build, revision;
4535 uint flags, keyIx, hashIx, cultIx;
4536 bool hasVersion = false, isKeyToken = false;
4540 internal AssemblyRef(MetaData md, string name) : base(name,md)
4542 tabIx = MDTable.AssemblyRef;
4545 public void AddAssemblyAttr (AssemAttr aa)
4551 /// Add version information about this external assembly
4553 /// <param name="majVer">Major Version</param>
4554 /// <param name="minVer">Minor Version</param>
4555 /// <param name="bldNo">Build Number</param>
4556 /// <param name="revNo">Revision Number</param>
4557 public void AddVersionInfo(int majVer, int minVer, int bldNo, int revNo)
4559 major = (ushort)majVer;
4560 minor = (ushort)minVer;
4561 build = (ushort)bldNo;
4562 revision = (ushort)revNo;
4567 /// Add the hash value for this external assembly
4569 /// <param name="hash">bytes of the hash value</param>
4570 public void AddHash(byte[] hash)
4572 hashIx = metaData.AddToBlobHeap(hash);
4576 /// Set the culture for this external assembly
4578 /// <param name="cult">the culture string</param>
4579 public void AddCulture(string cult)
4581 cultIx = metaData.AddToStringsHeap(cult);
4586 /// Add the full public key for this external assembly
4588 /// <param name="key">bytes of the public key</param>
4589 public void AddKey(byte[] key)
4591 flags |= 0x0001; // full public key
4593 keyIx = metaData.AddToBlobHeap(key);
4597 /// Add the public key token (low 8 bytes of the public key)
4599 /// <param name="key">low 8 bytes of public key</param>
4600 public void AddKeyToken(byte[] key)
4602 keyIx = metaData.AddToBlobHeap(key);
4608 /// Add a class to this external assembly
4610 /// <param name="nsName">name space name</param>
4611 /// <param name="name">class name</param>
4612 /// <returns></returns>
4613 public virtual ClassRef AddClass(string nsName, string name)
4615 ClassRef aClass = new ClassRef(nsName,name,metaData);
4616 metaData.AddToTable(MDTable.TypeRef,aClass);
4617 aClass.SetParent(this);
4622 /// Add a value class to this external assembly
4624 /// <param name="nsName">name space name</param>
4625 /// <param name="name">class name</param>
4626 /// <returns></returns>
4627 public virtual ClassRef AddValueClass(string nsName, string name)
4629 ClassRef aClass = new ClassRef(nsName,name,metaData);
4630 metaData.AddToTable(MDTable.TypeRef,aClass);
4631 aClass.SetParent(this);
4632 aClass.MakeValueClass(ValueClass.ValueType);
4636 internal string TypeName()
4638 string result = name;
4640 result = result + ", Version=" + major + "." + minor + "." +
4641 build + "." + revision;
4642 if (keyBytes != null) {
4643 string tokenStr = "=";
4644 if (isKeyToken) tokenStr = "Token=";
4645 result = result + ", PublicKey" + tokenStr;
4646 for (int i=0; i < keyBytes.Length; i++) {
4647 result = result + Hex.Byte(keyBytes[i]);
4650 if (culture != null)
4651 result = result + ", Culture=" + culture;
4655 internal sealed override uint Size(MetaData md)
4657 return 12 + 2 * md.StringsIndexSize() + 2 * md.BlobIndexSize();
4660 internal sealed override void Write(FileImage output)
4662 output.Write(major);
4663 output.Write(minor);
4664 output.Write(build);
4665 output.Write(revision);
4666 output.Write(flags);
4667 output.BlobIndex(keyIx);
4668 output.StringsIndex(nameIx);
4669 output.StringsIndex(cultIx);
4670 output.BlobIndex(hashIx);
4673 internal sealed override uint GetCodedIx(CIx code)
4676 case (CIx.ResolutionScope) : return 2;
4677 case (CIx.HasCustomAttr) : return 15;
4678 case (CIx.Implementation) : return 1;
4685 /**************************************************************************/
4687 /// Descriptor for a class defined in System (mscorlib)
4689 internal class SystemClass : ClassRef {
4691 PrimitiveType elemType;
4693 internal SystemClass(PrimitiveType eType, AssemblyRef paren, MetaData md)
4694 : base("System",eType.GetName(),md) {
4699 internal override sealed MetaDataElement GetTypeSpec(MetaData md)
4701 if (typeSpec == null) typeSpec = (TypeSpec)elemType.GetTypeSpec(md);
4706 internal sealed override void TypeSig(MemoryStream str)
4708 str.WriteByte(elemType.GetTypeIndex());
4713 /**************************************************************************/
4715 /// The assembly for mscorlib.
4717 public sealed class MSCorLib : AssemblyRef {
4719 private static readonly int valueTypeIx = 18;
4720 private readonly string systemName = "System";
4721 private Class[] systemClasses = new Class[valueTypeIx+2];
4722 private PrimitiveType[] systemTypes = new PrimitiveType[valueTypeIx];
4724 private static int[] specialNames = {
4725 PrimitiveType.Void.GetName().GetHashCode(),
4726 PrimitiveType.Boolean.GetName().GetHashCode(),
4727 PrimitiveType.Char.GetName().GetHashCode(),
4728 PrimitiveType.Int8.GetName().GetHashCode(),
4729 PrimitiveType.UInt8.GetName().GetHashCode(),
4730 PrimitiveType.Int16.GetName().GetHashCode(),
4731 PrimitiveType.UInt16.GetName().GetHashCode(),
4732 PrimitiveType.Int32.GetName().GetHashCode(),
4733 PrimitiveType.UInt32.GetName().GetHashCode(),
4734 PrimitiveType.Int64.GetName().GetHashCode(),
4735 PrimitiveType.UInt64.GetName().GetHashCode(),
4736 PrimitiveType.Float32.GetName().GetHashCode(),
4737 PrimitiveType.Float64.GetName().GetHashCode(),
4738 PrimitiveType.String.GetName().GetHashCode(),
4739 PrimitiveType.TypedRef.GetName().GetHashCode(),
4740 PrimitiveType.IntPtr.GetName().GetHashCode(),
4741 PrimitiveType.UIntPtr.GetName().GetHashCode(),
4742 PrimitiveType.Object.GetName().GetHashCode(),
4743 PrimitiveType.ValueType.GetName ().GetHashCode(),
4744 "Enum".GetHashCode()
4747 internal MSCorLib(MetaData md) : base(md,"mscorlib")
4749 if (!PEFile.IsMSCorlib)
4750 md.AddToTable(MDTable.AssemblyRef,this);
4751 systemTypes[PrimitiveType.Void.GetSystemTypeIx()] = PrimitiveType.Void;
4752 systemTypes[PrimitiveType.Boolean.GetSystemTypeIx()] = PrimitiveType.Boolean;
4753 systemTypes[PrimitiveType.Char.GetSystemTypeIx()] = PrimitiveType.Char;
4754 systemTypes[PrimitiveType.Int8.GetSystemTypeIx()] = PrimitiveType.Int8;
4755 systemTypes[PrimitiveType.UInt8.GetSystemTypeIx()] = PrimitiveType.UInt8;
4756 systemTypes[PrimitiveType.Int16.GetSystemTypeIx()] = PrimitiveType.Int16;
4757 systemTypes[PrimitiveType.UInt16.GetSystemTypeIx()] = PrimitiveType.UInt16;
4758 systemTypes[PrimitiveType.Int32.GetSystemTypeIx()] = PrimitiveType.Int32;
4759 systemTypes[PrimitiveType.UInt32.GetSystemTypeIx()] = PrimitiveType.UInt32;
4760 systemTypes[PrimitiveType.Int64.GetSystemTypeIx()] = PrimitiveType.Int64;
4761 systemTypes[PrimitiveType.UInt64.GetSystemTypeIx()] = PrimitiveType.UInt64;
4762 systemTypes[PrimitiveType.Float32.GetSystemTypeIx()] = PrimitiveType.Float32;
4763 systemTypes[PrimitiveType.Float64.GetSystemTypeIx()] = PrimitiveType.Float64;
4764 systemTypes[PrimitiveType.IntPtr.GetSystemTypeIx()] = PrimitiveType.IntPtr;
4765 systemTypes[PrimitiveType.UIntPtr.GetSystemTypeIx()] = PrimitiveType.UIntPtr;
4766 systemTypes[PrimitiveType.String.GetSystemTypeIx()] = PrimitiveType.String;
4767 systemTypes[PrimitiveType.Object.GetSystemTypeIx()] = PrimitiveType.Object;
4768 systemTypes[PrimitiveType.TypedRef.GetSystemTypeIx()] = PrimitiveType.TypedRef;
4772 /// Add a class to the mscorlib assembly
4774 /// <param name="nsName">name space name</param>
4775 /// <param name="name">class name</param>
4776 /// <returns></returns>
4777 public override ClassRef AddClass(string nsName, string name)
4779 /* This gets called by !mscorlib, for adding references INTO mscorlib, so
4780 it should be returning ClassRef ..*/
4781 Class aClass = GetSpecialClass(nsName,name);
4782 if (aClass == null) {
4783 aClass = new ClassRef(nsName,name,metaData);
4784 metaData.AddToTable(MDTable.TypeRef,aClass);
4785 if (aClass is ClassRef)
4786 ((ClassRef) aClass).SetParent(this);
4788 //FIXME: Check for !ClassRef here?
4789 return (ClassRef) aClass;
4792 private Class GetSpecialClass(string nsName,string name)
4794 if (nsName.CompareTo(systemName) != 0) return null;
4795 int hash = name.GetHashCode();
4796 for (int i=0; i < specialNames.Length; i++) {
4797 if (hash != specialNames[i])
4799 if (systemClasses[i] == null) {
4800 if (i < valueTypeIx) {
4801 systemClasses[i] = new SystemClass(systemTypes[i],this,metaData);
4802 if ((systemTypes[i] != PrimitiveType.Object) &&
4803 (systemTypes[i] != PrimitiveType.String)) {
4804 systemClasses[i].MakeValueClass(ValueClass.ValueType);
4807 systemClasses[i] = new ClassRef(nsName,name,metaData);
4808 ((ClassRef) systemClasses[i]).SetParent(this);
4809 if (!ClassDef.IsValueType (nsName, name) && !ClassDef.IsEnum (nsName, name))
4810 systemClasses[i].MakeValueClass(ValueClass.ValueType);
4812 metaData.AddToTable(MDTable.TypeRef,systemClasses[i]);
4814 return systemClasses[i];
4819 internal void SetSpecialSystemClass (string nsName, string name, Class aClass)
4821 if (nsName != systemName) return;
4822 int hash = name.GetHashCode ();
4823 for (int i = 0; i < specialNames.Length; i++) {
4824 if (hash != specialNames [i])
4826 if (systemClasses [i] == null) {
4827 systemClasses [i] = aClass;
4832 internal Class GetSpecialSystemClass(PrimitiveType pType)
4834 int ix = pType.GetSystemTypeIx();
4835 if (systemClasses[ix] == null && !PEFile.IsMSCorlib) {
4836 systemClasses[ix] = new SystemClass(pType,this,metaData);
4837 metaData.AddToTable(MDTable.TypeRef,systemClasses[ix]);
4839 return systemClasses[ix];
4842 private ClassRef GetValueClass(string name, int hash)
4844 /* Called by MSCorLib.AddValueClass, which is called by
4845 !mscorlib, for adding ref to value class INTO mscorlib,
4846 so this should be classref */
4847 int ix = valueTypeIx;
4848 if (hash != specialNames[valueTypeIx]) ix++;
4849 if (systemClasses[ix] == null) {
4850 systemClasses[ix] = new ClassRef(systemName,name,metaData);
4851 ((ClassRef) systemClasses[ix]).SetParent(this);
4852 ((ClassRef) systemClasses[ix]).MakeValueClass(ValueClass.ValueType);
4853 metaData.AddToTable(MDTable.TypeRef,systemClasses[ix]);
4855 return (ClassRef) systemClasses[ix];
4858 internal Class ValueType()
4860 if (systemClasses[valueTypeIx] == null && !PEFile.IsMSCorlib) {
4861 ClassRef valType = new ClassRef("System","ValueType",metaData);
4862 valType.SetParent(this);
4863 valType.MakeValueClass(ValueClass.ValueType);
4864 metaData.AddToTable(MDTable.TypeRef,valType);
4865 systemClasses[valueTypeIx] = valType;
4867 return systemClasses[valueTypeIx];
4870 internal Class EnumType()
4872 /* Called by both mscorlib & !mscorlib, so can be
4873 either ClassRef or ClassDef */
4874 //systemClasses [ valueTypeIx + 1] -> System.Enum
4875 if (systemClasses[valueTypeIx + 1] == null && !PEFile.IsMSCorlib) {
4876 ClassRef valType = new ClassRef("System","Enum",metaData);
4877 valType.SetParent(this);
4878 valType.MakeValueClass(ValueClass.Enum);
4879 metaData.AddToTable(MDTable.TypeRef,valType);
4880 systemClasses[valueTypeIx + 1] = valType;
4882 return systemClasses[valueTypeIx + 1];
4886 /// Add a value class to this external assembly
4888 /// <param name="nsName">name space name</param>
4889 /// <param name="name">class name</param>
4890 /// <returns></returns>
4891 public override ClassRef AddValueClass(string nsName, string name)
4893 if (nsName.CompareTo(systemName) == 0) {
4894 int hash = name.GetHashCode();
4895 if ((hash == specialNames[valueTypeIx]) ||
4896 (hash == specialNames[valueTypeIx+1])) {
4897 return GetValueClass(name,hash);
4900 ClassRef aClass = new ClassRef(nsName,name,metaData);
4901 metaData.AddToTable(MDTable.TypeRef,aClass);
4902 aClass.SetParent(this);
4903 aClass.MakeValueClass(ValueClass.ValueType);
4909 /**************************************************************************/
4912 /// Root (20 bytes + UTF-8 Version String + quad align padding)
4913 /// StreamHeaders (8 bytes + null terminated name string + quad align padding)
4915 /// #~ (always present - holds metadata tables)
4916 /// #Strings (always present - holds identifier strings)
4917 /// #US (Userstring heap)
4918 /// #Blob (signature blobs)
4919 /// #GUID (guids for assemblies or Modules)
4921 public class MetaData {
4923 internal static readonly int[] CIxShiftMap = {2,2,5,1,2,3,1,1,1,2,3,2,1};
4924 private static readonly byte StringsHeapMask = 0x1;
4925 private static readonly byte GUIDHeapMask = 0x2;
4926 private static readonly byte BlobHeapMask = 0x4;
4927 private static readonly uint MetaDataSignature = 0x424A5342;
4928 private static readonly uint maxSmlIxSize = 0xFFFF;
4929 private static readonly uint max1BitSmlIx = 0x7FFF;
4930 private static readonly uint max2BitSmlIx = 0x3FFF;
4931 private static readonly uint max3BitSmlIx = 0x1FFF;
4932 private static readonly uint max5BitSmlIx = 0x7FF;
4933 // NOTE: version and stream name strings MUST always be quad padded
4934 private static readonly string version = "v4.0.30319\0\0";
4935 private static readonly char[] tildeName = {'#','~','\0','\0'};
4936 private static readonly char[] stringsName = {'#','S','t','r','i','n','g','s','\0','\0','\0','\0'};
4937 private static readonly char[] usName = {'#','U','S','\0'};
4938 private static readonly char[] guidName = {'#','G','U','I','D','\0','\0','\0'};
4939 private static readonly char[] blobName = {'#','B','l','o','b','\0','\0','\0'};
4940 private static readonly uint MetaDataHeaderSize = 20 + (uint)version.Length;
4941 private static readonly uint TildeHeaderSize = 24;
4942 private static readonly uint StreamHeaderSize = 8;
4943 private static readonly uint numMetaDataTables = (int)MDTable.GenericParamConstraint + 1;
4945 MetaDataStream strings, us, guid, blob;
4947 MetaDataStream[] streams = new MetaDataStream[5];
4948 uint numStreams = 5;
4949 uint tildeTide = 0, tildePadding = 0, tildeStart = 0;
4950 uint numTables = 0, resourcesSize = 0;
4951 ArrayList[] metaDataTables = new ArrayList[numMetaDataTables];
4952 ArrayList byteCodes = new ArrayList();
4953 uint codeSize = 0, codeStart, byteCodePadding = 0, metaDataSize = 0;
4954 ulong valid = 0, /*sorted = 0x000002003301FA00;*/ sorted = 0;
4955 bool[] largeIx = new bool[numMetaDataTables];
4956 bool[] lgeCIx = new bool[(int)CIx.MaxCIx];
4957 bool largeStrings = false, largeUS = false, largeGUID = false, largeBlob = false;
4958 private FileImage file;
4959 private byte heapSizes = 0;
4960 MetaDataElement entryPoint;
4961 BinaryWriter output;
4962 public MSCorLib mscorlib;
4963 private TypeSpec[] systemTypeSpecs = new TypeSpec[PrimitiveType.NumSystemTypes];
4965 private ArrayList cattr_list;
4966 private ArrayList declsec_list;
4967 ArrayList resources;
4969 internal MetaData(FileImage file)
4971 // tilde = new MetaDataStream(tildeName,false,0);
4973 strings = new MetaDataStream(stringsName,new UTF8Encoding(),true);
4974 us = new MetaDataStream(usName,new UnicodeEncoding(),true);
4975 guid = new MetaDataStream(guidName,false);
4976 blob = new MetaDataStream(blobName,true);
4977 streams[1] = strings;
4981 for (int i=0; i < numMetaDataTables; i++) {
4984 for (int i=0; i < lgeCIx.Length; i++) {
4987 mscorlib = new MSCorLib(this);
4990 internal TypeSpec GetPrimitiveTypeSpec(int ix)
4992 return systemTypeSpecs[ix];
4995 internal void SetPrimitiveTypeSpec(int ix, TypeSpec typeSpec)
4997 systemTypeSpecs[ix] = typeSpec;
5000 internal uint Size()
5002 return metaDataSize;
5005 private void CalcHeapSizes ()
5007 if (strings.LargeIx()) {
5008 largeStrings = true;
5009 heapSizes |= StringsHeapMask;
5011 if (guid.LargeIx()) {
5013 heapSizes |= GUIDHeapMask;
5015 if (blob.LargeIx()) {
5017 heapSizes |= BlobHeapMask;
5020 largeUS = us.LargeIx();
5023 internal void StreamSize(byte mask)
5028 internal uint AddToUSHeap(string str)
5030 if (str == null) return 0;
5031 return us.Add(str,true);
5034 internal uint AddToUSHeap(byte[] str)
5036 if (str == null) return 0;
5037 return us.Add (str, true);
5040 internal uint AddToStringsHeap(string str)
5042 if ((str == null) || (str.CompareTo("") == 0)) return 0;
5043 return strings.Add(str,false);
5046 internal uint AddToGUIDHeap(Guid guidNum)
5048 return guid.Add(guidNum, false);
5051 internal uint AddToBlobHeap(byte[] blobBytes)
5053 if (blobBytes == null) return 0;
5054 return blob.Add(blobBytes, true);
5057 internal uint AddToBlobHeap(byte val)
5059 return blob.Add(val, true);
5062 internal uint AddToBlobHeap(sbyte val)
5064 return blob.Add(val, true);
5067 internal uint AddToBlobHeap(ushort val)
5069 return blob.Add(val, true);
5072 internal uint AddToBlobHeap(short val)
5074 return blob.Add(val, true);
5077 internal uint AddToBlobHeap(uint val)
5079 return blob.Add(val, true);
5082 internal uint AddToBlobHeap(int val)
5084 return blob.Add(val, true);
5087 internal uint AddToBlobHeap(ulong val)
5089 return blob.Add(val, true);
5092 internal uint AddToBlobHeap(long val)
5094 return blob.Add(val, true);
5097 internal uint AddToBlobHeap(float val)
5099 return blob.Add(val, true);
5102 internal uint AddToBlobHeap(double val)
5104 return blob.Add(val, true);
5107 internal uint AddToBlobHeap(string val)
5109 return blob.Add(val,true);
5112 internal void AddCustomAttribute (CustomAttribute cattr)
5114 if (cattr_list == null)
5115 cattr_list = new ArrayList ();
5116 cattr_list.Add (cattr);
5119 internal void AddDeclSecurity (BaseDeclSecurity decl_sec)
5121 if (declsec_list == null)
5122 declsec_list = new ArrayList ();
5123 declsec_list.Add (decl_sec);
5126 private ArrayList GetTable(MDTable tableIx)
5128 int tabIx = (int)tableIx;
5129 if (metaDataTables[tabIx] == null) {
5130 metaDataTables[tabIx] = new ArrayList();
5131 valid |= ((ulong)0x1 << tabIx);
5132 // Console.WriteLine("after creating table " + tableIx + "(" + tabIx + ") valid = " + valid);
5135 return metaDataTables[tabIx];
5138 internal void AddToTable(MDTable tableIx, MetaDataElement elem)
5141 // Console.Out.WriteLine("ERROR - element already in table " + tableIx);
5144 // updates Row field of the element
5145 // Console.WriteLine("Adding element to table " + (uint)tableIx);
5146 ArrayList table = GetTable(tableIx);
5147 elem.Row = (uint)table.Count + 1;
5151 internal uint TableIndex(MDTable tableIx)
5153 if (metaDataTables[(int)tableIx] == null) return 1;
5154 return (uint)metaDataTables[(int)tableIx].Count+1;
5157 internal uint AddCode(CILInstructions byteCode)
5159 byteCodes.Add(byteCode);
5160 uint offset = codeSize + codeStart;
5161 codeSize += byteCode.GetCodeSize();
5165 internal void SetEntryPoint(MetaDataElement ep)
5170 internal uint AddResource(byte[] resBytes)
5172 if (resources == null) resources = new ArrayList ();
5173 resources.Add (resBytes);
5174 uint offset = resourcesSize;
5175 resourcesSize += (uint)resBytes.Length + 4;
5179 internal void AddData(DataConstant cVal)
5181 file.AddInitData(cVal);
5184 internal static void CompressNum(uint val, MemoryStream sig)
5187 sig.WriteByte((byte)val);
5188 } else if (val <= 0x3FFF) {
5189 byte b1 = (byte)((val >> 8) | 0x80);
5190 byte b2 = (byte)(val & FileImage.iByteMask[0]);
5194 byte b1 = (byte)((val >> 24) | 0xC0);
5195 byte b2 = (byte)((val & FileImage.iByteMask[2]) >> 16);
5196 byte b3 = (byte)((val & FileImage.iByteMask[1]) >> 8);;
5197 byte b4 = (byte)(val & FileImage.iByteMask[0]);
5205 internal uint CodeSize()
5207 return codeSize + byteCodePadding;
5210 internal uint GetResourcesSize()
5212 return resourcesSize;
5215 internal uint StringsIndexSize()
5217 if (largeStrings) return 4;
5221 internal uint GUIDIndexSize()
5223 if (largeGUID) return 4;
5227 internal uint USIndexSize()
5229 if (largeUS) return 4;
5233 internal uint BlobIndexSize()
5235 if (largeBlob) return 4;
5239 internal uint CodedIndexSize(CIx code)
5241 if (lgeCIx[(uint)code]) return 4;
5245 internal uint TableIndexSize(MDTable tabIx)
5247 if (largeIx[(uint)tabIx]) return 4;
5251 private void SetIndexSizes()
5253 for (int i=0; i < numMetaDataTables; i++) {
5254 if (metaDataTables[i] == null)
5257 uint count = (uint)metaDataTables[i].Count;
5258 if (count > maxSmlIxSize)
5261 MDTable tabIx = (MDTable)i;
5262 if (count > max5BitSmlIx) {
5263 lgeCIx[(int)CIx.HasCustomAttr] = true;
5265 if (count > max3BitSmlIx) {
5266 if ((tabIx == MDTable.TypeRef) || (tabIx == MDTable.ModuleRef) || (tabIx == MDTable.Method) || (tabIx == MDTable.TypeSpec) || (tabIx == MDTable.Field))
5267 lgeCIx[(int)CIx.CustomAttributeType] = true;
5268 if ((tabIx == MDTable.Method) || (tabIx == MDTable.MemberRef))
5269 lgeCIx[(int)CIx.MemberRefParent] = true;
5271 if (count > max2BitSmlIx) {
5272 if ((tabIx == MDTable.Field) || (tabIx == MDTable.Param) || (tabIx == MDTable.Property))
5273 lgeCIx[(int)CIx.HasConst] = true;
5274 if ((tabIx == MDTable.TypeDef) || (tabIx == MDTable.TypeRef) || (tabIx == MDTable.TypeSpec))
5275 lgeCIx[(int)CIx.TypeDefOrRef] = true;
5276 if ((tabIx == MDTable.TypeDef) || (tabIx == MDTable.Method) || (tabIx == MDTable.Assembly))
5277 lgeCIx[(int)CIx.HasDeclSecurity] = true;
5278 if ((tabIx == MDTable.File) || (tabIx == MDTable.AssemblyRef) || (tabIx == MDTable.ExportedType))
5279 lgeCIx[(int)CIx.Implementation] = true;
5280 if ((tabIx == MDTable.Module) || (tabIx == MDTable.ModuleRef) || (tabIx == MDTable.AssemblyRef) || (tabIx == MDTable.TypeRef))
5281 lgeCIx[(int)CIx.ResolutionScope] = true;
5283 if (count > max1BitSmlIx) {
5284 if ((tabIx == MDTable.Field) || (tabIx == MDTable.Param))
5285 lgeCIx[(int)CIx.HasFieldMarshal] = true;
5286 if ((tabIx == MDTable.Event) || (tabIx == MDTable.Property))
5287 lgeCIx[(int)CIx.HasSemantics] = true;
5288 if ((tabIx == MDTable.Method) || (tabIx == MDTable.MemberRef))
5289 lgeCIx[(int)CIx.MethodDefOrRef] = true;
5290 if ((tabIx == MDTable.Field) || (tabIx == MDTable.Method))
5291 lgeCIx[(int)CIx.MemberForwarded] = true;
5292 if ((tabIx == MDTable.TypeDef) || (tabIx == MDTable.Method))
5293 lgeCIx[(int)CIx.TypeOrMethodDef] = true;
5298 private void SetStreamOffsets()
5300 uint sizeOfHeaders = StreamHeaderSize + (uint)tildeName.Length;
5301 for (int i=1; i < numStreams; i++) {
5302 sizeOfHeaders += streams[i].headerSize();
5304 metaDataSize = MetaDataHeaderSize + sizeOfHeaders;
5305 tildeStart = metaDataSize;
5306 metaDataSize += tildeTide + tildePadding;
5307 for (int i=1; i < numStreams; i++) {
5308 streams[i].Start = metaDataSize;
5309 metaDataSize += streams[i].Size();
5310 streams[i].WriteDetails();
5314 internal void CalcTildeStreamSize()
5317 //tilde.SetIndexSizes(strings.LargeIx(),us.LargeIx(),guid.LargeIx(),blob.LargeIx());
5318 tildeTide = TildeHeaderSize;
5319 tildeTide += 4 * numTables;
5320 //Console.WriteLine("Tilde header + sizes = " + tildeTide);
5321 for (int i=0; i < numMetaDataTables; i++) {
5322 if (metaDataTables[i] != null) {
5323 ArrayList table = metaDataTables[i];
5324 // Console.WriteLine("Meta data table " + i + " at offset " + tildeTide);
5325 tildeTide += (uint)table.Count * ((MetaDataElement)table[0]).Size(this);
5326 // Console.WriteLine("Metadata table " + i + " has size " + table.Count);
5327 // Console.WriteLine("tildeTide = " + tildeTide);
5330 if ((tildeTide % 4) != 0) tildePadding = 4 - (tildeTide % 4);
5331 //Console.WriteLine("tildePadding = " + tildePadding);
5334 internal void WriteTildeStream(FileImage output)
5336 output.Seek(0,SeekOrigin.Current);
5337 output.Write((uint)0); // Reserved
5338 output.Write((byte)2); // MajorVersion
5339 output.Write((byte)0); // MinorVersion
5340 output.Write(heapSizes);
5341 output.Write((byte)1); // Reserved
5342 output.Write(valid);
5343 output.Write(sorted);
5345 for (int i=0; i < numMetaDataTables; i++) {
5346 if (metaDataTables[i] != null) {
5347 uint count = (uint)metaDataTables[i].Count;
5348 output.Write(count);
5352 output.Seek(0,SeekOrigin.Current);
5353 // Console.WriteLine("Starting metaData tables at " + tabStart);
5354 for (int i=0; i < numMetaDataTables; i++) {
5355 if (metaDataTables[i] != null) {
5356 // Console.WriteLine("Starting metaData table " + i + " at " + (output.Seek(0,SeekOrigin.Current) - startTilde));
5357 ArrayList table = metaDataTables[i];
5358 for (int j=0; j < table.Count; j++) {
5359 ((MetaDataElement)table[j]).Write(output);
5363 // Console.WriteLine("Writing padding at " + output.Seek(0,SeekOrigin.Current));
5364 for (int i=0; i < tildePadding; i++) output.Write((byte)0);
5367 private void BuildTable(ArrayList table)
5369 if (table == null) return;
5370 for (int j=0; j < table.Count; j++) {
5371 ((MetaDataElement)table[j]).BuildTables(this);
5375 private void SortTable (ArrayList mTable)
5377 if (mTable == null) return;
5379 for (int i=0; i < mTable.Count; i++) {
5380 ((MetaDataElement)mTable[i]).Row = (uint)i+1;
5384 internal void BuildMetaData(uint codeStartOffset)
5386 codeStart = codeStartOffset;
5387 BuildTable(metaDataTables[(int)MDTable.TypeDef]);
5388 BuildTable(metaDataTables[(int)MDTable.TypeSpec]);
5389 BuildTable(metaDataTables[(int)MDTable.MemberRef]);
5390 BuildTable(metaDataTables[(int)MDTable.GenericParam]);
5391 BuildTable(metaDataTables[(int)MDTable.MethodSpec]);
5392 BuildTable(metaDataTables[(int)MDTable.GenericParamConstraint]);
5393 BuildTable(metaDataTables[(int)MDTable.ManifestResource]);
5395 if (cattr_list != null) {
5396 foreach (CustomAttribute cattr in cattr_list)
5397 cattr.BuildTables (this);
5400 if (declsec_list != null) {
5401 foreach (BaseDeclSecurity decl_sec in declsec_list)
5402 decl_sec.BuildTables (this);
5405 /* for (int i=0; i < metaDataTables.Length; i++) {
5406 ArrayList table = metaDataTables[i];
5407 if (table != null) {
5408 for (int j=0; j < table.Count; j++) {
5409 ((MetaDataElement)table[j]).BuildTables(this);
5416 for (int i=1; i < numStreams; i++) {
5417 streams[i].EndStream();
5419 CalcTildeStreamSize();
5421 byteCodePadding = NumToAlign(codeSize,4);
5422 if (entryPoint != null) file.SetEntryPoint(entryPoint.Token());
5424 // Check ordering of specific tables
5425 // Constant, CustomAttribute, FieldMarshal, DeclSecurity, MethodSemantics
5426 // ImplMap, GenericParam
5427 // Need to load GenericParamConstraint AFTER GenericParam table in correct order
5429 // InterfaceImpl, ClassLayout, FieldLayout, MethodImpl, FieldRVA, NestedClass
5430 // will _ALWAYS_ be in the correct order as embedded in BuildMDTables
5432 SortTable(metaDataTables[(int)MDTable.Constant]);
5433 SortTable(metaDataTables[(int)MDTable.FieldMarshal]);
5434 SortTable(metaDataTables[(int)MDTable.DeclSecurity]);
5435 SortTable(metaDataTables[(int)MDTable.MethodSemantics]);
5436 SortTable(metaDataTables[(int)MDTable.ImplMap]);
5437 if (metaDataTables[(int)MDTable.GenericParam] != null) {
5438 SortTable(metaDataTables[(int)MDTable.GenericParam]);
5439 // Now add GenericParamConstraints
5440 /*for (int i=0; i < metaDataTables[(int)MDTable.GenericParam].Count; i++) {
5441 ((GenericParameter)metaDataTables[(int)MDTable.GenericParam][i]).AddConstraints(this);
5444 SortTable(metaDataTables[(int)MDTable.GenericParamConstraint]);
5445 SortTable(metaDataTables[(int)MDTable.InterfaceImpl]);
5446 SortTable(metaDataTables[(int)MDTable.CustomAttribute]);
5450 internal void WriteByteCodes(FileImage output)
5452 for (int i=0; i < byteCodes.Count; i++) {
5453 ((CILInstructions)byteCodes[i]).Write(output);
5455 for (int i=0; i < byteCodePadding; i++) {
5456 output.Write((byte)0);
5460 internal void WriteResources (FileImage output)
5462 if (resources == null) return;
5463 for (int i = 0; i < resources.Count; i ++) {
5464 byte [] resBytes = (byte []) resources [i];
5465 output.Write ((uint) resBytes.Length);
5466 output.Write (resBytes);
5470 internal void WriteMetaData(FileImage output)
5472 this.output = output;
5473 mdStart = output.Seek(0,SeekOrigin.Current);
5474 // Console.WriteLine("Writing metaData at " + Hex.Long(mdStart));
5475 output.Write(MetaDataSignature);
5476 output.Write((short)1); // Major Version
5477 output.Write((short)1); // Minor Version ECMA = 0, PEFiles = 1
5478 output.Write(0); // Reserved
5479 output.Write(version.Length);
5480 output.Write(version.ToCharArray()); // version string is already zero padded
5481 output.Write((short)0);
5482 output.Write((ushort)numStreams);
5483 // write tilde header
5484 output.Write(tildeStart);
5485 output.Write(tildeTide + tildePadding);
5486 output.Write(tildeName);
5487 for (int i=1; i < numStreams; i++) streams[i].WriteHeader(output);
5488 // Console.WriteLine("Writing tilde stream at " + output.Seek(0,SeekOrigin.Current) + " = " + tildeStart);
5489 WriteTildeStream(output);
5490 for (int i=1; i < numStreams; i++) streams[i].Write(output);
5491 // Console.WriteLine("Finished Writing metaData at " + output.Seek(0,SeekOrigin.Current));
5494 internal bool LargeStringsIndex() { return strings.LargeIx(); }
5495 internal bool LargeGUIDIndex() { return guid.LargeIx(); }
5496 internal bool LargeUSIndex() { return us.LargeIx(); }
5497 internal bool LargeBlobIndex() { return blob.LargeIx(); }
5499 internal bool LargeIx(MDTable tabIx) { return largeIx[(uint)tabIx]; }
5502 private uint NumToAlign(uint val, uint alignVal)
5504 if ((val % alignVal) == 0) return 0;
5505 return alignVal - (val % alignVal);
5508 internal void WriteCodedIndex(CIx code, MetaDataElement elem, FileImage output)
5512 ix = (elem.Row << CIxShiftMap[(uint)code]) | elem.GetCodedIx(code);
5513 // Console.WriteLine("coded index = " + ix + " row = " + elem.Row);
5515 // Console.WriteLine("elem for coded index is null");
5517 if (lgeCIx[(uint)code])
5520 output.Write((ushort)ix);
5525 /**************************************************************************/
5527 /// Stream in the Meta Data (#Strings, #US, #Blob and #GUID)
5530 internal class MetaDataStream : BinaryWriter {
5532 private static readonly uint StreamHeaderSize = 8;
5533 private static uint maxSmlIxSize = 0xFFFF;
5535 private uint start = 0;
5536 uint size = 0, tide = 1;
5537 bool largeIx = false;
5540 Hashtable htable = new Hashtable();
5541 Hashtable btable = new Hashtable (new ByteArrayHashCodeProvider (), new ByteArrayComparer ());
5543 internal MetaDataStream(char[] name, bool addInitByte) : base(new MemoryStream())
5545 if (addInitByte) { Write((byte)0); size = 1; }
5547 sizeOfHeader = StreamHeaderSize + (uint)name.Length;
5550 internal MetaDataStream(char[] name, System.Text.Encoding enc, bool addInitByte) : base(new MemoryStream(),enc)
5552 if (addInitByte) { Write((byte)0); size = 1; }
5554 sizeOfHeader = StreamHeaderSize + (uint)name.Length;
5558 get { return start; }
5559 set { start = value; }
5562 internal uint headerSize()
5564 // Console.WriteLine(name + " stream has headersize of " + sizeOfHeader);
5565 return sizeOfHeader;
5568 internal void SetSize(uint siz)
5573 internal uint Size()
5578 internal bool LargeIx()
5583 internal void WriteDetails()
5585 // Console.WriteLine(name + " - size = " + size);
5588 internal uint Add(string str, bool prependSize)
5590 Object val = htable[str];
5594 htable[str] = index;
5595 char[] arr = str.ToCharArray();
5596 if (prependSize) CompressNum((uint)arr.Length*2+1);
5599 size = (uint)Seek(0,SeekOrigin.Current);
5605 internal uint Add (byte[] str, bool prependSize)
5607 Object val = btable [str];
5611 btable [str] = index;
5612 if (prependSize) CompressNum ((uint) str.Length);
5614 size = (uint) Seek (0, SeekOrigin.Current);
5622 internal uint Add(Guid guid, bool prependSize)
5624 byte [] b = guid.ToByteArray ();
5625 if (prependSize) CompressNum ((uint) b.Length);
5626 Write(guid.ToByteArray());
5627 size =(uint)Seek(0,SeekOrigin.Current);
5631 internal uint Add(byte[] blob)
5634 CompressNum((uint)blob.Length);
5636 size = (uint)Seek(0,SeekOrigin.Current);
5640 internal uint Add(byte val, bool prependSize)
5643 if (prependSize) CompressNum (1);
5645 size = (uint)Seek(0,SeekOrigin.Current);
5649 internal uint Add(sbyte val, bool prependSize)
5652 if (prependSize) CompressNum (1);
5654 size = (uint)Seek(0,SeekOrigin.Current);
5658 internal uint Add(ushort val, bool prependSize)
5661 if (prependSize) CompressNum (2);
5663 size = (uint)Seek(0,SeekOrigin.Current);
5667 internal uint Add(short val, bool prependSize)
5670 if (prependSize) CompressNum (2);
5672 size = (uint)Seek(0,SeekOrigin.Current);
5676 internal uint Add(uint val, bool prependSize)
5679 if (prependSize) CompressNum (4);
5681 size = (uint)Seek(0,SeekOrigin.Current);
5685 internal uint Add(int val, bool prependSize)
5688 if (prependSize) CompressNum (4);
5690 size = (uint)Seek(0,SeekOrigin.Current);
5694 internal uint Add(ulong val, bool prependSize)
5697 if (prependSize) CompressNum (8);
5699 size = (uint)Seek(0,SeekOrigin.Current);
5703 internal uint Add(long val, bool prependSize)
5706 if (prependSize) CompressNum (8);
5708 size = (uint)Seek(0,SeekOrigin.Current);
5712 internal uint Add(float val, bool prependSize)
5715 if (prependSize) CompressNum (4);
5717 size = (uint)Seek(0,SeekOrigin.Current);
5721 internal uint Add(double val, bool prependSize)
5724 if (prependSize) CompressNum (8);
5726 size = (uint)Seek(0,SeekOrigin.Current);
5730 private void CompressNum(uint val)
5734 } else if (val < 0x3FFF) {
5735 byte b1 = (byte)((val >> 8) | 0x80);
5736 byte b2 = (byte)(val & FileImage.iByteMask[0]);
5740 byte b1 = (byte)((val >> 24) | 0xC0);
5741 byte b2 = (byte)((val & FileImage.iByteMask[2]) >> 16);
5742 byte b3 = (byte)((val & FileImage.iByteMask[1]) >> 8);;
5743 byte b4 = (byte)(val & FileImage.iByteMask[0]);
5751 private void QuadAlign()
5753 if ((size % 4) != 0) {
5754 uint pad = 4 - (size % 4);
5756 for (int i=0; i < pad; i++) {
5762 internal void EndStream()
5765 if (size > maxSmlIxSize) {
5770 internal void WriteHeader(BinaryWriter output)
5772 output.Write(start);
5777 internal virtual void Write(BinaryWriter output)
5779 // Console.WriteLine("Writing " + name + " stream at " + output.Seek(0,SeekOrigin.Current) + " = " + start);
5780 MemoryStream str = (MemoryStream)BaseStream;
5781 output.Write(str.ToArray());
5786 /**************************************************************************/
5787 class ByteArrayComparer : IComparer {
5789 public int Compare (object x, object y)
5791 byte [] a = (byte []) x;
5792 byte [] b = (byte []) y;
5795 if (b.Length != len)
5798 for (int i = 0; i < len; ++i)
5805 class ByteArrayHashCodeProvider : IHashCodeProvider {
5807 public int GetHashCode (Object key)
5809 byte [] arr = (byte []) key;
5810 int len = arr.Length;
5813 for (int i = 0; i < len; ++i)
5814 h = (h << 5) - h + arr [i];