2009-03-27 Sebastien Pouliot <sebastien@ximian.com>
[mono-project.git] / mcs / class / PEAPI / Metadata.cs
blob49ed4dc52331de7a14edb01a82f4c05dc2464089
1 using System;
2 using System.IO;
3 using System.Collections;
4 using System.Text;
5 using System.Reflection;
7 namespace PEAPI {
9 #region Enums
11 /// <summary>
12 /// flags for the assembly (.corflags)
13 /// </summary>
14 public enum CorFlags {CF_IL_ONLY = 1, CF_32_BITREQUIRED = 2,
15 CF_STRONGNAMESIGNED = 8, CF_TRACKDEBUGDATA = 0x10000 }
17 /// <summary>
18 /// subsystem for the assembly (.subsystem)
19 /// </summary>
20 public enum SubSystem { Native = 1, Windows_GUI = 2,
21 Windows_CUI = 3, OS2_CUI = 5, POSIX_CUI = 7, Native_Windows = 8,
22 Windows_CE_GUI = 9}
24 /// <summary>
25 /// Hash algorithms for the assembly
26 /// </summary>
27 public enum HashAlgorithm { None, SHA1 }
29 /// <summary>
30 /// Attributes for this assembly
31 /// </summary>
32 public enum AssemAttr { Retargetable = 0x100, EnableJITCompileTracking = 0x8000,
33 DisableJITCompileOptimizer = 0x4000}
35 /// <summary>
36 /// Method call conventions
37 /// </summary>
38 [Flags]
39 public enum CallConv { Default, Cdecl, Stdcall, Thiscall,
40 Fastcall, Vararg, Instance = 0x20, Generic = 0x10, InstanceExplicit = 0x60 }
42 /// <summary>
43 /// Type custom modifier
44 /// </summary>
45 public enum CustomModifier { modreq = 0x1F, modopt };
47 /// <summary>
48 /// Attibutes for a class
49 /// </summary>
50 [Flags]
51 public enum TypeAttr {Private, Public, NestedPublic, NestedPrivate,
52 NestedFamily, NestedAssembly, NestedFamAndAssem, NestedFamOrAssem,
53 SequentialLayout, ExplicitLayout = 0x10, Interface = 0x20,
54 Abstract = 0x80, PublicAbstract = 0x81, Sealed = 0x100,
55 PublicSealed = 0x101, SpecialName = 0x400, RTSpecialName = 0x800,
56 Import = 0x1000, Serializable = 0x2000, UnicodeClass = 0x10000,
57 AutoClass = 0x20000, HasSecurity = 0x40000, BeforeFieldInit = 0x100000,
58 VisibilityMask = 0x07 }
60 /// <summary>
61 /// Attributes for a field
62 /// </summary>
63 public enum FieldAttr {Default, Private, FamAndAssem, Assembly,
64 Family, FamOrAssem, Public, Static = 0x10, PublicStatic = 0x16,
65 Initonly = 0x20, Literal = 0x40, Notserialized = 0x80,
66 SpecialName = 0x200, RTSpecialName = 0x400, HasFieldMarshal = 0x1000 }
68 /// <summary>
69 /// Attributes for a method
70 /// </summary>
71 public enum MethAttr { Default, Private, FamAndAssem, Assembly,
72 Family, FamOrAssem, Public, Static = 0x0010, PublicStatic = 0x16,
73 Final = 0x0020, PublicStaticFinal = 0x36, Virtual = 0x0040,
74 PrivateVirtual, PublicVirtual = 0x0046, HideBySig = 0x0080,
75 NewSlot = 0x0100, Strict = 0x200, Abstract = 0x0400, SpecialName = 0x0800,
76 RTSpecialName = 0x1000, SpecialRTSpecialName = 0x1800,
77 HasSecurity = 0x4000, RequireSecObject = 0x8000}
79 /// <summary>
80 /// Attributes for .pinvokeimpl method declarations
81 /// </summary>
82 public enum PInvokeAttr { nomangle = 1, ansi = 2, unicode = 4, autochar = 6,
83 bestfit_on = 0x0010, bestfit_off = 0x0020, bestfit_mask = 0x0030,
84 lasterr = 0x0040, winapi = 0x0100, cdecl = 0x0200,
85 stdcall = 0x0300, thiscall = 0x0400, fastcall = 0x0500,
86 charmaperror_on = 0x1000, charmaperror_off = 0x2000
89 /// <summary>
90 /// Implementation attributes for a method
91 /// </summary>
92 public enum ImplAttr { IL, Native, Runtime = 0x03, Unmanaged = 0x04,
93 ForwardRef = 0x10, PreserveSig = 0x0080, InternalCall = 0x1000,
94 Synchronised = 0x0020, Synchronized = 0x0020, NoInLining = 0x0008, Optil = 0x0002}
96 /// <summary>
97 /// Modes for a parameter
98 /// </summary>
99 public enum ParamAttr { Default, In, Out, Opt = 16, HasDefault = 0x1000, HasFieldMarshal = 0x2000 }
101 /// <summary>
102 /// CIL instructions
103 /// </summary>
104 public enum Op { nop, breakOp, ldarg_0, ldarg_1, ldarg_2, ldarg_3,
105 ldloc_0, ldloc_1, ldloc_2, ldloc_3, stloc_0, stloc_1, stloc_2, stloc_3,
106 ldnull = 0x14, ldc_i4_m1, ldc_i4_0, ldc_i4_1, ldc_i4_2, ldc_i4_3,
107 ldc_i4_4, ldc_i4_5, ldc_i4_6, ldc_i4_7, ldc_i4_8, dup = 0x25, pop,
108 ret = 0x2A, ldind_i1 = 0x46, ldind_u1, ldind_i2, ldind_u2, ldind_i4,
109 ldind_u4, ldind_i8, ldind_i, ldind_r4, ldind_r8, ldind_ref, stind_ref,
110 stind_i1, stind_i2, stind_i4, stind_i8, stind_r4, stind_r8, add, sub, mul,
111 div, div_un, rem, rem_un, and, or, xor, shl, shr, shr_un, neg, not,
112 conv_i1, conv_i2, conv_i4, conv_i8, conv_r4, conv_r8, conv_u4, conv_u8,
113 conv_r_un = 0x76, throwOp = 0x7A, conv_ovf_i1_un = 0x82, conv_ovf_i2_un,
114 conv_ovf_i4_un, conv_ovf_i8_un, conf_ovf_u1_un, conv_ovf_u2_un,
115 conv_ovf_u4_un, conv_ovf_u8_un, conv_ovf_i_un, conv_ovf_u_un,
116 ldlen = 0x8E, ldelem_i1 = 0x90, ldelem_u1, ldelem_i2, ldelem_u2,
117 ldelem_i4, ldelem_u4, ldelem_i8, ldelem_i, ldelem_r4, ldelem_r8,
118 ldelem_ref, stelem_i, stelem_i1, stelem_i2, stelem_i4, stelem_i8, stelem_r4 = 0xA0, stelem_r8,
119 stelem_ref, conv_ovf_i1 = 0xb3, conv_ovf_u1, conv_ovf_i2, conv_ovf_u2,
120 conv_ovf_i4, conv_ovf_u4, conv_ovf_i8, conv_ovf_u8, ckfinite = 0xC3,
121 conv_u2 = 0xD1, conv_u1, conv_i, conv_ovf_i, conv_ovf_u, add_ovf,
122 add_ovf_un, mul_ovf, mul_ovf_un, sub_ovf, sub_ovf_un, endfinally,
123 stind_i = 0xDF, conv_u, arglist = 0xFE00, ceq, cgt, cgt_un, clt, clt_un,
124 localloc = 0xFE0F, endfilter = 0xFE11, volatile_ = 0xFE13, tail_,
125 cpblk = 0xFE17, initblk, rethrow = 0xFE1A, refanytype = 0xFE1D, readonly_ = 0xFE1E }
127 /// <summary>
128 /// CIL instructions requiring an integer parameter
129 /// </summary>
130 public enum IntOp {ldarg_s = 0x0E, ldarga_s, starg_s, ldloc_s, ldloca_s,
131 stloc_s, ldc_i4_s = 0x1F, ldc_i4, ldarg = 0xFE09,
132 ldarga, starg, ldloc, ldloca, stloc, unaligned = 0xFE12 }
134 /// <summary>
135 /// CIL instructions requiring a field parameter
136 /// </summary>
137 public enum FieldOp {ldfld = 0x7B, ldflda, stfld, ldsfld, ldsflda,
138 stsfld, ldtoken = 0xD0 }
140 /// <summary>
141 /// CIL instructions requiring a method parameter
142 /// </summary>
143 public enum MethodOp {jmp = 0x27, call, callvirt = 0x6F, newobj = 0x73,
144 ldtoken = 0xD0, ldftn = 0xFE06, ldvirtfn }
146 /// <summary>
147 /// CIL instructions requiring a type parameter
148 /// </summary>
149 public enum TypeOp {cpobj = 0x70, ldobj, castclass = 0x74, isinst,
150 unbox = 0x79, stobj = 0x81, box = 0x8C, newarr,
151 ldelema = 0x8F, refanyval = 0xC2, mkrefany = 0xC6,
152 ldtoken = 0xD0, initobj = 0xFE15, constrained = 0xFE16,
153 sizeOf = 0xFE1C, ldelem = 0xA3, stelem = 0xA4, unbox_any }
155 /// <summary>
156 /// CIL branch instructions
157 /// </summary>
158 public enum BranchOp {
159 // short branches
160 br_s = 0x2B, brfalse_s, brtrue_s, beq_s, bge_s, bgt_s,
161 ble_s, blt_s, bne_un_s, bge_un_s, bgt_un_s, ble_un_s, blt_un_s,
162 // long branches
163 br = 0x38, brfalse, brtrue, beq, bge, bgt, ble, blt,
164 bne_un, bge_un, bgt_un, ble_un, blt_un,
166 leave = 0xDD, leave_s }
168 /// <summary>
169 /// Index for all the tables in the meta data
170 /// </summary>
171 public enum MDTable { Module, TypeRef, TypeDef, Field = 0x04, Method = 0x06,
172 Param = 0x08, InterfaceImpl, MemberRef, Constant, CustomAttribute,
173 FieldMarshal, DeclSecurity, ClassLayout, FieldLayout, StandAloneSig,
174 EventMap, Event = 0x14, PropertyMap, Property = 0x17, MethodSemantics,
175 MethodImpl, ModuleRef, TypeSpec, ImplMap, FieldRVA, Assembly = 0x20,
176 AssemblyProcessor, AssemblyOS, AssemblyRef, AssemblyRefProcessor,
177 AssemblyRefOS, File, ExportedType, ManifestResource, NestedClass,
178 GenericParam, MethodSpec, GenericParamConstraint }
180 public enum SafeArrayType { int16 = 2, int32, float32, float64,
181 currency, date, bstr, dispatch, error, boolean, variant, unknown,
182 Decimal, int8 = 16, uint8, uint16, uint32, Int = 22, UInt }
184 internal enum CIx { TypeDefOrRef, HasConst, HasCustomAttr, HasFieldMarshal,
185 HasDeclSecurity, MemberRefParent, HasSemantics, MethodDefOrRef,
186 MemberForwarded, Implementation, CustomAttributeType, ResolutionScope,
187 TypeOrMethodDef, MaxCIx }
189 internal enum MapType { eventMap, propertyMap, nestedClass }
191 public enum ValueClass { ValueType, Enum }
193 public enum GenParamType : byte {
194 Var = 0x13, MVar = 0x1E
197 [Flags]
198 public enum GenericParamAttributes : ushort {
199 VarianceMask = 0x0003,
200 NonVariant = 0x0000,
201 Covariant = 0x0001,
202 Contravariant = 0x0002,
204 SpecialConstraintMask = 0x001c,
205 ReferenceTypeConstraint = 0x0004,
206 NotNullableValueTypeConstraint = 0x0008,
207 DefaultConstructorConstrait = 0x0010
210 /* Taken from Mono.Cecil */
211 public enum SecurityAction : short {
212 Request = 1,
213 Demand = 2,
214 Assert = 3,
215 Deny = 4,
216 PermitOnly = 5,
217 LinkDemand = 6,
218 InheritDemand = 7,
219 RequestMinimum = 8,
220 RequestOptional = 9,
221 RequestRefuse = 10,
222 PreJitGrant = 11,
223 PreJitDeny = 12,
224 NonCasDemand = 13,
225 NonCasLinkDemand = 14,
226 NonCasInheritance = 15,
227 LinkDemandChoice = 16,
228 InheritDemandChoice = 17,
229 DemandChoice = 18
232 #endregion
234 /**************************************************************************/
235 /// <summary>
236 /// Base class for all Meta Data table elements
237 /// </summary>
239 public abstract class MetaDataElement: IComparable {
240 protected ArrayList customAttributes;
241 private uint row = 0;
242 protected bool done = false;
243 protected MDTable tabIx;
244 protected bool sortTable = false;
245 //Temporary hack..
246 private bool has_custom_attrs = false;
248 internal MetaDataElement() { }
250 public uint Row {
251 get {
252 return row;
254 set {
255 row = value;
259 public bool HasCustomAttr {
260 get { return has_custom_attrs; }
261 set { has_custom_attrs = value; }
264 internal virtual uint GetCodedIx(CIx code) { return 0; }
266 /// <summary>
267 /// Add a custom attribute to this item
268 /// </summary>
269 /// <param name="ctorMeth">the constructor method for this attribute</param>
270 /// <param name="val">the byte value of the parameters</param>
271 public void AddCustomAttribute(Method ctorMeth, byte[] val)
273 if (customAttributes == null) {
274 customAttributes = new ArrayList();
276 customAttributes.Add(new CustomAttribute(this,ctorMeth,val));
279 /// <summary>
280 /// Add a custom attribute to this item
281 /// </summary>
282 /// <param name="ctorMeth">the constructor method for this attribute</param>
283 /// <param name="val">the constant values of the parameters</param>
284 public void AddCustomAttribute(Method ctorMeth, Constant[] cVals)
286 if (customAttributes == null) {
287 customAttributes = new ArrayList();
289 // customAttributes.Add(new CustomAttribute(this,ctorMeth,cVals));
292 internal uint Token()
294 return (((uint)tabIx << 24) | row);
297 internal virtual void BuildTables(MetaData md)
299 done = true;
302 internal virtual uint Size(MetaData md)
304 return 0;
307 internal virtual void Write(FileImage output) { }
309 internal virtual uint SortKey()
311 throw new PEFileException("Trying to sort table of " + this);
312 //return 0;
315 internal virtual uint SortKey2()
317 return 0;
320 public int CompareTo(object obj)
322 uint otherKey = ((MetaDataElement)obj).SortKey();
323 uint thisKey = SortKey();
325 if (thisKey == otherKey) {
327 otherKey = ((MetaDataElement)obj).SortKey2();
328 thisKey = SortKey2();
329 if (thisKey == otherKey)
330 return 0;
331 if (thisKey < otherKey)
332 return -1;
333 return 1;
335 if (thisKey < otherKey) return -1;
337 return 1;
342 /**************************************************************************/
343 /// <summary>
344 /// Layout information for a class (.class [sequential | explicit])
345 /// </summary>
346 internal class ClassLayout : MetaDataElement {
348 ClassDef parent;
349 ushort packSize = 0;
350 uint classSize = 0;
352 internal ClassLayout(int pack, int cSize, ClassDef par)
354 packSize = (ushort)pack;
355 classSize = (uint)cSize;
356 parent = par;
357 tabIx = MDTable.ClassLayout;
360 internal sealed override uint Size(MetaData md)
362 return 6 + md.TableIndexSize(MDTable.TypeDef);
365 internal sealed override void Write(FileImage output)
367 output.Write(packSize);
368 output.Write(classSize);
369 output.WriteIndex(MDTable.TypeDef,parent.Row);
374 /**************************************************************************/
375 /// <summary>
376 /// Summary description for ConstantElem.
377 /// </summary>
378 internal class ConstantElem : MetaDataElement {
380 MetaDataElement parent;
381 Constant cValue;
382 uint valIx = 0;
384 internal ConstantElem(MetaDataElement parent, Constant val)
386 this.parent = parent;
387 cValue = val;
388 tabIx = MDTable.Constant;
389 sortTable = true;
392 internal override uint SortKey()
394 return (parent.Row << MetaData.CIxShiftMap[(uint)CIx.HasConst])
395 | parent.GetCodedIx(CIx.HasConst);
398 internal sealed override void BuildTables(MetaData md)
400 if (done) return;
401 valIx = cValue.GetBlobIndex(md);
402 done = true;
405 internal void AddToBlob(BinaryWriter bw)
407 cValue.Write(bw);
410 internal sealed override uint Size(MetaData md)
412 return 2 + md.CodedIndexSize(CIx.HasConst) + md.BlobIndexSize();
415 internal sealed override void Write(FileImage output)
417 output.Write(cValue.GetTypeIndex());
418 output.Write((byte)0);
419 output.WriteCodedIndex(CIx.HasConst,parent);
420 output.BlobIndex(valIx);
424 /**************************************************************************/
425 /// <summary>
426 /// Descriptor for a Custom Attribute (.custom)
427 /// </summary>
429 public class CustomAttribute : MetaDataElement {
431 private static readonly ushort prolog = 0x0001;
432 MetaDataElement parent;
433 Method type;
434 uint valIx;
435 Constant cVal;
436 byte[] byteVal;
437 ushort numNamed = 0;
438 ArrayList names, vals;
440 internal CustomAttribute(MetaDataElement paren, Method constrType,
441 Constant val) {
442 parent = paren;
443 type = constrType;
444 cVal = val;
445 tabIx = MDTable.CustomAttribute;
448 internal CustomAttribute(MetaDataElement paren, Method constrType,
449 byte[] val) {
450 parent = paren;
451 type = constrType;
452 tabIx = MDTable.CustomAttribute;
453 byteVal = val;
456 internal override uint SortKey()
458 return (parent.Row << MetaData.CIxShiftMap[(uint)CIx.HasCustomAttr])
459 | parent.GetCodedIx(CIx.HasCustomAttr);
462 public void AddFieldOrProp(string name, Constant val)
464 if (numNamed == 0) {
465 names = new ArrayList();
466 vals = new ArrayList();
468 names.Add(name);
469 vals.Add(val);
472 internal sealed override void BuildTables(MetaData md)
474 md.AddToTable(MDTable.CustomAttribute, this);
475 if (byteVal == null) {
476 valIx = 0;
477 return;
480 BinaryWriter bw = new BinaryWriter(new MemoryStream());
481 bw.Write(byteVal);
482 MemoryStream str = (MemoryStream)bw.BaseStream;
483 valIx = md.AddToBlobHeap(str.ToArray());
486 internal sealed override uint Size(MetaData md)
488 return md.CodedIndexSize(CIx.HasCustomAttr) + md.CodedIndexSize(CIx.CustomAttributeType) + md.BlobIndexSize();
491 internal sealed override void Write(FileImage output)
493 output.WriteCodedIndex(CIx.HasCustomAttr,parent);
494 output.WriteCodedIndex(CIx.CustomAttributeType,type);
495 output.BlobIndex(valIx);
500 /**************************************************************************/
501 /// <summary>
502 /// Descriptor for security permissions for a class or a method
503 /// </summary>
505 public abstract class BaseDeclSecurity : MetaDataElement {
507 ushort action;
508 MetaDataElement parent;
509 uint permissionIx;
511 internal BaseDeclSecurity(MetaDataElement paren, ushort act)
513 parent = paren;
514 action = act;
515 tabIx = MDTable.DeclSecurity;
518 internal override uint SortKey()
520 return (parent.Row << MetaData.CIxShiftMap[(uint)CIx.HasDeclSecurity])
521 | parent.GetCodedIx(CIx.HasDeclSecurity);
524 internal sealed override uint Size(MetaData md)
526 return 2 + md.CodedIndexSize(CIx.HasDeclSecurity) + md.BlobIndexSize();
529 internal sealed override void BuildTables(MetaData md)
531 if (done) return;
533 BinaryWriter bw = new BinaryWriter (new MemoryStream ());
534 md.AddToTable (MDTable.DeclSecurity, this);
535 MemoryStream str = (MemoryStream)bw.BaseStream;
536 WriteSig (bw);
537 permissionIx = md.AddToBlobHeap(str.ToArray());
539 done = true;
542 internal abstract void WriteSig (BinaryWriter bw);
544 internal sealed override void Write(FileImage output)
546 output.Write(action);
547 output.WriteCodedIndex(CIx.HasDeclSecurity,parent);
548 output.BlobIndex(permissionIx);
553 public class DeclSecurity : BaseDeclSecurity {
555 byte [] byteVal;
557 internal DeclSecurity(MetaDataElement paren, ushort act, byte [] val)
558 : base (paren, act)
560 byteVal = val;
563 internal override void WriteSig (BinaryWriter bw)
565 bw.Write (byteVal);
570 public class DeclSecurity_20 : BaseDeclSecurity {
572 PermissionSet ps;
574 internal DeclSecurity_20 (MetaDataElement paren, ushort act, PermissionSet ps)
575 : base (paren, act)
577 this.ps = ps;
580 internal override void WriteSig (BinaryWriter bw)
582 ps.Write (bw);
586 public class PermissionMember {
588 MemberTypes member_type;
589 PEAPI.Type type;
590 string name;
591 object value;
593 public PermissionMember (MemberTypes member_type, PEAPI.Type type, string name, object value)
595 this.member_type = member_type;
596 this.type = type;
597 this.name = name;
598 this.value = value;
601 public void Write (BinaryWriter bw)
603 byte [] b;
605 if (member_type == MemberTypes.Field)
606 bw.Write ((byte) 0x53);
607 else
608 //Property
609 bw.Write ((byte) 0x54);
611 if (type is PrimitiveType) {
612 bw.Write (type.GetTypeIndex ());
613 } else {
614 //must be enum
615 bw.Write ((byte) 0x55); //ENUM
617 b = Encoding.UTF8.GetBytes (((ClassRef) type).TypeName ());
618 MetaData.CompressNum ((uint) b.Length, (MemoryStream) bw.BaseStream);
619 bw.Write (b);
622 b = Encoding.UTF8.GetBytes (name);
623 MetaData.CompressNum ((uint) b.Length, (MemoryStream) bw.BaseStream);
624 bw.Write (b);
626 ((Constant) value).Write (bw);
631 public class Permission
633 PEAPI.Type type;
635 //PermissionMembers
636 ArrayList members;
637 string name;
639 public Permission (PEAPI.Type type, string name)
641 this.type = type;
642 this.name = name;
645 public void AddMember (PEAPI.PermissionMember member)
647 if (members == null)
648 members = new ArrayList ();
650 members.Add (member);
653 public void Write (BinaryWriter bw)
655 byte [] b = Encoding.UTF8.GetBytes (name);
656 MetaData.CompressNum ((uint) b.Length, (MemoryStream) bw.BaseStream);
657 bw.Write (b);
659 BinaryWriter perm_writer = new BinaryWriter (new MemoryStream (), Encoding.Unicode);
660 MemoryStream str = (MemoryStream) perm_writer.BaseStream;
662 MetaData.CompressNum ((uint) members.Count, str);//number of params
663 foreach (PermissionMember member in members)
664 member.Write (perm_writer);
666 bw.Write ((byte) str.Length); //(optional) parameters length
667 bw.Write (str.ToArray ());
671 public class PermissionSet
673 PEAPI.SecurityAction sec_action;
674 ArrayList permissions;
675 PEAPI.PermissionSet ps;
677 public PermissionSet (PEAPI.SecurityAction sec_action)
679 this.sec_action = sec_action;
682 public void AddPermission (PEAPI.Permission perm)
684 if (permissions == null)
685 permissions = new ArrayList ();
687 permissions.Add (perm);
690 public void Write (BinaryWriter bw)
692 bw.Write ((byte) 0x2e);
693 MetaData.CompressNum ((uint) permissions.Count, (MemoryStream) bw.BaseStream);
695 foreach (Permission perm in permissions)
696 perm.Write (bw);
701 /**************************************************************************/
702 /// <summary>
703 /// Descriptor for layout information for a field
704 /// </summary>
706 public class FieldLayout : MetaDataElement {
708 Field field;
709 uint offset;
711 internal FieldLayout(Field field, uint offset)
713 this.field = field;
714 this.offset = offset;
715 tabIx = MDTable.FieldLayout;
718 internal sealed override uint Size(MetaData md)
720 return 4 + md.TableIndexSize(MDTable.Field);
723 internal sealed override void Write(FileImage output)
725 output.Write(offset);
726 output.WriteIndex(MDTable.Field,field.Row);
731 /*****************************************************************************/
732 /// <summary>
733 /// Marshalling information for a field or param
734 /// </summary>
735 public class FieldMarshal : MetaDataElement {
737 MetaDataElement field;
738 NativeType nt;
739 uint ntIx;
741 internal FieldMarshal(MetaDataElement field, NativeType nType)
743 this.field = field;
744 this.nt = nType;
745 tabIx = MDTable.FieldMarshal;
748 internal override uint SortKey()
750 return (field.Row << MetaData.CIxShiftMap[(uint)CIx.HasFieldMarshal])
751 | field.GetCodedIx(CIx.HasFieldMarshal);
754 internal sealed override void BuildTables(MetaData md)
756 if (done) return;
757 ntIx = md.AddToBlobHeap(nt.ToBlob());
758 done = true;
761 internal sealed override uint Size(MetaData md)
763 return md.CodedIndexSize(CIx.HasFieldMarshal) + md.BlobIndexSize();
766 internal sealed override void Write(FileImage output)
768 output.WriteCodedIndex(CIx.HasFieldMarshal,field);
769 output.BlobIndex(ntIx);
774 /**************************************************************************/
775 /// <summary>
776 /// Descriptor for the address of a field's value in the PE file
777 /// </summary>
778 public class FieldRVA : MetaDataElement {
780 Field field;
781 DataConstant data;
783 internal FieldRVA(Field field, DataConstant data)
785 this.field = field;
786 this.data = data;
787 tabIx = MDTable.FieldRVA;
790 internal sealed override void BuildTables(MetaData md)
792 if (done) return;
793 md.AddData(data);
794 done = true;
797 internal sealed override uint Size(MetaData md)
799 return 4 + md.TableIndexSize(MDTable.Field);
802 internal sealed override void Write(FileImage output)
804 output.WriteDataRVA(data.DataOffset);
805 output.WriteIndex(MDTable.Field,field.Row);
810 /**************************************************************************/
811 /// <summary>
812 /// Descriptor for a file referenced in THIS assembly/module (.file)
813 /// </summary>
814 public class FileRef : MetaDataElement {
816 private static readonly uint NoMetaData = 0x1;
817 uint nameIx = 0, hashIx = 0;
818 uint flags = 0;
819 protected string name;
821 internal FileRef(string name, byte[] hashBytes, bool metaData,
822 bool entryPoint, MetaData md) {
823 if (!metaData) flags = NoMetaData;
824 if (entryPoint) md.SetEntryPoint(this);
825 this.name = name;
826 nameIx = md.AddToStringsHeap(name);
827 hashIx = md.AddToBlobHeap(hashBytes);
828 tabIx = MDTable.File;
831 internal FileRef(uint nameIx, byte[] hashBytes, bool metaData,
832 bool entryPoint, MetaData md) {
833 if (!metaData) flags = NoMetaData;
834 if (entryPoint) md.SetEntryPoint(this);
835 this.nameIx = nameIx;
836 hashIx = md.AddToBlobHeap(hashBytes);
837 tabIx = MDTable.File;
840 internal sealed override uint Size(MetaData md)
842 return 4 + md.StringsIndexSize() + md.BlobIndexSize();
845 internal sealed override void BuildTables(MetaData md)
847 md.AddToTable(MDTable.File,this);
850 internal sealed override void Write(FileImage output)
852 output.Write(flags);
853 output.StringsIndex(nameIx);
854 output.BlobIndex(hashIx);
857 internal sealed override uint GetCodedIx(CIx code)
859 switch (code) {
860 case (CIx.HasCustomAttr) : return 16;
861 case (CIx.Implementation) : return 0;
863 return 0;
867 /**************************************************************************/
868 /// <summary>
869 /// Descriptor for pinvoke information for a method NOT YET IMPLEMENTED
870 /// </summary>
871 public class ImplMap : MetaDataElement {
873 private static readonly ushort NoMangle = 0x01;
874 ushort flags;
875 Method meth;
876 string importName;
877 uint iNameIx;
878 ModuleRef importScope;
880 internal ImplMap(ushort flag, Method implMeth, string iName, ModuleRef mScope)
882 flags = flag;
883 meth = implMeth;
884 importName = iName;
885 importScope = mScope;
886 tabIx = MDTable.ImplMap;
887 if (iName == null) flags |= NoMangle;
888 //throw(new NotYetImplementedException("PInvoke "));
891 internal override uint SortKey()
893 return (meth.Row << MetaData.CIxShiftMap[(uint)CIx.MemberForwarded])
894 | meth.GetCodedIx(CIx.MemberForwarded);
897 internal sealed override void BuildTables(MetaData md)
899 if (done) return;
900 iNameIx = md.AddToStringsHeap(importName);
901 done = true;
904 internal sealed override uint Size(MetaData md)
906 return 2+ md.CodedIndexSize(CIx.MemberForwarded) +
907 md.StringsIndexSize() + md.TableIndexSize(MDTable.ModuleRef);
910 internal sealed override void Write(FileImage output)
912 output.Write(flags);
913 output.WriteCodedIndex(CIx.MemberForwarded,meth);
914 output.StringsIndex(iNameIx);
915 output.WriteIndex(MDTable.ModuleRef,importScope.Row);
920 /**************************************************************************/
922 public class GenericParameter : MetaDataElement {
924 MetaDataElement owner;
925 MetaData metadata;
926 public string name;
927 uint nameIx;
928 short index;
929 GenericParamAttributes attr;
931 internal GenericParameter (ClassDef owner, MetaData metadata,
932 short index, string name, GenericParamAttributes attr) : this (owner, metadata, index, name, attr, true)
936 internal GenericParameter (MethodDef owner, MetaData metadata,
937 short index, string name, GenericParamAttributes attr) : this (owner, metadata, index, name, attr, true)
941 private GenericParameter (MetaDataElement owner, MetaData metadata,
942 short index, string name, GenericParamAttributes attr, bool nadda) {
943 this.owner = owner;
944 this.metadata = metadata;
945 this.index = index;
946 tabIx = MDTable.GenericParam;
947 this.name = name;
948 this.attr = attr;
951 internal override uint SortKey()
953 return (owner.Row << MetaData.CIxShiftMap[(uint)CIx.TypeOrMethodDef])
954 | owner.GetCodedIx(CIx.TypeOrMethodDef);
957 internal override uint SortKey2 ()
959 return (uint) index;
962 public void AddConstraint (Type constraint)
964 metadata.AddToTable (MDTable.GenericParamConstraint,
965 new GenericParamConstraint (this, constraint));
968 internal sealed override uint Size(MetaData md)
970 return (uint) (4 +
971 md.CodedIndexSize(CIx.TypeOrMethodDef) +
972 md.StringsIndexSize ());
975 internal sealed override void BuildTables(MetaData md)
977 if (done) return;
978 nameIx = md.AddToStringsHeap(name);
979 done = true;
982 internal sealed override void Write(FileImage output)
984 output.Write ((short) index);
985 output.Write ((short) attr);
986 output.WriteCodedIndex(CIx.TypeOrMethodDef, owner);
987 output.StringsIndex (nameIx);
990 internal sealed override uint GetCodedIx(CIx code)
992 switch (code) {
993 case (CIx.HasCustomAttr) : return 19;
995 return 0;
1000 internal class GenericParamConstraint : MetaDataElement {
1002 GenericParameter param;
1003 Type type;
1005 public GenericParamConstraint (GenericParameter param, Type type)
1007 this.param = param;
1008 this.type = type;
1009 tabIx = MDTable.GenericParamConstraint;
1012 internal override uint SortKey()
1014 return param.Row;
1017 internal sealed override uint Size(MetaData md)
1019 return (uint) (md.TableIndexSize(MDTable.GenericParam) +
1020 md.CodedIndexSize(CIx.TypeDefOrRef));
1023 internal sealed override void Write(FileImage output)
1025 output.WriteIndex(MDTable.GenericParam, param.Row);
1026 output.WriteCodedIndex(CIx.TypeDefOrRef, type);
1031 internal class MethodSpec : Method {
1033 Method meth;
1034 GenericMethodSig g_sig;
1035 uint sidx;
1037 internal MethodSpec (Method meth, GenericMethodSig g_sig) : base ("")
1039 this.meth = meth;
1040 this.g_sig = g_sig;
1041 tabIx = MDTable.MethodSpec;
1044 internal override uint GetSigIx (MetaData md)
1046 throw new Exception ("Should not be used.");
1049 public override void AddCallConv (CallConv cconv)
1051 throw new Exception ("Should not be used.");
1054 internal sealed override void BuildTables (MetaData md)
1056 if (done) return;
1057 sidx = g_sig.GetSigIx (md);
1058 done = true;
1061 internal sealed override uint Size (MetaData md)
1063 return (uint) (md.CodedIndexSize(CIx.MethodDefOrRef) +
1064 md.BlobIndexSize ());
1067 internal sealed override void Write (FileImage output)
1069 output.WriteCodedIndex (CIx.MethodDefOrRef, meth);
1070 output.BlobIndex (sidx);
1073 internal sealed override void TypeSig (MemoryStream sig)
1075 throw new Exception ("Should not be used.");
1079 /**************************************************************************/
1080 /// <summary>
1081 /// Descriptor for interface implemented by a class
1082 /// </summary>
1083 public class InterfaceImpl: MetaDataElement {
1085 ClassDef theClass;
1086 Class theInterface;
1088 internal InterfaceImpl(ClassDef theClass, Class theInterface)
1090 this.theClass = theClass;
1091 this.theInterface = theInterface;
1092 tabIx = MDTable.InterfaceImpl;
1095 internal sealed override uint Size(MetaData md)
1097 return md.TableIndexSize(MDTable.TypeDef) +
1098 md.CodedIndexSize(CIx.TypeDefOrRef);
1101 internal sealed override void Write(FileImage output)
1103 output.WriteIndex(MDTable.TypeDef,theClass.Row);
1104 output.WriteCodedIndex(CIx.TypeDefOrRef,theInterface);
1107 internal sealed override uint GetCodedIx(CIx code) { return 5; }
1109 internal override uint SortKey ()
1111 return (theClass.Row << MetaData.CIxShiftMap[(uint)CIx.TypeDefOrRef])
1112 | theClass.GetCodedIx (CIx.TypeDefOrRef);
1117 /**************************************************************************/
1118 /// <summary>
1119 /// Descriptor for resources used in this PE file
1120 /// </summary>
1122 public class ManifestResource : MetaDataElement {
1124 public static readonly uint PublicResource = 0x1;
1125 public static readonly uint PrivateResource = 0x2;
1127 string mrName;
1128 MetaDataElement rRef;
1129 uint fileOffset;
1130 uint nameIx = 0;
1131 uint flags = 0;
1132 byte [] resourceBytes;
1134 public ManifestResource (string name, byte[] resBytes, uint flags)
1136 InitResource (name, flags);
1137 this.resourceBytes = resBytes;
1140 public ManifestResource(string name, uint flags, FileRef fileRef)
1142 InitResource (name, flags);
1143 rRef = fileRef;
1146 public ManifestResource(string name, uint flags, FileRef fileRef,
1147 uint fileIx) {
1148 InitResource (name, flags);
1149 rRef = fileRef;
1150 fileOffset = fileIx;
1153 public ManifestResource(string name, uint flags, AssemblyRef assemRef)
1155 InitResource (name, flags);
1156 rRef = assemRef;
1159 internal ManifestResource (ManifestResource mres)
1161 mrName = mres.mrName;
1162 flags = mres.flags;
1163 rRef = mres.rRef;
1164 fileOffset = mres.fileOffset;
1165 resourceBytes = mres.resourceBytes;
1168 private void InitResource (string name, uint flags)
1170 mrName = name;
1171 this.flags = flags;
1172 tabIx = MDTable.ManifestResource;
1175 internal sealed override void BuildTables(MetaData md)
1177 if (done) return;
1178 md.AddToTable (MDTable.ManifestResource, this);
1179 nameIx = md.AddToStringsHeap(mrName);
1180 if (resourceBytes != null) {
1181 if (rRef != null)
1182 throw new PEFileException ("Manifest Resource has byte value and file reference");
1183 fileOffset = md.AddResource(resourceBytes);
1184 } else {
1185 if (rRef == null)
1186 throw new PEFileException ("Manifest Resource has no implementation or value");
1187 rRef.BuildTables (md);
1190 done = true;
1193 internal sealed override uint Size(MetaData md)
1195 return 8 + md.StringsIndexSize() +
1196 md.CodedIndexSize(CIx.Implementation);
1199 internal sealed override void Write(FileImage output)
1201 output.Write(fileOffset);
1202 output.Write(flags);
1203 output.StringsIndex(nameIx);
1204 output.WriteCodedIndex(CIx.Implementation,rRef);
1207 internal sealed override uint GetCodedIx(CIx code) { return 18; }
1209 public string Name {
1210 get { return mrName; }
1211 set { mrName = value; }
1215 /**************************************************************************/
1216 /// <summary>
1217 /// Base class for elements in the PropertyMap, EventMap and
1218 /// NestedClass MetaData tables
1219 /// </summary>
1220 public class MapElem : MetaDataElement {
1222 ClassDef parent;
1223 uint elemIx;
1224 MDTable elemTable;
1226 internal MapElem(ClassDef par, uint elIx, MDTable elemTab)
1228 parent = par;
1229 elemIx = elIx;
1230 elemTable = elemTab;
1233 internal sealed override uint Size(MetaData md)
1235 return md.TableIndexSize(MDTable.TypeDef) + md.TableIndexSize(elemTable);
1238 internal sealed override void Write(FileImage output)
1240 output.WriteIndex(MDTable.TypeDef,parent.Row);
1241 output.WriteIndex(elemTable,elemIx);
1245 /**************************************************************************/
1246 /// <summary>
1247 /// Descriptor for an overriding method (.override)
1248 /// </summary>
1249 public class MethodImpl : MetaDataElement {
1251 ClassDef parent;
1252 Method header, body;
1254 internal MethodImpl(ClassDef par, Method decl, Method bod)
1256 parent = par;
1257 header = decl;
1258 body = bod;
1259 tabIx = MDTable.MethodImpl;
1262 internal sealed override uint Size(MetaData md)
1264 return md.TableIndexSize(MDTable.TypeDef) + 2 * md.CodedIndexSize(CIx.MethodDefOrRef);
1267 internal sealed override void Write(FileImage output)
1269 output.WriteIndex(MDTable.TypeDef,parent.Row);
1270 output.WriteCodedIndex(CIx.MethodDefOrRef,body);
1271 output.WriteCodedIndex(CIx.MethodDefOrRef,header);
1276 /**************************************************************************/
1277 /// <summary>
1278 /// Descriptor for Property and Event methods
1279 /// </summary>
1280 public class MethodSemantics : MetaDataElement {
1282 Feature.MethodType type;
1283 MethodDef meth;
1284 Feature eventOrProp;
1286 internal MethodSemantics(Feature.MethodType mType, MethodDef method, Feature feature)
1288 type = mType;
1289 meth = method;
1290 eventOrProp = feature;
1291 tabIx = MDTable.MethodSemantics;
1294 internal override uint SortKey()
1296 return (eventOrProp.Row << MetaData.CIxShiftMap [(uint)CIx.HasSemantics])
1297 | eventOrProp.GetCodedIx (CIx.HasSemantics);
1300 internal sealed override uint Size(MetaData md)
1302 return 2 + md.TableIndexSize(MDTable.Method) + md.CodedIndexSize(CIx.HasSemantics);
1305 internal sealed override void Write(FileImage output)
1307 output.Write((ushort)type);
1308 output.WriteIndex(MDTable.Method,meth.Row);
1309 output.WriteCodedIndex(CIx.HasSemantics,eventOrProp);
1314 /**************************************************************************/
1315 /// <summary>
1316 /// Descriptor for a parameter of a method defined in this assembly/module
1317 /// </summary>
1318 public class Param : MetaDataElement {
1321 Type pType;
1322 string pName;
1323 internal ushort seqNo = 0;
1324 ushort parMode;
1325 ConstantElem defaultVal;
1326 uint nameIx = 0;
1327 FieldMarshal marshalInfo;
1329 /// <summary>
1330 /// Create a new parameter for a method
1331 /// </summary>
1332 /// <param name="mode">param mode (in, out, opt)</param>
1333 /// <param name="parName">parameter name</param>
1334 /// <param name="parType">parameter type</param>
1335 public Param(ParamAttr mode, string parName, Type parType)
1337 pName = parName;
1338 pType = parType;
1339 parMode = (ushort)mode;
1340 tabIx = MDTable.Param;
1343 public bool HasMarshalInfo {
1344 get { return marshalInfo != null; }
1347 /// <summary>
1348 /// Add a default value to this parameter
1349 /// </summary>
1350 /// <param name="c">the default value for the parameter</param>
1351 public void AddDefaultValue(Constant cVal)
1353 defaultVal = new ConstantElem(this,cVal);
1354 parMode |= (ushort) ParamAttr.HasDefault;
1357 /// <summary>
1358 /// Add marshalling information about this parameter
1359 /// </summary>
1360 public void AddMarshallInfo(NativeType marshallType)
1362 parMode |= (ushort) ParamAttr.HasFieldMarshal;
1363 marshalInfo = new FieldMarshal(this,marshallType);
1366 internal Type GetParType() { return pType; }
1368 internal sealed override void BuildTables(MetaData md)
1370 if (done) return;
1371 nameIx = md.AddToStringsHeap(pName);
1372 if (defaultVal != null) {
1373 md.AddToTable(MDTable.Constant,defaultVal);
1374 defaultVal.BuildTables(md);
1376 if (marshalInfo != null) {
1377 md.AddToTable(MDTable.FieldMarshal,marshalInfo);
1378 marshalInfo.BuildTables(md);
1380 done = true;
1383 internal void TypeSig(MemoryStream str)
1385 pType.TypeSig(str);
1388 internal sealed override uint Size(MetaData md)
1390 return 4 + md.StringsIndexSize();
1393 internal sealed override void Write(FileImage output)
1395 output.Write(parMode);
1396 output.Write(seqNo);
1397 output.StringsIndex(nameIx);
1400 internal sealed override uint GetCodedIx(CIx code)
1402 switch (code) {
1403 case (CIx.HasCustomAttr) : return 4;
1404 case (CIx.HasConst) : return 1;
1405 case (CIx.HasFieldMarshal) : return 1;
1407 return 0;
1412 /**************************************************************************/
1413 public abstract class Signature : MetaDataElement {
1415 protected uint sigIx;
1417 internal Signature()
1419 tabIx = MDTable.StandAloneSig;
1422 internal sealed override uint Size(MetaData md)
1424 return md.BlobIndexSize();
1427 internal sealed override void Write(FileImage output)
1429 output.BlobIndex(sigIx);
1432 internal sealed override uint GetCodedIx(CIx code) { return (uint)tabIx; }
1436 /**************************************************************************/
1437 public class TypeSpec : MetaDataElement {
1438 uint sigIx = 0;
1440 internal TypeSpec(Type aType, MetaData md)
1442 MemoryStream sig = new MemoryStream();
1443 aType.TypeSig(sig);
1444 sigIx = md.AddToBlobHeap(sig.ToArray());
1445 tabIx = MDTable.TypeSpec;
1448 internal sealed override uint GetCodedIx(CIx code)
1450 switch (code) {
1451 case (CIx.TypeDefOrRef) : return 2;
1452 case (CIx.HasCustomAttr) : return 13;
1453 case (CIx.MemberRefParent) : return 4;
1455 return 0;
1458 internal override uint Size(MetaData md)
1460 return md.BlobIndexSize();
1463 internal sealed override void Write(FileImage output)
1465 //Console.WriteLine("Writing the blob index for a TypeSpec");
1466 output.BlobIndex(sigIx);
1471 /**************************************************************************/
1472 /// <summary>
1473 /// Base class for all IL types
1474 /// </summary>
1475 public abstract class Type : MetaDataElement {
1476 protected byte typeIndex;
1477 protected TypeSpec typeSpec;
1479 internal Type(byte tyIx) { typeIndex = tyIx; }
1481 internal byte GetTypeIndex() { return typeIndex; }
1482 internal void SetTypeIndex (byte b) { typeIndex = b; }
1484 internal virtual MetaDataElement GetTypeSpec(MetaData md)
1486 if (typeSpec == null) {
1487 typeSpec = new TypeSpec(this,md);
1488 md.AddToTable(MDTable.TypeSpec,typeSpec);
1490 return typeSpec;
1493 internal virtual void TypeSig(MemoryStream str)
1495 throw(new TypeSignatureException(this.GetType().AssemblyQualifiedName +
1496 " doesn't have a type signature!!"));
1500 public class ClassRefInst : Type {
1502 private Type type;
1503 private bool is_value;
1505 public ClassRefInst (Type type, bool is_value) : base (PrimitiveType.Class.GetTypeIndex ())
1507 this.type = type;
1508 this.is_value = is_value;
1509 if (is_value)
1510 typeIndex = PrimitiveType.ValueType.GetTypeIndex ();
1511 tabIx = MDTable.TypeSpec;
1514 internal sealed override void TypeSig(MemoryStream str)
1516 type.TypeSig (str);
1520 /**************************************************************************/
1521 /// <summary>
1522 /// The base descriptor for a class
1523 /// </summary>
1524 public abstract class Class : Type {
1526 protected int row = 0;
1527 public string name, nameSpace;
1528 protected uint nameIx, nameSpaceIx;
1529 protected MetaData _metaData;
1530 internal Class(string nameSpaceName, string className, MetaData md)
1531 : base(PrimitiveType.Class.GetTypeIndex ())
1533 nameSpace = nameSpaceName;
1534 name = className;
1535 nameIx = md.AddToStringsHeap(name);
1536 nameSpaceIx = md.AddToStringsHeap(nameSpace);
1537 _metaData = md;
1540 internal Class(uint nsIx, uint nIx) : base(PrimitiveType.Class.GetTypeIndex ())
1542 nameSpaceIx = nsIx;
1543 nameIx = nIx;
1546 internal Class (byte typeIndex) : base (typeIndex)
1548 nameSpace = "Should not be used";
1549 name = "Should not be used";
1552 internal virtual uint TypeDefOrRefToken() { return 0; }
1554 internal virtual void MakeValueClass(ValueClass vClass)
1556 typeIndex = PrimitiveType.ValueType.GetTypeIndex ();
1559 internal virtual string TypeName()
1561 return (nameSpace + "." + name);
1564 internal override MetaDataElement GetTypeSpec(MetaData md)
1566 return this;
1570 /**************************************************************************/
1571 // This Class produces entries in the TypeDef table of the MetaData
1572 // in the PE meta data.
1574 // NOTE: Entry 0 in TypeDef table is always the pseudo class <module>
1575 // which is the parent for functions and variables declared a module level
1577 /// <summary>
1578 /// The descriptor for a class defined in the IL (.class) in the current assembly/module
1579 /// </summary>
1580 ///
1581 public class ClassDef : Class {
1583 private static readonly byte ElementType_Class = 0x12;
1585 Class superType;
1586 ArrayList fields = new ArrayList();
1587 ArrayList methods = new ArrayList();
1588 ArrayList events;
1589 ArrayList properties;
1590 bool typeIndexChecked = true;
1591 uint fieldIx = 0, methodIx = 0;
1592 byte[] securityActions;
1593 uint flags;
1594 ClassLayout layout;
1595 ClassDef parentClass;
1596 MetaData metaData;
1598 internal ClassDef(TypeAttr attrSet, string nsName, string name,
1599 MetaData md) : base(nsName, name, md)
1601 metaData = md;
1602 if (! ((nsName == "" && name == "<Module>") || (nsName == "System" && name == "Object")) ) {
1603 superType = metaData.mscorlib.GetSpecialSystemClass(PrimitiveType.Object);
1605 flags = (uint)attrSet;
1606 tabIx = MDTable.TypeDef;
1609 internal void SetSuper(Class sClass)
1611 superType = sClass;
1612 if (! (sClass is GenericTypeInst))
1613 typeIndexChecked = false;
1616 internal override void MakeValueClass(ValueClass vClass)
1618 if (vClass == ValueClass.Enum)
1619 superType = metaData.mscorlib.EnumType();
1620 else
1621 superType = metaData.mscorlib.ValueType();
1623 typeIndex = PrimitiveType.ValueType.GetTypeIndex ();
1626 public void SpecialNoSuper()
1628 superType = null;
1631 /// <summary>
1632 /// Add an attribute to this class
1633 /// </summary>
1634 /// <param name="ta">the attribute to be added</param>
1635 public void AddAttribute(TypeAttr ta)
1637 flags |= (uint)ta;
1640 /// <summary>
1641 /// Add an interface that is implemented by this class
1642 /// </summary>
1643 /// <param name="iFace">the interface that is implemented</param>
1644 public void AddImplementedInterface(Class iFace)
1646 metaData.AddToTable(MDTable.InterfaceImpl,new InterfaceImpl(this,iFace));
1649 /// <summary>
1650 /// Add a named generic type parameter
1651 /// </summary>
1652 public GenericParameter AddGenericParameter (short index, string name)
1654 return AddGenericParameter (index, name, 0);
1657 /// <summary>
1658 /// Add a named generic type parameter with attributes
1659 /// </summary>
1660 public GenericParameter AddGenericParameter (short index, string name, GenericParamAttributes attr)
1662 GenericParameter gp = new GenericParameter (this, metaData, index, name, attr);
1663 metaData.AddToTable (MDTable.GenericParam, gp);
1664 return gp;
1667 /// <summary>
1668 /// Add a field to this class
1669 /// </summary>
1670 /// <param name="name">field name</param>
1671 /// <param name="fType">field type</param>
1672 /// <returns>a descriptor for this new field</returns>
1673 public FieldDef AddField(string name, Type fType)
1675 FieldDef field = new FieldDef(name,fType);
1676 fields.Add(field);
1677 return field;
1680 /// <summary>
1681 /// Add a field to this class
1682 /// </summary>
1683 /// <param name="fAtts">attributes for this field</param>
1684 /// <param name="name">field name</param>
1685 /// <param name="fType">field type</param>
1686 /// <returns>a descriptor for this new field</returns>
1687 public FieldDef AddField(FieldAttr fAtts, string name, Type fType)
1689 FieldDef field = new FieldDef(fAtts,name,fType);
1690 fields.Add(field);
1691 return field;
1694 public void SetFieldOrder (ArrayList fields)
1696 this.fields = fields;
1699 /// <summary>
1700 /// Add a method to this class
1701 /// </summary>
1702 /// <param name="name">method name</param>
1703 /// <param name="retType">return type</param>
1704 /// <param name="pars">parameters</param>
1705 /// <returns>a descriptor for this new method</returns>
1706 public MethodDef AddMethod(string name, Type retType, Param[] pars)
1708 return AddMethod (name, new Param (ParamAttr.Default, "", retType), pars);
1711 public MethodDef AddMethod (string name, Param ret_param, Param [] pars)
1713 // Console.WriteLine("Adding method " + name + " to class " + this.name);
1714 MethodDef meth = new MethodDef(metaData,name, ret_param, pars);
1715 methods.Add(meth);
1716 return meth;
1719 /// <summary>
1720 /// Add a method to this class
1721 /// </summary>
1722 /// <param name="mAtts">attributes for this method</param>
1723 /// <param name="iAtts">implementation attributes for this method</param>
1724 /// <param name="name">method name</param>
1725 /// <param name="retType">return type</param>
1726 /// <param name="pars">parameters</param>
1727 /// <returns>a descriptor for this new method</returns>
1728 public MethodDef AddMethod(MethAttr mAtts, ImplAttr iAtts, string name,
1729 Param ret_param, Param [] pars) {
1730 // Console.WriteLine("Adding method " + name + " to class " + this.name);
1731 MethodDef meth = new MethodDef (metaData, mAtts, iAtts, name, ret_param, pars);
1732 methods.Add(meth);
1733 return meth;
1736 /// <summary>
1737 /// Add an event to this class
1738 /// </summary>
1739 /// <param name="name">event name</param>
1740 /// <param name="eType">event type</param>
1741 /// <returns>a descriptor for this new event</returns>
1742 public Event AddEvent(string name, Type eType)
1744 Event e = new Event(name,eType,this);
1745 if (events == null) events = new ArrayList();
1746 events.Add(e);
1747 return e;
1750 /// <summary>
1751 /// Add a property to this class
1752 /// </summary>
1753 /// <param name="name">property name</param>
1754 /// <param name="propType">property type</param>
1755 /// <returns>a descriptor for this new property</returns>
1756 public Property AddProperty(string name, Type retType, Type[] pars)
1758 Property p = new Property(name, retType, pars, this);
1759 if (properties == null) properties = new ArrayList();
1760 properties.Add(p);
1761 return p;
1764 /// <summary>
1765 /// Add a nested class to this class
1766 /// </summary>
1767 /// <param name="attrSet">attributes for this nested class</param>
1768 /// <param name="nsName">nested name space name</param>
1769 /// <param name="name">nested class name</param>
1770 /// <returns>a descriptor for this new nested class</returns>
1771 public ClassDef AddNestedClass(TypeAttr attrSet, string nsName,
1772 string name) {
1773 ClassDef nClass = new ClassDef(attrSet,"",name,metaData);
1774 metaData.AddToTable(MDTable.TypeDef,nClass);
1775 metaData.AddToTable(MDTable.NestedClass,new MapElem(nClass,Row,MDTable.TypeDef));
1776 nClass.parentClass = this;
1777 return (nClass);
1780 public static bool IsValueType (Class type)
1782 return IsValueType (type.nameSpace, type.name);
1785 public static bool IsEnum (Class type)
1787 return IsEnum (type.nameSpace, type.name);
1790 public static bool IsValueType (string nsName, string name)
1792 return (nsName == "System" && name == "ValueType");
1795 public static bool IsEnum (string nsName, string name)
1797 return (nsName == "System" && name == "Enum");
1800 /// <summary>
1801 /// Add a nested class to this class
1802 /// </summary>
1803 /// <param name="attrSet">attributes for this nested class</param>
1804 /// <param name="nsName">nested name space name</param>
1805 /// <param name="name">nested class name</param>
1806 /// <param name="sType">super type of this nested class</param>
1807 /// <returns>a descriptor for this new nested class</returns>
1808 public ClassDef AddNestedClass(TypeAttr attrSet, string nsName,
1809 string name, Class sType) {
1810 ClassDef nClass = AddNestedClass (attrSet, nsName, name);
1811 nClass.SetSuper(sType);
1812 if (ClassDef.IsValueType (sType))
1813 nClass.MakeValueClass (ValueClass.ValueType);
1814 else
1815 if (ClassDef.IsEnum (sType))
1816 nClass.MakeValueClass (ValueClass.Enum);
1818 if (ClassDef.IsValueType (sType) || ClassDef.IsEnum (sType))
1819 nClass.SetTypeIndex (PrimitiveType.ValueType.GetTypeIndex ());
1821 nClass.typeIndexChecked = true;
1822 return (nClass);
1825 /// <summary>
1826 /// Add layout information for this class. This class must have the
1827 /// sequential or explicit attribute.
1828 /// </summary>
1829 /// <param name="packSize">packing size (.pack)</param>
1830 /// <param name="classSize">class size (.size)</param>
1831 public void AddLayoutInfo (int packSize, int classSize)
1833 layout = new ClassLayout(packSize,classSize,this);
1836 /// <summary>
1837 /// Use a method as the implementation for another method (.override)
1838 /// </summary>
1839 /// <param name="decl">the method to be overridden</param>
1840 /// <param name="body">the implementation to be used</param>
1841 public void AddMethodOverride(Method decl, Method body)
1843 metaData.AddToTable(MDTable.MethodImpl,new MethodImpl(this,decl,body));
1846 /// <summary>
1847 /// Add security to this class NOT YET IMPLEMENTED
1848 /// </summary>
1849 /// <param name="permissionSet"></param>
1850 public void AddSecurity(byte[] permissionSet)
1852 throw(new NotYetImplementedException("Class security "));
1853 //flags |= HasSecurity;
1854 // securityActions = permissionSet;
1857 //public void AddLineInfo(int row, int col) { }
1859 internal void CheckTypeIndex()
1861 if (typeIndexChecked) return;
1862 if (superType is ClassDef)
1863 ((ClassDef)superType).CheckTypeIndex();
1864 typeIndex = superType.GetTypeIndex();
1865 typeIndexChecked = true;
1868 internal sealed override void BuildTables(MetaData md)
1870 if (done) return;
1871 if ((flags & (uint)TypeAttr.Interface) != 0) { superType = null; }
1872 // Console.WriteLine("Building tables for " + name);
1873 if (layout != null) md.AddToTable(MDTable.ClassLayout,layout);
1874 // Console.WriteLine("adding methods " + methods.Count);
1875 methodIx = md.TableIndex(MDTable.Method);
1876 for (int i=0; i < methods.Count; i++) {
1877 md.AddToTable(MDTable.Method,(MetaDataElement)methods[i]);
1878 ((MethodDef)methods[i]).BuildTables(md);
1880 // Console.WriteLine("adding fields");
1881 fieldIx = md.TableIndex(MDTable.Field);
1882 for (int i=0; i < fields.Count; i++) {
1883 md.AddToTable(MDTable.Field,(MetaDataElement)fields[i]);
1884 ((FieldDef)fields[i]).BuildTables(md);
1886 // Console.WriteLine("adding events and properties");
1887 if (events != null) {
1888 for (int i=0; i < events.Count; i++) {
1889 md.AddToTable(MDTable.Event,(Event)events[i]);
1890 ((Event)events[i]).BuildTables(md);
1892 md.AddToTable(MDTable.EventMap,
1893 new MapElem(this,((Event)events[0]).Row,MDTable.Event));
1895 if (properties != null) {
1896 for (int i=0; i < properties.Count; i++) {
1897 md.AddToTable(MDTable.Property,(Property)properties[i]);
1898 ((Property)properties[i]).BuildTables(md);
1900 md.AddToTable(MDTable.PropertyMap,new MapElem(this,
1901 ((Property)properties[0]).Row,MDTable.Property));
1903 // Console.WriteLine("End of building tables");
1904 done = true;
1907 internal sealed override uint Size(MetaData md)
1909 return 4 + 2 * md.StringsIndexSize() +
1910 md.CodedIndexSize(CIx.TypeDefOrRef) +
1911 md.TableIndexSize(MDTable.Field) +
1912 md.TableIndexSize(MDTable.Method);
1915 internal sealed override void Write(FileImage output)
1917 output.Write(flags);
1918 output.StringsIndex(nameIx);
1919 output.StringsIndex(nameSpaceIx);
1920 //if (superType != null)
1921 // Console.WriteLine("getting coded index for superType of " + name + " = " + superType.GetCodedIx(CIx.TypeDefOrRef));
1922 output.WriteCodedIndex(CIx.TypeDefOrRef,superType);
1923 output.WriteIndex(MDTable.Field,fieldIx);
1924 output.WriteIndex(MDTable.Method,methodIx);
1927 internal sealed override uint TypeDefOrRefToken()
1929 uint cIx = Row;
1930 cIx = cIx << 2;
1931 return cIx;
1934 internal sealed override void TypeSig(MemoryStream sig)
1936 if (!typeIndexChecked) CheckTypeIndex();
1937 sig.WriteByte(GetTypeIndex());
1938 MetaData.CompressNum(TypeDefOrRefToken(),sig);
1941 internal sealed override uint GetCodedIx(CIx code)
1943 switch (code) {
1944 case (CIx.TypeDefOrRef) : return 0;
1945 case (CIx.HasCustomAttr) : return 3;
1946 case (CIx.HasDeclSecurity) : return 0;
1947 case (CIx.TypeOrMethodDef) : return 0;
1949 return 0;
1954 /**************************************************************************/
1955 /// <summary>
1956 /// Descriptor for a class/interface declared in another module of THIS
1957 /// assembly, or in another assembly.
1958 /// </summary>
1959 public class ClassRef : Class, IExternRef, IResolutionScope {
1961 protected IResolutionScope parent;
1962 ExternClass externClass;
1963 protected MetaData metaData;
1965 internal ClassRef(string nsName, string name, MetaData md) : base(nsName, name, md)
1967 metaData = md;
1968 tabIx = MDTable.TypeRef;
1971 /// <summary>
1972 /// Add a method to this class
1973 /// </summary>
1974 /// <param name="name">method name</param>
1975 /// <param name="retType">return type</param>
1976 /// <param name="pars">parameter types</param>
1977 /// <returns>a descriptor for this method</returns>
1978 public MethodRef AddMethod(string name, Type retType, Type[] pars)
1980 return AddMethod (name, retType, pars, 0);
1983 /// <summary>
1984 /// Add a method to this class
1985 /// </summary>
1986 /// <param name="name">method name</param>
1987 /// <param name="retType">return type</param>
1988 /// <param name="pars">parameter types</param>
1989 /// <param name="gen_param_count">num of generic parameters</param>
1990 /// <returns>a descriptor for this method</returns>
1991 public MethodRef AddMethod (string name, Type retType, Type[] pars, int gen_param_count)
1993 MethodRef meth = new MethodRef (this, name, retType, pars, false, null, gen_param_count);
1994 metaData.AddToTable(MDTable.MemberRef,meth);
1995 return meth;
1998 /// <summary>
1999 /// Add a method to this class
2000 /// </summary>
2001 /// <param name="name">method name</param>
2002 /// <param name="retType">return type</param>
2003 /// <param name="pars">parameter types</param>
2004 /// <returns>a descriptor for this method</returns>
2005 public MethodRef AddVarArgMethod(string name, Type retType,
2006 Type[] pars, Type[] optPars)
2008 MethodRef meth = new MethodRef(this,name,retType,pars,true,optPars, 0);
2009 metaData.AddToTable(MDTable.MemberRef,meth);
2010 return meth;
2013 /// <summary>
2014 /// Add a field to this class
2015 /// </summary>
2016 /// <param name="name">field name</param>
2017 /// <param name="fType">field type</param>
2018 /// <returns>a descriptor for this field</returns>
2019 public FieldRef AddField(string name, Type fType)
2021 FieldRef field = new FieldRef(this,name,fType);
2022 metaData.AddToTable(MDTable.MemberRef,field);
2023 return field;
2026 public ClassRef AddClass (string nsName, string name)
2028 ClassRef aClass = new ClassRef(nsName,name,metaData);
2029 metaData.AddToTable(MDTable.TypeRef,aClass);
2030 aClass.SetParent(this);
2031 return aClass;
2034 public ClassRef AddValueClass (string nsName, string name)
2036 ClassRef aClass = AddClass (nsName, name);
2037 aClass.MakeValueClass (ValueClass.ValueType);
2038 return aClass;
2041 internal void SetParent(IResolutionScope par)
2043 parent = par;
2046 internal override string TypeName()
2048 if ((parent != null) && (parent is AssemblyRef))
2049 return (nameSpace + "." + name + ", " + ((AssemblyRef)parent).TypeName());
2050 else
2051 return (nameSpace + name);
2054 internal sealed override uint Size(MetaData md)
2056 return md.CodedIndexSize(CIx.ResolutionScope) + 2 *
2057 md.StringsIndexSize();
2060 internal sealed override void Write(FileImage output)
2062 output.WriteCodedIndex(CIx.ResolutionScope,(MetaDataElement) parent);
2063 output.StringsIndex(nameIx);
2064 output.StringsIndex(nameSpaceIx);
2067 internal override sealed uint TypeDefOrRefToken()
2069 uint cIx = Row;
2070 cIx = (cIx << 2) | 0x1;
2071 return cIx;
2074 internal override void TypeSig(MemoryStream sig)
2076 sig.WriteByte(GetTypeIndex());
2077 MetaData.CompressNum(TypeDefOrRefToken(),sig);
2080 internal sealed override uint GetCodedIx(CIx code)
2082 switch (code) {
2083 case (CIx.TypeDefOrRef) : return 1;
2084 case (CIx.HasCustomAttr) : return 2;
2085 case (CIx.MemberRefParent) : return 1;
2086 case (CIx.ResolutionScope) : return 3;
2088 return 0;
2093 /**************************************************************************/
2094 public class ExternClassRef : ClassRef {
2096 ExternClass externClass;
2098 internal ExternClassRef(TypeAttr attrs, string nsName, string name,
2099 FileRef declFile, MetaData md) : base(nsName,name,md)
2101 externClass = new ExternClass(attrs,nameSpaceIx,nameIx,declFile);
2102 metaData.AddToTable(MDTable.ExportedType,externClass);
2105 internal ExternClassRef(string name, MetaData md) : base(null,name,md)
2109 public ClassRef AddNestedClass(TypeAttr attrs, string name)
2111 ExternClassRef nestedClass = new ExternClassRef(name,metaData);
2112 externClass = new ExternClass(attrs,0,nameIx,this.externClass);
2113 metaData.AddToTable(MDTable.ExportedType,externClass);
2114 return nestedClass;
2119 /**************************************************************************/
2120 /// <summary>
2121 /// Descriptor for a class defined in another module of THIS assembly
2122 /// and exported (.class extern)
2123 /// </summary>
2125 internal class ExternClass : Class {
2127 MetaDataElement parent;
2128 uint flags;
2130 internal ExternClass(TypeAttr attr, uint nsIx, uint nIx,
2131 MetaDataElement paren) : base(nsIx,nIx)
2133 flags = (uint)attr;
2134 parent = paren;
2135 tabIx = MDTable.ExportedType;
2138 internal sealed override uint Size(MetaData md)
2140 return 8 + 2* md.StringsIndexSize() + md.CodedIndexSize(CIx.Implementation);
2143 internal sealed override void Write(FileImage output)
2145 output.Write(flags);
2146 output.Write(0);
2147 output.StringsIndex(nameIx);
2148 output.StringsIndex(nameSpaceIx);
2149 output.WriteCodedIndex(CIx.Implementation,parent);
2152 internal sealed override uint GetCodedIx(CIx code)
2154 switch (code) {
2155 case (CIx.HasCustomAttr) : return 17;
2156 case (CIx.Implementation) : return 2;
2158 return 0;
2163 public class GenParam : Class {
2165 private int index;
2166 private string param_name;
2167 private uint sigIx = 0;
2169 public GenParam (int index, string name, GenParamType ptype) : base ((byte) ptype)
2171 this.index = index;
2172 this.param_name = name;
2173 tabIx = MDTable.TypeSpec;
2176 public int Index {
2177 get { return index; }
2178 set { index = value; }
2181 public string Name {
2182 get { return param_name; }
2183 set { param_name = value; }
2186 public GenParamType Type {
2187 get { return (GenParamType) GetTypeIndex (); }
2190 internal sealed override void BuildTables (MetaData md)
2192 if (done)
2193 return;
2194 MemoryStream str = new MemoryStream ();
2195 TypeSig (str);
2196 sigIx = md.AddToBlobHeap (str.ToArray ());
2198 done = true;
2201 internal sealed override void TypeSig(MemoryStream str)
2203 if (index < 0)
2204 throw new PEFileException (String.Format ("Unresolved {0} - {1}", (GenParamType) GetTypeIndex (), param_name));
2205 str.WriteByte(typeIndex);
2206 MetaData.CompressNum ((uint) index, str);
2209 internal override uint Size(MetaData md)
2211 return md.BlobIndexSize();
2214 internal sealed override void Write (FileImage output)
2216 output.BlobIndex (sigIx);
2219 internal sealed override uint GetCodedIx(CIx code)
2221 switch (code) {
2222 case (CIx.TypeDefOrRef) : return 2;
2223 case (CIx.HasCustomAttr) : return 13;
2224 case (CIx.MemberRefParent) : return 4;
2226 return 0;
2230 public class GenericTypeInst : Class {
2232 private Type gen_type;
2233 private Type[] gen_param;
2234 bool inTable = false;
2235 uint sigIx = 0;
2237 public GenericTypeInst (Type gen_type, Type[] gen_param)
2238 : base ((byte) PrimitiveType.GenericInst.GetTypeIndex ())
2240 this.gen_type = gen_type;
2241 this.gen_param = gen_param;
2242 tabIx = MDTable.TypeSpec;
2245 internal override MetaDataElement GetTypeSpec (MetaData md)
2247 if (!inTable) {
2248 md.AddToTable (MDTable.TypeSpec, this);
2249 inTable = true;
2252 return this;
2255 internal sealed override void TypeSig(MemoryStream str)
2257 str.WriteByte(typeIndex);
2258 gen_type.TypeSig (str);
2259 MetaData.CompressNum ((uint) gen_param.Length, str);
2260 foreach (Type param in gen_param)
2261 param.TypeSig (str);
2264 internal sealed override void BuildTables (MetaData md)
2266 if (done)
2267 return;
2268 MemoryStream str = new MemoryStream ();
2269 TypeSig (str);
2270 sigIx = md.AddToBlobHeap (str.ToArray ());
2272 done = true;
2275 internal sealed override uint Size (MetaData md)
2277 return md.BlobIndexSize ();
2280 internal sealed override void Write (FileImage output)
2282 output.BlobIndex (sigIx);
2285 internal sealed override uint GetCodedIx (CIx code)
2287 switch (code) {
2288 case (CIx.TypeDefOrRef): return 2;
2289 case (CIx.MemberRefParent): return 4;
2290 case (CIx.HasCustomAttr): return 13;
2292 return 0;
2296 public class GenericMethodSig {
2298 private Type[] gen_param;
2299 private bool done;
2300 private uint sigIx = 0;
2302 public GenericMethodSig (Type[] gen_param)
2304 this.gen_param = gen_param;
2305 done = false;
2308 internal void TypeSig (MemoryStream str)
2310 str.WriteByte (0x0A); /* GENERIC_INST */
2311 MetaData.CompressNum ((uint) gen_param.Length, str);
2312 foreach (Type param in gen_param)
2313 param.TypeSig (str);
2316 internal uint GetSigIx (MetaData md)
2318 if (done)
2319 return sigIx;
2321 MemoryStream sig = new MemoryStream();
2322 TypeSig (sig);
2323 sigIx = md.AddToBlobHeap (sig.ToArray());
2324 done = true;
2325 return sigIx;
2329 public class Sentinel : Type {
2331 public Sentinel () : base (0x41) { }
2333 internal sealed override void TypeSig(MemoryStream str)
2335 str.WriteByte(typeIndex);
2339 /**************************************************************************/
2340 /// <summary>
2341 /// Descriptor for a FunctionPointer type
2342 /// </summary>
2343 ///
2344 public class MethPtrType : Type {
2346 bool varArgMeth;
2347 Type retType;
2348 Type [] parList;
2349 Type [] optParList;
2350 CallConv callConv;
2351 uint numPars;
2352 uint numOptPars;
2353 uint sigIx = 0;
2355 /// <summary>
2356 /// Create a new function pointer type
2357 /// </summary>
2358 /// <param name="meth">the function to be referenced</param>
2359 public MethPtrType (CallConv callconv, Type retType, Type[] pars,
2360 bool varArgMeth, Type[] optPars) : base(0x1B)
2362 this.retType = retType;
2363 callConv = callconv;
2364 parList = pars;
2365 this.varArgMeth = varArgMeth;
2366 if (parList != null) numPars = (uint)parList.Length;
2367 if (varArgMeth) {
2368 optParList = optPars;
2369 if (optParList != null) numOptPars = (uint)optParList.Length;
2370 callConv |= CallConv.Vararg;
2372 tabIx = MDTable.TypeSpec;
2375 internal sealed override void TypeSig(MemoryStream sig)
2377 sig.WriteByte(typeIndex);
2378 // Bootlegged from method ref
2379 sig.WriteByte((byte)callConv);
2380 MetaData.CompressNum (numPars + numOptPars, sig);
2381 retType.TypeSig (sig);
2382 for (int i=0; i < numPars; i++) {
2383 parList[i].TypeSig (sig);
2385 if (varArgMeth) {
2386 sig.WriteByte (0x41); // Write the sentinel
2387 for (int i=0; i < numOptPars; i++) {
2388 optParList[i].TypeSig (sig);
2393 internal sealed override void BuildTables(MetaData md)
2395 if (done) return;
2396 MemoryStream sig = new MemoryStream();
2397 TypeSig(sig);
2398 sigIx = md.AddToBlobHeap(sig.ToArray());
2399 done = true;
2402 internal sealed override uint Size(MetaData md)
2404 return md.BlobIndexSize();
2407 internal sealed override void Write(FileImage output)
2409 output.BlobIndex(sigIx);
2412 internal sealed override uint GetCodedIx(CIx code) { return 0x1B; }
2416 #region Array Types
2417 /* Classes for Arrays */
2419 /// <summary>
2420 /// The IL Array type
2421 /// </summary>
2422 public abstract class Array : Type {
2424 protected Type elemType;
2425 protected MetaData metaData;
2426 protected string cnameSpace, cname;
2428 internal Array(Type eType, byte TypeId) : base(TypeId)
2430 elemType = eType;
2431 tabIx = MDTable.TypeSpec;
2435 /// <summary>
2436 /// Single dimensional array with zero lower bound
2437 /// </summary>
2438 public class ZeroBasedArray : Array {
2440 /// <summary>
2441 /// Create a new array - elementType[]
2442 /// </summary>
2443 /// <param name="elementType">the type of the array elements</param>
2444 public ZeroBasedArray(Type elementType) : base (elementType, PrimitiveType.SZArray.GetTypeIndex ()) { }
2446 internal sealed override void TypeSig(MemoryStream str)
2448 str.WriteByte(typeIndex);
2449 elemType.TypeSig(str);
2454 /// <summary>
2455 /// Multi dimensional array with explicit bounds
2456 /// </summary>
2457 public class BoundArray : Array {
2458 int[] lowerBounds;
2459 int[] sizes;
2460 uint numDims;
2462 /// <summary>
2463 /// Create a new multi dimensional array type
2464 /// eg. elemType[1..5,3..10,5,,] would be
2465 /// new BoundArray(elemType,5,[1,3,0],[5,10,4])
2466 /// </summary>
2467 /// <param name="elementType">the type of the elements</param>
2468 /// <param name="dimensions">the number of dimensions</param>
2469 /// <param name="loBounds">lower bounds of dimensions</param>
2470 /// <param name="sizes">sizes for the dimensions</param>
2471 public BoundArray(Type elementType, uint dimensions, int[] loBounds,
2472 int[] sizes) : base (elementType,0x14)
2474 numDims = dimensions;
2475 lowerBounds = loBounds;
2476 this.sizes = sizes;
2479 /// <summary>
2480 /// Create a new multi dimensional array type
2481 /// eg. elemType[5,10,20] would be new BoundArray(elemType,3,[5,10,20])
2482 /// </summary>
2483 /// <param name="elementType">the type of the elements</param>
2484 /// <param name="dimensions">the number of dimensions</param>
2485 /// <param name="size">the sizes of the dimensions</param>
2486 public BoundArray(Type elementType, uint dimensions, int[] size)
2487 : base (elementType,0x14)
2489 numDims = dimensions;
2490 sizes = size;
2493 /// <summary>
2494 /// Create a new multi dimensional array type
2495 /// eg. elemType[,,] would be new BoundArray(elemType,3)
2496 /// </summary>
2497 /// <param name="elementType">the type of the elements</param>
2498 /// <param name="dimensions">the number of dimensions</param>
2499 public BoundArray(Type elementType, uint dimensions)
2500 : base (elementType,0x14)
2502 numDims = dimensions;
2505 internal sealed override void TypeSig(MemoryStream str)
2507 str.WriteByte(typeIndex);
2508 elemType.TypeSig(str);
2509 MetaData.CompressNum(numDims,str);
2510 if ((sizes != null) && (sizes.Length > 0)) {
2512 MetaData.CompressNum((uint)sizes.Length,str);
2513 for (int i=0; i < sizes.Length; i++) {
2514 MetaData.CompressNum((uint)sizes[i],str);
2516 } else str.WriteByte(0);
2517 if ((lowerBounds != null) && (lowerBounds.Length > 0)) {
2518 MetaData.CompressNum((uint)lowerBounds.Length,str);
2519 for (int i=0; i < lowerBounds.Length; i++) {
2520 CompressSignedNum (lowerBounds[i],str);
2522 } else str.WriteByte(0);
2524 private void CompressSignedNum (int val, MemoryStream str)
2526 uint uval = (uint) val;
2527 byte sign = 0;
2528 if (val < 0) {
2529 val = -val;
2530 sign = 1;
2533 /* Map the signed number to an unsigned number in two ways.
2535 fval: left-rotated 2's complement representation
2536 sval: map the signed number to unsigned as follows: 0 -> 0, -1 -> 1, 1 -> 2, -2 -> 3, 2 -> 4, ....
2537 the mapping is: x -> 2*|x| - signbit(x)
2539 uint fval = (uval << 1) | sign;
2540 int sval = (val << 1) - sign;
2542 /* An overly clever transformation:
2544 a. sval is used to determine the number of bytes in the compressed representation.
2545 b. fval is truncated to the appropriate number of bits and output using the
2546 normal unsigned-int compressor.
2548 However, or certain values, the truncated fval doesn't carry enough information to round trip.
2550 (fval & 0x3FFF) <= 0x7F => compressor emits 1 byte, not 2 => there is aliasing of values
2552 So, we use full 4 bytes to encode such values.
2554 LAMESPEC: The Microsoft implementation doesn't appear to handle this subtle case.
2555 e.g., it ends up encoding -8192 as the byte 0x01, which decodes to -64
2557 if (sval <= 0x7F)
2558 MetaData.CompressNum (fval & 0x7F, str);
2559 else if (sval <= 0x3FFF && (fval & 0x3FFF) > 0x7F)
2560 MetaData.CompressNum (fval & 0x3FFF, str);
2561 else if (sval <= 0x1FFFFFFF && (fval & 0x1FFFFFFF) > 0x3FFF)
2562 MetaData.CompressNum (fval & 0x1FFFFFFF, str);
2563 else
2564 /* FIXME: number cannot be represented. Report a warning. */
2565 // throw new Exception ("cannot represent signed value" + -val);
2566 MetaData.CompressNum (fval, str);
2570 #endregion
2573 /* Empty interface for grouping TypeRef's possible ResolutionScope
2574 namely : Module, ModuleRef, AssemblyRef and TypeRef */
2575 public interface IResolutionScope {
2578 /**************************************************************************/
2579 /// <summary>
2580 /// Base class for scopes (extended by Module, ModuleRef, Assembly, AssemblyRef)
2581 /// </summary>
2582 public abstract class ResolutionScope : MetaDataElement, IResolutionScope {
2584 protected uint nameIx = 0;
2585 protected MetaData metaData;
2586 protected string name;
2588 internal ResolutionScope(string name, MetaData md)
2590 metaData = md;
2591 this.name = name;
2592 nameIx = md.AddToStringsHeap(name);
2595 internal string GetName() { return name; }
2599 /**************************************************************************/
2600 /// <summary>
2601 /// Descriptor for THIS assembly (.assembly)
2602 /// </summary>
2603 public class Assembly : ResolutionScope {
2605 ushort majorVer, minorVer, buildNo, revisionNo;
2606 uint flags;
2607 uint hashAlgId;
2608 uint keyIx = 0, cultIx = 0;
2609 bool hasPublicKey = false;
2611 internal Assembly(string name, MetaData md) : base(name,md)
2613 tabIx = MDTable.Assembly;
2616 /// <summary>
2617 /// Add details about THIS assembly
2618 /// </summary>
2619 /// <param name="majVer">Major Version</param>
2620 /// <param name="minVer">Minor Version</param>
2621 /// <param name="bldNo">Build Number</param>
2622 /// <param name="revNo">Revision Number</param>
2623 /// <param name="key">Hash Key</param>
2624 /// <param name="hash">Hash Algorithm</param>
2625 /// <param name="cult">Culture</param>
2626 public void AddAssemblyInfo(int majVer, int minVer, int bldNo, int revNo,
2627 byte[] key, uint hash, string cult)
2629 majorVer = (ushort)majVer;
2630 minorVer = (ushort)minVer;
2631 buildNo = (ushort)bldNo;
2632 revisionNo = (ushort)revNo;
2633 hashAlgId = hash;
2634 hasPublicKey = (key != null);
2635 keyIx = metaData.AddToBlobHeap(key);
2636 cultIx = metaData.AddToStringsHeap(cult);
2639 /// <summary>
2640 /// Add an attribute to THIS assembly
2641 /// </summary>
2642 /// <param name="aa">assembly attribute</param>
2643 public void AddAssemblyAttr(AssemAttr aa)
2645 flags |= (uint)aa;
2648 internal sealed override uint Size(MetaData md)
2650 return 16 + md.BlobIndexSize() + 2 * md.StringsIndexSize();
2653 internal sealed override void Write(FileImage output)
2655 // Console.WriteLine("Writing assembly element with nameIx of " + nameIx + " at file offset " + output.Seek(0,SeekOrigin.Current));
2656 output.Write((uint)hashAlgId);
2657 output.Write(majorVer);
2658 output.Write(minorVer);
2659 output.Write(buildNo);
2660 output.Write(revisionNo);
2661 output.Write(flags);
2662 output.BlobIndex(keyIx);
2663 output.StringsIndex(nameIx);
2664 output.StringsIndex(cultIx);
2667 internal sealed override uint GetCodedIx(CIx code)
2669 switch (code) {
2670 case (CIx.HasCustomAttr) : return 14;
2671 case (CIx.HasDeclSecurity) : return 2;
2673 return 0;
2676 internal bool HasPublicKey {
2677 get { return hasPublicKey; }
2681 /**************************************************************************/
2682 /// <summary>
2683 /// Descriptor for THIS module
2684 /// </summary>
2685 public class Module : ResolutionScope, IExternRef {
2687 Guid mvid;
2688 uint mvidIx = 0;
2690 internal Module(string name, MetaData md) : base(name,md)
2692 mvid = Guid.NewGuid();
2693 mvidIx = md.AddToGUIDHeap(mvid);
2694 tabIx = MDTable.Module;
2697 public Guid Guid {
2698 get { return mvid; }
2701 public ClassRef AddClass(string nsName, string name)
2703 ClassRef aClass = new ClassRef (nsName, name, metaData);
2704 metaData.AddToTable (MDTable.TypeRef, aClass);
2705 aClass.SetParent (this);
2706 return aClass;
2709 public ClassRef AddValueClass(string nsName, string name)
2711 ClassRef aClass = AddClass (nsName, name);
2712 aClass.MakeValueClass (ValueClass.ValueType);
2713 return aClass;
2716 internal sealed override uint Size(MetaData md)
2718 return 2 + md.StringsIndexSize() + 3 * md.GUIDIndexSize();
2721 internal sealed override void Write(FileImage output)
2723 output.Write((short)0);
2724 output.StringsIndex(nameIx);
2725 output.GUIDIndex(mvidIx);
2726 output.GUIDIndex(0);
2727 output.GUIDIndex(0);
2730 internal sealed override uint GetCodedIx(CIx code)
2732 switch (code) {
2733 case (CIx.HasCustomAttr) : return 7;
2734 case (CIx.ResolutionScope) : return 0;
2736 return 0;
2739 /**************************************************************************/
2740 /// <summary>
2741 /// Descriptor for another module in THIS assembly
2742 /// </summary>
2743 public class ModuleRef : ResolutionScope, IExternRef {
2745 internal ModuleRef(MetaData md, string name) : base(name,md)
2747 tabIx = MDTable.ModuleRef;
2750 /// <summary>
2751 /// Add a class to this external module. This is a class declared in
2752 /// another module of THIS assembly.
2753 /// </summary>
2754 /// <param name="nsName">name space name</param>
2755 /// <param name="name">class name</param>
2756 /// <returns>a descriptor for this class in another module</returns>
2757 public ClassRef AddClass(string nsName, string name)
2759 ClassRef aClass = new ClassRef(nsName,name,metaData);
2760 metaData.AddToTable(MDTable.TypeRef,aClass);
2761 aClass.SetParent(this);
2762 return aClass;
2765 /// <summary>
2766 /// Make a file descriptor to correspond to this module. The file
2767 /// descriptor will have the same name as the module descriptor
2768 /// </summary>
2769 /// <param name="hashBytes">the hash of the file</param>
2770 /// <param name="hasMetaData">the file contains metadata</param>
2771 /// <param name="entryPoint">the program entry point is in this file</param>
2772 /// <returns>a descriptor for the file which contains this module</returns>
2773 public FileRef MakeFile(byte[] hashBytes, bool hasMetaData, bool entryPoint)
2775 FileRef file = new FileRef(nameIx,hashBytes,hasMetaData,entryPoint,metaData);
2776 metaData.AddToTable(MDTable.File,file);
2777 return file;
2780 /// <summary>
2781 /// Add a value class to this module. This is a class declared in
2782 /// another module of THIS assembly.
2783 /// </summary>
2784 /// <param name="nsName">name space name</param>
2785 /// <param name="name">class name</param>
2786 /// <returns></returns>
2787 public ClassRef AddValueClass(string nsName, string name)
2789 ClassRef aClass = new ClassRef(nsName,name,metaData);
2790 metaData.AddToTable(MDTable.TypeRef,aClass);
2791 aClass.SetParent(this);
2792 aClass.MakeValueClass(ValueClass.ValueType);
2793 return aClass;
2796 /// <summary>
2797 /// Add a class which is declared public in this external module of
2798 /// THIS assembly. This class will be exported from this assembly.
2799 /// The ilasm syntax for this is .extern class
2800 /// </summary>
2801 /// <param name="attrSet">attributes of the class to be exported</param>
2802 /// <param name="nsName">name space name</param>
2803 /// <param name="name">external class name</param>
2804 /// <param name="declFile">the file where the class is declared</param>
2805 /// <param name="isValueClass">is this class a value type?</param>
2806 /// <returns>a descriptor for this external class</returns>
2807 public ExternClassRef AddExternClass(TypeAttr attrSet, string nsName,
2808 string name, FileRef declFile,
2809 bool isValueClass) {
2810 ExternClassRef cRef = new ExternClassRef(attrSet,nsName,name,declFile,metaData);
2811 metaData.AddToTable(MDTable.TypeRef,cRef);
2812 cRef.SetParent(this);
2813 if (isValueClass) cRef.MakeValueClass(ValueClass.ValueType);
2814 return cRef;
2817 /// <summary>
2818 /// Add a "global" method in another module
2819 /// </summary>
2820 /// <param name="name">method name</param>
2821 /// <param name="retType">return type</param>
2822 /// <param name="pars">method parameter types</param>
2823 /// <returns>a descriptor for this method in anther module</returns>
2824 public MethodRef AddMethod(string name, Type retType, Type[] pars)
2826 MethodRef meth = new MethodRef(this,name,retType,pars,false,null, 0);
2827 metaData.AddToTable(MDTable.MemberRef,meth);
2828 return meth;
2831 /// <summary>
2832 /// Add a vararg method to this class
2833 /// </summary>
2834 /// <param name="name">method name</param>
2835 /// <param name="retType">return type</param>
2836 /// <param name="pars">parameter types</param>
2837 /// <param name="optPars">optional param types for this vararg method</param>
2838 /// <returns>a descriptor for this method</returns>
2839 public MethodRef AddVarArgMethod(string name, Type retType,
2840 Type[] pars, Type[] optPars) {
2841 MethodRef meth = new MethodRef(this,name,retType,pars,true,optPars, 0);
2842 metaData.AddToTable(MDTable.MemberRef,meth);
2843 return meth;
2846 /// <summary>
2847 /// Add a field in another module
2848 /// </summary>
2849 /// <param name="name">field name</param>
2850 /// <param name="fType">field type</param>
2851 /// <returns>a descriptor for this field in another module</returns>
2852 public FieldRef AddField(string name, Type fType)
2854 FieldRef field = new FieldRef(this,name,fType);
2855 metaData.AddToTable(MDTable.MemberRef,field);
2856 return field;
2859 internal sealed override uint Size(MetaData md)
2861 return md.StringsIndexSize();
2864 internal sealed override void Write(FileImage output)
2866 output.StringsIndex(nameIx);
2869 internal sealed override uint GetCodedIx(CIx code)
2871 switch (code) {
2872 case (CIx.HasCustomAttr) : return 12;
2873 case (CIx.MemberRefParent) : return 2;
2874 case (CIx.ResolutionScope) : return 1;
2876 return 0;
2881 #region Classes for Constants
2882 /// <summary>
2883 /// Descriptor for a constant value
2884 /// </summary>
2885 public abstract class Constant {
2886 protected uint size = 0;
2887 protected Type type;
2888 protected uint blobIndex;
2889 protected bool addedToBlobHeap = false;
2891 internal Constant() { }
2893 internal virtual uint GetBlobIndex(MetaData md) { return 0; }
2895 internal uint GetSize() { return size; }
2897 internal byte GetTypeIndex() { return type.GetTypeIndex(); }
2899 internal virtual void Write(BinaryWriter bw) { }
2902 /// <summary>
2903 /// Descriptor for a constant value
2904 /// </summary>
2905 public abstract class DataConstant : Constant {
2906 private uint dataOffset = 0;
2908 internal DataConstant() { }
2910 public uint DataOffset {
2911 get { return dataOffset; }
2912 set { dataOffset = value; }
2917 /// <summary>
2918 /// Boolean constant
2919 /// </summary>
2920 public class BoolConst : Constant {
2921 bool val;
2923 /// <summary>
2924 /// Create a new boolean constant with the value "val"
2925 /// </summary>
2926 /// <param name="val">value of this boolean constant</param>
2927 public BoolConst(bool val)
2929 this.val = val;
2930 size = 1;
2931 type = PrimitiveType.Boolean;
2934 internal sealed override uint GetBlobIndex(MetaData md)
2936 if (!addedToBlobHeap) {
2937 if (val) blobIndex = md.AddToBlobHeap((sbyte)1);
2938 else blobIndex = md.AddToBlobHeap((sbyte)0);
2939 addedToBlobHeap = true;
2941 return blobIndex;
2944 internal sealed override void Write(BinaryWriter bw)
2946 if (val) bw.Write((sbyte)1);
2947 else bw.Write((sbyte)0);
2952 public class ByteArrConst : DataConstant {
2953 byte[] val;
2955 public ByteArrConst(byte[] val)
2957 type = PrimitiveType.String;
2958 this.val = val;
2959 size = (uint)val.Length;
2962 public Type Type {
2963 get { return type; }
2964 set { type = value; }
2967 internal sealed override uint GetBlobIndex(MetaData md)
2969 if (!addedToBlobHeap) {
2970 blobIndex = md.AddToBlobHeap(val);
2971 addedToBlobHeap = true;
2973 return blobIndex;
2976 internal sealed override void Write(BinaryWriter bw)
2978 bw.Write(val);
2983 public class CharConst : Constant {
2984 char val;
2986 public CharConst(char val)
2988 this.val = val;
2989 size = 2;
2990 type = PrimitiveType.Char;
2993 internal sealed override uint GetBlobIndex(MetaData md)
2995 if (!addedToBlobHeap) {
2996 blobIndex = md.AddToBlobHeap(val);
2997 addedToBlobHeap = true;
2999 return blobIndex;
3002 internal sealed override void Write(BinaryWriter bw)
3004 bw.Write(val);
3009 public class FloatConst : DataConstant {
3010 float val;
3012 public FloatConst(float val)
3014 this.val = val;
3015 size = 4;
3016 type = PrimitiveType.Float32;
3019 internal sealed override uint GetBlobIndex(MetaData md)
3021 if (!addedToBlobHeap) {
3022 blobIndex = md.AddToBlobHeap(val);
3023 addedToBlobHeap = true;
3025 return blobIndex;
3028 internal sealed override void Write(BinaryWriter bw)
3030 bw.Write(val);
3035 public class DoubleConst : DataConstant {
3036 double val;
3038 public DoubleConst(double val)
3040 this.val = val;
3041 size = 8;
3042 type = PrimitiveType.Float64;
3045 internal sealed override uint GetBlobIndex(MetaData md)
3047 if (!addedToBlobHeap) {
3048 blobIndex = md.AddToBlobHeap(val);
3049 addedToBlobHeap = true;
3051 return blobIndex;
3054 internal sealed override void Write(BinaryWriter bw)
3056 bw.Write(val);
3061 public class IntConst : DataConstant {
3062 long val;
3064 public IntConst(sbyte val)
3066 this.val = val;
3067 size = 1;
3068 type = PrimitiveType.Int8;
3071 public IntConst(short val)
3073 this.val = val;
3074 size = 2;
3075 type = PrimitiveType.Int16;
3078 public IntConst(int val)
3080 this.val = val;
3081 size = 4;
3082 type = PrimitiveType.Int32;
3085 public IntConst(long val)
3087 this.val = val;
3088 size = 8;
3089 type = PrimitiveType.Int64;
3092 internal sealed override uint GetBlobIndex(MetaData md)
3094 if (!addedToBlobHeap) {
3095 switch (size) {
3096 case (1) : blobIndex = md.AddToBlobHeap((sbyte)val); break;
3097 case (2) : blobIndex = md.AddToBlobHeap((short)val); break;
3098 case (4) : blobIndex = md.AddToBlobHeap((int)val); break;
3099 default : blobIndex = md.AddToBlobHeap(val); break;
3101 addedToBlobHeap = true;
3103 return blobIndex;
3106 internal sealed override void Write(BinaryWriter bw)
3108 switch (size) {
3109 case (1) : bw.Write((sbyte)val); break;
3110 case (2) : bw.Write((short)val); break;
3111 case (4) : bw.Write((int)val); break;
3112 default : bw.Write(val); break;
3118 public class UIntConst : Constant {
3119 ulong val;
3121 public UIntConst(byte val)
3123 this.val = val;
3124 size = 1;
3125 type = PrimitiveType.UInt8;
3127 public UIntConst(ushort val)
3129 this.val = val;
3130 size = 2;
3131 type = PrimitiveType.UInt16;
3133 public UIntConst(uint val)
3135 this.val = val;
3136 size = 4;
3137 type = PrimitiveType.UInt32;
3139 public UIntConst(ulong val)
3141 this.val = val;
3142 size = 8;
3143 type = PrimitiveType.UInt64;
3146 internal sealed override uint GetBlobIndex(MetaData md)
3148 if (!addedToBlobHeap) {
3149 switch (size) {
3150 case (1) : blobIndex = md.AddToBlobHeap((byte)val); break;
3151 case (2) : blobIndex = md.AddToBlobHeap((ushort)val); break;
3152 case (4) : blobIndex = md.AddToBlobHeap((uint)val); break;
3153 default : blobIndex = md.AddToBlobHeap(val); break;
3155 addedToBlobHeap = true;
3157 return blobIndex;
3160 internal sealed override void Write(BinaryWriter bw)
3162 switch (size) {
3163 case (1) : bw.Write((byte)val); break;
3164 case (2) : bw.Write((ushort)val); break;
3165 case (4) : bw.Write((uint)val); break;
3166 default : bw.Write(val); break;
3172 public class StringConst : DataConstant {
3173 string val;
3175 public StringConst(string val)
3177 this.val = val;
3178 size = (uint)val.Length; // need to add null ??
3179 type = PrimitiveType.String;
3182 internal sealed override uint GetBlobIndex(MetaData md)
3184 if (!addedToBlobHeap) {
3185 byte [] b = Encoding.Unicode.GetBytes (val);
3186 blobIndex = md.AddToBlobHeap(b);
3187 addedToBlobHeap = true;
3189 return blobIndex;
3192 internal sealed override void Write(BinaryWriter bw)
3194 bw.Write(val);
3199 public class NullConst : Constant {
3201 public NullConst()
3203 size = 4;
3204 type = PrimitiveType.Class;
3207 internal sealed override uint GetBlobIndex(MetaData md)
3209 if (!addedToBlobHeap) {
3210 blobIndex = md.AddToBlobHeap((int)0);
3211 addedToBlobHeap = true;
3213 return blobIndex;
3216 internal sealed override void Write(BinaryWriter bw)
3218 bw.Write((int)0);
3223 public class AddressConstant : DataConstant {
3224 DataConstant data;
3226 public AddressConstant(DataConstant dConst)
3228 data = dConst;
3229 size = 4;
3230 type = PrimitiveType.TypedRef;
3233 internal sealed override void Write(BinaryWriter bw)
3235 ((FileImage)bw).WriteDataRVA(data.DataOffset);
3240 public class RepeatedConstant : DataConstant {
3241 DataConstant data;
3242 uint repCount;
3244 public RepeatedConstant(DataConstant dConst, int repeatCount)
3246 data = dConst;
3247 repCount = (uint)repeatCount;
3248 int[] sizes = new int[1];
3249 sizes[0] = repeatCount;
3250 type = new BoundArray(type,1,sizes);
3251 size = data.GetSize() * repCount;
3254 internal sealed override void Write(BinaryWriter bw)
3256 for (int i=0; i < repCount; i++) {
3257 data.Write(bw);
3263 public class ArrayConstant : DataConstant {
3264 DataConstant[] dataVals;
3266 public ArrayConstant(DataConstant[] dVals)
3268 dataVals = dVals;
3269 for (int i=0; i < dataVals.Length; i++) {
3270 size += dataVals[i].GetSize();
3274 internal sealed override void Write(BinaryWriter bw)
3276 for (int i=0; i < dataVals.Length; i++) {
3277 dataVals[i].Write(bw);
3283 public class ClassType : Constant {
3284 string name;
3285 Class desc;
3287 public ClassType(string className)
3289 name = className;
3290 type = PrimitiveType.ClassType;
3293 public ClassType(Class classDesc)
3295 desc = classDesc;
3296 type = PrimitiveType.ClassType;
3299 internal override void Write(BinaryWriter bw)
3301 if (name == null) name = desc.TypeName();
3302 bw.Write(name);
3307 #endregion
3309 /**************************************************************************/
3310 /// <summary>
3311 /// Descriptor for a custom modifier of a type (modopt or modreq)
3312 /// </summary>
3314 public class CustomModifiedType : Type {
3316 Type type;
3317 Class cmodType;
3319 /// <summary>
3320 /// Create a new custom modifier for a type
3321 /// </summary>
3322 /// <param name="type">the type to be modified</param>
3323 /// <param name="cmod">the modifier</param>
3324 /// <param name="cmodType">the type reference to be associated with the type</param>
3325 public CustomModifiedType(Type type, CustomModifier cmod, Class cmodType)
3326 : base((byte)cmod)
3328 this.type = type;
3329 this.cmodType = cmodType;
3332 internal sealed override void TypeSig(MemoryStream str)
3334 str.WriteByte(typeIndex);
3335 MetaData.CompressNum(cmodType.TypeDefOrRefToken(),str);
3336 type.TypeSig(str);
3341 /**************************************************************************/
3342 /// <summary>
3343 /// Base class for Event and Property descriptors
3344 /// </summary>
3346 public class Feature : MetaDataElement {
3348 internal enum MethodType : ushort { Setter = 0x01, Getter, Other = 0x04, AddOn = 0x08,
3349 RemoveOn = 0x10, Fire = 0x20 }
3351 private static readonly int INITSIZE = 5;
3352 private static readonly ushort specialName = 0x200;
3353 private static readonly ushort rtSpecialName = 0x400;
3355 protected ClassDef parent;
3356 protected ushort flags = 0;
3357 protected string name;
3358 protected int tide = 0;
3359 protected uint nameIx;
3360 protected MethodSemantics[] methods = new MethodSemantics[INITSIZE];
3362 internal Feature(string name, ClassDef par)
3364 parent = par;
3365 this.name = name;
3368 internal void AddMethod(MethodDef meth, MethodType mType)
3370 if (tide >= methods.Length) {
3371 int len = methods.Length;
3372 MethodSemantics[] mTmp = methods;
3373 methods = new MethodSemantics[len * 2];
3374 for (int i=0; i < len; i++) {
3375 methods[i] = mTmp[i];
3378 methods[tide++] = new MethodSemantics(mType,meth,this);
3381 /// <summary>
3382 /// Set the specialName attribute for this Event or Property
3383 /// </summary>
3384 public void SetSpecialName()
3386 flags |= specialName;
3389 /// <summary>
3390 /// Set the RTSpecialName attribute for this Event or Property
3391 /// </summary>
3392 public void SetRTSpecialName()
3394 flags |= rtSpecialName;
3399 /**************************************************************************/
3400 /// <summary>
3401 /// Descriptor for an event
3402 /// </summary>
3403 public class Event : Feature {
3405 Type eventType;
3407 internal Event(string name, Type eType, ClassDef parent)
3408 : base(name, parent)
3410 eventType = eType;
3411 tabIx = MDTable.Event;
3414 /// <summary>
3415 /// Add the addon method to this event
3416 /// </summary>
3417 /// <param name="addon">the addon method</param>
3418 public void AddAddon(MethodDef addon)
3420 AddMethod(addon,MethodType.AddOn);
3423 /// <summary>
3424 /// Add the removeon method to this event
3425 /// </summary>
3426 /// <param name="removeOn">the removeon method</param>
3427 public void AddRemoveOn(MethodDef removeOn)
3429 AddMethod(removeOn,MethodType.RemoveOn);
3432 /// <summary>
3433 /// Add the fire method to this event
3434 /// </summary>
3435 /// <param name="fire">the fire method</param>
3436 public void AddFire(MethodDef fire)
3438 AddMethod(fire,MethodType.Fire);
3441 /// <summary>
3442 /// Add another method to this event
3443 /// </summary>
3444 /// <param name="other">the method to be added</param>
3445 public void AddOther(MethodDef other)
3447 AddMethod(other,MethodType.Other);
3450 internal sealed override void BuildTables(MetaData md)
3452 if (done) return;
3453 nameIx = md.AddToStringsHeap(name);
3454 for (int i=0; i < tide; i++) {
3455 md.AddToTable(MDTable.MethodSemantics,methods[i]);
3457 done = true;
3460 internal sealed override uint Size(MetaData md)
3462 return 2 + md.StringsIndexSize() + md.CodedIndexSize(CIx.TypeDefOrRef);
3465 internal sealed override void Write(FileImage output)
3467 output.Write(flags);
3468 output.StringsIndex(nameIx);
3469 output.WriteCodedIndex(CIx.TypeDefOrRef,eventType);
3472 internal sealed override uint GetCodedIx(CIx code)
3474 switch (code) {
3475 case (CIx.HasCustomAttr) : return 10;
3476 case (CIx.HasSemantics) : return 0;
3478 return 0;
3483 /**************************************************************************/
3484 /// <summary>
3485 /// Descriptor for the Property of a class
3486 /// </summary>
3487 public class Property : Feature {
3489 private static readonly byte PropertyTag = 0x8;
3490 private bool instance;
3491 MethodDef getterMeth;
3492 ConstantElem constVal;
3493 uint typeBlobIx = 0;
3494 Type[] parList;
3495 Type returnType;
3496 uint numPars = 0;
3498 internal Property(string name, Type retType, Type[] pars, ClassDef parent) : base(name, parent)
3500 returnType = retType;
3501 parList = pars;
3502 if (pars != null) numPars = (uint)pars.Length;
3503 tabIx = MDTable.Property;
3506 /// <summary>
3507 /// Add a set method to this property
3508 /// </summary>
3509 /// <param name="setter">the set method</param>
3510 public void AddSetter(MethodDef setter)
3512 AddMethod(setter,MethodType.Setter);
3515 /// <summary>
3516 /// Add a get method to this property
3517 /// </summary>
3518 /// <param name="getter">the get method</param>
3519 public void AddGetter(MethodDef getter)
3521 AddMethod(getter,MethodType.Getter);
3522 getterMeth = getter;
3525 /// <summary>
3526 /// Add another method to this property
3527 /// </summary>
3528 /// <param name="other">the method</param>
3529 public void AddOther(MethodDef other)
3531 AddMethod(other,MethodType.Other);
3534 /// <summary>
3535 /// Add an initial value for this property
3536 /// </summary>
3537 /// <param name="constVal">the initial value for this property</param>
3538 public void AddInitValue(Constant constVal)
3540 this.constVal = new ConstantElem(this,constVal);
3543 public void SetInstance (bool isInstance)
3545 this.instance = isInstance;
3548 internal sealed override void BuildTables(MetaData md)
3550 if (done) return;
3551 nameIx = md.AddToStringsHeap(name);
3552 MemoryStream sig = new MemoryStream();
3553 byte tag = PropertyTag;
3554 if (instance)
3555 tag |= 0x20;
3556 sig.WriteByte(tag);
3557 MetaData.CompressNum(numPars,sig);
3558 returnType.TypeSig(sig);
3559 for (int i=0; i < numPars; i++) {
3560 parList[i].TypeSig(sig);
3562 typeBlobIx = md.AddToBlobHeap(sig.ToArray());
3563 for (int i=0; i < tide; i++) {
3564 md.AddToTable(MDTable.MethodSemantics,methods[i]);
3566 if (constVal != null) {
3567 md.AddToTable(MDTable.Constant,constVal);
3568 constVal.BuildTables(md);
3570 done = true;
3573 internal sealed override uint Size(MetaData md)
3575 return 2 + md.StringsIndexSize() + md.BlobIndexSize();
3578 internal sealed override void Write(FileImage output)
3580 output.Write(flags);
3581 output.StringsIndex(nameIx);
3582 output.BlobIndex(typeBlobIx);
3585 internal sealed override uint GetCodedIx(CIx code)
3587 switch (code) {
3588 case (CIx.HasCustomAttr) : return 9;
3589 case (CIx.HasConst) : return 2;
3590 case (CIx.HasSemantics) : return 1;
3592 return 0;
3597 /**************************************************************************/
3598 /// <summary>
3599 /// Base class for field/methods (member of a class)
3600 /// </summary>
3601 public abstract class Member : MetaDataElement {
3603 protected string name;
3604 protected uint nameIx = 0, sigIx = 0;
3606 internal Member(string memName)
3608 name = memName;
3609 tabIx = MDTable.MemberRef;
3614 /*****************************************************************************/
3615 /// <summary>
3616 /// Descriptor for a field of a class
3617 /// </summary>
3619 public abstract class Field : Member {
3621 protected static readonly byte FieldSig = 0x6;
3623 protected Type type;
3625 internal Field(string pfName, Type pfType) : base(pfName)
3627 type = pfType;
3631 /**************************************************************************/
3632 /// <summary>
3633 /// Descriptor for a field defined in a class of THIS assembly/module
3634 /// </summary>
3635 public class FieldDef : Field {
3637 //private static readonly uint PInvokeImpl = 0x2000;
3638 private static readonly ushort HasFieldRVA = 0x100;
3639 private static readonly ushort HasDefault = 0x8000;
3641 FieldRVA rva;
3642 ConstantElem constVal;
3643 FieldLayout layout;
3644 FieldMarshal marshalInfo;
3645 ushort flags;
3647 internal FieldDef(string name, Type fType) : base(name,fType)
3649 tabIx = MDTable.Field;
3652 internal FieldDef(FieldAttr attrSet, string name, Type fType) : base(name, fType)
3654 flags = (ushort)attrSet;
3655 tabIx = MDTable.Field;
3658 /// <summary>
3659 /// Add an attribute(s) to this field
3660 /// </summary>
3661 /// <param name="fa">the attribute(s) to be added</param>
3662 public void AddFieldAttr(FieldAttr fa)
3664 flags |= (ushort)fa;
3667 /// <summary>
3668 /// Add a value for this field
3669 /// </summary>
3670 /// <param name="val">the value for the field</param>
3671 public void AddValue(Constant val)
3673 constVal = new ConstantElem(this,val);
3674 flags |= HasDefault;
3677 /// <summary>
3678 /// Add an initial value for this field (at dataLabel) (.data)
3679 /// </summary>
3680 /// <param name="val">the value for the field</param>
3681 /// <param name="repeatVal">the number of repetitions of this value</param>
3682 public void AddDataValue(DataConstant val)
3684 flags |= HasFieldRVA;
3685 rva = new FieldRVA(this,val);
3688 /// <summary>
3689 /// Set the offset of the field. Used for sequential or explicit classes.
3690 /// (.field [offs])
3691 /// </summary>
3692 /// <param name="offs">field offset</param>
3693 public void SetOffset(uint offs)
3695 layout = new FieldLayout(this,offs);
3698 /// <summary>
3699 /// Set the marshalling info for a field
3700 /// </summary>
3701 /// <param name="mInf"></param>
3702 public void SetMarshalInfo(NativeType marshallType)
3704 flags |= (ushort) FieldAttr.HasFieldMarshal;
3705 marshalInfo = new FieldMarshal(this,marshallType);
3708 internal sealed override void BuildTables(MetaData md)
3710 if (done) return;
3711 nameIx = md.AddToStringsHeap(name);
3712 MemoryStream sig = new MemoryStream();
3713 sig.WriteByte(FieldSig);
3714 type.TypeSig(sig);
3715 sigIx = md.AddToBlobHeap(sig.ToArray());
3716 if (rva != null) {
3717 md.AddToTable(MDTable.FieldRVA,rva);
3718 rva.BuildTables(md);
3719 } else if (constVal != null) {
3720 md.AddToTable(MDTable.Constant,constVal);
3721 constVal.BuildTables(md);
3723 if (layout != null) md.AddToTable(MDTable.FieldLayout,layout);
3724 if (marshalInfo != null) {
3725 md.AddToTable(MDTable.FieldMarshal,marshalInfo);
3726 marshalInfo.BuildTables(md);
3728 done = true;
3731 internal sealed override uint Size(MetaData md)
3733 return 2 + md.StringsIndexSize() + md.BlobIndexSize();
3736 internal sealed override void Write(FileImage output)
3738 output.Write(flags);
3739 output.StringsIndex(nameIx);
3740 output.BlobIndex(sigIx);
3743 internal sealed override uint GetCodedIx(CIx code)
3745 switch (code) {
3746 case (CIx.HasConst) : return 0;
3747 case (CIx.HasCustomAttr) : return 1;
3748 case (CIx.HasFieldMarshal) : return 0;
3749 case (CIx.MemberForwarded) : return 0;
3751 return 0;
3756 /**************************************************************************/
3757 /// <summary>
3758 /// Descriptor for a field of a class defined in another assembly/module
3759 /// </summary>
3760 public class FieldRef : Field {
3762 MetaDataElement parent;
3764 internal FieldRef(MetaDataElement paren, string name, Type fType) : base(name, fType)
3766 parent = paren;
3769 internal sealed override void BuildTables(MetaData md)
3771 if (done) return;
3772 nameIx = md.AddToStringsHeap(name);
3773 MemoryStream sig = new MemoryStream();
3774 sig.WriteByte(FieldSig);
3775 type.TypeSig(sig);
3776 sigIx = md.AddToBlobHeap(sig.ToArray());
3777 done = true;
3780 internal sealed override uint Size(MetaData md)
3782 return md.CodedIndexSize(CIx.MemberRefParent) + md.StringsIndexSize() + md.BlobIndexSize();
3785 internal sealed override void Write(FileImage output)
3787 output.WriteCodedIndex(CIx.MemberRefParent,parent);
3788 output.StringsIndex(nameIx);
3789 output.BlobIndex(sigIx);
3792 internal sealed override uint GetCodedIx(CIx code) { return 6; }
3796 /**************************************************************************/
3797 /// <summary>
3798 /// Base class for Method Descriptors
3799 /// </summary>
3801 public abstract class Method : Member {
3803 internal Method (string methName) : base (methName)
3806 public abstract void AddCallConv(CallConv cconv);
3807 internal abstract void TypeSig(MemoryStream sig);
3808 internal abstract uint GetSigIx(MetaData md);
3811 /**************************************************************************/
3812 /// <summary>
3813 /// Descriptor for a method defined in THIS assembly/module
3814 /// IL .method
3815 /// </summary>
3817 public class MethodDef : Method {
3819 private static readonly ushort PInvokeImpl = 0x2000;
3820 //private static readonly uint UnmanagedExport = 0x0008;
3821 // private static readonly byte LocalSigByte = 0x7;
3822 uint parIx = 0, textOffset = 0;
3823 private CallConv callConv = CallConv.Default;
3824 private int gen_param_count;
3826 MetaData metaData;
3827 CILInstructions code;
3828 ArrayList securityActions = new ArrayList();
3829 Param[] parList;
3830 Local[] locals;
3831 bool initLocals;
3832 ushort methFlags = 0, implFlags = 0;
3833 int maxStack = 0, numPars = 0;
3834 bool entryPoint = false;
3835 LocalSig localSig;
3836 ArrayList varArgSigList;
3837 ImplMap pinvokeImpl;
3838 Param ret_param;
3840 internal MethodDef (MetaData md, string name, Param ret_param, Param [] pars)
3841 : this (md, 0, 0, name, ret_param, pars)
3845 internal MethodDef (MetaData md, MethAttr mAttrSet, ImplAttr iAttrSet, string name,
3846 Param ret_param, Param [] pars)
3847 : base (name)
3849 methFlags = (ushort)mAttrSet;
3850 implFlags = (ushort)iAttrSet;
3851 this.ret_param = ret_param;
3852 metaData = md;
3853 parList = pars;
3854 if (parList != null)
3855 numPars = parList.Length;
3856 tabIx = MDTable.Method;
3859 internal Param[] GetPars()
3861 return parList;
3864 internal override uint GetSigIx(MetaData md)
3866 MemoryStream sig = new MemoryStream();
3867 TypeSig(sig);
3868 return md.AddToBlobHeap(sig.ToArray());
3871 public override void AddCallConv(CallConv cconv)
3873 callConv |= cconv;
3876 /// <summary>
3877 /// Add some attributes to this method descriptor
3878 /// </summary>
3879 /// <param name="ma">the attributes to be added</param>
3880 public void AddMethAttribute(MethAttr ma)
3882 methFlags |= (ushort)ma;
3885 /// <summary>
3886 /// Add some implementation attributes to this method descriptor
3887 /// </summary>
3888 /// <param name="ia">the attributes to be added</param>
3889 public void AddImplAttribute(ImplAttr ia)
3891 implFlags |= (ushort)ia;
3894 public void AddPInvokeInfo(ModuleRef scope, string methName,
3895 PInvokeAttr callAttr) {
3896 pinvokeImpl = new ImplMap((ushort)callAttr,this,methName,scope);
3897 methFlags |= PInvokeImpl;
3900 /// <summary>
3901 /// Add a named generic type parameter
3902 /// </summary>
3903 public GenericParameter AddGenericParameter (short index, string name)
3905 return AddGenericParameter (index, name, 0);
3908 /// <summary>
3909 /// Add a named generic type parameter with attributes
3910 /// </summary>
3911 public GenericParameter AddGenericParameter (short index, string name, GenericParamAttributes attr)
3913 GenericParameter gp = new GenericParameter (this, metaData, index, name, attr);
3914 metaData.AddToTable (MDTable.GenericParam, gp);
3915 gen_param_count ++;
3916 return gp;
3919 /// <summary>
3920 /// Set the maximum stack height for this method
3921 /// </summary>
3922 /// <param name="maxStack">the maximum height of the stack</param>
3923 public void SetMaxStack(int maxStack)
3925 this.maxStack = maxStack;
3928 /// <summary>
3929 /// Add local variables to this method
3930 /// </summary>
3931 /// <param name="locals">the locals to be added</param>
3932 /// <param name="initLocals">are locals initialised to default values</param>
3933 public void AddLocals(Local[] locals, bool initLocals)
3935 this.locals = locals;
3936 this.initLocals = initLocals;
3939 /* Add Marshal info for return type */
3940 public void AddRetTypeMarshallInfo (NativeType marshallType)
3942 ret_param.AddMarshallInfo (marshallType);
3945 /// <summary>
3946 /// Mark this method as having an entry point
3947 /// </summary>
3948 public void DeclareEntryPoint()
3950 entryPoint = true;
3953 /// <summary>
3954 /// Create a code buffer for this method to add the IL instructions to
3955 /// </summary>
3956 /// <returns>a buffer for this method's IL instructions</returns>
3957 public CILInstructions CreateCodeBuffer()
3959 code = new CILInstructions(metaData);
3960 return code;
3963 /// <summary>
3964 /// Make a method reference descriptor for this method to be used
3965 /// as a callsite signature for this vararg method
3966 /// </summary>
3967 /// <param name="optPars">the optional pars for the vararg method call</param>
3968 /// <returns></returns>
3969 public MethodRef MakeVarArgSignature(Type[] optPars)
3971 Type[] pars = new Type[numPars];
3972 MethodRef varArgSig;
3973 for (int i=0; i < numPars; i++) {
3974 pars[i] = parList[i].GetParType();
3976 varArgSig = new MethodRef (this, name, ret_param.GetParType (), pars, true, optPars, 0);
3978 if (varArgSigList == null)
3979 varArgSigList = new ArrayList ();
3980 varArgSigList.Add (varArgSig);
3981 return varArgSig;
3984 internal sealed override void TypeSig(MemoryStream sig)
3986 sig.WriteByte((byte)callConv);
3987 if ((callConv & CallConv.Generic) == CallConv.Generic)
3988 MetaData.CompressNum ((uint) gen_param_count, sig);
3989 MetaData.CompressNum((uint)numPars,sig);
3991 ret_param.seqNo = 0;
3992 ret_param.TypeSig (sig);
3993 for (ushort i=0; i < numPars; i++) {
3994 parList[i].seqNo = (ushort)(i+1);
3995 parList[i].TypeSig(sig);
3999 internal sealed override void BuildTables(MetaData md)
4001 if (done) return;
4002 if (pinvokeImpl != null) {
4003 md.AddToTable(MDTable.ImplMap,pinvokeImpl);
4004 pinvokeImpl.BuildTables(md);
4006 if (entryPoint) md.SetEntryPoint(this);
4007 uint locToken = 0;
4008 if (locals != null) {
4009 localSig = new LocalSig(locals);
4010 md.AddToTable(MDTable.StandAloneSig,localSig);
4011 localSig.BuildTables(md);
4012 locToken = localSig.Token();
4014 if (code != null) {
4015 code.CheckCode(locToken,initLocals,maxStack);
4016 textOffset = md.AddCode(code);
4018 nameIx = md.AddToStringsHeap(name);
4019 sigIx = GetSigIx(md);
4020 parIx = md.TableIndex(MDTable.Param);
4021 if (ret_param.HasMarshalInfo || ret_param.HasCustomAttr) {
4022 md.AddToTable(MDTable.Param, ret_param);
4023 ret_param.BuildTables(md);
4025 for (int i=0; i < numPars; i++) {
4026 md.AddToTable(MDTable.Param,parList[i]);
4027 parList[i].BuildTables(md);
4029 if (varArgSigList != null) {
4030 foreach (MethodRef varArgSig in varArgSigList) {
4031 md.AddToTable(MDTable.MemberRef,varArgSig);
4032 varArgSig.BuildTables(md);
4035 // Console.WriteLine("method has " + numPars + " parameters");
4036 done = true;
4039 internal sealed override uint Size(MetaData md)
4041 return 8 + md.StringsIndexSize() + md.BlobIndexSize() + md.TableIndexSize(MDTable.Param);
4044 internal sealed override void Write(FileImage output)
4046 if (ZeroRva ()) output.Write(0);
4047 else output.WriteCodeRVA(textOffset);
4048 output.Write(implFlags);
4049 output.Write(methFlags);
4050 output.StringsIndex(nameIx);
4051 output.BlobIndex(sigIx);
4052 output.WriteIndex(MDTable.Param,parIx);
4055 internal bool ZeroRva ()
4057 return (((methFlags & (ushort)MethAttr.Abstract) != 0) ||
4058 ((implFlags & (ushort)ImplAttr.Runtime) != 0) ||
4059 ((implFlags & (ushort)ImplAttr.InternalCall) != 0) ||
4060 (pinvokeImpl != null)); // TODO: Not entirely true but works for now
4063 internal sealed override uint GetCodedIx(CIx code)
4065 switch (code) {
4066 case (CIx.HasCustomAttr) : return 0;
4067 case (CIx.HasDeclSecurity) : return 1;
4068 case (CIx.MemberRefParent) : return 3;
4069 case (CIx.MethodDefOrRef) : return 0;
4070 case (CIx.MemberForwarded) : return 1;
4071 case (CIx.CustomAttributeType) : return 2;
4072 case (CIx.TypeOrMethodDef) : return 1;
4074 return 0;
4078 /**************************************************************************/
4079 /// <summary>
4080 /// Descriptor for a method defined in another assembly/module
4081 /// </summary>
4082 public class MethodRef : Method {
4084 private static readonly byte Sentinel = 0x41;
4085 Type[] parList, optParList;
4086 MetaDataElement parent;
4087 uint numPars = 0, numOptPars = 0;
4088 CallConv callConv = CallConv.Default;
4089 Type retType;
4090 int gen_param_count;
4092 internal MethodRef(MetaDataElement paren, string name, Type retType,
4093 Type[] pars, bool varArgMeth, Type[] optPars, int gen_param_count) : base(name)
4095 parent = paren;
4096 parList = pars;
4097 this.retType = retType;
4098 if (parList != null) numPars = (uint)parList.Length;
4099 if (varArgMeth) {
4100 optParList = optPars;
4101 if (optParList != null) numOptPars = (uint)optParList.Length;
4102 callConv = CallConv.Vararg;
4104 this.gen_param_count = gen_param_count;
4107 internal override uint GetSigIx(MetaData md)
4109 MemoryStream sig = new MemoryStream();
4110 TypeSig(sig);
4111 return md.AddToBlobHeap(sig.ToArray());
4114 public override void AddCallConv(CallConv cconv)
4116 callConv |= cconv;
4119 internal sealed override void TypeSig(MemoryStream sig)
4121 sig.WriteByte((byte)callConv);
4122 if ((callConv & CallConv.Generic) == CallConv.Generic)
4123 MetaData.CompressNum ((uint) gen_param_count, sig);
4124 MetaData.CompressNum(numPars+numOptPars,sig);
4125 retType.TypeSig(sig);
4126 for (int i=0; i < numPars; i++) {
4127 parList[i].TypeSig(sig);
4129 if (numOptPars > 0) {
4130 sig.WriteByte(Sentinel);
4131 for (int i=0; i < numOptPars; i++) {
4132 optParList[i].TypeSig(sig);
4137 internal sealed override void BuildTables(MetaData md)
4139 if (done) return;
4140 nameIx = md.AddToStringsHeap(name);
4141 sigIx = GetSigIx(md);
4142 done = true;
4145 internal sealed override uint Size(MetaData md)
4147 return md.CodedIndexSize(CIx.MemberRefParent) + md.StringsIndexSize() + md.BlobIndexSize();
4150 internal sealed override void Write(FileImage output)
4152 output.WriteCodedIndex(CIx.MemberRefParent,parent);
4153 output.StringsIndex(nameIx);
4154 output.BlobIndex(sigIx);
4157 internal sealed override uint GetCodedIx(CIx code)
4159 switch (code) {
4160 case (CIx.HasCustomAttr) : return 6;
4161 case (CIx.MethodDefOrRef) : return 1;
4162 case (CIx.CustomAttributeType) : return 3;
4164 return 0;
4170 /**************************************************************************/
4171 /// <summary>
4172 /// Descriptors for native types used for marshalling
4173 /// </summary>
4174 public class NativeType {
4175 public static readonly NativeType Void = new NativeType(0x01);
4176 public static readonly NativeType Boolean = new NativeType(0x02);
4177 public static readonly NativeType Int8 = new NativeType(0x03);
4178 public static readonly NativeType UInt8 = new NativeType(0x04);
4179 public static readonly NativeType Int16 = new NativeType(0x05);
4180 public static readonly NativeType UInt16 = new NativeType(0x06);
4181 public static readonly NativeType Int32 = new NativeType(0x07);
4182 public static readonly NativeType UInt32 = new NativeType(0x08);
4183 public static readonly NativeType Int64 = new NativeType(0x09);
4184 public static readonly NativeType UInt64 = new NativeType(0x0A);
4185 public static readonly NativeType Float32 = new NativeType(0x0B);
4186 public static readonly NativeType Float64 = new NativeType(0x0C);
4187 public static readonly NativeType Currency = new NativeType(0x0F);
4188 public static readonly NativeType BStr = new NativeType(0x13);
4189 public static readonly NativeType LPStr = new NativeType(0x14);
4190 public static readonly NativeType LPWStr = new NativeType(0x15);
4191 public static readonly NativeType LPTStr = new NativeType(0x16);
4192 public static readonly NativeType FixedSysString = new NativeType(0x17);
4193 public static readonly NativeType IUnknown = new NativeType(0x19);
4194 public static readonly NativeType IDispatch = new NativeType(0x1A);
4195 public static readonly NativeType Struct = new NativeType(0x1B);
4196 public static readonly NativeType Interface = new NativeType(0x1C);
4197 public static readonly NativeType Int = new NativeType(0x1F);
4198 public static readonly NativeType UInt = new NativeType(0x20);
4199 public static readonly NativeType ByValStr = new NativeType(0x22);
4200 public static readonly NativeType AnsiBStr = new NativeType(0x23);
4201 public static readonly NativeType TBstr = new NativeType(0x24);
4202 public static readonly NativeType VariantBool = new NativeType(0x25);
4203 public static readonly NativeType FuncPtr = new NativeType(0x26);
4204 public static readonly NativeType AsAny = new NativeType(0x28);
4205 public static readonly NativeType LPStruct = new NativeType(0x2b);
4206 public static readonly NativeType Error = new NativeType(0x2d);
4208 protected byte typeIndex;
4210 internal NativeType(byte tyIx) { typeIndex = tyIx; }
4211 internal byte GetTypeIndex() { return typeIndex; }
4213 internal virtual byte[] ToBlob()
4215 byte[] bytes = new byte[1];
4216 bytes[0] = GetTypeIndex();
4217 return bytes;
4222 public class FixedSysString : NativeType {
4224 uint size;
4226 public FixedSysString (uint size) : base (NativeType.FixedSysString.GetTypeIndex ())
4228 this.size = size;
4231 internal override byte [] ToBlob ()
4233 MemoryStream str = new MemoryStream ();
4234 str.WriteByte (GetTypeIndex ());
4235 MetaData.CompressNum (size, str);
4236 return str.ToArray ();
4241 public class NativeArray : NativeType {
4243 NativeType elemType;
4244 int numElem = -1, parNum = -1, elemMult = -1;
4246 public NativeArray(NativeType elemType) : this (elemType, -1, -1, -1)
4248 this.elemType = elemType;
4251 /* public NativeArray(NativeType elemType, int len) : base(0x2A) {
4252 this.elemType = elemType;
4253 this.len = len;
4257 public NativeArray(NativeType elemType, int numElem, int parNumForLen, int elemMult) : base(0x2A)
4259 this.elemType = elemType;
4260 this.numElem = numElem;
4261 parNum = parNumForLen;
4262 this.elemMult = elemMult;
4265 public NativeArray(NativeType elemType, int numElem, int parNumForLen)
4266 : this (elemType, numElem, parNumForLen, -1)
4270 internal override byte[] ToBlob()
4272 MemoryStream str = new MemoryStream();
4273 str.WriteByte(GetTypeIndex());
4274 if (elemType == null) str.WriteByte(0x50); // no info (MAX)
4275 else str.WriteByte(elemType.GetTypeIndex());
4277 /* see : mono/metadata/metadata.c:mono_metadata_parse_marshal_spec
4278 * LAMESPEC: Older spec versions say elemMult comes before
4279 * len. Newer spec versions don't talk about elemMult at
4280 * all, but csc still emits it, and it is used to distinguish
4281 * between parNum being 0, and parNum being omitted.
4284 if (parNum == -1)
4285 // <native_type> []
4286 return str.ToArray ();
4288 MetaData.CompressNum((uint) parNum,str);
4289 if (numElem != -1) {
4290 MetaData.CompressNum ((uint) numElem, str);
4291 if (elemMult != -1)
4292 // <native_type> [ int32 ]
4293 MetaData.CompressNum((uint) elemMult,str);
4294 //else <native_type> [ int32 + int32 ]
4295 } else if (elemMult != -1) {
4296 // When can this occur ?
4297 MetaData.CompressNum (0, str);
4298 MetaData.CompressNum((uint) elemMult,str);
4300 //else <native_type> [ + int32 ]
4302 return str.ToArray();
4307 public class SafeArray : NativeType {
4309 SafeArrayType elemType;
4310 bool hasElemType;
4312 public SafeArray() : base(0x1D)
4316 public SafeArray(SafeArrayType elemType) : base(0x1D)
4318 this.elemType = elemType;
4319 hasElemType = true;
4322 internal override byte[] ToBlob()
4324 byte[] bytes = new byte[hasElemType ? 2 : 1];
4325 bytes[0] = GetTypeIndex();
4326 if (hasElemType)
4327 bytes[1] = (byte)elemType;
4328 return bytes;
4333 public class FixedArray : NativeType {
4335 NativeType elemType;
4336 uint numElem;
4338 //public FixedArray(NativeType elemType, int numElems) : base(0x1E) {
4339 public FixedArray(int numElems) : base(0x1E)
4341 //this.elemType = elemType;
4342 numElem = (uint)numElems;
4345 internal override byte[] ToBlob()
4347 MemoryStream str = new MemoryStream();
4348 str.WriteByte(GetTypeIndex());
4349 MetaData.CompressNum(numElem,str);
4350 /* FIXME:
4351 fixed array [5] lpstr [2]
4352 This format is not supported by ilasm 1.1.4322.2032,
4353 but is supported by 2.0.5125..
4354 ilasm 1.1 only supports "fixed array [5]"
4355 if (elemType == null) str.WriteByte(0x50); // no info (MAX)
4356 else str.WriteByte(elemType.GetTypeIndex());*/
4358 return str.ToArray();
4363 public class CustomMarshaller : NativeType {
4365 string typeName;
4366 string marshallerName;
4367 string cookie;
4369 public CustomMarshaller(string typeNameOrGUID, string marshallerName,
4370 string optCookie) : base(0x2C)
4372 typeName = typeNameOrGUID;
4373 this.marshallerName = marshallerName;
4374 cookie = optCookie;
4377 public CustomMarshaller(string marshallerName, string optCookie)
4378 :this (null, marshallerName, optCookie)
4382 internal override byte[] ToBlob()
4384 MemoryStream str = new MemoryStream();
4385 BinaryWriter bw = new BinaryWriter(str,new UTF8Encoding());
4386 bw.Write(GetTypeIndex());
4387 //Native type name & unmanaged type - unused
4388 //See mono/metadata/metadata.c : mono_metadata_parse_marshal_spec
4389 bw.Write ((byte) 0); // Native Type name, unused
4390 bw.Write ((byte) 0); // Unmanaged type, unused
4391 if (marshallerName != null) {
4392 MetaData.CompressNum ((uint)marshallerName.Length, str);
4393 bw.Write(marshallerName.ToCharArray());
4394 } else {
4395 bw.Write ((byte) 0);
4397 if (cookie != null) {
4398 MetaData.CompressNum ((uint)cookie.Length, str);
4399 bw.Write(cookie.ToCharArray());
4400 } else {
4401 bw.Write ((byte) 0);
4403 bw.Flush();
4404 return str.ToArray();
4408 /**************************************************************************/
4409 /// <summary>
4410 /// Descriptor for the Primitive types defined in IL
4411 /// </summary>
4412 public class PrimitiveType : Type {
4414 private string name;
4415 private int systemTypeIndex;
4416 public static int NumSystemTypes = 18;
4418 public static readonly PrimitiveType Void = new PrimitiveType(0x01,"Void",0);
4419 public static readonly PrimitiveType Boolean = new PrimitiveType(0x02,"Boolean",1);
4420 public static readonly PrimitiveType Char = new PrimitiveType(0x03,"Char",2);
4421 public static readonly PrimitiveType Int8 = new PrimitiveType(0x04,"SByte",3);
4422 public static readonly PrimitiveType UInt8 = new PrimitiveType(0x05,"Byte",4);
4423 public static readonly PrimitiveType Int16 = new PrimitiveType(0x06,"Int16",5);
4424 public static readonly PrimitiveType UInt16 = new PrimitiveType(0x07,"UInt16",6);
4425 public static readonly PrimitiveType Int32 = new PrimitiveType(0x08,"Int32",7);
4426 public static readonly PrimitiveType UInt32 = new PrimitiveType(0x09,"UInt32",8);
4427 public static readonly PrimitiveType Int64 = new PrimitiveType(0x0A,"Int64",9);
4428 public static readonly PrimitiveType UInt64 = new PrimitiveType(0x0B,"UInt64",10);
4429 public static readonly PrimitiveType Float32 = new PrimitiveType(0x0C,"Single",11);
4430 public static readonly PrimitiveType Float64 = new PrimitiveType(0x0D,"Double",12);
4431 public static readonly PrimitiveType String = new PrimitiveType(0x0E,"String",13);
4432 internal static readonly PrimitiveType Class = new PrimitiveType(0x12);
4433 internal static readonly PrimitiveType Var = new PrimitiveType(0x13);
4434 internal static readonly PrimitiveType GenericInst = new PrimitiveType(0x15);
4435 public static readonly PrimitiveType TypedRef = new PrimitiveType(0x16,"TypedReference",14);
4436 public static readonly PrimitiveType IntPtr = new PrimitiveType(0x18,"IntPtr",15);
4437 public static readonly PrimitiveType UIntPtr = new PrimitiveType(0x19,"UIntPtr",16);
4438 public static readonly PrimitiveType Object = new PrimitiveType(0x1C,"Object",17);
4439 internal static readonly PrimitiveType ClassType = new PrimitiveType(0x50);
4440 internal static readonly PrimitiveType SZArray = new PrimitiveType(0x1D);
4441 internal static readonly PrimitiveType MVar = new PrimitiveType(0x1E);
4442 internal static readonly PrimitiveType ValueType = new PrimitiveType(0x11, "ValueType", 18);
4443 public static readonly PrimitiveType NativeInt = IntPtr;
4444 public static readonly PrimitiveType NativeUInt = UIntPtr;
4446 internal PrimitiveType(byte typeIx) : base(typeIx) { }
4448 internal PrimitiveType(byte typeIx, string name, int STIx) : base(typeIx)
4450 this.name = name;
4451 this.systemTypeIndex = STIx;
4454 internal string GetName() { return name; }
4456 internal int GetSystemTypeIx() { return systemTypeIndex; }
4458 internal sealed override void TypeSig(MemoryStream str)
4460 str.WriteByte(typeIndex);
4463 internal override MetaDataElement GetTypeSpec(MetaData md)
4465 TypeSpec tS = md.GetPrimitiveTypeSpec(systemTypeIndex);
4466 if (tS == null) {
4467 tS = new TypeSpec(this,md);
4468 md.SetPrimitiveTypeSpec(systemTypeIndex,tS);
4469 md.AddToTable(MDTable.TypeSpec,tS);
4471 return tS;
4476 /**************************************************************************/
4477 /// <summary>
4478 /// Descriptor for an pointer (type * or type &)
4479 /// </summary>
4480 public abstract class PtrType : Type {
4482 Type baseType;
4484 internal PtrType(Type bType, byte typeIx) : base(typeIx)
4486 baseType = bType;
4487 tabIx = MDTable.TypeSpec;
4490 internal sealed override void TypeSig(MemoryStream str)
4492 str.WriteByte(typeIndex);
4493 baseType.TypeSig(str);
4497 /**************************************************************************/
4498 /// <summary>
4499 /// Descriptor for a managed pointer (type & or byref)
4500 /// </summary>
4502 public class ManagedPointer : PtrType {
4504 /// <summary>
4505 /// Create new managed pointer to baseType
4506 /// </summary>
4507 /// <param name="bType">the base type of the pointer</param>
4508 public ManagedPointer(Type baseType) : base(baseType,0x10) { }
4511 /**************************************************************************/
4512 /// <summary>
4513 /// Descriptor for an unmanaged pointer (type *)
4514 /// </summary>
4515 public class UnmanagedPointer : PtrType {
4517 /// <summary>
4518 /// Create a new unmanaged pointer to baseType
4519 /// </summary>
4520 /// <param name="baseType">the base type of the pointer</param>
4521 public UnmanagedPointer(Type baseType) : base(baseType, 0x0F) { }
4525 /**************************************************************************/
4527 public interface IExternRef {
4528 ClassRef AddClass(string nsName, string name);
4529 ClassRef AddValueClass(string nsName, string name);
4532 /// <summary>
4533 /// A reference to an external assembly (.assembly extern)
4534 /// </summary>
4535 public class AssemblyRef : ResolutionScope, IExternRef {
4537 private ushort major, minor, build, revision;
4538 uint flags, keyIx, hashIx, cultIx;
4539 bool hasVersion = false, isKeyToken = false;
4540 byte[] keyBytes;
4541 string culture;
4543 internal AssemblyRef(MetaData md, string name) : base(name,md)
4545 tabIx = MDTable.AssemblyRef;
4548 public void AddAssemblyAttr (AssemAttr aa)
4550 flags |= (uint)aa;
4553 /// <summary>
4554 /// Add version information about this external assembly
4555 /// </summary>
4556 /// <param name="majVer">Major Version</param>
4557 /// <param name="minVer">Minor Version</param>
4558 /// <param name="bldNo">Build Number</param>
4559 /// <param name="revNo">Revision Number</param>
4560 public void AddVersionInfo(int majVer, int minVer, int bldNo, int revNo)
4562 major = (ushort)majVer;
4563 minor = (ushort)minVer;
4564 build = (ushort)bldNo;
4565 revision = (ushort)revNo;
4566 hasVersion = true;
4569 /// <summary>
4570 /// Add the hash value for this external assembly
4571 /// </summary>
4572 /// <param name="hash">bytes of the hash value</param>
4573 public void AddHash(byte[] hash)
4575 hashIx = metaData.AddToBlobHeap(hash);
4578 /// <summary>
4579 /// Set the culture for this external assembly
4580 /// </summary>
4581 /// <param name="cult">the culture string</param>
4582 public void AddCulture(string cult)
4584 cultIx = metaData.AddToStringsHeap(cult);
4585 culture = cult;
4588 /// <summary>
4589 /// Add the full public key for this external assembly
4590 /// </summary>
4591 /// <param name="key">bytes of the public key</param>
4592 public void AddKey(byte[] key)
4594 flags |= 0x0001; // full public key
4595 keyBytes = key;
4596 keyIx = metaData.AddToBlobHeap(key);
4599 /// <summary>
4600 /// Add the public key token (low 8 bytes of the public key)
4601 /// </summary>
4602 /// <param name="key">low 8 bytes of public key</param>
4603 public void AddKeyToken(byte[] key)
4605 keyIx = metaData.AddToBlobHeap(key);
4606 keyBytes = key;
4607 isKeyToken = true;
4610 /// <summary>
4611 /// Add a class to this external assembly
4612 /// </summary>
4613 /// <param name="nsName">name space name</param>
4614 /// <param name="name">class name</param>
4615 /// <returns></returns>
4616 public virtual ClassRef AddClass(string nsName, string name)
4618 ClassRef aClass = new ClassRef(nsName,name,metaData);
4619 metaData.AddToTable(MDTable.TypeRef,aClass);
4620 aClass.SetParent(this);
4621 return aClass;
4624 /// <summary>
4625 /// Add a value class to this external assembly
4626 /// </summary>
4627 /// <param name="nsName">name space name</param>
4628 /// <param name="name">class name</param>
4629 /// <returns></returns>
4630 public virtual ClassRef AddValueClass(string nsName, string name)
4632 ClassRef aClass = new ClassRef(nsName,name,metaData);
4633 metaData.AddToTable(MDTable.TypeRef,aClass);
4634 aClass.SetParent(this);
4635 aClass.MakeValueClass(ValueClass.ValueType);
4636 return aClass;
4639 internal string TypeName()
4641 string result = name;
4642 if (hasVersion)
4643 result = result + ", Version=" + major + "." + minor + "." +
4644 build + "." + revision;
4645 if (keyBytes != null) {
4646 string tokenStr = "=";
4647 if (isKeyToken) tokenStr = "Token=";
4648 result = result + ", PublicKey" + tokenStr;
4649 for (int i=0; i < keyBytes.Length; i++) {
4650 result = result + Hex.Byte(keyBytes[i]);
4653 if (culture != null)
4654 result = result + ", Culture=" + culture;
4655 return result;
4658 internal sealed override uint Size(MetaData md)
4660 return 12 + 2 * md.StringsIndexSize() + 2 * md.BlobIndexSize();
4663 internal sealed override void Write(FileImage output)
4665 output.Write(major);
4666 output.Write(minor);
4667 output.Write(build);
4668 output.Write(revision);
4669 output.Write(flags);
4670 output.BlobIndex(keyIx);
4671 output.StringsIndex(nameIx);
4672 output.StringsIndex(cultIx);
4673 output.BlobIndex(hashIx);
4676 internal sealed override uint GetCodedIx(CIx code)
4678 switch (code) {
4679 case (CIx.ResolutionScope) : return 2;
4680 case (CIx.HasCustomAttr) : return 15;
4681 case (CIx.Implementation) : return 1;
4683 return 0;
4688 /**************************************************************************/
4689 /// <summary>
4690 /// Descriptor for a class defined in System (mscorlib)
4691 /// </summary>
4692 internal class SystemClass : ClassRef {
4694 PrimitiveType elemType;
4696 internal SystemClass(PrimitiveType eType, AssemblyRef paren, MetaData md)
4697 : base("System",eType.GetName(),md) {
4698 elemType = eType;
4699 parent = paren;
4702 internal override sealed MetaDataElement GetTypeSpec(MetaData md)
4704 if (typeSpec == null) typeSpec = (TypeSpec)elemType.GetTypeSpec(md);
4705 return typeSpec;
4709 internal sealed override void TypeSig(MemoryStream str)
4711 str.WriteByte(elemType.GetTypeIndex());
4716 /**************************************************************************/
4717 /// <summary>
4718 /// The assembly for mscorlib.
4719 /// </summary>
4720 public sealed class MSCorLib : AssemblyRef {
4722 private static readonly int valueTypeIx = 18;
4723 private readonly string systemName = "System";
4724 private Class[] systemClasses = new Class[valueTypeIx+2];
4725 private PrimitiveType[] systemTypes = new PrimitiveType[valueTypeIx];
4726 private TypeSpec[] specialTypeSpecs = new TypeSpec[valueTypeIx];
4727 private static int[] specialNames = {
4728 PrimitiveType.Void.GetName().GetHashCode(),
4729 PrimitiveType.Boolean.GetName().GetHashCode(),
4730 PrimitiveType.Char.GetName().GetHashCode(),
4731 PrimitiveType.Int8.GetName().GetHashCode(),
4732 PrimitiveType.UInt8.GetName().GetHashCode(),
4733 PrimitiveType.Int16.GetName().GetHashCode(),
4734 PrimitiveType.UInt16.GetName().GetHashCode(),
4735 PrimitiveType.Int32.GetName().GetHashCode(),
4736 PrimitiveType.UInt32.GetName().GetHashCode(),
4737 PrimitiveType.Int64.GetName().GetHashCode(),
4738 PrimitiveType.UInt64.GetName().GetHashCode(),
4739 PrimitiveType.Float32.GetName().GetHashCode(),
4740 PrimitiveType.Float64.GetName().GetHashCode(),
4741 PrimitiveType.String.GetName().GetHashCode(),
4742 PrimitiveType.TypedRef.GetName().GetHashCode(),
4743 PrimitiveType.IntPtr.GetName().GetHashCode(),
4744 PrimitiveType.UIntPtr.GetName().GetHashCode(),
4745 PrimitiveType.Object.GetName().GetHashCode(),
4746 PrimitiveType.ValueType.GetName ().GetHashCode(),
4747 "Enum".GetHashCode()
4750 internal MSCorLib(MetaData md) : base(md,"mscorlib")
4752 if (!PEFile.IsMSCorlib)
4753 md.AddToTable(MDTable.AssemblyRef,this);
4754 systemTypes[PrimitiveType.Void.GetSystemTypeIx()] = PrimitiveType.Void;
4755 systemTypes[PrimitiveType.Boolean.GetSystemTypeIx()] = PrimitiveType.Boolean;
4756 systemTypes[PrimitiveType.Char.GetSystemTypeIx()] = PrimitiveType.Char;
4757 systemTypes[PrimitiveType.Int8.GetSystemTypeIx()] = PrimitiveType.Int8;
4758 systemTypes[PrimitiveType.UInt8.GetSystemTypeIx()] = PrimitiveType.UInt8;
4759 systemTypes[PrimitiveType.Int16.GetSystemTypeIx()] = PrimitiveType.Int16;
4760 systemTypes[PrimitiveType.UInt16.GetSystemTypeIx()] = PrimitiveType.UInt16;
4761 systemTypes[PrimitiveType.Int32.GetSystemTypeIx()] = PrimitiveType.Int32;
4762 systemTypes[PrimitiveType.UInt32.GetSystemTypeIx()] = PrimitiveType.UInt32;
4763 systemTypes[PrimitiveType.Int64.GetSystemTypeIx()] = PrimitiveType.Int64;
4764 systemTypes[PrimitiveType.UInt64.GetSystemTypeIx()] = PrimitiveType.UInt64;
4765 systemTypes[PrimitiveType.Float32.GetSystemTypeIx()] = PrimitiveType.Float32;
4766 systemTypes[PrimitiveType.Float64.GetSystemTypeIx()] = PrimitiveType.Float64;
4767 systemTypes[PrimitiveType.IntPtr.GetSystemTypeIx()] = PrimitiveType.IntPtr;
4768 systemTypes[PrimitiveType.UIntPtr.GetSystemTypeIx()] = PrimitiveType.UIntPtr;
4769 systemTypes[PrimitiveType.String.GetSystemTypeIx()] = PrimitiveType.String;
4770 systemTypes[PrimitiveType.Object.GetSystemTypeIx()] = PrimitiveType.Object;
4771 systemTypes[PrimitiveType.TypedRef.GetSystemTypeIx()] = PrimitiveType.TypedRef;
4774 /// <summary>
4775 /// Add a class to the mscorlib assembly
4776 /// </summary>
4777 /// <param name="nsName">name space name</param>
4778 /// <param name="name">class name</param>
4779 /// <returns></returns>
4780 public override ClassRef AddClass(string nsName, string name)
4782 /* This gets called by !mscorlib, for adding references INTO mscorlib, so
4783 it should be returning ClassRef ..*/
4784 Class aClass = GetSpecialClass(nsName,name);
4785 if (aClass == null) {
4786 aClass = new ClassRef(nsName,name,metaData);
4787 metaData.AddToTable(MDTable.TypeRef,aClass);
4788 if (aClass is ClassRef)
4789 ((ClassRef) aClass).SetParent(this);
4791 //FIXME: Check for !ClassRef here?
4792 return (ClassRef) aClass;
4795 private Class GetSpecialClass(string nsName,string name)
4797 if (nsName.CompareTo(systemName) != 0) return null;
4798 int hash = name.GetHashCode();
4799 for (int i=0; i < specialNames.Length; i++) {
4800 if (hash != specialNames[i])
4801 continue;
4802 if (systemClasses[i] == null) {
4803 if (i < valueTypeIx) {
4804 systemClasses[i] = new SystemClass(systemTypes[i],this,metaData);
4805 if ((systemTypes[i] != PrimitiveType.Object) &&
4806 (systemTypes[i] != PrimitiveType.String)) {
4807 systemClasses[i].MakeValueClass(ValueClass.ValueType);
4809 } else {
4810 systemClasses[i] = new ClassRef(nsName,name,metaData);
4811 ((ClassRef) systemClasses[i]).SetParent(this);
4812 if (!ClassDef.IsValueType (nsName, name) && !ClassDef.IsEnum (nsName, name))
4813 systemClasses[i].MakeValueClass(ValueClass.ValueType);
4815 metaData.AddToTable(MDTable.TypeRef,systemClasses[i]);
4817 return systemClasses[i];
4819 return null;
4822 internal void SetSpecialSystemClass (string nsName, string name, Class aClass)
4824 if (nsName != systemName) return;
4825 int hash = name.GetHashCode ();
4826 for (int i = 0; i < specialNames.Length; i++) {
4827 if (hash != specialNames [i])
4828 continue;
4829 if (systemClasses [i] == null) {
4830 systemClasses [i] = aClass;
4835 internal Class GetSpecialSystemClass(PrimitiveType pType)
4837 int ix = pType.GetSystemTypeIx();
4838 if (systemClasses[ix] == null && !PEFile.IsMSCorlib) {
4839 systemClasses[ix] = new SystemClass(pType,this,metaData);
4840 metaData.AddToTable(MDTable.TypeRef,systemClasses[ix]);
4842 return systemClasses[ix];
4845 private ClassRef GetValueClass(string name, int hash)
4847 /* Called by MSCorLib.AddValueClass, which is called by
4848 !mscorlib, for adding ref to value class INTO mscorlib,
4849 so this should be classref */
4850 int ix = valueTypeIx;
4851 if (hash != specialNames[valueTypeIx]) ix++;
4852 if (systemClasses[ix] == null) {
4853 systemClasses[ix] = new ClassRef(systemName,name,metaData);
4854 ((ClassRef) systemClasses[ix]).SetParent(this);
4855 ((ClassRef) systemClasses[ix]).MakeValueClass(ValueClass.ValueType);
4856 metaData.AddToTable(MDTable.TypeRef,systemClasses[ix]);
4858 return (ClassRef) systemClasses[ix];
4861 internal Class ValueType()
4863 if (systemClasses[valueTypeIx] == null && !PEFile.IsMSCorlib) {
4864 ClassRef valType = new ClassRef("System","ValueType",metaData);
4865 valType.SetParent(this);
4866 valType.MakeValueClass(ValueClass.ValueType);
4867 metaData.AddToTable(MDTable.TypeRef,valType);
4868 systemClasses[valueTypeIx] = valType;
4870 return systemClasses[valueTypeIx];
4873 internal Class EnumType()
4875 /* Called by both mscorlib & !mscorlib, so can be
4876 either ClassRef or ClassDef */
4877 //systemClasses [ valueTypeIx + 1] -> System.Enum
4878 if (systemClasses[valueTypeIx + 1] == null && !PEFile.IsMSCorlib) {
4879 ClassRef valType = new ClassRef("System","Enum",metaData);
4880 valType.SetParent(this);
4881 valType.MakeValueClass(ValueClass.Enum);
4882 metaData.AddToTable(MDTable.TypeRef,valType);
4883 systemClasses[valueTypeIx + 1] = valType;
4885 return systemClasses[valueTypeIx + 1];
4888 /// <summary>
4889 /// Add a value class to this external assembly
4890 /// </summary>
4891 /// <param name="nsName">name space name</param>
4892 /// <param name="name">class name</param>
4893 /// <returns></returns>
4894 public override ClassRef AddValueClass(string nsName, string name)
4896 if (nsName.CompareTo(systemName) == 0) {
4897 int hash = name.GetHashCode();
4898 if ((hash == specialNames[valueTypeIx]) ||
4899 (hash == specialNames[valueTypeIx+1])) {
4900 return GetValueClass(name,hash);
4903 ClassRef aClass = new ClassRef(nsName,name,metaData);
4904 metaData.AddToTable(MDTable.TypeRef,aClass);
4905 aClass.SetParent(this);
4906 aClass.MakeValueClass(ValueClass.ValueType);
4907 return aClass;
4912 /**************************************************************************/
4913 /// <summary>
4914 /// MetaData
4915 /// Root (20 bytes + UTF-8 Version String + quad align padding)
4916 /// StreamHeaders (8 bytes + null terminated name string + quad align padding)
4917 /// Streams
4918 /// #~ (always present - holds metadata tables)
4919 /// #Strings (always present - holds identifier strings)
4920 /// #US (Userstring heap)
4921 /// #Blob (signature blobs)
4922 /// #GUID (guids for assemblies or Modules)
4923 /// </summary>
4924 public class MetaData {
4926 internal static readonly int[] CIxShiftMap = {2,2,5,1,2,3,1,1,1,2,3,2,1};
4927 private static readonly byte StringsHeapMask = 0x1;
4928 private static readonly byte GUIDHeapMask = 0x2;
4929 private static readonly byte BlobHeapMask = 0x4;
4930 private static readonly uint MetaDataSignature = 0x424A5342;
4931 private static readonly uint maxSmlIxSize = 0xFFFF;
4932 private static readonly uint max1BitSmlIx = 0x7FFF;
4933 private static readonly uint max2BitSmlIx = 0x3FFF;
4934 private static readonly uint max3BitSmlIx = 0x1FFF;
4935 private static readonly uint max5BitSmlIx = 0x7FF;
4936 // NOTE: version and stream name strings MUST always be quad padded
4937 #if NET_2_0 || BOOTSTRAP_NET_2_0
4938 private static readonly string version = "v2.0.50727\0\0";
4939 #else
4940 private static readonly string version = "v1.1.4322\0\0\0";
4941 #endif
4942 private static readonly char[] tildeName = {'#','~','\0','\0'};
4943 private static readonly char[] stringsName = {'#','S','t','r','i','n','g','s','\0','\0','\0','\0'};
4944 private static readonly char[] usName = {'#','U','S','\0'};
4945 private static readonly char[] guidName = {'#','G','U','I','D','\0','\0','\0'};
4946 private static readonly char[] blobName = {'#','B','l','o','b','\0','\0','\0'};
4947 private static readonly uint MetaDataHeaderSize = 20 + (uint)version.Length;
4948 private static readonly uint TildeHeaderSize = 24;
4949 private static readonly uint StreamHeaderSize = 8;
4950 private static readonly uint numMetaDataTables = (int)MDTable.GenericParamConstraint + 1;
4951 private static readonly uint tildeHeaderSize = 8 + (uint)tildeName.Length;
4953 MetaDataStream strings, us, guid, blob;
4955 MetaDataStream[] streams = new MetaDataStream[5];
4956 uint numStreams = 5;
4957 uint tildeTide = 0, tildePadding = 0, tildeStart = 0;
4958 uint numTables = 0, resourcesSize = 0;
4959 ArrayList[] metaDataTables = new ArrayList[numMetaDataTables];
4960 ArrayList byteCodes = new ArrayList();
4961 uint codeSize = 0, codeStart, byteCodePadding = 0, metaDataSize = 0;
4962 ulong valid = 0, /*sorted = 0x000002003301FA00;*/ sorted = 0;
4963 bool[] largeIx = new bool[numMetaDataTables];
4964 bool[] lgeCIx = new bool[(int)CIx.MaxCIx];
4965 bool largeStrings = false, largeUS = false, largeGUID = false, largeBlob = false;
4966 private FileImage file;
4967 private byte heapSizes = 0;
4968 MetaDataElement entryPoint;
4969 BinaryWriter output;
4970 public MSCorLib mscorlib;
4971 private TypeSpec[] systemTypeSpecs = new TypeSpec[PrimitiveType.NumSystemTypes];
4972 long mdStart;
4973 private ArrayList cattr_list;
4974 private ArrayList declsec_list;
4975 ArrayList resources;
4977 internal MetaData(FileImage file)
4979 // tilde = new MetaDataStream(tildeName,false,0);
4980 this.file = file;
4981 strings = new MetaDataStream(stringsName,new UTF8Encoding(),true);
4982 us = new MetaDataStream(usName,new UnicodeEncoding(),true);
4983 guid = new MetaDataStream(guidName,false);
4984 blob = new MetaDataStream(blobName,true);
4985 streams[1] = strings;
4986 streams[2] = us;
4987 streams[3] = guid;
4988 streams[4] = blob;
4989 for (int i=0; i < numMetaDataTables; i++) {
4990 largeIx[i] = false;
4992 for (int i=0; i < lgeCIx.Length; i++) {
4993 lgeCIx[i] = false;
4995 mscorlib = new MSCorLib(this);
4998 internal TypeSpec GetPrimitiveTypeSpec(int ix)
5000 return systemTypeSpecs[ix];
5003 internal void SetPrimitiveTypeSpec(int ix, TypeSpec typeSpec)
5005 systemTypeSpecs[ix] = typeSpec;
5008 internal uint Size()
5010 return metaDataSize;
5013 private void CalcHeapSizes ()
5015 if (strings.LargeIx()) {
5016 largeStrings = true;
5017 heapSizes |= StringsHeapMask;
5019 if (guid.LargeIx()) {
5020 largeGUID = true;
5021 heapSizes |= GUIDHeapMask;
5023 if (blob.LargeIx()) {
5024 largeBlob = true;
5025 heapSizes |= BlobHeapMask;
5028 largeUS = us.LargeIx();
5031 internal void StreamSize(byte mask)
5033 heapSizes |= mask;
5036 internal uint AddToUSHeap(string str)
5038 if (str == null) return 0;
5039 return us.Add(str,true);
5042 internal uint AddToUSHeap(byte[] str)
5044 if (str == null) return 0;
5045 return us.Add (str, true);
5048 internal uint AddToStringsHeap(string str)
5050 if ((str == null) || (str.CompareTo("") == 0)) return 0;
5051 return strings.Add(str,false);
5054 internal uint AddToGUIDHeap(Guid guidNum)
5056 return guid.Add(guidNum, false);
5059 internal uint AddToBlobHeap(byte[] blobBytes)
5061 if (blobBytes == null) return 0;
5062 return blob.Add(blobBytes, true);
5065 internal uint AddToBlobHeap(byte val)
5067 return blob.Add(val, true);
5070 internal uint AddToBlobHeap(sbyte val)
5072 return blob.Add(val, true);
5075 internal uint AddToBlobHeap(ushort val)
5077 return blob.Add(val, true);
5080 internal uint AddToBlobHeap(short val)
5082 return blob.Add(val, true);
5085 internal uint AddToBlobHeap(uint val)
5087 return blob.Add(val, true);
5090 internal uint AddToBlobHeap(int val)
5092 return blob.Add(val, true);
5095 internal uint AddToBlobHeap(ulong val)
5097 return blob.Add(val, true);
5100 internal uint AddToBlobHeap(long val)
5102 return blob.Add(val, true);
5105 internal uint AddToBlobHeap(float val)
5107 return blob.Add(val, true);
5110 internal uint AddToBlobHeap(double val)
5112 return blob.Add(val, true);
5115 internal uint AddToBlobHeap(string val)
5117 return blob.Add(val,true);
5120 internal void AddCustomAttribute (CustomAttribute cattr)
5122 if (cattr_list == null)
5123 cattr_list = new ArrayList ();
5124 cattr_list.Add (cattr);
5127 internal void AddDeclSecurity (BaseDeclSecurity decl_sec)
5129 if (declsec_list == null)
5130 declsec_list = new ArrayList ();
5131 declsec_list.Add (decl_sec);
5134 private ArrayList GetTable(MDTable tableIx)
5136 int tabIx = (int)tableIx;
5137 if (metaDataTables[tabIx] == null) {
5138 metaDataTables[tabIx] = new ArrayList();
5139 valid |= ((ulong)0x1 << tabIx);
5140 // Console.WriteLine("after creating table " + tableIx + "(" + tabIx + ") valid = " + valid);
5141 numTables++;
5143 return metaDataTables[tabIx];
5146 internal void AddToTable(MDTable tableIx, MetaDataElement elem)
5148 if (elem.Row > 0) {
5149 // Console.Out.WriteLine("ERROR - element already in table " + tableIx);
5150 return;
5152 // updates Row field of the element
5153 // Console.WriteLine("Adding element to table " + (uint)tableIx);
5154 ArrayList table = GetTable(tableIx);
5155 elem.Row = (uint)table.Count + 1;
5156 table.Add(elem);
5159 internal uint TableIndex(MDTable tableIx)
5161 if (metaDataTables[(int)tableIx] == null) return 1;
5162 return (uint)metaDataTables[(int)tableIx].Count+1;
5165 internal uint AddCode(CILInstructions byteCode)
5167 byteCodes.Add(byteCode);
5168 uint offset = codeSize + codeStart;
5169 codeSize += byteCode.GetCodeSize();
5170 return offset;
5173 internal void SetEntryPoint(MetaDataElement ep)
5175 entryPoint = ep;
5178 internal uint AddResource(byte[] resBytes)
5180 if (resources == null) resources = new ArrayList ();
5181 resources.Add (resBytes);
5182 uint offset = resourcesSize;
5183 resourcesSize += (uint)resBytes.Length + 4;
5184 return offset;
5187 internal void AddData(DataConstant cVal)
5189 file.AddInitData(cVal);
5192 internal static void CompressNum(uint val, MemoryStream sig)
5194 if (val <= 0x7F) {
5195 sig.WriteByte((byte)val);
5196 } else if (val <= 0x3FFF) {
5197 byte b1 = (byte)((val >> 8) | 0x80);
5198 byte b2 = (byte)(val & FileImage.iByteMask[0]);
5199 sig.WriteByte(b1);
5200 sig.WriteByte(b2);
5201 } else {
5202 byte b1 = (byte)((val >> 24) | 0xC0);
5203 byte b2 = (byte)((val & FileImage.iByteMask[2]) >> 16);
5204 byte b3 = (byte)((val & FileImage.iByteMask[1]) >> 8);;
5205 byte b4 = (byte)(val & FileImage.iByteMask[0]);
5206 sig.WriteByte(b1);
5207 sig.WriteByte(b2);
5208 sig.WriteByte(b3);
5209 sig.WriteByte(b4);
5213 internal uint CodeSize()
5215 return codeSize + byteCodePadding;
5218 internal uint GetResourcesSize()
5220 return resourcesSize;
5223 internal uint StringsIndexSize()
5225 if (largeStrings) return 4;
5226 return 2;
5229 internal uint GUIDIndexSize()
5231 if (largeGUID) return 4;
5232 return 2;
5235 internal uint USIndexSize()
5237 if (largeUS) return 4;
5238 return 2;
5241 internal uint BlobIndexSize()
5243 if (largeBlob) return 4;
5244 return 2;
5247 internal uint CodedIndexSize(CIx code)
5249 if (lgeCIx[(uint)code]) return 4;
5250 return 2;
5253 internal uint TableIndexSize(MDTable tabIx)
5255 if (largeIx[(uint)tabIx]) return 4;
5256 return 2;
5259 private void SetIndexSizes()
5261 for (int i=0; i < numMetaDataTables; i++) {
5262 if (metaDataTables[i] == null)
5263 continue;
5265 uint count = (uint)metaDataTables[i].Count;
5266 if (count > maxSmlIxSize)
5267 largeIx[i] = true;
5269 MDTable tabIx = (MDTable)i;
5270 if (count > max5BitSmlIx) {
5271 lgeCIx[(int)CIx.HasCustomAttr] = true;
5273 if (count > max3BitSmlIx) {
5274 if ((tabIx == MDTable.TypeRef) || (tabIx == MDTable.ModuleRef) || (tabIx == MDTable.Method) || (tabIx == MDTable.TypeSpec) || (tabIx == MDTable.Field))
5275 lgeCIx[(int)CIx.CustomAttributeType] = true;
5276 if ((tabIx == MDTable.Method) || (tabIx == MDTable.MemberRef))
5277 lgeCIx[(int)CIx.MemberRefParent] = true;
5279 if (count > max2BitSmlIx) {
5280 if ((tabIx == MDTable.Field) || (tabIx == MDTable.Param) || (tabIx == MDTable.Property))
5281 lgeCIx[(int)CIx.HasConst] = true;
5282 if ((tabIx == MDTable.TypeDef) || (tabIx == MDTable.TypeRef) || (tabIx == MDTable.TypeSpec))
5283 lgeCIx[(int)CIx.TypeDefOrRef] = true;
5284 if ((tabIx == MDTable.TypeDef) || (tabIx == MDTable.Method) || (tabIx == MDTable.Assembly))
5285 lgeCIx[(int)CIx.HasDeclSecurity] = true;
5286 if ((tabIx == MDTable.File) || (tabIx == MDTable.AssemblyRef) || (tabIx == MDTable.ExportedType))
5287 lgeCIx[(int)CIx.Implementation] = true;
5288 if ((tabIx == MDTable.Module) || (tabIx == MDTable.ModuleRef) || (tabIx == MDTable.AssemblyRef) || (tabIx == MDTable.TypeRef))
5289 lgeCIx[(int)CIx.ResolutionScope] = true;
5291 if (count > max1BitSmlIx) {
5292 if ((tabIx == MDTable.Field) || (tabIx == MDTable.Param))
5293 lgeCIx[(int)CIx.HasFieldMarshal] = true;
5294 if ((tabIx == MDTable.Event) || (tabIx == MDTable.Property))
5295 lgeCIx[(int)CIx.HasSemantics] = true;
5296 if ((tabIx == MDTable.Method) || (tabIx == MDTable.MemberRef))
5297 lgeCIx[(int)CIx.MethodDefOrRef] = true;
5298 if ((tabIx == MDTable.Field) || (tabIx == MDTable.Method))
5299 lgeCIx[(int)CIx.MemberForwarded] = true;
5300 if ((tabIx == MDTable.TypeDef) || (tabIx == MDTable.Method))
5301 lgeCIx[(int)CIx.TypeOrMethodDef] = true;
5306 private void SetStreamOffsets()
5308 uint sizeOfHeaders = StreamHeaderSize + (uint)tildeName.Length;
5309 for (int i=1; i < numStreams; i++) {
5310 sizeOfHeaders += streams[i].headerSize();
5312 metaDataSize = MetaDataHeaderSize + sizeOfHeaders;
5313 tildeStart = metaDataSize;
5314 metaDataSize += tildeTide + tildePadding;
5315 for (int i=1; i < numStreams; i++) {
5316 streams[i].Start = metaDataSize;
5317 metaDataSize += streams[i].Size();
5318 streams[i].WriteDetails();
5322 internal void CalcTildeStreamSize()
5324 CalcHeapSizes ();
5325 //tilde.SetIndexSizes(strings.LargeIx(),us.LargeIx(),guid.LargeIx(),blob.LargeIx());
5326 tildeTide = TildeHeaderSize;
5327 tildeTide += 4 * numTables;
5328 //Console.WriteLine("Tilde header + sizes = " + tildeTide);
5329 for (int i=0; i < numMetaDataTables; i++) {
5330 if (metaDataTables[i] != null) {
5331 ArrayList table = metaDataTables[i];
5332 // Console.WriteLine("Meta data table " + i + " at offset " + tildeTide);
5333 tildeTide += (uint)table.Count * ((MetaDataElement)table[0]).Size(this);
5334 // Console.WriteLine("Metadata table " + i + " has size " + table.Count);
5335 // Console.WriteLine("tildeTide = " + tildeTide);
5338 if ((tildeTide % 4) != 0) tildePadding = 4 - (tildeTide % 4);
5339 //Console.WriteLine("tildePadding = " + tildePadding);
5342 internal void WriteTildeStream(FileImage output)
5344 long startTilde = output.Seek(0,SeekOrigin.Current);
5345 output.Write((uint)0); // Reserved
5346 #if NET_2_0 || BOOTSTRAP_NET_2_0
5347 output.Write((byte)2); // MajorVersion
5348 output.Write((byte)0); // MinorVersion
5349 #else
5350 output.Write((byte)1); // MajorVersion
5351 output.Write((byte)0); // MinorVersion
5352 #endif
5353 output.Write(heapSizes);
5354 output.Write((byte)1); // Reserved
5355 output.Write(valid);
5356 output.Write(sorted);
5357 for (int i=0; i < numMetaDataTables; i++) {
5358 if (metaDataTables[i] != null) {
5359 uint count = (uint)metaDataTables[i].Count;
5360 output.Write(count);
5363 long tabStart = output.Seek(0,SeekOrigin.Current);
5364 // Console.WriteLine("Starting metaData tables at " + tabStart);
5365 for (int i=0; i < numMetaDataTables; i++) {
5366 if (metaDataTables[i] != null) {
5367 // Console.WriteLine("Starting metaData table " + i + " at " + (output.Seek(0,SeekOrigin.Current) - startTilde));
5368 ArrayList table = metaDataTables[i];
5369 for (int j=0; j < table.Count; j++) {
5370 ((MetaDataElement)table[j]).Write(output);
5374 // Console.WriteLine("Writing padding at " + output.Seek(0,SeekOrigin.Current));
5375 for (int i=0; i < tildePadding; i++) output.Write((byte)0);
5378 private void BuildTable(ArrayList table)
5380 if (table == null) return;
5381 for (int j=0; j < table.Count; j++) {
5382 ((MetaDataElement)table[j]).BuildTables(this);
5386 private void SortTable (ArrayList mTable)
5388 if (mTable == null) return;
5389 mTable.Sort();
5390 for (int i=0; i < mTable.Count; i++) {
5391 ((MetaDataElement)mTable[i]).Row = (uint)i+1;
5395 internal void BuildMetaData(uint codeStartOffset)
5397 codeStart = codeStartOffset;
5398 BuildTable(metaDataTables[(int)MDTable.TypeDef]);
5399 BuildTable(metaDataTables[(int)MDTable.TypeSpec]);
5400 BuildTable(metaDataTables[(int)MDTable.MemberRef]);
5401 #if NET_2_0 || BOOTSTRAP_NET_2_0
5402 BuildTable(metaDataTables[(int)MDTable.GenericParam]);
5403 BuildTable(metaDataTables[(int)MDTable.MethodSpec]);
5404 BuildTable(metaDataTables[(int)MDTable.GenericParamConstraint]);
5405 #endif
5406 BuildTable(metaDataTables[(int)MDTable.ManifestResource]);
5408 if (cattr_list != null) {
5409 foreach (CustomAttribute cattr in cattr_list)
5410 cattr.BuildTables (this);
5413 if (declsec_list != null) {
5414 foreach (BaseDeclSecurity decl_sec in declsec_list)
5415 decl_sec.BuildTables (this);
5418 /* for (int i=0; i < metaDataTables.Length; i++) {
5419 ArrayList table = metaDataTables[i];
5420 if (table != null) {
5421 for (int j=0; j < table.Count; j++) {
5422 ((MetaDataElement)table[j]).BuildTables(this);
5428 SetIndexSizes();
5429 for (int i=1; i < numStreams; i++) {
5430 streams[i].EndStream();
5432 CalcTildeStreamSize();
5433 SetStreamOffsets();
5434 byteCodePadding = NumToAlign(codeSize,4);
5435 if (entryPoint != null) file.SetEntryPoint(entryPoint.Token());
5437 // Check ordering of specific tables
5438 // Constant, CustomAttribute, FieldMarshal, DeclSecurity, MethodSemantics
5439 // ImplMap, GenericParam
5440 // Need to load GenericParamConstraint AFTER GenericParam table in correct order
5441 // The tables:
5442 // InterfaceImpl, ClassLayout, FieldLayout, MethodImpl, FieldRVA, NestedClass
5443 // will _ALWAYS_ be in the correct order as embedded in BuildMDTables
5445 SortTable(metaDataTables[(int)MDTable.Constant]);
5446 SortTable(metaDataTables[(int)MDTable.FieldMarshal]);
5447 SortTable(metaDataTables[(int)MDTable.DeclSecurity]);
5448 SortTable(metaDataTables[(int)MDTable.MethodSemantics]);
5449 SortTable(metaDataTables[(int)MDTable.ImplMap]);
5450 #if NET_2_0 || BOOTSTRAP_NET_2_0
5451 if (metaDataTables[(int)MDTable.GenericParam] != null) {
5452 SortTable(metaDataTables[(int)MDTable.GenericParam]);
5453 // Now add GenericParamConstraints
5454 /*for (int i=0; i < metaDataTables[(int)MDTable.GenericParam].Count; i++) {
5455 ((GenericParameter)metaDataTables[(int)MDTable.GenericParam][i]).AddConstraints(this);
5458 SortTable(metaDataTables[(int)MDTable.GenericParamConstraint]);
5459 #endif
5460 SortTable(metaDataTables[(int)MDTable.InterfaceImpl]);
5461 SortTable(metaDataTables[(int)MDTable.CustomAttribute]);
5465 internal void WriteByteCodes(FileImage output)
5467 for (int i=0; i < byteCodes.Count; i++) {
5468 ((CILInstructions)byteCodes[i]).Write(output);
5470 for (int i=0; i < byteCodePadding; i++) {
5471 output.Write((byte)0);
5475 internal void WriteResources (FileImage output)
5477 if (resources == null) return;
5478 for (int i = 0; i < resources.Count; i ++) {
5479 byte [] resBytes = (byte []) resources [i];
5480 output.Write ((uint) resBytes.Length);
5481 output.Write (resBytes);
5485 internal void WriteMetaData(FileImage output)
5487 this.output = output;
5488 mdStart = output.Seek(0,SeekOrigin.Current);
5489 // Console.WriteLine("Writing metaData at " + Hex.Long(mdStart));
5490 output.Write(MetaDataSignature);
5491 output.Write((short)1); // Major Version
5492 output.Write((short)1); // Minor Version ECMA = 0, PEFiles = 1
5493 output.Write(0); // Reserved
5494 output.Write(version.Length);
5495 output.Write(version.ToCharArray()); // version string is already zero padded
5496 output.Write((short)0);
5497 output.Write((ushort)numStreams);
5498 // write tilde header
5499 output.Write(tildeStart);
5500 output.Write(tildeTide + tildePadding);
5501 output.Write(tildeName);
5502 for (int i=1; i < numStreams; i++) streams[i].WriteHeader(output);
5503 // Console.WriteLine("Writing tilde stream at " + output.Seek(0,SeekOrigin.Current) + " = " + tildeStart);
5504 WriteTildeStream(output);
5505 for (int i=1; i < numStreams; i++) streams[i].Write(output);
5506 // Console.WriteLine("Finished Writing metaData at " + output.Seek(0,SeekOrigin.Current));
5509 internal bool LargeStringsIndex() { return strings.LargeIx(); }
5510 internal bool LargeGUIDIndex() { return guid.LargeIx(); }
5511 internal bool LargeUSIndex() { return us.LargeIx(); }
5512 internal bool LargeBlobIndex() { return blob.LargeIx(); }
5514 internal bool LargeIx(MDTable tabIx) { return largeIx[(uint)tabIx]; }
5517 private uint NumToAlign(uint val, uint alignVal)
5519 if ((val % alignVal) == 0) return 0;
5520 return alignVal - (val % alignVal);
5523 internal void WriteCodedIndex(CIx code, MetaDataElement elem, FileImage output)
5525 uint ix = 0;
5526 if (elem != null) {
5527 ix = (elem.Row << CIxShiftMap[(uint)code]) | elem.GetCodedIx(code);
5528 // Console.WriteLine("coded index = " + ix + " row = " + elem.Row);
5529 //} else {
5530 // Console.WriteLine("elem for coded index is null");
5532 if (lgeCIx[(uint)code])
5533 output.Write(ix);
5534 else
5535 output.Write((ushort)ix);
5540 /**************************************************************************/
5541 /// <summary>
5542 /// Stream in the Meta Data (#Strings, #US, #Blob and #GUID)
5543 /// </summary>
5545 internal class MetaDataStream : BinaryWriter {
5547 private static readonly uint StreamHeaderSize = 8;
5548 private static uint maxSmlIxSize = 0xFFFF;
5550 private uint start = 0;
5551 uint size = 0, tide = 1;
5552 bool largeIx = false;
5553 uint sizeOfHeader;
5554 char[] name;
5555 Hashtable htable = new Hashtable();
5556 Hashtable btable = new Hashtable (new ByteArrayHashCodeProvider (), new ByteArrayComparer ());
5558 internal MetaDataStream(char[] name, bool addInitByte) : base(new MemoryStream())
5560 if (addInitByte) { Write((byte)0); size = 1; }
5561 this.name = name;
5562 sizeOfHeader = StreamHeaderSize + (uint)name.Length;
5565 internal MetaDataStream(char[] name, System.Text.Encoding enc, bool addInitByte) : base(new MemoryStream(),enc)
5567 if (addInitByte) { Write((byte)0); size = 1; }
5568 this.name = name;
5569 sizeOfHeader = StreamHeaderSize + (uint)name.Length;
5572 public uint Start {
5573 get { return start; }
5574 set { start = value; }
5577 internal uint headerSize()
5579 // Console.WriteLine(name + " stream has headersize of " + sizeOfHeader);
5580 return sizeOfHeader;
5583 internal void SetSize(uint siz)
5585 size = siz;
5588 internal uint Size()
5590 return size;
5593 internal bool LargeIx()
5595 return largeIx;
5598 internal void WriteDetails()
5600 // Console.WriteLine(name + " - size = " + size);
5603 internal uint Add(string str, bool prependSize)
5605 Object val = htable[str];
5606 uint index = 0;
5607 if (val == null) {
5608 index = size;
5609 htable[str] = index;
5610 char[] arr = str.ToCharArray();
5611 if (prependSize) CompressNum((uint)arr.Length*2+1);
5612 Write(arr);
5613 Write((byte)0);
5614 size = (uint)Seek(0,SeekOrigin.Current);
5615 } else {
5616 index = (uint)val;
5618 return index;
5620 internal uint Add (byte[] str, bool prependSize)
5622 Object val = btable [str];
5623 uint index = 0;
5624 if (val == null) {
5625 index = size;
5626 btable [str] = index;
5627 if (prependSize) CompressNum ((uint) str.Length);
5628 Write (str);
5629 size = (uint) Seek (0, SeekOrigin.Current);
5630 } else {
5631 index = (uint) val;
5633 return index;
5637 internal uint Add(Guid guid, bool prependSize)
5639 byte [] b = guid.ToByteArray ();
5640 if (prependSize) CompressNum ((uint) b.Length);
5641 Write(guid.ToByteArray());
5642 size =(uint)Seek(0,SeekOrigin.Current);
5643 return tide++;
5646 internal uint Add(byte[] blob)
5648 uint ix = size;
5649 CompressNum((uint)blob.Length);
5650 Write(blob);
5651 size = (uint)Seek(0,SeekOrigin.Current);
5652 return ix;
5655 internal uint Add(byte val, bool prependSize)
5657 uint ix = size;
5658 if (prependSize) CompressNum (1);
5659 Write(val);
5660 size = (uint)Seek(0,SeekOrigin.Current);
5661 return ix;
5664 internal uint Add(sbyte val, bool prependSize)
5666 uint ix = size;
5667 if (prependSize) CompressNum (1);
5668 Write(val);
5669 size = (uint)Seek(0,SeekOrigin.Current);
5670 return ix;
5673 internal uint Add(ushort val, bool prependSize)
5675 uint ix = size;
5676 if (prependSize) CompressNum (2);
5677 Write(val);
5678 size = (uint)Seek(0,SeekOrigin.Current);
5679 return ix;
5682 internal uint Add(short val, bool prependSize)
5684 uint ix = size;
5685 if (prependSize) CompressNum (2);
5686 Write(val);
5687 size = (uint)Seek(0,SeekOrigin.Current);
5688 return ix;
5691 internal uint Add(uint val, bool prependSize)
5693 uint ix = size;
5694 if (prependSize) CompressNum (4);
5695 Write(val);
5696 size = (uint)Seek(0,SeekOrigin.Current);
5697 return ix;
5700 internal uint Add(int val, bool prependSize)
5702 uint ix = size;
5703 if (prependSize) CompressNum (4);
5704 Write (val);
5705 size = (uint)Seek(0,SeekOrigin.Current);
5706 return ix;
5709 internal uint Add(ulong val, bool prependSize)
5711 uint ix = size;
5712 if (prependSize) CompressNum (8);
5713 Write(val);
5714 size = (uint)Seek(0,SeekOrigin.Current);
5715 return ix;
5718 internal uint Add(long val, bool prependSize)
5720 uint ix = size;
5721 if (prependSize) CompressNum (8);
5722 Write(val);
5723 size = (uint)Seek(0,SeekOrigin.Current);
5724 return ix;
5727 internal uint Add(float val, bool prependSize)
5729 uint ix = size;
5730 if (prependSize) CompressNum (4);
5731 Write(val);
5732 size = (uint)Seek(0,SeekOrigin.Current);
5733 return ix;
5736 internal uint Add(double val, bool prependSize)
5738 uint ix = size;
5739 if (prependSize) CompressNum (8);
5740 Write(val);
5741 size = (uint)Seek(0,SeekOrigin.Current);
5742 return ix;
5745 private void CompressNum(uint val)
5747 if (val < 0x7F) {
5748 Write((byte)val);
5749 } else if (val < 0x3FFF) {
5750 byte b1 = (byte)((val >> 8) | 0x80);
5751 byte b2 = (byte)(val & FileImage.iByteMask[0]);
5752 Write(b1);
5753 Write(b2);
5754 } else {
5755 byte b1 = (byte)((val >> 24) | 0xC0);
5756 byte b2 = (byte)((val & FileImage.iByteMask[2]) >> 16);
5757 byte b3 = (byte)((val & FileImage.iByteMask[1]) >> 8);;
5758 byte b4 = (byte)(val & FileImage.iByteMask[0]);
5759 Write(b1);
5760 Write(b2);
5761 Write(b3);
5762 Write(b4);
5766 private void QuadAlign()
5768 if ((size % 4) != 0) {
5769 uint pad = 4 - (size % 4);
5770 size += pad;
5771 for (int i=0; i < pad; i++) {
5772 Write((byte)0);
5777 internal void EndStream()
5779 QuadAlign();
5780 if (size > maxSmlIxSize) {
5781 largeIx = true;
5785 internal void WriteHeader(BinaryWriter output)
5787 output.Write(start);
5788 output.Write(size);
5789 output.Write(name);
5792 internal virtual void Write(BinaryWriter output)
5794 // Console.WriteLine("Writing " + name + " stream at " + output.Seek(0,SeekOrigin.Current) + " = " + start);
5795 MemoryStream str = (MemoryStream)BaseStream;
5796 output.Write(str.ToArray());
5801 /**************************************************************************/
5802 class ByteArrayComparer : IComparer {
5804 public int Compare (object x, object y)
5806 byte [] a = (byte []) x;
5807 byte [] b = (byte []) y;
5808 int len = a.Length;
5810 if (b.Length != len)
5811 return 1;
5813 for (int i = 0; i < len; ++i)
5814 if (a [i] != b [i])
5815 return 1;
5816 return 0;
5820 class ByteArrayHashCodeProvider : IHashCodeProvider {
5822 public int GetHashCode (Object key)
5824 byte [] arr = (byte []) key;
5825 int len = arr.Length;
5826 int h = 0;
5828 for (int i = 0; i < len; ++i)
5829 h = (h << 5) - h + arr [i];
5831 return h;