3 using System.Collections;
5 using System.Reflection;
12 /// flags for the assembly (.corflags)
14 public enum CorFlags {CF_IL_ONLY = 1, CF_32_BITREQUIRED = 2,
15 CF_STRONGNAMESIGNED = 8, CF_TRACKDEBUGDATA = 0x10000 }
18 /// subsystem for the assembly (.subsystem)
20 public enum SubSystem { Native = 1, Windows_GUI = 2,
21 Windows_CUI = 3, OS2_CUI = 5, POSIX_CUI = 7, Native_Windows = 8,
25 /// Hash algorithms for the assembly
27 public enum HashAlgorithm { None, SHA1 }
30 /// Attributes for this assembly
32 public enum AssemAttr { Retargetable = 0x100, EnableJITCompileTracking = 0x8000,
33 DisableJITCompileOptimizer = 0x4000}
36 /// Method call conventions
39 public enum CallConv { Default, Cdecl, Stdcall, Thiscall,
40 Fastcall, Vararg, Instance = 0x20, Generic = 0x10, InstanceExplicit = 0x60 }
43 /// Type custom modifier
45 public enum CustomModifier { modreq = 0x1F, modopt };
48 /// Attibutes for a class
51 public enum TypeAttr {Private, Public, NestedPublic, NestedPrivate,
52 NestedFamily, NestedAssembly, NestedFamAndAssem, NestedFamOrAssem,
53 SequentialLayout, ExplicitLayout = 0x10, Interface = 0x20,
54 Abstract = 0x80, PublicAbstract = 0x81, Sealed = 0x100,
55 PublicSealed = 0x101, SpecialName = 0x400, RTSpecialName = 0x800,
56 Import = 0x1000, Serializable = 0x2000, UnicodeClass = 0x10000,
57 AutoClass = 0x20000, HasSecurity = 0x40000, BeforeFieldInit = 0x100000,
59 VisibilityMask = 0x07 }
62 /// Attributes for a field
64 public enum FieldAttr {Default, Private, FamAndAssem, Assembly,
65 Family, FamOrAssem, Public, Static = 0x10, PublicStatic = 0x16,
66 Initonly = 0x20, Literal = 0x40, Notserialized = 0x80,
67 SpecialName = 0x200, RTSpecialName = 0x400, HasFieldMarshal = 0x1000 }
70 /// Attributes for a method
72 public enum MethAttr { Default, Private, FamAndAssem, Assembly,
73 Family, FamOrAssem, Public, Static = 0x0010, PublicStatic = 0x16,
74 Final = 0x0020, PublicStaticFinal = 0x36, Virtual = 0x0040,
75 PrivateVirtual, PublicVirtual = 0x0046, HideBySig = 0x0080,
76 NewSlot = 0x0100, Strict = 0x200, Abstract = 0x0400, SpecialName = 0x0800,
77 RTSpecialName = 0x1000, SpecialRTSpecialName = 0x1800,
78 HasSecurity = 0x4000, RequireSecObject = 0x8000}
81 /// Attributes for .pinvokeimpl method declarations
83 public enum PInvokeAttr { nomangle = 1, ansi = 2, unicode = 4, autochar = 6,
84 bestfit_on = 0x0010, bestfit_off = 0x0020, bestfit_mask = 0x0030,
85 lasterr = 0x0040, winapi = 0x0100, cdecl = 0x0200,
86 stdcall = 0x0300, thiscall = 0x0400, fastcall = 0x0500,
87 charmaperror_on = 0x1000, charmaperror_off = 0x2000
91 /// Implementation attributes for a method
93 public enum ImplAttr { IL, Native, Runtime = 0x03, Unmanaged = 0x04,
94 ForwardRef = 0x10, PreserveSig = 0x0080, InternalCall = 0x1000,
95 Synchronised = 0x0020, Synchronized = 0x0020, NoInLining = 0x0008, NoOptimization = 0x0040, Optil = 0x0002,
96 AggressiveInlining = 0x0100
100 /// Storage location for initial field data
102 public enum DataSegment { Data, TLS, CIL }
105 /// Modes for a parameter
107 public enum ParamAttr { Default, In, Out, Opt = 16, HasDefault = 0x1000, HasFieldMarshal = 0x2000 }
112 public enum Op { nop, breakOp, ldarg_0, ldarg_1, ldarg_2, ldarg_3,
113 ldloc_0, ldloc_1, ldloc_2, ldloc_3, stloc_0, stloc_1, stloc_2, stloc_3,
114 ldnull = 0x14, ldc_i4_m1, ldc_i4_0, ldc_i4_1, ldc_i4_2, ldc_i4_3,
115 ldc_i4_4, ldc_i4_5, ldc_i4_6, ldc_i4_7, ldc_i4_8, dup = 0x25, pop,
116 ret = 0x2A, ldind_i1 = 0x46, ldind_u1, ldind_i2, ldind_u2, ldind_i4,
117 ldind_u4, ldind_i8, ldind_i, ldind_r4, ldind_r8, ldind_ref, stind_ref,
118 stind_i1, stind_i2, stind_i4, stind_i8, stind_r4, stind_r8, add, sub, mul,
119 div, div_un, rem, rem_un, and, or, xor, shl, shr, shr_un, neg, not,
120 conv_i1, conv_i2, conv_i4, conv_i8, conv_r4, conv_r8, conv_u4, conv_u8,
121 conv_r_un = 0x76, throwOp = 0x7A, conv_ovf_i1_un = 0x82, conv_ovf_i2_un,
122 conv_ovf_i4_un, conv_ovf_i8_un, conf_ovf_u1_un, conv_ovf_u2_un,
123 conv_ovf_u4_un, conv_ovf_u8_un, conv_ovf_i_un, conv_ovf_u_un,
124 ldlen = 0x8E, ldelem_i1 = 0x90, ldelem_u1, ldelem_i2, ldelem_u2,
125 ldelem_i4, ldelem_u4, ldelem_i8, ldelem_i, ldelem_r4, ldelem_r8,
126 ldelem_ref, stelem_i, stelem_i1, stelem_i2, stelem_i4, stelem_i8, stelem_r4 = 0xA0, stelem_r8,
127 stelem_ref, conv_ovf_i1 = 0xb3, conv_ovf_u1, conv_ovf_i2, conv_ovf_u2,
128 conv_ovf_i4, conv_ovf_u4, conv_ovf_i8, conv_ovf_u8, ckfinite = 0xC3,
129 conv_u2 = 0xD1, conv_u1, conv_i, conv_ovf_i, conv_ovf_u, add_ovf,
130 add_ovf_un, mul_ovf, mul_ovf_un, sub_ovf, sub_ovf_un, endfinally,
131 stind_i = 0xDF, conv_u, arglist = 0xFE00, ceq, cgt, cgt_un, clt, clt_un,
132 localloc = 0xFE0F, endfilter = 0xFE11, volatile_ = 0xFE13, tail_,
133 cpblk = 0xFE17, initblk, rethrow = 0xFE1A, refanytype = 0xFE1D, readonly_ = 0xFE1E }
136 /// CIL instructions requiring an integer parameter
138 public enum IntOp {ldarg_s = 0x0E, ldarga_s, starg_s, ldloc_s, ldloca_s,
139 stloc_s, ldc_i4_s = 0x1F, ldc_i4, ldarg = 0xFE09,
140 ldarga, starg, ldloc, ldloca, stloc, unaligned = 0xFE12 }
143 /// CIL instructions requiring a field parameter
145 public enum FieldOp {ldfld = 0x7B, ldflda, stfld, ldsfld, ldsflda,
146 stsfld, ldtoken = 0xD0 }
149 /// CIL instructions requiring a method parameter
151 public enum MethodOp {jmp = 0x27, call, callvirt = 0x6F, newobj = 0x73,
152 ldtoken = 0xD0, ldftn = 0xFE06, ldvirtfn }
155 /// CIL instructions requiring a type parameter
157 public enum TypeOp {cpobj = 0x70, ldobj, castclass = 0x74, isinst,
158 unbox = 0x79, stobj = 0x81, box = 0x8C, newarr,
159 ldelema = 0x8F, refanyval = 0xC2, mkrefany = 0xC6,
160 ldtoken = 0xD0, initobj = 0xFE15, constrained = 0xFE16,
161 sizeOf = 0xFE1C, ldelem = 0xA3, stelem = 0xA4, unbox_any }
164 /// CIL branch instructions
166 public enum BranchOp {
168 br_s = 0x2B, brfalse_s, brtrue_s, beq_s, bge_s, bgt_s,
169 ble_s, blt_s, bne_un_s, bge_un_s, bgt_un_s, ble_un_s, blt_un_s,
171 br = 0x38, brfalse, brtrue, beq, bge, bgt, ble, blt,
172 bne_un, bge_un, bgt_un, ble_un, blt_un,
174 leave = 0xDD, leave_s }
177 /// Index for all the tables in the meta data
179 public enum MDTable { Module, TypeRef, TypeDef, Field = 0x04, Method = 0x06,
180 Param = 0x08, InterfaceImpl, MemberRef, Constant, CustomAttribute,
181 FieldMarshal, DeclSecurity, ClassLayout, FieldLayout, StandAloneSig,
182 EventMap, Event = 0x14, PropertyMap, Property = 0x17, MethodSemantics,
183 MethodImpl, ModuleRef, TypeSpec, ImplMap, FieldRVA, Assembly = 0x20,
184 AssemblyProcessor, AssemblyOS, AssemblyRef, AssemblyRefProcessor,
185 AssemblyRefOS, File, ExportedType, ManifestResource, NestedClass,
186 GenericParam, MethodSpec, GenericParamConstraint }
188 public enum SafeArrayType { int16 = 2, int32, float32, float64,
189 currency, date, bstr, dispatch, error, boolean, variant, unknown,
190 Decimal, int8 = 16, uint8, uint16, uint32, Int = 22, UInt }
192 internal enum CIx { TypeDefOrRef, HasConst, HasCustomAttr, HasFieldMarshal,
193 HasDeclSecurity, MemberRefParent, HasSemantics, MethodDefOrRef,
194 MemberForwarded, Implementation, CustomAttributeType, ResolutionScope,
195 TypeOrMethodDef, MaxCIx }
197 internal enum MapType { eventMap, propertyMap, nestedClass }
199 public enum ValueClass { ValueType, Enum }
201 public enum GenParamType : byte {
202 Var = 0x13, MVar = 0x1E
206 public enum GenericParamAttributes : ushort {
207 VarianceMask = 0x0003,
210 Contravariant = 0x0002,
212 SpecialConstraintMask = 0x001c,
213 ReferenceTypeConstraint = 0x0004,
214 NotNullableValueTypeConstraint = 0x0008,
215 DefaultConstructorConstrait = 0x0010
218 /* Taken from Mono.Cecil */
219 public enum SecurityAction : short {
233 NonCasLinkDemand = 14,
234 NonCasInheritance = 15,
235 LinkDemandChoice = 16,
236 InheritDemandChoice = 17,
242 /**************************************************************************/
244 /// Base class for all Meta Data table elements
247 public abstract class MetaDataElement: IComparable {
248 protected ArrayList customAttributes;
249 private uint row = 0;
250 protected bool done = false;
251 protected MDTable tabIx;
252 protected bool sortTable = false;
254 private bool has_custom_attrs = false;
256 internal MetaDataElement() { }
267 public bool HasCustomAttr {
268 get { return has_custom_attrs; }
269 set { has_custom_attrs = value; }
272 internal virtual uint GetCodedIx(CIx code) { return 0; }
275 /// Add a custom attribute to this item
277 /// <param name="ctorMeth">the constructor method for this attribute</param>
278 /// <param name="val">the byte value of the parameters</param>
279 public void AddCustomAttribute(Method ctorMeth, byte[] val)
281 if (customAttributes == null) {
282 customAttributes = new ArrayList();
284 customAttributes.Add(new CustomAttribute(this,ctorMeth,val));
288 /// Add a custom attribute to this item
290 /// <param name="ctorMeth">the constructor method for this attribute</param>
291 /// <param name="val">the constant values of the parameters</param>
292 public void AddCustomAttribute(Method ctorMeth, Constant[] cVals)
294 if (customAttributes == null) {
295 customAttributes = new ArrayList();
297 // customAttributes.Add(new CustomAttribute(this,ctorMeth,cVals));
300 internal uint Token()
302 return (((uint)tabIx << 24) | row);
305 internal virtual void BuildTables(MetaData md)
310 internal virtual uint Size(MetaData md)
315 internal virtual void Write(FileImage output) { }
317 internal virtual uint SortKey()
319 throw new PEFileException("Trying to sort table of " + this);
323 internal virtual uint SortKey2()
328 public int CompareTo(object obj)
330 uint otherKey = ((MetaDataElement)obj).SortKey();
331 uint thisKey = SortKey();
333 if (thisKey == otherKey) {
335 otherKey = ((MetaDataElement)obj).SortKey2();
336 thisKey = SortKey2();
337 if (thisKey == otherKey)
339 if (thisKey < otherKey)
343 if (thisKey < otherKey) return -1;
350 /**************************************************************************/
352 /// Layout information for a class (.class [sequential | explicit])
354 internal class ClassLayout : MetaDataElement {
360 internal ClassLayout(int pack, int cSize, ClassDef par)
362 packSize = (ushort)pack;
363 classSize = (uint)cSize;
365 tabIx = MDTable.ClassLayout;
368 internal sealed override uint Size(MetaData md)
370 return 6 + md.TableIndexSize(MDTable.TypeDef);
373 internal sealed override void Write(FileImage output)
375 output.Write(packSize);
376 output.Write(classSize);
377 output.WriteIndex(MDTable.TypeDef,parent.Row);
382 /**************************************************************************/
384 /// Summary description for ConstantElem.
386 internal class ConstantElem : MetaDataElement {
388 MetaDataElement parent;
392 internal ConstantElem(MetaDataElement parent, Constant val)
394 this.parent = parent;
396 tabIx = MDTable.Constant;
400 internal override uint SortKey()
402 return (parent.Row << MetaData.CIxShiftMap[(uint)CIx.HasConst])
403 | parent.GetCodedIx(CIx.HasConst);
406 internal sealed override void BuildTables(MetaData md)
409 valIx = cValue.GetBlobIndex(md);
413 internal void AddToBlob(BinaryWriter bw)
418 internal sealed override uint Size(MetaData md)
420 return 2 + md.CodedIndexSize(CIx.HasConst) + md.BlobIndexSize();
423 internal sealed override void Write(FileImage output)
425 output.Write(cValue.GetTypeIndex());
426 output.Write((byte)0);
427 output.WriteCodedIndex(CIx.HasConst,parent);
428 output.BlobIndex(valIx);
432 /**************************************************************************/
434 /// Descriptor for a Custom Attribute (.custom)
437 public class CustomAttribute : MetaDataElement {
439 MetaDataElement parent;
445 ArrayList names, vals;
447 internal CustomAttribute(MetaDataElement paren, Method constrType,
452 tabIx = MDTable.CustomAttribute;
454 byteVal = ConstantToByteArray (val);
457 static byte[] ConstantToByteArray (Constant c)
459 var bac = c as ByteArrConst;
463 var ms = new MemoryStream ();
471 return ms.ToArray ();
474 var sc = c as StringConst;
476 string value = sc.val;
478 throw new NotImplementedException ();
480 var buf = Encoding.UTF8.GetBytes (value);
481 MetaData.CompressNum ((uint) buf.Length, ms);
482 var byteVal = ms.ToArray ();
483 System.Array.Resize (ref byteVal, (int) ms.Length + buf.Length + 2);
484 System.Array.Copy (buf, 0, byteVal, ms.Length, buf.Length);
488 var ac = c as ArrayConstant;
490 var bw = new BinaryWriter (ms);
491 if (ac.ExplicitSize != null)
492 bw.Write (ac.ExplicitSize.Value);
495 return ms.ToArray ();
498 var bc = c as DataConstant;
500 var bw = new BinaryWriter (ms);
503 return ms.ToArray ();
506 throw new NotImplementedException (c.GetType ().ToString ());
509 internal CustomAttribute(MetaDataElement paren, Method constrType,
513 tabIx = MDTable.CustomAttribute;
517 internal override uint SortKey()
519 return (parent.Row << MetaData.CIxShiftMap[(uint)CIx.HasCustomAttr])
520 | parent.GetCodedIx(CIx.HasCustomAttr);
523 public void AddFieldOrProp(string name, Constant val)
526 names = new ArrayList();
527 vals = new ArrayList();
533 internal sealed override void BuildTables(MetaData md)
535 md.AddToTable(MDTable.CustomAttribute, this);
536 if (byteVal == null) {
541 BinaryWriter bw = new BinaryWriter(new MemoryStream());
543 MemoryStream str = (MemoryStream)bw.BaseStream;
544 valIx = md.AddToBlobHeap(str.ToArray());
547 internal sealed override uint Size(MetaData md)
549 return md.CodedIndexSize(CIx.HasCustomAttr) + md.CodedIndexSize(CIx.CustomAttributeType) + md.BlobIndexSize();
552 internal sealed override void Write(FileImage output)
554 output.WriteCodedIndex(CIx.HasCustomAttr,parent);
555 output.WriteCodedIndex(CIx.CustomAttributeType,type);
556 output.BlobIndex(valIx);
561 /**************************************************************************/
563 /// Descriptor for security permissions for a class or a method
566 public abstract class BaseDeclSecurity : MetaDataElement {
569 MetaDataElement parent;
572 internal BaseDeclSecurity(MetaDataElement paren, ushort act)
576 tabIx = MDTable.DeclSecurity;
579 internal override uint SortKey()
581 return (parent.Row << MetaData.CIxShiftMap[(uint)CIx.HasDeclSecurity])
582 | parent.GetCodedIx(CIx.HasDeclSecurity);
585 internal sealed override uint Size(MetaData md)
587 return 2 + md.CodedIndexSize(CIx.HasDeclSecurity) + md.BlobIndexSize();
590 internal sealed override void BuildTables(MetaData md)
594 BinaryWriter bw = new BinaryWriter (new MemoryStream ());
595 md.AddToTable (MDTable.DeclSecurity, this);
596 MemoryStream str = (MemoryStream)bw.BaseStream;
598 permissionIx = md.AddToBlobHeap(str.ToArray());
603 internal abstract void WriteSig (BinaryWriter bw);
605 internal sealed override void Write(FileImage output)
607 output.Write(action);
608 output.WriteCodedIndex(CIx.HasDeclSecurity,parent);
609 output.BlobIndex(permissionIx);
614 public class DeclSecurity : BaseDeclSecurity {
618 internal DeclSecurity(MetaDataElement paren, ushort act, byte [] val)
624 internal override void WriteSig (BinaryWriter bw)
631 public class DeclSecurity_20 : BaseDeclSecurity {
635 internal DeclSecurity_20 (MetaDataElement paren, ushort act, PermissionSet ps)
641 internal override void WriteSig (BinaryWriter bw)
647 public class PermissionMember {
649 MemberTypes member_type;
654 public PermissionMember (MemberTypes member_type, PEAPI.Type type, string name, object value)
656 this.member_type = member_type;
662 public void Write (BinaryWriter bw)
666 if (member_type == MemberTypes.Field)
667 bw.Write ((byte) 0x53);
670 bw.Write ((byte) 0x54);
672 if (type is PrimitiveType) {
673 bw.Write (type.GetTypeIndex ());
676 bw.Write ((byte) 0x55); //ENUM
678 b = Encoding.UTF8.GetBytes (((ClassRef) type).TypeName ());
679 MetaData.CompressNum ((uint) b.Length, (MemoryStream) bw.BaseStream);
683 b = Encoding.UTF8.GetBytes (name);
684 MetaData.CompressNum ((uint) b.Length, (MemoryStream) bw.BaseStream);
687 ((Constant) value).Write (bw);
692 public class Permission
700 public Permission (PEAPI.Type type, string name)
706 public void AddMember (PEAPI.PermissionMember member)
709 members = new ArrayList ();
711 members.Add (member);
714 public void Write (BinaryWriter bw)
716 byte [] b = Encoding.UTF8.GetBytes (name);
717 MetaData.CompressNum ((uint) b.Length, (MemoryStream) bw.BaseStream);
720 BinaryWriter perm_writer = new BinaryWriter (new MemoryStream (), Encoding.Unicode);
721 MemoryStream str = (MemoryStream) perm_writer.BaseStream;
723 MetaData.CompressNum ((uint) members.Count, str);//number of params
724 foreach (PermissionMember member in members)
725 member.Write (perm_writer);
727 bw.Write ((byte) str.Length); //(optional) parameters length
728 bw.Write (str.ToArray ());
732 public class PermissionSet
734 PEAPI.SecurityAction sec_action;
735 ArrayList permissions;
737 public PermissionSet (PEAPI.SecurityAction sec_action)
739 this.sec_action = sec_action;
742 public void AddPermission (PEAPI.Permission perm)
744 if (permissions == null)
745 permissions = new ArrayList ();
747 permissions.Add (perm);
750 public void Write (BinaryWriter bw)
752 bw.Write ((byte) 0x2e);
753 MetaData.CompressNum ((uint) permissions.Count, (MemoryStream) bw.BaseStream);
755 foreach (Permission perm in permissions)
761 /**************************************************************************/
763 /// Descriptor for layout information for a field
766 public class FieldLayout : MetaDataElement {
771 internal FieldLayout(Field field, uint offset)
774 this.offset = offset;
775 tabIx = MDTable.FieldLayout;
778 internal sealed override uint Size(MetaData md)
780 return 4 + md.TableIndexSize(MDTable.Field);
783 internal sealed override void Write(FileImage output)
785 output.Write(offset);
786 output.WriteIndex(MDTable.Field,field.Row);
791 /*****************************************************************************/
793 /// Marshalling information for a field or param
795 public class FieldMarshal : MetaDataElement {
797 MetaDataElement field;
801 internal FieldMarshal(MetaDataElement field, NativeType nType)
805 tabIx = MDTable.FieldMarshal;
808 internal override uint SortKey()
810 return (field.Row << MetaData.CIxShiftMap[(uint)CIx.HasFieldMarshal])
811 | field.GetCodedIx(CIx.HasFieldMarshal);
814 internal sealed override void BuildTables(MetaData md)
817 ntIx = md.AddToBlobHeap(nt.ToBlob());
821 internal sealed override uint Size(MetaData md)
823 return md.CodedIndexSize(CIx.HasFieldMarshal) + md.BlobIndexSize();
826 internal sealed override void Write(FileImage output)
828 output.WriteCodedIndex(CIx.HasFieldMarshal,field);
829 output.BlobIndex(ntIx);
834 /**************************************************************************/
836 /// Descriptor for the address of a field's value in the PE file
838 public class FieldRVA : MetaDataElement {
843 internal FieldRVA(Field field, DataConstant data)
847 tabIx = MDTable.FieldRVA;
850 internal sealed override void BuildTables(MetaData md)
857 internal sealed override uint Size(MetaData md)
859 return 4 + md.TableIndexSize(MDTable.Field);
862 internal sealed override void Write(FileImage output)
864 output.WriteDataRVA(data.DataOffset);
865 output.WriteIndex(MDTable.Field,field.Row);
870 /**************************************************************************/
872 /// Descriptor for a file referenced in THIS assembly/module (.file)
874 public class FileRef : MetaDataElement {
876 private static readonly uint NoMetaData = 0x1;
877 uint nameIx = 0, hashIx = 0;
879 protected string name;
881 internal FileRef(string name, byte[] hashBytes, bool metaData,
882 bool entryPoint, MetaData md) {
883 if (!metaData) flags = NoMetaData;
884 if (entryPoint) md.SetEntryPoint(this);
886 nameIx = md.AddToStringsHeap(name);
887 hashIx = md.AddToBlobHeap(hashBytes);
888 tabIx = MDTable.File;
891 internal FileRef(uint nameIx, byte[] hashBytes, bool metaData,
892 bool entryPoint, MetaData md) {
893 if (!metaData) flags = NoMetaData;
894 if (entryPoint) md.SetEntryPoint(this);
895 this.nameIx = nameIx;
896 hashIx = md.AddToBlobHeap(hashBytes);
897 tabIx = MDTable.File;
900 internal sealed override uint Size(MetaData md)
902 return 4 + md.StringsIndexSize() + md.BlobIndexSize();
905 internal sealed override void BuildTables(MetaData md)
907 md.AddToTable(MDTable.File,this);
910 internal sealed override void Write(FileImage output)
913 output.StringsIndex(nameIx);
914 output.BlobIndex(hashIx);
917 internal sealed override uint GetCodedIx(CIx code)
920 case (CIx.HasCustomAttr) : return 16;
921 case (CIx.Implementation) : return 0;
927 /**************************************************************************/
929 /// Descriptor for pinvoke information for a method NOT YET IMPLEMENTED
931 public class ImplMap : MetaDataElement {
933 private static readonly ushort NoMangle = 0x01;
938 ModuleRef importScope;
940 internal ImplMap(ushort flag, Method implMeth, string iName, ModuleRef mScope)
945 importScope = mScope;
946 tabIx = MDTable.ImplMap;
947 if (iName == null) flags |= NoMangle;
948 //throw(new NotYetImplementedException("PInvoke "));
951 internal override uint SortKey()
953 return (meth.Row << MetaData.CIxShiftMap[(uint)CIx.MemberForwarded])
954 | meth.GetCodedIx(CIx.MemberForwarded);
957 internal sealed override void BuildTables(MetaData md)
960 iNameIx = md.AddToStringsHeap(importName);
964 internal sealed override uint Size(MetaData md)
966 return 2+ md.CodedIndexSize(CIx.MemberForwarded) +
967 md.StringsIndexSize() + md.TableIndexSize(MDTable.ModuleRef);
970 internal sealed override void Write(FileImage output)
973 output.WriteCodedIndex(CIx.MemberForwarded,meth);
974 output.StringsIndex(iNameIx);
975 output.WriteIndex(MDTable.ModuleRef,importScope.Row);
980 /**************************************************************************/
982 public class GenericParameter : MetaDataElement {
984 MetaDataElement owner;
989 GenericParamAttributes attr;
991 internal GenericParameter (ClassDef owner, MetaData metadata,
992 short index, string name, GenericParamAttributes attr) : this (owner, metadata, index, name, attr, true)
996 internal GenericParameter (MethodDef owner, MetaData metadata,
997 short index, string name, GenericParamAttributes attr) : this (owner, metadata, index, name, attr, true)
1001 private GenericParameter (MetaDataElement owner, MetaData metadata,
1002 short index, string name, GenericParamAttributes attr, bool nadda) {
1004 this.metadata = metadata;
1006 tabIx = MDTable.GenericParam;
1011 internal override uint SortKey()
1013 return (owner.Row << MetaData.CIxShiftMap[(uint)CIx.TypeOrMethodDef])
1014 | owner.GetCodedIx(CIx.TypeOrMethodDef);
1017 internal override uint SortKey2 ()
1019 return (uint) index;
1022 public void AddConstraint (Type constraint)
1024 metadata.AddToTable (MDTable.GenericParamConstraint,
1025 new GenericParamConstraint (this, constraint));
1028 internal sealed override uint Size(MetaData md)
1031 md.CodedIndexSize(CIx.TypeOrMethodDef) +
1032 md.StringsIndexSize ());
1035 internal sealed override void BuildTables(MetaData md)
1038 nameIx = md.AddToStringsHeap(name);
1042 internal sealed override void Write(FileImage output)
1044 output.Write ((short) index);
1045 output.Write ((short) attr);
1046 output.WriteCodedIndex(CIx.TypeOrMethodDef, owner);
1047 output.StringsIndex (nameIx);
1050 internal sealed override uint GetCodedIx(CIx code)
1053 case (CIx.HasCustomAttr) : return 19;
1060 internal class GenericParamConstraint : MetaDataElement {
1062 GenericParameter param;
1065 public GenericParamConstraint (GenericParameter param, Type type)
1069 tabIx = MDTable.GenericParamConstraint;
1072 internal override uint SortKey()
1077 internal sealed override uint Size(MetaData md)
1079 return (uint) (md.TableIndexSize(MDTable.GenericParam) +
1080 md.CodedIndexSize(CIx.TypeDefOrRef));
1083 internal sealed override void Write(FileImage output)
1085 output.WriteIndex(MDTable.GenericParam, param.Row);
1086 output.WriteCodedIndex(CIx.TypeDefOrRef, type);
1091 internal class MethodSpec : Method {
1094 GenericMethodSig g_sig;
1097 internal MethodSpec (Method meth, GenericMethodSig g_sig) : base ("")
1101 tabIx = MDTable.MethodSpec;
1104 internal override uint GetSigIx (MetaData md)
1106 throw new Exception ("Should not be used.");
1109 public override void AddCallConv (CallConv cconv)
1111 throw new Exception ("Should not be used.");
1114 internal sealed override void BuildTables (MetaData md)
1117 sidx = g_sig.GetSigIx (md);
1121 internal sealed override uint Size (MetaData md)
1123 return (uint) (md.CodedIndexSize(CIx.MethodDefOrRef) +
1124 md.BlobIndexSize ());
1127 internal sealed override void Write (FileImage output)
1129 output.WriteCodedIndex (CIx.MethodDefOrRef, meth);
1130 output.BlobIndex (sidx);
1133 internal sealed override void TypeSig (MemoryStream sig)
1135 throw new Exception ("Should not be used.");
1139 /**************************************************************************/
1141 /// Descriptor for interface implemented by a class
1143 public class InterfaceImpl: MetaDataElement {
1148 internal InterfaceImpl(ClassDef theClass, Class theInterface)
1150 this.theClass = theClass;
1151 this.theInterface = theInterface;
1152 tabIx = MDTable.InterfaceImpl;
1155 internal sealed override uint Size(MetaData md)
1157 return md.TableIndexSize(MDTable.TypeDef) +
1158 md.CodedIndexSize(CIx.TypeDefOrRef);
1161 internal sealed override void Write(FileImage output)
1163 output.WriteIndex(MDTable.TypeDef,theClass.Row);
1164 output.WriteCodedIndex(CIx.TypeDefOrRef,theInterface);
1167 internal sealed override uint GetCodedIx(CIx code) { return 5; }
1169 internal override uint SortKey ()
1171 return (theClass.Row << MetaData.CIxShiftMap[(uint)CIx.TypeDefOrRef])
1172 | theClass.GetCodedIx (CIx.TypeDefOrRef);
1177 /**************************************************************************/
1179 /// Descriptor for resources used in this PE file
1182 public class ManifestResource : MetaDataElement {
1184 public static readonly uint PublicResource = 0x1;
1185 public static readonly uint PrivateResource = 0x2;
1188 MetaDataElement rRef;
1192 byte [] resourceBytes;
1194 public ManifestResource (string name, byte[] resBytes, uint flags)
1196 InitResource (name, flags);
1197 this.resourceBytes = resBytes;
1200 public ManifestResource(string name, uint flags, FileRef fileRef)
1202 InitResource (name, flags);
1206 public ManifestResource(string name, uint flags, FileRef fileRef,
1208 InitResource (name, flags);
1210 fileOffset = fileIx;
1213 public ManifestResource(string name, uint flags, AssemblyRef assemRef)
1215 InitResource (name, flags);
1219 internal ManifestResource (ManifestResource mres)
1221 mrName = mres.mrName;
1224 fileOffset = mres.fileOffset;
1225 resourceBytes = mres.resourceBytes;
1228 private void InitResource (string name, uint flags)
1232 tabIx = MDTable.ManifestResource;
1235 internal sealed override void BuildTables(MetaData md)
1238 md.AddToTable (MDTable.ManifestResource, this);
1239 nameIx = md.AddToStringsHeap(mrName);
1240 if (resourceBytes != null) {
1242 throw new PEFileException ("Manifest Resource has byte value and file reference");
1243 fileOffset = md.AddResource(resourceBytes);
1246 throw new PEFileException ("Manifest Resource has no implementation or value");
1247 rRef.BuildTables (md);
1253 internal sealed override uint Size(MetaData md)
1255 return 8 + md.StringsIndexSize() +
1256 md.CodedIndexSize(CIx.Implementation);
1259 internal sealed override void Write(FileImage output)
1261 output.Write(fileOffset);
1262 output.Write(flags);
1263 output.StringsIndex(nameIx);
1264 output.WriteCodedIndex(CIx.Implementation,rRef);
1267 internal sealed override uint GetCodedIx(CIx code) { return 18; }
1269 public string Name {
1270 get { return mrName; }
1271 set { mrName = value; }
1275 /**************************************************************************/
1277 /// Base class for elements in the PropertyMap, EventMap and
1278 /// NestedClass MetaData tables
1280 public class MapElem : MetaDataElement {
1286 internal MapElem(ClassDef par, uint elIx, MDTable elemTab)
1290 elemTable = elemTab;
1293 internal sealed override uint Size(MetaData md)
1295 return md.TableIndexSize(MDTable.TypeDef) + md.TableIndexSize(elemTable);
1298 internal sealed override void Write(FileImage output)
1300 output.WriteIndex(MDTable.TypeDef,parent.Row);
1301 output.WriteIndex(elemTable,elemIx);
1305 /**************************************************************************/
1307 /// Descriptor for an overriding method (.override)
1309 public class MethodImpl : MetaDataElement {
1312 Method header, body;
1314 internal MethodImpl(ClassDef par, Method decl, Method bod)
1319 tabIx = MDTable.MethodImpl;
1322 internal sealed override uint Size(MetaData md)
1324 return md.TableIndexSize(MDTable.TypeDef) + 2 * md.CodedIndexSize(CIx.MethodDefOrRef);
1327 internal sealed override void Write(FileImage output)
1329 output.WriteIndex(MDTable.TypeDef,parent.Row);
1330 output.WriteCodedIndex(CIx.MethodDefOrRef,body);
1331 output.WriteCodedIndex(CIx.MethodDefOrRef,header);
1336 /**************************************************************************/
1338 /// Descriptor for Property and Event methods
1340 public class MethodSemantics : MetaDataElement {
1342 Feature.MethodType type;
1344 Feature eventOrProp;
1346 internal MethodSemantics(Feature.MethodType mType, MethodDef method, Feature feature)
1350 eventOrProp = feature;
1351 tabIx = MDTable.MethodSemantics;
1354 internal override uint SortKey()
1356 return (eventOrProp.Row << MetaData.CIxShiftMap [(uint)CIx.HasSemantics])
1357 | eventOrProp.GetCodedIx (CIx.HasSemantics);
1360 internal sealed override uint Size(MetaData md)
1362 return 2 + md.TableIndexSize(MDTable.Method) + md.CodedIndexSize(CIx.HasSemantics);
1365 internal sealed override void Write(FileImage output)
1367 output.Write((ushort)type);
1368 output.WriteIndex(MDTable.Method,meth.Row);
1369 output.WriteCodedIndex(CIx.HasSemantics,eventOrProp);
1374 /**************************************************************************/
1376 /// Descriptor for a parameter of a method defined in this assembly/module
1378 public class Param : MetaDataElement {
1383 internal ushort seqNo = 0;
1385 ConstantElem defaultVal;
1387 FieldMarshal marshalInfo;
1390 /// Create a new parameter for a method
1392 /// <param name="mode">param mode (in, out, opt)</param>
1393 /// <param name="parName">parameter name</param>
1394 /// <param name="parType">parameter type</param>
1395 public Param(ParamAttr mode, string parName, Type parType)
1399 parMode = (ushort)mode;
1400 tabIx = MDTable.Param;
1403 public bool HasMarshalInfo {
1404 get { return marshalInfo != null; }
1408 /// Add a default value to this parameter
1410 /// <param name="c">the default value for the parameter</param>
1411 public void AddDefaultValue(Constant cVal)
1413 defaultVal = new ConstantElem(this,cVal);
1414 parMode |= (ushort) ParamAttr.HasDefault;
1418 /// Add marshalling information about this parameter
1420 public void AddMarshallInfo(NativeType marshallType)
1422 parMode |= (ushort) ParamAttr.HasFieldMarshal;
1423 marshalInfo = new FieldMarshal(this,marshallType);
1426 internal Type GetParType() { return pType; }
1428 internal sealed override void BuildTables(MetaData md)
1431 nameIx = md.AddToStringsHeap(pName);
1432 if (defaultVal != null) {
1433 md.AddToTable(MDTable.Constant,defaultVal);
1434 defaultVal.BuildTables(md);
1436 if (marshalInfo != null) {
1437 md.AddToTable(MDTable.FieldMarshal,marshalInfo);
1438 marshalInfo.BuildTables(md);
1443 internal void TypeSig(MemoryStream str)
1448 internal sealed override uint Size(MetaData md)
1450 return 4 + md.StringsIndexSize();
1453 internal sealed override void Write(FileImage output)
1455 output.Write(parMode);
1456 output.Write(seqNo);
1457 output.StringsIndex(nameIx);
1460 internal sealed override uint GetCodedIx(CIx code)
1463 case (CIx.HasCustomAttr) : return 4;
1464 case (CIx.HasConst) : return 1;
1465 case (CIx.HasFieldMarshal) : return 1;
1472 /**************************************************************************/
1473 public abstract class Signature : MetaDataElement {
1475 protected uint sigIx;
1477 internal Signature()
1479 tabIx = MDTable.StandAloneSig;
1482 internal sealed override uint Size(MetaData md)
1484 return md.BlobIndexSize();
1487 internal sealed override void Write(FileImage output)
1489 output.BlobIndex(sigIx);
1492 internal sealed override uint GetCodedIx(CIx code) { return (uint)tabIx; }
1496 /**************************************************************************/
1497 public class TypeSpec : MetaDataElement {
1500 internal TypeSpec(Type aType, MetaData md)
1502 MemoryStream sig = new MemoryStream();
1504 sigIx = md.AddToBlobHeap(sig.ToArray());
1505 tabIx = MDTable.TypeSpec;
1508 internal sealed override uint GetCodedIx(CIx code)
1511 case (CIx.TypeDefOrRef) : return 2;
1512 case (CIx.HasCustomAttr) : return 13;
1513 case (CIx.MemberRefParent) : return 4;
1518 internal override uint Size(MetaData md)
1520 return md.BlobIndexSize();
1523 internal sealed override void Write(FileImage output)
1525 //Console.WriteLine("Writing the blob index for a TypeSpec");
1526 output.BlobIndex(sigIx);
1531 /**************************************************************************/
1533 /// Base class for all IL types
1535 public abstract class Type : MetaDataElement {
1536 protected byte typeIndex;
1537 protected TypeSpec typeSpec;
1539 internal Type(byte tyIx) { typeIndex = tyIx; }
1541 internal byte GetTypeIndex() { return typeIndex; }
1542 internal void SetTypeIndex (byte b) { typeIndex = b; }
1544 internal virtual MetaDataElement GetTypeSpec(MetaData md)
1546 if (typeSpec == null) {
1547 typeSpec = new TypeSpec(this,md);
1548 md.AddToTable(MDTable.TypeSpec,typeSpec);
1553 internal virtual void TypeSig(MemoryStream str)
1555 throw(new TypeSignatureException(this.GetType().AssemblyQualifiedName +
1556 " doesn't have a type signature!!"));
1560 public class ClassRefInst : Type {
1563 private bool is_value;
1565 public ClassRefInst (Type type, bool is_value) : base (PrimitiveType.Class.GetTypeIndex ())
1568 this.is_value = is_value;
1570 typeIndex = PrimitiveType.ValueType.GetTypeIndex ();
1571 tabIx = MDTable.TypeSpec;
1574 internal sealed override void TypeSig(MemoryStream str)
1580 /**************************************************************************/
1582 /// The base descriptor for a class
1584 public abstract class Class : Type {
1586 protected int row = 0;
1587 public string name, nameSpace;
1588 protected uint nameIx, nameSpaceIx;
1589 protected MetaData _metaData;
1590 internal Class(string nameSpaceName, string className, MetaData md)
1591 : base(PrimitiveType.Class.GetTypeIndex ())
1593 nameSpace = nameSpaceName;
1595 nameIx = md.AddToStringsHeap(name);
1596 nameSpaceIx = md.AddToStringsHeap(nameSpace);
1600 internal Class(uint nsIx, uint nIx) : base(PrimitiveType.Class.GetTypeIndex ())
1606 internal Class (byte typeIndex) : base (typeIndex)
1608 nameSpace = "Should not be used";
1609 name = "Should not be used";
1612 internal virtual uint TypeDefOrRefToken() { return 0; }
1614 internal virtual void MakeValueClass(ValueClass vClass)
1616 typeIndex = PrimitiveType.ValueType.GetTypeIndex ();
1619 internal virtual string TypeName()
1621 return (nameSpace + "." + name);
1624 internal override MetaDataElement GetTypeSpec(MetaData md)
1630 /**************************************************************************/
1631 // This Class produces entries in the TypeDef table of the MetaData
1632 // in the PE meta data.
1634 // NOTE: Entry 0 in TypeDef table is always the pseudo class <module>
1635 // which is the parent for functions and variables declared a module level
1638 /// The descriptor for a class defined in the IL (.class) in the current assembly/module
1641 public class ClassDef : Class {
1645 ArrayList fields = new ArrayList();
1646 ArrayList methods = new ArrayList();
1648 ArrayList properties;
1649 bool typeIndexChecked = true;
1650 uint fieldIx = 0, methodIx = 0;
1653 ClassDef parentClass;
1656 internal ClassDef(TypeAttr attrSet, string nsName, string name,
1657 MetaData md) : base(nsName, name, md)
1660 flags = (uint)attrSet;
1661 tabIx = MDTable.TypeDef;
1664 internal void SetSuper(Class sClass)
1667 setSuperType = true;
1668 if (! (sClass is GenericTypeInst))
1669 typeIndexChecked = false;
1672 internal override void MakeValueClass(ValueClass vClass)
1674 if (vClass == ValueClass.Enum)
1675 superType = metaData.mscorlib.EnumType();
1677 superType = metaData.mscorlib.ValueType();
1679 setSuperType = true;
1680 typeIndex = PrimitiveType.ValueType.GetTypeIndex ();
1683 public void SpecialNoSuper()
1685 setSuperType = true;
1689 /// Add an attribute to this class
1691 /// <param name="ta">the attribute to be added</param>
1692 public void AddAttribute(TypeAttr ta)
1698 /// Add an interface that is implemented by this class
1700 /// <param name="iFace">the interface that is implemented</param>
1701 public void AddImplementedInterface(Class iFace)
1703 metaData.AddToTable(MDTable.InterfaceImpl,new InterfaceImpl(this,iFace));
1707 /// Add a named generic type parameter
1709 public GenericParameter AddGenericParameter (short index, string name)
1711 return AddGenericParameter (index, name, 0);
1715 /// Add a named generic type parameter with attributes
1717 public GenericParameter AddGenericParameter (short index, string name, GenericParamAttributes attr)
1719 GenericParameter gp = new GenericParameter (this, metaData, index, name, attr);
1720 metaData.AddToTable (MDTable.GenericParam, gp);
1725 /// Add a field to this class
1727 /// <param name="name">field name</param>
1728 /// <param name="fType">field type</param>
1729 /// <returns>a descriptor for this new field</returns>
1730 public FieldDef AddField(string name, Type fType)
1732 FieldDef field = new FieldDef(name,fType);
1738 /// Add a field to this class
1740 /// <param name="fAtts">attributes for this field</param>
1741 /// <param name="name">field name</param>
1742 /// <param name="fType">field type</param>
1743 /// <returns>a descriptor for this new field</returns>
1744 public FieldDef AddField(FieldAttr fAtts, string name, Type fType)
1746 FieldDef field = new FieldDef(fAtts,name,fType);
1751 public void SetFieldOrder (ArrayList fields)
1753 this.fields = fields;
1757 /// Add a method to this class
1759 /// <param name="name">method name</param>
1760 /// <param name="retType">return type</param>
1761 /// <param name="pars">parameters</param>
1762 /// <returns>a descriptor for this new method</returns>
1763 public MethodDef AddMethod(string name, Type retType, Param[] pars)
1765 return AddMethod (name, new Param (ParamAttr.Default, "", retType), pars);
1768 public MethodDef AddMethod (string name, Param ret_param, Param [] pars)
1770 // Console.WriteLine("Adding method " + name + " to class " + this.name);
1771 MethodDef meth = new MethodDef(metaData,name, ret_param, pars);
1777 /// Add a method to this class
1779 /// <param name="mAtts">attributes for this method</param>
1780 /// <param name="iAtts">implementation attributes for this method</param>
1781 /// <param name="name">method name</param>
1782 /// <param name="retType">return type</param>
1783 /// <param name="pars">parameters</param>
1784 /// <returns>a descriptor for this new method</returns>
1785 public MethodDef AddMethod(MethAttr mAtts, ImplAttr iAtts, string name,
1786 Param ret_param, Param [] pars) {
1787 // Console.WriteLine("Adding method " + name + " to class " + this.name);
1788 MethodDef meth = new MethodDef (metaData, mAtts, iAtts, name, ret_param, pars);
1794 /// Add an event to this class
1796 /// <param name="name">event name</param>
1797 /// <param name="eType">event type</param>
1798 /// <returns>a descriptor for this new event</returns>
1799 public Event AddEvent(string name, Type eType)
1801 Event e = new Event(name,eType,this);
1802 if (events == null) events = new ArrayList();
1808 /// Add a property to this class
1810 /// <param name="name">property name</param>
1811 /// <param name="propType">property type</param>
1812 /// <returns>a descriptor for this new property</returns>
1813 public Property AddProperty(string name, Type retType, Type[] pars)
1815 Property p = new Property(name, retType, pars, this);
1816 if (properties == null) properties = new ArrayList();
1822 /// Add a nested class to this class
1824 /// <param name="attrSet">attributes for this nested class</param>
1825 /// <param name="nsName">nested name space name</param>
1826 /// <param name="name">nested class name</param>
1827 /// <returns>a descriptor for this new nested class</returns>
1828 public ClassDef AddNestedClass(TypeAttr attrSet, string nsName,
1830 ClassDef nClass = new ClassDef(attrSet,"",name,metaData);
1831 metaData.AddToTable(MDTable.TypeDef,nClass);
1832 metaData.AddToTable(MDTable.NestedClass,new MapElem(nClass,Row,MDTable.TypeDef));
1833 nClass.parentClass = this;
1837 public static bool IsValueType (Class type)
1839 return IsValueType (type.nameSpace, type.name);
1842 public static bool IsEnum (Class type)
1844 return IsEnum (type.nameSpace, type.name);
1847 public static bool IsValueType (string nsName, string name)
1849 return (nsName == "System" && name == "ValueType");
1852 public static bool IsEnum (string nsName, string name)
1854 return (nsName == "System" && name == "Enum");
1858 /// Add a nested class to this class
1860 /// <param name="attrSet">attributes for this nested class</param>
1861 /// <param name="nsName">nested name space name</param>
1862 /// <param name="name">nested class name</param>
1863 /// <param name="sType">super type of this nested class</param>
1864 /// <returns>a descriptor for this new nested class</returns>
1865 public ClassDef AddNestedClass(TypeAttr attrSet, string nsName,
1866 string name, Class sType) {
1867 ClassDef nClass = AddNestedClass (attrSet, nsName, name);
1868 nClass.SetSuper(sType);
1869 if (ClassDef.IsValueType (sType))
1870 nClass.MakeValueClass (ValueClass.ValueType);
1872 if (ClassDef.IsEnum (sType))
1873 nClass.MakeValueClass (ValueClass.Enum);
1875 if (ClassDef.IsValueType (sType) || ClassDef.IsEnum (sType))
1876 nClass.SetTypeIndex (PrimitiveType.ValueType.GetTypeIndex ());
1878 nClass.typeIndexChecked = true;
1883 /// Add layout information for this class. This class must have the
1884 /// sequential or explicit attribute.
1886 /// <param name="packSize">packing size (.pack)</param>
1887 /// <param name="classSize">class size (.size)</param>
1888 public void AddLayoutInfo (int packSize, int classSize)
1890 layout = new ClassLayout(packSize,classSize,this);
1894 /// Use a method as the implementation for another method (.override)
1896 /// <param name="decl">the method to be overridden</param>
1897 /// <param name="body">the implementation to be used</param>
1898 public void AddMethodOverride(Method decl, Method body)
1900 metaData.AddToTable(MDTable.MethodImpl,new MethodImpl(this,decl,body));
1904 /// Add security to this class NOT YET IMPLEMENTED
1906 /// <param name="permissionSet"></param>
1907 public void AddSecurity(byte[] permissionSet)
1909 throw(new NotYetImplementedException("Class security "));
1910 //flags |= HasSecurity;
1911 // securityActions = permissionSet;
1914 //public void AddLineInfo(int row, int col) { }
1916 internal void CheckTypeIndex()
1918 if (typeIndexChecked) return;
1919 if (superType is ClassDef)
1920 ((ClassDef)superType).CheckTypeIndex();
1921 typeIndex = superType.GetTypeIndex();
1922 typeIndexChecked = true;
1925 internal sealed override void BuildTables(MetaData md)
1930 if ((flags & (uint)TypeAttr.Interface) != 0) {
1932 setSuperType = true;
1934 // Console.WriteLine("Building tables for " + name);
1935 if (layout != null) md.AddToTable(MDTable.ClassLayout,layout);
1936 // Console.WriteLine("adding methods " + methods.Count);
1937 methodIx = md.TableIndex(MDTable.Method);
1938 for (int i=0; i < methods.Count; i++) {
1939 md.AddToTable(MDTable.Method,(MetaDataElement)methods[i]);
1940 ((MethodDef)methods[i]).BuildTables(md);
1942 // Console.WriteLine("adding fields");
1943 fieldIx = md.TableIndex(MDTable.Field);
1944 for (int i=0; i < fields.Count; i++) {
1945 md.AddToTable(MDTable.Field,(MetaDataElement)fields[i]);
1946 ((FieldDef)fields[i]).BuildTables(md);
1948 // Console.WriteLine("adding events and properties");
1949 if (events != null) {
1950 for (int i=0; i < events.Count; i++) {
1951 md.AddToTable(MDTable.Event,(Event)events[i]);
1952 ((Event)events[i]).BuildTables(md);
1954 md.AddToTable(MDTable.EventMap,
1955 new MapElem(this,((Event)events[0]).Row,MDTable.Event));
1957 if (properties != null) {
1958 for (int i=0; i < properties.Count; i++) {
1959 md.AddToTable(MDTable.Property,(Property)properties[i]);
1960 ((Property)properties[i]).BuildTables(md);
1962 md.AddToTable(MDTable.PropertyMap,new MapElem(this,
1963 ((Property)properties[0]).Row,MDTable.Property));
1965 // Console.WriteLine("End of building tables");
1968 superType = metaData.mscorlib.GetSpecialSystemClass(PrimitiveType.Object);
1973 internal sealed override uint Size(MetaData md)
1975 return 4 + 2 * md.StringsIndexSize() +
1976 md.CodedIndexSize(CIx.TypeDefOrRef) +
1977 md.TableIndexSize(MDTable.Field) +
1978 md.TableIndexSize(MDTable.Method);
1981 internal sealed override void Write(FileImage output)
1983 output.Write(flags);
1984 output.StringsIndex(nameIx);
1985 output.StringsIndex(nameSpaceIx);
1986 //if (superType != null)
1987 // Console.WriteLine("getting coded index for superType of " + name + " = " + superType.GetCodedIx(CIx.TypeDefOrRef));
1988 output.WriteCodedIndex(CIx.TypeDefOrRef,superType);
1989 output.WriteIndex(MDTable.Field,fieldIx);
1990 output.WriteIndex(MDTable.Method,methodIx);
1993 internal sealed override uint TypeDefOrRefToken()
2000 internal sealed override void TypeSig(MemoryStream sig)
2002 if (!typeIndexChecked) CheckTypeIndex();
2003 sig.WriteByte(GetTypeIndex());
2004 MetaData.CompressNum(TypeDefOrRefToken(),sig);
2007 internal sealed override uint GetCodedIx(CIx code)
2010 case (CIx.TypeDefOrRef) : return 0;
2011 case (CIx.HasCustomAttr) : return 3;
2012 case (CIx.HasDeclSecurity) : return 0;
2013 case (CIx.TypeOrMethodDef) : return 0;
2020 /**************************************************************************/
2022 /// Descriptor for a class/interface declared in another module of THIS
2023 /// assembly, or in another assembly.
2025 public class ClassRef : Class, IExternRef, IResolutionScope {
2027 protected IResolutionScope parent;
2028 protected MetaData metaData;
2030 internal ClassRef(string nsName, string name, MetaData md) : base(nsName, name, md)
2033 tabIx = MDTable.TypeRef;
2037 /// Add a method to this class
2039 /// <param name="name">method name</param>
2040 /// <param name="retType">return type</param>
2041 /// <param name="pars">parameter types</param>
2042 /// <returns>a descriptor for this method</returns>
2043 public MethodRef AddMethod(string name, Type retType, Type[] pars)
2045 return AddMethod (name, retType, pars, 0);
2049 /// Add a method to this class
2051 /// <param name="name">method name</param>
2052 /// <param name="retType">return type</param>
2053 /// <param name="pars">parameter types</param>
2054 /// <param name="gen_param_count">num of generic parameters</param>
2055 /// <returns>a descriptor for this method</returns>
2056 public MethodRef AddMethod (string name, Type retType, Type[] pars, int gen_param_count)
2058 MethodRef meth = new MethodRef (this, name, retType, pars, false, null, gen_param_count);
2059 metaData.AddToTable(MDTable.MemberRef,meth);
2064 /// Add a method to this class
2066 /// <param name="name">method name</param>
2067 /// <param name="retType">return type</param>
2068 /// <param name="pars">parameter types</param>
2069 /// <returns>a descriptor for this method</returns>
2070 public MethodRef AddVarArgMethod(string name, Type retType,
2071 Type[] pars, Type[] optPars)
2073 MethodRef meth = new MethodRef(this,name,retType,pars,true,optPars, 0);
2074 metaData.AddToTable(MDTable.MemberRef,meth);
2079 /// Add a field to this class
2081 /// <param name="name">field name</param>
2082 /// <param name="fType">field type</param>
2083 /// <returns>a descriptor for this field</returns>
2084 public FieldRef AddField(string name, Type fType)
2086 FieldRef field = new FieldRef(this,name,fType);
2087 metaData.AddToTable(MDTable.MemberRef,field);
2091 public ClassRef AddClass (string nsName, string name)
2093 ClassRef aClass = new ClassRef(nsName,name,metaData);
2094 metaData.AddToTable(MDTable.TypeRef,aClass);
2095 aClass.SetParent(this);
2099 public ClassRef AddValueClass (string nsName, string name)
2101 ClassRef aClass = AddClass (nsName, name);
2102 aClass.MakeValueClass (ValueClass.ValueType);
2106 internal void SetParent(IResolutionScope par)
2111 internal override string TypeName()
2113 if ((parent != null) && (parent is AssemblyRef))
2114 return (nameSpace + "." + name + ", " + ((AssemblyRef)parent).TypeName());
2116 return (nameSpace + name);
2119 internal sealed override uint Size(MetaData md)
2121 return md.CodedIndexSize(CIx.ResolutionScope) + 2 *
2122 md.StringsIndexSize();
2125 internal sealed override void Write(FileImage output)
2127 output.WriteCodedIndex(CIx.ResolutionScope,(MetaDataElement) parent);
2128 output.StringsIndex(nameIx);
2129 output.StringsIndex(nameSpaceIx);
2132 internal override sealed uint TypeDefOrRefToken()
2135 cIx = (cIx << 2) | 0x1;
2139 internal override void TypeSig(MemoryStream sig)
2141 sig.WriteByte(GetTypeIndex());
2142 MetaData.CompressNum(TypeDefOrRefToken(),sig);
2145 internal sealed override uint GetCodedIx(CIx code)
2148 case (CIx.TypeDefOrRef) : return 1;
2149 case (CIx.HasCustomAttr) : return 2;
2150 case (CIx.MemberRefParent) : return 1;
2151 case (CIx.ResolutionScope) : return 3;
2158 /**************************************************************************/
2159 public class ExternClassRef : ClassRef {
2161 ExternClass externClass;
2163 internal ExternClassRef(TypeAttr attrs, string nsName, string name,
2164 MetaDataElement declRef, MetaData md) : base(nsName,name,md)
2166 externClass = new ExternClass(attrs,nameSpaceIx,nameIx,declRef);
2167 metaData.AddToTable(MDTable.ExportedType,externClass);
2170 internal ExternClassRef(string name, MetaData md) : base(null,name,md)
2174 public ClassRef AddNestedClass(TypeAttr attrs, string name)
2176 ExternClassRef nestedClass = new ExternClassRef(name,metaData);
2177 externClass = new ExternClass(attrs,0,nameIx,this.externClass);
2178 metaData.AddToTable(MDTable.ExportedType,externClass);
2184 /**************************************************************************/
2186 /// Descriptor for a class defined in another module of THIS assembly
2187 /// and exported (.class extern)
2190 internal class ExternClass : Class {
2192 MetaDataElement parent;
2195 internal ExternClass(TypeAttr attr, uint nsIx, uint nIx,
2196 MetaDataElement paren) : base(nsIx,nIx)
2200 tabIx = MDTable.ExportedType;
2203 internal sealed override uint Size(MetaData md)
2205 return 8 + 2* md.StringsIndexSize() + md.CodedIndexSize(CIx.Implementation);
2208 internal sealed override void Write(FileImage output)
2210 output.Write(flags);
2212 output.StringsIndex(nameIx);
2213 output.StringsIndex(nameSpaceIx);
2214 output.WriteCodedIndex(CIx.Implementation,parent);
2217 internal sealed override uint GetCodedIx(CIx code)
2220 case (CIx.HasCustomAttr) : return 17;
2221 case (CIx.Implementation) : return 2;
2228 public class GenParam : Class {
2231 private string param_name;
2232 private uint sigIx = 0;
2234 public GenParam (int index, string name, GenParamType ptype) : base ((byte) ptype)
2237 this.param_name = name;
2238 tabIx = MDTable.TypeSpec;
2242 get { return index; }
2243 set { index = value; }
2246 public string Name {
2247 get { return param_name; }
2248 set { param_name = value; }
2251 public GenParamType Type {
2252 get { return (GenParamType) GetTypeIndex (); }
2255 internal sealed override void BuildTables (MetaData md)
2259 MemoryStream str = new MemoryStream ();
2261 sigIx = md.AddToBlobHeap (str.ToArray ());
2266 internal sealed override void TypeSig(MemoryStream str)
2269 throw new PEFileException (String.Format ("Unresolved {0} - {1}", (GenParamType) GetTypeIndex (), param_name));
2270 str.WriteByte(typeIndex);
2271 MetaData.CompressNum ((uint) index, str);
2274 internal override uint Size(MetaData md)
2276 return md.BlobIndexSize();
2279 internal sealed override void Write (FileImage output)
2281 output.BlobIndex (sigIx);
2284 internal sealed override uint GetCodedIx(CIx code)
2287 case (CIx.TypeDefOrRef) : return 2;
2288 case (CIx.HasCustomAttr) : return 13;
2289 case (CIx.MemberRefParent) : return 4;
2295 public class GenericTypeInst : Class {
2297 private Type gen_type;
2298 private Type[] gen_param;
2299 bool inTable = false;
2302 public GenericTypeInst (Type gen_type, Type[] gen_param)
2303 : base ((byte) PrimitiveType.GenericInst.GetTypeIndex ())
2305 this.gen_type = gen_type;
2306 this.gen_param = gen_param;
2307 tabIx = MDTable.TypeSpec;
2310 internal override MetaDataElement GetTypeSpec (MetaData md)
2313 md.AddToTable (MDTable.TypeSpec, this);
2320 internal sealed override void TypeSig(MemoryStream str)
2322 str.WriteByte(typeIndex);
2323 gen_type.TypeSig (str);
2324 MetaData.CompressNum ((uint) gen_param.Length, str);
2325 foreach (Type param in gen_param)
2326 param.TypeSig (str);
2329 internal sealed override void BuildTables (MetaData md)
2333 MemoryStream str = new MemoryStream ();
2335 sigIx = md.AddToBlobHeap (str.ToArray ());
2340 internal sealed override uint Size (MetaData md)
2342 return md.BlobIndexSize ();
2345 internal sealed override void Write (FileImage output)
2347 output.BlobIndex (sigIx);
2350 internal sealed override uint GetCodedIx (CIx code)
2353 case (CIx.TypeDefOrRef): return 2;
2354 case (CIx.MemberRefParent): return 4;
2355 case (CIx.HasCustomAttr): return 13;
2361 public class GenericMethodSig {
2363 private Type[] gen_param;
2365 private uint sigIx = 0;
2367 public GenericMethodSig (Type[] gen_param)
2369 this.gen_param = gen_param;
2373 internal void TypeSig (MemoryStream str)
2375 str.WriteByte (0x0A); /* GENERIC_INST */
2376 MetaData.CompressNum ((uint) gen_param.Length, str);
2377 foreach (Type param in gen_param)
2378 param.TypeSig (str);
2381 internal uint GetSigIx (MetaData md)
2386 MemoryStream sig = new MemoryStream();
2388 sigIx = md.AddToBlobHeap (sig.ToArray());
2394 public class Sentinel : Type {
2396 public Sentinel () : base (0x41) { }
2398 internal sealed override void TypeSig(MemoryStream str)
2400 str.WriteByte(typeIndex);
2404 /**************************************************************************/
2406 /// Descriptor for a FunctionPointer type
2409 public class MethPtrType : Type {
2421 /// Create a new function pointer type
2423 /// <param name="meth">the function to be referenced</param>
2424 public MethPtrType (CallConv callconv, Type retType, Type[] pars,
2425 bool varArgMeth, Type[] optPars) : base(0x1B)
2427 this.retType = retType;
2428 callConv = callconv;
2430 this.varArgMeth = varArgMeth;
2431 if (parList != null) numPars = (uint)parList.Length;
2433 optParList = optPars;
2434 if (optParList != null) numOptPars = (uint)optParList.Length;
2435 callConv |= CallConv.Vararg;
2437 tabIx = MDTable.TypeSpec;
2440 internal sealed override void TypeSig(MemoryStream sig)
2442 sig.WriteByte(typeIndex);
2443 // Bootlegged from method ref
2444 sig.WriteByte((byte)callConv);
2445 MetaData.CompressNum (numPars + numOptPars, sig);
2446 retType.TypeSig (sig);
2447 for (int i=0; i < numPars; i++) {
2448 parList[i].TypeSig (sig);
2451 sig.WriteByte (0x41); // Write the sentinel
2452 for (int i=0; i < numOptPars; i++) {
2453 optParList[i].TypeSig (sig);
2458 internal sealed override void BuildTables(MetaData md)
2461 MemoryStream sig = new MemoryStream();
2463 sigIx = md.AddToBlobHeap(sig.ToArray());
2467 internal sealed override uint Size(MetaData md)
2469 return md.BlobIndexSize();
2472 internal sealed override void Write(FileImage output)
2474 output.BlobIndex(sigIx);
2477 internal sealed override uint GetCodedIx(CIx code) { return 0x1B; }
2482 /* Classes for Arrays */
2485 /// The IL Array type
2487 public abstract class Array : Type {
2489 protected Type elemType;
2490 protected MetaData metaData;
2491 protected string cnameSpace, cname;
2493 internal Array(Type eType, byte TypeId) : base(TypeId)
2496 tabIx = MDTable.TypeSpec;
2501 /// Single dimensional array with zero lower bound
2503 public class ZeroBasedArray : Array {
2506 /// Create a new array - elementType[]
2508 /// <param name="elementType">the type of the array elements</param>
2509 public ZeroBasedArray(Type elementType) : base (elementType, PrimitiveType.SZArray.GetTypeIndex ()) { }
2511 internal sealed override void TypeSig(MemoryStream str)
2513 str.WriteByte(typeIndex);
2514 elemType.TypeSig(str);
2520 /// Multi dimensional array with explicit bounds
2522 public class BoundArray : Array {
2528 /// Create a new multi dimensional array type
2529 /// eg. elemType[1..5,3..10,5,,] would be
2530 /// new BoundArray(elemType,5,[1,3,0],[5,10,4])
2532 /// <param name="elementType">the type of the elements</param>
2533 /// <param name="dimensions">the number of dimensions</param>
2534 /// <param name="loBounds">lower bounds of dimensions</param>
2535 /// <param name="sizes">sizes for the dimensions</param>
2536 public BoundArray(Type elementType, uint dimensions, int[] loBounds,
2537 int[] sizes) : base (elementType,0x14)
2539 numDims = dimensions;
2540 lowerBounds = loBounds;
2545 /// Create a new multi dimensional array type
2546 /// eg. elemType[5,10,20] would be new BoundArray(elemType,3,[5,10,20])
2548 /// <param name="elementType">the type of the elements</param>
2549 /// <param name="dimensions">the number of dimensions</param>
2550 /// <param name="size">the sizes of the dimensions</param>
2551 public BoundArray(Type elementType, uint dimensions, int[] size)
2552 : base (elementType,0x14)
2554 numDims = dimensions;
2559 /// Create a new multi dimensional array type
2560 /// eg. elemType[,,] would be new BoundArray(elemType,3)
2562 /// <param name="elementType">the type of the elements</param>
2563 /// <param name="dimensions">the number of dimensions</param>
2564 public BoundArray(Type elementType, uint dimensions)
2565 : base (elementType,0x14)
2567 numDims = dimensions;
2570 internal sealed override void TypeSig(MemoryStream str)
2572 str.WriteByte(typeIndex);
2573 elemType.TypeSig(str);
2574 MetaData.CompressNum(numDims,str);
2575 if ((sizes != null) && (sizes.Length > 0)) {
2577 MetaData.CompressNum((uint)sizes.Length,str);
2578 for (int i=0; i < sizes.Length; i++) {
2579 MetaData.CompressNum((uint)sizes[i],str);
2581 } else str.WriteByte(0);
2582 if ((lowerBounds != null) && (lowerBounds.Length > 0)) {
2583 MetaData.CompressNum((uint)lowerBounds.Length,str);
2584 for (int i=0; i < lowerBounds.Length; i++) {
2585 CompressSignedNum (lowerBounds[i],str);
2587 } else str.WriteByte(0);
2589 private void CompressSignedNum (int val, MemoryStream str)
2591 uint uval = (uint) val;
2598 /* Map the signed number to an unsigned number in two ways.
2600 fval: left-rotated 2's complement representation
2601 sval: map the signed number to unsigned as follows: 0 -> 0, -1 -> 1, 1 -> 2, -2 -> 3, 2 -> 4, ....
2602 the mapping is: x -> 2*|x| - signbit(x)
2604 uint fval = (uval << 1) | sign;
2605 int sval = (val << 1) - sign;
2607 /* An overly clever transformation:
2609 a. sval is used to determine the number of bytes in the compressed representation.
2610 b. fval is truncated to the appropriate number of bits and output using the
2611 normal unsigned-int compressor.
2613 However, or certain values, the truncated fval doesn't carry enough information to round trip.
2615 (fval & 0x3FFF) <= 0x7F => compressor emits 1 byte, not 2 => there is aliasing of values
2617 So, we use full 4 bytes to encode such values.
2619 LAMESPEC: The Microsoft implementation doesn't appear to handle this subtle case.
2620 e.g., it ends up encoding -8192 as the byte 0x01, which decodes to -64
2623 MetaData.CompressNum (fval & 0x7F, str);
2624 else if (sval <= 0x3FFF && (fval & 0x3FFF) > 0x7F)
2625 MetaData.CompressNum (fval & 0x3FFF, str);
2626 else if (sval <= 0x1FFFFFFF && (fval & 0x1FFFFFFF) > 0x3FFF)
2627 MetaData.CompressNum (fval & 0x1FFFFFFF, str);
2629 /* FIXME: number cannot be represented. Report a warning. */
2630 // throw new Exception ("cannot represent signed value" + -val);
2631 MetaData.CompressNum (fval, str);
2638 /* Empty interface for grouping TypeRef's possible ResolutionScope
2639 namely : Module, ModuleRef, AssemblyRef and TypeRef */
2640 public interface IResolutionScope {
2643 /**************************************************************************/
2645 /// Base class for scopes (extended by Module, ModuleRef, Assembly, AssemblyRef)
2647 public abstract class ResolutionScope : MetaDataElement, IResolutionScope {
2649 protected uint nameIx = 0;
2650 protected MetaData metaData;
2651 protected string name;
2653 internal ResolutionScope(string name, MetaData md)
2657 nameIx = md.AddToStringsHeap(name);
2660 internal string GetName() { return name; }
2664 /**************************************************************************/
2666 /// Descriptor for THIS assembly (.assembly)
2668 public class Assembly : ResolutionScope {
2670 ushort majorVer, minorVer, buildNo, revisionNo;
2673 uint keyIx = 0, cultIx = 0;
2674 bool hasPublicKey = false;
2676 internal Assembly(string name, MetaData md) : base(name,md)
2678 tabIx = MDTable.Assembly;
2682 /// Add details about THIS assembly
2684 /// <param name="majVer">Major Version</param>
2685 /// <param name="minVer">Minor Version</param>
2686 /// <param name="bldNo">Build Number</param>
2687 /// <param name="revNo">Revision Number</param>
2688 /// <param name="key">Hash Key</param>
2689 /// <param name="hash">Hash Algorithm</param>
2690 /// <param name="cult">Culture</param>
2691 public void AddAssemblyInfo(int majVer, int minVer, int bldNo, int revNo,
2692 byte[] key, uint hash, string cult)
2694 majorVer = (ushort)majVer;
2695 minorVer = (ushort)minVer;
2696 buildNo = (ushort)bldNo;
2697 revisionNo = (ushort)revNo;
2699 hasPublicKey = (key != null);
2700 keyIx = metaData.AddToBlobHeap(key);
2701 cultIx = metaData.AddToStringsHeap(cult);
2705 /// Add an attribute to THIS assembly
2707 /// <param name="aa">assembly attribute</param>
2708 public void AddAssemblyAttr(AssemAttr aa)
2713 internal sealed override uint Size(MetaData md)
2715 return 16 + md.BlobIndexSize() + 2 * md.StringsIndexSize();
2718 internal sealed override void Write(FileImage output)
2720 // Console.WriteLine("Writing assembly element with nameIx of " + nameIx + " at file offset " + output.Seek(0,SeekOrigin.Current));
2721 output.Write((uint)hashAlgId);
2722 output.Write(majorVer);
2723 output.Write(minorVer);
2724 output.Write(buildNo);
2725 output.Write(revisionNo);
2726 output.Write(flags);
2727 output.BlobIndex(keyIx);
2728 output.StringsIndex(nameIx);
2729 output.StringsIndex(cultIx);
2732 internal sealed override uint GetCodedIx(CIx code)
2735 case (CIx.HasCustomAttr) : return 14;
2736 case (CIx.HasDeclSecurity) : return 2;
2741 internal bool HasPublicKey {
2742 get { return hasPublicKey; }
2746 /**************************************************************************/
2748 /// Descriptor for THIS module
2750 public class Module : ResolutionScope, IExternRef {
2755 internal Module(string name, MetaData md) : base(name,md)
2757 mvid = Guid.NewGuid();
2758 mvidIx = md.AddToGUIDHeap(mvid);
2759 tabIx = MDTable.Module;
2763 get { return mvid; }
2766 public ClassRef AddClass(string nsName, string name)
2768 ClassRef aClass = new ClassRef (nsName, name, metaData);
2769 metaData.AddToTable (MDTable.TypeRef, aClass);
2770 aClass.SetParent (this);
2774 public ClassRef AddValueClass(string nsName, string name)
2776 ClassRef aClass = AddClass (nsName, name);
2777 aClass.MakeValueClass (ValueClass.ValueType);
2781 internal sealed override uint Size(MetaData md)
2783 return 2 + md.StringsIndexSize() + 3 * md.GUIDIndexSize();
2786 internal sealed override void Write(FileImage output)
2788 output.Write((short)0);
2789 output.StringsIndex(nameIx);
2790 output.GUIDIndex(mvidIx);
2791 output.GUIDIndex(0);
2792 output.GUIDIndex(0);
2795 internal sealed override uint GetCodedIx(CIx code)
2798 case (CIx.HasCustomAttr) : return 7;
2799 case (CIx.ResolutionScope) : return 0;
2804 /**************************************************************************/
2806 /// Descriptor for another module in THIS assembly
2808 public class ModuleRef : ResolutionScope, IExternRef {
2810 internal ModuleRef(MetaData md, string name) : base(name,md)
2812 tabIx = MDTable.ModuleRef;
2816 /// Add a class to this external module. This is a class declared in
2817 /// another module of THIS assembly.
2819 /// <param name="nsName">name space name</param>
2820 /// <param name="name">class name</param>
2821 /// <returns>a descriptor for this class in another module</returns>
2822 public ClassRef AddClass(string nsName, string name)
2824 ClassRef aClass = new ClassRef(nsName,name,metaData);
2825 metaData.AddToTable(MDTable.TypeRef,aClass);
2826 aClass.SetParent(this);
2831 /// Make a file descriptor to correspond to this module. The file
2832 /// descriptor will have the same name as the module descriptor
2834 /// <param name="hashBytes">the hash of the file</param>
2835 /// <param name="hasMetaData">the file contains metadata</param>
2836 /// <param name="entryPoint">the program entry point is in this file</param>
2837 /// <returns>a descriptor for the file which contains this module</returns>
2838 public FileRef MakeFile(byte[] hashBytes, bool hasMetaData, bool entryPoint)
2840 FileRef file = new FileRef(nameIx,hashBytes,hasMetaData,entryPoint,metaData);
2841 metaData.AddToTable(MDTable.File,file);
2846 /// Add a value class to this module. This is a class declared in
2847 /// another module of THIS assembly.
2849 /// <param name="nsName">name space name</param>
2850 /// <param name="name">class name</param>
2851 /// <returns></returns>
2852 public ClassRef AddValueClass(string nsName, string name)
2854 ClassRef aClass = new ClassRef(nsName,name,metaData);
2855 metaData.AddToTable(MDTable.TypeRef,aClass);
2856 aClass.SetParent(this);
2857 aClass.MakeValueClass(ValueClass.ValueType);
2862 /// Add a class which is declared public in this external module of
2863 /// THIS assembly. This class will be exported from this assembly.
2864 /// The ilasm syntax for this is .extern class
2866 /// <param name="attrSet">attributes of the class to be exported</param>
2867 /// <param name="nsName">name space name</param>
2868 /// <param name="name">external class name</param>
2869 /// <param name="declFile">the file where the class is declared</param>
2870 /// <param name="isValueClass">is this class a value type?</param>
2871 /// <returns>a descriptor for this external class</returns>
2872 public ExternClassRef AddExternClass(TypeAttr attrSet, string nsName,
2873 string name, FileRef declFile,
2874 bool isValueClass) {
2875 ExternClassRef cRef = new ExternClassRef(attrSet,nsName,name,declFile,metaData);
2876 metaData.AddToTable(MDTable.TypeRef,cRef);
2877 cRef.SetParent(this);
2878 if (isValueClass) cRef.MakeValueClass(ValueClass.ValueType);
2883 /// Add a "global" method in another module
2885 /// <param name="name">method name</param>
2886 /// <param name="retType">return type</param>
2887 /// <param name="pars">method parameter types</param>
2888 /// <returns>a descriptor for this method in anther module</returns>
2889 public MethodRef AddMethod(string name, Type retType, Type[] pars)
2891 MethodRef meth = new MethodRef(this,name,retType,pars,false,null, 0);
2892 metaData.AddToTable(MDTable.MemberRef,meth);
2897 /// Add a vararg method to this class
2899 /// <param name="name">method name</param>
2900 /// <param name="retType">return type</param>
2901 /// <param name="pars">parameter types</param>
2902 /// <param name="optPars">optional param types for this vararg method</param>
2903 /// <returns>a descriptor for this method</returns>
2904 public MethodRef AddVarArgMethod(string name, Type retType,
2905 Type[] pars, Type[] optPars) {
2906 MethodRef meth = new MethodRef(this,name,retType,pars,true,optPars, 0);
2907 metaData.AddToTable(MDTable.MemberRef,meth);
2912 /// Add a field in another module
2914 /// <param name="name">field name</param>
2915 /// <param name="fType">field type</param>
2916 /// <returns>a descriptor for this field in another module</returns>
2917 public FieldRef AddField(string name, Type fType)
2919 FieldRef field = new FieldRef(this,name,fType);
2920 metaData.AddToTable(MDTable.MemberRef,field);
2924 internal sealed override uint Size(MetaData md)
2926 return md.StringsIndexSize();
2929 internal sealed override void Write(FileImage output)
2931 output.StringsIndex(nameIx);
2934 internal sealed override uint GetCodedIx(CIx code)
2937 case (CIx.HasCustomAttr) : return 12;
2938 case (CIx.MemberRefParent) : return 2;
2939 case (CIx.ResolutionScope) : return 1;
2946 #region Classes for Constants
2948 /// Descriptor for a constant value
2950 public abstract class Constant {
2951 protected uint size = 0;
2952 protected Type type;
2953 protected uint blobIndex;
2954 protected bool addedToBlobHeap = false;
2956 internal Constant() { }
2958 internal virtual uint GetBlobIndex(MetaData md) { return 0; }
2960 internal uint GetSize() { return size; }
2962 internal byte GetTypeIndex() { return type.GetTypeIndex(); }
2964 internal virtual void Write(BinaryWriter bw) { }
2968 /// Descriptor for a constant value
2970 public abstract class DataConstant : Constant {
2971 private uint dataOffset = 0;
2973 internal DataConstant() { }
2975 public uint DataOffset {
2976 get { return dataOffset; }
2977 set { dataOffset = value; }
2983 /// Boolean constant
2985 public class BoolConst : DataConstant {
2989 /// Create a new boolean constant with the value "val"
2991 /// <param name="val">value of this boolean constant</param>
2992 public BoolConst(bool val)
2996 type = PrimitiveType.Boolean;
2999 internal sealed override uint GetBlobIndex(MetaData md)
3001 if (!addedToBlobHeap) {
3002 if (val) blobIndex = md.AddToBlobHeap((sbyte)1);
3003 else blobIndex = md.AddToBlobHeap((sbyte)0);
3004 addedToBlobHeap = true;
3009 internal sealed override void Write(BinaryWriter bw)
3011 if (val) bw.Write((sbyte)1);
3012 else bw.Write((sbyte)0);
3017 public class ByteArrConst : DataConstant {
3018 internal byte[] val;
3020 public ByteArrConst(byte[] val)
3022 type = PrimitiveType.String;
3024 size = (uint)val.Length;
3028 get { return type; }
3029 set { type = value; }
3032 internal sealed override uint GetBlobIndex(MetaData md)
3034 if (!addedToBlobHeap) {
3035 blobIndex = md.AddToBlobHeap(val);
3036 addedToBlobHeap = true;
3041 internal sealed override void Write(BinaryWriter bw)
3048 public class CharConst : Constant {
3051 public CharConst(char val)
3055 type = PrimitiveType.Char;
3058 internal sealed override uint GetBlobIndex(MetaData md)
3060 if (!addedToBlobHeap) {
3061 blobIndex = md.AddToBlobHeap(val);
3062 addedToBlobHeap = true;
3067 internal sealed override void Write(BinaryWriter bw)
3074 public class FloatConst : DataConstant {
3077 public FloatConst(float val)
3081 type = PrimitiveType.Float32;
3084 internal sealed override uint GetBlobIndex(MetaData md)
3086 if (!addedToBlobHeap) {
3087 blobIndex = md.AddToBlobHeap(val);
3088 addedToBlobHeap = true;
3093 internal sealed override void Write(BinaryWriter bw)
3100 public class DoubleConst : DataConstant {
3103 public DoubleConst(double val)
3107 type = PrimitiveType.Float64;
3110 internal sealed override uint GetBlobIndex(MetaData md)
3112 if (!addedToBlobHeap) {
3113 blobIndex = md.AddToBlobHeap(val);
3114 addedToBlobHeap = true;
3119 internal sealed override void Write(BinaryWriter bw)
3126 public class IntConst : DataConstant {
3129 public IntConst(sbyte val)
3133 type = PrimitiveType.Int8;
3136 public IntConst(short val)
3140 type = PrimitiveType.Int16;
3143 public IntConst(int val)
3147 type = PrimitiveType.Int32;
3150 public IntConst(long val)
3154 type = PrimitiveType.Int64;
3157 internal sealed override uint GetBlobIndex(MetaData md)
3159 if (!addedToBlobHeap) {
3161 case (1) : blobIndex = md.AddToBlobHeap((sbyte)val); break;
3162 case (2) : blobIndex = md.AddToBlobHeap((short)val); break;
3163 case (4) : blobIndex = md.AddToBlobHeap((int)val); break;
3164 default : blobIndex = md.AddToBlobHeap(val); break;
3166 addedToBlobHeap = true;
3171 internal sealed override void Write(BinaryWriter bw)
3174 case (1) : bw.Write((sbyte)val); break;
3175 case (2) : bw.Write((short)val); break;
3176 case (4) : bw.Write((int)val); break;
3177 default : bw.Write(val); break;
3183 public class UIntConst : DataConstant {
3186 public UIntConst(byte val)
3190 type = PrimitiveType.UInt8;
3192 public UIntConst(ushort val)
3196 type = PrimitiveType.UInt16;
3198 public UIntConst(uint val)
3202 type = PrimitiveType.UInt32;
3204 public UIntConst(ulong val)
3208 type = PrimitiveType.UInt64;
3211 internal sealed override uint GetBlobIndex(MetaData md)
3213 if (!addedToBlobHeap) {
3215 case (1) : blobIndex = md.AddToBlobHeap((byte)val); break;
3216 case (2) : blobIndex = md.AddToBlobHeap((ushort)val); break;
3217 case (4) : blobIndex = md.AddToBlobHeap((uint)val); break;
3218 default : blobIndex = md.AddToBlobHeap(val); break;
3220 addedToBlobHeap = true;
3225 internal sealed override void Write(BinaryWriter bw)
3228 case (1) : bw.Write((byte)val); break;
3229 case (2) : bw.Write((ushort)val); break;
3230 case (4) : bw.Write((uint)val); break;
3231 default : bw.Write(val); break;
3237 public class StringConst : DataConstant {
3238 internal string val;
3240 public StringConst(string val)
3243 size = (uint)val.Length; // need to add null ??
3244 type = PrimitiveType.String;
3247 internal sealed override uint GetBlobIndex(MetaData md)
3249 if (!addedToBlobHeap) {
3250 byte [] b = Encoding.Unicode.GetBytes (val);
3251 blobIndex = md.AddToBlobHeap(b);
3252 addedToBlobHeap = true;
3257 internal sealed override void Write(BinaryWriter bw)
3264 public class NullConst : Constant {
3269 type = PrimitiveType.Class;
3272 internal sealed override uint GetBlobIndex(MetaData md)
3274 if (!addedToBlobHeap) {
3275 blobIndex = md.AddToBlobHeap((int)0);
3276 addedToBlobHeap = true;
3281 internal sealed override void Write(BinaryWriter bw)
3288 public class AddressConstant : DataConstant {
3291 public AddressConstant(DataConstant dConst)
3295 type = PrimitiveType.TypedRef;
3298 internal sealed override void Write(BinaryWriter bw)
3300 ((FileImage)bw).WriteDataRVA(data.DataOffset);
3305 public class RepeatedConstant : DataConstant {
3309 public RepeatedConstant(DataConstant dConst, int repeatCount)
3312 repCount = (uint)repeatCount;
3313 int[] sizes = new int[1];
3314 sizes[0] = repeatCount;
3315 type = new BoundArray(type,1,sizes);
3316 size = data.GetSize() * repCount;
3319 internal sealed override void Write(BinaryWriter bw)
3321 for (int i=0; i < repCount; i++) {
3328 public class ArrayConstant : DataConstant {
3329 DataConstant[] dataVals;
3331 public ArrayConstant(DataConstant[] dVals)
3334 for (int i=0; i < dataVals.Length; i++) {
3335 size += dataVals[i].GetSize();
3339 public int? ExplicitSize { get; set; }
3341 internal sealed override void Write(BinaryWriter bw)
3343 for (int i=0; i < dataVals.Length; i++) {
3344 dataVals[i].Write(bw);
3350 public class ClassType : Constant {
3354 public ClassType(string className)
3357 type = PrimitiveType.ClassType;
3360 public ClassType(Class classDesc)
3363 type = PrimitiveType.ClassType;
3366 internal override void Write(BinaryWriter bw)
3368 if (name == null) name = desc.TypeName();
3376 /**************************************************************************/
3378 /// Descriptor for a custom modifier of a type (modopt or modreq)
3381 public class CustomModifiedType : Type {
3385 PrimitiveTypeRef cmodPrimType;
3388 /// Create a new custom modifier for a type
3390 /// <param name="type">the type to be modified</param>
3391 /// <param name="cmod">the modifier</param>
3392 /// <param name="cmodType">the type reference to be associated with the type</param>
3393 public CustomModifiedType(Type type, CustomModifier cmod, Class cmodType)
3397 this.cmodType = cmodType;
3400 public CustomModifiedType(Type type, CustomModifier cmod, PrimitiveTypeRef cmodType)
3404 this.cmodPrimType = cmodType;
3407 internal sealed override void TypeSig(MemoryStream str)
3409 str.WriteByte(typeIndex);
3411 if (cmodType != null) {
3412 MetaData.CompressNum(cmodType.TypeDefOrRefToken(),str);
3414 MetaData.CompressNum(cmodPrimType.TypeDefOrRefToken(),str);
3422 /**************************************************************************/
3424 /// Base class for Event and Property descriptors
3427 public class Feature : MetaDataElement {
3429 internal enum MethodType : ushort { Setter = 0x01, Getter, Other = 0x04, AddOn = 0x08,
3430 RemoveOn = 0x10, Fire = 0x20 }
3432 private static readonly int INITSIZE = 5;
3433 private static readonly ushort specialName = 0x200;
3434 private static readonly ushort rtSpecialName = 0x400;
3436 protected ClassDef parent;
3437 protected ushort flags = 0;
3438 protected string name;
3439 protected int tide = 0;
3440 protected uint nameIx;
3441 protected MethodSemantics[] methods = new MethodSemantics[INITSIZE];
3443 internal Feature(string name, ClassDef par)
3449 internal void AddMethod(MethodDef meth, MethodType mType)
3451 if (tide >= methods.Length) {
3452 int len = methods.Length;
3453 MethodSemantics[] mTmp = methods;
3454 methods = new MethodSemantics[len * 2];
3455 for (int i=0; i < len; i++) {
3456 methods[i] = mTmp[i];
3459 methods[tide++] = new MethodSemantics(mType,meth,this);
3463 /// Set the specialName attribute for this Event or Property
3465 public void SetSpecialName()
3467 flags |= specialName;
3471 /// Set the RTSpecialName attribute for this Event or Property
3473 public void SetRTSpecialName()
3475 flags |= rtSpecialName;
3480 /**************************************************************************/
3482 /// Descriptor for an event
3484 public class Event : Feature {
3488 internal Event(string name, Type eType, ClassDef parent)
3489 : base(name, parent)
3492 tabIx = MDTable.Event;
3496 /// Add the addon method to this event
3498 /// <param name="addon">the addon method</param>
3499 public void AddAddon(MethodDef addon)
3501 AddMethod(addon,MethodType.AddOn);
3505 /// Add the removeon method to this event
3507 /// <param name="removeOn">the removeon method</param>
3508 public void AddRemoveOn(MethodDef removeOn)
3510 AddMethod(removeOn,MethodType.RemoveOn);
3514 /// Add the fire method to this event
3516 /// <param name="fire">the fire method</param>
3517 public void AddFire(MethodDef fire)
3519 AddMethod(fire,MethodType.Fire);
3523 /// Add another method to this event
3525 /// <param name="other">the method to be added</param>
3526 public void AddOther(MethodDef other)
3528 AddMethod(other,MethodType.Other);
3531 internal sealed override void BuildTables(MetaData md)
3534 nameIx = md.AddToStringsHeap(name);
3535 for (int i=0; i < tide; i++) {
3536 md.AddToTable(MDTable.MethodSemantics,methods[i]);
3541 internal sealed override uint Size(MetaData md)
3543 return 2 + md.StringsIndexSize() + md.CodedIndexSize(CIx.TypeDefOrRef);
3546 internal sealed override void Write(FileImage output)
3548 output.Write(flags);
3549 output.StringsIndex(nameIx);
3550 output.WriteCodedIndex(CIx.TypeDefOrRef,eventType);
3553 internal sealed override uint GetCodedIx(CIx code)
3556 case (CIx.HasCustomAttr) : return 10;
3557 case (CIx.HasSemantics) : return 0;
3564 /**************************************************************************/
3566 /// Descriptor for the Property of a class
3568 public class Property : Feature {
3570 private static readonly byte PropertyTag = 0x8;
3571 private bool instance;
3572 MethodDef getterMeth;
3573 ConstantElem constVal;
3574 uint typeBlobIx = 0;
3579 internal Property(string name, Type retType, Type[] pars, ClassDef parent) : base(name, parent)
3581 returnType = retType;
3583 if (pars != null) numPars = (uint)pars.Length;
3584 tabIx = MDTable.Property;
3588 /// Add a set method to this property
3590 /// <param name="setter">the set method</param>
3591 public void AddSetter(MethodDef setter)
3593 AddMethod(setter,MethodType.Setter);
3597 /// Add a get method to this property
3599 /// <param name="getter">the get method</param>
3600 public void AddGetter(MethodDef getter)
3602 AddMethod(getter,MethodType.Getter);
3603 getterMeth = getter;
3607 /// Add another method to this property
3609 /// <param name="other">the method</param>
3610 public void AddOther(MethodDef other)
3612 AddMethod(other,MethodType.Other);
3616 /// Add an initial value for this property
3618 /// <param name="constVal">the initial value for this property</param>
3619 public void AddInitValue(Constant constVal)
3621 this.constVal = new ConstantElem(this,constVal);
3624 public void SetInstance (bool isInstance)
3626 this.instance = isInstance;
3629 internal sealed override void BuildTables(MetaData md)
3632 nameIx = md.AddToStringsHeap(name);
3633 MemoryStream sig = new MemoryStream();
3634 byte tag = PropertyTag;
3638 MetaData.CompressNum(numPars,sig);
3639 returnType.TypeSig(sig);
3640 for (int i=0; i < numPars; i++) {
3641 parList[i].TypeSig(sig);
3643 typeBlobIx = md.AddToBlobHeap(sig.ToArray());
3644 for (int i=0; i < tide; i++) {
3645 md.AddToTable(MDTable.MethodSemantics,methods[i]);
3647 if (constVal != null) {
3648 md.AddToTable(MDTable.Constant,constVal);
3649 constVal.BuildTables(md);
3654 internal sealed override uint Size(MetaData md)
3656 return 2 + md.StringsIndexSize() + md.BlobIndexSize();
3659 internal sealed override void Write(FileImage output)
3661 output.Write(flags);
3662 output.StringsIndex(nameIx);
3663 output.BlobIndex(typeBlobIx);
3666 internal sealed override uint GetCodedIx(CIx code)
3669 case (CIx.HasCustomAttr) : return 9;
3670 case (CIx.HasConst) : return 2;
3671 case (CIx.HasSemantics) : return 1;
3678 /**************************************************************************/
3680 /// Base class for field/methods (member of a class)
3682 public abstract class Member : MetaDataElement {
3684 protected string name;
3685 protected uint nameIx = 0, sigIx = 0;
3687 internal Member(string memName)
3690 tabIx = MDTable.MemberRef;
3695 /*****************************************************************************/
3697 /// Descriptor for a field of a class
3700 public abstract class Field : Member {
3702 protected static readonly byte FieldSig = 0x6;
3704 protected Type type;
3706 internal Field(string pfName, Type pfType) : base(pfName)
3712 /**************************************************************************/
3714 /// Descriptor for a field defined in a class of THIS assembly/module
3716 public class FieldDef : Field {
3718 //private static readonly uint PInvokeImpl = 0x2000;
3719 private static readonly ushort HasFieldRVA = 0x100;
3720 private static readonly ushort HasDefault = 0x8000;
3723 ConstantElem constVal;
3725 FieldMarshal marshalInfo;
3728 internal FieldDef(string name, Type fType) : base(name,fType)
3730 tabIx = MDTable.Field;
3733 internal FieldDef(FieldAttr attrSet, string name, Type fType) : base(name, fType)
3735 flags = (ushort)attrSet;
3736 tabIx = MDTable.Field;
3740 /// Add an attribute(s) to this field
3742 /// <param name="fa">the attribute(s) to be added</param>
3743 public void AddFieldAttr(FieldAttr fa)
3745 flags |= (ushort)fa;
3749 /// Add a value for this field
3751 /// <param name="val">the value for the field</param>
3752 public void AddValue(Constant val)
3754 constVal = new ConstantElem(this,val);
3755 flags |= HasDefault;
3759 /// Add an initial value for this field (at dataLabel) (.data)
3761 /// <param name="val">the value for the field</param>
3762 /// <param name="repeatVal">the number of repetitions of this value</param>
3763 public void AddDataValue(DataConstant val)
3765 flags |= HasFieldRVA;
3766 rva = new FieldRVA(this,val);
3770 /// Set the offset of the field. Used for sequential or explicit classes.
3773 /// <param name="offs">field offset</param>
3774 public void SetOffset(uint offs)
3776 layout = new FieldLayout(this,offs);
3780 /// Set the marshalling info for a field
3782 /// <param name="mInf"></param>
3783 public void SetMarshalInfo(NativeType marshallType)
3785 flags |= (ushort) FieldAttr.HasFieldMarshal;
3786 marshalInfo = new FieldMarshal(this,marshallType);
3789 internal sealed override void BuildTables(MetaData md)
3792 nameIx = md.AddToStringsHeap(name);
3793 MemoryStream sig = new MemoryStream();
3794 sig.WriteByte(FieldSig);
3796 sigIx = md.AddToBlobHeap(sig.ToArray());
3798 md.AddToTable(MDTable.FieldRVA,rva);
3799 rva.BuildTables(md);
3800 } else if (constVal != null) {
3801 md.AddToTable(MDTable.Constant,constVal);
3802 constVal.BuildTables(md);
3804 if (layout != null) md.AddToTable(MDTable.FieldLayout,layout);
3805 if (marshalInfo != null) {
3806 md.AddToTable(MDTable.FieldMarshal,marshalInfo);
3807 marshalInfo.BuildTables(md);
3812 internal sealed override uint Size(MetaData md)
3814 return 2 + md.StringsIndexSize() + md.BlobIndexSize();
3817 internal sealed override void Write(FileImage output)
3819 output.Write(flags);
3820 output.StringsIndex(nameIx);
3821 output.BlobIndex(sigIx);
3824 internal sealed override uint GetCodedIx(CIx code)
3827 case (CIx.HasConst) : return 0;
3828 case (CIx.HasCustomAttr) : return 1;
3829 case (CIx.HasFieldMarshal) : return 0;
3830 case (CIx.MemberForwarded) : return 0;
3837 /**************************************************************************/
3839 /// Descriptor for a field of a class defined in another assembly/module
3841 public class FieldRef : Field {
3843 MetaDataElement parent;
3845 internal FieldRef(MetaDataElement paren, string name, Type fType) : base(name, fType)
3850 internal sealed override void BuildTables(MetaData md)
3853 nameIx = md.AddToStringsHeap(name);
3854 MemoryStream sig = new MemoryStream();
3855 sig.WriteByte(FieldSig);
3857 sigIx = md.AddToBlobHeap(sig.ToArray());
3861 internal sealed override uint Size(MetaData md)
3863 return md.CodedIndexSize(CIx.MemberRefParent) + md.StringsIndexSize() + md.BlobIndexSize();
3866 internal sealed override void Write(FileImage output)
3868 output.WriteCodedIndex(CIx.MemberRefParent,parent);
3869 output.StringsIndex(nameIx);
3870 output.BlobIndex(sigIx);
3873 internal sealed override uint GetCodedIx(CIx code) { return 6; }
3877 /**************************************************************************/
3879 /// Base class for Method Descriptors
3882 public abstract class Method : Member {
3884 internal Method (string methName) : base (methName)
3887 public abstract void AddCallConv(CallConv cconv);
3888 internal abstract void TypeSig(MemoryStream sig);
3889 internal abstract uint GetSigIx(MetaData md);
3892 /**************************************************************************/
3894 /// Descriptor for a method defined in THIS assembly/module
3898 public class MethodDef : Method {
3900 private static readonly ushort PInvokeImpl = 0x2000;
3901 //private static readonly uint UnmanagedExport = 0x0008;
3902 // private static readonly byte LocalSigByte = 0x7;
3903 uint parIx = 0, textOffset = 0;
3904 private CallConv callConv = CallConv.Default;
3905 private int gen_param_count;
3908 CILInstructions code;
3912 ushort methFlags = 0, implFlags = 0;
3913 int maxStack = 0, numPars = 0;
3914 bool entryPoint = false;
3916 ArrayList varArgSigList;
3917 ImplMap pinvokeImpl;
3920 internal MethodDef (MetaData md, string name, Param ret_param, Param [] pars)
3921 : this (md, 0, 0, name, ret_param, pars)
3925 internal MethodDef (MetaData md, MethAttr mAttrSet, ImplAttr iAttrSet, string name,
3926 Param ret_param, Param [] pars)
3929 methFlags = (ushort)mAttrSet;
3930 implFlags = (ushort)iAttrSet;
3931 this.ret_param = ret_param;
3934 if (parList != null)
3935 numPars = parList.Length;
3936 tabIx = MDTable.Method;
3939 internal Param[] GetPars()
3944 internal override uint GetSigIx(MetaData md)
3946 MemoryStream sig = new MemoryStream();
3948 return md.AddToBlobHeap(sig.ToArray());
3951 public override void AddCallConv(CallConv cconv)
3957 /// Add some attributes to this method descriptor
3959 /// <param name="ma">the attributes to be added</param>
3960 public void AddMethAttribute(MethAttr ma)
3962 methFlags |= (ushort)ma;
3966 /// Add some implementation attributes to this method descriptor
3968 /// <param name="ia">the attributes to be added</param>
3969 public void AddImplAttribute(ImplAttr ia)
3971 implFlags |= (ushort)ia;
3974 public void AddPInvokeInfo(ModuleRef scope, string methName,
3975 PInvokeAttr callAttr) {
3976 pinvokeImpl = new ImplMap((ushort)callAttr,this,methName,scope);
3977 methFlags |= PInvokeImpl;
3981 /// Add a named generic type parameter
3983 public GenericParameter AddGenericParameter (short index, string name)
3985 return AddGenericParameter (index, name, 0);
3989 /// Add a named generic type parameter with attributes
3991 public GenericParameter AddGenericParameter (short index, string name, GenericParamAttributes attr)
3993 GenericParameter gp = new GenericParameter (this, metaData, index, name, attr);
3994 metaData.AddToTable (MDTable.GenericParam, gp);
4000 /// Set the maximum stack height for this method
4002 /// <param name="maxStack">the maximum height of the stack</param>
4003 public void SetMaxStack(int maxStack)
4005 this.maxStack = maxStack;
4009 /// Add local variables to this method
4011 /// <param name="locals">the locals to be added</param>
4012 /// <param name="initLocals">are locals initialised to default values</param>
4013 public void AddLocals(Local[] locals, bool initLocals)
4015 this.locals = locals;
4016 this.initLocals = initLocals;
4019 /* Add Marshal info for return type */
4020 public void AddRetTypeMarshallInfo (NativeType marshallType)
4022 ret_param.AddMarshallInfo (marshallType);
4026 /// Mark this method as having an entry point
4028 public void DeclareEntryPoint()
4034 /// Create a code buffer for this method to add the IL instructions to
4036 /// <returns>a buffer for this method's IL instructions</returns>
4037 public CILInstructions CreateCodeBuffer()
4039 code = new CILInstructions(metaData);
4044 /// Make a method reference descriptor for this method to be used
4045 /// as a callsite signature for this vararg method
4047 /// <param name="optPars">the optional pars for the vararg method call</param>
4048 /// <returns></returns>
4049 public MethodRef MakeVarArgSignature(Type[] optPars)
4051 Type[] pars = new Type[numPars];
4052 MethodRef varArgSig;
4053 for (int i=0; i < numPars; i++) {
4054 pars[i] = parList[i].GetParType();
4056 varArgSig = new MethodRef (this, name, ret_param.GetParType (), pars, true, optPars, 0);
4058 if (varArgSigList == null)
4059 varArgSigList = new ArrayList ();
4060 varArgSigList.Add (varArgSig);
4064 internal sealed override void TypeSig(MemoryStream sig)
4066 sig.WriteByte((byte)callConv);
4067 if ((callConv & CallConv.Generic) == CallConv.Generic)
4068 MetaData.CompressNum ((uint) gen_param_count, sig);
4069 MetaData.CompressNum((uint)numPars,sig);
4071 ret_param.seqNo = 0;
4072 ret_param.TypeSig (sig);
4073 for (ushort i=0; i < numPars; i++) {
4074 parList[i].seqNo = (ushort)(i+1);
4075 parList[i].TypeSig(sig);
4079 internal sealed override void BuildTables(MetaData md)
4082 if (pinvokeImpl != null) {
4083 md.AddToTable(MDTable.ImplMap,pinvokeImpl);
4084 pinvokeImpl.BuildTables(md);
4086 if (entryPoint) md.SetEntryPoint(this);
4088 if (locals != null) {
4089 localSig = new LocalSig(locals);
4090 md.AddToTable(MDTable.StandAloneSig,localSig);
4091 localSig.BuildTables(md);
4092 locToken = localSig.Token();
4095 code.CheckCode(locToken,initLocals,maxStack);
4096 textOffset = md.AddCode(code);
4098 nameIx = md.AddToStringsHeap(name);
4099 sigIx = GetSigIx(md);
4100 parIx = md.TableIndex(MDTable.Param);
4101 if (ret_param.HasMarshalInfo || ret_param.HasCustomAttr) {
4102 md.AddToTable(MDTable.Param, ret_param);
4103 ret_param.BuildTables(md);
4105 for (int i=0; i < numPars; i++) {
4106 md.AddToTable(MDTable.Param,parList[i]);
4107 parList[i].BuildTables(md);
4109 if (varArgSigList != null) {
4110 foreach (MethodRef varArgSig in varArgSigList) {
4111 md.AddToTable(MDTable.MemberRef,varArgSig);
4112 varArgSig.BuildTables(md);
4115 // Console.WriteLine("method has " + numPars + " parameters");
4119 internal sealed override uint Size(MetaData md)
4121 return 8 + md.StringsIndexSize() + md.BlobIndexSize() + md.TableIndexSize(MDTable.Param);
4124 internal sealed override void Write(FileImage output)
4126 if (ZeroRva ()) output.Write(0);
4127 else output.WriteCodeRVA(textOffset);
4128 output.Write(implFlags);
4129 output.Write(methFlags);
4130 output.StringsIndex(nameIx);
4131 output.BlobIndex(sigIx);
4132 output.WriteIndex(MDTable.Param,parIx);
4135 internal bool ZeroRva ()
4137 return (((methFlags & (ushort)MethAttr.Abstract) != 0) ||
4138 ((implFlags & (ushort)ImplAttr.Runtime) != 0) ||
4139 ((implFlags & (ushort)ImplAttr.InternalCall) != 0) ||
4140 (pinvokeImpl != null)); // TODO: Not entirely true but works for now
4143 internal sealed override uint GetCodedIx(CIx code)
4146 case (CIx.HasCustomAttr) : return 0;
4147 case (CIx.HasDeclSecurity) : return 1;
4148 case (CIx.MemberRefParent) : return 3;
4149 case (CIx.MethodDefOrRef) : return 0;
4150 case (CIx.MemberForwarded) : return 1;
4151 case (CIx.CustomAttributeType) : return 2;
4152 case (CIx.TypeOrMethodDef) : return 1;
4158 /**************************************************************************/
4160 /// Descriptor for a method defined in another assembly/module
4162 public class MethodRef : Method {
4164 private static readonly byte Sentinel = 0x41;
4165 Type[] parList, optParList;
4166 MetaDataElement parent;
4167 uint numPars = 0, numOptPars = 0;
4168 CallConv callConv = CallConv.Default;
4170 int gen_param_count;
4172 internal MethodRef(MetaDataElement paren, string name, Type retType,
4173 Type[] pars, bool varArgMeth, Type[] optPars, int gen_param_count) : base(name)
4177 this.retType = retType;
4178 if (parList != null) numPars = (uint)parList.Length;
4180 optParList = optPars;
4181 if (optParList != null) numOptPars = (uint)optParList.Length;
4182 callConv = CallConv.Vararg;
4184 this.gen_param_count = gen_param_count;
4187 internal override uint GetSigIx(MetaData md)
4189 MemoryStream sig = new MemoryStream();
4191 return md.AddToBlobHeap(sig.ToArray());
4194 public override void AddCallConv(CallConv cconv)
4199 internal sealed override void TypeSig(MemoryStream sig)
4201 sig.WriteByte((byte)callConv);
4202 if ((callConv & CallConv.Generic) == CallConv.Generic)
4203 MetaData.CompressNum ((uint) gen_param_count, sig);
4204 MetaData.CompressNum(numPars+numOptPars,sig);
4205 retType.TypeSig(sig);
4206 for (int i=0; i < numPars; i++) {
4207 parList[i].TypeSig(sig);
4209 if (numOptPars > 0) {
4210 sig.WriteByte(Sentinel);
4211 for (int i=0; i < numOptPars; i++) {
4212 optParList[i].TypeSig(sig);
4217 internal sealed override void BuildTables(MetaData md)
4220 nameIx = md.AddToStringsHeap(name);
4221 sigIx = GetSigIx(md);
4225 internal sealed override uint Size(MetaData md)
4227 return md.CodedIndexSize(CIx.MemberRefParent) + md.StringsIndexSize() + md.BlobIndexSize();
4230 internal sealed override void Write(FileImage output)
4232 output.WriteCodedIndex(CIx.MemberRefParent,parent);
4233 output.StringsIndex(nameIx);
4234 output.BlobIndex(sigIx);
4237 internal sealed override uint GetCodedIx(CIx code)
4240 case (CIx.HasCustomAttr) : return 6;
4241 case (CIx.MethodDefOrRef) : return 1;
4242 case (CIx.CustomAttributeType) : return 3;
4250 /**************************************************************************/
4252 /// Descriptors for native types used for marshalling
4254 public class NativeType {
4255 public static readonly NativeType Void = new NativeType(0x01);
4256 public static readonly NativeType Boolean = new NativeType(0x02);
4257 public static readonly NativeType Int8 = new NativeType(0x03);
4258 public static readonly NativeType UInt8 = new NativeType(0x04);
4259 public static readonly NativeType Int16 = new NativeType(0x05);
4260 public static readonly NativeType UInt16 = new NativeType(0x06);
4261 public static readonly NativeType Int32 = new NativeType(0x07);
4262 public static readonly NativeType UInt32 = new NativeType(0x08);
4263 public static readonly NativeType Int64 = new NativeType(0x09);
4264 public static readonly NativeType UInt64 = new NativeType(0x0A);
4265 public static readonly NativeType Float32 = new NativeType(0x0B);
4266 public static readonly NativeType Float64 = new NativeType(0x0C);
4267 public static readonly NativeType Currency = new NativeType(0x0F);
4268 public static readonly NativeType BStr = new NativeType(0x13);
4269 public static readonly NativeType LPStr = new NativeType(0x14);
4270 public static readonly NativeType LPWStr = new NativeType(0x15);
4271 public static readonly NativeType LPTStr = new NativeType(0x16);
4272 public static readonly NativeType FixedSysString = new NativeType(0x17);
4273 public static readonly NativeType IUnknown = new NativeType(0x19);
4274 public static readonly NativeType IDispatch = new NativeType(0x1A);
4275 public static readonly NativeType Struct = new NativeType(0x1B);
4276 public static readonly NativeType Interface = new NativeType(0x1C);
4277 public static readonly NativeType Int = new NativeType(0x1F);
4278 public static readonly NativeType UInt = new NativeType(0x20);
4279 public static readonly NativeType ByValStr = new NativeType(0x22);
4280 public static readonly NativeType AnsiBStr = new NativeType(0x23);
4281 public static readonly NativeType TBstr = new NativeType(0x24);
4282 public static readonly NativeType VariantBool = new NativeType(0x25);
4283 public static readonly NativeType FuncPtr = new NativeType(0x26);
4284 public static readonly NativeType AsAny = new NativeType(0x28);
4285 public static readonly NativeType LPStruct = new NativeType(0x2b);
4286 public static readonly NativeType Error = new NativeType(0x2d);
4288 protected byte typeIndex;
4290 internal NativeType(byte tyIx) { typeIndex = tyIx; }
4291 internal byte GetTypeIndex() { return typeIndex; }
4293 internal virtual byte[] ToBlob()
4295 byte[] bytes = new byte[1];
4296 bytes[0] = GetTypeIndex();
4302 public class FixedSysString : NativeType {
4306 public FixedSysString (uint size) : base (NativeType.FixedSysString.GetTypeIndex ())
4311 internal override byte [] ToBlob ()
4313 MemoryStream str = new MemoryStream ();
4314 str.WriteByte (GetTypeIndex ());
4315 MetaData.CompressNum (size, str);
4316 return str.ToArray ();
4321 public class NativeArray : NativeType {
4323 NativeType elemType;
4324 int numElem = -1, parNum = -1, elemMult = -1;
4326 public NativeArray(NativeType elemType) : this (elemType, -1, -1, -1)
4328 this.elemType = elemType;
4331 /* public NativeArray(NativeType elemType, int len) : base(0x2A) {
4332 this.elemType = elemType;
4337 public NativeArray(NativeType elemType, int numElem, int parNumForLen, int elemMult) : base(0x2A)
4339 this.elemType = elemType;
4340 this.numElem = numElem;
4341 parNum = parNumForLen;
4342 this.elemMult = elemMult;
4345 public NativeArray(NativeType elemType, int numElem, int parNumForLen)
4346 : this (elemType, numElem, parNumForLen, -1)
4350 internal override byte[] ToBlob()
4352 MemoryStream str = new MemoryStream();
4353 str.WriteByte(GetTypeIndex());
4354 if (elemType == null) str.WriteByte(0x50); // no info (MAX)
4355 else str.WriteByte(elemType.GetTypeIndex());
4357 /* see : mono/metadata/metadata.c:mono_metadata_parse_marshal_spec
4358 * LAMESPEC: Older spec versions say elemMult comes before
4359 * len. Newer spec versions don't talk about elemMult at
4360 * all, but csc still emits it, and it is used to distinguish
4361 * between parNum being 0, and parNum being omitted.
4366 return str.ToArray ();
4368 MetaData.CompressNum((uint) parNum,str);
4369 if (numElem != -1) {
4370 MetaData.CompressNum ((uint) numElem, str);
4372 // <native_type> [ int32 ]
4373 MetaData.CompressNum((uint) elemMult,str);
4374 //else <native_type> [ int32 + int32 ]
4375 } else if (elemMult != -1) {
4376 // When can this occur ?
4377 MetaData.CompressNum (0, str);
4378 MetaData.CompressNum((uint) elemMult,str);
4380 //else <native_type> [ + int32 ]
4382 return str.ToArray();
4387 public class SafeArray : NativeType {
4389 SafeArrayType elemType;
4392 public SafeArray() : base(0x1D)
4396 public SafeArray(SafeArrayType elemType) : base(0x1D)
4398 this.elemType = elemType;
4402 internal override byte[] ToBlob()
4404 byte[] bytes = new byte[hasElemType ? 2 : 1];
4405 bytes[0] = GetTypeIndex();
4407 bytes[1] = (byte)elemType;
4413 public class FixedArray : NativeType {
4417 //public FixedArray(NativeType elemType, int numElems) : base(0x1E) {
4418 public FixedArray(int numElems) : base(0x1E)
4420 //this.elemType = elemType;
4421 numElem = (uint)numElems;
4424 internal override byte[] ToBlob()
4426 MemoryStream str = new MemoryStream();
4427 str.WriteByte(GetTypeIndex());
4428 MetaData.CompressNum(numElem,str);
4430 fixed array [5] lpstr [2]
4431 This format is not supported by ilasm 1.1.4322.2032,
4432 but is supported by 2.0.5125..
4433 ilasm 1.1 only supports "fixed array [5]"
4434 if (elemType == null) str.WriteByte(0x50); // no info (MAX)
4435 else str.WriteByte(elemType.GetTypeIndex());*/
4437 return str.ToArray();
4442 public class CustomMarshaller : NativeType {
4445 string marshallerName;
4448 public CustomMarshaller(string typeNameOrGUID, string marshallerName,
4449 string optCookie) : base(0x2C)
4451 typeName = typeNameOrGUID;
4452 this.marshallerName = marshallerName;
4456 public CustomMarshaller(string marshallerName, string optCookie)
4457 :this (null, marshallerName, optCookie)
4461 internal override byte[] ToBlob()
4463 MemoryStream str = new MemoryStream();
4464 BinaryWriter bw = new BinaryWriter(str,new UTF8Encoding());
4465 bw.Write(GetTypeIndex());
4466 //Native type name & unmanaged type - unused
4467 //See mono/metadata/metadata.c : mono_metadata_parse_marshal_spec
4468 bw.Write ((byte) 0); // Native Type name, unused
4469 bw.Write ((byte) 0); // Unmanaged type, unused
4470 if (marshallerName != null) {
4471 MetaData.CompressNum ((uint)marshallerName.Length, str);
4472 bw.Write(marshallerName.ToCharArray());
4474 bw.Write ((byte) 0);
4476 if (cookie != null) {
4477 MetaData.CompressNum ((uint)cookie.Length, str);
4478 bw.Write(cookie.ToCharArray());
4480 bw.Write ((byte) 0);
4483 return str.ToArray();
4487 /**************************************************************************/
4489 /// Descriptor for the Primitive types defined in IL
4491 public class PrimitiveType : Type {
4493 private string name;
4494 private int systemTypeIndex;
4495 public static int NumSystemTypes = 18;
4497 public static readonly PrimitiveType Void = new PrimitiveType(0x01,"Void",0);
4498 public static readonly PrimitiveType Boolean = new PrimitiveType(0x02,"Boolean",1);
4499 public static readonly PrimitiveType Char = new PrimitiveType(0x03,"Char",2);
4500 public static readonly PrimitiveType Int8 = new PrimitiveType(0x04,"SByte",3);
4501 public static readonly PrimitiveType UInt8 = new PrimitiveType(0x05,"Byte",4);
4502 public static readonly PrimitiveType Int16 = new PrimitiveType(0x06,"Int16",5);
4503 public static readonly PrimitiveType UInt16 = new PrimitiveType(0x07,"UInt16",6);
4504 public static readonly PrimitiveType Int32 = new PrimitiveType(0x08,"Int32",7);
4505 public static readonly PrimitiveType UInt32 = new PrimitiveType(0x09,"UInt32",8);
4506 public static readonly PrimitiveType Int64 = new PrimitiveType(0x0A,"Int64",9);
4507 public static readonly PrimitiveType UInt64 = new PrimitiveType(0x0B,"UInt64",10);
4508 public static readonly PrimitiveType Float32 = new PrimitiveType(0x0C,"Single",11);
4509 public static readonly PrimitiveType Float64 = new PrimitiveType(0x0D,"Double",12);
4510 public static readonly PrimitiveType String = new PrimitiveType(0x0E,"String",13);
4511 internal static readonly PrimitiveType Class = new PrimitiveType(0x12);
4512 internal static readonly PrimitiveType Var = new PrimitiveType(0x13);
4513 internal static readonly PrimitiveType GenericInst = new PrimitiveType(0x15);
4514 public static readonly PrimitiveType TypedRef = new PrimitiveType(0x16,"TypedReference",14);
4515 public static readonly PrimitiveType IntPtr = new PrimitiveType(0x18,"IntPtr",15);
4516 public static readonly PrimitiveType UIntPtr = new PrimitiveType(0x19,"UIntPtr",16);
4517 public static readonly PrimitiveType Object = new PrimitiveType(0x1C,"Object",17);
4518 internal static readonly PrimitiveType ClassType = new PrimitiveType(0x50);
4519 internal static readonly PrimitiveType SZArray = new PrimitiveType(0x1D);
4520 internal static readonly PrimitiveType MVar = new PrimitiveType(0x1E);
4521 internal static readonly PrimitiveType ValueType = new PrimitiveType(0x11, "ValueType", 18);
4522 public static readonly PrimitiveType NativeInt = IntPtr;
4523 public static readonly PrimitiveType NativeUInt = UIntPtr;
4525 internal PrimitiveType(byte typeIx) : base(typeIx) { }
4527 internal PrimitiveType(byte typeIx, string name, int STIx) : base(typeIx)
4530 this.systemTypeIndex = STIx;
4533 internal string GetName() { return name; }
4535 internal int GetSystemTypeIx() { return systemTypeIndex; }
4537 internal sealed override void TypeSig(MemoryStream str)
4539 str.WriteByte(typeIndex);
4542 internal override MetaDataElement GetTypeSpec(MetaData md)
4544 TypeSpec tS = md.GetPrimitiveTypeSpec(systemTypeIndex);
4546 tS = new TypeSpec(this,md);
4547 md.SetPrimitiveTypeSpec(systemTypeIndex,tS);
4548 md.AddToTable(MDTable.TypeSpec,tS);
4555 public class PrimitiveTypeRef : Type
4560 internal PrimitiveTypeRef(PrimitiveType type, MetaData md)
4567 internal uint TypeDefOrRefToken()
4569 uint cIx = type.GetTypeSpec (metaData).Row;
4570 cIx = (cIx << 2) | 0x2;
4575 /**************************************************************************/
4577 /// Descriptor for an pointer (type * or type &)
4579 public abstract class PtrType : Type {
4583 internal PtrType(Type bType, byte typeIx) : base(typeIx)
4586 tabIx = MDTable.TypeSpec;
4589 internal sealed override void TypeSig(MemoryStream str)
4591 str.WriteByte(typeIndex);
4592 baseType.TypeSig(str);
4596 /**************************************************************************/
4598 /// Descriptor for a managed pointer (type & or byref)
4601 public class ManagedPointer : PtrType {
4604 /// Create new managed pointer to baseType
4606 /// <param name="bType">the base type of the pointer</param>
4607 public ManagedPointer(Type baseType) : base(baseType,0x10) { }
4610 /**************************************************************************/
4612 /// Descriptor for an unmanaged pointer (type *)
4614 public class UnmanagedPointer : PtrType {
4617 /// Create a new unmanaged pointer to baseType
4619 /// <param name="baseType">the base type of the pointer</param>
4620 public UnmanagedPointer(Type baseType) : base(baseType, 0x0F) { }
4624 /**************************************************************************/
4626 public interface IExternRef {
4627 ClassRef AddClass(string nsName, string name);
4628 ClassRef AddValueClass(string nsName, string name);
4632 /// A reference to an external assembly (.assembly extern)
4634 public class AssemblyRef : ResolutionScope, IExternRef {
4636 private ushort major, minor, build, revision;
4637 uint flags, keyIx, hashIx, cultIx;
4638 bool hasVersion = false, isKeyToken = false;
4642 internal AssemblyRef(MetaData md, string name) : base(name,md)
4644 tabIx = MDTable.AssemblyRef;
4647 public void AddAssemblyAttr (AssemAttr aa)
4653 /// Add version information about this external assembly
4655 /// <param name="majVer">Major Version</param>
4656 /// <param name="minVer">Minor Version</param>
4657 /// <param name="bldNo">Build Number</param>
4658 /// <param name="revNo">Revision Number</param>
4659 public void AddVersionInfo(int majVer, int minVer, int bldNo, int revNo)
4661 major = (ushort)majVer;
4662 minor = (ushort)minVer;
4663 build = (ushort)bldNo;
4664 revision = (ushort)revNo;
4669 /// Add the hash value for this external assembly
4671 /// <param name="hash">bytes of the hash value</param>
4672 public void AddHash(byte[] hash)
4674 hashIx = metaData.AddToBlobHeap(hash);
4678 /// Set the culture for this external assembly
4680 /// <param name="cult">the culture string</param>
4681 public void AddCulture(string cult)
4683 cultIx = metaData.AddToStringsHeap(cult);
4688 /// Add the full public key for this external assembly
4690 /// <param name="key">bytes of the public key</param>
4691 public void AddKey(byte[] key)
4693 flags |= 0x0001; // full public key
4695 keyIx = metaData.AddToBlobHeap(key);
4699 /// Add the public key token (low 8 bytes of the public key)
4701 /// <param name="key">low 8 bytes of public key</param>
4702 public void AddKeyToken(byte[] key)
4704 keyIx = metaData.AddToBlobHeap(key);
4710 /// Add a class to this external assembly
4712 /// <param name="nsName">name space name</param>
4713 /// <param name="name">class name</param>
4714 /// <returns></returns>
4715 public virtual ClassRef AddClass(string nsName, string name)
4717 ClassRef aClass = new ClassRef(nsName,name,metaData);
4718 metaData.AddToTable(MDTable.TypeRef,aClass);
4719 aClass.SetParent(this);
4724 /// Add a value class to this external assembly
4726 /// <param name="nsName">name space name</param>
4727 /// <param name="name">class name</param>
4728 /// <returns></returns>
4729 public virtual ClassRef AddValueClass(string nsName, string name)
4731 ClassRef aClass = new ClassRef(nsName,name,metaData);
4732 metaData.AddToTable(MDTable.TypeRef,aClass);
4733 aClass.SetParent(this);
4734 aClass.MakeValueClass(ValueClass.ValueType);
4738 internal string TypeName()
4740 string result = name;
4742 result = result + ", Version=" + major + "." + minor + "." +
4743 build + "." + revision;
4744 if (keyBytes != null) {
4745 string tokenStr = "=";
4746 if (isKeyToken) tokenStr = "Token=";
4747 result = result + ", PublicKey" + tokenStr;
4748 for (int i=0; i < keyBytes.Length; i++) {
4749 result = result + Hex.Byte(keyBytes[i]);
4752 if (culture != null)
4753 result = result + ", Culture=" + culture;
4757 internal sealed override uint Size(MetaData md)
4759 return 12 + 2 * md.StringsIndexSize() + 2 * md.BlobIndexSize();
4762 internal sealed override void Write(FileImage output)
4764 output.Write(major);
4765 output.Write(minor);
4766 output.Write(build);
4767 output.Write(revision);
4768 output.Write(flags);
4769 output.BlobIndex(keyIx);
4770 output.StringsIndex(nameIx);
4771 output.StringsIndex(cultIx);
4772 output.BlobIndex(hashIx);
4775 internal sealed override uint GetCodedIx(CIx code)
4778 case (CIx.ResolutionScope) : return 2;
4779 case (CIx.HasCustomAttr) : return 15;
4780 case (CIx.Implementation) : return 1;
4787 /**************************************************************************/
4789 /// Descriptor for a class defined in System (mscorlib)
4791 internal class SystemClass : ClassRef {
4793 PrimitiveType elemType;
4795 internal SystemClass(PrimitiveType eType, AssemblyRef paren, MetaData md)
4796 : base("System",eType.GetName(),md) {
4801 internal override sealed MetaDataElement GetTypeSpec(MetaData md)
4803 if (typeSpec == null) typeSpec = (TypeSpec)elemType.GetTypeSpec(md);
4808 internal sealed override void TypeSig(MemoryStream str)
4810 str.WriteByte(elemType.GetTypeIndex());
4815 /**************************************************************************/
4817 /// The assembly for mscorlib.
4819 public sealed class MSCorLib : AssemblyRef {
4821 private static readonly int valueTypeIx = 18;
4822 private readonly string systemName = "System";
4823 private Class[] systemClasses = new Class[valueTypeIx+2];
4824 private PrimitiveType[] systemTypes = new PrimitiveType[valueTypeIx];
4826 private static int[] specialNames = {
4827 PrimitiveType.Void.GetName().GetHashCode(),
4828 PrimitiveType.Boolean.GetName().GetHashCode(),
4829 PrimitiveType.Char.GetName().GetHashCode(),
4830 PrimitiveType.Int8.GetName().GetHashCode(),
4831 PrimitiveType.UInt8.GetName().GetHashCode(),
4832 PrimitiveType.Int16.GetName().GetHashCode(),
4833 PrimitiveType.UInt16.GetName().GetHashCode(),
4834 PrimitiveType.Int32.GetName().GetHashCode(),
4835 PrimitiveType.UInt32.GetName().GetHashCode(),
4836 PrimitiveType.Int64.GetName().GetHashCode(),
4837 PrimitiveType.UInt64.GetName().GetHashCode(),
4838 PrimitiveType.Float32.GetName().GetHashCode(),
4839 PrimitiveType.Float64.GetName().GetHashCode(),
4840 PrimitiveType.String.GetName().GetHashCode(),
4841 PrimitiveType.TypedRef.GetName().GetHashCode(),
4842 PrimitiveType.IntPtr.GetName().GetHashCode(),
4843 PrimitiveType.UIntPtr.GetName().GetHashCode(),
4844 PrimitiveType.Object.GetName().GetHashCode(),
4845 PrimitiveType.ValueType.GetName ().GetHashCode(),
4846 "Enum".GetHashCode()
4849 internal MSCorLib(MetaData md) : base(md,"mscorlib")
4851 if (!PEFile.IsMSCorlib)
4852 md.AddToTable(MDTable.AssemblyRef,this);
4853 systemTypes[PrimitiveType.Void.GetSystemTypeIx()] = PrimitiveType.Void;
4854 systemTypes[PrimitiveType.Boolean.GetSystemTypeIx()] = PrimitiveType.Boolean;
4855 systemTypes[PrimitiveType.Char.GetSystemTypeIx()] = PrimitiveType.Char;
4856 systemTypes[PrimitiveType.Int8.GetSystemTypeIx()] = PrimitiveType.Int8;
4857 systemTypes[PrimitiveType.UInt8.GetSystemTypeIx()] = PrimitiveType.UInt8;
4858 systemTypes[PrimitiveType.Int16.GetSystemTypeIx()] = PrimitiveType.Int16;
4859 systemTypes[PrimitiveType.UInt16.GetSystemTypeIx()] = PrimitiveType.UInt16;
4860 systemTypes[PrimitiveType.Int32.GetSystemTypeIx()] = PrimitiveType.Int32;
4861 systemTypes[PrimitiveType.UInt32.GetSystemTypeIx()] = PrimitiveType.UInt32;
4862 systemTypes[PrimitiveType.Int64.GetSystemTypeIx()] = PrimitiveType.Int64;
4863 systemTypes[PrimitiveType.UInt64.GetSystemTypeIx()] = PrimitiveType.UInt64;
4864 systemTypes[PrimitiveType.Float32.GetSystemTypeIx()] = PrimitiveType.Float32;
4865 systemTypes[PrimitiveType.Float64.GetSystemTypeIx()] = PrimitiveType.Float64;
4866 systemTypes[PrimitiveType.IntPtr.GetSystemTypeIx()] = PrimitiveType.IntPtr;
4867 systemTypes[PrimitiveType.UIntPtr.GetSystemTypeIx()] = PrimitiveType.UIntPtr;
4868 systemTypes[PrimitiveType.String.GetSystemTypeIx()] = PrimitiveType.String;
4869 systemTypes[PrimitiveType.Object.GetSystemTypeIx()] = PrimitiveType.Object;
4870 systemTypes[PrimitiveType.TypedRef.GetSystemTypeIx()] = PrimitiveType.TypedRef;
4874 /// Add a class to the mscorlib assembly
4876 /// <param name="nsName">name space name</param>
4877 /// <param name="name">class name</param>
4878 /// <returns></returns>
4879 public override ClassRef AddClass(string nsName, string name)
4881 /* This gets called by !mscorlib, for adding references INTO mscorlib, so
4882 it should be returning ClassRef ..*/
4883 Class aClass = GetSpecialClass(nsName,name);
4884 if (aClass == null) {
4885 aClass = new ClassRef(nsName,name,metaData);
4886 metaData.AddToTable(MDTable.TypeRef,aClass);
4887 if (aClass is ClassRef)
4888 ((ClassRef) aClass).SetParent(this);
4890 //FIXME: Check for !ClassRef here?
4891 return (ClassRef) aClass;
4894 private Class GetSpecialClass(string nsName,string name)
4896 if (nsName.CompareTo(systemName) != 0) return null;
4897 int hash = name.GetHashCode();
4898 for (int i=0; i < specialNames.Length; i++) {
4899 if (hash != specialNames[i])
4901 if (systemClasses[i] == null) {
4902 if (i < valueTypeIx) {
4903 systemClasses[i] = new SystemClass(systemTypes[i],this,metaData);
4904 if ((systemTypes[i] != PrimitiveType.Object) &&
4905 (systemTypes[i] != PrimitiveType.String)) {
4906 systemClasses[i].MakeValueClass(ValueClass.ValueType);
4909 systemClasses[i] = new ClassRef(nsName,name,metaData);
4910 ((ClassRef) systemClasses[i]).SetParent(this);
4911 if (!ClassDef.IsValueType (nsName, name) && !ClassDef.IsEnum (nsName, name))
4912 systemClasses[i].MakeValueClass(ValueClass.ValueType);
4914 metaData.AddToTable(MDTable.TypeRef,systemClasses[i]);
4916 return systemClasses[i];
4921 internal void SetSpecialSystemClass (string nsName, string name, Class aClass)
4923 if (nsName != systemName) return;
4924 int hash = name.GetHashCode ();
4925 for (int i = 0; i < specialNames.Length; i++) {
4926 if (hash != specialNames [i])
4928 if (systemClasses [i] == null) {
4929 systemClasses [i] = aClass;
4934 internal Class GetSpecialSystemClass(PrimitiveType pType)
4936 int ix = pType.GetSystemTypeIx();
4937 if (systemClasses[ix] == null && !PEFile.IsMSCorlib) {
4938 systemClasses[ix] = new SystemClass(pType,this,metaData);
4939 metaData.AddToTable(MDTable.TypeRef,systemClasses[ix]);
4941 return systemClasses[ix];
4944 private ClassRef GetValueClass(string name, int hash)
4946 /* Called by MSCorLib.AddValueClass, which is called by
4947 !mscorlib, for adding ref to value class INTO mscorlib,
4948 so this should be classref */
4949 int ix = valueTypeIx;
4950 if (hash != specialNames[valueTypeIx]) ix++;
4951 if (systemClasses[ix] == null) {
4952 systemClasses[ix] = new ClassRef(systemName,name,metaData);
4953 ((ClassRef) systemClasses[ix]).SetParent(this);
4954 ((ClassRef) systemClasses[ix]).MakeValueClass(ValueClass.ValueType);
4955 metaData.AddToTable(MDTable.TypeRef,systemClasses[ix]);
4957 return (ClassRef) systemClasses[ix];
4960 internal Class ValueType()
4962 if (systemClasses[valueTypeIx] == null && !PEFile.IsMSCorlib) {
4963 ClassRef valType = new ClassRef("System","ValueType",metaData);
4964 valType.SetParent(this);
4965 valType.MakeValueClass(ValueClass.ValueType);
4966 metaData.AddToTable(MDTable.TypeRef,valType);
4967 systemClasses[valueTypeIx] = valType;
4969 return systemClasses[valueTypeIx];
4972 internal Class EnumType()
4974 /* Called by both mscorlib & !mscorlib, so can be
4975 either ClassRef or ClassDef */
4976 //systemClasses [ valueTypeIx + 1] -> System.Enum
4977 if (systemClasses[valueTypeIx + 1] == null && !PEFile.IsMSCorlib) {
4978 ClassRef valType = new ClassRef("System","Enum",metaData);
4979 valType.SetParent(this);
4980 valType.MakeValueClass(ValueClass.Enum);
4981 metaData.AddToTable(MDTable.TypeRef,valType);
4982 systemClasses[valueTypeIx + 1] = valType;
4984 return systemClasses[valueTypeIx + 1];
4988 /// Add a value class to this external assembly
4990 /// <param name="nsName">name space name</param>
4991 /// <param name="name">class name</param>
4992 /// <returns></returns>
4993 public override ClassRef AddValueClass(string nsName, string name)
4995 if (nsName.CompareTo(systemName) == 0) {
4996 int hash = name.GetHashCode();
4997 if ((hash == specialNames[valueTypeIx]) ||
4998 (hash == specialNames[valueTypeIx+1])) {
4999 return GetValueClass(name,hash);
5002 ClassRef aClass = new ClassRef(nsName,name,metaData);
5003 metaData.AddToTable(MDTable.TypeRef,aClass);
5004 aClass.SetParent(this);
5005 aClass.MakeValueClass(ValueClass.ValueType);
5011 /**************************************************************************/
5014 /// Root (20 bytes + UTF-8 Version String + quad align padding)
5015 /// StreamHeaders (8 bytes + null terminated name string + quad align padding)
5017 /// #~ (always present - holds metadata tables)
5018 /// #Strings (always present - holds identifier strings)
5019 /// #US (Userstring heap)
5020 /// #Blob (signature blobs)
5021 /// #GUID (guids for assemblies or Modules)
5023 public class MetaData {
5025 internal static readonly int[] CIxShiftMap = {2,2,5,1,2,3,1,1,1,2,3,2,1};
5026 private static readonly byte StringsHeapMask = 0x1;
5027 private static readonly byte GUIDHeapMask = 0x2;
5028 private static readonly byte BlobHeapMask = 0x4;
5029 private static readonly uint MetaDataSignature = 0x424A5342;
5030 private static readonly uint maxSmlIxSize = 0xFFFF;
5031 private static readonly uint max1BitSmlIx = 0x7FFF;
5032 private static readonly uint max2BitSmlIx = 0x3FFF;
5033 private static readonly uint max3BitSmlIx = 0x1FFF;
5034 private static readonly uint max5BitSmlIx = 0x7FF;
5035 // NOTE: version and stream name strings MUST always be quad padded
5036 private static readonly string version = "v4.0.30319\0\0";
5037 private static readonly char[] tildeName = {'#','~','\0','\0'};
5038 private static readonly char[] stringsName = {'#','S','t','r','i','n','g','s','\0','\0','\0','\0'};
5039 private static readonly char[] usName = {'#','U','S','\0'};
5040 private static readonly char[] guidName = {'#','G','U','I','D','\0','\0','\0'};
5041 private static readonly char[] blobName = {'#','B','l','o','b','\0','\0','\0'};
5042 private static readonly uint MetaDataHeaderSize = 20 + (uint)version.Length;
5043 private static readonly uint TildeHeaderSize = 24;
5044 private static readonly uint StreamHeaderSize = 8;
5045 private static readonly uint numMetaDataTables = (int)MDTable.GenericParamConstraint + 1;
5047 MetaDataStream strings, us, guid, blob;
5049 MetaDataStream[] streams = new MetaDataStream[5];
5050 uint numStreams = 5;
5051 uint tildeTide = 0, tildePadding = 0, tildeStart = 0;
5052 uint numTables = 0, resourcesSize = 0;
5053 ArrayList[] metaDataTables = new ArrayList[numMetaDataTables];
5054 ArrayList byteCodes = new ArrayList();
5055 uint codeSize = 0, codeStart, byteCodePadding = 0, metaDataSize = 0;
5056 ulong valid = 0, /*sorted = 0x000002003301FA00;*/ sorted = 0;
5057 bool[] largeIx = new bool[numMetaDataTables];
5058 bool[] lgeCIx = new bool[(int)CIx.MaxCIx];
5059 bool largeStrings = false, largeUS = false, largeGUID = false, largeBlob = false;
5060 private FileImage file;
5061 private byte heapSizes = 0;
5062 MetaDataElement entryPoint;
5063 BinaryWriter output;
5065 private TypeSpec[] systemTypeSpecs = new TypeSpec[PrimitiveType.NumSystemTypes];
5067 private ArrayList cattr_list;
5068 private ArrayList declsec_list;
5069 ArrayList resources;
5071 internal MetaData(FileImage file)
5073 // tilde = new MetaDataStream(tildeName,false,0);
5075 strings = new MetaDataStream(stringsName,new UTF8Encoding(),true);
5076 us = new MetaDataStream(usName,new UnicodeEncoding(),true);
5077 guid = new MetaDataStream(guidName,false);
5078 blob = new MetaDataStream(blobName,true);
5079 streams[1] = strings;
5083 for (int i=0; i < numMetaDataTables; i++) {
5086 for (int i=0; i < lgeCIx.Length; i++) {
5091 public MSCorLib mscorlib {
5093 return _mscorlib ?? (_mscorlib = new MSCorLib (this));
5098 internal TypeSpec GetPrimitiveTypeSpec(int ix)
5100 return systemTypeSpecs[ix];
5103 internal void SetPrimitiveTypeSpec(int ix, TypeSpec typeSpec)
5105 systemTypeSpecs[ix] = typeSpec;
5108 internal uint Size()
5110 return metaDataSize;
5113 private void CalcHeapSizes ()
5115 if (strings.LargeIx()) {
5116 largeStrings = true;
5117 heapSizes |= StringsHeapMask;
5119 if (guid.LargeIx()) {
5121 heapSizes |= GUIDHeapMask;
5123 if (blob.LargeIx()) {
5125 heapSizes |= BlobHeapMask;
5128 largeUS = us.LargeIx();
5131 internal void StreamSize(byte mask)
5136 internal uint AddToUSHeap(string str)
5138 if (str == null) return 0;
5139 return us.Add(str,true);
5142 internal uint AddToUSHeap(byte[] str)
5144 if (str == null) return 0;
5145 return us.Add (str, true);
5148 internal uint AddToStringsHeap(string str)
5150 if ((str == null) || (str.CompareTo("") == 0)) return 0;
5151 return strings.Add(str,false);
5154 internal uint AddToGUIDHeap(Guid guidNum)
5156 return guid.Add(guidNum, false);
5159 internal uint AddToBlobHeap(byte[] blobBytes)
5161 if (blobBytes == null) return 0;
5162 return blob.Add(blobBytes, true);
5165 internal uint AddToBlobHeap(byte val)
5167 return blob.Add(val, true);
5170 internal uint AddToBlobHeap(sbyte val)
5172 return blob.Add(val, true);
5175 internal uint AddToBlobHeap(ushort val)
5177 return blob.Add(val, true);
5180 internal uint AddToBlobHeap(short val)
5182 return blob.Add(val, true);
5185 internal uint AddToBlobHeap(uint val)
5187 return blob.Add(val, true);
5190 internal uint AddToBlobHeap(int val)
5192 return blob.Add(val, true);
5195 internal uint AddToBlobHeap(ulong val)
5197 return blob.Add(val, true);
5200 internal uint AddToBlobHeap(long val)
5202 return blob.Add(val, true);
5205 internal uint AddToBlobHeap(float val)
5207 return blob.Add(val, true);
5210 internal uint AddToBlobHeap(double val)
5212 return blob.Add(val, true);
5215 internal uint AddToBlobHeap(string val)
5217 return blob.Add(val,true);
5220 internal void AddCustomAttribute (CustomAttribute cattr)
5222 if (cattr_list == null)
5223 cattr_list = new ArrayList ();
5224 cattr_list.Add (cattr);
5227 internal void AddDeclSecurity (BaseDeclSecurity decl_sec)
5229 if (declsec_list == null)
5230 declsec_list = new ArrayList ();
5231 declsec_list.Add (decl_sec);
5234 private ArrayList GetTable(MDTable tableIx)
5236 int tabIx = (int)tableIx;
5237 if (metaDataTables[tabIx] == null) {
5238 metaDataTables[tabIx] = new ArrayList();
5239 valid |= ((ulong)0x1 << tabIx);
5240 // Console.WriteLine("after creating table " + tableIx + "(" + tabIx + ") valid = " + valid);
5243 return metaDataTables[tabIx];
5246 internal void AddToTable(MDTable tableIx, MetaDataElement elem)
5249 // Console.Out.WriteLine("ERROR - element already in table " + tableIx);
5252 // updates Row field of the element
5253 // Console.WriteLine("Adding element to table " + (uint)tableIx);
5254 ArrayList table = GetTable(tableIx);
5255 elem.Row = (uint)table.Count + 1;
5259 internal uint TableIndex(MDTable tableIx)
5261 if (metaDataTables[(int)tableIx] == null) return 1;
5262 return (uint)metaDataTables[(int)tableIx].Count+1;
5265 internal uint AddCode(CILInstructions byteCode)
5267 byteCodes.Add(byteCode);
5268 uint offset = codeSize + codeStart;
5269 codeSize += byteCode.GetCodeSize();
5273 internal void SetEntryPoint(MetaDataElement ep)
5278 internal uint AddResource(byte[] resBytes)
5280 if (resources == null) resources = new ArrayList ();
5281 resources.Add (resBytes);
5282 uint offset = resourcesSize;
5283 resourcesSize += (uint)resBytes.Length + 4;
5287 internal void AddData(DataConstant cVal)
5289 file.AddInitData(cVal);
5292 internal static void CompressNum(uint val, MemoryStream sig)
5295 sig.WriteByte((byte)val);
5296 } else if (val <= 0x3FFF) {
5297 byte b1 = (byte)((val >> 8) | 0x80);
5298 byte b2 = (byte)(val & FileImage.iByteMask[0]);
5302 byte b1 = (byte)((val >> 24) | 0xC0);
5303 byte b2 = (byte)((val & FileImage.iByteMask[2]) >> 16);
5304 byte b3 = (byte)((val & FileImage.iByteMask[1]) >> 8);;
5305 byte b4 = (byte)(val & FileImage.iByteMask[0]);
5313 internal uint CodeSize()
5315 return codeSize + byteCodePadding;
5318 internal uint GetResourcesSize()
5320 return resourcesSize;
5323 internal uint StringsIndexSize()
5325 if (largeStrings) return 4;
5329 internal uint GUIDIndexSize()
5331 if (largeGUID) return 4;
5335 internal uint USIndexSize()
5337 if (largeUS) return 4;
5341 internal uint BlobIndexSize()
5343 if (largeBlob) return 4;
5347 internal uint CodedIndexSize(CIx code)
5349 if (lgeCIx[(uint)code]) return 4;
5353 internal uint TableIndexSize(MDTable tabIx)
5355 if (largeIx[(uint)tabIx]) return 4;
5359 private void SetIndexSizes()
5361 for (int i=0; i < numMetaDataTables; i++) {
5362 if (metaDataTables[i] == null)
5365 uint count = (uint)metaDataTables[i].Count;
5366 if (count > maxSmlIxSize)
5369 MDTable tabIx = (MDTable)i;
5370 if (count > max5BitSmlIx) {
5371 if (tabIx == MDTable.Method || tabIx == MDTable.Field || tabIx == MDTable.TypeRef ||
5372 tabIx == MDTable.TypeDef || tabIx == MDTable.Param || tabIx == MDTable.InterfaceImpl ||
5373 tabIx == MDTable.MemberRef || tabIx == MDTable.Module || tabIx == MDTable.DeclSecurity ||
5374 tabIx == MDTable.Property || tabIx == MDTable.Event || tabIx == MDTable.StandAloneSig ||
5375 tabIx == MDTable.ModuleRef || tabIx == MDTable.TypeSpec || tabIx == MDTable.Assembly ||
5376 tabIx == MDTable.AssemblyRef || tabIx == MDTable.File || tabIx == MDTable.ExportedType ||
5377 tabIx == MDTable.ManifestResource || tabIx == MDTable.GenericParam)
5378 lgeCIx[(int)CIx.HasCustomAttr] = true;
5380 if (count > max3BitSmlIx) {
5381 if (tabIx == MDTable.Method || tabIx == MDTable.MemberRef)
5382 lgeCIx[(int)CIx.CustomAttributeType] = true;
5383 if (tabIx == MDTable.TypeDef || tabIx == MDTable.TypeRef || tabIx == MDTable.ModuleRef ||
5384 tabIx == MDTable.Method || tabIx == MDTable.TypeSpec)
5385 lgeCIx[(int)CIx.MemberRefParent] = true;
5387 if (count > max2BitSmlIx) {
5388 if ((tabIx == MDTable.Field) || (tabIx == MDTable.Param) || (tabIx == MDTable.Property))
5389 lgeCIx[(int)CIx.HasConst] = true;
5390 if ((tabIx == MDTable.TypeDef) || (tabIx == MDTable.TypeRef) || (tabIx == MDTable.TypeSpec))
5391 lgeCIx[(int)CIx.TypeDefOrRef] = true;
5392 if ((tabIx == MDTable.TypeDef) || (tabIx == MDTable.Method) || (tabIx == MDTable.Assembly))
5393 lgeCIx[(int)CIx.HasDeclSecurity] = true;
5394 if ((tabIx == MDTable.File) || (tabIx == MDTable.AssemblyRef) || (tabIx == MDTable.ExportedType))
5395 lgeCIx[(int)CIx.Implementation] = true;
5396 if ((tabIx == MDTable.Module) || (tabIx == MDTable.ModuleRef) || (tabIx == MDTable.AssemblyRef) || (tabIx == MDTable.TypeRef))
5397 lgeCIx[(int)CIx.ResolutionScope] = true;
5399 if (count > max1BitSmlIx) {
5400 if ((tabIx == MDTable.Field) || (tabIx == MDTable.Param))
5401 lgeCIx[(int)CIx.HasFieldMarshal] = true;
5402 if ((tabIx == MDTable.Event) || (tabIx == MDTable.Property))
5403 lgeCIx[(int)CIx.HasSemantics] = true;
5404 if ((tabIx == MDTable.Method) || (tabIx == MDTable.MemberRef))
5405 lgeCIx[(int)CIx.MethodDefOrRef] = true;
5406 if ((tabIx == MDTable.Field) || (tabIx == MDTable.Method))
5407 lgeCIx[(int)CIx.MemberForwarded] = true;
5408 if ((tabIx == MDTable.TypeDef) || (tabIx == MDTable.Method))
5409 lgeCIx[(int)CIx.TypeOrMethodDef] = true;
5414 private void SetStreamOffsets()
5416 uint sizeOfHeaders = StreamHeaderSize + (uint)tildeName.Length;
5417 for (int i=1; i < numStreams; i++) {
5418 sizeOfHeaders += streams[i].headerSize();
5420 metaDataSize = MetaDataHeaderSize + sizeOfHeaders;
5421 tildeStart = metaDataSize;
5422 metaDataSize += tildeTide + tildePadding;
5423 for (int i=1; i < numStreams; i++) {
5424 streams[i].Start = metaDataSize;
5425 metaDataSize += streams[i].Size();
5426 streams[i].WriteDetails();
5430 internal void CalcTildeStreamSize()
5433 //tilde.SetIndexSizes(strings.LargeIx(),us.LargeIx(),guid.LargeIx(),blob.LargeIx());
5434 tildeTide = TildeHeaderSize;
5435 tildeTide += 4 * numTables;
5436 //Console.WriteLine("Tilde header + sizes = " + tildeTide);
5437 for (int i=0; i < numMetaDataTables; i++) {
5438 if (metaDataTables[i] != null) {
5439 ArrayList table = metaDataTables[i];
5440 // Console.WriteLine("Meta data table " + i + " at offset " + tildeTide);
5441 tildeTide += (uint)table.Count * ((MetaDataElement)table[0]).Size(this);
5442 // Console.WriteLine("Metadata table " + i + " has size " + table.Count);
5443 // Console.WriteLine("tildeTide = " + tildeTide);
5446 if ((tildeTide % 4) != 0) tildePadding = 4 - (tildeTide % 4);
5447 //Console.WriteLine("tildePadding = " + tildePadding);
5450 internal void WriteTildeStream(FileImage output)
5452 output.Seek(0,SeekOrigin.Current);
5453 output.Write((uint)0); // Reserved
5454 output.Write((byte)2); // MajorVersion
5455 output.Write((byte)0); // MinorVersion
5456 output.Write(heapSizes);
5457 output.Write((byte)1); // Reserved
5458 output.Write(valid);
5459 output.Write(sorted);
5461 for (int i=0; i < numMetaDataTables; i++) {
5462 if (metaDataTables[i] != null) {
5463 uint count = (uint)metaDataTables[i].Count;
5464 output.Write(count);
5468 output.Seek(0,SeekOrigin.Current);
5469 // Console.WriteLine("Starting metaData tables at " + tabStart);
5470 for (int i=0; i < numMetaDataTables; i++) {
5471 if (metaDataTables[i] != null) {
5472 // Console.WriteLine("Starting metaData table " + i + " at " + (output.Seek(0,SeekOrigin.Current) - startTilde));
5473 ArrayList table = metaDataTables[i];
5474 for (int j=0; j < table.Count; j++) {
5475 ((MetaDataElement)table[j]).Write(output);
5479 // Console.WriteLine("Writing padding at " + output.Seek(0,SeekOrigin.Current));
5480 for (int i=0; i < tildePadding; i++) output.Write((byte)0);
5483 private void BuildTable(ArrayList table)
5485 if (table == null) return;
5486 for (int j=0; j < table.Count; j++) {
5487 ((MetaDataElement)table[j]).BuildTables(this);
5491 private void SortTable (ArrayList mTable)
5493 if (mTable == null) return;
5495 for (int i=0; i < mTable.Count; i++) {
5496 ((MetaDataElement)mTable[i]).Row = (uint)i+1;
5500 internal void BuildMetaData(uint codeStartOffset)
5502 codeStart = codeStartOffset;
5503 BuildTable(metaDataTables[(int)MDTable.TypeDef]);
5504 BuildTable(metaDataTables[(int)MDTable.TypeSpec]);
5505 BuildTable(metaDataTables[(int)MDTable.MemberRef]);
5506 BuildTable(metaDataTables[(int)MDTable.GenericParam]);
5507 BuildTable(metaDataTables[(int)MDTable.MethodSpec]);
5508 BuildTable(metaDataTables[(int)MDTable.GenericParamConstraint]);
5509 BuildTable(metaDataTables[(int)MDTable.ManifestResource]);
5511 if (cattr_list != null) {
5512 foreach (CustomAttribute cattr in cattr_list)
5513 cattr.BuildTables (this);
5516 if (declsec_list != null) {
5517 foreach (BaseDeclSecurity decl_sec in declsec_list)
5518 decl_sec.BuildTables (this);
5521 /* for (int i=0; i < metaDataTables.Length; i++) {
5522 ArrayList table = metaDataTables[i];
5523 if (table != null) {
5524 for (int j=0; j < table.Count; j++) {
5525 ((MetaDataElement)table[j]).BuildTables(this);
5532 for (int i=1; i < numStreams; i++) {
5533 streams[i].EndStream();
5535 CalcTildeStreamSize();
5537 byteCodePadding = NumToAlign(codeSize,4);
5538 if (entryPoint != null) file.SetEntryPoint(entryPoint.Token());
5540 // Check ordering of specific tables
5541 // Constant, CustomAttribute, FieldMarshal, DeclSecurity, MethodSemantics
5542 // ImplMap, GenericParam
5543 // Need to load GenericParamConstraint AFTER GenericParam table in correct order
5545 // InterfaceImpl, ClassLayout, FieldLayout, MethodImpl, FieldRVA, NestedClass
5546 // will _ALWAYS_ be in the correct order as embedded in BuildMDTables
5548 SortTable(metaDataTables[(int)MDTable.Constant]);
5549 SortTable(metaDataTables[(int)MDTable.FieldMarshal]);
5550 SortTable(metaDataTables[(int)MDTable.DeclSecurity]);
5551 SortTable(metaDataTables[(int)MDTable.MethodSemantics]);
5552 SortTable(metaDataTables[(int)MDTable.ImplMap]);
5553 if (metaDataTables[(int)MDTable.GenericParam] != null) {
5554 SortTable(metaDataTables[(int)MDTable.GenericParam]);
5555 // Now add GenericParamConstraints
5556 /*for (int i=0; i < metaDataTables[(int)MDTable.GenericParam].Count; i++) {
5557 ((GenericParameter)metaDataTables[(int)MDTable.GenericParam][i]).AddConstraints(this);
5560 SortTable(metaDataTables[(int)MDTable.GenericParamConstraint]);
5561 SortTable(metaDataTables[(int)MDTable.InterfaceImpl]);
5562 SortTable(metaDataTables[(int)MDTable.CustomAttribute]);
5566 internal void WriteByteCodes(FileImage output)
5568 for (int i=0; i < byteCodes.Count; i++) {
5569 ((CILInstructions)byteCodes[i]).Write(output);
5571 for (int i=0; i < byteCodePadding; i++) {
5572 output.Write((byte)0);
5576 internal void WriteResources (FileImage output)
5578 if (resources == null) return;
5579 for (int i = 0; i < resources.Count; i ++) {
5580 byte [] resBytes = (byte []) resources [i];
5581 output.Write ((uint) resBytes.Length);
5582 output.Write (resBytes);
5586 internal void WriteMetaData(FileImage output)
5588 this.output = output;
5589 mdStart = output.Seek(0,SeekOrigin.Current);
5590 // Console.WriteLine("Writing metaData at " + Hex.Long(mdStart));
5591 output.Write(MetaDataSignature);
5592 output.Write((short)1); // Major Version
5593 output.Write((short)1); // Minor Version ECMA = 0, PEFiles = 1
5594 output.Write(0); // Reserved
5595 output.Write(version.Length);
5596 output.Write(version.ToCharArray()); // version string is already zero padded
5597 output.Write((short)0);
5598 output.Write((ushort)numStreams);
5599 // write tilde header
5600 output.Write(tildeStart);
5601 output.Write(tildeTide + tildePadding);
5602 output.Write(tildeName);
5603 for (int i=1; i < numStreams; i++) streams[i].WriteHeader(output);
5604 // Console.WriteLine("Writing tilde stream at " + output.Seek(0,SeekOrigin.Current) + " = " + tildeStart);
5605 WriteTildeStream(output);
5606 for (int i=1; i < numStreams; i++) streams[i].Write(output);
5607 // Console.WriteLine("Finished Writing metaData at " + output.Seek(0,SeekOrigin.Current));
5610 internal bool LargeStringsIndex() { return strings.LargeIx(); }
5611 internal bool LargeGUIDIndex() { return guid.LargeIx(); }
5612 internal bool LargeUSIndex() { return us.LargeIx(); }
5613 internal bool LargeBlobIndex() { return blob.LargeIx(); }
5615 internal bool LargeIx(MDTable tabIx) { return largeIx[(uint)tabIx]; }
5618 private uint NumToAlign(uint val, uint alignVal)
5620 if ((val % alignVal) == 0) return 0;
5621 return alignVal - (val % alignVal);
5624 internal void WriteCodedIndex(CIx code, MetaDataElement elem, FileImage output)
5628 ix = (elem.Row << CIxShiftMap[(uint)code]) | elem.GetCodedIx(code);
5629 // Console.WriteLine("coded index = " + ix + " row = " + elem.Row);
5631 // Console.WriteLine("elem for coded index is null");
5633 if (lgeCIx[(uint)code])
5636 output.Write((ushort)ix);
5641 /**************************************************************************/
5643 /// Stream in the Meta Data (#Strings, #US, #Blob and #GUID)
5646 internal class MetaDataStream : BinaryWriter {
5648 private static readonly uint StreamHeaderSize = 8;
5649 private static uint maxSmlIxSize = 0xFFFF;
5651 private uint start = 0;
5652 uint size = 0, tide = 1;
5653 bool largeIx = false;
5656 Hashtable htable = new Hashtable();
5657 Hashtable btable = new Hashtable (new ByteArrayHashCodeProvider (), new ByteArrayComparer ());
5659 internal MetaDataStream(char[] name, bool addInitByte) : base(new MemoryStream())
5661 if (addInitByte) { Write((byte)0); size = 1; }
5663 sizeOfHeader = StreamHeaderSize + (uint)name.Length;
5666 internal MetaDataStream(char[] name, System.Text.Encoding enc, bool addInitByte) : base(new MemoryStream(),enc)
5668 if (addInitByte) { Write((byte)0); size = 1; }
5670 sizeOfHeader = StreamHeaderSize + (uint)name.Length;
5674 get { return start; }
5675 set { start = value; }
5678 internal uint headerSize()
5680 // Console.WriteLine(name + " stream has headersize of " + sizeOfHeader);
5681 return sizeOfHeader;
5684 internal void SetSize(uint siz)
5689 internal uint Size()
5694 internal bool LargeIx()
5699 internal void WriteDetails()
5701 // Console.WriteLine(name + " - size = " + size);
5704 internal uint Add(string str, bool prependSize)
5706 Object val = htable[str];
5710 htable[str] = index;
5711 char[] arr = str.ToCharArray();
5712 if (prependSize) CompressNum((uint)arr.Length*2+1);
5715 size = (uint)Seek(0,SeekOrigin.Current);
5721 internal uint Add (byte[] str, bool prependSize)
5723 Object val = btable [str];
5727 btable [str] = index;
5728 if (prependSize) CompressNum ((uint) str.Length);
5730 size = (uint) Seek (0, SeekOrigin.Current);
5738 internal uint Add(Guid guid, bool prependSize)
5740 byte [] b = guid.ToByteArray ();
5741 if (prependSize) CompressNum ((uint) b.Length);
5742 Write(guid.ToByteArray());
5743 size =(uint)Seek(0,SeekOrigin.Current);
5747 internal uint Add(byte[] blob)
5750 CompressNum((uint)blob.Length);
5752 size = (uint)Seek(0,SeekOrigin.Current);
5756 internal uint Add(byte val, bool prependSize)
5759 if (prependSize) CompressNum (1);
5761 size = (uint)Seek(0,SeekOrigin.Current);
5765 internal uint Add(sbyte val, bool prependSize)
5768 if (prependSize) CompressNum (1);
5770 size = (uint)Seek(0,SeekOrigin.Current);
5774 internal uint Add(ushort val, bool prependSize)
5777 if (prependSize) CompressNum (2);
5779 size = (uint)Seek(0,SeekOrigin.Current);
5783 internal uint Add(short val, bool prependSize)
5786 if (prependSize) CompressNum (2);
5788 size = (uint)Seek(0,SeekOrigin.Current);
5792 internal uint Add(uint val, bool prependSize)
5795 if (prependSize) CompressNum (4);
5797 size = (uint)Seek(0,SeekOrigin.Current);
5801 internal uint Add(int val, bool prependSize)
5804 if (prependSize) CompressNum (4);
5806 size = (uint)Seek(0,SeekOrigin.Current);
5810 internal uint Add(ulong val, bool prependSize)
5813 if (prependSize) CompressNum (8);
5815 size = (uint)Seek(0,SeekOrigin.Current);
5819 internal uint Add(long val, bool prependSize)
5822 if (prependSize) CompressNum (8);
5824 size = (uint)Seek(0,SeekOrigin.Current);
5828 internal uint Add(float val, bool prependSize)
5831 if (prependSize) CompressNum (4);
5833 size = (uint)Seek(0,SeekOrigin.Current);
5837 internal uint Add(double val, bool prependSize)
5840 if (prependSize) CompressNum (8);
5842 size = (uint)Seek(0,SeekOrigin.Current);
5846 private void CompressNum(uint val)
5850 } else if (val < 0x3FFF) {
5851 byte b1 = (byte)((val >> 8) | 0x80);
5852 byte b2 = (byte)(val & FileImage.iByteMask[0]);
5856 byte b1 = (byte)((val >> 24) | 0xC0);
5857 byte b2 = (byte)((val & FileImage.iByteMask[2]) >> 16);
5858 byte b3 = (byte)((val & FileImage.iByteMask[1]) >> 8);;
5859 byte b4 = (byte)(val & FileImage.iByteMask[0]);
5867 private void QuadAlign()
5869 if ((size % 4) != 0) {
5870 uint pad = 4 - (size % 4);
5872 for (int i=0; i < pad; i++) {
5878 internal void EndStream()
5881 if (size > maxSmlIxSize) {
5886 internal void WriteHeader(BinaryWriter output)
5888 output.Write(start);
5893 internal virtual void Write(BinaryWriter output)
5895 // Console.WriteLine("Writing " + name + " stream at " + output.Seek(0,SeekOrigin.Current) + " = " + start);
5896 MemoryStream str = (MemoryStream)BaseStream;
5897 output.Write(str.ToArray());
5902 /**************************************************************************/
5903 class ByteArrayComparer : IComparer {
5905 public int Compare (object x, object y)
5907 byte [] a = (byte []) x;
5908 byte [] b = (byte []) y;
5911 if (b.Length != len)
5914 for (int i = 0; i < len; ++i)
5921 class ByteArrayHashCodeProvider : IHashCodeProvider {
5923 public int GetHashCode (Object key)
5925 byte [] arr = (byte []) key;
5926 int len = arr.Length;
5929 for (int i = 0; i < len; ++i)
5930 h = (h << 5) - h + arr [i];