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 { 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,
58 VisibilityMask = 0x07 }
61 /// Attributes for a field
63 public enum FieldAttr {Default, Private, FamAndAssem, Assembly,
64 Family, FamOrAssem, Public, Static = 0x10, PublicStatic = 0x16,
65 Initonly = 0x20, Literal = 0x40, Notserialized = 0x80,
66 SpecialName = 0x200, RTSpecialName = 0x400, HasFieldMarshal = 0x1000 }
69 /// Attributes for a method
71 public enum MethAttr { Default, Private, FamAndAssem, Assembly,
72 Family, FamOrAssem, Public, Static = 0x0010, PublicStatic = 0x16,
73 Final = 0x0020, PublicStaticFinal = 0x36, Virtual = 0x0040,
74 PrivateVirtual, PublicVirtual = 0x0046, HideBySig = 0x0080,
75 NewSlot = 0x0100, Abstract = 0x0400, SpecialName = 0x0800,
76 RTSpecialName = 0x1000, SpecialRTSpecialName = 0x1800,
77 HasSecurity = 0x4000, RequireSecObject = 0x8000}
80 /// Attributes for .pinvokeimpl method declarations
82 public enum PInvokeAttr { nomangle = 1, ansi = 2, unicode = 4, autochar = 6,
83 bestfit_on = 0x0010, bestfit_off = 0x0020, bestfit_mask = 0x0030,
84 lasterr = 0x0040, winapi = 0x0100, cdecl = 0x0200,
85 stdcall = 0x0300, thiscall = 0x0400, fastcall = 0x0500,
86 charmaperror_on = 0x1000, charmaperror_off = 0x2000
90 /// Implementation attributes for a method
92 public enum ImplAttr { IL, Native, Runtime = 0x03, Unmanaged = 0x04,
93 ForwardRef = 0x10, PreserveSig = 0x0080, InternalCall = 0x1000,
94 Synchronised = 0x0020, Synchronized = 0x0020, NoInLining = 0x0008, Optil = 0x0002}
97 /// Modes for a parameter
99 public enum ParamAttr { Default, In, Out, Opt = 16, HasDefault = 0x1000, HasFieldMarshal = 0x2000 }
104 public enum Op { nop, breakOp, ldarg_0, ldarg_1, ldarg_2, ldarg_3,
105 ldloc_0, ldloc_1, ldloc_2, ldloc_3, stloc_0, stloc_1, stloc_2, stloc_3,
106 ldnull = 0x14, ldc_i4_m1, ldc_i4_0, ldc_i4_1, ldc_i4_2, ldc_i4_3,
107 ldc_i4_4, ldc_i4_5, ldc_i4_6, ldc_i4_7, ldc_i4_8, dup = 0x25, pop,
108 ret = 0x2A, ldind_i1 = 0x46, ldind_u1, ldind_i2, ldind_u2, ldind_i4,
109 ldind_u4, ldind_i8, ldind_i, ldind_r4, ldind_r8, ldind_ref, stind_ref,
110 stind_i1, stind_i2, stind_i4, stind_i8, stind_r4, stind_r8, add, sub, mul,
111 div, div_un, rem, rem_un, and, or, xor, shl, shr, shr_un, neg, not,
112 conv_i1, conv_i2, conv_i4, conv_i8, conv_r4, conv_r8, conv_u4, conv_u8,
113 conv_r_un = 0x76, throwOp = 0x7A, conv_ovf_i1_un = 0x82, conv_ovf_i2_un,
114 conv_ovf_i4_un, conv_ovf_i8_un, conf_ovf_u1_un, conv_ovf_u2_un,
115 conv_ovf_u4_un, conv_ovf_u8_un, conv_ovf_i_un, conv_ovf_u_un,
116 ldlen = 0x8E, ldelem_i1 = 0x90, ldelem_u1, ldelem_i2, ldelem_u2,
117 ldelem_i4, ldelem_u4, ldelem_i8, ldelem_i, ldelem_r4, ldelem_r8,
118 ldelem_ref, stelem_i, stelem_i1, stelem_i2, stelem_i4, stelem_i8, stelem_r4 = 0xA0, stelem_r8,
119 stelem_ref, conv_ovf_i1 = 0xb3, conv_ovf_u1, conv_ovf_i2, conv_ovf_u2,
120 conv_ovf_i4, conv_ovf_u4, conv_ovf_i8, conv_ovf_u8, ckfinite = 0xC3,
121 conv_u2 = 0xD1, conv_u1, conv_i, conv_ovf_i, conv_ovf_u, add_ovf,
122 add_ovf_un, mul_ovf, mul_ovf_un, sub_ovf, sub_ovf_un, endfinally,
123 stind_i = 0xDF, conv_u, arglist = 0xFE00, ceq, cgt, cgt_un, clt, clt_un,
124 localloc = 0xFE0F, endfilter = 0xFE11, volatile_ = 0xFE13, tail_,
125 cpblk = 0xFE17, initblk, rethrow = 0xFE1A, refanytype = 0xFE1D, readonly_ = 0xFE1E }
128 /// CIL instructions requiring an integer parameter
130 public enum IntOp {ldarg_s = 0x0E, ldarga_s, starg_s, ldloc_s, ldloca_s,
131 stloc_s, ldc_i4_s = 0x1F, ldc_i4, ldarg = 0xFE09,
132 ldarga, starg, ldloc, ldloca, stloc, unaligned = 0xFE12 }
135 /// CIL instructions requiring a field parameter
137 public enum FieldOp {ldfld = 0x7B, ldflda, stfld, ldsfld, ldsflda,
138 stsfld, ldtoken = 0xD0 }
141 /// CIL instructions requiring a method parameter
143 public enum MethodOp {jmp = 0x27, call, callvirt = 0x6F, newobj = 0x73,
144 ldtoken = 0xD0, ldftn = 0xFE06, ldvirtfn }
147 /// CIL instructions requiring a type parameter
149 public enum TypeOp {cpobj = 0x70, ldobj, castclass = 0x74, isinst,
150 unbox = 0x79, stobj = 0x81, box = 0x8C, newarr,
151 ldelema = 0x8F, refanyval = 0xC2, mkrefany = 0xC6,
152 ldtoken = 0xD0, initobj = 0xFE15, constrained = 0xFE16,
153 sizeOf = 0xFE1C, ldelem = 0xA3, stelem = 0xA4, unbox_any }
156 /// CIL branch instructions
158 public enum BranchOp {
160 br_s = 0x2B, brfalse_s, brtrue_s, beq_s, bge_s, bgt_s,
161 ble_s, blt_s, bne_un_s, bge_un_s, bgt_un_s, ble_un_s, blt_un_s,
163 br = 0x38, brfalse, brtrue, beq, bge, bgt, ble, blt,
164 bne_un, bge_un, bgt_un, ble_un, blt_un,
166 leave = 0xDD, leave_s }
169 /// Index for all the tables in the meta data
171 public enum MDTable { Module, TypeRef, TypeDef, Field = 0x04, Method = 0x06,
172 Param = 0x08, InterfaceImpl, MemberRef, Constant, CustomAttribute,
173 FieldMarshal, DeclSecurity, ClassLayout, FieldLayout, StandAloneSig,
174 EventMap, Event = 0x14, PropertyMap, Property = 0x17, MethodSemantics,
175 MethodImpl, ModuleRef, TypeSpec, ImplMap, FieldRVA, Assembly = 0x20,
176 AssemblyProcessor, AssemblyOS, AssemblyRef, AssemblyRefProcessor,
177 AssemblyRefOS, File, ExportedType, ManifestResource, NestedClass,
178 GenericParam, MethodSpec, GenericParamConstraint }
180 public enum SafeArrayType { int16 = 2, int32, float32, float64,
181 currency, date, bstr, dispatch, error, boolean, variant, unknown,
182 Decimal, int8 = 16, uint8, uint16, uint32, Int = 22, UInt }
184 internal enum CIx { TypeDefOrRef, HasConst, HasCustomAttr, HasFieldMarshal,
185 HasDeclSecurity, MemberRefParent, HasSemantics, MethodDefOrRef,
186 MemberForwarded, Implementation, CustomAttributeType, ResolutionScope,
187 TypeOrMethodDef, MaxCIx }
189 internal enum MapType { eventMap, propertyMap, nestedClass }
191 public enum ValueClass { ValueType, Enum }
193 public enum GenParamType : byte {
194 Var = 0x13, MVar = 0x1E
198 public enum GenericParamAttributes : ushort {
199 VarianceMask = 0x0003,
202 Contravariant = 0x0002,
204 SpecialConstraintMask = 0x001c,
205 ReferenceTypeConstraint = 0x0004,
206 NotNullableValueTypeConstraint = 0x0008,
207 DefaultConstructorConstrait = 0x0010
210 /* Taken from Mono.Cecil */
211 public enum SecurityAction : short {
225 NonCasLinkDemand = 14,
226 NonCasInheritance = 15,
227 LinkDemandChoice = 16,
228 InheritDemandChoice = 17,
234 /**************************************************************************/
236 /// Base class for all Meta Data table elements
239 public abstract class MetaDataElement: IComparable {
240 protected ArrayList customAttributes;
241 private uint row = 0;
242 protected bool done = false;
243 protected MDTable tabIx;
244 protected bool sortTable = false;
246 private bool has_custom_attrs = false;
248 internal MetaDataElement() { }
259 public bool HasCustomAttr {
260 get { return has_custom_attrs; }
261 set { has_custom_attrs = value; }
264 internal virtual uint GetCodedIx(CIx code) { return 0; }
267 /// Add a custom attribute to this item
269 /// <param name="ctorMeth">the constructor method for this attribute</param>
270 /// <param name="val">the byte value of the parameters</param>
271 public void AddCustomAttribute(Method ctorMeth, byte[] val)
273 if (customAttributes == null) {
274 customAttributes = new ArrayList();
276 customAttributes.Add(new CustomAttribute(this,ctorMeth,val));
280 /// Add a custom attribute to this item
282 /// <param name="ctorMeth">the constructor method for this attribute</param>
283 /// <param name="val">the constant values of the parameters</param>
284 public void AddCustomAttribute(Method ctorMeth, Constant[] cVals)
286 if (customAttributes == null) {
287 customAttributes = new ArrayList();
289 // customAttributes.Add(new CustomAttribute(this,ctorMeth,cVals));
292 internal uint Token()
294 return (((uint)tabIx << 24) | row);
297 internal virtual void BuildTables(MetaData md)
302 internal virtual uint Size(MetaData md)
307 internal virtual void Write(FileImage output) { }
309 internal virtual uint SortKey()
311 throw new PEFileException("Trying to sort table of " + this);
315 internal virtual uint SortKey2()
320 public int CompareTo(object obj)
322 uint otherKey = ((MetaDataElement)obj).SortKey();
323 uint thisKey = SortKey();
325 if (thisKey == otherKey) {
327 otherKey = ((MetaDataElement)obj).SortKey2();
328 thisKey = SortKey2();
329 if (thisKey == otherKey)
331 if (thisKey < otherKey)
335 if (thisKey < otherKey) return -1;
342 /**************************************************************************/
344 /// Layout information for a class (.class [sequential | explicit])
346 internal class ClassLayout : MetaDataElement {
352 internal ClassLayout(int pack, int cSize, ClassDef par)
354 packSize = (ushort)pack;
355 classSize = (uint)cSize;
357 tabIx = MDTable.ClassLayout;
360 internal sealed override uint Size(MetaData md)
362 return 6 + md.TableIndexSize(MDTable.TypeDef);
365 internal sealed override void Write(FileImage output)
367 output.Write(packSize);
368 output.Write(classSize);
369 output.WriteIndex(MDTable.TypeDef,parent.Row);
374 /**************************************************************************/
376 /// Summary description for ConstantElem.
378 internal class ConstantElem : MetaDataElement {
380 MetaDataElement parent;
384 internal ConstantElem(MetaDataElement parent, Constant val)
386 this.parent = parent;
388 tabIx = MDTable.Constant;
392 internal override uint SortKey()
394 return (parent.Row << MetaData.CIxShiftMap[(uint)CIx.HasConst])
395 | parent.GetCodedIx(CIx.HasConst);
398 internal sealed override void BuildTables(MetaData md)
401 valIx = cValue.GetBlobIndex(md);
405 internal void AddToBlob(BinaryWriter bw)
410 internal sealed override uint Size(MetaData md)
412 return 2 + md.CodedIndexSize(CIx.HasConst) + md.BlobIndexSize();
415 internal sealed override void Write(FileImage output)
417 output.Write(cValue.GetTypeIndex());
418 output.Write((byte)0);
419 output.WriteCodedIndex(CIx.HasConst,parent);
420 output.BlobIndex(valIx);
424 /**************************************************************************/
426 /// Descriptor for a Custom Attribute (.custom)
429 public class CustomAttribute : MetaDataElement {
431 private static readonly ushort prolog = 0x0001;
432 MetaDataElement parent;
438 ArrayList names, vals;
440 internal CustomAttribute(MetaDataElement paren, Method constrType,
445 tabIx = MDTable.CustomAttribute;
448 internal CustomAttribute(MetaDataElement paren, Method constrType,
452 tabIx = MDTable.CustomAttribute;
456 internal override uint SortKey()
458 return (parent.Row << MetaData.CIxShiftMap[(uint)CIx.HasCustomAttr])
459 | parent.GetCodedIx(CIx.HasCustomAttr);
462 public void AddFieldOrProp(string name, Constant val)
465 names = new ArrayList();
466 vals = new ArrayList();
472 internal sealed override void BuildTables(MetaData md)
474 md.AddToTable(MDTable.CustomAttribute, this);
475 if (byteVal == null) {
480 BinaryWriter bw = new BinaryWriter(new MemoryStream());
482 MemoryStream str = (MemoryStream)bw.BaseStream;
483 valIx = md.AddToBlobHeap(str.ToArray());
486 internal sealed override uint Size(MetaData md)
488 return md.CodedIndexSize(CIx.HasCustomAttr) + md.CodedIndexSize(CIx.CustomAttributeType) + md.BlobIndexSize();
491 internal sealed override void Write(FileImage output)
493 output.WriteCodedIndex(CIx.HasCustomAttr,parent);
494 output.WriteCodedIndex(CIx.CustomAttributeType,type);
495 output.BlobIndex(valIx);
500 /**************************************************************************/
502 /// Descriptor for security permissions for a class or a method
505 public abstract class BaseDeclSecurity : MetaDataElement {
508 MetaDataElement parent;
511 internal BaseDeclSecurity(MetaDataElement paren, ushort act)
515 tabIx = MDTable.DeclSecurity;
518 internal override uint SortKey()
520 return (parent.Row << MetaData.CIxShiftMap[(uint)CIx.HasDeclSecurity])
521 | parent.GetCodedIx(CIx.HasDeclSecurity);
524 internal sealed override uint Size(MetaData md)
526 return 2 + md.CodedIndexSize(CIx.HasDeclSecurity) + md.BlobIndexSize();
529 internal sealed override void BuildTables(MetaData md)
533 BinaryWriter bw = new BinaryWriter (new MemoryStream ());
534 md.AddToTable (MDTable.DeclSecurity, this);
535 MemoryStream str = (MemoryStream)bw.BaseStream;
537 permissionIx = md.AddToBlobHeap(str.ToArray());
542 internal abstract void WriteSig (BinaryWriter bw);
544 internal sealed override void Write(FileImage output)
546 output.Write(action);
547 output.WriteCodedIndex(CIx.HasDeclSecurity,parent);
548 output.BlobIndex(permissionIx);
553 public class DeclSecurity : BaseDeclSecurity {
557 internal DeclSecurity(MetaDataElement paren, ushort act, byte [] val)
563 internal override void WriteSig (BinaryWriter bw)
570 public class DeclSecurity_20 : BaseDeclSecurity {
574 internal DeclSecurity_20 (MetaDataElement paren, ushort act, PermissionSet ps)
580 internal override void WriteSig (BinaryWriter bw)
586 public class PermissionMember {
588 MemberTypes member_type;
593 public PermissionMember (MemberTypes member_type, PEAPI.Type type, string name, object value)
595 this.member_type = member_type;
601 public void Write (BinaryWriter bw)
605 if (member_type == MemberTypes.Field)
606 bw.Write ((byte) 0x53);
609 bw.Write ((byte) 0x54);
611 if (type is PrimitiveType) {
612 bw.Write (type.GetTypeIndex ());
615 bw.Write ((byte) 0x55); //ENUM
617 b = Encoding.UTF8.GetBytes (((ClassRef) type).TypeName ());
618 MetaData.CompressNum ((uint) b.Length, (MemoryStream) bw.BaseStream);
622 b = Encoding.UTF8.GetBytes (name);
623 MetaData.CompressNum ((uint) b.Length, (MemoryStream) bw.BaseStream);
626 ((Constant) value).Write (bw);
631 public class Permission
639 public Permission (PEAPI.Type type, string name)
645 public void AddMember (PEAPI.PermissionMember member)
648 members = new ArrayList ();
650 members.Add (member);
653 public void Write (BinaryWriter bw)
655 byte [] b = Encoding.UTF8.GetBytes (name);
656 MetaData.CompressNum ((uint) b.Length, (MemoryStream) bw.BaseStream);
659 BinaryWriter perm_writer = new BinaryWriter (new MemoryStream (), Encoding.Unicode);
660 MemoryStream str = (MemoryStream) perm_writer.BaseStream;
662 MetaData.CompressNum ((uint) members.Count, str);//number of params
663 foreach (PermissionMember member in members)
664 member.Write (perm_writer);
666 bw.Write ((byte) str.Length); //(optional) parameters length
667 bw.Write (str.ToArray ());
671 public class PermissionSet
673 PEAPI.SecurityAction sec_action;
674 ArrayList permissions;
675 PEAPI.PermissionSet ps;
677 public PermissionSet (PEAPI.SecurityAction sec_action)
679 this.sec_action = sec_action;
682 public void AddPermission (PEAPI.Permission perm)
684 if (permissions == null)
685 permissions = new ArrayList ();
687 permissions.Add (perm);
690 public void Write (BinaryWriter bw)
692 bw.Write ((byte) 0x2e);
693 MetaData.CompressNum ((uint) permissions.Count, (MemoryStream) bw.BaseStream);
695 foreach (Permission perm in permissions)
701 /**************************************************************************/
703 /// Descriptor for layout information for a field
706 public class FieldLayout : MetaDataElement {
711 internal FieldLayout(Field field, uint offset)
714 this.offset = offset;
715 tabIx = MDTable.FieldLayout;
718 internal sealed override uint Size(MetaData md)
720 return 4 + md.TableIndexSize(MDTable.Field);
723 internal sealed override void Write(FileImage output)
725 output.Write(offset);
726 output.WriteIndex(MDTable.Field,field.Row);
731 /*****************************************************************************/
733 /// Marshalling information for a field or param
735 public class FieldMarshal : MetaDataElement {
737 MetaDataElement field;
741 internal FieldMarshal(MetaDataElement field, NativeType nType)
745 tabIx = MDTable.FieldMarshal;
748 internal override uint SortKey()
750 return (field.Row << MetaData.CIxShiftMap[(uint)CIx.HasFieldMarshal])
751 | field.GetCodedIx(CIx.HasFieldMarshal);
754 internal sealed override void BuildTables(MetaData md)
757 ntIx = md.AddToBlobHeap(nt.ToBlob());
761 internal sealed override uint Size(MetaData md)
763 return md.CodedIndexSize(CIx.HasFieldMarshal) + md.BlobIndexSize();
766 internal sealed override void Write(FileImage output)
768 output.WriteCodedIndex(CIx.HasFieldMarshal,field);
769 output.BlobIndex(ntIx);
774 /**************************************************************************/
776 /// Descriptor for the address of a field's value in the PE file
778 public class FieldRVA : MetaDataElement {
783 internal FieldRVA(Field field, DataConstant data)
787 tabIx = MDTable.FieldRVA;
790 internal sealed override void BuildTables(MetaData md)
797 internal sealed override uint Size(MetaData md)
799 return 4 + md.TableIndexSize(MDTable.Field);
802 internal sealed override void Write(FileImage output)
804 output.WriteDataRVA(data.DataOffset);
805 output.WriteIndex(MDTable.Field,field.Row);
810 /**************************************************************************/
812 /// Descriptor for a file referenced in THIS assembly/module (.file)
814 public class FileRef : MetaDataElement {
816 private static readonly uint NoMetaData = 0x1;
817 uint nameIx = 0, hashIx = 0;
819 protected string name;
821 internal FileRef(string name, byte[] hashBytes, bool metaData,
822 bool entryPoint, MetaData md) {
823 if (!metaData) flags = NoMetaData;
824 if (entryPoint) md.SetEntryPoint(this);
826 nameIx = md.AddToStringsHeap(name);
827 hashIx = md.AddToBlobHeap(hashBytes);
828 tabIx = MDTable.File;
831 internal FileRef(uint nameIx, byte[] hashBytes, bool metaData,
832 bool entryPoint, MetaData md) {
833 if (!metaData) flags = NoMetaData;
834 if (entryPoint) md.SetEntryPoint(this);
835 this.nameIx = nameIx;
836 hashIx = md.AddToBlobHeap(hashBytes);
837 tabIx = MDTable.File;
840 internal sealed override uint Size(MetaData md)
842 return 4 + md.StringsIndexSize() + md.BlobIndexSize();
845 internal sealed override void BuildTables(MetaData md)
847 md.AddToTable(MDTable.File,this);
850 internal sealed override void Write(FileImage output)
853 output.StringsIndex(nameIx);
854 output.BlobIndex(hashIx);
857 internal sealed override uint GetCodedIx(CIx code)
860 case (CIx.HasCustomAttr) : return 16;
861 case (CIx.Implementation) : return 0;
867 /**************************************************************************/
869 /// Descriptor for pinvoke information for a method NOT YET IMPLEMENTED
871 public class ImplMap : MetaDataElement {
873 private static readonly ushort NoMangle = 0x01;
878 ModuleRef importScope;
880 internal ImplMap(ushort flag, Method implMeth, string iName, ModuleRef mScope)
885 importScope = mScope;
886 tabIx = MDTable.ImplMap;
887 if (iName == null) flags |= NoMangle;
888 //throw(new NotYetImplementedException("PInvoke "));
891 internal override uint SortKey()
893 return (meth.Row << MetaData.CIxShiftMap[(uint)CIx.MemberForwarded])
894 | meth.GetCodedIx(CIx.MemberForwarded);
897 internal sealed override void BuildTables(MetaData md)
900 iNameIx = md.AddToStringsHeap(importName);
904 internal sealed override uint Size(MetaData md)
906 return 2+ md.CodedIndexSize(CIx.MemberForwarded) +
907 md.StringsIndexSize() + md.TableIndexSize(MDTable.ModuleRef);
910 internal sealed override void Write(FileImage output)
913 output.WriteCodedIndex(CIx.MemberForwarded,meth);
914 output.StringsIndex(iNameIx);
915 output.WriteIndex(MDTable.ModuleRef,importScope.Row);
920 /**************************************************************************/
922 public class GenericParameter : MetaDataElement {
924 MetaDataElement owner;
929 GenericParamAttributes attr;
931 internal GenericParameter (ClassDef owner, MetaData metadata,
932 short index, string name, GenericParamAttributes attr) : this (owner, metadata, index, name, attr, true)
936 internal GenericParameter (MethodDef owner, MetaData metadata,
937 short index, string name, GenericParamAttributes attr) : this (owner, metadata, index, name, attr, true)
941 private GenericParameter (MetaDataElement owner, MetaData metadata,
942 short index, string name, GenericParamAttributes attr, bool nadda) {
944 this.metadata = metadata;
946 tabIx = MDTable.GenericParam;
951 internal override uint SortKey()
953 return (owner.Row << MetaData.CIxShiftMap[(uint)CIx.TypeOrMethodDef])
954 | owner.GetCodedIx(CIx.TypeOrMethodDef);
957 internal override uint SortKey2 ()
962 public void AddConstraint (Type constraint)
964 metadata.AddToTable (MDTable.GenericParamConstraint,
965 new GenericParamConstraint (this, constraint));
968 internal sealed override uint Size(MetaData md)
971 md.CodedIndexSize(CIx.TypeOrMethodDef) +
972 md.StringsIndexSize ());
975 internal sealed override void BuildTables(MetaData md)
978 nameIx = md.AddToStringsHeap(name);
982 internal sealed override void Write(FileImage output)
984 output.Write ((short) index);
985 output.Write ((short) attr);
986 output.WriteCodedIndex(CIx.TypeOrMethodDef, owner);
987 output.StringsIndex (nameIx);
990 internal sealed override uint GetCodedIx(CIx code)
993 case (CIx.HasCustomAttr) : return 19;
1000 internal class GenericParamConstraint : MetaDataElement {
1002 GenericParameter param;
1005 public GenericParamConstraint (GenericParameter param, Type type)
1009 tabIx = MDTable.GenericParamConstraint;
1012 internal override uint SortKey()
1017 internal sealed override uint Size(MetaData md)
1019 return (uint) (md.TableIndexSize(MDTable.GenericParam) +
1020 md.CodedIndexSize(CIx.TypeDefOrRef));
1023 internal sealed override void Write(FileImage output)
1025 output.WriteIndex(MDTable.GenericParam, param.Row);
1026 output.WriteCodedIndex(CIx.TypeDefOrRef, type);
1031 internal class MethodSpec : Method {
1034 GenericMethodSig g_sig;
1037 internal MethodSpec (Method meth, GenericMethodSig g_sig) : base ("")
1041 tabIx = MDTable.MethodSpec;
1044 internal override uint GetSigIx (MetaData md)
1046 throw new Exception ("Should not be used.");
1049 public override void AddCallConv (CallConv cconv)
1051 throw new Exception ("Should not be used.");
1054 internal sealed override void BuildTables (MetaData md)
1057 sidx = g_sig.GetSigIx (md);
1061 internal sealed override uint Size (MetaData md)
1063 return (uint) (md.CodedIndexSize(CIx.MethodDefOrRef) +
1064 md.BlobIndexSize ());
1067 internal sealed override void Write (FileImage output)
1069 output.WriteCodedIndex (CIx.MethodDefOrRef, meth);
1070 output.BlobIndex (sidx);
1073 internal sealed override void TypeSig (MemoryStream sig)
1075 throw new Exception ("Should not be used.");
1079 /**************************************************************************/
1081 /// Descriptor for interface implemented by a class
1083 public class InterfaceImpl: MetaDataElement {
1088 internal InterfaceImpl(ClassDef theClass, Class theInterface)
1090 this.theClass = theClass;
1091 this.theInterface = theInterface;
1092 tabIx = MDTable.InterfaceImpl;
1095 internal sealed override uint Size(MetaData md)
1097 return md.TableIndexSize(MDTable.TypeDef) +
1098 md.CodedIndexSize(CIx.TypeDefOrRef);
1101 internal sealed override void Write(FileImage output)
1103 output.WriteIndex(MDTable.TypeDef,theClass.Row);
1104 output.WriteCodedIndex(CIx.TypeDefOrRef,theInterface);
1107 internal sealed override uint GetCodedIx(CIx code) { return 5; }
1109 internal override uint SortKey ()
1111 return (theClass.Row << MetaData.CIxShiftMap[(uint)CIx.TypeDefOrRef])
1112 | theClass.GetCodedIx (CIx.TypeDefOrRef);
1117 /**************************************************************************/
1119 /// Descriptor for resources used in this PE file
1122 public class ManifestResource : MetaDataElement {
1124 public static readonly uint PublicResource = 0x1;
1125 public static readonly uint PrivateResource = 0x2;
1128 MetaDataElement rRef;
1132 byte [] resourceBytes;
1134 public ManifestResource (string name, byte[] resBytes, uint flags)
1136 InitResource (name, flags);
1137 this.resourceBytes = resBytes;
1140 public ManifestResource(string name, uint flags, FileRef fileRef)
1142 InitResource (name, flags);
1146 public ManifestResource(string name, uint flags, FileRef fileRef,
1148 InitResource (name, flags);
1150 fileOffset = fileIx;
1153 public ManifestResource(string name, uint flags, AssemblyRef assemRef)
1155 InitResource (name, flags);
1159 internal ManifestResource (ManifestResource mres)
1161 mrName = mres.mrName;
1164 fileOffset = mres.fileOffset;
1165 resourceBytes = mres.resourceBytes;
1168 private void InitResource (string name, uint flags)
1172 tabIx = MDTable.ManifestResource;
1175 internal sealed override void BuildTables(MetaData md)
1178 md.AddToTable (MDTable.ManifestResource, this);
1179 nameIx = md.AddToStringsHeap(mrName);
1180 if (resourceBytes != null) {
1182 throw new PEFileException ("Manifest Resource has byte value and file reference");
1183 fileOffset = md.AddResource(resourceBytes);
1186 throw new PEFileException ("Manifest Resource has no implementation or value");
1187 rRef.BuildTables (md);
1193 internal sealed override uint Size(MetaData md)
1195 return 8 + md.StringsIndexSize() +
1196 md.CodedIndexSize(CIx.Implementation);
1199 internal sealed override void Write(FileImage output)
1201 output.Write(fileOffset);
1202 output.Write(flags);
1203 output.StringsIndex(nameIx);
1204 output.WriteCodedIndex(CIx.Implementation,rRef);
1207 internal sealed override uint GetCodedIx(CIx code) { return 18; }
1209 public string Name {
1210 get { return mrName; }
1211 set { mrName = value; }
1215 /**************************************************************************/
1217 /// Base class for elements in the PropertyMap, EventMap and
1218 /// NestedClass MetaData tables
1220 public class MapElem : MetaDataElement {
1226 internal MapElem(ClassDef par, uint elIx, MDTable elemTab)
1230 elemTable = elemTab;
1233 internal sealed override uint Size(MetaData md)
1235 return md.TableIndexSize(MDTable.TypeDef) + md.TableIndexSize(elemTable);
1238 internal sealed override void Write(FileImage output)
1240 output.WriteIndex(MDTable.TypeDef,parent.Row);
1241 output.WriteIndex(elemTable,elemIx);
1245 /**************************************************************************/
1247 /// Descriptor for an overriding method (.override)
1249 public class MethodImpl : MetaDataElement {
1252 Method header, body;
1254 internal MethodImpl(ClassDef par, Method decl, Method bod)
1259 tabIx = MDTable.MethodImpl;
1262 internal sealed override uint Size(MetaData md)
1264 return md.TableIndexSize(MDTable.TypeDef) + 2 * md.CodedIndexSize(CIx.MethodDefOrRef);
1267 internal sealed override void Write(FileImage output)
1269 output.WriteIndex(MDTable.TypeDef,parent.Row);
1270 output.WriteCodedIndex(CIx.MethodDefOrRef,body);
1271 output.WriteCodedIndex(CIx.MethodDefOrRef,header);
1276 /**************************************************************************/
1278 /// Descriptor for Property and Event methods
1280 public class MethodSemantics : MetaDataElement {
1282 Feature.MethodType type;
1284 Feature eventOrProp;
1286 internal MethodSemantics(Feature.MethodType mType, MethodDef method, Feature feature)
1290 eventOrProp = feature;
1291 tabIx = MDTable.MethodSemantics;
1294 internal override uint SortKey()
1296 return (eventOrProp.Row << MetaData.CIxShiftMap [(uint)CIx.HasSemantics])
1297 | eventOrProp.GetCodedIx (CIx.HasSemantics);
1300 internal sealed override uint Size(MetaData md)
1302 return 2 + md.TableIndexSize(MDTable.Method) + md.CodedIndexSize(CIx.HasSemantics);
1305 internal sealed override void Write(FileImage output)
1307 output.Write((ushort)type);
1308 output.WriteIndex(MDTable.Method,meth.Row);
1309 output.WriteCodedIndex(CIx.HasSemantics,eventOrProp);
1314 /**************************************************************************/
1316 /// Descriptor for a parameter of a method defined in this assembly/module
1318 public class Param : MetaDataElement {
1323 internal ushort seqNo = 0;
1325 ConstantElem defaultVal;
1327 FieldMarshal marshalInfo;
1330 /// Create a new parameter for a method
1332 /// <param name="mode">param mode (in, out, opt)</param>
1333 /// <param name="parName">parameter name</param>
1334 /// <param name="parType">parameter type</param>
1335 public Param(ParamAttr mode, string parName, Type parType)
1339 parMode = (ushort)mode;
1340 tabIx = MDTable.Param;
1343 public bool HasMarshalInfo {
1344 get { return marshalInfo != null; }
1348 /// Add a default value to this parameter
1350 /// <param name="c">the default value for the parameter</param>
1351 public void AddDefaultValue(Constant cVal)
1353 defaultVal = new ConstantElem(this,cVal);
1354 parMode |= (ushort) ParamAttr.HasDefault;
1358 /// Add marshalling information about this parameter
1360 public void AddMarshallInfo(NativeType marshallType)
1362 parMode |= (ushort) ParamAttr.HasFieldMarshal;
1363 marshalInfo = new FieldMarshal(this,marshallType);
1366 internal Type GetParType() { return pType; }
1368 internal sealed override void BuildTables(MetaData md)
1371 nameIx = md.AddToStringsHeap(pName);
1372 if (defaultVal != null) {
1373 md.AddToTable(MDTable.Constant,defaultVal);
1374 defaultVal.BuildTables(md);
1376 if (marshalInfo != null) {
1377 md.AddToTable(MDTable.FieldMarshal,marshalInfo);
1378 marshalInfo.BuildTables(md);
1383 internal void TypeSig(MemoryStream str)
1388 internal sealed override uint Size(MetaData md)
1390 return 4 + md.StringsIndexSize();
1393 internal sealed override void Write(FileImage output)
1395 output.Write(parMode);
1396 output.Write(seqNo);
1397 output.StringsIndex(nameIx);
1400 internal sealed override uint GetCodedIx(CIx code)
1403 case (CIx.HasCustomAttr) : return 4;
1404 case (CIx.HasConst) : return 1;
1405 case (CIx.HasFieldMarshal) : return 1;
1412 /**************************************************************************/
1413 public abstract class Signature : MetaDataElement {
1415 protected uint sigIx;
1417 internal Signature()
1419 tabIx = MDTable.StandAloneSig;
1422 internal sealed override uint Size(MetaData md)
1424 return md.BlobIndexSize();
1427 internal sealed override void Write(FileImage output)
1429 output.BlobIndex(sigIx);
1432 internal sealed override uint GetCodedIx(CIx code) { return (uint)tabIx; }
1436 /**************************************************************************/
1437 public class TypeSpec : MetaDataElement {
1440 internal TypeSpec(Type aType, MetaData md)
1442 MemoryStream sig = new MemoryStream();
1444 sigIx = md.AddToBlobHeap(sig.ToArray());
1445 tabIx = MDTable.TypeSpec;
1448 internal sealed override uint GetCodedIx(CIx code)
1451 case (CIx.TypeDefOrRef) : return 2;
1452 case (CIx.HasCustomAttr) : return 13;
1453 case (CIx.MemberRefParent) : return 4;
1458 internal override uint Size(MetaData md)
1460 return md.BlobIndexSize();
1463 internal sealed override void Write(FileImage output)
1465 //Console.WriteLine("Writing the blob index for a TypeSpec");
1466 output.BlobIndex(sigIx);
1471 /**************************************************************************/
1473 /// Base class for all IL types
1475 public abstract class Type : MetaDataElement {
1476 protected byte typeIndex;
1477 protected TypeSpec typeSpec;
1479 internal Type(byte tyIx) { typeIndex = tyIx; }
1481 internal byte GetTypeIndex() { return typeIndex; }
1482 internal void SetTypeIndex (byte b) { typeIndex = b; }
1484 internal virtual MetaDataElement GetTypeSpec(MetaData md)
1486 if (typeSpec == null) {
1487 typeSpec = new TypeSpec(this,md);
1488 md.AddToTable(MDTable.TypeSpec,typeSpec);
1493 internal virtual void TypeSig(MemoryStream str)
1495 throw(new TypeSignatureException(this.GetType().AssemblyQualifiedName +
1496 " doesn't have a type signature!!"));
1500 public class ClassRefInst : Type {
1503 private bool is_value;
1505 public ClassRefInst (Type type, bool is_value) : base (PrimitiveType.Class.GetTypeIndex ())
1508 this.is_value = is_value;
1510 typeIndex = PrimitiveType.ValueType.GetTypeIndex ();
1511 tabIx = MDTable.TypeSpec;
1514 internal sealed override void TypeSig(MemoryStream str)
1520 /**************************************************************************/
1522 /// The base descriptor for a class
1524 public abstract class Class : Type {
1526 protected int row = 0;
1527 public string name, nameSpace;
1528 protected uint nameIx, nameSpaceIx;
1529 protected MetaData _metaData;
1530 internal Class(string nameSpaceName, string className, MetaData md)
1531 : base(PrimitiveType.Class.GetTypeIndex ())
1533 nameSpace = nameSpaceName;
1535 nameIx = md.AddToStringsHeap(name);
1536 nameSpaceIx = md.AddToStringsHeap(nameSpace);
1540 internal Class(uint nsIx, uint nIx) : base(PrimitiveType.Class.GetTypeIndex ())
1546 internal Class (byte typeIndex) : base (typeIndex)
1548 nameSpace = "Should not be used";
1549 name = "Should not be used";
1552 internal virtual uint TypeDefOrRefToken() { return 0; }
1554 internal virtual void MakeValueClass(ValueClass vClass)
1556 typeIndex = PrimitiveType.ValueType.GetTypeIndex ();
1559 internal virtual string TypeName()
1561 return (nameSpace + "." + name);
1564 internal override MetaDataElement GetTypeSpec(MetaData md)
1570 /**************************************************************************/
1571 // This Class produces entries in the TypeDef table of the MetaData
1572 // in the PE meta data.
1574 // NOTE: Entry 0 in TypeDef table is always the pseudo class <module>
1575 // which is the parent for functions and variables declared a module level
1578 /// The descriptor for a class defined in the IL (.class) in the current assembly/module
1581 public class ClassDef : Class {
1583 private static readonly byte ElementType_Class = 0x12;
1586 ArrayList fields = new ArrayList();
1587 ArrayList methods = new ArrayList();
1589 ArrayList properties;
1590 bool typeIndexChecked = true;
1591 uint fieldIx = 0, methodIx = 0;
1592 byte[] securityActions;
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 ExternClass externClass;
1963 protected MetaData metaData;
1965 internal ClassRef(string nsName, string name, MetaData md) : base(nsName, name, md)
1968 tabIx = MDTable.TypeRef;
1972 /// Add a method to this class
1974 /// <param name="name">method name</param>
1975 /// <param name="retType">return type</param>
1976 /// <param name="pars">parameter types</param>
1977 /// <returns>a descriptor for this method</returns>
1978 public MethodRef AddMethod(string name, Type retType, Type[] pars)
1980 return AddMethod (name, retType, pars, 0);
1984 /// Add a method to this class
1986 /// <param name="name">method name</param>
1987 /// <param name="retType">return type</param>
1988 /// <param name="pars">parameter types</param>
1989 /// <param name="gen_param_count">num of generic parameters</param>
1990 /// <returns>a descriptor for this method</returns>
1991 public MethodRef AddMethod (string name, Type retType, Type[] pars, int gen_param_count)
1993 MethodRef meth = new MethodRef (this, name, retType, pars, false, null, gen_param_count);
1994 metaData.AddToTable(MDTable.MemberRef,meth);
1999 /// Add a method to this class
2001 /// <param name="name">method name</param>
2002 /// <param name="retType">return type</param>
2003 /// <param name="pars">parameter types</param>
2004 /// <returns>a descriptor for this method</returns>
2005 public MethodRef AddVarArgMethod(string name, Type retType,
2006 Type[] pars, Type[] optPars)
2008 MethodRef meth = new MethodRef(this,name,retType,pars,true,optPars, 0);
2009 metaData.AddToTable(MDTable.MemberRef,meth);
2014 /// Add a field to this class
2016 /// <param name="name">field name</param>
2017 /// <param name="fType">field type</param>
2018 /// <returns>a descriptor for this field</returns>
2019 public FieldRef AddField(string name, Type fType)
2021 FieldRef field = new FieldRef(this,name,fType);
2022 metaData.AddToTable(MDTable.MemberRef,field);
2026 public ClassRef AddClass (string nsName, string name)
2028 ClassRef aClass = new ClassRef(nsName,name,metaData);
2029 metaData.AddToTable(MDTable.TypeRef,aClass);
2030 aClass.SetParent(this);
2034 public ClassRef AddValueClass (string nsName, string name)
2036 ClassRef aClass = AddClass (nsName, name);
2037 aClass.MakeValueClass (ValueClass.ValueType);
2041 internal void SetParent(IResolutionScope par)
2046 internal override string TypeName()
2048 if ((parent != null) && (parent is AssemblyRef))
2049 return (nameSpace + "." + name + ", " + ((AssemblyRef)parent).TypeName());
2051 return (nameSpace + name);
2054 internal sealed override uint Size(MetaData md)
2056 return md.CodedIndexSize(CIx.ResolutionScope) + 2 *
2057 md.StringsIndexSize();
2060 internal sealed override void Write(FileImage output)
2062 output.WriteCodedIndex(CIx.ResolutionScope,(MetaDataElement) parent);
2063 output.StringsIndex(nameIx);
2064 output.StringsIndex(nameSpaceIx);
2067 internal override sealed uint TypeDefOrRefToken()
2070 cIx = (cIx << 2) | 0x1;
2074 internal override void TypeSig(MemoryStream sig)
2076 sig.WriteByte(GetTypeIndex());
2077 MetaData.CompressNum(TypeDefOrRefToken(),sig);
2080 internal sealed override uint GetCodedIx(CIx code)
2083 case (CIx.TypeDefOrRef) : return 1;
2084 case (CIx.HasCustomAttr) : return 2;
2085 case (CIx.MemberRefParent) : return 1;
2086 case (CIx.ResolutionScope) : return 3;
2093 /**************************************************************************/
2094 public class ExternClassRef : ClassRef {
2096 ExternClass externClass;
2098 internal ExternClassRef(TypeAttr attrs, string nsName, string name,
2099 FileRef declFile, MetaData md) : base(nsName,name,md)
2101 externClass = new ExternClass(attrs,nameSpaceIx,nameIx,declFile);
2102 metaData.AddToTable(MDTable.ExportedType,externClass);
2105 internal ExternClassRef(string name, MetaData md) : base(null,name,md)
2109 public ClassRef AddNestedClass(TypeAttr attrs, string name)
2111 ExternClassRef nestedClass = new ExternClassRef(name,metaData);
2112 externClass = new ExternClass(attrs,0,nameIx,this.externClass);
2113 metaData.AddToTable(MDTable.ExportedType,externClass);
2119 /**************************************************************************/
2121 /// Descriptor for a class defined in another module of THIS assembly
2122 /// and exported (.class extern)
2125 internal class ExternClass : Class {
2127 MetaDataElement parent;
2130 internal ExternClass(TypeAttr attr, uint nsIx, uint nIx,
2131 MetaDataElement paren) : base(nsIx,nIx)
2135 tabIx = MDTable.ExportedType;
2138 internal sealed override uint Size(MetaData md)
2140 return 8 + 2* md.StringsIndexSize() + md.CodedIndexSize(CIx.Implementation);
2143 internal sealed override void Write(FileImage output)
2145 output.Write(flags);
2147 output.StringsIndex(nameIx);
2148 output.StringsIndex(nameSpaceIx);
2149 output.WriteCodedIndex(CIx.Implementation,parent);
2152 internal sealed override uint GetCodedIx(CIx code)
2155 case (CIx.HasCustomAttr) : return 17;
2156 case (CIx.Implementation) : return 2;
2163 public class GenParam : Class {
2166 private string param_name;
2167 private uint sigIx = 0;
2169 public GenParam (int index, string name, GenParamType ptype) : base ((byte) ptype)
2172 this.param_name = name;
2173 tabIx = MDTable.TypeSpec;
2177 get { return index; }
2178 set { index = value; }
2181 public string Name {
2182 get { return param_name; }
2183 set { param_name = value; }
2186 public GenParamType Type {
2187 get { return (GenParamType) GetTypeIndex (); }
2190 internal sealed override void BuildTables (MetaData md)
2194 MemoryStream str = new MemoryStream ();
2196 sigIx = md.AddToBlobHeap (str.ToArray ());
2201 internal sealed override void TypeSig(MemoryStream str)
2204 throw new PEFileException (String.Format ("Unresolved {0} - {1}", (GenParamType) GetTypeIndex (), param_name));
2205 str.WriteByte(typeIndex);
2206 MetaData.CompressNum ((uint) index, str);
2209 internal override uint Size(MetaData md)
2211 return md.BlobIndexSize();
2214 internal sealed override void Write (FileImage output)
2216 output.BlobIndex (sigIx);
2219 internal sealed override uint GetCodedIx(CIx code)
2222 case (CIx.TypeDefOrRef) : return 2;
2223 case (CIx.HasCustomAttr) : return 13;
2224 case (CIx.MemberRefParent) : return 4;
2230 public class GenericTypeInst : Class {
2232 private Type gen_type;
2233 private Type[] gen_param;
2234 bool inTable = false;
2237 public GenericTypeInst (Type gen_type, Type[] gen_param)
2238 : base ((byte) PrimitiveType.GenericInst.GetTypeIndex ())
2240 this.gen_type = gen_type;
2241 this.gen_param = gen_param;
2242 tabIx = MDTable.TypeSpec;
2245 internal override MetaDataElement GetTypeSpec (MetaData md)
2248 md.AddToTable (MDTable.TypeSpec, this);
2255 internal sealed override void TypeSig(MemoryStream str)
2257 str.WriteByte(typeIndex);
2258 gen_type.TypeSig (str);
2259 MetaData.CompressNum ((uint) gen_param.Length, str);
2260 foreach (Type param in gen_param)
2261 param.TypeSig (str);
2264 internal sealed override void BuildTables (MetaData md)
2268 MemoryStream str = new MemoryStream ();
2270 sigIx = md.AddToBlobHeap (str.ToArray ());
2275 internal sealed override uint Size (MetaData md)
2277 return md.BlobIndexSize ();
2280 internal sealed override void Write (FileImage output)
2282 output.BlobIndex (sigIx);
2285 internal sealed override uint GetCodedIx (CIx code)
2288 case (CIx.TypeDefOrRef): return 2;
2289 case (CIx.MemberRefParent): return 4;
2290 case (CIx.HasCustomAttr): return 13;
2296 public class GenericMethodSig {
2298 private Type[] gen_param;
2300 private uint sigIx = 0;
2302 public GenericMethodSig (Type[] gen_param)
2304 this.gen_param = gen_param;
2308 internal void TypeSig (MemoryStream str)
2310 str.WriteByte (0x0A); /* GENERIC_INST */
2311 MetaData.CompressNum ((uint) gen_param.Length, str);
2312 foreach (Type param in gen_param)
2313 param.TypeSig (str);
2316 internal uint GetSigIx (MetaData md)
2321 MemoryStream sig = new MemoryStream();
2323 sigIx = md.AddToBlobHeap (sig.ToArray());
2329 public class Sentinel : Type {
2331 public Sentinel () : base (0x41) { }
2333 internal sealed override void TypeSig(MemoryStream str)
2335 str.WriteByte(typeIndex);
2339 /**************************************************************************/
2341 /// Descriptor for a FunctionPointer type
2344 public class MethPtrType : Type {
2356 /// Create a new function pointer type
2358 /// <param name="meth">the function to be referenced</param>
2359 public MethPtrType (CallConv callconv, Type retType, Type[] pars,
2360 bool varArgMeth, Type[] optPars) : base(0x1B)
2362 this.retType = retType;
2363 callConv = callconv;
2365 this.varArgMeth = varArgMeth;
2366 if (parList != null) numPars = (uint)parList.Length;
2368 optParList = optPars;
2369 if (optParList != null) numOptPars = (uint)optParList.Length;
2370 callConv |= CallConv.Vararg;
2372 tabIx = MDTable.TypeSpec;
2375 internal sealed override void TypeSig(MemoryStream sig)
2377 sig.WriteByte(typeIndex);
2378 // Bootlegged from method ref
2379 sig.WriteByte((byte)callConv);
2380 MetaData.CompressNum (numPars + numOptPars, sig);
2381 retType.TypeSig (sig);
2382 for (int i=0; i < numPars; i++) {
2383 parList[i].TypeSig (sig);
2386 sig.WriteByte (0x41); // Write the sentinel
2387 for (int i=0; i < numOptPars; i++) {
2388 optParList[i].TypeSig (sig);
2393 internal sealed override void BuildTables(MetaData md)
2396 MemoryStream sig = new MemoryStream();
2398 sigIx = md.AddToBlobHeap(sig.ToArray());
2402 internal sealed override uint Size(MetaData md)
2404 return md.BlobIndexSize();
2407 internal sealed override void Write(FileImage output)
2409 output.BlobIndex(sigIx);
2412 internal sealed override uint GetCodedIx(CIx code) { return 0x1B; }
2417 /* Classes for Arrays */
2420 /// The IL Array type
2422 public abstract class Array : Type {
2424 protected Type elemType;
2425 protected MetaData metaData;
2426 protected string cnameSpace, cname;
2428 internal Array(Type eType, byte TypeId) : base(TypeId)
2431 tabIx = MDTable.TypeSpec;
2436 /// Single dimensional array with zero lower bound
2438 public class ZeroBasedArray : Array {
2441 /// Create a new array - elementType[]
2443 /// <param name="elementType">the type of the array elements</param>
2444 public ZeroBasedArray(Type elementType) : base (elementType, PrimitiveType.SZArray.GetTypeIndex ()) { }
2446 internal sealed override void TypeSig(MemoryStream str)
2448 str.WriteByte(typeIndex);
2449 elemType.TypeSig(str);
2455 /// Multi dimensional array with explicit bounds
2457 public class BoundArray : Array {
2463 /// Create a new multi dimensional array type
2464 /// eg. elemType[1..5,3..10,5,,] would be
2465 /// new BoundArray(elemType,5,[1,3,0],[5,10,4])
2467 /// <param name="elementType">the type of the elements</param>
2468 /// <param name="dimensions">the number of dimensions</param>
2469 /// <param name="loBounds">lower bounds of dimensions</param>
2470 /// <param name="sizes">sizes for the dimensions</param>
2471 public BoundArray(Type elementType, uint dimensions, int[] loBounds,
2472 int[] sizes) : base (elementType,0x14)
2474 numDims = dimensions;
2475 lowerBounds = loBounds;
2480 /// Create a new multi dimensional array type
2481 /// eg. elemType[5,10,20] would be new BoundArray(elemType,3,[5,10,20])
2483 /// <param name="elementType">the type of the elements</param>
2484 /// <param name="dimensions">the number of dimensions</param>
2485 /// <param name="size">the sizes of the dimensions</param>
2486 public BoundArray(Type elementType, uint dimensions, int[] size)
2487 : base (elementType,0x14)
2489 numDims = dimensions;
2494 /// Create a new multi dimensional array type
2495 /// eg. elemType[,,] would be new BoundArray(elemType,3)
2497 /// <param name="elementType">the type of the elements</param>
2498 /// <param name="dimensions">the number of dimensions</param>
2499 public BoundArray(Type elementType, uint dimensions)
2500 : base (elementType,0x14)
2502 numDims = dimensions;
2505 internal sealed override void TypeSig(MemoryStream str)
2507 str.WriteByte(typeIndex);
2508 elemType.TypeSig(str);
2509 MetaData.CompressNum(numDims,str);
2510 if ((sizes != null) && (sizes.Length > 0)) {
2512 MetaData.CompressNum((uint)sizes.Length,str);
2513 for (int i=0; i < sizes.Length; i++) {
2514 MetaData.CompressNum((uint)sizes[i],str);
2516 } else str.WriteByte(0);
2517 if ((lowerBounds != null) && (lowerBounds.Length > 0)) {
2518 MetaData.CompressNum((uint)lowerBounds.Length,str);
2519 for (int i=0; i < lowerBounds.Length; i++) {
2520 CompressSignedNum (lowerBounds[i],str);
2522 } else str.WriteByte(0);
2524 private void CompressSignedNum (int val, MemoryStream str)
2526 uint uval = (uint) val;
2533 /* Map the signed number to an unsigned number in two ways.
2535 fval: left-rotated 2's complement representation
2536 sval: map the signed number to unsigned as follows: 0 -> 0, -1 -> 1, 1 -> 2, -2 -> 3, 2 -> 4, ....
2537 the mapping is: x -> 2*|x| - signbit(x)
2539 uint fval = (uval << 1) | sign;
2540 int sval = (val << 1) - sign;
2542 /* An overly clever transformation:
2544 a. sval is used to determine the number of bytes in the compressed representation.
2545 b. fval is truncated to the appropriate number of bits and output using the
2546 normal unsigned-int compressor.
2548 However, or certain values, the truncated fval doesn't carry enough information to round trip.
2550 (fval & 0x3FFF) <= 0x7F => compressor emits 1 byte, not 2 => there is aliasing of values
2552 So, we use full 4 bytes to encode such values.
2554 LAMESPEC: The Microsoft implementation doesn't appear to handle this subtle case.
2555 e.g., it ends up encoding -8192 as the byte 0x01, which decodes to -64
2558 MetaData.CompressNum (fval & 0x7F, str);
2559 else if (sval <= 0x3FFF && (fval & 0x3FFF) > 0x7F)
2560 MetaData.CompressNum (fval & 0x3FFF, str);
2561 else if (sval <= 0x1FFFFFFF && (fval & 0x1FFFFFFF) > 0x3FFF)
2562 MetaData.CompressNum (fval & 0x1FFFFFFF, str);
2564 /* FIXME: number cannot be represented. Report a warning. */
2565 // throw new Exception ("cannot represent signed value" + -val);
2566 MetaData.CompressNum (fval, str);
2573 /* Empty interface for grouping TypeRef's possible ResolutionScope
2574 namely : Module, ModuleRef, AssemblyRef and TypeRef */
2575 public interface IResolutionScope {
2578 /**************************************************************************/
2580 /// Base class for scopes (extended by Module, ModuleRef, Assembly, AssemblyRef)
2582 public abstract class ResolutionScope : MetaDataElement, IResolutionScope {
2584 protected uint nameIx = 0;
2585 protected MetaData metaData;
2586 protected string name;
2588 internal ResolutionScope(string name, MetaData md)
2592 nameIx = md.AddToStringsHeap(name);
2595 internal string GetName() { return name; }
2599 /**************************************************************************/
2601 /// Descriptor for THIS assembly (.assembly)
2603 public class Assembly : ResolutionScope {
2605 ushort majorVer, minorVer, buildNo, revisionNo;
2608 uint keyIx = 0, cultIx = 0;
2609 bool hasPublicKey = false;
2611 internal Assembly(string name, MetaData md) : base(name,md)
2613 tabIx = MDTable.Assembly;
2617 /// Add details about THIS assembly
2619 /// <param name="majVer">Major Version</param>
2620 /// <param name="minVer">Minor Version</param>
2621 /// <param name="bldNo">Build Number</param>
2622 /// <param name="revNo">Revision Number</param>
2623 /// <param name="key">Hash Key</param>
2624 /// <param name="hash">Hash Algorithm</param>
2625 /// <param name="cult">Culture</param>
2626 public void AddAssemblyInfo(int majVer, int minVer, int bldNo, int revNo,
2627 byte[] key, uint hash, string cult)
2629 majorVer = (ushort)majVer;
2630 minorVer = (ushort)minVer;
2631 buildNo = (ushort)bldNo;
2632 revisionNo = (ushort)revNo;
2634 hasPublicKey = (key != null);
2635 keyIx = metaData.AddToBlobHeap(key);
2636 cultIx = metaData.AddToStringsHeap(cult);
2640 /// Add an attribute to THIS assembly
2642 /// <param name="aa">assembly attribute</param>
2643 public void AddAssemblyAttr(AssemAttr aa)
2648 internal sealed override uint Size(MetaData md)
2650 return 16 + md.BlobIndexSize() + 2 * md.StringsIndexSize();
2653 internal sealed override void Write(FileImage output)
2655 // Console.WriteLine("Writing assembly element with nameIx of " + nameIx + " at file offset " + output.Seek(0,SeekOrigin.Current));
2656 output.Write((uint)hashAlgId);
2657 output.Write(majorVer);
2658 output.Write(minorVer);
2659 output.Write(buildNo);
2660 output.Write(revisionNo);
2661 output.Write(flags);
2662 output.BlobIndex(keyIx);
2663 output.StringsIndex(nameIx);
2664 output.StringsIndex(cultIx);
2667 internal sealed override uint GetCodedIx(CIx code)
2670 case (CIx.HasCustomAttr) : return 14;
2671 case (CIx.HasDeclSecurity) : return 2;
2676 internal bool HasPublicKey {
2677 get { return hasPublicKey; }
2681 /**************************************************************************/
2683 /// Descriptor for THIS module
2685 public class Module : ResolutionScope, IExternRef {
2690 internal Module(string name, MetaData md) : base(name,md)
2692 mvid = Guid.NewGuid();
2693 mvidIx = md.AddToGUIDHeap(mvid);
2694 tabIx = MDTable.Module;
2698 get { return mvid; }
2701 public ClassRef AddClass(string nsName, string name)
2703 ClassRef aClass = new ClassRef (nsName, name, metaData);
2704 metaData.AddToTable (MDTable.TypeRef, aClass);
2705 aClass.SetParent (this);
2709 public ClassRef AddValueClass(string nsName, string name)
2711 ClassRef aClass = AddClass (nsName, name);
2712 aClass.MakeValueClass (ValueClass.ValueType);
2716 internal sealed override uint Size(MetaData md)
2718 return 2 + md.StringsIndexSize() + 3 * md.GUIDIndexSize();
2721 internal sealed override void Write(FileImage output)
2723 output.Write((short)0);
2724 output.StringsIndex(nameIx);
2725 output.GUIDIndex(mvidIx);
2726 output.GUIDIndex(0);
2727 output.GUIDIndex(0);
2730 internal sealed override uint GetCodedIx(CIx code)
2733 case (CIx.HasCustomAttr) : return 7;
2734 case (CIx.ResolutionScope) : return 0;
2739 /**************************************************************************/
2741 /// Descriptor for another module in THIS assembly
2743 public class ModuleRef : ResolutionScope, IExternRef {
2745 internal ModuleRef(MetaData md, string name) : base(name,md)
2747 tabIx = MDTable.ModuleRef;
2751 /// Add a class to this external module. This is a class declared in
2752 /// another module of THIS assembly.
2754 /// <param name="nsName">name space name</param>
2755 /// <param name="name">class name</param>
2756 /// <returns>a descriptor for this class in another module</returns>
2757 public ClassRef AddClass(string nsName, string name)
2759 ClassRef aClass = new ClassRef(nsName,name,metaData);
2760 metaData.AddToTable(MDTable.TypeRef,aClass);
2761 aClass.SetParent(this);
2766 /// Make a file descriptor to correspond to this module. The file
2767 /// descriptor will have the same name as the module descriptor
2769 /// <param name="hashBytes">the hash of the file</param>
2770 /// <param name="hasMetaData">the file contains metadata</param>
2771 /// <param name="entryPoint">the program entry point is in this file</param>
2772 /// <returns>a descriptor for the file which contains this module</returns>
2773 public FileRef MakeFile(byte[] hashBytes, bool hasMetaData, bool entryPoint)
2775 FileRef file = new FileRef(nameIx,hashBytes,hasMetaData,entryPoint,metaData);
2776 metaData.AddToTable(MDTable.File,file);
2781 /// Add a value class to this module. This is a class declared in
2782 /// another module of THIS assembly.
2784 /// <param name="nsName">name space name</param>
2785 /// <param name="name">class name</param>
2786 /// <returns></returns>
2787 public ClassRef AddValueClass(string nsName, string name)
2789 ClassRef aClass = new ClassRef(nsName,name,metaData);
2790 metaData.AddToTable(MDTable.TypeRef,aClass);
2791 aClass.SetParent(this);
2792 aClass.MakeValueClass(ValueClass.ValueType);
2797 /// Add a class which is declared public in this external module of
2798 /// THIS assembly. This class will be exported from this assembly.
2799 /// The ilasm syntax for this is .extern class
2801 /// <param name="attrSet">attributes of the class to be exported</param>
2802 /// <param name="nsName">name space name</param>
2803 /// <param name="name">external class name</param>
2804 /// <param name="declFile">the file where the class is declared</param>
2805 /// <param name="isValueClass">is this class a value type?</param>
2806 /// <returns>a descriptor for this external class</returns>
2807 public ExternClassRef AddExternClass(TypeAttr attrSet, string nsName,
2808 string name, FileRef declFile,
2809 bool isValueClass) {
2810 ExternClassRef cRef = new ExternClassRef(attrSet,nsName,name,declFile,metaData);
2811 metaData.AddToTable(MDTable.TypeRef,cRef);
2812 cRef.SetParent(this);
2813 if (isValueClass) cRef.MakeValueClass(ValueClass.ValueType);
2818 /// Add a "global" method in another module
2820 /// <param name="name">method name</param>
2821 /// <param name="retType">return type</param>
2822 /// <param name="pars">method parameter types</param>
2823 /// <returns>a descriptor for this method in anther module</returns>
2824 public MethodRef AddMethod(string name, Type retType, Type[] pars)
2826 MethodRef meth = new MethodRef(this,name,retType,pars,false,null, 0);
2827 metaData.AddToTable(MDTable.MemberRef,meth);
2832 /// Add a vararg method to this class
2834 /// <param name="name">method name</param>
2835 /// <param name="retType">return type</param>
2836 /// <param name="pars">parameter types</param>
2837 /// <param name="optPars">optional param types for this vararg method</param>
2838 /// <returns>a descriptor for this method</returns>
2839 public MethodRef AddVarArgMethod(string name, Type retType,
2840 Type[] pars, Type[] optPars) {
2841 MethodRef meth = new MethodRef(this,name,retType,pars,true,optPars, 0);
2842 metaData.AddToTable(MDTable.MemberRef,meth);
2847 /// Add a field in another module
2849 /// <param name="name">field name</param>
2850 /// <param name="fType">field type</param>
2851 /// <returns>a descriptor for this field in another module</returns>
2852 public FieldRef AddField(string name, Type fType)
2854 FieldRef field = new FieldRef(this,name,fType);
2855 metaData.AddToTable(MDTable.MemberRef,field);
2859 internal sealed override uint Size(MetaData md)
2861 return md.StringsIndexSize();
2864 internal sealed override void Write(FileImage output)
2866 output.StringsIndex(nameIx);
2869 internal sealed override uint GetCodedIx(CIx code)
2872 case (CIx.HasCustomAttr) : return 12;
2873 case (CIx.MemberRefParent) : return 2;
2874 case (CIx.ResolutionScope) : return 1;
2881 #region Classes for Constants
2883 /// Descriptor for a constant value
2885 public abstract class Constant {
2886 protected uint size = 0;
2887 protected Type type;
2888 protected uint blobIndex;
2889 protected bool addedToBlobHeap = false;
2891 internal Constant() { }
2893 internal virtual uint GetBlobIndex(MetaData md) { return 0; }
2895 internal uint GetSize() { return size; }
2897 internal byte GetTypeIndex() { return type.GetTypeIndex(); }
2899 internal virtual void Write(BinaryWriter bw) { }
2903 /// Descriptor for a constant value
2905 public abstract class DataConstant : Constant {
2906 private uint dataOffset = 0;
2908 internal DataConstant() { }
2910 public uint DataOffset {
2911 get { return dataOffset; }
2912 set { dataOffset = value; }
2918 /// Boolean constant
2920 public class BoolConst : Constant {
2924 /// Create a new boolean constant with the value "val"
2926 /// <param name="val">value of this boolean constant</param>
2927 public BoolConst(bool val)
2931 type = PrimitiveType.Boolean;
2934 internal sealed override uint GetBlobIndex(MetaData md)
2936 if (!addedToBlobHeap) {
2937 if (val) blobIndex = md.AddToBlobHeap((sbyte)1);
2938 else blobIndex = md.AddToBlobHeap((sbyte)0);
2939 addedToBlobHeap = true;
2944 internal sealed override void Write(BinaryWriter bw)
2946 if (val) bw.Write((sbyte)1);
2947 else bw.Write((sbyte)0);
2952 public class ByteArrConst : DataConstant {
2955 public ByteArrConst(byte[] val)
2957 type = PrimitiveType.String;
2959 size = (uint)val.Length;
2963 get { return type; }
2964 set { type = value; }
2967 internal sealed override uint GetBlobIndex(MetaData md)
2969 if (!addedToBlobHeap) {
2970 blobIndex = md.AddToBlobHeap(val);
2971 addedToBlobHeap = true;
2976 internal sealed override void Write(BinaryWriter bw)
2983 public class CharConst : Constant {
2986 public CharConst(char val)
2990 type = PrimitiveType.Char;
2993 internal sealed override uint GetBlobIndex(MetaData md)
2995 if (!addedToBlobHeap) {
2996 blobIndex = md.AddToBlobHeap(val);
2997 addedToBlobHeap = true;
3002 internal sealed override void Write(BinaryWriter bw)
3009 public class FloatConst : DataConstant {
3012 public FloatConst(float val)
3016 type = PrimitiveType.Float32;
3019 internal sealed override uint GetBlobIndex(MetaData md)
3021 if (!addedToBlobHeap) {
3022 blobIndex = md.AddToBlobHeap(val);
3023 addedToBlobHeap = true;
3028 internal sealed override void Write(BinaryWriter bw)
3035 public class DoubleConst : DataConstant {
3038 public DoubleConst(double val)
3042 type = PrimitiveType.Float64;
3045 internal sealed override uint GetBlobIndex(MetaData md)
3047 if (!addedToBlobHeap) {
3048 blobIndex = md.AddToBlobHeap(val);
3049 addedToBlobHeap = true;
3054 internal sealed override void Write(BinaryWriter bw)
3061 public class IntConst : DataConstant {
3064 public IntConst(sbyte val)
3068 type = PrimitiveType.Int8;
3071 public IntConst(short val)
3075 type = PrimitiveType.Int16;
3078 public IntConst(int val)
3082 type = PrimitiveType.Int32;
3085 public IntConst(long val)
3089 type = PrimitiveType.Int64;
3092 internal sealed override uint GetBlobIndex(MetaData md)
3094 if (!addedToBlobHeap) {
3096 case (1) : blobIndex = md.AddToBlobHeap((sbyte)val); break;
3097 case (2) : blobIndex = md.AddToBlobHeap((short)val); break;
3098 case (4) : blobIndex = md.AddToBlobHeap((int)val); break;
3099 default : blobIndex = md.AddToBlobHeap(val); break;
3101 addedToBlobHeap = true;
3106 internal sealed override void Write(BinaryWriter bw)
3109 case (1) : bw.Write((sbyte)val); break;
3110 case (2) : bw.Write((short)val); break;
3111 case (4) : bw.Write((int)val); break;
3112 default : bw.Write(val); break;
3118 public class UIntConst : Constant {
3121 public UIntConst(byte val)
3125 type = PrimitiveType.UInt8;
3127 public UIntConst(ushort val)
3131 type = PrimitiveType.UInt16;
3133 public UIntConst(uint val)
3137 type = PrimitiveType.UInt32;
3139 public UIntConst(ulong val)
3143 type = PrimitiveType.UInt64;
3146 internal sealed override uint GetBlobIndex(MetaData md)
3148 if (!addedToBlobHeap) {
3150 case (1) : blobIndex = md.AddToBlobHeap((byte)val); break;
3151 case (2) : blobIndex = md.AddToBlobHeap((ushort)val); break;
3152 case (4) : blobIndex = md.AddToBlobHeap((uint)val); break;
3153 default : blobIndex = md.AddToBlobHeap(val); break;
3155 addedToBlobHeap = true;
3160 internal sealed override void Write(BinaryWriter bw)
3163 case (1) : bw.Write((byte)val); break;
3164 case (2) : bw.Write((ushort)val); break;
3165 case (4) : bw.Write((uint)val); break;
3166 default : bw.Write(val); break;
3172 public class StringConst : DataConstant {
3175 public StringConst(string val)
3178 size = (uint)val.Length; // need to add null ??
3179 type = PrimitiveType.String;
3182 internal sealed override uint GetBlobIndex(MetaData md)
3184 if (!addedToBlobHeap) {
3185 byte [] b = Encoding.Unicode.GetBytes (val);
3186 blobIndex = md.AddToBlobHeap(b);
3187 addedToBlobHeap = true;
3192 internal sealed override void Write(BinaryWriter bw)
3199 public class NullConst : Constant {
3204 type = PrimitiveType.Class;
3207 internal sealed override uint GetBlobIndex(MetaData md)
3209 if (!addedToBlobHeap) {
3210 blobIndex = md.AddToBlobHeap((int)0);
3211 addedToBlobHeap = true;
3216 internal sealed override void Write(BinaryWriter bw)
3223 public class AddressConstant : DataConstant {
3226 public AddressConstant(DataConstant dConst)
3230 type = PrimitiveType.TypedRef;
3233 internal sealed override void Write(BinaryWriter bw)
3235 ((FileImage)bw).WriteDataRVA(data.DataOffset);
3240 public class RepeatedConstant : DataConstant {
3244 public RepeatedConstant(DataConstant dConst, int repeatCount)
3247 repCount = (uint)repeatCount;
3248 int[] sizes = new int[1];
3249 sizes[0] = repeatCount;
3250 type = new BoundArray(type,1,sizes);
3251 size = data.GetSize() * repCount;
3254 internal sealed override void Write(BinaryWriter bw)
3256 for (int i=0; i < repCount; i++) {
3263 public class ArrayConstant : DataConstant {
3264 DataConstant[] dataVals;
3266 public ArrayConstant(DataConstant[] dVals)
3269 for (int i=0; i < dataVals.Length; i++) {
3270 size += dataVals[i].GetSize();
3274 internal sealed override void Write(BinaryWriter bw)
3276 for (int i=0; i < dataVals.Length; i++) {
3277 dataVals[i].Write(bw);
3283 public class ClassType : Constant {
3287 public ClassType(string className)
3290 type = PrimitiveType.ClassType;
3293 public ClassType(Class classDesc)
3296 type = PrimitiveType.ClassType;
3299 internal override void Write(BinaryWriter bw)
3301 if (name == null) name = desc.TypeName();
3309 /**************************************************************************/
3311 /// Descriptor for a custom modifier of a type (modopt or modreq)
3314 public class CustomModifiedType : Type {
3320 /// Create a new custom modifier for a type
3322 /// <param name="type">the type to be modified</param>
3323 /// <param name="cmod">the modifier</param>
3324 /// <param name="cmodType">the type reference to be associated with the type</param>
3325 public CustomModifiedType(Type type, CustomModifier cmod, Class cmodType)
3329 this.cmodType = cmodType;
3332 internal sealed override void TypeSig(MemoryStream str)
3334 str.WriteByte(typeIndex);
3335 MetaData.CompressNum(cmodType.TypeDefOrRefToken(),str);
3341 /**************************************************************************/
3343 /// Base class for Event and Property descriptors
3346 public class Feature : MetaDataElement {
3348 internal enum MethodType : ushort { Setter = 0x01, Getter, Other = 0x04, AddOn = 0x08,
3349 RemoveOn = 0x10, Fire = 0x20 }
3351 private static readonly int INITSIZE = 5;
3352 private static readonly ushort specialName = 0x200;
3353 private static readonly ushort rtSpecialName = 0x400;
3355 protected ClassDef parent;
3356 protected ushort flags = 0;
3357 protected string name;
3358 protected int tide = 0;
3359 protected uint nameIx;
3360 protected MethodSemantics[] methods = new MethodSemantics[INITSIZE];
3362 internal Feature(string name, ClassDef par)
3368 internal void AddMethod(MethodDef meth, MethodType mType)
3370 if (tide >= methods.Length) {
3371 int len = methods.Length;
3372 MethodSemantics[] mTmp = methods;
3373 methods = new MethodSemantics[len * 2];
3374 for (int i=0; i < len; i++) {
3375 methods[i] = mTmp[i];
3378 methods[tide++] = new MethodSemantics(mType,meth,this);
3382 /// Set the specialName attribute for this Event or Property
3384 public void SetSpecialName()
3386 flags |= specialName;
3390 /// Set the RTSpecialName attribute for this Event or Property
3392 public void SetRTSpecialName()
3394 flags |= rtSpecialName;
3399 /**************************************************************************/
3401 /// Descriptor for an event
3403 public class Event : Feature {
3407 internal Event(string name, Type eType, ClassDef parent)
3408 : base(name, parent)
3411 tabIx = MDTable.Event;
3415 /// Add the addon method to this event
3417 /// <param name="addon">the addon method</param>
3418 public void AddAddon(MethodDef addon)
3420 AddMethod(addon,MethodType.AddOn);
3424 /// Add the removeon method to this event
3426 /// <param name="removeOn">the removeon method</param>
3427 public void AddRemoveOn(MethodDef removeOn)
3429 AddMethod(removeOn,MethodType.RemoveOn);
3433 /// Add the fire method to this event
3435 /// <param name="fire">the fire method</param>
3436 public void AddFire(MethodDef fire)
3438 AddMethod(fire,MethodType.Fire);
3442 /// Add another method to this event
3444 /// <param name="other">the method to be added</param>
3445 public void AddOther(MethodDef other)
3447 AddMethod(other,MethodType.Other);
3450 internal sealed override void BuildTables(MetaData md)
3453 nameIx = md.AddToStringsHeap(name);
3454 for (int i=0; i < tide; i++) {
3455 md.AddToTable(MDTable.MethodSemantics,methods[i]);
3460 internal sealed override uint Size(MetaData md)
3462 return 2 + md.StringsIndexSize() + md.CodedIndexSize(CIx.TypeDefOrRef);
3465 internal sealed override void Write(FileImage output)
3467 output.Write(flags);
3468 output.StringsIndex(nameIx);
3469 output.WriteCodedIndex(CIx.TypeDefOrRef,eventType);
3472 internal sealed override uint GetCodedIx(CIx code)
3475 case (CIx.HasCustomAttr) : return 10;
3476 case (CIx.HasSemantics) : return 0;
3483 /**************************************************************************/
3485 /// Descriptor for the Property of a class
3487 public class Property : Feature {
3489 private static readonly byte PropertyTag = 0x8;
3490 private bool instance;
3491 MethodDef getterMeth;
3492 ConstantElem constVal;
3493 uint typeBlobIx = 0;
3498 internal Property(string name, Type retType, Type[] pars, ClassDef parent) : base(name, parent)
3500 returnType = retType;
3502 if (pars != null) numPars = (uint)pars.Length;
3503 tabIx = MDTable.Property;
3507 /// Add a set method to this property
3509 /// <param name="setter">the set method</param>
3510 public void AddSetter(MethodDef setter)
3512 AddMethod(setter,MethodType.Setter);
3516 /// Add a get method to this property
3518 /// <param name="getter">the get method</param>
3519 public void AddGetter(MethodDef getter)
3521 AddMethod(getter,MethodType.Getter);
3522 getterMeth = getter;
3526 /// Add another method to this property
3528 /// <param name="other">the method</param>
3529 public void AddOther(MethodDef other)
3531 AddMethod(other,MethodType.Other);
3535 /// Add an initial value for this property
3537 /// <param name="constVal">the initial value for this property</param>
3538 public void AddInitValue(Constant constVal)
3540 this.constVal = new ConstantElem(this,constVal);
3543 public void SetInstance (bool isInstance)
3545 this.instance = isInstance;
3548 internal sealed override void BuildTables(MetaData md)
3551 nameIx = md.AddToStringsHeap(name);
3552 MemoryStream sig = new MemoryStream();
3553 byte tag = PropertyTag;
3557 MetaData.CompressNum(numPars,sig);
3558 returnType.TypeSig(sig);
3559 for (int i=0; i < numPars; i++) {
3560 parList[i].TypeSig(sig);
3562 typeBlobIx = md.AddToBlobHeap(sig.ToArray());
3563 for (int i=0; i < tide; i++) {
3564 md.AddToTable(MDTable.MethodSemantics,methods[i]);
3566 if (constVal != null) {
3567 md.AddToTable(MDTable.Constant,constVal);
3568 constVal.BuildTables(md);
3573 internal sealed override uint Size(MetaData md)
3575 return 2 + md.StringsIndexSize() + md.BlobIndexSize();
3578 internal sealed override void Write(FileImage output)
3580 output.Write(flags);
3581 output.StringsIndex(nameIx);
3582 output.BlobIndex(typeBlobIx);
3585 internal sealed override uint GetCodedIx(CIx code)
3588 case (CIx.HasCustomAttr) : return 9;
3589 case (CIx.HasConst) : return 2;
3590 case (CIx.HasSemantics) : return 1;
3597 /**************************************************************************/
3599 /// Base class for field/methods (member of a class)
3601 public abstract class Member : MetaDataElement {
3603 protected string name;
3604 protected uint nameIx = 0, sigIx = 0;
3606 internal Member(string memName)
3609 tabIx = MDTable.MemberRef;
3614 /*****************************************************************************/
3616 /// Descriptor for a field of a class
3619 public abstract class Field : Member {
3621 protected static readonly byte FieldSig = 0x6;
3623 protected Type type;
3625 internal Field(string pfName, Type pfType) : base(pfName)
3631 /**************************************************************************/
3633 /// Descriptor for a field defined in a class of THIS assembly/module
3635 public class FieldDef : Field {
3637 //private static readonly uint PInvokeImpl = 0x2000;
3638 private static readonly ushort HasFieldRVA = 0x100;
3639 private static readonly ushort HasDefault = 0x8000;
3642 ConstantElem constVal;
3644 FieldMarshal marshalInfo;
3647 internal FieldDef(string name, Type fType) : base(name,fType)
3649 tabIx = MDTable.Field;
3652 internal FieldDef(FieldAttr attrSet, string name, Type fType) : base(name, fType)
3654 flags = (ushort)attrSet;
3655 tabIx = MDTable.Field;
3659 /// Add an attribute(s) to this field
3661 /// <param name="fa">the attribute(s) to be added</param>
3662 public void AddFieldAttr(FieldAttr fa)
3664 flags |= (ushort)fa;
3668 /// Add a value for this field
3670 /// <param name="val">the value for the field</param>
3671 public void AddValue(Constant val)
3673 constVal = new ConstantElem(this,val);
3674 flags |= HasDefault;
3678 /// Add an initial value for this field (at dataLabel) (.data)
3680 /// <param name="val">the value for the field</param>
3681 /// <param name="repeatVal">the number of repetitions of this value</param>
3682 public void AddDataValue(DataConstant val)
3684 flags |= HasFieldRVA;
3685 rva = new FieldRVA(this,val);
3689 /// Set the offset of the field. Used for sequential or explicit classes.
3692 /// <param name="offs">field offset</param>
3693 public void SetOffset(uint offs)
3695 layout = new FieldLayout(this,offs);
3699 /// Set the marshalling info for a field
3701 /// <param name="mInf"></param>
3702 public void SetMarshalInfo(NativeType marshallType)
3704 flags |= (ushort) FieldAttr.HasFieldMarshal;
3705 marshalInfo = new FieldMarshal(this,marshallType);
3708 internal sealed override void BuildTables(MetaData md)
3711 nameIx = md.AddToStringsHeap(name);
3712 MemoryStream sig = new MemoryStream();
3713 sig.WriteByte(FieldSig);
3715 sigIx = md.AddToBlobHeap(sig.ToArray());
3717 md.AddToTable(MDTable.FieldRVA,rva);
3718 rva.BuildTables(md);
3719 } else if (constVal != null) {
3720 md.AddToTable(MDTable.Constant,constVal);
3721 constVal.BuildTables(md);
3723 if (layout != null) md.AddToTable(MDTable.FieldLayout,layout);
3724 if (marshalInfo != null) {
3725 md.AddToTable(MDTable.FieldMarshal,marshalInfo);
3726 marshalInfo.BuildTables(md);
3731 internal sealed override uint Size(MetaData md)
3733 return 2 + md.StringsIndexSize() + md.BlobIndexSize();
3736 internal sealed override void Write(FileImage output)
3738 output.Write(flags);
3739 output.StringsIndex(nameIx);
3740 output.BlobIndex(sigIx);
3743 internal sealed override uint GetCodedIx(CIx code)
3746 case (CIx.HasConst) : return 0;
3747 case (CIx.HasCustomAttr) : return 1;
3748 case (CIx.HasFieldMarshal) : return 0;
3749 case (CIx.MemberForwarded) : return 0;
3756 /**************************************************************************/
3758 /// Descriptor for a field of a class defined in another assembly/module
3760 public class FieldRef : Field {
3762 MetaDataElement parent;
3764 internal FieldRef(MetaDataElement paren, string name, Type fType) : base(name, fType)
3769 internal sealed override void BuildTables(MetaData md)
3772 nameIx = md.AddToStringsHeap(name);
3773 MemoryStream sig = new MemoryStream();
3774 sig.WriteByte(FieldSig);
3776 sigIx = md.AddToBlobHeap(sig.ToArray());
3780 internal sealed override uint Size(MetaData md)
3782 return md.CodedIndexSize(CIx.MemberRefParent) + md.StringsIndexSize() + md.BlobIndexSize();
3785 internal sealed override void Write(FileImage output)
3787 output.WriteCodedIndex(CIx.MemberRefParent,parent);
3788 output.StringsIndex(nameIx);
3789 output.BlobIndex(sigIx);
3792 internal sealed override uint GetCodedIx(CIx code) { return 6; }
3796 /**************************************************************************/
3798 /// Base class for Method Descriptors
3801 public abstract class Method : Member {
3803 internal Method (string methName) : base (methName)
3806 public abstract void AddCallConv(CallConv cconv);
3807 internal abstract void TypeSig(MemoryStream sig);
3808 internal abstract uint GetSigIx(MetaData md);
3811 /**************************************************************************/
3813 /// Descriptor for a method defined in THIS assembly/module
3817 public class MethodDef : Method {
3819 private static readonly ushort PInvokeImpl = 0x2000;
3820 //private static readonly uint UnmanagedExport = 0x0008;
3821 // private static readonly byte LocalSigByte = 0x7;
3822 uint parIx = 0, textOffset = 0;
3823 private CallConv callConv = CallConv.Default;
3824 private int gen_param_count;
3827 CILInstructions code;
3828 ArrayList securityActions = new ArrayList();
3832 ushort methFlags = 0, implFlags = 0;
3833 int maxStack = 0, numPars = 0;
3834 bool entryPoint = false;
3836 ArrayList varArgSigList;
3837 ImplMap pinvokeImpl;
3840 internal MethodDef (MetaData md, string name, Param ret_param, Param [] pars)
3841 : this (md, 0, 0, name, ret_param, pars)
3845 internal MethodDef (MetaData md, MethAttr mAttrSet, ImplAttr iAttrSet, string name,
3846 Param ret_param, Param [] pars)
3849 methFlags = (ushort)mAttrSet;
3850 implFlags = (ushort)iAttrSet;
3851 this.ret_param = ret_param;
3854 if (parList != null)
3855 numPars = parList.Length;
3856 tabIx = MDTable.Method;
3859 internal Param[] GetPars()
3864 internal override uint GetSigIx(MetaData md)
3866 MemoryStream sig = new MemoryStream();
3868 return md.AddToBlobHeap(sig.ToArray());
3871 public override void AddCallConv(CallConv cconv)
3877 /// Add some attributes to this method descriptor
3879 /// <param name="ma">the attributes to be added</param>
3880 public void AddMethAttribute(MethAttr ma)
3882 methFlags |= (ushort)ma;
3886 /// Add some implementation attributes to this method descriptor
3888 /// <param name="ia">the attributes to be added</param>
3889 public void AddImplAttribute(ImplAttr ia)
3891 implFlags |= (ushort)ia;
3894 public void AddPInvokeInfo(ModuleRef scope, string methName,
3895 PInvokeAttr callAttr) {
3896 pinvokeImpl = new ImplMap((ushort)callAttr,this,methName,scope);
3897 methFlags |= PInvokeImpl;
3901 /// Add a named generic type parameter
3903 public GenericParameter AddGenericParameter (short index, string name)
3905 return AddGenericParameter (index, name, 0);
3909 /// Add a named generic type parameter with attributes
3911 public GenericParameter AddGenericParameter (short index, string name, GenericParamAttributes attr)
3913 GenericParameter gp = new GenericParameter (this, metaData, index, name, attr);
3914 metaData.AddToTable (MDTable.GenericParam, gp);
3920 /// Set the maximum stack height for this method
3922 /// <param name="maxStack">the maximum height of the stack</param>
3923 public void SetMaxStack(int maxStack)
3925 this.maxStack = maxStack;
3929 /// Add local variables to this method
3931 /// <param name="locals">the locals to be added</param>
3932 /// <param name="initLocals">are locals initialised to default values</param>
3933 public void AddLocals(Local[] locals, bool initLocals)
3935 this.locals = locals;
3936 this.initLocals = initLocals;
3939 /* Add Marshal info for return type */
3940 public void AddRetTypeMarshallInfo (NativeType marshallType)
3942 ret_param.AddMarshallInfo (marshallType);
3946 /// Mark this method as having an entry point
3948 public void DeclareEntryPoint()
3954 /// Create a code buffer for this method to add the IL instructions to
3956 /// <returns>a buffer for this method's IL instructions</returns>
3957 public CILInstructions CreateCodeBuffer()
3959 code = new CILInstructions(metaData);
3964 /// Make a method reference descriptor for this method to be used
3965 /// as a callsite signature for this vararg method
3967 /// <param name="optPars">the optional pars for the vararg method call</param>
3968 /// <returns></returns>
3969 public MethodRef MakeVarArgSignature(Type[] optPars)
3971 Type[] pars = new Type[numPars];
3972 MethodRef varArgSig;
3973 for (int i=0; i < numPars; i++) {
3974 pars[i] = parList[i].GetParType();
3976 varArgSig = new MethodRef (this, name, ret_param.GetParType (), pars, true, optPars, 0);
3978 if (varArgSigList == null)
3979 varArgSigList = new ArrayList ();
3980 varArgSigList.Add (varArgSig);
3984 internal sealed override void TypeSig(MemoryStream sig)
3986 sig.WriteByte((byte)callConv);
3987 if ((callConv & CallConv.Generic) == CallConv.Generic)
3988 MetaData.CompressNum ((uint) gen_param_count, sig);
3989 MetaData.CompressNum((uint)numPars,sig);
3991 ret_param.seqNo = 0;
3992 ret_param.TypeSig (sig);
3993 for (ushort i=0; i < numPars; i++) {
3994 parList[i].seqNo = (ushort)(i+1);
3995 parList[i].TypeSig(sig);
3999 internal sealed override void BuildTables(MetaData md)
4002 if (pinvokeImpl != null) {
4003 md.AddToTable(MDTable.ImplMap,pinvokeImpl);
4004 pinvokeImpl.BuildTables(md);
4006 if (entryPoint) md.SetEntryPoint(this);
4008 if (locals != null) {
4009 localSig = new LocalSig(locals);
4010 md.AddToTable(MDTable.StandAloneSig,localSig);
4011 localSig.BuildTables(md);
4012 locToken = localSig.Token();
4015 code.CheckCode(locToken,initLocals,maxStack);
4016 textOffset = md.AddCode(code);
4018 nameIx = md.AddToStringsHeap(name);
4019 sigIx = GetSigIx(md);
4020 parIx = md.TableIndex(MDTable.Param);
4021 if (ret_param.HasMarshalInfo || ret_param.HasCustomAttr) {
4022 md.AddToTable(MDTable.Param, ret_param);
4023 ret_param.BuildTables(md);
4025 for (int i=0; i < numPars; i++) {
4026 md.AddToTable(MDTable.Param,parList[i]);
4027 parList[i].BuildTables(md);
4029 if (varArgSigList != null) {
4030 foreach (MethodRef varArgSig in varArgSigList) {
4031 md.AddToTable(MDTable.MemberRef,varArgSig);
4032 varArgSig.BuildTables(md);
4035 // Console.WriteLine("method has " + numPars + " parameters");
4039 internal sealed override uint Size(MetaData md)
4041 return 8 + md.StringsIndexSize() + md.BlobIndexSize() + md.TableIndexSize(MDTable.Param);
4044 internal sealed override void Write(FileImage output)
4046 if (ZeroRva ()) output.Write(0);
4047 else output.WriteCodeRVA(textOffset);
4048 output.Write(implFlags);
4049 output.Write(methFlags);
4050 output.StringsIndex(nameIx);
4051 output.BlobIndex(sigIx);
4052 output.WriteIndex(MDTable.Param,parIx);
4055 internal bool ZeroRva ()
4057 return (((methFlags & (ushort)MethAttr.Abstract) != 0) ||
4058 ((implFlags & (ushort)ImplAttr.Runtime) != 0) ||
4059 ((implFlags & (ushort)ImplAttr.InternalCall) != 0) ||
4060 (pinvokeImpl != null)); // TODO: Not entirely true but works for now
4063 internal sealed override uint GetCodedIx(CIx code)
4066 case (CIx.HasCustomAttr) : return 0;
4067 case (CIx.HasDeclSecurity) : return 1;
4068 case (CIx.MemberRefParent) : return 3;
4069 case (CIx.MethodDefOrRef) : return 0;
4070 case (CIx.MemberForwarded) : return 1;
4071 case (CIx.CustomAttributeType) : return 2;
4072 case (CIx.TypeOrMethodDef) : return 1;
4078 /**************************************************************************/
4080 /// Descriptor for a method defined in another assembly/module
4082 public class MethodRef : Method {
4084 private static readonly byte Sentinel = 0x41;
4085 Type[] parList, optParList;
4086 MetaDataElement parent;
4087 uint numPars = 0, numOptPars = 0;
4088 CallConv callConv = CallConv.Default;
4090 int gen_param_count;
4092 internal MethodRef(MetaDataElement paren, string name, Type retType,
4093 Type[] pars, bool varArgMeth, Type[] optPars, int gen_param_count) : base(name)
4097 this.retType = retType;
4098 if (parList != null) numPars = (uint)parList.Length;
4100 optParList = optPars;
4101 if (optParList != null) numOptPars = (uint)optParList.Length;
4102 callConv = CallConv.Vararg;
4104 this.gen_param_count = gen_param_count;
4107 internal override uint GetSigIx(MetaData md)
4109 MemoryStream sig = new MemoryStream();
4111 return md.AddToBlobHeap(sig.ToArray());
4114 public override void AddCallConv(CallConv cconv)
4119 internal sealed override void TypeSig(MemoryStream sig)
4121 sig.WriteByte((byte)callConv);
4122 if ((callConv & CallConv.Generic) == CallConv.Generic)
4123 MetaData.CompressNum ((uint) gen_param_count, sig);
4124 MetaData.CompressNum(numPars+numOptPars,sig);
4125 retType.TypeSig(sig);
4126 for (int i=0; i < numPars; i++) {
4127 parList[i].TypeSig(sig);
4129 if (numOptPars > 0) {
4130 sig.WriteByte(Sentinel);
4131 for (int i=0; i < numOptPars; i++) {
4132 optParList[i].TypeSig(sig);
4137 internal sealed override void BuildTables(MetaData md)
4140 nameIx = md.AddToStringsHeap(name);
4141 sigIx = GetSigIx(md);
4145 internal sealed override uint Size(MetaData md)
4147 return md.CodedIndexSize(CIx.MemberRefParent) + md.StringsIndexSize() + md.BlobIndexSize();
4150 internal sealed override void Write(FileImage output)
4152 output.WriteCodedIndex(CIx.MemberRefParent,parent);
4153 output.StringsIndex(nameIx);
4154 output.BlobIndex(sigIx);
4157 internal sealed override uint GetCodedIx(CIx code)
4160 case (CIx.HasCustomAttr) : return 6;
4161 case (CIx.MethodDefOrRef) : return 1;
4162 case (CIx.CustomAttributeType) : return 3;
4170 /**************************************************************************/
4172 /// Descriptors for native types used for marshalling
4174 public class NativeType {
4175 public static readonly NativeType Void = new NativeType(0x01);
4176 public static readonly NativeType Boolean = new NativeType(0x02);
4177 public static readonly NativeType Int8 = new NativeType(0x03);
4178 public static readonly NativeType UInt8 = new NativeType(0x04);
4179 public static readonly NativeType Int16 = new NativeType(0x05);
4180 public static readonly NativeType UInt16 = new NativeType(0x06);
4181 public static readonly NativeType Int32 = new NativeType(0x07);
4182 public static readonly NativeType UInt32 = new NativeType(0x08);
4183 public static readonly NativeType Int64 = new NativeType(0x09);
4184 public static readonly NativeType UInt64 = new NativeType(0x0A);
4185 public static readonly NativeType Float32 = new NativeType(0x0B);
4186 public static readonly NativeType Float64 = new NativeType(0x0C);
4187 public static readonly NativeType Currency = new NativeType(0x0F);
4188 public static readonly NativeType BStr = new NativeType(0x13);
4189 public static readonly NativeType LPStr = new NativeType(0x14);
4190 public static readonly NativeType LPWStr = new NativeType(0x15);
4191 public static readonly NativeType LPTStr = new NativeType(0x16);
4192 public static readonly NativeType FixedSysString = new NativeType(0x17);
4193 public static readonly NativeType IUnknown = new NativeType(0x19);
4194 public static readonly NativeType IDispatch = new NativeType(0x1A);
4195 public static readonly NativeType Struct = new NativeType(0x1B);
4196 public static readonly NativeType Interface = new NativeType(0x1C);
4197 public static readonly NativeType Int = new NativeType(0x1F);
4198 public static readonly NativeType UInt = new NativeType(0x20);
4199 public static readonly NativeType ByValStr = new NativeType(0x22);
4200 public static readonly NativeType AnsiBStr = new NativeType(0x23);
4201 public static readonly NativeType TBstr = new NativeType(0x24);
4202 public static readonly NativeType VariantBool = new NativeType(0x25);
4203 public static readonly NativeType FuncPtr = new NativeType(0x26);
4204 public static readonly NativeType AsAny = new NativeType(0x28);
4205 public static readonly NativeType LPStruct = new NativeType(0x2b);
4206 public static readonly NativeType Error = new NativeType(0x2d);
4208 protected byte typeIndex;
4210 internal NativeType(byte tyIx) { typeIndex = tyIx; }
4211 internal byte GetTypeIndex() { return typeIndex; }
4213 internal virtual byte[] ToBlob()
4215 byte[] bytes = new byte[1];
4216 bytes[0] = GetTypeIndex();
4222 public class FixedSysString : NativeType {
4226 public FixedSysString (uint size) : base (NativeType.FixedSysString.GetTypeIndex ())
4231 internal override byte [] ToBlob ()
4233 MemoryStream str = new MemoryStream ();
4234 str.WriteByte (GetTypeIndex ());
4235 MetaData.CompressNum (size, str);
4236 return str.ToArray ();
4241 public class NativeArray : NativeType {
4243 NativeType elemType;
4244 int numElem = -1, parNum = -1, elemMult = -1;
4246 public NativeArray(NativeType elemType) : this (elemType, -1, -1, -1)
4248 this.elemType = elemType;
4251 /* public NativeArray(NativeType elemType, int len) : base(0x2A) {
4252 this.elemType = elemType;
4257 public NativeArray(NativeType elemType, int numElem, int parNumForLen, int elemMult) : base(0x2A)
4259 this.elemType = elemType;
4260 this.numElem = numElem;
4261 parNum = parNumForLen;
4262 this.elemMult = elemMult;
4265 public NativeArray(NativeType elemType, int numElem, int parNumForLen)
4266 : this (elemType, numElem, parNumForLen, -1)
4270 internal override byte[] ToBlob()
4272 MemoryStream str = new MemoryStream();
4273 str.WriteByte(GetTypeIndex());
4274 if (elemType == null) str.WriteByte(0x50); // no info (MAX)
4275 else str.WriteByte(elemType.GetTypeIndex());
4277 /* see : mono/metadata/metadata.c:mono_metadata_parse_marshal_spec
4278 * LAMESPEC: Older spec versions say elemMult comes before
4279 * len. Newer spec versions don't talk about elemMult at
4280 * all, but csc still emits it, and it is used to distinguish
4281 * between parNum being 0, and parNum being omitted.
4286 return str.ToArray ();
4288 MetaData.CompressNum((uint) parNum,str);
4289 if (numElem != -1) {
4290 MetaData.CompressNum ((uint) numElem, str);
4292 // <native_type> [ int32 ]
4293 MetaData.CompressNum((uint) elemMult,str);
4294 //else <native_type> [ int32 + int32 ]
4295 } else if (elemMult != -1) {
4296 // When can this occur ?
4297 MetaData.CompressNum (0, str);
4298 MetaData.CompressNum((uint) elemMult,str);
4300 //else <native_type> [ + int32 ]
4302 return str.ToArray();
4307 public class SafeArray : NativeType {
4309 SafeArrayType elemType;
4312 public SafeArray() : base(0x1D)
4316 public SafeArray(SafeArrayType elemType) : base(0x1D)
4318 this.elemType = elemType;
4322 internal override byte[] ToBlob()
4324 byte[] bytes = new byte[hasElemType ? 2 : 1];
4325 bytes[0] = GetTypeIndex();
4327 bytes[1] = (byte)elemType;
4333 public class FixedArray : NativeType {
4335 NativeType elemType;
4338 //public FixedArray(NativeType elemType, int numElems) : base(0x1E) {
4339 public FixedArray(int numElems) : base(0x1E)
4341 //this.elemType = elemType;
4342 numElem = (uint)numElems;
4345 internal override byte[] ToBlob()
4347 MemoryStream str = new MemoryStream();
4348 str.WriteByte(GetTypeIndex());
4349 MetaData.CompressNum(numElem,str);
4351 fixed array [5] lpstr [2]
4352 This format is not supported by ilasm 1.1.4322.2032,
4353 but is supported by 2.0.5125..
4354 ilasm 1.1 only supports "fixed array [5]"
4355 if (elemType == null) str.WriteByte(0x50); // no info (MAX)
4356 else str.WriteByte(elemType.GetTypeIndex());*/
4358 return str.ToArray();
4363 public class CustomMarshaller : NativeType {
4366 string marshallerName;
4369 public CustomMarshaller(string typeNameOrGUID, string marshallerName,
4370 string optCookie) : base(0x2C)
4372 typeName = typeNameOrGUID;
4373 this.marshallerName = marshallerName;
4377 public CustomMarshaller(string marshallerName, string optCookie)
4378 :this (null, marshallerName, optCookie)
4382 internal override byte[] ToBlob()
4384 MemoryStream str = new MemoryStream();
4385 BinaryWriter bw = new BinaryWriter(str,new UTF8Encoding());
4386 bw.Write(GetTypeIndex());
4387 //Native type name & unmanaged type - unused
4388 //See mono/metadata/metadata.c : mono_metadata_parse_marshal_spec
4389 bw.Write ((byte) 0); // Native Type name, unused
4390 bw.Write ((byte) 0); // Unmanaged type, unused
4391 if (marshallerName != null) {
4392 MetaData.CompressNum ((uint)marshallerName.Length, str);
4393 bw.Write(marshallerName.ToCharArray());
4395 bw.Write ((byte) 0);
4397 if (cookie != null) {
4398 MetaData.CompressNum ((uint)cookie.Length, str);
4399 bw.Write(cookie.ToCharArray());
4401 bw.Write ((byte) 0);
4404 return str.ToArray();
4408 /**************************************************************************/
4410 /// Descriptor for the Primitive types defined in IL
4412 public class PrimitiveType : Type {
4414 private string name;
4415 private int systemTypeIndex;
4416 public static int NumSystemTypes = 18;
4418 public static readonly PrimitiveType Void = new PrimitiveType(0x01,"Void",0);
4419 public static readonly PrimitiveType Boolean = new PrimitiveType(0x02,"Boolean",1);
4420 public static readonly PrimitiveType Char = new PrimitiveType(0x03,"Char",2);
4421 public static readonly PrimitiveType Int8 = new PrimitiveType(0x04,"SByte",3);
4422 public static readonly PrimitiveType UInt8 = new PrimitiveType(0x05,"Byte",4);
4423 public static readonly PrimitiveType Int16 = new PrimitiveType(0x06,"Int16",5);
4424 public static readonly PrimitiveType UInt16 = new PrimitiveType(0x07,"UInt16",6);
4425 public static readonly PrimitiveType Int32 = new PrimitiveType(0x08,"Int32",7);
4426 public static readonly PrimitiveType UInt32 = new PrimitiveType(0x09,"UInt32",8);
4427 public static readonly PrimitiveType Int64 = new PrimitiveType(0x0A,"Int64",9);
4428 public static readonly PrimitiveType UInt64 = new PrimitiveType(0x0B,"UInt64",10);
4429 public static readonly PrimitiveType Float32 = new PrimitiveType(0x0C,"Single",11);
4430 public static readonly PrimitiveType Float64 = new PrimitiveType(0x0D,"Double",12);
4431 public static readonly PrimitiveType String = new PrimitiveType(0x0E,"String",13);
4432 internal static readonly PrimitiveType Class = new PrimitiveType(0x12);
4433 internal static readonly PrimitiveType Var = new PrimitiveType(0x13);
4434 internal static readonly PrimitiveType GenericInst = new PrimitiveType(0x15);
4435 public static readonly PrimitiveType TypedRef = new PrimitiveType(0x16,"TypedReference",14);
4436 public static readonly PrimitiveType IntPtr = new PrimitiveType(0x18,"IntPtr",15);
4437 public static readonly PrimitiveType UIntPtr = new PrimitiveType(0x19,"UIntPtr",16);
4438 public static readonly PrimitiveType Object = new PrimitiveType(0x1C,"Object",17);
4439 internal static readonly PrimitiveType ClassType = new PrimitiveType(0x50);
4440 internal static readonly PrimitiveType SZArray = new PrimitiveType(0x1D);
4441 internal static readonly PrimitiveType MVar = new PrimitiveType(0x1E);
4442 internal static readonly PrimitiveType ValueType = new PrimitiveType(0x11, "ValueType", 18);
4443 public static readonly PrimitiveType NativeInt = IntPtr;
4444 public static readonly PrimitiveType NativeUInt = UIntPtr;
4446 internal PrimitiveType(byte typeIx) : base(typeIx) { }
4448 internal PrimitiveType(byte typeIx, string name, int STIx) : base(typeIx)
4451 this.systemTypeIndex = STIx;
4454 internal string GetName() { return name; }
4456 internal int GetSystemTypeIx() { return systemTypeIndex; }
4458 internal sealed override void TypeSig(MemoryStream str)
4460 str.WriteByte(typeIndex);
4463 internal override MetaDataElement GetTypeSpec(MetaData md)
4465 TypeSpec tS = md.GetPrimitiveTypeSpec(systemTypeIndex);
4467 tS = new TypeSpec(this,md);
4468 md.SetPrimitiveTypeSpec(systemTypeIndex,tS);
4469 md.AddToTable(MDTable.TypeSpec,tS);
4476 /**************************************************************************/
4478 /// Descriptor for an pointer (type * or type &)
4480 public abstract class PtrType : Type {
4484 internal PtrType(Type bType, byte typeIx) : base(typeIx)
4487 tabIx = MDTable.TypeSpec;
4490 internal sealed override void TypeSig(MemoryStream str)
4492 str.WriteByte(typeIndex);
4493 baseType.TypeSig(str);
4497 /**************************************************************************/
4499 /// Descriptor for a managed pointer (type & or byref)
4502 public class ManagedPointer : PtrType {
4505 /// Create new managed pointer to baseType
4507 /// <param name="bType">the base type of the pointer</param>
4508 public ManagedPointer(Type baseType) : base(baseType,0x10) { }
4511 /**************************************************************************/
4513 /// Descriptor for an unmanaged pointer (type *)
4515 public class UnmanagedPointer : PtrType {
4518 /// Create a new unmanaged pointer to baseType
4520 /// <param name="baseType">the base type of the pointer</param>
4521 public UnmanagedPointer(Type baseType) : base(baseType, 0x0F) { }
4525 /**************************************************************************/
4527 public interface IExternRef {
4528 ClassRef AddClass(string nsName, string name);
4529 ClassRef AddValueClass(string nsName, string name);
4533 /// A reference to an external assembly (.assembly extern)
4535 public class AssemblyRef : ResolutionScope, IExternRef {
4537 private ushort major, minor, build, revision;
4538 uint flags, keyIx, hashIx, cultIx;
4539 bool hasVersion = false, isKeyToken = false;
4543 internal AssemblyRef(MetaData md, string name) : base(name,md)
4545 tabIx = MDTable.AssemblyRef;
4549 /// Add version information about this external assembly
4551 /// <param name="majVer">Major Version</param>
4552 /// <param name="minVer">Minor Version</param>
4553 /// <param name="bldNo">Build Number</param>
4554 /// <param name="revNo">Revision Number</param>
4555 public void AddVersionInfo(int majVer, int minVer, int bldNo, int revNo)
4557 major = (ushort)majVer;
4558 minor = (ushort)minVer;
4559 build = (ushort)bldNo;
4560 revision = (ushort)revNo;
4565 /// Add the hash value for this external assembly
4567 /// <param name="hash">bytes of the hash value</param>
4568 public void AddHash(byte[] hash)
4570 hashIx = metaData.AddToBlobHeap(hash);
4574 /// Set the culture for this external assembly
4576 /// <param name="cult">the culture string</param>
4577 public void AddCulture(string cult)
4579 cultIx = metaData.AddToStringsHeap(cult);
4584 /// Add the full public key for this external assembly
4586 /// <param name="key">bytes of the public key</param>
4587 public void AddKey(byte[] key)
4589 flags |= 0x0001; // full public key
4591 keyIx = metaData.AddToBlobHeap(key);
4595 /// Add the public key token (low 8 bytes of the public key)
4597 /// <param name="key">low 8 bytes of public key</param>
4598 public void AddKeyToken(byte[] key)
4600 keyIx = metaData.AddToBlobHeap(key);
4606 /// Add a class to this external assembly
4608 /// <param name="nsName">name space name</param>
4609 /// <param name="name">class name</param>
4610 /// <returns></returns>
4611 public virtual ClassRef AddClass(string nsName, string name)
4613 ClassRef aClass = new ClassRef(nsName,name,metaData);
4614 metaData.AddToTable(MDTable.TypeRef,aClass);
4615 aClass.SetParent(this);
4620 /// Add a value class to this external assembly
4622 /// <param name="nsName">name space name</param>
4623 /// <param name="name">class name</param>
4624 /// <returns></returns>
4625 public virtual ClassRef AddValueClass(string nsName, string name)
4627 ClassRef aClass = new ClassRef(nsName,name,metaData);
4628 metaData.AddToTable(MDTable.TypeRef,aClass);
4629 aClass.SetParent(this);
4630 aClass.MakeValueClass(ValueClass.ValueType);
4634 internal string TypeName()
4636 string result = name;
4638 result = result + ", Version=" + major + "." + minor + "." +
4639 build + "." + revision;
4640 if (keyBytes != null) {
4641 string tokenStr = "=";
4642 if (isKeyToken) tokenStr = "Token=";
4643 result = result + ", PublicKey" + tokenStr;
4644 for (int i=0; i < keyBytes.Length; i++) {
4645 result = result + Hex.Byte(keyBytes[i]);
4648 if (culture != null)
4649 result = result + ", Culture=" + culture;
4653 internal sealed override uint Size(MetaData md)
4655 return 12 + 2 * md.StringsIndexSize() + 2 * md.BlobIndexSize();
4658 internal sealed override void Write(FileImage output)
4660 output.Write(major);
4661 output.Write(minor);
4662 output.Write(build);
4663 output.Write(revision);
4664 output.Write(flags);
4665 output.BlobIndex(keyIx);
4666 output.StringsIndex(nameIx);
4667 output.StringsIndex(cultIx);
4668 output.BlobIndex(hashIx);
4671 internal sealed override uint GetCodedIx(CIx code)
4674 case (CIx.ResolutionScope) : return 2;
4675 case (CIx.HasCustomAttr) : return 15;
4676 case (CIx.Implementation) : return 1;
4683 /**************************************************************************/
4685 /// Descriptor for a class defined in System (mscorlib)
4687 internal class SystemClass : ClassRef {
4689 PrimitiveType elemType;
4691 internal SystemClass(PrimitiveType eType, AssemblyRef paren, MetaData md)
4692 : base("System",eType.GetName(),md) {
4697 internal override sealed MetaDataElement GetTypeSpec(MetaData md)
4699 if (typeSpec == null) typeSpec = (TypeSpec)elemType.GetTypeSpec(md);
4704 internal sealed override void TypeSig(MemoryStream str)
4706 str.WriteByte(elemType.GetTypeIndex());
4711 /**************************************************************************/
4713 /// The assembly for mscorlib.
4715 public sealed class MSCorLib : AssemblyRef {
4717 private static readonly int valueTypeIx = 18;
4718 private readonly string systemName = "System";
4719 private Class[] systemClasses = new Class[valueTypeIx+2];
4720 private PrimitiveType[] systemTypes = new PrimitiveType[valueTypeIx];
4721 private TypeSpec[] specialTypeSpecs = new TypeSpec[valueTypeIx];
4722 private static int[] specialNames = {
4723 PrimitiveType.Void.GetName().GetHashCode(),
4724 PrimitiveType.Boolean.GetName().GetHashCode(),
4725 PrimitiveType.Char.GetName().GetHashCode(),
4726 PrimitiveType.Int8.GetName().GetHashCode(),
4727 PrimitiveType.UInt8.GetName().GetHashCode(),
4728 PrimitiveType.Int16.GetName().GetHashCode(),
4729 PrimitiveType.UInt16.GetName().GetHashCode(),
4730 PrimitiveType.Int32.GetName().GetHashCode(),
4731 PrimitiveType.UInt32.GetName().GetHashCode(),
4732 PrimitiveType.Int64.GetName().GetHashCode(),
4733 PrimitiveType.UInt64.GetName().GetHashCode(),
4734 PrimitiveType.Float32.GetName().GetHashCode(),
4735 PrimitiveType.Float64.GetName().GetHashCode(),
4736 PrimitiveType.String.GetName().GetHashCode(),
4737 PrimitiveType.TypedRef.GetName().GetHashCode(),
4738 PrimitiveType.IntPtr.GetName().GetHashCode(),
4739 PrimitiveType.UIntPtr.GetName().GetHashCode(),
4740 PrimitiveType.Object.GetName().GetHashCode(),
4741 PrimitiveType.ValueType.GetName ().GetHashCode(),
4742 "Enum".GetHashCode()
4745 internal MSCorLib(MetaData md) : base(md,"mscorlib")
4747 if (!PEFile.IsMSCorlib)
4748 md.AddToTable(MDTable.AssemblyRef,this);
4749 systemTypes[PrimitiveType.Void.GetSystemTypeIx()] = PrimitiveType.Void;
4750 systemTypes[PrimitiveType.Boolean.GetSystemTypeIx()] = PrimitiveType.Boolean;
4751 systemTypes[PrimitiveType.Char.GetSystemTypeIx()] = PrimitiveType.Char;
4752 systemTypes[PrimitiveType.Int8.GetSystemTypeIx()] = PrimitiveType.Int8;
4753 systemTypes[PrimitiveType.UInt8.GetSystemTypeIx()] = PrimitiveType.UInt8;
4754 systemTypes[PrimitiveType.Int16.GetSystemTypeIx()] = PrimitiveType.Int16;
4755 systemTypes[PrimitiveType.UInt16.GetSystemTypeIx()] = PrimitiveType.UInt16;
4756 systemTypes[PrimitiveType.Int32.GetSystemTypeIx()] = PrimitiveType.Int32;
4757 systemTypes[PrimitiveType.UInt32.GetSystemTypeIx()] = PrimitiveType.UInt32;
4758 systemTypes[PrimitiveType.Int64.GetSystemTypeIx()] = PrimitiveType.Int64;
4759 systemTypes[PrimitiveType.UInt64.GetSystemTypeIx()] = PrimitiveType.UInt64;
4760 systemTypes[PrimitiveType.Float32.GetSystemTypeIx()] = PrimitiveType.Float32;
4761 systemTypes[PrimitiveType.Float64.GetSystemTypeIx()] = PrimitiveType.Float64;
4762 systemTypes[PrimitiveType.IntPtr.GetSystemTypeIx()] = PrimitiveType.IntPtr;
4763 systemTypes[PrimitiveType.UIntPtr.GetSystemTypeIx()] = PrimitiveType.UIntPtr;
4764 systemTypes[PrimitiveType.String.GetSystemTypeIx()] = PrimitiveType.String;
4765 systemTypes[PrimitiveType.Object.GetSystemTypeIx()] = PrimitiveType.Object;
4766 systemTypes[PrimitiveType.TypedRef.GetSystemTypeIx()] = PrimitiveType.TypedRef;
4770 /// Add a class to the mscorlib assembly
4772 /// <param name="nsName">name space name</param>
4773 /// <param name="name">class name</param>
4774 /// <returns></returns>
4775 public override ClassRef AddClass(string nsName, string name)
4777 /* This gets called by !mscorlib, for adding references INTO mscorlib, so
4778 it should be returning ClassRef ..*/
4779 Class aClass = GetSpecialClass(nsName,name);
4780 if (aClass == null) {
4781 aClass = new ClassRef(nsName,name,metaData);
4782 metaData.AddToTable(MDTable.TypeRef,aClass);
4783 if (aClass is ClassRef)
4784 ((ClassRef) aClass).SetParent(this);
4786 //FIXME: Check for !ClassRef here?
4787 return (ClassRef) aClass;
4790 private Class GetSpecialClass(string nsName,string name)
4792 if (nsName.CompareTo(systemName) != 0) return null;
4793 int hash = name.GetHashCode();
4794 for (int i=0; i < specialNames.Length; i++) {
4795 if (hash != specialNames[i])
4797 if (systemClasses[i] == null) {
4798 if (i < valueTypeIx) {
4799 systemClasses[i] = new SystemClass(systemTypes[i],this,metaData);
4800 if ((systemTypes[i] != PrimitiveType.Object) &&
4801 (systemTypes[i] != PrimitiveType.String)) {
4802 systemClasses[i].MakeValueClass(ValueClass.ValueType);
4805 systemClasses[i] = new ClassRef(nsName,name,metaData);
4806 ((ClassRef) systemClasses[i]).SetParent(this);
4807 if (!ClassDef.IsValueType (nsName, name) && !ClassDef.IsEnum (nsName, name))
4808 systemClasses[i].MakeValueClass(ValueClass.ValueType);
4810 metaData.AddToTable(MDTable.TypeRef,systemClasses[i]);
4812 return systemClasses[i];
4817 internal void SetSpecialSystemClass (string nsName, string name, Class aClass)
4819 if (nsName != systemName) return;
4820 int hash = name.GetHashCode ();
4821 for (int i = 0; i < specialNames.Length; i++) {
4822 if (hash != specialNames [i])
4824 if (systemClasses [i] == null) {
4825 systemClasses [i] = aClass;
4830 internal Class GetSpecialSystemClass(PrimitiveType pType)
4832 int ix = pType.GetSystemTypeIx();
4833 if (systemClasses[ix] == null && !PEFile.IsMSCorlib) {
4834 systemClasses[ix] = new SystemClass(pType,this,metaData);
4835 metaData.AddToTable(MDTable.TypeRef,systemClasses[ix]);
4837 return systemClasses[ix];
4840 private ClassRef GetValueClass(string name, int hash)
4842 /* Called by MSCorLib.AddValueClass, which is called by
4843 !mscorlib, for adding ref to value class INTO mscorlib,
4844 so this should be classref */
4845 int ix = valueTypeIx;
4846 if (hash != specialNames[valueTypeIx]) ix++;
4847 if (systemClasses[ix] == null) {
4848 systemClasses[ix] = new ClassRef(systemName,name,metaData);
4849 ((ClassRef) systemClasses[ix]).SetParent(this);
4850 ((ClassRef) systemClasses[ix]).MakeValueClass(ValueClass.ValueType);
4851 metaData.AddToTable(MDTable.TypeRef,systemClasses[ix]);
4853 return (ClassRef) systemClasses[ix];
4856 internal Class ValueType()
4858 if (systemClasses[valueTypeIx] == null && !PEFile.IsMSCorlib) {
4859 ClassRef valType = new ClassRef("System","ValueType",metaData);
4860 valType.SetParent(this);
4861 valType.MakeValueClass(ValueClass.ValueType);
4862 metaData.AddToTable(MDTable.TypeRef,valType);
4863 systemClasses[valueTypeIx] = valType;
4865 return systemClasses[valueTypeIx];
4868 internal Class EnumType()
4870 /* Called by both mscorlib & !mscorlib, so can be
4871 either ClassRef or ClassDef */
4872 //systemClasses [ valueTypeIx + 1] -> System.Enum
4873 if (systemClasses[valueTypeIx + 1] == null && !PEFile.IsMSCorlib) {
4874 ClassRef valType = new ClassRef("System","Enum",metaData);
4875 valType.SetParent(this);
4876 valType.MakeValueClass(ValueClass.Enum);
4877 metaData.AddToTable(MDTable.TypeRef,valType);
4878 systemClasses[valueTypeIx + 1] = valType;
4880 return systemClasses[valueTypeIx + 1];
4884 /// Add a value class to this external assembly
4886 /// <param name="nsName">name space name</param>
4887 /// <param name="name">class name</param>
4888 /// <returns></returns>
4889 public override ClassRef AddValueClass(string nsName, string name)
4891 if (nsName.CompareTo(systemName) == 0) {
4892 int hash = name.GetHashCode();
4893 if ((hash == specialNames[valueTypeIx]) ||
4894 (hash == specialNames[valueTypeIx+1])) {
4895 return GetValueClass(name,hash);
4898 ClassRef aClass = new ClassRef(nsName,name,metaData);
4899 metaData.AddToTable(MDTable.TypeRef,aClass);
4900 aClass.SetParent(this);
4901 aClass.MakeValueClass(ValueClass.ValueType);
4907 /**************************************************************************/
4910 /// Root (20 bytes + UTF-8 Version String + quad align padding)
4911 /// StreamHeaders (8 bytes + null terminated name string + quad align padding)
4913 /// #~ (always present - holds metadata tables)
4914 /// #Strings (always present - holds identifier strings)
4915 /// #US (Userstring heap)
4916 /// #Blob (signature blobs)
4917 /// #GUID (guids for assemblies or Modules)
4919 public class MetaData {
4921 internal static readonly int[] CIxShiftMap = {2,2,5,1,2,3,1,1,1,2,3,2,1};
4922 private static readonly byte StringsHeapMask = 0x1;
4923 private static readonly byte GUIDHeapMask = 0x2;
4924 private static readonly byte BlobHeapMask = 0x4;
4925 private static readonly uint MetaDataSignature = 0x424A5342;
4926 private static readonly uint maxSmlIxSize = 0xFFFF;
4927 private static readonly uint max1BitSmlIx = 0x7FFF;
4928 private static readonly uint max2BitSmlIx = 0x3FFF;
4929 private static readonly uint max3BitSmlIx = 0x1FFF;
4930 private static readonly uint max5BitSmlIx = 0x7FF;
4931 // NOTE: version and stream name strings MUST always be quad padded
4932 #if NET_2_0 || BOOTSTRAP_NET_2_0
4933 private static readonly string version = "v2.0.50727\0\0";
4935 private static readonly string version = "v1.1.4322\0\0\0";
4937 private static readonly char[] tildeName = {'#','~','\0','\0'};
4938 private static readonly char[] stringsName = {'#','S','t','r','i','n','g','s','\0','\0','\0','\0'};
4939 private static readonly char[] usName = {'#','U','S','\0'};
4940 private static readonly char[] guidName = {'#','G','U','I','D','\0','\0','\0'};
4941 private static readonly char[] blobName = {'#','B','l','o','b','\0','\0','\0'};
4942 private static readonly uint MetaDataHeaderSize = 20 + (uint)version.Length;
4943 private static readonly uint TildeHeaderSize = 24;
4944 private static readonly uint StreamHeaderSize = 8;
4945 private static readonly uint numMetaDataTables = (int)MDTable.GenericParamConstraint + 1;
4946 private static readonly uint tildeHeaderSize = 8 + (uint)tildeName.Length;
4948 MetaDataStream strings, us, guid, blob;
4950 MetaDataStream[] streams = new MetaDataStream[5];
4951 uint numStreams = 5;
4952 uint tildeTide = 0, tildePadding = 0, tildeStart = 0;
4953 uint numTables = 0, resourcesSize = 0;
4954 ArrayList[] metaDataTables = new ArrayList[numMetaDataTables];
4955 ArrayList byteCodes = new ArrayList();
4956 uint codeSize = 0, codeStart, byteCodePadding = 0, metaDataSize = 0;
4957 ulong valid = 0, /*sorted = 0x000002003301FA00;*/ sorted = 0;
4958 bool[] largeIx = new bool[numMetaDataTables];
4959 bool[] lgeCIx = new bool[(int)CIx.MaxCIx];
4960 bool largeStrings = false, largeUS = false, largeGUID = false, largeBlob = false;
4961 private FileImage file;
4962 private byte heapSizes = 0;
4963 MetaDataElement entryPoint;
4964 BinaryWriter output;
4965 public MSCorLib mscorlib;
4966 private TypeSpec[] systemTypeSpecs = new TypeSpec[PrimitiveType.NumSystemTypes];
4968 private ArrayList cattr_list;
4969 private ArrayList declsec_list;
4970 ArrayList resources;
4972 internal MetaData(FileImage file)
4974 // tilde = new MetaDataStream(tildeName,false,0);
4976 strings = new MetaDataStream(stringsName,new UTF8Encoding(),true);
4977 us = new MetaDataStream(usName,new UnicodeEncoding(),true);
4978 guid = new MetaDataStream(guidName,false);
4979 blob = new MetaDataStream(blobName,true);
4980 streams[1] = strings;
4984 for (int i=0; i < numMetaDataTables; i++) {
4987 for (int i=0; i < lgeCIx.Length; i++) {
4990 mscorlib = new MSCorLib(this);
4993 internal TypeSpec GetPrimitiveTypeSpec(int ix)
4995 return systemTypeSpecs[ix];
4998 internal void SetPrimitiveTypeSpec(int ix, TypeSpec typeSpec)
5000 systemTypeSpecs[ix] = typeSpec;
5003 internal uint Size()
5005 return metaDataSize;
5008 private void CalcHeapSizes ()
5010 if (strings.LargeIx()) {
5011 largeStrings = true;
5012 heapSizes |= StringsHeapMask;
5014 if (guid.LargeIx()) {
5016 heapSizes |= GUIDHeapMask;
5018 if (blob.LargeIx()) {
5020 heapSizes |= BlobHeapMask;
5023 largeUS = us.LargeIx();
5026 internal void StreamSize(byte mask)
5031 internal uint AddToUSHeap(string str)
5033 if (str == null) return 0;
5034 return us.Add(str,true);
5037 internal uint AddToUSHeap(byte[] str)
5039 if (str == null) return 0;
5040 return us.Add (str, true);
5043 internal uint AddToStringsHeap(string str)
5045 if ((str == null) || (str.CompareTo("") == 0)) return 0;
5046 return strings.Add(str,false);
5049 internal uint AddToGUIDHeap(Guid guidNum)
5051 return guid.Add(guidNum, false);
5054 internal uint AddToBlobHeap(byte[] blobBytes)
5056 if (blobBytes == null) return 0;
5057 return blob.Add(blobBytes, true);
5060 internal uint AddToBlobHeap(byte val)
5062 return blob.Add(val, true);
5065 internal uint AddToBlobHeap(sbyte val)
5067 return blob.Add(val, true);
5070 internal uint AddToBlobHeap(ushort val)
5072 return blob.Add(val, true);
5075 internal uint AddToBlobHeap(short val)
5077 return blob.Add(val, true);
5080 internal uint AddToBlobHeap(uint val)
5082 return blob.Add(val, true);
5085 internal uint AddToBlobHeap(int val)
5087 return blob.Add(val, true);
5090 internal uint AddToBlobHeap(ulong val)
5092 return blob.Add(val, true);
5095 internal uint AddToBlobHeap(long val)
5097 return blob.Add(val, true);
5100 internal uint AddToBlobHeap(float val)
5102 return blob.Add(val, true);
5105 internal uint AddToBlobHeap(double val)
5107 return blob.Add(val, true);
5110 internal uint AddToBlobHeap(string val)
5112 return blob.Add(val,true);
5115 internal void AddCustomAttribute (CustomAttribute cattr)
5117 if (cattr_list == null)
5118 cattr_list = new ArrayList ();
5119 cattr_list.Add (cattr);
5122 internal void AddDeclSecurity (BaseDeclSecurity decl_sec)
5124 if (declsec_list == null)
5125 declsec_list = new ArrayList ();
5126 declsec_list.Add (decl_sec);
5129 private ArrayList GetTable(MDTable tableIx)
5131 int tabIx = (int)tableIx;
5132 if (metaDataTables[tabIx] == null) {
5133 metaDataTables[tabIx] = new ArrayList();
5134 valid |= ((ulong)0x1 << tabIx);
5135 // Console.WriteLine("after creating table " + tableIx + "(" + tabIx + ") valid = " + valid);
5138 return metaDataTables[tabIx];
5141 internal void AddToTable(MDTable tableIx, MetaDataElement elem)
5144 // Console.Out.WriteLine("ERROR - element already in table " + tableIx);
5147 // updates Row field of the element
5148 // Console.WriteLine("Adding element to table " + (uint)tableIx);
5149 ArrayList table = GetTable(tableIx);
5150 elem.Row = (uint)table.Count + 1;
5154 internal uint TableIndex(MDTable tableIx)
5156 if (metaDataTables[(int)tableIx] == null) return 1;
5157 return (uint)metaDataTables[(int)tableIx].Count+1;
5160 internal uint AddCode(CILInstructions byteCode)
5162 byteCodes.Add(byteCode);
5163 uint offset = codeSize + codeStart;
5164 codeSize += byteCode.GetCodeSize();
5168 internal void SetEntryPoint(MetaDataElement ep)
5173 internal uint AddResource(byte[] resBytes)
5175 if (resources == null) resources = new ArrayList ();
5176 resources.Add (resBytes);
5177 uint offset = resourcesSize;
5178 resourcesSize += (uint)resBytes.Length + 4;
5182 internal void AddData(DataConstant cVal)
5184 file.AddInitData(cVal);
5187 internal static void CompressNum(uint val, MemoryStream sig)
5190 sig.WriteByte((byte)val);
5191 } else if (val <= 0x3FFF) {
5192 byte b1 = (byte)((val >> 8) | 0x80);
5193 byte b2 = (byte)(val & FileImage.iByteMask[0]);
5197 byte b1 = (byte)((val >> 24) | 0xC0);
5198 byte b2 = (byte)((val & FileImage.iByteMask[2]) >> 16);
5199 byte b3 = (byte)((val & FileImage.iByteMask[1]) >> 8);;
5200 byte b4 = (byte)(val & FileImage.iByteMask[0]);
5208 internal uint CodeSize()
5210 return codeSize + byteCodePadding;
5213 internal uint GetResourcesSize()
5215 return resourcesSize;
5218 internal uint StringsIndexSize()
5220 if (largeStrings) return 4;
5224 internal uint GUIDIndexSize()
5226 if (largeGUID) return 4;
5230 internal uint USIndexSize()
5232 if (largeUS) return 4;
5236 internal uint BlobIndexSize()
5238 if (largeBlob) return 4;
5242 internal uint CodedIndexSize(CIx code)
5244 if (lgeCIx[(uint)code]) return 4;
5248 internal uint TableIndexSize(MDTable tabIx)
5250 if (largeIx[(uint)tabIx]) return 4;
5254 private void SetIndexSizes()
5256 for (int i=0; i < numMetaDataTables; i++) {
5257 if (metaDataTables[i] == null)
5260 uint count = (uint)metaDataTables[i].Count;
5261 if (count > maxSmlIxSize)
5264 MDTable tabIx = (MDTable)i;
5265 if (count > max5BitSmlIx) {
5266 lgeCIx[(int)CIx.HasCustomAttr] = true;
5268 if (count > max3BitSmlIx) {
5269 if ((tabIx == MDTable.TypeRef) || (tabIx == MDTable.ModuleRef) || (tabIx == MDTable.Method) || (tabIx == MDTable.TypeSpec) || (tabIx == MDTable.Field))
5270 lgeCIx[(int)CIx.CustomAttributeType] = true;
5271 if ((tabIx == MDTable.Method) || (tabIx == MDTable.MemberRef))
5272 lgeCIx[(int)CIx.MemberRefParent] = true;
5274 if (count > max2BitSmlIx) {
5275 if ((tabIx == MDTable.Field) || (tabIx == MDTable.Param) || (tabIx == MDTable.Property))
5276 lgeCIx[(int)CIx.HasConst] = true;
5277 if ((tabIx == MDTable.TypeDef) || (tabIx == MDTable.TypeRef) || (tabIx == MDTable.TypeSpec))
5278 lgeCIx[(int)CIx.TypeDefOrRef] = true;
5279 if ((tabIx == MDTable.TypeDef) || (tabIx == MDTable.Method) || (tabIx == MDTable.Assembly))
5280 lgeCIx[(int)CIx.HasDeclSecurity] = true;
5281 if ((tabIx == MDTable.File) || (tabIx == MDTable.AssemblyRef) || (tabIx == MDTable.ExportedType))
5282 lgeCIx[(int)CIx.Implementation] = true;
5283 if ((tabIx == MDTable.Module) || (tabIx == MDTable.ModuleRef) || (tabIx == MDTable.AssemblyRef) || (tabIx == MDTable.TypeRef))
5284 lgeCIx[(int)CIx.ResolutionScope] = true;
5286 if (count > max1BitSmlIx) {
5287 if ((tabIx == MDTable.Field) || (tabIx == MDTable.Param))
5288 lgeCIx[(int)CIx.HasFieldMarshal] = true;
5289 if ((tabIx == MDTable.Event) || (tabIx == MDTable.Property))
5290 lgeCIx[(int)CIx.HasSemantics] = true;
5291 if ((tabIx == MDTable.Method) || (tabIx == MDTable.MemberRef))
5292 lgeCIx[(int)CIx.MethodDefOrRef] = true;
5293 if ((tabIx == MDTable.Field) || (tabIx == MDTable.Method))
5294 lgeCIx[(int)CIx.MemberForwarded] = true;
5295 if ((tabIx == MDTable.TypeDef) || (tabIx == MDTable.Method))
5296 lgeCIx[(int)CIx.TypeOrMethodDef] = true;
5301 private void SetStreamOffsets()
5303 uint sizeOfHeaders = StreamHeaderSize + (uint)tildeName.Length;
5304 for (int i=1; i < numStreams; i++) {
5305 sizeOfHeaders += streams[i].headerSize();
5307 metaDataSize = MetaDataHeaderSize + sizeOfHeaders;
5308 tildeStart = metaDataSize;
5309 metaDataSize += tildeTide + tildePadding;
5310 for (int i=1; i < numStreams; i++) {
5311 streams[i].Start = metaDataSize;
5312 metaDataSize += streams[i].Size();
5313 streams[i].WriteDetails();
5317 internal void CalcTildeStreamSize()
5320 //tilde.SetIndexSizes(strings.LargeIx(),us.LargeIx(),guid.LargeIx(),blob.LargeIx());
5321 tildeTide = TildeHeaderSize;
5322 tildeTide += 4 * numTables;
5323 //Console.WriteLine("Tilde header + sizes = " + tildeTide);
5324 for (int i=0; i < numMetaDataTables; i++) {
5325 if (metaDataTables[i] != null) {
5326 ArrayList table = metaDataTables[i];
5327 // Console.WriteLine("Meta data table " + i + " at offset " + tildeTide);
5328 tildeTide += (uint)table.Count * ((MetaDataElement)table[0]).Size(this);
5329 // Console.WriteLine("Metadata table " + i + " has size " + table.Count);
5330 // Console.WriteLine("tildeTide = " + tildeTide);
5333 if ((tildeTide % 4) != 0) tildePadding = 4 - (tildeTide % 4);
5334 //Console.WriteLine("tildePadding = " + tildePadding);
5337 internal void WriteTildeStream(FileImage output)
5339 long startTilde = output.Seek(0,SeekOrigin.Current);
5340 output.Write((uint)0); // Reserved
5341 #if NET_2_0 || BOOTSTRAP_NET_2_0
5342 output.Write((byte)2); // MajorVersion
5343 output.Write((byte)0); // MinorVersion
5345 output.Write((byte)1); // MajorVersion
5346 output.Write((byte)0); // MinorVersion
5348 output.Write(heapSizes);
5349 output.Write((byte)1); // Reserved
5350 output.Write(valid);
5351 output.Write(sorted);
5352 for (int i=0; i < numMetaDataTables; i++) {
5353 if (metaDataTables[i] != null) {
5354 uint count = (uint)metaDataTables[i].Count;
5355 output.Write(count);
5358 long tabStart = output.Seek(0,SeekOrigin.Current);
5359 // Console.WriteLine("Starting metaData tables at " + tabStart);
5360 for (int i=0; i < numMetaDataTables; i++) {
5361 if (metaDataTables[i] != null) {
5362 // Console.WriteLine("Starting metaData table " + i + " at " + (output.Seek(0,SeekOrigin.Current) - startTilde));
5363 ArrayList table = metaDataTables[i];
5364 for (int j=0; j < table.Count; j++) {
5365 ((MetaDataElement)table[j]).Write(output);
5369 // Console.WriteLine("Writing padding at " + output.Seek(0,SeekOrigin.Current));
5370 for (int i=0; i < tildePadding; i++) output.Write((byte)0);
5373 private void BuildTable(ArrayList table)
5375 if (table == null) return;
5376 for (int j=0; j < table.Count; j++) {
5377 ((MetaDataElement)table[j]).BuildTables(this);
5381 private void SortTable (ArrayList mTable)
5383 if (mTable == null) return;
5385 for (int i=0; i < mTable.Count; i++) {
5386 ((MetaDataElement)mTable[i]).Row = (uint)i+1;
5390 internal void BuildMetaData(uint codeStartOffset)
5392 codeStart = codeStartOffset;
5393 BuildTable(metaDataTables[(int)MDTable.TypeDef]);
5394 BuildTable(metaDataTables[(int)MDTable.TypeSpec]);
5395 BuildTable(metaDataTables[(int)MDTable.MemberRef]);
5396 #if NET_2_0 || BOOTSTRAP_NET_2_0
5397 BuildTable(metaDataTables[(int)MDTable.GenericParam]);
5398 BuildTable(metaDataTables[(int)MDTable.MethodSpec]);
5399 BuildTable(metaDataTables[(int)MDTable.GenericParamConstraint]);
5401 BuildTable(metaDataTables[(int)MDTable.ManifestResource]);
5403 if (cattr_list != null) {
5404 foreach (CustomAttribute cattr in cattr_list)
5405 cattr.BuildTables (this);
5408 if (declsec_list != null) {
5409 foreach (BaseDeclSecurity decl_sec in declsec_list)
5410 decl_sec.BuildTables (this);
5413 /* for (int i=0; i < metaDataTables.Length; i++) {
5414 ArrayList table = metaDataTables[i];
5415 if (table != null) {
5416 for (int j=0; j < table.Count; j++) {
5417 ((MetaDataElement)table[j]).BuildTables(this);
5424 for (int i=1; i < numStreams; i++) {
5425 streams[i].EndStream();
5427 CalcTildeStreamSize();
5429 byteCodePadding = NumToAlign(codeSize,4);
5430 if (entryPoint != null) file.SetEntryPoint(entryPoint.Token());
5432 // Check ordering of specific tables
5433 // Constant, CustomAttribute, FieldMarshal, DeclSecurity, MethodSemantics
5434 // ImplMap, GenericParam
5435 // Need to load GenericParamConstraint AFTER GenericParam table in correct order
5437 // InterfaceImpl, ClassLayout, FieldLayout, MethodImpl, FieldRVA, NestedClass
5438 // will _ALWAYS_ be in the correct order as embedded in BuildMDTables
5440 SortTable(metaDataTables[(int)MDTable.Constant]);
5441 SortTable(metaDataTables[(int)MDTable.FieldMarshal]);
5442 SortTable(metaDataTables[(int)MDTable.DeclSecurity]);
5443 SortTable(metaDataTables[(int)MDTable.MethodSemantics]);
5444 SortTable(metaDataTables[(int)MDTable.ImplMap]);
5445 #if NET_2_0 || BOOTSTRAP_NET_2_0
5446 if (metaDataTables[(int)MDTable.GenericParam] != null) {
5447 SortTable(metaDataTables[(int)MDTable.GenericParam]);
5448 // Now add GenericParamConstraints
5449 /*for (int i=0; i < metaDataTables[(int)MDTable.GenericParam].Count; i++) {
5450 ((GenericParameter)metaDataTables[(int)MDTable.GenericParam][i]).AddConstraints(this);
5453 SortTable(metaDataTables[(int)MDTable.GenericParamConstraint]);
5455 SortTable(metaDataTables[(int)MDTable.InterfaceImpl]);
5456 SortTable(metaDataTables[(int)MDTable.CustomAttribute]);
5460 internal void WriteByteCodes(FileImage output)
5462 for (int i=0; i < byteCodes.Count; i++) {
5463 ((CILInstructions)byteCodes[i]).Write(output);
5465 for (int i=0; i < byteCodePadding; i++) {
5466 output.Write((byte)0);
5470 internal void WriteResources (FileImage output)
5472 if (resources == null) return;
5473 for (int i = 0; i < resources.Count; i ++) {
5474 byte [] resBytes = (byte []) resources [i];
5475 output.Write ((uint) resBytes.Length);
5476 output.Write (resBytes);
5480 internal void WriteMetaData(FileImage output)
5482 this.output = output;
5483 mdStart = output.Seek(0,SeekOrigin.Current);
5484 // Console.WriteLine("Writing metaData at " + Hex.Long(mdStart));
5485 output.Write(MetaDataSignature);
5486 output.Write((short)1); // Major Version
5487 output.Write((short)1); // Minor Version ECMA = 0, PEFiles = 1
5488 output.Write(0); // Reserved
5489 output.Write(version.Length);
5490 output.Write(version.ToCharArray()); // version string is already zero padded
5491 output.Write((short)0);
5492 output.Write((ushort)numStreams);
5493 // write tilde header
5494 output.Write(tildeStart);
5495 output.Write(tildeTide + tildePadding);
5496 output.Write(tildeName);
5497 for (int i=1; i < numStreams; i++) streams[i].WriteHeader(output);
5498 // Console.WriteLine("Writing tilde stream at " + output.Seek(0,SeekOrigin.Current) + " = " + tildeStart);
5499 WriteTildeStream(output);
5500 for (int i=1; i < numStreams; i++) streams[i].Write(output);
5501 // Console.WriteLine("Finished Writing metaData at " + output.Seek(0,SeekOrigin.Current));
5504 internal bool LargeStringsIndex() { return strings.LargeIx(); }
5505 internal bool LargeGUIDIndex() { return guid.LargeIx(); }
5506 internal bool LargeUSIndex() { return us.LargeIx(); }
5507 internal bool LargeBlobIndex() { return blob.LargeIx(); }
5509 internal bool LargeIx(MDTable tabIx) { return largeIx[(uint)tabIx]; }
5512 private uint NumToAlign(uint val, uint alignVal)
5514 if ((val % alignVal) == 0) return 0;
5515 return alignVal - (val % alignVal);
5518 internal void WriteCodedIndex(CIx code, MetaDataElement elem, FileImage output)
5522 ix = (elem.Row << CIxShiftMap[(uint)code]) | elem.GetCodedIx(code);
5523 // Console.WriteLine("coded index = " + ix + " row = " + elem.Row);
5525 // Console.WriteLine("elem for coded index is null");
5527 if (lgeCIx[(uint)code])
5530 output.Write((ushort)ix);
5535 /**************************************************************************/
5537 /// Stream in the Meta Data (#Strings, #US, #Blob and #GUID)
5540 internal class MetaDataStream : BinaryWriter {
5542 private static readonly uint StreamHeaderSize = 8;
5543 private static uint maxSmlIxSize = 0xFFFF;
5545 private uint start = 0;
5546 uint size = 0, tide = 1;
5547 bool largeIx = false;
5550 Hashtable htable = new Hashtable();
5551 Hashtable btable = new Hashtable (new ByteArrayHashCodeProvider (), new ByteArrayComparer ());
5553 internal MetaDataStream(char[] name, bool addInitByte) : base(new MemoryStream())
5555 if (addInitByte) { Write((byte)0); size = 1; }
5557 sizeOfHeader = StreamHeaderSize + (uint)name.Length;
5560 internal MetaDataStream(char[] name, System.Text.Encoding enc, bool addInitByte) : base(new MemoryStream(),enc)
5562 if (addInitByte) { Write((byte)0); size = 1; }
5564 sizeOfHeader = StreamHeaderSize + (uint)name.Length;
5568 get { return start; }
5569 set { start = value; }
5572 internal uint headerSize()
5574 // Console.WriteLine(name + " stream has headersize of " + sizeOfHeader);
5575 return sizeOfHeader;
5578 internal void SetSize(uint siz)
5583 internal uint Size()
5588 internal bool LargeIx()
5593 internal void WriteDetails()
5595 // Console.WriteLine(name + " - size = " + size);
5598 internal uint Add(string str, bool prependSize)
5600 Object val = htable[str];
5604 htable[str] = index;
5605 char[] arr = str.ToCharArray();
5606 if (prependSize) CompressNum((uint)arr.Length*2+1);
5609 size = (uint)Seek(0,SeekOrigin.Current);
5615 internal uint Add (byte[] str, bool prependSize)
5617 Object val = btable [str];
5621 btable [str] = index;
5622 if (prependSize) CompressNum ((uint) str.Length);
5624 size = (uint) Seek (0, SeekOrigin.Current);
5632 internal uint Add(Guid guid, bool prependSize)
5634 byte [] b = guid.ToByteArray ();
5635 if (prependSize) CompressNum ((uint) b.Length);
5636 Write(guid.ToByteArray());
5637 size =(uint)Seek(0,SeekOrigin.Current);
5641 internal uint Add(byte[] blob)
5644 CompressNum((uint)blob.Length);
5646 size = (uint)Seek(0,SeekOrigin.Current);
5650 internal uint Add(byte val, bool prependSize)
5653 if (prependSize) CompressNum (1);
5655 size = (uint)Seek(0,SeekOrigin.Current);
5659 internal uint Add(sbyte val, bool prependSize)
5662 if (prependSize) CompressNum (1);
5664 size = (uint)Seek(0,SeekOrigin.Current);
5668 internal uint Add(ushort val, bool prependSize)
5671 if (prependSize) CompressNum (2);
5673 size = (uint)Seek(0,SeekOrigin.Current);
5677 internal uint Add(short val, bool prependSize)
5680 if (prependSize) CompressNum (2);
5682 size = (uint)Seek(0,SeekOrigin.Current);
5686 internal uint Add(uint val, bool prependSize)
5689 if (prependSize) CompressNum (4);
5691 size = (uint)Seek(0,SeekOrigin.Current);
5695 internal uint Add(int val, bool prependSize)
5698 if (prependSize) CompressNum (4);
5700 size = (uint)Seek(0,SeekOrigin.Current);
5704 internal uint Add(ulong val, bool prependSize)
5707 if (prependSize) CompressNum (8);
5709 size = (uint)Seek(0,SeekOrigin.Current);
5713 internal uint Add(long val, bool prependSize)
5716 if (prependSize) CompressNum (8);
5718 size = (uint)Seek(0,SeekOrigin.Current);
5722 internal uint Add(float val, bool prependSize)
5725 if (prependSize) CompressNum (4);
5727 size = (uint)Seek(0,SeekOrigin.Current);
5731 internal uint Add(double val, bool prependSize)
5734 if (prependSize) CompressNum (8);
5736 size = (uint)Seek(0,SeekOrigin.Current);
5740 private void CompressNum(uint val)
5744 } else if (val < 0x3FFF) {
5745 byte b1 = (byte)((val >> 8) | 0x80);
5746 byte b2 = (byte)(val & FileImage.iByteMask[0]);
5750 byte b1 = (byte)((val >> 24) | 0xC0);
5751 byte b2 = (byte)((val & FileImage.iByteMask[2]) >> 16);
5752 byte b3 = (byte)((val & FileImage.iByteMask[1]) >> 8);;
5753 byte b4 = (byte)(val & FileImage.iByteMask[0]);
5761 private void QuadAlign()
5763 if ((size % 4) != 0) {
5764 uint pad = 4 - (size % 4);
5766 for (int i=0; i < pad; i++) {
5772 internal void EndStream()
5775 if (size > maxSmlIxSize) {
5780 internal void WriteHeader(BinaryWriter output)
5782 output.Write(start);
5787 internal virtual void Write(BinaryWriter output)
5789 // Console.WriteLine("Writing " + name + " stream at " + output.Seek(0,SeekOrigin.Current) + " = " + start);
5790 MemoryStream str = (MemoryStream)BaseStream;
5791 output.Write(str.ToArray());
5796 /**************************************************************************/
5797 class ByteArrayComparer : IComparer {
5799 public int Compare (object x, object y)
5801 byte [] a = (byte []) x;
5802 byte [] b = (byte []) y;
5805 if (b.Length != len)
5808 for (int i = 0; i < len; ++i)
5815 class ByteArrayHashCodeProvider : IHashCodeProvider {
5817 public int GetHashCode (Object key)
5819 byte [] arr = (byte []) key;
5820 int len = arr.Length;
5823 for (int i = 0; i < len; ++i)
5824 h = (h << 5) - h + arr [i];