3 using System.Collections;
5 using System.Reflection;
12 /// flags for the assembly (.corflags)
14 public enum CorFlags {CF_IL_ONLY = 1, CF_32_BITREQUIRED = 2,
15 CF_STRONGNAMESIGNED = 8, CF_TRACKDEBUGDATA = 0x10000 }
18 /// subsystem for the assembly (.subsystem)
20 public enum SubSystem { Native = 1, Windows_GUI = 2,
21 Windows_CUI = 3, OS2_CUI = 5, POSIX_CUI = 7, Native_Windows = 8,
25 /// Hash algorithms for the assembly
27 public enum HashAlgorithm { None, SHA1 }
30 /// Attributes for this assembly
32 public enum AssemAttr { Retargetable = 0x100, EnableJITCompileTracking = 0x8000,
33 DisableJITCompileOptimizer = 0x4000}
36 /// Method call conventions
39 public enum CallConv { Default, Cdecl, Stdcall, Thiscall,
40 Fastcall, Vararg, Instance = 0x20, Generic = 0x10, InstanceExplicit = 0x60 }
43 /// Type custom modifier
45 public enum CustomModifier { modreq = 0x1F, modopt };
48 /// Attibutes for a class
51 public enum TypeAttr {Private, Public, NestedPublic, NestedPrivate,
52 NestedFamily, NestedAssembly, NestedFamAndAssem, NestedFamOrAssem,
53 SequentialLayout, ExplicitLayout = 0x10, Interface = 0x20,
54 Abstract = 0x80, PublicAbstract = 0x81, Sealed = 0x100,
55 PublicSealed = 0x101, SpecialName = 0x400, RTSpecialName = 0x800,
56 Import = 0x1000, Serializable = 0x2000, UnicodeClass = 0x10000,
57 AutoClass = 0x20000, HasSecurity = 0x40000, BeforeFieldInit = 0x100000,
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, Strict = 0x200, 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 MetaDataElement parent;
437 ArrayList names, vals;
439 internal CustomAttribute(MetaDataElement paren, Method constrType,
444 tabIx = MDTable.CustomAttribute;
447 internal CustomAttribute(MetaDataElement paren, Method constrType,
451 tabIx = MDTable.CustomAttribute;
455 internal override uint SortKey()
457 return (parent.Row << MetaData.CIxShiftMap[(uint)CIx.HasCustomAttr])
458 | parent.GetCodedIx(CIx.HasCustomAttr);
461 public void AddFieldOrProp(string name, Constant val)
464 names = new ArrayList();
465 vals = new ArrayList();
471 internal sealed override void BuildTables(MetaData md)
473 md.AddToTable(MDTable.CustomAttribute, this);
474 if (byteVal == null) {
479 BinaryWriter bw = new BinaryWriter(new MemoryStream());
481 MemoryStream str = (MemoryStream)bw.BaseStream;
482 valIx = md.AddToBlobHeap(str.ToArray());
485 internal sealed override uint Size(MetaData md)
487 return md.CodedIndexSize(CIx.HasCustomAttr) + md.CodedIndexSize(CIx.CustomAttributeType) + md.BlobIndexSize();
490 internal sealed override void Write(FileImage output)
492 output.WriteCodedIndex(CIx.HasCustomAttr,parent);
493 output.WriteCodedIndex(CIx.CustomAttributeType,type);
494 output.BlobIndex(valIx);
499 /**************************************************************************/
501 /// Descriptor for security permissions for a class or a method
504 public abstract class BaseDeclSecurity : MetaDataElement {
507 MetaDataElement parent;
510 internal BaseDeclSecurity(MetaDataElement paren, ushort act)
514 tabIx = MDTable.DeclSecurity;
517 internal override uint SortKey()
519 return (parent.Row << MetaData.CIxShiftMap[(uint)CIx.HasDeclSecurity])
520 | parent.GetCodedIx(CIx.HasDeclSecurity);
523 internal sealed override uint Size(MetaData md)
525 return 2 + md.CodedIndexSize(CIx.HasDeclSecurity) + md.BlobIndexSize();
528 internal sealed override void BuildTables(MetaData md)
532 BinaryWriter bw = new BinaryWriter (new MemoryStream ());
533 md.AddToTable (MDTable.DeclSecurity, this);
534 MemoryStream str = (MemoryStream)bw.BaseStream;
536 permissionIx = md.AddToBlobHeap(str.ToArray());
541 internal abstract void WriteSig (BinaryWriter bw);
543 internal sealed override void Write(FileImage output)
545 output.Write(action);
546 output.WriteCodedIndex(CIx.HasDeclSecurity,parent);
547 output.BlobIndex(permissionIx);
552 public class DeclSecurity : BaseDeclSecurity {
556 internal DeclSecurity(MetaDataElement paren, ushort act, byte [] val)
562 internal override void WriteSig (BinaryWriter bw)
569 public class DeclSecurity_20 : BaseDeclSecurity {
573 internal DeclSecurity_20 (MetaDataElement paren, ushort act, PermissionSet ps)
579 internal override void WriteSig (BinaryWriter bw)
585 public class PermissionMember {
587 MemberTypes member_type;
592 public PermissionMember (MemberTypes member_type, PEAPI.Type type, string name, object value)
594 this.member_type = member_type;
600 public void Write (BinaryWriter bw)
604 if (member_type == MemberTypes.Field)
605 bw.Write ((byte) 0x53);
608 bw.Write ((byte) 0x54);
610 if (type is PrimitiveType) {
611 bw.Write (type.GetTypeIndex ());
614 bw.Write ((byte) 0x55); //ENUM
616 b = Encoding.UTF8.GetBytes (((ClassRef) type).TypeName ());
617 MetaData.CompressNum ((uint) b.Length, (MemoryStream) bw.BaseStream);
621 b = Encoding.UTF8.GetBytes (name);
622 MetaData.CompressNum ((uint) b.Length, (MemoryStream) bw.BaseStream);
625 ((Constant) value).Write (bw);
630 public class Permission
638 public Permission (PEAPI.Type type, string name)
644 public void AddMember (PEAPI.PermissionMember member)
647 members = new ArrayList ();
649 members.Add (member);
652 public void Write (BinaryWriter bw)
654 byte [] b = Encoding.UTF8.GetBytes (name);
655 MetaData.CompressNum ((uint) b.Length, (MemoryStream) bw.BaseStream);
658 BinaryWriter perm_writer = new BinaryWriter (new MemoryStream (), Encoding.Unicode);
659 MemoryStream str = (MemoryStream) perm_writer.BaseStream;
661 MetaData.CompressNum ((uint) members.Count, str);//number of params
662 foreach (PermissionMember member in members)
663 member.Write (perm_writer);
665 bw.Write ((byte) str.Length); //(optional) parameters length
666 bw.Write (str.ToArray ());
670 public class PermissionSet
672 PEAPI.SecurityAction sec_action;
673 ArrayList permissions;
675 public PermissionSet (PEAPI.SecurityAction sec_action)
677 this.sec_action = sec_action;
680 public void AddPermission (PEAPI.Permission perm)
682 if (permissions == null)
683 permissions = new ArrayList ();
685 permissions.Add (perm);
688 public void Write (BinaryWriter bw)
690 bw.Write ((byte) 0x2e);
691 MetaData.CompressNum ((uint) permissions.Count, (MemoryStream) bw.BaseStream);
693 foreach (Permission perm in permissions)
699 /**************************************************************************/
701 /// Descriptor for layout information for a field
704 public class FieldLayout : MetaDataElement {
709 internal FieldLayout(Field field, uint offset)
712 this.offset = offset;
713 tabIx = MDTable.FieldLayout;
716 internal sealed override uint Size(MetaData md)
718 return 4 + md.TableIndexSize(MDTable.Field);
721 internal sealed override void Write(FileImage output)
723 output.Write(offset);
724 output.WriteIndex(MDTable.Field,field.Row);
729 /*****************************************************************************/
731 /// Marshalling information for a field or param
733 public class FieldMarshal : MetaDataElement {
735 MetaDataElement field;
739 internal FieldMarshal(MetaDataElement field, NativeType nType)
743 tabIx = MDTable.FieldMarshal;
746 internal override uint SortKey()
748 return (field.Row << MetaData.CIxShiftMap[(uint)CIx.HasFieldMarshal])
749 | field.GetCodedIx(CIx.HasFieldMarshal);
752 internal sealed override void BuildTables(MetaData md)
755 ntIx = md.AddToBlobHeap(nt.ToBlob());
759 internal sealed override uint Size(MetaData md)
761 return md.CodedIndexSize(CIx.HasFieldMarshal) + md.BlobIndexSize();
764 internal sealed override void Write(FileImage output)
766 output.WriteCodedIndex(CIx.HasFieldMarshal,field);
767 output.BlobIndex(ntIx);
772 /**************************************************************************/
774 /// Descriptor for the address of a field's value in the PE file
776 public class FieldRVA : MetaDataElement {
781 internal FieldRVA(Field field, DataConstant data)
785 tabIx = MDTable.FieldRVA;
788 internal sealed override void BuildTables(MetaData md)
795 internal sealed override uint Size(MetaData md)
797 return 4 + md.TableIndexSize(MDTable.Field);
800 internal sealed override void Write(FileImage output)
802 output.WriteDataRVA(data.DataOffset);
803 output.WriteIndex(MDTable.Field,field.Row);
808 /**************************************************************************/
810 /// Descriptor for a file referenced in THIS assembly/module (.file)
812 public class FileRef : MetaDataElement {
814 private static readonly uint NoMetaData = 0x1;
815 uint nameIx = 0, hashIx = 0;
817 protected string name;
819 internal FileRef(string name, byte[] hashBytes, bool metaData,
820 bool entryPoint, MetaData md) {
821 if (!metaData) flags = NoMetaData;
822 if (entryPoint) md.SetEntryPoint(this);
824 nameIx = md.AddToStringsHeap(name);
825 hashIx = md.AddToBlobHeap(hashBytes);
826 tabIx = MDTable.File;
829 internal FileRef(uint nameIx, byte[] hashBytes, bool metaData,
830 bool entryPoint, MetaData md) {
831 if (!metaData) flags = NoMetaData;
832 if (entryPoint) md.SetEntryPoint(this);
833 this.nameIx = nameIx;
834 hashIx = md.AddToBlobHeap(hashBytes);
835 tabIx = MDTable.File;
838 internal sealed override uint Size(MetaData md)
840 return 4 + md.StringsIndexSize() + md.BlobIndexSize();
843 internal sealed override void BuildTables(MetaData md)
845 md.AddToTable(MDTable.File,this);
848 internal sealed override void Write(FileImage output)
851 output.StringsIndex(nameIx);
852 output.BlobIndex(hashIx);
855 internal sealed override uint GetCodedIx(CIx code)
858 case (CIx.HasCustomAttr) : return 16;
859 case (CIx.Implementation) : return 0;
865 /**************************************************************************/
867 /// Descriptor for pinvoke information for a method NOT YET IMPLEMENTED
869 public class ImplMap : MetaDataElement {
871 private static readonly ushort NoMangle = 0x01;
876 ModuleRef importScope;
878 internal ImplMap(ushort flag, Method implMeth, string iName, ModuleRef mScope)
883 importScope = mScope;
884 tabIx = MDTable.ImplMap;
885 if (iName == null) flags |= NoMangle;
886 //throw(new NotYetImplementedException("PInvoke "));
889 internal override uint SortKey()
891 return (meth.Row << MetaData.CIxShiftMap[(uint)CIx.MemberForwarded])
892 | meth.GetCodedIx(CIx.MemberForwarded);
895 internal sealed override void BuildTables(MetaData md)
898 iNameIx = md.AddToStringsHeap(importName);
902 internal sealed override uint Size(MetaData md)
904 return 2+ md.CodedIndexSize(CIx.MemberForwarded) +
905 md.StringsIndexSize() + md.TableIndexSize(MDTable.ModuleRef);
908 internal sealed override void Write(FileImage output)
911 output.WriteCodedIndex(CIx.MemberForwarded,meth);
912 output.StringsIndex(iNameIx);
913 output.WriteIndex(MDTable.ModuleRef,importScope.Row);
918 /**************************************************************************/
920 public class GenericParameter : MetaDataElement {
922 MetaDataElement owner;
927 GenericParamAttributes attr;
929 internal GenericParameter (ClassDef owner, MetaData metadata,
930 short index, string name, GenericParamAttributes attr) : this (owner, metadata, index, name, attr, true)
934 internal GenericParameter (MethodDef owner, MetaData metadata,
935 short index, string name, GenericParamAttributes attr) : this (owner, metadata, index, name, attr, true)
939 private GenericParameter (MetaDataElement owner, MetaData metadata,
940 short index, string name, GenericParamAttributes attr, bool nadda) {
942 this.metadata = metadata;
944 tabIx = MDTable.GenericParam;
949 internal override uint SortKey()
951 return (owner.Row << MetaData.CIxShiftMap[(uint)CIx.TypeOrMethodDef])
952 | owner.GetCodedIx(CIx.TypeOrMethodDef);
955 internal override uint SortKey2 ()
960 public void AddConstraint (Type constraint)
962 metadata.AddToTable (MDTable.GenericParamConstraint,
963 new GenericParamConstraint (this, constraint));
966 internal sealed override uint Size(MetaData md)
969 md.CodedIndexSize(CIx.TypeOrMethodDef) +
970 md.StringsIndexSize ());
973 internal sealed override void BuildTables(MetaData md)
976 nameIx = md.AddToStringsHeap(name);
980 internal sealed override void Write(FileImage output)
982 output.Write ((short) index);
983 output.Write ((short) attr);
984 output.WriteCodedIndex(CIx.TypeOrMethodDef, owner);
985 output.StringsIndex (nameIx);
988 internal sealed override uint GetCodedIx(CIx code)
991 case (CIx.HasCustomAttr) : return 19;
998 internal class GenericParamConstraint : MetaDataElement {
1000 GenericParameter param;
1003 public GenericParamConstraint (GenericParameter param, Type type)
1007 tabIx = MDTable.GenericParamConstraint;
1010 internal override uint SortKey()
1015 internal sealed override uint Size(MetaData md)
1017 return (uint) (md.TableIndexSize(MDTable.GenericParam) +
1018 md.CodedIndexSize(CIx.TypeDefOrRef));
1021 internal sealed override void Write(FileImage output)
1023 output.WriteIndex(MDTable.GenericParam, param.Row);
1024 output.WriteCodedIndex(CIx.TypeDefOrRef, type);
1029 internal class MethodSpec : Method {
1032 GenericMethodSig g_sig;
1035 internal MethodSpec (Method meth, GenericMethodSig g_sig) : base ("")
1039 tabIx = MDTable.MethodSpec;
1042 internal override uint GetSigIx (MetaData md)
1044 throw new Exception ("Should not be used.");
1047 public override void AddCallConv (CallConv cconv)
1049 throw new Exception ("Should not be used.");
1052 internal sealed override void BuildTables (MetaData md)
1055 sidx = g_sig.GetSigIx (md);
1059 internal sealed override uint Size (MetaData md)
1061 return (uint) (md.CodedIndexSize(CIx.MethodDefOrRef) +
1062 md.BlobIndexSize ());
1065 internal sealed override void Write (FileImage output)
1067 output.WriteCodedIndex (CIx.MethodDefOrRef, meth);
1068 output.BlobIndex (sidx);
1071 internal sealed override void TypeSig (MemoryStream sig)
1073 throw new Exception ("Should not be used.");
1077 /**************************************************************************/
1079 /// Descriptor for interface implemented by a class
1081 public class InterfaceImpl: MetaDataElement {
1086 internal InterfaceImpl(ClassDef theClass, Class theInterface)
1088 this.theClass = theClass;
1089 this.theInterface = theInterface;
1090 tabIx = MDTable.InterfaceImpl;
1093 internal sealed override uint Size(MetaData md)
1095 return md.TableIndexSize(MDTable.TypeDef) +
1096 md.CodedIndexSize(CIx.TypeDefOrRef);
1099 internal sealed override void Write(FileImage output)
1101 output.WriteIndex(MDTable.TypeDef,theClass.Row);
1102 output.WriteCodedIndex(CIx.TypeDefOrRef,theInterface);
1105 internal sealed override uint GetCodedIx(CIx code) { return 5; }
1107 internal override uint SortKey ()
1109 return (theClass.Row << MetaData.CIxShiftMap[(uint)CIx.TypeDefOrRef])
1110 | theClass.GetCodedIx (CIx.TypeDefOrRef);
1115 /**************************************************************************/
1117 /// Descriptor for resources used in this PE file
1120 public class ManifestResource : MetaDataElement {
1122 public static readonly uint PublicResource = 0x1;
1123 public static readonly uint PrivateResource = 0x2;
1126 MetaDataElement rRef;
1130 byte [] resourceBytes;
1132 public ManifestResource (string name, byte[] resBytes, uint flags)
1134 InitResource (name, flags);
1135 this.resourceBytes = resBytes;
1138 public ManifestResource(string name, uint flags, FileRef fileRef)
1140 InitResource (name, flags);
1144 public ManifestResource(string name, uint flags, FileRef fileRef,
1146 InitResource (name, flags);
1148 fileOffset = fileIx;
1151 public ManifestResource(string name, uint flags, AssemblyRef assemRef)
1153 InitResource (name, flags);
1157 internal ManifestResource (ManifestResource mres)
1159 mrName = mres.mrName;
1162 fileOffset = mres.fileOffset;
1163 resourceBytes = mres.resourceBytes;
1166 private void InitResource (string name, uint flags)
1170 tabIx = MDTable.ManifestResource;
1173 internal sealed override void BuildTables(MetaData md)
1176 md.AddToTable (MDTable.ManifestResource, this);
1177 nameIx = md.AddToStringsHeap(mrName);
1178 if (resourceBytes != null) {
1180 throw new PEFileException ("Manifest Resource has byte value and file reference");
1181 fileOffset = md.AddResource(resourceBytes);
1184 throw new PEFileException ("Manifest Resource has no implementation or value");
1185 rRef.BuildTables (md);
1191 internal sealed override uint Size(MetaData md)
1193 return 8 + md.StringsIndexSize() +
1194 md.CodedIndexSize(CIx.Implementation);
1197 internal sealed override void Write(FileImage output)
1199 output.Write(fileOffset);
1200 output.Write(flags);
1201 output.StringsIndex(nameIx);
1202 output.WriteCodedIndex(CIx.Implementation,rRef);
1205 internal sealed override uint GetCodedIx(CIx code) { return 18; }
1207 public string Name {
1208 get { return mrName; }
1209 set { mrName = value; }
1213 /**************************************************************************/
1215 /// Base class for elements in the PropertyMap, EventMap and
1216 /// NestedClass MetaData tables
1218 public class MapElem : MetaDataElement {
1224 internal MapElem(ClassDef par, uint elIx, MDTable elemTab)
1228 elemTable = elemTab;
1231 internal sealed override uint Size(MetaData md)
1233 return md.TableIndexSize(MDTable.TypeDef) + md.TableIndexSize(elemTable);
1236 internal sealed override void Write(FileImage output)
1238 output.WriteIndex(MDTable.TypeDef,parent.Row);
1239 output.WriteIndex(elemTable,elemIx);
1243 /**************************************************************************/
1245 /// Descriptor for an overriding method (.override)
1247 public class MethodImpl : MetaDataElement {
1250 Method header, body;
1252 internal MethodImpl(ClassDef par, Method decl, Method bod)
1257 tabIx = MDTable.MethodImpl;
1260 internal sealed override uint Size(MetaData md)
1262 return md.TableIndexSize(MDTable.TypeDef) + 2 * md.CodedIndexSize(CIx.MethodDefOrRef);
1265 internal sealed override void Write(FileImage output)
1267 output.WriteIndex(MDTable.TypeDef,parent.Row);
1268 output.WriteCodedIndex(CIx.MethodDefOrRef,body);
1269 output.WriteCodedIndex(CIx.MethodDefOrRef,header);
1274 /**************************************************************************/
1276 /// Descriptor for Property and Event methods
1278 public class MethodSemantics : MetaDataElement {
1280 Feature.MethodType type;
1282 Feature eventOrProp;
1284 internal MethodSemantics(Feature.MethodType mType, MethodDef method, Feature feature)
1288 eventOrProp = feature;
1289 tabIx = MDTable.MethodSemantics;
1292 internal override uint SortKey()
1294 return (eventOrProp.Row << MetaData.CIxShiftMap [(uint)CIx.HasSemantics])
1295 | eventOrProp.GetCodedIx (CIx.HasSemantics);
1298 internal sealed override uint Size(MetaData md)
1300 return 2 + md.TableIndexSize(MDTable.Method) + md.CodedIndexSize(CIx.HasSemantics);
1303 internal sealed override void Write(FileImage output)
1305 output.Write((ushort)type);
1306 output.WriteIndex(MDTable.Method,meth.Row);
1307 output.WriteCodedIndex(CIx.HasSemantics,eventOrProp);
1312 /**************************************************************************/
1314 /// Descriptor for a parameter of a method defined in this assembly/module
1316 public class Param : MetaDataElement {
1321 internal ushort seqNo = 0;
1323 ConstantElem defaultVal;
1325 FieldMarshal marshalInfo;
1328 /// Create a new parameter for a method
1330 /// <param name="mode">param mode (in, out, opt)</param>
1331 /// <param name="parName">parameter name</param>
1332 /// <param name="parType">parameter type</param>
1333 public Param(ParamAttr mode, string parName, Type parType)
1337 parMode = (ushort)mode;
1338 tabIx = MDTable.Param;
1341 public bool HasMarshalInfo {
1342 get { return marshalInfo != null; }
1346 /// Add a default value to this parameter
1348 /// <param name="c">the default value for the parameter</param>
1349 public void AddDefaultValue(Constant cVal)
1351 defaultVal = new ConstantElem(this,cVal);
1352 parMode |= (ushort) ParamAttr.HasDefault;
1356 /// Add marshalling information about this parameter
1358 public void AddMarshallInfo(NativeType marshallType)
1360 parMode |= (ushort) ParamAttr.HasFieldMarshal;
1361 marshalInfo = new FieldMarshal(this,marshallType);
1364 internal Type GetParType() { return pType; }
1366 internal sealed override void BuildTables(MetaData md)
1369 nameIx = md.AddToStringsHeap(pName);
1370 if (defaultVal != null) {
1371 md.AddToTable(MDTable.Constant,defaultVal);
1372 defaultVal.BuildTables(md);
1374 if (marshalInfo != null) {
1375 md.AddToTable(MDTable.FieldMarshal,marshalInfo);
1376 marshalInfo.BuildTables(md);
1381 internal void TypeSig(MemoryStream str)
1386 internal sealed override uint Size(MetaData md)
1388 return 4 + md.StringsIndexSize();
1391 internal sealed override void Write(FileImage output)
1393 output.Write(parMode);
1394 output.Write(seqNo);
1395 output.StringsIndex(nameIx);
1398 internal sealed override uint GetCodedIx(CIx code)
1401 case (CIx.HasCustomAttr) : return 4;
1402 case (CIx.HasConst) : return 1;
1403 case (CIx.HasFieldMarshal) : return 1;
1410 /**************************************************************************/
1411 public abstract class Signature : MetaDataElement {
1413 protected uint sigIx;
1415 internal Signature()
1417 tabIx = MDTable.StandAloneSig;
1420 internal sealed override uint Size(MetaData md)
1422 return md.BlobIndexSize();
1425 internal sealed override void Write(FileImage output)
1427 output.BlobIndex(sigIx);
1430 internal sealed override uint GetCodedIx(CIx code) { return (uint)tabIx; }
1434 /**************************************************************************/
1435 public class TypeSpec : MetaDataElement {
1438 internal TypeSpec(Type aType, MetaData md)
1440 MemoryStream sig = new MemoryStream();
1442 sigIx = md.AddToBlobHeap(sig.ToArray());
1443 tabIx = MDTable.TypeSpec;
1446 internal sealed override uint GetCodedIx(CIx code)
1449 case (CIx.TypeDefOrRef) : return 2;
1450 case (CIx.HasCustomAttr) : return 13;
1451 case (CIx.MemberRefParent) : return 4;
1456 internal override uint Size(MetaData md)
1458 return md.BlobIndexSize();
1461 internal sealed override void Write(FileImage output)
1463 //Console.WriteLine("Writing the blob index for a TypeSpec");
1464 output.BlobIndex(sigIx);
1469 /**************************************************************************/
1471 /// Base class for all IL types
1473 public abstract class Type : MetaDataElement {
1474 protected byte typeIndex;
1475 protected TypeSpec typeSpec;
1477 internal Type(byte tyIx) { typeIndex = tyIx; }
1479 internal byte GetTypeIndex() { return typeIndex; }
1480 internal void SetTypeIndex (byte b) { typeIndex = b; }
1482 internal virtual MetaDataElement GetTypeSpec(MetaData md)
1484 if (typeSpec == null) {
1485 typeSpec = new TypeSpec(this,md);
1486 md.AddToTable(MDTable.TypeSpec,typeSpec);
1491 internal virtual void TypeSig(MemoryStream str)
1493 throw(new TypeSignatureException(this.GetType().AssemblyQualifiedName +
1494 " doesn't have a type signature!!"));
1498 public class ClassRefInst : Type {
1501 private bool is_value;
1503 public ClassRefInst (Type type, bool is_value) : base (PrimitiveType.Class.GetTypeIndex ())
1506 this.is_value = is_value;
1508 typeIndex = PrimitiveType.ValueType.GetTypeIndex ();
1509 tabIx = MDTable.TypeSpec;
1512 internal sealed override void TypeSig(MemoryStream str)
1518 /**************************************************************************/
1520 /// The base descriptor for a class
1522 public abstract class Class : Type {
1524 protected int row = 0;
1525 public string name, nameSpace;
1526 protected uint nameIx, nameSpaceIx;
1527 protected MetaData _metaData;
1528 internal Class(string nameSpaceName, string className, MetaData md)
1529 : base(PrimitiveType.Class.GetTypeIndex ())
1531 nameSpace = nameSpaceName;
1533 nameIx = md.AddToStringsHeap(name);
1534 nameSpaceIx = md.AddToStringsHeap(nameSpace);
1538 internal Class(uint nsIx, uint nIx) : base(PrimitiveType.Class.GetTypeIndex ())
1544 internal Class (byte typeIndex) : base (typeIndex)
1546 nameSpace = "Should not be used";
1547 name = "Should not be used";
1550 internal virtual uint TypeDefOrRefToken() { return 0; }
1552 internal virtual void MakeValueClass(ValueClass vClass)
1554 typeIndex = PrimitiveType.ValueType.GetTypeIndex ();
1557 internal virtual string TypeName()
1559 return (nameSpace + "." + name);
1562 internal override MetaDataElement GetTypeSpec(MetaData md)
1568 /**************************************************************************/
1569 // This Class produces entries in the TypeDef table of the MetaData
1570 // in the PE meta data.
1572 // NOTE: Entry 0 in TypeDef table is always the pseudo class <module>
1573 // which is the parent for functions and variables declared a module level
1576 /// The descriptor for a class defined in the IL (.class) in the current assembly/module
1579 public class ClassDef : Class {
1582 ArrayList fields = new ArrayList();
1583 ArrayList methods = new ArrayList();
1585 ArrayList properties;
1586 bool typeIndexChecked = true;
1587 uint fieldIx = 0, methodIx = 0;
1590 ClassDef parentClass;
1593 internal ClassDef(TypeAttr attrSet, string nsName, string name,
1594 MetaData md) : base(nsName, name, md)
1597 if (! ((nsName == "" && name == "<Module>") || (nsName == "System" && name == "Object")) ) {
1598 superType = metaData.mscorlib.GetSpecialSystemClass(PrimitiveType.Object);
1600 flags = (uint)attrSet;
1601 tabIx = MDTable.TypeDef;
1604 internal void SetSuper(Class sClass)
1607 if (! (sClass is GenericTypeInst))
1608 typeIndexChecked = false;
1611 internal override void MakeValueClass(ValueClass vClass)
1613 if (vClass == ValueClass.Enum)
1614 superType = metaData.mscorlib.EnumType();
1616 superType = metaData.mscorlib.ValueType();
1618 typeIndex = PrimitiveType.ValueType.GetTypeIndex ();
1621 public void SpecialNoSuper()
1627 /// Add an attribute to this class
1629 /// <param name="ta">the attribute to be added</param>
1630 public void AddAttribute(TypeAttr ta)
1636 /// Add an interface that is implemented by this class
1638 /// <param name="iFace">the interface that is implemented</param>
1639 public void AddImplementedInterface(Class iFace)
1641 metaData.AddToTable(MDTable.InterfaceImpl,new InterfaceImpl(this,iFace));
1645 /// Add a named generic type parameter
1647 public GenericParameter AddGenericParameter (short index, string name)
1649 return AddGenericParameter (index, name, 0);
1653 /// Add a named generic type parameter with attributes
1655 public GenericParameter AddGenericParameter (short index, string name, GenericParamAttributes attr)
1657 GenericParameter gp = new GenericParameter (this, metaData, index, name, attr);
1658 metaData.AddToTable (MDTable.GenericParam, gp);
1663 /// Add a field to this class
1665 /// <param name="name">field name</param>
1666 /// <param name="fType">field type</param>
1667 /// <returns>a descriptor for this new field</returns>
1668 public FieldDef AddField(string name, Type fType)
1670 FieldDef field = new FieldDef(name,fType);
1676 /// Add a field to this class
1678 /// <param name="fAtts">attributes for this field</param>
1679 /// <param name="name">field name</param>
1680 /// <param name="fType">field type</param>
1681 /// <returns>a descriptor for this new field</returns>
1682 public FieldDef AddField(FieldAttr fAtts, string name, Type fType)
1684 FieldDef field = new FieldDef(fAtts,name,fType);
1689 public void SetFieldOrder (ArrayList fields)
1691 this.fields = fields;
1695 /// Add a method to this class
1697 /// <param name="name">method name</param>
1698 /// <param name="retType">return type</param>
1699 /// <param name="pars">parameters</param>
1700 /// <returns>a descriptor for this new method</returns>
1701 public MethodDef AddMethod(string name, Type retType, Param[] pars)
1703 return AddMethod (name, new Param (ParamAttr.Default, "", retType), pars);
1706 public MethodDef AddMethod (string name, Param ret_param, Param [] pars)
1708 // Console.WriteLine("Adding method " + name + " to class " + this.name);
1709 MethodDef meth = new MethodDef(metaData,name, ret_param, pars);
1715 /// Add a method to this class
1717 /// <param name="mAtts">attributes for this method</param>
1718 /// <param name="iAtts">implementation attributes for this method</param>
1719 /// <param name="name">method name</param>
1720 /// <param name="retType">return type</param>
1721 /// <param name="pars">parameters</param>
1722 /// <returns>a descriptor for this new method</returns>
1723 public MethodDef AddMethod(MethAttr mAtts, ImplAttr iAtts, string name,
1724 Param ret_param, Param [] pars) {
1725 // Console.WriteLine("Adding method " + name + " to class " + this.name);
1726 MethodDef meth = new MethodDef (metaData, mAtts, iAtts, name, ret_param, pars);
1732 /// Add an event to this class
1734 /// <param name="name">event name</param>
1735 /// <param name="eType">event type</param>
1736 /// <returns>a descriptor for this new event</returns>
1737 public Event AddEvent(string name, Type eType)
1739 Event e = new Event(name,eType,this);
1740 if (events == null) events = new ArrayList();
1746 /// Add a property to this class
1748 /// <param name="name">property name</param>
1749 /// <param name="propType">property type</param>
1750 /// <returns>a descriptor for this new property</returns>
1751 public Property AddProperty(string name, Type retType, Type[] pars)
1753 Property p = new Property(name, retType, pars, this);
1754 if (properties == null) properties = new ArrayList();
1760 /// Add a nested class to this class
1762 /// <param name="attrSet">attributes for this nested class</param>
1763 /// <param name="nsName">nested name space name</param>
1764 /// <param name="name">nested class name</param>
1765 /// <returns>a descriptor for this new nested class</returns>
1766 public ClassDef AddNestedClass(TypeAttr attrSet, string nsName,
1768 ClassDef nClass = new ClassDef(attrSet,"",name,metaData);
1769 metaData.AddToTable(MDTable.TypeDef,nClass);
1770 metaData.AddToTable(MDTable.NestedClass,new MapElem(nClass,Row,MDTable.TypeDef));
1771 nClass.parentClass = this;
1775 public static bool IsValueType (Class type)
1777 return IsValueType (type.nameSpace, type.name);
1780 public static bool IsEnum (Class type)
1782 return IsEnum (type.nameSpace, type.name);
1785 public static bool IsValueType (string nsName, string name)
1787 return (nsName == "System" && name == "ValueType");
1790 public static bool IsEnum (string nsName, string name)
1792 return (nsName == "System" && name == "Enum");
1796 /// Add a nested class to this class
1798 /// <param name="attrSet">attributes for this nested class</param>
1799 /// <param name="nsName">nested name space name</param>
1800 /// <param name="name">nested class name</param>
1801 /// <param name="sType">super type of this nested class</param>
1802 /// <returns>a descriptor for this new nested class</returns>
1803 public ClassDef AddNestedClass(TypeAttr attrSet, string nsName,
1804 string name, Class sType) {
1805 ClassDef nClass = AddNestedClass (attrSet, nsName, name);
1806 nClass.SetSuper(sType);
1807 if (ClassDef.IsValueType (sType))
1808 nClass.MakeValueClass (ValueClass.ValueType);
1810 if (ClassDef.IsEnum (sType))
1811 nClass.MakeValueClass (ValueClass.Enum);
1813 if (ClassDef.IsValueType (sType) || ClassDef.IsEnum (sType))
1814 nClass.SetTypeIndex (PrimitiveType.ValueType.GetTypeIndex ());
1816 nClass.typeIndexChecked = true;
1821 /// Add layout information for this class. This class must have the
1822 /// sequential or explicit attribute.
1824 /// <param name="packSize">packing size (.pack)</param>
1825 /// <param name="classSize">class size (.size)</param>
1826 public void AddLayoutInfo (int packSize, int classSize)
1828 layout = new ClassLayout(packSize,classSize,this);
1832 /// Use a method as the implementation for another method (.override)
1834 /// <param name="decl">the method to be overridden</param>
1835 /// <param name="body">the implementation to be used</param>
1836 public void AddMethodOverride(Method decl, Method body)
1838 metaData.AddToTable(MDTable.MethodImpl,new MethodImpl(this,decl,body));
1842 /// Add security to this class NOT YET IMPLEMENTED
1844 /// <param name="permissionSet"></param>
1845 public void AddSecurity(byte[] permissionSet)
1847 throw(new NotYetImplementedException("Class security "));
1848 //flags |= HasSecurity;
1849 // securityActions = permissionSet;
1852 //public void AddLineInfo(int row, int col) { }
1854 internal void CheckTypeIndex()
1856 if (typeIndexChecked) return;
1857 if (superType is ClassDef)
1858 ((ClassDef)superType).CheckTypeIndex();
1859 typeIndex = superType.GetTypeIndex();
1860 typeIndexChecked = true;
1863 internal sealed override void BuildTables(MetaData md)
1866 if ((flags & (uint)TypeAttr.Interface) != 0) { superType = null; }
1867 // Console.WriteLine("Building tables for " + name);
1868 if (layout != null) md.AddToTable(MDTable.ClassLayout,layout);
1869 // Console.WriteLine("adding methods " + methods.Count);
1870 methodIx = md.TableIndex(MDTable.Method);
1871 for (int i=0; i < methods.Count; i++) {
1872 md.AddToTable(MDTable.Method,(MetaDataElement)methods[i]);
1873 ((MethodDef)methods[i]).BuildTables(md);
1875 // Console.WriteLine("adding fields");
1876 fieldIx = md.TableIndex(MDTable.Field);
1877 for (int i=0; i < fields.Count; i++) {
1878 md.AddToTable(MDTable.Field,(MetaDataElement)fields[i]);
1879 ((FieldDef)fields[i]).BuildTables(md);
1881 // Console.WriteLine("adding events and properties");
1882 if (events != null) {
1883 for (int i=0; i < events.Count; i++) {
1884 md.AddToTable(MDTable.Event,(Event)events[i]);
1885 ((Event)events[i]).BuildTables(md);
1887 md.AddToTable(MDTable.EventMap,
1888 new MapElem(this,((Event)events[0]).Row,MDTable.Event));
1890 if (properties != null) {
1891 for (int i=0; i < properties.Count; i++) {
1892 md.AddToTable(MDTable.Property,(Property)properties[i]);
1893 ((Property)properties[i]).BuildTables(md);
1895 md.AddToTable(MDTable.PropertyMap,new MapElem(this,
1896 ((Property)properties[0]).Row,MDTable.Property));
1898 // Console.WriteLine("End of building tables");
1902 internal sealed override uint Size(MetaData md)
1904 return 4 + 2 * md.StringsIndexSize() +
1905 md.CodedIndexSize(CIx.TypeDefOrRef) +
1906 md.TableIndexSize(MDTable.Field) +
1907 md.TableIndexSize(MDTable.Method);
1910 internal sealed override void Write(FileImage output)
1912 output.Write(flags);
1913 output.StringsIndex(nameIx);
1914 output.StringsIndex(nameSpaceIx);
1915 //if (superType != null)
1916 // Console.WriteLine("getting coded index for superType of " + name + " = " + superType.GetCodedIx(CIx.TypeDefOrRef));
1917 output.WriteCodedIndex(CIx.TypeDefOrRef,superType);
1918 output.WriteIndex(MDTable.Field,fieldIx);
1919 output.WriteIndex(MDTable.Method,methodIx);
1922 internal sealed override uint TypeDefOrRefToken()
1929 internal sealed override void TypeSig(MemoryStream sig)
1931 if (!typeIndexChecked) CheckTypeIndex();
1932 sig.WriteByte(GetTypeIndex());
1933 MetaData.CompressNum(TypeDefOrRefToken(),sig);
1936 internal sealed override uint GetCodedIx(CIx code)
1939 case (CIx.TypeDefOrRef) : return 0;
1940 case (CIx.HasCustomAttr) : return 3;
1941 case (CIx.HasDeclSecurity) : return 0;
1942 case (CIx.TypeOrMethodDef) : return 0;
1949 /**************************************************************************/
1951 /// Descriptor for a class/interface declared in another module of THIS
1952 /// assembly, or in another assembly.
1954 public class ClassRef : Class, IExternRef, IResolutionScope {
1956 protected IResolutionScope parent;
1957 protected MetaData metaData;
1959 internal ClassRef(string nsName, string name, MetaData md) : base(nsName, name, md)
1962 tabIx = MDTable.TypeRef;
1966 /// Add a method to this class
1968 /// <param name="name">method name</param>
1969 /// <param name="retType">return type</param>
1970 /// <param name="pars">parameter types</param>
1971 /// <returns>a descriptor for this method</returns>
1972 public MethodRef AddMethod(string name, Type retType, Type[] pars)
1974 return AddMethod (name, retType, pars, 0);
1978 /// Add a method to this class
1980 /// <param name="name">method name</param>
1981 /// <param name="retType">return type</param>
1982 /// <param name="pars">parameter types</param>
1983 /// <param name="gen_param_count">num of generic parameters</param>
1984 /// <returns>a descriptor for this method</returns>
1985 public MethodRef AddMethod (string name, Type retType, Type[] pars, int gen_param_count)
1987 MethodRef meth = new MethodRef (this, name, retType, pars, false, null, gen_param_count);
1988 metaData.AddToTable(MDTable.MemberRef,meth);
1993 /// Add a method to this class
1995 /// <param name="name">method name</param>
1996 /// <param name="retType">return type</param>
1997 /// <param name="pars">parameter types</param>
1998 /// <returns>a descriptor for this method</returns>
1999 public MethodRef AddVarArgMethod(string name, Type retType,
2000 Type[] pars, Type[] optPars)
2002 MethodRef meth = new MethodRef(this,name,retType,pars,true,optPars, 0);
2003 metaData.AddToTable(MDTable.MemberRef,meth);
2008 /// Add a field to this class
2010 /// <param name="name">field name</param>
2011 /// <param name="fType">field type</param>
2012 /// <returns>a descriptor for this field</returns>
2013 public FieldRef AddField(string name, Type fType)
2015 FieldRef field = new FieldRef(this,name,fType);
2016 metaData.AddToTable(MDTable.MemberRef,field);
2020 public ClassRef AddClass (string nsName, string name)
2022 ClassRef aClass = new ClassRef(nsName,name,metaData);
2023 metaData.AddToTable(MDTable.TypeRef,aClass);
2024 aClass.SetParent(this);
2028 public ClassRef AddValueClass (string nsName, string name)
2030 ClassRef aClass = AddClass (nsName, name);
2031 aClass.MakeValueClass (ValueClass.ValueType);
2035 internal void SetParent(IResolutionScope par)
2040 internal override string TypeName()
2042 if ((parent != null) && (parent is AssemblyRef))
2043 return (nameSpace + "." + name + ", " + ((AssemblyRef)parent).TypeName());
2045 return (nameSpace + name);
2048 internal sealed override uint Size(MetaData md)
2050 return md.CodedIndexSize(CIx.ResolutionScope) + 2 *
2051 md.StringsIndexSize();
2054 internal sealed override void Write(FileImage output)
2056 output.WriteCodedIndex(CIx.ResolutionScope,(MetaDataElement) parent);
2057 output.StringsIndex(nameIx);
2058 output.StringsIndex(nameSpaceIx);
2061 internal override sealed uint TypeDefOrRefToken()
2064 cIx = (cIx << 2) | 0x1;
2068 internal override void TypeSig(MemoryStream sig)
2070 sig.WriteByte(GetTypeIndex());
2071 MetaData.CompressNum(TypeDefOrRefToken(),sig);
2074 internal sealed override uint GetCodedIx(CIx code)
2077 case (CIx.TypeDefOrRef) : return 1;
2078 case (CIx.HasCustomAttr) : return 2;
2079 case (CIx.MemberRefParent) : return 1;
2080 case (CIx.ResolutionScope) : return 3;
2087 /**************************************************************************/
2088 public class ExternClassRef : ClassRef {
2090 ExternClass externClass;
2092 internal ExternClassRef(TypeAttr attrs, string nsName, string name,
2093 FileRef declFile, MetaData md) : base(nsName,name,md)
2095 externClass = new ExternClass(attrs,nameSpaceIx,nameIx,declFile);
2096 metaData.AddToTable(MDTable.ExportedType,externClass);
2099 internal ExternClassRef(string name, MetaData md) : base(null,name,md)
2103 public ClassRef AddNestedClass(TypeAttr attrs, string name)
2105 ExternClassRef nestedClass = new ExternClassRef(name,metaData);
2106 externClass = new ExternClass(attrs,0,nameIx,this.externClass);
2107 metaData.AddToTable(MDTable.ExportedType,externClass);
2113 /**************************************************************************/
2115 /// Descriptor for a class defined in another module of THIS assembly
2116 /// and exported (.class extern)
2119 internal class ExternClass : Class {
2121 MetaDataElement parent;
2124 internal ExternClass(TypeAttr attr, uint nsIx, uint nIx,
2125 MetaDataElement paren) : base(nsIx,nIx)
2129 tabIx = MDTable.ExportedType;
2132 internal sealed override uint Size(MetaData md)
2134 return 8 + 2* md.StringsIndexSize() + md.CodedIndexSize(CIx.Implementation);
2137 internal sealed override void Write(FileImage output)
2139 output.Write(flags);
2141 output.StringsIndex(nameIx);
2142 output.StringsIndex(nameSpaceIx);
2143 output.WriteCodedIndex(CIx.Implementation,parent);
2146 internal sealed override uint GetCodedIx(CIx code)
2149 case (CIx.HasCustomAttr) : return 17;
2150 case (CIx.Implementation) : return 2;
2157 public class GenParam : Class {
2160 private string param_name;
2161 private uint sigIx = 0;
2163 public GenParam (int index, string name, GenParamType ptype) : base ((byte) ptype)
2166 this.param_name = name;
2167 tabIx = MDTable.TypeSpec;
2171 get { return index; }
2172 set { index = value; }
2175 public string Name {
2176 get { return param_name; }
2177 set { param_name = value; }
2180 public GenParamType Type {
2181 get { return (GenParamType) GetTypeIndex (); }
2184 internal sealed override void BuildTables (MetaData md)
2188 MemoryStream str = new MemoryStream ();
2190 sigIx = md.AddToBlobHeap (str.ToArray ());
2195 internal sealed override void TypeSig(MemoryStream str)
2198 throw new PEFileException (String.Format ("Unresolved {0} - {1}", (GenParamType) GetTypeIndex (), param_name));
2199 str.WriteByte(typeIndex);
2200 MetaData.CompressNum ((uint) index, str);
2203 internal override uint Size(MetaData md)
2205 return md.BlobIndexSize();
2208 internal sealed override void Write (FileImage output)
2210 output.BlobIndex (sigIx);
2213 internal sealed override uint GetCodedIx(CIx code)
2216 case (CIx.TypeDefOrRef) : return 2;
2217 case (CIx.HasCustomAttr) : return 13;
2218 case (CIx.MemberRefParent) : return 4;
2224 public class GenericTypeInst : Class {
2226 private Type gen_type;
2227 private Type[] gen_param;
2228 bool inTable = false;
2231 public GenericTypeInst (Type gen_type, Type[] gen_param)
2232 : base ((byte) PrimitiveType.GenericInst.GetTypeIndex ())
2234 this.gen_type = gen_type;
2235 this.gen_param = gen_param;
2236 tabIx = MDTable.TypeSpec;
2239 internal override MetaDataElement GetTypeSpec (MetaData md)
2242 md.AddToTable (MDTable.TypeSpec, this);
2249 internal sealed override void TypeSig(MemoryStream str)
2251 str.WriteByte(typeIndex);
2252 gen_type.TypeSig (str);
2253 MetaData.CompressNum ((uint) gen_param.Length, str);
2254 foreach (Type param in gen_param)
2255 param.TypeSig (str);
2258 internal sealed override void BuildTables (MetaData md)
2262 MemoryStream str = new MemoryStream ();
2264 sigIx = md.AddToBlobHeap (str.ToArray ());
2269 internal sealed override uint Size (MetaData md)
2271 return md.BlobIndexSize ();
2274 internal sealed override void Write (FileImage output)
2276 output.BlobIndex (sigIx);
2279 internal sealed override uint GetCodedIx (CIx code)
2282 case (CIx.TypeDefOrRef): return 2;
2283 case (CIx.MemberRefParent): return 4;
2284 case (CIx.HasCustomAttr): return 13;
2290 public class GenericMethodSig {
2292 private Type[] gen_param;
2294 private uint sigIx = 0;
2296 public GenericMethodSig (Type[] gen_param)
2298 this.gen_param = gen_param;
2302 internal void TypeSig (MemoryStream str)
2304 str.WriteByte (0x0A); /* GENERIC_INST */
2305 MetaData.CompressNum ((uint) gen_param.Length, str);
2306 foreach (Type param in gen_param)
2307 param.TypeSig (str);
2310 internal uint GetSigIx (MetaData md)
2315 MemoryStream sig = new MemoryStream();
2317 sigIx = md.AddToBlobHeap (sig.ToArray());
2323 public class Sentinel : Type {
2325 public Sentinel () : base (0x41) { }
2327 internal sealed override void TypeSig(MemoryStream str)
2329 str.WriteByte(typeIndex);
2333 /**************************************************************************/
2335 /// Descriptor for a FunctionPointer type
2338 public class MethPtrType : Type {
2350 /// Create a new function pointer type
2352 /// <param name="meth">the function to be referenced</param>
2353 public MethPtrType (CallConv callconv, Type retType, Type[] pars,
2354 bool varArgMeth, Type[] optPars) : base(0x1B)
2356 this.retType = retType;
2357 callConv = callconv;
2359 this.varArgMeth = varArgMeth;
2360 if (parList != null) numPars = (uint)parList.Length;
2362 optParList = optPars;
2363 if (optParList != null) numOptPars = (uint)optParList.Length;
2364 callConv |= CallConv.Vararg;
2366 tabIx = MDTable.TypeSpec;
2369 internal sealed override void TypeSig(MemoryStream sig)
2371 sig.WriteByte(typeIndex);
2372 // Bootlegged from method ref
2373 sig.WriteByte((byte)callConv);
2374 MetaData.CompressNum (numPars + numOptPars, sig);
2375 retType.TypeSig (sig);
2376 for (int i=0; i < numPars; i++) {
2377 parList[i].TypeSig (sig);
2380 sig.WriteByte (0x41); // Write the sentinel
2381 for (int i=0; i < numOptPars; i++) {
2382 optParList[i].TypeSig (sig);
2387 internal sealed override void BuildTables(MetaData md)
2390 MemoryStream sig = new MemoryStream();
2392 sigIx = md.AddToBlobHeap(sig.ToArray());
2396 internal sealed override uint Size(MetaData md)
2398 return md.BlobIndexSize();
2401 internal sealed override void Write(FileImage output)
2403 output.BlobIndex(sigIx);
2406 internal sealed override uint GetCodedIx(CIx code) { return 0x1B; }
2411 /* Classes for Arrays */
2414 /// The IL Array type
2416 public abstract class Array : Type {
2418 protected Type elemType;
2419 protected MetaData metaData;
2420 protected string cnameSpace, cname;
2422 internal Array(Type eType, byte TypeId) : base(TypeId)
2425 tabIx = MDTable.TypeSpec;
2430 /// Single dimensional array with zero lower bound
2432 public class ZeroBasedArray : Array {
2435 /// Create a new array - elementType[]
2437 /// <param name="elementType">the type of the array elements</param>
2438 public ZeroBasedArray(Type elementType) : base (elementType, PrimitiveType.SZArray.GetTypeIndex ()) { }
2440 internal sealed override void TypeSig(MemoryStream str)
2442 str.WriteByte(typeIndex);
2443 elemType.TypeSig(str);
2449 /// Multi dimensional array with explicit bounds
2451 public class BoundArray : Array {
2457 /// Create a new multi dimensional array type
2458 /// eg. elemType[1..5,3..10,5,,] would be
2459 /// new BoundArray(elemType,5,[1,3,0],[5,10,4])
2461 /// <param name="elementType">the type of the elements</param>
2462 /// <param name="dimensions">the number of dimensions</param>
2463 /// <param name="loBounds">lower bounds of dimensions</param>
2464 /// <param name="sizes">sizes for the dimensions</param>
2465 public BoundArray(Type elementType, uint dimensions, int[] loBounds,
2466 int[] sizes) : base (elementType,0x14)
2468 numDims = dimensions;
2469 lowerBounds = loBounds;
2474 /// Create a new multi dimensional array type
2475 /// eg. elemType[5,10,20] would be new BoundArray(elemType,3,[5,10,20])
2477 /// <param name="elementType">the type of the elements</param>
2478 /// <param name="dimensions">the number of dimensions</param>
2479 /// <param name="size">the sizes of the dimensions</param>
2480 public BoundArray(Type elementType, uint dimensions, int[] size)
2481 : base (elementType,0x14)
2483 numDims = dimensions;
2488 /// Create a new multi dimensional array type
2489 /// eg. elemType[,,] would be new BoundArray(elemType,3)
2491 /// <param name="elementType">the type of the elements</param>
2492 /// <param name="dimensions">the number of dimensions</param>
2493 public BoundArray(Type elementType, uint dimensions)
2494 : base (elementType,0x14)
2496 numDims = dimensions;
2499 internal sealed override void TypeSig(MemoryStream str)
2501 str.WriteByte(typeIndex);
2502 elemType.TypeSig(str);
2503 MetaData.CompressNum(numDims,str);
2504 if ((sizes != null) && (sizes.Length > 0)) {
2506 MetaData.CompressNum((uint)sizes.Length,str);
2507 for (int i=0; i < sizes.Length; i++) {
2508 MetaData.CompressNum((uint)sizes[i],str);
2510 } else str.WriteByte(0);
2511 if ((lowerBounds != null) && (lowerBounds.Length > 0)) {
2512 MetaData.CompressNum((uint)lowerBounds.Length,str);
2513 for (int i=0; i < lowerBounds.Length; i++) {
2514 CompressSignedNum (lowerBounds[i],str);
2516 } else str.WriteByte(0);
2518 private void CompressSignedNum (int val, MemoryStream str)
2520 uint uval = (uint) val;
2527 /* Map the signed number to an unsigned number in two ways.
2529 fval: left-rotated 2's complement representation
2530 sval: map the signed number to unsigned as follows: 0 -> 0, -1 -> 1, 1 -> 2, -2 -> 3, 2 -> 4, ....
2531 the mapping is: x -> 2*|x| - signbit(x)
2533 uint fval = (uval << 1) | sign;
2534 int sval = (val << 1) - sign;
2536 /* An overly clever transformation:
2538 a. sval is used to determine the number of bytes in the compressed representation.
2539 b. fval is truncated to the appropriate number of bits and output using the
2540 normal unsigned-int compressor.
2542 However, or certain values, the truncated fval doesn't carry enough information to round trip.
2544 (fval & 0x3FFF) <= 0x7F => compressor emits 1 byte, not 2 => there is aliasing of values
2546 So, we use full 4 bytes to encode such values.
2548 LAMESPEC: The Microsoft implementation doesn't appear to handle this subtle case.
2549 e.g., it ends up encoding -8192 as the byte 0x01, which decodes to -64
2552 MetaData.CompressNum (fval & 0x7F, str);
2553 else if (sval <= 0x3FFF && (fval & 0x3FFF) > 0x7F)
2554 MetaData.CompressNum (fval & 0x3FFF, str);
2555 else if (sval <= 0x1FFFFFFF && (fval & 0x1FFFFFFF) > 0x3FFF)
2556 MetaData.CompressNum (fval & 0x1FFFFFFF, str);
2558 /* FIXME: number cannot be represented. Report a warning. */
2559 // throw new Exception ("cannot represent signed value" + -val);
2560 MetaData.CompressNum (fval, str);
2567 /* Empty interface for grouping TypeRef's possible ResolutionScope
2568 namely : Module, ModuleRef, AssemblyRef and TypeRef */
2569 public interface IResolutionScope {
2572 /**************************************************************************/
2574 /// Base class for scopes (extended by Module, ModuleRef, Assembly, AssemblyRef)
2576 public abstract class ResolutionScope : MetaDataElement, IResolutionScope {
2578 protected uint nameIx = 0;
2579 protected MetaData metaData;
2580 protected string name;
2582 internal ResolutionScope(string name, MetaData md)
2586 nameIx = md.AddToStringsHeap(name);
2589 internal string GetName() { return name; }
2593 /**************************************************************************/
2595 /// Descriptor for THIS assembly (.assembly)
2597 public class Assembly : ResolutionScope {
2599 ushort majorVer, minorVer, buildNo, revisionNo;
2602 uint keyIx = 0, cultIx = 0;
2603 bool hasPublicKey = false;
2605 internal Assembly(string name, MetaData md) : base(name,md)
2607 tabIx = MDTable.Assembly;
2611 /// Add details about THIS assembly
2613 /// <param name="majVer">Major Version</param>
2614 /// <param name="minVer">Minor Version</param>
2615 /// <param name="bldNo">Build Number</param>
2616 /// <param name="revNo">Revision Number</param>
2617 /// <param name="key">Hash Key</param>
2618 /// <param name="hash">Hash Algorithm</param>
2619 /// <param name="cult">Culture</param>
2620 public void AddAssemblyInfo(int majVer, int minVer, int bldNo, int revNo,
2621 byte[] key, uint hash, string cult)
2623 majorVer = (ushort)majVer;
2624 minorVer = (ushort)minVer;
2625 buildNo = (ushort)bldNo;
2626 revisionNo = (ushort)revNo;
2628 hasPublicKey = (key != null);
2629 keyIx = metaData.AddToBlobHeap(key);
2630 cultIx = metaData.AddToStringsHeap(cult);
2634 /// Add an attribute to THIS assembly
2636 /// <param name="aa">assembly attribute</param>
2637 public void AddAssemblyAttr(AssemAttr aa)
2642 internal sealed override uint Size(MetaData md)
2644 return 16 + md.BlobIndexSize() + 2 * md.StringsIndexSize();
2647 internal sealed override void Write(FileImage output)
2649 // Console.WriteLine("Writing assembly element with nameIx of " + nameIx + " at file offset " + output.Seek(0,SeekOrigin.Current));
2650 output.Write((uint)hashAlgId);
2651 output.Write(majorVer);
2652 output.Write(minorVer);
2653 output.Write(buildNo);
2654 output.Write(revisionNo);
2655 output.Write(flags);
2656 output.BlobIndex(keyIx);
2657 output.StringsIndex(nameIx);
2658 output.StringsIndex(cultIx);
2661 internal sealed override uint GetCodedIx(CIx code)
2664 case (CIx.HasCustomAttr) : return 14;
2665 case (CIx.HasDeclSecurity) : return 2;
2670 internal bool HasPublicKey {
2671 get { return hasPublicKey; }
2675 /**************************************************************************/
2677 /// Descriptor for THIS module
2679 public class Module : ResolutionScope, IExternRef {
2684 internal Module(string name, MetaData md) : base(name,md)
2686 mvid = Guid.NewGuid();
2687 mvidIx = md.AddToGUIDHeap(mvid);
2688 tabIx = MDTable.Module;
2692 get { return mvid; }
2695 public ClassRef AddClass(string nsName, string name)
2697 ClassRef aClass = new ClassRef (nsName, name, metaData);
2698 metaData.AddToTable (MDTable.TypeRef, aClass);
2699 aClass.SetParent (this);
2703 public ClassRef AddValueClass(string nsName, string name)
2705 ClassRef aClass = AddClass (nsName, name);
2706 aClass.MakeValueClass (ValueClass.ValueType);
2710 internal sealed override uint Size(MetaData md)
2712 return 2 + md.StringsIndexSize() + 3 * md.GUIDIndexSize();
2715 internal sealed override void Write(FileImage output)
2717 output.Write((short)0);
2718 output.StringsIndex(nameIx);
2719 output.GUIDIndex(mvidIx);
2720 output.GUIDIndex(0);
2721 output.GUIDIndex(0);
2724 internal sealed override uint GetCodedIx(CIx code)
2727 case (CIx.HasCustomAttr) : return 7;
2728 case (CIx.ResolutionScope) : return 0;
2733 /**************************************************************************/
2735 /// Descriptor for another module in THIS assembly
2737 public class ModuleRef : ResolutionScope, IExternRef {
2739 internal ModuleRef(MetaData md, string name) : base(name,md)
2741 tabIx = MDTable.ModuleRef;
2745 /// Add a class to this external module. This is a class declared in
2746 /// another module of THIS assembly.
2748 /// <param name="nsName">name space name</param>
2749 /// <param name="name">class name</param>
2750 /// <returns>a descriptor for this class in another module</returns>
2751 public ClassRef AddClass(string nsName, string name)
2753 ClassRef aClass = new ClassRef(nsName,name,metaData);
2754 metaData.AddToTable(MDTable.TypeRef,aClass);
2755 aClass.SetParent(this);
2760 /// Make a file descriptor to correspond to this module. The file
2761 /// descriptor will have the same name as the module descriptor
2763 /// <param name="hashBytes">the hash of the file</param>
2764 /// <param name="hasMetaData">the file contains metadata</param>
2765 /// <param name="entryPoint">the program entry point is in this file</param>
2766 /// <returns>a descriptor for the file which contains this module</returns>
2767 public FileRef MakeFile(byte[] hashBytes, bool hasMetaData, bool entryPoint)
2769 FileRef file = new FileRef(nameIx,hashBytes,hasMetaData,entryPoint,metaData);
2770 metaData.AddToTable(MDTable.File,file);
2775 /// Add a value class to this module. This is a class declared in
2776 /// another module of THIS assembly.
2778 /// <param name="nsName">name space name</param>
2779 /// <param name="name">class name</param>
2780 /// <returns></returns>
2781 public ClassRef AddValueClass(string nsName, string name)
2783 ClassRef aClass = new ClassRef(nsName,name,metaData);
2784 metaData.AddToTable(MDTable.TypeRef,aClass);
2785 aClass.SetParent(this);
2786 aClass.MakeValueClass(ValueClass.ValueType);
2791 /// Add a class which is declared public in this external module of
2792 /// THIS assembly. This class will be exported from this assembly.
2793 /// The ilasm syntax for this is .extern class
2795 /// <param name="attrSet">attributes of the class to be exported</param>
2796 /// <param name="nsName">name space name</param>
2797 /// <param name="name">external class name</param>
2798 /// <param name="declFile">the file where the class is declared</param>
2799 /// <param name="isValueClass">is this class a value type?</param>
2800 /// <returns>a descriptor for this external class</returns>
2801 public ExternClassRef AddExternClass(TypeAttr attrSet, string nsName,
2802 string name, FileRef declFile,
2803 bool isValueClass) {
2804 ExternClassRef cRef = new ExternClassRef(attrSet,nsName,name,declFile,metaData);
2805 metaData.AddToTable(MDTable.TypeRef,cRef);
2806 cRef.SetParent(this);
2807 if (isValueClass) cRef.MakeValueClass(ValueClass.ValueType);
2812 /// Add a "global" method in another module
2814 /// <param name="name">method name</param>
2815 /// <param name="retType">return type</param>
2816 /// <param name="pars">method parameter types</param>
2817 /// <returns>a descriptor for this method in anther module</returns>
2818 public MethodRef AddMethod(string name, Type retType, Type[] pars)
2820 MethodRef meth = new MethodRef(this,name,retType,pars,false,null, 0);
2821 metaData.AddToTable(MDTable.MemberRef,meth);
2826 /// Add a vararg method to this class
2828 /// <param name="name">method name</param>
2829 /// <param name="retType">return type</param>
2830 /// <param name="pars">parameter types</param>
2831 /// <param name="optPars">optional param types for this vararg method</param>
2832 /// <returns>a descriptor for this method</returns>
2833 public MethodRef AddVarArgMethod(string name, Type retType,
2834 Type[] pars, Type[] optPars) {
2835 MethodRef meth = new MethodRef(this,name,retType,pars,true,optPars, 0);
2836 metaData.AddToTable(MDTable.MemberRef,meth);
2841 /// Add a field in another module
2843 /// <param name="name">field name</param>
2844 /// <param name="fType">field type</param>
2845 /// <returns>a descriptor for this field in another module</returns>
2846 public FieldRef AddField(string name, Type fType)
2848 FieldRef field = new FieldRef(this,name,fType);
2849 metaData.AddToTable(MDTable.MemberRef,field);
2853 internal sealed override uint Size(MetaData md)
2855 return md.StringsIndexSize();
2858 internal sealed override void Write(FileImage output)
2860 output.StringsIndex(nameIx);
2863 internal sealed override uint GetCodedIx(CIx code)
2866 case (CIx.HasCustomAttr) : return 12;
2867 case (CIx.MemberRefParent) : return 2;
2868 case (CIx.ResolutionScope) : return 1;
2875 #region Classes for Constants
2877 /// Descriptor for a constant value
2879 public abstract class Constant {
2880 protected uint size = 0;
2881 protected Type type;
2882 protected uint blobIndex;
2883 protected bool addedToBlobHeap = false;
2885 internal Constant() { }
2887 internal virtual uint GetBlobIndex(MetaData md) { return 0; }
2889 internal uint GetSize() { return size; }
2891 internal byte GetTypeIndex() { return type.GetTypeIndex(); }
2893 internal virtual void Write(BinaryWriter bw) { }
2897 /// Descriptor for a constant value
2899 public abstract class DataConstant : Constant {
2900 private uint dataOffset = 0;
2902 internal DataConstant() { }
2904 public uint DataOffset {
2905 get { return dataOffset; }
2906 set { dataOffset = value; }
2912 /// Boolean constant
2914 public class BoolConst : Constant {
2918 /// Create a new boolean constant with the value "val"
2920 /// <param name="val">value of this boolean constant</param>
2921 public BoolConst(bool val)
2925 type = PrimitiveType.Boolean;
2928 internal sealed override uint GetBlobIndex(MetaData md)
2930 if (!addedToBlobHeap) {
2931 if (val) blobIndex = md.AddToBlobHeap((sbyte)1);
2932 else blobIndex = md.AddToBlobHeap((sbyte)0);
2933 addedToBlobHeap = true;
2938 internal sealed override void Write(BinaryWriter bw)
2940 if (val) bw.Write((sbyte)1);
2941 else bw.Write((sbyte)0);
2946 public class ByteArrConst : DataConstant {
2949 public ByteArrConst(byte[] val)
2951 type = PrimitiveType.String;
2953 size = (uint)val.Length;
2957 get { return type; }
2958 set { type = value; }
2961 internal sealed override uint GetBlobIndex(MetaData md)
2963 if (!addedToBlobHeap) {
2964 blobIndex = md.AddToBlobHeap(val);
2965 addedToBlobHeap = true;
2970 internal sealed override void Write(BinaryWriter bw)
2977 public class CharConst : Constant {
2980 public CharConst(char val)
2984 type = PrimitiveType.Char;
2987 internal sealed override uint GetBlobIndex(MetaData md)
2989 if (!addedToBlobHeap) {
2990 blobIndex = md.AddToBlobHeap(val);
2991 addedToBlobHeap = true;
2996 internal sealed override void Write(BinaryWriter bw)
3003 public class FloatConst : DataConstant {
3006 public FloatConst(float val)
3010 type = PrimitiveType.Float32;
3013 internal sealed override uint GetBlobIndex(MetaData md)
3015 if (!addedToBlobHeap) {
3016 blobIndex = md.AddToBlobHeap(val);
3017 addedToBlobHeap = true;
3022 internal sealed override void Write(BinaryWriter bw)
3029 public class DoubleConst : DataConstant {
3032 public DoubleConst(double val)
3036 type = PrimitiveType.Float64;
3039 internal sealed override uint GetBlobIndex(MetaData md)
3041 if (!addedToBlobHeap) {
3042 blobIndex = md.AddToBlobHeap(val);
3043 addedToBlobHeap = true;
3048 internal sealed override void Write(BinaryWriter bw)
3055 public class IntConst : DataConstant {
3058 public IntConst(sbyte val)
3062 type = PrimitiveType.Int8;
3065 public IntConst(short val)
3069 type = PrimitiveType.Int16;
3072 public IntConst(int val)
3076 type = PrimitiveType.Int32;
3079 public IntConst(long val)
3083 type = PrimitiveType.Int64;
3086 internal sealed override uint GetBlobIndex(MetaData md)
3088 if (!addedToBlobHeap) {
3090 case (1) : blobIndex = md.AddToBlobHeap((sbyte)val); break;
3091 case (2) : blobIndex = md.AddToBlobHeap((short)val); break;
3092 case (4) : blobIndex = md.AddToBlobHeap((int)val); break;
3093 default : blobIndex = md.AddToBlobHeap(val); break;
3095 addedToBlobHeap = true;
3100 internal sealed override void Write(BinaryWriter bw)
3103 case (1) : bw.Write((sbyte)val); break;
3104 case (2) : bw.Write((short)val); break;
3105 case (4) : bw.Write((int)val); break;
3106 default : bw.Write(val); break;
3112 public class UIntConst : Constant {
3115 public UIntConst(byte val)
3119 type = PrimitiveType.UInt8;
3121 public UIntConst(ushort val)
3125 type = PrimitiveType.UInt16;
3127 public UIntConst(uint val)
3131 type = PrimitiveType.UInt32;
3133 public UIntConst(ulong val)
3137 type = PrimitiveType.UInt64;
3140 internal sealed override uint GetBlobIndex(MetaData md)
3142 if (!addedToBlobHeap) {
3144 case (1) : blobIndex = md.AddToBlobHeap((byte)val); break;
3145 case (2) : blobIndex = md.AddToBlobHeap((ushort)val); break;
3146 case (4) : blobIndex = md.AddToBlobHeap((uint)val); break;
3147 default : blobIndex = md.AddToBlobHeap(val); break;
3149 addedToBlobHeap = true;
3154 internal sealed override void Write(BinaryWriter bw)
3157 case (1) : bw.Write((byte)val); break;
3158 case (2) : bw.Write((ushort)val); break;
3159 case (4) : bw.Write((uint)val); break;
3160 default : bw.Write(val); break;
3166 public class StringConst : DataConstant {
3169 public StringConst(string val)
3172 size = (uint)val.Length; // need to add null ??
3173 type = PrimitiveType.String;
3176 internal sealed override uint GetBlobIndex(MetaData md)
3178 if (!addedToBlobHeap) {
3179 byte [] b = Encoding.Unicode.GetBytes (val);
3180 blobIndex = md.AddToBlobHeap(b);
3181 addedToBlobHeap = true;
3186 internal sealed override void Write(BinaryWriter bw)
3193 public class NullConst : Constant {
3198 type = PrimitiveType.Class;
3201 internal sealed override uint GetBlobIndex(MetaData md)
3203 if (!addedToBlobHeap) {
3204 blobIndex = md.AddToBlobHeap((int)0);
3205 addedToBlobHeap = true;
3210 internal sealed override void Write(BinaryWriter bw)
3217 public class AddressConstant : DataConstant {
3220 public AddressConstant(DataConstant dConst)
3224 type = PrimitiveType.TypedRef;
3227 internal sealed override void Write(BinaryWriter bw)
3229 ((FileImage)bw).WriteDataRVA(data.DataOffset);
3234 public class RepeatedConstant : DataConstant {
3238 public RepeatedConstant(DataConstant dConst, int repeatCount)
3241 repCount = (uint)repeatCount;
3242 int[] sizes = new int[1];
3243 sizes[0] = repeatCount;
3244 type = new BoundArray(type,1,sizes);
3245 size = data.GetSize() * repCount;
3248 internal sealed override void Write(BinaryWriter bw)
3250 for (int i=0; i < repCount; i++) {
3257 public class ArrayConstant : DataConstant {
3258 DataConstant[] dataVals;
3260 public ArrayConstant(DataConstant[] dVals)
3263 for (int i=0; i < dataVals.Length; i++) {
3264 size += dataVals[i].GetSize();
3268 internal sealed override void Write(BinaryWriter bw)
3270 for (int i=0; i < dataVals.Length; i++) {
3271 dataVals[i].Write(bw);
3277 public class ClassType : Constant {
3281 public ClassType(string className)
3284 type = PrimitiveType.ClassType;
3287 public ClassType(Class classDesc)
3290 type = PrimitiveType.ClassType;
3293 internal override void Write(BinaryWriter bw)
3295 if (name == null) name = desc.TypeName();
3303 /**************************************************************************/
3305 /// Descriptor for a custom modifier of a type (modopt or modreq)
3308 public class CustomModifiedType : Type {
3314 /// Create a new custom modifier for a type
3316 /// <param name="type">the type to be modified</param>
3317 /// <param name="cmod">the modifier</param>
3318 /// <param name="cmodType">the type reference to be associated with the type</param>
3319 public CustomModifiedType(Type type, CustomModifier cmod, Class cmodType)
3323 this.cmodType = cmodType;
3326 internal sealed override void TypeSig(MemoryStream str)
3328 str.WriteByte(typeIndex);
3329 MetaData.CompressNum(cmodType.TypeDefOrRefToken(),str);
3335 /**************************************************************************/
3337 /// Base class for Event and Property descriptors
3340 public class Feature : MetaDataElement {
3342 internal enum MethodType : ushort { Setter = 0x01, Getter, Other = 0x04, AddOn = 0x08,
3343 RemoveOn = 0x10, Fire = 0x20 }
3345 private static readonly int INITSIZE = 5;
3346 private static readonly ushort specialName = 0x200;
3347 private static readonly ushort rtSpecialName = 0x400;
3349 protected ClassDef parent;
3350 protected ushort flags = 0;
3351 protected string name;
3352 protected int tide = 0;
3353 protected uint nameIx;
3354 protected MethodSemantics[] methods = new MethodSemantics[INITSIZE];
3356 internal Feature(string name, ClassDef par)
3362 internal void AddMethod(MethodDef meth, MethodType mType)
3364 if (tide >= methods.Length) {
3365 int len = methods.Length;
3366 MethodSemantics[] mTmp = methods;
3367 methods = new MethodSemantics[len * 2];
3368 for (int i=0; i < len; i++) {
3369 methods[i] = mTmp[i];
3372 methods[tide++] = new MethodSemantics(mType,meth,this);
3376 /// Set the specialName attribute for this Event or Property
3378 public void SetSpecialName()
3380 flags |= specialName;
3384 /// Set the RTSpecialName attribute for this Event or Property
3386 public void SetRTSpecialName()
3388 flags |= rtSpecialName;
3393 /**************************************************************************/
3395 /// Descriptor for an event
3397 public class Event : Feature {
3401 internal Event(string name, Type eType, ClassDef parent)
3402 : base(name, parent)
3405 tabIx = MDTable.Event;
3409 /// Add the addon method to this event
3411 /// <param name="addon">the addon method</param>
3412 public void AddAddon(MethodDef addon)
3414 AddMethod(addon,MethodType.AddOn);
3418 /// Add the removeon method to this event
3420 /// <param name="removeOn">the removeon method</param>
3421 public void AddRemoveOn(MethodDef removeOn)
3423 AddMethod(removeOn,MethodType.RemoveOn);
3427 /// Add the fire method to this event
3429 /// <param name="fire">the fire method</param>
3430 public void AddFire(MethodDef fire)
3432 AddMethod(fire,MethodType.Fire);
3436 /// Add another method to this event
3438 /// <param name="other">the method to be added</param>
3439 public void AddOther(MethodDef other)
3441 AddMethod(other,MethodType.Other);
3444 internal sealed override void BuildTables(MetaData md)
3447 nameIx = md.AddToStringsHeap(name);
3448 for (int i=0; i < tide; i++) {
3449 md.AddToTable(MDTable.MethodSemantics,methods[i]);
3454 internal sealed override uint Size(MetaData md)
3456 return 2 + md.StringsIndexSize() + md.CodedIndexSize(CIx.TypeDefOrRef);
3459 internal sealed override void Write(FileImage output)
3461 output.Write(flags);
3462 output.StringsIndex(nameIx);
3463 output.WriteCodedIndex(CIx.TypeDefOrRef,eventType);
3466 internal sealed override uint GetCodedIx(CIx code)
3469 case (CIx.HasCustomAttr) : return 10;
3470 case (CIx.HasSemantics) : return 0;
3477 /**************************************************************************/
3479 /// Descriptor for the Property of a class
3481 public class Property : Feature {
3483 private static readonly byte PropertyTag = 0x8;
3484 private bool instance;
3485 MethodDef getterMeth;
3486 ConstantElem constVal;
3487 uint typeBlobIx = 0;
3492 internal Property(string name, Type retType, Type[] pars, ClassDef parent) : base(name, parent)
3494 returnType = retType;
3496 if (pars != null) numPars = (uint)pars.Length;
3497 tabIx = MDTable.Property;
3501 /// Add a set method to this property
3503 /// <param name="setter">the set method</param>
3504 public void AddSetter(MethodDef setter)
3506 AddMethod(setter,MethodType.Setter);
3510 /// Add a get method to this property
3512 /// <param name="getter">the get method</param>
3513 public void AddGetter(MethodDef getter)
3515 AddMethod(getter,MethodType.Getter);
3516 getterMeth = getter;
3520 /// Add another method to this property
3522 /// <param name="other">the method</param>
3523 public void AddOther(MethodDef other)
3525 AddMethod(other,MethodType.Other);
3529 /// Add an initial value for this property
3531 /// <param name="constVal">the initial value for this property</param>
3532 public void AddInitValue(Constant constVal)
3534 this.constVal = new ConstantElem(this,constVal);
3537 public void SetInstance (bool isInstance)
3539 this.instance = isInstance;
3542 internal sealed override void BuildTables(MetaData md)
3545 nameIx = md.AddToStringsHeap(name);
3546 MemoryStream sig = new MemoryStream();
3547 byte tag = PropertyTag;
3551 MetaData.CompressNum(numPars,sig);
3552 returnType.TypeSig(sig);
3553 for (int i=0; i < numPars; i++) {
3554 parList[i].TypeSig(sig);
3556 typeBlobIx = md.AddToBlobHeap(sig.ToArray());
3557 for (int i=0; i < tide; i++) {
3558 md.AddToTable(MDTable.MethodSemantics,methods[i]);
3560 if (constVal != null) {
3561 md.AddToTable(MDTable.Constant,constVal);
3562 constVal.BuildTables(md);
3567 internal sealed override uint Size(MetaData md)
3569 return 2 + md.StringsIndexSize() + md.BlobIndexSize();
3572 internal sealed override void Write(FileImage output)
3574 output.Write(flags);
3575 output.StringsIndex(nameIx);
3576 output.BlobIndex(typeBlobIx);
3579 internal sealed override uint GetCodedIx(CIx code)
3582 case (CIx.HasCustomAttr) : return 9;
3583 case (CIx.HasConst) : return 2;
3584 case (CIx.HasSemantics) : return 1;
3591 /**************************************************************************/
3593 /// Base class for field/methods (member of a class)
3595 public abstract class Member : MetaDataElement {
3597 protected string name;
3598 protected uint nameIx = 0, sigIx = 0;
3600 internal Member(string memName)
3603 tabIx = MDTable.MemberRef;
3608 /*****************************************************************************/
3610 /// Descriptor for a field of a class
3613 public abstract class Field : Member {
3615 protected static readonly byte FieldSig = 0x6;
3617 protected Type type;
3619 internal Field(string pfName, Type pfType) : base(pfName)
3625 /**************************************************************************/
3627 /// Descriptor for a field defined in a class of THIS assembly/module
3629 public class FieldDef : Field {
3631 //private static readonly uint PInvokeImpl = 0x2000;
3632 private static readonly ushort HasFieldRVA = 0x100;
3633 private static readonly ushort HasDefault = 0x8000;
3636 ConstantElem constVal;
3638 FieldMarshal marshalInfo;
3641 internal FieldDef(string name, Type fType) : base(name,fType)
3643 tabIx = MDTable.Field;
3646 internal FieldDef(FieldAttr attrSet, string name, Type fType) : base(name, fType)
3648 flags = (ushort)attrSet;
3649 tabIx = MDTable.Field;
3653 /// Add an attribute(s) to this field
3655 /// <param name="fa">the attribute(s) to be added</param>
3656 public void AddFieldAttr(FieldAttr fa)
3658 flags |= (ushort)fa;
3662 /// Add a value for this field
3664 /// <param name="val">the value for the field</param>
3665 public void AddValue(Constant val)
3667 constVal = new ConstantElem(this,val);
3668 flags |= HasDefault;
3672 /// Add an initial value for this field (at dataLabel) (.data)
3674 /// <param name="val">the value for the field</param>
3675 /// <param name="repeatVal">the number of repetitions of this value</param>
3676 public void AddDataValue(DataConstant val)
3678 flags |= HasFieldRVA;
3679 rva = new FieldRVA(this,val);
3683 /// Set the offset of the field. Used for sequential or explicit classes.
3686 /// <param name="offs">field offset</param>
3687 public void SetOffset(uint offs)
3689 layout = new FieldLayout(this,offs);
3693 /// Set the marshalling info for a field
3695 /// <param name="mInf"></param>
3696 public void SetMarshalInfo(NativeType marshallType)
3698 flags |= (ushort) FieldAttr.HasFieldMarshal;
3699 marshalInfo = new FieldMarshal(this,marshallType);
3702 internal sealed override void BuildTables(MetaData md)
3705 nameIx = md.AddToStringsHeap(name);
3706 MemoryStream sig = new MemoryStream();
3707 sig.WriteByte(FieldSig);
3709 sigIx = md.AddToBlobHeap(sig.ToArray());
3711 md.AddToTable(MDTable.FieldRVA,rva);
3712 rva.BuildTables(md);
3713 } else if (constVal != null) {
3714 md.AddToTable(MDTable.Constant,constVal);
3715 constVal.BuildTables(md);
3717 if (layout != null) md.AddToTable(MDTable.FieldLayout,layout);
3718 if (marshalInfo != null) {
3719 md.AddToTable(MDTable.FieldMarshal,marshalInfo);
3720 marshalInfo.BuildTables(md);
3725 internal sealed override uint Size(MetaData md)
3727 return 2 + md.StringsIndexSize() + md.BlobIndexSize();
3730 internal sealed override void Write(FileImage output)
3732 output.Write(flags);
3733 output.StringsIndex(nameIx);
3734 output.BlobIndex(sigIx);
3737 internal sealed override uint GetCodedIx(CIx code)
3740 case (CIx.HasConst) : return 0;
3741 case (CIx.HasCustomAttr) : return 1;
3742 case (CIx.HasFieldMarshal) : return 0;
3743 case (CIx.MemberForwarded) : return 0;
3750 /**************************************************************************/
3752 /// Descriptor for a field of a class defined in another assembly/module
3754 public class FieldRef : Field {
3756 MetaDataElement parent;
3758 internal FieldRef(MetaDataElement paren, string name, Type fType) : base(name, fType)
3763 internal sealed override void BuildTables(MetaData md)
3766 nameIx = md.AddToStringsHeap(name);
3767 MemoryStream sig = new MemoryStream();
3768 sig.WriteByte(FieldSig);
3770 sigIx = md.AddToBlobHeap(sig.ToArray());
3774 internal sealed override uint Size(MetaData md)
3776 return md.CodedIndexSize(CIx.MemberRefParent) + md.StringsIndexSize() + md.BlobIndexSize();
3779 internal sealed override void Write(FileImage output)
3781 output.WriteCodedIndex(CIx.MemberRefParent,parent);
3782 output.StringsIndex(nameIx);
3783 output.BlobIndex(sigIx);
3786 internal sealed override uint GetCodedIx(CIx code) { return 6; }
3790 /**************************************************************************/
3792 /// Base class for Method Descriptors
3795 public abstract class Method : Member {
3797 internal Method (string methName) : base (methName)
3800 public abstract void AddCallConv(CallConv cconv);
3801 internal abstract void TypeSig(MemoryStream sig);
3802 internal abstract uint GetSigIx(MetaData md);
3805 /**************************************************************************/
3807 /// Descriptor for a method defined in THIS assembly/module
3811 public class MethodDef : Method {
3813 private static readonly ushort PInvokeImpl = 0x2000;
3814 //private static readonly uint UnmanagedExport = 0x0008;
3815 // private static readonly byte LocalSigByte = 0x7;
3816 uint parIx = 0, textOffset = 0;
3817 private CallConv callConv = CallConv.Default;
3818 private int gen_param_count;
3821 CILInstructions code;
3825 ushort methFlags = 0, implFlags = 0;
3826 int maxStack = 0, numPars = 0;
3827 bool entryPoint = false;
3829 ArrayList varArgSigList;
3830 ImplMap pinvokeImpl;
3833 internal MethodDef (MetaData md, string name, Param ret_param, Param [] pars)
3834 : this (md, 0, 0, name, ret_param, pars)
3838 internal MethodDef (MetaData md, MethAttr mAttrSet, ImplAttr iAttrSet, string name,
3839 Param ret_param, Param [] pars)
3842 methFlags = (ushort)mAttrSet;
3843 implFlags = (ushort)iAttrSet;
3844 this.ret_param = ret_param;
3847 if (parList != null)
3848 numPars = parList.Length;
3849 tabIx = MDTable.Method;
3852 internal Param[] GetPars()
3857 internal override uint GetSigIx(MetaData md)
3859 MemoryStream sig = new MemoryStream();
3861 return md.AddToBlobHeap(sig.ToArray());
3864 public override void AddCallConv(CallConv cconv)
3870 /// Add some attributes to this method descriptor
3872 /// <param name="ma">the attributes to be added</param>
3873 public void AddMethAttribute(MethAttr ma)
3875 methFlags |= (ushort)ma;
3879 /// Add some implementation attributes to this method descriptor
3881 /// <param name="ia">the attributes to be added</param>
3882 public void AddImplAttribute(ImplAttr ia)
3884 implFlags |= (ushort)ia;
3887 public void AddPInvokeInfo(ModuleRef scope, string methName,
3888 PInvokeAttr callAttr) {
3889 pinvokeImpl = new ImplMap((ushort)callAttr,this,methName,scope);
3890 methFlags |= PInvokeImpl;
3894 /// Add a named generic type parameter
3896 public GenericParameter AddGenericParameter (short index, string name)
3898 return AddGenericParameter (index, name, 0);
3902 /// Add a named generic type parameter with attributes
3904 public GenericParameter AddGenericParameter (short index, string name, GenericParamAttributes attr)
3906 GenericParameter gp = new GenericParameter (this, metaData, index, name, attr);
3907 metaData.AddToTable (MDTable.GenericParam, gp);
3913 /// Set the maximum stack height for this method
3915 /// <param name="maxStack">the maximum height of the stack</param>
3916 public void SetMaxStack(int maxStack)
3918 this.maxStack = maxStack;
3922 /// Add local variables to this method
3924 /// <param name="locals">the locals to be added</param>
3925 /// <param name="initLocals">are locals initialised to default values</param>
3926 public void AddLocals(Local[] locals, bool initLocals)
3928 this.locals = locals;
3929 this.initLocals = initLocals;
3932 /* Add Marshal info for return type */
3933 public void AddRetTypeMarshallInfo (NativeType marshallType)
3935 ret_param.AddMarshallInfo (marshallType);
3939 /// Mark this method as having an entry point
3941 public void DeclareEntryPoint()
3947 /// Create a code buffer for this method to add the IL instructions to
3949 /// <returns>a buffer for this method's IL instructions</returns>
3950 public CILInstructions CreateCodeBuffer()
3952 code = new CILInstructions(metaData);
3957 /// Make a method reference descriptor for this method to be used
3958 /// as a callsite signature for this vararg method
3960 /// <param name="optPars">the optional pars for the vararg method call</param>
3961 /// <returns></returns>
3962 public MethodRef MakeVarArgSignature(Type[] optPars)
3964 Type[] pars = new Type[numPars];
3965 MethodRef varArgSig;
3966 for (int i=0; i < numPars; i++) {
3967 pars[i] = parList[i].GetParType();
3969 varArgSig = new MethodRef (this, name, ret_param.GetParType (), pars, true, optPars, 0);
3971 if (varArgSigList == null)
3972 varArgSigList = new ArrayList ();
3973 varArgSigList.Add (varArgSig);
3977 internal sealed override void TypeSig(MemoryStream sig)
3979 sig.WriteByte((byte)callConv);
3980 if ((callConv & CallConv.Generic) == CallConv.Generic)
3981 MetaData.CompressNum ((uint) gen_param_count, sig);
3982 MetaData.CompressNum((uint)numPars,sig);
3984 ret_param.seqNo = 0;
3985 ret_param.TypeSig (sig);
3986 for (ushort i=0; i < numPars; i++) {
3987 parList[i].seqNo = (ushort)(i+1);
3988 parList[i].TypeSig(sig);
3992 internal sealed override void BuildTables(MetaData md)
3995 if (pinvokeImpl != null) {
3996 md.AddToTable(MDTable.ImplMap,pinvokeImpl);
3997 pinvokeImpl.BuildTables(md);
3999 if (entryPoint) md.SetEntryPoint(this);
4001 if (locals != null) {
4002 localSig = new LocalSig(locals);
4003 md.AddToTable(MDTable.StandAloneSig,localSig);
4004 localSig.BuildTables(md);
4005 locToken = localSig.Token();
4008 code.CheckCode(locToken,initLocals,maxStack);
4009 textOffset = md.AddCode(code);
4011 nameIx = md.AddToStringsHeap(name);
4012 sigIx = GetSigIx(md);
4013 parIx = md.TableIndex(MDTable.Param);
4014 if (ret_param.HasMarshalInfo || ret_param.HasCustomAttr) {
4015 md.AddToTable(MDTable.Param, ret_param);
4016 ret_param.BuildTables(md);
4018 for (int i=0; i < numPars; i++) {
4019 md.AddToTable(MDTable.Param,parList[i]);
4020 parList[i].BuildTables(md);
4022 if (varArgSigList != null) {
4023 foreach (MethodRef varArgSig in varArgSigList) {
4024 md.AddToTable(MDTable.MemberRef,varArgSig);
4025 varArgSig.BuildTables(md);
4028 // Console.WriteLine("method has " + numPars + " parameters");
4032 internal sealed override uint Size(MetaData md)
4034 return 8 + md.StringsIndexSize() + md.BlobIndexSize() + md.TableIndexSize(MDTable.Param);
4037 internal sealed override void Write(FileImage output)
4039 if (ZeroRva ()) output.Write(0);
4040 else output.WriteCodeRVA(textOffset);
4041 output.Write(implFlags);
4042 output.Write(methFlags);
4043 output.StringsIndex(nameIx);
4044 output.BlobIndex(sigIx);
4045 output.WriteIndex(MDTable.Param,parIx);
4048 internal bool ZeroRva ()
4050 return (((methFlags & (ushort)MethAttr.Abstract) != 0) ||
4051 ((implFlags & (ushort)ImplAttr.Runtime) != 0) ||
4052 ((implFlags & (ushort)ImplAttr.InternalCall) != 0) ||
4053 (pinvokeImpl != null)); // TODO: Not entirely true but works for now
4056 internal sealed override uint GetCodedIx(CIx code)
4059 case (CIx.HasCustomAttr) : return 0;
4060 case (CIx.HasDeclSecurity) : return 1;
4061 case (CIx.MemberRefParent) : return 3;
4062 case (CIx.MethodDefOrRef) : return 0;
4063 case (CIx.MemberForwarded) : return 1;
4064 case (CIx.CustomAttributeType) : return 2;
4065 case (CIx.TypeOrMethodDef) : return 1;
4071 /**************************************************************************/
4073 /// Descriptor for a method defined in another assembly/module
4075 public class MethodRef : Method {
4077 private static readonly byte Sentinel = 0x41;
4078 Type[] parList, optParList;
4079 MetaDataElement parent;
4080 uint numPars = 0, numOptPars = 0;
4081 CallConv callConv = CallConv.Default;
4083 int gen_param_count;
4085 internal MethodRef(MetaDataElement paren, string name, Type retType,
4086 Type[] pars, bool varArgMeth, Type[] optPars, int gen_param_count) : base(name)
4090 this.retType = retType;
4091 if (parList != null) numPars = (uint)parList.Length;
4093 optParList = optPars;
4094 if (optParList != null) numOptPars = (uint)optParList.Length;
4095 callConv = CallConv.Vararg;
4097 this.gen_param_count = gen_param_count;
4100 internal override uint GetSigIx(MetaData md)
4102 MemoryStream sig = new MemoryStream();
4104 return md.AddToBlobHeap(sig.ToArray());
4107 public override void AddCallConv(CallConv cconv)
4112 internal sealed override void TypeSig(MemoryStream sig)
4114 sig.WriteByte((byte)callConv);
4115 if ((callConv & CallConv.Generic) == CallConv.Generic)
4116 MetaData.CompressNum ((uint) gen_param_count, sig);
4117 MetaData.CompressNum(numPars+numOptPars,sig);
4118 retType.TypeSig(sig);
4119 for (int i=0; i < numPars; i++) {
4120 parList[i].TypeSig(sig);
4122 if (numOptPars > 0) {
4123 sig.WriteByte(Sentinel);
4124 for (int i=0; i < numOptPars; i++) {
4125 optParList[i].TypeSig(sig);
4130 internal sealed override void BuildTables(MetaData md)
4133 nameIx = md.AddToStringsHeap(name);
4134 sigIx = GetSigIx(md);
4138 internal sealed override uint Size(MetaData md)
4140 return md.CodedIndexSize(CIx.MemberRefParent) + md.StringsIndexSize() + md.BlobIndexSize();
4143 internal sealed override void Write(FileImage output)
4145 output.WriteCodedIndex(CIx.MemberRefParent,parent);
4146 output.StringsIndex(nameIx);
4147 output.BlobIndex(sigIx);
4150 internal sealed override uint GetCodedIx(CIx code)
4153 case (CIx.HasCustomAttr) : return 6;
4154 case (CIx.MethodDefOrRef) : return 1;
4155 case (CIx.CustomAttributeType) : return 3;
4163 /**************************************************************************/
4165 /// Descriptors for native types used for marshalling
4167 public class NativeType {
4168 public static readonly NativeType Void = new NativeType(0x01);
4169 public static readonly NativeType Boolean = new NativeType(0x02);
4170 public static readonly NativeType Int8 = new NativeType(0x03);
4171 public static readonly NativeType UInt8 = new NativeType(0x04);
4172 public static readonly NativeType Int16 = new NativeType(0x05);
4173 public static readonly NativeType UInt16 = new NativeType(0x06);
4174 public static readonly NativeType Int32 = new NativeType(0x07);
4175 public static readonly NativeType UInt32 = new NativeType(0x08);
4176 public static readonly NativeType Int64 = new NativeType(0x09);
4177 public static readonly NativeType UInt64 = new NativeType(0x0A);
4178 public static readonly NativeType Float32 = new NativeType(0x0B);
4179 public static readonly NativeType Float64 = new NativeType(0x0C);
4180 public static readonly NativeType Currency = new NativeType(0x0F);
4181 public static readonly NativeType BStr = new NativeType(0x13);
4182 public static readonly NativeType LPStr = new NativeType(0x14);
4183 public static readonly NativeType LPWStr = new NativeType(0x15);
4184 public static readonly NativeType LPTStr = new NativeType(0x16);
4185 public static readonly NativeType FixedSysString = new NativeType(0x17);
4186 public static readonly NativeType IUnknown = new NativeType(0x19);
4187 public static readonly NativeType IDispatch = new NativeType(0x1A);
4188 public static readonly NativeType Struct = new NativeType(0x1B);
4189 public static readonly NativeType Interface = new NativeType(0x1C);
4190 public static readonly NativeType Int = new NativeType(0x1F);
4191 public static readonly NativeType UInt = new NativeType(0x20);
4192 public static readonly NativeType ByValStr = new NativeType(0x22);
4193 public static readonly NativeType AnsiBStr = new NativeType(0x23);
4194 public static readonly NativeType TBstr = new NativeType(0x24);
4195 public static readonly NativeType VariantBool = new NativeType(0x25);
4196 public static readonly NativeType FuncPtr = new NativeType(0x26);
4197 public static readonly NativeType AsAny = new NativeType(0x28);
4198 public static readonly NativeType LPStruct = new NativeType(0x2b);
4199 public static readonly NativeType Error = new NativeType(0x2d);
4201 protected byte typeIndex;
4203 internal NativeType(byte tyIx) { typeIndex = tyIx; }
4204 internal byte GetTypeIndex() { return typeIndex; }
4206 internal virtual byte[] ToBlob()
4208 byte[] bytes = new byte[1];
4209 bytes[0] = GetTypeIndex();
4215 public class FixedSysString : NativeType {
4219 public FixedSysString (uint size) : base (NativeType.FixedSysString.GetTypeIndex ())
4224 internal override byte [] ToBlob ()
4226 MemoryStream str = new MemoryStream ();
4227 str.WriteByte (GetTypeIndex ());
4228 MetaData.CompressNum (size, str);
4229 return str.ToArray ();
4234 public class NativeArray : NativeType {
4236 NativeType elemType;
4237 int numElem = -1, parNum = -1, elemMult = -1;
4239 public NativeArray(NativeType elemType) : this (elemType, -1, -1, -1)
4241 this.elemType = elemType;
4244 /* public NativeArray(NativeType elemType, int len) : base(0x2A) {
4245 this.elemType = elemType;
4250 public NativeArray(NativeType elemType, int numElem, int parNumForLen, int elemMult) : base(0x2A)
4252 this.elemType = elemType;
4253 this.numElem = numElem;
4254 parNum = parNumForLen;
4255 this.elemMult = elemMult;
4258 public NativeArray(NativeType elemType, int numElem, int parNumForLen)
4259 : this (elemType, numElem, parNumForLen, -1)
4263 internal override byte[] ToBlob()
4265 MemoryStream str = new MemoryStream();
4266 str.WriteByte(GetTypeIndex());
4267 if (elemType == null) str.WriteByte(0x50); // no info (MAX)
4268 else str.WriteByte(elemType.GetTypeIndex());
4270 /* see : mono/metadata/metadata.c:mono_metadata_parse_marshal_spec
4271 * LAMESPEC: Older spec versions say elemMult comes before
4272 * len. Newer spec versions don't talk about elemMult at
4273 * all, but csc still emits it, and it is used to distinguish
4274 * between parNum being 0, and parNum being omitted.
4279 return str.ToArray ();
4281 MetaData.CompressNum((uint) parNum,str);
4282 if (numElem != -1) {
4283 MetaData.CompressNum ((uint) numElem, str);
4285 // <native_type> [ int32 ]
4286 MetaData.CompressNum((uint) elemMult,str);
4287 //else <native_type> [ int32 + int32 ]
4288 } else if (elemMult != -1) {
4289 // When can this occur ?
4290 MetaData.CompressNum (0, str);
4291 MetaData.CompressNum((uint) elemMult,str);
4293 //else <native_type> [ + int32 ]
4295 return str.ToArray();
4300 public class SafeArray : NativeType {
4302 SafeArrayType elemType;
4305 public SafeArray() : base(0x1D)
4309 public SafeArray(SafeArrayType elemType) : base(0x1D)
4311 this.elemType = elemType;
4315 internal override byte[] ToBlob()
4317 byte[] bytes = new byte[hasElemType ? 2 : 1];
4318 bytes[0] = GetTypeIndex();
4320 bytes[1] = (byte)elemType;
4326 public class FixedArray : NativeType {
4330 //public FixedArray(NativeType elemType, int numElems) : base(0x1E) {
4331 public FixedArray(int numElems) : base(0x1E)
4333 //this.elemType = elemType;
4334 numElem = (uint)numElems;
4337 internal override byte[] ToBlob()
4339 MemoryStream str = new MemoryStream();
4340 str.WriteByte(GetTypeIndex());
4341 MetaData.CompressNum(numElem,str);
4343 fixed array [5] lpstr [2]
4344 This format is not supported by ilasm 1.1.4322.2032,
4345 but is supported by 2.0.5125..
4346 ilasm 1.1 only supports "fixed array [5]"
4347 if (elemType == null) str.WriteByte(0x50); // no info (MAX)
4348 else str.WriteByte(elemType.GetTypeIndex());*/
4350 return str.ToArray();
4355 public class CustomMarshaller : NativeType {
4358 string marshallerName;
4361 public CustomMarshaller(string typeNameOrGUID, string marshallerName,
4362 string optCookie) : base(0x2C)
4364 typeName = typeNameOrGUID;
4365 this.marshallerName = marshallerName;
4369 public CustomMarshaller(string marshallerName, string optCookie)
4370 :this (null, marshallerName, optCookie)
4374 internal override byte[] ToBlob()
4376 MemoryStream str = new MemoryStream();
4377 BinaryWriter bw = new BinaryWriter(str,new UTF8Encoding());
4378 bw.Write(GetTypeIndex());
4379 //Native type name & unmanaged type - unused
4380 //See mono/metadata/metadata.c : mono_metadata_parse_marshal_spec
4381 bw.Write ((byte) 0); // Native Type name, unused
4382 bw.Write ((byte) 0); // Unmanaged type, unused
4383 if (marshallerName != null) {
4384 MetaData.CompressNum ((uint)marshallerName.Length, str);
4385 bw.Write(marshallerName.ToCharArray());
4387 bw.Write ((byte) 0);
4389 if (cookie != null) {
4390 MetaData.CompressNum ((uint)cookie.Length, str);
4391 bw.Write(cookie.ToCharArray());
4393 bw.Write ((byte) 0);
4396 return str.ToArray();
4400 /**************************************************************************/
4402 /// Descriptor for the Primitive types defined in IL
4404 public class PrimitiveType : Type {
4406 private string name;
4407 private int systemTypeIndex;
4408 public static int NumSystemTypes = 18;
4410 public static readonly PrimitiveType Void = new PrimitiveType(0x01,"Void",0);
4411 public static readonly PrimitiveType Boolean = new PrimitiveType(0x02,"Boolean",1);
4412 public static readonly PrimitiveType Char = new PrimitiveType(0x03,"Char",2);
4413 public static readonly PrimitiveType Int8 = new PrimitiveType(0x04,"SByte",3);
4414 public static readonly PrimitiveType UInt8 = new PrimitiveType(0x05,"Byte",4);
4415 public static readonly PrimitiveType Int16 = new PrimitiveType(0x06,"Int16",5);
4416 public static readonly PrimitiveType UInt16 = new PrimitiveType(0x07,"UInt16",6);
4417 public static readonly PrimitiveType Int32 = new PrimitiveType(0x08,"Int32",7);
4418 public static readonly PrimitiveType UInt32 = new PrimitiveType(0x09,"UInt32",8);
4419 public static readonly PrimitiveType Int64 = new PrimitiveType(0x0A,"Int64",9);
4420 public static readonly PrimitiveType UInt64 = new PrimitiveType(0x0B,"UInt64",10);
4421 public static readonly PrimitiveType Float32 = new PrimitiveType(0x0C,"Single",11);
4422 public static readonly PrimitiveType Float64 = new PrimitiveType(0x0D,"Double",12);
4423 public static readonly PrimitiveType String = new PrimitiveType(0x0E,"String",13);
4424 internal static readonly PrimitiveType Class = new PrimitiveType(0x12);
4425 internal static readonly PrimitiveType Var = new PrimitiveType(0x13);
4426 internal static readonly PrimitiveType GenericInst = new PrimitiveType(0x15);
4427 public static readonly PrimitiveType TypedRef = new PrimitiveType(0x16,"TypedReference",14);
4428 public static readonly PrimitiveType IntPtr = new PrimitiveType(0x18,"IntPtr",15);
4429 public static readonly PrimitiveType UIntPtr = new PrimitiveType(0x19,"UIntPtr",16);
4430 public static readonly PrimitiveType Object = new PrimitiveType(0x1C,"Object",17);
4431 internal static readonly PrimitiveType ClassType = new PrimitiveType(0x50);
4432 internal static readonly PrimitiveType SZArray = new PrimitiveType(0x1D);
4433 internal static readonly PrimitiveType MVar = new PrimitiveType(0x1E);
4434 internal static readonly PrimitiveType ValueType = new PrimitiveType(0x11, "ValueType", 18);
4435 public static readonly PrimitiveType NativeInt = IntPtr;
4436 public static readonly PrimitiveType NativeUInt = UIntPtr;
4438 internal PrimitiveType(byte typeIx) : base(typeIx) { }
4440 internal PrimitiveType(byte typeIx, string name, int STIx) : base(typeIx)
4443 this.systemTypeIndex = STIx;
4446 internal string GetName() { return name; }
4448 internal int GetSystemTypeIx() { return systemTypeIndex; }
4450 internal sealed override void TypeSig(MemoryStream str)
4452 str.WriteByte(typeIndex);
4455 internal override MetaDataElement GetTypeSpec(MetaData md)
4457 TypeSpec tS = md.GetPrimitiveTypeSpec(systemTypeIndex);
4459 tS = new TypeSpec(this,md);
4460 md.SetPrimitiveTypeSpec(systemTypeIndex,tS);
4461 md.AddToTable(MDTable.TypeSpec,tS);
4468 /**************************************************************************/
4470 /// Descriptor for an pointer (type * or type &)
4472 public abstract class PtrType : Type {
4476 internal PtrType(Type bType, byte typeIx) : base(typeIx)
4479 tabIx = MDTable.TypeSpec;
4482 internal sealed override void TypeSig(MemoryStream str)
4484 str.WriteByte(typeIndex);
4485 baseType.TypeSig(str);
4489 /**************************************************************************/
4491 /// Descriptor for a managed pointer (type & or byref)
4494 public class ManagedPointer : PtrType {
4497 /// Create new managed pointer to baseType
4499 /// <param name="bType">the base type of the pointer</param>
4500 public ManagedPointer(Type baseType) : base(baseType,0x10) { }
4503 /**************************************************************************/
4505 /// Descriptor for an unmanaged pointer (type *)
4507 public class UnmanagedPointer : PtrType {
4510 /// Create a new unmanaged pointer to baseType
4512 /// <param name="baseType">the base type of the pointer</param>
4513 public UnmanagedPointer(Type baseType) : base(baseType, 0x0F) { }
4517 /**************************************************************************/
4519 public interface IExternRef {
4520 ClassRef AddClass(string nsName, string name);
4521 ClassRef AddValueClass(string nsName, string name);
4525 /// A reference to an external assembly (.assembly extern)
4527 public class AssemblyRef : ResolutionScope, IExternRef {
4529 private ushort major, minor, build, revision;
4530 uint flags, keyIx, hashIx, cultIx;
4531 bool hasVersion = false, isKeyToken = false;
4535 internal AssemblyRef(MetaData md, string name) : base(name,md)
4537 tabIx = MDTable.AssemblyRef;
4540 public void AddAssemblyAttr (AssemAttr aa)
4546 /// Add version information about this external assembly
4548 /// <param name="majVer">Major Version</param>
4549 /// <param name="minVer">Minor Version</param>
4550 /// <param name="bldNo">Build Number</param>
4551 /// <param name="revNo">Revision Number</param>
4552 public void AddVersionInfo(int majVer, int minVer, int bldNo, int revNo)
4554 major = (ushort)majVer;
4555 minor = (ushort)minVer;
4556 build = (ushort)bldNo;
4557 revision = (ushort)revNo;
4562 /// Add the hash value for this external assembly
4564 /// <param name="hash">bytes of the hash value</param>
4565 public void AddHash(byte[] hash)
4567 hashIx = metaData.AddToBlobHeap(hash);
4571 /// Set the culture for this external assembly
4573 /// <param name="cult">the culture string</param>
4574 public void AddCulture(string cult)
4576 cultIx = metaData.AddToStringsHeap(cult);
4581 /// Add the full public key for this external assembly
4583 /// <param name="key">bytes of the public key</param>
4584 public void AddKey(byte[] key)
4586 flags |= 0x0001; // full public key
4588 keyIx = metaData.AddToBlobHeap(key);
4592 /// Add the public key token (low 8 bytes of the public key)
4594 /// <param name="key">low 8 bytes of public key</param>
4595 public void AddKeyToken(byte[] key)
4597 keyIx = metaData.AddToBlobHeap(key);
4603 /// Add a class to this external assembly
4605 /// <param name="nsName">name space name</param>
4606 /// <param name="name">class name</param>
4607 /// <returns></returns>
4608 public virtual ClassRef AddClass(string nsName, string name)
4610 ClassRef aClass = new ClassRef(nsName,name,metaData);
4611 metaData.AddToTable(MDTable.TypeRef,aClass);
4612 aClass.SetParent(this);
4617 /// Add a value class to this external assembly
4619 /// <param name="nsName">name space name</param>
4620 /// <param name="name">class name</param>
4621 /// <returns></returns>
4622 public virtual ClassRef AddValueClass(string nsName, string name)
4624 ClassRef aClass = new ClassRef(nsName,name,metaData);
4625 metaData.AddToTable(MDTable.TypeRef,aClass);
4626 aClass.SetParent(this);
4627 aClass.MakeValueClass(ValueClass.ValueType);
4631 internal string TypeName()
4633 string result = name;
4635 result = result + ", Version=" + major + "." + minor + "." +
4636 build + "." + revision;
4637 if (keyBytes != null) {
4638 string tokenStr = "=";
4639 if (isKeyToken) tokenStr = "Token=";
4640 result = result + ", PublicKey" + tokenStr;
4641 for (int i=0; i < keyBytes.Length; i++) {
4642 result = result + Hex.Byte(keyBytes[i]);
4645 if (culture != null)
4646 result = result + ", Culture=" + culture;
4650 internal sealed override uint Size(MetaData md)
4652 return 12 + 2 * md.StringsIndexSize() + 2 * md.BlobIndexSize();
4655 internal sealed override void Write(FileImage output)
4657 output.Write(major);
4658 output.Write(minor);
4659 output.Write(build);
4660 output.Write(revision);
4661 output.Write(flags);
4662 output.BlobIndex(keyIx);
4663 output.StringsIndex(nameIx);
4664 output.StringsIndex(cultIx);
4665 output.BlobIndex(hashIx);
4668 internal sealed override uint GetCodedIx(CIx code)
4671 case (CIx.ResolutionScope) : return 2;
4672 case (CIx.HasCustomAttr) : return 15;
4673 case (CIx.Implementation) : return 1;
4680 /**************************************************************************/
4682 /// Descriptor for a class defined in System (mscorlib)
4684 internal class SystemClass : ClassRef {
4686 PrimitiveType elemType;
4688 internal SystemClass(PrimitiveType eType, AssemblyRef paren, MetaData md)
4689 : base("System",eType.GetName(),md) {
4694 internal override sealed MetaDataElement GetTypeSpec(MetaData md)
4696 if (typeSpec == null) typeSpec = (TypeSpec)elemType.GetTypeSpec(md);
4701 internal sealed override void TypeSig(MemoryStream str)
4703 str.WriteByte(elemType.GetTypeIndex());
4708 /**************************************************************************/
4710 /// The assembly for mscorlib.
4712 public sealed class MSCorLib : AssemblyRef {
4714 private static readonly int valueTypeIx = 18;
4715 private readonly string systemName = "System";
4716 private Class[] systemClasses = new Class[valueTypeIx+2];
4717 private PrimitiveType[] systemTypes = new PrimitiveType[valueTypeIx];
4719 private static int[] specialNames = {
4720 PrimitiveType.Void.GetName().GetHashCode(),
4721 PrimitiveType.Boolean.GetName().GetHashCode(),
4722 PrimitiveType.Char.GetName().GetHashCode(),
4723 PrimitiveType.Int8.GetName().GetHashCode(),
4724 PrimitiveType.UInt8.GetName().GetHashCode(),
4725 PrimitiveType.Int16.GetName().GetHashCode(),
4726 PrimitiveType.UInt16.GetName().GetHashCode(),
4727 PrimitiveType.Int32.GetName().GetHashCode(),
4728 PrimitiveType.UInt32.GetName().GetHashCode(),
4729 PrimitiveType.Int64.GetName().GetHashCode(),
4730 PrimitiveType.UInt64.GetName().GetHashCode(),
4731 PrimitiveType.Float32.GetName().GetHashCode(),
4732 PrimitiveType.Float64.GetName().GetHashCode(),
4733 PrimitiveType.String.GetName().GetHashCode(),
4734 PrimitiveType.TypedRef.GetName().GetHashCode(),
4735 PrimitiveType.IntPtr.GetName().GetHashCode(),
4736 PrimitiveType.UIntPtr.GetName().GetHashCode(),
4737 PrimitiveType.Object.GetName().GetHashCode(),
4738 PrimitiveType.ValueType.GetName ().GetHashCode(),
4739 "Enum".GetHashCode()
4742 internal MSCorLib(MetaData md) : base(md,"mscorlib")
4744 if (!PEFile.IsMSCorlib)
4745 md.AddToTable(MDTable.AssemblyRef,this);
4746 systemTypes[PrimitiveType.Void.GetSystemTypeIx()] = PrimitiveType.Void;
4747 systemTypes[PrimitiveType.Boolean.GetSystemTypeIx()] = PrimitiveType.Boolean;
4748 systemTypes[PrimitiveType.Char.GetSystemTypeIx()] = PrimitiveType.Char;
4749 systemTypes[PrimitiveType.Int8.GetSystemTypeIx()] = PrimitiveType.Int8;
4750 systemTypes[PrimitiveType.UInt8.GetSystemTypeIx()] = PrimitiveType.UInt8;
4751 systemTypes[PrimitiveType.Int16.GetSystemTypeIx()] = PrimitiveType.Int16;
4752 systemTypes[PrimitiveType.UInt16.GetSystemTypeIx()] = PrimitiveType.UInt16;
4753 systemTypes[PrimitiveType.Int32.GetSystemTypeIx()] = PrimitiveType.Int32;
4754 systemTypes[PrimitiveType.UInt32.GetSystemTypeIx()] = PrimitiveType.UInt32;
4755 systemTypes[PrimitiveType.Int64.GetSystemTypeIx()] = PrimitiveType.Int64;
4756 systemTypes[PrimitiveType.UInt64.GetSystemTypeIx()] = PrimitiveType.UInt64;
4757 systemTypes[PrimitiveType.Float32.GetSystemTypeIx()] = PrimitiveType.Float32;
4758 systemTypes[PrimitiveType.Float64.GetSystemTypeIx()] = PrimitiveType.Float64;
4759 systemTypes[PrimitiveType.IntPtr.GetSystemTypeIx()] = PrimitiveType.IntPtr;
4760 systemTypes[PrimitiveType.UIntPtr.GetSystemTypeIx()] = PrimitiveType.UIntPtr;
4761 systemTypes[PrimitiveType.String.GetSystemTypeIx()] = PrimitiveType.String;
4762 systemTypes[PrimitiveType.Object.GetSystemTypeIx()] = PrimitiveType.Object;
4763 systemTypes[PrimitiveType.TypedRef.GetSystemTypeIx()] = PrimitiveType.TypedRef;
4767 /// Add a class to the mscorlib assembly
4769 /// <param name="nsName">name space name</param>
4770 /// <param name="name">class name</param>
4771 /// <returns></returns>
4772 public override ClassRef AddClass(string nsName, string name)
4774 /* This gets called by !mscorlib, for adding references INTO mscorlib, so
4775 it should be returning ClassRef ..*/
4776 Class aClass = GetSpecialClass(nsName,name);
4777 if (aClass == null) {
4778 aClass = new ClassRef(nsName,name,metaData);
4779 metaData.AddToTable(MDTable.TypeRef,aClass);
4780 if (aClass is ClassRef)
4781 ((ClassRef) aClass).SetParent(this);
4783 //FIXME: Check for !ClassRef here?
4784 return (ClassRef) aClass;
4787 private Class GetSpecialClass(string nsName,string name)
4789 if (nsName.CompareTo(systemName) != 0) return null;
4790 int hash = name.GetHashCode();
4791 for (int i=0; i < specialNames.Length; i++) {
4792 if (hash != specialNames[i])
4794 if (systemClasses[i] == null) {
4795 if (i < valueTypeIx) {
4796 systemClasses[i] = new SystemClass(systemTypes[i],this,metaData);
4797 if ((systemTypes[i] != PrimitiveType.Object) &&
4798 (systemTypes[i] != PrimitiveType.String)) {
4799 systemClasses[i].MakeValueClass(ValueClass.ValueType);
4802 systemClasses[i] = new ClassRef(nsName,name,metaData);
4803 ((ClassRef) systemClasses[i]).SetParent(this);
4804 if (!ClassDef.IsValueType (nsName, name) && !ClassDef.IsEnum (nsName, name))
4805 systemClasses[i].MakeValueClass(ValueClass.ValueType);
4807 metaData.AddToTable(MDTable.TypeRef,systemClasses[i]);
4809 return systemClasses[i];
4814 internal void SetSpecialSystemClass (string nsName, string name, Class aClass)
4816 if (nsName != systemName) return;
4817 int hash = name.GetHashCode ();
4818 for (int i = 0; i < specialNames.Length; i++) {
4819 if (hash != specialNames [i])
4821 if (systemClasses [i] == null) {
4822 systemClasses [i] = aClass;
4827 internal Class GetSpecialSystemClass(PrimitiveType pType)
4829 int ix = pType.GetSystemTypeIx();
4830 if (systemClasses[ix] == null && !PEFile.IsMSCorlib) {
4831 systemClasses[ix] = new SystemClass(pType,this,metaData);
4832 metaData.AddToTable(MDTable.TypeRef,systemClasses[ix]);
4834 return systemClasses[ix];
4837 private ClassRef GetValueClass(string name, int hash)
4839 /* Called by MSCorLib.AddValueClass, which is called by
4840 !mscorlib, for adding ref to value class INTO mscorlib,
4841 so this should be classref */
4842 int ix = valueTypeIx;
4843 if (hash != specialNames[valueTypeIx]) ix++;
4844 if (systemClasses[ix] == null) {
4845 systemClasses[ix] = new ClassRef(systemName,name,metaData);
4846 ((ClassRef) systemClasses[ix]).SetParent(this);
4847 ((ClassRef) systemClasses[ix]).MakeValueClass(ValueClass.ValueType);
4848 metaData.AddToTable(MDTable.TypeRef,systemClasses[ix]);
4850 return (ClassRef) systemClasses[ix];
4853 internal Class ValueType()
4855 if (systemClasses[valueTypeIx] == null && !PEFile.IsMSCorlib) {
4856 ClassRef valType = new ClassRef("System","ValueType",metaData);
4857 valType.SetParent(this);
4858 valType.MakeValueClass(ValueClass.ValueType);
4859 metaData.AddToTable(MDTable.TypeRef,valType);
4860 systemClasses[valueTypeIx] = valType;
4862 return systemClasses[valueTypeIx];
4865 internal Class EnumType()
4867 /* Called by both mscorlib & !mscorlib, so can be
4868 either ClassRef or ClassDef */
4869 //systemClasses [ valueTypeIx + 1] -> System.Enum
4870 if (systemClasses[valueTypeIx + 1] == null && !PEFile.IsMSCorlib) {
4871 ClassRef valType = new ClassRef("System","Enum",metaData);
4872 valType.SetParent(this);
4873 valType.MakeValueClass(ValueClass.Enum);
4874 metaData.AddToTable(MDTable.TypeRef,valType);
4875 systemClasses[valueTypeIx + 1] = valType;
4877 return systemClasses[valueTypeIx + 1];
4881 /// Add a value class to this external assembly
4883 /// <param name="nsName">name space name</param>
4884 /// <param name="name">class name</param>
4885 /// <returns></returns>
4886 public override ClassRef AddValueClass(string nsName, string name)
4888 if (nsName.CompareTo(systemName) == 0) {
4889 int hash = name.GetHashCode();
4890 if ((hash == specialNames[valueTypeIx]) ||
4891 (hash == specialNames[valueTypeIx+1])) {
4892 return GetValueClass(name,hash);
4895 ClassRef aClass = new ClassRef(nsName,name,metaData);
4896 metaData.AddToTable(MDTable.TypeRef,aClass);
4897 aClass.SetParent(this);
4898 aClass.MakeValueClass(ValueClass.ValueType);
4904 /**************************************************************************/
4907 /// Root (20 bytes + UTF-8 Version String + quad align padding)
4908 /// StreamHeaders (8 bytes + null terminated name string + quad align padding)
4910 /// #~ (always present - holds metadata tables)
4911 /// #Strings (always present - holds identifier strings)
4912 /// #US (Userstring heap)
4913 /// #Blob (signature blobs)
4914 /// #GUID (guids for assemblies or Modules)
4916 public class MetaData {
4918 internal static readonly int[] CIxShiftMap = {2,2,5,1,2,3,1,1,1,2,3,2,1};
4919 private static readonly byte StringsHeapMask = 0x1;
4920 private static readonly byte GUIDHeapMask = 0x2;
4921 private static readonly byte BlobHeapMask = 0x4;
4922 private static readonly uint MetaDataSignature = 0x424A5342;
4923 private static readonly uint maxSmlIxSize = 0xFFFF;
4924 private static readonly uint max1BitSmlIx = 0x7FFF;
4925 private static readonly uint max2BitSmlIx = 0x3FFF;
4926 private static readonly uint max3BitSmlIx = 0x1FFF;
4927 private static readonly uint max5BitSmlIx = 0x7FF;
4928 // NOTE: version and stream name strings MUST always be quad padded
4930 private static readonly string version = "v4.0.30319\0\0";
4932 private static readonly string version = "v2.0.50727\0\0";
4934 private static readonly string version = "v1.1.4322\0\0\0";
4936 private static readonly char[] tildeName = {'#','~','\0','\0'};
4937 private static readonly char[] stringsName = {'#','S','t','r','i','n','g','s','\0','\0','\0','\0'};
4938 private static readonly char[] usName = {'#','U','S','\0'};
4939 private static readonly char[] guidName = {'#','G','U','I','D','\0','\0','\0'};
4940 private static readonly char[] blobName = {'#','B','l','o','b','\0','\0','\0'};
4941 private static readonly uint MetaDataHeaderSize = 20 + (uint)version.Length;
4942 private static readonly uint TildeHeaderSize = 24;
4943 private static readonly uint StreamHeaderSize = 8;
4944 private static readonly uint numMetaDataTables = (int)MDTable.GenericParamConstraint + 1;
4946 MetaDataStream strings, us, guid, blob;
4948 MetaDataStream[] streams = new MetaDataStream[5];
4949 uint numStreams = 5;
4950 uint tildeTide = 0, tildePadding = 0, tildeStart = 0;
4951 uint numTables = 0, resourcesSize = 0;
4952 ArrayList[] metaDataTables = new ArrayList[numMetaDataTables];
4953 ArrayList byteCodes = new ArrayList();
4954 uint codeSize = 0, codeStart, byteCodePadding = 0, metaDataSize = 0;
4955 ulong valid = 0, /*sorted = 0x000002003301FA00;*/ sorted = 0;
4956 bool[] largeIx = new bool[numMetaDataTables];
4957 bool[] lgeCIx = new bool[(int)CIx.MaxCIx];
4958 bool largeStrings = false, largeUS = false, largeGUID = false, largeBlob = false;
4959 private FileImage file;
4960 private byte heapSizes = 0;
4961 MetaDataElement entryPoint;
4962 BinaryWriter output;
4963 public MSCorLib mscorlib;
4964 private TypeSpec[] systemTypeSpecs = new TypeSpec[PrimitiveType.NumSystemTypes];
4966 private ArrayList cattr_list;
4967 private ArrayList declsec_list;
4968 ArrayList resources;
4970 internal MetaData(FileImage file)
4972 // tilde = new MetaDataStream(tildeName,false,0);
4974 strings = new MetaDataStream(stringsName,new UTF8Encoding(),true);
4975 us = new MetaDataStream(usName,new UnicodeEncoding(),true);
4976 guid = new MetaDataStream(guidName,false);
4977 blob = new MetaDataStream(blobName,true);
4978 streams[1] = strings;
4982 for (int i=0; i < numMetaDataTables; i++) {
4985 for (int i=0; i < lgeCIx.Length; i++) {
4988 mscorlib = new MSCorLib(this);
4991 internal TypeSpec GetPrimitiveTypeSpec(int ix)
4993 return systemTypeSpecs[ix];
4996 internal void SetPrimitiveTypeSpec(int ix, TypeSpec typeSpec)
4998 systemTypeSpecs[ix] = typeSpec;
5001 internal uint Size()
5003 return metaDataSize;
5006 private void CalcHeapSizes ()
5008 if (strings.LargeIx()) {
5009 largeStrings = true;
5010 heapSizes |= StringsHeapMask;
5012 if (guid.LargeIx()) {
5014 heapSizes |= GUIDHeapMask;
5016 if (blob.LargeIx()) {
5018 heapSizes |= BlobHeapMask;
5021 largeUS = us.LargeIx();
5024 internal void StreamSize(byte mask)
5029 internal uint AddToUSHeap(string str)
5031 if (str == null) return 0;
5032 return us.Add(str,true);
5035 internal uint AddToUSHeap(byte[] str)
5037 if (str == null) return 0;
5038 return us.Add (str, true);
5041 internal uint AddToStringsHeap(string str)
5043 if ((str == null) || (str.CompareTo("") == 0)) return 0;
5044 return strings.Add(str,false);
5047 internal uint AddToGUIDHeap(Guid guidNum)
5049 return guid.Add(guidNum, false);
5052 internal uint AddToBlobHeap(byte[] blobBytes)
5054 if (blobBytes == null) return 0;
5055 return blob.Add(blobBytes, true);
5058 internal uint AddToBlobHeap(byte val)
5060 return blob.Add(val, true);
5063 internal uint AddToBlobHeap(sbyte val)
5065 return blob.Add(val, true);
5068 internal uint AddToBlobHeap(ushort val)
5070 return blob.Add(val, true);
5073 internal uint AddToBlobHeap(short val)
5075 return blob.Add(val, true);
5078 internal uint AddToBlobHeap(uint val)
5080 return blob.Add(val, true);
5083 internal uint AddToBlobHeap(int val)
5085 return blob.Add(val, true);
5088 internal uint AddToBlobHeap(ulong val)
5090 return blob.Add(val, true);
5093 internal uint AddToBlobHeap(long val)
5095 return blob.Add(val, true);
5098 internal uint AddToBlobHeap(float val)
5100 return blob.Add(val, true);
5103 internal uint AddToBlobHeap(double val)
5105 return blob.Add(val, true);
5108 internal uint AddToBlobHeap(string val)
5110 return blob.Add(val,true);
5113 internal void AddCustomAttribute (CustomAttribute cattr)
5115 if (cattr_list == null)
5116 cattr_list = new ArrayList ();
5117 cattr_list.Add (cattr);
5120 internal void AddDeclSecurity (BaseDeclSecurity decl_sec)
5122 if (declsec_list == null)
5123 declsec_list = new ArrayList ();
5124 declsec_list.Add (decl_sec);
5127 private ArrayList GetTable(MDTable tableIx)
5129 int tabIx = (int)tableIx;
5130 if (metaDataTables[tabIx] == null) {
5131 metaDataTables[tabIx] = new ArrayList();
5132 valid |= ((ulong)0x1 << tabIx);
5133 // Console.WriteLine("after creating table " + tableIx + "(" + tabIx + ") valid = " + valid);
5136 return metaDataTables[tabIx];
5139 internal void AddToTable(MDTable tableIx, MetaDataElement elem)
5142 // Console.Out.WriteLine("ERROR - element already in table " + tableIx);
5145 // updates Row field of the element
5146 // Console.WriteLine("Adding element to table " + (uint)tableIx);
5147 ArrayList table = GetTable(tableIx);
5148 elem.Row = (uint)table.Count + 1;
5152 internal uint TableIndex(MDTable tableIx)
5154 if (metaDataTables[(int)tableIx] == null) return 1;
5155 return (uint)metaDataTables[(int)tableIx].Count+1;
5158 internal uint AddCode(CILInstructions byteCode)
5160 byteCodes.Add(byteCode);
5161 uint offset = codeSize + codeStart;
5162 codeSize += byteCode.GetCodeSize();
5166 internal void SetEntryPoint(MetaDataElement ep)
5171 internal uint AddResource(byte[] resBytes)
5173 if (resources == null) resources = new ArrayList ();
5174 resources.Add (resBytes);
5175 uint offset = resourcesSize;
5176 resourcesSize += (uint)resBytes.Length + 4;
5180 internal void AddData(DataConstant cVal)
5182 file.AddInitData(cVal);
5185 internal static void CompressNum(uint val, MemoryStream sig)
5188 sig.WriteByte((byte)val);
5189 } else if (val <= 0x3FFF) {
5190 byte b1 = (byte)((val >> 8) | 0x80);
5191 byte b2 = (byte)(val & FileImage.iByteMask[0]);
5195 byte b1 = (byte)((val >> 24) | 0xC0);
5196 byte b2 = (byte)((val & FileImage.iByteMask[2]) >> 16);
5197 byte b3 = (byte)((val & FileImage.iByteMask[1]) >> 8);;
5198 byte b4 = (byte)(val & FileImage.iByteMask[0]);
5206 internal uint CodeSize()
5208 return codeSize + byteCodePadding;
5211 internal uint GetResourcesSize()
5213 return resourcesSize;
5216 internal uint StringsIndexSize()
5218 if (largeStrings) return 4;
5222 internal uint GUIDIndexSize()
5224 if (largeGUID) return 4;
5228 internal uint USIndexSize()
5230 if (largeUS) return 4;
5234 internal uint BlobIndexSize()
5236 if (largeBlob) return 4;
5240 internal uint CodedIndexSize(CIx code)
5242 if (lgeCIx[(uint)code]) return 4;
5246 internal uint TableIndexSize(MDTable tabIx)
5248 if (largeIx[(uint)tabIx]) return 4;
5252 private void SetIndexSizes()
5254 for (int i=0; i < numMetaDataTables; i++) {
5255 if (metaDataTables[i] == null)
5258 uint count = (uint)metaDataTables[i].Count;
5259 if (count > maxSmlIxSize)
5262 MDTable tabIx = (MDTable)i;
5263 if (count > max5BitSmlIx) {
5264 lgeCIx[(int)CIx.HasCustomAttr] = true;
5266 if (count > max3BitSmlIx) {
5267 if ((tabIx == MDTable.TypeRef) || (tabIx == MDTable.ModuleRef) || (tabIx == MDTable.Method) || (tabIx == MDTable.TypeSpec) || (tabIx == MDTable.Field))
5268 lgeCIx[(int)CIx.CustomAttributeType] = true;
5269 if ((tabIx == MDTable.Method) || (tabIx == MDTable.MemberRef))
5270 lgeCIx[(int)CIx.MemberRefParent] = true;
5272 if (count > max2BitSmlIx) {
5273 if ((tabIx == MDTable.Field) || (tabIx == MDTable.Param) || (tabIx == MDTable.Property))
5274 lgeCIx[(int)CIx.HasConst] = true;
5275 if ((tabIx == MDTable.TypeDef) || (tabIx == MDTable.TypeRef) || (tabIx == MDTable.TypeSpec))
5276 lgeCIx[(int)CIx.TypeDefOrRef] = true;
5277 if ((tabIx == MDTable.TypeDef) || (tabIx == MDTable.Method) || (tabIx == MDTable.Assembly))
5278 lgeCIx[(int)CIx.HasDeclSecurity] = true;
5279 if ((tabIx == MDTable.File) || (tabIx == MDTable.AssemblyRef) || (tabIx == MDTable.ExportedType))
5280 lgeCIx[(int)CIx.Implementation] = true;
5281 if ((tabIx == MDTable.Module) || (tabIx == MDTable.ModuleRef) || (tabIx == MDTable.AssemblyRef) || (tabIx == MDTable.TypeRef))
5282 lgeCIx[(int)CIx.ResolutionScope] = true;
5284 if (count > max1BitSmlIx) {
5285 if ((tabIx == MDTable.Field) || (tabIx == MDTable.Param))
5286 lgeCIx[(int)CIx.HasFieldMarshal] = true;
5287 if ((tabIx == MDTable.Event) || (tabIx == MDTable.Property))
5288 lgeCIx[(int)CIx.HasSemantics] = true;
5289 if ((tabIx == MDTable.Method) || (tabIx == MDTable.MemberRef))
5290 lgeCIx[(int)CIx.MethodDefOrRef] = true;
5291 if ((tabIx == MDTable.Field) || (tabIx == MDTable.Method))
5292 lgeCIx[(int)CIx.MemberForwarded] = true;
5293 if ((tabIx == MDTable.TypeDef) || (tabIx == MDTable.Method))
5294 lgeCIx[(int)CIx.TypeOrMethodDef] = true;
5299 private void SetStreamOffsets()
5301 uint sizeOfHeaders = StreamHeaderSize + (uint)tildeName.Length;
5302 for (int i=1; i < numStreams; i++) {
5303 sizeOfHeaders += streams[i].headerSize();
5305 metaDataSize = MetaDataHeaderSize + sizeOfHeaders;
5306 tildeStart = metaDataSize;
5307 metaDataSize += tildeTide + tildePadding;
5308 for (int i=1; i < numStreams; i++) {
5309 streams[i].Start = metaDataSize;
5310 metaDataSize += streams[i].Size();
5311 streams[i].WriteDetails();
5315 internal void CalcTildeStreamSize()
5318 //tilde.SetIndexSizes(strings.LargeIx(),us.LargeIx(),guid.LargeIx(),blob.LargeIx());
5319 tildeTide = TildeHeaderSize;
5320 tildeTide += 4 * numTables;
5321 //Console.WriteLine("Tilde header + sizes = " + tildeTide);
5322 for (int i=0; i < numMetaDataTables; i++) {
5323 if (metaDataTables[i] != null) {
5324 ArrayList table = metaDataTables[i];
5325 // Console.WriteLine("Meta data table " + i + " at offset " + tildeTide);
5326 tildeTide += (uint)table.Count * ((MetaDataElement)table[0]).Size(this);
5327 // Console.WriteLine("Metadata table " + i + " has size " + table.Count);
5328 // Console.WriteLine("tildeTide = " + tildeTide);
5331 if ((tildeTide % 4) != 0) tildePadding = 4 - (tildeTide % 4);
5332 //Console.WriteLine("tildePadding = " + tildePadding);
5335 internal void WriteTildeStream(FileImage output)
5337 output.Seek(0,SeekOrigin.Current);
5338 output.Write((uint)0); // Reserved
5340 output.Write((byte)2); // MajorVersion
5341 output.Write((byte)0); // MinorVersion
5343 output.Write((byte)1); // MajorVersion
5344 output.Write((byte)0); // MinorVersion
5346 output.Write(heapSizes);
5347 output.Write((byte)1); // Reserved
5348 output.Write(valid);
5349 output.Write(sorted);
5351 for (int i=0; i < numMetaDataTables; i++) {
5352 if (metaDataTables[i] != null) {
5353 uint count = (uint)metaDataTables[i].Count;
5354 output.Write(count);
5358 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]);
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]);
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];