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 {
1644 ArrayList fields = new ArrayList();
1645 ArrayList methods = new ArrayList();
1647 ArrayList properties;
1648 bool typeIndexChecked = true;
1649 uint fieldIx = 0, methodIx = 0;
1652 ClassDef parentClass;
1655 internal ClassDef(TypeAttr attrSet, string nsName, string name,
1656 MetaData md) : base(nsName, name, md)
1659 if (! ((nsName == "" && name == "<Module>") || (nsName == "System" && name == "Object")) ) {
1660 superType = metaData.mscorlib.GetSpecialSystemClass(PrimitiveType.Object);
1662 flags = (uint)attrSet;
1663 tabIx = MDTable.TypeDef;
1666 internal void SetSuper(Class sClass)
1669 if (! (sClass is GenericTypeInst))
1670 typeIndexChecked = false;
1673 internal override void MakeValueClass(ValueClass vClass)
1675 if (vClass == ValueClass.Enum)
1676 superType = metaData.mscorlib.EnumType();
1678 superType = metaData.mscorlib.ValueType();
1680 typeIndex = PrimitiveType.ValueType.GetTypeIndex ();
1683 public void SpecialNoSuper()
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)
1928 if ((flags & (uint)TypeAttr.Interface) != 0) { superType = null; }
1929 // Console.WriteLine("Building tables for " + name);
1930 if (layout != null) md.AddToTable(MDTable.ClassLayout,layout);
1931 // Console.WriteLine("adding methods " + methods.Count);
1932 methodIx = md.TableIndex(MDTable.Method);
1933 for (int i=0; i < methods.Count; i++) {
1934 md.AddToTable(MDTable.Method,(MetaDataElement)methods[i]);
1935 ((MethodDef)methods[i]).BuildTables(md);
1937 // Console.WriteLine("adding fields");
1938 fieldIx = md.TableIndex(MDTable.Field);
1939 for (int i=0; i < fields.Count; i++) {
1940 md.AddToTable(MDTable.Field,(MetaDataElement)fields[i]);
1941 ((FieldDef)fields[i]).BuildTables(md);
1943 // Console.WriteLine("adding events and properties");
1944 if (events != null) {
1945 for (int i=0; i < events.Count; i++) {
1946 md.AddToTable(MDTable.Event,(Event)events[i]);
1947 ((Event)events[i]).BuildTables(md);
1949 md.AddToTable(MDTable.EventMap,
1950 new MapElem(this,((Event)events[0]).Row,MDTable.Event));
1952 if (properties != null) {
1953 for (int i=0; i < properties.Count; i++) {
1954 md.AddToTable(MDTable.Property,(Property)properties[i]);
1955 ((Property)properties[i]).BuildTables(md);
1957 md.AddToTable(MDTable.PropertyMap,new MapElem(this,
1958 ((Property)properties[0]).Row,MDTable.Property));
1960 // Console.WriteLine("End of building tables");
1964 internal sealed override uint Size(MetaData md)
1966 return 4 + 2 * md.StringsIndexSize() +
1967 md.CodedIndexSize(CIx.TypeDefOrRef) +
1968 md.TableIndexSize(MDTable.Field) +
1969 md.TableIndexSize(MDTable.Method);
1972 internal sealed override void Write(FileImage output)
1974 output.Write(flags);
1975 output.StringsIndex(nameIx);
1976 output.StringsIndex(nameSpaceIx);
1977 //if (superType != null)
1978 // Console.WriteLine("getting coded index for superType of " + name + " = " + superType.GetCodedIx(CIx.TypeDefOrRef));
1979 output.WriteCodedIndex(CIx.TypeDefOrRef,superType);
1980 output.WriteIndex(MDTable.Field,fieldIx);
1981 output.WriteIndex(MDTable.Method,methodIx);
1984 internal sealed override uint TypeDefOrRefToken()
1991 internal sealed override void TypeSig(MemoryStream sig)
1993 if (!typeIndexChecked) CheckTypeIndex();
1994 sig.WriteByte(GetTypeIndex());
1995 MetaData.CompressNum(TypeDefOrRefToken(),sig);
1998 internal sealed override uint GetCodedIx(CIx code)
2001 case (CIx.TypeDefOrRef) : return 0;
2002 case (CIx.HasCustomAttr) : return 3;
2003 case (CIx.HasDeclSecurity) : return 0;
2004 case (CIx.TypeOrMethodDef) : return 0;
2011 /**************************************************************************/
2013 /// Descriptor for a class/interface declared in another module of THIS
2014 /// assembly, or in another assembly.
2016 public class ClassRef : Class, IExternRef, IResolutionScope {
2018 protected IResolutionScope parent;
2019 protected MetaData metaData;
2021 internal ClassRef(string nsName, string name, MetaData md) : base(nsName, name, md)
2024 tabIx = MDTable.TypeRef;
2028 /// Add a method to this class
2030 /// <param name="name">method name</param>
2031 /// <param name="retType">return type</param>
2032 /// <param name="pars">parameter types</param>
2033 /// <returns>a descriptor for this method</returns>
2034 public MethodRef AddMethod(string name, Type retType, Type[] pars)
2036 return AddMethod (name, retType, pars, 0);
2040 /// Add a method to this class
2042 /// <param name="name">method name</param>
2043 /// <param name="retType">return type</param>
2044 /// <param name="pars">parameter types</param>
2045 /// <param name="gen_param_count">num of generic parameters</param>
2046 /// <returns>a descriptor for this method</returns>
2047 public MethodRef AddMethod (string name, Type retType, Type[] pars, int gen_param_count)
2049 MethodRef meth = new MethodRef (this, name, retType, pars, false, null, gen_param_count);
2050 metaData.AddToTable(MDTable.MemberRef,meth);
2055 /// Add a method to this class
2057 /// <param name="name">method name</param>
2058 /// <param name="retType">return type</param>
2059 /// <param name="pars">parameter types</param>
2060 /// <returns>a descriptor for this method</returns>
2061 public MethodRef AddVarArgMethod(string name, Type retType,
2062 Type[] pars, Type[] optPars)
2064 MethodRef meth = new MethodRef(this,name,retType,pars,true,optPars, 0);
2065 metaData.AddToTable(MDTable.MemberRef,meth);
2070 /// Add a field to this class
2072 /// <param name="name">field name</param>
2073 /// <param name="fType">field type</param>
2074 /// <returns>a descriptor for this field</returns>
2075 public FieldRef AddField(string name, Type fType)
2077 FieldRef field = new FieldRef(this,name,fType);
2078 metaData.AddToTable(MDTable.MemberRef,field);
2082 public ClassRef AddClass (string nsName, string name)
2084 ClassRef aClass = new ClassRef(nsName,name,metaData);
2085 metaData.AddToTable(MDTable.TypeRef,aClass);
2086 aClass.SetParent(this);
2090 public ClassRef AddValueClass (string nsName, string name)
2092 ClassRef aClass = AddClass (nsName, name);
2093 aClass.MakeValueClass (ValueClass.ValueType);
2097 internal void SetParent(IResolutionScope par)
2102 internal override string TypeName()
2104 if ((parent != null) && (parent is AssemblyRef))
2105 return (nameSpace + "." + name + ", " + ((AssemblyRef)parent).TypeName());
2107 return (nameSpace + name);
2110 internal sealed override uint Size(MetaData md)
2112 return md.CodedIndexSize(CIx.ResolutionScope) + 2 *
2113 md.StringsIndexSize();
2116 internal sealed override void Write(FileImage output)
2118 output.WriteCodedIndex(CIx.ResolutionScope,(MetaDataElement) parent);
2119 output.StringsIndex(nameIx);
2120 output.StringsIndex(nameSpaceIx);
2123 internal override sealed uint TypeDefOrRefToken()
2126 cIx = (cIx << 2) | 0x1;
2130 internal override void TypeSig(MemoryStream sig)
2132 sig.WriteByte(GetTypeIndex());
2133 MetaData.CompressNum(TypeDefOrRefToken(),sig);
2136 internal sealed override uint GetCodedIx(CIx code)
2139 case (CIx.TypeDefOrRef) : return 1;
2140 case (CIx.HasCustomAttr) : return 2;
2141 case (CIx.MemberRefParent) : return 1;
2142 case (CIx.ResolutionScope) : return 3;
2149 /**************************************************************************/
2150 public class ExternClassRef : ClassRef {
2152 ExternClass externClass;
2154 internal ExternClassRef(TypeAttr attrs, string nsName, string name,
2155 MetaDataElement declRef, MetaData md) : base(nsName,name,md)
2157 externClass = new ExternClass(attrs,nameSpaceIx,nameIx,declRef);
2158 metaData.AddToTable(MDTable.ExportedType,externClass);
2161 internal ExternClassRef(string name, MetaData md) : base(null,name,md)
2165 public ClassRef AddNestedClass(TypeAttr attrs, string name)
2167 ExternClassRef nestedClass = new ExternClassRef(name,metaData);
2168 externClass = new ExternClass(attrs,0,nameIx,this.externClass);
2169 metaData.AddToTable(MDTable.ExportedType,externClass);
2175 /**************************************************************************/
2177 /// Descriptor for a class defined in another module of THIS assembly
2178 /// and exported (.class extern)
2181 internal class ExternClass : Class {
2183 MetaDataElement parent;
2186 internal ExternClass(TypeAttr attr, uint nsIx, uint nIx,
2187 MetaDataElement paren) : base(nsIx,nIx)
2191 tabIx = MDTable.ExportedType;
2194 internal sealed override uint Size(MetaData md)
2196 return 8 + 2* md.StringsIndexSize() + md.CodedIndexSize(CIx.Implementation);
2199 internal sealed override void Write(FileImage output)
2201 output.Write(flags);
2203 output.StringsIndex(nameIx);
2204 output.StringsIndex(nameSpaceIx);
2205 output.WriteCodedIndex(CIx.Implementation,parent);
2208 internal sealed override uint GetCodedIx(CIx code)
2211 case (CIx.HasCustomAttr) : return 17;
2212 case (CIx.Implementation) : return 2;
2219 public class GenParam : Class {
2222 private string param_name;
2223 private uint sigIx = 0;
2225 public GenParam (int index, string name, GenParamType ptype) : base ((byte) ptype)
2228 this.param_name = name;
2229 tabIx = MDTable.TypeSpec;
2233 get { return index; }
2234 set { index = value; }
2237 public string Name {
2238 get { return param_name; }
2239 set { param_name = value; }
2242 public GenParamType Type {
2243 get { return (GenParamType) GetTypeIndex (); }
2246 internal sealed override void BuildTables (MetaData md)
2250 MemoryStream str = new MemoryStream ();
2252 sigIx = md.AddToBlobHeap (str.ToArray ());
2257 internal sealed override void TypeSig(MemoryStream str)
2260 throw new PEFileException (String.Format ("Unresolved {0} - {1}", (GenParamType) GetTypeIndex (), param_name));
2261 str.WriteByte(typeIndex);
2262 MetaData.CompressNum ((uint) index, str);
2265 internal override uint Size(MetaData md)
2267 return md.BlobIndexSize();
2270 internal sealed override void Write (FileImage output)
2272 output.BlobIndex (sigIx);
2275 internal sealed override uint GetCodedIx(CIx code)
2278 case (CIx.TypeDefOrRef) : return 2;
2279 case (CIx.HasCustomAttr) : return 13;
2280 case (CIx.MemberRefParent) : return 4;
2286 public class GenericTypeInst : Class {
2288 private Type gen_type;
2289 private Type[] gen_param;
2290 bool inTable = false;
2293 public GenericTypeInst (Type gen_type, Type[] gen_param)
2294 : base ((byte) PrimitiveType.GenericInst.GetTypeIndex ())
2296 this.gen_type = gen_type;
2297 this.gen_param = gen_param;
2298 tabIx = MDTable.TypeSpec;
2301 internal override MetaDataElement GetTypeSpec (MetaData md)
2304 md.AddToTable (MDTable.TypeSpec, this);
2311 internal sealed override void TypeSig(MemoryStream str)
2313 str.WriteByte(typeIndex);
2314 gen_type.TypeSig (str);
2315 MetaData.CompressNum ((uint) gen_param.Length, str);
2316 foreach (Type param in gen_param)
2317 param.TypeSig (str);
2320 internal sealed override void BuildTables (MetaData md)
2324 MemoryStream str = new MemoryStream ();
2326 sigIx = md.AddToBlobHeap (str.ToArray ());
2331 internal sealed override uint Size (MetaData md)
2333 return md.BlobIndexSize ();
2336 internal sealed override void Write (FileImage output)
2338 output.BlobIndex (sigIx);
2341 internal sealed override uint GetCodedIx (CIx code)
2344 case (CIx.TypeDefOrRef): return 2;
2345 case (CIx.MemberRefParent): return 4;
2346 case (CIx.HasCustomAttr): return 13;
2352 public class GenericMethodSig {
2354 private Type[] gen_param;
2356 private uint sigIx = 0;
2358 public GenericMethodSig (Type[] gen_param)
2360 this.gen_param = gen_param;
2364 internal void TypeSig (MemoryStream str)
2366 str.WriteByte (0x0A); /* GENERIC_INST */
2367 MetaData.CompressNum ((uint) gen_param.Length, str);
2368 foreach (Type param in gen_param)
2369 param.TypeSig (str);
2372 internal uint GetSigIx (MetaData md)
2377 MemoryStream sig = new MemoryStream();
2379 sigIx = md.AddToBlobHeap (sig.ToArray());
2385 public class Sentinel : Type {
2387 public Sentinel () : base (0x41) { }
2389 internal sealed override void TypeSig(MemoryStream str)
2391 str.WriteByte(typeIndex);
2395 /**************************************************************************/
2397 /// Descriptor for a FunctionPointer type
2400 public class MethPtrType : Type {
2412 /// Create a new function pointer type
2414 /// <param name="meth">the function to be referenced</param>
2415 public MethPtrType (CallConv callconv, Type retType, Type[] pars,
2416 bool varArgMeth, Type[] optPars) : base(0x1B)
2418 this.retType = retType;
2419 callConv = callconv;
2421 this.varArgMeth = varArgMeth;
2422 if (parList != null) numPars = (uint)parList.Length;
2424 optParList = optPars;
2425 if (optParList != null) numOptPars = (uint)optParList.Length;
2426 callConv |= CallConv.Vararg;
2428 tabIx = MDTable.TypeSpec;
2431 internal sealed override void TypeSig(MemoryStream sig)
2433 sig.WriteByte(typeIndex);
2434 // Bootlegged from method ref
2435 sig.WriteByte((byte)callConv);
2436 MetaData.CompressNum (numPars + numOptPars, sig);
2437 retType.TypeSig (sig);
2438 for (int i=0; i < numPars; i++) {
2439 parList[i].TypeSig (sig);
2442 sig.WriteByte (0x41); // Write the sentinel
2443 for (int i=0; i < numOptPars; i++) {
2444 optParList[i].TypeSig (sig);
2449 internal sealed override void BuildTables(MetaData md)
2452 MemoryStream sig = new MemoryStream();
2454 sigIx = md.AddToBlobHeap(sig.ToArray());
2458 internal sealed override uint Size(MetaData md)
2460 return md.BlobIndexSize();
2463 internal sealed override void Write(FileImage output)
2465 output.BlobIndex(sigIx);
2468 internal sealed override uint GetCodedIx(CIx code) { return 0x1B; }
2473 /* Classes for Arrays */
2476 /// The IL Array type
2478 public abstract class Array : Type {
2480 protected Type elemType;
2481 protected MetaData metaData;
2482 protected string cnameSpace, cname;
2484 internal Array(Type eType, byte TypeId) : base(TypeId)
2487 tabIx = MDTable.TypeSpec;
2492 /// Single dimensional array with zero lower bound
2494 public class ZeroBasedArray : Array {
2497 /// Create a new array - elementType[]
2499 /// <param name="elementType">the type of the array elements</param>
2500 public ZeroBasedArray(Type elementType) : base (elementType, PrimitiveType.SZArray.GetTypeIndex ()) { }
2502 internal sealed override void TypeSig(MemoryStream str)
2504 str.WriteByte(typeIndex);
2505 elemType.TypeSig(str);
2511 /// Multi dimensional array with explicit bounds
2513 public class BoundArray : Array {
2519 /// Create a new multi dimensional array type
2520 /// eg. elemType[1..5,3..10,5,,] would be
2521 /// new BoundArray(elemType,5,[1,3,0],[5,10,4])
2523 /// <param name="elementType">the type of the elements</param>
2524 /// <param name="dimensions">the number of dimensions</param>
2525 /// <param name="loBounds">lower bounds of dimensions</param>
2526 /// <param name="sizes">sizes for the dimensions</param>
2527 public BoundArray(Type elementType, uint dimensions, int[] loBounds,
2528 int[] sizes) : base (elementType,0x14)
2530 numDims = dimensions;
2531 lowerBounds = loBounds;
2536 /// Create a new multi dimensional array type
2537 /// eg. elemType[5,10,20] would be new BoundArray(elemType,3,[5,10,20])
2539 /// <param name="elementType">the type of the elements</param>
2540 /// <param name="dimensions">the number of dimensions</param>
2541 /// <param name="size">the sizes of the dimensions</param>
2542 public BoundArray(Type elementType, uint dimensions, int[] size)
2543 : base (elementType,0x14)
2545 numDims = dimensions;
2550 /// Create a new multi dimensional array type
2551 /// eg. elemType[,,] would be new BoundArray(elemType,3)
2553 /// <param name="elementType">the type of the elements</param>
2554 /// <param name="dimensions">the number of dimensions</param>
2555 public BoundArray(Type elementType, uint dimensions)
2556 : base (elementType,0x14)
2558 numDims = dimensions;
2561 internal sealed override void TypeSig(MemoryStream str)
2563 str.WriteByte(typeIndex);
2564 elemType.TypeSig(str);
2565 MetaData.CompressNum(numDims,str);
2566 if ((sizes != null) && (sizes.Length > 0)) {
2568 MetaData.CompressNum((uint)sizes.Length,str);
2569 for (int i=0; i < sizes.Length; i++) {
2570 MetaData.CompressNum((uint)sizes[i],str);
2572 } else str.WriteByte(0);
2573 if ((lowerBounds != null) && (lowerBounds.Length > 0)) {
2574 MetaData.CompressNum((uint)lowerBounds.Length,str);
2575 for (int i=0; i < lowerBounds.Length; i++) {
2576 CompressSignedNum (lowerBounds[i],str);
2578 } else str.WriteByte(0);
2580 private void CompressSignedNum (int val, MemoryStream str)
2582 uint uval = (uint) val;
2589 /* Map the signed number to an unsigned number in two ways.
2591 fval: left-rotated 2's complement representation
2592 sval: map the signed number to unsigned as follows: 0 -> 0, -1 -> 1, 1 -> 2, -2 -> 3, 2 -> 4, ....
2593 the mapping is: x -> 2*|x| - signbit(x)
2595 uint fval = (uval << 1) | sign;
2596 int sval = (val << 1) - sign;
2598 /* An overly clever transformation:
2600 a. sval is used to determine the number of bytes in the compressed representation.
2601 b. fval is truncated to the appropriate number of bits and output using the
2602 normal unsigned-int compressor.
2604 However, or certain values, the truncated fval doesn't carry enough information to round trip.
2606 (fval & 0x3FFF) <= 0x7F => compressor emits 1 byte, not 2 => there is aliasing of values
2608 So, we use full 4 bytes to encode such values.
2610 LAMESPEC: The Microsoft implementation doesn't appear to handle this subtle case.
2611 e.g., it ends up encoding -8192 as the byte 0x01, which decodes to -64
2614 MetaData.CompressNum (fval & 0x7F, str);
2615 else if (sval <= 0x3FFF && (fval & 0x3FFF) > 0x7F)
2616 MetaData.CompressNum (fval & 0x3FFF, str);
2617 else if (sval <= 0x1FFFFFFF && (fval & 0x1FFFFFFF) > 0x3FFF)
2618 MetaData.CompressNum (fval & 0x1FFFFFFF, str);
2620 /* FIXME: number cannot be represented. Report a warning. */
2621 // throw new Exception ("cannot represent signed value" + -val);
2622 MetaData.CompressNum (fval, str);
2629 /* Empty interface for grouping TypeRef's possible ResolutionScope
2630 namely : Module, ModuleRef, AssemblyRef and TypeRef */
2631 public interface IResolutionScope {
2634 /**************************************************************************/
2636 /// Base class for scopes (extended by Module, ModuleRef, Assembly, AssemblyRef)
2638 public abstract class ResolutionScope : MetaDataElement, IResolutionScope {
2640 protected uint nameIx = 0;
2641 protected MetaData metaData;
2642 protected string name;
2644 internal ResolutionScope(string name, MetaData md)
2648 nameIx = md.AddToStringsHeap(name);
2651 internal string GetName() { return name; }
2655 /**************************************************************************/
2657 /// Descriptor for THIS assembly (.assembly)
2659 public class Assembly : ResolutionScope {
2661 ushort majorVer, minorVer, buildNo, revisionNo;
2664 uint keyIx = 0, cultIx = 0;
2665 bool hasPublicKey = false;
2667 internal Assembly(string name, MetaData md) : base(name,md)
2669 tabIx = MDTable.Assembly;
2673 /// Add details about THIS assembly
2675 /// <param name="majVer">Major Version</param>
2676 /// <param name="minVer">Minor Version</param>
2677 /// <param name="bldNo">Build Number</param>
2678 /// <param name="revNo">Revision Number</param>
2679 /// <param name="key">Hash Key</param>
2680 /// <param name="hash">Hash Algorithm</param>
2681 /// <param name="cult">Culture</param>
2682 public void AddAssemblyInfo(int majVer, int minVer, int bldNo, int revNo,
2683 byte[] key, uint hash, string cult)
2685 majorVer = (ushort)majVer;
2686 minorVer = (ushort)minVer;
2687 buildNo = (ushort)bldNo;
2688 revisionNo = (ushort)revNo;
2690 hasPublicKey = (key != null);
2691 keyIx = metaData.AddToBlobHeap(key);
2692 cultIx = metaData.AddToStringsHeap(cult);
2696 /// Add an attribute to THIS assembly
2698 /// <param name="aa">assembly attribute</param>
2699 public void AddAssemblyAttr(AssemAttr aa)
2704 internal sealed override uint Size(MetaData md)
2706 return 16 + md.BlobIndexSize() + 2 * md.StringsIndexSize();
2709 internal sealed override void Write(FileImage output)
2711 // Console.WriteLine("Writing assembly element with nameIx of " + nameIx + " at file offset " + output.Seek(0,SeekOrigin.Current));
2712 output.Write((uint)hashAlgId);
2713 output.Write(majorVer);
2714 output.Write(minorVer);
2715 output.Write(buildNo);
2716 output.Write(revisionNo);
2717 output.Write(flags);
2718 output.BlobIndex(keyIx);
2719 output.StringsIndex(nameIx);
2720 output.StringsIndex(cultIx);
2723 internal sealed override uint GetCodedIx(CIx code)
2726 case (CIx.HasCustomAttr) : return 14;
2727 case (CIx.HasDeclSecurity) : return 2;
2732 internal bool HasPublicKey {
2733 get { return hasPublicKey; }
2737 /**************************************************************************/
2739 /// Descriptor for THIS module
2741 public class Module : ResolutionScope, IExternRef {
2746 internal Module(string name, MetaData md) : base(name,md)
2748 mvid = Guid.NewGuid();
2749 mvidIx = md.AddToGUIDHeap(mvid);
2750 tabIx = MDTable.Module;
2754 get { return mvid; }
2757 public ClassRef AddClass(string nsName, string name)
2759 ClassRef aClass = new ClassRef (nsName, name, metaData);
2760 metaData.AddToTable (MDTable.TypeRef, aClass);
2761 aClass.SetParent (this);
2765 public ClassRef AddValueClass(string nsName, string name)
2767 ClassRef aClass = AddClass (nsName, name);
2768 aClass.MakeValueClass (ValueClass.ValueType);
2772 internal sealed override uint Size(MetaData md)
2774 return 2 + md.StringsIndexSize() + 3 * md.GUIDIndexSize();
2777 internal sealed override void Write(FileImage output)
2779 output.Write((short)0);
2780 output.StringsIndex(nameIx);
2781 output.GUIDIndex(mvidIx);
2782 output.GUIDIndex(0);
2783 output.GUIDIndex(0);
2786 internal sealed override uint GetCodedIx(CIx code)
2789 case (CIx.HasCustomAttr) : return 7;
2790 case (CIx.ResolutionScope) : return 0;
2795 /**************************************************************************/
2797 /// Descriptor for another module in THIS assembly
2799 public class ModuleRef : ResolutionScope, IExternRef {
2801 internal ModuleRef(MetaData md, string name) : base(name,md)
2803 tabIx = MDTable.ModuleRef;
2807 /// Add a class to this external module. This is a class declared in
2808 /// another module of THIS assembly.
2810 /// <param name="nsName">name space name</param>
2811 /// <param name="name">class name</param>
2812 /// <returns>a descriptor for this class in another module</returns>
2813 public ClassRef AddClass(string nsName, string name)
2815 ClassRef aClass = new ClassRef(nsName,name,metaData);
2816 metaData.AddToTable(MDTable.TypeRef,aClass);
2817 aClass.SetParent(this);
2822 /// Make a file descriptor to correspond to this module. The file
2823 /// descriptor will have the same name as the module descriptor
2825 /// <param name="hashBytes">the hash of the file</param>
2826 /// <param name="hasMetaData">the file contains metadata</param>
2827 /// <param name="entryPoint">the program entry point is in this file</param>
2828 /// <returns>a descriptor for the file which contains this module</returns>
2829 public FileRef MakeFile(byte[] hashBytes, bool hasMetaData, bool entryPoint)
2831 FileRef file = new FileRef(nameIx,hashBytes,hasMetaData,entryPoint,metaData);
2832 metaData.AddToTable(MDTable.File,file);
2837 /// Add a value class to this module. This is a class declared in
2838 /// another module of THIS assembly.
2840 /// <param name="nsName">name space name</param>
2841 /// <param name="name">class name</param>
2842 /// <returns></returns>
2843 public ClassRef AddValueClass(string nsName, string name)
2845 ClassRef aClass = new ClassRef(nsName,name,metaData);
2846 metaData.AddToTable(MDTable.TypeRef,aClass);
2847 aClass.SetParent(this);
2848 aClass.MakeValueClass(ValueClass.ValueType);
2853 /// Add a class which is declared public in this external module of
2854 /// THIS assembly. This class will be exported from this assembly.
2855 /// The ilasm syntax for this is .extern class
2857 /// <param name="attrSet">attributes of the class to be exported</param>
2858 /// <param name="nsName">name space name</param>
2859 /// <param name="name">external class name</param>
2860 /// <param name="declFile">the file where the class is declared</param>
2861 /// <param name="isValueClass">is this class a value type?</param>
2862 /// <returns>a descriptor for this external class</returns>
2863 public ExternClassRef AddExternClass(TypeAttr attrSet, string nsName,
2864 string name, FileRef declFile,
2865 bool isValueClass) {
2866 ExternClassRef cRef = new ExternClassRef(attrSet,nsName,name,declFile,metaData);
2867 metaData.AddToTable(MDTable.TypeRef,cRef);
2868 cRef.SetParent(this);
2869 if (isValueClass) cRef.MakeValueClass(ValueClass.ValueType);
2874 /// Add a "global" method in another module
2876 /// <param name="name">method name</param>
2877 /// <param name="retType">return type</param>
2878 /// <param name="pars">method parameter types</param>
2879 /// <returns>a descriptor for this method in anther module</returns>
2880 public MethodRef AddMethod(string name, Type retType, Type[] pars)
2882 MethodRef meth = new MethodRef(this,name,retType,pars,false,null, 0);
2883 metaData.AddToTable(MDTable.MemberRef,meth);
2888 /// Add a vararg method to this class
2890 /// <param name="name">method name</param>
2891 /// <param name="retType">return type</param>
2892 /// <param name="pars">parameter types</param>
2893 /// <param name="optPars">optional param types for this vararg method</param>
2894 /// <returns>a descriptor for this method</returns>
2895 public MethodRef AddVarArgMethod(string name, Type retType,
2896 Type[] pars, Type[] optPars) {
2897 MethodRef meth = new MethodRef(this,name,retType,pars,true,optPars, 0);
2898 metaData.AddToTable(MDTable.MemberRef,meth);
2903 /// Add a field in another module
2905 /// <param name="name">field name</param>
2906 /// <param name="fType">field type</param>
2907 /// <returns>a descriptor for this field in another module</returns>
2908 public FieldRef AddField(string name, Type fType)
2910 FieldRef field = new FieldRef(this,name,fType);
2911 metaData.AddToTable(MDTable.MemberRef,field);
2915 internal sealed override uint Size(MetaData md)
2917 return md.StringsIndexSize();
2920 internal sealed override void Write(FileImage output)
2922 output.StringsIndex(nameIx);
2925 internal sealed override uint GetCodedIx(CIx code)
2928 case (CIx.HasCustomAttr) : return 12;
2929 case (CIx.MemberRefParent) : return 2;
2930 case (CIx.ResolutionScope) : return 1;
2937 #region Classes for Constants
2939 /// Descriptor for a constant value
2941 public abstract class Constant {
2942 protected uint size = 0;
2943 protected Type type;
2944 protected uint blobIndex;
2945 protected bool addedToBlobHeap = false;
2947 internal Constant() { }
2949 internal virtual uint GetBlobIndex(MetaData md) { return 0; }
2951 internal uint GetSize() { return size; }
2953 internal byte GetTypeIndex() { return type.GetTypeIndex(); }
2955 internal virtual void Write(BinaryWriter bw) { }
2959 /// Descriptor for a constant value
2961 public abstract class DataConstant : Constant {
2962 private uint dataOffset = 0;
2964 internal DataConstant() { }
2966 public uint DataOffset {
2967 get { return dataOffset; }
2968 set { dataOffset = value; }
2974 /// Boolean constant
2976 public class BoolConst : DataConstant {
2980 /// Create a new boolean constant with the value "val"
2982 /// <param name="val">value of this boolean constant</param>
2983 public BoolConst(bool val)
2987 type = PrimitiveType.Boolean;
2990 internal sealed override uint GetBlobIndex(MetaData md)
2992 if (!addedToBlobHeap) {
2993 if (val) blobIndex = md.AddToBlobHeap((sbyte)1);
2994 else blobIndex = md.AddToBlobHeap((sbyte)0);
2995 addedToBlobHeap = true;
3000 internal sealed override void Write(BinaryWriter bw)
3002 if (val) bw.Write((sbyte)1);
3003 else bw.Write((sbyte)0);
3008 public class ByteArrConst : DataConstant {
3009 internal byte[] val;
3011 public ByteArrConst(byte[] val)
3013 type = PrimitiveType.String;
3015 size = (uint)val.Length;
3019 get { return type; }
3020 set { type = value; }
3023 internal sealed override uint GetBlobIndex(MetaData md)
3025 if (!addedToBlobHeap) {
3026 blobIndex = md.AddToBlobHeap(val);
3027 addedToBlobHeap = true;
3032 internal sealed override void Write(BinaryWriter bw)
3039 public class CharConst : Constant {
3042 public CharConst(char val)
3046 type = PrimitiveType.Char;
3049 internal sealed override uint GetBlobIndex(MetaData md)
3051 if (!addedToBlobHeap) {
3052 blobIndex = md.AddToBlobHeap(val);
3053 addedToBlobHeap = true;
3058 internal sealed override void Write(BinaryWriter bw)
3065 public class FloatConst : DataConstant {
3068 public FloatConst(float val)
3072 type = PrimitiveType.Float32;
3075 internal sealed override uint GetBlobIndex(MetaData md)
3077 if (!addedToBlobHeap) {
3078 blobIndex = md.AddToBlobHeap(val);
3079 addedToBlobHeap = true;
3084 internal sealed override void Write(BinaryWriter bw)
3091 public class DoubleConst : DataConstant {
3094 public DoubleConst(double val)
3098 type = PrimitiveType.Float64;
3101 internal sealed override uint GetBlobIndex(MetaData md)
3103 if (!addedToBlobHeap) {
3104 blobIndex = md.AddToBlobHeap(val);
3105 addedToBlobHeap = true;
3110 internal sealed override void Write(BinaryWriter bw)
3117 public class IntConst : DataConstant {
3120 public IntConst(sbyte val)
3124 type = PrimitiveType.Int8;
3127 public IntConst(short val)
3131 type = PrimitiveType.Int16;
3134 public IntConst(int val)
3138 type = PrimitiveType.Int32;
3141 public IntConst(long val)
3145 type = PrimitiveType.Int64;
3148 internal sealed override uint GetBlobIndex(MetaData md)
3150 if (!addedToBlobHeap) {
3152 case (1) : blobIndex = md.AddToBlobHeap((sbyte)val); break;
3153 case (2) : blobIndex = md.AddToBlobHeap((short)val); break;
3154 case (4) : blobIndex = md.AddToBlobHeap((int)val); break;
3155 default : blobIndex = md.AddToBlobHeap(val); break;
3157 addedToBlobHeap = true;
3162 internal sealed override void Write(BinaryWriter bw)
3165 case (1) : bw.Write((sbyte)val); break;
3166 case (2) : bw.Write((short)val); break;
3167 case (4) : bw.Write((int)val); break;
3168 default : bw.Write(val); break;
3174 public class UIntConst : DataConstant {
3177 public UIntConst(byte val)
3181 type = PrimitiveType.UInt8;
3183 public UIntConst(ushort val)
3187 type = PrimitiveType.UInt16;
3189 public UIntConst(uint val)
3193 type = PrimitiveType.UInt32;
3195 public UIntConst(ulong val)
3199 type = PrimitiveType.UInt64;
3202 internal sealed override uint GetBlobIndex(MetaData md)
3204 if (!addedToBlobHeap) {
3206 case (1) : blobIndex = md.AddToBlobHeap((byte)val); break;
3207 case (2) : blobIndex = md.AddToBlobHeap((ushort)val); break;
3208 case (4) : blobIndex = md.AddToBlobHeap((uint)val); break;
3209 default : blobIndex = md.AddToBlobHeap(val); break;
3211 addedToBlobHeap = true;
3216 internal sealed override void Write(BinaryWriter bw)
3219 case (1) : bw.Write((byte)val); break;
3220 case (2) : bw.Write((ushort)val); break;
3221 case (4) : bw.Write((uint)val); break;
3222 default : bw.Write(val); break;
3228 public class StringConst : DataConstant {
3229 internal string val;
3231 public StringConst(string val)
3234 size = (uint)val.Length; // need to add null ??
3235 type = PrimitiveType.String;
3238 internal sealed override uint GetBlobIndex(MetaData md)
3240 if (!addedToBlobHeap) {
3241 byte [] b = Encoding.Unicode.GetBytes (val);
3242 blobIndex = md.AddToBlobHeap(b);
3243 addedToBlobHeap = true;
3248 internal sealed override void Write(BinaryWriter bw)
3255 public class NullConst : Constant {
3260 type = PrimitiveType.Class;
3263 internal sealed override uint GetBlobIndex(MetaData md)
3265 if (!addedToBlobHeap) {
3266 blobIndex = md.AddToBlobHeap((int)0);
3267 addedToBlobHeap = true;
3272 internal sealed override void Write(BinaryWriter bw)
3279 public class AddressConstant : DataConstant {
3282 public AddressConstant(DataConstant dConst)
3286 type = PrimitiveType.TypedRef;
3289 internal sealed override void Write(BinaryWriter bw)
3291 ((FileImage)bw).WriteDataRVA(data.DataOffset);
3296 public class RepeatedConstant : DataConstant {
3300 public RepeatedConstant(DataConstant dConst, int repeatCount)
3303 repCount = (uint)repeatCount;
3304 int[] sizes = new int[1];
3305 sizes[0] = repeatCount;
3306 type = new BoundArray(type,1,sizes);
3307 size = data.GetSize() * repCount;
3310 internal sealed override void Write(BinaryWriter bw)
3312 for (int i=0; i < repCount; i++) {
3319 public class ArrayConstant : DataConstant {
3320 DataConstant[] dataVals;
3322 public ArrayConstant(DataConstant[] dVals)
3325 for (int i=0; i < dataVals.Length; i++) {
3326 size += dataVals[i].GetSize();
3330 public int? ExplicitSize { get; set; }
3332 internal sealed override void Write(BinaryWriter bw)
3334 for (int i=0; i < dataVals.Length; i++) {
3335 dataVals[i].Write(bw);
3341 public class ClassType : Constant {
3345 public ClassType(string className)
3348 type = PrimitiveType.ClassType;
3351 public ClassType(Class classDesc)
3354 type = PrimitiveType.ClassType;
3357 internal override void Write(BinaryWriter bw)
3359 if (name == null) name = desc.TypeName();
3367 /**************************************************************************/
3369 /// Descriptor for a custom modifier of a type (modopt or modreq)
3372 public class CustomModifiedType : Type {
3376 PrimitiveTypeRef cmodPrimType;
3379 /// Create a new custom modifier for a type
3381 /// <param name="type">the type to be modified</param>
3382 /// <param name="cmod">the modifier</param>
3383 /// <param name="cmodType">the type reference to be associated with the type</param>
3384 public CustomModifiedType(Type type, CustomModifier cmod, Class cmodType)
3388 this.cmodType = cmodType;
3391 public CustomModifiedType(Type type, CustomModifier cmod, PrimitiveTypeRef cmodType)
3395 this.cmodPrimType = cmodType;
3398 internal sealed override void TypeSig(MemoryStream str)
3400 str.WriteByte(typeIndex);
3402 if (cmodType != null) {
3403 MetaData.CompressNum(cmodType.TypeDefOrRefToken(),str);
3405 MetaData.CompressNum(cmodPrimType.TypeDefOrRefToken(),str);
3413 /**************************************************************************/
3415 /// Base class for Event and Property descriptors
3418 public class Feature : MetaDataElement {
3420 internal enum MethodType : ushort { Setter = 0x01, Getter, Other = 0x04, AddOn = 0x08,
3421 RemoveOn = 0x10, Fire = 0x20 }
3423 private static readonly int INITSIZE = 5;
3424 private static readonly ushort specialName = 0x200;
3425 private static readonly ushort rtSpecialName = 0x400;
3427 protected ClassDef parent;
3428 protected ushort flags = 0;
3429 protected string name;
3430 protected int tide = 0;
3431 protected uint nameIx;
3432 protected MethodSemantics[] methods = new MethodSemantics[INITSIZE];
3434 internal Feature(string name, ClassDef par)
3440 internal void AddMethod(MethodDef meth, MethodType mType)
3442 if (tide >= methods.Length) {
3443 int len = methods.Length;
3444 MethodSemantics[] mTmp = methods;
3445 methods = new MethodSemantics[len * 2];
3446 for (int i=0; i < len; i++) {
3447 methods[i] = mTmp[i];
3450 methods[tide++] = new MethodSemantics(mType,meth,this);
3454 /// Set the specialName attribute for this Event or Property
3456 public void SetSpecialName()
3458 flags |= specialName;
3462 /// Set the RTSpecialName attribute for this Event or Property
3464 public void SetRTSpecialName()
3466 flags |= rtSpecialName;
3471 /**************************************************************************/
3473 /// Descriptor for an event
3475 public class Event : Feature {
3479 internal Event(string name, Type eType, ClassDef parent)
3480 : base(name, parent)
3483 tabIx = MDTable.Event;
3487 /// Add the addon method to this event
3489 /// <param name="addon">the addon method</param>
3490 public void AddAddon(MethodDef addon)
3492 AddMethod(addon,MethodType.AddOn);
3496 /// Add the removeon method to this event
3498 /// <param name="removeOn">the removeon method</param>
3499 public void AddRemoveOn(MethodDef removeOn)
3501 AddMethod(removeOn,MethodType.RemoveOn);
3505 /// Add the fire method to this event
3507 /// <param name="fire">the fire method</param>
3508 public void AddFire(MethodDef fire)
3510 AddMethod(fire,MethodType.Fire);
3514 /// Add another method to this event
3516 /// <param name="other">the method to be added</param>
3517 public void AddOther(MethodDef other)
3519 AddMethod(other,MethodType.Other);
3522 internal sealed override void BuildTables(MetaData md)
3525 nameIx = md.AddToStringsHeap(name);
3526 for (int i=0; i < tide; i++) {
3527 md.AddToTable(MDTable.MethodSemantics,methods[i]);
3532 internal sealed override uint Size(MetaData md)
3534 return 2 + md.StringsIndexSize() + md.CodedIndexSize(CIx.TypeDefOrRef);
3537 internal sealed override void Write(FileImage output)
3539 output.Write(flags);
3540 output.StringsIndex(nameIx);
3541 output.WriteCodedIndex(CIx.TypeDefOrRef,eventType);
3544 internal sealed override uint GetCodedIx(CIx code)
3547 case (CIx.HasCustomAttr) : return 10;
3548 case (CIx.HasSemantics) : return 0;
3555 /**************************************************************************/
3557 /// Descriptor for the Property of a class
3559 public class Property : Feature {
3561 private static readonly byte PropertyTag = 0x8;
3562 private bool instance;
3563 MethodDef getterMeth;
3564 ConstantElem constVal;
3565 uint typeBlobIx = 0;
3570 internal Property(string name, Type retType, Type[] pars, ClassDef parent) : base(name, parent)
3572 returnType = retType;
3574 if (pars != null) numPars = (uint)pars.Length;
3575 tabIx = MDTable.Property;
3579 /// Add a set method to this property
3581 /// <param name="setter">the set method</param>
3582 public void AddSetter(MethodDef setter)
3584 AddMethod(setter,MethodType.Setter);
3588 /// Add a get method to this property
3590 /// <param name="getter">the get method</param>
3591 public void AddGetter(MethodDef getter)
3593 AddMethod(getter,MethodType.Getter);
3594 getterMeth = getter;
3598 /// Add another method to this property
3600 /// <param name="other">the method</param>
3601 public void AddOther(MethodDef other)
3603 AddMethod(other,MethodType.Other);
3607 /// Add an initial value for this property
3609 /// <param name="constVal">the initial value for this property</param>
3610 public void AddInitValue(Constant constVal)
3612 this.constVal = new ConstantElem(this,constVal);
3615 public void SetInstance (bool isInstance)
3617 this.instance = isInstance;
3620 internal sealed override void BuildTables(MetaData md)
3623 nameIx = md.AddToStringsHeap(name);
3624 MemoryStream sig = new MemoryStream();
3625 byte tag = PropertyTag;
3629 MetaData.CompressNum(numPars,sig);
3630 returnType.TypeSig(sig);
3631 for (int i=0; i < numPars; i++) {
3632 parList[i].TypeSig(sig);
3634 typeBlobIx = md.AddToBlobHeap(sig.ToArray());
3635 for (int i=0; i < tide; i++) {
3636 md.AddToTable(MDTable.MethodSemantics,methods[i]);
3638 if (constVal != null) {
3639 md.AddToTable(MDTable.Constant,constVal);
3640 constVal.BuildTables(md);
3645 internal sealed override uint Size(MetaData md)
3647 return 2 + md.StringsIndexSize() + md.BlobIndexSize();
3650 internal sealed override void Write(FileImage output)
3652 output.Write(flags);
3653 output.StringsIndex(nameIx);
3654 output.BlobIndex(typeBlobIx);
3657 internal sealed override uint GetCodedIx(CIx code)
3660 case (CIx.HasCustomAttr) : return 9;
3661 case (CIx.HasConst) : return 2;
3662 case (CIx.HasSemantics) : return 1;
3669 /**************************************************************************/
3671 /// Base class for field/methods (member of a class)
3673 public abstract class Member : MetaDataElement {
3675 protected string name;
3676 protected uint nameIx = 0, sigIx = 0;
3678 internal Member(string memName)
3681 tabIx = MDTable.MemberRef;
3686 /*****************************************************************************/
3688 /// Descriptor for a field of a class
3691 public abstract class Field : Member {
3693 protected static readonly byte FieldSig = 0x6;
3695 protected Type type;
3697 internal Field(string pfName, Type pfType) : base(pfName)
3703 /**************************************************************************/
3705 /// Descriptor for a field defined in a class of THIS assembly/module
3707 public class FieldDef : Field {
3709 //private static readonly uint PInvokeImpl = 0x2000;
3710 private static readonly ushort HasFieldRVA = 0x100;
3711 private static readonly ushort HasDefault = 0x8000;
3714 ConstantElem constVal;
3716 FieldMarshal marshalInfo;
3719 internal FieldDef(string name, Type fType) : base(name,fType)
3721 tabIx = MDTable.Field;
3724 internal FieldDef(FieldAttr attrSet, string name, Type fType) : base(name, fType)
3726 flags = (ushort)attrSet;
3727 tabIx = MDTable.Field;
3731 /// Add an attribute(s) to this field
3733 /// <param name="fa">the attribute(s) to be added</param>
3734 public void AddFieldAttr(FieldAttr fa)
3736 flags |= (ushort)fa;
3740 /// Add a value for this field
3742 /// <param name="val">the value for the field</param>
3743 public void AddValue(Constant val)
3745 constVal = new ConstantElem(this,val);
3746 flags |= HasDefault;
3750 /// Add an initial value for this field (at dataLabel) (.data)
3752 /// <param name="val">the value for the field</param>
3753 /// <param name="repeatVal">the number of repetitions of this value</param>
3754 public void AddDataValue(DataConstant val)
3756 flags |= HasFieldRVA;
3757 rva = new FieldRVA(this,val);
3761 /// Set the offset of the field. Used for sequential or explicit classes.
3764 /// <param name="offs">field offset</param>
3765 public void SetOffset(uint offs)
3767 layout = new FieldLayout(this,offs);
3771 /// Set the marshalling info for a field
3773 /// <param name="mInf"></param>
3774 public void SetMarshalInfo(NativeType marshallType)
3776 flags |= (ushort) FieldAttr.HasFieldMarshal;
3777 marshalInfo = new FieldMarshal(this,marshallType);
3780 internal sealed override void BuildTables(MetaData md)
3783 nameIx = md.AddToStringsHeap(name);
3784 MemoryStream sig = new MemoryStream();
3785 sig.WriteByte(FieldSig);
3787 sigIx = md.AddToBlobHeap(sig.ToArray());
3789 md.AddToTable(MDTable.FieldRVA,rva);
3790 rva.BuildTables(md);
3791 } else if (constVal != null) {
3792 md.AddToTable(MDTable.Constant,constVal);
3793 constVal.BuildTables(md);
3795 if (layout != null) md.AddToTable(MDTable.FieldLayout,layout);
3796 if (marshalInfo != null) {
3797 md.AddToTable(MDTable.FieldMarshal,marshalInfo);
3798 marshalInfo.BuildTables(md);
3803 internal sealed override uint Size(MetaData md)
3805 return 2 + md.StringsIndexSize() + md.BlobIndexSize();
3808 internal sealed override void Write(FileImage output)
3810 output.Write(flags);
3811 output.StringsIndex(nameIx);
3812 output.BlobIndex(sigIx);
3815 internal sealed override uint GetCodedIx(CIx code)
3818 case (CIx.HasConst) : return 0;
3819 case (CIx.HasCustomAttr) : return 1;
3820 case (CIx.HasFieldMarshal) : return 0;
3821 case (CIx.MemberForwarded) : return 0;
3828 /**************************************************************************/
3830 /// Descriptor for a field of a class defined in another assembly/module
3832 public class FieldRef : Field {
3834 MetaDataElement parent;
3836 internal FieldRef(MetaDataElement paren, string name, Type fType) : base(name, fType)
3841 internal sealed override void BuildTables(MetaData md)
3844 nameIx = md.AddToStringsHeap(name);
3845 MemoryStream sig = new MemoryStream();
3846 sig.WriteByte(FieldSig);
3848 sigIx = md.AddToBlobHeap(sig.ToArray());
3852 internal sealed override uint Size(MetaData md)
3854 return md.CodedIndexSize(CIx.MemberRefParent) + md.StringsIndexSize() + md.BlobIndexSize();
3857 internal sealed override void Write(FileImage output)
3859 output.WriteCodedIndex(CIx.MemberRefParent,parent);
3860 output.StringsIndex(nameIx);
3861 output.BlobIndex(sigIx);
3864 internal sealed override uint GetCodedIx(CIx code) { return 6; }
3868 /**************************************************************************/
3870 /// Base class for Method Descriptors
3873 public abstract class Method : Member {
3875 internal Method (string methName) : base (methName)
3878 public abstract void AddCallConv(CallConv cconv);
3879 internal abstract void TypeSig(MemoryStream sig);
3880 internal abstract uint GetSigIx(MetaData md);
3883 /**************************************************************************/
3885 /// Descriptor for a method defined in THIS assembly/module
3889 public class MethodDef : Method {
3891 private static readonly ushort PInvokeImpl = 0x2000;
3892 //private static readonly uint UnmanagedExport = 0x0008;
3893 // private static readonly byte LocalSigByte = 0x7;
3894 uint parIx = 0, textOffset = 0;
3895 private CallConv callConv = CallConv.Default;
3896 private int gen_param_count;
3899 CILInstructions code;
3903 ushort methFlags = 0, implFlags = 0;
3904 int maxStack = 0, numPars = 0;
3905 bool entryPoint = false;
3907 ArrayList varArgSigList;
3908 ImplMap pinvokeImpl;
3911 internal MethodDef (MetaData md, string name, Param ret_param, Param [] pars)
3912 : this (md, 0, 0, name, ret_param, pars)
3916 internal MethodDef (MetaData md, MethAttr mAttrSet, ImplAttr iAttrSet, string name,
3917 Param ret_param, Param [] pars)
3920 methFlags = (ushort)mAttrSet;
3921 implFlags = (ushort)iAttrSet;
3922 this.ret_param = ret_param;
3925 if (parList != null)
3926 numPars = parList.Length;
3927 tabIx = MDTable.Method;
3930 internal Param[] GetPars()
3935 internal override uint GetSigIx(MetaData md)
3937 MemoryStream sig = new MemoryStream();
3939 return md.AddToBlobHeap(sig.ToArray());
3942 public override void AddCallConv(CallConv cconv)
3948 /// Add some attributes to this method descriptor
3950 /// <param name="ma">the attributes to be added</param>
3951 public void AddMethAttribute(MethAttr ma)
3953 methFlags |= (ushort)ma;
3957 /// Add some implementation attributes to this method descriptor
3959 /// <param name="ia">the attributes to be added</param>
3960 public void AddImplAttribute(ImplAttr ia)
3962 implFlags |= (ushort)ia;
3965 public void AddPInvokeInfo(ModuleRef scope, string methName,
3966 PInvokeAttr callAttr) {
3967 pinvokeImpl = new ImplMap((ushort)callAttr,this,methName,scope);
3968 methFlags |= PInvokeImpl;
3972 /// Add a named generic type parameter
3974 public GenericParameter AddGenericParameter (short index, string name)
3976 return AddGenericParameter (index, name, 0);
3980 /// Add a named generic type parameter with attributes
3982 public GenericParameter AddGenericParameter (short index, string name, GenericParamAttributes attr)
3984 GenericParameter gp = new GenericParameter (this, metaData, index, name, attr);
3985 metaData.AddToTable (MDTable.GenericParam, gp);
3991 /// Set the maximum stack height for this method
3993 /// <param name="maxStack">the maximum height of the stack</param>
3994 public void SetMaxStack(int maxStack)
3996 this.maxStack = maxStack;
4000 /// Add local variables to this method
4002 /// <param name="locals">the locals to be added</param>
4003 /// <param name="initLocals">are locals initialised to default values</param>
4004 public void AddLocals(Local[] locals, bool initLocals)
4006 this.locals = locals;
4007 this.initLocals = initLocals;
4010 /* Add Marshal info for return type */
4011 public void AddRetTypeMarshallInfo (NativeType marshallType)
4013 ret_param.AddMarshallInfo (marshallType);
4017 /// Mark this method as having an entry point
4019 public void DeclareEntryPoint()
4025 /// Create a code buffer for this method to add the IL instructions to
4027 /// <returns>a buffer for this method's IL instructions</returns>
4028 public CILInstructions CreateCodeBuffer()
4030 code = new CILInstructions(metaData);
4035 /// Make a method reference descriptor for this method to be used
4036 /// as a callsite signature for this vararg method
4038 /// <param name="optPars">the optional pars for the vararg method call</param>
4039 /// <returns></returns>
4040 public MethodRef MakeVarArgSignature(Type[] optPars)
4042 Type[] pars = new Type[numPars];
4043 MethodRef varArgSig;
4044 for (int i=0; i < numPars; i++) {
4045 pars[i] = parList[i].GetParType();
4047 varArgSig = new MethodRef (this, name, ret_param.GetParType (), pars, true, optPars, 0);
4049 if (varArgSigList == null)
4050 varArgSigList = new ArrayList ();
4051 varArgSigList.Add (varArgSig);
4055 internal sealed override void TypeSig(MemoryStream sig)
4057 sig.WriteByte((byte)callConv);
4058 if ((callConv & CallConv.Generic) == CallConv.Generic)
4059 MetaData.CompressNum ((uint) gen_param_count, sig);
4060 MetaData.CompressNum((uint)numPars,sig);
4062 ret_param.seqNo = 0;
4063 ret_param.TypeSig (sig);
4064 for (ushort i=0; i < numPars; i++) {
4065 parList[i].seqNo = (ushort)(i+1);
4066 parList[i].TypeSig(sig);
4070 internal sealed override void BuildTables(MetaData md)
4073 if (pinvokeImpl != null) {
4074 md.AddToTable(MDTable.ImplMap,pinvokeImpl);
4075 pinvokeImpl.BuildTables(md);
4077 if (entryPoint) md.SetEntryPoint(this);
4079 if (locals != null) {
4080 localSig = new LocalSig(locals);
4081 md.AddToTable(MDTable.StandAloneSig,localSig);
4082 localSig.BuildTables(md);
4083 locToken = localSig.Token();
4086 code.CheckCode(locToken,initLocals,maxStack);
4087 textOffset = md.AddCode(code);
4089 nameIx = md.AddToStringsHeap(name);
4090 sigIx = GetSigIx(md);
4091 parIx = md.TableIndex(MDTable.Param);
4092 if (ret_param.HasMarshalInfo || ret_param.HasCustomAttr) {
4093 md.AddToTable(MDTable.Param, ret_param);
4094 ret_param.BuildTables(md);
4096 for (int i=0; i < numPars; i++) {
4097 md.AddToTable(MDTable.Param,parList[i]);
4098 parList[i].BuildTables(md);
4100 if (varArgSigList != null) {
4101 foreach (MethodRef varArgSig in varArgSigList) {
4102 md.AddToTable(MDTable.MemberRef,varArgSig);
4103 varArgSig.BuildTables(md);
4106 // Console.WriteLine("method has " + numPars + " parameters");
4110 internal sealed override uint Size(MetaData md)
4112 return 8 + md.StringsIndexSize() + md.BlobIndexSize() + md.TableIndexSize(MDTable.Param);
4115 internal sealed override void Write(FileImage output)
4117 if (ZeroRva ()) output.Write(0);
4118 else output.WriteCodeRVA(textOffset);
4119 output.Write(implFlags);
4120 output.Write(methFlags);
4121 output.StringsIndex(nameIx);
4122 output.BlobIndex(sigIx);
4123 output.WriteIndex(MDTable.Param,parIx);
4126 internal bool ZeroRva ()
4128 return (((methFlags & (ushort)MethAttr.Abstract) != 0) ||
4129 ((implFlags & (ushort)ImplAttr.Runtime) != 0) ||
4130 ((implFlags & (ushort)ImplAttr.InternalCall) != 0) ||
4131 (pinvokeImpl != null)); // TODO: Not entirely true but works for now
4134 internal sealed override uint GetCodedIx(CIx code)
4137 case (CIx.HasCustomAttr) : return 0;
4138 case (CIx.HasDeclSecurity) : return 1;
4139 case (CIx.MemberRefParent) : return 3;
4140 case (CIx.MethodDefOrRef) : return 0;
4141 case (CIx.MemberForwarded) : return 1;
4142 case (CIx.CustomAttributeType) : return 2;
4143 case (CIx.TypeOrMethodDef) : return 1;
4149 /**************************************************************************/
4151 /// Descriptor for a method defined in another assembly/module
4153 public class MethodRef : Method {
4155 private static readonly byte Sentinel = 0x41;
4156 Type[] parList, optParList;
4157 MetaDataElement parent;
4158 uint numPars = 0, numOptPars = 0;
4159 CallConv callConv = CallConv.Default;
4161 int gen_param_count;
4163 internal MethodRef(MetaDataElement paren, string name, Type retType,
4164 Type[] pars, bool varArgMeth, Type[] optPars, int gen_param_count) : base(name)
4168 this.retType = retType;
4169 if (parList != null) numPars = (uint)parList.Length;
4171 optParList = optPars;
4172 if (optParList != null) numOptPars = (uint)optParList.Length;
4173 callConv = CallConv.Vararg;
4175 this.gen_param_count = gen_param_count;
4178 internal override uint GetSigIx(MetaData md)
4180 MemoryStream sig = new MemoryStream();
4182 return md.AddToBlobHeap(sig.ToArray());
4185 public override void AddCallConv(CallConv cconv)
4190 internal sealed override void TypeSig(MemoryStream sig)
4192 sig.WriteByte((byte)callConv);
4193 if ((callConv & CallConv.Generic) == CallConv.Generic)
4194 MetaData.CompressNum ((uint) gen_param_count, sig);
4195 MetaData.CompressNum(numPars+numOptPars,sig);
4196 retType.TypeSig(sig);
4197 for (int i=0; i < numPars; i++) {
4198 parList[i].TypeSig(sig);
4200 if (numOptPars > 0) {
4201 sig.WriteByte(Sentinel);
4202 for (int i=0; i < numOptPars; i++) {
4203 optParList[i].TypeSig(sig);
4208 internal sealed override void BuildTables(MetaData md)
4211 nameIx = md.AddToStringsHeap(name);
4212 sigIx = GetSigIx(md);
4216 internal sealed override uint Size(MetaData md)
4218 return md.CodedIndexSize(CIx.MemberRefParent) + md.StringsIndexSize() + md.BlobIndexSize();
4221 internal sealed override void Write(FileImage output)
4223 output.WriteCodedIndex(CIx.MemberRefParent,parent);
4224 output.StringsIndex(nameIx);
4225 output.BlobIndex(sigIx);
4228 internal sealed override uint GetCodedIx(CIx code)
4231 case (CIx.HasCustomAttr) : return 6;
4232 case (CIx.MethodDefOrRef) : return 1;
4233 case (CIx.CustomAttributeType) : return 3;
4241 /**************************************************************************/
4243 /// Descriptors for native types used for marshalling
4245 public class NativeType {
4246 public static readonly NativeType Void = new NativeType(0x01);
4247 public static readonly NativeType Boolean = new NativeType(0x02);
4248 public static readonly NativeType Int8 = new NativeType(0x03);
4249 public static readonly NativeType UInt8 = new NativeType(0x04);
4250 public static readonly NativeType Int16 = new NativeType(0x05);
4251 public static readonly NativeType UInt16 = new NativeType(0x06);
4252 public static readonly NativeType Int32 = new NativeType(0x07);
4253 public static readonly NativeType UInt32 = new NativeType(0x08);
4254 public static readonly NativeType Int64 = new NativeType(0x09);
4255 public static readonly NativeType UInt64 = new NativeType(0x0A);
4256 public static readonly NativeType Float32 = new NativeType(0x0B);
4257 public static readonly NativeType Float64 = new NativeType(0x0C);
4258 public static readonly NativeType Currency = new NativeType(0x0F);
4259 public static readonly NativeType BStr = new NativeType(0x13);
4260 public static readonly NativeType LPStr = new NativeType(0x14);
4261 public static readonly NativeType LPWStr = new NativeType(0x15);
4262 public static readonly NativeType LPTStr = new NativeType(0x16);
4263 public static readonly NativeType FixedSysString = new NativeType(0x17);
4264 public static readonly NativeType IUnknown = new NativeType(0x19);
4265 public static readonly NativeType IDispatch = new NativeType(0x1A);
4266 public static readonly NativeType Struct = new NativeType(0x1B);
4267 public static readonly NativeType Interface = new NativeType(0x1C);
4268 public static readonly NativeType Int = new NativeType(0x1F);
4269 public static readonly NativeType UInt = new NativeType(0x20);
4270 public static readonly NativeType ByValStr = new NativeType(0x22);
4271 public static readonly NativeType AnsiBStr = new NativeType(0x23);
4272 public static readonly NativeType TBstr = new NativeType(0x24);
4273 public static readonly NativeType VariantBool = new NativeType(0x25);
4274 public static readonly NativeType FuncPtr = new NativeType(0x26);
4275 public static readonly NativeType AsAny = new NativeType(0x28);
4276 public static readonly NativeType LPStruct = new NativeType(0x2b);
4277 public static readonly NativeType Error = new NativeType(0x2d);
4279 protected byte typeIndex;
4281 internal NativeType(byte tyIx) { typeIndex = tyIx; }
4282 internal byte GetTypeIndex() { return typeIndex; }
4284 internal virtual byte[] ToBlob()
4286 byte[] bytes = new byte[1];
4287 bytes[0] = GetTypeIndex();
4293 public class FixedSysString : NativeType {
4297 public FixedSysString (uint size) : base (NativeType.FixedSysString.GetTypeIndex ())
4302 internal override byte [] ToBlob ()
4304 MemoryStream str = new MemoryStream ();
4305 str.WriteByte (GetTypeIndex ());
4306 MetaData.CompressNum (size, str);
4307 return str.ToArray ();
4312 public class NativeArray : NativeType {
4314 NativeType elemType;
4315 int numElem = -1, parNum = -1, elemMult = -1;
4317 public NativeArray(NativeType elemType) : this (elemType, -1, -1, -1)
4319 this.elemType = elemType;
4322 /* public NativeArray(NativeType elemType, int len) : base(0x2A) {
4323 this.elemType = elemType;
4328 public NativeArray(NativeType elemType, int numElem, int parNumForLen, int elemMult) : base(0x2A)
4330 this.elemType = elemType;
4331 this.numElem = numElem;
4332 parNum = parNumForLen;
4333 this.elemMult = elemMult;
4336 public NativeArray(NativeType elemType, int numElem, int parNumForLen)
4337 : this (elemType, numElem, parNumForLen, -1)
4341 internal override byte[] ToBlob()
4343 MemoryStream str = new MemoryStream();
4344 str.WriteByte(GetTypeIndex());
4345 if (elemType == null) str.WriteByte(0x50); // no info (MAX)
4346 else str.WriteByte(elemType.GetTypeIndex());
4348 /* see : mono/metadata/metadata.c:mono_metadata_parse_marshal_spec
4349 * LAMESPEC: Older spec versions say elemMult comes before
4350 * len. Newer spec versions don't talk about elemMult at
4351 * all, but csc still emits it, and it is used to distinguish
4352 * between parNum being 0, and parNum being omitted.
4357 return str.ToArray ();
4359 MetaData.CompressNum((uint) parNum,str);
4360 if (numElem != -1) {
4361 MetaData.CompressNum ((uint) numElem, str);
4363 // <native_type> [ int32 ]
4364 MetaData.CompressNum((uint) elemMult,str);
4365 //else <native_type> [ int32 + int32 ]
4366 } else if (elemMult != -1) {
4367 // When can this occur ?
4368 MetaData.CompressNum (0, str);
4369 MetaData.CompressNum((uint) elemMult,str);
4371 //else <native_type> [ + int32 ]
4373 return str.ToArray();
4378 public class SafeArray : NativeType {
4380 SafeArrayType elemType;
4383 public SafeArray() : base(0x1D)
4387 public SafeArray(SafeArrayType elemType) : base(0x1D)
4389 this.elemType = elemType;
4393 internal override byte[] ToBlob()
4395 byte[] bytes = new byte[hasElemType ? 2 : 1];
4396 bytes[0] = GetTypeIndex();
4398 bytes[1] = (byte)elemType;
4404 public class FixedArray : NativeType {
4408 //public FixedArray(NativeType elemType, int numElems) : base(0x1E) {
4409 public FixedArray(int numElems) : base(0x1E)
4411 //this.elemType = elemType;
4412 numElem = (uint)numElems;
4415 internal override byte[] ToBlob()
4417 MemoryStream str = new MemoryStream();
4418 str.WriteByte(GetTypeIndex());
4419 MetaData.CompressNum(numElem,str);
4421 fixed array [5] lpstr [2]
4422 This format is not supported by ilasm 1.1.4322.2032,
4423 but is supported by 2.0.5125..
4424 ilasm 1.1 only supports "fixed array [5]"
4425 if (elemType == null) str.WriteByte(0x50); // no info (MAX)
4426 else str.WriteByte(elemType.GetTypeIndex());*/
4428 return str.ToArray();
4433 public class CustomMarshaller : NativeType {
4436 string marshallerName;
4439 public CustomMarshaller(string typeNameOrGUID, string marshallerName,
4440 string optCookie) : base(0x2C)
4442 typeName = typeNameOrGUID;
4443 this.marshallerName = marshallerName;
4447 public CustomMarshaller(string marshallerName, string optCookie)
4448 :this (null, marshallerName, optCookie)
4452 internal override byte[] ToBlob()
4454 MemoryStream str = new MemoryStream();
4455 BinaryWriter bw = new BinaryWriter(str,new UTF8Encoding());
4456 bw.Write(GetTypeIndex());
4457 //Native type name & unmanaged type - unused
4458 //See mono/metadata/metadata.c : mono_metadata_parse_marshal_spec
4459 bw.Write ((byte) 0); // Native Type name, unused
4460 bw.Write ((byte) 0); // Unmanaged type, unused
4461 if (marshallerName != null) {
4462 MetaData.CompressNum ((uint)marshallerName.Length, str);
4463 bw.Write(marshallerName.ToCharArray());
4465 bw.Write ((byte) 0);
4467 if (cookie != null) {
4468 MetaData.CompressNum ((uint)cookie.Length, str);
4469 bw.Write(cookie.ToCharArray());
4471 bw.Write ((byte) 0);
4474 return str.ToArray();
4478 /**************************************************************************/
4480 /// Descriptor for the Primitive types defined in IL
4482 public class PrimitiveType : Type {
4484 private string name;
4485 private int systemTypeIndex;
4486 public static int NumSystemTypes = 18;
4488 public static readonly PrimitiveType Void = new PrimitiveType(0x01,"Void",0);
4489 public static readonly PrimitiveType Boolean = new PrimitiveType(0x02,"Boolean",1);
4490 public static readonly PrimitiveType Char = new PrimitiveType(0x03,"Char",2);
4491 public static readonly PrimitiveType Int8 = new PrimitiveType(0x04,"SByte",3);
4492 public static readonly PrimitiveType UInt8 = new PrimitiveType(0x05,"Byte",4);
4493 public static readonly PrimitiveType Int16 = new PrimitiveType(0x06,"Int16",5);
4494 public static readonly PrimitiveType UInt16 = new PrimitiveType(0x07,"UInt16",6);
4495 public static readonly PrimitiveType Int32 = new PrimitiveType(0x08,"Int32",7);
4496 public static readonly PrimitiveType UInt32 = new PrimitiveType(0x09,"UInt32",8);
4497 public static readonly PrimitiveType Int64 = new PrimitiveType(0x0A,"Int64",9);
4498 public static readonly PrimitiveType UInt64 = new PrimitiveType(0x0B,"UInt64",10);
4499 public static readonly PrimitiveType Float32 = new PrimitiveType(0x0C,"Single",11);
4500 public static readonly PrimitiveType Float64 = new PrimitiveType(0x0D,"Double",12);
4501 public static readonly PrimitiveType String = new PrimitiveType(0x0E,"String",13);
4502 internal static readonly PrimitiveType Class = new PrimitiveType(0x12);
4503 internal static readonly PrimitiveType Var = new PrimitiveType(0x13);
4504 internal static readonly PrimitiveType GenericInst = new PrimitiveType(0x15);
4505 public static readonly PrimitiveType TypedRef = new PrimitiveType(0x16,"TypedReference",14);
4506 public static readonly PrimitiveType IntPtr = new PrimitiveType(0x18,"IntPtr",15);
4507 public static readonly PrimitiveType UIntPtr = new PrimitiveType(0x19,"UIntPtr",16);
4508 public static readonly PrimitiveType Object = new PrimitiveType(0x1C,"Object",17);
4509 internal static readonly PrimitiveType ClassType = new PrimitiveType(0x50);
4510 internal static readonly PrimitiveType SZArray = new PrimitiveType(0x1D);
4511 internal static readonly PrimitiveType MVar = new PrimitiveType(0x1E);
4512 internal static readonly PrimitiveType ValueType = new PrimitiveType(0x11, "ValueType", 18);
4513 public static readonly PrimitiveType NativeInt = IntPtr;
4514 public static readonly PrimitiveType NativeUInt = UIntPtr;
4516 internal PrimitiveType(byte typeIx) : base(typeIx) { }
4518 internal PrimitiveType(byte typeIx, string name, int STIx) : base(typeIx)
4521 this.systemTypeIndex = STIx;
4524 internal string GetName() { return name; }
4526 internal int GetSystemTypeIx() { return systemTypeIndex; }
4528 internal sealed override void TypeSig(MemoryStream str)
4530 str.WriteByte(typeIndex);
4533 internal override MetaDataElement GetTypeSpec(MetaData md)
4535 TypeSpec tS = md.GetPrimitiveTypeSpec(systemTypeIndex);
4537 tS = new TypeSpec(this,md);
4538 md.SetPrimitiveTypeSpec(systemTypeIndex,tS);
4539 md.AddToTable(MDTable.TypeSpec,tS);
4546 public class PrimitiveTypeRef : Type
4551 internal PrimitiveTypeRef(PrimitiveType type, MetaData md)
4558 internal uint TypeDefOrRefToken()
4560 uint cIx = type.GetTypeSpec (metaData).Row;
4561 cIx = (cIx << 2) | 0x2;
4566 /**************************************************************************/
4568 /// Descriptor for an pointer (type * or type &)
4570 public abstract class PtrType : Type {
4574 internal PtrType(Type bType, byte typeIx) : base(typeIx)
4577 tabIx = MDTable.TypeSpec;
4580 internal sealed override void TypeSig(MemoryStream str)
4582 str.WriteByte(typeIndex);
4583 baseType.TypeSig(str);
4587 /**************************************************************************/
4589 /// Descriptor for a managed pointer (type & or byref)
4592 public class ManagedPointer : PtrType {
4595 /// Create new managed pointer to baseType
4597 /// <param name="bType">the base type of the pointer</param>
4598 public ManagedPointer(Type baseType) : base(baseType,0x10) { }
4601 /**************************************************************************/
4603 /// Descriptor for an unmanaged pointer (type *)
4605 public class UnmanagedPointer : PtrType {
4608 /// Create a new unmanaged pointer to baseType
4610 /// <param name="baseType">the base type of the pointer</param>
4611 public UnmanagedPointer(Type baseType) : base(baseType, 0x0F) { }
4615 /**************************************************************************/
4617 public interface IExternRef {
4618 ClassRef AddClass(string nsName, string name);
4619 ClassRef AddValueClass(string nsName, string name);
4623 /// A reference to an external assembly (.assembly extern)
4625 public class AssemblyRef : ResolutionScope, IExternRef {
4627 private ushort major, minor, build, revision;
4628 uint flags, keyIx, hashIx, cultIx;
4629 bool hasVersion = false, isKeyToken = false;
4633 internal AssemblyRef(MetaData md, string name) : base(name,md)
4635 tabIx = MDTable.AssemblyRef;
4638 public void AddAssemblyAttr (AssemAttr aa)
4644 /// Add version information about this external assembly
4646 /// <param name="majVer">Major Version</param>
4647 /// <param name="minVer">Minor Version</param>
4648 /// <param name="bldNo">Build Number</param>
4649 /// <param name="revNo">Revision Number</param>
4650 public void AddVersionInfo(int majVer, int minVer, int bldNo, int revNo)
4652 major = (ushort)majVer;
4653 minor = (ushort)minVer;
4654 build = (ushort)bldNo;
4655 revision = (ushort)revNo;
4660 /// Add the hash value for this external assembly
4662 /// <param name="hash">bytes of the hash value</param>
4663 public void AddHash(byte[] hash)
4665 hashIx = metaData.AddToBlobHeap(hash);
4669 /// Set the culture for this external assembly
4671 /// <param name="cult">the culture string</param>
4672 public void AddCulture(string cult)
4674 cultIx = metaData.AddToStringsHeap(cult);
4679 /// Add the full public key for this external assembly
4681 /// <param name="key">bytes of the public key</param>
4682 public void AddKey(byte[] key)
4684 flags |= 0x0001; // full public key
4686 keyIx = metaData.AddToBlobHeap(key);
4690 /// Add the public key token (low 8 bytes of the public key)
4692 /// <param name="key">low 8 bytes of public key</param>
4693 public void AddKeyToken(byte[] key)
4695 keyIx = metaData.AddToBlobHeap(key);
4701 /// Add a class to this external assembly
4703 /// <param name="nsName">name space name</param>
4704 /// <param name="name">class name</param>
4705 /// <returns></returns>
4706 public virtual ClassRef AddClass(string nsName, string name)
4708 ClassRef aClass = new ClassRef(nsName,name,metaData);
4709 metaData.AddToTable(MDTable.TypeRef,aClass);
4710 aClass.SetParent(this);
4715 /// Add a value class to this external assembly
4717 /// <param name="nsName">name space name</param>
4718 /// <param name="name">class name</param>
4719 /// <returns></returns>
4720 public virtual ClassRef AddValueClass(string nsName, string name)
4722 ClassRef aClass = new ClassRef(nsName,name,metaData);
4723 metaData.AddToTable(MDTable.TypeRef,aClass);
4724 aClass.SetParent(this);
4725 aClass.MakeValueClass(ValueClass.ValueType);
4729 internal string TypeName()
4731 string result = name;
4733 result = result + ", Version=" + major + "." + minor + "." +
4734 build + "." + revision;
4735 if (keyBytes != null) {
4736 string tokenStr = "=";
4737 if (isKeyToken) tokenStr = "Token=";
4738 result = result + ", PublicKey" + tokenStr;
4739 for (int i=0; i < keyBytes.Length; i++) {
4740 result = result + Hex.Byte(keyBytes[i]);
4743 if (culture != null)
4744 result = result + ", Culture=" + culture;
4748 internal sealed override uint Size(MetaData md)
4750 return 12 + 2 * md.StringsIndexSize() + 2 * md.BlobIndexSize();
4753 internal sealed override void Write(FileImage output)
4755 output.Write(major);
4756 output.Write(minor);
4757 output.Write(build);
4758 output.Write(revision);
4759 output.Write(flags);
4760 output.BlobIndex(keyIx);
4761 output.StringsIndex(nameIx);
4762 output.StringsIndex(cultIx);
4763 output.BlobIndex(hashIx);
4766 internal sealed override uint GetCodedIx(CIx code)
4769 case (CIx.ResolutionScope) : return 2;
4770 case (CIx.HasCustomAttr) : return 15;
4771 case (CIx.Implementation) : return 1;
4778 /**************************************************************************/
4780 /// Descriptor for a class defined in System (mscorlib)
4782 internal class SystemClass : ClassRef {
4784 PrimitiveType elemType;
4786 internal SystemClass(PrimitiveType eType, AssemblyRef paren, MetaData md)
4787 : base("System",eType.GetName(),md) {
4792 internal override sealed MetaDataElement GetTypeSpec(MetaData md)
4794 if (typeSpec == null) typeSpec = (TypeSpec)elemType.GetTypeSpec(md);
4799 internal sealed override void TypeSig(MemoryStream str)
4801 str.WriteByte(elemType.GetTypeIndex());
4806 /**************************************************************************/
4808 /// The assembly for mscorlib.
4810 public sealed class MSCorLib : AssemblyRef {
4812 private static readonly int valueTypeIx = 18;
4813 private readonly string systemName = "System";
4814 private Class[] systemClasses = new Class[valueTypeIx+2];
4815 private PrimitiveType[] systemTypes = new PrimitiveType[valueTypeIx];
4817 private static int[] specialNames = {
4818 PrimitiveType.Void.GetName().GetHashCode(),
4819 PrimitiveType.Boolean.GetName().GetHashCode(),
4820 PrimitiveType.Char.GetName().GetHashCode(),
4821 PrimitiveType.Int8.GetName().GetHashCode(),
4822 PrimitiveType.UInt8.GetName().GetHashCode(),
4823 PrimitiveType.Int16.GetName().GetHashCode(),
4824 PrimitiveType.UInt16.GetName().GetHashCode(),
4825 PrimitiveType.Int32.GetName().GetHashCode(),
4826 PrimitiveType.UInt32.GetName().GetHashCode(),
4827 PrimitiveType.Int64.GetName().GetHashCode(),
4828 PrimitiveType.UInt64.GetName().GetHashCode(),
4829 PrimitiveType.Float32.GetName().GetHashCode(),
4830 PrimitiveType.Float64.GetName().GetHashCode(),
4831 PrimitiveType.String.GetName().GetHashCode(),
4832 PrimitiveType.TypedRef.GetName().GetHashCode(),
4833 PrimitiveType.IntPtr.GetName().GetHashCode(),
4834 PrimitiveType.UIntPtr.GetName().GetHashCode(),
4835 PrimitiveType.Object.GetName().GetHashCode(),
4836 PrimitiveType.ValueType.GetName ().GetHashCode(),
4837 "Enum".GetHashCode()
4840 internal MSCorLib(MetaData md) : base(md,"mscorlib")
4842 if (!PEFile.IsMSCorlib)
4843 md.AddToTable(MDTable.AssemblyRef,this);
4844 systemTypes[PrimitiveType.Void.GetSystemTypeIx()] = PrimitiveType.Void;
4845 systemTypes[PrimitiveType.Boolean.GetSystemTypeIx()] = PrimitiveType.Boolean;
4846 systemTypes[PrimitiveType.Char.GetSystemTypeIx()] = PrimitiveType.Char;
4847 systemTypes[PrimitiveType.Int8.GetSystemTypeIx()] = PrimitiveType.Int8;
4848 systemTypes[PrimitiveType.UInt8.GetSystemTypeIx()] = PrimitiveType.UInt8;
4849 systemTypes[PrimitiveType.Int16.GetSystemTypeIx()] = PrimitiveType.Int16;
4850 systemTypes[PrimitiveType.UInt16.GetSystemTypeIx()] = PrimitiveType.UInt16;
4851 systemTypes[PrimitiveType.Int32.GetSystemTypeIx()] = PrimitiveType.Int32;
4852 systemTypes[PrimitiveType.UInt32.GetSystemTypeIx()] = PrimitiveType.UInt32;
4853 systemTypes[PrimitiveType.Int64.GetSystemTypeIx()] = PrimitiveType.Int64;
4854 systemTypes[PrimitiveType.UInt64.GetSystemTypeIx()] = PrimitiveType.UInt64;
4855 systemTypes[PrimitiveType.Float32.GetSystemTypeIx()] = PrimitiveType.Float32;
4856 systemTypes[PrimitiveType.Float64.GetSystemTypeIx()] = PrimitiveType.Float64;
4857 systemTypes[PrimitiveType.IntPtr.GetSystemTypeIx()] = PrimitiveType.IntPtr;
4858 systemTypes[PrimitiveType.UIntPtr.GetSystemTypeIx()] = PrimitiveType.UIntPtr;
4859 systemTypes[PrimitiveType.String.GetSystemTypeIx()] = PrimitiveType.String;
4860 systemTypes[PrimitiveType.Object.GetSystemTypeIx()] = PrimitiveType.Object;
4861 systemTypes[PrimitiveType.TypedRef.GetSystemTypeIx()] = PrimitiveType.TypedRef;
4865 /// Add a class to the mscorlib assembly
4867 /// <param name="nsName">name space name</param>
4868 /// <param name="name">class name</param>
4869 /// <returns></returns>
4870 public override ClassRef AddClass(string nsName, string name)
4872 /* This gets called by !mscorlib, for adding references INTO mscorlib, so
4873 it should be returning ClassRef ..*/
4874 Class aClass = GetSpecialClass(nsName,name);
4875 if (aClass == null) {
4876 aClass = new ClassRef(nsName,name,metaData);
4877 metaData.AddToTable(MDTable.TypeRef,aClass);
4878 if (aClass is ClassRef)
4879 ((ClassRef) aClass).SetParent(this);
4881 //FIXME: Check for !ClassRef here?
4882 return (ClassRef) aClass;
4885 private Class GetSpecialClass(string nsName,string name)
4887 if (nsName.CompareTo(systemName) != 0) return null;
4888 int hash = name.GetHashCode();
4889 for (int i=0; i < specialNames.Length; i++) {
4890 if (hash != specialNames[i])
4892 if (systemClasses[i] == null) {
4893 if (i < valueTypeIx) {
4894 systemClasses[i] = new SystemClass(systemTypes[i],this,metaData);
4895 if ((systemTypes[i] != PrimitiveType.Object) &&
4896 (systemTypes[i] != PrimitiveType.String)) {
4897 systemClasses[i].MakeValueClass(ValueClass.ValueType);
4900 systemClasses[i] = new ClassRef(nsName,name,metaData);
4901 ((ClassRef) systemClasses[i]).SetParent(this);
4902 if (!ClassDef.IsValueType (nsName, name) && !ClassDef.IsEnum (nsName, name))
4903 systemClasses[i].MakeValueClass(ValueClass.ValueType);
4905 metaData.AddToTable(MDTable.TypeRef,systemClasses[i]);
4907 return systemClasses[i];
4912 internal void SetSpecialSystemClass (string nsName, string name, Class aClass)
4914 if (nsName != systemName) return;
4915 int hash = name.GetHashCode ();
4916 for (int i = 0; i < specialNames.Length; i++) {
4917 if (hash != specialNames [i])
4919 if (systemClasses [i] == null) {
4920 systemClasses [i] = aClass;
4925 internal Class GetSpecialSystemClass(PrimitiveType pType)
4927 int ix = pType.GetSystemTypeIx();
4928 if (systemClasses[ix] == null && !PEFile.IsMSCorlib) {
4929 systemClasses[ix] = new SystemClass(pType,this,metaData);
4930 metaData.AddToTable(MDTable.TypeRef,systemClasses[ix]);
4932 return systemClasses[ix];
4935 private ClassRef GetValueClass(string name, int hash)
4937 /* Called by MSCorLib.AddValueClass, which is called by
4938 !mscorlib, for adding ref to value class INTO mscorlib,
4939 so this should be classref */
4940 int ix = valueTypeIx;
4941 if (hash != specialNames[valueTypeIx]) ix++;
4942 if (systemClasses[ix] == null) {
4943 systemClasses[ix] = new ClassRef(systemName,name,metaData);
4944 ((ClassRef) systemClasses[ix]).SetParent(this);
4945 ((ClassRef) systemClasses[ix]).MakeValueClass(ValueClass.ValueType);
4946 metaData.AddToTable(MDTable.TypeRef,systemClasses[ix]);
4948 return (ClassRef) systemClasses[ix];
4951 internal Class ValueType()
4953 if (systemClasses[valueTypeIx] == null && !PEFile.IsMSCorlib) {
4954 ClassRef valType = new ClassRef("System","ValueType",metaData);
4955 valType.SetParent(this);
4956 valType.MakeValueClass(ValueClass.ValueType);
4957 metaData.AddToTable(MDTable.TypeRef,valType);
4958 systemClasses[valueTypeIx] = valType;
4960 return systemClasses[valueTypeIx];
4963 internal Class EnumType()
4965 /* Called by both mscorlib & !mscorlib, so can be
4966 either ClassRef or ClassDef */
4967 //systemClasses [ valueTypeIx + 1] -> System.Enum
4968 if (systemClasses[valueTypeIx + 1] == null && !PEFile.IsMSCorlib) {
4969 ClassRef valType = new ClassRef("System","Enum",metaData);
4970 valType.SetParent(this);
4971 valType.MakeValueClass(ValueClass.Enum);
4972 metaData.AddToTable(MDTable.TypeRef,valType);
4973 systemClasses[valueTypeIx + 1] = valType;
4975 return systemClasses[valueTypeIx + 1];
4979 /// Add a value class to this external assembly
4981 /// <param name="nsName">name space name</param>
4982 /// <param name="name">class name</param>
4983 /// <returns></returns>
4984 public override ClassRef AddValueClass(string nsName, string name)
4986 if (nsName.CompareTo(systemName) == 0) {
4987 int hash = name.GetHashCode();
4988 if ((hash == specialNames[valueTypeIx]) ||
4989 (hash == specialNames[valueTypeIx+1])) {
4990 return GetValueClass(name,hash);
4993 ClassRef aClass = new ClassRef(nsName,name,metaData);
4994 metaData.AddToTable(MDTable.TypeRef,aClass);
4995 aClass.SetParent(this);
4996 aClass.MakeValueClass(ValueClass.ValueType);
5002 /**************************************************************************/
5005 /// Root (20 bytes + UTF-8 Version String + quad align padding)
5006 /// StreamHeaders (8 bytes + null terminated name string + quad align padding)
5008 /// #~ (always present - holds metadata tables)
5009 /// #Strings (always present - holds identifier strings)
5010 /// #US (Userstring heap)
5011 /// #Blob (signature blobs)
5012 /// #GUID (guids for assemblies or Modules)
5014 public class MetaData {
5016 internal static readonly int[] CIxShiftMap = {2,2,5,1,2,3,1,1,1,2,3,2,1};
5017 private static readonly byte StringsHeapMask = 0x1;
5018 private static readonly byte GUIDHeapMask = 0x2;
5019 private static readonly byte BlobHeapMask = 0x4;
5020 private static readonly uint MetaDataSignature = 0x424A5342;
5021 private static readonly uint maxSmlIxSize = 0xFFFF;
5022 private static readonly uint max1BitSmlIx = 0x7FFF;
5023 private static readonly uint max2BitSmlIx = 0x3FFF;
5024 private static readonly uint max3BitSmlIx = 0x1FFF;
5025 private static readonly uint max5BitSmlIx = 0x7FF;
5026 // NOTE: version and stream name strings MUST always be quad padded
5027 private static readonly string version = "v4.0.30319\0\0";
5028 private static readonly char[] tildeName = {'#','~','\0','\0'};
5029 private static readonly char[] stringsName = {'#','S','t','r','i','n','g','s','\0','\0','\0','\0'};
5030 private static readonly char[] usName = {'#','U','S','\0'};
5031 private static readonly char[] guidName = {'#','G','U','I','D','\0','\0','\0'};
5032 private static readonly char[] blobName = {'#','B','l','o','b','\0','\0','\0'};
5033 private static readonly uint MetaDataHeaderSize = 20 + (uint)version.Length;
5034 private static readonly uint TildeHeaderSize = 24;
5035 private static readonly uint StreamHeaderSize = 8;
5036 private static readonly uint numMetaDataTables = (int)MDTable.GenericParamConstraint + 1;
5038 MetaDataStream strings, us, guid, blob;
5040 MetaDataStream[] streams = new MetaDataStream[5];
5041 uint numStreams = 5;
5042 uint tildeTide = 0, tildePadding = 0, tildeStart = 0;
5043 uint numTables = 0, resourcesSize = 0;
5044 ArrayList[] metaDataTables = new ArrayList[numMetaDataTables];
5045 ArrayList byteCodes = new ArrayList();
5046 uint codeSize = 0, codeStart, byteCodePadding = 0, metaDataSize = 0;
5047 ulong valid = 0, /*sorted = 0x000002003301FA00;*/ sorted = 0;
5048 bool[] largeIx = new bool[numMetaDataTables];
5049 bool[] lgeCIx = new bool[(int)CIx.MaxCIx];
5050 bool largeStrings = false, largeUS = false, largeGUID = false, largeBlob = false;
5051 private FileImage file;
5052 private byte heapSizes = 0;
5053 MetaDataElement entryPoint;
5054 BinaryWriter output;
5055 public MSCorLib mscorlib;
5056 private TypeSpec[] systemTypeSpecs = new TypeSpec[PrimitiveType.NumSystemTypes];
5058 private ArrayList cattr_list;
5059 private ArrayList declsec_list;
5060 ArrayList resources;
5062 internal MetaData(FileImage file)
5064 // tilde = new MetaDataStream(tildeName,false,0);
5066 strings = new MetaDataStream(stringsName,new UTF8Encoding(),true);
5067 us = new MetaDataStream(usName,new UnicodeEncoding(),true);
5068 guid = new MetaDataStream(guidName,false);
5069 blob = new MetaDataStream(blobName,true);
5070 streams[1] = strings;
5074 for (int i=0; i < numMetaDataTables; i++) {
5077 for (int i=0; i < lgeCIx.Length; i++) {
5080 mscorlib = new MSCorLib(this);
5083 internal TypeSpec GetPrimitiveTypeSpec(int ix)
5085 return systemTypeSpecs[ix];
5088 internal void SetPrimitiveTypeSpec(int ix, TypeSpec typeSpec)
5090 systemTypeSpecs[ix] = typeSpec;
5093 internal uint Size()
5095 return metaDataSize;
5098 private void CalcHeapSizes ()
5100 if (strings.LargeIx()) {
5101 largeStrings = true;
5102 heapSizes |= StringsHeapMask;
5104 if (guid.LargeIx()) {
5106 heapSizes |= GUIDHeapMask;
5108 if (blob.LargeIx()) {
5110 heapSizes |= BlobHeapMask;
5113 largeUS = us.LargeIx();
5116 internal void StreamSize(byte mask)
5121 internal uint AddToUSHeap(string str)
5123 if (str == null) return 0;
5124 return us.Add(str,true);
5127 internal uint AddToUSHeap(byte[] str)
5129 if (str == null) return 0;
5130 return us.Add (str, true);
5133 internal uint AddToStringsHeap(string str)
5135 if ((str == null) || (str.CompareTo("") == 0)) return 0;
5136 return strings.Add(str,false);
5139 internal uint AddToGUIDHeap(Guid guidNum)
5141 return guid.Add(guidNum, false);
5144 internal uint AddToBlobHeap(byte[] blobBytes)
5146 if (blobBytes == null) return 0;
5147 return blob.Add(blobBytes, true);
5150 internal uint AddToBlobHeap(byte val)
5152 return blob.Add(val, true);
5155 internal uint AddToBlobHeap(sbyte val)
5157 return blob.Add(val, true);
5160 internal uint AddToBlobHeap(ushort val)
5162 return blob.Add(val, true);
5165 internal uint AddToBlobHeap(short val)
5167 return blob.Add(val, true);
5170 internal uint AddToBlobHeap(uint val)
5172 return blob.Add(val, true);
5175 internal uint AddToBlobHeap(int val)
5177 return blob.Add(val, true);
5180 internal uint AddToBlobHeap(ulong val)
5182 return blob.Add(val, true);
5185 internal uint AddToBlobHeap(long val)
5187 return blob.Add(val, true);
5190 internal uint AddToBlobHeap(float val)
5192 return blob.Add(val, true);
5195 internal uint AddToBlobHeap(double val)
5197 return blob.Add(val, true);
5200 internal uint AddToBlobHeap(string val)
5202 return blob.Add(val,true);
5205 internal void AddCustomAttribute (CustomAttribute cattr)
5207 if (cattr_list == null)
5208 cattr_list = new ArrayList ();
5209 cattr_list.Add (cattr);
5212 internal void AddDeclSecurity (BaseDeclSecurity decl_sec)
5214 if (declsec_list == null)
5215 declsec_list = new ArrayList ();
5216 declsec_list.Add (decl_sec);
5219 private ArrayList GetTable(MDTable tableIx)
5221 int tabIx = (int)tableIx;
5222 if (metaDataTables[tabIx] == null) {
5223 metaDataTables[tabIx] = new ArrayList();
5224 valid |= ((ulong)0x1 << tabIx);
5225 // Console.WriteLine("after creating table " + tableIx + "(" + tabIx + ") valid = " + valid);
5228 return metaDataTables[tabIx];
5231 internal void AddToTable(MDTable tableIx, MetaDataElement elem)
5234 // Console.Out.WriteLine("ERROR - element already in table " + tableIx);
5237 // updates Row field of the element
5238 // Console.WriteLine("Adding element to table " + (uint)tableIx);
5239 ArrayList table = GetTable(tableIx);
5240 elem.Row = (uint)table.Count + 1;
5244 internal uint TableIndex(MDTable tableIx)
5246 if (metaDataTables[(int)tableIx] == null) return 1;
5247 return (uint)metaDataTables[(int)tableIx].Count+1;
5250 internal uint AddCode(CILInstructions byteCode)
5252 byteCodes.Add(byteCode);
5253 uint offset = codeSize + codeStart;
5254 codeSize += byteCode.GetCodeSize();
5258 internal void SetEntryPoint(MetaDataElement ep)
5263 internal uint AddResource(byte[] resBytes)
5265 if (resources == null) resources = new ArrayList ();
5266 resources.Add (resBytes);
5267 uint offset = resourcesSize;
5268 resourcesSize += (uint)resBytes.Length + 4;
5272 internal void AddData(DataConstant cVal)
5274 file.AddInitData(cVal);
5277 internal static void CompressNum(uint val, MemoryStream sig)
5280 sig.WriteByte((byte)val);
5281 } else if (val <= 0x3FFF) {
5282 byte b1 = (byte)((val >> 8) | 0x80);
5283 byte b2 = (byte)(val & FileImage.iByteMask[0]);
5287 byte b1 = (byte)((val >> 24) | 0xC0);
5288 byte b2 = (byte)((val & FileImage.iByteMask[2]) >> 16);
5289 byte b3 = (byte)((val & FileImage.iByteMask[1]) >> 8);;
5290 byte b4 = (byte)(val & FileImage.iByteMask[0]);
5298 internal uint CodeSize()
5300 return codeSize + byteCodePadding;
5303 internal uint GetResourcesSize()
5305 return resourcesSize;
5308 internal uint StringsIndexSize()
5310 if (largeStrings) return 4;
5314 internal uint GUIDIndexSize()
5316 if (largeGUID) return 4;
5320 internal uint USIndexSize()
5322 if (largeUS) return 4;
5326 internal uint BlobIndexSize()
5328 if (largeBlob) return 4;
5332 internal uint CodedIndexSize(CIx code)
5334 if (lgeCIx[(uint)code]) return 4;
5338 internal uint TableIndexSize(MDTable tabIx)
5340 if (largeIx[(uint)tabIx]) return 4;
5344 private void SetIndexSizes()
5346 for (int i=0; i < numMetaDataTables; i++) {
5347 if (metaDataTables[i] == null)
5350 uint count = (uint)metaDataTables[i].Count;
5351 if (count > maxSmlIxSize)
5354 MDTable tabIx = (MDTable)i;
5355 if (count > max5BitSmlIx) {
5356 if (tabIx == MDTable.Method || tabIx == MDTable.Field || tabIx == MDTable.TypeRef ||
5357 tabIx == MDTable.TypeDef || tabIx == MDTable.Param || tabIx == MDTable.InterfaceImpl ||
5358 tabIx == MDTable.MemberRef || tabIx == MDTable.Module || tabIx == MDTable.DeclSecurity ||
5359 tabIx == MDTable.Property || tabIx == MDTable.Event || tabIx == MDTable.StandAloneSig ||
5360 tabIx == MDTable.ModuleRef || tabIx == MDTable.TypeSpec || tabIx == MDTable.Assembly ||
5361 tabIx == MDTable.AssemblyRef || tabIx == MDTable.File || tabIx == MDTable.ExportedType ||
5362 tabIx == MDTable.ManifestResource || tabIx == MDTable.GenericParam)
5363 lgeCIx[(int)CIx.HasCustomAttr] = true;
5365 if (count > max3BitSmlIx) {
5366 if (tabIx == MDTable.Method || tabIx == MDTable.MemberRef)
5367 lgeCIx[(int)CIx.CustomAttributeType] = true;
5368 if (tabIx == MDTable.TypeDef || tabIx == MDTable.TypeRef || tabIx == MDTable.ModuleRef ||
5369 tabIx == MDTable.Method || tabIx == MDTable.TypeSpec)
5370 lgeCIx[(int)CIx.MemberRefParent] = true;
5372 if (count > max2BitSmlIx) {
5373 if ((tabIx == MDTable.Field) || (tabIx == MDTable.Param) || (tabIx == MDTable.Property))
5374 lgeCIx[(int)CIx.HasConst] = true;
5375 if ((tabIx == MDTable.TypeDef) || (tabIx == MDTable.TypeRef) || (tabIx == MDTable.TypeSpec))
5376 lgeCIx[(int)CIx.TypeDefOrRef] = true;
5377 if ((tabIx == MDTable.TypeDef) || (tabIx == MDTable.Method) || (tabIx == MDTable.Assembly))
5378 lgeCIx[(int)CIx.HasDeclSecurity] = true;
5379 if ((tabIx == MDTable.File) || (tabIx == MDTable.AssemblyRef) || (tabIx == MDTable.ExportedType))
5380 lgeCIx[(int)CIx.Implementation] = true;
5381 if ((tabIx == MDTable.Module) || (tabIx == MDTable.ModuleRef) || (tabIx == MDTable.AssemblyRef) || (tabIx == MDTable.TypeRef))
5382 lgeCIx[(int)CIx.ResolutionScope] = true;
5384 if (count > max1BitSmlIx) {
5385 if ((tabIx == MDTable.Field) || (tabIx == MDTable.Param))
5386 lgeCIx[(int)CIx.HasFieldMarshal] = true;
5387 if ((tabIx == MDTable.Event) || (tabIx == MDTable.Property))
5388 lgeCIx[(int)CIx.HasSemantics] = true;
5389 if ((tabIx == MDTable.Method) || (tabIx == MDTable.MemberRef))
5390 lgeCIx[(int)CIx.MethodDefOrRef] = true;
5391 if ((tabIx == MDTable.Field) || (tabIx == MDTable.Method))
5392 lgeCIx[(int)CIx.MemberForwarded] = true;
5393 if ((tabIx == MDTable.TypeDef) || (tabIx == MDTable.Method))
5394 lgeCIx[(int)CIx.TypeOrMethodDef] = true;
5399 private void SetStreamOffsets()
5401 uint sizeOfHeaders = StreamHeaderSize + (uint)tildeName.Length;
5402 for (int i=1; i < numStreams; i++) {
5403 sizeOfHeaders += streams[i].headerSize();
5405 metaDataSize = MetaDataHeaderSize + sizeOfHeaders;
5406 tildeStart = metaDataSize;
5407 metaDataSize += tildeTide + tildePadding;
5408 for (int i=1; i < numStreams; i++) {
5409 streams[i].Start = metaDataSize;
5410 metaDataSize += streams[i].Size();
5411 streams[i].WriteDetails();
5415 internal void CalcTildeStreamSize()
5418 //tilde.SetIndexSizes(strings.LargeIx(),us.LargeIx(),guid.LargeIx(),blob.LargeIx());
5419 tildeTide = TildeHeaderSize;
5420 tildeTide += 4 * numTables;
5421 //Console.WriteLine("Tilde header + sizes = " + tildeTide);
5422 for (int i=0; i < numMetaDataTables; i++) {
5423 if (metaDataTables[i] != null) {
5424 ArrayList table = metaDataTables[i];
5425 // Console.WriteLine("Meta data table " + i + " at offset " + tildeTide);
5426 tildeTide += (uint)table.Count * ((MetaDataElement)table[0]).Size(this);
5427 // Console.WriteLine("Metadata table " + i + " has size " + table.Count);
5428 // Console.WriteLine("tildeTide = " + tildeTide);
5431 if ((tildeTide % 4) != 0) tildePadding = 4 - (tildeTide % 4);
5432 //Console.WriteLine("tildePadding = " + tildePadding);
5435 internal void WriteTildeStream(FileImage output)
5437 output.Seek(0,SeekOrigin.Current);
5438 output.Write((uint)0); // Reserved
5439 output.Write((byte)2); // MajorVersion
5440 output.Write((byte)0); // MinorVersion
5441 output.Write(heapSizes);
5442 output.Write((byte)1); // Reserved
5443 output.Write(valid);
5444 output.Write(sorted);
5446 for (int i=0; i < numMetaDataTables; i++) {
5447 if (metaDataTables[i] != null) {
5448 uint count = (uint)metaDataTables[i].Count;
5449 output.Write(count);
5453 output.Seek(0,SeekOrigin.Current);
5454 // Console.WriteLine("Starting metaData tables at " + tabStart);
5455 for (int i=0; i < numMetaDataTables; i++) {
5456 if (metaDataTables[i] != null) {
5457 // Console.WriteLine("Starting metaData table " + i + " at " + (output.Seek(0,SeekOrigin.Current) - startTilde));
5458 ArrayList table = metaDataTables[i];
5459 for (int j=0; j < table.Count; j++) {
5460 ((MetaDataElement)table[j]).Write(output);
5464 // Console.WriteLine("Writing padding at " + output.Seek(0,SeekOrigin.Current));
5465 for (int i=0; i < tildePadding; i++) output.Write((byte)0);
5468 private void BuildTable(ArrayList table)
5470 if (table == null) return;
5471 for (int j=0; j < table.Count; j++) {
5472 ((MetaDataElement)table[j]).BuildTables(this);
5476 private void SortTable (ArrayList mTable)
5478 if (mTable == null) return;
5480 for (int i=0; i < mTable.Count; i++) {
5481 ((MetaDataElement)mTable[i]).Row = (uint)i+1;
5485 internal void BuildMetaData(uint codeStartOffset)
5487 codeStart = codeStartOffset;
5488 BuildTable(metaDataTables[(int)MDTable.TypeDef]);
5489 BuildTable(metaDataTables[(int)MDTable.TypeSpec]);
5490 BuildTable(metaDataTables[(int)MDTable.MemberRef]);
5491 BuildTable(metaDataTables[(int)MDTable.GenericParam]);
5492 BuildTable(metaDataTables[(int)MDTable.MethodSpec]);
5493 BuildTable(metaDataTables[(int)MDTable.GenericParamConstraint]);
5494 BuildTable(metaDataTables[(int)MDTable.ManifestResource]);
5496 if (cattr_list != null) {
5497 foreach (CustomAttribute cattr in cattr_list)
5498 cattr.BuildTables (this);
5501 if (declsec_list != null) {
5502 foreach (BaseDeclSecurity decl_sec in declsec_list)
5503 decl_sec.BuildTables (this);
5506 /* for (int i=0; i < metaDataTables.Length; i++) {
5507 ArrayList table = metaDataTables[i];
5508 if (table != null) {
5509 for (int j=0; j < table.Count; j++) {
5510 ((MetaDataElement)table[j]).BuildTables(this);
5517 for (int i=1; i < numStreams; i++) {
5518 streams[i].EndStream();
5520 CalcTildeStreamSize();
5522 byteCodePadding = NumToAlign(codeSize,4);
5523 if (entryPoint != null) file.SetEntryPoint(entryPoint.Token());
5525 // Check ordering of specific tables
5526 // Constant, CustomAttribute, FieldMarshal, DeclSecurity, MethodSemantics
5527 // ImplMap, GenericParam
5528 // Need to load GenericParamConstraint AFTER GenericParam table in correct order
5530 // InterfaceImpl, ClassLayout, FieldLayout, MethodImpl, FieldRVA, NestedClass
5531 // will _ALWAYS_ be in the correct order as embedded in BuildMDTables
5533 SortTable(metaDataTables[(int)MDTable.Constant]);
5534 SortTable(metaDataTables[(int)MDTable.FieldMarshal]);
5535 SortTable(metaDataTables[(int)MDTable.DeclSecurity]);
5536 SortTable(metaDataTables[(int)MDTable.MethodSemantics]);
5537 SortTable(metaDataTables[(int)MDTable.ImplMap]);
5538 if (metaDataTables[(int)MDTable.GenericParam] != null) {
5539 SortTable(metaDataTables[(int)MDTable.GenericParam]);
5540 // Now add GenericParamConstraints
5541 /*for (int i=0; i < metaDataTables[(int)MDTable.GenericParam].Count; i++) {
5542 ((GenericParameter)metaDataTables[(int)MDTable.GenericParam][i]).AddConstraints(this);
5545 SortTable(metaDataTables[(int)MDTable.GenericParamConstraint]);
5546 SortTable(metaDataTables[(int)MDTable.InterfaceImpl]);
5547 SortTable(metaDataTables[(int)MDTable.CustomAttribute]);
5551 internal void WriteByteCodes(FileImage output)
5553 for (int i=0; i < byteCodes.Count; i++) {
5554 ((CILInstructions)byteCodes[i]).Write(output);
5556 for (int i=0; i < byteCodePadding; i++) {
5557 output.Write((byte)0);
5561 internal void WriteResources (FileImage output)
5563 if (resources == null) return;
5564 for (int i = 0; i < resources.Count; i ++) {
5565 byte [] resBytes = (byte []) resources [i];
5566 output.Write ((uint) resBytes.Length);
5567 output.Write (resBytes);
5571 internal void WriteMetaData(FileImage output)
5573 this.output = output;
5574 mdStart = output.Seek(0,SeekOrigin.Current);
5575 // Console.WriteLine("Writing metaData at " + Hex.Long(mdStart));
5576 output.Write(MetaDataSignature);
5577 output.Write((short)1); // Major Version
5578 output.Write((short)1); // Minor Version ECMA = 0, PEFiles = 1
5579 output.Write(0); // Reserved
5580 output.Write(version.Length);
5581 output.Write(version.ToCharArray()); // version string is already zero padded
5582 output.Write((short)0);
5583 output.Write((ushort)numStreams);
5584 // write tilde header
5585 output.Write(tildeStart);
5586 output.Write(tildeTide + tildePadding);
5587 output.Write(tildeName);
5588 for (int i=1; i < numStreams; i++) streams[i].WriteHeader(output);
5589 // Console.WriteLine("Writing tilde stream at " + output.Seek(0,SeekOrigin.Current) + " = " + tildeStart);
5590 WriteTildeStream(output);
5591 for (int i=1; i < numStreams; i++) streams[i].Write(output);
5592 // Console.WriteLine("Finished Writing metaData at " + output.Seek(0,SeekOrigin.Current));
5595 internal bool LargeStringsIndex() { return strings.LargeIx(); }
5596 internal bool LargeGUIDIndex() { return guid.LargeIx(); }
5597 internal bool LargeUSIndex() { return us.LargeIx(); }
5598 internal bool LargeBlobIndex() { return blob.LargeIx(); }
5600 internal bool LargeIx(MDTable tabIx) { return largeIx[(uint)tabIx]; }
5603 private uint NumToAlign(uint val, uint alignVal)
5605 if ((val % alignVal) == 0) return 0;
5606 return alignVal - (val % alignVal);
5609 internal void WriteCodedIndex(CIx code, MetaDataElement elem, FileImage output)
5613 ix = (elem.Row << CIxShiftMap[(uint)code]) | elem.GetCodedIx(code);
5614 // Console.WriteLine("coded index = " + ix + " row = " + elem.Row);
5616 // Console.WriteLine("elem for coded index is null");
5618 if (lgeCIx[(uint)code])
5621 output.Write((ushort)ix);
5626 /**************************************************************************/
5628 /// Stream in the Meta Data (#Strings, #US, #Blob and #GUID)
5631 internal class MetaDataStream : BinaryWriter {
5633 private static readonly uint StreamHeaderSize = 8;
5634 private static uint maxSmlIxSize = 0xFFFF;
5636 private uint start = 0;
5637 uint size = 0, tide = 1;
5638 bool largeIx = false;
5641 Hashtable htable = new Hashtable();
5642 Hashtable btable = new Hashtable (new ByteArrayHashCodeProvider (), new ByteArrayComparer ());
5644 internal MetaDataStream(char[] name, bool addInitByte) : base(new MemoryStream())
5646 if (addInitByte) { Write((byte)0); size = 1; }
5648 sizeOfHeader = StreamHeaderSize + (uint)name.Length;
5651 internal MetaDataStream(char[] name, System.Text.Encoding enc, bool addInitByte) : base(new MemoryStream(),enc)
5653 if (addInitByte) { Write((byte)0); size = 1; }
5655 sizeOfHeader = StreamHeaderSize + (uint)name.Length;
5659 get { return start; }
5660 set { start = value; }
5663 internal uint headerSize()
5665 // Console.WriteLine(name + " stream has headersize of " + sizeOfHeader);
5666 return sizeOfHeader;
5669 internal void SetSize(uint siz)
5674 internal uint Size()
5679 internal bool LargeIx()
5684 internal void WriteDetails()
5686 // Console.WriteLine(name + " - size = " + size);
5689 internal uint Add(string str, bool prependSize)
5691 Object val = htable[str];
5695 htable[str] = index;
5696 char[] arr = str.ToCharArray();
5697 if (prependSize) CompressNum((uint)arr.Length*2+1);
5700 size = (uint)Seek(0,SeekOrigin.Current);
5706 internal uint Add (byte[] str, bool prependSize)
5708 Object val = btable [str];
5712 btable [str] = index;
5713 if (prependSize) CompressNum ((uint) str.Length);
5715 size = (uint) Seek (0, SeekOrigin.Current);
5723 internal uint Add(Guid guid, bool prependSize)
5725 byte [] b = guid.ToByteArray ();
5726 if (prependSize) CompressNum ((uint) b.Length);
5727 Write(guid.ToByteArray());
5728 size =(uint)Seek(0,SeekOrigin.Current);
5732 internal uint Add(byte[] blob)
5735 CompressNum((uint)blob.Length);
5737 size = (uint)Seek(0,SeekOrigin.Current);
5741 internal uint Add(byte val, bool prependSize)
5744 if (prependSize) CompressNum (1);
5746 size = (uint)Seek(0,SeekOrigin.Current);
5750 internal uint Add(sbyte val, bool prependSize)
5753 if (prependSize) CompressNum (1);
5755 size = (uint)Seek(0,SeekOrigin.Current);
5759 internal uint Add(ushort val, bool prependSize)
5762 if (prependSize) CompressNum (2);
5764 size = (uint)Seek(0,SeekOrigin.Current);
5768 internal uint Add(short val, bool prependSize)
5771 if (prependSize) CompressNum (2);
5773 size = (uint)Seek(0,SeekOrigin.Current);
5777 internal uint Add(uint val, bool prependSize)
5780 if (prependSize) CompressNum (4);
5782 size = (uint)Seek(0,SeekOrigin.Current);
5786 internal uint Add(int val, bool prependSize)
5789 if (prependSize) CompressNum (4);
5791 size = (uint)Seek(0,SeekOrigin.Current);
5795 internal uint Add(ulong val, bool prependSize)
5798 if (prependSize) CompressNum (8);
5800 size = (uint)Seek(0,SeekOrigin.Current);
5804 internal uint Add(long val, bool prependSize)
5807 if (prependSize) CompressNum (8);
5809 size = (uint)Seek(0,SeekOrigin.Current);
5813 internal uint Add(float val, bool prependSize)
5816 if (prependSize) CompressNum (4);
5818 size = (uint)Seek(0,SeekOrigin.Current);
5822 internal uint Add(double val, bool prependSize)
5825 if (prependSize) CompressNum (8);
5827 size = (uint)Seek(0,SeekOrigin.Current);
5831 private void CompressNum(uint val)
5835 } else if (val < 0x3FFF) {
5836 byte b1 = (byte)((val >> 8) | 0x80);
5837 byte b2 = (byte)(val & FileImage.iByteMask[0]);
5841 byte b1 = (byte)((val >> 24) | 0xC0);
5842 byte b2 = (byte)((val & FileImage.iByteMask[2]) >> 16);
5843 byte b3 = (byte)((val & FileImage.iByteMask[1]) >> 8);;
5844 byte b4 = (byte)(val & FileImage.iByteMask[0]);
5852 private void QuadAlign()
5854 if ((size % 4) != 0) {
5855 uint pad = 4 - (size % 4);
5857 for (int i=0; i < pad; i++) {
5863 internal void EndStream()
5866 if (size > maxSmlIxSize) {
5871 internal void WriteHeader(BinaryWriter output)
5873 output.Write(start);
5878 internal virtual void Write(BinaryWriter output)
5880 // Console.WriteLine("Writing " + name + " stream at " + output.Seek(0,SeekOrigin.Current) + " = " + start);
5881 MemoryStream str = (MemoryStream)BaseStream;
5882 output.Write(str.ToArray());
5887 /**************************************************************************/
5888 class ByteArrayComparer : IComparer {
5890 public int Compare (object x, object y)
5892 byte [] a = (byte []) x;
5893 byte [] b = (byte []) y;
5896 if (b.Length != len)
5899 for (int i = 0; i < len; ++i)
5906 class ByteArrayHashCodeProvider : IHashCodeProvider {
5908 public int GetHashCode (Object key)
5910 byte [] arr = (byte []) key;
5911 int len = arr.Length;
5914 for (int i = 0; i < len; ++i)
5915 h = (h << 5) - h + arr [i];